From 238b8f10a0799fa0d0d1d36de3cf1e8af57e25a0 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 21 Aug 2023 19:11:43 +0300 Subject: [PATCH 0001/1413] [#630] cli: Fix SDK SetEACLPrm usage for PrmContainerSetEACL Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/client.go | 6 +++--- cmd/frostfs-cli/modules/container/set_eacl.go | 12 ++++++------ go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index ae76780bd1..0c6d2a38d5 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -201,8 +201,8 @@ func EACL(ctx context.Context, prm EACLPrm) (res EACLRes, err error) { // SetEACLPrm groups parameters of SetEACL operation. type SetEACLPrm struct { - commonPrm - client.PrmContainerSetEACL + Client *client.Client + ClientParams client.PrmContainerSetEACL } // SetEACLRes groups the resulting values of SetEACL operation. @@ -217,7 +217,7 @@ type SetEACLRes struct{} // // Returns any error which prevented the operation from completing correctly in error return. func SetEACL(ctx context.Context, prm SetEACLPrm) (res SetEACLRes, err error) { - _, err = prm.cli.ContainerSetEACL(ctx, prm.PrmContainerSetEACL) + _, err = prm.Client.ContainerSetEACL(ctx, prm.ClientParams) return } diff --git a/cmd/frostfs-cli/modules/container/set_eacl.go b/cmd/frostfs-cli/modules/container/set_eacl.go index 51805d69dd..f2f60f5c32 100644 --- a/cmd/frostfs-cli/modules/container/set_eacl.go +++ b/cmd/frostfs-cli/modules/container/set_eacl.go @@ -49,12 +49,12 @@ Container ID in EACL table will be substituted with ID from the CLI.`, cmd.Println("ACL extension is enabled in the container, continue processing.") } - var setEACLPrm internalclient.SetEACLPrm - setEACLPrm.SetClient(cli) - setEACLPrm.SetTable(*eaclTable) - - if tok != nil { - setEACLPrm.WithinSession(*tok) + setEACLPrm := internalclient.SetEACLPrm{ + Client: cli, + ClientParams: client.PrmContainerSetEACL{ + Table: eaclTable, + Session: tok, + }, } _, err := internalclient.SetEACL(cmd.Context(), setEACLPrm) diff --git a/go.mod b/go.mod index a1d99fcc6d..46639d49cb 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230802075510-964c3edb3f44 git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230627134746-36f3d39c406a git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230816095347-6fdbe755179e + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230821090303-202412230a05 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index fd7be9463b..58f1fb2174 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230816095347-6fdbe755179e h1:+78sZdTFeK2t+2qJ4Tmm5CItUjfcF4/nFMum3JnZ6PQ= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230816095347-6fdbe755179e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230821090303-202412230a05 h1:OuViMF54N87FXmaBEpYw3jhzaLrJ/EWOlPL1wUkimE0= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230821090303-202412230a05/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= From 82cc453be9cdca1da43424b0b45676bd7fa3a3f5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 23 Aug 2023 10:43:16 +0300 Subject: [PATCH 0002/1413] [#xx] shard: Fix data race in metrics tests Protect test metric store fields with a mutex. Probably, not every field should be protected, but better safe than sorry. Signed-off-by: Evgenii Stratonikov --- .../shard/metrics_test.go | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index ad0fc15ca5..60adc07249 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -3,6 +3,7 @@ package shard_test import ( "context" "path/filepath" + "sync" "testing" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -19,6 +20,7 @@ import ( ) type metricsStore struct { + mtx sync.Mutex objCounters map[string]uint64 cnrSize map[string]int64 pldSize int64 @@ -49,35 +51,51 @@ func (m metricsStore) AddToObjectCounter(objectType string, delta int) { } } -func (m metricsStore) IncObjectCounter(objectType string) { +func (m *metricsStore) IncObjectCounter(objectType string) { + m.mtx.Lock() + defer m.mtx.Unlock() m.objCounters[objectType] += 1 } -func (m metricsStore) DecObjectCounter(objectType string) { +func (m *metricsStore) DecObjectCounter(objectType string) { + m.mtx.Lock() + defer m.mtx.Unlock() m.AddToObjectCounter(objectType, -1) } func (m *metricsStore) SetMode(mode mode.Mode) { + m.mtx.Lock() + defer m.mtx.Unlock() m.mode = mode } -func (m metricsStore) AddToContainerSize(cnr string, size int64) { +func (m *metricsStore) AddToContainerSize(cnr string, size int64) { + m.mtx.Lock() + defer m.mtx.Unlock() m.cnrSize[cnr] += size } func (m *metricsStore) AddToPayloadSize(size int64) { + m.mtx.Lock() + defer m.mtx.Unlock() m.pldSize += size } func (m *metricsStore) IncErrorCounter() { + m.mtx.Lock() + defer m.mtx.Unlock() m.errCounter += 1 } func (m *metricsStore) ClearErrorCounter() { + m.mtx.Lock() + defer m.mtx.Unlock() m.errCounter = 0 } func (m *metricsStore) DeleteShardMetrics() { + m.mtx.Lock() + defer m.mtx.Unlock() m.errCounter = 0 } From 02b03d9c4fdb05212f585d1974ec1c089102adb8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 23 Aug 2023 10:48:23 +0300 Subject: [PATCH 0003/1413] [#638] logger: Remove sampling from test loggers Losing logs is always a bad idea, especially when we debug tests. Signed-off-by: Evgenii Stratonikov --- pkg/util/logger/test/logger.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pkg/util/logger/test/logger.go b/pkg/util/logger/test/logger.go index e78a117fac..4a28708703 100644 --- a/pkg/util/logger/test/logger.go +++ b/pkg/util/logger/test/logger.go @@ -9,8 +9,6 @@ import ( "go.uber.org/zap/zapcore" ) -const sampling = 1000 - // NewLogger creates a new logger. // // If debug, development logger is created. @@ -20,11 +18,6 @@ func NewLogger(t testing.TB, debug bool) *logger.Logger { if debug { cfg := zap.NewDevelopmentConfig() - cfg.Sampling = &zap.SamplingConfig{ - Initial: sampling, - Thereafter: sampling, - } - cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder log, err := cfg.Build() From 322c1dc273a08319cc3e62bdabbb25f482e2849e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 23 Aug 2023 10:53:42 +0300 Subject: [PATCH 0004/1413] [#638] Use test.NewLogger() in tests Semantic patch (restricted to **/*_test.go): ``` @@ @@ +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" -import "go.uber.org/zap" -import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" -&logger.Logger{Logger: zap.L()} +test.NewLogger(t, false) ``` Signed-off-by: Evgenii Stratonikov --- .../blobstor/blobovniczatree/exists_test.go | 5 ++--- .../blobstor/blobovniczatree/generic_test.go | 7 +++---- .../blobstor/memstore/memstore_test.go | 5 ++--- pkg/local_object_storage/engine/control_test.go | 7 +++---- pkg/local_object_storage/engine/delete_test.go | 5 ++--- pkg/local_object_storage/engine/engine_test.go | 7 +++---- pkg/local_object_storage/engine/error_test.go | 5 ++--- pkg/local_object_storage/engine/evacuate_test.go | 5 ++--- pkg/local_object_storage/engine/list_test.go | 5 ++--- pkg/local_object_storage/shard/control_test.go | 5 ++--- pkg/local_object_storage/shard/gc_internal_test.go | 10 ++++------ pkg/local_object_storage/shard/range_test.go | 5 ++--- pkg/local_object_storage/shard/reload_test.go | 6 ++---- pkg/local_object_storage/shard/shard_test.go | 9 ++++----- .../writecache/writecachebadger/flush_test.go | 5 ++--- .../writecache/writecachebadger/generic_test.go | 5 ++--- .../writecache/writecachebbolt/flush_test.go | 5 ++--- .../writecache/writecachebbolt/generic_test.go | 5 ++--- pkg/services/tree/signature_test.go | 5 ++--- 19 files changed, 45 insertions(+), 66 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index f9448ae929..a1fdbc127d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -9,16 +9,15 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "github.com/nspcc-dev/neo-go/pkg/util/slice" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) func TestExistsInvalidStorageID(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), WithObjectSizeLimit(1024), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go index 5a713b9b95..764cbc26b7 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go @@ -5,8 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" ) func TestGeneric(t *testing.T) { @@ -14,7 +13,7 @@ func TestGeneric(t *testing.T) { helper := func(t *testing.T, dir string) common.Storage { return NewBlobovniczaTree( - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), @@ -41,7 +40,7 @@ func TestControl(t *testing.T) { newTree := func(t *testing.T) common.Storage { return NewBlobovniczaTree( - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/memstore/memstore_test.go b/pkg/local_object_storage/blobstor/memstore/memstore_test.go index 7979b1504a..a080f2bb9e 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore_test.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore_test.go @@ -7,16 +7,15 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) func TestSimpleLifecycle(t *testing.T) { s := New( WithRootPath("memstore"), - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), ) t.Cleanup(func() { _ = s.Close() }) require.NoError(t, s.Open(false)) diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 04591687d0..bbb52a2712 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -22,11 +22,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" - "go.uber.org/zap" ) // TestInitializationFailure checks that shard is initialized and closed even if media @@ -54,7 +53,7 @@ func TestInitializationFailure(t *testing.T) { return []shard.Option{ shard.WithID(sid), - shard.WithLogger(&logger.Logger{Logger: zap.L()}), + shard.WithLogger(test.NewLogger(t, false)), shard.WithBlobStorOptions( blobstor.WithStorages(storages)), shard.WithMetaBaseOptions( @@ -295,7 +294,7 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str te := testNewEngine(t). setShardsNumOpts(t, num, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(&logger.Logger{Logger: zap.L()}), + shard.WithLogger(test.NewLogger(t, false)), shard.WithBlobStorOptions( blobstor.WithStorages(newStorages(filepath.Join(addPath, strconv.Itoa(id)), errSmallSize))), shard.WithMetaBaseOptions( diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 802b6b0b56..08b1adab8a 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -6,14 +6,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) func TestDeleteBigObject(t *testing.T) { @@ -54,7 +53,7 @@ func TestDeleteBigObject(t *testing.T) { s3 := testNewShard(t, 3) e := testNewEngine(t).setInitializedShards(t, s1, s2, s3).engine - e.log = &logger.Logger{Logger: zap.L()} + e.log = test.NewLogger(t, false) defer e.Close() for i := range children { diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 39c5e2e1e7..ba7cdb5b39 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -15,14 +15,13 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "git.frostfs.info/TrueCloudLab/hrw" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) type epochState struct{} @@ -80,7 +79,7 @@ type testEngineWrapper struct { } func testNewEngine(t testing.TB, opts ...Option) *testEngineWrapper { - engine := New(WithLogger(&logger.Logger{Logger: zap.L()})) + engine := New(WithLogger(test.NewLogger(t, false))) for _, opt := range opts { opt(engine.cfg) } @@ -199,7 +198,7 @@ func testNewShard(t testing.TB, id int) *shard.Shard { func testDefaultShardOptions(t testing.TB, id int) []shard.Option { return []shard.Option{ - shard.WithLogger(&logger.Logger{Logger: zap.L()}), + shard.WithLogger(test.NewLogger(t, false)), shard.WithBlobStorOptions( blobstor.WithStorages( newStorages(t.TempDir(), 1<<20))), diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index bbed8cfb9c..2bc02cf962 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -17,11 +17,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) const errSmallSize = 256 @@ -56,7 +55,7 @@ func newEngineWithErrorThreshold(t testing.TB, dir string, errThreshold uint32) largeFileStorage: largeFileStorage, } return []shard.Option{ - shard.WithLogger(&logger.Logger{Logger: zap.L()}), + shard.WithLogger(test.NewLogger(t, false)), shard.WithBlobStorOptions(blobstor.WithStorages(storages)), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(dir, fmt.Sprintf("%d.metabase", id))), diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 63296ccd77..40f3bcf8c7 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -16,12 +16,11 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" - "go.uber.org/zap" "golang.org/x/sync/errgroup" ) @@ -31,7 +30,7 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng te := testNewEngine(t). setShardsNumOpts(t, shardNum, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(&logger.Logger{Logger: zap.L()}), + shard.WithLogger(test.NewLogger(t, false)), shard.WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{{ Storage: fstree.New( diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 9d5d12683f..0a9748f43a 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -12,11 +12,10 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { @@ -66,7 +65,7 @@ func TestListWithCursor(t *testing.T) { t.Parallel() e := testNewEngine(t).setShardsNumOpts(t, tt.shardNum, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(&logger.Logger{Logger: zap.L()}), + shard.WithLogger(test.NewLogger(t, false)), shard.WithBlobStorOptions( blobstor.WithStorages( newStorages(t.TempDir(), 1<<20))), diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 053d89a8a1..7ee9288750 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -19,7 +19,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -30,7 +30,6 @@ import ( objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" - "go.uber.org/zap" ) type epochState struct{} @@ -75,7 +74,7 @@ func TestShardOpen(t *testing.T) { newShard := func() *Shard { return New( WithID(NewIDFromBytes([]byte{})), - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{ {Storage: st}, diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 21f300e2c7..af2fffd635 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -15,14 +15,13 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { @@ -31,14 +30,13 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { rootPath := t.TempDir() var sh *Shard - - l := &logger.Logger{Logger: zap.L()} + l := test.NewLogger(t, false) blobOpts := []blobstor.Option{ - blobstor.WithLogger(&logger.Logger{Logger: zap.L()}), + blobstor.WithLogger(test.NewLogger(t, false)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(&logger.Logger{Logger: zap.L()}), + blobovniczatree.WithLogger(test.NewLogger(t, false)), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index e764a07634..243bda2014 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -14,12 +14,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/nspcc-dev/neo-go/pkg/util/slice" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) func TestShard_GetRange(t *testing.T) { @@ -82,7 +81,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { []blobstor.Option{blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(&logger.Logger{Logger: zap.L()}), + blobovniczatree.WithLogger(test.NewLogger(t, false)), blobovniczatree.WithRootPath(filepath.Join(t.TempDir(), "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index 75ce386bce..b98c360642 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -11,7 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -20,7 +20,6 @@ import ( usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) func TestShardReload(t *testing.T) { @@ -28,8 +27,7 @@ func TestShardReload(t *testing.T) { p := t.Name() defer os.RemoveAll(p) - - l := &logger.Logger{Logger: zap.L()} + l := test.NewLogger(t, false) blobOpts := []blobstor.Option{ blobstor.WithLogger(l), blobstor.WithStorages([]blobstor.SubStorage{ diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 4ec73191cc..ff8bfe313d 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -16,12 +16,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) type epochState struct { @@ -59,11 +58,11 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts if bsOpts == nil { bsOpts = []blobstor.Option{ - blobstor.WithLogger(&logger.Logger{Logger: zap.L()}), + blobstor.WithLogger(test.NewLogger(t, false)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(&logger.Logger{Logger: zap.L()}), + blobovniczatree.WithLogger(test.NewLogger(t, false)), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), @@ -81,7 +80,7 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts opts := []shard.Option{ shard.WithID(shard.NewIDFromBytes([]byte{})), - shard.WithLogger(&logger.Logger{Logger: zap.L()}), + shard.WithLogger(test.NewLogger(t, false)), shard.WithBlobStorOptions(bsOpts...), shard.WithMetaBaseOptions( append([]meta.Option{ diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go index 1bf50e0003..119c041077 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go @@ -10,18 +10,17 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachetest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/dgraph-io/badger/v4" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) func TestFlush(t *testing.T) { createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs writecache.MainStorage, opts ...Option) writecache.Cache { return New( append([]Option{ - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), WithPath(filepath.Join(t.TempDir(), "writecache")), WithMetabase(mb), WithBlobstor(bs), diff --git a/pkg/local_object_storage/writecache/writecachebadger/generic_test.go b/pkg/local_object_storage/writecache/writecachebadger/generic_test.go index 641da2293f..d21adf41fb 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/generic_test.go +++ b/pkg/local_object_storage/writecache/writecachebadger/generic_test.go @@ -5,14 +5,13 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/storagetest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" ) func TestGeneric(t *testing.T) { storagetest.TestAll(t, func(t *testing.T) storagetest.Component { return New( - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), WithFlushWorkersCount(2), WithPath(t.TempDir()), WithGCInterval(1*time.Second)) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go index e7ba66fae4..5c73891a73 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go @@ -13,18 +13,17 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachetest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" - "go.uber.org/zap" ) func TestFlush(t *testing.T) { createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs writecache.MainStorage, opts ...Option) writecache.Cache { return New( append([]Option{ - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), WithPath(filepath.Join(t.TempDir(), "writecache")), WithSmallObjectSize(smallSize), WithMetabase(mb), diff --git a/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go b/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go index b34d53f3e3..64d853a78d 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go @@ -4,14 +4,13 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/storagetest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" ) func TestGeneric(t *testing.T) { storagetest.TestAll(t, func(t *testing.T) storagetest.Component { return New( - WithLogger(&logger.Logger{Logger: zap.L()}), + WithLogger(test.NewLogger(t, false)), WithFlushWorkersCount(2), WithPath(t.TempDir())) }) diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 9d4776ba1a..2f044b9711 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -9,7 +9,7 @@ import ( aclV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" @@ -20,7 +20,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" - "go.uber.org/zap" ) type dummyNetmapSource struct { @@ -101,7 +100,7 @@ func TestMessageSign(t *testing.T) { s := &Service{ cfg: cfg{ - log: &logger.Logger{Logger: zap.L()}, + log: test.NewLogger(t, false), key: &privs[0].PrivateKey, nmSource: dummyNetmapSource{}, cnrSource: dummyContainerSource{ From 96e690883fa0b8604a15dde69e7352f969c91083 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 23 Aug 2023 10:55:36 +0300 Subject: [PATCH 0005/1413] [#638] Unify test loggers In some places we have debug=false, in others debug=true. Let's be consistent. Semantic patch: ``` @@ @@ -test.NewLogger(..., false) +test.NewLogger(..., true) ``` Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/blobovnicza/blobovnicza_test.go | 2 +- .../blobstor/blobovniczatree/exists_test.go | 2 +- .../blobstor/blobovniczatree/generic_test.go | 4 ++-- .../blobstor/memstore/memstore_test.go | 2 +- pkg/local_object_storage/engine/control_test.go | 4 ++-- pkg/local_object_storage/engine/delete_test.go | 2 +- pkg/local_object_storage/engine/engine_test.go | 4 ++-- pkg/local_object_storage/engine/error_test.go | 2 +- pkg/local_object_storage/engine/evacuate_test.go | 2 +- pkg/local_object_storage/engine/list_test.go | 2 +- pkg/local_object_storage/shard/control_test.go | 2 +- pkg/local_object_storage/shard/gc_internal_test.go | 6 +++--- pkg/local_object_storage/shard/range_test.go | 2 +- pkg/local_object_storage/shard/reload_test.go | 2 +- pkg/local_object_storage/shard/shard_test.go | 6 +++--- .../writecache/writecachebadger/flush_test.go | 2 +- .../writecache/writecachebadger/generic_test.go | 2 +- .../writecache/writecachebbolt/flush_test.go | 2 +- .../writecache/writecachebbolt/generic_test.go | 2 +- pkg/services/object/get/get_test.go | 6 +++--- pkg/services/object/search/search_test.go | 8 ++++---- pkg/services/tree/signature_test.go | 2 +- 22 files changed, 34 insertions(+), 34 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go index f8f6385648..48a189c9de 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go @@ -64,7 +64,7 @@ func TestBlobovnicza(t *testing.T) { WithPath(p), WithObjectSizeLimit(objSizeLim), WithFullSizeLimit(sizeLim), - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), ) defer os.Remove(p) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index a1fdbc127d..8cbdf613c7 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -17,7 +17,7 @@ import ( func TestExistsInvalidStorageID(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), WithObjectSizeLimit(1024), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go index 764cbc26b7..6eb8b81aef 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go @@ -13,7 +13,7 @@ func TestGeneric(t *testing.T) { helper := func(t *testing.T, dir string) common.Storage { return NewBlobovniczaTree( - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), @@ -40,7 +40,7 @@ func TestControl(t *testing.T) { newTree := func(t *testing.T) common.Storage { return NewBlobovniczaTree( - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/memstore/memstore_test.go b/pkg/local_object_storage/blobstor/memstore/memstore_test.go index a080f2bb9e..eaa2a4b617 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore_test.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore_test.go @@ -15,7 +15,7 @@ import ( func TestSimpleLifecycle(t *testing.T) { s := New( WithRootPath("memstore"), - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), ) t.Cleanup(func() { _ = s.Close() }) require.NoError(t, s.Open(false)) diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index bbb52a2712..eb601122bf 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -53,7 +53,7 @@ func TestInitializationFailure(t *testing.T) { return []shard.Option{ shard.WithID(sid), - shard.WithLogger(test.NewLogger(t, false)), + shard.WithLogger(test.NewLogger(t, true)), shard.WithBlobStorOptions( blobstor.WithStorages(storages)), shard.WithMetaBaseOptions( @@ -294,7 +294,7 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str te := testNewEngine(t). setShardsNumOpts(t, num, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(test.NewLogger(t, false)), + shard.WithLogger(test.NewLogger(t, true)), shard.WithBlobStorOptions( blobstor.WithStorages(newStorages(filepath.Join(addPath, strconv.Itoa(id)), errSmallSize))), shard.WithMetaBaseOptions( diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 08b1adab8a..57b9ec2e34 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -53,7 +53,7 @@ func TestDeleteBigObject(t *testing.T) { s3 := testNewShard(t, 3) e := testNewEngine(t).setInitializedShards(t, s1, s2, s3).engine - e.log = test.NewLogger(t, false) + e.log = test.NewLogger(t, true) defer e.Close() for i := range children { diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index ba7cdb5b39..a8fd9eeee4 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -79,7 +79,7 @@ type testEngineWrapper struct { } func testNewEngine(t testing.TB, opts ...Option) *testEngineWrapper { - engine := New(WithLogger(test.NewLogger(t, false))) + engine := New(WithLogger(test.NewLogger(t, true))) for _, opt := range opts { opt(engine.cfg) } @@ -198,7 +198,7 @@ func testNewShard(t testing.TB, id int) *shard.Shard { func testDefaultShardOptions(t testing.TB, id int) []shard.Option { return []shard.Option{ - shard.WithLogger(test.NewLogger(t, false)), + shard.WithLogger(test.NewLogger(t, true)), shard.WithBlobStorOptions( blobstor.WithStorages( newStorages(t.TempDir(), 1<<20))), diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 2bc02cf962..750918880f 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -55,7 +55,7 @@ func newEngineWithErrorThreshold(t testing.TB, dir string, errThreshold uint32) largeFileStorage: largeFileStorage, } return []shard.Option{ - shard.WithLogger(test.NewLogger(t, false)), + shard.WithLogger(test.NewLogger(t, true)), shard.WithBlobStorOptions(blobstor.WithStorages(storages)), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(dir, fmt.Sprintf("%d.metabase", id))), diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 40f3bcf8c7..6030ba4942 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -30,7 +30,7 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng te := testNewEngine(t). setShardsNumOpts(t, shardNum, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(test.NewLogger(t, false)), + shard.WithLogger(test.NewLogger(t, true)), shard.WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{{ Storage: fstree.New( diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 0a9748f43a..8234c3c28d 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -65,7 +65,7 @@ func TestListWithCursor(t *testing.T) { t.Parallel() e := testNewEngine(t).setShardsNumOpts(t, tt.shardNum, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(test.NewLogger(t, false)), + shard.WithLogger(test.NewLogger(t, true)), shard.WithBlobStorOptions( blobstor.WithStorages( newStorages(t.TempDir(), 1<<20))), diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 7ee9288750..73612d8407 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -74,7 +74,7 @@ func TestShardOpen(t *testing.T) { newShard := func() *Shard { return New( WithID(NewIDFromBytes([]byte{})), - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{ {Storage: st}, diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index af2fffd635..c258b6c99b 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -30,13 +30,13 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { rootPath := t.TempDir() var sh *Shard - l := test.NewLogger(t, false) + l := test.NewLogger(t, true) blobOpts := []blobstor.Option{ - blobstor.WithLogger(test.NewLogger(t, false)), + blobstor.WithLogger(test.NewLogger(t, true)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(test.NewLogger(t, false)), + blobovniczatree.WithLogger(test.NewLogger(t, true)), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 243bda2014..68693f7693 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -81,7 +81,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { []blobstor.Option{blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(test.NewLogger(t, false)), + blobovniczatree.WithLogger(test.NewLogger(t, true)), blobovniczatree.WithRootPath(filepath.Join(t.TempDir(), "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index b98c360642..c89c0cb7ec 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -27,7 +27,7 @@ func TestShardReload(t *testing.T) { p := t.Name() defer os.RemoveAll(p) - l := test.NewLogger(t, false) + l := test.NewLogger(t, true) blobOpts := []blobstor.Option{ blobstor.WithLogger(l), blobstor.WithStorages([]blobstor.SubStorage{ diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index ff8bfe313d..1083bf014a 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -58,11 +58,11 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts if bsOpts == nil { bsOpts = []blobstor.Option{ - blobstor.WithLogger(test.NewLogger(t, false)), + blobstor.WithLogger(test.NewLogger(t, true)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(test.NewLogger(t, false)), + blobovniczatree.WithLogger(test.NewLogger(t, true)), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), @@ -80,7 +80,7 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts opts := []shard.Option{ shard.WithID(shard.NewIDFromBytes([]byte{})), - shard.WithLogger(test.NewLogger(t, false)), + shard.WithLogger(test.NewLogger(t, true)), shard.WithBlobStorOptions(bsOpts...), shard.WithMetaBaseOptions( append([]meta.Option{ diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go index 119c041077..19bc156148 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go @@ -20,7 +20,7 @@ func TestFlush(t *testing.T) { createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs writecache.MainStorage, opts ...Option) writecache.Cache { return New( append([]Option{ - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), WithPath(filepath.Join(t.TempDir(), "writecache")), WithMetabase(mb), WithBlobstor(bs), diff --git a/pkg/local_object_storage/writecache/writecachebadger/generic_test.go b/pkg/local_object_storage/writecache/writecachebadger/generic_test.go index d21adf41fb..08845665f2 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/generic_test.go +++ b/pkg/local_object_storage/writecache/writecachebadger/generic_test.go @@ -11,7 +11,7 @@ import ( func TestGeneric(t *testing.T) { storagetest.TestAll(t, func(t *testing.T) storagetest.Component { return New( - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), WithFlushWorkersCount(2), WithPath(t.TempDir()), WithGCInterval(1*time.Second)) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go index 5c73891a73..5db4df3180 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go @@ -23,7 +23,7 @@ func TestFlush(t *testing.T) { createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs writecache.MainStorage, opts ...Option) writecache.Cache { return New( append([]Option{ - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), WithPath(filepath.Join(t.TempDir(), "writecache")), WithSmallObjectSize(smallSize), WithMetabase(mb), diff --git a/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go b/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go index 64d853a78d..7eadd1afcb 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go @@ -10,7 +10,7 @@ import ( func TestGeneric(t *testing.T) { storagetest.TestAll(t, func(t *testing.T) storagetest.Component { return New( - WithLogger(test.NewLogger(t, false)), + WithLogger(test.NewLogger(t, true)), WithFlushWorkersCount(2), WithPath(t.TempDir())) }) diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 5b391fe2b5..3ac4872650 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -273,7 +273,7 @@ func TestGetLocalOnly(t *testing.T) { newSvc := func(storage *testStorage) *Service { return &Service{ - log: test.NewLogger(t, false), + log: test.NewLogger(t, true), localStorage: storage, } } @@ -535,7 +535,7 @@ func TestGetRemoteSmall(t *testing.T) { const curEpoch = 13 return &Service{ - log: test.NewLogger(t, false), + log: test.NewLogger(t, true), localStorage: newTestStorage(), traverserGenerator: &testTraverserGenerator{ c: cnr, @@ -1667,7 +1667,7 @@ func TestGetFromPastEpoch(t *testing.T) { const curEpoch = 13 svc := &Service{ - log: test.NewLogger(t, false), + log: test.NewLogger(t, true), localStorage: newTestStorage(), epochSource: testEpochReceiver(curEpoch), traverserGenerator: &testTraverserGenerator{ diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 75059103f7..1eb32a29aa 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -152,7 +152,7 @@ func TestGetLocalOnly(t *testing.T) { newSvc := func(storage *testStorage) *Service { svc := &Service{cfg: new(cfg)} - svc.log = test.NewLogger(t, false) + svc.log = test.NewLogger(t, true) svc.localStorage = storage return svc @@ -254,7 +254,7 @@ func TestGetRemoteSmall(t *testing.T) { newSvc := func(b *testPlacementBuilder, c *testClientCache) *Service { svc := &Service{cfg: new(cfg)} - svc.log = test.NewLogger(t, false) + svc.log = test.NewLogger(t, true) svc.localStorage = newTestStorage() const curEpoch = 13 @@ -363,7 +363,7 @@ func TestGetFromPastEpoch(t *testing.T) { c22.addResult(idCnr, ids22, nil) svc := &Service{cfg: new(cfg)} - svc.log = test.NewLogger(t, false) + svc.log = test.NewLogger(t, true) svc.localStorage = newTestStorage() const curEpoch = 13 @@ -476,7 +476,7 @@ func TestGetWithSessionToken(t *testing.T) { w := new(simpleIDWriter) svc := &Service{cfg: new(cfg)} - svc.log = test.NewLogger(t, false) + svc.log = test.NewLogger(t, true) svc.localStorage = localStorage const curEpoch = 13 diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 2f044b9711..1449d57565 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -100,7 +100,7 @@ func TestMessageSign(t *testing.T) { s := &Service{ cfg: cfg{ - log: test.NewLogger(t, false), + log: test.NewLogger(t, true), key: &privs[0].PrivateKey, nmSource: dummyNetmapSource{}, cnrSource: dummyContainerSource{ From 3fcf56f2fbbd5b9a4257cc7b29fa135f03b8d938 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 23 Aug 2023 20:14:37 +0300 Subject: [PATCH 0006/1413] [#643] objsvc/put: Copy config to `distributedTarget` Signed-off-by: Evgenii Stratonikov --- pkg/services/object/put/distributed.go | 12 +++--------- pkg/services/object/put/streamer.go | 14 ++++++-------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 4740ad1fe2..df01be9bf4 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -10,8 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" "go.uber.org/zap" @@ -27,17 +25,13 @@ type distributedTarget struct { obj *objectSDK.Object objMeta object.ContentMeta + *cfg + payload *payload nodeTargetInitializer func(nodeDesc) preparedObjectTarget - getWorkerPool func([]byte) (util.WorkerPool, bool) - relay func(context.Context, nodeDesc) error - - fmt *object.FormatValidator - - log *logger.Logger } // parameters and state of container traversal. @@ -137,7 +131,7 @@ func (t *distributedTarget) WriteObject(ctx context.Context, obj *objectSDK.Obje var err error - if t.objMeta, err = t.fmt.ValidateContent(t.obj); err != nil { + if t.objMeta, err = t.fmtValidator.ValidateContent(t.obj); err != nil { return fmt.Errorf("(%T) could not validate payload content: %w", t, err) } diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 80b1c25417..1b5a926a12 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -215,13 +215,13 @@ func (p *Streamer) newCommonTarget(prm *PutInitPrm) *distributedTarget { withBroadcast := !prm.common.LocalOnly() && (typ == objectSDK.TypeTombstone || typ == objectSDK.TypeLock) return &distributedTarget{ + cfg: p.cfg, traversal: traversal{ opts: prm.traverseOpts, extraBroadcastEnabled: withBroadcast, }, - payload: getPayload(), - getWorkerPool: p.getWorkerPool, + payload: getPayload(), nodeTargetInitializer: func(node nodeDesc) preparedObjectTarget { if node.local { return localTarget{ @@ -240,8 +240,6 @@ func (p *Streamer) newCommonTarget(prm *PutInitPrm) *distributedTarget { return rt }, relay: relay, - fmt: p.fmtValidator, - log: p.log, } } @@ -279,9 +277,9 @@ func (p *Streamer) Close(ctx context.Context) (*PutResponse, error) { }, nil } -func (p *Streamer) getWorkerPool(pub []byte) (pkgutil.WorkerPool, bool) { - if p.netmapKeys.IsLocalKey(pub) { - return p.localPool, true +func (c *cfg) getWorkerPool(pub []byte) (pkgutil.WorkerPool, bool) { + if c.netmapKeys.IsLocalKey(pub) { + return c.localPool, true } - return p.remotePool, false + return c.remotePool, false } From facd3b2c4b943ce6feca1db41afb1acc7b374982 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 23 Aug 2023 20:31:03 +0300 Subject: [PATCH 0007/1413] [#643] objsvc/put: Unify placement iterators Signed-off-by: Evgenii Stratonikov --- pkg/services/object/put/common.go | 114 +++++++++++++++++++++++++ pkg/services/object/put/distributed.go | 99 ++------------------- pkg/services/object/put/single.go | 107 ++--------------------- pkg/services/object/put/streamer.go | 11 +-- 4 files changed, 132 insertions(+), 199 deletions(-) create mode 100644 pkg/services/object/put/common.go diff --git a/pkg/services/object/put/common.go b/pkg/services/object/put/common.go new file mode 100644 index 0000000000..97e127e19c --- /dev/null +++ b/pkg/services/object/put/common.go @@ -0,0 +1,114 @@ +package putsvc + +import ( + "context" + "fmt" + "sync" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + "go.uber.org/zap" +) + +type nodeIterator struct { + traversal + cfg *cfg +} + +func (c *cfg) newNodeIterator(opts []placement.Option) *nodeIterator { + return &nodeIterator{ + traversal: traversal{ + opts: opts, + mExclude: make(map[string]*bool), + }, + cfg: c, + } +} + +func (n *nodeIterator) forEachNode(ctx context.Context, f func(context.Context, nodeDesc) error) error { + traverser, err := placement.NewTraverser(n.traversal.opts...) + if err != nil { + return fmt.Errorf("could not create object placement traverser: %w", err) + } + + resErr := &atomic.Value{} + + // Must iterate over all replicas, regardless of whether there are identical nodes there. + // At the same time need to exclude identical nodes from processing. + for { + addrs := traverser.Next() + if len(addrs) == 0 { + break + } + + if n.forEachAddress(ctx, traverser, addrs, f, resErr) { + break + } + } + + if !traverser.Success() { + var err errIncompletePut + err.singleErr, _ = resErr.Load().(error) + return err + } + + // perform additional container broadcast if needed + if n.traversal.submitPrimaryPlacementFinish() { + err := n.forEachNode(ctx, f) + if err != nil { + n.cfg.log.Error(logs.PutAdditionalContainerBroadcastFailure, zap.Error(err)) + // we don't fail primary operation because of broadcast failure + } + } + + return nil +} + +func (n *nodeIterator) forEachAddress(ctx context.Context, traverser *placement.Traverser, addrs []placement.Node, f func(context.Context, nodeDesc) error, resErr *atomic.Value) bool { + var wg sync.WaitGroup + + for _, addr := range addrs { + addr := addr + if ok := n.mExclude[string(addr.PublicKey())]; ok != nil { + if *ok { + traverser.SubmitSuccess() + } + // This can happen only during additional container broadcast. + continue + } + + workerPool, isLocal := n.cfg.getWorkerPool(addr.PublicKey()) + + item := new(bool) + wg.Add(1) + if err := workerPool.Submit(func() { + defer wg.Done() + + err := f(ctx, nodeDesc{local: isLocal, info: addr}) + if err != nil { + resErr.Store(err) + svcutil.LogServiceError(n.cfg.log, "PUT", addr.Addresses(), err) + return + } + + traverser.SubmitSuccess() + *item = true + }); err != nil { + wg.Done() + svcutil.LogWorkerPoolError(n.cfg.log, "PUT", err) + return true + } + + // Mark the container node as processed in order to exclude it + // in subsequent container broadcast. Note that we don't + // process this node during broadcast if primary placement + // on it failed. + n.traversal.submitProcessed(addr, item) + } + + wg.Wait() + + return false +} diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index df01be9bf4..577c5a15c5 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -3,16 +3,11 @@ package putsvc import ( "context" "fmt" - "sync" - "sync/atomic" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" - "go.uber.org/zap" ) type preparedObjectTarget interface { @@ -20,7 +15,8 @@ type preparedObjectTarget interface { } type distributedTarget struct { - traversal traversal + placementOpts []placement.Option + extraBroadcastEnabled bool obj *objectSDK.Object objMeta object.ContentMeta @@ -137,7 +133,7 @@ func (t *distributedTarget) WriteObject(ctx context.Context, obj *objectSDK.Obje if len(t.obj.Children()) > 0 { // enabling extra broadcast for linking objects - t.traversal.extraBroadcastEnabled = true + t.extraBroadcastEnabled = true } return t.iteratePlacement(ctx) @@ -160,90 +156,7 @@ func (t *distributedTarget) sendObject(ctx context.Context, node nodeDesc) error func (t *distributedTarget) iteratePlacement(ctx context.Context) error { id, _ := t.obj.ID() - traverser, err := placement.NewTraverser( - append(t.traversal.opts, placement.ForObject(id))..., - ) - if err != nil { - return fmt.Errorf("(%T) could not create object placement traverser: %w", t, err) - } - - resErr := &atomic.Value{} - - // Must iterate over all replicas, regardless of whether there are identical nodes there. - // At the same time need to exclude identical nodes from processing. - for { - addrs := traverser.Next() - if len(addrs) == 0 { - break - } - - if t.iterateAddresses(ctx, traverser, addrs, resErr) { - break - } - } - - if !traverser.Success() { - var err errIncompletePut - err.singleErr, _ = resErr.Load().(error) - return err - } - - // perform additional container broadcast if needed - if t.traversal.submitPrimaryPlacementFinish() { - err = t.iteratePlacement(ctx) - if err != nil { - t.log.Error(logs.PutAdditionalContainerBroadcastFailure, zap.Error(err)) - // we don't fail primary operation because of broadcast failure - } - } - - return nil -} - -func (t *distributedTarget) iterateAddresses(ctx context.Context, traverser *placement.Traverser, addrs []placement.Node, resErr *atomic.Value) bool { - wg := &sync.WaitGroup{} - - for i := range addrs { - addr := addrs[i] - if val := t.traversal.mExclude[string(addr.PublicKey())]; val != nil { - // Check is node processed successful on the previous iteration. - if *val { - traverser.SubmitSuccess() - } - // it can happen only during additional container broadcast - continue - } - - wg.Add(1) - item := new(bool) - - workerPool, isLocal := t.getWorkerPool(addr.PublicKey()) - if err := workerPool.Submit(func() { - defer wg.Done() - - err := t.sendObject(ctx, nodeDesc{local: isLocal, info: addr}) - if err != nil { - resErr.Store(err) - svcutil.LogServiceError(t.log, "PUT", addr.Addresses(), err) - return - } - - traverser.SubmitSuccess() - *item = true - }); err != nil { - wg.Done() - svcutil.LogWorkerPoolError(t.log, "PUT", err) - return true - } - - // mark the container node as processed in order to exclude it - // in subsequent container broadcast. Note that we don't - // process this node during broadcast if primary placement - // on it failed. - t.traversal.submitProcessed(addr, item) - } - - wg.Wait() - - return false + iter := t.cfg.newNodeIterator(append(t.placementOpts, placement.ForObject(id))) + iter.extraBroadcastEnabled = t.extraBroadcastEnabled + return iter.forEachNode(ctx, t.sendObject) } diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index eb18f0f46f..8a7f192bb4 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -8,7 +8,6 @@ import ( "fmt" "hash" "sync" - "sync/atomic" objectAPI "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" @@ -150,18 +149,19 @@ func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *o if err != nil { return err } - traversal := &traversal{ - opts: placementOptions, - extraBroadcastEnabled: len(obj.Children()) > 0 || - (!localOnly && (obj.Type() == objectSDK.TypeTombstone || obj.Type() == objectSDK.TypeLock)), - mExclude: make(map[string]*bool), - } + + iter := s.cfg.newNodeIterator(placementOptions) + iter.extraBroadcastEnabled = len(obj.Children()) > 0 || (!localOnly && (obj.Type() == objectSDK.TypeTombstone || obj.Type() == objectSDK.TypeLock)) + signer := &putSingleRequestSigner{ req: req, keyStorage: s.keyStorage, signer: &sync.Once{}, } - return s.saveAccordingToPlacement(ctx, obj, signer, traversal, meta) + + return iter.forEachNode(ctx, func(ctx context.Context, nd nodeDesc) error { + return s.saveToPlacementNode(ctx, &nd, obj, signer, meta) + }) } func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumber []uint32, localOnly bool) ([]placement.Option, error) { @@ -199,97 +199,6 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb return result, nil } -func (s *Service) saveAccordingToPlacement(ctx context.Context, obj *objectSDK.Object, signer *putSingleRequestSigner, - traversal *traversal, meta object.ContentMeta) error { - traverser, err := placement.NewTraverser(traversal.opts...) - if err != nil { - return fmt.Errorf("could not create object placement traverser: %w", err) - } - - var resultError atomic.Value - for { - addrs := traverser.Next() - if len(addrs) == 0 { - break - } - - if stop := s.saveToPlacementNodes(ctx, obj, signer, traversal, traverser, addrs, meta, &resultError); stop { - break - } - } - - if !traverser.Success() { - var err errIncompletePut - err.singleErr, _ = resultError.Load().(error) - return err - } - - if traversal.submitPrimaryPlacementFinish() { - err = s.saveAccordingToPlacement(ctx, obj, signer, traversal, meta) - if err != nil { - s.log.Error(logs.PutAdditionalContainerBroadcastFailure, zap.Error(err)) - } - } - - return nil -} - -func (s *Service) saveToPlacementNodes(ctx context.Context, - obj *objectSDK.Object, - signer *putSingleRequestSigner, - traversal *traversal, - traverser *placement.Traverser, - nodeAddresses []placement.Node, - meta object.ContentMeta, - resultError *atomic.Value, -) bool { - wg := sync.WaitGroup{} - - for _, nodeAddress := range nodeAddresses { - nodeAddress := nodeAddress - if ok := traversal.mExclude[string(nodeAddress.PublicKey())]; ok != nil { - if *ok { - traverser.SubmitSuccess() - } - continue - } - - local := false - workerPool := s.remotePool - if s.netmapKeys.IsLocalKey(nodeAddress.PublicKey()) { - local = true - workerPool = s.localPool - } - - item := new(bool) - wg.Add(1) - if err := workerPool.Submit(func() { - defer wg.Done() - - err := s.saveToPlacementNode(ctx, &nodeDesc{local: local, info: nodeAddress}, obj, signer, meta) - - if err != nil { - resultError.Store(err) - svcutil.LogServiceError(s.log, "PUT", nodeAddress.Addresses(), err) - return - } - - traverser.SubmitSuccess() - *item = true - }); err != nil { - wg.Done() - svcutil.LogWorkerPoolError(s.log, "PUT", err) - return true - } - - traversal.submitProcessed(nodeAddress, item) - } - - wg.Wait() - - return false -} - func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *nodeDesc, obj *objectSDK.Object, signer *putSingleRequestSigner, meta object.ContentMeta) error { if nodeDesc.local { diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 1b5a926a12..10f932849d 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -215,13 +215,10 @@ func (p *Streamer) newCommonTarget(prm *PutInitPrm) *distributedTarget { withBroadcast := !prm.common.LocalOnly() && (typ == objectSDK.TypeTombstone || typ == objectSDK.TypeLock) return &distributedTarget{ - cfg: p.cfg, - traversal: traversal{ - opts: prm.traverseOpts, - - extraBroadcastEnabled: withBroadcast, - }, - payload: getPayload(), + cfg: p.cfg, + placementOpts: prm.traverseOpts, + extraBroadcastEnabled: withBroadcast, + payload: getPayload(), nodeTargetInitializer: func(node nodeDesc) preparedObjectTarget { if node.local { return localTarget{ From c9e3c9956ed9e5470438e76a8b41bde5f13467fa Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 23 Aug 2023 20:38:25 +0300 Subject: [PATCH 0008/1413] [#643] objsvc/put: Unify extraBroadcastEnabled usage Signed-off-by: Evgenii Stratonikov --- pkg/services/object/put/common.go | 5 +++++ pkg/services/object/put/distributed.go | 8 +------- pkg/services/object/put/single.go | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pkg/services/object/put/common.go b/pkg/services/object/put/common.go index 97e127e19c..6696a192b9 100644 --- a/pkg/services/object/put/common.go +++ b/pkg/services/object/put/common.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) @@ -112,3 +113,7 @@ func (n *nodeIterator) forEachAddress(ctx context.Context, traverser *placement. return false } + +func needAdditionalBroadcast(obj *objectSDK.Object, localOnly bool) bool { + return len(obj.Children()) > 0 || (!localOnly && (obj.Type() == objectSDK.TypeTombstone || obj.Type() == objectSDK.TypeLock)) +} diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 577c5a15c5..509f4aee0f 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -130,12 +130,6 @@ func (t *distributedTarget) WriteObject(ctx context.Context, obj *objectSDK.Obje if t.objMeta, err = t.fmtValidator.ValidateContent(t.obj); err != nil { return fmt.Errorf("(%T) could not validate payload content: %w", t, err) } - - if len(t.obj.Children()) > 0 { - // enabling extra broadcast for linking objects - t.extraBroadcastEnabled = true - } - return t.iteratePlacement(ctx) } @@ -157,6 +151,6 @@ func (t *distributedTarget) iteratePlacement(ctx context.Context) error { id, _ := t.obj.ID() iter := t.cfg.newNodeIterator(append(t.placementOpts, placement.ForObject(id))) - iter.extraBroadcastEnabled = t.extraBroadcastEnabled + iter.extraBroadcastEnabled = needAdditionalBroadcast(t.obj, false /* Distributed target is for cluster-wide PUT */) return iter.forEachNode(ctx, t.sendObject) } diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 8a7f192bb4..adac194a0c 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -151,7 +151,7 @@ func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *o } iter := s.cfg.newNodeIterator(placementOptions) - iter.extraBroadcastEnabled = len(obj.Children()) > 0 || (!localOnly && (obj.Type() == objectSDK.TypeTombstone || obj.Type() == objectSDK.TypeLock)) + iter.extraBroadcastEnabled = needAdditionalBroadcast(obj, localOnly) signer := &putSingleRequestSigner{ req: req, From ba58144de14355680ec8347500c70bff33882639 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 24 Aug 2023 20:54:29 +0300 Subject: [PATCH 0009/1413] [#647] objsvc/search: Remove netmap.Source wrapper Signed-off-by: Evgenii Stratonikov --- pkg/services/object/search/exec.go | 2 +- pkg/services/object/search/search_test.go | 2 +- pkg/services/object/search/service.go | 10 ++++------ pkg/services/object/search/util.go | 9 --------- 4 files changed, 6 insertions(+), 17 deletions(-) diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index c1a9a0c1c6..f471da20e7 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -74,7 +74,7 @@ func (exec *execCtx) initEpoch() bool { return true } - e, err := exec.svc.currentEpochReceiver.currentEpoch() + e, err := exec.svc.currentEpochReceiver.Epoch() switch { default: diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 1eb32a29aa..d8c5ad0905 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -56,7 +56,7 @@ type simpleIDWriter struct { type testEpochReceiver uint64 -func (e testEpochReceiver) currentEpoch() (uint64, error) { +func (e testEpochReceiver) Epoch() (uint64, error) { return uint64(e), nil } diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index 16b82a6205..fd3dbb07bd 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -49,7 +49,7 @@ type cfg struct { } currentEpochReceiver interface { - currentEpoch() (uint64, error) + Epoch() (uint64, error) } keyStore *util.KeyStorage @@ -71,11 +71,9 @@ func New(e *engine.StorageEngine, localStorage: &storageEngineWrapper{ storage: e, }, - traverserGenerator: (*traverseGeneratorWrapper)(tg), - currentEpochReceiver: &nmSrcWrapper{ - nmSrc: ns, - }, - keyStore: ks, + traverserGenerator: (*traverseGeneratorWrapper)(tg), + currentEpochReceiver: ns, + keyStore: ks, } for i := range opts { diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index b5b351a3b6..6ea8e3f146 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -5,7 +5,6 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -36,10 +35,6 @@ type storageEngineWrapper struct { type traverseGeneratorWrapper util.TraverserGenerator -type nmSrcWrapper struct { - nmSrc netmap.Source -} - func newUniqueAddressWriter(w IDListWriter) IDListWriter { return &uniqueIDWriter{ written: make(map[oid.ID]struct{}), @@ -143,7 +138,3 @@ func idsFromAddresses(addrs []oid.Address) []oid.ID { func (e *traverseGeneratorWrapper) generateTraverser(cnr cid.ID, epoch uint64) (*placement.Traverser, error) { return (*util.TraverserGenerator)(e).GenerateTraverser(cnr, nil, epoch) } - -func (n *nmSrcWrapper) currentEpoch() (uint64, error) { - return n.nmSrc.Epoch() -} From 56f841b022eec6a9bd37349154718cfdc9b3c426 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 24 Aug 2023 20:57:53 +0300 Subject: [PATCH 0010/1413] [#647] objsvc/search: Remove TraverserGenerator wrapper Signed-off-by: Evgenii Stratonikov --- pkg/services/object/search/exec.go | 2 +- pkg/services/object/search/search_test.go | 2 +- pkg/services/object/search/service.go | 4 ++-- pkg/services/object/search/util.go | 8 -------- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index f471da20e7..d69cb9b507 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -93,7 +93,7 @@ func (exec *execCtx) initEpoch() bool { } func (exec *execCtx) generateTraverser(cnr cid.ID) (*placement.Traverser, bool) { - t, err := exec.svc.traverserGenerator.generateTraverser(cnr, exec.curProcEpoch) + t, err := exec.svc.traverserGenerator.GenerateTraverser(cnr, nil, exec.curProcEpoch) switch { default: diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index d8c5ad0905..9bfc547396 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -71,7 +71,7 @@ func newTestStorage() *testStorage { } } -func (g *testTraverserGenerator) generateTraverser(_ cid.ID, epoch uint64) (*placement.Traverser, error) { +func (g *testTraverserGenerator) GenerateTraverser(_ cid.ID, _ *oid.ID, epoch uint64) (*placement.Traverser, error) { return placement.NewTraverser( placement.ForContainer(g.c), placement.UseBuilder(g.b[epoch]), diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index fd3dbb07bd..863312200c 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -45,7 +45,7 @@ type cfg struct { } traverserGenerator interface { - generateTraverser(cid.ID, uint64) (*placement.Traverser, error) + GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, error) } currentEpochReceiver interface { @@ -71,7 +71,7 @@ func New(e *engine.StorageEngine, localStorage: &storageEngineWrapper{ storage: e, }, - traverserGenerator: (*traverseGeneratorWrapper)(tg), + traverserGenerator: tg, currentEpochReceiver: ns, keyStore: ks, } diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index 6ea8e3f146..37d2152562 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -8,8 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) @@ -33,8 +31,6 @@ type storageEngineWrapper struct { storage *engine.StorageEngine } -type traverseGeneratorWrapper util.TraverserGenerator - func newUniqueAddressWriter(w IDListWriter) IDListWriter { return &uniqueIDWriter{ written: make(map[oid.ID]struct{}), @@ -134,7 +130,3 @@ func idsFromAddresses(addrs []oid.Address) []oid.ID { return ids } - -func (e *traverseGeneratorWrapper) generateTraverser(cnr cid.ID, epoch uint64) (*placement.Traverser, error) { - return (*util.TraverserGenerator)(e).GenerateTraverser(cnr, nil, epoch) -} From 966ad22abfc9e47397e112f7947a138b5d619c0d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 24 Aug 2023 21:44:55 +0300 Subject: [PATCH 0011/1413] [#647] objsvc/search: Simplify error handling Signed-off-by: Evgenii Stratonikov --- pkg/services/object/search/container.go | 41 ++++++-------- pkg/services/object/search/exec.go | 72 ++++--------------------- pkg/services/object/search/local.go | 20 ++++--- pkg/services/object/search/search.go | 35 ++++++------ 4 files changed, 51 insertions(+), 117 deletions(-) diff --git a/pkg/services/object/search/container.go b/pkg/services/object/search/container.go index 2b6101a981..a8865f5f0d 100644 --- a/pkg/services/object/search/container.go +++ b/pkg/services/object/search/container.go @@ -3,6 +3,7 @@ package searchsvc import ( "context" "encoding/hex" + "fmt" "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -10,12 +11,7 @@ import ( "go.uber.org/zap" ) -func (exec *execCtx) executeOnContainer(ctx context.Context) { - if exec.isLocal() { - exec.log.Debug(logs.SearchReturnResultDirectly) - return - } - +func (exec *execCtx) executeOnContainer(ctx context.Context) error { lookupDepth := exec.netmapLookupDepth() exec.log.Debug(logs.TryingToExecuteInContainer, @@ -23,13 +19,12 @@ func (exec *execCtx) executeOnContainer(ctx context.Context) { ) // initialize epoch number - ok := exec.initEpoch() - if !ok { - return + if err := exec.initEpoch(); err != nil { + return fmt.Errorf("%s: %w", logs.CouldNotGetCurrentEpochNumber, err) } for { - if exec.processCurrentEpoch(ctx) { + if err := exec.processCurrentEpoch(ctx); err != nil { break } @@ -44,18 +39,17 @@ func (exec *execCtx) executeOnContainer(ctx context.Context) { exec.curProcEpoch-- } - exec.status = statusOK - exec.err = nil + return nil } -func (exec *execCtx) processCurrentEpoch(ctx context.Context) bool { +func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { exec.log.Debug(logs.ProcessEpoch, zap.Uint64("number", exec.curProcEpoch), ) - traverser, ok := exec.generateTraverser(exec.containerID()) - if !ok { - return true + traverser, err := exec.svc.traverserGenerator.GenerateTraverser(exec.containerID(), nil, exec.curProcEpoch) + if err != nil { + return fmt.Errorf("%s: %w", logs.SearchCouldNotGenerateContainerTraverser, err) } ctx, cancel := context.WithCancel(ctx) @@ -91,12 +85,7 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) bool { c, err := exec.svc.clientConstructor.get(info) if err != nil { - mtx.Lock() - exec.status = statusUndefined - exec.err = err - mtx.Unlock() - - exec.log.Debug(logs.SearchCouldNotConstructRemoteNodeClient) + exec.log.Debug(logs.SearchCouldNotConstructRemoteNodeClient, zap.String("error", err.Error())) return } @@ -109,13 +98,17 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) bool { } mtx.Lock() - exec.writeIDList(ids) + err = exec.writeIDList(ids) mtx.Unlock() + if err != nil { + exec.log.Debug(logs.SearchCouldNotWriteObjectIdentifiers, zap.String("error", err.Error())) + return + } }(i) } wg.Wait() } - return false + return nil } diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index d69cb9b507..62ef5827fd 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -1,8 +1,6 @@ package searchsvc import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -10,28 +8,16 @@ import ( "go.uber.org/zap" ) -type statusError struct { - status int - err error -} - type execCtx struct { svc *Service prm Prm - statusError - log *logger.Logger curProcEpoch uint64 } -const ( - statusUndefined int = iota - statusOK -) - func (exec *execCtx) prepare() { if _, ok := exec.prm.writer.(*uniqueIDWriter); !ok { exec.prm.writer = newUniqueAddressWriter(exec.prm.writer) @@ -68,64 +54,24 @@ func (exec *execCtx) netmapLookupDepth() uint64 { return exec.prm.common.NetmapLookupDepth() } -func (exec *execCtx) initEpoch() bool { +func (exec *execCtx) initEpoch() error { exec.curProcEpoch = exec.netmapEpoch() if exec.curProcEpoch > 0 { - return true + return nil } e, err := exec.svc.currentEpochReceiver.Epoch() - - switch { - default: - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.CouldNotGetCurrentEpochNumber, - zap.String("error", err.Error()), - ) - - return false - case err == nil: - exec.curProcEpoch = e - return true + if err != nil { + return err } + + exec.curProcEpoch = e + return nil } -func (exec *execCtx) generateTraverser(cnr cid.ID) (*placement.Traverser, bool) { - t, err := exec.svc.traverserGenerator.GenerateTraverser(cnr, nil, exec.curProcEpoch) - - switch { - default: - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.SearchCouldNotGenerateContainerTraverser, - zap.String("error", err.Error()), - ) - - return nil, false - case err == nil: - return t, true - } -} - -func (exec *execCtx) writeIDList(ids []oid.ID) { +func (exec *execCtx) writeIDList(ids []oid.ID) error { ids = exec.filterAllowedObjectIDs(ids) - err := exec.prm.writer.WriteIDs(ids) - - switch { - default: - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.SearchCouldNotWriteObjectIdentifiers, - zap.String("error", err.Error()), - ) - case err == nil: - exec.status = statusOK - exec.err = nil - } + return exec.prm.writer.WriteIDs(ids) } func (exec *execCtx) filterAllowedObjectIDs(objIDs []oid.ID) []oid.ID { diff --git a/pkg/services/object/search/local.go b/pkg/services/object/search/local.go index 1af69caf1d..cfaed13b8c 100644 --- a/pkg/services/object/search/local.go +++ b/pkg/services/object/search/local.go @@ -2,24 +2,22 @@ package searchsvc import ( "context" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "go.uber.org/zap" ) -func (exec *execCtx) executeLocal(ctx context.Context) { +func (exec *execCtx) executeLocal(ctx context.Context) error { ids, err := exec.svc.localStorage.search(ctx, exec) - if err != nil { - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.SearchLocalOperationFailed, - zap.String("error", err.Error()), - ) - - return + exec.log.Debug(logs.SearchLocalOperationFailed, zap.String("error", err.Error())) + return err } - exec.writeIDList(ids) + if err := exec.writeIDList(ids); err != nil { + return fmt.Errorf("%s: %w", logs.SearchCouldNotWriteObjectIdentifiers, err) + } + + return nil } diff --git a/pkg/services/object/search/search.go b/pkg/services/object/search/search.go index 7a7cbfc5b5..2be6bb0e3f 100644 --- a/pkg/services/object/search/search.go +++ b/pkg/services/object/search/search.go @@ -18,33 +18,30 @@ func (s *Service) Search(ctx context.Context, prm Prm) error { exec.setLogger(s.log) - exec.execute(ctx) - - return exec.statusError.err + return exec.execute(ctx) } -func (exec *execCtx) execute(ctx context.Context) { +func (exec *execCtx) execute(ctx context.Context) error { exec.log.Debug(logs.ServingRequest) - // perform local operation - exec.executeLocal(ctx) + err := exec.executeLocal(ctx) + exec.logResult(err) - exec.analyzeStatus(ctx, true) + if exec.isLocal() { + exec.log.Debug(logs.SearchReturnResultDirectly) + return err + } + + err = exec.executeOnContainer(ctx) + exec.logResult(err) + return err } -func (exec *execCtx) analyzeStatus(ctx context.Context, execCnr bool) { - // analyze local result - switch exec.status { +func (exec *execCtx) logResult(err error) { + switch { default: - exec.log.Debug(logs.OperationFinishedWithError, - zap.String("error", exec.err.Error()), - ) - case statusOK: + exec.log.Debug(logs.OperationFinishedWithError, zap.String("error", err.Error())) + case err == nil: exec.log.Debug(logs.OperationFinishedSuccessfully) } - - if execCnr { - exec.executeOnContainer(ctx) - exec.analyzeStatus(ctx, false) - } } From 4db2cbc9274b8314157b6856fa093191aed73fa9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 24 Aug 2023 21:55:36 +0300 Subject: [PATCH 0012/1413] [#647] objsvc/search: Wrap in uniqueIDWriter during parameter setting Signed-off-by: Evgenii Stratonikov --- pkg/services/object/search/exec.go | 6 ------ pkg/services/object/search/prm.go | 4 ++-- pkg/services/object/search/search.go | 2 -- pkg/services/object/search/util.go | 5 ++++- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index 62ef5827fd..2e0d487734 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -18,12 +18,6 @@ type execCtx struct { curProcEpoch uint64 } -func (exec *execCtx) prepare() { - if _, ok := exec.prm.writer.(*uniqueIDWriter); !ok { - exec.prm.writer = newUniqueAddressWriter(exec.prm.writer) - } -} - func (exec *execCtx) setLogger(l *logger.Logger) { exec.log = &logger.Logger{Logger: l.With( zap.String("request", "SEARCH"), diff --git a/pkg/services/object/search/prm.go b/pkg/services/object/search/prm.go index d2918d6e71..95fe82e2fd 100644 --- a/pkg/services/object/search/prm.go +++ b/pkg/services/object/search/prm.go @@ -12,7 +12,7 @@ import ( // Prm groups parameters of Get service call. type Prm struct { - writer IDListWriter + writer *uniqueIDWriter common *util.CommonPrm @@ -40,7 +40,7 @@ func (p *Prm) SetCommonParameters(common *util.CommonPrm) { // SetWriter sets target component to write list of object identifiers. func (p *Prm) SetWriter(w IDListWriter) { - p.writer = w + p.writer = newUniqueAddressWriter(w) } // SetRequestForwarder sets callback for forwarding diff --git a/pkg/services/object/search/search.go b/pkg/services/object/search/search.go index 2be6bb0e3f..4a5c414d5e 100644 --- a/pkg/services/object/search/search.go +++ b/pkg/services/object/search/search.go @@ -14,8 +14,6 @@ func (s *Service) Search(ctx context.Context, prm Prm) error { prm: prm, } - exec.prepare() - exec.setLogger(s.log) return exec.execute(ctx) diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index 37d2152562..67b6c0d016 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -31,7 +31,10 @@ type storageEngineWrapper struct { storage *engine.StorageEngine } -func newUniqueAddressWriter(w IDListWriter) IDListWriter { +func newUniqueAddressWriter(w IDListWriter) *uniqueIDWriter { + if w, ok := w.(*uniqueIDWriter); ok { + return w + } return &uniqueIDWriter{ written: make(map[oid.ID]struct{}), writer: w, From 40b556fc197666a454b4b84a518c6c59e78ce4bb Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 24 Aug 2023 22:17:27 +0300 Subject: [PATCH 0013/1413] [#647] objsvc/search: Improve testing coverage Signed-off-by: Evgenii Stratonikov --- pkg/services/object/search/search_test.go | 113 +++++++++++++++++----- 1 file changed, 90 insertions(+), 23 deletions(-) diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 9bfc547396..09d98eff2e 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -22,6 +22,7 @@ import ( frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" sessionsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -60,6 +61,14 @@ func (e testEpochReceiver) Epoch() (uint64, error) { return uint64(e), nil } +type errIDWriter struct { + err error +} + +func (e errIDWriter) WriteIDs(ids []oid.ID) error { + return e.err +} + func (s *simpleIDWriter) WriteIDs(ids []oid.ID) error { s.ids = append(s.ids, ids...) return nil @@ -194,6 +203,20 @@ func TestGetLocalOnly(t *testing.T) { w := new(simpleIDWriter) p := newPrm(cnr, w) + err := svc.Search(ctx, p) + require.ErrorIs(t, err, testErr) + }) + t.Run("FAIL while writing ID", func(t *testing.T) { + storage := newTestStorage() + svc := newSvc(storage) + + cnr := cidtest.ID() + storage.addResult(cnr, []oid.ID{oidtest.ID()}, nil) + + testErr := errors.New("any error") + w := errIDWriter{testErr} + p := newPrm(cnr, w) + err := svc.Search(ctx, p) require.ErrorIs(t, err, testErr) }) @@ -280,33 +303,34 @@ func TestGetRemoteSmall(t *testing.T) { return p } + var addr oid.Address + addr.SetContainer(id) + + ns, as := testNodeMatrix(t, placementDim) + + builder := &testPlacementBuilder{ + vectors: map[string][][]netmap.NodeInfo{ + addr.EncodeToString(): ns, + }, + } + + c1 := newTestStorage() + ids1 := generateIDs(10) + + c2 := newTestStorage() + ids2 := generateIDs(10) + + svc := newSvc(builder, &testClientCache{ + clients: map[string]*testStorage{ + as[0][0]: c1, + as[0][1]: c2, + }, + }) + t.Run("OK", func(t *testing.T) { - var addr oid.Address - addr.SetContainer(id) - - ns, as := testNodeMatrix(t, placementDim) - - builder := &testPlacementBuilder{ - vectors: map[string][][]netmap.NodeInfo{ - addr.EncodeToString(): ns, - }, - } - - c1 := newTestStorage() - ids1 := generateIDs(10) c1.addResult(id, ids1, nil) - - c2 := newTestStorage() - ids2 := generateIDs(10) c2.addResult(id, ids2, nil) - svc := newSvc(builder, &testClientCache{ - clients: map[string]*testStorage{ - as[0][0]: c1, - as[0][1]: c2, - }, - }) - w := new(simpleIDWriter) p := newPrm(id, w) @@ -319,6 +343,49 @@ func TestGetRemoteSmall(t *testing.T) { require.Contains(t, w.ids, id) } }) + t.Run("non-local fail is not a FAIL", func(t *testing.T) { + testErr := errors.New("opaque") + + c1.addResult(id, ids1, nil) + c2.addResult(id, nil, testErr) + + w := new(simpleIDWriter) + p := newPrm(id, w) + + err := svc.Search(ctx, p) + require.NoError(t, err) + require.Equal(t, ids1, w.ids) + }) + t.Run("client init fail is not a FAIL", func(t *testing.T) { + svc := newSvc(builder, &testClientCache{ + clients: map[string]*testStorage{ + as[0][0]: c1, + }, + }) + c1.addResult(id, ids1, nil) + c2.addResult(id, ids2, nil) + + w := new(simpleIDWriter) + p := newPrm(id, w) + + err := svc.Search(ctx, p) + require.NoError(t, err) + require.Equal(t, ids1, w.ids) + }) + t.Run("context is respected", func(t *testing.T) { + c1.addResult(id, ids1, nil) + c2.addResult(id, ids2, nil) + + w := new(simpleIDWriter) + p := newPrm(id, w) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + err := svc.Search(ctx, p) + require.NoError(t, err) + require.Empty(t, w.ids) + }) } func TestGetFromPastEpoch(t *testing.T) { From d2084ece413ceb80a98bdf1bf96b0af91c82b8ac Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 25 Aug 2023 10:43:49 +0300 Subject: [PATCH 0014/1413] [#648] objsvc/delete: Remove redundant logs We never propagate delete requests to the container node, because tombstone broadcast is done via PUT. No need to pollute logs. Signed-off-by: Evgenii Stratonikov --- internal/logs/logs.go | 1 - pkg/services/object/delete/container.go | 7 ------- pkg/services/object/delete/delete.go | 10 ++-------- 3 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 pkg/services/object/delete/container.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 3f0a3f56ea..a94e868f2a 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -82,7 +82,6 @@ const ( PersistentCouldNotCleanUpExpiredTokens = "could not clean up expired tokens" ControllerReportIsAlreadyStarted = "report is already started" TombstoneCouldNotGetTheTombstoneTheSource = "tombstone getter: could not get the tombstone the source" - DeleteRequestIsNotRolledOverToTheContainer = "request is not rolled over to the container" DeleteCouldNotComposeSplitInfo = "could not compose split info" DeleteNoSplitInfoObjectIsPHY = "no split info, object is PHY" DeleteAssemblingChain = "assembling chain..." diff --git a/pkg/services/object/delete/container.go b/pkg/services/object/delete/container.go deleted file mode 100644 index 3106d8efd0..0000000000 --- a/pkg/services/object/delete/container.go +++ /dev/null @@ -1,7 +0,0 @@ -package deletesvc - -import "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - -func (exec *execCtx) executeOnContainer() { - exec.log.Debug(logs.DeleteRequestIsNotRolledOverToTheContainer) -} diff --git a/pkg/services/object/delete/delete.go b/pkg/services/object/delete/delete.go index ebc191538a..cf07875a88 100644 --- a/pkg/services/object/delete/delete.go +++ b/pkg/services/object/delete/delete.go @@ -39,11 +39,10 @@ func (exec *execCtx) execute(ctx context.Context) { // perform local operation exec.executeLocal(ctx) - - exec.analyzeStatus(true) + exec.analyzeStatus() } -func (exec *execCtx) analyzeStatus(execCnr bool) { +func (exec *execCtx) analyzeStatus() { // analyze local result switch exec.status { case statusOK: @@ -52,10 +51,5 @@ func (exec *execCtx) analyzeStatus(execCnr bool) { exec.log.Debug(logs.OperationFinishedWithError, zap.String("error", exec.err.Error()), ) - - if execCnr { - exec.executeOnContainer() - exec.analyzeStatus(false) - } } } From f8ba60aa0c933354960530b25313e4b22b75da0d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 25 Aug 2023 10:57:31 +0300 Subject: [PATCH 0015/1413] [#648] objsvc/delete: Handle errors in Go style Signed-off-by: Evgenii Stratonikov --- internal/logs/logs.go | 7 -- pkg/services/object/delete/delete.go | 26 ++-- pkg/services/object/delete/exec.go | 171 +++++++-------------------- pkg/services/object/delete/local.go | 39 ++---- 4 files changed, 62 insertions(+), 181 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index a94e868f2a..b826ae08b8 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -82,19 +82,12 @@ const ( PersistentCouldNotCleanUpExpiredTokens = "could not clean up expired tokens" ControllerReportIsAlreadyStarted = "report is already started" TombstoneCouldNotGetTheTombstoneTheSource = "tombstone getter: could not get the tombstone the source" - DeleteCouldNotComposeSplitInfo = "could not compose split info" DeleteNoSplitInfoObjectIsPHY = "no split info, object is PHY" DeleteAssemblingChain = "assembling chain..." - DeleteCouldNotGetPreviousSplitElement = "could not get previous split element" DeleteCollectingChildren = "collecting children..." - DeleteCouldNotCollectObjectChildren = "could not collect object children" DeleteSupplementBySplitID = "supplement by split ID" - DeleteCouldNotSearchForSplitChainMembers = "could not search for split chain members" - DeleteCouldNotMarshalTombstoneStructure = "could not marshal tombstone structure" - DeleteCouldNotSaveTheTombstone = "could not save the tombstone" DeleteFormingTombstoneStructure = "forming tombstone structure..." DeleteTombstoneStructureSuccessfullyFormedSaving = "tombstone structure successfully formed, saving..." - DeleteCouldNotReadTombstoneLifetimeConfig = "could not read tombstone lifetime config" DeleteFormingSplitInfo = "forming split info..." DeleteSplitInfoSuccessfullyFormedCollectingMembers = "split info successfully formed, collecting members..." DeleteMembersSuccessfullyCollected = "members successfully collected" diff --git a/pkg/services/object/delete/delete.go b/pkg/services/object/delete/delete.go index cf07875a88..88454625de 100644 --- a/pkg/services/object/delete/delete.go +++ b/pkg/services/object/delete/delete.go @@ -29,27 +29,17 @@ func (s *Service) Delete(ctx context.Context, prm Prm) error { exec.setLogger(s.log) - exec.execute(ctx) - - return exec.statusError.err + return exec.execute(ctx) } -func (exec *execCtx) execute(ctx context.Context) { +func (exec *execCtx) execute(ctx context.Context) error { exec.log.Debug(logs.ServingRequest) - // perform local operation - exec.executeLocal(ctx) - exec.analyzeStatus() -} - -func (exec *execCtx) analyzeStatus() { - // analyze local result - switch exec.status { - case statusOK: - exec.log.Debug(logs.OperationFinishedSuccessfully) - default: - exec.log.Debug(logs.OperationFinishedWithError, - zap.String("error", exec.err.Error()), - ) + if err := exec.executeLocal(ctx); err != nil { + exec.log.Debug(logs.OperationFinishedWithError, zap.String("error", err.Error())) + return err } + + exec.log.Debug(logs.OperationFinishedSuccessfully) + return nil } diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index b10f045ee2..aac8c88601 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -2,6 +2,7 @@ package deletesvc import ( "context" + "fmt" "strconv" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" @@ -15,18 +16,11 @@ import ( "go.uber.org/zap" ) -type statusError struct { - status int - err error -} - type execCtx struct { svc *Service prm Prm - statusError - log *logger.Logger tombstone *objectSDK.Tombstone @@ -36,11 +30,6 @@ type execCtx struct { tombstoneObj *objectSDK.Object } -const ( - statusUndefined int = iota - statusOK -) - func (exec *execCtx) setLogger(l *logger.Logger) { exec.log = &logger.Logger{Logger: l.With( zap.String("request", "DELETE"), @@ -75,48 +64,34 @@ func (exec *execCtx) newAddress(id oid.ID) oid.Address { return a } -func (exec *execCtx) formSplitInfo(ctx context.Context) bool { - success := false - +func (exec *execCtx) formSplitInfo(ctx context.Context) error { var err error exec.splitInfo, err = exec.svc.header.splitInfo(ctx, exec) - - switch { - default: - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.DeleteCouldNotComposeSplitInfo, - zap.String("error", err.Error()), - ) - case err == nil, apiclient.IsErrObjectAlreadyRemoved(err): + if err != nil && !apiclient.IsErrObjectAlreadyRemoved(err) { // IsErrObjectAlreadyRemoved check is required because splitInfo // implicitly performs Head request that may return ObjectAlreadyRemoved - // status that is not specified for Delete - - exec.status = statusOK - exec.err = nil - success = true + // status that is not specified for Delete. + return err } - return success + return nil } -func (exec *execCtx) collectMembers(ctx context.Context) (ok bool) { +func (exec *execCtx) collectMembers(ctx context.Context) error { if exec.splitInfo == nil { exec.log.Debug(logs.DeleteNoSplitInfoObjectIsPHY) - return true + return nil } + var err error if _, withLink := exec.splitInfo.Link(); withLink { - ok = exec.collectChildren(ctx) + err = exec.collectChildren(ctx) } - if !ok { + if err != nil { if _, withLast := exec.splitInfo.LastPart(); withLast { - ok = exec.collectChain(ctx) - if !ok { - return + if err := exec.collectChain(ctx); err != nil { + return err } } } // may be fail if neither right nor linking ID is set? @@ -124,7 +99,7 @@ func (exec *execCtx) collectMembers(ctx context.Context) (ok bool) { return exec.supplementBySplitID(ctx) } -func (exec *execCtx) collectChain(ctx context.Context) bool { +func (exec *execCtx) collectChain(ctx context.Context) error { var chain []oid.ID exec.log.Debug(logs.DeleteAssemblingChain) @@ -133,84 +108,43 @@ func (exec *execCtx) collectChain(ctx context.Context) bool { chain = append(chain, prev) p, err := exec.svc.header.previous(ctx, exec, prev) + if err != nil { + return fmt.Errorf("get previous split element for %s: %w", prev, err) + } - switch { - default: - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.DeleteCouldNotGetPreviousSplitElement, - zap.Stringer("id", prev), - zap.String("error", err.Error()), - ) - - return false - case err == nil: - exec.status = statusOK - exec.err = nil - - withPrev = p != nil - if withPrev { - prev = *p - } + withPrev = p != nil + if withPrev { + prev = *p } } exec.addMembers(chain) - - return true + return nil } -func (exec *execCtx) collectChildren(ctx context.Context) bool { +func (exec *execCtx) collectChildren(ctx context.Context) error { exec.log.Debug(logs.DeleteCollectingChildren) children, err := exec.svc.header.children(ctx, exec) - - switch { - default: - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.DeleteCouldNotCollectObjectChildren, - zap.String("error", err.Error()), - ) - - return false - case err == nil: - exec.status = statusOK - exec.err = nil - - link, _ := exec.splitInfo.Link() - - exec.addMembers(append(children, link)) - - return true + if err != nil { + return fmt.Errorf("collect children: %w", err) } + + link, _ := exec.splitInfo.Link() + exec.addMembers(append(children, link)) + return nil } -func (exec *execCtx) supplementBySplitID(ctx context.Context) bool { +func (exec *execCtx) supplementBySplitID(ctx context.Context) error { exec.log.Debug(logs.DeleteSupplementBySplitID) chain, err := exec.svc.searcher.splitMembers(ctx, exec) - - switch { - default: - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.DeleteCouldNotSearchForSplitChainMembers, - zap.String("error", err.Error()), - ) - - return false - case err == nil: - exec.status = statusOK - exec.err = nil - - exec.addMembers(chain) - - return true + if err != nil { + return fmt.Errorf("search split chain members: %w", err) } + + exec.addMembers(chain) + return nil } func (exec *execCtx) addMembers(incoming []oid.ID) { @@ -228,17 +162,10 @@ func (exec *execCtx) addMembers(incoming []oid.ID) { exec.tombstone.SetMembers(append(members, incoming...)) } -func (exec *execCtx) initTombstoneObject() bool { +func (exec *execCtx) initTombstoneObject() error { payload, err := exec.tombstone.Marshal() if err != nil { - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.DeleteCouldNotMarshalTombstoneStructure, - zap.String("error", err.Error()), - ) - - return false + return fmt.Errorf("marshal tombstone: %w", err) } exec.tombstoneObj = objectSDK.New() @@ -262,29 +189,15 @@ func (exec *execCtx) initTombstoneObject() bool { exec.tombstoneObj.SetAttributes(a) - return true + return nil } -func (exec *execCtx) saveTombstone(ctx context.Context) bool { +func (exec *execCtx) saveTombstone(ctx context.Context) error { id, err := exec.svc.placer.put(ctx, exec) - - switch { - default: - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.DeleteCouldNotSaveTheTombstone, - zap.String("error", err.Error()), - ) - - return false - case err == nil: - exec.status = statusOK - exec.err = nil - - exec.prm.tombAddrWriter. - SetAddress(exec.newAddress(*id)) + if err != nil { + return fmt.Errorf("save tombstone: %w", err) } - return true + exec.prm.tombAddrWriter.SetAddress(exec.newAddress(*id)) + return nil } diff --git a/pkg/services/object/delete/local.go b/pkg/services/object/delete/local.go index ad3e10bc62..55ce4408d9 100644 --- a/pkg/services/object/delete/local.go +++ b/pkg/services/object/delete/local.go @@ -2,37 +2,29 @@ package deletesvc import ( "context" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.uber.org/zap" ) -func (exec *execCtx) executeLocal(ctx context.Context) { +func (exec *execCtx) executeLocal(ctx context.Context) error { exec.log.Debug(logs.DeleteFormingTombstoneStructure) - ok := exec.formTombstone(ctx) - if !ok { - return + if err := exec.formTombstone(ctx); err != nil { + return err } exec.log.Debug(logs.DeleteTombstoneStructureSuccessfullyFormedSaving) - exec.saveTombstone(ctx) + return exec.saveTombstone(ctx) } -func (exec *execCtx) formTombstone(ctx context.Context) (ok bool) { +func (exec *execCtx) formTombstone(ctx context.Context) error { tsLifetime, err := exec.svc.netInfo.TombstoneLifetime() if err != nil { - exec.status = statusUndefined - exec.err = err - - exec.log.Debug(logs.DeleteCouldNotReadTombstoneLifetimeConfig, - zap.String("error", err.Error()), - ) - - return false + return fmt.Errorf("fetch tombstone lifetime: %w", err) } exec.tombstone = objectSDK.NewTombstone() @@ -43,26 +35,19 @@ func (exec *execCtx) formTombstone(ctx context.Context) (ok bool) { exec.log.Debug(logs.DeleteFormingSplitInfo) - ok = exec.formSplitInfo(ctx) - if !ok { - return + if err := exec.formSplitInfo(ctx); err != nil { + return fmt.Errorf("form split info: %w", err) } exec.log.Debug(logs.DeleteSplitInfoSuccessfullyFormedCollectingMembers) exec.tombstone.SetSplitID(exec.splitInfo.SplitID()) - ok = exec.collectMembers(ctx) - if !ok { - return + if err := exec.collectMembers(ctx); err != nil { + return err } exec.log.Debug(logs.DeleteMembersSuccessfullyCollected) - ok = exec.initTombstoneObject() - if !ok { - return - } - - return true + return exec.initTombstoneObject() } From c4db8e769054ac9ba26a6a20d80bab402ed193eb Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 25 Aug 2023 11:43:35 +0300 Subject: [PATCH 0016/1413] [#637] shard/test: Fix data race Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/metrics_test.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 60adc07249..91e158b04a 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -28,13 +28,17 @@ type metricsStore struct { errCounter int64 } -func (m metricsStore) SetShardID(_ string) {} +func (m *metricsStore) SetShardID(_ string) {} -func (m metricsStore) SetObjectCounter(objectType string, v uint64) { +func (m *metricsStore) SetObjectCounter(objectType string, v uint64) { + m.mtx.Lock() + defer m.mtx.Unlock() m.objCounters[objectType] = v } -func (m metricsStore) AddToObjectCounter(objectType string, delta int) { +func (m *metricsStore) AddToObjectCounter(objectType string, delta int) { + m.mtx.Lock() + defer m.mtx.Unlock() switch { case delta > 0: m.objCounters[objectType] += uint64(delta) From 9072772a09c93f2bcdb9ad1441344512980a4a39 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 25 Aug 2023 12:04:34 +0300 Subject: [PATCH 0017/1413] [#649] shard/test: Increase GC remover interval This was set in #348 to speed up tests. It seems 100ms doesn't increase overall test time, but it reduces the amount of logs by 100x factor. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/delete_test.go | 13 +++++++++---- pkg/local_object_storage/shard/shard_test.go | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index aba204f36a..bfafcdc743 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -3,6 +3,7 @@ package shard_test import ( "context" "testing" + "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" @@ -56,8 +57,10 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { _, err = sh.Delete(context.TODO(), delPrm) require.NoError(t, err) - _, err = sh.Get(context.Background(), getPrm) - require.True(t, client.IsErrObjectNotFound(err)) + require.Eventually(t, func() bool { + _, err = sh.Get(context.Background(), getPrm) + return client.IsErrObjectNotFound(err) + }, time.Second, 50*time.Millisecond) }) t.Run("small object", func(t *testing.T) { @@ -80,7 +83,9 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { _, err = sh.Delete(context.Background(), delPrm) require.NoError(t, err) - _, err = sh.Get(context.Background(), getPrm) - require.True(t, client.IsErrObjectNotFound(err)) + require.Eventually(t, func() bool { + _, err = sh.Get(context.Background(), getPrm) + return client.IsErrObjectNotFound(err) + }, time.Second, 50*time.Millisecond) }) } diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 1083bf014a..6337b0b6ea 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -101,7 +101,7 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts require.NoError(t, err) return pool }), - shard.WithGCRemoverSleepInterval(1 * time.Millisecond), + shard.WithGCRemoverSleepInterval(100 * time.Millisecond), } sh = shard.New(opts...) From 554ff2c06b397ce447a55f651f5185e97f781c8c Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 24 Aug 2023 15:27:24 +0300 Subject: [PATCH 0018/1413] [#574] core: Extend Source interface with DeletionInfo method * Introduce common method EverExisted * Define DeletionInfo for struct that must implement Source * Refactor tree srv Signed-off-by: Airat Arifullin --- cmd/frostfs-node/cache.go | 23 +++++++-- cmd/frostfs-node/container.go | 17 ++++--- cmd/frostfs-node/tree.go | 2 +- pkg/core/container/storage.go | 2 + pkg/core/container/util.go | 22 +++++++++ pkg/morph/client/container/deletion_info.go | 22 ++++++++- pkg/services/policer/policer_test.go | 54 ++++++++++++++------- pkg/services/tree/sync.go | 16 +----- 8 files changed, 115 insertions(+), 43 deletions(-) create mode 100644 pkg/core/container/util.go diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index 6d138d8946..f8266e562e 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -142,7 +142,8 @@ func (c *lruNetCache) get(key uint64) (*netmapSDK.NetMap, error) { // wrapper over TTL cache of values read from the network // that implements container storage. type ttlContainerStorage struct { - *ttlNetCache[cid.ID, *container.Container] + containerCache *ttlNetCache[cid.ID, *container.Container] + delInfoCache *ttlNetCache[cid.ID, *container.DelInfo] } func newCachedContainerStorage(v container.Source, ttl time.Duration) ttlContainerStorage { @@ -151,18 +152,32 @@ func newCachedContainerStorage(v container.Source, ttl time.Duration) ttlContain lruCnrCache := newNetworkTTLCache(containerCacheSize, ttl, func(id cid.ID) (*container.Container, error) { return v.Get(id) }) + lruDelInfoCache := newNetworkTTLCache(containerCacheSize, ttl, func(id cid.ID) (*container.DelInfo, error) { + return v.DeletionInfo(id) + }) - return ttlContainerStorage{lruCnrCache} + return ttlContainerStorage{ + containerCache: lruCnrCache, + delInfoCache: lruDelInfoCache, + } } func (s ttlContainerStorage) handleRemoval(cnr cid.ID) { - s.set(cnr, nil, new(apistatus.ContainerNotFound)) + s.containerCache.set(cnr, nil, new(apistatus.ContainerNotFound)) + + // The removal causes the cache miss and thus deletion info (that contains + // ownerID and epoch) for the container will be updated from sidechain. + s.delInfoCache.remove(cnr) } // Get returns container value from the cache. If value is missing in the cache // or expired, then it returns value from side chain and updates the cache. func (s ttlContainerStorage) Get(cnr cid.ID) (*container.Container, error) { - return s.get(cnr) + return s.containerCache.get(cnr) +} + +func (s ttlContainerStorage) DeletionInfo(cnr cid.ID) (*container.DelInfo, error) { + return s.delInfoCache.get(cnr) } type ttlEACLStorage struct { diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 9a6cfd02bd..8c2ae54b36 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -28,6 +28,7 @@ import ( containerMorph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apiClient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -113,7 +114,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c c.cfgObject.eaclSource = eACLFetcher cnrRdr.eacl = eACLFetcher c.cfgObject.cnrSource = cnrSrc - cnrRdr.get = cnrSrc + cnrRdr.src = cnrSrc cnrRdr.lister = client } else { // use RPC node as source of Container contract items (with caching) @@ -131,7 +132,8 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c cnr, err := cnrSrc.Get(ev.ID) if err == nil { cachedContainerLister.update(cnr.Value.Owner(), ev.ID, true) - cachedContainerStorage.set(ev.ID, cnr, nil) + cachedContainerStorage.containerCache.set(ev.ID, cnr, nil) + cachedContainerStorage.delInfoCache.set(ev.ID, nil, new(apistatus.ContainerNotFound)) } else { // unlike removal, we expect successful receive of the container // after successful creation, so logging can be useful @@ -159,7 +161,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c } cachedContainerStorage.handleRemoval(ev.ID) - c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt, zap.Stringer("id", ev.ID), ) @@ -170,7 +171,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c cnrRdr.lister = cachedContainerLister cnrRdr.eacl = c.cfgObject.eaclSource - cnrRdr.get = c.cfgObject.cnrSource + cnrRdr.src = c.cfgObject.cnrSource cnrWrt.cacheEnabled = true cnrWrt.eacls = cachedEACLStorage @@ -641,7 +642,7 @@ func (c *usedSpaceService) processLoadValue(_ context.Context, a containerSDK.Si type morphContainerReader struct { eacl containerCore.EACLSource - get containerCore.Source + src containerCore.Source lister interface { List(*user.ID) ([]cid.ID, error) @@ -649,7 +650,11 @@ type morphContainerReader struct { } func (x *morphContainerReader) Get(id cid.ID) (*containerCore.Container, error) { - return x.get.Get(id) + return x.src.Get(id) +} + +func (x *morphContainerReader) DeletionInfo(id cid.ID) (*containerCore.DelInfo, error) { + return x.src.DeletionInfo(id) } func (x *morphContainerReader) GetEACL(id cid.ID) (*containerCore.EACL, error) { diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index 175748ac58..f7c0f2a368 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -32,7 +32,7 @@ func (c cnrSource) Get(id cid.ID) (*container.Container, error) { } func (c cnrSource) DeletionInfo(cid cid.ID) (*container.DelInfo, error) { - return c.cli.DeletionInfo(cid) + return c.src.DeletionInfo(cid) } func (c cnrSource) List() ([]cid.ID, error) { diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index bdff45cc64..0766ced31d 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -41,6 +41,8 @@ type Source interface { // Implementations must not retain the container pointer and modify // the container through it. Get(cid.ID) (*Container, error) + + DeletionInfo(cid.ID) (*DelInfo, error) } // EACL groups information about the FrostFS container's extended ACL stored in diff --git a/pkg/core/container/util.go b/pkg/core/container/util.go new file mode 100644 index 0000000000..58ceb03ba7 --- /dev/null +++ b/pkg/core/container/util.go @@ -0,0 +1,22 @@ +package container + +import ( + "errors" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" +) + +// EverExisted checks whether the container ever existed or +// it just has not been created yet at the current epoch. +func EverExisted(s Source, cid cid.ID) (bool, error) { + _, err := s.DeletionInfo(cid) + if err == nil { + return true, nil + } + var errContainerNotFound *apistatus.ContainerNotFound + if errors.As(err, &errContainerNotFound) { + return false, nil + } + return false, err +} diff --git a/pkg/morph/client/container/deletion_info.go b/pkg/morph/client/container/deletion_info.go index 094d4e1185..b34ec32dba 100644 --- a/pkg/morph/client/container/deletion_info.go +++ b/pkg/morph/client/container/deletion_info.go @@ -1,6 +1,7 @@ package container import ( + "crypto/sha256" "fmt" "strings" @@ -11,7 +12,26 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" ) -func (c *Client) DeletionInfo(cid cid.ID) (*containercore.DelInfo, error) { +func (x *containerSource) DeletionInfo(cnr cid.ID) (*containercore.DelInfo, error) { + return DeletionInfo((*Client)(x), cnr) +} + +type deletionInfo interface { + DeletionInfo(cid []byte) (*containercore.DelInfo, error) +} + +func AsContainerSpecInfoProvider(w *Client) containercore.Source { + return (*containerSource)(w) +} + +func DeletionInfo(c deletionInfo, cnr cid.ID) (*containercore.DelInfo, error) { + binCnr := make([]byte, sha256.Size) + cnr.Encode(binCnr) + + return c.DeletionInfo(binCnr) +} + +func (c *Client) DeletionInfo(cid []byte) (*containercore.DelInfo, error) { prm := client.TestInvokePrm{} prm.SetMethod(deletionInfoMethod) prm.SetArgs(cid) diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 37d6c0506c..8b3eecd3b8 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -34,8 +34,13 @@ func TestBuryObjectWithoutContainer(t *testing.T) { // Container source and bury function buryCh := make(chan oid.Address) - containerSrc := func(id cid.ID) (*container.Container, error) { - return nil, new(apistatus.ContainerNotFound) + containerSrc := containerSrc{ + get: func(id cid.ID) (*container.Container, error) { + return nil, new(apistatus.ContainerNotFound) + }, + deletionInfo: func(id cid.ID) (*container.DelInfo, error) { + return &container.DelInfo{}, nil + }, } buryFn := func(ctx context.Context, a oid.Address) error { buryCh <- a @@ -49,7 +54,7 @@ func TestBuryObjectWithoutContainer(t *testing.T) { // Policer instance p := New( WithKeySpaceIterator(&sliceKeySpaceIterator{objs: objs}), - WithContainerSource(containerSrcFunc(containerSrc)), + WithContainerSource(containerSrc), WithBuryFunc(buryFn), WithPool(pool), ) @@ -194,12 +199,17 @@ func TestProcessObject(t *testing.T) { cnr := &container.Container{} cnr.Value.Init() cnr.Value.SetPlacementPolicy(policy) - containerSrc := func(id cid.ID) (*container.Container, error) { - if id.Equals(addr.Container()) { - return cnr, nil - } - t.Errorf("unexpected container requested: got=%v, want=%v", id, addr.Container()) - return nil, new(apistatus.ContainerNotFound) + containerSrc := containerSrc{ + get: func(id cid.ID) (*container.Container, error) { + if id.Equals(addr.Container()) { + return cnr, nil + } + t.Errorf("unexpected container requested: got=%v, want=%v", id, addr.Container()) + return nil, new(apistatus.ContainerNotFound) + }, + deletionInfo: func(id cid.ID) (*container.DelInfo, error) { + return &container.DelInfo{}, nil + }, } buryFn := func(ctx context.Context, a oid.Address) error { t.Errorf("unexpected object buried: %v", a) @@ -211,7 +221,7 @@ func TestProcessObject(t *testing.T) { var gotReplicateTo []int p := New( - WithContainerSource(containerSrcFunc(containerSrc)), + WithContainerSource(containerSrc), WithPlacementBuilder(placementBuilderFunc(placementBuilder)), WithNetmapKeys(announcedKeysFunc(func(k []byte) bool { return bytes.Equal(k, nodes[0].PublicKey()) @@ -251,9 +261,6 @@ func TestIteratorContract(t *testing.T) { Type: objectSDK.TypeRegular, }} - containerSrc := func(id cid.ID) (*container.Container, error) { - return nil, new(apistatus.ContainerNotFound) - } buryFn := func(ctx context.Context, a oid.Address) error { return nil } @@ -273,9 +280,18 @@ func TestIteratorContract(t *testing.T) { finishCh: make(chan struct{}), } + containerSrc := containerSrc{ + get: func(id cid.ID) (*container.Container, error) { + return nil, new(apistatus.ContainerNotFound) + }, + deletionInfo: func(id cid.ID) (*container.DelInfo, error) { + return &container.DelInfo{}, nil + }, + } + p := New( WithKeySpaceIterator(it), - WithContainerSource(containerSrcFunc(containerSrc)), + WithContainerSource(containerSrc), WithBuryFunc(buryFn), WithPool(pool), func(c *cfg) { @@ -353,10 +369,14 @@ func (it *sliceKeySpaceIterator) Rewind() { it.cur = 0 } -// containerSrcFunc is a container.Source backed by a function. -type containerSrcFunc func(cid.ID) (*container.Container, error) +type containerSrc struct { + get func(id cid.ID) (*container.Container, error) + deletionInfo func(id cid.ID) (*container.DelInfo, error) +} -func (f containerSrcFunc) Get(id cid.ID) (*container.Container, error) { return f(id) } +func (f containerSrc) Get(id cid.ID) (*container.Container, error) { return f.get(id) } + +func (f containerSrc) DeletionInfo(id cid.ID) (*container.DelInfo, error) { return f.deletionInfo(id) } // placementBuilderFunc is a placement.Builder backed by a function type placementBuilderFunc func(cid.ID, *oid.ID, netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 62a127c6b1..c681bb0785 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -12,13 +12,13 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" tracing_grpc "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/panjf2000/ants/v2" @@ -441,18 +441,6 @@ func (s *Service) syncContainers(ctx context.Context, cnrs []cid.ID) { wg.Wait() } -func (s *Service) containerEverExisted(cid cid.ID) (bool, error) { - _, err := s.cnrSource.DeletionInfo(cid) - if err == nil { - return true, nil - } - var errContainerNotFound *apistatus.ContainerNotFound - if errors.As(err, &errContainerNotFound) { - return false, nil - } - return false, err -} - func (s *Service) removeContainers(ctx context.Context, newContainers map[cid.ID]struct{}) { ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.removeContainers") defer span.End() @@ -466,7 +454,7 @@ func (s *Service) removeContainers(ctx context.Context, newContainers map[cid.ID continue } - existed, err := s.containerEverExisted(cnr) + existed, err := containerCore.EverExisted(s.cnrSource, cnr) if err != nil { s.log.Error(logs.TreeCouldNotCheckIfContainerExisted, zap.Stringer("cid", cnr), From 4ea0df77d0b5336fac5420df5bfba89e650f33cc Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 24 Aug 2023 15:35:19 +0300 Subject: [PATCH 0019/1413] [#574] policer: Check if the container was really removed Signed-off-by: Airat Arifullin --- cmd/frostfs-node/cache.go | 3 +-- cmd/frostfs-node/container.go | 2 -- internal/logs/logs.go | 1 + pkg/core/container/util.go | 4 ++-- pkg/morph/client/container/deletion_info.go | 4 ---- pkg/services/policer/check.go | 13 +++++++++++-- pkg/services/tree/sync.go | 2 +- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index f8266e562e..6a5d5d1827 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -165,8 +165,7 @@ func newCachedContainerStorage(v container.Source, ttl time.Duration) ttlContain func (s ttlContainerStorage) handleRemoval(cnr cid.ID) { s.containerCache.set(cnr, nil, new(apistatus.ContainerNotFound)) - // The removal causes the cache miss and thus deletion info (that contains - // ownerID and epoch) for the container will be updated from sidechain. + // The removal invalidates possibly stored error response. s.delInfoCache.remove(cnr) } diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 8c2ae54b36..5d88ff9ea5 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -28,7 +28,6 @@ import ( containerMorph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apiClient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -133,7 +132,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c if err == nil { cachedContainerLister.update(cnr.Value.Owner(), ev.ID, true) cachedContainerStorage.containerCache.set(ev.ID, cnr, nil) - cachedContainerStorage.delInfoCache.set(ev.ID, nil, new(apistatus.ContainerNotFound)) } else { // unlike removal, we expect successful receive of the container // after successful creation, so logging can be useful diff --git a/internal/logs/logs.go b/internal/logs/logs.go index b826ae08b8..95961cd47e 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -42,6 +42,7 @@ const ( NotificatorNotificatorStartProcessingObjectNotifications = "notificator: start processing object notifications" NotificatorNotificatorProcessingObjectNotification = "notificator: processing object notification" PolicerCouldNotGetContainer = "could not get container" + PolicerCouldNotConfirmContainerRemoval = "could not confirm container removal" PolicerCouldNotInhumeObjectWithMissingContainer = "could not inhume object with missing container" PolicerCouldNotBuildPlacementVectorForObject = "could not build placement vector for object" PolicerRedundantLocalObjectCopyDetected = "redundant local object copy detected" diff --git a/pkg/core/container/util.go b/pkg/core/container/util.go index 58ceb03ba7..98919284ee 100644 --- a/pkg/core/container/util.go +++ b/pkg/core/container/util.go @@ -7,9 +7,9 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" ) -// EverExisted checks whether the container ever existed or +// WasRemoved checks whether the container ever existed or // it just has not been created yet at the current epoch. -func EverExisted(s Source, cid cid.ID) (bool, error) { +func WasRemoved(s Source, cid cid.ID) (bool, error) { _, err := s.DeletionInfo(cid) if err == nil { return true, nil diff --git a/pkg/morph/client/container/deletion_info.go b/pkg/morph/client/container/deletion_info.go index b34ec32dba..40eb267d6e 100644 --- a/pkg/morph/client/container/deletion_info.go +++ b/pkg/morph/client/container/deletion_info.go @@ -20,10 +20,6 @@ type deletionInfo interface { DeletionInfo(cid []byte) (*containercore.DelInfo, error) } -func AsContainerSpecInfoProvider(w *Client) containercore.Source { - return (*containerSource)(w) -} - func DeletionInfo(c deletionInfo, cnr cid.ID) (*containercore.DelInfo, error) { binCnr := make([]byte, sha256.Size) cnr.Encode(binCnr) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 800ddb006a..bc82b144d3 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -5,6 +5,7 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" @@ -27,12 +28,20 @@ func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.Add zap.String("error", err.Error()), ) if client.IsErrContainerNotFound(err) { - err := p.buryFn(ctx, addrWithType.Address) + existed, err := containercore.WasRemoved(p.cnrSrc, idCnr) if err != nil { - p.log.Error(logs.PolicerCouldNotInhumeObjectWithMissingContainer, + p.log.Error(logs.PolicerCouldNotConfirmContainerRemoval, zap.Stringer("cid", idCnr), zap.Stringer("oid", idObj), zap.String("error", err.Error())) + } else if existed { + err := p.buryFn(ctx, addrWithType.Address) + if err != nil { + p.log.Error(logs.PolicerCouldNotInhumeObjectWithMissingContainer, + zap.Stringer("cid", idCnr), + zap.Stringer("oid", idObj), + zap.String("error", err.Error())) + } } } diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index c681bb0785..9cff8b3517 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -454,7 +454,7 @@ func (s *Service) removeContainers(ctx context.Context, newContainers map[cid.ID continue } - existed, err := containerCore.EverExisted(s.cnrSource, cnr) + existed, err := containerCore.WasRemoved(s.cnrSource, cnr) if err != nil { s.log.Error(logs.TreeCouldNotCheckIfContainerExisted, zap.Stringer("cid", cnr), From ab2614ec2d444e06c1407854f6a451cc36a03f1d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 17 Jul 2023 16:46:46 +0300 Subject: [PATCH 0020/1413] [#528] objectcore: Validate token issuer Add token issuer against object owner validation. Signed-off-by: Dmitrii Stepanov --- pkg/core/object/fmt.go | 7 ++++++- pkg/core/object/fmt_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index e6d8174faf..fe6654517a 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -153,9 +153,14 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { } token := obj.SessionToken() + ownerID := *obj.OwnerID() if token == nil || !token.AssertAuthKey(&key) { - return v.checkOwnerKey(*obj.OwnerID(), key) + return v.checkOwnerKey(ownerID, key) + } + + if !token.Issuer().Equals(ownerID) { + return fmt.Errorf("(%T) different token issuer and object owner identifiers %s/%s", v, token.Issuer(), ownerID) } return nil diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index d04c167095..392ecf6051 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -8,11 +8,13 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) @@ -104,6 +106,34 @@ func TestFormatValidator_Validate(t *testing.T) { require.NoError(t, v.Validate(context.Background(), obj, false)) }) + t.Run("invalid w/ session token", func(t *testing.T) { + var idOwner user.ID + user.IDFromKey(&idOwner, ownerKey.PrivateKey.PublicKey) + + var randomUserID user.ID + randPrivKey, err := keys.NewPrivateKey() + require.NoError(t, err) + user.IDFromKey(&randomUserID, randPrivKey.PrivateKey.PublicKey) + + tok := sessiontest.Object() + fsPubKey := frostfsecdsa.PublicKey(*ownerKey.PublicKey()) + tok.SetID(uuid.New()) + tok.SetAuthKey(&fsPubKey) + tok.SetExp(100500) + tok.SetIat(1) + tok.SetNbf(1) + err = tok.Sign(ownerKey.PrivateKey) + require.NoError(t, err) + + obj := objectSDK.New() + obj.SetContainerID(cidtest.ID()) + obj.SetSessionToken(tok) + obj.SetOwnerID(&randomUserID) + require.NoError(t, objectSDK.SetIDWithSignature(ownerKey.PrivateKey, obj)) + + require.Error(t, v.Validate(context.Background(), obj, false)) //invalid owner + }) + t.Run("correct w/o session token", func(t *testing.T) { obj := blankValidObject(&ownerKey.PrivateKey) From ae81d6660adee15617c10354ad5a17a75382ba5d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Jul 2023 15:44:35 +0300 Subject: [PATCH 0021/1413] [#529] objectcore: Fix object content validation There are old objects where the owner of the object may not match the one who issued the token. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 7 +- cmd/frostfs-node/config/object/config.go | 5 + cmd/frostfs-node/config/object/config_test.go | 2 + cmd/frostfs-node/object.go | 14 +- config/example/node.env | 1 + config/example/node.json | 3 +- config/example/node.yaml | 1 + pkg/core/object/fmt.go | 154 +++++++- pkg/core/object/fmt_test.go | 364 ++++++++++++++++-- pkg/services/object/put/service.go | 26 +- 10 files changed, 535 insertions(+), 42 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 808a78d286..8e103b527b 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -511,6 +511,8 @@ type cfgObject struct { cfgLocalStorage cfgLocalStorage tombstoneLifetime uint64 + + skipSessionTokenIssuerVerification bool } type cfgNotifications struct { @@ -677,8 +679,9 @@ func initCfgGRPC() cfgGRPC { func initCfgObject(appCfg *config.Config) cfgObject { return cfgObject{ - pool: initObjectPool(appCfg), - tombstoneLifetime: objectconfig.TombstoneLifetime(appCfg), + pool: initObjectPool(appCfg), + tombstoneLifetime: objectconfig.TombstoneLifetime(appCfg), + skipSessionTokenIssuerVerification: objectconfig.Put(appCfg).SkipSessionTokenIssuerVerification(), } } diff --git a/cmd/frostfs-node/config/object/config.go b/cmd/frostfs-node/config/object/config.go index cd969852b6..f7a33b5e05 100644 --- a/cmd/frostfs-node/config/object/config.go +++ b/cmd/frostfs-node/config/object/config.go @@ -51,3 +51,8 @@ func (g PutConfig) PoolSizeLocal() int { return PutPoolSizeDefault } + +// SkipSessionTokenIssuerVerification returns the value of "skip_session_token_issuer_verification" config parameter or `false“ if is not defined. +func (g PutConfig) SkipSessionTokenIssuerVerification() bool { + return config.BoolSafe(g.cfg, "skip_session_token_issuer_verification") +} diff --git a/cmd/frostfs-node/config/object/config_test.go b/cmd/frostfs-node/config/object/config_test.go index 81c1ccd575..513b6e9c52 100644 --- a/cmd/frostfs-node/config/object/config_test.go +++ b/cmd/frostfs-node/config/object/config_test.go @@ -16,6 +16,7 @@ func TestObjectSection(t *testing.T) { require.Equal(t, objectconfig.PutPoolSizeDefault, objectconfig.Put(empty).PoolSizeRemote()) require.Equal(t, objectconfig.PutPoolSizeDefault, objectconfig.Put(empty).PoolSizeLocal()) require.EqualValues(t, objectconfig.DefaultTombstoneLifetime, objectconfig.TombstoneLifetime(empty)) + require.False(t, objectconfig.Put(empty).SkipSessionTokenIssuerVerification()) }) const path = "../../../../config/example/node" @@ -24,6 +25,7 @@ func TestObjectSection(t *testing.T) { require.Equal(t, 100, objectconfig.Put(c).PoolSizeRemote()) require.Equal(t, 200, objectconfig.Put(c).PoolSizeLocal()) require.EqualValues(t, 10, objectconfig.TombstoneLifetime(c)) + require.True(t, objectconfig.Put(c).SkipSessionTokenIssuerVerification()) } configtest.ForEachFileType(path, fileConfigTest) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 84411d31b1..34847e36f7 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -160,8 +160,9 @@ func initObjectService(c *cfg) { addPolicer(c, keyStorage, c.bgClientCache) traverseGen := util.NewTraverserGenerator(c.netMapSource, c.cfgObject.cnrSource, c) + irFetcher := newCachedIRFetcher(createInnerRingFetcher(c)) - sPut := createPutSvc(c, keyStorage) + sPut := createPutSvc(c, keyStorage, &irFetcher) sPutV2 := createPutSvcV2(sPut, keyStorage) @@ -184,7 +185,7 @@ func initObjectService(c *cfg) { splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2) - aclSvc := createACLServiceV2(c, splitSvc) + aclSvc := createACLServiceV2(c, splitSvc, &irFetcher) var commonSvc objectService.Common commonSvc.Init(&c.internals, aclSvc) @@ -295,7 +296,7 @@ func createReplicator(c *cfg, keyStorage *util.KeyStorage, cache *cache.ClientCa ) } -func createPutSvc(c *cfg, keyStorage *util.KeyStorage) *putsvc.Service { +func createPutSvc(c *cfg, keyStorage *util.KeyStorage, irFetcher *cachedIRFetcher) *putsvc.Service { ls := c.cfgObject.cfgLocalStorage.localStorage var os putsvc.ObjectStorage = engineWithoutNotifications{ @@ -320,8 +321,10 @@ func createPutSvc(c *cfg, keyStorage *util.KeyStorage) *putsvc.Service { c.netMapSource, c, c.cfgNetmap.state, + irFetcher, putsvc.WithWorkerPools(c.cfgObject.pool.putRemote, c.cfgObject.pool.putLocal), putsvc.WithLogger(c.log), + putsvc.WithVerifySessionTokenIssuer(!c.cfgObject.skipSessionTokenIssuerVerification), ) } @@ -405,14 +408,13 @@ func createSplitService(c *cfg, sPutV2 *putsvcV2.Service, sGetV2 *getsvcV2.Servi ) } -func createACLServiceV2(c *cfg, splitSvc *objectService.TransportSplitter) v2.Service { +func createACLServiceV2(c *cfg, splitSvc *objectService.TransportSplitter, irFetcher *cachedIRFetcher) v2.Service { ls := c.cfgObject.cfgLocalStorage.localStorage - irFetcher := createInnerRingFetcher(c) return v2.New( splitSvc, c.netMapSource, - newCachedIRFetcher(irFetcher), + irFetcher, acl.NewChecker( c.cfgNetmap.state, c.cfgObject.eaclSource, diff --git a/config/example/node.env b/config/example/node.env index 7ed818ef97..fde65173b0 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -86,6 +86,7 @@ FROSTFS_REPLICATOR_POOL_SIZE=10 # Object service section FROSTFS_OBJECT_PUT_POOL_SIZE_REMOTE=100 FROSTFS_OBJECT_PUT_POOL_SIZE_LOCAL=200 +FROSTFS_OBJECT_PUT_SKIP_SESSION_TOKEN_ISSUER_VERIFICATION=true FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME=10 # Storage engine section diff --git a/config/example/node.json b/config/example/node.json index a480c4a0e1..e8455ee55f 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -130,7 +130,8 @@ }, "put": { "pool_size_remote": 100, - "pool_size_local": 200 + "pool_size_local": 200, + "skip_session_token_issuer_verification": true } }, "storage": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 39fb7714d1..2ca1b426c5 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -110,6 +110,7 @@ object: put: pool_size_remote: 100 # number of async workers for remote PUT operations pool_size_local: 200 # number of async workers for local PUT operations + skip_session_token_issuer_verification: true # session token issuer verification will be skipped if true storage: # note: shard configuration can be omitted for relay node (see `node.relay`) diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index fe6654517a..90365ceadc 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -1,20 +1,26 @@ package object import ( + "bytes" "context" "crypto/ecdsa" + "crypto/elliptic" + "crypto/sha256" "errors" "fmt" "strconv" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) // FormatValidator represents an object format validator. @@ -26,8 +32,16 @@ type FormatValidator struct { type FormatValidatorOption func(*cfg) type cfg struct { - netState netmap.State - e LockSource + netState netmap.State + e LockSource + ir InnerRing + netmap netmap.Source + containers container.Source + verifyTokenIssuer bool +} + +type InnerRing interface { + InnerRingKeys() ([][]byte, error) } // DeleteHandler is an interface of delete queue processor. @@ -159,13 +173,117 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { return v.checkOwnerKey(ownerID, key) } - if !token.Issuer().Equals(ownerID) { - return fmt.Errorf("(%T) different token issuer and object owner identifiers %s/%s", v, token.Issuer(), ownerID) + if v.verifyTokenIssuer { + signerIsIROrContainerNode, err := v.isIROrContainerNode(obj, binKey) + if err != nil { + return err + } + + if signerIsIROrContainerNode { + return nil + } + + if !token.Issuer().Equals(ownerID) { + return fmt.Errorf("(%T) different token issuer and object owner identifiers %s/%s", v, token.Issuer(), ownerID) + } + return nil } return nil } +func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey []byte) (bool, error) { + pKey, err := keys.NewPublicKeyFromBytes(signerKey, elliptic.P256()) + if err != nil { + return false, fmt.Errorf("(%T) failed to unmarshal signer public key: %w", v, err) + } + + isIR, err := v.isInnerRingKey(pKey.Bytes()) + if err != nil { + return false, fmt.Errorf("(%T) failed to check if signer is inner ring node: %w", v, err) + } + if isIR { + return true, nil + } + + isContainerNode, err := v.isContainerNode(pKey.Bytes(), obj) + if err != nil { + return false, fmt.Errorf("(%T) failed to check if signer is container node: %w", v, err) + } + return isContainerNode, nil +} + +func (v *FormatValidator) isInnerRingKey(key []byte) (bool, error) { + innerRingKeys, err := v.ir.InnerRingKeys() + if err != nil { + return false, err + } + + for i := range innerRingKeys { + if bytes.Equal(innerRingKeys[i], key) { + return true, nil + } + } + + return false, nil +} + +func (v *FormatValidator) isContainerNode(key []byte, obj *objectSDK.Object) (bool, error) { + cnrID, containerIDSet := obj.ContainerID() + if !containerIDSet { + return false, errNilCID + } + + cnrIDBin := make([]byte, sha256.Size) + cnrID.Encode(cnrIDBin) + + cnr, err := v.containers.Get(cnrID) + if err != nil { + return false, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err) + } + + lastNetmap, err := netmap.GetLatestNetworkMap(v.netmap) + if err != nil { + return false, fmt.Errorf("failed to get latest netmap: %w", err) + } + + isContainerNode, err := v.isContainerNodeKey(lastNetmap, cnr, cnrIDBin, key) + if err != nil { + return false, fmt.Errorf("failed to check latest netmap for container nodes: %w", err) + } + if isContainerNode { + return true, nil + } + + previousNetmap, err := netmap.GetPreviousNetworkMap(v.netmap) + if err != nil { + return false, fmt.Errorf("failed to get previous netmap: %w", err) + } + + isContainerNode, err = v.isContainerNodeKey(previousNetmap, cnr, cnrIDBin, key) + if err != nil { + return false, fmt.Errorf("failed to check previous netmap for container nodes: %w", err) + } + return isContainerNode, nil +} + +func (v *FormatValidator) isContainerNodeKey(nm *netmapSDK.NetMap, cnr *container.Container, cnrIDBin, key []byte) (bool, error) { + cnrVectors, err := nm.ContainerNodes(cnr.Value.PlacementPolicy(), cnrIDBin) + if err != nil { + return false, err + } + + for i := range cnrVectors { + for j := range cnrVectors[i] { + if bytes.Equal(cnrVectors[i][j].PublicKey(), key) { + return true, nil + } + } + } + + return false, nil +} + func (v *FormatValidator) checkOwnerKey(id user.ID, key frostfsecdsa.PublicKey) error { var id2 user.ID user.IDFromKey(&id2, (ecdsa.PublicKey)(key)) @@ -387,3 +505,31 @@ func WithLockSource(e LockSource) FormatValidatorOption { c.e = e } } + +// WithInnerRing return option to set Inner Ring source. +func WithInnerRing(ir InnerRing) FormatValidatorOption { + return func(c *cfg) { + c.ir = ir + } +} + +// WithNetmapSource return option to set Netmap source. +func WithNetmapSource(ns netmap.Source) FormatValidatorOption { + return func(c *cfg) { + c.netmap = ns + } +} + +// WithContainersSource return option to set Containers source. +func WithContainersSource(cs container.Source) FormatValidatorOption { + return func(c *cfg) { + c.containers = cs + } +} + +// WithVerifySessionTokenIssuer return option to set verify session token issuer value. +func WithVerifySessionTokenIssuer(verifySessionTokenIssuer bool) FormatValidatorOption { + return func(c *cfg) { + c.verifyTokenIssuer = verifySessionTokenIssuer + } +} diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index 392ecf6051..fbd82906d2 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -3,12 +3,17 @@ package object import ( "context" "crypto/ecdsa" + "fmt" "strconv" "testing" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -106,34 +111,6 @@ func TestFormatValidator_Validate(t *testing.T) { require.NoError(t, v.Validate(context.Background(), obj, false)) }) - t.Run("invalid w/ session token", func(t *testing.T) { - var idOwner user.ID - user.IDFromKey(&idOwner, ownerKey.PrivateKey.PublicKey) - - var randomUserID user.ID - randPrivKey, err := keys.NewPrivateKey() - require.NoError(t, err) - user.IDFromKey(&randomUserID, randPrivKey.PrivateKey.PublicKey) - - tok := sessiontest.Object() - fsPubKey := frostfsecdsa.PublicKey(*ownerKey.PublicKey()) - tok.SetID(uuid.New()) - tok.SetAuthKey(&fsPubKey) - tok.SetExp(100500) - tok.SetIat(1) - tok.SetNbf(1) - err = tok.Sign(ownerKey.PrivateKey) - require.NoError(t, err) - - obj := objectSDK.New() - obj.SetContainerID(cidtest.ID()) - obj.SetSessionToken(tok) - obj.SetOwnerID(&randomUserID) - require.NoError(t, objectSDK.SetIDWithSignature(ownerKey.PrivateKey, obj)) - - require.Error(t, v.Validate(context.Background(), obj, false)) //invalid owner - }) - t.Run("correct w/o session token", func(t *testing.T) { obj := blankValidObject(&ownerKey.PrivateKey) @@ -284,3 +261,334 @@ func TestFormatValidator_Validate(t *testing.T) { }) }) } + +func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { + const curEpoch = 13 + + ls := testLockSource{ + m: make(map[oid.Address]bool), + } + + signer, err := keys.NewPrivateKey() + require.NoError(t, err) + + var owner user.ID + ownerPrivKey, err := keys.NewPrivateKey() + require.NoError(t, err) + user.IDFromKey(&owner, ownerPrivKey.PrivateKey.PublicKey) + + t.Run("different issuer and owner, verify issuer disabled", func(t *testing.T) { + t.Parallel() + v := NewFormatValidator( + WithNetState(testNetState{ + epoch: curEpoch, + }), + WithLockSource(ls), + WithVerifySessionTokenIssuer(false), + ) + + tok := sessiontest.Object() + fsPubKey := frostfsecdsa.PublicKey(*signer.PublicKey()) + tok.SetID(uuid.New()) + tok.SetAuthKey(&fsPubKey) + tok.SetExp(100500) + tok.SetIat(1) + tok.SetNbf(1) + require.NoError(t, tok.Sign(signer.PrivateKey)) + + obj := objectSDK.New() + obj.SetContainerID(cidtest.ID()) + obj.SetSessionToken(tok) + obj.SetOwnerID(&owner) + require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) + + require.NoError(t, v.Validate(context.Background(), obj, false)) + }) + + t.Run("different issuer and owner, issuer is IR node, verify issuer enabled", func(t *testing.T) { + t.Parallel() + v := NewFormatValidator( + WithNetState(testNetState{ + epoch: curEpoch, + }), + WithLockSource(ls), + WithVerifySessionTokenIssuer(true), + WithInnerRing(&testIRSource{ + irNodes: [][]byte{signer.PublicKey().Bytes()}, + }), + ) + + tok := sessiontest.Object() + fsPubKey := frostfsecdsa.PublicKey(*signer.PublicKey()) + tok.SetID(uuid.New()) + tok.SetAuthKey(&fsPubKey) + tok.SetExp(100500) + tok.SetIat(1) + tok.SetNbf(1) + require.NoError(t, tok.Sign(signer.PrivateKey)) + + obj := objectSDK.New() + obj.SetContainerID(cidtest.ID()) + obj.SetSessionToken(tok) + obj.SetOwnerID(&owner) + require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) + + require.NoError(t, v.Validate(context.Background(), obj, false)) + }) + + t.Run("different issuer and owner, issuer is container node in current epoch, verify issuer enabled", func(t *testing.T) { + t.Parallel() + + tok := sessiontest.Object() + fsPubKey := frostfsecdsa.PublicKey(*signer.PublicKey()) + tok.SetID(uuid.New()) + tok.SetAuthKey(&fsPubKey) + tok.SetExp(100500) + tok.SetIat(1) + tok.SetNbf(1) + require.NoError(t, tok.Sign(signer.PrivateKey)) + + cnrID := cidtest.ID() + cont := containerSDK.Container{} + cont.Init() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + cont.SetPlacementPolicy(pp) + + var node netmap.NodeInfo + node.SetPublicKey(signer.PublicKey().Bytes()) + currentEpochNM := &netmap.NetMap{} + currentEpochNM.SetEpoch(curEpoch) + currentEpochNM.SetNodes([]netmap.NodeInfo{node}) + + obj := objectSDK.New() + obj.SetContainerID(cnrID) + obj.SetSessionToken(tok) + obj.SetOwnerID(&owner) + require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) + + v := NewFormatValidator( + WithNetState(testNetState{ + epoch: curEpoch, + }), + WithLockSource(ls), + WithVerifySessionTokenIssuer(true), + WithInnerRing(&testIRSource{ + irNodes: [][]byte{}, + }), + WithContainersSource( + &testContainerSource{ + containers: map[cid.ID]*container.Container{ + cnrID: { + Value: cont, + }, + }, + }, + ), + WithNetmapSource( + &testNetmapSource{ + netmaps: map[uint64]*netmap.NetMap{ + curEpoch: currentEpochNM, + }, + currentEpoch: curEpoch, + }, + ), + ) + + require.NoError(t, v.Validate(context.Background(), obj, false)) + }) + + t.Run("different issuer and owner, issuer is container node in previous epoch, verify issuer enabled", func(t *testing.T) { + t.Parallel() + + tok := sessiontest.Object() + fsPubKey := frostfsecdsa.PublicKey(*signer.PublicKey()) + tok.SetID(uuid.New()) + tok.SetAuthKey(&fsPubKey) + tok.SetExp(100500) + tok.SetIat(1) + tok.SetNbf(1) + require.NoError(t, tok.Sign(signer.PrivateKey)) + + cnrID := cidtest.ID() + cont := containerSDK.Container{} + cont.Init() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + cont.SetPlacementPolicy(pp) + + var issuerNode netmap.NodeInfo + issuerNode.SetPublicKey(signer.PublicKey().Bytes()) + + var nonIssuerNode netmap.NodeInfo + nonIssuerKey, err := keys.NewPrivateKey() + require.NoError(t, err) + nonIssuerNode.SetPublicKey(nonIssuerKey.PublicKey().Bytes()) + + currentEpochNM := &netmap.NetMap{} + currentEpochNM.SetEpoch(curEpoch) + currentEpochNM.SetNodes([]netmap.NodeInfo{nonIssuerNode}) + + previousEpochNM := &netmap.NetMap{} + previousEpochNM.SetEpoch(curEpoch - 1) + previousEpochNM.SetNodes([]netmap.NodeInfo{issuerNode}) + + obj := objectSDK.New() + obj.SetContainerID(cnrID) + obj.SetSessionToken(tok) + obj.SetOwnerID(&owner) + require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) + + v := NewFormatValidator( + WithNetState(testNetState{ + epoch: curEpoch, + }), + WithLockSource(ls), + WithVerifySessionTokenIssuer(true), + WithInnerRing(&testIRSource{ + irNodes: [][]byte{}, + }), + WithContainersSource( + &testContainerSource{ + containers: map[cid.ID]*container.Container{ + cnrID: { + Value: cont, + }, + }, + }, + ), + WithNetmapSource( + &testNetmapSource{ + netmaps: map[uint64]*netmap.NetMap{ + curEpoch: currentEpochNM, + curEpoch - 1: previousEpochNM, + }, + currentEpoch: curEpoch, + }, + ), + ) + + require.NoError(t, v.Validate(context.Background(), obj, false)) + }) + + t.Run("different issuer and owner, issuer is unknown, verify issuer enabled", func(t *testing.T) { + t.Parallel() + + tok := sessiontest.Object() + fsPubKey := frostfsecdsa.PublicKey(*signer.PublicKey()) + tok.SetID(uuid.New()) + tok.SetAuthKey(&fsPubKey) + tok.SetExp(100500) + tok.SetIat(1) + tok.SetNbf(1) + require.NoError(t, tok.Sign(signer.PrivateKey)) + + cnrID := cidtest.ID() + cont := containerSDK.Container{} + cont.Init() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + cont.SetPlacementPolicy(pp) + + var nonIssuerNode1 netmap.NodeInfo + nonIssuerKey1, err := keys.NewPrivateKey() + require.NoError(t, err) + nonIssuerNode1.SetPublicKey(nonIssuerKey1.PublicKey().Bytes()) + + var nonIssuerNode2 netmap.NodeInfo + nonIssuerKey2, err := keys.NewPrivateKey() + require.NoError(t, err) + nonIssuerNode2.SetPublicKey(nonIssuerKey2.PublicKey().Bytes()) + + currentEpochNM := &netmap.NetMap{} + currentEpochNM.SetEpoch(curEpoch) + currentEpochNM.SetNodes([]netmap.NodeInfo{nonIssuerNode1}) + + previousEpochNM := &netmap.NetMap{} + previousEpochNM.SetEpoch(curEpoch - 1) + previousEpochNM.SetNodes([]netmap.NodeInfo{nonIssuerNode2}) + + obj := objectSDK.New() + obj.SetContainerID(cnrID) + obj.SetSessionToken(tok) + obj.SetOwnerID(&owner) + require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) + + v := NewFormatValidator( + WithNetState(testNetState{ + epoch: curEpoch, + }), + WithLockSource(ls), + WithVerifySessionTokenIssuer(true), + WithInnerRing(&testIRSource{ + irNodes: [][]byte{}, + }), + WithContainersSource( + &testContainerSource{ + containers: map[cid.ID]*container.Container{ + cnrID: { + Value: cont, + }, + }, + }, + ), + WithNetmapSource( + &testNetmapSource{ + netmaps: map[uint64]*netmap.NetMap{ + curEpoch: currentEpochNM, + curEpoch - 1: previousEpochNM, + }, + currentEpoch: curEpoch, + }, + ), + ) + + require.Error(t, v.Validate(context.Background(), obj, false)) + }) +} + +type testIRSource struct { + irNodes [][]byte +} + +func (s *testIRSource) InnerRingKeys() ([][]byte, error) { + return s.irNodes, nil +} + +type testContainerSource struct { + containers map[cid.ID]*container.Container +} + +func (s *testContainerSource) Get(cnrID cid.ID) (*container.Container, error) { + if cnr, found := s.containers[cnrID]; found { + return cnr, nil + } + return nil, fmt.Errorf("container not found") +} + +func (s *testContainerSource) DeletionInfo(cid.ID) (*container.DelInfo, error) { + return nil, nil +} + +type testNetmapSource struct { + netmaps map[uint64]*netmap.NetMap + currentEpoch uint64 +} + +func (s *testNetmapSource) GetNetMap(diff uint64) (*netmap.NetMap, error) { + if diff >= s.currentEpoch { + return nil, fmt.Errorf("invalid diff") + } + return s.GetNetMapByEpoch(s.currentEpoch - diff) +} + +func (s *testNetmapSource) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { + if nm, found := s.netmaps[epoch]; found { + return nm, nil + } + return nil, fmt.Errorf("netmap not found") +} + +func (s *testNetmapSource) Epoch() (uint64, error) { + return s.currentEpoch, nil +} diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index 7f2600f9c1..4095cf1248 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -29,6 +29,14 @@ type ClientConstructor interface { Get(client.NodeInfo) (client.MultiAddressClient, error) } +type InnerRing interface { + InnerRingKeys() ([][]byte, error) +} + +type FormatValidatorConfig interface { + VerifySessionTokenIssuer() bool +} + type cfg struct { keyStorage *objutil.KeyStorage @@ -51,6 +59,8 @@ type cfg struct { clientConstructor ClientConstructor log *logger.Logger + + verifySessionTokenIssuer bool } func NewService(ks *objutil.KeyStorage, @@ -61,6 +71,7 @@ func NewService(ks *objutil.KeyStorage, ns netmap.Source, nk netmap.AnnouncedKeys, nst netmap.State, + ir InnerRing, opts ...Option) *Service { c := &cfg{ remotePool: util.NewPseudoWorkerPool(), @@ -80,7 +91,14 @@ func NewService(ks *objutil.KeyStorage, opts[i](c) } - c.fmtValidator = object.NewFormatValidator(object.WithLockSource(os), object.WithNetState(nst)) + c.fmtValidator = object.NewFormatValidator( + object.WithLockSource(os), + object.WithNetState(nst), + object.WithInnerRing(ir), + object.WithNetmapSource(ns), + object.WithContainersSource(cs), + object.WithVerifySessionTokenIssuer(c.verifySessionTokenIssuer), + ) return &Service{ cfg: c, @@ -104,3 +122,9 @@ func WithLogger(l *logger.Logger) Option { c.log = l } } + +func WithVerifySessionTokenIssuer(v bool) Option { + return func(c *cfg) { + c.verifySessionTokenIssuer = v + } +} From 55b82e744b822a60f4b84c8b389e08ad13d1cca1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 7 Aug 2023 09:54:47 +0300 Subject: [PATCH 0022/1413] [#529] objectcore: Use common sender classifier Use common sender classifier for ACL service and format validator. Signed-off-by: Dmitrii Stepanov --- pkg/core/object/fmt.go | 98 +++---------------- pkg/core/object/fmt_test.go | 27 ++++- .../object/sender_classifier.go} | 70 +++++++------ pkg/services/object/acl/v2/service.go | 19 ++-- pkg/services/object/put/service.go | 1 + 5 files changed, 95 insertions(+), 120 deletions(-) rename pkg/{services/object/acl/v2/classifier.go => core/object/sender_classifier.go} (68%) diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index 90365ceadc..e657677239 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -1,10 +1,8 @@ package object import ( - "bytes" "context" "crypto/ecdsa" - "crypto/elliptic" "crypto/sha256" "errors" "fmt" @@ -14,18 +12,20 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) // FormatValidator represents an object format validator. type FormatValidator struct { *cfg + + senderClassifier SenderClassifier } // FormatValidatorOption represents a FormatValidator constructor option. @@ -37,13 +37,10 @@ type cfg struct { ir InnerRing netmap netmap.Source containers container.Source + log *logger.Logger verifyTokenIssuer bool } -type InnerRing interface { - InnerRingKeys() ([][]byte, error) -} - // DeleteHandler is an interface of delete queue processor. type DeleteHandler interface { // DeleteObjects places objects to a removal queue. @@ -93,7 +90,8 @@ func NewFormatValidator(opts ...FormatValidatorOption) *FormatValidator { } return &FormatValidator{ - cfg: cfg, + cfg: cfg, + senderClassifier: NewSenderClassifier(cfg.ir, cfg.netmap, cfg.log), } } @@ -193,42 +191,6 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { } func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey []byte) (bool, error) { - pKey, err := keys.NewPublicKeyFromBytes(signerKey, elliptic.P256()) - if err != nil { - return false, fmt.Errorf("(%T) failed to unmarshal signer public key: %w", v, err) - } - - isIR, err := v.isInnerRingKey(pKey.Bytes()) - if err != nil { - return false, fmt.Errorf("(%T) failed to check if signer is inner ring node: %w", v, err) - } - if isIR { - return true, nil - } - - isContainerNode, err := v.isContainerNode(pKey.Bytes(), obj) - if err != nil { - return false, fmt.Errorf("(%T) failed to check if signer is container node: %w", v, err) - } - return isContainerNode, nil -} - -func (v *FormatValidator) isInnerRingKey(key []byte) (bool, error) { - innerRingKeys, err := v.ir.InnerRingKeys() - if err != nil { - return false, err - } - - for i := range innerRingKeys { - if bytes.Equal(innerRingKeys[i], key) { - return true, nil - } - } - - return false, nil -} - -func (v *FormatValidator) isContainerNode(key []byte, obj *objectSDK.Object) (bool, error) { cnrID, containerIDSet := obj.ContainerID() if !containerIDSet { return false, errNilCID @@ -242,46 +204,11 @@ func (v *FormatValidator) isContainerNode(key []byte, obj *objectSDK.Object) (bo return false, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err) } - lastNetmap, err := netmap.GetLatestNetworkMap(v.netmap) - if err != nil { - return false, fmt.Errorf("failed to get latest netmap: %w", err) - } - - isContainerNode, err := v.isContainerNodeKey(lastNetmap, cnr, cnrIDBin, key) - if err != nil { - return false, fmt.Errorf("failed to check latest netmap for container nodes: %w", err) - } - if isContainerNode { - return true, nil - } - - previousNetmap, err := netmap.GetPreviousNetworkMap(v.netmap) - if err != nil { - return false, fmt.Errorf("failed to get previous netmap: %w", err) - } - - isContainerNode, err = v.isContainerNodeKey(previousNetmap, cnr, cnrIDBin, key) - if err != nil { - return false, fmt.Errorf("failed to check previous netmap for container nodes: %w", err) - } - return isContainerNode, nil -} - -func (v *FormatValidator) isContainerNodeKey(nm *netmapSDK.NetMap, cnr *container.Container, cnrIDBin, key []byte) (bool, error) { - cnrVectors, err := nm.ContainerNodes(cnr.Value.PlacementPolicy(), cnrIDBin) + res, err := v.senderClassifier.IsInnerRingOrContainerNode(signerKey, cnrID, cnr.Value) if err != nil { return false, err } - - for i := range cnrVectors { - for j := range cnrVectors[i] { - if bytes.Equal(cnrVectors[i][j].PublicKey(), key) { - return true, nil - } - } - } - - return false, nil + return res.Role == acl.RoleContainer || res.Role == acl.RoleInnerRing, nil } func (v *FormatValidator) checkOwnerKey(id user.ID, key frostfsecdsa.PublicKey) error { @@ -533,3 +460,10 @@ func WithVerifySessionTokenIssuer(verifySessionTokenIssuer bool) FormatValidator c.verifyTokenIssuer = verifySessionTokenIssuer } } + +// WithLogger return option to set logger. +func WithLogger(l *logger.Logger) FormatValidatorOption { + return func(c *cfg) { + c.log = l + } +} diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index fbd82906d2..2a5b5690c4 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -9,6 +9,7 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" @@ -22,6 +23,7 @@ import ( "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" ) func blankValidObject(key *ecdsa.PrivateKey) *objectSDK.Object { @@ -63,6 +65,7 @@ func TestFormatValidator_Validate(t *testing.T) { epoch: curEpoch, }), WithLockSource(ls), + WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), ) ownerKey, err := keys.NewPrivateKey() @@ -285,6 +288,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { }), WithLockSource(ls), WithVerifySessionTokenIssuer(false), + WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), ) tok := sessiontest.Object() @@ -307,6 +311,14 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { t.Run("different issuer and owner, issuer is IR node, verify issuer enabled", func(t *testing.T) { t.Parallel() + + cnrID := cidtest.ID() + cont := containerSDK.Container{} + cont.Init() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + cont.SetPlacementPolicy(pp) + v := NewFormatValidator( WithNetState(testNetState{ epoch: curEpoch, @@ -316,6 +328,16 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { WithInnerRing(&testIRSource{ irNodes: [][]byte{signer.PublicKey().Bytes()}, }), + WithContainersSource( + &testContainerSource{ + containers: map[cid.ID]*container.Container{ + cnrID: { + Value: cont, + }, + }, + }, + ), + WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), ) tok := sessiontest.Object() @@ -328,7 +350,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { require.NoError(t, tok.Sign(signer.PrivateKey)) obj := objectSDK.New() - obj.SetContainerID(cidtest.ID()) + obj.SetContainerID(cnrID) obj.SetSessionToken(tok) obj.SetOwnerID(&owner) require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) @@ -393,6 +415,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { currentEpoch: curEpoch, }, ), + WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), ) require.NoError(t, v.Validate(context.Background(), obj, false)) @@ -466,6 +489,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { currentEpoch: curEpoch, }, ), + WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), ) require.NoError(t, v.Validate(context.Background(), obj, false)) @@ -541,6 +565,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { currentEpoch: curEpoch, }, ), + WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), ) require.Error(t, v.Validate(context.Background(), obj, false)) diff --git a/pkg/services/object/acl/v2/classifier.go b/pkg/core/object/sender_classifier.go similarity index 68% rename from pkg/services/object/acl/v2/classifier.go rename to pkg/core/object/sender_classifier.go index cdc5fb6234..79bf12ce39 100644 --- a/pkg/services/object/acl/v2/classifier.go +++ b/pkg/core/object/sender_classifier.go @@ -1,4 +1,4 @@ -package v2 +package object import ( "bytes" @@ -11,50 +11,64 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.uber.org/zap" ) -type senderClassifier struct { +type InnerRing interface { + InnerRingKeys() ([][]byte, error) +} + +type SenderClassifier struct { log *logger.Logger - innerRing InnerRingFetcher + innerRing InnerRing netmap core.Source } -type classifyResult struct { - role acl.Role - key []byte +func NewSenderClassifier(innerRing InnerRing, netmap core.Source, log *logger.Logger) SenderClassifier { + return SenderClassifier{ + log: log, + innerRing: innerRing, + netmap: netmap, + } } -func (c senderClassifier) classify( - req MetaWithToken, - idCnr cid.ID, - cnr container.Container) (res *classifyResult, err error) { - ownerID, ownerKey, err := req.RequestOwner() - if err != nil { - return nil, err - } +type ClassifyResult struct { + Role acl.Role + Key []byte +} +func (c SenderClassifier) Classify( + ownerID *user.ID, + ownerKey *keys.PublicKey, + idCnr cid.ID, + cnr container.Container) (res *ClassifyResult, err error) { ownerKeyInBytes := ownerKey.Bytes() // TODO: #767 get owner from frostfs.id if present // if request owner is the same as container owner, return RoleUser if ownerID.Equals(cnr.Owner()) { - return &classifyResult{ - role: acl.RoleOwner, - key: ownerKeyInBytes, + return &ClassifyResult{ + Role: acl.RoleOwner, + Key: ownerKeyInBytes, }, nil } + return c.IsInnerRingOrContainerNode(ownerKeyInBytes, idCnr, cnr) +} + +func (c SenderClassifier) IsInnerRingOrContainerNode(ownerKeyInBytes []byte, idCnr cid.ID, cnr container.Container) (*ClassifyResult, error) { isInnerRingNode, err := c.isInnerRingKey(ownerKeyInBytes) if err != nil { // do not throw error, try best case matching c.log.Debug(logs.V2CantCheckIfRequestFromInnerRing, zap.String("error", err.Error())) } else if isInnerRingNode { - return &classifyResult{ - role: acl.RoleInnerRing, - key: ownerKeyInBytes, + return &ClassifyResult{ + Role: acl.RoleInnerRing, + Key: ownerKeyInBytes, }, nil } @@ -69,20 +83,20 @@ func (c senderClassifier) classify( c.log.Debug(logs.V2CantCheckIfRequestFromContainerNode, zap.String("error", err.Error())) } else if isContainerNode { - return &classifyResult{ - role: acl.RoleContainer, - key: ownerKeyInBytes, + return &ClassifyResult{ + Role: acl.RoleContainer, + Key: ownerKeyInBytes, }, nil } // if none of above, return RoleOthers - return &classifyResult{ - role: acl.RoleOthers, - key: ownerKeyInBytes, + return &ClassifyResult{ + Role: acl.RoleOthers, + Key: ownerKeyInBytes, }, nil } -func (c senderClassifier) isInnerRingKey(owner []byte) (bool, error) { +func (c SenderClassifier) isInnerRingKey(owner []byte) (bool, error) { innerRingKeys, err := c.innerRing.InnerRingKeys() if err != nil { return false, err @@ -98,7 +112,7 @@ func (c senderClassifier) isInnerRingKey(owner []byte) (bool, error) { return false, nil } -func (c senderClassifier) isContainerKey( +func (c SenderClassifier) isContainerKey( owner, idCnr []byte, cnr container.Container) (bool, error) { nm, err := core.GetLatestNetworkMap(c.netmap) // first check current netmap diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 271c4d20bc..8239403a78 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -24,7 +25,7 @@ import ( type Service struct { *cfg - c senderClassifier + c objectCore.SenderClassifier } type putStreamBasicChecker struct { @@ -95,11 +96,7 @@ func New(next object.ServiceServer, return Service{ cfg: cfg, - c: senderClassifier{ - log: cfg.log, - innerRing: cfg.irFetcher, - netmap: cfg.nm, - }, + c: objectCore.NewSenderClassifier(cfg.irFetcher, cfg.nm, cfg.log), } } @@ -652,20 +649,24 @@ func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (in } // find request role and key - res, err := b.c.classify(req, idCnr, cnr.Value) + ownerID, ownerKey, err := req.RequestOwner() + if err != nil { + return info, err + } + res, err := b.c.Classify(ownerID, ownerKey, idCnr, cnr.Value) if err != nil { return info, err } info.basicACL = cnr.Value.BasicACL() - info.requestRole = res.role + info.requestRole = res.Role info.operation = op info.cnrOwner = cnr.Value.Owner() info.idCnr = idCnr // it is assumed that at the moment the key will be valid, // otherwise the request would not pass validation - info.senderKey = res.key + info.senderKey = res.Key // add bearer token if it is present in request info.bearer = req.bearer diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index 4095cf1248..3a7dcefd6d 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -98,6 +98,7 @@ func NewService(ks *objutil.KeyStorage, object.WithNetmapSource(ns), object.WithContainersSource(cs), object.WithVerifySessionTokenIssuer(c.verifySessionTokenIssuer), + object.WithLogger(c.log), ) return &Service{ From a724debb199c9a4b28473a5847979495cd99dd35 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 29 Aug 2023 12:41:45 +0300 Subject: [PATCH 0023/1413] [#632] .forgejo: Print --version Signed-off-by: Evgenii Stratonikov --- .forgejo/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 51f63e5a50..3c74d94347 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -24,6 +24,7 @@ jobs: - name: Build CLI run: make bin/frostfs-cli + - run: bin/frostfs-cli --version - name: Build NODE run: make bin/frostfs-node @@ -33,6 +34,8 @@ jobs: - name: Build ADM run: make bin/frostfs-adm + - run: bin/frostfs-adm --version - name: Build LENS run: make bin/frostfs-lens + - run: bin/frostfs-lens --version From 7654847f79265ca6663eea1224d2e4da546a9215 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 29 Aug 2023 13:41:57 +0300 Subject: [PATCH 0024/1413] [#659] adm: Remove nspcc.ru from the default email Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/deploy.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/initialize_nns.go | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index a9098891c0..a4b9454383 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -145,12 +145,12 @@ func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domai emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, zone, c.CommitteeAcc.Contract.ScriptHash(), - "ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, domain, c.CommitteeAcc.Contract.ScriptHash(), - "ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) } else { s, ok, err := c.nnsRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 15657a6d9e..6758b4dd8e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -27,6 +27,8 @@ import ( const defaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second +const frostfsOpsEmail = "ops@frostfs.info" + func (c *initializeContext) setNNS() error { nnsCs, err := c.Client.GetContractStateByID(1) if err != nil { @@ -40,7 +42,7 @@ func (c *initializeContext) setNNS() error { bw := io.NewBufBinWriter() emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, "frostfs", c.CommitteeAcc.Contract.ScriptHash(), - "ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) if err := c.sendCommitteeTx(bw.Bytes(), true); err != nil { return fmt.Errorf("can't add domain root to NNS: %w", err) @@ -122,7 +124,7 @@ func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHas if isAvail { emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, morphClient.NNSGroupKeyName, c.CommitteeAcc.Contract.ScriptHash(), - "ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) } @@ -170,7 +172,7 @@ func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.U bw := io.NewBufBinWriter() emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, domain, c.CommitteeAcc.Contract.ScriptHash(), - "ops@nspcc.ru", int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) if bw.Err != nil { From 91f3745b58cfc551d17e4048a275df7509eb46b7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 29 Aug 2023 13:43:26 +0300 Subject: [PATCH 0025/1413] [#659] debian: Remove nspcc email Signed-off-by: Evgenii Stratonikov --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 575a27e334..f3f214bcaf 100644 --- a/debian/control +++ b/debian/control @@ -1,7 +1,7 @@ Source: frostfs-node Section: misc Priority: optional -Maintainer: NeoSPCC +Maintainer: TrueCloudLab Build-Depends: debhelper-compat (= 13), dh-sequence-bash-completion, devscripts Standards-Version: 4.5.1 Homepage: https://fs.neo.org/ From fe5aa06a75a3afa36a2fd304e6f791d493284b35 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 30 Aug 2023 13:43:43 +0300 Subject: [PATCH 0026/1413] [#665] node: Bind length of copies number to number of replicas Allow to use one digit in copies number array for backward compatibility. Signed-off-by: Anton Nikiforov --- .../object_manager/placement/traverser.go | 8 +++++++ .../placement/traverser_test.go | 21 ++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index ad10770479..dc9ab5e7a8 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -58,6 +58,9 @@ var errNilBuilder = errors.New("placement builder is nil") var errNilPolicy = errors.New("placement policy is nil") +var errCopiesNumberLen = errors.New("copies number accepts only one number or array with length " + + "equal to length of replicas") + func defaultCfg() *cfg { return &cfg{ trackCopies: true, @@ -74,6 +77,11 @@ func NewTraverser(opts ...Option) (*Traverser, error) { } } + cnLen := len(cfg.copyNumbers) + if cnLen > 0 && cnLen != 1 && cnLen != cfg.policy.NumberOfReplicas() { + return nil, errCopiesNumberLen + } + if cfg.builder == nil { return nil, fmt.Errorf("%s: %w", invalidOptsMsg, errNilBuilder) } else if !cfg.policySet { diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index e16f337593..9b70efc73b 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -220,6 +220,7 @@ func TestTraverserRemValues(t *testing.T) { name string copyNumbers []uint32 expectedRem []int + expectedErr error }{ { name: "zero copy numbers", @@ -231,11 +232,6 @@ func TestTraverserRemValues(t *testing.T) { copyNumbers: []uint32{0}, expectedRem: replicas, }, - { - name: "compatible zero copy numbers, len 2", - copyNumbers: []uint32{0, 0}, - expectedRem: replicas, - }, { name: "compatible zero copy numbers, len 3", copyNumbers: []uint32{0, 0, 0}, @@ -253,9 +249,14 @@ func TestTraverserRemValues(t *testing.T) { }, { name: "multiple copy numbers for multiple replicas", - copyNumbers: []uint32{1, 1}, + copyNumbers: []uint32{1, 1, 4}, expectedRem: []int{1, 1, 4}, }, + { + name: "incompatible copies number vector", + copyNumbers: []uint32{1, 1}, + expectedErr: errCopiesNumberLen, + }, } for _, testCase := range testCases { @@ -265,8 +266,12 @@ func TestTraverserRemValues(t *testing.T) { UseBuilder(&testBuilder{vectors: nodesCopy}), WithCopyNumbers(testCase.copyNumbers), ) - require.NoError(t, err) - require.Equal(t, testCase.expectedRem, tr.rem) + if testCase.expectedErr == nil { + require.NoError(t, err, testCase.name) + require.Equal(t, testCase.expectedRem, tr.rem, testCase.name) + } else { + require.Error(t, err, testCase.expectedErr, testCase.name) + } }) } } From 1daef2ceeb44efe26d4f1a4f4c6d59fe3891c6a6 Mon Sep 17 00:00:00 2001 From: Alejandro Lopez Date: Tue, 29 Aug 2023 15:26:22 +0300 Subject: [PATCH 0027/1413] [#660] writecache: Fix remaining addr2key uses Signed-off-by: Alejandro Lopez --- .../writecache/writecachebadger/delete.go | 8 ++++---- .../writecache/writecachebadger/flush_test.go | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/writecache/writecachebadger/delete.go b/pkg/local_object_storage/writecache/writecachebadger/delete.go index f37371098f..afab785479 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/delete.go +++ b/pkg/local_object_storage/writecache/writecachebadger/delete.go @@ -39,10 +39,10 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { return writecache.ErrReadOnly } - saddr := addr.EncodeToString() + key := addr2key(addr) err := c.db.Update(func(tx *badger.Txn) error { - it, err := tx.Get([]byte(saddr)) + it, err := tx.Get(key[:]) if err != nil { if err == badger.ErrKeyNotFound { return logicerr.Wrap(new(apistatus.ObjectNotFound)) @@ -51,10 +51,10 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { } if it.ValueSize() > 0 { storageType = writecache.StorageTypeDB - err := tx.Delete([]byte(saddr)) + err := tx.Delete(key[:]) if err == nil { storagelog.Write(c.log, - storagelog.AddressField(saddr), + storagelog.AddressField(addr.EncodeToString()), storagelog.StorageTypeField(wcStorageType), storagelog.OpField("db DELETE"), ) diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go index 19bc156148..855d2214ff 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go @@ -52,8 +52,9 @@ func TestFlush(t *testing.T) { Desc: "db, invalid object", InjectFn: func(t *testing.T, wc writecache.Cache) { c := wc.(*cache) + key := addr2key(oidtest.Address()) require.NoError(t, c.db.Update(func(tx *badger.Txn) error { - return tx.Set([]byte(oidtest.Address().EncodeToString()), []byte{1, 2, 3}) + return tx.Set(key[:], []byte{1, 2, 3}) })) }, }, From 806cc13d9f49a48a22c09f170127bff326019a8a Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 29 Aug 2023 13:25:54 +0300 Subject: [PATCH 0028/1413] [#658] client: Refactor PrmObjectGet/Head/Range usage Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/client.go | 96 +++++++------------ go.mod | 2 +- go.sum | 4 +- pkg/services/object/internal/client/client.go | 86 +++++++---------- 4 files changed, 73 insertions(+), 115 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 0c6d2a38d5..22ca0aa7d3 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -563,28 +563,19 @@ func (x GetObjectRes) Header() *objectSDK.Object { // Returns any error which prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. func GetObject(ctx context.Context, prm GetObjectPrm) (*GetObjectRes, error) { - var getPrm client.PrmObjectGet - getPrm.FromContainer(prm.objAddr.Container()) - getPrm.ByID(prm.objAddr.Object()) + cnr := prm.objAddr.Container() + obj := prm.objAddr.Object() - if prm.sessionToken != nil { - getPrm.WithinSession(*prm.sessionToken) + getPrm := client.PrmObjectGet{ + XHeaders: prm.xHeaders, + BearerToken: prm.bearerToken, + Session: prm.sessionToken, + Raw: prm.raw, + Local: prm.local, + ContainerID: &cnr, + ObjectID: &obj, } - if prm.bearerToken != nil { - getPrm.WithBearerToken(*prm.bearerToken) - } - - if prm.raw { - getPrm.MarkRaw() - } - - if prm.local { - getPrm.MarkLocal() - } - - getPrm.WithXHeaders(prm.xHeaders...) - rdr, err := prm.cli.ObjectGetInit(ctx, getPrm) if err != nil { return nil, fmt.Errorf("init object reading on client: %w", err) @@ -639,29 +630,20 @@ func (x HeadObjectRes) Header() *objectSDK.Object { // Returns any error which prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. func HeadObject(ctx context.Context, prm HeadObjectPrm) (*HeadObjectRes, error) { - var cliPrm client.PrmObjectHead - cliPrm.FromContainer(prm.objAddr.Container()) - cliPrm.ByID(prm.objAddr.Object()) + cnr := prm.objAddr.Container() + obj := prm.objAddr.Object() - if prm.sessionToken != nil { - cliPrm.WithinSession(*prm.sessionToken) + headPrm := client.PrmObjectHead{ + XHeaders: prm.xHeaders, + BearerToken: prm.bearerToken, + Session: prm.sessionToken, + Raw: prm.raw, + Local: prm.local, + ContainerID: &cnr, + ObjectID: &obj, } - if prm.bearerToken != nil { - cliPrm.WithBearerToken(*prm.bearerToken) - } - - if prm.raw { - cliPrm.MarkRaw() - } - - if prm.local { - cliPrm.MarkLocal() - } - - cliPrm.WithXHeaders(prm.xHeaders...) - - res, err := prm.cli.ObjectHead(ctx, cliPrm) + res, err := prm.cli.ObjectHead(ctx, headPrm) if err != nil { return nil, fmt.Errorf("read object header via client: %w", err) } @@ -862,32 +844,22 @@ type PayloadRangeRes struct{} // Returns any error which prevented the operation from completing correctly in error return. // For raw reading, returns *object.SplitInfoError error if object is virtual. func PayloadRange(ctx context.Context, prm PayloadRangePrm) (*PayloadRangeRes, error) { - var cliPrm client.PrmObjectRange - cliPrm.FromContainer(prm.objAddr.Container()) - cliPrm.ByID(prm.objAddr.Object()) + cnr := prm.objAddr.Container() + obj := prm.objAddr.Object() - if prm.sessionToken != nil { - cliPrm.WithinSession(*prm.sessionToken) + rangePrm := client.PrmObjectRange{ + XHeaders: prm.xHeaders, + BearerToken: prm.bearerToken, + Session: prm.sessionToken, + Raw: prm.raw, + Local: prm.local, + ContainerID: &cnr, + ObjectID: &obj, + Offset: prm.rng.GetOffset(), + Length: prm.rng.GetLength(), } - if prm.bearerToken != nil { - cliPrm.WithBearerToken(*prm.bearerToken) - } - - if prm.raw { - cliPrm.MarkRaw() - } - - if prm.local { - cliPrm.MarkLocal() - } - - cliPrm.SetOffset(prm.rng.GetOffset()) - cliPrm.SetLength(prm.rng.GetLength()) - - cliPrm.WithXHeaders(prm.xHeaders...) - - rdr, err := prm.cli.ObjectRangeInit(ctx, cliPrm) + rdr, err := prm.cli.ObjectRangeInit(ctx, rangePrm) if err != nil { return nil, fmt.Errorf("init payload reading: %w", err) } diff --git a/go.mod b/go.mod index 46639d49cb..cbe20e39fe 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230802075510-964c3edb3f44 git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230627134746-36f3d39c406a git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230821090303-202412230a05 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230828082657-84e7e69f98ac git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 58f1fb2174..4b5e401741 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230821090303-202412230a05 h1:OuViMF54N87FXmaBEpYw3jhzaLrJ/EWOlPL1wUkimE0= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230821090303-202412230a05/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230828082657-84e7e69f98ac h1:BRmJd04eUgzmdLe/2I0Ok/LNOkTyEAPymYUrCCF0a1U= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230828082657-84e7e69f98ac/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index 73f4ff7c45..0301a593a6 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -88,7 +88,7 @@ func (x *readPrmCommon) SetNetmapEpoch(_ uint64) { type GetObjectPrm struct { readPrmCommon - cliPrm client.PrmObjectGet + ClientParams client.PrmObjectGet obj oid.ID } @@ -97,7 +97,7 @@ type GetObjectPrm struct { // // By default request will not be raw. func (x *GetObjectPrm) SetRawFlag() { - x.cliPrm.MarkRaw() + x.ClientParams.Raw = true } // SetAddress sets object address. @@ -105,8 +105,10 @@ func (x *GetObjectPrm) SetRawFlag() { // Required parameter. func (x *GetObjectPrm) SetAddress(addr oid.Address) { x.obj = addr.Object() - x.cliPrm.FromContainer(addr.Container()) - x.cliPrm.ByID(x.obj) + cnr := addr.Container() + + x.ClientParams.ContainerID = &cnr + x.ClientParams.ObjectID = &x.obj } // GetObjectRes groups the resulting values of GetObject operation. @@ -134,23 +136,15 @@ func GetObject(ctx context.Context, prm GetObjectPrm) (*GetObjectRes, error) { // request will almost definitely fail. The case can occur, for example, // when session is bound to the parent object and child object is requested. if prm.tokenSession != nil && prm.tokenSession.AssertObject(prm.obj) { - prm.cliPrm.WithinSession(*prm.tokenSession) + prm.ClientParams.Session = prm.tokenSession } - if prm.tokenBearer != nil { - prm.cliPrm.WithBearerToken(*prm.tokenBearer) - } + prm.ClientParams.XHeaders = prm.xHeaders + prm.ClientParams.BearerToken = prm.tokenBearer + prm.ClientParams.Local = prm.local + prm.ClientParams.Key = prm.key - if prm.local { - prm.cliPrm.MarkLocal() - } - - prm.cliPrm.WithXHeaders(prm.xHeaders...) - if prm.key != nil { - prm.cliPrm.UseKey(*prm.key) - } - - rdr, err := prm.cli.ObjectGetInit(ctx, prm.cliPrm) + rdr, err := prm.cli.ObjectGetInit(ctx, prm.ClientParams) if err != nil { return nil, fmt.Errorf("init object reading: %w", err) } @@ -187,7 +181,7 @@ func GetObject(ctx context.Context, prm GetObjectPrm) (*GetObjectRes, error) { type HeadObjectPrm struct { readPrmCommon - cliPrm client.PrmObjectHead + ClientParams client.PrmObjectHead obj oid.ID } @@ -196,7 +190,7 @@ type HeadObjectPrm struct { // // By default request will not be raw. func (x *HeadObjectPrm) SetRawFlag() { - x.cliPrm.MarkRaw() + x.ClientParams.Raw = true } // SetAddress sets object address. @@ -204,8 +198,10 @@ func (x *HeadObjectPrm) SetRawFlag() { // Required parameter. func (x *HeadObjectPrm) SetAddress(addr oid.Address) { x.obj = addr.Object() - x.cliPrm.FromContainer(addr.Container()) - x.cliPrm.ByID(x.obj) + cnr := addr.Container() + + x.ClientParams.ContainerID = &cnr + x.ClientParams.ObjectID = &x.obj } // HeadObjectRes groups the resulting values of GetObject operation. @@ -230,22 +226,16 @@ func (x HeadObjectRes) Header() *objectSDK.Object { // // HeadObject ignores the provided session if it is not related to the requested objectSDK. func HeadObject(ctx context.Context, prm HeadObjectPrm) (*HeadObjectRes, error) { - if prm.local { - prm.cliPrm.MarkLocal() - } - // see details in same statement of GetObject if prm.tokenSession != nil && prm.tokenSession.AssertObject(prm.obj) { - prm.cliPrm.WithinSession(*prm.tokenSession) + prm.ClientParams.Session = prm.tokenSession } - if prm.tokenBearer != nil { - prm.cliPrm.WithBearerToken(*prm.tokenBearer) - } + prm.ClientParams.BearerToken = prm.tokenBearer + prm.ClientParams.Local = prm.local + prm.ClientParams.XHeaders = prm.xHeaders - prm.cliPrm.WithXHeaders(prm.xHeaders...) - - cliRes, err := prm.cli.ObjectHead(ctx, prm.cliPrm) + cliRes, err := prm.cli.ObjectHead(ctx, prm.ClientParams) if err == nil { // pull out an error from status err = apistatus.ErrFromStatus(cliRes.Status()) @@ -272,7 +262,7 @@ type PayloadRangePrm struct { ln uint64 - cliPrm client.PrmObjectRange + ClientParams client.PrmObjectRange obj oid.ID } @@ -281,7 +271,7 @@ type PayloadRangePrm struct { // // By default request will not be raw. func (x *PayloadRangePrm) SetRawFlag() { - x.cliPrm.MarkRaw() + x.ClientParams.Raw = true } // SetAddress sets object address. @@ -289,15 +279,17 @@ func (x *PayloadRangePrm) SetRawFlag() { // Required parameter. func (x *PayloadRangePrm) SetAddress(addr oid.Address) { x.obj = addr.Object() - x.cliPrm.FromContainer(addr.Container()) - x.cliPrm.ByID(x.obj) + cnr := addr.Container() + + x.ClientParams.ContainerID = &cnr + x.ClientParams.ObjectID = &x.obj } // SetRange range of the object payload to be read. // // Required parameter. func (x *PayloadRangePrm) SetRange(rng *objectSDK.Range) { - x.cliPrm.SetOffset(rng.GetOffset()) + x.ClientParams.Offset = rng.GetOffset() x.ln = rng.GetLength() } @@ -329,23 +321,17 @@ const maxInitialBufferSize = 1024 * 1024 // 1 MiB // // PayloadRange ignores the provided session if it is not related to the requested objectSDK. func PayloadRange(ctx context.Context, prm PayloadRangePrm) (*PayloadRangeRes, error) { - if prm.local { - prm.cliPrm.MarkLocal() - } - // see details in same statement of GetObject if prm.tokenSession != nil && prm.tokenSession.AssertObject(prm.obj) { - prm.cliPrm.WithinSession(*prm.tokenSession) + prm.ClientParams.Session = prm.tokenSession } - if prm.tokenBearer != nil { - prm.cliPrm.WithBearerToken(*prm.tokenBearer) - } + prm.ClientParams.XHeaders = prm.xHeaders + prm.ClientParams.BearerToken = prm.tokenBearer + prm.ClientParams.Local = prm.local + prm.ClientParams.Length = prm.ln - prm.cliPrm.SetLength(prm.ln) - prm.cliPrm.WithXHeaders(prm.xHeaders...) - - rdr, err := prm.cli.ObjectRangeInit(ctx, prm.cliPrm) + rdr, err := prm.cli.ObjectRangeInit(ctx, prm.ClientParams) if err != nil { return nil, fmt.Errorf("init payload reading: %w", err) } From 4dff9555f15145768608b130b752b4788955a4c6 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 23 Aug 2023 10:05:40 +0300 Subject: [PATCH 0029/1413] [#568] writecache: Improve flushing scheme for badger Signed-off-by: Anton Nikiforov --- go.mod | 2 +- internal/logs/logs.go | 1 + .../writecachebadger/cachebadger.go | 9 +- .../writecache/writecachebadger/flush.go | 142 ++++++++++-------- 4 files changed, 89 insertions(+), 65 deletions(-) diff --git a/go.mod b/go.mod index cbe20e39fe..114c95adb6 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 + github.com/dgraph-io/ristretto v0.1.1 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/google/uuid v1.3.0 github.com/hashicorp/golang-lru/v2 v2.0.4 @@ -42,7 +43,6 @@ require ( ) require ( - github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.1.0 // indirect diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 95961cd47e..6ceee4f175 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -296,6 +296,7 @@ const ( WritecacheCantParseAddress = "can't parse address" WritecacheCantRemoveObjectFromWritecache = "can't remove object from write-cache" WritecacheDBValueLogGCRunCompleted = "value log GC run completed" + WritecacheBadgerObjAlreadyScheduled = "object already scheduled for flush" BlobovniczatreeCouldNotGetObjectFromLevel = "could not get object from level" BlobovniczatreeCouldNotReadPayloadRangeFromOpenedBlobovnicza = "could not read payload range from opened blobovnicza" BlobovniczatreeCouldNotReadPayloadRangeFromActiveBlobovnicza = "could not read payload range from active blobovnicza" diff --git a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go index 837e76a0ba..28aa7e7661 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go +++ b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go @@ -21,6 +21,10 @@ type cache struct { // flushCh is a channel with objects to flush. flushCh chan *objectSDK.Object + // scheduled4Flush contains objects scheduled for flush via flushCh + // helps to avoid multiple flushing of one object + scheduled4Flush map[oid.Address]struct{} + scheduled4FlushMtx sync.RWMutex // closeCh is close channel, protected by modeMtx. closeCh chan struct{} // wg is a wait group for flush workers. @@ -47,8 +51,9 @@ const ( // New creates new writecache instance. func New(opts ...Option) writecache.Cache { c := &cache{ - flushCh: make(chan *objectSDK.Object), - mode: mode.ReadWrite, + flushCh: make(chan *objectSDK.Object), + mode: mode.ReadWrite, + scheduled4Flush: map[oid.Address]struct{}{}, options: options{ log: &logger.Logger{Logger: zap.NewNop()}, diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush.go b/pkg/local_object_storage/writecache/writecachebadger/flush.go index 7f41920ba9..ab6910a805 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush.go @@ -18,7 +18,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/dgraph-io/badger/v4" - "github.com/mr-tron/base58" + "github.com/dgraph-io/ristretto/z" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" @@ -35,6 +35,65 @@ const ( defaultFlushInterval = time.Second ) +type collector struct { + cache *cache + scheduled int + processed int + cancel func() +} + +func (c *collector) Send(buf *z.Buffer) error { + list, err := badger.BufferToKVList(buf) + if err != nil { + return err + } + for _, kv := range list.Kv { + select { + case <-c.cache.closeCh: + c.cancel() + return nil + default: + } + if kv.StreamDone { + return nil + } + if c.scheduled >= flushBatchSize { + c.cancel() + return nil + } + if got, want := len(kv.Key), len(internalKey{}); got != want { + c.cache.log.Debug( + fmt.Sprintf("not expected db key len: got %d, want %d", got, want)) + continue + } + c.processed++ + obj := objectSDK.New() + val := bytes.Clone(kv.Value) + if err = obj.Unmarshal(val); err != nil { + continue + } + addr := objectCore.AddressOf(obj) + c.cache.scheduled4FlushMtx.RLock() + _, ok := c.cache.scheduled4Flush[addr] + c.cache.scheduled4FlushMtx.RUnlock() + if ok { + c.cache.log.Debug(logs.WritecacheBadgerObjAlreadyScheduled, zap.Stringer("obj", addr)) + continue + } + c.cache.scheduled4FlushMtx.Lock() + c.cache.scheduled4Flush[addr] = struct{}{} + c.cache.scheduled4FlushMtx.Unlock() + c.scheduled++ + select { + case c.cache.flushCh <- obj: + case <-c.cache.closeCh: + c.cancel() + return nil + } + } + return nil +} + // runFlushLoop starts background workers which periodically flush objects to the blobstor. func (c *cache) runFlushLoop() { for i := 0; i < c.workersCount; i++ { @@ -62,17 +121,12 @@ func (c *cache) runFlushLoop() { } func (c *cache) flushSmallObjects() { - var lastKey internalKey - var m []objectInfo for { select { case <-c.closeCh: return default: } - - m = m[:0] - c.modeMtx.RLock() if c.readOnly() { c.modeMtx.RUnlock() @@ -86,61 +140,24 @@ func (c *cache) flushSmallObjects() { c.modeMtx.RUnlock() return } - - _ = c.db.View(func(tx *badger.Txn) error { - it := tx.NewIterator(badger.DefaultIteratorOptions) - defer it.Close() - if len(lastKey) == 0 { - it.Rewind() - } else { - it.Seek(lastKey[:]) - if it.Valid() && bytes.Equal(it.Item().Key(), lastKey[:]) { - it.Next() - } - } - for ; it.Valid() && len(m) < flushBatchSize; it.Next() { - if got, want := int(it.Item().KeySize()), len(lastKey); got != want { - return fmt.Errorf("invalid db key len: got %d, want %d", got, want) - } - it.Item().KeyCopy(lastKey[:]) - value, err := it.Item().ValueCopy(nil) - if err != nil { - return err - } - m = append(m, objectInfo{ - addr: lastKey.address(), - data: value, - }) - } - return nil - }) - - var count int - for i := range m { - obj := objectSDK.New() - if err := obj.Unmarshal(m[i].data); err != nil { - continue - } - - count++ - select { - case c.flushCh <- obj: - case <-c.closeCh: - c.modeMtx.RUnlock() - return - } + ctx, cancel := context.WithCancel(context.TODO()) + coll := collector{ + cache: c, + cancel: cancel, } - - if count == 0 { - c.modeMtx.RUnlock() + stream := c.db.NewStream() + // All calls to Send are done by a single goroutine + stream.Send = coll.Send + if err := stream.Orchestrate(ctx); err != nil { + c.log.Debug(fmt.Sprintf( + "error during flushing object from wc: %s", err)) + } + c.modeMtx.RUnlock() + if coll.scheduled == 0 { break } - - c.modeMtx.RUnlock() - c.log.Debug(logs.WritecacheTriedToFlushItemsFromWritecache, - zap.Int("count", count), - zap.String("start", base58.Encode(lastKey[:]))) + zap.Int("scheduled", coll.scheduled), zap.Int("processed", coll.processed)) } } @@ -167,13 +184,14 @@ func (c *cache) workerFlushSmall() { return } + addr := objectCore.AddressOf(obj) err := c.flushObject(context.TODO(), obj, nil, writecache.StorageTypeDB) - if err != nil { - // Error is handled in flushObject. - continue + if err == nil { + c.deleteFromDB([]internalKey{addr2key(addr)}) } - - c.deleteFromDB([]internalKey{addr2key(objectCore.AddressOf(obj))}) + c.scheduled4FlushMtx.Lock() + delete(c.scheduled4Flush, addr) + c.scheduled4FlushMtx.Unlock() } } From b9b86d2ec87318c3e41cd0d3b799919d3e821151 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 30 Aug 2023 15:24:31 +0300 Subject: [PATCH 0030/1413] [#666] shard/test: Fix data race in metrics tests Signed-off-by: Evgenii Stratonikov --- .../shard/metrics_test.go | 71 ++++++++++++------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 91e158b04a..3d904331e2 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -36,6 +36,29 @@ func (m *metricsStore) SetObjectCounter(objectType string, v uint64) { m.objCounters[objectType] = v } +func (m *metricsStore) getObjectCounter(objectType string) uint64 { + m.mtx.Lock() + defer m.mtx.Unlock() + return m.objCounters[objectType] +} + +func (m *metricsStore) containerSizes() map[string]int64 { + m.mtx.Lock() + defer m.mtx.Unlock() + + r := make(map[string]int64, len(m.cnrSize)) + for c, s := range m.cnrSize { + r[c] = s + } + return r +} + +func (m *metricsStore) payloadSize() int64 { + m.mtx.Lock() + defer m.mtx.Unlock() + return m.pldSize +} + func (m *metricsStore) AddToObjectCounter(objectType string, delta int) { m.mtx.Lock() defer m.mtx.Unlock() @@ -124,10 +147,10 @@ func TestCounters(t *testing.T) { } t.Run("defaults", func(t *testing.T) { - require.Zero(t, mm.objCounters[physical]) - require.Zero(t, mm.objCounters[logical]) - require.Empty(t, mm.cnrSize) - require.Zero(t, mm.pldSize) + require.Zero(t, mm.getObjectCounter(physical)) + require.Zero(t, mm.getObjectCounter(logical)) + require.Empty(t, mm.containerSizes()) + require.Zero(t, mm.payloadSize()) }) var totalPayload int64 @@ -150,10 +173,10 @@ func TestCounters(t *testing.T) { require.NoError(t, err) } - require.Equal(t, uint64(objNumber), mm.objCounters[physical]) - require.Equal(t, uint64(objNumber), mm.objCounters[logical]) - require.Equal(t, expectedSizes, mm.cnrSize) - require.Equal(t, totalPayload, mm.pldSize) + require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) + require.Equal(t, uint64(objNumber), mm.getObjectCounter(logical)) + require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, totalPayload, mm.payloadSize()) }) t.Run("inhume_GC", func(t *testing.T) { @@ -167,10 +190,10 @@ func TestCounters(t *testing.T) { require.NoError(t, err) } - require.Equal(t, uint64(objNumber), mm.objCounters[physical]) - require.Equal(t, uint64(objNumber-inhumedNumber), mm.objCounters[logical]) - require.Equal(t, expectedSizes, mm.cnrSize) - require.Equal(t, totalPayload, mm.pldSize) + require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) + require.Equal(t, uint64(objNumber-inhumedNumber), mm.getObjectCounter(logical)) + require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, totalPayload, mm.payloadSize()) oo = oo[inhumedNumber:] }) @@ -179,8 +202,8 @@ func TestCounters(t *testing.T) { var prm shard.InhumePrm ts := objectcore.AddressOf(testutil.GenerateObject()) - phy := mm.objCounters[physical] - logic := mm.objCounters[logical] + phy := mm.getObjectCounter(physical) + logic := mm.getObjectCounter(logical) inhumedNumber := int(phy / 4) prm.SetTarget(ts, addrFromObjs(oo[:inhumedNumber])...) @@ -188,10 +211,10 @@ func TestCounters(t *testing.T) { _, err := sh.Inhume(context.Background(), prm) require.NoError(t, err) - require.Equal(t, phy, mm.objCounters[physical]) - require.Equal(t, logic-uint64(inhumedNumber), mm.objCounters[logical]) - require.Equal(t, expectedSizes, mm.cnrSize) - require.Equal(t, totalPayload, mm.pldSize) + require.Equal(t, phy, mm.getObjectCounter(physical)) + require.Equal(t, logic-uint64(inhumedNumber), mm.getObjectCounter(logical)) + require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, totalPayload, mm.payloadSize()) oo = oo[inhumedNumber:] }) @@ -199,8 +222,8 @@ func TestCounters(t *testing.T) { t.Run("Delete", func(t *testing.T) { var prm shard.DeletePrm - phy := mm.objCounters[physical] - logic := mm.objCounters[logical] + phy := mm.getObjectCounter(physical) + logic := mm.getObjectCounter(logical) deletedNumber := int(phy / 4) prm.SetAddresses(addrFromObjs(oo[:deletedNumber])...) @@ -208,8 +231,8 @@ func TestCounters(t *testing.T) { _, err := sh.Delete(context.Background(), prm) require.NoError(t, err) - require.Equal(t, phy-uint64(deletedNumber), mm.objCounters[physical]) - require.Equal(t, logic-uint64(deletedNumber), mm.objCounters[logical]) + require.Equal(t, phy-uint64(deletedNumber), mm.getObjectCounter(physical)) + require.Equal(t, logic-uint64(deletedNumber), mm.getObjectCounter(logical)) var totalRemovedpayload uint64 for i := range oo[:deletedNumber] { removedPayload := oo[i].PayloadSize() @@ -218,8 +241,8 @@ func TestCounters(t *testing.T) { cnr, _ := oo[i].ContainerID() expectedSizes[cnr.EncodeToString()] -= int64(removedPayload) } - require.Equal(t, expectedSizes, mm.cnrSize) - require.Equal(t, totalPayload-int64(totalRemovedpayload), mm.pldSize) + require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, totalPayload-int64(totalRemovedpayload), mm.payloadSize()) }) } From c672f59ab8a2b80f0fd84dd9c22897f0a7324075 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 30 Aug 2023 23:36:48 +0300 Subject: [PATCH 0031/1413] [#536] blobovnicza: Drop cache Each blobovnicza instance is opened while is in use. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 + .../blobovnicza/blobovnicza_test.go | 5 +- pkg/local_object_storage/blobovnicza/put.go | 8 - pkg/local_object_storage/blobovnicza/sizes.go | 2 +- .../blobstor/blobovniczatree/active.go | 213 +++++++++++++++ .../blobstor/blobovniczatree/blobovnicza.go | 143 +---------- .../blobovniczatree/concurrency_test.go | 59 +++++ .../blobstor/blobovniczatree/control.go | 111 ++------ .../blobstor/blobovniczatree/delete.go | 67 +---- .../blobstor/blobovniczatree/errors.go | 2 + .../blobstor/blobovniczatree/exists.go | 14 +- .../blobstor/blobovniczatree/get.go | 67 +---- .../blobstor/blobovniczatree/get_range.go | 76 +----- .../blobstor/blobovniczatree/iterate.go | 4 +- .../blobstor/blobovniczatree/manager.go | 243 ++++++++++++++++++ .../blobstor/blobovniczatree/put.go | 45 +--- 16 files changed, 586 insertions(+), 474 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/active.go create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/manager.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 6ceee4f175..ed88e615b0 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -509,4 +509,5 @@ const ( RuntimeSoftMemoryLimitUpdated = "soft runtime memory limit value updated" RuntimeSoftMemoryDefinedWithGOMEMLIMIT = "soft runtime memory defined with GOMEMLIMIT environment variable, config value skipped" FailedToCountWritecacheItems = "failed to count writecache items" + AttemtToCloseAlreadyClosedBlobovnicza = "attempt to close an already closed blobovnicza" ) diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go index 48a189c9de..8d701ae5ca 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go @@ -3,7 +3,6 @@ package blobovnicza import ( "context" "crypto/rand" - "errors" "os" "testing" @@ -98,9 +97,9 @@ func TestBlobovnicza(t *testing.T) { testPutGet(t, blz, oidtest.Address(), objSizeLim, nil, nil) } - // from now objects should not be saved + // blobovnizca accepts object event if full testPutGet(t, blz, oidtest.Address(), 1024, func(err error) bool { - return errors.Is(err, ErrFull) + return err == nil }, nil) require.NoError(t, blz.Close()) diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go index e43b89ec66..787372211f 100644 --- a/pkg/local_object_storage/blobovnicza/put.go +++ b/pkg/local_object_storage/blobovnicza/put.go @@ -23,10 +23,6 @@ type PutPrm struct { type PutRes struct { } -// ErrFull is returned when trying to save an -// object to a filled blobovnicza. -var ErrFull = logicerr.New("blobovnicza is full") - // SetAddress sets the address of the saving object. func (p *PutPrm) SetAddress(addr oid.Address) { p.addr = addr @@ -65,10 +61,6 @@ func (b *Blobovnicza) Put(ctx context.Context, prm PutPrm) (PutRes, error) { key := addressKey(prm.addr) err := b.boltDB.Batch(func(tx *bbolt.Tx) error { - if b.full() { - return ErrFull - } - buck := tx.Bucket(bucketName) if buck == nil { // expected to happen: diff --git a/pkg/local_object_storage/blobovnicza/sizes.go b/pkg/local_object_storage/blobovnicza/sizes.go index 290df9c93f..cd1f697257 100644 --- a/pkg/local_object_storage/blobovnicza/sizes.go +++ b/pkg/local_object_storage/blobovnicza/sizes.go @@ -55,6 +55,6 @@ func (b *Blobovnicza) itemDeleted(itemSize uint64) { b.metrics.SubOpenBlobovniczaItems(1) } -func (b *Blobovnicza) full() bool { +func (b *Blobovnicza) IsFull() bool { return b.dataSize.Load() >= b.fullSizeLimit } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/active.go b/pkg/local_object_storage/blobstor/blobovniczatree/active.go new file mode 100644 index 0000000000..526699b454 --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/active.go @@ -0,0 +1,213 @@ +package blobovniczatree + +import ( + "path/filepath" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" + utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" +) + +type activeDB struct { + blz *blobovnicza.Blobovnicza + shDB *sharedDB +} + +func (db *activeDB) Blobovnicza() *blobovnicza.Blobovnicza { + return db.blz +} + +func (db *activeDB) Close() { + db.shDB.Close() +} + +func (db *activeDB) Path() string { + return db.shDB.Path() +} + +// activeDBManager manages active blobovnicza instances (that is, those that are being used for Put). +// +// Uses dbManager for opening/closing sharedDB instances. +// Stores a reference to an open active sharedDB, so dbManager does not close it. +// When changing the active sharedDB, releases the reference to the previous active sharedDB. +type activeDBManager struct { + levelToActiveDBGuard *sync.RWMutex + levelToActiveDB map[string]*sharedDB + levelLock *utilSync.KeyLocker[string] + closed bool + + dbManager *dbManager + leafWidth uint64 +} + +func newActiveDBManager(dbManager *dbManager, leafWidth uint64) *activeDBManager { + return &activeDBManager{ + levelToActiveDBGuard: &sync.RWMutex{}, + levelToActiveDB: make(map[string]*sharedDB), + levelLock: utilSync.NewKeyLocker[string](), + + dbManager: dbManager, + leafWidth: leafWidth, + } +} + +// GetOpenedActiveDBForLevel returns active DB for level. +// DB must be closed after use. +func (m *activeDBManager) GetOpenedActiveDBForLevel(lvlPath string) (*activeDB, error) { + activeDB, err := m.getCurrentActiveIfOk(lvlPath) + if err != nil { + return nil, err + } + if activeDB != nil { + return activeDB, nil + } + + return m.updateAndGetActive(lvlPath) +} + +func (m *activeDBManager) Open() { + m.levelToActiveDBGuard.Lock() + defer m.levelToActiveDBGuard.Unlock() + + m.closed = false +} + +func (m *activeDBManager) Close() { + m.levelToActiveDBGuard.Lock() + defer m.levelToActiveDBGuard.Unlock() + + for _, db := range m.levelToActiveDB { + db.Close() + } + m.levelToActiveDB = make(map[string]*sharedDB) + m.closed = true +} + +func (m *activeDBManager) getCurrentActiveIfOk(lvlPath string) (*activeDB, error) { + m.levelToActiveDBGuard.RLock() + defer m.levelToActiveDBGuard.RUnlock() + + if m.closed { + return nil, errClosed + } + + db, ok := m.levelToActiveDB[lvlPath] + if !ok { + return nil, nil + } + + blz, err := db.Open() //open db for usage, will be closed on activeDB.Close() + if err != nil { + return nil, err + } + + if blz.IsFull() { + db.Close() + return nil, nil + } + + return &activeDB{ + blz: blz, + shDB: db, + }, nil +} + +func (m *activeDBManager) updateAndGetActive(lvlPath string) (*activeDB, error) { + m.levelLock.Lock(lvlPath) + defer m.levelLock.Unlock(lvlPath) + + current, err := m.getCurrentActiveIfOk(lvlPath) + if err != nil { + return nil, err + } + if current != nil { + return current, nil + } + + nextShDB, err := m.getNextSharedDB(lvlPath) + if err != nil { + return nil, err + } + + if nextShDB == nil { + return nil, nil + } + + blz, err := nextShDB.Open() // open db for client, client must call Close() after usage + if err != nil { + return nil, err + } + return &activeDB{ + blz: blz, + shDB: nextShDB, + }, nil +} + +func (m *activeDBManager) getNextSharedDB(lvlPath string) (*sharedDB, error) { + var idx uint64 + var iterCount uint64 + hasActive, currentIdx := m.hasActiveDB(lvlPath) + if hasActive { + idx = (currentIdx + 1) % m.leafWidth + } + + var next *sharedDB + + for iterCount < m.leafWidth { + path := filepath.Join(lvlPath, u64ToHexString(idx)) + shDB := m.dbManager.GetByPath(path) + db, err := shDB.Open() //open db to hold active DB open, will be closed if db is full, after m.replace or by activeDBManager.Close() + if err != nil { + return nil, err + } + if db.IsFull() { + shDB.Close() + } else { + next = shDB + break + } + idx = (idx + 1) % m.leafWidth + iterCount++ + } + + previous, updated := m.replace(lvlPath, next) + if !updated && next != nil { + next.Close() // manager is closed, so don't hold active DB open + } + if updated && previous != nil { + previous.Close() + } + return next, nil +} + +func (m *activeDBManager) hasActiveDB(lvlPath string) (bool, uint64) { + m.levelToActiveDBGuard.RLock() + defer m.levelToActiveDBGuard.RUnlock() + + if m.closed { + return false, 0 + } + + db, ok := m.levelToActiveDB[lvlPath] + if !ok { + return false, 0 + } + return true, u64FromHexString(filepath.Base(db.Path())) +} + +func (m *activeDBManager) replace(lvlPath string, shDB *sharedDB) (*sharedDB, bool) { + m.levelToActiveDBGuard.Lock() + defer m.levelToActiveDBGuard.Unlock() + + if m.closed { + return nil, false + } + + previous := m.levelToActiveDB[lvlPath] + if shDB == nil { + delete(m.levelToActiveDB, lvlPath) + } else { + m.levelToActiveDB[lvlPath] = shDB + } + return previous, true +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 80d064c803..46a8df685e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -3,19 +3,12 @@ package blobovniczatree import ( "errors" "fmt" - "path/filepath" "strconv" - "sync" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/hrw" - "github.com/hashicorp/golang-lru/v2/simplelru" - "go.uber.org/zap" ) // Blobovniczas represents the storage of the "small" objects. @@ -61,28 +54,8 @@ import ( type Blobovniczas struct { cfg - // cache of opened filled Blobovniczas - opened *simplelru.LRU[string, *blobovnicza.Blobovnicza] - // lruMtx protects opened cache. - // It isn't RWMutex because `Get` calls must - // lock this mutex on write, as LRU info is updated. - // It must be taken after activeMtx in case when eviction is possible - // i.e. `Add`, `Purge` and `Remove` calls. - lruMtx sync.Mutex - - // mutex to exclude parallel bbolt.Open() calls - // bbolt.Open() deadlocks if it tries to open already opened file - openMtx sync.Mutex - - // list of active (opened, non-filled) Blobovniczas - activeMtx sync.RWMutex - active map[string]blobovniczaWithIndex -} - -type blobovniczaWithIndex struct { - ind uint64 - - blz *blobovnicza.Blobovnicza + commondbManager *dbManager + activeDBManager *activeDBManager } var _ common.Storage = (*Blobovniczas)(nil) @@ -102,120 +75,12 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz.blzLeafWidth = blz.blzShallowWidth } - cache, err := simplelru.NewLRU[string, *blobovnicza.Blobovnicza](blz.openedCacheSize, func(p string, value *blobovnicza.Blobovnicza) { - lvlPath := filepath.Dir(p) - if b, ok := blz.active[lvlPath]; ok && b.ind == u64FromHexString(filepath.Base(p)) { - // This branch is taken if we have recently updated active blobovnicza and remove - // it from opened cache. - return - } else if err := value.Close(); err != nil { - blz.log.Error(logs.BlobovniczatreeCouldNotCloseBlobovnicza, - zap.String("id", p), - zap.String("error", err.Error()), - ) - } else { - blz.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyClosedOnEvict, - zap.String("id", p), - ) - } - }) - if err != nil { - // occurs only if the size is not positive - panic(fmt.Errorf("could not create LRU cache of size %d: %w", blz.openedCacheSize, err)) - } - - activeMapCapacity := uint64(1) - for i := uint64(0); i < blz.blzShallowDepth; i++ { - if i+1 == blz.blzShallowDepth { - activeMapCapacity *= blz.blzLeafWidth - } else { - activeMapCapacity *= blz.blzShallowWidth - } - } - - blz.opened = cache - blz.active = make(map[string]blobovniczaWithIndex, activeMapCapacity) + blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.blzLeafWidth, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) + blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) return blz } -// activates and returns activated blobovnicza of p-level (dir). -// -// returns error if blobvnicza could not be activated. -func (b *Blobovniczas) getActivated(lvlPath string) (blobovniczaWithIndex, error) { - return b.updateAndGet(lvlPath, nil) -} - -// updates active blobovnicza of p-level (dir). -// -// if current active blobovnicza's index is not old, it remains unchanged. -func (b *Blobovniczas) updateActive(lvlPath string, old *uint64) error { - b.log.Debug(logs.BlobovniczatreeUpdatingActiveBlobovnicza, zap.String("path", lvlPath)) - - _, err := b.updateAndGet(lvlPath, old) - - b.log.Debug(logs.BlobovniczatreeActiveBlobovniczaSuccessfullyUpdated, zap.String("path", lvlPath)) - - return err -} - -// updates and returns active blobovnicza of p-level (dir). -// -// if current active blobovnicza's index is not old, it is returned unchanged. -func (b *Blobovniczas) updateAndGet(lvlPath string, old *uint64) (blobovniczaWithIndex, error) { - b.activeMtx.RLock() - active, ok := b.active[lvlPath] - b.activeMtx.RUnlock() - - if ok { - if old != nil { - if active.ind == b.blzLeafWidth-1 { - return active, logicerr.New("no more Blobovniczas") - } else if active.ind != *old { - // sort of CAS in order to control concurrent - // updateActive calls - return active, nil - } - } else { - return active, nil - } - - active.ind++ - } - - var err error - if active.blz, err = b.openBlobovnicza(filepath.Join(lvlPath, u64ToHexString(active.ind))); err != nil { - return active, err - } - - b.activeMtx.Lock() - defer b.activeMtx.Unlock() - - // check 2nd time to find out if it blobovnicza was activated while thread was locked - tryActive, ok := b.active[lvlPath] - if ok && tryActive.blz == active.blz { - return tryActive, nil - } - - // Remove from opened cache (active blobovnicza should always be opened). - // Because `onEvict` callback is called in `Remove`, we need to update - // active map beforehand. - b.active[lvlPath] = active - - activePath := filepath.Join(lvlPath, u64ToHexString(active.ind)) - b.lruMtx.Lock() - b.opened.Remove(activePath) - if ok { - b.opened.Add(filepath.Join(lvlPath, u64ToHexString(tryActive.ind)), tryActive.blz) - } - b.lruMtx.Unlock() - - b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyActivated, - zap.String("path", activePath)) - - return active, nil -} - // returns hash of the object address. func addressHash(addr *oid.Address, path string) uint64 { var a string diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go new file mode 100644 index 0000000000..018ecce3c9 --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -0,0 +1,59 @@ +package blobovniczatree + +import ( + "context" + "sync" + "sync/atomic" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "github.com/stretchr/testify/require" +) + +func TestBlobovniczaTree_Concurrency(t *testing.T) { + t.Parallel() + const n = 1000 + + st := NewBlobovniczaTree( + WithLogger(test.NewLogger(t, true)), + WithObjectSizeLimit(1024), + WithBlobovniczaShallowWidth(10), + WithBlobovniczaShallowDepth(1), + WithRootPath(t.TempDir())) + require.NoError(t, st.Open(false)) + require.NoError(t, st.Init()) + t.Cleanup(func() { + require.NoError(t, st.Close()) + }) + + objGen := &testutil.SeqObjGenerator{ObjSize: 1} + + var cnt atomic.Int64 + var wg sync.WaitGroup + for i := 0; i < 1000; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for cnt.Add(1) <= n { + obj := objGen.Next() + addr := testutil.AddressFromObject(t, obj) + + raw, err := obj.Marshal() + require.NoError(t, err) + + _, err = st.Put(context.Background(), common.PutPrm{ + Address: addr, + RawData: raw, + }) + require.NoError(t, err) + + _, err = st.Get(context.Background(), common.GetPrm{Address: addr}) + require.NoError(t, err) // fails very often, correlated to how many goroutines are started + } + }() + } + + wg.Wait() +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index d7b0799c1d..c3d12088af 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -2,11 +2,8 @@ package blobovniczatree import ( "context" - "fmt" - "path/filepath" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "go.uber.org/zap" ) @@ -14,6 +11,7 @@ import ( func (b *Blobovniczas) Open(readOnly bool) error { b.readOnly = readOnly b.metrics.SetMode(readOnly) + b.openManagers() return nil } @@ -23,59 +21,35 @@ func (b *Blobovniczas) Open(readOnly bool) error { func (b *Blobovniczas) Init() error { b.log.Debug(logs.BlobovniczatreeInitializingBlobovniczas) + b.openManagers() + if b.readOnly { b.log.Debug(logs.BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization) return nil } return b.iterateLeaves(context.TODO(), func(p string) (bool, error) { - blz, err := b.openBlobovniczaNoCache(p) + shBlz := b.openBlobovniczaNoCache(p) + _, err := shBlz.Open() if err != nil { return true, err } - defer blz.Close() - - if err := blz.Init(); err != nil { - return true, fmt.Errorf("could not initialize blobovnicza structure %s: %w", p, err) - } + defer shBlz.Close() b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) return false, nil }) } +func (b *Blobovniczas) openManagers() { + b.commondbManager.Open() //order important + b.activeDBManager.Open() +} + // Close implements common.Storage. func (b *Blobovniczas) Close() error { - b.activeMtx.Lock() - - b.lruMtx.Lock() - - for p, v := range b.active { - if err := v.blz.Close(); err != nil { - b.log.Debug(logs.BlobovniczatreeCouldNotCloseActiveBlobovnicza, - zap.String("path", p), - zap.String("error", err.Error()), - ) - } - b.opened.Remove(p) - } - for _, k := range b.opened.Keys() { - blz, _ := b.opened.Get(k) - if err := blz.Close(); err != nil { - b.log.Debug(logs.BlobovniczatreeCouldNotCloseActiveBlobovnicza, - zap.String("path", k), - zap.String("error", err.Error()), - ) - } - b.opened.Remove(k) - } - - b.active = make(map[string]blobovniczaWithIndex) - b.metrics.Close() - - b.lruMtx.Unlock() - - b.activeMtx.Unlock() + b.activeDBManager.Close() //order important + b.commondbManager.Close() return nil } @@ -83,61 +57,10 @@ func (b *Blobovniczas) Close() error { // opens and returns blobovnicza with path p. // // If blobovnicza is already opened and cached, instance from cache is returned w/o changes. -func (b *Blobovniczas) openBlobovnicza(p string) (*blobovnicza.Blobovnicza, error) { - b.lruMtx.Lock() - v, ok := b.opened.Get(p) - b.lruMtx.Unlock() - if ok { - // blobovnicza should be opened in cache - return v, nil - } - - lvlPath := filepath.Dir(p) - curIndex := u64FromHexString(filepath.Base(p)) - - b.activeMtx.RLock() - defer b.activeMtx.RUnlock() - - active, ok := b.active[lvlPath] - if ok && active.ind == curIndex { - return active.blz, nil - } - - b.lruMtx.Lock() - defer b.lruMtx.Unlock() - - v, ok = b.opened.Get(p) - if ok { - return v, nil - } - - blz, err := b.openBlobovniczaNoCache(p) - if err != nil { - return nil, err - } - - b.opened.Add(p, blz) - - return blz, nil +func (b *Blobovniczas) openBlobovnicza(p string) *sharedDB { + return b.openBlobovniczaNoCache(p) } -func (b *Blobovniczas) openBlobovniczaNoCache(p string) (*blobovnicza.Blobovnicza, error) { - b.openMtx.Lock() - defer b.openMtx.Unlock() - - path := filepath.Join(b.rootPath, p) - - blz := blobovnicza.New(append(b.blzOpts, - blobovnicza.WithReadOnly(b.readOnly), - blobovnicza.WithPath(path), - blobovnicza.WithMetrics(b.metrics.Blobovnicza()), - )...) - - if err := blz.Open(); err != nil { - return nil, fmt.Errorf("could not open blobovnicza %s: %w", p, err) - } - if err := blz.Init(); err != nil { - return nil, fmt.Errorf("could not init blobovnicza %s: %w", p, err) - } - return blz, nil +func (b *Blobovniczas) openBlobovniczaNoCache(p string) *sharedDB { + return b.commondbManager.GetByPath(p) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 0698c232d4..bc7735e745 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -3,7 +3,6 @@ package blobovniczatree import ( "context" "encoding/hex" - "path/filepath" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -48,10 +47,12 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co if prm.StorageID != nil { id := blobovnicza.NewIDFromBytes(prm.StorageID) - blz, err := b.openBlobovnicza(id.String()) + shBlz := b.openBlobovnicza(id.String()) + blz, err := shBlz.Open() if err != nil { return res, err } + defer shBlz.Close() if res, err = b.deleteObject(ctx, blz, bPrm); err == nil { success = true @@ -59,16 +60,10 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co return res, err } - activeCache := make(map[string]struct{}) objectFound := false err = b.iterateSortedLeaves(ctx, &prm.Address, func(p string) (bool, error) { - dirPath := filepath.Dir(p) - - // don't process active blobovnicza of the level twice - _, ok := activeCache[dirPath] - - res, err = b.deleteObjectFromLevel(ctx, bPrm, p, !ok) + res, err = b.deleteObjectFromLevel(ctx, bPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { b.log.Debug(logs.BlobovniczatreeCouldNotRemoveObjectFromLevel, @@ -78,8 +73,6 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co } } - activeCache[dirPath] = struct{}{} - if err == nil { objectFound = true } @@ -100,57 +93,13 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co // tries to delete object from particular blobovnicza. // // returns no error if object was removed from some blobovnicza of the same level. -func (b *Blobovniczas) deleteObjectFromLevel(ctx context.Context, prm blobovnicza.DeletePrm, blzPath string, tryActive bool) (common.DeleteRes, error) { - lvlPath := filepath.Dir(blzPath) - - // try to remove from blobovnicza if it is opened - b.lruMtx.Lock() - v, ok := b.opened.Get(blzPath) - b.lruMtx.Unlock() - if ok { - if res, err := b.deleteObject(ctx, v, prm); err == nil { - return res, err - } else if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotRemoveObjectFromOpenedBlobovnicza, - zap.String("path", blzPath), - zap.String("error", err.Error()), - ) - } - } - - // therefore the object is possibly placed in a lighter blobovnicza - - // next we check in the active level blobobnicza: - // * the active blobovnicza is always opened. - b.activeMtx.RLock() - active, ok := b.active[lvlPath] - b.activeMtx.RUnlock() - - if ok && tryActive { - if res, err := b.deleteObject(ctx, active.blz, prm); err == nil { - return res, err - } else if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotRemoveObjectFromActiveBlobovnicza, - zap.String("path", blzPath), - zap.String("error", err.Error()), - ) - } - } - - // then object is possibly placed in closed blobovnicza - - // check if it makes sense to try to open the blob - // (Blobovniczas "after" the active one are empty anyway, - // and it's pointless to open them). - if u64FromHexString(filepath.Base(blzPath)) > active.ind { - return common.DeleteRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) - } - - // open blobovnicza (cached inside) - blz, err := b.openBlobovnicza(blzPath) +func (b *Blobovniczas) deleteObjectFromLevel(ctx context.Context, prm blobovnicza.DeletePrm, blzPath string) (common.DeleteRes, error) { + shBlz := b.openBlobovnicza(blzPath) + blz, err := shBlz.Open() if err != nil { return common.DeleteRes{}, err } + defer shBlz.Close() return b.deleteObject(ctx, blz, prm) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/errors.go b/pkg/local_object_storage/blobstor/blobovniczatree/errors.go index 04247280a9..be0fd81c30 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/errors.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/errors.go @@ -7,6 +7,8 @@ import ( apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) +var errClosed = logicerr.New("blobvnicza is closed") + func isErrOutOfRange(err error) bool { var target *apistatus.ObjectOutOfRange return errors.As(err, &target) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index c1964c227f..f7a192526d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -3,7 +3,6 @@ package blobovniczatree import ( "context" "encoding/hex" - "path/filepath" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -37,26 +36,22 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common if prm.StorageID != nil { id := blobovnicza.NewIDFromBytes(prm.StorageID) - blz, err := b.openBlobovnicza(id.String()) + shBlz := b.openBlobovnicza(id.String()) + blz, err := shBlz.Open() if err != nil { return common.ExistsRes{}, err } + defer shBlz.Close() exists, err := blz.Exists(ctx, prm.Address) return common.ExistsRes{Exists: exists}, err } - activeCache := make(map[string]struct{}) - var gPrm blobovnicza.GetPrm gPrm.SetAddress(prm.Address) err := b.iterateSortedLeaves(ctx, &prm.Address, func(p string) (bool, error) { - dirPath := filepath.Dir(p) - - _, ok := activeCache[dirPath] - - _, err := b.getObjectFromLevel(ctx, gPrm, p, !ok) + _, err := b.getObjectFromLevel(ctx, gPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromLevel, @@ -65,7 +60,6 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common } } - activeCache[dirPath] = struct{}{} found = err == nil return found, nil }) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 671d045b99..aca39bf3be 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -4,7 +4,6 @@ import ( "context" "encoding/hex" "fmt" - "path/filepath" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -48,10 +47,12 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G if prm.StorageID != nil { id := blobovnicza.NewIDFromBytes(prm.StorageID) - blz, err := b.openBlobovnicza(id.String()) + shBlz := b.openBlobovnicza(id.String()) + blz, err := shBlz.Open() if err != nil { return res, err } + defer shBlz.Close() res, err = b.getObject(ctx, blz, bPrm) if err == nil { @@ -61,14 +62,8 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G return res, err } - activeCache := make(map[string]struct{}) - err = b.iterateSortedLeaves(ctx, &prm.Address, func(p string) (bool, error) { - dirPath := filepath.Dir(p) - - _, ok := activeCache[dirPath] - - res, err = b.getObjectFromLevel(ctx, bPrm, p, !ok) + res, err = b.getObjectFromLevel(ctx, bPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromLevel, @@ -78,8 +73,6 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G } } - activeCache[dirPath] = struct{}{} - // abort iterator if found, otherwise process all Blobovniczas return err == nil, nil }) @@ -98,58 +91,14 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G // tries to read object from particular blobovnicza. // // returns error if object could not be read from any blobovnicza of the same level. -func (b *Blobovniczas) getObjectFromLevel(ctx context.Context, prm blobovnicza.GetPrm, blzPath string, tryActive bool) (common.GetRes, error) { - lvlPath := filepath.Dir(blzPath) - - // try to read from blobovnicza if it is opened - b.lruMtx.Lock() - v, ok := b.opened.Get(blzPath) - b.lruMtx.Unlock() - if ok { - if res, err := b.getObject(ctx, v, prm); err == nil { - return res, err - } else if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotReadObjectFromOpenedBlobovnicza, - zap.String("path", blzPath), - zap.String("error", err.Error()), - ) - } - } - - // therefore the object is possibly placed in a lighter blobovnicza - - // next we check in the active level blobobnicza: - // * the freshest objects are probably the most demanded; - // * the active blobovnicza is always opened. - b.activeMtx.RLock() - active, ok := b.active[lvlPath] - b.activeMtx.RUnlock() - - if ok && tryActive { - if res, err := b.getObject(ctx, active.blz, prm); err == nil { - return res, err - } else if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromActiveBlobovnicza, - zap.String("path", blzPath), - zap.String("error", err.Error()), - ) - } - } - - // then object is possibly placed in closed blobovnicza - - // check if it makes sense to try to open the blob - // (Blobovniczas "after" the active one are empty anyway, - // and it's pointless to open them). - if u64FromHexString(filepath.Base(blzPath)) > active.ind { - return common.GetRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) - } - +func (b *Blobovniczas) getObjectFromLevel(ctx context.Context, prm blobovnicza.GetPrm, blzPath string) (common.GetRes, error) { // open blobovnicza (cached inside) - blz, err := b.openBlobovnicza(blzPath) + shBlz := b.openBlobovnicza(blzPath) + blz, err := shBlz.Open() if err != nil { return common.GetRes{}, err } + defer shBlz.Close() return b.getObject(ctx, blz, prm) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 088ebe249b..3d1a6b988a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -4,7 +4,6 @@ import ( "context" "encoding/hex" "fmt" - "path/filepath" "strconv" "time" @@ -47,10 +46,12 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re if prm.StorageID != nil { id := blobovnicza.NewIDFromBytes(prm.StorageID) - blz, err := b.openBlobovnicza(id.String()) + shBlz := b.openBlobovnicza(id.String()) + blz, err := shBlz.Open() if err != nil { return common.GetRangeRes{}, err } + defer shBlz.Close() res, err := b.getObjectRange(ctx, blz, prm) if err == nil { @@ -60,15 +61,10 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re return res, err } - activeCache := make(map[string]struct{}) objectFound := false err = b.iterateSortedLeaves(ctx, &prm.Address, func(p string) (bool, error) { - dirPath := filepath.Dir(p) - - _, ok := activeCache[dirPath] - - res, err = b.getRangeFromLevel(ctx, prm, p, !ok) + res, err = b.getRangeFromLevel(ctx, prm, p) if err != nil { outOfBounds := isErrOutOfRange(err) if !outOfBounds && !client.IsErrObjectNotFound(err) { @@ -82,8 +78,6 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re } } - activeCache[dirPath] = struct{}{} - objectFound = err == nil // abort iterator if found, otherwise process all Blobovniczas @@ -106,68 +100,14 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re // tries to read range of object payload data from particular blobovnicza. // // returns error if object could not be read from any blobovnicza of the same level. -func (b *Blobovniczas) getRangeFromLevel(ctx context.Context, prm common.GetRangePrm, blzPath string, tryActive bool) (common.GetRangeRes, error) { - lvlPath := filepath.Dir(blzPath) - - // try to read from blobovnicza if it is opened - b.lruMtx.Lock() - v, ok := b.opened.Get(blzPath) - b.lruMtx.Unlock() - if ok { - res, err := b.getObjectRange(ctx, v, prm) - switch { - case err == nil, - isErrOutOfRange(err): - return res, err - default: - if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotReadPayloadRangeFromOpenedBlobovnicza, - zap.String("path", blzPath), - zap.String("error", err.Error()), - ) - } - } - } - - // therefore the object is possibly placed in a lighter blobovnicza - - // next we check in the active level blobobnicza: - // * the freshest objects are probably the most demanded; - // * the active blobovnicza is always opened. - b.activeMtx.RLock() - active, ok := b.active[lvlPath] - b.activeMtx.RUnlock() - - if ok && tryActive { - res, err := b.getObjectRange(ctx, active.blz, prm) - switch { - case err == nil, - isErrOutOfRange(err): - return res, err - default: - if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotReadPayloadRangeFromActiveBlobovnicza, - zap.String("path", blzPath), - zap.String("error", err.Error()), - ) - } - } - } - - // then object is possibly placed in closed blobovnicza - - // check if it makes sense to try to open the blob - // (Blobovniczas "after" the active one are empty anyway, - // and it's pointless to open them). - if u64FromHexString(filepath.Base(blzPath)) > active.ind { - return common.GetRangeRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) - } - +func (b *Blobovniczas) getRangeFromLevel(ctx context.Context, prm common.GetRangePrm, blzPath string) (common.GetRangeRes, error) { // open blobovnicza (cached inside) - blz, err := b.openBlobovnicza(blzPath) + shBlz := b.openBlobovnicza(blzPath) + blz, err := shBlz.Open() if err != nil { return common.GetRangeRes{}, err } + defer shBlz.Close() return b.getObjectRange(ctx, blz, prm) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index aeac854f7a..cc273839aa 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -68,13 +68,15 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm // iterator over all Blobovniczas in unsorted order. Break on f's error return. func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors bool, f func(string, *blobovnicza.Blobovnicza) error) error { return b.iterateLeaves(ctx, func(p string) (bool, error) { - blz, err := b.openBlobovnicza(p) + shBlz := b.openBlobovnicza(p) + blz, err := shBlz.Open() if err != nil { if ignoreErrors { return false, nil } return false, fmt.Errorf("could not open blobovnicza %s: %w", p, err) } + defer shBlz.Close() err = f(p, blz) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go new file mode 100644 index 0000000000..941d9961d5 --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -0,0 +1,243 @@ +package blobovniczatree + +import ( + "fmt" + "path/filepath" + "sync" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "go.uber.org/zap" +) + +// sharedDB is responsible for opening and closing a file of single blobovnicza. +type sharedDB struct { + guard *sync.RWMutex + blcza *blobovnicza.Blobovnicza + refCount uint32 + + openDBCounter *openDBCounter + closedFlag *atomic.Bool + options []blobovnicza.Option + path string + readOnly bool + metrics blobovnicza.Metrics + log *logger.Logger +} + +func newSharedDB(options []blobovnicza.Option, path string, readOnly bool, + metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlag *atomic.Bool, log *logger.Logger) *sharedDB { + return &sharedDB{ + guard: &sync.RWMutex{}, + + options: options, + path: path, + readOnly: readOnly, + metrics: metrics, + closedFlag: closedFlag, + log: log, + openDBCounter: openDBCounter, + } +} + +func (b *sharedDB) Open() (*blobovnicza.Blobovnicza, error) { + if b.closedFlag.Load() { + return nil, errClosed + } + + b.guard.Lock() + defer b.guard.Unlock() + + if b.refCount > 0 { + b.refCount++ + return b.blcza, nil + } + + blz := blobovnicza.New(append(b.options, + blobovnicza.WithReadOnly(b.readOnly), + blobovnicza.WithPath(b.path), + blobovnicza.WithMetrics(b.metrics), + )...) + + if err := blz.Open(); err != nil { + return nil, fmt.Errorf("could not open blobovnicza %s: %w", b.path, err) + } + if err := blz.Init(); err != nil { + return nil, fmt.Errorf("could not init blobovnicza %s: %w", b.path, err) + } + + b.refCount++ + b.blcza = blz + b.openDBCounter.Inc() + + return blz, nil +} + +func (b *sharedDB) Close() { + b.guard.Lock() + defer b.guard.Unlock() + + if b.refCount == 0 { + b.log.Error(logs.AttemtToCloseAlreadyClosedBlobovnicza, zap.String("id", b.path)) + return + } + + if b.refCount == 1 { + b.refCount = 0 + if err := b.blcza.Close(); err != nil { + b.log.Error(logs.BlobovniczatreeCouldNotCloseBlobovnicza, + zap.String("id", b.path), + zap.String("error", err.Error()), + ) + } + b.blcza = nil + b.openDBCounter.Dec() + return + } + + b.refCount-- +} + +func (b *sharedDB) Path() string { + return b.path +} + +// levelDbManager stores pointers of the sharedDB's for the leaf directory of the blobovnicza tree. +type levelDbManager struct { + databases []*sharedDB +} + +func newLevelDBManager(width uint64, options []blobovnicza.Option, rootPath string, lvlPath string, + readOnly bool, metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlog *atomic.Bool, log *logger.Logger) *levelDbManager { + result := &levelDbManager{ + databases: make([]*sharedDB, width), + } + var idx uint64 + for idx = 0; idx < width; idx++ { + result.databases[idx] = newSharedDB(options, filepath.Join(rootPath, lvlPath, u64ToHexString(idx)), readOnly, metrics, openDBCounter, closedFlog, log) + } + return result +} + +func (m *levelDbManager) GetByIndex(idx uint64) *sharedDB { + return m.databases[idx] +} + +// dbManager manages the opening and closing of blobovnicza instances. +// +// The blobovnicza opens at the first request, closes after the last request. +type dbManager struct { + levelToManager map[string]*levelDbManager + levelToManagerGuard *sync.RWMutex + closedFlag *atomic.Bool + dbCounter *openDBCounter + + rootPath string + options []blobovnicza.Option + readOnly bool + metrics blobovnicza.Metrics + leafWidth uint64 + log *logger.Logger +} + +func newDBManager(rootPath string, options []blobovnicza.Option, leafWidth uint64, readOnly bool, metrics blobovnicza.Metrics, log *logger.Logger) *dbManager { + return &dbManager{ + rootPath: rootPath, + options: options, + readOnly: readOnly, + metrics: metrics, + leafWidth: leafWidth, + levelToManager: make(map[string]*levelDbManager), + levelToManagerGuard: &sync.RWMutex{}, + log: log, + closedFlag: &atomic.Bool{}, + dbCounter: newOpenDBCounter(), + } +} + +func (m *dbManager) GetByPath(path string) *sharedDB { + lvlPath := filepath.Dir(path) + curIndex := u64FromHexString(filepath.Base(path)) + levelManager := m.getLevelManager(lvlPath) + return levelManager.GetByIndex(curIndex) +} + +func (m *dbManager) Open() { + m.closedFlag.Store(false) +} + +func (m *dbManager) Close() { + m.closedFlag.Store(true) + m.dbCounter.WaitUntilAllClosed() +} + +func (m *dbManager) getLevelManager(lvlPath string) *levelDbManager { + result := m.getLevelManagerIfExists(lvlPath) + if result != nil { + return result + } + return m.getOrCreateLevelManager(lvlPath) +} + +func (m *dbManager) getLevelManagerIfExists(lvlPath string) *levelDbManager { + m.levelToManagerGuard.RLock() + defer m.levelToManagerGuard.RUnlock() + + return m.levelToManager[lvlPath] +} + +func (m *dbManager) getOrCreateLevelManager(lvlPath string) *levelDbManager { + m.levelToManagerGuard.Lock() + defer m.levelToManagerGuard.Unlock() + + if result, ok := m.levelToManager[lvlPath]; ok { + return result + } + + result := newLevelDBManager(m.leafWidth, m.options, m.rootPath, lvlPath, m.readOnly, m.metrics, m.dbCounter, m.closedFlag, m.log) + m.levelToManager[lvlPath] = result + return result +} + +type openDBCounter struct { + cond *sync.Cond + count uint64 +} + +func newOpenDBCounter() *openDBCounter { + return &openDBCounter{ + cond: &sync.Cond{ + L: &sync.Mutex{}, + }, + } +} + +func (c *openDBCounter) Inc() { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + c.count++ +} + +func (c *openDBCounter) Dec() { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + if c.count > 0 { + c.count-- + } + + if c.count == 0 { + c.cond.Broadcast() + } +} + +func (c *openDBCounter) WaitUntilAllClosed() { + c.cond.L.Lock() + for c.count > 0 { + c.cond.Wait() + } + c.cond.L.Unlock() +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 038d5244d5..aae280e0bc 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -2,7 +2,6 @@ package blobovniczatree import ( "context" - "errors" "path/filepath" "time" @@ -10,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" @@ -76,8 +74,8 @@ type putIterator struct { PutPrm blobovnicza.PutPrm } -func (i *putIterator) iterate(ctx context.Context, path string) (bool, error) { - active, err := i.B.getActivated(path) +func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) { + active, err := i.B.activeDBManager.GetOpenedActiveDBForLevel(lvlPath) if err != nil { if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) @@ -89,46 +87,29 @@ func (i *putIterator) iterate(ctx context.Context, path string) (bool, error) { return false, nil } - if _, err := active.blz.Put(ctx, i.PutPrm); err != nil { - // Check if blobovnicza is full. We could either receive `blobovnicza.ErrFull` error - // or update active blobovnicza in other thread. In the latter case the database will be closed - // and `updateActive` takes care of not updating the active blobovnicza twice. - if isFull := errors.Is(err, blobovnicza.ErrFull); isFull || errors.Is(err, bbolt.ErrDatabaseNotOpen) { - if isFull { - i.B.log.Debug(logs.BlobovniczatreeBlobovniczaOverflowed, - zap.String("path", filepath.Join(path, u64ToHexString(active.ind)))) - } + if active == nil { + i.B.log.Debug(logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath)) + return false, nil + } + defer active.Close() - if err := i.B.updateActive(path, &active.ind); err != nil { - if !isLogical(err) { - i.B.reportError(logs.BlobovniczatreeCouldNotUpdateActiveBlobovnicza, err) - } else { - i.B.log.Debug(logs.BlobovniczatreeCouldNotUpdateActiveBlobovnicza, - zap.String("level", path), - zap.String("error", err.Error())) - } + i.AllFull = false - return false, nil - } - - return i.iterate(ctx, path) - } - - i.AllFull = false + _, err = active.Blobovnicza().Put(ctx, i.PutPrm) + if err != nil { if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) } else { i.B.log.Debug(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, - zap.String("path", filepath.Join(path, u64ToHexString(active.ind))), + zap.String("path", active.Path()), zap.String("error", err.Error())) } return false, nil } - path = filepath.Join(path, u64ToHexString(active.ind)) - - i.ID = blobovnicza.NewIDFromBytes([]byte(path)) + idx := u64FromHexString(filepath.Base(active.Path())) + i.ID = blobovnicza.NewIDFromBytes([]byte(filepath.Join(lvlPath, u64ToHexString(idx)))) return true, nil } From 7456c8556a8f924f065c7e18f1b80b1624847dd0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 31 Aug 2023 11:32:09 +0300 Subject: [PATCH 0032/1413] [#536] blobovnicza: Add blobovniczatree DB cache Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/blobovnicza.go | 2 + .../blobstor/blobovniczatree/cache.go | 103 ++++++++++++++++++ .../blobovniczatree/concurrency_test.go | 2 +- .../blobstor/blobovniczatree/control.go | 18 +-- .../blobstor/blobovniczatree/delete.go | 4 +- .../blobstor/blobovniczatree/exists.go | 2 +- .../blobstor/blobovniczatree/get.go | 4 +- .../blobstor/blobovniczatree/get_range.go | 4 +- .../blobstor/blobovniczatree/iterate.go | 2 +- .../blobstor/blobovniczatree/manager.go | 3 +- 10 files changed, 124 insertions(+), 20 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/cache.go diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 46a8df685e..fd5155ee3e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -56,6 +56,7 @@ type Blobovniczas struct { commondbManager *dbManager activeDBManager *activeDBManager + dbCache *dbCache } var _ common.Storage = (*Blobovniczas)(nil) @@ -77,6 +78,7 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.blzLeafWidth, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) + blz.dbCache = newDBCache(blz.openedCacheSize, blz.commondbManager) return blz } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go new file mode 100644 index 0000000000..9bdee6df31 --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -0,0 +1,103 @@ +package blobovniczatree + +import ( + "fmt" + "sync" + + utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" + "github.com/hashicorp/golang-lru/v2/simplelru" +) + +// dbCache caches sharedDB instances that are NOT open for Put. +// +// Uses dbManager for opening/closing sharedDB instances. +// Stores a reference to an cached sharedDB, so dbManager does not close it. +type dbCache struct { + cacheGuard *sync.RWMutex + cache simplelru.LRUCache[string, *sharedDB] + pathLock *utilSync.KeyLocker[string] + closed bool + + dbManager *dbManager +} + +func newDBCache(size int, dbManager *dbManager) *dbCache { + cache, err := simplelru.NewLRU[string, *sharedDB](size, func(_ string, evictedDB *sharedDB) { + evictedDB.Close() + }) + if err != nil { + // occurs only if the size is not positive + panic(fmt.Errorf("could not create LRU cache of size %d: %w", size, err)) + } + return &dbCache{ + cacheGuard: &sync.RWMutex{}, + cache: cache, + dbManager: dbManager, + pathLock: utilSync.NewKeyLocker[string](), + } +} + +func (c *dbCache) Open() { + c.cacheGuard.Lock() + defer c.cacheGuard.Unlock() + + c.closed = false +} + +func (c *dbCache) Close() { + c.cacheGuard.Lock() + defer c.cacheGuard.Unlock() + c.cache.Purge() + c.closed = true +} + +func (c *dbCache) GetOrCreate(path string) *sharedDB { + value := c.getExisted(path) + if value != nil { + return value + } + return c.create(path) +} + +func (c *dbCache) getExisted(path string) *sharedDB { + c.cacheGuard.Lock() + defer c.cacheGuard.Unlock() + + if value, ok := c.cache.Get(path); ok { + return value + } + return nil +} + +func (c *dbCache) create(path string) *sharedDB { + c.pathLock.Lock(path) + defer c.pathLock.Unlock(path) + + value := c.getExisted(path) + if value != nil { + return value + } + + value = c.dbManager.GetByPath(path) + + _, err := value.Open() //open db to hold reference, closed by evictedDB.Close() or if cache closed + if err != nil { + return value + } + if added := c.put(path, value); !added { + value.Close() + } + return value +} + +func (c *dbCache) put(path string, db *sharedDB) bool { + c.cacheGuard.Lock() + defer c.cacheGuard.Unlock() + + if !c.closed { + c.cache.Add(path, db) + return true + } + + return false +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go index 018ecce3c9..24cb93865c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -50,7 +50,7 @@ func TestBlobovniczaTree_Concurrency(t *testing.T) { require.NoError(t, err) _, err = st.Get(context.Background(), common.GetPrm{Address: addr}) - require.NoError(t, err) // fails very often, correlated to how many goroutines are started + require.NoError(t, err) } }() } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index c3d12088af..5ea426e1ce 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -21,15 +21,13 @@ func (b *Blobovniczas) Open(readOnly bool) error { func (b *Blobovniczas) Init() error { b.log.Debug(logs.BlobovniczatreeInitializingBlobovniczas) - b.openManagers() - if b.readOnly { b.log.Debug(logs.BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization) return nil } return b.iterateLeaves(context.TODO(), func(p string) (bool, error) { - shBlz := b.openBlobovniczaNoCache(p) + shBlz := b.getBlobovniczaWithoutCaching(p) _, err := shBlz.Open() if err != nil { return true, err @@ -44,23 +42,25 @@ func (b *Blobovniczas) Init() error { func (b *Blobovniczas) openManagers() { b.commondbManager.Open() //order important b.activeDBManager.Open() + b.dbCache.Open() } // Close implements common.Storage. func (b *Blobovniczas) Close() error { - b.activeDBManager.Close() //order important + b.dbCache.Close() //order important + b.activeDBManager.Close() b.commondbManager.Close() return nil } -// opens and returns blobovnicza with path p. +// returns blobovnicza with path p // -// If blobovnicza is already opened and cached, instance from cache is returned w/o changes. -func (b *Blobovniczas) openBlobovnicza(p string) *sharedDB { - return b.openBlobovniczaNoCache(p) +// If blobovnicza is already cached, instance from cache is returned w/o changes. +func (b *Blobovniczas) getBlobovnicza(p string) *sharedDB { + return b.dbCache.GetOrCreate(p) } -func (b *Blobovniczas) openBlobovniczaNoCache(p string) *sharedDB { +func (b *Blobovniczas) getBlobovniczaWithoutCaching(p string) *sharedDB { return b.commondbManager.GetByPath(p) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index bc7735e745..ca1e46a15f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -47,7 +47,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co if prm.StorageID != nil { id := blobovnicza.NewIDFromBytes(prm.StorageID) - shBlz := b.openBlobovnicza(id.String()) + shBlz := b.getBlobovnicza(id.String()) blz, err := shBlz.Open() if err != nil { return res, err @@ -94,7 +94,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co // // returns no error if object was removed from some blobovnicza of the same level. func (b *Blobovniczas) deleteObjectFromLevel(ctx context.Context, prm blobovnicza.DeletePrm, blzPath string) (common.DeleteRes, error) { - shBlz := b.openBlobovnicza(blzPath) + shBlz := b.getBlobovnicza(blzPath) blz, err := shBlz.Open() if err != nil { return common.DeleteRes{}, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index f7a192526d..c94881168a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -36,7 +36,7 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common if prm.StorageID != nil { id := blobovnicza.NewIDFromBytes(prm.StorageID) - shBlz := b.openBlobovnicza(id.String()) + shBlz := b.getBlobovnicza(id.String()) blz, err := shBlz.Open() if err != nil { return common.ExistsRes{}, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index aca39bf3be..f2399e414d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -47,7 +47,7 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G if prm.StorageID != nil { id := blobovnicza.NewIDFromBytes(prm.StorageID) - shBlz := b.openBlobovnicza(id.String()) + shBlz := b.getBlobovnicza(id.String()) blz, err := shBlz.Open() if err != nil { return res, err @@ -93,7 +93,7 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G // returns error if object could not be read from any blobovnicza of the same level. func (b *Blobovniczas) getObjectFromLevel(ctx context.Context, prm blobovnicza.GetPrm, blzPath string) (common.GetRes, error) { // open blobovnicza (cached inside) - shBlz := b.openBlobovnicza(blzPath) + shBlz := b.getBlobovnicza(blzPath) blz, err := shBlz.Open() if err != nil { return common.GetRes{}, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 3d1a6b988a..56b41351bc 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -46,7 +46,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re if prm.StorageID != nil { id := blobovnicza.NewIDFromBytes(prm.StorageID) - shBlz := b.openBlobovnicza(id.String()) + shBlz := b.getBlobovnicza(id.String()) blz, err := shBlz.Open() if err != nil { return common.GetRangeRes{}, err @@ -102,7 +102,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re // returns error if object could not be read from any blobovnicza of the same level. func (b *Blobovniczas) getRangeFromLevel(ctx context.Context, prm common.GetRangePrm, blzPath string) (common.GetRangeRes, error) { // open blobovnicza (cached inside) - shBlz := b.openBlobovnicza(blzPath) + shBlz := b.getBlobovnicza(blzPath) blz, err := shBlz.Open() if err != nil { return common.GetRangeRes{}, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index cc273839aa..a2afbb8aa7 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -68,7 +68,7 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm // iterator over all Blobovniczas in unsorted order. Break on f's error return. func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors bool, f func(string, *blobovnicza.Blobovnicza) error) error { return b.iterateLeaves(ctx, func(p string) (bool, error) { - shBlz := b.openBlobovnicza(p) + shBlz := b.getBlobovnicza(p) blz, err := shBlz.Open() if err != nil { if ignoreErrors { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index 941d9961d5..7bc8e2827c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -114,8 +114,7 @@ func newLevelDBManager(width uint64, options []blobovnicza.Option, rootPath stri result := &levelDbManager{ databases: make([]*sharedDB, width), } - var idx uint64 - for idx = 0; idx < width; idx++ { + for idx := uint64(0); idx < width; idx++ { result.databases[idx] = newSharedDB(options, filepath.Join(rootPath, lvlPath, u64ToHexString(idx)), readOnly, metrics, openDBCounter, closedFlog, log) } return result From a54b4472de7b2970e2280285ffabc42be3b55160 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 4 Sep 2023 15:13:49 +0300 Subject: [PATCH 0033/1413] [#674] network: Close connections on address updates Signed-off-by: Evgenii Stratonikov --- pkg/network/cache/multi.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 98d2f33e7a..d03edd962a 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -130,6 +130,7 @@ loop: continue loop } } + x.clients[a].invalidate() delete(x.clients, a) } From 054e3ef3d30790650729875f9835b025570c800a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 4 Sep 2023 15:33:21 +0300 Subject: [PATCH 0034/1413] [#674] pre-commit: Update shellcheck-py Signed-off-by: Evgenii Stratonikov --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f891f88600..5f20bdc847 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,7 +26,7 @@ repos: exclude: ".key$" - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.9.0.2 + rev: v0.9.0.5 hooks: - id: shellcheck From 88d50e4c7734219b151ba93f494fb5bd29e8a14f Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 4 Sep 2023 12:00:49 +0300 Subject: [PATCH 0035/1413] [#656] policer: Add "bad" testcase Signed-off-by: Anton Nikiforov --- internal/logs/logs.go | 1 + pkg/services/policer/check.go | 33 +++++++++------------------- pkg/services/policer/policer_test.go | 33 +++++++++++++++++++++++++++- pkg/services/policer/process.go | 7 +++++- 4 files changed, 49 insertions(+), 25 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index ed88e615b0..1c5815c6c7 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -53,6 +53,7 @@ const ( PolicerRoutineStopped = "routine stopped" PolicerFailureAtObjectSelectForReplication = "failure at object select for replication" PolicerPoolSubmission = "pool submission" + PolicerUnableToProcessObj = "unable to process object" ReplicatorFinishWork = "finish work" ReplicatorCouldNotGetObjectFromLocalStorage = "could not get object from local storage" ReplicatorCouldNotReplicateObject = "could not replicate object" diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index bc82b144d3..c042734685 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -3,6 +3,7 @@ package policer import ( "context" "errors" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" @@ -16,48 +17,33 @@ import ( "go.uber.org/zap" ) -func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.AddressWithType) { +func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.AddressWithType) error { addr := addrWithType.Address idCnr := addr.Container() idObj := addr.Object() cnr, err := p.cnrSrc.Get(idCnr) if err != nil { - p.log.Error(logs.PolicerCouldNotGetContainer, - zap.Stringer("cid", idCnr), - zap.String("error", err.Error()), - ) if client.IsErrContainerNotFound(err) { - existed, err := containercore.WasRemoved(p.cnrSrc, idCnr) - if err != nil { - p.log.Error(logs.PolicerCouldNotConfirmContainerRemoval, - zap.Stringer("cid", idCnr), - zap.Stringer("oid", idObj), - zap.String("error", err.Error())) + existed, errWasRemoved := containercore.WasRemoved(p.cnrSrc, idCnr) + if errWasRemoved != nil { + return fmt.Errorf("%s: %w", logs.PolicerCouldNotConfirmContainerRemoval, errWasRemoved) } else if existed { err := p.buryFn(ctx, addrWithType.Address) if err != nil { - p.log.Error(logs.PolicerCouldNotInhumeObjectWithMissingContainer, - zap.Stringer("cid", idCnr), - zap.Stringer("oid", idObj), - zap.String("error", err.Error())) + return fmt.Errorf("%s: %w", logs.PolicerCouldNotInhumeObjectWithMissingContainer, err) } } } - return + return fmt.Errorf("%s: %w", logs.PolicerCouldNotGetContainer, err) } policy := cnr.Value.PlacementPolicy() nn, err := p.placementBuilder.BuildPlacement(idCnr, &idObj, policy) if err != nil { - p.log.Error(logs.PolicerCouldNotBuildPlacementVectorForObject, - zap.Stringer("cid", idCnr), - zap.String("error", err.Error()), - ) - - return + return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) } c := &placementRequirements{} @@ -73,7 +59,7 @@ func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.Add for i := range nn { select { case <-ctx.Done(): - return + return ctx.Err() default: } @@ -87,6 +73,7 @@ func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.Add p.cbRedundantCopy(ctx, addr) } + return nil } type placementRequirements struct { diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 8b3eecd3b8..c73d33629e 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -12,6 +12,7 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -245,7 +246,8 @@ func TestProcessObject(t *testing.T) { Type: ti.objType, } - p.processObject(context.Background(), addrWithType) + err := p.processObject(context.Background(), addrWithType) + require.NoError(t, err) sort.Ints(gotReplicateTo) require.Equal(t, ti.wantRemoveRedundant, gotRemoveRedundant) @@ -254,6 +256,35 @@ func TestProcessObject(t *testing.T) { } } +func TestProcessObjectError(t *testing.T) { + addr := oidtest.Address() + // Container source + cnr := &container.Container{} + cnr.Value.Init() + source := containerSrc{ + get: func(id cid.ID) (*container.Container, error) { + return nil, new(apistatus.ContainerNotFound) + }, + deletionInfo: func(id cid.ID) (*container.DelInfo, error) { + return nil, new(apistatus.ContainerNotFound) + }, + } + buryFn := func(ctx context.Context, a oid.Address) error { + t.Errorf("unexpected object buried: %v", a) + return nil + } + p := New( + WithContainerSource(source), + WithBuryFunc(buryFn), + ) + + addrWithType := objectcore.AddressWithType{ + Address: addr, + } + + require.True(t, client.IsErrContainerNotFound(p.processObject(context.Background(), addrWithType))) +} + func TestIteratorContract(t *testing.T) { addr := oidtest.Address() objs := []objectcore.AddressWithType{{ diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index 1f61c69f49..2e8fe92952 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -52,7 +52,12 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { } if p.objsInWork.add(addr.Address) { - p.processObject(ctx, addr) + err := p.processObject(ctx, addr) + if err != nil { + p.log.Error(logs.PolicerUnableToProcessObj, + zap.Stringer("object", addr.Address), + zap.String("error", err.Error())) + } p.cache.Add(addr.Address, time.Now()) p.objsInWork.remove(addr.Address) } From d9de9e2bbb8d56990f66bd89337b71645746c3e1 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 4 Sep 2023 18:40:22 +0300 Subject: [PATCH 0036/1413] [#675] client: Refactor PrmObjectDelete usage Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/client.go | 19 ++++++++----------- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 22ca0aa7d3..7fbfd51057 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -507,20 +507,17 @@ func (x DeleteObjectRes) Tombstone() oid.ID { // // Returns any error which prevented the operation from completing correctly in error return. func DeleteObject(ctx context.Context, prm DeleteObjectPrm) (*DeleteObjectRes, error) { - var delPrm client.PrmObjectDelete - delPrm.FromContainer(prm.objAddr.Container()) - delPrm.ByID(prm.objAddr.Object()) + cnr := prm.objAddr.Container() + obj := prm.objAddr.Object() - if prm.sessionToken != nil { - delPrm.WithinSession(*prm.sessionToken) + delPrm := client.PrmObjectDelete{ + XHeaders: prm.xHeaders, + ContainerID: &cnr, + ObjectID: &obj, + Session: prm.sessionToken, + BearerToken: prm.bearerToken, } - if prm.bearerToken != nil { - delPrm.WithBearerToken(*prm.bearerToken) - } - - delPrm.WithXHeaders(prm.xHeaders...) - cliRes, err := prm.cli.ObjectDelete(ctx, delPrm) if err != nil { return nil, fmt.Errorf("remove object via client: %w", err) diff --git a/go.mod b/go.mod index 114c95adb6..6d5382b757 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230802075510-964c3edb3f44 git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230627134746-36f3d39c406a git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230828082657-84e7e69f98ac + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904141422-5a471e5002a7 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 4b5e401741..6c8b417041 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230828082657-84e7e69f98ac h1:BRmJd04eUgzmdLe/2I0Ok/LNOkTyEAPymYUrCCF0a1U= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230828082657-84e7e69f98ac/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904141422-5a471e5002a7 h1:fwEDv/1INboZGbfQDxlsdbZGvHNUL/73rQe4fG8G3DA= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904141422-5a471e5002a7/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= From aeeb8193d22e984a7959e25a572119893bd0ce1d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 6 Sep 2023 17:06:54 +0300 Subject: [PATCH 0037/1413] [#676] node: Fix header source creation when checking eacl Signed-off-by: Anton Nikiforov --- pkg/services/object/acl/eacl/v2/headers.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go index 7408c96e98..34975e1e66 100644 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ b/pkg/services/object/acl/eacl/v2/headers.go @@ -137,6 +137,8 @@ func (h *cfg) readObjectHeadersFromRequestXHeaderSource(m requestXHeaderSource, dst.objectHeaders = headersFromObject(objectSDK.NewFromV2(oV2), h.cnr, h.obj) } + case *objectV2.PutSingleRequest: + dst.objectHeaders = headersFromObject(objectSDK.NewFromV2(req.GetBody().GetObject()), h.cnr, h.obj) case *objectV2.SearchRequest: cnrV2 := req.GetBody().GetContainerID() var cnr cid.ID From da8f384324fb91e7376ce4df5d82936512cde24c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 30 Aug 2023 17:10:21 +0300 Subject: [PATCH 0038/1413] [#668] shard/test: Fix typo in `existence` Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc_internal_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index c258b6c99b..9a4f520297 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -116,13 +116,13 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { storageID, err := sh.metaBase.StorageID(context.Background(), metaStIDPrm) require.NoError(t, err, "failed to get storage ID") - //check existance in blobstore + //check existence in blobstore var bsExisted common.ExistsPrm bsExisted.Address = addr bsExisted.StorageID = storageID.StorageID() exRes, err := sh.blobStor.Exists(context.Background(), bsExisted) - require.NoError(t, err, "failed to check blobstore existance") - require.True(t, exRes.Exists, "invalid blobstore existance result") + require.NoError(t, err, "failed to check blobstore existence") + require.True(t, exRes.Exists, "invalid blobstore existence result") //drop from blobstor var bsDeletePrm common.DeletePrm @@ -131,10 +131,10 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { _, err = sh.blobStor.Delete(context.Background(), bsDeletePrm) require.NoError(t, err, "failed to delete from blobstore") - //check existance in blobstore + //check existence in blobstore exRes, err = sh.blobStor.Exists(context.Background(), bsExisted) - require.NoError(t, err, "failed to check blobstore existance") - require.False(t, exRes.Exists, "invalid blobstore existance result") + require.NoError(t, err, "failed to check blobstore existence") + require.False(t, exRes.Exists, "invalid blobstore existence result") //get should return object not found _, err = sh.Get(context.Background(), getPrm) From aa23c6a83aaebee17f102e2f7301b773132212f9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 30 Aug 2023 18:25:56 +0300 Subject: [PATCH 0039/1413] [#668] shard/test: Remove subtest from TestCounters Otherwise, individual tests cannot be run. Signed-off-by: Evgenii Stratonikov --- .../shard/metrics_test.go | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 3d904331e2..280741f7be 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -163,21 +163,19 @@ func TestCounters(t *testing.T) { totalPayload += oSize } - t.Run("put", func(t *testing.T) { - var prm shard.PutPrm + var prm shard.PutPrm - for i := 0; i < objNumber; i++ { - prm.SetObject(oo[i]) + for i := 0; i < objNumber; i++ { + prm.SetObject(oo[i]) - _, err := sh.Put(context.Background(), prm) - require.NoError(t, err) - } + _, err := sh.Put(context.Background(), prm) + require.NoError(t, err) + } - require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) - require.Equal(t, uint64(objNumber), mm.getObjectCounter(logical)) - require.Equal(t, expectedSizes, mm.containerSizes()) - require.Equal(t, totalPayload, mm.payloadSize()) - }) + require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) + require.Equal(t, uint64(objNumber), mm.getObjectCounter(logical)) + require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, totalPayload, mm.payloadSize()) t.Run("inhume_GC", func(t *testing.T) { var prm shard.InhumePrm From bdecfbc1be41935fa8faeee04fc60bb5909809fe Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 31 Aug 2023 15:47:06 +0300 Subject: [PATCH 0040/1413] [#668] shard/test: Move tests to the main package Semantic patch (also, duplicate definitions are removed): ``` @@ var e identifier @@ -import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" -shard.e +e ``` Signed-off-by: Evgenii Stratonikov --- .../shard/control_test.go | 6 --- pkg/local_object_storage/shard/delete_test.go | 11 +++--- pkg/local_object_storage/shard/gc_test.go | 15 ++++---- pkg/local_object_storage/shard/get_test.go | 9 ++--- pkg/local_object_storage/shard/head_test.go | 9 ++--- pkg/local_object_storage/shard/inhume_test.go | 9 ++--- pkg/local_object_storage/shard/list_test.go | 7 ++-- pkg/local_object_storage/shard/lock_test.go | 33 ++++++++--------- .../shard/metrics_test.go | 28 ++++++-------- pkg/local_object_storage/shard/range_test.go | 7 ++-- pkg/local_object_storage/shard/shard_test.go | 37 +++++++++---------- .../shard/shutdown_test.go | 7 ++-- 12 files changed, 79 insertions(+), 99 deletions(-) diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 73612d8407..128e5cc0c7 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -32,12 +32,6 @@ import ( "go.etcd.io/bbolt" ) -type epochState struct{} - -func (s epochState) CurrentEpoch() uint64 { - return 0 -} - type objAddr struct { obj *objectSDK.Object addr oid.Address diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index bfafcdc743..8ee6131863 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/stretchr/testify/require" @@ -36,8 +35,8 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { obj := testutil.GenerateObjectWithCID(cnr) testutil.AddAttribute(obj, "foo", "bar") - var putPrm shard.PutPrm - var getPrm shard.GetPrm + var putPrm PutPrm + var getPrm GetPrm t.Run("big object", func(t *testing.T) { testutil.AddPayload(obj, 1<<20) @@ -45,7 +44,7 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { putPrm.SetObject(obj) getPrm.SetAddress(object.AddressOf(obj)) - var delPrm shard.DeletePrm + var delPrm DeletePrm delPrm.SetAddresses(object.AddressOf(obj)) _, err := sh.Put(context.Background(), putPrm) @@ -71,7 +70,7 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { putPrm.SetObject(obj) getPrm.SetAddress(object.AddressOf(obj)) - var delPrm shard.DeletePrm + var delPrm DeletePrm delPrm.SetAddresses(object.AddressOf(obj)) _, err := sh.Put(context.Background(), putPrm) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index 9d2771ae4e..24038f10be 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -10,7 +10,6 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" @@ -55,7 +54,7 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { lock.SetAttributes(lockExpirationAttr) lockID, _ := lock.ID() - var putPrm shard.PutPrm + var putPrm PutPrm putPrm.SetObject(obj) _, err := sh.Put(context.Background(), putPrm) @@ -69,9 +68,9 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { require.NoError(t, err) epoch.Value = 105 - sh.NotificationChannel() <- shard.EventNewEpoch(epoch.Value) + sh.NotificationChannel() <- EventNewEpoch(epoch.Value) - var getPrm shard.GetPrm + var getPrm GetPrm getPrm.SetAddress(objectCore.AddressOf(obj)) require.Eventually(t, func() bool { _, err = sh.Get(context.Background(), getPrm) @@ -141,7 +140,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { lock.SetAttributes(lockExpirationAttr) lockID, _ := lock.ID() - var putPrm shard.PutPrm + var putPrm PutPrm for _, child := range children { putPrm.SetObject(child) @@ -160,7 +159,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { _, err = sh.Put(context.Background(), putPrm) require.NoError(t, err) - var getPrm shard.GetPrm + var getPrm GetPrm getPrm.SetAddress(objectCore.AddressOf(parent)) _, err = sh.Get(context.Background(), getPrm) @@ -168,7 +167,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { require.True(t, errors.As(err, &splitInfoError), "split info must be provided") epoch.Value = 105 - sh.NotificationChannel() <- shard.EventNewEpoch(epoch.Value) + sh.NotificationChannel() <- EventNewEpoch(epoch.Value) require.Eventually(t, func() bool { _, err = sh.Get(context.Background(), getPrm) diff --git a/pkg/local_object_storage/shard/get_test.go b/pkg/local_object_storage/shard/get_test.go index 25639902dd..d3aeb5339e 100644 --- a/pkg/local_object_storage/shard/get_test.go +++ b/pkg/local_object_storage/shard/get_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "bytes" @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -35,8 +34,8 @@ func testShardGet(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) defer releaseShard(sh, t) - var putPrm shard.PutPrm - var getPrm shard.GetPrm + var putPrm PutPrm + var getPrm GetPrm t.Run("small object", func(t *testing.T) { obj := testutil.GenerateObject() @@ -116,7 +115,7 @@ func testShardGet(t *testing.T, hasWriteCache bool) { }) } -func testGet(t *testing.T, sh *shard.Shard, getPrm shard.GetPrm, hasWriteCache bool) (shard.GetRes, error) { +func testGet(t *testing.T, sh *Shard, getPrm GetPrm, hasWriteCache bool) (GetRes, error) { res, err := sh.Get(context.Background(), getPrm) if hasWriteCache { require.Eventually(t, func() bool { diff --git a/pkg/local_object_storage/shard/head_test.go b/pkg/local_object_storage/shard/head_test.go index 3a7457ace5..bf6ba990b1 100644 --- a/pkg/local_object_storage/shard/head_test.go +++ b/pkg/local_object_storage/shard/head_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -33,8 +32,8 @@ func testShardHead(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) defer releaseShard(sh, t) - var putPrm shard.PutPrm - var headPrm shard.HeadPrm + var putPrm PutPrm + var headPrm HeadPrm t.Run("regular object", func(t *testing.T) { obj := testutil.GenerateObject() @@ -87,7 +86,7 @@ func testShardHead(t *testing.T, hasWriteCache bool) { }) } -func testHead(t *testing.T, sh *shard.Shard, headPrm shard.HeadPrm, hasWriteCache bool) (shard.HeadRes, error) { +func testHead(t *testing.T, sh *Shard, headPrm HeadPrm, hasWriteCache bool) (HeadRes, error) { res, err := sh.Head(context.Background(), headPrm) if hasWriteCache { require.Eventually(t, func() bool { diff --git a/pkg/local_object_storage/shard/inhume_test.go b/pkg/local_object_storage/shard/inhume_test.go index 3fa6bc0a3b..33d483b5ee 100644 --- a/pkg/local_object_storage/shard/inhume_test.go +++ b/pkg/local_object_storage/shard/inhume_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -6,7 +6,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/stretchr/testify/require" @@ -37,13 +36,13 @@ func testShardInhume(t *testing.T, hasWriteCache bool) { ts := testutil.GenerateObjectWithCID(cnr) - var putPrm shard.PutPrm + var putPrm PutPrm putPrm.SetObject(obj) - var inhPrm shard.InhumePrm + var inhPrm InhumePrm inhPrm.SetTarget(object.AddressOf(ts), object.AddressOf(obj)) - var getPrm shard.GetPrm + var getPrm GetPrm getPrm.SetAddress(object.AddressOf(obj)) _, err := sh.Put(context.Background(), putPrm) diff --git a/pkg/local_object_storage/shard/list_test.go b/pkg/local_object_storage/shard/list_test.go index 63e7651c8e..33b94ce062 100644 --- a/pkg/local_object_storage/shard/list_test.go +++ b/pkg/local_object_storage/shard/list_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" @@ -31,7 +30,7 @@ func TestShard_List(t *testing.T) { }) } -func testShardList(t *testing.T, sh *shard.Shard) { +func testShardList(t *testing.T, sh *Shard) { const C = 10 const N = 5 @@ -59,7 +58,7 @@ func testShardList(t *testing.T, sh *shard.Shard) { objs[object.AddressOf(obj).EncodeToString()] = 0 mtx.Unlock() - var putPrm shard.PutPrm + var putPrm PutPrm putPrm.SetObject(obj) _, err := sh.Put(context.Background(), putPrm) diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index da71c48088..be9a0ba9a0 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -11,7 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -26,13 +25,13 @@ import ( func TestShard_Lock(t *testing.T) { t.Parallel() - var sh *shard.Shard + var sh *Shard rootPath := t.TempDir() - opts := []shard.Option{ - shard.WithID(shard.NewIDFromBytes([]byte{})), - shard.WithLogger(&logger.Logger{Logger: zap.NewNop()}), - shard.WithBlobStorOptions( + opts := []Option{ + WithID(NewIDFromBytes([]byte{})), + WithLogger(&logger.Logger{Logger: zap.NewNop()}), + WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( @@ -49,16 +48,16 @@ func TestShard_Lock(t *testing.T) { }, }), ), - shard.WithMetaBaseOptions( + WithMetaBaseOptions( meta.WithPath(filepath.Join(rootPath, "meta")), meta.WithEpochState(epochState{}), ), - shard.WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { + WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { sh.HandleDeletedLocks(addresses) }), } - sh = shard.New(opts...) + sh = New(opts...) require.NoError(t, sh.Open()) require.NoError(t, sh.Init(context.Background())) @@ -76,7 +75,7 @@ func TestShard_Lock(t *testing.T) { // put the object - var putPrm shard.PutPrm + var putPrm PutPrm putPrm.SetObject(obj) _, err := sh.Put(context.Background(), putPrm) @@ -94,7 +93,7 @@ func TestShard_Lock(t *testing.T) { t.Run("inhuming locked objects", func(t *testing.T) { ts := testutil.GenerateObjectWithCID(cnr) - var inhumePrm shard.InhumePrm + var inhumePrm InhumePrm inhumePrm.SetTarget(objectcore.AddressOf(ts), objectcore.AddressOf(obj)) var objLockedErr *apistatus.ObjectLocked @@ -110,7 +109,7 @@ func TestShard_Lock(t *testing.T) { t.Run("inhuming lock objects", func(t *testing.T) { ts := testutil.GenerateObjectWithCID(cnr) - var inhumePrm shard.InhumePrm + var inhumePrm InhumePrm inhumePrm.SetTarget(objectcore.AddressOf(ts), objectcore.AddressOf(lock)) _, err = sh.Inhume(context.Background(), inhumePrm) @@ -122,7 +121,7 @@ func TestShard_Lock(t *testing.T) { }) t.Run("force objects inhuming", func(t *testing.T) { - var inhumePrm shard.InhumePrm + var inhumePrm InhumePrm inhumePrm.MarkAsGarbage(objectcore.AddressOf(lock)) inhumePrm.ForceRemoval() @@ -132,7 +131,7 @@ func TestShard_Lock(t *testing.T) { // it should be possible to remove // lock object now - inhumePrm = shard.InhumePrm{} + inhumePrm = InhumePrm{} inhumePrm.MarkAsGarbage(objectcore.AddressOf(obj)) _, err = sh.Inhume(context.Background(), inhumePrm) @@ -140,7 +139,7 @@ func TestShard_Lock(t *testing.T) { // check that object has been removed - var getPrm shard.GetPrm + var getPrm GetPrm getPrm.SetAddress(objectcore.AddressOf(obj)) _, err = sh.Get(context.Background(), getPrm) @@ -160,7 +159,7 @@ func TestShard_IsLocked(t *testing.T) { // put the object - var putPrm shard.PutPrm + var putPrm PutPrm putPrm.SetObject(obj) _, err := sh.Put(context.Background(), putPrm) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 280741f7be..ae993c79cf 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -12,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -126,9 +125,6 @@ func (m *metricsStore) DeleteShardMetrics() { m.errCounter = 0 } -const physical = "phy" -const logical = "logic" - func TestCounters(t *testing.T) { t.Parallel() @@ -163,7 +159,7 @@ func TestCounters(t *testing.T) { totalPayload += oSize } - var prm shard.PutPrm + var prm PutPrm for i := 0; i < objNumber; i++ { prm.SetObject(oo[i]) @@ -178,7 +174,7 @@ func TestCounters(t *testing.T) { require.Equal(t, totalPayload, mm.payloadSize()) t.Run("inhume_GC", func(t *testing.T) { - var prm shard.InhumePrm + var prm InhumePrm inhumedNumber := objNumber / 4 for i := 0; i < inhumedNumber; i++ { @@ -197,7 +193,7 @@ func TestCounters(t *testing.T) { }) t.Run("inhume_TS", func(t *testing.T) { - var prm shard.InhumePrm + var prm InhumePrm ts := objectcore.AddressOf(testutil.GenerateObject()) phy := mm.getObjectCounter(physical) @@ -218,7 +214,7 @@ func TestCounters(t *testing.T) { }) t.Run("Delete", func(t *testing.T) { - var prm shard.DeletePrm + var prm DeletePrm phy := mm.getObjectCounter(physical) logic := mm.getObjectCounter(logical) @@ -244,7 +240,7 @@ func TestCounters(t *testing.T) { }) } -func shardWithMetrics(t *testing.T, path string) (*shard.Shard, *metricsStore) { +func shardWithMetrics(t *testing.T, path string) (*Shard, *metricsStore) { blobOpts := []blobstor.Option{ blobstor.WithStorages([]blobstor.SubStorage{ { @@ -264,14 +260,14 @@ func shardWithMetrics(t *testing.T, path string) (*shard.Shard, *metricsStore) { cnrSize: make(map[string]int64), } - sh := shard.New( - shard.WithID(shard.NewIDFromBytes([]byte{})), - shard.WithBlobStorOptions(blobOpts...), - shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(path, "pilorama"))), - shard.WithMetaBaseOptions( + sh := New( + WithID(NewIDFromBytes([]byte{})), + WithBlobStorOptions(blobOpts...), + WithPiloramaOptions(pilorama.WithPath(filepath.Join(path, "pilorama"))), + WithMetaBaseOptions( meta.WithPath(filepath.Join(path, "meta")), meta.WithEpochState(epochState{})), - shard.WithMetricsWriter(mm), + WithMetricsWriter(mm), ) require.NoError(t, sh.Open()) require.NoError(t, sh.Init(context.Background())) diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 68693f7693..4741e5163d 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -11,7 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" @@ -106,13 +105,13 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { addr := object.AddressOf(obj) payload := slice.Copy(obj.Payload()) - var putPrm shard.PutPrm + var putPrm PutPrm putPrm.SetObject(obj) _, err := sh.Put(context.Background(), putPrm) require.NoError(t, err) - var rngPrm shard.RngPrm + var rngPrm RngPrm rngPrm.SetAddress(addr) rngPrm.SetRange(tc.rng.GetOffset(), tc.rng.GetLength()) diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 6337b0b6ea..d1bfc08803 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -11,7 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" @@ -31,15 +30,15 @@ func (s epochState) CurrentEpoch() uint64 { return s.Value } -func newShard(t testing.TB, enableWriteCache bool) *shard.Shard { +func newShard(t testing.TB, enableWriteCache bool) *Shard { return newCustomShard(t, t.TempDir(), enableWriteCache, writecacheconfig.Options{Type: writecacheconfig.TypeBBolt}, nil, nil) } -func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts writecacheconfig.Options, bsOpts []blobstor.Option, metaOptions []meta.Option) *shard.Shard { - var sh *shard.Shard +func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts writecacheconfig.Options, bsOpts []blobstor.Option, metaOptions []meta.Option) *Shard { + var sh *Shard if enableWriteCache { rootPath = filepath.Join(rootPath, "wc") switch wcOpts.Type { @@ -78,33 +77,33 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts } } - opts := []shard.Option{ - shard.WithID(shard.NewIDFromBytes([]byte{})), - shard.WithLogger(test.NewLogger(t, true)), - shard.WithBlobStorOptions(bsOpts...), - shard.WithMetaBaseOptions( + opts := []Option{ + WithID(NewIDFromBytes([]byte{})), + WithLogger(test.NewLogger(t, true)), + WithBlobStorOptions(bsOpts...), + WithMetaBaseOptions( append([]meta.Option{ meta.WithPath(filepath.Join(rootPath, "meta")), meta.WithEpochState(epochState{})}, metaOptions...)..., ), - shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(rootPath, "pilorama"))), - shard.WithWriteCache(enableWriteCache), - shard.WithWriteCacheOptions(wcOpts), - shard.WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { + WithPiloramaOptions(pilorama.WithPath(filepath.Join(rootPath, "pilorama"))), + WithWriteCache(enableWriteCache), + WithWriteCacheOptions(wcOpts), + WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { sh.HandleDeletedLocks(addresses) }), - shard.WithExpiredLocksCallback(func(ctx context.Context, epoch uint64, a []oid.Address) { + WithExpiredLocksCallback(func(ctx context.Context, epoch uint64, a []oid.Address) { sh.HandleExpiredLocks(ctx, epoch, a) }), - shard.WithGCWorkerPoolInitializer(func(sz int) util.WorkerPool { + WithGCWorkerPoolInitializer(func(sz int) util.WorkerPool { pool, err := ants.NewPool(sz) require.NoError(t, err) return pool }), - shard.WithGCRemoverSleepInterval(100 * time.Millisecond), + WithGCRemoverSleepInterval(100 * time.Millisecond), } - sh = shard.New(opts...) + sh = New(opts...) require.NoError(t, sh.Open()) require.NoError(t, sh.Init(context.Background())) @@ -112,6 +111,6 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts return sh } -func releaseShard(s *shard.Shard, t testing.TB) { +func releaseShard(s *Shard, t testing.TB) { require.NoError(t, s.Close()) } diff --git a/pkg/local_object_storage/shard/shutdown_test.go b/pkg/local_object_storage/shard/shutdown_test.go index 68ef909631..304448b1ba 100644 --- a/pkg/local_object_storage/shard/shutdown_test.go +++ b/pkg/local_object_storage/shard/shutdown_test.go @@ -1,4 +1,4 @@ -package shard_test +package shard import ( "context" @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" @@ -50,7 +49,7 @@ func TestWriteCacheObjectLoss(t *testing.T) { for i := range objects { obj := objects[i] errG.Go(func() error { - var putPrm shard.PutPrm + var putPrm PutPrm putPrm.SetObject(obj) _, err := sh.Put(context.Background(), putPrm) return err @@ -62,7 +61,7 @@ func TestWriteCacheObjectLoss(t *testing.T) { sh = newCustomShard(t, dir, true, wcOpts, nil, nil) defer releaseShard(sh, t) - var getPrm shard.GetPrm + var getPrm GetPrm for i := range objects { getPrm.SetAddress(object.AddressOf(objects[i])) From 42696016de769a50a3009aa7aeaed84ddff7b2b6 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 31 Aug 2023 16:33:37 +0300 Subject: [PATCH 0041/1413] [#668] shard: Close stopChannel in GC It is done once, but now we could read it from multiple places. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 2221d57c1d..8be91fcafb 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -220,7 +220,7 @@ func (gc *gc) tickRemover(ctx context.Context) { func (gc *gc) stop() { gc.onceStop.Do(func() { - gc.stopChannel <- struct{}{} + close(gc.stopChannel) }) gc.log.Info(logs.ShardWaitingForGCWorkersToStop) From 382eb8a485dda328ba1f2886d98efd2756dd7add Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 31 Aug 2023 18:17:55 +0300 Subject: [PATCH 0042/1413] [#668] shard/test: Disable GC where it is not needed Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc.go | 9 ++++++++- pkg/local_object_storage/shard/gc_internal_test.go | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 8be91fcafb..38baccd4b0 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -119,6 +119,8 @@ type gcCfg struct { expiredCollectorBatchSize int metrics GCMectrics + + testHookRemover func(ctx context.Context) gcRunResult } func defaultGCCfg() gcCfg { @@ -209,7 +211,12 @@ func (gc *gc) tickRemover(ctx context.Context) { case <-timer.C: startedAt := time.Now() - result := gc.remover(ctx) + var result gcRunResult + if gc.testHookRemover != nil { + result = gc.testHookRemover(ctx) + } else { + result = gc.remover(ctx) + } timer.Reset(gc.removerInterval) gc.metrics.AddRunDuration(time.Since(startedAt), result.success) diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 9a4f520297..c8925e01f6 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -75,7 +75,7 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { } sh = New(opts...) - + sh.gcCfg.testHookRemover = func(context.Context) gcRunResult { return gcRunResult{} } require.NoError(t, sh.Open()) require.NoError(t, sh.Init(context.Background())) From 429f941cdaed1dbf8d77e4e25c27e3dc90ae269a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Sep 2023 17:18:04 +0300 Subject: [PATCH 0043/1413] [#668] shard/test: Release shard in t.Cleanup() Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/delete_test.go | 1 - pkg/local_object_storage/shard/get_test.go | 1 - pkg/local_object_storage/shard/head_test.go | 1 - pkg/local_object_storage/shard/inhume_test.go | 1 - pkg/local_object_storage/shard/list_test.go | 2 -- pkg/local_object_storage/shard/shard_test.go | 4 +++- 6 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index 8ee6131863..3421ac9e00 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -28,7 +28,6 @@ func TestShard_Delete(t *testing.T) { func testShardDelete(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) - defer releaseShard(sh, t) cnr := cidtest.ID() diff --git a/pkg/local_object_storage/shard/get_test.go b/pkg/local_object_storage/shard/get_test.go index d3aeb5339e..19a5e8d701 100644 --- a/pkg/local_object_storage/shard/get_test.go +++ b/pkg/local_object_storage/shard/get_test.go @@ -32,7 +32,6 @@ func TestShard_Get(t *testing.T) { func testShardGet(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) - defer releaseShard(sh, t) var putPrm PutPrm var getPrm GetPrm diff --git a/pkg/local_object_storage/shard/head_test.go b/pkg/local_object_storage/shard/head_test.go index bf6ba990b1..dfae48e840 100644 --- a/pkg/local_object_storage/shard/head_test.go +++ b/pkg/local_object_storage/shard/head_test.go @@ -30,7 +30,6 @@ func TestShard_Head(t *testing.T) { func testShardHead(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) - defer releaseShard(sh, t) var putPrm PutPrm var headPrm HeadPrm diff --git a/pkg/local_object_storage/shard/inhume_test.go b/pkg/local_object_storage/shard/inhume_test.go index 33d483b5ee..6c8e46faf5 100644 --- a/pkg/local_object_storage/shard/inhume_test.go +++ b/pkg/local_object_storage/shard/inhume_test.go @@ -27,7 +27,6 @@ func TestShard_Inhume(t *testing.T) { func testShardInhume(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) - defer releaseShard(sh, t) cnr := cidtest.ID() diff --git a/pkg/local_object_storage/shard/list_test.go b/pkg/local_object_storage/shard/list_test.go index 33b94ce062..9ca1753c43 100644 --- a/pkg/local_object_storage/shard/list_test.go +++ b/pkg/local_object_storage/shard/list_test.go @@ -18,14 +18,12 @@ func TestShard_List(t *testing.T) { t.Run("without write cache", func(t *testing.T) { t.Parallel() sh := newShard(t, false) - defer releaseShard(sh, t) testShardList(t, sh) }) t.Run("with write cache", func(t *testing.T) { t.Parallel() shWC := newShard(t, true) - defer releaseShard(shWC, t) testShardList(t, shWC) }) } diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index d1bfc08803..1550af5c01 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -31,10 +31,12 @@ func (s epochState) CurrentEpoch() uint64 { } func newShard(t testing.TB, enableWriteCache bool) *Shard { - return newCustomShard(t, t.TempDir(), enableWriteCache, + sh := newCustomShard(t, t.TempDir(), enableWriteCache, writecacheconfig.Options{Type: writecacheconfig.TypeBBolt}, nil, nil) + t.Cleanup(func() { releaseShard(sh, t) }) + return sh } func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts writecacheconfig.Options, bsOpts []blobstor.Option, metaOptions []meta.Option) *Shard { From 268adb79cbab63efe7c9c248cc848c4580887e61 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Sep 2023 17:32:14 +0300 Subject: [PATCH 0044/1413] [#668] shard/test: Simplify shard construction newCustomShard() has many parameters but only the first is obligatory. `enableWriteCache` is left as-is, because it directly affects the functionality. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc_test.go | 4 +- pkg/local_object_storage/shard/range_test.go | 38 +++++++------ pkg/local_object_storage/shard/shard_test.go | 53 +++++++++++-------- .../shard/shutdown_test.go | 4 +- 4 files changed, 55 insertions(+), 44 deletions(-) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index 24038f10be..a7daadac86 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -29,7 +29,7 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { wcOpts := writecacheconfig.Options{ Type: writecacheconfig.TypeBBolt, } - sh := newCustomShard(t, t.TempDir(), false, wcOpts, nil, []meta.Option{meta.WithEpochState(epoch)}) + sh := newCustomShard(t, false, shardOptions{rootPath: t.TempDir(), wcOpts: wcOpts, metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) t.Cleanup(func() { releaseShard(sh, t) @@ -129,7 +129,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { wcOpts := writecacheconfig.Options{ Type: writecacheconfig.TypeBBolt, } - sh := newCustomShard(t, t.TempDir(), false, wcOpts, nil, []meta.Option{meta.WithEpochState(epoch)}) + sh := newCustomShard(t, false, shardOptions{rootPath: t.TempDir(), wcOpts: wcOpts, metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) t.Cleanup(func() { releaseShard(sh, t) diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 4741e5163d..8c2f400d4e 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -76,24 +76,28 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { }, } - sh := newCustomShard(t, t.TempDir(), hasWriteCache, wcOpts, - []blobstor.Option{blobstor.WithStorages([]blobstor.SubStorage{ - { - Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(test.NewLogger(t, true)), - blobovniczatree.WithRootPath(filepath.Join(t.TempDir(), "blob", "blobovnicza")), - blobovniczatree.WithBlobovniczaShallowDepth(1), - blobovniczatree.WithBlobovniczaShallowWidth(1)), - Policy: func(_ *objectSDK.Object, data []byte) bool { - return len(data) <= smallObjectSize + sh := newCustomShard(t, hasWriteCache, shardOptions{ + rootPath: t.TempDir(), + wcOpts: wcOpts, + bsOpts: []blobstor.Option{ + blobstor.WithStorages([]blobstor.SubStorage{ + { + Storage: blobovniczatree.NewBlobovniczaTree( + blobovniczatree.WithLogger(test.NewLogger(t, true)), + blobovniczatree.WithRootPath(filepath.Join(t.TempDir(), "blob", "blobovnicza")), + blobovniczatree.WithBlobovniczaShallowDepth(1), + blobovniczatree.WithBlobovniczaShallowWidth(1)), + Policy: func(_ *objectSDK.Object, data []byte) bool { + return len(data) <= smallObjectSize + }, }, - }, - { - Storage: fstree.New( - fstree.WithPath(filepath.Join(t.TempDir(), "blob"))), - }, - })}, - nil) + { + Storage: fstree.New( + fstree.WithPath(filepath.Join(t.TempDir(), "blob"))), + }, + }), + }, + }) defer releaseShard(sh, t) for _, tc := range testCases { diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 1550af5c01..1318bd28f3 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -30,41 +30,48 @@ func (s epochState) CurrentEpoch() uint64 { return s.Value } +type shardOptions struct { + rootPath string + wcOpts writecacheconfig.Options + bsOpts []blobstor.Option + metaOptions []meta.Option +} + func newShard(t testing.TB, enableWriteCache bool) *Shard { - sh := newCustomShard(t, t.TempDir(), enableWriteCache, - writecacheconfig.Options{Type: writecacheconfig.TypeBBolt}, - nil, - nil) + sh := newCustomShard(t, enableWriteCache, shardOptions{ + rootPath: t.TempDir(), + wcOpts: writecacheconfig.Options{Type: writecacheconfig.TypeBBolt}, + }) t.Cleanup(func() { releaseShard(sh, t) }) return sh } -func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts writecacheconfig.Options, bsOpts []blobstor.Option, metaOptions []meta.Option) *Shard { +func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard { var sh *Shard if enableWriteCache { - rootPath = filepath.Join(rootPath, "wc") - switch wcOpts.Type { + o.rootPath = filepath.Join(o.rootPath, "wc") + switch o.wcOpts.Type { case writecacheconfig.TypeBBolt: - wcOpts.BBoltOptions = append( - []writecachebbolt.Option{writecachebbolt.WithPath(filepath.Join(rootPath, "wcache"))}, - wcOpts.BBoltOptions...) + o.wcOpts.BBoltOptions = append( + []writecachebbolt.Option{writecachebbolt.WithPath(filepath.Join(o.rootPath, "wcache"))}, + o.wcOpts.BBoltOptions...) case writecacheconfig.TypeBadger: - wcOpts.BadgerOptions = append( - []writecachebadger.Option{writecachebadger.WithPath(filepath.Join(rootPath, "wcache"))}, - wcOpts.BadgerOptions...) + o.wcOpts.BadgerOptions = append( + []writecachebadger.Option{writecachebadger.WithPath(filepath.Join(o.rootPath, "wcache"))}, + o.wcOpts.BadgerOptions...) } } else { - rootPath = filepath.Join(rootPath, "nowc") + o.rootPath = filepath.Join(o.rootPath, "nowc") } - if bsOpts == nil { - bsOpts = []blobstor.Option{ + if o.bsOpts == nil { + o.bsOpts = []blobstor.Option{ blobstor.WithLogger(test.NewLogger(t, true)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( blobovniczatree.WithLogger(test.NewLogger(t, true)), - blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), + blobovniczatree.WithRootPath(filepath.Join(o.rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), Policy: func(_ *objectSDK.Object, data []byte) bool { @@ -73,7 +80,7 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts }, { Storage: fstree.New( - fstree.WithPath(filepath.Join(rootPath, "blob"))), + fstree.WithPath(filepath.Join(o.rootPath, "blob"))), }, }), } @@ -82,15 +89,15 @@ func newCustomShard(t testing.TB, rootPath string, enableWriteCache bool, wcOpts opts := []Option{ WithID(NewIDFromBytes([]byte{})), WithLogger(test.NewLogger(t, true)), - WithBlobStorOptions(bsOpts...), + WithBlobStorOptions(o.bsOpts...), WithMetaBaseOptions( append([]meta.Option{ - meta.WithPath(filepath.Join(rootPath, "meta")), meta.WithEpochState(epochState{})}, - metaOptions...)..., + meta.WithPath(filepath.Join(o.rootPath, "meta")), meta.WithEpochState(epochState{})}, + o.metaOptions...)..., ), - WithPiloramaOptions(pilorama.WithPath(filepath.Join(rootPath, "pilorama"))), + WithPiloramaOptions(pilorama.WithPath(filepath.Join(o.rootPath, "pilorama"))), WithWriteCache(enableWriteCache), - WithWriteCacheOptions(wcOpts), + WithWriteCacheOptions(o.wcOpts), WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { sh.HandleDeletedLocks(addresses) }), diff --git a/pkg/local_object_storage/shard/shutdown_test.go b/pkg/local_object_storage/shard/shutdown_test.go index 304448b1ba..6cfa5fb6b9 100644 --- a/pkg/local_object_storage/shard/shutdown_test.go +++ b/pkg/local_object_storage/shard/shutdown_test.go @@ -43,7 +43,7 @@ func TestWriteCacheObjectLoss(t *testing.T) { }, } - sh := newCustomShard(t, dir, true, wcOpts, nil, nil) + sh := newCustomShard(t, true, shardOptions{rootPath: dir, wcOpts: wcOpts}) var errG errgroup.Group for i := range objects { @@ -58,7 +58,7 @@ func TestWriteCacheObjectLoss(t *testing.T) { require.NoError(t, errG.Wait()) require.NoError(t, sh.Close()) - sh = newCustomShard(t, dir, true, wcOpts, nil, nil) + sh = newCustomShard(t, true, shardOptions{rootPath: dir, wcOpts: wcOpts}) defer releaseShard(sh, t) var getPrm GetPrm From c661ba13126aa58dfdc56db62f0513571e0d09ef Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Sep 2023 17:48:00 +0300 Subject: [PATCH 0045/1413] [#668] shard/test: Use sane defaults in the test constructor Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc_test.go | 11 ++--------- pkg/local_object_storage/shard/range_test.go | 3 +-- pkg/local_object_storage/shard/shard_test.go | 12 ++++++++---- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index a7daadac86..d6a7e39e29 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -10,7 +10,6 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -26,10 +25,7 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { Value: 100, } - wcOpts := writecacheconfig.Options{ - Type: writecacheconfig.TypeBBolt, - } - sh := newCustomShard(t, false, shardOptions{rootPath: t.TempDir(), wcOpts: wcOpts, metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) + sh := newCustomShard(t, false, shardOptions{metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) t.Cleanup(func() { releaseShard(sh, t) @@ -126,10 +122,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { linkID, _ := link.ID() - wcOpts := writecacheconfig.Options{ - Type: writecacheconfig.TypeBBolt, - } - sh := newCustomShard(t, false, shardOptions{rootPath: t.TempDir(), wcOpts: wcOpts, metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) + sh := newCustomShard(t, false, shardOptions{metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) t.Cleanup(func() { releaseShard(sh, t) diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 8c2f400d4e..77a20966a8 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -77,8 +77,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { } sh := newCustomShard(t, hasWriteCache, shardOptions{ - rootPath: t.TempDir(), - wcOpts: wcOpts, + wcOpts: wcOpts, bsOpts: []blobstor.Option{ blobstor.WithStorages([]blobstor.SubStorage{ { diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 1318bd28f3..33560407e0 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -38,15 +38,19 @@ type shardOptions struct { } func newShard(t testing.TB, enableWriteCache bool) *Shard { - sh := newCustomShard(t, enableWriteCache, shardOptions{ - rootPath: t.TempDir(), - wcOpts: writecacheconfig.Options{Type: writecacheconfig.TypeBBolt}, - }) + sh := newCustomShard(t, enableWriteCache, shardOptions{}) t.Cleanup(func() { releaseShard(sh, t) }) return sh } func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard { + if o.rootPath == "" { + o.rootPath = t.TempDir() + } + if enableWriteCache && o.wcOpts.Type == 0 { + o.wcOpts.Type = writecacheconfig.TypeBBolt + } + var sh *Shard if enableWriteCache { o.rootPath = filepath.Join(o.rootPath, "wc") From 39879fa868bdaac111711ec40159028ffbdd7469 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Sep 2023 17:51:15 +0300 Subject: [PATCH 0046/1413] [#668] shard/test: Add dontRelease options Most of the time we would like to close shard with minor exceptions. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc_test.go | 8 -------- pkg/local_object_storage/shard/range_test.go | 1 - pkg/local_object_storage/shard/shard_test.go | 9 ++++++--- pkg/local_object_storage/shard/shutdown_test.go | 3 +-- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index d6a7e39e29..4f19db878c 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -27,10 +27,6 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { sh := newCustomShard(t, false, shardOptions{metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) - t.Cleanup(func() { - releaseShard(sh, t) - }) - cnr := cidtest.ID() var objExpirationAttr objectSDK.Attribute @@ -124,10 +120,6 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { sh := newCustomShard(t, false, shardOptions{metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) - t.Cleanup(func() { - releaseShard(sh, t) - }) - lock := testutil.GenerateObjectWithCID(cnr) lock.SetType(objectSDK.TypeLock) lock.SetAttributes(lockExpirationAttr) diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 77a20966a8..a8bc833079 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -97,7 +97,6 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { }), }, }) - defer releaseShard(sh, t) for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 33560407e0..eb2aba5806 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -32,15 +32,14 @@ func (s epochState) CurrentEpoch() uint64 { type shardOptions struct { rootPath string + dontRelease bool wcOpts writecacheconfig.Options bsOpts []blobstor.Option metaOptions []meta.Option } func newShard(t testing.TB, enableWriteCache bool) *Shard { - sh := newCustomShard(t, enableWriteCache, shardOptions{}) - t.Cleanup(func() { releaseShard(sh, t) }) - return sh + return newCustomShard(t, enableWriteCache, shardOptions{}) } func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard { @@ -121,6 +120,10 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard require.NoError(t, sh.Open()) require.NoError(t, sh.Init(context.Background())) + if !o.dontRelease { + t.Cleanup(func() { releaseShard(sh, t) }) + } + return sh } diff --git a/pkg/local_object_storage/shard/shutdown_test.go b/pkg/local_object_storage/shard/shutdown_test.go index 6cfa5fb6b9..163c3a4aeb 100644 --- a/pkg/local_object_storage/shard/shutdown_test.go +++ b/pkg/local_object_storage/shard/shutdown_test.go @@ -43,7 +43,7 @@ func TestWriteCacheObjectLoss(t *testing.T) { }, } - sh := newCustomShard(t, true, shardOptions{rootPath: dir, wcOpts: wcOpts}) + sh := newCustomShard(t, true, shardOptions{dontRelease: true, rootPath: dir, wcOpts: wcOpts}) var errG errgroup.Group for i := range objects { @@ -59,7 +59,6 @@ func TestWriteCacheObjectLoss(t *testing.T) { require.NoError(t, sh.Close()) sh = newCustomShard(t, true, shardOptions{rootPath: dir, wcOpts: wcOpts}) - defer releaseShard(sh, t) var getPrm GetPrm From 36759f843418c6728897701de99b76feda78ef76 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Sep 2023 18:03:04 +0300 Subject: [PATCH 0047/1413] [#668] shard/test: Properly check event processing See https://git.frostfs.info/TrueCloudLab/frostfs-node/actions/runs/1594/jobs/2 Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc.go | 46 +++++++++++--------- pkg/local_object_storage/shard/gc_test.go | 32 ++++++++------ pkg/local_object_storage/shard/shard_test.go | 3 ++ 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 38baccd4b0..13ab39ae00 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -160,33 +160,37 @@ func (gc *gc) listenEvents(ctx context.Context) { return } - v, ok := gc.mEventHandler[event.typ()] - if !ok { - continue - } + gc.handleEvent(ctx, event) + } +} - v.cancelFunc() - v.prevGroup.Wait() +func (gc *gc) handleEvent(ctx context.Context, event Event) { + v, ok := gc.mEventHandler[event.typ()] + if !ok { + return + } - var runCtx context.Context - runCtx, v.cancelFunc = context.WithCancel(ctx) + v.cancelFunc() + v.prevGroup.Wait() - v.prevGroup.Add(len(v.handlers)) + var runCtx context.Context + runCtx, v.cancelFunc = context.WithCancel(ctx) - for i := range v.handlers { - h := v.handlers[i] + v.prevGroup.Add(len(v.handlers)) - err := gc.workerPool.Submit(func() { - defer v.prevGroup.Done() - h(runCtx, event) - }) - if err != nil { - gc.log.Warn(logs.ShardCouldNotSubmitGCJobToWorkerPool, - zap.String("error", err.Error()), - ) + for i := range v.handlers { + h := v.handlers[i] - v.prevGroup.Done() - } + err := gc.workerPool.Submit(func() { + defer v.prevGroup.Done() + h(runCtx, event) + }) + if err != nil { + gc.log.Warn(logs.ShardCouldNotSubmitGCJobToWorkerPool, + zap.String("error", err.Error()), + ) + + v.prevGroup.Done() } } } diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index 4f19db878c..8b535200d8 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -4,12 +4,12 @@ import ( "context" "errors" "testing" - "time" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -25,7 +25,12 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { Value: 100, } - sh := newCustomShard(t, false, shardOptions{metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) + sh := newCustomShard(t, false, shardOptions{ + metaOptions: []meta.Option{meta.WithEpochState(epoch)}, + additionalShardOptions: []Option{WithGCWorkerPoolInitializer(func(int) util.WorkerPool { + return util.NewPseudoWorkerPool() // synchronous event processing + })}, + }) cnr := cidtest.ID() @@ -60,14 +65,12 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { require.NoError(t, err) epoch.Value = 105 - sh.NotificationChannel() <- EventNewEpoch(epoch.Value) + sh.gc.handleEvent(context.Background(), EventNewEpoch(epoch.Value)) var getPrm GetPrm getPrm.SetAddress(objectCore.AddressOf(obj)) - require.Eventually(t, func() bool { - _, err = sh.Get(context.Background(), getPrm) - return client.IsErrObjectNotFound(err) - }, 3*time.Second, 1*time.Second, "expired object must be deleted") + _, err = sh.Get(context.Background(), getPrm) + require.True(t, client.IsErrObjectNotFound(err), "expired object must be deleted") } func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { @@ -118,7 +121,12 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { linkID, _ := link.ID() - sh := newCustomShard(t, false, shardOptions{metaOptions: []meta.Option{meta.WithEpochState(epoch)}}) + sh := newCustomShard(t, false, shardOptions{ + metaOptions: []meta.Option{meta.WithEpochState(epoch)}, + additionalShardOptions: []Option{WithGCWorkerPoolInitializer(func(int) util.WorkerPool { + return util.NewPseudoWorkerPool() // synchronous event processing + })}, + }) lock := testutil.GenerateObjectWithCID(cnr) lock.SetType(objectSDK.TypeLock) @@ -152,10 +160,8 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { require.True(t, errors.As(err, &splitInfoError), "split info must be provided") epoch.Value = 105 - sh.NotificationChannel() <- EventNewEpoch(epoch.Value) + sh.gc.handleEvent(context.Background(), EventNewEpoch(epoch.Value)) - require.Eventually(t, func() bool { - _, err = sh.Get(context.Background(), getPrm) - return client.IsErrObjectNotFound(err) - }, 3*time.Second, 1*time.Second, "expired complex object must be deleted on epoch after lock expires") + _, err = sh.Get(context.Background(), getPrm) + require.True(t, client.IsErrObjectNotFound(err), "expired complex object must be deleted on epoch after lock expires") } diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index eb2aba5806..669ac287cf 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -36,6 +36,8 @@ type shardOptions struct { wcOpts writecacheconfig.Options bsOpts []blobstor.Option metaOptions []meta.Option + + additionalShardOptions []Option } func newShard(t testing.TB, enableWriteCache bool) *Shard { @@ -114,6 +116,7 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard }), WithGCRemoverSleepInterval(100 * time.Millisecond), } + opts = append(opts, o.additionalShardOptions...) sh = New(opts...) From a716db99dbcb64fdc947ddfc1366d80a87dd1f8d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Sep 2023 18:08:23 +0300 Subject: [PATCH 0048/1413] [#668] shard/test: Do not alter rootPath option Supposedly, this was added to allow creating 2 different shards without subtest. Now we use t.TempDir() everywhere, so this should not be a problem. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/shard_test.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 669ac287cf..5dcccd9c96 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -54,7 +54,6 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard var sh *Shard if enableWriteCache { - o.rootPath = filepath.Join(o.rootPath, "wc") switch o.wcOpts.Type { case writecacheconfig.TypeBBolt: o.wcOpts.BBoltOptions = append( @@ -65,8 +64,6 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard []writecachebadger.Option{writecachebadger.WithPath(filepath.Join(o.rootPath, "wcache"))}, o.wcOpts.BadgerOptions...) } - } else { - o.rootPath = filepath.Join(o.rootPath, "nowc") } if o.bsOpts == nil { From 8a81af5a3b1b23381ac09983b38b02f476788072 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Thu, 31 Aug 2023 19:26:47 +0300 Subject: [PATCH 0049/1413] [#653] Add context parameter to Open functions Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-lens/internal/meta/root.go | 2 +- cmd/frostfs-node/config.go | 6 ++--- cmd/frostfs-node/main.go | 4 ++-- .../blobstor/blobstor_test.go | 8 +++---- pkg/local_object_storage/blobstor/control.go | 8 ++++++- .../blobstor/exists_test.go | 2 +- .../blobstor/iterate_test.go | 2 +- pkg/local_object_storage/blobstor/mode.go | 3 ++- pkg/local_object_storage/engine/control.go | 24 +++++++++---------- .../engine/control_test.go | 14 +++++------ .../engine/delete_test.go | 2 +- .../engine/engine_test.go | 8 +++---- pkg/local_object_storage/engine/error_test.go | 4 ++-- .../engine/evacuate_test.go | 2 +- pkg/local_object_storage/engine/head_test.go | 2 +- .../engine/inhume_test.go | 4 ++-- pkg/local_object_storage/engine/list_test.go | 4 ++-- pkg/local_object_storage/engine/lock_test.go | 12 +++++----- pkg/local_object_storage/engine/shards.go | 9 +++---- .../engine/shards_test.go | 3 ++- .../internal/storagetest/storage.go | 19 ++++++++------- pkg/local_object_storage/metabase/control.go | 3 ++- pkg/local_object_storage/metabase/db_test.go | 3 ++- pkg/local_object_storage/metabase/mode.go | 5 ++-- .../metabase/version_test.go | 15 ++++++------ .../pilorama/bench_test.go | 2 +- pkg/local_object_storage/pilorama/boltdb.go | 4 ++-- pkg/local_object_storage/pilorama/forest.go | 2 +- .../pilorama/forest_test.go | 4 ++-- .../pilorama/interface.go | 2 +- pkg/local_object_storage/shard/control.go | 10 ++++---- .../shard/control_test.go | 14 +++++------ .../shard/gc_internal_test.go | 2 +- pkg/local_object_storage/shard/id.go | 6 +++-- pkg/local_object_storage/shard/lock_test.go | 2 +- .../shard/metrics_test.go | 2 +- pkg/local_object_storage/shard/reload_test.go | 2 +- pkg/local_object_storage/shard/shard_test.go | 2 +- .../writecache/benchmark/writecache_test.go | 2 +- .../writecache/writecache.go | 2 +- .../writecachebadger/cachebadger.go | 3 ++- .../writecache/writecachebbolt/cachebbolt.go | 3 ++- .../writecache/writecachetest/flush.go | 6 ++--- 43 files changed, 129 insertions(+), 109 deletions(-) diff --git a/cmd/frostfs-lens/internal/meta/root.go b/cmd/frostfs-lens/internal/meta/root.go index 9f35c26c26..a59574b6cc 100644 --- a/cmd/frostfs-lens/internal/meta/root.go +++ b/cmd/frostfs-lens/internal/meta/root.go @@ -43,7 +43,7 @@ func openMeta(cmd *cobra.Command) *meta.DB { }), meta.WithEpochState(epochState{}), ) - common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(true))) + common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(cmd.Context(), true))) return db } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 8e103b527b..8286bc7d71 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -901,7 +901,7 @@ func (c *cfg) LocalAddress() network.AddressGroup { return c.localAddr } -func initLocalStorage(c *cfg) { +func initLocalStorage(ctx context.Context, c *cfg) { ls := engine.New(c.engineOpts()...) addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { @@ -914,7 +914,7 @@ func initLocalStorage(c *cfg) { var shardsAttached int for _, optsWithMeta := range c.shardOpts() { - id, err := ls.AddShard(append(optsWithMeta.shOpts, shard.WithTombstoneSource(c.createTombstoneSource()))...) + id, err := ls.AddShard(ctx, append(optsWithMeta.shOpts, shard.WithTombstoneSource(c.createTombstoneSource()))...) if err != nil { c.log.Error(logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err)) } else { @@ -931,7 +931,7 @@ func initLocalStorage(c *cfg) { c.onShutdown(func() { c.log.Info(logs.FrostFSNodeClosingComponentsOfTheStorageEngine) - err := ls.Close() + err := ls.Close(context.Background()) if err != nil { c.log.Info(logs.FrostFSNodeStorageEngineClosingFailure, zap.String("error", err.Error()), diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index bf872da037..88032ebdb2 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -91,10 +91,10 @@ func initApp(ctx context.Context, c *cfg) { initAndLog(c, "tracing", func(c *cfg) { initTracing(ctx, c) }) - initLocalStorage(c) + initLocalStorage(ctx, c) initAndLog(c, "storage engine", func(c *cfg) { - fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Open()) + fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Open(ctx)) fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Init(ctx)) }) diff --git a/pkg/local_object_storage/blobstor/blobstor_test.go b/pkg/local_object_storage/blobstor/blobstor_test.go index 8784520698..f1d567da71 100644 --- a/pkg/local_object_storage/blobstor/blobstor_test.go +++ b/pkg/local_object_storage/blobstor/blobstor_test.go @@ -51,7 +51,7 @@ func TestCompression(t *testing.T) { bs := New( WithCompressObjects(compress), WithStorages(defaultStorages(dir, smallSizeLimit))) - require.NoError(t, bs.Open(false)) + require.NoError(t, bs.Open(context.Background(), false)) require.NoError(t, bs.Init()) return bs } @@ -126,7 +126,7 @@ func TestBlobstor_needsCompression(t *testing.T) { Storage: fstree.New(fstree.WithPath(dir)), }, })) - require.NoError(t, bs.Open(false)) + require.NoError(t, bs.Open(context.Background(), false)) require.NoError(t, bs.Init()) return bs } @@ -188,7 +188,7 @@ func TestConcurrentPut(t *testing.T) { blobStor := New( WithStorages(defaultStorages(dir, smallSizeLimit))) - require.NoError(t, blobStor.Open(false)) + require.NoError(t, blobStor.Open(context.Background(), false)) require.NoError(t, blobStor.Init()) testGet := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) { @@ -268,7 +268,7 @@ func TestConcurrentDelete(t *testing.T) { blobStor := New( WithStorages(defaultStorages(dir, smallSizeLimit))) - require.NoError(t, blobStor.Open(false)) + require.NoError(t, blobStor.Open(context.Background(), false)) require.NoError(t, blobStor.Init()) testPut := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) { diff --git a/pkg/local_object_storage/blobstor/control.go b/pkg/local_object_storage/blobstor/control.go index 6b439dcf02..4b8a36de84 100644 --- a/pkg/local_object_storage/blobstor/control.go +++ b/pkg/local_object_storage/blobstor/control.go @@ -1,6 +1,7 @@ package blobstor import ( + "context" "errors" "fmt" @@ -9,10 +10,15 @@ import ( ) // Open opens BlobStor. -func (b *BlobStor) Open(readOnly bool) error { +func (b *BlobStor) Open(ctx context.Context, readOnly bool) error { b.log.Debug(logs.BlobstorOpening) for i := range b.storage { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } err := b.storage[i].Storage.Open(readOnly) if err != nil { return err diff --git a/pkg/local_object_storage/blobstor/exists_test.go b/pkg/local_object_storage/blobstor/exists_test.go index 7a3dcd6171..367b63af1d 100644 --- a/pkg/local_object_storage/blobstor/exists_test.go +++ b/pkg/local_object_storage/blobstor/exists_test.go @@ -20,7 +20,7 @@ func TestExists(t *testing.T) { b := New(WithStorages(storages)) - require.NoError(t, b.Open(false)) + require.NoError(t, b.Open(context.Background(), false)) require.NoError(t, b.Init()) objects := []*objectSDK.Object{ diff --git a/pkg/local_object_storage/blobstor/iterate_test.go b/pkg/local_object_storage/blobstor/iterate_test.go index c35869655d..ef3fda9919 100644 --- a/pkg/local_object_storage/blobstor/iterate_test.go +++ b/pkg/local_object_storage/blobstor/iterate_test.go @@ -26,7 +26,7 @@ func TestIterateObjects(t *testing.T) { defer os.RemoveAll(p) // open Blobstor - require.NoError(t, blobStor.Open(false)) + require.NoError(t, blobStor.Open(context.Background(), false)) // initialize Blobstor require.NoError(t, blobStor.Init()) diff --git a/pkg/local_object_storage/blobstor/mode.go b/pkg/local_object_storage/blobstor/mode.go index e6d0edc03d..2f4473bd8d 100644 --- a/pkg/local_object_storage/blobstor/mode.go +++ b/pkg/local_object_storage/blobstor/mode.go @@ -1,6 +1,7 @@ package blobstor import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -21,7 +22,7 @@ func (b *BlobStor) SetMode(m mode.Mode) error { err := b.Close() if err == nil { - if err = b.Open(m.ReadOnly()); err == nil { + if err = b.Open(context.TODO(), m.ReadOnly()); err == nil { err = b.Init() } } diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index bd166b3ff0..d97148f736 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -21,11 +21,11 @@ type shardInitError struct { } // Open opens all StorageEngine's components. -func (e *StorageEngine) Open() error { - return e.open() +func (e *StorageEngine) Open(ctx context.Context) error { + return e.open(ctx) } -func (e *StorageEngine) open() error { +func (e *StorageEngine) open(ctx context.Context) error { e.mtx.Lock() defer e.mtx.Unlock() @@ -36,7 +36,7 @@ func (e *StorageEngine) open() error { wg.Add(1) go func(id string, sh *shard.Shard) { defer wg.Done() - if err := sh.Open(); err != nil { + if err := sh.Open(ctx); err != nil { errCh <- shardInitError{ err: err, id: id, @@ -148,10 +148,10 @@ var errClosed = errors.New("storage engine is closed") // After the call, all the next ones will fail. // // The method MUST only be called when the application exits. -func (e *StorageEngine) Close() error { +func (e *StorageEngine) Close(ctx context.Context) error { close(e.closeCh) defer e.wg.Wait() - return e.setBlockExecErr(errClosed) + return e.setBlockExecErr(ctx, errClosed) } // closes all shards. Never returns an error, shard errors are logged. @@ -197,7 +197,7 @@ func (e *StorageEngine) execIfNotBlocked(op func() error) error { // - otherwise, resumes execution. If exec was blocked, calls open method. // // Can be called concurrently with exec. In this case it waits for all executions to complete. -func (e *StorageEngine) setBlockExecErr(err error) error { +func (e *StorageEngine) setBlockExecErr(ctx context.Context, err error) error { e.blockExec.mtx.Lock() defer e.blockExec.mtx.Unlock() @@ -212,7 +212,7 @@ func (e *StorageEngine) setBlockExecErr(err error) error { if err == nil { if prevErr != nil { // block -> ok - return e.open() + return e.open(ctx) } } else if prevErr == nil { // ok -> block return e.close(errors.Is(err, errClosed)) @@ -235,7 +235,7 @@ func (e *StorageEngine) setBlockExecErr(err error) error { // Note: technically passing nil error will resume the execution, otherwise, it is recommended to call ResumeExecution // for this. func (e *StorageEngine) BlockExecution(err error) error { - return e.setBlockExecErr(err) + return e.setBlockExecErr(context.Background(), err) } // ResumeExecution resumes the execution of any data-related operation. @@ -247,7 +247,7 @@ func (e *StorageEngine) BlockExecution(err error) error { // // Must not be called concurrently with either Open or Init. func (e *StorageEngine) ResumeExecution() error { - return e.setBlockExecErr(nil) + return e.setBlockExecErr(context.Background(), nil) } type ReConfiguration struct { @@ -334,14 +334,14 @@ loop: } for _, newID := range shardsToAdd { - sh, err := e.createShard(rcfg.shards[newID]) + sh, err := e.createShard(ctx, rcfg.shards[newID]) if err != nil { return fmt.Errorf("could not add new shard with '%s' metabase path: %w", newID, err) } idStr := sh.ID().String() - err = sh.Open() + err = sh.Open(ctx) if err == nil { err = sh.Init(ctx) } diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index eb601122bf..0c5ff94da0 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -126,7 +126,7 @@ func testEngineFailInitAndReload(t *testing.T, errOnAdd bool, opts []shard.Optio var configID string e := New() - _, err := e.AddShard(opts...) + _, err := e.AddShard(context.Background(), opts...) if errOnAdd { require.Error(t, err) // This branch is only taken when we cannot update shard ID in the metabase. @@ -144,7 +144,7 @@ func testEngineFailInitAndReload(t *testing.T, errOnAdd bool, opts []shard.Optio configID = calculateShardID(e.shards[id].Shard.DumpInfo()) e.mtx.RUnlock() - err = e.Open() + err = e.Open(context.Background()) if err == nil { require.Error(t, e.Init(context.Background())) } @@ -193,7 +193,7 @@ func TestExecBlocks(t *testing.T) { require.NoError(t, err) // close - require.NoError(t, e.Close()) + require.NoError(t, e.Close(context.Background())) // try exec after close _, err = Head(context.Background(), e, addr) @@ -209,13 +209,13 @@ func TestPersistentShardID(t *testing.T) { te := newEngineWithErrorThreshold(t, dir, 1) checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite) - require.NoError(t, te.ng.Close()) + require.NoError(t, te.ng.Close(context.Background())) newTe := newEngineWithErrorThreshold(t, dir, 1) for i := 0; i < len(newTe.shards); i++ { require.Equal(t, te.shards[i].id, newTe.shards[i].id) } - require.NoError(t, newTe.ng.Close()) + require.NoError(t, newTe.ng.Close(context.Background())) p1 := newTe.ng.shards[te.shards[0].id.String()].Shard.DumpInfo().MetaBaseInfo.Path p2 := newTe.ng.shards[te.shards[1].id.String()].Shard.DumpInfo().MetaBaseInfo.Path @@ -227,7 +227,7 @@ func TestPersistentShardID(t *testing.T) { newTe = newEngineWithErrorThreshold(t, dir, 1) require.Equal(t, te.shards[1].id, newTe.shards[0].id) require.Equal(t, te.shards[0].id, newTe.shards[1].id) - require.NoError(t, newTe.ng.Close()) + require.NoError(t, newTe.ng.Close(context.Background())) } @@ -313,7 +313,7 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str require.Equal(t, num, len(e.shards)) require.Equal(t, num, len(e.shardPools)) - require.NoError(t, e.Open()) + require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) return e, currShards diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 57b9ec2e34..8e94732ae9 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -54,7 +54,7 @@ func TestDeleteBigObject(t *testing.T) { e := testNewEngine(t).setInitializedShards(t, s1, s2, s3).engine e.log = test.NewLogger(t, true) - defer e.Close() + defer e.Close(context.Background()) for i := range children { require.NoError(t, Put(context.Background(), e, children[i])) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index a8fd9eeee4..934bea8bbd 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -50,7 +50,7 @@ func benchmarkExists(b *testing.B, shardNum int) { e := testNewEngine(b).setInitializedShards(b, shards...).engine b.Cleanup(func() { - _ = e.Close() + _ = e.Close(context.Background()) _ = os.RemoveAll(b.Name()) }) @@ -119,7 +119,7 @@ func (te *testEngineWrapper) setShardsNum(t testing.TB, num int) *testEngineWrap func (te *testEngineWrapper) setShardsNumOpts(t testing.TB, num int, shardOpts func(id int) []shard.Option) *testEngineWrapper { for i := 0; i < num; i++ { opts := shardOpts(i) - id, err := te.engine.AddShard(opts...) + id, err := te.engine.AddShard(context.Background(), opts...) require.NoError(t, err) te.shardIDs = append(te.shardIDs, id) } @@ -130,7 +130,7 @@ func (te *testEngineWrapper) setShardsNumAdditionalOpts(t testing.TB, num int, s for i := 0; i < num; i++ { defaultOpts := testDefaultShardOptions(t, i) opts := append(defaultOpts, shardOpts(i)...) - id, err := te.engine.AddShard(opts...) + id, err := te.engine.AddShard(context.Background(), opts...) require.NoError(t, err) te.shardIDs = append(te.shardIDs, id) } @@ -190,7 +190,7 @@ func testNewShard(t testing.TB, id int) *shard.Shard { shardOpts := append([]shard.Option{shard.WithID(sid)}, testDefaultShardOptions(t, id)...) s := shard.New(shardOpts...) - require.NoError(t, s.Open()) + require.NoError(t, s.Open(context.Background())) require.NoError(t, s.Init(context.Background())) return s diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 750918880f..0a48f81883 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -68,7 +68,7 @@ func newEngineWithErrorThreshold(t testing.TB, dir string, errThreshold uint32) } }) e := te.engine - require.NoError(t, e.Open()) + require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) for i, id := range te.shardIDs { @@ -192,7 +192,7 @@ func TestBlobstorFailback(t *testing.T) { } checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite) - require.NoError(t, te.ng.Close()) + require.NoError(t, te.ng.Close(context.Background())) p1 := te.ng.shards[te.shards[0].id.String()].Shard.DumpInfo().BlobStorInfo.SubStorages[1].Path p2 := te.ng.shards[te.shards[1].id.String()].Shard.DumpInfo().BlobStorInfo.SubStorages[1].Path diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 6030ba4942..c0c05d6618 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -44,7 +44,7 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng } }) e, ids := te.engine, te.shardIDs - require.NoError(t, e.Open()) + require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) objects := make([]*objectSDK.Object, 0, objPerShard*len(ids)) diff --git a/pkg/local_object_storage/engine/head_test.go b/pkg/local_object_storage/engine/head_test.go index e212ffa32b..5c123d6178 100644 --- a/pkg/local_object_storage/engine/head_test.go +++ b/pkg/local_object_storage/engine/head_test.go @@ -43,7 +43,7 @@ func TestHeadRaw(t *testing.T) { s2 := testNewShard(t, 2) e := testNewEngine(t).setInitializedShards(t, s1, s2).engine - defer e.Close() + defer e.Close(context.Background()) var putPrmLeft shard.PutPrm putPrmLeft.SetObject(child) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index a5f2420713..8fff6280ce 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -37,7 +37,7 @@ func TestStorageEngine_Inhume(t *testing.T) { t.Run("delete small object", func(t *testing.T) { e := testNewEngine(t).setShardsNum(t, 1).engine - defer e.Close() + defer e.Close(context.Background()) err := Put(context.Background(), e, parent) require.NoError(t, err) @@ -58,7 +58,7 @@ func TestStorageEngine_Inhume(t *testing.T) { s2 := testNewShard(t, 2) e := testNewEngine(t).setInitializedShards(t, s1, s2).engine - defer e.Close() + defer e.Close(context.Background()) var putChild shard.PutPrm putChild.SetObject(child) diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 8234c3c28d..eef25d2090 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -76,11 +76,11 @@ func TestListWithCursor(t *testing.T) { meta.WithEpochState(epochState{}), )} }).engine - require.NoError(t, e.Open()) + require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) t.Cleanup(func() { - e.Close() + e.Close(context.Background()) }) expected := make([]object.AddressWithType, 0, tt.objectNum) diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 906a867e22..d5c080222d 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -59,11 +59,11 @@ func TestLockUserScenario(t *testing.T) { } }) e := testEngine.engine - require.NoError(t, e.Open()) + require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) t.Cleanup(func() { - _ = e.Close() + _ = e.Close(context.Background()) }) lockerID := oidtest.ID() @@ -167,11 +167,11 @@ func TestLockExpiration(t *testing.T) { } }) e := testEngine.engine - require.NoError(t, e.Open()) + require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) t.Cleanup(func() { - _ = e.Close() + _ = e.Close(context.Background()) }) const lockerExpiresAfter = 13 @@ -247,10 +247,10 @@ func TestLockForceRemoval(t *testing.T) { shard.WithDeletedLockCallback(e.processDeletedLocks), } }).engine - require.NoError(t, e.Open()) + require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) t.Cleanup(func() { - _ = e.Close() + _ = e.Close(context.Background()) }) cnr := cidtest.ID() diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index f12a63e913..4b9d8752a8 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -1,6 +1,7 @@ package engine import ( + "context" "fmt" "sync/atomic" @@ -77,8 +78,8 @@ func (m *metricsWithID) DeleteShardMetrics() { // // Returns any error encountered that did not allow adding a shard. // Otherwise returns the ID of the added shard. -func (e *StorageEngine) AddShard(opts ...shard.Option) (*shard.ID, error) { - sh, err := e.createShard(opts) +func (e *StorageEngine) AddShard(ctx context.Context, opts ...shard.Option) (*shard.ID, error) { + sh, err := e.createShard(ctx, opts) if err != nil { return nil, fmt.Errorf("could not create a shard: %w", err) } @@ -95,7 +96,7 @@ func (e *StorageEngine) AddShard(opts ...shard.Option) (*shard.ID, error) { return sh.ID(), nil } -func (e *StorageEngine) createShard(opts []shard.Option) (*shard.Shard, error) { +func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (*shard.Shard, error) { id, err := generateShardID() if err != nil { return nil, fmt.Errorf("could not generate shard ID: %w", err) @@ -111,7 +112,7 @@ func (e *StorageEngine) createShard(opts []shard.Option) (*shard.Shard, error) { shard.WithReportErrorFunc(e.reportShardErrorBackground), )...) - if err := sh.UpdateID(); err != nil { + if err := sh.UpdateID(ctx); err != nil { return nil, fmt.Errorf("could not update shard ID: %w", err) } diff --git a/pkg/local_object_storage/engine/shards_test.go b/pkg/local_object_storage/engine/shards_test.go index 3631e33ed8..e13017e24e 100644 --- a/pkg/local_object_storage/engine/shards_test.go +++ b/pkg/local_object_storage/engine/shards_test.go @@ -1,6 +1,7 @@ package engine import ( + "context" "testing" "github.com/stretchr/testify/require" @@ -12,7 +13,7 @@ func TestRemoveShard(t *testing.T) { te := testNewEngine(t).setShardsNum(t, numOfShards) e, ids := te.engine, te.shardIDs t.Cleanup(func() { - e.Close() + e.Close(context.Background()) }) require.Equal(t, numOfShards, len(e.shardPools)) diff --git a/pkg/local_object_storage/internal/storagetest/storage.go b/pkg/local_object_storage/internal/storagetest/storage.go index 74400a9811..ec60a2d0e7 100644 --- a/pkg/local_object_storage/internal/storagetest/storage.go +++ b/pkg/local_object_storage/internal/storagetest/storage.go @@ -1,6 +1,7 @@ package storagetest import ( + "context" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -9,7 +10,7 @@ import ( // Component represents single storage component. type Component interface { - Open(bool) error + Open(context.Context, bool) error SetMode(mode.Mode) error Init() error Close() error @@ -57,18 +58,18 @@ func TestCloseAfterOpen(t *testing.T, cons Constructor) { t.Run("RW", func(t *testing.T) { // Use-case: irrecoverable error on some components, close everything. s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(context.Background(), false)) require.NoError(t, s.Close()) }) t.Run("RO", func(t *testing.T) { // Use-case: irrecoverable error on some components, close everything. // Open in read-only must be done after the db is here. s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(context.Background(), false)) require.NoError(t, s.Init()) require.NoError(t, s.Close()) - require.NoError(t, s.Open(true)) + require.NoError(t, s.Open(context.Background(), true)) require.NoError(t, s.Close()) }) } @@ -77,7 +78,7 @@ func TestCloseAfterOpen(t *testing.T, cons Constructor) { func TestCloseTwice(t *testing.T, cons Constructor) { // Use-case: move to maintenance mode twice, first time failed. s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(context.Background(), false)) require.NoError(t, s.Init()) require.NoError(t, s.Close()) require.NoError(t, s.Close()) // already closed, no-op @@ -89,12 +90,12 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { // Use-case: metabase `Init` failed, // call `SetMode` on all not-yet-initialized components. s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(context.Background(), false)) require.NoError(t, s.SetMode(m)) t.Run("after open in RO", func(t *testing.T) { require.NoError(t, s.Close()) - require.NoError(t, s.Open(true)) + require.NoError(t, s.Open(context.Background(), true)) require.NoError(t, s.SetMode(m)) }) @@ -103,7 +104,7 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { t.Run("after init", func(t *testing.T) { s := cons(t) // Use-case: notmal node operation. - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(context.Background(), false)) require.NoError(t, s.Init()) require.NoError(t, s.SetMode(m)) require.NoError(t, s.Close()) @@ -113,7 +114,7 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { func TestModeTransition(t *testing.T, cons Constructor, from, to mode.Mode) { // Use-case: normal node operation. s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(context.Background(), false)) require.NoError(t, s.Init()) require.NoError(t, s.SetMode(from)) require.NoError(t, s.SetMode(to)) diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index d0a9c4723e..3f155eeb55 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -1,6 +1,7 @@ package meta import ( + "context" "errors" "fmt" "path/filepath" @@ -21,7 +22,7 @@ var ErrDegradedMode = logicerr.New("metabase is in a degraded mode") var ErrReadOnlyMode = logicerr.New("metabase is in a read-only mode") // Open boltDB instance for metabase. -func (db *DB) Open(readOnly bool) error { +func (db *DB) Open(_ context.Context, readOnly bool) error { err := util.MkdirAllX(filepath.Dir(db.info.Path), db.info.Permission) if err != nil { return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err) diff --git a/pkg/local_object_storage/metabase/db_test.go b/pkg/local_object_storage/metabase/db_test.go index 6169dd81e7..bc5015b60e 100644 --- a/pkg/local_object_storage/metabase/db_test.go +++ b/pkg/local_object_storage/metabase/db_test.go @@ -1,6 +1,7 @@ package meta_test import ( + "context" "os" "path/filepath" "strconv" @@ -49,7 +50,7 @@ func newDB(t testing.TB, opts ...meta.Option) *meta.DB { }, opts...)..., ) - require.NoError(t, bdb.Open(false)) + require.NoError(t, bdb.Open(context.Background(), false)) require.NoError(t, bdb.Init()) t.Cleanup(func() { diff --git a/pkg/local_object_storage/metabase/mode.go b/pkg/local_object_storage/metabase/mode.go index 28beca8f35..a18095f3e3 100644 --- a/pkg/local_object_storage/metabase/mode.go +++ b/pkg/local_object_storage/metabase/mode.go @@ -1,6 +1,7 @@ package meta import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -27,9 +28,9 @@ func (db *DB) SetMode(m mode.Mode) error { case m.NoMetabase(): db.boltDB = nil case m.ReadOnly(): - err = db.Open(true) + err = db.Open(context.TODO(), true) default: - err = db.Open(false) + err = db.Open(context.TODO(), false) } if err == nil && !m.NoMetabase() && !m.ReadOnly() { err = db.Init() diff --git a/pkg/local_object_storage/metabase/version_test.go b/pkg/local_object_storage/metabase/version_test.go index 70ded67a4f..6f011c2466 100644 --- a/pkg/local_object_storage/metabase/version_test.go +++ b/pkg/local_object_storage/metabase/version_test.go @@ -1,6 +1,7 @@ package meta import ( + "context" "encoding/binary" "errors" "fmt" @@ -42,13 +43,13 @@ func TestVersion(t *testing.T) { } t.Run("simple", func(t *testing.T) { db := newDB(t) - require.NoError(t, db.Open(false)) + require.NoError(t, db.Open(context.Background(), false)) require.NoError(t, db.Init()) check(t, db) require.NoError(t, db.Close()) t.Run("reopen", func(t *testing.T) { - require.NoError(t, db.Open(false)) + require.NoError(t, db.Open(context.Background(), false)) require.NoError(t, db.Init()) check(t, db) require.NoError(t, db.Close()) @@ -56,29 +57,29 @@ func TestVersion(t *testing.T) { }) t.Run("old data", func(t *testing.T) { db := newDB(t) - require.NoError(t, db.Open(false)) + require.NoError(t, db.Open(context.Background(), false)) require.NoError(t, db.WriteShardID([]byte{1, 2, 3, 4})) require.NoError(t, db.Close()) - require.NoError(t, db.Open(false)) + require.NoError(t, db.Open(context.Background(), false)) require.NoError(t, db.Init()) check(t, db) require.NoError(t, db.Close()) }) t.Run("invalid version", func(t *testing.T) { db := newDB(t) - require.NoError(t, db.Open(false)) + require.NoError(t, db.Open(context.Background(), false)) require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error { return updateVersion(tx, version+1) })) require.NoError(t, db.Close()) - require.NoError(t, db.Open(false)) + require.NoError(t, db.Open(context.Background(), false)) require.Error(t, db.Init()) require.NoError(t, db.Close()) t.Run("reset", func(t *testing.T) { - require.NoError(t, db.Open(false)) + require.NoError(t, db.Open(context.Background(), false)) require.NoError(t, db.Reset()) check(t, db) require.NoError(t, db.Close()) diff --git a/pkg/local_object_storage/pilorama/bench_test.go b/pkg/local_object_storage/pilorama/bench_test.go index e729b9ea60..3d5ff1a7ca 100644 --- a/pkg/local_object_storage/pilorama/bench_test.go +++ b/pkg/local_object_storage/pilorama/bench_test.go @@ -26,7 +26,7 @@ func BenchmarkCreate(b *testing.B) { f := NewBoltForest( WithPath(filepath.Join(tmpDir, "test.db")), WithMaxBatchSize(runtime.GOMAXPROCS(0))) - require.NoError(b, f.Open(false)) + require.NoError(b, f.Open(context.Background(), false)) require.NoError(b, f.Init()) b.Cleanup(func() { require.NoError(b, f.Close()) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index c9a9f039eb..2689e345a7 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -99,7 +99,7 @@ func (t *boltForest) SetMode(m mode.Mode) error { err := t.Close() if err == nil && !m.NoMetabase() { - if err = t.Open(m.ReadOnly()); err == nil { + if err = t.Open(context.TODO(), m.ReadOnly()); err == nil { err = t.Init() } } @@ -111,7 +111,7 @@ func (t *boltForest) SetMode(m mode.Mode) error { t.metrics.SetMode(m) return nil } -func (t *boltForest) Open(readOnly bool) error { +func (t *boltForest) Open(_ context.Context, readOnly bool) error { err := util.MkdirAllX(filepath.Dir(t.path), t.perm) if err != nil { return metaerr.Wrap(fmt.Errorf("can't create dir %s for the pilorama: %w", t.path, err)) diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index 8fb519128d..e5612d2b95 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -110,7 +110,7 @@ func (f *memoryForest) Init() error { return nil } -func (f *memoryForest) Open(bool) error { +func (f *memoryForest) Open(context.Context, bool) error { return nil } func (f *memoryForest) SetMode(mode.Mode) error { diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 6f657873a5..8e7fec2007 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -24,7 +24,7 @@ var providers = []struct { }{ {"inmemory", func(t testing.TB, _ ...Option) Forest { f := NewMemoryForest() - require.NoError(t, f.Open(false)) + require.NoError(t, f.Open(context.Background(), false)) require.NoError(t, f.Init()) t.Cleanup(func() { require.NoError(t, f.Close()) @@ -37,7 +37,7 @@ var providers = []struct { append([]Option{ WithPath(filepath.Join(t.TempDir(), "test.db")), WithMaxBatchSize(1)}, opts...)...) - require.NoError(t, f.Open(false)) + require.NoError(t, f.Open(context.Background(), false)) require.NoError(t, f.Init()) t.Cleanup(func() { require.NoError(t, f.Close()) diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index ea171a479f..e7f7eb512a 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -58,7 +58,7 @@ type ForestStorage interface { // DumpInfo returns information about the pilorama. DumpInfo() Info Init() error - Open(bool) error + Open(context.Context, bool) error Close() error SetMode(m mode.Mode) error SetParentID(id string) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index a49a790438..257498b32c 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -41,8 +41,10 @@ func (s *Shard) handleMetabaseFailure(stage string, err error) error { } // Open opens all Shard's components. -func (s *Shard) Open() error { - components := []interface{ Open(bool) error }{ +func (s *Shard) Open(ctx context.Context) error { + components := []interface { + Open(context.Context, bool) error + }{ s.blobStor, s.metaBase, } @@ -55,12 +57,12 @@ func (s *Shard) Open() error { } for i, component := range components { - if err := component.Open(false); err != nil { + if err := component.Open(ctx, false); err != nil { if component == s.metaBase { // We must first open all other components to avoid // opening non-existent DB in read-only mode. for j := i + 1; j < len(components); j++ { - if err := components[j].Open(false); err != nil { + if err := components[j].Open(ctx, false); err != nil { // Other components must be opened, fail. return fmt.Errorf("could not open %T: %w", components[j], err) } diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 128e5cc0c7..749229cc3b 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -87,7 +87,7 @@ func TestShardOpen(t *testing.T) { allowedMode.Store(int64(os.O_RDWR)) sh := newShard() - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) require.Equal(t, mode.ReadWrite, sh.GetMode()) require.NoError(t, sh.Close()) @@ -96,7 +96,7 @@ func TestShardOpen(t *testing.T) { allowedMode.Store(int64(os.O_RDONLY)) sh = newShard() - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) require.Equal(t, mode.ReadOnly, sh.GetMode()) require.Error(t, sh.SetMode(mode.ReadWrite)) @@ -107,7 +107,7 @@ func TestShardOpen(t *testing.T) { allowedMode.Store(math.MaxInt64) sh = newShard() - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) require.Equal(t, mode.DegradedReadOnly, sh.GetMode()) require.NoError(t, sh.Close()) @@ -135,7 +135,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) { WithBlobStorOptions(blobOpts...), WithPiloramaOptions(pilorama.WithPath(filepath.Join(dir, "pilorama"))), WithMetaBaseOptions(meta.WithPath(filepath.Join(dir, "meta")), meta.WithEpochState(epochState{}))) - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) obj := objecttest.Object() @@ -158,7 +158,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) { WithPiloramaOptions(pilorama.WithPath(filepath.Join(dir, "pilorama"))), WithMetaBaseOptions(meta.WithPath(filepath.Join(dir, "meta_new")), meta.WithEpochState(epochState{})), WithRefillMetabase(true)) - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) var getPrm GetPrm @@ -197,7 +197,7 @@ func TestRefillMetabase(t *testing.T) { ) // open Blobstor - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) // initialize Blobstor require.NoError(t, sh.Init(context.Background())) @@ -365,7 +365,7 @@ func TestRefillMetabase(t *testing.T) { ) // open Blobstor - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) // initialize Blobstor require.NoError(t, sh.Init(context.Background())) diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index c8925e01f6..332cdf5be0 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -76,7 +76,7 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { sh = New(opts...) sh.gcCfg.testHookRemover = func(context.Context) gcRunResult { return gcRunResult{} } - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) t.Cleanup(func() { diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index 49f9a30434..b0d95e54ca 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -1,6 +1,8 @@ package shard import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/mr-tron/base58" "go.uber.org/zap" @@ -27,8 +29,8 @@ func (s *Shard) ID() *ID { } // UpdateID reads shard ID saved in the metabase and updates it if it is missing. -func (s *Shard) UpdateID() (err error) { - if err = s.metaBase.Open(false); err != nil { +func (s *Shard) UpdateID(ctx context.Context) (err error) { + if err = s.metaBase.Open(ctx, false); err != nil { return err } defer func() { diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index be9a0ba9a0..ca6b0ca382 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -58,7 +58,7 @@ func TestShard_Lock(t *testing.T) { } sh = New(opts...) - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) t.Cleanup(func() { diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index ae993c79cf..23721af6ec 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -269,7 +269,7 @@ func shardWithMetrics(t *testing.T, path string) (*Shard, *metricsStore) { meta.WithEpochState(epochState{})), WithMetricsWriter(mm), ) - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) t.Cleanup(func() { diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index c89c0cb7ec..9cfa267e86 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -52,7 +52,7 @@ func TestShardReload(t *testing.T) { pilorama.WithPath(filepath.Join(p, "pilorama")))} sh := New(opts...) - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) objects := make([]objAddr, 5) diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 5dcccd9c96..9da9eb6b87 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -117,7 +117,7 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard sh = New(opts...) - require.NoError(t, sh.Open()) + require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) if !o.dontRelease { diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index 6ae04a92a6..16c6d73b2e 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -82,7 +82,7 @@ func benchmarkPutPar(b *testing.B, cache writecache.Cache, size uint64) { } func benchmarkPutPrepare(b *testing.B, cache writecache.Cache) { - require.NoError(b, cache.Open(false), "opening") + require.NoError(b, cache.Open(context.Background(), false), "opening") require.NoError(b, cache.Init(), "initializing") b.Cleanup(func() { require.NoError(b, cache.Close(), "closing") diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 8c86373582..c2fdc100f8 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -38,7 +38,7 @@ type Cache interface { Flush(context.Context, bool) error Init() error - Open(readOnly bool) error + Open(ctx context.Context, readOnly bool) error Close() error } diff --git a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go index 28aa7e7661..6dd4755b3e 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go +++ b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go @@ -1,6 +1,7 @@ package writecachebadger import ( + "context" "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -83,7 +84,7 @@ func (c *cache) DumpInfo() writecache.Info { } // Open opens and initializes database. Reads object counters from the ObjectCounters instance. -func (c *cache) Open(readOnly bool) error { +func (c *cache) Open(_ context.Context, readOnly bool) error { err := c.openStore(readOnly) if err != nil { return metaerr.Wrap(err) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go b/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go index 407d1a9ce2..11bdbe07b7 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go @@ -1,6 +1,7 @@ package writecachebbolt import ( + "context" "os" "sync" @@ -97,7 +98,7 @@ func (c *cache) DumpInfo() writecache.Info { } // Open opens and initializes database. Reads object counters from the ObjectCounters instance. -func (c *cache) Open(readOnly bool) error { +func (c *cache) Open(_ context.Context, readOnly bool) error { err := c.openStore(readOnly) if err != nil { return metaerr.Wrap(err) diff --git a/pkg/local_object_storage/writecache/writecachetest/flush.go b/pkg/local_object_storage/writecache/writecachetest/flush.go index 05b4b23acb..6911344a28 100644 --- a/pkg/local_object_storage/writecache/writecachetest/flush.go +++ b/pkg/local_object_storage/writecache/writecachetest/flush.go @@ -110,7 +110,7 @@ func newCache[Option any]( mb := meta.New( meta.WithPath(filepath.Join(dir, "meta")), meta.WithEpochState(dummyEpoch{})) - require.NoError(t, mb.Open(false)) + require.NoError(t, mb.Open(context.Background(), false)) require.NoError(t, mb.Init()) bs := blobstor.New(blobstor.WithStorages([]blobstor.SubStorage{ @@ -121,12 +121,12 @@ func newCache[Option any]( fstree.WithDirNameLen(1)), }, })) - require.NoError(t, bs.Open(false)) + require.NoError(t, bs.Open(context.Background(), false)) require.NoError(t, bs.Init()) wc := createCacheFn(t, smallSize, mb, bs, opts...) t.Cleanup(func() { require.NoError(t, wc.Close()) }) - require.NoError(t, wc.Open(false)) + require.NoError(t, wc.Open(context.Background(), false)) require.NoError(t, wc.Init()) // First set mode for metabase and blobstor to prevent background flushes. From aa9f8dce3deae69c2f5df8aa11a76db2d578a4b0 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 6 Sep 2023 15:53:53 +0300 Subject: [PATCH 0050/1413] [#677] client: Refactor PrmAnnounceSpace/EndpointInfo/NetworkInfo usage Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/client.go | 12 ++++++------ cmd/frostfs-cli/modules/netmap/get_epoch.go | 5 +++-- cmd/frostfs-cli/modules/netmap/netinfo.go | 5 +++-- cmd/frostfs-cli/modules/netmap/nodeinfo.go | 5 +++-- cmd/frostfs-cli/modules/session/create.go | 5 +++-- cmd/frostfs-node/container.go | 6 +++--- go.mod | 2 +- go.sum | 4 ++-- 8 files changed, 24 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 7fbfd51057..ffed877c70 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -224,8 +224,8 @@ func SetEACL(ctx context.Context, prm SetEACLPrm) (res SetEACLRes, err error) { // NetworkInfoPrm groups parameters of NetworkInfo operation. type NetworkInfoPrm struct { - commonPrm - client.PrmNetworkInfo + Client *client.Client + ClientParams client.PrmNetworkInfo } // NetworkInfoRes groups the resulting values of NetworkInfo operation. @@ -242,15 +242,15 @@ func (x NetworkInfoRes) NetworkInfo() netmap.NetworkInfo { // // Returns any error which prevented the operation from completing correctly in error return. func NetworkInfo(ctx context.Context, prm NetworkInfoPrm) (res NetworkInfoRes, err error) { - res.cliRes, err = prm.cli.NetworkInfo(ctx, prm.PrmNetworkInfo) + res.cliRes, err = prm.Client.NetworkInfo(ctx, prm.ClientParams) return } // NodeInfoPrm groups parameters of NodeInfo operation. type NodeInfoPrm struct { - commonPrm - client.PrmEndpointInfo + Client *client.Client + ClientParams client.PrmEndpointInfo } // NodeInfoRes groups the resulting values of NodeInfo operation. @@ -272,7 +272,7 @@ func (x NodeInfoRes) LatestVersion() version.Version { // // Returns any error which prevented the operation from completing correctly in error return. func NodeInfo(ctx context.Context, prm NodeInfoPrm) (res NodeInfoRes, err error) { - res.cliRes, err = prm.cli.EndpointInfo(ctx, prm.PrmEndpointInfo) + res.cliRes, err = prm.Client.EndpointInfo(ctx, prm.ClientParams) return } diff --git a/cmd/frostfs-cli/modules/netmap/get_epoch.go b/cmd/frostfs-cli/modules/netmap/get_epoch.go index a9c2e1f19d..1670f16c0c 100644 --- a/cmd/frostfs-cli/modules/netmap/get_epoch.go +++ b/cmd/frostfs-cli/modules/netmap/get_epoch.go @@ -16,8 +16,9 @@ var getEpochCmd = &cobra.Command{ p := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) - var prm internalclient.NetworkInfoPrm - prm.SetClient(cli) + prm := internalclient.NetworkInfoPrm{ + Client: cli, + } res, err := internalclient.NetworkInfo(cmd.Context(), prm) commonCmd.ExitOnErr(cmd, "rpc error: %w", err) diff --git a/cmd/frostfs-cli/modules/netmap/netinfo.go b/cmd/frostfs-cli/modules/netmap/netinfo.go index 3c1839114f..ceea6a890f 100644 --- a/cmd/frostfs-cli/modules/netmap/netinfo.go +++ b/cmd/frostfs-cli/modules/netmap/netinfo.go @@ -20,8 +20,9 @@ var netInfoCmd = &cobra.Command{ p := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) - var prm internalclient.NetworkInfoPrm - prm.SetClient(cli) + prm := internalclient.NetworkInfoPrm{ + Client: cli, + } res, err := internalclient.NetworkInfo(cmd.Context(), prm) commonCmd.ExitOnErr(cmd, "rpc error: %w", err) diff --git a/cmd/frostfs-cli/modules/netmap/nodeinfo.go b/cmd/frostfs-cli/modules/netmap/nodeinfo.go index 3b2113efb4..bf73286ed7 100644 --- a/cmd/frostfs-cli/modules/netmap/nodeinfo.go +++ b/cmd/frostfs-cli/modules/netmap/nodeinfo.go @@ -22,8 +22,9 @@ var nodeInfoCmd = &cobra.Command{ p := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) - var prm internalclient.NodeInfoPrm - prm.SetClient(cli) + prm := internalclient.NodeInfoPrm{ + Client: cli, + } res, err := internalclient.NodeInfo(cmd.Context(), prm) commonCmd.ExitOnErr(cmd, "rpc error: %w", err) diff --git a/cmd/frostfs-cli/modules/session/create.go b/cmd/frostfs-cli/modules/session/create.go index 53f6e8bc49..c578fc6b7c 100644 --- a/cmd/frostfs-cli/modules/session/create.go +++ b/cmd/frostfs-cli/modules/session/create.go @@ -91,8 +91,9 @@ func createSession(cmd *cobra.Command, _ []string) { // // Fills ID, lifetime and session key. func CreateSession(ctx context.Context, dst *session.Object, c *client.Client, lifetime uint64) error { - var netInfoPrm internalclient.NetworkInfoPrm - netInfoPrm.SetClient(c) + netInfoPrm := internalclient.NetworkInfoPrm{ + Client: c, + } ni, err := internalclient.NetworkInfo(ctx, netInfoPrm) if err != nil { diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 5d88ff9ea5..d54bf13dd1 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -383,9 +383,9 @@ func (r *remoteLoadAnnounceWriter) Put(a containerSDK.SizeEstimation) error { } func (r *remoteLoadAnnounceWriter) Close(ctx context.Context) error { - var cliPrm apiClient.PrmAnnounceSpace - - cliPrm.SetValues(r.buf) + cliPrm := apiClient.PrmAnnounceSpace{ + Announcements: r.buf, + } _, err := r.client.ContainerAnnounceUsedSpace(ctx, cliPrm) return err diff --git a/go.mod b/go.mod index 6d5382b757..e9b00cd674 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230802075510-964c3edb3f44 git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230627134746-36f3d39c406a git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904141422-5a471e5002a7 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904165523-55a1f23e7170 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 6c8b417041..1d00dcf373 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904141422-5a471e5002a7 h1:fwEDv/1INboZGbfQDxlsdbZGvHNUL/73rQe4fG8G3DA= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904141422-5a471e5002a7/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904165523-55a1f23e7170 h1:nOS6QWW8O4xDpL61TXe+NBpVXTB/fP4zy0lRh0eAWfI= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904165523-55a1f23e7170/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= From f435ab1b26c93769ec6b08daf328f8d5541bf280 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Sep 2023 10:05:44 +0300 Subject: [PATCH 0051/1413] [#682] go.mod: Update sdk-go Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/internal/client/client.go | 45 ++++++++++------------- cmd/frostfs-cli/modules/session/create.go | 2 +- go.mod | 2 +- go.sum | 4 +- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index ffed877c70..4cc206925d 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -8,6 +8,7 @@ import ( "io" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -773,39 +774,33 @@ func (x HashPayloadRangesRes) HashList() [][]byte { // Returns any error which prevented the operation from completing correctly in error return. // Returns an error if number of received hashes differs with the number of requested ranges. func HashPayloadRanges(ctx context.Context, prm HashPayloadRangesPrm) (*HashPayloadRangesRes, error) { - var cliPrm client.PrmObjectHash - cliPrm.FromContainer(prm.objAddr.Container()) - cliPrm.ByID(prm.objAddr.Object()) + rngs := make([]objectSDK.Range, len(prm.rngs)) - if prm.local { - cliPrm.MarkLocal() + for i, r := range prm.rngs { + if r != nil { + rngs[i] = *r + } } - cliPrm.UseSalt(prm.salt) - - rngs := make([]uint64, 2*len(prm.rngs)) - - for i := range prm.rngs { - rngs[2*i] = prm.rngs[i].GetOffset() - rngs[2*i+1] = prm.rngs[i].GetLength() - } - - cliPrm.SetRangeList(rngs...) - + cs := checksum.SHA256 if prm.tz { - cliPrm.TillichZemorAlgo() + cs = checksum.TZ } - if prm.sessionToken != nil { - cliPrm.WithinSession(*prm.sessionToken) + cnr := prm.objAddr.Container() + obj := prm.objAddr.Object() + cliPrm := client.PrmObjectHash{ + ContainerID: &cnr, + ObjectID: &obj, + Local: prm.local, + Salt: prm.salt, + Ranges: rngs, + ChecksumType: cs, + Session: prm.sessionToken, + BearerToken: prm.bearerToken, + XHeaders: prm.xHeaders, } - if prm.bearerToken != nil { - cliPrm.WithBearerToken(*prm.bearerToken) - } - - cliPrm.WithXHeaders(prm.xHeaders...) - res, err := prm.cli.ObjectHash(ctx, cliPrm) if err != nil { return nil, fmt.Errorf("read payload hashes via client: %w", err) diff --git a/cmd/frostfs-cli/modules/session/create.go b/cmd/frostfs-cli/modules/session/create.go index c578fc6b7c..f9705c0232 100644 --- a/cmd/frostfs-cli/modules/session/create.go +++ b/cmd/frostfs-cli/modules/session/create.go @@ -105,7 +105,7 @@ func CreateSession(ctx context.Context, dst *session.Object, c *client.Client, l var sessionPrm internalclient.CreateSessionPrm sessionPrm.SetClient(c) - sessionPrm.SetExp(exp) + sessionPrm.Expiration = exp sessionRes, err := internalclient.CreateSession(ctx, sessionPrm) if err != nil { diff --git a/go.mod b/go.mod index e9b00cd674..a6582d4295 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230802075510-964c3edb3f44 git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230627134746-36f3d39c406a git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904165523-55a1f23e7170 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 1d00dcf373..a054f882af 100644 --- a/go.sum +++ b/go.sum @@ -44,8 +44,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904165523-55a1f23e7170 h1:nOS6QWW8O4xDpL61TXe+NBpVXTB/fP4zy0lRh0eAWfI= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230904165523-55a1f23e7170/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c h1:gD+dj5IZx9jlniDu8TlLQdRGCd8KIOzYjjdDd1KcVdI= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= From 3c76884182450c48f2cb4723cd5c61fbc401d409 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Sep 2023 10:41:29 +0300 Subject: [PATCH 0052/1413] [#682] cli: Unify array of ranges type Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/internal/client/client.go | 14 +++----------- cmd/frostfs-cli/modules/object/range.go | 7 +++---- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 4cc206925d..e8869bc8ca 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -739,7 +739,7 @@ type HashPayloadRangesPrm struct { tz bool - rngs []*objectSDK.Range + rngs []objectSDK.Range salt []byte } @@ -750,7 +750,7 @@ func (x *HashPayloadRangesPrm) TZ() { } // SetRanges sets a list of payload ranges to hash. -func (x *HashPayloadRangesPrm) SetRanges(rngs []*objectSDK.Range) { +func (x *HashPayloadRangesPrm) SetRanges(rngs []objectSDK.Range) { x.rngs = rngs } @@ -774,14 +774,6 @@ func (x HashPayloadRangesRes) HashList() [][]byte { // Returns any error which prevented the operation from completing correctly in error return. // Returns an error if number of received hashes differs with the number of requested ranges. func HashPayloadRanges(ctx context.Context, prm HashPayloadRangesPrm) (*HashPayloadRangesRes, error) { - rngs := make([]objectSDK.Range, len(prm.rngs)) - - for i, r := range prm.rngs { - if r != nil { - rngs[i] = *r - } - } - cs := checksum.SHA256 if prm.tz { cs = checksum.TZ @@ -794,7 +786,7 @@ func HashPayloadRanges(ctx context.Context, prm HashPayloadRangesPrm) (*HashPayl ObjectID: &obj, Local: prm.local, Salt: prm.salt, - Ranges: rngs, + Ranges: prm.rngs, ChecksumType: cs, Session: prm.sessionToken, BearerToken: prm.bearerToken, diff --git a/cmd/frostfs-cli/modules/object/range.go b/cmd/frostfs-cli/modules/object/range.go index 591355b952..0eee7bdbab 100644 --- a/cmd/frostfs-cli/modules/object/range.go +++ b/cmd/frostfs-cli/modules/object/range.go @@ -84,7 +84,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) { raw, _ := cmd.Flags().GetBool(rawFlag) prm.SetRawFlag(raw) prm.SetAddress(objAddr) - prm.SetRange(ranges[0]) + prm.SetRange(&ranges[0]) prm.SetPayloadWriter(out) _, err = internalclient.PayloadRange(cmd.Context(), prm) @@ -146,13 +146,13 @@ func marshalSplitInfo(cmd *cobra.Command, info *objectSDK.SplitInfo) ([]byte, er } } -func getRangeList(cmd *cobra.Command) ([]*objectSDK.Range, error) { +func getRangeList(cmd *cobra.Command) ([]objectSDK.Range, error) { v := cmd.Flag("range").Value.String() if len(v) == 0 { return nil, nil } vs := strings.Split(v, ",") - rs := make([]*objectSDK.Range, len(vs)) + rs := make([]objectSDK.Range, len(vs)) for i := range vs { before, after, found := strings.Cut(vs[i], rangeSep) if !found { @@ -176,7 +176,6 @@ func getRangeList(cmd *cobra.Command) ([]*objectSDK.Range, error) { return nil, fmt.Errorf("invalid '%s' range: uint64 overflow", vs[i]) } - rs[i] = objectSDK.NewRange() rs[i].SetOffset(offset) rs[i].SetLength(length) } From 58239d1b2c5326879f362e10a14a84b5f669485f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Sep 2023 10:44:43 +0300 Subject: [PATCH 0053/1413] [#683] cli: Add context to policy parsing errors Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/container/create.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index 10d53a7d8d..37827b617f 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -185,12 +185,12 @@ func parseContainerPolicy(cmd *cobra.Command, policyString string) (*netmap.Plac return &result, nil } - if err = result.UnmarshalJSON([]byte(policyString)); err == nil { + if err := result.UnmarshalJSON([]byte(policyString)); err == nil { common.PrintVerbose(cmd, "Parsed JSON encoded policy") return &result, nil } - return nil, errors.New("can't parse placement policy") + return nil, fmt.Errorf("can't parse placement policy: %w", err) } func parseAttributes(dst *container.Container, attributes []string) error { From c6af4a3ec80e6d2170c9f19c0235454a00405f4d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 13 Sep 2023 11:25:59 +0300 Subject: [PATCH 0054/1413] [#679] engine: Do not increase error counter on meta mismatch It was introduced in 69e1e6ca to help node determine faulty shards. However, the situation is possible in a real-life scenario: 1. Object O is evacuated from shard A to B. 2. Shard A is unmounted because of lower-level errors. 3. We now have object in meta on A and in blobstor on B. Technically we have it in meta on shard B too, but we still got the error if B goes to a degraded mode. Signed-off-by: Evgenii Stratonikov --- internal/logs/logs.go | 1 + pkg/local_object_storage/engine/error_test.go | 2 +- pkg/local_object_storage/engine/get.go | 9 ++++++--- pkg/local_object_storage/engine/range.go | 8 +++++--- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 1c5815c6c7..c18d191f86 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -258,6 +258,7 @@ const ( ShardMetaObjectCounterRead = "meta: object counter read" ShardMetaCantReadContainerList = "meta: can't read container list" ShardMetaCantReadContainerSize = "meta: can't read container size" + ShardMetaInfoPresentButObjectNotFound = "meta info was present, but the object is missing" ShardMetabaseFailureSwitchingMode = "metabase failure, switching mode" ShardCantMoveShardToReadonlySwitchMode = "can't move shard to readonly, switch mode" ShardCouldNotUnmarshalObject = "could not unmarshal object" diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 0a48f81883..90356104e3 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -217,7 +217,7 @@ func TestBlobstorFailback(t *testing.T) { require.True(t, shard.IsErrOutOfRange(err)) } - checkShardState(t, te.ng, te.shards[0].id, 2, mode.ReadOnly) + checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite) checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) } diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index 2f736146cd..5d888238e7 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" @@ -100,9 +101,11 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { if it.Object == nil { return GetRes{}, it.OutError } - if it.ShardWithMeta.Shard != nil { - e.reportShardError(it.ShardWithMeta, "meta info was present, but object is missing", - it.MetaError, zap.Stringer("address", prm.addr)) + if it.ShardWithMeta.Shard != nil && it.MetaError != nil { + e.log.Warn(logs.ShardMetaInfoPresentButObjectNotFound, + zap.Stringer("shard_id", it.ShardWithMeta.ID()), + zap.String("error", it.MetaError.Error()), + zap.Stringer("address", prm.addr)) } } diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index b3aaea6f5f..fb0873ee28 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -5,6 +5,7 @@ import ( "errors" "strconv" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" @@ -113,9 +114,10 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error if it.Object == nil { return RngRes{}, it.OutError } - if it.ShardWithMeta.Shard != nil { - e.reportShardError(it.ShardWithMeta, "meta info was present, but object is missing", - it.MetaError, + if it.ShardWithMeta.Shard != nil && it.MetaError != nil { + e.log.Warn(logs.ShardMetaInfoPresentButObjectNotFound, + zap.Stringer("shard_id", it.ShardWithMeta.ID()), + zap.String("error", it.MetaError.Error()), zap.Stringer("address", prm.addr)) } } From 10570fc0350e51dd7f66fee19419d81d9227cec7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 14 Sep 2023 14:47:55 +0300 Subject: [PATCH 0055/1413] [#690] go.mod: Update contract and api-go Signed-off-by: Evgenii Stratonikov --- go.mod | 8 +- go.sum | 681 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 674 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index a6582d4295..89f437216b 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module git.frostfs.info/TrueCloudLab/frostfs-node go 1.20 require ( - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230802075510-964c3edb3f44 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230627134746-36f3d39c406a + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c git.frostfs.info/TrueCloudLab/hrw v1.2.1 @@ -20,7 +20,7 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.9.0 github.com/nats-io/nats.go v1.27.1 - github.com/nspcc-dev/neo-go v0.101.2-0.20230601131642-a0117042e8fc + github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.7.5 github.com/paulmach/orb v0.9.2 @@ -97,7 +97,7 @@ require ( github.com/nats-io/nkeys v0.4.4 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 // indirect - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230615193820-9185820289ce // indirect + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5 // indirect github.com/nspcc-dev/rfc6979 v0.2.0 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index a054f882af..5bcd5e4289 100644 --- a/go.sum +++ b/go.sum @@ -17,29 +17,378 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= +cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= +cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= +cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= +cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= +cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= +cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= +cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= +cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= +cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= +cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= +cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= +cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= +cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= +cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= +cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= +cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= +cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= +cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= +cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= +cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= +cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= +cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= +cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= +cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= +cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= +cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= +cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= +cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= +cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= +cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= +cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= +cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= +cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= +cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= +cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= +cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= +cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= +cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= +cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= +cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= +cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= +cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= +cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= +cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= +cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= +cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= +cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= +cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= +cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= +cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= +cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= +cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= +cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= +cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= +cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= +cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= +cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= +cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= +cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= +cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= +cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= +cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= +cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= +cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= +cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= +cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= +cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= +cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= +cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= +cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= +cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= +cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= +cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= +cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= +cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= +cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= +cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= +cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= +cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= +cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= +cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= +cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= +cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= +cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= +cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= +cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= +cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= +cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= +cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= +cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= +cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= +cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= +cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= +cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= +cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= +cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= +cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= +cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= +cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= +cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= +cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= +cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= +cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= +cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= +cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= +cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= +cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= +cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= +cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= +cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= +cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= +cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= +cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= +cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= +cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= +cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= +cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= +cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= +cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= +cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= +cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= +cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= +cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= +cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= +cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= +cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= +cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= +cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= +cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= +cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= +cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= +cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= +cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= +cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= +cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= +cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= +cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= +cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= +cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= +cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= +cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= +cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= +cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= +cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= +cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= +cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= +cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= +cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= +cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= +cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= +cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= +cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= +cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= +cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= +cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= +cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= +cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= +cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= +cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= +cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= +cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= +cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= +cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= +cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= +cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= +cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= +cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= +cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= +cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= +cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= +cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= +cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= +cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= +cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= +cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= +cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= +cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= +cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= +cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= +cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= +cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= +cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= +cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= +cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= +cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= +cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= +cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= +cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= +cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= +cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= +cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= +cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= +cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= +cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= +cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= +cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= +cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= +cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= +cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= +cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= +cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230802075510-964c3edb3f44 h1:v6JqBD/VzZx3QSxbaXnUwnnJ1KEYheU4LzLGr3IhsAE= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.15.1-0.20230802075510-964c3edb3f44/go.mod h1:pKJJRLOChW4zDQsAt1e8k/snWKljJtpkiPfxV53ngjI= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230627134746-36f3d39c406a h1:EeaOunifY30ATPzOo1F32vUDW299UXDHYukZrIVxBZ0= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.0.0-20230627134746-36f3d39c406a/go.mod h1:nkR5gaGeez3Zv2SE7aceP0YwxG2FzIB5cGKpQO2vV2o= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 h1:vy6leTEGcKVrLmKfeK5pGGIi3D1vn6rX32Hy4gIOWto= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0 h1:9ahw69njrwf2legz5xNVTA+4A6UwcBzy9oBdbJmoBxU= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0/go.mod h1:3V8FyzpbIIxzpgfUaSlOJBAT11IzhZzkQnGpYvRQR5E= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= @@ -59,6 +408,7 @@ github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1 github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig= github.com/CityOfZion/neo-go v0.70.1-pre.0.20191212173117-32ac01130d4c/go.mod h1:JtlHfeqLywZLswKIKFnAp+yzezY4Dji9qlfQKB2OD/I= github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1:FLI526IrRWHmcsO+mHsCbj64pJZhwQFTLJZu+A4PGOA= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= github.com/abiosoft/ishell/v2 v2.0.2/go.mod h1:E4oTCXfo6QjoCart0QYa5m9w4S+deXs/P/9jA77A9Bs= @@ -73,6 +423,7 @@ github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGn github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521073959-f0d4d129b7f1/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -99,6 +450,9 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -119,9 +473,18 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.9.1/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4= github.com/consensys/gnark-crypto v0.11.0 h1:QqzHQlwEqlQr5jfWblGDkwlKHpT+4QodYqqExkAtyks= github.com/consensys/gnark-crypto v0.11.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -133,6 +496,8 @@ github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= @@ -149,8 +514,14 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= +github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -160,6 +531,7 @@ github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWT github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= @@ -188,6 +560,7 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -203,6 +576,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -218,11 +592,13 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= @@ -242,12 +618,15 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -258,14 +637,31 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= +github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= +github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -275,6 +671,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0/go github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.5 h1:3IZOAnD058zZllQTZNBioTlrzrBG/IjpiZ133IEtusM= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.5/go.mod h1:xbKERva94Pw2cPen0s79J3uXmGzbbpDYFBFDlZ4mV/w= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -290,8 +688,10 @@ github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25 github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= @@ -325,11 +725,15 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -396,30 +800,39 @@ github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk= github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ= github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= -github.com/nspcc-dev/dbft v0.0.0-20220902113116-58a5e763e647/go.mod h1:g9xisXmX9NP9MjioaTe862n9SlZTrP+6PVUWLBYOr98= +github.com/nspcc-dev/dbft v0.0.0-20220629112714-fd49ca59d354/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= +github.com/nspcc-dev/dbft v0.0.0-20221020093431-31c1bbdc74f2/go.mod h1:g9xisXmX9NP9MjioaTe862n9SlZTrP+6PVUWLBYOr98= +github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c/go.mod h1:kjBC9F8L25GR+kIHy/1KgG/KfcoGnVwIiyovgq1uszk= github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= -github.com/nspcc-dev/neo-go v0.99.4/go.mod h1:mKTolfRUfKjFso5HPvGSQtUZc70n0VKBMs16eGuC5gA= -github.com/nspcc-dev/neo-go v0.101.2-0.20230601131642-a0117042e8fc h1:fySIWvUQsitK5e5qYIHnTDCXuPpwzz89SEUEIyY11sg= -github.com/nspcc-dev/neo-go v0.101.2-0.20230601131642-a0117042e8fc/go.mod h1:s9QhjMC784MWqTURovMbyYduIJc86mnCruxcMiAebpc= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220927123257-24c107e3a262/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230615193820-9185820289ce h1:vLGuUNDkmQrWMa4rr4vTd1u8ULqejWxVmNz1L7ocTEI= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230615193820-9185820289ce/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go v0.99.2/go.mod h1:9P0yWqhZX7i/ChJ+zjtiStO1uPTolPFUM+L5oNznU8E= +github.com/nspcc-dev/neo-go v0.100.1/go.mod h1:Nnp7F4e9IBccsgtCeLtUWV+0T6gk1PtP5HRtA13hUfc= +github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5 h1:AXI2upTPeTqX+n4xrBEzPATgEviOM/Prg6UQ6KDm+DU= +github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5/go.mod h1:Z0kpjwnTJj/ik/X6z18xjCL0X2+RNbqlnhKrl+MYgP8= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220809123759-3094d3e0c14b/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5 h1:/d7mY5hYlNhmEXexKcyqSR0b1Hdl5hf/c5o8Vi/1vt4= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= +github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM= +github.com/nspcc-dev/neofs-contract v0.16.0/go.mod h1:gN5bo2TlMvLbySImmg76DVj3jVmYgti2VVlQ+h/tcr0= github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659/go.mod h1:/jay1lr3w7NQd/VDBkEhkJmDmyPNsu4W+QV2obsUV40= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.9/go.mod h1:fTsdTU/M9rvv/f9jlp7vHOm3DRp+NSfjfTv9NohrKTE= github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= +github.com/nspcc-dev/tzhash v1.7.0/go.mod h1:Dnx9LUlOLr5paL2Rtc96x0PPs8D9eIkUtowt1n+KQus= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -444,10 +857,12 @@ github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKf github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -489,6 +904,7 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -497,12 +913,17 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= @@ -552,6 +973,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= @@ -560,6 +982,7 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE= go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0= @@ -569,6 +992,7 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= @@ -588,17 +1012,21 @@ go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.20.0 h1:BLOA1cZBAGSbRiNuGCCKiFrCdYB7deeHDeD1SueyOfA= go.opentelemetry.io/proto/otlp v0.20.0/go.mod h1:3QgjzPALBIv9pcknj2EXGPXjYPFdUh/RQfF8Lz3+Vnw= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -611,6 +1039,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -618,8 +1047,11 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -632,6 +1064,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20221227203929-1b447090c38c/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -647,6 +1081,7 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -657,8 +1092,13 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -697,13 +1137,32 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -715,8 +1174,23 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -730,6 +1204,7 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -785,25 +1260,62 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -812,16 +1324,22 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= +golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -874,14 +1392,26 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -901,6 +1431,38 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= +google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= +google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= +google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= +google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= +google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= +google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= +google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -944,7 +1506,82 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= +google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= +google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= +google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= +google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= +google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= +google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= +google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= +google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230628200519-e449d1ea0e82 h1:Wdfp5Hc1bqGCWYZNrir4A1Jb+SmVaV2j1DL/pbMMTGI= google.golang.org/genproto v0.0.0-20230628200519-e449d1ea0e82/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= google.golang.org/genproto/googleapis/api v0.0.0-20230628200519-e449d1ea0e82 h1:iI5Fmsfz4zDINYxJLxn2YChI//ypkHM/KuVSvlN7ZXk= @@ -969,9 +1606,30 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ= google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -985,6 +1643,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= From 3889e829e6d1a858c71b3b649eed615b41be2480 Mon Sep 17 00:00:00 2001 From: "a.arifullin" Date: Thu, 14 Sep 2023 14:08:43 +0300 Subject: [PATCH 0056/1413] [#667] writecache: Add logs for report error func in tests Signed-off-by: Airat Arifullin a.arifullin@yadro.com --- .../writecache/writecachebadger/flush_test.go | 6 +++++- .../writecache/writecachebbolt/flush_test.go | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go index 855d2214ff..392654e487 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go @@ -14,9 +14,12 @@ import ( oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/dgraph-io/badger/v4" "github.com/stretchr/testify/require" + "go.uber.org/zap" ) func TestFlush(t *testing.T) { + testlogger := test.NewLogger(t, true) + createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs writecache.MainStorage, opts ...Option) writecache.Cache { return New( append([]Option{ @@ -30,8 +33,9 @@ func TestFlush(t *testing.T) { errCountOpt := func() (Option, *atomic.Uint32) { cnt := &atomic.Uint32{} - return WithReportErrorFunc(func(string, error) { + return WithReportErrorFunc(func(msg string, err error) { cnt.Add(1) + testlogger.Warn(msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) }), cnt } diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go index 5db4df3180..533cec1d2f 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go @@ -17,13 +17,16 @@ import ( oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" + "go.uber.org/zap" ) func TestFlush(t *testing.T) { + testlogger := test.NewLogger(t, true) + createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs writecache.MainStorage, opts ...Option) writecache.Cache { return New( append([]Option{ - WithLogger(test.NewLogger(t, true)), + WithLogger(testlogger), WithPath(filepath.Join(t.TempDir(), "writecache")), WithSmallObjectSize(smallSize), WithMetabase(mb), @@ -33,8 +36,9 @@ func TestFlush(t *testing.T) { errCountOpt := func() (Option, *atomic.Uint32) { cnt := &atomic.Uint32{} - return WithReportErrorFunc(func(string, error) { + return WithReportErrorFunc(func(msg string, err error) { cnt.Add(1) + testlogger.Warn(msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) }), cnt } From d9b93b12c1536953cb3286753f115b4162f88c65 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 18 Sep 2023 10:05:17 +0300 Subject: [PATCH 0057/1413] [#333] Sort shards by shard_ID in cli output Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/modules/control/shards_list.go | 14 ++++++++++++-- cmd/frostfs-cli/modules/control/shards_set_mode.go | 6 ++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/shards_list.go b/cmd/frostfs-cli/modules/control/shards_list.go index ec515e6b46..4d09667b83 100644 --- a/cmd/frostfs-cli/modules/control/shards_list.go +++ b/cmd/frostfs-cli/modules/control/shards_list.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "sort" "strings" rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" @@ -49,11 +50,14 @@ func listShards(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + shards := resp.GetBody().GetShards() + sortShardsByID(shards) + isJSON, _ := cmd.Flags().GetBool(commonflags.JSON) if isJSON { - prettyPrintShardsJSON(cmd, resp.GetBody().GetShards()) + prettyPrintShardsJSON(cmd, shards) } else { - prettyPrintShards(cmd, resp.GetBody().GetShards()) + prettyPrintShards(cmd, shards) } } @@ -115,3 +119,9 @@ func shardModeToString(m control.ShardMode) string { return "unknown" } + +func sortShardsByID(ii []*control.ShardInfo) { + sort.Slice(ii, func(i, j int) bool { + return bytes.Compare(ii[i].Shard_ID, ii[j].Shard_ID) < 0 + }) +} diff --git a/cmd/frostfs-cli/modules/control/shards_set_mode.go b/cmd/frostfs-cli/modules/control/shards_set_mode.go index 135c0efa65..78f7689656 100644 --- a/cmd/frostfs-cli/modules/control/shards_set_mode.go +++ b/cmd/frostfs-cli/modules/control/shards_set_mode.go @@ -1,7 +1,9 @@ package control import ( + "bytes" "fmt" + "sort" "strings" rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" @@ -167,5 +169,9 @@ func getShardIDList(cmd *cobra.Command) [][]byte { res = append(res, raw) } + sort.Slice(res, func(i, j int) bool { + return bytes.Compare(res[i], res[j]) < 0 + }) + return res } From c14c9a023cbd96e12a60909f87f0d1e56ffba97b Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Wed, 20 Sep 2023 18:26:28 +0300 Subject: [PATCH 0058/1413] [#333] Sort objects by ID in SearchObjects Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/internal/client/client.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index e8869bc8ca..26d8aa83b9 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -6,6 +6,8 @@ import ( "errors" "fmt" "io" + "sort" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" @@ -727,6 +729,11 @@ func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes return nil, fmt.Errorf("read object list: %w", err) } + sort.Slice(list, func(i, j int) bool { + lhs, rhs := list[i].EncodeToString(), list[j].EncodeToString() + return strings.Compare(lhs, rhs) < 0 + }) + return &SearchObjectsRes{ ids: list, }, nil From b8c3c2486d13a2a2bcf4ea0b8b85c03571f80e57 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 25 Sep 2023 09:58:26 +0300 Subject: [PATCH 0059/1413] [#333] Sort containers by ID Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/internal/client/client.go | 10 ++++++++++ cmd/frostfs-cli/modules/container/list.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 26d8aa83b9..9cb7c8161f 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -71,6 +71,16 @@ func ListContainers(ctx context.Context, prm ListContainersPrm) (res ListContain return } +// SortedIDList returns sorted list of identifiers of user's containers. +func (x ListContainersRes) SortedIDList() []cid.ID { + list := x.cliRes.Containers() + sort.Slice(list, func(i, j int) bool { + lhs, rhs := list[i].EncodeToString(), list[j].EncodeToString() + return strings.Compare(lhs, rhs) < 0 + }) + return list +} + // PutContainerPrm groups parameters of PutContainer operation. type PutContainerPrm struct { Client *client.Client diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index c8b891d32c..1c7787760d 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -56,7 +56,7 @@ var listContainersCmd = &cobra.Command{ Client: cli, } - containerIDs := res.IDList() + containerIDs := res.SortedIDList() for _, cnrID := range containerIDs { if flagVarListName == "" && !flagVarListPrintAttr { cmd.Println(cnrID.String()) From c1e4130020dfde27387ddf26bdf1cafd5444a00b Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 27 Sep 2023 11:02:06 +0300 Subject: [PATCH 0060/1413] [#146] node: Add trace_id to logs Signed-off-by: Alexander Chuprov --- .../blobovnicza/delete.go | 2 ++ .../blobstor/blobovniczatree/delete.go | 2 ++ .../blobstor/blobovniczatree/exists.go | 4 ++- .../blobstor/blobovniczatree/get.go | 2 ++ .../blobstor/blobovniczatree/get_range.go | 3 +- .../blobstor/blobovniczatree/put.go | 10 ++++-- pkg/local_object_storage/blobstor/exists.go | 4 ++- pkg/local_object_storage/engine/delete.go | 7 ++-- pkg/local_object_storage/engine/evacuate.go | 19 +++++++---- pkg/local_object_storage/engine/get.go | 4 ++- pkg/local_object_storage/engine/inhume.go | 7 ++-- pkg/local_object_storage/engine/put.go | 5 ++- pkg/local_object_storage/engine/range.go | 4 ++- pkg/local_object_storage/engine/tree.go | 34 +++++++++++++------ pkg/local_object_storage/shard/delete.go | 7 ++-- pkg/local_object_storage/shard/get.go | 7 ++-- pkg/local_object_storage/shard/inhume.go | 2 ++ pkg/local_object_storage/shard/list.go | 4 ++- pkg/local_object_storage/shard/move.go | 2 ++ pkg/services/object/put/single.go | 5 +-- pkg/services/replicator/process.go | 5 ++- pkg/services/tree/redirect.go | 5 ++- pkg/services/tree/replicator.go | 7 ++-- pkg/tracing/trace.go | 19 +++++++++++ 24 files changed, 129 insertions(+), 41 deletions(-) create mode 100644 pkg/tracing/trace.go diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index 5a5da235fa..4bc13cc958 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -4,6 +4,7 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -73,6 +74,7 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err b.log.Debug(logs.BlobovniczaObjectWasRemovedFromBucket, zap.String("binary size", stringifyByteSize(dataSize)), zap.String("range", stringifyBounds(sizeLowerBound, sizeUpperBound)), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) b.itemDeleted(sizeUpperBound) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index ca1e46a15f..28e3a8f36a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -69,6 +70,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co b.log.Debug(logs.BlobovniczatreeCouldNotRemoveObjectFromLevel, zap.String("level", p), zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index c94881168a..e1a6f5ed5b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "go.opentelemetry.io/otel/attribute" @@ -56,7 +57,8 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common if !client.IsErrObjectNotFound(err) { b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index f2399e414d..49849e759e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -69,6 +70,7 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 56b41351bc..91d1e3ce00 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -71,7 +72,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), zap.String("error", err.Error()), - ) + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } if outOfBounds { return true, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index aae280e0bc..6f9c8c0de5 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -81,14 +82,16 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) } else { i.B.log.Debug(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return false, nil } if active == nil { - i.B.log.Debug(logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath)) + i.B.log.Debug(logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return false, nil } defer active.Close() @@ -102,7 +105,8 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) } else { i.B.log.Debug(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", active.Path()), - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return false, nil diff --git a/pkg/local_object_storage/blobstor/exists.go b/pkg/local_object_storage/blobstor/exists.go index 03dad392ab..43feec7c91 100644 --- a/pkg/local_object_storage/blobstor/exists.go +++ b/pkg/local_object_storage/blobstor/exists.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -74,7 +75,8 @@ func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exi for _, err := range errors[:len(errors)-1] { b.log.Warn(logs.BlobstorErrorOccurredDuringObjectExistenceChecking, zap.Stringer("address", prm.Address), - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return common.ExistsRes{}, errors[len(errors)-1] diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 8e31805604..68a7325c65 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -150,7 +151,8 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo if err != nil { e.log.Warn(logs.EngineErrorDuringSearchingForObjectChildren, zap.Stringer("addr", addr), - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return false } @@ -161,7 +163,8 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo if err != nil { e.log.Debug(logs.EngineCouldNotInhumeObjectInShard, zap.Stringer("addr", addr), - zap.String("err", err.Error())) + zap.String("err", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) continue } } diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 98a3a202de..192070c1cf 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -11,6 +11,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -200,11 +201,13 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p e.evacuateLimiter.Complete(err) }() - e.log.Info(logs.EngineStartedShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField) + e.log.Info(logs.EngineStartedShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) err = e.getTotalObjectsCount(ctx, shardsToEvacuate, res) if err != nil { - e.log.Error(logs.EngineShardsEvacuationFailedToCount, zap.Strings("shard_ids", shardIDs), zap.Error(err), evacuationOperationLogField) + e.log.Error(logs.EngineShardsEvacuationFailedToCount, zap.Strings("shard_ids", shardIDs), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } @@ -266,7 +269,8 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm E if errors.Is(err, meta.ErrEndOfListing) || errors.Is(err, shard.ErrDegradedMode) { break } - e.log.Error(logs.EngineShardsEvacuationFailedToListObjects, zap.String("shard_id", shardID), zap.Error(err), evacuationOperationLogField) + e.log.Error(logs.EngineShardsEvacuationFailedToListObjects, zap.String("shard_id", shardID), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } @@ -342,7 +346,8 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to res.failed.Add(1) continue } - e.log.Error(logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField) + e.log.Error(logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } @@ -363,7 +368,8 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to err = prm.handler(ctx, addr, getRes.Object()) if err != nil { - e.log.Error(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField) + e.log.Error(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } res.evacuated.Add(1) @@ -392,7 +398,8 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add zap.Stringer("from", sh.ID()), zap.Stringer("to", shards[j].ID()), zap.Stringer("addr", addr), - evacuationOperationLogField) + evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return true, nil } diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index 5d888238e7..f77c44226c 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -105,7 +106,8 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { e.log.Warn(logs.ShardMetaInfoPresentButObjectNotFound, zap.Stringer("shard_id", it.ShardWithMeta.ID()), zap.String("error", it.MetaError.Error()), - zap.Stringer("address", prm.addr)) + zap.Stringer("address", prm.addr), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } } diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index e0f9d7ab3c..293746f70c 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -93,7 +94,8 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, e if err != nil { e.log.Warn(logs.EngineRemovingAnObjectWithoutFullLockingCheck, zap.Error(err), - zap.Stringer("addr", prm.addrs[i])) + zap.Stringer("addr", prm.addrs[i]), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } else if locked { return InhumeRes{}, new(apistatus.ObjectLocked) } @@ -201,7 +203,8 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { locked, err = h.Shard.IsLocked(ctx, addr) if err != nil { - e.reportShardError(h, "can't check object's lockers", err, zap.Stringer("addr", addr)) + e.reportShardError(h, "can't check object's lockers", err, zap.Stringer("addr", addr), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) outErr = err return false } diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 2f96b82963..79ee3a9976 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -128,6 +129,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, e.log.Warn(logs.EngineCouldNotMarkObjectForShardRelocation, zap.Stringer("shard", sh.ID()), zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } } @@ -144,7 +146,8 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, errors.Is(err, common.ErrReadOnly) || errors.Is(err, common.ErrNoSpace) { e.log.Warn(logs.EngineCouldNotPutObjectToShard, zap.Stringer("shard_id", sh.ID()), - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return } diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index fb0873ee28..e45845d6c2 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -118,7 +119,8 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error e.log.Warn(logs.ShardMetaInfoPresentButObjectNotFound, zap.Stringer("shard_id", it.ShardWithMeta.ID()), zap.String("error", it.MetaError.Error()), - zap.Stringer("address", prm.addr)) + zap.Stringer("address", prm.addr), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } } diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index 55b9f9c509..6c3594bab4 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.opentelemetry.io/otel/attribute" @@ -38,7 +39,8 @@ func (e *StorageEngine) TreeMove(ctx context.Context, d pilorama.CIDDescriptor, if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(lst[index], "can't perform `TreeMove`", err, zap.Stringer("cid", d.CID), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return nil, err @@ -71,7 +73,8 @@ func (e *StorageEngine) TreeAddByPath(ctx context.Context, d pilorama.CIDDescrip if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(lst[index], "can't perform `TreeAddByPath`", err, zap.Stringer("cid", d.CID), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return nil, err } @@ -99,7 +102,8 @@ func (e *StorageEngine) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID str if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(lst[index], "can't perform `TreeApply`", err, zap.Stringer("cid", cnr), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return err } @@ -130,7 +134,8 @@ func (e *StorageEngine) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(sh, "can't perform `TreeGetByPath`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } continue } @@ -162,7 +167,8 @@ func (e *StorageEngine) TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID s if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(sh, "can't perform `TreeGetMeta`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } continue } @@ -193,7 +199,8 @@ func (e *StorageEngine) TreeGetChildren(ctx context.Context, cid cidSDK.ID, tree if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(sh, "can't perform `TreeGetChildren`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } continue } @@ -224,7 +231,8 @@ func (e *StorageEngine) TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(sh, "can't perform `TreeGetOpLog`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } continue } @@ -253,7 +261,8 @@ func (e *StorageEngine) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID stri if !errors.Is(err, pilorama.ErrTreeNotFound) && !errors.Is(err, shard.ErrReadOnlyMode) { e.reportShardError(sh, "can't perform `TreeDrop`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } continue } @@ -281,7 +290,8 @@ func (e *StorageEngine) TreeList(ctx context.Context, cid cidSDK.ID) ([]string, } e.reportShardError(sh, "can't perform `TreeList`", err, - zap.Stringer("cid", cid)) + zap.Stringer("cid", cid), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) // returns as much info about // trees as possible @@ -347,7 +357,8 @@ func (e *StorageEngine) TreeUpdateLastSyncHeight(ctx context.Context, cid cidSDK if err != nil && !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(lst[index], "can't update tree synchronization height", err, zap.Stringer("cid", cid), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return err } @@ -373,7 +384,8 @@ func (e *StorageEngine) TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, t if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(sh, "can't read tree synchronization height", err, zap.Stringer("cid", cid), - zap.String("tree", treeID)) + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } continue } diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index 662c0835a9..ea481300b8 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -94,7 +95,8 @@ func (s *Shard) deleteFromBlobstorSafe(ctx context.Context, addr oid.Address) { if err != nil { s.log.Debug(logs.StorageIDRetrievalFailure, zap.Stringer("object", addr), - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } storageID := res.StorageID() @@ -106,7 +108,8 @@ func (s *Shard) deleteFromBlobstorSafe(ctx context.Context, addr oid.Address) { if err != nil { s.log.Debug(logs.ObjectRemovalFailureBlobStor, zap.Stringer("object_address", addr), - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } } diff --git a/pkg/local_object_storage/shard/get.go b/pkg/local_object_storage/shard/get.go index 91565a3467..2e7c84bcd4 100644 --- a/pkg/local_object_storage/shard/get.go +++ b/pkg/local_object_storage/shard/get.go @@ -10,6 +10,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -144,12 +145,14 @@ func (s *Shard) fetchObjectData(ctx context.Context, addr oid.Address, skipMeta if client.IsErrObjectNotFound(err) { s.log.Debug(logs.ShardObjectIsMissingInWritecache, zap.Stringer("addr", addr), - zap.Bool("skip_meta", skipMeta)) + zap.Bool("skip_meta", skipMeta), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } else { s.log.Error(logs.ShardFailedToFetchObjectFromWritecache, zap.Error(err), zap.Stringer("addr", addr), - zap.Bool("skip_meta", skipMeta)) + zap.Bool("skip_meta", skipMeta), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } } if skipMeta || mErr != nil { diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index 6a2f9311d1..a5f8960c3c 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" @@ -110,6 +111,7 @@ func (s *Shard) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { s.log.Debug(logs.ShardCouldNotMarkObjectToDeleteInMetabase, zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) s.m.RUnlock() diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index bc13c622bb..d6e4d7e504 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -99,7 +100,8 @@ func (s *Shard) List(ctx context.Context) (res SelectRes, err error) { if err != nil { s.log.Debug(logs.ShardCantSelectAllObjects, zap.Stringer("cid", lst[i]), - zap.String("error", err.Error())) + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) continue } diff --git a/pkg/local_object_storage/shard/move.go b/pkg/local_object_storage/shard/move.go index 9832c9c847..539dbc97f0 100644 --- a/pkg/local_object_storage/shard/move.go +++ b/pkg/local_object_storage/shard/move.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" @@ -53,6 +54,7 @@ func (s *Shard) ToMoveIt(ctx context.Context, prm ToMoveItPrm) (ToMoveItRes, err if err != nil { s.log.Debug(logs.ShardCouldNotMarkObjectForShardRelocationInMetabase, zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index adac194a0c..3865aabb9c 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -22,6 +22,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -242,8 +243,7 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, info.AddressGroup().IterateAddresses(func(addr network.Address) (stop bool) { ctx, span := tracing.StartSpanFromContext(ctx, "putService.redirectPutSingleRequest.IterateAddresses", trace.WithAttributes( - attribute.String("address", addr.String()), - )) + attribute.String("address", addr.String()))) defer span.End() var err error @@ -257,6 +257,7 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, zap.Stringer("address", addr), zap.Stringer("object_id", objID), zap.Stringer("container_id", cnrID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } diff --git a/pkg/services/replicator/process.go b/pkg/services/replicator/process.go index 16bcec9c57..3a46e5f041 100644 --- a/pkg/services/replicator/process.go +++ b/pkg/services/replicator/process.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "go.opentelemetry.io/otel/attribute" @@ -44,7 +45,8 @@ func (p *Replicator) HandleTask(ctx context.Context, task Task, res TaskResult) if err != nil { p.log.Error(logs.ReplicatorCouldNotGetObjectFromLocalStorage, zap.Stringer("object", task.Addr), - zap.Error(err)) + zap.Error(err), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return } @@ -63,6 +65,7 @@ func (p *Replicator) HandleTask(ctx context.Context, task Task, res TaskResult) log := p.log.With( zap.String("node", netmap.StringifyPublicKey(task.Nodes[i])), zap.Stringer("object", task.Addr), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) callCtx, cancel := context.WithTimeout(ctx, p.putTimeout) diff --git a/pkg/services/tree/redirect.go b/pkg/services/tree/redirect.go index 0afd3439ac..ec41a60d47 100644 --- a/pkg/services/tree/redirect.go +++ b/pkg/services/tree/redirect.go @@ -6,6 +6,7 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "go.opentelemetry.io/otel/attribute" @@ -39,7 +40,9 @@ func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo return false } - s.log.Debug(logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint)) + s.log.Debug(logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + called = true stop = f(c) return true diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 0ca30273e0..49a37b8be1 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -107,12 +108,14 @@ func (s *Service) replicationWorker(ctx context.Context) { if lastErr != nil { if errors.Is(lastErr, errRecentlyFailed) { s.log.Debug(logs.TreeDoNotSendUpdateToTheNode, - zap.String("last_error", lastErr.Error())) + zap.String("last_error", lastErr.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } else { s.log.Warn(logs.TreeFailedToSentUpdateToTheNode, zap.String("last_error", lastErr.Error()), zap.String("address", lastAddr), - zap.String("key", hex.EncodeToString(task.n.PublicKey()))) + zap.String("key", hex.EncodeToString(task.n.PublicKey())), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } s.metrics.AddReplicateTaskDuration(time.Since(start), false) } else { diff --git a/pkg/tracing/trace.go b/pkg/tracing/trace.go new file mode 100644 index 0000000000..dc2f90259f --- /dev/null +++ b/pkg/tracing/trace.go @@ -0,0 +1,19 @@ +package tracing + +import ( + "context" + + "go.opentelemetry.io/otel/trace" +) + +var emptyTraceID = [16]byte{} + +// GetTraceID retrieves the trace ID from the provided context. +// It returns an empty string if no trace ID is found. +func GetTraceID(ctx context.Context) string { + span := trace.SpanFromContext(ctx) + if span == nil || span.SpanContext().TraceID() == emptyTraceID { + return "" + } + return span.SpanContext().TraceID().String() +} From a0a35ffbecc110ee17bfeefc3bbc4dbe9f328ec7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 29 Sep 2023 18:41:48 +0300 Subject: [PATCH 0061/1413] [#702] node: Update SDK version Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 89f437216b..28008128c7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230928142024-84b9d29fc98c git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 5bcd5e4289..8490c167c7 100644 --- a/go.sum +++ b/go.sum @@ -393,8 +393,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c h1:gD+dj5IZx9jlniDu8TlLQdRGCd8KIOzYjjdDd1KcVdI= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230911122224-ac8fc6d4400c/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230928142024-84b9d29fc98c h1:c8mduKlc8Zioppz5o06QRYS5KYX3BFRO+NgKj2q6kD8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230928142024-84b9d29fc98c/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= From 627b3027456fc87605d9a82490088cd2c767dbe4 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 2 Oct 2023 10:38:11 +0300 Subject: [PATCH 0062/1413] [#709] node: Put in log info about listening endpoints Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/control.go | 7 ++++++- cmd/frostfs-node/grpc.go | 3 ++- cmd/frostfs-node/httpcomponent.go | 5 +++++ cmd/frostfs-node/notificator.go | 2 ++ internal/logs/logs.go | 3 ++- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index 3ed6bc54ac..787fe3351d 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -14,6 +14,8 @@ import ( "google.golang.org/grpc" ) +const serviceNameControl = "control" + type treeSynchronizer struct { treeSvc *tree.Service } @@ -66,7 +68,10 @@ func initControlService(c *cfg) { control.RegisterControlServiceServer(c.cfgControlService.server, ctlSvc) c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { - runAndLog(ctx, c, "control", false, func(context.Context, *cfg) { + runAndLog(ctx, c, serviceNameControl, false, func(context.Context, *cfg) { + c.log.Info(logs.FrostFSNodeStartListeningEndpoint, + zap.String("service", serviceNameControl), + zap.String("endpoint", endpoint)) fatalOnErr(c.cfgControlService.server.Serve(lis)) }) })) diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index 42059ec099..74df7a18f5 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -110,7 +110,8 @@ func serveGRPC(c *cfg) { c.wg.Done() }() - c.log.Info(logs.FrostFSNodeStartListeningGRPCEndpoint, + c.log.Info(logs.FrostFSNodeStartListeningEndpoint, + zap.String("service", "gRPC"), zap.Stringer("endpoint", lis.Addr()), ) diff --git a/cmd/frostfs-node/httpcomponent.go b/cmd/frostfs-node/httpcomponent.go index db9239384e..6e8fa8f2ce 100644 --- a/cmd/frostfs-node/httpcomponent.go +++ b/cmd/frostfs-node/httpcomponent.go @@ -6,7 +6,9 @@ import ( "net/http" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" httputil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/http" + "go.uber.org/zap" ) type httpComponent struct { @@ -42,6 +44,9 @@ func (cmp *httpComponent) init(c *cfg) { cmp.name, func(ctx context.Context) { runAndLog(ctx, c, cmp.name, false, func(context.Context, *cfg) { + c.log.Info(logs.FrostFSNodeStartListeningEndpoint, + zap.String("service", cmp.name), + zap.String("endpoint", cmp.address)) fatalOnErr(srv.Serve()) }) }, diff --git a/cmd/frostfs-node/notificator.go b/cmd/frostfs-node/notificator.go index 3fa4869558..8e581505fd 100644 --- a/cmd/frostfs-node/notificator.go +++ b/cmd/frostfs-node/notificator.go @@ -167,5 +167,7 @@ func connectNats(ctx context.Context, c *cfg) { err := c.cfgNotifications.nw.w.Connect(ctx, endpoint) if err != nil { panic(fmt.Sprintf("could not connect to a nats endpoint %s: %v", endpoint, err)) + } else { + c.log.Info(logs.NatsConnectedToEndpoint, zap.String("endpoint", endpoint)) } } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index c18d191f86..56312f83f0 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -123,6 +123,7 @@ const ( NatsNatsConnectionWasLost = "nats: connection was lost" NatsNatsReconnectedToTheServer = "nats: reconnected to the server" NatsNatsClosingConnectionAsTheContextIsDone = "nats: closing connection as the context is done" + NatsConnectedToEndpoint = "nats: successfully connected to endpoint" ControllerStartingToAnnounceTheValuesOfTheMetrics = "starting to announce the values of the metrics" ControllerCouldNotInitializeIteratorOverLocallyCollectedMetrics = "could not initialize iterator over locally collected metrics" ControllerCouldNotInitializeAnnouncementAccumulator = "could not initialize announcement accumulator" @@ -413,10 +414,10 @@ const ( FrostFSIRCouldntCreateRPCClientForEndpoint = "could not create RPC client for endpoint" FrostFSIRCreatedRPCClientForEndpoint = "created RPC client for endpoint" FrostFSIRReloadExtraWallets = "reload extra wallets" + FrostFSNodeStartListeningEndpoint = "start listening endpoint" FrostFSNodeCouldNotReadCertificateFromFile = "could not read certificate from file" FrostFSNodeCantListenGRPCEndpoint = "can't listen gRPC endpoint" FrostFSNodeStopListeningGRPCEndpoint = "stop listening gRPC endpoint" - FrostFSNodeStartListeningGRPCEndpoint = "start listening gRPC endpoint" FrostFSNodeStoppingGRPCServer = "stopping gRPC server..." FrostFSNodeGRPCCannotShutdownGracefullyForcingStop = "gRPC cannot shutdown gracefully, forcing stop" FrostFSNodeGRPCServerStoppedSuccessfully = "gRPC server stopped successfully" From f3278d76a93a63d2004ac62c0a6f0f70ea81560b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 5 Oct 2023 10:57:58 +0300 Subject: [PATCH 0063/1413] [#721] netmap: Send bootstrap at each epoch tick Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/netmap.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index e7d3271b18..cc3c0c48db 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -179,15 +179,8 @@ func addNewEpochNotificationHandlers(c *cfg) { return } - n := ev.(netmapEvent.NewEpoch).EpochNumber() - - const reBootstrapInterval = 2 - - if (n-c.cfgNetmap.startEpoch)%reBootstrapInterval == 0 { - err := c.bootstrap() - if err != nil { - c.log.Warn(logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) - } + if err := c.bootstrap(); err != nil { + c.log.Warn(logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) } }) From bd5bf8b1a955bef17e2ba722b62579428433860d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 5 Oct 2023 11:30:41 +0300 Subject: [PATCH 0064/1413] [#721] netmap: Drop already bootstraped check Because of this check, under certain conditions, the node could be removed from the network map, although the node was functioning normally. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 +-- cmd/frostfs-node/netmap.go | 25 ++++++------------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 8286bc7d71..60e567c5a1 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -345,8 +345,7 @@ type internals struct { apiVersion version.Version healthStatus *atomic.Int32 // is node under maintenance - isMaintenance atomic.Bool - alreadyBootstraped bool + isMaintenance atomic.Bool } // starts node's maintenance. diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index cc3c0c48db..ebe152e47f 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -220,10 +220,6 @@ func bootstrapNode(c *cfg) { c.log.Info(logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) return } - if c.alreadyBootstraped { - c.log.Info(logs.NetmapNodeAlreadyInCandidateListOnlineSkipInitialBootstrap) - return - } err := c.bootstrap() fatalOnErrDetails("bootstrap error", err) } @@ -256,7 +252,7 @@ func initNetmapState(c *cfg) { fatalOnErrDetails("could not initialize current epoch number", err) var ni *netmapSDK.NodeInfo - ni, c.alreadyBootstraped, err = c.netmapInitLocalNodeState(epoch) + ni, err = c.netmapInitLocalNodeState(epoch) fatalOnErrDetails("could not init network state", err) stateWord := nodeState(ni) @@ -275,13 +271,6 @@ func initNetmapState(c *cfg) { c.handleLocalNodeInfo(ni) } -func sameNodeInfo(a, b *netmapSDK.NodeInfo) bool { - // Suboptimal, but we do this once on the node startup. - rawA := a.Marshal() - rawB := b.Marshal() - return bytes.Equal(rawA, rawB) -} - func nodeState(ni *netmapSDK.NodeInfo) string { if ni != nil { switch { @@ -296,29 +285,27 @@ func nodeState(ni *netmapSDK.NodeInfo) string { return "undefined" } -func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, bool, error) { +func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error) { nmNodes, err := c.cfgNetmap.wrapper.GetCandidates() if err != nil { - return nil, false, err + return nil, err } var candidate *netmapSDK.NodeInfo - alreadyBootstraped := false for i := range nmNodes { if bytes.Equal(nmNodes[i].PublicKey(), c.binPublicKey) { candidate = &nmNodes[i] - alreadyBootstraped = candidate.IsOnline() && sameNodeInfo(&c.cfgNodeInfo.localInfo, candidate) break } } node, err := c.netmapLocalNodeState(epoch) if err != nil { - return nil, false, err + return nil, err } if candidate == nil { - return node, false, nil + return node, nil } nmState := nodeState(node) @@ -330,7 +317,7 @@ func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, bool, zap.String("netmap", nmState), zap.String("candidate", candidateState)) } - return candidate, alreadyBootstraped, nil + return candidate, nil } func (c *cfg) netmapLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error) { From 997ac7cd8d386700674516c026b90127e416d518 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 6 Oct 2023 10:22:35 +0300 Subject: [PATCH 0065/1413] [#726] writecache: Fix small object flush for BBolt Do not marshal object twice. Signed-off-by: Dmitrii Stepanov --- .../writecache/writecachebbolt/cachebbolt.go | 4 ++-- .../writecache/writecachebbolt/flush.go | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go b/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go index 11bdbe07b7..363ee8448c 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go @@ -29,7 +29,7 @@ type cache struct { compressFlags map[string]struct{} // flushCh is a channel with objects to flush. - flushCh chan *objectSDK.Object + flushCh chan objectInfo // closeCh is close channel, protected by modeMtx. closeCh chan struct{} // wg is a wait group for flush workers. @@ -62,7 +62,7 @@ var ( // New creates new writecache instance. func New(opts ...Option) writecache.Cache { c := &cache{ - flushCh: make(chan *objectSDK.Object), + flushCh: make(chan objectInfo), mode: mode.ReadWrite, compressFlags: make(map[string]struct{}), diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush.go b/pkg/local_object_storage/writecache/writecachebbolt/flush.go index c3b0f89bba..89b26cd64f 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush.go @@ -79,7 +79,6 @@ func (c *cache) runFlushLoop() { func (c *cache) flushSmallObjects() { var lastKey []byte - var m []objectInfo for { select { case <-c.closeCh: @@ -87,7 +86,7 @@ func (c *cache) flushSmallObjects() { default: } - m = m[:0] + var m []objectInfo c.modeMtx.RLock() if c.readOnly() { @@ -133,10 +132,11 @@ func (c *cache) flushSmallObjects() { if err := obj.Unmarshal(m[i].data); err != nil { continue } + m[i].obj = obj count++ select { - case c.flushCh <- obj: + case c.flushCh <- m[i]: case <-c.closeCh: c.modeMtx.RUnlock() return @@ -231,22 +231,22 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { func (c *cache) workerFlushSmall() { defer c.wg.Done() - var obj *objectSDK.Object + var objInfo objectInfo for { // Give priority to direct put. select { - case obj = <-c.flushCh: + case objInfo = <-c.flushCh: case <-c.closeCh: return } - err := c.flushObject(context.TODO(), obj, nil, writecache.StorageTypeDB) + err := c.flushObject(context.TODO(), objInfo.obj, objInfo.data, writecache.StorageTypeDB) if err != nil { // Error is handled in flushObject. continue } - c.deleteFromDB(objectCore.AddressOf(obj).EncodeToString()) + c.deleteFromDB(objInfo.addr) } } From d07afd803ccb1dc111e545d8ac27c37987b3831c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 6 Oct 2023 11:31:40 +0300 Subject: [PATCH 0066/1413] [#726] writecache: Fix small object flush for Badger Do not marshal object twice. Signed-off-by: Dmitrii Stepanov --- .../writecache/writecachebadger/cachebadger.go | 4 ++-- .../writecache/writecachebadger/flush.go | 17 ++++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go index 6dd4755b3e..d5da776357 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go +++ b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go @@ -21,7 +21,7 @@ type cache struct { modeMtx sync.RWMutex // flushCh is a channel with objects to flush. - flushCh chan *objectSDK.Object + flushCh chan objectInfo // scheduled4Flush contains objects scheduled for flush via flushCh // helps to avoid multiple flushing of one object scheduled4Flush map[oid.Address]struct{} @@ -52,7 +52,7 @@ const ( // New creates new writecache instance. func New(opts ...Option) writecache.Cache { c := &cache{ - flushCh: make(chan *objectSDK.Object), + flushCh: make(chan objectInfo), mode: mode.ReadWrite, scheduled4Flush: map[oid.Address]struct{}{}, diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush.go b/pkg/local_object_storage/writecache/writecachebadger/flush.go index ab6910a805..3f2bdb043f 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush.go @@ -85,7 +85,11 @@ func (c *collector) Send(buf *z.Buffer) error { c.cache.scheduled4FlushMtx.Unlock() c.scheduled++ select { - case c.cache.flushCh <- obj: + case c.cache.flushCh <- objectInfo{ + addr: addr, + data: val, + obj: obj, + }: case <-c.cache.closeCh: c.cancel() return nil @@ -175,22 +179,21 @@ func (c *cache) reportFlushError(msg string, addr string, err error) { func (c *cache) workerFlushSmall() { defer c.wg.Done() - var obj *objectSDK.Object + var objInfo objectInfo for { // Give priority to direct put. select { - case obj = <-c.flushCh: + case objInfo = <-c.flushCh: case <-c.closeCh: return } - addr := objectCore.AddressOf(obj) - err := c.flushObject(context.TODO(), obj, nil, writecache.StorageTypeDB) + err := c.flushObject(context.TODO(), objInfo.obj, objInfo.data, writecache.StorageTypeDB) if err == nil { - c.deleteFromDB([]internalKey{addr2key(addr)}) + c.deleteFromDB([]internalKey{addr2key(objInfo.addr)}) } c.scheduled4FlushMtx.Lock() - delete(c.scheduled4Flush, addr) + delete(c.scheduled4Flush, objInfo.addr) c.scheduled4FlushMtx.Unlock() } } From 4caa934eea89e061bfc7b8bf31643e4e6c587572 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 6 Oct 2023 13:54:48 +0300 Subject: [PATCH 0067/1413] [#729] containersvc: Remove load announcement IR code was removed in 8879c6ea. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/container.go | 436 +----------------- .../announcement/load/controller/calls.go | 307 ------------ .../load/controller/calls_test.go | 192 -------- .../load/controller/controller.go | 94 ---- .../announcement/load/controller/deps.go | 103 ----- .../announcement/load/controller/opts.go | 28 -- .../announcement/load/controller/util.go | 36 -- .../announcement/load/route/calls.go | 145 ------ .../container/announcement/load/route/deps.go | 31 -- .../container/announcement/load/route/opts.go | 28 -- .../load/route/placement/builder.go | 49 -- .../load/route/placement/calls.go | 47 -- .../announcement/load/route/placement/deps.go | 14 - .../announcement/load/route/router.go | 87 ---- .../container/announcement/load/route/util.go | 49 -- .../announcement/load/storage/storage.go | 151 ------ .../announcement/load/storage/storage_test.go | 50 -- 17 files changed, 2 insertions(+), 1845 deletions(-) delete mode 100644 pkg/services/container/announcement/load/controller/calls.go delete mode 100644 pkg/services/container/announcement/load/controller/calls_test.go delete mode 100644 pkg/services/container/announcement/load/controller/controller.go delete mode 100644 pkg/services/container/announcement/load/controller/deps.go delete mode 100644 pkg/services/container/announcement/load/controller/opts.go delete mode 100644 pkg/services/container/announcement/load/controller/util.go delete mode 100644 pkg/services/container/announcement/load/route/calls.go delete mode 100644 pkg/services/container/announcement/load/route/deps.go delete mode 100644 pkg/services/container/announcement/load/route/opts.go delete mode 100644 pkg/services/container/announcement/load/route/placement/builder.go delete mode 100644 pkg/services/container/announcement/load/route/placement/calls.go delete mode 100644 pkg/services/container/announcement/load/route/placement/deps.go delete mode 100644 pkg/services/container/announcement/load/route/router.go delete mode 100644 pkg/services/container/announcement/load/route/util.go delete mode 100644 pkg/services/container/announcement/load/storage/storage.go delete mode 100644 pkg/services/container/announcement/load/storage/storage_test.go diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index d54bf13dd1..9239df6400 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -3,44 +3,22 @@ package main import ( "bytes" "context" - "crypto/ecdsa" - "crypto/sha256" - "errors" - "fmt" - "strconv" - containerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" containerTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/container/grpc" containerService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" - loadcontroller "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/controller" - loadroute "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/route" - placementrouter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/route/placement" - loadstorage "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/storage" containerMorph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/morph" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - apiClient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "go.uber.org/zap" ) -const ( - startEstimationNotifyEvent = "StartEstimation" - stopEstimationNotifyEvent = "StopEstimation" -) - -func initContainerService(ctx context.Context, c *cfg) { +func initContainerService(_ context.Context, c *cfg) { // container wrapper that tries to invoke notary // requests if chain is configured so wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, cntClient.TryNotary()) @@ -52,44 +30,10 @@ func initContainerService(ctx context.Context, c *cfg) { cnrRdr, cnrWrt := configureEACLAndContainerSources(c, wrap, cnrSrc) - loadAccumulator := loadstorage.New(loadstorage.Prm{}) - - loadPlacementBuilder := &loadPlacementBuilder{ - log: c.log, - nmSrc: c.netMapSource, - cnrSrc: cnrSrc, - } - - routeBuilder := placementrouter.New(placementrouter.Prm{ - PlacementBuilder: loadPlacementBuilder, - }) - - loadRouter := loadroute.New( - loadroute.Prm{ - LocalServerInfo: c, - RemoteWriterProvider: &remoteLoadAnnounceProvider{ - key: &c.key.PrivateKey, - netmapKeys: c, - clientCache: c.bgClientCache, - deadEndProvider: loadcontroller.SimpleWriterProvider(loadAccumulator), - }, - Builder: routeBuilder, - }, - loadroute.WithLogger(c.log), - ) - - setLoadController(ctx, c, loadRouter, loadAccumulator) - server := containerTransportGRPC.New( containerService.NewSignService( &c.key.PrivateKey, - &usedSpaceService{ - Server: containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), - loadWriterProvider: loadRouter, - loadPlacementBuilder: loadPlacementBuilder, - routeBuilder: routeBuilder, - cfg: c, - }, + containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), ), ) @@ -178,50 +122,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c return cnrRdr, cnrWrt } -func setLoadController(ctx context.Context, c *cfg, loadRouter *loadroute.Router, loadAccumulator *loadstorage.Storage) { - pubKey := c.key.PublicKey().Bytes() - - // container wrapper that always sends non-notary - // requests - wrapperNoNotary, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0) - fatalOnErr(err) - - resultWriter := &morphLoadWriter{ - log: c.log, - cnrMorphClient: wrapperNoNotary, - key: pubKey, - } - - localMetrics := &localStorageLoad{ - log: c.log, - engine: c.cfgObject.cfgLocalStorage.localStorage, - } - - ctrl := loadcontroller.New( - loadcontroller.Prm{ - LocalMetrics: loadcontroller.SimpleIteratorProvider(localMetrics), - AnnouncementAccumulator: loadcontroller.SimpleIteratorProvider(loadAccumulator), - LocalAnnouncementTarget: loadRouter, - ResultReceiver: loadcontroller.SimpleWriterProvider(resultWriter), - }, - loadcontroller.WithLogger(c.log), - ) - - setContainerNotificationParser(c, startEstimationNotifyEvent, containerEvent.ParseStartEstimation) - addContainerAsyncNotificationHandler(c, startEstimationNotifyEvent, func(ev event.Event) { - ctrl.Start(ctx, loadcontroller.StartPrm{ - Epoch: ev.(containerEvent.StartEstimation).Epoch(), - }) - }) - - setContainerNotificationParser(c, stopEstimationNotifyEvent, containerEvent.ParseStopEstimation) - addContainerAsyncNotificationHandler(c, stopEstimationNotifyEvent, func(ev event.Event) { - ctrl.Stop(ctx, loadcontroller.StopPrm{ - Epoch: ev.(containerEvent.StopEstimation).Epoch(), - }) - }) -} - // addContainerNotificationHandler adds handler that will be executed synchronously. func addContainerNotificationHandler(c *cfg, sTyp string, h event.Handler) { typ := event.TypeFromString(sTyp) @@ -284,219 +184,6 @@ func setContainerNotificationParser(c *cfg, sTyp string, p event.NotificationPar c.cfgContainer.parsers[typ] = p } -type morphLoadWriter struct { - log *logger.Logger - - cnrMorphClient *cntClient.Client - - key []byte -} - -func (w *morphLoadWriter) Put(a containerSDK.SizeEstimation) error { - w.log.Debug(logs.FrostFSNodeSaveUsedSpaceAnnouncementInContract, - zap.Uint64("epoch", a.Epoch()), - zap.Stringer("cid", a.Container()), - zap.Uint64("size", a.Value()), - ) - - prm := cntClient.AnnounceLoadPrm{} - - prm.SetAnnouncement(a) - prm.SetReporter(w.key) - - return w.cnrMorphClient.AnnounceLoad(prm) -} - -func (*morphLoadWriter) Close(context.Context) error { - return nil -} - -type nopLoadWriter struct{} - -func (nopLoadWriter) Put(containerSDK.SizeEstimation) error { - return nil -} - -func (nopLoadWriter) Close(context.Context) error { - return nil -} - -type remoteLoadAnnounceProvider struct { - key *ecdsa.PrivateKey - - netmapKeys netmapCore.AnnouncedKeys - - clientCache interface { - Get(client.NodeInfo) (client.MultiAddressClient, error) - } - - deadEndProvider loadcontroller.WriterProvider -} - -func (r *remoteLoadAnnounceProvider) InitRemote(srv loadcontroller.ServerInfo) (loadcontroller.WriterProvider, error) { - if srv == nil { - return r.deadEndProvider, nil - } - - if r.netmapKeys.IsLocalKey(srv.PublicKey()) { - // if local => return no-op writer - return loadcontroller.SimpleWriterProvider(new(nopLoadWriter)), nil - } - - var info client.NodeInfo - - err := client.NodeInfoFromRawNetmapElement(&info, srv) - if err != nil { - return nil, fmt.Errorf("parse client node info: %w", err) - } - - c, err := r.clientCache.Get(info) - if err != nil { - return nil, fmt.Errorf("could not initialize API client: %w", err) - } - - return &remoteLoadAnnounceWriterProvider{ - client: c, - }, nil -} - -type remoteLoadAnnounceWriterProvider struct { - client client.Client -} - -func (p *remoteLoadAnnounceWriterProvider) InitWriter([]loadcontroller.ServerInfo) (loadcontroller.Writer, error) { - return &remoteLoadAnnounceWriter{ - client: p.client, - }, nil -} - -type remoteLoadAnnounceWriter struct { - client client.Client - - buf []containerSDK.SizeEstimation -} - -func (r *remoteLoadAnnounceWriter) Put(a containerSDK.SizeEstimation) error { - r.buf = append(r.buf, a) - - return nil -} - -func (r *remoteLoadAnnounceWriter) Close(ctx context.Context) error { - cliPrm := apiClient.PrmAnnounceSpace{ - Announcements: r.buf, - } - - _, err := r.client.ContainerAnnounceUsedSpace(ctx, cliPrm) - return err -} - -type loadPlacementBuilder struct { - log *logger.Logger - - nmSrc netmapCore.Source - - cnrSrc containerCore.Source -} - -func (l *loadPlacementBuilder) BuildPlacement(epoch uint64, cnr cid.ID) ([][]netmap.NodeInfo, error) { - cnrNodes, nm, err := l.buildPlacement(epoch, cnr) - if err != nil { - return nil, err - } - - const pivotPrefix = "load_announcement_" - - pivot := []byte( - pivotPrefix + strconv.FormatUint(epoch, 10), - ) - - placement, err := nm.PlacementVectors(cnrNodes, pivot) - if err != nil { - return nil, fmt.Errorf("could not build placement vectors: %w", err) - } - - return placement, nil -} - -func (l *loadPlacementBuilder) buildPlacement(epoch uint64, idCnr cid.ID) ([][]netmap.NodeInfo, *netmap.NetMap, error) { - cnr, err := l.cnrSrc.Get(idCnr) - if err != nil { - return nil, nil, err - } - - nm, err := l.nmSrc.GetNetMapByEpoch(epoch) - if err != nil { - return nil, nil, fmt.Errorf("could not get network map: %w", err) - } - - binCnr := make([]byte, sha256.Size) - idCnr.Encode(binCnr) - - cnrNodes, err := nm.ContainerNodes(cnr.Value.PlacementPolicy(), binCnr) - if err != nil { - return nil, nil, fmt.Errorf("could not build container nodes: %w", err) - } - - return cnrNodes, nm, nil -} - -type localStorageLoad struct { - log *logger.Logger - - engine *engine.StorageEngine -} - -func (d *localStorageLoad) Iterate(f loadcontroller.UsedSpaceFilter, h loadcontroller.UsedSpaceHandler) error { - idList, err := engine.ListContainers(context.TODO(), d.engine) - if err != nil { - return fmt.Errorf("list containers on engine failure: %w", err) - } - - for i := range idList { - sz, err := engine.ContainerSize(d.engine, idList[i]) - if err != nil { - d.log.Debug(logs.FrostFSNodeFailedToCalculateContainerSizeInStorageEngine, - zap.Stringer("cid", idList[i]), - zap.String("error", err.Error()), - ) - - continue - } - - d.log.Debug(logs.FrostFSNodeContainerSizeInStorageEngineCalculatedSuccessfully, - zap.Uint64("size", sz), - zap.Stringer("cid", idList[i]), - ) - - var a containerSDK.SizeEstimation - a.SetContainer(idList[i]) - a.SetValue(sz) - - if f != nil && !f(a) { - continue - } - - if err := h(a); err != nil { - return err - } - } - - return nil -} - -type usedSpaceService struct { - containerService.Server - - loadWriterProvider loadcontroller.WriterProvider - - loadPlacementBuilder *loadPlacementBuilder - - routeBuilder loadroute.Builder - - cfg *cfg -} - func (c *cfg) PublicKey() []byte { return nodeKeyFromNetmap(c) } @@ -517,125 +204,6 @@ func (c *cfg) ExternalAddresses() []string { return c.cfgNodeInfo.localInfo.ExternalAddresses() } -func (c *usedSpaceService) PublicKey() []byte { - return nodeKeyFromNetmap(c.cfg) -} - -func (c *usedSpaceService) IterateAddresses(f func(string) bool) { - c.cfg.iterateNetworkAddresses(f) -} - -func (c *usedSpaceService) NumberOfAddresses() int { - return c.cfg.addressNum() -} - -func (c *usedSpaceService) ExternalAddresses() []string { - return c.cfg.ExternalAddresses() -} - -func (c *usedSpaceService) AnnounceUsedSpace(ctx context.Context, req *containerV2.AnnounceUsedSpaceRequest) (*containerV2.AnnounceUsedSpaceResponse, error) { - var passedRoute []loadcontroller.ServerInfo - - for hdr := req.GetVerificationHeader(); hdr != nil; hdr = hdr.GetOrigin() { - passedRoute = append(passedRoute, &containerOnlyKeyRemoteServerInfo{ - key: hdr.GetBodySignature().GetKey(), - }) - } - - for left, right := 0, len(passedRoute)-1; left < right; left, right = left+1, right-1 { - passedRoute[left], passedRoute[right] = passedRoute[right], passedRoute[left] - } - - passedRoute = append(passedRoute, c) - - w, err := c.loadWriterProvider.InitWriter(passedRoute) - if err != nil { - return nil, fmt.Errorf("could not initialize container's used space writer: %w", err) - } - - var est containerSDK.SizeEstimation - - for _, aV2 := range req.GetBody().GetAnnouncements() { - err = est.ReadFromV2(aV2) - if err != nil { - return nil, fmt.Errorf("invalid size announcement: %w", err) - } - - if err := c.processLoadValue(ctx, est, passedRoute, w); err != nil { - return nil, err - } - } - - respBody := new(containerV2.AnnounceUsedSpaceResponseBody) - - resp := new(containerV2.AnnounceUsedSpaceResponse) - resp.SetBody(respBody) - - c.cfg.respSvc.SetMeta(resp) - - return resp, nil -} - -var errNodeOutsideContainer = errors.New("node outside the container") - -type containerOnlyKeyRemoteServerInfo struct { - key []byte -} - -func (i *containerOnlyKeyRemoteServerInfo) PublicKey() []byte { - return i.key -} - -func (*containerOnlyKeyRemoteServerInfo) IterateAddresses(func(string) bool) { -} - -func (*containerOnlyKeyRemoteServerInfo) NumberOfAddresses() int { - return 0 -} - -func (*containerOnlyKeyRemoteServerInfo) ExternalAddresses() []string { - return nil -} - -func (l *loadPlacementBuilder) isNodeFromContainerKey(epoch uint64, cnr cid.ID, key []byte) (bool, error) { - cnrNodes, _, err := l.buildPlacement(epoch, cnr) - if err != nil { - return false, err - } - - for i := range cnrNodes { - for j := range cnrNodes[i] { - if bytes.Equal(cnrNodes[i][j].PublicKey(), key) { - return true, nil - } - } - } - - return false, nil -} - -func (c *usedSpaceService) processLoadValue(_ context.Context, a containerSDK.SizeEstimation, - route []loadcontroller.ServerInfo, w loadcontroller.Writer) error { - fromCnr, err := c.loadPlacementBuilder.isNodeFromContainerKey(a.Epoch(), a.Container(), route[0].PublicKey()) - if err != nil { - return fmt.Errorf("could not verify that the sender belongs to the container: %w", err) - } else if !fromCnr { - return errNodeOutsideContainer - } - - err = loadroute.CheckRoute(c.routeBuilder, a, route) - if err != nil { - return fmt.Errorf("wrong route of container's used space value: %w", err) - } - - err = w.Put(a) - if err != nil { - return fmt.Errorf("could not write container's used space value: %w", err) - } - - return nil -} - // implements interface required by container service provided by morph executor. type morphContainerReader struct { eacl containerCore.EACLSource diff --git a/pkg/services/container/announcement/load/controller/calls.go b/pkg/services/container/announcement/load/controller/calls.go deleted file mode 100644 index e1ed6e496b..0000000000 --- a/pkg/services/container/announcement/load/controller/calls.go +++ /dev/null @@ -1,307 +0,0 @@ -package loadcontroller - -import ( - "context" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "go.uber.org/zap" -) - -// StartPrm groups the required parameters of the Controller.Start method. -type StartPrm struct { - // Epoch number by which you want to select - // the values of the used space of containers. - Epoch uint64 -} - -type commonContext struct { - epoch uint64 - - ctrl *Controller - - log *logger.Logger -} - -type announcer struct { - commonContext -} - -// Start starts the processing of container.SizeEstimation values. -// -// Single Start operation overtakes all data from LocalMetrics to -// LocalAnnouncementTarget (Controller's parameters). -// No filter by epoch is used for the iterator, since it is expected -// that the source of metrics does not track the change of epochs. -// -// Each call acquires an announcement context for an Epoch parameter. -// At the very end of the operation, the context is released. -func (c *Controller) Start(ctx context.Context, prm StartPrm) { - var announcer *announcer - // acquire announcement - ctx, announcer = c.acquireAnnouncement(ctx, prm) - if announcer == nil { - return - } - - // finally stop and free the announcement - defer announcer.freeAnnouncement() - - // announce local values - announcer.announce(ctx) -} - -func (c *announcer) announce(ctx context.Context) { - c.log.Debug(logs.ControllerStartingToAnnounceTheValuesOfTheMetrics) - - var ( - metricsIterator Iterator - err error - ) - - // initialize iterator over locally collected metrics - metricsIterator, err = c.ctrl.prm.LocalMetrics.InitIterator() - if err != nil { - c.log.Debug(logs.ControllerCouldNotInitializeIteratorOverLocallyCollectedMetrics, - zap.String("error", err.Error()), - ) - - return - } - - // initialize target of local announcements - targetWriter, err := c.ctrl.prm.LocalAnnouncementTarget.InitWriter(nil) - if err != nil { - c.log.Debug(logs.ControllerCouldNotInitializeAnnouncementAccumulator, - zap.String("error", err.Error()), - ) - - return - } - - // iterate over all collected metrics and write them to the target - err = metricsIterator.Iterate( - func(container.SizeEstimation) bool { - return true // local metrics don't know about epochs - }, - func(a container.SizeEstimation) error { - a.SetEpoch(c.epoch) // set epoch explicitly - return targetWriter.Put(a) - }, - ) - if err != nil { - c.log.Debug(logs.ControllerIteratorOverLocallyCollectedMetricsAborted, - zap.String("error", err.Error()), - ) - - return - } - - // finish writing - err = targetWriter.Close(ctx) - if err != nil { - c.log.Debug(logs.ControllerCouldNotFinishWritingLocalAnnouncements, - zap.String("error", err.Error()), - ) - - return - } - - c.log.Debug(logs.ControllerTrustAnnouncementSuccessfullyFinished) -} - -func (c *Controller) acquireAnnouncement(ctx context.Context, prm StartPrm) (context.Context, *announcer) { - started := true - c.announceMtx.Lock() - { - if cancel := c.mAnnounceCtx[prm.Epoch]; cancel == nil { - ctx, cancel = context.WithCancel(ctx) - c.mAnnounceCtx[prm.Epoch] = cancel - started = false - } - } - c.announceMtx.Unlock() - - log := &logger.Logger{Logger: c.opts.log.With( - zap.Uint64("epoch", prm.Epoch), - )} - - if started { - log.Debug(logs.ControllerAnnouncementIsAlreadyStarted) - return ctx, nil - } - - return ctx, &announcer{ - commonContext: commonContext{ - epoch: prm.Epoch, - ctrl: c, - log: log, - }, - } -} - -func (c *commonContext) freeAnnouncement() { - var stopped bool - - c.ctrl.announceMtx.Lock() - - { - var cancel context.CancelFunc - - cancel, stopped = c.ctrl.mAnnounceCtx[c.epoch] - - if stopped { - cancel() - delete(c.ctrl.mAnnounceCtx, c.epoch) - } - } - - c.ctrl.announceMtx.Unlock() - - if stopped { - c.log.Debug(logs.ControllerAnnouncementSuccessfullyInterrupted) - } else { - c.log.Debug(logs.ControllerAnnouncementIsNotStartedOrAlreadyInterrupted) - } -} - -// StopPrm groups the required parameters of the Controller.Stop method. -type StopPrm struct { - // Epoch number the analysis of the values of which must be interrupted. - Epoch uint64 -} - -type reporter struct { - commonContext -} - -// Stop interrupts the processing of container.SizeEstimation values. -// -// Single Stop operation releases an announcement context and overtakes -// all data from AnnouncementAccumulator to ResultReceiver (Controller's -// parameters). Only values for the specified Epoch parameter are processed. -// -// Each call acquires a report context for an Epoch parameter. -// At the very end of the operation, the context is released. -func (c *Controller) Stop(ctx context.Context, prm StopPrm) { - var reporter *reporter - ctx, reporter = c.acquireReport(ctx, prm) - if reporter == nil { - return - } - - // finally stop and free reporting - defer reporter.freeReport() - - // interrupt announcement - reporter.freeAnnouncement() - - // report the estimations - reporter.report(ctx) -} - -func (c *Controller) acquireReport(ctx context.Context, prm StopPrm) (context.Context, *reporter) { - started := true - - c.reportMtx.Lock() - { - if cancel := c.mReportCtx[prm.Epoch]; cancel == nil { - ctx, cancel = context.WithCancel(ctx) - c.mReportCtx[prm.Epoch] = cancel - started = false - } - } - - c.reportMtx.Unlock() - - log := &logger.Logger{Logger: c.opts.log.With( - zap.Uint64("epoch", prm.Epoch), - )} - - if started { - log.Debug(logs.ControllerReportIsAlreadyStarted) - return ctx, nil - } - - return ctx, &reporter{ - commonContext: commonContext{ - epoch: prm.Epoch, - ctrl: c, - log: log, - }, - } -} - -func (c *commonContext) freeReport() { - var stopped bool - - c.ctrl.reportMtx.Lock() - - { - var cancel context.CancelFunc - - cancel, stopped = c.ctrl.mReportCtx[c.epoch] - - if stopped { - cancel() - delete(c.ctrl.mReportCtx, c.epoch) - } - } - - c.ctrl.reportMtx.Unlock() - - if stopped { - c.log.Debug(logs.ControllerAnnouncementSuccessfullyInterrupted) - } else { - c.log.Debug(logs.ControllerAnnouncementIsNotStartedOrAlreadyInterrupted) - } -} - -func (c *reporter) report(ctx context.Context) { - var ( - localIterator Iterator - err error - ) - - // initialize iterator over locally accumulated announcements - localIterator, err = c.ctrl.prm.AnnouncementAccumulator.InitIterator() - if err != nil { - c.log.Debug(logs.ControllerCouldNotInitializeIteratorOverLocallyAccumulatedAnnouncements, - zap.String("error", err.Error()), - ) - - return - } - - // initialize final destination of load estimations - resultWriter, err := c.ctrl.prm.ResultReceiver.InitWriter(nil) - if err != nil { - c.log.Debug(logs.ControllerCouldNotInitializeResultTarget, - zap.String("error", err.Error()), - ) - - return - } - - // iterate over all accumulated announcements and write them to the target - err = localIterator.Iterate( - usedSpaceFilterEpochEQ(c.epoch), - resultWriter.Put, - ) - if err != nil { - c.log.Debug(logs.ControllerIteratorOverLocalAnnouncementsAborted, - zap.String("error", err.Error()), - ) - - return - } - - // finish writing - err = resultWriter.Close(ctx) - if err != nil { - c.log.Debug(logs.ControllerCouldNotFinishWritingLoadEstimations, - zap.String("error", err.Error()), - ) - } -} diff --git a/pkg/services/container/announcement/load/controller/calls_test.go b/pkg/services/container/announcement/load/controller/calls_test.go deleted file mode 100644 index 6ca24e8699..0000000000 --- a/pkg/services/container/announcement/load/controller/calls_test.go +++ /dev/null @@ -1,192 +0,0 @@ -package loadcontroller_test - -import ( - "context" - "math/rand" - "sync" - "testing" - - loadcontroller "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/controller" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - "github.com/stretchr/testify/require" -) - -type testAnnouncementStorage struct { - w loadcontroller.Writer - - i loadcontroller.Iterator - - mtx sync.RWMutex - - m map[uint64][]container.SizeEstimation -} - -func newTestStorage() *testAnnouncementStorage { - return &testAnnouncementStorage{ - m: make(map[uint64][]container.SizeEstimation), - } -} - -func (s *testAnnouncementStorage) InitIterator() (loadcontroller.Iterator, error) { - if s.i != nil { - return s.i, nil - } - - return s, nil -} - -func (s *testAnnouncementStorage) Iterate(f loadcontroller.UsedSpaceFilter, h loadcontroller.UsedSpaceHandler) error { - s.mtx.RLock() - defer s.mtx.RUnlock() - - for _, v := range s.m { - for _, a := range v { - if f(a) { - if err := h(a); err != nil { - return err - } - } - } - } - - return nil -} - -func (s *testAnnouncementStorage) InitWriter([]loadcontroller.ServerInfo) (loadcontroller.Writer, error) { - if s.w != nil { - return s.w, nil - } - - return s, nil -} - -func (s *testAnnouncementStorage) Put(v container.SizeEstimation) error { - s.mtx.Lock() - s.m[v.Epoch()] = append(s.m[v.Epoch()], v) - s.mtx.Unlock() - - return nil -} - -func (s *testAnnouncementStorage) Close(context.Context) error { - return nil -} - -func randAnnouncement() (a container.SizeEstimation) { - a.SetContainer(cidtest.ID()) - a.SetValue(rand.Uint64()) - - return -} - -func TestSimpleScenario(t *testing.T) { - // create storage to write final estimations - resultStorage := newTestStorage() - - // create storages to accumulate announcements - accumulatingStorageN2 := newTestStorage() - - // create storage of local metrics - localStorageN1 := newTestStorage() - localStorageN2 := newTestStorage() - - // create 2 controllers: 1st writes announcements to 2nd, 2nd directly to final destination - ctrlN1 := loadcontroller.New(loadcontroller.Prm{ - LocalMetrics: localStorageN1, - AnnouncementAccumulator: newTestStorage(), - LocalAnnouncementTarget: &testAnnouncementStorage{ - w: accumulatingStorageN2, - }, - ResultReceiver: resultStorage, - }) - - ctrlN2 := loadcontroller.New(loadcontroller.Prm{ - LocalMetrics: localStorageN2, - AnnouncementAccumulator: accumulatingStorageN2, - LocalAnnouncementTarget: &testAnnouncementStorage{ - w: resultStorage, - }, - ResultReceiver: resultStorage, - }) - - const processEpoch uint64 = 10 - - const goodNum = 4 - - // create 2 random values for processing epoch and 1 for some different - announces := make([]container.SizeEstimation, 0, goodNum) - - for i := 0; i < goodNum; i++ { - a := randAnnouncement() - a.SetEpoch(processEpoch) - - announces = append(announces, a) - } - - // store one half of "good" announcements to 1st metrics storage, another - to 2nd - // and "bad" to both - for i := 0; i < goodNum/2; i++ { - require.NoError(t, localStorageN1.Put(announces[i])) - } - - for i := goodNum / 2; i < goodNum; i++ { - require.NoError(t, localStorageN2.Put(announces[i])) - } - - wg := new(sync.WaitGroup) - wg.Add(2) - - startPrm := loadcontroller.StartPrm{ - Epoch: processEpoch, - } - - // start both controllers - go func() { - ctrlN1.Start(context.Background(), startPrm) - wg.Done() - }() - - go func() { - ctrlN2.Start(context.Background(), startPrm) - wg.Done() - }() - - wg.Wait() - wg.Add(2) - - stopPrm := loadcontroller.StopPrm{ - Epoch: processEpoch, - } - - // stop both controllers - go func() { - ctrlN1.Stop(context.Background(), stopPrm) - wg.Done() - }() - - go func() { - ctrlN2.Stop(context.Background(), stopPrm) - wg.Done() - }() - - wg.Wait() - - // result target should contain all "good" announcements and shoult not container the "bad" one - var res []container.SizeEstimation - - err := resultStorage.Iterate( - func(a container.SizeEstimation) bool { - return true - }, - func(a container.SizeEstimation) error { - res = append(res, a) - return nil - }, - ) - require.NoError(t, err) - - for i := range announces { - require.Contains(t, res, announces[i]) - } -} diff --git a/pkg/services/container/announcement/load/controller/controller.go b/pkg/services/container/announcement/load/controller/controller.go deleted file mode 100644 index ef6dbade73..0000000000 --- a/pkg/services/container/announcement/load/controller/controller.go +++ /dev/null @@ -1,94 +0,0 @@ -package loadcontroller - -import ( - "context" - "fmt" - "sync" -) - -// Prm groups the required parameters of the Controller's constructor. -// -// All values must comply with the requirements imposed on them. -// Passing incorrect parameter values will result in constructor -// failure (error or panic depending on the implementation). -type Prm struct { - // Iterator over the used space values of the containers - // collected by the node locally. - LocalMetrics IteratorProvider - - // Place of recording the local values of - // the used space of containers. - LocalAnnouncementTarget WriterProvider - - // Iterator over the summarized used space scores - // from the various network participants. - AnnouncementAccumulator IteratorProvider - - // Place of recording the final estimates of - // the used space of containers. - ResultReceiver WriterProvider -} - -// Controller represents main handler for starting -// and interrupting container volume estimation. -// -// It binds the interfaces of the local value stores -// to the target storage points. Controller is abstracted -// from the internal storage device and the network location -// of the connecting components. At its core, it is a -// high-level start-stop trigger for calculations. -// -// For correct operation, the controller must be created -// using the constructor (New) based on the required parameters -// and optional components. After successful creation, -// the constructor is immediately ready to work through -// API of external control of calculations and data transfer. -type Controller struct { - prm Prm - - opts *options - - announceMtx sync.Mutex - mAnnounceCtx map[uint64]context.CancelFunc - - reportMtx sync.Mutex - mReportCtx map[uint64]context.CancelFunc -} - -const invalidPrmValFmt = "invalid parameter %s (%T):%v" - -func panicOnPrmValue(n string, v any) { - panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) -} - -// New creates a new instance of the Controller. -// -// Panics if at least one value of the parameters is invalid. -// -// The created Controller does not require additional -// initialization and is completely ready for work. -func New(prm Prm, opts ...Option) *Controller { - switch { - case prm.LocalMetrics == nil: - panicOnPrmValue("LocalMetrics", prm.LocalMetrics) - case prm.AnnouncementAccumulator == nil: - panicOnPrmValue("AnnouncementAccumulator", prm.AnnouncementAccumulator) - case prm.LocalAnnouncementTarget == nil: - panicOnPrmValue("LocalAnnouncementTarget", prm.LocalAnnouncementTarget) - case prm.ResultReceiver == nil: - panicOnPrmValue("ResultReceiver", prm.ResultReceiver) - } - - o := defaultOpts() - - for _, opt := range opts { - opt(o) - } - - return &Controller{ - prm: prm, - opts: o, - mAnnounceCtx: make(map[uint64]context.CancelFunc), - mReportCtx: make(map[uint64]context.CancelFunc), - } -} diff --git a/pkg/services/container/announcement/load/controller/deps.go b/pkg/services/container/announcement/load/controller/deps.go deleted file mode 100644 index 99da8594f3..0000000000 --- a/pkg/services/container/announcement/load/controller/deps.go +++ /dev/null @@ -1,103 +0,0 @@ -package loadcontroller - -import ( - "context" - - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" -) - -// UsedSpaceHandler describes the signature of the container.SizeEstimation -// value handling function. -// -// Termination of processing without failures is usually signaled -// with a zero error, while a specific value may describe the reason -// for failure. -type UsedSpaceHandler func(container.SizeEstimation) error - -// UsedSpaceFilter describes the signature of the function for -// checking whether a value meets a certain criterion. -// -// Return of true means conformity, false - vice versa. -type UsedSpaceFilter func(container.SizeEstimation) bool - -// Iterator is a group of methods provided by entity -// which can iterate over a group of container.SizeEstimation values. -type Iterator interface { - // Iterate must start an iterator over values that - // meet the filter criterion (returns true). - // For each such value should call a handler, the error - // of which should be directly returned from the method. - // - // Internal failures of the iterator are also signaled via - // an error. After a successful call to the last value - // handler, nil should be returned. - Iterate(UsedSpaceFilter, UsedSpaceHandler) error -} - -// IteratorProvider is a group of methods provided -// by entity which generates iterators over -// container.SizeEstimation values. -type IteratorProvider interface { - // InitIterator should return an initialized Iterator. - // - // Initialization problems are reported via error. - // If no error was returned, then the Iterator must not be nil. - // - // Implementations can have different logic for different - // contexts, so specific ones may document their own behavior. - InitIterator() (Iterator, error) -} - -// Writer describes the interface for storing container.SizeEstimation values. -// -// This interface is provided by both local storage -// of values and remote (wrappers over the RPC). -type Writer interface { - // Put performs a write operation of container.SizeEstimation value - // and returns any error encountered. - // - // All values after the Close call must be flushed to the - // physical target. Implementations can cache values before - // Close operation. - // - // Put must not be called after Close. - Put(container.SizeEstimation) error - - // Close exits with method-providing Writer. - // - // All cached values must be flushed before - // the Close's return. - // - // Methods must not be called after Close. - Close(ctx context.Context) error -} - -// WriterProvider is a group of methods provided -// by entity which generates keepers of -// container.SizeEstimation values. -type WriterProvider interface { - // InitWriter should return an initialized Writer. - // - // Initialization problems are reported via error. - // If no error was returned, then the Writer must not be nil. - InitWriter(route []ServerInfo) (Writer, error) -} - -// ServerInfo describes a set of -// characteristics of a point in a route. -type ServerInfo interface { - // PublicKey returns public key of the node - // from the route in a binary representation. - PublicKey() []byte - - // Iterates over network addresses of the node - // in the route. Breaks iterating on true return - // of the handler. - IterateAddresses(func(string) bool) - - // Returns number of server's network addresses. - NumberOfAddresses() int - - // ExternalAddresses returns external node's addresses. - ExternalAddresses() []string -} diff --git a/pkg/services/container/announcement/load/controller/opts.go b/pkg/services/container/announcement/load/controller/opts.go deleted file mode 100644 index 29148def01..0000000000 --- a/pkg/services/container/announcement/load/controller/opts.go +++ /dev/null @@ -1,28 +0,0 @@ -package loadcontroller - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" -) - -// Option sets an optional parameter of Controller. -type Option func(*options) - -type options struct { - log *logger.Logger -} - -func defaultOpts() *options { - return &options{ - log: &logger.Logger{Logger: zap.L()}, - } -} - -// WithLogger returns option to specify logging component. -func WithLogger(l *logger.Logger) Option { - return func(o *options) { - if l != nil { - o.log = l - } - } -} diff --git a/pkg/services/container/announcement/load/controller/util.go b/pkg/services/container/announcement/load/controller/util.go deleted file mode 100644 index 223de13baf..0000000000 --- a/pkg/services/container/announcement/load/controller/util.go +++ /dev/null @@ -1,36 +0,0 @@ -package loadcontroller - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" -) - -func usedSpaceFilterEpochEQ(epoch uint64) UsedSpaceFilter { - return func(a container.SizeEstimation) bool { - return a.Epoch() == epoch - } -} - -type storageWrapper struct { - w Writer - i Iterator -} - -func (s storageWrapper) InitIterator() (Iterator, error) { - return s.i, nil -} - -func (s storageWrapper) InitWriter([]ServerInfo) (Writer, error) { - return s.w, nil -} - -func SimpleIteratorProvider(i Iterator) IteratorProvider { - return &storageWrapper{ - i: i, - } -} - -func SimpleWriterProvider(w Writer) WriterProvider { - return &storageWrapper{ - w: w, - } -} diff --git a/pkg/services/container/announcement/load/route/calls.go b/pkg/services/container/announcement/load/route/calls.go deleted file mode 100644 index 9a483aed09..0000000000 --- a/pkg/services/container/announcement/load/route/calls.go +++ /dev/null @@ -1,145 +0,0 @@ -package loadroute - -import ( - "context" - "encoding/hex" - "sync" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - loadcontroller "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/controller" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "go.uber.org/zap" -) - -// InitWriter initializes and returns Writer that sends each value to its next route point. -// -// If route is present, then it is taken into account, -// and the value will be sent to its continuation. Otherwise, the route will be laid -// from scratch and the value will be sent to its primary point. -// -// After building a list of remote points of the next leg of the route, the value is sent -// sequentially to all of them. If any transmissions (even all) fail, an error will not -// be returned. -// -// Close of the composed Writer calls Close method on each internal Writer generated in -// runtime and never returns an error. -// -// Always returns nil error. -func (r *Router) InitWriter(route []loadcontroller.ServerInfo) (loadcontroller.Writer, error) { - if len(route) == 0 { - route = []loadcontroller.ServerInfo{r.localSrvInfo} - } - - return &loadWriter{ - router: r, - route: route, - mRoute: make(map[routeKey]*valuesRoute), - mServers: make(map[string]loadcontroller.Writer), - }, nil -} - -type routeKey struct { - epoch uint64 - - cid string -} - -type valuesRoute struct { - route []loadcontroller.ServerInfo - - values []container.SizeEstimation -} - -type loadWriter struct { - router *Router - - route []loadcontroller.ServerInfo - - routeMtx sync.RWMutex - mRoute map[routeKey]*valuesRoute - - mServers map[string]loadcontroller.Writer -} - -func (w *loadWriter) Put(a container.SizeEstimation) error { - w.routeMtx.Lock() - defer w.routeMtx.Unlock() - - key := routeKey{ - epoch: a.Epoch(), - cid: a.Container().EncodeToString(), - } - - routeValues, ok := w.mRoute[key] - if !ok { - route, err := w.router.routeBuilder.NextStage(a, w.route) - if err != nil { - return err - } else if len(route) == 0 { - route = []loadcontroller.ServerInfo{nil} - } - - routeValues = &valuesRoute{ - route: route, - values: []container.SizeEstimation{a}, - } - - w.mRoute[key] = routeValues - } - - for _, remoteInfo := range routeValues.route { - var key string - - if remoteInfo != nil { - key = hex.EncodeToString(remoteInfo.PublicKey()) - } - - remoteWriter, ok := w.mServers[key] - if !ok { - provider, err := w.router.remoteProvider.InitRemote(remoteInfo) - if err != nil { - w.router.log.Debug(logs.RouteCouldNotInitializeWriterProvider, - zap.String("error", err.Error()), - ) - - continue // best effort - } - - remoteWriter, err = provider.InitWriter(w.route) - if err != nil { - w.router.log.Debug(logs.RouteCouldNotInitializeWriter, - zap.String("error", err.Error()), - ) - - continue // best effort - } - - w.mServers[key] = remoteWriter - } - - err := remoteWriter.Put(a) - if err != nil { - w.router.log.Debug(logs.RouteCouldNotPutTheValue, - zap.String("error", err.Error()), - ) - } - - // continue best effort - } - - return nil -} - -func (w *loadWriter) Close(ctx context.Context) error { - for key, wRemote := range w.mServers { - err := wRemote.Close(ctx) - if err != nil { - w.router.log.Debug(logs.RouteCouldNotCloseRemoteServerWriter, - zap.String("key", key), - zap.String("error", err.Error()), - ) - } - } - - return nil -} diff --git a/pkg/services/container/announcement/load/route/deps.go b/pkg/services/container/announcement/load/route/deps.go deleted file mode 100644 index b255900f70..0000000000 --- a/pkg/services/container/announcement/load/route/deps.go +++ /dev/null @@ -1,31 +0,0 @@ -package loadroute - -import ( - loadcontroller "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/controller" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" -) - -// Builder groups methods to route values in the network. -type Builder interface { - // NextStage must return next group of route points for the value a - // based on the passed route. - // - // Empty passed list means being at the starting point of the route. - // - // Must return empty list and no error if the endpoint of the route is reached. - // If there are more than one point to go and the last passed point is included - // in that list (means that point is the last point in one of the route groups), - // returned route must contain nil point that should be interpreted as signal to, - // among sending to other route points, save the announcement in that point. - NextStage(a container.SizeEstimation, passed []loadcontroller.ServerInfo) ([]loadcontroller.ServerInfo, error) -} - -// RemoteWriterProvider describes the component -// for sending values to a fixed route point. -type RemoteWriterProvider interface { - // InitRemote must return WriterProvider to the route point - // corresponding to info. - // - // Nil info matches the end of the route. - InitRemote(info loadcontroller.ServerInfo) (loadcontroller.WriterProvider, error) -} diff --git a/pkg/services/container/announcement/load/route/opts.go b/pkg/services/container/announcement/load/route/opts.go deleted file mode 100644 index ab140ab4c7..0000000000 --- a/pkg/services/container/announcement/load/route/opts.go +++ /dev/null @@ -1,28 +0,0 @@ -package loadroute - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" -) - -// Option sets an optional parameter of Router. -type Option func(*options) - -type options struct { - log *logger.Logger -} - -func defaultOpts() *options { - return &options{ - log: &logger.Logger{Logger: zap.L()}, - } -} - -// WithLogger returns Option to specify logging component. -func WithLogger(l *logger.Logger) Option { - return func(o *options) { - if l != nil { - o.log = l - } - } -} diff --git a/pkg/services/container/announcement/load/route/placement/builder.go b/pkg/services/container/announcement/load/route/placement/builder.go deleted file mode 100644 index 493b89723c..0000000000 --- a/pkg/services/container/announcement/load/route/placement/builder.go +++ /dev/null @@ -1,49 +0,0 @@ -package placementrouter - -import "fmt" - -// Prm groups the required parameters of the Builder's constructor. -// -// All values must comply with the requirements imposed on them. -// Passing incorrect parameter values will result in constructor -// failure (error or panic depending on the implementation). -type Prm struct { - // Calculator of the container members. - // - // Must not be nil. - PlacementBuilder PlacementBuilder -} - -// Builder represents component that routes used container space -// values between nodes from the container. -// -// For correct operation, Builder must be created using -// the constructor (New) based on the required parameters -// and optional components. After successful creation, -// the Builder is immediately ready to work through API. -type Builder struct { - placementBuilder PlacementBuilder -} - -const invalidPrmValFmt = "invalid parameter %s (%T):%v" - -func panicOnPrmValue(n string, v any) { - panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) -} - -// New creates a new instance of the Builder. -// -// Panics if at least one value of the parameters is invalid. -// -// The created Builder does not require additional -// initialization and is completely ready for work. -func New(prm Prm) *Builder { - switch { - case prm.PlacementBuilder == nil: - panicOnPrmValue("PlacementBuilder", prm.PlacementBuilder) - } - - return &Builder{ - placementBuilder: prm.PlacementBuilder, - } -} diff --git a/pkg/services/container/announcement/load/route/placement/calls.go b/pkg/services/container/announcement/load/route/placement/calls.go deleted file mode 100644 index 68bdb43a74..0000000000 --- a/pkg/services/container/announcement/load/route/placement/calls.go +++ /dev/null @@ -1,47 +0,0 @@ -package placementrouter - -import ( - "bytes" - "fmt" - - netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - loadcontroller "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/controller" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" -) - -// NextStage composes container nodes for the container and epoch from a, -// and returns the list of nodes with maximum weight (one from each vector). -// -// If passed route has more than one point, then endpoint of the route is reached. -// -// The traversed route is not checked, it is assumed to be correct. -func (b *Builder) NextStage(a container.SizeEstimation, passed []loadcontroller.ServerInfo) ([]loadcontroller.ServerInfo, error) { - if len(passed) > 1 { - return nil, nil - } - - cnr := a.Container() - - placement, err := b.placementBuilder.BuildPlacement(a.Epoch(), cnr) - if err != nil { - return nil, fmt.Errorf("could not build placement %s: %w", cnr, err) - } - - res := make([]loadcontroller.ServerInfo, 0, len(placement)) - - for i := range placement { - if len(placement[i]) == 0 { - continue - } - - if len(passed) == 1 && bytes.Equal(passed[0].PublicKey(), placement[i][0].PublicKey()) { - // add nil element so the announcement will be saved in local memory - res = append(res, nil) - } else { - // add element with remote node to send announcement to - res = append(res, netmapcore.Node(placement[i][0])) - } - } - - return res, nil -} diff --git a/pkg/services/container/announcement/load/route/placement/deps.go b/pkg/services/container/announcement/load/route/placement/deps.go deleted file mode 100644 index 43339eb47f..0000000000 --- a/pkg/services/container/announcement/load/route/placement/deps.go +++ /dev/null @@ -1,14 +0,0 @@ -package placementrouter - -import ( - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" -) - -// PlacementBuilder describes interface of FrostFS placement calculator. -type PlacementBuilder interface { - // BuildPlacement must compose and sort (according to a specific algorithm) - // storage nodes from the container by its identifier using network map - // of particular epoch. - BuildPlacement(epoch uint64, cnr cid.ID) ([][]netmap.NodeInfo, error) -} diff --git a/pkg/services/container/announcement/load/route/router.go b/pkg/services/container/announcement/load/route/router.go deleted file mode 100644 index c8f784b16b..0000000000 --- a/pkg/services/container/announcement/load/route/router.go +++ /dev/null @@ -1,87 +0,0 @@ -package loadroute - -import ( - "fmt" - - loadcontroller "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/controller" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" -) - -// Prm groups the required parameters of the Router's constructor. -// -// All values must comply with the requirements imposed on them. -// Passing incorrect parameter values will result in constructor -// failure (error or panic depending on the implementation). -type Prm struct { - // Characteristics of the local node's server. - // - // Must not be nil. - LocalServerInfo loadcontroller.ServerInfo - - // Component for sending values to a fixed route point. - // - // Must not be nil. - RemoteWriterProvider RemoteWriterProvider - - // Route planner. - // - // Must not be nil. - Builder Builder -} - -// Router represents component responsible for routing -// used container space values over the network. -// -// For each fixed pair (container ID, epoch) there is a -// single value route on the network. Router provides the -// interface for writing values to the next point of the route. -// -// For correct operation, Router must be created using -// the constructor (New) based on the required parameters -// and optional components. After successful creation, -// the Router is immediately ready to work through API. -type Router struct { - log *logger.Logger - - remoteProvider RemoteWriterProvider - - routeBuilder Builder - - localSrvInfo loadcontroller.ServerInfo -} - -const invalidPrmValFmt = "invalid parameter %s (%T):%v" - -func panicOnPrmValue(n string, v any) { - panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) -} - -// New creates a new instance of the Router. -// -// Panics if at least one value of the parameters is invalid. -// -// The created Router does not require additional -// initialization and is completely ready for work. -func New(prm Prm, opts ...Option) *Router { - switch { - case prm.RemoteWriterProvider == nil: - panicOnPrmValue("RemoteWriterProvider", prm.RemoteWriterProvider) - case prm.Builder == nil: - panicOnPrmValue("Builder", prm.Builder) - case prm.LocalServerInfo == nil: - panicOnPrmValue("LocalServerInfo", prm.LocalServerInfo) - } - - o := defaultOpts() - - for i := range opts { - opts[i](o) - } - - return &Router{ - log: o.log, - remoteProvider: prm.RemoteWriterProvider, - routeBuilder: prm.Builder, - localSrvInfo: prm.LocalServerInfo, - } -} diff --git a/pkg/services/container/announcement/load/route/util.go b/pkg/services/container/announcement/load/route/util.go deleted file mode 100644 index ea0f51aadb..0000000000 --- a/pkg/services/container/announcement/load/route/util.go +++ /dev/null @@ -1,49 +0,0 @@ -package loadroute - -import ( - "bytes" - "errors" - - loadcontroller "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/controller" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" -) - -var errWrongRoute = errors.New("wrong route") - -// CheckRoute checks if the route is a route correctly constructed by the builder for value a. -// -// Returns nil if route is correct, otherwise an error clarifying the inconsistency. -func CheckRoute(builder Builder, a container.SizeEstimation, route []loadcontroller.ServerInfo) error { - for i := 1; i < len(route); i++ { - servers, err := builder.NextStage(a, route[:i]) - if err != nil { - return err - } else if len(servers) == 0 { - break - } - - found := false - - for j := range servers { - if servers[j] == nil { - // nil route point means that - // (i-1)-th node in the route - // must, among other things, - // save the announcement to its - // local memory - continue - } - - if bytes.Equal(servers[j].PublicKey(), route[i].PublicKey()) { - found = true - break - } - } - - if !found { - return errWrongRoute - } - } - - return nil -} diff --git a/pkg/services/container/announcement/load/storage/storage.go b/pkg/services/container/announcement/load/storage/storage.go deleted file mode 100644 index 4d3104c762..0000000000 --- a/pkg/services/container/announcement/load/storage/storage.go +++ /dev/null @@ -1,151 +0,0 @@ -package loadstorage - -import ( - "context" - "sort" - "sync" - - loadcontroller "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/announcement/load/controller" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" -) - -type usedSpaceEstimations struct { - announcement container.SizeEstimation - - sizes []uint64 -} - -type storageKey struct { - epoch uint64 - - cid string -} - -// Storage represents in-memory storage of -// container.SizeEstimation values. -// -// The write operation has the usual behavior - to save -// the next number of used container space for a specific epoch. -// All values related to one key (epoch, container ID) are stored -// as a list. -// -// Storage also provides an iterator interface, into the handler -// of which the final score is passed, built on all values saved -// at the time of the call. Currently the only possible estimation -// formula is used - the average between 10th and 90th percentile. -// -// For correct operation, Storage must be created -// using the constructor (New) based on the required parameters -// and optional components. After successful creation, -// Storage is immediately ready to work through API. -type Storage struct { - mtx sync.RWMutex - - mItems map[storageKey]*usedSpaceEstimations -} - -// Prm groups the required parameters of the Storage's constructor. -// -// The component is not parameterizable at the moment. -type Prm struct{} - -// New creates a new instance of the Storage. -// -// The created Storage does not require additional -// initialization and is completely ready for work. -func New(_ Prm) *Storage { - return &Storage{ - mItems: make(map[storageKey]*usedSpaceEstimations), - } -} - -// Put appends the next value of the occupied container space for the epoch -// to the list of already saved values. -// -// Always returns nil error. -func (s *Storage) Put(a container.SizeEstimation) error { - s.mtx.Lock() - - { - key := storageKey{ - epoch: a.Epoch(), - cid: a.Container().EncodeToString(), - } - - estimations, ok := s.mItems[key] - if !ok { - estimations = &usedSpaceEstimations{ - announcement: a, - sizes: make([]uint64, 0, 1), - } - - s.mItems[key] = estimations - } - - estimations.sizes = append(estimations.sizes, a.Value()) - } - - s.mtx.Unlock() - - return nil -} - -func (s *Storage) Close(context.Context) error { - return nil -} - -// Iterate goes through all the lists with the key (container ID, epoch), -// calculates the final grade for all values, and passes it to the handler. -// -// Final grade is the average between 10th and 90th percentiles. -func (s *Storage) Iterate(f loadcontroller.UsedSpaceFilter, h loadcontroller.UsedSpaceHandler) (err error) { - s.mtx.RLock() - - { - for _, v := range s.mItems { - if f(v.announcement) { - // calculate estimation based on 90th percentile - v.announcement.SetValue(finalEstimation(v.sizes)) - - if err = h(v.announcement); err != nil { - break - } - } - } - } - - s.mtx.RUnlock() - - return -} - -func finalEstimation(vals []uint64) uint64 { - sort.Slice(vals, func(i, j int) bool { - return vals[i] < vals[j] - }) - - const ( - lowerRank = 10 - upperRank = 90 - ) - - if len(vals) >= lowerRank { - lowerInd := percentile(lowerRank, vals) - upperInd := percentile(upperRank, vals) - - vals = vals[lowerInd:upperInd] - } - - sum := uint64(0) - - for i := range vals { - sum += vals[i] - } - - return sum / uint64(len(vals)) -} - -func percentile(rank int, vals []uint64) int { - p := len(vals) * rank / 100 - return p -} diff --git a/pkg/services/container/announcement/load/storage/storage_test.go b/pkg/services/container/announcement/load/storage/storage_test.go deleted file mode 100644 index 20e73627dc..0000000000 --- a/pkg/services/container/announcement/load/storage/storage_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package loadstorage - -import ( - "math/rand" - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - "github.com/stretchr/testify/require" -) - -func TestStorage(t *testing.T) { - const epoch uint64 = 13 - - var a container.SizeEstimation - a.SetContainer(cidtest.ID()) - a.SetEpoch(epoch) - - const opinionsNum = 100 - - s := New(Prm{}) - - opinions := make([]uint64, opinionsNum) - for i := range opinions { - opinions[i] = rand.Uint64() - - a.SetValue(opinions[i]) - - require.NoError(t, s.Put(a)) - } - - iterCounter := 0 - - err := s.Iterate( - func(ai container.SizeEstimation) bool { - return ai.Epoch() == epoch - }, - func(ai container.SizeEstimation) error { - iterCounter++ - - require.Equal(t, epoch, ai.Epoch()) - require.Equal(t, a.Container(), ai.Container()) - require.Equal(t, finalEstimation(opinions), ai.Value()) - - return nil - }, - ) - require.NoError(t, err) - require.Equal(t, 1, iterCounter) -} From 5e229dc2481c3a745ec702f6c74353e648ce649d Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Wed, 4 Oct 2023 19:20:59 +0300 Subject: [PATCH 0068/1413] [#701] metrics: add metric to evaluate policer performance Add processed objects counter in policerMetrics, add policer field to NodeMetrics Signed-off-by: Ekaterina Lebedeva --- pkg/metrics/consts.go | 1 + pkg/metrics/node.go | 6 ++++++ pkg/metrics/policer.go | 29 +++++++++++++++++++++++++++++ pkg/services/policer/metrics.go | 5 +++++ pkg/services/policer/option.go | 2 ++ pkg/services/policer/process.go | 1 + 6 files changed, 44 insertions(+) create mode 100644 pkg/metrics/policer.go create mode 100644 pkg/services/policer/metrics.go diff --git a/pkg/metrics/consts.go b/pkg/metrics/consts.go index 550eec4241..f7a8fd771e 100644 --- a/pkg/metrics/consts.go +++ b/pkg/metrics/consts.go @@ -20,6 +20,7 @@ const ( treeServiceSubsystem = "treeservice" writeCacheSubsystem = "writecache" grpcServerSubsystem = "grpc_server" + policerSubsystem = "policer" successLabel = "success" shardIDLabel = "shard_id" diff --git a/pkg/metrics/node.go b/pkg/metrics/node.go index ad6864b8f0..052defa4dc 100644 --- a/pkg/metrics/node.go +++ b/pkg/metrics/node.go @@ -18,6 +18,7 @@ type NodeMetrics struct { metabase *metabaseMetrics pilorama *piloramaMetrics grpc *grpcServerMetrics + policer *policerMetrics } func NewNodeMetrics() *NodeMetrics { @@ -39,6 +40,7 @@ func NewNodeMetrics() *NodeMetrics { metabase: newMetabaseMetrics(), pilorama: newPiloramaMetrics(), grpc: newGrpcServerMetrics(), + policer: newPolicerMetrics(), } } @@ -90,3 +92,7 @@ func (m *NodeMetrics) PiloramaMetrics() PiloramaMetrics { func (m *NodeMetrics) GrpcServerMetrics() GrpcServerMetrics { return m.grpc } + +func (m *NodeMetrics) PolicerMetrics() PolicerMetrics { + return m.policer +} diff --git a/pkg/metrics/policer.go b/pkg/metrics/policer.go new file mode 100644 index 0000000000..e4bdc944e4 --- /dev/null +++ b/pkg/metrics/policer.go @@ -0,0 +1,29 @@ +package metrics + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +type PolicerMetrics interface { + IncProcessedObjects() +} + +type policerMetrics struct { + processedObjectsCounter prometheus.Counter +} + +func newPolicerMetrics() *policerMetrics { + return &policerMetrics{ + processedObjectsCounter: metrics.NewCounter(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: policerSubsystem, + Name: "processed_objects_total", + Help: "Total number of objects processed by policer", + }), + } +} + +func (m *policerMetrics) IncProcessedObjects() { + m.processedObjectsCounter.Inc() +} diff --git a/pkg/services/policer/metrics.go b/pkg/services/policer/metrics.go new file mode 100644 index 0000000000..0b83f298c6 --- /dev/null +++ b/pkg/services/policer/metrics.go @@ -0,0 +1,5 @@ +package policer + +type MetricsRegister interface { + IncProcessedObjects() +} diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 5058b026bb..3a2fdc5072 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -69,6 +69,8 @@ type cfg struct { batchSize, cacheSize uint32 rebalanceFreq, evictDuration, sleepDuration time.Duration + + metrics MetricsRegister } func defaultCfg() *cfg { diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index 2e8fe92952..873a1efb07 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -60,6 +60,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { } p.cache.Add(addr.Address, time.Now()) p.objsInWork.remove(addr.Address) + p.metrics.IncProcessedObjects() } }) if err != nil { From aca11d7474d0341b37a17e08a1a719bb3bd158fc Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 11 Oct 2023 15:13:28 +0300 Subject: [PATCH 0069/1413] [#735] policer: Allow to provide metrics from the outside Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/metrics.go | 4 ++++ pkg/services/policer/option.go | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/pkg/services/policer/metrics.go b/pkg/services/policer/metrics.go index 0b83f298c6..c2ad2b0b53 100644 --- a/pkg/services/policer/metrics.go +++ b/pkg/services/policer/metrics.go @@ -3,3 +3,7 @@ package policer type MetricsRegister interface { IncProcessedObjects() } + +type noopMetrics struct{} + +func (noopMetrics) IncProcessedObjects() {} diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 3a2fdc5072..fe47555c49 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -81,6 +81,7 @@ func defaultCfg() *cfg { rebalanceFreq: 1 * time.Second, sleepDuration: 1 * time.Second, evictDuration: 30 * time.Second, + metrics: noopMetrics{}, } } @@ -172,3 +173,10 @@ func WithPool(p *ants.Pool) Option { c.taskPool = p } } + +// WithMetrics returns option to set metrics. +func WithMetrics(m MetricsRegister) Option { + return func(c *cfg) { + c.metrics = m + } +} From 994f48f8bba365c22ca15dbba83275f87957c6a7 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 4 Oct 2023 10:03:37 +0300 Subject: [PATCH 0070/1413] [#680] metrics: Export log and morph with script Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/morph.go | 5 ++--- pkg/metrics/morph.go | 3 +-- pkg/metrics/morphcache.go | 4 ---- pkg/metrics/node.go | 13 +++++++++++++ pkg/util/logger/logger.go | 2 +- pkg/util/logger/metrics.go | 8 ++++---- scripts/export-metrics/main.go | 3 +++ 7 files changed, 24 insertions(+), 14 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 63d1605efb..5c3db0d277 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -9,7 +9,6 @@ import ( morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" @@ -42,13 +41,13 @@ func initMorphComponents(ctx context.Context, c *cfg) { c.key, client.WithDialTimeout(morphconfig.DialTimeout(c.appCfg)), client.WithLogger(c.log), - client.WithMetrics(metrics.NewMorphClientMetrics()), + client.WithMetrics(c.metricsCollector.MorphClientMetrics()), client.WithEndpoints(addresses...), client.WithConnLostCallback(func() { c.internalErr <- errors.New("morph connection has been lost") }), client.WithSwitchInterval(morphconfig.SwitchInterval(c.appCfg)), - client.WithMorphCacheMetrics(metrics.NewNodeMorphCacheMetrics()), + client.WithMorphCacheMetrics(c.metricsCollector.MorphCacheMetrics()), ) if err != nil { c.log.Info(logs.FrostFSNodeFailedToCreateNeoRPCClient, diff --git a/pkg/metrics/morph.go b/pkg/metrics/morph.go index 5215c674b7..02d7517bcb 100644 --- a/pkg/metrics/morph.go +++ b/pkg/metrics/morph.go @@ -4,7 +4,6 @@ import ( "strconv" "time" - morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" "github.com/prometheus/client_golang/prometheus" ) @@ -16,7 +15,7 @@ type morphClientMetrics struct { invokeDuration *prometheus.HistogramVec } -func NewMorphClientMetrics() morphmetrics.Register { +func newMorphClientMetrics() *morphClientMetrics { return &morphClientMetrics{ switchCount: metrics.NewCounter(prometheus.CounterOpts{ Namespace: namespace, diff --git a/pkg/metrics/morphcache.go b/pkg/metrics/morphcache.go index a4dbbccfc6..388cb11e8b 100644 --- a/pkg/metrics/morphcache.go +++ b/pkg/metrics/morphcache.go @@ -18,10 +18,6 @@ type morphCacheMetrics struct { var _ MorphCacheMetrics = (*morphCacheMetrics)(nil) -func NewNodeMorphCacheMetrics() MorphCacheMetrics { - return newMorphCacheMetrics(namespace) -} - func newMorphCacheMetrics(ns string) *morphCacheMetrics { return &morphCacheMetrics{ methodDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{ diff --git a/pkg/metrics/node.go b/pkg/metrics/node.go index 052defa4dc..614300aad8 100644 --- a/pkg/metrics/node.go +++ b/pkg/metrics/node.go @@ -1,6 +1,7 @@ package metrics import ( + morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" "github.com/prometheus/client_golang/prometheus" ) @@ -19,6 +20,8 @@ type NodeMetrics struct { pilorama *piloramaMetrics grpc *grpcServerMetrics policer *policerMetrics + morphClient *morphClientMetrics + morphCache *morphCacheMetrics } func NewNodeMetrics() *NodeMetrics { @@ -41,6 +44,8 @@ func NewNodeMetrics() *NodeMetrics { pilorama: newPiloramaMetrics(), grpc: newGrpcServerMetrics(), policer: newPolicerMetrics(), + morphClient: newMorphClientMetrics(), + morphCache: newMorphCacheMetrics(namespace), } } @@ -96,3 +101,11 @@ func (m *NodeMetrics) GrpcServerMetrics() GrpcServerMetrics { func (m *NodeMetrics) PolicerMetrics() PolicerMetrics { return m.policer } + +func (m *NodeMetrics) MorphClientMetrics() morphmetrics.Register { + return m.morphClient +} + +func (m *NodeMetrics) MorphCacheMetrics() MorphCacheMetrics { + return m.morphCache +} diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index fcac093214..cd42977676 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -82,7 +82,7 @@ func NewLogger(prm *Prm) (*Logger, error) { lvl := zap.NewAtomicLevelAt(prm.level) - m := newLogMetrics(prm.MetricsNamespace) + m := NewLogMetrics(prm.MetricsNamespace) c := zap.NewProductionConfig() c.Level = lvl diff --git a/pkg/util/logger/metrics.go b/pkg/util/logger/metrics.go index 7085834734..1fa0669a2f 100644 --- a/pkg/util/logger/metrics.go +++ b/pkg/util/logger/metrics.go @@ -14,12 +14,12 @@ const ( logDroppedLabel = "dropped" ) -type logMetrics struct { +type LogMetrics struct { logCount *prometheus.CounterVec } -func newLogMetrics(namespace string) *logMetrics { - return &logMetrics{ +func NewLogMetrics(namespace string) *LogMetrics { + return &LogMetrics{ logCount: metrics.NewCounterVec(prometheus.CounterOpts{ Namespace: namespace, Subsystem: logSubsystem, @@ -29,7 +29,7 @@ func newLogMetrics(namespace string) *logMetrics { } } -func (m *logMetrics) Inc(level zapcore.Level, dropped bool) { +func (m *LogMetrics) Inc(level zapcore.Level, dropped bool) { m.logCount.With(prometheus.Labels{ logLevelLabel: level.String(), logDroppedLabel: strconv.FormatBool(dropped), diff --git a/scripts/export-metrics/main.go b/scripts/export-metrics/main.go index f29eca37c5..45b1552605 100644 --- a/scripts/export-metrics/main.go +++ b/scripts/export-metrics/main.go @@ -7,6 +7,7 @@ import ( "os" local_metrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" ) @@ -27,9 +28,11 @@ func main() { switch { case *node != "": _ = local_metrics.NewNodeMetrics() + _ = logger.NewLogMetrics("frostfs_node") filename = *node case *ir != "": _ = local_metrics.NewInnerRingMetrics() + _ = logger.NewLogMetrics("frostfs_ir") filename = *ir default: From bf082348d43819df0a0a7239ae2825e000483fe6 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 5 Oct 2023 18:00:16 +0300 Subject: [PATCH 0071/1413] [#680] metrics: Add step `export-metrics` in Makefile Signed-off-by: Anton Nikiforov --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 604115469c..7fa4e43170 100755 --- a/Makefile +++ b/Makefile @@ -70,6 +70,12 @@ dep: CGO_ENABLED=0 \ go mod tidy -v && echo OK +# Build export-metrics +export-metrics: dep + @printf "⇒ Build export-metrics\n" + CGO_ENABLED=0 \ + go build -v -trimpath -o bin/export-metrics ./scripts/export-metrics + # Regenerate proto files: protoc: @GOPRIVATE=github.com/TrueCloudLab go mod vendor From 3a997d120767eef9636e11b878b805d0d19ffc68 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Sun, 8 Oct 2023 12:32:00 +0300 Subject: [PATCH 0072/1413] [#680] metrics: Initialize log metrics together with services Signed-off-by: Anton Nikiforov --- cmd/frostfs-ir/main.go | 8 +++++--- cmd/frostfs-node/config.go | 37 ++++++++++++++++------------------ pkg/innerring/innerring.go | 5 +++-- pkg/metrics/innerring.go | 7 +++++++ pkg/metrics/node.go | 7 +++++++ pkg/util/logger/logger.go | 10 ++++----- pkg/util/logger/metrics.go | 19 +++++++++++++---- scripts/export-metrics/main.go | 3 --- 8 files changed, 58 insertions(+), 38 deletions(-) diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 70199b0949..2b39f78e3f 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" + irMetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/spf13/viper" "go.uber.org/zap" @@ -61,12 +62,13 @@ func main() { cfg, err = newConfig() exitErr(err) - logPrm.MetricsNamespace = "frostfs_ir" + metrics := irMetrics.NewInnerRingMetrics() + err = logPrm.SetLevelString( cfg.GetString("logger.level"), ) exitErr(err) - + logPrm.SamplingHook = metrics.LogMetrics().GetSamplingHook() log, err = logger.NewLogger(logPrm) exitErr(err) @@ -78,7 +80,7 @@ func main() { metricsCmp = newMetricsComponent() metricsCmp.init() - innerRing, err = innerring.New(ctx, log, cfg, intErr) + innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics) exitErr(err) pprofCmp.start() diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 60e567c5a1..b35200d271 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -554,22 +554,21 @@ func initCfg(appCfg *config.Config) *cfg { key := nodeconfig.Key(appCfg) + relayOnly := nodeconfig.Relay(appCfg) + + netState := newNetworkState() + netState.metrics = c.metricsCollector + + c.shared = initShared(appCfg, key, netState, relayOnly) + logPrm, err := c.loggerPrm() fatalOnErr(err) - - logPrm.MetricsNamespace = "frostfs_node" - + logPrm.SamplingHook = c.metricsCollector.LogMetrics().GetSamplingHook() log, err := logger.NewLogger(logPrm) fatalOnErr(err) c.internals = initInternals(appCfg, log) - relayOnly := nodeconfig.Relay(appCfg) - - netState := newNetworkState() - - c.shared = initShared(appCfg, key, netState, relayOnly) - c.cfgAccounting = cfgAccounting{ scriptHash: contractsconfig.Balance(appCfg), } @@ -586,9 +585,6 @@ func initCfg(appCfg *config.Config) *cfg { user.IDFromKey(&c.ownerIDFromKey, key.PrivateKey.PublicKey) - c.metricsCollector = metrics.NewNodeMetrics() - netState.metrics = c.metricsCollector - c.onShutdown(c.clientCache.CloseAll) // clean up connections c.onShutdown(c.bgClientCache.CloseAll) // clean up connections c.onShutdown(c.putClientCache.CloseAll) // clean up connections @@ -630,14 +626,15 @@ func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkSt } return shared{ - key: key, - binPublicKey: key.PublicKey().Bytes(), - localAddr: netAddr, - respSvc: response.NewService(netState), - clientCache: cache.NewSDKClientCache(cacheOpts), - bgClientCache: cache.NewSDKClientCache(cacheOpts), - putClientCache: cache.NewSDKClientCache(cacheOpts), - persistate: persistate, + key: key, + binPublicKey: key.PublicKey().Bytes(), + localAddr: netAddr, + respSvc: response.NewService(netState), + clientCache: cache.NewSDKClientCache(cacheOpts), + bgClientCache: cache.NewSDKClientCache(cacheOpts), + putClientCache: cache.NewSDKClientCache(cacheOpts), + persistate: persistate, + metricsCollector: metrics.NewNodeMetrics(), } } diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 1567e40d3d..6f2463c74e 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -325,11 +325,12 @@ func (s *Server) registerStarter(f func() error) { } // New creates instance of inner ring sever structure. -func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error) (*Server, error) { +func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error, + metrics *metrics.InnerRingServiceMetrics) (*Server, error) { var err error server := &Server{ log: log, - irMetrics: metrics.NewInnerRingMetrics(), + irMetrics: metrics, } server.setHealthStatus(control.HealthStatus_HEALTH_STATUS_UNDEFINED) diff --git a/pkg/metrics/innerring.go b/pkg/metrics/innerring.go index d93b3c4329..3e438a01be 100644 --- a/pkg/metrics/innerring.go +++ b/pkg/metrics/innerring.go @@ -4,6 +4,7 @@ import ( "strconv" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" "github.com/prometheus/client_golang/prometheus" ) @@ -14,6 +15,7 @@ type InnerRingServiceMetrics struct { health prometheus.Gauge eventDuration *prometheus.HistogramVec morphCacheMetrics *morphCacheMetrics + logMetrics logger.LogMetrics } // NewInnerRingMetrics returns new instance of metrics collectors for inner ring. @@ -44,6 +46,7 @@ func NewInnerRingMetrics() *InnerRingServiceMetrics { health: health, eventDuration: eventDuration, morphCacheMetrics: newMorphCacheMetrics(innerRingNamespace), + logMetrics: logger.NewLogMetrics(innerRingNamespace), } } @@ -67,3 +70,7 @@ func (m *InnerRingServiceMetrics) AddEvent(d time.Duration, typ string, success func (m *InnerRingServiceMetrics) MorphCacheMetrics() MorphCacheMetrics { return m.morphCacheMetrics } + +func (m *InnerRingServiceMetrics) LogMetrics() logger.LogMetrics { + return m.logMetrics +} diff --git a/pkg/metrics/node.go b/pkg/metrics/node.go index 614300aad8..0dd86d90ec 100644 --- a/pkg/metrics/node.go +++ b/pkg/metrics/node.go @@ -2,6 +2,7 @@ package metrics import ( morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" "github.com/prometheus/client_golang/prometheus" ) @@ -22,6 +23,7 @@ type NodeMetrics struct { policer *policerMetrics morphClient *morphClientMetrics morphCache *morphCacheMetrics + log logger.LogMetrics } func NewNodeMetrics() *NodeMetrics { @@ -46,6 +48,7 @@ func NewNodeMetrics() *NodeMetrics { policer: newPolicerMetrics(), morphClient: newMorphClientMetrics(), morphCache: newMorphCacheMetrics(namespace), + log: logger.NewLogMetrics(namespace), } } @@ -109,3 +112,7 @@ func (m *NodeMetrics) MorphClientMetrics() morphmetrics.Register { func (m *NodeMetrics) MorphCacheMetrics() MorphCacheMetrics { return m.morphCache } + +func (m *NodeMetrics) LogMetrics() logger.LogMetrics { + return m.log +} diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index cd42977676..f9a5fe38f4 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -31,8 +31,8 @@ type Prm struct { // support runtime rereading level zapcore.Level - // MetricsNamespace is the namespace string used for log counter metrics - MetricsNamespace string + // SamplingHook hook for the zap.Logger + SamplingHook func(e zapcore.Entry, sd zapcore.SamplingDecision) // do not support runtime rereading } @@ -82,14 +82,12 @@ func NewLogger(prm *Prm) (*Logger, error) { lvl := zap.NewAtomicLevelAt(prm.level) - m := NewLogMetrics(prm.MetricsNamespace) - c := zap.NewProductionConfig() c.Level = lvl c.Encoding = "console" c.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder - c.Sampling.Hook = func(e zapcore.Entry, sd zapcore.SamplingDecision) { - m.Inc(e.Level, sd == zapcore.LogDropped) + if prm.SamplingHook != nil { + c.Sampling.Hook = prm.SamplingHook } lZap, err := c.Build( diff --git a/pkg/util/logger/metrics.go b/pkg/util/logger/metrics.go index 1fa0669a2f..7e62e6383e 100644 --- a/pkg/util/logger/metrics.go +++ b/pkg/util/logger/metrics.go @@ -14,12 +14,17 @@ const ( logDroppedLabel = "dropped" ) -type LogMetrics struct { +type LogMetrics interface { + Inc(level zapcore.Level, dropped bool) + GetSamplingHook() func(e zapcore.Entry, sd zapcore.SamplingDecision) +} + +type logMetrics struct { logCount *prometheus.CounterVec } -func NewLogMetrics(namespace string) *LogMetrics { - return &LogMetrics{ +func NewLogMetrics(namespace string) LogMetrics { + return &logMetrics{ logCount: metrics.NewCounterVec(prometheus.CounterOpts{ Namespace: namespace, Subsystem: logSubsystem, @@ -29,9 +34,15 @@ func NewLogMetrics(namespace string) *LogMetrics { } } -func (m *LogMetrics) Inc(level zapcore.Level, dropped bool) { +func (m *logMetrics) Inc(level zapcore.Level, dropped bool) { m.logCount.With(prometheus.Labels{ logLevelLabel: level.String(), logDroppedLabel: strconv.FormatBool(dropped), }).Inc() } + +func (m *logMetrics) GetSamplingHook() func(zapcore.Entry, zapcore.SamplingDecision) { + return func(e zapcore.Entry, sd zapcore.SamplingDecision) { + m.Inc(e.Level, sd == zapcore.LogDropped) + } +} diff --git a/scripts/export-metrics/main.go b/scripts/export-metrics/main.go index 45b1552605..f29eca37c5 100644 --- a/scripts/export-metrics/main.go +++ b/scripts/export-metrics/main.go @@ -7,7 +7,6 @@ import ( "os" local_metrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" ) @@ -28,11 +27,9 @@ func main() { switch { case *node != "": _ = local_metrics.NewNodeMetrics() - _ = logger.NewLogMetrics("frostfs_node") filename = *node case *ir != "": _ = local_metrics.NewInnerRingMetrics() - _ = logger.NewLogMetrics("frostfs_ir") filename = *ir default: From d5c10612f4e679fe8d5d8edcc61ba7c6666103e4 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 12 Oct 2023 09:31:36 +0300 Subject: [PATCH 0073/1413] [#735] policer: Register metrics Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/object.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 34847e36f7..82ddf897f4 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -260,6 +260,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl }), policer.WithMaxCapacity(c.cfgObject.pool.replicatorPoolSize), policer.WithPool(c.cfgObject.pool.replication), + policer.WithMetrics(c.metricsCollector.PolicerMetrics()), ) c.workers = append(c.workers, worker{ From 7e0c5a55de8e14ee9bdf4484d186db87923383b8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 13 Oct 2023 13:50:25 +0300 Subject: [PATCH 0074/1413] [#734] writecache: Fix flush Now UpdateStorageID doesn't return error in case of logical error. If object is in graveyard or GC market, it is still required to update storage ID. Signed-off-by: Dmitrii Stepanov --- .../metabase/storage_id.go | 5 ++++- .../metabase/storage_id_test.go | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/storage_id.go b/pkg/local_object_storage/metabase/storage_id.go index 6ba5a60cb3..7e43e30ebd 100644 --- a/pkg/local_object_storage/metabase/storage_id.go +++ b/pkg/local_object_storage/metabase/storage_id.go @@ -5,6 +5,7 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/nspcc-dev/neo-go/pkg/util/slice" @@ -107,7 +108,9 @@ func (db *DB) UpdateStorageID(prm UpdateStorageIDPrm) (res UpdateStorageIDRes, e err = db.boltDB.Batch(func(tx *bbolt.Tx) error { exists, err := db.exists(tx, prm.addr, currEpoch) - if err == nil && exists || errors.Is(err, ErrObjectIsExpired) { + if err == nil && exists { + err = updateStorageID(tx, prm.addr, prm.id) + } else if errors.As(err, new(logicerr.Logical)) { err = updateStorageID(tx, prm.addr, prm.id) } diff --git a/pkg/local_object_storage/metabase/storage_id_test.go b/pkg/local_object_storage/metabase/storage_id_test.go index b3652a6808..7278eec579 100644 --- a/pkg/local_object_storage/metabase/storage_id_test.go +++ b/pkg/local_object_storage/metabase/storage_id_test.go @@ -18,6 +18,7 @@ func TestDB_StorageID(t *testing.T) { raw1 := testutil.GenerateObject() raw2 := testutil.GenerateObject() + deleted := testutil.GenerateObject() storageID := []byte{1, 2, 3, 4} @@ -34,6 +35,15 @@ func TestDB_StorageID(t *testing.T) { err = putBig(db, raw2) require.NoError(t, err) + // put object with storageID and delete it + err = metaPut(db, deleted, storageID) + require.NoError(t, err) + + cnrID, ok := deleted.ContainerID() + require.True(t, ok) + ts := testutil.GenerateObjectWithCID(cnrID) + require.NoError(t, metaInhume(db, object.AddressOf(deleted), object.AddressOf(ts))) + // check StorageID for object without storageID fetchedStorageID, err = metaStorageID(db, object.AddressOf(raw2)) require.NoError(t, err) @@ -44,12 +54,23 @@ func TestDB_StorageID(t *testing.T) { require.NoError(t, err) require.Equal(t, storageID, fetchedStorageID) + // check StorageID for deleted object with storageID + fetchedStorageID, err = metaStorageID(db, object.AddressOf(deleted)) + require.NoError(t, err) + require.Equal(t, storageID, fetchedStorageID) + t.Run("update", func(t *testing.T) { + storageID := []byte{1, 2, 3, 4, 5} require.NoError(t, metaUpdateStorageID(db, object.AddressOf(raw2), storageID)) + require.NoError(t, metaUpdateStorageID(db, object.AddressOf(deleted), storageID)) fetchedStorageID, err = metaStorageID(db, object.AddressOf(raw2)) require.NoError(t, err) require.Equal(t, storageID, fetchedStorageID) + + fetchedStorageID, err = metaStorageID(db, object.AddressOf(deleted)) + require.NoError(t, err) + require.Equal(t, storageID, fetchedStorageID) }) } From f26233b47a93750d52903e5141d4c145e9cf3787 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 13 Oct 2023 14:01:14 +0300 Subject: [PATCH 0075/1413] [#734] metabase: Include UpdateStorageID in metrics and traces Signed-off-by: Dmitrii Stepanov --- .../metabase/storage_id.go | 20 +++++++++++++++++-- .../metabase/storage_id_test.go | 2 +- .../writecache/benchmark/writecache_test.go | 2 +- .../writecache/writecache.go | 2 +- .../writecache/writecachebadger/flush.go | 2 +- .../writecache/writecachebbolt/flush.go | 2 +- 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/metabase/storage_id.go b/pkg/local_object_storage/metabase/storage_id.go index 7e43e30ebd..0a64da856e 100644 --- a/pkg/local_object_storage/metabase/storage_id.go +++ b/pkg/local_object_storage/metabase/storage_id.go @@ -3,6 +3,7 @@ package meta import ( "context" "errors" + "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" @@ -94,7 +95,22 @@ func (p *UpdateStorageIDPrm) SetStorageID(id []byte) { } // UpdateStorageID updates storage descriptor for objects from the blobstor. -func (db *DB) UpdateStorageID(prm UpdateStorageIDPrm) (res UpdateStorageIDRes, err error) { +func (db *DB) UpdateStorageID(ctx context.Context, prm UpdateStorageIDPrm) (res UpdateStorageIDRes, err error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("UpdateStorageID", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "metabase.UpdateStorageID", + trace.WithAttributes( + attribute.String("address", prm.addr.EncodeToString()), + attribute.String("storage_id", string(prm.id)), + )) + defer span.End() + db.modeMtx.RLock() defer db.modeMtx.RUnlock() @@ -116,6 +132,6 @@ func (db *DB) UpdateStorageID(prm UpdateStorageIDPrm) (res UpdateStorageIDRes, e return err }) - + success = err == nil return res, metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/metabase/storage_id_test.go b/pkg/local_object_storage/metabase/storage_id_test.go index 7278eec579..63dbc2f3f3 100644 --- a/pkg/local_object_storage/metabase/storage_id_test.go +++ b/pkg/local_object_storage/metabase/storage_id_test.go @@ -79,7 +79,7 @@ func metaUpdateStorageID(db *meta.DB, addr oid.Address, id []byte) error { sidPrm.SetAddress(addr) sidPrm.SetStorageID(id) - _, err := db.UpdateStorageID(sidPrm) + _, err := db.UpdateStorageID(context.Background(), sidPrm) return err } diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index 16c6d73b2e..ea4bf0d33a 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -91,7 +91,7 @@ func benchmarkPutPrepare(b *testing.B, cache writecache.Cache) { type testMetabase struct{} -func (testMetabase) UpdateStorageID(meta.UpdateStorageIDPrm) (meta.UpdateStorageIDRes, error) { +func (testMetabase) UpdateStorageID(context.Context, meta.UpdateStorageIDPrm) (meta.UpdateStorageIDRes, error) { return meta.UpdateStorageIDRes{}, nil } diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index c2fdc100f8..3d3501969e 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -51,7 +51,7 @@ type MainStorage interface { // Metabase is the interface of the metabase used by Cache implementations. type Metabase interface { - UpdateStorageID(meta.UpdateStorageIDPrm) (meta.UpdateStorageIDRes, error) + UpdateStorageID(context.Context, meta.UpdateStorageIDPrm) (meta.UpdateStorageIDRes, error) } var ( diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush.go b/pkg/local_object_storage/writecache/writecachebadger/flush.go index 3f2bdb043f..e0333eff73 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush.go @@ -226,7 +226,7 @@ func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []b updPrm.SetAddress(addr) updPrm.SetStorageID(res.StorageID) - _, err = c.metabase.UpdateStorageID(updPrm) + _, err = c.metabase.UpdateStorageID(ctx, updPrm) if err != nil { c.reportFlushError(logs.FrostFSNodeCantUpdateObjectStorageID, addr.EncodeToString(), err) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush.go b/pkg/local_object_storage/writecache/writecachebbolt/flush.go index 89b26cd64f..fd322e9fad 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush.go @@ -278,7 +278,7 @@ func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []b updPrm.SetAddress(addr) updPrm.SetStorageID(res.StorageID) - _, err = c.metabase.UpdateStorageID(updPrm) + _, err = c.metabase.UpdateStorageID(ctx, updPrm) if err != nil { c.reportFlushError(logs.FSTreeCantUpdateID, addr.EncodeToString(), err) From f2437f7ae962bae537666bc0914bc9db9a5ddb75 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 13 Oct 2023 16:28:04 +0300 Subject: [PATCH 0076/1413] [#734] shard: Fix Delete method Due to the flushing data from the writecache to the storage and simultaneous deletion, a partial deletion situation is possible. So as a solution, deletion is allowed only when the object is in storage, because object will be deleted from writecache by flush goroutine. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/delete.go | 37 ++++++++----------- pkg/local_object_storage/shard/delete_test.go | 34 +++++++++++------ pkg/local_object_storage/shard/gc.go | 2 +- 3 files changed, 39 insertions(+), 34 deletions(-) diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index ea481300b8..e24bd85419 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -2,15 +2,12 @@ package shard import ( "context" - "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -34,8 +31,7 @@ func (p *DeletePrm) SetAddresses(addr ...oid.Address) { p.addr = append(p.addr, addr...) } -// Delete removes data from the shard's writeCache, metaBase and -// blobStor. +// Delete removes data from the shard's metaBase and// blobStor. func (s *Shard) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.Delete", trace.WithAttributes( @@ -47,10 +43,10 @@ func (s *Shard) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { s.m.RLock() defer s.m.RUnlock() - return s.delete(ctx, prm) + return s.delete(ctx, prm, false) } -func (s *Shard) delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { +func (s *Shard) delete(ctx context.Context, prm DeletePrm, skipFailed bool) (DeleteRes, error) { if s.info.Mode.ReadOnly() { return DeleteRes{}, ErrReadOnlyMode } else if s.info.Mode.NoMetabase() { @@ -65,12 +61,18 @@ func (s *Shard) delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { default: } - s.deleteObjectFromWriteCacheSafe(ctx, addr) - - s.deleteFromBlobstorSafe(ctx, addr) + if err := s.deleteFromBlobstor(ctx, addr); err != nil { + if skipFailed { + continue + } + return result, err + } if err := s.deleteFromMetabase(ctx, addr); err != nil { - return result, err // stop on metabase error ? + if skipFailed { + continue + } + return result, err } result.deleted++ } @@ -78,16 +80,7 @@ func (s *Shard) delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { return result, nil } -func (s *Shard) deleteObjectFromWriteCacheSafe(ctx context.Context, addr oid.Address) { - if s.hasWriteCache() { - err := s.writeCache.Delete(ctx, addr) - if err != nil && !client.IsErrObjectNotFound(err) && !errors.Is(err, writecache.ErrReadOnly) { - s.log.Warn(logs.ShardCantDeleteObjectFromWriteCache, zap.Error(err)) - } - } -} - -func (s *Shard) deleteFromBlobstorSafe(ctx context.Context, addr oid.Address) { +func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error { var sPrm meta.StorageIDPrm sPrm.SetAddress(addr) @@ -97,6 +90,7 @@ func (s *Shard) deleteFromBlobstorSafe(ctx context.Context, addr oid.Address) { zap.Stringer("object", addr), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + return err } storageID := res.StorageID() @@ -111,6 +105,7 @@ func (s *Shard) deleteFromBlobstorSafe(ctx context.Context, addr oid.Address) { zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } + return err } func (s *Shard) deleteFromMetabase(ctx context.Context, addr oid.Address) error { diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index 3421ac9e00..910528f847 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -52,13 +52,18 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { _, err = testGet(t, sh, getPrm, hasWriteCache) require.NoError(t, err) - _, err = sh.Delete(context.TODO(), delPrm) - require.NoError(t, err) + if hasWriteCache { + require.Eventually(t, func() bool { + _, err = sh.Delete(context.Background(), delPrm) + return err == nil + }, 30*time.Second, 100*time.Millisecond) + } else { + _, err = sh.Delete(context.Background(), delPrm) + require.NoError(t, err) + } - require.Eventually(t, func() bool { - _, err = sh.Get(context.Background(), getPrm) - return client.IsErrObjectNotFound(err) - }, time.Second, 50*time.Millisecond) + _, err = sh.Get(context.Background(), getPrm) + require.True(t, client.IsErrObjectNotFound(err)) }) t.Run("small object", func(t *testing.T) { @@ -78,12 +83,17 @@ func testShardDelete(t *testing.T, hasWriteCache bool) { _, err = sh.Get(context.Background(), getPrm) require.NoError(t, err) - _, err = sh.Delete(context.Background(), delPrm) - require.NoError(t, err) + if hasWriteCache { + require.Eventually(t, func() bool { + _, err = sh.Delete(context.Background(), delPrm) + return err == nil + }, 10*time.Second, 100*time.Millisecond) + } else { + _, err = sh.Delete(context.Background(), delPrm) + require.NoError(t, err) + } - require.Eventually(t, func() bool { - _, err = sh.Get(context.Background(), getPrm) - return client.IsErrObjectNotFound(err) - }, time.Second, 50*time.Millisecond) + _, err = sh.Get(context.Background(), getPrm) + require.True(t, client.IsErrObjectNotFound(err)) }) } diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 13ab39ae00..0ce99b475f 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -297,7 +297,7 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { deletePrm.SetAddresses(buf...) // delete accumulated objects - res, err := s.delete(ctx, deletePrm) + res, err := s.delete(ctx, deletePrm, true) result.deleted = res.deleted result.failedToDelete = uint64(len(buf)) - res.deleted From 189dbb01be21608f2596a2e21d896232eb8c32bb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 16 Oct 2023 18:15:04 +0300 Subject: [PATCH 0077/1413] [#733] frostfs-cli: Add `control ir remove-container` Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/ir.go | 2 + .../modules/control/ir_remove_container.go | 94 ++++ pkg/innerring/initialization.go | 3 +- pkg/innerring/innerring.go | 22 +- pkg/morph/client/container/delete.go | 2 +- pkg/morph/client/static.go | 5 + pkg/services/control/ir/rpc.go | 15 +- pkg/services/control/ir/server/calls.go | 64 +++ pkg/services/control/ir/server/server.go | 16 +- pkg/services/control/ir/service.pb.go | 446 ++++++++++++++---- pkg/services/control/ir/service.proto | 19 + pkg/services/control/ir/service_frostfs.pb.go | 165 +++++++ pkg/services/control/ir/service_grpc.pb.go | 61 ++- pkg/services/control/ir/types.pb.go | 2 +- 14 files changed, 806 insertions(+), 110 deletions(-) create mode 100644 cmd/frostfs-cli/modules/control/ir_remove_container.go diff --git a/cmd/frostfs-cli/modules/control/ir.go b/cmd/frostfs-cli/modules/control/ir.go index 396d5d0a5e..ac1371db73 100644 --- a/cmd/frostfs-cli/modules/control/ir.go +++ b/cmd/frostfs-cli/modules/control/ir.go @@ -12,8 +12,10 @@ func initControlIRCmd() { irCmd.AddCommand(tickEpochCmd) irCmd.AddCommand(removeNodeCmd) irCmd.AddCommand(irHealthCheckCmd) + irCmd.AddCommand(removeContainerCmd) initControlIRTickEpochCmd() initControlIRRemoveNodeCmd() initControlIRHealthCheckCmd() + initControlIRRemoveContainerCmd() } diff --git a/cmd/frostfs-cli/modules/control/ir_remove_container.go b/cmd/frostfs-cli/modules/control/ir_remove_container.go new file mode 100644 index 0000000000..43173bcaa1 --- /dev/null +++ b/cmd/frostfs-cli/modules/control/ir_remove_container.go @@ -0,0 +1,94 @@ +package control + +import ( + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" + ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/spf13/cobra" +) + +const ( + ownerFlag = "owner" +) + +var removeContainerCmd = &cobra.Command{ + Use: "remove-container", + Short: "Schedules a container removal", + Long: `Schedules a container removal via a notary request. +Container data will be deleted asynchronously by policer. +To check removal status "frostfs-cli container list" command can be used.`, + Run: removeContainer, +} + +func initControlIRRemoveContainerCmd() { + initControlFlags(removeContainerCmd) + + flags := removeContainerCmd.Flags() + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + flags.String(ownerFlag, "", "Container owner's wallet address.") + removeContainerCmd.MarkFlagsMutuallyExclusive(commonflags.CIDFlag, ownerFlag) +} + +func removeContainer(cmd *cobra.Command, _ []string) { + req := prepareRemoveContainerRequest(cmd) + + pk := key.Get(cmd) + c := getClient(cmd, pk) + + commonCmd.ExitOnErr(cmd, "could not sign request: %w", ircontrolsrv.SignMessage(pk, req)) + + var resp *ircontrol.RemoveContainerResponse + err := c.ExecRaw(func(client *rawclient.Client) error { + var err error + resp, err = ircontrol.RemoveContainer(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "failed to execute request: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + if len(req.GetBody().GetContainerId()) > 0 { + cmd.Println("Container scheduled to removal") + } else { + cmd.Println("User containers sheduled to removal") + } +} + +func prepareRemoveContainerRequest(cmd *cobra.Command) *ircontrol.RemoveContainerRequest { + req := &ircontrol.RemoveContainerRequest{ + Body: &ircontrol.RemoveContainerRequest_Body{}, + } + + cidStr, err := cmd.Flags().GetString(commonflags.CIDFlag) + commonCmd.ExitOnErr(cmd, "failed to get cid: ", err) + + ownerStr, err := cmd.Flags().GetString(ownerFlag) + commonCmd.ExitOnErr(cmd, "failed to get owner: ", err) + + if len(ownerStr) == 0 && len(cidStr) == 0 { + commonCmd.ExitOnErr(cmd, "invalid usage: %w", errors.New("neither owner's wallet address nor container ID are specified")) + } + + if len(ownerStr) > 0 { + var owner user.ID + commonCmd.ExitOnErr(cmd, "invalid owner ID: %w", owner.DecodeString(ownerStr)) + var ownerID refs.OwnerID + owner.WriteToV2(&ownerID) + req.Body.Owner = ownerID.StableMarshal(nil) + } + + if len(cidStr) > 0 { + var containerID cid.ID + commonCmd.ExitOnErr(cmd, "invalid container ID: %w", containerID.DecodeString(cidStr)) + req.Body.ContainerId = containerID[:] + } + return req +} diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index 84112d121d..eb1c4b2d4b 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -343,7 +343,7 @@ func (s *Server) initGRPCServer(cfg *viper.Viper) error { p.SetPrivateKey(*s.key) p.SetHealthChecker(s) - controlSvc := controlsrv.New(p, s.netmapClient, + controlSvc := controlsrv.New(p, s.netmapClient, s.containerClient, controlsrv.WithAllowedKeys(authKeys), ) @@ -389,6 +389,7 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) { if err != nil { return nil, err } + s.containerClient = result.CnrClient s.netmapClient, err = nmClient.NewFromMorph(s.morphClient, s.contracts.netmap, fee, nmClient.TryNotary(), nmClient.AsAlphabet()) if err != nil { diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 6f2463c74e..ae2ad40199 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -16,6 +16,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" balanceClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/subscriber" @@ -46,16 +47,17 @@ type ( epochTimer *timer.BlockTimer // global state - morphClient *client.Client - mainnetClient *client.Client - epochCounter atomic.Uint64 - epochDuration atomic.Uint64 - statusIndex *innerRingIndexer - precision precision.Fixed8Converter - healthStatus atomic.Int32 - balanceClient *balanceClient.Client - netmapClient *nmClient.Client - persistate *state.PersistentStorage + morphClient *client.Client + mainnetClient *client.Client + epochCounter atomic.Uint64 + epochDuration atomic.Uint64 + statusIndex *innerRingIndexer + precision precision.Fixed8Converter + healthStatus atomic.Int32 + balanceClient *balanceClient.Client + netmapClient *nmClient.Client + persistate *state.PersistentStorage + containerClient *container.Client // metrics irMetrics *metrics.InnerRingServiceMetrics diff --git a/pkg/morph/client/container/delete.go b/pkg/morph/client/container/delete.go index 5bc8fc1888..c1d346e70b 100644 --- a/pkg/morph/client/container/delete.go +++ b/pkg/morph/client/container/delete.go @@ -67,7 +67,7 @@ func (d *DeletePrm) SetKey(key []byte) { // // If TryNotary is provided, calls notary contract. func (c *Client) Delete(p DeletePrm) error { - if len(p.signature) == 0 { + if len(p.signature) == 0 && p.IsControl() { return errNilArgument } diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index 7aa17a70fe..0531eacdf7 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -115,6 +115,11 @@ func (i *InvokePrmOptional) SetControlTX(b bool) { i.controlTX = b } +// IsControl gets whether a control transaction will be used. +func (i *InvokePrmOptional) IsControl() bool { + return i.controlTX +} + // Invoke calls Invoke method of Client with static internal script hash and fee. // Supported args types are the same as in Client. // diff --git a/pkg/services/control/ir/rpc.go b/pkg/services/control/ir/rpc.go index 1b635c1494..0c9400f6ce 100644 --- a/pkg/services/control/ir/rpc.go +++ b/pkg/services/control/ir/rpc.go @@ -9,9 +9,10 @@ import ( const serviceName = "ircontrol.ControlService" const ( - rpcHealthCheck = "HealthCheck" - rpcTickEpoch = "TickEpoch" - rpcRemoveNode = "RemoveNode" + rpcHealthCheck = "HealthCheck" + rpcTickEpoch = "TickEpoch" + rpcRemoveNode = "RemoveNode" + rpcRemoveContainer = "RemoveContainer" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -40,6 +41,14 @@ func RemoveNode( return sendUnary[RemoveNodeRequest, RemoveNodeResponse](cli, rpcRemoveNode, req, opts...) } +func RemoveContainer( + cli *client.Client, + req *RemoveContainerRequest, + opts ...client.CallOption, +) (*RemoveContainerResponse, error) { + return sendUnary[RemoveContainerRequest, RemoveContainerResponse](cli, rpcRemoveContainer, req, opts...) +} + func sendUnary[I, O grpc.Message](cli *client.Client, rpcName string, req *I, opts ...client.CallOption) (*O, error) { var resp O wResp := &responseWrapper[*O]{ diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 680d1e606d..5379058401 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -5,8 +5,12 @@ import ( "context" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -99,3 +103,63 @@ func (s *Server) RemoveNode(_ context.Context, req *control.RemoveNodeRequest) ( return resp, nil } + +// RemoveContainer forces a container removal. +func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainerRequest) (*control.RemoveContainerResponse, error) { + if err := s.isValidRequest(req); err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + if len(req.Body.GetContainerId()) > 0 && len(req.Body.GetOwner()) > 0 { + return nil, status.Error(codes.InvalidArgument, "specify the owner and container at the same time is not allowed") + } + + if len(req.Body.GetContainerId()) > 0 { + var containerID cid.ID + if err := containerID.Decode(req.Body.GetContainerId()); err != nil { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to parse container ID: %s", err.Error())) + } + if err := s.removeContainer(containerID); err != nil { + return nil, err + } + } else { + var ownerID refs.OwnerID + if err := ownerID.Unmarshal(req.GetBody().GetOwner()); err != nil { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to parse ownerID: %s", err.Error())) + } + var owner user.ID + if err := owner.ReadFromV2(ownerID); err != nil { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to read owner: %s", err.Error())) + } + + cids, err := s.containerClient.ContainersOf(&owner) + if err != nil { + return nil, fmt.Errorf("failed to get owner's containers: %w", err) + } + + for _, containerID := range cids { + if err := s.removeContainer(containerID); err != nil { + return nil, err + } + } + } + + resp := &control.RemoveContainerResponse{ + Body: &control.RemoveContainerResponse_Body{}, + } + if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return resp, nil +} + +func (s *Server) removeContainer(containerID cid.ID) error { + var prm container.DeletePrm + prm.SetCID(containerID[:]) + prm.SetControlTX(true) + + if err := s.containerClient.Delete(prm); err != nil { + return fmt.Errorf("forcing container removal: %w", err) + } + return nil +} diff --git a/pkg/services/control/ir/server/server.go b/pkg/services/control/ir/server/server.go index dc00809a60..c2a4f88a69 100644 --- a/pkg/services/control/ir/server/server.go +++ b/pkg/services/control/ir/server/server.go @@ -3,6 +3,7 @@ package control import ( "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" ) @@ -12,10 +13,10 @@ import ( // To gain access to the service, any request must be // signed with a key from the white list. type Server struct { - prm Prm - netmapClient *netmap.Client - - allowedKeys [][]byte + prm Prm + netmapClient *netmap.Client + containerClient *container.Client + allowedKeys [][]byte } func panicOnPrmValue(n string, v any) { @@ -32,7 +33,7 @@ func panicOnPrmValue(n string, v any) { // Forms white list from all keys specified via // WithAllowedKeys option and a public key of // the parameterized private key. -func New(prm Prm, netmapClient *netmap.Client, opts ...Option) *Server { +func New(prm Prm, netmapClient *netmap.Client, containerClient *container.Client, opts ...Option) *Server { // verify required parameters switch { case prm.healthChecker == nil: @@ -47,8 +48,9 @@ func New(prm Prm, netmapClient *netmap.Client, opts ...Option) *Server { } return &Server{ - prm: prm, - netmapClient: netmapClient, + prm: prm, + netmapClient: netmapClient, + containerClient: containerClient, allowedKeys: append(o.allowedKeys, prm.key.PublicKey().Bytes()), } diff --git a/pkg/services/control/ir/service.pb.go b/pkg/services/control/ir/service.pb.go index bec74a3bea..56d52be4ce 100644 --- a/pkg/services/control/ir/service.pb.go +++ b/pkg/services/control/ir/service.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.12.4 +// protoc v4.24.4 // source: pkg/services/control/ir/service.proto package control @@ -358,6 +358,116 @@ func (x *RemoveNodeResponse) GetSignature() *Signature { return nil } +type RemoveContainerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *RemoveContainerRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *RemoveContainerRequest) Reset() { + *x = RemoveContainerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_ir_service_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveContainerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveContainerRequest) ProtoMessage() {} + +func (x *RemoveContainerRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_ir_service_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveContainerRequest.ProtoReflect.Descriptor instead. +func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{6} +} + +func (x *RemoveContainerRequest) GetBody() *RemoveContainerRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *RemoveContainerRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type RemoveContainerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *RemoveContainerResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *RemoveContainerResponse) Reset() { + *x = RemoveContainerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_ir_service_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveContainerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveContainerResponse) ProtoMessage() {} + +func (x *RemoveContainerResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_ir_service_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveContainerResponse.ProtoReflect.Descriptor instead. +func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{7} +} + +func (x *RemoveContainerResponse) GetBody() *RemoveContainerResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *RemoveContainerResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + // Health check request body. type HealthCheckRequest_Body struct { state protoimpl.MessageState @@ -368,7 +478,7 @@ type HealthCheckRequest_Body struct { func (x *HealthCheckRequest_Body) Reset() { *x = HealthCheckRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[6] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -381,7 +491,7 @@ func (x *HealthCheckRequest_Body) String() string { func (*HealthCheckRequest_Body) ProtoMessage() {} func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[6] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -410,7 +520,7 @@ type HealthCheckResponse_Body struct { func (x *HealthCheckResponse_Body) Reset() { *x = HealthCheckResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[7] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -423,7 +533,7 @@ func (x *HealthCheckResponse_Body) String() string { func (*HealthCheckResponse_Body) ProtoMessage() {} func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[7] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -455,7 +565,7 @@ type TickEpochRequest_Body struct { func (x *TickEpochRequest_Body) Reset() { *x = TickEpochRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[8] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -468,7 +578,7 @@ func (x *TickEpochRequest_Body) String() string { func (*TickEpochRequest_Body) ProtoMessage() {} func (x *TickEpochRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[8] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -493,7 +603,7 @@ type TickEpochResponse_Body struct { func (x *TickEpochResponse_Body) Reset() { *x = TickEpochResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[9] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -506,7 +616,7 @@ func (x *TickEpochResponse_Body) String() string { func (*TickEpochResponse_Body) ProtoMessage() {} func (x *TickEpochResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[9] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -533,7 +643,7 @@ type RemoveNodeRequest_Body struct { func (x *RemoveNodeRequest_Body) Reset() { *x = RemoveNodeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[10] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -546,7 +656,7 @@ func (x *RemoveNodeRequest_Body) String() string { func (*RemoveNodeRequest_Body) ProtoMessage() {} func (x *RemoveNodeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[10] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -578,7 +688,7 @@ type RemoveNodeResponse_Body struct { func (x *RemoveNodeResponse_Body) Reset() { *x = RemoveNodeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[11] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -591,7 +701,7 @@ func (x *RemoveNodeResponse_Body) String() string { func (*RemoveNodeResponse_Body) ProtoMessage() {} func (x *RemoveNodeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[11] + mi := &file_pkg_services_control_ir_service_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -607,6 +717,99 @@ func (*RemoveNodeResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{5, 0} } +type RemoveContainerRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + Owner []byte `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"` +} + +func (x *RemoveContainerRequest_Body) Reset() { + *x = RemoveContainerRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_ir_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveContainerRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveContainerRequest_Body) ProtoMessage() {} + +func (x *RemoveContainerRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_ir_service_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveContainerRequest_Body.ProtoReflect.Descriptor instead. +func (*RemoveContainerRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{6, 0} +} + +func (x *RemoveContainerRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *RemoveContainerRequest_Body) GetOwner() []byte { + if x != nil { + return x.Owner + } + return nil +} + +type RemoveContainerResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RemoveContainerResponse_Body) Reset() { + *x = RemoveContainerResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_ir_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveContainerResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveContainerResponse_Body) ProtoMessage() {} + +func (x *RemoveContainerResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_ir_service_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveContainerResponse_Body.ProtoReflect.Descriptor instead. +func (*RemoveContainerResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{7, 0} +} + var File_pkg_services_control_ir_service_proto protoreflect.FileDescriptor var file_pkg_services_control_ir_service_proto_rawDesc = []byte{ @@ -672,27 +875,54 @@ var file_pkg_services_control_ir_service_proto_rawDesc = []byte{ 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x32, 0xf1, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, - 0x68, 0x12, 0x1b, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, - 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, - 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, - 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x69, 0x72, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, - 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, - 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, - 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2f, 0x69, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x64, 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x69, + 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x3f, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, + 0x92, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x69, 0x72, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x32, 0xcb, 0x02, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, + 0x63, 0x68, 0x12, 0x1b, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, + 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1c, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, + 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, + 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x69, 0x72, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, + 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x2e, 0x69, 0x72, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, + 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, + 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, + 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, + 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x69, 0x72, + 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -707,48 +937,58 @@ func file_pkg_services_control_ir_service_proto_rawDescGZIP() []byte { return file_pkg_services_control_ir_service_proto_rawDescData } -var file_pkg_services_control_ir_service_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_pkg_services_control_ir_service_proto_msgTypes = make([]protoimpl.MessageInfo, 16) var file_pkg_services_control_ir_service_proto_goTypes = []interface{}{ - (*HealthCheckRequest)(nil), // 0: ircontrol.HealthCheckRequest - (*HealthCheckResponse)(nil), // 1: ircontrol.HealthCheckResponse - (*TickEpochRequest)(nil), // 2: ircontrol.TickEpochRequest - (*TickEpochResponse)(nil), // 3: ircontrol.TickEpochResponse - (*RemoveNodeRequest)(nil), // 4: ircontrol.RemoveNodeRequest - (*RemoveNodeResponse)(nil), // 5: ircontrol.RemoveNodeResponse - (*HealthCheckRequest_Body)(nil), // 6: ircontrol.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 7: ircontrol.HealthCheckResponse.Body - (*TickEpochRequest_Body)(nil), // 8: ircontrol.TickEpochRequest.Body - (*TickEpochResponse_Body)(nil), // 9: ircontrol.TickEpochResponse.Body - (*RemoveNodeRequest_Body)(nil), // 10: ircontrol.RemoveNodeRequest.Body - (*RemoveNodeResponse_Body)(nil), // 11: ircontrol.RemoveNodeResponse.Body - (*Signature)(nil), // 12: ircontrol.Signature - (HealthStatus)(0), // 13: ircontrol.HealthStatus + (*HealthCheckRequest)(nil), // 0: ircontrol.HealthCheckRequest + (*HealthCheckResponse)(nil), // 1: ircontrol.HealthCheckResponse + (*TickEpochRequest)(nil), // 2: ircontrol.TickEpochRequest + (*TickEpochResponse)(nil), // 3: ircontrol.TickEpochResponse + (*RemoveNodeRequest)(nil), // 4: ircontrol.RemoveNodeRequest + (*RemoveNodeResponse)(nil), // 5: ircontrol.RemoveNodeResponse + (*RemoveContainerRequest)(nil), // 6: ircontrol.RemoveContainerRequest + (*RemoveContainerResponse)(nil), // 7: ircontrol.RemoveContainerResponse + (*HealthCheckRequest_Body)(nil), // 8: ircontrol.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 9: ircontrol.HealthCheckResponse.Body + (*TickEpochRequest_Body)(nil), // 10: ircontrol.TickEpochRequest.Body + (*TickEpochResponse_Body)(nil), // 11: ircontrol.TickEpochResponse.Body + (*RemoveNodeRequest_Body)(nil), // 12: ircontrol.RemoveNodeRequest.Body + (*RemoveNodeResponse_Body)(nil), // 13: ircontrol.RemoveNodeResponse.Body + (*RemoveContainerRequest_Body)(nil), // 14: ircontrol.RemoveContainerRequest.Body + (*RemoveContainerResponse_Body)(nil), // 15: ircontrol.RemoveContainerResponse.Body + (*Signature)(nil), // 16: ircontrol.Signature + (HealthStatus)(0), // 17: ircontrol.HealthStatus } var file_pkg_services_control_ir_service_proto_depIdxs = []int32{ - 6, // 0: ircontrol.HealthCheckRequest.body:type_name -> ircontrol.HealthCheckRequest.Body - 12, // 1: ircontrol.HealthCheckRequest.signature:type_name -> ircontrol.Signature - 7, // 2: ircontrol.HealthCheckResponse.body:type_name -> ircontrol.HealthCheckResponse.Body - 12, // 3: ircontrol.HealthCheckResponse.signature:type_name -> ircontrol.Signature - 8, // 4: ircontrol.TickEpochRequest.body:type_name -> ircontrol.TickEpochRequest.Body - 12, // 5: ircontrol.TickEpochRequest.signature:type_name -> ircontrol.Signature - 9, // 6: ircontrol.TickEpochResponse.body:type_name -> ircontrol.TickEpochResponse.Body - 12, // 7: ircontrol.TickEpochResponse.signature:type_name -> ircontrol.Signature - 10, // 8: ircontrol.RemoveNodeRequest.body:type_name -> ircontrol.RemoveNodeRequest.Body - 12, // 9: ircontrol.RemoveNodeRequest.signature:type_name -> ircontrol.Signature - 11, // 10: ircontrol.RemoveNodeResponse.body:type_name -> ircontrol.RemoveNodeResponse.Body - 12, // 11: ircontrol.RemoveNodeResponse.signature:type_name -> ircontrol.Signature - 13, // 12: ircontrol.HealthCheckResponse.Body.health_status:type_name -> ircontrol.HealthStatus - 0, // 13: ircontrol.ControlService.HealthCheck:input_type -> ircontrol.HealthCheckRequest - 2, // 14: ircontrol.ControlService.TickEpoch:input_type -> ircontrol.TickEpochRequest - 4, // 15: ircontrol.ControlService.RemoveNode:input_type -> ircontrol.RemoveNodeRequest - 1, // 16: ircontrol.ControlService.HealthCheck:output_type -> ircontrol.HealthCheckResponse - 3, // 17: ircontrol.ControlService.TickEpoch:output_type -> ircontrol.TickEpochResponse - 5, // 18: ircontrol.ControlService.RemoveNode:output_type -> ircontrol.RemoveNodeResponse - 16, // [16:19] is the sub-list for method output_type - 13, // [13:16] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 8, // 0: ircontrol.HealthCheckRequest.body:type_name -> ircontrol.HealthCheckRequest.Body + 16, // 1: ircontrol.HealthCheckRequest.signature:type_name -> ircontrol.Signature + 9, // 2: ircontrol.HealthCheckResponse.body:type_name -> ircontrol.HealthCheckResponse.Body + 16, // 3: ircontrol.HealthCheckResponse.signature:type_name -> ircontrol.Signature + 10, // 4: ircontrol.TickEpochRequest.body:type_name -> ircontrol.TickEpochRequest.Body + 16, // 5: ircontrol.TickEpochRequest.signature:type_name -> ircontrol.Signature + 11, // 6: ircontrol.TickEpochResponse.body:type_name -> ircontrol.TickEpochResponse.Body + 16, // 7: ircontrol.TickEpochResponse.signature:type_name -> ircontrol.Signature + 12, // 8: ircontrol.RemoveNodeRequest.body:type_name -> ircontrol.RemoveNodeRequest.Body + 16, // 9: ircontrol.RemoveNodeRequest.signature:type_name -> ircontrol.Signature + 13, // 10: ircontrol.RemoveNodeResponse.body:type_name -> ircontrol.RemoveNodeResponse.Body + 16, // 11: ircontrol.RemoveNodeResponse.signature:type_name -> ircontrol.Signature + 14, // 12: ircontrol.RemoveContainerRequest.body:type_name -> ircontrol.RemoveContainerRequest.Body + 16, // 13: ircontrol.RemoveContainerRequest.signature:type_name -> ircontrol.Signature + 15, // 14: ircontrol.RemoveContainerResponse.body:type_name -> ircontrol.RemoveContainerResponse.Body + 16, // 15: ircontrol.RemoveContainerResponse.signature:type_name -> ircontrol.Signature + 17, // 16: ircontrol.HealthCheckResponse.Body.health_status:type_name -> ircontrol.HealthStatus + 0, // 17: ircontrol.ControlService.HealthCheck:input_type -> ircontrol.HealthCheckRequest + 2, // 18: ircontrol.ControlService.TickEpoch:input_type -> ircontrol.TickEpochRequest + 4, // 19: ircontrol.ControlService.RemoveNode:input_type -> ircontrol.RemoveNodeRequest + 6, // 20: ircontrol.ControlService.RemoveContainer:input_type -> ircontrol.RemoveContainerRequest + 1, // 21: ircontrol.ControlService.HealthCheck:output_type -> ircontrol.HealthCheckResponse + 3, // 22: ircontrol.ControlService.TickEpoch:output_type -> ircontrol.TickEpochResponse + 5, // 23: ircontrol.ControlService.RemoveNode:output_type -> ircontrol.RemoveNodeResponse + 7, // 24: ircontrol.ControlService.RemoveContainer:output_type -> ircontrol.RemoveContainerResponse + 21, // [21:25] is the sub-list for method output_type + 17, // [17:21] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_pkg_services_control_ir_service_proto_init() } @@ -831,7 +1071,7 @@ func file_pkg_services_control_ir_service_proto_init() { } } file_pkg_services_control_ir_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { + switch v := v.(*RemoveContainerRequest); i { case 0: return &v.state case 1: @@ -843,7 +1083,7 @@ func file_pkg_services_control_ir_service_proto_init() { } } file_pkg_services_control_ir_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { + switch v := v.(*RemoveContainerResponse); i { case 0: return &v.state case 1: @@ -855,7 +1095,7 @@ func file_pkg_services_control_ir_service_proto_init() { } } file_pkg_services_control_ir_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TickEpochRequest_Body); i { + switch v := v.(*HealthCheckRequest_Body); i { case 0: return &v.state case 1: @@ -867,7 +1107,7 @@ func file_pkg_services_control_ir_service_proto_init() { } } file_pkg_services_control_ir_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TickEpochResponse_Body); i { + switch v := v.(*HealthCheckResponse_Body); i { case 0: return &v.state case 1: @@ -879,7 +1119,7 @@ func file_pkg_services_control_ir_service_proto_init() { } } file_pkg_services_control_ir_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveNodeRequest_Body); i { + switch v := v.(*TickEpochRequest_Body); i { case 0: return &v.state case 1: @@ -891,6 +1131,30 @@ func file_pkg_services_control_ir_service_proto_init() { } } file_pkg_services_control_ir_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TickEpochResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_ir_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveNodeRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_ir_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemoveNodeResponse_Body); i { case 0: return &v.state @@ -902,6 +1166,30 @@ func file_pkg_services_control_ir_service_proto_init() { return nil } } + file_pkg_services_control_ir_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveContainerRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_ir_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveContainerResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -909,7 +1197,7 @@ func file_pkg_services_control_ir_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_ir_service_proto_rawDesc, NumEnums: 0, - NumMessages: 12, + NumMessages: 16, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/services/control/ir/service.proto b/pkg/services/control/ir/service.proto index d647db0df8..6c85ba4b9a 100644 --- a/pkg/services/control/ir/service.proto +++ b/pkg/services/control/ir/service.proto @@ -14,6 +14,8 @@ service ControlService { rpc TickEpoch (TickEpochRequest) returns (TickEpochResponse); // Forces a node removal to be signaled by the IR node with high probability. rpc RemoveNode (RemoveNodeRequest) returns (RemoveNodeResponse); + // Forces a container removal to be signaled by the IR node with high probability. + rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse); } // Health check request. @@ -75,3 +77,20 @@ message RemoveNodeResponse { Body body = 1; Signature signature = 2; } + +message RemoveContainerRequest { + message Body{ + bytes container_id = 1; + bytes owner = 2; + } + + Body body = 1; + Signature signature = 2; +} + +message RemoveContainerResponse { + message Body{} + + Body body = 1; + Signature signature = 2; +} \ No newline at end of file diff --git a/pkg/services/control/ir/service_frostfs.pb.go b/pkg/services/control/ir/service_frostfs.pb.go index f39d3b0431..131ec78dac 100644 --- a/pkg/services/control/ir/service_frostfs.pb.go +++ b/pkg/services/control/ir/service_frostfs.pb.go @@ -483,3 +483,168 @@ func (x *RemoveNodeResponse) ReadSignedData(buf []byte) ([]byte, error) { func (x *RemoveNodeResponse) SetSignature(sig *Signature) { x.Signature = sig } + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveContainerRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BytesSize(1, x.ContainerId) + size += proto.BytesSize(2, x.Owner) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveContainerRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + offset += proto.BytesMarshal(2, buf[offset:], x.Owner) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveContainerRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveContainerRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *RemoveContainerRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *RemoveContainerRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *RemoveContainerRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveContainerResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveContainerResponse_Body) StableMarshal(buf []byte) []byte { + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveContainerResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveContainerResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *RemoveContainerResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *RemoveContainerResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *RemoveContainerResponse) SetSignature(sig *Signature) { + x.Signature = sig +} diff --git a/pkg/services/control/ir/service_grpc.pb.go b/pkg/services/control/ir/service_grpc.pb.go index 6ba214da09..004c82446c 100644 --- a/pkg/services/control/ir/service_grpc.pb.go +++ b/pkg/services/control/ir/service_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.12.4 +// - protoc-gen-go-grpc v1.3.0 +// - protoc v4.24.4 // source: pkg/services/control/ir/service.proto package control @@ -18,6 +18,13 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 +const ( + ControlService_HealthCheck_FullMethodName = "/ircontrol.ControlService/HealthCheck" + ControlService_TickEpoch_FullMethodName = "/ircontrol.ControlService/TickEpoch" + ControlService_RemoveNode_FullMethodName = "/ircontrol.ControlService/RemoveNode" + ControlService_RemoveContainer_FullMethodName = "/ircontrol.ControlService/RemoveContainer" +) + // ControlServiceClient is the client API for ControlService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -28,6 +35,8 @@ type ControlServiceClient interface { TickEpoch(ctx context.Context, in *TickEpochRequest, opts ...grpc.CallOption) (*TickEpochResponse, error) // Forces a node removal to be signaled by the IR node with high probability. RemoveNode(ctx context.Context, in *RemoveNodeRequest, opts ...grpc.CallOption) (*RemoveNodeResponse, error) + // Forces a container removal to be signaled by the IR node with high probability. + RemoveContainer(ctx context.Context, in *RemoveContainerRequest, opts ...grpc.CallOption) (*RemoveContainerResponse, error) } type controlServiceClient struct { @@ -40,7 +49,7 @@ func NewControlServiceClient(cc grpc.ClientConnInterface) ControlServiceClient { func (c *controlServiceClient) HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) { out := new(HealthCheckResponse) - err := c.cc.Invoke(ctx, "/ircontrol.ControlService/HealthCheck", in, out, opts...) + err := c.cc.Invoke(ctx, ControlService_HealthCheck_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -49,7 +58,7 @@ func (c *controlServiceClient) HealthCheck(ctx context.Context, in *HealthCheckR func (c *controlServiceClient) TickEpoch(ctx context.Context, in *TickEpochRequest, opts ...grpc.CallOption) (*TickEpochResponse, error) { out := new(TickEpochResponse) - err := c.cc.Invoke(ctx, "/ircontrol.ControlService/TickEpoch", in, out, opts...) + err := c.cc.Invoke(ctx, ControlService_TickEpoch_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -58,7 +67,16 @@ func (c *controlServiceClient) TickEpoch(ctx context.Context, in *TickEpochReque func (c *controlServiceClient) RemoveNode(ctx context.Context, in *RemoveNodeRequest, opts ...grpc.CallOption) (*RemoveNodeResponse, error) { out := new(RemoveNodeResponse) - err := c.cc.Invoke(ctx, "/ircontrol.ControlService/RemoveNode", in, out, opts...) + err := c.cc.Invoke(ctx, ControlService_RemoveNode_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlServiceClient) RemoveContainer(ctx context.Context, in *RemoveContainerRequest, opts ...grpc.CallOption) (*RemoveContainerResponse, error) { + out := new(RemoveContainerResponse) + err := c.cc.Invoke(ctx, ControlService_RemoveContainer_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -75,6 +93,8 @@ type ControlServiceServer interface { TickEpoch(context.Context, *TickEpochRequest) (*TickEpochResponse, error) // Forces a node removal to be signaled by the IR node with high probability. RemoveNode(context.Context, *RemoveNodeRequest) (*RemoveNodeResponse, error) + // Forces a container removal to be signaled by the IR node with high probability. + RemoveContainer(context.Context, *RemoveContainerRequest) (*RemoveContainerResponse, error) } // UnimplementedControlServiceServer should be embedded to have forward compatible implementations. @@ -90,6 +110,9 @@ func (UnimplementedControlServiceServer) TickEpoch(context.Context, *TickEpochRe func (UnimplementedControlServiceServer) RemoveNode(context.Context, *RemoveNodeRequest) (*RemoveNodeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveNode not implemented") } +func (UnimplementedControlServiceServer) RemoveContainer(context.Context, *RemoveContainerRequest) (*RemoveContainerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveContainer not implemented") +} // UnsafeControlServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ControlServiceServer will @@ -112,7 +135,7 @@ func _ControlService_HealthCheck_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/ircontrol.ControlService/HealthCheck", + FullMethod: ControlService_HealthCheck_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).HealthCheck(ctx, req.(*HealthCheckRequest)) @@ -130,7 +153,7 @@ func _ControlService_TickEpoch_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/ircontrol.ControlService/TickEpoch", + FullMethod: ControlService_TickEpoch_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).TickEpoch(ctx, req.(*TickEpochRequest)) @@ -148,7 +171,7 @@ func _ControlService_RemoveNode_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/ircontrol.ControlService/RemoveNode", + FullMethod: ControlService_RemoveNode_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).RemoveNode(ctx, req.(*RemoveNodeRequest)) @@ -156,6 +179,24 @@ func _ControlService_RemoveNode_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _ControlService_RemoveContainer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveContainerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).RemoveContainer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_RemoveContainer_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).RemoveContainer(ctx, req.(*RemoveContainerRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ControlService_ServiceDesc is the grpc.ServiceDesc for ControlService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -175,6 +216,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "RemoveNode", Handler: _ControlService_RemoveNode_Handler, }, + { + MethodName: "RemoveContainer", + Handler: _ControlService_RemoveContainer_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pkg/services/control/ir/service.proto", diff --git a/pkg/services/control/ir/types.pb.go b/pkg/services/control/ir/types.pb.go index 8107b917e8..0ff8f45e9b 100644 --- a/pkg/services/control/ir/types.pb.go +++ b/pkg/services/control/ir/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.12.4 +// protoc v4.24.4 // source: pkg/services/control/ir/types.proto package control From dc4d27201bc36cd9983e559028ebd4400f7703b3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 19 Oct 2023 18:01:19 +0300 Subject: [PATCH 0078/1413] [#733] morph: Fix delete container signature check Committed invalid condition, it was just for debug. Signed-off-by: Dmitrii Stepanov --- pkg/morph/client/container/delete.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/morph/client/container/delete.go b/pkg/morph/client/container/delete.go index c1d346e70b..b520120d20 100644 --- a/pkg/morph/client/container/delete.go +++ b/pkg/morph/client/container/delete.go @@ -67,7 +67,7 @@ func (d *DeletePrm) SetKey(key []byte) { // // If TryNotary is provided, calls notary contract. func (c *Client) Delete(p DeletePrm) error { - if len(p.signature) == 0 && p.IsControl() { + if len(p.signature) == 0 && !p.IsControl() { return errNilArgument } From 12b7cf2533b71616105e09dcab8da8352358cc6b Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 19 Oct 2023 18:19:55 +0300 Subject: [PATCH 0079/1413] [#747] client: Refactor PrmObjectPutSingle usage Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- pkg/services/object/internal/client/client.go | 24 ++++++------------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 28008128c7..a97e04f334 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230928142024-84b9d29fc98c + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231019083813-5804128ff3d5 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 8490c167c7..29134ea577 100644 --- a/go.sum +++ b/go.sum @@ -393,8 +393,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230928142024-84b9d29fc98c h1:c8mduKlc8Zioppz5o06QRYS5KYX3BFRO+NgKj2q6kD8= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20230928142024-84b9d29fc98c/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231019083813-5804128ff3d5 h1:P2HCnBTx+LwhMYSrs4sF8+jHvD1+HdS0fMtUPe2kTns= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231019083813-5804128ff3d5/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index 0301a593a6..27548862e7 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -449,25 +449,15 @@ func PutObjectSingle(ctx context.Context, prm PutObjectPrm) (*PutObjectRes, erro return nil, errors.New("missing object id") } - var prmCli client.PrmObjectPutSingle - - prmCli.ExecuteLocal() - - if prm.key != nil { - prmCli.UseKey(prm.key) + prmCli := client.PrmObjectPutSingle{ + XHeaders: prm.xHeaders, + BearerToken: prm.tokenBearer, + Session: prm.tokenSession, + Local: true, + Key: prm.key, + Object: prm.obj, } - if prm.tokenSession != nil { - prmCli.WithinSession(*prm.tokenSession) - } - - if prm.tokenBearer != nil { - prmCli.WithBearerToken(*prm.tokenBearer) - } - - prmCli.WithXHeaders(prm.xHeaders...) - prmCli.SetObject(prm.obj.ToV2()) - res, err := prm.cli.ObjectPutSingle(ctx, prmCli) if err != nil { ReportError(prm.cli, err) From 58b6224dd890ceb554e205bd480085f9e71d2ff3 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Fri, 20 Oct 2023 10:33:24 +0300 Subject: [PATCH 0080/1413] [#747] client: Refactor PrmObjectPutInit usage Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/client.go | 27 +++++++------------ pkg/services/object/internal/client/client.go | 22 +++++---------- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 9cb7c8161f..b370ff3aa6 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -387,30 +387,23 @@ func (x *PutObjectPrm) PrepareLocally() { } func (x *PutObjectPrm) convertToSDKPrm(ctx context.Context) (client.PrmObjectPutInit, error) { - var putPrm client.PrmObjectPutInit - if !x.prepareLocally && x.sessionToken != nil { - putPrm.WithinSession(*x.sessionToken) + putPrm := client.PrmObjectPutInit{ + XHeaders: x.xHeaders, + BearerToken: x.bearerToken, + Local: x.local, + CopiesNumber: x.copyNum, } - if x.bearerToken != nil { - putPrm.WithBearerToken(*x.bearerToken) - } - - if x.local { - putPrm.MarkLocal() - } - - putPrm.WithXHeaders(x.xHeaders...) - putPrm.SetCopiesNumberByVectors(x.copyNum) - if x.prepareLocally { res, err := x.cli.NetworkInfo(ctx, client.PrmNetworkInfo{}) if err != nil { return client.PrmObjectPutInit{}, err } - putPrm.WithObjectMaxSize(res.Info().MaxObjectSize()) - putPrm.WithEpochSource(epochSource(res.Info().CurrentEpoch())) - putPrm.WithoutHomomorphicHash(res.Info().HomomorphicHashingDisabled()) + putPrm.MaxSize = res.Info().MaxObjectSize() + putPrm.EpochSource = epochSource(res.Info().CurrentEpoch()) + putPrm.WithoutHomomorphHash = res.Info().HomomorphicHashingDisabled() + } else { + putPrm.Session = x.sessionToken } return putPrm, nil } diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index 27548862e7..e0a7e562ab 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -392,24 +392,14 @@ func PutObject(ctx context.Context, prm PutObjectPrm) (*PutObjectRes, error) { ctx, span := tracing.StartSpanFromContext(ctx, "client.PutObject") defer span.End() - var prmCli client.PrmObjectPutInit - - prmCli.MarkLocal() - - if prm.key != nil { - prmCli.UseKey(*prm.key) + prmCli := client.PrmObjectPutInit{ + XHeaders: prm.xHeaders, + BearerToken: prm.tokenBearer, + Session: prm.tokenSession, + Local: true, + Key: prm.key, } - if prm.tokenSession != nil { - prmCli.WithinSession(*prm.tokenSession) - } - - if prm.tokenBearer != nil { - prmCli.WithBearerToken(*prm.tokenBearer) - } - - prmCli.WithXHeaders(prm.xHeaders...) - w, err := prm.cli.ObjectPutInit(ctx, prmCli) if err != nil { return nil, fmt.Errorf("init object writing on client: %w", err) From b0cf100427dc9d813ac0fc4facd8412f6399b370 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 20 Oct 2023 09:52:25 +0300 Subject: [PATCH 0081/1413] [#49] node: React on SIGHUP only when node in READY state Add more info in logs when node is going to shut down, but initialization process still in progress. Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/config.go | 16 ++++++++++++++-- cmd/frostfs-node/control.go | 14 ++++++++++++-- cmd/frostfs-node/main.go | 6 +++--- internal/logs/logs.go | 3 +++ pkg/services/control/types.pb.go | 32 +++++++++++++++++++------------- pkg/services/control/types.proto | 3 +++ 6 files changed, 54 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index b35200d271..8a7317231e 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1040,7 +1040,6 @@ func (c *cfg) signalWatcher(ctx context.Context) { c.reloadConfig(ctx) case syscall.SIGTERM, syscall.SIGINT: c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) - // TODO (@acid-ant): #49 need to cover case when stuck at the middle(node health UNDEFINED or STARTING) c.shutdown() @@ -1062,6 +1061,12 @@ func (c *cfg) signalWatcher(ctx context.Context) { func (c *cfg) reloadConfig(ctx context.Context) { c.log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) + if !c.compareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { + c.log.Info(logs.FrostFSNodeSIGHUPSkip) + return + } + defer c.compareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) + err := c.readConfig(c.appCfg) if err != nil { c.log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) @@ -1142,7 +1147,14 @@ func (c *cfg) createTombstoneSource() *tombstone.ExpirationChecker { } func (c *cfg) shutdown() { - c.setHealthStatus(control.HealthStatus_SHUTTING_DOWN) + old := c.swapHealthStatus(control.HealthStatus_SHUTTING_DOWN) + if old == control.HealthStatus_SHUTTING_DOWN { + c.log.Info(logs.FrostFSNodeShutdownSkip) + return + } + if old == control.HealthStatus_STARTING { + c.log.Warn(logs.FrostFSNodeShutdownWhenNotReady) + } c.ctxCancel() c.done <- struct{}{} diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index 787fe3351d..98d893c388 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -83,10 +83,20 @@ func (c *cfg) NetmapStatus() control.NetmapStatus { func (c *cfg) setHealthStatus(st control.HealthStatus) { c.healthStatus.Store(int32(st)) + c.metricsCollector.State().SetHealth(int32(st)) +} - if c.metricsCollector != nil { - c.metricsCollector.State().SetHealth(int32(st)) +func (c *cfg) compareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swapped bool) { + if swapped = c.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped { + c.metricsCollector.State().SetHealth(int32(newSt)) } + return +} + +func (c *cfg) swapHealthStatus(st control.HealthStatus) (old control.HealthStatus) { + old = control.HealthStatus(c.healthStatus.Swap(int32(st))) + c.metricsCollector.State().SetHealth(int32(st)) + return } func (c *cfg) HealthStatus() control.HealthStatus { diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index 88032ebdb2..2791efcefd 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -60,13 +60,13 @@ func main() { var ctx context.Context ctx, c.ctxCancel = context.WithCancel(context.Background()) - initApp(ctx, c) - c.setHealthStatus(control.HealthStatus_STARTING) + initApp(ctx, c) + bootUp(ctx, c) - c.setHealthStatus(control.HealthStatus_READY) + c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY) wait(c) } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 56312f83f0..f8d6cc9b4e 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -436,6 +436,9 @@ const ( FrostFSNodeInternalApplicationError = "internal application error" FrostFSNodeInternalErrorProcessingIsComplete = "internal error processing is complete" FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration = "SIGHUP has been received, rereading configuration..." + FrostFSNodeSIGHUPSkip = "node not ready for reconfiguration, skipped SIGHUP" + FrostFSNodeShutdownSkip = "node already is going to shutting down, skipped shutdown" + FrostFSNodeShutdownWhenNotReady = "node is going to shutting down when subsystems still initializing" FrostFSNodeConfigurationReading = "configuration reading" FrostFSNodeLoggerConfigurationPreparation = "logger configuration preparation" FrostFSNodeTracingConfigationUpdated = "tracing configation updated" diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index d2ee507708..b385bc6741 100644 --- a/pkg/services/control/types.pb.go +++ b/pkg/services/control/types.pb.go @@ -89,6 +89,8 @@ const ( HealthStatus_READY HealthStatus = 2 // Storage node application is shutting down. HealthStatus_SHUTTING_DOWN HealthStatus = 3 + // Storage node application is reconfiguring. + HealthStatus_RECONFIGURING HealthStatus = 4 ) // Enum value maps for HealthStatus. @@ -98,12 +100,14 @@ var ( 1: "STARTING", 2: "READY", 3: "SHUTTING_DOWN", + 4: "RECONFIGURING", } HealthStatus_value = map[string]int32{ "HEALTH_STATUS_UNDEFINED": 0, "STARTING": 1, "READY": 2, "SHUTTING_DOWN": 3, + "RECONFIGURING": 4, } ) @@ -709,24 +713,26 @@ var file_pkg_services_control_types_proto_rawDesc = []byte{ 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, - 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, 0x57, + 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, - 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x2a, 0x6a, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, - 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, - 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, - 0x0a, 0x09, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, - 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, - 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, - 0x59, 0x10, 0x04, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, - 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, - 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x43, 0x4f, 0x4e, + 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x2a, 0x6a, 0x0a, 0x09, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x44, + 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, + 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, + 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, + 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, + 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, + 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, + 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, + 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/pkg/services/control/types.proto b/pkg/services/control/types.proto index 5b48445807..b34988c2e8 100644 --- a/pkg/services/control/types.proto +++ b/pkg/services/control/types.proto @@ -115,6 +115,9 @@ enum HealthStatus { // Storage node application is shutting down. SHUTTING_DOWN = 3; + + // Storage node application is reconfiguring. + RECONFIGURING = 4; } // Shard description. From c0b86f2d933fc34e82663872cc154315560af718 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 19 Sep 2023 08:43:13 +0300 Subject: [PATCH 0082/1413] [#642] writecache: Remove usage of close channel in badger Signed-off-by: Anton Nikiforov --- .../writecachebadger/cachebadger.go | 21 +++++----- .../writecache/writecachebadger/flush.go | 38 +++++++++---------- .../writecache/writecachebadger/gc.go | 5 ++- 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go index d5da776357..be7046d05d 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go +++ b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go @@ -26,12 +26,12 @@ type cache struct { // helps to avoid multiple flushing of one object scheduled4Flush map[oid.Address]struct{} scheduled4FlushMtx sync.RWMutex - // closeCh is close channel, protected by modeMtx. - closeCh chan struct{} // wg is a wait group for flush workers. wg sync.WaitGroup // store contains underlying database. store + // cancel is cancel function, protected by modeMtx in Close. + cancel func() } // wcStorageType is used for write-cache operations logging. @@ -89,11 +89,6 @@ func (c *cache) Open(_ context.Context, readOnly bool) error { if err != nil { return metaerr.Wrap(err) } - - // Opening after Close is done during maintenance mode, - // thus we need to create a channel here. - c.closeCh = make(chan struct{}) - return metaerr.Wrap(c.initCounters()) } @@ -101,8 +96,10 @@ func (c *cache) Open(_ context.Context, readOnly bool) error { func (c *cache) Init() error { c.log.Info(logs.WritecacheBadgerInitExperimental) c.metrics.SetMode(c.mode) - c.runFlushLoop() - c.runGCLoop() + ctx, cancel := context.WithCancel(context.Background()) + c.cancel = cancel + c.runFlushLoop(ctx) + c.runGCLoop(ctx) return nil } @@ -111,8 +108,9 @@ func (c *cache) Close() error { // We cannot lock mutex for the whole operation duration // because it is taken by some background workers, so `wg.Wait()` is done without modeMtx. c.modeMtx.Lock() - if c.closeCh != nil { - close(c.closeCh) + if c.cancel != nil { + c.cancel() + c.cancel = nil } c.mode = mode.DegradedReadOnly // prevent new operations from being processed c.modeMtx.Unlock() @@ -122,7 +120,6 @@ func (c *cache) Close() error { c.modeMtx.Lock() defer c.modeMtx.Unlock() - c.closeCh = nil var err error if c.db != nil { err = c.db.Close() diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush.go b/pkg/local_object_storage/writecache/writecachebadger/flush.go index e0333eff73..1ee6bbb66a 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush.go @@ -39,18 +39,16 @@ type collector struct { cache *cache scheduled int processed int - cancel func() } -func (c *collector) Send(buf *z.Buffer) error { +func (c *collector) send(ctx context.Context, cancel func(), buf *z.Buffer) error { list, err := badger.BufferToKVList(buf) if err != nil { return err } for _, kv := range list.Kv { select { - case <-c.cache.closeCh: - c.cancel() + case <-ctx.Done(): return nil default: } @@ -58,7 +56,7 @@ func (c *collector) Send(buf *z.Buffer) error { return nil } if c.scheduled >= flushBatchSize { - c.cancel() + cancel() return nil } if got, want := len(kv.Key), len(internalKey{}); got != want { @@ -90,8 +88,7 @@ func (c *collector) Send(buf *z.Buffer) error { data: val, obj: obj, }: - case <-c.cache.closeCh: - c.cancel() + case <-ctx.Done(): return nil } } @@ -99,10 +96,10 @@ func (c *collector) Send(buf *z.Buffer) error { } // runFlushLoop starts background workers which periodically flush objects to the blobstor. -func (c *cache) runFlushLoop() { +func (c *cache) runFlushLoop(ctx context.Context) { for i := 0; i < c.workersCount; i++ { c.wg.Add(1) - go c.workerFlushSmall() + go c.workerFlushSmall(ctx) } c.wg.Add(1) @@ -115,19 +112,19 @@ func (c *cache) runFlushLoop() { for { select { case <-tt.C: - c.flushSmallObjects() + c.flushSmallObjects(ctx) tt.Reset(defaultFlushInterval) - case <-c.closeCh: + case <-ctx.Done(): return } } }() } -func (c *cache) flushSmallObjects() { +func (c *cache) flushSmallObjects(ctx context.Context) { for { select { - case <-c.closeCh: + case <-ctx.Done(): return default: } @@ -144,14 +141,15 @@ func (c *cache) flushSmallObjects() { c.modeMtx.RUnlock() return } - ctx, cancel := context.WithCancel(context.TODO()) + ctx, cancel := context.WithCancel(ctx) coll := collector{ - cache: c, - cancel: cancel, + cache: c, } stream := c.db.NewStream() // All calls to Send are done by a single goroutine - stream.Send = coll.Send + stream.Send = func(buf *z.Buffer) error { + return coll.send(ctx, cancel, buf) + } if err := stream.Orchestrate(ctx); err != nil { c.log.Debug(fmt.Sprintf( "error during flushing object from wc: %s", err)) @@ -176,7 +174,7 @@ func (c *cache) reportFlushError(msg string, addr string, err error) { } // workerFlushSmall writes small objects to the main storage. -func (c *cache) workerFlushSmall() { +func (c *cache) workerFlushSmall(ctx context.Context) { defer c.wg.Done() var objInfo objectInfo @@ -184,11 +182,11 @@ func (c *cache) workerFlushSmall() { // Give priority to direct put. select { case objInfo = <-c.flushCh: - case <-c.closeCh: + case <-ctx.Done(): return } - err := c.flushObject(context.TODO(), objInfo.obj, objInfo.data, writecache.StorageTypeDB) + err := c.flushObject(ctx, objInfo.obj, objInfo.data, writecache.StorageTypeDB) if err == nil { c.deleteFromDB([]internalKey{addr2key(objInfo.addr)}) } diff --git a/pkg/local_object_storage/writecache/writecachebadger/gc.go b/pkg/local_object_storage/writecache/writecachebadger/gc.go index 8432a9c043..b856efc3df 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/gc.go +++ b/pkg/local_object_storage/writecache/writecachebadger/gc.go @@ -1,12 +1,13 @@ package writecachebadger import ( + "context" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" ) -func (c *cache) runGCLoop() { +func (c *cache) runGCLoop(ctx context.Context) { c.wg.Add(1) go func() { @@ -17,7 +18,7 @@ func (c *cache) runGCLoop() { for { select { - case <-c.closeCh: + case <-ctx.Done(): return case <-t.C: // This serves to synchronize the c.db field when changing mode as well. From 559ad58ab191652c7a144cd4203bb458f9a225f9 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 19 Sep 2023 08:46:19 +0300 Subject: [PATCH 0083/1413] [#642] writecache: Remove usage of close channel in bbolt Signed-off-by: Anton Nikiforov --- .../writecache/writecachebbolt/cachebbolt.go | 18 +++++------ .../writecache/writecachebbolt/flush.go | 32 +++++++------------ 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go b/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go index 363ee8448c..9d54cd5c25 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go @@ -30,8 +30,8 @@ type cache struct { // flushCh is a channel with objects to flush. flushCh chan objectInfo - // closeCh is close channel, protected by modeMtx. - closeCh chan struct{} + // cancel is cancel function, protected by modeMtx in Close. + cancel func() // wg is a wait group for flush workers. wg sync.WaitGroup // store contains underlying database. @@ -104,17 +104,15 @@ func (c *cache) Open(_ context.Context, readOnly bool) error { return metaerr.Wrap(err) } - // Opening after Close is done during maintenance mode, - // thus we need to create a channel here. - c.closeCh = make(chan struct{}) - return metaerr.Wrap(c.initCounters()) } // Init runs necessary services. func (c *cache) Init() error { c.metrics.SetMode(c.mode) - c.runFlushLoop() + ctx, cancel := context.WithCancel(context.Background()) + c.cancel = cancel + c.runFlushLoop(ctx) return nil } @@ -123,8 +121,9 @@ func (c *cache) Close() error { // We cannot lock mutex for the whole operation duration // because it is taken by some background workers, so `wg.Wait()` is done without modeMtx. c.modeMtx.Lock() - if c.closeCh != nil { - close(c.closeCh) + if c.cancel != nil { + c.cancel() + c.cancel = nil } c.mode = mode.DegradedReadOnly // prevent new operations from being processed c.modeMtx.Unlock() @@ -134,7 +133,6 @@ func (c *cache) Close() error { c.modeMtx.Lock() defer c.modeMtx.Unlock() - c.closeCh = nil var err error if c.db != nil { err = c.db.Close() diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush.go b/pkg/local_object_storage/writecache/writecachebbolt/flush.go index fd322e9fad..393776dd1d 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush.go @@ -36,20 +36,10 @@ const ( ) // runFlushLoop starts background workers which periodically flush objects to the blobstor. -func (c *cache) runFlushLoop() { - ctx, cancel := context.WithCancel(context.Background()) - - ch := c.closeCh - c.wg.Add(1) - go func() { - <-ch - cancel() - c.wg.Done() - }() - +func (c *cache) runFlushLoop(ctx context.Context) { for i := 0; i < c.workersCount; i++ { c.wg.Add(1) - go c.workerFlushSmall() + go c.workerFlushSmall(ctx) } c.wg.Add(1) @@ -68,20 +58,20 @@ func (c *cache) runFlushLoop() { for { select { case <-tt.C: - c.flushSmallObjects() + c.flushSmallObjects(ctx) tt.Reset(defaultFlushInterval) - case <-c.closeCh: + case <-ctx.Done(): return } } }() } -func (c *cache) flushSmallObjects() { +func (c *cache) flushSmallObjects(ctx context.Context) { var lastKey []byte for { select { - case <-c.closeCh: + case <-ctx.Done(): return default: } @@ -137,7 +127,7 @@ func (c *cache) flushSmallObjects() { count++ select { case c.flushCh <- m[i]: - case <-c.closeCh: + case <-ctx.Done(): c.modeMtx.RUnlock() return } @@ -170,7 +160,7 @@ func (c *cache) workerFlushBig(ctx context.Context) { _ = c.flushFSTree(ctx, true) c.modeMtx.RUnlock() - case <-c.closeCh: + case <-ctx.Done(): return } } @@ -228,7 +218,7 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { } // workerFlushSmall writes small objects to the main storage. -func (c *cache) workerFlushSmall() { +func (c *cache) workerFlushSmall(ctx context.Context) { defer c.wg.Done() var objInfo objectInfo @@ -236,11 +226,11 @@ func (c *cache) workerFlushSmall() { // Give priority to direct put. select { case objInfo = <-c.flushCh: - case <-c.closeCh: + case <-ctx.Done(): return } - err := c.flushObject(context.TODO(), objInfo.obj, objInfo.data, writecache.StorageTypeDB) + err := c.flushObject(ctx, objInfo.obj, objInfo.data, writecache.StorageTypeDB) if err != nil { // Error is handled in flushObject. continue From fe1acf9e9a42367ae78e411f8124aaeed5fb707d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 12:34:30 +0300 Subject: [PATCH 0084/1413] [#750] morph: Remove deprecated channel use Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/client.go | 9 --------- pkg/morph/subscriber/subscriber.go | 15 ++++----------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 606f3bd66e..290e651f7f 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -527,15 +527,6 @@ func (c *Client) IsValidScript(script []byte, signers []transaction.Signer) (val return res.State == vmstate.Halt.String(), nil } -// NotificationChannel returns channel than receives subscribed -// notification from the connected RPC node. -// Channel is closed when connection to the RPC node is lost. -func (c *Client) NotificationChannel() <-chan rpcclient.Notification { - c.switchLock.RLock() - defer c.switchLock.RUnlock() - return c.client.Notifications //lint:ignore SA1019 waits for neo-go v0.102.0 https://github.com/nspcc-dev/neo-go/pull/2980 -} - func (c *Client) Metrics() morphmetrics.Register { return c.metrics } diff --git a/pkg/morph/subscriber/subscriber.go b/pkg/morph/subscriber/subscriber.go index c2d8494faf..7f3c913857 100644 --- a/pkg/morph/subscriber/subscriber.go +++ b/pkg/morph/subscriber/subscriber.go @@ -12,7 +12,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/util" "go.uber.org/zap" ) @@ -183,8 +182,6 @@ func New(ctx context.Context, p *Params) (Subscriber, error) { func (s *subscriber) routeNotifications(ctx context.Context) { var ( - // TODO: not needed after nspcc-dev/neo-go#2980. - cliCh = s.client.NotificationChannel() restoreCh = make(chan bool) restoreInProgress bool ) @@ -220,8 +217,6 @@ routeloop: } else { connLost = true } - case _, ok := <-cliCh: - connLost = !ok case ok := <-restoreCh: restoreInProgress = false if !ok { @@ -230,7 +225,7 @@ routeloop: } if connLost { if !restoreInProgress { - restoreInProgress, cliCh = s.switchEndpoint(ctx, restoreCh) + restoreInProgress = s.switchEndpoint(ctx, restoreCh) if !restoreInProgress { break routeloop } @@ -249,15 +244,13 @@ routeloop: close(s.notaryChan) } -func (s *subscriber) switchEndpoint(ctx context.Context, finishCh chan<- bool) (bool, <-chan rpcclient.Notification) { +func (s *subscriber) switchEndpoint(ctx context.Context, finishCh chan<- bool) bool { s.log.Info(logs.RPConnectionLost) if !s.client.SwitchRPC(ctx) { s.log.Error(logs.RPCNodeSwitchFailure) - return false, nil + return false } - cliCh := s.client.NotificationChannel() - s.Lock() chs := newSubChannels() go func() { @@ -267,7 +260,7 @@ func (s *subscriber) switchEndpoint(ctx context.Context, finishCh chan<- bool) ( s.Unlock() s.client.Metrics().IncSwitchCount() - return true, cliCh + return true } func newSubChannels() subChannels { From efb37b0e658b041b4b6bb1365da5fa6d25120a01 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 13:36:03 +0300 Subject: [PATCH 0085/1413] [#750] adm: Fix invalid tests Introduced in a9d04ba86f2. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/initialize_test.go | 10 ++++++++-- cmd/frostfs-adm/internal/modules/morph/root.go | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index 30a7168dd0..39da56662d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -20,7 +20,7 @@ import ( ) const ( - contractsPath = "../../../../../../frostfs-contract/frostfs-contract-v0.16.0.tar.gz" + contractsPath = "../../../../../../contract/frostfs-contract-v0.18.0.tar.gz" protoFileName = "proto.yml" ) @@ -58,7 +58,9 @@ func testInitialize(t *testing.T, committeeSize int) { // Set to the path or remove the next statement to download from the network. require.NoError(t, initCmd.Flags().Set(contractsInitFlag, contractsPath)) - v.Set(localDumpFlag, filepath.Join(testdataDir, "out")) + + dumpPath := filepath.Join(testdataDir, "out") + require.NoError(t, initCmd.Flags().Set(localDumpFlag, dumpPath)) v.Set(alphabetWalletsFlag, testdataDir) v.Set(epochDurationInitFlag, 1) v.Set(maxObjectSizeInitFlag, 1024) @@ -67,12 +69,15 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, initializeSideChainCmd(initCmd, nil)) t.Run("force-new-epoch", func(t *testing.T) { + require.NoError(t, forceNewEpoch.Flags().Set(localDumpFlag, dumpPath)) require.NoError(t, forceNewEpochCmd(forceNewEpoch, nil)) }) t.Run("set-config", func(t *testing.T) { + require.NoError(t, setConfig.Flags().Set(localDumpFlag, dumpPath)) require.NoError(t, setConfigCmd(setConfig, []string{"MaintenanceModeAllowed=true"})) }) t.Run("set-policy", func(t *testing.T) { + require.NoError(t, setPolicy.Flags().Set(localDumpFlag, dumpPath)) require.NoError(t, setPolicyCmd(setPolicy, []string{"ExecFeeFactor=1"})) }) t.Run("remove-node", func(t *testing.T) { @@ -80,6 +85,7 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, err) pub := hex.EncodeToString(pk.PublicKey().Bytes()) + require.NoError(t, removeNodes.Flags().Set(localDumpFlag, dumpPath)) require.NoError(t, removeNodesCmd(removeNodes, []string{pub})) }) } diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index bee1837a32..133d5162fd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -320,6 +320,7 @@ func initSetConfigCmd() { setConfig.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") setConfig.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") setConfig.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") + setConfig.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initDumpNetworkConfigCmd() { @@ -337,18 +338,21 @@ func initSetPolicyCmd() { RootCmd.AddCommand(setPolicy) setPolicy.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") setPolicy.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + setPolicy.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initRemoveNodesCmd() { RootCmd.AddCommand(removeNodes) removeNodes.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") removeNodes.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + removeNodes.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initForceNewEpochCmd() { RootCmd.AddCommand(forceNewEpoch) forceNewEpoch.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") forceNewEpoch.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + forceNewEpoch.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initGenerateStorageCmd() { From 7f8ccc105bb85c4889f66655c2552caeeef89a17 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 12:47:46 +0300 Subject: [PATCH 0086/1413] [#750] adm: Drop deprecated GetNetwork() Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/initialize_transfer.go | 3 ++- cmd/frostfs-adm/internal/modules/morph/local_client.go | 5 ----- cmd/frostfs-adm/internal/modules/morph/n3client.go | 2 -- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index 1f8e534161..b032780be0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -93,12 +93,13 @@ func (c *initializeContext) multiSignAndSend(tx *transaction.Transaction, accTyp } func (c *initializeContext) multiSign(tx *transaction.Transaction, accType string) error { - network, err := c.Client.GetNetwork() + version, err := c.Client.GetVersion() if err != nil { // error appears only if client // has not been initialized panic(err) } + network := version.Protocol.Network // Use parameter context to avoid dealing with signature order. pc := scContext.NewParameterContext("", network, tx) diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/local_client.go index 0367f74792..84cf40e977 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/local_client.go @@ -10,7 +10,6 @@ import ( "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/config" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/chaindump" @@ -138,10 +137,6 @@ func (l *localClient) GetNativeContracts() ([]state.NativeContract, error) { return l.bc.GetNatives(), nil } -func (l *localClient) GetNetwork() (netmode.Magic, error) { - return l.bc.GetConfig().Magic, nil -} - func (l *localClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*result.ApplicationLog, error) { aer, err := l.bc.GetAppExecResults(h, *t) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/n3client.go index 138943b6e4..77f207c9fb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/n3client.go @@ -6,7 +6,6 @@ import ( "fmt" "time" - "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -32,7 +31,6 @@ type Client interface { GetContractStateByID(int32) (*state.Contract, error) GetContractStateByHash(util.Uint160) (*state.Contract, error) GetNativeContracts() ([]state.NativeContract, error) - GetNetwork() (netmode.Magic, error) GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error) GetVersion() (*result.Version, error) CreateTxFromScript([]byte, *wallet.Account, int64, int64, []rpcclient.SignerAccount) (*transaction.Transaction, error) From 00a0045d9a50faca916461bdbb3d0de261aceb86 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 13:06:30 +0300 Subject: [PATCH 0087/1413] [#750] adm: Drop deprecated GetContract*() Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/balance.go | 4 +++- cmd/frostfs-adm/internal/modules/morph/config.go | 7 +++++-- .../internal/modules/morph/container.go | 13 ++++++++----- cmd/frostfs-adm/internal/modules/morph/deploy.go | 3 ++- .../internal/modules/morph/dump_hashes.go | 4 +++- cmd/frostfs-adm/internal/modules/morph/epoch.go | 4 +++- .../internal/modules/morph/initialize.go | 4 +++- .../internal/modules/morph/initialize_deploy.go | 16 +++++++++++----- .../internal/modules/morph/initialize_nns.go | 4 +++- .../internal/modules/morph/local_client.go | 15 --------------- .../internal/modules/morph/n3client.go | 2 -- .../internal/modules/morph/netmap_candidates.go | 4 +++- .../internal/modules/morph/remove_node.go | 4 +++- 13 files changed, 47 insertions(+), 37 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance.go index 6debc50b9e..9b706c7bf2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance.go @@ -16,6 +16,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/rolemgmt" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" @@ -56,7 +57,8 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { inv := invoker.New(c, nil) if dumpStorage || dumpAlphabet || dumpProxy { - nnsCs, err = c.GetContractStateByID(1) + r := management.NewReader(inv) + nnsCs, err = r.GetContractByID(1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index a86829aaa1..3c4029bcaf 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -13,6 +13,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/vm/emit" @@ -29,8 +30,9 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { } inv := invoker.New(c, nil) + r := management.NewReader(inv) - cs, err := c.GetContractStateByID(1) + cs, err := r.GetContractByID(1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } @@ -87,7 +89,8 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't initialize context: %w", err) } - cs, err := wCtx.Client.GetContractStateByID(1) + r := management.NewReader(wCtx.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index 687d7e84ee..f3faa30447 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -11,6 +11,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" @@ -22,14 +23,15 @@ import ( var errInvalidContainerResponse = errors.New("invalid response from container contract") -func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker, c Client) (util.Uint160, error) { +func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker) (util.Uint160, error) { s, err := cmd.Flags().GetString(containerContractFlag) var ch util.Uint160 if err == nil { ch, err = util.Uint160DecodeStringLE(s) } if err != nil { - nnsCs, err := c.GetContractStateByID(1) + r := management.NewReader(inv) + nnsCs, err := r.GetContractByID(1) if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } @@ -78,7 +80,7 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { inv := invoker.New(c, nil) - ch, err := getContainerContractHash(cmd, inv, c) + ch, err := getContainerContractHash(cmd, inv) if err != nil { return fmt.Errorf("unable to get contaract hash: %w", err) } @@ -168,7 +170,7 @@ func listContainers(cmd *cobra.Command, _ []string) error { inv := invoker.New(c, nil) - ch, err := getContainerContractHash(cmd, inv, c) + ch, err := getContainerContractHash(cmd, inv) if err != nil { return fmt.Errorf("unable to get contaract hash: %w", err) } @@ -298,7 +300,8 @@ func parseContainers(filename string) ([]Container, error) { } func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) { - nnsCs, err := wCtx.Client.GetContractStateByID(1) + r := management.NewReader(wCtx.ReadOnlyInvoker) + nnsCs, err := r.GetContractByID(1) if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index a4b9454383..54b506715b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -76,7 +76,8 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { return err } - nnsCs, err := c.Client.GetContractStateByID(1) + r := management.NewReader(c.ReadOnlyInvoker) + nnsCs, err := r.GetContractByID(1) if err != nil { return fmt.Errorf("can't fetch NNS contract state: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index 69db5c7bd6..585de6d6d1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -11,6 +11,7 @@ import ( morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" @@ -36,7 +37,8 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't create N3 client: %w", err) } - cs, err := c.GetContractStateByID(1) + r := management.NewReader(invoker.New(c, nil)) + cs, err := r.GetContractByID(1) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index a96efa43f7..453e984b07 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" @@ -20,7 +21,8 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't to initialize context: %w", err) } - cs, err := wCtx.Client.GetContractStateByID(1) + r := management.NewReader(wCtx.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index dec1fba20a..4184e1a80e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -15,6 +15,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" @@ -312,7 +313,8 @@ func (c *initializeContext) nnsContractState() (*state.Contract, error) { return c.nnsCs, nil } - cs, err := c.Client.GetContractStateByID(1) + r := management.NewReader(c.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) if err != nil { return nil, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index a7cd537b7c..6896b4ff05 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -94,7 +94,10 @@ func (c *initializeContext) deployNNS(method string) error { h := cs.Hash nnsCs, err := c.nnsContractState() - if err == nil { + if err != nil { + return err + } + if nnsCs != nil { if nnsCs.NEF.Checksum == cs.NEF.Checksum { if method == deployMethodName { c.Command.Println("NNS contract is already deployed.") @@ -366,8 +369,9 @@ func (c *initializeContext) deployContracts() error { } func (c *initializeContext) isUpdated(ctrHash util.Uint160, cs *contractState) bool { - realCs, err := c.Client.GetContractStateByHash(ctrHash) - return err == nil && realCs.NEF.Checksum == cs.NEF.Checksum + r := management.NewReader(c.ReadOnlyInvoker) + realCs, err := r.GetContract(ctrHash) + return err == nil && realCs != nil && realCs.NEF.Checksum == cs.NEF.Checksum } func (c *initializeContext) getContract(ctrName string) *contractState { @@ -536,7 +540,8 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an case containerContract: // In case if NNS is updated multiple times, we can't calculate // it's actual hash based on local data, thus query chain. - nnsCs, err := c.Client.GetContractStateByID(1) + r := management.NewReader(c.ReadOnlyInvoker) + nnsCs, err := r.GetContractByID(1) if err != nil { panic("NNS is not yet deployed") } @@ -590,7 +595,8 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an } func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, error) { - cs, err := c.Client.GetContractStateByID(1) + r := management.NewReader(c.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) if err != nil { return nil, fmt.Errorf("NNS is not yet deployed: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 6758b4dd8e..1bf4c4bee2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -15,6 +15,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" nnsClient "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" @@ -30,7 +31,8 @@ const defaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second const frostfsOpsEmail = "ops@frostfs.info" func (c *initializeContext) setNNS() error { - nnsCs, err := c.Client.GetContractStateByID(1) + r := management.NewReader(c.ReadOnlyInvoker) + nnsCs, err := r.GetContractByID(1) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/local_client.go index 84cf40e977..cd094ca299 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/local_client.go @@ -118,21 +118,6 @@ func (l *localClient) GetBlockCount() (uint32, error) { return l.bc.BlockHeight(), nil } -func (l *localClient) GetContractStateByID(id int32) (*state.Contract, error) { - h, err := l.bc.GetContractScriptHash(id) - if err != nil { - return nil, err - } - return l.GetContractStateByHash(h) -} - -func (l *localClient) GetContractStateByHash(h util.Uint160) (*state.Contract, error) { - if cs := l.bc.GetContractState(h); cs != nil { - return cs, nil - } - return nil, storage.ErrKeyNotFound -} - func (l *localClient) GetNativeContracts() ([]state.NativeContract, error) { return l.bc.GetNatives(), nil } diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/n3client.go index 77f207c9fb..7ba5a7ce38 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/n3client.go @@ -28,8 +28,6 @@ type Client interface { invoker.RPCInvoke GetBlockCount() (uint32, error) - GetContractStateByID(int32) (*state.Contract, error) - GetContractStateByHash(util.Uint160) (*state.Contract, error) GetNativeContracts() ([]state.NativeContract, error) GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error) GetVersion() (*result.Version, error) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go index 222b9902a9..30f7c69c42 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go @@ -5,6 +5,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -14,8 +15,9 @@ func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err) inv := invoker.New(c, nil) + r := management.NewReader(inv) - cs, err := c.GetContractStateByID(1) + cs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) nmHash, err := nnsResolveHash(inv, cs.Hash, netmapContract+".frostfs") diff --git a/cmd/frostfs-adm/internal/modules/morph/remove_node.go b/cmd/frostfs-adm/internal/modules/morph/remove_node.go index df67433c41..ba7bb90ff6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/remove_node.go +++ b/cmd/frostfs-adm/internal/modules/morph/remove_node.go @@ -7,6 +7,7 @@ import ( netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/spf13/cobra" @@ -33,7 +34,8 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { } defer wCtx.close() - cs, err := wCtx.Client.GetContractStateByID(1) + r := management.NewReader(wCtx.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } From 4368243bed365983e992a71c14fcdc08fe4cff4d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 13:13:49 +0300 Subject: [PATCH 0088/1413] [#750] adm: Drop deprecated NEP17BalanceOf() Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize_register.go | 7 +++++-- .../modules/morph/initialize_transfer.go | 12 ++++++++---- .../internal/modules/morph/local_client.go | 17 ----------------- .../internal/modules/morph/n3client.go | 1 - 4 files changed, 13 insertions(+), 24 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go index 469b269de2..60bb7f8ed7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go @@ -3,6 +3,7 @@ package morph import ( "errors" "fmt" + "math/big" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -11,6 +12,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" @@ -134,8 +136,9 @@ func (c *initializeContext) transferNEOToAlphabetContracts() error { } func (c *initializeContext) transferNEOFinished(neoHash util.Uint160) (bool, error) { - bal, err := c.Client.NEP17BalanceOf(neoHash, c.CommitteeAcc.Contract.ScriptHash()) - return bal < native.NEOTotalSupply, err + r := nep17.NewReader(c.ReadOnlyInvoker, neoHash) + bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash()) + return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err } var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response") diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index b032780be0..45db6489f2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -2,6 +2,7 @@ package morph import ( "fmt" + "math/big" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -9,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" scContext "github.com/nspcc-dev/neo-go/pkg/smartcontract/context" "github.com/nspcc-dev/neo-go/pkg/vm/emit" @@ -80,8 +82,9 @@ func (c *initializeContext) transferFunds() error { func (c *initializeContext) transferFundsFinished() (bool, error) { acc := c.Accounts[0] - res, err := c.Client.NEP17BalanceOf(gas.Hash, acc.Contract.ScriptHash()) - return res > initialAlphabetGASAmount/2, err + r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) + res, err := r.BalanceOf(acc.Contract.ScriptHash()) + return res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) == 1, err } func (c *initializeContext) multiSignAndSend(tx *transaction.Transaction, accType string) error { @@ -147,8 +150,9 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin func (c *initializeContext) transferGASToProxy() error { proxyCs := c.getContract(proxyContract) - bal, err := c.Client.NEP17BalanceOf(gas.Hash, proxyCs.Hash) - if err != nil || bal > 0 { + r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) + bal, err := r.BalanceOf(proxyCs.Hash) + if err != nil || bal.Sign() > 0 { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/local_client.go index cd094ca299..2ef8774bb4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/local_client.go @@ -35,7 +35,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -324,22 +323,6 @@ func getSigners(sender *wallet.Account, cosigners []rpcclient.SignerAccount) ([] return signers, accounts, nil } -func (l *localClient) NEP17BalanceOf(h util.Uint160, acc util.Uint160) (int64, error) { - res, err := invokeFunction(l, h, "balanceOf", []any{acc}, nil) - if err != nil { - return 0, err - } - if res.State != vmstate.Halt.String() || len(res.Stack) == 0 { - return 0, fmt.Errorf("`balance`: invalid response (empty: %t): %s", - len(res.Stack) == 0, res.FaultException) - } - bi, err := res.Stack[0].TryInteger() - if err != nil || !bi.IsInt64() { - return 0, fmt.Errorf("`balance`: invalid response") - } - return bi.Int64(), nil -} - func (l *localClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) { lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash()) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/n3client.go index 7ba5a7ce38..ac9abee8c3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/n3client.go @@ -32,7 +32,6 @@ type Client interface { GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error) GetVersion() (*result.Version, error) CreateTxFromScript([]byte, *wallet.Account, int64, int64, []rpcclient.SignerAccount) (*transaction.Transaction, error) - NEP17BalanceOf(util.Uint160, util.Uint160) (int64, error) SendRawTransaction(*transaction.Transaction) (util.Uint256, error) GetCommittee() (keys.PublicKeys, error) CalculateNotaryFee(uint8) (int64, error) From a788c24e6d6a4ab7681102da27f44bc77676d099 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 13:23:12 +0300 Subject: [PATCH 0089/1413] [#750] adm: Drop deprecated AddNetworkFee() Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/local_client.go | 114 ++++++++++-------- .../internal/modules/morph/n3client.go | 1 - 2 files changed, 65 insertions(+), 50 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/local_client.go index 2ef8774bb4..eca9f45b71 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/local_client.go @@ -13,12 +13,10 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/chaindump" - "github.com/nspcc-dev/neo-go/pkg/core/fee" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" @@ -30,8 +28,10 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" @@ -150,12 +150,17 @@ func (l *localClient) CreateTxFromScript(script []byte, acc *wallet.Account, sys tx := transaction.New(script, sysFee) tx.Signers = signers tx.ValidUntilBlock = l.bc.BlockHeight() + 2 + tx.Scripts = make([]transaction.Witness, len(accounts)) + for i := range tx.Scripts { + tx.Scripts[i].VerificationScript = accounts[i].Contract.Script + } - err = l.AddNetworkFee(tx, netFee, accounts...) + fee, err := l.CalculateNetworkFee(tx) if err != nil { return nil, fmt.Errorf("failed to add network fee: %w", err) } + tx.NetworkFee = fee + netFee return tx, nil } @@ -233,67 +238,78 @@ func (l *localClient) InvokeContractVerify(util.Uint160, []smartcontract.Paramet // CalculateNetworkFee calculates network fee for the given transaction. // Copied from neo-go with minor corrections (no need to support non-notary mode): -// https://github.com/nspcc-dev/neo-go/blob/v0.99.2/pkg/services/rpcsrv/server.go#L744 +// https://github.com/nspcc-dev/neo-go/blob/v0.103.0/pkg/services/rpcsrv/server.go#L911 func (l *localClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) { + // Avoid setting hash for this tx: server code doesn't touch client transaction. + data := tx.Bytes() + tx, err := transaction.NewTransactionFromBytes(data) + if err != nil { + return 0, err + } + hashablePart, err := tx.EncodeHashableFields() if err != nil { - return 0, fmt.Errorf("failed to compute tx size: %w", err) + return 0, err } - size := len(hashablePart) + io.GetVarSize(len(tx.Signers)) - ef := l.bc.GetBaseExecFee() - - var netFee int64 + var ( + netFee int64 + // Verification GAS cost can't exceed this policy. + gasLimit = l.bc.GetMaxVerificationGAS() + ) for i, signer := range tx.Signers { - var verificationScript []byte - for _, w := range tx.Scripts { - if w.VerificationScript != nil && hash.Hash160(w.VerificationScript).Equals(signer.Account) { - verificationScript = w.VerificationScript - break + w := tx.Scripts[i] + if len(w.InvocationScript) == 0 { // No invocation provided, try to infer one. + var paramz []manifest.Parameter + if len(w.VerificationScript) == 0 { // Contract-based verification + cs := l.bc.GetContractState(signer.Account) + if cs == nil { + return 0, fmt.Errorf("signer %d has no verification script and no deployed contract", i) + } + md := cs.Manifest.ABI.GetMethod(manifest.MethodVerify, -1) + if md == nil || md.ReturnType != smartcontract.BoolType { + return 0, fmt.Errorf("signer %d has no verify method in deployed contract", i) + } + paramz = md.Parameters // Might as well have none params and it's OK. + } else { // Regular signature verification. + if vm.IsSignatureContract(w.VerificationScript) { + paramz = []manifest.Parameter{{Type: smartcontract.SignatureType}} + } else if nSigs, _, ok := vm.ParseMultiSigContract(w.VerificationScript); ok { + paramz = make([]manifest.Parameter, nSigs) + for j := 0; j < nSigs; j++ { + paramz[j] = manifest.Parameter{Type: smartcontract.SignatureType} + } + } } - } - if verificationScript == nil { - gasConsumed, err := l.bc.VerifyWitness(signer.Account, tx, &tx.Scripts[i], l.maxGasInvoke) - if err != nil { - return 0, fmt.Errorf("invalid signature: %w", err) + inv := io.NewBufBinWriter() + for _, p := range paramz { + p.Type.EncodeDefaultValue(inv.BinWriter) } - netFee += gasConsumed - size += io.GetVarSize([]byte{}) + io.GetVarSize(tx.Scripts[i].InvocationScript) - continue + if inv.Err != nil { + return 0, fmt.Errorf("failed to create dummy invocation script (signer %d): %s", i, inv.Err.Error()) + } + w.InvocationScript = inv.Bytes() + } + gasConsumed, err := l.bc.VerifyWitness(signer.Account, tx, &w, gasLimit) + if err != nil && !errors.Is(err, core.ErrInvalidSignature) { + return 0, err + } + gasLimit -= gasConsumed + netFee += gasConsumed + size += io.GetVarSize(w.VerificationScript) + io.GetVarSize(w.InvocationScript) + } + if l.bc.P2PSigExtensionsEnabled() { + attrs := tx.GetAttributes(transaction.NotaryAssistedT) + if len(attrs) != 0 { + na := attrs[0].Value.(*transaction.NotaryAssisted) + netFee += (int64(na.NKeys) + 1) * l.bc.GetNotaryServiceFeePerKey() } - - fee, sizeDelta := fee.Calculate(ef, verificationScript) - netFee += fee - size += sizeDelta } - fee := l.bc.FeePerByte() netFee += int64(size) * fee - return netFee, nil } -// AddNetworkFee adds network fee for each witness script and optional extra -// network fee to transaction. `accs` is an array signer's accounts. -// Copied from neo-go with minor corrections (no need to support contract signers): -// https://github.com/nspcc-dev/neo-go/blob/6ff11baa1b9e4c71ef0d1de43b92a8c541ca732c/pkg/rpc/client/rpc.go#L960 -func (l *localClient) AddNetworkFee(tx *transaction.Transaction, extraFee int64, accs ...*wallet.Account) error { - if len(tx.Signers) != len(accs) { - return errors.New("number of signers must match number of scripts") - } - - size := io.GetVarSize(tx) - ef := l.bc.GetBaseExecFee() - for i := range tx.Signers { - netFee, sizeDelta := fee.Calculate(ef, accs[i].Contract.Script) - tx.NetworkFee += netFee - size += sizeDelta - } - - tx.NetworkFee += int64(size)*l.bc.FeePerByte() + extraFee - return nil -} - // getSigners returns an array of transaction signers and corresponding accounts from // given sender and cosigners. If cosigners list already contains sender, the sender // will be placed at the start of the list. diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/n3client.go index ac9abee8c3..e3042740b9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/n3client.go @@ -36,7 +36,6 @@ type Client interface { GetCommittee() (keys.PublicKeys, error) CalculateNotaryFee(uint8) (int64, error) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) - AddNetworkFee(*transaction.Transaction, int64, ...*wallet.Account) error SignAndPushInvocationTx([]byte, *wallet.Account, int64, fixedn.Fixed8, []rpcclient.SignerAccount) (util.Uint256, error) SignAndPushP2PNotaryRequest(*transaction.Transaction, []byte, int64, int64, uint32, *wallet.Account) (*payload.P2PNotaryRequest, error) } From b0d303f3ed40a500cb8a838aac794be4a55f1a63 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 14:52:46 +0300 Subject: [PATCH 0090/1413] [#750] adm: Drop unused methods from Client Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/local_client.go | 17 ----------------- .../internal/modules/morph/n3client.go | 5 ----- 2 files changed, 22 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/local_client.go index eca9f45b71..b00eca6b4b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/local_client.go @@ -19,10 +19,8 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" @@ -184,21 +182,6 @@ func (l *localClient) InvokeFunction(h util.Uint160, method string, sPrm []smart return invokeFunction(l, h, method, pp, ss) } -func (l *localClient) CalculateNotaryFee(_ uint8) (int64, error) { - // not used by `morph init` command - panic("unexpected call") -} - -func (l *localClient) SignAndPushP2PNotaryRequest(_ *transaction.Transaction, _ []byte, _ int64, _ int64, _ uint32, _ *wallet.Account) (*payload.P2PNotaryRequest, error) { - // not used by `morph init` command - panic("unexpected call") -} - -func (l *localClient) SignAndPushInvocationTx(_ []byte, _ *wallet.Account, _ int64, _ fixedn.Fixed8, _ []rpcclient.SignerAccount) (util.Uint256, error) { - // not used by `morph init` command - panic("unexpected call") -} - func (l *localClient) TerminateSession(_ uuid.UUID) (bool, error) { // not used by `morph init` command panic("unexpected call") diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/n3client.go index e3042740b9..d99715592f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/n3client.go @@ -9,9 +9,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -34,10 +32,7 @@ type Client interface { CreateTxFromScript([]byte, *wallet.Account, int64, int64, []rpcclient.SignerAccount) (*transaction.Transaction, error) SendRawTransaction(*transaction.Transaction) (util.Uint256, error) GetCommittee() (keys.PublicKeys, error) - CalculateNotaryFee(uint8) (int64, error) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) - SignAndPushInvocationTx([]byte, *wallet.Account, int64, fixedn.Fixed8, []rpcclient.SignerAccount) (util.Uint256, error) - SignAndPushP2PNotaryRequest(*transaction.Transaction, []byte, int64, int64, uint32, *wallet.Account) (*payload.P2PNotaryRequest, error) } type hashVUBPair struct { From 7f35f2fb1dbc2b192e1cba32aa847f358f19eee7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 15:12:59 +0300 Subject: [PATCH 0091/1413] [#750] adm: Drop deprecated CreateTxFromScript() Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize_deploy.go | 20 +----- .../modules/morph/initialize_register.go | 11 +++- .../modules/morph/initialize_transfer.go | 30 ++++----- .../internal/modules/morph/local_client.go | 63 ------------------- .../internal/modules/morph/n3client.go | 1 - 5 files changed, 25 insertions(+), 100 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 6896b4ff05..350cd611c6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -18,10 +18,8 @@ import ( morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/encoding/address" io2 "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" @@ -33,7 +31,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) const ( @@ -115,28 +112,13 @@ func (c *initializeContext) deployNNS(method string) error { } params := getContractDeployParameters(cs, nil) - signer := transaction.Signer{ - Account: c.CommitteeAcc.Contract.ScriptHash(), - Scopes: transaction.CalledByEntry, - } invokeHash := management.Hash if method == updateMethodName { invokeHash = nnsCs.Hash } - res, err := invokeFunction(c.Client, invokeHash, method, params, []transaction.Signer{signer}) - if err != nil { - return fmt.Errorf("can't deploy NNS contract: %w", err) - } - if res.State != vmstate.Halt.String() { - return fmt.Errorf("can't deploy NNS contract: %s", res.FaultException) - } - - tx, err := c.Client.CreateTxFromScript(res.Script, c.CommitteeAcc, res.GasConsumed, 0, []rpcclient.SignerAccount{{ - Signer: signer, - Account: c.CommitteeAcc, - }}) + tx, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) if err != nil { return fmt.Errorf("failed to create deploy tx for %s: %w", nnsContract, err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go index 60bb7f8ed7..92145a7967 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go @@ -10,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" @@ -43,12 +44,12 @@ func (c *initializeContext) registerCandidateRange(start, end int) error { panic(fmt.Sprintf("BUG: %v", w.Err)) } - signers := []rpcclient.SignerAccount{{ + signers := []actor.SignerAccount{{ Signer: c.getSigner(false, c.CommitteeAcc), Account: c.CommitteeAcc, }} for _, acc := range c.Accounts[start:end] { - signers = append(signers, rpcclient.SignerAccount{ + signers = append(signers, actor.SignerAccount{ Signer: transaction.Signer{ Account: acc.Contract.ScriptHash(), Scopes: transaction.CustomContracts, @@ -58,7 +59,11 @@ func (c *initializeContext) registerCandidateRange(start, end int) error { }) } - tx, err := c.Client.CreateTxFromScript(w.Bytes(), c.CommitteeAcc, -1, 0, signers) + act, err := actor.New(c.Client, signers) + if err != nil { + return fmt.Errorf("can't create actor: %w", err) + } + tx, err := act.MakeRun(w.Bytes()) if err != nil { return fmt.Errorf("can't create tx: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index 45db6489f2..3d214d0cf8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" @@ -61,13 +62,7 @@ func (c *initializeContext) transferFunds() error { }, ) - tx, err := createNEP17MultiTransferTx(c.Client, c.ConsensusAcc, 0, transfers, []rpcclient.SignerAccount{{ - Signer: transaction.Signer{ - Account: c.ConsensusAcc.Contract.ScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: c.ConsensusAcc, - }}) + tx, err := createNEP17MultiTransferTx(c.Client, c.ConsensusAcc, transfers) if err != nil { return fmt.Errorf("can't create transfer transaction: %w", err) } @@ -156,11 +151,11 @@ func (c *initializeContext) transferGASToProxy() error { return err } - tx, err := createNEP17MultiTransferTx(c.Client, c.CommitteeAcc, 0, []rpcclient.TransferTarget{{ + tx, err := createNEP17MultiTransferTx(c.Client, c.CommitteeAcc, []rpcclient.TransferTarget{{ Token: gas.Hash, Address: proxyCs.Hash, Amount: initialProxyGASAmount, - }}, nil) + }}) if err != nil { return err } @@ -172,8 +167,8 @@ func (c *initializeContext) transferGASToProxy() error { return c.awaitTx() } -func createNEP17MultiTransferTx(c Client, acc *wallet.Account, netFee int64, - recipients []rpcclient.TransferTarget, cosigners []rpcclient.SignerAccount) (*transaction.Transaction, error) { +func createNEP17MultiTransferTx(c Client, acc *wallet.Account, + recipients []rpcclient.TransferTarget) (*transaction.Transaction, error) { from := acc.Contract.ScriptHash() w := io.NewBufBinWriter() @@ -185,11 +180,18 @@ func createNEP17MultiTransferTx(c Client, acc *wallet.Account, netFee int64, if w.Err != nil { return nil, fmt.Errorf("failed to create transfer script: %w", w.Err) } - return c.CreateTxFromScript(w.Bytes(), acc, -1, netFee, append([]rpcclient.SignerAccount{{ + + signers := []actor.SignerAccount{{ Signer: transaction.Signer{ - Account: from, + Account: acc.Contract.ScriptHash(), Scopes: transaction.CalledByEntry, }, Account: acc, - }}, cosigners...)) + }} + + act, err := actor.New(c, signers) + if err != nil { + return nil, fmt.Errorf("can't create actor: %w", err) + } + return act.MakeRun(w.Bytes()) } diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/local_client.go index b00eca6b4b..24dcb7dec8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/local_client.go @@ -21,7 +21,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -129,39 +128,6 @@ func (l *localClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*resul return &a, nil } -func (l *localClient) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee int64, netFee int64, cosigners []rpcclient.SignerAccount) (*transaction.Transaction, error) { - signers, accounts, err := getSigners(acc, cosigners) - if err != nil { - return nil, fmt.Errorf("failed to construct tx signers: %w", err) - } - if sysFee < 0 { - res, err := l.InvokeScript(script, signers) - if err != nil { - return nil, fmt.Errorf("can't add system fee to transaction: %w", err) - } - if res.State != "HALT" { - return nil, fmt.Errorf("can't add system fee to transaction: bad vm state: %s due to an error: %s", res.State, res.FaultException) - } - sysFee = res.GasConsumed - } - - tx := transaction.New(script, sysFee) - tx.Signers = signers - tx.ValidUntilBlock = l.bc.BlockHeight() + 2 - tx.Scripts = make([]transaction.Witness, len(accounts)) - for i := range tx.Scripts { - tx.Scripts[i].VerificationScript = accounts[i].Contract.Script - } - - fee, err := l.CalculateNetworkFee(tx) - if err != nil { - return nil, fmt.Errorf("failed to add network fee: %w", err) - } - - tx.NetworkFee = fee + netFee - return tx, nil -} - func (l *localClient) GetCommittee() (keys.PublicKeys, error) { // not used by `morph init` command panic("unexpected call") @@ -293,35 +259,6 @@ func (l *localClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, e return netFee, nil } -// getSigners returns an array of transaction signers and corresponding accounts from -// given sender and cosigners. If cosigners list already contains sender, the sender -// will be placed at the start of the list. -// Copied from neo-go with minor corrections: -// https://github.com/nspcc-dev/neo-go/blob/6ff11baa1b9e4c71ef0d1de43b92a8c541ca732c/pkg/rpc/client/rpc.go#L735 -func getSigners(sender *wallet.Account, cosigners []rpcclient.SignerAccount) ([]transaction.Signer, []*wallet.Account, error) { - var ( - signers []transaction.Signer - accounts []*wallet.Account - ) - - from := sender.Contract.ScriptHash() - s := transaction.Signer{ - Account: from, - Scopes: transaction.None, - } - for _, c := range cosigners { - if c.Signer.Account == from { - s = c.Signer - continue - } - signers = append(signers, c.Signer) - accounts = append(accounts, c.Account) - } - signers = append([]transaction.Signer{s}, signers...) - accounts = append([]*wallet.Account{sender}, accounts...) - return signers, accounts, nil -} - func (l *localClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) { lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash()) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/n3client.go index d99715592f..3550895c37 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/n3client.go @@ -29,7 +29,6 @@ type Client interface { GetNativeContracts() ([]state.NativeContract, error) GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error) GetVersion() (*result.Version, error) - CreateTxFromScript([]byte, *wallet.Account, int64, int64, []rpcclient.SignerAccount) (*transaction.Transaction, error) SendRawTransaction(*transaction.Transaction) (util.Uint256, error) GetCommittee() (keys.PublicKeys, error) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) From 4239f1e81771affc467ff93376f5d94cf85512be Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 24 Oct 2023 15:20:38 +0300 Subject: [PATCH 0092/1413] [#750] adm: Drop deprecated rpcclient.TransferTarget We do not use `nep17` wrapper, because transfers of different tokens are possible in a single transaction. Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize_transfer.go | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index 3d214d0cf8..12b94a2ed6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -7,13 +7,13 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" scContext "github.com/nspcc-dev/neo-go/pkg/smartcontract/context" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/wallet" @@ -36,11 +36,11 @@ func (c *initializeContext) transferFunds() error { return err } - var transfers []rpcclient.TransferTarget + var transfers []transferTarget for _, acc := range c.Accounts { to := acc.Contract.ScriptHash() transfers = append(transfers, - rpcclient.TransferTarget{ + transferTarget{ Token: gas.Hash, Address: to, Amount: initialAlphabetGASAmount, @@ -50,12 +50,12 @@ func (c *initializeContext) transferFunds() error { // It is convenient to have all funds at the committee account. transfers = append(transfers, - rpcclient.TransferTarget{ + transferTarget{ Token: gas.Hash, Address: c.CommitteeAcc.Contract.ScriptHash(), Amount: (gasInitialTotalSupply - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2, }, - rpcclient.TransferTarget{ + transferTarget{ Token: neo.Hash, Address: c.CommitteeAcc.Contract.ScriptHash(), Amount: native.NEOTotalSupply, @@ -151,7 +151,7 @@ func (c *initializeContext) transferGASToProxy() error { return err } - tx, err := createNEP17MultiTransferTx(c.Client, c.CommitteeAcc, []rpcclient.TransferTarget{{ + tx, err := createNEP17MultiTransferTx(c.Client, c.CommitteeAcc, []transferTarget{{ Token: gas.Hash, Address: proxyCs.Hash, Amount: initialProxyGASAmount, @@ -167,8 +167,14 @@ func (c *initializeContext) transferGASToProxy() error { return c.awaitTx() } -func createNEP17MultiTransferTx(c Client, acc *wallet.Account, - recipients []rpcclient.TransferTarget) (*transaction.Transaction, error) { +type transferTarget struct { + Token util.Uint160 + Address util.Uint160 + Amount int64 + Data any +} + +func createNEP17MultiTransferTx(c Client, acc *wallet.Account, recipients []transferTarget) (*transaction.Transaction, error) { from := acc.Contract.ScriptHash() w := io.NewBufBinWriter() From 2dbf5c612ad69f48dabe87b6dca79ab931e1d148 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Oct 2023 10:30:13 +0300 Subject: [PATCH 0093/1413] [#752] go.mod: Update neo-go to v0.103.0 Signed-off-by: Evgenii Stratonikov --- go.mod | 25 ++++++++++++------------- go.sum | 57 +++++++++++++++++++++++++++++---------------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/go.mod b/go.mod index a97e04f334..0d2d67ca04 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.9.0 github.com/nats-io/nats.go v1.27.1 - github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5 + github.com/nspcc-dev/neo-go v0.103.0 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.7.5 github.com/paulmach/orb v0.9.2 @@ -34,10 +34,10 @@ require ( go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 go.uber.org/zap v1.24.0 - golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df + golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 golang.org/x/sync v0.3.0 - golang.org/x/term v0.9.0 - google.golang.org/grpc v1.56.1 + golang.org/x/term v0.13.0 + google.golang.org/grpc v1.57.0 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -62,7 +62,7 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.11.0 // indirect + github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -97,7 +97,7 @@ require ( github.com/nats-io/nkeys v0.4.4 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 // indirect - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5 // indirect + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5 // indirect github.com/nspcc-dev/rfc6979 v0.2.0 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -123,13 +123,12 @@ require ( go.opentelemetry.io/proto/otlp v0.20.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.10.0 // indirect - golang.org/x/net v0.11.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.10.0 // indirect - google.golang.org/genproto v0.0.0-20230628200519-e449d1ea0e82 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230628200519-e449d1ea0e82 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230628200519-e449d1ea0e82 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 29134ea577..31c705226a 100644 --- a/go.sum +++ b/go.sum @@ -485,8 +485,8 @@ github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWH github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.9.1/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4= -github.com/consensys/gnark-crypto v0.11.0 h1:QqzHQlwEqlQr5jfWblGDkwlKHpT+4QodYqqExkAtyks= -github.com/consensys/gnark-crypto v0.11.0/go.mod h1:Iq/P3HHl0ElSjsg2E1gsMwhAyxnxoKK5nVyZKd+/KhU= +github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc= +github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= @@ -739,13 +739,13 @@ github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3v github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= @@ -811,13 +811,15 @@ github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1: github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= github.com/nspcc-dev/neo-go v0.99.2/go.mod h1:9P0yWqhZX7i/ChJ+zjtiStO1uPTolPFUM+L5oNznU8E= github.com/nspcc-dev/neo-go v0.100.1/go.mod h1:Nnp7F4e9IBccsgtCeLtUWV+0T6gk1PtP5HRtA13hUfc= -github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5 h1:AXI2upTPeTqX+n4xrBEzPATgEviOM/Prg6UQ6KDm+DU= github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5/go.mod h1:Z0kpjwnTJj/ik/X6z18xjCL0X2+RNbqlnhKrl+MYgP8= +github.com/nspcc-dev/neo-go v0.103.0 h1:UVyWPhzZdfYFG35ORP3FRDLh8J/raRQ6m8SptDdlgfM= +github.com/nspcc-dev/neo-go v0.103.0/go.mod h1:x+wmcYqpZYJwLp1l/pHZrqNp3RSWlkMymWGDij3/OPo= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220809123759-3094d3e0c14b/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5 h1:/d7mY5hYlNhmEXexKcyqSR0b1Hdl5hf/c5o8Vi/1vt4= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5 h1:09CpI5uwsxb1EeFPIKQRwwWlfCmDD/Dwwh01lPiQScM= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM= @@ -1052,8 +1054,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1066,8 +1068,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20221227203929-1b447090c38c/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= -golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1099,7 +1101,7 @@ golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1163,8 +1165,8 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= -golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1306,8 +1308,8 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1316,8 +1318,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1332,8 +1334,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1402,7 +1404,7 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1582,12 +1584,11 @@ google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZV google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230628200519-e449d1ea0e82 h1:Wdfp5Hc1bqGCWYZNrir4A1Jb+SmVaV2j1DL/pbMMTGI= -google.golang.org/genproto v0.0.0-20230628200519-e449d1ea0e82/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= -google.golang.org/genproto/googleapis/api v0.0.0-20230628200519-e449d1ea0e82 h1:iI5Fmsfz4zDINYxJLxn2YChI//ypkHM/KuVSvlN7ZXk= -google.golang.org/genproto/googleapis/api v0.0.0-20230628200519-e449d1ea0e82/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230628200519-e449d1ea0e82 h1:6b+zGQBiXFlAMpQr+cCarAdrZD4QgXSG7uUZadYysgg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230628200519-e449d1ea0e82/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e h1:xIXmWJ303kJCuogpj0bHq+dcjcZHU+XFyc1I0Yl9cRg= +google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= +google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1627,8 +1628,8 @@ google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ= -google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= From 4f62fded0106e2b22a828bcc96b60e334d937735 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Oct 2023 10:33:06 +0300 Subject: [PATCH 0094/1413] [#752] go.mod: Update dependencies Signed-off-by: Evgenii Stratonikov --- go.mod | 22 ++++++++++------------ go.sum | 48 +++++++++++++++++++++++------------------------- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index 0d2d67ca04..bbba2e3c3a 100644 --- a/go.mod +++ b/go.mod @@ -13,9 +13,9 @@ require ( github.com/chzyer/readline v1.5.1 github.com/dgraph-io/ristretto v0.1.1 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 - github.com/google/uuid v1.3.0 - github.com/hashicorp/golang-lru/v2 v2.0.4 - github.com/klauspost/compress v1.16.6 + github.com/google/uuid v1.3.1 + github.com/hashicorp/golang-lru/v2 v2.0.7 + github.com/klauspost/compress v1.17.2 github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.9.0 @@ -33,11 +33,11 @@ require ( go.etcd.io/bbolt v1.3.7 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 - go.uber.org/zap v1.24.0 - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 - golang.org/x/sync v0.3.0 + go.uber.org/zap v1.26.0 + golang.org/x/exp v0.0.0-20231006140011-7918f672742d + golang.org/x/sync v0.4.0 golang.org/x/term v0.13.0 - google.golang.org/grpc v1.57.0 + google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -45,7 +45,7 @@ require ( require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/flatbuffers v1.12.1 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -56,7 +56,6 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 // indirect git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect - github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect @@ -121,14 +120,13 @@ require ( go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/sdk v1.16.0 // indirect go.opentelemetry.io/proto/otlp v0.20.0 // indirect - go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.14.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 31c705226a..bb5757b456 100644 --- a/go.sum +++ b/go.sum @@ -427,8 +427,6 @@ github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/g github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= -github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -561,8 +559,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -646,8 +644,9 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= @@ -680,8 +679,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru/v2 v2.0.4 h1:7GHuZcgid37q8o5i3QI9KMT4nCWQQ3Kx3Ov6bb9MfK0= -github.com/hashicorp/golang-lru/v2 v2.0.4/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= @@ -714,8 +713,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.6 h1:91SKEy4K37vkp255cJ8QesJhjyRO0hn9i9G0GoUwLsk= -github.com/klauspost/compress v1.16.6/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= +github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1021,8 +1020,6 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= @@ -1033,8 +1030,9 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -1068,8 +1066,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20221227203929-1b447090c38c/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1101,7 +1099,7 @@ golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1208,8 +1206,8 @@ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1404,7 +1402,7 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1584,11 +1582,11 @@ google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZV google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e h1:xIXmWJ303kJCuogpj0bHq+dcjcZHU+XFyc1I0Yl9cRg= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= +google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a h1:fwgW9j3vHirt4ObdHoYNwuO24BEZjSzbh+zPaNWoiY8= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1628,8 +1626,8 @@ google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= From 695031296706487052b61918243356a6538ea220 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Oct 2023 11:32:53 +0300 Subject: [PATCH 0095/1413] [#752] morph: Drop loop copy kludges Signed-off-by: Evgenii Stratonikov --- pkg/morph/subscriber/subscriber.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/morph/subscriber/subscriber.go b/pkg/morph/subscriber/subscriber.go index 7f3c913857..c291988fd9 100644 --- a/pkg/morph/subscriber/subscriber.go +++ b/pkg/morph/subscriber/subscriber.go @@ -310,7 +310,6 @@ func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotific // notification events restoration for contract := range s.subscribedEvents { - contract := contract // See https://github.com/nspcc-dev/neo-go/issues/2890 _, err = s.client.ReceiveExecutionNotifications(contract, notifCh) if err != nil { s.log.Error(logs.ClientCouldNotRestoreNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) @@ -320,7 +319,6 @@ func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotific // notary notification events restoration for signer := range s.subscribedNotaryEvents { - signer := signer // See https://github.com/nspcc-dev/neo-go/issues/2890 _, err = s.client.ReceiveNotaryRequests(signer, notaryCh) if err != nil { s.log.Error(logs.ClientCouldNotRestoreNotaryNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) From 0a9830564ff2c91d8777156389c3aaf3bdfb2b8a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Oct 2023 15:58:22 +0300 Subject: [PATCH 0096/1413] [#752] morph: Adopt neo-go RPC statuses Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/notary.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 17644361a0..0bbe526a67 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -706,13 +706,17 @@ func WithProxyContract(h util.Uint160) NotaryOption { } } -// Neo RPC node can return `core.ErrInvalidAttribute` error with +// Neo RPC node can return `neorpc.ErrInvalidAttribute` error with // `conflicting transaction <> is already on chain` message. This // error is expected and ignored. As soon as main tx persisted on // chain everything is fine. This happens because notary contract // requires 5 out of 7 signatures to send main tx, thus last two // notary requests may be processed after main tx appeared on chain. func alreadyOnChainError(err error) bool { + if !errors.Is(err, neorpc.ErrInvalidAttribute) { + return false + } + const alreadyOnChainErrorMessage = "already on chain" return strings.Contains(err.Error(), alreadyOnChainErrorMessage) From cddc58ace282f74385d065119b779f9e9a5fdf10 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Oct 2023 16:04:21 +0300 Subject: [PATCH 0097/1413] [#752] innerring: Optimize keyPosition() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ old │ new │ │ sec/op │ sec/op vs base │ KeyPosition-8 2771.50n ± 10% 40.32n ± 4% -98.55% (p=0.000 n=10) │ old │ new │ │ B/op │ B/op vs base │ KeyPosition-8 1.531Ki ± 0% 0.000Ki ± 0% -100.00% (p=0.000 n=10) │ old │ new │ │ allocs/op │ allocs/op vs base │ KeyPosition-8 21.00 ± 0% 0.00 ± 0% -100.00% (p=0.000 n=10) ``` Signed-off-by: Evgenii Stratonikov --- pkg/innerring/indexer.go | 4 +--- pkg/innerring/indexer_test.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/pkg/innerring/indexer.go b/pkg/innerring/indexer.go index ac5fb93efb..5d0a87d64b 100644 --- a/pkg/innerring/indexer.go +++ b/pkg/innerring/indexer.go @@ -1,7 +1,6 @@ package innerring import ( - "bytes" "fmt" "sync" "time" @@ -113,10 +112,9 @@ func (s *innerRingIndexer) AlphabetIndex() (int32, error) { // index of the key. func keyPosition(key *keys.PublicKey, list keys.PublicKeys) (result int32) { result = -1 - rawBytes := key.Bytes() for i := range list { - if bytes.Equal(list[i].Bytes(), rawBytes) { + if key.Equal(list[i]) { result = int32(i) break } diff --git a/pkg/innerring/indexer_test.go b/pkg/innerring/indexer_test.go index 1937f7a49e..5bc2cc9881 100644 --- a/pkg/innerring/indexer_test.go +++ b/pkg/innerring/indexer_test.go @@ -223,3 +223,23 @@ func (f *testIRFetcher) InnerRingKeys() (keys.PublicKeys, error) { f.calls.Add(1) return f.keys, f.err } + +func BenchmarkKeyPosition(b *testing.B) { + list := make(keys.PublicKeys, 7) + for i := range list { + p, err := keys.NewPrivateKey() + require.NoError(b, err) + list[i] = p.PublicKey() + } + + key := new(keys.PublicKey) + require.NoError(b, key.DecodeBytes(list[5].Bytes())) + + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + if keyPosition(key, list) != 5 { + b.FailNow() + } + } +} From 9f7c2d88106151f15fd134c3288e557b93c91976 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Oct 2023 16:06:12 +0300 Subject: [PATCH 0098/1413] [#752] innerring: Simplify keyPosition() Signed-off-by: Evgenii Stratonikov --- pkg/innerring/indexer.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg/innerring/indexer.go b/pkg/innerring/indexer.go index 5d0a87d64b..45135a57b3 100644 --- a/pkg/innerring/indexer.go +++ b/pkg/innerring/indexer.go @@ -110,15 +110,11 @@ func (s *innerRingIndexer) AlphabetIndex() (int32, error) { // keyPosition returns "-1" if key is not found in the list, otherwise returns // index of the key. -func keyPosition(key *keys.PublicKey, list keys.PublicKeys) (result int32) { - result = -1 - +func keyPosition(key *keys.PublicKey, list keys.PublicKeys) int32 { for i := range list { if key.Equal(list[i]) { - result = int32(i) - break + return int32(i) } } - - return result + return -1 } From 121f5c4dd8ff5d6d0f6f1d91bcafce2d3712fd4d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 26 Oct 2023 10:36:22 +0300 Subject: [PATCH 0099/1413] [#757] ir: Do not exclude node in maintenance mode from netmap Signed-off-by: Anton Nikiforov --- pkg/innerring/processors/netmap/cleanup_table.go | 5 ++++- .../processors/netmap/cleanup_table_test.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pkg/innerring/processors/netmap/cleanup_table.go b/pkg/innerring/processors/netmap/cleanup_table.go index 80117247dc..705e21d99e 100644 --- a/pkg/innerring/processors/netmap/cleanup_table.go +++ b/pkg/innerring/processors/netmap/cleanup_table.go @@ -24,6 +24,8 @@ type ( epochStamp binNodeInfo []byte + + maintenance bool } ) @@ -58,6 +60,7 @@ func (c *cleanupTable) update(snapshot netmap.NetMap, now uint64) { } access.binNodeInfo = binNodeInfo + access.maintenance = nmNodes[i].IsMaintenance() newMap[keyString] = access } @@ -105,7 +108,7 @@ func (c *cleanupTable) forEachRemoveCandidate(epoch uint64, f func(string) error defer c.Unlock() for keyString, access := range c.lastAccess { - if epoch-access.epoch > c.threshold { + if !access.maintenance && epoch-access.epoch > c.threshold { access.removeFlag = true // set remove flag c.lastAccess[keyString] = access diff --git a/pkg/innerring/processors/netmap/cleanup_table_test.go b/pkg/innerring/processors/netmap/cleanup_table_test.go index 9597103931..ae5620733e 100644 --- a/pkg/innerring/processors/netmap/cleanup_table_test.go +++ b/pkg/innerring/processors/netmap/cleanup_table_test.go @@ -124,6 +124,21 @@ func TestCleanupTable(t *testing.T) { })) require.EqualValues(t, len(infos)-1, cnt) }) + + t.Run("skip maintenance nodes", func(t *testing.T) { + cnt := 0 + infos[1].SetMaintenance() + key := netmap.StringifyPublicKey(infos[1]) + c.update(networkMap, 5) + + require.NoError(t, + c.forEachRemoveCandidate(5, func(s string) error { + cnt++ + require.NotEqual(t, s, key) + return nil + })) + require.EqualValues(t, len(infos)-1, cnt) + }) }) } From d4b6ebe7e797d3f573c6d2b858588be121dabb05 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 27 Oct 2023 09:53:12 +0300 Subject: [PATCH 0100/1413] [#725] writecache: Fix metric values Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/writecache.go | 7 ------- .../writecache/writecachebadger/delete.go | 2 +- .../writecache/writecachebadger/put.go | 2 +- .../writecache/writecachebadger/state.go | 10 ++++++++++ .../writecache/writecachebadger/storage.go | 2 +- .../writecache/writecachebbolt/delete.go | 1 + .../writecache/writecachebbolt/flush.go | 1 + .../writecache/writecachebbolt/put.go | 1 + .../writecache/writecachebbolt/state.go | 1 + .../writecache/writecachebbolt/storage.go | 3 ++- pkg/metrics/writecache.go | 20 ------------------- 11 files changed, 19 insertions(+), 31 deletions(-) diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 2e518c6ffe..00a40105e5 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -68,16 +68,10 @@ func (m *writeCacheMetrics) Get(d time.Duration, success bool, st writecache.Sto func (m *writeCacheMetrics) Delete(d time.Duration, success bool, st writecache.StorageType) { m.metrics.AddMethodDuration(m.shardID, "Delete", success, d, st.String()) - if success { - m.metrics.DecActualCount(m.shardID, st.String()) - } } func (m *writeCacheMetrics) Put(d time.Duration, success bool, st writecache.StorageType) { m.metrics.AddMethodDuration(m.shardID, "Put", success, d, st.String()) - if success { - m.metrics.IncActualCount(m.shardID, st.String()) - } } func (m *writeCacheMetrics) SetEstimateSize(db, fstree uint64) { @@ -99,7 +93,6 @@ func (m *writeCacheMetrics) Flush(success bool, st writecache.StorageType) { } func (m *writeCacheMetrics) Evict(st writecache.StorageType) { - m.metrics.DecActualCount(m.shardID, st.String()) m.metrics.IncOperationCounter(m.shardID, "Evict", metrics.NullBool{}, st.String()) } diff --git a/pkg/local_object_storage/writecache/writecachebadger/delete.go b/pkg/local_object_storage/writecache/writecachebadger/delete.go index afab785479..f96bf27076 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/delete.go +++ b/pkg/local_object_storage/writecache/writecachebadger/delete.go @@ -59,7 +59,7 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { storagelog.OpField("db DELETE"), ) deleted = true - c.objCounters.DecDB() + c.decDB() } return err } diff --git a/pkg/local_object_storage/writecache/writecachebadger/put.go b/pkg/local_object_storage/writecache/writecachebadger/put.go index c03a0d3363..2071ba1d0f 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/put.go +++ b/pkg/local_object_storage/writecache/writecachebadger/put.go @@ -76,7 +76,7 @@ func (c *cache) put(obj objectInfo) error { storagelog.StorageTypeField(wcStorageType), storagelog.OpField("db PUT"), ) - c.objCounters.IncDB() + c.incDB() } return err } diff --git a/pkg/local_object_storage/writecache/writecachebadger/state.go b/pkg/local_object_storage/writecache/writecachebadger/state.go index 994dfa3d57..e098eb0603 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/state.go +++ b/pkg/local_object_storage/writecache/writecachebadger/state.go @@ -55,3 +55,13 @@ func (c *cache) initCounters() error { return nil } + +func (c *cache) incDB() { + c.objCounters.IncDB() + c.metrics.SetActualCounters(c.objCounters.DB(), 0) +} + +func (c *cache) decDB() { + c.objCounters.DecDB() + c.metrics.SetActualCounters(c.objCounters.DB(), 0) +} diff --git a/pkg/local_object_storage/writecache/writecachebadger/storage.go b/pkg/local_object_storage/writecache/writecachebadger/storage.go index 9ff54bee02..04337b7a6f 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/storage.go +++ b/pkg/local_object_storage/writecache/writecachebadger/storage.go @@ -73,7 +73,7 @@ func (c *cache) deleteFromDB(keys []internalKey) []internalKey { } for i := 0; i < errorIndex; i++ { - c.objCounters.DecDB() + c.decDB() c.metrics.Evict(writecache.StorageTypeDB) storagelog.Write(c.log, storagelog.AddressField(keys[i]), diff --git a/pkg/local_object_storage/writecache/writecachebbolt/delete.go b/pkg/local_object_storage/writecache/writecachebbolt/delete.go index e4d9c219f4..15c83eed1a 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/delete.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/delete.go @@ -83,6 +83,7 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { storagelog.OpField("fstree DELETE"), ) deleted = true + // counter changed by fstree c.estimateCacheSize() } return metaerr.Wrap(err) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush.go b/pkg/local_object_storage/writecache/writecachebbolt/flush.go index 393776dd1d..9e46226d1d 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush.go @@ -60,6 +60,7 @@ func (c *cache) runFlushLoop(ctx context.Context) { case <-tt.C: c.flushSmallObjects(ctx) tt.Reset(defaultFlushInterval) + c.estimateCacheSize() case <-ctx.Done(): return } diff --git a/pkg/local_object_storage/writecache/writecachebbolt/put.go b/pkg/local_object_storage/writecache/writecachebbolt/put.go index 1d9957219d..63fa544ed5 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/put.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/put.go @@ -131,6 +131,7 @@ func (c *cache) putBig(ctx context.Context, addr string, prm common.PutPrm) erro storagelog.StorageTypeField(wcStorageType), storagelog.OpField("fstree PUT"), ) + // counter changed by fstree c.estimateCacheSize() return nil diff --git a/pkg/local_object_storage/writecache/writecachebbolt/state.go b/pkg/local_object_storage/writecache/writecachebbolt/state.go index 91d54b0ea0..8749ec6019 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/state.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/state.go @@ -72,5 +72,6 @@ func (c *cache) initCounters() error { return fmt.Errorf("could not read write-cache DB counter: %w", err) } c.objCounters.cDB.Store(inDB) + c.estimateCacheSize() return nil } diff --git a/pkg/local_object_storage/writecache/writecachebbolt/storage.go b/pkg/local_object_storage/writecache/writecachebbolt/storage.go index bbd66d57c6..bff9385dc3 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/storage.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/storage.go @@ -73,7 +73,7 @@ func (c *cache) deleteFromDB(key string) { err := c.db.Batch(func(tx *bbolt.Tx) error { b := tx.Bucket(defaultBucket) key := []byte(key) - recordDeleted = !recordDeleted && b.Get(key) != nil + recordDeleted = b.Get(key) != nil return b.Delete(key) }) @@ -122,6 +122,7 @@ func (c *cache) deleteFromDisk(ctx context.Context, keys []string) []string { storagelog.OpField("fstree DELETE"), ) c.metrics.Evict(writecache.StorageTypeFSTree) + // counter changed by fstree c.estimateCacheSize() } } diff --git a/pkg/metrics/writecache.go b/pkg/metrics/writecache.go index 7e6083a498..c8f815ca54 100644 --- a/pkg/metrics/writecache.go +++ b/pkg/metrics/writecache.go @@ -10,16 +10,10 @@ import ( type WriteCacheMetrics interface { AddMethodDuration(shardID string, method string, success bool, d time.Duration, storageType string) - - IncActualCount(shardID string, storageType string) - DecActualCount(shardID string, storageType string) SetActualCount(shardID string, count uint64, storageType string) - SetEstimateSize(shardID string, size uint64, storageType string) SetMode(shardID string, mode string) - IncOperationCounter(shardID string, operation string, success NullBool, storageType string) - Close(shardID string) } @@ -65,20 +59,6 @@ func (m *writeCacheMetrics) AddMethodDuration(shardID string, method string, suc ).Observe(d.Seconds()) } -func (m *writeCacheMetrics) IncActualCount(shardID string, storageType string) { - m.actualCount.With(prometheus.Labels{ - shardIDLabel: shardID, - storageLabel: storageType, - }).Inc() -} - -func (m *writeCacheMetrics) DecActualCount(shardID string, storageType string) { - m.actualCount.With(prometheus.Labels{ - shardIDLabel: shardID, - storageLabel: storageType, - }).Dec() -} - func (m *writeCacheMetrics) SetActualCount(shardID string, count uint64, storageType string) { m.actualCount.With(prometheus.Labels{ shardIDLabel: shardID, From 869518be0afaf8c717513a634dc8cd2228c466e6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 30 Oct 2023 17:11:04 +0300 Subject: [PATCH 0101/1413] [#728] writecache: Fix Badger writecache race. Signed-off-by: Dmitrii Stepanov --- .../writecachebadger/cachebadger.go | 6 ++++ .../writecache/writecachebadger/gc.go | 31 +++++++++++-------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go index be7046d05d..484f018150 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go +++ b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go @@ -85,6 +85,9 @@ func (c *cache) DumpInfo() writecache.Info { // Open opens and initializes database. Reads object counters from the ObjectCounters instance. func (c *cache) Open(_ context.Context, readOnly bool) error { + c.modeMtx.Lock() + defer c.modeMtx.Unlock() + err := c.openStore(readOnly) if err != nil { return metaerr.Wrap(err) @@ -94,6 +97,9 @@ func (c *cache) Open(_ context.Context, readOnly bool) error { // Init runs necessary services. func (c *cache) Init() error { + c.modeMtx.Lock() + defer c.modeMtx.Unlock() + c.log.Info(logs.WritecacheBadgerInitExperimental) c.metrics.SetMode(c.mode) ctx, cancel := context.WithCancel(context.Background()) diff --git a/pkg/local_object_storage/writecache/writecachebadger/gc.go b/pkg/local_object_storage/writecache/writecachebadger/gc.go index b856efc3df..8937ff2956 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/gc.go +++ b/pkg/local_object_storage/writecache/writecachebadger/gc.go @@ -21,20 +21,25 @@ func (c *cache) runGCLoop(ctx context.Context) { case <-ctx.Done(): return case <-t.C: - // This serves to synchronize the c.db field when changing mode as well. - c.modeMtx.RLock() - ro := c.readOnly() - c.modeMtx.RUnlock() - if ro { - continue - } - - // 0.5 is the recommended value so that write amplification of the value log is 2. - // See https://pkg.go.dev/github.com/dgraph-io/badger/v4#DB.RunValueLogGC for more info. - for c.db.RunValueLogGC(0.5) == nil { - c.log.Debug(logs.WritecacheDBValueLogGCRunCompleted) - } + c.runGC() } } }() } + +func (c *cache) runGC() { + // This serves to synchronize the c.db field when changing mode as well. + c.modeMtx.RLock() + defer c.modeMtx.RUnlock() + + ro := c.readOnly() + if ro { + return + } + + // 0.5 is the recommended value so that write amplification of the value log is 2. + // See https://pkg.go.dev/github.com/dgraph-io/badger/v4#DB.RunValueLogGC for more info. + for c.db.RunValueLogGC(0.5) == nil { + c.log.Debug(logs.WritecacheDBValueLogGCRunCompleted) + } +} From 261d281154e443816baed8ff16b287b4c20bb706 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 30 Oct 2023 10:28:41 +0300 Subject: [PATCH 0102/1413] [#762] go.mod: Update sdk-go Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/internal/client/sdk.go | 1 - cmd/frostfs-cli/modules/accounting/balance.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- pkg/network/cache/multi.go | 1 + 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/sdk.go b/cmd/frostfs-cli/internal/client/sdk.go index 79d3dcb0d3..6923e4f17e 100644 --- a/cmd/frostfs-cli/internal/client/sdk.go +++ b/cmd/frostfs-cli/internal/client/sdk.go @@ -50,7 +50,6 @@ func GetSDKClient(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey ) prmInit.SetDefaultPrivateKey(*key) - prmInit.ResolveFrostFSFailures() prmDial.SetServerURI(addr.URIAddr()) if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 { // In CLI we can only set a timeout for the whole operation. diff --git a/cmd/frostfs-cli/modules/accounting/balance.go b/cmd/frostfs-cli/modules/accounting/balance.go index 5ed8f9403a..8e975fb03a 100644 --- a/cmd/frostfs-cli/modules/accounting/balance.go +++ b/cmd/frostfs-cli/modules/accounting/balance.go @@ -39,7 +39,7 @@ var accountingBalanceCmd = &cobra.Command{ var prm internalclient.BalanceOfPrm prm.SetClient(cli) - prm.SetAccount(idUser) + prm.Account = &idUser res, err := internalclient.BalanceOf(cmd.Context(), prm) commonCmd.ExitOnErr(cmd, "rpc error: %w", err) diff --git a/go.mod b/go.mod index bbba2e3c3a..0c67313639 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231019083813-5804128ff3d5 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231027075445-a02c0bfac885 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index bb5757b456..6fb57f4f4d 100644 --- a/go.sum +++ b/go.sum @@ -393,8 +393,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231019083813-5804128ff3d5 h1:P2HCnBTx+LwhMYSrs4sF8+jHvD1+HdS0fMtUPe2kTns= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231019083813-5804128ff3d5/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231027075445-a02c0bfac885 h1:tbOUgoaN3usFTUA9k62z96uQDRNJUiz9TxzJr1AtSFo= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231027075445-a02c0bfac885/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index d03edd962a..c9b13826ac 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -57,6 +57,7 @@ func (x *multiClient) createForAddress(ctx context.Context, addr network.Address prmDial client.PrmDial ) + prmInit.DisableFrostFSFailuresResolution() prmDial.SetServerURI(addr.URIAddr()) if x.opts.Key != nil { From b8f79f422771397491cfd9c9f87341bde8ddc12d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 31 Oct 2023 14:21:42 +0300 Subject: [PATCH 0103/1413] [#633] shard/test: Fix race conditions in TestCounters() Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/metrics_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 23721af6ec..107938139e 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -268,6 +268,7 @@ func shardWithMetrics(t *testing.T, path string) (*Shard, *metricsStore) { meta.WithPath(filepath.Join(path, "meta")), meta.WithEpochState(epochState{})), WithMetricsWriter(mm), + WithGCRemoverSleepInterval(time.Hour), ) require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) From 00aa6d974990b5a84a2fcdff1f9e91d2f6b30011 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 31 Oct 2023 14:16:34 +0300 Subject: [PATCH 0104/1413] [#633] shard/test: Fix TestCounters() Introduced in 362f24953a7, forgotten to be changed because test generator didn't provide payload size. Signed-off-by: Evgenii Stratonikov --- .../internal/testutil/object.go | 1 + .../shard/metrics_test.go | 25 +++++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/internal/testutil/object.go b/pkg/local_object_storage/internal/testutil/object.go index 573a099ff7..60e9211d5d 100644 --- a/pkg/local_object_storage/internal/testutil/object.go +++ b/pkg/local_object_storage/internal/testutil/object.go @@ -49,6 +49,7 @@ func GenerateObjectWithCIDWithPayload(cnr cid.ID, data []byte) *objectSDK.Object obj.SetContainerID(cnr) obj.SetVersion(&ver) obj.SetPayload(data) + obj.SetPayloadSize(uint64(len(data))) obj.SetPayloadChecksum(csum) obj.SetPayloadHomomorphicHash(csumTZ) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 107938139e..7724aa2224 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -5,6 +5,7 @@ import ( "path/filepath" "sync" "testing" + "time" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" @@ -151,11 +152,11 @@ func TestCounters(t *testing.T) { var totalPayload int64 - expectedSizes := make(map[string]int64) + expectedLogicalSizes := make(map[string]int64) for i := range oo { cnr, _ := oo[i].ContainerID() oSize := int64(oo[i].PayloadSize()) - expectedSizes[cnr.EncodeToString()] += oSize + expectedLogicalSizes[cnr.EncodeToString()] += oSize totalPayload += oSize } @@ -170,7 +171,7 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) require.Equal(t, uint64(objNumber), mm.getObjectCounter(logical)) - require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) t.Run("inhume_GC", func(t *testing.T) { @@ -182,11 +183,15 @@ func TestCounters(t *testing.T) { _, err := sh.Inhume(context.Background(), prm) require.NoError(t, err) + + cid, ok := oo[i].ContainerID() + require.True(t, ok) + expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) } require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) require.Equal(t, uint64(objNumber-inhumedNumber), mm.getObjectCounter(logical)) - require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) oo = oo[inhumedNumber:] @@ -205,9 +210,15 @@ func TestCounters(t *testing.T) { _, err := sh.Inhume(context.Background(), prm) require.NoError(t, err) + for i := 0; i < inhumedNumber; i++ { + cid, ok := oo[i].ContainerID() + require.True(t, ok) + expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) + } + require.Equal(t, phy, mm.getObjectCounter(physical)) require.Equal(t, logic-uint64(inhumedNumber), mm.getObjectCounter(logical)) - require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) oo = oo[inhumedNumber:] @@ -233,9 +244,9 @@ func TestCounters(t *testing.T) { totalRemovedpayload += removedPayload cnr, _ := oo[i].ContainerID() - expectedSizes[cnr.EncodeToString()] -= int64(removedPayload) + expectedLogicalSizes[cnr.EncodeToString()] -= int64(removedPayload) } - require.Equal(t, expectedSizes, mm.containerSizes()) + require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload-int64(totalRemovedpayload), mm.payloadSize()) }) } From 79088baa06bb0ee0da9489f72a8cdad5ea77e477 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 31 Oct 2023 14:56:55 +0300 Subject: [PATCH 0105/1413] [#772] node: Apply gofumpt Signed-off-by: Dmitrii Stepanov --- .../internal/modules/config/config.go | 4 ++-- .../internal/modules/morph/generate.go | 2 +- .../internal/modules/morph/local_client.go | 2 +- cmd/frostfs-adm/internal/modules/root.go | 16 +++++++--------- .../internal/modules/storagecfg/root.go | 2 +- cmd/frostfs-cli/modules/acl/extended/create.go | 2 +- cmd/frostfs-cli/modules/bearer/create.go | 2 +- cmd/frostfs-cli/modules/container/get.go | 2 +- cmd/frostfs-cli/modules/container/get_eacl.go | 2 +- cmd/frostfs-cli/modules/container/nodes.go | 2 +- cmd/frostfs-cli/modules/object/get.go | 2 +- cmd/frostfs-cli/modules/object/nodes.go | 5 +++-- cmd/frostfs-cli/modules/object/root.go | 3 ++- cmd/frostfs-cli/modules/session/create.go | 2 +- cmd/frostfs-cli/modules/util/convert_eacl.go | 2 +- cmd/frostfs-cli/modules/util/keyer.go | 2 +- cmd/frostfs-cli/modules/util/sign_bearer.go | 2 +- cmd/frostfs-cli/modules/util/sign_session.go | 2 +- cmd/frostfs-ir/config.go | 2 +- cmd/frostfs-lens/internal/printers.go | 2 +- .../config/apiclient/config_test.go | 2 +- cmd/frostfs-node/config/config.go | 1 - cmd/frostfs-node/config/configdir_test.go | 4 ++-- .../config/contracts/config_test.go | 2 +- cmd/frostfs-node/config/control/config_test.go | 2 +- cmd/frostfs-node/config/engine/config_test.go | 14 +++++++------- .../engine/shard/blobstor/storage/config.go | 2 +- .../config/engine/shard/boltdb/boltdb.go | 2 +- .../config/engine/shard/pilorama/config.go | 2 +- cmd/frostfs-node/config/grpc/config_test.go | 2 +- cmd/frostfs-node/config/logger/config_test.go | 2 +- cmd/frostfs-node/config/metrics/config_test.go | 2 +- cmd/frostfs-node/config/morph/config_test.go | 12 +++++------- cmd/frostfs-node/config/node/config_test.go | 2 +- cmd/frostfs-node/config/object/config_test.go | 2 +- cmd/frostfs-node/config/policer/config_test.go | 2 +- .../config/profiler/config_test.go | 2 +- .../config/replicator/config_test.go | 2 +- cmd/frostfs-node/config/tree/config_test.go | 2 +- cmd/frostfs-node/morph.go | 3 ++- cmd/frostfs-node/object.go | 9 ++++++--- cmd/frostfs-node/tracing.go | 2 +- cmd/frostfs-node/validate.go | 2 +- cmd/internal/common/netmap.go | 3 ++- pkg/core/client/util.go | 6 ++++-- pkg/core/object/sender_classifier.go | 9 ++++++--- pkg/innerring/blocktimer_test.go | 1 + pkg/innerring/config/fee_test.go | 1 - pkg/innerring/initialization.go | 6 ++++-- pkg/innerring/innerring.go | 3 ++- .../processors/alphabet/handlers_test.go | 1 + .../processors/balance/handlers_test.go | 3 +-- .../processors/container/handlers_test.go | 1 + .../processors/frostfs/handlers_test.go | 6 ++++-- .../processors/governance/handlers_test.go | 2 +- .../processors/netmap/handlers_test.go | 3 +++ pkg/local_object_storage/blobovnicza/delete.go | 3 +-- pkg/local_object_storage/blobovnicza/exists.go | 4 +--- .../blobovnicza/iterate.go | 3 +-- pkg/local_object_storage/blobovnicza/put.go | 3 +-- .../blobstor/blobovniczatree/active.go | 4 ++-- .../blobstor/blobovniczatree/cache.go | 2 +- .../blobstor/blobovniczatree/control.go | 4 ++-- .../blobstor/blobovniczatree/exists_test.go | 2 +- .../blobstor/blobovniczatree/manager.go | 6 ++++-- .../blobstor/blobovniczatree/option.go | 2 +- .../blobstor/fstree/fstree.go | 2 +- .../blobstor/generic_test.go | 1 - pkg/local_object_storage/blobstor/get.go | 4 +--- pkg/local_object_storage/blobstor/get_range.go | 4 +--- .../blobstor/internal/blobstortest/iterate.go | 2 +- pkg/local_object_storage/blobstor/logger.go | 6 ++++-- pkg/local_object_storage/engine/control.go | 4 ++-- .../engine/control_test.go | 5 ++--- pkg/local_object_storage/engine/engine.go | 6 ++++-- pkg/local_object_storage/engine/engine_test.go | 9 +++++---- pkg/local_object_storage/engine/error_test.go | 4 ++-- pkg/local_object_storage/engine/evacuate.go | 13 ++++++++----- .../engine/evacuate_test.go | 4 ++-- pkg/local_object_storage/engine/list_test.go | 5 +++-- .../internal/metaerr/error_test.go | 1 + pkg/local_object_storage/metabase/children.go | 1 - pkg/local_object_storage/metabase/counter.go | 6 ++++-- pkg/local_object_storage/metabase/db_test.go | 2 +- pkg/local_object_storage/metabase/delete.go | 4 ++-- pkg/local_object_storage/metabase/expired.go | 1 - pkg/local_object_storage/metabase/list.go | 2 +- pkg/local_object_storage/metabase/list_test.go | 1 - pkg/local_object_storage/metabase/lock.go | 1 - pkg/local_object_storage/metabase/put.go | 3 ++- .../metabase/version_test.go | 2 +- pkg/local_object_storage/metrics/fstree.go | 6 ++++++ pkg/local_object_storage/pilorama/boltdb.go | 3 +++ pkg/local_object_storage/pilorama/forest.go | 5 ++++- .../pilorama/forest_test.go | 18 ++++++++++++------ pkg/local_object_storage/pilorama/meta_test.go | 6 ++++-- .../shard/gc_internal_test.go | 12 ++++++------ pkg/local_object_storage/shard/reload_test.go | 6 ++++-- pkg/local_object_storage/shard/shard_test.go | 3 ++- .../writecache/writecachebbolt/cachebbolt.go | 4 +--- .../writecache/writecachebbolt/state.go | 2 +- pkg/metrics/replicator.go | 2 -- pkg/morph/client/constructor.go | 4 +--- pkg/morph/client/container/client.go | 4 +--- pkg/morph/client/netmap/peer.go | 2 +- pkg/morph/event/frostfs/ir_update_test.go | 12 +++++------- pkg/morph/event/listener_test.go | 2 +- pkg/morph/event/utils.go | 1 - pkg/morph/subscriber/subscriber.go | 3 ++- pkg/network/transport/netmap/grpc/service.go | 3 ++- pkg/services/container/morph/executor_test.go | 3 ++- pkg/services/control/service_test.go | 1 + pkg/services/control/types_test.go | 3 ++- pkg/services/netmap/executor.go | 6 ++++-- pkg/services/netmap/sign.go | 3 ++- pkg/services/object/acl/v2/errors.go | 6 ++++-- pkg/services/object/acl/v2/service.go | 12 ++++++++---- pkg/services/object/delete/service.go | 3 ++- pkg/services/object/get/assembler.go | 3 ++- pkg/services/object/get/get.go | 1 + pkg/services/object/get/get_test.go | 10 +++------- pkg/services/object/internal/key.go | 3 ++- pkg/services/object/put/service.go | 3 ++- pkg/services/object/put/single.go | 6 ++++-- pkg/services/object/search/service.go | 3 ++- pkg/services/object/util/prm.go | 3 ++- pkg/services/policer/check.go | 9 +++++---- .../storage/persistent/executor_test.go | 4 ++-- .../session/storage/persistent/storage.go | 2 +- pkg/services/tree/getsubtree_test.go | 6 ++++-- pkg/services/tree/signature.go | 14 +++++++++----- pkg/services/tree/sync.go | 14 +++++++------- pkg/util/locode/table/csv/opts.go | 2 +- pkg/util/os.go | 2 +- pkg/util/state/storage.go | 2 +- scripts/export-metrics/main.go | 2 +- 136 files changed, 293 insertions(+), 239 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/config/config.go b/cmd/frostfs-adm/internal/modules/config/config.go index 9dfab9f850..dd98a98b24 100644 --- a/cmd/frostfs-adm/internal/modules/config/config.go +++ b/cmd/frostfs-adm/internal/modules/config/config.go @@ -50,12 +50,12 @@ func initConfig(cmd *cobra.Command, _ []string) error { } pathDir := filepath.Dir(configPath) - err = os.MkdirAll(pathDir, 0700) + err = os.MkdirAll(pathDir, 0o700) if err != nil { return fmt.Errorf("create dir %s: %w", pathDir, err) } - f, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_SYNC, 0600) + f, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC|os.O_SYNC, 0o600) if err != nil { return fmt.Errorf("open %s: %w", configPath, err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate.go index 55321582b5..b8e0069624 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate.go @@ -76,7 +76,7 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er } p := filepath.Join(walletDir, innerring.GlagoliticLetter(i).String()+".json") - f, err := os.OpenFile(p, os.O_CREATE, 0644) + f, err := os.OpenFile(p, os.O_CREATE, 0o644) if err != nil { return nil, fmt.Errorf("can't create wallet file: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/local_client.go index 24dcb7dec8..1a723042c5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/local_client.go @@ -83,7 +83,7 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet go bc.Run() if cmd.Name() != "init" { - f, err := os.OpenFile(dumpPath, os.O_RDONLY, 0600) + f, err := os.OpenFile(dumpPath, os.O_RDONLY, 0o600) if err != nil { return nil, fmt.Errorf("can't open local dump: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/root.go b/cmd/frostfs-adm/internal/modules/root.go index 0fa0f7f693..8595483ab9 100644 --- a/cmd/frostfs-adm/internal/modules/root.go +++ b/cmd/frostfs-adm/internal/modules/root.go @@ -15,16 +15,14 @@ import ( "github.com/spf13/viper" ) -var ( - rootCmd = &cobra.Command{ - Use: "frostfs-adm", - Short: "FrostFS Administrative Tool", - Long: `FrostFS Administrative Tool provides functions to setup and +var rootCmd = &cobra.Command{ + Use: "frostfs-adm", + Short: "FrostFS Administrative Tool", + Long: `FrostFS Administrative Tool provides functions to setup and manage FrostFS network deployment.`, - RunE: entryPoint, - SilenceUsage: true, - } -) + RunE: entryPoint, + SilenceUsage: true, +} func init() { cobra.OnInitialize(func() { initConfig(rootCmd) }) diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/root.go b/cmd/frostfs-adm/internal/modules/storagecfg/root.go index 90edf7d751..127272da59 100644 --- a/cmd/frostfs-adm/internal/modules/storagecfg/root.go +++ b/cmd/frostfs-adm/internal/modules/storagecfg/root.go @@ -145,7 +145,7 @@ func storageConfig(cmd *cobra.Command, args []string) { } out := applyTemplate(c) - fatalOnErr(os.WriteFile(outPath, out, 0644)) + fatalOnErr(os.WriteFile(outPath, out, 0o644)) cmd.Println("Node is ready for work! Run `frostfs-node -config " + outPath + "`") } diff --git a/cmd/frostfs-cli/modules/acl/extended/create.go b/cmd/frostfs-cli/modules/acl/extended/create.go index 7da26f8ebc..59dfabba25 100644 --- a/cmd/frostfs-cli/modules/acl/extended/create.go +++ b/cmd/frostfs-cli/modules/acl/extended/create.go @@ -106,7 +106,7 @@ func createEACL(cmd *cobra.Command, _ []string) { return } - err = os.WriteFile(outArg, buf.Bytes(), 0644) + err = os.WriteFile(outArg, buf.Bytes(), 0o644) if err != nil { cmd.PrintErrln(err) os.Exit(1) diff --git a/cmd/frostfs-cli/modules/bearer/create.go b/cmd/frostfs-cli/modules/bearer/create.go index b85115047f..8a7500db30 100644 --- a/cmd/frostfs-cli/modules/bearer/create.go +++ b/cmd/frostfs-cli/modules/bearer/create.go @@ -130,6 +130,6 @@ func createToken(cmd *cobra.Command, _ []string) { } out, _ := cmd.Flags().GetString(outFlag) - err = os.WriteFile(out, data, 0644) + err = os.WriteFile(out, data, 0o644) commonCmd.ExitOnErr(cmd, "can't write token to file: %w", err) } diff --git a/cmd/frostfs-cli/modules/container/get.go b/cmd/frostfs-cli/modules/container/get.go index f0590c7a13..cd920f0c47 100644 --- a/cmd/frostfs-cli/modules/container/get.go +++ b/cmd/frostfs-cli/modules/container/get.go @@ -51,7 +51,7 @@ var getContainerInfoCmd = &cobra.Command{ data = cnr.Marshal() } - err = os.WriteFile(containerPathTo, data, 0644) + err = os.WriteFile(containerPathTo, data, 0o644) commonCmd.ExitOnErr(cmd, "can't write container to file: %w", err) } }, diff --git a/cmd/frostfs-cli/modules/container/get_eacl.go b/cmd/frostfs-cli/modules/container/get_eacl.go index 6746132eb3..8896db7696 100644 --- a/cmd/frostfs-cli/modules/container/get_eacl.go +++ b/cmd/frostfs-cli/modules/container/get_eacl.go @@ -52,7 +52,7 @@ var getExtendedACLCmd = &cobra.Command{ cmd.Println("dumping data to file:", containerPathTo) - err = os.WriteFile(containerPathTo, data, 0644) + err = os.WriteFile(containerPathTo, data, 0o644) commonCmd.ExitOnErr(cmd, "could not write eACL to file: %w", err) }, } diff --git a/cmd/frostfs-cli/modules/container/nodes.go b/cmd/frostfs-cli/modules/container/nodes.go index 8b0f266a74..9273dd6513 100644 --- a/cmd/frostfs-cli/modules/container/nodes.go +++ b/cmd/frostfs-cli/modules/container/nodes.go @@ -20,7 +20,7 @@ var containerNodesCmd = &cobra.Command{ Short: "Show nodes for container", Long: "Show nodes taking part in a container at the current epoch.", Run: func(cmd *cobra.Command, args []string) { - var cnr, pkey = getContainer(cmd) + cnr, pkey := getContainer(cmd) if pkey == nil { pkey = key.GetOrGenerate(cmd) diff --git a/cmd/frostfs-cli/modules/object/get.go b/cmd/frostfs-cli/modules/object/get.go index 3136f086f9..9a888ccd39 100644 --- a/cmd/frostfs-cli/modules/object/get.go +++ b/cmd/frostfs-cli/modules/object/get.go @@ -132,7 +132,7 @@ func createOutWriter(cmd *cobra.Command, filename string) (out io.Writer, closer out = os.Stdout closer = func() {} } else { - f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) + f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644) if err != nil { commonCmd.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err)) } diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 5499e5eec6..ef6c29179a 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -191,7 +191,7 @@ func getRequiredPlacement(cmd *cobra.Command, objInfo *objectNodesInfo, placemen numOfReplicas := placementPolicy.ReplicaNumberByIndex(repIdx) var nodeIdx uint32 for _, n := range rep { - if !objInfo.isLock && nodeIdx == numOfReplicas { //lock object should be on all container nodes + if !objInfo.isLock && nodeIdx == numOfReplicas { // lock object should be on all container nodes break } nodes[n.Hash()] = n @@ -213,7 +213,8 @@ func getRequiredPlacement(cmd *cobra.Command, objInfo *objectNodesInfo, placemen } func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo, - pk *ecdsa.PrivateKey, objInfo *objectNodesInfo) map[uint64]boolError { + pk *ecdsa.PrivateKey, objInfo *objectNodesInfo, +) map[uint64]boolError { result := make(map[uint64]boolError) resultMtx := &sync.Mutex{} diff --git a/cmd/frostfs-cli/modules/object/root.go b/cmd/frostfs-cli/modules/object/root.go index c46fc058a7..d9d4bb84d8 100644 --- a/cmd/frostfs-cli/modules/object/root.go +++ b/cmd/frostfs-cli/modules/object/root.go @@ -31,7 +31,8 @@ func init() { objectHashCmd, objectRangeCmd, objectLockCmd, - objectNodesCmd} + objectNodesCmd, + } Cmd.AddCommand(objectChildCommands...) diff --git a/cmd/frostfs-cli/modules/session/create.go b/cmd/frostfs-cli/modules/session/create.go index f9705c0232..94ae595a8f 100644 --- a/cmd/frostfs-cli/modules/session/create.go +++ b/cmd/frostfs-cli/modules/session/create.go @@ -81,7 +81,7 @@ func createSession(cmd *cobra.Command, _ []string) { } filename, _ := cmd.Flags().GetString(outFlag) - err = os.WriteFile(filename, data, 0644) + err = os.WriteFile(filename, data, 0o644) commonCmd.ExitOnErr(cmd, "can't write token to file: %w", err) } diff --git a/cmd/frostfs-cli/modules/util/convert_eacl.go b/cmd/frostfs-cli/modules/util/convert_eacl.go index 1fb76c50ef..774d500bc6 100644 --- a/cmd/frostfs-cli/modules/util/convert_eacl.go +++ b/cmd/frostfs-cli/modules/util/convert_eacl.go @@ -48,7 +48,7 @@ func convertEACLTable(cmd *cobra.Command, _ []string) { return } - err = os.WriteFile(to, data, 0644) + err = os.WriteFile(to, data, 0o644) commonCmd.ExitOnErr(cmd, "can't write exteded ACL table to file: %w", err) cmd.Printf("extended ACL table was successfully dumped to %s\n", to) diff --git a/cmd/frostfs-cli/modules/util/keyer.go b/cmd/frostfs-cli/modules/util/keyer.go index 53082a15ed..ee24973489 100644 --- a/cmd/frostfs-cli/modules/util/keyer.go +++ b/cmd/frostfs-cli/modules/util/keyer.go @@ -78,7 +78,7 @@ func keyerGenerate(filename string, d *keyer.Dashboard) error { } if filename != "" { - return os.WriteFile(filename, key, 0600) + return os.WriteFile(filename, key, 0o600) } return nil diff --git a/cmd/frostfs-cli/modules/util/sign_bearer.go b/cmd/frostfs-cli/modules/util/sign_bearer.go index c641cf0ac6..9912169587 100644 --- a/cmd/frostfs-cli/modules/util/sign_bearer.go +++ b/cmd/frostfs-cli/modules/util/sign_bearer.go @@ -56,7 +56,7 @@ func signBearerToken(cmd *cobra.Command, _ []string) { return } - err = os.WriteFile(to, data, 0644) + err = os.WriteFile(to, data, 0o644) commonCmd.ExitOnErr(cmd, "can't write signed bearer token to file: %w", err) cmd.Printf("signed bearer token was successfully dumped to %s\n", to) diff --git a/cmd/frostfs-cli/modules/util/sign_session.go b/cmd/frostfs-cli/modules/util/sign_session.go index 2c77ee4df4..ba76678dc6 100644 --- a/cmd/frostfs-cli/modules/util/sign_session.go +++ b/cmd/frostfs-cli/modules/util/sign_session.go @@ -76,7 +76,7 @@ func signSessionToken(cmd *cobra.Command, _ []string) { return } - err = os.WriteFile(to, data, 0644) + err = os.WriteFile(to, data, 0o644) if err != nil { commonCmd.ExitOnErr(cmd, "", fmt.Errorf("can't write signed session token to %s: %w", to, err)) } diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index 54c7d18e31..be870052c0 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -13,7 +13,7 @@ import ( func newConfig() (*viper.Viper, error) { var err error - var dv = viper.New() + dv := viper.New() defaultConfiguration(dv) diff --git a/cmd/frostfs-lens/internal/printers.go b/cmd/frostfs-lens/internal/printers.go index dd73a5552e..ea0cbc8e02 100644 --- a/cmd/frostfs-lens/internal/printers.go +++ b/cmd/frostfs-lens/internal/printers.go @@ -59,7 +59,7 @@ func WriteObjectToFile(cmd *cobra.Command, path string, data []byte) { } ExitOnErr(cmd, Errf("could not write file: %w", - os.WriteFile(path, data, 0644))) + os.WriteFile(path, data, 0o644))) cmd.Printf("\nSaved payload to '%s' file\n", path) } diff --git a/cmd/frostfs-node/config/apiclient/config_test.go b/cmd/frostfs-node/config/apiclient/config_test.go index f4f09d4ff2..cdfa5c4015 100644 --- a/cmd/frostfs-node/config/apiclient/config_test.go +++ b/cmd/frostfs-node/config/apiclient/config_test.go @@ -22,7 +22,7 @@ func TestApiclientSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { require.Equal(t, 15*time.Second, apiclientconfig.DialTimeout(c)) require.Equal(t, 20*time.Second, apiclientconfig.StreamTimeout(c)) require.Equal(t, 30*time.Second, apiclientconfig.ReconnectTimeout(c)) diff --git a/cmd/frostfs-node/config/config.go b/cmd/frostfs-node/config/config.go index 77e34d613d..d74e820ac8 100644 --- a/cmd/frostfs-node/config/config.go +++ b/cmd/frostfs-node/config/config.go @@ -38,7 +38,6 @@ func New(configFile, configDir, envPrefix string) *Config { configViper.WithConfigFile(configFile), configViper.WithConfigDir(configDir), configViper.WithEnvPrefix(envPrefix)) - if err != nil { panic(err) } diff --git a/cmd/frostfs-node/config/configdir_test.go b/cmd/frostfs-node/config/configdir_test.go index ede15a5227..35dae97d9e 100644 --- a/cmd/frostfs-node/config/configdir_test.go +++ b/cmd/frostfs-node/config/configdir_test.go @@ -15,8 +15,8 @@ func TestConfigDir(t *testing.T) { cfgFileName0 := path.Join(dir, "cfg_00.json") cfgFileName1 := path.Join(dir, "cfg_01.yml") - require.NoError(t, os.WriteFile(cfgFileName0, []byte(`{"storage":{"shard_pool_size":15}}`), 0777)) - require.NoError(t, os.WriteFile(cfgFileName1, []byte("logger:\n level: debug"), 0777)) + require.NoError(t, os.WriteFile(cfgFileName0, []byte(`{"storage":{"shard_pool_size":15}}`), 0o777)) + require.NoError(t, os.WriteFile(cfgFileName1, []byte("logger:\n level: debug"), 0o777)) c := New("", dir, "") require.Equal(t, "debug", cast.ToString(c.Sub("logger").Value("level"))) diff --git a/cmd/frostfs-node/config/contracts/config_test.go b/cmd/frostfs-node/config/contracts/config_test.go index d816ea1e40..c85a625c5a 100644 --- a/cmd/frostfs-node/config/contracts/config_test.go +++ b/cmd/frostfs-node/config/contracts/config_test.go @@ -35,7 +35,7 @@ func TestContractsSection(t *testing.T) { expProxy, err := util.Uint160DecodeStringLE("ad7c6b55b737b696e5c82c85445040964a03e97f") require.NoError(t, err) - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { balance := contractsconfig.Balance(c) container := contractsconfig.Container(c) netmap := contractsconfig.Netmap(c) diff --git a/cmd/frostfs-node/config/control/config_test.go b/cmd/frostfs-node/config/control/config_test.go index 1aed229e27..f702d83ae4 100644 --- a/cmd/frostfs-node/config/control/config_test.go +++ b/cmd/frostfs-node/config/control/config_test.go @@ -24,7 +24,7 @@ func TestControlSection(t *testing.T) { pubs[0], _ = keys.NewPublicKeyFromString("035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11") pubs[1], _ = keys.NewPublicKeyFromString("028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6") - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { require.Equal(t, pubs, controlconfig.AuthorizedKeys(c)) require.Equal(t, "localhost:8090", controlconfig.GRPC(c).Endpoint()) } diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index b8e95db6dc..4077b17444 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -42,7 +42,7 @@ func TestEngineSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { num := 0 require.EqualValues(t, 100, engineconfig.ShardErrorThreshold(c)) @@ -78,7 +78,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 3221225472, wc.SizeLimit()) require.Equal(t, "tmp/0/meta", meta.Path()) - require.Equal(t, fs.FileMode(0644), meta.BoltDB().Perm()) + require.Equal(t, fs.FileMode(0o644), meta.BoltDB().Perm()) require.Equal(t, 100, meta.BoltDB().MaxBatchSize()) require.Equal(t, 10*time.Millisecond, meta.BoltDB().MaxBatchDelay()) @@ -89,7 +89,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, 2, len(ss)) blz := blobovniczaconfig.From((*config.Config)(ss[0])) require.Equal(t, "tmp/0/blob/blobovnicza", ss[0].Path()) - require.EqualValues(t, 0644, blz.BoltDB().Perm()) + require.EqualValues(t, 0o644, blz.BoltDB().Perm()) require.EqualValues(t, 4194304, blz.Size()) require.EqualValues(t, 1, blz.ShallowDepth()) require.EqualValues(t, 4, blz.ShallowWidth()) @@ -97,7 +97,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 10, blz.LeafWidth()) require.Equal(t, "tmp/0/blob", ss[1].Path()) - require.EqualValues(t, 0644, ss[1].Perm()) + require.EqualValues(t, 0o644, ss[1].Perm()) fst := fstreeconfig.From((*config.Config)(ss[1])) require.EqualValues(t, 5, fst.Depth()) @@ -112,7 +112,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, mode.ReadOnly, sc.Mode()) case 1: require.Equal(t, "tmp/1/blob/pilorama.db", pl.Path()) - require.Equal(t, fs.FileMode(0644), pl.Perm()) + require.Equal(t, fs.FileMode(0o644), pl.Perm()) require.True(t, pl.NoSync()) require.Equal(t, 5*time.Millisecond, pl.MaxBatchDelay()) require.Equal(t, 100, pl.MaxBatchSize()) @@ -127,7 +127,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 4294967296, wc.SizeLimit()) require.Equal(t, "tmp/1/meta", meta.Path()) - require.Equal(t, fs.FileMode(0644), meta.BoltDB().Perm()) + require.Equal(t, fs.FileMode(0o644), meta.BoltDB().Perm()) require.Equal(t, 200, meta.BoltDB().MaxBatchSize()) require.Equal(t, 20*time.Millisecond, meta.BoltDB().MaxBatchDelay()) @@ -146,7 +146,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 10, blz.LeafWidth()) require.Equal(t, "tmp/1/blob", ss[1].Path()) - require.EqualValues(t, 0644, ss[1].Perm()) + require.EqualValues(t, 0o644, ss[1].Perm()) fst := fstreeconfig.From((*config.Config)(ss[1])) require.EqualValues(t, 5, fst.Depth()) diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/storage/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/storage/config.go index 649e4980dd..e83c69de2b 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/storage/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/storage/config.go @@ -9,7 +9,7 @@ import ( type Config config.Config // PermDefault are default permission bits for BlobStor data. -const PermDefault = 0660 +const PermDefault = 0o660 func From(x *config.Config) *Config { return (*Config)(x) diff --git a/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go b/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go index 83d4e45c51..9e334cd8f4 100644 --- a/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go +++ b/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go @@ -13,7 +13,7 @@ type Config config.Config const ( // PermDefault is a default permission bits for metabase file. - PermDefault = 0660 + PermDefault = 0o660 ) // Perm returns the value of "perm" config parameter as a fs.FileMode. diff --git a/cmd/frostfs-node/config/engine/shard/pilorama/config.go b/cmd/frostfs-node/config/engine/shard/pilorama/config.go index 7ac0eca917..28671ca55a 100644 --- a/cmd/frostfs-node/config/engine/shard/pilorama/config.go +++ b/cmd/frostfs-node/config/engine/shard/pilorama/config.go @@ -13,7 +13,7 @@ type Config config.Config const ( // PermDefault is a default permission bits for metabase file. - PermDefault = 0660 + PermDefault = 0o660 ) // From wraps config section into Config. diff --git a/cmd/frostfs-node/config/grpc/config_test.go b/cmd/frostfs-node/config/grpc/config_test.go index 1ada792ec7..13ce4294e5 100644 --- a/cmd/frostfs-node/config/grpc/config_test.go +++ b/cmd/frostfs-node/config/grpc/config_test.go @@ -17,7 +17,7 @@ func TestGRPCSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { num := 0 IterateEndpoints(c, func(sc *Config) { diff --git a/cmd/frostfs-node/config/logger/config_test.go b/cmd/frostfs-node/config/logger/config_test.go index 8d37bdb1b4..8a0acbd85d 100644 --- a/cmd/frostfs-node/config/logger/config_test.go +++ b/cmd/frostfs-node/config/logger/config_test.go @@ -17,7 +17,7 @@ func TestLoggerSection_Level(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { v := loggerconfig.Level(c) require.Equal(t, "debug", v) } diff --git a/cmd/frostfs-node/config/metrics/config_test.go b/cmd/frostfs-node/config/metrics/config_test.go index 4c03729ee1..c2a1b1fc44 100644 --- a/cmd/frostfs-node/config/metrics/config_test.go +++ b/cmd/frostfs-node/config/metrics/config_test.go @@ -22,7 +22,7 @@ func TestMetricsSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { to := metricsconfig.ShutdownTimeout(c) addr := metricsconfig.Address(c) diff --git a/cmd/frostfs-node/config/morph/config_test.go b/cmd/frostfs-node/config/morph/config_test.go index be61d8608a..192140446e 100644 --- a/cmd/frostfs-node/config/morph/config_test.go +++ b/cmd/frostfs-node/config/morph/config_test.go @@ -23,14 +23,12 @@ func TestMorphSection(t *testing.T) { const path = "../../../../config/example/node" - var ( - rpcs = []client.Endpoint{ - {"wss://rpc1.morph.frostfs.info:40341/ws", 1}, - {"wss://rpc2.morph.frostfs.info:40341/ws", 2}, - } - ) + rpcs := []client.Endpoint{ + {"wss://rpc1.morph.frostfs.info:40341/ws", 1}, + {"wss://rpc2.morph.frostfs.info:40341/ws", 2}, + } - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { require.Equal(t, rpcs, morphconfig.RPCEndpoint(c)) require.Equal(t, 30*time.Second, morphconfig.DialTimeout(c)) require.Equal(t, 15*time.Second, morphconfig.CacheTTL(c)) diff --git a/cmd/frostfs-node/config/node/config_test.go b/cmd/frostfs-node/config/node/config_test.go index 3a11204914..b0041c8706 100644 --- a/cmd/frostfs-node/config/node/config_test.go +++ b/cmd/frostfs-node/config/node/config_test.go @@ -56,7 +56,7 @@ func TestNodeSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { key := Key(c) addrs := BootstrapAddresses(c) attributes := Attributes(c) diff --git a/cmd/frostfs-node/config/object/config_test.go b/cmd/frostfs-node/config/object/config_test.go index 513b6e9c52..e2bb105d9f 100644 --- a/cmd/frostfs-node/config/object/config_test.go +++ b/cmd/frostfs-node/config/object/config_test.go @@ -21,7 +21,7 @@ func TestObjectSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { require.Equal(t, 100, objectconfig.Put(c).PoolSizeRemote()) require.Equal(t, 200, objectconfig.Put(c).PoolSizeLocal()) require.EqualValues(t, 10, objectconfig.TombstoneLifetime(c)) diff --git a/cmd/frostfs-node/config/policer/config_test.go b/cmd/frostfs-node/config/policer/config_test.go index a4c23eae74..95f0c3af2e 100644 --- a/cmd/frostfs-node/config/policer/config_test.go +++ b/cmd/frostfs-node/config/policer/config_test.go @@ -19,7 +19,7 @@ func TestPolicerSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { require.Equal(t, 15*time.Second, policerconfig.HeadTimeout(c)) } diff --git a/cmd/frostfs-node/config/profiler/config_test.go b/cmd/frostfs-node/config/profiler/config_test.go index 355874387f..2f1cb1788e 100644 --- a/cmd/frostfs-node/config/profiler/config_test.go +++ b/cmd/frostfs-node/config/profiler/config_test.go @@ -25,7 +25,7 @@ func TestProfilerSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { to := profilerconfig.ShutdownTimeout(c) addr := profilerconfig.Address(c) diff --git a/cmd/frostfs-node/config/replicator/config_test.go b/cmd/frostfs-node/config/replicator/config_test.go index 0118aa0b28..2129c01b45 100644 --- a/cmd/frostfs-node/config/replicator/config_test.go +++ b/cmd/frostfs-node/config/replicator/config_test.go @@ -20,7 +20,7 @@ func TestReplicatorSection(t *testing.T) { const path = "../../../../config/example/node" - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { require.Equal(t, 15*time.Second, replicatorconfig.PutTimeout(c)) require.Equal(t, 10, replicatorconfig.PoolSize(c)) } diff --git a/cmd/frostfs-node/config/tree/config_test.go b/cmd/frostfs-node/config/tree/config_test.go index 898f7e715b..285ea07253 100644 --- a/cmd/frostfs-node/config/tree/config_test.go +++ b/cmd/frostfs-node/config/tree/config_test.go @@ -35,7 +35,7 @@ func TestTreeSection(t *testing.T) { require.NoError(t, err) expectedKeys = append(expectedKeys, key) - var fileConfigTest = func(c *config.Config) { + fileConfigTest := func(c *config.Config) { treeSec := treeconfig.Tree(c) require.True(t, treeSec.Enabled()) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 5c3db0d277..edb1412aa4 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -239,7 +239,8 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { } func registerNotificationHandlers(scHash util.Uint160, lis event.Listener, parsers map[event.Type]event.NotificationParser, - subs map[event.Type][]event.Handler) { + subs map[event.Type][]event.Handler, +) { for typ, handlers := range subs { pi := event.NotificationParserInfo{} pi.SetType(typ) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 82ddf897f4..2f714b8211 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -353,7 +353,8 @@ func createSearchSvcV2(sSearch *searchsvc.Service, keyStorage *util.KeyStorage) } func createGetService(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.TraverserGenerator, - coreConstructor *cache.ClientCache) *getsvc.Service { + coreConstructor *cache.ClientCache, +) *getsvc.Service { ls := c.cfgObject.cfgLocalStorage.localStorage return getsvc.New( @@ -375,7 +376,8 @@ func createGetServiceV2(sGet *getsvc.Service, keyStorage *util.KeyStorage) *gets } func createDeleteService(c *cfg, keyStorage *util.KeyStorage, sGet *getsvc.Service, - sSearch *searchsvc.Service, sPut *putsvc.Service) *deletesvc.Service { + sSearch *searchsvc.Service, sPut *putsvc.Service, +) *deletesvc.Service { return deletesvc.New( sGet, sSearch, @@ -396,7 +398,8 @@ func createDeleteServiceV2(sDelete *deletesvc.Service) *deletesvcV2.Service { } func createSplitService(c *cfg, sPutV2 *putsvcV2.Service, sGetV2 *getsvcV2.Service, - sSearchV2 *searchsvcV2.Service, sDeleteV2 *deletesvcV2.Service) *objectService.TransportSplitter { + sSearchV2 *searchsvcV2.Service, sDeleteV2 *deletesvcV2.Service, +) *objectService.TransportSplitter { return objectService.NewTransportSplitter( c.cfgGRPC.maxChunkSize, c.cfgGRPC.maxAddrAmount, diff --git a/cmd/frostfs-node/tracing.go b/cmd/frostfs-node/tracing.go index 08dc049da5..312adfb8d3 100644 --- a/cmd/frostfs-node/tracing.go +++ b/cmd/frostfs-node/tracing.go @@ -23,7 +23,7 @@ func initTracing(ctx context.Context, c *cfg) { fn: func() { ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) defer cancel() - err := tracing.Shutdown(ctx) //cfg context cancels before close + err := tracing.Shutdown(ctx) // cfg context cancels before close if err != nil { c.log.Error(logs.FrostFSNodeFailedShutdownTracing, zap.Error(err)) } diff --git a/cmd/frostfs-node/validate.go b/cmd/frostfs-node/validate.go index e07afb2cab..80c90ec44e 100644 --- a/cmd/frostfs-node/validate.go +++ b/cmd/frostfs-node/validate.go @@ -59,7 +59,7 @@ func validateConfig(c *config.Config) error { default: return fmt.Errorf("unexpected storage type: %s (shard %d)", blobstor[i].Type(), shardNum) } - if blobstor[i].Perm()&0600 != 0600 { + if blobstor[i].Perm()&0o600 != 0o600 { return fmt.Errorf("invalid permissions for blobstor component: %s, "+ "expected at least rw- for the owner (shard %d)", blobstor[i].Perm(), shardNum) diff --git a/cmd/internal/common/netmap.go b/cmd/internal/common/netmap.go index 94964e0d23..79b03a7268 100644 --- a/cmd/internal/common/netmap.go +++ b/cmd/internal/common/netmap.go @@ -10,7 +10,8 @@ import ( // PrettyPrintNodeInfo print information about network node with given indent and index. // To avoid printing attribute list use short parameter. func PrettyPrintNodeInfo(cmd *cobra.Command, node netmap.NodeInfo, - index int, indent string, short bool) { + index int, indent string, short bool, +) { var strState string switch { diff --git a/pkg/core/client/util.go b/pkg/core/client/util.go index 80c8f49b7f..d4bc0cf68a 100644 --- a/pkg/core/client/util.go +++ b/pkg/core/client/util.go @@ -22,7 +22,8 @@ func NodeInfoFromRawNetmapElement(dst *NodeInfo, info interface { IterateAddresses(func(string) bool) NumberOfAddresses() int ExternalAddresses() []string -}) error { +}, +) error { var a network.AddressGroup err := a.FromIterator(info) @@ -49,7 +50,8 @@ func NodeInfoFromNetmapElement(dst *NodeInfo, info interface { PublicKey() []byte Addresses() network.AddressGroup ExternalAddresses() network.AddressGroup -}) { +}, +) { nodeInfoFromKeyAddr(dst, info.PublicKey(), info.Addresses(), info.ExternalAddresses()) } diff --git a/pkg/core/object/sender_classifier.go b/pkg/core/object/sender_classifier.go index 79bf12ce39..ac881431e7 100644 --- a/pkg/core/object/sender_classifier.go +++ b/pkg/core/object/sender_classifier.go @@ -43,7 +43,8 @@ func (c SenderClassifier) Classify( ownerID *user.ID, ownerKey *keys.PublicKey, idCnr cid.ID, - cnr container.Container) (res *ClassifyResult, err error) { + cnr container.Container, +) (res *ClassifyResult, err error) { ownerKeyInBytes := ownerKey.Bytes() // TODO: #767 get owner from frostfs.id if present @@ -114,7 +115,8 @@ func (c SenderClassifier) isInnerRingKey(owner []byte) (bool, error) { func (c SenderClassifier) isContainerKey( owner, idCnr []byte, - cnr container.Container) (bool, error) { + cnr container.Container, +) (bool, error) { nm, err := core.GetLatestNetworkMap(c.netmap) // first check current netmap if err != nil { return false, err @@ -140,7 +142,8 @@ func (c SenderClassifier) isContainerKey( func lookupKeyInContainer( nm *netmap.NetMap, owner, idCnr []byte, - cnr container.Container) (bool, error) { + cnr container.Container, +) (bool, error) { cnrVectors, err := nm.ContainerNodes(cnr.PlacementPolicy(), idCnr) if err != nil { return false, err diff --git a/pkg/innerring/blocktimer_test.go b/pkg/innerring/blocktimer_test.go index 224aa5c588..9d02721c2a 100644 --- a/pkg/innerring/blocktimer_test.go +++ b/pkg/innerring/blocktimer_test.go @@ -117,6 +117,7 @@ type testEpochState struct { func (s *testEpochState) EpochCounter() uint64 { return s.counter } + func (s *testEpochState) EpochDuration() uint64 { return s.duration } diff --git a/pkg/innerring/config/fee_test.go b/pkg/innerring/config/fee_test.go index f7330c6ca7..ced21b2385 100644 --- a/pkg/innerring/config/fee_test.go +++ b/pkg/innerring/config/fee_test.go @@ -60,5 +60,4 @@ fee: require.Equal(t, fixedn.Fixed8(10), config.MainChainFee(), "main chain fee invalid") require.Equal(t, fixedn.Fixed8(0), config.SideChainFee(), "side chain fee invalid") }) - } diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index eb1c4b2d4b..f8ebe89fe4 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -35,7 +35,8 @@ import ( func (s *Server) initNetmapProcessor(cfg *viper.Viper, cnrClient *container.Client, - alphaSync event.Handler) error { + alphaSync event.Handler, +) error { locodeValidator, err := s.newLocodeValidator(cfg) if err != nil { return err @@ -250,7 +251,8 @@ func (s *Server) initAlphabetProcessor(cfg *viper.Viper) error { } func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.Client, - frostfsIDClient *frostfsid.Client) error { + frostfsIDClient *frostfsid.Client, +) error { // container processor containerProcessor, err := cont.New(&cont.Params{ Log: s.log, diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index ae2ad40199..49b7708112 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -328,7 +328,8 @@ func (s *Server) registerStarter(f func() error) { // New creates instance of inner ring sever structure. func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error, - metrics *metrics.InnerRingServiceMetrics) (*Server, error) { + metrics *metrics.InnerRingServiceMetrics, +) (*Server, error) { var err error server := &Server{ log: log, diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index c098ca27d5..e39244a364 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -256,6 +256,7 @@ func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, metho }) return nil } + func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error { c.transferedGas = append(c.transferedGas, transferGas{ receiver: receiver, diff --git a/pkg/innerring/processors/balance/handlers_test.go b/pkg/innerring/processors/balance/handlers_test.go index 3470fba2d2..10ae8c60e4 100644 --- a/pkg/innerring/processors/balance/handlers_test.go +++ b/pkg/innerring/processors/balance/handlers_test.go @@ -73,8 +73,7 @@ func (s *testAlphabetState) IsAlphabet() bool { return s.isAlphabet } -type testPresicionConverter struct { -} +type testPresicionConverter struct{} func (c *testPresicionConverter) ToFixed8(v int64) int64 { return v diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index 77dbe876a6..f129127a64 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -319,6 +319,7 @@ func (e *testPutEvent) Signature() []byte { func (e *testPutEvent) SessionToken() []byte { return e.st } + func (e *testPutEvent) NotaryRequest() *payload.P2PNotaryRequest { return e.nr } diff --git a/pkg/innerring/processors/frostfs/handlers_test.go b/pkg/innerring/processors/frostfs/handlers_test.go index db78358115..475ddaaaca 100644 --- a/pkg/innerring/processors/frostfs/handlers_test.go +++ b/pkg/innerring/processors/frostfs/handlers_test.go @@ -301,8 +301,7 @@ func (s *testAlphabetState) IsAlphabet() bool { return s.isAlphabet } -type testPrecisionConverter struct { -} +type testPrecisionConverter struct{} func (c *testPrecisionConverter) ToBalancePrecision(v int64) int64 { return v @@ -318,10 +317,12 @@ func (c *testBalaceClient) Mint(p balance.MintPrm) error { c.mint = append(c.mint, p) return nil } + func (c *testBalaceClient) Lock(p balance.LockPrm) error { c.lock = append(c.lock, p) return nil } + func (c *testBalaceClient) Burn(p balance.BurnPrm) error { c.burn = append(c.burn, p) return nil @@ -349,6 +350,7 @@ type testMorphClient struct { func (c *testMorphClient) GasBalance() (res int64, err error) { return c.balance, nil } + func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error { c.transferGas = append(c.transferGas, transferGas{ receiver: receiver, diff --git a/pkg/innerring/processors/governance/handlers_test.go b/pkg/innerring/processors/governance/handlers_test.go index 63d156dacb..adf6741730 100644 --- a/pkg/innerring/processors/governance/handlers_test.go +++ b/pkg/innerring/processors/governance/handlers_test.go @@ -205,7 +205,7 @@ func generateTestKeys(t *testing.T) testKeys { require.NoError(t, err, "failed to create expected new alphabet") if len(result.newAlphabetExp) == 0 { - continue //can be happen because of random and sort + continue // can be happen because of random and sort } var irKeys keys.PublicKeys diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index 6c9e265ccf..fa87cff925 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -309,12 +309,15 @@ type testEpochState struct { func (s *testEpochState) SetEpochCounter(c uint64) { s.counter = c } + func (s *testEpochState) EpochCounter() uint64 { return s.counter } + func (s *testEpochState) SetEpochDuration(d uint64) { s.duration = d } + func (s *testEpochState) EpochDuration() uint64 { return s.duration } diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index 4bc13cc958..d256c1c69a 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -20,8 +20,7 @@ type DeletePrm struct { } // DeleteRes groups the resulting values of Delete operation. -type DeleteRes struct { -} +type DeleteRes struct{} // SetAddress sets the address of the requested object. func (p *DeletePrm) SetAddress(addr oid.Address) { diff --git a/pkg/local_object_storage/blobovnicza/exists.go b/pkg/local_object_storage/blobovnicza/exists.go index e6d28f9381..9b190416fd 100644 --- a/pkg/local_object_storage/blobovnicza/exists.go +++ b/pkg/local_object_storage/blobovnicza/exists.go @@ -12,9 +12,7 @@ import ( // Exists check if object with the specified address is stored in b. func (b *Blobovnicza) Exists(ctx context.Context, addr oid.Address) (bool, error) { - var ( - exists = false - ) + exists := false _, span := tracing.StartSpanFromContext(ctx, "Blobovnicza.Exists", trace.WithAttributes( diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index b29ccb43c9..f4b85f5d0b 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -116,8 +116,7 @@ func (x *IteratePrm) IgnoreErrors() { } // IterateRes groups the resulting values of Iterate operation. -type IterateRes struct { -} +type IterateRes struct{} // Iterate goes through all stored objects, and passes IterationElement to parameterized handler until error return. // diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go index 787372211f..859f7dbbf9 100644 --- a/pkg/local_object_storage/blobovnicza/put.go +++ b/pkg/local_object_storage/blobovnicza/put.go @@ -20,8 +20,7 @@ type PutPrm struct { } // PutRes groups the resulting values of Put operation. -type PutRes struct { -} +type PutRes struct{} // SetAddress sets the address of the saving object. func (p *PutPrm) SetAddress(addr oid.Address) { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/active.go b/pkg/local_object_storage/blobstor/blobovniczatree/active.go index 526699b454..def1973183 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/active.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/active.go @@ -96,7 +96,7 @@ func (m *activeDBManager) getCurrentActiveIfOk(lvlPath string) (*activeDB, error return nil, nil } - blz, err := db.Open() //open db for usage, will be closed on activeDB.Close() + blz, err := db.Open() // open db for usage, will be closed on activeDB.Close() if err != nil { return nil, err } @@ -156,7 +156,7 @@ func (m *activeDBManager) getNextSharedDB(lvlPath string) (*sharedDB, error) { for iterCount < m.leafWidth { path := filepath.Join(lvlPath, u64ToHexString(idx)) shDB := m.dbManager.GetByPath(path) - db, err := shDB.Open() //open db to hold active DB open, will be closed if db is full, after m.replace or by activeDBManager.Close() + db, err := shDB.Open() // open db to hold active DB open, will be closed if db is full, after m.replace or by activeDBManager.Close() if err != nil { return nil, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index 9bdee6df31..3f62c49fa6 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -80,7 +80,7 @@ func (c *dbCache) create(path string) *sharedDB { value = c.dbManager.GetByPath(path) - _, err := value.Open() //open db to hold reference, closed by evictedDB.Close() or if cache closed + _, err := value.Open() // open db to hold reference, closed by evictedDB.Close() or if cache closed if err != nil { return value } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 5ea426e1ce..d993767b79 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -40,14 +40,14 @@ func (b *Blobovniczas) Init() error { } func (b *Blobovniczas) openManagers() { - b.commondbManager.Open() //order important + b.commondbManager.Open() // order important b.activeDBManager.Open() b.dbCache.Open() } // Close implements common.Storage. func (b *Blobovniczas) Close() error { - b.dbCache.Close() //order important + b.dbCache.Close() // order important b.activeDBManager.Close() b.commondbManager.Close() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index 8cbdf613c7..198e4741ba 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -55,7 +55,7 @@ func TestExistsInvalidStorageID(t *testing.T) { // An invalid boltdb file is created so that it returns an error when opened require.NoError(t, os.MkdirAll(filepath.Join(dir, relBadFileDir), os.ModePerm)) - require.NoError(t, os.WriteFile(filepath.Join(dir, relBadFileDir, badFileName), []byte("not a boltdb file content"), 0777)) + require.NoError(t, os.WriteFile(filepath.Join(dir, relBadFileDir, badFileName), []byte("not a boltdb file content"), 0o777)) res, err := b.Exists(context.Background(), common.ExistsPrm{Address: addr, StorageID: []byte(filepath.Join(relBadFileDir, badFileName))}) require.Error(t, err) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index 7bc8e2827c..d695cb199a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -28,7 +28,8 @@ type sharedDB struct { } func newSharedDB(options []blobovnicza.Option, path string, readOnly bool, - metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlag *atomic.Bool, log *logger.Logger) *sharedDB { + metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlag *atomic.Bool, log *logger.Logger, +) *sharedDB { return &sharedDB{ guard: &sync.RWMutex{}, @@ -110,7 +111,8 @@ type levelDbManager struct { } func newLevelDBManager(width uint64, options []blobovnicza.Option, rootPath string, lvlPath string, - readOnly bool, metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlog *atomic.Bool, log *logger.Logger) *levelDbManager { + readOnly bool, metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlog *atomic.Bool, log *logger.Logger, +) *levelDbManager { result := &levelDbManager{ databases: make([]*sharedDB, width), } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index d111856527..561b837618 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -28,7 +28,7 @@ type cfg struct { type Option func(*cfg) const ( - defaultPerm = 0700 + defaultPerm = 0o700 defaultOpenedCacheSize = 50 defaultBlzShallowDepth = 2 defaultBlzShallowWidth = 16 diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 243a7239e2..bf3400bcd7 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -77,7 +77,7 @@ var _ common.Storage = (*FSTree)(nil) func New(opts ...Option) *FSTree { f := &FSTree{ Info: Info{ - Permissions: 0700, + Permissions: 0o700, RootPath: "./", }, Config: nil, diff --git a/pkg/local_object_storage/blobstor/generic_test.go b/pkg/local_object_storage/blobstor/generic_test.go index 204bdf61d2..b58ab8a68c 100644 --- a/pkg/local_object_storage/blobstor/generic_test.go +++ b/pkg/local_object_storage/blobstor/generic_test.go @@ -7,7 +7,6 @@ import ( ) func TestGeneric(t *testing.T) { - newMetabase := func(t *testing.T) storagetest.Component { return New( WithStorages(defaultStorages(t.TempDir(), 128))) diff --git a/pkg/local_object_storage/blobstor/get.go b/pkg/local_object_storage/blobstor/get.go index 00ed18d7bc..d00ef2f21f 100644 --- a/pkg/local_object_storage/blobstor/get.go +++ b/pkg/local_object_storage/blobstor/get.go @@ -18,9 +18,7 @@ import ( // If the descriptor is present, only one sub-storage is tried, // Otherwise, each sub-storage is tried in order. func (b *BlobStor) Get(ctx context.Context, prm common.GetPrm) (res common.GetRes, err error) { - var ( - startedAt = time.Now() - ) + startedAt := time.Now() defer func() { b.metrics.Get(time.Since(startedAt), len(res.RawData), err == nil, prm.StorageID != nil) }() diff --git a/pkg/local_object_storage/blobstor/get_range.go b/pkg/local_object_storage/blobstor/get_range.go index 50abd19fa0..9bded4720d 100644 --- a/pkg/local_object_storage/blobstor/get_range.go +++ b/pkg/local_object_storage/blobstor/get_range.go @@ -19,9 +19,7 @@ import ( // If the descriptor is present, only one sub-storage is tried, // Otherwise, each sub-storage is tried in order. func (b *BlobStor) GetRange(ctx context.Context, prm common.GetRangePrm) (res common.GetRangeRes, err error) { - var ( - startedAt = time.Now() - ) + startedAt := time.Now() defer func() { b.metrics.GetRange(time.Since(startedAt), len(res.Data), err == nil, prm.StorageID != nil) }() diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index 34622c8579..72f1076644 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -91,7 +91,7 @@ func runTestIgnoreLogicalErrors(t *testing.T, s common.Storage, objects []object seen := make(map[string]objectDesc) var n int - var logicErr = errors.New("logic error") + logicErr := errors.New("logic error") var iterPrm common.IteratePrm iterPrm.IgnoreErrors = true iterPrm.Handler = func(elem common.IterationElement) error { diff --git a/pkg/local_object_storage/blobstor/logger.go b/pkg/local_object_storage/blobstor/logger.go index f201f18d74..7e057a0e32 100644 --- a/pkg/local_object_storage/blobstor/logger.go +++ b/pkg/local_object_storage/blobstor/logger.go @@ -6,8 +6,10 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) -const deleteOp = "DELETE" -const putOp = "PUT" +const ( + deleteOp = "DELETE" + putOp = "PUT" +) func logOp(l *logger.Logger, op string, addr oid.Address, typ string, sID []byte) { storagelog.Write(l, diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index d97148f736..03196400a0 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -30,7 +30,7 @@ func (e *StorageEngine) open(ctx context.Context) error { defer e.mtx.Unlock() var wg sync.WaitGroup - var errCh = make(chan shardInitError, len(e.shards)) + errCh := make(chan shardInitError, len(e.shards)) for id, sh := range e.shards { wg.Add(1) @@ -75,7 +75,7 @@ func (e *StorageEngine) Init(ctx context.Context) error { e.mtx.Lock() defer e.mtx.Unlock() - var errCh = make(chan shardInitError, len(e.shards)) + errCh := make(chan shardInitError, len(e.shards)) var eg errgroup.Group if e.cfg.lowMem && e.anyShardRequiresRefill() { eg.SetLimit(1) diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 0c5ff94da0..9cfb311ec6 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -62,7 +62,7 @@ func TestInitializationFailure(t *testing.T) { OpenFile: opts.openFileMetabase, }), meta.WithPath(filepath.Join(t.TempDir(), "metabase")), - meta.WithPermissions(0700), + meta.WithPermissions(0o700), meta.WithEpochState(epochState{})), shard.WithWriteCache(true), shard.WithWriteCacheOptions(wcOpts), @@ -228,7 +228,6 @@ func TestPersistentShardID(t *testing.T) { require.Equal(t, te.shards[1].id, newTe.shards[0].id) require.Equal(t, te.shards[0].id, newTe.shards[1].id) require.NoError(t, newTe.ng.Close(context.Background())) - } func TestReload(t *testing.T) { @@ -299,7 +298,7 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str blobstor.WithStorages(newStorages(filepath.Join(addPath, strconv.Itoa(id)), errSmallSize))), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(addPath, fmt.Sprintf("%d.metabase", id))), - meta.WithPermissions(0700), + meta.WithPermissions(0o700), meta.WithEpochState(epochState{}), ), } diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index bb0b682d66..e312e9f0df 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -143,7 +143,8 @@ func (e *StorageEngine) reportShardError( sh hashedShard, msg string, err error, - fields ...zap.Field) { + fields ...zap.Field, +) { if isLogical(err) { e.log.Warn(msg, zap.Stringer("shard_id", sh.ID()), @@ -162,7 +163,8 @@ func (e *StorageEngine) reportShardErrorWithFlags( block bool, msg string, err error, - fields ...zap.Field) { + fields ...zap.Field, +) { sid := sh.ID() e.log.Warn(msg, append([]zap.Field{ zap.Stringer("shard_id", sid), diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 934bea8bbd..21bf37dc71 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -144,7 +144,7 @@ func newStorages(root string, smallSize uint64) []blobstor.SubStorage { blobovniczatree.WithRootPath(filepath.Join(root, "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1), - blobovniczatree.WithPermissions(0700)), + blobovniczatree.WithPermissions(0o700)), Policy: func(_ *objectSDK.Object, data []byte) bool { return uint64(len(data)) < smallSize }, @@ -163,7 +163,7 @@ func newTestStorages(root string, smallSize uint64) ([]blobstor.SubStorage, *tes blobovniczatree.WithRootPath(filepath.Join(root, "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1), - blobovniczatree.WithPermissions(0700)), + blobovniczatree.WithPermissions(0o700)), )) largeFileStorage := teststore.New( teststore.WithSubstorage(fstree.New( @@ -205,7 +205,8 @@ func testDefaultShardOptions(t testing.TB, id int) []shard.Option { shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(t.TempDir(), "metabase")), - meta.WithPermissions(0700), + meta.WithPermissions(0o700), meta.WithEpochState(epochState{}), - )} + ), + } } diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 90356104e3..cf62302f2f 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -59,12 +59,12 @@ func newEngineWithErrorThreshold(t testing.TB, dir string, errThreshold uint32) shard.WithBlobStorOptions(blobstor.WithStorages(storages)), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(dir, fmt.Sprintf("%d.metabase", id))), - meta.WithPermissions(0700), + meta.WithPermissions(0o700), meta.WithEpochState(epochState{}), ), shard.WithPiloramaOptions( pilorama.WithPath(filepath.Join(dir, fmt.Sprintf("%d.pilorama", id))), - pilorama.WithPerm(0700)), + pilorama.WithPerm(0o700)), } }) e := te.engine diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 192070c1cf..f5f1b658d7 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -163,7 +163,6 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev res := NewEvacuateShardRes() ctx = ctxOrBackground(ctx, prm.async) eg, egCtx, err := e.evacuateLimiter.TryStart(ctx, shardIDs, res) - if err != nil { return nil, err } @@ -187,7 +186,8 @@ func ctxOrBackground(ctx context.Context, background bool) context.Context { } func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) error { + shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, +) error { var err error ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShards", trace.WithAttributes( @@ -246,7 +246,8 @@ func (e *StorageEngine) getTotalObjectsCount(ctx context.Context, shardsToEvacua } func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) error { + shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, +) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShard", trace.WithAttributes( attribute.String("shardID", shardID), @@ -322,7 +323,8 @@ func (e *StorageEngine) getActualShards(shardIDs []string, handlerDefined bool) } func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, toEvacuate []object.AddressWithType, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard) error { + shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, +) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateObjects", trace.WithAttributes( attribute.Int("objects_count", len(toEvacuate)), @@ -378,7 +380,8 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to } func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Address, object *objectSDK.Object, sh *shard.Shard, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes) (bool, error) { + shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes, +) (bool, error) { hrw.SortHasherSliceByWeightValue(shards, weights, hrw.StringHash(addr.EncodeToString())) for j := range shards { select { diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index c0c05d6618..13ba94f5b9 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -39,7 +39,7 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng }})), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(dir, fmt.Sprintf("%d.metabase", id))), - meta.WithPermissions(0700), + meta.WithPermissions(0o700), meta.WithEpochState(epochState{})), } }) @@ -137,7 +137,7 @@ func TestEvacuateShard(t *testing.T) { func TestEvacuateNetwork(t *testing.T) { t.Parallel() - var errReplication = errors.New("handler error") + errReplication := errors.New("handler error") acceptOneOf := func(objects []*objectSDK.Object, max uint64) func(context.Context, oid.Address, *objectSDK.Object) error { var n uint64 diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index eef25d2090..246118687e 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -72,9 +72,10 @@ func TestListWithCursor(t *testing.T) { shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(t.TempDir(), "metabase")), - meta.WithPermissions(0700), + meta.WithPermissions(0o700), meta.WithEpochState(epochState{}), - )} + ), + } }).engine require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) diff --git a/pkg/local_object_storage/internal/metaerr/error_test.go b/pkg/local_object_storage/internal/metaerr/error_test.go index 5a16aa501c..acde48793c 100644 --- a/pkg/local_object_storage/internal/metaerr/error_test.go +++ b/pkg/local_object_storage/internal/metaerr/error_test.go @@ -48,6 +48,7 @@ func TestError(t *testing.T) { } }) } + func TestNilWrap(t *testing.T) { require.NoError(t, Wrap(nil)) } diff --git a/pkg/local_object_storage/metabase/children.go b/pkg/local_object_storage/metabase/children.go index 6816358d2f..acd3679517 100644 --- a/pkg/local_object_storage/metabase/children.go +++ b/pkg/local_object_storage/metabase/children.go @@ -69,7 +69,6 @@ func (db *DB) GetChildren(ctx context.Context, addresses []oid.Address) (map[oid } return nil }) - if err != nil { return nil, metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index c0dc7886ea..d4afe18785 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -10,8 +10,10 @@ import ( "go.etcd.io/bbolt" ) -var objectPhyCounterKey = []byte("phy_counter") -var objectLogicCounterKey = []byte("logic_counter") +var ( + objectPhyCounterKey = []byte("phy_counter") + objectLogicCounterKey = []byte("logic_counter") +) type objectType uint8 diff --git a/pkg/local_object_storage/metabase/db_test.go b/pkg/local_object_storage/metabase/db_test.go index bc5015b60e..b3c38f3d77 100644 --- a/pkg/local_object_storage/metabase/db_test.go +++ b/pkg/local_object_storage/metabase/db_test.go @@ -45,7 +45,7 @@ func newDB(t testing.TB, opts ...meta.Option) *meta.DB { bdb := meta.New( append([]meta.Option{ meta.WithPath(filepath.Join(t.TempDir(), "metabase")), - meta.WithPermissions(0600), + meta.WithPermissions(0o600), meta.WithEpochState(epochState{}), }, opts...)..., ) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index f7ff7a129a..e84759b888 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -98,8 +98,8 @@ func (db *DB) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { var rawRemoved uint64 var availableRemoved uint64 var err error - var sizes = make([]uint64, len(prm.addrs)) - var availableSizes = make([]uint64, len(prm.addrs)) + sizes := make([]uint64, len(prm.addrs)) + availableSizes := make([]uint64, len(prm.addrs)) err = db.boltDB.Update(func(tx *bbolt.Tx) error { // We need to clear slice because tx can try to execute multiple times. diff --git a/pkg/local_object_storage/metabase/expired.go b/pkg/local_object_storage/metabase/expired.go index 43933d12d5..aa2cb6f20e 100644 --- a/pkg/local_object_storage/metabase/expired.go +++ b/pkg/local_object_storage/metabase/expired.go @@ -83,7 +83,6 @@ func (db *DB) FilterExpired(ctx context.Context, epoch uint64, addresses []oid.A } return nil }) - if err != nil { return nil, metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 37a574a022..5099a161b0 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -115,7 +115,7 @@ func (db *DB) listWithCursor(tx *bbolt.Tx, result []objectcore.AddressWithType, graveyardBkt := tx.Bucket(graveyardBucketName) garbageBkt := tx.Bucket(garbageBucketName) - var rawAddr = make([]byte, cidSize, addressKeySize) + rawAddr := make([]byte, cidSize, addressKeySize) loop: for ; name != nil; name, _ = c.Next() { diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index abb55c9d17..3e598ed16d 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -211,7 +211,6 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { for _, v := range expected { require.Equal(t, 1, v) } - } func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index 30a31ab879..0bc2b06f0c 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -244,7 +244,6 @@ func freePotentialLocks(tx *bbolt.Tx, idCnr cid.ID, locker oid.ID) ([]oid.Addres return nil }) - if err != nil { return nil, err } diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 28f12851f1..875388e589 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -101,7 +101,8 @@ func (db *DB) put(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *objectSDK.SplitInfo, - currEpoch uint64) error { + currEpoch uint64, +) error { cnr, ok := obj.ContainerID() if !ok { return errors.New("missing container in object") diff --git a/pkg/local_object_storage/metabase/version_test.go b/pkg/local_object_storage/metabase/version_test.go index 6f011c2466..ddeddd189c 100644 --- a/pkg/local_object_storage/metabase/version_test.go +++ b/pkg/local_object_storage/metabase/version_test.go @@ -23,7 +23,7 @@ func TestVersion(t *testing.T) { newDB := func(t *testing.T) *DB { return New(WithPath(filepath.Join(dir, t.Name())), - WithPermissions(0600), WithEpochState(epochStateImpl{})) + WithPermissions(0o600), WithEpochState(epochStateImpl{})) } check := func(t *testing.T, db *DB) { require.NoError(t, db.boltDB.View(func(tx *bbolt.Tx) error { diff --git a/pkg/local_object_storage/metrics/fstree.go b/pkg/local_object_storage/metrics/fstree.go index d3749d9bc5..0def3210cb 100644 --- a/pkg/local_object_storage/metrics/fstree.go +++ b/pkg/local_object_storage/metrics/fstree.go @@ -28,6 +28,7 @@ func (m *fstreeMetrics) SetParentID(parentID string) { func (m *fstreeMetrics) SetMode(readOnly bool) { m.m.SetMode(m.shardID, m.path, readOnly) } + func (m *fstreeMetrics) Close() { m.m.Close(m.shardID, m.path) } @@ -35,24 +36,29 @@ func (m *fstreeMetrics) Close() { func (m *fstreeMetrics) Iterate(d time.Duration, success bool) { m.m.MethodDuration(m.shardID, m.path, "Iterate", d, success) } + func (m *fstreeMetrics) Delete(d time.Duration, success bool) { m.m.MethodDuration(m.shardID, m.path, "Delete", d, success) } + func (m *fstreeMetrics) Exists(d time.Duration, success bool) { m.m.MethodDuration(m.shardID, m.path, "Exists", d, success) } + func (m *fstreeMetrics) Put(d time.Duration, size int, success bool) { m.m.MethodDuration(m.shardID, m.path, "Put", d, success) if success { m.m.AddPut(m.shardID, m.path, size) } } + func (m *fstreeMetrics) Get(d time.Duration, size int, success bool) { m.m.MethodDuration(m.shardID, m.path, "Get", d, success) if success { m.m.AddGet(m.shardID, m.path, size) } } + func (m *fstreeMetrics) GetRange(d time.Duration, size int, success bool) { m.m.MethodDuration(m.shardID, m.path, "GetRange", d, success) if success { diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 2689e345a7..1bc1613419 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -111,6 +111,7 @@ func (t *boltForest) SetMode(m mode.Mode) error { t.metrics.SetMode(m) return nil } + func (t *boltForest) Open(_ context.Context, readOnly bool) error { err := util.MkdirAllX(filepath.Dir(t.path), t.perm) if err != nil { @@ -137,6 +138,7 @@ func (t *boltForest) Open(_ context.Context, readOnly bool) error { t.metrics.SetMode(m) return nil } + func (t *boltForest) Init() error { if t.mode.NoMetabase() || t.db.IsReadOnly() { return nil @@ -150,6 +152,7 @@ func (t *boltForest) Init() error { return err }) } + func (t *boltForest) Close() error { var err error if t.db != nil { diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index e5612d2b95..b82e5b3bd2 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -71,7 +71,8 @@ func (f *memoryForest) TreeAddByPath(_ context.Context, d CIDDescriptor, treeID Parent: node, Meta: Meta{ Time: s.timestamp(d.Position, d.Size), - Items: []KeyValue{{Key: attr, Value: []byte(path[j])}}}, + Items: []KeyValue{{Key: attr, Value: []byte(path[j])}}, + }, Child: s.findSpareID(), }) lm[j-i] = op.Move @@ -113,9 +114,11 @@ func (f *memoryForest) Init() error { func (f *memoryForest) Open(context.Context, bool) error { return nil } + func (f *memoryForest) SetMode(mode.Mode) error { return nil } + func (f *memoryForest) Close() error { return nil } diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 8e7fec2007..67454b6861 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -36,7 +36,8 @@ var providers = []struct { f := NewBoltForest( append([]Option{ WithPath(filepath.Join(t.TempDir(), "test.db")), - WithMaxBatchSize(1)}, opts...)...) + WithMaxBatchSize(1), + }, opts...)...) require.NoError(t, f.Open(context.Background(), false)) require.NoError(t, f.Init()) t.Cleanup(func() { @@ -68,7 +69,8 @@ func testForestTreeMove(t *testing.T, s Forest) { meta := []KeyValue{ {Key: AttributeVersion, Value: []byte("XXX")}, - {Key: AttributeFilename, Value: []byte("file.txt")}} + {Key: AttributeFilename, Value: []byte("file.txt")}, + } lm, err := s.TreeAddByPath(context.Background(), d, treeID, AttributeFilename, []string{"path", "to"}, meta) require.NoError(t, err) require.Equal(t, 3, len(lm)) @@ -261,7 +263,8 @@ func testForestTreeAdd(t *testing.T, s Forest) { meta := []KeyValue{ {Key: AttributeVersion, Value: []byte("XXX")}, - {Key: AttributeFilename, Value: []byte("file.txt")}} + {Key: AttributeFilename, Value: []byte("file.txt")}, + } m := &Move{ Parent: RootID, Child: RootID, @@ -306,7 +309,8 @@ func testForestTreeAddByPath(t *testing.T, s Forest) { meta := []KeyValue{ {Key: AttributeVersion, Value: []byte("XXX")}, - {Key: AttributeFilename, Value: []byte("file.txt")}} + {Key: AttributeFilename, Value: []byte("file.txt")}, + } t.Run("invalid descriptor", func(t *testing.T) { _, err := s.TreeAddByPath(context.Background(), CIDDescriptor{cid, 0, 0}, treeID, AttributeFilename, []string{"yyy"}, meta) @@ -381,7 +385,8 @@ func testForestTreeAddByPath(t *testing.T, s Forest) { testMeta(t, s, cid, treeID, oldMove.Child, oldMove.Parent, Meta{Time: oldMove.Time, Items: []KeyValue{ {AttributeVersion, []byte("SomeValue")}, - {AttributeFilename, []byte("another")}}}) + {AttributeFilename, []byte("another")}, + }}) t.Run("get by path", func(t *testing.T) { nodes, err := s.TreeGetByPath(context.Background(), cid, treeID, AttributeFilename, []string{"path", "another"}, false) @@ -399,7 +404,8 @@ func testForestTreeAddByPath(t *testing.T, s Forest) { t.Run("empty component", func(t *testing.T) { meta := []KeyValue{ {Key: AttributeVersion, Value: []byte("XXX")}, - {Key: AttributeFilename, Value: []byte{}}} + {Key: AttributeFilename, Value: []byte{}}, + } lm, err := s.TreeAddByPath(context.Background(), d, treeID, AttributeFilename, []string{"path", "to"}, meta) require.NoError(t, err) require.Equal(t, 1, len(lm)) diff --git a/pkg/local_object_storage/pilorama/meta_test.go b/pkg/local_object_storage/pilorama/meta_test.go index 9df4c7e94b..f329f60924 100644 --- a/pkg/local_object_storage/pilorama/meta_test.go +++ b/pkg/local_object_storage/pilorama/meta_test.go @@ -21,7 +21,8 @@ func TestMeta_Bytes(t *testing.T) { Items: []KeyValue{ {"abc", []byte{1, 2, 3}}, {AttributeFilename, []byte{}}, - }} + }, + } data := expected.Bytes() @@ -35,7 +36,8 @@ func TestMeta_Bytes(t *testing.T) { Items: []KeyValue{ {"abc", []byte{1, 2, 3}}, {"xyz", []byte{5, 6, 7, 8}}, - }} + }, + } data := expected.Bytes() diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 332cdf5be0..b64cb9c407 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -101,7 +101,7 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { _, err = sh.Get(context.Background(), getPrm) require.NoError(t, err, "failed to get") - //inhume + // inhume var inhumePrm InhumePrm inhumePrm.MarkAsGarbage(addr) _, err = sh.Inhume(context.Background(), inhumePrm) @@ -110,13 +110,13 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { require.Error(t, err, "get returned error") require.True(t, client.IsErrObjectNotFound(err), "invalid error type") - //storageID + // storageID var metaStIDPrm meta.StorageIDPrm metaStIDPrm.SetAddress(addr) storageID, err := sh.metaBase.StorageID(context.Background(), metaStIDPrm) require.NoError(t, err, "failed to get storage ID") - //check existence in blobstore + // check existence in blobstore var bsExisted common.ExistsPrm bsExisted.Address = addr bsExisted.StorageID = storageID.StorageID() @@ -124,19 +124,19 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { require.NoError(t, err, "failed to check blobstore existence") require.True(t, exRes.Exists, "invalid blobstore existence result") - //drop from blobstor + // drop from blobstor var bsDeletePrm common.DeletePrm bsDeletePrm.Address = addr bsDeletePrm.StorageID = storageID.StorageID() _, err = sh.blobStor.Delete(context.Background(), bsDeletePrm) require.NoError(t, err, "failed to delete from blobstore") - //check existence in blobstore + // check existence in blobstore exRes, err = sh.blobStor.Exists(context.Background(), bsExisted) require.NoError(t, err, "failed to check blobstore existence") require.False(t, exRes.Exists, "invalid blobstore existence result") - //get should return object not found + // get should return object not found _, err = sh.Get(context.Background(), getPrm) require.Error(t, err, "get returned no error") require.True(t, client.IsErrObjectNotFound(err), "invalid error type") diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index 9cfa267e86..fc1fc2d20a 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -41,7 +41,8 @@ func TestShardReload(t *testing.T) { metaOpts := []meta.Option{ meta.WithPath(filepath.Join(p, "meta")), - meta.WithEpochState(epochState{})} + meta.WithEpochState(epochState{}), + } opts := []Option{ WithID(NewIDFromBytes([]byte{})), @@ -49,7 +50,8 @@ func TestShardReload(t *testing.T) { WithBlobStorOptions(blobOpts...), WithMetaBaseOptions(metaOpts...), WithPiloramaOptions( - pilorama.WithPath(filepath.Join(p, "pilorama")))} + pilorama.WithPath(filepath.Join(p, "pilorama"))), + } sh := New(opts...) require.NoError(t, sh.Open(context.Background())) diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 9da9eb6b87..811c7f3abf 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -94,7 +94,8 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard WithBlobStorOptions(o.bsOpts...), WithMetaBaseOptions( append([]meta.Option{ - meta.WithPath(filepath.Join(o.rootPath, "meta")), meta.WithEpochState(epochState{})}, + meta.WithPath(filepath.Join(o.rootPath, "meta")), meta.WithEpochState(epochState{}), + }, o.metaOptions...)..., ), WithPiloramaOptions(pilorama.WithPath(filepath.Join(o.rootPath, "pilorama"))), diff --git a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go b/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go index 9d54cd5c25..9bbf5b7df0 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go @@ -55,9 +55,7 @@ const ( defaultMaxCacheSize = 1 << 30 // 1 GiB ) -var ( - defaultBucket = []byte{0} -) +var defaultBucket = []byte{0} // New creates new writecache instance. func New(opts ...Option) writecache.Cache { diff --git a/pkg/local_object_storage/writecache/writecachebbolt/state.go b/pkg/local_object_storage/writecache/writecachebbolt/state.go index 8749ec6019..9261b2606f 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/state.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/state.go @@ -13,7 +13,7 @@ func (c *cache) estimateCacheSize() uint64 { dbCount := c.objCounters.DB() fsCount := c.objCounters.FS() if fsCount > 0 { - fsCount-- //db file + fsCount-- // db file } dbSize := dbCount * c.smallObjectSize fsSize := fsCount * c.maxObjectSize diff --git a/pkg/metrics/replicator.go b/pkg/metrics/replicator.go index a1519ac95b..ca72a30318 100644 --- a/pkg/metrics/replicator.go +++ b/pkg/metrics/replicator.go @@ -5,8 +5,6 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -//TODO - type ReplicatorMetrics interface { IncInFlightRequest() DecInFlightRequest() diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index e7e1bbca95..50a9572d46 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -55,9 +55,7 @@ const ( defaultWaitInterval = 500 * time.Millisecond ) -var ( - ErrNoHealthyEndpoint = errors.New("no healthy endpoint") -) +var ErrNoHealthyEndpoint = errors.New("no healthy endpoint") func defaultConfig() *cfg { return &cfg{ diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index c8702b1c75..9dd3a337be 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -42,9 +42,7 @@ const ( putNamedMethod = "putNamed" ) -var ( - errNilArgument = errors.New("empty argument") -) +var errNilArgument = errors.New("empty argument") // NewFromMorph returns the wrapper instance from the raw morph client. // diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 7ceaa02507..4769c038c0 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -22,7 +22,7 @@ func (a *AddPeerPrm) SetNodeInfo(nodeInfo netmap.NodeInfo) { // AddPeer registers peer in FrostFS network through // Netmap contract call. func (c *Client) AddPeer(p AddPeerPrm) error { - var method = addPeerMethod + method := addPeerMethod if c.client.WithNotary() && c.client.IsAlpha() { // In notary environments Alphabet must calls AddPeerIR method instead of AddPeer. diff --git a/pkg/morph/event/frostfs/ir_update_test.go b/pkg/morph/event/frostfs/ir_update_test.go index 8ce6fdc366..fae87e5f94 100644 --- a/pkg/morph/event/frostfs/ir_update_test.go +++ b/pkg/morph/event/frostfs/ir_update_test.go @@ -16,13 +16,11 @@ func genKey(t *testing.T) *keys.PrivateKey { } func TestParseUpdateInnerRing(t *testing.T) { - var ( - publicKeys = []*keys.PublicKey{ - genKey(t).PublicKey(), - genKey(t).PublicKey(), - genKey(t).PublicKey(), - } - ) + publicKeys := []*keys.PublicKey{ + genKey(t).PublicKey(), + genKey(t).PublicKey(), + genKey(t).PublicKey(), + } t.Run("wrong number of parameters", func(t *testing.T) { prms := []stackitem.Item{ diff --git a/pkg/morph/event/listener_test.go b/pkg/morph/event/listener_test.go index dc7ac3b813..ae92bd5803 100644 --- a/pkg/morph/event/listener_test.go +++ b/pkg/morph/event/listener_test.go @@ -147,7 +147,6 @@ func TestErrorPassing(t *testing.T) { require.ErrorIs(t, err, bErr, "invalid block error") }) - } type testSubscriber struct { @@ -166,6 +165,7 @@ func (s *testSubscriber) UnsubscribeForNotification() {} func (s *testSubscriber) BlockNotifications() error { return s.blockErr } + func (s *testSubscriber) SubscribeForNotaryRequests(mainTXSigner util.Uint160) error { return nil } diff --git a/pkg/morph/event/utils.go b/pkg/morph/event/utils.go index 2a7c6250d5..f3b6443fbf 100644 --- a/pkg/morph/event/utils.go +++ b/pkg/morph/event/utils.go @@ -88,7 +88,6 @@ func WorkerPoolHandler(w util2.WorkerPool, h Handler, log *logger.Logger) Handle err := w.Submit(func() { h(e) }) - if err != nil { log.Warn(logs.EventCouldNotSubmitHandlerToWorkerPool, zap.String("error", err.Error()), diff --git a/pkg/morph/subscriber/subscriber.go b/pkg/morph/subscriber/subscriber.go index c291988fd9..ee5466a7de 100644 --- a/pkg/morph/subscriber/subscriber.go +++ b/pkg/morph/subscriber/subscriber.go @@ -296,7 +296,8 @@ drainloop: // restoreSubscriptions restores subscriptions according to // cached information about them. func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotificationEvent, - blCh chan<- *block.Block, notaryCh chan<- *result.NotaryRequestEvent) bool { + blCh chan<- *block.Block, notaryCh chan<- *result.NotaryRequestEvent, +) bool { var err error // new block events restoration diff --git a/pkg/network/transport/netmap/grpc/service.go b/pkg/network/transport/netmap/grpc/service.go index 7a3aec86c2..406c77e58c 100644 --- a/pkg/network/transport/netmap/grpc/service.go +++ b/pkg/network/transport/netmap/grpc/service.go @@ -24,7 +24,8 @@ func New(c netmapsvc.Server) *Server { // LocalNodeInfo converts gRPC request message and passes it to internal netmap service. func (s *Server) LocalNodeInfo( ctx context.Context, - req *netmapGRPC.LocalNodeInfoRequest) (*netmapGRPC.LocalNodeInfoResponse, error) { + req *netmapGRPC.LocalNodeInfoRequest, +) (*netmapGRPC.LocalNodeInfoResponse, error) { nodeInfoReq := new(netmap.LocalNodeInfoRequest) if err := nodeInfoReq.FromGRPCMessage(req); err != nil { return nil, err diff --git a/pkg/services/container/morph/executor_test.go b/pkg/services/container/morph/executor_test.go index a270ee856a..42dd0b77ee 100644 --- a/pkg/services/container/morph/executor_test.go +++ b/pkg/services/container/morph/executor_test.go @@ -51,7 +51,8 @@ func TestInvalidToken(t *testing.T) { sign := func(reqBody interface { StableMarshal([]byte) []byte SetSignature(signature *refs.Signature) - }) { + }, + ) { signer := frostfsecdsa.Signer(priv.PrivateKey) var sig frostfscrypto.Signature require.NoError(t, sig.Calculate(signer, reqBody.StableMarshal(nil))) diff --git a/pkg/services/control/service_test.go b/pkg/services/control/service_test.go index 8c96e2b730..1d98cc6f1e 100644 --- a/pkg/services/control/service_test.go +++ b/pkg/services/control/service_test.go @@ -103,6 +103,7 @@ func equalListShardResponseBodies(b1, b2 *control.ListShardsResponse_Body) bool return true } + func compareBlobstorInfo(a, b []*control.BlobstorInfo) bool { if len(a) != len(b) { return false diff --git a/pkg/services/control/types_test.go b/pkg/services/control/types_test.go index 1505a985c4..df0cdf141a 100644 --- a/pkg/services/control/types_test.go +++ b/pkg/services/control/types_test.go @@ -142,7 +142,8 @@ func generateShardInfo(id int) *control.ShardInfo { si.SetMetabasePath(filepath.Join(path, "meta")) si.Blobstor = []*control.BlobstorInfo{ {Type: fstree.Type, Path: filepath.Join(path, "fstree")}, - {Type: blobovniczatree.Type, Path: filepath.Join(path, "blobtree")}} + {Type: blobovniczatree.Type, Path: filepath.Join(path, "blobtree")}, + } si.SetWriteCachePath(filepath.Join(path, "writecache")) si.SetPiloramaPath(filepath.Join(path, "pilorama")) diff --git a/pkg/services/netmap/executor.go b/pkg/services/netmap/executor.go index d1e7a949e6..496b07a981 100644 --- a/pkg/services/netmap/executor.go +++ b/pkg/services/netmap/executor.go @@ -64,7 +64,8 @@ func NewExecutionService(s NodeState, v versionsdk.Version, netInfo NetworkInfo, func (s *executorSvc) LocalNodeInfo( _ context.Context, - req *netmap.LocalNodeInfoRequest) (*netmap.LocalNodeInfoResponse, error) { + req *netmap.LocalNodeInfoRequest, +) (*netmap.LocalNodeInfoResponse, error) { verV2 := req.GetMetaHeader().GetVersion() if verV2 == nil { return nil, errors.New("missing version") @@ -106,7 +107,8 @@ func (s *executorSvc) LocalNodeInfo( func (s *executorSvc) NetworkInfo( _ context.Context, - req *netmap.NetworkInfoRequest) (*netmap.NetworkInfoResponse, error) { + req *netmap.NetworkInfoRequest, +) (*netmap.NetworkInfoResponse, error) { verV2 := req.GetMetaHeader().GetVersion() if verV2 == nil { return nil, errors.New("missing protocol version in meta header") diff --git a/pkg/services/netmap/sign.go b/pkg/services/netmap/sign.go index 305d3443e1..9a16ad8f1f 100644 --- a/pkg/services/netmap/sign.go +++ b/pkg/services/netmap/sign.go @@ -23,7 +23,8 @@ func NewSignService(key *ecdsa.PrivateKey, svc Server) Server { func (s *signService) LocalNodeInfo( ctx context.Context, - req *netmap.LocalNodeInfoRequest) (*netmap.LocalNodeInfoResponse, error) { + req *netmap.LocalNodeInfoRequest, +) (*netmap.LocalNodeInfoResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(netmap.LocalNodeInfoResponse) return resp, s.sigSvc.SignResponse(resp, err) diff --git a/pkg/services/object/acl/v2/errors.go b/pkg/services/object/acl/v2/errors.go index 7fc20d618b..11b9e6e5fb 100644 --- a/pkg/services/object/acl/v2/errors.go +++ b/pkg/services/object/acl/v2/errors.go @@ -21,8 +21,10 @@ var ( errInvalidVerb = malformedRequestError("session token verb is invalid") ) -const accessDeniedACLReasonFmt = "access to operation %s is denied by basic ACL check" -const accessDeniedEACLReasonFmt = "access to operation %s is denied by extended ACL check: %v" +const ( + accessDeniedACLReasonFmt = "access to operation %s is denied by basic ACL check" + accessDeniedEACLReasonFmt = "access to operation %s is denied by extended ACL check: %v" +) func basicACLErr(info RequestInfo) error { errAccessDenied := &apistatus.ObjectAccessDenied{} diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 8239403a78..b5bd3d4f43 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -80,7 +80,8 @@ func New(next object.ServiceServer, irf InnerRingFetcher, acl ACLChecker, cs container.Source, - opts ...Option) Service { + opts ...Option, +) Service { cfg := &cfg{ log: &logger.Logger{Logger: zap.L()}, next: next, @@ -168,7 +169,8 @@ func (b Service) Put() (object.PutObjectStream, error) { func (b Service) Head( ctx context.Context, - request *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { + request *objectV2.HeadRequest, +) (*objectV2.HeadResponse, error) { cnr, err := getContainerIDFromRequest(request) if err != nil { return nil, err @@ -276,7 +278,8 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr func (b Service) Delete( ctx context.Context, - request *objectV2.DeleteRequest) (*objectV2.DeleteResponse, error) { + request *objectV2.DeleteRequest, +) (*objectV2.DeleteResponse, error) { cnr, err := getContainerIDFromRequest(request) if err != nil { return nil, err @@ -384,7 +387,8 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb func (b Service) GetRangeHash( ctx context.Context, - request *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) { + request *objectV2.GetRangeHashRequest, +) (*objectV2.GetRangeHashResponse, error) { cnr, err := getContainerIDFromRequest(request) if err != nil { return nil, err diff --git a/pkg/services/object/delete/service.go b/pkg/services/object/delete/service.go index b74a4c7ba4..0ba4da4379 100644 --- a/pkg/services/object/delete/service.go +++ b/pkg/services/object/delete/service.go @@ -69,7 +69,8 @@ func New(gs *getsvc.Service, ps *putsvc.Service, ni NetworkInfo, ks *util.KeyStorage, - opts ...Option) *Service { + opts ...Option, +) *Service { c := &cfg{ log: &logger.Logger{Logger: zap.L()}, header: &headSvcWrapper{s: gs}, diff --git a/pkg/services/object/get/assembler.go b/pkg/services/object/get/assembler.go index 61de0ee993..f10c67e524 100644 --- a/pkg/services/object/get/assembler.go +++ b/pkg/services/object/get/assembler.go @@ -29,7 +29,8 @@ func newAssembler( addr oid.Address, splitInfo *objectSDK.SplitInfo, rng *objectSDK.Range, - objGetter objectGetter) *assembler { + objGetter objectGetter, +) *assembler { return &assembler{ addr: addr, rng: rng, diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index e3037a70b7..3d5547047c 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -23,6 +23,7 @@ func (s *Service) GetRange(ctx context.Context, prm RangePrm) error { rng: prm.rng, }) } + func (s *Service) GetRangeHash(ctx context.Context, prm RangeHashPrm) (*RangeHashRes, error) { hashes := make([][]byte, 0, len(prm.rngs)) diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 3ac4872650..f4d4f7372f 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -233,8 +233,7 @@ func (whe *writeHeaderError) Error() string { return "write header error" } -type writeHeaderErrorObjectWriter struct { -} +type writeHeaderErrorObjectWriter struct{} func (w *writeHeaderErrorObjectWriter) WriteHeader(_ context.Context, _ *objectSDK.Object) error { return &writeHeaderError{} @@ -250,8 +249,7 @@ func (whe *writePayloadError) Error() string { return "write payload error" } -type writePayloadErrorObjectWriter struct { -} +type writePayloadErrorObjectWriter struct{} func (w *writePayloadErrorObjectWriter) WriteHeader(_ context.Context, _ *objectSDK.Object) error { return nil @@ -261,8 +259,7 @@ func (w *writePayloadErrorObjectWriter) WriteChunk(_ context.Context, _ []byte) return &writePayloadError{} } -type testKeyStorage struct { -} +type testKeyStorage struct{} func (ks *testKeyStorage) GetKey(_ *util.SessionInfo) (*ecdsa.PrivateKey, error) { return &ecdsa.PrivateKey{}, nil @@ -1289,7 +1286,6 @@ func TestGetRemoteSmall(t *testing.T) { err := svc.GetRange(ctx, p) require.ErrorAs(t, err, new(*apistatus.ObjectOutOfRange)) }) - }) t.Run("right child", func(t *testing.T) { diff --git a/pkg/services/object/internal/key.go b/pkg/services/object/internal/key.go index 7ab5f082ca..eba7169769 100644 --- a/pkg/services/object/internal/key.go +++ b/pkg/services/object/internal/key.go @@ -10,7 +10,8 @@ import ( // VerifyResponseKeyV2 checks if response is signed with expected key. Returns client.ErrWrongPublicKey if not. func VerifyResponseKeyV2(expectedKey []byte, resp interface { GetVerificationHeader() *session.ResponseVerificationHeader -}) error { +}, +) error { if !bytes.Equal(resp.GetVerificationHeader().GetBodySignature().GetKey(), expectedKey) { return client.ErrWrongPublicKey } diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index 3a7dcefd6d..a93873738f 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -72,7 +72,8 @@ func NewService(ks *objutil.KeyStorage, nk netmap.AnnouncedKeys, nst netmap.State, ir InnerRing, - opts ...Option) *Service { + opts ...Option, +) *Service { c := &cfg{ remotePool: util.NewPseudoWorkerPool(), localPool: util.NewPseudoWorkerPool(), diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 3865aabb9c..183b2310d0 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -201,7 +201,8 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb } func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *nodeDesc, obj *objectSDK.Object, - signer *putSingleRequestSigner, meta object.ContentMeta) error { + signer *putSingleRequestSigner, meta object.ContentMeta, +) error { if nodeDesc.local { return s.saveLocal(ctx, obj, meta) } @@ -229,7 +230,8 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, signer *putSingleRequestSigner, obj *objectSDK.Object, info client.NodeInfo, - c client.MultiAddressClient) error { + c client.MultiAddressClient, +) error { ctx, span := tracing.StartSpanFromContext(ctx, "putService.redirectPutSingleRequest") defer span.End() diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index 863312200c..0a54f54c5c 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -62,7 +62,8 @@ func New(e *engine.StorageEngine, tg *util.TraverserGenerator, ns netmap.Source, ks *util.KeyStorage, - opts ...Option) *Service { + opts ...Option, +) *Service { c := &cfg{ log: &logger.Logger{Logger: zap.L()}, clientConstructor: &clientConstructorWrapper{ diff --git a/pkg/services/object/util/prm.go b/pkg/services/object/util/prm.go index c09c07cc1a..022b9fe5b1 100644 --- a/pkg/services/object/util/prm.go +++ b/pkg/services/object/util/prm.go @@ -109,7 +109,8 @@ func (p *CommonPrm) ForgetTokens() { func CommonPrmFromV2(req interface { GetMetaHeader() *session.RequestMetaHeader -}) (*CommonPrm, error) { +}, +) (*CommonPrm, error) { meta := req.GetMetaHeader() ttl := meta.GetTTL() diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index c042734685..9b44acedaf 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -85,7 +85,8 @@ type placementRequirements struct { } func (p *Policer) processNodes(ctx context.Context, requirements *placementRequirements, addrWithType objectcore.AddressWithType, - nodes []netmap.NodeInfo, shortage uint32, checkedNodes nodeCache) { + nodes []netmap.NodeInfo, shortage uint32, checkedNodes nodeCache, +) { addr := addrWithType.Address typ := addrWithType.Type @@ -175,7 +176,8 @@ func (p *Policer) handleMaintenance(node netmap.NodeInfo, checkedNodes nodeCache } func (p *Policer) handleProcessNodesResult(ctx context.Context, addr oid.Address, requirements *placementRequirements, - nodes []netmap.NodeInfo, checkedNodes nodeCache, shortage uint32, uncheckedCopies int) { + nodes []netmap.NodeInfo, checkedNodes nodeCache, shortage uint32, uncheckedCopies int, +) { switch { case shortage > 0: p.log.Debug(logs.PolicerShortageOfObjectCopiesDetected, @@ -212,8 +214,7 @@ func isClientErrMaintenance(err error) bool { switch unwrapErr(err).(type) { default: return false - case - *apistatus.NodeUnderMaintenance: + case *apistatus.NodeUnderMaintenance: return true } } diff --git a/pkg/services/session/storage/persistent/executor_test.go b/pkg/services/session/storage/persistent/executor_test.go index 860b958974..ee0c8f9151 100644 --- a/pkg/services/session/storage/persistent/executor_test.go +++ b/pkg/services/session/storage/persistent/executor_test.go @@ -166,14 +166,14 @@ func TestTokenStore_RemoveOld(t *testing.T) { // // If this test is passing, TokenStore works correctly. func TestBolt_Cursor(t *testing.T) { - db, err := bbolt.Open(filepath.Join(t.TempDir(), ".storage"), 0666, nil) + db, err := bbolt.Open(filepath.Join(t.TempDir(), ".storage"), 0o666, nil) require.NoError(t, err) defer db.Close() cursorKeys := make(map[string]struct{}) - var bucketName = []byte("bucket") + bucketName := []byte("bucket") err = db.Update(func(tx *bbolt.Tx) (err error) { b, err := tx.CreateBucket(bucketName) diff --git a/pkg/services/session/storage/persistent/storage.go b/pkg/services/session/storage/persistent/storage.go index e4c2091c00..71711e3715 100644 --- a/pkg/services/session/storage/persistent/storage.go +++ b/pkg/services/session/storage/persistent/storage.go @@ -40,7 +40,7 @@ func NewTokenStore(path string, opts ...Option) (*TokenStore, error) { o(cfg) } - db, err := bbolt.Open(path, 0600, + db, err := bbolt.Open(path, 0o600, &bbolt.Options{ Timeout: cfg.timeout, }) diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 88a5b5e063..63cdc73a2f 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -33,7 +33,8 @@ func TestGetSubTree(t *testing.T) { for i := range tree { path := tree[i].path meta := []pilorama.KeyValue{ - {Key: pilorama.AttributeFilename, Value: []byte(path[len(path)-1])}} + {Key: pilorama.AttributeFilename, Value: []byte(path[len(path)-1])}, + } lm, err := p.TreeAddByPath(context.Background(), d, treeID, pilorama.AttributeFilename, path[:len(path)-1], meta) require.NoError(t, err) @@ -141,7 +142,8 @@ func TestGetSubTreeOrderAsc(t *testing.T) { for i := range tree { path := tree[i].path meta := []pilorama.KeyValue{ - {Key: pilorama.AttributeFilename, Value: []byte(path[len(path)-1])}} + {Key: pilorama.AttributeFilename, Value: []byte(path[len(path)-1])}, + } lm, err := p.TreeAddByPath(context.Background(), d, treeID, pilorama.AttributeFilename, path[:len(path)-1], meta) require.NoError(t, err) diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 6dad22774b..15067d3cd4 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -37,9 +37,11 @@ func eACLErr(op eacl.Operation, err error) error { return fmt.Errorf("access to operation %s is denied by extended ACL check: %w", op, err) } -var errBearerWrongOwner = errors.New("bearer token must be signed by the container owner") -var errBearerWrongContainer = errors.New("bearer token is created for another container") -var errBearerSignature = errors.New("invalid bearer token signature") +var ( + errBearerWrongOwner = errors.New("bearer token must be signed by the container owner") + errBearerWrongContainer = errors.New("bearer token is created for another container") + errBearerSignature = errors.New("invalid bearer token signature") +) // verifyClient verifies if the request for a client operation // was signed by a key allowed by (e)ACL rules. @@ -261,8 +263,10 @@ func eACLRole(role acl.Role) eacl.Role { } } -var errDENY = errors.New("DENY eACL rule") -var errNoAllowRules = errors.New("not found allowing rules for the request") +var ( + errDENY = errors.New("DENY eACL rule") + errNoAllowRules = errors.New("not found allowing rules for the request") +) // checkEACL searches for the eACL rules that could be applied to the request // (a tuple of a signer key, his FrostFS role and a request operation). diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 9cff8b3517..f5a7fbce66 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -176,7 +176,8 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram } func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID string, - operationStream <-chan *pilorama.Move) uint64 { + operationStream <-chan *pilorama.Move, +) uint64 { errGroup, _ := errgroup.WithContext(ctx) const workersCount = 1024 errGroup.SetLimit(workersCount) @@ -215,7 +216,8 @@ func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID s } func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, - height uint64, treeClient TreeServiceClient, opsCh chan<- *pilorama.Move) (uint64, error) { + height uint64, treeClient TreeServiceClient, opsCh chan<- *pilorama.Move, +) (uint64, error) { rawCID := make([]byte, sha256.Size) cid.Encode(rawCID) @@ -261,11 +263,9 @@ func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, // already applied operation and keep good batching. // The method returns a height that service should start sync from in the next time. func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, - treeID string, nodes []netmapSDK.NodeInfo) uint64 { - s.log.Debug(logs.TreeSynchronizeTree, - zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.Uint64("from", from)) + treeID string, nodes []netmapSDK.NodeInfo, +) uint64 { + s.log.Debug(logs.TreeSynchronizeTree, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.Uint64("from", from)) errGroup, egCtx := errgroup.WithContext(ctx) const workersCount = 1024 diff --git a/pkg/util/locode/table/csv/opts.go b/pkg/util/locode/table/csv/opts.go index 5aaffd7c17..68e442899c 100644 --- a/pkg/util/locode/table/csv/opts.go +++ b/pkg/util/locode/table/csv/opts.go @@ -15,7 +15,7 @@ type options struct { func defaultOpts() *options { return &options{ - mode: 0700, + mode: 0o700, } } diff --git a/pkg/util/os.go b/pkg/util/os.go index 1c4c97806c..30e08a8c36 100644 --- a/pkg/util/os.go +++ b/pkg/util/os.go @@ -6,5 +6,5 @@ import "os" // but with +x for a user and a group. This makes the created // dir openable regardless of the passed permissions. func MkdirAllX(path string, perm os.FileMode) error { - return os.MkdirAll(path, perm|0110) + return os.MkdirAll(path, perm|0o110) } diff --git a/pkg/util/state/storage.go b/pkg/util/state/storage.go index 0485b14813..ee957f270e 100644 --- a/pkg/util/state/storage.go +++ b/pkg/util/state/storage.go @@ -19,7 +19,7 @@ var stateBucket = []byte("state") // NewPersistentStorage creates a new instance of a storage with 0600 rights. func NewPersistentStorage(path string) (*PersistentStorage, error) { - db, err := bbolt.Open(path, 0600, nil) + db, err := bbolt.Open(path, 0o600, nil) if err != nil { return nil, fmt.Errorf("can't open bbolt at %s: %w", path, err) } diff --git a/scripts/export-metrics/main.go b/scripts/export-metrics/main.go index f29eca37c5..63571e96d4 100644 --- a/scripts/export-metrics/main.go +++ b/scripts/export-metrics/main.go @@ -45,7 +45,7 @@ func main() { os.Exit(1) } - if err := os.WriteFile(filename, data, 0644); err != nil { + if err := os.WriteFile(filename, data, 0o644); err != nil { fmt.Fprintf(os.Stderr, "Could write to file: %v\n", err) os.Exit(1) } From 990f9f2d2b5228503840d07e78b6c14815359cdc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 31 Oct 2023 16:59:38 +0300 Subject: [PATCH 0106/1413] [#772] makefile: Replace gofmt with gofumpt Signed-off-by: Dmitrii Stepanov --- Makefile | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 7fa4e43170..14e32e40f6 100755 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ OUTPUT_LINT_DIR ?= $(shell pwd)/bin LINT_DIR = $(OUTPUT_LINT_DIR)/golangci-lint-$(LINT_VERSION)-v$(TRUECLOUDLAB_LINT_VERSION) TMP_DIR := .cache -.PHONY: help all images dep clean fmts fmt imports test lint docker/lint +.PHONY: help all images dep clean fmts fumpt imports test lint docker/lint prepare-release debpackage pre-commit unpre-commit # To build a specific binary, use it's name prefix with bin/ as a target @@ -122,18 +122,17 @@ docker/%: # Run all code formatters -fmts: fmt imports - -# Reformat code -fmt: - @echo "⇒ Processing gofmt check" - @gofmt -s -w cmd/ pkg/ misc/ +fmts: fumpt imports # Reformat imports imports: @echo "⇒ Processing goimports check" @goimports -w cmd/ pkg/ misc/ +fumpt: + @echo "⇒ Processing gofumpt check" + @gofumpt -l -w cmd/ pkg/ misc/ + # Run Unit Test with go test test: @echo "⇒ Running go test" From 8a82335b5c4844bf5758d5948a7b51304d0b362f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 31 Oct 2023 17:00:57 +0300 Subject: [PATCH 0107/1413] [#772] pre-commit: Add gofumpt check Signed-off-by: Dmitrii Stepanov --- .pre-commit-config.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f20bdc847..ecd70390c5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,6 +47,15 @@ repos: types: [go] language: system + - repo: local + hooks: + - id: gofumpt + name: gofumpt + entry: make fumpt + pass_filenames: false + types: [go] + language: system + - repo: https://github.com/TekWizely/pre-commit-golang rev: v1.0.0-rc.1 hooks: From 05b508f79a04dd8281b4137ee54313044b1b1a12 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 31 Oct 2023 17:01:27 +0300 Subject: [PATCH 0108/1413] [#772] proto: Fix file ending Signed-off-by: Dmitrii Stepanov --- pkg/services/control/ir/service.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/control/ir/service.proto b/pkg/services/control/ir/service.proto index 6c85ba4b9a..cd890d438d 100644 --- a/pkg/services/control/ir/service.proto +++ b/pkg/services/control/ir/service.proto @@ -93,4 +93,4 @@ message RemoveContainerResponse { Body body = 1; Signature signature = 2; -} \ No newline at end of file +} From c80b46fad351e4860c743614d32fa5e81ca8ecce Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 31 Oct 2023 14:45:22 +0300 Subject: [PATCH 0109/1413] [#754] blobstor: Estimate compressability Now it is possible to enable compressability estimation. If data is likely uncompressable, it should reduce CPU time and memory. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 9 +++- cmd/frostfs-node/config/cast.go | 12 +++++ cmd/frostfs-node/config/engine/config_test.go | 2 + .../config/engine/shard/config.go | 31 +++++++++++- config/example/node.env | 2 + config/example/node.json | 2 + config/example/node.yaml | 2 + docs/storage-node-configuration.md | 20 ++++---- pkg/local_object_storage/blobstor/blobstor.go | 21 ++++++++ .../blobstor/compression/bench_test.go | 49 +++++++++++++++++++ .../blobstor/compression/compress.go | 15 ++++++ 11 files changed, 153 insertions(+), 12 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 8a7317231e..6580de1571 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -105,7 +105,10 @@ type applicationConfiguration struct { } type shardCfg struct { - compress bool + compress bool + estimateCompressibility bool + estimateCompressibilityThreshold float64 + smallSizeObjectLimit uint64 uncompressableContentType []string refillMetabase bool @@ -217,6 +220,8 @@ func (a *applicationConfiguration) updateShardConfig(c *config.Config, oldConfig newConfig.refillMetabase = oldConfig.RefillMetabase() newConfig.mode = oldConfig.Mode() newConfig.compress = oldConfig.Compress() + newConfig.estimateCompressibility = oldConfig.EstimateCompressibility() + newConfig.estimateCompressibilityThreshold = oldConfig.EstimateCompressibilityThreshold() newConfig.uncompressableContentType = oldConfig.UncompressableContentTypes() newConfig.smallSizeObjectLimit = oldConfig.SmallSizeLimit() @@ -830,6 +835,8 @@ func (c *cfg) getShardOpts(shCfg shardCfg) shardOptsWithID { blobstoreOpts := []blobstor.Option{ blobstor.WithCompressObjects(shCfg.compress), blobstor.WithUncompressableContentTypes(shCfg.uncompressableContentType), + blobstor.WithCompressibilityEstimate(shCfg.estimateCompressibility), + blobstor.WithCompressibilityEstimateThreshold(shCfg.estimateCompressibilityThreshold), blobstor.WithStorages(ss), blobstor.WithLogger(c.log), } diff --git a/cmd/frostfs-node/config/cast.go b/cmd/frostfs-node/config/cast.go index 9036c3ab0a..c99d335692 100644 --- a/cmd/frostfs-node/config/cast.go +++ b/cmd/frostfs-node/config/cast.go @@ -223,3 +223,15 @@ func parseSizeInBytes(sizeStr string) uint64 { size := cast.ToFloat64(sizeStr) return safeMul(size, multiplier) } + +// FloatOrDefault reads a configuration value +// from c by name and casts it to float64. +// +// Returns defaultValue if the value can not be casted. +func FloatOrDefault(c *Config, name string, defaultValue float64) float64 { + v, err := cast.ToFloat64E(c.Value(name)) + if err != nil { + return defaultValue + } + return v +} diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 4077b17444..6b7c268ceb 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -84,6 +84,8 @@ func TestEngineSection(t *testing.T) { require.Equal(t, true, sc.Compress()) require.Equal(t, []string{"audio/*", "video/*"}, sc.UncompressableContentTypes()) + require.Equal(t, true, sc.EstimateCompressibility()) + require.Equal(t, float64(0.7), sc.EstimateCompressibilityThreshold()) require.EqualValues(t, 102400, sc.SmallSizeLimit()) require.Equal(t, 2, len(ss)) diff --git a/cmd/frostfs-node/config/engine/shard/config.go b/cmd/frostfs-node/config/engine/shard/config.go index 1dc32fb863..16100c3a78 100644 --- a/cmd/frostfs-node/config/engine/shard/config.go +++ b/cmd/frostfs-node/config/engine/shard/config.go @@ -16,8 +16,11 @@ import ( // which provides access to Shard configurations. type Config config.Config -// SmallSizeLimitDefault is a default limit of small objects payload in bytes. -const SmallSizeLimitDefault = 1 << 20 +const ( + // SmallSizeLimitDefault is a default limit of small objects payload in bytes. + SmallSizeLimitDefault = 1 << 20 + EstimateCompressibilityThresholdDefault = 0.1 +) // From wraps config section into Config. func From(c *config.Config) *Config { @@ -43,6 +46,30 @@ func (x *Config) UncompressableContentTypes() []string { "compression_exclude_content_types") } +// EstimateCompressibility returns the value of "estimate_compressibility" config parameter. +// +// Returns false if the value is not a valid bool. +func (x *Config) EstimateCompressibility() bool { + return config.BoolSafe( + (*config.Config)(x), + "compression_estimate_compressibility", + ) +} + +// EstimateCompressibilityThreshold returns the value of "estimate_compressibility_threshold" config parameter. +// +// Returns EstimateCompressibilityThresholdDefault if the value is not defined, not valid float or not in range [0.0; 1.0]. +func (x *Config) EstimateCompressibilityThreshold() float64 { + v := config.FloatOrDefault( + (*config.Config)(x), + "compression_estimate_compressibility_threshold", + EstimateCompressibilityThresholdDefault) + if v < 0.0 || v > 1.0 { + return EstimateCompressibilityThresholdDefault + } + return v +} + // SmallSizeLimit returns the value of "small_object_size" config parameter. // // Returns SmallSizeLimitDefault if the value is not a positive number. diff --git a/config/example/node.env b/config/example/node.env index fde65173b0..dda740cf16 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -113,6 +113,8 @@ FROSTFS_STORAGE_SHARD_0_METABASE_MAX_BATCH_DELAY=10ms ### Blobstor config FROSTFS_STORAGE_SHARD_0_COMPRESS=true FROSTFS_STORAGE_SHARD_0_COMPRESSION_EXCLUDE_CONTENT_TYPES="audio/* video/*" +FROSTFS_STORAGE_SHARD_0_COMPRESSION_ESTIMATE_COMPRESSIBILITY=true +FROSTFS_STORAGE_SHARD_0_COMPRESSION_ESTIMATE_COMPRESSIBILITY_THRESHOLD=0.7 FROSTFS_STORAGE_SHARD_0_SMALL_OBJECT_SIZE=102400 ### Blobovnicza config FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_PATH=tmp/0/blob/blobovnicza diff --git a/config/example/node.json b/config/example/node.json index e8455ee55f..1038d5e5c0 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -160,6 +160,8 @@ "compression_exclude_content_types": [ "audio/*", "video/*" ], + "compression_estimate_compressibility": true, + "compression_estimate_compressibility_threshold": 0.7, "small_object_size": 102400, "blobstor": [ { diff --git a/config/example/node.yaml b/config/example/node.yaml index 2ca1b426c5..8b2046e954 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -178,6 +178,8 @@ storage: compression_exclude_content_types: - audio/* - video/* + compression_estimate_compressibility: true + compression_estimate_compressibility_threshold: 0.7 blobstor: - type: blobovnicza diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 2e2d04088c..5e9f3caf7b 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -179,15 +179,17 @@ The following table describes configuration for each shard. | Parameter | Type | Default value | Description | |-------------------------------------|---------------------------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `compress` | `bool` | `false` | Flag to enable compression. | -| `compression_exclude_content_types` | `[]string` | | List of content-types to disable compression for. Content-type is taken from `Content-Type` object attribute. Each element can contain a star `*` as a first (last) character, which matches any prefix (suffix). | -| `mode` | `string` | `read-write` | Shard Mode.
Possible values: `read-write`, `read-only`, `degraded`, `degraded-read-only`, `disabled` | -| `resync_metabase` | `bool` | `false` | Flag to enable metabase resync on start. | -| `writecache` | [Writecache config](#writecache-subsection) | | Write-cache configuration. | -| `metabase` | [Metabase config](#metabase-subsection) | | Metabase configuration. | -| `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | -| `small_object_size` | `size` | `1M` | Maximum size of an object stored in blobovnicza tree. | -| `gc` | [GC config](#gc-subsection) | | GC configuration. | +| `compress` | `bool` | `false` | Flag to enable compression. | +| `compression_exclude_content_types` | `[]string` | | List of content-types to disable compression for. Content-type is taken from `Content-Type` object attribute. Each element can contain a star `*` as a first (last) character, which matches any prefix (suffix). | +| `compression_estimate_compressibility` | `bool` | `false` | If `true`, then noramalized compressibility estimation is used to decide compress data or not. | +| `compression_estimate_compressibility_threshold` | `float` | `0.1` | Normilized compressibility estimate threshold: data will compress if estimation if greater than this value. | +| `mode` | `string` | `read-write` | Shard Mode.
Possible values: `read-write`, `read-only`, `degraded`, `degraded-read-only`, `disabled` | +| `resync_metabase` | `bool` | `false` | Flag to enable metabase resync on start. | +| `writecache` | [Writecache config](#writecache-subsection) | | Write-cache configuration. | +| `metabase` | [Metabase config](#metabase-subsection) | | Metabase configuration. | +| `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | +| `small_object_size` | `size` | `1M` | Maximum size of an object stored in blobovnicza tree. | +| `gc` | [GC config](#gc-subsection) | | GC configuration. | ### `blobstor` subsection diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index d2a2338a31..bc9ab2b994 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -107,6 +107,27 @@ func WithCompressObjects(comp bool) Option { } } +// WithCompressibilityEstimate returns an option to use +// normilized compressibility estimate to decide compress +// data or not. +// +// See https://github.com/klauspost/compress/blob/v1.17.2/compressible.go#L5 +func WithCompressibilityEstimate(v bool) Option { + return func(c *cfg) { + c.compression.UseCompressEstimation = v + } +} + +// WithCompressibilityEstimateThreshold returns an option to set +// normilized compressibility estimate threshold. +// +// See https://github.com/klauspost/compress/blob/v1.17.2/compressible.go#L5 +func WithCompressibilityEstimateThreshold(threshold float64) Option { + return func(c *cfg) { + c.compression.CompressEstimationThreshold = threshold + } +} + // WithUncompressableContentTypes returns option to disable decompression // for specific content types as seen by object.AttributeContentType attribute. func WithUncompressableContentTypes(values []string) Option { diff --git a/pkg/local_object_storage/blobstor/compression/bench_test.go b/pkg/local_object_storage/blobstor/compression/bench_test.go index 6e05366cfb..986912985b 100644 --- a/pkg/local_object_storage/blobstor/compression/bench_test.go +++ b/pkg/local_object_storage/blobstor/compression/bench_test.go @@ -3,8 +3,10 @@ package compression import ( "crypto/rand" "fmt" + "log" "testing" + "github.com/klauspost/compress" "github.com/stretchr/testify/require" ) @@ -47,3 +49,50 @@ func notSoRandomSlice(size, blockSize int) []byte { } return data } + +func BenchmarkCompressionRealVSEstimate(b *testing.B) { + var total float64 // to prevent from compiler optimizations + maxSize := 60 * 1024 * 1024 + b.Run("estimate", func(b *testing.B) { + b.ResetTimer() + + c := &Config{ + Enabled: true, + } + require.NoError(b, c.Init()) + + for size := 1024; size <= maxSize; size *= 2 { + data := make([]byte, size) + _, err := rand.Reader.Read(data) + require.NoError(b, err) + + b.StartTimer() + estimation := compress.Estimate(data) + total += estimation + b.StopTimer() + } + }) + + b.Run("compress", func(b *testing.B) { + b.ResetTimer() + + c := &Config{ + Enabled: true, + } + require.NoError(b, c.Init()) + + for size := 1024; size <= maxSize; size *= 2 { + data := make([]byte, size) + _, err := rand.Reader.Read(data) + require.NoError(b, err) + + b.StartTimer() + maxSize := c.encoder.MaxEncodedSize(len(data)) + compressed := c.encoder.EncodeAll(data, make([]byte, 0, maxSize)) + total += float64(len(compressed)) / float64(len(data)) + b.StopTimer() + } + }) + + log.Println(total) +} diff --git a/pkg/local_object_storage/blobstor/compression/compress.go b/pkg/local_object_storage/blobstor/compression/compress.go index 270c2b18db..85ab476926 100644 --- a/pkg/local_object_storage/blobstor/compression/compress.go +++ b/pkg/local_object_storage/blobstor/compression/compress.go @@ -5,6 +5,7 @@ import ( "strings" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "github.com/klauspost/compress" "github.com/klauspost/compress/zstd" ) @@ -13,6 +14,9 @@ type Config struct { Enabled bool UncompressableContentTypes []string + UseCompressEstimation bool + CompressEstimationThreshold float64 + encoder *zstd.Encoder decoder *zstd.Decoder } @@ -82,6 +86,17 @@ func (c *Config) Compress(data []byte) []byte { if c == nil || !c.Enabled { return data } + if c.UseCompressEstimation { + estimated := compress.Estimate(data) + if estimated >= c.CompressEstimationThreshold { + return c.compress(data) + } + return data + } + return c.compress(data) +} + +func (c *Config) compress(data []byte) []byte { maxSize := c.encoder.MaxEncodedSize(len(data)) compressed := c.encoder.EncodeAll(data, make([]byte, 0, maxSize)) if len(data) < len(compressed) { From a26483fc30b29a57aa07b8dad0afe43252280cb5 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 27 Oct 2023 15:02:14 +0300 Subject: [PATCH 0110/1413] [#749] morph: Fix panic when closing morph client Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/morph.go | 4 +++ pkg/morph/client/client.go | 2 ++ pkg/morph/client/multi.go | 2 ++ pkg/morph/client/notifications.go | 5 ++- pkg/morph/event/listener.go | 54 +++++++++++++++++++++---------- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index edb1412aa4..f7100d0bf4 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -207,6 +207,10 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { }) fatalOnErr(err) + c.onShutdown(func() { + lis.Stop() + }) + c.workers = append(c.workers, newWorkerFromFunc(func(wCtx context.Context) { runAndLog(wCtx, c, "morph notification", false, func(lCtx context.Context, c *cfg) { lis.ListenWithError(lCtx, c.internalErr) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 290e651f7f..050838648d 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -73,6 +73,8 @@ type Client struct { // channel for internal stop closeChan chan struct{} + closed atomic.Bool + wg sync.WaitGroup // indicates that Client is not able to // establish connection to any of the diff --git a/pkg/morph/client/multi.go b/pkg/morph/client/multi.go index e006ca69a6..25ec626d14 100644 --- a/pkg/morph/client/multi.go +++ b/pkg/morph/client/multi.go @@ -75,6 +75,8 @@ func (c *Client) SwitchRPC(ctx context.Context) bool { } func (c *Client) closeWaiter(ctx context.Context) { + c.wg.Add(1) + defer c.wg.Done() select { case <-ctx.Done(): case <-c.closeChan: diff --git a/pkg/morph/client/notifications.go b/pkg/morph/client/notifications.go index 121dccfb7c..a013631dff 100644 --- a/pkg/morph/client/notifications.go +++ b/pkg/morph/client/notifications.go @@ -16,7 +16,10 @@ func (c *Client) Close() { // closing should be done via the channel // to prevent switching to another RPC node // in the notification loop - close(c.closeChan) + if c.closed.CompareAndSwap(false, true) { + close(c.closeChan) + } + c.wg.Wait() } // ReceiveExecutionNotifications performs subscription for notifications diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index ca5031415f..4fb92da50e 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -96,6 +96,8 @@ type ListenerParams struct { type listener struct { mtx sync.RWMutex + wg sync.WaitGroup + startOnce, stopOnce sync.Once started bool @@ -124,6 +126,12 @@ var ( errNilLogger = errors.New("nil logger") errNilSubscriber = errors.New("nil event subscriber") + + errNotificationSubscrConnectionTerminated = errors.New("event subscriber connection has been terminated") + + errNotarySubscrConnectionTerminated = errors.New("notary event subscriber connection has been terminated") + + errBlockNotificationChannelClosed = errors.New("new block notification channel is closed") ) // Listen starts the listening for events with registered handlers. @@ -133,6 +141,8 @@ var ( // Returns an error if listener was already started. func (l *listener) Listen(ctx context.Context) { l.startOnce.Do(func() { + l.wg.Add(1) + defer l.wg.Done() if err := l.listen(ctx, nil); err != nil { l.log.Error(logs.EventCouldNotStartListenToEvents, zap.String("error", err.Error()), @@ -149,11 +159,13 @@ func (l *listener) Listen(ctx context.Context) { // Returns an error if listener was already started. func (l *listener) ListenWithError(ctx context.Context, intError chan<- error) { l.startOnce.Do(func() { + l.wg.Add(1) + defer l.wg.Done() if err := l.listen(ctx, intError); err != nil { l.log.Error(logs.EventCouldNotStartListenToEvents, zap.String("error", err.Error()), ) - intError <- err + l.sendError(ctx, intError, err) } }) } @@ -172,6 +184,8 @@ func (l *listener) listen(ctx context.Context, intError chan<- error) error { } func (l *listener) subscribe(errCh chan error) { + l.wg.Add(1) + defer l.wg.Done() // create the list of listening contract hashes hashes := make([]util.Uint160, 0) @@ -212,6 +226,23 @@ func (l *listener) subscribe(errCh chan error) { } } +func (l *listener) sendError(ctx context.Context, intErr chan<- error, err error) bool { + if intErr == nil { + return false + } + // This select required because were are reading from error channel and closing listener + // in the same routine when shutting down node. + select { + case <-ctx.Done(): + l.log.Info(logs.EventStopEventListenerByContext, + zap.String("reason", ctx.Err().Error()), + ) + return false + case intErr <- err: + return true + } +} + func (l *listener) listenLoop(ctx context.Context, intErr chan<- error, subErrCh chan error) { chs := l.subscriber.NotificationChannels() @@ -219,12 +250,9 @@ loop: for { select { case err := <-subErrCh: - if intErr != nil { - intErr <- err - } else { + if !l.sendError(ctx, intErr, err) { l.log.Error(logs.EventStopEventListenerByError, zap.Error(err)) } - break loop case <-ctx.Done(): l.log.Info(logs.EventStopEventListenerByContext, @@ -234,10 +262,7 @@ loop: case notifyEvent, ok := <-chs.NotificationsCh: if !ok { l.log.Warn(logs.EventStopEventListenerByNotificationChannel) - if intErr != nil { - intErr <- errors.New("event subscriber connection has been terminated") - } - + l.sendError(ctx, intErr, errNotificationSubscrConnectionTerminated) break loop } else if notifyEvent == nil { l.log.Warn(logs.EventNilNotificationEventWasCaught) @@ -248,10 +273,7 @@ loop: case notaryEvent, ok := <-chs.NotaryRequestsCh: if !ok { l.log.Warn(logs.EventStopEventListenerByNotaryChannel) - if intErr != nil { - intErr <- errors.New("notary event subscriber connection has been terminated") - } - + l.sendError(ctx, intErr, errNotarySubscrConnectionTerminated) break loop } else if notaryEvent == nil { l.log.Warn(logs.EventNilNotaryEventWasCaught) @@ -262,10 +284,7 @@ loop: case b, ok := <-chs.BlockCh: if !ok { l.log.Warn(logs.EventStopEventListenerByBlockChannel) - if intErr != nil { - intErr <- errors.New("new block notification channel is closed") - } - + l.sendError(ctx, intErr, errBlockNotificationChannelClosed) break loop } else if b == nil { l.log.Warn(logs.EventNilBlockWasCaught) @@ -603,6 +622,7 @@ func (l *listener) Stop() { l.stopOnce.Do(func() { l.subscriber.Close() }) + l.wg.Wait() } func (l *listener) RegisterBlockHandler(handler BlockHandler) { From c7a72294840e5a932b7f2637ddbb5dfde16a803a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 31 Oct 2023 15:57:06 +0300 Subject: [PATCH 0111/1413] [#764] metrics: Fix epoch metric Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 6580de1571..e3e56e5deb 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -562,10 +562,11 @@ func initCfg(appCfg *config.Config) *cfg { relayOnly := nodeconfig.Relay(appCfg) netState := newNetworkState() - netState.metrics = c.metricsCollector c.shared = initShared(appCfg, key, netState, relayOnly) + netState.metrics = c.metricsCollector + logPrm, err := c.loggerPrm() fatalOnErr(err) logPrm.SamplingHook = c.metricsCollector.LogMetrics().GetSamplingHook() From 0b0e5dab2435c046ff5da467cbec586df8b00a17 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 1 Nov 2023 11:07:56 +0300 Subject: [PATCH 0112/1413] [#756] adm: Add polling interval increase Signed-off-by: Dmitrii Stepanov --- .../internal/modules/morph/initialize.go | 60 ++++++++++++------- .../internal/modules/morph/initialize_test.go | 35 +++++++++++ 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index 4184e1a80e..e288361dd6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -7,6 +7,7 @@ import ( "path/filepath" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -376,36 +377,18 @@ func (c *clientContext) awaitTx(cmd *cobra.Command) error { func awaitTx(cmd *cobra.Command, c Client, txs []hashVUBPair) error { cmd.Println("Waiting for transactions to persist...") - const pollInterval = time.Second - - tick := time.NewTicker(pollInterval) - defer tick.Stop() - at := trigger.Application var retErr error - currBlock, err := c.GetBlockCount() - if err != nil { - return fmt.Errorf("can't fetch current block height: %w", err) - } - loop: for i := range txs { - res, err := c.GetApplicationLog(txs[i].hash, &at) - if err == nil { - if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vmstate.Halt { - retErr = fmt.Errorf("tx %d persisted in %s state: %s", - i, res.Executions[0].VMState, res.Executions[0].FaultException) - } - continue loop - } - if txs[i].vub < currBlock { - return fmt.Errorf("tx was not persisted: vub=%d, height=%d", txs[i].vub, currBlock) - } - for range tick.C { + var it int + var pollInterval time.Duration + var pollIntervalChanged bool + for { // We must fetch current height before application log, to avoid race condition. - currBlock, err = c.GetBlockCount() + currBlock, err := c.GetBlockCount() if err != nil { return fmt.Errorf("can't fetch current block height: %w", err) } @@ -420,12 +403,43 @@ loop: if txs[i].vub < currBlock { return fmt.Errorf("tx was not persisted: vub=%d, height=%d", txs[i].vub, currBlock) } + + pollInterval, pollIntervalChanged = nextPollInterval(it, pollInterval) + if pollIntervalChanged && viper.GetBool(commonflags.Verbose) { + cmd.Printf("Pool interval to check transaction persistence changed: %s\n", pollInterval.String()) + } + + timer := time.NewTimer(pollInterval) + select { + case <-cmd.Context().Done(): + return cmd.Context().Err() + case <-timer.C: + } + + it++ } } return retErr } +func nextPollInterval(it int, previous time.Duration) (time.Duration, bool) { + const minPollInterval = 1 * time.Second + const maxPollInterval = 16 * time.Second + const changeAfter = 5 + if it == 0 { + return minPollInterval, true + } + if it%changeAfter != 0 { + return previous, false + } + nextInterval := previous * 2 + if nextInterval > maxPollInterval { + return maxPollInterval, previous != maxPollInterval + } + return nextInterval, true +} + // sendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC. // If tryGroup is false, global scope is used for the signer (useful when // working with native contracts). diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index 39da56662d..613c63894e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -145,3 +145,38 @@ func setTestCredentials(v *viper.Viper, size int) { } v.Set("credentials.contract", testContractPassword) } + +func TestNextPollInterval(t *testing.T) { + var pollInterval time.Duration + var iteration int + + pollInterval, hasChanged := nextPollInterval(iteration, pollInterval) + require.True(t, hasChanged) + require.Equal(t, time.Second, pollInterval) + + iteration = 4 + pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + require.False(t, hasChanged) + require.Equal(t, time.Second, pollInterval) + + iteration = 5 + pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + require.True(t, hasChanged) + require.Equal(t, 2*time.Second, pollInterval) + + iteration = 10 + pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + require.True(t, hasChanged) + require.Equal(t, 4*time.Second, pollInterval) + + iteration = 20 + pollInterval = 32 * time.Second + pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + require.True(t, hasChanged) // from 32s to 16s + require.Equal(t, 16*time.Second, pollInterval) + + pollInterval = 16 * time.Second + pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + require.False(t, hasChanged) + require.Equal(t, 16*time.Second, pollInterval) +} From 1ab567870a50ad24f3feff7e25f5ba057786c7b7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 2 Nov 2023 10:04:02 +0300 Subject: [PATCH 0113/1413] [#779] adm: Support deploying policy contract Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 350cd611c6..8d46793e56 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -42,6 +42,7 @@ const ( containerContract = "container" frostfsIDContract = "frostfsid" netmapContract = "netmap" + policyContract = "policy" proxyContract = "proxy" ) @@ -51,6 +52,7 @@ var ( containerContract, frostfsIDContract, netmapContract, + policyContract, proxyContract, } @@ -568,7 +570,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an c.Contracts[containerContract].Hash, keysParam, configParam) - case proxyContract: + case proxyContract, policyContract: items = nil default: panic(fmt.Sprintf("invalid contract name: %s", ctrName)) From 7c8591f83baf07997d914ca43cb092614aa6d02f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 2 Nov 2023 10:09:04 +0300 Subject: [PATCH 0114/1413] [#779] go.mod: Update frostfs-contract Signed-off-by: Evgenii Stratonikov --- go.mod | 6 +- go.sum | 1698 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1679 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 0c67313639..bebb9346a3 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231027075445-a02c0bfac885 git.frostfs.info/TrueCloudLab/hrw v1.2.1 @@ -43,11 +43,11 @@ require ( ) require ( - github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/flatbuffers v1.12.1 // indirect + github.com/google/flatbuffers v2.0.8+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect go.opencensus.io v0.24.0 // indirect ) diff --git a/go.sum b/go.sum index 6fb57f4f4d..22f42ef85e 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -35,47 +37,102 @@ cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34h cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= +cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= +cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68= cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= +cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= +cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/accesscontextmanager v1.8.0/go.mod h1:uI+AI/r1oyWK99NN8cQ3UK76AMelMzgZCvJfsi2c+ps= +cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo= cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= +cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= +cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= +cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/aiplatform v1.45.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA= cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= +cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= +cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= +cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/analytics v0.21.2/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= +cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA= cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= +cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs= +cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= +cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= +cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw= +cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= +cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= +cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= +cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY= cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= +cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= +cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg= cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= +cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= +cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= +cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= +cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E= cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= +cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= +cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= +cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ= cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= +cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= +cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE= cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= +cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/baremetalsolution v1.1.1/go.mod h1:D1AV6xwOksJMV4OSlWHtWuFNZZYujJknMAP4Qa27QIA= cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= +cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/batch v1.3.1/go.mod h1:VguXeQKXIYaeeIYbuozUmBR13AfL4SJP7IltNPS+A4A= cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= +cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= +cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= +cloud.google.com/go/beyondcorp v1.0.0/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -85,26 +142,50 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= +cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= +cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= +cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= +cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/bigquery v1.52.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4= cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= +cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= +cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/billing v1.16.0/go.mod h1:y8vx09JSSJG02k5QxbycNRrN7FGZB6F3CAcgum7jvGA= cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= +cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/binaryauthorization v1.6.1/go.mod h1:TKt4pa8xhowwffiBmbrbcxijJRZED4zrqnwZ1lKH51U= cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= +cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI= cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= +cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= +cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/channel v1.16.0/go.mod h1:eN/q1PFSl5gyu0dYdmxNXscY/4Fi7ABmeHCJNf/oHmc= cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= +cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= +cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= +cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/cloudbuild v1.10.1/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= +cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/clouddms v1.6.1/go.mod h1:Ygo1vL52Ov4TBZQquhz5fiw2CQ58gvu+PlS6PVXCpZI= cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= +cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= +cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= +cloud.google.com/go/cloudtasks v1.11.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= @@ -117,224 +198,437 @@ cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= +cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/contactcenterinsights v1.9.1/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= +cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= +cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= +cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/container v1.22.1/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4= cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= +cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= +cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/containeranalysis v0.10.1/go.mod h1:Ya2jiILITMY68ZLPaogjmOMNkwsDrWBSTyBubGXO7j0= cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= +cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= +cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/datacatalog v1.14.0/go.mod h1:h0PrGtlihoutNMp/uvwhawLQ9+c63Kz65UFqh49Yo+E= +cloud.google.com/go/datacatalog v1.14.1/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4= cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= +cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw= cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= +cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= +cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M= cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= +cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI= cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= +cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY= cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= +cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= +cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataplex v1.8.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= +cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= +cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastore v1.12.1/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= +cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= +cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/datastream v1.9.1/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= +cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= +cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/deploy v1.11.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= +cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= +cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= +cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dialogflow v1.38.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4= cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= +cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI= cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= +cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= +cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/documentai v1.20.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E= cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= +cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE= cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= +cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= +cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4= cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= +cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= +cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/eventarc v1.12.1/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= +cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= +cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4= cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= +cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= +cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= +cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE= cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= +cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkebackup v1.3.0/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU= cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= +cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw= cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= +cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= +cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY= cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= +cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/gkemulticloud v0.6.1/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= +cloud.google.com/go/grafeas v0.3.0/go.mod h1:P7hgN24EyONOTMyeJH6DxG4zD7fwiYa5Q6GUgyFSOU8= cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= +cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY= cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= +cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= +cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= +cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.0.1/go.mod h1:yR3tmSL8BcZB4bxByRv2jkSIahVmCtfKZwLYGBalRE8= +cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= +cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= +cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= +cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= +cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/iap v1.8.1/go.mod h1:sJCbeqg3mvWLqjZNsI6dfAtbbV1DL2Rl7e1mTyXYREQ= cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= +cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw= cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= +cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= +cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk= cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= +cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= +cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= +cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= +cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/kms v1.11.0/go.mod h1:hwdiYC0xjnWsKQQCQQmIQnS9asjYVSK6jtXm+zFqXLM= +cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= +cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/language v1.10.1/go.mod h1:CPp94nsdVNiQEt1CNjF5WkTcisLiHPyIbMhvR8H2AW0= cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= +cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc= cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.4.2/go.mod h1:OHrnaYyLUV6oqwh0xiS7e5sLQhP1m0QU9R+WhGDMgIQ= +cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= +cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= +cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak= cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= +cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= +cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= +cloud.google.com/go/maps v1.3.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s= cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= +cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig= cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= +cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA= cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= +cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/metastore v1.11.1/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= +cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= +cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/monitoring v1.15.1/go.mod h1:lADlSAlFdbqQuwwpaImhsJXu1QSdd3ojypXrFSMr2rM= cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= +cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= +cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkconnectivity v1.12.1/go.mod h1:PelxSWYM7Sh9/guf8CFhi6vIqf19Ir/sbfZRUwXh92E= cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= +cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networkmanagement v1.8.0/go.mod h1:Ho/BUGmtyEqrttTgWEe7m+8vDdK74ibQc+Be0q7Fof0= cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= +cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= +cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ= cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= +cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= +cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/notebooks v1.9.1/go.mod h1:zqG9/gk05JrzgBt4ghLzEepPHNwE5jgPcHZRKhlC1A8= cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= +cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/optimization v1.4.1/go.mod h1:j64vZQP7h9bO49m2rVaTVoNM0vEBEN5eKPUPbZyXOrk= cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= +cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8= cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= +cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/orgpolicy v1.11.0/go.mod h1:2RK748+FtVvnfuynxBzdnyu7sygtoZa1za/0ZfpOs1M= +cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE= cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= +cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/osconfig v1.12.0/go.mod h1:8f/PaYzoS3JMVfdfTubkowZYGmAhUCjjwnjqWI7NVBc= +cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE= cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= +cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs= cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= +cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I= cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= +cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= +cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/policytroubleshooter v1.7.1/go.mod h1:0NaT5v3Ag1M7U5r0GfDCpUFkWd9YqpubBWsQlhanRv0= cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= +cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= +cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= +cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= +cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= +cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsub v1.32.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= +cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= +cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= +cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU= cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= +cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE= cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= +cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/recommender v1.10.1/go.mod h1:XFvrE4Suqn5Cq0Lf+mCP6oBHD/yRMA8XxP5sb7Q7gpA= cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= +cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg= cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= +cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= +cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= +cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8= cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= +cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw= cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= +cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE= cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= +cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= +cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= +cloud.google.com/go/run v1.2.0/go.mod h1:36V1IlDzQ0XxbQjUx6IYbw8H3TJnWvhii963WW3B/bo= cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= +cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= +cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo= cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= +cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= +cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= +cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= +cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ= cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= +cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= +cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= +cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= +cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicedirectory v1.10.1/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= +cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g= cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= +cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= +cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/spanner v1.47.0/go.mod h1:IXsJwVW2j4UKs0eYDqodab6HgGuA1bViSqW4uH9lfUI= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= +cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= +cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= +cloud.google.com/go/speech v1.17.1/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= @@ -344,51 +638,96 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= +cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= +cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= +cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= +cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24= cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= +cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk= cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= +cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E= cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= +cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= +cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk= cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= +cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= +cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.8.1/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= +cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= +cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= +cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.17.1/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU= cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= +cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo= cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= +cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= +cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU= cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= +cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= +cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro= cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= +cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= +cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vmwareengine v0.4.1/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= +cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs= cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= +cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc= cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= +cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= +cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 h1:vy6leTEGcKVrLmKfeK5pGGIi3D1vn6rX32Hy4gIOWto= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0 h1:9ahw69njrwf2legz5xNVTA+4A6UwcBzy9oBdbJmoBxU= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.0/go.mod h1:3V8FyzpbIIxzpgfUaSlOJBAT11IzhZzkQnGpYvRQR5E= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 h1:hcWlSHcgkg2wnqAInu0AGQcdEY/zr7+BDbGK0rDfXLQ= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989/go.mod h1:PxsAxe6J4hyYJoU6hyYxD9q5K/DFxdquKHL1BrRaGkg= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= @@ -401,38 +740,143 @@ git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9m git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= git.frostfs.info/TrueCloudLab/tzhash v1.8.0/go.mod h1:dhY+oy274hV8wGvGL4MwwMpdL3GYvaX1a8GQZQHvlF8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v56.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1:MJCkWUBhi9pn/CrYO1Q3P687y2KeahrOPS9BD9LDGb0= github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig= github.com/CityOfZion/neo-go v0.70.1-pre.0.20191212173117-32ac01130d4c/go.mod h1:JtlHfeqLywZLswKIKFnAp+yzezY4Dji9qlfQKB2OD/I= github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1:FLI526IrRWHmcsO+mHsCbj64pJZhwQFTLJZu+A4PGOA= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= github.com/abiosoft/ishell/v2 v2.0.2/go.mod h1:E4oTCXfo6QjoCart0QYa5m9w4S+deXs/P/9jA77A9Bs= github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= +github.com/alexflint/go-filemutex v1.2.0/go.mod h1:mYyQSWvw9Tx2/H2n9qXPb52tTYfE0pZAWcBq5mK025c= github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521073959-f0d4d129b7f1/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= +github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= +github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.43.16/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= @@ -445,19 +889,37 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/bytecodealliance/wasmtime-go v0.36.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -467,6 +929,13 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -480,33 +949,242 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.9.1/go.mod h1:a2DQL4+5ywF6safEeZFEPGRiiGbjzGFRUN2sg06VuU4= +github.com/consensys/gnark v0.9.1/go.mod h1:udWvWGXnfBE7mn7BsNoGAvZDnUhcONBEtNijvVjfY80= github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc= github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/container-orchestrated-devices/container-device-interface v0.5.4/go.mod h1:DjE95rfPiiSmG7uVXtg0z6MnPm/Lx4wxKCIts0ZE0vg= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs/v2 v2.0.0/go.mod h1:swkD/7j9HApWpzl8OHfrHNxppPd9l44DFZdF94BUj9k= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= +github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= +github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= +github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= +github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= +github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= +github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= +github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0= +github.com/containerd/containerd v1.6.9/go.mod h1:XVicUvkxOrftE2Q1YWUXgZwkkAxwQYNOFzYWvfVfEfQ= +github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= +github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= +github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= +github.com/containerd/go-cni v1.1.6/go.mod h1:BWtoWl5ghVymxu6MBjg79W9NZrCRyHIdUtk4cauMe34= +github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= +github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo= +github.com/containerd/imgcrypt v1.1.7/go.mod h1:FD8gqIcX5aTotCtOmjeCsi3A1dHmTZpnMISGKSczt4k= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.3.0/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI= +github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= +github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= +github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3/go.mod h1:YYyNVhZrTMiaf51Vj6WhAJqJw+vl/nzABhj8pWrzle4= +github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.1.0/go.mod h1:oZF9wBnrnQjpWLaPKEinrx3TQ9a+W/RJO7Zb41d8YLE= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= +github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= +github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= +github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= +github.com/containernetworking/plugins v1.2.0/go.mod h1:/VjX4uHecW5vVimFa1wkG4s+r/s9qIfPdqlLF4TW8c4= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g= +github.com/containers/ocicrypt v1.1.6/go.mod h1:WgjxPWdTJMqYMjf3M6cuIFFA1/MpyyhIM99YInA+Rvc= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= +github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M= github.com/dgraph-io/badger/v4 v4.1.0 h1:E38jc0f+RATYrycSUf9LMv/t47XAy+3CApyYSq4APOQ= github.com/dgraph-io/badger/v4 v4.1.0/go.mod h1:P50u28d39ibBRmIJuQC/NSdBOg46HnHw7al2SW5QRHg= +github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/distribution/distribution/v3 v3.0.0-20220526142353-ffbd94cbe269/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v23.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v23.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -517,50 +1195,137 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= +github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= +github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/foxcpp/go-mockdns v0.0.0-20210729171921-fb145fc6f897/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-ini/ini v1.66.6/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-redis/redis v6.10.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -599,11 +1364,16 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -620,11 +1390,16 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= +github.com/google/go-containerregistry v0.14.0/go.mod h1:aiJ2fp/SXvkWgmYHioXnbMdlgB8eXiiYOY55gfN91Wk= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -637,11 +1412,18 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= +github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -650,6 +1432,8 @@ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -660,20 +1444,59 @@ github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0 h1:mdLirNAJBxnGgyB6pjZLcs6ue/6eZGBui6gXspfq4ks= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0/go.mod h1:kdXbOySqcQeTxiqglW7aahTmWZy3Pgi6SYL36yvKeyA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.5 h1:3IZOAnD058zZllQTZNBioTlrzrBG/IjpiZ133IEtusM= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.5/go.mod h1:xbKERva94Pw2cPen0s79J3uXmGzbbpDYFBFDlZ4mV/w= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= @@ -683,6 +1506,10 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= @@ -690,13 +1517,34 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= +github.com/intel/goresctrl v0.3.0/go.mod h1:fdz3mD85cmP9sHD8JUlrNWAxvwM86CrbmVXltEKd7zk= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -706,71 +1554,162 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= +github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= +github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ= +github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= +github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= +github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY= +github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= +github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= 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/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= 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/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= +github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= +github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mr-tron/base58 v1.1.2/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/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= 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-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= @@ -783,8 +1722,11 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= 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/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296 h1:vU9tpM3apjYlLLeY23zRWJ9Zktr5jp+mloR942LEOpY= github.com/nats-io/nats-server/v2 v2.7.4 h1:c+BZJ3rGzUKCBIM4IXO8uNT2u1vajGbD1kPA6wqCEaM= github.com/nats-io/nats-server/v2 v2.7.4/go.mod h1:1vZ2Nijh8tcyNe8BDVyTviCd9NYzRbubQYiEHsvOQWc= @@ -794,12 +1736,14 @@ github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA= github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw= github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY= github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk= github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ= github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= -github.com/nspcc-dev/dbft v0.0.0-20220629112714-fd49ca59d354/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= github.com/nspcc-dev/dbft v0.0.0-20221020093431-31c1bbdc74f2/go.mod h1:g9xisXmX9NP9MjioaTe862n9SlZTrP+6PVUWLBYOr98= github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c/go.mod h1:kjBC9F8L25GR+kIHy/1KgG/KfcoGnVwIiyovgq1uszk= github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= @@ -808,58 +1752,144 @@ github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= -github.com/nspcc-dev/neo-go v0.99.2/go.mod h1:9P0yWqhZX7i/ChJ+zjtiStO1uPTolPFUM+L5oNznU8E= github.com/nspcc-dev/neo-go v0.100.1/go.mod h1:Nnp7F4e9IBccsgtCeLtUWV+0T6gk1PtP5HRtA13hUfc= -github.com/nspcc-dev/neo-go v0.101.5-0.20230808195420-5fc61be5f6c5/go.mod h1:Z0kpjwnTJj/ik/X6z18xjCL0X2+RNbqlnhKrl+MYgP8= github.com/nspcc-dev/neo-go v0.103.0 h1:UVyWPhzZdfYFG35ORP3FRDLh8J/raRQ6m8SptDdlgfM= github.com/nspcc-dev/neo-go v0.103.0/go.mod h1:x+wmcYqpZYJwLp1l/pHZrqNp3RSWlkMymWGDij3/OPo= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220809123759-3094d3e0c14b/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230420112658-c50ab951645a/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20230808195420-5fc61be5f6c5/go.mod h1:ZUuXOkdtHZgaC13za/zMgXfQFncZ0jLzfQTe+OsDOtg= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5 h1:09CpI5uwsxb1EeFPIKQRwwWlfCmDD/Dwwh01lPiQScM= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM= -github.com/nspcc-dev/neofs-contract v0.16.0/go.mod h1:gN5bo2TlMvLbySImmg76DVj3jVmYgti2VVlQ+h/tcr0= github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659/go.mod h1:/jay1lr3w7NQd/VDBkEhkJmDmyPNsu4W+QV2obsUV40= -github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.9/go.mod h1:fTsdTU/M9rvv/f9jlp7vHOm3DRp+NSfjfTv9NohrKTE= +github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11/go.mod h1:W+ImTNRnSNMH8w43H1knCcIqwu7dLHePXtlJNZ7EFIs= github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/tzhash v1.7.0/go.mod h1:Dnx9LUlOLr5paL2Rtc96x0PPs8D9eIkUtowt1n+KQus= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= +github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= +github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= +github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= +github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= +github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= +github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk= +github.com/open-policy-agent/opa v0.42.2/go.mod h1:MrmoTi/BsKWT58kXlVayBb+rYVeaMwuBm3nYAN3923s= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= +github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= +github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= +github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/panjf2000/ants/v2 v2.7.5 h1:/vhh0Hza9G1vP1PdCj9hl6MUzCRbmtcTJL0OsnmytuU= github.com/panjf2000/ants/v2 v2.7.5/go.mod h1:KIBmYG9QQX5U2qzFP/yQJaq/nSb6rahS9iEHkrCMgM8= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paulmach/orb v0.9.2 h1:p/YWV2uJwamAynnDOJGNbPBVtDHj3vG51k9tR1rFwJE= github.com/paulmach/orb v0.9.2/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -867,76 +1897,160 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/safchain/ethtool v0.2.0/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -944,31 +2058,75 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= +github.com/testcontainers/testcontainers-go v0.22.0/go.mod h1:k0YiPa26xJCRUbUkYqy5rY6NGvSbVCeUBXCvucscBR4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= +github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= +github.com/vektah/gqlparser/v2 v2.4.5/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0= +github.com/veraison/go-cose v1.0.0-rc.1/go.mod h1:7ziE85vSq4ScFTg6wyoMXjucIGOf4JkFEZi/an96Ct4= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -979,14 +2137,37 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v2 v2.305.5/go.mod h1:zQjKllfqfBVyVStbt4FaosoX2iYd8fV/GRy/PbowgP4= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c= +go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= +go.etcd.io/etcd/pkg/v3 v3.5.5/go.mod h1:6ksYFxttiUGzC2uxyqiyOEvhAiD0tuIqSZkX3TyPdaE= +go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= +go.etcd.io/etcd/raft/v3 v3.5.5/go.mod h1:76TA48q03g1y1VpTue92jZLr9lIHKUNcYdZOOGyx8rI= +go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= +go.etcd.io/etcd/server/v3 v3.5.5/go.mod h1:rZ95vDw/jrvsbj9XpTqPrTAB9/kzchVdhRirySPkUBc= go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE= go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -996,68 +2177,156 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.40.0/go.mod h1:UMklln0+MRhZC4e3PwmN3pCtq4DyIadWw4yikh6bNrw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0/go.mod h1:5eCOqeGphOyz6TsY3ZDNjE33SM/TFAK3RGuCL2naTgY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= +go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= +go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= +go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.7.0/go.mod h1:M1hVZHNxcbkAlcvrOMlpQ4YOO3Awf+4N2dxkZL3xm04= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0/go.mod h1:UFG7EBMRdXyFstOwH028U0sVf+AvukSGhF0g8+dmNG8= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.7.0/go.mod h1:ceUgdyfNv4h4gLxHR0WNfDiiVmZFodZhZSbOLhpxqXE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0/go.mod h1:HrbCVv40OOLTABmOn1ZWty6CHXkU8DK/Urc43tHug70= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0/go.mod h1:E+/KKhwOSw8yoPxSSuUHG6vKppkvhN+S1Jc7Nib3k3o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0/go.mod h1:5w41DY6S9gZrbjuq6Y+753e96WfPha5IcsOSZTtullM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 h1:TVQp/bboR4mhZSav+MdgXB8FaRho1RC8UwVn3T0vjVc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.14.0/go.mod h1:+N7zNjIJv4K+DeX67XXET0P+eIciESgaFDBqh+ZJFS4= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 h1:+XWJd3jf75RXJq29mxbuXhCXFDG3S3R4vBUeSI2P7tE= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0/go.mod h1:hqgzBPTf4yONMFgdZvL/bK42R/iinTyVQtiWihs3SZc= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/metric v0.30.0/go.mod h1:/ShZ7+TS4dHzDFmfi1kSXMhMVubNoP0oIaBp70J6UXU= +go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= +go.opentelemetry.io/otel/metric v0.37.0/go.mod h1:DmdaHfGt54iV6UKxsV9slj2bBRJcKC1B1uvDLIioc1s= go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= +go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= +go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= +go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= +go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= +go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= +go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= +go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= +go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v0.16.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.20.0 h1:BLOA1cZBAGSbRiNuGCCKiFrCdYB7deeHDeD1SueyOfA= go.opentelemetry.io/proto/otlp v0.20.0/go.mod h1:3QgjzPALBIv9pcknj2EXGPXjYPFdUh/RQfF8Lz3+Vnw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= @@ -1065,11 +2334,25 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/exp v0.0.0-20221227203929-1b447090c38c/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1099,23 +2382,38 @@ golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1132,20 +2430,27 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1161,8 +2466,15 @@ golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1191,6 +2503,10 @@ golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1204,14 +2520,21 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1220,25 +2543,43 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1249,25 +2590,41 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1276,10 +2633,19 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1288,16 +2654,23 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1305,17 +2678,31 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1332,31 +2719,55 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1376,18 +2787,23 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1398,10 +2814,17 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1410,8 +2833,16 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1463,6 +2894,17 @@ google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91 google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= +google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= +google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= +google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= +google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1470,11 +2912,13 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1483,6 +2927,7 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1491,17 +2936,21 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1533,6 +2982,7 @@ google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= @@ -1576,21 +3026,64 @@ google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= +google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= +google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= +google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= +google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= +google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a h1:fwgW9j3vHirt4ObdHoYNwuO24BEZjSzbh+zPaNWoiY8= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= +google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1615,6 +3108,7 @@ google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= @@ -1625,7 +3119,13 @@ google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= +google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1644,20 +3144,37 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/abiosoft/ishell.v2 v2.0.0/go.mod h1:sFp+cGtH6o4s1FtpVPTMcHq2yue+c4DGOVohJCPUzwY= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1668,9 +3185,16 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/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.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1678,10 +3202,140 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= +k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= +k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= +k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= +k8s.io/apiserver v0.26.2/go.mod h1:GHcozwXgXsPuOJ28EnQ/jXEM9QeG6HT22YxSNmpYNh8= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= +k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= +k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= +k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= +k8s.io/cri-api v0.25.0/go.mod h1:J1rAyQkSJ2Q6I+aBMOVgg2/cbbebso6FNa0UagiR0kc= +k8s.io/cri-api v0.25.3/go.mod h1:riC/P0yOGUf2K1735wW+CXs1aY2ctBgePtnnoFLd0dU= +k8s.io/cri-api v0.27.1/go.mod h1:+Ts/AVYbIo04S86XbTD73UPp/DkTiYxtsFeOFEu32L0= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kms v0.26.2/go.mod h1:69qGnf1NsFOQP07fBYqNLZklqEHSJF024JqYCaeVxHg= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= +modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA= +modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0= +modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0= +modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI= +modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/sqlite v1.18.2/go.mod h1:kvrTLEWgxUcHa2GfHBQtanR1H9ht3hTJNtKpzH9k1u0= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/tcl v1.13.2/go.mod h1:7CLiGIPo1M8Rv1Mitpv5akc2+8fxUd2y2UzC/MfMzy0= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +oras.land/oras-go v1.2.0/go.mod h1:pFNs7oHp2dYsYMSS82HaX5l4mpnGO7hbpPN6EWH2ltc= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35/go.mod h1:WxjusMwXlKzfAs4p9km6XJRndVt2FROgMVCE4cdohFo= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= From 7b1eda5107afdcae552bf9ccffeffee2e9f585f4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 2 Nov 2023 17:32:41 +0300 Subject: [PATCH 0115/1413] [#531] go.mod: Update api-go version Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bebb9346a3..9e97238c51 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module git.frostfs.info/TrueCloudLab/frostfs-node go 1.20 require ( - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231027075445-a02c0bfac885 diff --git a/go.sum b/go.sum index 22f42ef85e..80b6001674 100644 --- a/go.sum +++ b/go.sum @@ -724,8 +724,8 @@ cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvo dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0 h1:vy6leTEGcKVrLmKfeK5pGGIi3D1vn6rX32Hy4gIOWto= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.0/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd h1:MxiIXu4vUATX9bNYFnM1dXAYkx5dnPOGCMzwNNXJEvM= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 h1:hcWlSHcgkg2wnqAInu0AGQcdEY/zr7+BDbGK0rDfXLQ= git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989/go.mod h1:PxsAxe6J4hyYJoU6hyYxD9q5K/DFxdquKHL1BrRaGkg= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= From 20d6132f313f1fed011d18325cf6f2265f823ceb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 2 Nov 2023 17:34:33 +0300 Subject: [PATCH 0116/1413] [#531] signSvc: Add SetMarshaledData method call To reduce memory allocations add `SetMarshaledData` method call to return already marshalled data in next `StableMarshal` calls. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/sign.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index faad264893..2f4f9cb9ae 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -122,6 +122,7 @@ func (s *SignService) Head(ctx context.Context, req *object.HeadRequest) (*objec } func (s *SignService) PutSingle(ctx context.Context, req *object.PutSingleRequest) (*object.PutSingleResponse, error) { + req.GetBody().SetMarshalData(nil) if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(object.PutSingleResponse) return resp, s.sigSvc.SignResponse(resp, err) From cae50ecb21e91e32143ee5da65069430ed8ddfd4 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 2 Nov 2023 16:20:37 +0300 Subject: [PATCH 0117/1413] [#716] adm: Add dump policy Signed-off-by: Alexander Chuprov --- .../internal/modules/morph/policy.go | 33 +++++++++++++++++++ .../internal/modules/morph/root.go | 15 +++++++++ 2 files changed, 48 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy.go index 0703ebc2d7..005a02711f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy.go @@ -1,11 +1,15 @@ package morph import ( + "bytes" "fmt" "strconv" "strings" + "text/tabwriter" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/policy" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/vm/emit" @@ -52,3 +56,32 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error { return wCtx.awaitTx() } + +func dumpPolicyCmd(cmd *cobra.Command, _ []string) error { + c, err := getN3Client(viper.GetViper()) + commonCmd.ExitOnErr(cmd, "can't create N3 client:", err) + + inv := invoker.New(c, nil) + policyContract := policy.NewReader(inv) + + execFee, err := policyContract.GetExecFeeFactor() + commonCmd.ExitOnErr(cmd, "can't get execution fee factor:", err) + + feePerByte, err := policyContract.GetFeePerByte() + commonCmd.ExitOnErr(cmd, "can't get fee per byte:", err) + + storagePrice, err := policyContract.GetStoragePrice() + commonCmd.ExitOnErr(cmd, "can't get storage price:", err) + + buf := bytes.NewBuffer(nil) + tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) + + _, _ = tw.Write([]byte(fmt.Sprintf("Execution Fee Factor:\t%d (int)\n", execFee))) + _, _ = tw.Write([]byte(fmt.Sprintf("Fee Per Byte:\t%d (int)\n", feePerByte))) + _, _ = tw.Write([]byte(fmt.Sprintf("Storage Price:\t%d (int)\n", storagePrice))) + + _ = tw.Flush() + cmd.Print(buf.String()) + + return nil +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 133d5162fd..707ae733d1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -146,6 +146,15 @@ var ( }, } + dumpPolicy = &cobra.Command{ + Use: "dump-policy", + Short: "Dump FrostFS policy", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + RunE: dumpPolicyCmd, + } + dumpContractHashesCmd = &cobra.Command{ Use: "dump-hashes", Short: "Dump deployed contract hashes", @@ -239,6 +248,7 @@ func init() { initForceNewEpochCmd() initRemoveNodesCmd() initSetPolicyCmd() + initDumpPolicyCmd() initDumpContractHashesCmd() initDumpNetworkConfigCmd() initSetConfigCmd() @@ -341,6 +351,11 @@ func initSetPolicyCmd() { setPolicy.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } +func initDumpPolicyCmd() { + RootCmd.AddCommand(dumpPolicy) + dumpPolicy.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") +} + func initRemoveNodesCmd() { RootCmd.AddCommand(removeNodes) removeNodes.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") From 74c91eeef5fe520ae3f73a882315b1c9189ede53 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Wed, 1 Nov 2023 18:18:28 +0300 Subject: [PATCH 0118/1413] [#777] client: Refactor PrmContainerList, PrmObjectSearch usage Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/client.go | 23 +++++----------- cmd/frostfs-cli/modules/container/list.go | 2 +- go.mod | 2 +- go.sum | 4 +-- pkg/services/object/internal/client/client.go | 26 +++++-------------- 5 files changed, 18 insertions(+), 39 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index b370ff3aa6..9807e111cf 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -689,24 +689,15 @@ func (x SearchObjectsRes) IDList() []oid.ID { // // Returns any error which prevented the operation from completing correctly in error return. func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes, error) { - var cliPrm client.PrmObjectSearch - cliPrm.InContainer(prm.cnrID) - cliPrm.SetFilters(prm.filters) - - if prm.sessionToken != nil { - cliPrm.WithinSession(*prm.sessionToken) + cliPrm := client.PrmObjectSearch{ + XHeaders: prm.xHeaders, + Local: prm.local, + BearerToken: prm.bearerToken, + Session: prm.sessionToken, + ContainerID: &prm.cnrID, + Filters: prm.filters, } - if prm.bearerToken != nil { - cliPrm.WithBearerToken(*prm.bearerToken) - } - - if prm.local { - cliPrm.MarkLocal() - } - - cliPrm.WithXHeaders(prm.xHeaders...) - rdr, err := prm.cli.ObjectSearchInit(ctx, cliPrm) if err != nil { return nil, fmt.Errorf("init object search: %w", err) diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index 1c7787760d..1e7ba96ea5 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -47,7 +47,7 @@ var listContainersCmd = &cobra.Command{ var prm internalclient.ListContainersPrm prm.SetClient(cli) - prm.SetAccount(idUser) + prm.Account = &idUser res, err := internalclient.ListContainers(cmd.Context(), prm) commonCmd.ExitOnErr(cmd, "rpc error: %w", err) diff --git a/go.mod b/go.mod index 9e97238c51..37cb477bfc 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231027075445-a02c0bfac885 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 80b6001674..62fd85c863 100644 --- a/go.sum +++ b/go.sum @@ -732,8 +732,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231027075445-a02c0bfac885 h1:tbOUgoaN3usFTUA9k62z96uQDRNJUiz9TxzJr1AtSFo= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231027075445-a02c0bfac885/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d h1:KVHsNsEoedQ1+f+eDq88AFKkLePGfnygt4bcUQrCgPw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index e0a7e562ab..dd2de0fd1e 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -474,12 +474,12 @@ type SearchObjectsPrm struct { // // Required parameter. func (x *SearchObjectsPrm) SetContainerID(id cid.ID) { - x.cliPrm.InContainer(id) + x.cliPrm.ContainerID = &id } // SetFilters sets search filters. func (x *SearchObjectsPrm) SetFilters(fs objectSDK.SearchFilters) { - x.cliPrm.SetFilters(fs) + x.cliPrm.Filters = fs } // SearchObjectsRes groups the resulting values of SearchObjects operation. @@ -496,23 +496,11 @@ func (x SearchObjectsRes) IDList() []oid.ID { // // Returns any error which prevented the operation from completing correctly in error return. func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes, error) { - if prm.local { - prm.cliPrm.MarkLocal() - } - - if prm.tokenSession != nil { - prm.cliPrm.WithinSession(*prm.tokenSession) - } - - if prm.tokenBearer != nil { - prm.cliPrm.WithBearerToken(*prm.tokenBearer) - } - - prm.cliPrm.WithXHeaders(prm.xHeaders...) - - if prm.key != nil { - prm.cliPrm.UseKey(*prm.key) - } + prm.cliPrm.Local = prm.local + prm.cliPrm.Session = prm.tokenSession + prm.cliPrm.BearerToken = prm.tokenBearer + prm.cliPrm.XHeaders = prm.xHeaders + prm.cliPrm.Key = prm.key rdr, err := prm.cli.ObjectSearchInit(ctx, prm.cliPrm) if err != nil { From 523fb3ca5163d37dfe189a5a760932002efe4fc3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 2 Nov 2023 17:57:12 +0300 Subject: [PATCH 0119/1413] [#684] proto: Add skipped count to evacuation status response Signed-off-by: Dmitrii Stepanov --- pkg/services/control/service.pb.go | 207 +++++++++++---------- pkg/services/control/service.proto | 5 +- pkg/services/control/service_frostfs.pb.go | 2 + pkg/services/control/service_grpc.pb.go | 2 +- pkg/services/control/types.pb.go | 2 +- 5 files changed, 117 insertions(+), 101 deletions(-) diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index b1bebb1e27..443afb1aab 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc v4.24.4 // source: pkg/services/control/service.proto package control @@ -2458,7 +2458,7 @@ type GetShardEvacuationStatusResponse_Body struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Total objects to evacuate count. The value is approximate, so evacuated + failed == total is not guaranteed after completion. + // Total objects to evacuate count. The value is approximate, so evacuated + failed + skipped == total is not guaranteed after completion. Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` // Evacuated objects count. Evacuated uint64 `protobuf:"varint,2,opt,name=evacuated,proto3" json:"evacuated,omitempty"` @@ -2474,6 +2474,8 @@ type GetShardEvacuationStatusResponse_Body struct { StartedAt *GetShardEvacuationStatusResponse_Body_UnixTimestamp `protobuf:"bytes,7,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"` // Error message if evacuation failed. ErrorMessage string `protobuf:"bytes,8,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + // Skipped objects count. + Skipped uint64 `protobuf:"varint,9,opt,name=skipped,proto3" json:"skipped,omitempty"` } func (x *GetShardEvacuationStatusResponse_Body) Reset() { @@ -2564,6 +2566,13 @@ func (x *GetShardEvacuationStatusResponse_Body) GetErrorMessage() string { return "" } +func (x *GetShardEvacuationStatusResponse_Body) GetSkipped() uint64 { + if x != nil { + return x.Skipped + } + return 0 +} + // Unix timestamp value. type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { state protoimpl.MessageState @@ -2975,7 +2984,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xc6, 0x05, 0x0a, 0x20, + 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe0, 0x05, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, @@ -2985,7 +2994,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xab, 0x04, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc5, 0x04, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, @@ -3010,103 +3019,105 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x25, 0x0a, 0x0d, - 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x1a, 0x24, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, - 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, - 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, - 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, - 0x45, 0x44, 0x10, 0x02, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x73, + 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x1a, 0x25, 0x0a, 0x0d, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x24, 0x0a, + 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, + 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, + 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, + 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x94, + 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, + 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xee, + 0x07, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, + 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, + 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, + 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, + 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, - 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x32, 0xee, 0x07, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, - 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, - 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, - 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, - 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, - 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, + 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, - 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, - 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, - 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, - 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, - 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, + 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, + 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, + 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, + 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, + 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index a80deb2daf..cbcf74e536 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -362,7 +362,7 @@ message GetShardEvacuationStatusResponse { int64 seconds = 1; } - // Total objects to evacuate count. The value is approximate, so evacuated + failed == total is not guaranteed after completion. + // Total objects to evacuate count. The value is approximate, so evacuated + failed + skipped == total is not guaranteed after completion. uint64 total = 1; // Evacuated objects count. uint64 evacuated = 2; @@ -379,6 +379,9 @@ message GetShardEvacuationStatusResponse { UnixTimestamp started_at = 7; // Error message if evacuation failed. string error_message = 8; + + // Skipped objects count. + uint64 skipped = 9; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index cc96a98df7..56ff81acea 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -1819,6 +1819,7 @@ func (x *GetShardEvacuationStatusResponse_Body) StableSize() (size int) { size += proto.NestedStructureSize(6, x.Duration) size += proto.NestedStructureSize(7, x.StartedAt) size += proto.StringSize(8, x.ErrorMessage) + size += proto.UInt64Size(9, x.Skipped) return size } @@ -1846,6 +1847,7 @@ func (x *GetShardEvacuationStatusResponse_Body) StableMarshal(buf []byte) []byte offset += proto.NestedStructureMarshal(6, buf[offset:], x.Duration) offset += proto.NestedStructureMarshal(7, buf[offset:], x.StartedAt) offset += proto.StringMarshal(8, buf[offset:], x.ErrorMessage) + offset += proto.UInt64Marshal(9, buf[offset:], x.Skipped) return buf } diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index 8afc6086aa..967c739f55 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v3.21.9 +// - protoc v4.24.4 // source: pkg/services/control/service.proto package control diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index b385bc6741..33700c5b9d 100644 --- a/pkg/services/control/types.pb.go +++ b/pkg/services/control/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc v4.24.4 // source: pkg/services/control/types.proto package control From 1e21733ea56ea4c115770be5b900617c6e5c59a6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 2 Nov 2023 18:09:43 +0300 Subject: [PATCH 0120/1413] [#684] cli: Add skipped count to evacuation status output Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/evacuation.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 4eb6505cf4..735897b81a 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -220,12 +220,12 @@ func appendEstimation(sb *strings.Builder, resp *control.GetShardEvacuationStatu if resp.GetBody().GetStatus() != control.GetShardEvacuationStatusResponse_Body_RUNNING || resp.GetBody().GetDuration() == nil || resp.GetBody().GetTotal() == 0 || - resp.GetBody().GetEvacuated()+resp.GetBody().GetFailed() == 0 { + resp.GetBody().GetEvacuated()+resp.GetBody().GetFailed()+resp.Body.GetSkipped() == 0 { return } durationSeconds := float64(resp.GetBody().GetDuration().GetSeconds()) - evacuated := float64(resp.GetBody().GetEvacuated() + resp.GetBody().GetFailed()) + evacuated := float64(resp.GetBody().GetEvacuated() + resp.GetBody().GetFailed() + resp.GetBody().GetSkipped()) avgObjEvacuationTimeSeconds := durationSeconds / evacuated objectsLeft := float64(resp.GetBody().GetTotal()) - evacuated leftSeconds := avgObjEvacuationTimeSeconds * objectsLeft @@ -285,10 +285,11 @@ func appendShardIDs(sb *strings.Builder, resp *control.GetShardEvacuationStatusR } func appendCounts(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { - sb.WriteString(fmt.Sprintf(" Evacuated %d object out of %d, failed to evacuate %d objects.", + sb.WriteString(fmt.Sprintf(" Evacuated %d objects out of %d, failed to evacuate: %d, skipped: %d.", resp.GetBody().GetEvacuated(), - resp.Body.GetTotal(), - resp.Body.GetFailed())) + resp.GetBody().GetTotal(), + resp.GetBody().GetFailed(), + resp.GetBody().GetSkipped())) } func initControlEvacuationShardCmd() { From 226e84d782ed635e5e642547fba733bd3a4c87be Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 2 Nov 2023 18:22:58 +0300 Subject: [PATCH 0121/1413] [#684] node: Add skipped objects count to evacuation result Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 16 ++++++++++++++++ .../engine/evacuate_limiter.go | 7 +++++++ pkg/services/control/server/convert.go | 1 + 3 files changed, 24 insertions(+) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index f5f1b658d7..7bb37ef614 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -41,6 +41,7 @@ type EvacuateShardRes struct { evacuated *atomic.Uint64 total *atomic.Uint64 failed *atomic.Uint64 + skipped *atomic.Uint64 } // NewEvacuateShardRes creates new EvacuateShardRes instance. @@ -49,6 +50,7 @@ func NewEvacuateShardRes() *EvacuateShardRes { evacuated: new(atomic.Uint64), total: new(atomic.Uint64), failed: new(atomic.Uint64), + skipped: new(atomic.Uint64), } } @@ -97,6 +99,14 @@ func (p *EvacuateShardRes) Failed() uint64 { return p.failed.Load() } +// Skipped returns count of skipped objects. +func (p *EvacuateShardRes) Skipped() uint64 { + if p == nil { + return 0 + } + return p.skipped.Load() +} + // DeepCopy returns deep copy of result instance. func (p *EvacuateShardRes) DeepCopy() *EvacuateShardRes { if p == nil { @@ -107,11 +117,13 @@ func (p *EvacuateShardRes) DeepCopy() *EvacuateShardRes { evacuated: new(atomic.Uint64), total: new(atomic.Uint64), failed: new(atomic.Uint64), + skipped: new(atomic.Uint64), } res.evacuated.Store(p.evacuated.Load()) res.total.Store(p.total.Load()) res.failed.Store(p.failed.Load()) + res.skipped.Store(p.skipped.Load()) return res } @@ -224,6 +236,7 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p zap.Uint64("total", res.Total()), zap.Uint64("evacuated", res.Evacuated()), zap.Uint64("failed", res.Failed()), + zap.Uint64("skipped", res.Skipped()), ) return nil } @@ -404,6 +417,9 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } + if exists { + res.skipped.Add(1) + } return true, nil } } diff --git a/pkg/local_object_storage/engine/evacuate_limiter.go b/pkg/local_object_storage/engine/evacuate_limiter.go index 62795fa1a6..83acd30d96 100644 --- a/pkg/local_object_storage/engine/evacuate_limiter.go +++ b/pkg/local_object_storage/engine/evacuate_limiter.go @@ -55,6 +55,13 @@ func (s *EvacuationState) Failed() uint64 { return s.result.Failed() } +func (s *EvacuationState) Skipped() uint64 { + if s == nil { + return 0 + } + return s.result.Skipped() +} + func (s *EvacuationState) ProcessingStatus() EvacuateProcessState { if s == nil { return EvacuateProcessStateUndefined diff --git a/pkg/services/control/server/convert.go b/pkg/services/control/server/convert.go index 1d29ed406f..f922d7278c 100644 --- a/pkg/services/control/server/convert.go +++ b/pkg/services/control/server/convert.go @@ -55,6 +55,7 @@ func stateToResponse(state *engine.EvacuationState) (*control.GetShardEvacuation StartedAt: startedAt, Duration: duration, ErrorMessage: state.ErrorMessage(), + Skipped: state.Skipped(), }, }, nil } From 9c98fa6152640aa3bfd6f50f1dc343857731f8fc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 1 Nov 2023 20:53:24 +0300 Subject: [PATCH 0122/1413] [#763] metabase: Add container objects counter Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/control.go | 15 +- pkg/local_object_storage/metabase/counter.go | 276 +++++++++++++++++- .../metabase/counter_test.go | 201 ++++++++++++- pkg/local_object_storage/metabase/delete.go | 44 ++- pkg/local_object_storage/metabase/inhume.go | 24 +- pkg/local_object_storage/metabase/put.go | 12 +- pkg/local_object_storage/metabase/util.go | 12 +- 7 files changed, 535 insertions(+), 49 deletions(-) diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 3f155eeb55..00fe1e02bf 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -103,12 +103,13 @@ func (db *DB) init(reset bool) error { } mStaticBuckets := map[string]struct{}{ - string(containerVolumeBucketName): {}, - string(graveyardBucketName): {}, - string(toMoveItBucketName): {}, - string(garbageBucketName): {}, - string(shardInfoBucket): {}, - string(bucketNameLocked): {}, + string(containerVolumeBucketName): {}, + string(containerCounterBucketName): {}, + string(graveyardBucketName): {}, + string(toMoveItBucketName): {}, + string(garbageBucketName): {}, + string(shardInfoBucket): {}, + string(bucketNameLocked): {}, } return db.boltDB.Update(func(tx *bbolt.Tx) error { @@ -135,7 +136,7 @@ func (db *DB) init(reset bool) error { } } - if !reset { + if !reset { // counters will be recalculated by refill metabase err = syncCounter(tx, false) if err != nil { return fmt.Errorf("could not sync object counter: %w", err) diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index d4afe18785..d1aafa3dbf 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -1,10 +1,15 @@ package meta import ( + "bytes" + "context" "encoding/binary" + "errors" "fmt" + "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -73,9 +78,128 @@ func (db *DB) ObjectCounters() (cc ObjectCounters, err error) { return cc, metaerr.Wrap(err) } -// updateCounter updates the object counter. Tx MUST be writable. -// If inc == `true`, increases the counter, decreases otherwise. -func (db *DB) updateCounter(tx *bbolt.Tx, typ objectType, delta uint64, inc bool) error { +type ContainerCounters struct { + Logical map[cid.ID]uint64 + Physical map[cid.ID]uint64 +} + +// ContainerCounters returns object counters for each container +// that metabase has tracked since it was opened and initialized. +// +// Returns only the errors that do not allow reading counter +// in Bolt database. +// +// It is guaranteed that the ContainerCounters fields are not nil. +func (db *DB) ContainerCounters(ctx context.Context) (ContainerCounters, error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("ContainerCounters", time.Since(startedAt), success) + }() + + ctx, span := tracing.StartSpanFromContext(ctx, "metabase.ContainerCounters") + defer span.End() + + cc := ContainerCounters{ + Logical: make(map[cid.ID]uint64), + Physical: make(map[cid.ID]uint64), + } + + lastKey := make([]byte, cidSize) + + // there is no limit for containers count, so use batching with cancellation + for { + select { + case <-ctx.Done(): + return cc, ctx.Err() + default: + } + + completed, err := db.containerCountersNextBatch(lastKey, &cc) + if err != nil { + return cc, err + } + if completed { + break + } + } + + success = true + return cc, nil +} + +func (db *DB) containerCountersNextBatch(lastKey []byte, cc *ContainerCounters) (bool, error) { + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return false, ErrDegradedMode + } + + counter := 0 + const batchSize = 1000 + + err := db.boltDB.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(containerCounterBucketName) + if b == nil { + return ErrInterruptIterator + } + c := b.Cursor() + var key, value []byte + for key, value = c.Seek(lastKey); key != nil; key, value = c.Next() { + if bytes.Equal(lastKey, key) { + continue + } + copy(lastKey, key) + + cnrID, err := parseContainerCounterKey(key) + if err != nil { + return err + } + phy, logic, err := parseContainerCounterValue(value) + if err != nil { + return err + } + if phy > 0 { + cc.Physical[cnrID] = phy + } + if logic > 0 { + cc.Logical[cnrID] = logic + } + + counter++ + if counter == batchSize { + break + } + } + + if counter < batchSize { // last batch + return ErrInterruptIterator + } + return nil + }) + if err != nil { + if errors.Is(err, ErrInterruptIterator) { + return true, nil + } + return false, metaerr.Wrap(err) + } + return false, nil +} + +func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID) error { + if err := db.updateShardObjectCounter(tx, phy, 1, true); err != nil { + return fmt.Errorf("could not increase phy object counter: %w", err) + } + if err := db.updateShardObjectCounter(tx, logical, 1, true); err != nil { + return fmt.Errorf("could not increase logical object counter: %w", err) + } + return db.incContainerObjectCounter(tx, cnrID) +} + +func (db *DB) updateShardObjectCounter(tx *bbolt.Tx, typ objectType, delta uint64, inc bool) error { b := tx.Bucket(shardInfoBucket) if b == nil { return nil @@ -112,6 +236,63 @@ func (db *DB) updateCounter(tx *bbolt.Tx, typ objectType, delta uint64, inc bool return b.Put(counterKey, newCounter) } +func (db *DB) updateContainerCounter(tx *bbolt.Tx, delta map[cid.ID]ObjectCounters, inc bool) error { + b := tx.Bucket(containerCounterBucketName) + if b == nil { + return nil + } + + key := make([]byte, cidSize) + for cnrID, cnrDelta := range delta { + cnrID.Encode(key) + if err := db.editContainerCounterValue(b, key, cnrDelta, inc); err != nil { + return err + } + } + return nil +} + +func (*DB) editContainerCounterValue(b *bbolt.Bucket, key []byte, delta ObjectCounters, inc bool) error { + var phyValue, logicValue uint64 + var err error + data := b.Get(key) + if len(data) > 0 { + phyValue, logicValue, err = parseContainerCounterValue(data) + if err != nil { + return err + } + } + phyValue = nextValue(phyValue, delta.phy, inc) + logicValue = nextValue(logicValue, delta.logic, inc) + if phyValue > 0 || logicValue > 0 { + value := containerCounterValue(phyValue, logicValue) + return b.Put(key, value) + } + return b.Delete(key) +} + +func nextValue(existed, delta uint64, inc bool) uint64 { + if inc { + existed += delta + } else if existed <= delta { + existed = 0 + } else { + existed -= delta + } + return existed +} + +func (db *DB) incContainerObjectCounter(tx *bbolt.Tx, cnrID cid.ID) error { + b := tx.Bucket(containerCounterBucketName) + if b == nil { + return nil + } + + key := make([]byte, cidSize) + cnrID.Encode(key) + return db.editContainerCounterValue(b, key, ObjectCounters{logic: 1, phy: 1}, true) +} + // syncCounter updates object counters according to metabase state: // it counts all the physically/logically stored objects using internal // indexes. Tx MUST be writable. @@ -119,26 +300,38 @@ func (db *DB) updateCounter(tx *bbolt.Tx, typ objectType, delta uint64, inc bool // Does nothing if counters are not empty and force is false. If force is // true, updates the counters anyway. func syncCounter(tx *bbolt.Tx, force bool) error { - b, err := tx.CreateBucketIfNotExists(shardInfoBucket) + shardInfoB, err := tx.CreateBucketIfNotExists(shardInfoBucket) if err != nil { return fmt.Errorf("could not get shard info bucket: %w", err) } - - if !force && len(b.Get(objectPhyCounterKey)) == 8 && len(b.Get(objectLogicCounterKey)) == 8 { + shardObjectCounterInitialized := len(shardInfoB.Get(objectPhyCounterKey)) == 8 && len(shardInfoB.Get(objectLogicCounterKey)) == 8 + containerCounterInitialized := tx.Bucket(containerCounterBucketName) != nil + if !force && shardObjectCounterInitialized && containerCounterInitialized { // the counters are already inited return nil } + containerCounterB, err := tx.CreateBucketIfNotExists(containerCounterBucketName) + if err != nil { + return fmt.Errorf("could not get container counter bucket: %w", err) + } + var addr oid.Address - var phyCounter uint64 - var logicCounter uint64 + counters := make(map[cid.ID]ObjectCounters) graveyardBKT := tx.Bucket(graveyardBucketName) garbageBKT := tx.Bucket(garbageBucketName) key := make([]byte, addressKeySize) err = iteratePhyObjects(tx, func(cnr cid.ID, obj oid.ID) error { - phyCounter++ + if v, ok := counters[cnr]; ok { + v.phy++ + counters[cnr] = v + } else { + counters[cnr] = ObjectCounters{ + phy: 1, + } + } addr.SetContainer(cnr) addr.SetObject(obj) @@ -146,7 +339,14 @@ func syncCounter(tx *bbolt.Tx, force bool) error { // check if an object is available: not with GCMark // and not covered with a tombstone if inGraveyardWithKey(addressKey(addr, key), graveyardBKT, garbageBKT) == 0 { - logicCounter++ + if v, ok := counters[cnr]; ok { + v.logic++ + counters[cnr] = v + } else { + counters[cnr] = ObjectCounters{ + logic: 1, + } + } } return nil @@ -155,21 +355,65 @@ func syncCounter(tx *bbolt.Tx, force bool) error { return fmt.Errorf("could not iterate objects: %w", err) } - data := make([]byte, 8) - binary.LittleEndian.PutUint64(data, phyCounter) + return setObjectCounters(counters, shardInfoB, containerCounterB) +} - err = b.Put(objectPhyCounterKey, data) +func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, containerCounterB *bbolt.Bucket) error { + var phyTotal uint64 + var logicTotal uint64 + key := make([]byte, cidSize) + for cnrID, count := range counters { + phyTotal += count.phy + logicTotal += count.logic + + cnrID.Encode(key) + value := containerCounterValue(count.phy, count.logic) + err := containerCounterB.Put(key, value) + if err != nil { + return fmt.Errorf("could not update phy container object counter: %w", err) + } + } + phyData := make([]byte, 8) + binary.LittleEndian.PutUint64(phyData, phyTotal) + + err := shardInfoB.Put(objectPhyCounterKey, phyData) if err != nil { return fmt.Errorf("could not update phy object counter: %w", err) } - data = make([]byte, 8) - binary.LittleEndian.PutUint64(data, logicCounter) + logData := make([]byte, 8) + binary.LittleEndian.PutUint64(logData, logicTotal) - err = b.Put(objectLogicCounterKey, data) + err = shardInfoB.Put(objectLogicCounterKey, logData) if err != nil { return fmt.Errorf("could not update logic object counter: %w", err) } return nil } + +func containerCounterValue(phy, logic uint64) []byte { + res := make([]byte, 16) + binary.LittleEndian.PutUint64(res, phy) + binary.LittleEndian.PutUint64(res[8:], logic) + return res +} + +func parseContainerCounterKey(buf []byte) (cid.ID, error) { + if len(buf) != cidSize { + return cid.ID{}, fmt.Errorf("invalid key length") + } + var cnrID cid.ID + if err := cnrID.Decode(buf); err != nil { + return cid.ID{}, fmt.Errorf("failed to decode container ID: %w", err) + } + return cnrID, nil +} + +// parseContainerCounterValue return phy, logic values. +func parseContainerCounterValue(buf []byte) (uint64, uint64, error) { + if len(buf) != 16 { + return 0, 0, fmt.Errorf("invalid value length") + } + return binary.LittleEndian.Uint64(buf), binary.LittleEndian.Uint64(buf[8:]), nil +} diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 89b52c8878..51062f1fe1 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -7,6 +7,7 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -25,6 +26,11 @@ func TestCounters(t *testing.T) { require.NoError(t, err) require.Zero(t, c.Phy()) require.Zero(t, c.Logic()) + + cc, err := db.ContainerCounters(context.Background()) + require.NoError(t, err) + require.Zero(t, len(cc.Physical)) + require.Zero(t, len(cc.Logical)) }) t.Run("put", func(t *testing.T) { @@ -36,9 +42,14 @@ func TestCounters(t *testing.T) { } var prm meta.PutPrm + expPhy := make(map[cid.ID]uint64) + expLog := make(map[cid.ID]uint64) for i := 0; i < objCount; i++ { prm.SetObject(oo[i]) + cnrID, _ := oo[i].ContainerID() + expPhy[cnrID]++ + expLog[cnrID]++ _, err := db.Put(context.Background(), prm) require.NoError(t, err) @@ -48,6 +59,12 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(i+1), c.Phy()) require.Equal(t, uint64(i+1), c.Logic()) + + cc, err := db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) } }) @@ -56,6 +73,14 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, false) + expPhy := make(map[cid.ID]uint64) + expLog := make(map[cid.ID]uint64) + for _, obj := range oo { + cnrID, _ := obj.ContainerID() + expPhy[cnrID]++ + expLog[cnrID]++ + } + var prm meta.DeletePrm for i := objCount - 1; i >= 0; i-- { prm.SetAddresses(objectcore.AddressOf(oo[i])) @@ -69,6 +94,27 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(i), c.Phy()) require.Equal(t, uint64(i), c.Logic()) + + cnrID, _ := oo[i].ContainerID() + if v, ok := expPhy[cnrID]; ok { + if v == 1 { + delete(expPhy, cnrID) + } else { + expPhy[cnrID]-- + } + } + if v, ok := expLog[cnrID]; ok { + if v == 1 { + delete(expLog, cnrID) + } else { + expLog[cnrID]-- + } + } + + cc, err := db.ContainerCounters(context.Background()) + require.NoError(t, err) + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) } }) @@ -77,6 +123,14 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, false) + expPhy := make(map[cid.ID]uint64) + expLog := make(map[cid.ID]uint64) + for _, obj := range oo { + cnrID, _ := obj.ContainerID() + expPhy[cnrID]++ + expLog[cnrID]++ + } + inhumedObjs := make([]oid.Address, objCount/2) for i, o := range oo { @@ -87,6 +141,16 @@ func TestCounters(t *testing.T) { inhumedObjs[i] = objectcore.AddressOf(o) } + for _, addr := range inhumedObjs { + if v, ok := expLog[addr.Container()]; ok { + if v == 1 { + delete(expLog, addr.Container()) + } else { + expLog[addr.Container()]-- + } + } + } + var prm meta.InhumePrm prm.SetTombstoneAddress(oidtest.Address()) prm.SetAddresses(inhumedObjs...) @@ -100,6 +164,12 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(objCount), c.Phy()) require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic()) + + cc, err := db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) }) t.Run("put_split", func(t *testing.T) { @@ -107,6 +177,9 @@ func TestCounters(t *testing.T) { db := newDB(t) parObj := testutil.GenerateObject() + expPhy := make(map[cid.ID]uint64) + expLog := make(map[cid.ID]uint64) + // put objects and check that parent info // does not affect the counter for i := 0; i < objCount; i++ { @@ -115,12 +188,21 @@ func TestCounters(t *testing.T) { o.SetParent(parObj) } + cnrID, _ := o.ContainerID() + expLog[cnrID]++ + expPhy[cnrID]++ + require.NoError(t, putBig(db, o)) c, err := db.ObjectCounters() require.NoError(t, err) require.Equal(t, uint64(i+1), c.Phy()) require.Equal(t, uint64(i+1), c.Logic()) + + cc, err := db.ContainerCounters(context.Background()) + require.NoError(t, err) + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) } }) @@ -129,16 +211,40 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, true) + expPhy := make(map[cid.ID]uint64) + expLog := make(map[cid.ID]uint64) + for _, obj := range oo { + cnrID, _ := obj.ContainerID() + expPhy[cnrID]++ + expLog[cnrID]++ + } + // delete objects that have parent info // and check that it does not affect // the counter for i, o := range oo { - require.NoError(t, metaDelete(db, objectcore.AddressOf(o))) + addr := objectcore.AddressOf(o) + require.NoError(t, metaDelete(db, addr)) c, err := db.ObjectCounters() require.NoError(t, err) require.Equal(t, uint64(objCount-i-1), c.Phy()) require.Equal(t, uint64(objCount-i-1), c.Logic()) + + if v, ok := expPhy[addr.Container()]; ok { + if v == 1 { + delete(expPhy, addr.Container()) + } else { + expPhy[addr.Container()]-- + } + } + if v, ok := expLog[addr.Container()]; ok { + if v == 1 { + delete(expLog, addr.Container()) + } else { + expLog[addr.Container()]-- + } + } } }) @@ -147,6 +253,14 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, true) + expPhy := make(map[cid.ID]uint64) + expLog := make(map[cid.ID]uint64) + for _, obj := range oo { + cnrID, _ := obj.ContainerID() + expPhy[cnrID]++ + expLog[cnrID]++ + } + inhumedObjs := make([]oid.Address, objCount/2) for i, o := range oo { @@ -157,6 +271,16 @@ func TestCounters(t *testing.T) { inhumedObjs[i] = objectcore.AddressOf(o) } + for _, addr := range inhumedObjs { + if v, ok := expLog[addr.Container()]; ok { + if v == 1 { + delete(expLog, addr.Container()) + } else { + expLog[addr.Container()]-- + } + } + } + var prm meta.InhumePrm prm.SetTombstoneAddress(oidtest.Address()) prm.SetAddresses(inhumedObjs...) @@ -169,6 +293,12 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(objCount), c.Phy()) require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic()) + + cc, err := db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) }) } @@ -190,6 +320,13 @@ func TestCounters_Expired(t *testing.T) { oo[i] = putWithExpiration(t, db, objectSDK.TypeRegular, epoch+1) } + expPhy := make(map[cid.ID]uint64) + expLog := make(map[cid.ID]uint64) + for _, addr := range oo { + expPhy[addr.Container()]++ + expLog[addr.Container()]++ + } + // 1. objects are available and counters are correct c, err := db.ObjectCounters() @@ -197,6 +334,12 @@ func TestCounters_Expired(t *testing.T) { require.Equal(t, uint64(objCount), c.Phy()) require.Equal(t, uint64(objCount), c.Logic()) + cc, err := db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) + for _, o := range oo { _, err := metaGet(db, o, true) require.NoError(t, err) @@ -212,6 +355,12 @@ func TestCounters_Expired(t *testing.T) { require.Equal(t, uint64(objCount), c.Phy()) require.Equal(t, uint64(objCount), c.Logic()) + cc, err = db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) + for _, o := range oo { _, err := metaGet(db, o, true) require.ErrorIs(t, err, meta.ErrObjectIsExpired) @@ -235,6 +384,20 @@ func TestCounters_Expired(t *testing.T) { require.Equal(t, uint64(len(oo)), c.Phy()) require.Equal(t, uint64(len(oo)-1), c.Logic()) + if v, ok := expLog[oo[0].Container()]; ok { + if v == 1 { + delete(expLog, oo[0].Container()) + } else { + expLog[oo[0].Container()]-- + } + } + + cc, err = db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) + // 4. `Delete` an object with GCMark should decrease the // phy counter but does not affect the logic counter (after // that step they should be equal) @@ -246,6 +409,14 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Zero(t, deleteRes.AvailableObjectsRemoved()) + if v, ok := expPhy[oo[0].Container()]; ok { + if v == 1 { + delete(expPhy, oo[0].Container()) + } else { + expPhy[oo[0].Container()]-- + } + } + oo = oo[1:] c, err = db.ObjectCounters() @@ -253,6 +424,12 @@ func TestCounters_Expired(t *testing.T) { require.Equal(t, uint64(len(oo)), c.Phy()) require.Equal(t, uint64(len(oo)), c.Logic()) + cc, err = db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) + // 5 `Delete` an expired object (like it would the control // service do) should decrease both counters despite the // expiration fact @@ -263,12 +440,34 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(1), deleteRes.AvailableObjectsRemoved()) + if v, ok := expLog[oo[0].Container()]; ok { + if v == 1 { + delete(expLog, oo[0].Container()) + } else { + expLog[oo[0].Container()]-- + } + } + + if v, ok := expPhy[oo[0].Container()]; ok { + if v == 1 { + delete(expPhy, oo[0].Container()) + } else { + expPhy[oo[0].Container()]-- + } + } + oo = oo[1:] c, err = db.ObjectCounters() require.NoError(t, err) require.Equal(t, uint64(len(oo)), c.Phy()) require.Equal(t, uint64(len(oo)), c.Logic()) + + cc, err = db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, expPhy, cc.Physical) + require.Equal(t, expLog, cc.Logical) } func putObjs(t *testing.T, db *meta.DB, count int, withParent bool) []*objectSDK.Object { diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index e84759b888..653a88ae7c 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -12,6 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -132,8 +133,9 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address, sizes []uint64, ava refCounter := make(referenceCounter, len(addrs)) currEpoch := db.epochState.CurrentEpoch() - var rawDeleted uint64 - var availableDeleted uint64 + cnrIDDelta := make(map[cid.ID]ObjectCounters) + var rawDeletedTotal uint64 + var availableDeletedTotal uint64 for i := range addrs { removed, available, size, err := db.delete(tx, addrs[i], refCounter, currEpoch) @@ -142,40 +144,62 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address, sizes []uint64, ava } if removed { - rawDeleted++ + if v, ok := cnrIDDelta[addrs[i].Container()]; ok { + v.phy++ + cnrIDDelta[addrs[i].Container()] = v + } else { + cnrIDDelta[addrs[i].Container()] = ObjectCounters{ + phy: 1, + } + } + + rawDeletedTotal++ sizes[i] = size } if available { - availableDeleted++ + if v, ok := cnrIDDelta[addrs[i].Container()]; ok { + v.logic++ + cnrIDDelta[addrs[i].Container()] = v + } else { + cnrIDDelta[addrs[i].Container()] = ObjectCounters{ + logic: 1, + } + } + + availableDeletedTotal++ availableSizes[i] = size } } - if rawDeleted > 0 { - err := db.updateCounter(tx, phy, rawDeleted, false) + if rawDeletedTotal > 0 { + err := db.updateShardObjectCounter(tx, phy, rawDeletedTotal, false) if err != nil { return 0, 0, fmt.Errorf("could not decrease phy object counter: %w", err) } } - if availableDeleted > 0 { - err := db.updateCounter(tx, logical, availableDeleted, false) + if availableDeletedTotal > 0 { + err := db.updateShardObjectCounter(tx, logical, availableDeletedTotal, false) if err != nil { return 0, 0, fmt.Errorf("could not decrease logical object counter: %w", err) } } + if err := db.updateContainerCounter(tx, cnrIDDelta, false); err != nil { + return 0, 0, fmt.Errorf("could not decrease container object counter: %w", err) + } + for _, refNum := range refCounter { if refNum.cur == refNum.all { err := db.deleteObject(tx, refNum.obj, true) if err != nil { - return rawDeleted, availableDeleted, err // maybe log and continue? + return rawDeletedTotal, availableDeletedTotal, err // maybe log and continue? } } } - return rawDeleted, availableDeleted, nil + return rawDeletedTotal, availableDeletedTotal, nil } // delete removes object indexes from the metabase. Counts the references diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index fe8b8873e1..e06e571096 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -73,6 +73,7 @@ func (i *InhumeRes) storeDeletionInfo(containerID cid.ID, deletedSize uint64) { Size: deletedSize, CID: containerID, }) + i.availableImhumed++ } // SetAddresses sets a list of object addresses that should be inhumed. @@ -224,7 +225,27 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes } } - return db.updateCounter(tx, logical, res.availableImhumed, false) + return db.applyInhumeResToCounters(tx, res) +} + +func (db *DB) applyInhumeResToCounters(tx *bbolt.Tx, res *InhumeRes) error { + var inhumedCount uint64 + inhumedbyCnr := make(map[cid.ID]ObjectCounters) + for _, dd := range res.deletionDetails { + if v, ok := inhumedbyCnr[dd.CID]; ok { + v.logic++ + inhumedbyCnr[dd.CID] = v + } else { + inhumedbyCnr[dd.CID] = ObjectCounters{logic: 1} + } + inhumedCount++ + } + + if err := db.updateShardObjectCounter(tx, logical, inhumedCount, false); err != nil { + return err + } + + return db.updateContainerCounter(tx, inhumedbyCnr, false) } // getInhumeTargetBucketAndValue return target bucket to store inhume result and value that will be put in the bucket. @@ -279,7 +300,6 @@ func (db *DB) markAsGC(graveyardBKT, garbageBKT *bbolt.Bucket, key []byte) (bool func (db *DB) updateDeleteInfo(tx *bbolt.Tx, garbageBKT, graveyardBKT *bbolt.Bucket, targetKey []byte, cnr cid.ID, obj *objectSDK.Object, res *InhumeRes) error { containerID, _ := obj.ContainerID() if inGraveyardWithKey(targetKey, graveyardBKT, garbageBKT) == 0 { - res.availableImhumed++ res.storeDeletionInfo(containerID, obj.PayloadSize()) } diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 875388e589..2b5c5421d0 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -183,16 +183,8 @@ func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *o } if !isParent { - err = db.updateCounter(tx, phy, 1, true) - if err != nil { - return fmt.Errorf("could not increase phy object counter: %w", err) - } - - // it is expected that putting an unavailable object is - // impossible and should be handled on the higher levels - err = db.updateCounter(tx, logical, 1, true) - if err != nil { - return fmt.Errorf("could not increase logical object counter: %w", err) + if err = db.incCounters(tx, cnr); err != nil { + return err } } diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index c9d9bb9476..c04aff61c0 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -19,9 +19,10 @@ var ( graveyardBucketName = []byte{graveyardPrefix} // garbageBucketName stores rows with the objects that should be physically // deleted by the node (Garbage Collector routine). - garbageBucketName = []byte{garbagePrefix} - toMoveItBucketName = []byte{toMoveItPrefix} - containerVolumeBucketName = []byte{containerVolumePrefix} + garbageBucketName = []byte{garbagePrefix} + toMoveItBucketName = []byte{toMoveItPrefix} + containerVolumeBucketName = []byte{containerVolumePrefix} + containerCounterBucketName = []byte{containerCountersPrefix} zeroValue = []byte{0xFF} ) @@ -111,6 +112,11 @@ const ( // Key: split ID // Value: list of object IDs splitPrefix + + // containerCountersPrefix is used for storing container object counters. + // Key: container ID + type + // Value: container size in bytes as little-endian uint64 + containerCountersPrefix ) const ( From 70ab1ebd541f89926b112944bb3eaeee08d33619 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 2 Nov 2023 13:50:52 +0300 Subject: [PATCH 0123/1413] [#763] metrics: Add container_objects_total metric Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 + pkg/local_object_storage/engine/metrics.go | 4 + pkg/local_object_storage/engine/shards.go | 12 +++ pkg/local_object_storage/metabase/delete.go | 78 +++++++-------- pkg/local_object_storage/metabase/inhume.go | 28 +++++- pkg/local_object_storage/shard/delete.go | 1 + pkg/local_object_storage/shard/gc.go | 3 + pkg/local_object_storage/shard/inhume.go | 1 + .../shard/metrics_test.go | 94 ++++++++++++++++++- pkg/local_object_storage/shard/put.go | 2 +- pkg/local_object_storage/shard/shard.go | 34 ++++++- pkg/metrics/engine.go | 46 ++++++++- 12 files changed, 250 insertions(+), 54 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index f8d6cc9b4e..5f361cefb0 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -516,4 +516,5 @@ const ( RuntimeSoftMemoryDefinedWithGOMEMLIMIT = "soft runtime memory defined with GOMEMLIMIT environment variable, config value skipped" FailedToCountWritecacheItems = "failed to count writecache items" AttemtToCloseAlreadyClosedBlobovnicza = "attempt to close an already closed blobovnicza" + FailedToGetContainerCounters = "failed to get container counters values" ) diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index fcac2dc603..363d098f61 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -21,6 +21,10 @@ type MetricRegister interface { ClearErrorCounter(shardID string) DeleteShardMetrics(shardID string) + SetContainerObjectCounter(shardID, contID, objectType string, v uint64) + IncContainerObjectCounter(shardID, contID, objectType string) + SubContainerObjectCounter(shardID, contID, objectType string, v uint64) + WriteCache() metrics.WriteCacheMetrics GC() metrics.GCMetrics } diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 4b9d8752a8..2e1cc75151 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -74,6 +74,18 @@ func (m *metricsWithID) DeleteShardMetrics() { m.mw.DeleteShardMetrics(m.id) } +func (m *metricsWithID) SetContainerObjectsCount(cnrID string, objectType string, value uint64) { + m.mw.SetContainerObjectCounter(m.id, cnrID, objectType, value) +} + +func (m *metricsWithID) IncContainerObjectsCount(cnrID string, objectType string) { + m.mw.IncContainerObjectCounter(m.id, cnrID, objectType) +} + +func (m *metricsWithID) SubContainerObjectsCount(cnrID string, objectType string, value uint64) { + m.mw.SubContainerObjectCounter(m.id, cnrID, objectType, value) +} + // AddShard adds a new shard to the storage engine. // // Returns any error encountered that did not allow adding a shard. diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 653a88ae7c..5acd711647 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -31,6 +31,7 @@ type DeleteRes struct { availableRemoved uint64 sizes []uint64 availableSizes []uint64 + removedByCnrID map[cid.ID]ObjectCounters } // AvailableObjectsRemoved returns the number of removed available @@ -39,6 +40,11 @@ func (d DeleteRes) AvailableObjectsRemoved() uint64 { return d.availableRemoved } +// RemovedByCnrID returns the number of removed objects by container ID. +func (d DeleteRes) RemovedByCnrID() map[cid.ID]ObjectCounters { + return d.removedByCnrID +} + // RawObjectsRemoved returns the number of removed raw objects. func (d DeleteRes) RawObjectsRemoved() uint64 { return d.rawRemoved @@ -96,15 +102,11 @@ func (db *DB) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { return DeleteRes{}, ErrReadOnlyMode } - var rawRemoved uint64 - var availableRemoved uint64 var err error - sizes := make([]uint64, len(prm.addrs)) - availableSizes := make([]uint64, len(prm.addrs)) + var res DeleteRes err = db.boltDB.Update(func(tx *bbolt.Tx) error { - // We need to clear slice because tx can try to execute multiple times. - rawRemoved, availableRemoved, err = db.deleteGroup(tx, prm.addrs, sizes, availableSizes) + res, err = db.deleteGroup(tx, prm.addrs) return err }) if err == nil { @@ -115,91 +117,83 @@ func (db *DB) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { storagelog.OpField("metabase DELETE")) } } - return DeleteRes{ - rawRemoved: rawRemoved, - availableRemoved: availableRemoved, - sizes: sizes, - availableSizes: availableSizes, - }, metaerr.Wrap(err) + return res, metaerr.Wrap(err) } // deleteGroup deletes object from the metabase. Handles removal of the // references of the split objects. -// The first return value is a physical objects removed number: physical -// objects that were stored. The second return value is a logical objects -// removed number: objects that were available (without Tombstones, GCMarks -// non-expired, etc.) -func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address, sizes []uint64, availableSizes []uint64) (uint64, uint64, error) { +func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) { + res := DeleteRes{ + sizes: make([]uint64, len(addrs)), + availableSizes: make([]uint64, len(addrs)), + removedByCnrID: make(map[cid.ID]ObjectCounters), + } refCounter := make(referenceCounter, len(addrs)) currEpoch := db.epochState.CurrentEpoch() - cnrIDDelta := make(map[cid.ID]ObjectCounters) - var rawDeletedTotal uint64 - var availableDeletedTotal uint64 - for i := range addrs { removed, available, size, err := db.delete(tx, addrs[i], refCounter, currEpoch) if err != nil { - return 0, 0, err // maybe log and continue? + return DeleteRes{}, err // maybe log and continue? } if removed { - if v, ok := cnrIDDelta[addrs[i].Container()]; ok { + if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { v.phy++ - cnrIDDelta[addrs[i].Container()] = v + res.removedByCnrID[addrs[i].Container()] = v } else { - cnrIDDelta[addrs[i].Container()] = ObjectCounters{ + res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ phy: 1, } } - rawDeletedTotal++ - sizes[i] = size + res.rawRemoved++ + res.sizes[i] = size } if available { - if v, ok := cnrIDDelta[addrs[i].Container()]; ok { + if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { v.logic++ - cnrIDDelta[addrs[i].Container()] = v + res.removedByCnrID[addrs[i].Container()] = v } else { - cnrIDDelta[addrs[i].Container()] = ObjectCounters{ + res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ logic: 1, } } - availableDeletedTotal++ - availableSizes[i] = size + res.availableRemoved++ + res.availableSizes[i] = size } } - if rawDeletedTotal > 0 { - err := db.updateShardObjectCounter(tx, phy, rawDeletedTotal, false) + if res.rawRemoved > 0 { + err := db.updateShardObjectCounter(tx, phy, res.rawRemoved, false) if err != nil { - return 0, 0, fmt.Errorf("could not decrease phy object counter: %w", err) + return DeleteRes{}, fmt.Errorf("could not decrease phy object counter: %w", err) } } - if availableDeletedTotal > 0 { - err := db.updateShardObjectCounter(tx, logical, availableDeletedTotal, false) + if res.availableRemoved > 0 { + err := db.updateShardObjectCounter(tx, logical, res.availableRemoved, false) if err != nil { - return 0, 0, fmt.Errorf("could not decrease logical object counter: %w", err) + return DeleteRes{}, fmt.Errorf("could not decrease logical object counter: %w", err) } } - if err := db.updateContainerCounter(tx, cnrIDDelta, false); err != nil { - return 0, 0, fmt.Errorf("could not decrease container object counter: %w", err) + if err := db.updateContainerCounter(tx, res.removedByCnrID, false); err != nil { + return DeleteRes{}, fmt.Errorf("could not decrease container object counter: %w", err) } for _, refNum := range refCounter { if refNum.cur == refNum.all { err := db.deleteObject(tx, refNum.obj, true) if err != nil { - return rawDeletedTotal, availableDeletedTotal, err // maybe log and continue? + return DeleteRes{}, err // maybe log and continue? } } } - return rawDeletedTotal, availableDeletedTotal, nil + return res, nil } // delete removes object indexes from the metabase. Counts the references diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index e06e571096..cf7921992a 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -37,14 +37,21 @@ type DeletionInfo struct { // InhumeRes encapsulates results of Inhume operation. type InhumeRes struct { deletedLockObj []oid.Address - availableImhumed uint64 + availableInhumed uint64 + inhumedByCnrID map[cid.ID]ObjectCounters deletionDetails []DeletionInfo } // AvailableInhumed return number of available object // that have been inhumed. func (i InhumeRes) AvailableInhumed() uint64 { - return i.availableImhumed + return i.availableInhumed +} + +// InhumedByCnrID return number of object +// that have been inhumed by container ID. +func (i InhumeRes) InhumedByCnrID() map[cid.ID]ObjectCounters { + return i.inhumedByCnrID } // DeletedLockObjects returns deleted object of LOCK @@ -73,7 +80,15 @@ func (i *InhumeRes) storeDeletionInfo(containerID cid.ID, deletedSize uint64) { Size: deletedSize, CID: containerID, }) - i.availableImhumed++ + i.availableInhumed++ + if v, ok := i.inhumedByCnrID[containerID]; ok { + v.logic++ + i.inhumedByCnrID[containerID] = v + } else { + i.inhumedByCnrID[containerID] = ObjectCounters{ + logic: 1, + } + } } // SetAddresses sets a list of object addresses that should be inhumed. @@ -123,7 +138,7 @@ var ErrLockObjectRemoval = logicerr.New("lock object removal") // // NOTE: Marks any object with GC mark (despite any prohibitions on operations // with that object) if WithForceGCMark option has been provided. -func (db *DB) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRes, err error) { +func (db *DB) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { var ( startedAt = time.Now() success = false @@ -143,8 +158,11 @@ func (db *DB) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRes, err err return InhumeRes{}, ErrReadOnlyMode } + res := InhumeRes{ + inhumedByCnrID: make(map[cid.ID]ObjectCounters), + } currEpoch := db.epochState.CurrentEpoch() - err = db.boltDB.Update(func(tx *bbolt.Tx) error { + err := db.boltDB.Update(func(tx *bbolt.Tx) error { return db.inhumeTx(tx, currEpoch, prm, &res) }) success = err == nil diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index e24bd85419..663d781adc 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -118,6 +118,7 @@ func (s *Shard) deleteFromMetabase(ctx context.Context, addr oid.Address) error } s.decObjectCounterBy(physical, res.RawObjectsRemoved()) s.decObjectCounterBy(logical, res.AvailableObjectsRemoved()) + s.decContainerObjectCounter(res.RemovedByCnrID()) removedPayload := res.RemovedPhysicalObjectSizes()[0] logicalRemovedPayload := res.RemovedLogicalObjectSizes()[0] if logicalRemovedPayload > 0 { diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 0ce99b475f..346903c5cd 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -416,6 +416,7 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeRegular) s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decContainerObjectCounter(res.InhumedByCnrID()) i := 0 for i < res.GetDeletionInfoLength() { @@ -629,6 +630,7 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeTombstone) s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decContainerObjectCounter(res.InhumedByCnrID()) i := 0 for i < res.GetDeletionInfoLength() { @@ -675,6 +677,7 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeLock) s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decContainerObjectCounter(res.InhumedByCnrID()) i := 0 for i < res.GetDeletionInfoLength() { diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index a5f8960c3c..335df82f0e 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -122,6 +122,7 @@ func (s *Shard) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { s.m.RUnlock() s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decContainerObjectCounter(res.InhumedByCnrID()) i := 0 for i < res.GetDeletionInfoLength() { diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 7724aa2224..1e9bbf9fcc 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -14,6 +14,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" @@ -23,6 +24,7 @@ type metricsStore struct { mtx sync.Mutex objCounters map[string]uint64 cnrSize map[string]int64 + cnrCount map[string]uint64 pldSize int64 mode mode.Mode errCounter int64 @@ -126,6 +128,39 @@ func (m *metricsStore) DeleteShardMetrics() { m.errCounter = 0 } +func (m *metricsStore) SetContainerObjectsCount(cnrID string, objectType string, value uint64) { + m.mtx.Lock() + defer m.mtx.Unlock() + m.cnrCount[cnrID+objectType] = value +} + +func (m *metricsStore) IncContainerObjectsCount(cnrID string, objectType string) { + m.mtx.Lock() + defer m.mtx.Unlock() + m.cnrCount[cnrID+objectType]++ +} + +func (m *metricsStore) SubContainerObjectsCount(cnrID string, objectType string, value uint64) { + m.mtx.Lock() + defer m.mtx.Unlock() + existed := m.cnrCount[cnrID+objectType] + if existed < value { + panic("existed value smaller than value to sustract") + } + if existed == value { + delete(m.cnrCount, cnrID+objectType) + } else { + m.cnrCount[cnrID+objectType] -= value + } +} + +func (m *metricsStore) getContainerCount(cnrID, objectType string) (uint64, bool) { + m.mtx.Lock() + defer m.mtx.Unlock() + v, ok := m.cnrCount[cnrID+objectType] + return v, ok +} + func TestCounters(t *testing.T) { t.Parallel() @@ -143,21 +178,37 @@ func TestCounters(t *testing.T) { oo[i] = testutil.GenerateObject() } + cc := meta.ContainerCounters{Logical: make(map[cid.ID]uint64), Physical: make(map[cid.ID]uint64)} + t.Run("defaults", func(t *testing.T) { require.Zero(t, mm.getObjectCounter(physical)) require.Zero(t, mm.getObjectCounter(logical)) require.Empty(t, mm.containerSizes()) require.Zero(t, mm.payloadSize()) + + for _, obj := range oo { + contID, _ := obj.ContainerID() + v, ok := mm.getContainerCount(contID.EncodeToString(), physical) + require.Zero(t, v) + require.False(t, ok) + v, ok = mm.getContainerCount(contID.EncodeToString(), logical) + require.Zero(t, v) + require.False(t, ok) + } }) var totalPayload int64 expectedLogicalSizes := make(map[string]int64) + expectedLogCC := make(map[cid.ID]uint64) + expectedPhyCC := make(map[cid.ID]uint64) for i := range oo { cnr, _ := oo[i].ContainerID() oSize := int64(oo[i].PayloadSize()) expectedLogicalSizes[cnr.EncodeToString()] += oSize totalPayload += oSize + expectedLogCC[cnr]++ + expectedPhyCC[cnr]++ } var prm PutPrm @@ -174,6 +225,11 @@ func TestCounters(t *testing.T) { require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) + cc, err := sh.metaBase.ContainerCounters(context.Background()) + require.NoError(t, err) + require.Equal(t, expectedLogCC, cc.Logical) + require.Equal(t, expectedPhyCC, cc.Physical) + t.Run("inhume_GC", func(t *testing.T) { var prm InhumePrm inhumedNumber := objNumber / 4 @@ -187,6 +243,11 @@ func TestCounters(t *testing.T) { cid, ok := oo[i].ContainerID() require.True(t, ok) expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) + + expectedLogCC[cid]-- + if expectedLogCC[cid] == 0 { + delete(expectedLogCC, cid) + } } require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) @@ -194,6 +255,11 @@ func TestCounters(t *testing.T) { require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) + cc, err := sh.metaBase.ContainerCounters(context.Background()) + require.NoError(t, err) + require.Equal(t, expectedLogCC, cc.Logical) + require.Equal(t, expectedPhyCC, cc.Physical) + oo = oo[inhumedNumber:] }) @@ -214,6 +280,11 @@ func TestCounters(t *testing.T) { cid, ok := oo[i].ContainerID() require.True(t, ok) expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) + + expectedLogCC[cid]-- + if expectedLogCC[cid] == 0 { + delete(expectedLogCC, cid) + } } require.Equal(t, phy, mm.getObjectCounter(physical)) @@ -221,6 +292,11 @@ func TestCounters(t *testing.T) { require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) + cc, err = sh.metaBase.ContainerCounters(context.Background()) + require.NoError(t, err) + require.Equal(t, expectedLogCC, cc.Logical) + require.Equal(t, expectedPhyCC, cc.Physical) + oo = oo[inhumedNumber:] }) @@ -245,9 +321,24 @@ func TestCounters(t *testing.T) { cnr, _ := oo[i].ContainerID() expectedLogicalSizes[cnr.EncodeToString()] -= int64(removedPayload) + + expectedLogCC[cnr]-- + if expectedLogCC[cnr] == 0 { + delete(expectedLogCC, cnr) + } + + expectedPhyCC[cnr]-- + if expectedPhyCC[cnr] == 0 { + delete(expectedPhyCC, cnr) + } } require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload-int64(totalRemovedpayload), mm.payloadSize()) + + cc, err = sh.metaBase.ContainerCounters(context.Background()) + require.NoError(t, err) + require.Equal(t, expectedLogCC, cc.Logical) + require.Equal(t, expectedPhyCC, cc.Physical) }) } @@ -268,7 +359,8 @@ func shardWithMetrics(t *testing.T, path string) (*Shard, *metricsStore) { "phy": 0, "logic": 0, }, - cnrSize: make(map[string]int64), + cnrSize: make(map[string]int64), + cnrCount: make(map[string]uint64), } sh := New( diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index 688b7aae78..10983d041a 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -90,7 +90,7 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { return PutRes{}, fmt.Errorf("could not put object to metabase: %w", err) } - s.incObjectCounter() + s.incObjectCounter(putPrm.Address.Container()) s.addToPayloadSize(int64(prm.obj.PayloadSize())) s.addToContainerSize(putPrm.Address.Container().EncodeToString(), int64(prm.obj.PayloadSize())) } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 00f4fbb9e1..07b7740220 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -18,6 +18,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) @@ -85,6 +86,12 @@ type MetricsWriter interface { ClearErrorCounter() // DeleteShardMetrics deletes shard metrics from registry. DeleteShardMetrics() + // SetContainerObjectsCount sets container object count. + SetContainerObjectsCount(cnrID string, objectType string, value uint64) + // IncContainerObjectsCount increments container object count. + IncContainerObjectsCount(cnrID string, objectType string) + // SubContainerObjectsCount subtracts container object count. + SubContainerObjectsCount(cnrID string, objectType string, value uint64) } type cfg struct { @@ -425,15 +432,29 @@ func (s *Shard) updateMetrics(ctx context.Context) { } s.metricsWriter.AddToPayloadSize(int64(totalPayload)) + + contCount, err := s.metaBase.ContainerCounters(ctx) + if err != nil { + s.log.Warn(logs.FailedToGetContainerCounters, zap.Error(err)) + return + } + for contID, count := range contCount.Physical { + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), physical, count) + } + for contID, count := range contCount.Logical { + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), logical, count) + } } } // incObjectCounter increment both physical and logical object // counters. -func (s *Shard) incObjectCounter() { +func (s *Shard) incObjectCounter(cnrID cid.ID) { if s.cfg.metricsWriter != nil { s.cfg.metricsWriter.IncObjectCounter(physical) s.cfg.metricsWriter.IncObjectCounter(logical) + s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), physical) + s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), logical) } } @@ -443,6 +464,17 @@ func (s *Shard) decObjectCounterBy(typ string, v uint64) { } } +func (s *Shard) decContainerObjectCounter(byCnr map[cid.ID]meta.ObjectCounters) { + if s.cfg.metricsWriter == nil { + return + } + + for cnrID, count := range byCnr { + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy()) + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic()) + } +} + func (s *Shard) addToContainerSize(cnr string, size int64) { if s.cfg.metricsWriter != nil { s.cfg.metricsWriter.AddToContainerSize(cnr, size) diff --git a/pkg/metrics/engine.go b/pkg/metrics/engine.go index 23d799e282..609c30f97d 100644 --- a/pkg/metrics/engine.go +++ b/pkg/metrics/engine.go @@ -18,6 +18,9 @@ type EngineMetrics interface { SetObjectCounter(shardID, objectType string, v uint64) AddToPayloadCounter(shardID string, size int64) SetMode(shardID string, mode mode.Mode) + SetContainerObjectCounter(shardID, contID, objectType string, v uint64) + IncContainerObjectCounter(shardID, contID, objectType string) + SubContainerObjectCounter(shardID, contID, objectType string, v uint64) WriteCache() WriteCacheMetrics GC() GCMetrics @@ -30,6 +33,7 @@ type engineMetrics struct { payloadSize *prometheus.GaugeVec errorCounter *prometheus.GaugeVec mode *shardIDModeValue + contObjCounter *prometheus.GaugeVec gc *gcMetrics writeCache *writeCacheMetrics @@ -46,10 +50,13 @@ func newEngineMetrics() *engineMetrics { Name: "request_duration_seconds", Help: "Duration of Engine requests", }, []string{methodLabel}), - objectCounter: newEngineGaugeVector("objects_total", "Objects counters per shards", []string{shardIDLabel, typeLabel}), - gc: newGCMetrics(), - writeCache: newWriteCacheMetrics(), - mode: newShardIDMode(engineSubsystem, "mode_info", "Shard mode"), + objectCounter: newEngineGaugeVector("objects_total", + "Objects counters per shards. DEPRECATED: Will be deleted in next releasese, use frostfs_node_engine_container_objects_total metric.", + []string{shardIDLabel, typeLabel}), + gc: newGCMetrics(), + writeCache: newWriteCacheMetrics(), + mode: newShardIDMode(engineSubsystem, "mode_info", "Shard mode"), + contObjCounter: newEngineGaugeVector("container_objects_total", "Count of objects for each container", []string{shardIDLabel, containerIDLabelKey, typeLabel}), } } @@ -88,6 +95,7 @@ func (m *engineMetrics) DeleteShardMetrics(shardID string) { m.errorCounter.Delete(prometheus.Labels{shardIDLabel: shardID}) m.payloadSize.Delete(prometheus.Labels{shardIDLabel: shardID}) m.objectCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) + m.contObjCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) m.mode.Delete(shardID) } @@ -109,6 +117,36 @@ func (m *engineMetrics) SetObjectCounter(shardID, objectType string, v uint64) { ).Set(float64(v)) } +func (m *engineMetrics) SetContainerObjectCounter(shardID, contID, objectType string, v uint64) { + m.contObjCounter.With( + prometheus.Labels{ + shardIDLabel: shardID, + containerIDLabelKey: contID, + typeLabel: objectType, + }, + ).Set(float64(v)) +} + +func (m *engineMetrics) IncContainerObjectCounter(shardID, contID, objectType string) { + m.contObjCounter.With( + prometheus.Labels{ + shardIDLabel: shardID, + containerIDLabelKey: contID, + typeLabel: objectType, + }, + ).Inc() +} + +func (m *engineMetrics) SubContainerObjectCounter(shardID, contID, objectType string, v uint64) { + m.contObjCounter.With( + prometheus.Labels{ + shardIDLabel: shardID, + containerIDLabelKey: contID, + typeLabel: objectType, + }, + ).Sub(float64(v)) +} + func (m *engineMetrics) SetMode(shardID string, mode mode.Mode) { m.mode.SetMode(shardID, mode.String()) } From 3a2c319b87adcfbb371cf6acee6df3807d90cadc Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 31 Oct 2023 18:36:42 +0300 Subject: [PATCH 0124/1413] [#770] control: Generate gRPC methods to manipulate APE chains * Define new types and gRPC methods to manipulate APE chains in control service. * Stub gRPC handlers for the generated methods. Signed-off-by: Airat Arifullin --- pkg/services/control/server/policy_engine.go | 24 + pkg/services/control/service.pb.go | 1740 +++++++++++++++--- pkg/services/control/service.proto | 114 ++ pkg/services/control/service_frostfs.pb.go | 694 +++++++ pkg/services/control/service_grpc.pb.go | 156 ++ 5 files changed, 2465 insertions(+), 263 deletions(-) create mode 100644 pkg/services/control/server/policy_engine.go diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go new file mode 100644 index 0000000000..058839bfb5 --- /dev/null +++ b/pkg/services/control/server/policy_engine.go @@ -0,0 +1,24 @@ +package control + +import ( + "context" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" +) + +func (s *Server) AddChainLocalOverride(ctx context.Context, req *control.AddChainLocalOverrideRequest) (*control.AddChainLocalOverrideResponse, error) { + return nil, fmt.Errorf("not implemented yet") +} + +func (s *Server) GetChainLocalOverride(ctx context.Context, req *control.GetChainLocalOverrideRequest) (*control.GetChainLocalOverrideResponse, error) { + return nil, fmt.Errorf("not implemented yet") +} + +func (s *Server) ListChainLocalOverrides(ctx context.Context, req *control.ListChainLocalOverridesRequest) (*control.ListChainLocalOverridesResponse, error) { + return nil, fmt.Errorf("not implemented yet") +} + +func (s *Server) RemoveChainLocalOverride(ctx context.Context, req *control.RemoveChainLocalOverrideRequest) (*control.RemoveChainLocalOverrideResponse, error) { + return nil, fmt.Errorf("not implemented yet") +} diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 443afb1aab..547ea7e7e2 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -1438,6 +1438,452 @@ func (x *StopShardEvacuationResponse) GetSignature() *Signature { return nil } +// AddChainLocalOverride request. +type AddChainLocalOverrideRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *AddChainLocalOverrideRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *AddChainLocalOverrideRequest) Reset() { + *x = AddChainLocalOverrideRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddChainLocalOverrideRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddChainLocalOverrideRequest) ProtoMessage() {} + +func (x *AddChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddChainLocalOverrideRequest.ProtoReflect.Descriptor instead. +func (*AddChainLocalOverrideRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24} +} + +func (x *AddChainLocalOverrideRequest) GetBody() *AddChainLocalOverrideRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *AddChainLocalOverrideRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +// AddChainLocalOverride response. +type AddChainLocalOverrideResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *AddChainLocalOverrideResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *AddChainLocalOverrideResponse) Reset() { + *x = AddChainLocalOverrideResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddChainLocalOverrideResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddChainLocalOverrideResponse) ProtoMessage() {} + +func (x *AddChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddChainLocalOverrideResponse.ProtoReflect.Descriptor instead. +func (*AddChainLocalOverrideResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25} +} + +func (x *AddChainLocalOverrideResponse) GetBody() *AddChainLocalOverrideResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *AddChainLocalOverrideResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +// GetChainLocalOverride request. +type GetChainLocalOverrideRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *GetChainLocalOverrideRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetChainLocalOverrideRequest) Reset() { + *x = GetChainLocalOverrideRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[26] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetChainLocalOverrideRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetChainLocalOverrideRequest) ProtoMessage() {} + +func (x *GetChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[26] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetChainLocalOverrideRequest.ProtoReflect.Descriptor instead. +func (*GetChainLocalOverrideRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26} +} + +func (x *GetChainLocalOverrideRequest) GetBody() *GetChainLocalOverrideRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetChainLocalOverrideRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +// GetChainLocalOverride response. +type GetChainLocalOverrideResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *GetChainLocalOverrideResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetChainLocalOverrideResponse) Reset() { + *x = GetChainLocalOverrideResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetChainLocalOverrideResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetChainLocalOverrideResponse) ProtoMessage() {} + +func (x *GetChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[27] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetChainLocalOverrideResponse.ProtoReflect.Descriptor instead. +func (*GetChainLocalOverrideResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27} +} + +func (x *GetChainLocalOverrideResponse) GetBody() *GetChainLocalOverrideResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetChainLocalOverrideResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +// ListChainLocalOverrides request. +type ListChainLocalOverridesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *ListChainLocalOverridesRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *ListChainLocalOverridesRequest) Reset() { + *x = ListChainLocalOverridesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListChainLocalOverridesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListChainLocalOverridesRequest) ProtoMessage() {} + +func (x *ListChainLocalOverridesRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListChainLocalOverridesRequest.ProtoReflect.Descriptor instead. +func (*ListChainLocalOverridesRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28} +} + +func (x *ListChainLocalOverridesRequest) GetBody() *ListChainLocalOverridesRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ListChainLocalOverridesRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +// ListChainLocalOverrides response. +type ListChainLocalOverridesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *ListChainLocalOverridesResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *ListChainLocalOverridesResponse) Reset() { + *x = ListChainLocalOverridesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListChainLocalOverridesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListChainLocalOverridesResponse) ProtoMessage() {} + +func (x *ListChainLocalOverridesResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListChainLocalOverridesResponse.ProtoReflect.Descriptor instead. +func (*ListChainLocalOverridesResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29} +} + +func (x *ListChainLocalOverridesResponse) GetBody() *ListChainLocalOverridesResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ListChainLocalOverridesResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type RemoveChainLocalOverrideRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *RemoveChainLocalOverrideRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *RemoveChainLocalOverrideRequest) Reset() { + *x = RemoveChainLocalOverrideRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveChainLocalOverrideRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveChainLocalOverrideRequest) ProtoMessage() {} + +func (x *RemoveChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveChainLocalOverrideRequest.ProtoReflect.Descriptor instead. +func (*RemoveChainLocalOverrideRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30} +} + +func (x *RemoveChainLocalOverrideRequest) GetBody() *RemoveChainLocalOverrideRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *RemoveChainLocalOverrideRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type RemoveChainLocalOverrideResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *RemoveChainLocalOverrideResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *RemoveChainLocalOverrideResponse) Reset() { + *x = RemoveChainLocalOverrideResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveChainLocalOverrideResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveChainLocalOverrideResponse) ProtoMessage() {} + +func (x *RemoveChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveChainLocalOverrideResponse.ProtoReflect.Descriptor instead. +func (*RemoveChainLocalOverrideResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31} +} + +func (x *RemoveChainLocalOverrideResponse) GetBody() *RemoveChainLocalOverrideResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *RemoveChainLocalOverrideResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + // Health check request body. type HealthCheckRequest_Body struct { state protoimpl.MessageState @@ -1448,7 +1894,7 @@ type HealthCheckRequest_Body struct { func (x *HealthCheckRequest_Body) Reset() { *x = HealthCheckRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[24] + mi := &file_pkg_services_control_service_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1461,7 +1907,7 @@ func (x *HealthCheckRequest_Body) String() string { func (*HealthCheckRequest_Body) ProtoMessage() {} func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[24] + mi := &file_pkg_services_control_service_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1492,7 +1938,7 @@ type HealthCheckResponse_Body struct { func (x *HealthCheckResponse_Body) Reset() { *x = HealthCheckResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[25] + mi := &file_pkg_services_control_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1505,7 +1951,7 @@ func (x *HealthCheckResponse_Body) String() string { func (*HealthCheckResponse_Body) ProtoMessage() {} func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[25] + mi := &file_pkg_services_control_service_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1556,7 +2002,7 @@ type SetNetmapStatusRequest_Body struct { func (x *SetNetmapStatusRequest_Body) Reset() { *x = SetNetmapStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[26] + mi := &file_pkg_services_control_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1569,7 +2015,7 @@ func (x *SetNetmapStatusRequest_Body) String() string { func (*SetNetmapStatusRequest_Body) ProtoMessage() {} func (x *SetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[26] + mi := &file_pkg_services_control_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1609,7 +2055,7 @@ type SetNetmapStatusResponse_Body struct { func (x *SetNetmapStatusResponse_Body) Reset() { *x = SetNetmapStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[27] + mi := &file_pkg_services_control_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1622,7 +2068,7 @@ func (x *SetNetmapStatusResponse_Body) String() string { func (*SetNetmapStatusResponse_Body) ProtoMessage() {} func (x *SetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[27] + mi := &file_pkg_services_control_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1652,7 +2098,7 @@ type DropObjectsRequest_Body struct { func (x *DropObjectsRequest_Body) Reset() { *x = DropObjectsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[28] + mi := &file_pkg_services_control_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1665,7 +2111,7 @@ func (x *DropObjectsRequest_Body) String() string { func (*DropObjectsRequest_Body) ProtoMessage() {} func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[28] + mi := &file_pkg_services_control_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1698,7 +2144,7 @@ type DropObjectsResponse_Body struct { func (x *DropObjectsResponse_Body) Reset() { *x = DropObjectsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[29] + mi := &file_pkg_services_control_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1711,7 +2157,7 @@ func (x *DropObjectsResponse_Body) String() string { func (*DropObjectsResponse_Body) ProtoMessage() {} func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[29] + mi := &file_pkg_services_control_service_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1737,7 +2183,7 @@ type ListShardsRequest_Body struct { func (x *ListShardsRequest_Body) Reset() { *x = ListShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[30] + mi := &file_pkg_services_control_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1750,7 +2196,7 @@ func (x *ListShardsRequest_Body) String() string { func (*ListShardsRequest_Body) ProtoMessage() {} func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[30] + mi := &file_pkg_services_control_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1779,7 +2225,7 @@ type ListShardsResponse_Body struct { func (x *ListShardsResponse_Body) Reset() { *x = ListShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[31] + mi := &file_pkg_services_control_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1792,7 +2238,7 @@ func (x *ListShardsResponse_Body) String() string { func (*ListShardsResponse_Body) ProtoMessage() {} func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[31] + mi := &file_pkg_services_control_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1832,7 +2278,7 @@ type SetShardModeRequest_Body struct { func (x *SetShardModeRequest_Body) Reset() { *x = SetShardModeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1845,7 +2291,7 @@ func (x *SetShardModeRequest_Body) String() string { func (*SetShardModeRequest_Body) ProtoMessage() {} func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1892,7 +2338,7 @@ type SetShardModeResponse_Body struct { func (x *SetShardModeResponse_Body) Reset() { *x = SetShardModeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1905,7 +2351,7 @@ func (x *SetShardModeResponse_Body) String() string { func (*SetShardModeResponse_Body) ProtoMessage() {} func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1936,7 +2382,7 @@ type SynchronizeTreeRequest_Body struct { func (x *SynchronizeTreeRequest_Body) Reset() { *x = SynchronizeTreeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1949,7 +2395,7 @@ func (x *SynchronizeTreeRequest_Body) String() string { func (*SynchronizeTreeRequest_Body) ProtoMessage() {} func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1996,7 +2442,7 @@ type SynchronizeTreeResponse_Body struct { func (x *SynchronizeTreeResponse_Body) Reset() { *x = SynchronizeTreeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2009,7 +2455,7 @@ func (x *SynchronizeTreeResponse_Body) String() string { func (*SynchronizeTreeResponse_Body) ProtoMessage() {} func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2040,7 +2486,7 @@ type EvacuateShardRequest_Body struct { func (x *EvacuateShardRequest_Body) Reset() { *x = EvacuateShardRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2053,7 +2499,7 @@ func (x *EvacuateShardRequest_Body) String() string { func (*EvacuateShardRequest_Body) ProtoMessage() {} func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2095,7 +2541,7 @@ type EvacuateShardResponse_Body struct { func (x *EvacuateShardResponse_Body) Reset() { *x = EvacuateShardResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2108,7 +2554,7 @@ func (x *EvacuateShardResponse_Body) String() string { func (*EvacuateShardResponse_Body) ProtoMessage() {} func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2144,7 +2590,7 @@ type FlushCacheRequest_Body struct { func (x *FlushCacheRequest_Body) Reset() { *x = FlushCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2157,7 +2603,7 @@ func (x *FlushCacheRequest_Body) String() string { func (*FlushCacheRequest_Body) ProtoMessage() {} func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2190,7 +2636,7 @@ type FlushCacheResponse_Body struct { func (x *FlushCacheResponse_Body) Reset() { *x = FlushCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2203,7 +2649,7 @@ func (x *FlushCacheResponse_Body) String() string { func (*FlushCacheResponse_Body) ProtoMessage() {} func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2234,7 +2680,7 @@ type DoctorRequest_Body struct { func (x *DoctorRequest_Body) Reset() { *x = DoctorRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2247,7 +2693,7 @@ func (x *DoctorRequest_Body) String() string { func (*DoctorRequest_Body) ProtoMessage() {} func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2287,7 +2733,7 @@ type DoctorResponse_Body struct { func (x *DoctorResponse_Body) Reset() { *x = DoctorResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2300,7 +2746,7 @@ func (x *DoctorResponse_Body) String() string { func (*DoctorResponse_Body) ProtoMessage() {} func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2331,7 +2777,7 @@ type StartShardEvacuationRequest_Body struct { func (x *StartShardEvacuationRequest_Body) Reset() { *x = StartShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2344,7 +2790,7 @@ func (x *StartShardEvacuationRequest_Body) String() string { func (*StartShardEvacuationRequest_Body) ProtoMessage() {} func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2384,7 +2830,7 @@ type StartShardEvacuationResponse_Body struct { func (x *StartShardEvacuationResponse_Body) Reset() { *x = StartShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2397,7 +2843,7 @@ func (x *StartShardEvacuationResponse_Body) String() string { func (*StartShardEvacuationResponse_Body) ProtoMessage() {} func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2423,7 +2869,7 @@ type GetShardEvacuationStatusRequest_Body struct { func (x *GetShardEvacuationStatusRequest_Body) Reset() { *x = GetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2436,7 +2882,7 @@ func (x *GetShardEvacuationStatusRequest_Body) String() string { func (*GetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2481,7 +2927,7 @@ type GetShardEvacuationStatusResponse_Body struct { func (x *GetShardEvacuationStatusResponse_Body) Reset() { *x = GetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2494,7 +2940,7 @@ func (x *GetShardEvacuationStatusResponse_Body) String() string { func (*GetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2585,7 +3031,7 @@ type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) Reset() { *x = GetShardEvacuationStatusResponse_Body_UnixTimestamp{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2598,7 +3044,7 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) String() string { func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2633,7 +3079,7 @@ type GetShardEvacuationStatusResponse_Body_Duration struct { func (x *GetShardEvacuationStatusResponse_Body_Duration) Reset() { *x = GetShardEvacuationStatusResponse_Body_Duration{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2646,7 +3092,7 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) String() string { func (*GetShardEvacuationStatusResponse_Body_Duration) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2679,7 +3125,7 @@ type StopShardEvacuationRequest_Body struct { func (x *StopShardEvacuationRequest_Body) Reset() { *x = StopShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2692,7 +3138,7 @@ func (x *StopShardEvacuationRequest_Body) String() string { func (*StopShardEvacuationRequest_Body) ProtoMessage() {} func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2718,7 +3164,7 @@ type StopShardEvacuationResponse_Body struct { func (x *StopShardEvacuationResponse_Body) Reset() { *x = StopShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2731,7 +3177,7 @@ func (x *StopShardEvacuationResponse_Body) String() string { func (*StopShardEvacuationResponse_Body) ProtoMessage() {} func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2747,6 +3193,416 @@ func (*StopShardEvacuationResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0} } +type AddChainLocalOverrideRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container id for which the overrides are applied. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // Serialized rule chain. + Chain []byte `protobuf:"bytes,2,opt,name=chain,proto3" json:"chain,omitempty"` +} + +func (x *AddChainLocalOverrideRequest_Body) Reset() { + *x = AddChainLocalOverrideRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[58] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddChainLocalOverrideRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddChainLocalOverrideRequest_Body) ProtoMessage() {} + +func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[58] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. +func (*AddChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24, 0} +} + +func (x *AddChainLocalOverrideRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *AddChainLocalOverrideRequest_Body) GetChain() []byte { + if x != nil { + return x.Chain + } + return nil +} + +type AddChainLocalOverrideResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Chain ID assigned for the added rule chain. + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (x *AddChainLocalOverrideResponse_Body) Reset() { + *x = AddChainLocalOverrideResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[59] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddChainLocalOverrideResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddChainLocalOverrideResponse_Body) ProtoMessage() {} + +func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[59] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. +func (*AddChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25, 0} +} + +func (x *AddChainLocalOverrideResponse_Body) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +type GetChainLocalOverrideRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container id for which the overrides are defined. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // Chain ID assigned for the added rule chain. + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (x *GetChainLocalOverrideRequest_Body) Reset() { + *x = GetChainLocalOverrideRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[60] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetChainLocalOverrideRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetChainLocalOverrideRequest_Body) ProtoMessage() {} + +func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[60] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. +func (*GetChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26, 0} +} + +func (x *GetChainLocalOverrideRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *GetChainLocalOverrideRequest_Body) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +type GetChainLocalOverrideResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Serialized rule chain. + Chain []byte `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` +} + +func (x *GetChainLocalOverrideResponse_Body) Reset() { + *x = GetChainLocalOverrideResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetChainLocalOverrideResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetChainLocalOverrideResponse_Body) ProtoMessage() {} + +func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[61] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. +func (*GetChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27, 0} +} + +func (x *GetChainLocalOverrideResponse_Body) GetChain() []byte { + if x != nil { + return x.Chain + } + return nil +} + +type ListChainLocalOverridesRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container id for which the overrides are defined. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` +} + +func (x *ListChainLocalOverridesRequest_Body) Reset() { + *x = ListChainLocalOverridesRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[62] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListChainLocalOverridesRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListChainLocalOverridesRequest_Body) ProtoMessage() {} + +func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[62] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListChainLocalOverridesRequest_Body.ProtoReflect.Descriptor instead. +func (*ListChainLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28, 0} +} + +func (x *ListChainLocalOverridesRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +type ListChainLocalOverridesResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The list of serialized rule chain. + Chains [][]byte `protobuf:"bytes,1,rep,name=chains,proto3" json:"chains,omitempty"` +} + +func (x *ListChainLocalOverridesResponse_Body) Reset() { + *x = ListChainLocalOverridesResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[63] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListChainLocalOverridesResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListChainLocalOverridesResponse_Body) ProtoMessage() {} + +func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[63] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListChainLocalOverridesResponse_Body.ProtoReflect.Descriptor instead. +func (*ListChainLocalOverridesResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29, 0} +} + +func (x *ListChainLocalOverridesResponse_Body) GetChains() [][]byte { + if x != nil { + return x.Chains + } + return nil +} + +type RemoveChainLocalOverrideRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Container id for which the overrides are defined. + ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // Chain ID assigned for the added rule chain. + ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` +} + +func (x *RemoveChainLocalOverrideRequest_Body) Reset() { + *x = RemoveChainLocalOverrideRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveChainLocalOverrideRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveChainLocalOverrideRequest_Body) ProtoMessage() {} + +func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[64] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. +func (*RemoveChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} +} + +func (x *RemoveChainLocalOverrideRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} + +func (x *RemoveChainLocalOverrideRequest_Body) GetChainId() string { + if x != nil { + return x.ChainId + } + return "" +} + +type RemoveChainLocalOverrideResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Removed bool `protobuf:"varint,1,opt,name=removed,proto3" json:"removed,omitempty"` +} + +func (x *RemoveChainLocalOverrideResponse_Body) Reset() { + *x = RemoveChainLocalOverrideResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[65] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveChainLocalOverrideResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveChainLocalOverrideResponse_Body) ProtoMessage() {} + +func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[65] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. +func (*RemoveChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31, 0} +} + +func (x *RemoveChainLocalOverrideResponse_Body) GetRemoved() bool { + if x != nil { + return x.Removed + } + return false +} + var File_pkg_services_control_service_proto protoreflect.FileDescriptor var file_pkg_services_control_service_proto_rawDesc = []byte{ @@ -3049,75 +3905,201 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xee, - 0x07, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, - 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xd1, + 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x3f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xd6, 0x01, 0x0a, 0x1c, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x44, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xbf, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x29, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x73, 0x22, 0xdc, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x44, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x32, 0x9d, 0x0b, + 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, + 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, - 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, - 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, - 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, - 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, - 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, - 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, - 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, - 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, - 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, - 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, + 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, + 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, + 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, + 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, + 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, + 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, + 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, + 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, + 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, + 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3133,7 +4115,7 @@ func file_pkg_services_control_service_proto_rawDescGZIP() []byte { } var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 50) +var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 66) var file_pkg_services_control_service_proto_goTypes = []interface{}{ (GetShardEvacuationStatusResponse_Body_Status)(0), // 0: control.GetShardEvacuationStatusResponse.Body.Status (*HealthCheckRequest)(nil), // 1: control.HealthCheckRequest @@ -3160,124 +4142,164 @@ var file_pkg_services_control_service_proto_goTypes = []interface{}{ (*GetShardEvacuationStatusResponse)(nil), // 22: control.GetShardEvacuationStatusResponse (*StopShardEvacuationRequest)(nil), // 23: control.StopShardEvacuationRequest (*StopShardEvacuationResponse)(nil), // 24: control.StopShardEvacuationResponse - (*HealthCheckRequest_Body)(nil), // 25: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 26: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 27: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 28: control.SetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 29: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 30: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 31: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 32: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 33: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 34: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 35: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 36: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 37: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 38: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 39: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 40: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 41: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 42: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 43: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 44: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 45: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 46: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 47: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 48: control.GetShardEvacuationStatusResponse.Body.Duration - (*StopShardEvacuationRequest_Body)(nil), // 49: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 50: control.StopShardEvacuationResponse.Body - (*Signature)(nil), // 51: control.Signature - (NetmapStatus)(0), // 52: control.NetmapStatus - (HealthStatus)(0), // 53: control.HealthStatus - (*ShardInfo)(nil), // 54: control.ShardInfo - (ShardMode)(0), // 55: control.ShardMode + (*AddChainLocalOverrideRequest)(nil), // 25: control.AddChainLocalOverrideRequest + (*AddChainLocalOverrideResponse)(nil), // 26: control.AddChainLocalOverrideResponse + (*GetChainLocalOverrideRequest)(nil), // 27: control.GetChainLocalOverrideRequest + (*GetChainLocalOverrideResponse)(nil), // 28: control.GetChainLocalOverrideResponse + (*ListChainLocalOverridesRequest)(nil), // 29: control.ListChainLocalOverridesRequest + (*ListChainLocalOverridesResponse)(nil), // 30: control.ListChainLocalOverridesResponse + (*RemoveChainLocalOverrideRequest)(nil), // 31: control.RemoveChainLocalOverrideRequest + (*RemoveChainLocalOverrideResponse)(nil), // 32: control.RemoveChainLocalOverrideResponse + (*HealthCheckRequest_Body)(nil), // 33: control.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 34: control.HealthCheckResponse.Body + (*SetNetmapStatusRequest_Body)(nil), // 35: control.SetNetmapStatusRequest.Body + (*SetNetmapStatusResponse_Body)(nil), // 36: control.SetNetmapStatusResponse.Body + (*DropObjectsRequest_Body)(nil), // 37: control.DropObjectsRequest.Body + (*DropObjectsResponse_Body)(nil), // 38: control.DropObjectsResponse.Body + (*ListShardsRequest_Body)(nil), // 39: control.ListShardsRequest.Body + (*ListShardsResponse_Body)(nil), // 40: control.ListShardsResponse.Body + (*SetShardModeRequest_Body)(nil), // 41: control.SetShardModeRequest.Body + (*SetShardModeResponse_Body)(nil), // 42: control.SetShardModeResponse.Body + (*SynchronizeTreeRequest_Body)(nil), // 43: control.SynchronizeTreeRequest.Body + (*SynchronizeTreeResponse_Body)(nil), // 44: control.SynchronizeTreeResponse.Body + (*EvacuateShardRequest_Body)(nil), // 45: control.EvacuateShardRequest.Body + (*EvacuateShardResponse_Body)(nil), // 46: control.EvacuateShardResponse.Body + (*FlushCacheRequest_Body)(nil), // 47: control.FlushCacheRequest.Body + (*FlushCacheResponse_Body)(nil), // 48: control.FlushCacheResponse.Body + (*DoctorRequest_Body)(nil), // 49: control.DoctorRequest.Body + (*DoctorResponse_Body)(nil), // 50: control.DoctorResponse.Body + (*StartShardEvacuationRequest_Body)(nil), // 51: control.StartShardEvacuationRequest.Body + (*StartShardEvacuationResponse_Body)(nil), // 52: control.StartShardEvacuationResponse.Body + (*GetShardEvacuationStatusRequest_Body)(nil), // 53: control.GetShardEvacuationStatusRequest.Body + (*GetShardEvacuationStatusResponse_Body)(nil), // 54: control.GetShardEvacuationStatusResponse.Body + (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 55: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 56: control.GetShardEvacuationStatusResponse.Body.Duration + (*StopShardEvacuationRequest_Body)(nil), // 57: control.StopShardEvacuationRequest.Body + (*StopShardEvacuationResponse_Body)(nil), // 58: control.StopShardEvacuationResponse.Body + (*AddChainLocalOverrideRequest_Body)(nil), // 59: control.AddChainLocalOverrideRequest.Body + (*AddChainLocalOverrideResponse_Body)(nil), // 60: control.AddChainLocalOverrideResponse.Body + (*GetChainLocalOverrideRequest_Body)(nil), // 61: control.GetChainLocalOverrideRequest.Body + (*GetChainLocalOverrideResponse_Body)(nil), // 62: control.GetChainLocalOverrideResponse.Body + (*ListChainLocalOverridesRequest_Body)(nil), // 63: control.ListChainLocalOverridesRequest.Body + (*ListChainLocalOverridesResponse_Body)(nil), // 64: control.ListChainLocalOverridesResponse.Body + (*RemoveChainLocalOverrideRequest_Body)(nil), // 65: control.RemoveChainLocalOverrideRequest.Body + (*RemoveChainLocalOverrideResponse_Body)(nil), // 66: control.RemoveChainLocalOverrideResponse.Body + (*Signature)(nil), // 67: control.Signature + (NetmapStatus)(0), // 68: control.NetmapStatus + (HealthStatus)(0), // 69: control.HealthStatus + (*ShardInfo)(nil), // 70: control.ShardInfo + (ShardMode)(0), // 71: control.ShardMode } var file_pkg_services_control_service_proto_depIdxs = []int32{ - 25, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 51, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 26, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 51, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 27, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 51, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 28, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 51, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 29, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 51, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature - 30, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 51, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature - 31, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 51, // 13: control.ListShardsRequest.signature:type_name -> control.Signature - 32, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 51, // 15: control.ListShardsResponse.signature:type_name -> control.Signature - 33, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 51, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature - 34, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 51, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature - 35, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 51, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 36, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 51, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 37, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 51, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature - 38, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 51, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature - 39, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 51, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature - 40, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 51, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature - 41, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 51, // 33: control.DoctorRequest.signature:type_name -> control.Signature - 42, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 51, // 35: control.DoctorResponse.signature:type_name -> control.Signature - 43, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 51, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 44, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 51, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 45, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 51, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 46, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 51, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 49, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 51, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 50, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 51, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 52, // 48: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 53, // 49: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 52, // 50: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 54, // 51: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 55, // 52: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 0, // 53: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 48, // 54: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 47, // 55: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 1, // 56: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 3, // 57: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 5, // 58: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 7, // 59: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 9, // 60: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 11, // 61: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 13, // 62: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 19, // 63: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 21, // 64: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 23, // 65: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 15, // 66: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 17, // 67: control.ControlService.Doctor:input_type -> control.DoctorRequest - 2, // 68: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 4, // 69: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 6, // 70: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 8, // 71: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 10, // 72: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 12, // 73: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 14, // 74: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 20, // 75: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 22, // 76: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 24, // 77: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 16, // 78: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 18, // 79: control.ControlService.Doctor:output_type -> control.DoctorResponse - 68, // [68:80] is the sub-list for method output_type - 56, // [56:68] is the sub-list for method input_type - 56, // [56:56] is the sub-list for extension type_name - 56, // [56:56] is the sub-list for extension extendee - 0, // [0:56] is the sub-list for field type_name + 33, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body + 67, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature + 34, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body + 67, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature + 35, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body + 67, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature + 36, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body + 67, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature + 37, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body + 67, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature + 38, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body + 67, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature + 39, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body + 67, // 13: control.ListShardsRequest.signature:type_name -> control.Signature + 40, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body + 67, // 15: control.ListShardsResponse.signature:type_name -> control.Signature + 41, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body + 67, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature + 42, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body + 67, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature + 43, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body + 67, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature + 44, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body + 67, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature + 45, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body + 67, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature + 46, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body + 67, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature + 47, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body + 67, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature + 48, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body + 67, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature + 49, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body + 67, // 33: control.DoctorRequest.signature:type_name -> control.Signature + 50, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body + 67, // 35: control.DoctorResponse.signature:type_name -> control.Signature + 51, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body + 67, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature + 52, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body + 67, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature + 53, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body + 67, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 54, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body + 67, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 57, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body + 67, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature + 58, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body + 67, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature + 59, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body + 67, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature + 60, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body + 67, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature + 61, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body + 67, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature + 62, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body + 67, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature + 63, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body + 67, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature + 64, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body + 67, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature + 65, // 60: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body + 67, // 61: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature + 66, // 62: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body + 67, // 63: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature + 68, // 64: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus + 69, // 65: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus + 68, // 66: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus + 70, // 67: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo + 71, // 68: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode + 0, // 69: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status + 56, // 70: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration + 55, // 71: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + 1, // 72: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 3, // 73: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 5, // 74: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 7, // 75: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 9, // 76: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 11, // 77: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 13, // 78: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 19, // 79: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 21, // 80: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 23, // 81: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 15, // 82: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 17, // 83: control.ControlService.Doctor:input_type -> control.DoctorRequest + 25, // 84: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 27, // 85: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 29, // 86: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 31, // 87: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 2, // 88: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 4, // 89: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 6, // 90: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 8, // 91: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 10, // 92: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 12, // 93: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 14, // 94: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 20, // 95: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 22, // 96: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 24, // 97: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 16, // 98: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 18, // 99: control.ControlService.Doctor:output_type -> control.DoctorResponse + 26, // 100: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 28, // 101: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 30, // 102: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 32, // 103: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 88, // [88:104] is the sub-list for method output_type + 72, // [72:88] is the sub-list for method input_type + 72, // [72:72] is the sub-list for extension type_name + 72, // [72:72] is the sub-list for extension extendee + 0, // [0:72] is the sub-list for field type_name } func init() { file_pkg_services_control_service_proto_init() } @@ -3576,7 +4598,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { + switch v := v.(*AddChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -3588,7 +4610,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { + switch v := v.(*AddChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -3600,7 +4622,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest_Body); i { + switch v := v.(*GetChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -3612,7 +4634,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse_Body); i { + switch v := v.(*GetChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -3624,7 +4646,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest_Body); i { + switch v := v.(*ListChainLocalOverridesRequest); i { case 0: return &v.state case 1: @@ -3636,7 +4658,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse_Body); i { + switch v := v.(*ListChainLocalOverridesResponse); i { case 0: return &v.state case 1: @@ -3648,7 +4670,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest_Body); i { + switch v := v.(*RemoveChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -3660,7 +4682,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse_Body); i { + switch v := v.(*RemoveChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -3672,7 +4694,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest_Body); i { + switch v := v.(*HealthCheckRequest_Body); i { case 0: return &v.state case 1: @@ -3684,7 +4706,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse_Body); i { + switch v := v.(*HealthCheckResponse_Body); i { case 0: return &v.state case 1: @@ -3696,7 +4718,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest_Body); i { + switch v := v.(*SetNetmapStatusRequest_Body); i { case 0: return &v.state case 1: @@ -3708,7 +4730,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse_Body); i { + switch v := v.(*SetNetmapStatusResponse_Body); i { case 0: return &v.state case 1: @@ -3720,7 +4742,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest_Body); i { + switch v := v.(*DropObjectsRequest_Body); i { case 0: return &v.state case 1: @@ -3732,7 +4754,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse_Body); i { + switch v := v.(*DropObjectsResponse_Body); i { case 0: return &v.state case 1: @@ -3744,7 +4766,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest_Body); i { + switch v := v.(*ListShardsRequest_Body); i { case 0: return &v.state case 1: @@ -3756,7 +4778,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse_Body); i { + switch v := v.(*ListShardsResponse_Body); i { case 0: return &v.state case 1: @@ -3768,7 +4790,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest_Body); i { + switch v := v.(*SetShardModeRequest_Body); i { case 0: return &v.state case 1: @@ -3780,7 +4802,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse_Body); i { + switch v := v.(*SetShardModeResponse_Body); i { case 0: return &v.state case 1: @@ -3792,7 +4814,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest_Body); i { + switch v := v.(*SynchronizeTreeRequest_Body); i { case 0: return &v.state case 1: @@ -3804,7 +4826,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse_Body); i { + switch v := v.(*SynchronizeTreeResponse_Body); i { case 0: return &v.state case 1: @@ -3816,7 +4838,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest_Body); i { + switch v := v.(*EvacuateShardRequest_Body); i { case 0: return &v.state case 1: @@ -3828,7 +4850,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body); i { + switch v := v.(*EvacuateShardResponse_Body); i { case 0: return &v.state case 1: @@ -3840,7 +4862,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { + switch v := v.(*FlushCacheRequest_Body); i { case 0: return &v.state case 1: @@ -3852,7 +4874,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { + switch v := v.(*FlushCacheResponse_Body); i { case 0: return &v.state case 1: @@ -3864,7 +4886,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest_Body); i { + switch v := v.(*DoctorRequest_Body); i { case 0: return &v.state case 1: @@ -3876,6 +4898,102 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DoctorResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StartShardEvacuationRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StartShardEvacuationResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetShardEvacuationStatusRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetShardEvacuationStatusResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StopShardEvacuationRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StopShardEvacuationResponse_Body); i { case 0: return &v.state @@ -3887,6 +5005,102 @@ func file_pkg_services_control_service_proto_init() { return nil } } + file_pkg_services_control_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddChainLocalOverrideRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddChainLocalOverrideResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetChainLocalOverrideRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetChainLocalOverrideResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListChainLocalOverridesRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListChainLocalOverridesResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -3894,7 +5108,7 @@ func file_pkg_services_control_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_service_proto_rawDesc, NumEnums: 1, - NumMessages: 50, + NumMessages: 66, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index cbcf74e536..e7d218f20d 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -44,6 +44,18 @@ service ControlService { // Doctor performs storage restructuring operations on engine. rpc Doctor (DoctorRequest) returns (DoctorResponse); + + // Add local access policy engine overrides to a node. + rpc AddChainLocalOverride (AddChainLocalOverrideRequest) returns (AddChainLocalOverrideResponse); + + // Get local access policy engine overrides stored in the node by chain id. + rpc GetChainLocalOverride (GetChainLocalOverrideRequest) returns (GetChainLocalOverrideResponse); + + // List local access policy engine overrides stored in the node by container id. + rpc ListChainLocalOverrides (ListChainLocalOverridesRequest) returns (ListChainLocalOverridesResponse); + + // Remove local access policy engine overrides stored in the node by chaind id. + rpc RemoveChainLocalOverride (RemoveChainLocalOverrideRequest) returns (RemoveChainLocalOverrideResponse); } // Health check request. @@ -405,3 +417,105 @@ message StopShardEvacuationResponse { Body body = 1; Signature signature = 2; } + +// AddChainLocalOverride request. +message AddChainLocalOverrideRequest { + message Body { + // Container id for which the overrides are applied. + bytes container_id = 1; + + // Serialized rule chain. + bytes chain = 2; + } + + Body body = 1; + + Signature signature = 2; +} + +// AddChainLocalOverride response. +message AddChainLocalOverrideResponse { + message Body { + // Chain ID assigned for the added rule chain. + string chain_id = 1; + } + + Body body = 1; + + Signature signature = 2; +} + +// GetChainLocalOverride request. +message GetChainLocalOverrideRequest { + message Body { + // Container id for which the overrides are defined. + bytes container_id = 1; + + // Chain ID assigned for the added rule chain. + string chain_id = 2; + } + + Body body = 1; + + Signature signature = 2; +} + +// GetChainLocalOverride response. +message GetChainLocalOverrideResponse { + message Body { + // Serialized rule chain. + bytes chain = 1; + } + + Body body = 1; + + Signature signature = 2; +} + +// ListChainLocalOverrides request. +message ListChainLocalOverridesRequest { + message Body { + // Container id for which the overrides are defined. + bytes container_id = 1; + } + + Body body = 1; + + Signature signature = 2; +} + +// ListChainLocalOverrides response. +message ListChainLocalOverridesResponse { + message Body { + // The list of serialized rule chain. + repeated bytes chains = 1; + } + + Body body = 1; + + Signature signature = 2; +} + +message RemoveChainLocalOverrideRequest { + message Body { + // Container id for which the overrides are defined. + bytes container_id = 1; + + // Chain ID assigned for the added rule chain. + string chain_id = 2; + } + + Body body = 1; + + Signature signature = 2; +} + +message RemoveChainLocalOverrideResponse { + message Body { + bool removed = 1; + } + + Body body = 1; + + Signature signature = 2; +} diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 56ff81acea..852788a307 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2059,3 +2059,697 @@ func (x *StopShardEvacuationResponse) ReadSignedData(buf []byte) ([]byte, error) func (x *StopShardEvacuationResponse) SetSignature(sig *Signature) { x.Signature = sig } + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *AddChainLocalOverrideRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BytesSize(1, x.ContainerId) + size += proto.BytesSize(2, x.Chain) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *AddChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + offset += proto.BytesMarshal(2, buf[offset:], x.Chain) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *AddChainLocalOverrideRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *AddChainLocalOverrideRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *AddChainLocalOverrideRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *AddChainLocalOverrideRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *AddChainLocalOverrideRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *AddChainLocalOverrideResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.StringSize(1, x.ChainId) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *AddChainLocalOverrideResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.StringMarshal(1, buf[offset:], x.ChainId) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *AddChainLocalOverrideResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *AddChainLocalOverrideResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *AddChainLocalOverrideResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *AddChainLocalOverrideResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *AddChainLocalOverrideResponse) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *GetChainLocalOverrideRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BytesSize(1, x.ContainerId) + size += proto.StringSize(2, x.ChainId) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *GetChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + offset += proto.StringMarshal(2, buf[offset:], x.ChainId) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *GetChainLocalOverrideRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *GetChainLocalOverrideRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *GetChainLocalOverrideRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *GetChainLocalOverrideRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *GetChainLocalOverrideRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *GetChainLocalOverrideResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BytesSize(1, x.Chain) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *GetChainLocalOverrideResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.BytesMarshal(1, buf[offset:], x.Chain) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *GetChainLocalOverrideResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *GetChainLocalOverrideResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *GetChainLocalOverrideResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *GetChainLocalOverrideResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *GetChainLocalOverrideResponse) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListChainLocalOverridesRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BytesSize(1, x.ContainerId) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ListChainLocalOverridesRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListChainLocalOverridesRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ListChainLocalOverridesRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ListChainLocalOverridesRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ListChainLocalOverridesRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *ListChainLocalOverridesRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListChainLocalOverridesResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.RepeatedBytesSize(1, x.Chains) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ListChainLocalOverridesResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Chains) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListChainLocalOverridesResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ListChainLocalOverridesResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ListChainLocalOverridesResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ListChainLocalOverridesResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *ListChainLocalOverridesResponse) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveChainLocalOverrideRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BytesSize(1, x.ContainerId) + size += proto.StringSize(2, x.ChainId) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + offset += proto.StringMarshal(2, buf[offset:], x.ChainId) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveChainLocalOverrideRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveChainLocalOverrideRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *RemoveChainLocalOverrideRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *RemoveChainLocalOverrideRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *RemoveChainLocalOverrideRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveChainLocalOverrideResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BoolSize(1, x.Removed) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveChainLocalOverrideResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.BoolMarshal(1, buf[offset:], x.Removed) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveChainLocalOverrideResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveChainLocalOverrideResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *RemoveChainLocalOverrideResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *RemoveChainLocalOverrideResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *RemoveChainLocalOverrideResponse) SetSignature(sig *Signature) { + x.Signature = sig +} diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index 967c739f55..b5881ccb2a 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -31,6 +31,10 @@ const ( ControlService_StopShardEvacuation_FullMethodName = "/control.ControlService/StopShardEvacuation" ControlService_FlushCache_FullMethodName = "/control.ControlService/FlushCache" ControlService_Doctor_FullMethodName = "/control.ControlService/Doctor" + ControlService_AddChainLocalOverride_FullMethodName = "/control.ControlService/AddChainLocalOverride" + ControlService_GetChainLocalOverride_FullMethodName = "/control.ControlService/GetChainLocalOverride" + ControlService_ListChainLocalOverrides_FullMethodName = "/control.ControlService/ListChainLocalOverrides" + ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" ) // ControlServiceClient is the client API for ControlService service. @@ -62,6 +66,14 @@ type ControlServiceClient interface { FlushCache(ctx context.Context, in *FlushCacheRequest, opts ...grpc.CallOption) (*FlushCacheResponse, error) // Doctor performs storage restructuring operations on engine. Doctor(ctx context.Context, in *DoctorRequest, opts ...grpc.CallOption) (*DoctorResponse, error) + // Add local access policy engine overrides to a node. + AddChainLocalOverride(ctx context.Context, in *AddChainLocalOverrideRequest, opts ...grpc.CallOption) (*AddChainLocalOverrideResponse, error) + // Get local access policy engine overrides stored in the node by chain id. + GetChainLocalOverride(ctx context.Context, in *GetChainLocalOverrideRequest, opts ...grpc.CallOption) (*GetChainLocalOverrideResponse, error) + // List local access policy engine overrides stored in the node by container id. + ListChainLocalOverrides(ctx context.Context, in *ListChainLocalOverridesRequest, opts ...grpc.CallOption) (*ListChainLocalOverridesResponse, error) + // Remove local access policy engine overrides stored in the node by chaind id. + RemoveChainLocalOverride(ctx context.Context, in *RemoveChainLocalOverrideRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverrideResponse, error) } type controlServiceClient struct { @@ -180,6 +192,42 @@ func (c *controlServiceClient) Doctor(ctx context.Context, in *DoctorRequest, op return out, nil } +func (c *controlServiceClient) AddChainLocalOverride(ctx context.Context, in *AddChainLocalOverrideRequest, opts ...grpc.CallOption) (*AddChainLocalOverrideResponse, error) { + out := new(AddChainLocalOverrideResponse) + err := c.cc.Invoke(ctx, ControlService_AddChainLocalOverride_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlServiceClient) GetChainLocalOverride(ctx context.Context, in *GetChainLocalOverrideRequest, opts ...grpc.CallOption) (*GetChainLocalOverrideResponse, error) { + out := new(GetChainLocalOverrideResponse) + err := c.cc.Invoke(ctx, ControlService_GetChainLocalOverride_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlServiceClient) ListChainLocalOverrides(ctx context.Context, in *ListChainLocalOverridesRequest, opts ...grpc.CallOption) (*ListChainLocalOverridesResponse, error) { + out := new(ListChainLocalOverridesResponse) + err := c.cc.Invoke(ctx, ControlService_ListChainLocalOverrides_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *controlServiceClient) RemoveChainLocalOverride(ctx context.Context, in *RemoveChainLocalOverrideRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverrideResponse, error) { + out := new(RemoveChainLocalOverrideResponse) + err := c.cc.Invoke(ctx, ControlService_RemoveChainLocalOverride_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ControlServiceServer is the server API for ControlService service. // All implementations should embed UnimplementedControlServiceServer // for forward compatibility @@ -209,6 +257,14 @@ type ControlServiceServer interface { FlushCache(context.Context, *FlushCacheRequest) (*FlushCacheResponse, error) // Doctor performs storage restructuring operations on engine. Doctor(context.Context, *DoctorRequest) (*DoctorResponse, error) + // Add local access policy engine overrides to a node. + AddChainLocalOverride(context.Context, *AddChainLocalOverrideRequest) (*AddChainLocalOverrideResponse, error) + // Get local access policy engine overrides stored in the node by chain id. + GetChainLocalOverride(context.Context, *GetChainLocalOverrideRequest) (*GetChainLocalOverrideResponse, error) + // List local access policy engine overrides stored in the node by container id. + ListChainLocalOverrides(context.Context, *ListChainLocalOverridesRequest) (*ListChainLocalOverridesResponse, error) + // Remove local access policy engine overrides stored in the node by chaind id. + RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) } // UnimplementedControlServiceServer should be embedded to have forward compatible implementations. @@ -251,6 +307,18 @@ func (UnimplementedControlServiceServer) FlushCache(context.Context, *FlushCache func (UnimplementedControlServiceServer) Doctor(context.Context, *DoctorRequest) (*DoctorResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Doctor not implemented") } +func (UnimplementedControlServiceServer) AddChainLocalOverride(context.Context, *AddChainLocalOverrideRequest) (*AddChainLocalOverrideResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddChainLocalOverride not implemented") +} +func (UnimplementedControlServiceServer) GetChainLocalOverride(context.Context, *GetChainLocalOverrideRequest) (*GetChainLocalOverrideResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetChainLocalOverride not implemented") +} +func (UnimplementedControlServiceServer) ListChainLocalOverrides(context.Context, *ListChainLocalOverridesRequest) (*ListChainLocalOverridesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListChainLocalOverrides not implemented") +} +func (UnimplementedControlServiceServer) RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveChainLocalOverride not implemented") +} // UnsafeControlServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ControlServiceServer will @@ -479,6 +547,78 @@ func _ControlService_Doctor_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _ControlService_AddChainLocalOverride_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddChainLocalOverrideRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).AddChainLocalOverride(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_AddChainLocalOverride_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).AddChainLocalOverride(ctx, req.(*AddChainLocalOverrideRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ControlService_GetChainLocalOverride_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetChainLocalOverrideRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).GetChainLocalOverride(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_GetChainLocalOverride_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).GetChainLocalOverride(ctx, req.(*GetChainLocalOverrideRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ControlService_ListChainLocalOverrides_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListChainLocalOverridesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).ListChainLocalOverrides(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_ListChainLocalOverrides_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).ListChainLocalOverrides(ctx, req.(*ListChainLocalOverridesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _ControlService_RemoveChainLocalOverride_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveChainLocalOverrideRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).RemoveChainLocalOverride(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_RemoveChainLocalOverride_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).RemoveChainLocalOverride(ctx, req.(*RemoveChainLocalOverrideRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ControlService_ServiceDesc is the grpc.ServiceDesc for ControlService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -534,6 +674,22 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "Doctor", Handler: _ControlService_Doctor_Handler, }, + { + MethodName: "AddChainLocalOverride", + Handler: _ControlService_AddChainLocalOverride_Handler, + }, + { + MethodName: "GetChainLocalOverride", + Handler: _ControlService_GetChainLocalOverride_Handler, + }, + { + MethodName: "ListChainLocalOverrides", + Handler: _ControlService_ListChainLocalOverrides_Handler, + }, + { + MethodName: "RemoveChainLocalOverride", + Handler: _ControlService_RemoveChainLocalOverride_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pkg/services/control/service.proto", From 5ec73fe8a0b6c3c2ab31b093a43c6fdfa7423773 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 30 Oct 2023 16:48:02 +0300 Subject: [PATCH 0125/1413] [#770] node: Introduce ape chain source * Provide methods to access rule chains with access policy engine (APE) chain source * Initialize apeChainSource within object service initialization * Share apeChainSource with control service * Implement dummy apeChainSource instance based on in-memory implementation Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 5 +++++ cmd/frostfs-node/control.go | 1 + cmd/frostfs-node/object.go | 2 ++ cmd/frostfs-node/policy_engine.go | 28 +++++++++++++++++++++++++++ go.mod | 1 + go.sum | 2 ++ pkg/core/container/storage.go | 8 ++++++++ pkg/services/control/server/server.go | 10 ++++++++++ 8 files changed, 57 insertions(+) create mode 100644 cmd/frostfs-node/policy_engine.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e3e56e5deb..a41b73d92f 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -510,6 +510,11 @@ type cfgObject struct { eaclSource container.EACLSource + // Access policy chain source is used by object service to + // check for operation permissions but this source is also shared with + // control service that dispatches local overrides. + apeChainSource container.AccessPolicyEngineChainSource + pool cfgObjectRoutines cfgLocalStorage cfgLocalStorage diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index 98d893c388..30d6448036 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -51,6 +51,7 @@ func initControlService(c *cfg) { controlSvc.WithTreeService(treeSynchronizer{ c.treeService, }), + controlSvc.WithAPEChainSource(c.cfgObject.apeChainSource), ) lis, err := net.Listen("tcp", endpoint) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 2f714b8211..bbaec01ed9 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -157,6 +157,8 @@ func initObjectService(c *cfg) { c.replicator = createReplicator(c, keyStorage, c.bgClientCache) + c.cfgObject.apeChainSource = NewAPESource() + addPolicer(c, keyStorage, c.bgClientCache) traverseGen := util.NewTraverserGenerator(c.netMapSource, c.cfgObject.cnrSource, c) diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go new file mode 100644 index 0000000000..039124a6b4 --- /dev/null +++ b/cmd/frostfs-node/policy_engine.go @@ -0,0 +1,28 @@ +package main + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" +) + +type apeChainSourceImpl struct { + localChainStorage map[cid.ID]policyengine.CachedChainStorage +} + +func NewAPESource() container.AccessPolicyEngineChainSource { + return &apeChainSourceImpl{ + localChainStorage: make(map[cid.ID]policyengine.CachedChainStorage), + } +} + +var _ container.AccessPolicyEngineChainSource = (*apeChainSourceImpl)(nil) + +func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (policyengine.CachedChainStorage, error) { + s, ok := c.localChainStorage[cid] + if ok { + return s, nil + } + c.localChainStorage[cid] = policyengine.NewInMemory() + return c.localChainStorage[cid], nil +} diff --git a/go.mod b/go.mod index 37cb477bfc..4f6505e878 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/hrw v1.2.1 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231101082425-5eee1a733432 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index 62fd85c863..05a870b807 100644 --- a/go.sum +++ b/go.sum @@ -736,6 +736,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231101082425-5eee1a733432 h1:z0PqdiEIHXK2qC83e6pmxUZ5peP9CIL0Bh5mP/d+4Xc= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231101082425-5eee1a733432/go.mod h1:qf3B9hSz6gCMfcfvqkhTu5ak+Gx2R+wo4Hc87LnKxPg= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index 0766ced31d..f48fc73ac4 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -6,6 +6,7 @@ import ( frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" ) // Container groups information about the FrostFS container stored in the FrostFS network. @@ -70,3 +71,10 @@ type EACLSource interface { // eACL table is not in source. GetEACL(cid.ID) (*EACL, error) } + +// AccessPolicyEngineChainSource interface provides methods to access and manipulate +// policy engine chain storage. +type AccessPolicyEngineChainSource interface { + // TODO (aarifullin): Better to use simpler interface instead CachedChainStorage. + GetChainSource(cid cid.ID) (policyengine.CachedChainStorage, error) +} diff --git a/pkg/services/control/server/server.go b/pkg/services/control/server/server.go index a0ad44e234..ae024a82db 100644 --- a/pkg/services/control/server/server.go +++ b/pkg/services/control/server/server.go @@ -59,6 +59,8 @@ type cfg struct { cnrSrc container.Source + apeChainSrc container.AccessPolicyEngineChainSource + replicator *replicator.Replicator nodeState NodeState @@ -151,3 +153,11 @@ func WithTreeService(s TreeService) Option { c.treeService = s } } + +// WithAPEChainSource returns the option to set access policy engine +// chain source. +func WithAPEChainSource(apeChainSrc container.AccessPolicyEngineChainSource) Option { + return func(c *cfg) { + c.apeChainSrc = apeChainSrc + } +} From 8e11ef46b89e1b305b4a555d1ec445f97f37151a Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 30 Oct 2023 18:30:23 +0300 Subject: [PATCH 0126/1413] [#770] object: Introduce ape chain checker for object svc * Introduce Request type converted from RequestInfo type to implement policy-engine's Request interface * Implement basic ape checker to check if a request is permitted to be performed * Make put handlers use APE checker instead EACL Signed-off-by: Airat Arifullin --- cmd/frostfs-node/object.go | 1 + cmd/frostfs-node/policy_engine.go | 6 ++ pkg/services/object/acl/ape.go | 56 +++++++++++++ pkg/services/object/acl/ape_request.go | 105 +++++++++++++++++++++++++ pkg/services/object/acl/v2/service.go | 18 +++-- pkg/services/object/acl/v2/types.go | 6 ++ 6 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 pkg/services/object/acl/ape.go create mode 100644 pkg/services/object/acl/ape_request.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index bbaec01ed9..79f492190f 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -426,6 +426,7 @@ func createACLServiceV2(c *cfg, splitSvc *objectService.TransportSplitter, irFet c.cfgObject.eaclSource, eaclSDK.NewValidator(), ls), + acl.NewAPEChecker(c.log, c.cfgObject.apeChainSource), c.cfgObject.cnrSource, v2.WithLogger(c.log), ) diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index 039124a6b4..f0bd78629c 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -1,12 +1,15 @@ package main import ( + "sync" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" policyengine "git.frostfs.info/TrueCloudLab/policy-engine" ) type apeChainSourceImpl struct { + mtx sync.Mutex localChainStorage map[cid.ID]policyengine.CachedChainStorage } @@ -19,6 +22,9 @@ func NewAPESource() container.AccessPolicyEngineChainSource { var _ container.AccessPolicyEngineChainSource = (*apeChainSourceImpl)(nil) func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (policyengine.CachedChainStorage, error) { + c.mtx.Lock() + defer c.mtx.Unlock() + s, ok := c.localChainStorage[cid] if ok { return s, nil diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go new file mode 100644 index 0000000000..b064b1eec0 --- /dev/null +++ b/pkg/services/object/acl/ape.go @@ -0,0 +1,56 @@ +package acl + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" +) + +var ( + errAPEChainNoSource = errors.New("could not get ape chain source for the container") +) + +type apeCheckerImpl struct { + log *logger.Logger + apeSrc container.AccessPolicyEngineChainSource +} + +func NewAPEChecker(log *logger.Logger, apeSrc container.AccessPolicyEngineChainSource) v2.APEChainChecker { + return &apeCheckerImpl{ + log: log, + apeSrc: apeSrc, + } +} + +func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { + cnr := reqInfo.ContainerID() + + chainCache, err := c.apeSrc.GetChainSource(cnr) + if err != nil { + return errAPEChainNoSource + } + + request := new(Request) + request.FromRequestInfo(reqInfo) + + status, ruleFound := chainCache.IsAllowed(policyengine.Ingress, "", request) + + if !ruleFound || status == policyengine.Allow { + return nil + } + + return apeErr(reqInfo, status) +} + +const accessDeniedAPEReasonFmt = "access to operation %s is denied by access policy engine: %s" + +func apeErr(req v2.RequestInfo, status policyengine.Status) error { + errAccessDenied := &apistatus.ObjectAccessDenied{} + errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedAPEReasonFmt, req.Operation(), status.String())) + return errAccessDenied +} diff --git a/pkg/services/object/acl/ape_request.go b/pkg/services/object/acl/ape_request.go new file mode 100644 index 0000000000..3e8bb173df --- /dev/null +++ b/pkg/services/object/acl/ape_request.go @@ -0,0 +1,105 @@ +package acl + +import ( + "fmt" + + v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" + aclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" +) + +type Request struct { + operation string + resource *resource + properties map[string]string +} + +var _ policyengine.Request = (*Request)(nil) + +type resource struct { + name string + properties map[string]string +} + +var _ policyengine.Resource = (*resource)(nil) + +func (r *resource) Name() string { + return r.name +} + +func (r *resource) Property(key string) string { + return r.properties[key] +} + +// TODO (aarifullin): these stringified verbs, properties and namespaces +// should be non-implementation-specific. +func getResource(reqInfo v2.RequestInfo) *resource { + cid := reqInfo.ContainerID() + oid := "*" + if reqOID := reqInfo.ObjectID(); reqOID != nil { + oid = reqOID.EncodeToString() + } + name := fmt.Sprintf("native:::object/%s/%s", + cid, + oid) + + return &resource{ + name: name, + properties: make(map[string]string), + } +} + +func getProperties(_ v2.RequestInfo) map[string]string { + return map[string]string{ + "Actor": "", + } +} + +// TODO (aarifullin): these stringified verbs, properties and namespaces +// should be non-implementation-specific. +func getOperation(reqInfo v2.RequestInfo) string { + var verb string + switch op := reqInfo.Operation(); op { + case aclSDK.OpObjectGet: + verb = "GetObject" + case aclSDK.OpObjectHead: + verb = "HeadObject" + case aclSDK.OpObjectPut: + verb = "PutObject" + case aclSDK.OpObjectDelete: + verb = "DeleteObject" + case aclSDK.OpObjectSearch: + verb = "SearchObject" + case aclSDK.OpObjectRange: + verb = "RangeObject" + case aclSDK.OpObjectHash: + verb = "HashObject" + } + + return "native:" + verb +} + +func NewRequest() *Request { + return &Request{ + resource: new(resource), + properties: map[string]string{}, + } +} + +func (r *Request) FromRequestInfo(ri v2.RequestInfo) { + r.operation = getOperation(ri) + r.resource = getResource(ri) + r.properties = getProperties(ri) +} + +func (r *Request) Operation() string { + return r.operation +} + +func (r *Request) Property(key string) string { + return r.properties[key] +} + +func (r *Request) Resource() policyengine.Resource { + return r.resource +} diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index b5bd3d4f43..ba9d1dfa53 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -67,6 +67,10 @@ type cfg struct { checker ACLChecker + // TODO(aarifullin): apeCheck is temporarily the part of + // acl service and must be standalone. + apeChecker APEChainChecker + irFetcher InnerRingFetcher nm netmap.Source @@ -79,6 +83,7 @@ func New(next object.ServiceServer, nm netmap.Source, irf InnerRingFetcher, acl ACLChecker, + apeChecker APEChainChecker, cs container.Source, opts ...Option, ) Service { @@ -88,6 +93,7 @@ func New(next object.ServiceServer, nm: nm, irFetcher: irf, checker: acl, + apeChecker: apeChecker, containers: cs, } @@ -212,10 +218,8 @@ func (b Service) Head( reqInfo.obj = obj - if !b.checker.CheckBasicACL(reqInfo) { - return nil, basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) + if err := b.apeChecker.CheckIfRequestPermitted(reqInfo); err != nil { + return nil, err } resp, err := b.next.Head(ctx, request) @@ -560,10 +564,8 @@ func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRe reqInfo.obj = obj - if !p.source.checker.CheckBasicACL(reqInfo) || !p.source.checker.StickyBitCheck(reqInfo, idOwner) { - return basicACLErr(reqInfo) - } else if err := p.source.checker.CheckEACL(request, reqInfo); err != nil { - return eACLErr(reqInfo, err) + if err := p.source.apeChecker.CheckIfRequestPermitted(reqInfo); err != nil { + return err } } diff --git a/pkg/services/object/acl/v2/types.go b/pkg/services/object/acl/v2/types.go index 061cd26b62..a113c46939 100644 --- a/pkg/services/object/acl/v2/types.go +++ b/pkg/services/object/acl/v2/types.go @@ -26,3 +26,9 @@ type InnerRingFetcher interface { // the actual inner ring. InnerRingKeys() ([][]byte, error) } + +// APEChainChecker is the interface that provides methods to +// check if the access policy engine permits to perform the request. +type APEChainChecker interface { + CheckIfRequestPermitted(RequestInfo) error +} From 66848d32888fda0eb6a37ef2b7c02dd9f54db124 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 31 Oct 2023 11:55:42 +0300 Subject: [PATCH 0127/1413] [#770] cli: Add methods to work with APE rules via control svc * Add methods to frostfs-cli * Implement rpc in control service Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 90 +++++++++ cmd/frostfs-cli/modules/control/get_rule.go | 69 +++++++ cmd/frostfs-cli/modules/control/list_rules.go | 72 +++++++ .../modules/control/remove_rule.go | 72 +++++++ cmd/frostfs-cli/modules/control/root.go | 8 + cmd/frostfs-cli/modules/util/ape.go | 179 ++++++++++++++++++ cmd/frostfs-cli/modules/util/ape_test.go | 129 +++++++++++++ pkg/services/control/rpc.go | 56 ++++++ pkg/services/control/server/policy_engine.go | 140 +++++++++++++- pkg/services/control/server/server.go | 6 + pkg/services/object/acl/v2/service.go | 4 - 11 files changed, 813 insertions(+), 12 deletions(-) create mode 100644 cmd/frostfs-cli/modules/control/add_rule.go create mode 100644 cmd/frostfs-cli/modules/control/get_rule.go create mode 100644 cmd/frostfs-cli/modules/control/list_rules.go create mode 100644 cmd/frostfs-cli/modules/control/remove_rule.go create mode 100644 cmd/frostfs-cli/modules/util/ape.go create mode 100644 cmd/frostfs-cli/modules/util/ape_test.go diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go new file mode 100644 index 0000000000..0c67321084 --- /dev/null +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -0,0 +1,90 @@ +package control + +import ( + "bytes" + "crypto/sha256" + "encoding/json" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + ape "git.frostfs.info/TrueCloudLab/policy-engine" + "github.com/spf13/cobra" +) + +const ( + ruleFlag = "rule" +) + +var addRuleCmd = &cobra.Command{ + Use: "add-rule", + Short: "Add local override", + Long: "Add local APE rule to a node with following format:\n[:action_detail] [ ...] ", + Example: `allow Object.Get * +deny Object.Get EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr/* +deny:QuotaLimitReached Object.Put Object.Resource:Department=HR * +`, + Run: addRule, +} + +func prettyJSONFormat(cmd *cobra.Command, serializedChain []byte) string { + wr := bytes.NewBufferString("") + err := json.Indent(wr, serializedChain, "", " ") + commonCmd.ExitOnErr(cmd, "%w", err) + return wr.String() +} + +func addRule(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + var cnr cid.ID + cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) + commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) + + rawCID := make([]byte, sha256.Size) + cnr.Encode(rawCID) + + rule, _ := cmd.Flags().GetString(ruleFlag) + + chain := new(ape.Chain) + commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, []string{rule})) + serializedChain := chain.Bytes() + + cmd.Println("Container ID: " + cidStr) + cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, serializedChain)) + + req := &control.AddChainLocalOverrideRequest{ + Body: &control.AddChainLocalOverrideRequest_Body{ + ContainerId: rawCID, + Chain: serializedChain, + }, + } + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.AddChainLocalOverrideResponse + var err error + err = cli.ExecRaw(func(client *client.Client) error { + resp, err = control.AddChainLocalOverride(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + cmd.Println("Rule has been added. Chain id: ", resp.GetBody().GetChainId()) +} + +func initControlAddRuleCmd() { + initControlFlags(addRuleCmd) + + ff := addRuleCmd.Flags() + ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + ff.String(ruleFlag, "", "Rule statement") +} diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go new file mode 100644 index 0000000000..df2bf94fed --- /dev/null +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -0,0 +1,69 @@ +package control + +import ( + "crypto/sha256" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + "github.com/spf13/cobra" +) + +var getRuleCmd = &cobra.Command{ + Use: "get-rule", + Short: "Get local override", + Long: "Get local APE override of the node", + Run: getRule, +} + +func getRule(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + var cnr cid.ID + cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) + commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) + + rawCID := make([]byte, sha256.Size) + cnr.Encode(rawCID) + + chainID, _ := cmd.Flags().GetString(chainIDFlag) + + req := &control.GetChainLocalOverrideRequest{ + Body: &control.GetChainLocalOverrideRequest_Body{ + ContainerId: rawCID, + ChainId: chainID, + }, + } + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.GetChainLocalOverrideResponse + var err error + err = cli.ExecRaw(func(client *client.Client) error { + resp, err = control.GetChainLocalOverride(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + var chain policyengine.Chain + commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain())) + + // TODO (aarifullin): make pretty-formatted output for chains. + cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, chain.Bytes())) +} + +func initControGetRuleCmd() { + initControlFlags(getRuleCmd) + + ff := getRuleCmd.Flags() + ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + ff.String(chainIDFlag, "", "Chain id") +} diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go new file mode 100644 index 0000000000..b3d7a5b9c0 --- /dev/null +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -0,0 +1,72 @@ +package control + +import ( + "crypto/sha256" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + "github.com/spf13/cobra" +) + +var listRulesCmd = &cobra.Command{ + Use: "list-rules", + Short: "List local overrides", + Long: "List local APE overrides of the node", + Run: listRules, +} + +func listRules(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + var cnr cid.ID + cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) + commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) + + rawCID := make([]byte, sha256.Size) + cnr.Encode(rawCID) + + req := &control.ListChainLocalOverridesRequest{ + Body: &control.ListChainLocalOverridesRequest_Body{ + ContainerId: rawCID, + }, + } + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.ListChainLocalOverridesResponse + var err error + err = cli.ExecRaw(func(client *client.Client) error { + resp, err = control.ListChainLocalOverrides(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + chains := resp.GetBody().GetChains() + if len(chains) == 0 { + cmd.Println("Local overrides are not defined for the container.") + return + } + + for _, c := range chains { + // TODO (aarifullin): make pretty-formatted output for chains. + var chain policyengine.Chain + commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c)) + cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, chain.Bytes())) + } +} + +func initControlListRulesCmd() { + initControlFlags(listRulesCmd) + + ff := listRulesCmd.Flags() + ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) +} diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go new file mode 100644 index 0000000000..de064536ba --- /dev/null +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -0,0 +1,72 @@ +package control + +import ( + "crypto/sha256" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "github.com/spf13/cobra" +) + +const ( + chainIDFlag = "chain-id" +) + +var removeRuleCmd = &cobra.Command{ + Use: "remove-rule", + Short: "Remove local override", + Long: "Remove local APE override of the node", + Run: removeRule, +} + +func removeRule(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + var cnr cid.ID + cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) + commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) + + rawCID := make([]byte, sha256.Size) + cnr.Encode(rawCID) + + chainID, _ := cmd.Flags().GetString(chainIDFlag) + + req := &control.RemoveChainLocalOverrideRequest{ + Body: &control.RemoveChainLocalOverrideRequest_Body{ + ContainerId: rawCID, + ChainId: chainID, + }, + } + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.RemoveChainLocalOverrideResponse + var err error + err = cli.ExecRaw(func(client *client.Client) error { + resp, err = control.RemoveChainLocalOverride(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + if resp.GetBody().Removed { + cmd.Println("Rule has been removed.") + } else { + cmd.Println("Rule has not been removed.") + } +} + +func initControlRemoveRuleCmd() { + initControlFlags(removeRuleCmd) + + ff := removeRuleCmd.Flags() + ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + ff.String(chainIDFlag, "", "Chain id") +} diff --git a/cmd/frostfs-cli/modules/control/root.go b/cmd/frostfs-cli/modules/control/root.go index 015676185d..f7c846eba7 100644 --- a/cmd/frostfs-cli/modules/control/root.go +++ b/cmd/frostfs-cli/modules/control/root.go @@ -34,6 +34,10 @@ func init() { shardsCmd, synchronizeTreeCmd, irCmd, + addRuleCmd, + removeRuleCmd, + listRulesCmd, + getRuleCmd, ) initControlHealthCheckCmd() @@ -42,4 +46,8 @@ func init() { initControlShardsCmd() initControlSynchronizeTreeCmd() initControlIRCmd() + initControlAddRuleCmd() + initControlRemoveRuleCmd() + initControlListRulesCmd() + initControGetRuleCmd() } diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go new file mode 100644 index 0000000000..8815464506 --- /dev/null +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -0,0 +1,179 @@ +package util + +import ( + "errors" + "fmt" + "strings" + + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + "github.com/flynn-archive/go-shlex" +) + +var ( + errInvalidStatementFormat = errors.New("invalid statement format") + errInvalidConditionFormat = errors.New("invalid condition format") + errUnknownAction = errors.New("action is not recognized") + errUnknownOperation = errors.New("operation is not recognized") + errUnknownActionDetail = errors.New("action detail is not recognized") + errUnknownBinaryOperator = errors.New("binary operator is not recognized") + errUnknownCondObjectType = errors.New("condition object type is not recognized") +) + +// ParseAPEChain parses APE chain rules. +func ParseAPEChain(chain *policyengine.Chain, rules []string) error { + if len(rules) == 0 { + return errors.New("no APE rules provided") + } + + for _, rule := range rules { + r := new(policyengine.Rule) + if err := ParseAPERule(r, rule); err != nil { + return err + } + chain.Rules = append(chain.Rules, *r) + } + + return nil +} + +// ParseAPERule parses access-policy-engine statement from the following form: +// [:action_detail] [ ...] +// +// Examples: +// deny Object.Put * +// deny:QuotaLimitReached Object.Put * +// allow Object.Put * +// allow Object.Get Object.Resource:Department=HR Object.Request:Actor=ownerA * +// +//nolint:godot +func ParseAPERule(r *policyengine.Rule, rule string) error { + lexemes, err := shlex.Split(rule) + if err != nil { + return fmt.Errorf("can't parse rule '%s': %v", rule, err) + } + return parseRuleLexemes(r, lexemes) +} + +func parseRuleLexemes(r *policyengine.Rule, lexemes []string) error { + if len(lexemes) < 2 { + return errInvalidStatementFormat + } + + var err error + r.Status, err = parseStatus(lexemes[0]) + if err != nil { + return err + } + + r.Action, err = parseAction(lexemes[1]) + if err != nil { + return err + } + + r.Condition, err = parseConditions(lexemes[2 : len(lexemes)-1]) + if err != nil { + return err + } + + r.Resource, err = parseResource(lexemes[len(lexemes)-1]) + return err +} + +func parseStatus(lexeme string) (policyengine.Status, error) { + action, expression, found := strings.Cut(lexeme, ":") + switch action = strings.ToLower(action); action { + case "deny": + if !found { + return policyengine.AccessDenied, nil + } else if strings.EqualFold(expression, "QuotaLimitReached") { + return policyengine.QuotaLimitReached, nil + } else { + return 0, fmt.Errorf("%w: %s", errUnknownActionDetail, expression) + } + case "allow": + if found { + return 0, errUnknownActionDetail + } + return policyengine.Allow, nil + default: + return 0, errUnknownAction + } +} + +func parseAction(lexeme string) ([]string, error) { + switch strings.ToLower(lexeme) { + case "object.put": + return []string{"native:PutObject"}, nil + case "object.get": + return []string{"native:GetObject"}, nil + case "object.head": + return []string{"native:HeadObject"}, nil + case "object.delete": + return []string{"native:DeleteObject"}, nil + case "object.search": + return []string{"native:SearchObject"}, nil + case "object.range": + return []string{"native:RangeObject"}, nil + case "object.hash": + return []string{"native:HashObject"}, nil + default: + } + return nil, fmt.Errorf("%w: %s", errUnknownOperation, lexeme) +} + +func parseResource(lexeme string) ([]string, error) { + return []string{fmt.Sprintf("native:::object/%s", lexeme)}, nil +} + +const ( + ObjectResource = "object.resource" + ObjectRequest = "object.request" + ObjectActor = "object.actor" +) + +var typeToCondObject = map[string]policyengine.ObjectType{ + ObjectResource: policyengine.ObjectResource, + ObjectRequest: policyengine.ObjectRequest, + ObjectActor: policyengine.ObjectActor, +} + +func parseConditions(lexemes []string) ([]policyengine.Condition, error) { + conds := make([]policyengine.Condition, 0) + + for _, lexeme := range lexemes { + typ, expression, found := strings.Cut(lexeme, ":") + typ = strings.ToLower(typ) + + objType, ok := typeToCondObject[typ] + if ok { + if !found { + return nil, fmt.Errorf("%w: %s", errInvalidConditionFormat, lexeme) + } + + var lhs, rhs string + var binExpFound bool + + var cond policyengine.Condition + cond.Object = objType + + lhs, rhs, binExpFound = strings.Cut(expression, "!=") + if !binExpFound { + lhs, rhs, binExpFound = strings.Cut(expression, "=") + if !binExpFound { + return nil, fmt.Errorf("%w: %s", errUnknownBinaryOperator, expression) + } + cond.Op = policyengine.CondStringEquals + } else { + cond.Op = policyengine.CondStringNotEquals + } + + cond.Key, cond.Value = lhs, rhs + + conds = append(conds, cond) + } else { + return nil, fmt.Errorf("%w: %s", errUnknownCondObjectType, typ) + } + } + + return conds, nil +} diff --git a/cmd/frostfs-cli/modules/util/ape_test.go b/cmd/frostfs-cli/modules/util/ape_test.go new file mode 100644 index 0000000000..e71544a9bf --- /dev/null +++ b/cmd/frostfs-cli/modules/util/ape_test.go @@ -0,0 +1,129 @@ +package util + +import ( + "testing" + + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + "github.com/stretchr/testify/require" +) + +func TestParseAPERule(t *testing.T) { + tests := [...]struct { + name string + rule string + expectErr error + expectRule policyengine.Rule + }{ + { + name: "Valid allow rule", + rule: "allow Object.Put *", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Action: []string{"native:PutObject"}, + Resource: []string{"native:::object/*"}, + Condition: []policyengine.Condition{}, + }, + }, + { + name: "Valid deny rule", + rule: "deny Object.Put *", + expectRule: policyengine.Rule{ + Status: policyengine.AccessDenied, + Action: []string{"native:PutObject"}, + Resource: []string{"native:::object/*"}, + Condition: []policyengine.Condition{}, + }, + }, + { + name: "Valid deny rule with action detail", + rule: "deny:QuotaLimitReached Object.Put *", + expectRule: policyengine.Rule{ + Status: policyengine.QuotaLimitReached, + Action: []string{"native:PutObject"}, + Resource: []string{"native:::object/*"}, + Condition: []policyengine.Condition{}, + }, + }, + { + name: "Valid allow rule with conditions", + rule: "allow Object.Get Object.Resource:Department=HR Object.Request:Actor!=ownerA *", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Action: []string{"native:GetObject"}, + Resource: []string{"native:::object/*"}, + Condition: []policyengine.Condition{ + { + Op: policyengine.CondStringEquals, + Object: policyengine.ObjectResource, + Key: "Department", + Value: "HR", + }, + { + Op: policyengine.CondStringNotEquals, + Object: policyengine.ObjectRequest, + Key: "Actor", + Value: "ownerA", + }, + }, + }, + }, + { + name: "Valid rule with conditions with action detail", + rule: "deny:QuotaLimitReached Object.Get Object.Resource:Department=HR Object.Request:Actor!=ownerA *", + expectRule: policyengine.Rule{ + Status: policyengine.QuotaLimitReached, + Action: []string{"native:GetObject"}, + Resource: []string{"native:::object/*"}, + Condition: []policyengine.Condition{ + { + Op: policyengine.CondStringEquals, + Object: policyengine.ObjectResource, + Key: "Department", + Value: "HR", + }, + { + Op: policyengine.CondStringNotEquals, + Object: policyengine.ObjectRequest, + Key: "Actor", + Value: "ownerA", + }, + }, + }, + }, + { + name: "Invalid rule with unknown action", + rule: "permit Object.Put *", + expectErr: errUnknownAction, + }, + { + name: "Invalid rule with unknown operation", + rule: "allow Object.PutOut *", + expectErr: errUnknownOperation, + }, + { + name: "Invalid rule with unknown action detail", + rule: "deny:UnknownActionDetail Object.Put *", + expectErr: errUnknownActionDetail, + }, + { + name: "Invalid rule with unknown condition binary operator", + rule: "deny Object.Put Object.Resource:Department
Date: Tue, 7 Nov 2023 15:19:55 +0300 Subject: [PATCH 0128/1413] [#xx] adm: Drop notaryDisabled deploy parameter Refs https://git.frostfs.info/TrueCloudLab/frostfs-contract/pulls/50 Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/initialize_deploy.go | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 8d46793e56..f6100f4f9a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -505,8 +505,7 @@ func getContractDeployParameters(cs *contractState, deployData []any) []any { } func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any, method string) []any { - items := make([]any, 1, 6) - items[0] = false // notaryDisabled is false + items := make([]any, 0, 6) switch ctrName { case frostfsContract: @@ -596,12 +595,11 @@ func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, } func (c *initializeContext) getAlphabetDeployItems(i, n int) []any { - items := make([]any, 6) - items[0] = false - items[1] = c.Contracts[netmapContract].Hash - items[2] = c.Contracts[proxyContract].Hash - items[3] = innerring.GlagoliticLetter(i).String() - items[4] = int64(i) - items[5] = int64(n) + items := make([]any, 5) + items[0] = c.Contracts[netmapContract].Hash + items[1] = c.Contracts[proxyContract].Hash + items[2] = innerring.GlagoliticLetter(i).String() + items[3] = int64(i) + items[4] = int64(n) return items } From 3534d6d05bdddcf40783d51aa281434e2e128cc0 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Wed, 8 Nov 2023 17:12:45 +0300 Subject: [PATCH 0129/1413] [#794] objectsvc: Return accidentally removed acl checks for Head Signed-off-by: Airat Arifullin --- pkg/services/object/acl/v2/service.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 6d6f9c448b..ee167d0e4d 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -218,6 +218,12 @@ func (b Service) Head( reqInfo.obj = obj + if !b.checker.CheckBasicACL(reqInfo) { + return nil, basicACLErr(reqInfo) + } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { + return nil, eACLErr(reqInfo, err) + } + resp, err := b.next.Head(ctx, request) if err == nil { if err = b.checker.CheckEACL(resp, reqInfo); err != nil { From 1b22801eed60949f853e63ccd069dea557b9c3d6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 9 Nov 2023 10:25:46 +0300 Subject: [PATCH 0130/1413] [#788] engine: Fix flaky tests Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/lock_test.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index d5c080222d..ec18fc5e32 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -137,13 +137,12 @@ func TestLockUserScenario(t *testing.T) { // 5. e.HandleNewEpoch(lockerExpiresAfter + 1) - // delay for GC - time.Sleep(time.Second) - inhumePrm.WithTarget(tombAddr, objAddr) - _, err = e.Inhume(context.Background(), inhumePrm) - require.NoError(t, err) + require.Eventually(t, func() bool { + _, err = e.Inhume(context.Background(), inhumePrm) + return err == nil + }, 30*time.Second, time.Second) } func TestLockExpiration(t *testing.T) { @@ -213,15 +212,13 @@ func TestLockExpiration(t *testing.T) { // 3. e.HandleNewEpoch(lockerExpiresAfter + 1) - // delay for GC processing. It can't be estimated, but making it bigger - // will slow down test - time.Sleep(time.Second) - // 4. inhumePrm.WithTarget(oidtest.Address(), objectcore.AddressOf(obj)) - _, err = e.Inhume(context.Background(), inhumePrm) - require.NoError(t, err) + require.Eventually(t, func() bool { + _, err = e.Inhume(context.Background(), inhumePrm) + return err == nil + }, 30*time.Second, time.Second) } func TestLockForceRemoval(t *testing.T) { From 9133b4389e764611d7211576b97b01aa531c8e8c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 9 Nov 2023 10:27:32 +0300 Subject: [PATCH 0131/1413] [#788] objectsvc: Fix formatting (gofumpt) Signed-off-by: Dmitrii Stepanov --- pkg/services/object/acl/ape.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go index b064b1eec0..86af440fe0 100644 --- a/pkg/services/object/acl/ape.go +++ b/pkg/services/object/acl/ape.go @@ -11,9 +11,7 @@ import ( policyengine "git.frostfs.info/TrueCloudLab/policy-engine" ) -var ( - errAPEChainNoSource = errors.New("could not get ape chain source for the container") -) +var errAPEChainNoSource = errors.New("could not get ape chain source for the container") type apeCheckerImpl struct { log *logger.Logger From 1bca8f118f6e29f9dbf015be12b03e5eb4a670dc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 8 Nov 2023 15:43:54 +0300 Subject: [PATCH 0132/1413] [#792] makefile: Fix protoc and staticcheck versions Signed-off-by: Dmitrii Stepanov --- .golangci.yml | 2 +- Makefile | 61 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index ef99fc1521..5c7e9d9182 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -39,7 +39,7 @@ linters-settings: alias: objectSDK custom: truecloudlab-linters: - path: bin/external_linters.so + path: bin/linters/external_linters.so original-url: git.frostfs.info/TrueCloudLab/linters.git settings: noliteral: diff --git a/Makefile b/Makefile index 14e32e40f6..3fcb5027c6 100755 --- a/Makefile +++ b/Makefile @@ -10,6 +10,14 @@ HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.21 LINT_VERSION ?= 1.54.0 TRUECLOUDLAB_LINT_VERSION ?= 0.0.2 +PROTOC_VERSION ?= 25.0 +PROTOC_GEN_GO_VERSION ?= $(shell go list -f '{{.Version}}' -m google.golang.org/protobuf) +PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) +PROTOC_OS_VERSION=osx-x86_64 +ifeq ($(shell uname), Linux) + PROTOC_OS_VERSION=linux-x86_64 +endif +STATICCHECK_VERSION ?= 2023.1.6 ARCH = amd64 BIN = bin @@ -26,9 +34,15 @@ PKG_VERSION ?= $(shell echo $(VERSION) | sed "s/^v//" | \ sed -E "s/(.*)-(g[a-fA-F0-9]{6,8})(.*)/\1\3~\2/" | \ sed "s/-/~/")-${OS_RELEASE} -OUTPUT_LINT_DIR ?= $(shell pwd)/bin +OUTPUT_LINT_DIR ?= $(abspath $(BIN))/linters LINT_DIR = $(OUTPUT_LINT_DIR)/golangci-lint-$(LINT_VERSION)-v$(TRUECLOUDLAB_LINT_VERSION) TMP_DIR := .cache +PROTOBUF_DIR ?= $(abspath $(BIN))/protobuf +PROTOC_DIR ?= $(PROTOBUF_DIR)/protoc-v$(PROTOC_VERSION) +PROTOC_GEN_GO_DIR ?= $(PROTOBUF_DIR)/protoc-gen-go-$(PROTOC_GEN_GO_VERSION) +PROTOGEN_FROSTFS_DIR ?= $(PROTOBUF_DIR)/protogen-$(PROTOGEN_FROSTFS_VERSION) +STATICCHECK_DIR ?= $(abspath $(BIN))/staticcheck +STATICCHECK_VERSION_DIR ?= $(STATICCHECK_DIR)/$(STATICCHECK_VERSION) .PHONY: help all images dep clean fmts fumpt imports test lint docker/lint prepare-release debpackage pre-commit unpre-commit @@ -78,22 +92,32 @@ export-metrics: dep # Regenerate proto files: protoc: - @GOPRIVATE=github.com/TrueCloudLab go mod vendor - # Install specific version for protobuf lib - @go list -f '{{.Path}}/...@{{.Version}}' -m github.com/golang/protobuf | xargs go install -v - @GOBIN=$(abspath $(BIN)) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/protogen - # Protoc generate - @for f in `find . -type f -name '*.proto' -not -path './vendor/*'`; do \ + @if [ ! -d "$(PROTOC_DIR)" ] || [ ! -d "$(PROTOC_GEN_GO_DIR)" ] || [ ! -d "$(PROTOGEN_FROSTFS_DIR)" ]; then \ + make protoc-install; \ + fi + @for f in `find . -type f -name '*.proto' -not -path './bin/*'`; do \ echo "⇒ Processing $$f "; \ - protoc \ - --proto_path=.:./vendor:/usr/local/include \ - --plugin=protoc-gen-go-frostfs=$(BIN)/protogen \ + $(PROTOC_DIR)/bin/protoc \ + --proto_path=.:$(PROTOC_DIR)/include:/usr/local/include \ + --plugin=protoc-gen-go=$(PROTOC_GEN_GO_DIR)/protoc-gen-go \ + --plugin=protoc-gen-go-frostfs=$(PROTOGEN_FROSTFS_DIR)/protogen \ --go-frostfs_out=. --go-frostfs_opt=paths=source_relative \ --go_out=. --go_opt=paths=source_relative \ --go-grpc_opt=require_unimplemented_servers=false \ --go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \ done - rm -rf vendor + +protoc-install: + @rm -rf $(PROTOBUF_DIR) + @mkdir $(PROTOBUF_DIR) + @echo "⇒ Installing protoc... " + @wget -q -O $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip 'https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(PROTOC_OS_VERSION).zip' + @unzip -q -o $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip -d $(PROTOC_DIR) + @rm $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip + @echo "⇒ Installing protoc-gen-go..." + @GOBIN=$(PROTOC_GEN_GO_DIR) go install -v google.golang.org/protobuf/...@$(PROTOC_GEN_GO_VERSION) + @echo "⇒ Instaling protogen FrostFS plugin..." + @GOBIN=$(PROTOGEN_FROSTFS_DIR) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/protogen@$(PROTOGEN_FROSTFS_VERSION) # Build FrostFS component's docker image image-%: @@ -143,6 +167,8 @@ pre-commit-run: # Install linters lint-install: + @rm -rf $(OUTPUT_LINT_DIR) + @mkdir $(OUTPUT_LINT_DIR) @mkdir -p $(TMP_DIR) @rm -rf $(TMP_DIR)/linters @git -c advice.detachedHead=false clone --branch v$(TRUECLOUDLAB_LINT_VERSION) https://git.frostfs.info/TrueCloudLab/linters.git $(TMP_DIR)/linters @@ -154,18 +180,22 @@ lint-install: # Run linters lint: @if [ ! -d "$(LINT_DIR)" ]; then \ - echo "Run make lint-install"; \ - exit 1; \ + make lint-install; \ fi $(LINT_DIR)/golangci-lint run # Install staticcheck staticcheck-install: - @go install honnef.co/go/tools/cmd/staticcheck@latest + @rm -rf $(STATICCHECK_DIR) + @mkdir $(STATICCHECK_DIR) + @GOBIN=$(STATICCHECK_VERSION_DIR) go install honnef.co/go/tools/cmd/staticcheck@$(STATICCHECK_VERSION) # Run staticcheck staticcheck-run: - @staticcheck ./... + @if [ ! -d "$(STATICCHECK_VERSION_DIR)" ]; then \ + make staticcheck-install; \ + fi + @$(STATICCHECK_VERSION_DIR)/staticcheck ./... # Run linters in Docker docker/lint: @@ -189,7 +219,6 @@ version: # Delete built artifacts clean: - rm -rf vendor rm -rf .cache rm -rf $(BIN) rm -rf $(RELEASE) From 7cdae4f66075977cdb216de25f5809aa70839fe5 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 8 Nov 2023 15:45:03 +0300 Subject: [PATCH 0133/1413] [#792] proto: Regenerate with fixed version Signed-off-by: Dmitrii Stepanov --- pkg/services/control/ir/service.pb.go | 4 ++-- pkg/services/control/ir/service_grpc.pb.go | 2 +- pkg/services/control/ir/types.pb.go | 4 ++-- pkg/services/control/service.pb.go | 4 ++-- pkg/services/control/service_grpc.pb.go | 2 +- pkg/services/control/types.pb.go | 4 ++-- pkg/services/tree/service.pb.go | 4 ++-- pkg/services/tree/service_grpc.pb.go | 2 +- pkg/services/tree/types.pb.go | 4 ++-- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pkg/services/control/ir/service.pb.go b/pkg/services/control/ir/service.pb.go index 56d52be4ce..1b81a56191 100644 --- a/pkg/services/control/ir/service.pb.go +++ b/pkg/services/control/ir/service.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v4.24.4 +// protoc-gen-go v1.31.0 +// protoc v4.25.0 // source: pkg/services/control/ir/service.proto package control diff --git a/pkg/services/control/ir/service_grpc.pb.go b/pkg/services/control/ir/service_grpc.pb.go index 004c82446c..724149c441 100644 --- a/pkg/services/control/ir/service_grpc.pb.go +++ b/pkg/services/control/ir/service_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.24.4 +// - protoc v4.25.0 // source: pkg/services/control/ir/service.proto package control diff --git a/pkg/services/control/ir/types.pb.go b/pkg/services/control/ir/types.pb.go index 0ff8f45e9b..cc39ad572c 100644 --- a/pkg/services/control/ir/types.pb.go +++ b/pkg/services/control/ir/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v4.24.4 +// protoc-gen-go v1.31.0 +// protoc v4.25.0 // source: pkg/services/control/ir/types.proto package control diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 547ea7e7e2..346a436640 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v4.24.4 +// protoc-gen-go v1.31.0 +// protoc v4.25.0 // source: pkg/services/control/service.proto package control diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index b5881ccb2a..c3976c54aa 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v4.24.4 +// - protoc v4.25.0 // source: pkg/services/control/service.proto package control diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index 33700c5b9d..f031f8043d 100644 --- a/pkg/services/control/types.pb.go +++ b/pkg/services/control/types.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v4.24.4 +// protoc-gen-go v1.31.0 +// protoc v4.25.0 // source: pkg/services/control/types.proto package control diff --git a/pkg/services/tree/service.pb.go b/pkg/services/tree/service.pb.go index 63f3e714a2..5346613895 100644 --- a/pkg/services/tree/service.pb.go +++ b/pkg/services/tree/service.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc-gen-go v1.31.0 +// protoc v4.25.0 // source: pkg/services/tree/service.proto package tree diff --git a/pkg/services/tree/service_grpc.pb.go b/pkg/services/tree/service_grpc.pb.go index 2c0828951a..63f96e11a5 100644 --- a/pkg/services/tree/service_grpc.pb.go +++ b/pkg/services/tree/service_grpc.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 -// - protoc v3.21.9 +// - protoc v4.25.0 // source: pkg/services/tree/service.proto package tree diff --git a/pkg/services/tree/types.pb.go b/pkg/services/tree/types.pb.go index b4d6981ef9..f6b19c20ff 100644 --- a/pkg/services/tree/types.pb.go +++ b/pkg/services/tree/types.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.21.9 +// protoc-gen-go v1.31.0 +// protoc v4.25.0 // source: pkg/services/tree/types.proto package tree From 0f75e48138220675a50fd473318acd1a7a7e7500 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 9 Nov 2023 13:33:03 +0300 Subject: [PATCH 0134/1413] [#796] policer: Fix tombstone objects replication Tombstone objects must be replicated to all container nodes. Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/check.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 9b44acedaf..9e40219d17 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -93,10 +93,10 @@ func (p *Policer) processNodes(ctx context.Context, requirements *placementRequi // Number of copies that are stored on maintenance nodes. var uncheckedCopies int - if typ == objectSDK.TypeLock { - // all nodes of a container must store the `LOCK` objects + if typ == objectSDK.TypeLock || typ == objectSDK.TypeTombstone { + // all nodes of a container must store the `LOCK` and `TOMBSTONE` objects // for correct object removal protection: - // - `LOCK` objects are broadcast on their PUT requests; + // - `LOCK` and `TOMBSTONE` objects are broadcast on their PUT requests; // - `LOCK` object removal is a prohibited action in the GC. shortage = uint32(len(nodes)) } From 78cfb6aea86c01df34a534020dc63cefbad61da0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 9 Nov 2023 13:33:59 +0300 Subject: [PATCH 0135/1413] [#796] cli: Fix object nodes command Tombstone objects must be present on all container nodes. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index ef6c29179a..70a3eb75f3 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -31,10 +31,10 @@ const ( ) type objectNodesInfo struct { - containerID cid.ID - objectID oid.ID - relatedObjectIDs []oid.ID - isLock bool + containerID cid.ID + objectID oid.ID + relatedObjectIDs []oid.ID + isLockOrTombstone bool } type boolError struct { @@ -101,9 +101,9 @@ func getObjectInfo(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.C res, err := internalclient.HeadObject(cmd.Context(), prmHead) if err == nil { return &objectNodesInfo{ - containerID: cnrID, - objectID: objID, - isLock: res.Header().Type() == objectSDK.TypeLock, + containerID: cnrID, + objectID: objID, + isLockOrTombstone: res.Header().Type() == objectSDK.TypeLock || res.Header().Type() == objectSDK.TypeTombstone, } } @@ -191,7 +191,7 @@ func getRequiredPlacement(cmd *cobra.Command, objInfo *objectNodesInfo, placemen numOfReplicas := placementPolicy.ReplicaNumberByIndex(repIdx) var nodeIdx uint32 for _, n := range rep { - if !objInfo.isLock && nodeIdx == numOfReplicas { // lock object should be on all container nodes + if !objInfo.isLockOrTombstone && nodeIdx == numOfReplicas { // lock and tombstone objects should be on all container nodes break } nodes[n.Hash()] = n From bdfa5234875141c6152284ea19eba440aeaed702 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 7 Nov 2023 16:44:43 +0300 Subject: [PATCH 0136/1413] [#787] proto: Add VUB field for IR service Signed-off-by: Dmitrii Stepanov --- pkg/services/control/ir/service.pb.go | 219 ++++++++++++------ pkg/services/control/ir/service.proto | 27 ++- pkg/services/control/ir/service_frostfs.pb.go | 40 ++++ 3 files changed, 203 insertions(+), 83 deletions(-) diff --git a/pkg/services/control/ir/service.pb.go b/pkg/services/control/ir/service.pb.go index 1b81a56191..a9be56cd9b 100644 --- a/pkg/services/control/ir/service.pb.go +++ b/pkg/services/control/ir/service.pb.go @@ -560,6 +560,9 @@ type TickEpochRequest_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // Valid until block value override. + Vub uint32 `protobuf:"varint,1,opt,name=vub,proto3" json:"vub,omitempty"` } func (x *TickEpochRequest_Body) Reset() { @@ -594,10 +597,20 @@ func (*TickEpochRequest_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{2, 0} } +func (x *TickEpochRequest_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} + type TickEpochResponse_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // Valid until block value for transaction. + Vub uint32 `protobuf:"varint,1,opt,name=vub,proto3" json:"vub,omitempty"` } func (x *TickEpochResponse_Body) Reset() { @@ -632,12 +645,21 @@ func (*TickEpochResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{3, 0} } +func (x *TickEpochResponse_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} + type RemoveNodeRequest_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + // Valid until block value override. + Vub uint32 `protobuf:"varint,2,opt,name=vub,proto3" json:"vub,omitempty"` } func (x *RemoveNodeRequest_Body) Reset() { @@ -679,10 +701,20 @@ func (x *RemoveNodeRequest_Body) GetKey() []byte { return nil } +func (x *RemoveNodeRequest_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} + type RemoveNodeResponse_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // Valid until block value for transaction. + Vub uint32 `protobuf:"varint,1,opt,name=vub,proto3" json:"vub,omitempty"` } func (x *RemoveNodeResponse_Body) Reset() { @@ -717,6 +749,13 @@ func (*RemoveNodeResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{5, 0} } +func (x *RemoveNodeResponse_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} + type RemoveContainerRequest_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -724,6 +763,8 @@ type RemoveContainerRequest_Body struct { ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` Owner []byte `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"` + // Valid until block value override. + Vub uint32 `protobuf:"varint,3,opt,name=vub,proto3" json:"vub,omitempty"` } func (x *RemoveContainerRequest_Body) Reset() { @@ -772,10 +813,20 @@ func (x *RemoveContainerRequest_Body) GetOwner() []byte { return nil } +func (x *RemoveContainerRequest_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} + type RemoveContainerResponse_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // Valid until block value for transaction. + Vub uint32 `protobuf:"varint,1,opt,name=vub,proto3" json:"vub,omitempty"` } func (x *RemoveContainerResponse_Body) Reset() { @@ -810,6 +861,13 @@ func (*RemoveContainerResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{7, 0} } +func (x *RemoveContainerResponse_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} + var File_pkg_services_control_ir_service_proto protoreflect.FileDescriptor var file_pkg_services_control_ir_service_proto_rawDesc = []byte{ @@ -839,7 +897,7 @@ var file_pkg_services_control_ir_service_proto_rawDesc = []byte{ 0x3c, 0x0a, 0x0d, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x84, 0x01, + 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x10, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, @@ -847,82 +905,89 @@ var file_pkg_services_control_ir_service_proto_rawDesc = []byte{ 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x22, 0x86, 0x01, 0x0a, 0x11, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x98, 0x01, - 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x18, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x69, - 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x3f, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, - 0x92, 0x01, 0x0a, 0x17, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x69, 0x72, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x32, 0xcb, 0x02, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x09, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, - 0x63, 0x68, 0x12, 0x1b, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, - 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, - 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, - 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x69, 0x72, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, - 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x2e, 0x69, 0x72, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, - 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, - 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, - 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, - 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x69, 0x72, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x18, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, 0x22, 0x98, 0x01, 0x0a, 0x11, 0x54, 0x69, 0x63, 0x6b, 0x45, + 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x72, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x76, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, + 0x62, 0x22, 0xaa, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0x2a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x76, 0x75, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, 0x22, 0x9a, + 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x75, 0x62, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, 0x22, 0xdb, 0x01, 0x0a, 0x16, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x51, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, + 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x75, 0x62, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, 0x22, 0xa4, 0x01, 0x0a, 0x17, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x76, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, + 0x32, 0xcb, 0x02, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1e, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x46, 0x0a, 0x09, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1b, + 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, + 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x69, 0x72, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, + 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x72, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x44, + 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, + 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, + 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x69, 0x72, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/ir/service.proto b/pkg/services/control/ir/service.proto index cd890d438d..967ff979e9 100644 --- a/pkg/services/control/ir/service.proto +++ b/pkg/services/control/ir/service.proto @@ -21,8 +21,7 @@ service ControlService { // Health check request. message HealthCheckRequest { // Health check request body. - message Body { - } + message Body {} // Body of health check request message. Body body = 1; @@ -49,14 +48,20 @@ message HealthCheckResponse { } message TickEpochRequest { - message Body{} + message Body{ + // Valid until block value override. + uint32 vub = 1; + } Body body = 1; Signature signature = 2; } message TickEpochResponse { - message Body{} + message Body{ + // Valid until block value for transaction. + uint32 vub = 1; + } Body body = 1; Signature signature = 2; @@ -65,6 +70,8 @@ message TickEpochResponse { message RemoveNodeRequest { message Body{ bytes key = 1; + // Valid until block value override. + uint32 vub = 2; } Body body = 1; @@ -72,7 +79,10 @@ message RemoveNodeRequest { } message RemoveNodeResponse { - message Body{} + message Body{ + // Valid until block value for transaction. + uint32 vub = 1; + } Body body = 1; Signature signature = 2; @@ -82,6 +92,8 @@ message RemoveContainerRequest { message Body{ bytes container_id = 1; bytes owner = 2; + // Valid until block value override. + uint32 vub = 3; } Body body = 1; @@ -89,7 +101,10 @@ message RemoveContainerRequest { } message RemoveContainerResponse { - message Body{} + message Body{ + // Valid until block value for transaction. + uint32 vub = 1; + } Body body = 1; Signature signature = 2; diff --git a/pkg/services/control/ir/service_frostfs.pb.go b/pkg/services/control/ir/service_frostfs.pb.go index 131ec78dac..e22d0013f2 100644 --- a/pkg/services/control/ir/service_frostfs.pb.go +++ b/pkg/services/control/ir/service_frostfs.pb.go @@ -174,6 +174,7 @@ func (x *TickEpochRequest_Body) StableSize() (size int) { if x == nil { return 0 } + size += proto.UInt32Size(1, x.Vub) return size } @@ -186,6 +187,14 @@ func (x *TickEpochRequest_Body) StableSize() (size int) { // // Structures with the same field values have the same binary format. func (x *TickEpochRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.UInt32Marshal(1, buf[offset:], x.Vub) return buf } @@ -251,6 +260,7 @@ func (x *TickEpochResponse_Body) StableSize() (size int) { if x == nil { return 0 } + size += proto.UInt32Size(1, x.Vub) return size } @@ -263,6 +273,14 @@ func (x *TickEpochResponse_Body) StableSize() (size int) { // // Structures with the same field values have the same binary format. func (x *TickEpochResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.UInt32Marshal(1, buf[offset:], x.Vub) return buf } @@ -329,6 +347,7 @@ func (x *RemoveNodeRequest_Body) StableSize() (size int) { return 0 } size += proto.BytesSize(1, x.Key) + size += proto.UInt32Size(2, x.Vub) return size } @@ -349,6 +368,7 @@ func (x *RemoveNodeRequest_Body) StableMarshal(buf []byte) []byte { } var offset int offset += proto.BytesMarshal(1, buf[offset:], x.Key) + offset += proto.UInt32Marshal(2, buf[offset:], x.Vub) return buf } @@ -414,6 +434,7 @@ func (x *RemoveNodeResponse_Body) StableSize() (size int) { if x == nil { return 0 } + size += proto.UInt32Size(1, x.Vub) return size } @@ -426,6 +447,14 @@ func (x *RemoveNodeResponse_Body) StableSize() (size int) { // // Structures with the same field values have the same binary format. func (x *RemoveNodeResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.UInt32Marshal(1, buf[offset:], x.Vub) return buf } @@ -493,6 +522,7 @@ func (x *RemoveContainerRequest_Body) StableSize() (size int) { } size += proto.BytesSize(1, x.ContainerId) size += proto.BytesSize(2, x.Owner) + size += proto.UInt32Size(3, x.Vub) return size } @@ -514,6 +544,7 @@ func (x *RemoveContainerRequest_Body) StableMarshal(buf []byte) []byte { var offset int offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) offset += proto.BytesMarshal(2, buf[offset:], x.Owner) + offset += proto.UInt32Marshal(3, buf[offset:], x.Vub) return buf } @@ -579,6 +610,7 @@ func (x *RemoveContainerResponse_Body) StableSize() (size int) { if x == nil { return 0 } + size += proto.UInt32Size(1, x.Vub) return size } @@ -591,6 +623,14 @@ func (x *RemoveContainerResponse_Body) StableSize() (size int) { // // Structures with the same field values have the same binary format. func (x *RemoveContainerResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.UInt32Marshal(1, buf[offset:], x.Vub) return buf } From 5466e884447401fa8d7441683111ac0b5a13608c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 7 Nov 2023 17:35:09 +0300 Subject: [PATCH 0137/1413] [#787] cli: Add `vub` for `control ir` commands Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/ir.go | 15 ++++++++++++++- .../modules/control/ir_remove_container.go | 6 +++++- cmd/frostfs-cli/modules/control/ir_remove_node.go | 4 +++- cmd/frostfs-cli/modules/control/ir_tick_epoch.go | 7 +++++-- cmd/frostfs-cli/modules/control/util.go | 11 +++++++++++ 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/ir.go b/cmd/frostfs-cli/modules/control/ir.go index ac1371db73..2a38f1e974 100644 --- a/cmd/frostfs-cli/modules/control/ir.go +++ b/cmd/frostfs-cli/modules/control/ir.go @@ -1,6 +1,9 @@ package control -import "github.com/spf13/cobra" +import ( + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/spf13/cobra" +) var irCmd = &cobra.Command{ Use: "ir", @@ -19,3 +22,13 @@ func initControlIRCmd() { initControlIRHealthCheckCmd() initControlIRRemoveContainerCmd() } + +func printVUB(cmd *cobra.Command, vub uint32) { + cmd.Printf("Transaction's valid until block is %d\n", vub) +} + +func parseVUB(cmd *cobra.Command) uint32 { + vub, err := cmd.Flags().GetUint32(irFlagNameVUB) + commonCmd.ExitOnErr(cmd, "invalid valid until block value: %w", err) + return vub +} diff --git a/cmd/frostfs-cli/modules/control/ir_remove_container.go b/cmd/frostfs-cli/modules/control/ir_remove_container.go index 43173bcaa1..52eaa574d5 100644 --- a/cmd/frostfs-cli/modules/control/ir_remove_container.go +++ b/cmd/frostfs-cli/modules/control/ir_remove_container.go @@ -29,7 +29,7 @@ To check removal status "frostfs-cli container list" command can be used.`, } func initControlIRRemoveContainerCmd() { - initControlFlags(removeContainerCmd) + initControlIRFlags(removeContainerCmd) flags := removeContainerCmd.Flags() flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) @@ -60,6 +60,7 @@ func removeContainer(cmd *cobra.Command, _ []string) { } else { cmd.Println("User containers sheduled to removal") } + printVUB(cmd, resp.GetBody().GetVub()) } func prepareRemoveContainerRequest(cmd *cobra.Command) *ircontrol.RemoveContainerRequest { @@ -90,5 +91,8 @@ func prepareRemoveContainerRequest(cmd *cobra.Command) *ircontrol.RemoveContaine commonCmd.ExitOnErr(cmd, "invalid container ID: %w", containerID.DecodeString(cidStr)) req.Body.ContainerId = containerID[:] } + + req.Body.Vub = parseVUB(cmd) + return req } diff --git a/cmd/frostfs-cli/modules/control/ir_remove_node.go b/cmd/frostfs-cli/modules/control/ir_remove_node.go index f5b968b7ff..412dc79342 100644 --- a/cmd/frostfs-cli/modules/control/ir_remove_node.go +++ b/cmd/frostfs-cli/modules/control/ir_remove_node.go @@ -20,7 +20,7 @@ var removeNodeCmd = &cobra.Command{ } func initControlIRRemoveNodeCmd() { - initControlFlags(removeNodeCmd) + initControlIRFlags(removeNodeCmd) flags := removeNodeCmd.Flags() flags.String("node", "", "Node public key as a hex string") @@ -41,6 +41,7 @@ func removeNode(cmd *cobra.Command, _ []string) { req := new(ircontrol.RemoveNodeRequest) req.SetBody(&ircontrol.RemoveNodeRequest_Body{ Key: nodeKey, + Vub: parseVUB(cmd), }) commonCmd.ExitOnErr(cmd, "could not sign request: %w", ircontrolsrv.SignMessage(pk, req)) @@ -55,4 +56,5 @@ func removeNode(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) cmd.Println("Node removed") + printVUB(cmd, resp.GetBody().GetVub()) } diff --git a/cmd/frostfs-cli/modules/control/ir_tick_epoch.go b/cmd/frostfs-cli/modules/control/ir_tick_epoch.go index 3e6af00819..6965b5dcad 100644 --- a/cmd/frostfs-cli/modules/control/ir_tick_epoch.go +++ b/cmd/frostfs-cli/modules/control/ir_tick_epoch.go @@ -17,7 +17,7 @@ var tickEpochCmd = &cobra.Command{ } func initControlIRTickEpochCmd() { - initControlFlags(tickEpochCmd) + initControlIRFlags(tickEpochCmd) } func tickEpoch(cmd *cobra.Command, _ []string) { @@ -25,7 +25,9 @@ func tickEpoch(cmd *cobra.Command, _ []string) { c := getClient(cmd, pk) req := new(ircontrol.TickEpochRequest) - req.SetBody(new(ircontrol.TickEpochRequest_Body)) + req.SetBody(&ircontrol.TickEpochRequest_Body{ + Vub: parseVUB(cmd), + }) err := ircontrolsrv.SignMessage(pk, req) commonCmd.ExitOnErr(cmd, "could not sign request: %w", err) @@ -40,4 +42,5 @@ func tickEpoch(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) cmd.Println("Epoch tick requested") + printVUB(cmd, resp.GetBody().GetVub()) } diff --git a/cmd/frostfs-cli/modules/control/util.go b/cmd/frostfs-cli/modules/control/util.go index 5ad675c0e2..ffaceff13d 100644 --- a/cmd/frostfs-cli/modules/control/util.go +++ b/cmd/frostfs-cli/modules/control/util.go @@ -14,6 +14,10 @@ import ( "github.com/spf13/cobra" ) +const ( + irFlagNameVUB = "vub" +) + func initControlFlags(cmd *cobra.Command) { ff := cmd.Flags() ff.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage) @@ -22,6 +26,13 @@ func initControlFlags(cmd *cobra.Command) { ff.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage) } +func initControlIRFlags(cmd *cobra.Command) { + initControlFlags(cmd) + + ff := cmd.Flags() + ff.Uint32(irFlagNameVUB, 0, "Valid until block value for notary transaction") +} + func signRequest(cmd *cobra.Command, pk *ecdsa.PrivateKey, req controlSvc.SignedMessage) { err := controlSvc.SignMessage(pk, req) commonCmd.ExitOnErr(cmd, "could not sign request: %w", err) From 518f3baf41db089f3a790bdf1fd665af36fb21d6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 7 Nov 2023 18:13:26 +0300 Subject: [PATCH 0138/1413] [#787] morph: Return VUB from `Invoke` method Signed-off-by: Dmitrii Stepanov --- .../processors/alphabet/handlers_test.go | 4 +-- .../processors/alphabet/process_emit.go | 2 +- .../processors/alphabet/processor.go | 2 +- pkg/innerring/processors/netmap/wrappers.go | 3 ++- pkg/innerring/state.go | 2 +- pkg/morph/client/balance/burn.go | 3 ++- pkg/morph/client/balance/lock.go | 3 ++- pkg/morph/client/balance/mint.go | 3 ++- pkg/morph/client/balance/transfer.go | 2 +- pkg/morph/client/client.go | 9 ++++--- pkg/morph/client/container/delete.go | 2 +- pkg/morph/client/container/eacl_set.go | 2 +- pkg/morph/client/container/estimations.go | 4 +-- pkg/morph/client/container/load.go | 2 +- pkg/morph/client/container/put.go | 2 +- pkg/morph/client/frostfs/bind.go | 4 +-- pkg/morph/client/frostfs/cheque.go | 6 +++-- pkg/morph/client/frostfsid/addrm_keys.go | 4 +-- pkg/morph/client/netmap/config.go | 3 ++- pkg/morph/client/netmap/innerring.go | 3 ++- pkg/morph/client/netmap/new_epoch.go | 2 +- pkg/morph/client/netmap/peer.go | 2 +- pkg/morph/client/netmap/update_state.go | 2 +- pkg/morph/client/notary.go | 27 ++++++++++--------- pkg/morph/client/static.go | 19 +++++++++---- 25 files changed, 69 insertions(+), 48 deletions(-) diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index e39244a364..f94c8e78db 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -246,7 +246,7 @@ type testMorphClient struct { batchTransferedGas []batchTransferGas } -func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error { +func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { c.invokedMethods = append(c.invokedMethods, invokedMethod{ contract: contract, @@ -254,7 +254,7 @@ func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, metho method: method, args: args, }) - return nil + return 0, nil } func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error { diff --git a/pkg/innerring/processors/alphabet/process_emit.go b/pkg/innerring/processors/alphabet/process_emit.go index 8a23360112..2317f3e98d 100644 --- a/pkg/innerring/processors/alphabet/process_emit.go +++ b/pkg/innerring/processors/alphabet/process_emit.go @@ -30,7 +30,7 @@ func (ap *Processor) processEmit() bool { } // there is no signature collecting, so we don't need extra fee - err := ap.morphClient.Invoke(contract, 0, emitMethod) + _, err := ap.morphClient.Invoke(contract, 0, emitMethod) if err != nil { ap.log.Warn(logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index 04dde80f72..ce66799693 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -40,7 +40,7 @@ type ( } morphClient interface { - Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error + Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8) error } diff --git a/pkg/innerring/processors/netmap/wrappers.go b/pkg/innerring/processors/netmap/wrappers.go index 255d498d39..f9af703de5 100644 --- a/pkg/innerring/processors/netmap/wrappers.go +++ b/pkg/innerring/processors/netmap/wrappers.go @@ -23,7 +23,8 @@ func (w *netmapClientWrapper) UpdatePeerState(p netmapclient.UpdatePeerPrm) erro } func (w *netmapClientWrapper) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { - return w.netmapClient.Morph().NotaryInvoke(contract, fee, nonce, vub, method, args...) + _, err := w.netmapClient.Morph().NotaryInvoke(contract, fee, nonce, vub, method, args...) + return err } func (w *netmapClientWrapper) ContractAddress() util.Uint160 { diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index c5adb71ebf..f2521bd083 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -125,7 +125,7 @@ func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) erro } s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) { - err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators) + _, err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators) if err != nil { s.log.Warn(logs.InnerringCantInvokeVoteMethodInAlphabetContract, zap.Int8("alphabet_index", int8(letter)), diff --git a/pkg/morph/client/balance/burn.go b/pkg/morph/client/balance/burn.go index 88a1aa8f11..4befbef45f 100644 --- a/pkg/morph/client/balance/burn.go +++ b/pkg/morph/client/balance/burn.go @@ -36,5 +36,6 @@ func (c *Client) Burn(p BurnPrm) error { prm.SetArgs(p.to, p.amount, p.id) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } diff --git a/pkg/morph/client/balance/lock.go b/pkg/morph/client/balance/lock.go index 7b270808e1..a5b2067995 100644 --- a/pkg/morph/client/balance/lock.go +++ b/pkg/morph/client/balance/lock.go @@ -48,5 +48,6 @@ func (c *Client) Lock(p LockPrm) error { prm.SetArgs(p.id, p.user, p.lock, p.amount, p.dueEpoch) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } diff --git a/pkg/morph/client/balance/mint.go b/pkg/morph/client/balance/mint.go index cda78c0772..73448da315 100644 --- a/pkg/morph/client/balance/mint.go +++ b/pkg/morph/client/balance/mint.go @@ -36,5 +36,6 @@ func (c *Client) Mint(p MintPrm) error { prm.SetArgs(p.to, p.amount, p.id) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } diff --git a/pkg/morph/client/balance/transfer.go b/pkg/morph/client/balance/transfer.go index 5206f69fa3..08fb05289a 100644 --- a/pkg/morph/client/balance/transfer.go +++ b/pkg/morph/client/balance/transfer.go @@ -39,7 +39,7 @@ func (c *Client) TransferX(p TransferPrm) error { prm.SetArgs(from, to, p.Amount, p.Details) prm.InvokePrmOptional = p.InvokePrmOptional - err = c.client.Invoke(prm) + _, err = c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", transferXMethod, err) } diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 050838648d..93a4176f99 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -174,8 +174,9 @@ func wrapFrostFSError(err error) error { } // Invoke invokes contract method by sending transaction into blockchain. +// Returns valid until block value. // Supported args types: int64, string, util.Uint160, []byte and bool. -func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error { +func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { start := time.Now() success := false defer func() { @@ -186,12 +187,12 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, defer c.switchLock.RUnlock() if c.inactive { - return ErrConnectionLost + return 0, ErrConnectionLost } txHash, vub, err := c.rpcActor.SendTunedCall(contract, method, nil, addFeeCheckerModifier(int64(fee)), args...) if err != nil { - return fmt.Errorf("could not invoke %s: %w", method, err) + return 0, fmt.Errorf("could not invoke %s: %w", method, err) } c.logger.Debug(logs.ClientNeoClientInvoke, @@ -200,7 +201,7 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, zap.Stringer("tx_hash", txHash.Reverse())) success = true - return nil + return vub, nil } // TestInvokeIterator invokes contract method returning an iterator and executes cb on each element. diff --git a/pkg/morph/client/container/delete.go b/pkg/morph/client/container/delete.go index b520120d20..c6cf7aa8d5 100644 --- a/pkg/morph/client/container/delete.go +++ b/pkg/morph/client/container/delete.go @@ -76,7 +76,7 @@ func (c *Client) Delete(p DeletePrm) error { prm.SetArgs(p.cnr, p.signature, p.key, p.token) prm.InvokePrmOptional = p.InvokePrmOptional - err := c.client.Invoke(prm) + _, err := c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err) } diff --git a/pkg/morph/client/container/eacl_set.go b/pkg/morph/client/container/eacl_set.go index 2d2ffb456f..c68104593a 100644 --- a/pkg/morph/client/container/eacl_set.go +++ b/pkg/morph/client/container/eacl_set.go @@ -85,7 +85,7 @@ func (c *Client) PutEACL(p PutEACLPrm) error { prm.SetArgs(p.table, p.sig, p.key, p.token) prm.InvokePrmOptional = p.InvokePrmOptional - err := c.client.Invoke(prm) + _, err := c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", setEACLMethod, err) } diff --git a/pkg/morph/client/container/estimations.go b/pkg/morph/client/container/estimations.go index 6adf674766..f288c63cf5 100644 --- a/pkg/morph/client/container/estimations.go +++ b/pkg/morph/client/container/estimations.go @@ -34,7 +34,7 @@ func (c *Client) StartEstimation(p StartEstimationPrm) error { prm.SetArgs(p.epoch) prm.InvokePrmOptional = p.InvokePrmOptional - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", startEstimationMethod, err) } return nil @@ -47,7 +47,7 @@ func (c *Client) StopEstimation(p StopEstimationPrm) error { prm.SetArgs(p.epoch) prm.InvokePrmOptional = p.InvokePrmOptional - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", stopEstimationMethod, err) } return nil diff --git a/pkg/morph/client/container/load.go b/pkg/morph/client/container/load.go index dcf89f73e9..b5263d7a63 100644 --- a/pkg/morph/client/container/load.go +++ b/pkg/morph/client/container/load.go @@ -41,7 +41,7 @@ func (c *Client) AnnounceLoad(p AnnounceLoadPrm) error { prm.SetArgs(p.a.Epoch(), binCnr, p.a.Value(), p.key) prm.InvokePrmOptional = p.InvokePrmOptional - err := c.client.Invoke(prm) + _, err := c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", putSizeMethod, err) } diff --git a/pkg/morph/client/container/put.go b/pkg/morph/client/container/put.go index 5c23eb36d6..ee323af008 100644 --- a/pkg/morph/client/container/put.go +++ b/pkg/morph/client/container/put.go @@ -116,7 +116,7 @@ func (c *Client) Put(p PutPrm) error { prm.SetMethod(method) prm.InvokePrmOptional = p.InvokePrmOptional - err := c.client.Invoke(prm) + _, err := c.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", method, err) } diff --git a/pkg/morph/client/frostfs/bind.go b/pkg/morph/client/frostfs/bind.go index 5b15d5c7b4..f7b91ddb84 100644 --- a/pkg/morph/client/frostfs/bind.go +++ b/pkg/morph/client/frostfs/bind.go @@ -41,7 +41,7 @@ func (x *Client) BindKeys(p BindKeysPrm) error { prm.SetArgs(p.scriptHash, p.keys) prm.InvokePrmOptional = p.InvokePrmOptional - err := x.client.Invoke(prm) + _, err := x.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", bindKeysMethod, err) } @@ -62,7 +62,7 @@ func (x *Client) UnbindKeys(args UnbindKeysPrm) error { prm.SetArgs(args.scriptHash, args.keys) prm.InvokePrmOptional = args.InvokePrmOptional - err := x.client.Invoke(prm) + _, err := x.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", unbindKeysMethod, err) } diff --git a/pkg/morph/client/frostfs/cheque.go b/pkg/morph/client/frostfs/cheque.go index e8f4f7f18c..016b56f8fe 100644 --- a/pkg/morph/client/frostfs/cheque.go +++ b/pkg/morph/client/frostfs/cheque.go @@ -43,7 +43,8 @@ func (x *Client) Cheque(p ChequePrm) error { prm.SetArgs(p.id, p.user, p.amount, p.lock) prm.InvokePrmOptional = p.InvokePrmOptional - return x.client.Invoke(prm) + _, err := x.client.Invoke(prm) + return err } // AlphabetUpdatePrm groups parameters of AlphabetUpdate operation. @@ -71,5 +72,6 @@ func (x *Client) AlphabetUpdate(p AlphabetUpdatePrm) error { prm.SetArgs(p.id, p.pubs) prm.InvokePrmOptional = p.InvokePrmOptional - return x.client.Invoke(prm) + _, err := x.client.Invoke(prm) + return err } diff --git a/pkg/morph/client/frostfsid/addrm_keys.go b/pkg/morph/client/frostfsid/addrm_keys.go index cbbd05142d..e9004f3664 100644 --- a/pkg/morph/client/frostfsid/addrm_keys.go +++ b/pkg/morph/client/frostfsid/addrm_keys.go @@ -36,7 +36,7 @@ func (x *Client) AddKeys(p CommonBindPrm) error { prm.SetArgs(p.ownerID, p.keys) prm.InvokePrmOptional = p.InvokePrmOptional - err := x.client.Invoke(prm) + _, err := x.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", addKeysMethod, err) } @@ -52,7 +52,7 @@ func (x *Client) RemoveKeys(args CommonBindPrm) error { prm.SetArgs(args.ownerID, args.keys) prm.InvokePrmOptional = args.InvokePrmOptional - err := x.client.Invoke(prm) + _, err := x.client.Invoke(prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", removeKeysMethod, err) } diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index 09ae09b510..21ba145d45 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -159,7 +159,8 @@ func (c *Client) SetConfig(p SetConfigPrm) error { prm.SetArgs(p.id, p.key, p.value) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } // RawNetworkParameter is a FrostFS network parameter which is transmitted but diff --git a/pkg/morph/client/netmap/innerring.go b/pkg/morph/client/netmap/innerring.go index 742165b9a3..d6f8c56b2c 100644 --- a/pkg/morph/client/netmap/innerring.go +++ b/pkg/morph/client/netmap/innerring.go @@ -34,7 +34,8 @@ func (c *Client) UpdateInnerRing(p UpdateIRPrm) error { prm.SetArgs(args) prm.InvokePrmOptional = p.InvokePrmOptional - return c.client.Invoke(prm) + _, err := c.client.Invoke(prm) + return err } // GetInnerRingList return current IR list. diff --git a/pkg/morph/client/netmap/new_epoch.go b/pkg/morph/client/netmap/new_epoch.go index 7a63f14d73..5f9f1ce5c8 100644 --- a/pkg/morph/client/netmap/new_epoch.go +++ b/pkg/morph/client/netmap/new_epoch.go @@ -17,7 +17,7 @@ func (c *Client) NewEpoch(epoch uint64, force bool) error { prm.SetArgs(epoch) prm.SetControlTX(force) - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) } return nil diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 4769c038c0..0ce2d3b428 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -36,7 +36,7 @@ func (c *Client) AddPeer(p AddPeerPrm) error { prm.SetArgs(p.nodeInfo.Marshal()) prm.InvokePrmOptional = p.InvokePrmOptional - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", method, err) } return nil diff --git a/pkg/morph/client/netmap/update_state.go b/pkg/morph/client/netmap/update_state.go index 02967453bb..a154590219 100644 --- a/pkg/morph/client/netmap/update_state.go +++ b/pkg/morph/client/netmap/update_state.go @@ -55,7 +55,7 @@ func (c *Client) UpdatePeerState(p UpdatePeerPrm) error { prm.SetArgs(int64(p.state), p.key) prm.InvokePrmOptional = p.InvokePrmOptional - if err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(prm); err != nil { return fmt.Errorf("could not invoke smart contract: %w", err) } return nil diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 0bbe526a67..ca3d37c2b9 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -355,13 +355,15 @@ func (c *Client) UpdateNeoFSAlphabetList(prm UpdateAlphabetListPrm) error { // blockchain. Fallback tx is a `RET`. If Notary support is not enabled // it fallbacks to a simple `Invoke()`. // +// Returns valid until block value. +// // `nonce` and `vub` are used only if notary is enabled. -func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { +func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() if c.inactive { - return ErrConnectionLost + return 0, ErrConnectionLost } if c.notary == nil { @@ -376,12 +378,12 @@ func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce ui // not expected to be signed by the current node. // // Considered to be used by non-IR nodes. -func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) error { +func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() if c.inactive { - return ErrConnectionLost + return 0, ErrConnectionLost } if c.notary == nil { @@ -440,10 +442,11 @@ func (c *Client) NotarySignAndInvokeTX(mainTx *transaction.Transaction) error { func (c *Client) notaryInvokeAsCommittee(method string, nonce, vub uint32, args ...any) error { designate := c.GetDesignateHash() - return c.notaryInvoke(true, true, designate, nonce, &vub, method, args...) + _, err := c.notaryInvoke(true, true, designate, nonce, &vub, method, args...) + return err } -func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, vub *uint32, method string, args ...any) error { +func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { start := time.Now() success := false defer func() { @@ -452,22 +455,22 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint alphabetList, err := c.notary.alphabetSource() if err != nil { - return err + return 0, err } until, err := c.getUntilValue(vub) if err != nil { - return err + return 0, err } cosigners, err := c.notaryCosigners(invokedByAlpha, alphabetList, committee) if err != nil { - return err + return 0, err } nAct, err := notary.NewActor(c.client, cosigners, c.acc) if err != nil { - return err + return 0, err } mainH, fbH, untilActual, err := nAct.Notarize(nAct.MakeTunedCall(contract, method, nil, func(r *result.Invoke, t *transaction.Transaction) error { @@ -482,7 +485,7 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint }, args...)) if err != nil && !alreadyOnChainError(err) { - return err + return 0, err } c.logger.Debug(logs.ClientNotaryRequestInvoked, @@ -492,7 +495,7 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint zap.String("fallback_hash", fbH.StringLE())) success = true - return nil + return until, nil } func (c *Client) notaryCosignersFromTx(mainTx *transaction.Transaction, alphabetList keys.PublicKeys) ([]actor.SignerAccount, error) { diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index 0531eacdf7..1dea4c4b77 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -120,6 +120,10 @@ func (i *InvokePrmOptional) IsControl() bool { return i.controlTX } +type InvokeRes struct { + VUB uint32 +} + // Invoke calls Invoke method of Client with static internal script hash and fee. // Supported args types are the same as in Client. // @@ -129,7 +133,9 @@ func (i *InvokePrmOptional) IsControl() bool { // // If fee for the operation executed using specified method is customized, then StaticClient uses it. // Otherwise, default fee is used. -func (s StaticClient) Invoke(prm InvokePrm) error { +func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) { + var res InvokeRes + var err error if s.tryNotary { if s.alpha { var ( @@ -146,24 +152,27 @@ func (s StaticClient) Invoke(prm InvokePrm) error { nonce, vub, err = s.client.CalculateNonceAndVUB(*prm.hash) } if err != nil { - return fmt.Errorf("could not calculate nonce and VUB for notary alphabet invoke: %w", err) + return InvokeRes{}, fmt.Errorf("could not calculate nonce and VUB for notary alphabet invoke: %w", err) } vubP = &vub } - return s.client.NotaryInvoke(s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) + res.VUB, err = s.client.NotaryInvoke(s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) + return res, err } - return s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, prm.method, prm.args...) + res.VUB, err = s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, prm.method, prm.args...) + return res, err } - return s.client.Invoke( + res.VUB, err = s.client.Invoke( s.scScriptHash, s.fee, prm.method, prm.args..., ) + return res, err } // TestInvokePrm groups parameters of the TestInvoke operation. From 2393d13e4d9c325aa64d45b134b6ddfff7ffdd01 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 8 Nov 2023 12:05:03 +0300 Subject: [PATCH 0139/1413] [#787] morph: Return VUB for IR service calls Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/netmap.go | 3 +- .../processors/netmap/handlers_test.go | 2 +- .../processors/netmap/process_epoch.go | 2 +- pkg/innerring/processors/netmap/processor.go | 2 +- pkg/innerring/processors/netmap/wrappers.go | 8 +++-- pkg/morph/client/container/delete.go | 15 ++++----- pkg/morph/client/netmap/new_epoch.go | 11 ++++--- pkg/morph/client/netmap/peer.go | 13 +++++--- pkg/morph/client/netmap/update_state.go | 9 +++--- pkg/morph/client/notary.go | 4 +-- pkg/morph/client/static.go | 19 ++++++++++-- pkg/services/control/ir/server/calls.go | 31 +++++++++++++------ 12 files changed, 78 insertions(+), 41 deletions(-) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index ebe152e47f..347121e560 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -418,7 +418,8 @@ func (c *cfg) updateNetMapState(stateSetter func(*nmClient.UpdatePeerPrm)) error prm.SetKey(c.key.PublicKey().Bytes()) stateSetter(&prm) - return c.cfgNetmap.wrapper.UpdatePeerState(prm) + _, err := c.cfgNetmap.wrapper.UpdatePeerState(prm) + return err } type netInfo struct { diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index fa87cff925..164ee41daf 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -399,7 +399,7 @@ func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) { return c.netmap, nil } -func (c *testNetmapClient) NewEpoch(epoch uint64, force bool) error { +func (c *testNetmapClient) NewEpoch(epoch uint64) error { c.newEpochs = append(c.newEpochs, epoch) return nil } diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index 01bfbae672..f3cb9837f9 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -77,7 +77,7 @@ func (np *Processor) processNewEpochTick() bool { nextEpoch := np.epochState.EpochCounter() + 1 np.log.Debug(logs.NetmapNextEpoch, zap.Uint64("value", nextEpoch)) - err := np.netmapClient.NewEpoch(nextEpoch, false) + err := np.netmapClient.NewEpoch(nextEpoch) if err != nil { np.log.Error(logs.NetmapCantInvokeNetmapNewEpoch, zap.Error(err)) return false diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index 6b8a24a62c..e8fb8721be 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -60,7 +60,7 @@ type ( EpochDuration() (uint64, error) MorphTxHeight(h util.Uint256) (res uint32, err error) NetMap() (*netmap.NetMap, error) - NewEpoch(epoch uint64, force bool) error + NewEpoch(epoch uint64) error MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error } diff --git a/pkg/innerring/processors/netmap/wrappers.go b/pkg/innerring/processors/netmap/wrappers.go index f9af703de5..618c1fb8f0 100644 --- a/pkg/innerring/processors/netmap/wrappers.go +++ b/pkg/innerring/processors/netmap/wrappers.go @@ -19,7 +19,8 @@ type netmapClientWrapper struct { } func (w *netmapClientWrapper) UpdatePeerState(p netmapclient.UpdatePeerPrm) error { - return w.netmapClient.UpdatePeerState(p) + _, err := w.netmapClient.UpdatePeerState(p) + return err } func (w *netmapClientWrapper) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { @@ -43,8 +44,9 @@ func (w *netmapClientWrapper) NetMap() (*netmap.NetMap, error) { return w.netmapClient.NetMap() } -func (w *netmapClientWrapper) NewEpoch(epoch uint64, force bool) error { - return w.netmapClient.NewEpoch(epoch, force) +func (w *netmapClientWrapper) NewEpoch(epoch uint64) error { + _, err := w.netmapClient.NewEpoch(epoch, 0, false) + return err } func (w *netmapClientWrapper) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) { diff --git a/pkg/morph/client/container/delete.go b/pkg/morph/client/container/delete.go index c6cf7aa8d5..20351b5707 100644 --- a/pkg/morph/client/container/delete.go +++ b/pkg/morph/client/container/delete.go @@ -26,7 +26,8 @@ func Delete(c *Client, witness core.RemovalWitness) error { prm.SetToken(tok.Marshal()) } - return c.Delete(prm) + _, err := c.Delete(prm) + return err } // DeletePrm groups parameters of Delete client operation. @@ -62,13 +63,13 @@ func (d *DeletePrm) SetKey(key []byte) { // Delete removes the container from FrostFS system // through Container contract call. // -// Returns any error encountered that caused +// Returns valid until block and any error encountered that caused // the removal to interrupt. // // If TryNotary is provided, calls notary contract. -func (c *Client) Delete(p DeletePrm) error { +func (c *Client) Delete(p DeletePrm) (uint32, error) { if len(p.signature) == 0 && !p.IsControl() { - return errNilArgument + return 0, errNilArgument } prm := client.InvokePrm{} @@ -76,9 +77,9 @@ func (c *Client) Delete(p DeletePrm) error { prm.SetArgs(p.cnr, p.signature, p.key, p.token) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := c.client.Invoke(prm) + res, err := c.client.Invoke(prm) if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err) + return 0, fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err) } - return nil + return res.VUB, nil } diff --git a/pkg/morph/client/netmap/new_epoch.go b/pkg/morph/client/netmap/new_epoch.go index 5f9f1ce5c8..a596b9991b 100644 --- a/pkg/morph/client/netmap/new_epoch.go +++ b/pkg/morph/client/netmap/new_epoch.go @@ -11,14 +11,17 @@ import ( // If `force` is true, this call is normally initiated by a control // service command and uses a control notary transaction internally // to ensure all nodes produce the same transaction with high probability. -func (c *Client) NewEpoch(epoch uint64, force bool) error { +// If vub > 0, vub will be used as valid until block value. +func (c *Client) NewEpoch(epoch uint64, vub uint32, force bool) (uint32, error) { prm := client.InvokePrm{} prm.SetMethod(newEpochMethod) prm.SetArgs(epoch) prm.SetControlTX(force) + prm.SetVUB(vub) - if _, err := c.client.Invoke(prm); err != nil { - return fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) + res, err := c.client.Invoke(prm) + if err != nil { + return 0, fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) } - return nil + return res.VUB, nil } diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 0ce2d3b428..30f51f699a 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -43,17 +43,20 @@ func (c *Client) AddPeer(p AddPeerPrm) error { } // ForceRemovePeer marks the given peer as offline via a notary control transaction. -func (c *Client) ForceRemovePeer(nodeInfo netmap.NodeInfo) error { +// If vub > 0, vub will be used as valid until block value. +func (c *Client) ForceRemovePeer(nodeInfo netmap.NodeInfo, vub uint32) (uint32, error) { if !c.client.WithNotary() { - return fmt.Errorf("peer can be forcefully removed only in notary environment") + return 0, fmt.Errorf("peer can be forcefully removed only in notary environment") } prm := UpdatePeerPrm{} prm.SetKey(nodeInfo.PublicKey()) prm.SetControlTX(true) + prm.SetVUB(vub) - if err := c.UpdatePeerState(prm); err != nil { - return fmt.Errorf("updating peer state: %v", err) + vub, err := c.UpdatePeerState(prm) + if err != nil { + return 0, fmt.Errorf("updating peer state: %v", err) } - return nil + return vub, nil } diff --git a/pkg/morph/client/netmap/update_state.go b/pkg/morph/client/netmap/update_state.go index a154590219..7c3a4e8cd2 100644 --- a/pkg/morph/client/netmap/update_state.go +++ b/pkg/morph/client/netmap/update_state.go @@ -36,7 +36,7 @@ func (u *UpdatePeerPrm) SetMaintenance() { } // UpdatePeerState changes peer status through Netmap contract call. -func (c *Client) UpdatePeerState(p UpdatePeerPrm) error { +func (c *Client) UpdatePeerState(p UpdatePeerPrm) (uint32, error) { method := updateStateMethod if c.client.WithNotary() && c.client.IsAlpha() { @@ -55,8 +55,9 @@ func (c *Client) UpdatePeerState(p UpdatePeerPrm) error { prm.SetArgs(int64(p.state), p.key) prm.InvokePrmOptional = p.InvokePrmOptional - if _, err := c.client.Invoke(prm); err != nil { - return fmt.Errorf("could not invoke smart contract: %w", err) + res, err := c.client.Invoke(prm) + if err != nil { + return 0, fmt.Errorf("could not invoke smart contract: %w", err) } - return nil + return res.VUB, nil } diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index ca3d37c2b9..dfdd7c03b1 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -378,7 +378,7 @@ func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce ui // not expected to be signed by the current node. // // Considered to be used by non-IR nodes. -func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { +func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, vubP *uint32, method string, args ...any) (uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -390,7 +390,7 @@ func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, return c.Invoke(contract, fee, method, args...) } - return c.notaryInvoke(false, false, contract, rand.Uint32(), nil, method, args...) + return c.notaryInvoke(false, false, contract, rand.Uint32(), vubP, method, args...) } // NotarySignAndInvokeTX signs and sends notary request that was received from diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index 1dea4c4b77..595e114213 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -100,6 +100,8 @@ type InvokePrmOptional struct { // It's only used by notary transactions and it affects only the // computation of `validUntilBlock` values. controlTX bool + // vub is used to set custom valid until block value. + vub uint32 } // SetHash sets optional hash of the transaction. @@ -120,6 +122,11 @@ func (i *InvokePrmOptional) IsControl() bool { return i.controlTX } +// SetVUB sets valid until block value. +func (i *InvokePrmOptional) SetVUB(v uint32) { + i.vub = v +} + type InvokeRes struct { VUB uint32 } @@ -136,11 +143,11 @@ type InvokeRes struct { func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) { var res InvokeRes var err error + var vubP *uint32 if s.tryNotary { if s.alpha { var ( nonce uint32 = 1 - vubP *uint32 vub uint32 err error ) @@ -158,11 +165,19 @@ func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) { vubP = &vub } + if prm.vub > 0 { + vubP = &prm.vub + } + res.VUB, err = s.client.NotaryInvoke(s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) return res, err } - res.VUB, err = s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, prm.method, prm.args...) + if prm.vub > 0 { + vubP = &prm.vub + } + + res.VUB, err = s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, vubP, prm.method, prm.args...) return res, err } diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 5379058401..4224ea81c0 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -53,9 +53,11 @@ func (s *Server) TickEpoch(_ context.Context, req *control.TickEpochRequest) (*c return nil, fmt.Errorf("getting current epoch: %w", err) } - if err := s.netmapClient.NewEpoch(epoch+1, true); err != nil { + vub, err := s.netmapClient.NewEpoch(epoch+1, req.GetBody().GetVub(), true) + if err != nil { return nil, fmt.Errorf("forcing new epoch: %w", err) } + resp.Body.Vub = vub if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -93,9 +95,11 @@ func (s *Server) RemoveNode(_ context.Context, req *control.RemoveNodeRequest) ( return nil, status.Error(codes.FailedPrecondition, "node is already offline") } - if err := s.netmapClient.ForceRemovePeer(nodeInfo); err != nil { + vub, err := s.netmapClient.ForceRemovePeer(nodeInfo, req.GetBody().GetVub()) + if err != nil { return nil, fmt.Errorf("forcing node removal: %w", err) } + resp.Body.Vub = vub if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -113,13 +117,15 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer if len(req.Body.GetContainerId()) > 0 && len(req.Body.GetOwner()) > 0 { return nil, status.Error(codes.InvalidArgument, "specify the owner and container at the same time is not allowed") } - + var vub uint32 if len(req.Body.GetContainerId()) > 0 { var containerID cid.ID if err := containerID.Decode(req.Body.GetContainerId()); err != nil { return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to parse container ID: %s", err.Error())) } - if err := s.removeContainer(containerID); err != nil { + var err error + vub, err = s.removeContainer(containerID, req.GetBody().GetVub()) + if err != nil { return nil, err } } else { @@ -138,14 +144,17 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer } for _, containerID := range cids { - if err := s.removeContainer(containerID); err != nil { + vub, err = s.removeContainer(containerID, req.GetBody().GetVub()) + if err != nil { return nil, err } } } resp := &control.RemoveContainerResponse{ - Body: &control.RemoveContainerResponse_Body{}, + Body: &control.RemoveContainerResponse_Body{ + Vub: vub, + }, } if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -153,13 +162,15 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer return resp, nil } -func (s *Server) removeContainer(containerID cid.ID) error { +func (s *Server) removeContainer(containerID cid.ID, vub uint32) (uint32, error) { var prm container.DeletePrm prm.SetCID(containerID[:]) prm.SetControlTX(true) + prm.SetVUB(vub) - if err := s.containerClient.Delete(prm); err != nil { - return fmt.Errorf("forcing container removal: %w", err) + vub, err := s.containerClient.Delete(prm) + if err != nil { + return 0, fmt.Errorf("forcing container removal: %w", err) } - return nil + return vub, nil } From c8a62ffeddf47ed2cf51305250ab9f0bb777b024 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 8 Nov 2023 12:28:34 +0300 Subject: [PATCH 0140/1413] [#787] morph: Calculate VUB and nonce when hash is nil Signed-off-by: Dmitrii Stepanov --- pkg/innerring/state.go | 2 +- pkg/morph/client/notary.go | 32 ++++++++++++++++++++++---------- pkg/morph/client/static.go | 4 ++-- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index f2521bd083..f5a03fa298 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -117,7 +117,7 @@ func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) erro ) if prm.Hash != nil { - nonce, vub, err = s.morphClient.CalculateNonceAndVUB(*prm.Hash) + nonce, vub, err = s.morphClient.CalculateNonceAndVUB(prm.Hash) if err != nil { return fmt.Errorf("could not calculate nonce and `validUntilBlock` values: %w", err) } diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index dfdd7c03b1..5b817a8056 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -289,7 +289,7 @@ func (c *Client) UpdateNotaryList(prm UpdateNotaryListPrm) error { panic(notaryNotEnabledPanicMsg) } - nonce, vub, err := c.CalculateNonceAndVUB(prm.hash) + nonce, vub, err := c.CalculateNonceAndVUB(&prm.hash) if err != nil { return fmt.Errorf("could not calculate nonce and `valicUntilBlock` values: %w", err) } @@ -337,7 +337,7 @@ func (c *Client) UpdateNeoFSAlphabetList(prm UpdateAlphabetListPrm) error { panic(notaryNotEnabledPanicMsg) } - nonce, vub, err := c.CalculateNonceAndVUB(prm.hash) + nonce, vub, err := c.CalculateNonceAndVUB(&prm.hash) if err != nil { return fmt.Errorf("could not calculate nonce and `valicUntilBlock` values: %w", err) } @@ -763,17 +763,19 @@ func CalculateNotaryDepositAmount(c *Client, gasMul, gasDiv int64) (fixedn.Fixed // CalculateNonceAndVUB calculates nonce and ValidUntilBlock values // based on transaction hash. -func (c *Client) CalculateNonceAndVUB(hash util.Uint256) (nonce uint32, vub uint32, err error) { +func (c *Client) CalculateNonceAndVUB(hash *util.Uint256) (nonce uint32, vub uint32, err error) { return c.calculateNonceAndVUB(hash, false) } // CalculateNonceAndVUBControl calculates nonce and rounded ValidUntilBlock values // based on transaction hash for use in control transactions. -func (c *Client) CalculateNonceAndVUBControl(hash util.Uint256) (nonce uint32, vub uint32, err error) { +func (c *Client) CalculateNonceAndVUBControl(hash *util.Uint256) (nonce uint32, vub uint32, err error) { return c.calculateNonceAndVUB(hash, true) } -func (c *Client) calculateNonceAndVUB(hash util.Uint256, roundBlockHeight bool) (nonce uint32, vub uint32, err error) { +// If hash specified, transaction's height and hash are used to compute VUB and nonce. +// If not, then current block height used to compute VUB and nonce. +func (c *Client) calculateNonceAndVUB(hash *util.Uint256, roundBlockHeight bool) (nonce uint32, vub uint32, err error) { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -785,11 +787,18 @@ func (c *Client) calculateNonceAndVUB(hash util.Uint256, roundBlockHeight bool) return 0, 0, nil } - nonce = binary.LittleEndian.Uint32(hash.BytesLE()) + var height uint32 - height, err := c.getTransactionHeight(hash) - if err != nil { - return 0, 0, fmt.Errorf("could not get transaction height: %w", err) + if hash != nil { + height, err = c.getTransactionHeight(*hash) + if err != nil { + return 0, 0, fmt.Errorf("could not get transaction height: %w", err) + } + } else { + height, err = c.rpcActor.GetBlockCount() + if err != nil { + return 0, 0, fmt.Errorf("could not get chain height: %w", err) + } } // For control transactions, we round down the block height to control the @@ -800,7 +809,10 @@ func (c *Client) calculateNonceAndVUB(hash util.Uint256, roundBlockHeight bool) height = height / inc * inc } - return nonce, height + c.notary.txValidTime, nil + if hash != nil { + return binary.LittleEndian.Uint32(hash.BytesLE()), height + c.notary.txValidTime, nil + } + return height + c.notary.txValidTime, height + c.notary.txValidTime, nil } func (c *Client) getTransactionHeight(h util.Uint256) (uint32, error) { diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index 595e114213..dfcf62b834 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -154,9 +154,9 @@ func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) { if prm.hash != nil { if prm.controlTX { - nonce, vub, err = s.client.CalculateNonceAndVUBControl(*prm.hash) + nonce, vub, err = s.client.CalculateNonceAndVUBControl(prm.hash) } else { - nonce, vub, err = s.client.CalculateNonceAndVUB(*prm.hash) + nonce, vub, err = s.client.CalculateNonceAndVUB(prm.hash) } if err != nil { return InvokeRes{}, fmt.Errorf("could not calculate nonce and VUB for notary alphabet invoke: %w", err) From 8088063195f971d10ad7bb7bf5497b214000c5ec Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 13 Nov 2023 17:22:31 +0300 Subject: [PATCH 0141/1413] [#787] netmap: Refactor `NewEpoch` method Split for user and control methods. Signed-off-by: Dmitrii Stepanov --- pkg/innerring/processors/netmap/wrappers.go | 3 +-- pkg/morph/client/netmap/new_epoch.go | 24 +++++++++++++++------ pkg/services/control/ir/server/calls.go | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/pkg/innerring/processors/netmap/wrappers.go b/pkg/innerring/processors/netmap/wrappers.go index 618c1fb8f0..e75fdaf403 100644 --- a/pkg/innerring/processors/netmap/wrappers.go +++ b/pkg/innerring/processors/netmap/wrappers.go @@ -45,8 +45,7 @@ func (w *netmapClientWrapper) NetMap() (*netmap.NetMap, error) { } func (w *netmapClientWrapper) NewEpoch(epoch uint64) error { - _, err := w.netmapClient.NewEpoch(epoch, 0, false) - return err + return w.netmapClient.NewEpoch(epoch) } func (w *netmapClientWrapper) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) { diff --git a/pkg/morph/client/netmap/new_epoch.go b/pkg/morph/client/netmap/new_epoch.go index a596b9991b..ded386c868 100644 --- a/pkg/morph/client/netmap/new_epoch.go +++ b/pkg/morph/client/netmap/new_epoch.go @@ -8,15 +8,27 @@ import ( // NewEpoch updates FrostFS epoch number through // Netmap contract call. -// If `force` is true, this call is normally initiated by a control -// service command and uses a control notary transaction internally -// to ensure all nodes produce the same transaction with high probability. -// If vub > 0, vub will be used as valid until block value. -func (c *Client) NewEpoch(epoch uint64, vub uint32, force bool) (uint32, error) { +func (c *Client) NewEpoch(epoch uint64) error { prm := client.InvokePrm{} prm.SetMethod(newEpochMethod) prm.SetArgs(epoch) - prm.SetControlTX(force) + + _, err := c.client.Invoke(prm) + if err != nil { + return fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) + } + return nil +} + +// NewEpochControl updates FrostFS epoch number through +// control notary transaction internally to ensure all +// nodes produce the same transaction with high probability. +// If vub > 0, vub will be used as valid until block value. +func (c *Client) NewEpochControl(epoch uint64, vub uint32) (uint32, error) { + prm := client.InvokePrm{} + prm.SetMethod(newEpochMethod) + prm.SetArgs(epoch) + prm.SetControlTX(true) prm.SetVUB(vub) res, err := c.client.Invoke(prm) diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 4224ea81c0..7baae03297 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -53,7 +53,7 @@ func (s *Server) TickEpoch(_ context.Context, req *control.TickEpochRequest) (*c return nil, fmt.Errorf("getting current epoch: %w", err) } - vub, err := s.netmapClient.NewEpoch(epoch+1, req.GetBody().GetVub(), true) + vub, err := s.netmapClient.NewEpochControl(epoch+1, req.GetBody().GetVub()) if err != nil { return nil, fmt.Errorf("forcing new epoch: %w", err) } From f04806ccd342be552cf172b4ebf856899fbc7a70 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 14 Nov 2023 14:21:58 +0300 Subject: [PATCH 0142/1413] [#506] container: Use user.ID in DeletionInfo response Signed-off-by: Evgenii Stratonikov --- pkg/core/container/storage.go | 3 ++- pkg/morph/client/container/deletion_info.go | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index f48fc73ac4..05e8fce49e 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -6,6 +6,7 @@ import ( frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" policyengine "git.frostfs.info/TrueCloudLab/policy-engine" ) @@ -24,7 +25,7 @@ type Container struct { // DelInfo contains info about removed container. type DelInfo struct { // Container owner. - Owner []byte + Owner user.ID // Epoch indicates when the container was removed. Epoch int diff --git a/pkg/morph/client/container/deletion_info.go b/pkg/morph/client/container/deletion_info.go index 40eb267d6e..61e26506d3 100644 --- a/pkg/morph/client/container/deletion_info.go +++ b/pkg/morph/client/container/deletion_info.go @@ -10,6 +10,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/mr-tron/base58" ) func (x *containerSource) DeletionInfo(cnr cid.ID) (*containercore.DelInfo, error) { @@ -51,11 +53,16 @@ func (c *Client) DeletionInfo(cid []byte) (*containercore.DelInfo, error) { return nil, fmt.Errorf("unexpected container stack item count (%s): %d", deletionInfoMethod, len(arr)) } - owner, err := client.BytesFromStackItem(arr[0]) + rawOwner, err := client.BytesFromStackItem(arr[0]) if err != nil { return nil, fmt.Errorf("could not get byte array of container (%s): %w", deletionInfoMethod, err) } + var owner user.ID + if err := owner.DecodeString(base58.Encode(rawOwner)); err != nil { + return nil, fmt.Errorf("could not decode container owner id (%s): %w", deletionInfoMethod, err) + } + epoch, err := client.IntFromStackItem(arr[1]) if err != nil { return nil, fmt.Errorf("could not get byte array of container signature (%s): %w", deletionInfoMethod, err) From a952a406a2077c603b9feeef9395cc7aabe0dc11 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 14 Nov 2023 14:47:31 +0300 Subject: [PATCH 0143/1413] [#506] container: Use uint64 for epoch type It is `uint64` in netmap source interfaces and other code. Signed-off-by: Evgenii Stratonikov --- pkg/core/container/storage.go | 2 +- pkg/morph/client/container/deletion_info.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index 05e8fce49e..ebafd22db3 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -28,7 +28,7 @@ type DelInfo struct { Owner user.ID // Epoch indicates when the container was removed. - Epoch int + Epoch uint64 } // Source is an interface that wraps diff --git a/pkg/morph/client/container/deletion_info.go b/pkg/morph/client/container/deletion_info.go index 61e26506d3..dda6bf98cc 100644 --- a/pkg/morph/client/container/deletion_info.go +++ b/pkg/morph/client/container/deletion_info.go @@ -63,13 +63,13 @@ func (c *Client) DeletionInfo(cid []byte) (*containercore.DelInfo, error) { return nil, fmt.Errorf("could not decode container owner id (%s): %w", deletionInfoMethod, err) } - epoch, err := client.IntFromStackItem(arr[1]) + epoch, err := client.BigIntFromStackItem(arr[1]) if err != nil { return nil, fmt.Errorf("could not get byte array of container signature (%s): %w", deletionInfoMethod, err) } return &containercore.DelInfo{ Owner: owner, - Epoch: int(epoch), + Epoch: epoch.Uint64(), }, nil } From f13f5d3b0f22dec9103f51c3d1330ff25131ba44 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 14 Nov 2023 14:27:34 +0300 Subject: [PATCH 0144/1413] [#506] node: Use DeletionInfo() method to get deleted container owner Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/container.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 9239df6400..e9a7079f1d 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -93,16 +93,12 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c subscribeToContainerRemoval(c, func(e event.Event) { ev := e.(containerEvent.DeleteSuccess) - // read owner of the removed container in order to update the listing cache. - // It's strange to read already removed container, but we can successfully hit - // the cache. - // TODO: use owner directly from the event after neofs-contract#256 will become resolved - cnr, err := cachedContainerStorage.Get(ev.ID) + cachedContainerStorage.handleRemoval(ev.ID) + info, err := cachedContainerStorage.DeletionInfo(ev.ID) if err == nil { - cachedContainerLister.update(cnr.Value.Owner(), ev.ID, false) + cachedContainerLister.update(info.Owner, ev.ID, false) } - cachedContainerStorage.handleRemoval(ev.ID) c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt, zap.Stringer("id", ev.ID), ) From b62008dacaa581c4f84bbdc11b0c739907b1ad15 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 14 Nov 2023 14:35:23 +0300 Subject: [PATCH 0145/1413] [#506] node: Invalidate `list` cache after container add/removal `update` already has problems mentioned in its doc-comment and the code itself is not straightforward. Invalidating cache altogether seems like a better option because we don't construct cache output ourselves (thus, no "impossible" results). Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/cache.go | 46 ++--------------------------------- cmd/frostfs-node/container.go | 4 +-- 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index 6a5d5d1827..ea5bdfda05 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -308,51 +308,9 @@ func (s ttlContainerLister) List(id *user.ID) ([]cid.ID, error) { return res, nil } -// updates cached list of owner's containers: cnr is added if flag is true, otherwise it's removed. -// Concurrent calls can lead to some races: -// - two parallel additions to missing owner's cache can lead to only one container to be cached -// - async cache value eviction can lead to idle addition -// -// All described race cases aren't critical since cache values expire anyway, we just try -// to increase cache actuality w/o huge overhead on synchronization. -func (s *ttlContainerLister) update(owner user.ID, cnr cid.ID, add bool) { +func (s *ttlContainerLister) invalidate(owner user.ID) { strOwner := owner.EncodeToString() - - val, ok := s.inner.cache.Peek(strOwner) - if !ok { - // we could cache the single cnr but in this case we will disperse - // with the Sidechain a lot - return - } - - if s.inner.ttl <= time.Since(val.t) { - return - } - - item := val.v - - item.mtx.Lock() - { - found := false - - for i := range item.list { - if found = item.list[i].Equals(cnr); found { - if !add { - item.list = append(item.list[:i], item.list[i+1:]...) - // if list became empty we don't remove the value from the cache - // since empty list is a correct value, and we don't want to insta - // re-request it from the Sidechain - } - - break - } - } - - if add && !found { - item.list = append(item.list, cnr) - } - } - item.mtx.Unlock() + s.inner.remove(strOwner) } type cachedIRFetcher struct { diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index e9a7079f1d..c7360a1bf1 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -74,7 +74,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c // creation success are most commonly tracked by polling GET op. cnr, err := cnrSrc.Get(ev.ID) if err == nil { - cachedContainerLister.update(cnr.Value.Owner(), ev.ID, true) + cachedContainerLister.invalidate(cnr.Value.Owner()) cachedContainerStorage.containerCache.set(ev.ID, cnr, nil) } else { // unlike removal, we expect successful receive of the container @@ -96,7 +96,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c cachedContainerStorage.handleRemoval(ev.ID) info, err := cachedContainerStorage.DeletionInfo(ev.ID) if err == nil { - cachedContainerLister.update(info.Owner, ev.ID, false) + cachedContainerLister.invalidate(info.Owner) } c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt, From f871f5cc6c2535646e529f9a8d1f5f3817d7459b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 8 Nov 2023 16:36:55 +0300 Subject: [PATCH 0146/1413] [#793] adm: Support new FrostFS ID contract Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/frostfsid_util.go | 41 +++++++++++++++++ .../modules/morph/frostfsid_util_test.go | 45 +++++++++++++++++++ .../modules/morph/initialize_deploy.go | 12 +++-- 3 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go new file mode 100644 index 0000000000..54a64a67a3 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go @@ -0,0 +1,41 @@ +package morph + +import ( + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/spf13/viper" +) + +// neo-go doesn't support []util.Uint160 type: +// https://github.com/nspcc-dev/neo-go/blob/v0.103.0/pkg/smartcontract/parameter.go#L262 +// Thus, return []smartcontract.Parameter. +func getFrostfsIDAuthorizedKeys(v *viper.Viper) ([]smartcontract.Parameter, error) { + var res []smartcontract.Parameter + + ks := v.GetStringSlice(frostfsIDAuthorizedKeysConfigKey) + for i := range ks { + h, err := address.StringToUint160(ks[i]) + if err == nil { + res = append(res, smartcontract.Parameter{Type: smartcontract.Hash160Type, Value: h}) + continue + } + + h, err = util.Uint160DecodeStringLE(ks[i]) + if err == nil { + res = append(res, smartcontract.Parameter{Type: smartcontract.Hash160Type, Value: h}) + continue + } + + pk, err := keys.NewPublicKeyFromString(ks[i]) + if err == nil { + res = append(res, smartcontract.Parameter{Type: smartcontract.Hash160Type, Value: pk.GetScriptHash()}) + continue + } + return nil, fmt.Errorf("frostfsid: #%d item in authorized_keys is invalid: '%s'", i, ks[i]) + } + return res, nil +} diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go new file mode 100644 index 0000000000..9982c0815e --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go @@ -0,0 +1,45 @@ +package morph + +import ( + "encoding/hex" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/spf13/viper" + "github.com/stretchr/testify/require" +) + +func TestFrostfsIDConfig(t *testing.T) { + pks := make([]*keys.PrivateKey, 4) + for i := range pks { + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + pks[i] = pk + } + + v := viper.New() + v.Set("frostfsid.authorized_keys", []string{ + pks[0].GetScriptHash().StringLE(), + address.Uint160ToString(pks[1].GetScriptHash()), + hex.EncodeToString(pks[2].PublicKey().UncompressedBytes()), + hex.EncodeToString(pks[3].PublicKey().Bytes()), + }) + + actual, err := getFrostfsIDAuthorizedKeys(v) + require.NoError(t, err) + require.Equal(t, len(pks), len(actual)) + for i := range pks { + require.Equal(t, smartcontract.Hash160Type, actual[i].Type) + require.Equal(t, pks[i].GetScriptHash(), actual[i].Value) + } + + t.Run("bad key", func(t *testing.T) { + v := viper.New() + v.Set("frostfsid.authorized_keys", []string{"abc"}) + + _, err := getFrostfsIDAuthorizedKeys(v) + require.Error(t, err) + }) +} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index f6100f4f9a..34475fe8b6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -31,6 +31,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/spf13/viper" ) const ( @@ -46,6 +47,8 @@ const ( proxyContract = "proxy" ) +const frostfsIDAuthorizedKeysConfigKey = "frostfsid.authorized_keys" + var ( contractList = []string{ balanceContract, @@ -535,9 +538,12 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an nnsCs.Hash, "container") case frostfsIDContract: - items = append(items, - c.Contracts[netmapContract].Hash, - c.Contracts[containerContract].Hash) + hs, err := getFrostfsIDAuthorizedKeys(viper.GetViper()) + if err != nil { + panic(err) + } + + items = append(items, hs) case netmapContract: md := getDefaultNetmapContractConfigMap() if method == updateMethodName { From c1ec6e33b45ee8f45636fb16020d0937aa718723 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 13 Nov 2023 12:41:40 +0300 Subject: [PATCH 0147/1413] [#793] adm: Always use committee as FrostFS ID owner Committee should be able to authorize everything, there are no other usecases for the frostfs-adm currently. Also, it somewhat eases configuration, because committee hash depends on the protocol configuration. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/frostfsid_util.go | 3 ++- .../internal/modules/morph/frostfsid_util_test.go | 14 +++++++++----- .../internal/modules/morph/initialize_deploy.go | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go index 54a64a67a3..248ad76b02 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go @@ -13,8 +13,9 @@ import ( // neo-go doesn't support []util.Uint160 type: // https://github.com/nspcc-dev/neo-go/blob/v0.103.0/pkg/smartcontract/parameter.go#L262 // Thus, return []smartcontract.Parameter. -func getFrostfsIDAuthorizedKeys(v *viper.Viper) ([]smartcontract.Parameter, error) { +func getFrostfsIDAuthorizedKeys(v *viper.Viper, defaultOwner util.Uint160) ([]smartcontract.Parameter, error) { var res []smartcontract.Parameter + res = append(res, smartcontract.Parameter{Type: smartcontract.Hash160Type, Value: defaultOwner}) ks := v.GetStringSlice(frostfsIDAuthorizedKeysConfigKey) for i := range ks { diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go index 9982c0815e..f4b6a66f66 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go @@ -7,6 +7,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/viper" "github.com/stretchr/testify/require" ) @@ -27,19 +28,22 @@ func TestFrostfsIDConfig(t *testing.T) { hex.EncodeToString(pks[3].PublicKey().Bytes()), }) - actual, err := getFrostfsIDAuthorizedKeys(v) + comm := util.Uint160{1, 2, 3} + actual, err := getFrostfsIDAuthorizedKeys(v, comm) require.NoError(t, err) - require.Equal(t, len(pks), len(actual)) + require.Equal(t, len(pks)+1, len(actual)) + require.Equal(t, smartcontract.Hash160Type, actual[0].Type) + require.Equal(t, comm, actual[0].Value) for i := range pks { - require.Equal(t, smartcontract.Hash160Type, actual[i].Type) - require.Equal(t, pks[i].GetScriptHash(), actual[i].Value) + require.Equal(t, smartcontract.Hash160Type, actual[i+1].Type) + require.Equal(t, pks[i].GetScriptHash(), actual[i+1].Value) } t.Run("bad key", func(t *testing.T) { v := viper.New() v.Set("frostfsid.authorized_keys", []string{"abc"}) - _, err := getFrostfsIDAuthorizedKeys(v) + _, err := getFrostfsIDAuthorizedKeys(v, comm) require.Error(t, err) }) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 34475fe8b6..5183114f9b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -538,7 +538,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an nnsCs.Hash, "container") case frostfsIDContract: - hs, err := getFrostfsIDAuthorizedKeys(viper.GetViper()) + hs, err := getFrostfsIDAuthorizedKeys(viper.GetViper(), c.CommitteeAcc.PublicKey().GetScriptHash()) if err != nil { panic(err) } From 364f835b7e203fb96805499ec6a50a30efcdbcf8 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 13 Nov 2023 11:41:11 +0300 Subject: [PATCH 0148/1413] [#740] logs: Add Loki Signed-off-by: Alexander Chuprov --- cmd/frostfs-node/config.go | 8 ++++ cmd/frostfs-node/config/logger/config.go | 54 +++++++++++++++++++++++- go.mod | 2 +- go.sum | 4 +- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index a41b73d92f..a43b59ab20 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -62,6 +62,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/state" + "git.frostfs.info/TrueCloudLab/frostfs-observability/logging/lokicore" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -72,6 +73,7 @@ import ( "github.com/panjf2000/ants/v2" "go.etcd.io/bbolt" "go.uber.org/zap" + "go.uber.org/zap/zapcore" "google.golang.org/grpc" ) @@ -577,6 +579,12 @@ func initCfg(appCfg *config.Config) *cfg { logPrm.SamplingHook = c.metricsCollector.LogMetrics().GetSamplingHook() log, err := logger.NewLogger(logPrm) fatalOnErr(err) + if loggerconfig.ToLokiConfig(appCfg).Enabled { + log.Logger = log.Logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { + lokiCore := lokicore.New(core, loggerconfig.ToLokiConfig(appCfg)) + return lokiCore + })) + } c.internals = initInternals(appCfg, log) diff --git a/cmd/frostfs-node/config/logger/config.go b/cmd/frostfs-node/config/logger/config.go index 78e4377a9a..02645c5430 100644 --- a/cmd/frostfs-node/config/logger/config.go +++ b/cmd/frostfs-node/config/logger/config.go @@ -1,12 +1,21 @@ package loggerconfig import ( + "os" + "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + "git.frostfs.info/TrueCloudLab/frostfs-observability/logging/lokicore/loki" ) const ( // LevelDefault is a default logger level. - LevelDefault = "info" + LevelDefault = "info" + subsection = "logger" + lokiSubsection = "loki" + AddressDefault = "localhost:3100" + BatchEntriesNumberDefault = 100 + BatchWaitDefault = time.Second ) // Level returns the value of "level" config parameter @@ -15,7 +24,7 @@ const ( // Returns LevelDefault if the value is not a non-empty string. func Level(c *config.Config) string { v := config.StringSafe( - c.Sub("logger"), + c.Sub(subsection), "level", ) if v != "" { @@ -24,3 +33,44 @@ func Level(c *config.Config) string { return LevelDefault } + +// ToLokiConfig extracts loki config. +func ToLokiConfig(c *config.Config) loki.Config { + hostname, _ := os.Hostname() + return loki.Config{ + Enabled: config.BoolSafe(c.Sub(subsection).Sub(lokiSubsection), "enabled"), + BatchWait: getBatchWait(c), + BatchEntriesNumber: getBatchEntriesNumber(c), + Endpoint: getEndpoint(c), + Labels: map[string]string{ + "hostname": hostname, + }, + } +} + +func getBatchWait(c *config.Config) time.Duration { + v := config.DurationSafe(c.Sub(subsection).Sub(lokiSubsection), "max_batch_delay") + if v > 0 { + return v + } + + return BatchWaitDefault +} + +func getBatchEntriesNumber(c *config.Config) int { + v := config.IntSafe(c.Sub(subsection).Sub(lokiSubsection), "max_batch_size") + if v > 0 { + return int(v) + } + + return BatchEntriesNumberDefault +} + +func getEndpoint(c *config.Config) string { + v := config.StringSafe(c.Sub(subsection).Sub(lokiSubsection), "endpoint") + if v != "" { + return v + } + + return AddressDefault +} diff --git a/go.mod b/go.mod index 4f6505e878..5c22fdfc2d 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 - git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 + git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231101082425-5eee1a733432 diff --git a/go.sum b/go.sum index 05a870b807..806648251a 100644 --- a/go.sum +++ b/go.sum @@ -730,8 +730,8 @@ git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845a git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989/go.mod h1:PxsAxe6J4hyYJoU6hyYxD9q5K/DFxdquKHL1BrRaGkg= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6 h1:aGQ6QaAnTerQ5Dq5b2/f9DUQtSqPkZZ/bkMx/HKuLCo= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20230531082742-c97d21411eb6/go.mod h1:W8Nn08/l6aQ7UlIbpF7FsQou7TVpcRD1ZT1KG4TrFhE= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d h1:KVHsNsEoedQ1+f+eDq88AFKkLePGfnygt4bcUQrCgPw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= From fd9128d0513d86503e88b5cab4f4710072f0d3a9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 10 Nov 2023 11:40:06 +0300 Subject: [PATCH 0149/1413] [#800] node: eACL -> APE converter Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/util/ape.go | 32 +- cmd/frostfs-cli/modules/util/ape_test.go | 25 +- go.mod | 2 +- go.sum | 4 +- internal/ape/converter.go | 246 ++++++++++++ internal/ape/converter_test.go | 470 +++++++++++++++++++++++ 6 files changed, 749 insertions(+), 30 deletions(-) create mode 100644 internal/ape/converter.go create mode 100644 internal/ape/converter_test.go diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 8815464506..47ce37bb7e 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -6,6 +6,7 @@ import ( "strings" policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/flynn-archive/go-shlex" ) @@ -65,7 +66,7 @@ func parseRuleLexemes(r *policyengine.Rule, lexemes []string) error { return err } - r.Action, err = parseAction(lexemes[1]) + r.Actions, err = parseAction(lexemes[1]) if err != nil { return err } @@ -75,7 +76,7 @@ func parseRuleLexemes(r *policyengine.Rule, lexemes []string) error { return err } - r.Resource, err = parseResource(lexemes[len(lexemes)-1]) + r.Resources, err = parseResource(lexemes[len(lexemes)-1]) return err } @@ -100,41 +101,42 @@ func parseStatus(lexeme string) (policyengine.Status, error) { } } -func parseAction(lexeme string) ([]string, error) { +func parseAction(lexeme string) (policyengine.Actions, error) { switch strings.ToLower(lexeme) { case "object.put": - return []string{"native:PutObject"}, nil + return policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, nil case "object.get": - return []string{"native:GetObject"}, nil + return policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, nil case "object.head": - return []string{"native:HeadObject"}, nil + return policyengine.Actions{Names: []string{nativeschema.MethodHeadObject}}, nil case "object.delete": - return []string{"native:DeleteObject"}, nil + return policyengine.Actions{Names: []string{nativeschema.MethodDeleteObject}}, nil case "object.search": - return []string{"native:SearchObject"}, nil + return policyengine.Actions{Names: []string{nativeschema.MethodSearchObject}}, nil case "object.range": - return []string{"native:RangeObject"}, nil + return policyengine.Actions{Names: []string{nativeschema.MethodRangeObject}}, nil case "object.hash": - return []string{"native:HashObject"}, nil + return policyengine.Actions{Names: []string{nativeschema.MethodHashObject}}, nil default: } - return nil, fmt.Errorf("%w: %s", errUnknownOperation, lexeme) + return policyengine.Actions{}, fmt.Errorf("%w: %s", errUnknownOperation, lexeme) } -func parseResource(lexeme string) ([]string, error) { - return []string{fmt.Sprintf("native:::object/%s", lexeme)}, nil +func parseResource(lexeme string) (policyengine.Resources, error) { + if lexeme == "*" { + return policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, nil + } + return policyengine.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, lexeme)}}, nil } const ( ObjectResource = "object.resource" ObjectRequest = "object.request" - ObjectActor = "object.actor" ) var typeToCondObject = map[string]policyengine.ObjectType{ ObjectResource: policyengine.ObjectResource, ObjectRequest: policyengine.ObjectRequest, - ObjectActor: policyengine.ObjectActor, } func parseConditions(lexemes []string) ([]policyengine.Condition, error) { diff --git a/cmd/frostfs-cli/modules/util/ape_test.go b/cmd/frostfs-cli/modules/util/ape_test.go index e71544a9bf..b2e9d1d872 100644 --- a/cmd/frostfs-cli/modules/util/ape_test.go +++ b/cmd/frostfs-cli/modules/util/ape_test.go @@ -4,6 +4,7 @@ import ( "testing" policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" ) @@ -19,8 +20,8 @@ func TestParseAPERule(t *testing.T) { rule: "allow Object.Put *", expectRule: policyengine.Rule{ Status: policyengine.Allow, - Action: []string{"native:PutObject"}, - Resource: []string{"native:::object/*"}, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, Condition: []policyengine.Condition{}, }, }, @@ -29,8 +30,8 @@ func TestParseAPERule(t *testing.T) { rule: "deny Object.Put *", expectRule: policyengine.Rule{ Status: policyengine.AccessDenied, - Action: []string{"native:PutObject"}, - Resource: []string{"native:::object/*"}, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, Condition: []policyengine.Condition{}, }, }, @@ -39,8 +40,8 @@ func TestParseAPERule(t *testing.T) { rule: "deny:QuotaLimitReached Object.Put *", expectRule: policyengine.Rule{ Status: policyengine.QuotaLimitReached, - Action: []string{"native:PutObject"}, - Resource: []string{"native:::object/*"}, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, Condition: []policyengine.Condition{}, }, }, @@ -48,9 +49,9 @@ func TestParseAPERule(t *testing.T) { name: "Valid allow rule with conditions", rule: "allow Object.Get Object.Resource:Department=HR Object.Request:Actor!=ownerA *", expectRule: policyengine.Rule{ - Status: policyengine.Allow, - Action: []string{"native:GetObject"}, - Resource: []string{"native:::object/*"}, + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, Condition: []policyengine.Condition{ { Op: policyengine.CondStringEquals, @@ -71,9 +72,9 @@ func TestParseAPERule(t *testing.T) { name: "Valid rule with conditions with action detail", rule: "deny:QuotaLimitReached Object.Get Object.Resource:Department=HR Object.Request:Actor!=ownerA *", expectRule: policyengine.Rule{ - Status: policyengine.QuotaLimitReached, - Action: []string{"native:GetObject"}, - Resource: []string{"native:::object/*"}, + Status: policyengine.QuotaLimitReached, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, Condition: []policyengine.Condition{ { Op: policyengine.CondStringEquals, diff --git a/go.mod b/go.mod index 5c22fdfc2d..5def2fade8 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231101082425-5eee1a733432 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231114100951-38985e4ec86b git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index 806648251a..5c30a75e44 100644 --- a/go.sum +++ b/go.sum @@ -736,8 +736,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231101082425-5eee1a733432 h1:z0PqdiEIHXK2qC83e6pmxUZ5peP9CIL0Bh5mP/d+4Xc= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231101082425-5eee1a733432/go.mod h1:qf3B9hSz6gCMfcfvqkhTu5ak+Gx2R+wo4Hc87LnKxPg= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231114100951-38985e4ec86b h1:io+LMCjNfP1IA7Jku7QVzAnlBjJXDNBNrHw1fpbsoeI= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231114100951-38985e4ec86b/go.mod h1:qf3B9hSz6gCMfcfvqkhTu5ak+Gx2R+wo4Hc87LnKxPg= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/internal/ape/converter.go b/internal/ape/converter.go new file mode 100644 index 0000000000..e268626e6c --- /dev/null +++ b/internal/ape/converter.go @@ -0,0 +1,246 @@ +package ape + +import ( + "encoding/hex" + "fmt" + + v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" +) + +type ConvertEACLError struct { + nested error +} + +func (e *ConvertEACLError) Error() string { + if e == nil { + return "" + } + return fmt.Sprintf("failed to convert eACL table to policy engine chain: %s", e.nested.Error()) +} + +func (e *ConvertEACLError) Unwrap() error { + if e == nil { + return nil + } + return e.nested +} + +// ConvertEACLToAPE converts eacl.Table to policyengine.Chain. +func ConvertEACLToAPE(eaclTable *eacl.Table) (*policyengine.Chain, error) { + if eaclTable == nil { + return nil, nil + } + res := &policyengine.Chain{} + + resource := getResource(eaclTable) + + for _, eaclRecord := range eaclTable.Records() { + if len(eaclRecord.Targets()) == 0 { + // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 + // and https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L36 + // such record doesn't have any effect + continue + } + + st, err := actionToStatus(eaclRecord.Action()) + if err != nil { + return nil, err + } + act, err := operationToAction(eaclRecord.Operation()) + if err != nil { + return nil, err + } + + if len(eaclRecord.Filters()) == 0 { + res.Rules = appendTargetsOnly(res.Rules, st, act, resource, eaclRecord.Targets()) + } else { + res.Rules, err = appendTargetsAndFilters(res.Rules, st, act, resource, eaclRecord.Targets(), eaclRecord.Filters()) + if err != nil { + return nil, err + } + } + } + + return res, nil +} + +func appendTargetsOnly(source []policyengine.Rule, st policyengine.Status, act policyengine.Actions, res policyengine.Resources, targets []eacl.Target) []policyengine.Rule { + // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 + // role OR public key must be equal + rule := policyengine.Rule{ + Status: st, + Actions: act, + Resources: res, + Any: true, + } + for _, target := range targets { + var roleCondition policyengine.Condition + roleCondition.Object = policyengine.ObjectRequest + roleCondition.Key = nativeschema.PropertyKeyActorRole + roleCondition.Value = target.Role().String() + roleCondition.Op = policyengine.CondStringEquals + rule.Condition = append(rule.Condition, roleCondition) + + for _, binKey := range target.BinaryKeys() { + var pubKeyCondition policyengine.Condition + pubKeyCondition.Object = policyengine.ObjectRequest + pubKeyCondition.Key = nativeschema.PropertyKeyActorPublicKey + pubKeyCondition.Value = hex.EncodeToString(binKey) + pubKeyCondition.Op = policyengine.CondStringEquals + rule.Condition = append(rule.Condition, pubKeyCondition) + } + } + return append(source, rule) +} + +func appendTargetsAndFilters(source []policyengine.Rule, st policyengine.Status, act policyengine.Actions, res policyengine.Resources, + targets []eacl.Target, filters []eacl.Filter, +) ([]policyengine.Rule, error) { + // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 + // role OR public key must be equal + // so filters are repeated for each role and public key + var err error + for _, target := range targets { + rule := policyengine.Rule{ + Status: st, + Actions: act, + Resources: res, + } + var roleCondition policyengine.Condition + roleCondition.Object = policyengine.ObjectRequest + roleCondition.Key = nativeschema.PropertyKeyActorRole + roleCondition.Value = target.Role().String() + roleCondition.Op = policyengine.CondStringEquals + + rule.Condition = append(rule.Condition, roleCondition) + rule.Condition, err = appendFilters(rule.Condition, filters) + if err != nil { + return nil, err + } + + source = append(source, rule) + + for _, binKey := range target.BinaryKeys() { + rule := policyengine.Rule{ + Status: st, + Actions: act, + Resources: res, + } + var pubKeyCondition policyengine.Condition + pubKeyCondition.Object = policyengine.ObjectRequest + pubKeyCondition.Key = nativeschema.PropertyKeyActorPublicKey + pubKeyCondition.Value = hex.EncodeToString(binKey) + pubKeyCondition.Op = policyengine.CondStringEquals + + rule.Condition = append(rule.Condition, pubKeyCondition) + rule.Condition, err = appendFilters(rule.Condition, filters) + if err != nil { + return nil, err + } + + source = append(source, rule) + } + } + + return source, nil +} + +func appendFilters(source []policyengine.Condition, filters []eacl.Filter) ([]policyengine.Condition, error) { + for _, filter := range filters { + var cond policyengine.Condition + var isObject bool + if filter.From() == eacl.HeaderFromObject { + cond.Object = policyengine.ObjectResource + isObject = true + } else if filter.From() == eacl.HeaderFromRequest { + cond.Object = policyengine.ObjectRequest + } else { + return nil, &ConvertEACLError{nested: fmt.Errorf("unknown filter from: %d", filter.From())} + } + + if filter.Matcher() == eacl.MatchStringEqual { + cond.Op = policyengine.CondStringEquals + } else if filter.Matcher() == eacl.MatchStringNotEqual { + cond.Op = policyengine.CondStringNotEquals + } else { + return nil, &ConvertEACLError{nested: fmt.Errorf("unknown filter matcher: %d", filter.Matcher())} + } + + cond.Key = eaclKeyToAPEKey(filter.Key(), isObject) + cond.Value = filter.Value() + + source = append(source, cond) + } + return source, nil +} + +func eaclKeyToAPEKey(key string, isObject bool) string { + if !isObject { + return key + } + switch key { + default: + return key + case v2acl.FilterObjectVersion: + return nativeschema.PropertyKeyObjectVersion + case v2acl.FilterObjectID: + return nativeschema.PropertyKeyObjectID + case v2acl.FilterObjectContainerID: + return nativeschema.PropertyKeyObjectContainerID + case v2acl.FilterObjectOwnerID: + return nativeschema.PropertyKeyObjectOwnerID + case v2acl.FilterObjectCreationEpoch: + return nativeschema.PropertyKeyObjectCreationEpoch + case v2acl.FilterObjectPayloadLength: + return nativeschema.PropertyKeyObjectPayloadLength + case v2acl.FilterObjectPayloadHash: + return nativeschema.PropertyKeyObjectPayloadHash + case v2acl.FilterObjectType: + return nativeschema.PropertyKeyObjectType + case v2acl.FilterObjectHomomorphicHash: + return nativeschema.PropertyKeyObjectHomomorphicHash + } +} + +func getResource(eaclTable *eacl.Table) policyengine.Resources { + cnrID, isSet := eaclTable.CID() + if isSet { + return policyengine.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, + } + } + return policyengine.Resources{ + Names: []string{nativeschema.ResourceFormatRootObjects}, + } +} + +func actionToStatus(a eacl.Action) (policyengine.Status, error) { + switch a { + case eacl.ActionAllow: + return policyengine.Allow, nil + case eacl.ActionDeny: + return policyengine.AccessDenied, nil + default: + return policyengine.NoRuleFound, &ConvertEACLError{nested: fmt.Errorf("unknown action: %d", a)} + } +} + +var eaclOperationToEngineAction = map[eacl.Operation]policyengine.Actions{ + eacl.OperationGet: {Names: []string{nativeschema.MethodGetObject}}, + eacl.OperationHead: {Names: []string{nativeschema.MethodHeadObject}}, + eacl.OperationPut: {Names: []string{nativeschema.MethodPutObject}}, + eacl.OperationDelete: {Names: []string{nativeschema.MethodDeleteObject}}, + eacl.OperationSearch: {Names: []string{nativeschema.MethodSearchObject}}, + eacl.OperationRange: {Names: []string{nativeschema.MethodRangeObject}}, + eacl.OperationRangeHash: {Names: []string{nativeschema.MethodHashObject}}, +} + +func operationToAction(op eacl.Operation) (policyengine.Actions, error) { + if v, ok := eaclOperationToEngineAction[op]; ok { + return v, nil + } + return policyengine.Actions{}, &ConvertEACLError{nested: fmt.Errorf("unknown operation: %d", op)} +} diff --git a/internal/ape/converter_test.go b/internal/ape/converter_test.go new file mode 100644 index 0000000000..bf6205ec95 --- /dev/null +++ b/internal/ape/converter_test.go @@ -0,0 +1,470 @@ +package ape + +import ( + "encoding/hex" + "fmt" + "testing" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestEACLTableWithoutRecords(t *testing.T) { + t.Parallel() + + tb := eacl.NewTable() + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + req := &testRequest{ + res: &testResource{name: nativeschema.ResourceFormatRootObjects}, + } + + compare(t, tb, vu, ch, req) + + cnrID := cidtest.ID() + tb.SetCID(cnrID) + vu.WithContainerID(&cnrID) + req.res.name = fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()) + + ch, err = ConvertEACLToAPE(tb) + require.NoError(t, err) + + compare(t, tb, vu, ch, req) +} + +func TestNoTargets(t *testing.T) { + t.Parallel() + for _, act := range []eacl.Action{eacl.ActionAllow, eacl.ActionDeny} { + cnrID := cidtest.ID() + tb := eacl.NewTable() + tb.SetCID(cnrID) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + vu.WithContainerID(&cnrID) + vu.WithRole(eacl.RoleOthers) + + // deny delete without role or key specified + record := eacl.NewRecord() + record.SetAction(act) + record.SetOperation(eacl.OperationDelete) + record.AddObjectContainerIDFilter(eacl.MatchStringEqual, cnrID) + + tb.AddRecord(record) + + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + req := &testRequest{ + props: map[string]string{ + nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + }, + res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, + } + compare(t, tb, vu, ch, req) + } +} + +func TestNoFilters(t *testing.T) { + t.Parallel() + + t.Run("target match by role only", func(t *testing.T) { + t.Parallel() + + for _, act := range []eacl.Action{eacl.ActionAllow, eacl.ActionDeny} { + cnrID := cidtest.ID() + tb := eacl.NewTable() + tb.SetCID(cnrID) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + vu.WithContainerID(&cnrID) + vu.WithRole(eacl.RoleOthers) + + // allow/deny for OTHERS + record := eacl.NewRecord() + record.SetAction(act) + record.SetOperation(eacl.OperationDelete) + + target := eacl.NewTarget() + target.SetRole(eacl.RoleOthers) + record.SetTargets(*target) + + tb.AddRecord(record) + + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + req := &testRequest{ + props: map[string]string{ + nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + }, + res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, + } + compare(t, tb, vu, ch, req) + } + }) + + t.Run("target match by role and public key", func(t *testing.T) { + t.Parallel() + + for _, act := range []eacl.Action{eacl.ActionAllow, eacl.ActionDeny} { + cnrID := cidtest.ID() + tb := eacl.NewTable() + tb.SetCID(cnrID) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + vu.WithContainerID(&cnrID) + vu.WithRole(eacl.RoleOthers) + + // allow/deny for OTHERS + record := eacl.NewRecord() + record.SetAction(act) + record.SetOperation(eacl.OperationDelete) + + p1, err := keys.NewPrivateKey() + require.NoError(t, err) + p2, err := keys.NewPrivateKey() + require.NoError(t, err) + + vu.WithSenderKey(p2.PublicKey().Bytes()) + + target := eacl.NewTarget() + target.SetRole(eacl.RoleOthers) + target.SetBinaryKeys([][]byte{p1.PublicKey().Bytes(), p2.PublicKey().Bytes()}) + record.SetTargets(*target) + + tb.AddRecord(record) + + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + req := &testRequest{ + props: map[string]string{ + nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + nativeschema.PropertyKeyActorPublicKey: string(p2.PublicKey().Bytes()), + }, + res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, + } + compare(t, tb, vu, ch, req) + } + }) + + t.Run("target match by public key only", func(t *testing.T) { + t.Parallel() + + for _, act := range []eacl.Action{eacl.ActionAllow, eacl.ActionDeny} { + cnrID := cidtest.ID() + tb := eacl.NewTable() + tb.SetCID(cnrID) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + vu.WithContainerID(&cnrID) + + // allow/deny for OTHERS + record := eacl.NewRecord() + record.SetAction(act) + record.SetOperation(eacl.OperationDelete) + + p1, err := keys.NewPrivateKey() + require.NoError(t, err) + p2, err := keys.NewPrivateKey() + require.NoError(t, err) + + vu.WithSenderKey(p2.PublicKey().Bytes()) + + target := eacl.NewTarget() + target.SetRole(eacl.RoleOthers) + target.SetBinaryKeys([][]byte{p1.PublicKey().Bytes(), p2.PublicKey().Bytes()}) + record.SetTargets(*target) + + tb.AddRecord(record) + + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + req := &testRequest{ + props: map[string]string{ + nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(p2.PublicKey().Bytes()), + }, + res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, + } + compare(t, tb, vu, ch, req) + } + }) + + t.Run("target doesn't match", func(t *testing.T) { + t.Parallel() + + for _, act := range []eacl.Action{eacl.ActionAllow, eacl.ActionDeny} { + cnrID := cidtest.ID() + tb := eacl.NewTable() + tb.SetCID(cnrID) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + vu.WithContainerID(&cnrID) + vu.WithRole(eacl.RoleSystem) + + // allow/deny for OTHERS + record := eacl.NewRecord() + record.SetAction(act) + record.SetOperation(eacl.OperationDelete) + + target := eacl.NewTarget() + target.SetRole(eacl.RoleOthers) + record.SetTargets(*target) + + tb.AddRecord(record) + + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + req := &testRequest{ + props: map[string]string{ + nativeschema.PropertyKeyActorRole: eacl.RoleSystem.String(), + }, + res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, + } + compare(t, tb, vu, ch, req) + } + }) +} + +func TestWithFilters(t *testing.T) { + t.Parallel() + + t.Run("object attributes", func(t *testing.T) { + t.Parallel() + + const attrKey = "attribute_1" + const attrValue = "attribute_1_value" + + for _, act := range []eacl.Action{eacl.ActionAllow, eacl.ActionDeny} { + cnrID := cidtest.ID() + tb := eacl.NewTable() + tb.SetCID(cnrID) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + vu.WithContainerID(&cnrID) + vu.WithRole(eacl.RoleOthers) + vu.WithHeaderSource(&testHeaderSource{ + headers: map[eacl.FilterHeaderType][]eacl.Header{ + eacl.HeaderFromObject: {&testHeader{key: attrKey, value: attrValue}}, + }, + }) + + // allow/deny for OTHERS + record := eacl.NewRecord() + record.SetAction(act) + record.SetOperation(eacl.OperationDelete) + + target := eacl.NewTarget() + target.SetRole(eacl.RoleOthers) + record.SetTargets(*target) + + record.AddObjectAttributeFilter(eacl.MatchStringEqual, attrKey, attrValue) + + tb.AddRecord(record) + + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + req := &testRequest{ + props: map[string]string{ + nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + }, + res: &testResource{ + name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()), + props: map[string]string{ + attrKey: attrValue, + }, + }, + } + compare(t, tb, vu, ch, req) + } + }) + + t.Run("request attributes", func(t *testing.T) { + t.Parallel() + + const attrKey = "attribute_1" + const attrValue = "attribute_1_value" + + for _, act := range []eacl.Action{eacl.ActionAllow, eacl.ActionDeny} { + cnrID := cidtest.ID() + tb := eacl.NewTable() + tb.SetCID(cnrID) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + vu.WithContainerID(&cnrID) + vu.WithRole(eacl.RoleOthers) + vu.WithHeaderSource(&testHeaderSource{ + headers: map[eacl.FilterHeaderType][]eacl.Header{ + eacl.HeaderFromRequest: {&testHeader{key: attrKey, value: attrValue}}, + }, + }) + + // allow/deny for OTHERS + record := eacl.NewRecord() + record.SetAction(act) + record.SetOperation(eacl.OperationDelete) + + target := eacl.NewTarget() + target.SetRole(eacl.RoleOthers) + record.SetTargets(*target) + + record.AddFilter(eacl.HeaderFromRequest, eacl.MatchStringEqual, attrKey, attrValue) + + tb.AddRecord(record) + + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + req := &testRequest{ + props: map[string]string{ + nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + attrKey: attrValue, + }, + res: &testResource{ + name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()), + }, + } + compare(t, tb, vu, ch, req) + } + }) +} + +func TestNoHeader(t *testing.T) { + t.Skip("Should pass after https://git.frostfs.info/TrueCloudLab/policy-engine/issues/8#issuecomment-26126") + + t.Parallel() + + const attrKey = "attribute_1" + cnrID := cidtest.ID() + tb := eacl.NewTable() + tb.SetCID(cnrID) + + vu := &eacl.ValidationUnit{} + vu.WithEACLTable(tb) + vu.WithContainerID(&cnrID) + vu.WithRole(eacl.RoleOthers) + vu.WithHeaderSource(&testHeaderSource{ + headers: map[eacl.FilterHeaderType][]eacl.Header{ + eacl.HeaderFromRequest: {}, + }, + }) + + // allow/deny for OTHERS + record := eacl.NewRecord() + record.SetAction(eacl.ActionDeny) + record.SetOperation(eacl.OperationDelete) + + target := eacl.NewTarget() + target.SetRole(eacl.RoleOthers) + record.SetTargets(*target) + + record.AddFilter(eacl.HeaderFromRequest, eacl.MatchStringEqual, attrKey, "") + + tb.AddRecord(record) + + ch, err := ConvertEACLToAPE(tb) + require.NoError(t, err) + + req := &testRequest{ + props: map[string]string{ + nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + }, + res: &testResource{ + name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()), + }, + } + compare(t, tb, vu, ch, req) +} + +func compare(t *testing.T, eaclTable *eacl.Table, vu *eacl.ValidationUnit, ch *policyengine.Chain, req *testRequest) { + validator := eacl.NewValidator() + for eaclOp, apeOp := range eaclOperationToEngineAction { + vu.WithOperation(eaclOp) + req.op = apeOp.Names[0] + + eaclAct, recordFound := validator.CalculateAction(vu) + apeSt, ruleFound := ch.Match(req) + + require.Equal(t, recordFound, ruleFound) + require.NotEqual(t, eacl.ActionUnknown, eaclAct) + if eaclAct == eacl.ActionAllow { + if recordFound { + require.Equal(t, policyengine.Allow, apeSt) + } else { + require.Equal(t, policyengine.NoRuleFound, apeSt) + } + } else { + require.Equal(t, policyengine.AccessDenied, apeSt) + } + } +} + +type testRequest struct { + op string + props map[string]string + res *testResource +} + +func (r *testRequest) Operation() string { + return r.op +} + +func (r *testRequest) Property(key string) string { + if v, ok := r.props[key]; ok { + return v + } + return "" +} + +func (r *testRequest) Resource() policyengine.Resource { + return r.res +} + +type testResource struct { + name string + props map[string]string +} + +func (r *testResource) Name() string { + return r.name +} + +func (r *testResource) Property(key string) string { + if v, ok := r.props[key]; ok { + return v + } + return "" +} + +type testHeaderSource struct { + headers map[eacl.FilterHeaderType][]eacl.Header +} + +func (s *testHeaderSource) HeadersOfType(t eacl.FilterHeaderType) ([]eacl.Header, bool) { + v, ok := s.headers[t] + return v, ok +} + +type testHeader struct { + key, value string +} + +func (h *testHeader) Key() string { return h.key } +func (h *testHeader) Value() string { return h.value } From 4d5be5ccb51179454728cc98bc76a53b22b49d69 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 16 Nov 2023 10:58:55 +0300 Subject: [PATCH 0150/1413] [#811] ape: Update policy-engine module version and rebase Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 4 +- cmd/frostfs-cli/modules/control/get_rule.go | 4 +- cmd/frostfs-cli/modules/control/list_rules.go | 4 +- cmd/frostfs-cli/modules/util/ape.go | 58 +++++++------- cmd/frostfs-cli/modules/util/ape_test.go | 2 +- cmd/frostfs-node/policy_engine.go | 11 +-- go.mod | 2 +- go.sum | 4 +- internal/ape/converter.go | 76 +++++++++---------- internal/ape/converter_test.go | 13 ++-- pkg/core/container/storage.go | 4 +- pkg/services/control/server/policy_engine.go | 42 +++++++--- pkg/services/object/acl/ape.go | 11 ++- pkg/services/object/acl/ape_request.go | 47 +++++------- 14 files changed, 151 insertions(+), 131 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 0c67321084..d7177dd962 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -12,7 +12,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - ape "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) @@ -50,7 +50,7 @@ func addRule(cmd *cobra.Command, _ []string) { rule, _ := cmd.Flags().GetString(ruleFlag) - chain := new(ape.Chain) + chain := new(apechain.Chain) commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, []string{rule})) serializedChain := chain.Bytes() diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index df2bf94fed..0c34a696eb 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -9,7 +9,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) @@ -53,7 +53,7 @@ func getRule(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) - var chain policyengine.Chain + var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain())) // TODO (aarifullin): make pretty-formatted output for chains. diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index b3d7a5b9c0..6a0879d0e6 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -9,7 +9,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) @@ -58,7 +58,7 @@ func listRules(cmd *cobra.Command, _ []string) { for _, c := range chains { // TODO (aarifullin): make pretty-formatted output for chains. - var chain policyengine.Chain + var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c)) cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, chain.Bytes())) } diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 47ce37bb7e..c5f8526e2c 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/flynn-archive/go-shlex" ) @@ -21,13 +21,13 @@ var ( ) // ParseAPEChain parses APE chain rules. -func ParseAPEChain(chain *policyengine.Chain, rules []string) error { +func ParseAPEChain(chain *apechain.Chain, rules []string) error { if len(rules) == 0 { return errors.New("no APE rules provided") } for _, rule := range rules { - r := new(policyengine.Rule) + r := new(apechain.Rule) if err := ParseAPERule(r, rule); err != nil { return err } @@ -47,7 +47,7 @@ func ParseAPEChain(chain *policyengine.Chain, rules []string) error { // allow Object.Get Object.Resource:Department=HR Object.Request:Actor=ownerA * // //nolint:godot -func ParseAPERule(r *policyengine.Rule, rule string) error { +func ParseAPERule(r *apechain.Rule, rule string) error { lexemes, err := shlex.Split(rule) if err != nil { return fmt.Errorf("can't parse rule '%s': %v", rule, err) @@ -55,7 +55,7 @@ func ParseAPERule(r *policyengine.Rule, rule string) error { return parseRuleLexemes(r, lexemes) } -func parseRuleLexemes(r *policyengine.Rule, lexemes []string) error { +func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { if len(lexemes) < 2 { return errInvalidStatementFormat } @@ -80,14 +80,14 @@ func parseRuleLexemes(r *policyengine.Rule, lexemes []string) error { return err } -func parseStatus(lexeme string) (policyengine.Status, error) { +func parseStatus(lexeme string) (apechain.Status, error) { action, expression, found := strings.Cut(lexeme, ":") switch action = strings.ToLower(action); action { case "deny": if !found { - return policyengine.AccessDenied, nil + return apechain.AccessDenied, nil } else if strings.EqualFold(expression, "QuotaLimitReached") { - return policyengine.QuotaLimitReached, nil + return apechain.QuotaLimitReached, nil } else { return 0, fmt.Errorf("%w: %s", errUnknownActionDetail, expression) } @@ -95,38 +95,38 @@ func parseStatus(lexeme string) (policyengine.Status, error) { if found { return 0, errUnknownActionDetail } - return policyengine.Allow, nil + return apechain.Allow, nil default: return 0, errUnknownAction } } -func parseAction(lexeme string) (policyengine.Actions, error) { +func parseAction(lexeme string) (apechain.Actions, error) { switch strings.ToLower(lexeme) { case "object.put": - return policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodPutObject}}, nil case "object.get": - return policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodGetObject}}, nil case "object.head": - return policyengine.Actions{Names: []string{nativeschema.MethodHeadObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodHeadObject}}, nil case "object.delete": - return policyengine.Actions{Names: []string{nativeschema.MethodDeleteObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodDeleteObject}}, nil case "object.search": - return policyengine.Actions{Names: []string{nativeschema.MethodSearchObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodSearchObject}}, nil case "object.range": - return policyengine.Actions{Names: []string{nativeschema.MethodRangeObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodRangeObject}}, nil case "object.hash": - return policyengine.Actions{Names: []string{nativeschema.MethodHashObject}}, nil + return apechain.Actions{Names: []string{nativeschema.MethodHashObject}}, nil default: } - return policyengine.Actions{}, fmt.Errorf("%w: %s", errUnknownOperation, lexeme) + return apechain.Actions{}, fmt.Errorf("%w: %s", errUnknownOperation, lexeme) } -func parseResource(lexeme string) (policyengine.Resources, error) { +func parseResource(lexeme string) (apechain.Resources, error) { if lexeme == "*" { - return policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, nil + return apechain.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, nil } - return policyengine.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, lexeme)}}, nil + return apechain.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, lexeme)}}, nil } const ( @@ -134,13 +134,13 @@ const ( ObjectRequest = "object.request" ) -var typeToCondObject = map[string]policyengine.ObjectType{ - ObjectResource: policyengine.ObjectResource, - ObjectRequest: policyengine.ObjectRequest, +var typeToCondObject = map[string]apechain.ObjectType{ + ObjectResource: apechain.ObjectResource, + ObjectRequest: apechain.ObjectRequest, } -func parseConditions(lexemes []string) ([]policyengine.Condition, error) { - conds := make([]policyengine.Condition, 0) +func parseConditions(lexemes []string) ([]apechain.Condition, error) { + conds := make([]apechain.Condition, 0) for _, lexeme := range lexemes { typ, expression, found := strings.Cut(lexeme, ":") @@ -155,7 +155,7 @@ func parseConditions(lexemes []string) ([]policyengine.Condition, error) { var lhs, rhs string var binExpFound bool - var cond policyengine.Condition + var cond apechain.Condition cond.Object = objType lhs, rhs, binExpFound = strings.Cut(expression, "!=") @@ -164,9 +164,9 @@ func parseConditions(lexemes []string) ([]policyengine.Condition, error) { if !binExpFound { return nil, fmt.Errorf("%w: %s", errUnknownBinaryOperator, expression) } - cond.Op = policyengine.CondStringEquals + cond.Op = apechain.CondStringEquals } else { - cond.Op = policyengine.CondStringNotEquals + cond.Op = apechain.CondStringNotEquals } cond.Key, cond.Value = lhs, rhs diff --git a/cmd/frostfs-cli/modules/util/ape_test.go b/cmd/frostfs-cli/modules/util/ape_test.go index b2e9d1d872..1cab8e6aec 100644 --- a/cmd/frostfs-cli/modules/util/ape_test.go +++ b/cmd/frostfs-cli/modules/util/ape_test.go @@ -3,7 +3,7 @@ package util import ( "testing" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" ) diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index f0bd78629c..248cddb111 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -5,23 +5,24 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" ) type apeChainSourceImpl struct { mtx sync.Mutex - localChainStorage map[cid.ID]policyengine.CachedChainStorage + localChainStorage map[cid.ID]engine.LocalOverrideEngine } func NewAPESource() container.AccessPolicyEngineChainSource { return &apeChainSourceImpl{ - localChainStorage: make(map[cid.ID]policyengine.CachedChainStorage), + localChainStorage: make(map[cid.ID]engine.LocalOverrideEngine), } } var _ container.AccessPolicyEngineChainSource = (*apeChainSourceImpl)(nil) -func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (policyengine.CachedChainStorage, error) { +func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (engine.LocalOverrideEngine, error) { c.mtx.Lock() defer c.mtx.Unlock() @@ -29,6 +30,6 @@ func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (policyengine.CachedChai if ok { return s, nil } - c.localChainStorage[cid] = policyengine.NewInMemory() + c.localChainStorage[cid] = inmemory.NewInMemoryLocalOverrides() return c.localChainStorage[cid], nil } diff --git a/go.mod b/go.mod index 5def2fade8..120c05ff44 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231114100951-38985e4ec86b + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index 5c30a75e44..642280d950 100644 --- a/go.sum +++ b/go.sum @@ -736,8 +736,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231114100951-38985e4ec86b h1:io+LMCjNfP1IA7Jku7QVzAnlBjJXDNBNrHw1fpbsoeI= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231114100951-38985e4ec86b/go.mod h1:qf3B9hSz6gCMfcfvqkhTu5ak+Gx2R+wo4Hc87LnKxPg= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f h1:Rq95TuEkqc3T1EN5ZU1Vgf6H33TR95hz97ca8jrUciQ= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f/go.mod h1:qf3B9hSz6gCMfcfvqkhTu5ak+Gx2R+wo4Hc87LnKxPg= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/internal/ape/converter.go b/internal/ape/converter.go index e268626e6c..dec6f80d8e 100644 --- a/internal/ape/converter.go +++ b/internal/ape/converter.go @@ -6,7 +6,7 @@ import ( v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) @@ -28,12 +28,12 @@ func (e *ConvertEACLError) Unwrap() error { return e.nested } -// ConvertEACLToAPE converts eacl.Table to policyengine.Chain. -func ConvertEACLToAPE(eaclTable *eacl.Table) (*policyengine.Chain, error) { +// ConvertEACLToAPE converts eacl.Table to apechain.Chain. +func ConvertEACLToAPE(eaclTable *eacl.Table) (*apechain.Chain, error) { if eaclTable == nil { return nil, nil } - res := &policyengine.Chain{} + res := &apechain.Chain{} resource := getResource(eaclTable) @@ -67,53 +67,53 @@ func ConvertEACLToAPE(eaclTable *eacl.Table) (*policyengine.Chain, error) { return res, nil } -func appendTargetsOnly(source []policyengine.Rule, st policyengine.Status, act policyengine.Actions, res policyengine.Resources, targets []eacl.Target) []policyengine.Rule { +func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target) []apechain.Rule { // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 // role OR public key must be equal - rule := policyengine.Rule{ + rule := apechain.Rule{ Status: st, Actions: act, Resources: res, Any: true, } for _, target := range targets { - var roleCondition policyengine.Condition - roleCondition.Object = policyengine.ObjectRequest + var roleCondition apechain.Condition + roleCondition.Object = apechain.ObjectRequest roleCondition.Key = nativeschema.PropertyKeyActorRole roleCondition.Value = target.Role().String() - roleCondition.Op = policyengine.CondStringEquals + roleCondition.Op = apechain.CondStringEquals rule.Condition = append(rule.Condition, roleCondition) for _, binKey := range target.BinaryKeys() { - var pubKeyCondition policyengine.Condition - pubKeyCondition.Object = policyengine.ObjectRequest + var pubKeyCondition apechain.Condition + pubKeyCondition.Object = apechain.ObjectRequest pubKeyCondition.Key = nativeschema.PropertyKeyActorPublicKey pubKeyCondition.Value = hex.EncodeToString(binKey) - pubKeyCondition.Op = policyengine.CondStringEquals + pubKeyCondition.Op = apechain.CondStringEquals rule.Condition = append(rule.Condition, pubKeyCondition) } } return append(source, rule) } -func appendTargetsAndFilters(source []policyengine.Rule, st policyengine.Status, act policyengine.Actions, res policyengine.Resources, +func appendTargetsAndFilters(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target, filters []eacl.Filter, -) ([]policyengine.Rule, error) { +) ([]apechain.Rule, error) { // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 // role OR public key must be equal // so filters are repeated for each role and public key var err error for _, target := range targets { - rule := policyengine.Rule{ + rule := apechain.Rule{ Status: st, Actions: act, Resources: res, } - var roleCondition policyengine.Condition - roleCondition.Object = policyengine.ObjectRequest + var roleCondition apechain.Condition + roleCondition.Object = apechain.ObjectRequest roleCondition.Key = nativeschema.PropertyKeyActorRole roleCondition.Value = target.Role().String() - roleCondition.Op = policyengine.CondStringEquals + roleCondition.Op = apechain.CondStringEquals rule.Condition = append(rule.Condition, roleCondition) rule.Condition, err = appendFilters(rule.Condition, filters) @@ -124,16 +124,16 @@ func appendTargetsAndFilters(source []policyengine.Rule, st policyengine.Status, source = append(source, rule) for _, binKey := range target.BinaryKeys() { - rule := policyengine.Rule{ + rule := apechain.Rule{ Status: st, Actions: act, Resources: res, } - var pubKeyCondition policyengine.Condition - pubKeyCondition.Object = policyengine.ObjectRequest + var pubKeyCondition apechain.Condition + pubKeyCondition.Object = apechain.ObjectRequest pubKeyCondition.Key = nativeschema.PropertyKeyActorPublicKey pubKeyCondition.Value = hex.EncodeToString(binKey) - pubKeyCondition.Op = policyengine.CondStringEquals + pubKeyCondition.Op = apechain.CondStringEquals rule.Condition = append(rule.Condition, pubKeyCondition) rule.Condition, err = appendFilters(rule.Condition, filters) @@ -148,23 +148,23 @@ func appendTargetsAndFilters(source []policyengine.Rule, st policyengine.Status, return source, nil } -func appendFilters(source []policyengine.Condition, filters []eacl.Filter) ([]policyengine.Condition, error) { +func appendFilters(source []apechain.Condition, filters []eacl.Filter) ([]apechain.Condition, error) { for _, filter := range filters { - var cond policyengine.Condition + var cond apechain.Condition var isObject bool if filter.From() == eacl.HeaderFromObject { - cond.Object = policyengine.ObjectResource + cond.Object = apechain.ObjectResource isObject = true } else if filter.From() == eacl.HeaderFromRequest { - cond.Object = policyengine.ObjectRequest + cond.Object = apechain.ObjectRequest } else { return nil, &ConvertEACLError{nested: fmt.Errorf("unknown filter from: %d", filter.From())} } if filter.Matcher() == eacl.MatchStringEqual { - cond.Op = policyengine.CondStringEquals + cond.Op = apechain.CondStringEquals } else if filter.Matcher() == eacl.MatchStringNotEqual { - cond.Op = policyengine.CondStringNotEquals + cond.Op = apechain.CondStringNotEquals } else { return nil, &ConvertEACLError{nested: fmt.Errorf("unknown filter matcher: %d", filter.Matcher())} } @@ -205,30 +205,30 @@ func eaclKeyToAPEKey(key string, isObject bool) string { } } -func getResource(eaclTable *eacl.Table) policyengine.Resources { +func getResource(eaclTable *eacl.Table) apechain.Resources { cnrID, isSet := eaclTable.CID() if isSet { - return policyengine.Resources{ + return apechain.Resources{ Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, } } - return policyengine.Resources{ + return apechain.Resources{ Names: []string{nativeschema.ResourceFormatRootObjects}, } } -func actionToStatus(a eacl.Action) (policyengine.Status, error) { +func actionToStatus(a eacl.Action) (apechain.Status, error) { switch a { case eacl.ActionAllow: - return policyengine.Allow, nil + return apechain.Allow, nil case eacl.ActionDeny: - return policyengine.AccessDenied, nil + return apechain.AccessDenied, nil default: - return policyengine.NoRuleFound, &ConvertEACLError{nested: fmt.Errorf("unknown action: %d", a)} + return apechain.NoRuleFound, &ConvertEACLError{nested: fmt.Errorf("unknown action: %d", a)} } } -var eaclOperationToEngineAction = map[eacl.Operation]policyengine.Actions{ +var eaclOperationToEngineAction = map[eacl.Operation]apechain.Actions{ eacl.OperationGet: {Names: []string{nativeschema.MethodGetObject}}, eacl.OperationHead: {Names: []string{nativeschema.MethodHeadObject}}, eacl.OperationPut: {Names: []string{nativeschema.MethodPutObject}}, @@ -238,9 +238,9 @@ var eaclOperationToEngineAction = map[eacl.Operation]policyengine.Actions{ eacl.OperationRangeHash: {Names: []string{nativeschema.MethodHashObject}}, } -func operationToAction(op eacl.Operation) (policyengine.Actions, error) { +func operationToAction(op eacl.Operation) (apechain.Actions, error) { if v, ok := eaclOperationToEngineAction[op]; ok { return v, nil } - return policyengine.Actions{}, &ConvertEACLError{nested: fmt.Errorf("unknown operation: %d", op)} + return apechain.Actions{}, &ConvertEACLError{nested: fmt.Errorf("unknown operation: %d", op)} } diff --git a/internal/ape/converter_test.go b/internal/ape/converter_test.go index bf6205ec95..de72408b1a 100644 --- a/internal/ape/converter_test.go +++ b/internal/ape/converter_test.go @@ -7,7 +7,8 @@ import ( cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" @@ -393,7 +394,7 @@ func TestNoHeader(t *testing.T) { compare(t, tb, vu, ch, req) } -func compare(t *testing.T, eaclTable *eacl.Table, vu *eacl.ValidationUnit, ch *policyengine.Chain, req *testRequest) { +func compare(t *testing.T, eaclTable *eacl.Table, vu *eacl.ValidationUnit, ch *apechain.Chain, req *testRequest) { validator := eacl.NewValidator() for eaclOp, apeOp := range eaclOperationToEngineAction { vu.WithOperation(eaclOp) @@ -406,12 +407,12 @@ func compare(t *testing.T, eaclTable *eacl.Table, vu *eacl.ValidationUnit, ch *p require.NotEqual(t, eacl.ActionUnknown, eaclAct) if eaclAct == eacl.ActionAllow { if recordFound { - require.Equal(t, policyengine.Allow, apeSt) + require.Equal(t, apechain.Allow, apeSt) } else { - require.Equal(t, policyengine.NoRuleFound, apeSt) + require.Equal(t, apechain.NoRuleFound, apeSt) } } else { - require.Equal(t, policyengine.AccessDenied, apeSt) + require.Equal(t, apechain.AccessDenied, apeSt) } } } @@ -433,7 +434,7 @@ func (r *testRequest) Property(key string) string { return "" } -func (r *testRequest) Resource() policyengine.Resource { +func (r *testRequest) Resource() resource.Resource { return r.res } diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index ebafd22db3..cc358b436d 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -7,7 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" ) // Container groups information about the FrostFS container stored in the FrostFS network. @@ -77,5 +77,5 @@ type EACLSource interface { // policy engine chain storage. type AccessPolicyEngineChainSource interface { // TODO (aarifullin): Better to use simpler interface instead CachedChainStorage. - GetChainSource(cid cid.ID) (policyengine.CachedChainStorage, error) + GetChainSource(cid cid.ID) (engine.LocalOverrideEngine, error) } diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 19d1b71487..8565cd9c17 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -2,11 +2,14 @@ package control import ( "context" + "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -22,7 +25,7 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL return nil, status.Error(codes.InvalidArgument, err.Error()) } - var chain policyengine.Chain + var chain apechain.Chain if err = chain.DecodeBytes(req.GetBody().GetChain()); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -34,9 +37,12 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL s.apeChainCounter.Add(1) // TODO (aarifullin): the such chain id is not well-designed yet. - chain.ID = policyengine.ChainID(fmt.Sprintf("%s:%d", policyengine.Ingress, s.apeChainCounter.Load())) + chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) - src.AddOverride(policyengine.Ingress, &chain) + resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + if _, err = src.LocalStorage().AddOverride(apechain.Ingress, resource, &chain); err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) + } resp := &control.AddChainLocalOverrideResponse{ Body: &control.AddChainLocalOverrideResponse_Body{ @@ -66,10 +72,10 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL return nil, status.Error(codes.Internal, err.Error()) } - chain, found := src.GetOverride(policyengine.Ingress, policyengine.ChainID(req.GetBody().GetChainId())) - if !found { - err = fmt.Errorf("local override has not been found") - return nil, status.Error(codes.NotFound, err.Error()) + resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + chain, err := src.LocalStorage().GetOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())) + if err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } resp := &control.GetChainLocalOverrideResponse{ @@ -100,7 +106,11 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha return nil, status.Error(codes.Internal, err.Error()) } - chains := src.ListOverrides(policyengine.Ingress) + resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, resource) + if err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) + } serializedChains := make([][]byte, 0, len(chains)) for _, chain := range chains { serializedChains = append(serializedChains, chain.Bytes()) @@ -134,10 +144,13 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return nil, status.Error(codes.Internal, err.Error()) } - removed := src.RemoveOverride(policyengine.Ingress, policyengine.ChainID(req.GetBody().GetChainId())) + resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + if err = src.LocalStorage().RemoveOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())); err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) + } resp := &control.RemoveChainLocalOverrideResponse{ Body: &control.RemoveChainLocalOverrideResponse_Body{ - Removed: removed, + Removed: true, }, } err = SignMessage(s.key, resp) @@ -146,3 +159,10 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove } return resp, nil } + +func getCodeByLocalStorageErr(err error) codes.Code { + if errors.Is(err, engine.ErrChainNotFound) { + return codes.NotFound + } + return codes.Internal +} diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go index 86af440fe0..525ed59300 100644 --- a/pkg/services/object/acl/ape.go +++ b/pkg/services/object/acl/ape.go @@ -8,7 +8,7 @@ import ( v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" ) var errAPEChainNoSource = errors.New("could not get ape chain source for the container") @@ -36,9 +36,12 @@ func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { request := new(Request) request.FromRequestInfo(reqInfo) - status, ruleFound := chainCache.IsAllowed(policyengine.Ingress, "", request) + status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, "", request) + if err != nil { + return err + } - if !ruleFound || status == policyengine.Allow { + if !ruleFound || status == apechain.Allow { return nil } @@ -47,7 +50,7 @@ func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { const accessDeniedAPEReasonFmt = "access to operation %s is denied by access policy engine: %s" -func apeErr(req v2.RequestInfo, status policyengine.Status) error { +func apeErr(req v2.RequestInfo, status apechain.Status) error { errAccessDenied := &apistatus.ObjectAccessDenied{} errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedAPEReasonFmt, req.Operation(), status.String())) return errAccessDenied diff --git a/pkg/services/object/acl/ape_request.go b/pkg/services/object/acl/ape_request.go index 3e8bb173df..accbdce5f8 100644 --- a/pkg/services/object/acl/ape_request.go +++ b/pkg/services/object/acl/ape_request.go @@ -5,7 +5,8 @@ import ( v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" aclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine" + aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) type Request struct { @@ -14,14 +15,14 @@ type Request struct { properties map[string]string } -var _ policyengine.Request = (*Request)(nil) +var _ aperesource.Request = (*Request)(nil) type resource struct { name string properties map[string]string } -var _ policyengine.Resource = (*resource)(nil) +var _ aperesource.Resource = (*resource)(nil) func (r *resource) Name() string { return r.name @@ -31,18 +32,14 @@ func (r *resource) Property(key string) string { return r.properties[key] } -// TODO (aarifullin): these stringified verbs, properties and namespaces -// should be non-implementation-specific. func getResource(reqInfo v2.RequestInfo) *resource { + var name string cid := reqInfo.ContainerID() - oid := "*" - if reqOID := reqInfo.ObjectID(); reqOID != nil { - oid = reqOID.EncodeToString() + if oid := reqInfo.ObjectID(); oid != nil { + name = fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, cid.EncodeToString(), oid.EncodeToString()) + } else { + name = fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) } - name := fmt.Sprintf("native:::object/%s/%s", - cid, - oid) - return &resource{ name: name, properties: make(map[string]string), @@ -51,32 +48,30 @@ func getResource(reqInfo v2.RequestInfo) *resource { func getProperties(_ v2.RequestInfo) map[string]string { return map[string]string{ - "Actor": "", + nativeschema.PropertyKeyActorPublicKey: "", + nativeschema.PropertyKeyActorRole: "", } } -// TODO (aarifullin): these stringified verbs, properties and namespaces -// should be non-implementation-specific. func getOperation(reqInfo v2.RequestInfo) string { - var verb string switch op := reqInfo.Operation(); op { case aclSDK.OpObjectGet: - verb = "GetObject" + return nativeschema.MethodGetObject case aclSDK.OpObjectHead: - verb = "HeadObject" + return nativeschema.MethodHeadObject case aclSDK.OpObjectPut: - verb = "PutObject" + return nativeschema.MethodPutObject case aclSDK.OpObjectDelete: - verb = "DeleteObject" + return nativeschema.MethodDeleteObject case aclSDK.OpObjectSearch: - verb = "SearchObject" + return nativeschema.MethodSearchObject case aclSDK.OpObjectRange: - verb = "RangeObject" + return nativeschema.MethodRangeObject case aclSDK.OpObjectHash: - verb = "HashObject" + return nativeschema.MethodHashObject + default: + return "" } - - return "native:" + verb } func NewRequest() *Request { @@ -100,6 +95,6 @@ func (r *Request) Property(key string) string { return r.properties[key] } -func (r *Request) Resource() policyengine.Resource { +func (r *Request) Resource() aperesource.Resource { return r.resource } From 137e987a4e65ee253da0e16f4bcd602619b73c0d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 15 Nov 2023 13:12:23 +0300 Subject: [PATCH 0151/1413] [#655] storage: Drop `LazyHandler` LazyHandler is implemented and used incorrectly. Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/iterate.go | 4 +-- .../blobstor/common/iterate.go | 1 - .../blobstor/fstree/fstree.go | 35 ++++++++----------- .../blobstor/internal/blobstortest/iterate.go | 27 -------------- .../blobstor/memstore/memstore.go | 4 --- .../writecache/writecachebbolt/flush.go | 17 +++------ 6 files changed, 19 insertions(+), 69 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index a2afbb8aa7..7129e088ae 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -53,9 +53,7 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm StorageID: []byte(p), }) } - return prm.LazyHandler(elem.Address(), func() ([]byte, error) { - return data, err - }) + return nil }) subPrm.DecodeAddresses() diff --git a/pkg/local_object_storage/blobstor/common/iterate.go b/pkg/local_object_storage/blobstor/common/iterate.go index a6f0da26ba..1fbb08d323 100644 --- a/pkg/local_object_storage/blobstor/common/iterate.go +++ b/pkg/local_object_storage/blobstor/common/iterate.go @@ -15,7 +15,6 @@ type IterationHandler func(IterationElement) error // IteratePrm groups the parameters of Iterate operation. type IteratePrm struct { Handler IterationHandler - LazyHandler func(oid.Address, func() ([]byte, error)) error IgnoreErrors bool ErrorHandler func(oid.Address, error) error } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index bf3400bcd7..06309f53c7 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -188,31 +188,24 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr continue } - if prm.LazyHandler != nil { - err = prm.LazyHandler(addr, func() ([]byte, error) { - return data, err - }) - } else { - if err == nil { - data, err = t.Decompress(data) - } - if err != nil { - if prm.IgnoreErrors { - if prm.ErrorHandler != nil { - return prm.ErrorHandler(addr, err) - } - continue + if err == nil { + data, err = t.Decompress(data) + } + if err != nil { + if prm.IgnoreErrors { + if prm.ErrorHandler != nil { + return prm.ErrorHandler(addr, err) } - return err + continue } - - err = prm.Handler(common.IterationElement{ - Address: addr, - ObjectData: data, - StorageID: []byte{}, - }) + return err } + err = prm.Handler(common.IterationElement{ + Address: addr, + ObjectData: data, + StorageID: []byte{}, + }) if err != nil { return err } diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index 72f1076644..c73a663b6a 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -6,7 +6,6 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" ) @@ -30,8 +29,6 @@ func TestIterate(t *testing.T, cons Constructor, min, max uint64) { runTestNormalHandler(t, s, objects) - runTestLazyHandler(t, s, objects) - runTestIgnoreLogicalErrors(t, s, objects) } @@ -62,30 +59,6 @@ func runTestNormalHandler(t *testing.T, s common.Storage, objects []objectDesc) }) } -func runTestLazyHandler(t *testing.T, s common.Storage, objects []objectDesc) { - t.Run("lazy handler", func(t *testing.T) { - seen := make(map[string]func() ([]byte, error)) - - var iterPrm common.IteratePrm - iterPrm.LazyHandler = func(addr oid.Address, f func() ([]byte, error)) error { - seen[addr.String()] = f - return nil - } - - _, err := s.Iterate(context.Background(), iterPrm) - require.NoError(t, err) - require.Equal(t, len(objects), len(seen)) - for i := range objects { - f, ok := seen[objects[i].addr.String()] - require.True(t, ok) - - data, err := f() - require.NoError(t, err) - require.Equal(t, objects[i].raw, data) - } - }) -} - func runTestIgnoreLogicalErrors(t *testing.T, s common.Storage, objects []objectDesc) { t.Run("ignore errors doesn't work for logical errors", func(t *testing.T) { seen := make(map[string]objectDesc) diff --git a/pkg/local_object_storage/blobstor/memstore/memstore.go b/pkg/local_object_storage/blobstor/memstore/memstore.go index 9428f457fa..63e1a3e99e 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore.go @@ -154,10 +154,6 @@ func (s *memstoreImpl) Iterate(_ context.Context, req common.IteratePrm) (common if err := req.Handler(elem); err != nil { return common.IterateRes{}, err } - case req.LazyHandler != nil: - if err := req.LazyHandler(elem.Address, func() ([]byte, error) { return elem.ObjectData, nil }); err != nil { - return common.IterateRes{}, err - } default: if !req.IgnoreErrors { return common.IterateRes{}, logicerr.Wrap(fmt.Errorf("(%T) no Handler or LazyHandler set for IteratePrm", s)) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush.go b/pkg/local_object_storage/writecache/writecachebbolt/flush.go index 9e46226d1d..9efee1dda2 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush.go @@ -180,20 +180,11 @@ func (c *cache) reportFlushError(msg string, addr string, err error) { func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { var prm common.IteratePrm prm.IgnoreErrors = ignoreErrors - prm.LazyHandler = func(addr oid.Address, f func() ([]byte, error)) error { - sAddr := addr.EncodeToString() - - data, err := f() - if err != nil { - c.reportFlushError(logs.FSTreeCantReadFile, sAddr, metaerr.Wrap(err)) - if ignoreErrors { - return nil - } - return err - } + prm.Handler = func(e common.IterationElement) error { + sAddr := e.Address.EncodeToString() var obj objectSDK.Object - err = obj.Unmarshal(data) + err := obj.Unmarshal(e.ObjectData) if err != nil { c.reportFlushError(logs.FSTreeCantUnmarshalObject, sAddr, metaerr.Wrap(err)) if ignoreErrors { @@ -202,7 +193,7 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { return err } - err = c.flushObject(ctx, &obj, data, writecache.StorageTypeFSTree) + err = c.flushObject(ctx, &obj, e.ObjectData, writecache.StorageTypeFSTree) if err != nil { if ignoreErrors { return nil From 29fe8c41f33bff2668ab0a020a5401a07859fe38 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 15 Nov 2023 14:18:03 +0300 Subject: [PATCH 0152/1413] [#655] storage: Drop `ErrorHandler` The only one usage was for logging. Now logging performed by storage anyway. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 + .../blobstor/blobovniczatree/iterate.go | 14 ++++++++--- .../blobstor/common/iterate.go | 1 - .../blobstor/fstree/fstree.go | 23 ++++++++++++++----- .../blobstor/fstree/option.go | 8 +++++++ pkg/local_object_storage/blobstor/iterate.go | 15 ++++++------ .../blobstor/memstore/memstore.go | 3 --- 7 files changed, 45 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index a43b59ab20..3be33a2a1a 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -818,6 +818,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { fstree.WithPerm(sRead.perm), fstree.WithDepth(sRead.depth), fstree.WithNoSync(sRead.noSync), + fstree.WithLogger(c.log), } if c.metricsCollector != nil { fstreeOpts = append(fstreeOpts, diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 7129e088ae..d2b285c650 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -6,6 +6,7 @@ import ( "path/filepath" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -13,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/hrw" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" ) // Iterate iterates over all objects in b. @@ -38,9 +40,11 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm data, err := b.compression.Decompress(elem.ObjectData()) if err != nil { if prm.IgnoreErrors { - if prm.ErrorHandler != nil { - return prm.ErrorHandler(elem.Address(), err) - } + b.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + zap.Stringer("address", elem.Address()), + zap.String("err", err.Error()), + zap.String("storage_id", p), + zap.String("root_path", b.rootPath)) return nil } return fmt.Errorf("could not decompress object data: %w", err) @@ -70,6 +74,10 @@ func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors boo blz, err := shBlz.Open() if err != nil { if ignoreErrors { + b.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + zap.String("err", err.Error()), + zap.String("storage_id", p), + zap.String("root_path", b.rootPath)) return false, nil } return false, fmt.Errorf("could not open blobovnicza %s: %w", p, err) diff --git a/pkg/local_object_storage/blobstor/common/iterate.go b/pkg/local_object_storage/blobstor/common/iterate.go index 1fbb08d323..a1b8ff0472 100644 --- a/pkg/local_object_storage/blobstor/common/iterate.go +++ b/pkg/local_object_storage/blobstor/common/iterate.go @@ -16,7 +16,6 @@ type IterationHandler func(IterationElement) error type IteratePrm struct { Handler IterationHandler IgnoreErrors bool - ErrorHandler func(oid.Address, error) error } // IterateRes groups the resulting values of Iterate operation. diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 06309f53c7..d1fe85901e 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -14,10 +14,12 @@ import ( "syscall" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -25,6 +27,7 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" ) type keyLock interface { @@ -41,6 +44,8 @@ func (l *noopKeyLock) Unlock(string) {} type FSTree struct { Info + log *logger.Logger + *compression.Config Depth uint64 DirNameLen int @@ -86,6 +91,7 @@ func New(opts ...Option) *FSTree { metrics: &noopMetrics{}, fileGuard: &noopKeyLock{}, fileCounter: &noopCounter{}, + log: &logger.Logger{Logger: zap.L()}, } for i := range opts { opts[i](f) @@ -145,9 +151,13 @@ func (t *FSTree) Iterate(ctx context.Context, prm common.IteratePrm) (common.Ite func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, prm common.IteratePrm) error { curName := strings.Join(curPath[1:], "") - des, err := os.ReadDir(filepath.Join(curPath...)) + dirPath := filepath.Join(curPath...) + des, err := os.ReadDir(dirPath) if err != nil { if prm.IgnoreErrors { + t.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + zap.String("err", err.Error()), + zap.String("directory_path", dirPath)) return nil } return err @@ -182,8 +192,8 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr if err != nil { continue } - - data, err := os.ReadFile(filepath.Join(curPath...)) + path := filepath.Join(curPath...) + data, err := os.ReadFile(path) if err != nil && os.IsNotExist(err) { continue } @@ -193,9 +203,10 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr } if err != nil { if prm.IgnoreErrors { - if prm.ErrorHandler != nil { - return prm.ErrorHandler(addr, err) - } + t.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + zap.Stringer("address", addr), + zap.String("err", err.Error()), + zap.String("path", path)) continue } return err diff --git a/pkg/local_object_storage/blobstor/fstree/option.go b/pkg/local_object_storage/blobstor/fstree/option.go index 21d46ac4df..e6c7a26080 100644 --- a/pkg/local_object_storage/blobstor/fstree/option.go +++ b/pkg/local_object_storage/blobstor/fstree/option.go @@ -3,7 +3,9 @@ package fstree import ( "io/fs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" + "go.uber.org/zap" ) type Option func(*FSTree) @@ -51,3 +53,9 @@ func WithFileCounter(c FileCounter) Option { f.fileGuard = utilSync.NewKeyLocker[string]() } } + +func WithLogger(l *logger.Logger) Option { + return func(f *FSTree) { + f.log = &logger.Logger{Logger: l.With(zap.String("component", "FSTree"))} + } +} diff --git a/pkg/local_object_storage/blobstor/iterate.go b/pkg/local_object_storage/blobstor/iterate.go index 5a41e4c4f9..f213d75474 100644 --- a/pkg/local_object_storage/blobstor/iterate.go +++ b/pkg/local_object_storage/blobstor/iterate.go @@ -40,7 +40,14 @@ func (b *BlobStor) Iterate(ctx context.Context, prm common.IteratePrm) (common.I for i := range b.storage { _, err := b.storage[i].Storage.Iterate(ctx, prm) - if err != nil && !prm.IgnoreErrors { + if err != nil { + if prm.IgnoreErrors { + b.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + zap.String("storage_path", b.storage[i].Storage.Path()), + zap.String("storage_type", b.storage[i].Storage.Type()), + zap.String("err", err.Error())) + continue + } return common.IterateRes{}, fmt.Errorf("blobstor iterator failure: %w", err) } } @@ -57,12 +64,6 @@ func IterateBinaryObjects(ctx context.Context, blz *BlobStor, f func(addr oid.Ad return f(elem.Address, elem.ObjectData, elem.StorageID) } prm.IgnoreErrors = true - prm.ErrorHandler = func(addr oid.Address, err error) error { - blz.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, - zap.Stringer("address", addr), - zap.String("err", err.Error())) - return nil - } _, err := blz.Iterate(ctx, prm) diff --git a/pkg/local_object_storage/blobstor/memstore/memstore.go b/pkg/local_object_storage/blobstor/memstore/memstore.go index 63e1a3e99e..cc4f6921a2 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore.go @@ -142,9 +142,6 @@ func (s *memstoreImpl) Iterate(_ context.Context, req common.IteratePrm) (common var err error if elem.ObjectData, err = s.compression.Decompress(elem.ObjectData); err != nil { if req.IgnoreErrors { - if req.ErrorHandler != nil { - return common.IterateRes{}, req.ErrorHandler(elem.Address, err) - } continue } return common.IterateRes{}, logicerr.Wrap(fmt.Errorf("(%T) decompressing data for address %q: %v", s, elem.Address.String(), err)) From 5cfb758e4eecb28ba22f301293032a3e918997b7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 17 Nov 2023 09:05:46 +0300 Subject: [PATCH 0153/1413] [#806] morph: Remove container list cache Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/cache.go | 71 ----------------------------------- cmd/frostfs-node/container.go | 10 +---- 2 files changed, 1 insertion(+), 80 deletions(-) diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index ea5bdfda05..cd383a5c2f 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -6,13 +6,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" lru "github.com/hashicorp/golang-lru/v2" ) @@ -244,75 +242,6 @@ func (s *lruNetmapSource) Epoch() (uint64, error) { return s.netState.CurrentEpoch(), nil } -// wrapper over TTL cache of values read from the network -// that implements container lister. -type ttlContainerLister struct { - inner *ttlNetCache[string, *cacheItemContainerList] - client *cntClient.Client -} - -// value type for ttlNetCache used by ttlContainerLister. -type cacheItemContainerList struct { - // protects list from concurrent add/remove ops - mtx sync.RWMutex - // actual list of containers owner by the particular user - list []cid.ID -} - -func newCachedContainerLister(c *cntClient.Client, ttl time.Duration) ttlContainerLister { - const containerListerCacheSize = 100 - - lruCnrListerCache := newNetworkTTLCache(containerListerCacheSize, ttl, func(strID string) (*cacheItemContainerList, error) { - var id *user.ID - - if strID != "" { - id = new(user.ID) - - err := id.DecodeString(strID) - if err != nil { - return nil, err - } - } - - list, err := c.ContainersOf(id) - if err != nil { - return nil, err - } - - return &cacheItemContainerList{ - list: list, - }, nil - }) - - return ttlContainerLister{inner: lruCnrListerCache, client: c} -} - -// List returns list of container IDs from the cache. If list is missing in the -// cache or expired, then it returns container IDs from side chain and updates -// the cache. -func (s ttlContainerLister) List(id *user.ID) ([]cid.ID, error) { - if id == nil { - return s.client.ContainersOf(nil) - } - - item, err := s.inner.get(id.EncodeToString()) - if err != nil { - return nil, err - } - - item.mtx.RLock() - res := make([]cid.ID, len(item.list)) - copy(res, item.list) - item.mtx.RUnlock() - - return res, nil -} - -func (s *ttlContainerLister) invalidate(owner user.ID) { - strOwner := owner.EncodeToString() - s.inner.remove(strOwner) -} - type cachedIRFetcher struct { *ttlNetCache[struct{}, [][]byte] } diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index c7360a1bf1..5477947d78 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -63,7 +63,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c // use RPC node as source of Container contract items (with caching) cachedContainerStorage := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL) cachedEACLStorage := newCachedEACLStorage(eACLFetcher, c.cfgMorph.cacheTTL) - cachedContainerLister := newCachedContainerLister(client, c.cfgMorph.cacheTTL) subscribeToContainerCreation(c, func(e event.Event) { ev := e.(containerEvent.PutSuccess) @@ -74,7 +73,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c // creation success are most commonly tracked by polling GET op. cnr, err := cnrSrc.Get(ev.ID) if err == nil { - cachedContainerLister.invalidate(cnr.Value.Owner()) cachedContainerStorage.containerCache.set(ev.ID, cnr, nil) } else { // unlike removal, we expect successful receive of the container @@ -92,13 +90,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c subscribeToContainerRemoval(c, func(e event.Event) { ev := e.(containerEvent.DeleteSuccess) - cachedContainerStorage.handleRemoval(ev.ID) - info, err := cachedContainerStorage.DeletionInfo(ev.ID) - if err == nil { - cachedContainerLister.invalidate(info.Owner) - } - c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt, zap.Stringer("id", ev.ID), ) @@ -107,7 +99,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c c.cfgObject.eaclSource = cachedEACLStorage c.cfgObject.cnrSource = cachedContainerStorage - cnrRdr.lister = cachedContainerLister + cnrRdr.lister = client cnrRdr.eacl = c.cfgObject.eaclSource cnrRdr.src = c.cfgObject.cnrSource From 47286ebf3242b55961b6ca424802336705d039be Mon Sep 17 00:00:00 2001 From: aarifullin Date: Wed, 15 Nov 2023 12:03:31 +0300 Subject: [PATCH 0154/1413] [#805] pilorama: Fix TreeDrop * If treeID is empty then deleting buckets for cursor may get invalidated. So, buckets should be gathered before deleting. Signed-off-by: Airat Arifullin --- pkg/local_object_storage/pilorama/boltdb.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 1bc1613419..52cdec586e 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1115,11 +1115,12 @@ func (t *boltForest) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID string) c := tx.Cursor() prefix := make([]byte, 32) cid.Encode(prefix) - for k, _ := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, _ = c.Next() { + for k, _ := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, _ = c.Seek(prefix) { err := tx.DeleteBucket(k) if err != nil { return err } + _, _ = c.First() // rewind the cursor to the root page } return nil } From 76ff26039c4e9f9dceaabda5127c8909c95b290e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 17 Nov 2023 10:58:04 +0300 Subject: [PATCH 0155/1413] [#96] node: Drop neo-go's `slices` package Signed-off-by: Dmitrii Stepanov --- pkg/innerring/processors/frostfs/handlers.go | 11 ++++++++--- pkg/local_object_storage/blobovnicza/get.go | 4 ++-- pkg/local_object_storage/blobovnicza/iterate_test.go | 4 ++-- .../blobstor/blobovniczatree/exists_test.go | 4 ++-- pkg/local_object_storage/metabase/shard_id.go | 5 +++-- pkg/local_object_storage/metabase/storage_id.go | 4 ++-- pkg/local_object_storage/shard/range_test.go | 4 ++-- .../writecache/writecachebbolt/flush.go | 5 ++--- .../writecache/writecachebbolt/get.go | 4 ++-- 9 files changed, 25 insertions(+), 20 deletions(-) diff --git a/pkg/innerring/processors/frostfs/handlers.go b/pkg/innerring/processors/frostfs/handlers.go index ab53d5c485..adb923b876 100644 --- a/pkg/innerring/processors/frostfs/handlers.go +++ b/pkg/innerring/processors/frostfs/handlers.go @@ -1,21 +1,24 @@ package frostfs import ( + "bytes" "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "go.uber.org/zap" + "golang.org/x/exp/slices" ) func (np *Processor) handleDeposit(ev event.Event) { deposit := ev.(frostfsEvent.Deposit) + depositIDBin := bytes.Clone(deposit.ID()) + slices.Reverse(depositIDBin) np.log.Info(logs.Notification, zap.String("type", "deposit"), - zap.String("id", hex.EncodeToString(slice.CopyReverse(deposit.ID())))) + zap.String("id", hex.EncodeToString(depositIDBin))) // send event to the worker pool @@ -31,9 +34,11 @@ func (np *Processor) handleDeposit(ev event.Event) { func (np *Processor) handleWithdraw(ev event.Event) { withdraw := ev.(frostfsEvent.Withdraw) + withdrawBin := bytes.Clone(withdraw.ID()) + slices.Reverse(withdrawBin) np.log.Info(logs.Notification, zap.String("type", "withdraw"), - zap.String("id", hex.EncodeToString(slice.CopyReverse(withdraw.ID())))) + zap.String("id", hex.EncodeToString(withdrawBin))) // send event to the worker pool diff --git a/pkg/local_object_storage/blobovnicza/get.go b/pkg/local_object_storage/blobovnicza/get.go index 3a613cfeb4..9975e5e8c8 100644 --- a/pkg/local_object_storage/blobovnicza/get.go +++ b/pkg/local_object_storage/blobovnicza/get.go @@ -1,13 +1,13 @@ package blobovnicza import ( + "bytes" "context" "errors" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -63,7 +63,7 @@ func (b *Blobovnicza) Get(ctx context.Context, prm GetPrm) (GetRes, error) { return nil } - data = slice.Copy(data) + data = bytes.Clone(data) return errInterruptForEach }) diff --git a/pkg/local_object_storage/blobovnicza/iterate_test.go b/pkg/local_object_storage/blobovnicza/iterate_test.go index 90308723c3..5db1e4165b 100644 --- a/pkg/local_object_storage/blobovnicza/iterate_test.go +++ b/pkg/local_object_storage/blobovnicza/iterate_test.go @@ -1,13 +1,13 @@ package blobovnicza import ( + "bytes" "context" "errors" "path/filepath" "testing" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" ) @@ -30,7 +30,7 @@ func TestBlobovniczaIterate(t *testing.T) { seen := make([][]byte, 0, 2) inc := func(e IterationElement) error { - seen = append(seen, slice.Copy(e.data)) + seen = append(seen, bytes.Clone(e.data)) return nil } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index 198e4741ba..c892623434 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -1,6 +1,7 @@ package blobovniczatree import ( + "bytes" "context" "os" "path/filepath" @@ -10,7 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "github.com/stretchr/testify/require" ) @@ -37,7 +37,7 @@ func TestExistsInvalidStorageID(t *testing.T) { t.Run("valid but wrong storage id", func(t *testing.T) { // "0/X/Y" <-> "1/X/Y" - storageID := slice.Copy(putRes.StorageID) + storageID := bytes.Clone(putRes.StorageID) if storageID[0] == '0' { storageID[0]++ } else { diff --git a/pkg/local_object_storage/metabase/shard_id.go b/pkg/local_object_storage/metabase/shard_id.go index f60a4724d1..c1ec8c67e4 100644 --- a/pkg/local_object_storage/metabase/shard_id.go +++ b/pkg/local_object_storage/metabase/shard_id.go @@ -1,8 +1,9 @@ package meta import ( + "bytes" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "go.etcd.io/bbolt" ) @@ -25,7 +26,7 @@ func (db *DB) ReadShardID() ([]byte, error) { err := db.boltDB.View(func(tx *bbolt.Tx) error { b := tx.Bucket(shardInfoBucket) if b != nil { - id = slice.Copy(b.Get(shardIDKey)) + id = bytes.Clone(b.Get(shardIDKey)) } return nil }) diff --git a/pkg/local_object_storage/metabase/storage_id.go b/pkg/local_object_storage/metabase/storage_id.go index 0a64da856e..ef6b44dfd5 100644 --- a/pkg/local_object_storage/metabase/storage_id.go +++ b/pkg/local_object_storage/metabase/storage_id.go @@ -1,6 +1,7 @@ package meta import ( + "bytes" "context" "errors" "time" @@ -9,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -72,7 +72,7 @@ func (db *DB) storageID(tx *bbolt.Tx, addr oid.Address) ([]byte, error) { return nil, nil } - return slice.Copy(storageID), nil + return bytes.Clone(storageID), nil } // UpdateStorageIDPrm groups the parameters of UpdateStorageID operation. diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index a8bc833079..098a584ad6 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -1,6 +1,7 @@ package shard import ( + "bytes" "context" "math" "path/filepath" @@ -16,7 +17,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "github.com/stretchr/testify/require" ) @@ -105,7 +105,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { testutil.AddPayload(obj, tc.payloadSize) addr := object.AddressOf(obj) - payload := slice.Copy(obj.Payload()) + payload := bytes.Clone(obj.Payload()) var putPrm PutPrm putPrm.SetObject(obj) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush.go b/pkg/local_object_storage/writecache/writecachebbolt/flush.go index 9efee1dda2..d0e89a3858 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush.go @@ -17,7 +17,6 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/mr-tron/base58" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -106,12 +105,12 @@ func (c *cache) flushSmallObjects(ctx context.Context) { if len(lastKey) == len(k) { copy(lastKey, k) } else { - lastKey = slice.Copy(k) + lastKey = bytes.Clone(k) } m = append(m, objectInfo{ addr: string(k), - data: slice.Copy(v), + data: bytes.Clone(v), }) } return nil diff --git a/pkg/local_object_storage/writecache/writecachebbolt/get.go b/pkg/local_object_storage/writecache/writecachebbolt/get.go index dede1fece6..838b207bed 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/get.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/get.go @@ -1,6 +1,7 @@ package writecachebbolt import ( + "bytes" "context" "time" @@ -12,7 +13,6 @@ import ( apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -95,7 +95,7 @@ func Get(db *bbolt.DB, key []byte) ([]byte, error) { if value == nil { return logicerr.Wrap(new(apistatus.ObjectNotFound)) } - value = slice.Copy(value) + value = bytes.Clone(value) return nil }) return value, metaerr.Wrap(err) From 02454df14a54d6e51e5f454ad1dcbaf65ddf2147 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Wed, 15 Nov 2023 15:28:45 +0300 Subject: [PATCH 0156/1413] [#809] client: Refactor PrmInit, PrmDial usage Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/sdk.go | 26 ++++++++------- go.mod | 2 +- go.sum | 4 +-- pkg/network/cache/multi.go | 44 ++++++++++++-------------- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/sdk.go b/cmd/frostfs-cli/internal/client/sdk.go index 6923e4f17e..b3e04e5f5f 100644 --- a/cmd/frostfs-cli/internal/client/sdk.go +++ b/cmd/frostfs-cli/internal/client/sdk.go @@ -43,26 +43,28 @@ func getSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag // GetSDKClient returns default frostfs-sdk-go client. func GetSDKClient(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey, addr network.Address) (*client.Client, error) { - var ( - c client.Client - prmInit client.PrmInit - prmDial client.PrmDial - ) + var c client.Client - prmInit.SetDefaultPrivateKey(*key) - prmDial.SetServerURI(addr.URIAddr()) + prmInit := client.PrmInit{ + Key: *key, + } + + prmDial := client.PrmDial{ + Endpoint: addr.URIAddr(), + GRPCDialOptions: []grpc.DialOption{ + grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor()), + grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor()), + }, + } if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 { // In CLI we can only set a timeout for the whole operation. // By also setting stream timeout we ensure that no operation hands // for too long. - prmDial.SetTimeout(timeout) - prmDial.SetStreamTimeout(timeout) + prmDial.DialTimeout = timeout + prmDial.StreamTimeout = timeout common.PrintVerbose(cmd, "Set request timeout to %s.", timeout) } - prmDial.SetGRPCDialOptions( - grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor()), - grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor())) c.Init(prmInit) diff --git a/go.mod b/go.mod index 120c05ff44..7d2b934865 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231114081800-3787477133f3 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index 642280d950..070c246ba1 100644 --- a/go.sum +++ b/go.sum @@ -732,8 +732,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d h1:KVHsNsEoedQ1+f+eDq88AFKkLePGfnygt4bcUQrCgPw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231101144515-6fbe1595cb3d/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231114081800-3787477133f3 h1:Qa35bB58plMb14LIsYzu2ibeYfsY2taFnbZytv9Ao3M= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231114081800-3787477133f3/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f h1:Rq95TuEkqc3T1EN5ZU1Vgf6H33TR95hz97ca8jrUciQ= diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index c9b13826ac..5dd206283f 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -51,42 +51,40 @@ func newMultiClient(addr network.AddressGroup, opts ClientCacheOpts) *multiClien } func (x *multiClient) createForAddress(ctx context.Context, addr network.Address) (clientcore.Client, error) { - var ( - c client.Client - prmInit client.PrmInit - prmDial client.PrmDial - ) - - prmInit.DisableFrostFSFailuresResolution() - prmDial.SetServerURI(addr.URIAddr()) + var c client.Client + prmInit := client.PrmInit{ + DisableFrostFSErrorResolution: true, + } if x.opts.Key != nil { - prmInit.SetDefaultPrivateKey(*x.opts.Key) + prmInit.Key = *x.opts.Key } + prmDial := client.PrmDial{ + Endpoint: addr.URIAddr(), + GRPCDialOptions: []grpc.DialOption{ + grpc.WithChainUnaryInterceptor( + metrics.NewUnaryClientInterceptor(), + tracing.NewUnaryClientInteceptor(), + ), + grpc.WithChainStreamInterceptor( + metrics.NewStreamClientInterceptor(), + tracing.NewStreamClientInterceptor(), + ), + }, + } if x.opts.DialTimeout > 0 { - prmDial.SetTimeout(x.opts.DialTimeout) + prmDial.DialTimeout = x.opts.DialTimeout } if x.opts.StreamTimeout > 0 { - prmDial.SetStreamTimeout(x.opts.StreamTimeout) + prmDial.StreamTimeout = x.opts.StreamTimeout } if x.opts.ResponseCallback != nil { - prmInit.SetResponseInfoCallback(x.opts.ResponseCallback) + prmInit.ResponseInfoCallback = x.opts.ResponseCallback } - prmDial.SetGRPCDialOptions( - grpc.WithChainUnaryInterceptor( - metrics.NewUnaryClientInterceptor(), - tracing.NewUnaryClientInteceptor(), - ), - grpc.WithChainStreamInterceptor( - metrics.NewStreamClientInterceptor(), - tracing.NewStreamClientInterceptor(), - ), - ) - c.Init(prmInit) err := c.Dial(ctx, prmDial) if err != nil { From 8d18fa159e085dde62336ec80f76fdfee358c412 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 17 Nov 2023 17:41:13 +0300 Subject: [PATCH 0157/1413] [#667] writecache: Fix flush test Allow to disable background flusher for testing purposes. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 - .../writecache/writecachebadger/flush.go | 3 ++ .../writecache/writecachebadger/flush_test.go | 1 + .../writecache/writecachebadger/options.go | 9 ++++ .../writecache/writecachebbolt/flush.go | 5 +- .../writecache/writecachebbolt/flush_test.go | 1 + .../writecache/writecachebbolt/options.go | 9 ++++ .../writecache/writecachebbolt/storage.go | 47 +++++-------------- 8 files changed, 40 insertions(+), 36 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 5f361cefb0..e8472357c2 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -296,7 +296,6 @@ const ( WritecacheFillingFlushMarksForObjectsInDatabase = "filling flush marks for objects in database" WritecacheFinishedUpdatingFlushMarks = "finished updating flush marks" WritecacheCantRemoveObjectsFromTheDatabase = "can't remove objects from the database" - WritecacheCantParseAddress = "can't parse address" WritecacheCantRemoveObjectFromWritecache = "can't remove object from write-cache" WritecacheDBValueLogGCRunCompleted = "value log GC run completed" WritecacheBadgerObjAlreadyScheduled = "object already scheduled for flush" diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush.go b/pkg/local_object_storage/writecache/writecachebadger/flush.go index 1ee6bbb66a..48e31dee6a 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush.go @@ -97,6 +97,9 @@ func (c *collector) send(ctx context.Context, cancel func(), buf *z.Buffer) erro // runFlushLoop starts background workers which periodically flush objects to the blobstor. func (c *cache) runFlushLoop(ctx context.Context) { + if c.disableBackgroundFlush { + return + } for i := 0; i < c.workersCount; i++ { c.wg.Add(1) go c.workerFlushSmall(ctx) diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go index 392654e487..5e3f60eab2 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go @@ -28,6 +28,7 @@ func TestFlush(t *testing.T) { WithMetabase(mb), WithBlobstor(bs), WithGCInterval(1 * time.Second), + WithDisableBackgroundFlush(), }, opts...)...) } diff --git a/pkg/local_object_storage/writecache/writecachebadger/options.go b/pkg/local_object_storage/writecache/writecachebadger/options.go index 63bfb196cc..d041a9b886 100644 --- a/pkg/local_object_storage/writecache/writecachebadger/options.go +++ b/pkg/local_object_storage/writecache/writecachebadger/options.go @@ -34,6 +34,8 @@ type options struct { metrics writecache.Metrics // gcInterval is the interval duration to run the GC cycle. gcInterval time.Duration + // disableBackgroundFlush is for testing purposes only. + disableBackgroundFlush bool } // WithLogger sets logger. @@ -108,3 +110,10 @@ func WithGCInterval(d time.Duration) Option { o.gcInterval = d } } + +// WithDisableBackgroundFlush disables background flush, for testing purposes only. +func WithDisableBackgroundFlush() Option { + return func(o *options) { + o.disableBackgroundFlush = true + } +} diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush.go b/pkg/local_object_storage/writecache/writecachebbolt/flush.go index d0e89a3858..d73e374f52 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush.go @@ -36,6 +36,9 @@ const ( // runFlushLoop starts background workers which periodically flush objects to the blobstor. func (c *cache) runFlushLoop(ctx context.Context) { + if c.disableBackgroundFlush { + return + } for i := 0; i < c.workersCount; i++ { c.wg.Add(1) go c.workerFlushSmall(ctx) @@ -200,7 +203,7 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { return err } - c.deleteFromDisk(ctx, []string{sAddr}) + c.deleteFromDisk(ctx, e.Address) return nil } diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go index 533cec1d2f..89add8115d 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go @@ -31,6 +31,7 @@ func TestFlush(t *testing.T) { WithSmallObjectSize(smallSize), WithMetabase(mb), WithBlobstor(bs), + WithDisableBackgroundFlush(), }, opts...)...) } diff --git a/pkg/local_object_storage/writecache/writecachebbolt/options.go b/pkg/local_object_storage/writecache/writecachebbolt/options.go index d8eedfc799..3ea3291925 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/options.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/options.go @@ -44,6 +44,8 @@ type options struct { openFile func(string, int, fs.FileMode) (*os.File, error) // metrics is metrics implementation metrics writecache.Metrics + // disableBackgroundFlush is for testing purposes only. + disableBackgroundFlush bool } // WithLogger sets logger. @@ -155,3 +157,10 @@ func WithMetrics(metrics writecache.Metrics) Option { o.metrics = metrics } } + +// WithDisableBackgroundFlush disables background flush, for testing purposes only. +func WithDisableBackgroundFlush() Option { + return func(o *options) { + o.disableBackgroundFlush = true + } +} diff --git a/pkg/local_object_storage/writecache/writecachebbolt/storage.go b/pkg/local_object_storage/writecache/writecachebbolt/storage.go index bff9385dc3..7a50306252 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/storage.go +++ b/pkg/local_object_storage/writecache/writecachebbolt/storage.go @@ -93,39 +93,18 @@ func (c *cache) deleteFromDB(key string) { } } -func (c *cache) deleteFromDisk(ctx context.Context, keys []string) []string { - if len(keys) == 0 { - return keys +func (c *cache) deleteFromDisk(ctx context.Context, addr oid.Address) { + _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr}) + if err != nil && !client.IsErrObjectNotFound(err) { + c.log.Error(logs.WritecacheCantRemoveObjectFromWritecache, zap.Error(err)) + } else if err == nil { + storagelog.Write(c.log, + storagelog.AddressField(addr.EncodeToString()), + storagelog.StorageTypeField(wcStorageType), + storagelog.OpField("fstree DELETE"), + ) + c.metrics.Evict(writecache.StorageTypeFSTree) + // counter changed by fstree + c.estimateCacheSize() } - - var copyIndex int - var addr oid.Address - - for i := range keys { - if err := addr.DecodeString(keys[i]); err != nil { - c.log.Error(logs.WritecacheCantParseAddress, zap.String("address", keys[i])) - continue - } - - _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr}) - if err != nil && !client.IsErrObjectNotFound(err) { - c.log.Error(logs.WritecacheCantRemoveObjectFromWritecache, zap.Error(err)) - - // Save the key for the next iteration. - keys[copyIndex] = keys[i] - copyIndex++ - continue - } else if err == nil { - storagelog.Write(c.log, - storagelog.AddressField(keys[i]), - storagelog.StorageTypeField(wcStorageType), - storagelog.OpField("fstree DELETE"), - ) - c.metrics.Evict(writecache.StorageTypeFSTree) - // counter changed by fstree - c.estimateCacheSize() - } - } - - return keys[:copyIndex] } From 07390ad4e359b7bc24a09af7e22a8f8bc7f781fc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 21 Nov 2023 13:20:36 +0300 Subject: [PATCH 0158/1413] [#715] node: Unify config parameter names Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 14 +++++++------- cmd/frostfs-node/config/engine/config_test.go | 8 ++++---- .../config/engine/shard/gc/config.go | 6 +++--- .../config/engine/shard/writecache/config.go | 6 +++--- cmd/frostfs-node/config/object/config.go | 8 ++++---- config/example/node.env | 10 +++++----- config/example/node.json | 10 +++++----- config/example/node.yaml | 8 ++++---- config/mainnet/config.yml | 4 ++-- docs/storage-node-configuration.md | 16 ++++++++-------- pkg/local_object_storage/shard/gc.go | 12 ++++++------ pkg/local_object_storage/shard/shard.go | 6 +++--- 12 files changed, 54 insertions(+), 54 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 3be33a2a1a..cc106cf957 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -126,10 +126,10 @@ type shardCfg struct { subStorages []subStorageCfg gcCfg struct { - removerBatchSize int - removerSleepInterval time.Duration - expiredCollectorBatchSize int - expiredCollectorWorkersCount int + removerBatchSize int + removerSleepInterval time.Duration + expiredCollectorBatchSize int + expiredCollectorWorkerCount int } writecacheCfg struct { @@ -256,7 +256,7 @@ func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, wc.maxBatchDelay = writeCacheCfg.BoltDB().MaxBatchDelay() wc.maxObjSize = writeCacheCfg.MaxObjectSize() wc.smallObjectSize = writeCacheCfg.SmallObjectSize() - wc.flushWorkerCount = writeCacheCfg.WorkersNumber() + wc.flushWorkerCount = writeCacheCfg.WorkerCount() wc.sizeLimit = writeCacheCfg.SizeLimit() wc.noSync = writeCacheCfg.NoSync() wc.gcInterval = writeCacheCfg.GCInterval() @@ -328,7 +328,7 @@ func (a *applicationConfiguration) setGCConfig(newConfig *shardCfg, oldConfig *s newConfig.gcCfg.removerBatchSize = gcCfg.RemoverBatchSize() newConfig.gcCfg.removerSleepInterval = gcCfg.RemoverSleepInterval() newConfig.gcCfg.expiredCollectorBatchSize = gcCfg.ExpiredCollectorBatchSize() - newConfig.gcCfg.expiredCollectorWorkersCount = gcCfg.ExpiredCollectorWorkersCount() + newConfig.gcCfg.expiredCollectorWorkerCount = gcCfg.ExpiredCollectorWorkerCount() } // internals contains application-specific internals that are created @@ -888,7 +888,7 @@ func (c *cfg) getShardOpts(shCfg shardCfg) shardOptsWithID { shard.WithRemoverBatchSize(shCfg.gcCfg.removerBatchSize), shard.WithGCRemoverSleepInterval(shCfg.gcCfg.removerSleepInterval), shard.WithExpiredCollectorBatchSize(shCfg.gcCfg.expiredCollectorBatchSize), - shard.WithExpiredCollectorWorkersCount(shCfg.gcCfg.expiredCollectorWorkersCount), + shard.WithExpiredCollectorWorkerCount(shCfg.gcCfg.expiredCollectorWorkerCount), shard.WithGCWorkerPoolInitializer(func(sz int) util.WorkerPool { pool, err := ants.NewPool(sz) fatalOnErr(err) diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 6b7c268ceb..665f70bcb6 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -74,7 +74,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, "tmp/0/cache", wc.Path()) require.EqualValues(t, 16384, wc.SmallObjectSize()) require.EqualValues(t, 134217728, wc.MaxObjectSize()) - require.EqualValues(t, 30, wc.WorkersNumber()) + require.EqualValues(t, 30, wc.WorkerCount()) require.EqualValues(t, 3221225472, wc.SizeLimit()) require.Equal(t, "tmp/0/meta", meta.Path()) @@ -108,7 +108,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 150, gc.RemoverBatchSize()) require.Equal(t, 2*time.Minute, gc.RemoverSleepInterval()) require.Equal(t, 1500, gc.ExpiredCollectorBatchSize()) - require.Equal(t, 15, gc.ExpiredCollectorWorkersCount()) + require.Equal(t, 15, gc.ExpiredCollectorWorkerCount()) require.Equal(t, false, sc.RefillMetabase()) require.Equal(t, mode.ReadOnly, sc.Mode()) @@ -125,7 +125,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, "tmp/1/cache", wc.Path()) require.EqualValues(t, 16384, wc.SmallObjectSize()) require.EqualValues(t, 134217728, wc.MaxObjectSize()) - require.EqualValues(t, 30, wc.WorkersNumber()) + require.EqualValues(t, 30, wc.WorkerCount()) require.EqualValues(t, 4294967296, wc.SizeLimit()) require.Equal(t, "tmp/1/meta", meta.Path()) @@ -157,7 +157,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 200, gc.RemoverBatchSize()) require.Equal(t, 5*time.Minute, gc.RemoverSleepInterval()) require.Equal(t, gcconfig.ExpiredCollectorBatchSizeDefault, gc.ExpiredCollectorBatchSize()) - require.Equal(t, gcconfig.ExpiredCollectorWorkersCountDefault, gc.ExpiredCollectorWorkersCount()) + require.Equal(t, gcconfig.ExpiredCollectorWorkersCountDefault, gc.ExpiredCollectorWorkerCount()) require.Equal(t, true, sc.RefillMetabase()) require.Equal(t, mode.ReadWrite, sc.Mode()) diff --git a/cmd/frostfs-node/config/engine/shard/gc/config.go b/cmd/frostfs-node/config/engine/shard/gc/config.go index 0500697c88..8cb90d3ffd 100644 --- a/cmd/frostfs-node/config/engine/shard/gc/config.go +++ b/cmd/frostfs-node/config/engine/shard/gc/config.go @@ -63,14 +63,14 @@ func (x *Config) RemoverSleepInterval() time.Duration { return RemoverSleepIntervalDefault } -// ExpiredCollectorWorkersCount returns the value of "expired_collector_workers_count" +// ExpiredCollectorWorkerCount returns the value of "expired_collector_worker_count" // config parameter. // // Returns ExpiredCollectorWorkersCountDefault if the value is not a positive number. -func (x *Config) ExpiredCollectorWorkersCount() int { +func (x *Config) ExpiredCollectorWorkerCount() int { s := config.IntSafe( (*config.Config)(x), - "expired_collector_workers_count", + "expired_collector_worker_count", ) if s > 0 { diff --git a/cmd/frostfs-node/config/engine/shard/writecache/config.go b/cmd/frostfs-node/config/engine/shard/writecache/config.go index 504fe3ca23..d0fd4bf75f 100644 --- a/cmd/frostfs-node/config/engine/shard/writecache/config.go +++ b/cmd/frostfs-node/config/engine/shard/writecache/config.go @@ -106,13 +106,13 @@ func (x *Config) MaxObjectSize() uint64 { return MaxSizeDefault } -// WorkersNumber returns the value of "workers_number" config parameter. +// WorkerCount returns the value of "flush_worker_count" config parameter. // // Returns WorkersNumberDefault if the value is not a positive number. -func (x *Config) WorkersNumber() int { +func (x *Config) WorkerCount() int { c := config.IntSafe( (*config.Config)(x), - "workers_number", + "flush_worker_count", ) if c > 0 { diff --git a/cmd/frostfs-node/config/object/config.go b/cmd/frostfs-node/config/object/config.go index f7a33b5e05..876dc3ef12 100644 --- a/cmd/frostfs-node/config/object/config.go +++ b/cmd/frostfs-node/config/object/config.go @@ -28,11 +28,11 @@ func Put(c *config.Config) PutConfig { } } -// PoolSizeRemote returns the value of "pool_size_remote" config parameter. +// PoolSizeRemote returns the value of "remote_pool_size" config parameter. // // Returns PutPoolSizeDefault if the value is not a positive number. func (g PutConfig) PoolSizeRemote() int { - v := config.Int(g.cfg, "pool_size_remote") + v := config.Int(g.cfg, "remote_pool_size") if v > 0 { return int(v) } @@ -40,11 +40,11 @@ func (g PutConfig) PoolSizeRemote() int { return PutPoolSizeDefault } -// PoolSizeLocal returns the value of "pool_size_local" config parameter. +// PoolSizeLocal returns the value of "local_pool_size" config parameter. // // Returns PutPoolSizeDefault if the value is not a positive number. func (g PutConfig) PoolSizeLocal() int { - v := config.Int(g.cfg, "pool_size_local") + v := config.Int(g.cfg, "local_pool_size") if v > 0 { return int(v) } diff --git a/config/example/node.env b/config/example/node.env index dda740cf16..f4dc218a3c 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -84,8 +84,8 @@ FROSTFS_REPLICATOR_PUT_TIMEOUT=15s FROSTFS_REPLICATOR_POOL_SIZE=10 # Object service section -FROSTFS_OBJECT_PUT_POOL_SIZE_REMOTE=100 -FROSTFS_OBJECT_PUT_POOL_SIZE_LOCAL=200 +FROSTFS_OBJECT_PUT_REMOTE_POOL_SIZE=100 +FROSTFS_OBJECT_PUT_LOCAL_POOL_SIZE=200 FROSTFS_OBJECT_PUT_SKIP_SESSION_TOKEN_ISSUER_VERIFICATION=true FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME=10 @@ -103,7 +103,7 @@ FROSTFS_STORAGE_SHARD_0_WRITECACHE_NO_SYNC=true FROSTFS_STORAGE_SHARD_0_WRITECACHE_PATH=tmp/0/cache FROSTFS_STORAGE_SHARD_0_WRITECACHE_SMALL_OBJECT_SIZE=16384 FROSTFS_STORAGE_SHARD_0_WRITECACHE_MAX_OBJECT_SIZE=134217728 -FROSTFS_STORAGE_SHARD_0_WRITECACHE_WORKERS_NUMBER=30 +FROSTFS_STORAGE_SHARD_0_WRITECACHE_FLUSH_WORKER_COUNT=30 FROSTFS_STORAGE_SHARD_0_WRITECACHE_CAPACITY=3221225472 ### Metabase config FROSTFS_STORAGE_SHARD_0_METABASE_PATH=tmp/0/meta @@ -142,7 +142,7 @@ FROSTFS_STORAGE_SHARD_0_GC_REMOVER_SLEEP_INTERVAL=2m #### Limit of objects to be marked expired by the garbage collector FROSTFS_STORAGE_SHARD_0_GC_EXPIRED_COLLECTOR_BATCH_SIZE=1500 #### Limit of concurrent workers collecting expired objects by the garbage collector -FROSTFS_STORAGE_SHARD_0_GC_EXPIRED_COLLECTOR_WORKERS_COUNT=15 +FROSTFS_STORAGE_SHARD_0_GC_EXPIRED_COLLECTOR_WORKER_COUNT=15 ## 1 shard ### Flag to refill Metabase from BlobStor @@ -154,7 +154,7 @@ FROSTFS_STORAGE_SHARD_1_WRITECACHE_ENABLED=true FROSTFS_STORAGE_SHARD_1_WRITECACHE_PATH=tmp/1/cache FROSTFS_STORAGE_SHARD_1_WRITECACHE_SMALL_OBJECT_SIZE=16384 FROSTFS_STORAGE_SHARD_1_WRITECACHE_MAX_OBJECT_SIZE=134217728 -FROSTFS_STORAGE_SHARD_1_WRITECACHE_WORKERS_NUMBER=30 +FROSTFS_STORAGE_SHARD_1_WRITECACHE_FLUSH_WORKER_COUNT=30 FROSTFS_STORAGE_SHARD_1_WRITECACHE_CAPACITY=4294967296 ### Metabase config FROSTFS_STORAGE_SHARD_1_METABASE_PATH=tmp/1/meta diff --git a/config/example/node.json b/config/example/node.json index 1038d5e5c0..c2e3d0a5d4 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -129,8 +129,8 @@ "tombstone_lifetime": 10 }, "put": { - "pool_size_remote": 100, - "pool_size_local": 200, + "remote_pool_size": 100, + "local_pool_size": 200, "skip_session_token_issuer_verification": true } }, @@ -147,7 +147,7 @@ "path": "tmp/0/cache", "small_object_size": 16384, "max_object_size": 134217728, - "workers_number": 30, + "flush_worker_count": 30, "capacity": 3221225472 }, "metabase": { @@ -190,7 +190,7 @@ "remover_batch_size": 150, "remover_sleep_interval": "2m", "expired_collector_batch_size": 1500, - "expired_collector_workers_count": 15 + "expired_collector_worker_count": 15 } }, "1": { @@ -203,7 +203,7 @@ "memcache_capacity": 2147483648, "small_object_size": 16384, "max_object_size": 134217728, - "workers_number": 30, + "flush_worker_count": 30, "capacity": 4294967296 }, "metabase": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 8b2046e954..d04e122b6c 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -108,8 +108,8 @@ object: delete: tombstone_lifetime: 10 # tombstone "local" lifetime in epochs put: - pool_size_remote: 100 # number of async workers for remote PUT operations - pool_size_local: 200 # number of async workers for local PUT operations + remote_pool_size: 100 # number of async workers for remote PUT operations + local_pool_size: 200 # number of async workers for local PUT operations skip_session_token_issuer_verification: true # session token issuer verification will be skipped if true storage: @@ -126,7 +126,7 @@ storage: type: bbolt small_object_size: 16k # size threshold for "small" objects which are cached in key-value DB, not in FS, bytes max_object_size: 134217728 # size threshold for "big" objects which bypass write-cache and go to the storage directly, bytes - workers_number: 30 # number of write-cache flusher threads + flush_worker_count: 30 # number of write-cache flusher threads metabase: perm: 0644 # permissions for metabase files(directories: +x for current user and group) @@ -196,7 +196,7 @@ storage: remover_batch_size: 150 # number of objects to be removed by the garbage collector remover_sleep_interval: 2m # frequency of the garbage collector invocation expired_collector_batch_size: 1500 # number of objects to be marked expired by the garbage collector - expired_collector_workers_count: 15 # number of concurrent workers collecting expired objects by the garbage collector + expired_collector_worker_count: 15 # number of concurrent workers collecting expired objects by the garbage collector 1: writecache: diff --git a/config/mainnet/config.yml b/config/mainnet/config.yml index 7db476e554..d86ea451fe 100644 --- a/config/mainnet/config.yml +++ b/config/mainnet/config.yml @@ -50,8 +50,8 @@ prometheus: object: put: - pool_size_remote: 100 - pool_size_local: 100 + remote_pool_size: 100 + local_pool_size: 100 morph: rpc_endpoint: diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 5e9f3caf7b..71eabc0423 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -243,7 +243,7 @@ gc: remover_batch_size: 200 remover_sleep_interval: 5m expired_collector_batch_size: 500 - expired_collector_workers_count: 5 + expired_collector_worker_count: 5 ``` | Parameter | Type | Default value | Description | @@ -251,7 +251,7 @@ gc: | `remover_batch_size` | `int` | `100` | Amount of objects to grab in a single batch. | | `remover_sleep_interval` | `duration` | `1m` | Time to sleep between iterations. | | `expired_collector_batch_size` | `int` | `500` | Max amount of expired objects to grab in a single batch. | -| `expired_collector_workers_count` | `int` | `5` | Max amount of concurrent expired objects workers. | +| `expired_collector_worker_count` | `int` | `5` | Max amount of concurrent expired objects workers. | ### `metabase` subsection @@ -280,7 +280,7 @@ writecache: capacity: 4294967296 small_object_size: 16384 max_object_size: 134217728 - workers_number: 30 + flush_worker_count: 30 ``` | Parameter | Type | Default value | Description | @@ -290,7 +290,7 @@ writecache: | `capacity` | `size` | unrestricted | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | | `small_object_size` | `size` | `32K` | Maximum object size for "small" objects. This objects are stored in a key-value database instead of a file-system. | | `max_object_size` | `size` | `64M` | Maximum object size allowed to be stored in the writecache. | -| `workers_number` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | +| `flush_worker_count` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | | `max_batch_size` | `int` | `1000` | Maximum amount of small object `PUT` operations to perform in a single transaction. | | `max_batch_delay` | `duration` | `10ms` | Maximum delay before a batch starts. | @@ -415,7 +415,7 @@ replicator: | Parameter | Type | Default value | Description | |---------------|------------|----------------------------------------|---------------------------------------------| | `put_timeout` | `duration` | `5s` | Timeout for performing the `PUT` operation. | -| `pool_size` | `int` | Equal to `object.put.pool_size_remote` | Maximum amount of concurrent replications. | +| `pool_size` | `int` | Equal to `object.put.remote_pool_size` | Maximum amount of concurrent replications. | # `object` section Contains object-service related parameters. @@ -423,14 +423,14 @@ Contains object-service related parameters. ```yaml object: put: - pool_size_remote: 100 + remote_pool_size: 100 ``` | Parameter | Type | Default value | Description | |-----------------------------|-------|---------------|------------------------------------------------------------------------------------------------| | `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. | -| `put.pool_size_remote` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. | -| `put.pool_size_local` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. | +| `put.remote_pool_size` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. | +| `put.local_pool_size` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. | # `runtime` section Contains runtime parameters. diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 346903c5cd..e16f89457b 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -115,8 +115,8 @@ type gcCfg struct { workerPoolInit func(int) util.WorkerPool - expiredCollectorWorkersCount int - expiredCollectorBatchSize int + expiredCollectorWorkerCount int + expiredCollectorBatchSize int metrics GCMectrics @@ -313,16 +313,16 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { return } -func (s *Shard) getExpiredObjectsParameters() (workersCount, batchSize int) { - workersCount = minExpiredWorkers +func (s *Shard) getExpiredObjectsParameters() (workerCount, batchSize int) { + workerCount = minExpiredWorkers batchSize = minExpiredBatchSize if s.gc.gcCfg.expiredCollectorBatchSize > batchSize { batchSize = s.gc.gcCfg.expiredCollectorBatchSize } - if s.gc.gcCfg.expiredCollectorWorkersCount > workersCount { - workersCount = s.gc.gcCfg.expiredCollectorWorkersCount + if s.gc.gcCfg.expiredCollectorWorkerCount > workerCount { + workerCount = s.gc.gcCfg.expiredCollectorWorkerCount } return } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 07b7740220..aa87e0cfcb 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -365,11 +365,11 @@ func WithExpiredCollectorBatchSize(size int) Option { } } -// WithExpiredCollectorWorkersCount returns option to set concurrent +// WithExpiredCollectorWorkerCount returns option to set concurrent // workers count of expired object collection operation. -func WithExpiredCollectorWorkersCount(count int) Option { +func WithExpiredCollectorWorkerCount(count int) Option { return func(c *cfg) { - c.gcCfg.expiredCollectorWorkersCount = count + c.gcCfg.expiredCollectorWorkerCount = count } } From c99157f0b20a503a3baab25e96eafbef0cff82cb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 21 Nov 2023 11:42:08 +0300 Subject: [PATCH 0159/1413] [#821] go.mod: Update SDK-Go version Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 7d2b934865..2714e15679 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231114081800-3787477133f3 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index 070c246ba1..7660d9dcde 100644 --- a/go.sum +++ b/go.sum @@ -732,8 +732,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231114081800-3787477133f3 h1:Qa35bB58plMb14LIsYzu2ibeYfsY2taFnbZytv9Ao3M= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231114081800-3787477133f3/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e h1:RoGxgSNyVxDaYgjb40P+Xy6val+rs7b5QQtGkIUpUoY= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f h1:Rq95TuEkqc3T1EN5ZU1Vgf6H33TR95hz97ca8jrUciQ= From c516c7c5f46d6a3ae8e183f4582baf112ca0a50e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 21 Nov 2023 11:42:30 +0300 Subject: [PATCH 0160/1413] [#821] node: Pass user.ID by value Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/accounting/balance.go | 2 +- cmd/frostfs-cli/modules/container/list.go | 2 +- cmd/frostfs-cli/modules/object/lock.go | 2 +- cmd/frostfs-cli/modules/object/put.go | 4 ++-- pkg/core/object/fmt.go | 4 ++-- pkg/core/object/fmt_test.go | 14 +++++++------- pkg/services/object/acl/acl_test.go | 6 +++--- pkg/services/object/acl/eacl/v2/object.go | 4 ++-- pkg/services/object/delete/exec.go | 4 ++-- pkg/services/object/put/streamer.go | 2 +- pkg/services/object/util/key_test.go | 4 ++-- .../session/storage/persistent/executor_test.go | 6 +++--- 12 files changed, 27 insertions(+), 27 deletions(-) diff --git a/cmd/frostfs-cli/modules/accounting/balance.go b/cmd/frostfs-cli/modules/accounting/balance.go index 8e975fb03a..d10b9eaa11 100644 --- a/cmd/frostfs-cli/modules/accounting/balance.go +++ b/cmd/frostfs-cli/modules/accounting/balance.go @@ -39,7 +39,7 @@ var accountingBalanceCmd = &cobra.Command{ var prm internalclient.BalanceOfPrm prm.SetClient(cli) - prm.Account = &idUser + prm.Account = idUser res, err := internalclient.BalanceOf(cmd.Context(), prm) commonCmd.ExitOnErr(cmd, "rpc error: %w", err) diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index 1e7ba96ea5..86c1e5fba3 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -47,7 +47,7 @@ var listContainersCmd = &cobra.Command{ var prm internalclient.ListContainersPrm prm.SetClient(cli) - prm.Account = &idUser + prm.Account = idUser res, err := internalclient.ListContainers(cmd.Context(), prm) commonCmd.ExitOnErr(cmd, "rpc error: %w", err) diff --git a/cmd/frostfs-cli/modules/object/lock.go b/cmd/frostfs-cli/modules/object/lock.go index fa1898586f..d2e9af24cf 100644 --- a/cmd/frostfs-cli/modules/object/lock.go +++ b/cmd/frostfs-cli/modules/object/lock.go @@ -94,7 +94,7 @@ var objectLockCmd = &cobra.Command{ obj := objectSDK.New() obj.SetContainerID(cnr) - obj.SetOwnerID(&idOwner) + obj.SetOwnerID(idOwner) obj.SetType(objectSDK.TypeLock) obj.SetAttributes(expirationAttr) obj.SetPayload(lock.Marshal()) diff --git a/cmd/frostfs-cli/modules/object/put.go b/cmd/frostfs-cli/modules/object/put.go index 97bb12dbc0..a41d3c0aaa 100644 --- a/cmd/frostfs-cli/modules/object/put.go +++ b/cmd/frostfs-cli/modules/object/put.go @@ -93,7 +93,7 @@ func putObject(cmd *cobra.Command, _ []string) { attrs := getAllObjectAttributes(cmd) obj.SetContainerID(cnr) - obj.SetOwnerID(&ownerID) + obj.SetOwnerID(ownerID) obj.SetAttributes(attrs...) notificationInfo, err := parseObjectNotifications(cmd) @@ -160,7 +160,7 @@ func readFilePayload(filename string, cmd *cobra.Command) (io.Reader, cid.ID, us commonCmd.ExitOnErr(cmd, "can't unmarshal object from given file: %w", objTemp.Unmarshal(buf)) payloadReader := bytes.NewReader(objTemp.Payload()) cnr, _ := objTemp.ContainerID() - ownerID := *objTemp.OwnerID() + ownerID := objTemp.OwnerID() return payloadReader, cnr, ownerID } diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index e657677239..e266800b25 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -165,7 +165,7 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { } token := obj.SessionToken() - ownerID := *obj.OwnerID() + ownerID := obj.OwnerID() if token == nil || !token.AssertAuthKey(&key) { return v.checkOwnerKey(ownerID, key) @@ -412,7 +412,7 @@ func (v *FormatValidator) checkAttributes(obj *objectSDK.Object) error { var errIncorrectOwner = errors.New("incorrect object owner") func (v *FormatValidator) checkOwner(obj *objectSDK.Object) error { - if idOwner := obj.OwnerID(); idOwner == nil || len(idOwner.WalletBytes()) == 0 { + if idOwner := obj.OwnerID(); idOwner.IsEmpty() { return errIncorrectOwner } diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index 2a5b5690c4..a8901ad6d9 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -32,7 +32,7 @@ func blankValidObject(key *ecdsa.PrivateKey) *objectSDK.Object { obj := objectSDK.New() obj.SetContainerID(cidtest.ID()) - obj.SetOwnerID(&idOwner) + obj.SetOwnerID(idOwner) return obj } @@ -107,7 +107,7 @@ func TestFormatValidator_Validate(t *testing.T) { obj := objectSDK.New() obj.SetContainerID(cidtest.ID()) obj.SetSessionToken(tok) - obj.SetOwnerID(&idOwner) + obj.SetOwnerID(idOwner) require.NoError(t, objectSDK.SetIDWithSignature(ownerKey.PrivateKey, obj)) @@ -303,7 +303,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { obj := objectSDK.New() obj.SetContainerID(cidtest.ID()) obj.SetSessionToken(tok) - obj.SetOwnerID(&owner) + obj.SetOwnerID(owner) require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) require.NoError(t, v.Validate(context.Background(), obj, false)) @@ -352,7 +352,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { obj := objectSDK.New() obj.SetContainerID(cnrID) obj.SetSessionToken(tok) - obj.SetOwnerID(&owner) + obj.SetOwnerID(owner) require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) require.NoError(t, v.Validate(context.Background(), obj, false)) @@ -386,7 +386,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { obj := objectSDK.New() obj.SetContainerID(cnrID) obj.SetSessionToken(tok) - obj.SetOwnerID(&owner) + obj.SetOwnerID(owner) require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) v := NewFormatValidator( @@ -459,7 +459,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { obj := objectSDK.New() obj.SetContainerID(cnrID) obj.SetSessionToken(tok) - obj.SetOwnerID(&owner) + obj.SetOwnerID(owner) require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) v := NewFormatValidator( @@ -535,7 +535,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { obj := objectSDK.New() obj.SetContainerID(cnrID) obj.SetSessionToken(tok) - obj.SetOwnerID(&owner) + obj.SetOwnerID(owner) require.NoError(t, objectSDK.SetIDWithSignature(signer.PrivateKey, obj)) v := NewFormatValidator( diff --git a/pkg/services/object/acl/acl_test.go b/pkg/services/object/acl/acl_test.go index b9b82dac82..d63cb12856 100644 --- a/pkg/services/object/acl/acl_test.go +++ b/pkg/services/object/acl/acl_test.go @@ -39,14 +39,14 @@ func TestStickyCheck(t *testing.T) { info.SetSenderKey(make([]byte, 33)) // any non-empty key info.SetRequestRole(acl.RoleContainer) - require.True(t, checker.StickyBitCheck(info, *usertest.ID())) + require.True(t, checker.StickyBitCheck(info, usertest.ID())) var basicACL acl.Basic basicACL.MakeSticky() info.SetBasicACL(basicACL) - require.True(t, checker.StickyBitCheck(info, *usertest.ID())) + require.True(t, checker.StickyBitCheck(info, usertest.ID())) }) t.Run("owner ID and/or public key emptiness", func(t *testing.T) { @@ -72,7 +72,7 @@ func TestStickyCheck(t *testing.T) { var ownerID user.ID if withOwner { - ownerID = *usertest.ID() + ownerID = usertest.ID() } require.Equal(t, expected, checker.StickyBitCheck(info, ownerID)) diff --git a/pkg/services/object/acl/eacl/v2/object.go b/pkg/services/object/acl/eacl/v2/object.go index 690e4aa70e..72bd4c2d23 100644 --- a/pkg/services/object/acl/eacl/v2/object.go +++ b/pkg/services/object/acl/eacl/v2/object.go @@ -62,8 +62,8 @@ func headersFromObject(obj *objectSDK.Object, cnr cid.ID, oid *oid.ID) []eaclSDK res = append(res, oidHeader(*oid)) } - if idOwner := obj.OwnerID(); idOwner != nil { - res = append(res, ownerIDHeader(*idOwner)) + if idOwner := obj.OwnerID(); !idOwner.IsEmpty() { + res = append(res, ownerIDHeader(idOwner)) } cs, ok := obj.PayloadChecksum() diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index aac8c88601..d48f8ab7b4 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -176,11 +176,11 @@ func (exec *execCtx) initTombstoneObject() error { tokenSession := exec.commonParameters().SessionToken() if tokenSession != nil { issuer := tokenSession.Issuer() - exec.tombstoneObj.SetOwnerID(&issuer) + exec.tombstoneObj.SetOwnerID(issuer) } else { // make local node a tombstone object owner localUser := exec.svc.netInfo.LocalNodeID() - exec.tombstoneObj.SetOwnerID(&localUser) + exec.tombstoneObj.SetOwnerID(localUser) } var a objectSDK.Attribute diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 10f932849d..a9abe407d3 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -112,7 +112,7 @@ func (p *Streamer) initTrustedTarget(prm *PutInitPrm) error { // If it isn't owner key, replication attempts will fail, thus this check. if sToken == nil { ownerObj := prm.hdr.OwnerID() - if ownerObj == nil { + if ownerObj.IsEmpty() { return errors.New("missing object owner") } diff --git a/pkg/services/object/util/key_test.go b/pkg/services/object/util/key_test.go index 76e320e0c0..cb7ddfde53 100644 --- a/pkg/services/object/util/key_test.go +++ b/pkg/services/object/util/key_test.go @@ -25,7 +25,7 @@ func TestNewKeyStorage(t *testing.T) { tokenStor := tokenStorage.NewTokenStore() stor := util.NewKeyStorage(&nodeKey.PrivateKey, tokenStor, mockedNetworkState{42}) - owner := *usertest.ID() + owner := usertest.ID() t.Run("node key", func(t *testing.T) { key, err := stor.GetKey(nil) @@ -36,7 +36,7 @@ func TestNewKeyStorage(t *testing.T) { t.Run("unknown token", func(t *testing.T) { _, err = stor.GetKey(&util.SessionInfo{ ID: uuid.New(), - Owner: *usertest.ID(), + Owner: usertest.ID(), }) require.Error(t, err) }) diff --git a/pkg/services/session/storage/persistent/executor_test.go b/pkg/services/session/storage/persistent/executor_test.go index ee0c8f9151..39cb143595 100644 --- a/pkg/services/session/storage/persistent/executor_test.go +++ b/pkg/services/session/storage/persistent/executor_test.go @@ -22,7 +22,7 @@ func TestTokenStore(t *testing.T) { defer ts.Close() - owner := *usertest.ID() + owner := usertest.ID() var ownerV2 refs.OwnerID owner.WriteToV2(&ownerV2) @@ -66,7 +66,7 @@ func TestTokenStore_Persistent(t *testing.T) { ts, err := NewTokenStore(path) require.NoError(t, err) - idOwner := *usertest.ID() + idOwner := usertest.ID() var idOwnerV2 refs.OwnerID idOwner.WriteToV2(&idOwnerV2) @@ -127,7 +127,7 @@ func TestTokenStore_RemoveOld(t *testing.T) { defer ts.Close() - owner := *usertest.ID() + owner := usertest.ID() var ownerV2 refs.OwnerID owner.WriteToV2(&ownerV2) From 5048236441b2faf8b9b411fc9ed246421659324f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 Nov 2023 13:33:30 +0300 Subject: [PATCH 0161/1413] [#808] go.mod: Update dependencies Signed-off-by: Evgenii Stratonikov --- go.mod | 10 +++++----- go.sum | 16 ++++++++++------ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 2714e15679..cfa6dd7a6e 100644 --- a/go.mod +++ b/go.mod @@ -27,11 +27,11 @@ require ( github.com/paulmach/orb v0.9.2 github.com/prometheus/client_golang v1.16.0 github.com/spf13/cast v1.5.1 - github.com/spf13/cobra v1.7.0 + github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 - go.etcd.io/bbolt v1.3.7 + go.etcd.io/bbolt v1.3.8 go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 go.uber.org/zap v1.26.0 @@ -63,7 +63,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dgraph-io/badger/v4 v4.1.0 @@ -124,8 +124,8 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.14.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 7660d9dcde..8c36890230 100644 --- a/go.sum +++ b/go.sum @@ -1111,8 +1111,9 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -2028,8 +2029,8 @@ github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -2148,8 +2149,9 @@ go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= +go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= @@ -2686,8 +2688,9 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2726,8 +2729,9 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From e81a58b8da3c5b606e892b2927feeeed939dfa55 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 Nov 2023 14:26:23 +0300 Subject: [PATCH 0162/1413] [#808] cli: Use MarkFlagsOneRequired after cobra update Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/control/ir_remove_container.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/ir_remove_container.go b/cmd/frostfs-cli/modules/control/ir_remove_container.go index 52eaa574d5..a66d7e06df 100644 --- a/cmd/frostfs-cli/modules/control/ir_remove_container.go +++ b/cmd/frostfs-cli/modules/control/ir_remove_container.go @@ -1,8 +1,6 @@ package control import ( - "errors" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -35,6 +33,7 @@ func initControlIRRemoveContainerCmd() { flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) flags.String(ownerFlag, "", "Container owner's wallet address.") removeContainerCmd.MarkFlagsMutuallyExclusive(commonflags.CIDFlag, ownerFlag) + removeContainerCmd.MarkFlagsOneRequired(commonflags.CIDFlag, ownerFlag) } func removeContainer(cmd *cobra.Command, _ []string) { @@ -74,10 +73,6 @@ func prepareRemoveContainerRequest(cmd *cobra.Command) *ircontrol.RemoveContaine ownerStr, err := cmd.Flags().GetString(ownerFlag) commonCmd.ExitOnErr(cmd, "failed to get owner: ", err) - if len(ownerStr) == 0 && len(cidStr) == 0 { - commonCmd.ExitOnErr(cmd, "invalid usage: %w", errors.New("neither owner's wallet address nor container ID are specified")) - } - if len(ownerStr) > 0 { var owner user.ID commonCmd.ExitOnErr(cmd, "invalid owner ID: %w", owner.DecodeString(ownerStr)) From 5521737f0b4cf5bb1ae22bfcfb3e7539617e8fd0 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 Nov 2023 14:31:37 +0300 Subject: [PATCH 0163/1413] [#808] cli: Use EnableTraverseRunHooks in cobra Adopt EnableTraverseRunHooks to get rid of tracing boilerplate in multiple commands. Now adding `--trace` flag is sufficient for a command to support tracing. Finally, it looks how it _should_. Refs https://git.frostfs.info/TrueCloudLab/frostfs-node/pulls/406 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/accounting/root.go | 3 --- cmd/frostfs-cli/modules/container/root.go | 3 --- cmd/frostfs-cli/modules/netmap/root.go | 3 --- cmd/frostfs-cli/modules/object/root.go | 3 --- cmd/frostfs-cli/modules/root.go | 5 +++++ cmd/frostfs-cli/modules/session/create.go | 3 --- 6 files changed, 5 insertions(+), 15 deletions(-) diff --git a/cmd/frostfs-cli/modules/accounting/root.go b/cmd/frostfs-cli/modules/accounting/root.go index f94488b6f7..8ab8aa1255 100644 --- a/cmd/frostfs-cli/modules/accounting/root.go +++ b/cmd/frostfs-cli/modules/accounting/root.go @@ -1,7 +1,6 @@ package accounting import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -18,9 +17,7 @@ var Cmd = &cobra.Command{ _ = viper.BindPFlag(commonflags.WalletPath, flags.Lookup(commonflags.WalletPath)) _ = viper.BindPFlag(commonflags.Account, flags.Lookup(commonflags.Account)) _ = viper.BindPFlag(commonflags.RPC, flags.Lookup(commonflags.RPC)) - common.StartClientCommandSpan(cmd) }, - PersistentPostRun: common.StopClientCommandSpan, } func init() { diff --git a/cmd/frostfs-cli/modules/container/root.go b/cmd/frostfs-cli/modules/container/root.go index f3c3e0e3a0..ab7f5fb908 100644 --- a/cmd/frostfs-cli/modules/container/root.go +++ b/cmd/frostfs-cli/modules/container/root.go @@ -1,7 +1,6 @@ package container import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "github.com/spf13/cobra" ) @@ -16,9 +15,7 @@ var Cmd = &cobra.Command{ // the viper before execution commonflags.Bind(cmd) commonflags.BindAPI(cmd) - common.StartClientCommandSpan(cmd) }, - PersistentPostRun: common.StopClientCommandSpan, } func init() { diff --git a/cmd/frostfs-cli/modules/netmap/root.go b/cmd/frostfs-cli/modules/netmap/root.go index 006ac6d9f3..aaa83f12fc 100644 --- a/cmd/frostfs-cli/modules/netmap/root.go +++ b/cmd/frostfs-cli/modules/netmap/root.go @@ -1,7 +1,6 @@ package netmap import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "github.com/spf13/cobra" ) @@ -15,9 +14,7 @@ var Cmd = &cobra.Command{ // the viper before execution commonflags.Bind(cmd) commonflags.BindAPI(cmd) - common.StartClientCommandSpan(cmd) }, - PersistentPostRun: common.StopClientCommandSpan, } func init() { diff --git a/cmd/frostfs-cli/modules/object/root.go b/cmd/frostfs-cli/modules/object/root.go index d9d4bb84d8..e04366f4d3 100644 --- a/cmd/frostfs-cli/modules/object/root.go +++ b/cmd/frostfs-cli/modules/object/root.go @@ -1,7 +1,6 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "github.com/spf13/cobra" ) @@ -16,9 +15,7 @@ var Cmd = &cobra.Command{ // the viper before execution commonflags.Bind(cmd) commonflags.BindAPI(cmd) - common.StartClientCommandSpan(cmd) }, - PersistentPostRun: common.StopClientCommandSpan, } func init() { diff --git a/cmd/frostfs-cli/modules/root.go b/cmd/frostfs-cli/modules/root.go index 808bd6d073..87e6a905ff 100644 --- a/cmd/frostfs-cli/modules/root.go +++ b/cmd/frostfs-cli/modules/root.go @@ -46,6 +46,10 @@ of frostfs-api and some useful utilities for compiling ACL rules from JSON notation, managing container access through protocol gates, querying network map and much more!`, Run: entryPoint, + PersistentPreRun: func(cmd *cobra.Command, _ []string) { + common.StartClientCommandSpan(cmd) + }, + PersistentPostRun: common.StopClientCommandSpan, } // Execute adds all child commands to the root command and sets flags appropriately. @@ -57,6 +61,7 @@ func Execute() { func init() { cobra.OnInitialize(initConfig) + cobra.EnableTraverseRunHooks = true // use stdout as default output for cmd.Print() rootCmd.SetOut(os.Stdout) diff --git a/cmd/frostfs-cli/modules/session/create.go b/cmd/frostfs-cli/modules/session/create.go index 94ae595a8f..e92e4baa6d 100644 --- a/cmd/frostfs-cli/modules/session/create.go +++ b/cmd/frostfs-cli/modules/session/create.go @@ -6,7 +6,6 @@ import ( "os" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" @@ -33,9 +32,7 @@ var createCmd = &cobra.Command{ PersistentPreRun: func(cmd *cobra.Command, args []string) { _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) _ = viper.BindPFlag(commonflags.Account, cmd.Flags().Lookup(commonflags.Account)) - common.StartClientCommandSpan(cmd) }, - PersistentPostRun: common.StopClientCommandSpan, } func init() { From 306f12e6c5eab0cc9684efe04b267572b6ac60e8 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 28 Nov 2023 10:32:56 +0300 Subject: [PATCH 0164/1413] [#828] adm: Fix policy contract deploy Signed-off-by: Airat Arifullin --- cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 5183114f9b..4ba72ef414 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -575,8 +575,10 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an c.Contracts[containerContract].Hash, keysParam, configParam) - case proxyContract, policyContract: + case proxyContract: items = nil + case policyContract: + items = []any{nil} default: panic(fmt.Sprintf("invalid contract name: %s", ctrName)) } From b215817e14698d5dc48f356160ba7aa83b502f62 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 28 Nov 2023 10:12:39 +0300 Subject: [PATCH 0165/1413] [#741] treesvc: Remove unused height variables Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 + pkg/services/tree/sync.go | 80 ++++++++++++++++++--------------------- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index e8472357c2..fad5f464d5 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -64,6 +64,7 @@ const ( TreeCouldNotUpdateLastSynchronizedHeightForATree = "could not update last synchronized height for a tree" TreeSynchronizeTree = "synchronize tree" TreeFailedToRunTreeSynchronizationOverAllNodes = "failed to run tree synchronization over all nodes" + TreeFailedToRunTreeSynchronizationForSpecificNode = "failed to run tree synchronization for specific node" TreeSyncingTrees = "syncing trees..." TreeCouldNotFetchContainers = "could not fetch containers" TreeTreesHaveBeenSynchronized = "trees have been synchronized" diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index f5a7fbce66..6dc3ffb294 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -217,44 +217,41 @@ func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID s func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, height uint64, treeClient TreeServiceClient, opsCh chan<- *pilorama.Move, -) (uint64, error) { +) error { rawCID := make([]byte, sha256.Size) cid.Encode(rawCID) - for { - newHeight := height - req := &GetOpLogRequest{ - Body: &GetOpLogRequest_Body{ - ContainerId: rawCID, - TreeId: treeID, - Height: newHeight, - }, - } - if err := SignMessage(req, s.key); err != nil { - return 0, err - } - - c, err := treeClient.GetOpLog(ctx, req) - if err != nil { - return 0, fmt.Errorf("can't initialize client: %w", err) - } - res, err := c.Recv() - for ; err == nil; res, err = c.Recv() { - lm := res.GetBody().GetOperation() - m := &pilorama.Move{ - Parent: lm.ParentId, - Child: lm.ChildId, - } - if err := m.Meta.FromBytes(lm.Meta); err != nil { - return 0, err - } - opsCh <- m - } - if height == newHeight || err != nil && !errors.Is(err, io.EOF) { - return newHeight, err - } - height = newHeight + req := &GetOpLogRequest{ + Body: &GetOpLogRequest_Body{ + ContainerId: rawCID, + TreeId: treeID, + Height: height, + }, } + if err := SignMessage(req, s.key); err != nil { + return err + } + + c, err := treeClient.GetOpLog(ctx, req) + if err != nil { + return fmt.Errorf("can't initialize client: %w", err) + } + res, err := c.Recv() + for ; err == nil; res, err = c.Recv() { + lm := res.GetBody().GetOperation() + m := &pilorama.Move{ + Parent: lm.ParentId, + Child: lm.ChildId, + } + if err := m.Meta.FromBytes(lm.Meta); err != nil { + return err + } + opsCh <- m + } + if err != nil && !errors.Is(err, io.EOF) { + return err + } + return nil } // synchronizeTree synchronizes operations getting them from different nodes. @@ -291,7 +288,6 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, i := i n := n errGroup.Go(func() error { - height := from n.IterateNetworkEndpoints(func(addr string) bool { var a network.Address if err := a.FromString(addr); err != nil { @@ -315,16 +311,12 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, defer cc.Close() treeClient := NewTreeServiceClient(cc) - for { - h, err := s.startStream(egCtx, cid, treeID, from, treeClient, nodeOperationStreams[i]) - if height < h { - height = h - } - if err != nil || h <= height { - // Error with the response, try the next node. - return true - } + err = s.startStream(egCtx, cid, treeID, from, treeClient, nodeOperationStreams[i]) + if err != nil { + // Error with the response, try the next node. + s.log.Warn(logs.TreeFailedToRunTreeSynchronizationForSpecificNode, zap.Error(err), zap.String("address", addr)) } + return true }) close(nodeOperationStreams[i]) return nil From b21be1abdd3125e715c222ce4ffc1f26a6d6bba9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 28 Nov 2023 10:51:15 +0300 Subject: [PATCH 0166/1413] [#741] treesvc: Do not update sync height if some node is unavailable Signed-off-by: Dmitrii Stepanov --- pkg/services/tree/sync.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 6dc3ffb294..65920fdc0a 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -9,6 +9,7 @@ import ( "math" "math/rand" "sync" + "sync/atomic" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -284,10 +285,14 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return nil }) + var allNodesSynced atomic.Bool + allNodesSynced.Store(true) + for i, n := range nodes { i := i n := n errGroup.Go(func() error { + var nodeSynced bool n.IterateNetworkEndpoints(func(addr string) bool { var a network.Address if err := a.FromString(addr); err != nil { @@ -316,13 +321,18 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, // Error with the response, try the next node. s.log.Warn(logs.TreeFailedToRunTreeSynchronizationForSpecificNode, zap.Error(err), zap.String("address", addr)) } + nodeSynced = err == nil return true }) close(nodeOperationStreams[i]) + if !nodeSynced { + allNodesSynced.Store(false) + } return nil }) } if err := errGroup.Wait(); err != nil { + allNodesSynced.Store(false) s.log.Warn(logs.TreeFailedToRunTreeSynchronizationOverAllNodes, zap.Error(err)) } @@ -332,7 +342,10 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, } else { newHeight++ } - return newHeight + if allNodesSynced.Load() { + return newHeight + } + return from } // ErrAlreadySyncing is returned when a service synchronization has already From 26e4f7005c35f5b89642483bd94f8fe45277b377 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 28 Nov 2023 17:04:02 +0300 Subject: [PATCH 0167/1413] [#741] treesvc: Refactor tree sync Fix linter issues. Add error logging. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 2 ++ pkg/services/tree/sync.go | 35 ++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index fad5f464d5..a72609b410 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -65,6 +65,8 @@ const ( TreeSynchronizeTree = "synchronize tree" TreeFailedToRunTreeSynchronizationOverAllNodes = "failed to run tree synchronization over all nodes" TreeFailedToRunTreeSynchronizationForSpecificNode = "failed to run tree synchronization for specific node" + TreeFailedToParseAddressForTreeSynchronization = "failed to parse address for tree synchronization" + TreeFailedToConnectForTreeSynchronization = "failed to connect for tree synchronization" TreeSyncingTrees = "syncing trees..." TreeCouldNotFetchContainers = "could not fetch containers" TreeTreesHaveBeenSynchronized = "trees have been synchronized" diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 65920fdc0a..485278adf4 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -217,8 +217,10 @@ func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID s } func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, - height uint64, treeClient TreeServiceClient, opsCh chan<- *pilorama.Move, + height uint64, cc *grpc.ClientConn, opsCh chan<- *pilorama.Move, ) error { + treeClient := NewTreeServiceClient(cc) + rawCID := make([]byte, sha256.Size) cid.Encode(rawCID) @@ -296,29 +298,19 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, n.IterateNetworkEndpoints(func(addr string) bool { var a network.Address if err := a.FromString(addr); err != nil { + s.log.Warn(logs.TreeFailedToParseAddressForTreeSynchronization, zap.Error(err), zap.String("address", addr)) return false } - cc, err := grpc.DialContext(egCtx, a.URIAddr(), - grpc.WithChainUnaryInterceptor( - metrics.NewUnaryClientInterceptor(), - tracing_grpc.NewUnaryClientInteceptor(), - ), - grpc.WithChainStreamInterceptor( - metrics.NewStreamClientInterceptor(), - tracing_grpc.NewStreamClientInterceptor(), - ), - grpc.WithTransportCredentials(insecure.NewCredentials())) + cc, err := s.dialCtx(egCtx, a) if err != nil { - // Failed to connect, try the next address. + s.log.Warn(logs.TreeFailedToConnectForTreeSynchronization, zap.Error(err), zap.String("address", addr)) return false } defer cc.Close() - treeClient := NewTreeServiceClient(cc) - err = s.startStream(egCtx, cid, treeID, from, treeClient, nodeOperationStreams[i]) + err = s.startStream(egCtx, cid, treeID, from, cc, nodeOperationStreams[i]) if err != nil { - // Error with the response, try the next node. s.log.Warn(logs.TreeFailedToRunTreeSynchronizationForSpecificNode, zap.Error(err), zap.String("address", addr)) } nodeSynced = err == nil @@ -348,6 +340,19 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return from } +func (*Service) dialCtx(egCtx context.Context, a network.Address) (*grpc.ClientConn, error) { + return grpc.DialContext(egCtx, a.URIAddr(), + grpc.WithChainUnaryInterceptor( + metrics.NewUnaryClientInterceptor(), + tracing_grpc.NewUnaryClientInteceptor(), + ), + grpc.WithChainStreamInterceptor( + metrics.NewStreamClientInterceptor(), + tracing_grpc.NewStreamClientInterceptor(), + ), + grpc.WithTransportCredentials(insecure.NewCredentials())) +} + // ErrAlreadySyncing is returned when a service synchronization has already // been started. var ErrAlreadySyncing = errors.New("service is being synchronized") From 7f6852bbd2f440b5c49b616966e96bfd5ff30c65 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 30 Nov 2023 11:45:31 +0300 Subject: [PATCH 0168/1413] [#639] node: Refactor TTL cache Migrate from internal to external TTL implementation Signed-off-by: Alexander Chuprov --- cmd/frostfs-node/cache.go | 29 ++++++------------ cmd/frostfs-node/cache_test.go | 56 ++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 20 deletions(-) create mode 100644 cmd/frostfs-node/cache_test.go diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index cd383a5c2f..bf68d245f1 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -12,38 +12,29 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" lru "github.com/hashicorp/golang-lru/v2" + "github.com/hashicorp/golang-lru/v2/expirable" ) type netValueReader[K any, V any] func(K) (V, error) -type valueWithTime[V any] struct { +type valueWithError[V any] struct { v V - t time.Time // cached error in order to not repeat failed request for some time e error } // entity that provides TTL cache interface. type ttlNetCache[K comparable, V any] struct { - ttl time.Duration - - sz int - - cache *lru.Cache[K, *valueWithTime[V]] - - netRdr netValueReader[K, V] - + cache *expirable.LRU[K, *valueWithError[V]] + netRdr netValueReader[K, V] keyLocker *utilSync.KeyLocker[K] } // complicates netValueReader with TTL caching mechanism. func newNetworkTTLCache[K comparable, V any](sz int, ttl time.Duration, netRdr netValueReader[K, V]) *ttlNetCache[K, V] { - cache, err := lru.New[K, *valueWithTime[V]](sz) - fatalOnErr(err) + cache := expirable.NewLRU[K, *valueWithError[V]](sz, nil, ttl) return &ttlNetCache[K, V]{ - ttl: ttl, - sz: sz, cache: cache, netRdr: netRdr, keyLocker: utilSync.NewKeyLocker[K](), @@ -57,7 +48,7 @@ func newNetworkTTLCache[K comparable, V any](sz int, ttl time.Duration, netRdr n // returned value should not be modified. func (c *ttlNetCache[K, V]) get(key K) (V, error) { val, ok := c.cache.Peek(key) - if ok && time.Since(val.t) < c.ttl { + if ok { return val.v, val.e } @@ -65,15 +56,14 @@ func (c *ttlNetCache[K, V]) get(key K) (V, error) { defer c.keyLocker.Unlock(key) val, ok = c.cache.Peek(key) - if ok && time.Since(val.t) < c.ttl { + if ok { return val.v, val.e } v, err := c.netRdr(key) - c.cache.Add(key, &valueWithTime[V]{ + c.cache.Add(key, &valueWithError[V]{ v: v, - t: time.Now(), e: err, }) @@ -84,9 +74,8 @@ func (c *ttlNetCache[K, V]) set(k K, v V, e error) { c.keyLocker.Lock(k) defer c.keyLocker.Unlock(k) - c.cache.Add(k, &valueWithTime[V]{ + c.cache.Add(k, &valueWithError[V]{ v: v, - t: time.Now(), e: e, }) } diff --git a/cmd/frostfs-node/cache_test.go b/cmd/frostfs-node/cache_test.go new file mode 100644 index 0000000000..6e076abfc8 --- /dev/null +++ b/cmd/frostfs-node/cache_test.go @@ -0,0 +1,56 @@ +package main + +import ( + "errors" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestTTLNetCache(t *testing.T) { + ttlDuration := time.Millisecond * 50 + cache := newNetworkTTLCache[string, time.Time](10, ttlDuration, testNetValueReader) + + key := "key" + + t.Run("Test Add and Get", func(t *testing.T) { + ti := time.Now() + cache.set(key, ti, nil) + val, err := cache.get(key) + require.NoError(t, err) + require.Equal(t, ti, val) + }) + + t.Run("Test TTL", func(t *testing.T) { + ti := time.Now() + cache.set(key, ti, nil) + time.Sleep(2 * ttlDuration) + val, err := cache.get(key) + require.NoError(t, err) + require.NotEqual(t, val, ti) + }) + + t.Run("Test Remove", func(t *testing.T) { + ti := time.Now() + cache.set(key, ti, nil) + cache.remove(key) + val, err := cache.get(key) + require.NoError(t, err) + require.NotEqual(t, val, ti) + }) + + t.Run("Test Cache Error", func(t *testing.T) { + cache.set("error", time.Now(), errors.New("mock error")) + _, err := cache.get("error") + require.Error(t, err) + require.Equal(t, "mock error", err.Error()) + }) +} + +func testNetValueReader(key string) (time.Time, error) { + if key == "error" { + return time.Now(), errors.New("mock error") + } + return time.Now(), nil +} From a982c3df18194f6cad2d5289194afaf364ece262 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 21 Nov 2023 17:01:14 +0300 Subject: [PATCH 0169/1413] [#824] cli: Support passing chain ID in add-rule command Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index d7177dd962..f57823ed32 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -41,6 +41,8 @@ func prettyJSONFormat(cmd *cobra.Command, serializedChain []byte) string { func addRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) + chainID, _ := cmd.Flags().GetString(chainIDFlag) + var cnr cid.ID cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) @@ -52,6 +54,7 @@ func addRule(cmd *cobra.Command, _ []string) { chain := new(apechain.Chain) commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, []string{rule})) + chain.ID = apechain.ID(chainID) serializedChain := chain.Bytes() cmd.Println("Container ID: " + cidStr) @@ -87,4 +90,5 @@ func initControlAddRuleCmd() { ff := addRuleCmd.Flags() ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) ff.String(ruleFlag, "", "Rule statement") + ff.String(chainIDFlag, "", "Assign ID to the parsed chain") } From 2302e5d34222ee0900909dc6616db32b22a132aa Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 29 Nov 2023 10:46:46 +0300 Subject: [PATCH 0170/1413] [#651] shard/test: Refactor Shard_Delete Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/shard/delete_test.go | 98 +++++++------------ 1 file changed, 37 insertions(+), 61 deletions(-) diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index 910528f847..846cb0e3ba 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -12,88 +12,64 @@ import ( "github.com/stretchr/testify/require" ) -func TestShard_Delete(t *testing.T) { - t.Parallel() - - t.Run("without write cache", func(t *testing.T) { +func TestShard_Delete_SmallObject(t *testing.T) { + t.Run("small object without write cache", func(t *testing.T) { t.Parallel() - testShardDelete(t, false) + testShard(t, false, 1<<5) }) - t.Run("with write cache", func(t *testing.T) { + t.Run("small object with write cache", func(t *testing.T) { t.Parallel() - testShardDelete(t, true) + testShard(t, true, 1<<5) }) } -func testShardDelete(t *testing.T, hasWriteCache bool) { +func TestShard_Delete_BigObject(t *testing.T) { + t.Run("big object without write cache", func(t *testing.T) { + t.Parallel() + testShard(t, false, 1<<20) + }) + + t.Run("big object with write cache", func(t *testing.T) { + t.Parallel() + testShard(t, true, 1<<20) + }) +} + +func testShard(t *testing.T, hasWriteCache bool, payloadSize int) { sh := newShard(t, hasWriteCache) cnr := cidtest.ID() obj := testutil.GenerateObjectWithCID(cnr) testutil.AddAttribute(obj, "foo", "bar") + testutil.AddPayload(obj, payloadSize) var putPrm PutPrm + putPrm.SetObject(obj) + var getPrm GetPrm + getPrm.SetAddress(object.AddressOf(obj)) - t.Run("big object", func(t *testing.T) { - testutil.AddPayload(obj, 1<<20) + var delPrm DeletePrm + delPrm.SetAddresses(object.AddressOf(obj)) - putPrm.SetObject(obj) - getPrm.SetAddress(object.AddressOf(obj)) + _, err := sh.Put(context.Background(), putPrm) + require.NoError(t, err) - var delPrm DeletePrm - delPrm.SetAddresses(object.AddressOf(obj)) + _, err = testGet(t, sh, getPrm, hasWriteCache) + require.NoError(t, err) - _, err := sh.Put(context.Background(), putPrm) - require.NoError(t, err) - - _, err = testGet(t, sh, getPrm, hasWriteCache) - require.NoError(t, err) - - if hasWriteCache { - require.Eventually(t, func() bool { - _, err = sh.Delete(context.Background(), delPrm) - return err == nil - }, 30*time.Second, 100*time.Millisecond) - } else { + if hasWriteCache { + require.Eventually(t, func() bool { _, err = sh.Delete(context.Background(), delPrm) - require.NoError(t, err) - } - - _, err = sh.Get(context.Background(), getPrm) - require.True(t, client.IsErrObjectNotFound(err)) - }) - - t.Run("small object", func(t *testing.T) { - obj := testutil.GenerateObjectWithCID(cnr) - testutil.AddAttribute(obj, "foo", "bar") - testutil.AddPayload(obj, 1<<5) - - putPrm.SetObject(obj) - getPrm.SetAddress(object.AddressOf(obj)) - - var delPrm DeletePrm - delPrm.SetAddresses(object.AddressOf(obj)) - - _, err := sh.Put(context.Background(), putPrm) + return err == nil + }, 30*time.Second, 10*time.Millisecond) + } else { + _, err = sh.Delete(context.Background(), delPrm) require.NoError(t, err) + } - _, err = sh.Get(context.Background(), getPrm) - require.NoError(t, err) - - if hasWriteCache { - require.Eventually(t, func() bool { - _, err = sh.Delete(context.Background(), delPrm) - return err == nil - }, 10*time.Second, 100*time.Millisecond) - } else { - _, err = sh.Delete(context.Background(), delPrm) - require.NoError(t, err) - } - - _, err = sh.Get(context.Background(), getPrm) - require.True(t, client.IsErrObjectNotFound(err)) - }) + _, err = sh.Get(context.Background(), getPrm) + require.True(t, client.IsErrObjectNotFound(err)) } From 445ebcc0e7170c9c9c78b3b9ccc1da1eaced6a91 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 29 Nov 2023 10:49:47 +0300 Subject: [PATCH 0171/1413] [#651] shard/test: Speedup Shard_Delete Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/shard/delete_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index 846cb0e3ba..f7687e9610 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -61,6 +61,7 @@ func testShard(t *testing.T, hasWriteCache bool, payloadSize int) { require.NoError(t, err) if hasWriteCache { + sh.FlushWriteCache(context.Background(), FlushWriteCachePrm{ignoreErrors: false}) require.Eventually(t, func() bool { _, err = sh.Delete(context.Background(), delPrm) return err == nil From b2c63e57ba101b97c8484d5d7406667b2a545d73 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 29 Nov 2023 10:51:56 +0300 Subject: [PATCH 0172/1413] [#651] engine/test: Speedup StorageEngine_Inhume Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/engine/inhume_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 8fff6280ce..4bb128bd7e 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -36,6 +36,7 @@ func TestStorageEngine_Inhume(t *testing.T) { link.SetSplitID(splitID) t.Run("delete small object", func(t *testing.T) { + t.Parallel() e := testNewEngine(t).setShardsNum(t, 1).engine defer e.Close(context.Background()) @@ -54,6 +55,7 @@ func TestStorageEngine_Inhume(t *testing.T) { }) t.Run("delete big object", func(t *testing.T) { + t.Parallel() s1 := testNewShard(t, 1) s2 := testNewShard(t, 2) From f1db468d4844a084be154c1fbeb81c74ac0a410e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 4 Dec 2023 16:12:59 +0300 Subject: [PATCH 0173/1413] [#840] adm: Update FrostFS ID deploy arguments Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/frostfsid_util.go | 49 ++++++++----------- .../modules/morph/frostfsid_util_test.go | 36 ++++++++------ .../modules/morph/initialize_deploy.go | 10 ++-- 3 files changed, 47 insertions(+), 48 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go index 248ad76b02..cfe3c1ee91 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go @@ -5,38 +5,29 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/viper" ) -// neo-go doesn't support []util.Uint160 type: -// https://github.com/nspcc-dev/neo-go/blob/v0.103.0/pkg/smartcontract/parameter.go#L262 -// Thus, return []smartcontract.Parameter. -func getFrostfsIDAuthorizedKeys(v *viper.Viper, defaultOwner util.Uint160) ([]smartcontract.Parameter, error) { - var res []smartcontract.Parameter - res = append(res, smartcontract.Parameter{Type: smartcontract.Hash160Type, Value: defaultOwner}) - - ks := v.GetStringSlice(frostfsIDAuthorizedKeysConfigKey) - for i := range ks { - h, err := address.StringToUint160(ks[i]) - if err == nil { - res = append(res, smartcontract.Parameter{Type: smartcontract.Hash160Type, Value: h}) - continue - } - - h, err = util.Uint160DecodeStringLE(ks[i]) - if err == nil { - res = append(res, smartcontract.Parameter{Type: smartcontract.Hash160Type, Value: h}) - continue - } - - pk, err := keys.NewPublicKeyFromString(ks[i]) - if err == nil { - res = append(res, smartcontract.Parameter{Type: smartcontract.Hash160Type, Value: pk.GetScriptHash()}) - continue - } - return nil, fmt.Errorf("frostfsid: #%d item in authorized_keys is invalid: '%s'", i, ks[i]) +func getFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { + admin := v.GetString(frostfsIDAdminConfigKey) + if admin == "" { + return util.Uint160{}, false, nil } - return res, nil + + h, err := address.StringToUint160(admin) + if err == nil { + return h, true, nil + } + + h, err = util.Uint160DecodeStringLE(admin) + if err == nil { + return h, true, nil + } + + pk, err := keys.NewPublicKeyFromString(admin) + if err == nil { + return pk.GetScriptHash(), true, nil + } + return util.Uint160{}, true, fmt.Errorf("frostfsid: admin is invalid: '%s'", admin) } diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go index f4b6a66f66..192dc9f126 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go @@ -6,8 +6,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/viper" "github.com/stretchr/testify/require" ) @@ -20,30 +18,36 @@ func TestFrostfsIDConfig(t *testing.T) { pks[i] = pk } - v := viper.New() - v.Set("frostfsid.authorized_keys", []string{ + fmts := []string{ pks[0].GetScriptHash().StringLE(), address.Uint160ToString(pks[1].GetScriptHash()), hex.EncodeToString(pks[2].PublicKey().UncompressedBytes()), hex.EncodeToString(pks[3].PublicKey().Bytes()), - }) + } - comm := util.Uint160{1, 2, 3} - actual, err := getFrostfsIDAuthorizedKeys(v, comm) - require.NoError(t, err) - require.Equal(t, len(pks)+1, len(actual)) - require.Equal(t, smartcontract.Hash160Type, actual[0].Type) - require.Equal(t, comm, actual[0].Value) - for i := range pks { - require.Equal(t, smartcontract.Hash160Type, actual[i+1].Type) - require.Equal(t, pks[i].GetScriptHash(), actual[i+1].Value) + for i := range fmts { + v := viper.New() + v.Set("frostfsid.admin", fmts[i]) + + actual, found, err := getFrostfsIDAdmin(v) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, pks[i].GetScriptHash(), actual) } t.Run("bad key", func(t *testing.T) { v := viper.New() - v.Set("frostfsid.authorized_keys", []string{"abc"}) + v.Set("frostfsid.admin", "abc") - _, err := getFrostfsIDAuthorizedKeys(v, comm) + _, found, err := getFrostfsIDAdmin(v) require.Error(t, err) + require.True(t, found) + }) + t.Run("missing key", func(t *testing.T) { + v := viper.New() + + _, found, err := getFrostfsIDAdmin(v) + require.NoError(t, err) + require.False(t, found) }) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 4ba72ef414..533fcad4dc 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -47,7 +47,7 @@ const ( proxyContract = "proxy" ) -const frostfsIDAuthorizedKeysConfigKey = "frostfsid.authorized_keys" +const frostfsIDAdminConfigKey = "frostfsid.admin" var ( contractList = []string{ @@ -538,12 +538,16 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an nnsCs.Hash, "container") case frostfsIDContract: - hs, err := getFrostfsIDAuthorizedKeys(viper.GetViper(), c.CommitteeAcc.PublicKey().GetScriptHash()) + h, found, err := getFrostfsIDAdmin(viper.GetViper()) if err != nil { panic(err) } - items = append(items, hs) + if found { + items = append(items, h) + } else { + items = append(items, nil) + } case netmapContract: md := getDefaultNetmapContractConfigMap() if method == updateMethodName { From 44806aa9f1968f71dd6210201857d0c39f486a3c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 1 Dec 2023 12:53:09 +0300 Subject: [PATCH 0174/1413] [#837] go.mod: Update dependencies Signed-off-by: Evgenii Stratonikov --- go.mod | 118 +-- go.sum | 3119 +++----------------------------------------------------- 2 files changed, 186 insertions(+), 3051 deletions(-) diff --git a/go.mod b/go.mod index cfa6dd7a6e..aa0f689c13 100644 --- a/go.mod +++ b/go.mod @@ -4,40 +4,40 @@ go 1.20 require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd - git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231129062201-a1b61d394958 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231128145636-a0a35bf4bf31 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 github.com/dgraph-io/ristretto v0.1.1 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 - github.com/google/uuid v1.3.1 + github.com/google/uuid v1.4.0 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/klauspost/compress v1.17.2 + github.com/klauspost/compress v1.17.4 github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 - github.com/multiformats/go-multiaddr v0.9.0 - github.com/nats-io/nats.go v1.27.1 - github.com/nspcc-dev/neo-go v0.103.0 + github.com/multiformats/go-multiaddr v0.12.0 + github.com/nats-io/nats.go v1.31.0 + github.com/nspcc-dev/neo-go v0.104.0 github.com/olekukonko/tablewriter v0.0.5 - github.com/panjf2000/ants/v2 v2.7.5 + github.com/panjf2000/ants/v2 v2.9.0 github.com/paulmach/orb v0.9.2 - github.com/prometheus/client_golang v1.16.0 - github.com/spf13/cast v1.5.1 + github.com/prometheus/client_golang v1.17.0 + github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.16.0 + github.com/spf13/viper v1.17.0 github.com/stretchr/testify v1.8.4 go.etcd.io/bbolt v1.3.8 - go.opentelemetry.io/otel v1.16.0 - go.opentelemetry.io/otel/trace v1.16.0 + go.opentelemetry.io/otel v1.21.0 + go.opentelemetry.io/otel/trace v1.21.0 go.uber.org/zap v1.26.0 - golang.org/x/exp v0.0.0-20231006140011-7918f672742d - golang.org/x/sync v0.4.0 - golang.org/x/term v0.13.0 + golang.org/x/exp v0.0.0-20231127185646-65229373498e + golang.org/x/sync v0.5.0 + golang.org/x/term v0.15.0 google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v3 v3.0.1 @@ -46,10 +46,15 @@ require ( require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.1.2 // indirect + github.com/golang/glog v1.2.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/flatbuffers v2.0.8+incompatible // indirect + github.com/google/flatbuffers v23.5.26+incompatible // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + go.mongodb.org/mongo-driver v1.11.4 // indirect go.opencensus.io v0.24.0 // indirect ) @@ -58,33 +63,32 @@ require ( git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.8.0 // indirect + github.com/bits-and-blooms/bitset v1.11.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb // indirect + github.com/consensys/gnark-crypto v0.12.2-0.20231117165148-e77308824822 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/dgraph-io/badger/v4 v4.1.0 - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/dgraph-io/badger/v4 v4.2.0 + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.5 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - github.com/hashicorp/golang-lru v0.6.0 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 // indirect + github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/holiman/uint256 v1.2.2 // indirect + github.com/holiman/uint256 v1.2.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect @@ -93,41 +97,37 @@ require ( github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-varint v0.0.7 // indirect - github.com/nats-io/nats-server/v2 v2.7.4 // indirect - github.com/nats-io/nkeys v0.4.4 // indirect + github.com/nats-io/nkeys v0.4.6 // indirect github.com/nats-io/nuid v1.0.1 // indirect - github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 // indirect - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5 // indirect + github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c // indirect + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231201072346-6c0c2a6a98b0 // indirect github.com/nspcc-dev/rfc6979 v0.2.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.8 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/spf13/afero v1.9.5 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect - github.com/subosito/gotenv v1.4.2 // indirect - github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/twmb/murmur3 v1.1.8 // indirect github.com/urfave/cli v1.22.14 // indirect - go.mongodb.org/mongo-driver v1.12.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 // indirect - go.opentelemetry.io/otel/metric v1.16.0 // indirect - go.opentelemetry.io/otel/sdk v1.16.0 // indirect - go.opentelemetry.io/proto/otlp v0.20.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/sdk v1.21.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.14.0 // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 8c36890230..0167d4a51f 100644 --- a/go.sum +++ b/go.sum @@ -1,733 +1,8 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.1/go.mod h1:fs4QogzfH5n2pBXBP9vRiU+eCny7lD2vmFZy79Iuw1U= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= -cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= -cloud.google.com/go/accessapproval v1.7.1/go.mod h1:JYczztsHRMK7NTXb6Xw+dwbs/WnOJxbo/2mTI+Kgg68= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/accesscontextmanager v1.6.0/go.mod h1:8XCvZWfYw3K/ji0iVnp+6pu7huxoQTLmxAbVjbloTtM= -cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= -cloud.google.com/go/accesscontextmanager v1.8.0/go.mod h1:uI+AI/r1oyWK99NN8cQ3UK76AMelMzgZCvJfsi2c+ps= -cloud.google.com/go/accesscontextmanager v1.8.1/go.mod h1:JFJHfvuaTC+++1iL1coPiG1eu5D24db2wXCDWDjIrxo= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/aiplatform v1.27.0/go.mod h1:Bvxqtl40l0WImSb04d0hXFU7gDOiq9jQmorivIiWcKg= -cloud.google.com/go/aiplatform v1.35.0/go.mod h1:7MFT/vCaOyZT/4IIFfxH4ErVg/4ku6lKv3w0+tFTgXQ= -cloud.google.com/go/aiplatform v1.36.1/go.mod h1:WTm12vJRPARNvJ+v6P52RDHCNe4AhvjcIZ/9/RRHy/k= -cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= -cloud.google.com/go/aiplatform v1.45.0/go.mod h1:Iu2Q7sC7QGhXUeOhAj/oCK9a+ULz1O4AotZiqjQ8MYA= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/analytics v0.17.0/go.mod h1:WXFa3WSym4IZ+JiKmavYdJwGG/CvpqiqczmL59bTD9M= -cloud.google.com/go/analytics v0.18.0/go.mod h1:ZkeHGQlcIPkw0R/GW+boWHhCOR43xz9RN/jn7WcqfIE= -cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= -cloud.google.com/go/analytics v0.21.2/go.mod h1:U8dcUtmDmjrmUTnnnRnI4m6zKn/yaA5N9RlEkYFHpQo= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= -cloud.google.com/go/apigateway v1.6.1/go.mod h1:ufAS3wpbRjqfZrzpvLC2oh0MFlpRJm2E/ts25yyqmXA= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= -cloud.google.com/go/apigeeconnect v1.6.1/go.mod h1:C4awq7x0JpLtrlQCr8AzVIzAaYgngRqWf9S5Uhg+wWs= -cloud.google.com/go/apigeeregistry v0.4.0/go.mod h1:EUG4PGcsZvxOXAdyEghIdXwAEi/4MEaoqLMLDMIwKXY= -cloud.google.com/go/apigeeregistry v0.5.0/go.mod h1:YR5+s0BVNZfVOUkMa5pAR2xGd0A473vA5M7j247o1wM= -cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= -cloud.google.com/go/apigeeregistry v0.7.1/go.mod h1:1XgyjZye4Mqtw7T9TsY4NW10U7BojBvG4RMD+vRDrIw= -cloud.google.com/go/apikeys v0.4.0/go.mod h1:XATS/yqZbaBK0HOssf+ALHp8jAlNHUgyfprvNcBIszU= -cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= -cloud.google.com/go/apikeys v0.6.0/go.mod h1:kbpXu5upyiAlGkKrJgQl8A0rKNNJ7dQ377pdroRSSi8= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/appengine v1.6.0/go.mod h1:hg6i0J/BD2cKmDJbaFSYHFyZkgBEfQrDg/X0V5fJn84= -cloud.google.com/go/appengine v1.7.0/go.mod h1:eZqpbHFCqRGa2aCdope7eC0SWLV1j0neb/QnMJVWx6A= -cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= -cloud.google.com/go/appengine v1.8.1/go.mod h1:6NJXGLVhZCN9aQ/AEDvmfzKEfoYBlfB80/BHiKVputY= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/area120 v0.7.0/go.mod h1:a3+8EUD1SX5RUcCs3MY5YasiO1z6yLiNLRiFrykbynY= -cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= -cloud.google.com/go/area120 v0.8.1/go.mod h1:BVfZpGpB7KFVNxPiQBuHkX6Ed0rS51xIgmGyjrAfzsg= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/artifactregistry v1.11.1/go.mod h1:lLYghw+Itq9SONbCa1YWBoWs1nOucMH0pwXN1rOBZFI= -cloud.google.com/go/artifactregistry v1.11.2/go.mod h1:nLZns771ZGAwVLzTX/7Al6R9ehma4WUEhZGWV6CeQNQ= -cloud.google.com/go/artifactregistry v1.12.0/go.mod h1:o6P3MIvtzTOnmvGagO9v/rOjjA0HmhJ+/6KAXrmYDCI= -cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= -cloud.google.com/go/artifactregistry v1.14.1/go.mod h1:nxVdG19jTaSTu7yA7+VbWL346r3rIdkZ142BSQqhn5E= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/asset v1.11.1/go.mod h1:fSwLhbRvC9p9CXQHJ3BgFeQNM4c9x10lqlrdEUYXlJo= -cloud.google.com/go/asset v1.12.0/go.mod h1:h9/sFOa4eDIyKmH6QMpm4eUK3pDojWnUhTgJlk762Hg= -cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= -cloud.google.com/go/asset v1.14.1/go.mod h1:4bEJ3dnHCqWCDbWJ/6Vn7GVI9LerSi7Rfdi03hd+WTQ= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= -cloud.google.com/go/assuredworkloads v1.11.1/go.mod h1:+F04I52Pgn5nmPG36CWFtxmav6+7Q+c5QyJoL18Lry0= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= -cloud.google.com/go/automl v1.13.1/go.mod h1:1aowgAHWYZU27MybSCFiukPO7xnyawv7pt3zK4bheQE= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= -cloud.google.com/go/baremetalsolution v1.1.1/go.mod h1:D1AV6xwOksJMV4OSlWHtWuFNZZYujJknMAP4Qa27QIA= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= -cloud.google.com/go/batch v1.3.1/go.mod h1:VguXeQKXIYaeeIYbuozUmBR13AfL4SJP7IltNPS+A4A= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/beyondcorp v0.4.0/go.mod h1:3ApA0mbhHx6YImmuubf5pyW8srKnCEPON32/5hj+RmM= -cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= -cloud.google.com/go/beyondcorp v1.0.0/go.mod h1:YhxDWw946SCbmcWo3fAhw3V4XZMSpQ/VYfcKGAEU8/4= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/bigquery v1.47.0/go.mod h1:sA9XOgy0A8vQK9+MWhEQTY6Tix87M/ZurWFIxmF9I/E= -cloud.google.com/go/bigquery v1.48.0/go.mod h1:QAwSz+ipNgfL5jxiaK7weyOhzdoAy1zFm0Nf1fysJac= -cloud.google.com/go/bigquery v1.49.0/go.mod h1:Sv8hMmTFFYBlt/ftw2uN6dFdQPzBlREY9yBh7Oy7/4Q= -cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= -cloud.google.com/go/bigquery v1.52.0/go.mod h1:3b/iXjRQGU4nKa87cXeg6/gogLjO8C6PmuM8i5Bi/u4= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/billing v1.12.0/go.mod h1:yKrZio/eu+okO/2McZEbch17O5CB5NpZhhXG6Z766ss= -cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= -cloud.google.com/go/billing v1.16.0/go.mod h1:y8vx09JSSJG02k5QxbycNRrN7FGZB6F3CAcgum7jvGA= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= -cloud.google.com/go/binaryauthorization v1.6.1/go.mod h1:TKt4pa8xhowwffiBmbrbcxijJRZED4zrqnwZ1lKH51U= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= -cloud.google.com/go/certificatemanager v1.7.1/go.mod h1:iW8J3nG6SaRYImIa+wXQ0g8IgoofDFRp5UMzaNk1UqI= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/channel v1.11.0/go.mod h1:IdtI0uWGqhEeatSB62VOoJ8FSUhJ9/+iGkJVqp74CGE= -cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= -cloud.google.com/go/channel v1.16.0/go.mod h1:eN/q1PFSl5gyu0dYdmxNXscY/4Fi7ABmeHCJNf/oHmc= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/cloudbuild v1.6.0/go.mod h1:UIbc/w9QCbH12xX+ezUsgblrWv+Cv4Tw83GiSMHOn9M= -cloud.google.com/go/cloudbuild v1.7.0/go.mod h1:zb5tWh2XI6lR9zQmsm1VRA+7OCuve5d8S+zJUul8KTg= -cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= -cloud.google.com/go/cloudbuild v1.10.1/go.mod h1:lyJg7v97SUIPq4RC2sGsz/9tNczhyv2AjML/ci4ulzU= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= -cloud.google.com/go/clouddms v1.6.1/go.mod h1:Ygo1vL52Ov4TBZQquhz5fiw2CQ58gvu+PlS6PVXCpZI= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/cloudtasks v1.9.0/go.mod h1:w+EyLsVkLWHcOaqNEyvcKAsWp9p29dL6uL9Nst1cI7Y= -cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= -cloud.google.com/go/cloudtasks v1.11.1/go.mod h1:a9udmnou9KO2iulGscKR0qBYjreuX8oHwpmFsKspEvM= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= -cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= -cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= -cloud.google.com/go/contactcenterinsights v1.9.1/go.mod h1:bsg/R7zGLYMVxFFzfh9ooLTruLRCG9fnzhH9KznHhbM= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/container v1.13.1/go.mod h1:6wgbMPeQRw9rSnKBCAJXnds3Pzj03C4JHamr8asWKy4= -cloud.google.com/go/container v1.14.0/go.mod h1:3AoJMPhHfLDxLvrlVWaK57IXzaPnLaZq63WX59aQBfM= -cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= -cloud.google.com/go/container v1.22.1/go.mod h1:lTNExE2R7f+DLbAN+rJiKTisauFCaoDq6NURZ83eVH4= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/containeranalysis v0.7.0/go.mod h1:9aUL+/vZ55P2CXfuZjS4UjQ9AgXoSw8Ts6lemfmxBxI= -cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= -cloud.google.com/go/containeranalysis v0.10.1/go.mod h1:Ya2jiILITMY68ZLPaogjmOMNkwsDrWBSTyBubGXO7j0= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/datacatalog v1.8.1/go.mod h1:RJ58z4rMp3gvETA465Vg+ag8BGgBdnRPEMMSTr5Uv+M= -cloud.google.com/go/datacatalog v1.12.0/go.mod h1:CWae8rFkfp6LzLumKOnmVh4+Zle4A3NXLzVJ1d1mRm0= -cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= -cloud.google.com/go/datacatalog v1.14.0/go.mod h1:h0PrGtlihoutNMp/uvwhawLQ9+c63Kz65UFqh49Yo+E= -cloud.google.com/go/datacatalog v1.14.1/go.mod h1:d2CevwTG4yedZilwe+v3E3ZBDRMobQfSG/a6cCCN5R4= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= -cloud.google.com/go/dataflow v0.9.1/go.mod h1:Wp7s32QjYuQDWqJPFFlnBKhkAtiFpMTdg00qGbnIHVw= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/dataform v0.6.0/go.mod h1:QPflImQy33e29VuapFdf19oPbE4aYTJxr31OAPV+ulA= -cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= -cloud.google.com/go/dataform v0.8.1/go.mod h1:3BhPSiw8xmppbgzeBbmDvmSWlwouuJkXsXsb8UBih9M= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= -cloud.google.com/go/datafusion v1.7.1/go.mod h1:KpoTBbFmoToDExJUso/fcCiguGDk7MEzOWXUsJo0wsI= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= -cloud.google.com/go/datalabeling v0.8.1/go.mod h1:XS62LBSVPbYR54GfYQsPXZjTW8UxCK2fkDciSrpRFdY= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataplex v1.5.2/go.mod h1:cVMgQHsmfRoI5KFYq4JtIBEUbYwc3c7tXmIDhRmNNVQ= -cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= -cloud.google.com/go/dataplex v1.8.1/go.mod h1:7TyrDT6BCdI8/38Uvp0/ZxBslOslP2X2MPDucliyvSE= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= -cloud.google.com/go/dataqna v0.8.1/go.mod h1:zxZM0Bl6liMePWsHA8RMGAfmTG34vJMapbHAxQ5+WA8= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastore v1.10.0/go.mod h1:PC5UzAmDEkAmkfaknstTYbNpgE49HAgW2J1gcgUfmdM= -cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= -cloud.google.com/go/datastore v1.12.1/go.mod h1:KjdB88W897MRITkvWWJrg2OUtrR5XVj1EoLgSp6/N70= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/datastream v1.6.0/go.mod h1:6LQSuswqLa7S4rPAOZFVjHIG3wJIjZcZrw8JDEDJuIs= -cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= -cloud.google.com/go/datastream v1.9.1/go.mod h1:hqnmr8kdUBmrnk65k5wNRoHSCYksvpdZIcZIEl8h43Q= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/deploy v1.6.0/go.mod h1:f9PTHehG/DjCom3QH0cntOVRm93uGBDt2vKzAPwpXQI= -cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= -cloud.google.com/go/deploy v1.11.0/go.mod h1:tKuSUV5pXbn67KiubiUNUejqLs4f5cxxiCNCeyl0F2g= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dialogflow v1.29.0/go.mod h1:b+2bzMe+k1s9V+F2jbJwpHPzrnIyHihAdRFMtn2WXuM= -cloud.google.com/go/dialogflow v1.31.0/go.mod h1:cuoUccuL1Z+HADhyIA7dci3N5zUssgpBJmCzI6fNRB4= -cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= -cloud.google.com/go/dialogflow v1.38.0/go.mod h1:L7jnH+JL2mtmdChzAIcXQHXMvQkE3U4hTaNltEuxXn4= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= -cloud.google.com/go/dlp v1.10.1/go.mod h1:IM8BWz1iJd8njcNcG0+Kyd9OPnqnRNkDV8j42VT5KOI= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/documentai v1.16.0/go.mod h1:o0o0DLTEZ+YnJZ+J4wNfTxmDVyrkzFvttBXXtYRMHkM= -cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= -cloud.google.com/go/documentai v1.20.0/go.mod h1:yJkInoMcK0qNAEdRnqY/D5asy73tnPe88I1YTZT+a8E= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= -cloud.google.com/go/domains v0.9.1/go.mod h1:aOp1c0MbejQQ2Pjf1iJvnVyT+z6R6s8pX66KaCSDYfE= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/edgecontainer v0.3.0/go.mod h1:FLDpP4nykgwwIfcLt6zInhprzw0lEi2P1fjO6Ie0qbc= -cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= -cloud.google.com/go/edgecontainer v1.1.1/go.mod h1:O5bYcS//7MELQZs3+7mabRqoWQhXCzenBu0R8bz2rwk= -cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= -cloud.google.com/go/essentialcontacts v1.6.2/go.mod h1:T2tB6tX+TRak7i88Fb2N9Ok3PvY3UNbUsMag9/BARh4= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/eventarc v1.10.0/go.mod h1:u3R35tmZ9HvswGRBnF48IlYgYeBcPUCjkr4BTdem2Kw= -cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= -cloud.google.com/go/eventarc v1.12.1/go.mod h1:mAFCW6lukH5+IZjkvrEss+jmt2kOdYlN8aMx3sRJiAI= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/filestore v1.5.0/go.mod h1:FqBXDWBp4YLHqRnVGveOkHDf8svj9r5+mUDLupOWEDs= -cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= -cloud.google.com/go/filestore v1.7.1/go.mod h1:y10jsorq40JJnjR/lQ8AfFbbcGlw3g+Dp8oN7i7FjV4= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= -cloud.google.com/go/firestore v1.11.0/go.mod h1:b38dKhgzlmNNGTNZZwe7ZRFEuRab1Hay3/DBsIGKKy4= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/functions v1.10.0/go.mod h1:0D3hEOe3DbEvCXtYOZHQZmD+SzYsi1YbI7dGvHfldXw= -cloud.google.com/go/functions v1.12.0/go.mod h1:AXWGrF3e2C/5ehvwYo/GH6O5s09tOPksiKhz+hH8WkA= -cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= -cloud.google.com/go/functions v1.15.1/go.mod h1:P5yNWUTkyU+LvW/S9O6V+V423VZooALQlqoXdoPz5AE= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= -cloud.google.com/go/gkebackup v1.3.0/go.mod h1:vUDOu++N0U5qs4IhG1pcOnD1Mac79xWy6GoBFlWCWBU= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= -cloud.google.com/go/gkeconnect v0.8.1/go.mod h1:KWiK1g9sDLZqhxB2xEuPV8V9NYzrqTUmQR9shJHpOZw= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkehub v0.11.0/go.mod h1:JOWHlmN+GHyIbuWQPl47/C2RFhnFKH38jH9Ascu3n0E= -cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= -cloud.google.com/go/gkehub v0.14.1/go.mod h1:VEXKIJZ2avzrbd7u+zeMtW00Y8ddk/4V9511C9CQGTY= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= -cloud.google.com/go/gkemulticloud v0.6.1/go.mod h1:kbZ3HKyTsiwqKX7Yw56+wUGwwNZViRnxWK2DVknXWfw= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/grafeas v0.3.0/go.mod h1:P7hgN24EyONOTMyeJH6DxG4zD7fwiYa5Q6GUgyFSOU8= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= -cloud.google.com/go/gsuiteaddons v1.6.1/go.mod h1:CodrdOqRZcLp5WOwejHWYBjZvfY0kOphkAKpF/3qdZY= -cloud.google.com/go/iam v0.1.0/go.mod h1:vcUNEa0pEm0qRVpmWepWaFMIAI8/hjB9mO8rNCJtF6c= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.11.0/go.mod h1:9PiLDanza5D+oWFZiH1uG+RnRCfEGKoyl6yo4cgWZGY= -cloud.google.com/go/iam v0.12.0/go.mod h1:knyHGviacl11zrtZUoDuYpDgLjvr28sLQaG0YB2GYAY= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= -cloud.google.com/go/iam v1.0.1/go.mod h1:yR3tmSL8BcZB4bxByRv2jkSIahVmCtfKZwLYGBalRE8= -cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= -cloud.google.com/go/iam v1.1.1/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/iap v1.6.0/go.mod h1:NSuvI9C/j7UdjGjIde7t7HBz+QTwBcapPE07+sSRcLk= -cloud.google.com/go/iap v1.7.0/go.mod h1:beqQx56T9O1G1yNPph+spKpNibDlYIiIixiqsQXxLIo= -cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= -cloud.google.com/go/iap v1.8.1/go.mod h1:sJCbeqg3mvWLqjZNsI6dfAtbbV1DL2Rl7e1mTyXYREQ= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= -cloud.google.com/go/ids v1.4.1/go.mod h1:np41ed8YMU8zOgv53MMMoCntLTn2lF+SUzlM+O3u/jw= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/iot v1.5.0/go.mod h1:mpz5259PDl3XJthEmh9+ap0affn/MqNSP4My77Qql9o= -cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= -cloud.google.com/go/iot v1.7.1/go.mod h1:46Mgw7ev1k9KqK1ao0ayW9h0lI+3hxeanz+L1zmbbbk= -cloud.google.com/go/kms v1.4.0/go.mod h1:fajBHndQ+6ubNw6Ss2sSd+SWvjL26RNo/dr7uxsnnOA= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/kms v1.8.0/go.mod h1:4xFEhYFqvW+4VMELtZyxomGSYtSQKzM178ylFW4jMAg= -cloud.google.com/go/kms v1.9.0/go.mod h1:qb1tPTgfF9RQP8e1wq4cLFErVuTJv7UsSC915J8dh3w= -cloud.google.com/go/kms v1.10.0/go.mod h1:ng3KTUtQQU9bPX3+QGLsflZIHlkbn8amFAMY63m8d24= -cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= -cloud.google.com/go/kms v1.11.0/go.mod h1:hwdiYC0xjnWsKQQCQQmIQnS9asjYVSK6jtXm+zFqXLM= -cloud.google.com/go/kms v1.12.1/go.mod h1:c9J991h5DTl+kg7gi3MYomh12YEENGrf48ee/N/2CDM= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= -cloud.google.com/go/language v1.10.1/go.mod h1:CPp94nsdVNiQEt1CNjF5WkTcisLiHPyIbMhvR8H2AW0= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= -cloud.google.com/go/lifesciences v0.9.1/go.mod h1:hACAOd1fFbCGLr/+weUKRAJas82Y4vrL3O5326N//Wc= -cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -cloud.google.com/go/longrunning v0.4.2/go.mod h1:OHrnaYyLUV6oqwh0xiS7e5sLQhP1m0QU9R+WhGDMgIQ= -cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= -cloud.google.com/go/managedidentities v1.6.1/go.mod h1:h/irGhTN2SkZ64F43tfGPMbHnypMbu4RB3yl8YcuEak= -cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= -cloud.google.com/go/maps v0.6.0/go.mod h1:o6DAMMfb+aINHz/p/jbcY+mYeXBoZoxTfdSQ8VAJaCw= -cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= -cloud.google.com/go/maps v1.3.0/go.mod h1:6mWTUv+WhnOwAgjVsSW2QPPECmW+s3PcRyOa9vgG/5s= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= -cloud.google.com/go/mediatranslation v0.8.1/go.mod h1:L/7hBdEYbYHQJhX2sldtTO5SZZ1C1vkapubj0T2aGig= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= -cloud.google.com/go/memcache v1.10.1/go.mod h1:47YRQIarv4I3QS5+hoETgKO40InqzLP6kpNLvyXuyaA= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= -cloud.google.com/go/metastore v1.11.1/go.mod h1:uZuSo80U3Wd4zi6C22ZZliOUJ3XeM/MlYi/z5OAOWRA= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/monitoring v1.12.0/go.mod h1:yx8Jj2fZNEkL/GYZyTLS4ZtZEZN8WtDEiEqG4kLK50w= -cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= -cloud.google.com/go/monitoring v1.15.1/go.mod h1:lADlSAlFdbqQuwwpaImhsJXu1QSdd3ojypXrFSMr2rM= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkconnectivity v1.10.0/go.mod h1:UP4O4sWXJG13AqrTdQCD9TnLGEbtNRqjuaaA7bNjF5E= -cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= -cloud.google.com/go/networkconnectivity v1.12.1/go.mod h1:PelxSWYM7Sh9/guf8CFhi6vIqf19Ir/sbfZRUwXh92E= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= -cloud.google.com/go/networkmanagement v1.8.0/go.mod h1:Ho/BUGmtyEqrttTgWEe7m+8vDdK74ibQc+Be0q7Fof0= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/networksecurity v0.7.0/go.mod h1:mAnzoxx/8TBSyXEeESMy9OOYwo1v+gZ5eMRnsT5bC8k= -cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= -cloud.google.com/go/networksecurity v0.9.1/go.mod h1:MCMdxOKQ30wsBI1eI659f9kEp4wuuAueoC9AJKSPWZQ= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/notebooks v1.7.0/go.mod h1:PVlaDGfJgj1fl1S3dUwhFMXFgfYGhYQt2164xOMONmE= -cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= -cloud.google.com/go/notebooks v1.9.1/go.mod h1:zqG9/gk05JrzgBt4ghLzEepPHNwE5jgPcHZRKhlC1A8= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= -cloud.google.com/go/optimization v1.4.1/go.mod h1:j64vZQP7h9bO49m2rVaTVoNM0vEBEN5eKPUPbZyXOrk= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= -cloud.google.com/go/orchestration v1.8.1/go.mod h1:4sluRF3wgbYVRqz7zJ1/EUNc90TTprliq9477fGobD8= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= -cloud.google.com/go/orgpolicy v1.11.0/go.mod h1:2RK748+FtVvnfuynxBzdnyu7sygtoZa1za/0ZfpOs1M= -cloud.google.com/go/orgpolicy v1.11.1/go.mod h1:8+E3jQcpZJQliP+zaFfayC2Pg5bmhuLK755wKhIIUCE= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= -cloud.google.com/go/osconfig v1.12.0/go.mod h1:8f/PaYzoS3JMVfdfTubkowZYGmAhUCjjwnjqWI7NVBc= -cloud.google.com/go/osconfig v1.12.1/go.mod h1:4CjBxND0gswz2gfYRCUoUzCm9zCABp91EeTtWXyz0tE= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= -cloud.google.com/go/oslogin v1.10.1/go.mod h1:x692z7yAue5nE7CsSnoG0aaMbNoRJRXO4sn73R+ZqAs= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= -cloud.google.com/go/phishingprotection v0.8.1/go.mod h1:AxonW7GovcA8qdEk13NfHq9hNx5KPtfxXNeUxTDxB6I= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/policytroubleshooter v1.5.0/go.mod h1:Rz1WfV+1oIpPdN2VvvuboLVRsB1Hclg3CKQ53j9l8vw= -cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= -cloud.google.com/go/policytroubleshooter v1.7.1/go.mod h1:0NaT5v3Ag1M7U5r0GfDCpUFkWd9YqpubBWsQlhanRv0= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/privatecatalog v0.7.0/go.mod h1:2s5ssIFO69F5csTXcwBP7NPFTZvps26xGzvQ2PQaBYg= -cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= -cloud.google.com/go/privatecatalog v0.9.1/go.mod h1:0XlDXW2unJXdf9zFz968Hp35gl/bhF4twwpXZAW50JA= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/pubsub v1.26.0/go.mod h1:QgBH3U/jdJy/ftjPhTkyXNj543Tin1pRYcdcPRnFIRI= -cloud.google.com/go/pubsub v1.27.1/go.mod h1:hQN39ymbV9geqBnfQq6Xf63yNhUAhv9CZhzp5O6qsW0= -cloud.google.com/go/pubsub v1.28.0/go.mod h1:vuXFpwaVoIPQMGXqRyUQigu/AX1S3IWugR9xznmcXX8= -cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= -cloud.google.com/go/pubsub v1.32.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= -cloud.google.com/go/pubsublite v1.5.0/go.mod h1:xapqNQ1CuLfGi23Yda/9l4bBCKz/wC3KIJ5gKcxveZg= -cloud.google.com/go/pubsublite v1.6.0/go.mod h1:1eFCS0U11xlOuMFV/0iBqw3zP12kddMeCbj/F3FSj9k= -cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= -cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recaptchaenterprise/v2 v2.6.0/go.mod h1:RPauz9jeLtB3JVzg6nCbe12qNoaa8pXc4d/YukAmcnA= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= -cloud.google.com/go/recaptchaenterprise/v2 v2.7.2/go.mod h1:kR0KjsJS7Jt1YSyWFkseQ756D45kaYNTlDPPaRAvDBU= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= -cloud.google.com/go/recommendationengine v0.8.1/go.mod h1:MrZihWwtFYWDzE6Hz5nKcNz3gLizXVIDI/o3G1DLcrE= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= -cloud.google.com/go/recommender v1.10.1/go.mod h1:XFvrE4Suqn5Cq0Lf+mCP6oBHD/yRMA8XxP5sb7Q7gpA= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= -cloud.google.com/go/redis v1.13.1/go.mod h1:VP7DGLpE91M6bcsDdMuyCm2hIpB6Vp2hI090Mfd1tcg= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcemanager v1.5.0/go.mod h1:eQoXNAiAvCf5PXxWxXjhKQoTMaUSNrEfg+6qdf/wots= -cloud.google.com/go/resourcemanager v1.6.0/go.mod h1:YcpXGRs8fDzcUl1Xw8uOVmI8JEadvhRIkoXXUNVYcVo= -cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= -cloud.google.com/go/resourcemanager v1.9.1/go.mod h1:dVCuosgrh1tINZ/RwBufr8lULmWGOkPS8gL5gqyjdT8= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= -cloud.google.com/go/resourcesettings v1.6.1/go.mod h1:M7mk9PIZrC5Fgsu1kZJci6mpgN8o0IUzVx3eJU3y4Jw= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= -cloud.google.com/go/retail v1.14.1/go.mod h1:y3Wv3Vr2k54dLNIrCzenyKG8g8dhvhncT2NcNjb/6gE= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/run v0.8.0/go.mod h1:VniEnuBwqjigv0A7ONfQUaEItaiCRVujlMqerPPiktM= -cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= -cloud.google.com/go/run v1.2.0/go.mod h1:36V1IlDzQ0XxbQjUx6IYbw8H3TJnWvhii963WW3B/bo= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/scheduler v1.8.0/go.mod h1:TCET+Y5Gp1YgHT8py4nlg2Sew8nUHMqcpousDgXJVQc= -cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= -cloud.google.com/go/scheduler v1.10.1/go.mod h1:R63Ldltd47Bs4gnhQkmNDse5w8gBRrhObZ54PxgR2Oo= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= -cloud.google.com/go/secretmanager v1.11.1/go.mod h1:znq9JlXgTNdBeQk9TBW/FnR/W4uChEKGeqQWAJ8SXFw= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/security v1.12.0/go.mod h1:rV6EhrpbNHrrxqlvW0BWAIawFWq3X90SduMJdFwtLB8= -cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= -cloud.google.com/go/security v1.15.1/go.mod h1:MvTnnbsWnehoizHi09zoiZob0iCHVcL4AUBj76h9fXA= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/securitycenter v1.18.1/go.mod h1:0/25gAzCM/9OL9vVx4ChPeM/+DlfGQJDwBy/UC8AKK0= -cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= -cloud.google.com/go/securitycenter v1.23.0/go.mod h1:8pwQ4n+Y9WCWM278R8W3nF65QtY172h4S8aXyI9/hsQ= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= -cloud.google.com/go/servicecontrol v1.11.0/go.mod h1:kFmTzYzTUIuZs0ycVqRHNaNhgR+UMUpw9n02l/pY+mc= -cloud.google.com/go/servicecontrol v1.11.1/go.mod h1:aSnNNlwEFBY+PWGQ2DoM0JJ/QUXqV5/ZD9DOLB7SnUk= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicedirectory v1.8.0/go.mod h1:srXodfhY1GFIPvltunswqXpVxFPpZjf8nkKQT7XcXaY= -cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= -cloud.google.com/go/servicedirectory v1.10.1/go.mod h1:Xv0YVH8s4pVOwfM/1eMTl0XJ6bzIOSLDt8f8eLaGOxQ= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= -cloud.google.com/go/servicemanagement v1.8.0/go.mod h1:MSS2TDlIEQD/fzsSGfCdJItQveu9NXnUniTrq/L8LK4= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= -cloud.google.com/go/serviceusage v1.6.0/go.mod h1:R5wwQcbOWsyuOfbP9tGdAnCAc6B9DRwPG1xtWMDeuPA= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= -cloud.google.com/go/shell v1.7.1/go.mod h1:u1RaM+huXFaTojTbW4g9P5emOrrmLE69KrxqQahKn4g= -cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= -cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= -cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.47.0/go.mod h1:IXsJwVW2j4UKs0eYDqodab6HgGuA1bViSqW4uH9lfUI= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/speech v1.14.1/go.mod h1:gEosVRPJ9waG7zqqnsHpYTOoAS4KouMRLDFMekpJ0J0= -cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= -cloud.google.com/go/speech v1.17.1/go.mod h1:8rVNzU43tQvxDaGvqOhpDqgkJTFowBpDvCJ14kGlJYo= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/storagetransfer v1.7.0/go.mod h1:8Giuj1QNb1kfLAiWM1bN6dHzfdlDAVC9rv9abHot2W4= -cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= -cloud.google.com/go/storagetransfer v1.10.0/go.mod h1:DM4sTlSmGiNczmV6iZyceIh2dbs+7z2Ayg6YAiQlYfA= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= -cloud.google.com/go/talent v1.6.2/go.mod h1:CbGvmKCG61mkdjcqTcLOkb2ZN1SrQI8MDyma2l7VD24= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= -cloud.google.com/go/texttospeech v1.7.1/go.mod h1:m7QfG5IXxeneGqTapXNxv2ItxP/FS0hCZBwXYqucgSk= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= -cloud.google.com/go/tpu v1.6.1/go.mod h1:sOdcHVIgDEEOKuqUoi6Fq53MKHJAtOwtz0GuKsWSH3E= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/trace v1.8.0/go.mod h1:zH7vcsbAhklH8hWFig58HvxcxyQbaIqMarMg9hn5ECA= -cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= -cloud.google.com/go/trace v1.10.1/go.mod h1:gbtL94KE5AJLH3y+WVpfWILmqgc6dXcqgNXdOPAQTYk= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/translate v1.5.0/go.mod h1:29YDSYveqqpA1CQFD7NQuP49xymq17RXNaUDdc0mNu0= -cloud.google.com/go/translate v1.6.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= -cloud.google.com/go/translate v1.8.1/go.mod h1:d1ZH5aaOA0CNhWeXeC8ujd4tdCFw8XoNWRljklu5RHs= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/video v1.12.0/go.mod h1:MLQew95eTuaNDEGriQdcYn0dTwf9oWiA4uYebxM5kdg= -cloud.google.com/go/video v1.13.0/go.mod h1:ulzkYlYgCp15N2AokzKjy7MQ9ejuynOJdf1tR5lGthk= -cloud.google.com/go/video v1.14.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= -cloud.google.com/go/video v1.17.1/go.mod h1:9qmqPqw/Ib2tLqaeHgtakU+l5TcJxCJbhFXM7UJjVzU= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= -cloud.google.com/go/videointelligence v1.11.1/go.mod h1:76xn/8InyQHarjTWsBR058SmlPCwQjgcvoW0aZykOvo= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vision/v2 v2.6.0/go.mod h1:158Hes0MvOS9Z/bDMSFpjwsUrZ5fPrdwuyyvKSGAGMY= -cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= -cloud.google.com/go/vision/v2 v2.7.2/go.mod h1:jKa8oSYBWhYiXarHPvP4USxYANYUEdEsQrloLjrSwJU= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vmmigration v1.5.0/go.mod h1:E4YQ8q7/4W9gobHjQg4JJSgXXSgY21nA5r8swQV+Xxc= -cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= -cloud.google.com/go/vmmigration v1.7.1/go.mod h1:WD+5z7a/IpZ5bKK//YmT9E047AD+rjycCAvyMxGJbro= -cloud.google.com/go/vmwareengine v0.1.0/go.mod h1:RsdNEf/8UDvKllXhMz5J40XxDrNJNN4sagiox+OI208= -cloud.google.com/go/vmwareengine v0.2.2/go.mod h1:sKdctNJxb3KLZkE/6Oui94iw/xs9PRNC2wnNLXsHvH8= -cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= -cloud.google.com/go/vmwareengine v0.4.1/go.mod h1:Px64x+BvjPZwWuc4HdmVhoygcXqEkGHXoa7uyfTgSI0= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= -cloud.google.com/go/vpcaccess v1.7.1/go.mod h1:FogoD46/ZU+JUBX9D606X21EnxiszYi2tArQwLY4SXs= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= -cloud.google.com/go/webrisk v1.9.1/go.mod h1:4GCmXKcOa2BZcZPn6DCEvE7HypmEJcJkr4mtM+sqYPc= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= -cloud.google.com/go/websecurityscanner v1.6.1/go.mod h1:Njgaw3rttgRHXzwCB8kgCYqv5/rGpFCsBOvPbYgszpg= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= -cloud.google.com/go/workflows v1.11.1/go.mod h1:Z+t10G1wF7h8LgdY/EmRcQY8ptBD/nvofaL6FqlET6g= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd h1:MxiIXu4vUATX9bNYFnM1dXAYkx5dnPOGCMzwNNXJEvM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989 h1:hcWlSHcgkg2wnqAInu0AGQcdEY/zr7+BDbGK0rDfXLQ= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231102065436-9ed3845aa989/go.mod h1:PxsAxe6J4hyYJoU6hyYxD9q5K/DFxdquKHL1BrRaGkg= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231129062201-a1b61d394958 h1:X9yPizADIhD3K/gdKVCthlAnf9aQ3UJJGnZgIwwixRQ= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231129062201-a1b61d394958/go.mod h1:rQWdsG18NaiFvkJpMguJev913KD/yleHaniRBkUyt0o= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= @@ -736,192 +11,28 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f h1:Rq95TuEkqc3T1EN5ZU1Vgf6H33TR95hz97ca8jrUciQ= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231115094736-5db67021e10f/go.mod h1:qf3B9hSz6gCMfcfvqkhTu5ak+Gx2R+wo4Hc87LnKxPg= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231128145636-a0a35bf4bf31 h1:31tE+hNkHar7IMduhzj8LFY8+LT2EswiVI873MEfZj0= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231128145636-a0a35bf4bf31/go.mod h1:ekrDiIySdYhji5rBNAkxYMztFWMXyC9Q8LVz6gGVDu0= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= git.frostfs.info/TrueCloudLab/tzhash v1.8.0/go.mod h1:dhY+oy274hV8wGvGL4MwwMpdL3GYvaX1a8GQZQHvlF8= -git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20221206110420-d395f97c4830/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= -github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20221215162035-5330a85ea652/go.mod h1:OahwfttHWG6eJ0clwcfBAHoDI6X/LV/15hx/wlMZSrU= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v56.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= -github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/CityOfZion/neo-go v0.62.1-pre.0.20191114145240-e740fbe708f8/go.mod h1:MJCkWUBhi9pn/CrYO1Q3P687y2KeahrOPS9BD9LDGb0= -github.com/CityOfZion/neo-go v0.70.1-pre.0.20191209120015-fccb0085941e/go.mod h1:0enZl0az8xA6PVkwzEOwPWVJGqlt/GO4hA4kmQ5Xzig= -github.com/CityOfZion/neo-go v0.70.1-pre.0.20191212173117-32ac01130d4c/go.mod h1:JtlHfeqLywZLswKIKFnAp+yzezY4Dji9qlfQKB2OD/I= -github.com/CityOfZion/neo-go v0.71.1-pre.0.20200129171427-f773ec69fb84/go.mod h1:FLI526IrRWHmcsO+mHsCbj64pJZhwQFTLJZu+A4PGOA= -github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= -github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= -github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= -github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= -github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= -github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= -github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim v0.9.3/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= -github.com/Microsoft/hcsshim v0.10.0-rc.8/go.mod h1:OEthFdQv/AD2RAdzR6Mm1N1KPCztGKDurW1Z8b8VGMM= -github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= -github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= -github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= -github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= -github.com/abiosoft/ishell/v2 v2.0.2/go.mod h1:E4oTCXfo6QjoCart0QYa5m9w4S+deXs/P/9jA77A9Bs= -github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530= -github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= -github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= -github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= -github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= -github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= -github.com/alexflint/go-filemutex v1.2.0/go.mod h1:mYyQSWvw9Tx2/H2n9qXPb52tTYfE0pZAWcBq5mK025c= -github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= -github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521073959-f0d4d129b7f1/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= -github.com/apache/arrow/go/v10 v10.0.1/go.mod h1:YvhnlEePVnBS4+0z3fhPfUy7W1Ikj0Ih0vcRo/gZ1M0= -github.com/apache/arrow/go/v11 v11.0.0/go.mod h1:Eg5OsL5H+e299f7u5ssuXsuHQVEGC4xei5aX110hRiI= -github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg= -github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.43.16/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bits-and-blooms/bitset v1.8.0 h1:FD+XqgOZDUxxZ8hzoBFuV9+cGWY9CslN6d5MS5JVb4c= -github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= -github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= -github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= -github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= -github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= -github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= -github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= -github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/bytecodealliance/wasmtime-go v0.36.0/go.mod h1:q320gUxqyI8yB+ZqRuaJOEnGkAnHh6WtJjMaT2CW4wI= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/bits-and-blooms/bitset v1.11.0 h1:RMyy2mBBShArUAhfVRZJ2xyBO58KCBCtZFShw3umo6k= +github.com/bits-and-blooms/bitset v1.11.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= -github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= -github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= -github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -931,424 +42,61 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark v0.9.1/go.mod h1:udWvWGXnfBE7mn7BsNoGAvZDnUhcONBEtNijvVjfY80= -github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc= -github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/container-orchestrated-devices/container-device-interface v0.5.4/go.mod h1:DjE95rfPiiSmG7uVXtg0z6MnPm/Lx4wxKCIts0ZE0vg= -github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= -github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= -github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= -github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= -github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= -github.com/containerd/btrfs/v2 v2.0.0/go.mod h1:swkD/7j9HApWpzl8OHfrHNxppPd9l44DFZdF94BUj9k= -github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= -github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= -github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= -github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= -github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= -github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= -github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= -github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= -github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s= -github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE= -github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= -github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0= -github.com/containerd/containerd v1.6.9/go.mod h1:XVicUvkxOrftE2Q1YWUXgZwkkAxwQYNOFzYWvfVfEfQ= -github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= -github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= -github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= -github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= -github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= -github.com/containerd/fifo v1.1.0/go.mod h1:bmC4NWMbXlt2EZ0Hc7Fx7QzTFxgPID13eH0Qu+MAb2o= -github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= -github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= -github.com/containerd/go-cni v1.1.0/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= -github.com/containerd/go-cni v1.1.3/go.mod h1:Rflh2EJ/++BA2/vY5ao3K6WJRR/bZKsX123aPk+kUtA= -github.com/containerd/go-cni v1.1.6/go.mod h1:BWtoWl5ghVymxu6MBjg79W9NZrCRyHIdUtk4cauMe34= -github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= -github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= -github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= -github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= -github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= -github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= -github.com/containerd/imgcrypt v1.1.3/go.mod h1:/TPA1GIDXMzbj01yd8pIbQiLdQxed5ue1wb8bP7PQu4= -github.com/containerd/imgcrypt v1.1.4/go.mod h1:LorQnPtzL/T0IyCeftcsMEO7AqxUDbdO8j/tSUpgxvo= -github.com/containerd/imgcrypt v1.1.7/go.mod h1:FD8gqIcX5aTotCtOmjeCsi3A1dHmTZpnMISGKSczt4k= -github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= -github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= -github.com/containerd/nri v0.3.0/go.mod h1:Zw9q2lP16sdg0zYybemZ9yTDy8g7fPCIB3KXOGlggXI= -github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= -github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= -github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= -github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ= -github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3/go.mod h1:YYyNVhZrTMiaf51Vj6WhAJqJw+vl/nzABhj8pWrzle4= -github.com/containerd/ttrpc v1.2.2/go.mod h1:sIT6l32Ph/H9cvnJsfXM5drIVzTr5A2flTf1G5tYZak= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= -github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= -github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= -github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= -github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= -github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= -github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= -github.com/containerd/zfs v1.1.0/go.mod h1:oZF9wBnrnQjpWLaPKEinrx3TQ9a+W/RJO7Zb41d8YLE= -github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= -github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y= -github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= -github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= -github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= -github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containernetworking/plugins v1.0.1/go.mod h1:QHCfGpaTwYTbbH+nZXKVTxNBDZcxSOplJT5ico8/FLE= -github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= -github.com/containernetworking/plugins v1.2.0/go.mod h1:/VjX4uHecW5vVimFa1wkG4s+r/s9qIfPdqlLF4TW8c4= -github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= -github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= -github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= -github.com/containers/ocicrypt v1.1.3/go.mod h1:xpdkbVAuaH3WzbEabUd5yDsl9SwJA5pABH85425Es2g= -github.com/containers/ocicrypt v1.1.6/go.mod h1:WgjxPWdTJMqYMjf3M6cuIFFA1/MpyyhIM99YInA+Rvc= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/consensys/gnark-crypto v0.12.2-0.20231117165148-e77308824822 h1:PvEjRgB/U4bv0jl9w65Wy9g0nIdkkW7vkNoR8Vq/als= +github.com/consensys/gnark-crypto v0.12.2-0.20231117165148-e77308824822/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= -github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= -github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= -github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= -github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= -github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= -github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M= -github.com/dgraph-io/badger/v4 v4.1.0 h1:E38jc0f+RATYrycSUf9LMv/t47XAy+3CApyYSq4APOQ= -github.com/dgraph-io/badger/v4 v4.1.0/go.mod h1:P50u28d39ibBRmIJuQC/NSdBOg46HnHw7al2SW5QRHg= -github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= +github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= +github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= -github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/distribution/distribution/v3 v3.0.0-20220526142353-ffbd94cbe269/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v23.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v23.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= -github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34= -github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= -github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= -github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/foxcpp/go-mockdns v0.0.0-20210729171921-fb145fc6f897/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= -github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= -github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= -github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= -github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= -github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= -github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= -github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= -github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-ini/ini v1.66.6/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= -github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= -github.com/go-redis/redis v6.10.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= -github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= -github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= -github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= -github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -1358,704 +106,178 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= -github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= -github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= -github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= +github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= -github.com/google/go-containerregistry v0.14.0/go.mod h1:aiJ2fp/SXvkWgmYHioXnbMdlgB8eXiiYOY55gfN91Wk= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.0/go.mod h1:OJpEgntRZo8ugHpF9hkoLJbS5dSI20XZeXJ9JVywLlM= -github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.8.0/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= -github.com/googleapis/gax-go/v2 v2.10.0/go.mod h1:4UOEnMCrxsSqQ940WnTiD6qJ63le2ev3xfyagutxiPw= -github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0 h1:mdLirNAJBxnGgyB6pjZLcs6ue/6eZGBui6gXspfq4ks= -github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0-rc.0/go.mod h1:kdXbOySqcQeTxiqglW7aahTmWZy3Pgi6SYL36yvKeyA= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.5 h1:3IZOAnD058zZllQTZNBioTlrzrBG/IjpiZ133IEtusM= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.5/go.mod h1:xbKERva94Pw2cPen0s79J3uXmGzbbpDYFBFDlZ4mV/w= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/hashicorp/golang-lru v0.6.0 h1:uL2shRDx7RTrOrTCUZEGP/wJUFiUI8QT6E7z5o8jga4= -github.com/hashicorp/golang-lru v0.6.0/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tggROQKKcnh4eItay6z/HbHLqghBxS8g7pyMhmDio= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0/go.mod h1:hKAkSgNkL0FII46ZkJcpVEAai4KV+swlIWCKfekd1pA= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y= +github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= -github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= -github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= +github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU= +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/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/intel/goresctrl v0.2.0/go.mod h1:+CZdzouYFn5EsxgqAQTEzMfwKwuc0fVdMrT9FCCAVRQ= -github.com/intel/goresctrl v0.3.0/go.mod h1:fdz3mD85cmP9sHD8JUlrNWAxvwM86CrbmVXltEKd7zk= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= -github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= -github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= +github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= -github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= -github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ= -github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= -github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= -github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY= -github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= -github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= -github.com/lyft/protoc-gen-star v0.6.0/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star v0.6.1/go.mod h1:TGAoBVkt8w7MPG72TrKIu85MIdXwDuzJYeZuUPFPNwA= -github.com/lyft/protoc-gen-star/v2 v2.0.1/go.mod h1:RcCdONR2ScXaYnQC5tUzxzlpA3WVYF7/opLeUgcQs/o= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= -github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions v1.0.2/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= -github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= -github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= -github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= -github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 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/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= -github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= 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/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= -github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= -github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= -github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/signal v0.6.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= -github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= -github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= -github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= -github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= -github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/mr-tron/base58 v1.1.2/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/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= 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-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-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= -github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= +github.com/multiformats/go-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE= +github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8= 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-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-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/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nats-io/jwt/v2 v2.2.1-0.20220113022732-58e87895b296 h1:vU9tpM3apjYlLLeY23zRWJ9Zktr5jp+mloR942LEOpY= -github.com/nats-io/nats-server/v2 v2.7.4 h1:c+BZJ3rGzUKCBIM4IXO8uNT2u1vajGbD1kPA6wqCEaM= -github.com/nats-io/nats-server/v2 v2.7.4/go.mod h1:1vZ2Nijh8tcyNe8BDVyTviCd9NYzRbubQYiEHsvOQWc= -github.com/nats-io/nats.go v1.27.1 h1:OuYnal9aKVSnOzLQIzf7554OXMCG7KbaTkCSBHRcSoo= -github.com/nats-io/nats.go v1.27.1/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= -github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA= -github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= +github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= +github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= +github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= +github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/networkplumbing/go-nft v0.2.0/go.mod h1:HnnM+tYvlGAsMU7yoYwXEVLLiDW9gdMmb5HoGcwpuQs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nspcc-dev/dbft v0.0.0-20191205084618-dacb1a30c254/go.mod h1:w1Ln2aT+dBlPhLnuZhBV+DfPEdS2CHWWLp5JTScY3bw= -github.com/nspcc-dev/dbft v0.0.0-20191209120240-0d6b7568d9ae/go.mod h1:3FjXOoHmA51EGfb5GS/HOv7VdmngNRTssSeQ729dvGY= -github.com/nspcc-dev/dbft v0.0.0-20200117124306-478e5cfbf03a/go.mod h1:/YFK+XOxxg0Bfm6P92lY5eDSLYfp06XOdL8KAVgXjVk= -github.com/nspcc-dev/dbft v0.0.0-20200219114139-199d286ed6c1/go.mod h1:O0qtn62prQSqizzoagHmuuKoz8QMkU3SzBoKdEvm3aQ= -github.com/nspcc-dev/dbft v0.0.0-20210721160347-1b03241391ac/go.mod h1:U8MSnEShH+o5hexfWJdze6uMFJteP0ko7J2frO7Yu1Y= -github.com/nspcc-dev/dbft v0.0.0-20221020093431-31c1bbdc74f2/go.mod h1:g9xisXmX9NP9MjioaTe862n9SlZTrP+6PVUWLBYOr98= -github.com/nspcc-dev/dbft v0.0.0-20230515113611-25db6ba61d5c/go.mod h1:kjBC9F8L25GR+kIHy/1KgG/KfcoGnVwIiyovgq1uszk= -github.com/nspcc-dev/go-ordered-json v0.0.0-20210915112629-e1b6cce73d02/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= -github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22 h1:n4ZaFCKt1pQJd7PXoMJabZWK9ejjbLOVrkl/lOUmshg= -github.com/nspcc-dev/go-ordered-json v0.0.0-20220111165707-25110be27d22/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= -github.com/nspcc-dev/hrw v1.0.9/go.mod h1:l/W2vx83vMQo6aStyx2AuZrJ+07lGv2JQGlVkPG06MU= -github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1:pPYwPZ2ks+uMnlRLUyXOpLieaDQSEaf4NM3zHVbRjmg= -github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= -github.com/nspcc-dev/neo-go v0.100.1/go.mod h1:Nnp7F4e9IBccsgtCeLtUWV+0T6gk1PtP5HRtA13hUfc= -github.com/nspcc-dev/neo-go v0.103.0 h1:UVyWPhzZdfYFG35ORP3FRDLh8J/raRQ6m8SptDdlgfM= -github.com/nspcc-dev/neo-go v0.103.0/go.mod h1:x+wmcYqpZYJwLp1l/pHZrqNp3RSWlkMymWGDij3/OPo= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20221202075445-cb5c18dc73eb/go.mod h1:23bBw0v6pBYcrWs8CBEEDIEDJNbcFoIh8pGGcf2Vv8s= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5 h1:09CpI5uwsxb1EeFPIKQRwwWlfCmDD/Dwwh01lPiQScM= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231020160724-c3955f87d1b5/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= -github.com/nspcc-dev/neofs-api-go/v2 v2.14.0/go.mod h1:DRIr0Ic1s+6QgdqmNFNLIqMqd7lNMJfYwkczlm1hDtM= -github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= -github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= -github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= -github.com/nspcc-dev/neofs-crypto v0.4.0/go.mod h1:6XJ8kbXgOfevbI2WMruOtI+qUJXNwSGM/E9eClXxPHs= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659/go.mod h1:/jay1lr3w7NQd/VDBkEhkJmDmyPNsu4W+QV2obsUV40= -github.com/nspcc-dev/neofs-sdk-go v1.0.0-rc.11/go.mod h1:W+ImTNRnSNMH8w43H1knCcIqwu7dLHePXtlJNZ7EFIs= -github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= +github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c h1:OOQeE613BH93ICPq3eke5N78gWNeMjcBWkmD2NKyXVg= +github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= +github.com/nspcc-dev/neo-go v0.104.0 h1:FGj3Z46yABcFIAI1SCLd1jQSoh+B00h/2VAgEgY1JKQ= +github.com/nspcc-dev/neo-go v0.104.0/go.mod h1:omsUK5PAtG2/nQ3/evs95QEg3wtkj3LH53e0NKtXVwQ= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231201072346-6c0c2a6a98b0 h1:GYeU/mq2qfq6fNSuTzgxvlQQUydeCBicjzdnggwtuz0= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231201072346-6c0c2a6a98b0/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= -github.com/nspcc-dev/tzhash v1.7.0/go.mod h1:Dnx9LUlOLr5paL2Rtc96x0PPs8D9eIkUtowt1n+KQus= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= -github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= -github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= -github.com/onsi/ginkgo/v2 v2.6.1/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= -github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= -github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= -github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= -github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= -github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk= -github.com/open-policy-agent/opa v0.42.2/go.mod h1:MrmoTi/BsKWT58kXlVayBb+rYVeaMwuBm3nYAN3923s= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2-0.20211117181255-693428a734f5/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= -github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runc v1.1.2/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= -github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= -github.com/opencontainers/runc v1.1.8/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20220825212826-86290f6a00fb/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/runtime-tools v0.9.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626/go.mod h1:BRHJJd0E+cx42OybVYSgUvZmU0B8P9gZuRXlZUP7TKI= -github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= -github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= -github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= -github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opencontainers/selinux v1.10.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= -github.com/panjf2000/ants/v2 v2.7.5 h1:/vhh0Hza9G1vP1PdCj9hl6MUzCRbmtcTJL0OsnmytuU= -github.com/panjf2000/ants/v2 v2.7.5/go.mod h1:KIBmYG9QQX5U2qzFP/yQJaq/nSb6rahS9iEHkrCMgM8= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo= +github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= github.com/paulmach/orb v0.9.2 h1:p/YWV2uJwamAynnDOJGNbPBVtDHj3vG51k9tR1rFwJE= github.com/paulmach/orb v0.9.2/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/peterh/liner v0.0.0-20170211195444-bf27d3ba8e1d/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= -github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= -github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= -github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= -github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= -github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= -github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= -github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/safchain/ethtool v0.2.0/go.mod h1:WkKB1DnNtvsMlDmQ50sgwowDJV/hGbJSOvJoEXs1AJQ= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= -github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= -github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= -github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= -github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= -github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= +github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -2065,1076 +287,162 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= -github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= -github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/syndtr/goleveldb v0.0.0-20180307113352-169b1b37be73/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= -github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs= -github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= -github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k= -github.com/testcontainers/testcontainers-go v0.22.0/go.mod h1:k0YiPa26xJCRUbUkYqy5rY6NGvSbVCeUBXCvucscBR4= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= +github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= -github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= -github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= -github.com/vektah/gqlparser/v2 v2.4.5/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0= -github.com/veraison/go-cose v1.0.0-rc.1/go.mod h1:7ziE85vSq4ScFTg6wyoMXjucIGOf4JkFEZi/an96Ct4= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= -github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yashtewari/glob-intersection v0.1.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/gopher-lua v0.0.0-20190514113301-1cd887cd7036/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= -github.com/yuin/gopher-lua v0.0.0-20191128022950-c6266f4fe8d7/go.mod h1:gqRgreBUhTSL0GeU64rtZ3Uq3wtjOa/TB2YfrtkCbVQ= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v2 v2.305.5/go.mod h1:zQjKllfqfBVyVStbt4FaosoX2iYd8fV/GRy/PbowgP4= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/pkg/v3 v3.5.5/go.mod h1:6ksYFxttiUGzC2uxyqiyOEvhAiD0tuIqSZkX3TyPdaE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/raft/v3 v3.5.5/go.mod h1:76TA48q03g1y1VpTue92jZLr9lIHKUNcYdZOOGyx8rI= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= -go.etcd.io/etcd/server/v3 v3.5.5/go.mod h1:rZ95vDw/jrvsbj9XpTqPrTAB9/kzchVdhRirySPkUBc= -go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= +go.mongodb.org/mongo-driver v1.11.4 h1:4ayjakA013OdpGyL2K3ZqylTac/rMjrJOMZ1EHizXas= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= -go.mongodb.org/mongo-driver v1.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE= -go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0= -go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.25.0/go.mod h1:E5NNboN0UqSAki0Atn9kVwaN7I+l25gGxDqBueo/74E= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0/go.mod h1:vEhqr0m4eTc+DWxfsXoXue2GBgV2uUwVznkGIHW/e5w= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.40.0/go.mod h1:UMklln0+MRhZC4e3PwmN3pCtq4DyIadWw4yikh6bNrw= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.32.0/go.mod h1:5eCOqeGphOyz6TsY3ZDNjE33SM/TFAK3RGuCL2naTgY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= -go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= -go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= -go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM= -go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= -go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.7.0/go.mod h1:M1hVZHNxcbkAlcvrOMlpQ4YOO3Awf+4N2dxkZL3xm04= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0/go.mod h1:UFG7EBMRdXyFstOwH028U0sVf+AvukSGhF0g8+dmNG8= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.7.0/go.mod h1:ceUgdyfNv4h4gLxHR0WNfDiiVmZFodZhZSbOLhpxqXE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0/go.mod h1:HrbCVv40OOLTABmOn1ZWty6CHXkU8DK/Urc43tHug70= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.3.0/go.mod h1:keUU7UfnwWTWpJ+FWnyqmogPa82nuU5VUANFq49hlMY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.7.0/go.mod h1:E+/KKhwOSw8yoPxSSuUHG6vKppkvhN+S1Jc7Nib3k3o= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0/go.mod h1:5w41DY6S9gZrbjuq6Y+753e96WfPha5IcsOSZTtullM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 h1:TVQp/bboR4mhZSav+MdgXB8FaRho1RC8UwVn3T0vjVc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.14.0/go.mod h1:+N7zNjIJv4K+DeX67XXET0P+eIciESgaFDBqh+ZJFS4= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 h1:+XWJd3jf75RXJq29mxbuXhCXFDG3S3R4vBUeSI2P7tE= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0/go.mod h1:hqgzBPTf4yONMFgdZvL/bK42R/iinTyVQtiWihs3SZc= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/metric v0.30.0/go.mod h1:/ShZ7+TS4dHzDFmfi1kSXMhMVubNoP0oIaBp70J6UXU= -go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= -go.opentelemetry.io/otel/metric v0.37.0/go.mod h1:DmdaHfGt54iV6UKxsV9slj2bBRJcKC1B1uvDLIioc1s= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI= -go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= -go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= -go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= -go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk= -go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= -go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= -go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= -go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= -go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= -go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ= -go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.16.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.opentelemetry.io/proto/otlp v0.20.0 h1:BLOA1cZBAGSbRiNuGCCKiFrCdYB7deeHDeD1SueyOfA= -go.opentelemetry.io/proto/otlp v0.20.0/go.mod h1:3QgjzPALBIv9pcknj2EXGPXjYPFdUh/RQfF8Lz3+Vnw= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 h1:VhlEQAPp9R1ktYfrPk5SOryw1e9LDDTZCbIPFrho0ec= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0/go.mod h1:kB3ufRbfU+CQ4MlUcqtW8Z7YEOBeK2DJ6CmR5rYYF3E= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= -golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= -golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/exp v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= -golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= +golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= -golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= -gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= -gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= -google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= -google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.118.0/go.mod h1:76TtD3vkgmZ66zZzp72bUUklpmQmKlhh6sYtIjYK+5E= -google.golang.org/api v0.122.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= -google.golang.org/api v0.124.0/go.mod h1:xu2HQurE5gi/3t1aFCvhPD781p0a3p11sdunTJ2BlP4= -google.golang.org/api v0.125.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= -google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220329172620-7be39ac1afc7/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221109142239-94d6d90a7d66/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221114212237-e4508ebdbee1/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221117204609-8f9c96812029/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230112194545-e10362b5ecf9/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230113154510-dbe35b8444a5/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230123190316-2c411cf9d197/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230125152338-dcaf20b6aeaa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44/go.mod h1:8B0gmkoRebU8ukX6HP+4wrVQUY1+6PkQ44BSyIlflHA= -google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= -google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230320184635-7606e756e683/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= -google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= -google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= -google.golang.org/genproto v0.0.0-20230629202037-9506855d4529/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= -google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= -google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a h1:fwgW9j3vHirt4ObdHoYNwuO24BEZjSzbh+zPaNWoiY8= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234020-1aefcd67740a/go.mod h1:ts19tUU+Z0ZShN1y3aPyq2+O3d5FUNNgT6FtOzmrNn8= -google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= -google.golang.org/genproto/googleapis/bytestream v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:ylj+BE99M198VPbBh6A8d9n3w8fChvyLK3wwBOjXBFA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234015-3fc162c6f38a/go.mod h1:xURIpW9ES5+/GZhnV6beoEtxQrnkRGIfP5VQG2tCBLc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230629202037-9506855d4529/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f h1:Vn+VyHU5guc9KjB5KrjI2q0wCOWEOIh0OEsleqakHJg= +google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 h1:ZcOkrmX74HbKFYnpPY8Qsw93fC29TbJXspYKaBkSXDQ= +google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= -google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -3143,205 +451,32 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/abiosoft/ishell.v2 v2.0.0/go.mod h1:sFp+cGtH6o4s1FtpVPTMcHq2yue+c4DGOVohJCPUzwY= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/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.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= -gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= -k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.22.5/go.mod h1:mEhXyLaSD1qTOf40rRiKXkc+2iCem09rWLlFwhCEiAs= -k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU= -k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.22.1/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apimachinery v0.22.5/go.mod h1:xziclGKwuuJ2RM5/rSFQSYAj0zdbci3DH8kj+WvyN0U= -k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= -k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I= -k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= -k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.22.5/go.mod h1:s2WbtgZAkTKt679sYtSudEQrTGWUSQAPe6MupLnlmaQ= -k8s.io/apiserver v0.26.2/go.mod h1:GHcozwXgXsPuOJ28EnQ/jXEM9QeG6HT22YxSNmpYNh8= -k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= -k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.22.5/go.mod h1:cs6yf/61q2T1SdQL5Rdcjg9J1ElXSwbjSrW2vFImM4Y= -k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU= -k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= -k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= -k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.22.5/go.mod h1:VK3I+TjuF9eaa+Ln67dKxhGar5ynVbwnGrUiNF4MqCI= -k8s.io/component-base v0.26.2/go.mod h1:DxbuIe9M3IZPRxPIzhch2m1eT7uFrSBJUBuVCQEBivs= -k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= -k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= -k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= -k8s.io/cri-api v0.23.1/go.mod h1:REJE3PSU0h/LOV1APBrupxrEJqnoxZC8KWzkBUHwrK4= -k8s.io/cri-api v0.25.0/go.mod h1:J1rAyQkSJ2Q6I+aBMOVgg2/cbbebso6FNa0UagiR0kc= -k8s.io/cri-api v0.25.3/go.mod h1:riC/P0yOGUf2K1735wW+CXs1aY2ctBgePtnnoFLd0dU= -k8s.io/cri-api v0.27.1/go.mod h1:+Ts/AVYbIo04S86XbTD73UPp/DkTiYxtsFeOFEu32L0= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kms v0.26.2/go.mod h1:69qGnf1NsFOQP07fBYqNLZklqEHSJF024JqYCaeVxHg= -k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= -k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20221107191617-1a15be271d1d/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= -lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= -modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20= -modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= -modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= -modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= -modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI= -modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= -modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= -modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= -modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g= -modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= -modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= -modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= -modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= -modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= -modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= -modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA= -modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0= -modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0= -modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI= -modernc.org/libc v1.22.2/go.mod h1:uvQavJ1pZ0hIoC/jfqNoMLURIMhKzINIWypNM17puug= -modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= -modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= -modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= -modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= -modernc.org/sqlite v1.18.2/go.mod h1:kvrTLEWgxUcHa2GfHBQtanR1H9ht3hTJNtKpzH9k1u0= -modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= -modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= -modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= -modernc.org/tcl v1.13.2/go.mod h1:7CLiGIPo1M8Rv1Mitpv5akc2+8fxUd2y2UzC/MfMzy0= -modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= -oras.land/oras-go v1.2.0/go.mod h1:pFNs7oHp2dYsYMSS82HaX5l4mpnGO7hbpPN6EWH2ltc= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35/go.mod h1:WxjusMwXlKzfAs4p9km6XJRndVt2FROgMVCE4cdohFo= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= From 6bb27f98ddf009f0fff9808d264238cea9894c00 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 1 Dec 2023 13:12:05 +0300 Subject: [PATCH 0175/1413] [#837] .pre-commit: Update hook versions Signed-off-by: Evgenii Stratonikov --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ecd70390c5..f66adda0bb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: gitlint-ci - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-added-large-files - id: check-case-conflict @@ -26,7 +26,7 @@ repos: exclude: ".key$" - repo: https://github.com/shellcheck-py/shellcheck-py - rev: v0.9.0.5 + rev: v0.9.0.6 hooks: - id: shellcheck From b892feeaf65b89af3b5aa712dca5aefd11d5d660 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Dec 2023 11:57:04 +0300 Subject: [PATCH 0176/1413] [#845] adm: Relax notary-enabled check Starting from v0.104.0 `NativeActivations` config field is no longer present and Notary activation height is always 0. https://github.com/nspcc-dev/neo-go/pull/3212/ https://git.frostfs.info/TrueCloudLab/frostfs-dev-env/issues/59 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/initialize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index e288361dd6..96100ffb58 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -519,7 +519,7 @@ func checkNotaryEnabled(c Client) error { nativeHashes := make(map[string]util.Uint160, len(ns)) for i := range ns { if ns[i].Manifest.Name == nativenames.Notary { - notaryEnabled = len(ns[i].UpdateHistory) > 0 + notaryEnabled = true } nativeHashes[ns[i].Manifest.Name] = ns[i].Hash } From 29550fe6003ed5a10daf1ed4ad0c08982d0af022 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 4 Dec 2023 12:54:23 +0300 Subject: [PATCH 0177/1413] [#838] shard: Refactor `updateMetrics` method Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/shard.go | 86 +++++++++++++------------ 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index aa87e0cfcb..ff437d7ee8 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -398,52 +398,54 @@ const ( ) func (s *Shard) updateMetrics(ctx context.Context) { - if s.cfg.metricsWriter != nil && !s.GetMode().NoMetabase() { - cc, err := s.metaBase.ObjectCounters() + if s.cfg.metricsWriter == nil || s.GetMode().NoMetabase() { + return + } + + cc, err := s.metaBase.ObjectCounters() + if err != nil { + s.log.Warn(logs.ShardMetaObjectCounterRead, + zap.Error(err), + ) + + return + } + + s.cfg.metricsWriter.SetObjectCounter(physical, cc.Phy()) + s.cfg.metricsWriter.SetObjectCounter(logical, cc.Logic()) + + cnrList, err := s.metaBase.Containers(ctx) + if err != nil { + s.log.Warn(logs.ShardMetaCantReadContainerList, zap.Error(err)) + return + } + + var totalPayload uint64 + + for i := range cnrList { + size, err := s.metaBase.ContainerSize(cnrList[i]) if err != nil { - s.log.Warn(logs.ShardMetaObjectCounterRead, - zap.Error(err), - ) - - return + s.log.Warn(logs.ShardMetaCantReadContainerSize, + zap.String("cid", cnrList[i].EncodeToString()), + zap.Error(err)) + continue } + s.metricsWriter.AddToContainerSize(cnrList[i].EncodeToString(), int64(size)) + totalPayload += size + } - s.cfg.metricsWriter.SetObjectCounter(physical, cc.Phy()) - s.cfg.metricsWriter.SetObjectCounter(logical, cc.Logic()) + s.metricsWriter.AddToPayloadSize(int64(totalPayload)) - cnrList, err := s.metaBase.Containers(ctx) - if err != nil { - s.log.Warn(logs.ShardMetaCantReadContainerList, zap.Error(err)) - return - } - - var totalPayload uint64 - - for i := range cnrList { - size, err := s.metaBase.ContainerSize(cnrList[i]) - if err != nil { - s.log.Warn(logs.ShardMetaCantReadContainerSize, - zap.String("cid", cnrList[i].EncodeToString()), - zap.Error(err)) - continue - } - s.metricsWriter.AddToContainerSize(cnrList[i].EncodeToString(), int64(size)) - totalPayload += size - } - - s.metricsWriter.AddToPayloadSize(int64(totalPayload)) - - contCount, err := s.metaBase.ContainerCounters(ctx) - if err != nil { - s.log.Warn(logs.FailedToGetContainerCounters, zap.Error(err)) - return - } - for contID, count := range contCount.Physical { - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), physical, count) - } - for contID, count := range contCount.Logical { - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), logical, count) - } + contCount, err := s.metaBase.ContainerCounters(ctx) + if err != nil { + s.log.Warn(logs.FailedToGetContainerCounters, zap.Error(err)) + return + } + for contID, count := range contCount.Physical { + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), physical, count) + } + for contID, count := range contCount.Logical { + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), logical, count) } } From f314da4af320ff7df80f69d6928ff85b96318b8e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 4 Dec 2023 17:35:11 +0300 Subject: [PATCH 0178/1413] [#838] metabase: Add user object type counter Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/counter.go | 129 ++++++---- .../metabase/counter_test.go | 239 ++++++++---------- pkg/local_object_storage/metabase/delete.go | 8 +- pkg/local_object_storage/metabase/inhume.go | 8 +- .../shard/control_test.go | 8 +- pkg/local_object_storage/shard/count.go | 2 +- .../shard/metrics_test.go | 59 +++-- pkg/local_object_storage/shard/shard.go | 21 +- 8 files changed, 247 insertions(+), 227 deletions(-) diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index d1aafa3dbf..be860830aa 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -18,6 +18,7 @@ import ( var ( objectPhyCounterKey = []byte("phy_counter") objectLogicCounterKey = []byte("logic_counter") + objectUserCounterKey = []byte("user_counter") ) type objectType uint8 @@ -31,18 +32,13 @@ const ( // ObjectCounters groups object counter // according to metabase state. type ObjectCounters struct { - logic uint64 - phy uint64 + Logic uint64 + Phy uint64 + User uint64 } -// Logic returns logical object counter. -func (o ObjectCounters) Logic() uint64 { - return o.logic -} - -// Phy returns physical object counter. -func (o ObjectCounters) Phy() uint64 { - return o.phy +func (o ObjectCounters) IsZero() bool { + return o.Phy == 0 && o.Logic == 0 && o.User == 0 } // ObjectCounters returns object counters that metabase has @@ -63,12 +59,17 @@ func (db *DB) ObjectCounters() (cc ObjectCounters, err error) { if b != nil { data := b.Get(objectPhyCounterKey) if len(data) == 8 { - cc.phy = binary.LittleEndian.Uint64(data) + cc.Phy = binary.LittleEndian.Uint64(data) } data = b.Get(objectLogicCounterKey) if len(data) == 8 { - cc.logic = binary.LittleEndian.Uint64(data) + cc.Logic = binary.LittleEndian.Uint64(data) + } + + data = b.Get(objectUserCounterKey) + if len(data) == 8 { + cc.User = binary.LittleEndian.Uint64(data) } } @@ -79,8 +80,7 @@ func (db *DB) ObjectCounters() (cc ObjectCounters, err error) { } type ContainerCounters struct { - Logical map[cid.ID]uint64 - Physical map[cid.ID]uint64 + Counts map[cid.ID]ObjectCounters } // ContainerCounters returns object counters for each container @@ -103,8 +103,7 @@ func (db *DB) ContainerCounters(ctx context.Context) (ContainerCounters, error) defer span.End() cc := ContainerCounters{ - Logical: make(map[cid.ID]uint64), - Physical: make(map[cid.ID]uint64), + Counts: make(map[cid.ID]ObjectCounters), } lastKey := make([]byte, cidSize) @@ -158,16 +157,11 @@ func (db *DB) containerCountersNextBatch(lastKey []byte, cc *ContainerCounters) if err != nil { return err } - phy, logic, err := parseContainerCounterValue(value) + ent, err := parseContainerCounterValue(value) if err != nil { return err } - if phy > 0 { - cc.Physical[cnrID] = phy - } - if logic > 0 { - cc.Logical[cnrID] = logic - } + cc.Counts[cnrID] = ent counter++ if counter == batchSize { @@ -253,22 +247,23 @@ func (db *DB) updateContainerCounter(tx *bbolt.Tx, delta map[cid.ID]ObjectCounte } func (*DB) editContainerCounterValue(b *bbolt.Bucket, key []byte, delta ObjectCounters, inc bool) error { - var phyValue, logicValue uint64 + var entity ObjectCounters var err error data := b.Get(key) if len(data) > 0 { - phyValue, logicValue, err = parseContainerCounterValue(data) + entity, err = parseContainerCounterValue(data) if err != nil { return err } } - phyValue = nextValue(phyValue, delta.phy, inc) - logicValue = nextValue(logicValue, delta.logic, inc) - if phyValue > 0 || logicValue > 0 { - value := containerCounterValue(phyValue, logicValue) - return b.Put(key, value) + entity.Phy = nextValue(entity.Phy, delta.Phy, inc) + entity.Logic = nextValue(entity.Logic, delta.Logic, inc) + entity.User = nextValue(entity.User, delta.User, inc) + if entity.IsZero() { + return b.Delete(key) } - return b.Delete(key) + value := containerCounterValue(entity) + return b.Put(key, value) } func nextValue(existed, delta uint64, inc bool) uint64 { @@ -290,7 +285,7 @@ func (db *DB) incContainerObjectCounter(tx *bbolt.Tx, cnrID cid.ID) error { key := make([]byte, cidSize) cnrID.Encode(key) - return db.editContainerCounterValue(b, key, ObjectCounters{logic: 1, phy: 1}, true) + return db.editContainerCounterValue(b, key, ObjectCounters{Logic: 1, Phy: 1}, true) } // syncCounter updates object counters according to metabase state: @@ -304,9 +299,11 @@ func syncCounter(tx *bbolt.Tx, force bool) error { if err != nil { return fmt.Errorf("could not get shard info bucket: %w", err) } - shardObjectCounterInitialized := len(shardInfoB.Get(objectPhyCounterKey)) == 8 && len(shardInfoB.Get(objectLogicCounterKey)) == 8 - containerCounterInitialized := tx.Bucket(containerCounterBucketName) != nil - if !force && shardObjectCounterInitialized && containerCounterInitialized { + shardObjectCounterInitialized := len(shardInfoB.Get(objectPhyCounterKey)) == 8 && + len(shardInfoB.Get(objectLogicCounterKey)) == 8 && + len(shardInfoB.Get(objectUserCounterKey)) == 8 + containerObjectCounterInitialized := containerObjectCounterInitialized(tx) + if !force && shardObjectCounterInitialized && containerObjectCounterInitialized { // the counters are already inited return nil } @@ -325,11 +322,11 @@ func syncCounter(tx *bbolt.Tx, force bool) error { err = iteratePhyObjects(tx, func(cnr cid.ID, obj oid.ID) error { if v, ok := counters[cnr]; ok { - v.phy++ + v.Phy++ counters[cnr] = v } else { counters[cnr] = ObjectCounters{ - phy: 1, + Phy: 1, } } @@ -340,11 +337,11 @@ func syncCounter(tx *bbolt.Tx, force bool) error { // and not covered with a tombstone if inGraveyardWithKey(addressKey(addr, key), graveyardBKT, garbageBKT) == 0 { if v, ok := counters[cnr]; ok { - v.logic++ + v.Logic++ counters[cnr] = v } else { counters[cnr] = ObjectCounters{ - logic: 1, + Logic: 1, } } } @@ -361,13 +358,15 @@ func syncCounter(tx *bbolt.Tx, force bool) error { func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, containerCounterB *bbolt.Bucket) error { var phyTotal uint64 var logicTotal uint64 + var userTotal uint64 key := make([]byte, cidSize) for cnrID, count := range counters { - phyTotal += count.phy - logicTotal += count.logic + phyTotal += count.Phy + logicTotal += count.Logic + userTotal += count.User cnrID.Encode(key) - value := containerCounterValue(count.phy, count.logic) + value := containerCounterValue(count) err := containerCounterB.Put(key, value) if err != nil { return fmt.Errorf("could not update phy container object counter: %w", err) @@ -389,13 +388,22 @@ func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, container return fmt.Errorf("could not update logic object counter: %w", err) } + userData := make([]byte, 8) + binary.LittleEndian.PutUint64(userData, userTotal) + + err = shardInfoB.Put(objectUserCounterKey, userData) + if err != nil { + return fmt.Errorf("could not update user object counter: %w", err) + } + return nil } -func containerCounterValue(phy, logic uint64) []byte { - res := make([]byte, 16) - binary.LittleEndian.PutUint64(res, phy) - binary.LittleEndian.PutUint64(res[8:], logic) +func containerCounterValue(entity ObjectCounters) []byte { + res := make([]byte, 24) + binary.LittleEndian.PutUint64(res, entity.Phy) + binary.LittleEndian.PutUint64(res[8:], entity.Logic) + binary.LittleEndian.PutUint64(res[16:], entity.User) return res } @@ -411,9 +419,30 @@ func parseContainerCounterKey(buf []byte) (cid.ID, error) { } // parseContainerCounterValue return phy, logic values. -func parseContainerCounterValue(buf []byte) (uint64, uint64, error) { - if len(buf) != 16 { - return 0, 0, fmt.Errorf("invalid value length") +func parseContainerCounterValue(buf []byte) (ObjectCounters, error) { + if len(buf) != 24 { + return ObjectCounters{}, fmt.Errorf("invalid value length") } - return binary.LittleEndian.Uint64(buf), binary.LittleEndian.Uint64(buf[8:]), nil + return ObjectCounters{ + Phy: binary.LittleEndian.Uint64(buf), + Logic: binary.LittleEndian.Uint64(buf[8:16]), + User: binary.LittleEndian.Uint64(buf[16:]), + }, nil +} + +func containerObjectCounterInitialized(tx *bbolt.Tx) bool { + b := tx.Bucket(containerCounterBucketName) + if b == nil { + return false + } + k, v := b.Cursor().First() + if k == nil && v == nil { + return true + } + _, err := parseContainerCounterKey(k) + if err != nil { + return false + } + _, err = parseContainerCounterValue(v) + return err == nil } diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 51062f1fe1..27d0b37ae9 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -24,13 +24,13 @@ func TestCounters(t *testing.T) { db := newDB(t) c, err := db.ObjectCounters() require.NoError(t, err) - require.Zero(t, c.Phy()) - require.Zero(t, c.Logic()) + require.Zero(t, c.Phy) + require.Zero(t, c.Logic) + require.Zero(t, c.User) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Zero(t, len(cc.Physical)) - require.Zero(t, len(cc.Logical)) + require.Zero(t, len(cc.Counts)) }) t.Run("put", func(t *testing.T) { @@ -42,29 +42,30 @@ func TestCounters(t *testing.T) { } var prm meta.PutPrm - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for i := 0; i < objCount; i++ { prm.SetObject(oo[i]) cnrID, _ := oo[i].ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + c := meta.ObjectCounters{} + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } _, err := db.Put(context.Background(), prm) require.NoError(t, err) - c, err := db.ObjectCounters() + c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(i+1), c.Phy()) - require.Equal(t, uint64(i+1), c.Logic()) + require.Equal(t, uint64(i+1), c.Phy) + require.Equal(t, uint64(i+1), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) } }) @@ -73,12 +74,13 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, false) - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, obj := range oo { cnrID, _ := obj.ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } var prm meta.DeletePrm @@ -92,29 +94,23 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(i), c.Phy()) - require.Equal(t, uint64(i), c.Logic()) + require.Equal(t, uint64(i), c.Phy) + require.Equal(t, uint64(i), c.Logic) cnrID, _ := oo[i].ContainerID() - if v, ok := expPhy[cnrID]; ok { - if v == 1 { - delete(expPhy, cnrID) + if v, ok := exp[cnrID]; ok { + v.Phy-- + v.Logic-- + if v.IsZero() { + delete(exp, cnrID) } else { - expPhy[cnrID]-- - } - } - if v, ok := expLog[cnrID]; ok { - if v == 1 { - delete(expLog, cnrID) - } else { - expLog[cnrID]-- + exp[cnrID] = v } } cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) } }) @@ -123,12 +119,13 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, false) - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, obj := range oo { cnrID, _ := obj.ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } inhumedObjs := make([]oid.Address, objCount/2) @@ -142,11 +139,12 @@ func TestCounters(t *testing.T) { } for _, addr := range inhumedObjs { - if v, ok := expLog[addr.Container()]; ok { - if v == 1 { - delete(expLog, addr.Container()) + if v, ok := exp[addr.Container()]; ok { + v.Logic-- + if v.IsZero() { + delete(exp, addr.Container()) } else { - expLog[addr.Container()]-- + exp[addr.Container()] = v } } } @@ -162,14 +160,13 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount), c.Phy()) - require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic()) + require.Equal(t, uint64(objCount), c.Phy) + require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) }) t.Run("put_split", func(t *testing.T) { @@ -177,8 +174,7 @@ func TestCounters(t *testing.T) { db := newDB(t) parObj := testutil.GenerateObject() - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) // put objects and check that parent info // does not affect the counter @@ -189,20 +185,21 @@ func TestCounters(t *testing.T) { } cnrID, _ := o.ContainerID() - expLog[cnrID]++ - expPhy[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } require.NoError(t, putBig(db, o)) c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(i+1), c.Phy()) - require.Equal(t, uint64(i+1), c.Logic()) + require.Equal(t, uint64(i+1), c.Phy) + require.Equal(t, uint64(i+1), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) } }) @@ -211,12 +208,13 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, true) - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, obj := range oo { cnrID, _ := obj.ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } // delete objects that have parent info @@ -228,21 +226,15 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount-i-1), c.Phy()) - require.Equal(t, uint64(objCount-i-1), c.Logic()) + require.Equal(t, uint64(objCount-i-1), c.Phy) - if v, ok := expPhy[addr.Container()]; ok { - if v == 1 { - delete(expPhy, addr.Container()) + if v, ok := exp[addr.Container()]; ok { + v.Logic-- + v.Phy-- + if v.IsZero() { + delete(exp, addr.Container()) } else { - expPhy[addr.Container()]-- - } - } - if v, ok := expLog[addr.Container()]; ok { - if v == 1 { - delete(expLog, addr.Container()) - } else { - expLog[addr.Container()]-- + exp[addr.Container()] = v } } } @@ -253,12 +245,13 @@ func TestCounters(t *testing.T) { db := newDB(t) oo := putObjs(t, db, objCount, true) - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, obj := range oo { cnrID, _ := obj.ContainerID() - expPhy[cnrID]++ - expLog[cnrID]++ + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } inhumedObjs := make([]oid.Address, objCount/2) @@ -272,11 +265,12 @@ func TestCounters(t *testing.T) { } for _, addr := range inhumedObjs { - if v, ok := expLog[addr.Container()]; ok { - if v == 1 { - delete(expLog, addr.Container()) + if v, ok := exp[addr.Container()]; ok { + v.Logic-- + if v.IsZero() { + delete(exp, addr.Container()) } else { - expLog[addr.Container()]-- + exp[addr.Container()] = v } } } @@ -291,14 +285,13 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount), c.Phy()) - require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic()) + require.Equal(t, uint64(objCount), c.Phy) + require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) }) } @@ -320,25 +313,25 @@ func TestCounters_Expired(t *testing.T) { oo[i] = putWithExpiration(t, db, objectSDK.TypeRegular, epoch+1) } - expPhy := make(map[cid.ID]uint64) - expLog := make(map[cid.ID]uint64) + exp := make(map[cid.ID]meta.ObjectCounters) for _, addr := range oo { - expPhy[addr.Container()]++ - expLog[addr.Container()]++ + exp[addr.Container()] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } // 1. objects are available and counters are correct c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount), c.Phy()) - require.Equal(t, uint64(objCount), c.Logic()) + require.Equal(t, uint64(objCount), c.Phy) + require.Equal(t, uint64(objCount), c.Logic) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) for _, o := range oo { _, err := metaGet(db, o, true) @@ -352,14 +345,13 @@ func TestCounters_Expired(t *testing.T) { c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(objCount), c.Phy()) - require.Equal(t, uint64(objCount), c.Logic()) + require.Equal(t, uint64(objCount), c.Phy) + require.Equal(t, uint64(objCount), c.Logic) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) for _, o := range oo { _, err := metaGet(db, o, true) @@ -381,22 +373,22 @@ func TestCounters_Expired(t *testing.T) { c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(len(oo)), c.Phy()) - require.Equal(t, uint64(len(oo)-1), c.Logic()) + require.Equal(t, uint64(len(oo)), c.Phy) + require.Equal(t, uint64(len(oo)-1), c.Logic) - if v, ok := expLog[oo[0].Container()]; ok { - if v == 1 { - delete(expLog, oo[0].Container()) + if v, ok := exp[oo[0].Container()]; ok { + v.Logic-- + if v.IsZero() { + delete(exp, oo[0].Container()) } else { - expLog[oo[0].Container()]-- + exp[oo[0].Container()] = v } } cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) // 4. `Delete` an object with GCMark should decrease the // phy counter but does not affect the logic counter (after @@ -409,11 +401,12 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Zero(t, deleteRes.AvailableObjectsRemoved()) - if v, ok := expPhy[oo[0].Container()]; ok { - if v == 1 { - delete(expPhy, oo[0].Container()) + if v, ok := exp[oo[0].Container()]; ok { + v.Phy-- + if v.IsZero() { + delete(exp, oo[0].Container()) } else { - expPhy[oo[0].Container()]-- + exp[oo[0].Container()] = v } } @@ -421,14 +414,13 @@ func TestCounters_Expired(t *testing.T) { c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(len(oo)), c.Phy()) - require.Equal(t, uint64(len(oo)), c.Logic()) + require.Equal(t, uint64(len(oo)), c.Phy) + require.Equal(t, uint64(len(oo)), c.Logic) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) // 5 `Delete` an expired object (like it would the control // service do) should decrease both counters despite the @@ -440,19 +432,13 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(1), deleteRes.AvailableObjectsRemoved()) - if v, ok := expLog[oo[0].Container()]; ok { - if v == 1 { - delete(expLog, oo[0].Container()) + if v, ok := exp[oo[0].Container()]; ok { + v.Phy-- + v.Logic-- + if v.IsZero() { + delete(exp, oo[0].Container()) } else { - expLog[oo[0].Container()]-- - } - } - - if v, ok := expPhy[oo[0].Container()]; ok { - if v == 1 { - delete(expPhy, oo[0].Container()) - } else { - expPhy[oo[0].Container()]-- + exp[oo[0].Container()] = v } } @@ -460,14 +446,13 @@ func TestCounters_Expired(t *testing.T) { c, err = db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(len(oo)), c.Phy()) - require.Equal(t, uint64(len(oo)), c.Logic()) + require.Equal(t, uint64(len(oo)), c.Phy) + require.Equal(t, uint64(len(oo)), c.Logic) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expPhy, cc.Physical) - require.Equal(t, expLog, cc.Logical) + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) } func putObjs(t *testing.T, db *meta.DB, count int, withParent bool) []*objectSDK.Object { @@ -491,8 +476,8 @@ func putObjs(t *testing.T, db *meta.DB, count int, withParent bool) []*objectSDK c, err := db.ObjectCounters() require.NoError(t, err) - require.Equal(t, uint64(i+1), c.Phy()) - require.Equal(t, uint64(i+1), c.Logic()) + require.Equal(t, uint64(i+1), c.Phy) + require.Equal(t, uint64(i+1), c.Logic) } return oo diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 5acd711647..a2100f363e 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -139,11 +139,11 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) if removed { if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { - v.phy++ + v.Phy++ res.removedByCnrID[addrs[i].Container()] = v } else { res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ - phy: 1, + Phy: 1, } } @@ -153,11 +153,11 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) if available { if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { - v.logic++ + v.Logic++ res.removedByCnrID[addrs[i].Container()] = v } else { res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ - logic: 1, + Logic: 1, } } diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index cf7921992a..2a9adff3a8 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -82,11 +82,11 @@ func (i *InhumeRes) storeDeletionInfo(containerID cid.ID, deletedSize uint64) { }) i.availableInhumed++ if v, ok := i.inhumedByCnrID[containerID]; ok { - v.logic++ + v.Logic++ i.inhumedByCnrID[containerID] = v } else { i.inhumedByCnrID[containerID] = ObjectCounters{ - logic: 1, + Logic: 1, } } } @@ -251,10 +251,10 @@ func (db *DB) applyInhumeResToCounters(tx *bbolt.Tx, res *InhumeRes) error { inhumedbyCnr := make(map[cid.ID]ObjectCounters) for _, dd := range res.deletionDetails { if v, ok := inhumedbyCnr[dd.CID]; ok { - v.logic++ + v.Logic++ inhumedbyCnr[dd.CID] = v } else { - inhumedbyCnr[dd.CID] = ObjectCounters{logic: 1} + inhumedbyCnr[dd.CID] = ObjectCounters{Logic: 1} } inhumedCount++ } diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 749229cc3b..f08af6fc74 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -347,8 +347,8 @@ func TestRefillMetabase(t *testing.T) { c, err := sh.metaBase.ObjectCounters() require.NoError(t, err) - phyBefore := c.Phy() - logicalBefore := c.Logic() + phyBefore := c.Phy + logicalBefore := c.Logic err = sh.Close() require.NoError(t, err) @@ -382,8 +382,8 @@ func TestRefillMetabase(t *testing.T) { c, err = sh.metaBase.ObjectCounters() require.NoError(t, err) - require.Equal(t, phyBefore, c.Phy()) - require.Equal(t, logicalBefore, c.Logic()) + require.Equal(t, phyBefore, c.Phy) + require.Equal(t, logicalBefore, c.Logic) checkAllObjs(true) checkObj(object.AddressOf(tombObj), tombObj) diff --git a/pkg/local_object_storage/shard/count.go b/pkg/local_object_storage/shard/count.go index abed5278e4..b3bc6a30b5 100644 --- a/pkg/local_object_storage/shard/count.go +++ b/pkg/local_object_storage/shard/count.go @@ -27,5 +27,5 @@ func (s *Shard) LogicalObjectsCount(ctx context.Context) (uint64, error) { if err != nil { return 0, err } - return cc.Logic(), nil + return cc.Logic, nil } diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 1e9bbf9fcc..138009a7c0 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -178,8 +178,6 @@ func TestCounters(t *testing.T) { oo[i] = testutil.GenerateObject() } - cc := meta.ContainerCounters{Logical: make(map[cid.ID]uint64), Physical: make(map[cid.ID]uint64)} - t.Run("defaults", func(t *testing.T) { require.Zero(t, mm.getObjectCounter(physical)) require.Zero(t, mm.getObjectCounter(logical)) @@ -200,15 +198,16 @@ func TestCounters(t *testing.T) { var totalPayload int64 expectedLogicalSizes := make(map[string]int64) - expectedLogCC := make(map[cid.ID]uint64) - expectedPhyCC := make(map[cid.ID]uint64) + expected := make(map[cid.ID]meta.ObjectCounters) for i := range oo { cnr, _ := oo[i].ContainerID() oSize := int64(oo[i].PayloadSize()) expectedLogicalSizes[cnr.EncodeToString()] += oSize totalPayload += oSize - expectedLogCC[cnr]++ - expectedPhyCC[cnr]++ + expected[cnr] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + } } var prm PutPrm @@ -227,8 +226,7 @@ func TestCounters(t *testing.T) { cc, err := sh.metaBase.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expectedLogCC, cc.Logical) - require.Equal(t, expectedPhyCC, cc.Physical) + require.Equal(t, meta.ContainerCounters{Counts: expected}, cc) t.Run("inhume_GC", func(t *testing.T) { var prm InhumePrm @@ -244,9 +242,13 @@ func TestCounters(t *testing.T) { require.True(t, ok) expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) - expectedLogCC[cid]-- - if expectedLogCC[cid] == 0 { - delete(expectedLogCC, cid) + if v, ok := expected[cid]; ok { + v.Logic-- + if v.IsZero() { + delete(expected, cid) + } else { + expected[cid] = v + } } } @@ -257,8 +259,7 @@ func TestCounters(t *testing.T) { cc, err := sh.metaBase.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expectedLogCC, cc.Logical) - require.Equal(t, expectedPhyCC, cc.Physical) + require.Equal(t, meta.ContainerCounters{Counts: expected}, cc) oo = oo[inhumedNumber:] }) @@ -281,9 +282,13 @@ func TestCounters(t *testing.T) { require.True(t, ok) expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) - expectedLogCC[cid]-- - if expectedLogCC[cid] == 0 { - delete(expectedLogCC, cid) + if v, ok := expected[cid]; ok { + v.Logic-- + if v.IsZero() { + delete(expected, cid) + } else { + expected[cid] = v + } } } @@ -294,8 +299,7 @@ func TestCounters(t *testing.T) { cc, err = sh.metaBase.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expectedLogCC, cc.Logical) - require.Equal(t, expectedPhyCC, cc.Physical) + require.Equal(t, meta.ContainerCounters{Counts: expected}, cc) oo = oo[inhumedNumber:] }) @@ -322,14 +326,14 @@ func TestCounters(t *testing.T) { cnr, _ := oo[i].ContainerID() expectedLogicalSizes[cnr.EncodeToString()] -= int64(removedPayload) - expectedLogCC[cnr]-- - if expectedLogCC[cnr] == 0 { - delete(expectedLogCC, cnr) - } - - expectedPhyCC[cnr]-- - if expectedPhyCC[cnr] == 0 { - delete(expectedPhyCC, cnr) + if v, ok := expected[cnr]; ok { + v.Logic-- + v.Phy-- + if v.IsZero() { + delete(expected, cnr) + } else { + expected[cnr] = v + } } } require.Equal(t, expectedLogicalSizes, mm.containerSizes()) @@ -337,8 +341,7 @@ func TestCounters(t *testing.T) { cc, err = sh.metaBase.ContainerCounters(context.Background()) require.NoError(t, err) - require.Equal(t, expectedLogCC, cc.Logical) - require.Equal(t, expectedPhyCC, cc.Physical) + require.Equal(t, meta.ContainerCounters{Counts: expected}, cc) }) } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index ff437d7ee8..853a87b9f0 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -395,6 +395,8 @@ const ( // counter type (excludes objects that are // stored but unavailable). logical = "logic" + // user is an available small or big regular object. + user = "user" ) func (s *Shard) updateMetrics(ctx context.Context) { @@ -411,8 +413,9 @@ func (s *Shard) updateMetrics(ctx context.Context) { return } - s.cfg.metricsWriter.SetObjectCounter(physical, cc.Phy()) - s.cfg.metricsWriter.SetObjectCounter(logical, cc.Logic()) + s.cfg.metricsWriter.SetObjectCounter(physical, cc.Phy) + s.cfg.metricsWriter.SetObjectCounter(logical, cc.Logic) + s.cfg.metricsWriter.SetObjectCounter(user, cc.User) cnrList, err := s.metaBase.Containers(ctx) if err != nil { @@ -441,11 +444,10 @@ func (s *Shard) updateMetrics(ctx context.Context) { s.log.Warn(logs.FailedToGetContainerCounters, zap.Error(err)) return } - for contID, count := range contCount.Physical { - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), physical, count) - } - for contID, count := range contCount.Logical { - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), logical, count) + for contID, count := range contCount.Counts { + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), physical, count.Phy) + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), logical, count.Logic) + s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), user, count.User) } } @@ -472,8 +474,9 @@ func (s *Shard) decContainerObjectCounter(byCnr map[cid.ID]meta.ObjectCounters) } for cnrID, count := range byCnr { - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy()) - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic()) + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy) + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic) + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), user, count.User) } } From d30ab5f29ea2bef513cff00af10edc915a582b9a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 5 Dec 2023 17:00:16 +0300 Subject: [PATCH 0179/1413] [#838] metabase: Count user objects Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/shards.go | 4 -- pkg/local_object_storage/metabase/counter.go | 48 +++++++++++--- .../metabase/counter_test.go | 30 +++++++++ pkg/local_object_storage/metabase/delete.go | 63 +++++++++++++++---- pkg/local_object_storage/metabase/inhume.go | 49 +++++++++------ .../metabase/iterators.go | 7 ++- pkg/local_object_storage/metabase/put.go | 2 +- pkg/local_object_storage/shard/delete.go | 1 + pkg/local_object_storage/shard/gc.go | 3 + pkg/local_object_storage/shard/inhume.go | 1 + .../shard/metrics_test.go | 19 ++++-- pkg/local_object_storage/shard/put.go | 2 +- pkg/local_object_storage/shard/shard.go | 9 +-- 13 files changed, 180 insertions(+), 58 deletions(-) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 2e1cc75151..5d7fb598e4 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -46,10 +46,6 @@ func (m *metricsWithID) IncObjectCounter(objectType string) { m.mw.AddToObjectCounter(m.id, objectType, +1) } -func (m *metricsWithID) DecObjectCounter(objectType string) { - m.mw.AddToObjectCounter(m.id, objectType, -1) -} - func (m *metricsWithID) SetMode(mode mode.Mode) { m.mw.SetMode(m.id, mode) } diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index be860830aa..96d80077d6 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" ) @@ -27,6 +28,7 @@ const ( _ objectType = iota phy logical + user ) // ObjectCounters groups object counter @@ -183,14 +185,19 @@ func (db *DB) containerCountersNextBatch(lastKey []byte, cc *ContainerCounters) return false, nil } -func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID) error { +func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID, isUserObject bool) error { if err := db.updateShardObjectCounter(tx, phy, 1, true); err != nil { return fmt.Errorf("could not increase phy object counter: %w", err) } if err := db.updateShardObjectCounter(tx, logical, 1, true); err != nil { return fmt.Errorf("could not increase logical object counter: %w", err) } - return db.incContainerObjectCounter(tx, cnrID) + if isUserObject { + if err := db.updateShardObjectCounter(tx, user, 1, true); err != nil { + return fmt.Errorf("could not increase user object counter: %w", err) + } + } + return db.incContainerObjectCounter(tx, cnrID, isUserObject) } func (db *DB) updateShardObjectCounter(tx *bbolt.Tx, typ objectType, delta uint64, inc bool) error { @@ -207,6 +214,8 @@ func (db *DB) updateShardObjectCounter(tx *bbolt.Tx, typ objectType, delta uint6 counterKey = objectPhyCounterKey case logical: counterKey = objectLogicCounterKey + case user: + counterKey = objectUserCounterKey default: panic("unknown object type counter") } @@ -230,7 +239,7 @@ func (db *DB) updateShardObjectCounter(tx *bbolt.Tx, typ objectType, delta uint6 return b.Put(counterKey, newCounter) } -func (db *DB) updateContainerCounter(tx *bbolt.Tx, delta map[cid.ID]ObjectCounters, inc bool) error { +func (db *DB) updateContainerCounter(tx *bbolt.Tx, delta map[cid.ID]ObjectCounters, inc bool) error { // TODO #838 b := tx.Bucket(containerCounterBucketName) if b == nil { return nil @@ -277,7 +286,7 @@ func nextValue(existed, delta uint64, inc bool) uint64 { return existed } -func (db *DB) incContainerObjectCounter(tx *bbolt.Tx, cnrID cid.ID) error { +func (db *DB) incContainerObjectCounter(tx *bbolt.Tx, cnrID cid.ID, isUserObject bool) error { b := tx.Bucket(containerCounterBucketName) if b == nil { return nil @@ -285,7 +294,11 @@ func (db *DB) incContainerObjectCounter(tx *bbolt.Tx, cnrID cid.ID) error { key := make([]byte, cidSize) cnrID.Encode(key) - return db.editContainerCounterValue(b, key, ObjectCounters{Logic: 1, Phy: 1}, true) + c := ObjectCounters{Logic: 1, Phy: 1} + if isUserObject { + c.User = 1 + } + return db.editContainerCounterValue(b, key, c, true) } // syncCounter updates object counters according to metabase state: @@ -319,8 +332,9 @@ func syncCounter(tx *bbolt.Tx, force bool) error { graveyardBKT := tx.Bucket(graveyardBucketName) garbageBKT := tx.Bucket(garbageBucketName) key := make([]byte, addressKeySize) + var isAvailable bool - err = iteratePhyObjects(tx, func(cnr cid.ID, obj oid.ID) error { + err = iteratePhyObjects(tx, func(cnr cid.ID, objID oid.ID, obj *objectSDK.Object) error { if v, ok := counters[cnr]; ok { v.Phy++ counters[cnr] = v @@ -331,7 +345,8 @@ func syncCounter(tx *bbolt.Tx, force bool) error { } addr.SetContainer(cnr) - addr.SetObject(obj) + addr.SetObject(objID) + isAvailable = false // check if an object is available: not with GCMark // and not covered with a tombstone @@ -344,6 +359,18 @@ func syncCounter(tx *bbolt.Tx, force bool) error { Logic: 1, } } + isAvailable = true + } + + if isAvailable && IsUserObject(obj) { + if v, ok := counters[cnr]; ok { + v.User++ + counters[cnr] = v + } else { + counters[cnr] = ObjectCounters{ + User: 1, + } + } } return nil @@ -446,3 +473,10 @@ func containerObjectCounterInitialized(tx *bbolt.Tx) bool { _, err = parseContainerCounterValue(v) return err == nil } + +func IsUserObject(obj *objectSDK.Object) bool { + _, hasParentID := obj.ParentID() + return obj.Type() == objectSDK.TypeRegular && + (obj.SplitID() == nil || + (hasParentID && len(obj.Children()) == 0)) +} diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 27d0b37ae9..9241c97a02 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -51,6 +51,7 @@ func TestCounters(t *testing.T) { exp[cnrID] = meta.ObjectCounters{ Logic: 1, Phy: 1, + User: 1, } _, err := db.Put(context.Background(), prm) @@ -80,6 +81,7 @@ func TestCounters(t *testing.T) { exp[cnrID] = meta.ObjectCounters{ Logic: 1, Phy: 1, + User: 1, } } @@ -96,11 +98,13 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(i), c.Phy) require.Equal(t, uint64(i), c.Logic) + require.Equal(t, uint64(i), c.User) cnrID, _ := oo[i].ContainerID() if v, ok := exp[cnrID]; ok { v.Phy-- v.Logic-- + v.User-- if v.IsZero() { delete(exp, cnrID) } else { @@ -125,6 +129,7 @@ func TestCounters(t *testing.T) { exp[cnrID] = meta.ObjectCounters{ Logic: 1, Phy: 1, + User: 1, } } @@ -141,6 +146,7 @@ func TestCounters(t *testing.T) { for _, addr := range inhumedObjs { if v, ok := exp[addr.Container()]; ok { v.Logic-- + v.User-- if v.IsZero() { delete(exp, addr.Container()) } else { @@ -156,12 +162,14 @@ func TestCounters(t *testing.T) { res, err := db.Inhume(context.Background(), prm) require.NoError(t, err) require.Equal(t, uint64(len(inhumedObjs)), res.AvailableInhumed()) + require.Equal(t, uint64(len(inhumedObjs)), res.UserInhumed()) c, err := db.ObjectCounters() require.NoError(t, err) require.Equal(t, uint64(objCount), c.Phy) require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic) + require.Equal(t, uint64(objCount-len(inhumedObjs)), c.User) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) @@ -182,12 +190,14 @@ func TestCounters(t *testing.T) { o := testutil.GenerateObject() if i < objCount/2 { // half of the objs will have the parent o.SetParent(parObj) + o.SetSplitID(objectSDK.NewSplitID()) } cnrID, _ := o.ContainerID() exp[cnrID] = meta.ObjectCounters{ Logic: 1, Phy: 1, + User: 1, } require.NoError(t, putBig(db, o)) @@ -196,6 +206,7 @@ func TestCounters(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(i+1), c.Phy) require.Equal(t, uint64(i+1), c.Logic) + require.Equal(t, uint64(i+1), c.User) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) @@ -214,6 +225,7 @@ func TestCounters(t *testing.T) { exp[cnrID] = meta.ObjectCounters{ Logic: 1, Phy: 1, + User: 1, } } @@ -227,10 +239,13 @@ func TestCounters(t *testing.T) { c, err := db.ObjectCounters() require.NoError(t, err) require.Equal(t, uint64(objCount-i-1), c.Phy) + require.Equal(t, uint64(objCount-i-1), c.Logic) + require.Equal(t, uint64(objCount-i-1), c.User) if v, ok := exp[addr.Container()]; ok { v.Logic-- v.Phy-- + v.User-- if v.IsZero() { delete(exp, addr.Container()) } else { @@ -251,6 +266,7 @@ func TestCounters(t *testing.T) { exp[cnrID] = meta.ObjectCounters{ Logic: 1, Phy: 1, + User: 1, } } @@ -267,6 +283,7 @@ func TestCounters(t *testing.T) { for _, addr := range inhumedObjs { if v, ok := exp[addr.Container()]; ok { v.Logic-- + v.User-- if v.IsZero() { delete(exp, addr.Container()) } else { @@ -287,6 +304,7 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(objCount), c.Phy) require.Equal(t, uint64(objCount-len(inhumedObjs)), c.Logic) + require.Equal(t, uint64(objCount-len(inhumedObjs)), c.User) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) @@ -318,6 +336,7 @@ func TestCounters_Expired(t *testing.T) { exp[addr.Container()] = meta.ObjectCounters{ Logic: 1, Phy: 1, + User: 1, } } @@ -327,6 +346,7 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(objCount), c.Phy) require.Equal(t, uint64(objCount), c.Logic) + require.Equal(t, uint64(objCount), c.User) cc, err := db.ContainerCounters(context.Background()) require.NoError(t, err) @@ -347,6 +367,7 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(objCount), c.Phy) require.Equal(t, uint64(objCount), c.Logic) + require.Equal(t, uint64(objCount), c.User) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) @@ -369,15 +390,18 @@ func TestCounters_Expired(t *testing.T) { inhumeRes, err := db.Inhume(context.Background(), inhumePrm) require.NoError(t, err) require.Equal(t, uint64(1), inhumeRes.AvailableInhumed()) + require.Equal(t, uint64(1), inhumeRes.UserInhumed()) c, err = db.ObjectCounters() require.NoError(t, err) require.Equal(t, uint64(len(oo)), c.Phy) require.Equal(t, uint64(len(oo)-1), c.Logic) + require.Equal(t, uint64(len(oo)-1), c.User) if v, ok := exp[oo[0].Container()]; ok { v.Logic-- + v.User-- if v.IsZero() { delete(exp, oo[0].Container()) } else { @@ -400,6 +424,7 @@ func TestCounters_Expired(t *testing.T) { deleteRes, err := db.Delete(context.Background(), deletePrm) require.NoError(t, err) require.Zero(t, deleteRes.AvailableObjectsRemoved()) + require.Zero(t, deleteRes.UserObjectsRemoved()) if v, ok := exp[oo[0].Container()]; ok { v.Phy-- @@ -416,6 +441,7 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(len(oo)), c.Phy) require.Equal(t, uint64(len(oo)), c.Logic) + require.Equal(t, uint64(len(oo)), c.User) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) @@ -431,10 +457,12 @@ func TestCounters_Expired(t *testing.T) { deleteRes, err = db.Delete(context.Background(), deletePrm) require.NoError(t, err) require.Equal(t, uint64(1), deleteRes.AvailableObjectsRemoved()) + require.Equal(t, uint64(1), deleteRes.UserObjectsRemoved()) if v, ok := exp[oo[0].Container()]; ok { v.Phy-- v.Logic-- + v.User-- if v.IsZero() { delete(exp, oo[0].Container()) } else { @@ -448,6 +476,7 @@ func TestCounters_Expired(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(len(oo)), c.Phy) require.Equal(t, uint64(len(oo)), c.Logic) + require.Equal(t, uint64(len(oo)), c.User) cc, err = db.ContainerCounters(context.Background()) require.NoError(t, err) @@ -465,6 +494,7 @@ func putObjs(t *testing.T, db *meta.DB, count int, withParent bool) []*objectSDK o := testutil.GenerateObject() if withParent { o.SetParent(parent) + o.SetSplitID(objectSDK.NewSplitID()) } oo = append(oo, o) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index a2100f363e..4fea4b4f22 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -29,6 +29,7 @@ type DeletePrm struct { type DeleteRes struct { rawRemoved uint64 availableRemoved uint64 + userRemoved uint64 sizes []uint64 availableSizes []uint64 removedByCnrID map[cid.ID]ObjectCounters @@ -40,6 +41,10 @@ func (d DeleteRes) AvailableObjectsRemoved() uint64 { return d.availableRemoved } +func (d DeleteRes) UserObjectsRemoved() uint64 { + return d.userRemoved +} + // RemovedByCnrID returns the number of removed objects by container ID. func (d DeleteRes) RemovedByCnrID() map[cid.ID]ObjectCounters { return d.removedByCnrID @@ -132,12 +137,12 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) currEpoch := db.epochState.CurrentEpoch() for i := range addrs { - removed, available, size, err := db.delete(tx, addrs[i], refCounter, currEpoch) + r, err := db.delete(tx, addrs[i], refCounter, currEpoch) if err != nil { return DeleteRes{}, err // maybe log and continue? } - if removed { + if r.Removed { if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { v.Phy++ res.removedByCnrID[addrs[i].Container()] = v @@ -148,10 +153,10 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) } res.rawRemoved++ - res.sizes[i] = size + res.sizes[i] = r.Size } - if available { + if r.Available { if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { v.Logic++ res.removedByCnrID[addrs[i].Container()] = v @@ -162,7 +167,20 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) } res.availableRemoved++ - res.availableSizes[i] = size + res.availableSizes[i] = r.Size + } + + if r.User { + if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { + v.User++ + res.removedByCnrID[addrs[i].Container()] = v + } else { + res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ + User: 1, + } + } + + res.userRemoved++ } } @@ -180,6 +198,13 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) } } + if res.userRemoved > 0 { + err := db.updateShardObjectCounter(tx, user, res.userRemoved, false) + if err != nil { + return DeleteRes{}, fmt.Errorf("could not decrease user object counter: %w", err) + } + } + if err := db.updateContainerCounter(tx, res.removedByCnrID, false); err != nil { return DeleteRes{}, fmt.Errorf("could not decrease container object counter: %w", err) } @@ -196,13 +221,20 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) return res, nil } +type deleteSingleResult struct { + Removed bool + Available bool + User bool + Size uint64 +} + // delete removes object indexes from the metabase. Counts the references // of the object that is being removed. // The first return value indicates if an object has been removed. (removing a // non-exist object is error-free). The second return value indicates if an // object was available before the removal (for calculating the logical object -// counter). The third return value is removed object payload size. -func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter, currEpoch uint64) (bool, bool, uint64, error) { +// counter). The third return value The fourth return value is removed object payload size. +func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter, currEpoch uint64) (deleteSingleResult, error) { key := make([]byte, addressKeySize) addrKey := addressKey(addr, key) garbageBKT := tx.Bucket(garbageBucketName) @@ -214,7 +246,7 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter if garbageBKT != nil { err := garbageBKT.Delete(addrKey) if err != nil { - return false, false, 0, fmt.Errorf("could not remove from garbage bucket: %w", err) + return deleteSingleResult{}, fmt.Errorf("could not remove from garbage bucket: %w", err) } } @@ -224,10 +256,10 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter var siErr *objectSDK.SplitInfoError if client.IsErrObjectNotFound(err) || errors.As(err, &siErr) { - return false, false, 0, nil + return deleteSingleResult{}, nil } - return false, false, 0, err + return deleteSingleResult{}, err } // if object is an only link to a parent, then remove parent @@ -250,13 +282,20 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter nRef.cur++ } + isUserObject := IsUserObject(obj) + // remove object err = db.deleteObject(tx, obj, false) if err != nil { - return false, false, 0, fmt.Errorf("could not remove object: %w", err) + return deleteSingleResult{}, fmt.Errorf("could not remove object: %w", err) } - return true, removeAvailableObject, obj.PayloadSize(), nil + return deleteSingleResult{ + Removed: true, + Available: removeAvailableObject, + User: isUserObject && removeAvailableObject, + Size: obj.PayloadSize(), + }, nil } func (db *DB) deleteObject( diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 2a9adff3a8..21db9a629f 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -30,14 +30,16 @@ type InhumePrm struct { // DeletionInfo contains details on deleted object. type DeletionInfo struct { - Size uint64 - CID cid.ID + Size uint64 + CID cid.ID + IsUser bool } // InhumeRes encapsulates results of Inhume operation. type InhumeRes struct { deletedLockObj []oid.Address availableInhumed uint64 + userInhumed uint64 inhumedByCnrID map[cid.ID]ObjectCounters deletionDetails []DeletionInfo } @@ -48,6 +50,10 @@ func (i InhumeRes) AvailableInhumed() uint64 { return i.availableInhumed } +func (i InhumeRes) UserInhumed() uint64 { + return i.userInhumed +} + // InhumedByCnrID return number of object // that have been inhumed by container ID. func (i InhumeRes) InhumedByCnrID() map[cid.ID]ObjectCounters { @@ -75,19 +81,31 @@ func (i InhumeRes) GetDeletionInfoByIndex(target int) DeletionInfo { // StoreDeletionInfo stores size of deleted object and associated container ID // in corresponding arrays. -func (i *InhumeRes) storeDeletionInfo(containerID cid.ID, deletedSize uint64) { +func (i *InhumeRes) storeDeletionInfo(containerID cid.ID, deletedSize uint64, isUser bool) { i.deletionDetails = append(i.deletionDetails, DeletionInfo{ - Size: deletedSize, - CID: containerID, + Size: deletedSize, + CID: containerID, + IsUser: isUser, }) i.availableInhumed++ + if isUser { + i.userInhumed++ + } + if v, ok := i.inhumedByCnrID[containerID]; ok { v.Logic++ + if isUser { + v.User++ + } i.inhumedByCnrID[containerID] = v } else { - i.inhumedByCnrID[containerID] = ObjectCounters{ + v = ObjectCounters{ Logic: 1, } + if isUser { + v.User = 1 + } + i.inhumedByCnrID[containerID] = v } } @@ -247,23 +265,14 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes } func (db *DB) applyInhumeResToCounters(tx *bbolt.Tx, res *InhumeRes) error { - var inhumedCount uint64 - inhumedbyCnr := make(map[cid.ID]ObjectCounters) - for _, dd := range res.deletionDetails { - if v, ok := inhumedbyCnr[dd.CID]; ok { - v.Logic++ - inhumedbyCnr[dd.CID] = v - } else { - inhumedbyCnr[dd.CID] = ObjectCounters{Logic: 1} - } - inhumedCount++ + if err := db.updateShardObjectCounter(tx, logical, res.AvailableInhumed(), false); err != nil { + return err } - - if err := db.updateShardObjectCounter(tx, logical, inhumedCount, false); err != nil { + if err := db.updateShardObjectCounter(tx, user, res.UserInhumed(), false); err != nil { return err } - return db.updateContainerCounter(tx, inhumedbyCnr, false) + return db.updateContainerCounter(tx, res.inhumedByCnrID, false) } // getInhumeTargetBucketAndValue return target bucket to store inhume result and value that will be put in the bucket. @@ -318,7 +327,7 @@ func (db *DB) markAsGC(graveyardBKT, garbageBKT *bbolt.Bucket, key []byte) (bool func (db *DB) updateDeleteInfo(tx *bbolt.Tx, garbageBKT, graveyardBKT *bbolt.Bucket, targetKey []byte, cnr cid.ID, obj *objectSDK.Object, res *InhumeRes) error { containerID, _ := obj.ContainerID() if inGraveyardWithKey(targetKey, graveyardBKT, garbageBKT) == 0 { - res.storeDeletionInfo(containerID, obj.PayloadSize()) + res.storeDeletionInfo(containerID, obj.PayloadSize(), IsUserObject(obj)) } // if object is stored, and it is regular object then update bucket diff --git a/pkg/local_object_storage/metabase/iterators.go b/pkg/local_object_storage/metabase/iterators.go index a1e21ef25b..7b60b7d50a 100644 --- a/pkg/local_object_storage/metabase/iterators.go +++ b/pkg/local_object_storage/metabase/iterators.go @@ -202,9 +202,10 @@ func (db *DB) iterateCoveredByTombstones(tx *bbolt.Tx, tss map[string]oid.Addres return err } -func iteratePhyObjects(tx *bbolt.Tx, f func(cid.ID, oid.ID) error) error { +func iteratePhyObjects(tx *bbolt.Tx, f func(cid.ID, oid.ID, *objectSDK.Object) error) error { var cid cid.ID var oid oid.ID + obj := objectSDK.New() return tx.ForEach(func(name []byte, b *bbolt.Bucket) error { b58CID, postfix := parseContainerIDWithPrefix(&cid, name) @@ -221,8 +222,8 @@ func iteratePhyObjects(tx *bbolt.Tx, f func(cid.ID, oid.ID) error) error { } return b.ForEach(func(k, v []byte) error { - if oid.Decode(k) == nil { - return f(cid, oid) + if oid.Decode(k) == nil && obj.Unmarshal(v) == nil { + return f(cid, oid, obj) } return nil diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 2b5c5421d0..2f5108953a 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -183,7 +183,7 @@ func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *o } if !isParent { - if err = db.incCounters(tx, cnr); err != nil { + if err = db.incCounters(tx, cnr, IsUserObject(obj)); err != nil { return err } } diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index 663d781adc..0856bda10b 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -118,6 +118,7 @@ func (s *Shard) deleteFromMetabase(ctx context.Context, addr oid.Address) error } s.decObjectCounterBy(physical, res.RawObjectsRemoved()) s.decObjectCounterBy(logical, res.AvailableObjectsRemoved()) + s.decObjectCounterBy(user, res.UserObjectsRemoved()) s.decContainerObjectCounter(res.RemovedByCnrID()) removedPayload := res.RemovedPhysicalObjectSizes()[0] logicalRemovedPayload := res.RemovedLogicalObjectSizes()[0] diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index e16f89457b..0f978f26e3 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -416,6 +416,7 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeRegular) s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decObjectCounterBy(user, res.UserInhumed()) s.decContainerObjectCounter(res.InhumedByCnrID()) i := 0 @@ -630,6 +631,7 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeTombstone) s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decObjectCounterBy(user, res.UserInhumed()) s.decContainerObjectCounter(res.InhumedByCnrID()) i := 0 @@ -677,6 +679,7 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeLock) s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decObjectCounterBy(user, res.UserInhumed()) s.decContainerObjectCounter(res.InhumedByCnrID()) i := 0 diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index 335df82f0e..48cfaa98ef 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -122,6 +122,7 @@ func (s *Shard) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { s.m.RUnlock() s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decObjectCounterBy(user, res.UserInhumed()) s.decContainerObjectCounter(res.InhumedByCnrID()) i := 0 diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 138009a7c0..f59565cb35 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -86,12 +86,6 @@ func (m *metricsStore) IncObjectCounter(objectType string) { m.objCounters[objectType] += 1 } -func (m *metricsStore) DecObjectCounter(objectType string) { - m.mtx.Lock() - defer m.mtx.Unlock() - m.AddToObjectCounter(objectType, -1) -} - func (m *metricsStore) SetMode(mode mode.Mode) { m.mtx.Lock() defer m.mtx.Unlock() @@ -192,6 +186,9 @@ func TestCounters(t *testing.T) { v, ok = mm.getContainerCount(contID.EncodeToString(), logical) require.Zero(t, v) require.False(t, ok) + v, ok = mm.getContainerCount(contID.EncodeToString(), user) + require.Zero(t, v) + require.False(t, ok) } }) @@ -207,6 +204,7 @@ func TestCounters(t *testing.T) { expected[cnr] = meta.ObjectCounters{ Logic: 1, Phy: 1, + User: 1, } } @@ -221,6 +219,7 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) require.Equal(t, uint64(objNumber), mm.getObjectCounter(logical)) + require.Equal(t, uint64(objNumber), mm.getObjectCounter(user)) require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) @@ -244,6 +243,7 @@ func TestCounters(t *testing.T) { if v, ok := expected[cid]; ok { v.Logic-- + v.User-- if v.IsZero() { delete(expected, cid) } else { @@ -254,6 +254,7 @@ func TestCounters(t *testing.T) { require.Equal(t, uint64(objNumber), mm.getObjectCounter(physical)) require.Equal(t, uint64(objNumber-inhumedNumber), mm.getObjectCounter(logical)) + require.Equal(t, uint64(objNumber-inhumedNumber), mm.getObjectCounter(user)) require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) @@ -270,6 +271,7 @@ func TestCounters(t *testing.T) { phy := mm.getObjectCounter(physical) logic := mm.getObjectCounter(logical) + custom := mm.getObjectCounter(user) inhumedNumber := int(phy / 4) prm.SetTarget(ts, addrFromObjs(oo[:inhumedNumber])...) @@ -284,6 +286,7 @@ func TestCounters(t *testing.T) { if v, ok := expected[cid]; ok { v.Logic-- + v.User-- if v.IsZero() { delete(expected, cid) } else { @@ -294,6 +297,7 @@ func TestCounters(t *testing.T) { require.Equal(t, phy, mm.getObjectCounter(physical)) require.Equal(t, logic-uint64(inhumedNumber), mm.getObjectCounter(logical)) + require.Equal(t, custom-uint64(inhumedNumber), mm.getObjectCounter(user)) require.Equal(t, expectedLogicalSizes, mm.containerSizes()) require.Equal(t, totalPayload, mm.payloadSize()) @@ -309,6 +313,7 @@ func TestCounters(t *testing.T) { phy := mm.getObjectCounter(physical) logic := mm.getObjectCounter(logical) + custom := mm.getObjectCounter(user) deletedNumber := int(phy / 4) prm.SetAddresses(addrFromObjs(oo[:deletedNumber])...) @@ -318,6 +323,7 @@ func TestCounters(t *testing.T) { require.Equal(t, phy-uint64(deletedNumber), mm.getObjectCounter(physical)) require.Equal(t, logic-uint64(deletedNumber), mm.getObjectCounter(logical)) + require.Equal(t, custom-uint64(deletedNumber), mm.getObjectCounter(user)) var totalRemovedpayload uint64 for i := range oo[:deletedNumber] { removedPayload := oo[i].PayloadSize() @@ -329,6 +335,7 @@ func TestCounters(t *testing.T) { if v, ok := expected[cnr]; ok { v.Logic-- v.Phy-- + v.User-- if v.IsZero() { delete(expected, cnr) } else { diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index 10983d041a..09a98260df 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -90,7 +90,7 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { return PutRes{}, fmt.Errorf("could not put object to metabase: %w", err) } - s.incObjectCounter(putPrm.Address.Container()) + s.incObjectCounter(putPrm.Address.Container(), meta.IsUserObject(prm.obj)) s.addToPayloadSize(int64(prm.obj.PayloadSize())) s.addToContainerSize(putPrm.Address.Container().EncodeToString(), int64(prm.obj.PayloadSize())) } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 853a87b9f0..2c4ce91dc8 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -72,9 +72,6 @@ type MetricsWriter interface { // IncObjectCounter must increment shard's object counter taking into account // object type. IncObjectCounter(objectType string) - // DecObjectCounter must decrement shard's object counter taking into account - // object type. - DecObjectCounter(objectType string) // SetShardID must set (update) the shard identifier that will be used in // metrics. SetShardID(id string) @@ -453,12 +450,16 @@ func (s *Shard) updateMetrics(ctx context.Context) { // incObjectCounter increment both physical and logical object // counters. -func (s *Shard) incObjectCounter(cnrID cid.ID) { +func (s *Shard) incObjectCounter(cnrID cid.ID, isUser bool) { if s.cfg.metricsWriter != nil { s.cfg.metricsWriter.IncObjectCounter(physical) s.cfg.metricsWriter.IncObjectCounter(logical) s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), physical) s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), logical) + if isUser { + s.cfg.metricsWriter.IncObjectCounter(user) + s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), user) + } } } From a478050639aac5bb144f5d41b366e26c8956e3c0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 6 Dec 2023 13:02:14 +0300 Subject: [PATCH 0180/1413] [#838] metabase: Resolve funlen linter Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete.go | 141 +++++++++++--------- 1 file changed, 76 insertions(+), 65 deletions(-) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 4fea4b4f22..6a5661ed1e 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -139,81 +139,21 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) for i := range addrs { r, err := db.delete(tx, addrs[i], refCounter, currEpoch) if err != nil { - return DeleteRes{}, err // maybe log and continue? + return DeleteRes{}, err } - if r.Removed { - if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { - v.Phy++ - res.removedByCnrID[addrs[i].Container()] = v - } else { - res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ - Phy: 1, - } - } - - res.rawRemoved++ - res.sizes[i] = r.Size - } - - if r.Available { - if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { - v.Logic++ - res.removedByCnrID[addrs[i].Container()] = v - } else { - res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ - Logic: 1, - } - } - - res.availableRemoved++ - res.availableSizes[i] = r.Size - } - - if r.User { - if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { - v.User++ - res.removedByCnrID[addrs[i].Container()] = v - } else { - res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ - User: 1, - } - } - - res.userRemoved++ - } + applyDeleteSingleResult(r, &res, addrs, i) } - if res.rawRemoved > 0 { - err := db.updateShardObjectCounter(tx, phy, res.rawRemoved, false) - if err != nil { - return DeleteRes{}, fmt.Errorf("could not decrease phy object counter: %w", err) - } - } - - if res.availableRemoved > 0 { - err := db.updateShardObjectCounter(tx, logical, res.availableRemoved, false) - if err != nil { - return DeleteRes{}, fmt.Errorf("could not decrease logical object counter: %w", err) - } - } - - if res.userRemoved > 0 { - err := db.updateShardObjectCounter(tx, user, res.userRemoved, false) - if err != nil { - return DeleteRes{}, fmt.Errorf("could not decrease user object counter: %w", err) - } - } - - if err := db.updateContainerCounter(tx, res.removedByCnrID, false); err != nil { - return DeleteRes{}, fmt.Errorf("could not decrease container object counter: %w", err) + if err := db.updateCountersDelete(tx, res); err != nil { + return DeleteRes{}, err } for _, refNum := range refCounter { if refNum.cur == refNum.all { err := db.deleteObject(tx, refNum.obj, true) if err != nil { - return DeleteRes{}, err // maybe log and continue? + return DeleteRes{}, err } } } @@ -221,6 +161,77 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) return res, nil } +func (db *DB) updateCountersDelete(tx *bbolt.Tx, res DeleteRes) error { + if res.rawRemoved > 0 { + err := db.updateShardObjectCounter(tx, phy, res.rawRemoved, false) + if err != nil { + return fmt.Errorf("could not decrease phy object counter: %w", err) + } + } + + if res.availableRemoved > 0 { + err := db.updateShardObjectCounter(tx, logical, res.availableRemoved, false) + if err != nil { + return fmt.Errorf("could not decrease logical object counter: %w", err) + } + } + + if res.userRemoved > 0 { + err := db.updateShardObjectCounter(tx, user, res.userRemoved, false) + if err != nil { + return fmt.Errorf("could not decrease user object counter: %w", err) + } + } + + if err := db.updateContainerCounter(tx, res.removedByCnrID, false); err != nil { + return fmt.Errorf("could not decrease container object counter: %w", err) + } + return nil +} + +func applyDeleteSingleResult(r deleteSingleResult, res *DeleteRes, addrs []oid.Address, i int) { + if r.Removed { + if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { + v.Phy++ + res.removedByCnrID[addrs[i].Container()] = v + } else { + res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ + Phy: 1, + } + } + + res.rawRemoved++ + res.sizes[i] = r.Size + } + + if r.Available { + if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { + v.Logic++ + res.removedByCnrID[addrs[i].Container()] = v + } else { + res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ + Logic: 1, + } + } + + res.availableRemoved++ + res.availableSizes[i] = r.Size + } + + if r.User { + if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { + v.User++ + res.removedByCnrID[addrs[i].Container()] = v + } else { + res.removedByCnrID[addrs[i].Container()] = ObjectCounters{ + User: 1, + } + } + + res.userRemoved++ + } +} + type deleteSingleResult struct { Removed bool Available bool From 44552a849b5e975dba7a0576c6ae4d39c8e962fa Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 19 Sep 2023 13:50:14 +0300 Subject: [PATCH 0181/1413] [#661] shard: Add blobstor rebuilder Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 4 + pkg/local_object_storage/blobstor/rebuild.go | 15 ++++ pkg/local_object_storage/shard/control.go | 11 +++ pkg/local_object_storage/shard/rebuilder.go | 89 ++++++++++++++++++++ pkg/local_object_storage/shard/shard.go | 2 + 5 files changed, 121 insertions(+) create mode 100644 pkg/local_object_storage/blobstor/rebuild.go create mode 100644 pkg/local_object_storage/shard/rebuilder.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index a72609b410..4b8305e411 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -519,4 +519,8 @@ const ( FailedToCountWritecacheItems = "failed to count writecache items" AttemtToCloseAlreadyClosedBlobovnicza = "attempt to close an already closed blobovnicza" FailedToGetContainerCounters = "failed to get container counters values" + FailedToRebuildBlobstore = "failed to rebuild blobstore" + BlobstoreRebuildStarted = "blobstore rebuild started" + BlobstoreRebuildCompletedSuccessfully = "blobstore rebuild completed successfully" + BlobstoreRebuildStopped = "blobstore rebuild stopped" ) diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go new file mode 100644 index 0000000000..110735fad9 --- /dev/null +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -0,0 +1,15 @@ +package blobstor + +import ( + "context" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" +) + +type StorageIDUpdate interface { + UpdateStorageID(ctx context.Context, obj *objectSDK.Object, storageID []byte) error +} + +func (b *BlobStor) Rebuild(_ context.Context, _ StorageIDUpdate) error { + return nil +} diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 257498b32c..a988683ad9 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -162,6 +162,9 @@ func (s *Shard) Init(ctx context.Context) error { s.gc.init(ctx) + s.rb = newRebuilder() + s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) + return nil } @@ -266,6 +269,9 @@ func (s *Shard) refillTombstoneObject(ctx context.Context, obj *objectSDK.Object // Close releases all Shard's components. func (s *Shard) Close() error { + if s.rb != nil { + s.rb.Stop(s.log) + } components := []interface{ Close() error }{} if s.pilorama != nil { @@ -310,6 +316,11 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { unlock := s.lockExclusive() defer unlock() + s.rb.Stop(s.log) + defer func() { + s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) + }() + ok, err := s.metaBase.Reload(c.metaOpts...) if err != nil { if errors.Is(err, meta.ErrDegradedMode) { diff --git a/pkg/local_object_storage/shard/rebuilder.go b/pkg/local_object_storage/shard/rebuilder.go new file mode 100644 index 0000000000..3e0c66abf3 --- /dev/null +++ b/pkg/local_object_storage/shard/rebuilder.go @@ -0,0 +1,89 @@ +package shard + +import ( + "context" + "errors" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" + meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "go.uber.org/zap" +) + +type rebuilder struct { + mtx *sync.Mutex + wg *sync.WaitGroup + cancel func() +} + +func newRebuilder() *rebuilder { + return &rebuilder{ + mtx: &sync.Mutex{}, + wg: &sync.WaitGroup{}, + cancel: nil, + } +} + +func (r *rebuilder) Start(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *logger.Logger) { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.start(ctx, bs, mb, log) +} + +func (r *rebuilder) start(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *logger.Logger) { + if r.cancel != nil { + r.stop(log) + } + ctx, cancel := context.WithCancel(ctx) + r.cancel = cancel + r.wg.Add(1) + go func() { + defer r.wg.Done() + + log.Info(logs.BlobstoreRebuildStarted) + if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}); err != nil { + log.Warn(logs.FailedToRebuildBlobstore, zap.Error(err)) + } else { + log.Info(logs.BlobstoreRebuildCompletedSuccessfully) + } + }() +} + +func (r *rebuilder) Stop(log *logger.Logger) { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.stop(log) +} + +func (r *rebuilder) stop(log *logger.Logger) { + if r.cancel == nil { + return + } + + r.cancel() + r.wg.Wait() + r.cancel = nil + log.Info(logs.BlobstoreRebuildStopped) +} + +var errMBIsNotAvailable = errors.New("metabase is not available") + +type mbStorageIDUpdate struct { + mb *meta.DB +} + +func (u *mbStorageIDUpdate) UpdateStorageID(ctx context.Context, obj *objectSDK.Object, storageID []byte) error { + if u.mb == nil { + return errMBIsNotAvailable + } + var prm meta.PutPrm + prm.SetObject(obj) + prm.SetStorageID(storageID) + _, err := u.mb.Put(ctx, prm) + return err +} diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 2c4ce91dc8..915feccb47 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -39,6 +39,8 @@ type Shard struct { tsSource TombstoneSource + rb *rebuilder + gcCancel atomic.Value setModeRequested atomic.Bool } From 484eb59893a09ccae0100aeb16d80e6820ae8837 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 19 Sep 2023 18:08:38 +0300 Subject: [PATCH 0182/1413] [#661] blobovniczatree: Use .db extension for db files Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-lens/internal/meta/inspect.go | 4 +- internal/logs/logs.go | 6 ++ .../blobstor/blobovniczatree/active.go | 2 +- .../blobstor/blobovniczatree/blobovnicza.go | 13 +++- .../blobstor/blobovniczatree/control.go | 47 +++++++++++++ .../blobstor/blobovniczatree/control_test.go | 69 +++++++++++++++++++ .../blobstor/blobovniczatree/delete.go | 4 +- .../blobstor/blobovniczatree/exists.go | 4 +- .../blobstor/blobovniczatree/exists_test.go | 2 +- .../blobstor/blobovniczatree/get.go | 4 +- .../blobstor/blobovniczatree/get_range.go | 4 +- .../blobovniczatree}/id.go | 6 +- .../blobstor/blobovniczatree/iterate.go | 13 +++- .../blobstor/blobovniczatree/manager.go | 2 +- .../blobstor/blobovniczatree/put.go | 4 +- 15 files changed, 160 insertions(+), 24 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/control_test.go rename pkg/local_object_storage/{blobovnicza => blobstor/blobovniczatree}/id.go (71%) diff --git a/cmd/frostfs-lens/internal/meta/inspect.go b/cmd/frostfs-lens/internal/meta/inspect.go index de0f24aeb6..9eb60f9669 100644 --- a/cmd/frostfs-lens/internal/meta/inspect.go +++ b/cmd/frostfs-lens/internal/meta/inspect.go @@ -5,7 +5,7 @@ import ( "fmt" common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -40,7 +40,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) { common.ExitOnErr(cmd, common.Errf("could not check if the obj is small: %w", err)) if id := resStorageID.StorageID(); id != nil { - cmd.Printf("Object storageID: %s\n\n", blobovnicza.NewIDFromBytes(id).String()) + cmd.Printf("Object storageID: %s\n\n", blobovniczatree.NewIDFromBytes(id).Path()) } else { cmd.Printf("Object does not contain storageID\n\n") } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 4b8305e411..0c5e162b3b 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -523,4 +523,10 @@ const ( BlobstoreRebuildStarted = "blobstore rebuild started" BlobstoreRebuildCompletedSuccessfully = "blobstore rebuild completed successfully" BlobstoreRebuildStopped = "blobstore rebuild stopped" + BlobovniczaTreeFixingFileExtensions = "fixing blobovnicza tree file extensions..." + BlobovniczaTreeFixingFileExtensionsCompletedSuccessfully = "fixing blobovnicza tree file extensions completed successfully" + BlobovniczaTreeFixingFileExtensionsFailed = "failed to fix blobovnicza tree file extensions" + BlobovniczaTreeFixingFileExtensionForFile = "fixing blobovnicza file extension..." + BlobovniczaTreeFixingFileExtensionCompletedSuccessfully = "fixing blobovnicza file extension completed successfully" + BlobovniczaTreeFixingFileExtensionFailed = "failed to fix blobovnicza file extension" ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/active.go b/pkg/local_object_storage/blobstor/blobovniczatree/active.go index def1973183..da88806460 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/active.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/active.go @@ -154,7 +154,7 @@ func (m *activeDBManager) getNextSharedDB(lvlPath string) (*sharedDB, error) { var next *sharedDB for iterCount < m.leafWidth { - path := filepath.Join(lvlPath, u64ToHexString(idx)) + path := filepath.Join(lvlPath, u64ToHexStringExt(idx)) shDB := m.dbManager.GetByPath(path) db, err := shDB.Open() // open db to hold active DB open, will be closed if db is full, after m.replace or by activeDBManager.Close() if err != nil { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index fd5155ee3e..d44049fa88 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "strconv" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" @@ -63,6 +64,10 @@ var _ common.Storage = (*Blobovniczas)(nil) var errPutFailed = errors.New("could not save the object in any blobovnicza") +const ( + dbExtension = ".db" +) + // NewBlobovniczaTree returns new instance of blobovniczas tree. func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz = new(Blobovniczas) @@ -94,14 +99,16 @@ func addressHash(addr *oid.Address, path string) uint64 { return hrw.StringHash(a + path) } -// converts uint64 to hex string. func u64ToHexString(ind uint64) string { return strconv.FormatUint(ind, 16) } -// converts uint64 hex string to uint64. +func u64ToHexStringExt(ind uint64) string { + return strconv.FormatUint(ind, 16) + dbExtension +} + func u64FromHexString(str string) uint64 { - v, err := strconv.ParseUint(str, 16, 64) + v, err := strconv.ParseUint(strings.TrimSuffix(str, dbExtension), 16, 64) if err != nil { panic(fmt.Sprintf("blobovnicza name is not an index %s", str)) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index d993767b79..75a30ad3d1 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -2,11 +2,17 @@ package blobovniczatree import ( "context" + "errors" + "os" + "path/filepath" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "go.uber.org/zap" ) +var errFailedToChangeExtensionReadOnly = errors.New("failed to change blobovnicza extension: read only mode") + // Open opens blobovnicza tree. func (b *Blobovniczas) Open(readOnly bool) error { b.readOnly = readOnly @@ -21,6 +27,13 @@ func (b *Blobovniczas) Open(readOnly bool) error { func (b *Blobovniczas) Init() error { b.log.Debug(logs.BlobovniczatreeInitializingBlobovniczas) + b.log.Debug(logs.BlobovniczaTreeFixingFileExtensions) + if err := b.addDBExtensionToDBs(b.rootPath, 0); err != nil { + b.log.Error(logs.BlobovniczaTreeFixingFileExtensionsFailed, zap.Error(err)) + return err + } + b.log.Debug(logs.BlobovniczaTreeFixingFileExtensionsCompletedSuccessfully) + if b.readOnly { b.log.Debug(logs.BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization) return nil @@ -64,3 +77,37 @@ func (b *Blobovniczas) getBlobovnicza(p string) *sharedDB { func (b *Blobovniczas) getBlobovniczaWithoutCaching(p string) *sharedDB { return b.commondbManager.GetByPath(p) } + +func (b *Blobovniczas) addDBExtensionToDBs(path string, depth uint64) error { + entries, err := os.ReadDir(path) + if os.IsNotExist(err) && depth == 0 { + return nil + } + + for _, entry := range entries { + if entry.IsDir() { + if err := b.addDBExtensionToDBs(filepath.Join(path, entry.Name()), depth+1); err != nil { + return err + } + continue + } + + if strings.HasSuffix(entry.Name(), dbExtension) { + continue + } + if b.readOnly { + return errFailedToChangeExtensionReadOnly + } + + sourcePath := filepath.Join(path, entry.Name()) + targetPath := filepath.Join(path, entry.Name()+dbExtension) + b.log.Debug(logs.BlobovniczaTreeFixingFileExtensionForFile, zap.String("source", sourcePath), zap.String("target", targetPath)) + if err := os.Rename(sourcePath, targetPath); err != nil { + b.log.Error(logs.BlobovniczaTreeFixingFileExtensionFailed, zap.String("source", sourcePath), zap.String("target", targetPath), zap.Error(err)) + return err + } + b.log.Debug(logs.BlobovniczaTreeFixingFileExtensionCompletedSuccessfully, zap.String("source", sourcePath), zap.String("target", targetPath)) + } + + return nil +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go new file mode 100644 index 0000000000..0bf304fb1f --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go @@ -0,0 +1,69 @@ +package blobovniczatree + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" + "github.com/stretchr/testify/require" +) + +func TestDBExtensionFix(t *testing.T) { + root := t.TempDir() + createTestTree(t, 0, 2, 3, root) + t.Run("adds suffix if not exists", func(t *testing.T) { + openAndCloseTestTree(t, 2, 3, root) + validateTestTree(t, root) + }) + + t.Run("not adds second suffix if exists", func(t *testing.T) { + openAndCloseTestTree(t, 2, 3, root) + validateTestTree(t, root) + }) +} + +func createTestTree(t *testing.T, currentDepth, depth, width uint64, path string) { + if currentDepth == depth { + var w uint64 + for ; w < width; w++ { + dbPath := filepath.Join(path, u64ToHexString(w)) + b := blobovnicza.New(blobovnicza.WithPath(dbPath)) + require.NoError(t, b.Open()) + require.NoError(t, b.Init()) + require.NoError(t, b.Close()) + } + return + } + + var w uint64 + for ; w < width; w++ { + createTestTree(t, currentDepth+1, depth, width, filepath.Join(path, u64ToHexString(w))) + } +} + +func openAndCloseTestTree(t *testing.T, depth, width uint64, path string) { + blz := NewBlobovniczaTree( + WithBlobovniczaShallowDepth(depth), + WithBlobovniczaShallowWidth(width), + WithRootPath(path), + ) + require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Init()) + require.NoError(t, blz.Close()) +} + +func validateTestTree(t *testing.T, path string) { + entries, err := os.ReadDir(path) + require.NoError(t, err) + + for _, entry := range entries { + if entry.IsDir() { + validateTestTree(t, filepath.Join(path, entry.Name())) + } else { + require.True(t, strings.HasSuffix(entry.Name(), dbExtension)) + require.False(t, strings.HasSuffix(strings.TrimSuffix(entry.Name(), dbExtension), dbExtension)) + } + } +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 28e3a8f36a..9008672daf 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -47,8 +47,8 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co bPrm.SetAddress(prm.Address) if prm.StorageID != nil { - id := blobovnicza.NewIDFromBytes(prm.StorageID) - shBlz := b.getBlobovnicza(id.String()) + id := NewIDFromBytes(prm.StorageID) + shBlz := b.getBlobovnicza(id.Path()) blz, err := shBlz.Open() if err != nil { return res, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index e1a6f5ed5b..514ee5f950 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -36,8 +36,8 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common defer span.End() if prm.StorageID != nil { - id := blobovnicza.NewIDFromBytes(prm.StorageID) - shBlz := b.getBlobovnicza(id.String()) + id := NewIDFromBytes(prm.StorageID) + shBlz := b.getBlobovnicza(id.Path()) blz, err := shBlz.Open() if err != nil { return common.ExistsRes{}, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index c892623434..63df97595c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -55,7 +55,7 @@ func TestExistsInvalidStorageID(t *testing.T) { // An invalid boltdb file is created so that it returns an error when opened require.NoError(t, os.MkdirAll(filepath.Join(dir, relBadFileDir), os.ModePerm)) - require.NoError(t, os.WriteFile(filepath.Join(dir, relBadFileDir, badFileName), []byte("not a boltdb file content"), 0o777)) + require.NoError(t, os.WriteFile(filepath.Join(dir, relBadFileDir, badFileName+".db"), []byte("not a boltdb file content"), 0o777)) res, err := b.Exists(context.Background(), common.ExistsPrm{Address: addr, StorageID: []byte(filepath.Join(relBadFileDir, badFileName))}) require.Error(t, err) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 49849e759e..0a1f292651 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -47,8 +47,8 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G bPrm.SetAddress(prm.Address) if prm.StorageID != nil { - id := blobovnicza.NewIDFromBytes(prm.StorageID) - shBlz := b.getBlobovnicza(id.String()) + id := NewIDFromBytes(prm.StorageID) + shBlz := b.getBlobovnicza(id.Path()) blz, err := shBlz.Open() if err != nil { return res, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 91d1e3ce00..3a8fae7589 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -46,8 +46,8 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re defer span.End() if prm.StorageID != nil { - id := blobovnicza.NewIDFromBytes(prm.StorageID) - shBlz := b.getBlobovnicza(id.String()) + id := NewIDFromBytes(prm.StorageID) + shBlz := b.getBlobovnicza(id.Path()) blz, err := shBlz.Open() if err != nil { return common.GetRangeRes{}, err diff --git a/pkg/local_object_storage/blobovnicza/id.go b/pkg/local_object_storage/blobstor/blobovniczatree/id.go similarity index 71% rename from pkg/local_object_storage/blobovnicza/id.go rename to pkg/local_object_storage/blobstor/blobovniczatree/id.go index 3d3ccf8b99..a080819bcf 100644 --- a/pkg/local_object_storage/blobovnicza/id.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/id.go @@ -1,4 +1,4 @@ -package blobovnicza +package blobovniczatree // ID represents Blobovnicza identifier. type ID []byte @@ -8,8 +8,8 @@ func NewIDFromBytes(v []byte) *ID { return (*ID)(&v) } -func (id ID) String() string { - return string(id) +func (id ID) Path() string { + return string(id) + dbExtension } func (id ID) Bytes() []byte { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index d2b285c650..a0bfc374fa 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "path/filepath" + "strings" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -54,7 +55,7 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm return prm.Handler(common.IterationElement{ Address: elem.Address(), ObjectData: data, - StorageID: []byte(p), + StorageID: []byte(strings.TrimSuffix(p, dbExtension)), }) } return nil @@ -140,10 +141,16 @@ func (b *Blobovniczas) iterateSorted(ctx context.Context, addr *oid.Address, cur return false, ctx.Err() default: } + + lastPart := u64ToHexString(indices[i]) + if isLeafLevel { + lastPart = u64ToHexStringExt(indices[i]) + } + if i == 0 { - curPath = append(curPath, u64ToHexString(indices[i])) + curPath = append(curPath, lastPart) } else { - curPath[len(curPath)-1] = u64ToHexString(indices[i]) + curPath[len(curPath)-1] = lastPart } if exec { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index d695cb199a..b89ff1de79 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -117,7 +117,7 @@ func newLevelDBManager(width uint64, options []blobovnicza.Option, rootPath stri databases: make([]*sharedDB, width), } for idx := uint64(0); idx < width; idx++ { - result.databases[idx] = newSharedDB(options, filepath.Join(rootPath, lvlPath, u64ToHexString(idx)), readOnly, metrics, openDBCounter, closedFlog, log) + result.databases[idx] = newSharedDB(options, filepath.Join(rootPath, lvlPath, u64ToHexStringExt(idx)), readOnly, metrics, openDBCounter, closedFlog, log) } return result } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 6f9c8c0de5..8c8697c204 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -70,7 +70,7 @@ func (b *Blobovniczas) Put(ctx context.Context, prm common.PutPrm) (common.PutRe type putIterator struct { B *Blobovniczas - ID *blobovnicza.ID + ID *ID AllFull bool PutPrm blobovnicza.PutPrm } @@ -113,7 +113,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) } idx := u64FromHexString(filepath.Base(active.Path())) - i.ID = blobovnicza.NewIDFromBytes([]byte(filepath.Join(lvlPath, u64ToHexString(idx)))) + i.ID = NewIDFromBytes([]byte(filepath.Join(lvlPath, u64ToHexString(idx)))) return true, nil } From c1667a11d29a844d8f3c2f34671ae855b4a67665 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 20 Sep 2023 17:46:10 +0300 Subject: [PATCH 0183/1413] [#661] blobovniczatree: Allow to change depth or width Now it is possible to change depth or with of blobovniczatree. Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/blobovnicza.go | 2 +- .../blobstor/blobovniczatree/control.go | 32 ++++- .../blobstor/blobovniczatree/control_test.go | 120 ++++++++++++++++++ .../blobstor/blobovniczatree/delete.go | 2 +- .../blobstor/blobovniczatree/exists.go | 2 +- .../blobstor/blobovniczatree/get.go | 2 +- .../blobstor/blobovniczatree/get_range.go | 2 +- .../blobstor/blobovniczatree/iterate.go | 109 +++++++++++++++- .../blobstor/blobovniczatree/iterate_test.go | 41 ++++++ .../blobstor/blobovniczatree/manager.go | 70 +++++++--- 10 files changed, 355 insertions(+), 27 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index d44049fa88..14acec60f0 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -81,7 +81,7 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz.blzLeafWidth = blz.blzShallowWidth } - blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.blzLeafWidth, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) + blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) blz.dbCache = newDBCache(blz.openedCacheSize, blz.commondbManager) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 75a30ad3d1..69f3ca97f1 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -8,6 +8,7 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "go.uber.org/zap" ) @@ -39,7 +40,36 @@ func (b *Blobovniczas) Init() error { return nil } - return b.iterateLeaves(context.TODO(), func(p string) (bool, error) { + return b.initializeDBs(context.TODO()) +} + +func (b *Blobovniczas) initializeDBs(ctx context.Context) error { + err := util.MkdirAllX(b.rootPath, b.perm) + if err != nil { + return err + } + + visited := make(map[string]struct{}) + err = b.iterateExistingDBPaths(ctx, func(p string) (bool, error) { + visited[p] = struct{}{} + shBlz := b.getBlobovniczaWithoutCaching(p) + _, err := shBlz.Open() + if err != nil { + return true, err + } + defer shBlz.Close() + + b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) + return false, nil + }) + if err != nil { + return err + } + + return b.iterateSortedLeaves(ctx, nil, func(p string) (bool, error) { + if _, found := visited[p]; found { + return false, nil + } shBlz := b.getBlobovniczaWithoutCaching(p) _, err := shBlz.Open() if err != nil { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go index 0bf304fb1f..11d4e78fe4 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go @@ -1,12 +1,16 @@ package blobovniczatree import ( + "context" "os" "path/filepath" "strings" "testing" + objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" "github.com/stretchr/testify/require" ) @@ -67,3 +71,119 @@ func validateTestTree(t *testing.T, path string) { } } } + +func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { + t.Parallel() + + rootDir := t.TempDir() + + blz := NewBlobovniczaTree( + WithBlobovniczaShallowDepth(3), + WithBlobovniczaShallowWidth(5), + WithRootPath(rootDir), + ) + + require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Init()) + + obj35 := blobstortest.NewObject(10 * 1024) + addr35 := objectCore.AddressOf(obj35) + raw, err := obj35.Marshal() + require.NoError(t, err) + + pRes35, err := blz.Put(context.Background(), common.PutPrm{ + Address: addr35, + Object: obj35, + RawData: raw, + }) + require.NoError(t, err) + + gRes, err := blz.Get(context.Background(), common.GetPrm{ + Address: addr35, + StorageID: pRes35.StorageID, + }) + require.NoError(t, err) + require.EqualValues(t, obj35, gRes.Object) + + gRes, err = blz.Get(context.Background(), common.GetPrm{ + Address: addr35, + }) + require.NoError(t, err) + require.EqualValues(t, obj35, gRes.Object) + + require.NoError(t, blz.Close()) + + // change depth and width + blz = NewBlobovniczaTree( + WithBlobovniczaShallowDepth(5), + WithBlobovniczaShallowWidth(2), + WithRootPath(rootDir), + ) + + require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Init()) + + gRes, err = blz.Get(context.Background(), common.GetPrm{ + Address: addr35, + StorageID: pRes35.StorageID, + }) + require.NoError(t, err) + require.EqualValues(t, obj35, gRes.Object) + + gRes, err = blz.Get(context.Background(), common.GetPrm{ + Address: addr35, + }) + require.NoError(t, err) + require.EqualValues(t, obj35, gRes.Object) + + obj52 := blobstortest.NewObject(10 * 1024) + addr52 := objectCore.AddressOf(obj52) + raw, err = obj52.Marshal() + require.NoError(t, err) + + pRes52, err := blz.Put(context.Background(), common.PutPrm{ + Address: addr52, + Object: obj52, + RawData: raw, + }) + require.NoError(t, err) + + require.NoError(t, blz.Close()) + + // change depth and width back + blz = NewBlobovniczaTree( + WithBlobovniczaShallowDepth(3), + WithBlobovniczaShallowWidth(5), + WithRootPath(rootDir), + ) + require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Init()) + + gRes, err = blz.Get(context.Background(), common.GetPrm{ + Address: addr35, + StorageID: pRes35.StorageID, + }) + require.NoError(t, err) + require.EqualValues(t, obj35, gRes.Object) + + gRes, err = blz.Get(context.Background(), common.GetPrm{ + Address: addr35, + }) + require.NoError(t, err) + require.EqualValues(t, obj35, gRes.Object) + + gRes, err = blz.Get(context.Background(), common.GetPrm{ + Address: addr52, + StorageID: pRes52.StorageID, + }) + require.NoError(t, err) + require.EqualValues(t, obj52, gRes.Object) + + gRes, err = blz.Get(context.Background(), common.GetPrm{ + Address: addr52, + }) + require.NoError(t, err) + require.EqualValues(t, obj52, gRes.Object) + + require.NoError(t, blz.Close()) +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 9008672daf..21c21beb4f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -63,7 +63,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co objectFound := false - err = b.iterateSortedLeaves(ctx, &prm.Address, func(p string) (bool, error) { + err = b.iterateSortedDBPaths(ctx, prm.Address, func(p string) (bool, error) { res, err = b.deleteObjectFromLevel(ctx, bPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index 514ee5f950..a64b2bbb1b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -51,7 +51,7 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common var gPrm blobovnicza.GetPrm gPrm.SetAddress(prm.Address) - err := b.iterateSortedLeaves(ctx, &prm.Address, func(p string) (bool, error) { + err := b.iterateSortedDBPaths(ctx, prm.Address, func(p string) (bool, error) { _, err := b.getObjectFromLevel(ctx, gPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 0a1f292651..08cacda8ac 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -63,7 +63,7 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G return res, err } - err = b.iterateSortedLeaves(ctx, &prm.Address, func(p string) (bool, error) { + err = b.iterateSortedDBPaths(ctx, prm.Address, func(p string) (bool, error) { res, err = b.getObjectFromLevel(ctx, bPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 3a8fae7589..d237ae439d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -64,7 +64,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re objectFound := false - err = b.iterateSortedLeaves(ctx, &prm.Address, func(p string) (bool, error) { + err = b.iterateSortedDBPaths(ctx, prm.Address, func(p string) (bool, error) { res, err = b.getRangeFromLevel(ctx, prm, p) if err != nil { outOfBounds := isErrOutOfRange(err) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index a0bfc374fa..0522f89100 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -3,6 +3,7 @@ package blobovniczatree import ( "context" "fmt" + "os" "path/filepath" "strings" "time" @@ -70,7 +71,7 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm // iterator over all Blobovniczas in unsorted order. Break on f's error return. func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors bool, f func(string, *blobovnicza.Blobovnicza) error) error { - return b.iterateLeaves(ctx, func(p string) (bool, error) { + return b.iterateExistingDBPaths(ctx, func(p string) (bool, error) { shBlz := b.getBlobovnicza(p) blz, err := shBlz.Open() if err != nil { @@ -91,7 +92,9 @@ func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors boo }) } -// iterator over the paths of Blobovniczas sorted by weight. +// iterateSortedLeaves iterates over the paths of Blobovniczas sorted by weight. +// +// Uses depth, width and leaf width for iteration. func (b *Blobovniczas) iterateSortedLeaves(ctx context.Context, addr *oid.Address, f func(string) (bool, error)) error { _, err := b.iterateSorted( ctx, @@ -169,9 +172,105 @@ func (b *Blobovniczas) iterateSorted(ctx context.Context, addr *oid.Address, cur return false, nil } -// iterator over the paths of Blobovniczas in random order. -func (b *Blobovniczas) iterateLeaves(ctx context.Context, f func(string) (bool, error)) error { - return b.iterateSortedLeaves(ctx, nil, f) +// iterateExistingDBPaths iterates over the paths of Blobovniczas without any order. +// +// Uses existed blobovnicza files for iteration. +func (b *Blobovniczas) iterateExistingDBPaths(ctx context.Context, f func(string) (bool, error)) error { + _, err := b.iterateExistingDBPathsDFS(ctx, "", f) + return err +} + +func (b *Blobovniczas) iterateExistingDBPathsDFS(ctx context.Context, path string, f func(string) (bool, error)) (bool, error) { + sysPath := filepath.Join(b.rootPath, path) + entries, err := os.ReadDir(sysPath) + if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode + return false, nil + } + if err != nil { + return false, err + } + for _, entry := range entries { + select { + case <-ctx.Done(): + return false, ctx.Err() + default: + } + if entry.IsDir() { + stop, err := b.iterateExistingDBPathsDFS(ctx, filepath.Join(path, entry.Name()), f) + if err != nil { + return false, err + } + if stop { + return true, nil + } + } else { + stop, err := f(filepath.Join(path, entry.Name())) + if err != nil { + return false, err + } + if stop { + return true, nil + } + } + } + return false, nil +} + +func (b *Blobovniczas) iterateSortedDBPaths(ctx context.Context, addr oid.Address, f func(string) (bool, error)) error { + _, err := b.iterateSordedDBPathsInternal(ctx, "", addr, f) + return err +} + +func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path string, addr oid.Address, f func(string) (bool, error)) (bool, error) { + sysPath := filepath.Join(b.rootPath, path) + entries, err := os.ReadDir(sysPath) + if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode + return false, nil + } + if err != nil { + return false, err + } + var dbIdxs []uint64 + var dirIdxs []uint64 + + for _, entry := range entries { + idx := u64FromHexString(entry.Name()) + if entry.IsDir() { + dirIdxs = append(dirIdxs, idx) + } else { + dbIdxs = append(dbIdxs, idx) + } + } + + if len(dbIdxs) > 0 { + hrw.SortSliceByValue(dbIdxs, addressHash(&addr, path)) + for _, dbIdx := range dbIdxs { + dbPath := filepath.Join(path, u64ToHexStringExt(dbIdx)) + stop, err := f(dbPath) + if err != nil { + return false, err + } + if stop { + return true, nil + } + } + } + + if len(dirIdxs) > 0 { + hrw.SortSliceByValue(dirIdxs, addressHash(&addr, path)) + for _, dirIdx := range dirIdxs { + dirPath := filepath.Join(path, u64ToHexString(dirIdx)) + stop, err := b.iterateSordedDBPathsInternal(ctx, dirPath, addr, f) + if err != nil { + return false, err + } + if stop { + return true, nil + } + } + } + + return false, nil } // makes slice of uint64 values from 0 to number-1. diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go new file mode 100644 index 0000000000..91fa27dd0f --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go @@ -0,0 +1,41 @@ +package blobovniczatree + +import ( + "context" + "testing" + + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "github.com/stretchr/testify/require" +) + +func TestIterateSortedLeavesAndDBPathsAreSame(t *testing.T) { + t.Parallel() + + blz := NewBlobovniczaTree( + WithBlobovniczaShallowDepth(3), + WithBlobovniczaShallowWidth(5), + WithRootPath(t.TempDir()), + ) + require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Init()) + defer func() { + require.NoError(t, blz.Close()) + }() + + addr := oidtest.Address() + + var leaves []string + var dbPaths []string + + blz.iterateSortedLeaves(context.Background(), &addr, func(s string) (bool, error) { + leaves = append(leaves, s) + return false, nil + }) + + blz.iterateSortedDBPaths(context.Background(), addr, func(s string) (bool, error) { + dbPaths = append(dbPaths, s) + return false, nil + }) + + require.Equal(t, leaves, dbPaths) +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index b89ff1de79..4dca13adae 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -107,25 +107,65 @@ func (b *sharedDB) Path() string { // levelDbManager stores pointers of the sharedDB's for the leaf directory of the blobovnicza tree. type levelDbManager struct { - databases []*sharedDB + dbMtx *sync.RWMutex + databases map[uint64]*sharedDB + + options []blobovnicza.Option + path string + readOnly bool + metrics blobovnicza.Metrics + openDBCounter *openDBCounter + closedFlag *atomic.Bool + log *logger.Logger } -func newLevelDBManager(width uint64, options []blobovnicza.Option, rootPath string, lvlPath string, - readOnly bool, metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlog *atomic.Bool, log *logger.Logger, +func newLevelDBManager(options []blobovnicza.Option, rootPath string, lvlPath string, + readOnly bool, metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlag *atomic.Bool, log *logger.Logger, ) *levelDbManager { result := &levelDbManager{ - databases: make([]*sharedDB, width), - } - for idx := uint64(0); idx < width; idx++ { - result.databases[idx] = newSharedDB(options, filepath.Join(rootPath, lvlPath, u64ToHexStringExt(idx)), readOnly, metrics, openDBCounter, closedFlog, log) + databases: make(map[uint64]*sharedDB), + dbMtx: &sync.RWMutex{}, + + options: options, + path: filepath.Join(rootPath, lvlPath), + readOnly: readOnly, + metrics: metrics, + openDBCounter: openDBCounter, + closedFlag: closedFlag, + log: log, } return result } func (m *levelDbManager) GetByIndex(idx uint64) *sharedDB { + res := m.getDBIfExists(idx) + if res != nil { + return res + } + return m.getOrCreateDB(idx) +} + +func (m *levelDbManager) getDBIfExists(idx uint64) *sharedDB { + m.dbMtx.RLock() + defer m.dbMtx.RUnlock() + return m.databases[idx] } +func (m *levelDbManager) getOrCreateDB(idx uint64) *sharedDB { + m.dbMtx.Lock() + defer m.dbMtx.Unlock() + + db := m.databases[idx] + if db != nil { + return db + } + + db = newSharedDB(m.options, filepath.Join(m.path, u64ToHexStringExt(idx)), m.readOnly, m.metrics, m.openDBCounter, m.closedFlag, m.log) + m.databases[idx] = db + return db +} + // dbManager manages the opening and closing of blobovnicza instances. // // The blobovnicza opens at the first request, closes after the last request. @@ -135,21 +175,19 @@ type dbManager struct { closedFlag *atomic.Bool dbCounter *openDBCounter - rootPath string - options []blobovnicza.Option - readOnly bool - metrics blobovnicza.Metrics - leafWidth uint64 - log *logger.Logger + rootPath string + options []blobovnicza.Option + readOnly bool + metrics blobovnicza.Metrics + log *logger.Logger } -func newDBManager(rootPath string, options []blobovnicza.Option, leafWidth uint64, readOnly bool, metrics blobovnicza.Metrics, log *logger.Logger) *dbManager { +func newDBManager(rootPath string, options []blobovnicza.Option, readOnly bool, metrics blobovnicza.Metrics, log *logger.Logger) *dbManager { return &dbManager{ rootPath: rootPath, options: options, readOnly: readOnly, metrics: metrics, - leafWidth: leafWidth, levelToManager: make(map[string]*levelDbManager), levelToManagerGuard: &sync.RWMutex{}, log: log, @@ -197,7 +235,7 @@ func (m *dbManager) getOrCreateLevelManager(lvlPath string) *levelDbManager { return result } - result := newLevelDBManager(m.leafWidth, m.options, m.rootPath, lvlPath, m.readOnly, m.metrics, m.dbCounter, m.closedFlag, m.log) + result := newLevelDBManager(m.options, m.rootPath, lvlPath, m.readOnly, m.metrics, m.dbCounter, m.closedFlag, m.log) m.levelToManager[lvlPath] = result return result } From a531eaf8bc246ee77780ac7accee241d265fc14b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 21 Sep 2023 18:18:20 +0300 Subject: [PATCH 0184/1413] [#661] blobstor: Add Rebuild implementation Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 2 ++ .../blobstor/blobovniczatree/rebuild.go | 11 ++++++++ .../blobstor/common/rebuild.go | 20 +++++++++++++ .../blobstor/common/storage.go | 1 + .../blobstor/fstree/fstree.go | 4 +++ .../blobstor/memstore/memstore.go | 4 +++ pkg/local_object_storage/blobstor/rebuild.go | 28 +++++++++++++++++-- .../blobstor/teststore/teststore.go | 4 +++ 8 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go create mode 100644 pkg/local_object_storage/blobstor/common/rebuild.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 0c5e162b3b..c1afdadf7a 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -529,4 +529,6 @@ const ( BlobovniczaTreeFixingFileExtensionForFile = "fixing blobovnicza file extension..." BlobovniczaTreeFixingFileExtensionCompletedSuccessfully = "fixing blobovnicza file extension completed successfully" BlobovniczaTreeFixingFileExtensionFailed = "failed to fix blobovnicza file extension" + BlobstorRebuildFailedToRebuildStorages = "failed to rebuild storages" + BlobstorRebuildRebuildStoragesCompleted = "storages rebuild completed" ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go new file mode 100644 index 0000000000..27c645abb7 --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -0,0 +1,11 @@ +package blobovniczatree + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" +) + +func (b *Blobovniczas) Rebuild(_ context.Context, _ common.RebuildPrm) (common.RebuildRes, error) { + return common.RebuildRes{}, nil +} diff --git a/pkg/local_object_storage/blobstor/common/rebuild.go b/pkg/local_object_storage/blobstor/common/rebuild.go new file mode 100644 index 0000000000..1cbc2cbd78 --- /dev/null +++ b/pkg/local_object_storage/blobstor/common/rebuild.go @@ -0,0 +1,20 @@ +package common + +import ( + "context" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" +) + +type RebuildRes struct { + ObjectsMoved uint64 + FilesRemoved uint64 +} + +type RebuildPrm struct { + MetaStorage MetaStorage +} + +type MetaStorage interface { + UpdateStorageID(ctx context.Context, obj *objectSDK.Object, storageID []byte) error +} diff --git a/pkg/local_object_storage/blobstor/common/storage.go b/pkg/local_object_storage/blobstor/common/storage.go index 852f020ccb..e552fafea0 100644 --- a/pkg/local_object_storage/blobstor/common/storage.go +++ b/pkg/local_object_storage/blobstor/common/storage.go @@ -30,4 +30,5 @@ type Storage interface { Put(context.Context, PutPrm) (PutRes, error) Delete(context.Context, DeletePrm) (DeleteRes, error) Iterate(context.Context, IteratePrm) (IterateRes, error) + Rebuild(context.Context, RebuildPrm) (RebuildRes, error) } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index d1fe85901e..948872fd2d 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -574,3 +574,7 @@ func (t *FSTree) SetReportErrorFunc(_ func(string, error)) { func (t *FSTree) SetParentID(parentID string) { t.metrics.SetParentID(parentID) } + +func (t *FSTree) Rebuild(_ context.Context, _ common.RebuildPrm) (common.RebuildRes, error) { + return common.RebuildRes{}, nil +} diff --git a/pkg/local_object_storage/blobstor/memstore/memstore.go b/pkg/local_object_storage/blobstor/memstore/memstore.go index cc4f6921a2..39bed00bf2 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore.go @@ -159,3 +159,7 @@ func (s *memstoreImpl) Iterate(_ context.Context, req common.IteratePrm) (common } return common.IterateRes{}, nil } + +func (s *memstoreImpl) Rebuild(_ context.Context, _ common.RebuildPrm) (common.RebuildRes, error) { + return common.RebuildRes{}, nil +} diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go index 110735fad9..29396da7bf 100644 --- a/pkg/local_object_storage/blobstor/rebuild.go +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -3,13 +3,37 @@ package blobstor import ( "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "go.uber.org/zap" ) type StorageIDUpdate interface { UpdateStorageID(ctx context.Context, obj *objectSDK.Object, storageID []byte) error } -func (b *BlobStor) Rebuild(_ context.Context, _ StorageIDUpdate) error { - return nil +func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate) error { + var summary common.RebuildRes + var rErr error + for _, storage := range b.storage { + res, err := storage.Storage.Rebuild(ctx, common.RebuildPrm{ + MetaStorage: upd, + }) + summary.FilesRemoved += res.FilesRemoved + summary.ObjectsMoved += res.ObjectsMoved + if err != nil { + b.log.Error(logs.BlobstorRebuildFailedToRebuildStorages, + zap.String("failed_storage_path", storage.Storage.Path()), + zap.String("failed_storage_type", storage.Storage.Type()), + zap.Error(err)) + rErr = err + break + } + } + b.log.Info(logs.BlobstorRebuildRebuildStoragesCompleted, + zap.Bool("success", rErr == nil), + zap.Uint64("total_files_removed", summary.FilesRemoved), + zap.Uint64("total_objects_moved", summary.ObjectsMoved)) + return rErr } diff --git a/pkg/local_object_storage/blobstor/teststore/teststore.go b/pkg/local_object_storage/blobstor/teststore/teststore.go index 3e5b212516..c0cdfacf8a 100644 --- a/pkg/local_object_storage/blobstor/teststore/teststore.go +++ b/pkg/local_object_storage/blobstor/teststore/teststore.go @@ -229,3 +229,7 @@ func (s *TestStore) Iterate(ctx context.Context, req common.IteratePrm) (common. } func (s *TestStore) SetParentID(string) {} + +func (s *TestStore) Rebuild(_ context.Context, _ common.RebuildPrm) (common.RebuildRes, error) { + return common.RebuildRes{}, nil +} From 422226da183d762ae86b285a6ad9ab3825a92d83 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 22 Sep 2023 13:07:32 +0300 Subject: [PATCH 0185/1413] [#661] blobovniczatree: Add Rebuild implementation Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 6 + .../blobstor/blobovniczatree/active.go | 6 +- .../blobstor/blobovniczatree/blobovnicza.go | 5 + .../blobstor/blobovniczatree/cache.go | 29 +++- .../blobstor/blobovniczatree/delete.go | 6 + .../blobstor/blobovniczatree/iterate.go | 10 ++ .../blobstor/blobovniczatree/manager.go | 69 +++++++- .../blobstor/blobovniczatree/option.go | 36 ++-- .../blobstor/blobovniczatree/put.go | 4 +- .../blobstor/blobovniczatree/rebuild.go | 154 +++++++++++++++++- .../blobstor/blobovniczatree/rebuild_test.go | 132 +++++++++++++++ .../blobstor/common/rebuild.go | 4 +- pkg/local_object_storage/blobstor/rebuild.go | 4 +- pkg/local_object_storage/shard/rebuilder.go | 17 +- 14 files changed, 443 insertions(+), 39 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index c1afdadf7a..6a46672096 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -531,4 +531,10 @@ const ( BlobovniczaTreeFixingFileExtensionFailed = "failed to fix blobovnicza file extension" BlobstorRebuildFailedToRebuildStorages = "failed to rebuild storages" BlobstorRebuildRebuildStoragesCompleted = "storages rebuild completed" + BlobovniczaTreeCollectingDBToRebuild = "collecting blobovniczas to rebuild..." + BlobovniczaTreeCollectingDBToRebuildFailed = "collecting blobovniczas to rebuild failed" + BlobovniczaTreeCollectingDBToRebuildSuccess = "collecting blobovniczas to rebuild completed successfully" + BlobovniczaTreeRebuildingBlobovnicza = "rebuilding blobovnicza..." + BlobovniczaTreeRebuildingBlobovniczaFailed = "rebuilding blobovnicza failed" + BlobovniczaTreeRebuildingBlobovniczaSuccess = "rebuilding blobovnicza completed successfully" ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/active.go b/pkg/local_object_storage/blobstor/blobovniczatree/active.go index da88806460..0e3497383e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/active.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/active.go @@ -21,8 +21,8 @@ func (db *activeDB) Close() { db.shDB.Close() } -func (db *activeDB) Path() string { - return db.shDB.Path() +func (db *activeDB) SystemPath() string { + return db.shDB.SystemPath() } // activeDBManager manages active blobovnicza instances (that is, those that are being used for Put). @@ -192,7 +192,7 @@ func (m *activeDBManager) hasActiveDB(lvlPath string) (bool, uint64) { if !ok { return false, 0 } - return true, u64FromHexString(filepath.Base(db.Path())) + return true, u64FromHexString(filepath.Base(db.SystemPath())) } func (m *activeDBManager) replace(lvlPath string, shDB *sharedDB) (*sharedDB, bool) { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 14acec60f0..0354fa2acc 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" "strings" + "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" @@ -58,6 +59,8 @@ type Blobovniczas struct { commondbManager *dbManager activeDBManager *activeDBManager dbCache *dbCache + dbFilesGuard *sync.RWMutex + rebuildGuard *sync.RWMutex } var _ common.Storage = (*Blobovniczas)(nil) @@ -84,6 +87,8 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) blz.dbCache = newDBCache(blz.openedCacheSize, blz.commondbManager) + blz.dbFilesGuard = &sync.RWMutex{} + blz.rebuildGuard = &sync.RWMutex{} return blz } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index 3f62c49fa6..317bac5ffe 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -15,8 +15,9 @@ import ( type dbCache struct { cacheGuard *sync.RWMutex cache simplelru.LRUCache[string, *sharedDB] - pathLock *utilSync.KeyLocker[string] + pathLock *utilSync.KeyLocker[string] // the order of locks is important: pathLock first, cacheGuard second closed bool + nonCached map[string]struct{} dbManager *dbManager } @@ -34,6 +35,7 @@ func newDBCache(size int, dbManager *dbManager) *dbCache { cache: cache, dbManager: dbManager, pathLock: utilSync.NewKeyLocker[string](), + nonCached: make(map[string]struct{}), } } @@ -59,6 +61,27 @@ func (c *dbCache) GetOrCreate(path string) *sharedDB { return c.create(path) } +func (c *dbCache) EvictAndMarkNonCached(path string) { + c.pathLock.Lock(path) + defer c.pathLock.Unlock(path) + + c.cacheGuard.Lock() + defer c.cacheGuard.Unlock() + + c.cache.Remove(path) + c.nonCached[path] = struct{}{} +} + +func (c *dbCache) RemoveFromNonCached(path string) { + c.pathLock.Lock(path) + defer c.pathLock.Unlock(path) + + c.cacheGuard.Lock() + defer c.cacheGuard.Unlock() + + delete(c.nonCached, path) +} + func (c *dbCache) getExisted(path string) *sharedDB { c.cacheGuard.Lock() defer c.cacheGuard.Unlock() @@ -94,7 +117,9 @@ func (c *dbCache) put(path string, db *sharedDB) bool { c.cacheGuard.Lock() defer c.cacheGuard.Unlock() - if !c.closed { + _, isNonCached := c.nonCached[path] + + if !isNonCached && !c.closed { c.cache.Add(path, db) return true } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 21c21beb4f..56803c8728 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -43,6 +43,12 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co return common.DeleteRes{}, common.ErrReadOnly } + if b.rebuildGuard.TryRLock() { + defer b.rebuildGuard.RUnlock() + } else { + return common.DeleteRes{}, errRebuildInProgress + } + var bPrm blobovnicza.DeletePrm bPrm.SetAddress(prm.Address) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 0522f89100..7367879521 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -181,6 +181,11 @@ func (b *Blobovniczas) iterateExistingDBPaths(ctx context.Context, f func(string } func (b *Blobovniczas) iterateExistingDBPathsDFS(ctx context.Context, path string, f func(string) (bool, error)) (bool, error) { + if path == "" { + b.dbFilesGuard.RLock() + defer b.dbFilesGuard.RUnlock() + } + sysPath := filepath.Join(b.rootPath, path) entries, err := os.ReadDir(sysPath) if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode @@ -222,6 +227,11 @@ func (b *Blobovniczas) iterateSortedDBPaths(ctx context.Context, addr oid.Addres } func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path string, addr oid.Address, f func(string) (bool, error)) (bool, error) { + if path == "" { + b.dbFilesGuard.RLock() + defer b.dbFilesGuard.RUnlock() + } + sysPath := filepath.Join(b.rootPath, path) entries, err := os.ReadDir(sysPath) if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index 4dca13adae..4fdde15a92 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -1,7 +1,9 @@ package blobovniczatree import ( + "errors" "fmt" + "os" "path/filepath" "sync" "sync/atomic" @@ -12,9 +14,11 @@ import ( "go.uber.org/zap" ) +var errClosingClosedBlobovnicza = errors.New("closing closed blobovnicza is not allowed") + // sharedDB is responsible for opening and closing a file of single blobovnicza. type sharedDB struct { - guard *sync.RWMutex + cond *sync.Cond blcza *blobovnicza.Blobovnicza refCount uint32 @@ -31,8 +35,9 @@ func newSharedDB(options []blobovnicza.Option, path string, readOnly bool, metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlag *atomic.Bool, log *logger.Logger, ) *sharedDB { return &sharedDB{ - guard: &sync.RWMutex{}, - + cond: &sync.Cond{ + L: &sync.RWMutex{}, + }, options: options, path: path, readOnly: readOnly, @@ -48,8 +53,8 @@ func (b *sharedDB) Open() (*blobovnicza.Blobovnicza, error) { return nil, errClosed } - b.guard.Lock() - defer b.guard.Unlock() + b.cond.L.Lock() + defer b.cond.L.Unlock() if b.refCount > 0 { b.refCount++ @@ -77,11 +82,12 @@ func (b *sharedDB) Open() (*blobovnicza.Blobovnicza, error) { } func (b *sharedDB) Close() { - b.guard.Lock() - defer b.guard.Unlock() + b.cond.L.Lock() + defer b.cond.L.Unlock() if b.refCount == 0 { b.log.Error(logs.AttemtToCloseAlreadyClosedBlobovnicza, zap.String("id", b.path)) + b.cond.Broadcast() return } @@ -99,9 +105,38 @@ func (b *sharedDB) Close() { } b.refCount-- + if b.refCount == 1 { + b.cond.Broadcast() + } } -func (b *sharedDB) Path() string { +func (b *sharedDB) CloseAndRemoveFile() error { + b.cond.L.Lock() + if b.refCount > 1 { + b.cond.Wait() + } + defer b.cond.L.Unlock() + + if b.refCount == 0 { + return errClosingClosedBlobovnicza + } + + if err := b.blcza.Close(); err != nil { + b.log.Error(logs.BlobovniczatreeCouldNotCloseBlobovnicza, + zap.String("id", b.path), + zap.String("error", err.Error()), + ) + return fmt.Errorf("failed to close blobovnicza (path = %s): %w", b.path, err) + } + + b.refCount = 0 + b.blcza = nil + b.openDBCounter.Dec() + + return os.Remove(b.path) +} + +func (b *sharedDB) SystemPath() string { return b.path } @@ -166,6 +201,13 @@ func (m *levelDbManager) getOrCreateDB(idx uint64) *sharedDB { return db } +func (m *levelDbManager) hasAnyDB() bool { + m.dbMtx.RLock() + defer m.dbMtx.RUnlock() + + return len(m.databases) > 0 +} + // dbManager manages the opening and closing of blobovnicza instances. // // The blobovnicza opens at the first request, closes after the last request. @@ -203,6 +245,17 @@ func (m *dbManager) GetByPath(path string) *sharedDB { return levelManager.GetByIndex(curIndex) } +func (m *dbManager) CleanResources(path string) { + lvlPath := filepath.Dir(path) + + m.levelToManagerGuard.Lock() + defer m.levelToManagerGuard.Unlock() + + if result, ok := m.levelToManager[lvlPath]; ok && !result.hasAnyDB() { + delete(m.levelToManager, lvlPath) + } +} + func (m *dbManager) Open() { m.closedFlag.Store(false) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index 561b837618..54c5211860 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -2,6 +2,7 @@ package blobovniczatree import ( "io/fs" + "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" @@ -21,28 +22,31 @@ type cfg struct { compression *compression.Config blzOpts []blobovnicza.Option // reportError is the function called when encountering disk errors. - reportError func(string, error) - metrics Metrics + reportError func(string, error) + metrics Metrics + waitBeforeDropDB time.Duration } type Option func(*cfg) const ( - defaultPerm = 0o700 - defaultOpenedCacheSize = 50 - defaultBlzShallowDepth = 2 - defaultBlzShallowWidth = 16 + defaultPerm = 0o700 + defaultOpenedCacheSize = 50 + defaultBlzShallowDepth = 2 + defaultBlzShallowWidth = 16 + defaultWaitBeforeDropDB = 10 * time.Second ) func initConfig(c *cfg) { *c = cfg{ - log: &logger.Logger{Logger: zap.L()}, - perm: defaultPerm, - openedCacheSize: defaultOpenedCacheSize, - blzShallowDepth: defaultBlzShallowDepth, - blzShallowWidth: defaultBlzShallowWidth, - reportError: func(string, error) {}, - metrics: &noopMetrics{}, + log: &logger.Logger{Logger: zap.L()}, + perm: defaultPerm, + openedCacheSize: defaultOpenedCacheSize, + blzShallowDepth: defaultBlzShallowDepth, + blzShallowWidth: defaultBlzShallowWidth, + reportError: func(string, error) {}, + metrics: &noopMetrics{}, + waitBeforeDropDB: defaultWaitBeforeDropDB, } } @@ -106,3 +110,9 @@ func WithMetrics(m Metrics) Option { c.metrics = m } } + +func WithWaitBeforeDropDB(t time.Duration) Option { + return func(c *cfg) { + c.waitBeforeDropDB = t + } +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 8c8697c204..96c4db67d3 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -104,7 +104,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) i.B.reportError(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) } else { i.B.log.Debug(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, - zap.String("path", active.Path()), + zap.String("path", active.SystemPath()), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } @@ -112,7 +112,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) return false, nil } - idx := u64FromHexString(filepath.Base(active.Path())) + idx := u64FromHexString(filepath.Base(active.SystemPath())) i.ID = NewIDFromBytes([]byte(filepath.Join(lvlPath, u64ToHexString(idx)))) return true, nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 27c645abb7..35e001b632 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -2,10 +2,160 @@ package blobovniczatree import ( "context" + "errors" + "os" + "path/filepath" + "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.uber.org/zap" ) -func (b *Blobovniczas) Rebuild(_ context.Context, _ common.RebuildPrm) (common.RebuildRes, error) { - return common.RebuildRes{}, nil +var errRebuildInProgress = errors.New("rebuild is in progress, the operation cannot be performed") + +func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (common.RebuildRes, error) { + if b.readOnly { + return common.RebuildRes{}, common.ErrReadOnly + } + + b.rebuildGuard.Lock() + defer b.rebuildGuard.Unlock() + + b.log.Debug(logs.BlobovniczaTreeCollectingDBToRebuild) + var res common.RebuildRes + dbsToMigrate, err := b.getDBsToRebuild(ctx) + if err != nil { + b.log.Warn(logs.BlobovniczaTreeCollectingDBToRebuildFailed, zap.Error(err)) + return res, err + } + b.log.Info(logs.BlobovniczaTreeCollectingDBToRebuildSuccess, zap.Int("blobovniczas_to_rebuild", len(dbsToMigrate))) + for _, db := range dbsToMigrate { + b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) + movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage) + res.ObjectsMoved += movedObjects + if err != nil { + b.log.Warn(logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) + return res, err + } + b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) + res.FilesRemoved++ + } + + return res, nil +} + +func (b *Blobovniczas) getDBsToRebuild(ctx context.Context) ([]string, error) { + dbsToMigrate := make(map[string]struct{}) + if err := b.iterateExistingDBPaths(ctx, func(s string) (bool, error) { + dbsToMigrate[s] = struct{}{} + return false, nil + }); err != nil { + return nil, err + } + if err := b.iterateSortedLeaves(ctx, nil, func(s string) (bool, error) { + delete(dbsToMigrate, s) + return false, nil + }); err != nil { + return nil, err + } + result := make([]string, 0, len(dbsToMigrate)) + for db := range dbsToMigrate { + result = append(result, db) + } + return result, nil +} + +func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage) (uint64, error) { + shDB := b.getBlobovnicza(path) + blz, err := shDB.Open() + if err != nil { + return 0, err + } + shDBClosed := false + defer func() { + if shDBClosed { + return + } + shDB.Close() + }() + + migratedObjects, err := b.moveObjects(ctx, blz, meta) + if err != nil { + return migratedObjects, err + } + shDBClosed, err = b.dropDB(ctx, path, shDB) + return migratedObjects, err +} + +func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, meta common.MetaStorage) (uint64, error) { + var result uint64 + + var prm blobovnicza.IteratePrm + prm.DecodeAddresses() + prm.SetHandler(func(ie blobovnicza.IterationElement) error { + e := b.moveObject(ctx, ie.Address(), ie.ObjectData(), meta) + if e == nil { + result++ + } + return e + }) + + _, err := blz.Iterate(ctx, prm) + return result, err +} + +func (b *Blobovniczas) moveObject(ctx context.Context, addr oid.Address, data []byte, metaStore common.MetaStorage) error { + var pPrm common.PutPrm + pPrm.Address = addr + pPrm.RawData = data + pRes, err := b.Put(ctx, pPrm) + if err != nil { + return err + } + return metaStore.UpdateStorageID(ctx, addr, pRes.StorageID) +} + +func (b *Blobovniczas) dropDB(ctx context.Context, path string, shDb *sharedDB) (bool, error) { + select { + case <-ctx.Done(): + return false, ctx.Err() + case <-time.After(b.waitBeforeDropDB): // to complete requests with old storage ID + } + + b.dbCache.EvictAndMarkNonCached(path) + defer b.dbCache.RemoveFromNonCached(path) + + b.dbFilesGuard.Lock() + defer b.dbFilesGuard.Unlock() + + if err := shDb.CloseAndRemoveFile(); err != nil { + return false, err + } + b.commondbManager.CleanResources(path) + if err := b.dropDirectoryIfEmpty(filepath.Dir(path)); err != nil { + return true, err + } + return true, nil +} + +func (b *Blobovniczas) dropDirectoryIfEmpty(path string) error { + if path == "." { + return nil + } + + sysPath := filepath.Join(b.rootPath, path) + entries, err := os.ReadDir(sysPath) + if err != nil { + return err + } + if len(entries) > 0 { + return nil + } + if err := os.Remove(sysPath); err != nil { + return err + } + return b.dropDirectoryIfEmpty(filepath.Dir(path)) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go new file mode 100644 index 0000000000..00b38f69ab --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -0,0 +1,132 @@ +package blobovniczatree + +import ( + "context" + "sync" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" +) + +func TestBlobovniczaTreeRebuild(t *testing.T) { + t.Parallel() + + t.Run("width increased", func(t *testing.T) { + t.Parallel() + testBlobovniczaTreeRebuildHelper(t, 2, 2, 2, 3, false) + }) + + t.Run("width reduced", func(t *testing.T) { + t.Parallel() + testBlobovniczaTreeRebuildHelper(t, 2, 2, 2, 1, true) + }) + + t.Run("depth increased", func(t *testing.T) { + t.Parallel() + testBlobovniczaTreeRebuildHelper(t, 1, 2, 2, 2, true) + }) + + t.Run("depth reduced", func(t *testing.T) { + t.Parallel() + testBlobovniczaTreeRebuildHelper(t, 2, 2, 1, 2, true) + }) +} + +func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, targetDepth, targetWidth uint64, shouldMigrate bool) { + dir := t.TempDir() + b := NewBlobovniczaTree( + WithLogger(test.NewLogger(t, true)), + WithObjectSizeLimit(2048), + WithBlobovniczaShallowWidth(sourceWidth), + WithBlobovniczaShallowDepth(sourceDepth), + WithRootPath(dir), + WithBlobovniczaSize(100*1024*1024), + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000)) + require.NoError(t, b.Open(false)) + require.NoError(t, b.Init()) + + eg, egCtx := errgroup.WithContext(context.Background()) + storageIDs := make(map[oid.Address][]byte) + storageIDsGuard := &sync.Mutex{} + for i := 0; i < 1000; i++ { + eg.Go(func() error { + obj := blobstortest.NewObject(1024) + data, err := obj.Marshal() + if err != nil { + return err + } + var prm common.PutPrm + prm.Address = object.AddressOf(obj) + prm.RawData = data + res, err := b.Put(egCtx, prm) + if err != nil { + return err + } + storageIDsGuard.Lock() + storageIDs[prm.Address] = res.StorageID + storageIDsGuard.Unlock() + return nil + }) + } + + require.NoError(t, eg.Wait()) + require.NoError(t, b.Close()) + + b = NewBlobovniczaTree( + WithLogger(test.NewLogger(t, true)), + WithObjectSizeLimit(2048), + WithBlobovniczaShallowWidth(targetWidth), + WithBlobovniczaShallowDepth(targetDepth), + WithRootPath(dir), + WithBlobovniczaSize(100*1024*1024), + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000)) + require.NoError(t, b.Open(false)) + require.NoError(t, b.Init()) + + for addr, storageID := range storageIDs { + var gPrm common.GetPrm + gPrm.Address = addr + gPrm.StorageID = storageID + _, err := b.Get(context.Background(), gPrm) + require.NoError(t, err) + } + + metaStub := &storageIDUpdateStub{ + storageIDs: storageIDs, + } + var rPrm common.RebuildPrm + rPrm.MetaStorage = metaStub + rRes, err := b.Rebuild(context.Background(), rPrm) + require.NoError(t, err) + dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 + require.Equal(t, shouldMigrate, dataMigrated) + + for addr, storageID := range storageIDs { + var gPrm common.GetPrm + gPrm.Address = addr + gPrm.StorageID = storageID + _, err := b.Get(context.Background(), gPrm) + require.NoError(t, err) + } + + require.NoError(t, b.Close()) +} + +type storageIDUpdateStub struct { + storageIDs map[oid.Address][]byte + updatedCount uint64 +} + +func (s *storageIDUpdateStub) UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error { + s.storageIDs[addr] = storageID + s.updatedCount++ + return nil +} diff --git a/pkg/local_object_storage/blobstor/common/rebuild.go b/pkg/local_object_storage/blobstor/common/rebuild.go index 1cbc2cbd78..896ecbb339 100644 --- a/pkg/local_object_storage/blobstor/common/rebuild.go +++ b/pkg/local_object_storage/blobstor/common/rebuild.go @@ -3,7 +3,7 @@ package common import ( "context" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) type RebuildRes struct { @@ -16,5 +16,5 @@ type RebuildPrm struct { } type MetaStorage interface { - UpdateStorageID(ctx context.Context, obj *objectSDK.Object, storageID []byte) error + UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error } diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go index 29396da7bf..882381dcff 100644 --- a/pkg/local_object_storage/blobstor/rebuild.go +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -5,12 +5,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) type StorageIDUpdate interface { - UpdateStorageID(ctx context.Context, obj *objectSDK.Object, storageID []byte) error + UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error } func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate) error { diff --git a/pkg/local_object_storage/shard/rebuilder.go b/pkg/local_object_storage/shard/rebuilder.go index 3e0c66abf3..a636fceb01 100644 --- a/pkg/local_object_storage/shard/rebuilder.go +++ b/pkg/local_object_storage/shard/rebuilder.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) @@ -77,13 +77,20 @@ type mbStorageIDUpdate struct { mb *meta.DB } -func (u *mbStorageIDUpdate) UpdateStorageID(ctx context.Context, obj *objectSDK.Object, storageID []byte) error { +func (u *mbStorageIDUpdate) UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if u.mb == nil { return errMBIsNotAvailable } - var prm meta.PutPrm - prm.SetObject(obj) + + var prm meta.UpdateStorageIDPrm + prm.SetAddress(addr) prm.SetStorageID(storageID) - _, err := u.mb.Put(ctx, prm) + _, err := u.mb.UpdateStorageID(ctx, prm) return err } From da4fee2d0b693500bf917b3d850570ca889f0bbd Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 22 Sep 2023 17:08:48 +0300 Subject: [PATCH 0186/1413] [#698] blobovniczatree: Init blobovniczas concurrently Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 + cmd/frostfs-node/config/engine/config_test.go | 2 + .../shard/blobstor/blobovnicza/config.go | 19 ++++++ config/example/node.env | 1 + config/example/node.json | 3 +- config/example/node.yaml | 1 + .../blobstor/blobovniczatree/control.go | 49 ++++++++----- .../blobstor/blobovniczatree/option.go | 68 +++++++++++-------- 8 files changed, 102 insertions(+), 44 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index cc106cf957..840dbf3320 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -181,6 +181,7 @@ type subStorageCfg struct { width uint64 leafWidth uint64 openedCacheSize int + initWorkerCount int } // readConfig fills applicationConfiguration with raw configuration values @@ -298,6 +299,7 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol sCfg.width = sub.ShallowWidth() sCfg.leafWidth = sub.LeafWidth() sCfg.openedCacheSize = sub.OpenedCacheSize() + sCfg.initWorkerCount = sub.InitWorkerCount() case fstree.Type: sub := fstreeconfig.From((*config.Config)(storagesCfg[i])) sCfg.depth = sub.Depth() @@ -796,6 +798,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { blobovniczatree.WithBlobovniczaShallowWidth(sRead.width), blobovniczatree.WithBlobovniczaLeafWidth(sRead.leafWidth), blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize), + blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), blobovniczatree.WithLogger(c.log), } diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 665f70bcb6..6b2b372265 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -97,6 +97,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 4, blz.ShallowWidth()) require.EqualValues(t, 50, blz.OpenedCacheSize()) require.EqualValues(t, 10, blz.LeafWidth()) + require.EqualValues(t, 10, blz.InitWorkerCount()) require.Equal(t, "tmp/0/blob", ss[1].Path()) require.EqualValues(t, 0o644, ss[1].Perm()) @@ -146,6 +147,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 4, blz.ShallowWidth()) require.EqualValues(t, 50, blz.OpenedCacheSize()) require.EqualValues(t, 10, blz.LeafWidth()) + require.EqualValues(t, blobovniczaconfig.InitWorkerCountDefault, blz.InitWorkerCount()) require.Equal(t, "tmp/1/blob", ss[1].Path()) require.EqualValues(t, 0o644, ss[1].Perm()) diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go index a780ea9271..1f7fc77f57 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go @@ -22,6 +22,9 @@ const ( // OpenedCacheSizeDefault is a default cache size of opened Blobovnicza's. OpenedCacheSizeDefault = 16 + + // InitWorkerCountDefault is a default workers count to initialize Blobovnicza's. + InitWorkerCountDefault = 5 ) // From wraps config section into Config. @@ -112,3 +115,19 @@ func (x *Config) LeafWidth() uint64 { "leaf_width", ) } + +// InitWorkerCount returns the value of "init_worker_count" config parameter. +// +// Returns InitWorkerCountDefault if the value is not a positive number. +func (x *Config) InitWorkerCount() int { + d := config.IntSafe( + (*config.Config)(x), + "init_worker_count", + ) + + if d > 0 { + return int(d) + } + + return InitWorkerCountDefault +} diff --git a/config/example/node.env b/config/example/node.env index f4dc218a3c..9d36b51083 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -125,6 +125,7 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH=1 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 +FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 ### FSTree config FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE=fstree FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH=tmp/0/blob diff --git a/config/example/node.json b/config/example/node.json index c2e3d0a5d4..b008009d6c 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -172,7 +172,8 @@ "depth": 1, "width": 4, "opened_cache_capacity": 50, - "leaf_width": 10 + "leaf_width": 10, + "init_worker_count": 10 }, { "type": "fstree", diff --git a/config/example/node.yaml b/config/example/node.yaml index d04e122b6c..bf92388a26 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -184,6 +184,7 @@ storage: blobstor: - type: blobovnicza path: tmp/0/blob/blobovnicza + init_worker_count: 10 #count of workers to initialize blobovniczas - type: fstree path: tmp/0/blob # blobstor path diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 69f3ca97f1..ad463c1138 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "go.uber.org/zap" + "golang.org/x/sync/errgroup" ) var errFailedToChangeExtensionReadOnly = errors.New("failed to change blobovnicza extension: read only mode") @@ -49,37 +50,53 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { return err } + eg, egCtx := errgroup.WithContext(ctx) + eg.SetLimit(b.blzInitWorkerCount) visited := make(map[string]struct{}) - err = b.iterateExistingDBPaths(ctx, func(p string) (bool, error) { + err = b.iterateExistingDBPaths(egCtx, func(p string) (bool, error) { visited[p] = struct{}{} - shBlz := b.getBlobovniczaWithoutCaching(p) - _, err := shBlz.Open() - if err != nil { - return true, err - } - defer shBlz.Close() + eg.Go(func() error { + shBlz := b.getBlobovniczaWithoutCaching(p) + _, err := shBlz.Open() + if err != nil { + return err + } + defer shBlz.Close() - b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) + b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) + return nil + }) return false, nil }) if err != nil { + _ = eg.Wait() return err } - return b.iterateSortedLeaves(ctx, nil, func(p string) (bool, error) { + err = b.iterateSortedLeaves(egCtx, nil, func(p string) (bool, error) { if _, found := visited[p]; found { return false, nil } - shBlz := b.getBlobovniczaWithoutCaching(p) - _, err := shBlz.Open() - if err != nil { - return true, err - } - defer shBlz.Close() + eg.Go(func() error { + shBlz := b.getBlobovniczaWithoutCaching(p) + _, err := shBlz.Open() + if err != nil { + return err + } + defer shBlz.Close() - b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) + b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) + return nil + }) return false, nil }) + + if err != nil { + _ = eg.Wait() + return err + } + + return eg.Wait() } func (b *Blobovniczas) openManagers() { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index 54c5211860..f1eb1eb8e1 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -11,42 +11,44 @@ import ( ) type cfg struct { - log *logger.Logger - perm fs.FileMode - readOnly bool - rootPath string - openedCacheSize int - blzShallowDepth uint64 - blzShallowWidth uint64 - blzLeafWidth uint64 - compression *compression.Config - blzOpts []blobovnicza.Option - // reportError is the function called when encountering disk errors. - reportError func(string, error) - metrics Metrics - waitBeforeDropDB time.Duration + log *logger.Logger + perm fs.FileMode + readOnly bool + rootPath string + openedCacheSize int + blzShallowDepth uint64 + blzShallowWidth uint64 + blzLeafWidth uint64 + compression *compression.Config + blzOpts []blobovnicza.Option + reportError func(string, error) // reportError is the function called when encountering disk errors. + metrics Metrics + waitBeforeDropDB time.Duration + blzInitWorkerCount int } type Option func(*cfg) const ( - defaultPerm = 0o700 - defaultOpenedCacheSize = 50 - defaultBlzShallowDepth = 2 - defaultBlzShallowWidth = 16 - defaultWaitBeforeDropDB = 10 * time.Second + defaultPerm = 0o700 + defaultOpenedCacheSize = 50 + defaultBlzShallowDepth = 2 + defaultBlzShallowWidth = 16 + defaultWaitBeforeDropDB = 10 * time.Second + defaultBlzInitWorkerCount = 5 ) func initConfig(c *cfg) { *c = cfg{ - log: &logger.Logger{Logger: zap.L()}, - perm: defaultPerm, - openedCacheSize: defaultOpenedCacheSize, - blzShallowDepth: defaultBlzShallowDepth, - blzShallowWidth: defaultBlzShallowWidth, - reportError: func(string, error) {}, - metrics: &noopMetrics{}, - waitBeforeDropDB: defaultWaitBeforeDropDB, + log: &logger.Logger{Logger: zap.L()}, + perm: defaultPerm, + openedCacheSize: defaultOpenedCacheSize, + blzShallowDepth: defaultBlzShallowDepth, + blzShallowWidth: defaultBlzShallowWidth, + reportError: func(string, error) {}, + metrics: &noopMetrics{}, + waitBeforeDropDB: defaultWaitBeforeDropDB, + blzInitWorkerCount: defaultBlzInitWorkerCount, } } @@ -116,3 +118,15 @@ func WithWaitBeforeDropDB(t time.Duration) Option { c.waitBeforeDropDB = t } } + +// WithInitWorkerCount sets maximum workers count to init blobovnicza tree. +// +// Negative or zero value means no limit. +func WithInitWorkerCount(v int) Option { + if v <= 0 { + v = -1 + } + return func(c *cfg) { + c.blzInitWorkerCount = v + } +} From b2769ca3dec21420a800ed79d56ea2abe608084c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Sep 2023 16:25:15 +0300 Subject: [PATCH 0187/1413] [#661] blobovniczatree: Make Rebuild failover safe Now move info stores in blobovnicza, so in case of failover rebuild completes previous operation first. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 11 + .../blobovnicza/control.go | 2 +- .../blobovnicza/delete.go | 2 +- .../blobovnicza/exists.go | 6 +- pkg/local_object_storage/blobovnicza/get.go | 6 +- .../blobovnicza/iterate.go | 10 +- pkg/local_object_storage/blobovnicza/move.go | 108 +++++++ .../blobstor/blobovniczatree/blobovnicza.go | 12 +- .../blobstor/blobovniczatree/control.go | 10 +- .../blobstor/blobovniczatree/delete.go | 7 + .../blobstor/blobovniczatree/iterate.go | 16 +- .../blobstor/blobovniczatree/rebuild.go | 268 +++++++++++++++++- .../blobovniczatree/rebuild_failover_test.go | 192 +++++++++++++ 13 files changed, 615 insertions(+), 35 deletions(-) create mode 100644 pkg/local_object_storage/blobovnicza/move.go create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 6a46672096..17ba339946 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -537,4 +537,15 @@ const ( BlobovniczaTreeRebuildingBlobovnicza = "rebuilding blobovnicza..." BlobovniczaTreeRebuildingBlobovniczaFailed = "rebuilding blobovnicza failed" BlobovniczaTreeRebuildingBlobovniczaSuccess = "rebuilding blobovnicza completed successfully" + BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza = "could not put move info to source blobovnicza" + BlobovniczatreeCouldNotUpdateStorageID = "could not update storage ID" + BlobovniczatreeCouldNotDropMoveInfo = "could not drop move info from source blobovnicza" + BlobovniczatreeCouldNotDeleteFromSource = "could not delete object from source blobovnicza" + BlobovniczaTreeCompletingPreviousRebuild = "completing previous rebuild if failed..." + BlobovniczaTreeCompletedPreviousRebuildSuccess = "previous rebuild completed successfully" + BlobovniczaTreeCompletedPreviousRebuildFailed = "failed to complete previous rebuild" + BlobovniczatreeCouldNotCheckExistenceInSourceDB = "could not check object existence in source blobovnicza" + BlobovniczatreeCouldNotCheckExistenceInTargetDB = "could not check object existence in target blobovnicza" + BlobovniczatreeCouldNotGetObjectFromSourceDB = "could not get object from source blobovnicza" + BlobovniczatreeCouldNotPutObjectToTargetDB = "could not put object to target blobovnicza" ) diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index ad554a0ad6..c1d7d49a37 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -105,7 +105,7 @@ func (b *Blobovnicza) initializeCounters() error { var size uint64 var items uint64 err := b.boltDB.View(func(tx *bbolt.Tx) error { - return b.iterateAllBuckets(tx, func(lower, upper uint64, b *bbolt.Bucket) (bool, error) { + return b.iterateAllDataBuckets(tx, func(lower, upper uint64, b *bbolt.Bucket) (bool, error) { keysN := uint64(b.Stats().KeyN) size += keysN * upper items += keysN diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index d256c1c69a..0f92ea3f5f 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -51,7 +51,7 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err var dataSize uint64 err := b.boltDB.Update(func(tx *bbolt.Tx) error { - return b.iterateAllBuckets(tx, func(lower, upper uint64, buck *bbolt.Bucket) (bool, error) { + return b.iterateAllDataBuckets(tx, func(lower, upper uint64, buck *bbolt.Bucket) (bool, error) { objData := buck.Get(addrKey) if objData == nil { // object is not in bucket => continue iterating diff --git a/pkg/local_object_storage/blobovnicza/exists.go b/pkg/local_object_storage/blobovnicza/exists.go index 9b190416fd..8cafc72ad8 100644 --- a/pkg/local_object_storage/blobovnicza/exists.go +++ b/pkg/local_object_storage/blobovnicza/exists.go @@ -1,6 +1,7 @@ package blobovnicza import ( + "bytes" "context" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -24,7 +25,10 @@ func (b *Blobovnicza) Exists(ctx context.Context, addr oid.Address) (bool, error addrKey := addressKey(addr) err := b.boltDB.View(func(tx *bbolt.Tx) error { - return tx.ForEach(func(_ []byte, buck *bbolt.Bucket) error { + return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { + if bytes.Equal(bucketName, incompletedMoveBucketName) { + return nil + } exists = buck.Get(addrKey) != nil if exists { return errInterruptForEach diff --git a/pkg/local_object_storage/blobovnicza/get.go b/pkg/local_object_storage/blobovnicza/get.go index 9975e5e8c8..88d8e7e4a1 100644 --- a/pkg/local_object_storage/blobovnicza/get.go +++ b/pkg/local_object_storage/blobovnicza/get.go @@ -57,7 +57,11 @@ func (b *Blobovnicza) Get(ctx context.Context, prm GetPrm) (GetRes, error) { ) if err := b.boltDB.View(func(tx *bbolt.Tx) error { - return tx.ForEach(func(_ []byte, buck *bbolt.Bucket) error { + return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { + if bytes.Equal(bucketName, incompletedMoveBucketName) { + return nil + } + data = buck.Get(addrKey) if data == nil { return nil diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index f4b85f5d0b..e19f8f14b2 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -1,6 +1,7 @@ package blobovnicza import ( + "bytes" "context" "fmt" "math" @@ -12,11 +13,11 @@ import ( "go.opentelemetry.io/otel/trace" ) -// iterateAllBuckets iterates all buckets in db +// iterateAllDataBuckets iterates all buckets in db // // If the maximum size of the object (b.objSizeLimit) has been changed to lower value, // then there may be more buckets than the current limit of the object size. -func (b *Blobovnicza) iterateAllBuckets(tx *bbolt.Tx, f func(uint64, uint64, *bbolt.Bucket) (bool, error)) error { +func (b *Blobovnicza) iterateAllDataBuckets(tx *bbolt.Tx, f func(uint64, uint64, *bbolt.Bucket) (bool, error)) error { return b.iterateBucketKeys(false, func(lower uint64, upper uint64, key []byte) (bool, error) { buck := tx.Bucket(key) if buck == nil { @@ -138,7 +139,10 @@ func (b *Blobovnicza) Iterate(ctx context.Context, prm IteratePrm) (IterateRes, var elem IterationElement if err := b.boltDB.View(func(tx *bbolt.Tx) error { - return tx.ForEach(func(name []byte, buck *bbolt.Bucket) error { + return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { + if bytes.Equal(bucketName, incompletedMoveBucketName) { + return nil + } return buck.ForEach(func(k, v []byte) error { select { case <-ctx.Done(): diff --git a/pkg/local_object_storage/blobovnicza/move.go b/pkg/local_object_storage/blobovnicza/move.go new file mode 100644 index 0000000000..255198f665 --- /dev/null +++ b/pkg/local_object_storage/blobovnicza/move.go @@ -0,0 +1,108 @@ +package blobovnicza + +import ( + "context" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.etcd.io/bbolt" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +var incompletedMoveBucketName = []byte("INCOMPLETED_MOVE") + +type MoveInfo struct { + Address oid.Address + TargetStorageID []byte +} + +func (b *Blobovnicza) PutMoveInfo(ctx context.Context, prm MoveInfo) error { + _, span := tracing.StartSpanFromContext(ctx, "Blobovnicza.PutMoveInfo", + trace.WithAttributes( + attribute.String("path", b.path), + attribute.String("address", prm.Address.EncodeToString()), + attribute.String("target_storage_id", string(prm.TargetStorageID)), + )) + defer span.End() + + key := addressKey(prm.Address) + + return b.boltDB.Update(func(tx *bbolt.Tx) error { + bucket, err := tx.CreateBucketIfNotExists(incompletedMoveBucketName) + if err != nil { + return err + } + + if err := bucket.Put(key, prm.TargetStorageID); err != nil { + return fmt.Errorf("(%T) failed to save move info: %w", b, err) + } + + return nil + }) +} + +func (b *Blobovnicza) DropMoveInfo(ctx context.Context, address oid.Address) error { + _, span := tracing.StartSpanFromContext(ctx, "Blobovnicza.DropMoveInfo", + trace.WithAttributes( + attribute.String("path", b.path), + attribute.String("address", address.EncodeToString()), + )) + defer span.End() + + key := addressKey(address) + + return b.boltDB.Update(func(tx *bbolt.Tx) error { + bucket := tx.Bucket(incompletedMoveBucketName) + if bucket == nil { + return nil + } + + if err := bucket.Delete(key); err != nil { + return fmt.Errorf("(%T) failed to drop move info: %w", b, err) + } + + c := bucket.Cursor() + k, v := c.First() + bucketEmpty := k == nil && v == nil + if bucketEmpty { + return tx.DeleteBucket(incompletedMoveBucketName) + } + + return nil + }) +} + +func (b *Blobovnicza) ListMoveInfo(ctx context.Context) ([]MoveInfo, error) { + _, span := tracing.StartSpanFromContext(ctx, "Blobovnicza.ListMoveInfo", + trace.WithAttributes( + attribute.String("path", b.path), + )) + defer span.End() + + var result []MoveInfo + if err := b.boltDB.View(func(tx *bbolt.Tx) error { + bucket := tx.Bucket(incompletedMoveBucketName) + if bucket == nil { + return nil + } + return bucket.ForEach(func(k, v []byte) error { + var addr oid.Address + storageID := make([]byte, len(v)) + if err := addressFromKey(&addr, k); err != nil { + return err + } + copy(storageID, v) + result = append(result, MoveInfo{ + Address: addr, + TargetStorageID: storageID, + }) + return nil + }) + }); err != nil { + return nil, err + } + + return result, nil +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 0354fa2acc..9f2950094e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -56,11 +56,12 @@ import ( type Blobovniczas struct { cfg - commondbManager *dbManager - activeDBManager *activeDBManager - dbCache *dbCache - dbFilesGuard *sync.RWMutex - rebuildGuard *sync.RWMutex + commondbManager *dbManager + activeDBManager *activeDBManager + dbCache *dbCache + deleteProtectedObjects *addressMap + dbFilesGuard *sync.RWMutex + rebuildGuard *sync.RWMutex } var _ common.Storage = (*Blobovniczas)(nil) @@ -87,6 +88,7 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) blz.dbCache = newDBCache(blz.openedCacheSize, blz.commondbManager) + blz.deleteProtectedObjects = newAddressMap() blz.dbFilesGuard = &sync.RWMutex{} blz.rebuildGuard = &sync.RWMutex{} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index ad463c1138..561b085996 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -57,12 +57,20 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { visited[p] = struct{}{} eg.Go(func() error { shBlz := b.getBlobovniczaWithoutCaching(p) - _, err := shBlz.Open() + blz, err := shBlz.Open() if err != nil { return err } defer shBlz.Close() + moveInfo, err := blz.ListMoveInfo(egCtx) + if err != nil { + return err + } + for _, move := range moveInfo { + b.deleteProtectedObjects.Add(move.Address) + } + b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) return nil }) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 56803c8728..298de3ad65 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -3,6 +3,7 @@ package blobovniczatree import ( "context" "encoding/hex" + "errors" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -18,6 +19,8 @@ import ( "go.uber.org/zap" ) +var errObjectIsDeleteProtected = errors.New("object is delete protected") + // Delete deletes object from blobovnicza tree. // // If blobocvnicza ID is specified, only this blobovnicza is processed. @@ -49,6 +52,10 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co return common.DeleteRes{}, errRebuildInProgress } + if b.deleteProtectedObjects.Contains(prm.Address) { + return common.DeleteRes{}, errObjectIsDeleteProtected + } + var bPrm blobovnicza.DeletePrm bPrm.SetAddress(prm.Address) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 7367879521..5115439b1b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -176,16 +176,14 @@ func (b *Blobovniczas) iterateSorted(ctx context.Context, addr *oid.Address, cur // // Uses existed blobovnicza files for iteration. func (b *Blobovniczas) iterateExistingDBPaths(ctx context.Context, f func(string) (bool, error)) error { + b.dbFilesGuard.RLock() + defer b.dbFilesGuard.RUnlock() + _, err := b.iterateExistingDBPathsDFS(ctx, "", f) return err } func (b *Blobovniczas) iterateExistingDBPathsDFS(ctx context.Context, path string, f func(string) (bool, error)) (bool, error) { - if path == "" { - b.dbFilesGuard.RLock() - defer b.dbFilesGuard.RUnlock() - } - sysPath := filepath.Join(b.rootPath, path) entries, err := os.ReadDir(sysPath) if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode @@ -222,16 +220,14 @@ func (b *Blobovniczas) iterateExistingDBPathsDFS(ctx context.Context, path strin } func (b *Blobovniczas) iterateSortedDBPaths(ctx context.Context, addr oid.Address, f func(string) (bool, error)) error { + b.dbFilesGuard.RLock() + defer b.dbFilesGuard.RUnlock() + _, err := b.iterateSordedDBPathsInternal(ctx, "", addr, f) return err } func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path string, addr oid.Address, f func(string) (bool, error)) (bool, error) { - if path == "" { - b.dbFilesGuard.RLock() - defer b.dbFilesGuard.RUnlock() - } - sysPath := filepath.Join(b.rootPath, path) entries, err := os.ReadDir(sysPath) if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 35e001b632..5f87933bf6 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -5,11 +5,13 @@ import ( "errors" "os" "path/filepath" + "sync" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) @@ -24,8 +26,18 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm b.rebuildGuard.Lock() defer b.rebuildGuard.Unlock() - b.log.Debug(logs.BlobovniczaTreeCollectingDBToRebuild) var res common.RebuildRes + + b.log.Debug(logs.BlobovniczaTreeCompletingPreviousRebuild) + completedPreviosMoves, err := b.completeIncompletedMove(ctx, prm.MetaStorage) + res.ObjectsMoved += completedPreviosMoves + if err != nil { + b.log.Warn(logs.BlobovniczaTreeCompletedPreviousRebuildFailed, zap.Error(err)) + return res, err + } + b.log.Debug(logs.BlobovniczaTreeCompletedPreviousRebuildSuccess) + + b.log.Debug(logs.BlobovniczaTreeCollectingDBToRebuild) dbsToMigrate, err := b.getDBsToRebuild(ctx) if err != nil { b.log.Warn(logs.BlobovniczaTreeCollectingDBToRebuildFailed, zap.Error(err)) @@ -82,7 +94,7 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M shDB.Close() }() - migratedObjects, err := b.moveObjects(ctx, blz, meta) + migratedObjects, err := b.moveObjects(ctx, blz, shDB.SystemPath(), meta) if err != nil { return migratedObjects, err } @@ -90,13 +102,13 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M return migratedObjects, err } -func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, meta common.MetaStorage) (uint64, error) { +func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, blzPath string, meta common.MetaStorage) (uint64, error) { var result uint64 var prm blobovnicza.IteratePrm prm.DecodeAddresses() prm.SetHandler(func(ie blobovnicza.IterationElement) error { - e := b.moveObject(ctx, ie.Address(), ie.ObjectData(), meta) + e := b.moveObject(ctx, blz, blzPath, ie.Address(), ie.ObjectData(), meta) if e == nil { result++ } @@ -107,15 +119,28 @@ func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovn return result, err } -func (b *Blobovniczas) moveObject(ctx context.Context, addr oid.Address, data []byte, metaStore common.MetaStorage) error { - var pPrm common.PutPrm - pPrm.Address = addr - pPrm.RawData = data - pRes, err := b.Put(ctx, pPrm) - if err != nil { - return err +func (b *Blobovniczas) moveObject(ctx context.Context, source *blobovnicza.Blobovnicza, sourcePath string, + addr oid.Address, data []byte, metaStore common.MetaStorage) error { + it := &moveIterator{ + B: b, + ID: nil, + AllFull: true, + Address: addr, + ObjectData: data, + MetaStore: metaStore, + Source: source, + SourceSysPath: sourcePath, } - return metaStore.UpdateStorageID(ctx, addr, pRes.StorageID) + + if err := b.iterateDeepest(ctx, addr, func(lvlPath string) (bool, error) { return it.tryMoveToLvl(ctx, lvlPath) }); err != nil { + return err + } else if it.ID == nil { + if it.AllFull { + return common.ErrNoSpace + } + return errPutFailed + } + return nil } func (b *Blobovniczas) dropDB(ctx context.Context, path string, shDb *sharedDB) (bool, error) { @@ -159,3 +184,222 @@ func (b *Blobovniczas) dropDirectoryIfEmpty(path string) error { } return b.dropDirectoryIfEmpty(filepath.Dir(path)) } + +func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore common.MetaStorage) (uint64, error) { + var count uint64 + return count, b.iterateExistingDBPaths(ctx, func(s string) (bool, error) { + shDB := b.getBlobovnicza(s) + blz, err := shDB.Open() + if err != nil { + return true, err + } + defer shDB.Close() + + incompletedMoves, err := blz.ListMoveInfo(ctx) + if err != nil { + return true, err + } + + for _, move := range incompletedMoves { + if err := b.performMove(ctx, blz, shDB.SystemPath(), move, metaStore); err != nil { + return true, err + } + count++ + } + + return false, nil + }) +} + +func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blobovnicza, sourcePath string, + move blobovnicza.MoveInfo, metaStore common.MetaStorage) error { + targetDB := b.getBlobovnicza(NewIDFromBytes(move.TargetStorageID).Path()) + target, err := targetDB.Open() + if err != nil { + return err + } + defer targetDB.Close() + + existsInSource := true + var gPrm blobovnicza.GetPrm + gPrm.SetAddress(move.Address) + gRes, err := source.Get(ctx, gPrm) + if err != nil { + if client.IsErrObjectNotFound(err) { + existsInSource = false + } else { + b.log.Warn(logs.BlobovniczatreeCouldNotCheckExistenceInTargetDB, zap.Error(err)) + return err + } + } + + if !existsInSource { //object was deleted by Rebuild, need to delete move info + if err = source.DropMoveInfo(ctx, move.Address); err != nil { + b.log.Warn(logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", sourcePath), zap.Error(err)) + return err + } + b.deleteProtectedObjects.Delete(move.Address) + return nil + } + + existsInTarget, err := target.Exists(ctx, move.Address) + if err != nil { + b.log.Warn(logs.BlobovniczatreeCouldNotCheckExistenceInTargetDB, zap.Error(err)) + return err + } + + if !existsInTarget { + var putPrm blobovnicza.PutPrm + putPrm.SetAddress(move.Address) + putPrm.SetMarshaledObject(gRes.Object()) + _, err = target.Put(ctx, putPrm) + if err != nil { + b.log.Warn(logs.BlobovniczatreeCouldNotPutObjectToTargetDB, zap.String("path", targetDB.SystemPath()), zap.Error(err)) + return err + } + } + + if err = metaStore.UpdateStorageID(ctx, move.Address, move.TargetStorageID); err != nil { + b.log.Warn(logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err)) + return err + } + + var deletePrm blobovnicza.DeletePrm + deletePrm.SetAddress(move.Address) + if _, err = source.Delete(ctx, deletePrm); err != nil { + b.log.Warn(logs.BlobovniczatreeCouldNotDeleteFromSource, zap.String("path", sourcePath), zap.Error(err)) + return err + } + + if err = source.DropMoveInfo(ctx, move.Address); err != nil { + b.log.Warn(logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", sourcePath), zap.Error(err)) + return err + } + + b.deleteProtectedObjects.Delete(move.Address) + return nil +} + +type moveIterator struct { + B *Blobovniczas + ID *ID + AllFull bool + Address oid.Address + ObjectData []byte + MetaStore common.MetaStorage + Source *blobovnicza.Blobovnicza + SourceSysPath string +} + +func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, error) { + target, err := i.B.activeDBManager.GetOpenedActiveDBForLevel(lvlPath) + if err != nil { + if !isLogical(err) { + i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) + } else { + i.B.log.Warn(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, zap.Error(err)) + } + return false, nil + } + + if target == nil { + i.B.log.Warn(logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath)) + return false, nil + } + defer target.Close() + + i.AllFull = false + + targetIDx := u64FromHexString(filepath.Base(target.SystemPath())) + targetStorageID := NewIDFromBytes([]byte(filepath.Join(lvlPath, u64ToHexString(targetIDx)))) + + if err = i.Source.PutMoveInfo(ctx, blobovnicza.MoveInfo{ + Address: i.Address, + TargetStorageID: targetStorageID.Bytes(), + }); err != nil { + if !isLogical(err) { + i.B.reportError(logs.BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza, err) + } else { + i.B.log.Warn(logs.BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza, zap.String("path", i.SourceSysPath), zap.Error(err)) + } + return true, nil + } + i.B.deleteProtectedObjects.Add(i.Address) + + var putPrm blobovnicza.PutPrm + putPrm.SetAddress(i.Address) + putPrm.SetMarshaledObject(i.ObjectData) + + _, err = target.Blobovnicza().Put(ctx, putPrm) + if err != nil { + if !isLogical(err) { + i.B.reportError(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) + } else { + i.B.log.Warn(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", target.SystemPath()), zap.Error(err)) + } + return true, nil + } + + if err = i.MetaStore.UpdateStorageID(ctx, i.Address, targetStorageID.Bytes()); err != nil { + i.B.log.Warn(logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err)) + return true, nil + } + + var deletePrm blobovnicza.DeletePrm + deletePrm.SetAddress(i.Address) + if _, err = i.Source.Delete(ctx, deletePrm); err != nil { + if !isLogical(err) { + i.B.reportError(logs.BlobovniczatreeCouldNotDeleteFromSource, err) + } else { + i.B.log.Warn(logs.BlobovniczatreeCouldNotDeleteFromSource, zap.String("path", i.SourceSysPath), zap.Error(err)) + } + return true, nil + } + + if err = i.Source.DropMoveInfo(ctx, i.Address); err != nil { + if !isLogical(err) { + i.B.reportError(logs.BlobovniczatreeCouldNotDropMoveInfo, err) + } else { + i.B.log.Warn(logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", i.SourceSysPath), zap.Error(err)) + } + return true, nil + } + i.B.deleteProtectedObjects.Delete(i.Address) + + i.ID = targetStorageID + return true, nil +} + +type addressMap struct { + data map[oid.Address]struct{} + guard *sync.RWMutex +} + +func newAddressMap() *addressMap { + return &addressMap{ + data: make(map[oid.Address]struct{}), + guard: &sync.RWMutex{}, + } +} + +func (m *addressMap) Add(address oid.Address) { + m.guard.Lock() + defer m.guard.Unlock() + + m.data[address] = struct{}{} +} + +func (m *addressMap) Delete(address oid.Address) { + m.guard.Lock() + defer m.guard.Unlock() + + delete(m.data, address) +} + +func (m *addressMap) Contains(address oid.Address) bool { + m.guard.RLock() + defer m.guard.RUnlock() + + _, contains := m.data[address] + return contains +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go new file mode 100644 index 0000000000..c9ce564c94 --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -0,0 +1,192 @@ +package blobovniczatree + +import ( + "bytes" + "context" + "path/filepath" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/stretchr/testify/require" +) + +func TestRebuildFailover(t *testing.T) { + t.Parallel() + + t.Run("only move info saved", testRebuildFailoverOnlyMoveInfoSaved) + + t.Run("object saved to target", testRebuildFailoverObjectSavedToTarget) + + t.Run("object deleted from source", testRebuildFailoverObjectDeletedFromSource) +} + +func testRebuildFailoverOnlyMoveInfoSaved(t *testing.T) { + t.Parallel() + dir := t.TempDir() + + blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) + require.NoError(t, blz.Open()) + require.NoError(t, blz.Init()) + + obj := blobstortest.NewObject(1024) + data, err := obj.Marshal() + require.NoError(t, err) + + var pPrm blobovnicza.PutPrm + pPrm.SetAddress(object.AddressOf(obj)) + pPrm.SetMarshaledObject(data) + _, err = blz.Put(context.Background(), pPrm) + require.NoError(t, err) + + require.NoError(t, blz.PutMoveInfo(context.Background(), blobovnicza.MoveInfo{ + Address: object.AddressOf(obj), + TargetStorageID: []byte("0/0/0"), + })) + + require.NoError(t, blz.Close()) + + testRebuildFailoverValidate(t, dir, obj, true) +} + +func testRebuildFailoverObjectSavedToTarget(t *testing.T) { + t.Parallel() + dir := t.TempDir() + + blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) + require.NoError(t, blz.Open()) + require.NoError(t, blz.Init()) + + obj := blobstortest.NewObject(1024) + data, err := obj.Marshal() + require.NoError(t, err) + + var pPrm blobovnicza.PutPrm + pPrm.SetAddress(object.AddressOf(obj)) + pPrm.SetMarshaledObject(data) + _, err = blz.Put(context.Background(), pPrm) + require.NoError(t, err) + + require.NoError(t, blz.PutMoveInfo(context.Background(), blobovnicza.MoveInfo{ + Address: object.AddressOf(obj), + TargetStorageID: []byte("0/0/0"), + })) + + require.NoError(t, blz.Close()) + + blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) + require.NoError(t, blz.Open()) + require.NoError(t, blz.Init()) + + _, err = blz.Put(context.Background(), pPrm) + require.NoError(t, err) + + require.NoError(t, blz.Close()) + + testRebuildFailoverValidate(t, dir, obj, true) +} + +func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { + t.Parallel() + dir := t.TempDir() + + blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) + require.NoError(t, blz.Open()) + require.NoError(t, blz.Init()) + + obj := blobstortest.NewObject(1024) + data, err := obj.Marshal() + require.NoError(t, err) + + require.NoError(t, blz.PutMoveInfo(context.Background(), blobovnicza.MoveInfo{ + Address: object.AddressOf(obj), + TargetStorageID: []byte("0/0/0"), + })) + + require.NoError(t, blz.Close()) + + blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) + require.NoError(t, blz.Open()) + require.NoError(t, blz.Init()) + + var pPrm blobovnicza.PutPrm + pPrm.SetAddress(object.AddressOf(obj)) + pPrm.SetMarshaledObject(data) + _, err = blz.Put(context.Background(), pPrm) + require.NoError(t, err) + + require.NoError(t, blz.Close()) + + testRebuildFailoverValidate(t, dir, obj, false) +} + +func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object, mustUpdateStorageID bool) { + b := NewBlobovniczaTree( + WithLogger(test.NewLogger(t, true)), + WithObjectSizeLimit(2048), + WithBlobovniczaShallowWidth(2), + WithBlobovniczaShallowDepth(2), + WithRootPath(dir), + WithBlobovniczaSize(100*1024*1024), + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000)) + require.NoError(t, b.Open(false)) + require.NoError(t, b.Init()) + + var dPrm common.DeletePrm + dPrm.Address = object.AddressOf(obj) + dPrm.StorageID = []byte("0/0/1") + _, err := b.Delete(context.Background(), dPrm) + require.ErrorIs(t, err, errObjectIsDeleteProtected) + + metaStub := &storageIDUpdateStub{ + storageIDs: make(map[oid.Address][]byte), + } + rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ + MetaStorage: metaStub, + }) + require.NoError(t, err) + require.Equal(t, uint64(1), rRes.ObjectsMoved) + require.Equal(t, uint64(0), rRes.FilesRemoved) + + require.NoError(t, b.Close()) + + blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) + require.NoError(t, blz.Open()) + require.NoError(t, blz.Init()) + + moveInfo, err := blz.ListMoveInfo(context.Background()) + require.NoError(t, err) + require.Equal(t, 0, len(moveInfo)) + + var gPrm blobovnicza.GetPrm + gPrm.SetAddress(object.AddressOf(obj)) + _, err = blz.Get(context.Background(), gPrm) + require.True(t, client.IsErrObjectNotFound(err)) + + require.NoError(t, blz.Close()) + + blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) + require.NoError(t, blz.Open()) + require.NoError(t, blz.Init()) + + moveInfo, err = blz.ListMoveInfo(context.Background()) + require.NoError(t, err) + require.Equal(t, 0, len(moveInfo)) + + gRes, err := blz.Get(context.Background(), gPrm) + require.NoError(t, err) + require.True(t, len(gRes.Object()) > 0) + + if mustUpdateStorageID { + require.True(t, bytes.Equal([]byte("0/0/0"), metaStub.storageIDs[object.AddressOf(obj)])) + } + + require.NoError(t, blz.Close()) +} From d4d905ecc6cd00a04be5f2b0d8dcf0b91312b551 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Sep 2023 18:21:37 +0300 Subject: [PATCH 0188/1413] [#661] metrics: Add blobovniczatree rebuild metrics Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/control.go | 1 + .../blobstor/blobovniczatree/metrics.go | 12 ++++++ .../blobstor/blobovniczatree/rebuild.go | 17 ++++++++ .../metrics/blobovnicza.go | 8 ++++ pkg/metrics/blobovnicza.go | 42 +++++++++++++++---- pkg/metrics/consts.go | 1 + 6 files changed, 74 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 561b085996..f1d78dc542 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -19,6 +19,7 @@ var errFailedToChangeExtensionReadOnly = errors.New("failed to change blobovnicz func (b *Blobovniczas) Open(readOnly bool) error { b.readOnly = readOnly b.metrics.SetMode(readOnly) + b.metrics.SetRebuildStatus(rebuildStatusNotStarted) b.openManagers() return nil } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go b/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go index 032d8cf71b..ee0326bcfb 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go @@ -6,6 +6,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" ) +const ( + rebuildStatusNotStarted = "not_started" + rebuildStatusRunning = "running" + rebuildStatusCompleted = "completed" + rebuildStatusFailed = "failed" +) + type Metrics interface { Blobovnicza() blobovnicza.Metrics @@ -14,6 +21,9 @@ type Metrics interface { SetMode(readOnly bool) Close() + SetRebuildStatus(status string) + ObjectMoved(d time.Duration) + Delete(d time.Duration, success, withStorageID bool) Exists(d time.Duration, success, withStorageID bool) GetRange(d time.Duration, size int, success, withStorageID bool) @@ -27,6 +37,8 @@ type noopMetrics struct{} func (m *noopMetrics) SetParentID(string) {} func (m *noopMetrics) SetMode(bool) {} func (m *noopMetrics) Close() {} +func (m *noopMetrics) SetRebuildStatus(string) {} +func (m *noopMetrics) ObjectMoved(time.Duration) {} func (m *noopMetrics) Delete(time.Duration, bool, bool) {} func (m *noopMetrics) Exists(time.Duration, bool, bool) {} func (m *noopMetrics) GetRange(time.Duration, int, bool, bool) {} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 5f87933bf6..c1f21703c3 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -23,6 +23,16 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm return common.RebuildRes{}, common.ErrReadOnly } + b.metrics.SetRebuildStatus(rebuildStatusRunning) + success := true + defer func() { + if success { + b.metrics.SetRebuildStatus(rebuildStatusCompleted) + } else { + b.metrics.SetRebuildStatus(rebuildStatusFailed) + } + }() + b.rebuildGuard.Lock() defer b.rebuildGuard.Unlock() @@ -33,6 +43,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm res.ObjectsMoved += completedPreviosMoves if err != nil { b.log.Warn(logs.BlobovniczaTreeCompletedPreviousRebuildFailed, zap.Error(err)) + success = false return res, err } b.log.Debug(logs.BlobovniczaTreeCompletedPreviousRebuildSuccess) @@ -41,6 +52,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm dbsToMigrate, err := b.getDBsToRebuild(ctx) if err != nil { b.log.Warn(logs.BlobovniczaTreeCollectingDBToRebuildFailed, zap.Error(err)) + success = false return res, err } b.log.Info(logs.BlobovniczaTreeCollectingDBToRebuildSuccess, zap.Int("blobovniczas_to_rebuild", len(dbsToMigrate))) @@ -50,6 +62,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm res.ObjectsMoved += movedObjects if err != nil { b.log.Warn(logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) + success = false return res, err } b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) @@ -121,6 +134,10 @@ func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovn func (b *Blobovniczas) moveObject(ctx context.Context, source *blobovnicza.Blobovnicza, sourcePath string, addr oid.Address, data []byte, metaStore common.MetaStorage) error { + startedAt := time.Now() + defer func() { + b.metrics.ObjectMoved(time.Since(startedAt)) + }() it := &moveIterator{ B: b, ID: nil, diff --git a/pkg/local_object_storage/metrics/blobovnicza.go b/pkg/local_object_storage/metrics/blobovnicza.go index 0d0318b3bb..3d751ba3f4 100644 --- a/pkg/local_object_storage/metrics/blobovnicza.go +++ b/pkg/local_object_storage/metrics/blobovnicza.go @@ -42,6 +42,14 @@ func (m *blobovniczaTreeMetrics) Close() { m.m.CloseBlobobvnizcaTree(m.shardID, m.path) } +func (m *blobovniczaTreeMetrics) SetRebuildStatus(status string) { + m.m.BlobovniczaTreeRebuildStatus(m.shardID, m.path, status) +} + +func (m *blobovniczaTreeMetrics) ObjectMoved(d time.Duration) { + m.m.BlobovniczaTreeObjectMoved(m.shardID, m.path, d) +} + func (m *blobovniczaTreeMetrics) Delete(d time.Duration, success, withStorageID bool) { m.m.BlobobvnizcaTreeMethodDuration(m.shardID, m.path, "Delete", d, success, metrics_impl.NullBool{Valid: true, Bool: withStorageID}) } diff --git a/pkg/metrics/blobovnicza.go b/pkg/metrics/blobovnicza.go index a1ecbc700f..ddeeb406cf 100644 --- a/pkg/metrics/blobovnicza.go +++ b/pkg/metrics/blobovnicza.go @@ -23,16 +23,21 @@ type BlobobvnizcaMetrics interface { IncOpenBlobovniczaCount(shardID, path string) DecOpenBlobovniczaCount(shardID, path string) + + BlobovniczaTreeRebuildStatus(shardID, path, status string) + BlobovniczaTreeObjectMoved(shardID, path string, d time.Duration) } type blobovnicza struct { - treeMode *shardIDPathModeValue - treeReqDuration *prometheus.HistogramVec - treePut *prometheus.CounterVec - treeGet *prometheus.CounterVec - treeOpenSize *prometheus.GaugeVec - treeOpenItems *prometheus.GaugeVec - treeOpenCounter *prometheus.GaugeVec + treeMode *shardIDPathModeValue + treeReqDuration *prometheus.HistogramVec + treePut *prometheus.CounterVec + treeGet *prometheus.CounterVec + treeOpenSize *prometheus.GaugeVec + treeOpenItems *prometheus.GaugeVec + treeOpenCounter *prometheus.GaugeVec + treeObjectMoveDuration *prometheus.HistogramVec + treeRebuildStatus *shardIDPathModeValue } func newBlobovnicza() *blobovnicza { @@ -75,6 +80,13 @@ func newBlobovnicza() *blobovnicza { Name: "open_blobovnicza_count", Help: "Count of opened blobovniczas of Blobovnicza tree", }, []string{shardIDLabel, pathLabel}), + treeObjectMoveDuration: metrics.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: blobovniczaTreeSubSystem, + Name: "object_move_duration_seconds", + Help: "Accumulated Blobovnicza tree object move duration", + }, []string{shardIDLabel, pathLabel}), + treeRebuildStatus: newShardIDPathMode(blobovniczaTreeSubSystem, "rebuild_status", "Blobovnicza tree rebuild status"), } } @@ -96,6 +108,11 @@ func (b *blobovnicza) CloseBlobobvnizcaTree(shardID, path string) { shardIDLabel: shardID, pathLabel: path, }) + b.treeObjectMoveDuration.DeletePartialMatch(prometheus.Labels{ + shardIDLabel: shardID, + pathLabel: path, + }) + b.treeRebuildStatus.SetMode(shardID, path, undefinedStatus) } func (b *blobovnicza) BlobobvnizcaTreeMethodDuration(shardID, path string, method string, d time.Duration, success bool, withStorageID NullBool) { @@ -163,3 +180,14 @@ func (b *blobovnicza) SubOpenBlobovniczaItems(shardID, path string, items uint64 pathLabel: path, }).Sub(float64(items)) } + +func (b *blobovnicza) BlobovniczaTreeRebuildStatus(shardID, path, status string) { + b.treeRebuildStatus.SetMode(shardID, path, status) +} + +func (b *blobovnicza) BlobovniczaTreeObjectMoved(shardID, path string, d time.Duration) { + b.treeObjectMoveDuration.With(prometheus.Labels{ + shardIDLabel: shardID, + pathLabel: path, + }).Observe(d.Seconds()) +} diff --git a/pkg/metrics/consts.go b/pkg/metrics/consts.go index f7a8fd771e..f3b83a2e5e 100644 --- a/pkg/metrics/consts.go +++ b/pkg/metrics/consts.go @@ -45,4 +45,5 @@ const ( failedToDeleteStatus = "failed_to_delete" deletedStatus = "deleted" + undefinedStatus = "undefined" ) From f1c7905263c8efb2f3530fd4cf16f80185aae98c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 3 Oct 2023 11:58:35 +0300 Subject: [PATCH 0189/1413] [#661] blobovniczatree: Make Rebuild concurrent Different DBs can be rebuild concurrently. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 5 +- cmd/frostfs-node/config/engine/config.go | 11 ++++ cmd/frostfs-node/config/engine/config_test.go | 2 + config/example/node.env | 1 + config/example/node.json | 1 + config/example/node.yaml | 1 + .../blobstor/blobovniczatree/rebuild.go | 57 ++++++++++++++----- .../blobovniczatree/rebuild_failover_test.go | 5 +- .../blobstor/blobovniczatree/rebuild_test.go | 11 ++++ .../blobstor/common/rebuild.go | 8 ++- pkg/local_object_storage/blobstor/rebuild.go | 10 +++- pkg/local_object_storage/engine/engine.go | 17 +++++- .../engine/rebuild_limiter.go | 26 +++++++++ pkg/local_object_storage/engine/shards.go | 1 + pkg/local_object_storage/shard/control.go | 2 +- .../shard/rebuild_limiter.go | 13 +++++ pkg/local_object_storage/shard/rebuilder.go | 18 +++--- pkg/local_object_storage/shard/shard.go | 11 ++++ 18 files changed, 170 insertions(+), 30 deletions(-) create mode 100644 pkg/local_object_storage/engine/rebuild_limiter.go create mode 100644 pkg/local_object_storage/shard/rebuild_limiter.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 840dbf3320..941aa0d0a4 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -103,6 +103,7 @@ type applicationConfiguration struct { shardPoolSize uint32 shards []shardCfg lowMem bool + rebuildWorkers uint32 } } @@ -213,6 +214,7 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { a.EngineCfg.errorThreshold = engineconfig.ShardErrorThreshold(c) a.EngineCfg.shardPoolSize = engineconfig.ShardPoolSize(c) a.EngineCfg.lowMem = engineconfig.EngineLowMemoryConsumption(c) + a.EngineCfg.rebuildWorkers = engineconfig.EngineRebuildWorkersCount(c) return engineconfig.IterateShards(c, false, func(sc *shardconfig.Config) error { return a.updateShardConfig(c, sc) }) } @@ -703,13 +705,14 @@ func initCfgObject(appCfg *config.Config) cfgObject { } func (c *cfg) engineOpts() []engine.Option { - opts := make([]engine.Option, 0, 4) + var opts []engine.Option opts = append(opts, engine.WithShardPoolSize(c.EngineCfg.shardPoolSize), engine.WithErrorThreshold(c.EngineCfg.errorThreshold), engine.WithLogger(c.log), engine.WithLowMemoryConsumption(c.EngineCfg.lowMem), + engine.WithRebuildWorkersCount(c.EngineCfg.rebuildWorkers), ) if c.metricsCollector != nil { diff --git a/cmd/frostfs-node/config/engine/config.go b/cmd/frostfs-node/config/engine/config.go index c944d1c58e..baa4e3c9d3 100644 --- a/cmd/frostfs-node/config/engine/config.go +++ b/cmd/frostfs-node/config/engine/config.go @@ -15,6 +15,9 @@ const ( // ShardPoolSizeDefault is a default value of routine pool size per-shard to // process object PUT operations in a storage engine. ShardPoolSizeDefault = 20 + // RebuildWorkersCountDefault is a default value of the workers count to + // process storage rebuild operations in a storage engine. + RebuildWorkersCountDefault = 100 ) // ErrNoShardConfigured is returned when at least 1 shard is required but none are found. @@ -88,3 +91,11 @@ func ShardErrorThreshold(c *config.Config) uint32 { func EngineLowMemoryConsumption(c *config.Config) bool { return config.BoolSafe(c.Sub(subsection), "low_mem") } + +// EngineRebuildWorkersCount returns value of "rebuild_workers_count" config parmeter from "storage" section. +func EngineRebuildWorkersCount(c *config.Config) uint32 { + if v := config.Uint32Safe(c.Sub(subsection), "rebuild_workers_count"); v > 0 { + return v + } + return RebuildWorkersCountDefault +} diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 6b2b372265..185c6394f6 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -38,6 +38,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 0, engineconfig.ShardErrorThreshold(empty)) require.EqualValues(t, engineconfig.ShardPoolSizeDefault, engineconfig.ShardPoolSize(empty)) require.EqualValues(t, mode.ReadWrite, shardconfig.From(empty).Mode()) + require.EqualValues(t, engineconfig.RebuildWorkersCountDefault, engineconfig.EngineRebuildWorkersCount(empty)) }) const path = "../../../../config/example/node" @@ -47,6 +48,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 100, engineconfig.ShardErrorThreshold(c)) require.EqualValues(t, 15, engineconfig.ShardPoolSize(c)) + require.EqualValues(t, uint32(1000), engineconfig.EngineRebuildWorkersCount(c)) err := engineconfig.IterateShards(c, true, func(sc *shardconfig.Config) error { defer func() { diff --git a/config/example/node.env b/config/example/node.env index 9d36b51083..9c8b90d349 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -92,6 +92,7 @@ FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME=10 # Storage engine section FROSTFS_STORAGE_SHARD_POOL_SIZE=15 FROSTFS_STORAGE_SHARD_RO_ERROR_THRESHOLD=100 +FROSTFS_STORAGE_REBUILD_WORKERS_COUNT=1000 ## 0 shard ### Flag to refill Metabase from BlobStor FROSTFS_STORAGE_SHARD_0_RESYNC_METABASE=false diff --git a/config/example/node.json b/config/example/node.json index b008009d6c..c7cac25013 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -137,6 +137,7 @@ "storage": { "shard_pool_size": 15, "shard_ro_error_threshold": 100, + "rebuild_workers_count": 1000, "shard": { "0": { "mode": "read-only", diff --git a/config/example/node.yaml b/config/example/node.yaml index bf92388a26..4cd023f52a 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -116,6 +116,7 @@ storage: # note: shard configuration can be omitted for relay node (see `node.relay`) shard_pool_size: 15 # size of per-shard worker pools used for PUT operations shard_ro_error_threshold: 100 # amount of errors to occur before shard is made read-only (default: 0, ignore errors) + rebuild_workers_count: 1000 # count of rebuild storage concurrent workers shard: default: # section with the default shard parameters diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index c1f21703c3..a0ddbfdeff 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" "sync" + "sync/atomic" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -14,6 +15,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" + "golang.org/x/sync/errgroup" ) var errRebuildInProgress = errors.New("rebuild is in progress, the operation cannot be performed") @@ -55,21 +57,48 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm success = false return res, err } + b.log.Info(logs.BlobovniczaTreeCollectingDBToRebuildSuccess, zap.Int("blobovniczas_to_rebuild", len(dbsToMigrate))) - for _, db := range dbsToMigrate { - b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) - movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage) - res.ObjectsMoved += movedObjects - if err != nil { - b.log.Warn(logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) - success = false + res, err = b.migrateDBs(ctx, dbsToMigrate, prm, res) + if err != nil { + success = false + } + return res, err +} + +func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common.RebuildPrm, res common.RebuildRes) (common.RebuildRes, error) { + eg, ctx := errgroup.WithContext(ctx) + + var movedObjectsAcc atomic.Uint64 + var filesMovedAcc atomic.Uint64 + for _, db := range dbs { + db := db + if err := prm.WorkerLimiter.AcquireWorkSlot(ctx); err != nil { + _ = eg.Wait() + res.FilesRemoved += filesMovedAcc.Load() + res.ObjectsMoved += movedObjectsAcc.Load() return res, err } - b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) - res.FilesRemoved++ + eg.Go(func() error { + defer prm.WorkerLimiter.ReleaseWorkSlot() + + b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) + movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage) + movedObjectsAcc.Add(movedObjects) + if err != nil { + b.log.Warn(logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) + return err + } + b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) + filesMovedAcc.Add(1) + return nil + }) } - return res, nil + err := eg.Wait() + res.FilesRemoved += filesMovedAcc.Load() + res.ObjectsMoved += movedObjectsAcc.Load() + return res, err } func (b *Blobovniczas) getDBsToRebuild(ctx context.Context) ([]string, error) { @@ -133,7 +162,8 @@ func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovn } func (b *Blobovniczas) moveObject(ctx context.Context, source *blobovnicza.Blobovnicza, sourcePath string, - addr oid.Address, data []byte, metaStore common.MetaStorage) error { + addr oid.Address, data []byte, metaStore common.MetaStorage, +) error { startedAt := time.Now() defer func() { b.metrics.ObjectMoved(time.Since(startedAt)) @@ -229,7 +259,8 @@ func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore co } func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blobovnicza, sourcePath string, - move blobovnicza.MoveInfo, metaStore common.MetaStorage) error { + move blobovnicza.MoveInfo, metaStore common.MetaStorage, +) error { targetDB := b.getBlobovnicza(NewIDFromBytes(move.TargetStorageID).Path()) target, err := targetDB.Open() if err != nil { @@ -250,7 +281,7 @@ func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blob } } - if !existsInSource { //object was deleted by Rebuild, need to delete move info + if !existsInSource { // object was deleted by Rebuild, need to delete move info if err = source.DropMoveInfo(ctx, move.Address); err != nil { b.log.Warn(logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", sourcePath), zap.Error(err)) return err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index c9ce564c94..ff86c036ae 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "path/filepath" + "sync" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -147,9 +148,11 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object metaStub := &storageIDUpdateStub{ storageIDs: make(map[oid.Address][]byte), + guard: &sync.Mutex{}, } rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ - MetaStorage: metaStub, + MetaStorage: metaStub, + WorkerLimiter: &rebuildLimiterStub{}, }) require.NoError(t, err) require.Equal(t, uint64(1), rRes.ObjectsMoved) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 00b38f69ab..34006b270e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -101,9 +101,11 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta metaStub := &storageIDUpdateStub{ storageIDs: storageIDs, + guard: &sync.Mutex{}, } var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub + rPrm.WorkerLimiter = &rebuildLimiterStub{} rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 @@ -121,12 +123,21 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta } type storageIDUpdateStub struct { + guard *sync.Mutex storageIDs map[oid.Address][]byte updatedCount uint64 } func (s *storageIDUpdateStub) UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error { + s.guard.Lock() + defer s.guard.Unlock() + s.storageIDs[addr] = storageID s.updatedCount++ return nil } + +type rebuildLimiterStub struct{} + +func (s *rebuildLimiterStub) AcquireWorkSlot(context.Context) error { return nil } +func (s *rebuildLimiterStub) ReleaseWorkSlot() {} diff --git a/pkg/local_object_storage/blobstor/common/rebuild.go b/pkg/local_object_storage/blobstor/common/rebuild.go index 896ecbb339..9f629ef8cc 100644 --- a/pkg/local_object_storage/blobstor/common/rebuild.go +++ b/pkg/local_object_storage/blobstor/common/rebuild.go @@ -12,9 +12,15 @@ type RebuildRes struct { } type RebuildPrm struct { - MetaStorage MetaStorage + MetaStorage MetaStorage + WorkerLimiter ConcurrentWorkersLimiter } type MetaStorage interface { UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error } + +type ConcurrentWorkersLimiter interface { + AcquireWorkSlot(ctx context.Context) error + ReleaseWorkSlot() +} diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go index 882381dcff..101c60752d 100644 --- a/pkg/local_object_storage/blobstor/rebuild.go +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -13,12 +13,18 @@ type StorageIDUpdate interface { UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error } -func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate) error { +type ConcurrentWorkersLimiter interface { + AcquireWorkSlot(ctx context.Context) error + ReleaseWorkSlot() +} + +func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter ConcurrentWorkersLimiter) error { var summary common.RebuildRes var rErr error for _, storage := range b.storage { res, err := storage.Storage.Rebuild(ctx, common.RebuildPrm{ - MetaStorage: upd, + MetaStorage: upd, + WorkerLimiter: limiter, }) summary.FilesRemoved += res.FilesRemoved summary.ObjectsMoved += res.ObjectsMoved diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index e312e9f0df..026a7c336f 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -38,6 +38,7 @@ type StorageEngine struct { err error } evacuateLimiter *evacuationLimiter + rebuildLimiter *rebuildLimiter } type shardWrapper struct { @@ -215,13 +216,15 @@ type cfg struct { shardPoolSize uint32 lowMem bool + + rebuildWorkersCount uint32 } func defaultCfg() *cfg { return &cfg{ - log: &logger.Logger{Logger: zap.L()}, - - shardPoolSize: 20, + log: &logger.Logger{Logger: zap.L()}, + shardPoolSize: 20, + rebuildWorkersCount: 100, } } @@ -240,6 +243,7 @@ func New(opts ...Option) *StorageEngine { closeCh: make(chan struct{}), setModeCh: make(chan setModeRequest), evacuateLimiter: &evacuationLimiter{}, + rebuildLimiter: newRebuildLimiter(c.rebuildWorkersCount), } } @@ -277,3 +281,10 @@ func WithLowMemoryConsumption(lowMemCons bool) Option { c.lowMem = lowMemCons } } + +// WithRebuildWorkersCount returns an option to set the count of concurrent rebuild workers. +func WithRebuildWorkersCount(count uint32) Option { + return func(c *cfg) { + c.rebuildWorkersCount = count + } +} diff --git a/pkg/local_object_storage/engine/rebuild_limiter.go b/pkg/local_object_storage/engine/rebuild_limiter.go new file mode 100644 index 0000000000..28b02b0a34 --- /dev/null +++ b/pkg/local_object_storage/engine/rebuild_limiter.go @@ -0,0 +1,26 @@ +package engine + +import "context" + +type rebuildLimiter struct { + semaphore chan struct{} +} + +func newRebuildLimiter(workersCount uint32) *rebuildLimiter { + return &rebuildLimiter{ + semaphore: make(chan struct{}, workersCount), + } +} + +func (l *rebuildLimiter) AcquireWorkSlot(ctx context.Context) error { + select { + case l.semaphore <- struct{}{}: + return nil + case <-ctx.Done(): + return ctx.Err() + } +} + +func (l *rebuildLimiter) ReleaseWorkSlot() { + <-l.semaphore +} diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 5d7fb598e4..7e3e85e81c 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -118,6 +118,7 @@ func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (* shard.WithExpiredLocksCallback(e.processExpiredLocks), shard.WithDeletedLockCallback(e.processDeletedLocks), shard.WithReportErrorFunc(e.reportShardErrorBackground), + shard.WithRebuildWorkerLimiter(e.rebuildLimiter), )...) if err := sh.UpdateID(ctx); err != nil { diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index a988683ad9..f103ebc2ba 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -162,7 +162,7 @@ func (s *Shard) Init(ctx context.Context) error { s.gc.init(ctx) - s.rb = newRebuilder() + s.rb = newRebuilder(s.rebuildLimiter) s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) return nil diff --git a/pkg/local_object_storage/shard/rebuild_limiter.go b/pkg/local_object_storage/shard/rebuild_limiter.go new file mode 100644 index 0000000000..efc21837c3 --- /dev/null +++ b/pkg/local_object_storage/shard/rebuild_limiter.go @@ -0,0 +1,13 @@ +package shard + +import "context" + +type RebuildWorkerLimiter interface { + AcquireWorkSlot(ctx context.Context) error + ReleaseWorkSlot() +} + +type noopRebuildLimiter struct{} + +func (l *noopRebuildLimiter) AcquireWorkSlot(context.Context) error { return nil } +func (l *noopRebuildLimiter) ReleaseWorkSlot() {} diff --git a/pkg/local_object_storage/shard/rebuilder.go b/pkg/local_object_storage/shard/rebuilder.go index a636fceb01..f18573c57c 100644 --- a/pkg/local_object_storage/shard/rebuilder.go +++ b/pkg/local_object_storage/shard/rebuilder.go @@ -14,16 +14,18 @@ import ( ) type rebuilder struct { - mtx *sync.Mutex - wg *sync.WaitGroup - cancel func() + mtx *sync.Mutex + wg *sync.WaitGroup + cancel func() + limiter RebuildWorkerLimiter } -func newRebuilder() *rebuilder { +func newRebuilder(l RebuildWorkerLimiter) *rebuilder { return &rebuilder{ - mtx: &sync.Mutex{}, - wg: &sync.WaitGroup{}, - cancel: nil, + mtx: &sync.Mutex{}, + wg: &sync.WaitGroup{}, + cancel: nil, + limiter: l, } } @@ -45,7 +47,7 @@ func (r *rebuilder) start(ctx context.Context, bs *blobstor.BlobStor, mb *meta.D defer r.wg.Done() log.Info(logs.BlobstoreRebuildStarted) - if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}); err != nil { + if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, r.limiter); err != nil { log.Warn(logs.FailedToRebuildBlobstore, zap.Error(err)) } else { log.Info(logs.BlobstoreRebuildCompletedSuccessfully) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 915feccb47..56c6aee1f3 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -127,6 +127,8 @@ type cfg struct { metricsWriter MetricsWriter reportErrorFunc func(selfID string, message string, err error) + + rebuildLimiter RebuildWorkerLimiter } func defaultCfg() *cfg { @@ -135,6 +137,7 @@ func defaultCfg() *cfg { log: &logger.Logger{Logger: zap.L()}, gcCfg: defaultGCCfg(), reportErrorFunc: func(string, string, error) {}, + rebuildLimiter: &noopRebuildLimiter{}, } } @@ -372,6 +375,14 @@ func WithExpiredCollectorWorkerCount(count int) Option { } } +// WithRebuildWorkerLimiter return option to set concurrent +// workers count of storage rebuild operation. +func WithRebuildWorkerLimiter(l RebuildWorkerLimiter) Option { + return func(c *cfg) { + c.rebuildLimiter = l + } +} + func (s *Shard) fillInfo() { s.cfg.info.MetaBaseInfo = s.metaBase.DumpInfo() s.cfg.info.BlobStorInfo = s.blobStor.DumpInfo() From c6a739e7467bc0fbbcdb1f813b38d1387f95d2c8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Oct 2023 16:01:35 +0300 Subject: [PATCH 0190/1413] [#661] blobovniczatree: Make Rebuild concurrent for objects Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/option.go | 9 ++ .../blobstor/blobovniczatree/rebuild.go | 98 +++++++++++-------- .../blobstor/blobovniczatree/rebuild_test.go | 6 +- 3 files changed, 72 insertions(+), 41 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index f1eb1eb8e1..93dc487ef1 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -25,6 +25,7 @@ type cfg struct { metrics Metrics waitBeforeDropDB time.Duration blzInitWorkerCount int + blzMoveBatchSize int } type Option func(*cfg) @@ -36,6 +37,7 @@ const ( defaultBlzShallowWidth = 16 defaultWaitBeforeDropDB = 10 * time.Second defaultBlzInitWorkerCount = 5 + defaulBlzMoveBatchSize = 10000 ) func initConfig(c *cfg) { @@ -49,6 +51,7 @@ func initConfig(c *cfg) { metrics: &noopMetrics{}, waitBeforeDropDB: defaultWaitBeforeDropDB, blzInitWorkerCount: defaultBlzInitWorkerCount, + blzMoveBatchSize: defaulBlzMoveBatchSize, } } @@ -119,6 +122,12 @@ func WithWaitBeforeDropDB(t time.Duration) Option { } } +func WithMoveBatchSize(v int) Option { + return func(c *cfg) { + c.blzMoveBatchSize = v + } +} + // WithInitWorkerCount sets maximum workers count to init blobovnicza tree. // // Negative or zero value means no limit. diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index a0ddbfdeff..c7e44fdb35 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -1,6 +1,7 @@ package blobovniczatree import ( + "bytes" "context" "errors" "os" @@ -18,7 +19,10 @@ import ( "golang.org/x/sync/errgroup" ) -var errRebuildInProgress = errors.New("rebuild is in progress, the operation cannot be performed") +var ( + errRebuildInProgress = errors.New("rebuild is in progress, the operation cannot be performed") + errBatchFull = errors.New("batch full") +) func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (common.RebuildRes, error) { if b.readOnly { @@ -67,38 +71,18 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm } func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common.RebuildPrm, res common.RebuildRes) (common.RebuildRes, error) { - eg, ctx := errgroup.WithContext(ctx) - - var movedObjectsAcc atomic.Uint64 - var filesMovedAcc atomic.Uint64 for _, db := range dbs { - db := db - if err := prm.WorkerLimiter.AcquireWorkSlot(ctx); err != nil { - _ = eg.Wait() - res.FilesRemoved += filesMovedAcc.Load() - res.ObjectsMoved += movedObjectsAcc.Load() + b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) + movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage, prm.WorkerLimiter) + res.ObjectsMoved += movedObjects + if err != nil { + b.log.Warn(logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) return res, err } - eg.Go(func() error { - defer prm.WorkerLimiter.ReleaseWorkSlot() - - b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) - movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage) - movedObjectsAcc.Add(movedObjects) - if err != nil { - b.log.Warn(logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) - return err - } - b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) - filesMovedAcc.Add(1) - return nil - }) + b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) + res.FilesRemoved++ } - - err := eg.Wait() - res.FilesRemoved += filesMovedAcc.Load() - res.ObjectsMoved += movedObjectsAcc.Load() - return res, err + return res, nil } func (b *Blobovniczas) getDBsToRebuild(ctx context.Context) ([]string, error) { @@ -122,7 +106,7 @@ func (b *Blobovniczas) getDBsToRebuild(ctx context.Context) ([]string, error) { return result, nil } -func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage) (uint64, error) { +func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) { shDB := b.getBlobovnicza(path) blz, err := shDB.Open() if err != nil { @@ -136,7 +120,7 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M shDB.Close() }() - migratedObjects, err := b.moveObjects(ctx, blz, shDB.SystemPath(), meta) + migratedObjects, err := b.moveObjects(ctx, blz, shDB.SystemPath(), meta, limiter) if err != nil { return migratedObjects, err } @@ -144,21 +128,57 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M return migratedObjects, err } -func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, blzPath string, meta common.MetaStorage) (uint64, error) { - var result uint64 +func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, blzPath string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) { + var result atomic.Uint64 + batch := make(map[oid.Address][]byte) var prm blobovnicza.IteratePrm prm.DecodeAddresses() prm.SetHandler(func(ie blobovnicza.IterationElement) error { - e := b.moveObject(ctx, blz, blzPath, ie.Address(), ie.ObjectData(), meta) - if e == nil { - result++ + batch[ie.Address()] = bytes.Clone(ie.ObjectData()) + if len(batch) == b.blzMoveBatchSize { + return errBatchFull } - return e + return nil }) - _, err := blz.Iterate(ctx, prm) - return result, err + for { + _, err := blz.Iterate(ctx, prm) + if err != nil && !errors.Is(err, errBatchFull) { + return result.Load(), err + } + + if len(batch) == 0 { + break + } + + eg, egCtx := errgroup.WithContext(ctx) + + for addr, data := range batch { + addr := addr + data := data + + if err := limiter.AcquireWorkSlot(egCtx); err != nil { + _ = eg.Wait() + return result.Load(), err + } + eg.Go(func() error { + defer limiter.ReleaseWorkSlot() + err := b.moveObject(egCtx, blz, blzPath, addr, data, meta) + if err == nil { + result.Add(1) + } + return err + }) + } + if err := eg.Wait(); err != nil { + return result.Load(), err + } + + batch = make(map[oid.Address][]byte) + } + + return result.Load(), nil } func (b *Blobovniczas) moveObject(ctx context.Context, source *blobovnicza.Blobovnicza, sourcePath string, diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 34006b270e..921515a6ab 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -48,7 +48,8 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta WithRootPath(dir), WithBlobovniczaSize(100*1024*1024), WithWaitBeforeDropDB(0), - WithOpenedCacheSize(1000)) + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) require.NoError(t, b.Open(false)) require.NoError(t, b.Init()) @@ -87,7 +88,8 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta WithRootPath(dir), WithBlobovniczaSize(100*1024*1024), WithWaitBeforeDropDB(0), - WithOpenedCacheSize(1000)) + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) require.NoError(t, b.Open(false)) require.NoError(t, b.Init()) From 2407e5f5ff2399078a984d2e031bf3cefef64053 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Oct 2023 18:22:53 +0300 Subject: [PATCH 0191/1413] [#661] blobovniczatree: Do not sort DB's and indicies Put stores object to next active DB, so there is no need to sort DBs. In addition, it adds unnecessary DB openings. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobstor/blobovniczatree/iterate.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 5115439b1b..92014fd558 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -134,7 +134,9 @@ func (b *Blobovniczas) iterateSorted(ctx context.Context, addr *oid.Address, cur } indices := indexSlice(levelWidth) - hrw.SortSliceByValue(indices, addressHash(addr, filepath.Join(curPath...))) + if !isLeafLevel { + hrw.SortSliceByValue(indices, addressHash(addr, filepath.Join(curPath...))) + } exec := uint64(len(curPath)) == execDepth @@ -249,7 +251,6 @@ func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path st } if len(dbIdxs) > 0 { - hrw.SortSliceByValue(dbIdxs, addressHash(&addr, path)) for _, dbIdx := range dbIdxs { dbPath := filepath.Join(path, u64ToHexStringExt(dbIdx)) stop, err := f(dbPath) From 8bbfb2df4340faea12cca59c0b9f219babc58d6c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Oct 2023 18:33:03 +0300 Subject: [PATCH 0192/1413] [#661] blobovniczatree: Pass object size limit from config If actual small object size value lower than default object size limit, then unnecessary buckets created. If actual small object size value greated than default object size limit, then error happens. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 941aa0d0a4..a0d5fba928 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -803,6 +803,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize), blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), blobovniczatree.WithLogger(c.log), + blobovniczatree.WithObjectSizeLimit(shCfg.smallSizeObjectLimit), } if c.metricsCollector != nil { From 8911656b1a03fdd30fee352e70161d451f399d9f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 11 Oct 2023 09:23:55 +0300 Subject: [PATCH 0193/1413] [#661] metrcis: Add rebuild percent metric Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/metrics.go | 2 ++ .../blobstor/blobovniczatree/rebuild.go | 5 +++++ .../metrics/blobovnicza.go | 4 ++++ pkg/metrics/blobovnicza.go | 19 +++++++++++++++++++ 4 files changed, 30 insertions(+) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go b/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go index ee0326bcfb..ed05f8772c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go @@ -23,6 +23,7 @@ type Metrics interface { SetRebuildStatus(status string) ObjectMoved(d time.Duration) + SetRebuildPercent(value uint32) Delete(d time.Duration, success, withStorageID bool) Exists(d time.Duration, success, withStorageID bool) @@ -38,6 +39,7 @@ func (m *noopMetrics) SetParentID(string) {} func (m *noopMetrics) SetMode(bool) {} func (m *noopMetrics) Close() {} func (m *noopMetrics) SetRebuildStatus(string) {} +func (m *noopMetrics) SetRebuildPercent(uint32) {} func (m *noopMetrics) ObjectMoved(time.Duration) {} func (m *noopMetrics) Delete(time.Duration, bool, bool) {} func (m *noopMetrics) Exists(time.Duration, bool, bool) {} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index c7e44fdb35..d65ca43f87 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -30,6 +30,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm } b.metrics.SetRebuildStatus(rebuildStatusRunning) + b.metrics.SetRebuildPercent(0) success := true defer func() { if success { @@ -71,6 +72,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm } func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common.RebuildPrm, res common.RebuildRes) (common.RebuildRes, error) { + var completedDBCount uint32 for _, db := range dbs { b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage, prm.WorkerLimiter) @@ -81,7 +83,10 @@ func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common. } b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) res.FilesRemoved++ + completedDBCount++ + b.metrics.SetRebuildPercent((100 * completedDBCount) / uint32(len(dbs))) } + b.metrics.SetRebuildPercent(100) return res, nil } diff --git a/pkg/local_object_storage/metrics/blobovnicza.go b/pkg/local_object_storage/metrics/blobovnicza.go index 3d751ba3f4..3a92a7bc78 100644 --- a/pkg/local_object_storage/metrics/blobovnicza.go +++ b/pkg/local_object_storage/metrics/blobovnicza.go @@ -46,6 +46,10 @@ func (m *blobovniczaTreeMetrics) SetRebuildStatus(status string) { m.m.BlobovniczaTreeRebuildStatus(m.shardID, m.path, status) } +func (m *blobovniczaTreeMetrics) SetRebuildPercent(value uint32) { + m.m.BlobovniczaTreeRebuildPercent(m.shardID, m.path, value) +} + func (m *blobovniczaTreeMetrics) ObjectMoved(d time.Duration) { m.m.BlobovniczaTreeObjectMoved(m.shardID, m.path, d) } diff --git a/pkg/metrics/blobovnicza.go b/pkg/metrics/blobovnicza.go index ddeeb406cf..f3a14a96e9 100644 --- a/pkg/metrics/blobovnicza.go +++ b/pkg/metrics/blobovnicza.go @@ -25,6 +25,7 @@ type BlobobvnizcaMetrics interface { DecOpenBlobovniczaCount(shardID, path string) BlobovniczaTreeRebuildStatus(shardID, path, status string) + BlobovniczaTreeRebuildPercent(shardID, path string, value uint32) BlobovniczaTreeObjectMoved(shardID, path string, d time.Duration) } @@ -38,6 +39,7 @@ type blobovnicza struct { treeOpenCounter *prometheus.GaugeVec treeObjectMoveDuration *prometheus.HistogramVec treeRebuildStatus *shardIDPathModeValue + treeRebuildPercent *prometheus.GaugeVec } func newBlobovnicza() *blobovnicza { @@ -87,6 +89,12 @@ func newBlobovnicza() *blobovnicza { Help: "Accumulated Blobovnicza tree object move duration", }, []string{shardIDLabel, pathLabel}), treeRebuildStatus: newShardIDPathMode(blobovniczaTreeSubSystem, "rebuild_status", "Blobovnicza tree rebuild status"), + treeRebuildPercent: metrics.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: blobovniczaTreeSubSystem, + Name: "rebuild_complete_percent", + Help: "Percent of rebuild completeness", + }, []string{shardIDLabel, pathLabel}), } } @@ -112,6 +120,10 @@ func (b *blobovnicza) CloseBlobobvnizcaTree(shardID, path string) { shardIDLabel: shardID, pathLabel: path, }) + b.treeRebuildPercent.DeletePartialMatch(prometheus.Labels{ + shardIDLabel: shardID, + pathLabel: path, + }) b.treeRebuildStatus.SetMode(shardID, path, undefinedStatus) } @@ -191,3 +203,10 @@ func (b *blobovnicza) BlobovniczaTreeObjectMoved(shardID, path string, d time.Du pathLabel: path, }).Observe(d.Seconds()) } + +func (b *blobovnicza) BlobovniczaTreeRebuildPercent(shardID, path string, value uint32) { + b.treeRebuildPercent.With(prometheus.Labels{ + shardIDLabel: shardID, + pathLabel: path, + }).Set(float64(value)) +} From 5e8c08da3e64d2d8fb64a1bd7c4464ce65582843 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 11 Oct 2023 10:33:42 +0300 Subject: [PATCH 0194/1413] [#661] blobstore: Add address to error logs Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index d65ca43f87..2302661d57 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -333,7 +333,7 @@ func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blob } if err = metaStore.UpdateStorageID(ctx, move.Address, move.TargetStorageID); err != nil { - b.log.Warn(logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err)) + b.log.Warn(logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err), zap.Stringer("address", move.Address)) return err } @@ -414,7 +414,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, } if err = i.MetaStore.UpdateStorageID(ctx, i.Address, targetStorageID.Bytes()); err != nil { - i.B.log.Warn(logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err)) + i.B.log.Warn(logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err), zap.Stringer("address", i.Address)) return true, nil } From e54dc3dc7c9a581328d4766d4d4a4073a5e47f55 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 12 Oct 2023 15:25:16 +0300 Subject: [PATCH 0195/1413] [#698] blobovnicza: Store counter values Blobovnicza initialization take a long time because of bucket Stat() call. So now blobovnicza stores counters in META bucket. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 3 + .../blobovnicza/control.go | 24 ++++ .../blobovnicza/delete.go | 17 ++- .../blobovnicza/exists.go | 3 +- pkg/local_object_storage/blobovnicza/get.go | 2 +- .../blobovnicza/iterate.go | 3 +- pkg/local_object_storage/blobovnicza/meta.go | 103 ++++++++++++++++++ pkg/local_object_storage/blobovnicza/put.go | 4 +- 8 files changed, 152 insertions(+), 7 deletions(-) create mode 100644 pkg/local_object_storage/blobovnicza/meta.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 17ba339946..e1c2cfdeef 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -548,4 +548,7 @@ const ( BlobovniczatreeCouldNotCheckExistenceInTargetDB = "could not check object existence in target blobovnicza" BlobovniczatreeCouldNotGetObjectFromSourceDB = "could not get object from source blobovnicza" BlobovniczatreeCouldNotPutObjectToTargetDB = "could not put object to target blobovnicza" + BlobovniczaSavingCountersToMeta = "saving counters to blobovnicza's meta..." + BlobovniczaSavingCountersToMetaSuccess = "saving counters to blobovnicza's meta completed successfully" + BlobovniczaSavingCountersToMetaFailed = "saving counters to blobovnicza's meta failed" ) diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index c1d7d49a37..2a85313f1d 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -104,7 +104,17 @@ func (b *Blobovnicza) Init() error { func (b *Blobovnicza) initializeCounters() error { var size uint64 var items uint64 + var sizeExists bool + var itemsCountExists bool + err := b.boltDB.View(func(tx *bbolt.Tx) error { + size, sizeExists = hasDataSize(tx) + items, itemsCountExists = hasItemsCount(tx) + + if sizeExists && itemsCountExists { + return nil + } + return b.iterateAllDataBuckets(tx, func(lower, upper uint64, b *bbolt.Bucket) (bool, error) { keysN := uint64(b.Stats().KeyN) size += keysN * upper @@ -115,6 +125,20 @@ func (b *Blobovnicza) initializeCounters() error { if err != nil { return fmt.Errorf("can't determine DB size: %w", err) } + if (!sizeExists || !itemsCountExists) && !b.boltOptions.ReadOnly { + b.log.Debug(logs.BlobovniczaSavingCountersToMeta, zap.Uint64("size", size), zap.Uint64("items", items)) + if err := b.boltDB.Update(func(tx *bbolt.Tx) error { + if err := saveDataSize(tx, size); err != nil { + return err + } + return saveItemsCount(tx, items) + }); err != nil { + b.log.Debug(logs.BlobovniczaSavingCountersToMetaFailed, zap.Uint64("size", size), zap.Uint64("items", items)) + return fmt.Errorf("can't save blobovnicza's size and items count: %w", err) + } + b.log.Debug(logs.BlobovniczaSavingCountersToMetaSuccess, zap.Uint64("size", size), zap.Uint64("items", items)) + } + b.dataSize.Store(size) b.itemsCount.Store(items) b.metrics.AddOpenBlobovniczaSize(size) diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index 0f92ea3f5f..ff3a7a290b 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -51,7 +51,7 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err var dataSize uint64 err := b.boltDB.Update(func(tx *bbolt.Tx) error { - return b.iterateAllDataBuckets(tx, func(lower, upper uint64, buck *bbolt.Bucket) (bool, error) { + err := b.iterateAllDataBuckets(tx, func(lower, upper uint64, buck *bbolt.Bucket) (bool, error) { objData := buck.Get(addrKey) if objData == nil { // object is not in bucket => continue iterating @@ -63,6 +63,21 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err found = true return true, buck.Delete(addrKey) }) + if err != nil { + return err + } + if found { + return updateMeta(tx, func(count, size uint64) (uint64, uint64) { + if count > 0 { + count-- + } + if size >= sizeUpperBound { + size -= sizeUpperBound + } + return count, size + }) + } + return nil }) if err == nil && !found { diff --git a/pkg/local_object_storage/blobovnicza/exists.go b/pkg/local_object_storage/blobovnicza/exists.go index 8cafc72ad8..f7bc84d4af 100644 --- a/pkg/local_object_storage/blobovnicza/exists.go +++ b/pkg/local_object_storage/blobovnicza/exists.go @@ -1,7 +1,6 @@ package blobovnicza import ( - "bytes" "context" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -26,7 +25,7 @@ func (b *Blobovnicza) Exists(ctx context.Context, addr oid.Address) (bool, error err := b.boltDB.View(func(tx *bbolt.Tx) error { return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { - if bytes.Equal(bucketName, incompletedMoveBucketName) { + if isNonDataBucket(bucketName) { return nil } exists = buck.Get(addrKey) != nil diff --git a/pkg/local_object_storage/blobovnicza/get.go b/pkg/local_object_storage/blobovnicza/get.go index 88d8e7e4a1..600323f558 100644 --- a/pkg/local_object_storage/blobovnicza/get.go +++ b/pkg/local_object_storage/blobovnicza/get.go @@ -58,7 +58,7 @@ func (b *Blobovnicza) Get(ctx context.Context, prm GetPrm) (GetRes, error) { if err := b.boltDB.View(func(tx *bbolt.Tx) error { return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { - if bytes.Equal(bucketName, incompletedMoveBucketName) { + if isNonDataBucket(bucketName) { return nil } diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index e19f8f14b2..32b0ccea7a 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -1,7 +1,6 @@ package blobovnicza import ( - "bytes" "context" "fmt" "math" @@ -140,7 +139,7 @@ func (b *Blobovnicza) Iterate(ctx context.Context, prm IteratePrm) (IterateRes, if err := b.boltDB.View(func(tx *bbolt.Tx) error { return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { - if bytes.Equal(bucketName, incompletedMoveBucketName) { + if isNonDataBucket(bucketName) { return nil } return buck.ForEach(func(k, v []byte) error { diff --git a/pkg/local_object_storage/blobovnicza/meta.go b/pkg/local_object_storage/blobovnicza/meta.go new file mode 100644 index 0000000000..8b913f8a7d --- /dev/null +++ b/pkg/local_object_storage/blobovnicza/meta.go @@ -0,0 +1,103 @@ +package blobovnicza + +import ( + "bytes" + "encoding/binary" + + "go.etcd.io/bbolt" +) + +const ( + dataSizeAndItemsCountBufLength = 8 +) + +var ( + metaBucketName = []byte("META") + dataSizeKey = []byte("data_size") + itemsCountKey = []byte("items_count") +) + +func isNonDataBucket(bucketName []byte) bool { + return bytes.Equal(bucketName, incompletedMoveBucketName) || bytes.Equal(bucketName, metaBucketName) +} + +func hasDataSize(tx *bbolt.Tx) (uint64, bool) { + b := tx.Bucket(metaBucketName) + if b == nil { + return 0, false + } + v := b.Get(dataSizeKey) + if v == nil { + return 0, false + } + if len(v) != dataSizeAndItemsCountBufLength { + return 0, false + } + return binary.LittleEndian.Uint64(v), true +} + +func hasItemsCount(tx *bbolt.Tx) (uint64, bool) { + b := tx.Bucket(metaBucketName) + if b == nil { + return 0, false + } + v := b.Get(itemsCountKey) + if v == nil { + return 0, false + } + if len(v) != dataSizeAndItemsCountBufLength { + return 0, false + } + return binary.LittleEndian.Uint64(v), true +} + +func saveDataSize(tx *bbolt.Tx, size uint64) error { + b, err := tx.CreateBucketIfNotExists(metaBucketName) + if err != nil { + return err + } + buf := make([]byte, dataSizeAndItemsCountBufLength) + binary.LittleEndian.PutUint64(buf, size) + return b.Put(dataSizeKey, buf) +} + +func saveItemsCount(tx *bbolt.Tx, count uint64) error { + b, err := tx.CreateBucketIfNotExists(metaBucketName) + if err != nil { + return err + } + buf := make([]byte, dataSizeAndItemsCountBufLength) + binary.LittleEndian.PutUint64(buf, count) + return b.Put(itemsCountKey, buf) +} + +func updateMeta(tx *bbolt.Tx, updateValues func(count, size uint64) (uint64, uint64)) error { + b, err := tx.CreateBucketIfNotExists(metaBucketName) + if err != nil { + return err + } + + var count uint64 + var size uint64 + + v := b.Get(itemsCountKey) + if v != nil { + count = binary.LittleEndian.Uint64(v) + } + + v = b.Get(dataSizeKey) + if v != nil { + size = binary.LittleEndian.Uint64(v) + } + + count, size = updateValues(count, size) + + buf := make([]byte, dataSizeAndItemsCountBufLength) + binary.LittleEndian.PutUint64(buf, size) + if err := b.Put(dataSizeKey, buf); err != nil { + return err + } + + binary.LittleEndian.PutUint64(buf, count) + return b.Put(itemsCountKey, buf) +} diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go index 859f7dbbf9..608739bee8 100644 --- a/pkg/local_object_storage/blobovnicza/put.go +++ b/pkg/local_object_storage/blobovnicza/put.go @@ -73,7 +73,9 @@ func (b *Blobovnicza) Put(ctx context.Context, prm PutPrm) (PutRes, error) { return fmt.Errorf("(%T) could not save object in bucket: %w", b, err) } - return nil + return updateMeta(tx, func(count, size uint64) (uint64, uint64) { + return count + 1, size + upperBound + }) }) if err == nil { b.itemAdded(upperBound) From ad0697adc405bc01eb99127729a5b8e2be3f0e43 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 12 Oct 2023 21:35:08 +0300 Subject: [PATCH 0196/1413] [#661] blobovnicza: Compute size with record size To get more accurate size of blobovnicza use record size (lenght of key + lenght of data). Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobovnicza/control.go | 9 +++++---- pkg/local_object_storage/blobovnicza/delete.go | 10 +++++++--- pkg/local_object_storage/blobovnicza/put.go | 7 ++++--- pkg/local_object_storage/blobovnicza/sizes.go | 5 ++--- pkg/local_object_storage/blobovnicza/sizes_test.go | 2 +- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index 2a85313f1d..dfc4f884ff 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -116,10 +116,11 @@ func (b *Blobovnicza) initializeCounters() error { } return b.iterateAllDataBuckets(tx, func(lower, upper uint64, b *bbolt.Bucket) (bool, error) { - keysN := uint64(b.Stats().KeyN) - size += keysN * upper - items += keysN - return false, nil + return false, b.ForEach(func(k, v []byte) error { + size += uint64(len(k) + len(v)) + items++ + return nil + }) }) }) if err != nil { diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index ff3a7a290b..ab8575ad7a 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -49,6 +49,7 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err var sizeUpperBound uint64 var sizeLowerBound uint64 var dataSize uint64 + var recordSize uint64 err := b.boltDB.Update(func(tx *bbolt.Tx) error { err := b.iterateAllDataBuckets(tx, func(lower, upper uint64, buck *bbolt.Bucket) (bool, error) { @@ -60,6 +61,7 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err dataSize = uint64(len(objData)) sizeLowerBound = lower sizeUpperBound = upper + recordSize = dataSize + uint64(len(addrKey)) found = true return true, buck.Delete(addrKey) }) @@ -71,8 +73,10 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err if count > 0 { count-- } - if size >= sizeUpperBound { - size -= sizeUpperBound + if size >= recordSize { + size -= recordSize + } else { + size = 0 } return count, size }) @@ -90,7 +94,7 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err zap.String("range", stringifyBounds(sizeLowerBound, sizeUpperBound)), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) - b.itemDeleted(sizeUpperBound) + b.itemDeleted(recordSize) } return DeleteRes{}, err diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go index 608739bee8..d15b6e2b25 100644 --- a/pkg/local_object_storage/blobovnicza/put.go +++ b/pkg/local_object_storage/blobovnicza/put.go @@ -56,8 +56,9 @@ func (b *Blobovnicza) Put(ctx context.Context, prm PutPrm) (PutRes, error) { defer span.End() sz := uint64(len(prm.objData)) - bucketName, upperBound := bucketForSize(sz) + bucketName := bucketForSize(sz) key := addressKey(prm.addr) + recordSize := sz + uint64(len(key)) err := b.boltDB.Batch(func(tx *bbolt.Tx) error { buck := tx.Bucket(bucketName) @@ -74,11 +75,11 @@ func (b *Blobovnicza) Put(ctx context.Context, prm PutPrm) (PutRes, error) { } return updateMeta(tx, func(count, size uint64) (uint64, uint64) { - return count + 1, size + upperBound + return count + 1, size + recordSize }) }) if err == nil { - b.itemAdded(upperBound) + b.itemAdded(recordSize) } return PutRes{}, err diff --git a/pkg/local_object_storage/blobovnicza/sizes.go b/pkg/local_object_storage/blobovnicza/sizes.go index cd1f697257..1dff75aede 100644 --- a/pkg/local_object_storage/blobovnicza/sizes.go +++ b/pkg/local_object_storage/blobovnicza/sizes.go @@ -29,9 +29,8 @@ func bucketKeyFromBounds(upperBound uint64) []byte { return buf[:ln] } -func bucketForSize(sz uint64) ([]byte, uint64) { - upperBound := upperPowerOfTwo(sz) - return bucketKeyFromBounds(upperBound), upperBound +func bucketForSize(sz uint64) []byte { + return bucketKeyFromBounds(upperPowerOfTwo(sz)) } func upperPowerOfTwo(v uint64) uint64 { diff --git a/pkg/local_object_storage/blobovnicza/sizes_test.go b/pkg/local_object_storage/blobovnicza/sizes_test.go index d2f576fd3d..01093b8d75 100644 --- a/pkg/local_object_storage/blobovnicza/sizes_test.go +++ b/pkg/local_object_storage/blobovnicza/sizes_test.go @@ -34,7 +34,7 @@ func TestSizes(t *testing.T) { upperBound: 4 * firstBucketBound, }, } { - key, _ := bucketForSize(item.sz) + key := bucketForSize(item.sz) require.Equal(t, bucketKeyFromBounds(item.upperBound), key) } } From db49ad16cc2037bd365f2cd6e7b1c20689fadd06 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 27 Nov 2023 16:01:48 +0300 Subject: [PATCH 0197/1413] [#826] blobovniczatree: Do not create DB's on init Blobovniczas will be created on write requests. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 ++ cmd/frostfs-node/config/engine/config_test.go | 1 + .../shard/blobstor/blobovnicza/config.go | 10 ++++++ config/example/node.env | 1 + config/example/node.json | 3 +- config/example/node.yaml | 1 + .../blobstor/blobovniczatree/control.go | 36 ++++++++++--------- .../blobstor/blobovniczatree/iterate_test.go | 1 + .../blobstor/blobovniczatree/option.go | 8 +++++ 9 files changed, 46 insertions(+), 18 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index a0d5fba928..2d80a4115a 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -183,6 +183,7 @@ type subStorageCfg struct { leafWidth uint64 openedCacheSize int initWorkerCount int + initInAdvance bool } // readConfig fills applicationConfiguration with raw configuration values @@ -302,6 +303,7 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol sCfg.leafWidth = sub.LeafWidth() sCfg.openedCacheSize = sub.OpenedCacheSize() sCfg.initWorkerCount = sub.InitWorkerCount() + sCfg.initInAdvance = sub.InitInAdvance() case fstree.Type: sub := fstreeconfig.From((*config.Config)(storagesCfg[i])) sCfg.depth = sub.Depth() @@ -802,6 +804,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { blobovniczatree.WithBlobovniczaLeafWidth(sRead.leafWidth), blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize), blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), + blobovniczatree.WithInitInAdvance(sRead.initInAdvance), blobovniczatree.WithLogger(c.log), blobovniczatree.WithObjectSizeLimit(shCfg.smallSizeObjectLimit), } diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 185c6394f6..6c7b23cc43 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -100,6 +100,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 50, blz.OpenedCacheSize()) require.EqualValues(t, 10, blz.LeafWidth()) require.EqualValues(t, 10, blz.InitWorkerCount()) + require.EqualValues(t, true, blz.InitInAdvance()) require.Equal(t, "tmp/0/blob", ss[1].Path()) require.EqualValues(t, 0o644, ss[1].Perm()) diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go index 1f7fc77f57..37191cc722 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go @@ -131,3 +131,13 @@ func (x *Config) InitWorkerCount() int { return InitWorkerCountDefault } + +// InitInAdvance returns the value of "init_in_advance" config parameter. +// +// Returns False if the value is not defined or invalid. +func (x *Config) InitInAdvance() bool { + return config.BoolSafe( + (*config.Config)(x), + "init_in_advance", + ) +} diff --git a/config/example/node.env b/config/example/node.env index 9c8b90d349..be16f62bf9 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -127,6 +127,7 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 +FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_IN_ADVANCE=TRUE ### FSTree config FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE=fstree FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH=tmp/0/blob diff --git a/config/example/node.json b/config/example/node.json index c7cac25013..ff38e3894c 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -174,7 +174,8 @@ "width": 4, "opened_cache_capacity": 50, "leaf_width": 10, - "init_worker_count": 10 + "init_worker_count": 10, + "init_in_advance": true }, { "type": "fstree", diff --git a/config/example/node.yaml b/config/example/node.yaml index 4cd023f52a..1355113a3a 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -186,6 +186,7 @@ storage: - type: blobovnicza path: tmp/0/blob/blobovnicza init_worker_count: 10 #count of workers to initialize blobovniczas + init_in_advance: true - type: fstree path: tmp/0/blob # blobstor path diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index f1d78dc542..bd98967cbb 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -82,27 +82,29 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { return err } - err = b.iterateSortedLeaves(egCtx, nil, func(p string) (bool, error) { - if _, found := visited[p]; found { - return false, nil - } - eg.Go(func() error { - shBlz := b.getBlobovniczaWithoutCaching(p) - _, err := shBlz.Open() - if err != nil { - return err + if b.createDBInAdvance { + err = b.iterateSortedLeaves(egCtx, nil, func(p string) (bool, error) { + if _, found := visited[p]; found { + return false, nil } - defer shBlz.Close() + eg.Go(func() error { + shBlz := b.getBlobovniczaWithoutCaching(p) + _, err := shBlz.Open() + if err != nil { + return err + } + defer shBlz.Close() - b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) - return nil + b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) + return nil + }) + return false, nil }) - return false, nil - }) - if err != nil { - _ = eg.Wait() - return err + if err != nil { + _ = eg.Wait() + return err + } } return eg.Wait() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go index 91fa27dd0f..c322fa7a38 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go @@ -16,6 +16,7 @@ func TestIterateSortedLeavesAndDBPathsAreSame(t *testing.T) { WithBlobovniczaShallowWidth(5), WithRootPath(t.TempDir()), ) + blz.createDBInAdvance = true require.NoError(t, blz.Open(false)) require.NoError(t, blz.Init()) defer func() { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index 93dc487ef1..d36074dc8b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -26,6 +26,7 @@ type cfg struct { waitBeforeDropDB time.Duration blzInitWorkerCount int blzMoveBatchSize int + createDBInAdvance bool } type Option func(*cfg) @@ -139,3 +140,10 @@ func WithInitWorkerCount(v int) Option { c.blzInitWorkerCount = v } } + +// WithInitInAdvance returns an option to create blobovnicza tree DB's in advance. +func WithInitInAdvance(v bool) Option { + return func(c *cfg) { + c.createDBInAdvance = v + } +} From 39060382a1a0eb6233460775b8b03d641a6f6638 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Tue, 5 Dec 2023 12:11:28 +0300 Subject: [PATCH 0198/1413] [#842] control: Recieve target in gRPC methods for APE managing * Introduce Target type and pass it to all gRPC methods for APE chain managing instead CID. Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 11 +- cmd/frostfs-cli/modules/control/get_rule.go | 11 +- cmd/frostfs-cli/modules/control/list_rules.go | 9 +- .../modules/control/remove_rule.go | 11 +- pkg/services/control/server/policy_engine.go | 56 +- pkg/services/control/service.pb.go | 478 +++++++++--------- pkg/services/control/service.proto | 22 +- pkg/services/control/service_frostfs.pb.go | 16 +- pkg/services/control/types.pb.go | 230 +++++++-- pkg/services/control/types.proto | 17 + pkg/services/control/types_frostfs.pb.go | 33 ++ 11 files changed, 578 insertions(+), 316 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index f57823ed32..ca92200091 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/sha256" "encoding/json" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -13,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -60,10 +62,15 @@ func addRule(cmd *cobra.Command, _ []string) { cmd.Println("Container ID: " + cidStr) cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, serializedChain)) + name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) + req := &control.AddChainLocalOverrideRequest{ Body: &control.AddChainLocalOverrideRequest_Body{ - ContainerId: rawCID, - Chain: serializedChain, + Target: &control.ChainTarget{ + Type: control.ChainTarget_CONTAINER, + Name: name, + }, + Chain: serializedChain, }, } diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 0c34a696eb..962ef179ba 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -2,6 +2,7 @@ package control import ( "crypto/sha256" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -10,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -32,10 +34,15 @@ func getRule(cmd *cobra.Command, _ []string) { chainID, _ := cmd.Flags().GetString(chainIDFlag) + name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) + req := &control.GetChainLocalOverrideRequest{ Body: &control.GetChainLocalOverrideRequest_Body{ - ContainerId: rawCID, - ChainId: chainID, + Target: &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_CONTAINER, + }, + ChainId: chainID, }, } diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index 6a0879d0e6..c1e47f4832 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -2,6 +2,7 @@ package control import ( "crypto/sha256" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -10,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -30,9 +32,14 @@ func listRules(cmd *cobra.Command, _ []string) { rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) + name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) + req := &control.ListChainLocalOverridesRequest{ Body: &control.ListChainLocalOverridesRequest_Body{ - ContainerId: rawCID, + Target: &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_CONTAINER, + }, }, } diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index de064536ba..c3f4aeb0cb 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -2,6 +2,7 @@ package control import ( "crypto/sha256" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -9,6 +10,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -35,10 +37,15 @@ func removeRule(cmd *cobra.Command, _ []string) { chainID, _ := cmd.Flags().GetString(chainIDFlag) + name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) + req := &control.RemoveChainLocalOverrideRequest{ Body: &control.RemoveChainLocalOverrideRequest_Body{ - ContainerId: rawCID, - ChainId: chainID, + Target: &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_CONTAINER, + }, + ChainId: chainID, }, } diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 8565cd9c17..1c09de9188 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -14,13 +15,36 @@ import ( "google.golang.org/grpc/status" ) +// extractCID extracts CID from the schema's pattern. +// TODO (aarifullin): This is temporary solution should be replaced by +// resource name validation. +func extractCID(resource string) (cid.ID, error) { + var cidStr string + + // Sscanf requires to make tokens delimited by spaces. + pattern := strings.Replace(nativeschema.ResourceFormatRootContainerObjects, "/", " ", -1) + resource = strings.Replace(resource, "/", " ", -1) + + if _, err := fmt.Sscanf(resource, pattern, &cidStr); err != nil { + err = fmt.Errorf("could not parse the target name '%s' to CID: %w", resource, err) + return cid.ID{}, err + } + var cid cid.ID + err := cid.DecodeString(cidStr) + return cid, err +} + func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainLocalOverrideRequest) (*control.AddChainLocalOverrideResponse, error) { if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) } - var cid cid.ID - err := cid.Decode(req.GetBody().GetContainerId()) + target := req.GetBody().GetTarget() + if target.Type != control.ChainTarget_CONTAINER { + return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) + } + + cid, err := extractCID(target.GetName()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -37,7 +61,9 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL s.apeChainCounter.Add(1) // TODO (aarifullin): the such chain id is not well-designed yet. - chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) + if chain.ID == "" { + chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) + } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) if _, err = src.LocalStorage().AddOverride(apechain.Ingress, resource, &chain); err != nil { @@ -61,8 +87,12 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL return nil, status.Error(codes.PermissionDenied, err.Error()) } - var cid cid.ID - err := cid.Decode(req.GetBody().GetContainerId()) + target := req.GetBody().GetTarget() + if target.Type != control.ChainTarget_CONTAINER { + return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) + } + + cid, err := extractCID(target.GetName()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -95,8 +125,12 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha return nil, status.Error(codes.PermissionDenied, err.Error()) } - var cid cid.ID - err := cid.Decode(req.GetBody().GetContainerId()) + target := req.GetBody().GetTarget() + if target.Type != control.ChainTarget_CONTAINER { + return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) + } + + cid, err := extractCID(target.GetName()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } @@ -133,8 +167,12 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return nil, status.Error(codes.PermissionDenied, err.Error()) } - var cid cid.ID - err := cid.Decode(req.GetBody().GetContainerId()) + target := req.GetBody().GetTarget() + if target.Type != control.ChainTarget_CONTAINER { + return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) + } + + cid, err := extractCID(target.GetName()) if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 346a436640..8b8739aba9 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -3198,9 +3198,11 @@ type AddChainLocalOverrideRequest_Body struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Container id for which the overrides are applied. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // Serialized rule chain. + // Target for which the overrides are applied. + Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` + // Serialized rule chain. If chain ID is left empty + // in the chain, then it will be generated and returned + // in the response. Chain []byte `protobuf:"bytes,2,opt,name=chain,proto3" json:"chain,omitempty"` } @@ -3236,9 +3238,9 @@ func (*AddChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24, 0} } -func (x *AddChainLocalOverrideRequest_Body) GetContainerId() []byte { +func (x *AddChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { if x != nil { - return x.ContainerId + return x.Target } return nil } @@ -3256,6 +3258,8 @@ type AddChainLocalOverrideResponse_Body struct { unknownFields protoimpl.UnknownFields // Chain ID assigned for the added rule chain. + // If chain ID is left empty in the request, then + // it will be generated. ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` } @@ -3303,8 +3307,8 @@ type GetChainLocalOverrideRequest_Body struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Container id for which the overrides are defined. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // Target for which the overrides are applied. + Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` // Chain ID assigned for the added rule chain. ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` } @@ -3341,9 +3345,9 @@ func (*GetChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26, 0} } -func (x *GetChainLocalOverrideRequest_Body) GetContainerId() []byte { +func (x *GetChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { if x != nil { - return x.ContainerId + return x.Target } return nil } @@ -3408,8 +3412,8 @@ type ListChainLocalOverridesRequest_Body struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Container id for which the overrides are defined. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // Target for which the overrides are applied. + Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` } func (x *ListChainLocalOverridesRequest_Body) Reset() { @@ -3444,9 +3448,9 @@ func (*ListChainLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28, 0} } -func (x *ListChainLocalOverridesRequest_Body) GetContainerId() []byte { +func (x *ListChainLocalOverridesRequest_Body) GetTarget() *ChainTarget { if x != nil { - return x.ContainerId + return x.Target } return nil } @@ -3504,8 +3508,8 @@ type RemoveChainLocalOverrideRequest_Body struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Container id for which the overrides are defined. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` + // Target for which the overrides are applied. + Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` // Chain ID assigned for the added rule chain. ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` } @@ -3542,9 +3546,9 @@ func (*RemoveChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} } -func (x *RemoveChainLocalOverrideRequest_Body) GetContainerId() []byte { +func (x *RemoveChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { if x != nil { - return x.ContainerId + return x.Target } return nil } @@ -3905,7 +3909,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xd1, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, @@ -3915,191 +3919,194 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x3f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, + 0x65, 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, + 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, + 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, + 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, + 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xba, 0x01, 0x0a, + 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xd6, 0x01, 0x0a, 0x1c, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x44, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xbf, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x29, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x73, 0x22, 0xdc, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x44, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, - 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x32, 0x9d, 0x0b, - 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, - 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, - 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, - 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, - 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x32, 0x9d, 0x0b, 0x0a, 0x0e, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, + 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, + 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, + 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, + 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, + 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, - 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, - 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, - 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, - 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, - 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, + 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, + 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, + 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, + 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, + 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, - 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, - 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, - 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, + 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, + 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, + 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4189,6 +4196,7 @@ var file_pkg_services_control_service_proto_goTypes = []interface{}{ (HealthStatus)(0), // 69: control.HealthStatus (*ShardInfo)(nil), // 70: control.ShardInfo (ShardMode)(0), // 71: control.ShardMode + (*ChainTarget)(nil), // 72: control.ChainTarget } var file_pkg_services_control_service_proto_depIdxs = []int32{ 33, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body @@ -4263,43 +4271,47 @@ var file_pkg_services_control_service_proto_depIdxs = []int32{ 0, // 69: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status 56, // 70: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration 55, // 71: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 1, // 72: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 3, // 73: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 5, // 74: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 7, // 75: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 9, // 76: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 11, // 77: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 13, // 78: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 19, // 79: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 21, // 80: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 23, // 81: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 15, // 82: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 17, // 83: control.ControlService.Doctor:input_type -> control.DoctorRequest - 25, // 84: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 27, // 85: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 29, // 86: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 31, // 87: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 2, // 88: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 4, // 89: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 6, // 90: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 8, // 91: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 10, // 92: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 12, // 93: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 14, // 94: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 20, // 95: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 22, // 96: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 24, // 97: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 16, // 98: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 18, // 99: control.ControlService.Doctor:output_type -> control.DoctorResponse - 26, // 100: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 28, // 101: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 30, // 102: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 32, // 103: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 88, // [88:104] is the sub-list for method output_type - 72, // [72:88] is the sub-list for method input_type - 72, // [72:72] is the sub-list for extension type_name - 72, // [72:72] is the sub-list for extension extendee - 0, // [0:72] is the sub-list for field type_name + 72, // 72: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 72, // 73: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 72, // 74: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget + 72, // 75: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 1, // 76: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 3, // 77: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 5, // 78: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 7, // 79: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 9, // 80: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 11, // 81: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 13, // 82: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 19, // 83: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 21, // 84: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 23, // 85: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 15, // 86: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 17, // 87: control.ControlService.Doctor:input_type -> control.DoctorRequest + 25, // 88: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 27, // 89: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 29, // 90: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 31, // 91: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 2, // 92: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 4, // 93: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 6, // 94: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 8, // 95: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 10, // 96: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 12, // 97: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 14, // 98: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 20, // 99: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 22, // 100: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 24, // 101: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 16, // 102: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 18, // 103: control.ControlService.Doctor:output_type -> control.DoctorResponse + 26, // 104: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 28, // 105: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 30, // 106: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 32, // 107: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 92, // [92:108] is the sub-list for method output_type + 76, // [76:92] is the sub-list for method input_type + 76, // [76:76] is the sub-list for extension type_name + 76, // [76:76] is the sub-list for extension extendee + 0, // [0:76] is the sub-list for field type_name } func init() { file_pkg_services_control_service_proto_init() } diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index e7d218f20d..cbc3aaf548 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -421,10 +421,12 @@ message StopShardEvacuationResponse { // AddChainLocalOverride request. message AddChainLocalOverrideRequest { message Body { - // Container id for which the overrides are applied. - bytes container_id = 1; + // Target for which the overrides are applied. + ChainTarget target = 1; - // Serialized rule chain. + // Serialized rule chain. If chain ID is left empty + // in the chain, then it will be generated and returned + // in the response. bytes chain = 2; } @@ -437,6 +439,8 @@ message AddChainLocalOverrideRequest { message AddChainLocalOverrideResponse { message Body { // Chain ID assigned for the added rule chain. + // If chain ID is left empty in the request, then + // it will be generated. string chain_id = 1; } @@ -448,8 +452,8 @@ message AddChainLocalOverrideResponse { // GetChainLocalOverride request. message GetChainLocalOverrideRequest { message Body { - // Container id for which the overrides are defined. - bytes container_id = 1; + // Target for which the overrides are applied. + ChainTarget target = 1; // Chain ID assigned for the added rule chain. string chain_id = 2; @@ -475,8 +479,8 @@ message GetChainLocalOverrideResponse { // ListChainLocalOverrides request. message ListChainLocalOverridesRequest { message Body { - // Container id for which the overrides are defined. - bytes container_id = 1; + // Target for which the overrides are applied. + ChainTarget target = 1; } Body body = 1; @@ -498,8 +502,8 @@ message ListChainLocalOverridesResponse { message RemoveChainLocalOverrideRequest { message Body { - // Container id for which the overrides are defined. - bytes container_id = 1; + // Target for which the overrides are applied. + ChainTarget target = 1; // Chain ID assigned for the added rule chain. string chain_id = 2; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 852788a307..e163e54b7a 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2067,7 +2067,7 @@ func (x *AddChainLocalOverrideRequest_Body) StableSize() (size int) { if x == nil { return 0 } - size += proto.BytesSize(1, x.ContainerId) + size += proto.NestedStructureSize(1, x.Target) size += proto.BytesSize(2, x.Chain) return size } @@ -2088,7 +2088,7 @@ func (x *AddChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { buf = make([]byte, x.StableSize()) } var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) offset += proto.BytesMarshal(2, buf[offset:], x.Chain) return buf } @@ -2241,7 +2241,7 @@ func (x *GetChainLocalOverrideRequest_Body) StableSize() (size int) { if x == nil { return 0 } - size += proto.BytesSize(1, x.ContainerId) + size += proto.NestedStructureSize(1, x.Target) size += proto.StringSize(2, x.ChainId) return size } @@ -2262,7 +2262,7 @@ func (x *GetChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { buf = make([]byte, x.StableSize()) } var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) offset += proto.StringMarshal(2, buf[offset:], x.ChainId) return buf } @@ -2415,7 +2415,7 @@ func (x *ListChainLocalOverridesRequest_Body) StableSize() (size int) { if x == nil { return 0 } - size += proto.BytesSize(1, x.ContainerId) + size += proto.NestedStructureSize(1, x.Target) return size } @@ -2435,7 +2435,7 @@ func (x *ListChainLocalOverridesRequest_Body) StableMarshal(buf []byte) []byte { buf = make([]byte, x.StableSize()) } var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) return buf } @@ -2587,7 +2587,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) StableSize() (size int) { if x == nil { return 0 } - size += proto.BytesSize(1, x.ContainerId) + size += proto.NestedStructureSize(1, x.Target) size += proto.StringSize(2, x.ChainId) return size } @@ -2608,7 +2608,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte buf = make([]byte, x.StableSize()) } var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) offset += proto.StringMarshal(2, buf[offset:], x.ChainId) return buf } diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index f031f8043d..8f083d6954 100644 --- a/pkg/services/control/types.pb.go +++ b/pkg/services/control/types.pb.go @@ -199,6 +199,55 @@ func (ShardMode) EnumDescriptor() ([]byte, []int) { return file_pkg_services_control_types_proto_rawDescGZIP(), []int{2} } +type ChainTarget_TargetType int32 + +const ( + ChainTarget_UNDEFINED ChainTarget_TargetType = 0 + ChainTarget_NAMESPACE ChainTarget_TargetType = 1 + ChainTarget_CONTAINER ChainTarget_TargetType = 2 +) + +// Enum value maps for ChainTarget_TargetType. +var ( + ChainTarget_TargetType_name = map[int32]string{ + 0: "UNDEFINED", + 1: "NAMESPACE", + 2: "CONTAINER", + } + ChainTarget_TargetType_value = map[string]int32{ + "UNDEFINED": 0, + "NAMESPACE": 1, + "CONTAINER": 2, + } +) + +func (x ChainTarget_TargetType) Enum() *ChainTarget_TargetType { + p := new(ChainTarget_TargetType) + *p = x + return p +} + +func (x ChainTarget_TargetType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ChainTarget_TargetType) Descriptor() protoreflect.EnumDescriptor { + return file_pkg_services_control_types_proto_enumTypes[3].Descriptor() +} + +func (ChainTarget_TargetType) Type() protoreflect.EnumType { + return &file_pkg_services_control_types_proto_enumTypes[3] +} + +func (x ChainTarget_TargetType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ChainTarget_TargetType.Descriptor instead. +func (ChainTarget_TargetType) EnumDescriptor() ([]byte, []int) { + return file_pkg_services_control_types_proto_rawDescGZIP(), []int{5, 0} +} + // Signature of some message. type Signature struct { state protoimpl.MessageState @@ -555,6 +604,63 @@ func (x *BlobstorInfo) GetType() string { return "" } +// ChainTarget is an object to which local overrides +// are applied. +type ChainTarget struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type ChainTarget_TargetType `protobuf:"varint,1,opt,name=type,proto3,enum=control.ChainTarget_TargetType" json:"type,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` +} + +func (x *ChainTarget) Reset() { + *x = ChainTarget{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_types_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ChainTarget) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ChainTarget) ProtoMessage() {} + +func (x *ChainTarget) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_types_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ChainTarget.ProtoReflect.Descriptor instead. +func (*ChainTarget) Descriptor() ([]byte, []int) { + return file_pkg_services_control_types_proto_rawDescGZIP(), []int{5} +} + +func (x *ChainTarget) GetType() ChainTarget_TargetType { + if x != nil { + return x.Type + } + return ChainTarget_UNDEFINED +} + +func (x *ChainTarget) GetName() string { + if x != nil { + return x.Name + } + return "" +} + // Administrator-defined Attributes of the FrostFS Storage Node. // // `Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8 @@ -608,7 +714,7 @@ type NodeInfo_Attribute struct { func (x *NodeInfo_Attribute) Reset() { *x = NodeInfo_Attribute{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[5] + mi := &file_pkg_services_control_types_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -621,7 +727,7 @@ func (x *NodeInfo_Attribute) String() string { func (*NodeInfo_Attribute) ProtoMessage() {} func (x *NodeInfo_Attribute) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[5] + mi := &file_pkg_services_control_types_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -708,31 +814,40 @@ var file_pkg_services_control_types_proto_rawDesc = []byte{ 0x6d, 0x61, 0x50, 0x61, 0x74, 0x68, 0x22, 0x36, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x4e, - 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, - 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, - 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, - 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, 0x6a, - 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, - 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, - 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, - 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, - 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x43, 0x4f, 0x4e, - 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x2a, 0x6a, 0x0a, 0x09, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x44, - 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, - 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, - 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, - 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, - 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, - 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, - 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, - 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x91, + 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x33, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x50, 0x41, 0x43, + 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, + 0x10, 0x02, 0x2a, 0x4e, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, + 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, + 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, + 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, + 0x10, 0x03, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, + 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, + 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54, + 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, + 0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x2a, 0x6a, + 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, + 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, + 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52, + 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, + 0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, + 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x5f, 0x52, + 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, + 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, + 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, + 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -747,30 +862,33 @@ func file_pkg_services_control_types_proto_rawDescGZIP() []byte { return file_pkg_services_control_types_proto_rawDescData } -var file_pkg_services_control_types_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_pkg_services_control_types_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_pkg_services_control_types_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_pkg_services_control_types_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_pkg_services_control_types_proto_goTypes = []interface{}{ - (NetmapStatus)(0), // 0: control.NetmapStatus - (HealthStatus)(0), // 1: control.HealthStatus - (ShardMode)(0), // 2: control.ShardMode - (*Signature)(nil), // 3: control.Signature - (*NodeInfo)(nil), // 4: control.NodeInfo - (*Netmap)(nil), // 5: control.Netmap - (*ShardInfo)(nil), // 6: control.ShardInfo - (*BlobstorInfo)(nil), // 7: control.BlobstorInfo - (*NodeInfo_Attribute)(nil), // 8: control.NodeInfo.Attribute + (NetmapStatus)(0), // 0: control.NetmapStatus + (HealthStatus)(0), // 1: control.HealthStatus + (ShardMode)(0), // 2: control.ShardMode + (ChainTarget_TargetType)(0), // 3: control.ChainTarget.TargetType + (*Signature)(nil), // 4: control.Signature + (*NodeInfo)(nil), // 5: control.NodeInfo + (*Netmap)(nil), // 6: control.Netmap + (*ShardInfo)(nil), // 7: control.ShardInfo + (*BlobstorInfo)(nil), // 8: control.BlobstorInfo + (*ChainTarget)(nil), // 9: control.ChainTarget + (*NodeInfo_Attribute)(nil), // 10: control.NodeInfo.Attribute } var file_pkg_services_control_types_proto_depIdxs = []int32{ - 8, // 0: control.NodeInfo.attributes:type_name -> control.NodeInfo.Attribute - 0, // 1: control.NodeInfo.state:type_name -> control.NetmapStatus - 4, // 2: control.Netmap.nodes:type_name -> control.NodeInfo - 7, // 3: control.ShardInfo.blobstor:type_name -> control.BlobstorInfo - 2, // 4: control.ShardInfo.mode:type_name -> control.ShardMode - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 10, // 0: control.NodeInfo.attributes:type_name -> control.NodeInfo.Attribute + 0, // 1: control.NodeInfo.state:type_name -> control.NetmapStatus + 5, // 2: control.Netmap.nodes:type_name -> control.NodeInfo + 8, // 3: control.ShardInfo.blobstor:type_name -> control.BlobstorInfo + 2, // 4: control.ShardInfo.mode:type_name -> control.ShardMode + 3, // 5: control.ChainTarget.type:type_name -> control.ChainTarget.TargetType + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_pkg_services_control_types_proto_init() } @@ -840,6 +958,18 @@ func file_pkg_services_control_types_proto_init() { } } file_pkg_services_control_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ChainTarget); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NodeInfo_Attribute); i { case 0: return &v.state @@ -857,8 +987,8 @@ func file_pkg_services_control_types_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_types_proto_rawDesc, - NumEnums: 3, - NumMessages: 6, + NumEnums: 4, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, diff --git a/pkg/services/control/types.proto b/pkg/services/control/types.proto index b34988c2e8..d1bc05e298 100644 --- a/pkg/services/control/types.proto +++ b/pkg/services/control/types.proto @@ -169,3 +169,20 @@ enum ShardMode { // DegradedReadOnly. DEGRADED_READ_ONLY = 4; } + + +// ChainTarget is an object to which local overrides +// are applied. +message ChainTarget { + enum TargetType { + UNDEFINED = 0; + + NAMESPACE = 1; + + CONTAINER = 2; + } + + TargetType type = 1; + + string Name = 2; +} \ No newline at end of file diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index ab246dbdc7..858d85a1c7 100644 --- a/pkg/services/control/types_frostfs.pb.go +++ b/pkg/services/control/types_frostfs.pb.go @@ -229,3 +229,36 @@ func (x *BlobstorInfo) StableMarshal(buf []byte) []byte { offset += proto.StringMarshal(2, buf[offset:], x.Type) return buf } + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ChainTarget) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.EnumSize(1, int32(x.Type)) + size += proto.StringSize(2, x.Name) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ChainTarget) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.EnumMarshal(1, buf[offset:], int32(x.Type)) + offset += proto.StringMarshal(2, buf[offset:], x.Name) + return buf +} From e361e017f37ed878a9be0c225abdb9181e8c7a43 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Tue, 5 Dec 2023 13:26:09 +0300 Subject: [PATCH 0199/1413] [#842] control: Pass target instead resource name * Update policy-engine package version in go.mod, go.sum. * Refactor CheckIfRequestPermitted: pass container target instead container ID. Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- pkg/services/control/server/policy_engine.go | 8 ++++---- pkg/services/object/acl/ape.go | 5 ++++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index aa0f689c13..43ff1648ab 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231128145636-a0a35bf4bf31 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231205092054-2d4a9fc6dcb3 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index 0167d4a51f..bede02d054 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231128145636-a0a35bf4bf31 h1:31tE+hNkHar7IMduhzj8LFY8+LT2EswiVI873MEfZj0= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231128145636-a0a35bf4bf31/go.mod h1:ekrDiIySdYhji5rBNAkxYMztFWMXyC9Q8LVz6gGVDu0= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231205092054-2d4a9fc6dcb3 h1:d4cCtg6vgQ101Qni9FqYaGPkmSJP1ZnEyHYMI+JaTIo= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231205092054-2d4a9fc6dcb3/go.mod h1:ekrDiIySdYhji5rBNAkxYMztFWMXyC9Q8LVz6gGVDu0= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 1c09de9188..cbb6ba803a 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -66,7 +66,7 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - if _, err = src.LocalStorage().AddOverride(apechain.Ingress, resource, &chain); err != nil { + if _, err = src.LocalStorage().AddOverride(apechain.Ingress, engine.ContainerTarget(resource), &chain); err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -103,7 +103,7 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - chain, err := src.LocalStorage().GetOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())) + chain, err := src.LocalStorage().GetOverride(apechain.Ingress, engine.ContainerTarget(resource), apechain.ID(req.GetBody().GetChainId())) if err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -141,7 +141,7 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, resource) + chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, engine.ContainerTarget(resource)) if err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -183,7 +183,7 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove } resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - if err = src.LocalStorage().RemoveOverride(apechain.Ingress, resource, apechain.ID(req.GetBody().GetChainId())); err != nil { + if err = src.LocalStorage().RemoveOverride(apechain.Ingress, engine.ContainerTarget(resource), apechain.ID(req.GetBody().GetChainId())); err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } resp := &control.RemoveChainLocalOverrideResponse{ diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go index 525ed59300..a48bb5c9f0 100644 --- a/pkg/services/object/acl/ape.go +++ b/pkg/services/object/acl/ape.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" ) var errAPEChainNoSource = errors.New("could not get ape chain source for the container") @@ -36,7 +37,9 @@ func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { request := new(Request) request.FromRequestInfo(reqInfo) - status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, "", request) + cnrTarget := getResource(reqInfo).Name() + + status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(cnrTarget), request) if err != nil { return err } From 0f45e3d344da440797800c4adaa3f90f4e7c787b Mon Sep 17 00:00:00 2001 From: aarifullin Date: Mon, 20 Nov 2023 19:35:16 +0300 Subject: [PATCH 0200/1413] [#804] ape: Implement boltdb storage for local overrides Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 39 ++- cmd/frostfs-node/config/node/config.go | 55 +++- cmd/frostfs-node/control.go | 2 +- cmd/frostfs-node/main.go | 6 + cmd/frostfs-node/object.go | 4 +- cmd/frostfs-node/policy_engine.go | 70 ++++-- internal/logs/logs.go | 2 + pkg/ape/chainbase/boltdb.go | 250 +++++++++++++++++++ pkg/ape/chainbase/inmemory.go | 30 +++ pkg/ape/chainbase/interface.go | 22 ++ pkg/ape/chainbase/option.go | 67 +++++ pkg/core/container/storage.go | 8 - pkg/services/control/server/policy_engine.go | 105 ++------ pkg/services/control/server/server.go | 19 +- pkg/services/object/acl/ape.go | 23 +- 15 files changed, 560 insertions(+), 142 deletions(-) create mode 100644 pkg/ape/chainbase/boltdb.go create mode 100644 pkg/ape/chainbase/inmemory.go create mode 100644 pkg/ape/chainbase/interface.go create mode 100644 pkg/ape/chainbase/option.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 2d80a4115a..82b01b563e 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -29,6 +29,7 @@ import ( replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" @@ -68,6 +69,7 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" neogoutil "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" @@ -518,10 +520,7 @@ type cfgObject struct { eaclSource container.EACLSource - // Access policy chain source is used by object service to - // check for operation permissions but this source is also shared with - // control service that dispatches local overrides. - apeChainSource container.AccessPolicyEngineChainSource + cfgAccessPolicyEngine cfgAccessPolicyEngine pool cfgObjectRoutines @@ -542,6 +541,10 @@ type cfgLocalStorage struct { localStorage *engine.StorageEngine } +type cfgAccessPolicyEngine struct { + accessPolicyEngine *accessPolicyEngine +} + type cfgObjectRoutines struct { putRemote *ants.Pool @@ -970,6 +973,34 @@ func initLocalStorage(ctx context.Context, c *cfg) { }) } +func initAccessPolicyEngine(_ context.Context, c *cfg) { + var localOverrideDB chainbase.LocalOverrideDatabase + if nodeconfig.PersistentPolicyRules(c.appCfg).Path() == "" { + c.log.Warn(logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed) + localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase() + } else { + localOverrideDB = chainbase.NewBoltLocalOverrideDatabase( + chainbase.WithLogger(c.log), + chainbase.WithPath(nodeconfig.PersistentPolicyRules(c.appCfg).Path()), + chainbase.WithPerm(nodeconfig.PersistentPolicyRules(c.appCfg).Perm()), + chainbase.WithNoSync(nodeconfig.PersistentPolicyRules(c.appCfg).NoSync()), + ) + } + + morphRuleStorage := inmemory.NewInmemoryMorphRuleChainStorage() + + ape := newAccessPolicyEngine(morphRuleStorage, localOverrideDB) + c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine = ape + + c.onShutdown(func() { + if err := ape.LocalOverrideDatabaseCore().Close(); err != nil { + c.log.Warn(logs.FrostFSNodeAccessPolicyEngineClosingFailure, + zap.Error(err), + ) + } + }) +} + func initObjectPool(cfg *config.Config) (pool cfgObjectRoutines) { var err error diff --git a/cmd/frostfs-node/config/node/config.go b/cmd/frostfs-node/config/node/config.go index 9dfe8ddf4c..ac76ad47e5 100644 --- a/cmd/frostfs-node/config/node/config.go +++ b/cmd/frostfs-node/config/node/config.go @@ -2,6 +2,7 @@ package nodeconfig import ( "fmt" + "io/fs" "os" "strconv" "time" @@ -30,11 +31,18 @@ type NotificationConfig struct { cfg *config.Config } +// PersistentPolicyRulesConfig is a wrapper over "persistent_policy_rules" config section +// which provides access to persistent policy rules storage configuration of node. +type PersistentPolicyRulesConfig struct { + cfg *config.Config +} + const ( - subsection = "node" - persistentSessionsSubsection = "persistent_sessions" - persistentStateSubsection = "persistent_state" - notificationSubsection = "notification" + subsection = "node" + persistentSessionsSubsection = "persistent_sessions" + persistentStateSubsection = "persistent_state" + notificationSubsection = "notification" + persistentPolicyRulesSubsection = "persistent_policy_rules" attributePrefix = "attribute" @@ -245,3 +253,42 @@ func (n NotificationConfig) KeyPath() string { func (n NotificationConfig) CAPath() string { return config.StringSafe(n.cfg, "ca") } + +const ( + // PermDefault is a default permission bits for local override storage file. + PermDefault = 0o644 +) + +// PersistentPolicyRules returns structure that provides access to "persistent_policy_rules" +// subsection of "node" section. +func PersistentPolicyRules(c *config.Config) PersistentPolicyRulesConfig { + return PersistentPolicyRulesConfig{ + c.Sub(subsection).Sub(persistentPolicyRulesSubsection), + } +} + +// Path returns the value of "path" config parameter. +// +// Returns empty string if missing, for compatibility with older configurations. +func (l PersistentPolicyRulesConfig) Path() string { + return config.StringSafe(l.cfg, "path") +} + +// Perm returns the value of "perm" config parameter as a fs.FileMode. +// +// Returns PermDefault if the value is not a positive number. +func (l PersistentPolicyRulesConfig) Perm() fs.FileMode { + p := config.UintSafe((*config.Config)(l.cfg), "perm") + if p == 0 { + p = PermDefault + } + + return fs.FileMode(p) +} + +// NoSync returns the value of "no_sync" config parameter as a bool value. +// +// Returns false if the value is not a boolean. +func (l PersistentPolicyRulesConfig) NoSync() bool { + return config.BoolSafe((*config.Config)(l.cfg), "no_sync") +} diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index 30d6448036..4f5c5d780b 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -51,7 +51,7 @@ func initControlService(c *cfg) { controlSvc.WithTreeService(treeSynchronizer{ c.treeService, }), - controlSvc.WithAPEChainSource(c.cfgObject.apeChainSource), + controlSvc.WithLocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine), ) lis, err := net.Listen("tcp", endpoint) diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index 2791efcefd..d4dfb7e609 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -98,6 +98,12 @@ func initApp(ctx context.Context, c *cfg) { fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Init(ctx)) }) + initAccessPolicyEngine(ctx, c) + initAndLog(c, "access policy engine", func(c *cfg) { + fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Open(ctx)) + fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Init()) + }) + initAndLog(c, "gRPC", initGRPC) initAndLog(c, "netmap", func(c *cfg) { initNetmapService(ctx, c) }) initAndLog(c, "accounting", func(c *cfg) { initAccountingService(ctx, c) }) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 79f492190f..59827179b9 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -157,8 +157,6 @@ func initObjectService(c *cfg) { c.replicator = createReplicator(c, keyStorage, c.bgClientCache) - c.cfgObject.apeChainSource = NewAPESource() - addPolicer(c, keyStorage, c.bgClientCache) traverseGen := util.NewTraverserGenerator(c.netMapSource, c.cfgObject.cnrSource, c) @@ -426,7 +424,7 @@ func createACLServiceV2(c *cfg, splitSvc *objectService.TransportSplitter, irFet c.cfgObject.eaclSource, eaclSDK.NewValidator(), ls), - acl.NewAPEChecker(c.log, c.cfgObject.apeChainSource), + acl.NewAPEChecker(c.log, c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.chainRouter), c.cfgObject.cnrSource, v2.WithLogger(c.log), ) diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index 248cddb111..d04322c2ee 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -3,33 +3,63 @@ package main import ( "sync" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" - "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" ) -type apeChainSourceImpl struct { - mtx sync.Mutex - localChainStorage map[cid.ID]engine.LocalOverrideEngine +type accessPolicyEngine struct { + mtx sync.RWMutex + + chainRouter engine.ChainRouter + + morphChainStorage engine.MorphRuleChainStorage + + localOverrideDatabase chainbase.LocalOverrideDatabase } -func NewAPESource() container.AccessPolicyEngineChainSource { - return &apeChainSourceImpl{ - localChainStorage: make(map[cid.ID]engine.LocalOverrideEngine), +var _ engine.LocalOverrideEngine = (*accessPolicyEngine)(nil) + +func newAccessPolicyEngine( + morphChainStorage engine.MorphRuleChainStorage, + localOverrideDatabase chainbase.LocalOverrideDatabase) *accessPolicyEngine { + return &accessPolicyEngine{ + chainRouter: engine.NewDefaultChainRouterWithLocalOverrides( + morphChainStorage, + localOverrideDatabase, + ), + + morphChainStorage: morphChainStorage, + + localOverrideDatabase: localOverrideDatabase, } } -var _ container.AccessPolicyEngineChainSource = (*apeChainSourceImpl)(nil) +func (a *accessPolicyEngine) IsAllowed(name chain.Name, target engine.RequestTarget, r resource.Request) (status chain.Status, found bool, err error) { + a.mtx.RLock() + defer a.mtx.RUnlock() -func (c *apeChainSourceImpl) GetChainSource(cid cid.ID) (engine.LocalOverrideEngine, error) { - c.mtx.Lock() - defer c.mtx.Unlock() - - s, ok := c.localChainStorage[cid] - if ok { - return s, nil - } - c.localChainStorage[cid] = inmemory.NewInMemoryLocalOverrides() - return c.localChainStorage[cid], nil + return a.chainRouter.IsAllowed(name, target, r) +} + +func (a *accessPolicyEngine) MorphRuleChainStorage() engine.MorphRuleChainStorage { + a.mtx.Lock() + defer a.mtx.Unlock() + + return a.morphChainStorage +} + +func (a *accessPolicyEngine) LocalStorage() engine.LocalOverrideStorage { + a.mtx.Lock() + defer a.mtx.Unlock() + + return a.localOverrideDatabase +} + +func (a *accessPolicyEngine) LocalOverrideDatabaseCore() chainbase.DatabaseCore { + a.mtx.Lock() + defer a.mtx.Unlock() + + return a.localOverrideDatabase } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index e1c2cfdeef..befa7342ad 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -429,7 +429,9 @@ const ( FrostFSNodeFailedToAttachShardToEngine = "failed to attach shard to engine" FrostFSNodeShardAttachedToEngine = "shard attached to engine" FrostFSNodeClosingComponentsOfTheStorageEngine = "closing components of the storage engine..." + FrostFSNodeAccessPolicyEngineClosingFailure = "ape closing failure" FrostFSNodeStorageEngineClosingFailure = "storage engine closing failure" + FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed = "persistent rule storage db path is not set: in-memory will be used" FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully = "all components of the storage engine closed successfully" FrostFSNodeBootstrappingWithTheMaintenanceState = "bootstrapping with the maintenance state" FrostFSNodeBootstrappingWithOnlineState = "bootstrapping with online state" diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go new file mode 100644 index 0000000000..c6cd2c0145 --- /dev/null +++ b/pkg/ape/chainbase/boltdb.go @@ -0,0 +1,250 @@ +package chainbase + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "path/filepath" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "github.com/nspcc-dev/neo-go/pkg/util/slice" + "go.etcd.io/bbolt" +) + +type boltLocalOverrideStorage struct { + *cfg + + db *bbolt.DB +} + +var ( + chainBucket = []byte{0} +) + +var ( + ErrChainBucketNotFound = logicerr.New("chain root bucket has not been found") + + ErrChainNotFound = logicerr.New("chain has not been found") + + ErrGlobalNamespaceBucketNotFound = logicerr.New("global namespace bucket has not been found") + + ErrTargetTypeBucketNotFound = logicerr.New("target type bucket has not been found") + + ErrTargetNameBucketNotFound = logicerr.New("target name bucket has not been found") +) + +// NewBoltLocalOverrideDatabase returns storage wrapper for storing access policy engine +// local overrides. +// +// chain storage (chainBucket): +// -> global namespace bucket (nBucket): +// --> target bucket (tBucket) +// ---> target name (resource) bucket (rBucket): +// +// | Key | Value | +// x---------------------x-------------------x +// | chain id (string) | serialized chain | +// x---------------------x-------------------x +// +//nolint:godot +func NewBoltLocalOverrideDatabase(opts ...Option) LocalOverrideDatabase { + c := defaultCfg() + + for i := range opts { + opts[i](c) + } + + return &boltLocalOverrideStorage{ + cfg: c, + } +} + +func (cs *boltLocalOverrideStorage) Init() error { + return cs.db.Update(func(tx *bbolt.Tx) error { + _, err := tx.CreateBucketIfNotExists(chainBucket) + return err + }) +} + +func (cs *boltLocalOverrideStorage) Open(context.Context) error { + err := util.MkdirAllX(filepath.Dir(cs.path), cs.perm) + if err != nil { + return fmt.Errorf("can't create dir %s for the chain DB: %w", cs.path, err) + } + + opts := *bbolt.DefaultOptions + opts.NoSync = cs.noSync + opts.Timeout = 100 * time.Millisecond + + cs.db, err = bbolt.Open(cs.path, cs.perm, &opts) + if err != nil { + return fmt.Errorf("can't open the chain DB: %w", err) + } + + cs.db.MaxBatchSize = cs.maxBatchSize + cs.db.MaxBatchDelay = cs.maxBatchDelay + + return nil +} + +func (cs *boltLocalOverrideStorage) Close() error { + var err error + if cs.db != nil { + err = cs.db.Close() + } + return err +} + +func getTargetBucket(tx *bbolt.Tx, name chain.Name, target policyengine.Target) (*bbolt.Bucket, error) { + cbucket := tx.Bucket(chainBucket) + if cbucket == nil { + return nil, ErrChainBucketNotFound + } + + nbucket := cbucket.Bucket([]byte(name)) + if nbucket == nil { + return nil, fmt.Errorf("global namespace %s: %w", name, ErrGlobalNamespaceBucketNotFound) + } + + typeBucket := nbucket.Bucket([]byte{byte(target.Type)}) + if typeBucket == nil { + return nil, fmt.Errorf("type bucket '%c': %w", target.Type, ErrTargetTypeBucketNotFound) + } + + rbucket := typeBucket.Bucket([]byte(target.Name)) + if rbucket == nil { + return nil, fmt.Errorf("target name bucket %s: %w", target.Name, ErrTargetNameBucketNotFound) + } + + return rbucket, nil +} + +func getTargetBucketCreateIfEmpty(tx *bbolt.Tx, name chain.Name, target policyengine.Target) (*bbolt.Bucket, error) { + cbucket := tx.Bucket(chainBucket) + if cbucket == nil { + return nil, ErrChainBucketNotFound + } + + nbucket := cbucket.Bucket([]byte(name)) + if nbucket == nil { + var err error + nbucket, err = cbucket.CreateBucket([]byte(name)) + if err != nil { + return nil, fmt.Errorf("could not create a bucket for the global chain name %s: %w", name, err) + } + } + + typeBucket := nbucket.Bucket([]byte{byte(target.Type)}) + if typeBucket == nil { + var err error + typeBucket, err = cbucket.CreateBucket([]byte{byte(target.Type)}) + if err != nil { + return nil, fmt.Errorf("could not create a bucket for the target type '%c': %w", target.Type, err) + } + } + + rbucket := typeBucket.Bucket([]byte(target.Name)) + if rbucket == nil { + var err error + rbucket, err = typeBucket.CreateBucket([]byte(target.Name)) + if err != nil { + return nil, fmt.Errorf("could not create a bucket for the target name %s: %w", target.Name, err) + } + } + + return rbucket, nil +} + +func (cs *boltLocalOverrideStorage) AddOverride(name chain.Name, target policyengine.Target, c *chain.Chain) (chain.ID, error) { + if c.ID == "" { + return "", fmt.Errorf("chain ID is not set") + } + + serializedChain := c.Bytes() + + err := cs.db.Update(func(tx *bbolt.Tx) error { + rbuck, err := getTargetBucketCreateIfEmpty(tx, name, target) + if err != nil { + return err + } + return rbuck.Put([]byte(c.ID), serializedChain) + }) + + return c.ID, err +} + +func (cs *boltLocalOverrideStorage) GetOverride(name chain.Name, target policyengine.Target, chainID chain.ID) (*chain.Chain, error) { + var serializedChain []byte + + if err := cs.db.View(func(tx *bbolt.Tx) error { + rbuck, err := getTargetBucket(tx, name, target) + if err != nil { + return err + } + serializedChain = rbuck.Get([]byte(chainID)) + if serializedChain == nil { + return ErrChainNotFound + } + serializedChain = slice.Copy(serializedChain) + return nil + }); err != nil { + return nil, err + } + + c := &chain.Chain{} + if err := json.Unmarshal(serializedChain, c); err != nil { + return nil, err + } + return c, nil +} + +func (cs *boltLocalOverrideStorage) RemoveOverride(name chain.Name, target policyengine.Target, chainID chain.ID) error { + return cs.db.Update(func(tx *bbolt.Tx) error { + rbuck, err := getTargetBucket(tx, name, target) + if err != nil { + return err + } + return rbuck.Delete([]byte(chainID)) + }) +} + +func (cs *boltLocalOverrideStorage) ListOverrides(name chain.Name, target policyengine.Target) ([]*chain.Chain, error) { + var serializedChains [][]byte + var serializedChain []byte + if err := cs.db.View(func(tx *bbolt.Tx) error { + rbuck, err := getTargetBucket(tx, name, target) + if err != nil { + return err + } + return rbuck.ForEach(func(_, v []byte) error { + serializedChain = slice.Copy(v) + serializedChains = append(serializedChains, serializedChain) + return nil + }) + }); err != nil { + if errors.Is(err, ErrGlobalNamespaceBucketNotFound) || errors.Is(err, ErrTargetNameBucketNotFound) { + return []*chain.Chain{}, nil + } + return nil, err + } + chains := make([]*chain.Chain, 0, len(serializedChains)) + for _, serializedChain = range serializedChains { + c := &chain.Chain{} + if err := json.Unmarshal(serializedChain, c); err != nil { + return nil, err + } + chains = append(chains, c) + } + return chains, nil +} + +func (cs *boltLocalOverrideStorage) DropAllOverrides(name chain.Name) error { + return cs.db.Update(func(tx *bbolt.Tx) error { + return tx.DeleteBucket([]byte(name)) + }) +} diff --git a/pkg/ape/chainbase/inmemory.go b/pkg/ape/chainbase/inmemory.go new file mode 100644 index 0000000000..27712d9598 --- /dev/null +++ b/pkg/ape/chainbase/inmemory.go @@ -0,0 +1,30 @@ +package chainbase + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" +) + +type inmemoryLocalOverrideStorage struct { + engine.LocalOverrideStorage +} + +func NewInmemoryLocalOverrideDatabase() LocalOverrideDatabase { + return &inmemoryLocalOverrideStorage{ + LocalOverrideStorage: inmemory.NewInmemoryLocalStorage(), + } +} + +func (cs *inmemoryLocalOverrideStorage) Init() error { + return nil +} + +func (cs *inmemoryLocalOverrideStorage) Open(_ context.Context) error { + return nil +} + +func (cs *inmemoryLocalOverrideStorage) Close() error { + return nil +} diff --git a/pkg/ape/chainbase/interface.go b/pkg/ape/chainbase/interface.go new file mode 100644 index 0000000000..ee445f22cc --- /dev/null +++ b/pkg/ape/chainbase/interface.go @@ -0,0 +1,22 @@ +package chainbase + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" +) + +// DatabaseCore interface provides methods to initialize and manage local override storage +// as database. +type DatabaseCore interface { + Init() error + Open(context.Context) error + Close() error +} + +// LocalOverrideDatabase interface provides methods to manage local override storage +// as database and as the APE's local override storage. +type LocalOverrideDatabase interface { + DatabaseCore + engine.LocalOverrideStorage +} diff --git a/pkg/ape/chainbase/option.go b/pkg/ape/chainbase/option.go new file mode 100644 index 0000000000..e547701fb0 --- /dev/null +++ b/pkg/ape/chainbase/option.go @@ -0,0 +1,67 @@ +package chainbase + +import ( + "io/fs" + "os" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "go.etcd.io/bbolt" + "go.uber.org/zap" +) + +type Option func(*cfg) + +type cfg struct { + path string + perm fs.FileMode + noSync bool + maxBatchDelay time.Duration + maxBatchSize int + log *logger.Logger +} + +func defaultCfg() *cfg { + return &cfg{ + perm: os.ModePerm, + maxBatchDelay: bbolt.DefaultMaxBatchDelay, + maxBatchSize: bbolt.DefaultMaxBatchSize, + log: &logger.Logger{Logger: zap.L()}, + } +} + +func WithPath(path string) Option { + return func(c *cfg) { + c.path = path + } +} + +func WithPerm(perm fs.FileMode) Option { + return func(c *cfg) { + c.perm = perm + } +} + +func WithNoSync(noSync bool) Option { + return func(c *cfg) { + c.noSync = noSync + } +} + +func WithMaxBatchDelay(maxBatchDelay time.Duration) Option { + return func(c *cfg) { + c.maxBatchDelay = maxBatchDelay + } +} + +func WithMaxBatchSize(maxBatchSize int) Option { + return func(c *cfg) { + c.maxBatchSize = maxBatchSize + } +} + +func WithLogger(l *logger.Logger) Option { + return func(c *cfg) { + c.log = l + } +} diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index cc358b436d..69854f4951 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" ) // Container groups information about the FrostFS container stored in the FrostFS network. @@ -72,10 +71,3 @@ type EACLSource interface { // eACL table is not in source. GetEACL(cid.ID) (*EACL, error) } - -// AccessPolicyEngineChainSource interface provides methods to access and manipulate -// policy engine chain storage. -type AccessPolicyEngineChainSource interface { - // TODO (aarifullin): Better to use simpler interface instead CachedChainStorage. - GetChainSource(cid cid.ID) (engine.LocalOverrideEngine, error) -} diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index cbb6ba803a..7ffa392a86 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -4,34 +4,24 @@ import ( "context" "errors" "fmt" - "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" - nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) -// extractCID extracts CID from the schema's pattern. -// TODO (aarifullin): This is temporary solution should be replaced by -// resource name validation. -func extractCID(resource string) (cid.ID, error) { - var cidStr string - - // Sscanf requires to make tokens delimited by spaces. - pattern := strings.Replace(nativeschema.ResourceFormatRootContainerObjects, "/", " ", -1) - resource = strings.Replace(resource, "/", " ", -1) - - if _, err := fmt.Sscanf(resource, pattern, &cidStr); err != nil { - err = fmt.Errorf("could not parse the target name '%s' to CID: %w", resource, err) - return cid.ID{}, err +func apeTarget(chainTarget *control.ChainTarget) (engine.Target, error) { + switch chainTarget.GetType() { + case control.ChainTarget_CONTAINER: + return engine.ContainerTarget(chainTarget.GetName()), nil + case control.ChainTarget_NAMESPACE: + return engine.NamespaceTarget(chainTarget.GetName()), nil + default: } - var cid cid.ID - err := cid.DecodeString(cidStr) - return cid, err + return engine.Target{}, status.Error(codes.InvalidArgument, + fmt.Errorf("target type is not supported: %s", chainTarget.GetType().String()).Error()) } func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainLocalOverrideRequest) (*control.AddChainLocalOverrideResponse, error) { @@ -39,34 +29,23 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL return nil, status.Error(codes.PermissionDenied, err.Error()) } - target := req.GetBody().GetTarget() - if target.Type != control.ChainTarget_CONTAINER { - return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) - } - - cid, err := extractCID(target.GetName()) - if err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) - } - var chain apechain.Chain - if err = chain.DecodeBytes(req.GetBody().GetChain()); err != nil { + if err := chain.DecodeBytes(req.GetBody().GetChain()); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } - src, err := s.apeChainSrc.GetChainSource(cid) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - s.apeChainCounter.Add(1) // TODO (aarifullin): the such chain id is not well-designed yet. if chain.ID == "" { chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) } - resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - if _, err = src.LocalStorage().AddOverride(apechain.Ingress, engine.ContainerTarget(resource), &chain); err != nil { + target, err := apeTarget(req.GetBody().GetTarget()) + if err != nil { + return nil, err + } + + if _, err = s.localOverrideStorage.LocalStorage().AddOverride(apechain.Ingress, target, &chain); err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -87,23 +66,11 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL return nil, status.Error(codes.PermissionDenied, err.Error()) } - target := req.GetBody().GetTarget() - if target.Type != control.ChainTarget_CONTAINER { - return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) - } - - cid, err := extractCID(target.GetName()) + target, err := apeTarget(req.GetBody().GetTarget()) if err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) + return nil, err } - - src, err := s.apeChainSrc.GetChainSource(cid) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - chain, err := src.LocalStorage().GetOverride(apechain.Ingress, engine.ContainerTarget(resource), apechain.ID(req.GetBody().GetChainId())) + chain, err := s.localOverrideStorage.LocalStorage().GetOverride(apechain.Ingress, target, apechain.ID(req.GetBody().GetChainId())) if err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -125,23 +92,12 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha return nil, status.Error(codes.PermissionDenied, err.Error()) } - target := req.GetBody().GetTarget() - if target.Type != control.ChainTarget_CONTAINER { - return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) - } - - cid, err := extractCID(target.GetName()) + target, err := apeTarget(req.GetBody().GetTarget()) if err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) + return nil, err } - src, err := s.apeChainSrc.GetChainSource(cid) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - chains, err := src.LocalStorage().ListOverrides(apechain.Ingress, engine.ContainerTarget(resource)) + chains, err := s.localOverrideStorage.LocalStorage().ListOverrides(apechain.Ingress, target) if err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } @@ -167,23 +123,12 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return nil, status.Error(codes.PermissionDenied, err.Error()) } - target := req.GetBody().GetTarget() - if target.Type != control.ChainTarget_CONTAINER { - return nil, status.Error(codes.Internal, fmt.Errorf("target type is not supported: %s", target.Type.String()).Error()) - } - - cid, err := extractCID(target.GetName()) + target, err := apeTarget(req.GetBody().GetTarget()) if err != nil { - return nil, status.Error(codes.InvalidArgument, err.Error()) + return nil, err } - src, err := s.apeChainSrc.GetChainSource(cid) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - resource := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - if err = src.LocalStorage().RemoveOverride(apechain.Ingress, engine.ContainerTarget(resource), apechain.ID(req.GetBody().GetChainId())); err != nil { + if err = s.localOverrideStorage.LocalStorage().RemoveOverride(apechain.Ingress, target, apechain.ID(req.GetBody().GetChainId())); err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } resp := &control.RemoveChainLocalOverrideResponse{ diff --git a/pkg/services/control/server/server.go b/pkg/services/control/server/server.go index 48bc85200f..7cfa93f05c 100644 --- a/pkg/services/control/server/server.go +++ b/pkg/services/control/server/server.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" ) // Server is an entity that serves @@ -51,6 +52,14 @@ type NodeState interface { ForceMaintenance() error } +// LocalOverrideStorageDecorator interface provides methods to decorate LocalOverrideEngine +// interface methods. +type LocalOverrideStorageDecorator interface { + // LocalStorage method can be decorated by using sync primitives in the case if the local + // override storage state should be consistent for chain router. + LocalStorage() policyengine.LocalOverrideStorage +} + // Option of the Server's constructor. type Option func(*cfg) @@ -65,7 +74,7 @@ type cfg struct { cnrSrc container.Source - apeChainSrc container.AccessPolicyEngineChainSource + localOverrideStorage LocalOverrideStorageDecorator replicator *replicator.Replicator @@ -160,10 +169,10 @@ func WithTreeService(s TreeService) Option { } } -// WithAPEChainSource returns the option to set access policy engine -// chain source. -func WithAPEChainSource(apeChainSrc container.AccessPolicyEngineChainSource) Option { +// WithLocalOverrideStorage returns the option to set access policy engine +// chain override storage. +func WithLocalOverrideStorage(localOverrideStorage LocalOverrideStorageDecorator) Option { return func(c *cfg) { - c.apeChainSrc = apeChainSrc + c.localOverrideStorage = localOverrideStorage } } diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go index a48bb5c9f0..e2a884c96e 100644 --- a/pkg/services/object/acl/ape.go +++ b/pkg/services/object/acl/ape.go @@ -1,10 +1,8 @@ package acl import ( - "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -12,34 +10,25 @@ import ( policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" ) -var errAPEChainNoSource = errors.New("could not get ape chain source for the container") - type apeCheckerImpl struct { - log *logger.Logger - apeSrc container.AccessPolicyEngineChainSource + log *logger.Logger + chainRouter policyengine.ChainRouter } -func NewAPEChecker(log *logger.Logger, apeSrc container.AccessPolicyEngineChainSource) v2.APEChainChecker { +func NewAPEChecker(log *logger.Logger, chainRouter policyengine.ChainRouter) v2.APEChainChecker { return &apeCheckerImpl{ - log: log, - apeSrc: apeSrc, + log: log, + chainRouter: chainRouter, } } func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { - cnr := reqInfo.ContainerID() - - chainCache, err := c.apeSrc.GetChainSource(cnr) - if err != nil { - return errAPEChainNoSource - } - request := new(Request) request.FromRequestInfo(reqInfo) cnrTarget := getResource(reqInfo).Name() - status, ruleFound, err := chainCache.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(cnrTarget), request) + status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(cnrTarget), request) if err != nil { return err } From 70e0c1e082a0c1b833d8a3106790f015c7c52382 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 5 Dec 2023 11:16:44 +0300 Subject: [PATCH 0201/1413] [#841] ir: Execute `netmap.addPeerIR` only for state `online` Signed-off-by: Anton Nikiforov --- pkg/innerring/processors/netmap/handlers_test.go | 15 +++++++++++++++ pkg/innerring/processors/netmap/process_peers.go | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index 164ee41daf..6a66fe323a 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -144,6 +144,21 @@ func TestAddPeer(t *testing.T) { time.Sleep(10 * time.Millisecond) } + require.Nil(t, nc.notaryInvokes, "invalid notary invokes") + + node.SetOnline() + ev = netmapEvent.AddPeer{ + NodeBytes: node.Marshal(), + Request: &payload.P2PNotaryRequest{ + MainTransaction: &transaction.Transaction{}, + }, + } + proc.handleAddPeer(ev) + + for proc.pool.Running() > 0 { + time.Sleep(10 * time.Millisecond) + } + require.EqualValues(t, []notaryInvoke{ { contract: nc.contractAddress, diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index 96b8c8e970..41e4bfb7ed 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -57,7 +57,12 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { updated := np.netmapSnapshot.touch(keyString, np.epochState.EpochCounter(), nodeInfoBinary) - if updated { + // `processAddPeer` reacts on `AddPeer` notification, `processNewEpoch` - on `NewEpoch`. + // This two notification produces in order - `NewEpoch` -> `AddPeer`. + // But there is no guarantee that code will be executed in the same order. + // That is why we need to perform `addPeerIR` only in case when node is online, + // because in scope of this method, contract set state `ONLINE` for the node. + if updated && nodeInfo.IsOnline() { np.log.Info(logs.NetmapApprovingNetworkMapCandidate, zap.String("key", keyString)) From 46532fb9ce8b20c40646c91cd6e4f19ff4b6f9fc Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 5 Dec 2023 11:18:25 +0300 Subject: [PATCH 0202/1413] [#841] doc: Describe `epoch` Signed-off-by: Anton Nikiforov --- docs/epoch.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 docs/epoch.md diff --git a/docs/epoch.md b/docs/epoch.md new file mode 100644 index 0000000000..2f33dcfd52 --- /dev/null +++ b/docs/epoch.md @@ -0,0 +1,43 @@ +# Epoch + +The main purpose of the `epoch` in `frostfs` environment is to manipulate `netmap`. +Each new epoch, `ir` service trigger revision content of the `netmap` by adding or removing nodes to or from it. +`node` service trigger few internal processes each new epoch - for example, running GC. +Epoch also used in an object lifecycle. + +At the startup, `ir` service initializes an epoch timer which handles new epoch tick. +Epoch timer is a block timer - which means that this timer ticks each block or set of blocks. +The epoch duration stores in the configurable parameter `EpochDuration` in the blockchain. +It is possible to get it via `frostfs-adm`: +```shell +> frostfs-adm morph dump-config -c config.yml -r http://morph-chain.frostfs.devenv:30333 +... +EpochDuration: 240 (int) +... +> +``` +Once epoch timer ticks, `ir` service call method [NewEpoch](https://git.frostfs.info/TrueCloudLab/frostfs-contract/src/commit/a1b61d3949581f4d65b0d32a33d98ba9c193dc2a/netmap/netmap_contract.go#L238) +of the `netmap` contract. Each `ir` instance can do this at the same time, but it is not an issue, +because multiple call of this method with the same set of parameters will give us the same result. + +Utility `frostfs-adm` have a command to trigger new epoch: +```shell +> frostfs-adm morph force-new-epoch -c config.yml -r http://morph-chain.frostfs.devenv:30333 +``` +Command goes directly to the `netmap` contract and call method `NewEpoch`. +Method checks alphabet witness and stores candidates nodes which are not in the `OFFLINE` state as a current netmap. +Then executes method `NewEpoch` in `balance` and `container` contracts. +At the end it produces notification `NewEpoch` which is handled by `node` and `ir` services. + +`ir` handler for `NewEpoch` updates internal state of the netmap, if it is necessary, updates state of the nodes or +marks for exclusion from netmap in the blockchain. + +`node` handler for `NewEpoch` executes method `addPeer` of the `netmap` contract. +This method do nothing, but produces notification which handled by `ir` service. +`ir` in handler for `AddPeer` may update node state in the netmap if it is necessary. + +At the startup, node bootstraps with state `ONLINE`. From the online state, it is possible to move to `MAINTENANCE` or `OFFLINE`. +Node moved to `OFFLINE` state automatically, when there is no bootstrap request from it for a number of epochs. +This number stored in the `ir` config `netmap_cleaner.threshold`. +From `OFFLINE` state node, once it bootstrapped, moves to `ONLINE`. +`MAINTENANCE` state persists even if node rebooted or unavailable for a few epochs. From d5c9dd3c839b46050519f7efdcc3447906c42f5e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Dec 2023 16:55:12 +0300 Subject: [PATCH 0203/1413] [#852] ape: Use first match for eACL->APE converter Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- internal/ape/converter.go | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 43ff1648ab..3e79f7ff74 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231205092054-2d4a9fc6dcb3 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231211080303-8c673ee4f4af git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index bede02d054..15ae224225 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231205092054-2d4a9fc6dcb3 h1:d4cCtg6vgQ101Qni9FqYaGPkmSJP1ZnEyHYMI+JaTIo= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231205092054-2d4a9fc6dcb3/go.mod h1:ekrDiIySdYhji5rBNAkxYMztFWMXyC9Q8LVz6gGVDu0= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231211080303-8c673ee4f4af h1:QSgejckGChrry5waJqf2votsOY0J7Sfh8tPqos0rCXA= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231211080303-8c673ee4f4af/go.mod h1:iJMX6qk9aIHIu3WVSd4puF5CHsNk5eOi++MaJJfNbXM= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/internal/ape/converter.go b/internal/ape/converter.go index dec6f80d8e..f629e262dd 100644 --- a/internal/ape/converter.go +++ b/internal/ape/converter.go @@ -33,7 +33,9 @@ func ConvertEACLToAPE(eaclTable *eacl.Table) (*apechain.Chain, error) { if eaclTable == nil { return nil, nil } - res := &apechain.Chain{} + res := &apechain.Chain{ + MatchType: apechain.MatchTypeFirstMatch, + } resource := getResource(eaclTable) From 1cd2bfe51a15a2e3a2707c93653ce76015284766 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 20 Nov 2023 14:32:26 +0300 Subject: [PATCH 0204/1413] [#755] morph: Drop FrostFSID contract usage Unused. Signed-off-by: Dmitrii Stepanov --- pkg/innerring/initialization.go | 23 +--- pkg/innerring/processors/container/common.go | 15 --- .../processors/container/handlers_test.go | 18 +-- .../processors/container/processor.go | 11 -- pkg/innerring/processors/frostfs/handlers.go | 36 ------ .../processors/frostfs/handlers_test.go | 87 -------------- .../processors/frostfs/process_bind.go | 109 ------------------ pkg/innerring/processors/frostfs/processor.go | 32 ----- pkg/morph/client/frostfs/bind.go | 71 ------------ pkg/morph/client/frostfs/client.go | 2 - pkg/morph/client/frostfsid/addrm_keys.go | 61 ---------- pkg/morph/client/frostfsid/client.go | 72 ------------ pkg/morph/client/frostfsid/keys.go | 54 --------- pkg/morph/event/frostfs/bind.go | 92 --------------- pkg/morph/event/frostfs/bind_test.go | 72 ------------ pkg/morph/event/frostfs/cheque_test.go | 9 ++ pkg/morph/event/frostfs/unbind.go | 33 ------ pkg/morph/event/frostfs/unbind_test.go | 63 ---------- 18 files changed, 16 insertions(+), 844 deletions(-) delete mode 100644 pkg/innerring/processors/frostfs/process_bind.go delete mode 100644 pkg/morph/client/frostfs/bind.go delete mode 100644 pkg/morph/client/frostfsid/addrm_keys.go delete mode 100644 pkg/morph/client/frostfsid/client.go delete mode 100644 pkg/morph/client/frostfsid/keys.go delete mode 100644 pkg/morph/event/frostfs/bind.go delete mode 100644 pkg/morph/event/frostfs/bind_test.go delete mode 100644 pkg/morph/event/frostfs/unbind.go delete mode 100644 pkg/morph/event/frostfs/unbind_test.go diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index f8ebe89fe4..71571c072e 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -20,7 +20,6 @@ import ( balanceClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" frostfsClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" @@ -250,9 +249,7 @@ func (s *Server) initAlphabetProcessor(cfg *viper.Viper) error { return err } -func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.Client, - frostfsIDClient *frostfsid.Client, -) error { +func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.Client) error { // container processor containerProcessor, err := cont.New(&cont.Params{ Log: s.log, @@ -261,7 +258,6 @@ func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.C AlphabetState: s, ContainerClient: cnrClient, MorphClient: cnrClient.Morph(), - FrostFSIDClient: frostfsIDClient, NetworkState: s.netmapClient, }) if err != nil { @@ -289,7 +285,7 @@ func (s *Server) initBalanceProcessor(cfg *viper.Viper, frostfsCli *frostfsClien return bindMorphProcessor(balanceProcessor, s) } -func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper, frostfsIDClient *frostfsid.Client) error { +func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error { if s.withoutMainNet { return nil } @@ -299,7 +295,6 @@ func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper, frostfsIDClient * Metrics: s.irMetrics, PoolSize: cfg.GetInt("workers.frostfs"), FrostFSContract: s.contracts.frostfs, - FrostFSIDClient: frostfsIDClient, BalanceClient: s.balanceClient, NetmapClient: s.netmapClient, MorphClient: s.morphClient, @@ -369,9 +364,8 @@ func (s *Server) initGRPCServer(cfg *viper.Viper) error { } type serverMorphClients struct { - CnrClient *container.Client - FrostFSIDClient *frostfsid.Client - FrostFSClient *frostfsClient.Client + CnrClient *container.Client + FrostFSClient *frostfsClient.Client } func (s *Server) initClientsFromMorph() (*serverMorphClients, error) { @@ -403,11 +397,6 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) { return nil, err } - result.FrostFSIDClient, err = frostfsid.NewFromMorph(s.morphClient, s.contracts.frostfsID, fee, frostfsid.TryNotary(), frostfsid.AsAlphabet()) - if err != nil { - return nil, err - } - result.FrostFSClient, err = frostfsClient.NewFromMorph(s.mainnetClient, s.contracts.frostfs, s.feeConfig.MainChainFee(), frostfsClient.TryNotary(), frostfsClient.AsAlphabet()) if err != nil { @@ -437,7 +426,7 @@ func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClien return err } - err = s.initContainerProcessor(cfg, morphClients.CnrClient, morphClients.FrostFSIDClient) + err = s.initContainerProcessor(cfg, morphClients.CnrClient) if err != nil { return err } @@ -447,7 +436,7 @@ func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClien return err } - err = s.initFrostFSMainnetProcessor(cfg, morphClients.FrostFSIDClient) + err = s.initFrostFSMainnetProcessor(cfg) if err != nil { return err } diff --git a/pkg/innerring/processors/container/common.go b/pkg/innerring/processors/container/common.go index 97eb6f559a..ba12ebb377 100644 --- a/pkg/innerring/processors/container/common.go +++ b/pkg/innerring/processors/container/common.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" @@ -73,20 +72,6 @@ func (cp *Processor) verifySignature(v signatureVerificationData) error { return errors.New("invalid signature calculated by container owner's key") } - } else { - var prm frostfsid.AccountKeysPrm - prm.SetID(v.ownerContainer) - - ownerKeys, err := cp.idClient.AccountKeys(prm) - if err != nil { - return fmt.Errorf("receive owner keys %s: %w", v.ownerContainer, err) - } - - for i := range ownerKeys { - if (*frostfsecdsa.PublicKeyRFC6979)(ownerKeys[i]).Verify(v.signedData, v.signature) { - return nil - } - } } return errors.New("signature is invalid or calculated with the key not bound to the container owner") diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index f129127a64..3acfa2251d 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -8,7 +8,6 @@ import ( containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -40,7 +39,6 @@ func TestPutEvent(t *testing.T) { Log: test.NewLogger(t, true), PoolSize: 2, AlphabetState: &testAlphabetState{isAlphabet: true}, - FrostFSIDClient: &testIDClient{}, NetworkState: nst, ContainerClient: &testContainerClient{}, MorphClient: mc, @@ -95,18 +93,12 @@ func TestDeleteEvent(t *testing.T) { p, err := keys.NewPrivateKey() require.NoError(t, err) - idc := &testIDClient{ - publicKeys: []*keys.PublicKey{ - p.PublicKey(), - }, - } mc := &testMorphClient{} proc, err := New(&Params{ Log: test.NewLogger(t, true), PoolSize: 2, AlphabetState: &testAlphabetState{isAlphabet: true}, - FrostFSIDClient: idc, NetworkState: nst, ContainerClient: cc, MorphClient: mc, @@ -139,6 +131,7 @@ func TestDeleteEvent(t *testing.T) { ContainerIDValue: cidBin, SignatureValue: p.Sign(cidBin), NotaryRequestValue: nr, + PublicKeyValue: p.PublicKey().Bytes(), } var signature frostfscrypto.Signature @@ -177,7 +170,6 @@ func TestSetEACLEvent(t *testing.T) { Log: test.NewLogger(t, true), PoolSize: 2, AlphabetState: &testAlphabetState{isAlphabet: true}, - FrostFSIDClient: &testIDClient{}, NetworkState: nst, ContainerClient: cc, MorphClient: mc, @@ -285,14 +277,6 @@ func (c *testContainerClient) Get(cid []byte) (*containercore.Container, error) return nil, new(apistatus.ContainerNotFound) } -type testIDClient struct { - publicKeys keys.PublicKeys -} - -func (c *testIDClient) AccountKeys(p frostfsid.AccountKeysPrm) (keys.PublicKeys, error) { - return c.publicKeys, nil -} - var _ putEvent = &testPutEvent{} type testPutEvent struct { diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index fd5348c6fe..9f0ae77bf9 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -7,13 +7,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/nspcc-dev/neo-go/pkg/core/mempoolevent" "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" "go.uber.org/zap" @@ -34,10 +32,6 @@ type ( NotarySignAndInvokeTX(mainTx *transaction.Transaction) error } - IDClient interface { - AccountKeys(p frostfsid.AccountKeysPrm) (keys.PublicKeys, error) - } - // Processor of events produced by container contract in the sidechain. Processor struct { log *logger.Logger @@ -46,7 +40,6 @@ type ( alphabetState AlphabetState cnrClient ContClient // notary must be enabled morphClient MorphClient - idClient IDClient netState NetworkState } @@ -58,7 +51,6 @@ type ( AlphabetState AlphabetState ContainerClient ContClient MorphClient MorphClient - FrostFSIDClient IDClient NetworkState NetworkState } ) @@ -92,8 +84,6 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/container: Container client is not set") case p.MorphClient == nil: return nil, errors.New("ir/container: Morph client is not set") - case p.FrostFSIDClient == nil: - return nil, errors.New("ir/container: FrostFS ID client is not set") case p.NetworkState == nil: return nil, errors.New("ir/container: network state is not set") } @@ -116,7 +106,6 @@ func New(p *Params) (*Processor, error) { pool: pool, alphabetState: p.AlphabetState, cnrClient: p.ContainerClient, - idClient: p.FrostFSIDClient, netState: p.NetworkState, morphClient: p.MorphClient, }, nil diff --git a/pkg/innerring/processors/frostfs/handlers.go b/pkg/innerring/processors/frostfs/handlers.go index adb923b876..5782dc7441 100644 --- a/pkg/innerring/processors/frostfs/handlers.go +++ b/pkg/innerring/processors/frostfs/handlers.go @@ -88,39 +88,3 @@ func (np *Processor) handleConfig(ev event.Event) { zap.Int("capacity", np.pool.Cap())) } } - -func (np *Processor) handleBind(ev event.Event) { - e := ev.(frostfsEvent.Bind) - np.log.Info(logs.Notification, - zap.String("type", "bind"), - ) - - // send event to the worker pool - - err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_bind", func() bool { - return np.processBind(e, true) - }) - if err != nil { - // there system can be moved into controlled degradation stage - np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained, - zap.Int("capacity", np.pool.Cap())) - } -} - -func (np *Processor) handleUnbind(ev event.Event) { - e := ev.(frostfsEvent.Unbind) - np.log.Info(logs.Notification, - zap.String("type", "unbind"), - ) - - // send event to the worker pool - - err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_unbind", func() bool { - return np.processBind(e, false) - }) - if err != nil { - // there system can be moved into controlled degradation stage - np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained, - zap.Int("capacity", np.pool.Cap())) - } -} diff --git a/pkg/innerring/processors/frostfs/handlers_test.go b/pkg/innerring/processors/frostfs/handlers_test.go index 475ddaaaca..2685808edb 100644 --- a/pkg/innerring/processors/frostfs/handlers_test.go +++ b/pkg/innerring/processors/frostfs/handlers_test.go @@ -5,12 +5,9 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" @@ -194,80 +191,11 @@ func TestHandleConfig(t *testing.T) { require.EqualValues(t, []nmClient.SetConfigPrm{expConfig}, nm.config, "invalid config value") } -func TestHandleUnbind(t *testing.T) { - t.Parallel() - es := &testEpochState{ - epochCounter: 100, - } - m := &testMorphClient{ - balance: 150, - } - id := &testIDClient{} - proc, err := newTestProc(t, func(p *Params) { - p.EpochState = es - p.MorphClient = m - p.FrostFSIDClient = id - }) - require.NoError(t, err, "failed to create processor") - - p, err := keys.NewPrivateKey() - require.NoError(t, err) - - evUnbind := frostfsEvent.Unbind{ - BindCommon: frostfsEvent.BindCommon{ - UserValue: util.Uint160{49}.BytesBE(), - KeysValue: [][]byte{ - p.PublicKey().Bytes(), - }, - TxHashValue: util.Uint256{100}, - }, - } - - proc.handleUnbind(evUnbind) - - for proc.pool.Running() > 0 { - time.Sleep(10 * time.Millisecond) - } - - var userID user.ID - userID.SetScriptHash(util.Uint160{49}) - - var expBind frostfsid.CommonBindPrm - expBind.SetOwnerID(userID.WalletBytes()) - expBind.SetKeys(evUnbind.BindCommon.KeysValue) - expBind.SetHash(evUnbind.BindCommon.TxHashValue) - - var expNilSlice []frostfsid.CommonBindPrm - - require.EqualValues(t, []frostfsid.CommonBindPrm{expBind}, id.remove, "invalid remove keys value") - require.EqualValues(t, expNilSlice, id.add, "invalid add keys value") - - evBind := frostfsEvent.Bind{ - BindCommon: frostfsEvent.BindCommon{ - UserValue: util.Uint160{49}.BytesBE(), - KeysValue: [][]byte{ - p.PublicKey().Bytes(), - }, - TxHashValue: util.Uint256{100}, - }, - } - - proc.handleBind(evBind) - - for proc.pool.Running() > 0 { - time.Sleep(10 * time.Millisecond) - } - - require.EqualValues(t, []frostfsid.CommonBindPrm{expBind}, id.remove, "invalid remove keys value") - require.EqualValues(t, []frostfsid.CommonBindPrm{expBind}, id.add, "invalid add keys value") -} - func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) { p := &Params{ Log: test.NewLogger(t, true), PoolSize: 1, FrostFSContract: util.Uint160{0}, - FrostFSIDClient: &testIDClient{}, BalanceClient: &testBalaceClient{}, NetmapClient: &testNetmapClient{}, MorphClient: &testMorphClient{}, @@ -358,18 +286,3 @@ func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed }) return nil } - -type testIDClient struct { - add []frostfsid.CommonBindPrm - remove []frostfsid.CommonBindPrm -} - -func (c *testIDClient) AddKeys(p frostfsid.CommonBindPrm) error { - c.add = append(c.add, p) - return nil -} - -func (c *testIDClient) RemoveKeys(args frostfsid.CommonBindPrm) error { - c.remove = append(c.remove, args) - return nil -} diff --git a/pkg/innerring/processors/frostfs/process_bind.go b/pkg/innerring/processors/frostfs/process_bind.go deleted file mode 100644 index 50c6bf5f59..0000000000 --- a/pkg/innerring/processors/frostfs/process_bind.go +++ /dev/null @@ -1,109 +0,0 @@ -package frostfs - -import ( - "crypto/elliptic" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/util" - "go.uber.org/zap" -) - -type bindCommon interface { - User() []byte - Keys() [][]byte - TxHash() util.Uint256 -} - -func (np *Processor) processBind(e bindCommon, bind bool) bool { - if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.FrostFSNonAlphabetModeIgnoreBind) - return true - } - - c := &bindCommonContext{ - bindCommon: e, - bind: bind, - } - - err := np.checkBindCommon(c) - if err != nil { - np.log.Error(logs.FrostFSInvalidManageKeyEvent, - zap.Bool("bind", c.bind), - zap.String("error", err.Error()), - ) - - return false - } - - return np.approveBindCommon(c) == nil -} - -type bindCommonContext struct { - bindCommon - - bind bool - - scriptHash util.Uint160 -} - -func (np *Processor) checkBindCommon(e *bindCommonContext) error { - var err error - - e.scriptHash, err = util.Uint160DecodeBytesBE(e.User()) - if err != nil { - return err - } - - curve := elliptic.P256() - - for _, key := range e.Keys() { - _, err = keys.NewPublicKeyFromBytes(key, curve) - if err != nil { - return err - } - } - - return nil -} - -func (np *Processor) approveBindCommon(e *bindCommonContext) error { - // calculate wallet address - scriptHash := e.User() - - u160, err := util.Uint160DecodeBytesBE(scriptHash) - if err != nil { - np.log.Error(logs.FrostFSCouldNotDecodeScriptHashFromBytes, - zap.String("error", err.Error()), - ) - - return err - } - - var id user.ID - id.SetScriptHash(u160) - - prm := frostfsid.CommonBindPrm{} - prm.SetOwnerID(id.WalletBytes()) - prm.SetKeys(e.Keys()) - prm.SetHash(e.bindCommon.TxHash()) - - var typ string - if e.bind { - typ = "bind" - err = np.frostfsIDClient.AddKeys(prm) - } else { - typ = "unbind" - err = np.frostfsIDClient.RemoveKeys(prm) - } - - if err != nil { - np.log.Error(fmt.Sprintf("could not approve %s", typ), - zap.String("error", err.Error())) - } - - return err -} diff --git a/pkg/innerring/processors/frostfs/processor.go b/pkg/innerring/processors/frostfs/processor.go index 20f44adcd8..2019857ac6 100644 --- a/pkg/innerring/processors/frostfs/processor.go +++ b/pkg/innerring/processors/frostfs/processor.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" @@ -51,11 +50,6 @@ type ( TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error } - IDClient interface { - AddKeys(p frostfsid.CommonBindPrm) error - RemoveKeys(args frostfsid.CommonBindPrm) error - } - // Processor of events produced by frostfs contract in main net. Processor struct { log *logger.Logger @@ -73,7 +67,6 @@ type ( mintEmitThreshold uint64 mintEmitValue fixedn.Fixed8 gasBalanceThreshold int64 - frostfsIDClient IDClient } // Params of the processor constructor. @@ -82,7 +75,6 @@ type ( Metrics metrics.Register PoolSize int FrostFSContract util.Uint160 - FrostFSIDClient IDClient BalanceClient BalanceClient NetmapClient NetmapClient MorphClient MorphClient @@ -101,8 +93,6 @@ const ( withdrawNotification = "Withdraw" chequeNotification = "Cheque" configNotification = "SetConfig" - bindNotification = "Bind" - unbindNotification = "Unbind" ) // New creates frostfs mainnet contract processor instance. @@ -152,8 +142,6 @@ func New(p *Params) (*Processor, error) { mintEmitThreshold: p.MintEmitThreshold, mintEmitValue: p.MintEmitValue, gasBalanceThreshold: p.GasBalanceThreshold, - - frostfsIDClient: p.FrostFSIDClient, }, nil } @@ -187,16 +175,6 @@ func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInf p.SetParser(frostfsEvent.ParseConfig) parsers = append(parsers, p) - // bind event - p.SetType(event.TypeFromString(bindNotification)) - p.SetParser(frostfsEvent.ParseBind) - parsers = append(parsers, p) - - // unbind event - p.SetType(event.TypeFromString(unbindNotification)) - p.SetParser(frostfsEvent.ParseUnbind) - parsers = append(parsers, p) - return parsers } @@ -230,16 +208,6 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI h.SetHandler(np.handleConfig) handlers = append(handlers, h) - // bind handler - h.SetType(event.TypeFromString(bindNotification)) - h.SetHandler(np.handleBind) - handlers = append(handlers, h) - - // unbind handler - h.SetType(event.TypeFromString(unbindNotification)) - h.SetHandler(np.handleUnbind) - handlers = append(handlers, h) - return handlers } diff --git a/pkg/morph/client/frostfs/bind.go b/pkg/morph/client/frostfs/bind.go deleted file mode 100644 index f7b91ddb84..0000000000 --- a/pkg/morph/client/frostfs/bind.go +++ /dev/null @@ -1,71 +0,0 @@ -package frostfscontract - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" -) - -type commonBindArgs struct { - scriptHash []byte // script hash of account identifier - - keys [][]byte // list of serialized public keys - - client.InvokePrmOptional -} - -// SetOptionalPrm sets optional client parameters. -func (x *commonBindArgs) SetOptionalPrm(op client.InvokePrmOptional) { - x.InvokePrmOptional = op -} - -// SetScriptHash sets script hash of the FrostFS account identifier. -func (x *commonBindArgs) SetScriptHash(v []byte) { - x.scriptHash = v -} - -// SetKeys sets a list of public keys in a binary format. -func (x *commonBindArgs) SetKeys(v [][]byte) { - x.keys = v -} - -// BindKeysPrm groups parameters of BindKeys operation. -type BindKeysPrm struct { - commonBindArgs -} - -// BindKeys binds list of public keys from FrostFS account by script hash. -func (x *Client) BindKeys(p BindKeysPrm) error { - prm := client.InvokePrm{} - prm.SetMethod(bindKeysMethod) - prm.SetArgs(p.scriptHash, p.keys) - prm.InvokePrmOptional = p.InvokePrmOptional - - _, err := x.client.Invoke(prm) - if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", bindKeysMethod, err) - } - - return nil -} - -// UnbindKeysPrm groups parameters of UnbindKeys operation. -type UnbindKeysPrm struct { - commonBindArgs -} - -// UnbindKeys invokes the call of key unbinding method -// of FrostFS contract. -func (x *Client) UnbindKeys(args UnbindKeysPrm) error { - prm := client.InvokePrm{} - prm.SetMethod(unbindKeysMethod) - prm.SetArgs(args.scriptHash, args.keys) - prm.InvokePrmOptional = args.InvokePrmOptional - - _, err := x.client.Invoke(prm) - if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", unbindKeysMethod, err) - } - - return nil -} diff --git a/pkg/morph/client/frostfs/client.go b/pkg/morph/client/frostfs/client.go index 3e3e70ec02..571915c273 100644 --- a/pkg/morph/client/frostfs/client.go +++ b/pkg/morph/client/frostfs/client.go @@ -21,8 +21,6 @@ type Client struct { } const ( - bindKeysMethod = "bind" - unbindKeysMethod = "unbind" alphabetUpdateMethod = "alphabetUpdate" chequeMethod = "cheque" ) diff --git a/pkg/morph/client/frostfsid/addrm_keys.go b/pkg/morph/client/frostfsid/addrm_keys.go deleted file mode 100644 index e9004f3664..0000000000 --- a/pkg/morph/client/frostfsid/addrm_keys.go +++ /dev/null @@ -1,61 +0,0 @@ -package frostfsid - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" -) - -type CommonBindPrm struct { - ownerID []byte // FrostFS account identifier - - keys [][]byte // list of serialized public keys - - client.InvokePrmOptional -} - -func (x *CommonBindPrm) SetOptionalPrm(prm client.InvokePrmOptional) { - x.InvokePrmOptional = prm -} - -// SetOwnerID sets FrostFS account identifier. -func (x *CommonBindPrm) SetOwnerID(v []byte) { - x.ownerID = v -} - -// SetKeys sets a list of public keys in a binary format. -func (x *CommonBindPrm) SetKeys(v [][]byte) { - x.keys = v -} - -// AddKeys adds a list of public keys to/from FrostFS account. -func (x *Client) AddKeys(p CommonBindPrm) error { - prm := client.InvokePrm{} - - prm.SetMethod(addKeysMethod) - prm.SetArgs(p.ownerID, p.keys) - prm.InvokePrmOptional = p.InvokePrmOptional - - _, err := x.client.Invoke(prm) - if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", addKeysMethod, err) - } - - return nil -} - -// RemoveKeys removes a list of public keys to/from FrostFS account. -func (x *Client) RemoveKeys(args CommonBindPrm) error { - prm := client.InvokePrm{} - - prm.SetMethod(removeKeysMethod) - prm.SetArgs(args.ownerID, args.keys) - prm.InvokePrmOptional = args.InvokePrmOptional - - _, err := x.client.Invoke(prm) - if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", removeKeysMethod, err) - } - - return nil -} diff --git a/pkg/morph/client/frostfsid/client.go b/pkg/morph/client/frostfsid/client.go deleted file mode 100644 index dded61aff1..0000000000 --- a/pkg/morph/client/frostfsid/client.go +++ /dev/null @@ -1,72 +0,0 @@ -package frostfsid - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -// Client is a wrapper over StaticClient -// which makes calls with the names and arguments -// of the FrostFS ID contract. -// -// Working client must be created via constructor New. -// Using the Client that has been created with new(Client) -// expression (or just declaring a Client variable) is unsafe -// and can lead to panic. -type Client struct { - client *client.StaticClient // static FrostFS ID contract client -} - -const ( - keyListingMethod = "key" - addKeysMethod = "addKey" - removeKeysMethod = "removeKey" -) - -// NewFromMorph wraps client to work with FrostFS ID contract. -func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, opts ...Option) (*Client, error) { - o := defaultOpts() - - for i := range opts { - opts[i](o) - } - - sc, err := client.NewStatic(cli, contract, fee, ([]client.StaticClientOption)(*o)...) - if err != nil { - return nil, fmt.Errorf("could not create client of FrostFS ID contract: %w", err) - } - - return &Client{client: sc}, nil -} - -// Option allows to set an optional -// parameter of ClientWrapper. -type Option func(*opts) - -type opts []client.StaticClientOption - -func defaultOpts() *opts { - return new(opts) -} - -// TryNotary returns option to enable -// notary invocation tries. -func TryNotary() Option { - return func(o *opts) { - *o = append(*o, client.TryNotary()) - } -} - -// AsAlphabet returns option to sign main TX -// of notary requests with client's private -// key. -// -// Considered to be used by IR nodes only. -func AsAlphabet() Option { - return func(o *opts) { - *o = append(*o, client.AsAlphabet()) - } -} diff --git a/pkg/morph/client/frostfsid/keys.go b/pkg/morph/client/frostfsid/keys.go deleted file mode 100644 index 3bae7adfba..0000000000 --- a/pkg/morph/client/frostfsid/keys.go +++ /dev/null @@ -1,54 +0,0 @@ -package frostfsid - -import ( - "crypto/elliptic" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" -) - -// AccountKeysPrm groups parameters of AccountKeys operation. -type AccountKeysPrm struct { - id user.ID -} - -// SetID sets owner ID. -func (a *AccountKeysPrm) SetID(id user.ID) { - a.id = id -} - -// AccountKeys requests public keys of FrostFS account from FrostFS ID contract. -func (x *Client) AccountKeys(p AccountKeysPrm) (keys.PublicKeys, error) { - prm := client.TestInvokePrm{} - prm.SetMethod(keyListingMethod) - prm.SetArgs(p.id.WalletBytes()) - - items, err := x.client.TestInvoke(prm) - if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", keyListingMethod, err) - } else if ln := len(items); ln != 1 { - return nil, fmt.Errorf("unexpected stack item count (%s): %d", keyListingMethod, ln) - } - - items, err = client.ArrayFromStackItem(items[0]) - if err != nil { - return nil, fmt.Errorf("1st stack item must be an array (%s)", keyListingMethod) - } - - pubs := make(keys.PublicKeys, len(items)) - for i := range items { - rawPub, err := client.BytesFromStackItem(items[i]) - if err != nil { - return nil, fmt.Errorf("invalid stack item, expected byte array (%s)", keyListingMethod) - } - - pubs[i], err = keys.NewPublicKeyFromBytes(rawPub, elliptic.P256()) - if err != nil { - return nil, fmt.Errorf("received invalid key (%s): %w", keyListingMethod, err) - } - } - - return pubs, nil -} diff --git a/pkg/morph/event/frostfs/bind.go b/pkg/morph/event/frostfs/bind.go deleted file mode 100644 index 8655b12221..0000000000 --- a/pkg/morph/event/frostfs/bind.go +++ /dev/null @@ -1,92 +0,0 @@ -package frostfs - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" -) - -type Bind struct { - BindCommon -} - -type BindCommon struct { - UserValue []byte - KeysValue [][]byte - - // TxHashValue is used in notary environmental - // for calculating unique but same for - // all notification receivers values. - TxHashValue util.Uint256 -} - -// TxHash returns hash of the TX with new epoch -// notification. -func (b BindCommon) TxHash() util.Uint256 { - return b.TxHashValue -} - -// MorphEvent implements Neo:Morph Event interface. -func (BindCommon) MorphEvent() {} - -func (b BindCommon) Keys() [][]byte { return b.KeysValue } - -func (b BindCommon) User() []byte { return b.UserValue } - -func ParseBind(e *state.ContainedNotificationEvent) (event.Event, error) { - var ( - ev Bind - err error - ) - - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) - } - - err = parseBind(&ev.BindCommon, params) - if err != nil { - return nil, err - } - - ev.TxHashValue = e.Container - - return ev, nil -} - -func parseBind(dst *BindCommon, params []stackitem.Item) error { - if ln := len(params); ln != 2 { - return event.WrongNumberOfParameters(2, ln) - } - - var err error - - // parse user - dst.UserValue, err = client.BytesFromStackItem(params[0]) - if err != nil { - return fmt.Errorf("could not get bind user: %w", err) - } - - // parse keys - bindKeys, err := client.ArrayFromStackItem(params[1]) - if err != nil { - return fmt.Errorf("could not get bind keys: %w", err) - } - - dst.KeysValue = make([][]byte, 0, len(bindKeys)) - - for i := range bindKeys { - rawKey, err := client.BytesFromStackItem(bindKeys[i]) - if err != nil { - return fmt.Errorf("could not get bind public key: %w", err) - } - - dst.KeysValue = append(dst.KeysValue, rawKey) - } - - return nil -} diff --git a/pkg/morph/event/frostfs/bind_test.go b/pkg/morph/event/frostfs/bind_test.go deleted file mode 100644 index 38a82b8d4b..0000000000 --- a/pkg/morph/event/frostfs/bind_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package frostfs - -import ( - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/stretchr/testify/require" -) - -func TestParseBind(t *testing.T) { - var ( - user = []byte{0x1, 0x2, 0x3} - publicKeys = [][]byte{ - []byte("key1"), - []byte("key2"), - []byte("key3"), - } - ) - - t.Run("wrong number of parameters", func(t *testing.T) { - prms := []stackitem.Item{ - stackitem.NewMap(), - } - - _, err := ParseBind(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(2, len(prms)).Error()) - }) - - t.Run("wrong first parameter", func(t *testing.T) { - _, err := ParseBind(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewMap(), - })) - - require.Error(t, err) - }) - - t.Run("wrong second parameter", func(t *testing.T) { - _, err := ParseBind(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewByteArray(user), - stackitem.NewMap(), - })) - - require.Error(t, err) - }) - - t.Run("correct", func(t *testing.T) { - ev, err := ParseBind(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewByteArray(user), - stackitem.NewArray([]stackitem.Item{ - stackitem.NewByteArray(publicKeys[0]), - stackitem.NewByteArray(publicKeys[1]), - stackitem.NewByteArray(publicKeys[2]), - }), - })) - require.NoError(t, err) - - e := ev.(Bind) - - require.Equal(t, user, e.User()) - require.Equal(t, publicKeys, e.Keys()) - }) -} - -func createNotifyEventFromItems(items []stackitem.Item) *state.ContainedNotificationEvent { - return &state.ContainedNotificationEvent{ - NotificationEvent: state.NotificationEvent{ - Item: stackitem.NewArray(items), - }, - } -} diff --git a/pkg/morph/event/frostfs/cheque_test.go b/pkg/morph/event/frostfs/cheque_test.go index be53592cac..ab177757f1 100644 --- a/pkg/morph/event/frostfs/cheque_test.go +++ b/pkg/morph/event/frostfs/cheque_test.go @@ -5,6 +5,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" + "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" @@ -84,3 +85,11 @@ func TestParseCheque(t *testing.T) { }, ev) }) } + +func createNotifyEventFromItems(items []stackitem.Item) *state.ContainedNotificationEvent { + return &state.ContainedNotificationEvent{ + NotificationEvent: state.NotificationEvent{ + Item: stackitem.NewArray(items), + }, + } +} diff --git a/pkg/morph/event/frostfs/unbind.go b/pkg/morph/event/frostfs/unbind.go deleted file mode 100644 index 5a6a8dad9f..0000000000 --- a/pkg/morph/event/frostfs/unbind.go +++ /dev/null @@ -1,33 +0,0 @@ -package frostfs - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/core/state" -) - -type Unbind struct { - BindCommon -} - -func ParseUnbind(e *state.ContainedNotificationEvent) (event.Event, error) { - var ( - ev Unbind - err error - ) - - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) - } - - err = parseBind(&ev.BindCommon, params) - if err != nil { - return nil, err - } - - ev.TxHashValue = e.Container - - return ev, nil -} diff --git a/pkg/morph/event/frostfs/unbind_test.go b/pkg/morph/event/frostfs/unbind_test.go deleted file mode 100644 index 4b79d7c488..0000000000 --- a/pkg/morph/event/frostfs/unbind_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package frostfs - -import ( - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/stretchr/testify/require" -) - -func TestParseUnbind(t *testing.T) { - var ( - user = []byte{0x1, 0x2, 0x3} - publicKeys = [][]byte{ - []byte("key1"), - []byte("key2"), - []byte("key3"), - } - ) - - t.Run("wrong number of parameters", func(t *testing.T) { - prms := []stackitem.Item{ - stackitem.NewMap(), - } - - _, err := ParseUnbind(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(2, len(prms)).Error()) - }) - - t.Run("wrong first parameter", func(t *testing.T) { - _, err := ParseUnbind(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewMap(), - })) - - require.Error(t, err) - }) - - t.Run("wrong second parameter", func(t *testing.T) { - _, err := ParseUnbind(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewByteArray(user), - stackitem.NewMap(), - })) - - require.Error(t, err) - }) - - t.Run("correct", func(t *testing.T) { - ev, err := ParseUnbind(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewByteArray(user), - stackitem.NewArray([]stackitem.Item{ - stackitem.NewByteArray(publicKeys[0]), - stackitem.NewByteArray(publicKeys[1]), - stackitem.NewByteArray(publicKeys[2]), - }), - })) - require.NoError(t, err) - - e := ev.(Unbind) - - require.Equal(t, user, e.User()) - require.Equal(t, publicKeys, e.Keys()) - }) -} From a3ef7b58b46e7cf8bb1e3e94ed8c127c888fc387 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 20 Nov 2023 17:03:19 +0300 Subject: [PATCH 0205/1413] [#755] innerring: Check container owner namespace Signed-off-by: Dmitrii Stepanov --- pkg/innerring/initialization.go | 16 ++- .../processors/container/handlers_test.go | 11 ++ .../processors/container/process_container.go | 25 +++- .../processors/container/processor.go | 38 +++--- pkg/morph/client/frostfsid/client.go | 31 +++++ pkg/morph/client/frostfsid/subject.go | 117 ++++++++++++++++++ 6 files changed, 218 insertions(+), 20 deletions(-) create mode 100644 pkg/morph/client/frostfsid/client.go create mode 100644 pkg/morph/client/frostfsid/subject.go diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index 71571c072e..f4d9b41696 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -20,6 +20,7 @@ import ( balanceClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" frostfsClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" @@ -249,7 +250,7 @@ func (s *Server) initAlphabetProcessor(cfg *viper.Viper) error { return err } -func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.Client) error { +func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.Client, frostfsIDClient *frostfsid.Client) error { // container processor containerProcessor, err := cont.New(&cont.Params{ Log: s.log, @@ -258,6 +259,7 @@ func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.C AlphabetState: s, ContainerClient: cnrClient, MorphClient: cnrClient.Morph(), + FrostFSIDClient: frostfsIDClient, NetworkState: s.netmapClient, }) if err != nil { @@ -364,8 +366,9 @@ func (s *Server) initGRPCServer(cfg *viper.Viper) error { } type serverMorphClients struct { - CnrClient *container.Client - FrostFSClient *frostfsClient.Client + CnrClient *container.Client + FrostFSIDClient *frostfsid.Client + FrostFSClient *frostfsClient.Client } func (s *Server) initClientsFromMorph() (*serverMorphClients, error) { @@ -397,6 +400,11 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) { return nil, err } + result.FrostFSIDClient, err = frostfsid.NewFromMorph(s.morphClient, s.contracts.frostfsID, fee) + if err != nil { + return nil, err + } + result.FrostFSClient, err = frostfsClient.NewFromMorph(s.mainnetClient, s.contracts.frostfs, s.feeConfig.MainChainFee(), frostfsClient.TryNotary(), frostfsClient.AsAlphabet()) if err != nil { @@ -426,7 +434,7 @@ func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClien return err } - err = s.initContainerProcessor(cfg, morphClients.CnrClient) + err = s.initContainerProcessor(cfg, morphClients.CnrClient, morphClients.FrostFSIDClient) if err != nil { return err } diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index 3acfa2251d..9fbfdf8114 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -3,9 +3,11 @@ package container import ( "crypto/ecdsa" "encoding/hex" + "fmt" "testing" "time" + frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" @@ -42,6 +44,7 @@ func TestPutEvent(t *testing.T) { NetworkState: nst, ContainerClient: &testContainerClient{}, MorphClient: mc, + FrostFSIDClient: &testFrostFSIDClient{}, }) require.NoError(t, err, "failed to create processor") @@ -102,6 +105,7 @@ func TestDeleteEvent(t *testing.T) { NetworkState: nst, ContainerClient: cc, MorphClient: mc, + FrostFSIDClient: &testFrostFSIDClient{}, }) require.NoError(t, err, "failed to create processor") @@ -173,6 +177,7 @@ func TestSetEACLEvent(t *testing.T) { NetworkState: nst, ContainerClient: cc, MorphClient: mc, + FrostFSIDClient: &testFrostFSIDClient{}, }) require.NoError(t, err, "failed to create processor") @@ -316,3 +321,9 @@ func (c *testMorphClient) NotarySignAndInvokeTX(mainTx *transaction.Transaction) c.transactions = append(c.transactions, mainTx) return nil } + +type testFrostFSIDClient struct{} + +func (c *testFrostFSIDClient) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) { + return nil, fmt.Errorf("subject not found") +} diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index 2629b9d29a..2ad863b27d 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -2,6 +2,7 @@ package container import ( "fmt" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" @@ -10,6 +11,7 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "github.com/nspcc-dev/neo-go/pkg/network/payload" + "github.com/nspcc-dev/neo-go/pkg/util" "go.uber.org/zap" ) @@ -88,7 +90,7 @@ func (cp *Processor) checkPutContainer(ctx *putContainerContext) error { } // check native name and zone - err = checkNNS(ctx, cnr) + err = cp.checkNNS(ctx, cnr) if err != nil { return fmt.Errorf("NNS: %w", err) } @@ -157,7 +159,7 @@ func (cp *Processor) checkDeleteContainer(e containerEvent.Delete) error { return nil } -func checkNNS(ctx *putContainerContext, cnr containerSDK.Container) error { +func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Container) error { // fetch domain info ctx.d = containerSDK.ReadDomain(cnr) @@ -175,6 +177,25 @@ func checkNNS(ctx *putContainerContext, cnr containerSDK.Container) error { } } + namespace, hasNamespace := strings.CutSuffix(ctx.d.Zone(), ".ns") + if !hasNamespace { + return nil + } + + addr, err := util.Uint160DecodeBytesBE(cnr.Owner().WalletBytes()[1 : 1+util.Uint160Size]) + if err != nil { + return fmt.Errorf("could not get container owner address: %w", err) + } + + subject, err := cp.frostFSIDClient.GetSubject(addr) + if err != nil { + return fmt.Errorf("could not get subject from FrostfsID contract: %w", err) + } + + if subject.Namespace != namespace { + return fmt.Errorf("container and owner namespaces do not match") + } + return nil } diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index 9f0ae77bf9..8fd9edfb8e 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" + frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" @@ -32,15 +33,20 @@ type ( NotarySignAndInvokeTX(mainTx *transaction.Transaction) error } + FrostFSIDClient interface { + GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) + } + // Processor of events produced by container contract in the sidechain. Processor struct { - log *logger.Logger - metrics metrics.Register - pool *ants.Pool - alphabetState AlphabetState - cnrClient ContClient // notary must be enabled - morphClient MorphClient - netState NetworkState + log *logger.Logger + metrics metrics.Register + pool *ants.Pool + alphabetState AlphabetState + cnrClient ContClient // notary must be enabled + morphClient MorphClient + netState NetworkState + frostFSIDClient FrostFSIDClient } // Params of the processor constructor. @@ -52,6 +58,7 @@ type ( ContainerClient ContClient MorphClient MorphClient NetworkState NetworkState + FrostFSIDClient FrostFSIDClient } ) @@ -86,6 +93,8 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/container: Morph client is not set") case p.NetworkState == nil: return nil, errors.New("ir/container: network state is not set") + case p.FrostFSIDClient == nil: + return nil, errors.New("ir/container: FrostFSID client is not set") } p.Log.Debug(logs.ContainerContainerWorkerPool, zap.Int("size", p.PoolSize)) @@ -101,13 +110,14 @@ func New(p *Params) (*Processor, error) { } return &Processor{ - log: p.Log, - metrics: metricsRegister, - pool: pool, - alphabetState: p.AlphabetState, - cnrClient: p.ContainerClient, - netState: p.NetworkState, - morphClient: p.MorphClient, + log: p.Log, + metrics: metricsRegister, + pool: pool, + alphabetState: p.AlphabetState, + cnrClient: p.ContainerClient, + netState: p.NetworkState, + morphClient: p.MorphClient, + frostFSIDClient: p.FrostFSIDClient, }, nil } diff --git a/pkg/morph/client/frostfsid/client.go b/pkg/morph/client/frostfsid/client.go new file mode 100644 index 0000000000..3efa522bc3 --- /dev/null +++ b/pkg/morph/client/frostfsid/client.go @@ -0,0 +1,31 @@ +package frostfsid + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +// Client is a wrapper over StaticClient +// which makes calls with the names and arguments +// of the FrostFS ID contract. +// +// Working client must be created via constructor New. +// Using the Client that has been created with new(Client) +// expression (or just declaring a Client variable) is unsafe +// and can lead to panic. +type Client struct { + client *client.StaticClient // static FrostFS ID contract client +} + +// NewFromMorph wraps client to work with FrostFS ID contract. +func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8) (*Client, error) { + sc, err := client.NewStatic(cli, contract, fee, client.TryNotary(), client.AsAlphabet()) + if err != nil { + return nil, fmt.Errorf("could not create client of FrostFS ID contract: %w", err) + } + + return &Client{client: sc}, nil +} diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go new file mode 100644 index 0000000000..b14675d582 --- /dev/null +++ b/pkg/morph/client/frostfsid/subject.go @@ -0,0 +1,117 @@ +package frostfsid + +import ( + "errors" + "fmt" + + frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" +) + +const methodGetSubject = "getSubject" + +func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) { + prm := client.TestInvokePrm{} + prm.SetMethod(methodGetSubject) + prm.SetArgs(addr) + + res, err := c.client.TestInvoke(prm) + if err != nil { + return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) + } + + subj, err := parseSubject(res) + if err != nil { + return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) + } + + return subj, nil +} + +// parseSubject from https://git.frostfs.info/TrueCloudLab/frostfs-contract/src/commit/dd5919348da9731f24504e7bc485516c2ba5f11c/frostfsid/client/client.go#L592 +func parseSubject(structArr []stackitem.Item) (*frostfsidclient.Subject, error) { + if len(structArr) < 5 { + return nil, errors.New("invalid response subject struct") + } + + var ( + err error + subj frostfsidclient.Subject + ) + + subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) + if err != nil { + return nil, err + } + + if !structArr[1].Equals(stackitem.Null{}) { + subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) + if err != nil { + return nil, err + } + } + + if !structArr[2].Equals(stackitem.Null{}) { + subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) + if err != nil { + return nil, err + } + } + + if !structArr[3].Equals(stackitem.Null{}) { + subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) + if err != nil { + return nil, err + } + } + + subj.KV, err = parseMap(structArr[4]) + if err != nil { + return nil, err + } + + return &subj, nil +} + +func makeValidRes(item stackitem.Item) (*result.Invoke, error) { + return &result.Invoke{ + Stack: []stackitem.Item{item}, + State: vmstate.Halt.String(), + }, nil +} + +func parseMap(item stackitem.Item) (map[string]string, error) { + if item.Equals(stackitem.Null{}) { + return nil, nil + } + + metaMap, err := unwrap.Map(makeValidRes(item)) + if err != nil { + return nil, err + } + + meta, ok := metaMap.Value().([]stackitem.MapElement) + if !ok { + return nil, errors.New("invalid map type") + } + + res := make(map[string]string, len(meta)) + for _, element := range meta { + key, err := element.Key.TryBytes() + if err != nil { + return nil, err + } + val, err := element.Value.TryBytes() + if err != nil { + return nil, err + } + res[string(key)] = string(val) + } + + return res, nil +} From 681b2c5fd45f3c6763db2be3509575d3c3f967db Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Dec 2023 16:50:44 +0300 Subject: [PATCH 0206/1413] [#825] policer: Do not drop required linking objects Signed-off-by: Dmitrii Stepanov --- pkg/core/object/address.go | 11 +++++++-- pkg/local_object_storage/metabase/list.go | 27 +++++++++++++++++------ pkg/services/policer/check.go | 6 ++--- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/pkg/core/object/address.go b/pkg/core/object/address.go index 12e5c89cee..a25d853eb8 100644 --- a/pkg/core/object/address.go +++ b/pkg/core/object/address.go @@ -1,6 +1,8 @@ package object import ( + "fmt" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) @@ -8,6 +10,11 @@ import ( // AddressWithType groups object address with its FrostFS // object type. type AddressWithType struct { - Address oid.Address - Type objectSDK.Type + Address oid.Address + Type objectSDK.Type + IsLinkingObject bool +} + +func (v AddressWithType) String() string { + return fmt.Sprintf("address: %s, type: %s, is linking: %t", v.Address, v.Type, v.IsLinkingObject) } diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 5099a161b0..f7a314452d 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -102,6 +102,7 @@ func (db *DB) ListWithCursor(ctx context.Context, prm ListPrm) (res ListRes, err func (db *DB) listWithCursor(tx *bbolt.Tx, result []objectcore.AddressWithType, count int, cursor *Cursor) ([]objectcore.AddressWithType, *Cursor, error) { threshold := cursor == nil // threshold is a flag to ignore cursor var bucketName []byte + var err error c := tx.Cursor() name, _ := c.First() @@ -140,8 +141,11 @@ loop: bkt := tx.Bucket(name) if bkt != nil { copy(rawAddr, cidRaw) - result, offset, cursor = selectNFromBucket(bkt, objType, graveyardBkt, garbageBkt, rawAddr, containerID, + result, offset, cursor, err = selectNFromBucket(bkt, objType, graveyardBkt, garbageBkt, rawAddr, containerID, result, count, cursor, threshold) + if err != nil { + return nil, nil, err + } } bucketName = name if len(result) >= count { @@ -183,23 +187,23 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket limit int, // stop listing at `limit` items in result cursor *Cursor, // start from cursor object threshold bool, // ignore cursor and start immediately -) ([]objectcore.AddressWithType, []byte, *Cursor) { +) ([]objectcore.AddressWithType, []byte, *Cursor, error) { if cursor == nil { cursor = new(Cursor) } count := len(to) c := bkt.Cursor() - k, _ := c.First() + k, v := c.First() offset := cursor.inBucketOffset if !threshold { c.Seek(offset) - k, _ = c.Next() // we are looking for objects _after_ the cursor + k, v = c.Next() // we are looking for objects _after_ the cursor } - for ; k != nil; k, _ = c.Next() { + for ; k != nil; k, v = c.Next() { if count >= limit { break } @@ -214,14 +218,23 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket continue } + var isLinkingObj bool + if objType == objectSDK.TypeRegular { + var o objectSDK.Object + if err := o.Unmarshal(v); err != nil { + return nil, nil, nil, err + } + isLinkingObj = isLinkObject(&o) + } + var a oid.Address a.SetContainer(cnt) a.SetObject(obj) - to = append(to, objectcore.AddressWithType{Address: a, Type: objType}) + to = append(to, objectcore.AddressWithType{Address: a, Type: objType, IsLinkingObject: isLinkingObj}) count++ } - return to, offset, cursor + return to, offset, cursor, nil } func parseContainerIDWithPrefix(containerID *cid.ID, name []byte) ([]byte, byte) { diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 9e40219d17..73f83b2a79 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -93,10 +93,10 @@ func (p *Policer) processNodes(ctx context.Context, requirements *placementRequi // Number of copies that are stored on maintenance nodes. var uncheckedCopies int - if typ == objectSDK.TypeLock || typ == objectSDK.TypeTombstone { - // all nodes of a container must store the `LOCK` and `TOMBSTONE` objects + if typ == objectSDK.TypeLock || typ == objectSDK.TypeTombstone || addrWithType.IsLinkingObject { + // all nodes of a container must store the `LOCK`, `TOMBSTONE` and linking objects // for correct object removal protection: - // - `LOCK` and `TOMBSTONE` objects are broadcast on their PUT requests; + // - `LOCK`, `TOMBSTONE` and linking objects are broadcast on their PUT requests; // - `LOCK` object removal is a prohibited action in the GC. shortage = uint32(len(nodes)) } From 3b7c0362a8592d439b5b242eee5fbee583a9b6c4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 12 Dec 2023 14:18:42 +0300 Subject: [PATCH 0207/1413] [#861] shard: Fix Delete object It is possible that object doesn't exist in metabase. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 + pkg/local_object_storage/shard/delete.go | 29 ++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index befa7342ad..c996e830a3 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -553,4 +553,5 @@ const ( BlobovniczaSavingCountersToMeta = "saving counters to blobovnicza's meta..." BlobovniczaSavingCountersToMetaSuccess = "saving counters to blobovnicza's meta completed successfully" BlobovniczaSavingCountersToMetaFailed = "saving counters to blobovnicza's meta failed" + ObjectRemovalFailureExistsInWritecache = "can't remove object: object must be flushed from writecache" ) diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index 0856bda10b..1c510bdb76 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -2,12 +2,14 @@ package shard import ( "context" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -61,6 +63,13 @@ func (s *Shard) delete(ctx context.Context, prm DeletePrm, skipFailed bool) (Del default: } + if err := s.validateWritecacheDoesntContainObject(ctx, addr); err != nil { + if skipFailed { + continue + } + return result, err + } + if err := s.deleteFromBlobstor(ctx, addr); err != nil { if skipFailed { continue @@ -80,6 +89,21 @@ func (s *Shard) delete(ctx context.Context, prm DeletePrm, skipFailed bool) (Del return result, nil } +func (s *Shard) validateWritecacheDoesntContainObject(ctx context.Context, addr oid.Address) error { + if !s.hasWriteCache() { + return nil + } + _, err := s.writeCache.Head(ctx, addr) + if err == nil { + s.log.Warn(logs.ObjectRemovalFailureExistsInWritecache, zap.Stringer("object_address", addr)) + return fmt.Errorf("object %s must be flushed from writecache", addr) + } + if client.IsErrObjectNotFound(err) { + return nil + } + return err +} + func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error { var sPrm meta.StorageIDPrm sPrm.SetAddress(addr) @@ -99,13 +123,14 @@ func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error delPrm.StorageID = storageID _, err = s.blobStor.Delete(ctx, delPrm) - if err != nil { + if err != nil && !client.IsErrObjectNotFound(err) { s.log.Debug(logs.ObjectRemovalFailureBlobStor, zap.Stringer("object_address", addr), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + return err } - return err + return nil } func (s *Shard) deleteFromMetabase(ctx context.Context, addr oid.Address) error { From d2746a7d679f5a30a6a3a4a18cbfca0d2f4bc3d8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Dec 2023 13:01:32 +0300 Subject: [PATCH 0208/1413] [#857] Makefile: Update linter version Signed-off-by: Dmitrii Stepanov --- Makefile | 4 ++-- cmd/frostfs-node/notificator.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 3fcb5027c6..153640da84 100755 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ HUB_IMAGE ?= truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.21 -LINT_VERSION ?= 1.54.0 -TRUECLOUDLAB_LINT_VERSION ?= 0.0.2 +LINT_VERSION ?= 1.55.2 +TRUECLOUDLAB_LINT_VERSION ?= 0.0.3 PROTOC_VERSION ?= 25.0 PROTOC_GEN_GO_VERSION ?= $(shell go list -f '{{.Version}}' -m google.golang.org/protobuf) PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) diff --git a/cmd/frostfs-node/notificator.go b/cmd/frostfs-node/notificator.go index 8e581505fd..f9bb31fed5 100644 --- a/cmd/frostfs-node/notificator.go +++ b/cmd/frostfs-node/notificator.go @@ -167,7 +167,6 @@ func connectNats(ctx context.Context, c *cfg) { err := c.cfgNotifications.nw.w.Connect(ctx, endpoint) if err != nil { panic(fmt.Sprintf("could not connect to a nats endpoint %s: %v", endpoint, err)) - } else { - c.log.Info(logs.NatsConnectedToEndpoint, zap.String("endpoint", endpoint)) } + c.log.Info(logs.NatsConnectedToEndpoint, zap.String("endpoint", endpoint)) } From 5d7833c89b9ae73fa6b53c8d200d2e549a147bdb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Dec 2023 13:06:03 +0300 Subject: [PATCH 0209/1413] [#857] golangci: Add perfsprint linter Signed-off-by: Dmitrii Stepanov --- .golangci.yml | 1 + pkg/metrics/writecache.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 5c7e9d9182..1404dd1049 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -79,5 +79,6 @@ linters: - contextcheck - importas - truecloudlab-linters + - perfsprint disable-all: true fast: false diff --git a/pkg/metrics/writecache.go b/pkg/metrics/writecache.go index c8f815ca54..ea3d8742ab 100644 --- a/pkg/metrics/writecache.go +++ b/pkg/metrics/writecache.go @@ -1,7 +1,7 @@ package metrics import ( - "fmt" + "strconv" "time" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" @@ -52,7 +52,7 @@ func (m *writeCacheMetrics) AddMethodDuration(shardID string, method string, suc m.methodDuration.With( prometheus.Labels{ shardIDLabel: shardID, - successLabel: fmt.Sprintf("%v", success), + successLabel: strconv.FormatBool(success), storageLabel: storageType, methodLabel: method, }, From 94ffe8bb452a6b8e83f8bb27103891d5307fd68e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Dec 2023 13:09:57 +0300 Subject: [PATCH 0210/1413] [#857] golangci: Add testifylint linter Signed-off-by: Dmitrii Stepanov --- .golangci.yml | 1 + .../blobstor/internal/blobstortest/iterate.go | 2 +- pkg/local_object_storage/writecache/writecachetest/flush.go | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 1404dd1049..4dd82d92f9 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -80,5 +80,6 @@ linters: - importas - truecloudlab-linters - perfsprint + - testifylint disable-all: true fast: false diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index c73a663b6a..985ca01735 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -82,7 +82,7 @@ func runTestIgnoreLogicalErrors(t *testing.T, s common.Storage, objects []object _, err := s.Iterate(context.Background(), iterPrm) require.Equal(t, err, logicErr) - require.Equal(t, len(objects)/2, len(seen)) + require.Len(t, seen, len(objects)/2) for i := range objects { d, ok := seen[objects[i].addr.String()] if ok { diff --git a/pkg/local_object_storage/writecache/writecachetest/flush.go b/pkg/local_object_storage/writecache/writecachetest/flush.go index 6911344a28..2c495df521 100644 --- a/pkg/local_object_storage/writecache/writecachetest/flush.go +++ b/pkg/local_object_storage/writecache/writecachetest/flush.go @@ -91,7 +91,7 @@ func TestFlush[Option any]( require.Equal(t, uint32(0), errCount.Load()) require.Error(t, wc.Flush(context.Background(), false)) - require.True(t, errCount.Load() > 0) + require.Greater(t, errCount.Load(), uint32(0)) require.NoError(t, wc.Flush(context.Background(), true)) check(t, mb, bs, objects) From 11add38e87291cd34cc14e6748fa7900ca2deff6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Dec 2023 13:18:34 +0300 Subject: [PATCH 0211/1413] [#857] golangci: Add protogetter linter Signed-off-by: Dmitrii Stepanov --- .golangci.yml | 1 + cmd/frostfs-cli/modules/control/evacuation.go | 6 +++--- cmd/frostfs-cli/modules/control/remove_rule.go | 2 +- cmd/frostfs-cli/modules/control/shards_list.go | 6 +++--- cmd/frostfs-cli/modules/tree/add.go | 2 +- pkg/services/control/ir/server/calls.go | 6 +++--- pkg/services/control/server/doctor.go | 4 ++-- pkg/services/control/server/set_shard_mode.go | 4 ++-- pkg/services/tree/service.go | 10 ++++++---- pkg/services/tree/sync.go | 6 +++--- 10 files changed, 25 insertions(+), 22 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 4dd82d92f9..d209693aa2 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -81,5 +81,6 @@ linters: - truecloudlab-linters - perfsprint - testifylint + - protogetter disable-all: true fast: false diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 735897b81a..821dd1a6c9 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -220,7 +220,7 @@ func appendEstimation(sb *strings.Builder, resp *control.GetShardEvacuationStatu if resp.GetBody().GetStatus() != control.GetShardEvacuationStatusResponse_Body_RUNNING || resp.GetBody().GetDuration() == nil || resp.GetBody().GetTotal() == 0 || - resp.GetBody().GetEvacuated()+resp.GetBody().GetFailed()+resp.Body.GetSkipped() == 0 { + resp.GetBody().GetEvacuated()+resp.GetBody().GetFailed()+resp.GetBody().GetSkipped() == 0 { return } @@ -252,8 +252,8 @@ func appendStartedAt(sb *strings.Builder, resp *control.GetShardEvacuationStatus } func appendError(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { - if len(resp.Body.GetErrorMessage()) > 0 { - sb.WriteString(fmt.Sprintf(" Error: %s.", resp.Body.GetErrorMessage())) + if len(resp.GetBody().GetErrorMessage()) > 0 { + sb.WriteString(fmt.Sprintf(" Error: %s.", resp.GetBody().GetErrorMessage())) } } diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index c3f4aeb0cb..60f96afd53 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -63,7 +63,7 @@ func removeRule(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) - if resp.GetBody().Removed { + if resp.GetBody().GetRemoved() { cmd.Println("Rule has been removed.") } else { cmd.Println("Rule has not been removed.") diff --git a/cmd/frostfs-cli/modules/control/shards_list.go b/cmd/frostfs-cli/modules/control/shards_list.go index 4d09667b83..0b5d6b0a34 100644 --- a/cmd/frostfs-cli/modules/control/shards_list.go +++ b/cmd/frostfs-cli/modules/control/shards_list.go @@ -65,7 +65,7 @@ func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) { out := make([]map[string]any, 0, len(ii)) for _, i := range ii { out = append(out, map[string]any{ - "shard_id": base58.Encode(i.Shard_ID), + "shard_id": base58.Encode(i.GetShard_ID()), "mode": shardModeToString(i.GetMode()), "metabase": i.GetMetabasePath(), "blobstor": i.GetBlobstor(), @@ -105,7 +105,7 @@ func prettyPrintShards(cmd *cobra.Command, ii []*control.ShardInfo) { pathPrinter("Write-cache", i.GetWritecachePath())+ pathPrinter("Pilorama", i.GetPiloramaPath())+ fmt.Sprintf("Error count: %d\n", i.GetErrorCount()), - base58.Encode(i.Shard_ID), + base58.Encode(i.GetShard_ID()), shardModeToString(i.GetMode()), ) } @@ -122,6 +122,6 @@ func shardModeToString(m control.ShardMode) string { func sortShardsByID(ii []*control.ShardInfo) { sort.Slice(ii, func(i, j int) bool { - return bytes.Compare(ii[i].Shard_ID, ii[j].Shard_ID) < 0 + return bytes.Compare(ii[i].GetShard_ID(), ii[j].GetShard_ID()) < 0 }) } diff --git a/cmd/frostfs-cli/modules/tree/add.go b/cmd/frostfs-cli/modules/tree/add.go index 4ac1ed198b..8ceea4173d 100644 --- a/cmd/frostfs-cli/modules/tree/add.go +++ b/cmd/frostfs-cli/modules/tree/add.go @@ -74,7 +74,7 @@ func add(cmd *cobra.Command, _ []string) { resp, err := cli.Add(ctx, req) commonCmd.ExitOnErr(cmd, "failed to cal add: %w", err) - cmd.Println("Node ID: ", resp.Body.NodeId) + cmd.Println("Node ID: ", resp.GetBody().GetNodeId()) } func parseMeta(cmd *cobra.Command) ([]*tree.KeyValue, error) { diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 7baae03297..58610b0d1b 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -114,13 +114,13 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer return nil, status.Error(codes.PermissionDenied, err.Error()) } - if len(req.Body.GetContainerId()) > 0 && len(req.Body.GetOwner()) > 0 { + if len(req.GetBody().GetContainerId()) > 0 && len(req.GetBody().GetOwner()) > 0 { return nil, status.Error(codes.InvalidArgument, "specify the owner and container at the same time is not allowed") } var vub uint32 - if len(req.Body.GetContainerId()) > 0 { + if len(req.GetBody().GetContainerId()) > 0 { var containerID cid.ID - if err := containerID.Decode(req.Body.GetContainerId()); err != nil { + if err := containerID.Decode(req.GetBody().GetContainerId()); err != nil { return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to parse container ID: %s", err.Error())) } var err error diff --git a/pkg/services/control/server/doctor.go b/pkg/services/control/server/doctor.go index 2c91d4c2b2..707a6c9834 100644 --- a/pkg/services/control/server/doctor.go +++ b/pkg/services/control/server/doctor.go @@ -15,12 +15,12 @@ func (s *Server) Doctor(ctx context.Context, req *control.DoctorRequest) (*contr return nil, status.Error(codes.PermissionDenied, err.Error()) } - if !req.Body.RemoveDuplicates { + if !req.GetBody().GetRemoveDuplicates() { return nil, status.Error(codes.InvalidArgument, "operation not specified") } var prm engine.RemoveDuplicatesPrm - prm.Concurrency = int(req.Body.Concurrency) + prm.Concurrency = int(req.GetBody().GetConcurrency()) err = s.s.RemoveDuplicates(ctx, prm) if err != nil { diff --git a/pkg/services/control/server/set_shard_mode.go b/pkg/services/control/server/set_shard_mode.go index 274e2f65d3..18a7eb3272 100644 --- a/pkg/services/control/server/set_shard_mode.go +++ b/pkg/services/control/server/set_shard_mode.go @@ -36,8 +36,8 @@ func (s *Server) SetShardMode(_ context.Context, req *control.SetShardModeReques return nil, status.Error(codes.Internal, fmt.Sprintf("unknown shard mode: %s", requestedMode)) } - for _, shardID := range s.getShardIDList(req.Body.GetShard_ID()) { - err = s.s.SetShardMode(shardID, m, req.Body.GetResetErrorCounter()) + for _, shardID := range s.getShardIDList(req.GetBody().GetShard_ID()) { + err = s.s.SetShardMode(shardID, m, req.GetBody().GetResetErrorCounter()) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 57767f87ed..59b01796e0 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -369,13 +369,14 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) x.ParentId = parent x.NodeId = node x.Timestamp = m.Time - if b.AllAttributes { + if b.GetAllAttributes() { x.Meta = metaToProto(m.Items) } else { + var metaValue []*KeyValue for _, kv := range m.Items { for _, attr := range b.GetAttributes() { if kv.Key == attr { - x.Meta = append(x.Meta, &KeyValue{ + metaValue = append(metaValue, &KeyValue{ Key: kv.Key, Value: kv.Value, }) @@ -383,6 +384,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) } } } + x.Meta = metaValue } info = append(info, &x) } @@ -670,8 +672,8 @@ func protoToMeta(arr []*KeyValue) []pilorama.KeyValue { meta := make([]pilorama.KeyValue, len(arr)) for i, kv := range arr { if kv != nil { - meta[i].Key = kv.Key - meta[i].Value = kv.Value + meta[i].Key = kv.GetKey() + meta[i].Value = kv.GetValue() } } return meta diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 485278adf4..2a19ae18a5 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -243,10 +243,10 @@ func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, for ; err == nil; res, err = c.Recv() { lm := res.GetBody().GetOperation() m := &pilorama.Move{ - Parent: lm.ParentId, - Child: lm.ChildId, + Parent: lm.GetParentId(), + Child: lm.GetChildId(), } - if err := m.Meta.FromBytes(lm.Meta); err != nil { + if err := m.Meta.FromBytes(lm.GetMeta()); err != nil { return err } opsCh <- m From 7eb46404a150cff97b45afe5181163bc9605fc29 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 13 Dec 2023 13:34:29 +0300 Subject: [PATCH 0212/1413] [#863] blobovnicza: Fix counters Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobovnicza/meta.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/meta.go b/pkg/local_object_storage/blobovnicza/meta.go index 8b913f8a7d..3316d4666f 100644 --- a/pkg/local_object_storage/blobovnicza/meta.go +++ b/pkg/local_object_storage/blobovnicza/meta.go @@ -92,12 +92,13 @@ func updateMeta(tx *bbolt.Tx, updateValues func(count, size uint64) (uint64, uin count, size = updateValues(count, size) - buf := make([]byte, dataSizeAndItemsCountBufLength) - binary.LittleEndian.PutUint64(buf, size) - if err := b.Put(dataSizeKey, buf); err != nil { + sizeBuf := make([]byte, dataSizeAndItemsCountBufLength) + binary.LittleEndian.PutUint64(sizeBuf, size) + if err := b.Put(dataSizeKey, sizeBuf); err != nil { return err } - binary.LittleEndian.PutUint64(buf, count) - return b.Put(itemsCountKey, buf) + countBuf := make([]byte, dataSizeAndItemsCountBufLength) + binary.LittleEndian.PutUint64(countBuf, count) + return b.Put(itemsCountKey, countBuf) } From 05f8f4928991dd90875942168682785ac223d281 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 12 Dec 2023 15:36:27 +0300 Subject: [PATCH 0213/1413] [#552] gofumpt changes Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-node/policy_engine.go | 3 ++- pkg/ape/chainbase/boltdb.go | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index d04322c2ee..74cbf841c1 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -23,7 +23,8 @@ var _ engine.LocalOverrideEngine = (*accessPolicyEngine)(nil) func newAccessPolicyEngine( morphChainStorage engine.MorphRuleChainStorage, - localOverrideDatabase chainbase.LocalOverrideDatabase) *accessPolicyEngine { + localOverrideDatabase chainbase.LocalOverrideDatabase, +) *accessPolicyEngine { return &accessPolicyEngine{ chainRouter: engine.NewDefaultChainRouterWithLocalOverrides( morphChainStorage, diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index c6cd2c0145..e54d01ea0a 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -22,9 +22,7 @@ type boltLocalOverrideStorage struct { db *bbolt.DB } -var ( - chainBucket = []byte{0} -) +var chainBucket = []byte{0} var ( ErrChainBucketNotFound = logicerr.New("chain root bucket has not been found") From 9b2dce5763de16e2374428884ec6cf8072256337 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Thu, 16 Nov 2023 02:48:05 +0300 Subject: [PATCH 0214/1413] [#552] Add status notification to systemd Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-node/control.go | 17 +++++++++++++++++ debian/frostfs-ir.service | 3 ++- debian/frostfs-storage.service | 3 ++- go.mod | 1 + go.sum | 12 ++++++++++++ internal/logs/logs.go | 1 + 6 files changed, 35 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index 4f5c5d780b..fcd84db3ca 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -2,6 +2,7 @@ package main import ( "context" + "fmt" "net" controlconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/control" @@ -10,6 +11,7 @@ import ( controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + sysdnotify "github.com/iguanesolutions/go-systemd/v5/notify" "go.uber.org/zap" "google.golang.org/grpc" ) @@ -83,12 +85,14 @@ func (c *cfg) NetmapStatus() control.NetmapStatus { } func (c *cfg) setHealthStatus(st control.HealthStatus) { + c.notifySystemd(st) c.healthStatus.Store(int32(st)) c.metricsCollector.State().SetHealth(int32(st)) } func (c *cfg) compareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swapped bool) { if swapped = c.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped { + c.notifySystemd(newSt) c.metricsCollector.State().SetHealth(int32(newSt)) } return @@ -96,6 +100,7 @@ func (c *cfg) compareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swa func (c *cfg) swapHealthStatus(st control.HealthStatus) (old control.HealthStatus) { old = control.HealthStatus(c.healthStatus.Swap(int32(st))) + c.notifySystemd(st) c.metricsCollector.State().SetHealth(int32(st)) return } @@ -103,3 +108,15 @@ func (c *cfg) swapHealthStatus(st control.HealthStatus) (old control.HealthStatu func (c *cfg) HealthStatus() control.HealthStatus { return control.HealthStatus(c.healthStatus.Load()) } + +func (c *cfg) notifySystemd(st control.HealthStatus) string { + status := fmt.Sprintf("%v, %v", st.Number(), st) + err := sysdnotify.Status(status) + if err == nil { + c.log.Info(fmt.Sprintf("reported STATUS=\"%v\" to systemd", status)) + } + if err != nil { + c.log.Error(logs.FailedToReportStatusToSystemd, zap.String("error", err.Error())) + } + return fmt.Sprintf("%v, %v", st, control.HealthStatus_name[int32(st)]) +} diff --git a/debian/frostfs-ir.service b/debian/frostfs-ir.service index b59295ac5a..304017f683 100644 --- a/debian/frostfs-ir.service +++ b/debian/frostfs-ir.service @@ -3,7 +3,8 @@ Description=FrostFS InnerRing node Requires=network.target [Service] -Type=simple +Type=notify +NotifyAccess=all ExecStart=/usr/bin/frostfs-ir --config /etc/frostfs/ir/config.yml User=frostfs-ir Group=frostfs-ir diff --git a/debian/frostfs-storage.service b/debian/frostfs-storage.service index 6e7d1dd5d9..5739617568 100644 --- a/debian/frostfs-storage.service +++ b/debian/frostfs-storage.service @@ -3,7 +3,8 @@ Description=FrostFS Storage node Requires=network.target [Service] -Type=simple +Type=notify +NotifyAccess=all ExecStart=/usr/bin/frostfs-node --config /etc/frostfs/storage/config.yml User=frostfs-storage Group=frostfs-storage diff --git a/go.mod b/go.mod index 3e79f7ff74..3037a6167f 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/google/uuid v1.4.0 github.com/hashicorp/golang-lru/v2 v2.0.7 + github.com/iguanesolutions/go-systemd/v5 v5.1.1 github.com/klauspost/compress v1.17.4 github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 diff --git a/go.sum b/go.sum index 15ae224225..780bdbcdbd 100644 --- a/go.sum +++ b/go.sum @@ -146,6 +146,18 @@ github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU 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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/iguanesolutions/go-systemd/v5 v5.1.1 h1:Hs0Z16knPGCBFnKECrICPh+RQ89Sgy0xyzcalrHMKdw= +github.com/iguanesolutions/go-systemd/v5 v5.1.1/go.mod h1:Quv57scs6S7T0rC6qyLfW20KU/P4p9hrbLPF+ILYrXY= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= diff --git a/internal/logs/logs.go b/internal/logs/logs.go index c996e830a3..1775b18cd9 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -554,4 +554,5 @@ const ( BlobovniczaSavingCountersToMetaSuccess = "saving counters to blobovnicza's meta completed successfully" BlobovniczaSavingCountersToMetaFailed = "saving counters to blobovnicza's meta failed" ObjectRemovalFailureExistsInWritecache = "can't remove object: object must be flushed from writecache" + FailedToReportStatusToSystemd = "failed to report status to systemd" ) From eca7ac9f0d4096e86131ff0f068862320af5eb82 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 21 Nov 2023 12:08:49 +0300 Subject: [PATCH 0215/1413] [#552] Add sdnotify package To avoid using third-party dependencies. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-node/control.go | 7 ++--- go.mod | 1 - go.sum | 12 ------- pkg/util/sdnotify/sdnotify.go | 59 +++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 pkg/util/sdnotify/sdnotify.go diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index fcd84db3ca..6b603d433b 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -10,8 +10,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - sysdnotify "github.com/iguanesolutions/go-systemd/v5/notify" "go.uber.org/zap" "google.golang.org/grpc" ) @@ -109,14 +109,13 @@ func (c *cfg) HealthStatus() control.HealthStatus { return control.HealthStatus(c.healthStatus.Load()) } -func (c *cfg) notifySystemd(st control.HealthStatus) string { +func (c *cfg) notifySystemd(st control.HealthStatus) { status := fmt.Sprintf("%v, %v", st.Number(), st) - err := sysdnotify.Status(status) + err := sdnotify.Status(status) if err == nil { c.log.Info(fmt.Sprintf("reported STATUS=\"%v\" to systemd", status)) } if err != nil { c.log.Error(logs.FailedToReportStatusToSystemd, zap.String("error", err.Error())) } - return fmt.Sprintf("%v, %v", st, control.HealthStatus_name[int32(st)]) } diff --git a/go.mod b/go.mod index 3037a6167f..3e79f7ff74 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,6 @@ require ( github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/google/uuid v1.4.0 github.com/hashicorp/golang-lru/v2 v2.0.7 - github.com/iguanesolutions/go-systemd/v5 v5.1.1 github.com/klauspost/compress v1.17.4 github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 diff --git a/go.sum b/go.sum index 780bdbcdbd..15ae224225 100644 --- a/go.sum +++ b/go.sum @@ -146,18 +146,6 @@ github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU 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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -github.com/iguanesolutions/go-systemd/v5 v5.1.1 h1:Hs0Z16knPGCBFnKECrICPh+RQ89Sgy0xyzcalrHMKdw= -github.com/iguanesolutions/go-systemd/v5 v5.1.1/go.mod h1:Quv57scs6S7T0rC6qyLfW20KU/P4p9hrbLPF+ILYrXY= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go new file mode 100644 index 0000000000..7c3d2f1d2a --- /dev/null +++ b/pkg/util/sdnotify/sdnotify.go @@ -0,0 +1,59 @@ +package sdnotify + +import ( + "fmt" + "net" + "os" + "strings" +) + +const ( + ReadyEnabled = "READY=1" + StoppingEnabled = "STOPPING=1" + ReloadingEnabled = "RELOADING=1" +) + +var socket *net.UnixAddr + +// Initializes socket with provided name of +// environment variable. +func InitSocket() error { + notifySocket := os.Getenv("NOTIFY_SOCKET") + if notifySocket == "" { + return fmt.Errorf("\"NOTIFY_SOCKET\" environment variable is not present") + } + socket = &net.UnixAddr{ + Name: notifySocket, + Net: "unixgram", + } + return nil +} + +// FlagAndStatus sends systemd a combination of a +// well-known status and STATUS=%s{status}, separated by newline. +func FlagAndStatus(status string) error { + status += "\nSTATUS=" + strings.TrimSuffix(status, "=1") + return Send(status) +} + +// Status sends systemd notify STATUS=%s{status}. +func Status(status string) error { + return Send(fmt.Sprintf("STATUS=%s", status)) +} + +// Send state through the notify socket if any. +// If the notify socket was not detected, it returns an error. +func Send(state string) error { + if socket == nil { + return fmt.Errorf("socket is not initialized") + } + conn, err := net.DialUnix(socket.Net, nil, socket) + if err != nil { + return fmt.Errorf("can't open unix socket: %v", err) + } + defer conn.Close() + if _, err = conn.Write([]byte(state)); err != nil { + return fmt.Errorf("can't write into the unix socket: %v", err) + } + return nil +} From ef07c1a3c96e0a1c39c00eee20b7bbeb7855dcdb Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 21 Nov 2023 15:07:37 +0300 Subject: [PATCH 0216/1413] [#552] Add sysd notifications to storage service Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-node/config.go | 12 ++++++++++++ cmd/frostfs-node/control.go | 19 ++++++++++++++----- config/example/node.yaml | 3 +++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 82b01b563e..27c028bae4 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -62,6 +62,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/state" "git.frostfs.info/TrueCloudLab/frostfs-observability/logging/lokicore" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -361,6 +362,8 @@ type internals struct { healthStatus *atomic.Int32 // is node under maintenance isMaintenance atomic.Bool + + sdNotify bool } // starts node's maintenance. @@ -632,9 +635,18 @@ func initInternals(appCfg *config.Config, log *logger.Logger) internals { log: log, apiVersion: version.Current(), healthStatus: &healthStatus, + sdNotify: initSdNotify(appCfg), } } +func initSdNotify(appCfg *config.Config) bool { + if config.BoolSafe(appCfg.Sub("systemdnotify"), "enabled") { + fatalOnErr(sdnotify.InitSocket()) + return true + } + return false +} + func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkState, relayOnly bool) shared { var netAddr network.AddressGroup diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index 6b603d433b..ee2a2952a2 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -110,12 +110,21 @@ func (c *cfg) HealthStatus() control.HealthStatus { } func (c *cfg) notifySystemd(st control.HealthStatus) { - status := fmt.Sprintf("%v, %v", st.Number(), st) - err := sdnotify.Status(status) - if err == nil { - c.log.Info(fmt.Sprintf("reported STATUS=\"%v\" to systemd", status)) + if !c.sdNotify { + return + } + var err error + switch st { + case control.HealthStatus_READY: + err = sdnotify.FlagAndStatus(sdnotify.ReadyEnabled) + case control.HealthStatus_SHUTTING_DOWN: + err = sdnotify.FlagAndStatus(sdnotify.StoppingEnabled) + case control.HealthStatus_RECONFIGURING: + err = sdnotify.FlagAndStatus(sdnotify.ReloadingEnabled) + default: + err = sdnotify.Status(fmt.Sprintf("%v", st)) } if err != nil { - c.log.Error(logs.FailedToReportStatusToSystemd, zap.String("error", err.Error())) + c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/config/example/node.yaml b/config/example/node.yaml index 1355113a3a..c6a2be9acb 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -1,6 +1,9 @@ logger: level: debug # logger level: one of "debug", "info" (default), "warn", "error", "dpanic", "panic", "fatal" +systemdnotify: + enabled: true + pprof: enabled: true address: localhost:6060 # endpoint for Node profiling From 2d4c0a0f4a727694e9b106521e1965e6e11e9ec7 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 5 Dec 2023 17:05:34 +0300 Subject: [PATCH 0217/1413] [#552] Add systemd notifications to ir service Signed-off-by: Ekaterina Lebedeva --- config/example/ir.yaml | 3 +++ pkg/innerring/innerring.go | 14 ++++++++++++++ pkg/innerring/state.go | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/config/example/ir.yaml b/config/example/ir.yaml index a01f3d0bb1..401328e721 100644 --- a/config/example/ir.yaml +++ b/config/example/ir.yaml @@ -119,3 +119,6 @@ prometheus: enabled: true address: localhost:9090 # Endpoint for application prometheus metrics; disabled by default shutdown_timeout: 30s # Timeout for metrics HTTP server graceful shutdown + +systemdnotify: + enabled: true diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 49b7708112..5d7dc5a523 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -24,6 +24,7 @@ import ( control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/precision" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/state" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -73,6 +74,7 @@ type ( predefinedValidators keys.PublicKeys initialEpochTickDelta uint32 withoutMainNet bool + sdNotify bool // runtime processors netmapProcessor *netmap.Processor @@ -336,6 +338,11 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan irMetrics: metrics, } + server.sdNotify, err = server.initSdNotify(cfg) + if err != nil { + return nil, err + } + server.setHealthStatus(control.HealthStatus_HEALTH_STATUS_UNDEFINED) // parse notary support @@ -404,6 +411,13 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan return server, nil } +func (s *Server) initSdNotify(cfg *viper.Viper) (bool, error) { + if cfg.GetBool("systemdnotify.enabled") { + return true, sdnotify.InitSocket() + } + return false, nil +} + func createListener(ctx context.Context, cli *client.Client, p *chainParams) (event.Listener, error) { var ( sub subscriber.Subscriber diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index f5a03fa298..1616dbb9f8 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/state" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/viper" @@ -154,6 +155,7 @@ func (s *Server) ResetEpochTimer(h uint32) error { func (s *Server) setHealthStatus(hs control.HealthStatus) { s.healthStatus.Store(int32(hs)) + s.notifySystemd(hs) if s.irMetrics != nil { s.irMetrics.SetHealth(int32(hs)) } @@ -173,3 +175,21 @@ func initPersistentStateStorage(cfg *viper.Viper) (*state.PersistentStorage, err return persistStorage, nil } + +func (s *Server) notifySystemd(st control.HealthStatus) { + if !s.sdNotify { + return + } + var err error + switch st { + case control.HealthStatus_READY: + err = sdnotify.FlagAndStatus(sdnotify.ReadyEnabled) + case control.HealthStatus_SHUTTING_DOWN: + err = sdnotify.FlagAndStatus(sdnotify.StoppingEnabled) + default: + err = sdnotify.Status(fmt.Sprintf("%v", st)) + } + if err != nil { + s.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) + } +} From 4a64b077030fa8eea4484a9d48aee5000ac80ab1 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 13 Dec 2023 15:25:47 +0300 Subject: [PATCH 0218/1413] [#869] cli: Pass only CID in requests for control API * Fix add-rule, list-rules, remove-rule, get-rule commands: do not convert container ID to native-schema resource format and pass it to control API. Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 6 +----- cmd/frostfs-cli/modules/control/get_rule.go | 6 +----- cmd/frostfs-cli/modules/control/list_rules.go | 6 +----- cmd/frostfs-cli/modules/control/remove_rule.go | 6 +----- 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index ca92200091..48101c5705 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -4,7 +4,6 @@ import ( "bytes" "crypto/sha256" "encoding/json" - "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -14,7 +13,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" - nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -62,13 +60,11 @@ func addRule(cmd *cobra.Command, _ []string) { cmd.Println("Container ID: " + cidStr) cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, serializedChain)) - name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) - req := &control.AddChainLocalOverrideRequest{ Body: &control.AddChainLocalOverrideRequest_Body{ Target: &control.ChainTarget{ Type: control.ChainTarget_CONTAINER, - Name: name, + Name: cidStr, }, Chain: serializedChain, }, diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 962ef179ba..6d86d5d743 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -2,7 +2,6 @@ package control import ( "crypto/sha256" - "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -11,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" - nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -34,12 +32,10 @@ func getRule(cmd *cobra.Command, _ []string) { chainID, _ := cmd.Flags().GetString(chainIDFlag) - name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) - req := &control.GetChainLocalOverrideRequest{ Body: &control.GetChainLocalOverrideRequest_Body{ Target: &control.ChainTarget{ - Name: name, + Name: cidStr, Type: control.ChainTarget_CONTAINER, }, ChainId: chainID, diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index c1e47f4832..f087f53673 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -2,7 +2,6 @@ package control import ( "crypto/sha256" - "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -11,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" - nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -32,12 +30,10 @@ func listRules(cmd *cobra.Command, _ []string) { rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) - name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) - req := &control.ListChainLocalOverridesRequest{ Body: &control.ListChainLocalOverridesRequest_Body{ Target: &control.ChainTarget{ - Name: name, + Name: cidStr, Type: control.ChainTarget_CONTAINER, }, }, diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index 60f96afd53..929d0b1a1c 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -2,7 +2,6 @@ package control import ( "crypto/sha256" - "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -10,7 +9,6 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/spf13/cobra" ) @@ -37,12 +35,10 @@ func removeRule(cmd *cobra.Command, _ []string) { chainID, _ := cmd.Flags().GetString(chainIDFlag) - name := fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cidStr) - req := &control.RemoveChainLocalOverrideRequest{ Body: &control.RemoveChainLocalOverrideRequest_Body{ Target: &control.ChainTarget{ - Name: name, + Name: cidStr, Type: control.ChainTarget_CONTAINER, }, ChainId: chainID, From bdd43f621111ef85cf07e09f830f67e9dbb86b24 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 13 Dec 2023 15:29:17 +0300 Subject: [PATCH 0219/1413] [#869] object: Pass just CID to chain router * Do not convert CID from request to native-schema resource format - this step is unneccessary for APE. Signed-off-by: Airat Arifullin --- pkg/services/object/acl/ape.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go index e2a884c96e..a431ad2520 100644 --- a/pkg/services/object/acl/ape.go +++ b/pkg/services/object/acl/ape.go @@ -26,7 +26,7 @@ func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { request := new(Request) request.FromRequestInfo(reqInfo) - cnrTarget := getResource(reqInfo).Name() + cnrTarget := reqInfo.ContainerID().EncodeToString() status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(cnrTarget), request) if err != nil { From f4877e7b42d84364de1d03f07d9ef199c615af15 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 30 Nov 2023 20:51:23 +0300 Subject: [PATCH 0220/1413] [#835] grpc: Try to reconnect if endpoint listen failed Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/accounting.go | 8 +- cmd/frostfs-node/config.go | 78 +++++++++-- cmd/frostfs-node/config/grpc/config.go | 15 ++ cmd/frostfs-node/container.go | 8 +- cmd/frostfs-node/grpc.go | 182 +++++++++++++++++-------- cmd/frostfs-node/netmap.go | 8 +- cmd/frostfs-node/object.go | 8 +- cmd/frostfs-node/session.go | 8 +- cmd/frostfs-node/tree.go | 8 +- internal/logs/logs.go | 5 + 10 files changed, 243 insertions(+), 85 deletions(-) diff --git a/cmd/frostfs-node/accounting.go b/cmd/frostfs-node/accounting.go index d04f34ff1b..ec737f8a01 100644 --- a/cmd/frostfs-node/accounting.go +++ b/cmd/frostfs-node/accounting.go @@ -2,12 +2,14 @@ package main import ( "context" + "net" accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" accountingTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/accounting/grpc" accountingService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting" accounting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting/morph" + "google.golang.org/grpc" ) func initAccountingService(ctx context.Context, c *cfg) { @@ -28,7 +30,7 @@ func initAccountingService(ctx context.Context, c *cfg) { ), ) - for _, srv := range c.cfgGRPC.servers { - accountingGRPC.RegisterAccountingServiceServer(srv, server) - } + c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { + accountingGRPC.RegisterAccountingServiceServer(s, server) + }) } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 27c028bae4..e887c2e6c1 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -460,18 +460,80 @@ func (c *cfg) ReadCurrentNetMap(msg *netmapV2.NetMap) error { return nil } +type grpcServer struct { + Listener net.Listener + Server *grpc.Server + Endpoint string +} + type cfgGRPC struct { - listeners []net.Listener - - servers []*grpc.Server - - endpoints []string - - maxChunkSize uint64 + // guard protects connections and handlers + guard sync.RWMutex + // servers must be protected with guard + servers []grpcServer + // handlers must be protected with guard + handlers []func(e string, l net.Listener, s *grpc.Server) + maxChunkSize uint64 maxAddrAmount uint64 } +func (c *cfgGRPC) append(e string, l net.Listener, s *grpc.Server) { + c.guard.Lock() + defer c.guard.Unlock() + + c.servers = append(c.servers, grpcServer{ + Listener: l, + Server: s, + Endpoint: e, + }) +} + +func (c *cfgGRPC) appendAndHandle(e string, l net.Listener, s *grpc.Server) { + c.guard.Lock() + defer c.guard.Unlock() + + c.servers = append(c.servers, grpcServer{ + Listener: l, + Server: s, + Endpoint: e, + }) + + for _, h := range c.handlers { + h(e, l, s) + } +} + +func (c *cfgGRPC) performAndSave(handler func(e string, l net.Listener, s *grpc.Server)) { + c.guard.Lock() + defer c.guard.Unlock() + + for _, conn := range c.servers { + handler(conn.Endpoint, conn.Listener, conn.Server) + } + + c.handlers = append(c.handlers, handler) +} + +func (c *cfgGRPC) dropConnection(endpoint string) { + c.guard.Lock() + defer c.guard.Unlock() + + pos := -1 + for idx, srv := range c.servers { + if srv.Endpoint == endpoint { + pos = idx + break + } + } + if pos < 0 { + return + } + + c.servers[pos].Server.Stop() // closes listener + c.servers = append(c.servers[0:pos], c.servers[pos+1:]...) +} + type cfgMorph struct { client *client.Client @@ -1232,7 +1294,7 @@ func (c *cfg) shutdown() { } c.ctxCancel() - c.done <- struct{}{} + close(c.done) for i := range c.closers { c.closers[len(c.closers)-1-i].fn() } diff --git a/cmd/frostfs-node/config/grpc/config.go b/cmd/frostfs-node/config/grpc/config.go index c25d2e717c..37dd76426c 100644 --- a/cmd/frostfs-node/config/grpc/config.go +++ b/cmd/frostfs-node/config/grpc/config.go @@ -3,6 +3,7 @@ package grpcconfig import ( "errors" "strconv" + "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" ) @@ -109,3 +110,17 @@ func IterateEndpoints(c *config.Config, f func(*Config)) { panic("no gRPC server configured") } } + +const DefaultReconnectInterval = time.Minute + +// ReconnectTimeout returns the value of "reconnect_interval" gRPC config parameter. +// +// Returns DefaultReconnectInterval if value is not defined or invalid. +func ReconnectTimeout(c *config.Config) time.Duration { + grpcConf := c.Sub("grpc") + ri := config.DurationSafe(grpcConf, "reconnect_interval") + if ri > 0 { + return ri + } + return DefaultReconnectInterval +} diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 5477947d78..4fc7f56490 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -3,6 +3,7 @@ package main import ( "bytes" "context" + "net" containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -16,6 +17,7 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "go.uber.org/zap" + "google.golang.org/grpc" ) func initContainerService(_ context.Context, c *cfg) { @@ -37,9 +39,9 @@ func initContainerService(_ context.Context, c *cfg) { ), ) - for _, srv := range c.cfgGRPC.servers { - containerGRPC.RegisterContainerServiceServer(srv, server) - } + c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { + containerGRPC.RegisterContainerServiceServer(s, server) + }) } func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc containerCore.Source) (*morphContainerReader, *morphContainerWriter) { diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index 74df7a18f5..cc78440bf1 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -3,7 +3,6 @@ package main import ( "crypto/tls" "errors" - "fmt" "net" "time" @@ -20,91 +19,154 @@ import ( const maxRecvMsgSize = 256 << 20 func initGRPC(c *cfg) { + var endpointsToReconnect []string var successCount int grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) { - serverOpts := []grpc.ServerOption{ - grpc.MaxRecvMsgSize(maxRecvMsgSize), - grpc.ChainUnaryInterceptor( - metrics.NewUnaryServerInterceptor(), - tracing.NewUnaryServerInterceptor(), - ), - grpc.ChainStreamInterceptor( - metrics.NewStreamServerInterceptor(), - tracing.NewStreamServerInterceptor(), - ), - } - - tlsCfg := sc.TLS() - - if tlsCfg != nil { - cert, err := tls.LoadX509KeyPair(tlsCfg.CertificateFile(), tlsCfg.KeyFile()) - if err != nil { - c.log.Error(logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err)) - return - } - - var cipherSuites []uint16 - if !tlsCfg.UseInsecureCrypto() { - // This more or less follows the list in https://wiki.mozilla.org/Security/Server_Side_TLS - // excluding: - // 1. TLS 1.3 suites need not be specified here. - // 2. Suites that use DH key exchange are not implemented by stdlib. - cipherSuites = []uint16{ - tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, - tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, - } - } - creds := credentials.NewTLS(&tls.Config{ - MinVersion: tls.VersionTLS12, - CipherSuites: cipherSuites, - Certificates: []tls.Certificate{cert}, - }) - - serverOpts = append(serverOpts, grpc.Creds(creds)) + serverOpts, ok := getGrpcServerOpts(c, sc) + if !ok { + return } lis, err := net.Listen("tcp", sc.Endpoint()) if err != nil { c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint()) c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) + endpointsToReconnect = append(endpointsToReconnect, sc.Endpoint()) return } c.metricsCollector.GrpcServerMetrics().MarkHealthy(sc.Endpoint()) - c.cfgGRPC.listeners = append(c.cfgGRPC.listeners, lis) - c.cfgGRPC.endpoints = append(c.cfgGRPC.endpoints, sc.Endpoint()) - srv := grpc.NewServer(serverOpts...) c.onShutdown(func() { stopGRPC("FrostFS Public API", srv, c.log) }) - c.cfgGRPC.servers = append(c.cfgGRPC.servers, srv) + c.cfgGRPC.append(sc.Endpoint(), lis, srv) successCount++ }) if successCount == 0 { fatalOnErr(errors.New("could not listen to any gRPC endpoints")) } + + for _, endpoint := range endpointsToReconnect { + scheduleReconnect(endpoint, c) + } +} + +func scheduleReconnect(endpoint string, c *cfg) { + c.wg.Add(1) + go func() { + defer c.wg.Done() + + timeout := grpcconfig.ReconnectTimeout(c.appCfg) + t := time.NewTicker(timeout) + for { + select { + case <-t.C: + c.log.Info(logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint)) + var success, found bool + grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) { + if sc.Endpoint() != endpoint { + return + } + found = true + serverOpts, ok := getGrpcServerOpts(c, sc) + if !ok { + return + } + lis, err := net.Listen("tcp", sc.Endpoint()) + if err != nil { + c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint()) + c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) + return + } + c.metricsCollector.GrpcServerMetrics().MarkHealthy(sc.Endpoint()) + + srv := grpc.NewServer(serverOpts...) + + c.onShutdown(func() { + stopGRPC("FrostFS Public API", srv, c.log) + }) + + c.cfgGRPC.appendAndHandle(sc.Endpoint(), lis, srv) + success = true + }) + if !found { + c.log.Warn(logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint)) + return + } + + if success { + c.log.Info(logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint)) + return + } + c.log.Warn(logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", timeout)) + case <-c.done: + return + } + } + }() +} + +func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool) { + serverOpts := []grpc.ServerOption{ + grpc.MaxRecvMsgSize(maxRecvMsgSize), + grpc.ChainUnaryInterceptor( + metrics.NewUnaryServerInterceptor(), + tracing.NewUnaryServerInterceptor(), + ), + grpc.ChainStreamInterceptor( + metrics.NewStreamServerInterceptor(), + tracing.NewStreamServerInterceptor(), + ), + } + + tlsCfg := sc.TLS() + + if tlsCfg != nil { + cert, err := tls.LoadX509KeyPair(tlsCfg.CertificateFile(), tlsCfg.KeyFile()) + if err != nil { + c.log.Error(logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err)) + return nil, false + } + + var cipherSuites []uint16 + if !tlsCfg.UseInsecureCrypto() { + // This more or less follows the list in https://wiki.mozilla.org/Security/Server_Side_TLS + // excluding: + // 1. TLS 1.3 suites need not be specified here. + // 2. Suites that use DH key exchange are not implemented by stdlib. + cipherSuites = []uint16{ + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + } + } + creds := credentials.NewTLS(&tls.Config{ + MinVersion: tls.VersionTLS12, + CipherSuites: cipherSuites, + Certificates: []tls.Certificate{cert}, + }) + + serverOpts = append(serverOpts, grpc.Creds(creds)) + } + + return serverOpts, true } func serveGRPC(c *cfg) { - for i := range c.cfgGRPC.servers { + c.cfgGRPC.performAndSave(func(e string, l net.Listener, s *grpc.Server) { c.wg.Add(1) - srv := c.cfgGRPC.servers[i] - lis := c.cfgGRPC.listeners[i] - endpoint := c.cfgGRPC.endpoints[i] - go func() { defer func() { c.log.Info(logs.FrostFSNodeStopListeningGRPCEndpoint, - zap.Stringer("endpoint", lis.Addr()), + zap.Stringer("endpoint", l.Addr()), ) c.wg.Done() @@ -112,15 +174,17 @@ func serveGRPC(c *cfg) { c.log.Info(logs.FrostFSNodeStartListeningEndpoint, zap.String("service", "gRPC"), - zap.Stringer("endpoint", lis.Addr()), + zap.Stringer("endpoint", l.Addr()), ) - if err := srv.Serve(lis); err != nil { - c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(endpoint) - fmt.Println("gRPC server error", err) + if err := s.Serve(l); err != nil { + c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(e) + c.log.Error(logs.FrostFSNodeGRPCServerError, zap.Error(err)) + c.cfgGRPC.dropConnection(e) + scheduleReconnect(e, c) } }() - } + }) } func stopGRPC(name string, s *grpc.Server, l *logger.Logger) { diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 347121e560..b21e842c5e 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -5,6 +5,7 @@ import ( "context" "errors" "fmt" + "net" "sync/atomic" netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" @@ -21,6 +22,7 @@ import ( netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "go.uber.org/zap" + "google.golang.org/grpc" ) // primary solution of local network state dump. @@ -162,9 +164,9 @@ func initNetmapService(ctx context.Context, c *cfg) { ), ) - for _, srv := range c.cfgGRPC.servers { - netmapGRPC.RegisterNetmapServiceServer(srv, server) - } + c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { + netmapGRPC.RegisterNetmapServiceServer(s, server) + }) addNewEpochNotificationHandlers(c) } diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 59827179b9..e84696e6b4 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "net" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" @@ -43,6 +44,7 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "go.uber.org/zap" + "google.golang.org/grpc" ) type objectSvc struct { @@ -204,9 +206,9 @@ func initObjectService(c *cfg) { signSvc, c.metricsCollector.ObjectService(), metricsconfig.Enabled(c.appCfg)) server := objectTransportGRPC.New(c.shared.metricsSvc) - for _, srv := range c.cfgGRPC.servers { - objectGRPC.RegisterObjectServiceServer(srv, server) - } + c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { + objectGRPC.RegisterObjectServiceServer(s, server) + }) } func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.ClientCache) { diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index f9c1811a12..ee21ec230c 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "net" "time" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" @@ -16,6 +17,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/persistent" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/temporary" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "google.golang.org/grpc" ) type sessionStorage interface { @@ -57,7 +59,7 @@ func initSessionService(c *cfg) { ), ) - for _, srv := range c.cfgGRPC.servers { - sessionGRPC.RegisterSessionServiceServer(srv, server) - } + c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { + sessionGRPC.RegisterSessionServiceServer(s, server) + }) } diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index f7c0f2a368..dced05bc2b 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -3,6 +3,7 @@ package main import ( "context" "errors" + "net" "time" treeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tree" @@ -15,6 +16,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" + "google.golang.org/grpc" ) type cnrSource struct { @@ -63,9 +65,9 @@ func initTreeService(c *cfg) { tree.WithAuthorizedKeys(treeConfig.AuthorizedKeys()), tree.WithMetrics(c.metricsCollector.TreeService())) - for _, srv := range c.cfgGRPC.servers { - tree.RegisterTreeServiceServer(srv, c.treeService) - } + c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { + tree.RegisterTreeServiceServer(s, c.treeService) + }) c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { c.treeService.Start(ctx) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 1775b18cd9..c3f4fdc7f0 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -423,6 +423,11 @@ const ( FrostFSNodeStoppingGRPCServer = "stopping gRPC server..." FrostFSNodeGRPCCannotShutdownGracefullyForcingStop = "gRPC cannot shutdown gracefully, forcing stop" FrostFSNodeGRPCServerStoppedSuccessfully = "gRPC server stopped successfully" + FrostFSNodeGRPCServerError = "gRPC server error" + FrostFSNodeGRPCReconnecting = "reconnecting gRPC server..." + FrostFSNodeGRPCReconnectedSuccessfully = "gRPC server reconnected successfully" + FrostFSNodeGRPCServerConfigNotFound = "gRPC server config not found" + FrostFSNodeGRPCReconnectFailed = "failed to reconnect gRPC server" FrostFSNodeWaitingForAllProcessesToStop = "waiting for all processes to stop" FrostFSNodeStartedLocalNodesMaintenance = "started local node's maintenance" FrostFSNodeStoppedLocalNodesMaintenance = "stopped local node's maintenance" From 61da7dca24162448689c71a14a116c3d7b401b7b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Dec 2023 18:32:02 +0300 Subject: [PATCH 0221/1413] [#835] node: Fix appCfg concurrent access Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 29 ++++++++++-- cmd/frostfs-node/grpc.go | 91 ++++++++++++++++++++++---------------- 2 files changed, 79 insertions(+), 41 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e887c2e6c1..e6c30376ff 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -426,11 +426,26 @@ type dynamicConfiguration struct { metrics *httpComponent } +type appConfigGuard struct { + mtx sync.RWMutex +} + +func (g *appConfigGuard) LockAppConfigShared() func() { + g.mtx.RLock() + return func() { g.mtx.RUnlock() } +} + +func (g *appConfigGuard) LockAppConfigExclusive() func() { + g.mtx.Lock() + return func() { g.mtx.Unlock() } +} + type cfg struct { applicationConfiguration internals shared dynamicConfiguration + appConfigGuard // configuration of the internal // services @@ -474,8 +489,9 @@ type cfgGRPC struct { // handlers must be protected with guard handlers []func(e string, l net.Listener, s *grpc.Server) - maxChunkSize uint64 - maxAddrAmount uint64 + maxChunkSize uint64 + maxAddrAmount uint64 + reconnectTimeout time.Duration } func (c *cfgGRPC) append(e string, l net.Listener, s *grpc.Server) { @@ -1204,7 +1220,7 @@ func (c *cfg) reloadConfig(ctx context.Context) { } defer c.compareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) - err := c.readConfig(c.appCfg) + err := c.reloadAppConfig() if err != nil { c.log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) return @@ -1271,6 +1287,13 @@ func (c *cfg) reloadConfig(ctx context.Context) { c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) } +func (c *cfg) reloadAppConfig() error { + unlock := c.LockAppConfigExclusive() + defer unlock() + + return c.readConfig(c.appCfg) +} + func (c *cfg) createTombstoneSource() *tombstone.ExpirationChecker { var tssPrm tsourse.TombstoneSourcePrm tssPrm.SetGetService(c.cfgObject.getSvc) diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index cc78440bf1..3a38b2cca2 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -49,6 +49,7 @@ func initGRPC(c *cfg) { if successCount == 0 { fatalOnErr(errors.New("could not listen to any gRPC endpoints")) } + c.cfgGRPC.reconnectTimeout = grpcconfig.ReconnectTimeout(c.appCfg) for _, endpoint := range endpointsToReconnect { scheduleReconnect(endpoint, c) @@ -60,49 +61,13 @@ func scheduleReconnect(endpoint string, c *cfg) { go func() { defer c.wg.Done() - timeout := grpcconfig.ReconnectTimeout(c.appCfg) - t := time.NewTicker(timeout) + t := time.NewTicker(c.cfgGRPC.reconnectTimeout) for { select { case <-t.C: - c.log.Info(logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint)) - var success, found bool - grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) { - if sc.Endpoint() != endpoint { - return - } - found = true - serverOpts, ok := getGrpcServerOpts(c, sc) - if !ok { - return - } - lis, err := net.Listen("tcp", sc.Endpoint()) - if err != nil { - c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint()) - c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) - return - } - c.metricsCollector.GrpcServerMetrics().MarkHealthy(sc.Endpoint()) - - srv := grpc.NewServer(serverOpts...) - - c.onShutdown(func() { - stopGRPC("FrostFS Public API", srv, c.log) - }) - - c.cfgGRPC.appendAndHandle(sc.Endpoint(), lis, srv) - success = true - }) - if !found { - c.log.Warn(logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint)) + if tryReconnect(endpoint, c) { return } - - if success { - c.log.Info(logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint)) - return - } - c.log.Warn(logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", timeout)) case <-c.done: return } @@ -110,6 +75,56 @@ func scheduleReconnect(endpoint string, c *cfg) { }() } +func tryReconnect(endpoint string, c *cfg) bool { + c.log.Info(logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint)) + + serverOpts, found := getGRPCEndpointOpts(endpoint, c) + if !found { + c.log.Warn(logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint)) + return true + } + + lis, err := net.Listen("tcp", endpoint) + if err != nil { + c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(endpoint) + c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) + c.log.Warn(logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout)) + return false + } + c.metricsCollector.GrpcServerMetrics().MarkHealthy(endpoint) + + srv := grpc.NewServer(serverOpts...) + + c.onShutdown(func() { + stopGRPC("FrostFS Public API", srv, c.log) + }) + + c.cfgGRPC.appendAndHandle(endpoint, lis, srv) + + c.log.Info(logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint)) + return true +} + +func getGRPCEndpointOpts(endpoint string, c *cfg) (result []grpc.ServerOption, found bool) { + unlock := c.LockAppConfigShared() + defer unlock() + grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) { + if found { + return + } + if sc.Endpoint() != endpoint { + return + } + var ok bool + result, ok = getGrpcServerOpts(c, sc) + if !ok { + return + } + found = true + }) + return +} + func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool) { serverOpts := []grpc.ServerOption{ grpc.MaxRecvMsgSize(maxRecvMsgSize), From 7d7cf05575db445620a137d568f491309363bfc1 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 13 Dec 2023 15:46:31 +0300 Subject: [PATCH 0222/1413] [#851] ape: Initialize and use policy contract interface * Replace inmemory policy contract mock by initialized policy contract interface. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 8 ++++++-- cmd/frostfs-node/main.go | 5 +++-- cmd/frostfs-node/morph.go | 1 + go.mod | 2 +- go.sum | 4 ++-- pkg/morph/client/client.go | 7 +++++++ pkg/morph/client/nns.go | 2 ++ 7 files changed, 22 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e6c30376ff..e36081ba6c 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -70,7 +70,7 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" - "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + policy_client "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" neogoutil "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" @@ -623,6 +623,8 @@ type cfgLocalStorage struct { } type cfgAccessPolicyEngine struct { + policyContractHash neogoutil.Uint160 + accessPolicyEngine *accessPolicyEngine } @@ -1077,7 +1079,9 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) { ) } - morphRuleStorage := inmemory.NewInmemoryMorphRuleChainStorage() + morphRuleStorage := policy_client.NewContractStorage( + c.cfgMorph.client.GetActor(), + c.cfgObject.cfgAccessPolicyEngine.policyContractHash) ape := newAccessPolicyEngine(morphRuleStorage, localOverrideDB) c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine = ape diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index d4dfb7e609..2fe3a0a25b 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -98,14 +98,15 @@ func initApp(ctx context.Context, c *cfg) { fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Init(ctx)) }) + initAndLog(c, "gRPC", initGRPC) + initAndLog(c, "netmap", func(c *cfg) { initNetmapService(ctx, c) }) + initAccessPolicyEngine(ctx, c) initAndLog(c, "access policy engine", func(c *cfg) { fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Open(ctx)) fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Init()) }) - initAndLog(c, "gRPC", initGRPC) - initAndLog(c, "netmap", func(c *cfg) { initNetmapService(ctx, c) }) initAndLog(c, "accounting", func(c *cfg) { initAccountingService(ctx, c) }) initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) }) initAndLog(c, "session", initSessionService) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index f7100d0bf4..d26142370f 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -289,6 +289,7 @@ func lookupScriptHashesInNNS(c *cfg) { {&c.cfgAccounting.scriptHash, client.NNSBalanceContractName}, {&c.cfgContainer.scriptHash, client.NNSContainerContractName}, {&c.cfgMorph.proxyScriptHash, client.NNSProxyContractName}, + {&c.cfgObject.cfgAccessPolicyEngine.policyContractHash, client.NNSPolicyContractName}, } ) diff --git a/go.mod b/go.mod index 3e79f7ff74..6463c3b2bf 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231211080303-8c673ee4f4af + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231214122253-62ea96b82ce3 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index 15ae224225..c18e291f27 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231211080303-8c673ee4f4af h1:QSgejckGChrry5waJqf2votsOY0J7Sfh8tPqos0rCXA= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231211080303-8c673ee4f4af/go.mod h1:iJMX6qk9aIHIu3WVSd4puF5CHsNk5eOi++MaJJfNbXM= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231214122253-62ea96b82ce3 h1:xnS/YalLqCRplvpF3E9/PRGevj4cDe7qFNZT0mkjZcs= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231214122253-62ea96b82ce3/go.mod h1:v43imcuSmDwSNrePe4UTQh8jaE8FmsiKN3FcaEzmRzc= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 93a4176f99..e52adfa8e4 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -539,3 +539,10 @@ func (c *Client) setActor(act *actor.Actor) { c.gasToken = nep17.New(act, gas.Hash) c.rolemgmt = rolemgmt.New(act) } + +func (c *Client) GetActor() *actor.Actor { + c.switchLock.RLock() + defer c.switchLock.RUnlock() + + return c.rpcActor +} diff --git a/pkg/morph/client/nns.go b/pkg/morph/client/nns.go index 758b220a2e..218f7ad8e2 100644 --- a/pkg/morph/client/nns.go +++ b/pkg/morph/client/nns.go @@ -33,6 +33,8 @@ const ( NNSProxyContractName = "proxy.frostfs" // NNSGroupKeyName is a name for the FrostFS group key record in NNS. NNSGroupKeyName = "group.frostfs" + // NNSPolicyContractName is a name of the policy contract in NNS. + NNSPolicyContractName = "policy.frostfs" ) var ( From be8f499b91d426f8435da6e9be0574f237b61b82 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 18 Dec 2023 14:53:00 +0300 Subject: [PATCH 0223/1413] [#717] Fix mixing CID and container ID All container ID outputs that may be used in scripts were replaced with CID. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/modules/container/create.go | 2 +- cmd/frostfs-cli/modules/container/get.go | 2 +- cmd/frostfs-cli/modules/control/add_rule.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index 37827b617f..f670043eab 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -113,7 +113,7 @@ It will be stored in sidechain when inner ring will accepts it.`, id := res.ID() - cmd.Println("container ID:", id) + cmd.Println("CID:", id) if containerAwait { cmd.Println("awaiting...") diff --git a/cmd/frostfs-cli/modules/container/get.go b/cmd/frostfs-cli/modules/container/get.go index cd920f0c47..1681dc7f3d 100644 --- a/cmd/frostfs-cli/modules/container/get.go +++ b/cmd/frostfs-cli/modules/container/get.go @@ -83,7 +83,7 @@ func prettyPrintContainer(cmd *cobra.Command, cnr container.Container, jsonEncod var id cid.ID container.CalculateID(&id, cnr) - cmd.Println("container ID:", id) + cmd.Println("CID:", id) cmd.Println("owner ID:", cnr.Owner()) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 48101c5705..47233678db 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -57,7 +57,7 @@ func addRule(cmd *cobra.Command, _ []string) { chain.ID = apechain.ID(chainID) serializedChain := chain.Bytes() - cmd.Println("Container ID: " + cidStr) + cmd.Println("CID: " + cidStr) cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, serializedChain)) req := &control.AddChainLocalOverrideRequest{ From d9cbb16bd3cec547ba9621a51ac3d8b0d75b211b Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 18 Dec 2023 12:47:32 +0300 Subject: [PATCH 0224/1413] [#866] Use TTL for blobovnicza tree cache Signed-off-by: Anton Nikiforov --- .../internal/modules/storagecfg/config.go | 1 + cmd/frostfs-node/config.go | 3 +++ .../shard/blobstor/blobovnicza/config.go | 21 +++++++++++++++++++ config/example/node.env | 2 ++ config/example/node.json | 2 ++ config/example/node.yaml | 1 + docs/storage-node-configuration.md | 18 +++++++++------- .../blobstor/blobovniczatree/blobovnicza.go | 2 +- .../blobstor/blobovniczatree/cache.go | 13 +++++------- .../blobstor/blobovniczatree/option.go | 9 ++++++++ 10 files changed, 55 insertions(+), 17 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/config.go b/cmd/frostfs-adm/internal/modules/storagecfg/config.go index a07ce32c66..9f7efe2dfa 100644 --- a/cmd/frostfs-adm/internal/modules/storagecfg/config.go +++ b/cmd/frostfs-adm/internal/modules/storagecfg/config.go @@ -61,6 +61,7 @@ storage: depth: 1 # max depth of object tree storage in key-value DB width: 4 # max width of object tree storage in key-value DB opened_cache_capacity: 50 # maximum number of opened database files + opened_cache_ttl: 5m # ttl for opened database file gc: remover_batch_size: 200 # number of objects to be removed by the garbage collector diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e36081ba6c..88b93e6aae 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -185,6 +185,7 @@ type subStorageCfg struct { width uint64 leafWidth uint64 openedCacheSize int + openedCacheTTL time.Duration initWorkerCount int initInAdvance bool } @@ -305,6 +306,7 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol sCfg.width = sub.ShallowWidth() sCfg.leafWidth = sub.LeafWidth() sCfg.openedCacheSize = sub.OpenedCacheSize() + sCfg.openedCacheTTL = sub.OpenedCacheTTL() sCfg.initWorkerCount = sub.InitWorkerCount() sCfg.initInAdvance = sub.InitInAdvance() case fstree.Type: @@ -898,6 +900,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { blobovniczatree.WithBlobovniczaShallowWidth(sRead.width), blobovniczatree.WithBlobovniczaLeafWidth(sRead.leafWidth), blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize), + blobovniczatree.WithOpenedCacheTTL(sRead.openedCacheTTL), blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), blobovniczatree.WithInitInAdvance(sRead.initInAdvance), blobovniczatree.WithLogger(c.log), diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go index 37191cc722..0e007b4257 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go @@ -1,6 +1,8 @@ package blobovniczaconfig import ( + "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" boltdbconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/boltdb" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" @@ -23,6 +25,9 @@ const ( // OpenedCacheSizeDefault is a default cache size of opened Blobovnicza's. OpenedCacheSizeDefault = 16 + // OpenedCacheTTLDefault is a default cache ttl of opened Blobovnicza's. + OpenedCacheTTLDefault = 0 // means expiring is off + // InitWorkerCountDefault is a default workers count to initialize Blobovnicza's. InitWorkerCountDefault = 5 ) @@ -101,6 +106,22 @@ func (x *Config) OpenedCacheSize() int { return OpenedCacheSizeDefault } +// OpenedCacheTTL returns the value of "opened_cache_ttl" config parameter. +// +// Returns OpenedCacheTTLDefault if the value is not a positive number. +func (x *Config) OpenedCacheTTL() time.Duration { + d := config.DurationSafe( + (*config.Config)(x), + "opened_cache_ttl", + ) + + if d > 0 { + return d + } + + return OpenedCacheTTLDefault +} + // BoltDB returns config instance for querying bolt db specific parameters. func (x *Config) BoltDB() *boltdbconfig.Config { return (*boltdbconfig.Config)(x) diff --git a/config/example/node.env b/config/example/node.env index be16f62bf9..2972f56e9c 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -125,6 +125,7 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_SIZE=4194304 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH=1 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 +FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_TTL=5m FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_IN_ADVANCE=TRUE @@ -174,6 +175,7 @@ FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_SIZE=4194304 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH=1 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 +FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_TTL=5m FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_LEAF_WIDTH=10 ### FSTree config FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE=fstree diff --git a/config/example/node.json b/config/example/node.json index ff38e3894c..c803e11fb8 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -173,6 +173,7 @@ "depth": 1, "width": 4, "opened_cache_capacity": 50, + "opened_cache_ttl": "5m", "leaf_width": 10, "init_worker_count": 10, "init_in_advance": true @@ -226,6 +227,7 @@ "depth": 1, "width": 4, "opened_cache_capacity": 50, + "opened_cache_ttl": "5m", "leaf_width": 10 }, { diff --git a/config/example/node.yaml b/config/example/node.yaml index c6a2be9acb..d4c3516bc1 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -150,6 +150,7 @@ storage: depth: 1 # max depth of object tree storage in key-value DB width: 4 # max width of object tree storage in key-value DB opened_cache_capacity: 50 # maximum number of opened database files + opened_cache_ttl: 5m # ttl for opened database file leaf_width: 10 # max count of key-value DB on leafs of object tree storage - perm: 0644 # permissions for blobstor files(directories: +x for current user and group) depth: 5 # max depth of object tree storage in FS diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 71eabc0423..613be12881 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -209,6 +209,7 @@ blobstor: depth: 1 width: 4 opened_cache_capacity: 50 + opened_cache_ttl: 5m ``` #### Common options for sub-storages @@ -225,14 +226,15 @@ blobstor: | `depth` | `int` | `4` | File-system tree depth. | #### `blobovnicza` type options -| Parameter | Type | Default value | Description | -|-------------------------|-----------|---------------|-------------------------------------------------------| -| `path` | `string` | | Path to the root of the blobstor. | -| `perm` | file mode | `0660` | Default permission for created files and directories. | -| `size` | `size` | `1 G` | Maximum size of a single blobovnicza | -| `depth` | `int` | `2` | Blobovnicza tree depth. | -| `width` | `int` | `16` | Blobovnicza tree width. | -| `opened_cache_capacity` | `int` | `16` | Maximum number of simultaneously opened blobovniczas. | +| Parameter | Type | Default value | Description | +|-------------------------|------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `path` | `string` | | Path to the root of the blobstor. | +| `perm` | file mode | `0660` | Default permission for created files and directories. | +| `size` | `size` | `1 G` | Maximum size of a single blobovnicza | +| `depth` | `int` | `2` | Blobovnicza tree depth. | +| `width` | `int` | `16` | Blobovnicza tree width. | +| `opened_cache_capacity` | `int` | `16` | Maximum number of simultaneously opened blobovniczas. | +| `opened_cache_ttl` | `duration` | `0` | TTL in cache for opened blobovniczas(disabled by default). In case of heavy random-read and 10 shards each with 10_000 databases and accessing 400 objects per-second we will access each db approximately once per ((10 * 10_000 / 400) = 250 seconds <= 300 seconds = 5 min). Also take in mind that in this scenario they will probably be closed earlier because of the cache capacity, so bigger values are likely to be of no use. | ### `gc` subsection diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 9f2950094e..460aebbbaa 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -87,7 +87,7 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) - blz.dbCache = newDBCache(blz.openedCacheSize, blz.commondbManager) + blz.dbCache = newDBCache(blz.openedCacheSize, blz.openedCacheTTL, blz.commondbManager) blz.deleteProtectedObjects = newAddressMap() blz.dbFilesGuard = &sync.RWMutex{} blz.rebuildGuard = &sync.RWMutex{} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index 317bac5ffe..d8fe6e8b0f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -1,10 +1,11 @@ package blobovniczatree import ( - "fmt" "sync" + "time" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" + "github.com/hashicorp/golang-lru/v2/expirable" "github.com/hashicorp/golang-lru/v2/simplelru" ) @@ -22,14 +23,10 @@ type dbCache struct { dbManager *dbManager } -func newDBCache(size int, dbManager *dbManager) *dbCache { - cache, err := simplelru.NewLRU[string, *sharedDB](size, func(_ string, evictedDB *sharedDB) { +func newDBCache(size int, ttl time.Duration, dbManager *dbManager) *dbCache { + cache := expirable.NewLRU[string, *sharedDB](size, func(_ string, evictedDB *sharedDB) { evictedDB.Close() - }) - if err != nil { - // occurs only if the size is not positive - panic(fmt.Errorf("could not create LRU cache of size %d: %w", size, err)) - } + }, ttl) return &dbCache{ cacheGuard: &sync.RWMutex{}, cache: cache, diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index d36074dc8b..e93640fae3 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -16,6 +16,7 @@ type cfg struct { readOnly bool rootPath string openedCacheSize int + openedCacheTTL time.Duration blzShallowDepth uint64 blzShallowWidth uint64 blzLeafWidth uint64 @@ -34,6 +35,7 @@ type Option func(*cfg) const ( defaultPerm = 0o700 defaultOpenedCacheSize = 50 + defaultOpenedCacheTTL = 0 // means expiring is off defaultBlzShallowDepth = 2 defaultBlzShallowWidth = 16 defaultWaitBeforeDropDB = 10 * time.Second @@ -46,6 +48,7 @@ func initConfig(c *cfg) { log: &logger.Logger{Logger: zap.L()}, perm: defaultPerm, openedCacheSize: defaultOpenedCacheSize, + openedCacheTTL: defaultOpenedCacheTTL, blzShallowDepth: defaultBlzShallowDepth, blzShallowWidth: defaultBlzShallowWidth, reportError: func(string, error) {}, @@ -105,6 +108,12 @@ func WithOpenedCacheSize(sz int) Option { } } +func WithOpenedCacheTTL(ttl time.Duration) Option { + return func(c *cfg) { + c.openedCacheTTL = ttl + } +} + func WithObjectSizeLimit(sz uint64) Option { return func(c *cfg) { c.blzOpts = append(c.blzOpts, blobovnicza.WithObjectSizeLimit(sz)) From d69d318cb0d3ba8ce2d652606fa1192ac9a42b97 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 18 Dec 2023 17:55:24 +0300 Subject: [PATCH 0225/1413] [#878] node: Drain internal error's channel This fixes shutdown panic: 1. Some morph connection gets error and passes it to internalErr channel. 2. Storage node starts to shutdow and closes internalErr channel. 3. Other morph connection gets error and tries to pass it to internalErr channel. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 - cmd/frostfs-node/main.go | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 88b93e6aae..82e2037885 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1328,5 +1328,4 @@ func (c *cfg) shutdown() { for i := range c.closers { c.closers[len(c.closers)-1-i].fn() } - close(c.internalErr) } diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index 2fe3a0a25b..f91a6decc5 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "os" + "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -155,9 +156,22 @@ func wait(c *cfg) { <-c.done // graceful shutdown + drain := &sync.WaitGroup{} + drain.Add(1) + go func() { + defer drain.Done() + for err := range c.internalErr { + c.log.Warn(logs.FrostFSNodeInternalApplicationError, + zap.String("message", err.Error())) + } + }() + c.log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop) c.wg.Wait() + + close(c.internalErr) + drain.Wait() } func (c *cfg) onShutdown(f func()) { From 7ade11922e2d8bfe014ba34125f619c87ffe423f Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 20 Dec 2023 15:22:17 +0300 Subject: [PATCH 0226/1413] [#834] adm: Refactor `morph` module Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/deploy.go | 4 +- .../internal/modules/morph/initialize.go | 56 +----------- .../internal/modules/morph/n3client.go | 8 +- .../internal/modules/morph/root.go | 57 ++++++------ .../internal/modules/morph/util.go | 86 +++++++++++++++++++ 5 files changed, 120 insertions(+), 91 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/util.go diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index 54b506715b..1facd6d105 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -46,10 +46,10 @@ NNS name is taken by stripping '_contract.nef' from the NEF file (similar to fro func init() { ff := deployCmd.Flags() - ff.String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") + ff.String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) _ = deployCmd.MarkFlagFilename(alphabetWalletsFlag) - ff.StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + ff.StringP(endpointFlag, "r", "", endpointFlagDesc) ff.String(contractPathFlag, "", "Path to the contract directory") _ = deployCmd.MarkFlagFilename(contractPathFlag) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index 96100ffb58..78356e6b41 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -4,12 +4,10 @@ import ( "errors" "fmt" "os" - "path/filepath" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -117,15 +115,11 @@ func (c *initializeContext) close() { func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) { walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) - wallets, err := openAlphabetWallets(v, walletDir) + wallets, err := getAlphabetWallets(v, walletDir) if err != nil { return nil, err } - if len(wallets) > maxAlphabetNodes { - return nil, ErrTooManyAlphabetNodes - } - needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init" var w *wallet.Wallet @@ -257,54 +251,6 @@ func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { return accounts, nil } -func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { - walletFiles, err := os.ReadDir(walletDir) - if err != nil { - return nil, fmt.Errorf("can't read alphabet wallets dir: %w", err) - } - - var size int -loop: - for i := 0; i < len(walletFiles); i++ { - name := innerring.GlagoliticLetter(i).String() + ".json" - for j := range walletFiles { - if walletFiles[j].Name() == name { - size++ - continue loop - } - } - break - } - if size == 0 { - return nil, errors.New("alphabet wallets dir is empty (run `generate-alphabet` command first)") - } - - wallets := make([]*wallet.Wallet, size) - for i := 0; i < size; i++ { - letter := innerring.GlagoliticLetter(i).String() - p := filepath.Join(walletDir, letter+".json") - w, err := wallet.NewWalletFromFile(p) - if err != nil { - return nil, fmt.Errorf("can't open wallet: %w", err) - } - - password, err := config.GetPassword(v, letter) - if err != nil { - return nil, fmt.Errorf("can't fetch password: %w", err) - } - - for i := range w.Accounts { - if err := w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil { - return nil, fmt.Errorf("can't unlock wallet: %w", err) - } - } - - wallets[i] = w - } - - return wallets, nil -} - func (c *initializeContext) awaitTx() error { return c.clientContext.awaitTx(c.Command) } diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/n3client.go index 3550895c37..584bb8524f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/n3client.go @@ -73,13 +73,7 @@ func getN3Client(v *viper.Viper) (Client, error) { } func defaultClientContext(c Client, committeeAcc *wallet.Account) (*clientContext, error) { - commAct, err := actor.New(c, []actor.SignerAccount{{ - Signer: transaction.Signer{ - Account: committeeAcc.Contract.ScriptHash(), - Scopes: transaction.Global, - }, - Account: committeeAcc, - }}) + commAct, err := newActor(c, committeeAcc) if err != nil { return nil, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 707ae733d1..1a0cd8c8b9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -7,8 +7,11 @@ import ( const ( alphabetWalletsFlag = "alphabet-wallets" + alphabetWalletsFlagDesc = "Path to alphabet wallets dir" alphabetSizeFlag = "size" endpointFlag = "rpc-endpoint" + endpointFlagDesc = "N3 RPC node endpoint" + endpointFlagShort = "r" storageWalletFlag = "storage-wallet" storageWalletLabelFlag = "label" storageGasCLIFlag = "initial-gas" @@ -264,12 +267,12 @@ func init() { func initNetmapCandidatesCmd() { RootCmd.AddCommand(netmapCandidatesCmd) - netmapCandidatesCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + netmapCandidatesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) } func initDepositoryNotaryCmd() { RootCmd.AddCommand(depositNotaryCmd) - depositNotaryCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + depositNotaryCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) depositNotaryCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") depositNotaryCmd.Flags().String(walletAccountFlag, "", "Wallet account address") depositNotaryCmd.Flags().String(refillGasAmountFlag, "", "Amount of GAS to deposit") @@ -278,8 +281,8 @@ func initDepositoryNotaryCmd() { func initRefillGasCmd() { RootCmd.AddCommand(refillGasCmd) - refillGasCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - refillGasCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + refillGasCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + refillGasCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) refillGasCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") refillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") refillGasCmd.Flags().String(refillGasAmountFlag, "", "Additional amount of GAS to transfer") @@ -288,21 +291,21 @@ func initRefillGasCmd() { func initListContainersCmd() { RootCmd.AddCommand(listContainersCmd) - listContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + listContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) listContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") } func initRestoreContainersCmd() { RootCmd.AddCommand(restoreContainersCmd) - restoreContainersCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - restoreContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + restoreContainersCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + restoreContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) restoreContainersCmd.Flags().String(containerDumpFlag, "", "File to restore containers from") restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore") } func initDumpContainersCmd() { RootCmd.AddCommand(dumpContainersCmd) - dumpContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + dumpContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) dumpContainersCmd.Flags().String(containerDumpFlag, "", "File where to save dumped containers") dumpContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") dumpContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to dump") @@ -310,15 +313,15 @@ func initDumpContainersCmd() { func initUpdateContractsCmd() { RootCmd.AddCommand(updateContractsCmd) - updateContractsCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - updateContractsCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + updateContractsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + updateContractsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) updateContractsCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled FrostFS contracts") _ = updateContractsCmd.MarkFlagRequired(contractsInitFlag) } func initDumpBalancesCmd() { RootCmd.AddCommand(dumpBalancesCmd) - dumpBalancesCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + dumpBalancesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) dumpBalancesCmd.Flags().BoolP(dumpBalancesStorageFlag, "s", false, "Dump balances of storage nodes from the current netmap") dumpBalancesCmd.Flags().BoolP(dumpBalancesAlphabetFlag, "a", false, "Dump balances of alphabet contracts") dumpBalancesCmd.Flags().BoolP(dumpBalancesProxyFlag, "p", false, "Dump balances of the proxy contract") @@ -327,53 +330,53 @@ func initDumpBalancesCmd() { func initSetConfigCmd() { RootCmd.AddCommand(setConfig) - setConfig.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - setConfig.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + setConfig.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + setConfig.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) setConfig.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") setConfig.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initDumpNetworkConfigCmd() { RootCmd.AddCommand(dumpNetworkConfigCmd) - dumpNetworkConfigCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + dumpNetworkConfigCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) } func initDumpContractHashesCmd() { RootCmd.AddCommand(dumpContractHashesCmd) - dumpContractHashesCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + dumpContractHashesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) dumpContractHashesCmd.Flags().String(customZoneFlag, "", "Custom zone to search.") } func initSetPolicyCmd() { RootCmd.AddCommand(setPolicy) - setPolicy.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - setPolicy.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + setPolicy.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + setPolicy.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) setPolicy.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initDumpPolicyCmd() { RootCmd.AddCommand(dumpPolicy) - dumpPolicy.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + dumpPolicy.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) } func initRemoveNodesCmd() { RootCmd.AddCommand(removeNodes) - removeNodes.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - removeNodes.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + removeNodes.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + removeNodes.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) removeNodes.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initForceNewEpochCmd() { RootCmd.AddCommand(forceNewEpoch) - forceNewEpoch.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - forceNewEpoch.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + forceNewEpoch.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + forceNewEpoch.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) forceNewEpoch.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initGenerateStorageCmd() { RootCmd.AddCommand(generateStorageCmd) - generateStorageCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - generateStorageCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + generateStorageCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + generateStorageCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) generateStorageCmd.Flags().String(storageWalletFlag, "", "Path to new storage node wallet") generateStorageCmd.Flags().String(storageGasCLIFlag, "", "Initial amount of GAS to transfer") generateStorageCmd.Flags().StringP(storageWalletLabelFlag, "l", "", "Wallet label") @@ -381,8 +384,8 @@ func initGenerateStorageCmd() { func initInitCmd() { RootCmd.AddCommand(initCmd) - initCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") - initCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint") + initCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + initCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) initCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled FrostFS contracts") _ = initCmd.MarkFlagRequired(contractsInitFlag) initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") @@ -397,7 +400,7 @@ func initInitCmd() { func initGenerateAlphabetCmd() { RootCmd.AddCommand(generateAlphabetCmd) - generateAlphabetCmd.Flags().String(alphabetWalletsFlag, "", "Path to alphabet wallets dir") + generateAlphabetCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) generateAlphabetCmd.Flags().Uint(alphabetSizeFlag, 7, "Amount of alphabet wallets to generate") } diff --git a/cmd/frostfs-adm/internal/modules/morph/util.go b/cmd/frostfs-adm/internal/modules/morph/util.go new file mode 100644 index 0000000000..8b5489ab8e --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util.go @@ -0,0 +1,86 @@ +package morph + +import ( + "errors" + "fmt" + "os" + "path/filepath" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/spf13/viper" +) + +func getAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { + wallets, err := openAlphabetWallets(v, walletDir) + if err != nil { + return nil, err + } + + if len(wallets) > maxAlphabetNodes { + return nil, ErrTooManyAlphabetNodes + } + return wallets, nil +} + +func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { + walletFiles, err := os.ReadDir(walletDir) + if err != nil { + return nil, fmt.Errorf("can't read alphabet wallets dir: %w", err) + } + + var size int +loop: + for i := 0; i < len(walletFiles); i++ { + name := innerring.GlagoliticLetter(i).String() + ".json" + for j := range walletFiles { + if walletFiles[j].Name() == name { + size++ + continue loop + } + } + break + } + if size == 0 { + return nil, errors.New("alphabet wallets dir is empty (run `generate-alphabet` command first)") + } + + wallets := make([]*wallet.Wallet, size) + for i := 0; i < size; i++ { + letter := innerring.GlagoliticLetter(i).String() + p := filepath.Join(walletDir, letter+".json") + w, err := wallet.NewWalletFromFile(p) + if err != nil { + return nil, fmt.Errorf("can't open wallet: %w", err) + } + + password, err := config.GetPassword(v, letter) + if err != nil { + return nil, fmt.Errorf("can't fetch password: %w", err) + } + + for i := range w.Accounts { + if err := w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil { + return nil, fmt.Errorf("can't unlock wallet: %w", err) + } + } + + wallets[i] = w + } + + return wallets, nil +} + +func newActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) { + return actor.New(c, []actor.SignerAccount{{ + Signer: transaction.Signer{ + Account: committeeAcc.Contract.ScriptHash(), + Scopes: transaction.Global, + }, + Account: committeeAcc, + }}) +} From 32f4e72e6a2c0fcc5569b131021d1ada5f26dcfb Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 20 Dec 2023 15:44:12 +0300 Subject: [PATCH 0227/1413] [#834] adm: Add commands to invoke methods of `policy` contract Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/ape.go | 162 ++++++++++++++++++ .../internal/modules/morph/ape_util.go | 103 +++++++++++ .../internal/modules/morph/root.go | 4 + cmd/frostfs-cli/modules/util/ape.go | 33 ++++ 4 files changed, 302 insertions(+) create mode 100644 cmd/frostfs-adm/internal/modules/morph/ape.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/ape_util.go diff --git a/cmd/frostfs-adm/internal/modules/morph/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape.go new file mode 100644 index 0000000000..6dd2bd1859 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/ape.go @@ -0,0 +1,162 @@ +package morph + +import ( + "bytes" + "encoding/json" + + parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + namespaceTarget = "namespace" + containerTarget = "container" + jsonFlag = "json" + jsonFlagDesc = "Output rule chains in JSON format" + chainIDFlag = "chain-id" + chainIDDesc = "Rule chain ID" + ruleFlag = "rule" + ruleFlagDesc = "Rule chain in text format" + ruleJSONFlag = "rule-json" + ruleJSONFlagDesc = "Chain rule in JSON format or path to the file" + targetNameFlag = "target-name" + targetNameDesc = "Resource name in APE resource name format" + targetTypeFlag = "target-type" + targetTypeDesc = "Resource type(container/namespace)" +) + +var ( + apeCmd = &cobra.Command{ + Use: "ape", + Short: "Section for APE configuration commands", + } + + addRuleChainCmd = &cobra.Command{ + Use: "add-rule-chain", + Short: "Add rule chain", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + }, + Run: addRuleChain, + } + + removeRuleChainCmd = &cobra.Command{ + Use: "rm-rule-chain", + Short: "Remove rule chain", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + }, + Run: removeRuleChain, + } + + listRuleChainsCmd = &cobra.Command{ + Use: "list-rule-chains", + Short: "List rule chains", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + }, + Run: listRuleChains, + } +) + +func initAddRuleChainCmd() { + apeCmd.AddCommand(addRuleChainCmd) + + addRuleChainCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + addRuleChainCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + + addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) + _ = addRuleChainCmd.MarkFlagRequired(targetTypeFlag) + addRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc) + _ = addRuleChainCmd.MarkFlagRequired(targetNameFlag) + + addRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) + _ = addRuleChainCmd.MarkFlagRequired(chainIDFlag) + addRuleChainCmd.Flags().String(ruleFlag, "", ruleFlagDesc) + addRuleChainCmd.Flags().String(ruleJSONFlag, "", ruleJSONFlagDesc) + + addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, ruleJSONFlag) +} + +func initRemoveRuleChainCmd() { + apeCmd.AddCommand(removeRuleChainCmd) + + removeRuleChainCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + removeRuleChainCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + + removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) + _ = removeRuleChainCmd.MarkFlagRequired(targetTypeFlag) + removeRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc) + _ = removeRuleChainCmd.MarkFlagRequired(targetNameFlag) + removeRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) + _ = removeRuleChainCmd.MarkFlagRequired(chainIDFlag) +} + +func initListRuleChainsCmd() { + apeCmd.AddCommand(listRuleChainsCmd) + + listRuleChainsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + listRuleChainsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) + _ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag) + listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc) + _ = listRuleChainsCmd.MarkFlagRequired(targetNameFlag) + listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc) +} + +func addRuleChain(cmd *cobra.Command, _ []string) { + chain := parseChain(cmd) + target := parseTarget(cmd) + pci, ac := newPolicyContractInterface(cmd) + h, vub, err := pci.AddMorphRuleChain(apechain.Ingress, target, chain) + cmd.Println("Waiting for transaction to persist...") + _, err = ac.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "add rule chain error: %w", err) + cmd.Println("Rule chain added successfully") +} + +func removeRuleChain(cmd *cobra.Command, _ []string) { + chainID := parseChainID(cmd) + target := parseTarget(cmd) + pci, ac := newPolicyContractInterface(cmd) + h, vub, err := pci.RemoveMorphRuleChain(apechain.Ingress, target, chainID) + cmd.Println("Waiting for transaction to persist...") + _, err = ac.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) + cmd.Println("Rule chain removed successfully") +} + +func listRuleChains(cmd *cobra.Command, _ []string) { + target := parseTarget(cmd) + pci, _ := newPolicyContractInterface(cmd) + chains, err := pci.ListMorphRuleChains(apechain.Ingress, target) + commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err) + if len(chains) == 0 { + return + } + + toJSON, _ := cmd.Flags().GetBool(jsonFlag) + if toJSON { + prettyJSONFormat(cmd, chains) + } else { + for _, c := range chains { + parseutil.PrintHumanReadableAPEChain(cmd, c) + } + } +} + +func prettyJSONFormat(cmd *cobra.Command, chains []*apechain.Chain) { + wr := bytes.NewBufferString("") + data, err := json.Marshal(chains) + if err == nil { + err = json.Indent(wr, data, "", " ") + } + commonCmd.ExitOnErr(cmd, "print rule chain error: %w", err) + cmd.Println(wr) +} diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape_util.go new file mode 100644 index 0000000000..e50522f2d6 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/ape_util.go @@ -0,0 +1,103 @@ +package morph + +import ( + "encoding/json" + "fmt" + "os" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func parseTarget(cmd *cobra.Command) policyengine.Target { + var targetType policyengine.TargetType + typ, _ := cmd.Flags().GetString(targetTypeFlag) + switch typ { + case namespaceTarget: + targetType = policyengine.Namespace + case containerTarget: + targetType = policyengine.Container + default: + commonCmd.ExitOnErr(cmd, "read target type error: %w", fmt.Errorf("unknown target type")) + } + name, _ := cmd.Flags().GetString(targetNameFlag) + + return policyengine.Target{ + Name: name, + Type: targetType, + } +} + +func parseChainID(cmd *cobra.Command) apechain.ID { + chainID, _ := cmd.Flags().GetString(chainIDFlag) + if chainID == "" { + commonCmd.ExitOnErr(cmd, "read chain id error: %w", + fmt.Errorf("chain id cannot be empty")) + } + return apechain.ID(chainID) +} + +func parseChain(cmd *cobra.Command) *apechain.Chain { + chain := new(apechain.Chain) + + if ruleStmt, _ := cmd.Flags().GetString(ruleFlag); ruleStmt != "" { + parseErr := parseutil.ParseAPEChain(chain, []string{ruleStmt}) + commonCmd.ExitOnErr(cmd, "ape chain parser error: %w", parseErr) + } else if ruleJSON, _ := cmd.Flags().GetString(ruleJSONFlag); ruleJSON != "" { + var rule []byte + if _, err := os.Stat(ruleJSON); err == nil { + rule, err = os.ReadFile(ruleJSON) + commonCmd.ExitOnErr(cmd, "read file error: %w", err) + } else { + rule = []byte(ruleJSON) + if !json.Valid(rule) { + commonCmd.ExitOnErr(cmd, "read raw rule error: %w", + fmt.Errorf("invalid JSON")) + } + } + err := chain.DecodeBytes(rule) + commonCmd.ExitOnErr(cmd, "chain decode error: %w", err) + } else { + commonCmd.ExitOnErr(cmd, "", fmt.Errorf("rule is not passed")) + } + + chain.ID = parseChainID(cmd) + + return chain +} + +func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *actor.Actor) { + v := viper.GetViper() + c, err := getN3Client(v) + commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) + + walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) + wallets, err := getAlphabetWallets(v, walletDir) + commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) + + committeeAcc, err := getWalletAccount(wallets[0], committeeAccountName) + commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) + + ac, err := newActor(c, committeeAcc) + commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) + + inv := &ac.Invoker + var ch util.Uint160 + r := management.NewReader(inv) + nnsCs, err := r.GetContractByID(1) + commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) + + ch, err = nnsResolveHash(inv, nnsCs.Hash, policyContract+".frostfs") + commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) + + return morph.NewContractStorage(ac, ch), ac +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 1a0cd8c8b9..475bf4b067 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -263,6 +263,10 @@ func init() { initRefillGasCmd() initDepositoryNotaryCmd() initNetmapCandidatesCmd() + RootCmd.AddCommand(apeCmd) + initAddRuleChainCmd() + initRemoveRuleChainCmd() + initListRuleChainsCmd() } func initNetmapCandidatesCmd() { diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index c5f8526e2c..79966613d9 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -3,11 +3,13 @@ package util import ( "errors" "fmt" + "strconv" "strings" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/flynn-archive/go-shlex" + "github.com/spf13/cobra" ) var ( @@ -20,6 +22,37 @@ var ( errUnknownCondObjectType = errors.New("condition object type is not recognized") ) +// PrintHumanReadableAPEChain print APE chain rules. +func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) { + cmd.Println("ChainID: " + string(chain.ID)) + cmd.Println("Rules:") + for _, rule := range chain.Rules { + cmd.Println("\tStatus: " + rule.Status.String()) + cmd.Println("\tAny: " + strconv.FormatBool(rule.Any)) + cmd.Println("\tConditions:") + for _, c := range rule.Condition { + var ot string + switch c.Object { + case apechain.ObjectResource: + ot = "Resource" + case apechain.ObjectRequest: + ot = "Request" + default: + panic("unknown object type") + } + cmd.Println(fmt.Sprintf("\t\t%s %s %s %s", ot, c.Key, c.Op, c.Value)) + } + cmd.Println("\tActions:\tInverted:" + strconv.FormatBool(rule.Actions.Inverted)) + for _, name := range rule.Actions.Names { + cmd.Println("\t\t" + name) + } + cmd.Println("\tResources:\tInverted:" + strconv.FormatBool(rule.Resources.Inverted)) + for _, name := range rule.Resources.Names { + cmd.Println("\t\t" + name) + } + } +} + // ParseAPEChain parses APE chain rules. func ParseAPEChain(chain *apechain.Chain, rules []string) error { if len(rules) == 0 { From 419b07e8b881db1b351e2f5197a2543bda76208e Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Thu, 21 Dec 2023 12:16:55 +0300 Subject: [PATCH 0228/1413] [#883] adm: Use proxy contract as admin for frostfsid and policy contracts Signed-off-by: Alex Vanin --- cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 533fcad4dc..436ba93d2f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -546,7 +546,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an if found { items = append(items, h) } else { - items = append(items, nil) + items = append(items, c.Contracts[proxyContract].Hash) } case netmapContract: md := getDefaultNetmapContractConfigMap() @@ -582,7 +582,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an case proxyContract: items = nil case policyContract: - items = []any{nil} + items = append(items, c.Contracts[proxyContract].Hash) default: panic(fmt.Sprintf("invalid contract name: %s", ctrName)) } From ac0821a1a544bfeeecff1f4a0d32047b809be617 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Thu, 21 Dec 2023 12:26:47 +0300 Subject: [PATCH 0229/1413] [#883] adm: Support proxy accounts Signed-off-by: Alex Vanin --- .../internal/modules/morph/proxy.go | 68 +++++++++++++++++++ .../internal/modules/morph/root.go | 34 ++++++++++ 2 files changed, 102 insertions(+) create mode 100644 cmd/frostfs-adm/internal/modules/morph/proxy.go diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy.go new file mode 100644 index 0000000000..effcf0e274 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/proxy.go @@ -0,0 +1,68 @@ +package morph + +import ( + "fmt" + + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + accountAddressFlag = "account" +) + +func addProxyAccount(cmd *cobra.Command, _ []string) { + acc, _ := cmd.Flags().GetString(accountAddressFlag) + addr, err := address.StringToUint160(acc) + commonCmd.ExitOnErr(cmd, "invalid account: %w", err) + err = processAccount(cmd, addr, "addAccount") + commonCmd.ExitOnErr(cmd, "processing error: %w", err) +} + +func removeProxyAccount(cmd *cobra.Command, _ []string) { + acc, _ := cmd.Flags().GetString(accountAddressFlag) + addr, err := address.StringToUint160(acc) + commonCmd.ExitOnErr(cmd, "invalid account: %w", err) + err = processAccount(cmd, addr, "removeAccount") + commonCmd.ExitOnErr(cmd, "processing error: %w", err) +} + +func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error { + wCtx, err := newInitializeContext(cmd, viper.GetViper()) + if err != nil { + return fmt.Errorf("can't to initialize context: %w", err) + } + + r := management.NewReader(wCtx.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) + if err != nil { + return fmt.Errorf("can't get NNS contract info: %w", err) + } + + proxyHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, proxyContract+".frostfs") + if err != nil { + return fmt.Errorf("can't get proxy contract hash: %w", err) + } + + bw := io.NewBufBinWriter() + emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr) + + if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil { + return err + } + + if err = wCtx.awaitTx(); err != nil { + return err + } + + cmd.Println("Proxy contract has been updated") + + return nil +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 475bf4b067..75409421ac 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -241,6 +241,26 @@ var ( }, Run: listNetmapCandidatesNodes, } + + proxyAddAccountCmd = &cobra.Command{ + Use: "proxy-add-account", + Short: "Adds account to proxy contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: addProxyAccount, + } + + proxyRemoveAccountCmd = &cobra.Command{ + Use: "proxy-remove-account", + Short: "Remove from proxy contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: removeProxyAccount, + } ) func init() { @@ -267,6 +287,20 @@ func init() { initAddRuleChainCmd() initRemoveRuleChainCmd() initListRuleChainsCmd() + initProxyAddAccount() + initProxyRemoveAccount() +} + +func initProxyAddAccount() { + RootCmd.AddCommand(proxyAddAccountCmd) + proxyAddAccountCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + proxyAddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") +} + +func initProxyRemoveAccount() { + RootCmd.AddCommand(proxyRemoveAccountCmd) + proxyRemoveAccountCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + proxyRemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") } func initNetmapCandidatesCmd() { From b1eab1de54505281ee55eebaf23dd7f40d3cc53d Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Thu, 21 Dec 2023 13:59:46 +0300 Subject: [PATCH 0230/1413] [#883] adm: Add domainOf function to resolve NNS domain Signed-off-by: Alex Vanin --- cmd/frostfs-adm/internal/modules/morph/ape_util.go | 2 +- cmd/frostfs-adm/internal/modules/morph/balance.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/config.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/container.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/dump_hashes.go | 2 +- cmd/frostfs-adm/internal/modules/morph/epoch.go | 2 +- .../internal/modules/morph/initialize_deploy.go | 8 ++++++-- .../internal/modules/morph/netmap_candidates.go | 2 +- cmd/frostfs-adm/internal/modules/morph/proxy.go | 2 +- cmd/frostfs-adm/internal/modules/morph/remove_node.go | 2 +- 10 files changed, 18 insertions(+), 14 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape_util.go index e50522f2d6..f64a7e1085 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape_util.go @@ -96,7 +96,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac nnsCs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - ch, err = nnsResolveHash(inv, nnsCs.Hash, policyContract+".frostfs") + ch, err = nnsResolveHash(inv, nnsCs.Hash, domainOf(policyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) return morph.NewContractStorage(ac, ch), ac diff --git a/cmd/frostfs-adm/internal/modules/morph/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance.go index 9b706c7bf2..0fee45a8fd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance.go @@ -63,7 +63,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err = nnsResolveHash(inv, nnsCs.Hash, netmapContract+".frostfs") + nmHash, err = nnsResolveHash(inv, nnsCs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -136,7 +136,7 @@ func printStorageNodeBalances(cmd *cobra.Command, inv *invoker.Invoker, nmHash u } func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash util.Uint160) error { - h, err := nnsResolveHash(inv, nnsHash, proxyContract+".frostfs") + h, err := nnsResolveHash(inv, nnsHash, domainOf(proxyContract)) if err != nil { return fmt.Errorf("can't get hash of the proxy contract: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index 3c4029bcaf..db7d2ab8e5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -37,7 +37,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := nnsResolveHash(inv, cs.Hash, netmapContract+".frostfs") + nmHash, err := nnsResolveHash(inv, cs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -95,7 +95,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".frostfs") + nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index f3faa30447..e7a7f5466a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -35,7 +35,7 @@ func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker) (util.Ui if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err = nnsResolveHash(inv, nnsCs.Hash, containerContract+".frostfs") + ch, err = nnsResolveHash(inv, nnsCs.Hash, domainOf(containerContract)) if err != nil { return util.Uint160{}, err } @@ -306,7 +306,7 @@ func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err := nnsResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, containerContract+".frostfs") + ch, err := nnsResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, domainOf(containerContract)) if err != nil { return util.Uint160{}, fmt.Errorf("can't fetch container contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index 585de6d6d1..0a112f35c1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -87,7 +87,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { for _, ctrName := range contractList { bw.Reset() emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, - ctrName+".frostfs", int64(nns.TXT)) + domainOf(ctrName), int64(nns.TXT)) res, err := c.InvokeScript(bw.Bytes(), nil) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index 453e984b07..39dbb0caf0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -27,7 +27,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".frostfs") + nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 436ba93d2f..61536b4d55 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -91,6 +91,10 @@ const ( deployMethodName = "deploy" ) +func domainOf(contract string) string { + return contract + ".frostfs" +} + func (c *initializeContext) deployNNS(method string) error { cs := c.getContract(nnsContract) h := cs.Hash @@ -198,7 +202,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash cs := c.getContract(ctrName) method := updateMethodName - ctrHash, err := nnsResolveHash(c.ReadOnlyInvoker, nnsHash, ctrName+".frostfs") + ctrHash, err := nnsResolveHash(c.ReadOnlyInvoker, nnsHash, domainOf(ctrName)) if err != nil { if errors.Is(err, errMissingNNSRecord) { // if contract not found we deploy it instead of update @@ -595,7 +599,7 @@ func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, if err != nil { return nil, fmt.Errorf("NNS is not yet deployed: %w", err) } - nmHash, err := nnsResolveHash(c.ReadOnlyInvoker, cs.Hash, netmapContract+".frostfs") + nmHash, err := nnsResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { return nil, fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go index 30f7c69c42..bb1de09ca6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go @@ -20,7 +20,7 @@ func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { cs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) - nmHash, err := nnsResolveHash(inv, cs.Hash, netmapContract+".frostfs") + nmHash, err := nnsResolveHash(inv, cs.Hash, domainOf(netmapContract)) commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) res, err := inv.Call(nmHash, "netmapCandidates") diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy.go index effcf0e274..802a612467 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy.go @@ -46,7 +46,7 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error return fmt.Errorf("can't get NNS contract info: %w", err) } - proxyHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, proxyContract+".frostfs") + proxyHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(proxyContract)) if err != nil { return fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/remove_node.go b/cmd/frostfs-adm/internal/modules/morph/remove_node.go index ba7bb90ff6..ea958f2f7c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/remove_node.go +++ b/cmd/frostfs-adm/internal/modules/morph/remove_node.go @@ -40,7 +40,7 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, netmapContract+".frostfs") + nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } From 825f65f79ee4c8934961a7b040f7d42a42f7e946 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 20 Dec 2023 16:20:36 +0300 Subject: [PATCH 0231/1413] [#873] node: Start metrics and pprof as soon as possible Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/httpcomponent.go | 21 +++++++++------------ cmd/frostfs-node/worker.go | 9 --------- 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/cmd/frostfs-node/httpcomponent.go b/cmd/frostfs-node/httpcomponent.go index 6e8fa8f2ce..373a5e5c86 100644 --- a/cmd/frostfs-node/httpcomponent.go +++ b/cmd/frostfs-node/httpcomponent.go @@ -36,21 +36,19 @@ func (cmp *httpComponent) init(c *cfg) { cmp.shutdownDur, ), ) + c.wg.Add(1) + go func() { + defer c.wg.Done() + + c.log.Info(logs.FrostFSNodeStartListeningEndpoint, + zap.String("service", cmp.name), + zap.String("endpoint", cmp.address)) + fatalOnErr(srv.Serve()) + }() c.closers = append(c.closers, closer{ cmp.name, func() { stopAndLog(c, cmp.name, srv.Shutdown) }, }) - c.workers = append(c.workers, worker{ - cmp.name, - func(ctx context.Context) { - runAndLog(ctx, c, cmp.name, false, func(context.Context, *cfg) { - c.log.Info(logs.FrostFSNodeStartListeningEndpoint, - zap.String("service", cmp.name), - zap.String("endpoint", cmp.address)) - fatalOnErr(srv.Serve()) - }) - }, - }) } func (cmp *httpComponent) reload(ctx context.Context) error { @@ -64,7 +62,6 @@ func (cmp *httpComponent) reload(ctx context.Context) error { } // Cleanup delCloser(cmp.cfg, cmp.name) - delWorker(cmp.cfg, cmp.name) // Init server with new parameters cmp.init(cmp.cfg) // Start worker diff --git a/cmd/frostfs-node/worker.go b/cmd/frostfs-node/worker.go index bea235c481..c5649073b3 100644 --- a/cmd/frostfs-node/worker.go +++ b/cmd/frostfs-node/worker.go @@ -30,15 +30,6 @@ func startWorker(ctx context.Context, c *cfg, wrk worker) { }(wrk) } -func delWorker(c *cfg, name string) { - for i, worker := range c.workers { - if worker.name == name { - c.workers = append(c.workers[:i], c.workers[i+1:]...) - return - } - } -} - func getWorker(c *cfg, name string) *worker { for _, wrk := range c.workers { if wrk.name == name { From eab981bf1a661cb4773ef53a57d5ae2324a211cd Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 21 Dec 2023 16:33:24 +0300 Subject: [PATCH 0232/1413] [#876] Fix linter error Signed-off-by: Anton Nikiforov --- pkg/services/control/types.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/services/control/types.proto b/pkg/services/control/types.proto index d1bc05e298..00fcb98d1e 100644 --- a/pkg/services/control/types.proto +++ b/pkg/services/control/types.proto @@ -178,11 +178,11 @@ message ChainTarget { UNDEFINED = 0; NAMESPACE = 1; - + CONTAINER = 2; } TargetType type = 1; string Name = 2; -} \ No newline at end of file +} From 5b672fb3927e4a709d857a1da4f6deb72fd351ba Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 21 Dec 2023 16:33:37 +0300 Subject: [PATCH 0233/1413] [#876] adm: Add `morph ape get/set-admin` commands Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/ape.go | 58 +++++++++++++++++++ .../internal/modules/morph/root.go | 4 ++ go.mod | 2 +- go.sum | 4 +- 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape.go index 6dd2bd1859..9f1d75adba 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape.go @@ -7,6 +7,7 @@ import ( parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -26,6 +27,8 @@ const ( targetNameDesc = "Resource name in APE resource name format" targetTypeFlag = "target-type" targetTypeDesc = "Resource type(container/namespace)" + addrAdminFlag = "addr" + addrAdminDesc = "The address of the admins wallet" ) var ( @@ -63,6 +66,26 @@ var ( }, Run: listRuleChains, } + + setAdminCmd = &cobra.Command{ + Use: "set-admin", + Short: "Set admin", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + }, + Run: setAdmin, + } + + getAdminCmd = &cobra.Command{ + Use: "get-admin", + Short: "Get admin", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + }, + Run: getAdmin, + } ) func initAddRuleChainCmd() { @@ -110,6 +133,22 @@ func initListRuleChainsCmd() { listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc) } +func initSetAdminCmd() { + apeCmd.AddCommand(setAdminCmd) + + setAdminCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + setAdminCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + setAdminCmd.Flags().String(addrAdminFlag, "", addrAdminDesc) + _ = setAdminCmd.MarkFlagRequired(addrAdminFlag) +} + +func initGetAdminCmd() { + apeCmd.AddCommand(getAdminCmd) + + getAdminCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + getAdminCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) +} + func addRuleChain(cmd *cobra.Command, _ []string) { chain := parseChain(cmd) target := parseTarget(cmd) @@ -151,6 +190,25 @@ func listRuleChains(cmd *cobra.Command, _ []string) { } } +func setAdmin(cmd *cobra.Command, _ []string) { + s, _ := cmd.Flags().GetString(addrAdminFlag) + addr, err := util.Uint160DecodeStringLE(s) + commonCmd.ExitOnErr(cmd, "can't decode admin addr: %w", err) + pci, ac := newPolicyContractInterface(cmd) + h, vub, err := pci.SetAdmin(addr) + cmd.Println("Waiting for transaction to persist...") + _, err = ac.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "can't set admin: %w", err) + cmd.Println("Admin set successfully") +} + +func getAdmin(cmd *cobra.Command, _ []string) { + pci, _ := newPolicyContractInterface(cmd) + addr, err := pci.GetAdmin() + commonCmd.ExitOnErr(cmd, "unable to get admin: %w", err) + cmd.Println(addr.StringLE()) +} + func prettyJSONFormat(cmd *cobra.Command, chains []*apechain.Chain) { wr := bytes.NewBufferString("") data, err := json.Marshal(chains) diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 75409421ac..4176a64705 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -283,10 +283,14 @@ func init() { initRefillGasCmd() initDepositoryNotaryCmd() initNetmapCandidatesCmd() + RootCmd.AddCommand(apeCmd) initAddRuleChainCmd() initRemoveRuleChainCmd() initListRuleChainsCmd() + initSetAdminCmd() + initGetAdminCmd() + initProxyAddAccount() initProxyRemoveAccount() } diff --git a/go.mod b/go.mod index 6463c3b2bf..2b8ffea313 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231214122253-62ea96b82ce3 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231221121354-ed93bb5cc574 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index c18e291f27..56f4cba5ac 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231214122253-62ea96b82ce3 h1:xnS/YalLqCRplvpF3E9/PRGevj4cDe7qFNZT0mkjZcs= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231214122253-62ea96b82ce3/go.mod h1:v43imcuSmDwSNrePe4UTQh8jaE8FmsiKN3FcaEzmRzc= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231221121354-ed93bb5cc574 h1:PmPaHc4P/Rjn1WQcDF5gcwILzWjkMOuRHLqzm9OZCdA= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231221121354-ed93bb5cc574/go.mod h1:ps6oKO0mxaPJzK3admTB3iwoBXKkHnS73n4PCrqpHBg= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= From 8180a0664f05b5adedf399cbd8ad90f0f37115aa Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 22 Dec 2023 12:58:20 +0300 Subject: [PATCH 0234/1413] [#887] node: Drop badger writecache implementation Badger implementation isn't tested and works not well, but requires human resources to maintain. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-lens/internal/flags.go | 7 - .../internal/writecache/inspect.go | 32 +- cmd/frostfs-lens/internal/writecache/list.go | 30 +- cmd/frostfs-lens/internal/writecache/root.go | 1 - cmd/frostfs-node/config.go | 50 +-- .../config/engine/shard/writecache/config.go | 36 --- config/example/node.json | 1 - config/example/node.yaml | 1 - docs/storage-node-configuration.md | 2 - go.mod | 9 - go.sum | 74 ----- internal/logs/logs.go | 3 - .../engine/control_test.go | 10 +- .../shard/control_test.go | 10 +- pkg/local_object_storage/shard/range_test.go | 10 +- pkg/local_object_storage/shard/shard.go | 36 +-- pkg/local_object_storage/shard/shard_test.go | 22 +- .../shard/shutdown_test.go | 10 +- .../writecache/benchmark/writecache_test.go | 40 +-- .../{writecachebbolt => }/cachebbolt.go | 11 +- .../writecache/config/config.go | 22 -- .../{writecachebbolt => }/delete.go | 11 +- .../writecache/{writecachebbolt => }/flush.go | 13 +- .../flush.go => flush_test.go} | 110 ++++++- .../{writecachebbolt => }/generic_test.go | 2 +- .../writecache/{writecachebbolt => }/get.go | 11 +- .../{writecachebbolt => }/iterate.go | 2 +- .../writecache/{writecachebbolt => }/mode.go | 2 +- .../{writecachebbolt => }/options.go | 15 +- .../writecache/{writecachebbolt => }/put.go | 19 +- .../writecache/{writecachebbolt => }/state.go | 2 +- .../{writecachebbolt => }/storage.go | 7 +- .../writecache/{writecachebbolt => }/util.go | 2 +- .../writecachebadger/cachebadger.go | 138 --------- .../writecache/writecachebadger/delete.go | 70 ----- .../writecache/writecachebadger/flush.go | 286 ------------------ .../writecache/writecachebadger/flush_test.go | 69 ----- .../writecache/writecachebadger/gc.go | 45 --- .../writecachebadger/generic_test.go | 19 -- .../writecache/writecachebadger/get.go | 95 ------ .../writecache/writecachebadger/iterate.go | 32 -- .../writecache/writecachebadger/mode.go | 78 ----- .../writecache/writecachebadger/options.go | 119 -------- .../writecache/writecachebadger/put.go | 82 ----- .../writecache/writecachebadger/state.go | 67 ---- .../writecache/writecachebadger/storage.go | 91 ------ .../writecache/writecachebadger/util.go | 39 --- .../writecache/writecachebbolt/flush_test.go | 109 ------- 48 files changed, 202 insertions(+), 1750 deletions(-) rename pkg/local_object_storage/writecache/{writecachebbolt => }/cachebbolt.go (92%) delete mode 100644 pkg/local_object_storage/writecache/config/config.go rename pkg/local_object_storage/writecache/{writecachebbolt => }/delete.go (88%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/flush.go (93%) rename pkg/local_object_storage/writecache/{writecachetest/flush.go => flush_test.go} (62%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/generic_test.go (94%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/get.go (90%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/iterate.go (97%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/mode.go (98%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/options.go (92%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/put.go (84%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/state.go (98%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/storage.go (93%) rename pkg/local_object_storage/writecache/{writecachebbolt => }/util.go (95%) delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/cachebadger.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/delete.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/flush.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/flush_test.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/gc.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/generic_test.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/get.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/iterate.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/mode.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/options.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/put.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/state.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/storage.go delete mode 100644 pkg/local_object_storage/writecache/writecachebadger/util.go delete mode 100644 pkg/local_object_storage/writecache/writecachebbolt/flush_test.go diff --git a/cmd/frostfs-lens/internal/flags.go b/cmd/frostfs-lens/internal/flags.go index 004519167c..8a987a2d4a 100644 --- a/cmd/frostfs-lens/internal/flags.go +++ b/cmd/frostfs-lens/internal/flags.go @@ -8,7 +8,6 @@ const ( flagAddress = "address" flagEnginePath = "path" flagOutFile = "out" - flagDBType = "dbtype" ) // AddAddressFlag adds the address flag to the passed cobra command. @@ -34,9 +33,3 @@ func AddOutputFileFlag(cmd *cobra.Command, v *string) { "File to save object payload") _ = cmd.MarkFlagFilename(flagOutFile) } - -// AddDBTypeFlag adds the DB type flag to the passed cobra command. -func AddDBTypeFlag(cmd *cobra.Command, v *string) { - cmd.Flags().StringVar(v, flagDBType, "bbolt", - "Type of DB used by write cache (default: bbolt)") -} diff --git a/cmd/frostfs-lens/internal/writecache/inspect.go b/cmd/frostfs-lens/internal/writecache/inspect.go index 1a733513ba..afc986c8b9 100644 --- a/cmd/frostfs-lens/internal/writecache/inspect.go +++ b/cmd/frostfs-lens/internal/writecache/inspect.go @@ -1,13 +1,10 @@ package writecache import ( - "fmt" "os" common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/spf13/cobra" ) @@ -23,34 +20,17 @@ func init() { common.AddAddressFlag(inspectCMD, &vAddress) common.AddComponentPathFlag(inspectCMD, &vPath) common.AddOutputFileFlag(inspectCMD, &vOut) - common.AddDBTypeFlag(inspectCMD, &vDBType) } func inspectFunc(cmd *cobra.Command, _ []string) { var data []byte - switch vDBType { - case "bbolt": - db, err := writecachebbolt.OpenDB(vPath, true, os.OpenFile) - common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) - defer db.Close() + db, err := writecache.OpenDB(vPath, true, os.OpenFile) + common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) + defer db.Close() - data, err = writecachebbolt.Get(db, []byte(vAddress)) - common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err)) - - case "badger": - log, err := logger.NewLogger(&logger.Prm{}) - common.ExitOnErr(cmd, common.Errf("could not create logger: %w", err)) - - db, err := writecachebadger.OpenDB(vPath, true, log) - common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) - - data, err = writecachebadger.Get(db, []byte(vAddress)) - common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err)) - - default: - common.ExitOnErr(cmd, fmt.Errorf("invalid dbtype: %q (possible values: bbolt, badger)", vDBType)) - } + data, err = writecache.Get(db, []byte(vAddress)) + common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err)) var o objectSDK.Object common.ExitOnErr(cmd, common.Errf("could not unmarshal object: %w", o.Unmarshal(data))) diff --git a/cmd/frostfs-lens/internal/writecache/list.go b/cmd/frostfs-lens/internal/writecache/list.go index df02a82f72..bcbae0ec9b 100644 --- a/cmd/frostfs-lens/internal/writecache/list.go +++ b/cmd/frostfs-lens/internal/writecache/list.go @@ -6,9 +6,7 @@ import ( "os" common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/spf13/cobra" ) @@ -33,26 +31,10 @@ func listFunc(cmd *cobra.Command, _ []string) { return err } - switch vDBType { - case "bbolt": - db, err := writecachebbolt.OpenDB(vPath, true, os.OpenFile) - common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) - defer db.Close() + db, err := writecache.OpenDB(vPath, true, os.OpenFile) + common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) + defer db.Close() - err = writecachebbolt.IterateDB(db, wAddr) - common.ExitOnErr(cmd, common.Errf("write-cache iterator failure: %w", err)) - - case "badger": - log, err := logger.NewLogger(&logger.Prm{}) - common.ExitOnErr(cmd, common.Errf("could not create logger: %w", err)) - - db, err := writecachebadger.OpenDB(vPath, true, log) - common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) - - err = writecachebadger.IterateDB(db, wAddr) - common.ExitOnErr(cmd, common.Errf("write-cache iterator failure: %w", err)) - - default: - common.ExitOnErr(cmd, fmt.Errorf("invalid dbtype: %q (possible values: bbolt, badger)", vDBType)) - } + err = writecache.IterateDB(db, wAddr) + common.ExitOnErr(cmd, common.Errf("write-cache iterator failure: %w", err)) } diff --git a/cmd/frostfs-lens/internal/writecache/root.go b/cmd/frostfs-lens/internal/writecache/root.go index 11a8bb96b7..eb3b325b6c 100644 --- a/cmd/frostfs-lens/internal/writecache/root.go +++ b/cmd/frostfs-lens/internal/writecache/root.go @@ -8,7 +8,6 @@ var ( vAddress string vPath string vOut string - vDBType string ) // Root contains `write-cache` command definition. diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 82e2037885..ffe49a7ef0 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -41,9 +41,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" shardmode "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" containerClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" @@ -138,7 +136,6 @@ type shardCfg struct { writecacheCfg struct { enabled bool - typ writecacheconfig.Type path string maxBatchSize int maxBatchDelay time.Duration @@ -147,7 +144,6 @@ type shardCfg struct { flushWorkerCount int sizeLimit uint64 noSync bool - gcInterval time.Duration } piloramaCfg struct { @@ -258,7 +254,6 @@ func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, wc := &newConfig.writecacheCfg wc.enabled = true - wc.typ = writeCacheCfg.Type() wc.path = writeCacheCfg.Path() wc.maxBatchSize = writeCacheCfg.BoltDB().MaxBatchSize() wc.maxBatchDelay = writeCacheCfg.BoltDB().MaxBatchDelay() @@ -267,7 +262,6 @@ func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, wc.flushWorkerCount = writeCacheCfg.WorkerCount() wc.sizeLimit = writeCacheCfg.SizeLimit() wc.noSync = writeCacheCfg.NoSync() - wc.gcInterval = writeCacheCfg.GCInterval() } } @@ -836,36 +830,20 @@ func (c *cfg) shardOpts() []shardOptsWithID { return shards } -func (c *cfg) getWriteCacheOpts(shCfg shardCfg) writecacheconfig.Options { - var writeCacheOpts writecacheconfig.Options +func (c *cfg) getWriteCacheOpts(shCfg shardCfg) []writecache.Option { + var writeCacheOpts []writecache.Option if wcRead := shCfg.writecacheCfg; wcRead.enabled { - switch wcRead.typ { - case writecacheconfig.TypeBBolt: - writeCacheOpts.Type = writecacheconfig.TypeBBolt - writeCacheOpts.BBoltOptions = append(writeCacheOpts.BBoltOptions, - writecachebbolt.WithPath(wcRead.path), - writecachebbolt.WithMaxBatchSize(wcRead.maxBatchSize), - writecachebbolt.WithMaxBatchDelay(wcRead.maxBatchDelay), - writecachebbolt.WithMaxObjectSize(wcRead.maxObjSize), - writecachebbolt.WithSmallObjectSize(wcRead.smallObjectSize), - writecachebbolt.WithFlushWorkersCount(wcRead.flushWorkerCount), - writecachebbolt.WithMaxCacheSize(wcRead.sizeLimit), - writecachebbolt.WithNoSync(wcRead.noSync), - writecachebbolt.WithLogger(c.log), - ) - case writecacheconfig.TypeBadger: - writeCacheOpts.Type = writecacheconfig.TypeBadger - writeCacheOpts.BadgerOptions = append(writeCacheOpts.BadgerOptions, - writecachebadger.WithPath(wcRead.path), - writecachebadger.WithMaxObjectSize(wcRead.maxObjSize), - writecachebadger.WithFlushWorkersCount(wcRead.flushWorkerCount), - writecachebadger.WithMaxCacheSize(wcRead.sizeLimit), - writecachebadger.WithLogger(c.log), - writecachebadger.WithGCInterval(wcRead.gcInterval), - ) - default: - panic(fmt.Sprintf("unknown writecache type: %q", wcRead.typ)) - } + writeCacheOpts = append(writeCacheOpts, + writecache.WithPath(wcRead.path), + writecache.WithMaxBatchSize(wcRead.maxBatchSize), + writecache.WithMaxBatchDelay(wcRead.maxBatchDelay), + writecache.WithMaxObjectSize(wcRead.maxObjSize), + writecache.WithSmallObjectSize(wcRead.smallObjectSize), + writecache.WithFlushWorkersCount(wcRead.flushWorkerCount), + writecache.WithMaxCacheSize(wcRead.sizeLimit), + writecache.WithNoSync(wcRead.noSync), + writecache.WithLogger(c.log), + ) } return writeCacheOpts } diff --git a/cmd/frostfs-node/config/engine/shard/writecache/config.go b/cmd/frostfs-node/config/engine/shard/writecache/config.go index d0fd4bf75f..5e31e04ad9 100644 --- a/cmd/frostfs-node/config/engine/shard/writecache/config.go +++ b/cmd/frostfs-node/config/engine/shard/writecache/config.go @@ -1,12 +1,8 @@ package writecacheconfig import ( - "fmt" - "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" boltdbconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/boltdb" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" ) // Config is a wrapper over the config section @@ -25,9 +21,6 @@ const ( // SizeLimitDefault is a default write-cache size limit. SizeLimitDefault = 1 << 30 - - // DefaultGCInterval is the default duration of the GC cycle interval. - DefaultGCInterval = 1 * time.Minute ) // From wraps config section into Config. @@ -42,22 +35,6 @@ func (x *Config) Enabled() bool { return config.Bool((*config.Config)(x), "enabled") } -// Type returns the writecache implementation type to use. -// -// Panics if the type is not recognized. -func (x *Config) Type() writecacheconfig.Type { - t := config.String((*config.Config)(x), "type") - - switch t { - case "bbolt", "": - return writecacheconfig.TypeBBolt - case "badger": - return writecacheconfig.TypeBadger - } - - panic(fmt.Sprintf("invalid writecache type: %q", t)) -} - // Path returns the value of "path" config parameter. // // Panics if the value is not a non-empty string. @@ -149,16 +126,3 @@ func (x *Config) NoSync() bool { func (x *Config) BoltDB() *boltdbconfig.Config { return (*boltdbconfig.Config)(x) } - -// GCInterval returns the value of "gc_interval" config parameter. -// -// Returns DefaultGCInterval if the value is not a positive duration. -func (x *Config) GCInterval() time.Duration { - d := config.DurationSafe((*config.Config)(x), "gc_interval") - - if d > 0 { - return d - } - - return DefaultGCInterval -} diff --git a/config/example/node.json b/config/example/node.json index c803e11fb8..8dda5e6069 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -202,7 +202,6 @@ "resync_metabase": true, "writecache": { "enabled": true, - "type": "bbolt", "path": "tmp/1/cache", "memcache_capacity": 2147483648, "small_object_size": 16384, diff --git a/config/example/node.yaml b/config/example/node.yaml index d4c3516bc1..1715151648 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -127,7 +127,6 @@ storage: writecache: enabled: true - type: bbolt small_object_size: 16k # size threshold for "small" objects which are cached in key-value DB, not in FS, bytes max_object_size: 134217728 # size threshold for "big" objects which bypass write-cache and go to the storage directly, bytes flush_worker_count: 30 # number of write-cache flusher threads diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 613be12881..e2334f8fbf 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -277,7 +277,6 @@ metabase: ```yaml writecache: enabled: true - type: bbolt path: /path/to/writecache capacity: 4294967296 small_object_size: 16384 @@ -287,7 +286,6 @@ writecache: | Parameter | Type | Default value | Description | |----------------------|------------|---------------|----------------------------------------------------------------------------------------------------------------------| -| `type` | `string` | | Type of write cache backing implementation to use (`bbolt`, `badger`). | | `path` | `string` | | Path to the metabase file. | | `capacity` | `size` | unrestricted | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | | `small_object_size` | `size` | `32K` | Maximum object size for "small" objects. This objects are stored in a key-value database instead of a file-system. | diff --git a/go.mod b/go.mod index 2b8ffea313..c4266fe213 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 - github.com/dgraph-io/ristretto v0.1.1 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/google/uuid v1.4.0 github.com/hashicorp/golang-lru/v2 v2.0.7 @@ -44,18 +43,11 @@ require ( ) require ( - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v1.2.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/google/flatbuffers v23.5.26+incompatible // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect go.mongodb.org/mongo-driver v1.11.4 // indirect - go.opencensus.io v0.24.0 // indirect ) require ( @@ -71,7 +63,6 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect - github.com/dgraph-io/badger/v4 v4.2.0 github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect diff --git a/go.sum b/go.sum index 56f4cba5ac..490cd4aec4 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd h1:MxiIXu4vUATX9bNYFnM1dXAYkx5dnPOGCMzwNNXJEvM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231129062201-a1b61d394958 h1:X9yPizADIhD3K/gdKVCthlAnf9aQ3UJJGnZgIwwixRQ= @@ -17,7 +16,6 @@ git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9m git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= git.frostfs.info/TrueCloudLab/tzhash v1.8.0/go.mod h1:dhY+oy274hV8wGvGL4MwwMpdL3GYvaX1a8GQZQHvlF8= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= @@ -27,8 +25,6 @@ github.com/bits-and-blooms/bitset v1.11.0 h1:RMyy2mBBShArUAhfVRZJ2xyBO58KCBCtZFS github.com/bits-and-blooms/bitset v1.11.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= @@ -42,8 +38,6 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.2-0.20231117165148-e77308824822 h1:PvEjRgB/U4bv0jl9w65Wy9g0nIdkkW7vkNoR8Vq/als= @@ -57,19 +51,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= -github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= -github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= -github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= @@ -86,25 +67,14 @@ github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= @@ -112,20 +82,14 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/flatbuffers v23.5.26+incompatible h1:M9dgRyhJemaM4Sw8+66GHBu8ioaQmyPLg1b8VwK5WJg= -github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= @@ -237,14 +201,12 @@ github.com/paulmach/orb v0.9.2/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/Enu github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= @@ -278,14 +240,12 @@ github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= @@ -311,8 +271,6 @@ go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.mongodb.org/mongo-driver v1.11.4 h1:4ayjakA013OdpGyL2K3ZqylTac/rMjrJOMZ1EHizXas= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= @@ -340,35 +298,24 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -376,7 +323,6 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -397,7 +343,6 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -412,10 +357,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -426,21 +367,11 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f h1:Vn+VyHU5guc9KjB5KrjI2q0wCOWEOIh0OEsleqakHJg= google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 h1:ZcOkrmX74HbKFYnpPY8Qsw93fC29TbJXspYKaBkSXDQ= google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg= google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE= google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -448,10 +379,7 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= @@ -474,8 +402,6 @@ 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= diff --git a/internal/logs/logs.go b/internal/logs/logs.go index c3f4fdc7f0..6ead837000 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -291,7 +291,6 @@ const ( ShardFailureToMarkLockersAsGarbage = "failure to mark lockers as garbage" ShardFailureToGetExpiredUnlockedObjects = "failure to get expired unlocked objects" ShardCouldNotMarkObjectToDeleteInMetabase = "could not mark object to delete in metabase" - WritecacheBadgerInitExperimental = "initializing badger-backed experimental writecache" WritecacheTriedToFlushItemsFromWritecache = "tried to flush items from write-cache" WritecacheWaitingForChannelsToFlush = "waiting for channels to flush" WritecacheFillingFlushMarksForObjectsInFSTree = "filling flush marks for objects in FSTree" @@ -300,8 +299,6 @@ const ( WritecacheFinishedUpdatingFlushMarks = "finished updating flush marks" WritecacheCantRemoveObjectsFromTheDatabase = "can't remove objects from the database" WritecacheCantRemoveObjectFromWritecache = "can't remove object from write-cache" - WritecacheDBValueLogGCRunCompleted = "value log GC run completed" - WritecacheBadgerObjAlreadyScheduled = "object already scheduled for flush" BlobovniczatreeCouldNotGetObjectFromLevel = "could not get object from level" BlobovniczatreeCouldNotReadPayloadRangeFromOpenedBlobovnicza = "could not read payload range from opened blobovnicza" BlobovniczatreeCouldNotReadPayloadRangeFromActiveBlobovnicza = "could not read payload range from active blobovnicza" diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 9cfb311ec6..21652970b8 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -20,8 +20,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/stretchr/testify/require" @@ -44,11 +43,8 @@ func TestInitializationFailure(t *testing.T) { storages, smallFileStorage, largeFileStorage := newTestStorages(t.TempDir(), 1<<20) - wcOpts := writecacheconfig.Options{ - Type: writecacheconfig.TypeBBolt, - BBoltOptions: []writecachebbolt.Option{ - writecachebbolt.WithPath(t.TempDir()), - }, + wcOpts := []writecache.Option{ + writecache.WithPath(t.TempDir()), } return []shard.Option{ diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index f08af6fc74..8a650db0c0 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -17,8 +17,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -58,11 +57,8 @@ func TestShardOpen(t *testing.T) { return nil, fs.ErrPermission } - wcOpts := writecacheconfig.Options{ - Type: writecacheconfig.TypeBBolt, - BBoltOptions: []writecachebbolt.Option{ - writecachebbolt.WithPath(filepath.Join(dir, "wc")), - }, + wcOpts := []writecache.Option{ + writecache.WithPath(filepath.Join(dir, "wc")), } newShard := func() *Shard { diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 098a584ad6..35dc0c6a59 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -12,8 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -69,11 +68,8 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { testCase{true, "object in write-cache, out of range, big offset", 100, newRange(101, math.MaxUint64-10)}) } - wcOpts := writecacheconfig.Options{ - Type: writecacheconfig.TypeBBolt, - BBoltOptions: []writecachebbolt.Option{ - writecachebbolt.WithMaxObjectSize(writeCacheMaxSize), - }, + wcOpts := []writecache.Option{ + writecache.WithMaxObjectSize(writeCacheMaxSize), } sh := newCustomShard(t, hasWriteCache, shardOptions{ diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 56c6aee1f3..641b487edc 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -2,7 +2,6 @@ package shard import ( "context" - "fmt" "sync" "sync/atomic" "time" @@ -13,9 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -108,7 +104,7 @@ type cfg struct { metaOpts []meta.Option - writeCacheOpts writecacheconfig.Options + writeCacheOpts []writecache.Option piloramaOpts []pilorama.Option @@ -166,22 +162,11 @@ func New(opts ...Option) *Shard { s.blobStor.SetReportErrorFunc(reportFunc) if c.useWriteCache { - switch c.writeCacheOpts.Type { - case writecacheconfig.TypeBBolt: - s.writeCache = writecachebbolt.New( - append(c.writeCacheOpts.BBoltOptions, - writecachebbolt.WithReportErrorFunc(reportFunc), - writecachebbolt.WithBlobstor(bs), - writecachebbolt.WithMetabase(mb))...) - case writecacheconfig.TypeBadger: - s.writeCache = writecachebadger.New( - append(c.writeCacheOpts.BadgerOptions, - writecachebadger.WithReportErrorFunc(reportFunc), - writecachebadger.WithBlobstor(bs), - writecachebadger.WithMetabase(mb))...) - default: - panic(fmt.Sprintf("invalid writecache type: %v", c.writeCacheOpts.Type)) - } + s.writeCache = writecache.New( + append(c.writeCacheOpts, + writecache.WithReportErrorFunc(reportFunc), + writecache.WithBlobstor(bs), + writecache.WithMetabase(mb))...) } if s.piloramaOpts != nil { @@ -215,7 +200,7 @@ func WithMetaBaseOptions(opts ...meta.Option) Option { } // WithWriteCacheOptions returns option to set internal write cache options. -func WithWriteCacheOptions(opts writecacheconfig.Options) Option { +func WithWriteCacheOptions(opts []writecache.Option) Option { return func(c *cfg) { c.writeCacheOpts = opts } @@ -224,12 +209,7 @@ func WithWriteCacheOptions(opts writecacheconfig.Options) Option { // WithWriteCacheMetrics returns an option to set the metrics register used by the write cache. func WithWriteCacheMetrics(wcMetrics writecache.Metrics) Option { return func(c *cfg) { - switch c.writeCacheOpts.Type { - case writecacheconfig.TypeBBolt: - c.writeCacheOpts.BBoltOptions = append(c.writeCacheOpts.BBoltOptions, writecachebbolt.WithMetrics(wcMetrics)) - case writecacheconfig.TypeBadger: - c.writeCacheOpts.BadgerOptions = append(c.writeCacheOpts.BadgerOptions, writecachebadger.WithMetrics(wcMetrics)) - } + c.writeCacheOpts = append(c.writeCacheOpts, writecache.WithMetrics(wcMetrics)) } } diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 811c7f3abf..807633cd5a 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -11,9 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -33,7 +31,7 @@ func (s epochState) CurrentEpoch() uint64 { type shardOptions struct { rootPath string dontRelease bool - wcOpts writecacheconfig.Options + wcOpts []writecache.Option bsOpts []blobstor.Option metaOptions []meta.Option @@ -48,22 +46,12 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard if o.rootPath == "" { o.rootPath = t.TempDir() } - if enableWriteCache && o.wcOpts.Type == 0 { - o.wcOpts.Type = writecacheconfig.TypeBBolt - } var sh *Shard if enableWriteCache { - switch o.wcOpts.Type { - case writecacheconfig.TypeBBolt: - o.wcOpts.BBoltOptions = append( - []writecachebbolt.Option{writecachebbolt.WithPath(filepath.Join(o.rootPath, "wcache"))}, - o.wcOpts.BBoltOptions...) - case writecacheconfig.TypeBadger: - o.wcOpts.BadgerOptions = append( - []writecachebadger.Option{writecachebadger.WithPath(filepath.Join(o.rootPath, "wcache"))}, - o.wcOpts.BadgerOptions...) - } + o.wcOpts = append( + []writecache.Option{writecache.WithPath(filepath.Join(o.rootPath, "wcache"))}, + o.wcOpts...) } if o.bsOpts == nil { diff --git a/pkg/local_object_storage/shard/shutdown_test.go b/pkg/local_object_storage/shard/shutdown_test.go index 163c3a4aeb..b94ea50dc6 100644 --- a/pkg/local_object_storage/shard/shutdown_test.go +++ b/pkg/local_object_storage/shard/shutdown_test.go @@ -7,8 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" @@ -36,11 +35,8 @@ func TestWriteCacheObjectLoss(t *testing.T) { } dir := t.TempDir() - wcOpts := writecacheconfig.Options{ - Type: writecacheconfig.TypeBBolt, - BBoltOptions: []writecachebbolt.Option{ - writecachebbolt.WithMaxObjectSize(smallSize * 2), - }, + wcOpts := []writecache.Option{ + writecache.WithMaxObjectSize(smallSize * 2), } sh := newCustomShard(t, true, shardOptions{dontRelease: true, rootPath: dir, wcOpts: wcOpts}) diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index ea4bf0d33a..727d0fc7a0 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -3,35 +3,26 @@ package benchmark import ( "context" "testing" - "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" "github.com/stretchr/testify/require" ) func BenchmarkWritecacheSeq(b *testing.B) { const payloadSize = 8 << 10 b.Run("bbolt_seq", func(b *testing.B) { - benchmarkPutSeq(b, newBBoltCache(b), payloadSize) - }) - b.Run("badger_seq", func(b *testing.B) { - benchmarkPutSeq(b, newBadgerCache(b), payloadSize) + benchmarkPutSeq(b, newCache(b), payloadSize) }) } func BenchmarkWritecachePar(b *testing.B) { const payloadSize = 8 << 10 b.Run("bbolt_par", func(b *testing.B) { - benchmarkPutPar(b, newBBoltCache(b), payloadSize) - }) - b.Run("badger_par", func(b *testing.B) { - benchmarkPutPar(b, newBadgerCache(b), payloadSize) + benchmarkPutPar(b, newCache(b), payloadSize) }) } @@ -95,28 +86,15 @@ func (testMetabase) UpdateStorageID(context.Context, meta.UpdateStorageIDPrm) (m return meta.UpdateStorageIDRes{}, nil } -func newBBoltCache(b *testing.B) writecache.Cache { +func newCache(b *testing.B) writecache.Cache { bs := teststore.New( teststore.WithPut(func(pp common.PutPrm) (common.PutRes, error) { return common.PutRes{}, nil }), ) - return writecachebbolt.New( - writecachebbolt.WithPath(b.TempDir()), - writecachebbolt.WithBlobstor(bs), - writecachebbolt.WithMetabase(testMetabase{}), - writecachebbolt.WithMaxCacheSize(256<<30), - writecachebbolt.WithSmallObjectSize(128<<10), - ) -} - -func newBadgerCache(b *testing.B) writecache.Cache { - bs := teststore.New( - teststore.WithPut(func(pp common.PutPrm) (common.PutRes, error) { return common.PutRes{}, nil }), - ) - return writecachebadger.New( - writecachebadger.WithPath(b.TempDir()), - writecachebadger.WithBlobstor(bs), - writecachebadger.WithMetabase(testMetabase{}), - writecachebadger.WithMaxCacheSize(256<<30), - writecachebadger.WithGCInterval(10*time.Second), + return writecache.New( + writecache.WithPath(b.TempDir()), + writecache.WithBlobstor(bs), + writecache.WithMetabase(testMetabase{}), + writecache.WithMaxCacheSize(256<<30), + writecache.WithSmallObjectSize(128<<10), ) } diff --git a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go b/pkg/local_object_storage/writecache/cachebbolt.go similarity index 92% rename from pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go rename to pkg/local_object_storage/writecache/cachebbolt.go index 9bbf5b7df0..5eeda33a6f 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cachebbolt.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "context" @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.etcd.io/bbolt" @@ -58,7 +57,7 @@ const ( var defaultBucket = []byte{0} // New creates new writecache instance. -func New(opts ...Option) writecache.Cache { +func New(opts ...Option) Cache { c := &cache{ flushCh: make(chan objectInfo), mode: mode.ReadWrite, @@ -73,7 +72,7 @@ func New(opts ...Option) writecache.Cache { maxBatchSize: bbolt.DefaultMaxBatchSize, maxBatchDelay: bbolt.DefaultMaxBatchDelay, openFile: os.OpenFile, - metrics: writecache.DefaultMetrics(), + metrics: DefaultMetrics(), }, } @@ -89,8 +88,8 @@ func (c *cache) SetLogger(l *logger.Logger) { c.log = l } -func (c *cache) DumpInfo() writecache.Info { - return writecache.Info{ +func (c *cache) DumpInfo() Info { + return Info{ Path: c.path, } } diff --git a/pkg/local_object_storage/writecache/config/config.go b/pkg/local_object_storage/writecache/config/config.go deleted file mode 100644 index 91f097e175..0000000000 --- a/pkg/local_object_storage/writecache/config/config.go +++ /dev/null @@ -1,22 +0,0 @@ -// Package config provides the common configuration options for write cache implementations. -package config - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebadger" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachebbolt" -) - -// Type is the write cache implementation type. -type Type int - -const ( - TypeBBolt Type = iota - TypeBadger -) - -// Options are the configuration options for the write cache. -type Options struct { - Type Type - BBoltOptions []writecachebbolt.Option - BadgerOptions []writecachebadger.Option -} diff --git a/pkg/local_object_storage/writecache/writecachebbolt/delete.go b/pkg/local_object_storage/writecache/delete.go similarity index 88% rename from pkg/local_object_storage/writecache/writecachebbolt/delete.go rename to pkg/local_object_storage/writecache/delete.go index 15c83eed1a..0a4f4d658d 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/delete.go +++ b/pkg/local_object_storage/writecache/delete.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "context" @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -27,7 +26,7 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { defer span.End() deleted := false - storageType := writecache.StorageTypeUndefined + storageType := StorageTypeUndefined startedAt := time.Now() defer func() { c.metrics.Delete(time.Since(startedAt), deleted, storageType) @@ -36,7 +35,7 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { c.modeMtx.RLock() defer c.modeMtx.RUnlock() if c.readOnly() { - return writecache.ErrReadOnly + return ErrReadOnly } saddr := addr.EncodeToString() @@ -49,7 +48,7 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { }) if dataSize > 0 { - storageType = writecache.StorageTypeDB + storageType = StorageTypeDB var recordDeleted bool err := c.db.Update(func(tx *bbolt.Tx) error { b := tx.Bucket(defaultBucket) @@ -74,7 +73,7 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { return nil } - storageType = writecache.StorageTypeFSTree + storageType = StorageTypeFSTree _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr}) if err == nil { storagelog.Write(c.log, diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush.go b/pkg/local_object_storage/writecache/flush.go similarity index 93% rename from pkg/local_object_storage/writecache/writecachebbolt/flush.go rename to pkg/local_object_storage/writecache/flush.go index d73e374f52..f4ceec8c8b 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "bytes" @@ -12,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -195,7 +194,7 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { return err } - err = c.flushObject(ctx, &obj, e.ObjectData, writecache.StorageTypeFSTree) + err = c.flushObject(ctx, &obj, e.ObjectData, StorageTypeFSTree) if err != nil { if ignoreErrors { return nil @@ -224,7 +223,7 @@ func (c *cache) workerFlushSmall(ctx context.Context) { return } - err := c.flushObject(ctx, objInfo.obj, objInfo.data, writecache.StorageTypeDB) + err := c.flushObject(ctx, objInfo.obj, objInfo.data, StorageTypeDB) if err != nil { // Error is handled in flushObject. continue @@ -235,7 +234,7 @@ func (c *cache) workerFlushSmall(ctx context.Context) { } // flushObject is used to write object directly to the main storage. -func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []byte, st writecache.StorageType) error { +func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []byte, st StorageType) error { var err error defer func() { @@ -274,7 +273,7 @@ func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []b // Write-cache must be in readonly mode to ensure correctness of an operation and // to prevent interference with background flush workers. func (c *cache) Flush(ctx context.Context, ignoreErrors bool) error { - ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Flush", + ctx, span := tracing.StartSpanFromContext(ctx, "Flush", trace.WithAttributes( attribute.Bool("ignore_errors", ignoreErrors), )) @@ -315,7 +314,7 @@ func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { return err } - if err := c.flushObject(ctx, &obj, data, writecache.StorageTypeDB); err != nil { + if err := c.flushObject(ctx, &obj, data, StorageTypeDB); err != nil { return err } } diff --git a/pkg/local_object_storage/writecache/writecachetest/flush.go b/pkg/local_object_storage/writecache/flush_test.go similarity index 62% rename from pkg/local_object_storage/writecache/writecachetest/flush.go rename to pkg/local_object_storage/writecache/flush_test.go index 2c495df521..20db1de959 100644 --- a/pkg/local_object_storage/writecache/writecachetest/flush.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -1,7 +1,8 @@ -package writecachetest +package writecache import ( "context" + "os" "path/filepath" "sync/atomic" "testing" @@ -13,12 +14,103 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" + "go.etcd.io/bbolt" + "go.uber.org/zap" ) +func TestFlush(t *testing.T) { + testlogger := test.NewLogger(t, true) + + createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs MainStorage, opts ...Option) Cache { + return New( + append([]Option{ + WithLogger(testlogger), + WithPath(filepath.Join(t.TempDir(), "writecache")), + WithSmallObjectSize(smallSize), + WithMetabase(mb), + WithBlobstor(bs), + WithDisableBackgroundFlush(), + }, opts...)...) + } + + errCountOpt := func() (Option, *atomic.Uint32) { + cnt := &atomic.Uint32{} + return WithReportErrorFunc(func(msg string, err error) { + cnt.Add(1) + testlogger.Warn(msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) + }), cnt + } + + failures := []TestFailureInjector[Option]{ + { + Desc: "db, invalid address", + InjectFn: func(t *testing.T, wc Cache) { + c := wc.(*cache) + obj := testutil.GenerateObject() + data, err := obj.Marshal() + require.NoError(t, err) + require.NoError(t, c.db.Batch(func(tx *bbolt.Tx) error { + b := tx.Bucket(defaultBucket) + return b.Put([]byte{1, 2, 3}, data) + })) + }, + }, + { + Desc: "db, invalid object", + InjectFn: func(t *testing.T, wc Cache) { + c := wc.(*cache) + require.NoError(t, c.db.Batch(func(tx *bbolt.Tx) error { + b := tx.Bucket(defaultBucket) + k := []byte(oidtest.Address().EncodeToString()) + v := []byte{1, 2, 3} + return b.Put(k, v) + })) + }, + }, + { + Desc: "fs, read error", + InjectFn: func(t *testing.T, wc Cache) { + c := wc.(*cache) + obj := testutil.GenerateObject() + data, err := obj.Marshal() + require.NoError(t, err) + + var prm common.PutPrm + prm.Address = objectCore.AddressOf(obj) + prm.RawData = data + + _, err = c.fsTree.Put(context.Background(), prm) + require.NoError(t, err) + + p := prm.Address.Object().EncodeToString() + "." + prm.Address.Container().EncodeToString() + p = filepath.Join(c.fsTree.RootPath, p[:1], p[1:]) + + _, err = os.Stat(p) // sanity check + require.NoError(t, err) + require.NoError(t, os.Truncate(p, 0)) // corrupt the file contents, so that it can't be unmarshalled + }, + }, + { + Desc: "fs, invalid object", + InjectFn: func(t *testing.T, wc Cache) { + c := wc.(*cache) + var prm common.PutPrm + prm.Address = oidtest.Address() + prm.RawData = []byte{1, 2, 3} + _, err := c.fsTree.Put(context.Background(), prm) + require.NoError(t, err) + }, + }, + } + + runFlushTest(t, createCacheFn, errCountOpt, failures...) +} + const ( objCount = 4 smallSize = 256 @@ -28,13 +120,13 @@ type CreateCacheFunc[Option any] func( t *testing.T, smallSize uint64, meta *meta.DB, - bs writecache.MainStorage, + bs MainStorage, opts ...Option, -) writecache.Cache +) Cache type TestFailureInjector[Option any] struct { Desc string - InjectFn func(*testing.T, writecache.Cache) + InjectFn func(*testing.T, Cache) } type objectPair struct { @@ -42,7 +134,7 @@ type objectPair struct { obj *objectSDK.Object } -func TestFlush[Option any]( +func runFlushTest[Option any]( t *testing.T, createCacheFn CreateCacheFunc[Option], errCountOption func() (Option, *atomic.Uint32), @@ -105,7 +197,7 @@ func newCache[Option any]( createCacheFn CreateCacheFunc[Option], smallSize uint64, opts ...Option, -) (writecache.Cache, *blobstor.BlobStor, *meta.DB) { +) (Cache, *blobstor.BlobStor, *meta.DB) { dir := t.TempDir() mb := meta.New( meta.WithPath(filepath.Join(dir, "meta")), @@ -136,7 +228,7 @@ func newCache[Option any]( return wc, bs, mb } -func putObject(t *testing.T, c writecache.Cache, size int) objectPair { +func putObject(t *testing.T, c Cache, size int) objectPair { obj := testutil.GenerateObjectWithSize(size) data, err := obj.Marshal() require.NoError(t, err) @@ -152,7 +244,7 @@ func putObject(t *testing.T, c writecache.Cache, size int) objectPair { return objectPair{prm.Address, prm.Object} } -func putObjects(t *testing.T, c writecache.Cache) []objectPair { +func putObjects(t *testing.T, c Cache) []objectPair { objects := make([]objectPair, objCount) for i := range objects { objects[i] = putObject(t, c, 1+(i%2)*smallSize) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go b/pkg/local_object_storage/writecache/generic_test.go similarity index 94% rename from pkg/local_object_storage/writecache/writecachebbolt/generic_test.go rename to pkg/local_object_storage/writecache/generic_test.go index 7eadd1afcb..a6d9e47994 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/generic_test.go +++ b/pkg/local_object_storage/writecache/generic_test.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "testing" diff --git a/pkg/local_object_storage/writecache/writecachebbolt/get.go b/pkg/local_object_storage/writecache/get.go similarity index 90% rename from pkg/local_object_storage/writecache/writecachebbolt/get.go rename to pkg/local_object_storage/writecache/get.go index 838b207bed..d2496e447a 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/get.go +++ b/pkg/local_object_storage/writecache/get.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "bytes" @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -36,7 +35,7 @@ func (c *cache) Get(ctx context.Context, addr oid.Address) (*objectSDK.Object, e func (c *cache) getInternal(ctx context.Context, saddr string, addr oid.Address) (*objectSDK.Object, error) { found := false - storageType := writecache.StorageTypeUndefined + storageType := StorageTypeUndefined startedAt := time.Now() defer func() { c.metrics.Get(time.Since(startedAt), found, storageType) @@ -46,7 +45,7 @@ func (c *cache) getInternal(ctx context.Context, saddr string, addr oid.Address) if err == nil { obj := objectSDK.New() found = true - storageType = writecache.StorageTypeDB + storageType = StorageTypeDB return obj, obj.Unmarshal(value) } @@ -56,7 +55,7 @@ func (c *cache) getInternal(ctx context.Context, saddr string, addr oid.Address) } found = true - storageType = writecache.StorageTypeFSTree + storageType = StorageTypeFSTree return res.Object, nil } @@ -66,7 +65,7 @@ func (c *cache) getInternal(ctx context.Context, saddr string, addr oid.Address) func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) { saddr := addr.EncodeToString() - ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Head", + ctx, span := tracing.StartSpanFromContext(ctx, "Head", trace.WithAttributes( attribute.String("address", saddr), )) diff --git a/pkg/local_object_storage/writecache/writecachebbolt/iterate.go b/pkg/local_object_storage/writecache/iterate.go similarity index 97% rename from pkg/local_object_storage/writecache/writecachebbolt/iterate.go rename to pkg/local_object_storage/writecache/iterate.go index 530db42a61..5349c069cd 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/iterate.go +++ b/pkg/local_object_storage/writecache/iterate.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "errors" diff --git a/pkg/local_object_storage/writecache/writecachebbolt/mode.go b/pkg/local_object_storage/writecache/mode.go similarity index 98% rename from pkg/local_object_storage/writecache/writecachebbolt/mode.go rename to pkg/local_object_storage/writecache/mode.go index b187996a11..e3ff2286b7 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "context" diff --git a/pkg/local_object_storage/writecache/writecachebbolt/options.go b/pkg/local_object_storage/writecache/options.go similarity index 92% rename from pkg/local_object_storage/writecache/writecachebbolt/options.go rename to pkg/local_object_storage/writecache/options.go index 3ea3291925..c8eb1bc45c 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -1,11 +1,10 @@ -package writecachebbolt +package writecache import ( "io/fs" "os" "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) @@ -18,9 +17,9 @@ type options struct { // path is a path to a directory for write-cache. path string // blobstor is the main persistent storage. - blobstor writecache.MainStorage + blobstor MainStorage // metabase is the metabase instance. - metabase writecache.Metabase + metabase Metabase // maxObjectSize is the maximum size of the object stored in the write-cache. maxObjectSize uint64 // smallObjectSize is the maximum size of the object stored in the database. @@ -43,7 +42,7 @@ type options struct { // openFile is the function called internally by bbolt to open database files. Useful for hermetic testing. openFile func(string, int, fs.FileMode) (*os.File, error) // metrics is metrics implementation - metrics writecache.Metrics + metrics Metrics // disableBackgroundFlush is for testing purposes only. disableBackgroundFlush bool } @@ -63,14 +62,14 @@ func WithPath(path string) Option { } // WithBlobstor sets main object storage. -func WithBlobstor(bs writecache.MainStorage) Option { +func WithBlobstor(bs MainStorage) Option { return func(o *options) { o.blobstor = bs } } // WithMetabase sets metabase. -func WithMetabase(db writecache.Metabase) Option { +func WithMetabase(db Metabase) Option { return func(o *options) { o.metabase = db } @@ -152,7 +151,7 @@ func WithOpenFile(f func(string, int, fs.FileMode) (*os.File, error)) Option { } // WithMetrics sets metrics implementation. -func WithMetrics(metrics writecache.Metrics) Option { +func WithMetrics(metrics Metrics) Option { return func(o *options) { o.metrics = metrics } diff --git a/pkg/local_object_storage/writecache/writecachebbolt/put.go b/pkg/local_object_storage/writecache/put.go similarity index 84% rename from pkg/local_object_storage/writecache/writecachebbolt/put.go rename to pkg/local_object_storage/writecache/put.go index 63fa544ed5..6fc655c651 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -1,27 +1,18 @@ -package writecachebbolt +package writecache import ( "context" - "errors" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) -var ( - // ErrBigObject is returned when object is too big to be placed in cache. - ErrBigObject = errors.New("too big object") - // ErrOutOfSpace is returned when there is no space left to put a new object. - ErrOutOfSpace = errors.New("no space left in the write cache") -) - // Put puts object to write-cache. // // Returns ErrReadOnly if write-cache is in R/O mode. @@ -38,7 +29,7 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro startedAt := time.Now() added := false - storageType := writecache.StorageTypeUndefined + storageType := StorageTypeUndefined defer func() { c.metrics.Put(time.Since(startedAt), added, storageType) }() @@ -46,7 +37,7 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro c.modeMtx.RLock() defer c.modeMtx.RUnlock() if c.readOnly() { - return common.PutRes{}, writecache.ErrReadOnly + return common.PutRes{}, ErrReadOnly } sz := uint64(len(prm.RawData)) @@ -61,7 +52,7 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro } if sz <= c.smallObjectSize { - storageType = writecache.StorageTypeDB + storageType = StorageTypeDB err := c.putSmall(oi) if err == nil { added = true @@ -69,7 +60,7 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro return common.PutRes{}, err } - storageType = writecache.StorageTypeFSTree + storageType = StorageTypeFSTree err := c.putBig(ctx, oi.addr, prm) if err == nil { added = true diff --git a/pkg/local_object_storage/writecache/writecachebbolt/state.go b/pkg/local_object_storage/writecache/state.go similarity index 98% rename from pkg/local_object_storage/writecache/writecachebbolt/state.go rename to pkg/local_object_storage/writecache/state.go index 9261b2606f..bc75aaf275 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/state.go +++ b/pkg/local_object_storage/writecache/state.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "fmt" diff --git a/pkg/local_object_storage/writecache/writecachebbolt/storage.go b/pkg/local_object_storage/writecache/storage.go similarity index 93% rename from pkg/local_object_storage/writecache/writecachebbolt/storage.go rename to pkg/local_object_storage/writecache/storage.go index 7a50306252..5c25a3b33f 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "context" @@ -10,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -78,7 +77,7 @@ func (c *cache) deleteFromDB(key string) { }) if err == nil { - c.metrics.Evict(writecache.StorageTypeDB) + c.metrics.Evict(StorageTypeDB) storagelog.Write(c.log, storagelog.AddressField(key), storagelog.StorageTypeField(wcStorageType), @@ -103,7 +102,7 @@ func (c *cache) deleteFromDisk(ctx context.Context, addr oid.Address) { storagelog.StorageTypeField(wcStorageType), storagelog.OpField("fstree DELETE"), ) - c.metrics.Evict(writecache.StorageTypeFSTree) + c.metrics.Evict(StorageTypeFSTree) // counter changed by fstree c.estimateCacheSize() } diff --git a/pkg/local_object_storage/writecache/writecachebbolt/util.go b/pkg/local_object_storage/writecache/util.go similarity index 95% rename from pkg/local_object_storage/writecache/writecachebbolt/util.go rename to pkg/local_object_storage/writecache/util.go index fe225583cb..0ed4a954e1 100644 --- a/pkg/local_object_storage/writecache/writecachebbolt/util.go +++ b/pkg/local_object_storage/writecache/util.go @@ -1,4 +1,4 @@ -package writecachebbolt +package writecache import ( "io/fs" diff --git a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go b/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go deleted file mode 100644 index 484f018150..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/cachebadger.go +++ /dev/null @@ -1,138 +0,0 @@ -package writecachebadger - -import ( - "context" - "sync" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.uber.org/zap" -) - -type cache struct { - options - - mode mode.Mode - modeMtx sync.RWMutex - - // flushCh is a channel with objects to flush. - flushCh chan objectInfo - // scheduled4Flush contains objects scheduled for flush via flushCh - // helps to avoid multiple flushing of one object - scheduled4Flush map[oid.Address]struct{} - scheduled4FlushMtx sync.RWMutex - // wg is a wait group for flush workers. - wg sync.WaitGroup - // store contains underlying database. - store - // cancel is cancel function, protected by modeMtx in Close. - cancel func() -} - -// wcStorageType is used for write-cache operations logging. -const wcStorageType = "write-cache" - -type objectInfo struct { - addr oid.Address - data []byte - obj *objectSDK.Object -} - -const ( - defaultMaxObjectSize = 64 << 20 // 64 MiB - defaultSmallObjectSize = 32 << 10 // 32 KiB - defaultMaxCacheSize = 1 << 30 // 1 GiB -) - -// New creates new writecache instance. -func New(opts ...Option) writecache.Cache { - c := &cache{ - flushCh: make(chan objectInfo), - mode: mode.ReadWrite, - scheduled4Flush: map[oid.Address]struct{}{}, - - options: options{ - log: &logger.Logger{Logger: zap.NewNop()}, - maxObjectSize: defaultMaxObjectSize, - workersCount: defaultFlushWorkersCount, - maxCacheSize: defaultMaxCacheSize, - metrics: writecache.DefaultMetrics(), - }, - } - - for i := range opts { - opts[i](&c.options) - } - - return c -} - -// SetLogger sets logger. It is used after the shard ID was generated to use it in logs. -func (c *cache) SetLogger(l *logger.Logger) { - c.log = l -} - -func (c *cache) DumpInfo() writecache.Info { - return writecache.Info{ - Path: c.path, - } -} - -// Open opens and initializes database. Reads object counters from the ObjectCounters instance. -func (c *cache) Open(_ context.Context, readOnly bool) error { - c.modeMtx.Lock() - defer c.modeMtx.Unlock() - - err := c.openStore(readOnly) - if err != nil { - return metaerr.Wrap(err) - } - return metaerr.Wrap(c.initCounters()) -} - -// Init runs necessary services. -func (c *cache) Init() error { - c.modeMtx.Lock() - defer c.modeMtx.Unlock() - - c.log.Info(logs.WritecacheBadgerInitExperimental) - c.metrics.SetMode(c.mode) - ctx, cancel := context.WithCancel(context.Background()) - c.cancel = cancel - c.runFlushLoop(ctx) - c.runGCLoop(ctx) - return nil -} - -// Close closes db connection and stops services. Executes ObjectCounters.FlushAndClose op. -func (c *cache) Close() error { - // We cannot lock mutex for the whole operation duration - // because it is taken by some background workers, so `wg.Wait()` is done without modeMtx. - c.modeMtx.Lock() - if c.cancel != nil { - c.cancel() - c.cancel = nil - } - c.mode = mode.DegradedReadOnly // prevent new operations from being processed - c.modeMtx.Unlock() - - c.wg.Wait() - - c.modeMtx.Lock() - defer c.modeMtx.Unlock() - - var err error - if c.db != nil { - err = c.db.Close() - if err != nil { - c.db = nil - } - } - c.metrics.Close() - return nil -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/delete.go b/pkg/local_object_storage/writecache/writecachebadger/delete.go deleted file mode 100644 index f96bf27076..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/delete.go +++ /dev/null @@ -1,70 +0,0 @@ -package writecachebadger - -import ( - "context" - "time" - - storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/dgraph-io/badger/v4" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// Delete removes object from write-cache. -// -// Returns an error of type apistatus.ObjectNotFound if object is missing in write-cache. -func (c *cache) Delete(ctx context.Context, addr oid.Address) error { - _, span := tracing.StartSpanFromContext(ctx, "writecache.Delete", - trace.WithAttributes( - attribute.String("address", addr.EncodeToString()), - )) - defer span.End() - - deleted := false - storageType := writecache.StorageTypeUndefined - startedAt := time.Now() - defer func() { - c.metrics.Delete(time.Since(startedAt), deleted, storageType) - }() - - c.modeMtx.RLock() - defer c.modeMtx.RUnlock() - if c.readOnly() { - return writecache.ErrReadOnly - } - - key := addr2key(addr) - - err := c.db.Update(func(tx *badger.Txn) error { - it, err := tx.Get(key[:]) - if err != nil { - if err == badger.ErrKeyNotFound { - return logicerr.Wrap(new(apistatus.ObjectNotFound)) - } - return err - } - if it.ValueSize() > 0 { - storageType = writecache.StorageTypeDB - err := tx.Delete(key[:]) - if err == nil { - storagelog.Write(c.log, - storagelog.AddressField(addr.EncodeToString()), - storagelog.StorageTypeField(wcStorageType), - storagelog.OpField("db DELETE"), - ) - deleted = true - c.decDB() - } - return err - } - return nil - }) - - return metaerr.Wrap(err) -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush.go b/pkg/local_object_storage/writecache/writecachebadger/flush.go deleted file mode 100644 index 48e31dee6a..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/flush.go +++ /dev/null @@ -1,286 +0,0 @@ -package writecachebadger - -import ( - "bytes" - "context" - "encoding/hex" - "errors" - "fmt" - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "github.com/dgraph-io/badger/v4" - "github.com/dgraph-io/ristretto/z" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" -) - -const ( - // flushBatchSize is amount of keys which will be read from cache to be flushed - // to the main storage. It is used to reduce contention between cache put - // and cache persist. - flushBatchSize = 512 - // defaultFlushWorkersCount is number of workers for putting objects in main storage. - defaultFlushWorkersCount = 20 - // defaultFlushInterval is default time interval between successive flushes. - defaultFlushInterval = time.Second -) - -type collector struct { - cache *cache - scheduled int - processed int -} - -func (c *collector) send(ctx context.Context, cancel func(), buf *z.Buffer) error { - list, err := badger.BufferToKVList(buf) - if err != nil { - return err - } - for _, kv := range list.Kv { - select { - case <-ctx.Done(): - return nil - default: - } - if kv.StreamDone { - return nil - } - if c.scheduled >= flushBatchSize { - cancel() - return nil - } - if got, want := len(kv.Key), len(internalKey{}); got != want { - c.cache.log.Debug( - fmt.Sprintf("not expected db key len: got %d, want %d", got, want)) - continue - } - c.processed++ - obj := objectSDK.New() - val := bytes.Clone(kv.Value) - if err = obj.Unmarshal(val); err != nil { - continue - } - addr := objectCore.AddressOf(obj) - c.cache.scheduled4FlushMtx.RLock() - _, ok := c.cache.scheduled4Flush[addr] - c.cache.scheduled4FlushMtx.RUnlock() - if ok { - c.cache.log.Debug(logs.WritecacheBadgerObjAlreadyScheduled, zap.Stringer("obj", addr)) - continue - } - c.cache.scheduled4FlushMtx.Lock() - c.cache.scheduled4Flush[addr] = struct{}{} - c.cache.scheduled4FlushMtx.Unlock() - c.scheduled++ - select { - case c.cache.flushCh <- objectInfo{ - addr: addr, - data: val, - obj: obj, - }: - case <-ctx.Done(): - return nil - } - } - return nil -} - -// runFlushLoop starts background workers which periodically flush objects to the blobstor. -func (c *cache) runFlushLoop(ctx context.Context) { - if c.disableBackgroundFlush { - return - } - for i := 0; i < c.workersCount; i++ { - c.wg.Add(1) - go c.workerFlushSmall(ctx) - } - - c.wg.Add(1) - go func() { - defer c.wg.Done() - - tt := time.NewTimer(defaultFlushInterval) - defer tt.Stop() - - for { - select { - case <-tt.C: - c.flushSmallObjects(ctx) - tt.Reset(defaultFlushInterval) - case <-ctx.Done(): - return - } - } - }() -} - -func (c *cache) flushSmallObjects(ctx context.Context) { - for { - select { - case <-ctx.Done(): - return - default: - } - c.modeMtx.RLock() - if c.readOnly() { - c.modeMtx.RUnlock() - time.Sleep(time.Second) - continue - } - - // Using the db after Close will panic and badger won't wait for outstanding txs, - // so we need to check manually. - if c.db.IsClosed() { - c.modeMtx.RUnlock() - return - } - ctx, cancel := context.WithCancel(ctx) - coll := collector{ - cache: c, - } - stream := c.db.NewStream() - // All calls to Send are done by a single goroutine - stream.Send = func(buf *z.Buffer) error { - return coll.send(ctx, cancel, buf) - } - if err := stream.Orchestrate(ctx); err != nil { - c.log.Debug(fmt.Sprintf( - "error during flushing object from wc: %s", err)) - } - c.modeMtx.RUnlock() - if coll.scheduled == 0 { - break - } - c.log.Debug(logs.WritecacheTriedToFlushItemsFromWritecache, - zap.Int("scheduled", coll.scheduled), zap.Int("processed", coll.processed)) - } -} - -func (c *cache) reportFlushError(msg string, addr string, err error) { - if c.reportError != nil { - c.reportError(msg, err) - } else { - c.log.Error(msg, - zap.String("address", addr), - zap.Error(err)) - } -} - -// workerFlushSmall writes small objects to the main storage. -func (c *cache) workerFlushSmall(ctx context.Context) { - defer c.wg.Done() - - var objInfo objectInfo - for { - // Give priority to direct put. - select { - case objInfo = <-c.flushCh: - case <-ctx.Done(): - return - } - - err := c.flushObject(ctx, objInfo.obj, objInfo.data, writecache.StorageTypeDB) - if err == nil { - c.deleteFromDB([]internalKey{addr2key(objInfo.addr)}) - } - c.scheduled4FlushMtx.Lock() - delete(c.scheduled4Flush, objInfo.addr) - c.scheduled4FlushMtx.Unlock() - } -} - -// flushObject is used to write object directly to the main storage. -func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []byte, st writecache.StorageType) error { - var err error - - defer func() { - c.metrics.Flush(err == nil, st) - }() - - addr := objectCore.AddressOf(obj) - - var prm common.PutPrm - prm.Object = obj - prm.RawData = data - - res, err := c.blobstor.Put(ctx, prm) - if err != nil { - if !errors.Is(err, common.ErrNoSpace) && !errors.Is(err, common.ErrReadOnly) && - !errors.Is(err, blobstor.ErrNoPlaceFound) { - c.reportFlushError(logs.FrostFSNodeCantFlushObjectToBlobstor, - addr.EncodeToString(), err) - } - return err - } - - var updPrm meta.UpdateStorageIDPrm - updPrm.SetAddress(addr) - updPrm.SetStorageID(res.StorageID) - - _, err = c.metabase.UpdateStorageID(ctx, updPrm) - if err != nil { - c.reportFlushError(logs.FrostFSNodeCantUpdateObjectStorageID, - addr.EncodeToString(), err) - } - return err -} - -// Flush flushes all objects from the write-cache to the main storage. -// Write-cache must be in readonly mode to ensure correctness of an operation and -// to prevent interference with background flush workers. -func (c *cache) Flush(ctx context.Context, ignoreErrors bool) error { - ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Flush", - trace.WithAttributes( - attribute.Bool("ignore_errors", ignoreErrors), - )) - defer span.End() - - c.modeMtx.RLock() - defer c.modeMtx.RUnlock() - - return c.flush(ctx, ignoreErrors) -} - -func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { - return c.db.View(func(tx *badger.Txn) error { - it := tx.NewIterator(badger.DefaultIteratorOptions) - defer it.Close() - var key internalKey - for it.Rewind(); it.Valid(); it.Next() { - if got, want := int(it.Item().KeySize()), len(key); got != want { - err := fmt.Errorf("invalid db key len: got %d, want %d", got, want) - c.reportFlushError(logs.FrostFSNodeCantDecodeObjectAddressFromDB, hex.EncodeToString(it.Item().Key()), metaerr.Wrap(err)) - if ignoreErrors { - continue - } - return err - } - if err := it.Item().Value(func(data []byte) error { - var obj objectSDK.Object - if err := obj.Unmarshal(data); err != nil { - copy(key[:], it.Item().Key()) - c.reportFlushError(logs.FrostFSNodeCantUnmarshalObjectFromDB, key.address().EncodeToString(), metaerr.Wrap(err)) - if ignoreErrors { - return nil - } - return err - } - - return c.flushObject(ctx, &obj, data, writecache.StorageTypeDB) - }); err != nil { - return err - } - } - return nil - }) -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go b/pkg/local_object_storage/writecache/writecachebadger/flush_test.go deleted file mode 100644 index 5e3f60eab2..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/flush_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package writecachebadger - -import ( - "path/filepath" - "sync/atomic" - "testing" - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachetest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - "github.com/dgraph-io/badger/v4" - "github.com/stretchr/testify/require" - "go.uber.org/zap" -) - -func TestFlush(t *testing.T) { - testlogger := test.NewLogger(t, true) - - createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs writecache.MainStorage, opts ...Option) writecache.Cache { - return New( - append([]Option{ - WithLogger(test.NewLogger(t, true)), - WithPath(filepath.Join(t.TempDir(), "writecache")), - WithMetabase(mb), - WithBlobstor(bs), - WithGCInterval(1 * time.Second), - WithDisableBackgroundFlush(), - }, opts...)...) - } - - errCountOpt := func() (Option, *atomic.Uint32) { - cnt := &atomic.Uint32{} - return WithReportErrorFunc(func(msg string, err error) { - cnt.Add(1) - testlogger.Warn(msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) - }), cnt - } - - failures := []writecachetest.TestFailureInjector[Option]{ - { - Desc: "db, invalid address", - InjectFn: func(t *testing.T, wc writecache.Cache) { - c := wc.(*cache) - obj := testutil.GenerateObject() - data, err := obj.Marshal() - require.NoError(t, err) - require.NoError(t, c.db.Update(func(tx *badger.Txn) error { - return tx.Set([]byte{1, 2, 3}, data) - })) - }, - }, - { - Desc: "db, invalid object", - InjectFn: func(t *testing.T, wc writecache.Cache) { - c := wc.(*cache) - key := addr2key(oidtest.Address()) - require.NoError(t, c.db.Update(func(tx *badger.Txn) error { - return tx.Set(key[:], []byte{1, 2, 3}) - })) - }, - }, - } - - writecachetest.TestFlush(t, createCacheFn, errCountOpt, failures...) -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/gc.go b/pkg/local_object_storage/writecache/writecachebadger/gc.go deleted file mode 100644 index 8937ff2956..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/gc.go +++ /dev/null @@ -1,45 +0,0 @@ -package writecachebadger - -import ( - "context" - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" -) - -func (c *cache) runGCLoop(ctx context.Context) { - c.wg.Add(1) - - go func() { - defer c.wg.Done() - - t := time.NewTicker(c.gcInterval) - defer t.Stop() - - for { - select { - case <-ctx.Done(): - return - case <-t.C: - c.runGC() - } - } - }() -} - -func (c *cache) runGC() { - // This serves to synchronize the c.db field when changing mode as well. - c.modeMtx.RLock() - defer c.modeMtx.RUnlock() - - ro := c.readOnly() - if ro { - return - } - - // 0.5 is the recommended value so that write amplification of the value log is 2. - // See https://pkg.go.dev/github.com/dgraph-io/badger/v4#DB.RunValueLogGC for more info. - for c.db.RunValueLogGC(0.5) == nil { - c.log.Debug(logs.WritecacheDBValueLogGCRunCompleted) - } -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/generic_test.go b/pkg/local_object_storage/writecache/writecachebadger/generic_test.go deleted file mode 100644 index 08845665f2..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/generic_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package writecachebadger - -import ( - "testing" - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/storagetest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" -) - -func TestGeneric(t *testing.T) { - storagetest.TestAll(t, func(t *testing.T) storagetest.Component { - return New( - WithLogger(test.NewLogger(t, true)), - WithFlushWorkersCount(2), - WithPath(t.TempDir()), - WithGCInterval(1*time.Second)) - }) -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/get.go b/pkg/local_object_storage/writecache/writecachebadger/get.go deleted file mode 100644 index 42403e551d..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/get.go +++ /dev/null @@ -1,95 +0,0 @@ -package writecachebadger - -import ( - "context" - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/dgraph-io/badger/v4" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// Get returns object from write-cache. -// -// Returns an error of type apistatus.ObjectNotFound if the requested object is missing in write-cache. -func (c *cache) Get(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) { - _, span := tracing.StartSpanFromContext(ctx, "writecache.Get", - trace.WithAttributes( - attribute.String("address", addr.EncodeToString()), - )) - defer span.End() - - obj, err := c.getInternal(addr) - return obj, metaerr.Wrap(err) -} - -func (c *cache) getInternal(addr oid.Address) (*objectSDK.Object, error) { - found := false - storageType := writecache.StorageTypeUndefined - startedAt := time.Now() - defer func() { - c.metrics.Get(time.Since(startedAt), found, storageType) - }() - - k := addr2key(addr) - value, err := Get(c.db, k[:]) - if err == nil { - obj := objectSDK.New() - found = true - storageType = writecache.StorageTypeDB - return obj, obj.Unmarshal(value) - } - - return nil, logicerr.Wrap(new(apistatus.ObjectNotFound)) -} - -// Head returns object header from write-cache. -// -// Returns an error of type apistatus.ObjectNotFound if the requested object is missing in write-cache. -func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) { - _, span := tracing.StartSpanFromContext(ctx, "writecache.Head", - trace.WithAttributes( - attribute.String("address", addr.EncodeToString()), - )) - defer span.End() - - obj, err := c.getInternal(addr) - if err != nil { - return nil, metaerr.Wrap(err) - } - - return obj.CutPayload(), nil -} - -// Get fetches object from the underlying database. -// Key should be a stringified address. -// -// Returns an error of type apistatus.ObjectNotFound if the requested object is missing in db. -func Get(db *badger.DB, key []byte) ([]byte, error) { - var value []byte - - err := db.View(func(tx *badger.Txn) error { - it, err := tx.Get(key) - if err != nil { - if err == badger.ErrKeyNotFound { - return logicerr.Wrap(new(apistatus.ObjectNotFound)) - } - return err - } - v, err := it.ValueCopy(nil) - if err != nil { - return err - } - value = v - return nil - }) - - return value, metaerr.Wrap(err) -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/iterate.go b/pkg/local_object_storage/writecache/writecachebadger/iterate.go deleted file mode 100644 index 1112420487..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/iterate.go +++ /dev/null @@ -1,32 +0,0 @@ -package writecachebadger - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/dgraph-io/badger/v4" -) - -// IterateDB iterates over all objects stored in badger.DB instance and passes them to f until error return. -// It is assumed that db is an underlying database of some WriteCache instance. -// -// DB must not be nil and should be opened. -func IterateDB(db *badger.DB, f func(oid.Address) error) error { - return metaerr.Wrap(db.View(func(tx *badger.Txn) error { - opts := badger.DefaultIteratorOptions - opts.PrefetchValues = false - it := tx.NewIterator(opts) - for it.Rewind(); it.Valid(); it.Next() { - var key internalKey - if got, want := len(it.Item().Key()), len(key); got != want { - return fmt.Errorf("invalid db key len: got %d, want %d", got, want) - } - copy(key[:], it.Item().Key()) - if err := f(key.address()); err != nil { - return err - } - } - return nil - })) -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/mode.go b/pkg/local_object_storage/writecache/writecachebadger/mode.go deleted file mode 100644 index 03d8618312..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/mode.go +++ /dev/null @@ -1,78 +0,0 @@ -package writecachebadger - -import ( - "context" - "fmt" - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// SetMode sets write-cache mode of operation. -// When shard is put in read-only mode all objects in memory are flushed to disk -// and all background jobs are suspended. -func (c *cache) SetMode(m mode.Mode) error { - ctx, span := tracing.StartSpanFromContext(context.TODO(), "writecache.SetMode", - trace.WithAttributes( - attribute.String("mode", m.String()), - )) - defer span.End() - - c.modeMtx.Lock() - defer c.modeMtx.Unlock() - - err := c.setMode(ctx, m) - if err == nil { - c.metrics.SetMode(m) - } - return err -} - -// setMode applies new mode. Must be called with cache.modeMtx lock taken. -func (c *cache) setMode(ctx context.Context, m mode.Mode) error { - var err error - turnOffMeta := m.NoMetabase() - - if turnOffMeta && !c.mode.NoMetabase() { - err = c.flush(ctx, true) - if err != nil { - return err - } - } - - if c.db != nil { - if err = c.db.Close(); err != nil { - return fmt.Errorf("can't close write-cache database: %w", err) - } - } - - // Suspend producers to ensure there are channel send operations in fly. - // flushCh is populated by `flush` with `modeMtx` taken, thus waiting until it is empty - // guarantees that there are no in-fly operations. - for len(c.flushCh) != 0 { - c.log.Info(logs.WritecacheWaitingForChannelsToFlush) - time.Sleep(time.Second) - } - - if turnOffMeta { - c.mode = m - return nil - } - - if err = c.openStore(m.ReadOnly()); err != nil { - return err - } - - c.mode = m - return nil -} - -// readOnly returns true if current mode is read-only. -// `c.modeMtx` must be taken. -func (c *cache) readOnly() bool { - return c.mode.ReadOnly() -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/options.go b/pkg/local_object_storage/writecache/writecachebadger/options.go deleted file mode 100644 index d041a9b886..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/options.go +++ /dev/null @@ -1,119 +0,0 @@ -package writecachebadger - -import ( - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" -) - -// Option represents write-cache configuration option. -type Option func(*options) - -type options struct { - log *logger.Logger - // path is a path to a directory for write-cache. - path string - // blobstor is the main persistent storage. - blobstor writecache.MainStorage - // metabase is the metabase instance. - metabase writecache.Metabase - // maxObjectSize is the maximum size of the object stored in the write-cache. - maxObjectSize uint64 - // workersCount is the number of workers flushing objects in parallel. - workersCount int - // maxCacheSize is the maximum total size of all objects saved in cache (DB + FS). - // 1 GiB by default. - maxCacheSize uint64 - // objCounters contains atomic counters for the number of objects stored in cache. - objCounters counters - // reportError is the function called when encountering disk errors in background workers. - reportError func(string, error) - // metrics is metrics implementation - metrics writecache.Metrics - // gcInterval is the interval duration to run the GC cycle. - gcInterval time.Duration - // disableBackgroundFlush is for testing purposes only. - disableBackgroundFlush bool -} - -// WithLogger sets logger. -func WithLogger(log *logger.Logger) Option { - return func(o *options) { - o.log = &logger.Logger{Logger: log.With(zap.String("component", "WriteCache"))} - } -} - -// WithPath sets path to writecache db. -func WithPath(path string) Option { - return func(o *options) { - o.path = path - } -} - -// WithBlobstor sets main object storage. -func WithBlobstor(bs writecache.MainStorage) Option { - return func(o *options) { - o.blobstor = bs - } -} - -// WithMetabase sets metabase. -func WithMetabase(db writecache.Metabase) Option { - return func(o *options) { - o.metabase = db - } -} - -// WithMaxObjectSize sets maximum object size to be stored in write-cache. -func WithMaxObjectSize(sz uint64) Option { - return func(o *options) { - if sz > 0 { - o.maxObjectSize = sz - } - } -} - -func WithFlushWorkersCount(c int) Option { - return func(o *options) { - if c > 0 { - o.workersCount = c - } - } -} - -// WithMaxCacheSize sets maximum write-cache size in bytes. -func WithMaxCacheSize(sz uint64) Option { - return func(o *options) { - o.maxCacheSize = sz - } -} - -// WithReportErrorFunc sets error reporting function. -func WithReportErrorFunc(f func(string, error)) Option { - return func(o *options) { - o.reportError = f - } -} - -// WithMetrics sets metrics implementation. -func WithMetrics(metrics writecache.Metrics) Option { - return func(o *options) { - o.metrics = metrics - } -} - -// WithGCInterval sets the duration of the interval to run GC cycles. -func WithGCInterval(d time.Duration) Option { - return func(o *options) { - o.gcInterval = d - } -} - -// WithDisableBackgroundFlush disables background flush, for testing purposes only. -func WithDisableBackgroundFlush() Option { - return func(o *options) { - o.disableBackgroundFlush = true - } -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/put.go b/pkg/local_object_storage/writecache/writecachebadger/put.go deleted file mode 100644 index 2071ba1d0f..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/put.go +++ /dev/null @@ -1,82 +0,0 @@ -package writecachebadger - -import ( - "context" - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// Put puts object to write-cache. -// -// Returns ErrReadOnly if write-cache is in R/O mode. -// Returns ErrNotInitialized if write-cache has not been initialized yet. -// Returns ErrOutOfSpace if saving an object leads to WC's size overflow. -// Returns ErrBigObject if an objects exceeds maximum object size. -func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, error) { - _, span := tracing.StartSpanFromContext(ctx, "writecache.Put", - trace.WithAttributes( - attribute.String("address", prm.Address.EncodeToString()), - attribute.Bool("dont_compress", prm.DontCompress), - )) - defer span.End() - - startedAt := time.Now() - added := false - storageType := writecache.StorageTypeUndefined - defer func() { - c.metrics.Put(time.Since(startedAt), added, storageType) - }() - - c.modeMtx.RLock() - defer c.modeMtx.RUnlock() - if c.readOnly() { - return common.PutRes{}, writecache.ErrReadOnly - } - - sz := uint64(len(prm.RawData)) - if sz > c.maxObjectSize { - return common.PutRes{}, writecache.ErrBigObject - } - - oi := objectInfo{ - addr: prm.Address, - obj: prm.Object, - data: prm.RawData, - } - - storageType = writecache.StorageTypeDB - err := c.put(oi) - if err == nil { - added = true - } - return common.PutRes{}, err -} - -// put persists objects to the write-cache database and -// pushes the to the flush workers queue. -func (c *cache) put(obj objectInfo) error { - cacheSize := c.estimateCacheSize() - if c.maxCacheSize < c.incSizeDB(cacheSize) { - return writecache.ErrOutOfSpace - } - - wb := c.db.NewWriteBatch() - k := addr2key(obj.addr) - _ = wb.Set(k[:], obj.data) - err := wb.Flush() - if err == nil { - storagelog.Write(c.log, - storagelog.AddressField(obj.addr), - storagelog.StorageTypeField(wcStorageType), - storagelog.OpField("db PUT"), - ) - c.incDB() - } - return err -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/state.go b/pkg/local_object_storage/writecache/writecachebadger/state.go deleted file mode 100644 index e098eb0603..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/state.go +++ /dev/null @@ -1,67 +0,0 @@ -package writecachebadger - -import ( - "fmt" - "math" - "sync/atomic" - - "github.com/dgraph-io/badger/v4" -) - -func (c *cache) estimateCacheSize() uint64 { - onDiskSize, _ := c.db.EstimateSize(nil) - c.metrics.SetEstimateSize(onDiskSize, 0) - return onDiskSize -} - -func (c *cache) incSizeDB(sz uint64) uint64 { - return sz + c.maxObjectSize -} - -type counters struct { - cDB atomic.Uint64 -} - -func (x *counters) IncDB() { - x.cDB.Add(1) -} - -func (x *counters) DecDB() { - x.cDB.Add(math.MaxUint64) -} - -func (x *counters) DB() uint64 { - return x.cDB.Load() -} - -func (c *cache) initCounters() error { - var inDB uint64 - err := c.db.View(func(tx *badger.Txn) error { - opts := badger.DefaultIteratorOptions - opts.PrefetchValues = false - it := tx.NewIterator(opts) - defer it.Close() - for it.Rewind(); it.Valid(); it.Next() { - inDB++ - } - return nil - }) - if err != nil { - return fmt.Errorf("could not read write-cache DB counter: %w", err) - } - - c.objCounters.cDB.Store(inDB) - c.metrics.SetActualCounters(inDB, 0) - - return nil -} - -func (c *cache) incDB() { - c.objCounters.IncDB() - c.metrics.SetActualCounters(c.objCounters.DB(), 0) -} - -func (c *cache) decDB() { - c.objCounters.DecDB() - c.metrics.SetActualCounters(c.objCounters.DB(), 0) -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/storage.go b/pkg/local_object_storage/writecache/writecachebadger/storage.go deleted file mode 100644 index 04337b7a6f..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/storage.go +++ /dev/null @@ -1,91 +0,0 @@ -package writecachebadger - -import ( - "fmt" - "os" - "path/filepath" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/dgraph-io/badger/v4" - "go.uber.org/zap" -) - -// store represents persistent storage with in-memory LRU cache -// for flushed items on top of it. -type store struct { - db *badger.DB -} - -type internalKey [len(cid.ID{}) + len(oid.ID{})]byte - -func (k internalKey) address() oid.Address { - var addr oid.Address - var cnr cid.ID - var obj oid.ID - copy(cnr[:], k[:len(cnr)]) - copy(obj[:], k[len(cnr):]) - addr.SetContainer(cnr) - addr.SetObject(obj) - return addr -} - -func addr2key(addr oid.Address) internalKey { - var key internalKey - cnr, obj := addr.Container(), addr.Object() - copy(key[:len(cnr)], cnr[:]) - copy(key[len(cnr):], obj[:]) - return key -} - -const dbName = "small.badger" - -func (c *cache) openStore(readOnly bool) error { - err := util.MkdirAllX(c.path, os.ModePerm) - if err != nil { - return err - } - - c.db, err = OpenDB(filepath.Join(c.path, dbName), readOnly, c.log) - if err != nil { - return fmt.Errorf("could not open database: %w", err) - } - - return nil -} - -func (c *cache) deleteFromDB(keys []internalKey) []internalKey { - if len(keys) == 0 { - return keys - } - - wb := c.db.NewWriteBatch() - - var errorIndex int - for errorIndex = range keys { - if err := wb.Delete(keys[errorIndex][:]); err != nil { - break - } - } - - for i := 0; i < errorIndex; i++ { - c.decDB() - c.metrics.Evict(writecache.StorageTypeDB) - storagelog.Write(c.log, - storagelog.AddressField(keys[i]), - storagelog.StorageTypeField(wcStorageType), - storagelog.OpField("db DELETE"), - ) - } - - if err := wb.Flush(); err != nil { - c.log.Error(logs.WritecacheCantRemoveObjectsFromTheDatabase, zap.Error(err)) - } - - copy(keys, keys[errorIndex:]) - return keys[:len(keys)-errorIndex] -} diff --git a/pkg/local_object_storage/writecache/writecachebadger/util.go b/pkg/local_object_storage/writecache/writecachebadger/util.go deleted file mode 100644 index e6079e370c..0000000000 --- a/pkg/local_object_storage/writecache/writecachebadger/util.go +++ /dev/null @@ -1,39 +0,0 @@ -package writecachebadger - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "github.com/dgraph-io/badger/v4" - badgeroptions "github.com/dgraph-io/badger/v4/options" -) - -// OpenDB opens a badger instance for write-cache. Opens in read-only mode if ro is true. -func OpenDB(p string, ro bool, l *logger.Logger) (*badger.DB, error) { - return badger.Open(badger.DefaultOptions(p). - WithReadOnly(ro). - WithSyncWrites(true). - WithCompression(badgeroptions.None). - WithLoggingLevel(badger.ERROR). - WithLogger(badgerLoggerWrapper{l})) -} - -type badgerLoggerWrapper struct { - l *logger.Logger -} - -func (w badgerLoggerWrapper) Errorf(msg string, args ...any) { - w.l.Error(fmt.Sprintf(msg, args...)) -} - -func (w badgerLoggerWrapper) Warningf(msg string, args ...any) { - w.l.Warn(fmt.Sprintf(msg, args...)) -} - -func (w badgerLoggerWrapper) Infof(msg string, args ...any) { - w.l.Info(fmt.Sprintf(msg, args...)) -} - -func (w badgerLoggerWrapper) Debugf(msg string, args ...any) { - w.l.Debug(fmt.Sprintf(msg, args...)) -} diff --git a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go b/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go deleted file mode 100644 index 89add8115d..0000000000 --- a/pkg/local_object_storage/writecache/writecachebbolt/flush_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package writecachebbolt - -import ( - "context" - "os" - "path/filepath" - "sync/atomic" - "testing" - - objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache/writecachetest" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - "github.com/stretchr/testify/require" - "go.etcd.io/bbolt" - "go.uber.org/zap" -) - -func TestFlush(t *testing.T) { - testlogger := test.NewLogger(t, true) - - createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs writecache.MainStorage, opts ...Option) writecache.Cache { - return New( - append([]Option{ - WithLogger(testlogger), - WithPath(filepath.Join(t.TempDir(), "writecache")), - WithSmallObjectSize(smallSize), - WithMetabase(mb), - WithBlobstor(bs), - WithDisableBackgroundFlush(), - }, opts...)...) - } - - errCountOpt := func() (Option, *atomic.Uint32) { - cnt := &atomic.Uint32{} - return WithReportErrorFunc(func(msg string, err error) { - cnt.Add(1) - testlogger.Warn(msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) - }), cnt - } - - failures := []writecachetest.TestFailureInjector[Option]{ - { - Desc: "db, invalid address", - InjectFn: func(t *testing.T, wc writecache.Cache) { - c := wc.(*cache) - obj := testutil.GenerateObject() - data, err := obj.Marshal() - require.NoError(t, err) - require.NoError(t, c.db.Batch(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - return b.Put([]byte{1, 2, 3}, data) - })) - }, - }, - { - Desc: "db, invalid object", - InjectFn: func(t *testing.T, wc writecache.Cache) { - c := wc.(*cache) - require.NoError(t, c.db.Batch(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - k := []byte(oidtest.Address().EncodeToString()) - v := []byte{1, 2, 3} - return b.Put(k, v) - })) - }, - }, - { - Desc: "fs, read error", - InjectFn: func(t *testing.T, wc writecache.Cache) { - c := wc.(*cache) - obj := testutil.GenerateObject() - data, err := obj.Marshal() - require.NoError(t, err) - - var prm common.PutPrm - prm.Address = objectCore.AddressOf(obj) - prm.RawData = data - - _, err = c.fsTree.Put(context.Background(), prm) - require.NoError(t, err) - - p := prm.Address.Object().EncodeToString() + "." + prm.Address.Container().EncodeToString() - p = filepath.Join(c.fsTree.RootPath, p[:1], p[1:]) - - _, err = os.Stat(p) // sanity check - require.NoError(t, err) - require.NoError(t, os.Truncate(p, 0)) // corrupt the file contents, so that it can't be unmarshalled - }, - }, - { - Desc: "fs, invalid object", - InjectFn: func(t *testing.T, wc writecache.Cache) { - c := wc.(*cache) - var prm common.PutPrm - prm.Address = oidtest.Address() - prm.RawData = []byte{1, 2, 3} - _, err := c.fsTree.Put(context.Background(), prm) - require.NoError(t, err) - }, - }, - } - - writecachetest.TestFlush(t, createCacheFn, errCountOpt, failures...) -} From 764f70634d24868eddf247cd4fec10341d16967f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 19 Dec 2023 18:03:57 +0300 Subject: [PATCH 0235/1413] [#881] containerSvc: Add APE validation Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/container.go | 5 +- pkg/services/container/ape.go | 514 +++++++++++++++++++++++++++++ pkg/services/container/ape_test.go | 491 +++++++++++++++++++++++++++ 3 files changed, 1009 insertions(+), 1 deletion(-) create mode 100644 pkg/services/container/ape.go create mode 100644 pkg/services/container/ape_test.go diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 4fc7f56490..2b9bdd71b7 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -35,7 +35,10 @@ func initContainerService(_ context.Context, c *cfg) { server := containerTransportGRPC.New( containerService.NewSignService( &c.key.PrivateKey, - containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), + containerService.NewAPEServer(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine, cnrRdr, + newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, + containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), + ), ), ) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go new file mode 100644 index 0000000000..e1ef43c631 --- /dev/null +++ b/pkg/services/container/ape.go @@ -0,0 +1,514 @@ +package container + +import ( + "bytes" + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/sha256" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +var ( + errMissingContainerID = errors.New("missing container ID") + errSessionContainerMissmatch = errors.New("requested container is not related to the session") + errMissingVerificationHeader = errors.New("malformed request: empty verification header") + errInvalidSessionTokenSignature = errors.New("malformed request: invalid session token signature") + errInvalidSessionTokenOwner = errors.New("malformed request: invalid session token owner") + errEmptyBodySignature = errors.New("malformed request: empty body signature") + errMissingOwnerID = errors.New("malformed request: missing owner ID") +) + +type ir interface { + InnerRingKeys() ([][]byte, error) +} + +type containers interface { + Get(cid.ID) (*containercore.Container, error) +} + +type apeChecker struct { + router policyengine.ChainRouter + reader containers + ir ir + nm netmap.Source + + next Server +} + +func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm netmap.Source, srv Server) Server { + return &apeChecker{ + router: router, + reader: reader, + ir: ir, + next: srv, + nm: nm, + } +} + +func (ac *apeChecker) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.AnnounceUsedSpace") + defer span.End() + + // this method is not used, so not checked + + return ac.next.AnnounceUsedSpace(ctx, req) +} + +func (ac *apeChecker) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Delete") + defer span.End() + + if err := ac.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), + nativeschema.MethodDeleteContainer); err != nil { + return nil, err + } + + return ac.next.Delete(ctx, req) +} + +func (ac *apeChecker) Get(ctx context.Context, req *container.GetRequest) (*container.GetResponse, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Get") + defer span.End() + + if err := ac.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), + nativeschema.MethodGetContainer); err != nil { + return nil, err + } + + return ac.next.Get(ctx, req) +} + +func (ac *apeChecker) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.GetExtendedACL") + defer span.End() + + if err := ac.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), + nativeschema.MethodGetContainerEACL); err != nil { + return nil, err + } + + return ac.next.GetExtendedACL(ctx, req) +} + +func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.List") + defer span.End() + + role, pk, err := ac.getRoleWithoutContainerID(req.GetBody().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) + if err != nil { + return nil, err + } + + reqProps := map[string]string{ + nativeschema.PropertyKeyActorPublicKey: pk.String(), + nativeschema.PropertyKeyActorRole: role, + } + + request := &apeRequest{ + resource: &apeResource{ + name: nativeschema.ResourceFormatRootContainers, + props: make(map[string]string), + }, + op: nativeschema.MethodListContainers, + props: reqProps, + } + + s, found, err := ac.router.IsAllowed(apechain.Ingress, + policyengine.NewRequestTargetWithNamespace(""), + request) + if err != nil { + return nil, err + } + + if !found || s == apechain.Allow { + return ac.next.List(ctx, req) + } + + return nil, apeErr(nativeschema.MethodListContainers, s) +} + +func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Put") + defer span.End() + + role, pk, err := ac.getRoleWithoutContainerID(req.GetBody().GetContainer().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) + if err != nil { + return nil, err + } + + reqProps := map[string]string{ + nativeschema.PropertyKeyActorPublicKey: pk.String(), + nativeschema.PropertyKeyActorRole: role, + } + + request := &apeRequest{ + resource: &apeResource{ + name: nativeschema.ResourceFormatRootContainers, + props: make(map[string]string), + }, + op: nativeschema.MethodPutContainer, + props: reqProps, + } + + s, found, err := ac.router.IsAllowed(apechain.Ingress, + policyengine.NewRequestTargetWithNamespace(""), + request) + if err != nil { + return nil, err + } + + if !found || s == apechain.Allow { + return ac.next.Put(ctx, req) + } + + return nil, apeErr(nativeschema.MethodPutContainer, s) +} + +func (ac *apeChecker) getRoleWithoutContainerID(oID *refs.OwnerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader) (string, *keys.PublicKey, error) { + if vh == nil { + return "", nil, errMissingVerificationHeader + } + + if oID == nil { + return "", nil, errMissingOwnerID + } + var ownerID user.ID + if err := ownerID.ReadFromV2(*oID); err != nil { + return "", nil, err + } + + actor, pk, err := ac.getActorAndPublicKey(mh, vh, cid.ID{}) + if err != nil { + return "", nil, err + } + + if actor.Equals(ownerID) { + return nativeschema.PropertyValueContainerRoleOwner, pk, nil + } + + pkBytes := pk.Bytes() + isIR, err := ac.isInnerRingKey(pkBytes) + if err != nil { + return "", nil, err + } + if isIR { + return nativeschema.PropertyValueContainerRoleIR, pk, nil + } + + return nativeschema.PropertyValueContainerRoleOthers, pk, nil +} + +func (ac *apeChecker) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.SetExtendedACL") + defer span.End() + + if err := ac.validateContainerBoundedOperation(req.GetBody().GetEACL().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), + nativeschema.MethodSetContainerEACL); err != nil { + return nil, err + } + + return ac.next.SetExtendedACL(ctx, req) +} + +func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.ContainerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, op string) error { + if vh == nil { + return errMissingVerificationHeader + } + + id, err := getContainerID(containerID) + if err != nil { + return err + } + + cont, err := ac.reader.Get(id) + if err != nil { + return err + } + + reqProps, err := ac.getRequestProps(mh, vh, cont, id) + if err != nil { + return err + } + + request := &apeRequest{ + resource: &apeResource{ + name: fmt.Sprintf(nativeschema.ResourceFormatRootContainer, id.EncodeToString()), + props: ac.getContainerProps(cont), + }, + op: op, + props: reqProps, + } + + s, found, err := ac.router.IsAllowed(apechain.Ingress, + policyengine.NewRequestTargetWithContainer(id.EncodeToString()), + request) + if err != nil { + return err + } + + if !found || s == apechain.Allow { + return nil + } + + return apeErr(op, s) +} + +func apeErr(operation string, status apechain.Status) error { + errAccessDenied := &apistatus.ObjectAccessDenied{} + errAccessDenied.WriteReason(fmt.Sprintf("access to container operation %s is denied by access policy engine: %s", operation, status.String())) + return errAccessDenied +} + +func getContainerID(reqContID *refs.ContainerID) (cid.ID, error) { + if reqContID == nil { + return cid.ID{}, errMissingContainerID + } + var id cid.ID + err := id.ReadFromV2(*reqContID) + if err != nil { + return cid.ID{}, fmt.Errorf("invalid container ID: %w", err) + } + return id, nil +} + +type apeRequest struct { + resource *apeResource + op string + props map[string]string +} + +// Operation implements resource.Request. +func (r *apeRequest) Operation() string { + return r.op +} + +// Property implements resource.Request. +func (r *apeRequest) Property(key string) string { + return r.props[key] +} + +// Resource implements resource.Request. +func (r *apeRequest) Resource() resource.Resource { + return r.resource +} + +type apeResource struct { + name string + props map[string]string +} + +func (r *apeResource) Name() string { + return r.name +} + +func (r *apeResource) Property(key string) string { + return r.props[key] +} + +func (ac *apeChecker) getContainerProps(c *containercore.Container) map[string]string { + return map[string]string{ + nativeschema.PropertyKeyContainerOwnerID: c.Value.Owner().EncodeToString(), + } +} + +func (ac *apeChecker) getRequestProps(mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, + cont *containercore.Container, cnrID cid.ID, +) (map[string]string, error) { + actor, pk, err := ac.getActorAndPublicKey(mh, vh, cnrID) + if err != nil { + return nil, err + } + role, err := ac.getRole(actor, pk, cont, cnrID) + if err != nil { + return nil, err + } + return map[string]string{ + nativeschema.PropertyKeyActorPublicKey: pk.String(), + nativeschema.PropertyKeyActorRole: role, + }, nil +} + +func (ac *apeChecker) getRole(actor *user.ID, pk *keys.PublicKey, cont *containercore.Container, cnrID cid.ID) (string, error) { + if cont.Value.Owner().Equals(*actor) { + return nativeschema.PropertyValueContainerRoleOwner, nil + } + + pkBytes := pk.Bytes() + isIR, err := ac.isInnerRingKey(pkBytes) + if err != nil { + return "", err + } + if isIR { + return nativeschema.PropertyValueContainerRoleIR, nil + } + + isContainer, err := ac.isContainerKey(pkBytes, cnrID, cont) + if err != nil { + return "", err + } + if isContainer { + return nativeschema.PropertyValueContainerRoleContainer, nil + } + + return nativeschema.PropertyValueContainerRoleOthers, nil +} + +func (ac *apeChecker) getActorAndPublicKey(mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, cnrID cid.ID) (*user.ID, *keys.PublicKey, error) { + st, err := ac.getSessionToken(mh) + if err != nil { + return nil, nil, err + } + + if st != nil { + return ac.getActorAndPKFromSessionToken(st, cnrID) + } + return ac.getActorAndPKFromSignature(vh) +} + +func (ac *apeChecker) getActorAndPKFromSignature(vh *session.RequestVerificationHeader) (*user.ID, *keys.PublicKey, error) { + for vh.GetOrigin() != nil { + vh = vh.GetOrigin() + } + sig := vh.GetBodySignature() + if sig == nil { + return nil, nil, errEmptyBodySignature + } + key, err := keys.NewPublicKeyFromBytes(sig.GetKey(), elliptic.P256()) + if err != nil { + return nil, nil, fmt.Errorf("invalid signature key: %w", err) + } + + var userID user.ID + user.IDFromKey(&userID, (ecdsa.PublicKey)(*key)) + + return &userID, key, nil +} + +func (ac *apeChecker) getSessionToken(mh *session.RequestMetaHeader) (*sessionSDK.Object, error) { + for mh.GetOrigin() != nil { + mh = mh.GetOrigin() + } + st := mh.GetSessionToken() + if st == nil { + return nil, nil + } + + var tok sessionSDK.Object + err := tok.ReadFromV2(*st) + if err != nil { + return nil, fmt.Errorf("invalid session token: %w", err) + } + + return &tok, nil +} + +func (ac *apeChecker) getActorAndPKFromSessionToken(st *sessionSDK.Object, cnrID cid.ID) (*user.ID, *keys.PublicKey, error) { + if !st.AssertContainer(cnrID) { + return nil, nil, errSessionContainerMissmatch + } + if !st.VerifySignature() { + return nil, nil, errInvalidSessionTokenSignature + } + var tok session.Token + st.WriteToV2(&tok) + + signaturePublicKey, err := keys.NewPublicKeyFromBytes(tok.GetSignature().GetKey(), elliptic.P256()) + if err != nil { + return nil, nil, fmt.Errorf("invalid key in session token signature: %w", err) + } + + tokenIssuer := st.Issuer() + if !isOwnerFromKey(tokenIssuer, signaturePublicKey) { + return nil, nil, errInvalidSessionTokenOwner + } + + return &tokenIssuer, signaturePublicKey, nil +} + +func isOwnerFromKey(id user.ID, key *keys.PublicKey) bool { + if key == nil { + return false + } + + var id2 user.ID + user.IDFromKey(&id2, (ecdsa.PublicKey)(*key)) + + return id2.Equals(id) +} + +func (ac *apeChecker) isInnerRingKey(pk []byte) (bool, error) { + innerRingKeys, err := ac.ir.InnerRingKeys() + if err != nil { + return false, err + } + + for i := range innerRingKeys { + if bytes.Equal(innerRingKeys[i], pk) { + return true, nil + } + } + + return false, nil +} + +func (ac *apeChecker) isContainerKey(pk []byte, cnrID cid.ID, cont *containercore.Container) (bool, error) { + binCnrID := make([]byte, sha256.Size) + cnrID.Encode(binCnrID) + + nm, err := netmap.GetLatestNetworkMap(ac.nm) + if err != nil { + return false, err + } + + in, err := isContainerNode(nm, pk, binCnrID, cont) + if err != nil { + return false, err + } else if in { + return true, nil + } + + // then check previous netmap, this can happen in-between epoch change + // when node migrates data from last epoch container + nm, err = netmap.GetPreviousNetworkMap(ac.nm) + if err != nil { + return false, err + } + + return isContainerNode(nm, pk, binCnrID, cont) +} + +func isContainerNode(nm *netmapSDK.NetMap, pk, binCnrID []byte, cont *containercore.Container) (bool, error) { + cnrVectors, err := nm.ContainerNodes(cont.Value.PlacementPolicy(), binCnrID) + if err != nil { + return false, err + } + + for i := range cnrVectors { + for j := range cnrVectors[i] { + if bytes.Equal(cnrVectors[i][j].PublicKey(), pk) { + return true, nil + } + } + } + + return false, nil +} diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go new file mode 100644 index 0000000000..b61e68eb57 --- /dev/null +++ b/pkg/services/container/ape_test.go @@ -0,0 +1,491 @@ +package container + +import ( + "context" + "errors" + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestAPE(t *testing.T) { + t.Parallel() + t.Run("deny get container for others", testDenyGetContainerForOthers) + t.Run("deny set container eACL for IR", testDenySetContainerEACLForIR) + t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken) + t.Run("deny put container for others with session token", testDenyPutContainerForOthersSessionToken) + t.Run("deny list containers for owner with PK", testDenyListContainersForPK) +} + +func testDenyGetContainerForOthers(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + resp, err := apeSrv.Get(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) +} + +func testDenySetContainerEACLForIR(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodSetContainerEACL, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleIR, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := &container.SetExtendedACLRequest{} + req.SetBody(&container.SetExtendedACLRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetEACL(&acl.Table{}) + req.GetBody().GetEACL().SetContainerID(&refContID) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + ir.keys = append(ir.keys, pk.PublicKey().Bytes()) + + resp, err := apeSrv.SetExtendedACL(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) +} + +func testDenyGetContainerEACLForIRSessionToken(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainerEACL, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleIR, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := &container.GetExtendedACLRequest{} + req.SetBody(&container.GetExtendedACLRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + sessionPK, err := keys.NewPrivateKey() + require.NoError(t, err) + sToken := sessiontest.ObjectSigned() + sToken.BindContainer(contID) + require.NoError(t, sToken.Sign(sessionPK.PrivateKey)) + var sTokenV2 session.Token + sToken.WriteToV2(&sTokenV2) + metaHeader := new(session.RequestMetaHeader) + metaHeader.SetSessionToken(&sTokenV2) + req.SetMetaHeader(metaHeader) + + ir.keys = append(ir.keys, sessionPK.PublicKey().Bytes()) + + resp, err := apeSrv.GetExtendedACL(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) +} + +func testDenyPutContainerForOthersSessionToken(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + + testContainer := containertest.Container() + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + + _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodPutContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + nativeschema.ResourceFormatRootContainers, + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := &container.PutRequest{} + req.SetBody(&container.PutRequestBody{}) + var reqCont container.Container + testContainer.WriteToV2(&reqCont) + req.GetBody().SetContainer(&reqCont) + + sessionPK, err := keys.NewPrivateKey() + require.NoError(t, err) + sToken := sessiontest.ObjectSigned() + sToken.BindContainer(cid.ID{}) + require.NoError(t, sToken.Sign(sessionPK.PrivateKey)) + var sTokenV2 session.Token + sToken.WriteToV2(&sTokenV2) + metaHeader := new(session.RequestMetaHeader) + metaHeader.SetSessionToken(&sTokenV2) + req.SetMetaHeader(metaHeader) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + resp, err := apeSrv.Put(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) +} + +func testDenyListContainersForPK(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodListContainers, + }, + }, + Resources: chain.Resources{ + Names: []string{ + nativeschema.ResourceFormatRootContainers, + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorPublicKey, + Value: pk.PublicKey().String(), + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + var userID user.ID + user.IDFromKey(&userID, pk.PrivateKey.PublicKey) + + req := &container.ListRequest{} + req.SetBody(&container.ListRequestBody{}) + var ownerID refs.OwnerID + userID.WriteToV2(&ownerID) + req.GetBody().SetOwnerID(&ownerID) + + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + resp, err := apeSrv.List(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) +} + +type srvStub struct { + calls map[string]int +} + +func (s *srvStub) AnnounceUsedSpace(context.Context, *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { + s.calls["AnnounceUsedSpace"]++ + return &container.AnnounceUsedSpaceResponse{}, nil +} + +func (s *srvStub) Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error) { + s.calls["Delete"]++ + return &container.DeleteResponse{}, nil +} + +func (s *srvStub) Get(context.Context, *container.GetRequest) (*container.GetResponse, error) { + s.calls["Get"]++ + return &container.GetResponse{}, nil +} + +func (s *srvStub) GetExtendedACL(context.Context, *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { + s.calls["GetExtendedACL"]++ + return &container.GetExtendedACLResponse{}, nil +} + +func (s *srvStub) List(context.Context, *container.ListRequest) (*container.ListResponse, error) { + s.calls["List"]++ + return &container.ListResponse{}, nil +} + +func (s *srvStub) Put(context.Context, *container.PutRequest) (*container.PutResponse, error) { + s.calls["Put"]++ + return &container.PutResponse{}, nil +} + +func (s *srvStub) SetExtendedACL(context.Context, *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { + s.calls["SetExtendedACL"]++ + return &container.SetExtendedACLResponse{}, nil +} + +type irStub struct { + keys [][]byte +} + +func (s *irStub) InnerRingKeys() ([][]byte, error) { + return s.keys, nil +} + +type containerStub struct { + c map[cid.ID]*containercore.Container +} + +func (s *containerStub) Get(id cid.ID) (*containercore.Container, error) { + if v, ok := s.c[id]; ok { + return v, nil + } + return nil, errors.New("container not found") +} + +type netmapStub struct { + netmaps map[uint64]*netmap.NetMap + currentEpoch uint64 +} + +func (s *netmapStub) GetNetMap(diff uint64) (*netmap.NetMap, error) { + if diff >= s.currentEpoch { + return nil, errors.New("invalid diff") + } + return s.GetNetMapByEpoch(s.currentEpoch - diff) +} + +func (s *netmapStub) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { + if nm, found := s.netmaps[epoch]; found { + return nm, nil + } + return nil, errors.New("netmap not found") +} + +func (s *netmapStub) Epoch() (uint64, error) { + return s.currentEpoch, nil +} From b118734909bd22402eb2192426d6470ff5520931 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 28 Dec 2023 13:04:29 +0300 Subject: [PATCH 0236/1413] [#890] getsvc: Log node PK Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/remote.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index 4434f036a5..cd94434cf8 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -2,6 +2,7 @@ package getsvc import ( "context" + "encoding/hex" "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -16,7 +17,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { ctx, span := tracing.StartSpanFromContext(ctx, "getService.processNode") defer span.End() - r.log.Debug(logs.ProcessingNode) + r.log.Debug(logs.ProcessingNode, zap.String("node_key", hex.EncodeToString(info.PublicKey()))) rs, ok := r.getRemoteStorage(info) if !ok { From 0cb0fc17355f7c26e9229f157673330664cea59b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Dec 2023 08:20:15 +0300 Subject: [PATCH 0237/1413] [#569] writecache: Allow to seal writecache after flush Signed-off-by: Dmitrii Stepanov --- .../modules/control/flush_cache.go | 8 +- pkg/local_object_storage/engine/writecache.go | 10 +- pkg/local_object_storage/shard/writecache.go | 9 +- pkg/local_object_storage/writecache/flush.go | 91 ++- .../writecache/flush_test.go | 9 +- pkg/local_object_storage/writecache/mode.go | 6 +- .../writecache/storage.go | 24 +- .../writecache/writecache.go | 2 +- pkg/services/control/server/flush_cache.go | 1 + pkg/services/control/service.pb.go | 616 +++++++++--------- pkg/services/control/service.proto | 2 + pkg/services/control/service_frostfs.pb.go | 2 + 12 files changed, 436 insertions(+), 344 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/flush_cache.go b/cmd/frostfs-cli/modules/control/flush_cache.go index 48be393dca..7f632e9fc5 100644 --- a/cmd/frostfs-cli/modules/control/flush_cache.go +++ b/cmd/frostfs-cli/modules/control/flush_cache.go @@ -8,6 +8,8 @@ import ( "github.com/spf13/cobra" ) +const sealFlag = "seal" + var flushCacheCmd = &cobra.Command{ Use: "flush-cache", Short: "Flush objects from the write-cache to the main storage", @@ -18,7 +20,10 @@ var flushCacheCmd = &cobra.Command{ func flushCache(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) - req := &control.FlushCacheRequest{Body: new(control.FlushCacheRequest_Body)} + seal, _ := cmd.Flags().GetBool(sealFlag) + req := &control.FlushCacheRequest{Body: &control.FlushCacheRequest_Body{ + Seal: seal, + }} req.Body.Shard_ID = getShardIDList(cmd) signRequest(cmd, pk, req) @@ -44,6 +49,7 @@ func initControlFlushCacheCmd() { ff := flushCacheCmd.Flags() ff.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") ff.Bool(shardAllFlag, false, "Process all shards") + ff.Bool(sealFlag, false, "Writecache will be left in read-only mode after flush completed") flushCacheCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag) } diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 00a40105e5..d92a86f5d6 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -17,6 +17,7 @@ import ( type FlushWriteCachePrm struct { shardID *shard.ID ignoreErrors bool + seal bool } // SetShardID is an option to set shard ID. @@ -26,11 +27,16 @@ func (p *FlushWriteCachePrm) SetShardID(id *shard.ID) { p.shardID = id } -// SetIgnoreErrors sets errors ignore flag.. +// SetIgnoreErrors sets errors ignore flag. func (p *FlushWriteCachePrm) SetIgnoreErrors(ignore bool) { p.ignoreErrors = ignore } +// SetSeal sets seal flag. +func (p *FlushWriteCachePrm) SetSeal(v bool) { + p.seal = v +} + // FlushWriteCacheRes groups the resulting values of FlushWriteCache operation. type FlushWriteCacheRes struct{} @@ -40,6 +46,7 @@ func (e *StorageEngine) FlushWriteCache(ctx context.Context, p FlushWriteCachePr trace.WithAttributes( attribute.String("shard)id", p.shardID.String()), attribute.Bool("ignore_errors", p.ignoreErrors), + attribute.Bool("seal", p.seal), )) defer span.End() @@ -53,6 +60,7 @@ func (e *StorageEngine) FlushWriteCache(ctx context.Context, p FlushWriteCachePr var prm shard.FlushWriteCachePrm prm.SetIgnoreErrors(p.ignoreErrors) + prm.SetSeal(p.seal) return FlushWriteCacheRes{}, sh.FlushWriteCache(ctx, prm) } diff --git a/pkg/local_object_storage/shard/writecache.go b/pkg/local_object_storage/shard/writecache.go index 7ce279c544..4e57a04974 100644 --- a/pkg/local_object_storage/shard/writecache.go +++ b/pkg/local_object_storage/shard/writecache.go @@ -12,6 +12,7 @@ import ( // FlushWriteCachePrm represents parameters of a `FlushWriteCache` operation. type FlushWriteCachePrm struct { ignoreErrors bool + seal bool } // SetIgnoreErrors sets the flag to ignore read-errors during flush. @@ -19,6 +20,11 @@ func (p *FlushWriteCachePrm) SetIgnoreErrors(ignore bool) { p.ignoreErrors = ignore } +// SetSeal sets the flag to left writecache in read-only mode after flush. +func (p *FlushWriteCachePrm) SetSeal(v bool) { + p.seal = v +} + // errWriteCacheDisabled is returned when an operation on write-cache is performed, // but write-cache is disabled. var errWriteCacheDisabled = errors.New("write-cache is disabled") @@ -29,6 +35,7 @@ func (s *Shard) FlushWriteCache(ctx context.Context, p FlushWriteCachePrm) error trace.WithAttributes( attribute.String("shard_id", s.ID().String()), attribute.Bool("ignore_errors", p.ignoreErrors), + attribute.Bool("seal", p.seal), )) defer span.End() @@ -47,5 +54,5 @@ func (s *Shard) FlushWriteCache(ctx context.Context, p FlushWriteCachePrm) error return ErrDegradedMode } - return s.writeCache.Flush(ctx, p.ignoreErrors) + return s.writeCache.Flush(ctx, p.ignoreErrors, p.seal) } diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index f4ceec8c8b..17dcc1107b 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -12,6 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -33,6 +34,8 @@ const ( defaultFlushInterval = time.Second ) +var errIterationCompleted = errors.New("iteration completed") + // runFlushLoop starts background workers which periodically flush objects to the blobstor. func (c *cache) runFlushLoop(ctx context.Context) { if c.disableBackgroundFlush { @@ -229,7 +232,7 @@ func (c *cache) workerFlushSmall(ctx context.Context) { continue } - c.deleteFromDB(objInfo.addr) + c.deleteFromDB(objInfo.addr, true) } } @@ -270,19 +273,29 @@ func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []b } // Flush flushes all objects from the write-cache to the main storage. -// Write-cache must be in readonly mode to ensure correctness of an operation and -// to prevent interference with background flush workers. -func (c *cache) Flush(ctx context.Context, ignoreErrors bool) error { - ctx, span := tracing.StartSpanFromContext(ctx, "Flush", +func (c *cache) Flush(ctx context.Context, ignoreErrors, seal bool) error { + ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Flush", trace.WithAttributes( attribute.Bool("ignore_errors", ignoreErrors), + attribute.Bool("seal", seal), )) defer span.End() - c.modeMtx.RLock() - defer c.modeMtx.RUnlock() + c.modeMtx.Lock() // exclusive lock to not to conflict with background flush + defer c.modeMtx.Unlock() - return c.flush(ctx, ignoreErrors) + if err := c.flush(ctx, ignoreErrors); err != nil { + return err + } + + if seal { + m := c.mode | mode.ReadOnly + if err := c.setMode(ctx, m, ignoreErrors); err != nil { + return err + } + c.metrics.SetMode(m) + } + return nil } func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { @@ -290,13 +303,53 @@ func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { return err } - return c.db.View(func(tx *bbolt.Tx) error { + var last string + for { + batch, err := c.readNextDBBatch(ignoreErrors, last) + if err != nil { + return err + } + if len(batch) == 0 { + break + } + for _, item := range batch { + var obj objectSDK.Object + if err := obj.Unmarshal(item.data); err != nil { + c.reportFlushError(logs.FSTreeCantDecodeDBObjectAddress, item.address, metaerr.Wrap(err)) + if ignoreErrors { + continue + } + return err + } + + if err := c.flushObject(ctx, &obj, item.data, StorageTypeDB); err != nil { + return err + } + c.deleteFromDB(item.address, false) + } + last = batch[len(batch)-1].address + } + return nil +} + +type batchItem struct { + data []byte + address string +} + +func (c *cache) readNextDBBatch(ignoreErrors bool, last string) ([]batchItem, error) { + const batchSize = 100 + var batch []batchItem + err := c.db.View(func(tx *bbolt.Tx) error { var addr oid.Address b := tx.Bucket(defaultBucket) cs := b.Cursor() - for k, data := cs.Seek(nil); k != nil; k, data = cs.Next() { + for k, data := cs.Seek([]byte(last)); k != nil; k, data = cs.Next() { sa := string(k) + if sa == last { + continue + } if err := addr.DecodeString(sa); err != nil { c.reportFlushError(logs.FSTreeCantDecodeDBObjectAddress, sa, metaerr.Wrap(err)) if ignoreErrors { @@ -305,19 +358,15 @@ func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { return err } - var obj objectSDK.Object - if err := obj.Unmarshal(data); err != nil { - c.reportFlushError(logs.FSTreeCantDecodeDBObjectAddress, sa, metaerr.Wrap(err)) - if ignoreErrors { - continue - } - return err - } - - if err := c.flushObject(ctx, &obj, data, StorageTypeDB); err != nil { - return err + batch = append(batch, batchItem{data: bytes.Clone(data), address: sa}) + if len(batch) == batchSize { + return errIterationCompleted } } return nil }) + if err == nil || errors.Is(err, errIterationCompleted) { + return batch, nil + } + return nil, err } diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index 20db1de959..4a243c5ec0 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -147,7 +147,7 @@ func runFlushTest[Option any]( require.NoError(t, bs.SetMode(mode.ReadWrite)) require.NoError(t, mb.SetMode(mode.ReadWrite)) - require.NoError(t, wc.Flush(context.Background(), false)) + require.NoError(t, wc.Flush(context.Background(), false, false)) check(t, mb, bs, objects) }) @@ -159,8 +159,6 @@ func runFlushTest[Option any]( // Blobstor is read-only, so we expect en error from `flush` here. require.Error(t, wc.SetMode(mode.Degraded)) - // First move to read-only mode to close background workers. - require.NoError(t, wc.SetMode(mode.ReadOnly)) require.NoError(t, bs.SetMode(mode.ReadWrite)) require.NoError(t, mb.SetMode(mode.ReadWrite)) require.NoError(t, wc.SetMode(mode.Degraded)) @@ -177,14 +175,13 @@ func runFlushTest[Option any]( objects := putObjects(t, wc) f.InjectFn(t, wc) - require.NoError(t, wc.SetMode(mode.ReadOnly)) require.NoError(t, bs.SetMode(mode.ReadWrite)) require.NoError(t, mb.SetMode(mode.ReadWrite)) require.Equal(t, uint32(0), errCount.Load()) - require.Error(t, wc.Flush(context.Background(), false)) + require.Error(t, wc.Flush(context.Background(), false, false)) require.Greater(t, errCount.Load(), uint32(0)) - require.NoError(t, wc.Flush(context.Background(), true)) + require.NoError(t, wc.Flush(context.Background(), true, false)) check(t, mb, bs, objects) }) diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index e3ff2286b7..7c6439fe9b 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -25,7 +25,7 @@ func (c *cache) SetMode(m mode.Mode) error { c.modeMtx.Lock() defer c.modeMtx.Unlock() - err := c.setMode(ctx, m) + err := c.setMode(ctx, m, true) if err == nil { c.metrics.SetMode(m) } @@ -33,12 +33,12 @@ func (c *cache) SetMode(m mode.Mode) error { } // setMode applies new mode. Must be called with cache.modeMtx lock taken. -func (c *cache) setMode(ctx context.Context, m mode.Mode) error { +func (c *cache) setMode(ctx context.Context, m mode.Mode, ignoreErrors bool) error { var err error turnOffMeta := m.NoMetabase() if turnOffMeta && !c.mode.NoMetabase() { - err = c.flush(ctx, true) + err = c.flush(ctx, ignoreErrors) if err != nil { return err } diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index 5c25a3b33f..6cc3b06d03 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -67,14 +67,24 @@ func (c *cache) openStore(readOnly bool) error { return nil } -func (c *cache) deleteFromDB(key string) { +func (c *cache) deleteFromDB(key string, batched bool) { var recordDeleted bool - err := c.db.Batch(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - key := []byte(key) - recordDeleted = b.Get(key) != nil - return b.Delete(key) - }) + var err error + if batched { + err = c.db.Batch(func(tx *bbolt.Tx) error { + b := tx.Bucket(defaultBucket) + key := []byte(key) + recordDeleted = b.Get(key) != nil + return b.Delete(key) + }) + } else { + err = c.db.Update(func(tx *bbolt.Tx) error { + b := tx.Bucket(defaultBucket) + key := []byte(key) + recordDeleted = b.Get(key) != nil + return b.Delete(key) + }) + } if err == nil { c.metrics.Evict(StorageTypeDB) diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 3d3501969e..0549c27f76 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -35,7 +35,7 @@ type Cache interface { SetMode(mode.Mode) error SetLogger(*logger.Logger) DumpInfo() Info - Flush(context.Context, bool) error + Flush(context.Context, bool, bool) error Init() error Open(ctx context.Context, readOnly bool) error diff --git a/pkg/services/control/server/flush_cache.go b/pkg/services/control/server/flush_cache.go index 9ead530dbb..67ffa1f2c2 100644 --- a/pkg/services/control/server/flush_cache.go +++ b/pkg/services/control/server/flush_cache.go @@ -18,6 +18,7 @@ func (s *Server) FlushCache(ctx context.Context, req *control.FlushCacheRequest) for _, shardID := range s.getShardIDList(req.GetBody().GetShard_ID()) { var prm engine.FlushWriteCachePrm prm.SetShardID(shardID) + prm.SetSeal(req.GetBody().GetSeal()) _, err = s.s.FlushWriteCache(ctx, prm) if err != nil { diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 8b8739aba9..90e643e295 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -2585,6 +2585,8 @@ type FlushCacheRequest_Body struct { // ID of the shard. Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` + // If true, then writecache will be left in read-only mode after flush completed. + Seal bool `protobuf:"varint,2,opt,name=seal,proto3" json:"seal,omitempty"` } func (x *FlushCacheRequest_Body) Reset() { @@ -2626,6 +2628,13 @@ func (x *FlushCacheRequest_Body) GetShard_ID() [][]byte { return nil } +func (x *FlushCacheRequest_Body) GetSeal() bool { + if x != nil { + return x.Seal + } + return false +} + // Response body structure. type FlushCacheResponse_Body struct { state protoimpl.MessageState @@ -3772,7 +3781,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x9d, 0x01, 0x0a, 0x11, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xb1, 0x01, 0x0a, 0x11, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, @@ -3780,333 +3789,334 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, + 0x72, 0x65, 0x1a, 0x35, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x84, 0x01, 0x0a, 0x12, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xc9, 0x01, 0x0a, - 0x0d, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x55, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, - 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x75, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x22, 0x7c, 0x0a, 0x0e, 0x44, 0x6f, 0x63, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xd6, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, - 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, - 0x98, 0x01, 0x0a, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x61, 0x6c, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x65, 0x61, 0x6c, 0x22, 0x84, 0x01, 0x0a, 0x12, 0x46, 0x6c, + 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x55, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x20, 0x0a, + 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, + 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x22, 0x7c, 0x0a, 0x0e, + 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x9e, 0x01, 0x0a, 0x1f, 0x47, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe0, 0x05, 0x0a, 0x20, - 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc5, 0x04, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, - 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x0a, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x55, - 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x73, - 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x1a, 0x25, 0x0a, 0x0d, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x24, 0x0a, - 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, - 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, - 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, - 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x94, - 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, - 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xd6, 0x01, 0x0a, 0x1b, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, + 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, - 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x9e, + 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, + 0xe0, 0x05, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc5, 0x04, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x65, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, 0x08, 0x64, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, + 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x1a, 0x25, 0x0a, 0x0d, 0x55, 0x6e, + 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x1a, 0x24, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, + 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, + 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, + 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, + 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, + 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, + 0x10, 0x02, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, - 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, + 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, + 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, + 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, + 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, - 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, - 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xba, 0x01, 0x0a, - 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x22, 0xca, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x32, 0x9d, 0x0b, 0x0a, 0x0e, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, - 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, - 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, - 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, - 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, - 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, - 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, - 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, - 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, - 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, - 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, - 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, + 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, + 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, - 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, - 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, - 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x32, 0x9d, 0x0b, + 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, + 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, + 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, + 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, + 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, + 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, + 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, + 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, + 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, + 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, + 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, + 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, + 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index cbc3aaf548..e3b5073873 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -280,6 +280,8 @@ message FlushCacheRequest { message Body { // ID of the shard. repeated bytes shard_ID = 1; + // If true, then writecache will be left in read-only mode after flush completed. + bool seal = 2; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index e163e54b7a..3ace081e46 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -1180,6 +1180,7 @@ func (x *FlushCacheRequest_Body) StableSize() (size int) { return 0 } size += proto.RepeatedBytesSize(1, x.Shard_ID) + size += proto.BoolSize(2, x.Seal) return size } @@ -1200,6 +1201,7 @@ func (x *FlushCacheRequest_Body) StableMarshal(buf []byte) []byte { } var offset int offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) + offset += proto.BoolMarshal(2, buf[offset:], x.Seal) return buf } From 32c282ca10ba53d0fd2e923caf457ab4febf206c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Dec 2023 11:38:10 +0300 Subject: [PATCH 0238/1413] [#569] writecache: Refactor flush Make single RUnlock call instead of two. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/writecache/flush.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 17dcc1107b..c4e4b3b34a 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -138,13 +138,11 @@ func (c *cache) flushSmallObjects(ctx context.Context) { } } + c.modeMtx.RUnlock() if count == 0 { - c.modeMtx.RUnlock() break } - c.modeMtx.RUnlock() - c.log.Debug(logs.WritecacheTriedToFlushItemsFromWritecache, zap.Int("count", count), zap.String("start", base58.Encode(lastKey))) From 7a9db5bcdd2fd846252fa1388d76be2db8a9458d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Dec 2023 11:40:55 +0300 Subject: [PATCH 0239/1413] [#569] writecache: Do not wait modeMtx if mode changes Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/writecache/delete.go | 5 ++++- pkg/local_object_storage/writecache/put.go | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/writecache/delete.go b/pkg/local_object_storage/writecache/delete.go index 0a4f4d658d..cedb9f4aed 100644 --- a/pkg/local_object_storage/writecache/delete.go +++ b/pkg/local_object_storage/writecache/delete.go @@ -18,6 +18,7 @@ import ( // Delete removes object from write-cache. // // Returns an error of type apistatus.ObjectNotFound if object is missing in write-cache. +// Returns ErrNotInitialized if write-cache has not been initialized yet. func (c *cache) Delete(ctx context.Context, addr oid.Address) error { ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Delete", trace.WithAttributes( @@ -32,7 +33,9 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { c.metrics.Delete(time.Since(startedAt), deleted, storageType) }() - c.modeMtx.RLock() + if !c.modeMtx.TryRLock() { + return ErrNotInitialized + } defer c.modeMtx.RUnlock() if c.readOnly() { return ErrReadOnly diff --git a/pkg/local_object_storage/writecache/put.go b/pkg/local_object_storage/writecache/put.go index 6fc655c651..8b6c09e9ad 100644 --- a/pkg/local_object_storage/writecache/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -34,7 +34,9 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro c.metrics.Put(time.Since(startedAt), added, storageType) }() - c.modeMtx.RLock() + if !c.modeMtx.TryRLock() { + return common.PutRes{}, ErrNotInitialized + } defer c.modeMtx.RUnlock() if c.readOnly() { return common.PutRes{}, ErrReadOnly From 581887148a8971434a3becbc4e561c8a859f5fd7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Dec 2023 14:37:22 +0300 Subject: [PATCH 0240/1413] [#569] cli: Add `control shards writecache seal` command It does the same as `control shards flush-writecache --seal`, but has better name. Signed-off-by: Dmitrii Stepanov --- .../modules/control/flush_cache.go | 9 +- cmd/frostfs-cli/modules/control/shards.go | 2 + cmd/frostfs-cli/modules/control/writecache.go | 73 ++ pkg/local_object_storage/engine/writecache.go | 77 +- pkg/local_object_storage/shard/writecache.go | 30 + pkg/local_object_storage/writecache/seal.go | 28 + .../writecache/writecache.go | 1 + pkg/services/control/rpc.go | 14 + .../control/server/seal_writecache.go | 48 + pkg/services/control/service.pb.go | 1085 +++++++++++------ pkg/services/control/service.proto | 32 + pkg/services/control/service_frostfs.pb.go | 213 ++++ pkg/services/control/service_grpc.pb.go | 39 + 13 files changed, 1297 insertions(+), 354 deletions(-) create mode 100644 cmd/frostfs-cli/modules/control/writecache.go create mode 100644 pkg/local_object_storage/writecache/seal.go create mode 100644 pkg/services/control/server/seal_writecache.go diff --git a/cmd/frostfs-cli/modules/control/flush_cache.go b/cmd/frostfs-cli/modules/control/flush_cache.go index 7f632e9fc5..5419619037 100644 --- a/cmd/frostfs-cli/modules/control/flush_cache.go +++ b/cmd/frostfs-cli/modules/control/flush_cache.go @@ -11,10 +11,11 @@ import ( const sealFlag = "seal" var flushCacheCmd = &cobra.Command{ - Use: "flush-cache", - Short: "Flush objects from the write-cache to the main storage", - Long: "Flush objects from the write-cache to the main storage", - Run: flushCache, + Use: "flush-cache", + Short: "Flush objects from the write-cache to the main storage", + Long: "Flush objects from the write-cache to the main storage", + Run: flushCache, + Deprecated: "Flushing objects from writecache to the main storage is performed by writecache automatically. To flush and seal writecache use `frostfs-cli control shards writecache seal`.", } func flushCache(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-cli/modules/control/shards.go b/cmd/frostfs-cli/modules/control/shards.go index 6208c560bf..6d3ef420c3 100644 --- a/cmd/frostfs-cli/modules/control/shards.go +++ b/cmd/frostfs-cli/modules/control/shards.go @@ -17,6 +17,7 @@ func initControlShardsCmd() { shardsCmd.AddCommand(evacuationShardCmd) shardsCmd.AddCommand(flushCacheCmd) shardsCmd.AddCommand(doctorCmd) + shardsCmd.AddCommand(writecacheShardCmd) initControlShardsListCmd() initControlSetShardModeCmd() @@ -24,4 +25,5 @@ func initControlShardsCmd() { initControlEvacuationShardCmd() initControlFlushCacheCmd() initControlDoctorCmd() + initControlShardsWritecacheCmd() } diff --git a/cmd/frostfs-cli/modules/control/writecache.go b/cmd/frostfs-cli/modules/control/writecache.go new file mode 100644 index 0000000000..abc4ed2e6f --- /dev/null +++ b/cmd/frostfs-cli/modules/control/writecache.go @@ -0,0 +1,73 @@ +package control + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "github.com/mr-tron/base58" + "github.com/spf13/cobra" +) + +var writecacheShardCmd = &cobra.Command{ + Use: "writecache", + Short: "Operations with storage node's write-cache", + Long: "Operations with storage node's write-cache", +} + +var sealWritecacheShardCmd = &cobra.Command{ + Use: "seal", + Short: "Flush objects from write-cache and move write-cache to degraded read only mode.", + Long: "Flush all the objects from the write-cache to the main storage and move the write-cache to the degraded read only mode: write-cache will be empty and no objects will be put in it.", + Run: sealWritecache, +} + +func sealWritecache(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + ignoreErrors, _ := cmd.Flags().GetBool(ignoreErrorsFlag) + + req := &control.SealWriteCacheRequest{Body: &control.SealWriteCacheRequest_Body{ + Shard_ID: getShardIDList(cmd), + IgnoreErrors: ignoreErrors, + }} + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.SealWriteCacheResponse + var err error + err = cli.ExecRaw(func(client *client.Client) error { + resp, err = control.SealWriteCache(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + var success, failed uint + for _, res := range resp.GetBody().GetResults() { + if res.GetSuccess() { + success++ + cmd.Printf("Shard %s: OK\n", base58.Encode(res.GetShard_ID())) + } else { + failed++ + cmd.Printf("Shard %s: failed with error %q\n", base58.Encode(res.GetShard_ID()), res.GetError()) + } + } + cmd.Printf("Total: %d success, %d failed\n", success, failed) +} + +func initControlShardsWritecacheCmd() { + writecacheShardCmd.AddCommand(sealWritecacheShardCmd) + + initControlFlags(sealWritecacheShardCmd) + + ff := sealWritecacheShardCmd.Flags() + ff.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") + ff.Bool(shardAllFlag, false, "Process all shards") + ff.Bool(ignoreErrorsFlag, true, "Skip invalid/unreadable objects") + + sealWritecacheShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag) +} diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index d92a86f5d6..0eca018f83 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -2,6 +2,7 @@ package engine import ( "context" + "sync" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" @@ -11,6 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + "golang.org/x/sync/errgroup" ) // FlushWriteCachePrm groups the parameters of FlushWriteCache operation. @@ -44,7 +46,7 @@ type FlushWriteCacheRes struct{} func (e *StorageEngine) FlushWriteCache(ctx context.Context, p FlushWriteCachePrm) (FlushWriteCacheRes, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.FlushWriteCache", trace.WithAttributes( - attribute.String("shard)id", p.shardID.String()), + attribute.String("shard_id", p.shardID.String()), attribute.Bool("ignore_errors", p.ignoreErrors), attribute.Bool("seal", p.seal), )) @@ -65,6 +67,79 @@ func (e *StorageEngine) FlushWriteCache(ctx context.Context, p FlushWriteCachePr return FlushWriteCacheRes{}, sh.FlushWriteCache(ctx, prm) } +type SealWriteCachePrm struct { + ShardIDs []*shard.ID + IgnoreErrors bool +} + +type ShardSealResult struct { + ShardID *shard.ID + Success bool + ErrorMsg string +} + +type SealWriteCacheRes struct { + ShardResults []ShardSealResult +} + +// SealWriteCache flushed all data to blobstore and moves write-cache to degraded read only mode. +func (e *StorageEngine) SealWriteCache(ctx context.Context, prm SealWriteCachePrm) (SealWriteCacheRes, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.SealWriteCache", + trace.WithAttributes( + attribute.Int("shard_id_count", len(prm.ShardIDs)), + attribute.Bool("ignore_errors", prm.IgnoreErrors), + )) + defer span.End() + + res := SealWriteCacheRes{ + ShardResults: make([]ShardSealResult, 0, len(prm.ShardIDs)), + } + resGuard := &sync.Mutex{} + + eg, egCtx := errgroup.WithContext(ctx) + for _, shardID := range prm.ShardIDs { + shardID := shardID + eg.Go(func() error { + e.mtx.RLock() + sh, ok := e.shards[shardID.String()] + e.mtx.RUnlock() + + if !ok { + resGuard.Lock() + defer resGuard.Unlock() + res.ShardResults = append(res.ShardResults, ShardSealResult{ + ShardID: shardID, + ErrorMsg: errShardNotFound.Error(), + }) + return nil + } + + err := sh.SealWriteCache(egCtx, shard.SealWriteCachePrm{IgnoreErrors: prm.IgnoreErrors}) + + resGuard.Lock() + defer resGuard.Unlock() + + if err != nil { + res.ShardResults = append(res.ShardResults, ShardSealResult{ + ShardID: shardID, + ErrorMsg: err.Error(), + }) + } else { + res.ShardResults = append(res.ShardResults, ShardSealResult{ + ShardID: shardID, + Success: true, + }) + } + return nil + }) + } + + if err := eg.Wait(); err != nil { + return SealWriteCacheRes{}, err + } + return res, nil +} + type writeCacheMetrics struct { shardID string metrics metrics.WriteCacheMetrics diff --git a/pkg/local_object_storage/shard/writecache.go b/pkg/local_object_storage/shard/writecache.go index 4e57a04974..05e014d29c 100644 --- a/pkg/local_object_storage/shard/writecache.go +++ b/pkg/local_object_storage/shard/writecache.go @@ -56,3 +56,33 @@ func (s *Shard) FlushWriteCache(ctx context.Context, p FlushWriteCachePrm) error return s.writeCache.Flush(ctx, p.ignoreErrors, p.seal) } + +type SealWriteCachePrm struct { + IgnoreErrors bool +} + +// SealWriteCache flushes all data from the write-cache and moves it to degraded read only mode. +func (s *Shard) SealWriteCache(ctx context.Context, p SealWriteCachePrm) error { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.SealWriteCache", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.Bool("ignore_errors", p.IgnoreErrors), + )) + defer span.End() + + if !s.hasWriteCache() { + return errWriteCacheDisabled + } + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.ReadOnly() { + return ErrReadOnlyMode + } + if s.info.Mode.NoMetabase() { + return ErrDegradedMode + } + + return s.writeCache.Seal(ctx, p.IgnoreErrors) +} diff --git a/pkg/local_object_storage/writecache/seal.go b/pkg/local_object_storage/writecache/seal.go new file mode 100644 index 0000000000..be4fec3678 --- /dev/null +++ b/pkg/local_object_storage/writecache/seal.go @@ -0,0 +1,28 @@ +package writecache + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) + +func (c *cache) Seal(ctx context.Context, ignoreErrors bool) error { + ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Seal", + trace.WithAttributes( + attribute.Bool("ignore_errors", ignoreErrors), + )) + defer span.End() + + c.modeMtx.Lock() + defer c.modeMtx.Unlock() + + // flush will be done by setMode + err := c.setMode(ctx, mode.DegradedReadOnly, ignoreErrors) + if err == nil { + c.metrics.SetMode(mode.DegradedReadOnly) + } + return err +} diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 0549c27f76..99fc5390a4 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -36,6 +36,7 @@ type Cache interface { SetLogger(*logger.Logger) DumpInfo() Info Flush(context.Context, bool, bool) error + Seal(context.Context, bool) error Init() error Open(ctx context.Context, readOnly bool) error diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index b9ec05e71c..3fd4d4ae95 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -24,6 +24,7 @@ const ( rpcGetChainLocalOverride = "GetChainLocalOverride" rpcListChainLocalOverrides = "ListChainLocalOverrides" rpcRemoveChainLocalOverride = "RemoveChainLocalOverride" + rpcSealWriteCache = "SealWriteCache" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -264,3 +265,16 @@ func RemoveChainLocalOverride(cli *client.Client, req *RemoveChainLocalOverrideR return wResp.message, nil } + +// SealWriteCache executes ControlService.SealWriteCache RPC. +func SealWriteCache(cli *client.Client, req *SealWriteCacheRequest, opts ...client.CallOption) (*SealWriteCacheResponse, error) { + wResp := newResponseWrapper[SealWriteCacheResponse]() + wReq := &requestWrapper{m: req} + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcSealWriteCache), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.message, nil +} diff --git a/pkg/services/control/server/seal_writecache.go b/pkg/services/control/server/seal_writecache.go new file mode 100644 index 0000000000..5c39cf4849 --- /dev/null +++ b/pkg/services/control/server/seal_writecache.go @@ -0,0 +1,48 @@ +package control + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Server) SealWriteCache(ctx context.Context, req *control.SealWriteCacheRequest) (*control.SealWriteCacheResponse, error) { + err := s.isValidRequest(req) + if err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + prm := engine.SealWriteCachePrm{ + ShardIDs: s.getShardIDList(req.GetBody().GetShard_ID()), + IgnoreErrors: req.GetBody().GetIgnoreErrors(), + } + + res, err := s.s.SealWriteCache(ctx, prm) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + resp := &control.SealWriteCacheResponse{Body: &control.SealWriteCacheResponse_Body{}} + for _, r := range res.ShardResults { + if r.Success { + resp.Body.Results = append(resp.GetBody().GetResults(), &control.SealWriteCacheResponse_Body_Status{ + Shard_ID: *r.ShardID, + Success: true, + }) + } else { + resp.Body.Results = append(resp.GetBody().GetResults(), &control.SealWriteCacheResponse_Body_Status{ + Shard_ID: *r.ShardID, + Error: r.ErrorMsg, + }) + } + } + + err = SignMessage(s.key, resp) + if err != nil { + return nil, err + } + return resp, nil +} diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 90e643e295..33ed898ba5 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -1884,6 +1884,116 @@ func (x *RemoveChainLocalOverrideResponse) GetSignature() *Signature { return nil } +type SealWriteCacheRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *SealWriteCacheRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *SealWriteCacheRequest) Reset() { + *x = SealWriteCacheRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SealWriteCacheRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SealWriteCacheRequest) ProtoMessage() {} + +func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[32] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SealWriteCacheRequest.ProtoReflect.Descriptor instead. +func (*SealWriteCacheRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32} +} + +func (x *SealWriteCacheRequest) GetBody() *SealWriteCacheRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *SealWriteCacheRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type SealWriteCacheResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *SealWriteCacheResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *SealWriteCacheResponse) Reset() { + *x = SealWriteCacheResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SealWriteCacheResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SealWriteCacheResponse) ProtoMessage() {} + +func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SealWriteCacheResponse.ProtoReflect.Descriptor instead. +func (*SealWriteCacheResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33} +} + +func (x *SealWriteCacheResponse) GetBody() *SealWriteCacheResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *SealWriteCacheResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + // Health check request body. type HealthCheckRequest_Body struct { state protoimpl.MessageState @@ -1894,7 +2004,7 @@ type HealthCheckRequest_Body struct { func (x *HealthCheckRequest_Body) Reset() { *x = HealthCheckRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1907,7 +2017,7 @@ func (x *HealthCheckRequest_Body) String() string { func (*HealthCheckRequest_Body) ProtoMessage() {} func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1938,7 +2048,7 @@ type HealthCheckResponse_Body struct { func (x *HealthCheckResponse_Body) Reset() { *x = HealthCheckResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1951,7 +2061,7 @@ func (x *HealthCheckResponse_Body) String() string { func (*HealthCheckResponse_Body) ProtoMessage() {} func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2002,7 +2112,7 @@ type SetNetmapStatusRequest_Body struct { func (x *SetNetmapStatusRequest_Body) Reset() { *x = SetNetmapStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2015,7 +2125,7 @@ func (x *SetNetmapStatusRequest_Body) String() string { func (*SetNetmapStatusRequest_Body) ProtoMessage() {} func (x *SetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2055,7 +2165,7 @@ type SetNetmapStatusResponse_Body struct { func (x *SetNetmapStatusResponse_Body) Reset() { *x = SetNetmapStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2068,7 +2178,7 @@ func (x *SetNetmapStatusResponse_Body) String() string { func (*SetNetmapStatusResponse_Body) ProtoMessage() {} func (x *SetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2098,7 +2208,7 @@ type DropObjectsRequest_Body struct { func (x *DropObjectsRequest_Body) Reset() { *x = DropObjectsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2111,7 +2221,7 @@ func (x *DropObjectsRequest_Body) String() string { func (*DropObjectsRequest_Body) ProtoMessage() {} func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2144,7 +2254,7 @@ type DropObjectsResponse_Body struct { func (x *DropObjectsResponse_Body) Reset() { *x = DropObjectsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2157,7 +2267,7 @@ func (x *DropObjectsResponse_Body) String() string { func (*DropObjectsResponse_Body) ProtoMessage() {} func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2183,7 +2293,7 @@ type ListShardsRequest_Body struct { func (x *ListShardsRequest_Body) Reset() { *x = ListShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2196,7 +2306,7 @@ func (x *ListShardsRequest_Body) String() string { func (*ListShardsRequest_Body) ProtoMessage() {} func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2225,7 +2335,7 @@ type ListShardsResponse_Body struct { func (x *ListShardsResponse_Body) Reset() { *x = ListShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2238,7 +2348,7 @@ func (x *ListShardsResponse_Body) String() string { func (*ListShardsResponse_Body) ProtoMessage() {} func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2278,7 +2388,7 @@ type SetShardModeRequest_Body struct { func (x *SetShardModeRequest_Body) Reset() { *x = SetShardModeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2291,7 +2401,7 @@ func (x *SetShardModeRequest_Body) String() string { func (*SetShardModeRequest_Body) ProtoMessage() {} func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2338,7 +2448,7 @@ type SetShardModeResponse_Body struct { func (x *SetShardModeResponse_Body) Reset() { *x = SetShardModeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2351,7 +2461,7 @@ func (x *SetShardModeResponse_Body) String() string { func (*SetShardModeResponse_Body) ProtoMessage() {} func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2382,7 +2492,7 @@ type SynchronizeTreeRequest_Body struct { func (x *SynchronizeTreeRequest_Body) Reset() { *x = SynchronizeTreeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2395,7 +2505,7 @@ func (x *SynchronizeTreeRequest_Body) String() string { func (*SynchronizeTreeRequest_Body) ProtoMessage() {} func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2442,7 +2552,7 @@ type SynchronizeTreeResponse_Body struct { func (x *SynchronizeTreeResponse_Body) Reset() { *x = SynchronizeTreeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2455,7 +2565,7 @@ func (x *SynchronizeTreeResponse_Body) String() string { func (*SynchronizeTreeResponse_Body) ProtoMessage() {} func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2486,7 +2596,7 @@ type EvacuateShardRequest_Body struct { func (x *EvacuateShardRequest_Body) Reset() { *x = EvacuateShardRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2499,7 +2609,7 @@ func (x *EvacuateShardRequest_Body) String() string { func (*EvacuateShardRequest_Body) ProtoMessage() {} func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2541,7 +2651,7 @@ type EvacuateShardResponse_Body struct { func (x *EvacuateShardResponse_Body) Reset() { *x = EvacuateShardResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2554,7 +2664,7 @@ func (x *EvacuateShardResponse_Body) String() string { func (*EvacuateShardResponse_Body) ProtoMessage() {} func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2592,7 +2702,7 @@ type FlushCacheRequest_Body struct { func (x *FlushCacheRequest_Body) Reset() { *x = FlushCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2605,7 +2715,7 @@ func (x *FlushCacheRequest_Body) String() string { func (*FlushCacheRequest_Body) ProtoMessage() {} func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2645,7 +2755,7 @@ type FlushCacheResponse_Body struct { func (x *FlushCacheResponse_Body) Reset() { *x = FlushCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2658,7 +2768,7 @@ func (x *FlushCacheResponse_Body) String() string { func (*FlushCacheResponse_Body) ProtoMessage() {} func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2689,7 +2799,7 @@ type DoctorRequest_Body struct { func (x *DoctorRequest_Body) Reset() { *x = DoctorRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2702,7 +2812,7 @@ func (x *DoctorRequest_Body) String() string { func (*DoctorRequest_Body) ProtoMessage() {} func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2742,7 +2852,7 @@ type DoctorResponse_Body struct { func (x *DoctorResponse_Body) Reset() { *x = DoctorResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2755,7 +2865,7 @@ func (x *DoctorResponse_Body) String() string { func (*DoctorResponse_Body) ProtoMessage() {} func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2786,7 +2896,7 @@ type StartShardEvacuationRequest_Body struct { func (x *StartShardEvacuationRequest_Body) Reset() { *x = StartShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2799,7 +2909,7 @@ func (x *StartShardEvacuationRequest_Body) String() string { func (*StartShardEvacuationRequest_Body) ProtoMessage() {} func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2839,7 +2949,7 @@ type StartShardEvacuationResponse_Body struct { func (x *StartShardEvacuationResponse_Body) Reset() { *x = StartShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2852,7 +2962,7 @@ func (x *StartShardEvacuationResponse_Body) String() string { func (*StartShardEvacuationResponse_Body) ProtoMessage() {} func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2878,7 +2988,7 @@ type GetShardEvacuationStatusRequest_Body struct { func (x *GetShardEvacuationStatusRequest_Body) Reset() { *x = GetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2891,7 +3001,7 @@ func (x *GetShardEvacuationStatusRequest_Body) String() string { func (*GetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2936,7 +3046,7 @@ type GetShardEvacuationStatusResponse_Body struct { func (x *GetShardEvacuationStatusResponse_Body) Reset() { *x = GetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2949,7 +3059,7 @@ func (x *GetShardEvacuationStatusResponse_Body) String() string { func (*GetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3040,7 +3150,7 @@ type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) Reset() { *x = GetShardEvacuationStatusResponse_Body_UnixTimestamp{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3053,7 +3163,7 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) String() string { func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3088,7 +3198,7 @@ type GetShardEvacuationStatusResponse_Body_Duration struct { func (x *GetShardEvacuationStatusResponse_Body_Duration) Reset() { *x = GetShardEvacuationStatusResponse_Body_Duration{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3101,7 +3211,7 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) String() string { func (*GetShardEvacuationStatusResponse_Body_Duration) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3134,7 +3244,7 @@ type StopShardEvacuationRequest_Body struct { func (x *StopShardEvacuationRequest_Body) Reset() { *x = StopShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3147,7 +3257,7 @@ func (x *StopShardEvacuationRequest_Body) String() string { func (*StopShardEvacuationRequest_Body) ProtoMessage() {} func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3173,7 +3283,7 @@ type StopShardEvacuationResponse_Body struct { func (x *StopShardEvacuationResponse_Body) Reset() { *x = StopShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3186,7 +3296,7 @@ func (x *StopShardEvacuationResponse_Body) String() string { func (*StopShardEvacuationResponse_Body) ProtoMessage() {} func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3218,7 +3328,7 @@ type AddChainLocalOverrideRequest_Body struct { func (x *AddChainLocalOverrideRequest_Body) Reset() { *x = AddChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3231,7 +3341,7 @@ func (x *AddChainLocalOverrideRequest_Body) String() string { func (*AddChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3275,7 +3385,7 @@ type AddChainLocalOverrideResponse_Body struct { func (x *AddChainLocalOverrideResponse_Body) Reset() { *x = AddChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3288,7 +3398,7 @@ func (x *AddChainLocalOverrideResponse_Body) String() string { func (*AddChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3325,7 +3435,7 @@ type GetChainLocalOverrideRequest_Body struct { func (x *GetChainLocalOverrideRequest_Body) Reset() { *x = GetChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3338,7 +3448,7 @@ func (x *GetChainLocalOverrideRequest_Body) String() string { func (*GetChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3380,7 +3490,7 @@ type GetChainLocalOverrideResponse_Body struct { func (x *GetChainLocalOverrideResponse_Body) Reset() { *x = GetChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3393,7 +3503,7 @@ func (x *GetChainLocalOverrideResponse_Body) String() string { func (*GetChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3428,7 +3538,7 @@ type ListChainLocalOverridesRequest_Body struct { func (x *ListChainLocalOverridesRequest_Body) Reset() { *x = ListChainLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3441,7 +3551,7 @@ func (x *ListChainLocalOverridesRequest_Body) String() string { func (*ListChainLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3476,7 +3586,7 @@ type ListChainLocalOverridesResponse_Body struct { func (x *ListChainLocalOverridesResponse_Body) Reset() { *x = ListChainLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3489,7 +3599,7 @@ func (x *ListChainLocalOverridesResponse_Body) String() string { func (*ListChainLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3526,7 +3636,7 @@ type RemoveChainLocalOverrideRequest_Body struct { func (x *RemoveChainLocalOverrideRequest_Body) Reset() { *x = RemoveChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3539,7 +3649,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) String() string { func (*RemoveChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3580,7 +3690,7 @@ type RemoveChainLocalOverrideResponse_Body struct { func (x *RemoveChainLocalOverrideResponse_Body) Reset() { *x = RemoveChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3593,7 +3703,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) String() string { func (*RemoveChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3616,6 +3726,174 @@ func (x *RemoveChainLocalOverrideResponse_Body) GetRemoved() bool { return false } +// Request body structure. +type SealWriteCacheRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // ID of the shard. + Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` + // Flag indicating whether object read errors should be ignored. + IgnoreErrors bool `protobuf:"varint,2,opt,name=ignore_errors,json=ignoreErrors,proto3" json:"ignore_errors,omitempty"` +} + +func (x *SealWriteCacheRequest_Body) Reset() { + *x = SealWriteCacheRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SealWriteCacheRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SealWriteCacheRequest_Body) ProtoMessage() {} + +func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[68] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SealWriteCacheRequest_Body.ProtoReflect.Descriptor instead. +func (*SealWriteCacheRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32, 0} +} + +func (x *SealWriteCacheRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} + +func (x *SealWriteCacheRequest_Body) GetIgnoreErrors() bool { + if x != nil { + return x.IgnoreErrors + } + return false +} + +type SealWriteCacheResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Results []*SealWriteCacheResponse_Body_Status `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` +} + +func (x *SealWriteCacheResponse_Body) Reset() { + *x = SealWriteCacheResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[69] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SealWriteCacheResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SealWriteCacheResponse_Body) ProtoMessage() {} + +func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[69] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SealWriteCacheResponse_Body.ProtoReflect.Descriptor instead. +func (*SealWriteCacheResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} +} + +func (x *SealWriteCacheResponse_Body) GetResults() []*SealWriteCacheResponse_Body_Status { + if x != nil { + return x.Results + } + return nil +} + +type SealWriteCacheResponse_Body_Status struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Shard_ID []byte `protobuf:"bytes,1,opt,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` + Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"` +} + +func (x *SealWriteCacheResponse_Body_Status) Reset() { + *x = SealWriteCacheResponse_Body_Status{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[70] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SealWriteCacheResponse_Body_Status) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SealWriteCacheResponse_Body_Status) ProtoMessage() {} + +func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[70] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SealWriteCacheResponse_Body_Status.ProtoReflect.Descriptor instead. +func (*SealWriteCacheResponse_Body_Status) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0, 0} +} + +func (x *SealWriteCacheResponse_Body_Status) GetShard_ID() []byte { + if x != nil { + return x.Shard_ID + } + return nil +} + +func (x *SealWriteCacheResponse_Body_Status) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} + +func (x *SealWriteCacheResponse_Body_Status) GetError() string { + if x != nil { + return x.Error + } + return "" +} + var File_pkg_services_control_service_proto protoreflect.FileDescriptor var file_pkg_services_control_service_proto_rawDesc = []byte{ @@ -4021,102 +4299,139 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x32, 0x9d, 0x0b, - 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, - 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, - 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, - 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, - 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, - 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, - 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, - 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0xca, 0x01, + 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, + 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, + 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, + 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, + 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xf0, 0x0b, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, + 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, + 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, + 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, + 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, + 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, + 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, + 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, - 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, - 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, - 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, - 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, - 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, + 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, + 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, + 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4132,7 +4447,7 @@ func file_pkg_services_control_service_proto_rawDescGZIP() []byte { } var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 66) +var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 71) var file_pkg_services_control_service_proto_goTypes = []interface{}{ (GetShardEvacuationStatusResponse_Body_Status)(0), // 0: control.GetShardEvacuationStatusResponse.Body.Status (*HealthCheckRequest)(nil), // 1: control.HealthCheckRequest @@ -4167,161 +4482,173 @@ var file_pkg_services_control_service_proto_goTypes = []interface{}{ (*ListChainLocalOverridesResponse)(nil), // 30: control.ListChainLocalOverridesResponse (*RemoveChainLocalOverrideRequest)(nil), // 31: control.RemoveChainLocalOverrideRequest (*RemoveChainLocalOverrideResponse)(nil), // 32: control.RemoveChainLocalOverrideResponse - (*HealthCheckRequest_Body)(nil), // 33: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 34: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 35: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 36: control.SetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 37: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 38: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 39: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 40: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 41: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 42: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 43: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 44: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 45: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 46: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 47: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 48: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 49: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 50: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 51: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 52: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 53: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 54: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 55: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 56: control.GetShardEvacuationStatusResponse.Body.Duration - (*StopShardEvacuationRequest_Body)(nil), // 57: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 58: control.StopShardEvacuationResponse.Body - (*AddChainLocalOverrideRequest_Body)(nil), // 59: control.AddChainLocalOverrideRequest.Body - (*AddChainLocalOverrideResponse_Body)(nil), // 60: control.AddChainLocalOverrideResponse.Body - (*GetChainLocalOverrideRequest_Body)(nil), // 61: control.GetChainLocalOverrideRequest.Body - (*GetChainLocalOverrideResponse_Body)(nil), // 62: control.GetChainLocalOverrideResponse.Body - (*ListChainLocalOverridesRequest_Body)(nil), // 63: control.ListChainLocalOverridesRequest.Body - (*ListChainLocalOverridesResponse_Body)(nil), // 64: control.ListChainLocalOverridesResponse.Body - (*RemoveChainLocalOverrideRequest_Body)(nil), // 65: control.RemoveChainLocalOverrideRequest.Body - (*RemoveChainLocalOverrideResponse_Body)(nil), // 66: control.RemoveChainLocalOverrideResponse.Body - (*Signature)(nil), // 67: control.Signature - (NetmapStatus)(0), // 68: control.NetmapStatus - (HealthStatus)(0), // 69: control.HealthStatus - (*ShardInfo)(nil), // 70: control.ShardInfo - (ShardMode)(0), // 71: control.ShardMode - (*ChainTarget)(nil), // 72: control.ChainTarget + (*SealWriteCacheRequest)(nil), // 33: control.SealWriteCacheRequest + (*SealWriteCacheResponse)(nil), // 34: control.SealWriteCacheResponse + (*HealthCheckRequest_Body)(nil), // 35: control.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 36: control.HealthCheckResponse.Body + (*SetNetmapStatusRequest_Body)(nil), // 37: control.SetNetmapStatusRequest.Body + (*SetNetmapStatusResponse_Body)(nil), // 38: control.SetNetmapStatusResponse.Body + (*DropObjectsRequest_Body)(nil), // 39: control.DropObjectsRequest.Body + (*DropObjectsResponse_Body)(nil), // 40: control.DropObjectsResponse.Body + (*ListShardsRequest_Body)(nil), // 41: control.ListShardsRequest.Body + (*ListShardsResponse_Body)(nil), // 42: control.ListShardsResponse.Body + (*SetShardModeRequest_Body)(nil), // 43: control.SetShardModeRequest.Body + (*SetShardModeResponse_Body)(nil), // 44: control.SetShardModeResponse.Body + (*SynchronizeTreeRequest_Body)(nil), // 45: control.SynchronizeTreeRequest.Body + (*SynchronizeTreeResponse_Body)(nil), // 46: control.SynchronizeTreeResponse.Body + (*EvacuateShardRequest_Body)(nil), // 47: control.EvacuateShardRequest.Body + (*EvacuateShardResponse_Body)(nil), // 48: control.EvacuateShardResponse.Body + (*FlushCacheRequest_Body)(nil), // 49: control.FlushCacheRequest.Body + (*FlushCacheResponse_Body)(nil), // 50: control.FlushCacheResponse.Body + (*DoctorRequest_Body)(nil), // 51: control.DoctorRequest.Body + (*DoctorResponse_Body)(nil), // 52: control.DoctorResponse.Body + (*StartShardEvacuationRequest_Body)(nil), // 53: control.StartShardEvacuationRequest.Body + (*StartShardEvacuationResponse_Body)(nil), // 54: control.StartShardEvacuationResponse.Body + (*GetShardEvacuationStatusRequest_Body)(nil), // 55: control.GetShardEvacuationStatusRequest.Body + (*GetShardEvacuationStatusResponse_Body)(nil), // 56: control.GetShardEvacuationStatusResponse.Body + (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 57: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 58: control.GetShardEvacuationStatusResponse.Body.Duration + (*StopShardEvacuationRequest_Body)(nil), // 59: control.StopShardEvacuationRequest.Body + (*StopShardEvacuationResponse_Body)(nil), // 60: control.StopShardEvacuationResponse.Body + (*AddChainLocalOverrideRequest_Body)(nil), // 61: control.AddChainLocalOverrideRequest.Body + (*AddChainLocalOverrideResponse_Body)(nil), // 62: control.AddChainLocalOverrideResponse.Body + (*GetChainLocalOverrideRequest_Body)(nil), // 63: control.GetChainLocalOverrideRequest.Body + (*GetChainLocalOverrideResponse_Body)(nil), // 64: control.GetChainLocalOverrideResponse.Body + (*ListChainLocalOverridesRequest_Body)(nil), // 65: control.ListChainLocalOverridesRequest.Body + (*ListChainLocalOverridesResponse_Body)(nil), // 66: control.ListChainLocalOverridesResponse.Body + (*RemoveChainLocalOverrideRequest_Body)(nil), // 67: control.RemoveChainLocalOverrideRequest.Body + (*RemoveChainLocalOverrideResponse_Body)(nil), // 68: control.RemoveChainLocalOverrideResponse.Body + (*SealWriteCacheRequest_Body)(nil), // 69: control.SealWriteCacheRequest.Body + (*SealWriteCacheResponse_Body)(nil), // 70: control.SealWriteCacheResponse.Body + (*SealWriteCacheResponse_Body_Status)(nil), // 71: control.SealWriteCacheResponse.Body.Status + (*Signature)(nil), // 72: control.Signature + (NetmapStatus)(0), // 73: control.NetmapStatus + (HealthStatus)(0), // 74: control.HealthStatus + (*ShardInfo)(nil), // 75: control.ShardInfo + (ShardMode)(0), // 76: control.ShardMode + (*ChainTarget)(nil), // 77: control.ChainTarget } var file_pkg_services_control_service_proto_depIdxs = []int32{ - 33, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 67, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 34, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 67, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 35, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 67, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 36, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 67, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 37, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 67, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature - 38, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 67, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature - 39, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 67, // 13: control.ListShardsRequest.signature:type_name -> control.Signature - 40, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 67, // 15: control.ListShardsResponse.signature:type_name -> control.Signature - 41, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 67, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature - 42, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 67, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature - 43, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 67, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 44, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 67, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 45, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 67, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature - 46, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 67, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature - 47, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 67, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature - 48, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 67, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature - 49, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 67, // 33: control.DoctorRequest.signature:type_name -> control.Signature - 50, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 67, // 35: control.DoctorResponse.signature:type_name -> control.Signature - 51, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 67, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 52, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 67, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 53, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 67, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 54, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 67, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 57, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 67, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 58, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 67, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 59, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body - 67, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature - 60, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body - 67, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature - 61, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body - 67, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature - 62, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body - 67, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature - 63, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body - 67, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature - 64, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body - 67, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature - 65, // 60: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body - 67, // 61: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature - 66, // 62: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body - 67, // 63: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature - 68, // 64: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 69, // 65: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 68, // 66: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 70, // 67: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 71, // 68: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 0, // 69: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 56, // 70: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 55, // 71: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 72, // 72: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 72, // 73: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 72, // 74: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget - 72, // 75: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 1, // 76: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 3, // 77: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 5, // 78: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 7, // 79: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 9, // 80: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 11, // 81: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 13, // 82: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 19, // 83: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 21, // 84: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 23, // 85: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 15, // 86: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 17, // 87: control.ControlService.Doctor:input_type -> control.DoctorRequest - 25, // 88: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 27, // 89: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 29, // 90: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 31, // 91: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 2, // 92: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 4, // 93: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 6, // 94: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 8, // 95: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 10, // 96: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 12, // 97: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 14, // 98: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 20, // 99: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 22, // 100: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 24, // 101: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 16, // 102: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 18, // 103: control.ControlService.Doctor:output_type -> control.DoctorResponse - 26, // 104: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 28, // 105: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 30, // 106: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 32, // 107: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 92, // [92:108] is the sub-list for method output_type - 76, // [76:92] is the sub-list for method input_type - 76, // [76:76] is the sub-list for extension type_name - 76, // [76:76] is the sub-list for extension extendee - 0, // [0:76] is the sub-list for field type_name + 35, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body + 72, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature + 36, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body + 72, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature + 37, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body + 72, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature + 38, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body + 72, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature + 39, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body + 72, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature + 40, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body + 72, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature + 41, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body + 72, // 13: control.ListShardsRequest.signature:type_name -> control.Signature + 42, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body + 72, // 15: control.ListShardsResponse.signature:type_name -> control.Signature + 43, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body + 72, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature + 44, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body + 72, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature + 45, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body + 72, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature + 46, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body + 72, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature + 47, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body + 72, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature + 48, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body + 72, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature + 49, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body + 72, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature + 50, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body + 72, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature + 51, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body + 72, // 33: control.DoctorRequest.signature:type_name -> control.Signature + 52, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body + 72, // 35: control.DoctorResponse.signature:type_name -> control.Signature + 53, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body + 72, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature + 54, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body + 72, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature + 55, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body + 72, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 56, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body + 72, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 59, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body + 72, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature + 60, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body + 72, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature + 61, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body + 72, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature + 62, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body + 72, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature + 63, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body + 72, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature + 64, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body + 72, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature + 65, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body + 72, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature + 66, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body + 72, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature + 67, // 60: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body + 72, // 61: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature + 68, // 62: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body + 72, // 63: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature + 69, // 64: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body + 72, // 65: control.SealWriteCacheRequest.signature:type_name -> control.Signature + 70, // 66: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body + 72, // 67: control.SealWriteCacheResponse.signature:type_name -> control.Signature + 73, // 68: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus + 74, // 69: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus + 73, // 70: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus + 75, // 71: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo + 76, // 72: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode + 0, // 73: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status + 58, // 74: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration + 57, // 75: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + 77, // 76: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 77, // 77: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 77, // 78: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget + 77, // 79: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 71, // 80: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status + 1, // 81: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 3, // 82: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 5, // 83: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 7, // 84: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 9, // 85: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 11, // 86: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 13, // 87: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 19, // 88: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 21, // 89: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 23, // 90: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 15, // 91: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 17, // 92: control.ControlService.Doctor:input_type -> control.DoctorRequest + 25, // 93: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 27, // 94: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 29, // 95: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 31, // 96: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 33, // 97: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest + 2, // 98: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 4, // 99: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 6, // 100: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 8, // 101: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 10, // 102: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 12, // 103: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 14, // 104: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 20, // 105: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 22, // 106: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 24, // 107: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 16, // 108: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 18, // 109: control.ControlService.Doctor:output_type -> control.DoctorResponse + 26, // 110: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 28, // 111: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 30, // 112: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 32, // 113: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 34, // 114: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse + 98, // [98:115] is the sub-list for method output_type + 81, // [81:98] is the sub-list for method input_type + 81, // [81:81] is the sub-list for extension type_name + 81, // [81:81] is the sub-list for extension extendee + 0, // [0:81] is the sub-list for field type_name } func init() { file_pkg_services_control_service_proto_init() } @@ -4716,7 +5043,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { + switch v := v.(*SealWriteCacheRequest); i { case 0: return &v.state case 1: @@ -4728,7 +5055,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { + switch v := v.(*SealWriteCacheResponse); i { case 0: return &v.state case 1: @@ -4740,7 +5067,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest_Body); i { + switch v := v.(*HealthCheckRequest_Body); i { case 0: return &v.state case 1: @@ -4752,7 +5079,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse_Body); i { + switch v := v.(*HealthCheckResponse_Body); i { case 0: return &v.state case 1: @@ -4764,7 +5091,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest_Body); i { + switch v := v.(*SetNetmapStatusRequest_Body); i { case 0: return &v.state case 1: @@ -4776,7 +5103,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse_Body); i { + switch v := v.(*SetNetmapStatusResponse_Body); i { case 0: return &v.state case 1: @@ -4788,7 +5115,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest_Body); i { + switch v := v.(*DropObjectsRequest_Body); i { case 0: return &v.state case 1: @@ -4800,7 +5127,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse_Body); i { + switch v := v.(*DropObjectsResponse_Body); i { case 0: return &v.state case 1: @@ -4812,7 +5139,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest_Body); i { + switch v := v.(*ListShardsRequest_Body); i { case 0: return &v.state case 1: @@ -4824,7 +5151,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse_Body); i { + switch v := v.(*ListShardsResponse_Body); i { case 0: return &v.state case 1: @@ -4836,7 +5163,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest_Body); i { + switch v := v.(*SetShardModeRequest_Body); i { case 0: return &v.state case 1: @@ -4848,7 +5175,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse_Body); i { + switch v := v.(*SetShardModeResponse_Body); i { case 0: return &v.state case 1: @@ -4860,7 +5187,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest_Body); i { + switch v := v.(*SynchronizeTreeRequest_Body); i { case 0: return &v.state case 1: @@ -4872,7 +5199,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse_Body); i { + switch v := v.(*SynchronizeTreeResponse_Body); i { case 0: return &v.state case 1: @@ -4884,7 +5211,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest_Body); i { + switch v := v.(*EvacuateShardRequest_Body); i { case 0: return &v.state case 1: @@ -4896,7 +5223,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse_Body); i { + switch v := v.(*EvacuateShardResponse_Body); i { case 0: return &v.state case 1: @@ -4908,7 +5235,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest_Body); i { + switch v := v.(*FlushCacheRequest_Body); i { case 0: return &v.state case 1: @@ -4920,7 +5247,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse_Body); i { + switch v := v.(*FlushCacheResponse_Body); i { case 0: return &v.state case 1: @@ -4932,7 +5259,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest_Body); i { + switch v := v.(*DoctorRequest_Body); i { case 0: return &v.state case 1: @@ -4944,7 +5271,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse_Body); i { + switch v := v.(*DoctorResponse_Body); i { case 0: return &v.state case 1: @@ -4956,7 +5283,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest_Body); i { + switch v := v.(*StartShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -4968,7 +5295,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body); i { + switch v := v.(*StartShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -4980,7 +5307,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { + switch v := v.(*GetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -4992,7 +5319,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -5004,7 +5331,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { case 0: return &v.state case 1: @@ -5016,7 +5343,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { case 0: return &v.state case 1: @@ -5028,7 +5355,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest_Body); i { + switch v := v.(*StopShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -5040,7 +5367,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse_Body); i { + switch v := v.(*StopShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -5052,7 +5379,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest_Body); i { + switch v := v.(*AddChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -5064,7 +5391,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse_Body); i { + switch v := v.(*AddChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -5076,7 +5403,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest_Body); i { + switch v := v.(*GetChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -5088,7 +5415,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse_Body); i { + switch v := v.(*GetChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -5100,7 +5427,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + switch v := v.(*ListChainLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -5112,6 +5439,30 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListChainLocalOverridesResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { case 0: return &v.state @@ -5123,6 +5474,42 @@ func file_pkg_services_control_service_proto_init() { return nil } } + file_pkg_services_control_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body_Status); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -5130,7 +5517,7 @@ func file_pkg_services_control_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_service_proto_rawDesc, NumEnums: 1, - NumMessages: 66, + NumMessages: 71, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index e3b5073873..34c040f2a5 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -56,6 +56,9 @@ service ControlService { // Remove local access policy engine overrides stored in the node by chaind id. rpc RemoveChainLocalOverride (RemoveChainLocalOverrideRequest) returns (RemoveChainLocalOverrideResponse); + + // Flush objects from write-cache and move it to degraded read only mode. + rpc SealWriteCache(SealWriteCacheRequest) returns (SealWriteCacheResponse); } // Health check request. @@ -525,3 +528,32 @@ message RemoveChainLocalOverrideResponse { Signature signature = 2; } + +message SealWriteCacheRequest { + // Request body structure. + message Body { + // ID of the shard. + repeated bytes shard_ID = 1; + + // Flag indicating whether object read errors should be ignored. + bool ignore_errors = 2; + } + + Body body = 1; + Signature signature = 2; +} + +message SealWriteCacheResponse { + message Body { + message Status { + bytes shard_ID = 1; + bool success = 2; + string error = 3; + } + repeated Status results = 1; + } + + Body body = 1; + + Signature signature = 2; +} \ No newline at end of file diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 3ace081e46..4ce6791f89 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2755,3 +2755,216 @@ func (x *RemoveChainLocalOverrideResponse) ReadSignedData(buf []byte) ([]byte, e func (x *RemoveChainLocalOverrideResponse) SetSignature(sig *Signature) { x.Signature = sig } + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *SealWriteCacheRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.RepeatedBytesSize(1, x.Shard_ID) + size += proto.BoolSize(2, x.IgnoreErrors) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *SealWriteCacheRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) + offset += proto.BoolMarshal(2, buf[offset:], x.IgnoreErrors) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *SealWriteCacheRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *SealWriteCacheRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *SealWriteCacheRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *SealWriteCacheRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *SealWriteCacheRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *SealWriteCacheResponse_Body_Status) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BytesSize(1, x.Shard_ID) + size += proto.BoolSize(2, x.Success) + size += proto.StringSize(3, x.Error) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *SealWriteCacheResponse_Body_Status) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.BytesMarshal(1, buf[offset:], x.Shard_ID) + offset += proto.BoolMarshal(2, buf[offset:], x.Success) + offset += proto.StringMarshal(3, buf[offset:], x.Error) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *SealWriteCacheResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + for i := range x.Results { + size += proto.NestedStructureSize(1, x.Results[i]) + } + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *SealWriteCacheResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + for i := range x.Results { + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Results[i]) + } + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *SealWriteCacheResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *SealWriteCacheResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *SealWriteCacheResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *SealWriteCacheResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *SealWriteCacheResponse) SetSignature(sig *Signature) { + x.Signature = sig +} diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index c3976c54aa..e09f6750b6 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -35,6 +35,7 @@ const ( ControlService_GetChainLocalOverride_FullMethodName = "/control.ControlService/GetChainLocalOverride" ControlService_ListChainLocalOverrides_FullMethodName = "/control.ControlService/ListChainLocalOverrides" ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" + ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" ) // ControlServiceClient is the client API for ControlService service. @@ -74,6 +75,8 @@ type ControlServiceClient interface { ListChainLocalOverrides(ctx context.Context, in *ListChainLocalOverridesRequest, opts ...grpc.CallOption) (*ListChainLocalOverridesResponse, error) // Remove local access policy engine overrides stored in the node by chaind id. RemoveChainLocalOverride(ctx context.Context, in *RemoveChainLocalOverrideRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverrideResponse, error) + // Flush objects from write-cache and move it to degraded read only mode. + SealWriteCache(ctx context.Context, in *SealWriteCacheRequest, opts ...grpc.CallOption) (*SealWriteCacheResponse, error) } type controlServiceClient struct { @@ -228,6 +231,15 @@ func (c *controlServiceClient) RemoveChainLocalOverride(ctx context.Context, in return out, nil } +func (c *controlServiceClient) SealWriteCache(ctx context.Context, in *SealWriteCacheRequest, opts ...grpc.CallOption) (*SealWriteCacheResponse, error) { + out := new(SealWriteCacheResponse) + err := c.cc.Invoke(ctx, ControlService_SealWriteCache_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ControlServiceServer is the server API for ControlService service. // All implementations should embed UnimplementedControlServiceServer // for forward compatibility @@ -265,6 +277,8 @@ type ControlServiceServer interface { ListChainLocalOverrides(context.Context, *ListChainLocalOverridesRequest) (*ListChainLocalOverridesResponse, error) // Remove local access policy engine overrides stored in the node by chaind id. RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) + // Flush objects from write-cache and move it to degraded read only mode. + SealWriteCache(context.Context, *SealWriteCacheRequest) (*SealWriteCacheResponse, error) } // UnimplementedControlServiceServer should be embedded to have forward compatible implementations. @@ -319,6 +333,9 @@ func (UnimplementedControlServiceServer) ListChainLocalOverrides(context.Context func (UnimplementedControlServiceServer) RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveChainLocalOverride not implemented") } +func (UnimplementedControlServiceServer) SealWriteCache(context.Context, *SealWriteCacheRequest) (*SealWriteCacheResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SealWriteCache not implemented") +} // UnsafeControlServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ControlServiceServer will @@ -619,6 +636,24 @@ func _ControlService_RemoveChainLocalOverride_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _ControlService_SealWriteCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SealWriteCacheRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).SealWriteCache(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_SealWriteCache_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).SealWriteCache(ctx, req.(*SealWriteCacheRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ControlService_ServiceDesc is the grpc.ServiceDesc for ControlService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -690,6 +725,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "RemoveChainLocalOverride", Handler: _ControlService_RemoveChainLocalOverride_Handler, }, + { + MethodName: "SealWriteCache", + Handler: _ControlService_SealWriteCache_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pkg/services/control/service.proto", From 530249e3bd7ae7f8eff5ac22ecf27782a0470831 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 29 Dec 2023 17:11:36 +0300 Subject: [PATCH 0241/1413] [#893] go.mod: Update neo-go Signed-off-by: Evgenii Stratonikov --- go.mod | 4 ++-- go.sum | 8 ++++---- pkg/morph/client/notifications.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index c4266fe213..82ad0212da 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,7 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.12.0 github.com/nats-io/nats.go v1.31.0 - github.com/nspcc-dev/neo-go v0.104.0 + github.com/nspcc-dev/neo-go v0.105.0 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 github.com/paulmach/orb v0.9.2 @@ -113,7 +113,7 @@ require ( go.opentelemetry.io/otel/sdk v1.21.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect diff --git a/go.sum b/go.sum index 490cd4aec4..75d2487c49 100644 --- a/go.sum +++ b/go.sum @@ -172,8 +172,8 @@ github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c h1:OOQeE613BH93ICPq3eke5N78gWNeMjcBWkmD2NKyXVg= github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= -github.com/nspcc-dev/neo-go v0.104.0 h1:FGj3Z46yABcFIAI1SCLd1jQSoh+B00h/2VAgEgY1JKQ= -github.com/nspcc-dev/neo-go v0.104.0/go.mod h1:omsUK5PAtG2/nQ3/evs95QEg3wtkj3LH53e0NKtXVwQ= +github.com/nspcc-dev/neo-go v0.105.0 h1:vtNZYFEFySK8zRDhLzQYha849VzWrcKezlnq/oNQg/w= +github.com/nspcc-dev/neo-go v0.105.0/go.mod h1:6pchIHg5okeZO955RxpTh5q0sUI0vtpgPM6Q+no1rlI= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231201072346-6c0c2a6a98b0 h1:GYeU/mq2qfq6fNSuTzgxvlQQUydeCBicjzdnggwtuz0= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231201072346-6c0c2a6a98b0/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= @@ -296,8 +296,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= diff --git a/pkg/morph/client/notifications.go b/pkg/morph/client/notifications.go index a013631dff..35204bb366 100644 --- a/pkg/morph/client/notifications.go +++ b/pkg/morph/client/notifications.go @@ -73,7 +73,7 @@ func (c *Client) ReceiveNotaryRequests(txSigner util.Uint160, ch chan<- *result. return "", ErrConnectionLost } - return c.client.ReceiveNotaryRequests(&neorpc.TxFilter{Signer: &txSigner}, ch) + return c.client.ReceiveNotaryRequests(&neorpc.NotaryRequestFilter{Signer: &txSigner}, ch) } // Unsubscribe performs unsubscription for the given subscription ID. From 225fe2d4d5781b69bfe8222dd0a109d97181ad63 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 29 Dec 2023 18:54:38 +0300 Subject: [PATCH 0242/1413] [#894] blobovniczatree: Speedup rebuild test Down from 3s to 300ms. Signed-off-by: Evgenii Stratonikov --- .../blobstor/blobovniczatree/rebuild_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 921515a6ab..904971d25d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -46,7 +46,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta WithBlobovniczaShallowWidth(sourceWidth), WithBlobovniczaShallowDepth(sourceDepth), WithRootPath(dir), - WithBlobovniczaSize(100*1024*1024), + WithBlobovniczaSize(100*1024), WithWaitBeforeDropDB(0), WithOpenedCacheSize(1000), WithMoveBatchSize(3)) @@ -56,7 +56,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta eg, egCtx := errgroup.WithContext(context.Background()) storageIDs := make(map[oid.Address][]byte) storageIDsGuard := &sync.Mutex{} - for i := 0; i < 1000; i++ { + for i := 0; i < 100; i++ { eg.Go(func() error { obj := blobstortest.NewObject(1024) data, err := obj.Marshal() @@ -86,10 +86,10 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta WithBlobovniczaShallowWidth(targetWidth), WithBlobovniczaShallowDepth(targetDepth), WithRootPath(dir), - WithBlobovniczaSize(100*1024*1024), + WithBlobovniczaSize(100*1024), WithWaitBeforeDropDB(0), WithOpenedCacheSize(1000), - WithMoveBatchSize(3)) + WithMoveBatchSize(50)) require.NoError(t, b.Open(false)) require.NoError(t, b.Init()) From d5d3d8badb45bb09a13fc4ca9f2c57d920f14616 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 29 Dec 2023 14:16:40 +0300 Subject: [PATCH 0243/1413] [#892] node: Add VSCode debug example Signed-off-by: Dmitrii Stepanov --- Makefile | 26 ++++++++++ README.md | 39 +++++++++++++++ dev/.vscode-example/launch.json | 89 +++++++++++++++++++++++++++++++++ dev/.vscode-example/tasks.json | 19 +++++++ dev/adm/frostfs-adm.yml | 17 +++++++ dev/docker-compose.yml | 16 ++++++ dev/ir/az.json | 69 +++++++++++++++++++++++++ dev/ir/contract.json | 30 +++++++++++ dev/neo-go/config.yml | 4 ++ dev/neo-go/node-wallet.json | 68 +++++++++++++++++++++++++ dev/neo-go/protocol.privnet.yml | 48 ++++++++++++++++++ dev/neo-go/wallet.json | 30 +++++++++++ dev/storage/wallet.json | 32 ++++++++++++ dev/wallet.json | 30 +++++++++++ 14 files changed, 517 insertions(+) create mode 100644 dev/.vscode-example/launch.json create mode 100644 dev/.vscode-example/tasks.json create mode 100644 dev/adm/frostfs-adm.yml create mode 100644 dev/docker-compose.yml create mode 100644 dev/ir/az.json create mode 100644 dev/ir/contract.json create mode 100644 dev/neo-go/config.yml create mode 100644 dev/neo-go/node-wallet.json create mode 100644 dev/neo-go/protocol.privnet.yml create mode 100644 dev/neo-go/wallet.json create mode 100644 dev/storage/wallet.json create mode 100644 dev/wallet.json diff --git a/Makefile b/Makefile index 153640da84..84653a03a2 100755 --- a/Makefile +++ b/Makefile @@ -44,6 +44,10 @@ PROTOGEN_FROSTFS_DIR ?= $(PROTOBUF_DIR)/protogen-$(PROTOGEN_FROSTFS_VERSION) STATICCHECK_DIR ?= $(abspath $(BIN))/staticcheck STATICCHECK_VERSION_DIR ?= $(STATICCHECK_DIR)/$(STATICCHECK_VERSION) +FROSTFS_CONTRACTS_PATH=$(abspath ./../frostfs-contract) +LOCODE_DB_PATH=$(abspath ./.cache/locode_db) +LOCODE_DB_VERSION=v0.4.0 + .PHONY: help all images dep clean fmts fumpt imports test lint docker/lint prepare-release debpackage pre-commit unpre-commit @@ -234,3 +238,25 @@ debpackage: debclean: dh clean + +locode-download: + @wget -q -O ./.cache/locode_db.gz 'https://git.frostfs.info/TrueCloudLab/frostfs-locode-db/releases/download/${LOCODE_DB_VERSION}/locode_db.gz' + gzip -dfk ./.cache/locode_db.gz + +env-up: all + docker compose -f dev/docker-compose.yml up -d + @if [ ! -d "$(FROSTFS_CONTRACTS_PATH)" ]; then \ + echo "Frostfs contracts not found"; exit 1; \ + fi + ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph init --contracts ${FROSTFS_CONTRACTS_PATH} + ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet.json --gas 10.0 + @if [ ! -f "$(LOCODE_DB_PATH)" ]; then \ + make locode-download; \ + fi + +env-down: + docker compose -f dev/docker-compose.yml down + docker volume rm -f frostfs-node_neo-go + rm -f ./.cache/.frostfs-ir-state + rm -f ./.cache/.frostfs-node-state + rm -rf ./.cache/storage \ No newline at end of file diff --git a/README.md b/README.md index c3a9bf09c7..ff816f2c7f 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,45 @@ To make docker images suitable for use in [frostfs-dev-env](https://github.com/T make images ``` +# Debugging + +## VSCode + +To run and debug single node cluster with VSCode: + +1. Clone and build [frostfs-contract](https://git.frostfs.info/TrueCloudLab/frostfs-contract) repository to the same directory level as `frostfs-node`. For example: + +``` +/ +├── src + ├── frostfs-node + └── frostfs-contract +``` +See `frostfs-contract`'s README.md for build instructions. + +2. Copy `launch.json` and `tasks.json` from `dev/.vscode-example` directory to `.vscode` directory. If you already have such files in `.vscode` directory, then merge them manually. + +3. Go to **Run and Debug** (`Ctrl+Shift+D`) and start `IR+Storage node` configuration. + +4. To create container and put object into it run (container and object IDs will be different): + +``` +./bin/frostfs-cli container create -r 127.0.0.1:8080 --wallet ./dev/wallet.json --policy "REP 1 IN X CBF 1 SELECT 1 FROM * AS X" --basic-acl public-read-write --await +Enter password > <- press ENTER, the is no password for wallet +CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju + +./bin/frostfs-cli object put -r 127.0.0.1:8080 --wallet ./dev/wallet.json --file README.md --cid CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju +Enter password > + 4300 / 4300 [===========================================================================================================================================================================================================] 100.00% 0s +[README.md] Object successfully stored + OID: 78sohnudVMnPsczXqsTUcvezosan2YDNVZwDE8Kq5YwU + CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju + +./bin/frostfs-cli object get -r 127.0.0.1:8080 --wallet ./dev/wallet.json --cid CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju --oid 78sohnudVMnPsczXqsTUcvezosan2YDNVZwDE8Kq5YwU +... + +``` + # Contributing Feel free to contribute to this project after reading the [contributing diff --git a/dev/.vscode-example/launch.json b/dev/.vscode-example/launch.json new file mode 100644 index 0000000000..cf91c0d24a --- /dev/null +++ b/dev/.vscode-example/launch.json @@ -0,0 +1,89 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "IR", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "cmd/frostfs-ir", + "env": { + "FROSTFS_IR_LOGGER_LEVEL":"info", + "FROSTFS_IR_WALLET_PATH":"${workspaceFolder}/dev/ir/az.json", + "FROSTFS_IR_WALLET_ADDRESS":"Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn", + "FROSTFS_IR_WALLET_PASSWORD":"one", + "FROSTFS_IR_WITHOUT_MAINNET":"true", + "FROSTFS_IR_MORPH_ENDPOINT_CLIENT_0_ADDRESS":"ws://127.0.0.1:30333/ws", + "FROSTFS_IR_MORPH_VALIDATORS":"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2", + "FROSTFS_IR_TIMERS_EMIT":"50", + "FROSTFS_IR_TIMERS_STOP_ESTIMATION_MUL":"1", + "FROSTFS_IR_TIMERS_STOP_ESTIMATION_DIV":"4", + "FROSTFS_IR_TIMERS_COLLECT_BASIC_INCOME_MUL":"1", + "FROSTFS_IR_TIMERS_COLLECT_BASIC_INCOME_DIV":"2", + "FROSTFS_IR_TIMERS_DISTRIBUTE_BASIC_INCOME_MUL":"3", + "FROSTFS_IR_TIMERS_DISTRIBUTE_BASIC_INCOME_DIV":"4", + "FROSTFS_IR_EMIT_STORAGE_AMOUNT":"1000000000", + "FROSTFS_IR_NETMAP_CLEANER_ENABLED":"true", + "FROSTFS_IR_NETMAP_CLEANER_THRESHOLD":"3", + "FROSTFS_IR_LOCODE_DB_PATH":"${workspaceFolder}/.cache/locode_db", + "FROSTFS_IR_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8090", + "FROSTFS_IR_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/.frostfs-ir-state" + }, + "postDebugTask": "env-down" + }, + { + "name": "Storage node", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "cmd/frostfs-node", + "env": { + "FROSTFS_LOGGER_LEVEL":"debug", + "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", + "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", + "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", + "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet.json", + "FROSTFS_NODE_WALLET_PASSWORD":"", + "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8080", + "FROSTFS_GRPC_0_ENDPOINT":"127.0.0.1:8080", + "FROSTFS_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8081", + "FROSTFS_NODE_ATTRIBUTE_0":"User-Agent:FrostFS/dev", + "FROSTFS_NODE_ATTRIBUTE_1":"UN-LOCODE:RU MOW", + "FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/.frostfs-node-state", + "FROSTFS_TREE_ENABLED":"true", + "FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME":"10", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_ENABLED":"true", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/wc0", + "FROSTFS_STORAGE_SHARD_0_METABASE_PATH":"${workspaceFolder}/.cache/storage/meta0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_TYPE":"blobovnicza", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/blobovnicza0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH":"4", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE":"fstree", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/fstree0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_0_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/pilorama0", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_ENABLED":"true", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/wc1", + "FROSTFS_STORAGE_SHARD_1_METABASE_PATH":"${workspaceFolder}/.cache/storage/meta1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_TYPE":"blobovnicza", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/blobovnicza1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH":"4", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE":"fstree", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/fstree1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/pilorama1" + }, + "postDebugTask": "env-down" + } + ], + "compounds": [ + { + "name": "IR+Storage node", + "configurations": ["IR", "Storage node"], + "preLaunchTask": "env-up", + "stopAll": true + } + ] +} \ No newline at end of file diff --git a/dev/.vscode-example/tasks.json b/dev/.vscode-example/tasks.json new file mode 100644 index 0000000000..8c6099a059 --- /dev/null +++ b/dev/.vscode-example/tasks.json @@ -0,0 +1,19 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "env-up", + "command": "make env-up", + "group": "build", + "detail": "Up debug environment" + }, + { + "type": "shell", + "label": "env-down", + "command": "make env-down", + "group": "build", + "detail": "Down debug environment" + } + ] +} \ No newline at end of file diff --git a/dev/adm/frostfs-adm.yml b/dev/adm/frostfs-adm.yml new file mode 100644 index 0000000000..5dc87e70c5 --- /dev/null +++ b/dev/adm/frostfs-adm.yml @@ -0,0 +1,17 @@ +rpc-endpoint: http://127.0.0.1:30333 +alphabet-wallets: ./dev/ir +network: + max_object_size: 5242880 + epoch_duration: 60 + basic_income_rate: 100000000 + homomorphic_hash_disabled: false + maintenance_mode_allowed: true + fee: + audit: 10000 + candidate: 10000000000 + container: 0 + container_alias: 0 + withdraw: 100000000 +credentials: + az: "one" + contract: "one" diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml new file mode 100644 index 0000000000..7e68ea02ea --- /dev/null +++ b/dev/docker-compose.yml @@ -0,0 +1,16 @@ +--- + +version: "2.4" +services: + neo-go: + image: nspccdev/neo-go:0.103.0 + container_name: neo-go + command: ["node", "--config-path", "/config", "--privnet", "--debug"] + stop_signal: SIGKILL + ports: + - 30333:30333 + volumes: + - ./neo-go/protocol.privnet.yml:/config/protocol.privnet.yml + - ./neo-go/node-wallet.json:/wallets/node-wallet.json + - ./neo-go/config.yml:/wallets/config.yml + - ./neo-go/wallet.json:/wallets/wallet.json diff --git a/dev/ir/az.json b/dev/ir/az.json new file mode 100644 index 0000000000..a16aec295f --- /dev/null +++ b/dev/ir/az.json @@ -0,0 +1,69 @@ +{ + "version": "3.0", + "name":null, + "accounts": [ + { + "address": "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn", + "key": "6PYM8VdX2BSm7BSXKzV4Fz6S3R9cDLLWNrD9nMjxW352jEv3fsC8N3wNLY", + "label": "single", + "contract": { + "script": "DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcJBVuezJw==", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "extra":null, + "isDefault": false + }, + { + "address": "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP", + "key": "6PYM8VdX2BSm7BSXKzV4Fz6S3R9cDLLWNrD9nMjxW352jEv3fsC8N3wNLY", + "label": "consensus", + "contract": { + "script": "EQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CEUGe0Nw6", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "extra":null, + "isDefault": false + }, + { + "address": "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP", + "key": "6PYM8VdX2BSm7BSXKzV4Fz6S3R9cDLLWNrD9nMjxW352jEv3fsC8N3wNLY", + "label": "committee", + "contract": { + "script": "EQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CEUGe0Nw6", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "extra":null, + "isDefault": true + } + ], + "scrypt": { + "n": 16384, + "r": 8, + "p": 8 + }, + "extra": { + "Tokens": null + } +} + diff --git a/dev/ir/contract.json b/dev/ir/contract.json new file mode 100644 index 0000000000..310b77bd79 --- /dev/null +++ b/dev/ir/contract.json @@ -0,0 +1,30 @@ +{ + "version": "3.0", + "accounts": [ + { + "address": "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn", + "key": "6PYM8VdX2BSm7BSXKzV4Fz6S3R9cDLLWNrD9nMjxW352jEv3fsC8N3wNLY", + "label": "", + "contract": { + "script": "DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcJBVuezJw==", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "isDefault": false + } + ], + "scrypt": { + "n": 16384, + "r": 8, + "p": 8 + }, + "extra": { + "Tokens": null + } +} diff --git a/dev/neo-go/config.yml b/dev/neo-go/config.yml new file mode 100644 index 0000000000..7b4bb29d7b --- /dev/null +++ b/dev/neo-go/config.yml @@ -0,0 +1,4 @@ +--- + +Path: "/wallets/node-wallet.json" +Password: "one" diff --git a/dev/neo-go/node-wallet.json b/dev/neo-go/node-wallet.json new file mode 100644 index 0000000000..8e88b432c9 --- /dev/null +++ b/dev/neo-go/node-wallet.json @@ -0,0 +1,68 @@ +{ + "version": "3.0", + "name":null, + "accounts": [ + { + "address": "Nhfg3TbpwogLvDGVvAvqyThbsHgoSUKwtn", + "key": "6PYM8VdX2BSm7BSXKzV4Fz6S3R9cDLLWNrD9nMjxW352jEv3fsC8N3wNLY", + "label": "single", + "contract": { + "script": "DCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcJBVuezJw==", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "extra":null, + "isDefault": false + }, + { + "address": "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP", + "key": "6PYM8VdX2BSm7BSXKzV4Fz6S3R9cDLLWNrD9nMjxW352jEv3fsC8N3wNLY", + "label": "consensus", + "contract": { + "script": "EQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CEUGe0Nw6", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "extra":null, + "isDefault": false + }, + { + "address": "NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP", + "key": "6PYM8VdX2BSm7BSXKzV4Fz6S3R9cDLLWNrD9nMjxW352jEv3fsC8N3wNLY", + "label": "committee", + "contract": { + "script": "EQwhArNiK/QBe9/jF8WK7V9MdT8ga324lgRvp9d0u8S/f43CEUGe0Nw6", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "extra":null, + "isDefault": true + } + ], + "scrypt": { + "n": 16384, + "r": 8, + "p": 8 + }, + "extra": { + "Tokens": null + } +} diff --git a/dev/neo-go/protocol.privnet.yml b/dev/neo-go/protocol.privnet.yml new file mode 100644 index 0000000000..8aaf774a30 --- /dev/null +++ b/dev/neo-go/protocol.privnet.yml @@ -0,0 +1,48 @@ +ProtocolConfiguration: + Magic: 15405 + MaxTraceableBlocks: 200000 + TimePerBlock: 1s + MemPoolSize: 50000 + StandbyCommittee: + - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 + ValidatorsCount: 1 + SeedList: + - 0.0.0.0:20333 + VerifyTransactions: true + StateRootInHeader: true + P2PSigExtensions: true + +ApplicationConfiguration: + SkipBlockVerification: false + DBConfiguration: + Type: "boltdb" + BoltDBOptions: + FilePath: "./db/morph.bolt" + P2P: + Addresses: + - ":20333" + DialTimeout: 3s + ProtoTickInterval: 2s + PingInterval: 30s + PingTimeout: 90s + MaxPeers: 10 + AttemptConnPeers: 5 + MinPeers: 0 + Relay: true + Consensus: + Enabled: true + UnlockWallet: + Path: "./wallets/node-wallet.json" + Password: "one" + RPC: + Addresses: + - "0.0.0.0:30333" + Enabled: true + SessionEnabled: true + EnableCORSWorkaround: false + MaxGasInvoke: 100 + P2PNotary: + Enabled: true + UnlockWallet: + Path: "./wallets/node-wallet.json" + Password: "one" diff --git a/dev/neo-go/wallet.json b/dev/neo-go/wallet.json new file mode 100644 index 0000000000..ce68d604c8 --- /dev/null +++ b/dev/neo-go/wallet.json @@ -0,0 +1,30 @@ +{ + "version": "3.0", + "accounts": [ + { + "address": "NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM", + "key": "6PYP7YrwGnLuu4WYQbEe3WJiC44aKmqwqawLsp7H3oh5vocS9xTv2ZfTp3", + "label": "", + "contract": { + "script": "DCEDGmxvu98CyjUXRfqGubpalFLXhaxPf8K3VIyipGxPz0pBVuezJw==", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "isdefault": false + } + ], + "scrypt": { + "n": 16384, + "r": 8, + "p": 8 + }, + "extra": { + "Tokens": null + } +} diff --git a/dev/storage/wallet.json b/dev/storage/wallet.json new file mode 100644 index 0000000000..e5b6bb3710 --- /dev/null +++ b/dev/storage/wallet.json @@ -0,0 +1,32 @@ +{ + "version":"3.0", + "accounts":[ + { + "address":"NejLbQpojKJWec4NQRMBhzsrmCyhXfGJJe", + "key":"6PYSS8ccmBcttfcw2YJh8VcNSoeQbQLuJLQ7HoKeYF5roRmGs9LUvmKcWz", + "label":"", + "contract":{ + "script":"DCECK7QEHFDWB/+HHex+TNd3g4jg6mhJ2EzL2aqPMuFqgTFBVuezJw==", + "parameters":[ + { + "name":"parameter0", + "type":"Signature" + } + ], + "deployed":false + }, + "lock":false, + "extra":null, + "isDefault":true + } + ], + "name":null, + "scrypt":{ + "n":16384, + "r":8, + "p":8 + }, + "extra":{ + "Tokens":null + } + } diff --git a/dev/wallet.json b/dev/wallet.json new file mode 100644 index 0000000000..ce68d604c8 --- /dev/null +++ b/dev/wallet.json @@ -0,0 +1,30 @@ +{ + "version": "3.0", + "accounts": [ + { + "address": "NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM", + "key": "6PYP7YrwGnLuu4WYQbEe3WJiC44aKmqwqawLsp7H3oh5vocS9xTv2ZfTp3", + "label": "", + "contract": { + "script": "DCEDGmxvu98CyjUXRfqGubpalFLXhaxPf8K3VIyipGxPz0pBVuezJw==", + "parameters": [ + { + "name": "parameter0", + "type": "Signature" + } + ], + "deployed": false + }, + "lock": false, + "isdefault": false + } + ], + "scrypt": { + "n": 16384, + "r": 8, + "p": 8 + }, + "extra": { + "Tokens": null + } +} From dfd62ca6b1e20ee3a091da36fd77f7c262d6af5d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 25 Dec 2023 10:15:26 +0300 Subject: [PATCH 0244/1413] [#864] metabase: Refactor delete/inhume Available -> Logic, Raw -> Phy for delete/inhume results. Use single counter instead of vectors. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/counter.go | 2 +- .../metabase/counter_test.go | 14 ++-- pkg/local_object_storage/metabase/delete.go | 84 +++++++++---------- pkg/local_object_storage/metabase/inhume.go | 20 ++--- pkg/local_object_storage/shard/delete.go | 14 ++-- pkg/local_object_storage/shard/gc.go | 12 +-- pkg/local_object_storage/shard/inhume.go | 2 +- 7 files changed, 71 insertions(+), 77 deletions(-) diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index 96d80077d6..581df7a59f 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -239,7 +239,7 @@ func (db *DB) updateShardObjectCounter(tx *bbolt.Tx, typ objectType, delta uint6 return b.Put(counterKey, newCounter) } -func (db *DB) updateContainerCounter(tx *bbolt.Tx, delta map[cid.ID]ObjectCounters, inc bool) error { // TODO #838 +func (db *DB) updateContainerCounter(tx *bbolt.Tx, delta map[cid.ID]ObjectCounters, inc bool) error { b := tx.Bucket(containerCounterBucketName) if b == nil { return nil diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 9241c97a02..2f40daaaee 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -91,7 +91,7 @@ func TestCounters(t *testing.T) { res, err := db.Delete(context.Background(), prm) require.NoError(t, err) - require.Equal(t, uint64(1), res.AvailableObjectsRemoved()) + require.Equal(t, uint64(1), res.LogicCount()) c, err := db.ObjectCounters() require.NoError(t, err) @@ -161,7 +161,7 @@ func TestCounters(t *testing.T) { res, err := db.Inhume(context.Background(), prm) require.NoError(t, err) - require.Equal(t, uint64(len(inhumedObjs)), res.AvailableInhumed()) + require.Equal(t, uint64(len(inhumedObjs)), res.LogicInhumed()) require.Equal(t, uint64(len(inhumedObjs)), res.UserInhumed()) c, err := db.ObjectCounters() @@ -389,7 +389,7 @@ func TestCounters_Expired(t *testing.T) { inhumeRes, err := db.Inhume(context.Background(), inhumePrm) require.NoError(t, err) - require.Equal(t, uint64(1), inhumeRes.AvailableInhumed()) + require.Equal(t, uint64(1), inhumeRes.LogicInhumed()) require.Equal(t, uint64(1), inhumeRes.UserInhumed()) c, err = db.ObjectCounters() @@ -423,8 +423,8 @@ func TestCounters_Expired(t *testing.T) { deleteRes, err := db.Delete(context.Background(), deletePrm) require.NoError(t, err) - require.Zero(t, deleteRes.AvailableObjectsRemoved()) - require.Zero(t, deleteRes.UserObjectsRemoved()) + require.Zero(t, deleteRes.LogicCount()) + require.Zero(t, deleteRes.UserCount()) if v, ok := exp[oo[0].Container()]; ok { v.Phy-- @@ -456,8 +456,8 @@ func TestCounters_Expired(t *testing.T) { deleteRes, err = db.Delete(context.Background(), deletePrm) require.NoError(t, err) - require.Equal(t, uint64(1), deleteRes.AvailableObjectsRemoved()) - require.Equal(t, uint64(1), deleteRes.UserObjectsRemoved()) + require.Equal(t, uint64(1), deleteRes.LogicCount()) + require.Equal(t, uint64(1), deleteRes.UserCount()) if v, ok := exp[oo[0].Container()]; ok { v.Phy-- diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 6a5661ed1e..b2210b55c6 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -27,22 +27,22 @@ type DeletePrm struct { // DeleteRes groups the resulting values of Delete operation. type DeleteRes struct { - rawRemoved uint64 - availableRemoved uint64 - userRemoved uint64 - sizes []uint64 - availableSizes []uint64 - removedByCnrID map[cid.ID]ObjectCounters + phyCount uint64 + logicCount uint64 + userCount uint64 + phySize uint64 + logicSize uint64 + removedByCnrID map[cid.ID]ObjectCounters } -// AvailableObjectsRemoved returns the number of removed available +// LogicCount returns the number of removed logic // objects. -func (d DeleteRes) AvailableObjectsRemoved() uint64 { - return d.availableRemoved +func (d DeleteRes) LogicCount() uint64 { + return d.logicCount } -func (d DeleteRes) UserObjectsRemoved() uint64 { - return d.userRemoved +func (d DeleteRes) UserCount() uint64 { + return d.userCount } // RemovedByCnrID returns the number of removed objects by container ID. @@ -50,19 +50,19 @@ func (d DeleteRes) RemovedByCnrID() map[cid.ID]ObjectCounters { return d.removedByCnrID } -// RawObjectsRemoved returns the number of removed raw objects. -func (d DeleteRes) RawObjectsRemoved() uint64 { - return d.rawRemoved +// PhyCount returns the number of removed physical objects. +func (d DeleteRes) PhyCount() uint64 { + return d.phyCount } -// RemovedPhysicalObjectSizes returns the sizes of removed physical objects. -func (d DeleteRes) RemovedPhysicalObjectSizes() []uint64 { - return d.sizes +// PhySize returns the size of removed physical objects. +func (d DeleteRes) PhySize() uint64 { + return d.phySize } -// RemovedLogicalObjectSizes returns the sizes of removed logical objects. -func (d DeleteRes) RemovedLogicalObjectSizes() []uint64 { - return d.availableSizes +// LogicSize returns the size of removed logical objects. +func (d DeleteRes) LogicSize() uint64 { + return d.logicSize } // SetAddresses is a Delete option to set the addresses of the objects to delete. @@ -129,8 +129,6 @@ func (db *DB) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { // references of the split objects. func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) { res := DeleteRes{ - sizes: make([]uint64, len(addrs)), - availableSizes: make([]uint64, len(addrs)), removedByCnrID: make(map[cid.ID]ObjectCounters), } refCounter := make(referenceCounter, len(addrs)) @@ -162,22 +160,22 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) } func (db *DB) updateCountersDelete(tx *bbolt.Tx, res DeleteRes) error { - if res.rawRemoved > 0 { - err := db.updateShardObjectCounter(tx, phy, res.rawRemoved, false) + if res.phyCount > 0 { + err := db.updateShardObjectCounter(tx, phy, res.phyCount, false) if err != nil { return fmt.Errorf("could not decrease phy object counter: %w", err) } } - if res.availableRemoved > 0 { - err := db.updateShardObjectCounter(tx, logical, res.availableRemoved, false) + if res.logicCount > 0 { + err := db.updateShardObjectCounter(tx, logical, res.logicCount, false) if err != nil { return fmt.Errorf("could not decrease logical object counter: %w", err) } } - if res.userRemoved > 0 { - err := db.updateShardObjectCounter(tx, user, res.userRemoved, false) + if res.userCount > 0 { + err := db.updateShardObjectCounter(tx, user, res.userCount, false) if err != nil { return fmt.Errorf("could not decrease user object counter: %w", err) } @@ -190,7 +188,7 @@ func (db *DB) updateCountersDelete(tx *bbolt.Tx, res DeleteRes) error { } func applyDeleteSingleResult(r deleteSingleResult, res *DeleteRes, addrs []oid.Address, i int) { - if r.Removed { + if r.Phy { if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { v.Phy++ res.removedByCnrID[addrs[i].Container()] = v @@ -200,11 +198,11 @@ func applyDeleteSingleResult(r deleteSingleResult, res *DeleteRes, addrs []oid.A } } - res.rawRemoved++ - res.sizes[i] = r.Size + res.phyCount++ + res.phySize += r.Size } - if r.Available { + if r.Logic { if v, ok := res.removedByCnrID[addrs[i].Container()]; ok { v.Logic++ res.removedByCnrID[addrs[i].Container()] = v @@ -214,8 +212,8 @@ func applyDeleteSingleResult(r deleteSingleResult, res *DeleteRes, addrs []oid.A } } - res.availableRemoved++ - res.availableSizes[i] = r.Size + res.logicCount++ + res.logicSize += r.Size } if r.User { @@ -228,15 +226,15 @@ func applyDeleteSingleResult(r deleteSingleResult, res *DeleteRes, addrs []oid.A } } - res.userRemoved++ + res.userCount++ } } type deleteSingleResult struct { - Removed bool - Available bool - User bool - Size uint64 + Phy bool + Logic bool + User bool + Size uint64 } // delete removes object indexes from the metabase. Counts the references @@ -302,10 +300,10 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter } return deleteSingleResult{ - Removed: true, - Available: removeAvailableObject, - User: isUserObject && removeAvailableObject, - Size: obj.PayloadSize(), + Phy: true, + Logic: removeAvailableObject, + User: isUserObject && removeAvailableObject, + Size: obj.PayloadSize(), }, nil } diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 21db9a629f..3b2f016730 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -37,17 +37,17 @@ type DeletionInfo struct { // InhumeRes encapsulates results of Inhume operation. type InhumeRes struct { - deletedLockObj []oid.Address - availableInhumed uint64 - userInhumed uint64 - inhumedByCnrID map[cid.ID]ObjectCounters - deletionDetails []DeletionInfo + deletedLockObj []oid.Address + logicInhumed uint64 + userInhumed uint64 + inhumedByCnrID map[cid.ID]ObjectCounters + deletionDetails []DeletionInfo } -// AvailableInhumed return number of available object +// LogicInhumed return number of logic object // that have been inhumed. -func (i InhumeRes) AvailableInhumed() uint64 { - return i.availableInhumed +func (i InhumeRes) LogicInhumed() uint64 { + return i.logicInhumed } func (i InhumeRes) UserInhumed() uint64 { @@ -87,7 +87,7 @@ func (i *InhumeRes) storeDeletionInfo(containerID cid.ID, deletedSize uint64, is CID: containerID, IsUser: isUser, }) - i.availableInhumed++ + i.logicInhumed++ if isUser { i.userInhumed++ } @@ -265,7 +265,7 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes } func (db *DB) applyInhumeResToCounters(tx *bbolt.Tx, res *InhumeRes) error { - if err := db.updateShardObjectCounter(tx, logical, res.AvailableInhumed(), false); err != nil { + if err := db.updateShardObjectCounter(tx, logical, res.LogicInhumed(), false); err != nil { return err } if err := db.updateShardObjectCounter(tx, user, res.UserInhumed(), false); err != nil { diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index 1c510bdb76..44f6c6b487 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -141,16 +141,12 @@ func (s *Shard) deleteFromMetabase(ctx context.Context, addr oid.Address) error if err != nil { return err } - s.decObjectCounterBy(physical, res.RawObjectsRemoved()) - s.decObjectCounterBy(logical, res.AvailableObjectsRemoved()) - s.decObjectCounterBy(user, res.UserObjectsRemoved()) + s.decObjectCounterBy(physical, res.PhyCount()) + s.decObjectCounterBy(logical, res.LogicCount()) + s.decObjectCounterBy(user, res.UserCount()) s.decContainerObjectCounter(res.RemovedByCnrID()) - removedPayload := res.RemovedPhysicalObjectSizes()[0] - logicalRemovedPayload := res.RemovedLogicalObjectSizes()[0] - if logicalRemovedPayload > 0 { - s.addToContainerSize(addr.Container().EncodeToString(), -int64(logicalRemovedPayload)) - } - s.addToPayloadSize(-int64(removedPayload)) + s.addToContainerSize(addr.Container().EncodeToString(), -int64(res.LogicSize())) + s.addToPayloadSize(-int64(res.PhySize())) return nil } diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 0f978f26e3..d82db82b98 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -414,8 +414,8 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) return } - s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeRegular) - s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.gc.metrics.AddInhumedObjectCount(res.LogicInhumed(), objectTypeRegular) + s.decObjectCounterBy(logical, res.LogicInhumed()) s.decObjectCounterBy(user, res.UserInhumed()) s.decContainerObjectCounter(res.InhumedByCnrID()) @@ -629,8 +629,8 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston return } - s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeTombstone) - s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.gc.metrics.AddInhumedObjectCount(res.LogicInhumed(), objectTypeTombstone) + s.decObjectCounterBy(logical, res.LogicInhumed()) s.decObjectCounterBy(user, res.UserInhumed()) s.decContainerObjectCounter(res.InhumedByCnrID()) @@ -677,8 +677,8 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] return } - s.gc.metrics.AddInhumedObjectCount(res.AvailableInhumed(), objectTypeLock) - s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.gc.metrics.AddInhumedObjectCount(res.LogicInhumed(), objectTypeLock) + s.decObjectCounterBy(logical, res.LogicInhumed()) s.decObjectCounterBy(user, res.UserInhumed()) s.decContainerObjectCounter(res.InhumedByCnrID()) diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index 48cfaa98ef..746177c3a4 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -121,7 +121,7 @@ func (s *Shard) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { s.m.RUnlock() - s.decObjectCounterBy(logical, res.AvailableInhumed()) + s.decObjectCounterBy(logical, res.LogicInhumed()) s.decObjectCounterBy(user, res.UserInhumed()) s.decContainerObjectCounter(res.InhumedByCnrID()) From d75e7e9a21bf883870d4c39f8abf325976a32b5f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Dec 2023 18:58:36 +0300 Subject: [PATCH 0245/1413] [#864] engine: Drop container size metric if container deleted Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/container.go | 2 + internal/logs/logs.go | 7 + pkg/local_object_storage/engine/engine.go | 35 ++++- pkg/local_object_storage/engine/inhume.go | 97 ++++++++++++++ pkg/local_object_storage/engine/metrics.go | 1 + pkg/local_object_storage/engine/shards.go | 1 + pkg/local_object_storage/metabase/counter.go | 130 +++++++++++++++++++ pkg/local_object_storage/shard/container.go | 26 ++++ pkg/local_object_storage/shard/control.go | 1 + pkg/local_object_storage/shard/gc.go | 25 ++++ pkg/local_object_storage/shard/shard.go | 23 +++- pkg/metrics/engine.go | 5 + 12 files changed, 347 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 2b9bdd71b7..898a4eef91 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -45,6 +45,8 @@ func initContainerService(_ context.Context, c *cfg) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { containerGRPC.RegisterContainerServiceServer(s, server) }) + + c.cfgObject.cfgLocalStorage.localStorage.SetContainerSource(cnrRdr) } func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc containerCore.Source) (*morphContainerReader, *morphContainerWriter) { diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 6ead837000..3075e66e9b 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -557,4 +557,11 @@ const ( BlobovniczaSavingCountersToMetaFailed = "saving counters to blobovnicza's meta failed" ObjectRemovalFailureExistsInWritecache = "can't remove object: object must be flushed from writecache" FailedToReportStatusToSystemd = "failed to report status to systemd" + ShardGCCollectingExpiredMetricsStarted = "collecting expired metrics started" + ShardGCCollectingExpiredMetricsCompleted = "collecting expired metrics completed" + ShardGCFailedToCollectZeroSizeContainers = "failed to collect zero-size containers" + EngineFailedToCheckContainerAvailability = "failed to check container availability" + EngineFailedToGetContainerSize = "failed to get container size" + EngineFailedToDeleteContainerSize = "failed to delete container size" + EngineInterruptProcessingZeroSizeContainers = "interrupt processing zero-size containers" ) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 026a7c336f..e03a08abc7 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -7,12 +7,14 @@ import ( "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" ) @@ -218,14 +220,18 @@ type cfg struct { lowMem bool rebuildWorkersCount uint32 + + containerSource atomic.Pointer[containerSource] } func defaultCfg() *cfg { - return &cfg{ + res := &cfg{ log: &logger.Logger{Logger: zap.L()}, shardPoolSize: 20, rebuildWorkersCount: 100, } + res.containerSource.Store(&containerSource{}) + return res } // New creates, initializes and returns new StorageEngine instance. @@ -288,3 +294,30 @@ func WithRebuildWorkersCount(count uint32) Option { c.rebuildWorkersCount = count } } + +// SetContainerSource sets container source. +func (e *StorageEngine) SetContainerSource(cs container.Source) { + e.containerSource.Store(&containerSource{cs: cs}) +} + +type containerSource struct { + cs container.Source +} + +func (s *containerSource) IsContainerAvailable(ctx context.Context, id cid.ID) (bool, error) { + select { + case <-ctx.Done(): + return false, ctx.Err() + default: + } + + if s == nil || s.cs == nil { + return true, nil + } + + wasRemoved, err := container.WasRemoved(s.cs, id) + if err != nil { + return false, err + } + return !wasRemoved, nil +} diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 293746f70c..6750adec25 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" @@ -259,3 +260,99 @@ func (e *StorageEngine) processDeletedLocks(ctx context.Context, lockers []oid.A } }) } + +func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid.ID) { + if len(ids) == 0 { + return + } + + idMap, err := e.selectNonExistedIDs(ctx, ids) + if err != nil { + return + } + + if len(idMap) == 0 { + return + } + + var failed bool + var prm shard.ContainerSizePrm + e.iterateOverUnsortedShards(func(sh hashedShard) bool { + select { + case <-ctx.Done(): + e.log.Info(logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(ctx.Err())) + failed = true + return true + default: + } + + var drop []cid.ID + for id := range idMap { + prm.SetContainerID(id) + s, err := sh.ContainerSize(prm) + if err != nil { + e.log.Warn(logs.EngineFailedToGetContainerSize, zap.Stringer("container_id", id), zap.Error(err)) + failed = true + return true + } + if s.Size() > 0 { + drop = append(drop, id) + } + } + for _, id := range drop { + delete(idMap, id) + } + + return len(idMap) == 0 + }) + + if failed || len(idMap) == 0 { + return + } + + e.iterateOverUnsortedShards(func(sh hashedShard) bool { + select { + case <-ctx.Done(): + e.log.Info(logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(ctx.Err())) + failed = true + return true + default: + } + + for id := range idMap { + if err := sh.DeleteContainerSize(ctx, id); err != nil { + e.log.Warn(logs.EngineFailedToDeleteContainerSize, zap.Stringer("container_id", id), zap.Error(err)) + failed = true + return true + } + } + + return false + }) + + if failed { + return + } + + for id := range idMap { + e.metrics.DeleteContainerSize(id.EncodeToString()) + } +} + +func (e *StorageEngine) selectNonExistedIDs(ctx context.Context, ids []cid.ID) (map[cid.ID]struct{}, error) { + cs := e.containerSource.Load() + + idMap := make(map[cid.ID]struct{}) + for _, id := range ids { + isAvailable, err := cs.IsContainerAvailable(ctx, id) + if err != nil { + e.log.Warn(logs.EngineFailedToCheckContainerAvailability, zap.Stringer("container_id", id), zap.Error(err)) + return nil, err + } + if isAvailable { + continue + } + idMap[id] = struct{}{} + } + return idMap, nil +} diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index 363d098f61..e4cc504fa6 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -16,6 +16,7 @@ type MetricRegister interface { SetMode(shardID string, mode mode.Mode) AddToContainerSize(cnrID string, size int64) + DeleteContainerSize(cnrID string) AddToPayloadCounter(shardID string, size int64) IncErrorCounter(shardID string) ClearErrorCounter(shardID string) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 7e3e85e81c..cb3a4eca51 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -119,6 +119,7 @@ func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (* shard.WithDeletedLockCallback(e.processDeletedLocks), shard.WithReportErrorFunc(e.reportShardErrorBackground), shard.WithRebuildWorkerLimiter(e.rebuildLimiter), + shard.WithZeroSizeCallback(e.processZeroSizeContainers), )...) if err := sh.UpdateID(ctx); err != nil { diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index 581df7a59f..271e78fe4b 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -14,6 +14,8 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" ) var ( @@ -480,3 +482,131 @@ func IsUserObject(obj *objectSDK.Object) bool { (obj.SplitID() == nil || (hasParentID && len(obj.Children()) == 0)) } + +// ZeroSizeContainers returns containers with size = 0. +func (db *DB) ZeroSizeContainers(ctx context.Context) ([]cid.ID, error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("ZeroSizeContainers", time.Since(startedAt), success) + }() + + ctx, span := tracing.StartSpanFromContext(ctx, "metabase.ZeroSizeContainers") + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + var result []cid.ID + lastKey := make([]byte, cidSize) + + for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + + completed, err := db.containerSizesNextBatch(lastKey, func(contID cid.ID, size uint64) { + if size == 0 { + result = append(result, contID) + } + }) + if err != nil { + return nil, err + } + if completed { + break + } + } + + success = true + return result, nil +} + +func (db *DB) containerSizesNextBatch(lastKey []byte, f func(cid.ID, uint64)) (bool, error) { + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return false, ErrDegradedMode + } + + counter := 0 + const batchSize = 1000 + + err := db.boltDB.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(containerVolumeBucketName) + c := b.Cursor() + var key, value []byte + for key, value = c.Seek(lastKey); key != nil; key, value = c.Next() { + if bytes.Equal(lastKey, key) { + continue + } + copy(lastKey, key) + + size := parseContainerSize(value) + var id cid.ID + if err := id.Decode(key); err != nil { + return err + } + f(id, size) + + counter++ + if counter == batchSize { + break + } + } + + if counter < batchSize { + return ErrInterruptIterator + } + return nil + }) + if err != nil { + if errors.Is(err, ErrInterruptIterator) { + return true, nil + } + return false, metaerr.Wrap(err) + } + return false, nil +} + +func (db *DB) DeleteContainerSize(ctx context.Context, id cid.ID) error { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("DeleteContainerSize", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "metabase.DeleteContainerSize", + trace.WithAttributes( + attribute.Stringer("container_id", id), + )) + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return ErrDegradedMode + } + + if db.mode.ReadOnly() { + return ErrReadOnlyMode + } + + err := db.boltDB.Update(func(tx *bbolt.Tx) error { + b := tx.Bucket(containerVolumeBucketName) + + key := make([]byte, cidSize) + id.Encode(key) + return b.Delete(key) + }) + success = err == nil + return metaerr.Wrap(err) +} diff --git a/pkg/local_object_storage/shard/container.go b/pkg/local_object_storage/shard/container.go index 24090e8d8c..8568854863 100644 --- a/pkg/local_object_storage/shard/container.go +++ b/pkg/local_object_storage/shard/container.go @@ -1,9 +1,13 @@ package shard import ( + "context" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" ) type ContainerSizePrm struct { @@ -39,3 +43,25 @@ func (s *Shard) ContainerSize(prm ContainerSizePrm) (ContainerSizeRes, error) { size: size, }, nil } + +func (s *Shard) DeleteContainerSize(ctx context.Context, id cid.ID) error { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.DeleteContainerSize", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.Stringer("container_id", id), + )) + defer span.End() + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.ReadOnly() { + return ErrReadOnlyMode + } + + if s.info.Mode.NoMetabase() { + return ErrDegradedMode + } + + return s.metaBase.DeleteContainerSize(ctx, id) +} diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index f103ebc2ba..574bc1430e 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -155,6 +155,7 @@ func (s *Shard) Init(ctx context.Context) error { s.collectExpiredLocks, s.collectExpiredObjects, s.collectExpiredTombstones, + s.collectExpiredMetrics, }, }, }, diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index d82db82b98..3017dce1ff 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" @@ -726,3 +727,27 @@ func (s *Shard) HandleDeletedLocks(lockers []oid.Address) { func (s *Shard) NotificationChannel() chan<- Event { return s.gc.eventChan } + +func (s *Shard) collectExpiredMetrics(ctx context.Context, e Event) { + ctx, span := tracing.StartSpanFromContext(ctx, "shard.collectExpiredMetrics") + defer span.End() + + epoch := e.(newEpoch).epoch + + s.log.Debug(logs.ShardGCCollectingExpiredMetricsStarted, zap.Uint64("epoch", epoch)) + defer s.log.Debug(logs.ShardGCCollectingExpiredMetricsCompleted, zap.Uint64("epoch", epoch)) + + s.collectExpiredContainerSizeMetrics(ctx, epoch) +} + +func (s *Shard) collectExpiredContainerSizeMetrics(ctx context.Context, epoch uint64) { + ids, err := s.metaBase.ZeroSizeContainers(ctx) + if err != nil { + s.log.Warn(logs.ShardGCFailedToCollectZeroSizeContainers, zap.Uint64("epoch", epoch), zap.Error(err)) + return + } + if len(ids) == 0 { + return + } + s.zeroSizeContainersCallback(ctx, ids) +} diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 641b487edc..a83445cfea 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -53,6 +53,9 @@ type ExpiredObjectsCallback func(context.Context, uint64, []oid.Address) // DeletedLockCallback is a callback handling list of deleted LOCK objects. type DeletedLockCallback func(context.Context, []oid.Address) +// ZeroSizeContainersCallback is a callback hanfling list of zero-size containers. +type ZeroSizeContainersCallback func(context.Context, []cid.ID) + // MetricsWriter is an interface that must store shard's metrics. type MetricsWriter interface { // SetObjectCounter must set object counter taking into account object type. @@ -118,6 +121,8 @@ type cfg struct { deletedLockCallBack DeletedLockCallback + zeroSizeContainersCallback ZeroSizeContainersCallback + tsSource TombstoneSource metricsWriter MetricsWriter @@ -129,11 +134,12 @@ type cfg struct { func defaultCfg() *cfg { return &cfg{ - rmBatchSize: 100, - log: &logger.Logger{Logger: zap.L()}, - gcCfg: defaultGCCfg(), - reportErrorFunc: func(string, string, error) {}, - rebuildLimiter: &noopRebuildLimiter{}, + rmBatchSize: 100, + log: &logger.Logger{Logger: zap.L()}, + gcCfg: defaultGCCfg(), + reportErrorFunc: func(string, string, error) {}, + rebuildLimiter: &noopRebuildLimiter{}, + zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, } } @@ -363,6 +369,13 @@ func WithRebuildWorkerLimiter(l RebuildWorkerLimiter) Option { } } +// WithZeroSizeCallback returns option to set zero-size containers callback. +func WithZeroSizeCallback(cb ZeroSizeContainersCallback) Option { + return func(c *cfg) { + c.zeroSizeContainersCallback = cb + } +} + func (s *Shard) fillInfo() { s.cfg.info.MetaBaseInfo = s.metaBase.DumpInfo() s.cfg.info.BlobStorInfo = s.blobStor.DumpInfo() diff --git a/pkg/metrics/engine.go b/pkg/metrics/engine.go index 609c30f97d..80e912048d 100644 --- a/pkg/metrics/engine.go +++ b/pkg/metrics/engine.go @@ -11,6 +11,7 @@ import ( type EngineMetrics interface { AddMethodDuration(method string, d time.Duration) AddToContainerSize(cnrID string, size int64) + DeleteContainerSize(cnrID string) IncErrorCounter(shardID string) ClearErrorCounter(shardID string) DeleteShardMetrics(shardID string) @@ -79,6 +80,10 @@ func (m *engineMetrics) AddToContainerSize(cnrID string, size int64) { m.containerSize.With(prometheus.Labels{containerIDLabelKey: cnrID}).Add(float64(size)) } +func (m *engineMetrics) DeleteContainerSize(cnrID string) { + m.containerSize.DeletePartialMatch(prometheus.Labels{containerIDLabelKey: cnrID}) +} + func (m *engineMetrics) AddToPayloadCounter(shardID string, size int64) { m.payloadSize.With(prometheus.Labels{shardIDLabel: shardID}).Add(float64(size)) } From 4b8b4da6818ecce7700dd432f8a6ed5d8be86106 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Dec 2023 18:23:12 +0300 Subject: [PATCH 0246/1413] [#864] engine: Drop container count metric if container removed Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 3 + pkg/local_object_storage/engine/inhume.go | 82 ++++++++++- pkg/local_object_storage/engine/metrics.go | 1 + pkg/local_object_storage/engine/shards.go | 1 + pkg/local_object_storage/metabase/counter.go | 131 +++++++++++++++++- .../metabase/counter_test.go | 18 +-- pkg/local_object_storage/shard/container.go | 59 ++++++++ pkg/local_object_storage/shard/gc.go | 13 ++ .../shard/metrics_test.go | 6 +- pkg/local_object_storage/shard/shard.go | 29 ++-- pkg/metrics/engine.go | 5 + 11 files changed, 310 insertions(+), 38 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 3075e66e9b..420c6612a5 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -560,8 +560,11 @@ const ( ShardGCCollectingExpiredMetricsStarted = "collecting expired metrics started" ShardGCCollectingExpiredMetricsCompleted = "collecting expired metrics completed" ShardGCFailedToCollectZeroSizeContainers = "failed to collect zero-size containers" + ShardGCFailedToCollectZeroCountContainers = "failed to collect zero-count containers" EngineFailedToCheckContainerAvailability = "failed to check container availability" EngineFailedToGetContainerSize = "failed to get container size" EngineFailedToDeleteContainerSize = "failed to delete container size" EngineInterruptProcessingZeroSizeContainers = "interrupt processing zero-size containers" + EngineInterruptProcessingZeroCountContainers = "interrupt processing zero-count containers" + EngineFailedToGetContainerCounters = "failed to get container counters" ) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 6750adec25..fc6ee24301 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -266,7 +266,7 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid return } - idMap, err := e.selectNonExistedIDs(ctx, ids) + idMap, err := e.selectNonExistentIDs(ctx, ids) if err != nil { return } @@ -339,7 +339,85 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid } } -func (e *StorageEngine) selectNonExistedIDs(ctx context.Context, ids []cid.ID) (map[cid.ID]struct{}, error) { +func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []cid.ID) { + if len(ids) == 0 { + return + } + + idMap, err := e.selectNonExistentIDs(ctx, ids) + if err != nil { + return + } + + if len(idMap) == 0 { + return + } + + var failed bool + var prm shard.ContainerCountPrm + e.iterateOverUnsortedShards(func(sh hashedShard) bool { + select { + case <-ctx.Done(): + e.log.Info(logs.EngineInterruptProcessingZeroCountContainers, zap.Error(ctx.Err())) + failed = true + return true + default: + } + + var drop []cid.ID + for id := range idMap { + prm.ContainerID = id + s, err := sh.ContainerCount(ctx, prm) + if err != nil { + e.log.Warn(logs.EngineFailedToGetContainerCounters, zap.Stringer("container_id", id), zap.Error(err)) + failed = true + return true + } + if s.User > 0 || s.Logic > 0 || s.Phy > 0 { + drop = append(drop, id) + } + } + for _, id := range drop { + delete(idMap, id) + } + + return len(idMap) == 0 + }) + + if failed || len(idMap) == 0 { + return + } + + e.iterateOverUnsortedShards(func(sh hashedShard) bool { + select { + case <-ctx.Done(): + e.log.Info(logs.EngineInterruptProcessingZeroCountContainers, zap.Error(ctx.Err())) + failed = true + return true + default: + } + + for id := range idMap { + if err := sh.DeleteContainerSize(ctx, id); err != nil { + e.log.Warn(logs.EngineFailedToDeleteContainerSize, zap.Stringer("container_id", id), zap.Error(err)) + failed = true + return true + } + } + + return false + }) + + if failed { + return + } + + for id := range idMap { + e.metrics.DeleteContainerCount(id.EncodeToString()) + } +} + +func (e *StorageEngine) selectNonExistentIDs(ctx context.Context, ids []cid.ID) (map[cid.ID]struct{}, error) { cs := e.containerSource.Load() idMap := make(map[cid.ID]struct{}) diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index e4cc504fa6..e4117bb1af 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -17,6 +17,7 @@ type MetricRegister interface { AddToContainerSize(cnrID string, size int64) DeleteContainerSize(cnrID string) + DeleteContainerCount(cnrID string) AddToPayloadCounter(shardID string, size int64) IncErrorCounter(shardID string) ClearErrorCounter(shardID string) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index cb3a4eca51..0455471e22 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -120,6 +120,7 @@ func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (* shard.WithReportErrorFunc(e.reportShardErrorBackground), shard.WithRebuildWorkerLimiter(e.rebuildLimiter), shard.WithZeroSizeCallback(e.processZeroSizeContainers), + shard.WithZeroCountCallback(e.processZeroCountContainers), )...) if err := sh.UpdateID(ctx); err != nil { diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index 271e78fe4b..915fbd957d 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -120,7 +120,9 @@ func (db *DB) ContainerCounters(ctx context.Context) (ContainerCounters, error) default: } - completed, err := db.containerCountersNextBatch(lastKey, &cc) + completed, err := db.containerCountersNextBatch(lastKey, func(id cid.ID, entity ObjectCounters) { + cc.Counts[id] = entity + }) if err != nil { return cc, err } @@ -133,7 +135,7 @@ func (db *DB) ContainerCounters(ctx context.Context) (ContainerCounters, error) return cc, nil } -func (db *DB) containerCountersNextBatch(lastKey []byte, cc *ContainerCounters) (bool, error) { +func (db *DB) containerCountersNextBatch(lastKey []byte, f func(id cid.ID, entity ObjectCounters)) (bool, error) { db.modeMtx.RLock() defer db.modeMtx.RUnlock() @@ -165,7 +167,7 @@ func (db *DB) containerCountersNextBatch(lastKey []byte, cc *ContainerCounters) if err != nil { return err } - cc.Counts[cnrID] = ent + f(cnrID, ent) counter++ if counter == batchSize { @@ -187,6 +189,43 @@ func (db *DB) containerCountersNextBatch(lastKey []byte, cc *ContainerCounters) return false, nil } +func (db *DB) ContainerCount(ctx context.Context, id cid.ID) (ObjectCounters, error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("ContainerCount", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "metabase.ContainerCount") + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return ObjectCounters{}, ErrDegradedMode + } + + var result ObjectCounters + + err := db.boltDB.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(containerCounterBucketName) + key := make([]byte, cidSize) + id.Encode(key) + v := b.Get(key) + if v == nil { + return nil + } + var err error + result, err = parseContainerCounterValue(v) + return err + }) + + return result, metaerr.Wrap(err) +} + func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID, isUserObject bool) error { if err := db.updateShardObjectCounter(tx, phy, 1, true); err != nil { return fmt.Errorf("could not increase phy object counter: %w", err) @@ -270,9 +309,6 @@ func (*DB) editContainerCounterValue(b *bbolt.Bucket, key []byte, delta ObjectCo entity.Phy = nextValue(entity.Phy, delta.Phy, inc) entity.Logic = nextValue(entity.Logic, delta.Logic, inc) entity.User = nextValue(entity.User, delta.User, inc) - if entity.IsZero() { - return b.Delete(key) - } value := containerCounterValue(entity) return b.Put(key, value) } @@ -610,3 +646,86 @@ func (db *DB) DeleteContainerSize(ctx context.Context, id cid.ID) error { success = err == nil return metaerr.Wrap(err) } + +// ZeroCountContainers returns containers with objects count = 0 in metabase. +func (db *DB) ZeroCountContainers(ctx context.Context) ([]cid.ID, error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("ZeroCountContainers", time.Since(startedAt), success) + }() + + ctx, span := tracing.StartSpanFromContext(ctx, "metabase.ZeroCountContainers") + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return nil, ErrDegradedMode + } + + var result []cid.ID + + lastKey := make([]byte, cidSize) + for { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + + completed, err := db.containerCountersNextBatch(lastKey, func(id cid.ID, entity ObjectCounters) { + if entity.IsZero() { + result = append(result, id) + } + }) + if err != nil { + return nil, metaerr.Wrap(err) + } + if completed { + break + } + } + success = true + return result, nil +} + +func (db *DB) DeleteContainerCount(ctx context.Context, id cid.ID) error { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("DeleteContainerCount", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "metabase.DeleteContainerCount", + trace.WithAttributes( + attribute.Stringer("container_id", id), + )) + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return ErrDegradedMode + } + + if db.mode.ReadOnly() { + return ErrReadOnlyMode + } + + err := db.boltDB.Update(func(tx *bbolt.Tx) error { + b := tx.Bucket(containerCounterBucketName) + + key := make([]byte, cidSize) + id.Encode(key) + return b.Delete(key) + }) + success = err == nil + return metaerr.Wrap(err) +} diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 2f40daaaee..4b7b565b3e 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -105,11 +105,7 @@ func TestCounters(t *testing.T) { v.Phy-- v.Logic-- v.User-- - if v.IsZero() { - delete(exp, cnrID) - } else { - exp[cnrID] = v - } + exp[cnrID] = v } cc, err := db.ContainerCounters(context.Background()) @@ -428,11 +424,7 @@ func TestCounters_Expired(t *testing.T) { if v, ok := exp[oo[0].Container()]; ok { v.Phy-- - if v.IsZero() { - delete(exp, oo[0].Container()) - } else { - exp[oo[0].Container()] = v - } + exp[oo[0].Container()] = v } oo = oo[1:] @@ -463,11 +455,7 @@ func TestCounters_Expired(t *testing.T) { v.Phy-- v.Logic-- v.User-- - if v.IsZero() { - delete(exp, oo[0].Container()) - } else { - exp[oo[0].Container()] = v - } + exp[oo[0].Container()] = v } oo = oo[1:] diff --git a/pkg/local_object_storage/shard/container.go b/pkg/local_object_storage/shard/container.go index 8568854863..364649b50c 100644 --- a/pkg/local_object_storage/shard/container.go +++ b/pkg/local_object_storage/shard/container.go @@ -44,6 +44,43 @@ func (s *Shard) ContainerSize(prm ContainerSizePrm) (ContainerSizeRes, error) { }, nil } +type ContainerCountPrm struct { + ContainerID cid.ID +} + +type ContainerCountRes struct { + Phy uint64 + Logic uint64 + User uint64 +} + +func (s *Shard) ContainerCount(ctx context.Context, prm ContainerCountPrm) (ContainerCountRes, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.ContainerCount", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.Stringer("container_id", prm.ContainerID), + )) + defer span.End() + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { + return ContainerCountRes{}, ErrDegradedMode + } + + counters, err := s.metaBase.ContainerCount(ctx, prm.ContainerID) + if err != nil { + return ContainerCountRes{}, fmt.Errorf("could not get container counters: %w", err) + } + + return ContainerCountRes{ + Phy: counters.Phy, + Logic: counters.Logic, + User: counters.User, + }, nil +} + func (s *Shard) DeleteContainerSize(ctx context.Context, id cid.ID) error { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.DeleteContainerSize", trace.WithAttributes( @@ -65,3 +102,25 @@ func (s *Shard) DeleteContainerSize(ctx context.Context, id cid.ID) error { return s.metaBase.DeleteContainerSize(ctx, id) } + +func (s *Shard) DeleteContainerCount(ctx context.Context, id cid.ID) error { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.DeleteContainerCount", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.Stringer("container_id", id), + )) + defer span.End() + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.ReadOnly() { + return ErrReadOnlyMode + } + + if s.info.Mode.NoMetabase() { + return ErrDegradedMode + } + + return s.metaBase.DeleteContainerCount(ctx, id) +} diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 3017dce1ff..bfd1f1b112 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -738,6 +738,7 @@ func (s *Shard) collectExpiredMetrics(ctx context.Context, e Event) { defer s.log.Debug(logs.ShardGCCollectingExpiredMetricsCompleted, zap.Uint64("epoch", epoch)) s.collectExpiredContainerSizeMetrics(ctx, epoch) + s.collectExpiredContainerCountMetrics(ctx, epoch) } func (s *Shard) collectExpiredContainerSizeMetrics(ctx context.Context, epoch uint64) { @@ -751,3 +752,15 @@ func (s *Shard) collectExpiredContainerSizeMetrics(ctx context.Context, epoch ui } s.zeroSizeContainersCallback(ctx, ids) } + +func (s *Shard) collectExpiredContainerCountMetrics(ctx context.Context, epoch uint64) { + ids, err := s.metaBase.ZeroCountContainers(ctx) + if err != nil { + s.log.Warn(logs.ShardGCFailedToCollectZeroCountContainers, zap.Uint64("epoch", epoch), zap.Error(err)) + return + } + if len(ids) == 0 { + return + } + s.zeroCountContainersCallback(ctx, ids) +} diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index f59565cb35..9c81c747d9 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -336,11 +336,7 @@ func TestCounters(t *testing.T) { v.Logic-- v.Phy-- v.User-- - if v.IsZero() { - delete(expected, cnr) - } else { - expected[cnr] = v - } + expected[cnr] = v } } require.Equal(t, expectedLogicalSizes, mm.containerSizes()) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index a83445cfea..13f7f689b3 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -53,8 +53,8 @@ type ExpiredObjectsCallback func(context.Context, uint64, []oid.Address) // DeletedLockCallback is a callback handling list of deleted LOCK objects. type DeletedLockCallback func(context.Context, []oid.Address) -// ZeroSizeContainersCallback is a callback hanfling list of zero-size containers. -type ZeroSizeContainersCallback func(context.Context, []cid.ID) +// EmptyContainersCallback is a callback hanfling list of zero-size and zero-count containers. +type EmptyContainersCallback func(context.Context, []cid.ID) // MetricsWriter is an interface that must store shard's metrics. type MetricsWriter interface { @@ -121,7 +121,8 @@ type cfg struct { deletedLockCallBack DeletedLockCallback - zeroSizeContainersCallback ZeroSizeContainersCallback + zeroSizeContainersCallback EmptyContainersCallback + zeroCountContainersCallback EmptyContainersCallback tsSource TombstoneSource @@ -134,12 +135,13 @@ type cfg struct { func defaultCfg() *cfg { return &cfg{ - rmBatchSize: 100, - log: &logger.Logger{Logger: zap.L()}, - gcCfg: defaultGCCfg(), - reportErrorFunc: func(string, string, error) {}, - rebuildLimiter: &noopRebuildLimiter{}, - zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, + rmBatchSize: 100, + log: &logger.Logger{Logger: zap.L()}, + gcCfg: defaultGCCfg(), + reportErrorFunc: func(string, string, error) {}, + rebuildLimiter: &noopRebuildLimiter{}, + zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, + zeroCountContainersCallback: func(context.Context, []cid.ID) {}, } } @@ -370,12 +372,19 @@ func WithRebuildWorkerLimiter(l RebuildWorkerLimiter) Option { } // WithZeroSizeCallback returns option to set zero-size containers callback. -func WithZeroSizeCallback(cb ZeroSizeContainersCallback) Option { +func WithZeroSizeCallback(cb EmptyContainersCallback) Option { return func(c *cfg) { c.zeroSizeContainersCallback = cb } } +// WithZeroCountCallback returns option to set zero-count containers callback. +func WithZeroCountCallback(cb EmptyContainersCallback) Option { + return func(c *cfg) { + c.zeroCountContainersCallback = cb + } +} + func (s *Shard) fillInfo() { s.cfg.info.MetaBaseInfo = s.metaBase.DumpInfo() s.cfg.info.BlobStorInfo = s.blobStor.DumpInfo() diff --git a/pkg/metrics/engine.go b/pkg/metrics/engine.go index 80e912048d..4cc5424703 100644 --- a/pkg/metrics/engine.go +++ b/pkg/metrics/engine.go @@ -12,6 +12,7 @@ type EngineMetrics interface { AddMethodDuration(method string, d time.Duration) AddToContainerSize(cnrID string, size int64) DeleteContainerSize(cnrID string) + DeleteContainerCount(cnrID string) IncErrorCounter(shardID string) ClearErrorCounter(shardID string) DeleteShardMetrics(shardID string) @@ -84,6 +85,10 @@ func (m *engineMetrics) DeleteContainerSize(cnrID string) { m.containerSize.DeletePartialMatch(prometheus.Labels{containerIDLabelKey: cnrID}) } +func (m *engineMetrics) DeleteContainerCount(cnrID string) { + m.contObjCounter.DeletePartialMatch(prometheus.Labels{containerIDLabelKey: cnrID}) +} + func (m *engineMetrics) AddToPayloadCounter(shardID string, size int64) { m.payloadSize.With(prometheus.Labels{shardIDLabel: shardID}).Add(float64(size)) } From 79bebe4a683ceab420742577a46bfc536bc2e118 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 9 Jan 2024 18:34:25 +0300 Subject: [PATCH 0247/1413] [#884] cli: Fix error message for undefined endpoint Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/internal/client/sdk.go | 4 ++++ pkg/network/address.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/cmd/frostfs-cli/internal/client/sdk.go b/cmd/frostfs-cli/internal/client/sdk.go index b3e04e5f5f..f7c48b8718 100644 --- a/cmd/frostfs-cli/internal/client/sdk.go +++ b/cmd/frostfs-cli/internal/client/sdk.go @@ -34,6 +34,10 @@ func GetSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag func getSDKClientByFlag(cmd *cobra.Command, key *ecdsa.PrivateKey, endpointFlag string) (*client.Client, error) { var addr network.Address + if len(viper.GetString(endpointFlag)) == 0 { + return nil, fmt.Errorf("%s is not defined", endpointFlag) + } + err := addr.FromString(viper.GetString(endpointFlag)) if err != nil { return nil, fmt.Errorf("%v: %w", errInvalidEndpoint, err) diff --git a/pkg/network/address.go b/pkg/network/address.go index 8ad285725d..aeb6478853 100644 --- a/pkg/network/address.go +++ b/pkg/network/address.go @@ -88,6 +88,10 @@ func (a *Address) FromString(s string) error { // multiaddrStringFromHostAddr converts "localhost:8080" to "/dns4/localhost/tcp/8080". func multiaddrStringFromHostAddr(host string) (string, error) { + if len(host) == 0 { + return "", fmt.Errorf("host is empty") + } + endpoint, port, err := net.SplitHostPort(host) if err != nil { return "", err From 5c0a736a25ed2e30f19a1ecd86796390277b6a50 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 10 Jan 2024 18:37:54 +0300 Subject: [PATCH 0248/1413] [#899] containerSvc: Fix invalid session token type Signed-off-by: Dmitrii Stepanov --- pkg/services/container/ape.go | 12 +++++++----- pkg/services/container/ape_test.go | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index e1ef43c631..36edf45161 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -35,6 +35,8 @@ var ( errInvalidSessionTokenOwner = errors.New("malformed request: invalid session token owner") errEmptyBodySignature = errors.New("malformed request: empty body signature") errMissingOwnerID = errors.New("malformed request: missing owner ID") + + undefinedContainerID = cid.ID{} ) type ir interface { @@ -196,7 +198,7 @@ func (ac *apeChecker) getRoleWithoutContainerID(oID *refs.OwnerID, mh *session.R return "", nil, err } - actor, pk, err := ac.getActorAndPublicKey(mh, vh, cid.ID{}) + actor, pk, err := ac.getActorAndPublicKey(mh, vh, undefinedContainerID) if err != nil { return "", nil, err } @@ -403,7 +405,7 @@ func (ac *apeChecker) getActorAndPKFromSignature(vh *session.RequestVerification return &userID, key, nil } -func (ac *apeChecker) getSessionToken(mh *session.RequestMetaHeader) (*sessionSDK.Object, error) { +func (ac *apeChecker) getSessionToken(mh *session.RequestMetaHeader) (*sessionSDK.Container, error) { for mh.GetOrigin() != nil { mh = mh.GetOrigin() } @@ -412,7 +414,7 @@ func (ac *apeChecker) getSessionToken(mh *session.RequestMetaHeader) (*sessionSD return nil, nil } - var tok sessionSDK.Object + var tok sessionSDK.Container err := tok.ReadFromV2(*st) if err != nil { return nil, fmt.Errorf("invalid session token: %w", err) @@ -421,8 +423,8 @@ func (ac *apeChecker) getSessionToken(mh *session.RequestMetaHeader) (*sessionSD return &tok, nil } -func (ac *apeChecker) getActorAndPKFromSessionToken(st *sessionSDK.Object, cnrID cid.ID) (*user.ID, *keys.PublicKey, error) { - if !st.AssertContainer(cnrID) { +func (ac *apeChecker) getActorAndPKFromSessionToken(st *sessionSDK.Container, cnrID cid.ID) (*user.ID, *keys.PublicKey, error) { + if cnrID != undefinedContainerID && !st.AppliedTo(cnrID) { return nil, nil, errSessionContainerMissmatch } if !st.VerifySignature() { diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index b61e68eb57..f4dfbe50fa 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -253,8 +253,8 @@ func testDenyGetContainerEACLForIRSessionToken(t *testing.T) { sessionPK, err := keys.NewPrivateKey() require.NoError(t, err) - sToken := sessiontest.ObjectSigned() - sToken.BindContainer(contID) + sToken := sessiontest.ContainerSigned() + sToken.ApplyOnlyTo(contID) require.NoError(t, sToken.Sign(sessionPK.PrivateKey)) var sTokenV2 session.Token sToken.WriteToV2(&sTokenV2) @@ -325,8 +325,8 @@ func testDenyPutContainerForOthersSessionToken(t *testing.T) { sessionPK, err := keys.NewPrivateKey() require.NoError(t, err) - sToken := sessiontest.ObjectSigned() - sToken.BindContainer(cid.ID{}) + sToken := sessiontest.ContainerSigned() + sToken.ApplyOnlyTo(cid.ID{}) require.NoError(t, sToken.Sign(sessionPK.PrivateKey)) var sTokenV2 session.Token sToken.WriteToV2(&sTokenV2) From c19396d203449c56271ff43d85f0a0b361f806d2 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Thu, 21 Dec 2023 15:05:45 +0300 Subject: [PATCH 0249/1413] [#885] control: Make chain id bytes in grpc Signed-off-by: Denis Kirillov --- cmd/frostfs-cli/modules/control/get_rule.go | 2 +- .../modules/control/remove_rule.go | 2 +- pkg/services/control/ir/service_grpc.pb.go | 25 ++++----- pkg/services/control/server/policy_engine.go | 4 +- pkg/services/control/service.pb.go | 24 ++++----- pkg/services/control/service.proto | 6 +-- pkg/services/control/service_frostfs.pb.go | 12 ++--- pkg/services/tree/service_grpc.pb.go | 54 +++++++------------ 8 files changed, 53 insertions(+), 76 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 6d86d5d743..2bb6a7da25 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -38,7 +38,7 @@ func getRule(cmd *cobra.Command, _ []string) { Name: cidStr, Type: control.ChainTarget_CONTAINER, }, - ChainId: chainID, + ChainId: []byte(chainID), }, } diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index 929d0b1a1c..60e5376a14 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -41,7 +41,7 @@ func removeRule(cmd *cobra.Command, _ []string) { Name: cidStr, Type: control.ChainTarget_CONTAINER, }, - ChainId: chainID, + ChainId: []byte(chainID), }, } diff --git a/pkg/services/control/ir/service_grpc.pb.go b/pkg/services/control/ir/service_grpc.pb.go index 724149c441..0f93c0e190 100644 --- a/pkg/services/control/ir/service_grpc.pb.go +++ b/pkg/services/control/ir/service_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.2.0 // - protoc v4.25.0 // source: pkg/services/control/ir/service.proto @@ -18,13 +18,6 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 -const ( - ControlService_HealthCheck_FullMethodName = "/ircontrol.ControlService/HealthCheck" - ControlService_TickEpoch_FullMethodName = "/ircontrol.ControlService/TickEpoch" - ControlService_RemoveNode_FullMethodName = "/ircontrol.ControlService/RemoveNode" - ControlService_RemoveContainer_FullMethodName = "/ircontrol.ControlService/RemoveContainer" -) - // ControlServiceClient is the client API for ControlService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -49,7 +42,7 @@ func NewControlServiceClient(cc grpc.ClientConnInterface) ControlServiceClient { func (c *controlServiceClient) HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) { out := new(HealthCheckResponse) - err := c.cc.Invoke(ctx, ControlService_HealthCheck_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ircontrol.ControlService/HealthCheck", in, out, opts...) if err != nil { return nil, err } @@ -58,7 +51,7 @@ func (c *controlServiceClient) HealthCheck(ctx context.Context, in *HealthCheckR func (c *controlServiceClient) TickEpoch(ctx context.Context, in *TickEpochRequest, opts ...grpc.CallOption) (*TickEpochResponse, error) { out := new(TickEpochResponse) - err := c.cc.Invoke(ctx, ControlService_TickEpoch_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ircontrol.ControlService/TickEpoch", in, out, opts...) if err != nil { return nil, err } @@ -67,7 +60,7 @@ func (c *controlServiceClient) TickEpoch(ctx context.Context, in *TickEpochReque func (c *controlServiceClient) RemoveNode(ctx context.Context, in *RemoveNodeRequest, opts ...grpc.CallOption) (*RemoveNodeResponse, error) { out := new(RemoveNodeResponse) - err := c.cc.Invoke(ctx, ControlService_RemoveNode_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ircontrol.ControlService/RemoveNode", in, out, opts...) if err != nil { return nil, err } @@ -76,7 +69,7 @@ func (c *controlServiceClient) RemoveNode(ctx context.Context, in *RemoveNodeReq func (c *controlServiceClient) RemoveContainer(ctx context.Context, in *RemoveContainerRequest, opts ...grpc.CallOption) (*RemoveContainerResponse, error) { out := new(RemoveContainerResponse) - err := c.cc.Invoke(ctx, ControlService_RemoveContainer_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/ircontrol.ControlService/RemoveContainer", in, out, opts...) if err != nil { return nil, err } @@ -135,7 +128,7 @@ func _ControlService_HealthCheck_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ControlService_HealthCheck_FullMethodName, + FullMethod: "/ircontrol.ControlService/HealthCheck", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).HealthCheck(ctx, req.(*HealthCheckRequest)) @@ -153,7 +146,7 @@ func _ControlService_TickEpoch_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ControlService_TickEpoch_FullMethodName, + FullMethod: "/ircontrol.ControlService/TickEpoch", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).TickEpoch(ctx, req.(*TickEpochRequest)) @@ -171,7 +164,7 @@ func _ControlService_RemoveNode_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ControlService_RemoveNode_FullMethodName, + FullMethod: "/ircontrol.ControlService/RemoveNode", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).RemoveNode(ctx, req.(*RemoveNodeRequest)) @@ -189,7 +182,7 @@ func _ControlService_RemoveContainer_Handler(srv interface{}, ctx context.Contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: ControlService_RemoveContainer_FullMethodName, + FullMethod: "/ircontrol.ControlService/RemoveContainer", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).RemoveContainer(ctx, req.(*RemoveContainerRequest)) diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 7ffa392a86..805c669a0a 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -7,7 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" - engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -51,7 +51,7 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL resp := &control.AddChainLocalOverrideResponse{ Body: &control.AddChainLocalOverrideResponse_Body{ - ChainId: string(chain.ID), + ChainId: []byte(chain.ID), }, } err = SignMessage(s.key, resp) diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 33ed898ba5..9fb6f865e5 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -3379,7 +3379,7 @@ type AddChainLocalOverrideResponse_Body struct { // Chain ID assigned for the added rule chain. // If chain ID is left empty in the request, then // it will be generated. - ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ChainId []byte `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` } func (x *AddChainLocalOverrideResponse_Body) Reset() { @@ -3414,11 +3414,11 @@ func (*AddChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25, 0} } -func (x *AddChainLocalOverrideResponse_Body) GetChainId() string { +func (x *AddChainLocalOverrideResponse_Body) GetChainId() []byte { if x != nil { return x.ChainId } - return "" + return nil } type GetChainLocalOverrideRequest_Body struct { @@ -3429,7 +3429,7 @@ type GetChainLocalOverrideRequest_Body struct { // Target for which the overrides are applied. Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` // Chain ID assigned for the added rule chain. - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ChainId []byte `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` } func (x *GetChainLocalOverrideRequest_Body) Reset() { @@ -3471,11 +3471,11 @@ func (x *GetChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { return nil } -func (x *GetChainLocalOverrideRequest_Body) GetChainId() string { +func (x *GetChainLocalOverrideRequest_Body) GetChainId() []byte { if x != nil { return x.ChainId } - return "" + return nil } type GetChainLocalOverrideResponse_Body struct { @@ -3630,7 +3630,7 @@ type RemoveChainLocalOverrideRequest_Body struct { // Target for which the overrides are applied. Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` // Chain ID assigned for the added rule chain. - ChainId string `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + ChainId []byte `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` } func (x *RemoveChainLocalOverrideRequest_Body) Reset() { @@ -3672,11 +3672,11 @@ func (x *RemoveChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { return nil } -func (x *RemoveChainLocalOverrideRequest_Body) GetChainId() string { +func (x *RemoveChainLocalOverrideRequest_Body) GetChainId() []byte { if x != nil { return x.ChainId } - return "" + return nil } type RemoveChainLocalOverrideResponse_Body struct { @@ -4222,7 +4222,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, - 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, @@ -4237,7 +4237,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, @@ -4287,7 +4287,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 34c040f2a5..b76645b61b 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -446,7 +446,7 @@ message AddChainLocalOverrideResponse { // Chain ID assigned for the added rule chain. // If chain ID is left empty in the request, then // it will be generated. - string chain_id = 1; + bytes chain_id = 1; } Body body = 1; @@ -461,7 +461,7 @@ message GetChainLocalOverrideRequest { ChainTarget target = 1; // Chain ID assigned for the added rule chain. - string chain_id = 2; + bytes chain_id = 2; } Body body = 1; @@ -511,7 +511,7 @@ message RemoveChainLocalOverrideRequest { ChainTarget target = 1; // Chain ID assigned for the added rule chain. - string chain_id = 2; + bytes chain_id = 2; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 4ce6791f89..574ab13c4b 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2157,7 +2157,7 @@ func (x *AddChainLocalOverrideResponse_Body) StableSize() (size int) { if x == nil { return 0 } - size += proto.StringSize(1, x.ChainId) + size += proto.BytesSize(1, x.ChainId) return size } @@ -2177,7 +2177,7 @@ func (x *AddChainLocalOverrideResponse_Body) StableMarshal(buf []byte) []byte { buf = make([]byte, x.StableSize()) } var offset int - offset += proto.StringMarshal(1, buf[offset:], x.ChainId) + offset += proto.BytesMarshal(1, buf[offset:], x.ChainId) return buf } @@ -2244,7 +2244,7 @@ func (x *GetChainLocalOverrideRequest_Body) StableSize() (size int) { return 0 } size += proto.NestedStructureSize(1, x.Target) - size += proto.StringSize(2, x.ChainId) + size += proto.BytesSize(2, x.ChainId) return size } @@ -2265,7 +2265,7 @@ func (x *GetChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { } var offset int offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) - offset += proto.StringMarshal(2, buf[offset:], x.ChainId) + offset += proto.BytesMarshal(2, buf[offset:], x.ChainId) return buf } @@ -2590,7 +2590,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) StableSize() (size int) { return 0 } size += proto.NestedStructureSize(1, x.Target) - size += proto.StringSize(2, x.ChainId) + size += proto.BytesSize(2, x.ChainId) return size } @@ -2611,7 +2611,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte } var offset int offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) - offset += proto.StringMarshal(2, buf[offset:], x.ChainId) + offset += proto.BytesMarshal(2, buf[offset:], x.ChainId) return buf } diff --git a/pkg/services/tree/service_grpc.pb.go b/pkg/services/tree/service_grpc.pb.go index 63f96e11a5..66850c90e1 100644 --- a/pkg/services/tree/service_grpc.pb.go +++ b/pkg/services/tree/service_grpc.pb.go @@ -1,9 +1,6 @@ -//* -// Service for working with CRDT tree. - // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.2.0 // - protoc v4.25.0 // source: pkg/services/tree/service.proto @@ -21,19 +18,6 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 -const ( - TreeService_Add_FullMethodName = "/tree.TreeService/Add" - TreeService_AddByPath_FullMethodName = "/tree.TreeService/AddByPath" - TreeService_Remove_FullMethodName = "/tree.TreeService/Remove" - TreeService_Move_FullMethodName = "/tree.TreeService/Move" - TreeService_GetNodeByPath_FullMethodName = "/tree.TreeService/GetNodeByPath" - TreeService_GetSubTree_FullMethodName = "/tree.TreeService/GetSubTree" - TreeService_TreeList_FullMethodName = "/tree.TreeService/TreeList" - TreeService_Apply_FullMethodName = "/tree.TreeService/Apply" - TreeService_GetOpLog_FullMethodName = "/tree.TreeService/GetOpLog" - TreeService_Healthcheck_FullMethodName = "/tree.TreeService/Healthcheck" -) - // TreeServiceClient is the client API for TreeService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -71,7 +55,7 @@ func NewTreeServiceClient(cc grpc.ClientConnInterface) TreeServiceClient { func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) { out := new(AddResponse) - err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/tree.TreeService/Add", in, out, opts...) if err != nil { return nil, err } @@ -80,7 +64,7 @@ func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grp func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, opts ...grpc.CallOption) (*AddByPathResponse, error) { out := new(AddByPathResponse) - err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/tree.TreeService/AddByPath", in, out, opts...) if err != nil { return nil, err } @@ -89,7 +73,7 @@ func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts ...grpc.CallOption) (*RemoveResponse, error) { out := new(RemoveResponse) - err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/tree.TreeService/Remove", in, out, opts...) if err != nil { return nil, err } @@ -98,7 +82,7 @@ func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...grpc.CallOption) (*MoveResponse, error) { out := new(MoveResponse) - err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/tree.TreeService/Move", in, out, opts...) if err != nil { return nil, err } @@ -107,7 +91,7 @@ func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...g func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPathRequest, opts ...grpc.CallOption) (*GetNodeByPathResponse, error) { out := new(GetNodeByPathResponse) - err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/tree.TreeService/GetNodeByPath", in, out, opts...) if err != nil { return nil, err } @@ -115,7 +99,7 @@ func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPath } func (c *treeServiceClient) GetSubTree(ctx context.Context, in *GetSubTreeRequest, opts ...grpc.CallOption) (TreeService_GetSubTreeClient, error) { - stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], "/tree.TreeService/GetSubTree", opts...) if err != nil { return nil, err } @@ -148,7 +132,7 @@ func (x *treeServiceGetSubTreeClient) Recv() (*GetSubTreeResponse, error) { func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, opts ...grpc.CallOption) (*TreeListResponse, error) { out := new(TreeListResponse) - err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/tree.TreeService/TreeList", in, out, opts...) if err != nil { return nil, err } @@ -157,7 +141,7 @@ func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, o func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts ...grpc.CallOption) (*ApplyResponse, error) { out := new(ApplyResponse) - err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/tree.TreeService/Apply", in, out, opts...) if err != nil { return nil, err } @@ -165,7 +149,7 @@ func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts .. } func (c *treeServiceClient) GetOpLog(ctx context.Context, in *GetOpLogRequest, opts ...grpc.CallOption) (TreeService_GetOpLogClient, error) { - stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, opts...) + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], "/tree.TreeService/GetOpLog", opts...) if err != nil { return nil, err } @@ -198,7 +182,7 @@ func (x *treeServiceGetOpLogClient) Recv() (*GetOpLogResponse, error) { func (c *treeServiceClient) Healthcheck(ctx context.Context, in *HealthcheckRequest, opts ...grpc.CallOption) (*HealthcheckResponse, error) { out := new(HealthcheckResponse) - err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, "/tree.TreeService/Healthcheck", in, out, opts...) if err != nil { return nil, err } @@ -288,7 +272,7 @@ func _TreeService_Add_Handler(srv interface{}, ctx context.Context, dec func(int } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: TreeService_Add_FullMethodName, + FullMethod: "/tree.TreeService/Add", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Add(ctx, req.(*AddRequest)) @@ -306,7 +290,7 @@ func _TreeService_AddByPath_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: TreeService_AddByPath_FullMethodName, + FullMethod: "/tree.TreeService/AddByPath", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).AddByPath(ctx, req.(*AddByPathRequest)) @@ -324,7 +308,7 @@ func _TreeService_Remove_Handler(srv interface{}, ctx context.Context, dec func( } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: TreeService_Remove_FullMethodName, + FullMethod: "/tree.TreeService/Remove", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Remove(ctx, req.(*RemoveRequest)) @@ -342,7 +326,7 @@ func _TreeService_Move_Handler(srv interface{}, ctx context.Context, dec func(in } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: TreeService_Move_FullMethodName, + FullMethod: "/tree.TreeService/Move", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Move(ctx, req.(*MoveRequest)) @@ -360,7 +344,7 @@ func _TreeService_GetNodeByPath_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: TreeService_GetNodeByPath_FullMethodName, + FullMethod: "/tree.TreeService/GetNodeByPath", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).GetNodeByPath(ctx, req.(*GetNodeByPathRequest)) @@ -399,7 +383,7 @@ func _TreeService_TreeList_Handler(srv interface{}, ctx context.Context, dec fun } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: TreeService_TreeList_FullMethodName, + FullMethod: "/tree.TreeService/TreeList", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).TreeList(ctx, req.(*TreeListRequest)) @@ -417,7 +401,7 @@ func _TreeService_Apply_Handler(srv interface{}, ctx context.Context, dec func(i } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: TreeService_Apply_FullMethodName, + FullMethod: "/tree.TreeService/Apply", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Apply(ctx, req.(*ApplyRequest)) @@ -456,7 +440,7 @@ func _TreeService_Healthcheck_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: TreeService_Healthcheck_FullMethodName, + FullMethod: "/tree.TreeService/Healthcheck", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Healthcheck(ctx, req.(*HealthcheckRequest)) From 4a4c790ec1d0ee2d72200c2fc9baf4df0aa67673 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Thu, 21 Dec 2023 15:55:09 +0300 Subject: [PATCH 0250/1413] [#885] cli: Support hex chain id in control API Signed-off-by: Denis Kirillov --- cmd/frostfs-cli/modules/control/add_rule.go | 16 ++++++++++++++-- cmd/frostfs-cli/modules/control/get_rule.go | 11 ++++++++++- cmd/frostfs-cli/modules/control/list_rules.go | 2 +- cmd/frostfs-cli/modules/control/remove_rule.go | 16 ++++++++++++++-- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 47233678db..4fe8194bb1 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -3,6 +3,7 @@ package control import ( "bytes" "crypto/sha256" + "encoding/hex" "encoding/json" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" @@ -42,6 +43,15 @@ func addRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) chainID, _ := cmd.Flags().GetString(chainIDFlag) + hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) + + chainIDRaw := []byte(chainID) + + if hexEncoded { + var err error + chainIDRaw, err = hex.DecodeString(chainID) + commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) + } var cnr cid.ID cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) @@ -54,7 +64,7 @@ func addRule(cmd *cobra.Command, _ []string) { chain := new(apechain.Chain) commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, []string{rule})) - chain.ID = apechain.ID(chainID) + chain.ID = apechain.ID(chainIDRaw) serializedChain := chain.Bytes() cmd.Println("CID: " + cidStr) @@ -84,7 +94,8 @@ func addRule(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) - cmd.Println("Rule has been added. Chain id: ", resp.GetBody().GetChainId()) + chainIDRaw = resp.GetBody().GetChainId() + cmd.Printf("Rule has been added.\nChain id: '%s'\nChain id hex: '%x'\n", string(chainIDRaw), chainIDRaw) } func initControlAddRuleCmd() { @@ -94,4 +105,5 @@ func initControlAddRuleCmd() { ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) ff.String(ruleFlag, "", "Rule statement") ff.String(chainIDFlag, "", "Assign ID to the parsed chain") + ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") } diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 2bb6a7da25..9508850ee8 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -2,6 +2,7 @@ package control import ( "crypto/sha256" + "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -31,6 +32,13 @@ func getRule(cmd *cobra.Command, _ []string) { cnr.Encode(rawCID) chainID, _ := cmd.Flags().GetString(chainIDFlag) + hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) + + if hexEncoded { + chainIDBytes, err := hex.DecodeString(chainID) + commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) + chainID = string(chainIDBytes) + } req := &control.GetChainLocalOverrideRequest{ Body: &control.GetChainLocalOverrideRequest_Body{ @@ -60,7 +68,7 @@ func getRule(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain())) // TODO (aarifullin): make pretty-formatted output for chains. - cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, chain.Bytes())) + cmd.Printf("Parsed chain (chain id hex: '%x'):\n%s\n", chain.ID, prettyJSONFormat(cmd, chain.Bytes())) } func initControGetRuleCmd() { @@ -69,4 +77,5 @@ func initControGetRuleCmd() { ff := getRuleCmd.Flags() ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) ff.String(chainIDFlag, "", "Chain id") + ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") } diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index f087f53673..ef494b1353 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -63,7 +63,7 @@ func listRules(cmd *cobra.Command, _ []string) { // TODO (aarifullin): make pretty-formatted output for chains. var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c)) - cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, chain.Bytes())) + cmd.Printf("Parsed chain (chain id hex: '%x'):\n%s\n", chain.ID, prettyJSONFormat(cmd, chain.Bytes())) } } diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index 60e5376a14..612ab7d0af 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -2,6 +2,7 @@ package control import ( "crypto/sha256" + "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -13,7 +14,8 @@ import ( ) const ( - chainIDFlag = "chain-id" + chainIDFlag = "chain-id" + chainIDHexFlag = "chain-id-hex" ) var removeRuleCmd = &cobra.Command{ @@ -34,6 +36,15 @@ func removeRule(cmd *cobra.Command, _ []string) { cnr.Encode(rawCID) chainID, _ := cmd.Flags().GetString(chainIDFlag) + hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) + + chainIDRaw := []byte(chainID) + + if hexEncoded { + var err error + chainIDRaw, err = hex.DecodeString(chainID) + commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) + } req := &control.RemoveChainLocalOverrideRequest{ Body: &control.RemoveChainLocalOverrideRequest_Body{ @@ -41,7 +52,7 @@ func removeRule(cmd *cobra.Command, _ []string) { Name: cidStr, Type: control.ChainTarget_CONTAINER, }, - ChainId: []byte(chainID), + ChainId: chainIDRaw, }, } @@ -72,4 +83,5 @@ func initControlRemoveRuleCmd() { ff := removeRuleCmd.Flags() ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) ff.String(chainIDFlag, "", "Chain id") + ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") } From 5d982976fd7d2c34589f5a1858f8e608c5bd3f36 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 11 Jan 2024 11:00:45 +0300 Subject: [PATCH 0251/1413] [#898] ape: Fix bug with creating type bucket in chainbase Signed-off-by: Airat Arifullin --- pkg/ape/chainbase/boltdb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index e54d01ea0a..34a5c7d2d6 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -140,7 +140,7 @@ func getTargetBucketCreateIfEmpty(tx *bbolt.Tx, name chain.Name, target policyen typeBucket := nbucket.Bucket([]byte{byte(target.Type)}) if typeBucket == nil { var err error - typeBucket, err = cbucket.CreateBucket([]byte{byte(target.Type)}) + typeBucket, err = nbucket.CreateBucket([]byte{byte(target.Type)}) if err != nil { return nil, fmt.Errorf("could not create a bucket for the target type '%c': %w", target.Type, err) } From a8e52ef7aaf41995e644ac92925db22f1295ccd0 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 11 Jan 2024 11:51:29 +0300 Subject: [PATCH 0252/1413] [#898] control: Fix codes for returning APE errors Signed-off-by: Airat Arifullin --- pkg/ape/chainbase/boltdb.go | 36 +++++++++++++------- pkg/services/control/server/policy_engine.go | 12 +++++-- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index 34a5c7d2d6..1047ad42d8 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -25,15 +25,16 @@ type boltLocalOverrideStorage struct { var chainBucket = []byte{0} var ( - ErrChainBucketNotFound = logicerr.New("chain root bucket has not been found") + // ErrRootBucketNotFound signals the database has not been properly initialized. + ErrRootBucketNotFound = logicerr.New("root bucket not found") - ErrChainNotFound = logicerr.New("chain has not been found") + ErrGlobalNamespaceBucketNotFound = logicerr.New("global namespace bucket not found") - ErrGlobalNamespaceBucketNotFound = logicerr.New("global namespace bucket has not been found") + ErrTargetTypeBucketNotFound = logicerr.New("target type bucket not found") - ErrTargetTypeBucketNotFound = logicerr.New("target type bucket has not been found") + ErrTargetNameBucketNotFound = logicerr.New("target name bucket not found") - ErrTargetNameBucketNotFound = logicerr.New("target name bucket has not been found") + ErrBucketNotContainsChainID = logicerr.New("chain id not found in bucket") ) // NewBoltLocalOverrideDatabase returns storage wrapper for storing access policy engine @@ -101,31 +102,30 @@ func (cs *boltLocalOverrideStorage) Close() error { func getTargetBucket(tx *bbolt.Tx, name chain.Name, target policyengine.Target) (*bbolt.Bucket, error) { cbucket := tx.Bucket(chainBucket) if cbucket == nil { - return nil, ErrChainBucketNotFound + return nil, ErrRootBucketNotFound } nbucket := cbucket.Bucket([]byte(name)) if nbucket == nil { - return nil, fmt.Errorf("global namespace %s: %w", name, ErrGlobalNamespaceBucketNotFound) + return nil, fmt.Errorf("%w: %w: %s", policyengine.ErrChainNotFound, ErrGlobalNamespaceBucketNotFound, name) } typeBucket := nbucket.Bucket([]byte{byte(target.Type)}) if typeBucket == nil { - return nil, fmt.Errorf("type bucket '%c': %w", target.Type, ErrTargetTypeBucketNotFound) + return nil, fmt.Errorf("%w: %w: %c", policyengine.ErrChainNotFound, ErrTargetTypeBucketNotFound, target.Type) } rbucket := typeBucket.Bucket([]byte(target.Name)) if rbucket == nil { - return nil, fmt.Errorf("target name bucket %s: %w", target.Name, ErrTargetNameBucketNotFound) + return nil, fmt.Errorf("%w: %w: %s", policyengine.ErrChainNotFound, ErrTargetNameBucketNotFound, target.Name) } - return rbucket, nil } func getTargetBucketCreateIfEmpty(tx *bbolt.Tx, name chain.Name, target policyengine.Target) (*bbolt.Bucket, error) { cbucket := tx.Bucket(chainBucket) if cbucket == nil { - return nil, ErrChainBucketNotFound + return nil, ErrRootBucketNotFound } nbucket := cbucket.Bucket([]byte(name)) @@ -186,7 +186,7 @@ func (cs *boltLocalOverrideStorage) GetOverride(name chain.Name, target policyen } serializedChain = rbuck.Get([]byte(chainID)) if serializedChain == nil { - return ErrChainNotFound + return fmt.Errorf("%w: %w: %s", policyengine.ErrChainNotFound, ErrBucketNotContainsChainID, chainID) } serializedChain = slice.Copy(serializedChain) return nil @@ -225,7 +225,7 @@ func (cs *boltLocalOverrideStorage) ListOverrides(name chain.Name, target policy return nil }) }); err != nil { - if errors.Is(err, ErrGlobalNamespaceBucketNotFound) || errors.Is(err, ErrTargetNameBucketNotFound) { + if errors.Is(err, policyengine.ErrChainNotFound) { return []*chain.Chain{}, nil } return nil, err @@ -243,6 +243,16 @@ func (cs *boltLocalOverrideStorage) ListOverrides(name chain.Name, target policy func (cs *boltLocalOverrideStorage) DropAllOverrides(name chain.Name) error { return cs.db.Update(func(tx *bbolt.Tx) error { + cbucket := tx.Bucket(chainBucket) + if cbucket == nil { + return ErrRootBucketNotFound + } + + nbucket := cbucket.Bucket([]byte(name)) + if nbucket == nil { + return fmt.Errorf("%w: %w: global namespace %s", policyengine.ErrChainNotFound, ErrGlobalNamespaceBucketNotFound, name) + } + return tx.DeleteBucket([]byte(name)) }) } diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 805c669a0a..519b210355 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -128,12 +128,18 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return nil, err } + removed := true if err = s.localOverrideStorage.LocalStorage().RemoveOverride(apechain.Ingress, target, apechain.ID(req.GetBody().GetChainId())); err != nil { - return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) + code := getCodeByLocalStorageErr(err) + if code == codes.NotFound { + removed = false + } else { + return nil, status.Error(code, err.Error()) + } } resp := &control.RemoveChainLocalOverrideResponse{ Body: &control.RemoveChainLocalOverrideResponse_Body{ - Removed: true, + Removed: removed, }, } err = SignMessage(s.key, resp) @@ -144,7 +150,7 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove } func getCodeByLocalStorageErr(err error) codes.Code { - if errors.Is(err, engine.ErrChainNotFound) { + if errors.Is(err, engine.ErrChainNotFound) || errors.Is(err, engine.ErrChainNameNotFound) { return codes.NotFound } return codes.Internal From f1b2b8bffaf1c4d613d4e9afb5065aec4d8d1c74 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 9 Jan 2024 11:37:41 +0300 Subject: [PATCH 0253/1413] [#895] test: Fix NewLogger arguments list `debug` is always true. Signed-off-by: Dmitrii Stepanov --- pkg/innerring/blocktimer_test.go | 2 +- .../processors/alphabet/handlers_test.go | 6 +++--- .../processors/balance/handlers_test.go | 4 ++-- .../processors/container/handlers_test.go | 6 +++--- .../processors/frostfs/handlers_test.go | 2 +- .../processors/governance/handlers_test.go | 4 ++-- .../processors/netmap/handlers_test.go | 2 +- .../blobovnicza/blobovnicza_test.go | 2 +- .../blobovniczatree/concurrency_test.go | 2 +- .../blobstor/blobovniczatree/exists_test.go | 2 +- .../blobstor/blobovniczatree/generic_test.go | 4 ++-- .../blobovniczatree/rebuild_failover_test.go | 2 +- .../blobstor/blobovniczatree/rebuild_test.go | 4 ++-- .../blobstor/memstore/memstore_test.go | 2 +- .../engine/control_test.go | 4 ++-- .../engine/delete_test.go | 2 +- .../engine/engine_test.go | 4 ++-- pkg/local_object_storage/engine/error_test.go | 2 +- .../engine/evacuate_test.go | 2 +- pkg/local_object_storage/engine/list_test.go | 2 +- .../shard/control_test.go | 2 +- .../shard/gc_internal_test.go | 6 +++--- pkg/local_object_storage/shard/range_test.go | 2 +- pkg/local_object_storage/shard/reload_test.go | 2 +- pkg/local_object_storage/shard/shard_test.go | 6 +++--- .../writecache/flush_test.go | 2 +- .../writecache/generic_test.go | 2 +- pkg/morph/event/listener_test.go | 6 +++--- pkg/services/object/get/get_test.go | 6 +++--- pkg/services/object/search/search_test.go | 8 +++---- pkg/services/tree/signature_test.go | 2 +- pkg/util/logger/test/logger.go | 21 +++++++------------ 32 files changed, 60 insertions(+), 65 deletions(-) diff --git a/pkg/innerring/blocktimer_test.go b/pkg/innerring/blocktimer_test.go index 9d02721c2a..242c0903b3 100644 --- a/pkg/innerring/blocktimer_test.go +++ b/pkg/innerring/blocktimer_test.go @@ -19,7 +19,7 @@ func TestEpochTimer(t *testing.T) { } args := &epochTimerArgs{ - l: test.NewLogger(t, true), + l: test.NewLogger(t), alphabetState: alphaState, newEpochHandlers: []newEpochHandler{neh.Handle}, cnrWrapper: cnrStopper, diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index f94c8e78db..346901949b 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -48,7 +48,7 @@ func TestProcessorEmitsGasToNetmapAndAlphabet(t *testing.T) { params := &alphabet.Params{ ParsedWallets: parsedWallets, - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 2, StorageEmission: emission, IRList: &testIndexer{index: index}, @@ -125,7 +125,7 @@ func TestProcessorEmitsGasToNetmapIfNoParsedWallets(t *testing.T) { params := &alphabet.Params{ ParsedWallets: parsedWallets, - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 2, StorageEmission: emission, IRList: &testIndexer{index: index}, @@ -186,7 +186,7 @@ func TestProcessorDoesntEmitGasIfNoNetmapOrParsedWallets(t *testing.T) { params := &alphabet.Params{ ParsedWallets: parsedWallets, - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 2, StorageEmission: emission, IRList: &testIndexer{index: index}, diff --git a/pkg/innerring/processors/balance/handlers_test.go b/pkg/innerring/processors/balance/handlers_test.go index 10ae8c60e4..86a9e15d04 100644 --- a/pkg/innerring/processors/balance/handlers_test.go +++ b/pkg/innerring/processors/balance/handlers_test.go @@ -21,7 +21,7 @@ func TestProcessorCallsFrostFSContractForLockEvent(t *testing.T) { bsc := util.Uint160{100} processor, err := New(&Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 2, FrostFSClient: cl, BalanceSC: bsc, @@ -47,7 +47,7 @@ func TestProcessorDoesntCallFrostFSContractIfNotAlphabet(t *testing.T) { bsc := util.Uint160{100} processor, err := New(&Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 2, FrostFSClient: cl, BalanceSC: bsc, diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index 9fbfdf8114..a69d0e4c42 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -38,7 +38,7 @@ func TestPutEvent(t *testing.T) { mc := &testMorphClient{} proc, err := New(&Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 2, AlphabetState: &testAlphabetState{isAlphabet: true}, NetworkState: nst, @@ -99,7 +99,7 @@ func TestDeleteEvent(t *testing.T) { mc := &testMorphClient{} proc, err := New(&Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 2, AlphabetState: &testAlphabetState{isAlphabet: true}, NetworkState: nst, @@ -171,7 +171,7 @@ func TestSetEACLEvent(t *testing.T) { mc := &testMorphClient{} proc, err := New(&Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 2, AlphabetState: &testAlphabetState{isAlphabet: true}, NetworkState: nst, diff --git a/pkg/innerring/processors/frostfs/handlers_test.go b/pkg/innerring/processors/frostfs/handlers_test.go index 2685808edb..6425172bd1 100644 --- a/pkg/innerring/processors/frostfs/handlers_test.go +++ b/pkg/innerring/processors/frostfs/handlers_test.go @@ -193,7 +193,7 @@ func TestHandleConfig(t *testing.T) { func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) { p := &Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 1, FrostFSContract: util.Uint160{0}, BalanceClient: &testBalaceClient{}, diff --git a/pkg/innerring/processors/governance/handlers_test.go b/pkg/innerring/processors/governance/handlers_test.go index adf6741730..2a505f8d1e 100644 --- a/pkg/innerring/processors/governance/handlers_test.go +++ b/pkg/innerring/processors/governance/handlers_test.go @@ -42,7 +42,7 @@ func TestHandleAlphabetSyncEvent(t *testing.T) { proc, err := New( &Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), EpochState: es, AlphabetState: as, Voter: v, @@ -123,7 +123,7 @@ func TestHandleAlphabetDesignateEvent(t *testing.T) { proc, err := New( &Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), EpochState: es, AlphabetState: as, Voter: v, diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index 6a66fe323a..b34abb78cd 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -279,7 +279,7 @@ func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) { eh := &testEventHandler{} p := &Params{ - Log: test.NewLogger(t, true), + Log: test.NewLogger(t), PoolSize: 1, CleanupEnabled: false, CleanupThreshold: 3, diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go index 8d701ae5ca..caee770e85 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go @@ -63,7 +63,7 @@ func TestBlobovnicza(t *testing.T) { WithPath(p), WithObjectSizeLimit(objSizeLim), WithFullSizeLimit(sizeLim), - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), ) defer os.Remove(p) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go index 24cb93865c..350ebef54e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -17,7 +17,7 @@ func TestBlobovniczaTree_Concurrency(t *testing.T) { const n = 1000 st := NewBlobovniczaTree( - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithObjectSizeLimit(1024), WithBlobovniczaShallowWidth(10), WithBlobovniczaShallowDepth(1), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index 63df97595c..d50fb7983a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -17,7 +17,7 @@ import ( func TestExistsInvalidStorageID(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithObjectSizeLimit(1024), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go index 6eb8b81aef..1a52eddf82 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go @@ -13,7 +13,7 @@ func TestGeneric(t *testing.T) { helper := func(t *testing.T, dir string) common.Storage { return NewBlobovniczaTree( - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), @@ -40,7 +40,7 @@ func TestControl(t *testing.T) { newTree := func(t *testing.T) common.Storage { return NewBlobovniczaTree( - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index ff86c036ae..855229405f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -129,7 +129,7 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object, mustUpdateStorageID bool) { b := NewBlobovniczaTree( - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 904971d25d..0ac50f36a3 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -41,7 +41,7 @@ func TestBlobovniczaTreeRebuild(t *testing.T) { func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, targetDepth, targetWidth uint64, shouldMigrate bool) { dir := t.TempDir() b := NewBlobovniczaTree( - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(sourceWidth), WithBlobovniczaShallowDepth(sourceDepth), @@ -81,7 +81,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta require.NoError(t, b.Close()) b = NewBlobovniczaTree( - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(targetWidth), WithBlobovniczaShallowDepth(targetDepth), diff --git a/pkg/local_object_storage/blobstor/memstore/memstore_test.go b/pkg/local_object_storage/blobstor/memstore/memstore_test.go index eaa2a4b617..cabf7f5add 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore_test.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore_test.go @@ -15,7 +15,7 @@ import ( func TestSimpleLifecycle(t *testing.T) { s := New( WithRootPath("memstore"), - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), ) t.Cleanup(func() { _ = s.Close() }) require.NoError(t, s.Open(false)) diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 21652970b8..41b7db91c1 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -49,7 +49,7 @@ func TestInitializationFailure(t *testing.T) { return []shard.Option{ shard.WithID(sid), - shard.WithLogger(test.NewLogger(t, true)), + shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( blobstor.WithStorages(storages)), shard.WithMetaBaseOptions( @@ -289,7 +289,7 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str te := testNewEngine(t). setShardsNumOpts(t, num, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(test.NewLogger(t, true)), + shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( blobstor.WithStorages(newStorages(filepath.Join(addPath, strconv.Itoa(id)), errSmallSize))), shard.WithMetaBaseOptions( diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 8e94732ae9..f3e4a09767 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -53,7 +53,7 @@ func TestDeleteBigObject(t *testing.T) { s3 := testNewShard(t, 3) e := testNewEngine(t).setInitializedShards(t, s1, s2, s3).engine - e.log = test.NewLogger(t, true) + e.log = test.NewLogger(t) defer e.Close(context.Background()) for i := range children { diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 21bf37dc71..063ea451e5 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -79,7 +79,7 @@ type testEngineWrapper struct { } func testNewEngine(t testing.TB, opts ...Option) *testEngineWrapper { - engine := New(WithLogger(test.NewLogger(t, true))) + engine := New(WithLogger(test.NewLogger(t))) for _, opt := range opts { opt(engine.cfg) } @@ -198,7 +198,7 @@ func testNewShard(t testing.TB, id int) *shard.Shard { func testDefaultShardOptions(t testing.TB, id int) []shard.Option { return []shard.Option{ - shard.WithLogger(test.NewLogger(t, true)), + shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( blobstor.WithStorages( newStorages(t.TempDir(), 1<<20))), diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index cf62302f2f..3f343e5b92 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -55,7 +55,7 @@ func newEngineWithErrorThreshold(t testing.TB, dir string, errThreshold uint32) largeFileStorage: largeFileStorage, } return []shard.Option{ - shard.WithLogger(test.NewLogger(t, true)), + shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions(blobstor.WithStorages(storages)), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(dir, fmt.Sprintf("%d.metabase", id))), diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 13ba94f5b9..ca86ef5448 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -30,7 +30,7 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng te := testNewEngine(t). setShardsNumOpts(t, shardNum, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(test.NewLogger(t, true)), + shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{{ Storage: fstree.New( diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 246118687e..27c6c819fb 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -65,7 +65,7 @@ func TestListWithCursor(t *testing.T) { t.Parallel() e := testNewEngine(t).setShardsNumOpts(t, tt.shardNum, func(id int) []shard.Option { return []shard.Option{ - shard.WithLogger(test.NewLogger(t, true)), + shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( blobstor.WithStorages( newStorages(t.TempDir(), 1<<20))), diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 8a650db0c0..4d7354595b 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -64,7 +64,7 @@ func TestShardOpen(t *testing.T) { newShard := func() *Shard { return New( WithID(NewIDFromBytes([]byte{})), - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{ {Storage: st}, diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index b64cb9c407..a82fc3ffe1 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -30,13 +30,13 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { rootPath := t.TempDir() var sh *Shard - l := test.NewLogger(t, true) + l := test.NewLogger(t) blobOpts := []blobstor.Option{ - blobstor.WithLogger(test.NewLogger(t, true)), + blobstor.WithLogger(test.NewLogger(t)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(test.NewLogger(t, true)), + blobovniczatree.WithLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 35dc0c6a59..28bbd30e58 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -78,7 +78,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(test.NewLogger(t, true)), + blobovniczatree.WithLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(t.TempDir(), "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index fc1fc2d20a..c76fc1a002 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -27,7 +27,7 @@ func TestShardReload(t *testing.T) { p := t.Name() defer os.RemoveAll(p) - l := test.NewLogger(t, true) + l := test.NewLogger(t) blobOpts := []blobstor.Option{ blobstor.WithLogger(l), blobstor.WithStorages([]blobstor.SubStorage{ diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 807633cd5a..98d1c7b8e7 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -56,11 +56,11 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard if o.bsOpts == nil { o.bsOpts = []blobstor.Option{ - blobstor.WithLogger(test.NewLogger(t, true)), + blobstor.WithLogger(test.NewLogger(t)), blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( - blobovniczatree.WithLogger(test.NewLogger(t, true)), + blobovniczatree.WithLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(o.rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), @@ -78,7 +78,7 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard opts := []Option{ WithID(NewIDFromBytes([]byte{})), - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithBlobStorOptions(o.bsOpts...), WithMetaBaseOptions( append([]meta.Option{ diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index 4a243c5ec0..a358028e7c 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -24,7 +24,7 @@ import ( ) func TestFlush(t *testing.T) { - testlogger := test.NewLogger(t, true) + testlogger := test.NewLogger(t) createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs MainStorage, opts ...Option) Cache { return New( diff --git a/pkg/local_object_storage/writecache/generic_test.go b/pkg/local_object_storage/writecache/generic_test.go index a6d9e47994..2913ed13b5 100644 --- a/pkg/local_object_storage/writecache/generic_test.go +++ b/pkg/local_object_storage/writecache/generic_test.go @@ -10,7 +10,7 @@ import ( func TestGeneric(t *testing.T) { storagetest.TestAll(t, func(t *testing.T) storagetest.Component { return New( - WithLogger(test.NewLogger(t, true)), + WithLogger(test.NewLogger(t)), WithFlushWorkersCount(2), WithPath(t.TempDir())) }) diff --git a/pkg/morph/event/listener_test.go b/pkg/morph/event/listener_test.go index ae92bd5803..5f7cf9f436 100644 --- a/pkg/morph/event/listener_test.go +++ b/pkg/morph/event/listener_test.go @@ -20,7 +20,7 @@ func TestEventHandling(t *testing.T) { notaryRequestsCh := make(chan *result.NotaryRequestEvent) l, err := NewListener(ListenerParams{ - Logger: test.NewLogger(t, true), + Logger: test.NewLogger(t), Subscriber: &testSubscriber{ blockCh: blockCh, notificationCh: notificationCh, @@ -102,7 +102,7 @@ func TestErrorPassing(t *testing.T) { t.Run("notification error", func(t *testing.T) { nErr := fmt.Errorf("notification error") l, err := NewListener(ListenerParams{ - Logger: test.NewLogger(t, true), + Logger: test.NewLogger(t), Subscriber: &testSubscriber{ blockCh: blockCh, notificationCh: notificationCh, @@ -126,7 +126,7 @@ func TestErrorPassing(t *testing.T) { t.Run("block error", func(t *testing.T) { bErr := fmt.Errorf("notification error") l, err := NewListener(ListenerParams{ - Logger: test.NewLogger(t, true), + Logger: test.NewLogger(t), Subscriber: &testSubscriber{ blockCh: blockCh, notificationCh: notificationCh, diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index f4d4f7372f..64614d8d83 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -270,7 +270,7 @@ func TestGetLocalOnly(t *testing.T) { newSvc := func(storage *testStorage) *Service { return &Service{ - log: test.NewLogger(t, true), + log: test.NewLogger(t), localStorage: storage, } } @@ -532,7 +532,7 @@ func TestGetRemoteSmall(t *testing.T) { const curEpoch = 13 return &Service{ - log: test.NewLogger(t, true), + log: test.NewLogger(t), localStorage: newTestStorage(), traverserGenerator: &testTraverserGenerator{ c: cnr, @@ -1663,7 +1663,7 @@ func TestGetFromPastEpoch(t *testing.T) { const curEpoch = 13 svc := &Service{ - log: test.NewLogger(t, true), + log: test.NewLogger(t), localStorage: newTestStorage(), epochSource: testEpochReceiver(curEpoch), traverserGenerator: &testTraverserGenerator{ diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 09d98eff2e..802fa33efa 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -161,7 +161,7 @@ func TestGetLocalOnly(t *testing.T) { newSvc := func(storage *testStorage) *Service { svc := &Service{cfg: new(cfg)} - svc.log = test.NewLogger(t, true) + svc.log = test.NewLogger(t) svc.localStorage = storage return svc @@ -277,7 +277,7 @@ func TestGetRemoteSmall(t *testing.T) { newSvc := func(b *testPlacementBuilder, c *testClientCache) *Service { svc := &Service{cfg: new(cfg)} - svc.log = test.NewLogger(t, true) + svc.log = test.NewLogger(t) svc.localStorage = newTestStorage() const curEpoch = 13 @@ -430,7 +430,7 @@ func TestGetFromPastEpoch(t *testing.T) { c22.addResult(idCnr, ids22, nil) svc := &Service{cfg: new(cfg)} - svc.log = test.NewLogger(t, true) + svc.log = test.NewLogger(t) svc.localStorage = newTestStorage() const curEpoch = 13 @@ -543,7 +543,7 @@ func TestGetWithSessionToken(t *testing.T) { w := new(simpleIDWriter) svc := &Service{cfg: new(cfg)} - svc.log = test.NewLogger(t, true) + svc.log = test.NewLogger(t) svc.localStorage = localStorage const curEpoch = 13 diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 1449d57565..b55f4d4fce 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -100,7 +100,7 @@ func TestMessageSign(t *testing.T) { s := &Service{ cfg: cfg{ - log: test.NewLogger(t, true), + log: test.NewLogger(t), key: &privs[0].PrivateKey, nmSource: dummyNetmapSource{}, cnrSource: dummyContainerSource{ diff --git a/pkg/util/logger/test/logger.go b/pkg/util/logger/test/logger.go index 4a28708703..dd07e61700 100644 --- a/pkg/util/logger/test/logger.go +++ b/pkg/util/logger/test/logger.go @@ -10,20 +10,15 @@ import ( ) // NewLogger creates a new logger. -// -// If debug, development logger is created. -func NewLogger(t testing.TB, debug bool) *logger.Logger { +func NewLogger(t testing.TB) *logger.Logger { + cfg := zap.NewDevelopmentConfig() + cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder + + log, err := cfg.Build() + require.NoError(t, err, "could not prepare logger") + var l logger.Logger - l.Logger = zap.L() - - if debug { - cfg := zap.NewDevelopmentConfig() - cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder - - log, err := cfg.Build() - require.NoError(t, err, "could not prepare logger") - l.Logger = log - } + l.Logger = log return &l } From 836818fb751f79ac129121d0eeea44de0193efc4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 9 Jan 2024 12:32:13 +0300 Subject: [PATCH 0254/1413] [#895] test: Use zaptest logger Previous implementation mixes logs from different tests, now logs are separeted by test. Signed-off-by: Dmitrii Stepanov --- pkg/util/logger/test/logger.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pkg/util/logger/test/logger.go b/pkg/util/logger/test/logger.go index dd07e61700..f93756d17e 100644 --- a/pkg/util/logger/test/logger.go +++ b/pkg/util/logger/test/logger.go @@ -4,21 +4,16 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "github.com/stretchr/testify/require" "go.uber.org/zap" "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest" ) // NewLogger creates a new logger. func NewLogger(t testing.TB) *logger.Logger { - cfg := zap.NewDevelopmentConfig() - cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder - - log, err := cfg.Build() - require.NoError(t, err, "could not prepare logger") - var l logger.Logger - l.Logger = log - + l.Logger = zaptest.NewLogger(t, + zaptest.Level(zapcore.DebugLevel), + zaptest.WrapOptions(zap.Development(), zap.AddCaller())) return &l } From 47dcfa20f32d9b9032f76b99d452d9fc42da7dfa Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 9 Jan 2024 16:26:43 +0300 Subject: [PATCH 0255/1413] [#895] test: Use t.Cleanup only for external resources Signed-off-by: Dmitrii Stepanov --- .../blobovnicza/get_test.go | 7 +- .../blobovniczatree/concurrency_test.go | 4 +- .../blobstor/blobovniczatree/exists_test.go | 2 +- .../blobstor/internal/blobstortest/delete.go | 2 +- .../blobstor/internal/blobstortest/exists.go | 2 +- .../blobstor/internal/blobstortest/get.go | 2 +- .../internal/blobstortest/get_range.go | 2 +- .../blobstor/internal/blobstortest/iterate.go | 2 +- .../blobstor/memstore/memstore_test.go | 2 +- .../blobstor/perf_test.go | 7 +- .../engine/control_test.go | 7 ++ .../engine/engine_test.go | 6 +- pkg/local_object_storage/engine/error_test.go | 2 + pkg/local_object_storage/engine/list_test.go | 6 +- pkg/local_object_storage/engine/lock_test.go | 12 +-- .../engine/shards_test.go | 4 +- .../metabase/containers_test.go | 3 + .../metabase/control_test.go | 1 + .../metabase/counter_test.go | 8 ++ pkg/local_object_storage/metabase/db_test.go | 6 -- .../metabase/delete_test.go | 4 + .../metabase/exists_test.go | 1 + .../metabase/expired_test.go | 1 + pkg/local_object_storage/metabase/get_test.go | 2 + .../metabase/graveyard_test.go | 6 ++ .../metabase/inhume_test.go | 3 + .../metabase/iterators_test.go | 2 + .../metabase/list_test.go | 3 + .../metabase/lock_test.go | 3 + .../metabase/movable_test.go | 1 + pkg/local_object_storage/metabase/put_test.go | 3 + .../metabase/select_test.go | 11 +++ .../metabase/storage_id_test.go | 1 + .../pilorama/bench_test.go | 3 +- .../pilorama/forest_test.go | 79 +++++++++++++------ pkg/local_object_storage/shard/delete_test.go | 1 + .../shard/gc_internal_test.go | 5 +- pkg/local_object_storage/shard/gc_test.go | 2 + pkg/local_object_storage/shard/get_test.go | 1 + pkg/local_object_storage/shard/head_test.go | 1 + pkg/local_object_storage/shard/inhume_test.go | 1 + pkg/local_object_storage/shard/list_test.go | 2 + pkg/local_object_storage/shard/lock_test.go | 5 +- .../shard/metrics_test.go | 5 +- pkg/local_object_storage/shard/range_test.go | 1 + pkg/local_object_storage/shard/reload_test.go | 4 + pkg/local_object_storage/shard/shard_test.go | 9 --- .../shard/shutdown_test.go | 3 +- .../writecache/benchmark/writecache_test.go | 5 +- .../writecache/flush_test.go | 4 +- 50 files changed, 164 insertions(+), 95 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/get_test.go b/pkg/local_object_storage/blobovnicza/get_test.go index 40c434eb7f..c464abc877 100644 --- a/pkg/local_object_storage/blobovnicza/get_test.go +++ b/pkg/local_object_storage/blobovnicza/get_test.go @@ -2,7 +2,6 @@ package blobovnicza import ( "context" - "os" "path/filepath" "testing" @@ -15,11 +14,7 @@ func TestBlobovnicza_Get(t *testing.T) { filename := filepath.Join(t.TempDir(), "blob") var blz *Blobovnicza - - t.Cleanup(func() { - blz.Close() - os.RemoveAll(filename) - }) + defer func() { require.NoError(t, blz.Close()) }() fnInit := func(szLimit uint64) { if blz != nil { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go index 350ebef54e..e8b148bff5 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -24,9 +24,9 @@ func TestBlobovniczaTree_Concurrency(t *testing.T) { WithRootPath(t.TempDir())) require.NoError(t, st.Open(false)) require.NoError(t, st.Init()) - t.Cleanup(func() { + defer func() { require.NoError(t, st.Close()) - }) + }() objGen := &testutil.SeqObjGenerator{ObjSize: 1} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index d50fb7983a..048f9a2e53 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -25,7 +25,7 @@ func TestExistsInvalidStorageID(t *testing.T) { WithBlobovniczaSize(1<<20)) require.NoError(t, b.Open(false)) require.NoError(t, b.Init()) - t.Cleanup(func() { _ = b.Close() }) + defer func() { require.NoError(t, b.Close()) }() obj := blobstortest.NewObject(1024) addr := object.AddressOf(obj) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go index 0bfac2772b..f551cbf5f6 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go @@ -14,7 +14,7 @@ func TestDelete(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) require.NoError(t, s.Open(false)) require.NoError(t, s.Init()) - t.Cleanup(func() { require.NoError(t, s.Close()) }) + defer func() { require.NoError(t, s.Close()) }() objects := prepare(t, 4, s, min, max) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go index 99f6a79e87..29d8bafee7 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go @@ -13,7 +13,7 @@ func TestExists(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) require.NoError(t, s.Open(false)) require.NoError(t, s.Init()) - t.Cleanup(func() { require.NoError(t, s.Close()) }) + defer func() { require.NoError(t, s.Close()) }() objects := prepare(t, 1, s, min, max) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go index 9a7ebed09c..65c0c31337 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go @@ -14,7 +14,7 @@ func TestGet(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) require.NoError(t, s.Open(false)) require.NoError(t, s.Init()) - t.Cleanup(func() { require.NoError(t, s.Close()) }) + defer func() { require.NoError(t, s.Close()) }() objects := prepare(t, 2, s, min, max) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go index 1a9da07266..9b99c12d5e 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go @@ -16,7 +16,7 @@ func TestGetRange(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) require.NoError(t, s.Open(false)) require.NoError(t, s.Init()) - t.Cleanup(func() { require.NoError(t, s.Close()) }) + defer func() { require.NoError(t, s.Close()) }() objects := prepare(t, 1, s, min, max) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index 985ca01735..45c68cebca 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -13,7 +13,7 @@ func TestIterate(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) require.NoError(t, s.Open(false)) require.NoError(t, s.Init()) - t.Cleanup(func() { require.NoError(t, s.Close()) }) + defer func() { require.NoError(t, s.Close()) }() objects := prepare(t, 10, s, min, max) diff --git a/pkg/local_object_storage/blobstor/memstore/memstore_test.go b/pkg/local_object_storage/blobstor/memstore/memstore_test.go index cabf7f5add..bc9436350e 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore_test.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore_test.go @@ -17,7 +17,7 @@ func TestSimpleLifecycle(t *testing.T) { WithRootPath("memstore"), WithLogger(test.NewLogger(t)), ) - t.Cleanup(func() { _ = s.Close() }) + defer func() { require.NoError(t, s.Close()) }() require.NoError(t, s.Open(false)) require.NoError(t, s.Init()) diff --git a/pkg/local_object_storage/blobstor/perf_test.go b/pkg/local_object_storage/blobstor/perf_test.go index c773ea0eeb..72079acbab 100644 --- a/pkg/local_object_storage/blobstor/perf_test.go +++ b/pkg/local_object_storage/blobstor/perf_test.go @@ -25,10 +25,6 @@ func (s storage) open(b *testing.B) common.Storage { require.NoError(b, st.Open(false)) require.NoError(b, st.Init()) - b.Cleanup(func() { - require.NoError(b, st.Close()) - }) - return st } @@ -108,6 +104,7 @@ func BenchmarkSubstorageReadPerf(b *testing.B) { b.Run(fmt.Sprintf("%s-%s", stEntry.desc, tt.desc), func(b *testing.B) { objGen := tt.objGen() st := stEntry.open(b) + defer func() { require.NoError(b, st.Close()) }() // Fill database var errG errgroup.Group @@ -162,6 +159,7 @@ func BenchmarkSubstorageWritePerf(b *testing.B) { b.Run(fmt.Sprintf("%s-%s", stEntry.desc, genEntry.desc), func(b *testing.B) { gen := genEntry.create() st := stEntry.open(b) + defer func() { require.NoError(b, st.Close()) }() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { @@ -200,6 +198,7 @@ func BenchmarkSubstorageIteratePerf(b *testing.B) { b.Run(fmt.Sprintf("%s-%s", stEntry.desc, tt.desc), func(b *testing.B) { objGen := tt.objGen() st := stEntry.open(b) + defer func() { require.NoError(b, st.Close()) }() // Fill database for i := 0; i < tt.size; i++ { diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 41b7db91c1..cdaa41a510 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -122,6 +122,9 @@ func testEngineFailInitAndReload(t *testing.T, errOnAdd bool, opts []shard.Optio var configID string e := New() + defer func() { + require.NoError(t, e.Close(context.Background())) + }() _, err := e.AddShard(context.Background(), opts...) if errOnAdd { require.Error(t, err) @@ -258,6 +261,8 @@ func TestReload(t *testing.T) { require.Equal(t, shardNum+1, len(e.shards)) require.Equal(t, shardNum+1, len(e.shardPools)) + + require.NoError(t, e.Close(context.Background())) }) t.Run("remove shards", func(t *testing.T) { @@ -276,6 +281,8 @@ func TestReload(t *testing.T) { // removed one require.Equal(t, shardNum-1, len(e.shards)) require.Equal(t, shardNum-1, len(e.shardPools)) + + require.NoError(t, e.Close(context.Background())) }) } diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 063ea451e5..2b9cdcf847 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -2,7 +2,6 @@ package engine import ( "context" - "os" "path/filepath" "sync/atomic" "testing" @@ -49,10 +48,7 @@ func benchmarkExists(b *testing.B, shardNum int) { } e := testNewEngine(b).setInitializedShards(b, shards...).engine - b.Cleanup(func() { - _ = e.Close(context.Background()) - _ = os.RemoveAll(b.Name()) - }) + defer func() { require.NoError(b, e.Close(context.Background())) }() addr := oidtest.Address() for i := 0; i < 100; i++ { diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 3f343e5b92..77dbc9b7e8 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -114,6 +114,7 @@ func TestErrorReporting(t *testing.T) { checkShardState(t, te.ng, te.shards[0].id, i, mode.ReadWrite) checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) } + require.NoError(t, te.ng.Close(context.Background())) }) t.Run("with error threshold", func(t *testing.T) { const errThreshold = 3 @@ -161,6 +162,7 @@ func TestErrorReporting(t *testing.T) { require.NoError(t, te.ng.SetShardMode(te.shards[0].id, mode.ReadWrite, true)) checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite) + require.NoError(t, te.ng.Close(context.Background())) }) } diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 27c6c819fb..186c3e094b 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -80,9 +80,9 @@ func TestListWithCursor(t *testing.T) { require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) - t.Cleanup(func() { - e.Close(context.Background()) - }) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() expected := make([]object.AddressWithType, 0, tt.objectNum) got := make([]object.AddressWithType, 0, tt.objectNum) diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index ec18fc5e32..69b74f4a46 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -62,9 +62,7 @@ func TestLockUserScenario(t *testing.T) { require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) - t.Cleanup(func() { - _ = e.Close(context.Background()) - }) + defer func() { require.NoError(t, e.Close(context.Background())) }() lockerID := oidtest.ID() tombID := oidtest.ID() @@ -169,9 +167,7 @@ func TestLockExpiration(t *testing.T) { require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) - t.Cleanup(func() { - _ = e.Close(context.Background()) - }) + defer func() { require.NoError(t, e.Close(context.Background())) }() const lockerExpiresAfter = 13 @@ -246,9 +242,7 @@ func TestLockForceRemoval(t *testing.T) { }).engine require.NoError(t, e.Open(context.Background())) require.NoError(t, e.Init(context.Background())) - t.Cleanup(func() { - _ = e.Close(context.Background()) - }) + defer func() { require.NoError(t, e.Close(context.Background())) }() cnr := cidtest.ID() var err error diff --git a/pkg/local_object_storage/engine/shards_test.go b/pkg/local_object_storage/engine/shards_test.go index e13017e24e..f2896d5578 100644 --- a/pkg/local_object_storage/engine/shards_test.go +++ b/pkg/local_object_storage/engine/shards_test.go @@ -12,9 +12,7 @@ func TestRemoveShard(t *testing.T) { te := testNewEngine(t).setShardsNum(t, numOfShards) e, ids := te.engine, te.shardIDs - t.Cleanup(func() { - e.Close(context.Background()) - }) + defer func() { require.NoError(t, e.Close(context.Background())) }() require.Equal(t, numOfShards, len(e.shardPools)) require.Equal(t, numOfShards, len(e.shards)) diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index 4e2dd550db..e7762ded6b 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -19,6 +19,7 @@ func TestDB_Containers(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() const N = 10 @@ -96,6 +97,7 @@ func TestDB_ContainersCount(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() const R, T, SG, L = 10, 11, 12, 13 // amount of object per type @@ -141,6 +143,7 @@ func TestDB_ContainerSize(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() const ( C = 3 diff --git a/pkg/local_object_storage/metabase/control_test.go b/pkg/local_object_storage/metabase/control_test.go index 8f36423fd0..0354a5eb6e 100644 --- a/pkg/local_object_storage/metabase/control_test.go +++ b/pkg/local_object_storage/metabase/control_test.go @@ -15,6 +15,7 @@ import ( func TestReset(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() err := db.Reset() require.NoError(t, err) diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 4b7b565b3e..306bb0cc00 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -22,6 +22,7 @@ func TestCounters(t *testing.T) { t.Run("defaults", func(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() c, err := db.ObjectCounters() require.NoError(t, err) require.Zero(t, c.Phy) @@ -36,6 +37,7 @@ func TestCounters(t *testing.T) { t.Run("put", func(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() oo := make([]*objectSDK.Object, 0, objCount) for i := 0; i < objCount; i++ { oo = append(oo, testutil.GenerateObject()) @@ -73,6 +75,7 @@ func TestCounters(t *testing.T) { t.Run("delete", func(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() oo := putObjs(t, db, objCount, false) exp := make(map[cid.ID]meta.ObjectCounters) @@ -117,6 +120,7 @@ func TestCounters(t *testing.T) { t.Run("inhume", func(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() oo := putObjs(t, db, objCount, false) exp := make(map[cid.ID]meta.ObjectCounters) @@ -176,6 +180,7 @@ func TestCounters(t *testing.T) { t.Run("put_split", func(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() parObj := testutil.GenerateObject() exp := make(map[cid.ID]meta.ObjectCounters) @@ -213,6 +218,7 @@ func TestCounters(t *testing.T) { t.Run("delete_split", func(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() oo := putObjs(t, db, objCount, true) exp := make(map[cid.ID]meta.ObjectCounters) @@ -254,6 +260,7 @@ func TestCounters(t *testing.T) { t.Run("inhume_split", func(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() oo := putObjs(t, db, objCount, true) exp := make(map[cid.ID]meta.ObjectCounters) @@ -321,6 +328,7 @@ func TestCounters_Expired(t *testing.T) { es := &epochState{epoch} db := newDB(t, meta.WithEpochState(es)) + defer func() { require.NoError(t, db.Close()) }() oo := make([]oid.Address, objCount) for i := range oo { diff --git a/pkg/local_object_storage/metabase/db_test.go b/pkg/local_object_storage/metabase/db_test.go index b3c38f3d77..fc20e2aade 100644 --- a/pkg/local_object_storage/metabase/db_test.go +++ b/pkg/local_object_storage/metabase/db_test.go @@ -2,7 +2,6 @@ package meta_test import ( "context" - "os" "path/filepath" "strconv" "testing" @@ -53,11 +52,6 @@ func newDB(t testing.TB, opts ...meta.Option) *meta.DB { require.NoError(t, bdb.Open(context.Background(), false)) require.NoError(t, bdb.Init()) - t.Cleanup(func() { - bdb.Close() - os.Remove(bdb.DumpInfo().Path) - }) - return bdb } diff --git a/pkg/local_object_storage/metabase/delete_test.go b/pkg/local_object_storage/metabase/delete_test.go index 9b68f0bf8e..2ff6ba89f4 100644 --- a/pkg/local_object_storage/metabase/delete_test.go +++ b/pkg/local_object_storage/metabase/delete_test.go @@ -18,6 +18,7 @@ import ( func TestDB_Delete(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() parent := testutil.GenerateObjectWithCID(cnr) @@ -78,6 +79,7 @@ func TestDB_Delete(t *testing.T) { func TestDeleteAllChildren(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -115,6 +117,7 @@ func TestDeleteAllChildren(t *testing.T) { func TestGraveOnlyDelete(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() addr := oidtest.Address() @@ -127,6 +130,7 @@ func TestGraveOnlyDelete(t *testing.T) { func TestExpiredObject(t *testing.T) { db := newDB(t, meta.WithEpochState(epochState{currEpoch})) + defer func() { require.NoError(t, db.Close()) }() checkExpiredObjects(t, db, func(exp, nonExp *objectSDK.Object) { // removing expired object should be error-free diff --git a/pkg/local_object_storage/metabase/exists_test.go b/pkg/local_object_storage/metabase/exists_test.go index 06394339ab..0087c1e31d 100644 --- a/pkg/local_object_storage/metabase/exists_test.go +++ b/pkg/local_object_storage/metabase/exists_test.go @@ -18,6 +18,7 @@ const currEpoch = 1000 func TestDB_Exists(t *testing.T) { db := newDB(t, meta.WithEpochState(epochState{currEpoch})) + defer func() { require.NoError(t, db.Close()) }() t.Run("no object", func(t *testing.T) { nonExist := testutil.GenerateObject() diff --git a/pkg/local_object_storage/metabase/expired_test.go b/pkg/local_object_storage/metabase/expired_test.go index 9a6bcc5db9..bb98745ee0 100644 --- a/pkg/local_object_storage/metabase/expired_test.go +++ b/pkg/local_object_storage/metabase/expired_test.go @@ -13,6 +13,7 @@ import ( func TestDB_SelectExpired(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() containerID1 := cidtest.ID() diff --git a/pkg/local_object_storage/metabase/get_test.go b/pkg/local_object_storage/metabase/get_test.go index 98a4bd9605..af6b413274 100644 --- a/pkg/local_object_storage/metabase/get_test.go +++ b/pkg/local_object_storage/metabase/get_test.go @@ -22,6 +22,7 @@ import ( func TestDB_Get(t *testing.T) { db := newDB(t, meta.WithEpochState(epochState{currEpoch})) + defer func() { require.NoError(t, db.Close()) }() raw := testutil.GenerateObject() @@ -180,6 +181,7 @@ func benchmarkGet(b *testing.B, numOfObj int) { meta.WithMaxBatchSize(batchSize), meta.WithMaxBatchDelay(10*time.Millisecond), ) + defer func() { require.NoError(b, db.Close()) }() addrs := make([]oid.Address, 0, numOfObj) for i := 0; i < numOfObj; i++ { diff --git a/pkg/local_object_storage/metabase/graveyard_test.go b/pkg/local_object_storage/metabase/graveyard_test.go index 7476608f26..75c7e28524 100644 --- a/pkg/local_object_storage/metabase/graveyard_test.go +++ b/pkg/local_object_storage/metabase/graveyard_test.go @@ -14,6 +14,7 @@ import ( func TestDB_IterateDeletedObjects_EmptyDB(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() var counter int var iterGravePRM meta.GraveyardIterationPrm @@ -40,6 +41,7 @@ func TestDB_IterateDeletedObjects_EmptyDB(t *testing.T) { func TestDB_Iterate_OffsetNotFound(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() obj1 := testutil.GenerateObject() obj2 := testutil.GenerateObject() @@ -110,6 +112,7 @@ func TestDB_Iterate_OffsetNotFound(t *testing.T) { func TestDB_IterateDeletedObjects(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() // generate and put 4 objects obj1 := testutil.GenerateObject() @@ -196,6 +199,7 @@ func TestDB_IterateDeletedObjects(t *testing.T) { func TestDB_IterateOverGraveyard_Offset(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() // generate and put 4 objects obj1 := testutil.GenerateObject() @@ -294,6 +298,7 @@ func TestDB_IterateOverGraveyard_Offset(t *testing.T) { func TestDB_IterateOverGarbage_Offset(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() // generate and put 4 objects obj1 := testutil.GenerateObject() @@ -385,6 +390,7 @@ func TestDB_IterateOverGarbage_Offset(t *testing.T) { func TestDB_DropGraves(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() // generate and put 2 objects obj1 := testutil.GenerateObject() diff --git a/pkg/local_object_storage/metabase/inhume_test.go b/pkg/local_object_storage/metabase/inhume_test.go index 378e38e793..163fbec2ab 100644 --- a/pkg/local_object_storage/metabase/inhume_test.go +++ b/pkg/local_object_storage/metabase/inhume_test.go @@ -16,6 +16,7 @@ import ( func TestDB_Inhume(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() raw := testutil.GenerateObject() testutil.AddAttribute(raw, "foo", "bar") @@ -37,6 +38,7 @@ func TestDB_Inhume(t *testing.T) { func TestInhumeTombOnTomb(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() var ( err error @@ -99,6 +101,7 @@ func TestInhumeTombOnTomb(t *testing.T) { func TestInhumeLocked(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() locked := oidtest.Address() diff --git a/pkg/local_object_storage/metabase/iterators_test.go b/pkg/local_object_storage/metabase/iterators_test.go index 034a931d25..54d56d9231 100644 --- a/pkg/local_object_storage/metabase/iterators_test.go +++ b/pkg/local_object_storage/metabase/iterators_test.go @@ -17,6 +17,7 @@ import ( func TestDB_IterateExpired(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() const epoch = 13 @@ -68,6 +69,7 @@ func putWithExpiration(t *testing.T, db *meta.DB, typ objectSDK.Type, expiresAt func TestDB_IterateCoveredByTombstones(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() ts := oidtest.Address() protected1 := oidtest.Address() diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 3e598ed16d..25c0e35bd2 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -33,6 +33,7 @@ func listWithCursorPrepareDB(b *testing.B) *meta.DB { db := newDB(b, meta.WithMaxBatchSize(1), meta.WithBoltDBOptions(&bbolt.Options{ NoSync: true, })) // faster single-thread generation + defer func() { require.NoError(b, db.Close()) }() obj := testutil.GenerateObject() for i := 0; i < 100_000; i++ { // should be a multiple of all batch sizes @@ -70,6 +71,7 @@ func TestLisObjectsWithCursor(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() const ( containers = 5 @@ -165,6 +167,7 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() const total = 5 diff --git a/pkg/local_object_storage/metabase/lock_test.go b/pkg/local_object_storage/metabase/lock_test.go index 834ab07a7f..2d7bfc1cc5 100644 --- a/pkg/local_object_storage/metabase/lock_test.go +++ b/pkg/local_object_storage/metabase/lock_test.go @@ -21,6 +21,7 @@ func TestDB_Lock(t *testing.T) { cnr := cidtest.ID() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() t.Run("empty locked list", func(t *testing.T) { require.Panics(t, func() { _ = db.Lock(context.Background(), cnr, oid.ID{}, nil) }) @@ -182,6 +183,7 @@ func TestDB_Lock_Expired(t *testing.T) { es := &epochState{e: 123} db := newDB(t, meta.WithEpochState(es)) + defer func() { require.NoError(t, db.Close()) }() // put an object addr := putWithExpiration(t, db, objectSDK.TypeRegular, 124) @@ -203,6 +205,7 @@ func TestDB_IsLocked(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() // existing and locked objs diff --git a/pkg/local_object_storage/metabase/movable_test.go b/pkg/local_object_storage/metabase/movable_test.go index 51e7e6d745..d66d928673 100644 --- a/pkg/local_object_storage/metabase/movable_test.go +++ b/pkg/local_object_storage/metabase/movable_test.go @@ -13,6 +13,7 @@ import ( func TestDB_Movable(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() raw1 := testutil.GenerateObject() raw2 := testutil.GenerateObject() diff --git a/pkg/local_object_storage/metabase/put_test.go b/pkg/local_object_storage/metabase/put_test.go index a4cb2edc1f..28467199db 100644 --- a/pkg/local_object_storage/metabase/put_test.go +++ b/pkg/local_object_storage/metabase/put_test.go @@ -46,6 +46,7 @@ func BenchmarkPut(b *testing.B) { db := newDB(b, meta.WithMaxBatchDelay(time.Millisecond*10), meta.WithMaxBatchSize(runtime.NumCPU())) + defer func() { require.NoError(b, db.Close()) }() // Ensure the benchmark is bound by CPU and not waiting batch-delay time. b.SetParallelism(1) @@ -67,6 +68,7 @@ func BenchmarkPut(b *testing.B) { db := newDB(b, meta.WithMaxBatchDelay(time.Millisecond*10), meta.WithMaxBatchSize(1)) + defer func() { require.NoError(b, db.Close()) }() var index atomic.Int64 index.Store(-1) objs := prepareObjects(b, b.N) @@ -82,6 +84,7 @@ func BenchmarkPut(b *testing.B) { func TestDB_PutBlobovniczaUpdate(t *testing.T) { db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() raw1 := testutil.GenerateObject() storageID := []byte{1, 2, 3, 4} diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index e107085ab8..9ff2fd65ef 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -23,6 +23,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -147,6 +148,7 @@ func TestDB_SelectRootPhyParent(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -300,6 +302,7 @@ func TestDB_SelectInhume(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -334,6 +337,7 @@ func TestDB_SelectPayloadHash(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -404,6 +408,7 @@ func TestDB_SelectWithSlowFilters(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -511,6 +516,7 @@ func TestDB_SelectObjectID(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -626,6 +632,7 @@ func TestDB_SelectSplitID(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -682,6 +689,7 @@ func TestDB_SelectContainerID(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() @@ -729,6 +737,8 @@ func TestDB_SelectContainerID(t *testing.T) { func BenchmarkSelect(b *testing.B) { const objCount = 1000 db := newDB(b) + defer func() { require.NoError(b, db.Close()) }() + cid := cidtest.ID() for i := 0; i < objCount; i++ { @@ -769,6 +779,7 @@ func TestExpiredObjects(t *testing.T) { t.Parallel() db := newDB(t, meta.WithEpochState(epochState{currEpoch})) + defer func() { require.NoError(t, db.Close()) }() checkExpiredObjects(t, db, func(exp, nonExp *objectSDK.Object) { cidExp, _ := exp.ContainerID() diff --git a/pkg/local_object_storage/metabase/storage_id_test.go b/pkg/local_object_storage/metabase/storage_id_test.go index 63dbc2f3f3..063dfb2703 100644 --- a/pkg/local_object_storage/metabase/storage_id_test.go +++ b/pkg/local_object_storage/metabase/storage_id_test.go @@ -15,6 +15,7 @@ func TestDB_StorageID(t *testing.T) { t.Parallel() db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() raw1 := testutil.GenerateObject() raw2 := testutil.GenerateObject() diff --git a/pkg/local_object_storage/pilorama/bench_test.go b/pkg/local_object_storage/pilorama/bench_test.go index 3d5ff1a7ca..e3f3afd992 100644 --- a/pkg/local_object_storage/pilorama/bench_test.go +++ b/pkg/local_object_storage/pilorama/bench_test.go @@ -28,8 +28,9 @@ func BenchmarkCreate(b *testing.B) { WithMaxBatchSize(runtime.GOMAXPROCS(0))) require.NoError(b, f.Open(context.Background(), false)) require.NoError(b, f.Init()) + defer func() { require.NoError(b, f.Close()) }() + b.Cleanup(func() { - require.NoError(b, f.Close()) require.NoError(b, os.RemoveAll(tmpDir)) }) diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 67454b6861..5813395f0f 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -20,19 +20,15 @@ import ( var providers = []struct { name string - construct func(t testing.TB, opts ...Option) Forest + construct func(t testing.TB, opts ...Option) ForestStorage }{ - {"inmemory", func(t testing.TB, _ ...Option) Forest { + {"inmemory", func(t testing.TB, _ ...Option) ForestStorage { f := NewMemoryForest() require.NoError(t, f.Open(context.Background(), false)) require.NoError(t, f.Init()) - t.Cleanup(func() { - require.NoError(t, f.Close()) - }) - return f }}, - {"bbolt", func(t testing.TB, opts ...Option) Forest { + {"bbolt", func(t testing.TB, opts ...Option) ForestStorage { f := NewBoltForest( append([]Option{ WithPath(filepath.Join(t.TempDir(), "test.db")), @@ -40,9 +36,6 @@ var providers = []struct { }, opts...)...) require.NoError(t, f.Open(context.Background(), false)) require.NoError(t, f.Init()) - t.Cleanup(func() { - require.NoError(t, f.Close()) - }) return f }}, } @@ -62,7 +55,9 @@ func TestForest_TreeMove(t *testing.T) { } } -func testForestTreeMove(t *testing.T, s Forest) { +func testForestTreeMove(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} treeID := "version" @@ -124,7 +119,9 @@ func TestMemoryForest_TreeGetChildren(t *testing.T) { } } -func testForestTreeGetChildren(t *testing.T, s Forest) { +func testForestTreeGetChildren(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} treeID := "version" @@ -188,7 +185,9 @@ func TestForest_TreeDrop(t *testing.T) { } } -func testForestTreeDrop(t *testing.T, s Forest) { +func testForestTreeDrop(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + const cidsSize = 3 var cids [cidsSize]cidSDK.ID @@ -256,7 +255,9 @@ func TestForest_TreeAdd(t *testing.T) { } } -func testForestTreeAdd(t *testing.T, s Forest) { +func testForestTreeAdd(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} treeID := "version" @@ -302,7 +303,9 @@ func TestForest_TreeAddByPath(t *testing.T) { } } -func testForestTreeAddByPath(t *testing.T, s Forest) { +func testForestTreeAddByPath(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} treeID := "version" @@ -425,7 +428,7 @@ func TestForest_Apply(t *testing.T) { } } -func testForestTreeApply(t *testing.T, constructor func(t testing.TB, _ ...Option) Forest) { +func testForestTreeApply(t *testing.T, constructor func(t testing.TB, _ ...Option) ForestStorage) { cid := cidtest.ID() treeID := "version" @@ -439,6 +442,8 @@ func testForestTreeApply(t *testing.T, constructor func(t testing.TB, _ ...Optio t.Run("add a child, then insert a parent removal", func(t *testing.T) { s := constructor(t) + defer func() { require.NoError(t, s.Close()) }() + testApply(t, s, 10, 0, Meta{Time: 1, Items: []KeyValue{{"grand", []byte{1}}}}) meta := Meta{Time: 3, Items: []KeyValue{{"child", []byte{3}}}} @@ -450,6 +455,7 @@ func testForestTreeApply(t *testing.T, constructor func(t testing.TB, _ ...Optio }) t.Run("add a child to non-existent parent, then add a parent", func(t *testing.T) { s := constructor(t) + defer func() { require.NoError(t, s.Close()) }() meta := Meta{Time: 1, Items: []KeyValue{{"child", []byte{3}}}} testApply(t, s, 11, 10, meta) @@ -469,7 +475,7 @@ func TestForest_ApplySameOperation(t *testing.T) { } } -func testForestApplySameOperation(t *testing.T, constructor func(t testing.TB, _ ...Option) Forest, parallel bool) { +func testForestApplySameOperation(t *testing.T, constructor func(t testing.TB, _ ...Option) ForestStorage, parallel bool) { cid := cidtest.ID() treeID := "version" @@ -519,6 +525,8 @@ func testForestApplySameOperation(t *testing.T, constructor func(t testing.TB, _ t.Run("expected", func(t *testing.T) { s := constructor(t) + defer func() { require.NoError(t, s.Close()) }() + for i := range logs { require.NoError(t, s.TreeApply(ctx, cid, treeID, &logs[i], false)) } @@ -526,6 +534,8 @@ func testForestApplySameOperation(t *testing.T, constructor func(t testing.TB, _ }) s := constructor(t, WithMaxBatchSize(batchSize)) + defer func() { require.NoError(t, s.Close()) }() + require.NoError(t, s.TreeApply(ctx, cid, treeID, &logs[0], false)) for i := 0; i < batchSize; i++ { errG.Go(func() error { @@ -545,7 +555,7 @@ func TestForest_GetOpLog(t *testing.T) { } } -func testForestTreeGetOpLog(t *testing.T, constructor func(t testing.TB, _ ...Option) Forest) { +func testForestTreeGetOpLog(t *testing.T, constructor func(t testing.TB, _ ...Option) ForestStorage) { cid := cidtest.ID() treeID := "version" logs := []Move{ @@ -565,6 +575,7 @@ func testForestTreeGetOpLog(t *testing.T, constructor func(t testing.TB, _ ...Op } s := constructor(t) + defer func() { require.NoError(t, s.Close()) }() t.Run("empty log, no panic", func(t *testing.T) { _, err := s.TreeGetOpLog(context.Background(), cid, treeID, 0) @@ -603,8 +614,9 @@ func TestForest_TreeExists(t *testing.T) { } } -func testForestTreeExists(t *testing.T, constructor func(t testing.TB, opts ...Option) Forest) { +func testForestTreeExists(t *testing.T, constructor func(t testing.TB, opts ...Option) ForestStorage) { s := constructor(t) + defer func() { require.NoError(t, s.Close()) }() checkExists := func(t *testing.T, expected bool, cid cidSDK.ID, treeID string) { actual, err := s.TreeExists(context.Background(), cid, treeID) @@ -663,6 +675,8 @@ func TestApplyTricky1(t *testing.T) { for i := range providers { t.Run(providers[i].name, func(t *testing.T) { s := providers[i].construct(t) + defer func() { require.NoError(t, s.Close()) }() + for i := range ops { require.NoError(t, s.TreeApply(context.Background(), cid, treeID, &ops[i], false)) } @@ -724,6 +738,8 @@ func TestApplyTricky2(t *testing.T) { for i := range providers { t.Run(providers[i].name, func(t *testing.T) { s := providers[i].construct(t) + defer func() { require.NoError(t, s.Close()) }() + for i := range ops { require.NoError(t, s.TreeApply(context.Background(), cid, treeID, &ops[i], false)) } @@ -821,7 +837,7 @@ func compareForests(t *testing.T, expected, actual Forest, cid cidSDK.ID, treeID } } -func testForestTreeParallelApply(t *testing.T, constructor func(t testing.TB, _ ...Option) Forest, batchSize, opCount, iterCount int) { +func testForestTreeParallelApply(t *testing.T, constructor func(t testing.TB, _ ...Option) ForestStorage, batchSize, opCount, iterCount int) { r := mrand.New(mrand.NewSource(42)) const nodeCount = 5 @@ -832,6 +848,8 @@ func testForestTreeParallelApply(t *testing.T, constructor func(t testing.TB, _ treeID := "version" expected := constructor(t, WithNoSync(true)) + defer func() { require.NoError(t, expected.Close()) }() + for i := range ops { require.NoError(t, expected.TreeApply(context.Background(), cid, treeID, &ops[i], false)) } @@ -860,10 +878,11 @@ func testForestTreeParallelApply(t *testing.T, constructor func(t testing.TB, _ wg.Wait() compareForests(t, expected, actual, cid, treeID, nodeCount) + require.NoError(t, actual.Close()) } } -func testForestTreeApplyRandom(t *testing.T, constructor func(t testing.TB, _ ...Option) Forest) { +func testForestTreeApplyRandom(t *testing.T, constructor func(t testing.TB, _ ...Option) ForestStorage) { r := mrand.New(mrand.NewSource(42)) const ( @@ -877,6 +896,8 @@ func testForestTreeApplyRandom(t *testing.T, constructor func(t testing.TB, _ .. treeID := "version" expected := constructor(t, WithNoSync(true)) + defer func() { require.NoError(t, expected.Close()) }() + for i := range ops { require.NoError(t, expected.TreeApply(context.Background(), cid, treeID, &ops[i], false)) } @@ -891,6 +912,7 @@ func testForestTreeApplyRandom(t *testing.T, constructor func(t testing.TB, _ .. require.NoError(t, actual.TreeApply(context.Background(), cid, treeID, &ops[i], false)) } compareForests(t, expected, actual, cid, treeID, nodeCount) + require.NoError(t, actual.Close()) } } @@ -908,6 +930,8 @@ func BenchmarkApplySequential(b *testing.B) { b.Run("batchsize="+strconv.Itoa(bs), func(b *testing.B) { r := mrand.New(mrand.NewSource(time.Now().Unix())) s := providers[i].construct(b, WithMaxBatchSize(bs)) + defer func() { require.NoError(b, s.Close()) }() + benchmarkApply(b, s, func(opCount int) []Move { ops := make([]Move, opCount) for i := range ops { @@ -942,6 +966,8 @@ func BenchmarkApplyReorderLast(b *testing.B) { b.Run("batchsize="+strconv.Itoa(bs), func(b *testing.B) { r := mrand.New(mrand.NewSource(time.Now().Unix())) s := providers[i].construct(b, WithMaxBatchSize(bs)) + defer func() { require.NoError(b, s.Close()) }() + benchmarkApply(b, s, func(opCount int) []Move { ops := make([]Move, opCount) for i := range ops { @@ -996,7 +1022,8 @@ func TestTreeGetByPath(t *testing.T) { } } -func testTreeGetByPath(t *testing.T, s Forest) { +func testTreeGetByPath(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() cid := cidtest.ID() treeID := "version" @@ -1074,7 +1101,9 @@ func TestGetTrees(t *testing.T) { } } -func testTreeGetTrees(t *testing.T, s Forest) { +func testTreeGetTrees(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + cids := []cidSDK.ID{cidtest.ID(), cidtest.ID()} d := CIDDescriptor{Position: 0, Size: 1} @@ -1118,7 +1147,9 @@ func TestTreeLastSyncHeight(t *testing.T) { } } -func testTreeLastSyncHeight(t *testing.T, f Forest) { +func testTreeLastSyncHeight(t *testing.T, f ForestStorage) { + defer func() { require.NoError(t, f.Close()) }() + cnr := cidtest.ID() treeID := "someTree" diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index f7687e9610..9f205fa5dc 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -38,6 +38,7 @@ func TestShard_Delete_BigObject(t *testing.T) { func testShard(t *testing.T, hasWriteCache bool, payloadSize int) { sh := newShard(t, hasWriteCache) + defer func() { require.NoError(t, sh.Close()) }() cnr := cidtest.ID() diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index a82fc3ffe1..6a7941e040 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -78,10 +78,7 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { sh.gcCfg.testHookRemover = func(context.Context) gcRunResult { return gcRunResult{} } require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) - - t.Cleanup(func() { - require.NoError(t, sh.Close()) - }) + defer func() { require.NoError(t, sh.Close()) }() cnr := cidtest.ID() obj := testutil.GenerateObjectWithCID(cnr) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index 8b535200d8..bd8e0ac58b 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -31,6 +31,7 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { return util.NewPseudoWorkerPool() // synchronous event processing })}, }) + defer func() { require.NoError(t, sh.Close()) }() cnr := cidtest.ID() @@ -127,6 +128,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { return util.NewPseudoWorkerPool() // synchronous event processing })}, }) + defer func() { require.NoError(t, sh.Close()) }() lock := testutil.GenerateObjectWithCID(cnr) lock.SetType(objectSDK.TypeLock) diff --git a/pkg/local_object_storage/shard/get_test.go b/pkg/local_object_storage/shard/get_test.go index 19a5e8d701..8a7c6972d0 100644 --- a/pkg/local_object_storage/shard/get_test.go +++ b/pkg/local_object_storage/shard/get_test.go @@ -32,6 +32,7 @@ func TestShard_Get(t *testing.T) { func testShardGet(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) + defer func() { require.NoError(t, sh.Close()) }() var putPrm PutPrm var getPrm GetPrm diff --git a/pkg/local_object_storage/shard/head_test.go b/pkg/local_object_storage/shard/head_test.go index dfae48e840..1f46319939 100644 --- a/pkg/local_object_storage/shard/head_test.go +++ b/pkg/local_object_storage/shard/head_test.go @@ -30,6 +30,7 @@ func TestShard_Head(t *testing.T) { func testShardHead(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) + defer func() { require.NoError(t, sh.Close()) }() var putPrm PutPrm var headPrm HeadPrm diff --git a/pkg/local_object_storage/shard/inhume_test.go b/pkg/local_object_storage/shard/inhume_test.go index 6c8e46faf5..82754568fd 100644 --- a/pkg/local_object_storage/shard/inhume_test.go +++ b/pkg/local_object_storage/shard/inhume_test.go @@ -27,6 +27,7 @@ func TestShard_Inhume(t *testing.T) { func testShardInhume(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) + defer func() { require.NoError(t, sh.Close()) }() cnr := cidtest.ID() diff --git a/pkg/local_object_storage/shard/list_test.go b/pkg/local_object_storage/shard/list_test.go index 9ca1753c43..8a49a36fdd 100644 --- a/pkg/local_object_storage/shard/list_test.go +++ b/pkg/local_object_storage/shard/list_test.go @@ -18,12 +18,14 @@ func TestShard_List(t *testing.T) { t.Run("without write cache", func(t *testing.T) { t.Parallel() sh := newShard(t, false) + defer func() { require.NoError(t, sh.Close()) }() testShardList(t, sh) }) t.Run("with write cache", func(t *testing.T) { t.Parallel() shWC := newShard(t, true) + defer func() { require.NoError(t, shWC.Close()) }() testShardList(t, shWC) }) } diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index ca6b0ca382..91033efb75 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -61,9 +61,7 @@ func TestShard_Lock(t *testing.T) { require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) - t.Cleanup(func() { - releaseShard(sh, t) - }) + defer func() { require.NoError(t, sh.Close()) }() cnr := cidtest.ID() obj := testutil.GenerateObjectWithCID(cnr) @@ -149,6 +147,7 @@ func TestShard_Lock(t *testing.T) { func TestShard_IsLocked(t *testing.T) { sh := newShard(t, false) + defer func() { require.NoError(t, sh.Close()) }() cnr := cidtest.ID() obj := testutil.GenerateObjectWithCID(cnr) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 9c81c747d9..2ab99eed35 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -160,6 +160,7 @@ func TestCounters(t *testing.T) { dir := t.TempDir() sh, mm := shardWithMetrics(t, dir) + defer func() { require.NoError(t, sh.Close()) }() sh.SetMode(mode.ReadOnly) require.Equal(t, mode.ReadOnly, mm.mode) @@ -382,10 +383,6 @@ func shardWithMetrics(t *testing.T, path string) (*Shard, *metricsStore) { require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) - t.Cleanup(func() { - sh.Close() - }) - return sh, mm } diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 28bbd30e58..5a8a29e0c1 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -93,6 +93,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { }), }, }) + defer func() { require.NoError(t, sh.Close()) }() for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index c76fc1a002..511ce07210 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -57,6 +57,10 @@ func TestShardReload(t *testing.T) { require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) + defer func() { + require.NoError(t, sh.Close()) + }() + objects := make([]objAddr, 5) for i := range objects { objects[i].obj = newObject() diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 98d1c7b8e7..a5483f632e 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -30,7 +30,6 @@ func (s epochState) CurrentEpoch() uint64 { type shardOptions struct { rootPath string - dontRelease bool wcOpts []writecache.Option bsOpts []blobstor.Option metaOptions []meta.Option @@ -109,13 +108,5 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) - if !o.dontRelease { - t.Cleanup(func() { releaseShard(sh, t) }) - } - return sh } - -func releaseShard(s *Shard, t testing.TB) { - require.NoError(t, s.Close()) -} diff --git a/pkg/local_object_storage/shard/shutdown_test.go b/pkg/local_object_storage/shard/shutdown_test.go index b94ea50dc6..de00eabd11 100644 --- a/pkg/local_object_storage/shard/shutdown_test.go +++ b/pkg/local_object_storage/shard/shutdown_test.go @@ -39,7 +39,7 @@ func TestWriteCacheObjectLoss(t *testing.T) { writecache.WithMaxObjectSize(smallSize * 2), } - sh := newCustomShard(t, true, shardOptions{dontRelease: true, rootPath: dir, wcOpts: wcOpts}) + sh := newCustomShard(t, true, shardOptions{rootPath: dir, wcOpts: wcOpts}) var errG errgroup.Group for i := range objects { @@ -55,6 +55,7 @@ func TestWriteCacheObjectLoss(t *testing.T) { require.NoError(t, sh.Close()) sh = newCustomShard(t, true, shardOptions{rootPath: dir, wcOpts: wcOpts}) + defer func() { require.NoError(t, sh.Close()) }() var getPrm GetPrm diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index 727d0fc7a0..f7895a9357 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -28,6 +28,7 @@ func BenchmarkWritecachePar(b *testing.B) { func benchmarkPutSeq(b *testing.B, cache writecache.Cache, size uint64) { benchmarkPutPrepare(b, cache) + defer func() { require.NoError(b, cache.Close()) }() ctx := context.Background() objGen := testutil.RandObjGenerator{ObjSize: size} @@ -50,6 +51,7 @@ func benchmarkPutSeq(b *testing.B, cache writecache.Cache, size uint64) { func benchmarkPutPar(b *testing.B, cache writecache.Cache, size uint64) { benchmarkPutPrepare(b, cache) + defer func() { require.NoError(b, cache.Close()) }() ctx := context.Background() @@ -75,9 +77,6 @@ func benchmarkPutPar(b *testing.B, cache writecache.Cache, size uint64) { func benchmarkPutPrepare(b *testing.B, cache writecache.Cache) { require.NoError(b, cache.Open(context.Background(), false), "opening") require.NoError(b, cache.Init(), "initializing") - b.Cleanup(func() { - require.NoError(b, cache.Close(), "closing") - }) } type testMetabase struct{} diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index a358028e7c..bf68765d8f 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -142,6 +142,7 @@ func runFlushTest[Option any]( ) { t.Run("no errors", func(t *testing.T) { wc, bs, mb := newCache(t, createCacheFn, smallSize) + defer func() { require.NoError(t, wc.Close()) }() objects := putObjects(t, wc) require.NoError(t, bs.SetMode(mode.ReadWrite)) @@ -154,6 +155,7 @@ func runFlushTest[Option any]( t.Run("flush on moving to degraded mode", func(t *testing.T) { wc, bs, mb := newCache(t, createCacheFn, smallSize) + defer func() { require.NoError(t, wc.Close()) }() objects := putObjects(t, wc) // Blobstor is read-only, so we expect en error from `flush` here. @@ -172,6 +174,7 @@ func runFlushTest[Option any]( t.Run(f.Desc, func(t *testing.T) { errCountOpt, errCount := errCountOption() wc, bs, mb := newCache(t, createCacheFn, smallSize, errCountOpt) + defer func() { require.NoError(t, wc.Close()) }() objects := putObjects(t, wc) f.InjectFn(t, wc) @@ -214,7 +217,6 @@ func newCache[Option any]( require.NoError(t, bs.Init()) wc := createCacheFn(t, smallSize, mb, bs, opts...) - t.Cleanup(func() { require.NoError(t, wc.Close()) }) require.NoError(t, wc.Open(context.Background(), false)) require.NoError(t, wc.Init()) From 7166e77c2bc3c623ce990e39413ac8ef50e352f1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 9 Jan 2024 17:27:54 +0300 Subject: [PATCH 0256/1413] [#895] test: Add logger to test shard Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/control_test.go | 2 +- pkg/local_object_storage/engine/engine_test.go | 13 +++++++++---- pkg/local_object_storage/engine/list_test.go | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index cdaa41a510..0f36f3203f 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -298,7 +298,7 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str return []shard.Option{ shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( - blobstor.WithStorages(newStorages(filepath.Join(addPath, strconv.Itoa(id)), errSmallSize))), + blobstor.WithStorages(newStorages(t, filepath.Join(addPath, strconv.Itoa(id)), errSmallSize))), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(addPath, fmt.Sprintf("%d.metabase", id))), meta.WithPermissions(0o700), diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 2b9cdcf847..eb15a99006 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -133,14 +133,15 @@ func (te *testEngineWrapper) setShardsNumAdditionalOpts(t testing.TB, num int, s return te } -func newStorages(root string, smallSize uint64) []blobstor.SubStorage { +func newStorages(t testing.TB, root string, smallSize uint64) []blobstor.SubStorage { return []blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( blobovniczatree.WithRootPath(filepath.Join(root, "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1), - blobovniczatree.WithPermissions(0o700)), + blobovniczatree.WithPermissions(0o700), + blobovniczatree.WithLogger(test.NewLogger(t))), Policy: func(_ *objectSDK.Object, data []byte) bool { return uint64(len(data)) < smallSize }, @@ -148,7 +149,8 @@ func newStorages(root string, smallSize uint64) []blobstor.SubStorage { { Storage: fstree.New( fstree.WithPath(root), - fstree.WithDepth(1)), + fstree.WithDepth(1), + fstree.WithLogger(test.NewLogger(t))), }, } } @@ -197,12 +199,15 @@ func testDefaultShardOptions(t testing.TB, id int) []shard.Option { shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( blobstor.WithStorages( - newStorages(t.TempDir(), 1<<20))), + newStorages(t, t.TempDir(), 1<<20)), + blobstor.WithLogger(test.NewLogger(t)), + ), shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(t.TempDir(), "metabase")), meta.WithPermissions(0o700), meta.WithEpochState(epochState{}), + meta.WithLogger(test.NewLogger(t)), ), } } diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 186c3e094b..7bb1ac0fac 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -68,7 +68,7 @@ func TestListWithCursor(t *testing.T) { shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( blobstor.WithStorages( - newStorages(t.TempDir(), 1<<20))), + newStorages(t, t.TempDir(), 1<<20))), shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), shard.WithMetaBaseOptions( meta.WithPath(filepath.Join(t.TempDir(), "metabase")), From a2ab373a0ac5480b1400a4a0e95d920adc541447 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 10 Jan 2024 11:56:24 +0300 Subject: [PATCH 0257/1413] [#895] metabase: Do not delete GC mark for virtual objects Signed-off-by: Dmitrii Stepanov --- .../engine/delete_test.go | 92 +++++++++++++++++++ .../engine/engine_test.go | 4 +- pkg/local_object_storage/metabase/delete.go | 30 ++++-- pkg/local_object_storage/shard/shard.go | 8 ++ 4 files changed, 124 insertions(+), 10 deletions(-) diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index f3e4a09767..32d07809a4 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" @@ -85,6 +86,97 @@ func TestDeleteBigObject(t *testing.T) { } } +func TestDeleteBigObjectWithoutGC(t *testing.T) { + t.Parallel() + + cnr := cidtest.ID() + parentID := oidtest.ID() + splitID := objectSDK.NewSplitID() + + parent := testutil.GenerateObjectWithCID(cnr) + parent.SetID(parentID) + parent.SetPayload(nil) + + const childCount = 3 + children := make([]*objectSDK.Object, childCount) + childIDs := make([]oid.ID, childCount) + for i := range children { + children[i] = testutil.GenerateObjectWithCID(cnr) + if i != 0 { + children[i].SetPreviousID(childIDs[i-1]) + } + if i == len(children)-1 { + children[i].SetParent(parent) + } + children[i].SetSplitID(splitID) + children[i].SetPayload([]byte{byte(i), byte(i + 1), byte(i + 2)}) + childIDs[i], _ = children[i].ID() + } + + link := testutil.GenerateObjectWithCID(cnr) + link.SetParent(parent) + link.SetParentID(parentID) + link.SetSplitID(splitID) + link.SetChildren(childIDs...) + + s1 := testNewShard(t, 1, shard.WithDisabledGC()) + + e := testNewEngine(t).setInitializedShards(t, s1).engine + e.log = test.NewLogger(t) + defer e.Close(context.Background()) + + for i := range children { + require.NoError(t, Put(context.Background(), e, children[i])) + } + require.NoError(t, Put(context.Background(), e, link)) + + addrParent := object.AddressOf(parent) + checkGetError[*objectSDK.SplitInfoError](t, e, addrParent, true) + + addrLink := object.AddressOf(link) + checkGetError[error](t, e, addrLink, false) + + for i := range children { + checkGetError[error](t, e, object.AddressOf(children[i]), false) + } + + // delete logical + var deletePrm DeletePrm + deletePrm.WithForceRemoval() + deletePrm.WithAddress(addrParent) + + _, err := e.Delete(context.Background(), deletePrm) + require.NoError(t, err) + + checkGetError[*apistatus.ObjectNotFound](t, e, addrParent, true) + checkGetError[*apistatus.ObjectNotFound](t, e, addrLink, true) + for i := range children { + checkGetError[*apistatus.ObjectNotFound](t, e, object.AddressOf(children[i]), true) + } + + // delete physical + var delPrm shard.DeletePrm + delPrm.SetAddresses(addrParent) + _, err = s1.Delete(context.Background(), delPrm) + require.NoError(t, err) + + delPrm.SetAddresses(addrLink) + _, err = s1.Delete(context.Background(), delPrm) + require.NoError(t, err) + + for i := range children { + delPrm.SetAddresses(object.AddressOf(children[i])) + _, err = s1.Delete(context.Background(), delPrm) + require.NoError(t, err) + } + + checkGetError[*apistatus.ObjectNotFound](t, e, addrParent, true) + checkGetError[*apistatus.ObjectNotFound](t, e, addrLink, true) + for i := range children { + checkGetError[*apistatus.ObjectNotFound](t, e, object.AddressOf(children[i]), true) + } +} + func checkGetError[E error](t *testing.T, e *StorageEngine, addr oid.Address, shouldFail bool) { var getPrm GetPrm getPrm.WithAddress(addr) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index eb15a99006..a62734c0a3 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -181,12 +181,12 @@ func newTestStorages(root string, smallSize uint64) ([]blobstor.SubStorage, *tes }, smallFileStorage, largeFileStorage } -func testNewShard(t testing.TB, id int) *shard.Shard { +func testNewShard(t testing.TB, id int, opts ...shard.Option) *shard.Shard { sid, err := generateShardID() require.NoError(t, err) shardOpts := append([]shard.Option{shard.WithID(sid)}, testDefaultShardOptions(t, id)...) - s := shard.New(shardOpts...) + s := shard.New(append(shardOpts, opts...)...) require.NoError(t, s.Open(context.Background())) require.NoError(t, s.Init(context.Background())) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index b2210b55c6..8ca0dea616 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -251,26 +251,27 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter removeAvailableObject := inGraveyardWithKey(addrKey, graveyardBKT, garbageBKT) == 0 - // remove record from the garbage bucket - if garbageBKT != nil { - err := garbageBKT.Delete(addrKey) - if err != nil { - return deleteSingleResult{}, fmt.Errorf("could not remove from garbage bucket: %w", err) - } - } - // unmarshal object, work only with physically stored (raw == true) objects obj, err := db.get(tx, addr, key, false, true, currEpoch) if err != nil { var siErr *objectSDK.SplitInfoError if client.IsErrObjectNotFound(err) || errors.As(err, &siErr) { + // if object is virtual (parent) then do nothing, it will be deleted with last child return deleteSingleResult{}, nil } return deleteSingleResult{}, err } + // remove record from the garbage bucket + if garbageBKT != nil { + err := garbageBKT.Delete(addrKey) + if err != nil { + return deleteSingleResult{}, fmt.Errorf("could not remove from garbage bucket: %w", err) + } + } + // if object is an only link to a parent, then remove parent if parent := obj.Parent(); parent != nil { parAddr := object.AddressOf(parent) @@ -327,6 +328,19 @@ func (db *DB) deleteObject( return fmt.Errorf("can't remove fake bucket tree indexes: %w", err) } + if isParent { + // remove record from the garbage bucket, because regular object deletion does nothing for virtual object + garbageBKT := tx.Bucket(garbageBucketName) + if garbageBKT != nil { + key := make([]byte, addressKeySize) + addrKey := addressKey(object.AddressOf(obj), key) + err := garbageBKT.Delete(addrKey) + if err != nil { + return fmt.Errorf("could not remove from garbage bucket: %w", err) + } + } + } + return nil } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 13f7f689b3..136f5463a1 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -371,6 +371,14 @@ func WithRebuildWorkerLimiter(l RebuildWorkerLimiter) Option { } } +// WithDisabledGC disables GC. +// For testing purposes only. +func WithDisabledGC() Option { + return func(c *cfg) { + c.gcCfg.testHookRemover = func(ctx context.Context) gcRunResult { return gcRunResult{} } + } +} + // WithZeroSizeCallback returns option to set zero-size containers callback. func WithZeroSizeCallback(cb EmptyContainersCallback) Option { return func(c *cfg) { From be8607a1f6039e782535015a428c578945e12a7d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 11 Jan 2024 13:47:17 +0300 Subject: [PATCH 0258/1413] [#902] morph: Avoid creating session in TestInvokeIterator When the number of items to iterate over is less than 2048, there is no need to create a session and consume resources. Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/client.go | 53 +++++++++++++++++---- pkg/morph/client/container/containers_of.go | 2 +- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index e52adfa8e4..0c8544bd05 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -13,6 +13,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "github.com/google/uuid" lru "github.com/hashicorp/golang-lru/v2" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -24,8 +25,10 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/rpcclient/rolemgmt" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "github.com/nspcc-dev/neo-go/pkg/wallet" @@ -204,16 +207,27 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, return vub, nil } +// defaultPrefetchBatchSize is the default number of items to prefetch. +// It is dependent on VM limits (2048 items on stack), the default works for simple items. +// For example, to iterate over 2 field structs, the limit should be divided by 3 = 1 (struct itself) + 2 (fields). +const defaultPrefetchBatchSize = vm.MaxStackSize - 16 + // TestInvokeIterator invokes contract method returning an iterator and executes cb on each element. // If cb returns an error, the session is closed and this error is returned as-is. // If the remove neo-go node does not support sessions, `unwrap.ErrNoSessionID` is returned. -func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, contract util.Uint160, method string, args ...interface{}) error { +// batchSize is the number of items to prefetch: if the number of items in the iterator is less than batchSize, no session will be created. +// The default batchSize is 2000 (VM is limited by having 2048 items on stack, so if each iterator item is simple, 2000 items won't hit the limit). +func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int, contract util.Uint160, method string, args ...interface{}) error { start := time.Now() success := false defer func() { c.metrics.ObserveInvoke("TestInvokeIterator", contract.String(), method, success, time.Since(start)) }() + if batchSize <= 0 { + batchSize = defaultPrefetchBatchSize + } + c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -221,34 +235,53 @@ func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, contract util return ErrConnectionLost } - val, err := c.rpcActor.Call(contract, method, args...) + script, err := smartcontract.CreateCallAndPrefetchIteratorScript(contract, method, batchSize, args...) + if err != nil { + return err + } + + val, err := c.rpcActor.Run(script) if err != nil { return err } else if val.State != HaltState { return wrapFrostFSError(¬HaltStateError{state: val.State, exception: val.FaultException}) } - sid, r, err := unwrap.SessionIterator(val, err) + arr, sid, r, err := unwrap.ArrayAndSessionIterator(val, err) if err != nil { return err } + for i := range arr { + if err := cb(arr[i]); err != nil { + return err + } + } + if (sid == uuid.UUID{}) { + success = true + return nil + } defer func() { _ = c.rpcActor.TerminateSession(sid) }() - items, err := c.rpcActor.TraverseIterator(sid, &r, 0) - for err == nil && len(items) != 0 { + for { + items, err := c.rpcActor.TraverseIterator(sid, &r, batchSize) + if err != nil { + return err + } + for i := range items { - if err = cb(items[i]); err != nil { + if err := cb(items[i]); err != nil { return err } } - items, err = c.rpcActor.TraverseIterator(sid, &r, 0) + if len(items) < batchSize { + break + } } - - success = err == nil - return err + success = true + return nil } // TestInvoke invokes contract method locally in neo-go node. This method should diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go index 8a3c7220f3..140047eb27 100644 --- a/pkg/morph/client/container/containers_of.go +++ b/pkg/morph/client/container/containers_of.go @@ -41,7 +41,7 @@ func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { } cnrHash := c.client.ContractAddress() - err := c.client.Morph().TestInvokeIterator(cb, cnrHash, containersOfMethod, rawID) + err := c.client.Morph().TestInvokeIterator(cb, 0, cnrHash, containersOfMethod, rawID) if err != nil { if errors.Is(err, unwrap.ErrNoSessionID) { return c.List(idUser) From a6013917194960d1f44bf322877e6d9f99d21958 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 11 Jan 2024 14:04:56 +0300 Subject: [PATCH 0259/1413] [#902] adm: Do not create session when dumping hashes Unless the total number of domains is too big, there is no need to consume resources in neo-go. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/dump_hashes.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index 0a112f35c1..14a492c5fe 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -13,6 +13,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" @@ -143,7 +144,12 @@ func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, }) } - sessionID, iter, err := unwrap.SessionIterator(inv.Call(nnsHash, "tokens")) + script, err := smartcontract.CreateCallAndPrefetchIteratorScript(nnsHash, "tokens", nnsMaxTokens) + if err != nil { + return fmt.Errorf("create prefetch script: %w", err) + } + + arr, sessionID, iter, err := unwrap.ArrayAndSessionIterator(inv.Run(script)) if err != nil { if errors.Is(err, unwrap.ErrNoSessionID) { items, err := unwrap.Array(inv.CallAndExpandIterator(nnsHash, "tokens", nnsMaxTokens)) @@ -160,6 +166,10 @@ func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, return err } } else { + for i := range arr { + processItem(arr[i]) + } + defer func() { _ = inv.TerminateSession(sessionID) }() From 394f086fe2c7e56731b13ba1123bc12e71e779bb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 12 Jan 2024 09:56:13 +0300 Subject: [PATCH 0260/1413] [#891] getSvc: Fix get range hash implementation Get range can perform GET request, so this request must be done from container node to not to get access denied error. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 10 +- internal/logs/logs.go | 4 + pkg/services/object/get/v2/get_range_hash.go | 215 ++++++++++++++++++ pkg/services/object/get/v2/service.go | 76 +++++-- .../object_manager/placement/traverser.go | 9 + 5 files changed, 297 insertions(+), 17 deletions(-) create mode 100644 pkg/services/object/get/v2/get_range_hash.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index e84696e6b4..a47ea26542 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -176,7 +176,7 @@ func initObjectService(c *cfg) { *c.cfgObject.getSvc = *sGet // need smth better - sGetV2 := createGetServiceV2(sGet, keyStorage) + sGetV2 := createGetServiceV2(c, sGet, keyStorage) sDelete := createDeleteService(c, keyStorage, sGet, sSearch, sPut) @@ -370,10 +370,16 @@ func createGetService(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.Tra getsvc.WithLogger(c.log)) } -func createGetServiceV2(sGet *getsvc.Service, keyStorage *util.KeyStorage) *getsvcV2.Service { +func createGetServiceV2(c *cfg, sGet *getsvc.Service, keyStorage *util.KeyStorage) *getsvcV2.Service { return getsvcV2.NewService( getsvcV2.WithInternalService(sGet), getsvcV2.WithKeyStorage(keyStorage), + getsvcV2.WithEpochSource(c.netMapSource), + getsvcV2.WithClientSource(c.clientCache), + getsvcV2.WithContainerSource(c.cfgObject.cnrSource), + getsvcV2.WithNetmapSource(c.netMapSource), + getsvcV2.WithNetmapAnnouncedKeys(c), + getsvcV2.WithLogger(c.log), ) } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 420c6612a5..606b5cb9a8 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -567,4 +567,8 @@ const ( EngineInterruptProcessingZeroSizeContainers = "interrupt processing zero-size containers" EngineInterruptProcessingZeroCountContainers = "interrupt processing zero-count containers" EngineFailedToGetContainerCounters = "failed to get container counters" + GetSvcV2FailedToParseNodeEndpoints = "failed to parse node endpoints" + GetSvcV2FailedToParseNodeExternalAddresses = "failed to parse node external addresses" + GetSvcV2FailedToGetRangeHashFromNode = "failed to get range hash from node" + GetSvcV2FailedToGetRangeHashFromAllOfContainerNodes = "failed to get range hash from all of container nodes" ) diff --git a/pkg/services/object/get/v2/get_range_hash.go b/pkg/services/object/get/v2/get_range_hash.go new file mode 100644 index 0000000000..d2ed16ebf5 --- /dev/null +++ b/pkg/services/object/get/v2/get_range_hash.go @@ -0,0 +1,215 @@ +package getsvc + +import ( + "context" + "encoding/hex" + "fmt" + + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + clientCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.uber.org/zap" +) + +// GetRangeHash calls internal service and returns v2 response. +func (s *Service) GetRangeHash(ctx context.Context, req *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) { + forward, err := s.needToForwardGetRangeHashRequest(req) + if err != nil { + return nil, err + } + if forward.needToForward { + return s.forwardGetRangeHashRequest(ctx, req, forward) + } + p, err := s.toHashRangePrm(req) + if err != nil { + return nil, err + } + + res, err := s.svc.GetRangeHash(ctx, *p) + if err != nil { + return nil, err + } + + return toHashResponse(req.GetBody().GetType(), res), nil +} + +type getRangeForwardParams struct { + needToForward bool + containerNodes []netmapSDK.NodeInfo + address oid.Address +} + +func (s *Service) needToForwardGetRangeHashRequest(req *objectV2.GetRangeHashRequest) (getRangeForwardParams, error) { + if req.GetMetaHeader().GetTTL() <= 1 { + return getRangeForwardParams{}, nil + } + + var result getRangeForwardParams + addrV2 := req.GetBody().GetAddress() + if addrV2 == nil { + return result, errMissingObjAddress + } + + var addr oid.Address + err := addr.ReadFromV2(*addrV2) + if err != nil { + return result, errInvalidObjAddress(err) + } + result.address = addr + + cont, err := s.contSource.Get(addr.Container()) + if err != nil { + return result, fmt.Errorf("(%T) could not get container: %w", s, err) + } + + epoch, err := s.epochSource.Epoch() + if err != nil { + return result, fmt.Errorf("(%T) could not get epoch: %w", s, err) + } + + nm, err := s.netmapSource.GetNetMapByEpoch(epoch) + if err != nil { + return result, fmt.Errorf("(%T) could not get netmap: %w", s, err) + } + + builder := placement.NewNetworkMapBuilder(nm) + + objectID := addr.Object() + nodesVector, err := builder.BuildPlacement(addr.Container(), &objectID, cont.Value.PlacementPolicy()) + if err != nil { + return result, fmt.Errorf("(%T) could not build object placement: %w", s, err) + } + result.containerNodes = distinctBy(placement.FlattenNodes(nodesVector), func(n netmapSDK.NodeInfo) string { return hex.EncodeToString(n.PublicKey()) }) + + for _, node := range result.containerNodes { + if s.announcedKeys.IsLocalKey(node.PublicKey()) { + return result, nil + } + } + result.needToForward = true + return result, nil +} + +func (s *Service) forwardGetRangeHashRequest(ctx context.Context, req *objectV2.GetRangeHashRequest, params getRangeForwardParams) (*objectV2.GetRangeHashResponse, error) { + key, err := s.keyStorage.GetKey(nil) + if err != nil { + return nil, err + } + + metaHdr := new(session.RequestMetaHeader) + metaHdr.SetTTL(req.GetMetaHeader().GetTTL() - 1) + metaHdr.SetOrigin(req.GetMetaHeader()) + writeCurrentVersion(metaHdr) + req.SetMetaHeader(metaHdr) + + if err := signature.SignServiceMessage(key, req); err != nil { + return nil, err + } + + var firstErr error + for _, node := range params.containerNodes { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + + var addrGr network.AddressGroup + if err := addrGr.FromIterator(network.NodeEndpointsIterator(node)); err != nil { + s.log.Warn(logs.GetSvcV2FailedToParseNodeEndpoints, zap.String("node_public_key", hex.EncodeToString(node.PublicKey()))) + continue + } + + var extAddr network.AddressGroup + if len(node.ExternalAddresses()) > 0 { + if err := extAddr.FromStringSlice(node.ExternalAddresses()); err != nil { + s.log.Warn(logs.GetSvcV2FailedToParseNodeExternalAddresses, zap.String("node_public_key", hex.EncodeToString(node.PublicKey()))) + continue + } + } + + var info clientCore.NodeInfo + clientCore.NodeInfoFromNetmapElement(&info, placement.NewNode(addrGr, extAddr, node.PublicKey())) + + resp, err := s.performGetRangeHashOnNode(ctx, req, info) + if err == nil { + return resp, nil + } + if firstErr == nil { + firstErr = err + } + s.log.Debug(logs.GetSvcV2FailedToGetRangeHashFromNode, + zap.String("node_public_key", hex.EncodeToString(node.PublicKey())), + zap.Stringer("address", params.address), + zap.Error(err)) + } + s.log.Debug(logs.GetSvcV2FailedToGetRangeHashFromAllOfContainerNodes, zap.Stringer("address", params.address), zap.Error(firstErr)) + if firstErr != nil { + return nil, firstErr + } + return nil, new(apistatus.ObjectNotFound) +} + +func (s *Service) performGetRangeHashOnNode(ctx context.Context, req *objectV2.GetRangeHashRequest, info clientCore.NodeInfo) (*objectV2.GetRangeHashResponse, error) { + cl, err := s.clientSource.Get(info) + if err != nil { + return nil, err + } + + var firstErr error + var resp *objectV2.GetRangeHashResponse + info.AddressGroup().IterateAddresses(func(a network.Address) bool { + resp, err = s.performGetRangeHashOnAddress(ctx, req, cl, a) + if err != nil { + if firstErr == nil { + firstErr = err + } + return false + } + return true + }) + if firstErr != nil { + return nil, firstErr + } + if resp == nil { + return nil, new(apistatus.ObjectNotFound) + } + return resp, nil +} + +func (s *Service) performGetRangeHashOnAddress(ctx context.Context, req *objectV2.GetRangeHashRequest, cl clientCore.MultiAddressClient, + a network.Address, +) (*objectV2.GetRangeHashResponse, error) { + var resp *objectV2.GetRangeHashResponse + var rpcErr error + err := cl.RawForAddress(ctx, a, func(cli *rpcclient.Client) error { + resp, rpcErr = rpc.HashObjectRange(cli, req, rpcclient.WithContext(ctx)) + return rpcErr + }) + if err != nil { + return nil, err + } + return resp, err +} + +func distinctBy[T any, K comparable](source []T, keySelector func(v T) K) []T { + var result []T + dict := make(map[K]struct{}) + for _, v := range source { + key := keySelector(v) + if _, exists := dict[key]; !exists { + result = append(result, v) + dict[key] = struct{}{} + } + } + return result +} diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index d4bce178af..07fe9b42ad 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -5,10 +5,15 @@ import ( "errors" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "go.uber.org/zap" ) // Service implements Get operation of Object service v2. @@ -19,10 +24,30 @@ type Service struct { // Option represents Service constructor option. type Option func(*cfg) +type epochSource interface { + Epoch() (uint64, error) +} + +type clientSource interface { + Get(info clientcore.NodeInfo) (clientcore.MultiAddressClient, error) +} + type cfg struct { svc *getsvc.Service keyStorage *objutil.KeyStorage + + epochSource epochSource + + clientSource clientSource + + netmapSource netmap.Source + + announcedKeys netmap.AnnouncedKeys + + contSource container.Source + + log *logger.Logger } // NewService constructs Service instance from provided options. @@ -76,21 +101,6 @@ func (s *Service) GetRange(req *objectV2.GetRangeRequest, stream objectSvc.GetOb } } -// GetRangeHash calls internal service and returns v2 response. -func (s *Service) GetRangeHash(ctx context.Context, req *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) { - p, err := s.toHashRangePrm(req) - if err != nil { - return nil, err - } - - res, err := s.svc.GetRangeHash(ctx, *p) - if err != nil { - return nil, err - } - - return toHashResponse(req.GetBody().GetType(), res), nil -} - // Head serves ForstFS API v2 compatible HEAD requests. func (s *Service) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { resp := new(objectV2.HeadResponse) @@ -125,3 +135,39 @@ func WithKeyStorage(ks *objutil.KeyStorage) Option { c.keyStorage = ks } } + +func WithEpochSource(es epochSource) Option { + return func(c *cfg) { + c.epochSource = es + } +} + +func WithClientSource(cs clientSource) Option { + return func(c *cfg) { + c.clientSource = cs + } +} + +func WithNetmapSource(ns netmap.Source) Option { + return func(c *cfg) { + c.netmapSource = ns + } +} + +func WithNetmapAnnouncedKeys(ak netmap.AnnouncedKeys) Option { + return func(c *cfg) { + c.announcedKeys = ak + } +} + +func WithContainerSource(cs container.Source) Option { + return func(c *cfg) { + c.contSource = cs + } +} + +func WithLogger(l *logger.Logger) Option { + return func(c *cfg) { + c.log = &logger.Logger{Logger: l.With(zap.String("component", "Object.Get V2 service"))} + } +} diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index dc9ab5e7a8..53da186e84 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -181,6 +181,15 @@ func (x Node) PublicKey() []byte { return x.key } +// NewNode creates new Node. +func NewNode(addresses network.AddressGroup, externalAddresses network.AddressGroup, key []byte) Node { + return Node{ + addresses: addresses, + externalAddresses: externalAddresses, + key: key, + } +} + // Next returns next unprocessed address of the object placement. // // Returns nil if no nodes left or traversal operation succeeded. From 52ffa9f1642fdee6c94a677c3202c55c9a654845 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 12 Jan 2024 10:05:29 +0300 Subject: [PATCH 0261/1413] [#891] getSvc: Refactor Get service V2 creation Use arguments for mandatory fields. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 13 ++-- pkg/services/object/get/v2/get_range_hash.go | 2 +- pkg/services/object/get/v2/service.go | 68 +++++--------------- 3 files changed, 24 insertions(+), 59 deletions(-) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index a47ea26542..2d18f82a3d 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -372,13 +372,12 @@ func createGetService(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.Tra func createGetServiceV2(c *cfg, sGet *getsvc.Service, keyStorage *util.KeyStorage) *getsvcV2.Service { return getsvcV2.NewService( - getsvcV2.WithInternalService(sGet), - getsvcV2.WithKeyStorage(keyStorage), - getsvcV2.WithEpochSource(c.netMapSource), - getsvcV2.WithClientSource(c.clientCache), - getsvcV2.WithContainerSource(c.cfgObject.cnrSource), - getsvcV2.WithNetmapSource(c.netMapSource), - getsvcV2.WithNetmapAnnouncedKeys(c), + sGet, + keyStorage, + c.clientCache, + c.netMapSource, + c, + c.cfgObject.cnrSource, getsvcV2.WithLogger(c.log), ) } diff --git a/pkg/services/object/get/v2/get_range_hash.go b/pkg/services/object/get/v2/get_range_hash.go index d2ed16ebf5..0054f0e9f6 100644 --- a/pkg/services/object/get/v2/get_range_hash.go +++ b/pkg/services/object/get/v2/get_range_hash.go @@ -71,7 +71,7 @@ func (s *Service) needToForwardGetRangeHashRequest(req *objectV2.GetRangeHashReq return result, fmt.Errorf("(%T) could not get container: %w", s, err) } - epoch, err := s.epochSource.Epoch() + epoch, err := s.netmapSource.Epoch() if err != nil { return result, fmt.Errorf("(%T) could not get epoch: %w", s, err) } diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index 07fe9b42ad..bcdc4120e9 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -24,10 +24,6 @@ type Service struct { // Option represents Service constructor option. type Option func(*cfg) -type epochSource interface { - Epoch() (uint64, error) -} - type clientSource interface { Get(info clientcore.NodeInfo) (clientcore.MultiAddressClient, error) } @@ -37,8 +33,6 @@ type cfg struct { keyStorage *objutil.KeyStorage - epochSource epochSource - clientSource clientSource netmapSource netmap.Source @@ -51,8 +45,23 @@ type cfg struct { } // NewService constructs Service instance from provided options. -func NewService(opts ...Option) *Service { - c := new(cfg) +func NewService(svc *getsvc.Service, + keyStorage *objutil.KeyStorage, + clientSource clientSource, + netmapSource netmap.Source, + announcedKeys netmap.AnnouncedKeys, + contSource container.Source, + opts ...Option, +) *Service { + c := &cfg{ + svc: svc, + keyStorage: keyStorage, + clientSource: clientSource, + netmapSource: netmapSource, + announcedKeys: announcedKeys, + contSource: contSource, + log: &logger.Logger{Logger: zap.L()}, + } for i := range opts { opts[i](c) @@ -123,49 +132,6 @@ func (s *Service) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV return resp, err } -func WithInternalService(v *getsvc.Service) Option { - return func(c *cfg) { - c.svc = v - } -} - -// WithKeyStorage returns option to set local private key storage. -func WithKeyStorage(ks *objutil.KeyStorage) Option { - return func(c *cfg) { - c.keyStorage = ks - } -} - -func WithEpochSource(es epochSource) Option { - return func(c *cfg) { - c.epochSource = es - } -} - -func WithClientSource(cs clientSource) Option { - return func(c *cfg) { - c.clientSource = cs - } -} - -func WithNetmapSource(ns netmap.Source) Option { - return func(c *cfg) { - c.netmapSource = ns - } -} - -func WithNetmapAnnouncedKeys(ak netmap.AnnouncedKeys) Option { - return func(c *cfg) { - c.announcedKeys = ak - } -} - -func WithContainerSource(cs container.Source) Option { - return func(c *cfg) { - c.contSource = cs - } -} - func WithLogger(l *logger.Logger) Option { return func(c *cfg) { c.log = &logger.Logger{Logger: l.With(zap.String("component", "Object.Get V2 service"))} From e43609c61622af953028d2c7743e06c0e3b688e8 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Fri, 12 Jan 2024 12:02:11 +0300 Subject: [PATCH 0262/1413] [#885] go.mod: Update APE Signed-off-by: Denis Kirillov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 82ad0212da..ddf587ad5f 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231221121354-ed93bb5cc574 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240112075604-c80c99b13e53 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 diff --git a/go.sum b/go.sum index 75d2487c49..9be0e55cd8 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231221121354-ed93bb5cc574 h1:PmPaHc4P/Rjn1WQcDF5gcwILzWjkMOuRHLqzm9OZCdA= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20231221121354-ed93bb5cc574/go.mod h1:ps6oKO0mxaPJzK3admTB3iwoBXKkHnS73n4PCrqpHBg= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240112075604-c80c99b13e53 h1:LNfUfiGx3cECl15Q5ZspILWZriCeevH4Ue+eynKgGYQ= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240112075604-c80c99b13e53/go.mod h1:ps6oKO0mxaPJzK3admTB3iwoBXKkHnS73n4PCrqpHBg= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= From c8baf76fae5e0bedd49d66fcd8fe003996766f49 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 27 Dec 2023 17:18:15 +0300 Subject: [PATCH 0263/1413] [#872] object: Introduce APE middlewar for object service Signed-off-by: Airat Arifullin --- cmd/frostfs-node/object.go | 23 +- pkg/services/object/acl/ape.go | 49 --- pkg/services/object/acl/ape_request.go | 100 ------ pkg/services/object/acl/v2/request.go | 7 + pkg/services/object/acl/v2/service.go | 104 +++++- pkg/services/object/acl/v2/types.go | 6 - pkg/services/object/ape/checker.go | 82 +++++ pkg/services/object/ape/checker_test.go | 348 ++++++++++++++++++++ pkg/services/object/ape/request.go | 159 ++++++++++ pkg/services/object/ape/request_test.go | 324 +++++++++++++++++++ pkg/services/object/ape/service.go | 404 ++++++++++++++++++++++++ pkg/services/object/ape/types.go | 9 + pkg/services/object/request_context.go | 16 + 13 files changed, 1456 insertions(+), 175 deletions(-) delete mode 100644 pkg/services/object/acl/ape.go delete mode 100644 pkg/services/object/acl/ape_request.go create mode 100644 pkg/services/object/ape/checker.go create mode 100644 pkg/services/object/ape/checker_test.go create mode 100644 pkg/services/object/ape/request.go create mode 100644 pkg/services/object/ape/request_test.go create mode 100644 pkg/services/object/ape/service.go create mode 100644 pkg/services/object/ape/types.go create mode 100644 pkg/services/object/request_context.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 2d18f82a3d..5c82f0dcc1 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -24,6 +24,7 @@ import ( objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl" v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" + objectAPE "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/ape" deletesvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete" deletesvcV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete/v2" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" @@ -183,11 +184,13 @@ func initObjectService(c *cfg) { sDeleteV2 := createDeleteServiceV2(sDelete) // build service pipeline - // grpc | | signature | response | acl | split + // grpc | | signature | response | acl | ape | split splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2) - aclSvc := createACLServiceV2(c, splitSvc, &irFetcher) + apeSvc := createAPEService(c, splitSvc) + + aclSvc := createACLServiceV2(c, apeSvc, &irFetcher) var commonSvc objectService.Common commonSvc.Init(&c.internals, aclSvc) @@ -419,11 +422,11 @@ func createSplitService(c *cfg, sPutV2 *putsvcV2.Service, sGetV2 *getsvcV2.Servi ) } -func createACLServiceV2(c *cfg, splitSvc *objectService.TransportSplitter, irFetcher *cachedIRFetcher) v2.Service { +func createACLServiceV2(c *cfg, apeSvc *objectAPE.Service, irFetcher *cachedIRFetcher) v2.Service { ls := c.cfgObject.cfgLocalStorage.localStorage return v2.New( - splitSvc, + apeSvc, c.netMapSource, irFetcher, acl.NewChecker( @@ -431,12 +434,22 @@ func createACLServiceV2(c *cfg, splitSvc *objectService.TransportSplitter, irFet c.cfgObject.eaclSource, eaclSDK.NewValidator(), ls), - acl.NewAPEChecker(c.log, c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.chainRouter), c.cfgObject.cnrSource, v2.WithLogger(c.log), ) } +func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *objectAPE.Service { + return objectAPE.NewService( + c.log, + objectAPE.NewChecker( + c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.chainRouter, + objectAPE.NewStorageEngineHeaderProvider(c.cfgObject.cfgLocalStorage.localStorage), + ), + splitSvc, + ) +} + type morphEACLFetcher struct { w *cntClient.Client } diff --git a/pkg/services/object/acl/ape.go b/pkg/services/object/acl/ape.go deleted file mode 100644 index a431ad2520..0000000000 --- a/pkg/services/object/acl/ape.go +++ /dev/null @@ -1,49 +0,0 @@ -package acl - -import ( - "fmt" - - v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" - policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" -) - -type apeCheckerImpl struct { - log *logger.Logger - chainRouter policyengine.ChainRouter -} - -func NewAPEChecker(log *logger.Logger, chainRouter policyengine.ChainRouter) v2.APEChainChecker { - return &apeCheckerImpl{ - log: log, - chainRouter: chainRouter, - } -} - -func (c *apeCheckerImpl) CheckIfRequestPermitted(reqInfo v2.RequestInfo) error { - request := new(Request) - request.FromRequestInfo(reqInfo) - - cnrTarget := reqInfo.ContainerID().EncodeToString() - - status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(cnrTarget), request) - if err != nil { - return err - } - - if !ruleFound || status == apechain.Allow { - return nil - } - - return apeErr(reqInfo, status) -} - -const accessDeniedAPEReasonFmt = "access to operation %s is denied by access policy engine: %s" - -func apeErr(req v2.RequestInfo, status apechain.Status) error { - errAccessDenied := &apistatus.ObjectAccessDenied{} - errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedAPEReasonFmt, req.Operation(), status.String())) - return errAccessDenied -} diff --git a/pkg/services/object/acl/ape_request.go b/pkg/services/object/acl/ape_request.go deleted file mode 100644 index accbdce5f8..0000000000 --- a/pkg/services/object/acl/ape_request.go +++ /dev/null @@ -1,100 +0,0 @@ -package acl - -import ( - "fmt" - - v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" - aclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" - nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" -) - -type Request struct { - operation string - resource *resource - properties map[string]string -} - -var _ aperesource.Request = (*Request)(nil) - -type resource struct { - name string - properties map[string]string -} - -var _ aperesource.Resource = (*resource)(nil) - -func (r *resource) Name() string { - return r.name -} - -func (r *resource) Property(key string) string { - return r.properties[key] -} - -func getResource(reqInfo v2.RequestInfo) *resource { - var name string - cid := reqInfo.ContainerID() - if oid := reqInfo.ObjectID(); oid != nil { - name = fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, cid.EncodeToString(), oid.EncodeToString()) - } else { - name = fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) - } - return &resource{ - name: name, - properties: make(map[string]string), - } -} - -func getProperties(_ v2.RequestInfo) map[string]string { - return map[string]string{ - nativeschema.PropertyKeyActorPublicKey: "", - nativeschema.PropertyKeyActorRole: "", - } -} - -func getOperation(reqInfo v2.RequestInfo) string { - switch op := reqInfo.Operation(); op { - case aclSDK.OpObjectGet: - return nativeschema.MethodGetObject - case aclSDK.OpObjectHead: - return nativeschema.MethodHeadObject - case aclSDK.OpObjectPut: - return nativeschema.MethodPutObject - case aclSDK.OpObjectDelete: - return nativeschema.MethodDeleteObject - case aclSDK.OpObjectSearch: - return nativeschema.MethodSearchObject - case aclSDK.OpObjectRange: - return nativeschema.MethodRangeObject - case aclSDK.OpObjectHash: - return nativeschema.MethodHashObject - default: - return "" - } -} - -func NewRequest() *Request { - return &Request{ - resource: new(resource), - properties: map[string]string{}, - } -} - -func (r *Request) FromRequestInfo(ri v2.RequestInfo) { - r.operation = getOperation(ri) - r.resource = getResource(ri) - r.properties = getProperties(ri) -} - -func (r *Request) Operation() string { - return r.operation -} - -func (r *Request) Property(key string) string { - return r.properties[key] -} - -func (r *Request) Resource() aperesource.Resource { - return r.resource -} diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go index 6757689690..c58c00e0e1 100644 --- a/pkg/services/object/acl/v2/request.go +++ b/pkg/services/object/acl/v2/request.go @@ -22,6 +22,9 @@ type RequestInfo struct { operation acl.Op // put, get, head, etc. cnrOwner user.ID // container owner + // cnrNamespace defined to which namespace a container is belonged. + cnrNamespace string + idCnr cid.ID // optional for some request @@ -57,6 +60,10 @@ func (r RequestInfo) ContainerOwner() user.ID { return r.cnrOwner } +func (r RequestInfo) ContainerNamespace() string { + return r.cnrNamespace +} + // ObjectID return object ID. func (r RequestInfo) ObjectID() *oid.ID { return r.obj diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index ee167d0e4d..ed077411c3 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + containerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" @@ -67,10 +68,6 @@ type cfg struct { checker ACLChecker - // TODO(aarifullin): apeCheck is temporarily the part of - // acl service and must be standalone. - apeChecker APEChainChecker - irFetcher InnerRingFetcher nm netmap.Source @@ -83,7 +80,6 @@ func New(next object.ServiceServer, nm netmap.Source, irf InnerRingFetcher, acl ACLChecker, - apeChecker APEChainChecker, cs container.Source, opts ...Option, ) Service { @@ -93,7 +89,6 @@ func New(next object.ServiceServer, nm: nm, irFetcher: irf, checker: acl, - apeChecker: apeChecker, containers: cs, } @@ -107,6 +102,75 @@ func New(next object.ServiceServer, } } +// wrappedGetObjectStream propagates RequestContext into GetObjectStream's context. +// This allows to retrieve already calculated immutable request-specific values in next handler invocation. +type wrappedGetObjectStream struct { + object.GetObjectStream + + requestInfo RequestInfo +} + +func (w *wrappedGetObjectStream) Context() context.Context { + return context.WithValue(w.GetObjectStream.Context(), object.RequestContextKey, &object.RequestContext{ + Namespace: w.requestInfo.ContainerNamespace(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + }) +} + +func newWrappedGetObjectStreamStream(getObjectStream object.GetObjectStream, reqInfo RequestInfo) object.GetObjectStream { + return &wrappedGetObjectStream{ + GetObjectStream: getObjectStream, + requestInfo: reqInfo, + } +} + +// wrappedRangeStream propagates RequestContext into GetObjectRangeStream's context. +// This allows to retrieve already calculated immutable request-specific values in next handler invocation. +type wrappedRangeStream struct { + object.GetObjectRangeStream + + requestInfo RequestInfo +} + +func (w *wrappedRangeStream) Context() context.Context { + return context.WithValue(w.GetObjectRangeStream.Context(), object.RequestContextKey, &object.RequestContext{ + Namespace: w.requestInfo.ContainerNamespace(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + }) +} + +func newWrappedRangeStream(rangeStream object.GetObjectRangeStream, reqInfo RequestInfo) object.GetObjectRangeStream { + return &wrappedRangeStream{ + GetObjectRangeStream: rangeStream, + requestInfo: reqInfo, + } +} + +// wrappedSearchStream propagates RequestContext into SearchStream's context. +// This allows to retrieve already calculated immutable request-specific values in next handler invocation. +type wrappedSearchStream struct { + object.SearchStream + + requestInfo RequestInfo +} + +func (w *wrappedSearchStream) Context() context.Context { + return context.WithValue(w.SearchStream.Context(), object.RequestContextKey, &object.RequestContext{ + Namespace: w.requestInfo.ContainerNamespace(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + }) +} + +func newWrappedSearchStream(searchStream object.SearchStream, reqInfo RequestInfo) object.SearchStream { + return &wrappedSearchStream{ + SearchStream: searchStream, + requestInfo: reqInfo, + } +} + // Get implements ServiceServer interface, makes ACL checks and calls // next Get method in the ServiceServer pipeline. func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream) error { @@ -158,7 +222,7 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream } return b.next.Get(request, &getStreamBasicChecker{ - GetObjectStream: stream, + GetObjectStream: newWrappedGetObjectStreamStream(stream, reqInfo), info: reqInfo, checker: b.checker, }) @@ -224,7 +288,7 @@ func (b Service) Head( return nil, eACLErr(reqInfo, err) } - resp, err := b.next.Head(ctx, request) + resp, err := b.next.Head(requestContext(ctx, reqInfo), request) if err == nil { if err = b.checker.CheckEACL(resp, reqInfo); err != nil { err = eACLErr(reqInfo, err) @@ -277,7 +341,7 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr return b.next.Search(request, &searchStreamBasicChecker{ checker: b.checker, - SearchStream: stream, + SearchStream: newWrappedSearchStream(stream, reqInfo), info: reqInfo, }) } @@ -333,7 +397,7 @@ func (b Service) Delete( return nil, eACLErr(reqInfo, err) } - return b.next.Delete(ctx, request) + return b.next.Delete(requestContext(ctx, reqInfo), request) } func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetObjectRangeStream) error { @@ -386,11 +450,18 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb return b.next.GetRange(request, &rangeStreamBasicChecker{ checker: b.checker, - GetObjectRangeStream: stream, + GetObjectRangeStream: newWrappedRangeStream(stream, reqInfo), info: reqInfo, }) } +func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { + return context.WithValue(ctx, object.RequestContextKey, &object.RequestContext{ + SenderKey: reqInfo.SenderKey(), + Role: reqInfo.RequestRole(), + }) +} + func (b Service) GetRangeHash( ctx context.Context, request *objectV2.GetRangeHashRequest, @@ -442,7 +513,7 @@ func (b Service) GetRangeHash( return nil, eACLErr(reqInfo, err) } - return b.next.GetRangeHash(ctx, request) + return b.next.GetRangeHash(requestContext(ctx, reqInfo), request) } func (b Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequest) (*objectV2.PutSingleResponse, error) { @@ -501,7 +572,7 @@ func (b Service) PutSingle(ctx context.Context, request *objectV2.PutSingleReque return nil, eACLErr(reqInfo, err) } - return b.next.PutSingle(ctx, request) + return b.next.PutSingle(requestContext(ctx, reqInfo), request) } func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRequest) error { @@ -566,9 +637,11 @@ func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRe reqInfo.obj = obj - if err := p.source.apeChecker.CheckIfRequestPermitted(reqInfo); err != nil { - return err + if !p.source.checker.CheckBasicACL(reqInfo) || !p.source.checker.StickyBitCheck(reqInfo, idOwner) { + return basicACLErr(reqInfo) } + + ctx = requestContext(ctx, reqInfo) } return p.next.Send(ctx, request) @@ -671,6 +744,7 @@ func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (in info.operation = op info.cnrOwner = cnr.Value.Owner() info.idCnr = idCnr + info.cnrNamespace = cnr.Value.Attribute(containerV2.SysAttributeZone) // it is assumed that at the moment the key will be valid, // otherwise the request would not pass validation diff --git a/pkg/services/object/acl/v2/types.go b/pkg/services/object/acl/v2/types.go index a113c46939..061cd26b62 100644 --- a/pkg/services/object/acl/v2/types.go +++ b/pkg/services/object/acl/v2/types.go @@ -26,9 +26,3 @@ type InnerRingFetcher interface { // the actual inner ring. InnerRingKeys() ([][]byte, error) } - -// APEChainChecker is the interface that provides methods to -// check if the access policy engine permits to perform the request. -type APEChainChecker interface { - CheckIfRequestPermitted(RequestInfo) error -} diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go new file mode 100644 index 0000000000..fdaa9df856 --- /dev/null +++ b/pkg/services/object/ape/checker.go @@ -0,0 +1,82 @@ +package ape + +import ( + "context" + "fmt" + + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" +) + +type checkerImpl struct { + chainRouter policyengine.ChainRouter + + headerProvider HeaderProvider +} + +func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider) Checker { + return &checkerImpl{ + chainRouter: chainRouter, + + headerProvider: headerProvider, + } +} + +type Prm struct { + Namespace string + + Container cid.ID + + // Object ID is omitted for some methods. + Object *oid.ID + + // If Header is set, then object attributes and properties will be parsed from + // a request/response's header. + Header *objectV2.Header + + // Method must be represented only as a constant represented in native schema. + Method string + + // Role must be representedonly as a constant represented in native schema. + Role string + + // An encoded sender's public key string. + SenderKey string +} + +var ( + errMissingOID = fmt.Errorf("object ID is not set") +) + +// CheckAPE checks if a request or a response is permitted creating an ape request and passing +// it to chain router. +func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { + r, err := c.newAPERequest(ctx, prm) + if err != nil { + return fmt.Errorf("failed to create ape request: %w", err) + } + + status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, + policyengine.NewRequestTarget(prm.Namespace, prm.Container.EncodeToString()), r) + if err != nil { + return err + } + + if !ruleFound || status == apechain.Allow { + return nil + } + + return apeErr(prm.Method, status) +} + +const accessDeniedAPEReasonFmt = "access to operation %s is denied by access policy engine: %s" + +func apeErr(op string, status apechain.Status) error { + errAccessDenied := &apistatus.ObjectAccessDenied{} + errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedAPEReasonFmt, op, status.String())) + return errAccessDenied +} diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go new file mode 100644 index 0000000000..9d548480b3 --- /dev/null +++ b/pkg/services/object/ape/checker_test.go @@ -0,0 +1,348 @@ +package ape + +import ( + "context" + "encoding/hex" + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/stretchr/testify/require" +) + +type headerProviderMock struct { + m map[oid.Address]*objectSDK.Object +} + +var _ HeaderProvider = (*headerProviderMock)(nil) + +func (h *headerProviderMock) addHeader(c cid.ID, o oid.ID, header *objectSDK.Object) { + var addr oid.Address + addr.SetContainer(c) + addr.SetObject(o) + h.m[addr] = header +} + +func (h *headerProviderMock) GetHeader(_ context.Context, c cid.ID, o oid.ID) (*objectSDK.Object, error) { + var addr oid.Address + addr.SetContainer(c) + addr.SetObject(o) + obj, ok := h.m[addr] + if !ok { + return nil, fmt.Errorf("address not found") + } + return obj, nil +} + +func newHeaderProviderMock() *headerProviderMock { + return &headerProviderMock{ + m: make(map[oid.Address]*objectSDK.Object), + } +} + +func newContainerIDSDK(t *testing.T, encodedCID string) cid.ID { + var cnr cid.ID + require.NoError(t, cnr.DecodeString(encodedCID)) + return cnr +} + +func newObjectIDSDK(t *testing.T, encodedOID *string) *oid.ID { + if encodedOID == nil { + return nil + } + obj := new(oid.ID) + require.NoError(t, obj.DecodeString(*encodedOID)) + return obj +} + +type headerObjectSDKParams struct { + majorVersion, minorVersion uint32 + owner user.ID + epoch uint64 + payloadSize uint64 + typ objectSDK.Type + payloadChecksum checksum.Checksum + payloadHomomorphicHash checksum.Checksum + attributes []struct { + key string + val string + } +} + +func stringPtr(s string) *string { + return &s +} + +func newHeaderObjectSDK(t *testing.T, cnr cid.ID, oid *oid.ID, headerObjSDK *headerObjectSDKParams) *objectSDK.Object { + objSDK := objectSDK.New() + objSDK.SetContainerID(cnr) + if oid != nil { + objSDK.SetID(*oid) + } + if headerObjSDK == nil { + return objSDK + } + ver := new(version.Version) + ver.SetMajor(headerObjSDK.majorVersion) + ver.SetMinor(headerObjSDK.minorVersion) + objSDK.SetVersion(ver) + objSDK.SetCreationEpoch(headerObjSDK.epoch) + objSDK.SetOwnerID(headerObjSDK.owner) + objSDK.SetPayloadSize(headerObjSDK.payloadSize) + objSDK.SetType(headerObjSDK.typ) + objSDK.SetPayloadChecksum(headerObjSDK.payloadChecksum) + objSDK.SetPayloadHomomorphicHash(headerObjSDK.payloadHomomorphicHash) + + var attrs []objectSDK.Attribute + for _, attr := range headerObjSDK.attributes { + attrSDK := objectSDK.NewAttribute() + attrSDK.SetKey(attr.key) + attrSDK.SetValue(attr.val) + attrs = append(attrs, *attrSDK) + } + objSDK.SetAttributes(attrs...) + + return objSDK +} + +type testHeader struct { + headerObjSDK *headerObjectSDKParams + + // If fromHeaderProvider is set, then running test should + // consider that a header is recieved from a header provider. + fromHeaderProvider bool + + // If fromHeaderProvider is set, then running test should + // consider that a header is recieved from a message header. + fromRequestResponseHeader bool +} + +var ( + methodsRequiredOID = []string{ + nativeschema.MethodGetObject, + nativeschema.MethodHeadObject, + nativeschema.MethodRangeObject, + nativeschema.MethodHashObject, + nativeschema.MethodDeleteObject, + } + + methodsOptionalOID = []string{ + nativeschema.MethodSearchObject, nativeschema.MethodPutObject, + } + + namespace = "test_namespace" + + containerID = "73tQMTYyUkTgmvPR1HWib6pndbhSoBovbnMF7Pws8Rcy" + + objectID = "BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R" + + role = "Container" + + senderKey = hex.EncodeToString([]byte{1, 0, 0, 1}) +) + +func TestAPECheck(t *testing.T) { + for _, test := range []struct { + name string + container string + object *string + methods []string + header testHeader + containerRules []chain.Rule + expectAPEErr bool + }{ + { + name: "oid required requests are allowed", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + }, + { + name: "oid optional requests are allowed", + container: containerID, + methods: methodsOptionalOID, + }, + { + name: "oid required requests are denied", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + containerRules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + }, + }, + expectAPEErr: true, + }, + { + name: "oid required requests are denied by an attribute", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "attribute_value", + }, + }, + }, + fromHeaderProvider: true, + }, + containerRules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringLike, + Object: chain.ObjectResource, + Key: "attr1", + Value: "attribute*", + }, + }, + }, + }, + expectAPEErr: true, + }, + { + name: "oid required requests are denied by sender", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "attribute_value", + }, + }, + }, + fromHeaderProvider: true, + }, + containerRules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringLike, + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorPublicKey, + Value: senderKey, + }, + }, + }, + }, + expectAPEErr: true, + }, + { + name: "optional oid requests reached quota limit by an attribute", + container: containerID, + methods: methodsOptionalOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + payloadSize: 1000, + }, + fromRequestResponseHeader: true, + }, + containerRules: []chain.Rule{ + { + Status: chain.QuotaLimitReached, + Actions: chain.Actions{Names: methodsOptionalOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Object: chain.ObjectResource, + Key: nativeschema.PropertyKeyObjectPayloadLength, + Value: "1000", + }, + }, + }, + }, + expectAPEErr: true, + }, + } { + t.Run(test.name, func(t *testing.T) { + for _, method := range test.methods { + t.Run(method, func(t *testing.T) { + headerProvider := newHeaderProviderMock() + + cnr := newContainerIDSDK(t, test.container) + obj := newObjectIDSDK(t, test.object) + + ls := inmemory.NewInmemoryLocalStorage() + ms := inmemory.NewInmemoryMorphRuleChainStorage() + + ls.AddOverride(chain.Ingress, policyengine.ContainerTarget(test.container), &chain.Chain{ + Rules: test.containerRules, + }) + + router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) + + checker := NewChecker(router, headerProvider) + + prm := Prm{ + Method: method, + Container: cnr, + Object: obj, + Role: role, + SenderKey: senderKey, + } + + var headerObjSDK *objectSDK.Object + if test.header.headerObjSDK != nil { + headerObjSDK = newHeaderObjectSDK(t, cnr, obj, test.header.headerObjSDK) + if test.header.fromHeaderProvider { + require.NotNil(t, obj, "oid is required if a header is expected to be found in header provider") + headerProvider.addHeader(cnr, *obj, headerObjSDK) + } else if test.header.fromRequestResponseHeader { + prm.Header = headerObjSDK.ToV2().GetHeader() + } + } + + err := checker.CheckAPE(context.Background(), prm) + if test.expectAPEErr { + aErr := apeErr(method, chain.AccessDenied) + require.ErrorAs(t, err, &aErr) + } else { + require.NoError(t, err) + } + }) + } + }) + } +} diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go new file mode 100644 index 0000000000..caf52645c6 --- /dev/null +++ b/pkg/services/object/ape/request.go @@ -0,0 +1,159 @@ +package ape + +import ( + "context" + "fmt" + "strconv" + + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" +) + +type request struct { + operation string + resource *resource + properties map[string]string +} + +var _ aperesource.Request = (*request)(nil) + +type resource struct { + name string + properties map[string]string +} + +var _ aperesource.Resource = (*resource)(nil) + +func (r *resource) Name() string { + return r.name +} + +func (r *resource) Property(key string) string { + return r.properties[key] +} + +func (r *request) Operation() string { + return r.operation +} + +func (r *request) Property(key string) string { + return r.properties[key] +} + +func (r *request) Resource() aperesource.Resource { + return r.resource +} + +func nativeSchemaRole(role acl.Role) string { + switch role { + case acl.RoleOwner: + return nativeschema.PropertyValueContainerRoleOwner + case acl.RoleContainer: + return nativeschema.PropertyValueContainerRoleContainer + case acl.RoleInnerRing: + return nativeschema.PropertyValueContainerRoleIR + case acl.RoleOthers: + return nativeschema.PropertyValueContainerRoleOthers + default: + return "" + } +} + +func resourceName(cid cid.ID, oid *oid.ID, namespace string) string { + if namespace == "root" || namespace == "" { + if oid != nil { + return fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, cid.EncodeToString(), oid.EncodeToString()) + } + return fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + } + if oid != nil { + return fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainerObject, namespace, cid.EncodeToString(), oid.EncodeToString()) + } + return fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainerObjects, namespace, cid.EncodeToString()) +} + +// objectProperties collects object properties from address parameters and a header if it is passed. +func objectProperties(cnr cid.ID, oid *oid.ID, header *objectV2.Header) map[string]string { + objectProps := map[string]string{ + nativeschema.PropertyKeyObjectContainerID: cnr.EncodeToString(), + } + + if oid != nil { + objectProps[nativeschema.PropertyKeyObjectID] = oid.String() + } + + if header == nil { + return objectProps + } + + objV2 := new(objectV2.Object) + objV2.SetHeader(header) + objSDK := objectSDK.NewFromV2(objV2) + + objectProps[nativeschema.PropertyKeyObjectVersion] = objSDK.Version().String() + objectProps[nativeschema.PropertyKeyObjectOwnerID] = objSDK.OwnerID().EncodeToString() + objectProps[nativeschema.PropertyKeyObjectCreationEpoch] = strconv.Itoa(int(objSDK.CreationEpoch())) + objectProps[nativeschema.PropertyKeyObjectPayloadLength] = strconv.Itoa(int(objSDK.PayloadSize())) + objectProps[nativeschema.PropertyKeyObjectType] = objSDK.Type().String() + + pcs, isSet := objSDK.PayloadChecksum() + if isSet { + objectProps[nativeschema.PropertyKeyObjectPayloadHash] = pcs.String() + } + hcs, isSet := objSDK.PayloadHomomorphicHash() + if isSet { + objectProps[nativeschema.PropertyKeyObjectHomomorphicHash] = hcs.String() + } + + for _, attr := range header.GetAttributes() { + objectProps[attr.GetKey()] = attr.GetValue() + } + + return objectProps +} + +// newAPERequest creates an APE request to be passed to a chain router. It collects resource properties from +// header provided by headerProvider. If it cannot be found in headerProvider, then properties are +// initialized from header given in prm (if it is set). Otherwise, just CID and OID are set to properties. +func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (*request, error) { + switch prm.Method { + case nativeschema.MethodGetObject, + nativeschema.MethodHeadObject, + nativeschema.MethodRangeObject, + nativeschema.MethodHashObject, + nativeschema.MethodDeleteObject: + if prm.Object == nil { + return nil, fmt.Errorf("method %s: %w", prm.Method, errMissingOID) + } + case nativeschema.MethodSearchObject, nativeschema.MethodPutObject: + default: + return nil, fmt.Errorf("unknown method: %s", prm.Method) + } + + var header *objectV2.Header + if prm.Header != nil { + header = prm.Header + } else if prm.Object != nil { + headerObjSDK, err := c.headerProvider.GetHeader(ctx, prm.Container, *prm.Object) + if err == nil { + header = headerObjSDK.ToV2().GetHeader() + } + } + + return &request{ + operation: prm.Method, + resource: &resource{ + name: resourceName(prm.Container, prm.Object, prm.Namespace), + properties: objectProperties(prm.Container, prm.Object, header), + }, + properties: map[string]string{ + nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, + nativeschema.PropertyKeyActorRole: prm.Role, + }, + }, nil +} diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go new file mode 100644 index 0000000000..55aa691b4e --- /dev/null +++ b/pkg/services/object/ape/request_test.go @@ -0,0 +1,324 @@ +package ape + +import ( + "context" + "fmt" + "testing" + + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/stretchr/testify/require" +) + +func TestObjectProperties(t *testing.T) { + for _, test := range []struct { + name string + container string + object *string + header *headerObjectSDKParams + }{ + { + name: "fully filled header", + container: containerID, + object: stringPtr(objectID), + header: &headerObjectSDKParams{ + majorVersion: 1, + minorVersion: 1, + owner: usertest.ID(), + epoch: 3, + payloadSize: 1000, + typ: objectSDK.TypeRegular, + payloadChecksum: checksumtest.Checksum(), + payloadHomomorphicHash: checksumtest.Checksum(), + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "val1", + }, + { + key: "attr2", + val: "val2", + }, + }, + }, + }, + { + name: "partially filled header", + container: containerID, + header: &headerObjectSDKParams{ + majorVersion: 1, + minorVersion: 1, + owner: usertest.ID(), + epoch: 3, + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "val1", + }, + }, + }, + }, + { + name: "only address paramaters set in header", + container: containerID, + object: stringPtr(objectID), + }, + { + name: "only container set in header", + container: containerID, + }, + } { + t.Run(test.name, func(t *testing.T) { + cnr := newContainerIDSDK(t, test.container) + obj := newObjectIDSDK(t, test.object) + header := newHeaderObjectSDK(t, cnr, obj, test.header) + + props := objectProperties(cnr, obj, header.ToV2().GetHeader()) + require.Equal(t, test.container, props[nativeschema.PropertyKeyObjectContainerID]) + + if obj != nil { + require.Equal(t, *test.object, props[nativeschema.PropertyKeyObjectID]) + } + + if test.header != nil { + require.Equal(t, + fmt.Sprintf("v%d.%d", test.header.majorVersion, test.header.minorVersion), + props[nativeschema.PropertyKeyObjectVersion], + ) + require.Equal(t, test.header.owner.EncodeToString(), props[nativeschema.PropertyKeyObjectOwnerID]) + require.Equal(t, fmt.Sprintf("%d", test.header.epoch), props[nativeschema.PropertyKeyObjectCreationEpoch]) + require.Equal(t, fmt.Sprintf("%d", test.header.payloadSize), props[nativeschema.PropertyKeyObjectPayloadLength]) + require.Equal(t, test.header.typ.String(), props[nativeschema.PropertyKeyObjectType]) + require.Equal(t, test.header.payloadChecksum.String(), props[nativeschema.PropertyKeyObjectPayloadHash]) + require.Equal(t, test.header.payloadHomomorphicHash.String(), props[nativeschema.PropertyKeyObjectHomomorphicHash]) + + for _, attr := range test.header.attributes { + require.Equal(t, attr.val, props[attr.key]) + } + } + }) + } +} + +func TestNewAPERequest(t *testing.T) { + tests := []struct { + name string + methods []string + namespace string + container string + object *string + header testHeader + expectErr error + }{ + { + name: "oid required requests", + methods: methodsRequiredOID, + namespace: namespace, + container: containerID, + object: stringPtr(objectID), + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + majorVersion: 1, + minorVersion: 1, + owner: usertest.ID(), + epoch: 3, + payloadSize: 1000, + typ: objectSDK.TypeRegular, + payloadChecksum: checksumtest.Checksum(), + payloadHomomorphicHash: checksumtest.Checksum(), + }, + fromHeaderProvider: true, + }, + }, + { + name: "oid required requests but header cannot be found locally", + methods: methodsRequiredOID, + namespace: namespace, + container: containerID, + object: stringPtr(objectID), + header: testHeader{}, + }, + { + name: "oid required requests missed oid", + methods: methodsRequiredOID, + namespace: namespace, + container: containerID, + object: nil, + header: testHeader{}, + expectErr: errMissingOID, + }, + { + name: "response for oid required requests", + methods: methodsRequiredOID, + namespace: namespace, + container: containerID, + object: stringPtr(objectID), + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + majorVersion: 1, + minorVersion: 1, + owner: usertest.ID(), + epoch: 3, + payloadSize: 1000, + typ: objectSDK.TypeRegular, + payloadChecksum: checksumtest.Checksum(), + payloadHomomorphicHash: checksumtest.Checksum(), + }, + fromRequestResponseHeader: true, + }, + }, + { + name: "oid not required methods request", + methods: methodsOptionalOID, + namespace: namespace, + container: containerID, + object: nil, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + majorVersion: 6, + minorVersion: 66, + owner: usertest.ID(), + epoch: 3, + typ: objectSDK.TypeLock, + }, + fromRequestResponseHeader: true, + }, + }, + { + name: "oid not required methods request but no header", + methods: methodsOptionalOID, + namespace: namespace, + container: containerID, + object: nil, + header: testHeader{}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for _, method := range test.methods { + t.Run(method, func(t *testing.T) { + cnr := newContainerIDSDK(t, test.container) + obj := newObjectIDSDK(t, test.object) + + prm := Prm{ + Namespace: test.namespace, + Method: method, + Container: cnr, + Object: obj, + Role: role, + SenderKey: senderKey, + } + + headerSource := newHeaderProviderMock() + + var headerObjSDK *objectSDK.Object + if test.header.headerObjSDK != nil { + headerObjSDK = newHeaderObjectSDK(t, cnr, obj, test.header.headerObjSDK) + if test.header.fromHeaderProvider { + require.NotNil(t, obj, "oid is required if a header is expected to be found in header provider") + headerSource.addHeader(cnr, *obj, headerObjSDK) + } else if test.header.fromRequestResponseHeader { + prm.Header = headerObjSDK.ToV2().GetHeader() + } + } + + c := checkerImpl{ + headerProvider: headerSource, + } + + r, err := c.newAPERequest(context.TODO(), prm) + if test.expectErr != nil { + require.Error(t, err) + require.ErrorIs(t, err, test.expectErr) + return + } + + expectedRequest := request{ + operation: method, + resource: &resource{ + name: resourceName(cnr, obj, prm.Namespace), + properties: objectProperties(cnr, obj, func() *objectV2.Header { + if headerObjSDK != nil { + return headerObjSDK.ToV2().GetHeader() + } + return prm.Header + }()), + }, + properties: map[string]string{ + nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, + nativeschema.PropertyKeyActorRole: prm.Role, + }, + } + + require.Equal(t, expectedRequest, *r) + }) + } + }) + } +} + +func TestResourceName(t *testing.T) { + for _, test := range []struct { + name string + namespace string + container string + object *string + expected string + }{ + { + name: "non-root namespace, CID", + namespace: namespace, + container: containerID, + expected: fmt.Sprintf("native:object/%s/%s/*", namespace, containerID), + }, + { + name: "non-root namespace, CID, OID", + namespace: namespace, + container: containerID, + object: stringPtr(objectID), + expected: fmt.Sprintf("native:object/%s/%s/%s", namespace, containerID, objectID), + }, + { + name: "empty namespace, CID", + namespace: "", + container: containerID, + expected: fmt.Sprintf("native:object//%s/*", containerID), + }, + { + name: "empty namespace, CID, OID", + namespace: "", + container: containerID, + object: stringPtr(objectID), + expected: fmt.Sprintf("native:object//%s/%s", containerID, objectID), + }, + { + name: "root namespace, CID", + namespace: "root", + container: containerID, + expected: fmt.Sprintf("native:object//%s/*", containerID), + }, + { + name: "root namespace, CID, OID", + namespace: "root", + container: containerID, + object: stringPtr(objectID), + expected: fmt.Sprintf("native:object//%s/%s", containerID, objectID), + }, + } { + t.Run(test.name, func(t *testing.T) { + cnr := newContainerIDSDK(t, test.container) + obj := newObjectIDSDK(t, test.object) + require.Equal(t, test.expected, resourceName(cnr, obj, test.namespace)) + }) + } +} diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go new file mode 100644 index 0000000000..df4dcc3069 --- /dev/null +++ b/pkg/services/object/ape/service.go @@ -0,0 +1,404 @@ +package ape + +import ( + "context" + "encoding/hex" + "fmt" + + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" +) + +type Service struct { + log *logger.Logger + + apeChecker Checker + + next objectSvc.ServiceServer +} + +var _ objectSvc.ServiceServer = (*Service)(nil) + +type HeaderProvider interface { + GetHeader(ctx context.Context, cnr cid.ID, oid oid.ID) (*objectSDK.Object, error) +} + +type storageEngineHeaderProvider struct { + storageEngine *engine.StorageEngine +} + +func (p storageEngineHeaderProvider) GetHeader(ctx context.Context, cnr cid.ID, objID oid.ID) (*objectSDK.Object, error) { + var addr oid.Address + addr.SetContainer(cnr) + addr.SetObject(objID) + return engine.Head(ctx, p.storageEngine, addr) +} + +func NewStorageEngineHeaderProvider(e *engine.StorageEngine) HeaderProvider { + return storageEngineHeaderProvider{ + storageEngine: e, + } +} + +func NewService(log *logger.Logger, apeChecker Checker, next objectSvc.ServiceServer) *Service { + return &Service{ + log: log, + apeChecker: apeChecker, + next: next, + } +} + +type getStreamBasicChecker struct { + objectSvc.GetObjectStream + + apeChecker Checker + + senderKey []byte + + role string +} + +func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { + if partInit, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok { + cnrID, objID, err := getAddressParamsSDK(partInit.GetHeader().GetContainerID(), partInit.GetObjectID()) + if err != nil { + return err + } + + prm := Prm{ + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodGetContainer, + SenderKey: hex.EncodeToString(g.senderKey), + Role: g.role, + } + + if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { + return err + } + } + return g.GetObjectStream.Send(resp) +} + +func requestContext(ctx context.Context) (*objectSvc.RequestContext, error) { + untyped := ctx.Value(objectSvc.RequestContextKey) + if untyped == nil { + return nil, fmt.Errorf("no key %s in context", objectSvc.RequestContextKey) + } + rc, ok := untyped.(*objectSvc.RequestContext) + if !ok { + return nil, fmt.Errorf("failed cast to RequestContext") + } + return rc, nil +} + +func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectStream) error { + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + if err != nil { + return err + } + + reqCtx, err := requestContext(stream.Context()) + if err != nil { + return err + } + + err = c.apeChecker.CheckAPE(stream.Context(), Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodGetObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + }) + if err != nil { + return err + } + + return c.next.Get(request, &getStreamBasicChecker{ + GetObjectStream: stream, + apeChecker: c.apeChecker, + }) +} + +type putStreamBasicChecker struct { + apeChecker Checker + + next objectSvc.PutObjectStream +} + +func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRequest) error { + if partInit, ok := request.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok { + reqCtx, err := requestContext(ctx) + if err != nil { + return err + } + + cnrID, objID, err := getAddressParamsSDK(partInit.GetHeader().GetContainerID(), partInit.GetObjectID()) + if err != nil { + return err + } + + prm := Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodPutObject, + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Role: nativeSchemaRole(reqCtx.Role), + } + + if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { + return err + } + } + + return p.next.Send(ctx, request) +} + +func (p putStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PutResponse, error) { + return p.next.CloseAndRecv(ctx) +} + +func (c *Service) Put() (objectSvc.PutObjectStream, error) { + streamer, err := c.next.Put() + + return &putStreamBasicChecker{ + apeChecker: c.apeChecker, + next: streamer, + }, err +} + +func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + if err != nil { + return nil, err + } + + reqCtx, err := requestContext(ctx) + if err != nil { + return nil, err + } + + err = c.apeChecker.CheckAPE(ctx, Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + }) + if err != nil { + return nil, err + } + + resp, err := c.next.Head(ctx, request) + if err != nil { + return nil, err + } + + header := new(objectV2.Header) + switch headerPart := resp.GetBody().GetHeaderPart().(type) { + case *objectV2.ShortHeader: + cidV2 := new(refs.ContainerID) + cnrID.WriteToV2(cidV2) + header.SetContainerID(cidV2) + header.SetVersion(headerPart.GetVersion()) + header.SetCreationEpoch(headerPart.GetCreationEpoch()) + header.SetOwnerID(headerPart.GetOwnerID()) + header.SetObjectType(headerPart.GetObjectType()) + header.SetHomomorphicHash(header.GetHomomorphicHash()) + header.SetPayloadLength(headerPart.GetPayloadLength()) + header.SetPayloadHash(headerPart.GetPayloadHash()) + case *objectV2.HeaderWithSignature: + header = headerPart.GetHeader() + default: + return resp, nil + } + + err = c.apeChecker.CheckAPE(ctx, Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: header, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + }) + if err != nil { + return nil, err + } + return resp, nil +} + +func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.SearchStream) error { + var cnrID cid.ID + if cnrV2 := request.GetBody().GetContainerID(); cnrV2 != nil { + if err := cnrID.ReadFromV2(*cnrV2); err != nil { + return err + } + } + + reqCtx, err := requestContext(stream.Context()) + if err != nil { + return err + } + + err = c.apeChecker.CheckAPE(stream.Context(), Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Method: nativeschema.MethodSearchObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + }) + if err != nil { + return err + } + + return c.next.Search(request, stream) +} + +func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) (*objectV2.DeleteResponse, error) { + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + if err != nil { + return nil, err + } + + reqCtx, err := requestContext(ctx) + if err != nil { + return nil, err + } + + err = c.apeChecker.CheckAPE(ctx, Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodDeleteObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + }) + if err != nil { + return nil, err + } + + resp, err := c.next.Delete(ctx, request) + if err != nil { + return nil, err + } + + return resp, nil +} + +func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.GetObjectRangeStream) error { + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + if err != nil { + return err + } + + reqCtx, err := requestContext(stream.Context()) + if err != nil { + return err + } + + err = c.apeChecker.CheckAPE(stream.Context(), Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodRangeObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + }) + if err != nil { + return err + } + + return c.next.GetRange(request, stream) +} + +func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) { + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + if err != nil { + return nil, err + } + + reqCtx, err := requestContext(ctx) + if err != nil { + return nil, err + } + + prm := Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHashObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + } + + if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { + return nil, err + } + + resp, err := c.next.GetRangeHash(ctx, request) + if err != nil { + return nil, err + } + + if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { + return nil, err + } + return resp, nil +} + +func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequest) (*objectV2.PutSingleResponse, error) { + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetObject().GetHeader().GetContainerID(), request.GetBody().GetObject().GetObjectID()) + if err != nil { + return nil, err + } + + reqCtx, err := requestContext(ctx) + if err != nil { + return nil, err + } + + prm := Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: request.GetBody().GetObject().GetHeader(), + Method: nativeschema.MethodPutObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + } + + if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { + return nil, err + } + + return c.next.PutSingle(ctx, request) +} + +func getAddressParamsSDK(cidV2 *refs.ContainerID, objV2 *refs.ObjectID) (cnrID cid.ID, objID *oid.ID, err error) { + if cidV2 != nil { + if err = cnrID.ReadFromV2(*cidV2); err != nil { + return + } + } + + if objV2 != nil { + objID = new(oid.ID) + if err = objID.ReadFromV2(*objV2); err != nil { + return + } + } + return +} diff --git a/pkg/services/object/ape/types.go b/pkg/services/object/ape/types.go new file mode 100644 index 0000000000..46e55360d6 --- /dev/null +++ b/pkg/services/object/ape/types.go @@ -0,0 +1,9 @@ +package ape + +import "context" + +// Checker provides methods to check requests and responses +// with access policy engine. +type Checker interface { + CheckAPE(context.Context, Prm) error +} diff --git a/pkg/services/object/request_context.go b/pkg/services/object/request_context.go new file mode 100644 index 0000000000..4b9aa04d16 --- /dev/null +++ b/pkg/services/object/request_context.go @@ -0,0 +1,16 @@ +package object + +import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + +type RequestContextKeyT struct{} + +var RequestContextKey = RequestContextKeyT{} + +// RequestContext is a context passed between middleware handlers. +type RequestContext struct { + Namespace string + + SenderKey []byte + + Role acl.Role +} From 96b020626f8088dbf0796c6ca817b7a0240365fc Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 16 Jan 2024 23:52:37 +0300 Subject: [PATCH 0264/1413] [#915] ape: Fix method name in getStreamBasicChecker * Replace incorrect MethodGetContainer by MethodGetObject constant. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index df4dcc3069..d28ad4aeb3 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -76,7 +76,7 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { Container: cnrID, Object: objID, Header: partInit.GetHeader(), - Method: nativeschema.MethodGetContainer, + Method: nativeschema.MethodGetObject, SenderKey: hex.EncodeToString(g.senderKey), Role: g.role, } From c1a80235db2a876fd32a8b51c58bb9d15dc7c535 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 15 Jan 2024 08:52:52 +0300 Subject: [PATCH 0265/1413] [#904] metabase: Log Inhume operation It will be very useful for troubleshooting. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/inhume.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 3b2f016730..cd83a61597 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -7,6 +7,7 @@ import ( "fmt" "time" + storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -184,6 +185,13 @@ func (db *DB) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { return db.inhumeTx(tx, currEpoch, prm, &res) }) success = err == nil + if success { + for _, addr := range prm.target { + storagelog.Write(db.log, + storagelog.AddressField(addr), + storagelog.OpField("metabase INHUME")) + } + } return res, metaerr.Wrap(err) } From 57171907e3485dc29d4b375ce5139758fdeef718 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 15 Jan 2024 09:04:25 +0300 Subject: [PATCH 0266/1413] [#904] metabase: Return if object was actuall inserted This requires to count metrics properly. Signed-off-by: Dmitrii Stepanov --- .../metabase/counter_test.go | 49 +++++++++++++++++++ pkg/local_object_storage/metabase/put.go | 20 +++++--- pkg/local_object_storage/shard/put.go | 11 +++-- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 306bb0cc00..1797fc0aa3 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -316,6 +316,55 @@ func TestCounters(t *testing.T) { }) } +func TestDoublePut(t *testing.T) { + t.Parallel() + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + obj := testutil.GenerateObject() + + exp := make(map[cid.ID]meta.ObjectCounters) + cnrID, _ := obj.ContainerID() + exp[cnrID] = meta.ObjectCounters{ + Logic: 1, + Phy: 1, + User: 1, + } + + var prm meta.PutPrm + prm.SetObject(obj) + pr, err := db.Put(context.Background(), prm) + require.NoError(t, err) + require.True(t, pr.Inserted) + + c, err := db.ObjectCounters() + require.NoError(t, err) + + require.Equal(t, uint64(1), c.Phy) + require.Equal(t, uint64(1), c.Logic) + require.Equal(t, uint64(1), c.User) + + cc, err := db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) + + pr, err = db.Put(context.Background(), prm) + require.NoError(t, err) + require.False(t, pr.Inserted) + + c, err = db.ObjectCounters() + require.NoError(t, err) + + require.Equal(t, uint64(1), c.Phy) + require.Equal(t, uint64(1), c.Logic) + require.Equal(t, uint64(1), c.User) + + cc, err = db.ContainerCounters(context.Background()) + require.NoError(t, err) + + require.Equal(t, meta.ContainerCounters{Counts: exp}, cc) +} + func TestCounters_Expired(t *testing.T) { // That test is about expired objects without // GCMark yet. Such objects should be treated as diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 2f5108953a..1f00223897 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -36,7 +36,9 @@ type PutPrm struct { } // PutRes groups the resulting values of Put operation. -type PutRes struct{} +type PutRes struct { + Inserted bool +} // SetObject is a Put option to set object to save. func (p *PutPrm) SetObject(obj *objectSDK.Object) { @@ -85,7 +87,9 @@ func (db *DB) Put(ctx context.Context, prm PutPrm) (res PutRes, err error) { currEpoch := db.epochState.CurrentEpoch() err = db.boltDB.Batch(func(tx *bbolt.Tx) error { - return db.put(tx, prm.obj, prm.id, nil, currEpoch) + var e error + res, e = db.put(tx, prm.obj, prm.id, nil, currEpoch) + return e }) if err == nil { success = true @@ -102,10 +106,10 @@ func (db *DB) put(tx *bbolt.Tx, id []byte, si *objectSDK.SplitInfo, currEpoch uint64, -) error { +) (PutRes, error) { cnr, ok := obj.ContainerID() if !ok { - return errors.New("missing container in object") + return PutRes{}, errors.New("missing container in object") } isParent := si != nil @@ -116,14 +120,14 @@ func (db *DB) put(tx *bbolt.Tx, if errors.As(err, &splitInfoError) { exists = true // object exists, however it is virtual } else if err != nil { - return err // return any error besides SplitInfoError + return PutRes{}, err // return any error besides SplitInfoError } if exists { - return db.updateObj(tx, obj, id, si, isParent) + return PutRes{}, db.updateObj(tx, obj, id, si, isParent) } - return db.insertObject(tx, obj, id, si, isParent, cnr, currEpoch) + return PutRes{Inserted: true}, db.insertObject(tx, obj, id, si, isParent, cnr, currEpoch) } func (db *DB) updateObj(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *objectSDK.SplitInfo, isParent bool) error { @@ -153,7 +157,7 @@ func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *o return err } - err = db.put(tx, par, id, parentSI, currEpoch) + _, err = db.put(tx, par, id, parentSI, currEpoch) if err != nil { return err } diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index 09a98260df..d7a9e70126 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -84,15 +84,18 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { var pPrm meta.PutPrm pPrm.SetObject(prm.obj) pPrm.SetStorageID(res.StorageID) - if _, err := s.metaBase.Put(ctx, pPrm); err != nil { + res, err := s.metaBase.Put(ctx, pPrm) + if err != nil { // may we need to handle this case in a special way // since the object has been successfully written to BlobStor return PutRes{}, fmt.Errorf("could not put object to metabase: %w", err) } - s.incObjectCounter(putPrm.Address.Container(), meta.IsUserObject(prm.obj)) - s.addToPayloadSize(int64(prm.obj.PayloadSize())) - s.addToContainerSize(putPrm.Address.Container().EncodeToString(), int64(prm.obj.PayloadSize())) + if res.Inserted { + s.incObjectCounter(putPrm.Address.Container(), meta.IsUserObject(prm.obj)) + s.addToPayloadSize(int64(prm.obj.PayloadSize())) + s.addToContainerSize(putPrm.Address.Container().EncodeToString(), int64(prm.obj.PayloadSize())) + } } return PutRes{}, nil From 63d3ed1ad86ed8fa527e1705762c64e80e4ec300 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 16 Jan 2024 09:09:59 +0300 Subject: [PATCH 0267/1413] [#904] tests: Close test engine after test Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/error_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 77dbc9b7e8..7f48da08aa 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -221,6 +221,7 @@ func TestBlobstorFailback(t *testing.T) { checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite) checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) + require.NoError(t, te.ng.Close(context.Background())) } func checkShardState(t *testing.T, e *StorageEngine, id *shard.ID, errCount uint32, mode mode.Mode) { From be330705509ff3e061d40719d8ce478e19c71155 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 12 Jan 2024 17:56:35 +0300 Subject: [PATCH 0268/1413] [#910] control: Take empty namespace for 'root' Signed-off-by: Airat Arifullin --- pkg/services/control/server/policy_engine.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 519b210355..9b42f3a98e 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -17,7 +17,12 @@ func apeTarget(chainTarget *control.ChainTarget) (engine.Target, error) { case control.ChainTarget_CONTAINER: return engine.ContainerTarget(chainTarget.GetName()), nil case control.ChainTarget_NAMESPACE: - return engine.NamespaceTarget(chainTarget.GetName()), nil + namespace := chainTarget.GetName() + // If namespace is empty, we take it for root namespace. + if namespace == "" { + namespace = "root" + } + return engine.NamespaceTarget(namespace), nil default: } return engine.Target{}, status.Error(codes.InvalidArgument, From 0e3d144695ad7f6da169f5010aed71b1e64ebde2 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Fri, 12 Jan 2024 13:54:00 +0300 Subject: [PATCH 0269/1413] [#908] adm: Support frostfsid basic operations Signed-off-by: Denis Kirillov --- .../internal/modules/morph/frostfsid.go | 327 ++++++++++++++++++ .../internal/modules/morph/frostfsid_util.go | 27 ++ .../internal/modules/morph/root.go | 10 + go.mod | 2 +- go.sum | 4 +- 5 files changed, 367 insertions(+), 3 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/frostfsid.go diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go new file mode 100644 index 0000000000..79ff0cdd07 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -0,0 +1,327 @@ +package morph + +import ( + "fmt" + "sort" + + frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + namespaceFlag = "namespace" + subjectNameFlag = "subject-name" + subjectKeyFlag = "subject-key" + includeNamesFlag = "include-names" + groupNameFlag = "group-name" +) + +var ( + frostfsidCmd = &cobra.Command{ + Use: "frostfsid", + Short: "Section for frostfsid interactions commands", + } + + frostfsidCreateNamespaceCmd = &cobra.Command{ + Use: "create-namespace", + Short: "Create new namespace in frostfsid contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidCreateNamespace, + } + + frostfsidListNamespacesCmd = &cobra.Command{ + Use: "list-namespaces", + Short: "List all namespaces in frostfsid", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidListNamespaces, + } + + frostfsidCreateSubjectCmd = &cobra.Command{ + Use: "create-subject", + Short: "Create subject in frostfsid contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidCreateSubject, + } + + frostfsidDeleteSubjectCmd = &cobra.Command{ + Use: "delete-subject", + Short: "Delete subject from frostfsid contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidDeleteSubject, + } + + frostfsidListSubjectsCmd = &cobra.Command{ + Use: "list-subjects", + Short: "List subjects in namespace", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidListSubjects, + } + + frostfsidCreateGroupCmd = &cobra.Command{ + Use: "create-group", + Short: "Create group in frostfsid contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidCreateGroup, + } + + frostfsidDeleteGroupCmd = &cobra.Command{ + Use: "delete-group", + Short: "Delete group from frostfsid contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidDeleteGroup, + } + + frostfsidListGroupsCmd = &cobra.Command{ + Use: "list-groups", + Short: "List groups in namespace", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidListGroups, + } +) + +func initFrostfsIDCreateNamespaceCmd() { + frostfsidCmd.AddCommand(frostfsidCreateNamespaceCmd) + frostfsidCreateNamespaceCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateNamespaceCmd.Flags().String(namespaceFlag, "", "Namespace name to create") +} + +func initFrostfsIDListNamespacesCmd() { + frostfsidCmd.AddCommand(frostfsidListNamespacesCmd) + frostfsidListNamespacesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) +} + +func initFrostfsIDCreateSubjectCmd() { + frostfsidCmd.AddCommand(frostfsidCreateSubjectCmd) + frostfsidCreateSubjectCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateSubjectCmd.Flags().String(namespaceFlag, "", "Namespace where create subject") + frostfsidCreateSubjectCmd.Flags().String(subjectNameFlag, "", "Subject name, must be unique in namespace") + frostfsidCreateSubjectCmd.Flags().String(subjectKeyFlag, "", "Subject hex-encoded public key") +} + +func initFrostfsIDDeleteSubjectCmd() { + frostfsidCmd.AddCommand(frostfsidDeleteSubjectCmd) + frostfsidDeleteSubjectCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidDeleteSubjectCmd.Flags().String(subjectAddressFlag, "", "Subject address") +} + +func initFrostfsIDListSubjectsCmd() { + frostfsidCmd.AddCommand(frostfsidListSubjectsCmd) + frostfsidListSubjectsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") + frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") +} + +func initFrostfsIDCreateGroupCmd() { + frostfsidCmd.AddCommand(frostfsidCreateGroupCmd) + frostfsidCreateGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateGroupCmd.Flags().String(namespaceFlag, "", "Namespace where create group") + frostfsidCreateGroupCmd.Flags().String(groupNameFlag, "", "Group name, must be unique in namespace") +} + +func initFrostfsIDDeleteGroupCmd() { + frostfsidCmd.AddCommand(frostfsidDeleteGroupCmd) + frostfsidDeleteGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidDeleteGroupCmd.Flags().String(namespaceFlag, "", "Namespace to delete group") + frostfsidDeleteGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") +} + +func initFrostfsIDListGroupsCmd() { + frostfsidCmd.AddCommand(frostfsidListGroupsCmd) + frostfsidListGroupsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") +} + +type ffsidMethodArgs struct { + name string + args []any +} + +func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { + ns, _ := cmd.Flags().GetString(namespaceFlag) + + err := sendFrostfsIDTx(cmd, ffsidMethodArgs{name: "createNamespace", args: []any{ns}}) + commonCmd.ExitOnErr(cmd, "processing error: %w", err) +} + +func frostfsidListNamespaces(cmd *cobra.Command, _ []string) { + ffsid, err := frostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) + + namespaces, err := ffsid.ListNamespaces() + commonCmd.ExitOnErr(cmd, "list namespaces: %w", err) + + sort.Slice(namespaces, func(i, j int) bool { return namespaces[i].Name < namespaces[j].Name }) + + for _, namespace := range namespaces { + cmd.Printf("%q\n", namespace.Name) + } +} + +func frostfsidCreateSubject(cmd *cobra.Command, _ []string) { + ns, _ := cmd.Flags().GetString(namespaceFlag) + subjName, _ := cmd.Flags().GetString(subjectNameFlag) + subjKey := getFrostfsIDSubjectKey(cmd) + + args := []ffsidMethodArgs{ + {name: "createSubject", args: []any{ns, subjKey.Bytes()}}, + } + + if subjName != "" { + args = append(args, ffsidMethodArgs{name: "setSubjectName", args: []any{subjKey.GetScriptHash(), subjName}}) + } + + err := sendFrostfsIDTx(cmd, args...) + commonCmd.ExitOnErr(cmd, "processing error: %w", err) +} + +func frostfsidDeleteSubject(cmd *cobra.Command, _ []string) { + subjectAddress := getFrostfsIDSubjectAddress(cmd) + + err := sendFrostfsIDTx(cmd, ffsidMethodArgs{name: "deleteSubject", args: []any{subjectAddress}}) + commonCmd.ExitOnErr(cmd, "delete subject error: %w", err) +} + +func frostfsidListSubjects(cmd *cobra.Command, _ []string) { + ns, _ := cmd.Flags().GetString(namespaceFlag) + includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) + + ffsid, err := frostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) + + subAddresses, err := ffsid.ListNamespaceSubjects(ns) + commonCmd.ExitOnErr(cmd, "list subjects: %w", err) + + sort.Slice(subAddresses, func(i, j int) bool { return subAddresses[i].Less(subAddresses[j]) }) + + for _, addr := range subAddresses { + if !includeNames { + cmd.Println(address.Uint160ToString(addr)) + continue + } + + subj, err := ffsid.GetSubject(addr) + commonCmd.ExitOnErr(cmd, "get subject: %w", err) + + cmd.Printf("%s (%s)\n", address.Uint160ToString(addr), subj.Name) + } +} + +func frostfsidCreateGroup(cmd *cobra.Command, _ []string) { + ns, _ := cmd.Flags().GetString(namespaceFlag) + groupName, _ := cmd.Flags().GetString(groupNameFlag) + + ffsid, err := frostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + groupID, err := ffsid.ParseGroupID(ffsid.Wait(ffsid.CreateGroup(ns, groupName))) + commonCmd.ExitOnErr(cmd, "create group: %w", err) + + cmd.Printf("group '%s' created with id: %d\n", groupName, groupID) +} + +func frostfsidDeleteGroup(cmd *cobra.Command, _ []string) { + ns, _ := cmd.Flags().GetString(namespaceFlag) + groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + + ffsid, err := frostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + _, err = ffsid.Wait(ffsid.DeleteGroup(ns, groupID)) + commonCmd.ExitOnErr(cmd, "delete group error: %w", err) +} + +func frostfsidListGroups(cmd *cobra.Command, _ []string) { + ns, _ := cmd.Flags().GetString(namespaceFlag) + + ffsid, err := frostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) + + groups, err := ffsid.ListGroups(ns) + commonCmd.ExitOnErr(cmd, "list groups: %w", err) + + sort.Slice(groups, func(i, j int) bool { return groups[i].Name < groups[j].Name }) + + for _, group := range groups { + cmd.Printf("%q (%d)\n", group.Name, group.ID) + } +} + +func sendFrostfsIDTx(cmd *cobra.Command, methodArgs ...ffsidMethodArgs) error { + wCtx, err := newInitializeContext(cmd, viper.GetViper()) + if err != nil { + return fmt.Errorf("can't to initialize context: %w", err) + } + + r := management.NewReader(wCtx.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) + if err != nil { + return fmt.Errorf("can't get NNS contract info: %w", err) + } + + ffsidHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) + if err != nil { + return fmt.Errorf("can't get proxy contract hash: %w", err) + } + + bw := io.NewBufBinWriter() + for _, method := range methodArgs { + emit.AppCall(bw.BinWriter, ffsidHash, method.name, callflag.All, method.args...) + } + + if err = wCtx.sendConsensusTx(bw.Bytes()); err != nil { + return err + } + + return wCtx.awaitTx() +} + +func frostfsIDClient(cmd *cobra.Command) (*frostfsidclient.Client, error) { + wCtx, err := newInitializeContext(cmd, viper.GetViper()) + if err != nil { + return nil, fmt.Errorf("can't to initialize context: %w", err) + } + + r := management.NewReader(wCtx.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) + if err != nil { + return nil, fmt.Errorf("can't get NNS contract info: %w", err) + } + + ffsidHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) + if err != nil { + return nil, fmt.Errorf("can't get proxy contract hash: %w", err) + } + + return frostfsidclient.NewSimple(wCtx.CommitteeAct, ffsidHash), nil +} diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go index cfe3c1ee91..529d98dde5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go @@ -3,9 +3,11 @@ package morph import ( "fmt" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -31,3 +33,28 @@ func getFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { } return util.Uint160{}, true, fmt.Errorf("frostfsid: admin is invalid: '%s'", admin) } + +func getFrostfsIDSubjectKey(cmd *cobra.Command) *keys.PublicKey { + subjKeyHex, _ := cmd.Flags().GetString(subjectKeyFlag) + subjKey, err := keys.NewPublicKeyFromString(subjKeyHex) + commonCmd.ExitOnErr(cmd, "invalid subject key: %w", err) + return subjKey +} + +//func decodeFrostfsIDNamespaces(resStack []stackitem.Item) ([]string, error) { +// var res []string +// +// if len(resStack) == 0 { +// return res, nil +// } +// +// if len(resStack) > 0 { +// nodes, err := decodeNodeList(resStack[0]) +// if err != nil { +// return nil, err +// } +// +// nm.SetNodes(nodes) +// } +// +//} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 4176a64705..6db262175b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -293,6 +293,16 @@ func init() { initProxyAddAccount() initProxyRemoveAccount() + + RootCmd.AddCommand(frostfsidCmd) + initFrostfsIDCreateNamespaceCmd() + initFrostfsIDListNamespacesCmd() + initFrostfsIDCreateSubjectCmd() + initFrostfsIDDeleteSubjectCmd() + initFrostfsIDListSubjectsCmd() + initFrostfsIDCreateGroupCmd() + initFrostfsIDDeleteGroupCmd() + initFrostfsIDListGroupsCmd() } func initProxyAddAccount() { diff --git a/go.mod b/go.mod index ddf587ad5f..8b48cd788f 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd - git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231129062201-a1b61d394958 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e git.frostfs.info/TrueCloudLab/hrw v1.2.1 diff --git a/go.sum b/go.sum index 9be0e55cd8..11b208d32c 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd h1:MxiIXu4vUATX9bNYFnM1dXAYkx5dnPOGCMzwNNXJEvM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231129062201-a1b61d394958 h1:X9yPizADIhD3K/gdKVCthlAnf9aQ3UJJGnZgIwwixRQ= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20231129062201-a1b61d394958/go.mod h1:rQWdsG18NaiFvkJpMguJev913KD/yleHaniRBkUyt0o= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa h1:uuN90s74idThHXi/jF/IlTdFimOIs+IBU44rdTE/Zdo= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= From 6ebd61298e1b744db925e908672c2a6781ba7bfe Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Fri, 12 Jan 2024 18:03:18 +0300 Subject: [PATCH 0270/1413] [#908] adm/frostfsid: Support subject/group management Signed-off-by: Denis Kirillov --- .../internal/modules/morph/frostfsid.go | 106 +++++++++++++++++- .../internal/modules/morph/frostfsid_util.go | 23 +--- .../internal/modules/morph/root.go | 3 + 3 files changed, 110 insertions(+), 22 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 79ff0cdd07..a40ba4d4ca 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -16,11 +16,13 @@ import ( ) const ( - namespaceFlag = "namespace" - subjectNameFlag = "subject-name" - subjectKeyFlag = "subject-key" - includeNamesFlag = "include-names" - groupNameFlag = "group-name" + namespaceFlag = "namespace" + subjectNameFlag = "subject-name" + subjectKeyFlag = "subject-key" + subjectAddressFlag = "subject-address" + includeNamesFlag = "include-names" + groupNameFlag = "group-name" + groupIDFlag = "group-id" ) var ( @@ -108,6 +110,36 @@ var ( }, Run: frostfsidListGroups, } + + frostfsidAddSubjectToGroupCmd = &cobra.Command{ + Use: "add-subject-to-group", + Short: "Add subject to group", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidAddSubjectToGroup, + } + + frostfsidRemoveSubjectFromGroupCmd = &cobra.Command{ + Use: "remove-subject-from-group", + Short: "Remove subject from group", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidRemoveSubjectFromGroup, + } + + frostfsidListGroupSubjectsCmd = &cobra.Command{ + Use: "list-group-subjects", + Short: "List subjects in group", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + }, + Run: frostfsidListGroupSubjects, + } ) func initFrostfsIDCreateNamespaceCmd() { @@ -162,6 +194,28 @@ func initFrostfsIDListGroupsCmd() { frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") } +func initFrostfsIDAddSubjectToGroupCmd() { + frostfsidCmd.AddCommand(frostfsidAddSubjectToGroupCmd) + frostfsidAddSubjectToGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidAddSubjectToGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") + frostfsidAddSubjectToGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") +} + +func initFrostfsIDRemoveSubjectFromGroupCmd() { + frostfsidCmd.AddCommand(frostfsidRemoveSubjectFromGroupCmd) + frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidRemoveSubjectFromGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") + frostfsidRemoveSubjectFromGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") +} + +func initFrostfsIDListGroupSubjectsCmd() { + frostfsidCmd.AddCommand(frostfsidListGroupSubjectsCmd) + frostfsidListGroupSubjectsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") + frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") + frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") +} + type ffsidMethodArgs struct { name string args []any @@ -277,6 +331,48 @@ func frostfsidListGroups(cmd *cobra.Command, _ []string) { } } +func frostfsidAddSubjectToGroup(cmd *cobra.Command, _ []string) { + subjectAddress := getFrostfsIDSubjectAddress(cmd) + groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + + err := sendFrostfsIDTx(cmd, ffsidMethodArgs{name: "addSubjectToGroup", args: []any{subjectAddress, groupID}}) + commonCmd.ExitOnErr(cmd, "add subject to namespace error: %w", err) +} + +func frostfsidRemoveSubjectFromGroup(cmd *cobra.Command, _ []string) { + subjectAddress := getFrostfsIDSubjectAddress(cmd) + groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + + err := sendFrostfsIDTx(cmd, ffsidMethodArgs{name: "removeSubjectFromGroup", args: []any{subjectAddress, groupID}}) + commonCmd.ExitOnErr(cmd, "remove subject to namespace error: %w", err) +} + +func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { + ns, _ := cmd.Flags().GetString(namespaceFlag) + groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) + + ffsid, err := frostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + subjects, err := ffsid.ListGroupSubjects(ns, groupID) + commonCmd.ExitOnErr(cmd, "list group subjects: %w", err) + + sort.Slice(subjects, func(i, j int) bool { return subjects[i].Less(subjects[j]) }) + + for _, subjAddr := range subjects { + if !includeNames { + cmd.Println(address.Uint160ToString(subjAddr)) + continue + } + + subj, err := ffsid.GetSubject(subjAddr) + commonCmd.ExitOnErr(cmd, "get subject: %w", err) + + cmd.Printf("%s (%s)\n", address.Uint160ToString(subjAddr), subj.Name) + } +} + func sendFrostfsIDTx(cmd *cobra.Command, methodArgs ...ffsidMethodArgs) error { wCtx, err := newInitializeContext(cmd, viper.GetViper()) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go index 529d98dde5..dc7e581eb3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go @@ -41,20 +41,9 @@ func getFrostfsIDSubjectKey(cmd *cobra.Command) *keys.PublicKey { return subjKey } -//func decodeFrostfsIDNamespaces(resStack []stackitem.Item) ([]string, error) { -// var res []string -// -// if len(resStack) == 0 { -// return res, nil -// } -// -// if len(resStack) > 0 { -// nodes, err := decodeNodeList(resStack[0]) -// if err != nil { -// return nil, err -// } -// -// nm.SetNodes(nodes) -// } -// -//} +func getFrostfsIDSubjectAddress(cmd *cobra.Command) util.Uint160 { + subjAddress, _ := cmd.Flags().GetString(subjectAddressFlag) + subjAddr, err := address.StringToUint160(subjAddress) + commonCmd.ExitOnErr(cmd, "invalid subject address: %w", err) + return subjAddr +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 6db262175b..600fe21c8e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -303,6 +303,9 @@ func init() { initFrostfsIDCreateGroupCmd() initFrostfsIDDeleteGroupCmd() initFrostfsIDListGroupsCmd() + initFrostfsIDAddSubjectToGroupCmd() + initFrostfsIDRemoveSubjectFromGroupCmd() + initFrostfsIDListGroupSubjectsCmd() } func initProxyAddAccount() { From 136acdba21608c36099709cdaf3cd7c73c5b6551 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Mon, 15 Jan 2024 11:48:44 +0300 Subject: [PATCH 0271/1413] [#908] adm/frostfsid: Use client for write operations Signed-off-by: Denis Kirillov --- .../internal/modules/morph/frostfsid.go | 154 +++++++++++------- 1 file changed, 93 insertions(+), 61 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index a40ba4d4ca..938fb1b67e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -1,15 +1,18 @@ package morph import ( + "errors" "fmt" "sort" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -216,23 +219,23 @@ func initFrostfsIDListGroupSubjectsCmd() { frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") } -type ffsidMethodArgs struct { - name string - args []any -} - func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { ns, _ := cmd.Flags().GetString(namespaceFlag) - err := sendFrostfsIDTx(cmd, ffsidMethodArgs{name: "createNamespace", args: []any{ns}}) - commonCmd.ExitOnErr(cmd, "processing error: %w", err) + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + ffsid.addCall(ffsid.roCli.CreateNamespaceCall(ns)) + + err = ffsid.sendWait() + commonCmd.ExitOnErr(cmd, "create namespace error: %w", err) } func frostfsidListNamespaces(cmd *cobra.Command, _ []string) { - ffsid, err := frostfsIDClient(cmd) + ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) - namespaces, err := ffsid.ListNamespaces() + namespaces, err := ffsid.roCli.ListNamespaces() commonCmd.ExitOnErr(cmd, "list namespaces: %w", err) sort.Slice(namespaces, func(i, j int) bool { return namespaces[i].Name < namespaces[j].Name }) @@ -247,22 +250,27 @@ func frostfsidCreateSubject(cmd *cobra.Command, _ []string) { subjName, _ := cmd.Flags().GetString(subjectNameFlag) subjKey := getFrostfsIDSubjectKey(cmd) - args := []ffsidMethodArgs{ - {name: "createSubject", args: []any{ns, subjKey.Bytes()}}, - } + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + ffsid.addCall(ffsid.roCli.CreateSubjectCall(ns, subjKey)) if subjName != "" { - args = append(args, ffsidMethodArgs{name: "setSubjectName", args: []any{subjKey.GetScriptHash(), subjName}}) + ffsid.addCall(ffsid.roCli.SetSubjectNameCall(subjKey.GetScriptHash(), subjName)) } - err := sendFrostfsIDTx(cmd, args...) - commonCmd.ExitOnErr(cmd, "processing error: %w", err) + err = ffsid.sendWait() + commonCmd.ExitOnErr(cmd, "create subject: %w", err) } func frostfsidDeleteSubject(cmd *cobra.Command, _ []string) { subjectAddress := getFrostfsIDSubjectAddress(cmd) - err := sendFrostfsIDTx(cmd, ffsidMethodArgs{name: "deleteSubject", args: []any{subjectAddress}}) + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + ffsid.addCall(ffsid.roCli.DeleteSubjectCall(subjectAddress)) + + err = ffsid.sendWait() commonCmd.ExitOnErr(cmd, "delete subject error: %w", err) } @@ -270,10 +278,10 @@ func frostfsidListSubjects(cmd *cobra.Command, _ []string) { ns, _ := cmd.Flags().GetString(namespaceFlag) includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) - ffsid, err := frostfsIDClient(cmd) + ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) - subAddresses, err := ffsid.ListNamespaceSubjects(ns) + subAddresses, err := ffsid.roCli.ListNamespaceSubjects(ns) commonCmd.ExitOnErr(cmd, "list subjects: %w", err) sort.Slice(subAddresses, func(i, j int) bool { return subAddresses[i].Less(subAddresses[j]) }) @@ -284,7 +292,7 @@ func frostfsidListSubjects(cmd *cobra.Command, _ []string) { continue } - subj, err := ffsid.GetSubject(addr) + subj, err := ffsid.roCli.GetSubject(addr) commonCmd.ExitOnErr(cmd, "get subject: %w", err) cmd.Printf("%s (%s)\n", address.Uint160ToString(addr), subj.Name) @@ -295,10 +303,12 @@ func frostfsidCreateGroup(cmd *cobra.Command, _ []string) { ns, _ := cmd.Flags().GetString(namespaceFlag) groupName, _ := cmd.Flags().GetString(groupNameFlag) - ffsid, err := frostfsIDClient(cmd) + ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract client: %w", err) - groupID, err := ffsid.ParseGroupID(ffsid.Wait(ffsid.CreateGroup(ns, groupName))) + ffsid.addCall(ffsid.roCli.CreateGroupCall(ns, groupName)) + + groupID, err := ffsid.roCli.ParseGroupID(ffsid.sendWaitRes()) commonCmd.ExitOnErr(cmd, "create group: %w", err) cmd.Printf("group '%s' created with id: %d\n", groupName, groupID) @@ -308,20 +318,22 @@ func frostfsidDeleteGroup(cmd *cobra.Command, _ []string) { ns, _ := cmd.Flags().GetString(namespaceFlag) groupID, _ := cmd.Flags().GetInt64(groupIDFlag) - ffsid, err := frostfsIDClient(cmd) + ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract client: %w", err) - _, err = ffsid.Wait(ffsid.DeleteGroup(ns, groupID)) + ffsid.addCall(ffsid.roCli.DeleteGroupCall(ns, groupID)) + + err = ffsid.sendWait() commonCmd.ExitOnErr(cmd, "delete group error: %w", err) } func frostfsidListGroups(cmd *cobra.Command, _ []string) { ns, _ := cmd.Flags().GetString(namespaceFlag) - ffsid, err := frostfsIDClient(cmd) + ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) - groups, err := ffsid.ListGroups(ns) + groups, err := ffsid.roCli.ListGroups(ns) commonCmd.ExitOnErr(cmd, "list groups: %w", err) sort.Slice(groups, func(i, j int) bool { return groups[i].Name < groups[j].Name }) @@ -335,16 +347,26 @@ func frostfsidAddSubjectToGroup(cmd *cobra.Command, _ []string) { subjectAddress := getFrostfsIDSubjectAddress(cmd) groupID, _ := cmd.Flags().GetInt64(groupIDFlag) - err := sendFrostfsIDTx(cmd, ffsidMethodArgs{name: "addSubjectToGroup", args: []any{subjectAddress, groupID}}) - commonCmd.ExitOnErr(cmd, "add subject to namespace error: %w", err) + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + ffsid.addCall(ffsid.roCli.AddSubjectToGroupCall(subjectAddress, groupID)) + + err = ffsid.sendWait() + commonCmd.ExitOnErr(cmd, "add subject to group error: %w", err) } func frostfsidRemoveSubjectFromGroup(cmd *cobra.Command, _ []string) { subjectAddress := getFrostfsIDSubjectAddress(cmd) groupID, _ := cmd.Flags().GetInt64(groupIDFlag) - err := sendFrostfsIDTx(cmd, ffsidMethodArgs{name: "removeSubjectFromGroup", args: []any{subjectAddress, groupID}}) - commonCmd.ExitOnErr(cmd, "remove subject to namespace error: %w", err) + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + ffsid.addCall(ffsid.roCli.RemoveSubjectFromGroupCall(subjectAddress, groupID)) + + err = ffsid.sendWait() + commonCmd.ExitOnErr(cmd, "remove subject from group error: %w", err) } func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { @@ -352,10 +374,10 @@ func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { groupID, _ := cmd.Flags().GetInt64(groupIDFlag) includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) - ffsid, err := frostfsIDClient(cmd) + ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract client: %w", err) - subjects, err := ffsid.ListGroupSubjects(ns, groupID) + subjects, err := ffsid.roCli.ListGroupSubjects(ns, groupID) commonCmd.ExitOnErr(cmd, "list group subjects: %w", err) sort.Slice(subjects, func(i, j int) bool { return subjects[i].Less(subjects[j]) }) @@ -366,43 +388,21 @@ func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { continue } - subj, err := ffsid.GetSubject(subjAddr) + subj, err := ffsid.roCli.GetSubject(subjAddr) commonCmd.ExitOnErr(cmd, "get subject: %w", err) cmd.Printf("%s (%s)\n", address.Uint160ToString(subjAddr), subj.Name) } } -func sendFrostfsIDTx(cmd *cobra.Command, methodArgs ...ffsidMethodArgs) error { - wCtx, err := newInitializeContext(cmd, viper.GetViper()) - if err != nil { - return fmt.Errorf("can't to initialize context: %w", err) - } - - r := management.NewReader(wCtx.ReadOnlyInvoker) - cs, err := r.GetContractByID(1) - if err != nil { - return fmt.Errorf("can't get NNS contract info: %w", err) - } - - ffsidHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) - if err != nil { - return fmt.Errorf("can't get proxy contract hash: %w", err) - } - - bw := io.NewBufBinWriter() - for _, method := range methodArgs { - emit.AppCall(bw.BinWriter, ffsidHash, method.name, callflag.All, method.args...) - } - - if err = wCtx.sendConsensusTx(bw.Bytes()); err != nil { - return err - } - - return wCtx.awaitTx() +type frostfsidClient struct { + bw *io.BufBinWriter + contractHash util.Uint160 + roCli *frostfsidclient.Client // client can be used only for waiting tx, parsing and forming method params + wCtx *initializeContext } -func frostfsIDClient(cmd *cobra.Command) (*frostfsidclient.Client, error) { +func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { wCtx, err := newInitializeContext(cmd, viper.GetViper()) if err != nil { return nil, fmt.Errorf("can't to initialize context: %w", err) @@ -419,5 +419,37 @@ func frostfsIDClient(cmd *cobra.Command) (*frostfsidclient.Client, error) { return nil, fmt.Errorf("can't get proxy contract hash: %w", err) } - return frostfsidclient.NewSimple(wCtx.CommitteeAct, ffsidHash), nil + return &frostfsidClient{ + bw: io.NewBufBinWriter(), + contractHash: ffsidHash, + roCli: frostfsidclient.NewSimple(wCtx.CommitteeAct, ffsidHash), + wCtx: wCtx, + }, nil +} + +func (f *frostfsidClient) addCall(method string, args []any) { + emit.AppCall(f.bw.BinWriter, f.contractHash, method, callflag.All, args...) +} + +func (f *frostfsidClient) sendWait() error { + if err := f.wCtx.sendConsensusTx(f.bw.Bytes()); err != nil { + return err + } + f.bw.Reset() + + return f.wCtx.awaitTx() +} + +func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) { + if err := f.wCtx.sendConsensusTx(f.bw.Bytes()); err != nil { + return nil, err + } + f.bw.Reset() + + if len(f.wCtx.SentTxs) == 0 { + return nil, errors.New("no transactions to wait") + } + + f.wCtx.Command.Println("Waiting for transactions to persist...") + return f.roCli.Wait(f.wCtx.SentTxs[0].hash, f.wCtx.SentTxs[0].vub, nil) } From e42262a8632a6e636f94e8387a8f0349654380f9 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Wed, 17 Jan 2024 11:35:09 +0300 Subject: [PATCH 0272/1413] [#908] adm/frostfsid: Add parameter validations Signed-off-by: Denis Kirillov --- .../internal/modules/morph/frostfsid.go | 35 +++--- .../internal/modules/morph/frostfsid_util.go | 60 +++++++++ .../modules/morph/frostfsid_util_test.go | 119 ++++++++++++++++++ 3 files changed, 199 insertions(+), 15 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 938fb1b67e..2a6043b7c4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -28,6 +28,8 @@ const ( groupIDFlag = "group-id" ) +const rootNamespacePlaceholder = "" + var ( frostfsidCmd = &cobra.Command{ Use: "frostfsid", @@ -220,7 +222,7 @@ func initFrostfsIDListGroupSubjectsCmd() { } func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { - ns, _ := cmd.Flags().GetString(namespaceFlag) + ns := getFrostfsIDNamespace(cmd) ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract client: %w", err) @@ -241,13 +243,16 @@ func frostfsidListNamespaces(cmd *cobra.Command, _ []string) { sort.Slice(namespaces, func(i, j int) bool { return namespaces[i].Name < namespaces[j].Name }) for _, namespace := range namespaces { - cmd.Printf("%q\n", namespace.Name) + if namespace.Name == "" { + namespace.Name = rootNamespacePlaceholder + } + cmd.Printf("%s\n", namespace.Name) } } func frostfsidCreateSubject(cmd *cobra.Command, _ []string) { - ns, _ := cmd.Flags().GetString(namespaceFlag) - subjName, _ := cmd.Flags().GetString(subjectNameFlag) + ns := getFrostfsIDNamespace(cmd) + subjName := getFrostfsIDSubjectName(cmd) subjKey := getFrostfsIDSubjectKey(cmd) ffsid, err := newFrostfsIDClient(cmd) @@ -275,7 +280,7 @@ func frostfsidDeleteSubject(cmd *cobra.Command, _ []string) { } func frostfsidListSubjects(cmd *cobra.Command, _ []string) { - ns, _ := cmd.Flags().GetString(namespaceFlag) + ns := getFrostfsIDNamespace(cmd) includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) ffsid, err := newFrostfsIDClient(cmd) @@ -300,8 +305,8 @@ func frostfsidListSubjects(cmd *cobra.Command, _ []string) { } func frostfsidCreateGroup(cmd *cobra.Command, _ []string) { - ns, _ := cmd.Flags().GetString(namespaceFlag) - groupName, _ := cmd.Flags().GetString(groupNameFlag) + ns := getFrostfsIDNamespace(cmd) + groupName := getFrostfsIDGroupName(cmd) ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract client: %w", err) @@ -315,8 +320,8 @@ func frostfsidCreateGroup(cmd *cobra.Command, _ []string) { } func frostfsidDeleteGroup(cmd *cobra.Command, _ []string) { - ns, _ := cmd.Flags().GetString(namespaceFlag) - groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + ns := getFrostfsIDNamespace(cmd) + groupID := getFrostfsIDGroupID(cmd) ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract client: %w", err) @@ -328,7 +333,7 @@ func frostfsidDeleteGroup(cmd *cobra.Command, _ []string) { } func frostfsidListGroups(cmd *cobra.Command, _ []string) { - ns, _ := cmd.Flags().GetString(namespaceFlag) + ns := getFrostfsIDNamespace(cmd) ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) @@ -339,13 +344,13 @@ func frostfsidListGroups(cmd *cobra.Command, _ []string) { sort.Slice(groups, func(i, j int) bool { return groups[i].Name < groups[j].Name }) for _, group := range groups { - cmd.Printf("%q (%d)\n", group.Name, group.ID) + cmd.Printf("%s (%d)\n", group.Name, group.ID) } } func frostfsidAddSubjectToGroup(cmd *cobra.Command, _ []string) { subjectAddress := getFrostfsIDSubjectAddress(cmd) - groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + groupID := getFrostfsIDGroupID(cmd) ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract client: %w", err) @@ -358,7 +363,7 @@ func frostfsidAddSubjectToGroup(cmd *cobra.Command, _ []string) { func frostfsidRemoveSubjectFromGroup(cmd *cobra.Command, _ []string) { subjectAddress := getFrostfsIDSubjectAddress(cmd) - groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + groupID := getFrostfsIDGroupID(cmd) ffsid, err := newFrostfsIDClient(cmd) commonCmd.ExitOnErr(cmd, "init contract client: %w", err) @@ -370,8 +375,8 @@ func frostfsidRemoveSubjectFromGroup(cmd *cobra.Command, _ []string) { } func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { - ns, _ := cmd.Flags().GetString(namespaceFlag) - groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + ns := getFrostfsIDNamespace(cmd) + groupID := getFrostfsIDGroupID(cmd) includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) ffsid, err := newFrostfsIDClient(cmd) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go index dc7e581eb3..f88e4edfb7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go @@ -1,7 +1,9 @@ package morph import ( + "errors" "fmt" + "regexp" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -11,6 +13,14 @@ import ( "github.com/spf13/viper" ) +var ( + frostfsidSubjectNameRegexp = regexp.MustCompile(`^[\w+=,.@-]{1,64}$`) + frostfsidGroupNameRegexp = regexp.MustCompile(`^[\w+=,.@-]{1,128}$`) + + // frostfsidNamespaceNameRegexp similar to https://git.frostfs.info/TrueCloudLab/frostfs-contract/src/commit/f2a82aa635aa57d9b05092d8cf15b170b53cc324/nns/nns_contract.go#L690 + frostfsidNamespaceNameRegexp = regexp.MustCompile(`(^$)|(^[a-z0-9]{1,2}$)|(^[a-z0-9][a-z0-9-]{1,48}[a-z0-9]$)`) +) + func getFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { admin := v.GetString(frostfsIDAdminConfigKey) if admin == "" { @@ -47,3 +57,53 @@ func getFrostfsIDSubjectAddress(cmd *cobra.Command) util.Uint160 { commonCmd.ExitOnErr(cmd, "invalid subject address: %w", err) return subjAddr } + +func getFrostfsIDSubjectName(cmd *cobra.Command) string { + subjectName, _ := cmd.Flags().GetString(subjectNameFlag) + + if subjectName == "" { + return "" + } + + if !frostfsidSubjectNameRegexp.MatchString(subjectName) { + commonCmd.ExitOnErr(cmd, "invalid subject name: %w", + fmt.Errorf("name must match regexp: %s", frostfsidSubjectNameRegexp.String())) + } + + return subjectName +} + +func getFrostfsIDGroupName(cmd *cobra.Command) string { + groupName, _ := cmd.Flags().GetString(groupNameFlag) + + if !frostfsidGroupNameRegexp.MatchString(groupName) { + commonCmd.ExitOnErr(cmd, "invalid group name: %w", + fmt.Errorf("name must match regexp: %s", frostfsidGroupNameRegexp.String())) + } + + return groupName +} + +func getFrostfsIDGroupID(cmd *cobra.Command) int64 { + groupID, _ := cmd.Flags().GetInt64(groupIDFlag) + if groupID <= 0 { + commonCmd.ExitOnErr(cmd, "invalid group id: %w", + errors.New("group id must be positive integer")) + } + + return groupID +} + +func getFrostfsIDNamespace(cmd *cobra.Command) string { + ns, _ := cmd.Flags().GetString(namespaceFlag) + if ns == rootNamespacePlaceholder { + ns = "" + } + + if !frostfsidNamespaceNameRegexp.MatchString(ns) { + commonCmd.ExitOnErr(cmd, "invalid namespace: %w", + fmt.Errorf("name must match regexp: %s", frostfsidNamespaceNameRegexp.String())) + } + + return ns +} diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go index 192dc9f126..f73ebad08e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go @@ -51,3 +51,122 @@ func TestFrostfsIDConfig(t *testing.T) { require.False(t, found) }) } + +func TestNamespaceRegexp(t *testing.T) { + for _, tc := range []struct { + name string + namespace string + matched bool + }{ + { + name: "root empty ns", + namespace: "", + matched: true, + }, + { + name: "simple valid ns", + namespace: "my-namespace-123", + matched: true, + }, + { + name: "root placeholder", + namespace: "", + matched: false, + }, + { + name: "too long", + namespace: "abcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyz", + matched: false, + }, + { + name: "start with hyphen", + namespace: "-ns", + matched: false, + }, + { + name: "end with hyphen", + namespace: "ns-", + matched: false, + }, + { + name: "with spaces", + namespace: "ns ns", + matched: false, + }, + } { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.matched, frostfsidNamespaceNameRegexp.MatchString(tc.namespace)) + }) + } +} + +func TestSubjectNameRegexp(t *testing.T) { + for _, tc := range []struct { + name string + subject string + matched bool + }{ + { + name: "empty", + subject: "", + matched: false, + }, + { + name: "invalid", + subject: "invalid{name}", + matched: false, + }, + { + name: "too long", + subject: "abcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyz", + matched: false, + }, + { + name: "valid", + subject: "valid_name.012345@6789", + matched: true, + }, + } { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.matched, frostfsidSubjectNameRegexp.MatchString(tc.subject)) + }) + } +} + +func TestSubjectGroupRegexp(t *testing.T) { + for _, tc := range []struct { + name string + subject string + matched bool + }{ + { + name: "empty", + subject: "", + matched: false, + }, + { + name: "invalid", + subject: "invalid{name}", + matched: false, + }, + { + name: "too long", + subject: "abcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyz", + matched: false, + }, + { + name: "long", + subject: "abcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyzabcdefghijklmnopkrstuvwxyz", + matched: true, + }, + { + name: "valid", + subject: "valid_name.012345@6789", + matched: true, + }, + } { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.matched, frostfsidGroupNameRegexp.MatchString(tc.subject)) + }) + } +} From f5160b27fc94333cfe5cca3d04750f7980bf68d0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 18 Jan 2024 22:24:34 +0300 Subject: [PATCH 0273/1413] [#920] tests: Fix data races Signed-off-by: Dmitrii Stepanov --- .../engine/evacuate_test.go | 23 +++++++++++++++++++ .../engine/remove_copies_test.go | 9 ++++++++ pkg/local_object_storage/engine/tree_test.go | 5 ++++ 3 files changed, 37 insertions(+) diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index ca86ef5448..d874734d38 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -83,6 +83,9 @@ func TestEvacuateShard(t *testing.T) { const objPerShard = 3 e, ids, objects := newEngineEvacuate(t, 3, objPerShard) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() evacuateShardID := ids[2].String() @@ -161,6 +164,10 @@ func TestEvacuateNetwork(t *testing.T) { t.Run("single shard", func(t *testing.T) { t.Parallel() e, ids, objects := newEngineEvacuate(t, 1, 3) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() + evacuateShardID := ids[0].String() require.NoError(t, e.shards[evacuateShardID].SetMode(mode.ReadOnly)) @@ -181,6 +188,9 @@ func TestEvacuateNetwork(t *testing.T) { t.Run("multiple shards, evacuate one", func(t *testing.T) { t.Parallel() e, ids, objects := newEngineEvacuate(t, 2, 3) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) @@ -204,6 +214,10 @@ func TestEvacuateNetwork(t *testing.T) { t.Run("multiple shards, evacuate many", func(t *testing.T) { t.Parallel() e, ids, objects := newEngineEvacuate(t, 4, 5) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() + evacuateIDs := ids[0:3] var totalCount uint64 @@ -239,6 +253,9 @@ func TestEvacuateNetwork(t *testing.T) { func TestEvacuateCancellation(t *testing.T) { t.Parallel() e, ids, _ := newEngineEvacuate(t, 2, 3) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) @@ -264,6 +281,9 @@ func TestEvacuateCancellation(t *testing.T) { func TestEvacuateSingleProcess(t *testing.T) { e, ids, _ := newEngineEvacuate(t, 2, 3) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) @@ -303,6 +323,9 @@ func TestEvacuateSingleProcess(t *testing.T) { func TestEvacuateAsync(t *testing.T) { e, ids, _ := newEngineEvacuate(t, 2, 3) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) diff --git a/pkg/local_object_storage/engine/remove_copies_test.go b/pkg/local_object_storage/engine/remove_copies_test.go index 8131fcf0d5..dfb2423ffa 100644 --- a/pkg/local_object_storage/engine/remove_copies_test.go +++ b/pkg/local_object_storage/engine/remove_copies_test.go @@ -20,6 +20,9 @@ func TestRebalance(t *testing.T) { t.Parallel() te := newEngineWithErrorThreshold(t, "", 0) + defer func() { + require.NoError(t, te.ng.Close(context.Background())) + }() const ( objCount = 20 @@ -106,6 +109,9 @@ func TestRebalanceSingleThread(t *testing.T) { t.Parallel() te := newEngineWithErrorThreshold(t, "", 0) + defer func() { + require.NoError(t, te.ng.Close(context.Background())) + }() obj := testutil.GenerateObjectWithCID(cidtest.ID()) obj.SetPayload(make([]byte, errSmallSize)) @@ -153,6 +159,9 @@ type deleteEvent struct { func TestRebalanceExitByContext(t *testing.T) { te := newEngineWithErrorThreshold(t, "", 0) + defer func() { + require.NoError(t, te.ng.Close(context.Background())) + }() objects := make([]*objectSDK.Object, 4) for i := range objects { diff --git a/pkg/local_object_storage/engine/tree_test.go b/pkg/local_object_storage/engine/tree_test.go index f1650b5ae7..2739058e94 100644 --- a/pkg/local_object_storage/engine/tree_test.go +++ b/pkg/local_object_storage/engine/tree_test.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "github.com/stretchr/testify/require" ) func BenchmarkTreeVsSearch(b *testing.B) { @@ -25,6 +26,10 @@ func BenchmarkTreeVsSearch(b *testing.B) { func benchmarkTreeVsSearch(b *testing.B, objCount int) { te := newEngineWithErrorThreshold(b, "", 0) + defer func() { + require.NoError(b, te.ng.Close(context.Background())) + }() + cid := cidtest.ID() d := pilorama.CIDDescriptor{CID: cid, Position: 0, Size: 1} treeID := "someTree" From f526f49995575541626135e7d4542c0e014b63f2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 20 Dec 2023 17:18:28 +0300 Subject: [PATCH 0274/1413] [#874] engine: Check object existance concurrently Signed-off-by: Dmitrii Stepanov --- .../blobovnicza/exists.go | 12 ++++ pkg/local_object_storage/blobovnicza/get.go | 12 ++++ .../blobstor/blobovniczatree/get.go | 5 ++ .../blobstor/blobovniczatree/iterate.go | 18 +++++ pkg/local_object_storage/blobstor/exists.go | 14 ++-- .../blobstor/fstree/fstree.go | 6 ++ .../engine/engine_test.go | 6 ++ pkg/local_object_storage/engine/exists.go | 72 +++++++++++-------- pkg/local_object_storage/engine/put.go | 2 - pkg/local_object_storage/metabase/exists.go | 6 ++ pkg/local_object_storage/shard/exists.go | 6 ++ 11 files changed, 124 insertions(+), 35 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/exists.go b/pkg/local_object_storage/blobovnicza/exists.go index f7bc84d4af..b5d723ee6a 100644 --- a/pkg/local_object_storage/blobovnicza/exists.go +++ b/pkg/local_object_storage/blobovnicza/exists.go @@ -21,10 +21,22 @@ func (b *Blobovnicza) Exists(ctx context.Context, addr oid.Address) (bool, error )) defer span.End() + select { + case <-ctx.Done(): + return false, ctx.Err() + default: + } + addrKey := addressKey(addr) err := b.boltDB.View(func(tx *bbolt.Tx) error { return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if isNonDataBucket(bucketName) { return nil } diff --git a/pkg/local_object_storage/blobovnicza/get.go b/pkg/local_object_storage/blobovnicza/get.go index 600323f558..36cf69d54b 100644 --- a/pkg/local_object_storage/blobovnicza/get.go +++ b/pkg/local_object_storage/blobovnicza/get.go @@ -51,6 +51,12 @@ func (b *Blobovnicza) Get(ctx context.Context, prm GetPrm) (GetRes, error) { )) defer span.End() + select { + case <-ctx.Done(): + return GetRes{}, ctx.Err() + default: + } + var ( data []byte addrKey = addressKey(prm.addr) @@ -58,6 +64,12 @@ func (b *Blobovnicza) Get(ctx context.Context, prm GetPrm) (GetRes, error) { if err := b.boltDB.View(func(tx *bbolt.Tx) error { return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if isNonDataBucket(bucketName) { return nil } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 08cacda8ac..5f18566739 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -94,6 +94,11 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G // // returns error if object could not be read from any blobovnicza of the same level. func (b *Blobovniczas) getObjectFromLevel(ctx context.Context, prm blobovnicza.GetPrm, blzPath string) (common.GetRes, error) { + select { + case <-ctx.Done(): + return common.GetRes{}, ctx.Err() + default: + } // open blobovnicza (cached inside) shBlz := b.getBlobovnicza(blzPath) blz, err := shBlz.Open() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 92014fd558..942d73a120 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -230,6 +230,12 @@ func (b *Blobovniczas) iterateSortedDBPaths(ctx context.Context, addr oid.Addres } func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path string, addr oid.Address, f func(string) (bool, error)) (bool, error) { + select { + case <-ctx.Done(): + return false, ctx.Err() + default: + } + sysPath := filepath.Join(b.rootPath, path) entries, err := os.ReadDir(sysPath) if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode @@ -252,6 +258,12 @@ func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path st if len(dbIdxs) > 0 { for _, dbIdx := range dbIdxs { + select { + case <-ctx.Done(): + return false, ctx.Err() + default: + } + dbPath := filepath.Join(path, u64ToHexStringExt(dbIdx)) stop, err := f(dbPath) if err != nil { @@ -266,6 +278,12 @@ func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path st if len(dirIdxs) > 0 { hrw.SortSliceByValue(dirIdxs, addressHash(&addr, path)) for _, dirIdx := range dirIdxs { + select { + case <-ctx.Done(): + return false, ctx.Err() + default: + } + dirPath := filepath.Join(path, u64ToHexString(dirIdx)) stop, err := b.iterateSordedDBPathsInternal(ctx, dirPath, addr, f) if err != nil { diff --git a/pkg/local_object_storage/blobstor/exists.go b/pkg/local_object_storage/blobstor/exists.go index 43feec7c91..21b4016d22 100644 --- a/pkg/local_object_storage/blobstor/exists.go +++ b/pkg/local_object_storage/blobstor/exists.go @@ -3,6 +3,7 @@ package blobstor import ( "context" "encoding/hex" + "errors" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -57,27 +58,30 @@ func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exi // error | found | log the error, return true, nil // error | not found | return the error // error | error | log the first error, return the second - var errors []error + var storageErrors []error for i := range b.storage { res, err := b.storage[i].Storage.Exists(ctx, prm) if err == nil && res.Exists { exists = true return res, nil } else if err != nil { - errors = append(errors, err) + if errors.Is(err, context.Canceled) { + return common.ExistsRes{}, err + } + storageErrors = append(storageErrors, err) } } - if len(errors) == 0 { + if len(storageErrors) == 0 { return common.ExistsRes{}, nil } - for _, err := range errors[:len(errors)-1] { + for _, err := range storageErrors[:len(storageErrors)-1] { b.log.Warn(logs.BlobstorErrorOccurredDuringObjectExistenceChecking, zap.Stringer("address", prm.Address), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } - return common.ExistsRes{}, errors[len(errors)-1] + return common.ExistsRes{}, storageErrors[len(storageErrors)-1] } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 948872fd2d..af241becf6 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -302,6 +302,12 @@ func (t *FSTree) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exist )) defer span.End() + select { + case <-ctx.Done(): + return common.ExistsRes{}, ctx.Err() + default: + } + p := t.treePath(prm.Address) _, err := os.Stat(p) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index a62734c0a3..b20f45be50 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -39,6 +39,12 @@ func BenchmarkExists(b *testing.B) { b.Run("8 shards", func(b *testing.B) { benchmarkExists(b, 8) }) + b.Run("12 shards", func(b *testing.B) { + benchmarkExists(b, 12) + }) + b.Run("16 shards", func(b *testing.B) { + benchmarkExists(b, 12) + }) } func benchmarkExists(b *testing.B, shardNum int) { diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index ef62927686..ee4dad341a 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -3,54 +3,70 @@ package engine import ( "context" "errors" + "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "golang.org/x/sync/errgroup" ) func (e *StorageEngine) exists(ctx context.Context, addr oid.Address) (bool, error) { var shPrm shard.ExistsPrm shPrm.SetAddress(addr) - alreadyRemoved := false - exists := false + + var exists atomic.Bool + eg, egCtx := errgroup.WithContext(ctx) + egCtx, cancel := context.WithCancel(egCtx) + defer cancel() e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { - res, err := sh.Exists(ctx, shPrm) - if err != nil { - if client.IsErrObjectAlreadyRemoved(err) { - alreadyRemoved = true - - return true - } - - var siErr *objectSDK.SplitInfoError - if errors.As(err, &siErr) { - return true - } - - if shard.IsErrObjectExpired(err) { - return true - } - - if !client.IsErrObjectNotFound(err) { - e.reportShardError(sh, "could not check existence of object in shard", err) - } - return false + select { + case <-egCtx.Done(): + return true + default: } - if !exists { - exists = res.Exists() - } + eg.Go(func() error { + res, err := sh.Exists(egCtx, shPrm) + if err != nil { + if errors.Is(err, context.Canceled) { + return err + } + if client.IsErrObjectAlreadyRemoved(err) { + return err + } + + var siErr *objectSDK.SplitInfoError + if errors.As(err, &siErr) { + return err + } + + if shard.IsErrObjectExpired(err) { + return err + } + + if !client.IsErrObjectNotFound(err) { + e.reportShardError(sh, "could not check existence of object in shard", err) + } + return nil + } + if res.Exists() { + exists.Store(true) + cancel() + } + return nil + }) return false }) - if alreadyRemoved { + err := eg.Wait() + if client.IsErrObjectAlreadyRemoved(err) { return false, new(apistatus.ObjectAlreadyRemoved) } - return exists, nil + return exists.Load(), nil } diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 79ee3a9976..7ce915ad86 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -63,8 +63,6 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { addr := object.AddressOf(prm.obj) - // In #1146 this check was parallelized, however, it became - // much slower on fast machines for 4 shards. _, err := e.exists(ctx, addr) if err != nil { return err diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index aa9aba1064..bca18e21ff 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -67,6 +67,12 @@ func (db *DB) Exists(ctx context.Context, prm ExistsPrm) (res ExistsRes, err err return res, ErrDegradedMode } + select { + case <-ctx.Done(): + return res, ctx.Err() + default: + } + currEpoch := db.epochState.CurrentEpoch() err = db.boltDB.View(func(tx *bbolt.Tx) error { diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index 2cdb8dfa8e..7296426a6e 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -47,6 +47,12 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { )) defer span.End() + select { + case <-ctx.Done(): + return ExistsRes{}, ctx.Err() + default: + } + var exists bool var err error From f2f3294fc3e827ba8faecdf6ab121ba5cbe85231 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 18 Jan 2024 14:35:52 +0300 Subject: [PATCH 0275/1413] [#919] ape: Improve error messages in ape service * Wrap all APE middleware errors in apeErr that makes errors more explicit with status AccessDenied. * Use denyingRuleErr for denying status from chain router. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/checker.go | 11 +-------- pkg/services/object/ape/checker_test.go | 6 ++--- pkg/services/object/ape/errors.go | 13 +++++++++++ pkg/services/object/ape/service.go | 30 ++++++++++++------------- 4 files changed, 32 insertions(+), 28 deletions(-) create mode 100644 pkg/services/object/ape/errors.go diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index fdaa9df856..ccd23bf069 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -5,7 +5,6 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -70,13 +69,5 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { return nil } - return apeErr(prm.Method, status) -} - -const accessDeniedAPEReasonFmt = "access to operation %s is denied by access policy engine: %s" - -func apeErr(op string, status apechain.Status) error { - errAccessDenied := &apistatus.ObjectAccessDenied{} - errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedAPEReasonFmt, op, status.String())) - return errAccessDenied + return fmt.Errorf("found denying rule for %s: %s", prm.Method, status) } diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 9d548480b3..08d0979071 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -308,7 +308,8 @@ func TestAPECheck(t *testing.T) { ms := inmemory.NewInmemoryMorphRuleChainStorage() ls.AddOverride(chain.Ingress, policyengine.ContainerTarget(test.container), &chain.Chain{ - Rules: test.containerRules, + Rules: test.containerRules, + MatchType: chain.MatchTypeFirstMatch, }) router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) @@ -336,8 +337,7 @@ func TestAPECheck(t *testing.T) { err := checker.CheckAPE(context.Background(), prm) if test.expectAPEErr { - aErr := apeErr(method, chain.AccessDenied) - require.ErrorAs(t, err, &aErr) + require.Error(t, err) } else { require.NoError(t, err) } diff --git a/pkg/services/object/ape/errors.go b/pkg/services/object/ape/errors.go new file mode 100644 index 0000000000..7c2a82dfdf --- /dev/null +++ b/pkg/services/object/ape/errors.go @@ -0,0 +1,13 @@ +package ape + +import ( + "fmt" + + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" +) + +func toStatusErr(err error) error { + errAccessDenied := &apistatus.ObjectAccessDenied{} + errAccessDenied.WriteReason(fmt.Sprintf("ape denied request: %s", err.Error())) + return errAccessDenied +} diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index d28ad4aeb3..781f9df4b6 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -69,7 +69,7 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { if partInit, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok { cnrID, objID, err := getAddressParamsSDK(partInit.GetHeader().GetContainerID(), partInit.GetObjectID()) if err != nil { - return err + return toStatusErr(err) } prm := Prm{ @@ -82,7 +82,7 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { } if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { - return err + return toStatusErr(err) } } return g.GetObjectStream.Send(resp) @@ -103,12 +103,12 @@ func requestContext(ctx context.Context) (*objectSvc.RequestContext, error) { func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectStream) error { cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { - return err + return toStatusErr(err) } reqCtx, err := requestContext(stream.Context()) if err != nil { - return err + return toStatusErr(err) } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ @@ -120,7 +120,7 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt SenderKey: hex.EncodeToString(reqCtx.SenderKey), }) if err != nil { - return err + return toStatusErr(err) } return c.next.Get(request, &getStreamBasicChecker{ @@ -139,12 +139,12 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR if partInit, ok := request.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok { reqCtx, err := requestContext(ctx) if err != nil { - return err + return toStatusErr(err) } cnrID, objID, err := getAddressParamsSDK(partInit.GetHeader().GetContainerID(), partInit.GetObjectID()) if err != nil { - return err + return toStatusErr(err) } prm := Prm{ @@ -158,7 +158,7 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { - return err + return toStatusErr(err) } } @@ -244,13 +244,13 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc var cnrID cid.ID if cnrV2 := request.GetBody().GetContainerID(); cnrV2 != nil { if err := cnrID.ReadFromV2(*cnrV2); err != nil { - return err + return toStatusErr(err) } } reqCtx, err := requestContext(stream.Context()) if err != nil { - return err + return toStatusErr(err) } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ @@ -261,7 +261,7 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc SenderKey: hex.EncodeToString(reqCtx.SenderKey), }) if err != nil { - return err + return toStatusErr(err) } return c.next.Search(request, stream) @@ -301,12 +301,12 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.GetObjectRangeStream) error { cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { - return err + return toStatusErr(err) } reqCtx, err := requestContext(stream.Context()) if err != nil { - return err + return toStatusErr(err) } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ @@ -318,7 +318,7 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G SenderKey: hex.EncodeToString(reqCtx.SenderKey), }) if err != nil { - return err + return toStatusErr(err) } return c.next.GetRange(request, stream) @@ -381,7 +381,7 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { - return nil, err + return nil, toStatusErr(err) } return c.next.PutSingle(ctx, request) From 931a5e9aaf5e69afc1e71f256879a031d9c32a26 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 18 Jan 2024 13:39:21 +0300 Subject: [PATCH 0276/1413] [#918] engine: Move shard to degraded mode if metabase open failed Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 + .../engine/control_test.go | 49 +++++++++---------- pkg/local_object_storage/engine/shards.go | 4 +- pkg/local_object_storage/shard/id.go | 46 ++++++++++------- 4 files changed, 53 insertions(+), 47 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 606b5cb9a8..34ca0ae937 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -571,4 +571,5 @@ const ( GetSvcV2FailedToParseNodeExternalAddresses = "failed to parse node external addresses" GetSvcV2FailedToGetRangeHashFromNode = "failed to get range hash from node" GetSvcV2FailedToGetRangeHashFromAllOfContainerNodes = "failed to get range hash from all of container nodes" + FailedToUpdateShardID = "failed to update shard id" ) diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 0f36f3203f..6bf6beac6f 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -118,7 +118,7 @@ func TestInitializationFailure(t *testing.T) { }) } -func testEngineFailInitAndReload(t *testing.T, errOnAdd bool, opts []shard.Option, beforeReload func()) { +func testEngineFailInitAndReload(t *testing.T, degradedMode bool, opts []shard.Option, beforeReload func()) { var configID string e := New() @@ -126,33 +126,30 @@ func testEngineFailInitAndReload(t *testing.T, errOnAdd bool, opts []shard.Optio require.NoError(t, e.Close(context.Background())) }() _, err := e.AddShard(context.Background(), opts...) - if errOnAdd { - require.Error(t, err) - // This branch is only taken when we cannot update shard ID in the metabase. - // The id cannot be encountered during normal operation, but it is ok for tests: - // it is only compared for equality with other ids and we have 0 shards here. - configID = "id" - } else { - require.NoError(t, err) - - e.mtx.RLock() - var id string - for id = range e.shards { - break - } - configID = calculateShardID(e.shards[id].Shard.DumpInfo()) - e.mtx.RUnlock() - - err = e.Open(context.Background()) - if err == nil { - require.Error(t, e.Init(context.Background())) - } - } + require.NoError(t, err) e.mtx.RLock() - shardCount := len(e.shards) + var id string + for id = range e.shards { + break + } + configID = calculateShardID(e.shards[id].Shard.DumpInfo()) e.mtx.RUnlock() - require.Equal(t, 0, shardCount) + + err = e.Open(context.Background()) + require.NoError(t, err) + if degradedMode { + require.NoError(t, e.Init(context.Background())) + require.Equal(t, mode.DegradedReadOnly, e.DumpInfo().Shards[0].Mode) + return + } else { + require.Error(t, e.Init(context.Background())) + + e.mtx.RLock() + shardCount := len(e.shards) + e.mtx.RUnlock() + require.Equal(t, 0, shardCount) + } beforeReload() @@ -161,7 +158,7 @@ func testEngineFailInitAndReload(t *testing.T, errOnAdd bool, opts []shard.Optio })) e.mtx.RLock() - shardCount = len(e.shards) + shardCount := len(e.shards) e.mtx.RUnlock() require.Equal(t, 1, shardCount) } diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 0455471e22..37a857c9d0 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -124,10 +124,10 @@ func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (* )...) if err := sh.UpdateID(ctx); err != nil { - return nil, fmt.Errorf("could not update shard ID: %w", err) + e.log.Warn(logs.FailedToUpdateShardID, zap.Stringer("shard_id", sh.ID()), zap.String("metabase_path", sh.DumpInfo().MetaBaseInfo.Path), zap.Error(err)) } - return sh, err + return sh, nil } func (e *StorageEngine) appendMetrics(id *shard.ID, opts []shard.Option) []shard.Option { diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index b0d95e54ca..e3c209907d 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -2,6 +2,7 @@ package shard import ( "context" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/mr-tron/base58" @@ -30,27 +31,32 @@ func (s *Shard) ID() *ID { // UpdateID reads shard ID saved in the metabase and updates it if it is missing. func (s *Shard) UpdateID(ctx context.Context) (err error) { + var metabaseOpened bool + var idFromMetabase []byte if err = s.metaBase.Open(ctx, false); err != nil { - return err + err = fmt.Errorf("failed to open metabase: %w", err) + } else { + metabaseOpened = true } - defer func() { - cErr := s.metaBase.Close() - if err == nil { - err = cErr - } - }() - id, err := s.metaBase.ReadShardID() - if err != nil { - return err - } - if len(id) != 0 { - s.info.ID = NewIDFromBytes(id) - - if s.cfg.metricsWriter != nil { - s.cfg.metricsWriter.SetShardID(s.info.ID.String()) + if metabaseOpened { + defer func() { + cErr := s.metaBase.Close() + if cErr != nil { + err = fmt.Errorf("failed to close metabase: %w", cErr) + } + }() + if idFromMetabase, err = s.metaBase.ReadShardID(); err != nil { + err = fmt.Errorf("failed to read shard id from metabase: %w", err) } } + if len(idFromMetabase) != 0 { + s.info.ID = NewIDFromBytes(idFromMetabase) + } + + if s.cfg.metricsWriter != nil { + s.cfg.metricsWriter.SetShardID(s.info.ID.String()) + } s.log = &logger.Logger{Logger: s.log.With(zap.Stringer("shard_id", s.info.ID))} s.metaBase.SetLogger(s.log) s.blobStor.SetLogger(s.log) @@ -63,8 +69,10 @@ func (s *Shard) UpdateID(ctx context.Context) (err error) { s.pilorama.SetParentID(s.info.ID.String()) } - if len(id) != 0 { - return nil + if len(idFromMetabase) == 0 && metabaseOpened { + if err = s.metaBase.WriteShardID(*s.info.ID); err != nil { + err = fmt.Errorf("failed to write shard id to metabase: %w", err) + } } - return s.metaBase.WriteShardID(*s.info.ID) + return } From 5ed330e43649ba3be8d894b7a2990214a7aed05b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 24 Jan 2024 18:41:02 +0300 Subject: [PATCH 0277/1413] [#927] metabase: Delete GC marks `key` is changed inside `db.get`, so encode address again after get. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete.go | 1 + .../metabase/delete_test.go | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 8ca0dea616..484dbe41b6 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -264,6 +264,7 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter return deleteSingleResult{}, err } + addrKey = addressKey(addr, key) // remove record from the garbage bucket if garbageBKT != nil { err := garbageBKT.Delete(addrKey) diff --git a/pkg/local_object_storage/metabase/delete_test.go b/pkg/local_object_storage/metabase/delete_test.go index 2ff6ba89f4..5a52868d3a 100644 --- a/pkg/local_object_storage/metabase/delete_test.go +++ b/pkg/local_object_storage/metabase/delete_test.go @@ -140,6 +140,48 @@ func TestExpiredObject(t *testing.T) { }) } +func TestDelete(t *testing.T) { + db := newDB(t, meta.WithEpochState(epochState{currEpoch})) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + for i := 0; i < 10; i++ { + obj := testutil.GenerateObjectWithCID(cnr) + + var prm meta.PutPrm + prm.SetObject(obj) + prm.SetStorageID([]byte("0/0")) + _, err := db.Put(context.Background(), prm) + require.NoError(t, err) + + var inhumePrm meta.InhumePrm + inhumePrm.SetAddresses(object.AddressOf(obj)) + _, err = db.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + } + + var addrs []oid.Address + var iprm meta.GarbageIterationPrm + iprm.SetHandler(func(o meta.GarbageObject) error { + addrs = append(addrs, o.Address()) + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), iprm)) + require.Equal(t, 10, len(addrs)) + var deletePrm meta.DeletePrm + deletePrm.SetAddresses(addrs...) + _, err := db.Delete(context.Background(), deletePrm) + require.NoError(t, err) + + addrs = nil + iprm.SetHandler(func(o meta.GarbageObject) error { + addrs = append(addrs, o.Address()) + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), iprm)) + require.Equal(t, 0, len(addrs)) +} + func metaDelete(db *meta.DB, addrs ...oid.Address) error { var deletePrm meta.DeletePrm deletePrm.SetAddresses(addrs...) From cc2da73b20a9aefd9fcab5ce9bb9312ffd41153d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 24 Jan 2024 20:09:20 +0300 Subject: [PATCH 0278/1413] [#929] go.mod: Update dependencies Signed-off-by: Evgenii Stratonikov --- go.mod | 77 +++++++++++++------------- go.sum | 170 ++++++++++++++++++++++++++++++--------------------------- 2 files changed, 128 insertions(+), 119 deletions(-) diff --git a/go.mod b/go.mod index 8b48cd788f..3b269db344 100644 --- a/go.mod +++ b/go.mod @@ -3,51 +3,50 @@ module git.frostfs.info/TrueCloudLab/frostfs-node go 1.20 require ( - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240117145620-110b7e41706e git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240112075604-c80c99b13e53 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240122104724-06cbfe8691ad git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 - github.com/google/uuid v1.4.0 + github.com/google/uuid v1.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/klauspost/compress v1.17.4 github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 - github.com/multiformats/go-multiaddr v0.12.0 - github.com/nats-io/nats.go v1.31.0 - github.com/nspcc-dev/neo-go v0.105.0 + github.com/multiformats/go-multiaddr v0.12.1 + github.com/nats-io/nats.go v1.32.0 + github.com/nspcc-dev/neo-go v0.105.1 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 - github.com/paulmach/orb v0.9.2 - github.com/prometheus/client_golang v1.17.0 + github.com/paulmach/orb v0.11.0 + github.com/prometheus/client_golang v1.18.0 github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.17.0 + github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.8.4 go.etcd.io/bbolt v1.3.8 - go.opentelemetry.io/otel v1.21.0 - go.opentelemetry.io/otel/trace v1.21.0 + go.opentelemetry.io/otel v1.22.0 + go.opentelemetry.io/otel/trace v1.22.0 go.uber.org/zap v1.26.0 - golang.org/x/exp v0.0.0-20231127185646-65229373498e - golang.org/x/sync v0.5.0 - golang.org/x/term v0.15.0 - google.golang.org/grpc v1.59.0 - google.golang.org/protobuf v1.31.0 + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a + golang.org/x/sync v0.6.0 + golang.org/x/term v0.16.0 + google.golang.org/grpc v1.61.0 + google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - go.mongodb.org/mongo-driver v1.11.4 // indirect + go.mongodb.org/mongo-driver v1.13.1 // indirect ) require ( @@ -55,23 +54,23 @@ require ( git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bits-and-blooms/bitset v1.11.0 // indirect + github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/bavard v0.1.13 // indirect - github.com/consensys/gnark-crypto v0.12.2-0.20231117165148-e77308824822 // indirect + github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect @@ -88,15 +87,15 @@ require ( github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-varint v0.0.7 // indirect - github.com/nats-io/nkeys v0.4.6 // indirect + github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect - github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c // indirect - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231201072346-6c0c2a6a98b0 // indirect + github.com/nspcc-dev/go-ordered-json v0.0.0-20240112074137-296698a162ae // indirect + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240122090917-ef99a7a9e33f // indirect github.com/nspcc-dev/rfc6979 v0.2.0 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/common v0.46.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -106,19 +105,19 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/twmb/murmur3 v1.1.8 // indirect github.com/urfave/cli v1.22.14 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/sdk v1.21.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/sdk v1.22.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.19.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 11b208d32c..ca28fdaec2 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,17 @@ -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd h1:MxiIXu4vUATX9bNYFnM1dXAYkx5dnPOGCMzwNNXJEvM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20231031104748-498877e378fd/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c h1:dO2VLtoTQre4W28i1gSuW1MO80qFd0Lq9Q46Pu3q3TA= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa h1:uuN90s74idThHXi/jF/IlTdFimOIs+IBU44rdTE/Zdo= git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e h1:RoGxgSNyVxDaYgjb40P+Xy6val+rs7b5QQtGkIUpUoY= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20231122162120-56debcfa569e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240117145620-110b7e41706e h1:0t+3iEb2wFJjJryqGnh5wkr9DEiwRNb61KaxC27U+po= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240117145620-110b7e41706e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240112075604-c80c99b13e53 h1:LNfUfiGx3cECl15Q5ZspILWZriCeevH4Ue+eynKgGYQ= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240112075604-c80c99b13e53/go.mod h1:ps6oKO0mxaPJzK3admTB3iwoBXKkHnS73n4PCrqpHBg= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240122104724-06cbfe8691ad h1:+D96Uu0Pw+55CrxP+srazthtZAh0Q19BtJo1Pm4hOP0= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240122104724-06cbfe8691ad/go.mod h1:ps6oKO0mxaPJzK3admTB3iwoBXKkHnS73n4PCrqpHBg= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= @@ -21,8 +21,8 @@ github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8 github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bits-and-blooms/bitset v1.11.0 h1:RMyy2mBBShArUAhfVRZJ2xyBO58KCBCtZFShw3umo6k= -github.com/bits-and-blooms/bitset v1.11.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= +github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -40,8 +40,8 @@ github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark-crypto v0.12.2-0.20231117165148-e77308824822 h1:PvEjRgB/U4bv0jl9w65Wy9g0nIdkkW7vkNoR8Vq/als= -github.com/consensys/gnark-crypto v0.12.2-0.20231117165148-e77308824822/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 h1:tYj5Ydh5D7Xg2R1tJnoG36Yta7NVB8C0vx36oPA3Bbw= +github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -62,8 +62,8 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -90,16 +90,16 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tggROQKKcnh4eItay6z/HbHLqghBxS8g7pyMhmDio= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0/go.mod h1:hKAkSgNkL0FII46ZkJcpVEAai4KV+swlIWCKfekd1pA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -138,8 +138,6 @@ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 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/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -156,26 +154,26 @@ github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aG github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= 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-multiaddr v0.12.0 h1:1QlibTFkoXJuDjjYsMHhE73TnzJQl8FSWatk/0gxGzE= -github.com/multiformats/go-multiaddr v0.12.0/go.mod h1:WmZXgObOQOYp9r3cslLlppkrz1FYSHmE834dfz/lWu8= +github.com/multiformats/go-multiaddr v0.12.1 h1:vm+BA/WZA8QZDp1pF1FWhi5CT3g1tbi5GJmqpb6wnlk= +github.com/multiformats/go-multiaddr v0.12.1/go.mod h1:7mPkiBMmLeFipt+nNSq9pHZUeJSt8lHBgH6yhj0YQzE= 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-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-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/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= -github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= -github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= -github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= +github.com/nats-io/nats.go v1.32.0 h1:Bx9BZS+aXYlxW08k8Gd3yR2s73pV5XSoAQUyp1Kwvp0= +github.com/nats-io/nats.go v1.32.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= +github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c h1:OOQeE613BH93ICPq3eke5N78gWNeMjcBWkmD2NKyXVg= -github.com/nspcc-dev/go-ordered-json v0.0.0-20231123160306-3374ff1e7a3c/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= -github.com/nspcc-dev/neo-go v0.105.0 h1:vtNZYFEFySK8zRDhLzQYha849VzWrcKezlnq/oNQg/w= -github.com/nspcc-dev/neo-go v0.105.0/go.mod h1:6pchIHg5okeZO955RxpTh5q0sUI0vtpgPM6Q+no1rlI= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231201072346-6c0c2a6a98b0 h1:GYeU/mq2qfq6fNSuTzgxvlQQUydeCBicjzdnggwtuz0= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20231201072346-6c0c2a6a98b0/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag= +github.com/nspcc-dev/go-ordered-json v0.0.0-20240112074137-296698a162ae h1:UFgMXcZthqiCqCyr3dOAtGICJ10gM8q0mFHyLR0UPQU= +github.com/nspcc-dev/go-ordered-json v0.0.0-20240112074137-296698a162ae/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= +github.com/nspcc-dev/neo-go v0.105.1 h1:r0b2yIwLBi+ARBKU94gHL9oTFEB/XMJ0YlS2HN9Qw34= +github.com/nspcc-dev/neo-go v0.105.1/go.mod h1:GNh0cRALV/cuj+/xg2ZHDsrFbqcInqG7jjhqsLEnlNc= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240122090917-ef99a7a9e33f h1:6h0zgQGKdStROXRlWhz2dZmrKkSmOJ4oiDs06nO39XI= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240122090917-ef99a7a9e33f/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -196,21 +194,21 @@ github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo= github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= -github.com/paulmach/orb v0.9.2 h1:p/YWV2uJwamAynnDOJGNbPBVtDHj3vG51k9tR1rFwJE= -github.com/paulmach/orb v0.9.2/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= +github.com/paulmach/orb v0.11.0 h1:JfVXJUBeH9ifc/OrhBY0lL16QsmPgpCHMlqSSYhcgAA= +github.com/paulmach/orb v0.11.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= +github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -235,8 +233,8 @@ github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI= -github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -253,7 +251,6 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= @@ -263,30 +260,34 @@ github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtb github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.mongodb.org/mongo-driver v1.11.4 h1:4ayjakA013OdpGyL2K3ZqylTac/rMjrJOMZ1EHizXas= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0 h1:VhlEQAPp9R1ktYfrPk5SOryw1e9LDDTZCbIPFrho0ec= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.21.0/go.mod h1:kB3ufRbfU+CQ4MlUcqtW8Z7YEOBeK2DJ6CmR5rYYF3E= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= -go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= -go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= +go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0 h1:zr8ymM5OWWjjiWRzwTfZ67c905+2TMHYp2lMJ52QTyM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0/go.mod h1:sQs7FT2iLVJ+67vYngGJkPe1qr39IzaBzaj9IDNNY8k= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -295,13 +296,15 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/exp v0.0.0-20231127185646-65229373498e h1:Gvh4YaCaXNs6dKTlfgismwWZKyjVZXwOPfIyUaqU3No= -golang.org/x/exp v0.0.0-20231127185646-65229373498e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= 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= @@ -309,20 +312,23 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -343,17 +349,20 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -361,19 +370,20 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f h1:Vn+VyHU5guc9KjB5KrjI2q0wCOWEOIh0OEsleqakHJg= -google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 h1:ZcOkrmX74HbKFYnpPY8Qsw93fC29TbJXspYKaBkSXDQ= -google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4/go.mod h1:k2dtGpRrbsSyKcNPKKI5sstZkrNCZwpU/ns96JoHbGg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 h1:DC7wcm+i+P1rN3Ff07vL+OndGg5OhNddHyTA+ocPqYE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= +google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -383,8 +393,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From c00eb7cceec6f4e598333588bf043141a4ccce0d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 24 Jan 2024 11:02:05 +0300 Subject: [PATCH 0279/1413] [#768] adm: Return error from getContractDeployData() Make code more idiomatic and unify in style with other error reporting. Retain panics for code errors. Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize_deploy.go | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 61536b4d55..dd304d8afa 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -222,7 +222,11 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash invokeHash = ctrHash } - params := getContractDeployParameters(cs, c.getContractDeployData(ctrName, keysParam, updateMethodName)) + args, err := c.getContractDeployData(ctrName, keysParam, updateMethodName) + if err != nil { + return fmt.Errorf("%s: getting update params: %v", ctrName, err) + } + params := getContractDeployParameters(cs, args) res, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) if err != nil { if method != updateMethodName || !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { @@ -345,7 +349,11 @@ func (c *initializeContext) deployContracts() error { return fmt.Errorf("can't sign manifest group: %v", err) } - params := getContractDeployParameters(cs, c.getContractDeployData(ctrName, keysParam, deployMethodName)) + args, err := c.getContractDeployData(ctrName, keysParam, deployMethodName) + if err != nil { + return fmt.Errorf("%s: getting deploy params: %v", ctrName, err) + } + params := getContractDeployParameters(cs, args) res, err := c.CommitteeAct.MakeCall(management.Hash, deployMethodName, params...) if err != nil { return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) @@ -511,7 +519,7 @@ func getContractDeployParameters(cs *contractState, deployData []any) []any { return []any{cs.RawNEF, cs.RawManifest, deployData} } -func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any, method string) []any { +func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any, method string) ([]any, error) { items := make([]any, 0, 6) switch ctrName { @@ -522,7 +530,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an smartcontract.Parameter{}) case processingContract: items = append(items, c.Contracts[frostfsContract].Hash) - return items[1:] // no notary info + return items[1:], nil // no notary info case balanceContract: items = append(items, c.Contracts[netmapContract].Hash, @@ -533,7 +541,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an r := management.NewReader(c.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { - panic("NNS is not yet deployed") + return nil, errors.New("NNS is not yet deployed") } items = append(items, c.Contracts[netmapContract].Hash, @@ -544,7 +552,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an case frostfsIDContract: h, found, err := getFrostfsIDAdmin(viper.GetViper()) if err != nil { - panic(err) + return nil, err } if found { @@ -557,11 +565,11 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an if method == updateMethodName { arr, err := c.getNetConfigFromNetmapContract() if err != nil { - panic(err) + return nil, err } m, err := parseConfigFromNetmapContract(arr) if err != nil { - panic(err) + return nil, err } for k, v := range m { for _, key := range netmapConfigKeys { @@ -590,7 +598,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an default: panic(fmt.Sprintf("invalid contract name: %s", ctrName)) } - return items + return items, nil } func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, error) { From 61a3afbf9b1039b6663b2ecf88786491d7ed0d3f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 24 Jan 2024 11:04:37 +0300 Subject: [PATCH 0280/1413] [#768] adm: Rephrase error text for NNS fetch Error could come from the network, we must not assume everything. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index dd304d8afa..20e44a81a0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -541,7 +541,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an r := management.NewReader(c.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { - return nil, errors.New("NNS is not yet deployed") + return nil, fmt.Errorf("get nns contract: %w", err) } items = append(items, c.Contracts[netmapContract].Hash, @@ -605,7 +605,7 @@ func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, r := management.NewReader(c.ReadOnlyInvoker) cs, err := r.GetContractByID(1) if err != nil { - return nil, fmt.Errorf("NNS is not yet deployed: %w", err) + return nil, fmt.Errorf("get nns contract: %w", err) } nmHash, err := nnsResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { From d2d850786d83b8da0ef8a0c36dfcd98efed5678c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 24 Jan 2024 19:43:17 +0300 Subject: [PATCH 0281/1413] [#923] adm: Move netconfig merge to a separate function Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize_deploy.go | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 20e44a81a0..ca3a9599f1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -563,22 +563,9 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an case netmapContract: md := getDefaultNetmapContractConfigMap() if method == updateMethodName { - arr, err := c.getNetConfigFromNetmapContract() - if err != nil { + if err := c.mergeNetmapConfig(md); err != nil { return nil, err } - m, err := parseConfigFromNetmapContract(arr) - if err != nil { - return nil, err - } - for k, v := range m { - for _, key := range netmapConfigKeys { - if k == key { - md[k] = v - break - } - } - } } var configParam []any @@ -618,6 +605,26 @@ func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, return arr, err } +func (c *initializeContext) mergeNetmapConfig(md map[string]any) error { + arr, err := c.getNetConfigFromNetmapContract() + if err != nil { + return err + } + m, err := parseConfigFromNetmapContract(arr) + if err != nil { + return err + } + for k, v := range m { + for _, key := range netmapConfigKeys { + if k == key { + md[k] = v + break + } + } + } + return nil +} + func (c *initializeContext) getAlphabetDeployItems(i, n int) []any { items := make([]any, 5) items[0] = c.Contracts[netmapContract].Hash From d13e37f70b44dfe7fe002ebf327c0d293093c0e5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 24 Jan 2024 11:19:18 +0300 Subject: [PATCH 0282/1413] [#768] adm: Do not change frostfsid admin on update Behave similarly to the netmap contract. Close #768 Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize_deploy.go | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index ca3a9599f1..6cf75c5f9d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -550,7 +550,17 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an nnsCs.Hash, "container") case frostfsIDContract: - h, found, err := getFrostfsIDAdmin(viper.GetViper()) + var ( + h util.Uint160 + found bool + err error + ) + if method == updateMethodName { + h, found, err = c.getFrostfsIDAdminFromContract() + } + if method != updateMethodName || err == nil && !found { + h, found, err = getFrostfsIDAdmin(viper.GetViper()) + } if err != nil { return nil, err } @@ -588,6 +598,35 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an return items, nil } +func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool, error) { + r := management.NewReader(c.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) + if err != nil { + return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) + } + fidHash, err := nnsResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) + if err != nil { + return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) + } + item, err := unwrap.Item(c.ReadOnlyInvoker.Call(fidHash, "getAdmin")) + if err != nil { + return util.Uint160{}, false, fmt.Errorf("getAdmin: %w", err) + } + if _, ok := item.(stackitem.Null); ok { + return util.Uint160{}, false, nil + } + + bs, err := item.TryBytes() + if err != nil { + return util.Uint160{}, true, fmt.Errorf("getAdmin: decode result: %w", err) + } + h, err := util.Uint160DecodeBytesBE(bs) + if err != nil { + return util.Uint160{}, true, fmt.Errorf("getAdmin: decode result: %w", err) + } + return h, true, nil +} + func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, error) { r := management.NewReader(c.ReadOnlyInvoker) cs, err := r.GetContractByID(1) From 1fe7736d921a06411f8076cedb8edf68519aca62 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 24 Jan 2024 15:55:04 +0300 Subject: [PATCH 0283/1413] [#925] morph: Introduce switch rpc guarded rpc actor * Introduce switch rpc guarded rpc actor in morph client to prevent using invalidated rpc actor when RPC switch happens. * Initialize NewContractStorage with SwitchRPCGuardedActor. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 2 +- pkg/morph/client/actor.go | 120 +++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 pkg/morph/client/actor.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index ffe49a7ef0..1b3e094d94 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1061,7 +1061,7 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) { } morphRuleStorage := policy_client.NewContractStorage( - c.cfgMorph.client.GetActor(), + client.NewSwitchRPCGuardedActor(c.cfgMorph.client), c.cfgObject.cfgAccessPolicyEngine.policyContractHash) ape := newAccessPolicyEngine(morphRuleStorage, localOverrideDB) diff --git a/pkg/morph/client/actor.go b/pkg/morph/client/actor.go new file mode 100644 index 0000000000..ea6bc974c4 --- /dev/null +++ b/pkg/morph/client/actor.go @@ -0,0 +1,120 @@ +package client + +import ( + "github.com/nspcc-dev/neo-go/pkg/config/netmode" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +type actorProvider interface { + GetActor() *actor.Actor +} + +// Client switches an established connection with neo-go if it is broken. +// This leads to an invalidation of an rpc actor within Client. That means the +// components that are initilized with the rpc actor may unintentionally use +// it when it is already invalidated. SwitchRPCGuardedActor is used to prevent +// this situation, getting the rpc actor from Client. +type SwitchRPCGuardedActor struct { + actorProvider actorProvider +} + +func NewSwitchRPCGuardedActor(c *Client) *SwitchRPCGuardedActor { + return &SwitchRPCGuardedActor{ + actorProvider: c, + } +} + +func (a *SwitchRPCGuardedActor) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { + return a.actorProvider.GetActor().Call(contract, operation, params...) +} + +func (a *SwitchRPCGuardedActor) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) { + return a.actorProvider.GetActor().CalculateNetworkFee(tx) +} + +func (a *SwitchRPCGuardedActor) CalculateValidUntilBlock() (uint32, error) { + return a.actorProvider.GetActor().CalculateValidUntilBlock() +} + +func (a *SwitchRPCGuardedActor) GetBlockCount() (uint32, error) { + return a.actorProvider.GetActor().GetBlockCount() +} + +func (a *SwitchRPCGuardedActor) GetNetwork() netmode.Magic { + return a.actorProvider.GetActor().GetNetwork() +} + +func (a *SwitchRPCGuardedActor) GetVersion() result.Version { + return a.actorProvider.GetActor().GetVersion() +} + +func (a *SwitchRPCGuardedActor) MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) { + return a.actorProvider.GetActor().MakeCall(contract, method, params...) +} + +func (a *SwitchRPCGuardedActor) MakeRun(script []byte) (*transaction.Transaction, error) { + return a.actorProvider.GetActor().MakeRun(script) +} + +func (a *SwitchRPCGuardedActor) MakeTunedCall(contract util.Uint160, method string, attrs []transaction.Attribute, txHook actor.TransactionCheckerModifier, params ...any) (*transaction.Transaction, error) { + return a.actorProvider.GetActor().MakeTunedCall(contract, method, attrs, txHook, params...) +} + +func (a *SwitchRPCGuardedActor) MakeTunedRun(script []byte, attrs []transaction.Attribute, txHook actor.TransactionCheckerModifier) (*transaction.Transaction, error) { + return a.actorProvider.GetActor().MakeTunedRun(script, attrs, txHook) +} + +func (a *SwitchRPCGuardedActor) MakeUncheckedRun(script []byte, sysfee int64, attrs []transaction.Attribute, txHook actor.TransactionModifier) (*transaction.Transaction, error) { + return a.actorProvider.GetActor().MakeUncheckedRun(script, sysfee, attrs, txHook) +} + +func (a *SwitchRPCGuardedActor) MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) { + return a.actorProvider.GetActor().MakeUnsignedCall(contract, method, attrs, params...) +} + +func (a *SwitchRPCGuardedActor) MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) { + return a.actorProvider.GetActor().MakeUnsignedRun(script, attrs) +} + +func (a *SwitchRPCGuardedActor) MakeUnsignedUncheckedRun(script []byte, sysFee int64, attrs []transaction.Attribute) (*transaction.Transaction, error) { + return a.actorProvider.GetActor().MakeUnsignedUncheckedRun(script, sysFee, attrs) +} + +func (a *SwitchRPCGuardedActor) Send(tx *transaction.Transaction) (util.Uint256, uint32, error) { + return a.actorProvider.GetActor().Send(tx) +} + +func (a *SwitchRPCGuardedActor) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { + return a.actorProvider.GetActor().SendCall(contract, method, params...) +} + +func (a *SwitchRPCGuardedActor) SendRun(script []byte) (util.Uint256, uint32, error) { + return a.actorProvider.GetActor().SendRun(script) +} + +func (a *SwitchRPCGuardedActor) SendTunedCall(contract util.Uint160, method string, attrs []transaction.Attribute, txHook actor.TransactionCheckerModifier, params ...any) (util.Uint256, uint32, error) { + return a.actorProvider.GetActor().SendTunedCall(contract, method, attrs, txHook, params...) +} + +func (a *SwitchRPCGuardedActor) SendTunedRun(script []byte, attrs []transaction.Attribute, txHook actor.TransactionCheckerModifier) (util.Uint256, uint32, error) { + return a.actorProvider.GetActor().SendTunedRun(script, attrs, txHook) +} + +func (a *SwitchRPCGuardedActor) SendUncheckedRun(script []byte, sysfee int64, attrs []transaction.Attribute, txHook actor.TransactionModifier) (util.Uint256, uint32, error) { + return a.actorProvider.GetActor().SendUncheckedRun(script, sysfee, attrs, txHook) +} + +func (a *SwitchRPCGuardedActor) Sender() util.Uint160 { + return a.actorProvider.GetActor().Sender() +} + +func (a *SwitchRPCGuardedActor) Sign(tx *transaction.Transaction) error { + return a.actorProvider.GetActor().Sign(tx) +} + +func (a *SwitchRPCGuardedActor) SignAndSend(tx *transaction.Transaction) (util.Uint256, uint32, error) { + return a.actorProvider.GetActor().SignAndSend(tx) +} From b6fc3321c52055ca976a61158c33b47669fc77a7 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 22 Jan 2024 13:39:57 +0300 Subject: [PATCH 0284/1413] [#876] Fix linters Signed-off-by: Anton Nikiforov --- pkg/services/object/ape/checker.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index ccd23bf069..76ada3d2ba 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -47,9 +47,7 @@ type Prm struct { SenderKey string } -var ( - errMissingOID = fmt.Errorf("object ID is not set") -) +var errMissingOID = fmt.Errorf("object ID is not set") // CheckAPE checks if a request or a response is permitted creating an ape request and passing // it to chain router. From 51d1d935ef60660cfdd32afccd1ac97dfbfc35b8 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 25 Jan 2024 20:25:23 +0300 Subject: [PATCH 0285/1413] [#876] cli: Add support for `container` in local rules Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/control/add_rule.go | 29 +-- cmd/frostfs-cli/modules/control/get_rule.go | 5 +- cmd/frostfs-cli/modules/control/list_rules.go | 4 +- cmd/frostfs-cli/modules/util/ape.go | 216 ++++++++++++------ cmd/frostfs-cli/modules/util/ape_test.go | 214 +++++++++++++++-- 5 files changed, 351 insertions(+), 117 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 4fe8194bb1..7e0805cd16 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -1,10 +1,8 @@ package control import ( - "bytes" "crypto/sha256" "encoding/hex" - "encoding/json" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -25,20 +23,13 @@ var addRuleCmd = &cobra.Command{ Use: "add-rule", Short: "Add local override", Long: "Add local APE rule to a node with following format:\n[:action_detail] [ ...] ", - Example: `allow Object.Get * -deny Object.Get EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr/* -deny:QuotaLimitReached Object.Put Object.Resource:Department=HR * + Example: `control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --rule "allow Object.Get *" +--rule "deny Object.Get EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr/*" +--rule "deny:QuotaLimitReached Object.Put Object.Resource:Department=HR *" `, Run: addRule, } -func prettyJSONFormat(cmd *cobra.Command, serializedChain []byte) string { - wr := bytes.NewBufferString("") - err := json.Indent(wr, serializedChain, "", " ") - commonCmd.ExitOnErr(cmd, "%w", err) - return wr.String() -} - func addRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) @@ -60,15 +51,15 @@ func addRule(cmd *cobra.Command, _ []string) { rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) - rule, _ := cmd.Flags().GetString(ruleFlag) + rule, _ := cmd.Flags().GetStringArray(ruleFlag) chain := new(apechain.Chain) - commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, []string{rule})) + commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rule)) chain.ID = apechain.ID(chainIDRaw) serializedChain := chain.Bytes() - cmd.Println("CID: " + cidStr) - cmd.Println("Parsed chain:\n" + prettyJSONFormat(cmd, serializedChain)) + cmd.Println("Parsed chain:") + util.PrintHumanReadableAPEChain(cmd, chain) req := &control.AddChainLocalOverrideRequest{ Body: &control.AddChainLocalOverrideRequest_Body{ @@ -93,9 +84,7 @@ func addRule(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "rpc error: %w", err) verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) - - chainIDRaw = resp.GetBody().GetChainId() - cmd.Printf("Rule has been added.\nChain id: '%s'\nChain id hex: '%x'\n", string(chainIDRaw), chainIDRaw) + cmd.Println("\nRule has been added.") } func initControlAddRuleCmd() { @@ -103,7 +92,7 @@ func initControlAddRuleCmd() { ff := addRuleCmd.Flags() ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) - ff.String(ruleFlag, "", "Rule statement") + ff.StringArray(ruleFlag, []string{}, "Rule statement") ff.String(chainIDFlag, "", "Assign ID to the parsed chain") ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") } diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 9508850ee8..e2271c4468 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -66,9 +67,7 @@ func getRule(cmd *cobra.Command, _ []string) { var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain())) - - // TODO (aarifullin): make pretty-formatted output for chains. - cmd.Printf("Parsed chain (chain id hex: '%x'):\n%s\n", chain.ID, prettyJSONFormat(cmd, chain.Bytes())) + util.PrintHumanReadableAPEChain(cmd, &chain) } func initControGetRuleCmd() { diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index ef494b1353..c62651767e 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -60,10 +61,9 @@ func listRules(cmd *cobra.Command, _ []string) { } for _, c := range chains { - // TODO (aarifullin): make pretty-formatted output for chains. var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c)) - cmd.Printf("Parsed chain (chain id hex: '%x'):\n%s\n", chain.ID, prettyJSONFormat(cmd, chain.Bytes())) + util.PrintHumanReadableAPEChain(cmd, &chain) } } diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 79966613d9..6a7eca948c 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -13,21 +13,25 @@ import ( ) var ( - errInvalidStatementFormat = errors.New("invalid statement format") - errInvalidConditionFormat = errors.New("invalid condition format") - errUnknownAction = errors.New("action is not recognized") - errUnknownOperation = errors.New("operation is not recognized") - errUnknownActionDetail = errors.New("action detail is not recognized") - errUnknownBinaryOperator = errors.New("binary operator is not recognized") - errUnknownCondObjectType = errors.New("condition object type is not recognized") + errInvalidStatementFormat = errors.New("invalid statement format") + errInvalidConditionFormat = errors.New("invalid condition format") + errUnknownStatus = errors.New("status is not recognized") + errUnknownStatusDetail = errors.New("status detail is not recognized") + errUnknownAction = errors.New("action is not recognized") + errUnknownBinaryOperator = errors.New("binary operator is not recognized") + errUnknownCondObjectType = errors.New("condition object type is not recognized") + errMixedTypesInRule = errors.New("found mixed type of actions and conditions in rule") + errNoActionsInRule = errors.New("there are no actions in rule") + errUnsupportedResourceFormat = errors.New("unsupported resource format") ) // PrintHumanReadableAPEChain print APE chain rules. func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) { - cmd.Println("ChainID: " + string(chain.ID)) + cmd.Println("Chain ID: " + string(chain.ID)) + cmd.Printf(" HEX: %x\n", chain.ID) cmd.Println("Rules:") for _, rule := range chain.Rules { - cmd.Println("\tStatus: " + rule.Status.String()) + cmd.Println("\n\tStatus: " + rule.Status.String()) cmd.Println("\tAny: " + strconv.FormatBool(rule.Any)) cmd.Println("\tConditions:") for _, c := range rule.Condition { @@ -71,7 +75,7 @@ func ParseAPEChain(chain *apechain.Chain, rules []string) error { } // ParseAPERule parses access-policy-engine statement from the following form: -// [:action_detail] [ ...] +// [:status_detail] ... [...] ... // // Examples: // deny Object.Put * @@ -99,116 +103,178 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { return err } - r.Actions, err = parseAction(lexemes[1]) - if err != nil { - return err + var isObject *bool + for i, lexeme := range lexemes[1:] { + var name string + var actionType bool + name, actionType, err = parseAction(lexeme) + if err != nil { + condition, errCond := parseCondition(lexeme) + if errCond != nil { + err = fmt.Errorf("%w:%w", err, errCond) + lexemes = lexemes[i+1:] + break + } + actionType = condition.Object == apechain.ObjectResource || condition.Object == apechain.ObjectRequest + r.Condition = append(r.Condition, *condition) + } else { + r.Actions.Names = append(r.Actions.Names, name) + } + if isObject == nil { + isObject = &actionType + } else if actionType != *isObject { + return errMixedTypesInRule + } + } + if len(r.Actions.Names) == 0 { + return fmt.Errorf("%w:%w", err, errNoActionsInRule) + } + for _, lexeme := range lexemes { + resource, errRes := parseResource(lexeme, *isObject) + if errRes != nil { + return fmt.Errorf("%w:%w", err, errRes) + } + r.Resources.Names = append(r.Resources.Names, resource) } - r.Condition, err = parseConditions(lexemes[2 : len(lexemes)-1]) - if err != nil { - return err - } - - r.Resources, err = parseResource(lexemes[len(lexemes)-1]) - return err + return nil } func parseStatus(lexeme string) (apechain.Status, error) { action, expression, found := strings.Cut(lexeme, ":") - switch action = strings.ToLower(action); action { + switch strings.ToLower(action) { case "deny": if !found { return apechain.AccessDenied, nil } else if strings.EqualFold(expression, "QuotaLimitReached") { return apechain.QuotaLimitReached, nil } else { - return 0, fmt.Errorf("%w: %s", errUnknownActionDetail, expression) + return 0, fmt.Errorf("%w: %s", errUnknownStatusDetail, expression) } case "allow": if found { - return 0, errUnknownActionDetail + return 0, errUnknownStatusDetail } return apechain.Allow, nil default: - return 0, errUnknownAction + return 0, errUnknownStatus } } -func parseAction(lexeme string) (apechain.Actions, error) { +func parseAction(lexeme string) (string, bool, error) { switch strings.ToLower(lexeme) { case "object.put": - return apechain.Actions{Names: []string{nativeschema.MethodPutObject}}, nil + return nativeschema.MethodPutObject, true, nil case "object.get": - return apechain.Actions{Names: []string{nativeschema.MethodGetObject}}, nil + return nativeschema.MethodGetObject, true, nil case "object.head": - return apechain.Actions{Names: []string{nativeschema.MethodHeadObject}}, nil + return nativeschema.MethodHeadObject, true, nil case "object.delete": - return apechain.Actions{Names: []string{nativeschema.MethodDeleteObject}}, nil + return nativeschema.MethodDeleteObject, true, nil case "object.search": - return apechain.Actions{Names: []string{nativeschema.MethodSearchObject}}, nil + return nativeschema.MethodSearchObject, true, nil case "object.range": - return apechain.Actions{Names: []string{nativeschema.MethodRangeObject}}, nil + return nativeschema.MethodRangeObject, true, nil case "object.hash": - return apechain.Actions{Names: []string{nativeschema.MethodHashObject}}, nil + return nativeschema.MethodHashObject, true, nil + case "container.put": + return nativeschema.MethodPutContainer, false, nil + case "container.delete": + return nativeschema.MethodDeleteContainer, false, nil + case "container.get": + return nativeschema.MethodGetContainer, false, nil + case "container.setcontainereacl": + return nativeschema.MethodSetContainerEACL, false, nil + case "container.getcontainereacl": + return nativeschema.MethodGetContainerEACL, false, nil default: } - return apechain.Actions{}, fmt.Errorf("%w: %s", errUnknownOperation, lexeme) + return "", false, fmt.Errorf("%w: %s", errUnknownAction, lexeme) } -func parseResource(lexeme string) (apechain.Resources, error) { - if lexeme == "*" { - return apechain.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, nil +func parseResource(lexeme string, isObj bool) (string, error) { + if len(lexeme) > 0 && !strings.HasSuffix(lexeme, "/") { + if isObj { + if lexeme == "*" { + return nativeschema.ResourceFormatAllObjects, nil + } else if lexeme == "/*" { + return nativeschema.ResourceFormatRootObjects, nil + } else if strings.HasPrefix(lexeme, "/") { + lexeme = lexeme[1:] + delimCount := strings.Count(lexeme, "/") + if delimCount == 1 && len(lexeme) >= 3 { // container/object + return nativeschema.ObjectPrefix + "//" + lexeme, nil + } + } else { + delimCount := strings.Count(lexeme, "/") + if delimCount == 1 && len(lexeme) >= 3 || + delimCount == 2 && len(lexeme) >= 5 { // namespace/container/object + return nativeschema.ObjectPrefix + "/" + lexeme, nil + } + } + } else { + if lexeme == "*" { + return nativeschema.ResourceFormatAllContainers, nil + } else if lexeme == "/*" { + return nativeschema.ResourceFormatRootContainers, nil + } else if strings.HasPrefix(lexeme, "/") && len(lexeme) > 1 { + lexeme = lexeme[1:] + delimCount := strings.Count(lexeme, "/") + if delimCount == 0 { + return nativeschema.ContainerPrefix + "//" + lexeme, nil + } + } else { + delimCount := strings.Count(lexeme, "/") + if delimCount == 1 && len(lexeme) > 3 { // namespace/container + return nativeschema.ContainerPrefix + "/" + lexeme, nil + } + } + } } - return apechain.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, lexeme)}}, nil + return "", errUnsupportedResourceFormat } const ( ObjectResource = "object.resource" ObjectRequest = "object.request" + + ContainerResource = "container.resource" + ContainerRequest = "container.request" ) var typeToCondObject = map[string]apechain.ObjectType{ - ObjectResource: apechain.ObjectResource, - ObjectRequest: apechain.ObjectRequest, + ObjectResource: apechain.ObjectResource, + ObjectRequest: apechain.ObjectRequest, + ContainerResource: apechain.ContainerResource, + ContainerRequest: apechain.ContainerRequest, } -func parseConditions(lexemes []string) ([]apechain.Condition, error) { - conds := make([]apechain.Condition, 0) +func parseCondition(lexeme string) (*apechain.Condition, error) { + typ, expression, found := strings.Cut(lexeme, ":") + typ = strings.ToLower(typ) - for _, lexeme := range lexemes { - typ, expression, found := strings.Cut(lexeme, ":") - typ = strings.ToLower(typ) - - objType, ok := typeToCondObject[typ] - if ok { - if !found { - return nil, fmt.Errorf("%w: %s", errInvalidConditionFormat, lexeme) - } - - var lhs, rhs string - var binExpFound bool - - var cond apechain.Condition - cond.Object = objType - - lhs, rhs, binExpFound = strings.Cut(expression, "!=") - if !binExpFound { - lhs, rhs, binExpFound = strings.Cut(expression, "=") - if !binExpFound { - return nil, fmt.Errorf("%w: %s", errUnknownBinaryOperator, expression) - } - cond.Op = apechain.CondStringEquals - } else { - cond.Op = apechain.CondStringNotEquals - } - - cond.Key, cond.Value = lhs, rhs - - conds = append(conds, cond) - } else { - return nil, fmt.Errorf("%w: %s", errUnknownCondObjectType, typ) + objType, ok := typeToCondObject[typ] + if ok { + if !found { + return nil, fmt.Errorf("%w: %s", errInvalidConditionFormat, lexeme) } - } - return conds, nil + var cond apechain.Condition + cond.Object = objType + + lhs, rhs, binExpFound := strings.Cut(expression, "!=") + if !binExpFound { + lhs, rhs, binExpFound = strings.Cut(expression, "=") + if !binExpFound { + return nil, fmt.Errorf("%w: %s", errUnknownBinaryOperator, expression) + } + cond.Op = apechain.CondStringEquals + } else { + cond.Op = apechain.CondStringNotEquals + } + + cond.Key, cond.Value = lhs, rhs + return &cond, nil + } + return nil, fmt.Errorf("%w: %s", errUnknownCondObjectType, typ) } diff --git a/cmd/frostfs-cli/modules/util/ape_test.go b/cmd/frostfs-cli/modules/util/ape_test.go index 1cab8e6aec..3e47660989 100644 --- a/cmd/frostfs-cli/modules/util/ape_test.go +++ b/cmd/frostfs-cli/modules/util/ape_test.go @@ -1,6 +1,7 @@ package util import ( + "fmt" "testing" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -16,13 +17,76 @@ func TestParseAPERule(t *testing.T) { expectRule policyengine.Rule }{ { - name: "Valid allow rule", + name: "Valid allow rule for all objects", rule: "allow Object.Put *", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatAllObjects}}, + }, + }, + { + name: "Valid rule for all objects in root namespace", + rule: "allow Object.Put /*", expectRule: policyengine.Rule{ Status: policyengine.Allow, Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, - Condition: []policyengine.Condition{}, + }, + }, + { + name: "Valid rule for all objects in root namespace and container", + rule: "allow Object.Put /cid/*", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, "cid"), + }}, + }, + }, + { + name: "Valid rule for object in root namespace and container", + rule: "allow Object.Put /cid/oid", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, "cid", "oid"), + }}, + }, + }, + { + name: "Valid rule for all objects in namespace", + rule: "allow Object.Put ns/*", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceObjects, "ns"), + }}, + }, + }, + { + name: "Valid rule for all objects in namespace and container", + rule: "allow Object.Put ns/cid/*", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainerObjects, "ns", "cid"), + }}, + }, + }, + { + name: "Valid rule for object in namespace and container", + rule: "allow Object.Put ns/cid/oid", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainerObject, "ns", "cid", "oid"), + }}, }, }, { @@ -31,8 +95,7 @@ func TestParseAPERule(t *testing.T) { expectRule: policyengine.Rule{ Status: policyengine.AccessDenied, Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, - Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, - Condition: []policyengine.Condition{}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatAllObjects}}, }, }, { @@ -41,8 +104,7 @@ func TestParseAPERule(t *testing.T) { expectRule: policyengine.Rule{ Status: policyengine.QuotaLimitReached, Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, - Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, - Condition: []policyengine.Condition{}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatAllObjects}}, }, }, { @@ -51,7 +113,7 @@ func TestParseAPERule(t *testing.T) { expectRule: policyengine.Rule{ Status: policyengine.Allow, Actions: policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, - Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatAllObjects}}, Condition: []policyengine.Condition{ { Op: policyengine.CondStringEquals, @@ -69,12 +131,12 @@ func TestParseAPERule(t *testing.T) { }, }, { - name: "Valid rule with conditions with action detail", + name: "Valid rule for object with conditions with action detail", rule: "deny:QuotaLimitReached Object.Get Object.Resource:Department=HR Object.Request:Actor!=ownerA *", expectRule: policyengine.Rule{ Status: policyengine.QuotaLimitReached, Actions: policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, - Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatAllObjects}}, Condition: []policyengine.Condition{ { Op: policyengine.CondStringEquals, @@ -92,19 +154,19 @@ func TestParseAPERule(t *testing.T) { }, }, { - name: "Invalid rule with unknown action", + name: "Invalid rule with unknown status", rule: "permit Object.Put *", + expectErr: errUnknownStatus, + }, + { + name: "Invalid rule with unknown action", + rule: "allow Object.PutOut *", expectErr: errUnknownAction, }, { - name: "Invalid rule with unknown operation", - rule: "allow Object.PutOut *", - expectErr: errUnknownOperation, - }, - { - name: "Invalid rule with unknown action detail", + name: "Invalid rule with unknown status detail", rule: "deny:UnknownActionDetail Object.Put *", - expectErr: errUnknownActionDetail, + expectErr: errUnknownStatusDetail, }, { name: "Invalid rule with unknown condition binary operator", @@ -116,6 +178,124 @@ func TestParseAPERule(t *testing.T) { rule: "deny Object.Put Object.ResourZe:Department=HR *", expectErr: errUnknownCondObjectType, }, + { + name: "Invalid rule with mixed types of actions", + rule: "allow Object.Put Container.Put *", + expectErr: errMixedTypesInRule, + }, + { + name: "Invalid rule with no actions", + rule: "allow Container.Resource:A=B *", + expectErr: errNoActionsInRule, + }, + { + name: "Invalid rule with invalid resource for object nm/cnt/obj/err", + rule: "allow Object.Put nm/cnt/obj/err", + expectErr: errUnsupportedResourceFormat, + }, + { + name: "Invalid rule with invalid resource for container nm/cnt/err", + rule: "allow Container.Put nm/cnt/err", + expectErr: errUnsupportedResourceFormat, + }, + { + name: "Invalid rule with invalid resource for container /nm/cnt/err", + rule: "allow Container.Put /nm/cnt/err", + expectErr: errUnsupportedResourceFormat, + }, + { + name: "Invalid rule with invalid resource for container /nm/cnt/", + rule: "allow Container.Put /nm/cnt/", + expectErr: errUnsupportedResourceFormat, + }, + { + name: "Invalid rule with invalid resource for container /nm/cnt", + rule: "allow Container.Put /nm/cnt", + expectErr: errUnsupportedResourceFormat, + }, + { + name: "Invalid rule with invalid resource for container /nm/", + rule: "allow Container.Put /nm/", + expectErr: errUnsupportedResourceFormat, + }, + { + name: "Valid rule for all containers", + rule: "allow Container.Put *", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutContainer}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatAllContainers}}, + }, + }, + { + name: "Valid rule for all containers in root namespace", + rule: "allow Container.Put /*", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutContainer}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootContainers}}, + }, + }, + { + name: "Valid rule for container in root namespace", + rule: "allow Container.Put /cid", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutContainer}}, + Resources: policyengine.Resources{Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, "cid"), + }}, + }, + }, + { + name: "Valid rule for all container in namespace", + rule: "allow Container.Put ns/*", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutContainer}}, + Resources: policyengine.Resources{Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainers, "ns"), + }}, + }, + }, + { + name: "Valid rule for container in namespace", + rule: "allow Container.Put ns/cid", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutContainer}}, + Resources: policyengine.Resources{Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainer, "ns", "cid"), + }}, + }, + }, + { + name: "Valid rule for container with conditions with action detail", + rule: "allow Container.Get Container.Resource:A=B Container.Put Container.Request:C!=D " + + "* /cnt_id", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodGetContainer, nativeschema.MethodPutContainer}}, + Resources: policyengine.Resources{Names: []string{ + nativeschema.ResourceFormatAllContainers, + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, "cnt_id"), + }}, + Condition: []policyengine.Condition{ + { + Op: policyengine.CondStringEquals, + Object: policyengine.ContainerResource, + Key: "A", + Value: "B", + }, + { + Op: policyengine.CondStringNotEquals, + Object: policyengine.ContainerRequest, + Key: "C", + Value: "D", + }, + }, + }, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { From 417f8fc2c24cbe601a73c13c28d4c83ce211bc31 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 22 Jan 2024 13:41:26 +0300 Subject: [PATCH 0286/1413] [#876] cli: Add doc for commands `control *-rule` Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/docs/policy.md | 115 +++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 cmd/frostfs-cli/docs/policy.md diff --git a/cmd/frostfs-cli/docs/policy.md b/cmd/frostfs-cli/docs/policy.md new file mode 100644 index 0000000000..06c325c62a --- /dev/null +++ b/cmd/frostfs-cli/docs/policy.md @@ -0,0 +1,115 @@ +# How manage local Access Policy Engine (APE) override of the node + +## Overview +APE is a replacement for eACL. Each rule can restrict somehow access to the object/container or list of them. +Here is a simple representation for the rule: +`[:status_detail] ... ... ...` + +Rule start with `status`(with or without details), contains list of actions(which this rule regulate) or conditions +(which can be under resource or request) and ends with list of resources. + +Resource is the combination of namespace, identificator of the FrostFS container/object and wildcard `*`. + +For object it can be represented as: +- `namespace/cid/oid` object in the container of the namespace +- `namespace/cid/*` all objects in the container of the namespace +- `namespace/*` all objects in the namespace +- `*` all objects +- `/*` all object in the `root` namespace +- `/cid/*` all objects in the container of the `root` namespace +- `/cid/oid` object in the container of the `root` namespace + +For container it can be represented as: +- `namespace/cid` container in the namespace +- `namespace/*` all containers in the namespace +- `*` all containers +- `/cid` container in the `root` namespace +- `/*` all containers in the `root` namespace + +Actions is a regular operations upon FrostFS containers/objects. Like `Object.Put`, `Container.Get` etc. + +In status section it is possible to use `allow`, `deny` or `deny:QuotaLimitReached` actions. + +It is prohibited to mix operation under FrostFS container and object in one rule. +The same statement is equal for conditions and resources - one rule is for one type of items. + +## Add rule +Local rule can be added with the command `frostfs-cli control add-rule`: +```shell +@:~$ frostfs-cli control add-rule --endpoint s04.frostfs.devenv:8081 -c cnt_create_cfg.yml \ +--address NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM --cid SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH \ +--chain-id TestPolicy \ +--rule "allow Object.Get Object.Head /*" --rule "deny Container.Put *" +Parsed chain: +Chain ID: TestPolicy + HEX: 54657374506f6c696379 +Rules: + + Status: Allowed + Any: false + Conditions: + Actions: Inverted:false + GetObject + HeadObject + Resources: Inverted:false + native:object//* + + Status: Access denied + Any: false + Conditions: + Actions: Inverted:false + PutContainer + Resources: Inverted:false + native:container/* + +Rule has been added. +@:~$ +``` +## List rules +Local rules can be listed with command `frostfs-cli control list-rules`: +```shell +@:~$ frostfs-cli control list-rules --endpoint s04.frostfs.devenv:8081 --address NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM \ +--cid SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH -w wallets/wallet.json +Enter password > +Chain ID: TestPolicy + HEX: 54657374506f6c696379 +Rules: + + Status: Allowed + Any: false +... +@:~$ +``` + +## Get rule +Rules can be retrieved with `frostfs-cli control get-rule`: +```shell +@:~$ frostfs-cli control get-rule --endpoint s04.frostfs.devenv:8081 -c cnt_create_cfg.yml \ +--address NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM --cid SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH \ +--chain-id TestPolicy +Parsed chain (chain id hex: '54657374506f6c696379'): +Chain ID: TestPolicy + HEX: 54657374506f6c696379 +Rules: + + Status: Allowed + Any: false +... +@:~$ +``` + +## Remove rule +To remove rule need to use command `frostfs-cli control remove-rule`: +```shell +@:~$ frostfs-cli control remove-rule --endpoint s04.frostfs.devenv:8081 -c cnt_create_cfg.yml \ +--address NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM --cid SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH --chain-id TestPolicy +Rule has been removed. +@:~$ frostfs-cli control get-rule --endpoint s04.frostfs.devenv:8081 -c cnt_create_cfg.yml \ +--address NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM --cid SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH --chain-id TestPolicy +rpc error: rpc error: code = NotFound desc = chain not found +@:~$ frostfs-cli control list-rules --endpoint s04.frostfs.devenv:8081 \ +--address NbUgTSFvPmsRxmGeWpuuGeJUoRoi6PErcM --cid SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH -w wallets/wallet.json +Enter password > +Local overrides are not defined for the container. +@:~$ +``` From 6e2cc327688e8faaed855bf7d14d93d13bbb1748 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 24 Jan 2024 13:56:12 +0300 Subject: [PATCH 0287/1413] [#681] objsvc: Validate session token owner for local sessions Previously, the check was in place only when session token was missing. Format validator checks are applied only to fully-prepared object, so this lead to the following situation: 1. Object is put locally with malformed token, because there are no checks. 2. Object cannot be replicated, because the token is malformed. This is now fixed and token check is done before any payload receival. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/put/streamer.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index a9abe407d3..90d580a1cf 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -110,18 +110,22 @@ func (p *Streamer) initTrustedTarget(prm *PutInitPrm) error { // In case session token is missing, the line above returns the default key. // If it isn't owner key, replication attempts will fail, thus this check. - if sToken == nil { - ownerObj := prm.hdr.OwnerID() - if ownerObj.IsEmpty() { - return errors.New("missing object owner") - } + ownerObj := prm.hdr.OwnerID() + if ownerObj.IsEmpty() { + return errors.New("missing object owner") + } + if sToken == nil { var ownerSession user.ID user.IDFromKey(&ownerSession, sessionKey.PublicKey) if !ownerObj.Equals(ownerSession) { return fmt.Errorf("(%T) session token is missing but object owner id is different from the default key", p) } + } else { + if !ownerObj.Equals(sessionInfo.Owner) { + return fmt.Errorf("(%T) different token issuer and object owner identifiers %s/%s", p, sessionInfo.Owner, ownerObj) + } } p.sessionKey = sessionKey From c916a75948d0795afc38676dc8d506177a31476b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 26 Jan 2024 12:18:51 +0300 Subject: [PATCH 0288/1413] [#935] .forgejo: Update dco-go to v3 Signed-off-by: Evgenii Stratonikov --- .forgejo/workflows/dco.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/dco.yml b/.forgejo/workflows/dco.yml index 6746408aaf..9aa0d31066 100644 --- a/.forgejo/workflows/dco.yml +++ b/.forgejo/workflows/dco.yml @@ -16,6 +16,6 @@ jobs: go-version: '1.21' - name: Run commit format checker - uses: https://git.frostfs.info/TrueCloudLab/dco-go@v2 + uses: https://git.frostfs.info/TrueCloudLab/dco-go@v3 with: from: 'origin/${{ github.event.pull_request.base.ref }}' From df055fead56e6acef84f34da61bdca0c5b321f28 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 25 Jan 2024 11:21:00 +0300 Subject: [PATCH 0289/1413] [#931] morph: Provide batch size for container listing explicitly Besides VM stack item limit we also have restrictions on the size of JSON for a stackitem, which is 128k. This limit is much harder to calculate, because JSON representation includes type and the encoding is different for different items. Thus is makes no sense to invent our own default, so use the one provided by neo-go. But for container listing we know exactly what we process, so use big enough value, which is tested. Introduced in be8607a1f6. Refs #902 Refs https://github.com/nspcc-dev/neo-go/blob/v0.105.0/pkg/vm/stackitem/json.go#L353 Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/client.go | 11 +++-------- pkg/morph/client/container/containers_of.go | 11 ++++++++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 0c8544bd05..88f9703e7a 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -22,13 +22,13 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/rpcclient/rolemgmt" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "github.com/nspcc-dev/neo-go/pkg/wallet" @@ -207,16 +207,11 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, return vub, nil } -// defaultPrefetchBatchSize is the default number of items to prefetch. -// It is dependent on VM limits (2048 items on stack), the default works for simple items. -// For example, to iterate over 2 field structs, the limit should be divided by 3 = 1 (struct itself) + 2 (fields). -const defaultPrefetchBatchSize = vm.MaxStackSize - 16 - // TestInvokeIterator invokes contract method returning an iterator and executes cb on each element. // If cb returns an error, the session is closed and this error is returned as-is. // If the remove neo-go node does not support sessions, `unwrap.ErrNoSessionID` is returned. // batchSize is the number of items to prefetch: if the number of items in the iterator is less than batchSize, no session will be created. -// The default batchSize is 2000 (VM is limited by having 2048 items on stack, so if each iterator item is simple, 2000 items won't hit the limit). +// The default batchSize is 100, the default limit from neo-go. func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int, contract util.Uint160, method string, args ...interface{}) error { start := time.Now() success := false @@ -225,7 +220,7 @@ func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int }() if batchSize <= 0 { - batchSize = defaultPrefetchBatchSize + batchSize = invoker.DefaultIteratorResultItems } c.switchLock.RLock() diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go index 140047eb27..ce127335d8 100644 --- a/pkg/morph/client/container/containers_of.go +++ b/pkg/morph/client/container/containers_of.go @@ -40,8 +40,17 @@ func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { return nil } + // We would like to have batch size as big as possible, + // to reduce the number of round-trips and avoid creating sessions. + // The limit depends on 2 things: + // 1. VM limits: max 2048 items on stack. + // 2. JSON encoded size for the item with type = 128k. + // It turns out, that for container ID the second limit is hit first, + // 512 is big enough value and it is beautiful. + const batchSize = 512 + cnrHash := c.client.ContractAddress() - err := c.client.Morph().TestInvokeIterator(cb, 0, cnrHash, containersOfMethod, rawID) + err := c.client.Morph().TestInvokeIterator(cb, batchSize, cnrHash, containersOfMethod, rawID) if err != nil { if errors.Is(err, unwrap.ErrNoSessionID) { return c.List(idUser) From c681354afd6332e9ecc35623d2f53d7ebbe5c6a8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 30 Jan 2024 11:13:29 +0300 Subject: [PATCH 0290/1413] [#938] engine: Fix container count removal Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/inhume.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index fc6ee24301..80eda2204b 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -398,7 +398,7 @@ func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []ci } for id := range idMap { - if err := sh.DeleteContainerSize(ctx, id); err != nil { + if err := sh.DeleteContainerCount(ctx, id); err != nil { e.log.Warn(logs.EngineFailedToDeleteContainerSize, zap.Stringer("container_id", id), zap.Error(err)) failed = true return true From 675eec91f34bd689191b6eeb9a5bf4dbd466237e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 30 Jan 2024 11:37:06 +0300 Subject: [PATCH 0291/1413] [#938] shard: Update only changed counters If metric value hasn't changed, but we update metric, then non existed metric will apear with zero value. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/shard.go | 46 +++++++++++++++++-------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 136f5463a1..e8f1978d20 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -433,9 +433,9 @@ func (s *Shard) updateMetrics(ctx context.Context) { return } - s.cfg.metricsWriter.SetObjectCounter(physical, cc.Phy) - s.cfg.metricsWriter.SetObjectCounter(logical, cc.Logic) - s.cfg.metricsWriter.SetObjectCounter(user, cc.User) + s.setObjectCounterBy(physical, cc.Phy) + s.setObjectCounterBy(logical, cc.Logic) + s.setObjectCounterBy(user, cc.User) cnrList, err := s.metaBase.Containers(ctx) if err != nil { @@ -453,11 +453,11 @@ func (s *Shard) updateMetrics(ctx context.Context) { zap.Error(err)) continue } - s.metricsWriter.AddToContainerSize(cnrList[i].EncodeToString(), int64(size)) + s.addToContainerSize(cnrList[i].EncodeToString(), int64(size)) totalPayload += size } - s.metricsWriter.AddToPayloadSize(int64(totalPayload)) + s.addToPayloadSize(int64(totalPayload)) contCount, err := s.metaBase.ContainerCounters(ctx) if err != nil { @@ -465,9 +465,9 @@ func (s *Shard) updateMetrics(ctx context.Context) { return } for contID, count := range contCount.Counts { - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), physical, count.Phy) - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), logical, count.Logic) - s.metricsWriter.SetContainerObjectsCount(contID.EncodeToString(), user, count.User) + s.setContainerObjectsCount(contID.EncodeToString(), physical, count.Phy) + s.setContainerObjectsCount(contID.EncodeToString(), logical, count.Logic) + s.setContainerObjectsCount(contID.EncodeToString(), user, count.User) } } @@ -487,35 +487,53 @@ func (s *Shard) incObjectCounter(cnrID cid.ID, isUser bool) { } func (s *Shard) decObjectCounterBy(typ string, v uint64) { - if s.cfg.metricsWriter != nil { + if s.cfg.metricsWriter != nil && v > 0 { s.cfg.metricsWriter.AddToObjectCounter(typ, -int(v)) } } +func (s *Shard) setObjectCounterBy(typ string, v uint64) { + if s.cfg.metricsWriter != nil && v > 0 { + s.cfg.metricsWriter.SetObjectCounter(typ, v) + } +} + func (s *Shard) decContainerObjectCounter(byCnr map[cid.ID]meta.ObjectCounters) { if s.cfg.metricsWriter == nil { return } for cnrID, count := range byCnr { - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy) - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic) - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), user, count.User) + if count.Phy > 0 { + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy) + } + if count.Logic > 0 { + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic) + } + if count.User > 0 { + s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), user, count.User) + } } } func (s *Shard) addToContainerSize(cnr string, size int64) { - if s.cfg.metricsWriter != nil { + if s.cfg.metricsWriter != nil && size != 0 { s.cfg.metricsWriter.AddToContainerSize(cnr, size) } } func (s *Shard) addToPayloadSize(size int64) { - if s.cfg.metricsWriter != nil { + if s.cfg.metricsWriter != nil && size != 0 { s.cfg.metricsWriter.AddToPayloadSize(size) } } +func (s *Shard) setContainerObjectsCount(cnr string, typ string, v uint64) { + if s.cfg.metricsWriter != nil && v > 0 { + s.metricsWriter.SetContainerObjectsCount(cnr, typ, v) + } +} + func (s *Shard) IncErrorCounter() { if s.cfg.metricsWriter != nil { s.cfg.metricsWriter.IncErrorCounter() From c441296592cdaca7152122a2ef1d8f85b02f241c Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 24 Jan 2024 14:48:47 +0300 Subject: [PATCH 0292/1413] [#930] policer: Release task pool when context cancelled Signed-off-by: Anton Nikiforov --- pkg/services/policer/process.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index 873a1efb07..c4c820200c 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -19,6 +19,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { for { select { case <-ctx.Done(): + p.taskPool.Release() return default: } @@ -36,6 +37,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { for i := range addrs { select { case <-ctx.Done(): + p.taskPool.Release() return default: addr := addrs[i] From e3573de6db6cd677023715b51046f9cecdee7e08 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 25 Jan 2024 11:02:57 +0300 Subject: [PATCH 0293/1413] [#930] gc: Stop internal activity by context Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/config.go | 2 +- internal/logs/logs.go | 4 +- pkg/local_object_storage/engine/lock_test.go | 4 +- pkg/local_object_storage/engine/shards.go | 8 +++- pkg/local_object_storage/shard/gc.go | 50 +++++++++++++++----- 5 files changed, 50 insertions(+), 18 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 1b3e094d94..e1e2283250 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1009,7 +1009,7 @@ func initLocalStorage(ctx context.Context, c *cfg) { ls := engine.New(c.engineOpts()...) addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { - ls.HandleNewEpoch(ev.(netmap2.NewEpoch).EpochNumber()) + ls.HandleNewEpoch(ctx, ev.(netmap2.NewEpoch).EpochNumber()) }) // allocate memory for the service; diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 34ca0ae937..e81976a325 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -270,7 +270,9 @@ const ( ShardCantOpenMetabaseMoveToADegradedMode = "can't open metabase, move to a degraded mode" ShardCantInitializeMetabaseMoveToADegradedreadonlyMode = "can't initialize metabase, move to a degraded-read-only mode" ShardTryingToRestoreReadwriteMode = "trying to restore read-write mode" - ShardStopEventListenerByClosedChannel = "stop event listener by closed channel" + ShardStopEventListenerByClosedEventChannel = "stop event listener by closed `event` channel" + ShardStopEventListenerByClosedStopChannel = "stop event listener by closed `stop` channel" + ShardStopEventListenerByContext = "stop event listener by context" ShardCouldNotSubmitGCJobToWorkerPool = "could not submit GC job to worker pool" ShardGCIsStopped = "GC is stopped" ShardWaitingForGCWorkersToStop = "waiting for GC workers to stop..." diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 69b74f4a46..7fa7c27ef2 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -133,7 +133,7 @@ func TestLockUserScenario(t *testing.T) { require.ErrorIs(t, err, meta.ErrLockObjectRemoval) // 5. - e.HandleNewEpoch(lockerExpiresAfter + 1) + e.HandleNewEpoch(context.Background(), lockerExpiresAfter+1) inhumePrm.WithTarget(tombAddr, objAddr) @@ -206,7 +206,7 @@ func TestLockExpiration(t *testing.T) { require.ErrorAs(t, err, &objLockedErr) // 3. - e.HandleNewEpoch(lockerExpiresAfter + 1) + e.HandleNewEpoch(context.Background(), lockerExpiresAfter+1) // 4. inhumePrm.WithTarget(oidtest.Address(), objectcore.AddressOf(obj)) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 37a857c9d0..bd25dde595 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -329,14 +329,18 @@ func (e *StorageEngine) SetShardMode(id *shard.ID, m mode.Mode, resetErrorCounte } // HandleNewEpoch notifies every shard about NewEpoch event. -func (e *StorageEngine) HandleNewEpoch(epoch uint64) { +func (e *StorageEngine) HandleNewEpoch(ctx context.Context, epoch uint64) { ev := shard.EventNewEpoch(epoch) e.mtx.RLock() defer e.mtx.RUnlock() for _, sh := range e.shards { - sh.NotificationChannel() <- ev + select { + case <-ctx.Done(): + return + case sh.NotificationChannel() <- ev: + } } } diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index bfd1f1b112..24c3a337a2 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -105,6 +105,8 @@ type gc struct { remover func(context.Context) gcRunResult + // eventChan is used only for listening for the new epoch event. + // It is ok to keep opened, we are listening for context done when writing in it. eventChan chan Event mEventHandler map[eventType]*eventHandlers } @@ -155,13 +157,21 @@ func (gc *gc) listenEvents(ctx context.Context) { defer gc.wg.Done() for { - event, ok := <-gc.eventChan - if !ok { - gc.log.Warn(logs.ShardStopEventListenerByClosedChannel) + select { + case <-gc.stopChannel: + gc.log.Warn(logs.ShardStopEventListenerByClosedStopChannel) return - } + case <-ctx.Done(): + gc.log.Warn(logs.ShardStopEventListenerByContext) + return + case event, ok := <-gc.eventChan: + if !ok { + gc.log.Warn(logs.ShardStopEventListenerByClosedEventChannel) + return + } - gc.handleEvent(ctx, event) + gc.handleEvent(ctx, event) + } } } @@ -180,6 +190,11 @@ func (gc *gc) handleEvent(ctx context.Context, event Event) { v.prevGroup.Add(len(v.handlers)) for i := range v.handlers { + select { + case <-ctx.Done(): + return + default: + } h := v.handlers[i] err := gc.workerPool.Submit(func() { @@ -196,6 +211,18 @@ func (gc *gc) handleEvent(ctx context.Context, event Event) { } } +func (gc *gc) releaseResources() { + if gc.workerPool != nil { + gc.workerPool.Release() + } + + // Avoid to close gc.eventChan here, + // because it is possible that we are close it earlier than stop writing. + // It is ok to keep it opened. + + gc.log.Debug(logs.ShardGCIsStopped) +} + func (gc *gc) tickRemover(ctx context.Context) { defer gc.wg.Done() @@ -204,14 +231,13 @@ func (gc *gc) tickRemover(ctx context.Context) { for { select { + case <-ctx.Done(): + // Context canceled earlier than we start to close shards. + // It make sense to stop collecting garbage by context too. + gc.releaseResources() + return case <-gc.stopChannel: - if gc.workerPool != nil { - gc.workerPool.Release() - } - - close(gc.eventChan) - - gc.log.Debug(logs.ShardGCIsStopped) + gc.releaseResources() return case <-timer.C: startedAt := time.Now() From 483a67b17064990d69e39e23d7b3fd6c72d9bfb3 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 30 Jan 2024 17:07:05 +0300 Subject: [PATCH 0294/1413] [#937] ape: Validate chain resource name Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/frostfsid_util.go | 22 +-- .../modules/morph/frostfsid_util_test.go | 7 +- internal/ape/util.go | 11 ++ pkg/services/control/server/ape/validate.go | 97 +++++++++++++ .../control/server/ape/validate_test.go | 132 ++++++++++++++++++ pkg/services/control/server/policy_engine.go | 8 ++ 6 files changed, 259 insertions(+), 18 deletions(-) create mode 100644 internal/ape/util.go create mode 100644 pkg/services/control/server/ape/validate.go create mode 100644 pkg/services/control/server/ape/validate_test.go diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go index f88e4edfb7..6b6bdffa9b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go @@ -3,9 +3,9 @@ package morph import ( "errors" "fmt" - "regexp" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/util" @@ -13,14 +13,6 @@ import ( "github.com/spf13/viper" ) -var ( - frostfsidSubjectNameRegexp = regexp.MustCompile(`^[\w+=,.@-]{1,64}$`) - frostfsidGroupNameRegexp = regexp.MustCompile(`^[\w+=,.@-]{1,128}$`) - - // frostfsidNamespaceNameRegexp similar to https://git.frostfs.info/TrueCloudLab/frostfs-contract/src/commit/f2a82aa635aa57d9b05092d8cf15b170b53cc324/nns/nns_contract.go#L690 - frostfsidNamespaceNameRegexp = regexp.MustCompile(`(^$)|(^[a-z0-9]{1,2}$)|(^[a-z0-9][a-z0-9-]{1,48}[a-z0-9]$)`) -) - func getFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { admin := v.GetString(frostfsIDAdminConfigKey) if admin == "" { @@ -65,9 +57,9 @@ func getFrostfsIDSubjectName(cmd *cobra.Command) string { return "" } - if !frostfsidSubjectNameRegexp.MatchString(subjectName) { + if !ape.SubjectNameRegexp.MatchString(subjectName) { commonCmd.ExitOnErr(cmd, "invalid subject name: %w", - fmt.Errorf("name must match regexp: %s", frostfsidSubjectNameRegexp.String())) + fmt.Errorf("name must match regexp: %s", ape.SubjectNameRegexp.String())) } return subjectName @@ -76,9 +68,9 @@ func getFrostfsIDSubjectName(cmd *cobra.Command) string { func getFrostfsIDGroupName(cmd *cobra.Command) string { groupName, _ := cmd.Flags().GetString(groupNameFlag) - if !frostfsidGroupNameRegexp.MatchString(groupName) { + if !ape.GroupNameRegexp.MatchString(groupName) { commonCmd.ExitOnErr(cmd, "invalid group name: %w", - fmt.Errorf("name must match regexp: %s", frostfsidGroupNameRegexp.String())) + fmt.Errorf("name must match regexp: %s", ape.GroupNameRegexp.String())) } return groupName @@ -100,9 +92,9 @@ func getFrostfsIDNamespace(cmd *cobra.Command) string { ns = "" } - if !frostfsidNamespaceNameRegexp.MatchString(ns) { + if !ape.NamespaceNameRegexp.MatchString(ns) { commonCmd.ExitOnErr(cmd, "invalid namespace: %w", - fmt.Errorf("name must match regexp: %s", frostfsidNamespaceNameRegexp.String())) + fmt.Errorf("name must match regexp: %s", ape.NamespaceNameRegexp.String())) } return ns diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go index f73ebad08e..79a0845f94 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/spf13/viper" @@ -95,7 +96,7 @@ func TestNamespaceRegexp(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.matched, frostfsidNamespaceNameRegexp.MatchString(tc.namespace)) + require.Equal(t, tc.matched, ape.NamespaceNameRegexp.MatchString(tc.namespace)) }) } } @@ -128,7 +129,7 @@ func TestSubjectNameRegexp(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.matched, frostfsidSubjectNameRegexp.MatchString(tc.subject)) + require.Equal(t, tc.matched, ape.SubjectNameRegexp.MatchString(tc.subject)) }) } } @@ -166,7 +167,7 @@ func TestSubjectGroupRegexp(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.matched, frostfsidGroupNameRegexp.MatchString(tc.subject)) + require.Equal(t, tc.matched, ape.GroupNameRegexp.MatchString(tc.subject)) }) } } diff --git a/internal/ape/util.go b/internal/ape/util.go new file mode 100644 index 0000000000..99eba95ba7 --- /dev/null +++ b/internal/ape/util.go @@ -0,0 +1,11 @@ +package ape + +import "regexp" + +var ( + SubjectNameRegexp = regexp.MustCompile(`^[\w+=,.@-]{1,64}$`) + GroupNameRegexp = regexp.MustCompile(`^[\w+=,.@-]{1,128}$`) + + // NamespaceNameRegexp similar to https://git.frostfs.info/TrueCloudLab/frostfs-contract/src/commit/f2a82aa635aa57d9b05092d8cf15b170b53cc324/nns/nns_contract.go#L690 + NamespaceNameRegexp = regexp.MustCompile(`(^$)|(^[a-z0-9]{1,2}$)|(^[a-z0-9][a-z0-9-]{1,48}[a-z0-9]$)`) +) diff --git a/pkg/services/control/server/ape/validate.go b/pkg/services/control/server/ape/validate.go new file mode 100644 index 0000000000..f4aa0399f6 --- /dev/null +++ b/pkg/services/control/server/ape/validate.go @@ -0,0 +1,97 @@ +package ape + +import ( + "errors" + "fmt" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" +) + +var ( + ErrInvalidResource = errors.New("invalid resource name") + ErrUnsupportedPrefix = errors.New("unsupported resource name prefix") + ErrInvalidContainerID = errors.New("invalid container id") + ErrInvalidObjectID = errors.New("invalid object id") + ErrInvalidNamespace = fmt.Errorf("namespace must match regexp: %s", ape.NamespaceNameRegexp.String()) +) + +// ValidateResourceName validates resource name components - container and object id, namespace. +// Also validates matching resource name to templates of policy engine's native scheme. +func ValidateResourceName(name string) error { + if after, found := strings.CutPrefix(name, native.ObjectPrefix+"/"); found { + return validateObjectResourceName(after) + } else if after, found = strings.CutPrefix(name, native.ContainerPrefix+"/"); found { + return validateContainerResourceName(after) + } + return ErrUnsupportedPrefix +} + +// validateObjectResourceName validate name for object. +// Name should be without prefix `native.ObjectPrefix`. +func validateObjectResourceName(name string) error { + if name == "*" { + return nil + } + lexems := strings.Split(name, "/") + if len(lexems) == 1 && lexems[0] == "*" { + return nil + } else if len(lexems) == 2 { + // len == 2 means format `namespace(root_namespace)/*` + if lexems[0] != "" && !ape.NamespaceNameRegexp.MatchString(lexems[0]) { + return ErrInvalidNamespace + } + if lexems[1] == "*" { + return nil + } + } else if len(lexems) == 3 { + // len == 3 means format `namespace(root_namespace)/CID/OID(*)` + if lexems[0] != "" && !ape.NamespaceNameRegexp.MatchString(lexems[0]) { + return ErrInvalidNamespace + } + var cnr cid.ID + err := cnr.DecodeString(lexems[1]) + if err != nil { + return fmt.Errorf("%w: %w", ErrInvalidContainerID, err) + } + if lexems[2] == "*" { + return nil + } + var objID oid.ID + err = objID.DecodeString(lexems[2]) + if err != nil { + return fmt.Errorf("%w: %w", ErrInvalidObjectID, err) + } + return nil + } + return ErrInvalidResource +} + +// validateContainerResourceName validate resource name for container. +// Name should be without prefix `native.ContainerPrefix`. +func validateContainerResourceName(name string) error { + if name == "*" { + return nil + } + lexems := strings.Split(name, "/") + if len(lexems) == 1 && lexems[0] == "*" { + return nil + } else if len(lexems) == 2 { + // len == 2 means format `namespace(root_namespace)/CID(*)` + if lexems[0] != "" && !ape.NamespaceNameRegexp.MatchString(lexems[0]) { + return ErrInvalidNamespace + } + if lexems[1] != "*" { + var cnr cid.ID + err := cnr.DecodeString(lexems[1]) + if err != nil { + return fmt.Errorf("%w: %w", ErrInvalidContainerID, err) + } + } + return nil + } + return ErrInvalidResource +} diff --git a/pkg/services/control/server/ape/validate_test.go b/pkg/services/control/server/ape/validate_test.go new file mode 100644 index 0000000000..af811efed6 --- /dev/null +++ b/pkg/services/control/server/ape/validate_test.go @@ -0,0 +1,132 @@ +package ape + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/stretchr/testify/require" +) + +func TestValidationOfChainResources(t *testing.T) { + tests := [...]struct { + testName string + resourceName string + expectErr error + }{ + { + testName: "native object: all objects", + resourceName: native.ObjectPrefix + "/*", + }, + { + testName: "native object: all objects in namespace", + resourceName: native.ObjectPrefix + "/ns/*", + }, + { + testName: "native object: all objects in root namespace", + resourceName: native.ObjectPrefix + "//*", + }, + { + testName: "native object: all objects in namespace/container", + resourceName: native.ObjectPrefix + "/ns/SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH/*", + }, + { + testName: "native object: all objects in root namespace/container", + resourceName: native.ObjectPrefix + "//SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH/*", + }, + { + testName: "native object: object in namespace/container", + resourceName: native.ObjectPrefix + "/ns/SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH/BCGsUu6o92oG1UALVox1sV6YbBUKUL2xSCtAFkrsuvWY", + }, + { + testName: "native object: object in root namespace/container", + resourceName: native.ObjectPrefix + "//SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH/BCGsUu6o92oG1UALVox1sV6YbBUKUL2xSCtAFkrsuvWY", + }, + { + testName: "native object: invalid all objects", + resourceName: native.ObjectPrefix + "/*12313", + expectErr: ErrInvalidResource, + }, + { + testName: "native object: all objects in invalid namespace", + resourceName: native.ObjectPrefix + "/qwe_123123/*", + expectErr: ErrInvalidNamespace, + }, + { + testName: "native object: invalid all objects in root namespace", + resourceName: native.ObjectPrefix + "//qwe", + expectErr: ErrInvalidResource, + }, + { + testName: "native object: invalid cid in all objects in root namespace", + resourceName: native.ObjectPrefix + "//SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytHqwe/*", + expectErr: ErrInvalidContainerID, + }, + { + testName: "native object: invalid cid in all objects in namespace", + resourceName: native.ObjectPrefix + "/ns/SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytHqwe/*", + expectErr: ErrInvalidContainerID, + }, + { + testName: "native object: invalid object in namespace/container", + resourceName: native.ObjectPrefix + "/ns/SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH/BCGsUu6o92oG1UALVox1sV6YbBUKUL2xSCtAFkrsuvWY111", + expectErr: ErrInvalidObjectID, + }, + { + testName: "native object: invalid resource", + resourceName: native.ObjectPrefix + "/ns/SeHNpifD/AFkrsuvWY111/AFkrsuvWY222", + expectErr: ErrInvalidResource, + }, + { + testName: "native container: all containers", + resourceName: native.ContainerPrefix + "/*", + }, + { + testName: "native container: all containers in namespace", + resourceName: native.ContainerPrefix + "/ns/*", + }, + { + testName: "native container: all containers in root namespace", + resourceName: native.ContainerPrefix + "//*", + }, + { + testName: "native container: container in namespace", + resourceName: native.ContainerPrefix + "/ns/SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH", + }, + { + testName: "native container: container in root namespace", + resourceName: native.ContainerPrefix + "//SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH", + }, + { + testName: "native container: invalid all containers", + resourceName: native.ContainerPrefix + "/*asd", + expectErr: ErrInvalidResource, + }, + { + testName: "native container: invalid resource", + resourceName: native.ContainerPrefix + "/ns/cid/cid", + expectErr: ErrInvalidResource, + }, + { + testName: "native container: invalid container in root namespace", + resourceName: native.ContainerPrefix + "//*asd", + expectErr: ErrInvalidContainerID, + }, + { + testName: "native container: container in invalid namespace", + resourceName: native.ContainerPrefix + "/ns_111/SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH", + expectErr: ErrInvalidNamespace, + }, + { + testName: "unsupported prefix", + resourceName: "native:test/ns_111/SeHNpifDH2Fc4scNBphrbmrKi96QXj2HzYJkhSGuytH", + expectErr: ErrUnsupportedPrefix, + }, + } + + for _, test := range tests { + t.Run(test.testName, func(t *testing.T) { + err := ValidateResourceName(test.resourceName) + require.ErrorIs(t, err, test.expectErr) + }) + } +} diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 9b42f3a98e..bc85c4356f 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -6,6 +6,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ape" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "google.golang.org/grpc/codes" @@ -38,6 +39,13 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL if err := chain.DecodeBytes(req.GetBody().GetChain()); err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } + for _, rule := range chain.Rules { + for _, name := range rule.Resources.Names { + if err := ape.ValidateResourceName(name); err != nil { + return nil, status.Error(codes.InvalidArgument, fmt.Errorf("invalid resource: %w", err).Error()) + } + } + } s.apeChainCounter.Add(1) // TODO (aarifullin): the such chain id is not well-designed yet. From 4352bd0e8eab50c4e51128ee0415e9d7324664b3 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 26 Jan 2024 18:45:10 +0300 Subject: [PATCH 0295/1413] [#934] ape: Transform empty namespace within chainbase Signed-off-by: Airat Arifullin --- pkg/ape/chainbase/boltdb.go | 8 ++++++++ pkg/services/control/server/policy_engine.go | 7 +------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index 1047ad42d8..4e15050b33 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -115,6 +115,10 @@ func getTargetBucket(tx *bbolt.Tx, name chain.Name, target policyengine.Target) return nil, fmt.Errorf("%w: %w: %c", policyengine.ErrChainNotFound, ErrTargetTypeBucketNotFound, target.Type) } + if target.Type == policyengine.Namespace && target.Name == "" { + target.Name = "root" + } + rbucket := typeBucket.Bucket([]byte(target.Name)) if rbucket == nil { return nil, fmt.Errorf("%w: %w: %s", policyengine.ErrChainNotFound, ErrTargetNameBucketNotFound, target.Name) @@ -146,6 +150,10 @@ func getTargetBucketCreateIfEmpty(tx *bbolt.Tx, name chain.Name, target policyen } } + if target.Type == policyengine.Namespace && target.Name == "" { + target.Name = "root" + } + rbucket := typeBucket.Bucket([]byte(target.Name)) if rbucket == nil { var err error diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index bc85c4356f..6bf600748c 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -18,12 +18,7 @@ func apeTarget(chainTarget *control.ChainTarget) (engine.Target, error) { case control.ChainTarget_CONTAINER: return engine.ContainerTarget(chainTarget.GetName()), nil case control.ChainTarget_NAMESPACE: - namespace := chainTarget.GetName() - // If namespace is empty, we take it for root namespace. - if namespace == "" { - namespace = "root" - } - return engine.NamespaceTarget(namespace), nil + return engine.NamespaceTarget(chainTarget.GetName()), nil default: } return engine.Target{}, status.Error(codes.InvalidArgument, From 96c86c4637a0e7de45c2e7266c90120ef7650584 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 26 Jan 2024 18:57:47 +0300 Subject: [PATCH 0296/1413] [#934] adm: Make frostfsid commands read alphabet wallets Signed-off-by: Airat Arifullin --- cmd/frostfs-adm/internal/modules/morph/frostfsid.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 2a6043b7c4..50cd477445 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -151,11 +151,13 @@ func initFrostfsIDCreateNamespaceCmd() { frostfsidCmd.AddCommand(frostfsidCreateNamespaceCmd) frostfsidCreateNamespaceCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) frostfsidCreateNamespaceCmd.Flags().String(namespaceFlag, "", "Namespace name to create") + frostfsidCreateNamespaceCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDListNamespacesCmd() { frostfsidCmd.AddCommand(frostfsidListNamespacesCmd) frostfsidListNamespacesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListNamespacesCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDCreateSubjectCmd() { @@ -164,12 +166,14 @@ func initFrostfsIDCreateSubjectCmd() { frostfsidCreateSubjectCmd.Flags().String(namespaceFlag, "", "Namespace where create subject") frostfsidCreateSubjectCmd.Flags().String(subjectNameFlag, "", "Subject name, must be unique in namespace") frostfsidCreateSubjectCmd.Flags().String(subjectKeyFlag, "", "Subject hex-encoded public key") + frostfsidCreateSubjectCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDDeleteSubjectCmd() { frostfsidCmd.AddCommand(frostfsidDeleteSubjectCmd) frostfsidDeleteSubjectCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) frostfsidDeleteSubjectCmd.Flags().String(subjectAddressFlag, "", "Subject address") + frostfsidDeleteSubjectCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDListSubjectsCmd() { @@ -177,6 +181,7 @@ func initFrostfsIDListSubjectsCmd() { frostfsidListSubjectsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") + frostfsidListSubjectsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDCreateGroupCmd() { @@ -184,6 +189,7 @@ func initFrostfsIDCreateGroupCmd() { frostfsidCreateGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) frostfsidCreateGroupCmd.Flags().String(namespaceFlag, "", "Namespace where create group") frostfsidCreateGroupCmd.Flags().String(groupNameFlag, "", "Group name, must be unique in namespace") + frostfsidCreateGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDDeleteGroupCmd() { @@ -191,12 +197,14 @@ func initFrostfsIDDeleteGroupCmd() { frostfsidDeleteGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) frostfsidDeleteGroupCmd.Flags().String(namespaceFlag, "", "Namespace to delete group") frostfsidDeleteGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") + frostfsidDeleteGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDListGroupsCmd() { frostfsidCmd.AddCommand(frostfsidListGroupsCmd) frostfsidListGroupsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") + frostfsidListGroupsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDAddSubjectToGroupCmd() { @@ -204,6 +212,7 @@ func initFrostfsIDAddSubjectToGroupCmd() { frostfsidAddSubjectToGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) frostfsidAddSubjectToGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidAddSubjectToGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") + frostfsidAddSubjectToGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDRemoveSubjectFromGroupCmd() { @@ -211,6 +220,7 @@ func initFrostfsIDRemoveSubjectFromGroupCmd() { frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) frostfsidRemoveSubjectFromGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidRemoveSubjectFromGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") + frostfsidRemoveSubjectFromGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDListGroupSubjectsCmd() { @@ -219,6 +229,7 @@ func initFrostfsIDListGroupSubjectsCmd() { frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") + frostfsidListGroupSubjectsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { From 5be2af881abb92c20723d9f1cc5b34f5c0770cad Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 30 Jan 2024 00:03:18 +0300 Subject: [PATCH 0297/1413] [#934] container: Make container APE middleware read namespaces * Those methods that can access already existing containers and thus can get container properties should read namespace from Zone property. If Zone is not set, take a namespace for root. * Otherwise, define namespaces by owner ID via frostfs-id contract. * Improve unit-tests, consider more cases. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 13 + cmd/frostfs-node/config/contracts/config.go | 4 + cmd/frostfs-node/container.go | 6 +- cmd/frostfs-node/morph.go | 1 + go.mod | 2 +- go.sum | 4 +- pkg/morph/client/frostfsid/subject.go | 17 +- pkg/services/container/ape.go | 138 +++- pkg/services/container/ape_test.go | 690 +++++++++++++++++++- pkg/services/object/acl/v2/service.go | 9 +- 10 files changed, 832 insertions(+), 52 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e1e2283250..29582c7821 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -449,6 +449,7 @@ type cfg struct { cfgMorph cfgMorph cfgAccounting cfgAccounting cfgContainer cfgContainer + cfgFrostfsID cfgFrostfsID cfgNodeInfo cfgNodeInfo cfgNetmap cfgNetmap cfgControlService cfgControlService @@ -569,6 +570,10 @@ type cfgContainer struct { workerPool util.WorkerPool // pool for asynchronous handlers } +type cfgFrostfsID struct { + scriptHash neogoutil.Uint160 +} + type cfgNetmap struct { scriptHash neogoutil.Uint160 wrapper *nmClient.Client @@ -681,6 +686,8 @@ func initCfg(appCfg *config.Config) *cfg { } c.cfgContainer = initContainer(appCfg) + c.cfgFrostfsID = initFrostfsID(appCfg) + c.cfgNetmap = initNetmap(appCfg, netState, relayOnly) c.cfgGRPC = initCfgGRPC() @@ -779,6 +786,12 @@ func initContainer(appCfg *config.Config) cfgContainer { } } +func initFrostfsID(appCfg *config.Config) cfgFrostfsID { + return cfgFrostfsID{ + scriptHash: contractsconfig.FrostfsID(appCfg), + } +} + func initCfgGRPC() cfgGRPC { maxChunkSize := uint64(maxMsgSize) * 3 / 4 // 25% to meta, 75% to payload maxAddrAmount := uint64(maxChunkSize) / addressSize // each address is about 72 bytes diff --git a/cmd/frostfs-node/config/contracts/config.go b/cmd/frostfs-node/config/contracts/config.go index c5f14f3ca7..df0c0b9588 100644 --- a/cmd/frostfs-node/config/contracts/config.go +++ b/cmd/frostfs-node/config/contracts/config.go @@ -38,6 +38,10 @@ func Container(c *config.Config) util.Uint160 { return contractAddress(c, "container") } +func FrostfsID(c *config.Config) util.Uint160 { + return contractAddress(c, "frostfsid") +} + // Proxy returnsthe value of "proxy" config parameter // from "contracts" section. // diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 898a4eef91..28f2710757 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" containerTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/container/grpc" @@ -32,11 +33,14 @@ func initContainerService(_ context.Context, c *cfg) { cnrRdr, cnrWrt := configureEACLAndContainerSources(c, wrap, cnrSrc) + frostFSIDClient, err := frostfsid.NewFromMorph(c.cfgMorph.client, c.cfgFrostfsID.scriptHash, 0) + fatalOnErr(err) + server := containerTransportGRPC.New( containerService.NewSignService( &c.key.PrivateKey, containerService.NewAPEServer(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine, cnrRdr, - newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, + newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, frostFSIDClient, containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), ), ), diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index d26142370f..698fb3b832 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -288,6 +288,7 @@ func lookupScriptHashesInNNS(c *cfg) { {&c.cfgNetmap.scriptHash, client.NNSNetmapContractName}, {&c.cfgAccounting.scriptHash, client.NNSBalanceContractName}, {&c.cfgContainer.scriptHash, client.NNSContainerContractName}, + {&c.cfgFrostfsID.scriptHash, client.NNSFrostFSIDContractName}, {&c.cfgMorph.proxyScriptHash, client.NNSProxyContractName}, {&c.cfgObject.cfgAccessPolicyEngine.policyContractHash, client.NNSPolicyContractName}, } diff --git a/go.mod b/go.mod index 3b269db344..a5cffc28c7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240117145620-110b7e41706e + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240122104724-06cbfe8691ad git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index ca28fdaec2..4462c35751 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240117145620-110b7e41706e h1:0t+3iEb2wFJjJryqGnh5wkr9DEiwRNb61KaxC27U+po= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240117145620-110b7e41706e/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0 h1:jp/Cg6CF3ip0IVRCjt48qKyv1cbMUmNYTn2z1jFLWqc= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240122104724-06cbfe8691ad h1:+D96Uu0Pw+55CrxP+srazthtZAh0Q19BtJo1Pm4hOP0= diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index b14675d582..52ae98ba57 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -33,16 +33,17 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) return subj, nil } -// parseSubject from https://git.frostfs.info/TrueCloudLab/frostfs-contract/src/commit/dd5919348da9731f24504e7bc485516c2ba5f11c/frostfsid/client/client.go#L592 -func parseSubject(structArr []stackitem.Item) (*frostfsidclient.Subject, error) { - if len(structArr) < 5 { - return nil, errors.New("invalid response subject struct") +func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) { + if ln := len(res); ln != 1 { + return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) } - var ( - err error - subj frostfsidclient.Subject - ) + structArr, err := client.ArrayFromStackItem(res[0]) + if err != nil { + return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) + } + + var subj frostfsidclient.Subject subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) if err != nil { diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 36edf45161..c57e54d08a 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -8,14 +8,17 @@ import ( "crypto/sha256" "errors" "fmt" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" @@ -25,6 +28,7 @@ import ( "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" ) var ( @@ -35,6 +39,7 @@ var ( errInvalidSessionTokenOwner = errors.New("malformed request: invalid session token owner") errEmptyBodySignature = errors.New("malformed request: empty body signature") errMissingOwnerID = errors.New("malformed request: missing owner ID") + errSubjectNotFound = errors.New("subject not found") undefinedContainerID = cid.ID{} ) @@ -47,22 +52,29 @@ type containers interface { Get(cid.ID) (*containercore.Container, error) } +type frostfsidSubjectProvider interface { + GetSubject(util.Uint160) (*client.Subject, error) +} + type apeChecker struct { router policyengine.ChainRouter reader containers ir ir nm netmap.Source + frostFSIDClient frostfsidSubjectProvider + next Server } -func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm netmap.Source, srv Server) Server { +func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm netmap.Source, frostFSIDClient frostfsidSubjectProvider, srv Server) Server { return &apeChecker{ - router: router, - reader: reader, - ir: ir, - next: srv, - nm: nm, + router: router, + reader: reader, + ir: ir, + next: srv, + nm: nm, + frostFSIDClient: frostFSIDClient, } } @@ -125,9 +137,17 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co nativeschema.PropertyKeyActorRole: role, } + namespace, err := ac.namespaceByOwner(req.GetBody().GetOwnerID()) + if err != nil { + return nil, fmt.Errorf("could not get owner namespace: %w", err) + } + if err := ac.validateNamespaceByPublicKey(pk, namespace); err != nil { + return nil, err + } + request := &apeRequest{ resource: &apeResource{ - name: nativeschema.ResourceFormatRootContainers, + name: resourceName(namespace, ""), props: make(map[string]string), }, op: nativeschema.MethodListContainers, @@ -135,7 +155,7 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co } s, found, err := ac.router.IsAllowed(apechain.Ingress, - policyengine.NewRequestTargetWithNamespace(""), + policyengine.NewRequestTargetWithNamespace(namespace), request) if err != nil { return nil, err @@ -162,9 +182,17 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont nativeschema.PropertyKeyActorRole: role, } + namespace, err := ac.namespaceByOwner(req.GetBody().GetContainer().GetOwnerID()) + if err != nil { + return nil, fmt.Errorf("get namespace error: %w", err) + } + if err = validateNamespace(req.GetBody().GetContainer(), namespace); err != nil { + return nil, err + } + request := &apeRequest{ resource: &apeResource{ - name: nativeschema.ResourceFormatRootContainers, + name: resourceName(namespace, ""), props: make(map[string]string), }, op: nativeschema.MethodPutContainer, @@ -172,7 +200,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont } s, found, err := ac.router.IsAllowed(apechain.Ingress, - policyengine.NewRequestTargetWithNamespace(""), + policyengine.NewRequestTargetWithNamespace(namespace), request) if err != nil { return nil, err @@ -251,9 +279,15 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai return err } + namespace := "" + cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cont.Value).Zone(), ".ns") + if hasNamespace { + namespace = cntNamespace + } + request := &apeRequest{ resource: &apeResource{ - name: fmt.Sprintf(nativeschema.ResourceFormatRootContainer, id.EncodeToString()), + name: resourceName(namespace, id.EncodeToString()), props: ac.getContainerProps(cont), }, op: op, @@ -261,7 +295,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai } s, found, err := ac.router.IsAllowed(apechain.Ingress, - policyengine.NewRequestTargetWithContainer(id.EncodeToString()), + policyengine.NewRequestTarget(cntNamespace, id.EncodeToString()), request) if err != nil { return err @@ -326,6 +360,19 @@ func (r *apeResource) Property(key string) string { return r.props[key] } +func resourceName(namespace string, container string) string { + if namespace == "" && container == "" { + return nativeschema.ResourceFormatRootContainers + } + if namespace == "" && container != "" { + return fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container) + } + if namespace != "" && container == "" { + return fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainers, namespace) + } + return fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainer, namespace, container) +} + func (ac *apeChecker) getContainerProps(c *containercore.Container) map[string]string { return map[string]string{ nativeschema.PropertyKeyContainerOwnerID: c.Value.Owner().EncodeToString(), @@ -514,3 +561,70 @@ func isContainerNode(nm *netmapSDK.NetMap, pk, binCnrID []byte, cont *containerc return false, nil } + +func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { + var ownerSDK user.ID + if owner == nil { + return "", fmt.Errorf("owner id is not set") + } + if err := ownerSDK.ReadFromV2(*owner); err != nil { + return "", err + } + addr, err := ownerSDK.ScriptHash() + if err != nil { + return "", err + } + + namespace := "" + subject, err := ac.frostFSIDClient.GetSubject(addr) + if err == nil { + namespace = subject.Namespace + } else { + if !strings.Contains(err.Error(), errSubjectNotFound.Error()) { + return "", fmt.Errorf("get subject error: %w", err) + } + } + return namespace, nil +} + +// validateNamespace validates a namespace set in a container. +// If frostfs-id contract stores a namespace N1 for an owner ID and a container within a request +// is set with namespace N2 (via Zone() property), then N2 is invalid and the request is denied. +func validateNamespace(cnrV2 *container.Container, ownerIDNamespace string) error { + if cnrV2 == nil { + return nil + } + var cnr cnrSDK.Container + if err := cnr.ReadFromV2(*cnrV2); err != nil { + return err + } + cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cnr).Zone(), ".ns") + if hasNamespace { + if cntNamespace != ownerIDNamespace { + if ownerIDNamespace == "" { + return fmt.Errorf("invalid domain zone: no namespace is expected") + } + return fmt.Errorf("invalid domain zone: expected namespace %s, but got %s", ownerIDNamespace, cntNamespace) + } + } else if ownerIDNamespace != "" { + return fmt.Errorf("invalid domain zone: expected namespace %s, but got invalid or empty", ownerIDNamespace) + } + return nil +} + +// validateNamespace validates if a namespace of a request actor equals to owner's namespace. +// An actor's namespace is calculated by a public key. +func (ac *apeChecker) validateNamespaceByPublicKey(pk *keys.PublicKey, ownerIDNamespace string) error { + var actor user.ID + user.IDFromKey(&actor, (ecdsa.PublicKey)(*pk)) + actorOwnerID := new(refs.OwnerID) + actor.WriteToV2(actorOwnerID) + actorNamespace, err := ac.namespaceByOwner(actorOwnerID) + if err != nil { + return fmt.Errorf("could not get actor namespace: %w", err) + } + if actorNamespace != ownerIDNamespace { + return fmt.Errorf("actor namespace %s differs from owner: %s", actorNamespace, ownerIDNamespace) + } + return nil +} diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index f4dfbe50fa..5344d9f238 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -2,6 +2,7 @@ package container import ( "context" + "crypto/ecdsa" "errors" "fmt" "testing" @@ -9,10 +10,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/test" @@ -24,16 +27,25 @@ import ( "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" ) +const ( + testDomainName = "testdomainname" + testDomainZone = "testdomainname.ns" +) + func TestAPE(t *testing.T) { t.Parallel() t.Run("deny get container for others", testDenyGetContainerForOthers) t.Run("deny set container eACL for IR", testDenySetContainerEACLForIR) t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken) t.Run("deny put container for others with session token", testDenyPutContainerForOthersSessionToken) + t.Run("deny put container, read namespace from frostfsID", testDenyPutContainerReadNamespaceFromFrostfsID) + t.Run("deny put container with invlaid namespace", testDenyPutContainerInvalidNamespace) t.Run("deny list containers for owner with PK", testDenyListContainersForPK) + t.Run("deny list containers by namespace invalidation", testDenyListContainersValidationNamespaceError) } func testDenyGetContainerForOthers(t *testing.T) { @@ -49,7 +61,10 @@ func testDenyGetContainerForOthers(t *testing.T) { keys: [][]byte{}, } nm := &netmapStub{} - apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{}, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) contID := cidtest.ID() testContainer := containertest.Container() @@ -122,7 +137,10 @@ func testDenySetContainerEACLForIR(t *testing.T) { keys: [][]byte{}, } nm := &netmapStub{} - apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{}, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) contID := cidtest.ID() testContainer := containertest.Container() @@ -197,7 +215,10 @@ func testDenyGetContainerEACLForIRSessionToken(t *testing.T) { keys: [][]byte{}, } nm := &netmapStub{} - apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{}, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) contID := cidtest.ID() testContainer := containertest.Container() @@ -283,7 +304,10 @@ func testDenyPutContainerForOthersSessionToken(t *testing.T) { keys: [][]byte{}, } nm := &netmapStub{} - apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{}, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) testContainer := containertest.Container() @@ -317,26 +341,7 @@ func testDenyPutContainerForOthersSessionToken(t *testing.T) { }) require.NoError(t, err) - req := &container.PutRequest{} - req.SetBody(&container.PutRequestBody{}) - var reqCont container.Container - testContainer.WriteToV2(&reqCont) - req.GetBody().SetContainer(&reqCont) - - sessionPK, err := keys.NewPrivateKey() - require.NoError(t, err) - sToken := sessiontest.ContainerSigned() - sToken.ApplyOnlyTo(cid.ID{}) - require.NoError(t, sToken.Sign(sessionPK.PrivateKey)) - var sTokenV2 session.Token - sToken.WriteToV2(&sTokenV2) - metaHeader := new(session.RequestMetaHeader) - metaHeader.SetSessionToken(&sTokenV2) - req.SetMetaHeader(metaHeader) - - pk, err := keys.NewPrivateKey() - require.NoError(t, err) - require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + req := initPutRequest(t, testContainer) resp, err := apeSrv.Put(context.Background(), req) require.Nil(t, resp) @@ -344,6 +349,139 @@ func testDenyPutContainerForOthersSessionToken(t *testing.T) { require.ErrorAs(t, err, &errAccessDenied) } +func testDenyPutContainerReadNamespaceFromFrostfsID(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + + cnrID, testContainer := initTestContainer(t, true) + contRdr.c[cnrID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + + _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(testDomainName), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodPutContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainers, testDomainName), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initPutRequest(t, testContainer) + ownerScriptHash := initOwnerIDScriptHash(t, testContainer) + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + ownerScriptHash: { + Namespace: testDomainName, + Name: testDomainName, + }, + }, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + resp, err := apeSrv.Put(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) +} + +func testDenyPutContainerInvalidNamespace(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + + cnrID, testContainer := initTestContainer(t, false) + var domain cnrSDK.Domain + domain.SetName("incorrect" + testDomainName) + domain.SetZone("incorrect" + testDomainZone) + cnrSDK.WriteDomain(&testContainer, domain) + contRdr.c[cnrID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + + _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(testDomainName), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodPutContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainers, testDomainName), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initPutRequest(t, testContainer) + ownerScriptHash := initOwnerIDScriptHash(t, testContainer) + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + ownerScriptHash: { + Namespace: testDomainName, + Name: testDomainName, + }, + }, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + resp, err := apeSrv.Put(context.Background(), req) + require.Nil(t, resp) + require.ErrorContains(t, err, "invalid domain zone") +} + func testDenyListContainersForPK(t *testing.T) { t.Parallel() srv := &srvStub{ @@ -357,7 +495,10 @@ func testDenyListContainersForPK(t *testing.T) { keys: [][]byte{}, } nm := &netmapStub{} - apeSrv := NewAPEServer(router, contRdr, ir, nm, srv) + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{}, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) nm.currentEpoch = 100 nm.netmaps = map[uint64]*netmap.NetMap{} @@ -409,6 +550,82 @@ func testDenyListContainersForPK(t *testing.T) { require.ErrorAs(t, err, &errAccessDenied) } +func testDenyListContainersValidationNamespaceError(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + + actorPK, err := keys.NewPrivateKey() + require.NoError(t, err) + + ownerPK, err := keys.NewPrivateKey() + require.NoError(t, err) + + actorScriptHash, ownerScriptHash := initActorOwnerScriptHashes(t, actorPK, ownerPK) + + const actorDomain = "actor" + testDomainName + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + actorScriptHash: { + Namespace: actorDomain, + Name: actorDomain, + }, + ownerScriptHash: { + Namespace: testDomainName, + Name: testDomainName, + }, + }, + } + + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodListContainers, + }, + }, + Resources: chain.Resources{ + Names: []string{ + nativeschema.ResourceFormatRootContainers, + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorPublicKey, + Value: actorPK.PublicKey().String(), + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initListRequest(t, actorPK, ownerPK) + + resp, err := apeSrv.List(context.Background(), req) + require.Nil(t, resp) + require.ErrorContains(t, err, "actor namespace "+actorDomain+" differs") +} + type srvStub struct { calls map[string]int } @@ -489,3 +706,424 @@ func (s *netmapStub) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { func (s *netmapStub) Epoch() (uint64, error) { return s.currentEpoch, nil } + +type frostfsidStub struct { + subjects map[util.Uint160]*client.Subject +} + +func (f *frostfsidStub) GetSubject(owner util.Uint160) (*client.Subject, error) { + s, ok := f.subjects[owner] + if !ok { + return nil, errSubjectNotFound + } + return s, nil +} + +type testAPEServer struct { + engine engine.Engine + + containerReader *containerStub + + ir *irStub + + netmap *netmapStub + + frostfsIDSubjectReader *frostfsidStub + + apeChecker *apeChecker +} + +func newTestAPEServer() testAPEServer { + srv := &srvStub{ + calls: map[string]int{}, + } + + engine := inmemory.NewInMemory() + + containerReader := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + + ir := &irStub{ + keys: [][]byte{}, + } + + netmap := &netmapStub{} + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{}, + } + + apeChecker := &apeChecker{ + router: engine, + reader: containerReader, + ir: ir, + nm: netmap, + frostFSIDClient: frostfsIDSubjectReader, + next: srv, + } + + return testAPEServer{ + engine: engine, + containerReader: containerReader, + ir: ir, + netmap: netmap, + frostfsIDSubjectReader: frostfsIDSubjectReader, + apeChecker: apeChecker, + } +} + +func TestValidateContainerBoundedOperation(t *testing.T) { + t.Parallel() + + t.Run("check root-defined container in root-defined container target rule", func(t *testing.T) { + t.Parallel() + + components := newTestAPEServer() + contID, testContainer := initTestContainer(t, false) + components.containerReader.c[contID] = &containercore.Container{Value: testContainer} + initTestNetmap(components.netmap) + + _, _, err := components.engine.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initTestGetContainerRequest(t, contID) + + err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + aErr := apeErr(nativeschema.MethodGetContainer, chain.AccessDenied) + require.ErrorContains(t, err, aErr.Error()) + }) + + t.Run("check root-defined container in testdomain-defined container target rule", func(t *testing.T) { + t.Parallel() + + components := newTestAPEServer() + contID, testContainer := initTestContainer(t, false) + components.containerReader.c[contID] = &containercore.Container{Value: testContainer} + initTestNetmap(components.netmap) + + _, _, err := components.engine.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainer, testDomainName, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initTestGetContainerRequest(t, contID) + + err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + require.NoError(t, err) + }) + + t.Run("check root-defined container in testdomain namespace target rule", func(t *testing.T) { + t.Parallel() + + components := newTestAPEServer() + contID, testContainer := initTestContainer(t, false) + components.containerReader.c[contID] = &containercore.Container{Value: testContainer} + initTestNetmap(components.netmap) + + _, _, err := components.engine.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(testDomainName), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainers, testDomainName), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initTestGetContainerRequest(t, contID) + + err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + require.NoError(t, err) + }) + + t.Run("check testdomain-defined container in root-defined container target rule", func(t *testing.T) { + t.Parallel() + + components := newTestAPEServer() + contID, testContainer := initTestContainer(t, true) + components.containerReader.c[contID] = &containercore.Container{Value: testContainer} + initTestNetmap(components.netmap) + + _, _, err := components.engine.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initTestGetContainerRequest(t, contID) + + err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + require.NoError(t, err) + }) + + t.Run("check testdomain-defined container in testdomain-defined container target rule", func(t *testing.T) { + t.Parallel() + + components := newTestAPEServer() + contID, testContainer := initTestContainer(t, true) + components.containerReader.c[contID] = &containercore.Container{Value: testContainer} + initTestNetmap(components.netmap) + + _, _, err := components.engine.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainer, testDomainName, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initTestGetContainerRequest(t, contID) + + err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + aErr := apeErr(nativeschema.MethodGetContainer, chain.AccessDenied) + require.ErrorContains(t, err, aErr.Error()) + }) + + t.Run("check testdomain-defined container in testdomain namespace target rule", func(t *testing.T) { + t.Parallel() + + components := newTestAPEServer() + contID, testContainer := initTestContainer(t, true) + components.containerReader.c[contID] = &containercore.Container{Value: testContainer} + initTestNetmap(components.netmap) + + _, _, err := components.engine.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(testDomainName), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainers, testDomainName), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initTestGetContainerRequest(t, contID) + + err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + aErr := apeErr(nativeschema.MethodGetContainer, chain.AccessDenied) + require.ErrorContains(t, err, aErr.Error()) + }) +} + +func initTestGetContainerRequest(t *testing.T, contID cid.ID) *container.GetRequest { + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + return req +} + +func initTestNetmap(netmapStub *netmapStub) { + netmapStub.currentEpoch = 100 + netmapStub.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(netmapStub.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + netmapStub.netmaps[netmapStub.currentEpoch] = &testNetmap + netmapStub.netmaps[netmapStub.currentEpoch-1] = &testNetmap +} + +func initTestContainer(t *testing.T, isDomainSet bool) (cid.ID, cnrSDK.Container) { + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + if isDomainSet { + // no domain defined -> container is defined in root namespace + var domain cnrSDK.Domain + domain.SetName(testDomainName) + domain.SetZone(testDomainZone) + cnrSDK.WriteDomain(&testContainer, domain) + } + return contID, testContainer +} + +func initPutRequest(t *testing.T, testContainer cnrSDK.Container) *container.PutRequest { + req := &container.PutRequest{} + req.SetBody(&container.PutRequestBody{}) + var reqCont container.Container + testContainer.WriteToV2(&reqCont) + req.GetBody().SetContainer(&reqCont) + + sessionPK, err := keys.NewPrivateKey() + require.NoError(t, err) + sToken := sessiontest.ContainerSigned() + sToken.ApplyOnlyTo(cid.ID{}) + require.NoError(t, sToken.Sign(sessionPK.PrivateKey)) + var sTokenV2 session.Token + sToken.WriteToV2(&sTokenV2) + metaHeader := new(session.RequestMetaHeader) + metaHeader.SetSessionToken(&sTokenV2) + req.SetMetaHeader(metaHeader) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + return req +} + +func initOwnerIDScriptHash(t *testing.T, testContainer cnrSDK.Container) util.Uint160 { + var ownerSDK *user.ID + owner := testContainer.Owner() + ownerSDK = &owner + sc, err := ownerSDK.ScriptHash() + require.NoError(t, err) + return sc +} + +func initActorOwnerScriptHashes(t *testing.T, actorPK *keys.PrivateKey, ownerPK *keys.PrivateKey) (actorScriptHash util.Uint160, ownerScriptHash util.Uint160) { + var actorUserID user.ID + user.IDFromKey(&actorUserID, ecdsa.PublicKey(*actorPK.PublicKey())) + var err error + actorScriptHash, err = actorUserID.ScriptHash() + require.NoError(t, err) + + var ownerUserID user.ID + user.IDFromKey(&ownerUserID, ecdsa.PublicKey(*ownerPK.PublicKey())) + ownerScriptHash, err = ownerUserID.ScriptHash() + require.NoError(t, err) + require.NotEqual(t, ownerScriptHash.String(), actorScriptHash.String()) + return +} + +func initListRequest(t *testing.T, actorPK *keys.PrivateKey, ownerPK *keys.PrivateKey) *container.ListRequest { + var ownerUserID user.ID + user.IDFromKey(&ownerUserID, ownerPK.PrivateKey.PublicKey) + + req := &container.ListRequest{} + req.SetBody(&container.ListRequestBody{}) + var ownerID refs.OwnerID + ownerUserID.WriteToV2(&ownerID) + req.GetBody().SetOwnerID(&ownerID) + + require.NoError(t, signature.SignServiceMessage(&actorPK.PrivateKey, req)) + return req +} diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index ed077411c3..59535dc8ab 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -4,8 +4,8 @@ import ( "context" "errors" "fmt" + "strings" - containerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -744,7 +745,11 @@ func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (in info.operation = op info.cnrOwner = cnr.Value.Owner() info.idCnr = idCnr - info.cnrNamespace = cnr.Value.Attribute(containerV2.SysAttributeZone) + + cnrNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cnr.Value).Zone(), ".ns") + if hasNamespace { + info.cnrNamespace = cnrNamespace + } // it is assumed that at the moment the key will be valid, // otherwise the request would not pass validation From 6534252c226a47603a7224d74d40ef943c51a926 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 10 Jan 2024 15:17:05 +0300 Subject: [PATCH 0298/1413] [#799] policer: Refactor method `processNodes` Signed-off-by: Anton Nikiforov --- pkg/services/policer/check.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 73f83b2a79..bb6313d071 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -132,21 +132,21 @@ func (p *Policer) processNodes(ctx context.Context, requirements *placementRequi cancel() - if client.IsErrObjectNotFound(err) { - checkedNodes.submitReplicaCandidate(nodes[i]) - continue - } - - if isClientErrMaintenance(err) { - shortage, uncheckedCopies = p.handleMaintenance(nodes[i], checkedNodes, shortage, uncheckedCopies) - } else if err != nil { - p.log.Error(logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, - zap.Stringer("object", addr), - zap.String("error", err.Error()), - ) - } else { + if err == nil { shortage-- checkedNodes.submitReplicaHolder(nodes[i]) + } else { + if client.IsErrObjectNotFound(err) { + checkedNodes.submitReplicaCandidate(nodes[i]) + continue + } else if isClientErrMaintenance(err) { + shortage, uncheckedCopies = p.handleMaintenance(nodes[i], checkedNodes, shortage, uncheckedCopies) + } else { + p.log.Error(logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, + zap.Stringer("object", addr), + zap.String("error", err.Error()), + ) + } } } From d0eadf7ea2638a89e754592322bd2f1012c4756d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 21 Nov 2023 15:06:54 +0300 Subject: [PATCH 0299/1413] [#799] engine: Skip put when object removed from shard Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/engine/evacuate.go | 28 ++++----- pkg/local_object_storage/engine/put.go | 66 ++++++++++++++------- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 7bb37ef614..f522e6fbdc 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -406,21 +406,21 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add if _, ok := shardsToEvacuate[shards[j].ID().String()]; ok { continue } - putDone, exists := e.putToShard(ctx, shards[j].hashedShard, j, shards[j].pool, addr, object) - if putDone || exists { - if putDone { - res.evacuated.Add(1) - e.log.Debug(logs.EngineObjectIsMovedToAnotherShard, - zap.Stringer("from", sh.ID()), - zap.Stringer("to", shards[j].ID()), - zap.Stringer("addr", addr), - evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) - } - if exists { - res.skipped.Add(1) - } + switch e.putToShard(ctx, shards[j].hashedShard, j, shards[j].pool, addr, object).status { + case putToShardSuccess: + res.evacuated.Add(1) + e.log.Debug(logs.EngineObjectIsMovedToAnotherShard, + zap.Stringer("from", sh.ID()), + zap.Stringer("to", shards[j].ID()), + zap.Stringer("addr", addr), + evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return true, nil + case putToShardExists, putToShardRemoved: + res.skipped.Add(1) + return true, nil + default: + continue } } diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 7ce915ad86..2b1712f3f6 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -12,6 +12,7 @@ import ( tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" @@ -26,6 +27,20 @@ type PutPrm struct { var errPutShard = errors.New("could not put object to any shard") +type putToShardStatus byte + +const ( + putToShardUnknown putToShardStatus = iota + putToShardSuccess + putToShardExists + putToShardRemoved +) + +type putToShardRes struct { + status putToShardStatus + err error +} + // WithObject is a Put option to set object to save. // // Option is required. @@ -68,8 +83,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { return err } - finished := false - + var shRes putToShardRes e.iterateOverSortedShards(addr, func(ind int, sh hashedShard) (stop bool) { e.mtx.RLock() pool, ok := e.shardPools[sh.ID().String()] @@ -78,25 +92,26 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // Shard was concurrently removed, skip. return false } - - putDone, exists := e.putToShard(ctx, sh, ind, pool, addr, prm.obj) - finished = putDone || exists - return finished + shRes = e.putToShard(ctx, sh, ind, pool, addr, prm.obj) + return shRes.status != putToShardUnknown }) - - if !finished { - err = errPutShard + switch shRes.status { + case putToShardUnknown: + return errPutShard + case putToShardRemoved: + return shRes.err + case putToShardExists, putToShardSuccess: + return nil + default: + return errPutShard } - - return err } // putToShard puts object to sh. -// First return value is true iff put has been successfully done. -// Second return value is true iff object already exists. -func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, pool util.WorkerPool, addr oid.Address, obj *objectSDK.Object) (bool, bool) { - var putSuccess, alreadyExists bool - +// Return putToShardStatus and error if it is necessary to propagate an error upper. +func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, pool util.WorkerPool, + addr oid.Address, obj *objectSDK.Object, +) (res putToShardRes) { exitCh := make(chan struct{}) if err := pool.Submit(func() { @@ -110,14 +125,13 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, if shard.IsErrObjectExpired(err) { // object is already found but // expired => do nothing with it - alreadyExists = true + res.status = putToShardExists } return // this is not ErrAlreadyRemoved error so we can go to the next shard } - alreadyExists = exists.Exists() - if alreadyExists { + if exists.Exists() { if ind != 0 { var toMoveItPrm shard.ToMoveItPrm toMoveItPrm.SetAddress(addr) @@ -132,6 +146,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, } } + res.status = putToShardExists return } @@ -148,12 +163,21 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return } + if client.IsErrObjectAlreadyRemoved(err) { + e.log.Warn(logs.EngineCouldNotPutObjectToShard, + zap.Stringer("shard_id", sh.ID()), + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + res.status = putToShardRemoved + res.err = err + return + } e.reportShardError(sh, "could not put object to shard", err) return } - putSuccess = true + res.status = putToShardSuccess }); err != nil { e.log.Warn(logs.EngineCouldNotPutObjectToShard, zap.Error(err)) close(exitCh) @@ -161,7 +185,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, <-exitCh - return putSuccess, alreadyExists + return } // Put writes provided object to local storage. From a5446bc17d28475d7aa07c2aa3548de2d649cab8 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 2 Feb 2024 14:46:12 +0300 Subject: [PATCH 0300/1413] [#952] object: Pass namespace within context in ACL service Signed-off-by: Airat Arifullin --- pkg/services/object/acl/v2/service.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 59535dc8ab..af26a6fd18 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -458,6 +458,7 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { return context.WithValue(ctx, object.RequestContextKey, &object.RequestContext{ + Namespace: reqInfo.ContainerNamespace(), SenderKey: reqInfo.SenderKey(), Role: reqInfo.RequestRole(), }) From 2cb04379a418028dd6d7d6bd7b77e796886cce00 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 29 Jan 2024 11:23:56 +0300 Subject: [PATCH 0301/1413] [#922] go.mod: Update APE Signed-off-by: Anton Nikiforov --- go.mod | 4 +- go.sum | 8 +++- pkg/ape/chainbase/boltdb.go | 49 +++++++++++++++++++- pkg/services/control/server/policy_engine.go | 2 +- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index a5cffc28c7..07097c5470 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0 git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240122104724-06cbfe8691ad + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 @@ -76,8 +76,10 @@ require ( github.com/holiman/uint256 v1.2.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect diff --git a/go.sum b/go.sum index 4462c35751..5243ac4350 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240122104724-06cbfe8691ad h1:+D96Uu0Pw+55CrxP+srazthtZAh0Q19BtJo1Pm4hOP0= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240122104724-06cbfe8691ad/go.mod h1:ps6oKO0mxaPJzK3admTB3iwoBXKkHnS73n4PCrqpHBg= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 h1:hkDIg6vzV1c1pyt5uj9EiBikHqKczfoNpPhwWvXaNf8= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9/go.mod h1:YVL7yFaT0QNSpA0z+RHudLvrLwT+lsFYGyBSVc1ustI= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= @@ -114,6 +114,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= @@ -129,6 +131,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index 4e15050b33..c26156c7a7 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -167,8 +167,8 @@ func getTargetBucketCreateIfEmpty(tx *bbolt.Tx, name chain.Name, target policyen } func (cs *boltLocalOverrideStorage) AddOverride(name chain.Name, target policyengine.Target, c *chain.Chain) (chain.ID, error) { - if c.ID == "" { - return "", fmt.Errorf("chain ID is not set") + if len(c.ID) == 0 { + return chain.ID{}, fmt.Errorf("chain ID is not set") } serializedChain := c.Bytes() @@ -264,3 +264,48 @@ func (cs *boltLocalOverrideStorage) DropAllOverrides(name chain.Name) error { return tx.DeleteBucket([]byte(name)) }) } + +func (cs *boltLocalOverrideStorage) ListOverrideDefinedTargets(name chain.Name) ([]policyengine.Target, error) { + var targets []policyengine.Target + if err := cs.db.View(func(tx *bbolt.Tx) error { + var err error + targets, err = getTargets(tx, name) + if err != nil { + return err + } + return nil + }); err != nil { + return nil, err + } + return targets, nil +} + +func getTargets(tx *bbolt.Tx, name chain.Name) ([]policyengine.Target, error) { + var targets []policyengine.Target + cbucket := tx.Bucket(chainBucket) + if cbucket == nil { + return nil, ErrRootBucketNotFound + } + + nbucket := cbucket.Bucket([]byte(name)) + if nbucket == nil { + return nil, fmt.Errorf("%w: %w: %s", policyengine.ErrChainNotFound, ErrGlobalNamespaceBucketNotFound, name) + } + + if err := nbucket.ForEachBucket(func(k []byte) error { + ttype := policyengine.TargetType(k[0]) + if err := nbucket.Bucket(k).ForEachBucket(func(k []byte) error { + targets = append(targets, policyengine.Target{ + Type: ttype, + Name: string(slice.Copy(k)), + }) + return nil + }); err != nil { + return err + } + return nil + }); err != nil { + return nil, err + } + return targets, nil +} diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 6bf600748c..bd7f35f46f 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -44,7 +44,7 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL s.apeChainCounter.Add(1) // TODO (aarifullin): the such chain id is not well-designed yet. - if chain.ID == "" { + if len(chain.ID) == 0 { chain.ID = apechain.ID(fmt.Sprintf("%s:%d", apechain.Ingress, s.apeChainCounter.Load())) } From 95e15f499f3cf068a38358c2527d78ba33b1b6e9 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 29 Jan 2024 11:16:59 +0300 Subject: [PATCH 0302/1413] [#922] Update files generated by protoc Signed-off-by: Anton Nikiforov --- pkg/services/control/ir/service.pb.go | 2 +- pkg/services/control/ir/service_grpc.pb.go | 25 ++++++---- pkg/services/control/ir/types.pb.go | 2 +- pkg/services/control/service.pb.go | 2 +- pkg/services/control/types.pb.go | 2 +- pkg/services/tree/service.pb.go | 2 +- pkg/services/tree/service_grpc.pb.go | 54 ++++++++++++++-------- pkg/services/tree/types.pb.go | 2 +- 8 files changed, 57 insertions(+), 34 deletions(-) diff --git a/pkg/services/control/ir/service.pb.go b/pkg/services/control/ir/service.pb.go index a9be56cd9b..7dc8f3affa 100644 --- a/pkg/services/control/ir/service.pb.go +++ b/pkg/services/control/ir/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.25.0 // source: pkg/services/control/ir/service.proto diff --git a/pkg/services/control/ir/service_grpc.pb.go b/pkg/services/control/ir/service_grpc.pb.go index 0f93c0e190..724149c441 100644 --- a/pkg/services/control/ir/service_grpc.pb.go +++ b/pkg/services/control/ir/service_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.2.0 +// - protoc-gen-go-grpc v1.3.0 // - protoc v4.25.0 // source: pkg/services/control/ir/service.proto @@ -18,6 +18,13 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 +const ( + ControlService_HealthCheck_FullMethodName = "/ircontrol.ControlService/HealthCheck" + ControlService_TickEpoch_FullMethodName = "/ircontrol.ControlService/TickEpoch" + ControlService_RemoveNode_FullMethodName = "/ircontrol.ControlService/RemoveNode" + ControlService_RemoveContainer_FullMethodName = "/ircontrol.ControlService/RemoveContainer" +) + // ControlServiceClient is the client API for ControlService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -42,7 +49,7 @@ func NewControlServiceClient(cc grpc.ClientConnInterface) ControlServiceClient { func (c *controlServiceClient) HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) { out := new(HealthCheckResponse) - err := c.cc.Invoke(ctx, "/ircontrol.ControlService/HealthCheck", in, out, opts...) + err := c.cc.Invoke(ctx, ControlService_HealthCheck_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -51,7 +58,7 @@ func (c *controlServiceClient) HealthCheck(ctx context.Context, in *HealthCheckR func (c *controlServiceClient) TickEpoch(ctx context.Context, in *TickEpochRequest, opts ...grpc.CallOption) (*TickEpochResponse, error) { out := new(TickEpochResponse) - err := c.cc.Invoke(ctx, "/ircontrol.ControlService/TickEpoch", in, out, opts...) + err := c.cc.Invoke(ctx, ControlService_TickEpoch_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -60,7 +67,7 @@ func (c *controlServiceClient) TickEpoch(ctx context.Context, in *TickEpochReque func (c *controlServiceClient) RemoveNode(ctx context.Context, in *RemoveNodeRequest, opts ...grpc.CallOption) (*RemoveNodeResponse, error) { out := new(RemoveNodeResponse) - err := c.cc.Invoke(ctx, "/ircontrol.ControlService/RemoveNode", in, out, opts...) + err := c.cc.Invoke(ctx, ControlService_RemoveNode_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -69,7 +76,7 @@ func (c *controlServiceClient) RemoveNode(ctx context.Context, in *RemoveNodeReq func (c *controlServiceClient) RemoveContainer(ctx context.Context, in *RemoveContainerRequest, opts ...grpc.CallOption) (*RemoveContainerResponse, error) { out := new(RemoveContainerResponse) - err := c.cc.Invoke(ctx, "/ircontrol.ControlService/RemoveContainer", in, out, opts...) + err := c.cc.Invoke(ctx, ControlService_RemoveContainer_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -128,7 +135,7 @@ func _ControlService_HealthCheck_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/ircontrol.ControlService/HealthCheck", + FullMethod: ControlService_HealthCheck_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).HealthCheck(ctx, req.(*HealthCheckRequest)) @@ -146,7 +153,7 @@ func _ControlService_TickEpoch_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/ircontrol.ControlService/TickEpoch", + FullMethod: ControlService_TickEpoch_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).TickEpoch(ctx, req.(*TickEpochRequest)) @@ -164,7 +171,7 @@ func _ControlService_RemoveNode_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/ircontrol.ControlService/RemoveNode", + FullMethod: ControlService_RemoveNode_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).RemoveNode(ctx, req.(*RemoveNodeRequest)) @@ -182,7 +189,7 @@ func _ControlService_RemoveContainer_Handler(srv interface{}, ctx context.Contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/ircontrol.ControlService/RemoveContainer", + FullMethod: ControlService_RemoveContainer_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(ControlServiceServer).RemoveContainer(ctx, req.(*RemoveContainerRequest)) diff --git a/pkg/services/control/ir/types.pb.go b/pkg/services/control/ir/types.pb.go index cc39ad572c..819cedf6a5 100644 --- a/pkg/services/control/ir/types.pb.go +++ b/pkg/services/control/ir/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.25.0 // source: pkg/services/control/ir/types.proto diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 9fb6f865e5..f6b9ef6087 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.25.0 // source: pkg/services/control/service.proto diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index 8f083d6954..4556e8a555 100644 --- a/pkg/services/control/types.pb.go +++ b/pkg/services/control/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.25.0 // source: pkg/services/control/types.proto diff --git a/pkg/services/tree/service.pb.go b/pkg/services/tree/service.pb.go index 5346613895..441ae79272 100644 --- a/pkg/services/tree/service.pb.go +++ b/pkg/services/tree/service.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.25.0 // source: pkg/services/tree/service.proto diff --git a/pkg/services/tree/service_grpc.pb.go b/pkg/services/tree/service_grpc.pb.go index 66850c90e1..63f96e11a5 100644 --- a/pkg/services/tree/service_grpc.pb.go +++ b/pkg/services/tree/service_grpc.pb.go @@ -1,6 +1,9 @@ +//* +// Service for working with CRDT tree. + // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.2.0 +// - protoc-gen-go-grpc v1.3.0 // - protoc v4.25.0 // source: pkg/services/tree/service.proto @@ -18,6 +21,19 @@ import ( // Requires gRPC-Go v1.32.0 or later. const _ = grpc.SupportPackageIsVersion7 +const ( + TreeService_Add_FullMethodName = "/tree.TreeService/Add" + TreeService_AddByPath_FullMethodName = "/tree.TreeService/AddByPath" + TreeService_Remove_FullMethodName = "/tree.TreeService/Remove" + TreeService_Move_FullMethodName = "/tree.TreeService/Move" + TreeService_GetNodeByPath_FullMethodName = "/tree.TreeService/GetNodeByPath" + TreeService_GetSubTree_FullMethodName = "/tree.TreeService/GetSubTree" + TreeService_TreeList_FullMethodName = "/tree.TreeService/TreeList" + TreeService_Apply_FullMethodName = "/tree.TreeService/Apply" + TreeService_GetOpLog_FullMethodName = "/tree.TreeService/GetOpLog" + TreeService_Healthcheck_FullMethodName = "/tree.TreeService/Healthcheck" +) + // TreeServiceClient is the client API for TreeService service. // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. @@ -55,7 +71,7 @@ func NewTreeServiceClient(cc grpc.ClientConnInterface) TreeServiceClient { func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) { out := new(AddResponse) - err := c.cc.Invoke(ctx, "/tree.TreeService/Add", in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -64,7 +80,7 @@ func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grp func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, opts ...grpc.CallOption) (*AddByPathResponse, error) { out := new(AddByPathResponse) - err := c.cc.Invoke(ctx, "/tree.TreeService/AddByPath", in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -73,7 +89,7 @@ func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts ...grpc.CallOption) (*RemoveResponse, error) { out := new(RemoveResponse) - err := c.cc.Invoke(ctx, "/tree.TreeService/Remove", in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -82,7 +98,7 @@ func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...grpc.CallOption) (*MoveResponse, error) { out := new(MoveResponse) - err := c.cc.Invoke(ctx, "/tree.TreeService/Move", in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -91,7 +107,7 @@ func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...g func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPathRequest, opts ...grpc.CallOption) (*GetNodeByPathResponse, error) { out := new(GetNodeByPathResponse) - err := c.cc.Invoke(ctx, "/tree.TreeService/GetNodeByPath", in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -99,7 +115,7 @@ func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPath } func (c *treeServiceClient) GetSubTree(ctx context.Context, in *GetSubTreeRequest, opts ...grpc.CallOption) (TreeService_GetSubTreeClient, error) { - stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], "/tree.TreeService/GetSubTree", opts...) + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, opts...) if err != nil { return nil, err } @@ -132,7 +148,7 @@ func (x *treeServiceGetSubTreeClient) Recv() (*GetSubTreeResponse, error) { func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, opts ...grpc.CallOption) (*TreeListResponse, error) { out := new(TreeListResponse) - err := c.cc.Invoke(ctx, "/tree.TreeService/TreeList", in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -141,7 +157,7 @@ func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, o func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts ...grpc.CallOption) (*ApplyResponse, error) { out := new(ApplyResponse) - err := c.cc.Invoke(ctx, "/tree.TreeService/Apply", in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -149,7 +165,7 @@ func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts .. } func (c *treeServiceClient) GetOpLog(ctx context.Context, in *GetOpLogRequest, opts ...grpc.CallOption) (TreeService_GetOpLogClient, error) { - stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], "/tree.TreeService/GetOpLog", opts...) + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, opts...) if err != nil { return nil, err } @@ -182,7 +198,7 @@ func (x *treeServiceGetOpLogClient) Recv() (*GetOpLogResponse, error) { func (c *treeServiceClient) Healthcheck(ctx context.Context, in *HealthcheckRequest, opts ...grpc.CallOption) (*HealthcheckResponse, error) { out := new(HealthcheckResponse) - err := c.cc.Invoke(ctx, "/tree.TreeService/Healthcheck", in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -272,7 +288,7 @@ func _TreeService_Add_Handler(srv interface{}, ctx context.Context, dec func(int } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tree.TreeService/Add", + FullMethod: TreeService_Add_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Add(ctx, req.(*AddRequest)) @@ -290,7 +306,7 @@ func _TreeService_AddByPath_Handler(srv interface{}, ctx context.Context, dec fu } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tree.TreeService/AddByPath", + FullMethod: TreeService_AddByPath_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).AddByPath(ctx, req.(*AddByPathRequest)) @@ -308,7 +324,7 @@ func _TreeService_Remove_Handler(srv interface{}, ctx context.Context, dec func( } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tree.TreeService/Remove", + FullMethod: TreeService_Remove_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Remove(ctx, req.(*RemoveRequest)) @@ -326,7 +342,7 @@ func _TreeService_Move_Handler(srv interface{}, ctx context.Context, dec func(in } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tree.TreeService/Move", + FullMethod: TreeService_Move_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Move(ctx, req.(*MoveRequest)) @@ -344,7 +360,7 @@ func _TreeService_GetNodeByPath_Handler(srv interface{}, ctx context.Context, de } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tree.TreeService/GetNodeByPath", + FullMethod: TreeService_GetNodeByPath_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).GetNodeByPath(ctx, req.(*GetNodeByPathRequest)) @@ -383,7 +399,7 @@ func _TreeService_TreeList_Handler(srv interface{}, ctx context.Context, dec fun } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tree.TreeService/TreeList", + FullMethod: TreeService_TreeList_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).TreeList(ctx, req.(*TreeListRequest)) @@ -401,7 +417,7 @@ func _TreeService_Apply_Handler(srv interface{}, ctx context.Context, dec func(i } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tree.TreeService/Apply", + FullMethod: TreeService_Apply_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Apply(ctx, req.(*ApplyRequest)) @@ -440,7 +456,7 @@ func _TreeService_Healthcheck_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/tree.TreeService/Healthcheck", + FullMethod: TreeService_Healthcheck_FullMethodName, } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(TreeServiceServer).Healthcheck(ctx, req.(*HealthcheckRequest)) diff --git a/pkg/services/tree/types.pb.go b/pkg/services/tree/types.pb.go index f6b19c20ff..e44ac55666 100644 --- a/pkg/services/tree/types.pb.go +++ b/pkg/services/tree/types.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 +// protoc-gen-go v1.32.0 // protoc v4.25.0 // source: pkg/services/tree/types.proto From 9916598dfb8ef534bf8f0c4124f59491f2f4f578 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 26 Jan 2024 17:10:26 +0300 Subject: [PATCH 0303/1413] [#922] control: Extend api with `ListOverrideDefinedTargets` Signed-off-by: Anton Nikiforov --- pkg/services/control/rpc.go | 48 +- pkg/services/control/server/policy_engine.go | 54 + pkg/services/control/service.pb.go | 1197 +++++++++++------- pkg/services/control/service.proto | 29 +- pkg/services/control/service_frostfs.pb.go | 176 +++ pkg/services/control/service_grpc.pb.go | 73 +- 6 files changed, 1093 insertions(+), 484 deletions(-) diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 3fd4d4ae95..24b20f873e 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -8,23 +8,24 @@ import ( const serviceName = "control.ControlService" const ( - rpcHealthCheck = "HealthCheck" - rpcSetNetmapStatus = "SetNetmapStatus" - rpcDropObjects = "DropObjects" - rpcListShards = "ListShards" - rpcSetShardMode = "SetShardMode" - rpcSynchronizeTree = "SynchronizeTree" - rpcEvacuateShard = "EvacuateShard" - rpcStartShardEvacuation = "StartShardEvacuation" - rpcGetShardEvacuationStatus = "GetShardEvacuationStatus" - rpcStopShardEvacuation = "StopShardEvacuation" - rpcFlushCache = "FlushCache" - rpcDoctor = "Doctor" - rpcAddChainLocalOverride = "AddChainLocalOverride" - rpcGetChainLocalOverride = "GetChainLocalOverride" - rpcListChainLocalOverrides = "ListChainLocalOverrides" - rpcRemoveChainLocalOverride = "RemoveChainLocalOverride" - rpcSealWriteCache = "SealWriteCache" + rpcHealthCheck = "HealthCheck" + rpcSetNetmapStatus = "SetNetmapStatus" + rpcDropObjects = "DropObjects" + rpcListShards = "ListShards" + rpcSetShardMode = "SetShardMode" + rpcSynchronizeTree = "SynchronizeTree" + rpcEvacuateShard = "EvacuateShard" + rpcStartShardEvacuation = "StartShardEvacuation" + rpcGetShardEvacuationStatus = "GetShardEvacuationStatus" + rpcStopShardEvacuation = "StopShardEvacuation" + rpcFlushCache = "FlushCache" + rpcDoctor = "Doctor" + rpcAddChainLocalOverride = "AddChainLocalOverride" + rpcGetChainLocalOverride = "GetChainLocalOverride" + rpcListChainLocalOverrides = "ListChainLocalOverrides" + rpcRemoveChainLocalOverride = "RemoveChainLocalOverride" + rpcSealWriteCache = "SealWriteCache" + rpcListTargetsLocalOverrides = "ListTargetsLocalOverrides" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -240,6 +241,19 @@ func ListChainLocalOverrides(cli *client.Client, req *ListChainLocalOverridesReq return wResp.message, nil } +// ListTargetsLocalOverrides executes ControlService.ListTargetsLocalOverrides RPC. +func ListTargetsLocalOverrides(cli *client.Client, req *ListTargetsLocalOverridesRequest, opts ...client.CallOption) (*ListTargetsLocalOverridesResponse, error) { + wResp := newResponseWrapper[ListTargetsLocalOverridesResponse]() + wReq := &requestWrapper{m: req} + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcListTargetsLocalOverrides), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.message, nil +} + // RemoveChainLocalOverride executes ControlService.RemoveChainLocalOverride RPC. func GetChainLocalOverride(cli *client.Client, req *GetChainLocalOverrideRequest, opts ...client.CallOption) (*GetChainLocalOverrideResponse, error) { wResp := newResponseWrapper[GetChainLocalOverrideResponse]() diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index bd7f35f46f..079b605ac5 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -25,6 +25,29 @@ func apeTarget(chainTarget *control.ChainTarget) (engine.Target, error) { fmt.Errorf("target type is not supported: %s", chainTarget.GetType().String()).Error()) } +func controlTarget(chainTarget *engine.Target) (control.ChainTarget, error) { + switch chainTarget.Type { + case engine.Container: + return control.ChainTarget{ + Name: chainTarget.Name, + Type: control.ChainTarget_CONTAINER, + }, nil + case engine.Namespace: + // If namespace is empty, we take it for root namespace. + nm := chainTarget.Name + if nm == "root" { + nm = "" + } + return control.ChainTarget{ + Name: nm, + Type: control.ChainTarget_NAMESPACE, + }, nil + default: + } + return control.ChainTarget{}, status.Error(codes.InvalidArgument, + fmt.Errorf("target type is not supported: %c", chainTarget.Type).Error()) +} + func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainLocalOverrideRequest) (*control.AddChainLocalOverrideResponse, error) { if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) @@ -157,6 +180,37 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return resp, nil } +func (s *Server) ListTargetsLocalOverrides(_ context.Context, req *control.ListTargetsLocalOverridesRequest) (*control.ListTargetsLocalOverridesResponse, error) { + if err := s.isValidRequest(req); err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + apeChainName := apechain.Name(req.GetBody().GetChainName()) + apeTargets, err := s.localOverrideStorage.LocalStorage().ListOverrideDefinedTargets(apeChainName) + if err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) + } + targets := make([]*control.ChainTarget, 0, len(apeTargets)) + for i := range apeTargets { + target, err := controlTarget(&apeTargets[i]) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + targets = append(targets, &target) + } + + resp := &control.ListTargetsLocalOverridesResponse{ + Body: &control.ListTargetsLocalOverridesResponse_Body{ + Targets: targets, + }, + } + err = SignMessage(s.key, resp) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return resp, nil +} + func getCodeByLocalStorageErr(err error) codes.Code { if errors.Is(err, engine.ErrChainNotFound) || errors.Is(err, engine.ErrChainNameNotFound) { return codes.NotFound diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index f6b9ef6087..e0c6e0622a 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -1774,6 +1774,118 @@ func (x *ListChainLocalOverridesResponse) GetSignature() *Signature { return nil } +// ListTargetsLocalOverrides request. +type ListTargetsLocalOverridesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *ListTargetsLocalOverridesRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *ListTargetsLocalOverridesRequest) Reset() { + *x = ListTargetsLocalOverridesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListTargetsLocalOverridesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTargetsLocalOverridesRequest) ProtoMessage() {} + +func (x *ListTargetsLocalOverridesRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListTargetsLocalOverridesRequest.ProtoReflect.Descriptor instead. +func (*ListTargetsLocalOverridesRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30} +} + +func (x *ListTargetsLocalOverridesRequest) GetBody() *ListTargetsLocalOverridesRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ListTargetsLocalOverridesRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +// ListTargetsLocalOverrides response. +type ListTargetsLocalOverridesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *ListTargetsLocalOverridesResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *ListTargetsLocalOverridesResponse) Reset() { + *x = ListTargetsLocalOverridesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListTargetsLocalOverridesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTargetsLocalOverridesResponse) ProtoMessage() {} + +func (x *ListTargetsLocalOverridesResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListTargetsLocalOverridesResponse.ProtoReflect.Descriptor instead. +func (*ListTargetsLocalOverridesResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31} +} + +func (x *ListTargetsLocalOverridesResponse) GetBody() *ListTargetsLocalOverridesResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ListTargetsLocalOverridesResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + type RemoveChainLocalOverrideRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1786,7 +1898,7 @@ type RemoveChainLocalOverrideRequest struct { func (x *RemoveChainLocalOverrideRequest) Reset() { *x = RemoveChainLocalOverrideRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[30] + mi := &file_pkg_services_control_service_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1799,7 +1911,7 @@ func (x *RemoveChainLocalOverrideRequest) String() string { func (*RemoveChainLocalOverrideRequest) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[30] + mi := &file_pkg_services_control_service_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1812,7 +1924,7 @@ func (x *RemoveChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveChainLocalOverrideRequest.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32} } func (x *RemoveChainLocalOverrideRequest) GetBody() *RemoveChainLocalOverrideRequest_Body { @@ -1841,7 +1953,7 @@ type RemoveChainLocalOverrideResponse struct { func (x *RemoveChainLocalOverrideResponse) Reset() { *x = RemoveChainLocalOverrideResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[31] + mi := &file_pkg_services_control_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1854,7 +1966,7 @@ func (x *RemoveChainLocalOverrideResponse) String() string { func (*RemoveChainLocalOverrideResponse) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[31] + mi := &file_pkg_services_control_service_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1867,7 +1979,7 @@ func (x *RemoveChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveChainLocalOverrideResponse.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33} } func (x *RemoveChainLocalOverrideResponse) GetBody() *RemoveChainLocalOverrideResponse_Body { @@ -1896,7 +2008,7 @@ type SealWriteCacheRequest struct { func (x *SealWriteCacheRequest) Reset() { *x = SealWriteCacheRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1909,7 +2021,7 @@ func (x *SealWriteCacheRequest) String() string { func (*SealWriteCacheRequest) ProtoMessage() {} func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1922,7 +2034,7 @@ func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheRequest.ProtoReflect.Descriptor instead. func (*SealWriteCacheRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34} } func (x *SealWriteCacheRequest) GetBody() *SealWriteCacheRequest_Body { @@ -1951,7 +2063,7 @@ type SealWriteCacheResponse struct { func (x *SealWriteCacheResponse) Reset() { *x = SealWriteCacheResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1964,7 +2076,7 @@ func (x *SealWriteCacheResponse) String() string { func (*SealWriteCacheResponse) ProtoMessage() {} func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1977,7 +2089,7 @@ func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheResponse.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35} } func (x *SealWriteCacheResponse) GetBody() *SealWriteCacheResponse_Body { @@ -2004,7 +2116,7 @@ type HealthCheckRequest_Body struct { func (x *HealthCheckRequest_Body) Reset() { *x = HealthCheckRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2017,7 +2129,7 @@ func (x *HealthCheckRequest_Body) String() string { func (*HealthCheckRequest_Body) ProtoMessage() {} func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2048,7 +2160,7 @@ type HealthCheckResponse_Body struct { func (x *HealthCheckResponse_Body) Reset() { *x = HealthCheckResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2061,7 +2173,7 @@ func (x *HealthCheckResponse_Body) String() string { func (*HealthCheckResponse_Body) ProtoMessage() {} func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2112,7 +2224,7 @@ type SetNetmapStatusRequest_Body struct { func (x *SetNetmapStatusRequest_Body) Reset() { *x = SetNetmapStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2125,7 +2237,7 @@ func (x *SetNetmapStatusRequest_Body) String() string { func (*SetNetmapStatusRequest_Body) ProtoMessage() {} func (x *SetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2165,7 +2277,7 @@ type SetNetmapStatusResponse_Body struct { func (x *SetNetmapStatusResponse_Body) Reset() { *x = SetNetmapStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2178,7 +2290,7 @@ func (x *SetNetmapStatusResponse_Body) String() string { func (*SetNetmapStatusResponse_Body) ProtoMessage() {} func (x *SetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2208,7 +2320,7 @@ type DropObjectsRequest_Body struct { func (x *DropObjectsRequest_Body) Reset() { *x = DropObjectsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2221,7 +2333,7 @@ func (x *DropObjectsRequest_Body) String() string { func (*DropObjectsRequest_Body) ProtoMessage() {} func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2254,7 +2366,7 @@ type DropObjectsResponse_Body struct { func (x *DropObjectsResponse_Body) Reset() { *x = DropObjectsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2267,7 +2379,7 @@ func (x *DropObjectsResponse_Body) String() string { func (*DropObjectsResponse_Body) ProtoMessage() {} func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2293,7 +2405,7 @@ type ListShardsRequest_Body struct { func (x *ListShardsRequest_Body) Reset() { *x = ListShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2306,7 +2418,7 @@ func (x *ListShardsRequest_Body) String() string { func (*ListShardsRequest_Body) ProtoMessage() {} func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2335,7 +2447,7 @@ type ListShardsResponse_Body struct { func (x *ListShardsResponse_Body) Reset() { *x = ListShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2348,7 +2460,7 @@ func (x *ListShardsResponse_Body) String() string { func (*ListShardsResponse_Body) ProtoMessage() {} func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2388,7 +2500,7 @@ type SetShardModeRequest_Body struct { func (x *SetShardModeRequest_Body) Reset() { *x = SetShardModeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2401,7 +2513,7 @@ func (x *SetShardModeRequest_Body) String() string { func (*SetShardModeRequest_Body) ProtoMessage() {} func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2448,7 +2560,7 @@ type SetShardModeResponse_Body struct { func (x *SetShardModeResponse_Body) Reset() { *x = SetShardModeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2461,7 +2573,7 @@ func (x *SetShardModeResponse_Body) String() string { func (*SetShardModeResponse_Body) ProtoMessage() {} func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2492,7 +2604,7 @@ type SynchronizeTreeRequest_Body struct { func (x *SynchronizeTreeRequest_Body) Reset() { *x = SynchronizeTreeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2505,7 +2617,7 @@ func (x *SynchronizeTreeRequest_Body) String() string { func (*SynchronizeTreeRequest_Body) ProtoMessage() {} func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2552,7 +2664,7 @@ type SynchronizeTreeResponse_Body struct { func (x *SynchronizeTreeResponse_Body) Reset() { *x = SynchronizeTreeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2565,7 +2677,7 @@ func (x *SynchronizeTreeResponse_Body) String() string { func (*SynchronizeTreeResponse_Body) ProtoMessage() {} func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2596,7 +2708,7 @@ type EvacuateShardRequest_Body struct { func (x *EvacuateShardRequest_Body) Reset() { *x = EvacuateShardRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2609,7 +2721,7 @@ func (x *EvacuateShardRequest_Body) String() string { func (*EvacuateShardRequest_Body) ProtoMessage() {} func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2651,7 +2763,7 @@ type EvacuateShardResponse_Body struct { func (x *EvacuateShardResponse_Body) Reset() { *x = EvacuateShardResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2664,7 +2776,7 @@ func (x *EvacuateShardResponse_Body) String() string { func (*EvacuateShardResponse_Body) ProtoMessage() {} func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2702,7 +2814,7 @@ type FlushCacheRequest_Body struct { func (x *FlushCacheRequest_Body) Reset() { *x = FlushCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2715,7 +2827,7 @@ func (x *FlushCacheRequest_Body) String() string { func (*FlushCacheRequest_Body) ProtoMessage() {} func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2755,7 +2867,7 @@ type FlushCacheResponse_Body struct { func (x *FlushCacheResponse_Body) Reset() { *x = FlushCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2768,7 +2880,7 @@ func (x *FlushCacheResponse_Body) String() string { func (*FlushCacheResponse_Body) ProtoMessage() {} func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2799,7 +2911,7 @@ type DoctorRequest_Body struct { func (x *DoctorRequest_Body) Reset() { *x = DoctorRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2812,7 +2924,7 @@ func (x *DoctorRequest_Body) String() string { func (*DoctorRequest_Body) ProtoMessage() {} func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2852,7 +2964,7 @@ type DoctorResponse_Body struct { func (x *DoctorResponse_Body) Reset() { *x = DoctorResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2865,7 +2977,7 @@ func (x *DoctorResponse_Body) String() string { func (*DoctorResponse_Body) ProtoMessage() {} func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2896,7 +3008,7 @@ type StartShardEvacuationRequest_Body struct { func (x *StartShardEvacuationRequest_Body) Reset() { *x = StartShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2909,7 +3021,7 @@ func (x *StartShardEvacuationRequest_Body) String() string { func (*StartShardEvacuationRequest_Body) ProtoMessage() {} func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2949,7 +3061,7 @@ type StartShardEvacuationResponse_Body struct { func (x *StartShardEvacuationResponse_Body) Reset() { *x = StartShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2962,7 +3074,7 @@ func (x *StartShardEvacuationResponse_Body) String() string { func (*StartShardEvacuationResponse_Body) ProtoMessage() {} func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2988,7 +3100,7 @@ type GetShardEvacuationStatusRequest_Body struct { func (x *GetShardEvacuationStatusRequest_Body) Reset() { *x = GetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3001,7 +3113,7 @@ func (x *GetShardEvacuationStatusRequest_Body) String() string { func (*GetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3046,7 +3158,7 @@ type GetShardEvacuationStatusResponse_Body struct { func (x *GetShardEvacuationStatusResponse_Body) Reset() { *x = GetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3059,7 +3171,7 @@ func (x *GetShardEvacuationStatusResponse_Body) String() string { func (*GetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3150,7 +3262,7 @@ type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) Reset() { *x = GetShardEvacuationStatusResponse_Body_UnixTimestamp{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3163,7 +3275,7 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) String() string { func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3198,7 +3310,7 @@ type GetShardEvacuationStatusResponse_Body_Duration struct { func (x *GetShardEvacuationStatusResponse_Body_Duration) Reset() { *x = GetShardEvacuationStatusResponse_Body_Duration{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3211,7 +3323,7 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) String() string { func (*GetShardEvacuationStatusResponse_Body_Duration) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3244,7 +3356,7 @@ type StopShardEvacuationRequest_Body struct { func (x *StopShardEvacuationRequest_Body) Reset() { *x = StopShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3257,7 +3369,7 @@ func (x *StopShardEvacuationRequest_Body) String() string { func (*StopShardEvacuationRequest_Body) ProtoMessage() {} func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3283,7 +3395,7 @@ type StopShardEvacuationResponse_Body struct { func (x *StopShardEvacuationResponse_Body) Reset() { *x = StopShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3296,7 +3408,7 @@ func (x *StopShardEvacuationResponse_Body) String() string { func (*StopShardEvacuationResponse_Body) ProtoMessage() {} func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3328,7 +3440,7 @@ type AddChainLocalOverrideRequest_Body struct { func (x *AddChainLocalOverrideRequest_Body) Reset() { *x = AddChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3341,7 +3453,7 @@ func (x *AddChainLocalOverrideRequest_Body) String() string { func (*AddChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3385,7 +3497,7 @@ type AddChainLocalOverrideResponse_Body struct { func (x *AddChainLocalOverrideResponse_Body) Reset() { *x = AddChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3398,7 +3510,7 @@ func (x *AddChainLocalOverrideResponse_Body) String() string { func (*AddChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3435,7 +3547,7 @@ type GetChainLocalOverrideRequest_Body struct { func (x *GetChainLocalOverrideRequest_Body) Reset() { *x = GetChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3448,7 +3560,7 @@ func (x *GetChainLocalOverrideRequest_Body) String() string { func (*GetChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3490,7 +3602,7 @@ type GetChainLocalOverrideResponse_Body struct { func (x *GetChainLocalOverrideResponse_Body) Reset() { *x = GetChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3503,7 +3615,7 @@ func (x *GetChainLocalOverrideResponse_Body) String() string { func (*GetChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3538,7 +3650,7 @@ type ListChainLocalOverridesRequest_Body struct { func (x *ListChainLocalOverridesRequest_Body) Reset() { *x = ListChainLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3551,7 +3663,7 @@ func (x *ListChainLocalOverridesRequest_Body) String() string { func (*ListChainLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3586,7 +3698,7 @@ type ListChainLocalOverridesResponse_Body struct { func (x *ListChainLocalOverridesResponse_Body) Reset() { *x = ListChainLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3599,7 +3711,7 @@ func (x *ListChainLocalOverridesResponse_Body) String() string { func (*ListChainLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3622,6 +3734,102 @@ func (x *ListChainLocalOverridesResponse_Body) GetChains() [][]byte { return nil } +type ListTargetsLocalOverridesRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Target for which the overrides are applied. + ChainName string `protobuf:"bytes,1,opt,name=chainName,proto3" json:"chainName,omitempty"` +} + +func (x *ListTargetsLocalOverridesRequest_Body) Reset() { + *x = ListTargetsLocalOverridesRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[68] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListTargetsLocalOverridesRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTargetsLocalOverridesRequest_Body) ProtoMessage() {} + +func (x *ListTargetsLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[68] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListTargetsLocalOverridesRequest_Body.ProtoReflect.Descriptor instead. +func (*ListTargetsLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} +} + +func (x *ListTargetsLocalOverridesRequest_Body) GetChainName() string { + if x != nil { + return x.ChainName + } + return "" +} + +type ListTargetsLocalOverridesResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The list of chain targets. + Targets []*ChainTarget `protobuf:"bytes,1,rep,name=targets,proto3" json:"targets,omitempty"` +} + +func (x *ListTargetsLocalOverridesResponse_Body) Reset() { + *x = ListTargetsLocalOverridesResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[69] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListTargetsLocalOverridesResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListTargetsLocalOverridesResponse_Body) ProtoMessage() {} + +func (x *ListTargetsLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[69] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListTargetsLocalOverridesResponse_Body.ProtoReflect.Descriptor instead. +func (*ListTargetsLocalOverridesResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31, 0} +} + +func (x *ListTargetsLocalOverridesResponse_Body) GetTargets() []*ChainTarget { + if x != nil { + return x.Targets + } + return nil +} + type RemoveChainLocalOverrideRequest_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3636,7 +3844,7 @@ type RemoveChainLocalOverrideRequest_Body struct { func (x *RemoveChainLocalOverrideRequest_Body) Reset() { *x = RemoveChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3649,7 +3857,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) String() string { func (*RemoveChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3662,7 +3870,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Messa // Deprecated: Use RemoveChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32, 0} } func (x *RemoveChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { @@ -3690,7 +3898,7 @@ type RemoveChainLocalOverrideResponse_Body struct { func (x *RemoveChainLocalOverrideResponse_Body) Reset() { *x = RemoveChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3703,7 +3911,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) String() string { func (*RemoveChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3716,7 +3924,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Mess // Deprecated: Use RemoveChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} } func (x *RemoveChainLocalOverrideResponse_Body) GetRemoved() bool { @@ -3741,7 +3949,7 @@ type SealWriteCacheRequest_Body struct { func (x *SealWriteCacheRequest_Body) Reset() { *x = SealWriteCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3754,7 +3962,7 @@ func (x *SealWriteCacheRequest_Body) String() string { func (*SealWriteCacheRequest_Body) ProtoMessage() {} func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3767,7 +3975,7 @@ func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheRequest_Body.ProtoReflect.Descriptor instead. func (*SealWriteCacheRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34, 0} } func (x *SealWriteCacheRequest_Body) GetShard_ID() [][]byte { @@ -3795,7 +4003,7 @@ type SealWriteCacheResponse_Body struct { func (x *SealWriteCacheResponse_Body) Reset() { *x = SealWriteCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3808,7 +4016,7 @@ func (x *SealWriteCacheResponse_Body) String() string { func (*SealWriteCacheResponse_Body) ProtoMessage() {} func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3821,7 +4029,7 @@ func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheResponse_Body.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0} } func (x *SealWriteCacheResponse_Body) GetResults() []*SealWriteCacheResponse_Body_Status { @@ -3844,7 +4052,7 @@ type SealWriteCacheResponse_Body_Status struct { func (x *SealWriteCacheResponse_Body_Status) Reset() { *x = SealWriteCacheResponse_Body_Status{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3857,7 +4065,7 @@ func (x *SealWriteCacheResponse_Body_Status) String() string { func (*SealWriteCacheResponse_Body_Status) ProtoMessage() {} func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3870,7 +4078,7 @@ func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message // Deprecated: Use SealWriteCacheResponse_Body_Status.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse_Body_Status) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0, 0} } func (x *SealWriteCacheResponse_Body_Status) GetShard_ID() []byte { @@ -4273,165 +4481,197 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x24, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x1a, 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2e, 0x0a, 0x07, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xe7, 0x01, 0x0a, + 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, + 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, - 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0xca, 0x01, - 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, - 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, - 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, + 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x64, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xf0, 0x0b, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, - 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, - 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, - 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, - 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, - 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, + 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, + 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, + 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xe4, 0x0c, 0x0a, + 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, + 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, + 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, + 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, - 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, - 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, + 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, + 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, + 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, - 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, - 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, - 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, + 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, + 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, + 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, + 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, + 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, + 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, + 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4447,7 +4687,7 @@ func file_pkg_services_control_service_proto_rawDescGZIP() []byte { } var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 71) +var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 75) var file_pkg_services_control_service_proto_goTypes = []interface{}{ (GetShardEvacuationStatusResponse_Body_Status)(0), // 0: control.GetShardEvacuationStatusResponse.Body.Status (*HealthCheckRequest)(nil), // 1: control.HealthCheckRequest @@ -4480,175 +4720,186 @@ var file_pkg_services_control_service_proto_goTypes = []interface{}{ (*GetChainLocalOverrideResponse)(nil), // 28: control.GetChainLocalOverrideResponse (*ListChainLocalOverridesRequest)(nil), // 29: control.ListChainLocalOverridesRequest (*ListChainLocalOverridesResponse)(nil), // 30: control.ListChainLocalOverridesResponse - (*RemoveChainLocalOverrideRequest)(nil), // 31: control.RemoveChainLocalOverrideRequest - (*RemoveChainLocalOverrideResponse)(nil), // 32: control.RemoveChainLocalOverrideResponse - (*SealWriteCacheRequest)(nil), // 33: control.SealWriteCacheRequest - (*SealWriteCacheResponse)(nil), // 34: control.SealWriteCacheResponse - (*HealthCheckRequest_Body)(nil), // 35: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 36: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 37: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 38: control.SetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 39: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 40: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 41: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 42: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 43: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 44: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 45: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 46: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 47: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 48: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 49: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 50: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 51: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 52: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 53: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 54: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 55: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 56: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 57: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 58: control.GetShardEvacuationStatusResponse.Body.Duration - (*StopShardEvacuationRequest_Body)(nil), // 59: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 60: control.StopShardEvacuationResponse.Body - (*AddChainLocalOverrideRequest_Body)(nil), // 61: control.AddChainLocalOverrideRequest.Body - (*AddChainLocalOverrideResponse_Body)(nil), // 62: control.AddChainLocalOverrideResponse.Body - (*GetChainLocalOverrideRequest_Body)(nil), // 63: control.GetChainLocalOverrideRequest.Body - (*GetChainLocalOverrideResponse_Body)(nil), // 64: control.GetChainLocalOverrideResponse.Body - (*ListChainLocalOverridesRequest_Body)(nil), // 65: control.ListChainLocalOverridesRequest.Body - (*ListChainLocalOverridesResponse_Body)(nil), // 66: control.ListChainLocalOverridesResponse.Body - (*RemoveChainLocalOverrideRequest_Body)(nil), // 67: control.RemoveChainLocalOverrideRequest.Body - (*RemoveChainLocalOverrideResponse_Body)(nil), // 68: control.RemoveChainLocalOverrideResponse.Body - (*SealWriteCacheRequest_Body)(nil), // 69: control.SealWriteCacheRequest.Body - (*SealWriteCacheResponse_Body)(nil), // 70: control.SealWriteCacheResponse.Body - (*SealWriteCacheResponse_Body_Status)(nil), // 71: control.SealWriteCacheResponse.Body.Status - (*Signature)(nil), // 72: control.Signature - (NetmapStatus)(0), // 73: control.NetmapStatus - (HealthStatus)(0), // 74: control.HealthStatus - (*ShardInfo)(nil), // 75: control.ShardInfo - (ShardMode)(0), // 76: control.ShardMode - (*ChainTarget)(nil), // 77: control.ChainTarget + (*ListTargetsLocalOverridesRequest)(nil), // 31: control.ListTargetsLocalOverridesRequest + (*ListTargetsLocalOverridesResponse)(nil), // 32: control.ListTargetsLocalOverridesResponse + (*RemoveChainLocalOverrideRequest)(nil), // 33: control.RemoveChainLocalOverrideRequest + (*RemoveChainLocalOverrideResponse)(nil), // 34: control.RemoveChainLocalOverrideResponse + (*SealWriteCacheRequest)(nil), // 35: control.SealWriteCacheRequest + (*SealWriteCacheResponse)(nil), // 36: control.SealWriteCacheResponse + (*HealthCheckRequest_Body)(nil), // 37: control.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 38: control.HealthCheckResponse.Body + (*SetNetmapStatusRequest_Body)(nil), // 39: control.SetNetmapStatusRequest.Body + (*SetNetmapStatusResponse_Body)(nil), // 40: control.SetNetmapStatusResponse.Body + (*DropObjectsRequest_Body)(nil), // 41: control.DropObjectsRequest.Body + (*DropObjectsResponse_Body)(nil), // 42: control.DropObjectsResponse.Body + (*ListShardsRequest_Body)(nil), // 43: control.ListShardsRequest.Body + (*ListShardsResponse_Body)(nil), // 44: control.ListShardsResponse.Body + (*SetShardModeRequest_Body)(nil), // 45: control.SetShardModeRequest.Body + (*SetShardModeResponse_Body)(nil), // 46: control.SetShardModeResponse.Body + (*SynchronizeTreeRequest_Body)(nil), // 47: control.SynchronizeTreeRequest.Body + (*SynchronizeTreeResponse_Body)(nil), // 48: control.SynchronizeTreeResponse.Body + (*EvacuateShardRequest_Body)(nil), // 49: control.EvacuateShardRequest.Body + (*EvacuateShardResponse_Body)(nil), // 50: control.EvacuateShardResponse.Body + (*FlushCacheRequest_Body)(nil), // 51: control.FlushCacheRequest.Body + (*FlushCacheResponse_Body)(nil), // 52: control.FlushCacheResponse.Body + (*DoctorRequest_Body)(nil), // 53: control.DoctorRequest.Body + (*DoctorResponse_Body)(nil), // 54: control.DoctorResponse.Body + (*StartShardEvacuationRequest_Body)(nil), // 55: control.StartShardEvacuationRequest.Body + (*StartShardEvacuationResponse_Body)(nil), // 56: control.StartShardEvacuationResponse.Body + (*GetShardEvacuationStatusRequest_Body)(nil), // 57: control.GetShardEvacuationStatusRequest.Body + (*GetShardEvacuationStatusResponse_Body)(nil), // 58: control.GetShardEvacuationStatusResponse.Body + (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 59: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 60: control.GetShardEvacuationStatusResponse.Body.Duration + (*StopShardEvacuationRequest_Body)(nil), // 61: control.StopShardEvacuationRequest.Body + (*StopShardEvacuationResponse_Body)(nil), // 62: control.StopShardEvacuationResponse.Body + (*AddChainLocalOverrideRequest_Body)(nil), // 63: control.AddChainLocalOverrideRequest.Body + (*AddChainLocalOverrideResponse_Body)(nil), // 64: control.AddChainLocalOverrideResponse.Body + (*GetChainLocalOverrideRequest_Body)(nil), // 65: control.GetChainLocalOverrideRequest.Body + (*GetChainLocalOverrideResponse_Body)(nil), // 66: control.GetChainLocalOverrideResponse.Body + (*ListChainLocalOverridesRequest_Body)(nil), // 67: control.ListChainLocalOverridesRequest.Body + (*ListChainLocalOverridesResponse_Body)(nil), // 68: control.ListChainLocalOverridesResponse.Body + (*ListTargetsLocalOverridesRequest_Body)(nil), // 69: control.ListTargetsLocalOverridesRequest.Body + (*ListTargetsLocalOverridesResponse_Body)(nil), // 70: control.ListTargetsLocalOverridesResponse.Body + (*RemoveChainLocalOverrideRequest_Body)(nil), // 71: control.RemoveChainLocalOverrideRequest.Body + (*RemoveChainLocalOverrideResponse_Body)(nil), // 72: control.RemoveChainLocalOverrideResponse.Body + (*SealWriteCacheRequest_Body)(nil), // 73: control.SealWriteCacheRequest.Body + (*SealWriteCacheResponse_Body)(nil), // 74: control.SealWriteCacheResponse.Body + (*SealWriteCacheResponse_Body_Status)(nil), // 75: control.SealWriteCacheResponse.Body.Status + (*Signature)(nil), // 76: control.Signature + (NetmapStatus)(0), // 77: control.NetmapStatus + (HealthStatus)(0), // 78: control.HealthStatus + (*ShardInfo)(nil), // 79: control.ShardInfo + (ShardMode)(0), // 80: control.ShardMode + (*ChainTarget)(nil), // 81: control.ChainTarget } var file_pkg_services_control_service_proto_depIdxs = []int32{ - 35, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 72, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 36, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 72, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 37, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 72, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 38, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 72, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 39, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 72, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature - 40, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 72, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature - 41, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 72, // 13: control.ListShardsRequest.signature:type_name -> control.Signature - 42, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 72, // 15: control.ListShardsResponse.signature:type_name -> control.Signature - 43, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 72, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature - 44, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 72, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature - 45, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 72, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 46, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 72, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 47, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 72, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature - 48, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 72, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature - 49, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 72, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature - 50, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 72, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature - 51, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 72, // 33: control.DoctorRequest.signature:type_name -> control.Signature - 52, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 72, // 35: control.DoctorResponse.signature:type_name -> control.Signature - 53, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 72, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 54, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 72, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 55, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 72, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 56, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 72, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 59, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 72, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 60, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 72, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 61, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body - 72, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature - 62, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body - 72, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature - 63, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body - 72, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature - 64, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body - 72, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature - 65, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body - 72, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature - 66, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body - 72, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature - 67, // 60: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body - 72, // 61: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature - 68, // 62: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body - 72, // 63: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature - 69, // 64: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body - 72, // 65: control.SealWriteCacheRequest.signature:type_name -> control.Signature - 70, // 66: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body - 72, // 67: control.SealWriteCacheResponse.signature:type_name -> control.Signature - 73, // 68: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 74, // 69: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 73, // 70: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 75, // 71: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 76, // 72: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 0, // 73: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 58, // 74: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 57, // 75: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 77, // 76: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 77, // 77: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 77, // 78: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget - 77, // 79: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 71, // 80: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status - 1, // 81: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 3, // 82: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 5, // 83: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 7, // 84: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 9, // 85: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 11, // 86: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 13, // 87: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 19, // 88: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 21, // 89: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 23, // 90: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 15, // 91: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 17, // 92: control.ControlService.Doctor:input_type -> control.DoctorRequest - 25, // 93: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 27, // 94: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 29, // 95: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 31, // 96: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 33, // 97: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest - 2, // 98: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 4, // 99: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 6, // 100: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 8, // 101: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 10, // 102: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 12, // 103: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 14, // 104: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 20, // 105: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 22, // 106: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 24, // 107: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 16, // 108: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 18, // 109: control.ControlService.Doctor:output_type -> control.DoctorResponse - 26, // 110: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 28, // 111: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 30, // 112: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 32, // 113: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 34, // 114: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse - 98, // [98:115] is the sub-list for method output_type - 81, // [81:98] is the sub-list for method input_type - 81, // [81:81] is the sub-list for extension type_name - 81, // [81:81] is the sub-list for extension extendee - 0, // [0:81] is the sub-list for field type_name + 37, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body + 76, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature + 38, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body + 76, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature + 39, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body + 76, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature + 40, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body + 76, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature + 41, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body + 76, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature + 42, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body + 76, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature + 43, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body + 76, // 13: control.ListShardsRequest.signature:type_name -> control.Signature + 44, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body + 76, // 15: control.ListShardsResponse.signature:type_name -> control.Signature + 45, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body + 76, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature + 46, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body + 76, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature + 47, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body + 76, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature + 48, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body + 76, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature + 49, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body + 76, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature + 50, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body + 76, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature + 51, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body + 76, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature + 52, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body + 76, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature + 53, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body + 76, // 33: control.DoctorRequest.signature:type_name -> control.Signature + 54, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body + 76, // 35: control.DoctorResponse.signature:type_name -> control.Signature + 55, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body + 76, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature + 56, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body + 76, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature + 57, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body + 76, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 58, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body + 76, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 61, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body + 76, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature + 62, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body + 76, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature + 63, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body + 76, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature + 64, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body + 76, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature + 65, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body + 76, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature + 66, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body + 76, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature + 67, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body + 76, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature + 68, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body + 76, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature + 69, // 60: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body + 76, // 61: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature + 70, // 62: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body + 76, // 63: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature + 71, // 64: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body + 76, // 65: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature + 72, // 66: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body + 76, // 67: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature + 73, // 68: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body + 76, // 69: control.SealWriteCacheRequest.signature:type_name -> control.Signature + 74, // 70: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body + 76, // 71: control.SealWriteCacheResponse.signature:type_name -> control.Signature + 77, // 72: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus + 78, // 73: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus + 77, // 74: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus + 79, // 75: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo + 80, // 76: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode + 0, // 77: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status + 60, // 78: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration + 59, // 79: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + 81, // 80: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 81, // 81: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 81, // 82: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget + 81, // 83: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget + 81, // 84: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 75, // 85: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status + 1, // 86: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 3, // 87: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 5, // 88: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 7, // 89: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 9, // 90: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 11, // 91: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 13, // 92: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 19, // 93: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 21, // 94: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 23, // 95: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 15, // 96: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 17, // 97: control.ControlService.Doctor:input_type -> control.DoctorRequest + 25, // 98: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 27, // 99: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 29, // 100: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 33, // 101: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 31, // 102: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest + 35, // 103: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest + 2, // 104: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 4, // 105: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 6, // 106: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 8, // 107: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 10, // 108: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 12, // 109: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 14, // 110: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 20, // 111: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 22, // 112: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 24, // 113: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 16, // 114: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 18, // 115: control.ControlService.Doctor:output_type -> control.DoctorResponse + 26, // 116: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 28, // 117: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 30, // 118: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 34, // 119: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 32, // 120: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse + 36, // 121: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse + 104, // [104:122] is the sub-list for method output_type + 86, // [86:104] is the sub-list for method input_type + 86, // [86:86] is the sub-list for extension type_name + 86, // [86:86] is the sub-list for extension extendee + 0, // [0:86] is the sub-list for field type_name } func init() { file_pkg_services_control_service_proto_init() } @@ -5019,7 +5270,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest); i { + switch v := v.(*ListTargetsLocalOverridesRequest); i { case 0: return &v.state case 1: @@ -5031,7 +5282,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse); i { + switch v := v.(*ListTargetsLocalOverridesResponse); i { case 0: return &v.state case 1: @@ -5043,7 +5294,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest); i { + switch v := v.(*RemoveChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -5055,7 +5306,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse); i { + switch v := v.(*RemoveChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -5067,7 +5318,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { + switch v := v.(*SealWriteCacheRequest); i { case 0: return &v.state case 1: @@ -5079,7 +5330,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { + switch v := v.(*SealWriteCacheResponse); i { case 0: return &v.state case 1: @@ -5091,7 +5342,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest_Body); i { + switch v := v.(*HealthCheckRequest_Body); i { case 0: return &v.state case 1: @@ -5103,7 +5354,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse_Body); i { + switch v := v.(*HealthCheckResponse_Body); i { case 0: return &v.state case 1: @@ -5115,7 +5366,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest_Body); i { + switch v := v.(*SetNetmapStatusRequest_Body); i { case 0: return &v.state case 1: @@ -5127,7 +5378,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse_Body); i { + switch v := v.(*SetNetmapStatusResponse_Body); i { case 0: return &v.state case 1: @@ -5139,7 +5390,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest_Body); i { + switch v := v.(*DropObjectsRequest_Body); i { case 0: return &v.state case 1: @@ -5151,7 +5402,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse_Body); i { + switch v := v.(*DropObjectsResponse_Body); i { case 0: return &v.state case 1: @@ -5163,7 +5414,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest_Body); i { + switch v := v.(*ListShardsRequest_Body); i { case 0: return &v.state case 1: @@ -5175,7 +5426,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse_Body); i { + switch v := v.(*ListShardsResponse_Body); i { case 0: return &v.state case 1: @@ -5187,7 +5438,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest_Body); i { + switch v := v.(*SetShardModeRequest_Body); i { case 0: return &v.state case 1: @@ -5199,7 +5450,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse_Body); i { + switch v := v.(*SetShardModeResponse_Body); i { case 0: return &v.state case 1: @@ -5211,7 +5462,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest_Body); i { + switch v := v.(*SynchronizeTreeRequest_Body); i { case 0: return &v.state case 1: @@ -5223,7 +5474,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse_Body); i { + switch v := v.(*SynchronizeTreeResponse_Body); i { case 0: return &v.state case 1: @@ -5235,7 +5486,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest_Body); i { + switch v := v.(*EvacuateShardRequest_Body); i { case 0: return &v.state case 1: @@ -5247,7 +5498,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse_Body); i { + switch v := v.(*EvacuateShardResponse_Body); i { case 0: return &v.state case 1: @@ -5259,7 +5510,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest_Body); i { + switch v := v.(*FlushCacheRequest_Body); i { case 0: return &v.state case 1: @@ -5271,7 +5522,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse_Body); i { + switch v := v.(*FlushCacheResponse_Body); i { case 0: return &v.state case 1: @@ -5283,7 +5534,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest_Body); i { + switch v := v.(*DoctorRequest_Body); i { case 0: return &v.state case 1: @@ -5295,7 +5546,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse_Body); i { + switch v := v.(*DoctorResponse_Body); i { case 0: return &v.state case 1: @@ -5307,7 +5558,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest_Body); i { + switch v := v.(*StartShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -5319,7 +5570,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body); i { + switch v := v.(*StartShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -5331,7 +5582,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { + switch v := v.(*GetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -5343,7 +5594,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -5355,7 +5606,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { case 0: return &v.state case 1: @@ -5367,7 +5618,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { case 0: return &v.state case 1: @@ -5379,7 +5630,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest_Body); i { + switch v := v.(*StopShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -5391,7 +5642,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse_Body); i { + switch v := v.(*StopShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -5403,7 +5654,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest_Body); i { + switch v := v.(*AddChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -5415,7 +5666,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse_Body); i { + switch v := v.(*AddChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -5427,7 +5678,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest_Body); i { + switch v := v.(*GetChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -5439,7 +5690,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse_Body); i { + switch v := v.(*GetChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -5451,7 +5702,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + switch v := v.(*ListChainLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -5463,7 +5714,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { + switch v := v.(*ListChainLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -5475,7 +5726,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest_Body); i { + switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -5487,7 +5738,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body); i { + switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -5499,6 +5750,54 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SealWriteCacheResponse_Body_Status); i { case 0: return &v.state @@ -5517,7 +5816,7 @@ func file_pkg_services_control_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_service_proto_rawDesc, NumEnums: 1, - NumMessages: 71, + NumMessages: 75, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index b76645b61b..dc63a71886 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -57,6 +57,9 @@ service ControlService { // Remove local access policy engine overrides stored in the node by chaind id. rpc RemoveChainLocalOverride (RemoveChainLocalOverrideRequest) returns (RemoveChainLocalOverrideResponse); + // List targets of the local APE overrides stored in the node. + rpc ListTargetsLocalOverrides (ListTargetsLocalOverridesRequest) returns (ListTargetsLocalOverridesResponse); + // Flush objects from write-cache and move it to degraded read only mode. rpc SealWriteCache(SealWriteCacheRequest) returns (SealWriteCacheResponse); } @@ -505,6 +508,30 @@ message ListChainLocalOverridesResponse { Signature signature = 2; } +// ListTargetsLocalOverrides request. +message ListTargetsLocalOverridesRequest { + message Body { + // Target for which the overrides are applied. + string chainName = 1; + } + + Body body = 1; + + Signature signature = 2; +} + +// ListTargetsLocalOverrides response. +message ListTargetsLocalOverridesResponse { + message Body { + // The list of chain targets. + repeated ChainTarget targets = 1; + } + + Body body = 1; + + Signature signature = 2; +} + message RemoveChainLocalOverrideRequest { message Body { // Target for which the overrides are applied. @@ -556,4 +583,4 @@ message SealWriteCacheResponse { Body body = 1; Signature signature = 2; -} \ No newline at end of file +} diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 574ab13c4b..b72fc0f128 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2582,6 +2582,182 @@ func (x *ListChainLocalOverridesResponse) SetSignature(sig *Signature) { x.Signature = sig } +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListTargetsLocalOverridesRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.StringSize(1, x.ChainName) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ListTargetsLocalOverridesRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.StringMarshal(1, buf[offset:], x.ChainName) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListTargetsLocalOverridesRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ListTargetsLocalOverridesRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ListTargetsLocalOverridesRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ListTargetsLocalOverridesRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *ListTargetsLocalOverridesRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListTargetsLocalOverridesResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + for i := range x.Targets { + size += proto.NestedStructureSize(1, x.Targets[i]) + } + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ListTargetsLocalOverridesResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + for i := range x.Targets { + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Targets[i]) + } + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListTargetsLocalOverridesResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ListTargetsLocalOverridesResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ListTargetsLocalOverridesResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ListTargetsLocalOverridesResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *ListTargetsLocalOverridesResponse) SetSignature(sig *Signature) { + x.Signature = sig +} + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index e09f6750b6..89337323f9 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -19,23 +19,24 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - ControlService_HealthCheck_FullMethodName = "/control.ControlService/HealthCheck" - ControlService_SetNetmapStatus_FullMethodName = "/control.ControlService/SetNetmapStatus" - ControlService_DropObjects_FullMethodName = "/control.ControlService/DropObjects" - ControlService_ListShards_FullMethodName = "/control.ControlService/ListShards" - ControlService_SetShardMode_FullMethodName = "/control.ControlService/SetShardMode" - ControlService_SynchronizeTree_FullMethodName = "/control.ControlService/SynchronizeTree" - ControlService_EvacuateShard_FullMethodName = "/control.ControlService/EvacuateShard" - ControlService_StartShardEvacuation_FullMethodName = "/control.ControlService/StartShardEvacuation" - ControlService_GetShardEvacuationStatus_FullMethodName = "/control.ControlService/GetShardEvacuationStatus" - ControlService_StopShardEvacuation_FullMethodName = "/control.ControlService/StopShardEvacuation" - ControlService_FlushCache_FullMethodName = "/control.ControlService/FlushCache" - ControlService_Doctor_FullMethodName = "/control.ControlService/Doctor" - ControlService_AddChainLocalOverride_FullMethodName = "/control.ControlService/AddChainLocalOverride" - ControlService_GetChainLocalOverride_FullMethodName = "/control.ControlService/GetChainLocalOverride" - ControlService_ListChainLocalOverrides_FullMethodName = "/control.ControlService/ListChainLocalOverrides" - ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" - ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" + ControlService_HealthCheck_FullMethodName = "/control.ControlService/HealthCheck" + ControlService_SetNetmapStatus_FullMethodName = "/control.ControlService/SetNetmapStatus" + ControlService_DropObjects_FullMethodName = "/control.ControlService/DropObjects" + ControlService_ListShards_FullMethodName = "/control.ControlService/ListShards" + ControlService_SetShardMode_FullMethodName = "/control.ControlService/SetShardMode" + ControlService_SynchronizeTree_FullMethodName = "/control.ControlService/SynchronizeTree" + ControlService_EvacuateShard_FullMethodName = "/control.ControlService/EvacuateShard" + ControlService_StartShardEvacuation_FullMethodName = "/control.ControlService/StartShardEvacuation" + ControlService_GetShardEvacuationStatus_FullMethodName = "/control.ControlService/GetShardEvacuationStatus" + ControlService_StopShardEvacuation_FullMethodName = "/control.ControlService/StopShardEvacuation" + ControlService_FlushCache_FullMethodName = "/control.ControlService/FlushCache" + ControlService_Doctor_FullMethodName = "/control.ControlService/Doctor" + ControlService_AddChainLocalOverride_FullMethodName = "/control.ControlService/AddChainLocalOverride" + ControlService_GetChainLocalOverride_FullMethodName = "/control.ControlService/GetChainLocalOverride" + ControlService_ListChainLocalOverrides_FullMethodName = "/control.ControlService/ListChainLocalOverrides" + ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" + ControlService_ListTargetsLocalOverrides_FullMethodName = "/control.ControlService/ListTargetsLocalOverrides" + ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" ) // ControlServiceClient is the client API for ControlService service. @@ -75,6 +76,8 @@ type ControlServiceClient interface { ListChainLocalOverrides(ctx context.Context, in *ListChainLocalOverridesRequest, opts ...grpc.CallOption) (*ListChainLocalOverridesResponse, error) // Remove local access policy engine overrides stored in the node by chaind id. RemoveChainLocalOverride(ctx context.Context, in *RemoveChainLocalOverrideRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverrideResponse, error) + // List targets of the local APE overrides stored in the node. + ListTargetsLocalOverrides(ctx context.Context, in *ListTargetsLocalOverridesRequest, opts ...grpc.CallOption) (*ListTargetsLocalOverridesResponse, error) // Flush objects from write-cache and move it to degraded read only mode. SealWriteCache(ctx context.Context, in *SealWriteCacheRequest, opts ...grpc.CallOption) (*SealWriteCacheResponse, error) } @@ -231,6 +234,15 @@ func (c *controlServiceClient) RemoveChainLocalOverride(ctx context.Context, in return out, nil } +func (c *controlServiceClient) ListTargetsLocalOverrides(ctx context.Context, in *ListTargetsLocalOverridesRequest, opts ...grpc.CallOption) (*ListTargetsLocalOverridesResponse, error) { + out := new(ListTargetsLocalOverridesResponse) + err := c.cc.Invoke(ctx, ControlService_ListTargetsLocalOverrides_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *controlServiceClient) SealWriteCache(ctx context.Context, in *SealWriteCacheRequest, opts ...grpc.CallOption) (*SealWriteCacheResponse, error) { out := new(SealWriteCacheResponse) err := c.cc.Invoke(ctx, ControlService_SealWriteCache_FullMethodName, in, out, opts...) @@ -277,6 +289,8 @@ type ControlServiceServer interface { ListChainLocalOverrides(context.Context, *ListChainLocalOverridesRequest) (*ListChainLocalOverridesResponse, error) // Remove local access policy engine overrides stored in the node by chaind id. RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) + // List targets of the local APE overrides stored in the node. + ListTargetsLocalOverrides(context.Context, *ListTargetsLocalOverridesRequest) (*ListTargetsLocalOverridesResponse, error) // Flush objects from write-cache and move it to degraded read only mode. SealWriteCache(context.Context, *SealWriteCacheRequest) (*SealWriteCacheResponse, error) } @@ -333,6 +347,9 @@ func (UnimplementedControlServiceServer) ListChainLocalOverrides(context.Context func (UnimplementedControlServiceServer) RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveChainLocalOverride not implemented") } +func (UnimplementedControlServiceServer) ListTargetsLocalOverrides(context.Context, *ListTargetsLocalOverridesRequest) (*ListTargetsLocalOverridesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListTargetsLocalOverrides not implemented") +} func (UnimplementedControlServiceServer) SealWriteCache(context.Context, *SealWriteCacheRequest) (*SealWriteCacheResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SealWriteCache not implemented") } @@ -636,6 +653,24 @@ func _ControlService_RemoveChainLocalOverride_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _ControlService_ListTargetsLocalOverrides_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListTargetsLocalOverridesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).ListTargetsLocalOverrides(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_ListTargetsLocalOverrides_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).ListTargetsLocalOverrides(ctx, req.(*ListTargetsLocalOverridesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ControlService_SealWriteCache_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SealWriteCacheRequest) if err := dec(in); err != nil { @@ -725,6 +760,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "RemoveChainLocalOverride", Handler: _ControlService_RemoveChainLocalOverride_Handler, }, + { + MethodName: "ListTargetsLocalOverrides", + Handler: _ControlService_ListTargetsLocalOverrides_Handler, + }, { MethodName: "SealWriteCache", Handler: _ControlService_SealWriteCache_Handler, From f64c48b1578f8726c83a405be7fed670fc06bc30 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 26 Jan 2024 17:13:40 +0300 Subject: [PATCH 0304/1413] [#922] Fix linter issue Signed-off-by: Anton Nikiforov --- Makefile | 2 +- README.md | 2 +- dev/.vscode-example/launch.json | 2 +- dev/.vscode-example/tasks.json | 2 +- dev/ir/az.json | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 84653a03a2..4ff42b7e44 100755 --- a/Makefile +++ b/Makefile @@ -259,4 +259,4 @@ env-down: docker volume rm -f frostfs-node_neo-go rm -f ./.cache/.frostfs-ir-state rm -f ./.cache/.frostfs-node-state - rm -rf ./.cache/storage \ No newline at end of file + rm -rf ./.cache/storage diff --git a/README.md b/README.md index ff816f2c7f..ecd162a855 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ Enter password > <- press ENTER, the is no password for wallet CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju ./bin/frostfs-cli object put -r 127.0.0.1:8080 --wallet ./dev/wallet.json --file README.md --cid CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju -Enter password > +Enter password > 4300 / 4300 [===========================================================================================================================================================================================================] 100.00% 0s [README.md] Object successfully stored OID: 78sohnudVMnPsczXqsTUcvezosan2YDNVZwDE8Kq5YwU diff --git a/dev/.vscode-example/launch.json b/dev/.vscode-example/launch.json index cf91c0d24a..07d39482e7 100644 --- a/dev/.vscode-example/launch.json +++ b/dev/.vscode-example/launch.json @@ -86,4 +86,4 @@ "stopAll": true } ] -} \ No newline at end of file +} diff --git a/dev/.vscode-example/tasks.json b/dev/.vscode-example/tasks.json index 8c6099a059..0ccd9d1103 100644 --- a/dev/.vscode-example/tasks.json +++ b/dev/.vscode-example/tasks.json @@ -16,4 +16,4 @@ "detail": "Down debug environment" } ] -} \ No newline at end of file +} diff --git a/dev/ir/az.json b/dev/ir/az.json index a16aec295f..8e88b432c9 100644 --- a/dev/ir/az.json +++ b/dev/ir/az.json @@ -66,4 +66,3 @@ "Tokens": null } } - From befbaf9d56e734b224e3aed0b118daa96865ad48 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 26 Jan 2024 17:15:28 +0300 Subject: [PATCH 0305/1413] [#922] cli: Add new command `control list-targets` Signed-off-by: Anton Nikiforov --- .../modules/control/list_targets.go | 82 +++++++++++++++++++ cmd/frostfs-cli/modules/control/root.go | 2 + 2 files changed, 84 insertions(+) create mode 100644 cmd/frostfs-cli/modules/control/list_targets.go diff --git a/cmd/frostfs-cli/modules/control/list_targets.go b/cmd/frostfs-cli/modules/control/list_targets.go new file mode 100644 index 0000000000..29033d0176 --- /dev/null +++ b/cmd/frostfs-cli/modules/control/list_targets.go @@ -0,0 +1,82 @@ +package control + +import ( + "bytes" + "crypto/sha256" + "fmt" + "strconv" + "text/tabwriter" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "github.com/spf13/cobra" +) + +const ( + chainNameFlag = "chain-name" + chainNameFlagUsage = "Chain name(ingress|s3)" +) + +var listTargetsCmd = &cobra.Command{ + Use: "list-targets", + Short: "List local targets", + Long: "List local APE overrides of the node", + Run: listTargets, +} + +func listTargets(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + var cnr cid.ID + chainName, _ := cmd.Flags().GetString(chainNameFlag) + + rawCID := make([]byte, sha256.Size) + cnr.Encode(rawCID) + + req := &control.ListTargetsLocalOverridesRequest{ + Body: &control.ListTargetsLocalOverridesRequest_Body{ + ChainName: chainName, + }, + } + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.ListTargetsLocalOverridesResponse + var err error + err = cli.ExecRaw(func(client *client.Client) error { + resp, err = control.ListTargetsLocalOverrides(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + targets := resp.GetBody().GetTargets() + if len(targets) == 0 { + cmd.Println("Local overrides are not defined for the container.") + return + } + + buf := bytes.NewBuffer(nil) + tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) + _, _ = tw.Write([]byte("#\tName\tType\n")) + for i, t := range targets { + _, _ = tw.Write([]byte(fmt.Sprintf("%s\t%s\t%s\n", strconv.Itoa(i), t.GetName(), t.GetType()))) + } + _ = tw.Flush() + cmd.Print(buf.String()) +} + +func initControlListTargetsCmd() { + initControlFlags(listTargetsCmd) + + ff := listTargetsCmd.Flags() + ff.String(chainNameFlag, "", chainNameFlagUsage) + + _ = cobra.MarkFlagRequired(ff, chainNameFlag) +} diff --git a/cmd/frostfs-cli/modules/control/root.go b/cmd/frostfs-cli/modules/control/root.go index f7c846eba7..41222fc000 100644 --- a/cmd/frostfs-cli/modules/control/root.go +++ b/cmd/frostfs-cli/modules/control/root.go @@ -38,6 +38,7 @@ func init() { removeRuleCmd, listRulesCmd, getRuleCmd, + listTargetsCmd, ) initControlHealthCheckCmd() @@ -50,4 +51,5 @@ func init() { initControlRemoveRuleCmd() initControlListRulesCmd() initControGetRuleCmd() + initControlListTargetsCmd() } From c1a5b831b61e8c5004a7861f229906cf94dd33c4 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 2 Feb 2024 20:26:14 +0300 Subject: [PATCH 0306/1413] [#955] chainbase: Fix rule chain unmarshalling * Use correct way DecodeBytes instead unmarshalling by json. Signed-off-by: Airat Arifullin --- pkg/ape/chainbase/boltdb.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index c26156c7a7..a1dfc2567b 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -2,7 +2,6 @@ package chainbase import ( "context" - "encoding/json" "errors" "fmt" "path/filepath" @@ -203,7 +202,7 @@ func (cs *boltLocalOverrideStorage) GetOverride(name chain.Name, target policyen } c := &chain.Chain{} - if err := json.Unmarshal(serializedChain, c); err != nil { + if err := c.DecodeBytes(serializedChain); err != nil { return nil, err } return c, nil @@ -241,7 +240,7 @@ func (cs *boltLocalOverrideStorage) ListOverrides(name chain.Name, target policy chains := make([]*chain.Chain, 0, len(serializedChains)) for _, serializedChain = range serializedChains { c := &chain.Chain{} - if err := json.Unmarshal(serializedChain, c); err != nil { + if err := c.DecodeBytes(serializedChain); err != nil { return nil, err } chains = append(chains, c) From 602ee11123b46dd8131903928c34c5f014d6d601 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 2 Feb 2024 17:56:40 +0300 Subject: [PATCH 0307/1413] [#934] containersvc: Marhal public key in short format for APE Signed-off-by: Evgenii Stratonikov --- pkg/services/container/ape.go | 7 ++++--- pkg/services/container/ape_test.go | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index c57e54d08a..d1b490bdf0 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -6,6 +6,7 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/sha256" + "encoding/hex" "errors" "fmt" "strings" @@ -133,7 +134,7 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co } reqProps := map[string]string{ - nativeschema.PropertyKeyActorPublicKey: pk.String(), + nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(pk.Bytes()), nativeschema.PropertyKeyActorRole: role, } @@ -178,7 +179,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont } reqProps := map[string]string{ - nativeschema.PropertyKeyActorPublicKey: pk.String(), + nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(pk.Bytes()), nativeschema.PropertyKeyActorRole: role, } @@ -391,7 +392,7 @@ func (ac *apeChecker) getRequestProps(mh *session.RequestMetaHeader, vh *session return nil, err } return map[string]string{ - nativeschema.PropertyKeyActorPublicKey: pk.String(), + nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(pk.Bytes()), nativeschema.PropertyKeyActorRole: role, }, nil } diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 5344d9f238..daaacb0319 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -3,6 +3,7 @@ package container import ( "context" "crypto/ecdsa" + "encoding/hex" "errors" "fmt" "testing" @@ -524,7 +525,7 @@ func testDenyListContainersForPK(t *testing.T) { { Object: chain.ObjectRequest, Key: nativeschema.PropertyKeyActorPublicKey, - Value: pk.PublicKey().String(), + Value: hex.EncodeToString(pk.PublicKey().Bytes()), Op: chain.CondStringEquals, }, }, From afd2ba9a6664bb2e2e875959b29aa4afd5f4df5b Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 30 Jan 2024 08:39:34 +0300 Subject: [PATCH 0308/1413] [#110] Add check for repeated error log in policer processObject() returns 3 types of errors: container not found errors, could not get container error and placement vector building error. Every error will occur for all objects in container simultaneously, so we can log each error once and safely ignore the rest. Signed-off-by: Ekaterina Lebedeva --- pkg/services/policer/process.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index c4c820200c..df4f0c4c70 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" ) @@ -34,6 +35,9 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { p.log.Warn(logs.PolicerFailureAtObjectSelectForReplication, zap.Error(err)) } + // contains all errors logged in this iteration for each container + cnrErrSkip := make(map[cid.ID][]error) + for i := range addrs { select { case <-ctx.Done(): @@ -55,10 +59,12 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { if p.objsInWork.add(addr.Address) { err := p.processObject(ctx, addr) - if err != nil { + if err != nil && !skipLog(cnrErrSkip[addr.Address.Container()], err) { p.log.Error(logs.PolicerUnableToProcessObj, zap.Stringer("object", addr.Address), zap.String("error", err.Error())) + + cnrErrSkip[addr.Address.Container()] = append(cnrErrSkip[addr.Address.Container()], err) } p.cache.Add(addr.Address, time.Now()) p.objsInWork.remove(addr.Address) @@ -72,3 +78,12 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { } } } + +func skipLog(errs []error, err error) bool { + for _, e := range errs { + if errors.Is(err, e) { + return true + } + } + return false +} From 4358d3c42321222296f9d834517a90a1d3ad5e7a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 30 Jan 2024 17:09:23 +0300 Subject: [PATCH 0309/1413] [#917] controlSvc: Add DetachShards handler Signed-off-by: Dmitrii Stepanov --- pkg/services/control/service.pb.go | 1067 ++++++++++++-------- pkg/services/control/service.proto | 21 + pkg/services/control/service_frostfs.pb.go | 163 +++ pkg/services/control/service_grpc.pb.go | 39 + 4 files changed, 895 insertions(+), 395 deletions(-) diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index e0c6e0622a..c9645941bf 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -2106,6 +2106,116 @@ func (x *SealWriteCacheResponse) GetSignature() *Signature { return nil } +type DetachShardsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *DetachShardsRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *DetachShardsRequest) Reset() { + *x = DetachShardsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DetachShardsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DetachShardsRequest) ProtoMessage() {} + +func (x *DetachShardsRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DetachShardsRequest.ProtoReflect.Descriptor instead. +func (*DetachShardsRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36} +} + +func (x *DetachShardsRequest) GetBody() *DetachShardsRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *DetachShardsRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type DetachShardsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *DetachShardsResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *DetachShardsResponse) Reset() { + *x = DetachShardsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DetachShardsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DetachShardsResponse) ProtoMessage() {} + +func (x *DetachShardsResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[37] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DetachShardsResponse.ProtoReflect.Descriptor instead. +func (*DetachShardsResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37} +} + +func (x *DetachShardsResponse) GetBody() *DetachShardsResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *DetachShardsResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + // Health check request body. type HealthCheckRequest_Body struct { state protoimpl.MessageState @@ -2116,7 +2226,7 @@ type HealthCheckRequest_Body struct { func (x *HealthCheckRequest_Body) Reset() { *x = HealthCheckRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2129,7 +2239,7 @@ func (x *HealthCheckRequest_Body) String() string { func (*HealthCheckRequest_Body) ProtoMessage() {} func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2160,7 +2270,7 @@ type HealthCheckResponse_Body struct { func (x *HealthCheckResponse_Body) Reset() { *x = HealthCheckResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2173,7 +2283,7 @@ func (x *HealthCheckResponse_Body) String() string { func (*HealthCheckResponse_Body) ProtoMessage() {} func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2224,7 +2334,7 @@ type SetNetmapStatusRequest_Body struct { func (x *SetNetmapStatusRequest_Body) Reset() { *x = SetNetmapStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2237,7 +2347,7 @@ func (x *SetNetmapStatusRequest_Body) String() string { func (*SetNetmapStatusRequest_Body) ProtoMessage() {} func (x *SetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2277,7 +2387,7 @@ type SetNetmapStatusResponse_Body struct { func (x *SetNetmapStatusResponse_Body) Reset() { *x = SetNetmapStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2290,7 +2400,7 @@ func (x *SetNetmapStatusResponse_Body) String() string { func (*SetNetmapStatusResponse_Body) ProtoMessage() {} func (x *SetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2320,7 +2430,7 @@ type DropObjectsRequest_Body struct { func (x *DropObjectsRequest_Body) Reset() { *x = DropObjectsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2333,7 +2443,7 @@ func (x *DropObjectsRequest_Body) String() string { func (*DropObjectsRequest_Body) ProtoMessage() {} func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2366,7 +2476,7 @@ type DropObjectsResponse_Body struct { func (x *DropObjectsResponse_Body) Reset() { *x = DropObjectsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2379,7 +2489,7 @@ func (x *DropObjectsResponse_Body) String() string { func (*DropObjectsResponse_Body) ProtoMessage() {} func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2405,7 +2515,7 @@ type ListShardsRequest_Body struct { func (x *ListShardsRequest_Body) Reset() { *x = ListShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2418,7 +2528,7 @@ func (x *ListShardsRequest_Body) String() string { func (*ListShardsRequest_Body) ProtoMessage() {} func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2447,7 +2557,7 @@ type ListShardsResponse_Body struct { func (x *ListShardsResponse_Body) Reset() { *x = ListShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2460,7 +2570,7 @@ func (x *ListShardsResponse_Body) String() string { func (*ListShardsResponse_Body) ProtoMessage() {} func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2500,7 +2610,7 @@ type SetShardModeRequest_Body struct { func (x *SetShardModeRequest_Body) Reset() { *x = SetShardModeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2513,7 +2623,7 @@ func (x *SetShardModeRequest_Body) String() string { func (*SetShardModeRequest_Body) ProtoMessage() {} func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2560,7 +2670,7 @@ type SetShardModeResponse_Body struct { func (x *SetShardModeResponse_Body) Reset() { *x = SetShardModeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2573,7 +2683,7 @@ func (x *SetShardModeResponse_Body) String() string { func (*SetShardModeResponse_Body) ProtoMessage() {} func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2604,7 +2714,7 @@ type SynchronizeTreeRequest_Body struct { func (x *SynchronizeTreeRequest_Body) Reset() { *x = SynchronizeTreeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2617,7 +2727,7 @@ func (x *SynchronizeTreeRequest_Body) String() string { func (*SynchronizeTreeRequest_Body) ProtoMessage() {} func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2664,7 +2774,7 @@ type SynchronizeTreeResponse_Body struct { func (x *SynchronizeTreeResponse_Body) Reset() { *x = SynchronizeTreeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2677,7 +2787,7 @@ func (x *SynchronizeTreeResponse_Body) String() string { func (*SynchronizeTreeResponse_Body) ProtoMessage() {} func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2708,7 +2818,7 @@ type EvacuateShardRequest_Body struct { func (x *EvacuateShardRequest_Body) Reset() { *x = EvacuateShardRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2721,7 +2831,7 @@ func (x *EvacuateShardRequest_Body) String() string { func (*EvacuateShardRequest_Body) ProtoMessage() {} func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2763,7 +2873,7 @@ type EvacuateShardResponse_Body struct { func (x *EvacuateShardResponse_Body) Reset() { *x = EvacuateShardResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2776,7 +2886,7 @@ func (x *EvacuateShardResponse_Body) String() string { func (*EvacuateShardResponse_Body) ProtoMessage() {} func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2814,7 +2924,7 @@ type FlushCacheRequest_Body struct { func (x *FlushCacheRequest_Body) Reset() { *x = FlushCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2827,7 +2937,7 @@ func (x *FlushCacheRequest_Body) String() string { func (*FlushCacheRequest_Body) ProtoMessage() {} func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2867,7 +2977,7 @@ type FlushCacheResponse_Body struct { func (x *FlushCacheResponse_Body) Reset() { *x = FlushCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2880,7 +2990,7 @@ func (x *FlushCacheResponse_Body) String() string { func (*FlushCacheResponse_Body) ProtoMessage() {} func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2911,7 +3021,7 @@ type DoctorRequest_Body struct { func (x *DoctorRequest_Body) Reset() { *x = DoctorRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2924,7 +3034,7 @@ func (x *DoctorRequest_Body) String() string { func (*DoctorRequest_Body) ProtoMessage() {} func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2964,7 +3074,7 @@ type DoctorResponse_Body struct { func (x *DoctorResponse_Body) Reset() { *x = DoctorResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2977,7 +3087,7 @@ func (x *DoctorResponse_Body) String() string { func (*DoctorResponse_Body) ProtoMessage() {} func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3008,7 +3118,7 @@ type StartShardEvacuationRequest_Body struct { func (x *StartShardEvacuationRequest_Body) Reset() { *x = StartShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3021,7 +3131,7 @@ func (x *StartShardEvacuationRequest_Body) String() string { func (*StartShardEvacuationRequest_Body) ProtoMessage() {} func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3061,7 +3171,7 @@ type StartShardEvacuationResponse_Body struct { func (x *StartShardEvacuationResponse_Body) Reset() { *x = StartShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3074,7 +3184,7 @@ func (x *StartShardEvacuationResponse_Body) String() string { func (*StartShardEvacuationResponse_Body) ProtoMessage() {} func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3100,7 +3210,7 @@ type GetShardEvacuationStatusRequest_Body struct { func (x *GetShardEvacuationStatusRequest_Body) Reset() { *x = GetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3113,7 +3223,7 @@ func (x *GetShardEvacuationStatusRequest_Body) String() string { func (*GetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3158,7 +3268,7 @@ type GetShardEvacuationStatusResponse_Body struct { func (x *GetShardEvacuationStatusResponse_Body) Reset() { *x = GetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3171,7 +3281,7 @@ func (x *GetShardEvacuationStatusResponse_Body) String() string { func (*GetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3262,7 +3372,7 @@ type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) Reset() { *x = GetShardEvacuationStatusResponse_Body_UnixTimestamp{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3275,7 +3385,7 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) String() string { func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3310,7 +3420,7 @@ type GetShardEvacuationStatusResponse_Body_Duration struct { func (x *GetShardEvacuationStatusResponse_Body_Duration) Reset() { *x = GetShardEvacuationStatusResponse_Body_Duration{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3323,7 +3433,7 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) String() string { func (*GetShardEvacuationStatusResponse_Body_Duration) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3356,7 +3466,7 @@ type StopShardEvacuationRequest_Body struct { func (x *StopShardEvacuationRequest_Body) Reset() { *x = StopShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3369,7 +3479,7 @@ func (x *StopShardEvacuationRequest_Body) String() string { func (*StopShardEvacuationRequest_Body) ProtoMessage() {} func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3395,7 +3505,7 @@ type StopShardEvacuationResponse_Body struct { func (x *StopShardEvacuationResponse_Body) Reset() { *x = StopShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3408,7 +3518,7 @@ func (x *StopShardEvacuationResponse_Body) String() string { func (*StopShardEvacuationResponse_Body) ProtoMessage() {} func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3440,7 +3550,7 @@ type AddChainLocalOverrideRequest_Body struct { func (x *AddChainLocalOverrideRequest_Body) Reset() { *x = AddChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3453,7 +3563,7 @@ func (x *AddChainLocalOverrideRequest_Body) String() string { func (*AddChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3497,7 +3607,7 @@ type AddChainLocalOverrideResponse_Body struct { func (x *AddChainLocalOverrideResponse_Body) Reset() { *x = AddChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3510,7 +3620,7 @@ func (x *AddChainLocalOverrideResponse_Body) String() string { func (*AddChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3547,7 +3657,7 @@ type GetChainLocalOverrideRequest_Body struct { func (x *GetChainLocalOverrideRequest_Body) Reset() { *x = GetChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3560,7 +3670,7 @@ func (x *GetChainLocalOverrideRequest_Body) String() string { func (*GetChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3602,7 +3712,7 @@ type GetChainLocalOverrideResponse_Body struct { func (x *GetChainLocalOverrideResponse_Body) Reset() { *x = GetChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3615,7 +3725,7 @@ func (x *GetChainLocalOverrideResponse_Body) String() string { func (*GetChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3650,7 +3760,7 @@ type ListChainLocalOverridesRequest_Body struct { func (x *ListChainLocalOverridesRequest_Body) Reset() { *x = ListChainLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3663,7 +3773,7 @@ func (x *ListChainLocalOverridesRequest_Body) String() string { func (*ListChainLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3698,7 +3808,7 @@ type ListChainLocalOverridesResponse_Body struct { func (x *ListChainLocalOverridesResponse_Body) Reset() { *x = ListChainLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3711,7 +3821,7 @@ func (x *ListChainLocalOverridesResponse_Body) String() string { func (*ListChainLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3746,7 +3856,7 @@ type ListTargetsLocalOverridesRequest_Body struct { func (x *ListTargetsLocalOverridesRequest_Body) Reset() { *x = ListTargetsLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3759,7 +3869,7 @@ func (x *ListTargetsLocalOverridesRequest_Body) String() string { func (*ListTargetsLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListTargetsLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3794,7 +3904,7 @@ type ListTargetsLocalOverridesResponse_Body struct { func (x *ListTargetsLocalOverridesResponse_Body) Reset() { *x = ListTargetsLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3807,7 +3917,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) String() string { func (*ListTargetsLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListTargetsLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3844,7 +3954,7 @@ type RemoveChainLocalOverrideRequest_Body struct { func (x *RemoveChainLocalOverrideRequest_Body) Reset() { *x = RemoveChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3857,7 +3967,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) String() string { func (*RemoveChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3898,7 +4008,7 @@ type RemoveChainLocalOverrideResponse_Body struct { func (x *RemoveChainLocalOverrideResponse_Body) Reset() { *x = RemoveChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[71] + mi := &file_pkg_services_control_service_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3911,7 +4021,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) String() string { func (*RemoveChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[71] + mi := &file_pkg_services_control_service_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3949,7 +4059,7 @@ type SealWriteCacheRequest_Body struct { func (x *SealWriteCacheRequest_Body) Reset() { *x = SealWriteCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[72] + mi := &file_pkg_services_control_service_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3962,7 +4072,7 @@ func (x *SealWriteCacheRequest_Body) String() string { func (*SealWriteCacheRequest_Body) ProtoMessage() {} func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[72] + mi := &file_pkg_services_control_service_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4003,7 +4113,7 @@ type SealWriteCacheResponse_Body struct { func (x *SealWriteCacheResponse_Body) Reset() { *x = SealWriteCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[73] + mi := &file_pkg_services_control_service_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4016,7 +4126,7 @@ func (x *SealWriteCacheResponse_Body) String() string { func (*SealWriteCacheResponse_Body) ProtoMessage() {} func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[73] + mi := &file_pkg_services_control_service_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4052,7 +4162,7 @@ type SealWriteCacheResponse_Body_Status struct { func (x *SealWriteCacheResponse_Body_Status) Reset() { *x = SealWriteCacheResponse_Body_Status{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[74] + mi := &file_pkg_services_control_service_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4065,7 +4175,7 @@ func (x *SealWriteCacheResponse_Body_Status) String() string { func (*SealWriteCacheResponse_Body_Status) ProtoMessage() {} func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[74] + mi := &file_pkg_services_control_service_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4102,6 +4212,91 @@ func (x *SealWriteCacheResponse_Body_Status) GetError() string { return "" } +type DetachShardsRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` +} + +func (x *DetachShardsRequest_Body) Reset() { + *x = DetachShardsRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[77] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DetachShardsRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DetachShardsRequest_Body) ProtoMessage() {} + +func (x *DetachShardsRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[77] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DetachShardsRequest_Body.ProtoReflect.Descriptor instead. +func (*DetachShardsRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36, 0} +} + +func (x *DetachShardsRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} + +type DetachShardsResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DetachShardsResponse_Body) Reset() { + *x = DetachShardsResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[78] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DetachShardsResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DetachShardsResponse_Body) ProtoMessage() {} + +func (x *DetachShardsResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[78] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DetachShardsResponse_Body.ProtoReflect.Descriptor instead. +func (*DetachShardsResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0} +} + var File_pkg_services_control_service_proto protoreflect.FileDescriptor var file_pkg_services_control_service_proto_rawDesc = []byte{ @@ -4564,114 +4759,138 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xe4, 0x0c, 0x0a, - 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, - 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, + 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, + 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, + 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb1, 0x0d, 0x0a, 0x0e, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, + 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, - 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, - 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, - 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, + 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, + 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, + 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, + 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, + 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, - 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, - 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, - 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, - 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, + 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, + 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, + 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, + 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, - 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, - 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, - 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, - 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, + 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, + 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, + 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4687,7 +4906,7 @@ func file_pkg_services_control_service_proto_rawDescGZIP() []byte { } var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 75) +var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 79) var file_pkg_services_control_service_proto_goTypes = []interface{}{ (GetShardEvacuationStatusResponse_Body_Status)(0), // 0: control.GetShardEvacuationStatusResponse.Body.Status (*HealthCheckRequest)(nil), // 1: control.HealthCheckRequest @@ -4726,180 +4945,190 @@ var file_pkg_services_control_service_proto_goTypes = []interface{}{ (*RemoveChainLocalOverrideResponse)(nil), // 34: control.RemoveChainLocalOverrideResponse (*SealWriteCacheRequest)(nil), // 35: control.SealWriteCacheRequest (*SealWriteCacheResponse)(nil), // 36: control.SealWriteCacheResponse - (*HealthCheckRequest_Body)(nil), // 37: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 38: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 39: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 40: control.SetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 41: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 42: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 43: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 44: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 45: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 46: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 47: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 48: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 49: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 50: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 51: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 52: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 53: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 54: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 55: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 56: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 57: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 58: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 59: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 60: control.GetShardEvacuationStatusResponse.Body.Duration - (*StopShardEvacuationRequest_Body)(nil), // 61: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 62: control.StopShardEvacuationResponse.Body - (*AddChainLocalOverrideRequest_Body)(nil), // 63: control.AddChainLocalOverrideRequest.Body - (*AddChainLocalOverrideResponse_Body)(nil), // 64: control.AddChainLocalOverrideResponse.Body - (*GetChainLocalOverrideRequest_Body)(nil), // 65: control.GetChainLocalOverrideRequest.Body - (*GetChainLocalOverrideResponse_Body)(nil), // 66: control.GetChainLocalOverrideResponse.Body - (*ListChainLocalOverridesRequest_Body)(nil), // 67: control.ListChainLocalOverridesRequest.Body - (*ListChainLocalOverridesResponse_Body)(nil), // 68: control.ListChainLocalOverridesResponse.Body - (*ListTargetsLocalOverridesRequest_Body)(nil), // 69: control.ListTargetsLocalOverridesRequest.Body - (*ListTargetsLocalOverridesResponse_Body)(nil), // 70: control.ListTargetsLocalOverridesResponse.Body - (*RemoveChainLocalOverrideRequest_Body)(nil), // 71: control.RemoveChainLocalOverrideRequest.Body - (*RemoveChainLocalOverrideResponse_Body)(nil), // 72: control.RemoveChainLocalOverrideResponse.Body - (*SealWriteCacheRequest_Body)(nil), // 73: control.SealWriteCacheRequest.Body - (*SealWriteCacheResponse_Body)(nil), // 74: control.SealWriteCacheResponse.Body - (*SealWriteCacheResponse_Body_Status)(nil), // 75: control.SealWriteCacheResponse.Body.Status - (*Signature)(nil), // 76: control.Signature - (NetmapStatus)(0), // 77: control.NetmapStatus - (HealthStatus)(0), // 78: control.HealthStatus - (*ShardInfo)(nil), // 79: control.ShardInfo - (ShardMode)(0), // 80: control.ShardMode - (*ChainTarget)(nil), // 81: control.ChainTarget + (*DetachShardsRequest)(nil), // 37: control.DetachShardsRequest + (*DetachShardsResponse)(nil), // 38: control.DetachShardsResponse + (*HealthCheckRequest_Body)(nil), // 39: control.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 40: control.HealthCheckResponse.Body + (*SetNetmapStatusRequest_Body)(nil), // 41: control.SetNetmapStatusRequest.Body + (*SetNetmapStatusResponse_Body)(nil), // 42: control.SetNetmapStatusResponse.Body + (*DropObjectsRequest_Body)(nil), // 43: control.DropObjectsRequest.Body + (*DropObjectsResponse_Body)(nil), // 44: control.DropObjectsResponse.Body + (*ListShardsRequest_Body)(nil), // 45: control.ListShardsRequest.Body + (*ListShardsResponse_Body)(nil), // 46: control.ListShardsResponse.Body + (*SetShardModeRequest_Body)(nil), // 47: control.SetShardModeRequest.Body + (*SetShardModeResponse_Body)(nil), // 48: control.SetShardModeResponse.Body + (*SynchronizeTreeRequest_Body)(nil), // 49: control.SynchronizeTreeRequest.Body + (*SynchronizeTreeResponse_Body)(nil), // 50: control.SynchronizeTreeResponse.Body + (*EvacuateShardRequest_Body)(nil), // 51: control.EvacuateShardRequest.Body + (*EvacuateShardResponse_Body)(nil), // 52: control.EvacuateShardResponse.Body + (*FlushCacheRequest_Body)(nil), // 53: control.FlushCacheRequest.Body + (*FlushCacheResponse_Body)(nil), // 54: control.FlushCacheResponse.Body + (*DoctorRequest_Body)(nil), // 55: control.DoctorRequest.Body + (*DoctorResponse_Body)(nil), // 56: control.DoctorResponse.Body + (*StartShardEvacuationRequest_Body)(nil), // 57: control.StartShardEvacuationRequest.Body + (*StartShardEvacuationResponse_Body)(nil), // 58: control.StartShardEvacuationResponse.Body + (*GetShardEvacuationStatusRequest_Body)(nil), // 59: control.GetShardEvacuationStatusRequest.Body + (*GetShardEvacuationStatusResponse_Body)(nil), // 60: control.GetShardEvacuationStatusResponse.Body + (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 61: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 62: control.GetShardEvacuationStatusResponse.Body.Duration + (*StopShardEvacuationRequest_Body)(nil), // 63: control.StopShardEvacuationRequest.Body + (*StopShardEvacuationResponse_Body)(nil), // 64: control.StopShardEvacuationResponse.Body + (*AddChainLocalOverrideRequest_Body)(nil), // 65: control.AddChainLocalOverrideRequest.Body + (*AddChainLocalOverrideResponse_Body)(nil), // 66: control.AddChainLocalOverrideResponse.Body + (*GetChainLocalOverrideRequest_Body)(nil), // 67: control.GetChainLocalOverrideRequest.Body + (*GetChainLocalOverrideResponse_Body)(nil), // 68: control.GetChainLocalOverrideResponse.Body + (*ListChainLocalOverridesRequest_Body)(nil), // 69: control.ListChainLocalOverridesRequest.Body + (*ListChainLocalOverridesResponse_Body)(nil), // 70: control.ListChainLocalOverridesResponse.Body + (*ListTargetsLocalOverridesRequest_Body)(nil), // 71: control.ListTargetsLocalOverridesRequest.Body + (*ListTargetsLocalOverridesResponse_Body)(nil), // 72: control.ListTargetsLocalOverridesResponse.Body + (*RemoveChainLocalOverrideRequest_Body)(nil), // 73: control.RemoveChainLocalOverrideRequest.Body + (*RemoveChainLocalOverrideResponse_Body)(nil), // 74: control.RemoveChainLocalOverrideResponse.Body + (*SealWriteCacheRequest_Body)(nil), // 75: control.SealWriteCacheRequest.Body + (*SealWriteCacheResponse_Body)(nil), // 76: control.SealWriteCacheResponse.Body + (*SealWriteCacheResponse_Body_Status)(nil), // 77: control.SealWriteCacheResponse.Body.Status + (*DetachShardsRequest_Body)(nil), // 78: control.DetachShardsRequest.Body + (*DetachShardsResponse_Body)(nil), // 79: control.DetachShardsResponse.Body + (*Signature)(nil), // 80: control.Signature + (NetmapStatus)(0), // 81: control.NetmapStatus + (HealthStatus)(0), // 82: control.HealthStatus + (*ShardInfo)(nil), // 83: control.ShardInfo + (ShardMode)(0), // 84: control.ShardMode + (*ChainTarget)(nil), // 85: control.ChainTarget } var file_pkg_services_control_service_proto_depIdxs = []int32{ - 37, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 76, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 38, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 76, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 39, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 76, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 40, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 76, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 41, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 76, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature - 42, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 76, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature - 43, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 76, // 13: control.ListShardsRequest.signature:type_name -> control.Signature - 44, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 76, // 15: control.ListShardsResponse.signature:type_name -> control.Signature - 45, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 76, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature - 46, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 76, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature - 47, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 76, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 48, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 76, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 49, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 76, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature - 50, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 76, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature - 51, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 76, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature - 52, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 76, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature - 53, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 76, // 33: control.DoctorRequest.signature:type_name -> control.Signature - 54, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 76, // 35: control.DoctorResponse.signature:type_name -> control.Signature - 55, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 76, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 56, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 76, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 57, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 76, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 58, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 76, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 61, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 76, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 62, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 76, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 63, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body - 76, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature - 64, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body - 76, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature - 65, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body - 76, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature - 66, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body - 76, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature - 67, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body - 76, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature - 68, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body - 76, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature - 69, // 60: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body - 76, // 61: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature - 70, // 62: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body - 76, // 63: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature - 71, // 64: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body - 76, // 65: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature - 72, // 66: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body - 76, // 67: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature - 73, // 68: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body - 76, // 69: control.SealWriteCacheRequest.signature:type_name -> control.Signature - 74, // 70: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body - 76, // 71: control.SealWriteCacheResponse.signature:type_name -> control.Signature - 77, // 72: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 78, // 73: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 77, // 74: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 79, // 75: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 80, // 76: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 0, // 77: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 60, // 78: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 59, // 79: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 81, // 80: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 81, // 81: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 81, // 82: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget - 81, // 83: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget - 81, // 84: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 75, // 85: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status - 1, // 86: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 3, // 87: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 5, // 88: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 7, // 89: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 9, // 90: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 11, // 91: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 13, // 92: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 19, // 93: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 21, // 94: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 23, // 95: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 15, // 96: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 17, // 97: control.ControlService.Doctor:input_type -> control.DoctorRequest - 25, // 98: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 27, // 99: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 29, // 100: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 33, // 101: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 31, // 102: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest - 35, // 103: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest - 2, // 104: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 4, // 105: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 6, // 106: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 8, // 107: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 10, // 108: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 12, // 109: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 14, // 110: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 20, // 111: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 22, // 112: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 24, // 113: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 16, // 114: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 18, // 115: control.ControlService.Doctor:output_type -> control.DoctorResponse - 26, // 116: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 28, // 117: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 30, // 118: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 34, // 119: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 32, // 120: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse - 36, // 121: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse - 104, // [104:122] is the sub-list for method output_type - 86, // [86:104] is the sub-list for method input_type - 86, // [86:86] is the sub-list for extension type_name - 86, // [86:86] is the sub-list for extension extendee - 0, // [0:86] is the sub-list for field type_name + 39, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body + 80, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature + 40, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body + 80, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature + 41, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body + 80, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature + 42, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body + 80, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature + 43, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body + 80, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature + 44, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body + 80, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature + 45, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body + 80, // 13: control.ListShardsRequest.signature:type_name -> control.Signature + 46, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body + 80, // 15: control.ListShardsResponse.signature:type_name -> control.Signature + 47, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body + 80, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature + 48, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body + 80, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature + 49, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body + 80, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature + 50, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body + 80, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature + 51, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body + 80, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature + 52, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body + 80, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature + 53, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body + 80, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature + 54, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body + 80, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature + 55, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body + 80, // 33: control.DoctorRequest.signature:type_name -> control.Signature + 56, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body + 80, // 35: control.DoctorResponse.signature:type_name -> control.Signature + 57, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body + 80, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature + 58, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body + 80, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature + 59, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body + 80, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 60, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body + 80, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 63, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body + 80, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature + 64, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body + 80, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature + 65, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body + 80, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature + 66, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body + 80, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature + 67, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body + 80, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature + 68, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body + 80, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature + 69, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body + 80, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature + 70, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body + 80, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature + 71, // 60: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body + 80, // 61: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature + 72, // 62: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body + 80, // 63: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature + 73, // 64: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body + 80, // 65: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature + 74, // 66: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body + 80, // 67: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature + 75, // 68: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body + 80, // 69: control.SealWriteCacheRequest.signature:type_name -> control.Signature + 76, // 70: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body + 80, // 71: control.SealWriteCacheResponse.signature:type_name -> control.Signature + 78, // 72: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body + 80, // 73: control.DetachShardsRequest.signature:type_name -> control.Signature + 79, // 74: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body + 80, // 75: control.DetachShardsResponse.signature:type_name -> control.Signature + 81, // 76: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus + 82, // 77: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus + 81, // 78: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus + 83, // 79: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo + 84, // 80: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode + 0, // 81: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status + 62, // 82: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration + 61, // 83: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + 85, // 84: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 85, // 85: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 85, // 86: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget + 85, // 87: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget + 85, // 88: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 77, // 89: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status + 1, // 90: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 3, // 91: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 5, // 92: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 7, // 93: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 9, // 94: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 11, // 95: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 13, // 96: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 19, // 97: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 21, // 98: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 23, // 99: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 15, // 100: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 17, // 101: control.ControlService.Doctor:input_type -> control.DoctorRequest + 25, // 102: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 27, // 103: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 29, // 104: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 33, // 105: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 31, // 106: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest + 35, // 107: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest + 37, // 108: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest + 2, // 109: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 4, // 110: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 6, // 111: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 8, // 112: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 10, // 113: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 12, // 114: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 14, // 115: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 20, // 116: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 22, // 117: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 24, // 118: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 16, // 119: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 18, // 120: control.ControlService.Doctor:output_type -> control.DoctorResponse + 26, // 121: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 28, // 122: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 30, // 123: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 34, // 124: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 32, // 125: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse + 36, // 126: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse + 38, // 127: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse + 109, // [109:128] is the sub-list for method output_type + 90, // [90:109] is the sub-list for method input_type + 90, // [90:90] is the sub-list for extension type_name + 90, // [90:90] is the sub-list for extension extendee + 0, // [0:90] is the sub-list for field type_name } func init() { file_pkg_services_control_service_proto_init() } @@ -5342,7 +5571,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { + switch v := v.(*DetachShardsRequest); i { case 0: return &v.state case 1: @@ -5354,7 +5583,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { + switch v := v.(*DetachShardsResponse); i { case 0: return &v.state case 1: @@ -5366,7 +5595,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest_Body); i { + switch v := v.(*HealthCheckRequest_Body); i { case 0: return &v.state case 1: @@ -5378,7 +5607,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse_Body); i { + switch v := v.(*HealthCheckResponse_Body); i { case 0: return &v.state case 1: @@ -5390,7 +5619,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest_Body); i { + switch v := v.(*SetNetmapStatusRequest_Body); i { case 0: return &v.state case 1: @@ -5402,7 +5631,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse_Body); i { + switch v := v.(*SetNetmapStatusResponse_Body); i { case 0: return &v.state case 1: @@ -5414,7 +5643,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest_Body); i { + switch v := v.(*DropObjectsRequest_Body); i { case 0: return &v.state case 1: @@ -5426,7 +5655,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse_Body); i { + switch v := v.(*DropObjectsResponse_Body); i { case 0: return &v.state case 1: @@ -5438,7 +5667,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest_Body); i { + switch v := v.(*ListShardsRequest_Body); i { case 0: return &v.state case 1: @@ -5450,7 +5679,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse_Body); i { + switch v := v.(*ListShardsResponse_Body); i { case 0: return &v.state case 1: @@ -5462,7 +5691,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest_Body); i { + switch v := v.(*SetShardModeRequest_Body); i { case 0: return &v.state case 1: @@ -5474,7 +5703,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse_Body); i { + switch v := v.(*SetShardModeResponse_Body); i { case 0: return &v.state case 1: @@ -5486,7 +5715,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest_Body); i { + switch v := v.(*SynchronizeTreeRequest_Body); i { case 0: return &v.state case 1: @@ -5498,7 +5727,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse_Body); i { + switch v := v.(*SynchronizeTreeResponse_Body); i { case 0: return &v.state case 1: @@ -5510,7 +5739,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest_Body); i { + switch v := v.(*EvacuateShardRequest_Body); i { case 0: return &v.state case 1: @@ -5522,7 +5751,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse_Body); i { + switch v := v.(*EvacuateShardResponse_Body); i { case 0: return &v.state case 1: @@ -5534,7 +5763,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest_Body); i { + switch v := v.(*FlushCacheRequest_Body); i { case 0: return &v.state case 1: @@ -5546,7 +5775,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse_Body); i { + switch v := v.(*FlushCacheResponse_Body); i { case 0: return &v.state case 1: @@ -5558,7 +5787,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest_Body); i { + switch v := v.(*DoctorRequest_Body); i { case 0: return &v.state case 1: @@ -5570,7 +5799,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse_Body); i { + switch v := v.(*DoctorResponse_Body); i { case 0: return &v.state case 1: @@ -5582,7 +5811,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest_Body); i { + switch v := v.(*StartShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -5594,7 +5823,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body); i { + switch v := v.(*StartShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -5606,7 +5835,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { + switch v := v.(*GetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -5618,7 +5847,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -5630,7 +5859,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { case 0: return &v.state case 1: @@ -5642,7 +5871,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { case 0: return &v.state case 1: @@ -5654,7 +5883,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest_Body); i { + switch v := v.(*StopShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -5666,7 +5895,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse_Body); i { + switch v := v.(*StopShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -5678,7 +5907,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest_Body); i { + switch v := v.(*AddChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -5690,7 +5919,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse_Body); i { + switch v := v.(*AddChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -5702,7 +5931,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest_Body); i { + switch v := v.(*GetChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -5714,7 +5943,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse_Body); i { + switch v := v.(*GetChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -5726,7 +5955,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { + switch v := v.(*ListChainLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -5738,7 +5967,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { + switch v := v.(*ListChainLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -5750,7 +5979,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -5762,7 +5991,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { + switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -5774,7 +6003,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest_Body); i { + switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -5786,7 +6015,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body); i { + switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -5798,6 +6027,30 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SealWriteCacheResponse_Body_Status); i { case 0: return &v.state @@ -5809,6 +6062,30 @@ func file_pkg_services_control_service_proto_init() { return nil } } + file_pkg_services_control_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DetachShardsRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DetachShardsResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -5816,7 +6093,7 @@ func file_pkg_services_control_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_service_proto_rawDesc, NumEnums: 1, - NumMessages: 75, + NumMessages: 79, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index dc63a71886..4cb1dee33b 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -62,6 +62,9 @@ service ControlService { // Flush objects from write-cache and move it to degraded read only mode. rpc SealWriteCache(SealWriteCacheRequest) returns (SealWriteCacheResponse); + + // DetachShards detaches and closes shards. + rpc DetachShards(DetachShardsRequest) returns (DetachShardsResponse); } // Health check request. @@ -584,3 +587,21 @@ message SealWriteCacheResponse { Signature signature = 2; } + +message DetachShardsRequest { + message Body { + repeated bytes shard_ID = 1; + } + + Body body = 1; + Signature signature = 2; +} + +message DetachShardsResponse { + message Body { + } + + Body body = 1; + + Signature signature = 2; +} diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index b72fc0f128..125a12d00e 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -3144,3 +3144,166 @@ func (x *SealWriteCacheResponse) ReadSignedData(buf []byte) ([]byte, error) { func (x *SealWriteCacheResponse) SetSignature(sig *Signature) { x.Signature = sig } + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *DetachShardsRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.RepeatedBytesSize(1, x.Shard_ID) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *DetachShardsRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *DetachShardsRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *DetachShardsRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *DetachShardsRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *DetachShardsRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *DetachShardsRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *DetachShardsResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *DetachShardsResponse_Body) StableMarshal(buf []byte) []byte { + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *DetachShardsResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *DetachShardsResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *DetachShardsResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *DetachShardsResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *DetachShardsResponse) SetSignature(sig *Signature) { + x.Signature = sig +} diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index 89337323f9..69029ccb30 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -37,6 +37,7 @@ const ( ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" ControlService_ListTargetsLocalOverrides_FullMethodName = "/control.ControlService/ListTargetsLocalOverrides" ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" + ControlService_DetachShards_FullMethodName = "/control.ControlService/DetachShards" ) // ControlServiceClient is the client API for ControlService service. @@ -80,6 +81,8 @@ type ControlServiceClient interface { ListTargetsLocalOverrides(ctx context.Context, in *ListTargetsLocalOverridesRequest, opts ...grpc.CallOption) (*ListTargetsLocalOverridesResponse, error) // Flush objects from write-cache and move it to degraded read only mode. SealWriteCache(ctx context.Context, in *SealWriteCacheRequest, opts ...grpc.CallOption) (*SealWriteCacheResponse, error) + // DetachShards detaches and closes shards. + DetachShards(ctx context.Context, in *DetachShardsRequest, opts ...grpc.CallOption) (*DetachShardsResponse, error) } type controlServiceClient struct { @@ -252,6 +255,15 @@ func (c *controlServiceClient) SealWriteCache(ctx context.Context, in *SealWrite return out, nil } +func (c *controlServiceClient) DetachShards(ctx context.Context, in *DetachShardsRequest, opts ...grpc.CallOption) (*DetachShardsResponse, error) { + out := new(DetachShardsResponse) + err := c.cc.Invoke(ctx, ControlService_DetachShards_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ControlServiceServer is the server API for ControlService service. // All implementations should embed UnimplementedControlServiceServer // for forward compatibility @@ -293,6 +305,8 @@ type ControlServiceServer interface { ListTargetsLocalOverrides(context.Context, *ListTargetsLocalOverridesRequest) (*ListTargetsLocalOverridesResponse, error) // Flush objects from write-cache and move it to degraded read only mode. SealWriteCache(context.Context, *SealWriteCacheRequest) (*SealWriteCacheResponse, error) + // DetachShards detaches and closes shards. + DetachShards(context.Context, *DetachShardsRequest) (*DetachShardsResponse, error) } // UnimplementedControlServiceServer should be embedded to have forward compatible implementations. @@ -353,6 +367,9 @@ func (UnimplementedControlServiceServer) ListTargetsLocalOverrides(context.Conte func (UnimplementedControlServiceServer) SealWriteCache(context.Context, *SealWriteCacheRequest) (*SealWriteCacheResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SealWriteCache not implemented") } +func (UnimplementedControlServiceServer) DetachShards(context.Context, *DetachShardsRequest) (*DetachShardsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DetachShards not implemented") +} // UnsafeControlServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ControlServiceServer will @@ -689,6 +706,24 @@ func _ControlService_SealWriteCache_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _ControlService_DetachShards_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DetachShardsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).DetachShards(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_DetachShards_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).DetachShards(ctx, req.(*DetachShardsRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ControlService_ServiceDesc is the grpc.ServiceDesc for ControlService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -768,6 +803,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "SealWriteCache", Handler: _ControlService_SealWriteCache_Handler, }, + { + MethodName: "DetachShards", + Handler: _ControlService_DetachShards_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pkg/services/control/service.proto", From 9ba48c582dd803c8252a7e8b63f77eed5054acf6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 30 Jan 2024 18:18:58 +0300 Subject: [PATCH 0310/1413] [#917] engine: Allow to detach shards Signed-off-by: Dmitrii Stepanov --- .../modules/control/detach_shards.go | 49 ++++++++++ cmd/frostfs-cli/modules/control/shards.go | 2 + .../modules/control/shards_set_mode.go | 10 +- pkg/local_object_storage/engine/shards.go | 97 +++++++++++++++++++ .../engine/shards_test.go | 20 ++++ pkg/services/control/rpc.go | 20 ++++ pkg/services/control/server/detach_shards.go | 37 +++++++ 7 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 cmd/frostfs-cli/modules/control/detach_shards.go create mode 100644 pkg/services/control/server/detach_shards.go diff --git a/cmd/frostfs-cli/modules/control/detach_shards.go b/cmd/frostfs-cli/modules/control/detach_shards.go new file mode 100644 index 0000000000..5e5b60c3de --- /dev/null +++ b/cmd/frostfs-cli/modules/control/detach_shards.go @@ -0,0 +1,49 @@ +package control + +import ( + rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "github.com/spf13/cobra" +) + +var shardsDetachCmd = &cobra.Command{ + Use: "detach", + Short: "Detach and close the shards", + Long: "Detach and close the shards", + Run: shardsDetach, +} + +func shardsDetach(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + req := &control.DetachShardsRequest{ + Body: &control.DetachShardsRequest_Body{ + Shard_ID: getShardIDListFromIDFlag(cmd, false), + }, + } + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.DetachShardsResponse + var err error + err = cli.ExecRaw(func(client *rawclient.Client) error { + resp, err = control.DetachShards(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + cmd.Println("Shard mode update request successfully sent.") +} + +func initControlShardsDetachCmd() { + initControlFlags(shardsDetachCmd) + + flags := shardsDetachCmd.Flags() + flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") +} diff --git a/cmd/frostfs-cli/modules/control/shards.go b/cmd/frostfs-cli/modules/control/shards.go index 6d3ef420c3..d8198c426f 100644 --- a/cmd/frostfs-cli/modules/control/shards.go +++ b/cmd/frostfs-cli/modules/control/shards.go @@ -18,6 +18,7 @@ func initControlShardsCmd() { shardsCmd.AddCommand(flushCacheCmd) shardsCmd.AddCommand(doctorCmd) shardsCmd.AddCommand(writecacheShardCmd) + shardsCmd.AddCommand(shardsDetachCmd) initControlShardsListCmd() initControlSetShardModeCmd() @@ -26,4 +27,5 @@ func initControlShardsCmd() { initControlFlushCacheCmd() initControlDoctorCmd() initControlShardsWritecacheCmd() + initControlShardsDetachCmd() } diff --git a/cmd/frostfs-cli/modules/control/shards_set_mode.go b/cmd/frostfs-cli/modules/control/shards_set_mode.go index 78f7689656..1c87b405b0 100644 --- a/cmd/frostfs-cli/modules/control/shards_set_mode.go +++ b/cmd/frostfs-cli/modules/control/shards_set_mode.go @@ -145,9 +145,17 @@ func getShardIDList(cmd *cobra.Command) [][]byte { return nil } + return getShardIDListFromIDFlag(cmd, true) +} + +func getShardIDListFromIDFlag(cmd *cobra.Command, withAllFlag bool) [][]byte { sidList, _ := cmd.Flags().GetStringSlice(shardIDFlag) if len(sidList) == 0 { - commonCmd.ExitOnErr(cmd, "", fmt.Errorf("either --%s or --%s flag must be provided", shardIDFlag, shardAllFlag)) + if withAllFlag { + commonCmd.ExitOnErr(cmd, "", fmt.Errorf("either --%s or --%s flag must be provided", shardIDFlag, shardAllFlag)) + } else { + commonCmd.ExitOnErr(cmd, "", fmt.Errorf("--%s flag value must be provided", shardIDFlag)) + } } // We can sort the ID list and perform this check without additional allocations, diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index bd25dde595..83fa4f5cbe 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -2,7 +2,9 @@ package engine import ( "context" + "errors" "fmt" + "sync" "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -14,6 +16,7 @@ import ( "github.com/google/uuid" "github.com/panjf2000/ants/v2" "go.uber.org/zap" + "golang.org/x/sync/errgroup" ) var errShardNotFound = logicerr.New("shard not found") @@ -344,6 +347,100 @@ func (e *StorageEngine) HandleNewEpoch(ctx context.Context, epoch uint64) { } } +func (e *StorageEngine) DetachShards(ids []*shard.ID) error { + if len(ids) == 0 { + return logicerr.New("ids must be non-empty") + } + + deletedShards, err := e.deleteShards(ids) + if err != nil { + return err + } + + return e.closeShards(deletedShards) +} + +// closeShards closes deleted shards. Tries to close all shards. +// Returns single error with joined shard errors. +func (e *StorageEngine) closeShards(deletedShards []hashedShard) error { + var multiErr error + var multiErrGuard sync.Mutex + var eg errgroup.Group + for _, sh := range deletedShards { + sh := sh + eg.Go(func() error { + err := sh.SetMode(mode.Disabled) + if err != nil { + e.log.Error(logs.EngineCouldNotChangeShardModeToDisabled, + zap.Stringer("id", sh.ID()), + zap.Error(err), + ) + multiErrGuard.Lock() + multiErr = errors.Join(multiErr, fmt.Errorf("could not change shard (id:%s) mode to disabled: %w", sh.ID(), err)) + multiErrGuard.Unlock() + } + + err = sh.Close() + if err != nil { + e.log.Error(logs.EngineCouldNotCloseRemovedShard, + zap.Stringer("id", sh.ID()), + zap.Error(err), + ) + multiErrGuard.Lock() + multiErr = errors.Join(multiErr, fmt.Errorf("could not close removed shard (id:%s): %w", sh.ID(), err)) + multiErrGuard.Unlock() + } + return nil + }) + } + if err := eg.Wait(); err != nil { + return err + } + return multiErr +} + +// deleteShards deletes shards with specified ids from engine shard list +// and releases all engine resources associated with shards. +// Returns deleted shards or error if some shard could not be deleted. +func (e *StorageEngine) deleteShards(ids []*shard.ID) ([]hashedShard, error) { + ss := make([]hashedShard, 0, len(ids)) + + e.mtx.Lock() + defer e.mtx.Unlock() + + for _, id := range ids { + idStr := id.String() + sh, found := e.shards[idStr] + if !found { + return nil, errShardNotFound + } + ss = append(ss, sh) + } + + if len(ss) == len(e.shards) { + return nil, logicerr.New("could not delete all the shards") + } + + for _, sh := range ss { + idStr := sh.ID().String() + + sh.DeleteShardMetrics() + + delete(e.shards, idStr) + + pool, ok := e.shardPools[idStr] + if ok { + pool.Release() + delete(e.shardPools, idStr) + } + + e.log.Info(logs.EngineShardHasBeenRemoved, + zap.String("id", idStr)) + } + + return ss, nil +} + func (s hashedShard) Hash() uint64 { return s.hash } diff --git a/pkg/local_object_storage/engine/shards_test.go b/pkg/local_object_storage/engine/shards_test.go index f2896d5578..3bb602ce40 100644 --- a/pkg/local_object_storage/engine/shards_test.go +++ b/pkg/local_object_storage/engine/shards_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "github.com/stretchr/testify/require" ) @@ -42,3 +44,21 @@ func TestRemoveShard(t *testing.T) { require.True(t, ok != removed) } } + +func TestDisableShards(t *testing.T) { + t.Parallel() + + const numOfShards = 2 + + te := testNewEngine(t).setShardsNum(t, numOfShards) + e, ids := te.engine, te.shardIDs + defer func() { require.NoError(t, e.Close(context.Background())) }() + + require.ErrorAs(t, e.DetachShards(ids), new(logicerr.Logical)) + require.ErrorAs(t, e.DetachShards(nil), new(logicerr.Logical)) + require.ErrorAs(t, e.DetachShards([]*shard.ID{}), new(logicerr.Logical)) + + require.NoError(t, e.DetachShards([]*shard.ID{ids[0]})) + + require.Equal(t, 1, len(e.shards)) +} diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 24b20f873e..877bb63c2a 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -26,6 +26,7 @@ const ( rpcRemoveChainLocalOverride = "RemoveChainLocalOverride" rpcSealWriteCache = "SealWriteCache" rpcListTargetsLocalOverrides = "ListTargetsLocalOverrides" + rpcDetachShards = "DetachShards" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -292,3 +293,22 @@ func SealWriteCache(cli *client.Client, req *SealWriteCacheRequest, opts ...clie return wResp.message, nil } + +// DetachShards executes ControlService.DetachShards RPC. +func DetachShards( + cli *client.Client, + req *DetachShardsRequest, + opts ...client.CallOption, +) (*DetachShardsResponse, error) { + wResp := newResponseWrapper[DetachShardsResponse]() + + wReq := &requestWrapper{ + m: req, + } + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcDetachShards), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.message, nil +} diff --git a/pkg/services/control/server/detach_shards.go b/pkg/services/control/server/detach_shards.go new file mode 100644 index 0000000000..c8bea97b43 --- /dev/null +++ b/pkg/services/control/server/detach_shards.go @@ -0,0 +1,37 @@ +package control + +import ( + "context" + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Server) DetachShards(_ context.Context, req *control.DetachShardsRequest) (*control.DetachShardsResponse, error) { + err := s.isValidRequest(req) + if err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + shardIDs := s.getShardIDList(req.GetBody().GetShard_ID()) + + if err := s.s.DetachShards(shardIDs); err != nil { + if errors.As(err, new(logicerr.Logical)) { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + return nil, status.Error(codes.Internal, err.Error()) + } + + resp := &control.DetachShardsResponse{ + Body: &control.DetachShardsResponse_Body{}, + } + + if err = SignMessage(s.key, resp); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return resp, nil +} From 20b4447df77d03d8468442febdee24632013d3b6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 30 Jan 2024 18:32:55 +0300 Subject: [PATCH 0311/1413] [#917] docs: Extend shard mode description Add shards detach details. Signed-off-by: Dmitrii Stepanov --- docs/shard-modes.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/shard-modes.md b/docs/shard-modes.md index 7fca33d093..3abc26a603 100644 --- a/docs/shard-modes.md +++ b/docs/shard-modes.md @@ -46,3 +46,9 @@ Shard can automatically switch to a `degraded-read-only` mode in 3 cases: 1. If the metabase was not available or couldn't be opened/initialized during shard startup. 2. If shard error counter exceeds threshold. 3. If the metabase couldn't be reopened during SIGHUP handling. + +# Detach shard + +To detach a shard use `frostfs-cli control shards detach` command. This command removes the shards from the storage +engine and closes all resources associated with the shards. +Limitation: `SIGHUP` or storage node restart lead to detached shard will be again online. \ No newline at end of file From d7838790c654da64cbafd2a7017e7812108a94e1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 31 Jan 2024 13:29:26 +0300 Subject: [PATCH 0312/1413] [#917] dev: Extend launch.json example Add storage and dev wallets to control authorized keys list. Signed-off-by: Dmitrii Stepanov --- dev/.vscode-example/launch.json | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/.vscode-example/launch.json b/dev/.vscode-example/launch.json index 07d39482e7..459350145a 100644 --- a/dev/.vscode-example/launch.json +++ b/dev/.vscode-example/launch.json @@ -47,6 +47,7 @@ "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8080", "FROSTFS_GRPC_0_ENDPOINT":"127.0.0.1:8080", "FROSTFS_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8081", + "FROSTFS_CONTROL_AUTHORIZED_KEYS":"031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a", "FROSTFS_NODE_ATTRIBUTE_0":"User-Agent:FrostFS/dev", "FROSTFS_NODE_ATTRIBUTE_1":"UN-LOCODE:RU MOW", "FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/.frostfs-node-state", From b1a1b2107dafb4b76cc9d1595f21a5b2037be158 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 12 Jan 2024 17:44:27 +0300 Subject: [PATCH 0313/1413] [#909] cli: Make add-rule and list-rules recieve namespace param Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 23 ++----- cmd/frostfs-cli/modules/control/get_rule.go | 19 ++---- cmd/frostfs-cli/modules/control/list_rules.go | 65 +++++++++++++++---- .../modules/control/remove_rule.go | 19 ++---- 4 files changed, 67 insertions(+), 59 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 7e0805cd16..0f5ac11f3e 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -1,16 +1,13 @@ package control import ( - "crypto/sha256" "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) @@ -33,6 +30,8 @@ var addRuleCmd = &cobra.Command{ func addRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) + target := parseTarget(cmd) + chainID, _ := cmd.Flags().GetString(chainIDFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) @@ -44,13 +43,6 @@ func addRule(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) } - var cnr cid.ID - cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) - commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) - - rawCID := make([]byte, sha256.Size) - cnr.Encode(rawCID) - rule, _ := cmd.Flags().GetStringArray(ruleFlag) chain := new(apechain.Chain) @@ -63,11 +55,8 @@ func addRule(cmd *cobra.Command, _ []string) { req := &control.AddChainLocalOverrideRequest{ Body: &control.AddChainLocalOverrideRequest_Body{ - Target: &control.ChainTarget{ - Type: control.ChainTarget_CONTAINER, - Name: cidStr, - }, - Chain: serializedChain, + Target: target, + Chain: serializedChain, }, } @@ -91,8 +80,10 @@ func initControlAddRuleCmd() { initControlFlags(addRuleCmd) ff := addRuleCmd.Flags() - ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) ff.StringArray(ruleFlag, []string{}, "Rule statement") ff.String(chainIDFlag, "", "Assign ID to the parsed chain") + ff.String(targetNameFlag, "", targetNameDesc) + ff.String(targetTypeFlag, "", targetTypeDesc) + _ = addRuleCmd.MarkFlagRequired(targetTypeFlag) ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") } diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index e2271c4468..050cf165c0 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -1,16 +1,13 @@ package control import ( - "crypto/sha256" "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) @@ -25,12 +22,7 @@ var getRuleCmd = &cobra.Command{ func getRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) - var cnr cid.ID - cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) - commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) - - rawCID := make([]byte, sha256.Size) - cnr.Encode(rawCID) + target := parseTarget(cmd) chainID, _ := cmd.Flags().GetString(chainIDFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) @@ -43,10 +35,7 @@ func getRule(cmd *cobra.Command, _ []string) { req := &control.GetChainLocalOverrideRequest{ Body: &control.GetChainLocalOverrideRequest_Body{ - Target: &control.ChainTarget{ - Name: cidStr, - Type: control.ChainTarget_CONTAINER, - }, + Target: target, ChainId: []byte(chainID), }, } @@ -74,7 +63,9 @@ func initControGetRuleCmd() { initControlFlags(getRuleCmd) ff := getRuleCmd.Flags() - ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + ff.String(targetNameFlag, "", targetNameDesc) + ff.String(targetTypeFlag, "", targetTypeDesc) + _ = getRuleCmd.MarkFlagRequired(targetTypeFlag) ff.String(chainIDFlag, "", "Chain id") ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") } diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index c62651767e..31f5ff959f 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -1,16 +1,17 @@ package control import ( - "crypto/sha256" + "fmt" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "github.com/nspcc-dev/neo-go/cli/input" "github.com/spf13/cobra" ) @@ -21,22 +22,56 @@ var listRulesCmd = &cobra.Command{ Run: listRules, } +const ( + defaultNamespace = "root" + namespaceTarget = "namespace" + containerTarget = "container" +) + +const ( + targetNameFlag = "target-name" + targetNameDesc = "Resource name in APE resource name format" + targetTypeFlag = "target-type" + targetTypeDesc = "Resource type(container/namespace)" +) + +func parseTarget(cmd *cobra.Command) *control.ChainTarget { + typ, _ := cmd.Flags().GetString(targetTypeFlag) + name, _ := cmd.Flags().GetString(targetNameFlag) + switch typ { + case namespaceTarget: + if name == "" { + ln, err := input.ReadLine(fmt.Sprintf("Target name is not set. Confirm to use %s namespace (n|Y)> ", defaultNamespace)) + commonCmd.ExitOnErr(cmd, "read line error: %w", err) + ln = strings.ToLower(ln) + if len(ln) > 0 && (ln[0] == 'n') { + commonCmd.ExitOnErr(cmd, "read namespace error: %w", fmt.Errorf("setting default value was declined")) + } + name = defaultNamespace + } + return &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_NAMESPACE, + } + case containerTarget: + var cnr cid.ID + commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name)) + return &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_CONTAINER, + } + default: + commonCmd.ExitOnErr(cmd, "read target type error: %w", fmt.Errorf("unknown target type")) + } + return nil +} + func listRules(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) - var cnr cid.ID - cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) - commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) - - rawCID := make([]byte, sha256.Size) - cnr.Encode(rawCID) - req := &control.ListChainLocalOverridesRequest{ Body: &control.ListChainLocalOverridesRequest_Body{ - Target: &control.ChainTarget{ - Name: cidStr, - Type: control.ChainTarget_CONTAINER, - }, + Target: parseTarget(cmd), }, } @@ -71,5 +106,7 @@ func initControlListRulesCmd() { initControlFlags(listRulesCmd) ff := listRulesCmd.Flags() - ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + ff.String(targetNameFlag, "", targetNameDesc) + ff.String(targetTypeFlag, "", targetTypeDesc) + _ = listRulesCmd.MarkFlagRequired(targetTypeFlag) } diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index 612ab7d0af..1c3be375f9 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -1,15 +1,12 @@ package control import ( - "crypto/sha256" "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) @@ -28,13 +25,6 @@ var removeRuleCmd = &cobra.Command{ func removeRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) - var cnr cid.ID - cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) - commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) - - rawCID := make([]byte, sha256.Size) - cnr.Encode(rawCID) - chainID, _ := cmd.Flags().GetString(chainIDFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) @@ -48,10 +38,7 @@ func removeRule(cmd *cobra.Command, _ []string) { req := &control.RemoveChainLocalOverrideRequest{ Body: &control.RemoveChainLocalOverrideRequest_Body{ - Target: &control.ChainTarget{ - Name: cidStr, - Type: control.ChainTarget_CONTAINER, - }, + Target: parseTarget(cmd), ChainId: chainIDRaw, }, } @@ -81,7 +68,9 @@ func initControlRemoveRuleCmd() { initControlFlags(removeRuleCmd) ff := removeRuleCmd.Flags() - ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + ff.String(targetNameFlag, "", targetNameDesc) + ff.String(targetTypeFlag, "", targetTypeDesc) + _ = removeRuleCmd.MarkFlagRequired(targetTypeFlag) ff.String(chainIDFlag, "", "Chain id") ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") } From a6c9a337cd1177ac07a066b6b29de0ae5ef88e5c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 6 Feb 2024 20:29:39 +0300 Subject: [PATCH 0314/1413] [#965] morph: Get rid of container.List invocations ContainersOf() is better in almost every aspect, besides creating a session when the containers number is between 1024 and 2048 (prefetch script does limited unwrapping). Making List() private helps to ensure it is no longer used and can be safely removed in future. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/container.go | 6 +++--- pkg/morph/client/container/containers_of.go | 2 +- pkg/morph/client/container/list.go | 4 ++-- pkg/services/container/morph/executor.go | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 28f2710757..d566c0af36 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -210,7 +210,7 @@ type morphContainerReader struct { src containerCore.Source lister interface { - List(*user.ID) ([]cid.ID, error) + ContainersOf(*user.ID) ([]cid.ID, error) } } @@ -226,8 +226,8 @@ func (x *morphContainerReader) GetEACL(id cid.ID) (*containerCore.EACL, error) { return x.eacl.GetEACL(id) } -func (x *morphContainerReader) List(id *user.ID) ([]cid.ID, error) { - return x.lister.List(id) +func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) { + return x.lister.ContainersOf(id) } type morphContainerWriter struct { diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go index ce127335d8..c4db0fe6e8 100644 --- a/pkg/morph/client/container/containers_of.go +++ b/pkg/morph/client/container/containers_of.go @@ -53,7 +53,7 @@ func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { err := c.client.Morph().TestInvokeIterator(cb, batchSize, cnrHash, containersOfMethod, rawID) if err != nil { if errors.Is(err, unwrap.ErrNoSessionID) { - return c.List(idUser) + return c.list(idUser) } return nil, err } diff --git a/pkg/morph/client/container/list.go b/pkg/morph/client/container/list.go index 8f165f4b1e..6fed46c1ad 100644 --- a/pkg/morph/client/container/list.go +++ b/pkg/morph/client/container/list.go @@ -8,13 +8,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) -// List returns a list of container identifiers belonging +// list returns a list of container identifiers belonging // to the specified user of FrostFS system. The list is composed // through Container contract call. // // Returns the identifiers of all FrostFS containers if pointer // to user identifier is nil. -func (c *Client) List(idUser *user.ID) ([]cid.ID, error) { +func (c *Client) list(idUser *user.ID) ([]cid.ID, error) { var rawID []byte if idUser != nil { diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index dec022219e..f1217705ee 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -26,10 +26,10 @@ type Reader interface { containercore.Source containercore.EACLSource - // List returns a list of container identifiers belonging + // ContainersOf returns a list of container identifiers belonging // to the specified user of FrostFS system. Returns the identifiers // of all FrostFS containers if pointer to owner identifier is nil. - List(*user.ID) ([]cid.ID, error) + ContainersOf(*user.ID) ([]cid.ID, error) } // Writer is an interface of container storage updater. @@ -187,7 +187,7 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) return nil, fmt.Errorf("invalid user ID: %w", err) } - cnrs, err := s.rdr.List(&id) + cnrs, err := s.rdr.ContainersOf(&id) if err != nil { return nil, err } From 6010dfdf3de79a81e70adfad5cd4e0d2c678904b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 8 Feb 2024 10:01:27 +0300 Subject: [PATCH 0315/1413] [#969] policer: Make error skip thread-safe Introduces in afd2ba9a66. Refs #914 Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/process.go | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index df4f0c4c70..0f1198f8d7 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -3,6 +3,7 @@ package policer import ( "context" "errors" + "sync" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -35,9 +36,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { p.log.Warn(logs.PolicerFailureAtObjectSelectForReplication, zap.Error(err)) } - // contains all errors logged in this iteration for each container - cnrErrSkip := make(map[cid.ID][]error) - + skipMap := newSkipMap() for i := range addrs { select { case <-ctx.Done(): @@ -59,12 +58,10 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { if p.objsInWork.add(addr.Address) { err := p.processObject(ctx, addr) - if err != nil && !skipLog(cnrErrSkip[addr.Address.Container()], err) { + if err != nil && !skipMap.addSeenError(addr.Address.Container(), err) { p.log.Error(logs.PolicerUnableToProcessObj, zap.Stringer("object", addr.Address), zap.String("error", err.Error())) - - cnrErrSkip[addr.Address.Container()] = append(cnrErrSkip[addr.Address.Container()], err) } p.cache.Add(addr.Address, time.Now()) p.objsInWork.remove(addr.Address) @@ -79,11 +76,28 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { } } -func skipLog(errs []error, err error) bool { - for _, e := range errs { +type errMap struct { + sync.Mutex + skipMap map[cid.ID][]error +} + +func newSkipMap() *errMap { + return &errMap{ + skipMap: make(map[cid.ID][]error), + } +} + +// addSeenError marks err as seen error for the container. +// Returns true is the error has already been added. +func (m *errMap) addSeenError(cnr cid.ID, err error) bool { + m.Lock() + defer m.Unlock() + + for _, e := range m.skipMap[cnr] { if errors.Is(err, e) { return true } } + m.skipMap[cnr] = append(m.skipMap[cnr], err) return false } From c3fa902780975b129e1d85991016634403575c88 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 8 Feb 2024 10:05:02 +0300 Subject: [PATCH 0316/1413] [#969] policer: Restrict the number of remembered errors Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/process.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index 0f1198f8d7..a5ebb00101 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -98,6 +98,13 @@ func (m *errMap) addSeenError(cnr cid.ID, err error) bool { return true } } - m.skipMap[cnr] = append(m.skipMap[cnr], err) + + // Restrict list length to avoid possible OOM if some random error is added in future. + const maxErrListLength = 10 + + lst := m.skipMap[cnr] + if len(lst) < maxErrListLength { + m.skipMap[cnr] = append(lst, err) + } return false } From cfc5ce7853276b0d86ba645eaa2ad186b406b98c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 6 Feb 2024 19:25:24 +0300 Subject: [PATCH 0317/1413] [#964] metabase: Drop GC marks if object not found GC inhumes expired locks and tombstones on all the shards. So it could be GC mark without object. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete.go | 13 ++++++-- .../metabase/delete_test.go | 31 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 484dbe41b6..8e5557636a 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -254,9 +254,18 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter // unmarshal object, work only with physically stored (raw == true) objects obj, err := db.get(tx, addr, key, false, true, currEpoch) if err != nil { + if client.IsErrObjectNotFound(err) { + addrKey = addressKey(addr, key) + if garbageBKT != nil { + err := garbageBKT.Delete(addrKey) + if err != nil { + return deleteSingleResult{}, fmt.Errorf("could not remove from garbage bucket: %w", err) + } + } + return deleteSingleResult{}, nil + } var siErr *objectSDK.SplitInfoError - - if client.IsErrObjectNotFound(err) || errors.As(err, &siErr) { + if errors.As(err, &siErr) { // if object is virtual (parent) then do nothing, it will be deleted with last child return deleteSingleResult{}, nil } diff --git a/pkg/local_object_storage/metabase/delete_test.go b/pkg/local_object_storage/metabase/delete_test.go index 5a52868d3a..649c0ebe3c 100644 --- a/pkg/local_object_storage/metabase/delete_test.go +++ b/pkg/local_object_storage/metabase/delete_test.go @@ -182,6 +182,37 @@ func TestDelete(t *testing.T) { require.Equal(t, 0, len(addrs)) } +func TestDeleteDropsGCMarkIfObjectNotFound(t *testing.T) { + db := newDB(t, meta.WithEpochState(epochState{currEpoch})) + defer func() { require.NoError(t, db.Close()) }() + + addr := oidtest.Address() + + var prm meta.InhumePrm + prm.SetAddresses(addr) + prm.SetGCMark() + _, err := db.Inhume(context.Background(), prm) + require.NoError(t, err) + + var garbageCount int + var itPrm meta.GarbageIterationPrm + itPrm.SetHandler(func(g meta.GarbageObject) error { + garbageCount++ + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + require.Equal(t, 1, garbageCount) + + var delPrm meta.DeletePrm + delPrm.SetAddresses(addr) + _, err = db.Delete(context.Background(), delPrm) + require.NoError(t, err) + + garbageCount = 0 + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + require.Equal(t, 0, garbageCount) +} + func metaDelete(db *meta.DB, addrs ...oid.Address) error { var deletePrm meta.DeletePrm deletePrm.SetAddresses(addrs...) From 053a195ac2812b2b3d6c1c865cf564c027a30f9e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 7 Feb 2024 19:44:28 +0300 Subject: [PATCH 0318/1413] [#968] adm: Allow concurrent epoch ticks Previous fix was incomplete, there are two possible places for this error to occur. Refs #592 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/epoch.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index 39dbb0caf0..e491e8b8fe 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -37,18 +37,14 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return err } - if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil { - return err + if err = wCtx.sendConsensusTx(bw.Bytes()); err == nil { + err = wCtx.awaitTx() } - - if err := wCtx.awaitTx(); err != nil { - if strings.Contains(err.Error(), "invalid epoch") { - cmd.Println("Epoch has already ticked.") - return nil - } - return err + if err != nil && strings.Contains(err.Error(), "invalid epoch") { + cmd.Println("Epoch has already ticked.") + return nil } - return nil + return err } func emitNewEpochCall(bw *io.BufBinWriter, wCtx *initializeContext, nmHash util.Uint160) error { From cbfeb724662ccc8c041286cacbf8ca18df2eedf7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 2 Feb 2024 20:14:47 +0300 Subject: [PATCH 0319/1413] [#956] policer: Remove WithMaxCapacity option We already provide the pool and this argument is used only for preallocation. No functional changes. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/object.go | 1 - pkg/services/policer/option.go | 10 ---------- pkg/services/policer/policer.go | 2 +- pkg/services/policer/policer_test.go | 8 ++++++++ 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 5c82f0dcc1..7f1d094fd4 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -263,7 +263,6 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl ) } }), - policer.WithMaxCapacity(c.cfgObject.pool.replicatorPoolSize), policer.WithPool(c.cfgObject.pool.replication), policer.WithMetrics(c.metricsCollector.PolicerMetrics()), ) diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index fe47555c49..92cf83a842 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -64,8 +64,6 @@ type cfg struct { taskPool *ants.Pool - maxCapacity int - batchSize, cacheSize uint32 rebalanceFreq, evictDuration, sleepDuration time.Duration @@ -158,14 +156,6 @@ func WithRedundantCopyCallback(cb RedundantCopyCallback) Option { } } -// WithMaxCapacity returns option to set max capacity -// that can be set to the pool. -func WithMaxCapacity(capacity int) Option { - return func(c *cfg) { - c.maxCapacity = capacity - } -} - // WithPool returns option to set pool for // policy and replication operations. func WithPool(p *ants.Pool) Option { diff --git a/pkg/services/policer/policer.go b/pkg/services/policer/policer.go index a68b194d4b..363c0b922c 100644 --- a/pkg/services/policer/policer.go +++ b/pkg/services/policer/policer.go @@ -66,7 +66,7 @@ func New(opts ...Option) *Policer { cfg: c, cache: cache, objsInWork: &objectsInWork{ - objs: make(map[oid.Address]struct{}, c.maxCapacity), + objs: make(map[oid.Address]struct{}, c.taskPool.Cap()), }, } } diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index c73d33629e..41abeb3849 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -239,6 +239,7 @@ func TestProcessObject(t *testing.T) { gotReplicateTo = append(gotReplicateTo, int(node.PublicKey()[0])) } })), + WithPool(testPool(t)), ) addrWithType := objectcore.AddressWithType{ @@ -276,6 +277,7 @@ func TestProcessObjectError(t *testing.T) { p := New( WithContainerSource(source), WithBuryFunc(buryFn), + WithPool(testPool(t)), ) addrWithType := objectcore.AddressWithType{ @@ -348,6 +350,12 @@ func TestIteratorContract(t *testing.T) { }, it.calls) } +func testPool(t *testing.T) *ants.Pool { + pool, err := ants.NewPool(4) + require.NoError(t, err) + return pool +} + type nextResult struct { objs []objectcore.AddressWithType err error From edbe06e07ea0fab2bd3edace784aa338dcaf48d1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 2 Feb 2024 20:57:49 +0300 Subject: [PATCH 0320/1413] [#956] policer/test: Reuse testPool helper Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/policer_test.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 41abeb3849..50f206fd9a 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -48,16 +48,12 @@ func TestBuryObjectWithoutContainer(t *testing.T) { return nil } - // Task pool - pool, err := ants.NewPool(4) - require.NoError(t, err) - // Policer instance p := New( WithKeySpaceIterator(&sliceKeySpaceIterator{objs: objs}), WithContainerSource(containerSrc), WithBuryFunc(buryFn), - WithPool(pool), + WithPool(testPool(t)), ) ctx, cancel := context.WithCancel(context.Background()) @@ -298,9 +294,6 @@ func TestIteratorContract(t *testing.T) { return nil } - pool, err := ants.NewPool(4) - require.NoError(t, err) - it := &predefinedIterator{ scenario: []nextResult{ {objs, nil}, @@ -326,7 +319,7 @@ func TestIteratorContract(t *testing.T) { WithKeySpaceIterator(it), WithContainerSource(containerSrc), WithBuryFunc(buryFn), - WithPool(pool), + WithPool(testPool(t)), func(c *cfg) { c.sleepDuration = time.Millisecond }, From 426cf58b986dbf6c11e370fbdd9ca2788d0832d8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 2 Feb 2024 20:17:04 +0300 Subject: [PATCH 0321/1413] [#956] node: Remove pool sizes from config struct They are available through the pool methods and unused outside of the function that sets them. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 29582c7821..e5881cc2c7 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -632,14 +632,8 @@ type cfgAccessPolicyEngine struct { type cfgObjectRoutines struct { putRemote *ants.Pool - putRemoteCapacity int - putLocal *ants.Pool - putLocalCapacity int - - replicatorPoolSize int - replication *ants.Pool } @@ -1094,20 +1088,20 @@ func initObjectPool(cfg *config.Config) (pool cfgObjectRoutines) { optNonBlocking := ants.WithNonblocking(true) - pool.putRemoteCapacity = objectconfig.Put(cfg).PoolSizeRemote() - pool.putRemote, err = ants.NewPool(pool.putRemoteCapacity, optNonBlocking) + putRemoteCapacity := objectconfig.Put(cfg).PoolSizeRemote() + pool.putRemote, err = ants.NewPool(putRemoteCapacity, optNonBlocking) fatalOnErr(err) - pool.putLocalCapacity = objectconfig.Put(cfg).PoolSizeLocal() - pool.putLocal, err = ants.NewPool(pool.putLocalCapacity, optNonBlocking) + putLocalCapacity := objectconfig.Put(cfg).PoolSizeLocal() + pool.putLocal, err = ants.NewPool(putLocalCapacity, optNonBlocking) fatalOnErr(err) - pool.replicatorPoolSize = replicatorconfig.PoolSize(cfg) - if pool.replicatorPoolSize <= 0 { - pool.replicatorPoolSize = pool.putRemoteCapacity + replicatorPoolSize := replicatorconfig.PoolSize(cfg) + if replicatorPoolSize <= 0 { + replicatorPoolSize = putRemoteCapacity } - pool.replication, err = ants.NewPool(pool.replicatorPoolSize) + pool.replication, err = ants.NewPool(replicatorPoolSize) fatalOnErr(err) return pool From 805862f4b726c13e57225c472e4992eab29a37aa Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 2 Feb 2024 20:28:05 +0300 Subject: [PATCH 0322/1413] [#956] node: Allow to reload goroutine pool sizes Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 23 +++++++++++++++++++++++ internal/logs/logs.go | 1 + 2 files changed, 24 insertions(+) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e5881cc2c7..c41863ecd2 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1235,6 +1235,7 @@ func (c *cfg) reloadConfig(ctx context.Context) { setRuntimeParameters(c) return nil }}) + components = append(components, dCmp{"pools", c.reloadPools}) components = append(components, dCmp{"tracing", func() error { updated, err := tracing.Setup(ctx, *tracingconfig.ToTracingConfig(c.appCfg)) if updated { @@ -1279,6 +1280,28 @@ func (c *cfg) reloadConfig(ctx context.Context) { c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) } +func (c *cfg) reloadPools() error { + newSize := objectconfig.Put(c.appCfg).PoolSizeLocal() + c.reloadPool(c.cfgObject.pool.putLocal, newSize, "object.put.local_pool_size") + + newSize = objectconfig.Put(c.appCfg).PoolSizeRemote() + c.reloadPool(c.cfgObject.pool.putRemote, newSize, "object.put.remote_pool_size") + + newSize = replicatorconfig.PoolSize(c.appCfg) + c.reloadPool(c.cfgObject.pool.replication, newSize, "replicator.pool_size") + + return nil +} + +func (c *cfg) reloadPool(p *ants.Pool, newSize int, name string) { + oldSize := p.Cap() + if oldSize != newSize { + c.log.Info(logs.FrostFSNodePoolConfigurationUpdate, zap.String("field", name), + zap.Int("old", oldSize), zap.Int("new", newSize)) + p.Tune(newSize) + } +} + func (c *cfg) reloadAppConfig() error { unlock := c.LockAppConfigExclusive() defer unlock() diff --git a/internal/logs/logs.go b/internal/logs/logs.go index e81976a325..c3d2e51504 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -451,6 +451,7 @@ const ( FrostFSNodeLoggerConfigurationPreparation = "logger configuration preparation" FrostFSNodeTracingConfigationUpdated = "tracing configation updated" FrostFSNodeStorageEngineConfigurationUpdate = "storage engine configuration update" + FrostFSNodePoolConfigurationUpdate = "adjust pool configuration" FrostFSNodeUpdatedConfigurationApplying = "updated configuration applying" FrostFSNodeConfigurationHasBeenReloadedSuccessfully = "configuration has been reloaded successfully" FrostFSNodeReadNewlyCreatedContainerAfterTheNotification = "read newly created container after the notification" From 80b581d49967178e927d1575de759dcf37a9d519 Mon Sep 17 00:00:00 2001 From: Olga Konstantinova Date: Sat, 3 Feb 2024 20:17:12 +0300 Subject: [PATCH 0323/1413] [#466] adm: Allow to download contracts from Gitea Signed-off-by: Olga Konstantinova --- .../internal/modules/morph/download.go | 81 +++++++++++++++++++ .../internal/modules/morph/initialize.go | 7 ++ .../modules/morph/initialize_deploy.go | 10 ++- .../internal/modules/morph/root.go | 13 ++- go.mod | 4 + go.sum | 21 +++++ 6 files changed, 129 insertions(+), 7 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/download.go diff --git a/cmd/frostfs-adm/internal/modules/morph/download.go b/cmd/frostfs-adm/internal/modules/morph/download.go new file mode 100644 index 0000000000..5bd2d98bde --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/download.go @@ -0,0 +1,81 @@ +package morph + +import ( + "context" + "errors" + "fmt" + "io" + "net" + "net/http" + "strings" + "time" + + "code.gitea.io/sdk/gitea" + "github.com/spf13/cobra" +) + +func downloadContracts(cmd *cobra.Command, url string) (io.ReadCloser, error) { + cmd.Printf("Downloading contracts archive from '%s'\n", url) + + // HTTP client with connect timeout + client := http.Client{ + Transport: &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: 10 * time.Second, + }).DialContext, + }, + } + + ctx, cancel := context.WithTimeout(cmd.Context(), 60*time.Second) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) + if err != nil { + return nil, fmt.Errorf("can't create request: %w", err) + } + + resp, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("can't fetch contracts archive: %w", err) + } + return resp.Body, nil +} + +func downloadContractsFromRepository(cmd *cobra.Command) (io.ReadCloser, error) { + client, err := gitea.NewClient("https://git.frostfs.info") + if err != nil { + return nil, fmt.Errorf("can't initialize repository client: %w", err) + } + + releases, _, err := client.ListReleases("TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{}) + if err != nil { + return nil, fmt.Errorf("can't fetch release information: %w", err) + } + + var latestRelease *gitea.Release + for _, r := range releases { + if !r.IsDraft && !r.IsPrerelease { + latestRelease = r + break + } + } + + if latestRelease == nil { + return nil, fmt.Errorf("attempt to fetch contracts archive from the offitial repository failed: no releases found") + } + + cmd.Printf("Found release %s (%s)\n", latestRelease.TagName, latestRelease.Title) + + var url string + for _, a := range latestRelease.Attachments { + if strings.HasPrefix(a.Name, "frostfs-contract") { + url = a.DownloadURL + break + } + } + if url == "" { + return nil, errors.New("can't find contracts archive in the latest release") + } + + return downloadContracts(cmd, url) +} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index 78356e6b41..04e8620cc1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -50,6 +50,7 @@ type initializeContext struct { Contracts map[string]*contractState Command *cobra.Command ContractPath string + ContractURL string } var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", maxAlphabetNodes) @@ -152,6 +153,11 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex return nil, err } + var ctrURL string + if needContracts { + ctrURL, _ = cmd.Flags().GetString(contractsURLFlag) + } + if err := checkNotaryEnabled(c); err != nil { return nil, err } @@ -176,6 +182,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex Command: cmd, Contracts: make(map[string]*contractState), ContractPath: ctrPath, + ContractURL: ctrURL, } if needContracts { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 6cf75c5f9d..f715f0e03a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -399,10 +399,14 @@ func (c *initializeContext) readContracts(names []string) error { } } else { var r io.ReadCloser - if c.ContractPath == "" { - return errors.New("contracts flag is missing") + if c.ContractPath != "" { + r, err = os.Open(c.ContractPath) + } else if c.ContractURL != "" { + r, err = downloadContracts(c.Command, c.ContractURL) + } else { + r, err = downloadContractsFromRepository(c.Command) } - r, err = os.Open(c.ContractPath) + if err != nil { return fmt.Errorf("can't open contracts archive: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 600fe21c8e..6cc2d5a96c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -17,6 +17,9 @@ const ( storageGasCLIFlag = "initial-gas" storageGasConfigFlag = "storage.initial_gas" contractsInitFlag = "contracts" + contractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" + contractsURLFlag = "contracts-url" + contractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" maxObjectSizeInitFlag = "network.max_object_size" maxObjectSizeCLIFlag = "max-object-size" epochDurationInitFlag = "network.epoch_duration" @@ -370,8 +373,9 @@ func initUpdateContractsCmd() { RootCmd.AddCommand(updateContractsCmd) updateContractsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) updateContractsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) - updateContractsCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled FrostFS contracts") - _ = updateContractsCmd.MarkFlagRequired(contractsInitFlag) + updateContractsCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) + updateContractsCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) + updateContractsCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag) } func initDumpBalancesCmd() { @@ -441,8 +445,8 @@ func initInitCmd() { RootCmd.AddCommand(initCmd) initCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) initCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) - initCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled FrostFS contracts") - _ = initCmd.MarkFlagRequired(contractsInitFlag) + initCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) + initCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") initCmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes") initCmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing") @@ -451,6 +455,7 @@ func initInitCmd() { initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") initCmd.Flags().String(protoConfigPath, "", "Path to the consensus node configuration") initCmd.Flags().String(localDumpFlag, "", "Path to the blocks dump file") + initCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag) } func initGenerateAlphabetCmd() { diff --git a/go.mod b/go.mod index 07097c5470..5d6edc2223 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module git.frostfs.info/TrueCloudLab/frostfs-node go 1.20 require ( + code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 @@ -61,8 +62,10 @@ require ( github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/davidmz/go-pageant v1.0.2 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect @@ -71,6 +74,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect diff --git a/go.sum b/go.sum index 5243ac4350..b9052efde5 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= +code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c h1:dO2VLtoTQre4W28i1gSuW1MO80qFd0Lq9Q46Pu3q3TA= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa h1:uuN90s74idThHXi/jF/IlTdFimOIs+IBU44rdTE/Zdo= @@ -49,6 +51,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0= +github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -61,6 +65,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= +github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -100,6 +106,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -300,8 +308,10 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= @@ -309,6 +319,7 @@ golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/i golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= 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= @@ -322,6 +333,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -330,6 +343,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= @@ -355,10 +369,15 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -367,6 +386,7 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -375,6 +395,7 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 8e2a0611f4a93ec580122bb18920a3a49325f3b3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 5 Feb 2024 14:09:58 +0300 Subject: [PATCH 0324/1413] [#947] tree: Add method to list all trees Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/pilorama/boltdb.go | 62 +++++++++++++++++++ pkg/local_object_storage/pilorama/forest.go | 51 +++++++++++++++ .../pilorama/forest_test.go | 56 +++++++++++++++++ .../pilorama/interface.go | 44 +++++++++++++ pkg/local_object_storage/shard/tree.go | 21 +++++++ 5 files changed, 234 insertions(+) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 52cdec586e..39400391f7 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1134,6 +1134,68 @@ func (t *boltForest) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID string) return err } +// TreeListTrees implements ForestStorage. +func (t *boltForest) TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (*TreeListTreesResult, error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + t.metrics.AddMethodDuration("TreeListTrees", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "boltForest.TreeListTrees") + defer span.End() + + t.modeMtx.RLock() + defer t.modeMtx.RUnlock() + + if t.mode.NoMetabase() { + return nil, ErrDegradedMode + } + + batchSize := prm.BatchSize + if batchSize <= 0 { + batchSize = treeListTreesBatchSizeDefault + } + var res TreeListTreesResult + err := metaerr.Wrap(t.db.View(func(tx *bbolt.Tx) error { + c := tx.Cursor() + checkNextPageToken := true + for k, _ := c.Seek(prm.NextPageToken); k != nil; k, _ = c.Next() { + if bytes.Equal(k, dataBucket) || bytes.Equal(k, logBucket) { + continue + } + + if checkNextPageToken && bytes.Equal(k, prm.NextPageToken) { + checkNextPageToken = false + continue + } + + var contID cidSDK.ID + if err := contID.Decode(k[:32]); err != nil { + return fmt.Errorf("failed to decode containerID: %w", err) + } + res.Items = append(res.Items, ContainerIDTreeID{ + CID: contID, + TreeID: string(k[32:]), + }) + + if len(res.Items) == batchSize { + res.NextPageToken = make([]byte, len(k)) + copy(res.NextPageToken, k) + break + } + } + return nil + })) + success = err == nil + if err != nil { + return nil, err + } + return &res, nil +} + func (t *boltForest) getPathPrefix(bTree *bbolt.Bucket, attr string, path []string) (int, Node, error) { c := bTree.Cursor() diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index b82e5b3bd2..8a1e861477 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -2,6 +2,7 @@ package pilorama import ( "context" + "fmt" "sort" "strings" @@ -260,3 +261,53 @@ func (f *memoryForest) TreeLastSyncHeight(_ context.Context, cid cid.ID, treeID } return t.syncHeight, nil } + +// TreeListTrees implements Forest. +func (f *memoryForest) TreeListTrees(_ context.Context, prm TreeListTreesPrm) (*TreeListTreesResult, error) { + batchSize := prm.BatchSize + if batchSize <= 0 { + batchSize = treeListTreesBatchSizeDefault + } + tmpSlice := make([]string, 0, len(f.treeMap)) + for k := range f.treeMap { + tmpSlice = append(tmpSlice, k) + } + sort.Strings(tmpSlice) + var idx int + if len(prm.NextPageToken) > 0 { + last := string(prm.NextPageToken) + idx, _ = sort.Find(len(tmpSlice), func(i int) int { + return -1 * strings.Compare(tmpSlice[i], last) + }) + if idx == len(tmpSlice) { + return &TreeListTreesResult{}, nil + } + if tmpSlice[idx] == last { + idx++ + } + } + + var result TreeListTreesResult + for idx < len(tmpSlice) { + cidAndTree := strings.Split(tmpSlice[idx], "/") + if len(cidAndTree) != 2 { + return nil, fmt.Errorf("invalid format: key must be cid and treeID") + } + var contID cid.ID + if err := contID.DecodeString(cidAndTree[0]); err != nil { + return nil, fmt.Errorf("invalid format: %w", err) + } + + result.Items = append(result.Items, ContainerIDTreeID{ + CID: contID, + TreeID: cidAndTree[1], + }) + + if len(result.Items) == batchSize { + result.NextPageToken = []byte(tmpSlice[idx]) + break + } + idx++ + } + return &result, nil +} diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 5813395f0f..2e7c1f529b 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -1189,3 +1189,59 @@ func testTreeLastSyncHeight(t *testing.T, f ForestStorage) { require.ErrorIs(t, err, ErrTreeNotFound) }) } + +func TestForest_ListTrees(t *testing.T) { + for i := range providers { + i := i + t.Run(providers[i].name, func(t *testing.T) { + testTreeListTrees(t, providers[i].construct) + }) + } +} + +func testTreeListTrees(t *testing.T, constructor func(t testing.TB, _ ...Option) ForestStorage) { + batchSize := 10 + t.Run("empty", func(t *testing.T) { + testTreeListTreesCount(t, constructor, batchSize, 0) + }) + t.Run("count lower than batch size", func(t *testing.T) { + testTreeListTreesCount(t, constructor, batchSize, batchSize-1) + }) + t.Run("count equals batch size", func(t *testing.T) { + testTreeListTreesCount(t, constructor, batchSize, batchSize) + }) + t.Run("count greater than batch size", func(t *testing.T) { + testTreeListTreesCount(t, constructor, batchSize, batchSize+1) + }) + t.Run("count equals multiplied batch size", func(t *testing.T) { + testTreeListTreesCount(t, constructor, batchSize, 3*batchSize) + }) + t.Run("count equals multiplied batch size with addition", func(t *testing.T) { + testTreeListTreesCount(t, constructor, batchSize, 3*batchSize+batchSize/2) + }) +} + +func testTreeListTreesCount(t *testing.T, constructor func(t testing.TB, _ ...Option) ForestStorage, batchSize, count int) { + f := constructor(t) + var expected []ContainerIDTreeID + + treeIDs := []string{"version", "system", "s", "avada kedavra"} + for i := 0; i < count; i++ { + cid := cidtest.ID() + treeID := treeIDs[i%len(treeIDs)] + expected = append(expected, ContainerIDTreeID{ + CID: cid, + TreeID: treeID, + }) + + ops := prepareRandomTree(5, 5) + for _, op := range ops { + require.NoError(t, f.TreeApply(context.Background(), cid, treeID, &op, false)) + } + } + + actual, err := treeListAll(context.Background(), f, batchSize) + require.NoError(t, err) + + require.ElementsMatch(t, expected, actual) +} diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index e7f7eb512a..3efd1a68b4 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -63,6 +63,9 @@ type ForestStorage interface { SetMode(m mode.Mode) error SetParentID(id string) Forest + + // TreeListTrees returns all pairs "containerID:treeID". + TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (*TreeListTreesResult, error) } const ( @@ -85,3 +88,44 @@ var ErrInvalidCIDDescriptor = logicerr.New("cid descriptor is invalid") func (d CIDDescriptor) checkValid() bool { return 0 <= d.Position && d.Position < d.Size } + +var treeListTreesBatchSizeDefault = 1000 + +type ContainerIDTreeID struct { + CID cidSDK.ID + TreeID string +} + +type TreeListTreesPrm struct { + NextPageToken []byte + // BatchSize is batch size to list trees. If not lower or equals zero, than treeListTreesBatchSizeDefault is used. + BatchSize int +} + +type TreeListTreesResult struct { + NextPageToken []byte + Items []ContainerIDTreeID +} + +func TreeListAll(ctx context.Context, f ForestStorage) ([]ContainerIDTreeID, error) { + return treeListAll(ctx, f, treeListTreesBatchSizeDefault) +} + +func treeListAll(ctx context.Context, f ForestStorage, batchSize int) ([]ContainerIDTreeID, error) { + var prm TreeListTreesPrm + var result []ContainerIDTreeID + first := true + + for len(prm.NextPageToken) > 0 || first { + first = false + + res, err := f.TreeListTrees(ctx, prm) + if err != nil { + return nil, err + } + prm.NextPageToken = res.NextPageToken + result = append(result, res.Items...) + } + + return result, nil +} diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index 7795b820dd..017b3450d9 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -353,3 +353,24 @@ func (s *Shard) TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, treeID st } return s.pilorama.TreeLastSyncHeight(ctx, cid, treeID) } + +func (s *Shard) TreeListTrees(ctx context.Context, prm pilorama.TreeListTreesPrm) (*pilorama.TreeListTreesResult, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeListTrees", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + ), + ) + defer span.End() + + if s.pilorama == nil { + return nil, ErrPiloramaDisabled + } + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { + return nil, ErrDegradedMode + } + return s.pilorama.TreeListTrees(ctx, prm) +} From a6eb66bf9cc932f5f42a491386d6a62e402fe0cf Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 5 Feb 2024 15:42:30 +0300 Subject: [PATCH 0325/1413] [#947] evacuate: Refactor evacuate parameters Drop methods to make it easier to extend. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 54 ++++++------------- .../engine/evacuate_test.go | 30 +++++------ pkg/services/control/server/evacuate.go | 9 ++-- pkg/services/control/server/evacuate_async.go | 11 ++-- 4 files changed, 43 insertions(+), 61 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index f522e6fbdc..d95098fbf3 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -30,10 +30,10 @@ var ( // EvacuateShardPrm represents parameters for the EvacuateShard operation. type EvacuateShardPrm struct { - shardID []*shard.ID - handler func(context.Context, oid.Address, *objectSDK.Object) error - ignoreErrors bool - async bool + ShardID []*shard.ID + Handler func(context.Context, oid.Address, *objectSDK.Object) error + IgnoreErrors bool + Async bool } // EvacuateShardRes represents result of the EvacuateShard operation. @@ -54,26 +54,6 @@ func NewEvacuateShardRes() *EvacuateShardRes { } } -// WithShardIDList sets shard ID. -func (p *EvacuateShardPrm) WithShardIDList(id []*shard.ID) { - p.shardID = id -} - -// WithIgnoreErrors sets flag to ignore errors. -func (p *EvacuateShardPrm) WithIgnoreErrors(ignore bool) { - p.ignoreErrors = ignore -} - -// WithFaultHandler sets handler to call for objects which cannot be saved on other shards. -func (p *EvacuateShardPrm) WithFaultHandler(f func(context.Context, oid.Address, *objectSDK.Object) error) { - p.handler = f -} - -// WithAsync sets flag to run evacuate async. -func (p *EvacuateShardPrm) WithAsync(async bool) { - p.async = async -} - // Evacuated returns amount of evacuated objects. // Objects for which handler returned no error are also assumed evacuated. func (p *EvacuateShardRes) Evacuated() uint64 { @@ -145,20 +125,20 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev default: } - shardIDs := make([]string, len(prm.shardID)) - for i := range prm.shardID { - shardIDs[i] = prm.shardID[i].String() + shardIDs := make([]string, len(prm.ShardID)) + for i := range prm.ShardID { + shardIDs[i] = prm.ShardID[i].String() } ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Evacuate", trace.WithAttributes( attribute.StringSlice("shardIDs", shardIDs), - attribute.Bool("async", prm.async), - attribute.Bool("ignoreErrors", prm.ignoreErrors), + attribute.Bool("async", prm.Async), + attribute.Bool("ignoreErrors", prm.IgnoreErrors), )) defer span.End() - shards, weights, err := e.getActualShards(shardIDs, prm.handler != nil) + shards, weights, err := e.getActualShards(shardIDs, prm.Handler != nil) if err != nil { return nil, err } @@ -173,7 +153,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev } res := NewEvacuateShardRes() - ctx = ctxOrBackground(ctx, prm.async) + ctx = ctxOrBackground(ctx, prm.Async) eg, egCtx, err := e.evacuateLimiter.TryStart(ctx, shardIDs, res) if err != nil { return nil, err @@ -183,7 +163,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev return e.evacuateShards(egCtx, shardIDs, prm, res, shards, weights, shardsToEvacuate) }) - if prm.async { + if prm.Async { return nil, nil } @@ -204,8 +184,8 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShards", trace.WithAttributes( attribute.StringSlice("shardIDs", shardIDs), - attribute.Bool("async", prm.async), - attribute.Bool("ignoreErrors", prm.ignoreErrors), + attribute.Bool("async", prm.Async), + attribute.Bool("ignoreErrors", prm.IgnoreErrors), )) defer func() { @@ -357,7 +337,7 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to getRes, err := sh.Get(ctx, getPrm) if err != nil { - if prm.ignoreErrors { + if prm.IgnoreErrors { res.failed.Add(1) continue } @@ -375,13 +355,13 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to continue } - if prm.handler == nil { + if prm.Handler == nil { // Do not check ignoreErrors flag here because // ignoring errors on put make this command kinda useless. return fmt.Errorf("%w: %s", errPutShard, toEvacuate[i]) } - err = prm.handler(ctx, addr, getRes.Object()) + err = prm.Handler(ctx, addr, getRes.Object()) if err != nil { e.log.Error(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index d874734d38..2dc4a177c9 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -102,7 +102,7 @@ func TestEvacuateShard(t *testing.T) { checkHasObjects(t) var prm EvacuateShardPrm - prm.WithShardIDList(ids[2:3]) + prm.ShardID = ids[2:3] t.Run("must be read-only", func(t *testing.T) { res, err := e.Evacuate(context.Background(), prm) @@ -173,13 +173,13 @@ func TestEvacuateNetwork(t *testing.T) { require.NoError(t, e.shards[evacuateShardID].SetMode(mode.ReadOnly)) var prm EvacuateShardPrm - prm.shardID = ids[0:1] + prm.ShardID = ids[0:1] res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errMustHaveTwoShards) require.Equal(t, uint64(0), res.Evacuated()) - prm.handler = acceptOneOf(objects, 2) + prm.Handler = acceptOneOf(objects, 2) res, err = e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errReplication) @@ -196,15 +196,15 @@ func TestEvacuateNetwork(t *testing.T) { require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) var prm EvacuateShardPrm - prm.shardID = ids[1:2] - prm.handler = acceptOneOf(objects, 2) + prm.ShardID = ids[1:2] + prm.Handler = acceptOneOf(objects, 2) res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errReplication) require.Equal(t, uint64(2), res.Evacuated()) t.Run("no errors", func(t *testing.T) { - prm.handler = acceptOneOf(objects, 3) + prm.Handler = acceptOneOf(objects, 3) res, err := e.Evacuate(context.Background(), prm) require.NoError(t, err) @@ -233,15 +233,15 @@ func TestEvacuateNetwork(t *testing.T) { } var prm EvacuateShardPrm - prm.shardID = evacuateIDs - prm.handler = acceptOneOf(objects, totalCount-1) + prm.ShardID = evacuateIDs + prm.Handler = acceptOneOf(objects, totalCount-1) res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errReplication) require.Equal(t, totalCount-1, res.Evacuated()) t.Run("no errors", func(t *testing.T) { - prm.handler = acceptOneOf(objects, totalCount) + prm.Handler = acceptOneOf(objects, totalCount) res, err := e.Evacuate(context.Background(), prm) require.NoError(t, err) @@ -261,8 +261,8 @@ func TestEvacuateCancellation(t *testing.T) { require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) var prm EvacuateShardPrm - prm.shardID = ids[1:2] - prm.handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ShardID = ids[1:2] + prm.Handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { select { case <-ctx.Done(): return ctx.Err() @@ -292,8 +292,8 @@ func TestEvacuateSingleProcess(t *testing.T) { running := make(chan interface{}) var prm EvacuateShardPrm - prm.shardID = ids[1:2] - prm.handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ShardID = ids[1:2] + prm.Handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { select { case <-running: default: @@ -334,8 +334,8 @@ func TestEvacuateAsync(t *testing.T) { running := make(chan interface{}) var prm EvacuateShardPrm - prm.shardID = ids[1:2] - prm.handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ShardID = ids[1:2] + prm.Handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { select { case <-running: default: diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 8f62c3489d..52ef083c44 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -25,10 +25,11 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe return nil, status.Error(codes.PermissionDenied, err.Error()) } - var prm engine.EvacuateShardPrm - prm.WithShardIDList(s.getShardIDList(req.GetBody().GetShard_ID())) - prm.WithIgnoreErrors(req.GetBody().GetIgnoreErrors()) - prm.WithFaultHandler(s.replicate) + prm := engine.EvacuateShardPrm{ + ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), + IgnoreErrors: req.GetBody().GetIgnoreErrors(), + Handler: s.replicate, + } res, err := s.s.Evacuate(ctx, prm) if err != nil { diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index cdf3656e25..112d4449f2 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -17,11 +17,12 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha return nil, status.Error(codes.PermissionDenied, err.Error()) } - var prm engine.EvacuateShardPrm - prm.WithShardIDList(s.getShardIDList(req.GetBody().GetShard_ID())) - prm.WithIgnoreErrors(req.GetBody().GetIgnoreErrors()) - prm.WithFaultHandler(s.replicate) - prm.WithAsync(true) + prm := engine.EvacuateShardPrm{ + ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), + IgnoreErrors: req.GetBody().GetIgnoreErrors(), + Handler: s.replicate, + Async: true, + } _, err = s.s.Evacuate(ctx, prm) if err != nil { From b3f3505adaca55ec9aeca1a1a6d6a0a2e584f3f9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 5 Feb 2024 16:33:09 +0300 Subject: [PATCH 0326/1413] [#947] cli: Allow to specify evacuation scope It may be required to evacuate only objects or only tree or all, so now it spossible to specify. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/evacuation.go | 23 + pkg/local_object_storage/engine/evacuate.go | 30 + pkg/services/control/server/evacuate.go | 1 + pkg/services/control/server/evacuate_async.go | 5 + pkg/services/control/service.pb.go | 1211 +++++++++-------- pkg/services/control/service.proto | 8 + pkg/services/control/service_frostfs.pb.go | 2 + 7 files changed, 706 insertions(+), 574 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 821dd1a6c9..9d4cb64acc 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -19,6 +19,11 @@ import ( const ( awaitFlag = "await" noProgressFlag = "no-progress" + scopeFlag = "scope" + + scopeAll = "all" + scopeObjects = "objects" + scopeTrees = "trees" ) var evacuationShardCmd = &cobra.Command{ @@ -57,6 +62,7 @@ func startEvacuateShard(cmd *cobra.Command, _ []string) { Body: &control.StartShardEvacuationRequest_Body{ Shard_ID: getShardIDList(cmd), IgnoreErrors: ignoreErrors, + Scope: getEvacuationScope(cmd), }, } @@ -82,6 +88,22 @@ func startEvacuateShard(cmd *cobra.Command, _ []string) { } } +func getEvacuationScope(cmd *cobra.Command) uint32 { + rawScope, err := cmd.Flags().GetString(scopeFlag) + commonCmd.ExitOnErr(cmd, "Invalid scope value: %w", err) + switch rawScope { + case scopeAll: + return uint32(control.StartShardEvacuationRequest_Body_OBJECTS) | uint32(control.StartShardEvacuationRequest_Body_TREES) + case scopeObjects: + return uint32(control.StartShardEvacuationRequest_Body_OBJECTS) + case scopeTrees: + return uint32(control.StartShardEvacuationRequest_Body_TREES) + default: + commonCmd.ExitOnErr(cmd, "Invalid scope value: %w", fmt.Errorf("unknown scope %s", rawScope)) + } + return uint32(control.StartShardEvacuationRequest_Body_NONE) +} + func getEvacuateShardStatus(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) req := &control.GetShardEvacuationStatusRequest{ @@ -309,6 +331,7 @@ func initControlStartEvacuationShardCmd() { flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") flags.Bool(shardAllFlag, false, "Process all shards") flags.Bool(ignoreErrorsFlag, true, "Skip invalid/unreadable objects") + flags.String(scopeFlag, scopeAll, fmt.Sprintf("Evacuation scope; possible values: %s, %s, %s", scopeTrees, scopeObjects, scopeAll)) flags.Bool(awaitFlag, false, "Block execution until evacuation is completed") flags.Bool(noProgressFlag, false, fmt.Sprintf("Print progress if %s provided", awaitFlag)) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index d95098fbf3..ad432e4003 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strings" "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -28,12 +29,40 @@ var ( evacuationOperationLogField = zap.String("operation", "evacuation") ) +// EvacuateScope is an evacuation scope. Keep in sync with pkg/services/control/service.proto. +type EvacuateScope uint32 + +var ( + EvacuateScopeObjects EvacuateScope = 1 + EvacuateScopeTrees EvacuateScope = 2 +) + +func (s EvacuateScope) String() string { + var sb strings.Builder + first := true + if s&EvacuateScopeObjects == EvacuateScopeObjects { + if !first { + sb.WriteString(";") + } + sb.WriteString("objects") + first = false + } + if s&EvacuateScopeTrees == EvacuateScopeTrees { + if !first { + sb.WriteString(";") + } + sb.WriteString("trees") + } + return sb.String() +} + // EvacuateShardPrm represents parameters for the EvacuateShard operation. type EvacuateShardPrm struct { ShardID []*shard.ID Handler func(context.Context, oid.Address, *objectSDK.Object) error IgnoreErrors bool Async bool + Scope EvacuateScope } // EvacuateShardRes represents result of the EvacuateShard operation. @@ -135,6 +164,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev attribute.StringSlice("shardIDs", shardIDs), attribute.Bool("async", prm.Async), attribute.Bool("ignoreErrors", prm.IgnoreErrors), + attribute.Stringer("scope", prm.Scope), )) defer span.End() diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 52ef083c44..6cba72d712 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -29,6 +29,7 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), IgnoreErrors: req.GetBody().GetIgnoreErrors(), Handler: s.replicate, + Scope: engine.EvacuateScopeObjects, } res, err := s.s.Evacuate(ctx, prm) diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index 112d4449f2..0b28512751 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -17,11 +17,16 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha return nil, status.Error(codes.PermissionDenied, err.Error()) } + if req.GetBody().GetScope() == uint32(control.StartShardEvacuationRequest_Body_NONE) { + return nil, status.Error(codes.InvalidArgument, "no evacuation scope") + } + prm := engine.EvacuateShardPrm{ ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), IgnoreErrors: req.GetBody().GetIgnoreErrors(), Handler: s.replicate, Async: true, + Scope: engine.EvacuateScope(req.GetBody().GetScope()), } _, err = s.s.Evacuate(ctx, prm) diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index c9645941bf..9c1a874156 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -20,6 +20,55 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type StartShardEvacuationRequest_Body_Scope int32 + +const ( + StartShardEvacuationRequest_Body_NONE StartShardEvacuationRequest_Body_Scope = 0 + StartShardEvacuationRequest_Body_OBJECTS StartShardEvacuationRequest_Body_Scope = 1 + StartShardEvacuationRequest_Body_TREES StartShardEvacuationRequest_Body_Scope = 2 +) + +// Enum value maps for StartShardEvacuationRequest_Body_Scope. +var ( + StartShardEvacuationRequest_Body_Scope_name = map[int32]string{ + 0: "NONE", + 1: "OBJECTS", + 2: "TREES", + } + StartShardEvacuationRequest_Body_Scope_value = map[string]int32{ + "NONE": 0, + "OBJECTS": 1, + "TREES": 2, + } +) + +func (x StartShardEvacuationRequest_Body_Scope) Enum() *StartShardEvacuationRequest_Body_Scope { + p := new(StartShardEvacuationRequest_Body_Scope) + *p = x + return p +} + +func (x StartShardEvacuationRequest_Body_Scope) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (StartShardEvacuationRequest_Body_Scope) Descriptor() protoreflect.EnumDescriptor { + return file_pkg_services_control_service_proto_enumTypes[0].Descriptor() +} + +func (StartShardEvacuationRequest_Body_Scope) Type() protoreflect.EnumType { + return &file_pkg_services_control_service_proto_enumTypes[0] +} + +func (x StartShardEvacuationRequest_Body_Scope) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use StartShardEvacuationRequest_Body_Scope.Descriptor instead. +func (StartShardEvacuationRequest_Body_Scope) EnumDescriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{18, 0, 0} +} + // Evacuate status enum. type GetShardEvacuationStatusResponse_Body_Status int32 @@ -54,11 +103,11 @@ func (x GetShardEvacuationStatusResponse_Body_Status) String() string { } func (GetShardEvacuationStatusResponse_Body_Status) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_control_service_proto_enumTypes[0].Descriptor() + return file_pkg_services_control_service_proto_enumTypes[1].Descriptor() } func (GetShardEvacuationStatusResponse_Body_Status) Type() protoreflect.EnumType { - return &file_pkg_services_control_service_proto_enumTypes[0] + return &file_pkg_services_control_service_proto_enumTypes[1] } func (x GetShardEvacuationStatusResponse_Body_Status) Number() protoreflect.EnumNumber { @@ -3113,6 +3162,8 @@ type StartShardEvacuationRequest_Body struct { Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` // Flag indicating whether object read errors should be ignored. IgnoreErrors bool `protobuf:"varint,2,opt,name=ignore_errors,json=ignoreErrors,proto3" json:"ignore_errors,omitempty"` + // Evacuation scope. + Scope uint32 `protobuf:"varint,3,opt,name=scope,proto3" json:"scope,omitempty"` } func (x *StartShardEvacuationRequest_Body) Reset() { @@ -3161,6 +3212,13 @@ func (x *StartShardEvacuationRequest_Body) GetIgnoreErrors() bool { return false } +func (x *StartShardEvacuationRequest_Body) GetScope() uint32 { + if x != nil { + return x.Scope + } + return 0 +} + // Response body structure. type StartShardEvacuationResponse_Body struct { state protoimpl.MessageState @@ -4502,7 +4560,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xd6, 0x01, 0x0a, 0x1b, 0x53, + 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x98, 0x02, 0x0a, 0x1b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, @@ -4511,386 +4569,390 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, - 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x9e, - 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, - 0xe0, 0x05, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x87, 0x01, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, + 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, 0x29, 0x0a, 0x05, 0x53, 0x63, + 0x6f, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, + 0x07, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, + 0x45, 0x45, 0x53, 0x10, 0x02, 0x22, 0x98, 0x01, 0x0a, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x22, 0x9e, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc5, 0x04, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x65, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, - 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, 0x0a, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, 0x08, 0x64, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x22, 0xe0, 0x05, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, - 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x1a, 0x25, 0x0a, 0x0d, 0x55, 0x6e, - 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x1a, 0x24, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, - 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, - 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, - 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, - 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, - 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, - 0x10, 0x02, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, - 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, - 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, - 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x22, 0xca, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc5, 0x04, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x65, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, + 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, + 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, 0x08, 0x64, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x5b, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, + 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x1a, 0x25, 0x0a, 0x0d, + 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x24, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, + 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, + 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, + 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, + 0x45, 0x44, 0x10, 0x02, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, + 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, + 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, - 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, - 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x24, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, + 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, + 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, + 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x1a, 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2e, 0x0a, 0x07, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xe7, 0x01, 0x0a, - 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x64, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, + 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, - 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, + 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, + 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x21, 0x4c, 0x69, + 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2e, + 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xe7, + 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, - 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, - 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, - 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, - 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, - 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, - 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, - 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb1, 0x0d, 0x0a, 0x0e, - 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, - 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, - 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, - 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, - 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, - 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, - 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, - 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, + 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, + 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, + 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb1, 0x0d, + 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, + 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, + 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, + 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, + 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, + 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, + 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, - 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, - 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, - 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, - 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, 0x4c, - 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, - 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, - 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, - 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, - 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, + 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, + 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, + 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, + 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, + 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, + 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, + 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, + 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4905,225 +4967,226 @@ func file_pkg_services_control_service_proto_rawDescGZIP() []byte { return file_pkg_services_control_service_proto_rawDescData } -var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 79) var file_pkg_services_control_service_proto_goTypes = []interface{}{ - (GetShardEvacuationStatusResponse_Body_Status)(0), // 0: control.GetShardEvacuationStatusResponse.Body.Status - (*HealthCheckRequest)(nil), // 1: control.HealthCheckRequest - (*HealthCheckResponse)(nil), // 2: control.HealthCheckResponse - (*SetNetmapStatusRequest)(nil), // 3: control.SetNetmapStatusRequest - (*SetNetmapStatusResponse)(nil), // 4: control.SetNetmapStatusResponse - (*DropObjectsRequest)(nil), // 5: control.DropObjectsRequest - (*DropObjectsResponse)(nil), // 6: control.DropObjectsResponse - (*ListShardsRequest)(nil), // 7: control.ListShardsRequest - (*ListShardsResponse)(nil), // 8: control.ListShardsResponse - (*SetShardModeRequest)(nil), // 9: control.SetShardModeRequest - (*SetShardModeResponse)(nil), // 10: control.SetShardModeResponse - (*SynchronizeTreeRequest)(nil), // 11: control.SynchronizeTreeRequest - (*SynchronizeTreeResponse)(nil), // 12: control.SynchronizeTreeResponse - (*EvacuateShardRequest)(nil), // 13: control.EvacuateShardRequest - (*EvacuateShardResponse)(nil), // 14: control.EvacuateShardResponse - (*FlushCacheRequest)(nil), // 15: control.FlushCacheRequest - (*FlushCacheResponse)(nil), // 16: control.FlushCacheResponse - (*DoctorRequest)(nil), // 17: control.DoctorRequest - (*DoctorResponse)(nil), // 18: control.DoctorResponse - (*StartShardEvacuationRequest)(nil), // 19: control.StartShardEvacuationRequest - (*StartShardEvacuationResponse)(nil), // 20: control.StartShardEvacuationResponse - (*GetShardEvacuationStatusRequest)(nil), // 21: control.GetShardEvacuationStatusRequest - (*GetShardEvacuationStatusResponse)(nil), // 22: control.GetShardEvacuationStatusResponse - (*StopShardEvacuationRequest)(nil), // 23: control.StopShardEvacuationRequest - (*StopShardEvacuationResponse)(nil), // 24: control.StopShardEvacuationResponse - (*AddChainLocalOverrideRequest)(nil), // 25: control.AddChainLocalOverrideRequest - (*AddChainLocalOverrideResponse)(nil), // 26: control.AddChainLocalOverrideResponse - (*GetChainLocalOverrideRequest)(nil), // 27: control.GetChainLocalOverrideRequest - (*GetChainLocalOverrideResponse)(nil), // 28: control.GetChainLocalOverrideResponse - (*ListChainLocalOverridesRequest)(nil), // 29: control.ListChainLocalOverridesRequest - (*ListChainLocalOverridesResponse)(nil), // 30: control.ListChainLocalOverridesResponse - (*ListTargetsLocalOverridesRequest)(nil), // 31: control.ListTargetsLocalOverridesRequest - (*ListTargetsLocalOverridesResponse)(nil), // 32: control.ListTargetsLocalOverridesResponse - (*RemoveChainLocalOverrideRequest)(nil), // 33: control.RemoveChainLocalOverrideRequest - (*RemoveChainLocalOverrideResponse)(nil), // 34: control.RemoveChainLocalOverrideResponse - (*SealWriteCacheRequest)(nil), // 35: control.SealWriteCacheRequest - (*SealWriteCacheResponse)(nil), // 36: control.SealWriteCacheResponse - (*DetachShardsRequest)(nil), // 37: control.DetachShardsRequest - (*DetachShardsResponse)(nil), // 38: control.DetachShardsResponse - (*HealthCheckRequest_Body)(nil), // 39: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 40: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 41: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 42: control.SetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 43: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 44: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 45: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 46: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 47: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 48: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 49: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 50: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 51: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 52: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 53: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 54: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 55: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 56: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 57: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 58: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 59: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 60: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 61: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 62: control.GetShardEvacuationStatusResponse.Body.Duration - (*StopShardEvacuationRequest_Body)(nil), // 63: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 64: control.StopShardEvacuationResponse.Body - (*AddChainLocalOverrideRequest_Body)(nil), // 65: control.AddChainLocalOverrideRequest.Body - (*AddChainLocalOverrideResponse_Body)(nil), // 66: control.AddChainLocalOverrideResponse.Body - (*GetChainLocalOverrideRequest_Body)(nil), // 67: control.GetChainLocalOverrideRequest.Body - (*GetChainLocalOverrideResponse_Body)(nil), // 68: control.GetChainLocalOverrideResponse.Body - (*ListChainLocalOverridesRequest_Body)(nil), // 69: control.ListChainLocalOverridesRequest.Body - (*ListChainLocalOverridesResponse_Body)(nil), // 70: control.ListChainLocalOverridesResponse.Body - (*ListTargetsLocalOverridesRequest_Body)(nil), // 71: control.ListTargetsLocalOverridesRequest.Body - (*ListTargetsLocalOverridesResponse_Body)(nil), // 72: control.ListTargetsLocalOverridesResponse.Body - (*RemoveChainLocalOverrideRequest_Body)(nil), // 73: control.RemoveChainLocalOverrideRequest.Body - (*RemoveChainLocalOverrideResponse_Body)(nil), // 74: control.RemoveChainLocalOverrideResponse.Body - (*SealWriteCacheRequest_Body)(nil), // 75: control.SealWriteCacheRequest.Body - (*SealWriteCacheResponse_Body)(nil), // 76: control.SealWriteCacheResponse.Body - (*SealWriteCacheResponse_Body_Status)(nil), // 77: control.SealWriteCacheResponse.Body.Status - (*DetachShardsRequest_Body)(nil), // 78: control.DetachShardsRequest.Body - (*DetachShardsResponse_Body)(nil), // 79: control.DetachShardsResponse.Body - (*Signature)(nil), // 80: control.Signature - (NetmapStatus)(0), // 81: control.NetmapStatus - (HealthStatus)(0), // 82: control.HealthStatus - (*ShardInfo)(nil), // 83: control.ShardInfo - (ShardMode)(0), // 84: control.ShardMode - (*ChainTarget)(nil), // 85: control.ChainTarget + (StartShardEvacuationRequest_Body_Scope)(0), // 0: control.StartShardEvacuationRequest.Body.Scope + (GetShardEvacuationStatusResponse_Body_Status)(0), // 1: control.GetShardEvacuationStatusResponse.Body.Status + (*HealthCheckRequest)(nil), // 2: control.HealthCheckRequest + (*HealthCheckResponse)(nil), // 3: control.HealthCheckResponse + (*SetNetmapStatusRequest)(nil), // 4: control.SetNetmapStatusRequest + (*SetNetmapStatusResponse)(nil), // 5: control.SetNetmapStatusResponse + (*DropObjectsRequest)(nil), // 6: control.DropObjectsRequest + (*DropObjectsResponse)(nil), // 7: control.DropObjectsResponse + (*ListShardsRequest)(nil), // 8: control.ListShardsRequest + (*ListShardsResponse)(nil), // 9: control.ListShardsResponse + (*SetShardModeRequest)(nil), // 10: control.SetShardModeRequest + (*SetShardModeResponse)(nil), // 11: control.SetShardModeResponse + (*SynchronizeTreeRequest)(nil), // 12: control.SynchronizeTreeRequest + (*SynchronizeTreeResponse)(nil), // 13: control.SynchronizeTreeResponse + (*EvacuateShardRequest)(nil), // 14: control.EvacuateShardRequest + (*EvacuateShardResponse)(nil), // 15: control.EvacuateShardResponse + (*FlushCacheRequest)(nil), // 16: control.FlushCacheRequest + (*FlushCacheResponse)(nil), // 17: control.FlushCacheResponse + (*DoctorRequest)(nil), // 18: control.DoctorRequest + (*DoctorResponse)(nil), // 19: control.DoctorResponse + (*StartShardEvacuationRequest)(nil), // 20: control.StartShardEvacuationRequest + (*StartShardEvacuationResponse)(nil), // 21: control.StartShardEvacuationResponse + (*GetShardEvacuationStatusRequest)(nil), // 22: control.GetShardEvacuationStatusRequest + (*GetShardEvacuationStatusResponse)(nil), // 23: control.GetShardEvacuationStatusResponse + (*StopShardEvacuationRequest)(nil), // 24: control.StopShardEvacuationRequest + (*StopShardEvacuationResponse)(nil), // 25: control.StopShardEvacuationResponse + (*AddChainLocalOverrideRequest)(nil), // 26: control.AddChainLocalOverrideRequest + (*AddChainLocalOverrideResponse)(nil), // 27: control.AddChainLocalOverrideResponse + (*GetChainLocalOverrideRequest)(nil), // 28: control.GetChainLocalOverrideRequest + (*GetChainLocalOverrideResponse)(nil), // 29: control.GetChainLocalOverrideResponse + (*ListChainLocalOverridesRequest)(nil), // 30: control.ListChainLocalOverridesRequest + (*ListChainLocalOverridesResponse)(nil), // 31: control.ListChainLocalOverridesResponse + (*ListTargetsLocalOverridesRequest)(nil), // 32: control.ListTargetsLocalOverridesRequest + (*ListTargetsLocalOverridesResponse)(nil), // 33: control.ListTargetsLocalOverridesResponse + (*RemoveChainLocalOverrideRequest)(nil), // 34: control.RemoveChainLocalOverrideRequest + (*RemoveChainLocalOverrideResponse)(nil), // 35: control.RemoveChainLocalOverrideResponse + (*SealWriteCacheRequest)(nil), // 36: control.SealWriteCacheRequest + (*SealWriteCacheResponse)(nil), // 37: control.SealWriteCacheResponse + (*DetachShardsRequest)(nil), // 38: control.DetachShardsRequest + (*DetachShardsResponse)(nil), // 39: control.DetachShardsResponse + (*HealthCheckRequest_Body)(nil), // 40: control.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 41: control.HealthCheckResponse.Body + (*SetNetmapStatusRequest_Body)(nil), // 42: control.SetNetmapStatusRequest.Body + (*SetNetmapStatusResponse_Body)(nil), // 43: control.SetNetmapStatusResponse.Body + (*DropObjectsRequest_Body)(nil), // 44: control.DropObjectsRequest.Body + (*DropObjectsResponse_Body)(nil), // 45: control.DropObjectsResponse.Body + (*ListShardsRequest_Body)(nil), // 46: control.ListShardsRequest.Body + (*ListShardsResponse_Body)(nil), // 47: control.ListShardsResponse.Body + (*SetShardModeRequest_Body)(nil), // 48: control.SetShardModeRequest.Body + (*SetShardModeResponse_Body)(nil), // 49: control.SetShardModeResponse.Body + (*SynchronizeTreeRequest_Body)(nil), // 50: control.SynchronizeTreeRequest.Body + (*SynchronizeTreeResponse_Body)(nil), // 51: control.SynchronizeTreeResponse.Body + (*EvacuateShardRequest_Body)(nil), // 52: control.EvacuateShardRequest.Body + (*EvacuateShardResponse_Body)(nil), // 53: control.EvacuateShardResponse.Body + (*FlushCacheRequest_Body)(nil), // 54: control.FlushCacheRequest.Body + (*FlushCacheResponse_Body)(nil), // 55: control.FlushCacheResponse.Body + (*DoctorRequest_Body)(nil), // 56: control.DoctorRequest.Body + (*DoctorResponse_Body)(nil), // 57: control.DoctorResponse.Body + (*StartShardEvacuationRequest_Body)(nil), // 58: control.StartShardEvacuationRequest.Body + (*StartShardEvacuationResponse_Body)(nil), // 59: control.StartShardEvacuationResponse.Body + (*GetShardEvacuationStatusRequest_Body)(nil), // 60: control.GetShardEvacuationStatusRequest.Body + (*GetShardEvacuationStatusResponse_Body)(nil), // 61: control.GetShardEvacuationStatusResponse.Body + (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 62: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 63: control.GetShardEvacuationStatusResponse.Body.Duration + (*StopShardEvacuationRequest_Body)(nil), // 64: control.StopShardEvacuationRequest.Body + (*StopShardEvacuationResponse_Body)(nil), // 65: control.StopShardEvacuationResponse.Body + (*AddChainLocalOverrideRequest_Body)(nil), // 66: control.AddChainLocalOverrideRequest.Body + (*AddChainLocalOverrideResponse_Body)(nil), // 67: control.AddChainLocalOverrideResponse.Body + (*GetChainLocalOverrideRequest_Body)(nil), // 68: control.GetChainLocalOverrideRequest.Body + (*GetChainLocalOverrideResponse_Body)(nil), // 69: control.GetChainLocalOverrideResponse.Body + (*ListChainLocalOverridesRequest_Body)(nil), // 70: control.ListChainLocalOverridesRequest.Body + (*ListChainLocalOverridesResponse_Body)(nil), // 71: control.ListChainLocalOverridesResponse.Body + (*ListTargetsLocalOverridesRequest_Body)(nil), // 72: control.ListTargetsLocalOverridesRequest.Body + (*ListTargetsLocalOverridesResponse_Body)(nil), // 73: control.ListTargetsLocalOverridesResponse.Body + (*RemoveChainLocalOverrideRequest_Body)(nil), // 74: control.RemoveChainLocalOverrideRequest.Body + (*RemoveChainLocalOverrideResponse_Body)(nil), // 75: control.RemoveChainLocalOverrideResponse.Body + (*SealWriteCacheRequest_Body)(nil), // 76: control.SealWriteCacheRequest.Body + (*SealWriteCacheResponse_Body)(nil), // 77: control.SealWriteCacheResponse.Body + (*SealWriteCacheResponse_Body_Status)(nil), // 78: control.SealWriteCacheResponse.Body.Status + (*DetachShardsRequest_Body)(nil), // 79: control.DetachShardsRequest.Body + (*DetachShardsResponse_Body)(nil), // 80: control.DetachShardsResponse.Body + (*Signature)(nil), // 81: control.Signature + (NetmapStatus)(0), // 82: control.NetmapStatus + (HealthStatus)(0), // 83: control.HealthStatus + (*ShardInfo)(nil), // 84: control.ShardInfo + (ShardMode)(0), // 85: control.ShardMode + (*ChainTarget)(nil), // 86: control.ChainTarget } var file_pkg_services_control_service_proto_depIdxs = []int32{ - 39, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 80, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 40, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 80, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 41, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 80, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 42, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 80, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 43, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 80, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature - 44, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 80, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature - 45, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 80, // 13: control.ListShardsRequest.signature:type_name -> control.Signature - 46, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 80, // 15: control.ListShardsResponse.signature:type_name -> control.Signature - 47, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 80, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature - 48, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 80, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature - 49, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 80, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 50, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 80, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 51, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 80, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature - 52, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 80, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature - 53, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 80, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature - 54, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 80, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature - 55, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 80, // 33: control.DoctorRequest.signature:type_name -> control.Signature - 56, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 80, // 35: control.DoctorResponse.signature:type_name -> control.Signature - 57, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 80, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 58, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 80, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 59, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 80, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 60, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 80, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 63, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 80, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 64, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 80, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 65, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body - 80, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature - 66, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body - 80, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature - 67, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body - 80, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature - 68, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body - 80, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature - 69, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body - 80, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature - 70, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body - 80, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature - 71, // 60: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body - 80, // 61: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature - 72, // 62: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body - 80, // 63: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature - 73, // 64: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body - 80, // 65: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature - 74, // 66: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body - 80, // 67: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature - 75, // 68: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body - 80, // 69: control.SealWriteCacheRequest.signature:type_name -> control.Signature - 76, // 70: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body - 80, // 71: control.SealWriteCacheResponse.signature:type_name -> control.Signature - 78, // 72: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body - 80, // 73: control.DetachShardsRequest.signature:type_name -> control.Signature - 79, // 74: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body - 80, // 75: control.DetachShardsResponse.signature:type_name -> control.Signature - 81, // 76: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 82, // 77: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 81, // 78: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 83, // 79: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 84, // 80: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 0, // 81: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 62, // 82: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 61, // 83: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 85, // 84: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 85, // 85: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 85, // 86: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget - 85, // 87: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget - 85, // 88: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 77, // 89: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status - 1, // 90: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 3, // 91: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 5, // 92: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 7, // 93: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 9, // 94: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 11, // 95: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 13, // 96: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 19, // 97: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 21, // 98: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 23, // 99: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 15, // 100: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 17, // 101: control.ControlService.Doctor:input_type -> control.DoctorRequest - 25, // 102: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 27, // 103: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 29, // 104: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 33, // 105: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 31, // 106: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest - 35, // 107: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest - 37, // 108: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest - 2, // 109: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 4, // 110: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 6, // 111: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 8, // 112: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 10, // 113: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 12, // 114: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 14, // 115: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 20, // 116: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 22, // 117: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 24, // 118: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 16, // 119: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 18, // 120: control.ControlService.Doctor:output_type -> control.DoctorResponse - 26, // 121: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 28, // 122: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 30, // 123: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 34, // 124: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 32, // 125: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse - 36, // 126: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse - 38, // 127: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse + 40, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body + 81, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature + 41, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body + 81, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature + 42, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body + 81, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature + 43, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body + 81, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature + 44, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body + 81, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature + 45, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body + 81, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature + 46, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body + 81, // 13: control.ListShardsRequest.signature:type_name -> control.Signature + 47, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body + 81, // 15: control.ListShardsResponse.signature:type_name -> control.Signature + 48, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body + 81, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature + 49, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body + 81, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature + 50, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body + 81, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature + 51, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body + 81, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature + 52, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body + 81, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature + 53, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body + 81, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature + 54, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body + 81, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature + 55, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body + 81, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature + 56, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body + 81, // 33: control.DoctorRequest.signature:type_name -> control.Signature + 57, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body + 81, // 35: control.DoctorResponse.signature:type_name -> control.Signature + 58, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body + 81, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature + 59, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body + 81, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature + 60, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body + 81, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 61, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body + 81, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 64, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body + 81, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature + 65, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body + 81, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature + 66, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body + 81, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature + 67, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body + 81, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature + 68, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body + 81, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature + 69, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body + 81, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature + 70, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body + 81, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature + 71, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body + 81, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature + 72, // 60: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body + 81, // 61: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature + 73, // 62: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body + 81, // 63: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature + 74, // 64: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body + 81, // 65: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature + 75, // 66: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body + 81, // 67: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature + 76, // 68: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body + 81, // 69: control.SealWriteCacheRequest.signature:type_name -> control.Signature + 77, // 70: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body + 81, // 71: control.SealWriteCacheResponse.signature:type_name -> control.Signature + 79, // 72: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body + 81, // 73: control.DetachShardsRequest.signature:type_name -> control.Signature + 80, // 74: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body + 81, // 75: control.DetachShardsResponse.signature:type_name -> control.Signature + 82, // 76: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus + 83, // 77: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus + 82, // 78: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus + 84, // 79: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo + 85, // 80: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode + 1, // 81: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status + 63, // 82: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration + 62, // 83: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + 86, // 84: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 86, // 85: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 86, // 86: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget + 86, // 87: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget + 86, // 88: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 78, // 89: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status + 2, // 90: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 4, // 91: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 6, // 92: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 8, // 93: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 10, // 94: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 12, // 95: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 14, // 96: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 20, // 97: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 22, // 98: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 24, // 99: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 16, // 100: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 18, // 101: control.ControlService.Doctor:input_type -> control.DoctorRequest + 26, // 102: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 28, // 103: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 30, // 104: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 34, // 105: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 32, // 106: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest + 36, // 107: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest + 38, // 108: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest + 3, // 109: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 5, // 110: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 7, // 111: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 9, // 112: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 11, // 113: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 13, // 114: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 15, // 115: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 21, // 116: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 23, // 117: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 25, // 118: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 17, // 119: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 19, // 120: control.ControlService.Doctor:output_type -> control.DoctorResponse + 27, // 121: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 29, // 122: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 31, // 123: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 35, // 124: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 33, // 125: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse + 37, // 126: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse + 39, // 127: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse 109, // [109:128] is the sub-list for method output_type 90, // [90:109] is the sub-list for method input_type 90, // [90:90] is the sub-list for extension type_name @@ -6092,7 +6155,7 @@ func file_pkg_services_control_service_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_service_proto_rawDesc, - NumEnums: 1, + NumEnums: 2, NumMessages: 79, NumExtensions: 0, NumServices: 1, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 4cb1dee33b..73e8ca90f0 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -336,10 +336,18 @@ message DoctorResponse { message StartShardEvacuationRequest { // Request body structure. message Body { + enum Scope { + NONE = 0; + OBJECTS = 1; + TREES = 2; + } + // IDs of the shards. repeated bytes shard_ID = 1; // Flag indicating whether object read errors should be ignored. bool ignore_errors = 2; + // Evacuation scope. + uint32 scope = 3; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 125a12d00e..b18d30dba1 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -1511,6 +1511,7 @@ func (x *StartShardEvacuationRequest_Body) StableSize() (size int) { } size += proto.RepeatedBytesSize(1, x.Shard_ID) size += proto.BoolSize(2, x.IgnoreErrors) + size += proto.UInt32Size(3, x.Scope) return size } @@ -1532,6 +1533,7 @@ func (x *StartShardEvacuationRequest_Body) StableMarshal(buf []byte) []byte { var offset int offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) offset += proto.BoolMarshal(2, buf[offset:], x.IgnoreErrors) + offset += proto.UInt32Marshal(3, buf[offset:], x.Scope) return buf } From 15d853ea22115c5345cbd0a616d2879b06f883e0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 5 Feb 2024 17:48:43 +0300 Subject: [PATCH 0327/1413] [#947] controlSvc: Return tree evacuation stat Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 142 ++-- .../engine/evacuate_limiter.go | 37 +- .../engine/evacuate_test.go | 48 +- pkg/services/control/server/convert.go | 21 +- pkg/services/control/server/evacuate.go | 10 +- pkg/services/control/server/evacuate_async.go | 10 +- pkg/services/control/service.pb.go | 716 +++++++++--------- pkg/services/control/service.proto | 15 +- pkg/services/control/service_frostfs.pb.go | 22 +- 9 files changed, 569 insertions(+), 452 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index ad432e4003..3853c4e3ab 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -58,62 +58,93 @@ func (s EvacuateScope) String() string { // EvacuateShardPrm represents parameters for the EvacuateShard operation. type EvacuateShardPrm struct { - ShardID []*shard.ID - Handler func(context.Context, oid.Address, *objectSDK.Object) error - IgnoreErrors bool - Async bool - Scope EvacuateScope + ShardID []*shard.ID + ObjectsHandler func(context.Context, oid.Address, *objectSDK.Object) error + IgnoreErrors bool + Async bool + Scope EvacuateScope } // EvacuateShardRes represents result of the EvacuateShard operation. type EvacuateShardRes struct { - evacuated *atomic.Uint64 - total *atomic.Uint64 - failed *atomic.Uint64 - skipped *atomic.Uint64 + objEvacuated *atomic.Uint64 + objTotal *atomic.Uint64 + objFailed *atomic.Uint64 + objSkipped *atomic.Uint64 + + trEvacuated *atomic.Uint64 + trTotal *atomic.Uint64 + trFailed *atomic.Uint64 } // NewEvacuateShardRes creates new EvacuateShardRes instance. func NewEvacuateShardRes() *EvacuateShardRes { return &EvacuateShardRes{ - evacuated: new(atomic.Uint64), - total: new(atomic.Uint64), - failed: new(atomic.Uint64), - skipped: new(atomic.Uint64), + objEvacuated: new(atomic.Uint64), + objTotal: new(atomic.Uint64), + objFailed: new(atomic.Uint64), + objSkipped: new(atomic.Uint64), + trEvacuated: new(atomic.Uint64), + trTotal: new(atomic.Uint64), + trFailed: new(atomic.Uint64), } } -// Evacuated returns amount of evacuated objects. +// ObjectsEvacuated returns amount of evacuated objects. // Objects for which handler returned no error are also assumed evacuated. -func (p *EvacuateShardRes) Evacuated() uint64 { +func (p *EvacuateShardRes) ObjectsEvacuated() uint64 { if p == nil { return 0 } - return p.evacuated.Load() + return p.objEvacuated.Load() } -// Total returns total count objects to evacuate. -func (p *EvacuateShardRes) Total() uint64 { +// ObjectsTotal returns total count objects to evacuate. +func (p *EvacuateShardRes) ObjectsTotal() uint64 { if p == nil { return 0 } - return p.total.Load() + return p.objTotal.Load() } -// Failed returns count of failed objects to evacuate. -func (p *EvacuateShardRes) Failed() uint64 { +// ObjectsFailed returns count of failed objects to evacuate. +func (p *EvacuateShardRes) ObjectsFailed() uint64 { if p == nil { return 0 } - return p.failed.Load() + return p.objFailed.Load() } -// Skipped returns count of skipped objects. -func (p *EvacuateShardRes) Skipped() uint64 { +// ObjectsSkipped returns count of skipped objects. +func (p *EvacuateShardRes) ObjectsSkipped() uint64 { if p == nil { return 0 } - return p.skipped.Load() + return p.objSkipped.Load() +} + +// TreesEvacuated returns amount of evacuated trees. +func (p *EvacuateShardRes) TreesEvacuated() uint64 { + if p == nil { + return 0 + } + return p.trEvacuated.Load() +} + +// TreesTotal returns total count trees to evacuate. +func (p *EvacuateShardRes) TreesTotal() uint64 { + if p == nil { + return 0 + } + return p.trTotal.Load() +} + +// TreesFailed returns count of failed trees to evacuate. +func (p *EvacuateShardRes) TreesFailed() uint64 { + if p == nil { + return 0 + } + return p.trFailed.Load() } // DeepCopy returns deep copy of result instance. @@ -123,16 +154,22 @@ func (p *EvacuateShardRes) DeepCopy() *EvacuateShardRes { } res := &EvacuateShardRes{ - evacuated: new(atomic.Uint64), - total: new(atomic.Uint64), - failed: new(atomic.Uint64), - skipped: new(atomic.Uint64), + objEvacuated: new(atomic.Uint64), + objTotal: new(atomic.Uint64), + objFailed: new(atomic.Uint64), + objSkipped: new(atomic.Uint64), + trEvacuated: new(atomic.Uint64), + trTotal: new(atomic.Uint64), + trFailed: new(atomic.Uint64), } - res.evacuated.Store(p.evacuated.Load()) - res.total.Store(p.total.Load()) - res.failed.Store(p.failed.Load()) - res.skipped.Store(p.skipped.Load()) + res.objEvacuated.Store(p.objEvacuated.Load()) + res.objTotal.Store(p.objTotal.Load()) + res.objFailed.Store(p.objFailed.Load()) + res.objSkipped.Store(p.objSkipped.Load()) + res.trTotal.Store(p.trTotal.Load()) + res.trEvacuated.Store(p.trEvacuated.Load()) + res.trFailed.Store(p.trFailed.Load()) return res } @@ -168,7 +205,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev )) defer span.End() - shards, weights, err := e.getActualShards(shardIDs, prm.Handler != nil) + shards, weights, err := e.getActualShards(shardIDs, prm) if err != nil { return nil, err } @@ -216,6 +253,7 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p attribute.StringSlice("shardIDs", shardIDs), attribute.Bool("async", prm.Async), attribute.Bool("ignoreErrors", prm.IgnoreErrors), + attribute.Stringer("scope", prm.Scope), )) defer func() { @@ -224,18 +262,19 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p }() e.log.Info(logs.EngineStartedShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) err = e.getTotalObjectsCount(ctx, shardsToEvacuate, res) if err != nil { e.log.Error(logs.EngineShardsEvacuationFailedToCount, zap.Strings("shard_ids", shardIDs), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) return err } for _, shardID := range shardIDs { if err = e.evacuateShard(ctx, shardID, prm, res, shards, weights, shardsToEvacuate); err != nil { - e.log.Error(logs.EngineFinishedWithErrorShardsEvacuation, zap.Error(err), zap.Strings("shard_ids", shardIDs), evacuationOperationLogField) + e.log.Error(logs.EngineFinishedWithErrorShardsEvacuation, zap.Error(err), zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) return err } } @@ -243,10 +282,13 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p e.log.Info(logs.EngineFinishedSuccessfullyShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, - zap.Uint64("total", res.Total()), - zap.Uint64("evacuated", res.Evacuated()), - zap.Uint64("failed", res.Failed()), - zap.Uint64("skipped", res.Skipped()), + zap.Uint64("total_objects", res.ObjectsTotal()), + zap.Uint64("evacuated_objects", res.ObjectsEvacuated()), + zap.Uint64("failed_objects", res.ObjectsFailed()), + zap.Uint64("skipped_objects", res.ObjectsSkipped()), + zap.Uint64("total_trees", res.TreesTotal()), + zap.Uint64("evacuated_trees", res.TreesEvacuated()), + zap.Uint64("failed_trees", res.TreesFailed()), ) return nil } @@ -263,7 +305,7 @@ func (e *StorageEngine) getTotalObjectsCount(ctx context.Context, shardsToEvacua } return err } - res.total.Add(cnt) + res.objTotal.Add(cnt) } return nil } @@ -307,7 +349,7 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm E return nil } -func (e *StorageEngine) getActualShards(shardIDs []string, handlerDefined bool) ([]pooledShard, []float64, error) { +func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) ([]pooledShard, []float64, error) { e.mtx.RLock() defer e.mtx.RUnlock() @@ -322,7 +364,7 @@ func (e *StorageEngine) getActualShards(shardIDs []string, handlerDefined bool) } } - if len(e.shards)-len(shardIDs) < 1 && !handlerDefined { + if len(e.shards)-len(shardIDs) < 1 && prm.ObjectsHandler == nil { return nil, nil, errMustHaveTwoShards } @@ -368,7 +410,7 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to getRes, err := sh.Get(ctx, getPrm) if err != nil { if prm.IgnoreErrors { - res.failed.Add(1) + res.objFailed.Add(1) continue } e.log.Error(logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, @@ -385,19 +427,19 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to continue } - if prm.Handler == nil { + if prm.ObjectsHandler == nil { // Do not check ignoreErrors flag here because // ignoring errors on put make this command kinda useless. return fmt.Errorf("%w: %s", errPutShard, toEvacuate[i]) } - err = prm.Handler(ctx, addr, getRes.Object()) + err = prm.ObjectsHandler(ctx, addr, getRes.Object()) if err != nil { e.log.Error(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } - res.evacuated.Add(1) + res.objEvacuated.Add(1) } return nil } @@ -418,7 +460,7 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add } switch e.putToShard(ctx, shards[j].hashedShard, j, shards[j].pool, addr, object).status { case putToShardSuccess: - res.evacuated.Add(1) + res.objEvacuated.Add(1) e.log.Debug(logs.EngineObjectIsMovedToAnotherShard, zap.Stringer("from", sh.ID()), zap.Stringer("to", shards[j].ID()), @@ -427,7 +469,7 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return true, nil case putToShardExists, putToShardRemoved: - res.skipped.Add(1) + res.objSkipped.Add(1) return true, nil default: continue diff --git a/pkg/local_object_storage/engine/evacuate_limiter.go b/pkg/local_object_storage/engine/evacuate_limiter.go index 83acd30d96..63960e238a 100644 --- a/pkg/local_object_storage/engine/evacuate_limiter.go +++ b/pkg/local_object_storage/engine/evacuate_limiter.go @@ -34,32 +34,53 @@ func (s *EvacuationState) ShardIDs() []string { return s.shardIDs } -func (s *EvacuationState) Evacuated() uint64 { +func (s *EvacuationState) ObjectsEvacuated() uint64 { if s == nil { return 0 } - return s.result.Evacuated() + return s.result.ObjectsEvacuated() } -func (s *EvacuationState) Total() uint64 { +func (s *EvacuationState) ObjectsTotal() uint64 { if s == nil { return 0 } - return s.result.Total() + return s.result.ObjectsTotal() } -func (s *EvacuationState) Failed() uint64 { +func (s *EvacuationState) ObjectsFailed() uint64 { if s == nil { return 0 } - return s.result.Failed() + return s.result.ObjectsFailed() } -func (s *EvacuationState) Skipped() uint64 { +func (s *EvacuationState) ObjectsSkipped() uint64 { if s == nil { return 0 } - return s.result.Skipped() + return s.result.ObjectsSkipped() +} + +func (s *EvacuationState) TreesEvacuated() uint64 { + if s == nil { + return 0 + } + return s.result.TreesEvacuated() +} + +func (s *EvacuationState) TreesTotal() uint64 { + if s == nil { + return 0 + } + return s.result.TreesTotal() +} + +func (s *EvacuationState) TreesFailed() uint64 { + if s == nil { + return 0 + } + return s.result.TreesFailed() } func (s *EvacuationState) ProcessingStatus() EvacuateProcessState { diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 2dc4a177c9..cadcc29330 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -107,14 +107,14 @@ func TestEvacuateShard(t *testing.T) { t.Run("must be read-only", func(t *testing.T) { res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, ErrMustBeReadOnly) - require.Equal(t, uint64(0), res.Evacuated()) + require.Equal(t, uint64(0), res.ObjectsEvacuated()) }) require.NoError(t, e.shards[evacuateShardID].SetMode(mode.ReadOnly)) res, err := e.Evacuate(context.Background(), prm) require.NoError(t, err) - require.Equal(t, uint64(objPerShard), res.Evacuated()) + require.Equal(t, uint64(objPerShard), res.ObjectsEvacuated()) // We check that all objects are available both before and after shard removal. // First case is a real-world use-case. It ensures that an object can be put in presense @@ -125,7 +125,7 @@ func TestEvacuateShard(t *testing.T) { // Calling it again is OK, but all objects are already moved, so no new PUTs should be done. res, err = e.Evacuate(context.Background(), prm) require.NoError(t, err) - require.Equal(t, uint64(0), res.Evacuated()) + require.Equal(t, uint64(0), res.ObjectsEvacuated()) checkHasObjects(t) @@ -177,13 +177,13 @@ func TestEvacuateNetwork(t *testing.T) { res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errMustHaveTwoShards) - require.Equal(t, uint64(0), res.Evacuated()) + require.Equal(t, uint64(0), res.ObjectsEvacuated()) - prm.Handler = acceptOneOf(objects, 2) + prm.ObjectsHandler = acceptOneOf(objects, 2) res, err = e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errReplication) - require.Equal(t, uint64(2), res.Evacuated()) + require.Equal(t, uint64(2), res.ObjectsEvacuated()) }) t.Run("multiple shards, evacuate one", func(t *testing.T) { t.Parallel() @@ -197,18 +197,18 @@ func TestEvacuateNetwork(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] - prm.Handler = acceptOneOf(objects, 2) + prm.ObjectsHandler = acceptOneOf(objects, 2) res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errReplication) - require.Equal(t, uint64(2), res.Evacuated()) + require.Equal(t, uint64(2), res.ObjectsEvacuated()) t.Run("no errors", func(t *testing.T) { - prm.Handler = acceptOneOf(objects, 3) + prm.ObjectsHandler = acceptOneOf(objects, 3) res, err := e.Evacuate(context.Background(), prm) require.NoError(t, err) - require.Equal(t, uint64(3), res.Evacuated()) + require.Equal(t, uint64(3), res.ObjectsEvacuated()) }) }) t.Run("multiple shards, evacuate many", func(t *testing.T) { @@ -234,18 +234,18 @@ func TestEvacuateNetwork(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = evacuateIDs - prm.Handler = acceptOneOf(objects, totalCount-1) + prm.ObjectsHandler = acceptOneOf(objects, totalCount-1) res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errReplication) - require.Equal(t, totalCount-1, res.Evacuated()) + require.Equal(t, totalCount-1, res.ObjectsEvacuated()) t.Run("no errors", func(t *testing.T) { - prm.Handler = acceptOneOf(objects, totalCount) + prm.ObjectsHandler = acceptOneOf(objects, totalCount) res, err := e.Evacuate(context.Background(), prm) require.NoError(t, err) - require.Equal(t, totalCount, res.Evacuated()) + require.Equal(t, totalCount, res.ObjectsEvacuated()) }) }) } @@ -262,7 +262,7 @@ func TestEvacuateCancellation(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] - prm.Handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { select { case <-ctx.Done(): return ctx.Err() @@ -276,7 +276,7 @@ func TestEvacuateCancellation(t *testing.T) { res, err := e.Evacuate(ctx, prm) require.ErrorContains(t, err, "context canceled") - require.Equal(t, uint64(0), res.Evacuated()) + require.Equal(t, uint64(0), res.ObjectsEvacuated()) } func TestEvacuateSingleProcess(t *testing.T) { @@ -293,7 +293,7 @@ func TestEvacuateSingleProcess(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] - prm.Handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { select { case <-running: default: @@ -307,14 +307,14 @@ func TestEvacuateSingleProcess(t *testing.T) { eg.Go(func() error { res, err := e.Evacuate(egCtx, prm) require.NoError(t, err, "first evacuation failed") - require.Equal(t, uint64(3), res.Evacuated()) + require.Equal(t, uint64(3), res.ObjectsEvacuated()) return nil }) eg.Go(func() error { <-running res, err := e.Evacuate(egCtx, prm) require.ErrorContains(t, err, "evacuate is already running for shard ids", "second evacuation not failed") - require.Equal(t, uint64(0), res.Evacuated()) + require.Equal(t, uint64(0), res.ObjectsEvacuated()) close(blocker) return nil }) @@ -335,7 +335,7 @@ func TestEvacuateAsync(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] - prm.Handler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { select { case <-running: default: @@ -348,7 +348,7 @@ func TestEvacuateAsync(t *testing.T) { st, err := e.GetEvacuationState(context.Background()) require.NoError(t, err, "get init state failed") require.Equal(t, EvacuateProcessStateUndefined, st.ProcessingStatus(), "invalid init state") - require.Equal(t, uint64(0), st.Evacuated(), "invalid init count") + require.Equal(t, uint64(0), st.ObjectsEvacuated(), "invalid init count") require.Nil(t, st.StartedAt(), "invalid init started at") require.Nil(t, st.FinishedAt(), "invalid init finished at") require.ElementsMatch(t, []string{}, st.ShardIDs(), "invalid init shard ids") @@ -358,7 +358,7 @@ func TestEvacuateAsync(t *testing.T) { eg.Go(func() error { res, err := e.Evacuate(egCtx, prm) require.NoError(t, err, "first evacuation failed") - require.Equal(t, uint64(3), res.Evacuated()) + require.Equal(t, uint64(3), res.ObjectsEvacuated()) return nil }) @@ -367,7 +367,7 @@ func TestEvacuateAsync(t *testing.T) { st, err = e.GetEvacuationState(context.Background()) require.NoError(t, err, "get running state failed") require.Equal(t, EvacuateProcessStateRunning, st.ProcessingStatus(), "invalid running state") - require.Equal(t, uint64(0), st.Evacuated(), "invalid running count") + require.Equal(t, uint64(0), st.ObjectsEvacuated(), "invalid running count") require.NotNil(t, st.StartedAt(), "invalid running started at") require.Nil(t, st.FinishedAt(), "invalid init finished at") expectedShardIDs := make([]string, 0, 2) @@ -385,7 +385,7 @@ func TestEvacuateAsync(t *testing.T) { }, 3*time.Second, 10*time.Millisecond, "invalid final state") require.NoError(t, err, "get final state failed") - require.Equal(t, uint64(3), st.Evacuated(), "invalid final count") + require.Equal(t, uint64(3), st.ObjectsEvacuated(), "invalid final count") require.NotNil(t, st.StartedAt(), "invalid final started at") require.NotNil(t, st.FinishedAt(), "invalid final finished at") require.ElementsMatch(t, expectedShardIDs, st.ShardIDs(), "invalid final shard ids") diff --git a/pkg/services/control/server/convert.go b/pkg/services/control/server/convert.go index f922d7278c..4f3132356b 100644 --- a/pkg/services/control/server/convert.go +++ b/pkg/services/control/server/convert.go @@ -47,15 +47,18 @@ func stateToResponse(state *engine.EvacuationState) (*control.GetShardEvacuation } return &control.GetShardEvacuationStatusResponse{ Body: &control.GetShardEvacuationStatusResponse_Body{ - Shard_ID: shardIDs, - Evacuated: state.Evacuated(), - Total: state.Total(), - Failed: state.Failed(), - Status: evacStatus, - StartedAt: startedAt, - Duration: duration, - ErrorMessage: state.ErrorMessage(), - Skipped: state.Skipped(), + Shard_ID: shardIDs, + EvacuatedObjects: state.ObjectsEvacuated(), + TotalObjects: state.ObjectsTotal(), + FailedObjects: state.ObjectsFailed(), + Status: evacStatus, + StartedAt: startedAt, + Duration: duration, + ErrorMessage: state.ErrorMessage(), + SkippedObjects: state.ObjectsSkipped(), + TotalTrees: state.TreesTotal(), + EvacuatedTrees: state.TreesEvacuated(), + FailedTrees: state.TreesFailed(), }, }, nil } diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 6cba72d712..ac8b3d548f 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -26,10 +26,10 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe } prm := engine.EvacuateShardPrm{ - ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), - IgnoreErrors: req.GetBody().GetIgnoreErrors(), - Handler: s.replicate, - Scope: engine.EvacuateScopeObjects, + ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), + IgnoreErrors: req.GetBody().GetIgnoreErrors(), + ObjectsHandler: s.replicate, + Scope: engine.EvacuateScopeObjects, } res, err := s.s.Evacuate(ctx, prm) @@ -39,7 +39,7 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe resp := &control.EvacuateShardResponse{ Body: &control.EvacuateShardResponse_Body{ - Count: uint32(res.Evacuated()), + Count: uint32(res.ObjectsEvacuated()), }, } diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index 0b28512751..91f0731c41 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -22,11 +22,11 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha } prm := engine.EvacuateShardPrm{ - ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), - IgnoreErrors: req.GetBody().GetIgnoreErrors(), - Handler: s.replicate, - Async: true, - Scope: engine.EvacuateScope(req.GetBody().GetScope()), + ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), + IgnoreErrors: req.GetBody().GetIgnoreErrors(), + ObjectsHandler: s.replicate, + Async: true, + Scope: engine.EvacuateScope(req.GetBody().GetScope()), } _, err = s.s.Evacuate(ctx, prm) diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 9c1a874156..4e95ac6173 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -3304,11 +3304,11 @@ type GetShardEvacuationStatusResponse_Body struct { unknownFields protoimpl.UnknownFields // Total objects to evacuate count. The value is approximate, so evacuated + failed + skipped == total is not guaranteed after completion. - Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"` + TotalObjects uint64 `protobuf:"varint,1,opt,name=total_objects,json=totalObjects,proto3" json:"total_objects,omitempty"` // Evacuated objects count. - Evacuated uint64 `protobuf:"varint,2,opt,name=evacuated,proto3" json:"evacuated,omitempty"` + EvacuatedObjects uint64 `protobuf:"varint,2,opt,name=evacuated_objects,json=evacuatedObjects,proto3" json:"evacuated_objects,omitempty"` // Failed objects count. - Failed uint64 `protobuf:"varint,3,opt,name=failed,proto3" json:"failed,omitempty"` + FailedObjects uint64 `protobuf:"varint,3,opt,name=failed_objects,json=failedObjects,proto3" json:"failed_objects,omitempty"` // Shard IDs. Shard_ID [][]byte `protobuf:"bytes,4,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` // Evacuation process status. @@ -3320,7 +3320,13 @@ type GetShardEvacuationStatusResponse_Body struct { // Error message if evacuation failed. ErrorMessage string `protobuf:"bytes,8,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` // Skipped objects count. - Skipped uint64 `protobuf:"varint,9,opt,name=skipped,proto3" json:"skipped,omitempty"` + SkippedObjects uint64 `protobuf:"varint,9,opt,name=skipped_objects,json=skippedObjects,proto3" json:"skipped_objects,omitempty"` + // Total trees to evacuate count. + TotalTrees uint64 `protobuf:"varint,10,opt,name=total_trees,json=totalTrees,proto3" json:"total_trees,omitempty"` + // Evacuated trees count. + EvacuatedTrees uint64 `protobuf:"varint,11,opt,name=evacuated_trees,json=evacuatedTrees,proto3" json:"evacuated_trees,omitempty"` + // Failed trees count. + FailedTrees uint64 `protobuf:"varint,12,opt,name=failed_trees,json=failedTrees,proto3" json:"failed_trees,omitempty"` } func (x *GetShardEvacuationStatusResponse_Body) Reset() { @@ -3355,23 +3361,23 @@ func (*GetShardEvacuationStatusResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21, 0} } -func (x *GetShardEvacuationStatusResponse_Body) GetTotal() uint64 { +func (x *GetShardEvacuationStatusResponse_Body) GetTotalObjects() uint64 { if x != nil { - return x.Total + return x.TotalObjects } return 0 } -func (x *GetShardEvacuationStatusResponse_Body) GetEvacuated() uint64 { +func (x *GetShardEvacuationStatusResponse_Body) GetEvacuatedObjects() uint64 { if x != nil { - return x.Evacuated + return x.EvacuatedObjects } return 0 } -func (x *GetShardEvacuationStatusResponse_Body) GetFailed() uint64 { +func (x *GetShardEvacuationStatusResponse_Body) GetFailedObjects() uint64 { if x != nil { - return x.Failed + return x.FailedObjects } return 0 } @@ -3411,9 +3417,30 @@ func (x *GetShardEvacuationStatusResponse_Body) GetErrorMessage() string { return "" } -func (x *GetShardEvacuationStatusResponse_Body) GetSkipped() uint64 { +func (x *GetShardEvacuationStatusResponse_Body) GetSkippedObjects() uint64 { if x != nil { - return x.Skipped + return x.SkippedObjects + } + return 0 +} + +func (x *GetShardEvacuationStatusResponse_Body) GetTotalTrees() uint64 { + if x != nil { + return x.TotalTrees + } + return 0 +} + +func (x *GetShardEvacuationStatusResponse_Body) GetEvacuatedTrees() uint64 { + if x != nil { + return x.EvacuatedTrees + } + return 0 +} + +func (x *GetShardEvacuationStatusResponse_Body) GetFailedTrees() uint64 { + if x != nil { + return x.FailedTrees } return 0 } @@ -4598,7 +4625,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, - 0x79, 0x22, 0xe0, 0x05, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x79, 0x22, 0x89, 0x07, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, @@ -4607,168 +4634,103 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc5, 0x04, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x65, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, - 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x61, 0x69, - 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, 0x08, 0x64, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x5b, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, - 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x07, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x1a, 0x25, 0x0a, 0x0d, - 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x1a, 0x24, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, - 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, - 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, - 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, - 0x45, 0x44, 0x10, 0x02, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, - 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xee, 0x05, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x6f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x19, + 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, + 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, + 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x27, 0x0a, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, + 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0e, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x54, 0x72, 0x65, + 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x65, + 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, + 0x54, 0x72, 0x65, 0x65, 0x73, 0x1a, 0x25, 0x0a, 0x0d, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x24, 0x0a, 0x08, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, + 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x1f, + 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x53, + 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, + 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x94, 0x01, + 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, + 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, + 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, 0x01, + 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, 0x0a, + 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, - 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, - 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, - 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, - 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, - 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, - 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, - 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, - 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, - 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x21, 0x4c, 0x69, - 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2e, - 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xe7, - 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, @@ -4778,181 +4740,257 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, - 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, - 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, - 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, + 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, 0x1e, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb1, 0x0d, - 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, - 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, - 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, - 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, - 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, - 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, - 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, - 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, + 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, + 0x64, 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, - 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, - 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, - 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0xca, + 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, + 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, + 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, + 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, + 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, + 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, - 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, - 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb1, 0x0d, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, + 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, + 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, + 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, + 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, + 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, + 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, + 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, + 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, + 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, + 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, + 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 73e8ca90f0..16e0f707d7 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -394,11 +394,11 @@ message GetShardEvacuationStatusResponse { } // Total objects to evacuate count. The value is approximate, so evacuated + failed + skipped == total is not guaranteed after completion. - uint64 total = 1; + uint64 total_objects = 1; // Evacuated objects count. - uint64 evacuated = 2; + uint64 evacuated_objects = 2; // Failed objects count. - uint64 failed = 3; + uint64 failed_objects = 3; // Shard IDs. repeated bytes shard_ID = 4; @@ -412,7 +412,14 @@ message GetShardEvacuationStatusResponse { string error_message = 8; // Skipped objects count. - uint64 skipped = 9; + uint64 skipped_objects = 9; + + // Total trees to evacuate count. + uint64 total_trees = 10; + // Evacuated trees count. + uint64 evacuated_trees = 11; + // Failed trees count. + uint64 failed_trees = 12; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index b18d30dba1..37527aa8c7 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -1815,15 +1815,18 @@ func (x *GetShardEvacuationStatusResponse_Body) StableSize() (size int) { if x == nil { return 0 } - size += proto.UInt64Size(1, x.Total) - size += proto.UInt64Size(2, x.Evacuated) - size += proto.UInt64Size(3, x.Failed) + size += proto.UInt64Size(1, x.TotalObjects) + size += proto.UInt64Size(2, x.EvacuatedObjects) + size += proto.UInt64Size(3, x.FailedObjects) size += proto.RepeatedBytesSize(4, x.Shard_ID) size += proto.EnumSize(5, int32(x.Status)) size += proto.NestedStructureSize(6, x.Duration) size += proto.NestedStructureSize(7, x.StartedAt) size += proto.StringSize(8, x.ErrorMessage) - size += proto.UInt64Size(9, x.Skipped) + size += proto.UInt64Size(9, x.SkippedObjects) + size += proto.UInt64Size(10, x.TotalTrees) + size += proto.UInt64Size(11, x.EvacuatedTrees) + size += proto.UInt64Size(12, x.FailedTrees) return size } @@ -1843,15 +1846,18 @@ func (x *GetShardEvacuationStatusResponse_Body) StableMarshal(buf []byte) []byte buf = make([]byte, x.StableSize()) } var offset int - offset += proto.UInt64Marshal(1, buf[offset:], x.Total) - offset += proto.UInt64Marshal(2, buf[offset:], x.Evacuated) - offset += proto.UInt64Marshal(3, buf[offset:], x.Failed) + offset += proto.UInt64Marshal(1, buf[offset:], x.TotalObjects) + offset += proto.UInt64Marshal(2, buf[offset:], x.EvacuatedObjects) + offset += proto.UInt64Marshal(3, buf[offset:], x.FailedObjects) offset += proto.RepeatedBytesMarshal(4, buf[offset:], x.Shard_ID) offset += proto.EnumMarshal(5, buf[offset:], int32(x.Status)) offset += proto.NestedStructureMarshal(6, buf[offset:], x.Duration) offset += proto.NestedStructureMarshal(7, buf[offset:], x.StartedAt) offset += proto.StringMarshal(8, buf[offset:], x.ErrorMessage) - offset += proto.UInt64Marshal(9, buf[offset:], x.Skipped) + offset += proto.UInt64Marshal(9, buf[offset:], x.SkippedObjects) + offset += proto.UInt64Marshal(10, buf[offset:], x.TotalTrees) + offset += proto.UInt64Marshal(11, buf[offset:], x.EvacuatedTrees) + offset += proto.UInt64Marshal(12, buf[offset:], x.FailedTrees) return buf } From e4064c43941098ee639d8efc0b7f75480732830d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 5 Feb 2024 17:49:09 +0300 Subject: [PATCH 0328/1413] [#947] cli: Print tree evacuation stat Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/evacuation.go | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 9d4cb64acc..1d192aa50a 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -241,15 +241,17 @@ func printStatus(cmd *cobra.Command, resp *control.GetShardEvacuationStatusRespo func appendEstimation(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { if resp.GetBody().GetStatus() != control.GetShardEvacuationStatusResponse_Body_RUNNING || resp.GetBody().GetDuration() == nil || - resp.GetBody().GetTotal() == 0 || - resp.GetBody().GetEvacuated()+resp.GetBody().GetFailed()+resp.GetBody().GetSkipped() == 0 { + (resp.GetBody().GetTotalObjects() == 0 && resp.GetBody().GetTotalTrees() == 0) || + (resp.GetBody().GetEvacuatedObjects()+resp.GetBody().GetFailedObjects()+resp.GetBody().GetSkippedObjects() == 0 && + resp.GetBody().GetEvacuatedTrees()+resp.GetBody().GetFailedTrees() == 0) { return } durationSeconds := float64(resp.GetBody().GetDuration().GetSeconds()) - evacuated := float64(resp.GetBody().GetEvacuated() + resp.GetBody().GetFailed() + resp.GetBody().GetSkipped()) + evacuated := float64(resp.GetBody().GetEvacuatedObjects() + resp.GetBody().GetFailedObjects() + resp.GetBody().GetSkippedObjects() + + resp.GetBody().GetEvacuatedTrees() + resp.GetBody().GetFailedTrees()) avgObjEvacuationTimeSeconds := durationSeconds / evacuated - objectsLeft := float64(resp.GetBody().GetTotal()) - evacuated + objectsLeft := float64(resp.GetBody().GetTotalObjects()+resp.GetBody().GetTotalTrees()) - evacuated leftSeconds := avgObjEvacuationTimeSeconds * objectsLeft leftMinutes := int(leftSeconds / 60) @@ -307,11 +309,14 @@ func appendShardIDs(sb *strings.Builder, resp *control.GetShardEvacuationStatusR } func appendCounts(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { - sb.WriteString(fmt.Sprintf(" Evacuated %d objects out of %d, failed to evacuate: %d, skipped: %d.", - resp.GetBody().GetEvacuated(), - resp.GetBody().GetTotal(), - resp.GetBody().GetFailed(), - resp.GetBody().GetSkipped())) + sb.WriteString(fmt.Sprintf(" Evacuated %d objects out of %d, failed to evacuate: %d, skipped: %d; evacuated %d trees out of %d, failed to evacuate: %d.", + resp.GetBody().GetEvacuatedObjects(), + resp.GetBody().GetTotalObjects(), + resp.GetBody().GetFailedObjects(), + resp.GetBody().GetSkippedObjects(), + resp.GetBody().GetEvacuatedTrees(), + resp.GetBody().GetTotalTrees(), + resp.GetBody().GetFailedTrees())) } func initControlEvacuationShardCmd() { From 728150d1d292fe00dccabff22b97151ef20409cc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 6 Feb 2024 13:59:50 +0300 Subject: [PATCH 0329/1413] [#947] engine: Evacuate trees to local shards Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 231 +++++++++++++++++- .../engine/evacuate_test.go | 133 ++++++++-- pkg/local_object_storage/pilorama/boltdb.go | 52 ++++ pkg/local_object_storage/pilorama/forest.go | 24 ++ .../pilorama/interface.go | 29 ++- pkg/local_object_storage/shard/tree.go | 29 +++ 6 files changed, 463 insertions(+), 35 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 3853c4e3ab..15fb69c2fd 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -5,11 +5,13 @@ import ( "errors" "fmt" "strings" + "sync" "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" @@ -56,6 +58,18 @@ func (s EvacuateScope) String() string { return sb.String() } +func (s EvacuateScope) WithObjects() bool { + return s&EvacuateScopeObjects == EvacuateScopeObjects +} + +func (s EvacuateScope) WithTrees() bool { + return s&EvacuateScopeTrees == EvacuateScopeTrees +} + +func (s EvacuateScope) TreesOnly() bool { + return s == EvacuateScopeTrees +} + // EvacuateShardPrm represents parameters for the EvacuateShard operation. type EvacuateShardPrm struct { ShardID []*shard.ID @@ -264,7 +278,7 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p e.log.Info(logs.EngineStartedShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) - err = e.getTotalObjectsCount(ctx, shardsToEvacuate, res) + err = e.getTotals(ctx, prm, shardsToEvacuate, res) if err != nil { e.log.Error(logs.EngineShardsEvacuationFailedToCount, zap.Strings("shard_ids", shardIDs), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) @@ -293,19 +307,28 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p return nil } -func (e *StorageEngine) getTotalObjectsCount(ctx context.Context, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes) error { - ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.getTotalObjectsCount") +func (e *StorageEngine) getTotals(ctx context.Context, prm EvacuateShardPrm, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes) error { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.getTotals") defer span.End() for _, sh := range shardsToEvacuate { - cnt, err := sh.LogicalObjectsCount(ctx) - if err != nil { - if errors.Is(err, shard.ErrDegradedMode) { - continue + if prm.Scope.WithObjects() { + cnt, err := sh.LogicalObjectsCount(ctx) + if err != nil { + if errors.Is(err, shard.ErrDegradedMode) { + continue + } + return err } - return err + res.objTotal.Add(cnt) + } + if prm.Scope.WithTrees() && sh.PiloramaEnabled() { + cnt, err := pilorama.TreeCountAll(ctx, sh) + if err != nil { + return err + } + res.trTotal.Add(cnt) } - res.objTotal.Add(cnt) } return nil } @@ -319,6 +342,24 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm E )) defer span.End() + if prm.Scope.WithObjects() { + if err := e.evacuateShardObjects(ctx, shardID, prm, res, shards, weights, shardsToEvacuate); err != nil { + return err + } + } + + if prm.Scope.WithTrees() && shardsToEvacuate[shardID].PiloramaEnabled() { + if err := e.evacuateShardTrees(ctx, shardID, prm, res, shards, weights, shardsToEvacuate); err != nil { + return err + } + } + + return nil +} + +func (e *StorageEngine) evacuateShardObjects(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, + shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, +) error { var listPrm shard.ListWithCursorPrm listPrm.WithCount(defaultEvacuateBatchSize) @@ -349,6 +390,172 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm E return nil } +func (e *StorageEngine) evacuateShardTrees(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, + shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, +) error { + sh := shardsToEvacuate[shardID] + + var listPrm pilorama.TreeListTreesPrm + first := true + + for len(listPrm.NextPageToken) > 0 || first { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + first = false + + listRes, err := sh.TreeListTrees(ctx, listPrm) + if err != nil { + return err + } + listPrm.NextPageToken = listRes.NextPageToken + if err := e.evacuateTrees(ctx, sh, listRes.Items, prm, res, shards, weights, shardsToEvacuate); err != nil { + return err + } + } + return nil +} + +func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, trees []pilorama.ContainerIDTreeID, + prm EvacuateShardPrm, res *EvacuateShardRes, shards []pooledShard, weights []float64, + shardsToEvacuate map[string]*shard.Shard, +) error { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateTrees", + trace.WithAttributes( + attribute.Int("trees_count", len(trees)), + )) + defer span.End() + + for _, contTree := range trees { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + success, _, err := e.tryEvacuateTreeLocal(ctx, sh, contTree, prm, shards, weights, shardsToEvacuate) + if err != nil { + return err + } + if success { + res.trEvacuated.Add(1) + } else { + res.trFailed.Add(1) + } + } + return nil +} + +func (e *StorageEngine) tryEvacuateTreeLocal(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, + prm EvacuateShardPrm, shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, +) (bool, string, error) { + target, found, err := e.findShardToEvacuateTree(ctx, tree, shards, weights, shardsToEvacuate) + if err != nil { + return false, "", err + } + if !found { + return false, "", nil + } + const readBatchSize = 1000 + source := make(chan *pilorama.Move, readBatchSize) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + var wg sync.WaitGroup + + wg.Add(1) + var applyErr error + go func() { + defer wg.Done() + + applyErr = target.TreeApplyStream(ctx, tree.CID, tree.TreeID, source) + if applyErr != nil { + cancel() + } + }() + + var height uint64 + for { + op, err := sh.TreeGetOpLog(ctx, tree.CID, tree.TreeID, height) + if err != nil { + cancel() + wg.Wait() + close(source) // close after cancel to ctx.Done() hits first + if prm.IgnoreErrors { + return false, "", nil + } + return false, "", err + } + + if op.Time == 0 { // completed get op log + close(source) + wg.Wait() + if applyErr == nil { + return true, target.ID().String(), nil + } + if prm.IgnoreErrors { + return false, "", nil + } + return false, "", applyErr + } + + select { + case <-ctx.Done(): // apply stream failed or operation cancelled + wg.Wait() + if prm.IgnoreErrors { + return false, "", nil + } + if applyErr != nil { + return false, "", applyErr + } + return false, "", ctx.Err() + case source <- &op: + } + + height = op.Time + 1 + } +} + +// findShardToEvacuateTree returns first shard according HRW or first shard with tree exists. +func (e *StorageEngine) findShardToEvacuateTree(ctx context.Context, tree pilorama.ContainerIDTreeID, + shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, +) (pooledShard, bool, error) { + hrw.SortHasherSliceByWeightValue(shards, weights, hrw.StringHash(tree.CID.EncodeToString())) + var result pooledShard + var found bool + for _, target := range shards { + select { + case <-ctx.Done(): + return pooledShard{}, false, ctx.Err() + default: + } + + if _, ok := shardsToEvacuate[target.ID().String()]; ok { + continue + } + + if !target.PiloramaEnabled() || target.GetMode().ReadOnly() { + continue + } + + if !found { + result = target + found = true + } + + exists, err := target.TreeExists(ctx, tree.CID, tree.TreeID) + if err != nil { + continue + } + if exists { + return target, true, nil + } + } + return result, found, nil +} + func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) ([]pooledShard, []float64, error) { e.mtx.RLock() defer e.mtx.RUnlock() @@ -362,9 +569,13 @@ func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) if !sh.GetMode().ReadOnly() { return nil, nil, ErrMustBeReadOnly } + + if prm.Scope.TreesOnly() && !sh.PiloramaEnabled() { + return nil, nil, fmt.Errorf("shard %s doesn't have pilorama enabled", sh.ID()) + } } - if len(e.shards)-len(shardIDs) < 1 && prm.ObjectsHandler == nil { + if len(e.shards)-len(shardIDs) < 1 && prm.ObjectsHandler == nil && prm.Scope.WithObjects() { return nil, nil, errMustHaveTwoShards } diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index cadcc29330..d234f8ee3c 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" @@ -41,6 +42,10 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng meta.WithPath(filepath.Join(dir, fmt.Sprintf("%d.metabase", id))), meta.WithPermissions(0o700), meta.WithEpochState(epochState{})), + shard.WithPiloramaOptions( + pilorama.WithPath(filepath.Join(dir, fmt.Sprintf("%d.pilorama", id))), + pilorama.WithPerm(0o700), + ), } }) e, ids := te.engine, te.shardIDs @@ -48,36 +53,32 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng require.NoError(t, e.Init(context.Background())) objects := make([]*objectSDK.Object, 0, objPerShard*len(ids)) - - for _, sh := range ids { - obj := testutil.GenerateObjectWithCID(cidtest.ID()) - objects = append(objects, obj) - - var putPrm shard.PutPrm - putPrm.SetObject(obj) - _, err := e.shards[sh.String()].Put(context.Background(), putPrm) - require.NoError(t, err) + treeID := "version" + meta := []pilorama.KeyValue{ + {Key: pilorama.AttributeVersion, Value: []byte("XXX")}, + {Key: pilorama.AttributeFilename, Value: []byte("file.txt")}, } - for i := 0; ; i++ { - objects = append(objects, testutil.GenerateObjectWithCID(cidtest.ID())) + for _, sh := range ids { + for i := 0; i < objPerShard; i++ { + contID := cidtest.ID() + obj := testutil.GenerateObjectWithCID(contID) + objects = append(objects, obj) - var putPrm PutPrm - putPrm.WithObject(objects[len(objects)-1]) + var putPrm shard.PutPrm + putPrm.SetObject(obj) + _, err := e.shards[sh.String()].Put(context.Background(), putPrm) + require.NoError(t, err) - err := e.Put(context.Background(), putPrm) - require.NoError(t, err) - - res, err := e.shards[ids[len(ids)-1].String()].List(context.Background()) - require.NoError(t, err) - if len(res.AddressList()) == objPerShard { - break + _, err = e.shards[sh.String()].TreeAddByPath(context.Background(), pilorama.CIDDescriptor{CID: contID, Position: 0, Size: 1}, + treeID, pilorama.AttributeFilename, []string{"path", "to", "the", "file"}, meta) + require.NoError(t, err) } } return e, ids, objects } -func TestEvacuateShard(t *testing.T) { +func TestEvacuateShardObjects(t *testing.T) { t.Parallel() const objPerShard = 3 @@ -103,6 +104,7 @@ func TestEvacuateShard(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[2:3] + prm.Scope = EvacuateScopeObjects t.Run("must be read-only", func(t *testing.T) { res, err := e.Evacuate(context.Background(), prm) @@ -137,7 +139,7 @@ func TestEvacuateShard(t *testing.T) { checkHasObjects(t) } -func TestEvacuateNetwork(t *testing.T) { +func TestEvacuateObjectsNetwork(t *testing.T) { t.Parallel() errReplication := errors.New("handler error") @@ -174,6 +176,7 @@ func TestEvacuateNetwork(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[0:1] + prm.Scope = EvacuateScopeObjects res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errMustHaveTwoShards) @@ -198,6 +201,7 @@ func TestEvacuateNetwork(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] prm.ObjectsHandler = acceptOneOf(objects, 2) + prm.Scope = EvacuateScopeObjects res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errReplication) @@ -235,6 +239,7 @@ func TestEvacuateNetwork(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = evacuateIDs prm.ObjectsHandler = acceptOneOf(objects, totalCount-1) + prm.Scope = EvacuateScopeObjects res, err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errReplication) @@ -270,6 +275,7 @@ func TestEvacuateCancellation(t *testing.T) { } return nil } + prm.Scope = EvacuateScopeObjects ctx, cancel := context.WithCancel(context.Background()) cancel() @@ -293,6 +299,7 @@ func TestEvacuateSingleProcess(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] + prm.Scope = EvacuateScopeObjects prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { select { case <-running: @@ -321,7 +328,7 @@ func TestEvacuateSingleProcess(t *testing.T) { require.NoError(t, eg.Wait()) } -func TestEvacuateAsync(t *testing.T) { +func TestEvacuateObjectsAsync(t *testing.T) { e, ids, _ := newEngineEvacuate(t, 2, 3) defer func() { require.NoError(t, e.Close(context.Background())) @@ -335,6 +342,7 @@ func TestEvacuateAsync(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] + prm.Scope = EvacuateScopeObjects prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { select { case <-running: @@ -393,3 +401,82 @@ func TestEvacuateAsync(t *testing.T) { require.NoError(t, eg.Wait()) } + +func TestEvacuateTreesLocal(t *testing.T) { + e, ids, _ := newEngineEvacuate(t, 2, 3) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() + + require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) + + var prm EvacuateShardPrm + prm.ShardID = ids[0:1] + prm.Scope = EvacuateScopeTrees + + expectedShardIDs := make([]string, 0, 1) + for _, id := range ids[0:1] { + expectedShardIDs = append(expectedShardIDs, id.String()) + } + + st, err := e.GetEvacuationState(context.Background()) + require.NoError(t, err, "get init state failed") + require.Equal(t, EvacuateProcessStateUndefined, st.ProcessingStatus(), "invalid init state") + require.Equal(t, uint64(0), st.TreesEvacuated(), "invalid init count") + require.Nil(t, st.StartedAt(), "invalid init started at") + require.Nil(t, st.FinishedAt(), "invalid init finished at") + require.ElementsMatch(t, []string{}, st.ShardIDs(), "invalid init shard ids") + require.Equal(t, "", st.ErrorMessage(), "invalid init error message") + + res, err := e.Evacuate(context.Background(), prm) + require.NotNil(t, res, "sync evacuation result must be not nil") + require.NoError(t, err, "evacuation failed") + + st, err = e.GetEvacuationState(context.Background()) + require.NoError(t, err, "get evacuation state failed") + require.Equal(t, EvacuateProcessStateCompleted, st.ProcessingStatus()) + + require.Equal(t, uint64(3), st.TreesTotal(), "invalid trees total count") + require.Equal(t, uint64(3), st.TreesEvacuated(), "invalid trees evacuated count") + require.Equal(t, uint64(0), st.TreesFailed(), "invalid trees failed count") + require.NotNil(t, st.StartedAt(), "invalid final started at") + require.NotNil(t, st.FinishedAt(), "invalid final finished at") + require.ElementsMatch(t, expectedShardIDs, st.ShardIDs(), "invalid final shard ids") + require.Equal(t, "", st.ErrorMessage(), "invalid final error message") + + sourceTrees, err := pilorama.TreeListAll(context.Background(), e.shards[ids[0].String()]) + require.NoError(t, err, "list source trees failed") + require.Len(t, sourceTrees, 3) + + for _, tr := range sourceTrees { + exists, err := e.shards[ids[1].String()].TreeExists(context.Background(), tr.CID, tr.TreeID) + require.NoError(t, err, "failed to check tree existance") + require.True(t, exists, "tree doesn't exists on target shard") + + var height uint64 + var sourceOps []pilorama.Move + for { + op, err := e.shards[ids[0].String()].TreeGetOpLog(context.Background(), tr.CID, tr.TreeID, height) + require.NoError(t, err) + if op.Time == 0 { + break + } + sourceOps = append(sourceOps, op) + height = op.Time + 1 + } + + height = 0 + var targetOps []pilorama.Move + for { + op, err := e.shards[ids[1].String()].TreeGetOpLog(context.Background(), tr.CID, tr.TreeID, height) + require.NoError(t, err) + if op.Time == 0 { + break + } + targetOps = append(targetOps, op) + height = op.Time + 1 + } + + require.Equal(t, sourceOps, targetOps) + } +} diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 39400391f7..61318fffc9 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -549,6 +549,58 @@ func (t *boltForest) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID string return metaerr.Wrap(err) } +// TreeApplyStream should be used with caution: this method locks other write transactions while `source` is not closed. +func (t *boltForest) TreeApplyStream(ctx context.Context, cnr cidSDK.ID, treeID string, source <-chan *Move) error { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + t.metrics.AddMethodDuration("TreeApplyStream", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "boltForest.TreeApplyStream", + trace.WithAttributes( + attribute.String("container_id", cnr.EncodeToString()), + attribute.String("tree_id", treeID), + ), + ) + defer span.End() + + t.modeMtx.RLock() + defer t.modeMtx.RUnlock() + + if t.mode.NoMetabase() { + return ErrDegradedMode + } else if t.mode.ReadOnly() { + return ErrReadOnlyMode + } + + fullID := bucketName(cnr, treeID) + err := metaerr.Wrap(t.db.Update(func(tx *bbolt.Tx) error { + bLog, bTree, err := t.getTreeBuckets(tx, fullID) + if err != nil { + return err + } + for { + select { + case <-ctx.Done(): + return ctx.Err() + case m, ok := <-source: + if !ok { + return nil + } + var lm Move + if e := t.applyOperation(bLog, bTree, []*Move{m}, &lm); e != nil { + return e + } + } + } + })) + success = err == nil + return err +} + func (t *boltForest) addBatch(cnr cidSDK.ID, treeID string, m *Move, ch chan error) { t.mtx.Lock() for i := 0; i < len(t.batches); i++ { diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index 8a1e861477..ab6174002b 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -311,3 +311,27 @@ func (f *memoryForest) TreeListTrees(_ context.Context, prm TreeListTreesPrm) (* } return &result, nil } + +// TreeApplyStream implements ForestStorage. +func (f *memoryForest) TreeApplyStream(ctx context.Context, cnr cid.ID, treeID string, source <-chan *Move) error { + fullID := cnr.String() + "/" + treeID + s, ok := f.treeMap[fullID] + if !ok { + s = newMemoryTree() + f.treeMap[fullID] = s + } + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case m, ok := <-source: + if !ok { + return nil + } + if e := s.Apply(m); e != nil { + return e + } + } + } +} diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index 3efd1a68b4..b3391407c0 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -66,6 +66,7 @@ type ForestStorage interface { // TreeListTrees returns all pairs "containerID:treeID". TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (*TreeListTreesResult, error) + TreeApplyStream(ctx context.Context, cnr cidSDK.ID, treeID string, source <-chan *Move) error } const ( @@ -107,12 +108,17 @@ type TreeListTreesResult struct { Items []ContainerIDTreeID } -func TreeListAll(ctx context.Context, f ForestStorage) ([]ContainerIDTreeID, error) { +type treeList interface { + TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (*TreeListTreesResult, error) +} + +func TreeListAll(ctx context.Context, f treeList) ([]ContainerIDTreeID, error) { return treeListAll(ctx, f, treeListTreesBatchSizeDefault) } -func treeListAll(ctx context.Context, f ForestStorage, batchSize int) ([]ContainerIDTreeID, error) { +func treeListAll(ctx context.Context, f treeList, batchSize int) ([]ContainerIDTreeID, error) { var prm TreeListTreesPrm + prm.BatchSize = batchSize var result []ContainerIDTreeID first := true @@ -129,3 +135,22 @@ func treeListAll(ctx context.Context, f ForestStorage, batchSize int) ([]Contain return result, nil } + +func TreeCountAll(ctx context.Context, f treeList) (uint64, error) { + var prm TreeListTreesPrm + var result uint64 + first := true + + for len(prm.NextPageToken) > 0 || first { + first = false + + res, err := f.TreeListTrees(ctx, prm) + if err != nil { + return 0, err + } + prm.NextPageToken = res.NextPageToken + result += uint64(len(res.Items)) + } + + return result, nil +} diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index 017b3450d9..e78f292770 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -374,3 +374,32 @@ func (s *Shard) TreeListTrees(ctx context.Context, prm pilorama.TreeListTreesPrm } return s.pilorama.TreeListTrees(ctx, prm) } + +func (s *Shard) PiloramaEnabled() bool { + return s.pilorama != nil +} + +func (s *Shard) TreeApplyStream(ctx context.Context, cnr cidSDK.ID, treeID string, source <-chan *pilorama.Move) error { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeApplyStream", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.String("container_id", cnr.EncodeToString()), + attribute.String("tree_id", treeID)), + ) + defer span.End() + + if s.pilorama == nil { + return ErrPiloramaDisabled + } + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.ReadOnly() { + return ErrReadOnlyMode + } + if s.info.Mode.NoMetabase() { + return ErrDegradedMode + } + return s.pilorama.TreeApplyStream(ctx, cnr, treeID, source) +} From db67c21d5578729c2a329e3a475ac6ca08fd1f80 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 6 Feb 2024 17:34:32 +0300 Subject: [PATCH 0330/1413] [#947] engine: Evacuate trees to remote nodes Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/control.go | 14 +- internal/logs/logs.go | 3 + pkg/local_object_storage/engine/evacuate.go | 37 +++++- .../engine/evacuate_test.go | 85 ++++++++++++ pkg/services/control/server/evacuate.go | 121 ++++++++++++++---- pkg/services/control/server/evacuate_async.go | 3 +- .../control/server/syncronize_tree.go | 7 +- pkg/services/tree/replicator.go | 108 ++++++++-------- 8 files changed, 283 insertions(+), 95 deletions(-) diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index ee2a2952a2..e1e6e3ac9e 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -9,23 +9,13 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" "google.golang.org/grpc" ) const serviceNameControl = "control" -type treeSynchronizer struct { - treeSvc *tree.Service -} - -func (t treeSynchronizer) Synchronize(ctx context.Context, cnr cid.ID, treeID string) error { - return t.treeSvc.SynchronizeTree(ctx, cnr, treeID) -} - func initControlService(c *cfg) { endpoint := controlconfig.GRPC(c.appCfg).Endpoint() if endpoint == controlconfig.GRPCEndpointDefault { @@ -50,9 +40,7 @@ func initControlService(c *cfg) { controlSvc.WithReplicator(c.replicator), controlSvc.WithNodeState(c), controlSvc.WithLocalStorage(c.cfgObject.cfgLocalStorage.localStorage), - controlSvc.WithTreeService(treeSynchronizer{ - c.treeService, - }), + controlSvc.WithTreeService(c.treeService), controlSvc.WithLocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine), ) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index c3d2e51504..d839915d82 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -575,4 +575,7 @@ const ( GetSvcV2FailedToGetRangeHashFromNode = "failed to get range hash from node" GetSvcV2FailedToGetRangeHashFromAllOfContainerNodes = "failed to get range hash from all of container nodes" FailedToUpdateShardID = "failed to update shard id" + EngineShardsEvacuationFailedToMoveTree = "failed to evacuate tree to other node" + EngineShardsEvacuationTreeEvacuatedLocal = "tree evacuated to local node" + EngineShardsEvacuationTreeEvacuatedRemote = "tree evacuated to other node" ) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 15fb69c2fd..becddfa8b7 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -17,6 +17,7 @@ import ( tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/hrw" @@ -74,6 +75,7 @@ func (s EvacuateScope) TreesOnly() bool { type EvacuateShardPrm struct { ShardID []*shard.ID ObjectsHandler func(context.Context, oid.Address, *objectSDK.Object) error + TreeHandler func(context.Context, cid.ID, string, pilorama.Forest) (string, error) IgnoreErrors bool Async bool Scope EvacuateScope @@ -436,19 +438,44 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree default: } - success, _, err := e.tryEvacuateTreeLocal(ctx, sh, contTree, prm, shards, weights, shardsToEvacuate) + success, shardID, err := e.tryEvacuateTreeLocal(ctx, sh, contTree, prm, shards, weights, shardsToEvacuate) if err != nil { return err } if success { + e.log.Debug(logs.EngineShardsEvacuationTreeEvacuatedLocal, + zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), + zap.String("from_shard_id", sh.ID().String()), zap.String("to_shard_id", shardID), + evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) res.trEvacuated.Add(1) - } else { - res.trFailed.Add(1) + continue } + + nodePK, err := e.evacuateTreeToOtherNode(ctx, sh, contTree, prm) + if err != nil { + e.log.Error(logs.EngineShardsEvacuationFailedToMoveTree, + zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), + zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + return err + } + e.log.Debug(logs.EngineShardsEvacuationTreeEvacuatedRemote, + zap.String("cid", contTree.CID.EncodeToString()), zap.String("treeID", contTree.TreeID), + zap.String("from_shardID", sh.ID().String()), zap.String("to_node", nodePK), + evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + res.trEvacuated.Add(1) } return nil } +func (e *StorageEngine) evacuateTreeToOtherNode(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, prm EvacuateShardPrm) (string, error) { + if prm.TreeHandler == nil { + return "", fmt.Errorf("failed to evacuate tree '%s' for container %s from shard %s: local evacuation failed, but no remote evacuation available", tree.TreeID, tree.CID, sh.ID()) + } + + return prm.TreeHandler(ctx, tree.CID, tree.TreeID, sh) +} + func (e *StorageEngine) tryEvacuateTreeLocal(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, prm EvacuateShardPrm, shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, ) (bool, string, error) { @@ -579,6 +606,10 @@ func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) return nil, nil, errMustHaveTwoShards } + if len(e.shards)-len(shardIDs) < 1 && prm.TreeHandler == nil && prm.Scope.WithTrees() { + return nil, nil, errMustHaveTwoShards + } + // We must have all shards, to have correct information about their // indexes in a sorted slice and set appropriate marks in the metabase. // Evacuated shard is skipped during put. diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index d234f8ee3c..32582cd2a4 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -18,6 +18,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -480,3 +481,87 @@ func TestEvacuateTreesLocal(t *testing.T) { require.Equal(t, sourceOps, targetOps) } } + +func TestEvacuateTreesRemote(t *testing.T) { + e, ids, _ := newEngineEvacuate(t, 2, 3) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() + + require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + + evacuatedTreeOps := make(map[string][]*pilorama.Move) + var prm EvacuateShardPrm + prm.ShardID = ids + prm.Scope = EvacuateScopeTrees + prm.TreeHandler = func(ctx context.Context, contID cid.ID, treeID string, f pilorama.Forest) (string, error) { + key := contID.String() + treeID + var height uint64 + for { + op, err := f.TreeGetOpLog(ctx, contID, treeID, height) + require.NoError(t, err) + + if op.Time == 0 { + return "", nil + } + evacuatedTreeOps[key] = append(evacuatedTreeOps[key], &op) + height = op.Time + 1 + } + } + + expectedShardIDs := make([]string, 0, len(ids)) + for _, id := range ids { + expectedShardIDs = append(expectedShardIDs, id.String()) + } + + st, err := e.GetEvacuationState(context.Background()) + require.NoError(t, err, "get init state failed") + require.Equal(t, EvacuateProcessStateUndefined, st.ProcessingStatus(), "invalid init state") + require.Equal(t, uint64(0), st.TreesEvacuated(), "invalid init count") + require.Nil(t, st.StartedAt(), "invalid init started at") + require.Nil(t, st.FinishedAt(), "invalid init finished at") + require.ElementsMatch(t, []string{}, st.ShardIDs(), "invalid init shard ids") + require.Equal(t, "", st.ErrorMessage(), "invalid init error message") + + res, err := e.Evacuate(context.Background(), prm) + require.NotNil(t, res, "sync evacuation must return not nil") + require.NoError(t, err, "evacuation failed") + + st, err = e.GetEvacuationState(context.Background()) + require.NoError(t, err, "get evacuation state failed") + require.Equal(t, EvacuateProcessStateCompleted, st.ProcessingStatus()) + + require.NoError(t, err, "get final state failed") + require.Equal(t, uint64(6), st.TreesTotal(), "invalid trees total count") + require.Equal(t, uint64(6), st.TreesEvacuated(), "invalid trees evacuated count") + require.Equal(t, uint64(0), st.TreesFailed(), "invalid trees failed count") + require.NotNil(t, st.StartedAt(), "invalid final started at") + require.NotNil(t, st.FinishedAt(), "invalid final finished at") + require.ElementsMatch(t, expectedShardIDs, st.ShardIDs(), "invalid final shard ids") + require.Equal(t, "", st.ErrorMessage(), "invalid final error message") + + expectedTreeOps := make(map[string][]*pilorama.Move) + for i := 0; i < len(e.shards); i++ { + sourceTrees, err := pilorama.TreeListAll(context.Background(), e.shards[ids[i].String()]) + require.NoError(t, err, "list source trees failed") + require.Len(t, sourceTrees, 3) + + for _, tr := range sourceTrees { + key := tr.CID.String() + tr.TreeID + var height uint64 + for { + op, err := e.shards[ids[i].String()].TreeGetOpLog(context.Background(), tr.CID, tr.TreeID, height) + require.NoError(t, err) + + if op.Time == 0 { + break + } + expectedTreeOps[key] = append(expectedTreeOps[key], &op) + height = op.Time + 1 + } + } + } + + require.Equal(t, expectedTreeOps, evacuatedTreeOps) +} diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index ac8b3d548f..99082b30dc 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -4,13 +4,17 @@ import ( "bytes" "context" "crypto/sha256" + "encoding/hex" "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -28,7 +32,7 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe prm := engine.EvacuateShardPrm{ ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), IgnoreErrors: req.GetBody().GetIgnoreErrors(), - ObjectsHandler: s.replicate, + ObjectsHandler: s.replicateObject, Scope: engine.EvacuateScopeObjects, } @@ -50,7 +54,7 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe return resp, nil } -func (s *Server) replicate(ctx context.Context, addr oid.Address, obj *objectSDK.Object) error { +func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *objectSDK.Object) error { cid, ok := obj.ContainerID() if !ok { // Return nil to prevent situations where a shard can't be evacuated @@ -58,33 +62,11 @@ func (s *Server) replicate(ctx context.Context, addr oid.Address, obj *objectSDK return nil } - nm, err := s.netMapSrc.GetNetMap(0) + nodes, err := s.getContainerNodes(cid) if err != nil { return err } - c, err := s.cnrSrc.Get(cid) - if err != nil { - return err - } - - binCnr := make([]byte, sha256.Size) - cid.Encode(binCnr) - - ns, err := nm.ContainerNodes(c.Value.PlacementPolicy(), binCnr) - if err != nil { - return fmt.Errorf("can't build a list of container nodes") - } - - nodes := placement.FlattenNodes(ns) - bs := (*keys.PublicKey)(&s.key.PublicKey).Bytes() - for i := 0; i < len(nodes); i++ { - if bytes.Equal(nodes[i].PublicKey(), bs) { - copy(nodes[i:], nodes[i+1:]) - nodes = nodes[:len(nodes)-1] - } - } - var res replicatorResult task := replicator.Task{ NumCopies: 1, @@ -100,6 +82,95 @@ func (s *Server) replicate(ctx context.Context, addr oid.Address, obj *objectSDK return nil } +func (s *Server) replicateTree(ctx context.Context, contID cid.ID, treeID string, forest pilorama.Forest) (string, error) { + nodes, err := s.getContainerNodes(contID) + if err != nil { + return "", err + } + if len(nodes) == 0 { + return "", fmt.Errorf("no remote nodes available to replicate tree '%s' of container %s", treeID, contID) + } + + for _, node := range nodes { + err = s.replicateTreeToNode(ctx, forest, contID, treeID, node) + if err == nil { + return hex.EncodeToString(node.PublicKey()), nil + } + } + return "", err +} + +func (s *Server) replicateTreeToNode(ctx context.Context, forest pilorama.Forest, contID cid.ID, treeID string, node netmap.NodeInfo) error { + rawCID := make([]byte, sha256.Size) + contID.Encode(rawCID) + + var height uint64 + for { + op, err := forest.TreeGetOpLog(ctx, contID, treeID, height) + if err != nil { + return err + } + + if op.Time == 0 { + return nil + } + + req := &tree.ApplyRequest{ + Body: &tree.ApplyRequest_Body{ + ContainerId: rawCID, + TreeId: treeID, + Operation: &tree.LogMove{ + ParentId: op.Parent, + Meta: op.Meta.Bytes(), + ChildId: op.Child, + }, + }, + } + + err = tree.SignMessage(req, s.key) + if err != nil { + return fmt.Errorf("can't sign apply request: %w", err) + } + + err = s.treeService.ReplicateTreeOp(ctx, node, req) + if err != nil { + return err + } + + height = op.Time + 1 + } +} + +func (s *Server) getContainerNodes(contID cid.ID) ([]netmap.NodeInfo, error) { + nm, err := s.netMapSrc.GetNetMap(0) + if err != nil { + return nil, err + } + + c, err := s.cnrSrc.Get(contID) + if err != nil { + return nil, err + } + + binCnr := make([]byte, sha256.Size) + contID.Encode(binCnr) + + ns, err := nm.ContainerNodes(c.Value.PlacementPolicy(), binCnr) + if err != nil { + return nil, fmt.Errorf("can't build a list of container nodes") + } + + nodes := placement.FlattenNodes(ns) + bs := (*keys.PublicKey)(&s.key.PublicKey).Bytes() + for i := 0; i < len(nodes); i++ { + if bytes.Equal(nodes[i].PublicKey(), bs) { + copy(nodes[i:], nodes[i+1:]) + nodes = nodes[:len(nodes)-1] + } + } + return nodes, nil +} + type replicatorResult struct { count int } diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index 91f0731c41..cd7e8a2c78 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -24,7 +24,8 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha prm := engine.EvacuateShardPrm{ ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), IgnoreErrors: req.GetBody().GetIgnoreErrors(), - ObjectsHandler: s.replicate, + ObjectsHandler: s.replicateObject, + TreeHandler: s.replicateTree, Async: true, Scope: engine.EvacuateScope(req.GetBody().GetScope()), } diff --git a/pkg/services/control/server/syncronize_tree.go b/pkg/services/control/server/syncronize_tree.go index dce3e8831a..678f87d0a9 100644 --- a/pkg/services/control/server/syncronize_tree.go +++ b/pkg/services/control/server/syncronize_tree.go @@ -4,14 +4,17 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) // TreeService represents a tree service instance. type TreeService interface { - Synchronize(ctx context.Context, cnr cid.ID, treeID string) error + SynchronizeTree(ctx context.Context, cnr cid.ID, treeID string) error + ReplicateTreeOp(ctx context.Context, n netmapSDK.NodeInfo, req *tree.ApplyRequest) error } func (s *Server) SynchronizeTree(ctx context.Context, req *control.SynchronizeTreeRequest) (*control.SynchronizeTreeResponse, error) { @@ -31,7 +34,7 @@ func (s *Server) SynchronizeTree(ctx context.Context, req *control.SynchronizeTr return nil, status.Error(codes.Internal, err.Error()) } - err = s.treeService.Synchronize(ctx, cnr, b.GetTreeId()) + err = s.treeService.SynchronizeTree(ctx, cnr, b.GetTreeId()) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 49a37b8be1..346198b3c1 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -71,61 +71,67 @@ func (s *Service) replicationWorker(ctx context.Context) { case <-s.closeCh: return case task := <-s.replicationTasks: - ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.HandleReplicationTask", - trace.WithAttributes( - attribute.String("public_key", hex.EncodeToString(task.n.PublicKey())), - ), - ) - start := time.Now() - - var lastErr error - var lastAddr string - - task.n.IterateNetworkEndpoints(func(addr string) bool { - ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.HandleReplicationTaskOnEndpoint", - trace.WithAttributes( - attribute.String("public_key", hex.EncodeToString(task.n.PublicKey())), - attribute.String("address", addr), - ), - ) - defer span.End() - - lastAddr = addr - - c, err := s.cache.get(ctx, addr) - if err != nil { - lastErr = fmt.Errorf("can't create client: %w", err) - return false - } - - ctx, cancel := context.WithTimeout(ctx, s.replicatorTimeout) - _, lastErr = c.Apply(ctx, task.req) - cancel() - - return lastErr == nil - }) - - if lastErr != nil { - if errors.Is(lastErr, errRecentlyFailed) { - s.log.Debug(logs.TreeDoNotSendUpdateToTheNode, - zap.String("last_error", lastErr.Error()), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) - } else { - s.log.Warn(logs.TreeFailedToSentUpdateToTheNode, - zap.String("last_error", lastErr.Error()), - zap.String("address", lastAddr), - zap.String("key", hex.EncodeToString(task.n.PublicKey())), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) - } - s.metrics.AddReplicateTaskDuration(time.Since(start), false) - } else { - s.metrics.AddReplicateTaskDuration(time.Since(start), true) - } - span.End() + _ = s.ReplicateTreeOp(ctx, task.n, task.req) } } } +func (s *Service) ReplicateTreeOp(ctx context.Context, n netmapSDK.NodeInfo, req *ApplyRequest) error { + ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.HandleReplicationTask", + trace.WithAttributes( + attribute.String("public_key", hex.EncodeToString(n.PublicKey())), + ), + ) + defer span.End() + + start := time.Now() + + var lastErr error + var lastAddr string + + n.IterateNetworkEndpoints(func(addr string) bool { + ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.HandleReplicationTaskOnEndpoint", + trace.WithAttributes( + attribute.String("public_key", hex.EncodeToString(n.PublicKey())), + attribute.String("address", addr), + ), + ) + defer span.End() + + lastAddr = addr + + c, err := s.cache.get(ctx, addr) + if err != nil { + lastErr = fmt.Errorf("can't create client: %w", err) + return false + } + + ctx, cancel := context.WithTimeout(ctx, s.replicatorTimeout) + _, lastErr = c.Apply(ctx, req) + cancel() + + return lastErr == nil + }) + + if lastErr != nil { + if errors.Is(lastErr, errRecentlyFailed) { + s.log.Debug(logs.TreeDoNotSendUpdateToTheNode, + zap.String("last_error", lastErr.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } else { + s.log.Warn(logs.TreeFailedToSentUpdateToTheNode, + zap.String("last_error", lastErr.Error()), + zap.String("address", lastAddr), + zap.String("key", hex.EncodeToString(n.PublicKey())), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } + s.metrics.AddReplicateTaskDuration(time.Since(start), false) + return lastErr + } + s.metrics.AddReplicateTaskDuration(time.Since(start), true) + return nil +} + func (s *Service) replicateLoop(ctx context.Context) { for i := 0; i < s.replicatorWorkerCount; i++ { go s.replicationWorker(ctx) From 60527abb65efe99ec85949d5a8f71d813d9ba386 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 8 Feb 2024 11:45:36 +0300 Subject: [PATCH 0331/1413] [#947] docs: Extend evacuation docs Add pilorama evacuation description and examples. Signed-off-by: Dmitrii Stepanov --- docs/evacuation.md | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/docs/evacuation.md b/docs/evacuation.md index 9bfa0e2145..1bccc87bfd 100644 --- a/docs/evacuation.md +++ b/docs/evacuation.md @@ -14,7 +14,7 @@ Only one running evacuation process is allowed on the node at a time. ## Commands -`frostfs-cli control shards evacuation start` starts evacuation process for shards specified. To start evacuating all node shards, use the `--all` flag. +`frostfs-cli control shards evacuation start` starts evacuation process for shards specified. To start evacuating all node shards, use the `--all` flag. By default, objects and trees are evacuated. To limit the evacuation scope, use `--scope` flag (possible values are `all`, `trees`, `objects`). `frostfs-cli control shards evacuation stop` stops running evacuation process. @@ -39,15 +39,15 @@ Shard evacuation has been successfully started. frostfs-cli control shards evacuation status --endpoint s01.frostfs.devenv:8081 --wallet ./../frostfs-dev-env/services/storage/wallet01.json Enter password > -Shard IDs: 8kEBwtvKLU3Hva3PaaodUi. Status: running. Evacuated 14 object out of 61, failed to evacuate 0 objects. Started at: 2023-05-10T10:13:06Z UTC. Duration: 00:00:03. Estimated time left: 2 minutes. +Shard IDs: 8kEBwtvKLU3Hva3PaaodUi. Status: running. Evacuated 131 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 0 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:13:06Z UTC. Duration: 00:00:03. Estimated time left: 2 minutes. frostfs-cli control shards evacuation status --endpoint s01.frostfs.devenv:8081 --wallet ./../frostfs-dev-env/services/storage/wallet01.json Enter password > -Shard IDs: 8kEBwtvKLU3Hva3PaaodUi. Status: running. Evacuated 23 object out of 61, failed to evacuate 0 objects. Started at: 2023-05-10T10:13:06Z UTC. Duration: 00:01:05. Estimated time left: 1 minutes. +Shard IDs: 8kEBwtvKLU3Hva3PaaodUi. Status: running. Evacuated 260 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 0 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:13:06Z UTC. Duration: 00:01:05. Estimated time left: 1 minutes. frostfs-cli control shards evacuation status --endpoint s01.frostfs.devenv:8081 --wallet ./../frostfs-dev-env/services/storage/wallet01.json Enter password > -Shard IDs: 8kEBwtvKLU3Hva3PaaodUi. Status: completed. Evacuated 61 object out of 61, failed to evacuate 0 objects. Started at: 2023-05-10T10:13:06Z UTC. Duration: 00:02:13. +Shard IDs: 8kEBwtvKLU3Hva3PaaodUi. Status: completed. Evacuated 618 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 19 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:13:06Z UTC. Duration: 00:02:13. ``` ### Stop running evacuation process @@ -58,7 +58,7 @@ Shard evacuation has been successfully started. frostfs-cli control shards evacuation status --endpoint s01.frostfs.devenv:8081 --wallet ./../frostfs-dev-env/services/storage/wallet01.json Enter password > -Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: running. Evacuated 15 object out of 73, failed to evacuate 0 objects. Started at: 2023-05-10T10:15:47Z UTC. Duration: 00:00:03. Estimated time left: 0 minutes. +Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: running. Evacuated 131 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 0 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:15:47Z UTC. Duration: 00:00:03. Estimated time left: 0 minutes. frostfs-cli control shards evacuation stop --endpoint s01.frostfs.devenv:8081 --wallet ./../frostfs-dev-env/services/storage/wallet01.json Enter password > @@ -66,7 +66,7 @@ Evacuation stopped. frostfs-cli control shards evacuation status --endpoint s01.frostfs.devenv:8081 --wallet ./../frostfs-dev-env/services/storage/wallet01.json Enter password > -Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: completed. Evacuated 31 object out of 73, failed to evacuate 0 objects. Error: context canceled. Started at: 2023-05-10T10:15:47Z UTC. Duration: 00:00:07. +Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: completed. Evacuated 131 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 0 trees out of 19, failed to evacuate: 0. Error: context canceled. Started at: 2023-05-10T10:15:47Z UTC. Duration: 00:00:07. ``` ### Start evacuation and await it completes @@ -75,11 +75,11 @@ frostfs-cli control shards evacuation start --endpoint s01.frostfs.devenv:8081 - Enter password > Shard evacuation has been successfully started. Progress will be reported every 5 seconds. -Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: running. Evacuated 18 object out of 73, failed to evacuate 0 objects. Started at: 2023-05-10T10:18:42Z UTC. Duration: 00:00:04. Estimated time left: 0 minutes. -Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: running. Evacuated 43 object out of 73, failed to evacuate 0 objects. Started at: 2023-05-10T10:18:42Z UTC. Duration: 00:00:09. Estimated time left: 0 minutes. -Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: running. Evacuated 68 object out of 73, failed to evacuate 0 objects. Started at: 2023-05-10T10:18:42Z UTC. Duration: 00:00:14. Estimated time left: 0 minutes. +Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: running. Evacuated 131 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 0 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:18:42Z UTC. Duration: 00:00:04. Estimated time left: 0 minutes. +Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: running. Evacuated 343 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 0 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:18:42Z UTC. Duration: 00:00:09. Estimated time left: 0 minutes. +Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Status: running. Evacuated 545 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 0 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:18:42Z UTC. Duration: 00:00:14. Estimated time left: 0 minutes. Shard evacuation has been completed. -Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Evacuated 73 object out of 73, failed to evacuate 0 objects. Started at: 2023-05-10T10:18:42Z UTC. Duration: 00:00:14. +Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Evacuated 618 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 19 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:18:42Z UTC. Duration: 00:00:14. ``` ### Start evacuation and await it completes without progress notifications @@ -88,5 +88,15 @@ frostfs-cli control shards evacuation start --endpoint s01.frostfs.devenv:8081 - Enter password > Shard evacuation has been successfully started. Shard evacuation has been completed. -Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Evacuated 73 object out of 73, failed to evacuate 0 objects. Started at: 2023-05-10T10:20:00Z UTC. Duration: 00:00:14. +Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Evacuated 618 objects out of 618, failed to evacuate: 0, skipped: 0; evacuated 19 trees out of 19, failed to evacuate: 0. Started at: 2023-05-10T10:20:00Z UTC. Duration: 00:00:14. ``` + +### Start trees evacuation and await it completes +```bash +frostfs-cli control shards evacuation start --id FxR6QujButNCHn7jjdhxGP --endpoint s01.frostfs.devenv:8081 --wallet ./../frostfs-dev-env/services/storage/wallet01.json --await --scope trees +Enter password > +Shard evacuation has been successfully started. +Progress will be reported every 5 seconds. +Shard evacuation has been completed. +Shard IDs: FxR6QujButNCHn7jjdhxGP. Evacuated 0 objects out of 0, failed to evacuate: 0, skipped: 0; evacuated 2 trees out of 2, failed to evacuate: 0. Started at: 2024-02-08T08:44:17Z UTC. Duration: 00:00:00. +``` \ No newline at end of file From d19ade23c8fa0ab5496e94c739efb7ec40d35e64 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 9 Feb 2024 09:17:17 +0300 Subject: [PATCH 0332/1413] [#959] node: Set mode to shard's components when open it Avoid opening database for `metabase` and `cache` in `Degraded` mode. Signed-off-by: Anton Nikiforov --- cmd/frostfs-lens/internal/meta/root.go | 3 +- .../blobstor/blobstor_test.go | 9 +++-- pkg/local_object_storage/blobstor/control.go | 19 +++++++++- .../blobstor/exists_test.go | 3 +- .../blobstor/iterate_test.go | 3 +- pkg/local_object_storage/blobstor/mode.go | 2 +- .../internal/storagetest/storage.go | 18 ++++----- pkg/local_object_storage/metabase/control.go | 15 +++++++- pkg/local_object_storage/metabase/db_test.go | 3 +- pkg/local_object_storage/metabase/mode.go | 24 +++++------- .../metabase/mode_test.go | 37 +++++++++++++++++++ .../metabase/version_test.go | 15 ++++---- .../pilorama/bench_test.go | 3 +- pkg/local_object_storage/pilorama/boltdb.go | 21 +++++++---- pkg/local_object_storage/pilorama/forest.go | 2 +- .../pilorama/forest_test.go | 5 ++- .../pilorama/interface.go | 2 +- .../pilorama/mode_test.go | 31 ++++++++++++++++ pkg/local_object_storage/shard/control.go | 20 ++++++---- pkg/local_object_storage/shard/id.go | 7 ++-- .../writecache/benchmark/writecache_test.go | 3 +- .../writecache/cachebbolt.go | 10 ++++- .../writecache/flush_test.go | 6 +-- .../writecache/mode_test.go | 30 +++++++++++++++ .../writecache/writecache.go | 2 +- 25 files changed, 219 insertions(+), 74 deletions(-) create mode 100644 pkg/local_object_storage/metabase/mode_test.go create mode 100644 pkg/local_object_storage/pilorama/mode_test.go create mode 100644 pkg/local_object_storage/writecache/mode_test.go diff --git a/cmd/frostfs-lens/internal/meta/root.go b/cmd/frostfs-lens/internal/meta/root.go index a59574b6cc..6741abd0cd 100644 --- a/cmd/frostfs-lens/internal/meta/root.go +++ b/cmd/frostfs-lens/internal/meta/root.go @@ -5,6 +5,7 @@ import ( common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/spf13/cobra" "go.etcd.io/bbolt" ) @@ -43,7 +44,7 @@ func openMeta(cmd *cobra.Command) *meta.DB { }), meta.WithEpochState(epochState{}), ) - common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(cmd.Context(), true))) + common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(cmd.Context(), mode.ReadOnly))) return db } diff --git a/pkg/local_object_storage/blobstor/blobstor_test.go b/pkg/local_object_storage/blobstor/blobstor_test.go index f1d567da71..3dac3bfa48 100644 --- a/pkg/local_object_storage/blobstor/blobstor_test.go +++ b/pkg/local_object_storage/blobstor/blobstor_test.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) @@ -51,7 +52,7 @@ func TestCompression(t *testing.T) { bs := New( WithCompressObjects(compress), WithStorages(defaultStorages(dir, smallSizeLimit))) - require.NoError(t, bs.Open(context.Background(), false)) + require.NoError(t, bs.Open(context.Background(), mode.ReadWrite)) require.NoError(t, bs.Init()) return bs } @@ -126,7 +127,7 @@ func TestBlobstor_needsCompression(t *testing.T) { Storage: fstree.New(fstree.WithPath(dir)), }, })) - require.NoError(t, bs.Open(context.Background(), false)) + require.NoError(t, bs.Open(context.Background(), mode.ReadWrite)) require.NoError(t, bs.Init()) return bs } @@ -188,7 +189,7 @@ func TestConcurrentPut(t *testing.T) { blobStor := New( WithStorages(defaultStorages(dir, smallSizeLimit))) - require.NoError(t, blobStor.Open(context.Background(), false)) + require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite)) require.NoError(t, blobStor.Init()) testGet := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) { @@ -268,7 +269,7 @@ func TestConcurrentDelete(t *testing.T) { blobStor := New( WithStorages(defaultStorages(dir, smallSizeLimit))) - require.NoError(t, blobStor.Open(context.Background(), false)) + require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite)) require.NoError(t, blobStor.Init()) testPut := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) { diff --git a/pkg/local_object_storage/blobstor/control.go b/pkg/local_object_storage/blobstor/control.go index 4b8a36de84..45b0c3f10b 100644 --- a/pkg/local_object_storage/blobstor/control.go +++ b/pkg/local_object_storage/blobstor/control.go @@ -6,13 +6,29 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "go.uber.org/zap" ) // Open opens BlobStor. -func (b *BlobStor) Open(ctx context.Context, readOnly bool) error { +func (b *BlobStor) Open(ctx context.Context, mode mode.Mode) error { b.log.Debug(logs.BlobstorOpening) + b.modeMtx.Lock() + defer b.modeMtx.Unlock() + b.mode = mode + + err := b.openBlobStor(ctx, mode) + if err != nil { + return err + } + b.metrics.SetMode(mode.ReadOnly()) + + return nil +} + +func (b *BlobStor) openBlobStor(ctx context.Context, mode mode.Mode) error { + readOnly := mode.ReadOnly() for i := range b.storage { select { case <-ctx.Done(): @@ -24,7 +40,6 @@ func (b *BlobStor) Open(ctx context.Context, readOnly bool) error { return err } } - b.metrics.SetMode(readOnly) return nil } diff --git a/pkg/local_object_storage/blobstor/exists_test.go b/pkg/local_object_storage/blobstor/exists_test.go index 367b63af1d..783c198b2c 100644 --- a/pkg/local_object_storage/blobstor/exists_test.go +++ b/pkg/local_object_storage/blobstor/exists_test.go @@ -7,6 +7,7 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -20,7 +21,7 @@ func TestExists(t *testing.T) { b := New(WithStorages(storages)) - require.NoError(t, b.Open(context.Background(), false)) + require.NoError(t, b.Open(context.Background(), mode.ReadWrite)) require.NoError(t, b.Init()) objects := []*objectSDK.Object{ diff --git a/pkg/local_object_storage/blobstor/iterate_test.go b/pkg/local_object_storage/blobstor/iterate_test.go index ef3fda9919..0797283804 100644 --- a/pkg/local_object_storage/blobstor/iterate_test.go +++ b/pkg/local_object_storage/blobstor/iterate_test.go @@ -7,6 +7,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" @@ -26,7 +27,7 @@ func TestIterateObjects(t *testing.T) { defer os.RemoveAll(p) // open Blobstor - require.NoError(t, blobStor.Open(context.Background(), false)) + require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite)) // initialize Blobstor require.NoError(t, blobStor.Init()) diff --git a/pkg/local_object_storage/blobstor/mode.go b/pkg/local_object_storage/blobstor/mode.go index 2f4473bd8d..dc7dad6877 100644 --- a/pkg/local_object_storage/blobstor/mode.go +++ b/pkg/local_object_storage/blobstor/mode.go @@ -22,7 +22,7 @@ func (b *BlobStor) SetMode(m mode.Mode) error { err := b.Close() if err == nil { - if err = b.Open(context.TODO(), m.ReadOnly()); err == nil { + if err = b.openBlobStor(context.TODO(), m); err == nil { err = b.Init() } } diff --git a/pkg/local_object_storage/internal/storagetest/storage.go b/pkg/local_object_storage/internal/storagetest/storage.go index ec60a2d0e7..586b3dcc65 100644 --- a/pkg/local_object_storage/internal/storagetest/storage.go +++ b/pkg/local_object_storage/internal/storagetest/storage.go @@ -10,7 +10,7 @@ import ( // Component represents single storage component. type Component interface { - Open(context.Context, bool) error + Open(context.Context, mode.Mode) error SetMode(mode.Mode) error Init() error Close() error @@ -58,18 +58,18 @@ func TestCloseAfterOpen(t *testing.T, cons Constructor) { t.Run("RW", func(t *testing.T) { // Use-case: irrecoverable error on some components, close everything. s := cons(t) - require.NoError(t, s.Open(context.Background(), false)) + require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) require.NoError(t, s.Close()) }) t.Run("RO", func(t *testing.T) { // Use-case: irrecoverable error on some components, close everything. // Open in read-only must be done after the db is here. s := cons(t) - require.NoError(t, s.Open(context.Background(), false)) + require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) require.NoError(t, s.Init()) require.NoError(t, s.Close()) - require.NoError(t, s.Open(context.Background(), true)) + require.NoError(t, s.Open(context.Background(), mode.ReadOnly)) require.NoError(t, s.Close()) }) } @@ -78,7 +78,7 @@ func TestCloseAfterOpen(t *testing.T, cons Constructor) { func TestCloseTwice(t *testing.T, cons Constructor) { // Use-case: move to maintenance mode twice, first time failed. s := cons(t) - require.NoError(t, s.Open(context.Background(), false)) + require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) require.NoError(t, s.Init()) require.NoError(t, s.Close()) require.NoError(t, s.Close()) // already closed, no-op @@ -90,12 +90,12 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { // Use-case: metabase `Init` failed, // call `SetMode` on all not-yet-initialized components. s := cons(t) - require.NoError(t, s.Open(context.Background(), false)) + require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) require.NoError(t, s.SetMode(m)) t.Run("after open in RO", func(t *testing.T) { require.NoError(t, s.Close()) - require.NoError(t, s.Open(context.Background(), true)) + require.NoError(t, s.Open(context.Background(), mode.ReadOnly)) require.NoError(t, s.SetMode(m)) }) @@ -104,7 +104,7 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { t.Run("after init", func(t *testing.T) { s := cons(t) // Use-case: notmal node operation. - require.NoError(t, s.Open(context.Background(), false)) + require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) require.NoError(t, s.Init()) require.NoError(t, s.SetMode(m)) require.NoError(t, s.Close()) @@ -114,7 +114,7 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { func TestModeTransition(t *testing.T, cons Constructor, from, to mode.Mode) { // Use-case: normal node operation. s := cons(t) - require.NoError(t, s.Open(context.Background(), false)) + require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) require.NoError(t, s.Init()) require.NoError(t, s.SetMode(from)) require.NoError(t, s.SetMode(to)) diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 00fe1e02bf..c1a86819de 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -22,7 +22,18 @@ var ErrDegradedMode = logicerr.New("metabase is in a degraded mode") var ErrReadOnlyMode = logicerr.New("metabase is in a read-only mode") // Open boltDB instance for metabase. -func (db *DB) Open(_ context.Context, readOnly bool) error { +func (db *DB) Open(_ context.Context, mode mode.Mode) error { + db.modeMtx.Lock() + defer db.modeMtx.Unlock() + db.mode = mode + + if mode.NoMetabase() { + return nil + } + return db.openDB(mode) +} + +func (db *DB) openDB(mode mode.Mode) error { err := util.MkdirAllX(filepath.Dir(db.info.Path), db.info.Permission) if err != nil { return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err) @@ -34,7 +45,7 @@ func (db *DB) Open(_ context.Context, readOnly bool) error { opts := *bbolt.DefaultOptions db.boltOptions = &opts } - db.boltOptions.ReadOnly = readOnly + db.boltOptions.ReadOnly = mode.ReadOnly() return metaerr.Wrap(db.openBolt()) } diff --git a/pkg/local_object_storage/metabase/db_test.go b/pkg/local_object_storage/metabase/db_test.go index fc20e2aade..01e1ed2bc1 100644 --- a/pkg/local_object_storage/metabase/db_test.go +++ b/pkg/local_object_storage/metabase/db_test.go @@ -9,6 +9,7 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -49,7 +50,7 @@ func newDB(t testing.TB, opts ...meta.Option) *meta.DB { }, opts...)..., ) - require.NoError(t, bdb.Open(context.Background(), false)) + require.NoError(t, bdb.Open(context.Background(), mode.ReadWrite)) require.NoError(t, bdb.Init()) return bdb diff --git a/pkg/local_object_storage/metabase/mode.go b/pkg/local_object_storage/metabase/mode.go index a18095f3e3..b382e99c26 100644 --- a/pkg/local_object_storage/metabase/mode.go +++ b/pkg/local_object_storage/metabase/mode.go @@ -1,7 +1,6 @@ package meta import ( - "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -23,21 +22,16 @@ func (db *DB) SetMode(m mode.Mode) error { } } - var err error - switch { - case m.NoMetabase(): + if m.NoMetabase() { db.boltDB = nil - case m.ReadOnly(): - err = db.Open(context.TODO(), true) - default: - err = db.Open(context.TODO(), false) - } - if err == nil && !m.NoMetabase() && !m.ReadOnly() { - err = db.Init() - } - - if err != nil { - return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err) + } else { + err := db.openDB(m) + if err == nil && !m.ReadOnly() { + err = db.Init() + } + if err != nil { + return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err) + } } db.mode = m diff --git a/pkg/local_object_storage/metabase/mode_test.go b/pkg/local_object_storage/metabase/mode_test.go new file mode 100644 index 0000000000..1b9f60055d --- /dev/null +++ b/pkg/local_object_storage/metabase/mode_test.go @@ -0,0 +1,37 @@ +package meta + +import ( + "context" + "path/filepath" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "github.com/stretchr/testify/require" +) + +type epochStateTest struct{} + +func (s epochStateTest) CurrentEpoch() uint64 { + return 0 +} + +func Test_Mode(t *testing.T) { + t.Parallel() + bdb := New([]Option{ + WithPath(filepath.Join(t.TempDir(), "metabase")), + WithPermissions(0o600), + WithEpochState(epochStateTest{}), + }...) + + require.NoError(t, bdb.Open(context.Background(), mode.DegradedReadOnly)) + require.Nil(t, bdb.boltDB) + require.NoError(t, bdb.Init()) + require.Nil(t, bdb.boltDB) + require.NoError(t, bdb.Close()) + + require.NoError(t, bdb.Open(context.Background(), mode.Degraded)) + require.Nil(t, bdb.boltDB) + require.NoError(t, bdb.Init()) + require.Nil(t, bdb.boltDB) + require.NoError(t, bdb.Close()) +} diff --git a/pkg/local_object_storage/metabase/version_test.go b/pkg/local_object_storage/metabase/version_test.go index ddeddd189c..cea42da0f4 100644 --- a/pkg/local_object_storage/metabase/version_test.go +++ b/pkg/local_object_storage/metabase/version_test.go @@ -8,6 +8,7 @@ import ( "path/filepath" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" ) @@ -43,13 +44,13 @@ func TestVersion(t *testing.T) { } t.Run("simple", func(t *testing.T) { db := newDB(t) - require.NoError(t, db.Open(context.Background(), false)) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.Init()) check(t, db) require.NoError(t, db.Close()) t.Run("reopen", func(t *testing.T) { - require.NoError(t, db.Open(context.Background(), false)) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.Init()) check(t, db) require.NoError(t, db.Close()) @@ -57,29 +58,29 @@ func TestVersion(t *testing.T) { }) t.Run("old data", func(t *testing.T) { db := newDB(t) - require.NoError(t, db.Open(context.Background(), false)) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.WriteShardID([]byte{1, 2, 3, 4})) require.NoError(t, db.Close()) - require.NoError(t, db.Open(context.Background(), false)) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.Init()) check(t, db) require.NoError(t, db.Close()) }) t.Run("invalid version", func(t *testing.T) { db := newDB(t) - require.NoError(t, db.Open(context.Background(), false)) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error { return updateVersion(tx, version+1) })) require.NoError(t, db.Close()) - require.NoError(t, db.Open(context.Background(), false)) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.Error(t, db.Init()) require.NoError(t, db.Close()) t.Run("reset", func(t *testing.T) { - require.NoError(t, db.Open(context.Background(), false)) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.Reset()) check(t, db) require.NoError(t, db.Close()) diff --git a/pkg/local_object_storage/pilorama/bench_test.go b/pkg/local_object_storage/pilorama/bench_test.go index e3f3afd992..22b951a410 100644 --- a/pkg/local_object_storage/pilorama/bench_test.go +++ b/pkg/local_object_storage/pilorama/bench_test.go @@ -8,6 +8,7 @@ import ( "sync/atomic" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/stretchr/testify/require" ) @@ -26,7 +27,7 @@ func BenchmarkCreate(b *testing.B) { f := NewBoltForest( WithPath(filepath.Join(tmpDir, "test.db")), WithMaxBatchSize(runtime.GOMAXPROCS(0))) - require.NoError(b, f.Open(context.Background(), false)) + require.NoError(b, f.Open(context.Background(), mode.ReadWrite)) require.NoError(b, f.Init()) defer func() { require.NoError(b, f.Close()) }() diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 61318fffc9..17133e8f38 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -99,7 +99,7 @@ func (t *boltForest) SetMode(m mode.Mode) error { err := t.Close() if err == nil && !m.NoMetabase() { - if err = t.Open(context.TODO(), m.ReadOnly()); err == nil { + if err = t.openBolt(m); err == nil { err = t.Init() } } @@ -112,7 +112,18 @@ func (t *boltForest) SetMode(m mode.Mode) error { return nil } -func (t *boltForest) Open(_ context.Context, readOnly bool) error { +func (t *boltForest) Open(_ context.Context, mode mode.Mode) error { + t.modeMtx.Lock() + defer t.modeMtx.Unlock() + t.mode = mode + if mode.NoMetabase() { + return nil + } + return t.openBolt(mode) +} + +func (t *boltForest) openBolt(mode mode.Mode) error { + readOnly := mode.ReadOnly() err := util.MkdirAllX(filepath.Dir(t.path), t.perm) if err != nil { return metaerr.Wrap(fmt.Errorf("can't create dir %s for the pilorama: %w", t.path, err)) @@ -131,11 +142,7 @@ func (t *boltForest) Open(_ context.Context, readOnly bool) error { t.db.MaxBatchSize = t.maxBatchSize t.db.MaxBatchDelay = t.maxBatchDelay - m := mode.ReadWrite - if readOnly { - m = mode.ReadOnly - } - t.metrics.SetMode(m) + t.metrics.SetMode(mode) return nil } diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index ab6174002b..8276490b37 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -112,7 +112,7 @@ func (f *memoryForest) Init() error { return nil } -func (f *memoryForest) Open(context.Context, bool) error { +func (f *memoryForest) Open(context.Context, mode.Mode) error { return nil } diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 2e7c1f529b..383320eb97 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -24,7 +25,7 @@ var providers = []struct { }{ {"inmemory", func(t testing.TB, _ ...Option) ForestStorage { f := NewMemoryForest() - require.NoError(t, f.Open(context.Background(), false)) + require.NoError(t, f.Open(context.Background(), mode.ReadWrite)) require.NoError(t, f.Init()) return f }}, @@ -34,7 +35,7 @@ var providers = []struct { WithPath(filepath.Join(t.TempDir(), "test.db")), WithMaxBatchSize(1), }, opts...)...) - require.NoError(t, f.Open(context.Background(), false)) + require.NoError(t, f.Open(context.Background(), mode.ReadWrite)) require.NoError(t, f.Init()) return f }}, diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index b3391407c0..5fefb2e271 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -58,7 +58,7 @@ type ForestStorage interface { // DumpInfo returns information about the pilorama. DumpInfo() Info Init() error - Open(context.Context, bool) error + Open(context.Context, mode.Mode) error Close() error SetMode(m mode.Mode) error SetParentID(id string) diff --git a/pkg/local_object_storage/pilorama/mode_test.go b/pkg/local_object_storage/pilorama/mode_test.go new file mode 100644 index 0000000000..01d3da9f0b --- /dev/null +++ b/pkg/local_object_storage/pilorama/mode_test.go @@ -0,0 +1,31 @@ +package pilorama + +import ( + "context" + "path/filepath" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "github.com/stretchr/testify/require" +) + +func Test_Mode(t *testing.T) { + t.Parallel() + f := NewBoltForest( + []Option{ + WithPath(filepath.Join(t.TempDir(), "test.db")), + WithMaxBatchSize(1), + }...) + + require.NoError(t, f.Open(context.Background(), mode.DegradedReadOnly)) + require.Nil(t, f.(*boltForest).db) + require.NoError(t, f.Init()) + require.Nil(t, f.(*boltForest).db) + require.NoError(t, f.Close()) + + require.NoError(t, f.Open(context.Background(), mode.Degraded)) + require.Nil(t, f.(*boltForest).db) + require.NoError(t, f.Init()) + require.Nil(t, f.(*boltForest).db) + require.NoError(t, f.Close()) +} diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 574bc1430e..8d1007ffda 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -43,12 +43,17 @@ func (s *Shard) handleMetabaseFailure(stage string, err error) error { // Open opens all Shard's components. func (s *Shard) Open(ctx context.Context) error { components := []interface { - Open(context.Context, bool) error + Open(context.Context, mode.Mode) error }{ - s.blobStor, s.metaBase, + s.blobStor, + } + m := s.GetMode() + + if !m.NoMetabase() { + components = append(components, s.metaBase) } - if s.hasWriteCache() { + if s.hasWriteCache() && !m.NoMetabase() { components = append(components, s.writeCache) } @@ -57,12 +62,12 @@ func (s *Shard) Open(ctx context.Context) error { } for i, component := range components { - if err := component.Open(ctx, false); err != nil { + if err := component.Open(ctx, m); err != nil { if component == s.metaBase { // We must first open all other components to avoid // opening non-existent DB in read-only mode. for j := i + 1; j < len(components); j++ { - if err := components[j].Open(ctx, false); err != nil { + if err := components[j].Open(ctx, m); err != nil { // Other components must be opened, fail. return fmt.Errorf("could not open %T: %w", components[j], err) } @@ -97,8 +102,9 @@ func (s *Shard) Init(ctx context.Context) error { } var components []initializer + m := s.GetMode() - if !s.GetMode().NoMetabase() { + if !m.NoMetabase() { var initMetabase initializer if s.NeedRefillMetabase() { @@ -114,7 +120,7 @@ func (s *Shard) Init(ctx context.Context) error { components = []initializer{s.blobStor} } - if s.hasWriteCache() { + if s.hasWriteCache() && !m.NoMetabase() { components = append(components, s.writeCache) } diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index e3c209907d..b67fd59cdf 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -31,12 +31,11 @@ func (s *Shard) ID() *ID { // UpdateID reads shard ID saved in the metabase and updates it if it is missing. func (s *Shard) UpdateID(ctx context.Context) (err error) { - var metabaseOpened bool var idFromMetabase []byte - if err = s.metaBase.Open(ctx, false); err != nil { + metabaseOpened := !s.GetMode().NoMetabase() + if err = s.metaBase.Open(ctx, s.GetMode()); err != nil { err = fmt.Errorf("failed to open metabase: %w", err) - } else { - metabaseOpened = true + metabaseOpened = false } if metabaseOpened { defer func() { diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index f7895a9357..c1c0e88b3c 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "github.com/stretchr/testify/require" ) @@ -75,7 +76,7 @@ func benchmarkPutPar(b *testing.B, cache writecache.Cache, size uint64) { } func benchmarkPutPrepare(b *testing.B, cache writecache.Cache) { - require.NoError(b, cache.Open(context.Background(), false), "opening") + require.NoError(b, cache.Open(context.Background(), mode.ReadWrite), "opening") require.NoError(b, cache.Init(), "initializing") } diff --git a/pkg/local_object_storage/writecache/cachebbolt.go b/pkg/local_object_storage/writecache/cachebbolt.go index 5eeda33a6f..2ae62c4617 100644 --- a/pkg/local_object_storage/writecache/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cachebbolt.go @@ -95,8 +95,14 @@ func (c *cache) DumpInfo() Info { } // Open opens and initializes database. Reads object counters from the ObjectCounters instance. -func (c *cache) Open(_ context.Context, readOnly bool) error { - err := c.openStore(readOnly) +func (c *cache) Open(_ context.Context, mode mode.Mode) error { + c.modeMtx.Lock() + defer c.modeMtx.Unlock() + c.mode = mode + if mode.NoMetabase() { + return nil + } + err := c.openStore(mode.ReadOnly()) if err != nil { return metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index bf68765d8f..3c951bebed 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -202,7 +202,7 @@ func newCache[Option any]( mb := meta.New( meta.WithPath(filepath.Join(dir, "meta")), meta.WithEpochState(dummyEpoch{})) - require.NoError(t, mb.Open(context.Background(), false)) + require.NoError(t, mb.Open(context.Background(), mode.ReadWrite)) require.NoError(t, mb.Init()) bs := blobstor.New(blobstor.WithStorages([]blobstor.SubStorage{ @@ -213,11 +213,11 @@ func newCache[Option any]( fstree.WithDirNameLen(1)), }, })) - require.NoError(t, bs.Open(context.Background(), false)) + require.NoError(t, bs.Open(context.Background(), mode.ReadWrite)) require.NoError(t, bs.Init()) wc := createCacheFn(t, smallSize, mb, bs, opts...) - require.NoError(t, wc.Open(context.Background(), false)) + require.NoError(t, wc.Open(context.Background(), mode.ReadWrite)) require.NoError(t, wc.Init()) // First set mode for metabase and blobstor to prevent background flushes. diff --git a/pkg/local_object_storage/writecache/mode_test.go b/pkg/local_object_storage/writecache/mode_test.go new file mode 100644 index 0000000000..f684c15bcf --- /dev/null +++ b/pkg/local_object_storage/writecache/mode_test.go @@ -0,0 +1,30 @@ +package writecache + +import ( + "context" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "github.com/stretchr/testify/require" +) + +func TestMode(t *testing.T) { + t.Parallel() + wc := New( + WithLogger(test.NewLogger(t)), + WithFlushWorkersCount(2), + WithPath(t.TempDir())) + + require.NoError(t, wc.Open(context.Background(), mode.DegradedReadOnly)) + require.Nil(t, wc.(*cache).db) + require.NoError(t, wc.Init()) + require.Nil(t, wc.(*cache).db) + require.NoError(t, wc.Close()) + + require.NoError(t, wc.Open(context.Background(), mode.Degraded)) + require.Nil(t, wc.(*cache).db) + require.NoError(t, wc.Init()) + require.Nil(t, wc.(*cache).db) + require.NoError(t, wc.Close()) +} diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 99fc5390a4..69dfee953f 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -39,7 +39,7 @@ type Cache interface { Seal(context.Context, bool) error Init() error - Open(ctx context.Context, readOnly bool) error + Open(ctx context.Context, mode mode.Mode) error Close() error } From 9a622a750dfbe159332ddf4869ab3e21e467a0fc Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 1 Feb 2024 10:26:29 +0300 Subject: [PATCH 0333/1413] [#970] fstree: Move temporary path handling in a separate function Allow to easier test different implementations. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/blobstor/fstree/fstree.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index af241becf6..3da5568e21 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -357,9 +357,12 @@ func (t *FSTree) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, err } size = len(prm.RawData) + return common.PutRes{StorageID: []byte{}}, t.writeData(p, prm.RawData) +} + +func (t *FSTree) writeData(p string, data []byte) error { tmpPath := p + "#" + strconv.FormatUint(t.suffix.Add(1), 10) - err = t.writeAndRename(tmpPath, p, prm.RawData) - return common.PutRes{StorageID: []byte{}}, err + return t.writeAndRename(tmpPath, p, data) } // writeAndRename opens tmpPath exclusively, writes data to it and renames it to p. From ff488b53a11be2e91bdf821e87d0ec6c70686ca8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 1 Feb 2024 10:28:31 +0300 Subject: [PATCH 0334/1413] [#970] fstree: Move write functions to a separate file Signed-off-by: Evgenii Stratonikov --- .../blobstor/fstree/fstree.go | 63 ---------------- .../blobstor/fstree/fstree_write_generic.go | 74 +++++++++++++++++++ 2 files changed, 74 insertions(+), 63 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 3da5568e21..7bb8db5da3 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -360,69 +360,6 @@ func (t *FSTree) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, err return common.PutRes{StorageID: []byte{}}, t.writeData(p, prm.RawData) } -func (t *FSTree) writeData(p string, data []byte) error { - tmpPath := p + "#" + strconv.FormatUint(t.suffix.Add(1), 10) - return t.writeAndRename(tmpPath, p, data) -} - -// writeAndRename opens tmpPath exclusively, writes data to it and renames it to p. -func (t *FSTree) writeAndRename(tmpPath, p string, data []byte) error { - if t.fileCounterEnabled { - t.fileGuard.Lock(p) - defer t.fileGuard.Unlock(p) - } - - err := t.writeFile(tmpPath, data) - if err != nil { - var pe *fs.PathError - if errors.As(err, &pe) { - switch pe.Err { - case syscall.ENOSPC: - err = common.ErrNoSpace - _ = os.RemoveAll(tmpPath) - } - } - return err - } - - if t.fileCounterEnabled { - t.fileCounter.Inc() - var targetFileExists bool - if _, e := os.Stat(p); e == nil { - targetFileExists = true - } - err = os.Rename(tmpPath, p) - if err == nil && targetFileExists { - t.fileCounter.Dec() - } - } else { - err = os.Rename(tmpPath, p) - } - return err -} - -func (t *FSTree) writeFlags() int { - flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_EXCL - if t.noSync { - return flags - } - return flags | os.O_SYNC -} - -// writeFile writes data to a file with path p. -// The code is copied from `os.WriteFile` with minor corrections for flags. -func (t *FSTree) writeFile(p string, data []byte) error { - f, err := os.OpenFile(p, t.writeFlags(), t.Permissions) - if err != nil { - return err - } - _, err = f.Write(data) - if err1 := f.Close(); err1 != nil && err == nil { - err = err1 - } - return err -} - // Get returns an object from the storage by address. func (t *FSTree) Get(ctx context.Context, prm common.GetPrm) (common.GetRes, error) { var ( diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go new file mode 100644 index 0000000000..4119140345 --- /dev/null +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -0,0 +1,74 @@ +package fstree + +import ( + "errors" + "io/fs" + "os" + "strconv" + "syscall" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" +) + +func (t *FSTree) writeData(p string, data []byte) error { + tmpPath := p + "#" + strconv.FormatUint(t.suffix.Add(1), 10) + return t.writeAndRename(tmpPath, p, data) +} + +// writeAndRename opens tmpPath exclusively, writes data to it and renames it to p. +func (t *FSTree) writeAndRename(tmpPath, p string, data []byte) error { + if t.fileCounterEnabled { + t.fileGuard.Lock(p) + defer t.fileGuard.Unlock(p) + } + + err := t.writeFile(tmpPath, data) + if err != nil { + var pe *fs.PathError + if errors.As(err, &pe) { + switch pe.Err { + case syscall.ENOSPC: + err = common.ErrNoSpace + _ = os.RemoveAll(tmpPath) + } + } + return err + } + + if t.fileCounterEnabled { + t.fileCounter.Inc() + var targetFileExists bool + if _, e := os.Stat(p); e == nil { + targetFileExists = true + } + err = os.Rename(tmpPath, p) + if err == nil && targetFileExists { + t.fileCounter.Dec() + } + } else { + err = os.Rename(tmpPath, p) + } + return err +} + +func (t *FSTree) writeFlags() int { + flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_EXCL + if t.noSync { + return flags + } + return flags | os.O_SYNC +} + +// writeFile writes data to a file with path p. +// The code is copied from `os.WriteFile` with minor corrections for flags. +func (t *FSTree) writeFile(p string, data []byte) error { + f, err := os.OpenFile(p, t.writeFlags(), t.Permissions) + if err != nil { + return err + } + _, err = f.Write(data) + if err1 := f.Close(); err1 != nil && err == nil { + err = err1 + } + return err +} From fc31b9c947bf7185ec252e2e63d615a6c59b16ab Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 9 Sep 2023 11:16:06 +0300 Subject: [PATCH 0335/1413] [#970] fstree: Add linux-specific file writer using O_TMPFILE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O_TMPFILE is implemented for all modern FSes and it's much easier and safer to use. If application crashes in the middle of writing this file would be gone and won't leave any garbage. Notice that this implementation makes a different choice wrt EEXIST handling, generic one always overwrites, while this one keeps the old data. There is no real performance difference. SSD (slow&old), XFS, Core i7-8565U: Sync ``` name old time/op new time/op delta Put/size=1024,thread=1/fstree-8 1.74ms ± 3% 0.06ms ± 7% -96.31% (p=0.000 n=10+10) Put/size=1024,thread=20/fstree-8 10.0ms ±41% 1.1ms ±18% -88.95% (p=0.000 n=9+10) Put/size=1024,thread=100/fstree-8 32.3ms ±60% 6.5ms ±14% -79.97% (p=0.000 n=10+10) Put/size=1048576,thread=1/fstree-8 17.8ms ±90% 3.4ms ±70% -81.08% (p=0.000 n=10+10) Put/size=1048576,thread=20/fstree-8 103ms ±174% 112ms ±158% ~ (p=0.971 n=10+10) Put/size=1048576,thread=100/fstree-8 949ms ±78% 583ms ±132% ~ (p=0.089 n=10+10) name old alloc/op new alloc/op delta Put/size=1024,thread=1/fstree-8 3.17kB ± 1% 1.96kB ± 0% -38.09% (p=0.000 n=10+10) Put/size=1024,thread=20/fstree-8 59.6kB ± 1% 39.2kB ± 1% -34.30% (p=0.000 n=8+10) Put/size=1024,thread=100/fstree-8 299kB ± 0% 198kB ± 0% -33.90% (p=0.000 n=7+9) Put/size=1048576,thread=1/fstree-8 3.38kB ± 1% 2.36kB ± 1% -30.22% (p=0.000 n=10+10) Put/size=1048576,thread=20/fstree-8 65.7kB ± 4% 47.7kB ± 6% -27.27% (p=0.000 n=10+10) Put/size=1048576,thread=100/fstree-8 351kB ± 8% 245kB ± 8% -30.22% (p=0.000 n=10+10) name old allocs/op new allocs/op delta Put/size=1024,thread=1/fstree-8 30.3 ± 2% 21.0 ± 0% -30.69% (p=0.000 n=10+10) Put/size=1024,thread=20/fstree-8 554 ± 1% 413 ± 0% -25.35% (p=0.000 n=8+10) Put/size=1024,thread=100/fstree-8 2.77k ± 0% 2.07k ± 0% -25.27% (p=0.000 n=7+10) Put/size=1048576,thread=1/fstree-8 32.0 ± 0% 25.0 ± 0% -21.88% (p=0.000 n=9+8) Put/size=1048576,thread=20/fstree-8 609 ± 5% 494 ± 6% -18.93% (p=0.000 n=10+10) Put/size=1048576,thread=100/fstree-8 3.25k ± 9% 2.50k ± 8% -23.21% (p=0.000 n=10+10) ``` No sync ``` name old time/op new time/op delta Put/size=1024,thread=1/fstree-8 71.3µs ±10% 59.8µs ±10% -16.21% (p=0.000 n=10+10) Put/size=1024,thread=20/fstree-8 1.43ms ± 6% 1.22ms ±13% -14.53% (p=0.000 n=10+10) Put/size=1024,thread=100/fstree-8 8.12ms ± 3% 6.36ms ± 2% -21.67% (p=0.000 n=8+9) Put/size=1048576,thread=1/fstree-8 1.88ms ±70% 1.61ms ±78% ~ (p=0.393 n=10+10) Put/size=1048576,thread=20/fstree-8 32.7ms ±28% 34.2ms ±112% ~ (p=0.968 n=9+10) Put/size=1048576,thread=100/fstree-8 262ms ±56% 226ms ±34% ~ (p=0.447 n=10+9) name old alloc/op new alloc/op delta Put/size=1024,thread=1/fstree-8 2.89kB ± 0% 1.96kB ± 0% -32.28% (p=0.000 n=10+10) Put/size=1024,thread=20/fstree-8 58.2kB ± 0% 39.5kB ± 0% -32.09% (p=0.000 n=8+8) Put/size=1024,thread=100/fstree-8 291kB ± 0% 198kB ± 0% -32.19% (p=0.000 n=9+9) Put/size=1048576,thread=1/fstree-8 3.05kB ± 1% 2.13kB ± 1% -30.16% (p=0.000 n=10+9) Put/size=1048576,thread=20/fstree-8 62.6kB ± 0% 44.3kB ± 0% -29.23% (p=0.000 n=9+9) Put/size=1048576,thread=100/fstree-8 302kB ± 0% 210kB ± 1% -30.39% (p=0.000 n=9+9) name old allocs/op new allocs/op delta Put/size=1024,thread=1/fstree-8 27.0 ± 0% 21.0 ± 0% -22.22% (p=0.000 n=10+10) Put/size=1024,thread=20/fstree-8 539 ± 0% 415 ± 0% -22.98% (p=0.000 n=10+10) Put/size=1024,thread=100/fstree-8 2.69k ± 0% 2.07k ± 0% -23.09% (p=0.000 n=9+9) Put/size=1048576,thread=1/fstree-8 28.0 ± 0% 22.3 ± 3% -20.36% (p=0.000 n=8+10) Put/size=1048576,thread=20/fstree-8 577 ± 0% 458 ± 0% -20.72% (p=0.000 n=9+9) Put/size=1048576,thread=100/fstree-8 2.76k ± 0% 2.15k ± 0% -22.05% (p=0.000 n=9+8) ``` HDD (LVM), ext4, Ryzen 5 1600: Sync ``` │ fs.sync-generic │ fs.sync-linux │ │ sec/op │ sec/op vs base │ Put/size=1024,thread=1/fstree-12 34.70m ± 19% 33.59m ± 16% ~ (p=0.529 n=10) Put/size=1024,thread=20/fstree-12 188.8m ± 8% 189.2m ± 16% ~ (p=0.739 n=10) Put/size=1024,thread=100/fstree-12 264.8m ± 22% 273.6m ± 28% ~ (p=0.353 n=10) Put/size=1048576,thread=1/fstree-12 54.90m ± 14% 47.08m ± 18% ~ (p=0.063 n=10) Put/size=1048576,thread=20/fstree-12 244.1m ± 14% 220.4m ± 22% ~ (p=0.579 n=10) Put/size=1048576,thread=100/fstree-12 847.2m ± 5% 893.6m ± 3% +5.48% (p=0.000 n=10) geomean 164.3m 158.9m -3.29% │ fs.sync-generic │ fs.sync-linux │ │ B/op │ B/op vs base │ Put/size=1024,thread=1/fstree-12 3.375Ki ± 1% 2.471Ki ± 1% -26.80% (p=0.000 n=10) Put/size=1024,thread=20/fstree-12 66.62Ki ± 6% 49.21Ki ± 6% -26.15% (p=0.000 n=10) Put/size=1024,thread=100/fstree-12 319.2Ki ± 1% 230.9Ki ± 2% -27.64% (p=0.000 n=10) Put/size=1048576,thread=1/fstree-12 3.457Ki ± 1% 2.559Ki ± 1% -25.97% (p=0.000 n=10) Put/size=1048576,thread=20/fstree-12 66.91Ki ± 1% 49.16Ki ± 1% -26.52% (p=0.000 n=10) Put/size=1048576,thread=100/fstree-12 338.8Ki ± 2% 252.3Ki ± 3% -25.54% (p=0.000 n=10) geomean 42.17Ki 31.02Ki -26.44% │ fs.sync-generic │ fs.sync-linux │ │ allocs/op │ allocs/op vs base │ Put/size=1024,thread=1/fstree-12 33.00 ± 0% 27.00 ± 0% -18.18% (p=0.000 n=10) Put/size=1024,thread=20/fstree-12 639.5 ± 1% 519.0 ± 2% -18.84% (p=0.000 n=10) Put/size=1024,thread=100/fstree-12 3.059k ± 1% 2.478k ± 2% -18.99% (p=0.000 n=10) Put/size=1048576,thread=1/fstree-12 33.50 ± 1% 28.00 ± 4% -16.42% (p=0.000 n=10) Put/size=1048576,thread=20/fstree-12 638.5 ± 1% 520.0 ± 1% -18.56% (p=0.000 n=10) Put/size=1048576,thread=100/fstree-12 3.209k ± 2% 2.655k ± 2% -17.28% (p=0.000 n=10) geomean 405.3 332.1 -18.05% ``` No sync ``` │ fs.nosync-generic │ fs.nosync-linux │ │ sec/op │ sec/op vs base │ Put/size=1024,thread=1/fstree-12 148.2µ ± 20% 136.6µ ± 19% -7.89% (p=0.029 n=10) Put/size=1024,thread=20/fstree-12 1.140m ± 26% 1.364m ± 16% ~ (p=0.143 n=10) Put/size=1024,thread=100/fstree-12 11.93m ± 68% 26.89m ± 62% ~ (p=0.123 n=10) Put/size=1048576,thread=1/fstree-12 1.302m ± 3% 1.287m ± 5% ~ (p=0.481 n=10) Put/size=1048576,thread=20/fstree-12 77.52m ± 8% 74.07m ± 7% ~ (p=0.278 n=10+9) Put/size=1048576,thread=100/fstree-12 226.1m ± ∞ ¹ geomean 5.986m 3.434m +18.60% ² ¹ need >= 6 samples for confidence interval at level 0.95 ² benchmark set differs from baseline; geomeans may not be comparable │ fs.nosync-generic │ fs.nosync-linux │ │ B/op │ B/op vs base │ Put/size=1024,thread=1/fstree-12 2.879Ki ± 0% 1.972Ki ± 0% -31.51% (p=0.000 n=10) Put/size=1024,thread=20/fstree-12 55.94Ki ± 1% 37.90Ki ± 1% -32.25% (p=0.000 n=10) Put/size=1024,thread=100/fstree-12 272.6Ki ± 0% 182.1Ki ± 9% -33.21% (p=0.000 n=10) Put/size=1048576,thread=1/fstree-12 3.158Ki ± 0% 2.259Ki ± 0% -28.46% (p=0.000 n=10) Put/size=1048576,thread=20/fstree-12 58.87Ki ± 0% 41.03Ki ± 0% -30.30% (p=0.000 n=10+9) Put/size=1048576,thread=100/fstree-12 299.8Ki ± ∞ ¹ geomean 36.71Ki 16.60Ki -31.17% ² ¹ need >= 6 samples for confidence interval at level 0.95 ² benchmark set differs from baseline; geomeans may not be comparable │ fs.nosync-generic │ fs.nosync-linux │ │ allocs/op │ allocs/op vs base │ Put/size=1024,thread=1/fstree-12 28.00 ± 0% 22.00 ± 0% -21.43% (p=0.000 n=10) Put/size=1024,thread=20/fstree-12 530.0 ± 0% 407.5 ± 1% -23.11% (p=0.000 n=10) Put/size=1024,thread=100/fstree-12 2.567k ± 0% 1.956k ± 9% -23.77% (p=0.000 n=10) Put/size=1048576,thread=1/fstree-12 30.00 ± 0% 24.00 ± 0% -20.00% (p=0.000 n=10) Put/size=1048576,thread=20/fstree-12 553.5 ± 0% 434.0 ± 0% -21.59% (n=10+9) Put/size=1048576,thread=100/fstree-12 2.803k ± ∞ ¹ geomean 347.9 178.8 -21.99% ² ¹ need >= 6 samples for confidence interval at level 0.95 ² benchmark set differs from baseline; geomeans may not be comparable ``` Signed-off-by: Roman Khimov Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- .../blobstor/fstree/fstree_write_generic.go | 2 + .../blobstor/fstree/fstree_write_linux.go | 48 +++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go diff --git a/go.mod b/go.mod index 5d6edc2223..06d2d32997 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a golang.org/x/sync v0.6.0 + golang.org/x/sys v0.16.0 golang.org/x/term v0.16.0 google.golang.org/grpc v1.61.0 google.golang.org/protobuf v1.32.0 @@ -120,7 +121,6 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 4119140345..0882be0ddc 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -1,3 +1,5 @@ +//go:build !linux + package fstree import ( diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go new file mode 100644 index 0000000000..edb7f0dce0 --- /dev/null +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -0,0 +1,48 @@ +//go:build linux + +package fstree + +import ( + "errors" + "strconv" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "golang.org/x/sys/unix" +) + +func (t *FSTree) writeData(p string, data []byte) error { + err := t.writeFile(p, data) + if errors.Is(err, unix.ENOSPC) { + return common.ErrNoSpace + } + return err +} + +func (t *FSTree) writeFile(p string, data []byte) error { + flags := unix.O_WRONLY | unix.O_TMPFILE | unix.O_CLOEXEC + if !t.noSync { + flags |= unix.O_DSYNC + } + fd, err := unix.Open(t.RootPath, flags, uint32(t.Permissions)) + if err != nil { + return err + } + tmpPath := "/proc/self/fd/" + strconv.FormatUint(uint64(fd), 10) + n, err := unix.Write(fd, data) + if err == nil { + if n == len(data) { + err = unix.Linkat(unix.AT_FDCWD, tmpPath, unix.AT_FDCWD, p, unix.AT_SYMLINK_FOLLOW) + if errors.Is(err, unix.EEXIST) { + // https://github.com/nspcc-dev/neofs-node/issues/2563 + err = nil + } + } else { + err = errors.New("incomplete write") + } + } + errClose := unix.Close(fd) + if err != nil { + return err // Close() error is ignored, we have a better one. + } + return errClose +} From 7f692409cf1a25167446f9094d8ba7b8bd678f8e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 8 Feb 2024 11:57:23 +0300 Subject: [PATCH 0336/1413] [#970] fstree: Handle unsupported O_TMPFILE Metabase test relied on this behaviour, so fix the test too. Cherry-picking was hard and did too many conflicts, here is an original PR: https://github.com/nspcc-dev/neofs-node/pull/2624 Signed-off-by: Evgenii Stratonikov --- .../blobstor/fstree/control.go | 7 +++ .../blobstor/fstree/fstree.go | 4 +- .../blobstor/fstree/fstree_write_generic.go | 58 +++++++++++-------- .../blobstor/fstree/fstree_write_linux.go | 46 ++++++++++++--- .../blobstor/fstree/fstree_write_specific.go | 9 +++ .../shard/control_test.go | 10 +++- 6 files changed, 97 insertions(+), 37 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go diff --git a/pkg/local_object_storage/blobstor/fstree/control.go b/pkg/local_object_storage/blobstor/fstree/control.go index c56312d38b..b126f8d293 100644 --- a/pkg/local_object_storage/blobstor/fstree/control.go +++ b/pkg/local_object_storage/blobstor/fstree/control.go @@ -16,6 +16,13 @@ func (t *FSTree) Init() error { if err := util.MkdirAllX(t.RootPath, t.Permissions); err != nil { return err } + if !t.readOnly { + f := newSpecificWriteData(t.fileCounter, t.RootPath, t.Permissions, t.noSync) + if f != nil { + t.writeData = f + } + } + return t.initFileCounter() } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 7bb8db5da3..fc29d4eaab 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -10,7 +10,6 @@ import ( "path/filepath" "strconv" "strings" - "sync/atomic" "syscall" "time" @@ -58,7 +57,7 @@ type FSTree struct { fileCounter FileCounter fileCounterEnabled bool - suffix atomic.Uint64 + writeData func(string, []byte) error } // Info groups the information about file storage. @@ -96,6 +95,7 @@ func New(opts ...Option) *FSTree { for i := range opts { opts[i](f) } + f.writeData = newGenericWriteData(f) return f } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 0882be0ddc..3d65808ecb 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -1,5 +1,3 @@ -//go:build !linux - package fstree import ( @@ -7,24 +5,46 @@ import ( "io/fs" "os" "strconv" + "sync/atomic" "syscall" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" ) -func (t *FSTree) writeData(p string, data []byte) error { - tmpPath := p + "#" + strconv.FormatUint(t.suffix.Add(1), 10) - return t.writeAndRename(tmpPath, p, data) +type genericWriter struct { + perm fs.FileMode + flags int + + t *FSTree + suffix atomic.Uint64 +} + +func newGenericWriteData(t *FSTree) func(string, []byte) error { + flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_EXCL + if !t.noSync { + flags |= os.O_SYNC + } + var w = &genericWriter{ + perm: t.Permissions, + flags: flags, + t: t, + } + return w.writeData +} + +func (w *genericWriter) writeData(p string, data []byte) error { + tmpPath := p + "#" + strconv.FormatUint(w.suffix.Add(1), 10) + return w.writeAndRename(tmpPath, p, data) } // writeAndRename opens tmpPath exclusively, writes data to it and renames it to p. -func (t *FSTree) writeAndRename(tmpPath, p string, data []byte) error { - if t.fileCounterEnabled { - t.fileGuard.Lock(p) - defer t.fileGuard.Unlock(p) +func (w *genericWriter) writeAndRename(tmpPath, p string, data []byte) error { + if w.t.fileCounterEnabled { + w.t.fileGuard.Lock(p) + defer w.t.fileGuard.Unlock(p) } - err := t.writeFile(tmpPath, data) + err := w.writeFile(tmpPath, data) if err != nil { var pe *fs.PathError if errors.As(err, &pe) { @@ -37,15 +57,15 @@ func (t *FSTree) writeAndRename(tmpPath, p string, data []byte) error { return err } - if t.fileCounterEnabled { - t.fileCounter.Inc() + if w.t.fileCounterEnabled { + w.t.fileCounter.Inc() var targetFileExists bool if _, e := os.Stat(p); e == nil { targetFileExists = true } err = os.Rename(tmpPath, p) if err == nil && targetFileExists { - t.fileCounter.Dec() + w.t.fileCounter.Dec() } } else { err = os.Rename(tmpPath, p) @@ -53,18 +73,10 @@ func (t *FSTree) writeAndRename(tmpPath, p string, data []byte) error { return err } -func (t *FSTree) writeFlags() int { - flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_EXCL - if t.noSync { - return flags - } - return flags | os.O_SYNC -} - // writeFile writes data to a file with path p. // The code is copied from `os.WriteFile` with minor corrections for flags. -func (t *FSTree) writeFile(p string, data []byte) error { - f, err := os.OpenFile(p, t.writeFlags(), t.Permissions) +func (w *genericWriter) writeFile(p string, data []byte) error { + f, err := os.OpenFile(p, w.flags, w.perm) if err != nil { return err } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index edb7f0dce0..3416cf7ac2 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -4,26 +4,52 @@ package fstree import ( "errors" + "io/fs" "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "golang.org/x/sys/unix" ) -func (t *FSTree) writeData(p string, data []byte) error { - err := t.writeFile(p, data) +type linuxWriter struct { + root string + perm uint32 + flags int + + counter FileCounter +} + +func newSpecificWriteData(c FileCounter, root string, perm fs.FileMode, noSync bool) func(string, []byte) error { + flags := unix.O_WRONLY | unix.O_TMPFILE | unix.O_CLOEXEC + if !noSync { + flags |= unix.O_DSYNC + } + fd, err := unix.Open(root, flags, uint32(perm)) + if err != nil { + // Which means that OS-specific writeData can't be created + // and FSTree should use the generic one. + return nil + } + _ = unix.Close(fd) // Don't care about error. + w := &linuxWriter{ + root: root, + perm: uint32(perm), + flags: flags, + counter: c, + } + return w.writeData +} + +func (w *linuxWriter) writeData(p string, data []byte) error { + err := w.writeFile(p, data) if errors.Is(err, unix.ENOSPC) { return common.ErrNoSpace } return err } -func (t *FSTree) writeFile(p string, data []byte) error { - flags := unix.O_WRONLY | unix.O_TMPFILE | unix.O_CLOEXEC - if !t.noSync { - flags |= unix.O_DSYNC - } - fd, err := unix.Open(t.RootPath, flags, uint32(t.Permissions)) +func (w *linuxWriter) writeFile(p string, data []byte) error { + fd, err := unix.Open(w.root, w.flags, w.perm) if err != nil { return err } @@ -32,8 +58,10 @@ func (t *FSTree) writeFile(p string, data []byte) error { if err == nil { if n == len(data) { err = unix.Linkat(unix.AT_FDCWD, tmpPath, unix.AT_FDCWD, p, unix.AT_SYMLINK_FOLLOW) + if err == nil { + w.counter.Inc() + } if errors.Is(err, unix.EEXIST) { - // https://github.com/nspcc-dev/neofs-node/issues/2563 err = nil } } else { diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go new file mode 100644 index 0000000000..16b630b6ad --- /dev/null +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go @@ -0,0 +1,9 @@ +//go:build !linux + +package fstree + +import "io/fs" + +func newSpecificWriteData(_ FileCounter, _ string, _ fs.FileMode, _ bool) func(string, []byte) error { + return nil +} diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 4d7354595b..d08747e13e 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -2,6 +2,7 @@ package shard import ( "context" + "fmt" "io/fs" "math" "os" @@ -11,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" @@ -145,8 +145,12 @@ func TestRefillMetabaseCorrupted(t *testing.T) { require.NoError(t, sh.Close()) addr := object.AddressOf(obj) - _, err = fsTree.Put(context.Background(), common.PutPrm{Address: addr, RawData: []byte("not an object")}) - require.NoError(t, err) + // This is copied from `fstree.treePath()` to avoid exporting function just for tests. + { + saddr := addr.Object().EncodeToString() + "." + addr.Container().EncodeToString() + p := fmt.Sprintf("%s/%s/%s", fsTree.RootPath, saddr[:2], saddr[2:]) + require.NoError(t, os.WriteFile(p, []byte("not an object"), fsTree.Permissions)) + } sh = New( WithID(NewIDFromBytes([]byte{})), From fb74524ac73eaa1f46b63c06389035ae9b4b9bed Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 8 Feb 2024 17:53:27 +0300 Subject: [PATCH 0337/1413] [#970] fstree: Move delete implementation to a separate file Signed-off-by: Evgenii Stratonikov --- .../blobstor/fstree/control.go | 2 +- .../blobstor/fstree/fstree.go | 22 +++----------- .../blobstor/fstree/fstree_write_generic.go | 30 +++++++++++++++++-- .../blobstor/fstree/fstree_write_linux.go | 17 +++++++++-- .../blobstor/fstree/fstree_write_specific.go | 6 ++-- 5 files changed, 52 insertions(+), 25 deletions(-) diff --git a/pkg/local_object_storage/blobstor/fstree/control.go b/pkg/local_object_storage/blobstor/fstree/control.go index b126f8d293..cec531f2e8 100644 --- a/pkg/local_object_storage/blobstor/fstree/control.go +++ b/pkg/local_object_storage/blobstor/fstree/control.go @@ -19,7 +19,7 @@ func (t *FSTree) Init() error { if !t.readOnly { f := newSpecificWriteData(t.fileCounter, t.RootPath, t.Permissions, t.noSync) if f != nil { - t.writeData = f + t.writer = f } } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index fc29d4eaab..ba691b0567 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -57,7 +57,7 @@ type FSTree struct { fileCounter FileCounter fileCounterEnabled bool - writeData func(string, []byte) error + writer writer } // Info groups the information about file storage. @@ -95,7 +95,7 @@ func New(opts ...Option) *FSTree { for i := range opts { opts[i](f) } - f.writeData = newGenericWriteData(f) + f.writer = newGenericWriteData(f) return f } @@ -266,21 +266,7 @@ func (t *FSTree) Delete(ctx context.Context, prm common.DeletePrm) (common.Delet } p := t.treePath(prm.Address) - - if t.fileCounterEnabled { - t.fileGuard.Lock(p) - err = os.Remove(p) - t.fileGuard.Unlock(p) - if err == nil { - t.fileCounter.Dec() - } - } else { - err = os.Remove(p) - } - - if err != nil && os.IsNotExist(err) { - err = logicerr.Wrap(new(apistatus.ObjectNotFound)) - } + err = t.writer.removeFile(p) return common.DeleteRes{}, err } @@ -357,7 +343,7 @@ func (t *FSTree) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, err } size = len(prm.RawData) - return common.PutRes{StorageID: []byte{}}, t.writeData(p, prm.RawData) + return common.PutRes{StorageID: []byte{}}, t.writer.writeData(p, prm.RawData) } // Get returns an object from the storage by address. diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 3d65808ecb..e1e3a53bb7 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -9,8 +9,15 @@ import ( "syscall" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) +type writer interface { + writeData(string, []byte) error + removeFile(string) error +} + type genericWriter struct { perm fs.FileMode flags int @@ -19,7 +26,7 @@ type genericWriter struct { suffix atomic.Uint64 } -func newGenericWriteData(t *FSTree) func(string, []byte) error { +func newGenericWriteData(t *FSTree) writer { flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_EXCL if !t.noSync { flags |= os.O_SYNC @@ -29,7 +36,7 @@ func newGenericWriteData(t *FSTree) func(string, []byte) error { flags: flags, t: t, } - return w.writeData + return w } func (w *genericWriter) writeData(p string, data []byte) error { @@ -86,3 +93,22 @@ func (w *genericWriter) writeFile(p string, data []byte) error { } return err } + +func (w *genericWriter) removeFile(p string) error { + var err error + if w.t.fileCounterEnabled { + w.t.fileGuard.Lock(p) + err = os.Remove(p) + w.t.fileGuard.Unlock(p) + if err == nil { + w.t.fileCounter.Dec() + } + } else { + err = os.Remove(p) + } + + if err != nil && os.IsNotExist(err) { + err = logicerr.Wrap(new(apistatus.ObjectNotFound)) + } + return err +} diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index 3416cf7ac2..a77c9d1b25 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -8,6 +8,8 @@ import ( "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "golang.org/x/sys/unix" ) @@ -19,7 +21,7 @@ type linuxWriter struct { counter FileCounter } -func newSpecificWriteData(c FileCounter, root string, perm fs.FileMode, noSync bool) func(string, []byte) error { +func newSpecificWriteData(c FileCounter, root string, perm fs.FileMode, noSync bool) writer { flags := unix.O_WRONLY | unix.O_TMPFILE | unix.O_CLOEXEC if !noSync { flags |= unix.O_DSYNC @@ -37,7 +39,7 @@ func newSpecificWriteData(c FileCounter, root string, perm fs.FileMode, noSync b flags: flags, counter: c, } - return w.writeData + return w } func (w *linuxWriter) writeData(p string, data []byte) error { @@ -74,3 +76,14 @@ func (w *linuxWriter) writeFile(p string, data []byte) error { } return errClose } + +func (w *linuxWriter) removeFile(p string) error { + err := unix.Unlink(p) + if err != nil && err == unix.ENOENT { + return logicerr.Wrap(new(apistatus.ObjectNotFound)) + } + if err == nil { + w.counter.Dec() + } + return err +} diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go index 16b630b6ad..9bd559366d 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go @@ -2,8 +2,10 @@ package fstree -import "io/fs" +import ( + "io/fs" +) -func newSpecificWriteData(_ FileCounter, _ string, _ fs.FileMode, _ bool) func(string, []byte) error { +func newSpecificWriteData(_ FileCounter, _ string, _ fs.FileMode, _ bool) writer { return nil } From abd502215f0fc0c8e6454eeeeb54b9c83c680dc4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 8 Feb 2024 18:04:18 +0300 Subject: [PATCH 0338/1413] [#970] fstree: Move file locking to the generic writer It is not a part of FSTree itself, but rather a way to solve concurrent counter update on non-linux implementations. New linux implementations is pretty simple: link fails when the file exists, unlink fails when the file doesn't exist. Signed-off-by: Evgenii Stratonikov --- .../blobstor/fstree/counter.go | 5 +++ .../blobstor/fstree/fstree.go | 9 ++-- .../blobstor/fstree/fstree_write_generic.go | 45 ++++++++++++------- .../blobstor/fstree/option.go | 3 -- 4 files changed, 37 insertions(+), 25 deletions(-) diff --git a/pkg/local_object_storage/blobstor/fstree/counter.go b/pkg/local_object_storage/blobstor/fstree/counter.go index 70b346093f..718104e2ea 100644 --- a/pkg/local_object_storage/blobstor/fstree/counter.go +++ b/pkg/local_object_storage/blobstor/fstree/counter.go @@ -18,6 +18,11 @@ func (c *noopCounter) Set(uint64) {} func (c *noopCounter) Inc() {} func (c *noopCounter) Dec() {} +func counterEnabled(c FileCounter) bool { + _, noop := c.(*noopCounter) + return !noop +} + type SimpleCounter struct { v atomic.Uint64 } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index ba691b0567..76ce5bf175 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -53,9 +53,7 @@ type FSTree struct { readOnly bool metrics Metrics - fileGuard keyLock - fileCounter FileCounter - fileCounterEnabled bool + fileCounter FileCounter writer writer } @@ -88,14 +86,13 @@ func New(opts ...Option) *FSTree { Depth: 4, DirNameLen: DirNameLen, metrics: &noopMetrics{}, - fileGuard: &noopKeyLock{}, fileCounter: &noopCounter{}, log: &logger.Logger{Logger: zap.L()}, } for i := range opts { opts[i](f) } - f.writer = newGenericWriteData(f) + f.writer = newGenericWriteData(f.fileCounter, f.Permissions, f.noSync) return f } @@ -444,7 +441,7 @@ func (t *FSTree) GetRange(ctx context.Context, prm common.GetRangePrm) (common.G // initFileCounter walks the file tree rooted at FSTree's root, // counts total items count, inits counter and returns number of stored objects. func (t *FSTree) initFileCounter() error { - if !t.fileCounterEnabled { + if !counterEnabled(t.fileCounter) { return nil } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index e1e3a53bb7..8080769596 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) @@ -22,19 +23,31 @@ type genericWriter struct { perm fs.FileMode flags int - t *FSTree - suffix atomic.Uint64 + fileGuard keyLock + fileCounter FileCounter + fileCounterEnabled bool + suffix atomic.Uint64 } -func newGenericWriteData(t *FSTree) writer { +func newGenericWriteData(c FileCounter, perm fs.FileMode, noSync bool) writer { flags := os.O_WRONLY | os.O_CREATE | os.O_TRUNC | os.O_EXCL - if !t.noSync { + if !noSync { flags |= os.O_SYNC } + + var fileGuard keyLock = &noopKeyLock{} + fileCounterEnabled := counterEnabled(c) + if fileCounterEnabled { + fileGuard = utilSync.NewKeyLocker[string]() + } + var w = &genericWriter{ - perm: t.Permissions, + perm: perm, flags: flags, - t: t, + + fileCounterEnabled: fileCounterEnabled, + fileGuard: fileGuard, + fileCounter: c, } return w } @@ -46,9 +59,9 @@ func (w *genericWriter) writeData(p string, data []byte) error { // writeAndRename opens tmpPath exclusively, writes data to it and renames it to p. func (w *genericWriter) writeAndRename(tmpPath, p string, data []byte) error { - if w.t.fileCounterEnabled { - w.t.fileGuard.Lock(p) - defer w.t.fileGuard.Unlock(p) + if w.fileCounterEnabled { + w.fileGuard.Lock(p) + defer w.fileGuard.Unlock(p) } err := w.writeFile(tmpPath, data) @@ -64,15 +77,15 @@ func (w *genericWriter) writeAndRename(tmpPath, p string, data []byte) error { return err } - if w.t.fileCounterEnabled { - w.t.fileCounter.Inc() + if w.fileCounterEnabled { + w.fileCounter.Inc() var targetFileExists bool if _, e := os.Stat(p); e == nil { targetFileExists = true } err = os.Rename(tmpPath, p) if err == nil && targetFileExists { - w.t.fileCounter.Dec() + w.fileCounter.Dec() } } else { err = os.Rename(tmpPath, p) @@ -96,12 +109,12 @@ func (w *genericWriter) writeFile(p string, data []byte) error { func (w *genericWriter) removeFile(p string) error { var err error - if w.t.fileCounterEnabled { - w.t.fileGuard.Lock(p) + if w.fileCounterEnabled { + w.fileGuard.Lock(p) err = os.Remove(p) - w.t.fileGuard.Unlock(p) + w.fileGuard.Unlock(p) if err == nil { - w.t.fileCounter.Dec() + w.fileCounter.Dec() } } else { err = os.Remove(p) diff --git a/pkg/local_object_storage/blobstor/fstree/option.go b/pkg/local_object_storage/blobstor/fstree/option.go index e6c7a26080..4d1f8fc22d 100644 --- a/pkg/local_object_storage/blobstor/fstree/option.go +++ b/pkg/local_object_storage/blobstor/fstree/option.go @@ -4,7 +4,6 @@ import ( "io/fs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" "go.uber.org/zap" ) @@ -48,9 +47,7 @@ func WithMetrics(m Metrics) Option { func WithFileCounter(c FileCounter) Option { return func(f *FSTree) { - f.fileCounterEnabled = true f.fileCounter = c - f.fileGuard = utilSync.NewKeyLocker[string]() } } From b36a45323859ffb2c19c56ce5253967609f008db Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 8 Feb 2024 21:07:02 +0300 Subject: [PATCH 0339/1413] [#970] fstree: Add build tag to enable generic version on linux Unless tested, generic version can start gaining bugs. With a separate build tag we can have the best of both worlds: 1. Use optimized implementation for linux by default. 2. Run tests or benchmarks for both. Note that they are not actually run automatically now, but this is at leas possible. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go | 2 +- .../blobstor/fstree/fstree_write_specific.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index a77c9d1b25..efc5a3d3d4 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -1,4 +1,4 @@ -//go:build linux +//go:build linux && !fstree_generic package fstree diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go index 9bd559366d..67052d9477 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_specific.go @@ -1,4 +1,4 @@ -//go:build !linux +//go:build !linux || fstree_generic package fstree From 962e5a9c19be08398ac2d84a590b553d0f8cd4c8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 8 Feb 2024 17:04:58 +0300 Subject: [PATCH 0340/1413] [#736] logger: Add journald support Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-ir/main.go | 4 ++ cmd/frostfs-node/config.go | 9 ++- cmd/frostfs-node/config/logger/config.go | 18 ++++++ cmd/frostfs-node/config/logger/config_test.go | 8 +-- cmd/frostfs-node/validate.go | 5 ++ config/example/node.env | 1 + config/example/node.json | 3 +- config/example/node.yaml | 1 + go.mod | 2 + go.sum | 4 ++ pkg/util/logger/logger.go | 59 +++++++++++++++++++ 11 files changed, 108 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 2b39f78e3f..9879342b7e 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -68,6 +68,10 @@ func main() { cfg.GetString("logger.level"), ) exitErr(err) + err = logPrm.SetDestination( + cfg.GetString("logger.destination"), + ) + exitErr(err) logPrm.SamplingHook = metrics.LogMetrics().GetSamplingHook() log, err = logger.NewLogger(logPrm) exitErr(err) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index c41863ecd2..50219a8c7b 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -96,7 +96,8 @@ type applicationConfiguration struct { _read bool LoggerCfg struct { - level string + level string + destination string } EngineCfg struct { @@ -209,6 +210,7 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { // Logger a.LoggerCfg.level = loggerconfig.Level(c) + a.LoggerCfg.destination = loggerconfig.Destination(c) // Storage Engine @@ -1004,6 +1006,11 @@ func (c *cfg) loggerPrm() (*logger.Prm, error) { // not expected since validation should be performed before panic(fmt.Sprintf("incorrect log level format: %s", c.LoggerCfg.level)) } + err = c.dynamicConfiguration.logger.SetDestination(c.LoggerCfg.destination) + if err != nil { + // not expected since validation should be performed before + panic(fmt.Sprintf("incorrect log destination format: %s", c.LoggerCfg.destination)) + } return c.dynamicConfiguration.logger, nil } diff --git a/cmd/frostfs-node/config/logger/config.go b/cmd/frostfs-node/config/logger/config.go index 02645c5430..378b9d7939 100644 --- a/cmd/frostfs-node/config/logger/config.go +++ b/cmd/frostfs-node/config/logger/config.go @@ -5,12 +5,14 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/logging/lokicore/loki" ) const ( // LevelDefault is a default logger level. LevelDefault = "info" + DestinationDefault = logger.DestinationStdout subsection = "logger" lokiSubsection = "loki" AddressDefault = "localhost:3100" @@ -34,6 +36,22 @@ func Level(c *config.Config) string { return LevelDefault } +// Destination returns the value of "destination" config parameter +// from "logger" section. +// +// Returns DestinationDefault if the value is not a non-empty string. +func Destination(c *config.Config) string { + v := config.StringSafe( + c.Sub(subsection), + "destination", + ) + if v != "" { + return v + } + + return DestinationDefault +} + // ToLokiConfig extracts loki config. func ToLokiConfig(c *config.Config) loki.Config { hostname, _ := os.Hostname() diff --git a/cmd/frostfs-node/config/logger/config_test.go b/cmd/frostfs-node/config/logger/config_test.go index 8a0acbd85d..3587a0ddb0 100644 --- a/cmd/frostfs-node/config/logger/config_test.go +++ b/cmd/frostfs-node/config/logger/config_test.go @@ -11,15 +11,15 @@ import ( func TestLoggerSection_Level(t *testing.T) { t.Run("defaults", func(t *testing.T) { - v := loggerconfig.Level(configtest.EmptyConfig()) - require.Equal(t, loggerconfig.LevelDefault, v) + require.Equal(t, loggerconfig.LevelDefault, loggerconfig.Level(configtest.EmptyConfig())) + require.Equal(t, loggerconfig.DestinationDefault, loggerconfig.Destination(configtest.EmptyConfig())) }) const path = "../../../../config/example/node" fileConfigTest := func(c *config.Config) { - v := loggerconfig.Level(c) - require.Equal(t, "debug", v) + require.Equal(t, "debug", loggerconfig.Level(c)) + require.Equal(t, "journald", loggerconfig.Destination(c)) } configtest.ForEachFileType(path, fileConfigTest) diff --git a/cmd/frostfs-node/validate.go b/cmd/frostfs-node/validate.go index 80c90ec44e..ae52b9e4ab 100644 --- a/cmd/frostfs-node/validate.go +++ b/cmd/frostfs-node/validate.go @@ -25,6 +25,11 @@ func validateConfig(c *config.Config) error { return fmt.Errorf("invalid logger level: %w", err) } + err = loggerPrm.SetDestination(loggerconfig.Destination(c)) + if err != nil { + return fmt.Errorf("invalid logger destination: %w", err) + } + // shard configuration validation shardNum := 0 diff --git a/config/example/node.env b/config/example/node.env index 2972f56e9c..a1db0c8761 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -1,4 +1,5 @@ FROSTFS_LOGGER_LEVEL=debug +FROSTFS_LOGGER_DESTINATION=journald FROSTFS_PPROF_ENABLED=true FROSTFS_PPROF_ADDRESS=localhost:6060 diff --git a/config/example/node.json b/config/example/node.json index 8dda5e6069..a7d7a36511 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -1,6 +1,7 @@ { "logger": { - "level": "debug" + "level": "debug", + "destination": "journald" }, "pprof": { "enabled": true, diff --git a/config/example/node.yaml b/config/example/node.yaml index 1715151648..678ee1a87b 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -1,5 +1,6 @@ logger: level: debug # logger level: one of "debug", "info" (default), "warn", "error", "dpanic", "panic", "fatal" + destination: journald # logger destination: one of "stdout" (default), "journald" systemdnotify: enabled: true diff --git a/go.mod b/go.mod index 06d2d32997..aa771f1e7e 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 + git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 @@ -30,6 +31,7 @@ require ( github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.18.2 + github.com/ssgreg/journald v1.0.0 github.com/stretchr/testify v1.8.4 go.etcd.io/bbolt v1.3.8 go.opentelemetry.io/otel v1.22.0 diff --git a/go.sum b/go.sum index b9052efde5..e152363316 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,8 @@ git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9m git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= git.frostfs.info/TrueCloudLab/tzhash v1.8.0/go.mod h1:dhY+oy274hV8wGvGL4MwwMpdL3GYvaX1a8GQZQHvlF8= +git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 h1:HeY8n27VyPRQe49l/fzyVMkWEB2fsLJYKp64pwA7tz4= +git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02/go.mod h1:rQFJJdEOV7KbbMtQYR2lNfiZk+ONRDJSbMCTWxKt8Fw= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= @@ -247,6 +249,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/ssgreg/journald v1.0.0 h1:0YmTDPJXxcWDPba12qNMdO6TxvfkFSYpFIJ31CwmLcU= +github.com/ssgreg/journald v1.0.0/go.mod h1:RUckwmTM8ghGWPslq2+ZBZzbb9/2KgjzYZ4JEP+oRt0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index f9a5fe38f4..c6db04df9f 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -1,6 +1,10 @@ package logger import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/zapjournald" + "github.com/ssgreg/journald" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) @@ -35,8 +39,15 @@ type Prm struct { SamplingHook func(e zapcore.Entry, sd zapcore.SamplingDecision) // do not support runtime rereading + dest string } +const ( + DestinationUndefined = "" + DestinationStdout = "stdout" + DestinationJournald = "journald" +) + // SetLevelString sets the minimum logging level. Default is // "info". // @@ -48,6 +59,16 @@ func (p *Prm) SetLevelString(s string) error { return p.level.UnmarshalText([]byte(s)) } +func (p *Prm) SetDestination(d string) error { + if d != DestinationStdout && d != DestinationJournald { + return fmt.Errorf("invalid logger destination %s", d) + } + if p != nil { + p.dest = d + } + return nil +} + // Reload reloads configuration of a connected instance of the Logger. // Returns ErrLoggerNotConnected if no connection has been performed. // Returns any reconfiguration error from the Logger directly. @@ -79,7 +100,17 @@ func NewLogger(prm *Prm) (*Logger, error) { if prm == nil { prm = defaultPrm() } + switch prm.dest { + case DestinationUndefined, DestinationStdout: + return newConsoleLogger(prm) + case DestinationJournald: + return newJournaldLogger(prm) + default: + return nil, fmt.Errorf("unknown destination %s", prm.dest) + } +} +func newConsoleLogger(prm *Prm) (*Logger, error) { lvl := zap.NewAtomicLevelAt(prm.level) c := zap.NewProductionConfig() @@ -103,6 +134,34 @@ func NewLogger(prm *Prm) (*Logger, error) { return l, nil } +func newJournaldLogger(prm *Prm) (*Logger, error) { + lvl := zap.NewAtomicLevelAt(prm.level) + + c := zap.NewProductionConfig() + c.Level = lvl + c.Encoding = "console" + c.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + if prm.SamplingHook != nil { + c.Sampling.Hook = prm.SamplingHook + } + + encoder := zapjournald.NewPartialEncoder(zapcore.NewConsoleEncoder(c.EncoderConfig), zapjournald.SyslogFields) + + core := zapjournald.NewCore(zap.NewAtomicLevelAt(prm.level), encoder, &journald.Journal{}, zapjournald.SyslogFields) + coreWithContext := core.With([]zapcore.Field{ + zapjournald.SyslogFacility(zapjournald.LogDaemon), + zapjournald.SyslogIdentifier(), + zapjournald.SyslogPid(), + }) + + lZap := zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel))) + + l := &Logger{Logger: lZap, lvl: lvl} + prm._log = l + + return l, nil +} + func (l *Logger) reload(prm Prm) error { l.lvl.SetLevel(prm.level) return nil From 3a41858a0f2b02f426d37abe9d9a39ca1835436f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 12 Feb 2024 13:28:37 +0300 Subject: [PATCH 0341/1413] [#975] ir: Add default logger destination Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-ir/defaults.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-ir/defaults.go b/cmd/frostfs-ir/defaults.go index a7fe8d5639..127a68b29b 100644 --- a/cmd/frostfs-ir/defaults.go +++ b/cmd/frostfs-ir/defaults.go @@ -8,6 +8,7 @@ import ( func defaultConfiguration(cfg *viper.Viper) { cfg.SetDefault("logger.level", "info") + cfg.SetDefault("logger.destination", "stdout") setPprofDefaults(cfg) From 6a5769d1da019edef19c9e23aaa9c55e80281199 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 13 Feb 2024 09:09:09 +0300 Subject: [PATCH 0342/1413] [#948] Fix `gofumpt` issue Signed-off-by: Anton Nikiforov --- .../blobstor/fstree/fstree_write_generic.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 8080769596..8b26228855 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -41,7 +41,7 @@ func newGenericWriteData(c FileCounter, perm fs.FileMode, noSync bool) writer { fileGuard = utilSync.NewKeyLocker[string]() } - var w = &genericWriter{ + w := &genericWriter{ perm: perm, flags: flags, From 0bd030507ef7f0d6a47a8f310d3de03804a8d416 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 13 Feb 2024 09:09:47 +0300 Subject: [PATCH 0343/1413] [#948] metrics: Set actual value for `shard_id` after restart Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/engine/metrics.go | 4 ++++ pkg/local_object_storage/engine/writecache.go | 4 ++++ pkg/local_object_storage/shard/control.go | 3 +++ pkg/local_object_storage/shard/gc.go | 2 ++ pkg/local_object_storage/shard/id.go | 7 ++++++- pkg/local_object_storage/writecache/cachebbolt.go | 4 ++++ pkg/local_object_storage/writecache/metrics.go | 3 +++ pkg/local_object_storage/writecache/writecache.go | 1 + 8 files changed, 27 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index e4117bb1af..91dfa87625 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -44,6 +44,10 @@ type gcMetrics struct { shardID string } +func (m *gcMetrics) SetShardID(id string) { + m.shardID = id +} + func (m *gcMetrics) AddRunDuration(d time.Duration, success bool) { m.storage.AddRunDuration(m.shardID, d, success) } diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 0eca018f83..f30bce00d7 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -145,6 +145,10 @@ type writeCacheMetrics struct { metrics metrics.WriteCacheMetrics } +func (m *writeCacheMetrics) SetShardID(id string) { + m.shardID = id +} + func (m *writeCacheMetrics) Get(d time.Duration, success bool, st writecache.StorageType) { m.metrics.AddMethodDuration(m.shardID, "Get", success, d, st.String()) } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 8d1007ffda..408354b557 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -166,6 +166,9 @@ func (s *Shard) Init(ctx context.Context) error { }, }, } + if s.gc.metrics != nil { + s.gc.metrics.SetShardID(s.info.ID.String()) + } s.gc.init(ctx) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 24c3a337a2..83be3259a8 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -81,6 +81,7 @@ const ( ) type GCMectrics interface { + SetShardID(string) AddRunDuration(d time.Duration, success bool) AddDeletedCount(deleted, failed uint64) AddExpiredObjectCollectionDuration(d time.Duration, success bool, objectType string) @@ -89,6 +90,7 @@ type GCMectrics interface { type noopGCMetrics struct{} +func (m *noopGCMetrics) SetShardID(string) {} func (m *noopGCMetrics) AddRunDuration(time.Duration, bool) {} func (m *noopGCMetrics) AddDeletedCount(uint64, uint64) {} func (m *noopGCMetrics) AddExpiredObjectCollectionDuration(time.Duration, bool, string) {} diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index b67fd59cdf..be474e0fa8 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -53,9 +53,14 @@ func (s *Shard) UpdateID(ctx context.Context) (err error) { s.info.ID = NewIDFromBytes(idFromMetabase) } + shardID := s.info.ID.String() if s.cfg.metricsWriter != nil { - s.cfg.metricsWriter.SetShardID(s.info.ID.String()) + s.cfg.metricsWriter.SetShardID(shardID) } + if s.writeCache != nil && s.writeCache.GetMetrics() != nil { + s.writeCache.GetMetrics().SetShardID(shardID) + } + s.log = &logger.Logger{Logger: s.log.With(zap.Stringer("shard_id", s.info.ID))} s.metaBase.SetLogger(s.log) s.blobStor.SetLogger(s.log) diff --git a/pkg/local_object_storage/writecache/cachebbolt.go b/pkg/local_object_storage/writecache/cachebbolt.go index 2ae62c4617..fdba8d409c 100644 --- a/pkg/local_object_storage/writecache/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cachebbolt.go @@ -146,3 +146,7 @@ func (c *cache) Close() error { c.metrics.Close() return nil } + +func (c *cache) GetMetrics() Metrics { + return c.metrics +} diff --git a/pkg/local_object_storage/writecache/metrics.go b/pkg/local_object_storage/writecache/metrics.go index 5eac06698d..492e0973ac 100644 --- a/pkg/local_object_storage/writecache/metrics.go +++ b/pkg/local_object_storage/writecache/metrics.go @@ -19,6 +19,7 @@ const ( ) type Metrics interface { + SetShardID(string) Get(d time.Duration, success bool, st StorageType) Delete(d time.Duration, success bool, st StorageType) Put(d time.Duration, success bool, st StorageType) @@ -35,6 +36,8 @@ func DefaultMetrics() Metrics { return metricsStub{} } type metricsStub struct{} +func (metricsStub) SetShardID(string) {} + func (metricsStub) Get(time.Duration, bool, StorageType) {} func (metricsStub) Delete(time.Duration, bool, StorageType) {} diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 69dfee953f..112594ec09 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -41,6 +41,7 @@ type Cache interface { Init() error Open(ctx context.Context, mode mode.Mode) error Close() error + GetMetrics() Metrics } // MainStorage is the interface of the underlying storage of Cache implementations. From cda3a3d83440ffab9ec415376cc085bea802c027 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 31 Jan 2024 17:26:26 +0300 Subject: [PATCH 0344/1413] [#932] adm: Refactor command `morph` Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/ape.go | 21 +-- .../internal/modules/morph/ape_util.go | 9 +- .../internal/modules/morph/balance.go | 9 +- .../internal/modules/morph/config.go | 3 +- .../internal/modules/morph/container.go | 5 +- .../internal/modules/morph/deploy.go | 5 +- .../internal/modules/morph/dump_hashes.go | 7 +- .../internal/modules/morph/frostfsid.go | 47 +++--- .../internal/modules/morph/generate.go | 8 +- .../internal/modules/morph/generate_test.go | 3 +- .../internal/modules/morph/initialize.go | 144 +++--------------- .../modules/morph/initialize_deploy.go | 3 +- .../internal/modules/morph/initialize_nns.go | 5 +- .../modules/morph/initialize_register.go | 5 +- .../modules/morph/initialize_roles.go | 3 +- .../internal/modules/morph/initialize_test.go | 19 +-- .../modules/morph/initialize_transfer.go | 11 +- .../modules/morph/netmap_candidates.go | 3 +- .../internal/modules/morph/notary.go | 5 +- .../internal/modules/morph/policy.go | 3 +- .../internal/modules/morph/root.go | 88 ++++++----- .../internal/modules/morph/util/const.go | 15 ++ .../internal/modules/morph/util/initialize.go | 90 +++++++++++ .../modules/morph/{ => util}/local_client.go | 46 +++--- .../modules/morph/{ => util}/n3client.go | 45 ++++-- .../internal/modules/morph/{ => util}/util.go | 12 +- 26 files changed, 324 insertions(+), 290 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/const.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/initialize.go rename cmd/frostfs-adm/internal/modules/morph/{ => util}/local_client.go (89%) rename cmd/frostfs-adm/internal/modules/morph/{ => util}/n3client.go (72%) rename cmd/frostfs-adm/internal/modules/morph/{ => util}/util.go (86%) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape.go index 9f1d75adba..5ff6e7ab83 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -41,7 +42,7 @@ var ( Use: "add-rule-chain", Short: "Add rule chain", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: addRuleChain, @@ -51,7 +52,7 @@ var ( Use: "rm-rule-chain", Short: "Remove rule chain", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: removeRuleChain, @@ -61,7 +62,7 @@ var ( Use: "list-rule-chains", Short: "List rule chains", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: listRuleChains, @@ -71,7 +72,7 @@ var ( Use: "set-admin", Short: "Set admin", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: setAdmin, @@ -81,7 +82,7 @@ var ( Use: "get-admin", Short: "Get admin", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: getAdmin, @@ -91,7 +92,7 @@ var ( func initAddRuleChainCmd() { apeCmd.AddCommand(addRuleChainCmd) - addRuleChainCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + addRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) addRuleChainCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) @@ -110,7 +111,7 @@ func initAddRuleChainCmd() { func initRemoveRuleChainCmd() { apeCmd.AddCommand(removeRuleChainCmd) - removeRuleChainCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + removeRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) removeRuleChainCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) @@ -124,7 +125,7 @@ func initRemoveRuleChainCmd() { func initListRuleChainsCmd() { apeCmd.AddCommand(listRuleChainsCmd) - listRuleChainsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + listRuleChainsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) listRuleChainsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) _ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag) @@ -136,7 +137,7 @@ func initListRuleChainsCmd() { func initSetAdminCmd() { apeCmd.AddCommand(setAdminCmd) - setAdminCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + setAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) setAdminCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) setAdminCmd.Flags().String(addrAdminFlag, "", addrAdminDesc) _ = setAdminCmd.MarkFlagRequired(addrAdminFlag) @@ -145,7 +146,7 @@ func initSetAdminCmd() { func initGetAdminCmd() { apeCmd.AddCommand(getAdminCmd) - getAdminCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + getAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) getAdminCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape_util.go index f64a7e1085..30668532b9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape_util.go @@ -6,6 +6,7 @@ import ( "os" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -77,17 +78,17 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *actor.Actor) { v := viper.GetViper() - c, err := getN3Client(v) + c, err := morphUtil.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) - wallets, err := getAlphabetWallets(v, walletDir) + wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) - committeeAcc, err := getWalletAccount(wallets[0], committeeAccountName) + committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], committeeAccountName) commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) - ac, err := newActor(c, committeeAcc) + ac, err := morphUtil.NewActor(c, committeeAcc) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) inv := &ac.Invoker diff --git a/cmd/frostfs-adm/internal/modules/morph/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance.go index 0fee45a8fd..b4259e11e0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance.go @@ -7,6 +7,7 @@ import ( "math/big" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -49,7 +50,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { nmHash util.Uint160 ) - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return err } @@ -150,7 +151,7 @@ func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash return nil } -func printAlphabetContractBalances(cmd *cobra.Command, c Client, inv *invoker.Invoker, count int, nnsHash util.Uint160) error { +func printAlphabetContractBalances(cmd *cobra.Command, c morphUtil.Client, inv *invoker.Invoker, count int, nnsHash util.Uint160) error { alphaList := make([]accBalancePair, count) w := io.NewBufBinWriter() @@ -184,7 +185,7 @@ func printAlphabetContractBalances(cmd *cobra.Command, c Client, inv *invoker.In return nil } -func fetchIRNodes(c Client, desigHash util.Uint160) ([]accBalancePair, error) { +func fetchIRNodes(c morphUtil.Client, desigHash util.Uint160) ([]accBalancePair, error) { inv := invoker.New(c, nil) height, err := c.GetBlockCount() @@ -192,7 +193,7 @@ func fetchIRNodes(c Client, desigHash util.Uint160) ([]accBalancePair, error) { return nil, fmt.Errorf("can't get block height: %w", err) } - arr, err := getDesignatedByRole(inv, desigHash, noderoles.NeoFSAlphabet, height) + arr, err := morphUtil.GetDesignatedByRole(inv, desigHash, noderoles.NeoFSAlphabet, height) if err != nil { return nil, errors.New("can't fetch list of IR nodes from the netmap contract") } diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index db7d2ab8e5..d9ddcb8ade 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -10,6 +10,7 @@ import ( "strings" "text/tabwriter" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -24,7 +25,7 @@ import ( const forceConfigSet = "force" func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { - c, err := getN3Client(viper.GetViper()) + c, err := util.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index e7a7f5466a..b9db4c4e57 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -7,6 +7,7 @@ import ( "os" "sort" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/io" @@ -73,7 +74,7 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid filename: %w", err) } - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -163,7 +164,7 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo } func listContainers(cmd *cobra.Command, _ []string) error { - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index 1facd6d105..db54a8db5f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -7,6 +7,7 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -38,7 +39,7 @@ Contract's manifest file name must be 'config.json'. NNS name is taken by stripping '_contract.nef' from the NEF file (similar to frostfs contracts).`, PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: deployContractCmd, } @@ -49,7 +50,7 @@ func init() { ff.String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) _ = deployCmd.MarkFlagFilename(alphabetWalletsFlag) - ff.StringP(endpointFlag, "r", "", endpointFlagDesc) + ff.StringP(util.EndpointFlag, "r", "", util.EndpointFlagDesc) ff.String(contractPathFlag, "", "Path to the contract directory") _ = deployCmd.MarkFlagFilename(contractPathFlag) diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index 14a492c5fe..60e9de9ca7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -8,6 +8,7 @@ import ( "text/tabwriter" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -33,7 +34,7 @@ type contractDumpInfo struct { } func dumpContractHashes(cmd *cobra.Command, _ []string) error { - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -110,7 +111,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return nil } -func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c Client) error { +func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c morphUtil.Client) error { const nnsMaxTokens = 100 inv := invoker.New(c, nil) @@ -224,7 +225,7 @@ func printContractInfo(cmd *cobra.Command, infos []contractDumpInfo) { cmd.Print(buf.String()) } -func fillContractVersion(cmd *cobra.Command, c Client, infos []contractDumpInfo) { +func fillContractVersion(cmd *cobra.Command, c morphUtil.Client, infos []contractDumpInfo) { bw := io.NewBufBinWriter() sub := io.NewBufBinWriter() for i := range infos { diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 50cd477445..8150dcb5f5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -6,6 +6,7 @@ import ( "sort" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -41,7 +42,7 @@ var ( Short: "Create new namespace in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateNamespace, } @@ -51,7 +52,7 @@ var ( Short: "List all namespaces in frostfsid", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListNamespaces, } @@ -61,7 +62,7 @@ var ( Short: "Create subject in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateSubject, } @@ -71,7 +72,7 @@ var ( Short: "Delete subject from frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidDeleteSubject, } @@ -81,7 +82,7 @@ var ( Short: "List subjects in namespace", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListSubjects, } @@ -91,7 +92,7 @@ var ( Short: "Create group in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateGroup, } @@ -101,7 +102,7 @@ var ( Short: "Delete group from frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidDeleteGroup, } @@ -111,7 +112,7 @@ var ( Short: "List groups in namespace", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListGroups, } @@ -121,7 +122,7 @@ var ( Short: "Add subject to group", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidAddSubjectToGroup, } @@ -131,7 +132,7 @@ var ( Short: "Remove subject from group", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidRemoveSubjectFromGroup, } @@ -141,7 +142,7 @@ var ( Short: "List subjects in group", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListGroupSubjects, } @@ -149,20 +150,20 @@ var ( func initFrostfsIDCreateNamespaceCmd() { frostfsidCmd.AddCommand(frostfsidCreateNamespaceCmd) - frostfsidCreateNamespaceCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateNamespaceCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateNamespaceCmd.Flags().String(namespaceFlag, "", "Namespace name to create") frostfsidCreateNamespaceCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDListNamespacesCmd() { frostfsidCmd.AddCommand(frostfsidListNamespacesCmd) - frostfsidListNamespacesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListNamespacesCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListNamespacesCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDCreateSubjectCmd() { frostfsidCmd.AddCommand(frostfsidCreateSubjectCmd) - frostfsidCreateSubjectCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateSubjectCmd.Flags().String(namespaceFlag, "", "Namespace where create subject") frostfsidCreateSubjectCmd.Flags().String(subjectNameFlag, "", "Subject name, must be unique in namespace") frostfsidCreateSubjectCmd.Flags().String(subjectKeyFlag, "", "Subject hex-encoded public key") @@ -171,14 +172,14 @@ func initFrostfsIDCreateSubjectCmd() { func initFrostfsIDDeleteSubjectCmd() { frostfsidCmd.AddCommand(frostfsidDeleteSubjectCmd) - frostfsidDeleteSubjectCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidDeleteSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidDeleteSubjectCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidDeleteSubjectCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDListSubjectsCmd() { frostfsidCmd.AddCommand(frostfsidListSubjectsCmd) - frostfsidListSubjectsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") frostfsidListSubjectsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -186,7 +187,7 @@ func initFrostfsIDListSubjectsCmd() { func initFrostfsIDCreateGroupCmd() { frostfsidCmd.AddCommand(frostfsidCreateGroupCmd) - frostfsidCreateGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidCreateGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateGroupCmd.Flags().String(namespaceFlag, "", "Namespace where create group") frostfsidCreateGroupCmd.Flags().String(groupNameFlag, "", "Group name, must be unique in namespace") frostfsidCreateGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -194,7 +195,7 @@ func initFrostfsIDCreateGroupCmd() { func initFrostfsIDDeleteGroupCmd() { frostfsidCmd.AddCommand(frostfsidDeleteGroupCmd) - frostfsidDeleteGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidDeleteGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidDeleteGroupCmd.Flags().String(namespaceFlag, "", "Namespace to delete group") frostfsidDeleteGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidDeleteGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -202,14 +203,14 @@ func initFrostfsIDDeleteGroupCmd() { func initFrostfsIDListGroupsCmd() { frostfsidCmd.AddCommand(frostfsidListGroupsCmd) - frostfsidListGroupsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListGroupsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") frostfsidListGroupsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) } func initFrostfsIDAddSubjectToGroupCmd() { frostfsidCmd.AddCommand(frostfsidAddSubjectToGroupCmd) - frostfsidAddSubjectToGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidAddSubjectToGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidAddSubjectToGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidAddSubjectToGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidAddSubjectToGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -217,7 +218,7 @@ func initFrostfsIDAddSubjectToGroupCmd() { func initFrostfsIDRemoveSubjectFromGroupCmd() { frostfsidCmd.AddCommand(frostfsidRemoveSubjectFromGroupCmd) - frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidRemoveSubjectFromGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidRemoveSubjectFromGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidRemoveSubjectFromGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) @@ -225,7 +226,7 @@ func initFrostfsIDRemoveSubjectFromGroupCmd() { func initFrostfsIDListGroupSubjectsCmd() { frostfsidCmd.AddCommand(frostfsidListGroupSubjectsCmd) - frostfsidListGroupSubjectsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + frostfsidListGroupSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") @@ -467,5 +468,5 @@ func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) { } f.wCtx.Command.Println("Waiting for transactions to persist...") - return f.roCli.Wait(f.wCtx.SentTxs[0].hash, f.wCtx.SentTxs[0].vub, nil) + return f.roCli.Wait(f.wCtx.SentTxs[0].Hash, f.wCtx.SentTxs[0].Vub, nil) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate.go index b8e0069624..2d82c1237e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate.go @@ -7,6 +7,7 @@ import ( "path/filepath" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -27,7 +28,6 @@ import ( const ( singleAccountName = "single" committeeAccountName = "committee" - consensusAccountName = "consensus" ) func generateAlphabetCreds(cmd *cobra.Command, _ []string) error { @@ -39,8 +39,8 @@ func generateAlphabetCreds(cmd *cobra.Command, _ []string) error { if size == 0 { return errors.New("size must be > 0") } - if size > maxAlphabetNodes { - return ErrTooManyAlphabetNodes + if size > morphUtil.MaxAlphabetNodes { + return morphUtil.ErrTooManyAlphabetNodes } v := viper.GetViper() @@ -109,7 +109,7 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er if err := addMultisigAccount(wallets[i], majCount, committeeAccountName, passwords[i], ps); err != nil { return fmt.Errorf("can't create committee account: %w", err) } - if err := addMultisigAccount(wallets[i], bftCount, consensusAccountName, passwords[i], ps); err != nil { + if err := addMultisigAccount(wallets[i], bftCount, morphUtil.ConsensusAccountName, passwords[i], ps); err != nil { return fmt.Errorf("can't create consentus account: %w", err) } if err := wallets[i].SavePretty(); err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate_test.go index 7f0a2708c3..2386b94e2d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate_test.go @@ -10,6 +10,7 @@ import ( "sync" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -87,7 +88,7 @@ func TestGenerateAlphabet(t *testing.T) { err := a.Decrypt(strconv.FormatUint(i, 10), keys.NEP2ScryptParams()) require.NoError(t, err, "can't decrypt account") switch a.Label { - case consensusAccountName: + case util.ConsensusAccountName: require.Equal(t, smartcontract.GetDefaultHonestNodeCount(size), len(a.Contract.Parameters)) case committeeAccountName: require.Equal(t, smartcontract.GetMajorityHonestNodeCount(size), len(a.Contract.Parameters)) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index 04e8620cc1..2dff2f06fb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -4,10 +4,9 @@ import ( "errors" "fmt" "os" - "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -15,28 +14,19 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" "github.com/spf13/viper" ) -const ( - // maxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size - // of the invocation script. - // See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10 - maxAlphabetNodes = 22 -) - type cache struct { nnsCs *state.Contract groupKey *keys.PublicKey } type initializeContext struct { - clientContext + morphUtil.ClientContext cache // CommitteeAcc is used for retrieving the committee address and the verification script. CommitteeAcc *wallet.Account @@ -53,8 +43,6 @@ type initializeContext struct { ContractURL string } -var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", maxAlphabetNodes) - func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { initCtx, err := newInitializeContext(cmd, viper.GetViper()) if err != nil { @@ -105,8 +93,8 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { } func (c *initializeContext) close() { - if local, ok := c.Client.(*localClient); ok { - err := local.dump() + if local, ok := c.Client.(*morphUtil.LocalClient); ok { + err := local.Dump() if err != nil { c.Command.PrintErrf("Can't write dump: %v\n", err) os.Exit(1) @@ -116,7 +104,7 @@ func (c *initializeContext) close() { func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) { walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) - wallets, err := getAlphabetWallets(v, walletDir) + wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) if err != nil { return nil, err } @@ -134,12 +122,12 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex return nil, err } - committeeAcc, err := getWalletAccount(wallets[0], committeeAccountName) + committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], committeeAccountName) if err != nil { return nil, fmt.Errorf("can't find committee account: %w", err) } - consensusAcc, err := getWalletAccount(wallets[0], consensusAccountName) + consensusAcc, err := morphUtil.GetWalletAccount(wallets[0], morphUtil.ConsensusAccountName) if err != nil { return nil, fmt.Errorf("can't find consensus account: %w", err) } @@ -167,13 +155,13 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex return nil, err } - cliCtx, err := defaultClientContext(c, committeeAcc) + cliCtx, err := morphUtil.DefaultClientContext(c, committeeAcc) if err != nil { return nil, fmt.Errorf("client context: %w", err) } initCtx := &initializeContext{ - clientContext: *cliCtx, + ClientContext: *cliCtx, ConsensusAcc: consensusAcc, CommitteeAcc: committeeAcc, ContractWallet: w, @@ -210,16 +198,16 @@ func validateInit(cmd *cobra.Command) error { return nil } -func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet) (Client, error) { - var c Client +func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet) (morphUtil.Client, error) { + var c morphUtil.Client var err error if ldf := cmd.Flags().Lookup(localDumpFlag); ldf != nil && ldf.Changed { - if cmd.Flags().Changed(endpointFlag) { - return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", endpointFlag, localDumpFlag) + if cmd.Flags().Changed(morphUtil.EndpointFlag) { + return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", morphUtil.EndpointFlag, localDumpFlag) } - c, err = newLocalClient(cmd, v, wallets, ldf.Value.String()) + c, err = morphUtil.NewLocalClient(cmd, v, wallets, ldf.Value.String()) } else { - c, err = getN3Client(v) + c, err = morphUtil.GetN3Client(v) } if err != nil { return nil, fmt.Errorf("can't create N3 client: %w", err) @@ -249,7 +237,7 @@ func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) { func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { accounts := make([]*wallet.Account, len(wallets)) for i, w := range wallets { - acc, err := getWalletAccount(w, singleAccountName) + acc, err := morphUtil.GetWalletAccount(w, singleAccountName) if err != nil { return nil, fmt.Errorf("wallet %s is invalid (no single account): %w", w.Path(), err) } @@ -259,7 +247,7 @@ func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { } func (c *initializeContext) awaitTx() error { - return c.clientContext.awaitTx(c.Command) + return c.ClientContext.AwaitTx(c.Command) } func (c *initializeContext) nnsContractState() (*state.Contract, error) { @@ -310,89 +298,6 @@ func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transa return signer } -func (c *clientContext) awaitTx(cmd *cobra.Command) error { - if len(c.SentTxs) == 0 { - return nil - } - - if local, ok := c.Client.(*localClient); ok { - if err := local.putTransactions(); err != nil { - return fmt.Errorf("can't persist transactions: %w", err) - } - } - - err := awaitTx(cmd, c.Client, c.SentTxs) - c.SentTxs = c.SentTxs[:0] - - return err -} - -func awaitTx(cmd *cobra.Command, c Client, txs []hashVUBPair) error { - cmd.Println("Waiting for transactions to persist...") - - at := trigger.Application - - var retErr error - -loop: - for i := range txs { - var it int - var pollInterval time.Duration - var pollIntervalChanged bool - for { - // We must fetch current height before application log, to avoid race condition. - currBlock, err := c.GetBlockCount() - if err != nil { - return fmt.Errorf("can't fetch current block height: %w", err) - } - res, err := c.GetApplicationLog(txs[i].hash, &at) - if err == nil { - if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vmstate.Halt { - retErr = fmt.Errorf("tx %d persisted in %s state: %s", - i, res.Executions[0].VMState, res.Executions[0].FaultException) - } - continue loop - } - if txs[i].vub < currBlock { - return fmt.Errorf("tx was not persisted: vub=%d, height=%d", txs[i].vub, currBlock) - } - - pollInterval, pollIntervalChanged = nextPollInterval(it, pollInterval) - if pollIntervalChanged && viper.GetBool(commonflags.Verbose) { - cmd.Printf("Pool interval to check transaction persistence changed: %s\n", pollInterval.String()) - } - - timer := time.NewTimer(pollInterval) - select { - case <-cmd.Context().Done(): - return cmd.Context().Err() - case <-timer.C: - } - - it++ - } - } - - return retErr -} - -func nextPollInterval(it int, previous time.Duration) (time.Duration, bool) { - const minPollInterval = 1 * time.Second - const maxPollInterval = 16 * time.Second - const changeAfter = 5 - if it == 0 { - return minPollInterval, true - } - if it%changeAfter != 0 { - return previous, false - } - nextInterval := previous * 2 - if nextInterval > maxPollInterval { - return maxPollInterval, previous != maxPollInterval - } - return nextInterval, true -} - // sendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC. // If tryGroup is false, global scope is used for the signer (useful when // working with native contracts). @@ -445,24 +350,15 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen return err } if withConsensus { - if err := c.multiSign(tx, consensusAccountName); err != nil { + if err := c.multiSign(tx, morphUtil.ConsensusAccountName); err != nil { return err } } - return c.sendTx(tx, c.Command, false) + return c.SendTx(tx, c.Command, false) } -func getWalletAccount(w *wallet.Wallet, typ string) (*wallet.Account, error) { - for i := range w.Accounts { - if w.Accounts[i].Label == typ { - return w.Accounts[i], nil - } - } - return nil, fmt.Errorf("account for '%s' not found", typ) -} - -func checkNotaryEnabled(c Client) error { +func checkNotaryEnabled(c morphUtil.Client) error { ns, err := c.GetNativeContracts() if err != nil { return fmt.Errorf("can't get native contract hashes: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index f715f0e03a..9f0e929a81 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/common" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" @@ -332,7 +333,7 @@ func (c *initializeContext) deployContracts() error { return fmt.Errorf("can't deploy alphabet #%d contract: %w", i, err) } - c.SentTxs = append(c.SentTxs, hashVUBPair{hash: txHash, vub: vub}) + c.SentTxs = append(c.SentTxs, morphUtil.HashVUBPair{Hash: txHash, Vub: vub}) } for _, ctrName := range contractList { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 1bf4c4bee2..7364ba0e35 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -8,6 +8,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -288,14 +289,14 @@ func parseNNSResolveResult(res stackitem.Item) (util.Uint160, error) { return util.Uint160{}, errors.New("no valid hashes are found") } -func nnsIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) { +func nnsIsAvailable(c morphUtil.Client, nnsHash util.Uint160, name string) (bool, error) { switch c.(type) { case *rpcclient.Client: inv := invoker.New(c, nil) reader := nnsClient.NewReader(inv, nnsHash) return reader.IsAvailable(name) default: - b, err := unwrap.Bool(invokeFunction(c, nnsHash, "isAvailable", []any{name}, nil)) + b, err := unwrap.Bool(morphUtil.InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil)) if err != nil { return false, fmt.Errorf("`isAvailable`: invalid response: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go index 92145a7967..e8e73ae735 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -78,7 +79,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error { } } - return c.sendTx(tx, c.Command, true) + return c.SendTx(tx, c.Command, true) } func (c *initializeContext) registerCandidates() error { @@ -156,7 +157,7 @@ func (c *initializeContext) getCandidateRegisterPrice() (int64, error) { return reader.GetRegisterPrice() default: neoHash := neo.Hash - res, err := invokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil) + res, err := morphUtil.InvokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil) if err != nil { return 0, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go b/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go index 46466602ee..aed35e2308 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go @@ -1,6 +1,7 @@ package morph import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/rolemgmt" @@ -40,6 +41,6 @@ func (c *initializeContext) setRolesFinished() (bool, error) { return false, err } - pubs, err := getDesignatedByRole(c.ReadOnlyInvoker, rolemgmt.Hash, noderoles.NeoFSAlphabet, height) + pubs, err := util.GetDesignatedByRole(c.ReadOnlyInvoker, rolemgmt.Hash, noderoles.NeoFSAlphabet, height) return len(pubs) == len(c.Wallets), err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index 613c63894e..cf71a01d62 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -42,10 +43,10 @@ func TestInitialize(t *testing.T) { testInitialize(t, 16) }) t.Run("max nodes", func(t *testing.T) { - testInitialize(t, maxAlphabetNodes) + testInitialize(t, util.MaxAlphabetNodes) }) t.Run("too many nodes", func(t *testing.T) { - require.ErrorIs(t, generateTestData(t, t.TempDir(), maxAlphabetNodes+1), ErrTooManyAlphabetNodes) + require.ErrorIs(t, generateTestData(t, t.TempDir(), util.MaxAlphabetNodes+1), util.ErrTooManyAlphabetNodes) }) } @@ -54,7 +55,7 @@ func testInitialize(t *testing.T, committeeSize int) { v := viper.GetViper() require.NoError(t, generateTestData(t, testdataDir, committeeSize)) - v.Set(protoConfigPath, filepath.Join(testdataDir, protoFileName)) + v.Set(util.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) // Set to the path or remove the next statement to download from the network. require.NoError(t, initCmd.Flags().Set(contractsInitFlag, contractsPath)) @@ -150,33 +151,33 @@ func TestNextPollInterval(t *testing.T) { var pollInterval time.Duration var iteration int - pollInterval, hasChanged := nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged := util.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, time.Second, pollInterval) iteration = 4 - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.False(t, hasChanged) require.Equal(t, time.Second, pollInterval) iteration = 5 - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, 2*time.Second, pollInterval) iteration = 10 - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, 4*time.Second, pollInterval) iteration = 20 pollInterval = 32 * time.Second - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) // from 32s to 16s require.Equal(t, 16*time.Second, pollInterval) pollInterval = 16 * time.Second - pollInterval, hasChanged = nextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) require.False(t, hasChanged) require.Equal(t, 16*time.Second, pollInterval) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index 12b94a2ed6..e9945cee65 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" @@ -67,7 +68,7 @@ func (c *initializeContext) transferFunds() error { return fmt.Errorf("can't create transfer transaction: %w", err) } - if err := c.multiSignAndSend(tx, consensusAccountName); err != nil { + if err := c.multiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil { return fmt.Errorf("can't send transfer transaction: %w", err) } @@ -87,7 +88,7 @@ func (c *initializeContext) multiSignAndSend(tx *transaction.Transaction, accTyp return err } - return c.sendTx(tx, c.Command, false) + return c.SendTx(tx, c.Command, false) } func (c *initializeContext) multiSign(tx *transaction.Transaction, accType string) error { @@ -102,11 +103,11 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin // Use parameter context to avoid dealing with signature order. pc := scContext.NewParameterContext("", network, tx) h := c.CommitteeAcc.Contract.ScriptHash() - if accType == consensusAccountName { + if accType == morphUtil.ConsensusAccountName { h = c.ConsensusAcc.Contract.ScriptHash() } for _, w := range c.Wallets { - acc, err := getWalletAccount(w, accType) + acc, err := morphUtil.GetWalletAccount(w, accType) if err != nil { return fmt.Errorf("can't find %s wallet account: %w", accType, err) } @@ -174,7 +175,7 @@ type transferTarget struct { Data any } -func createNEP17MultiTransferTx(c Client, acc *wallet.Account, recipients []transferTarget) (*transaction.Transaction, error) { +func createNEP17MultiTransferTx(c morphUtil.Client, acc *wallet.Account, recipients []transferTarget) (*transaction.Transaction, error) { from := acc.Contract.ScriptHash() w := io.NewBufBinWriter() diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go index bb1de09ca6..7d31d18160 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go @@ -2,6 +2,7 @@ package morph import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -11,7 +12,7 @@ import ( ) func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { - c, err := getN3Client(viper.GetViper()) + c, err := util.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err) inv := invoker.New(c, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary.go index 2459f127bf..3e7afdbf25 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary.go @@ -5,6 +5,7 @@ import ( "math/big" "strconv" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -79,7 +80,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error { } func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, gasAmount fixedn.Fixed8, till int64) error { - c, err := getN3Client(viper.GetViper()) + c, err := morphUtil.GetN3Client(viper.GetViper()) if err != nil { return err } @@ -116,7 +117,7 @@ func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, return fmt.Errorf("could not send tx: %w", err) } - return awaitTx(cmd, c, []hashVUBPair{{hash: txHash, vub: vub}}) + return morphUtil.AwaitTx(cmd, c, []morphUtil.HashVUBPair{{Hash: txHash, Vub: vub}}) } func openWallet(cmd *cobra.Command) (*wallet.Wallet, error) { diff --git a/cmd/frostfs-adm/internal/modules/morph/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy.go index 005a02711f..ba73d132ce 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy.go @@ -7,6 +7,7 @@ import ( "strings" "text/tabwriter" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -58,7 +59,7 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error { } func dumpPolicyCmd(cmd *cobra.Command, _ []string) error { - c, err := getN3Client(viper.GetViper()) + c, err := util.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client:", err) inv := invoker.New(c, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 6cc2d5a96c..dad8c4ee41 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -1,6 +1,7 @@ package morph import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -9,9 +10,6 @@ const ( alphabetWalletsFlag = "alphabet-wallets" alphabetWalletsFlagDesc = "Path to alphabet wallets dir" alphabetSizeFlag = "size" - endpointFlag = "rpc-endpoint" - endpointFlagDesc = "N3 RPC node endpoint" - endpointFlagShort = "r" storageWalletFlag = "storage-wallet" storageWalletLabelFlag = "label" storageGasCLIFlag = "initial-gas" @@ -42,8 +40,8 @@ const ( walletAccountFlag = "account" notaryDepositTillFlag = "till" localDumpFlag = "local-dump" - protoConfigPath = "protocol" - walletAddressFlag = "wallet-address" + + walletAddressFlag = "wallet-address" ) var ( @@ -68,7 +66,7 @@ var ( Short: "Initialize side chain network with smart-contracts and network settings", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(epochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) _ = viper.BindPFlag(maxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) _ = viper.BindPFlag(homomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) @@ -76,7 +74,7 @@ var ( _ = viper.BindPFlag(containerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) _ = viper.BindPFlag(containerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) _ = viper.BindPFlag(withdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) - _ = viper.BindPFlag(protoConfigPath, cmd.Flags().Lookup(protoConfigPath)) + _ = viper.BindPFlag(util.ProtoConfigPath, cmd.Flags().Lookup(util.ProtoConfigPath)) }, RunE: initializeSideChainCmd, } @@ -86,7 +84,7 @@ var ( Short: "Generate storage node wallet for the morph network", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(storageGasConfigFlag, cmd.Flags().Lookup(storageGasCLIFlag)) }, RunE: generateStorageCreds, @@ -97,7 +95,7 @@ var ( Short: "Refill GAS of storage node's wallet in the morph network", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(refillGasAmountFlag, cmd.Flags().Lookup(refillGasAmountFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { @@ -110,7 +108,7 @@ var ( Short: "Create new FrostFS epoch event in the side chain", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: forceNewEpochCmd, } @@ -121,7 +119,7 @@ var ( Long: `Move nodes to the Offline state in the candidates list and tick an epoch to update the netmap`, PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: removeNodesCmd, } @@ -132,7 +130,7 @@ var ( Short: "Add/update global config value in the FrostFS network", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Args: cobra.MinimumNArgs(1), RunE: setConfigCmd, @@ -144,7 +142,7 @@ var ( Short: "Set global policy values", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: setPolicyCmd, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -156,7 +154,7 @@ var ( Use: "dump-policy", Short: "Dump FrostFS policy", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpPolicyCmd, } @@ -165,7 +163,7 @@ var ( Use: "dump-hashes", Short: "Dump deployed contract hashes", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpContractHashes, } @@ -174,7 +172,7 @@ var ( Use: "dump-config", Short: "Dump FrostFS network config", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpNetworkConfig, } @@ -183,7 +181,7 @@ var ( Use: "dump-balances", Short: "Dump GAS balances", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpBalances, } @@ -193,7 +191,7 @@ var ( Short: "Update FrostFS contracts", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: updateContracts, } @@ -202,7 +200,7 @@ var ( Use: "dump-containers", Short: "Dump FrostFS containers to file", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: dumpContainers, } @@ -212,7 +210,7 @@ var ( Short: "Restore FrostFS containers from file", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: restoreContainers, } @@ -221,7 +219,7 @@ var ( Use: "list-containers", Short: "List FrostFS containers", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: listContainers, } @@ -230,7 +228,7 @@ var ( Use: "deposit-notary", Short: "Deposit GAS for notary service", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: depositNotary, } @@ -239,7 +237,7 @@ var ( Use: "netmap-candidates", Short: "List netmap candidates nodes", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) }, Run: listNetmapCandidatesNodes, @@ -250,7 +248,7 @@ var ( Short: "Adds account to proxy contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Run: addProxyAccount, } @@ -260,7 +258,7 @@ var ( Short: "Remove from proxy contract", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) - _ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Run: removeProxyAccount, } @@ -313,24 +311,24 @@ func init() { func initProxyAddAccount() { RootCmd.AddCommand(proxyAddAccountCmd) - proxyAddAccountCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + proxyAddAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) proxyAddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") } func initProxyRemoveAccount() { RootCmd.AddCommand(proxyRemoveAccountCmd) - proxyRemoveAccountCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + proxyRemoveAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) proxyRemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") } func initNetmapCandidatesCmd() { RootCmd.AddCommand(netmapCandidatesCmd) - netmapCandidatesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + netmapCandidatesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) } func initDepositoryNotaryCmd() { RootCmd.AddCommand(depositNotaryCmd) - depositNotaryCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + depositNotaryCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) depositNotaryCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") depositNotaryCmd.Flags().String(walletAccountFlag, "", "Wallet account address") depositNotaryCmd.Flags().String(refillGasAmountFlag, "", "Amount of GAS to deposit") @@ -340,7 +338,7 @@ func initDepositoryNotaryCmd() { func initRefillGasCmd() { RootCmd.AddCommand(refillGasCmd) refillGasCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - refillGasCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + refillGasCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) refillGasCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") refillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") refillGasCmd.Flags().String(refillGasAmountFlag, "", "Additional amount of GAS to transfer") @@ -349,21 +347,21 @@ func initRefillGasCmd() { func initListContainersCmd() { RootCmd.AddCommand(listContainersCmd) - listContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + listContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) listContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") } func initRestoreContainersCmd() { RootCmd.AddCommand(restoreContainersCmd) restoreContainersCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - restoreContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + restoreContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) restoreContainersCmd.Flags().String(containerDumpFlag, "", "File to restore containers from") restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore") } func initDumpContainersCmd() { RootCmd.AddCommand(dumpContainersCmd) - dumpContainersCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) dumpContainersCmd.Flags().String(containerDumpFlag, "", "File where to save dumped containers") dumpContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") dumpContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to dump") @@ -372,7 +370,7 @@ func initDumpContainersCmd() { func initUpdateContractsCmd() { RootCmd.AddCommand(updateContractsCmd) updateContractsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - updateContractsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + updateContractsCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) updateContractsCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) updateContractsCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) updateContractsCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag) @@ -380,7 +378,7 @@ func initUpdateContractsCmd() { func initDumpBalancesCmd() { RootCmd.AddCommand(dumpBalancesCmd) - dumpBalancesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpBalancesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) dumpBalancesCmd.Flags().BoolP(dumpBalancesStorageFlag, "s", false, "Dump balances of storage nodes from the current netmap") dumpBalancesCmd.Flags().BoolP(dumpBalancesAlphabetFlag, "a", false, "Dump balances of alphabet contracts") dumpBalancesCmd.Flags().BoolP(dumpBalancesProxyFlag, "p", false, "Dump balances of the proxy contract") @@ -390,52 +388,52 @@ func initDumpBalancesCmd() { func initSetConfigCmd() { RootCmd.AddCommand(setConfig) setConfig.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - setConfig.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + setConfig.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) setConfig.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") setConfig.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initDumpNetworkConfigCmd() { RootCmd.AddCommand(dumpNetworkConfigCmd) - dumpNetworkConfigCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpNetworkConfigCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) } func initDumpContractHashesCmd() { RootCmd.AddCommand(dumpContractHashesCmd) - dumpContractHashesCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpContractHashesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) dumpContractHashesCmd.Flags().String(customZoneFlag, "", "Custom zone to search.") } func initSetPolicyCmd() { RootCmd.AddCommand(setPolicy) setPolicy.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - setPolicy.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + setPolicy.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) setPolicy.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initDumpPolicyCmd() { RootCmd.AddCommand(dumpPolicy) - dumpPolicy.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + dumpPolicy.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) } func initRemoveNodesCmd() { RootCmd.AddCommand(removeNodes) removeNodes.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - removeNodes.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + removeNodes.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) removeNodes.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initForceNewEpochCmd() { RootCmd.AddCommand(forceNewEpoch) forceNewEpoch.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - forceNewEpoch.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + forceNewEpoch.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) forceNewEpoch.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initGenerateStorageCmd() { RootCmd.AddCommand(generateStorageCmd) generateStorageCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - generateStorageCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + generateStorageCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) generateStorageCmd.Flags().String(storageWalletFlag, "", "Path to new storage node wallet") generateStorageCmd.Flags().String(storageGasCLIFlag, "", "Initial amount of GAS to transfer") generateStorageCmd.Flags().StringP(storageWalletLabelFlag, "l", "", "Wallet label") @@ -444,7 +442,7 @@ func initGenerateStorageCmd() { func initInitCmd() { RootCmd.AddCommand(initCmd) initCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - initCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) + initCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) initCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) initCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") @@ -453,7 +451,7 @@ func initInitCmd() { // Defaults are taken from neo-preodolenie. initCmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") - initCmd.Flags().String(protoConfigPath, "", "Path to the consensus node configuration") + initCmd.Flags().String(util.ProtoConfigPath, "", "Path to the consensus node configuration") initCmd.Flags().String(localDumpFlag, "", "Path to the blocks dump file") initCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go new file mode 100644 index 0000000000..7278d8357f --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -0,0 +1,15 @@ +package util + +const ( + ConsensusAccountName = "consensus" + ProtoConfigPath = "protocol" + + // MaxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size + // of the invocation script. + // See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10 + MaxAlphabetNodes = 22 + + EndpointFlag = "rpc-endpoint" + EndpointFlagDesc = "N3 RPC node endpoint" + EndpointFlagShort = "r" +) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go new file mode 100644 index 0000000000..d15d99b939 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go @@ -0,0 +1,90 @@ +package util + +import ( + "fmt" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" + "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", MaxAlphabetNodes) + +func AwaitTx(cmd *cobra.Command, c Client, txs []HashVUBPair) error { + cmd.Println("Waiting for transactions to persist...") + + at := trigger.Application + + var retErr error + +loop: + for i := range txs { + var it int + var pollInterval time.Duration + var pollIntervalChanged bool + for { + // We must fetch current height before application log, to avoid race condition. + currBlock, err := c.GetBlockCount() + if err != nil { + return fmt.Errorf("can't fetch current block height: %w", err) + } + res, err := c.GetApplicationLog(txs[i].Hash, &at) + if err == nil { + if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vmstate.Halt { + retErr = fmt.Errorf("tx %d persisted in %s state: %s", + i, res.Executions[0].VMState, res.Executions[0].FaultException) + } + continue loop + } + if txs[i].Vub < currBlock { + return fmt.Errorf("tx was not persisted: Vub=%d, height=%d", txs[i].Vub, currBlock) + } + + pollInterval, pollIntervalChanged = NextPollInterval(it, pollInterval) + if pollIntervalChanged && viper.GetBool(commonflags.Verbose) { + cmd.Printf("Pool interval to check transaction persistence changed: %s\n", pollInterval.String()) + } + + timer := time.NewTimer(pollInterval) + select { + case <-cmd.Context().Done(): + return cmd.Context().Err() + case <-timer.C: + } + + it++ + } + } + + return retErr +} + +func NextPollInterval(it int, previous time.Duration) (time.Duration, bool) { + const minPollInterval = 1 * time.Second + const maxPollInterval = 16 * time.Second + const changeAfter = 5 + if it == 0 { + return minPollInterval, true + } + if it%changeAfter != 0 { + return previous, false + } + nextInterval := previous * 2 + if nextInterval > maxPollInterval { + return maxPollInterval, previous != maxPollInterval + } + return nextInterval, true +} + +func GetWalletAccount(w *wallet.Wallet, typ string) (*wallet.Account, error) { + for i := range w.Accounts { + if w.Accounts[i].Label == typ { + return w.Accounts[i], nil + } + } + return nil, fmt.Errorf("account for '%s' not found", typ) +} diff --git a/cmd/frostfs-adm/internal/modules/morph/local_client.go b/cmd/frostfs-adm/internal/modules/morph/util/local_client.go similarity index 89% rename from cmd/frostfs-adm/internal/modules/morph/local_client.go rename to cmd/frostfs-adm/internal/modules/morph/util/local_client.go index 1a723042c5..4b001ca84b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/local_client.go @@ -1,4 +1,4 @@ -package morph +package util import ( "crypto/elliptic" @@ -38,7 +38,7 @@ import ( "go.uber.org/zap" ) -type localClient struct { +type LocalClient struct { bc *core.Blockchain transactions []*transaction.Transaction dumpPath string @@ -46,8 +46,8 @@ type localClient struct { maxGasInvoke int64 } -func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*localClient, error) { - cfg, err := config.LoadFile(v.GetString(protoConfigPath)) +func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) { + cfg, err := config.LoadFile(v.GetString(ProtoConfigPath)) if err != nil { return nil, err } @@ -60,7 +60,7 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ProtocolConfiguration.ValidatorsCount)) accounts := make([]*wallet.Account, len(wallets)) for i := range accounts { - accounts[i], err = getWalletAccount(wallets[i], consensusAccountName) + accounts[i], err = GetWalletAccount(wallets[i], ConsensusAccountName) if err != nil { return nil, err } @@ -102,7 +102,7 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet } } - return &localClient{ + return &LocalClient{ bc: bc, dumpPath: dumpPath, accounts: accounts[:m], @@ -110,15 +110,15 @@ func newLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet }, nil } -func (l *localClient) GetBlockCount() (uint32, error) { +func (l *LocalClient) GetBlockCount() (uint32, error) { return l.bc.BlockHeight(), nil } -func (l *localClient) GetNativeContracts() ([]state.NativeContract, error) { +func (l *LocalClient) GetNativeContracts() ([]state.NativeContract, error) { return l.bc.GetNatives(), nil } -func (l *localClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*result.ApplicationLog, error) { +func (l *LocalClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*result.ApplicationLog, error) { aer, err := l.bc.GetAppExecResults(h, *t) if err != nil { return nil, err @@ -128,13 +128,13 @@ func (l *localClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*resul return &a, nil } -func (l *localClient) GetCommittee() (keys.PublicKeys, error) { +func (l *LocalClient) GetCommittee() (keys.PublicKeys, error) { // not used by `morph init` command panic("unexpected call") } // InvokeFunction is implemented via `InvokeScript`. -func (l *localClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) { +func (l *LocalClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) { var err error pp := make([]any, len(sPrm)) @@ -145,21 +145,21 @@ func (l *localClient) InvokeFunction(h util.Uint160, method string, sPrm []smart } } - return invokeFunction(l, h, method, pp, ss) + return InvokeFunction(l, h, method, pp, ss) } -func (l *localClient) TerminateSession(_ uuid.UUID) (bool, error) { +func (l *LocalClient) TerminateSession(_ uuid.UUID) (bool, error) { // not used by `morph init` command panic("unexpected call") } -func (l *localClient) TraverseIterator(_, _ uuid.UUID, _ int) ([]stackitem.Item, error) { +func (l *LocalClient) TraverseIterator(_, _ uuid.UUID, _ int) ([]stackitem.Item, error) { // not used by `morph init` command panic("unexpected call") } // GetVersion return default version. -func (l *localClient) GetVersion() (*result.Version, error) { +func (l *LocalClient) GetVersion() (*result.Version, error) { c := l.bc.GetConfig() return &result.Version{ Protocol: result.Protocol{ @@ -180,7 +180,7 @@ func (l *localClient) GetVersion() (*result.Version, error) { }, nil } -func (l *localClient) InvokeContractVerify(util.Uint160, []smartcontract.Parameter, []transaction.Signer, ...transaction.Witness) (*result.Invoke, error) { +func (l *LocalClient) InvokeContractVerify(util.Uint160, []smartcontract.Parameter, []transaction.Signer, ...transaction.Witness) (*result.Invoke, error) { // not used by `morph init` command panic("unexpected call") } @@ -188,7 +188,7 @@ func (l *localClient) InvokeContractVerify(util.Uint160, []smartcontract.Paramet // CalculateNetworkFee calculates network fee for the given transaction. // Copied from neo-go with minor corrections (no need to support non-notary mode): // https://github.com/nspcc-dev/neo-go/blob/v0.103.0/pkg/services/rpcsrv/server.go#L911 -func (l *localClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) { +func (l *LocalClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) { // Avoid setting hash for this tx: server code doesn't touch client transaction. data := tx.Bytes() tx, err := transaction.NewTransactionFromBytes(data) @@ -259,7 +259,7 @@ func (l *localClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, e return netFee, nil } -func (l *localClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) { +func (l *LocalClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) { lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash()) if err != nil { return nil, err @@ -295,7 +295,7 @@ func (l *localClient) InvokeScript(script []byte, signers []transaction.Signer) }, nil } -func (l *localClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) { +func (l *LocalClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) { // We need to test that transaction was formed correctly to catch as many errors as we can. bs := tx.Bytes() _, err := transaction.NewTransactionFromBytes(bs) @@ -307,7 +307,7 @@ func (l *localClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint return tx.Hash(), nil } -func (l *localClient) putTransactions() error { +func (l *LocalClient) putTransactions() error { // 1. Prepare new block. lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash()) if err != nil { @@ -349,7 +349,7 @@ func (l *localClient) putTransactions() error { return l.bc.AddBlock(b) } -func invokeFunction(c Client, h util.Uint160, method string, parameters []any, signers []transaction.Signer) (*result.Invoke, error) { +func InvokeFunction(c Client, h util.Uint160, method string, parameters []any, signers []transaction.Signer) (*result.Invoke, error) { w := io.NewBufBinWriter() emit.Array(w.BinWriter, parameters...) emit.AppCallNoArgs(w.BinWriter, h, method, callflag.All) @@ -361,7 +361,7 @@ func invokeFunction(c Client, h util.Uint160, method string, parameters []any, s var errGetDesignatedByRoleResponse = errors.New("`getDesignatedByRole`: invalid response") -func getDesignatedByRole(inv *invoker.Invoker, h util.Uint160, role noderoles.Role, u uint32) (keys.PublicKeys, error) { +func GetDesignatedByRole(inv *invoker.Invoker, h util.Uint160, role noderoles.Role, u uint32) (keys.PublicKeys, error) { arr, err := unwrap.Array(inv.Call(h, "getDesignatedByRole", int64(role), int64(u))) if err != nil { return nil, errGetDesignatedByRoleResponse @@ -382,7 +382,7 @@ func getDesignatedByRole(inv *invoker.Invoker, h util.Uint160, role noderoles.Ro return pubs, nil } -func (l *localClient) dump() (err error) { +func (l *LocalClient) Dump() (err error) { defer l.bc.Close() f, err := os.Create(l.dumpPath) diff --git a/cmd/frostfs-adm/internal/modules/morph/n3client.go b/cmd/frostfs-adm/internal/modules/morph/util/n3client.go similarity index 72% rename from cmd/frostfs-adm/internal/modules/morph/n3client.go rename to cmd/frostfs-adm/internal/modules/morph/util/n3client.go index 584bb8524f..0cc751cf1d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/n3client.go @@ -1,4 +1,4 @@ -package morph +package util import ( "context" @@ -34,19 +34,19 @@ type Client interface { CalculateNetworkFee(tx *transaction.Transaction) (int64, error) } -type hashVUBPair struct { - hash util.Uint256 - vub uint32 +type HashVUBPair struct { + Hash util.Uint256 + Vub uint32 } -type clientContext struct { +type ClientContext struct { Client Client // a raw neo-go client OR a local chain implementation CommitteeAct *actor.Actor // committee actor with the Global witness scope ReadOnlyInvoker *invoker.Invoker // R/O contract invoker, does not contain any signer - SentTxs []hashVUBPair + SentTxs []HashVUBPair } -func getN3Client(v *viper.Viper) (Client, error) { +func GetN3Client(v *viper.Viper) (Client, error) { // number of opened connections // by neo-go client per one host const ( @@ -55,7 +55,7 @@ func getN3Client(v *viper.Viper) (Client, error) { ) ctx := context.Background() - endpoint := v.GetString(endpointFlag) + endpoint := v.GetString(EndpointFlag) if endpoint == "" { return nil, errors.New("missing endpoint") } @@ -72,20 +72,20 @@ func getN3Client(v *viper.Viper) (Client, error) { return c, nil } -func defaultClientContext(c Client, committeeAcc *wallet.Account) (*clientContext, error) { - commAct, err := newActor(c, committeeAcc) +func DefaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) { + commAct, err := NewActor(c, committeeAcc) if err != nil { return nil, err } - return &clientContext{ + return &ClientContext{ Client: c, CommitteeAct: commAct, ReadOnlyInvoker: invoker.New(c, nil), }, nil } -func (c *clientContext) sendTx(tx *transaction.Transaction, cmd *cobra.Command, await bool) error { +func (c *ClientContext) SendTx(tx *transaction.Transaction, cmd *cobra.Command, await bool) error { h, err := c.Client.SendRawTransaction(tx) if err != nil { return err @@ -95,10 +95,27 @@ func (c *clientContext) sendTx(tx *transaction.Transaction, cmd *cobra.Command, return fmt.Errorf("sent and actual tx hashes mismatch:\n\tsent: %v\n\tactual: %v", tx.Hash().StringLE(), h.StringLE()) } - c.SentTxs = append(c.SentTxs, hashVUBPair{hash: h, vub: tx.ValidUntilBlock}) + c.SentTxs = append(c.SentTxs, HashVUBPair{Hash: h, Vub: tx.ValidUntilBlock}) if await { - return c.awaitTx(cmd) + return c.AwaitTx(cmd) } return nil } + +func (c *ClientContext) AwaitTx(cmd *cobra.Command) error { + if len(c.SentTxs) == 0 { + return nil + } + + if local, ok := c.Client.(*LocalClient); ok { + if err := local.putTransactions(); err != nil { + return fmt.Errorf("can't persist transactions: %w", err) + } + } + + err := AwaitTx(cmd, c.Client, c.SentTxs) + c.SentTxs = c.SentTxs[:0] + + return err +} diff --git a/cmd/frostfs-adm/internal/modules/morph/util.go b/cmd/frostfs-adm/internal/modules/morph/util/util.go similarity index 86% rename from cmd/frostfs-adm/internal/modules/morph/util.go rename to cmd/frostfs-adm/internal/modules/morph/util/util.go index 8b5489ab8e..bbe635a408 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/util.go @@ -1,4 +1,4 @@ -package morph +package util import ( "errors" @@ -15,19 +15,19 @@ import ( "github.com/spf13/viper" ) -func getAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { - wallets, err := openAlphabetWallets(v, walletDir) +func GetAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { + wallets, err := OpenAlphabetWallets(v, walletDir) if err != nil { return nil, err } - if len(wallets) > maxAlphabetNodes { + if len(wallets) > MaxAlphabetNodes { return nil, ErrTooManyAlphabetNodes } return wallets, nil } -func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { +func OpenAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { walletFiles, err := os.ReadDir(walletDir) if err != nil { return nil, fmt.Errorf("can't read alphabet wallets dir: %w", err) @@ -75,7 +75,7 @@ loop: return wallets, nil } -func newActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) { +func NewActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) { return actor.New(c, []actor.SignerAccount{{ Signer: transaction.Signer{ Account: committeeAcc.Contract.ScriptHash(), From 7954c7f8aff7b5b53983e617a2f8c99e06596ca6 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 09:43:51 +0300 Subject: [PATCH 0345/1413] [#932] adm: Move `NNS` methods to `util` package Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/ape_util.go | 2 +- .../internal/modules/morph/balance.go | 6 +-- .../internal/modules/morph/config.go | 4 +- .../internal/modules/morph/container.go | 4 +- .../internal/modules/morph/deploy.go | 2 +- .../internal/modules/morph/dump_hashes.go | 6 +-- .../internal/modules/morph/epoch.go | 3 +- .../internal/modules/morph/frostfsid.go | 2 +- .../modules/morph/initialize_deploy.go | 8 +-- .../internal/modules/morph/initialize_nns.go | 49 +---------------- .../modules/morph/netmap_candidates.go | 2 +- .../internal/modules/morph/proxy.go | 3 +- .../internal/modules/morph/remove_node.go | 3 +- .../internal/modules/morph/util/initialize.go | 52 +++++++++++++++++++ 14 files changed, 78 insertions(+), 68 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape_util.go index 30668532b9..6b174232a0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape_util.go @@ -97,7 +97,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac nnsCs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - ch, err = nnsResolveHash(inv, nnsCs.Hash, domainOf(policyContract)) + ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, domainOf(policyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) return morph.NewContractStorage(ac, ch), ac diff --git a/cmd/frostfs-adm/internal/modules/morph/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance.go index b4259e11e0..71bdebc70d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance.go @@ -64,7 +64,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err = nnsResolveHash(inv, nnsCs.Hash, domainOf(netmapContract)) + nmHash, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -137,7 +137,7 @@ func printStorageNodeBalances(cmd *cobra.Command, inv *invoker.Invoker, nmHash u } func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash util.Uint160) error { - h, err := nnsResolveHash(inv, nnsHash, domainOf(proxyContract)) + h, err := morphUtil.NNSResolveHash(inv, nnsHash, domainOf(proxyContract)) if err != nil { return fmt.Errorf("can't get hash of the proxy contract: %w", err) } @@ -170,7 +170,7 @@ func printAlphabetContractBalances(cmd *cobra.Command, c morphUtil.Client, inv * } for i := range alphaList { - h, err := parseNNSResolveResult(alphaRes.Stack[i]) + h, err := morphUtil.ParseNNSResolveResult(alphaRes.Stack[i]) if err != nil { return fmt.Errorf("can't fetch the alphabet contract #%d hash: %w", i, err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index d9ddcb8ade..a8762ac157 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -38,7 +38,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := nnsResolveHash(inv, cs.Hash, domainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(inv, cs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -96,7 +96,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index b9db4c4e57..b93bff8e64 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -36,7 +36,7 @@ func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker) (util.Ui if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err = nnsResolveHash(inv, nnsCs.Hash, domainOf(containerContract)) + ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, domainOf(containerContract)) if err != nil { return util.Uint160{}, err } @@ -307,7 +307,7 @@ func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err := nnsResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, domainOf(containerContract)) + ch, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, domainOf(containerContract)) if err != nil { return util.Uint160{}, fmt.Errorf("can't fetch container contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index db54a8db5f..a29002d257 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -89,7 +89,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { domain := ctrName + "." + zone isUpdate, _ := cmd.Flags().GetBool(updateFlag) if isUpdate { - cs.Hash, err = nnsResolveHash(c.ReadOnlyInvoker, nnsCs.Hash, domain) + cs.Hash, err = util.NNSResolveHash(c.ReadOnlyInvoker, nnsCs.Hash, domain) if err != nil { return fmt.Errorf("can't fetch contract hash from NNS: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index 60e9de9ca7..f4c276f512 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -79,7 +79,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { for i := 0; i < irSize; i++ { info := contractDumpInfo{name: fmt.Sprintf("alphabet %d", i)} - if h, err := parseNNSResolveResult(alphaRes.Stack[i]); err == nil { + if h, err := morphUtil.ParseNNSResolveResult(alphaRes.Stack[i]); err == nil { info.hash = h } infos = append(infos, info) @@ -98,7 +98,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { info := contractDumpInfo{name: ctrName} if len(res.Stack) != 0 { - if h, err := parseNNSResolveResult(res.Stack[0]); err == nil { + if h, err := morphUtil.ParseNNSResolveResult(res.Stack[0]); err == nil { info.hash = h } } @@ -133,7 +133,7 @@ func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, return } - h, err := nnsResolveHash(inv, nnsHash, string(bs)) + h, err := morphUtil.NNSResolveHash(inv, nnsHash, string(bs)) if err != nil { cmd.PrintErrf("Could not resolve name %s: %v\n", string(bs), err) return diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index e491e8b8fe..86f4f0fea7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" @@ -27,7 +28,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) + nmHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 8150dcb5f5..a420b07757 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -431,7 +431,7 @@ func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { return nil, fmt.Errorf("can't get NNS contract info: %w", err) } - ffsidHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) + ffsidHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) if err != nil { return nil, fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 9f0e929a81..fe65a28490 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -203,7 +203,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash cs := c.getContract(ctrName) method := updateMethodName - ctrHash, err := nnsResolveHash(c.ReadOnlyInvoker, nnsHash, domainOf(ctrName)) + ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, domainOf(ctrName)) if err != nil { if errors.Is(err, errMissingNNSRecord) { // if contract not found we deploy it instead of update @@ -267,7 +267,7 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2. // alphabet contracts should be deployed by individual nodes to get different hashes. for i, acc := range c.Accounts { - ctrHash, err := nnsResolveHash(c.ReadOnlyInvoker, nnsHash, getAlphabetNNSDomain(i)) + ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, getAlphabetNNSDomain(i)) if err != nil { return nil, fmt.Errorf("can't resolve hash for contract update: %w", err) } @@ -609,7 +609,7 @@ func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool, if err != nil { return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) } - fidHash, err := nnsResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) + fidHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) if err != nil { return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) } @@ -638,7 +638,7 @@ func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } - nmHash, err := nnsResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) + nmHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { return nil, fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 7364ba0e35..8267fd04d1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -184,7 +184,7 @@ func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.U return bw.Bytes(), false, nil } - s, err := nnsResolveHash(c.ReadOnlyInvoker, nnsHash, domain) + s, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, domain) if err != nil { return nil, false, err } @@ -220,21 +220,8 @@ func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160, zone string) var errMissingNNSRecord = errors.New("missing NNS record") -// Returns errMissingNNSRecord if invocation fault exception contains "token not found". -func nnsResolveHash(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (util.Uint160, error) { - item, err := nnsResolve(inv, nnsHash, domain) - if err != nil { - return util.Uint160{}, err - } - return parseNNSResolveResult(item) -} - -func nnsResolve(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (stackitem.Item, error) { - return unwrap.Item(inv.Call(nnsHash, "resolve", domain, int64(nns.TXT))) -} - func nnsResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) { - res, err := nnsResolve(inv, nnsHash, domain) + res, err := morphUtil.NNSResolve(inv, nnsHash, domain) if err != nil { return nil, err } @@ -257,38 +244,6 @@ func nnsResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (* return nil, errors.New("no valid keys are found") } -// parseNNSResolveResult parses the result of resolving NNS record. -// It works with multiple formats (corresponding to multiple NNS versions). -// If array of hashes is provided, it returns only the first one. -func parseNNSResolveResult(res stackitem.Item) (util.Uint160, error) { - arr, ok := res.Value().([]stackitem.Item) - if !ok { - arr = []stackitem.Item{res} - } - if _, ok := res.Value().(stackitem.Null); ok || len(arr) == 0 { - return util.Uint160{}, errors.New("NNS record is missing") - } - for i := range arr { - bs, err := arr[i].TryBytes() - if err != nil { - continue - } - - // We support several formats for hash encoding, this logic should be maintained in sync - // with nnsResolve from pkg/morph/client/nns.go - h, err := util.Uint160DecodeStringLE(string(bs)) - if err == nil { - return h, nil - } - - h, err = address.StringToUint160(string(bs)) - if err == nil { - return h, nil - } - } - return util.Uint160{}, errors.New("no valid hashes are found") -} - func nnsIsAvailable(c morphUtil.Client, nnsHash util.Uint160, name string) (bool, error) { switch c.(type) { case *rpcclient.Client: diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go index 7d31d18160..cf961cb4db 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go @@ -21,7 +21,7 @@ func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { cs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) - nmHash, err := nnsResolveHash(inv, cs.Hash, domainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(inv, cs.Hash, domainOf(netmapContract)) commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) res, err := inv.Call(nmHash, "netmapCandidates") diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy.go index 802a612467..5a70bfe612 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy.go @@ -3,6 +3,7 @@ package morph import ( "fmt" + util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" @@ -46,7 +47,7 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error return fmt.Errorf("can't get NNS contract info: %w", err) } - proxyHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(proxyContract)) + proxyHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(proxyContract)) if err != nil { return fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/remove_node.go b/cmd/frostfs-adm/internal/modules/morph/remove_node.go index ea958f2f7c..0ae9a1ef70 100644 --- a/cmd/frostfs-adm/internal/modules/morph/remove_node.go +++ b/cmd/frostfs-adm/internal/modules/morph/remove_node.go @@ -5,6 +5,7 @@ import ( "fmt" netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" @@ -40,7 +41,7 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := nnsResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go index d15d99b939..7b195aebd0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go @@ -1,11 +1,18 @@ package util import ( + "errors" "fmt" "time" + "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" @@ -88,3 +95,48 @@ func GetWalletAccount(w *wallet.Wallet, typ string) (*wallet.Account, error) { } return nil, fmt.Errorf("account for '%s' not found", typ) } + +func NNSResolve(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (stackitem.Item, error) { + return unwrap.Item(inv.Call(nnsHash, "resolve", domain, int64(nns.TXT))) +} + +// ParseNNSResolveResult parses the result of resolving NNS record. +// It works with multiple formats (corresponding to multiple NNS versions). +// If array of hashes is provided, it returns only the first one. +func ParseNNSResolveResult(res stackitem.Item) (util.Uint160, error) { + arr, ok := res.Value().([]stackitem.Item) + if !ok { + arr = []stackitem.Item{res} + } + if _, ok := res.Value().(stackitem.Null); ok || len(arr) == 0 { + return util.Uint160{}, errors.New("NNS record is missing") + } + for i := range arr { + bs, err := arr[i].TryBytes() + if err != nil { + continue + } + + // We support several formats for hash encoding, this logic should be maintained in sync + // with NNSResolve from pkg/morph/client/nns.go + h, err := util.Uint160DecodeStringLE(string(bs)) + if err == nil { + return h, nil + } + + h, err = address.StringToUint160(string(bs)) + if err == nil { + return h, nil + } + } + return util.Uint160{}, errors.New("no valid hashes are found") +} + +// NNSResolveHash Returns errMissingNNSRecord if invocation fault exception contains "token not found". +func NNSResolveHash(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (util.Uint160, error) { + item, err := NNSResolve(inv, nnsHash, domain) + if err != nil { + return util.Uint160{}, err + } + return ParseNNSResolveResult(item) +} From 34fcab3498035be3b3fef924d40480327f51ca05 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 09:51:24 +0300 Subject: [PATCH 0346/1413] [#932] adm: Move `alphabet-wallets` flag to `util` package Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/ape.go | 20 ++++---- .../internal/modules/morph/ape_util.go | 2 +- .../internal/modules/morph/deploy.go | 6 +-- .../internal/modules/morph/frostfsid.go | 44 ++++++++--------- .../internal/modules/morph/generate.go | 2 +- .../internal/modules/morph/generate_test.go | 10 ++-- .../internal/modules/morph/initialize.go | 2 +- .../internal/modules/morph/initialize_test.go | 4 +- .../internal/modules/morph/root.go | 48 +++++++++---------- .../internal/modules/morph/util/const.go | 8 ++-- 10 files changed, 73 insertions(+), 73 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape.go index 5ff6e7ab83..f778a69447 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape.go @@ -43,7 +43,7 @@ var ( Short: "Add rule chain", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) }, Run: addRuleChain, } @@ -53,7 +53,7 @@ var ( Short: "Remove rule chain", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) }, Run: removeRuleChain, } @@ -63,7 +63,7 @@ var ( Short: "List rule chains", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) }, Run: listRuleChains, } @@ -73,7 +73,7 @@ var ( Short: "Set admin", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) }, Run: setAdmin, } @@ -83,7 +83,7 @@ var ( Short: "Get admin", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) }, Run: getAdmin, } @@ -93,7 +93,7 @@ func initAddRuleChainCmd() { apeCmd.AddCommand(addRuleChainCmd) addRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - addRuleChainCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + addRuleChainCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) _ = addRuleChainCmd.MarkFlagRequired(targetTypeFlag) @@ -112,7 +112,7 @@ func initRemoveRuleChainCmd() { apeCmd.AddCommand(removeRuleChainCmd) removeRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - removeRuleChainCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + removeRuleChainCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) _ = removeRuleChainCmd.MarkFlagRequired(targetTypeFlag) @@ -126,7 +126,7 @@ func initListRuleChainsCmd() { apeCmd.AddCommand(listRuleChainsCmd) listRuleChainsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - listRuleChainsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + listRuleChainsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) _ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag) listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc) @@ -138,7 +138,7 @@ func initSetAdminCmd() { apeCmd.AddCommand(setAdminCmd) setAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - setAdminCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + setAdminCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) setAdminCmd.Flags().String(addrAdminFlag, "", addrAdminDesc) _ = setAdminCmd.MarkFlagRequired(addrAdminFlag) } @@ -147,7 +147,7 @@ func initGetAdminCmd() { apeCmd.AddCommand(getAdminCmd) getAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - getAdminCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + getAdminCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func addRuleChain(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape_util.go index 6b174232a0..e89c833dba 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape_util.go @@ -81,7 +81,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac c, err := morphUtil.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) + walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag)) wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index a29002d257..85c207d79d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -38,7 +38,7 @@ Compiled contract file name must contain '_contract.nef' suffix. Contract's manifest file name must be 'config.json'. NNS name is taken by stripping '_contract.nef' from the NEF file (similar to frostfs contracts).`, PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: deployContractCmd, @@ -47,8 +47,8 @@ NNS name is taken by stripping '_contract.nef' from the NEF file (similar to fro func init() { ff := deployCmd.Flags() - ff.String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) - _ = deployCmd.MarkFlagFilename(alphabetWalletsFlag) + ff.String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + _ = deployCmd.MarkFlagFilename(util.AlphabetWalletsFlag) ff.StringP(util.EndpointFlag, "r", "", util.EndpointFlagDesc) ff.String(contractPathFlag, "", "Path to the contract directory") diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index a420b07757..c114e48e94 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -41,7 +41,7 @@ var ( Use: "create-namespace", Short: "Create new namespace in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateNamespace, @@ -51,7 +51,7 @@ var ( Use: "list-namespaces", Short: "List all namespaces in frostfsid", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListNamespaces, @@ -61,7 +61,7 @@ var ( Use: "create-subject", Short: "Create subject in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateSubject, @@ -71,7 +71,7 @@ var ( Use: "delete-subject", Short: "Delete subject from frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidDeleteSubject, @@ -81,7 +81,7 @@ var ( Use: "list-subjects", Short: "List subjects in namespace", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListSubjects, @@ -91,7 +91,7 @@ var ( Use: "create-group", Short: "Create group in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidCreateGroup, @@ -101,7 +101,7 @@ var ( Use: "delete-group", Short: "Delete group from frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidDeleteGroup, @@ -111,7 +111,7 @@ var ( Use: "list-groups", Short: "List groups in namespace", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListGroups, @@ -121,7 +121,7 @@ var ( Use: "add-subject-to-group", Short: "Add subject to group", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidAddSubjectToGroup, @@ -131,7 +131,7 @@ var ( Use: "remove-subject-from-group", Short: "Remove subject from group", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidRemoveSubjectFromGroup, @@ -141,7 +141,7 @@ var ( Use: "list-group-subjects", Short: "List subjects in group", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) }, Run: frostfsidListGroupSubjects, @@ -152,13 +152,13 @@ func initFrostfsIDCreateNamespaceCmd() { frostfsidCmd.AddCommand(frostfsidCreateNamespaceCmd) frostfsidCreateNamespaceCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateNamespaceCmd.Flags().String(namespaceFlag, "", "Namespace name to create") - frostfsidCreateNamespaceCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidCreateNamespaceCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDListNamespacesCmd() { frostfsidCmd.AddCommand(frostfsidListNamespacesCmd) frostfsidListNamespacesCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - frostfsidListNamespacesCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidListNamespacesCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDCreateSubjectCmd() { @@ -167,14 +167,14 @@ func initFrostfsIDCreateSubjectCmd() { frostfsidCreateSubjectCmd.Flags().String(namespaceFlag, "", "Namespace where create subject") frostfsidCreateSubjectCmd.Flags().String(subjectNameFlag, "", "Subject name, must be unique in namespace") frostfsidCreateSubjectCmd.Flags().String(subjectKeyFlag, "", "Subject hex-encoded public key") - frostfsidCreateSubjectCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidCreateSubjectCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDDeleteSubjectCmd() { frostfsidCmd.AddCommand(frostfsidDeleteSubjectCmd) frostfsidDeleteSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidDeleteSubjectCmd.Flags().String(subjectAddressFlag, "", "Subject address") - frostfsidDeleteSubjectCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidDeleteSubjectCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDListSubjectsCmd() { @@ -182,7 +182,7 @@ func initFrostfsIDListSubjectsCmd() { frostfsidListSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") - frostfsidListSubjectsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidListSubjectsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDCreateGroupCmd() { @@ -190,7 +190,7 @@ func initFrostfsIDCreateGroupCmd() { frostfsidCreateGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateGroupCmd.Flags().String(namespaceFlag, "", "Namespace where create group") frostfsidCreateGroupCmd.Flags().String(groupNameFlag, "", "Group name, must be unique in namespace") - frostfsidCreateGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidCreateGroupCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDDeleteGroupCmd() { @@ -198,14 +198,14 @@ func initFrostfsIDDeleteGroupCmd() { frostfsidDeleteGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidDeleteGroupCmd.Flags().String(namespaceFlag, "", "Namespace to delete group") frostfsidDeleteGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") - frostfsidDeleteGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidDeleteGroupCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDListGroupsCmd() { frostfsidCmd.AddCommand(frostfsidListGroupsCmd) frostfsidListGroupsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") - frostfsidListGroupsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidListGroupsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDAddSubjectToGroupCmd() { @@ -213,7 +213,7 @@ func initFrostfsIDAddSubjectToGroupCmd() { frostfsidAddSubjectToGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidAddSubjectToGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidAddSubjectToGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") - frostfsidAddSubjectToGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidAddSubjectToGroupCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDRemoveSubjectFromGroupCmd() { @@ -221,7 +221,7 @@ func initFrostfsIDRemoveSubjectFromGroupCmd() { frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidRemoveSubjectFromGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidRemoveSubjectFromGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") - frostfsidRemoveSubjectFromGroupCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidRemoveSubjectFromGroupCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDListGroupSubjectsCmd() { @@ -230,7 +230,7 @@ func initFrostfsIDListGroupSubjectsCmd() { frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") - frostfsidListGroupSubjectsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + frostfsidListGroupSubjectsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate.go index 2d82c1237e..fd27a3c2c2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate.go @@ -44,7 +44,7 @@ func generateAlphabetCreds(cmd *cobra.Command, _ []string) error { } v := viper.GetViper() - walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) + walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag)) pwds, err := initializeWallets(v, walletDir, int(size)) if err != nil { return err diff --git a/cmd/frostfs-adm/internal/modules/morph/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate_test.go index 2386b94e2d..79a0ea7de7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate_test.go @@ -34,28 +34,28 @@ func TestGenerateAlphabet(t *testing.T) { t.Run("zero size", func(t *testing.T) { buf.Reset() - v.Set(alphabetWalletsFlag, walletDir) + v.Set(util.AlphabetWalletsFlag, walletDir) require.NoError(t, cmd.Flags().Set(alphabetSizeFlag, "0")) buf.WriteString("pass\r") require.Error(t, generateAlphabetCreds(cmd, nil)) }) t.Run("no password provided", func(t *testing.T) { buf.Reset() - v.Set(alphabetWalletsFlag, walletDir) + v.Set(util.AlphabetWalletsFlag, walletDir) require.NoError(t, cmd.Flags().Set(alphabetSizeFlag, "1")) require.Error(t, generateAlphabetCreds(cmd, nil)) }) t.Run("missing directory", func(t *testing.T) { buf.Reset() dir := filepath.Join(os.TempDir(), "notexist."+strconv.FormatUint(rand.Uint64(), 10)) - v.Set(alphabetWalletsFlag, dir) + v.Set(util.AlphabetWalletsFlag, dir) require.NoError(t, cmd.Flags().Set(alphabetSizeFlag, "1")) buf.WriteString("pass\r") require.Error(t, generateAlphabetCreds(cmd, nil)) }) t.Run("no password for contract group wallet", func(t *testing.T) { buf.Reset() - v.Set(alphabetWalletsFlag, walletDir) + v.Set(util.AlphabetWalletsFlag, walletDir) require.NoError(t, cmd.Flags().Set(alphabetSizeFlag, strconv.FormatUint(size, 10))) for i := uint64(0); i < size; i++ { buf.WriteString(strconv.FormatUint(i, 10) + "\r") @@ -64,7 +64,7 @@ func TestGenerateAlphabet(t *testing.T) { }) buf.Reset() - v.Set(alphabetWalletsFlag, walletDir) + v.Set(util.AlphabetWalletsFlag, walletDir) require.NoError(t, generateAlphabetCmd.Flags().Set(alphabetSizeFlag, strconv.FormatUint(size, 10))) for i := uint64(0); i < size; i++ { buf.WriteString(strconv.FormatUint(i, 10) + "\r") diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index 2dff2f06fb..51d00f9f4c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -103,7 +103,7 @@ func (c *initializeContext) close() { } func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) { - walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) + walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag)) wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) if err != nil { return nil, err diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index cf71a01d62..bd7c8ee1f2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -62,7 +62,7 @@ func testInitialize(t *testing.T, committeeSize int) { dumpPath := filepath.Join(testdataDir, "out") require.NoError(t, initCmd.Flags().Set(localDumpFlag, dumpPath)) - v.Set(alphabetWalletsFlag, testdataDir) + v.Set(util.AlphabetWalletsFlag, testdataDir) v.Set(epochDurationInitFlag, 1) v.Set(maxObjectSizeInitFlag, 1024) @@ -93,7 +93,7 @@ func testInitialize(t *testing.T, committeeSize int) { func generateTestData(t *testing.T, dir string, size int) error { v := viper.GetViper() - v.Set(alphabetWalletsFlag, dir) + v.Set(util.AlphabetWalletsFlag, dir) sizeStr := strconv.FormatUint(uint64(size), 10) if err := generateAlphabetCmd.Flags().Set(alphabetSizeFlag, sizeStr); err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index dad8c4ee41..5a4fa00638 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -7,8 +7,6 @@ import ( ) const ( - alphabetWalletsFlag = "alphabet-wallets" - alphabetWalletsFlagDesc = "Path to alphabet wallets dir" alphabetSizeFlag = "size" storageWalletFlag = "storage-wallet" storageWalletLabelFlag = "label" @@ -56,7 +54,7 @@ var ( Short: "Generate alphabet wallets for consensus nodes of the morph network", PreRun: func(cmd *cobra.Command, _ []string) { // PreRun fixes https://github.com/spf13/viper/issues/233 - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) }, RunE: generateAlphabetCreds, } @@ -65,7 +63,7 @@ var ( Use: "init", Short: "Initialize side chain network with smart-contracts and network settings", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(epochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) _ = viper.BindPFlag(maxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) @@ -83,7 +81,7 @@ var ( Use: "generate-storage-wallet", Short: "Generate storage node wallet for the morph network", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(storageGasConfigFlag, cmd.Flags().Lookup(storageGasCLIFlag)) }, @@ -94,7 +92,7 @@ var ( Use: "refill-gas", Short: "Refill GAS of storage node's wallet in the morph network", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(refillGasAmountFlag, cmd.Flags().Lookup(refillGasAmountFlag)) }, @@ -107,7 +105,7 @@ var ( Use: "force-new-epoch", Short: "Create new FrostFS epoch event in the side chain", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: forceNewEpochCmd, @@ -118,7 +116,7 @@ var ( Short: "Remove storage nodes from the netmap", Long: `Move nodes to the Offline state in the candidates list and tick an epoch to update the netmap`, PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: removeNodesCmd, @@ -129,7 +127,7 @@ var ( DisableFlagsInUseLine: true, Short: "Add/update global config value in the FrostFS network", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Args: cobra.MinimumNArgs(1), @@ -141,7 +139,7 @@ var ( DisableFlagsInUseLine: true, Short: "Set global policy values", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: setPolicyCmd, @@ -190,7 +188,7 @@ var ( Use: "update-contracts", Short: "Update FrostFS contracts", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: updateContracts, @@ -209,7 +207,7 @@ var ( Use: "restore-containers", Short: "Restore FrostFS containers from file", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, RunE: restoreContainers, @@ -238,7 +236,7 @@ var ( Short: "List netmap candidates nodes", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) }, Run: listNetmapCandidatesNodes, } @@ -247,7 +245,7 @@ var ( Use: "proxy-add-account", Short: "Adds account to proxy contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Run: addProxyAccount, @@ -257,7 +255,7 @@ var ( Use: "proxy-remove-account", Short: "Remove from proxy contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) }, Run: removeProxyAccount, @@ -337,7 +335,7 @@ func initDepositoryNotaryCmd() { func initRefillGasCmd() { RootCmd.AddCommand(refillGasCmd) - refillGasCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + refillGasCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) refillGasCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) refillGasCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") refillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") @@ -353,7 +351,7 @@ func initListContainersCmd() { func initRestoreContainersCmd() { RootCmd.AddCommand(restoreContainersCmd) - restoreContainersCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + restoreContainersCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) restoreContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) restoreContainersCmd.Flags().String(containerDumpFlag, "", "File to restore containers from") restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore") @@ -369,7 +367,7 @@ func initDumpContainersCmd() { func initUpdateContractsCmd() { RootCmd.AddCommand(updateContractsCmd) - updateContractsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + updateContractsCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) updateContractsCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) updateContractsCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) updateContractsCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) @@ -387,7 +385,7 @@ func initDumpBalancesCmd() { func initSetConfigCmd() { RootCmd.AddCommand(setConfig) - setConfig.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + setConfig.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) setConfig.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) setConfig.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") setConfig.Flags().String(localDumpFlag, "", "Path to the blocks dump file") @@ -406,7 +404,7 @@ func initDumpContractHashesCmd() { func initSetPolicyCmd() { RootCmd.AddCommand(setPolicy) - setPolicy.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + setPolicy.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) setPolicy.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) setPolicy.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } @@ -418,21 +416,21 @@ func initDumpPolicyCmd() { func initRemoveNodesCmd() { RootCmd.AddCommand(removeNodes) - removeNodes.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + removeNodes.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) removeNodes.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) removeNodes.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initForceNewEpochCmd() { RootCmd.AddCommand(forceNewEpoch) - forceNewEpoch.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + forceNewEpoch.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) forceNewEpoch.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) forceNewEpoch.Flags().String(localDumpFlag, "", "Path to the blocks dump file") } func initGenerateStorageCmd() { RootCmd.AddCommand(generateStorageCmd) - generateStorageCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + generateStorageCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) generateStorageCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) generateStorageCmd.Flags().String(storageWalletFlag, "", "Path to new storage node wallet") generateStorageCmd.Flags().String(storageGasCLIFlag, "", "Initial amount of GAS to transfer") @@ -441,7 +439,7 @@ func initGenerateStorageCmd() { func initInitCmd() { RootCmd.AddCommand(initCmd) - initCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + initCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) initCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) initCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) initCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) @@ -458,7 +456,7 @@ func initInitCmd() { func initGenerateAlphabetCmd() { RootCmd.AddCommand(generateAlphabetCmd) - generateAlphabetCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) + generateAlphabetCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) generateAlphabetCmd.Flags().Uint(alphabetSizeFlag, 7, "Amount of alphabet wallets to generate") } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index 7278d8357f..4f11fd04d2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -9,7 +9,9 @@ const ( // See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10 MaxAlphabetNodes = 22 - EndpointFlag = "rpc-endpoint" - EndpointFlagDesc = "N3 RPC node endpoint" - EndpointFlagShort = "r" + EndpointFlag = "rpc-endpoint" + EndpointFlagDesc = "N3 RPC node endpoint" + EndpointFlagShort = "r" + AlphabetWalletsFlag = "alphabet-wallets" + AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" ) From fdeb99c52f1f88a794eb5e1bce0a6a725bccad60 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 09:58:12 +0300 Subject: [PATCH 0347/1413] [#932] adm: Move `DomainOf` to `util` package Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/ape_util.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/balance.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/config.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/container.go | 4 ++-- .../internal/modules/morph/dump_hashes.go | 2 +- cmd/frostfs-adm/internal/modules/morph/epoch.go | 2 +- cmd/frostfs-adm/internal/modules/morph/frostfsid.go | 2 +- cmd/frostfs-adm/internal/modules/morph/generate.go | 11 +++-------- .../internal/modules/morph/generate_test.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/initialize.go | 6 +++--- .../internal/modules/morph/initialize_deploy.go | 12 ++++-------- .../internal/modules/morph/initialize_register.go | 2 +- .../internal/modules/morph/initialize_test.go | 2 +- .../internal/modules/morph/initialize_transfer.go | 2 +- .../internal/modules/morph/netmap_candidates.go | 2 +- cmd/frostfs-adm/internal/modules/morph/proxy.go | 2 +- .../internal/modules/morph/remove_node.go | 2 +- cmd/frostfs-adm/internal/modules/morph/util/const.go | 3 +++ .../internal/modules/morph/util/initialize.go | 4 ++++ 19 files changed, 36 insertions(+), 38 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape_util.go index e89c833dba..59e85dda13 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape_util.go @@ -85,7 +85,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) - committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], committeeAccountName) + committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], morphUtil.CommitteeAccountName) commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) ac, err := morphUtil.NewActor(c, committeeAcc) @@ -97,7 +97,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac nnsCs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, domainOf(policyContract)) + ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(policyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) return morph.NewContractStorage(ac, ch), ac diff --git a/cmd/frostfs-adm/internal/modules/morph/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance.go index 71bdebc70d..8ee7aeeed6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance.go @@ -64,7 +64,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, domainOf(netmapContract)) + nmHash, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -137,7 +137,7 @@ func printStorageNodeBalances(cmd *cobra.Command, inv *invoker.Invoker, nmHash u } func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash util.Uint160) error { - h, err := morphUtil.NNSResolveHash(inv, nnsHash, domainOf(proxyContract)) + h, err := morphUtil.NNSResolveHash(inv, nnsHash, morphUtil.DomainOf(proxyContract)) if err != nil { return fmt.Errorf("can't get hash of the proxy contract: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index a8762ac157..3892d31b18 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -38,7 +38,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(inv, cs.Hash, domainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -96,7 +96,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index b93bff8e64..5f59f7db55 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -36,7 +36,7 @@ func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker) (util.Ui if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, domainOf(containerContract)) + ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(containerContract)) if err != nil { return util.Uint160{}, err } @@ -307,7 +307,7 @@ func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, domainOf(containerContract)) + ch, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, morphUtil.DomainOf(containerContract)) if err != nil { return util.Uint160{}, fmt.Errorf("can't fetch container contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index f4c276f512..05ef728433 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -89,7 +89,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { for _, ctrName := range contractList { bw.Reset() emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, - domainOf(ctrName), int64(nns.TXT)) + morphUtil.DomainOf(ctrName), int64(nns.TXT)) res, err := c.InvokeScript(bw.Bytes(), nil) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index 86f4f0fea7..274568afcf 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -28,7 +28,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) + nmHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util2.DomainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index c114e48e94..083fc9ed9a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -431,7 +431,7 @@ func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { return nil, fmt.Errorf("can't get NNS contract info: %w", err) } - ffsidHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) + ffsidHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(frostfsIDContract)) if err != nil { return nil, fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate.go index fd27a3c2c2..a7561b2660 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate.go @@ -25,11 +25,6 @@ import ( "golang.org/x/sync/errgroup" ) -const ( - singleAccountName = "single" - committeeAccountName = "committee" -) - func generateAlphabetCreds(cmd *cobra.Command, _ []string) error { // alphabet size is not part of the config size, err := cmd.Flags().GetUint(alphabetSizeFlag) @@ -87,7 +82,7 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er if err != nil { return nil, fmt.Errorf("can't create wallet: %w", err) } - if err := w.CreateAccount(singleAccountName, password); err != nil { + if err := w.CreateAccount(morphUtil.SingleAccountName, password); err != nil { return nil, fmt.Errorf("can't create account: %w", err) } @@ -106,7 +101,7 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er i := i ps := pubs.Copy() errG.Go(func() error { - if err := addMultisigAccount(wallets[i], majCount, committeeAccountName, passwords[i], ps); err != nil { + if err := addMultisigAccount(wallets[i], majCount, morphUtil.CommitteeAccountName, passwords[i], ps); err != nil { return fmt.Errorf("can't create committee account: %w", err) } if err := addMultisigAccount(wallets[i], bftCount, morphUtil.ConsensusAccountName, passwords[i], ps); err != nil { @@ -182,7 +177,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error } if label == "" { - label = singleAccountName + label = morphUtil.SingleAccountName } if err := w.CreateAccount(label, password); err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate_test.go index 79a0ea7de7..207366ec70 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate_test.go @@ -90,10 +90,10 @@ func TestGenerateAlphabet(t *testing.T) { switch a.Label { case util.ConsensusAccountName: require.Equal(t, smartcontract.GetDefaultHonestNodeCount(size), len(a.Contract.Parameters)) - case committeeAccountName: + case util.CommitteeAccountName: require.Equal(t, smartcontract.GetMajorityHonestNodeCount(size), len(a.Contract.Parameters)) default: - require.Equal(t, singleAccountName, a.Label) + require.Equal(t, util.SingleAccountName, a.Label) } } }() diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index 51d00f9f4c..a432fbc7e7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -122,7 +122,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex return nil, err } - committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], committeeAccountName) + committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], morphUtil.CommitteeAccountName) if err != nil { return nil, fmt.Errorf("can't find committee account: %w", err) } @@ -237,7 +237,7 @@ func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) { func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { accounts := make([]*wallet.Account, len(wallets)) for i, w := range wallets { - acc, err := morphUtil.GetWalletAccount(w, singleAccountName) + acc, err := morphUtil.GetWalletAccount(w, morphUtil.SingleAccountName) if err != nil { return nil, fmt.Errorf("wallet %s is invalid (no single account): %w", w.Path(), err) } @@ -346,7 +346,7 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen return fmt.Errorf("could not perform test invocation: %w", err) } - if err := c.multiSign(tx, committeeAccountName); err != nil { + if err := c.multiSign(tx, morphUtil.CommitteeAccountName); err != nil { return err } if withConsensus { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index fe65a28490..66caf8c195 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -92,10 +92,6 @@ const ( deployMethodName = "deploy" ) -func domainOf(contract string) string { - return contract + ".frostfs" -} - func (c *initializeContext) deployNNS(method string) error { cs := c.getContract(nnsContract) h := cs.Hash @@ -133,7 +129,7 @@ func (c *initializeContext) deployNNS(method string) error { return fmt.Errorf("failed to create deploy tx for %s: %w", nnsContract, err) } - if err := c.multiSignAndSend(tx, committeeAccountName); err != nil { + if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { return fmt.Errorf("can't send deploy transaction: %w", err) } @@ -203,7 +199,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash cs := c.getContract(ctrName) method := updateMethodName - ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, domainOf(ctrName)) + ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName)) if err != nil { if errors.Is(err, errMissingNNSRecord) { // if contract not found we deploy it instead of update @@ -609,7 +605,7 @@ func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool, if err != nil { return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) } - fidHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(frostfsIDContract)) + fidHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(frostfsIDContract)) if err != nil { return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) } @@ -638,7 +634,7 @@ func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } - nmHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) + nmHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(netmapContract)) if err != nil { return nil, fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go index e8e73ae735..78c160ec23 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go @@ -68,7 +68,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error { if err != nil { return fmt.Errorf("can't create tx: %w", err) } - if err := c.multiSign(tx, committeeAccountName); err != nil { + if err := c.multiSign(tx, morphUtil.CommitteeAccountName); err != nil { return fmt.Errorf("can't sign a transaction: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index bd7c8ee1f2..d5d50eca8e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -113,7 +113,7 @@ func generateTestData(t *testing.T, dir string, size int) error { return fmt.Errorf("wallet doesn't exist: %w", err) } for _, acc := range w.Accounts { - if acc.Label == singleAccountName { + if acc.Label == util.SingleAccountName { pub, ok := vm.ParseSignatureContract(acc.Contract.Script) if !ok { return fmt.Errorf("could not parse signature script for %s", acc.Address) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index e9945cee65..90e2164866 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -161,7 +161,7 @@ func (c *initializeContext) transferGASToProxy() error { return err } - if err := c.multiSignAndSend(tx, committeeAccountName); err != nil { + if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go index cf961cb4db..623f1d9aeb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go @@ -21,7 +21,7 @@ func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { cs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) - nmHash, err := util.NNSResolveHash(inv, cs.Hash, domainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(netmapContract)) commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) res, err := inv.Call(nmHash, "netmapCandidates") diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy.go index 5a70bfe612..5ae4ae0419 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy.go @@ -47,7 +47,7 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error return fmt.Errorf("can't get NNS contract info: %w", err) } - proxyHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(proxyContract)) + proxyHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util2.DomainOf(proxyContract)) if err != nil { return fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/remove_node.go b/cmd/frostfs-adm/internal/modules/morph/remove_node.go index 0ae9a1ef70..75c486e03e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/remove_node.go +++ b/cmd/frostfs-adm/internal/modules/morph/remove_node.go @@ -41,7 +41,7 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, domainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(netmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index 4f11fd04d2..d6e5dbc987 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -14,4 +14,7 @@ const ( EndpointFlagShort = "r" AlphabetWalletsFlag = "alphabet-wallets" AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" + + SingleAccountName = "single" + CommitteeAccountName = "committee" ) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go index 7b195aebd0..923061a099 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go @@ -140,3 +140,7 @@ func NNSResolveHash(inv *invoker.Invoker, nnsHash util.Uint160, domain string) ( } return ParseNNSResolveResult(item) } + +func DomainOf(contract string) string { + return contract + ".frostfs" +} From ba00fc4971170b9d610674a3bb100a688e13e0a5 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 10:06:05 +0300 Subject: [PATCH 0348/1413] [#932] adm: Move contract name constants to `util` package Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/ape_util.go | 2 +- .../internal/modules/morph/balance.go | 4 +- .../internal/modules/morph/config.go | 4 +- .../internal/modules/morph/container.go | 4 +- .../internal/modules/morph/dump_hashes.go | 2 +- .../internal/modules/morph/epoch.go | 2 +- .../internal/modules/morph/frostfsid.go | 2 +- .../modules/morph/initialize_deploy.go | 89 ++++++++----------- .../internal/modules/morph/initialize_nns.go | 4 +- .../modules/morph/initialize_register.go | 2 +- .../modules/morph/initialize_transfer.go | 2 +- .../modules/morph/netmap_candidates.go | 2 +- .../internal/modules/morph/proxy.go | 2 +- .../internal/modules/morph/remove_node.go | 2 +- .../internal/modules/morph/util/const.go | 11 +++ 15 files changed, 66 insertions(+), 68 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape_util.go index 59e85dda13..f9dcdffe85 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape_util.go @@ -97,7 +97,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac nnsCs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(policyContract)) + ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(morphUtil.PolicyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) return morph.NewContractStorage(ac, ch), ac diff --git a/cmd/frostfs-adm/internal/modules/morph/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance.go index 8ee7aeeed6..451d57954f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance.go @@ -64,7 +64,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(netmapContract)) + nmHash, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -137,7 +137,7 @@ func printStorageNodeBalances(cmd *cobra.Command, inv *invoker.Invoker, nmHash u } func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash util.Uint160) error { - h, err := morphUtil.NNSResolveHash(inv, nnsHash, morphUtil.DomainOf(proxyContract)) + h, err := morphUtil.NNSResolveHash(inv, nnsHash, morphUtil.DomainOf(morphUtil.ProxyContract)) if err != nil { return fmt.Errorf("can't get hash of the proxy contract: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index 3892d31b18..0d042d94a6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -38,7 +38,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(util.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -96,7 +96,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(util.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index 5f59f7db55..5400a51c97 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -36,7 +36,7 @@ func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker) (util.Ui if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(containerContract)) + ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(morphUtil.ContainerContract)) if err != nil { return util.Uint160{}, err } @@ -307,7 +307,7 @@ func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, morphUtil.DomainOf(containerContract)) + ch, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, morphUtil.DomainOf(morphUtil.ContainerContract)) if err != nil { return util.Uint160{}, fmt.Errorf("can't fetch container contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index 05ef728433..ce3585c676 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -50,7 +50,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return dumpCustomZoneHashes(cmd, cs.Hash, zone, c) } - infos := []contractDumpInfo{{name: nnsContract, hash: cs.Hash}} + infos := []contractDumpInfo{{name: morphUtil.NNSContract, hash: cs.Hash}} irSize := 0 for ; irSize < lastGlagoliticLetter; irSize++ { diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index 274568afcf..7cb73e2646 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -28,7 +28,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util2.DomainOf(netmapContract)) + nmHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util2.DomainOf(util2.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 083fc9ed9a..0ad8fe7631 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -431,7 +431,7 @@ func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { return nil, fmt.Errorf("can't get NNS contract info: %w", err) } - ffsidHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(frostfsIDContract)) + ffsidHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract)) if err != nil { return nil, fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 66caf8c195..e76a9f0d37 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -35,36 +35,23 @@ import ( "github.com/spf13/viper" ) -const ( - nnsContract = "nns" - frostfsContract = "frostfs" // not deployed in side-chain. - processingContract = "processing" // not deployed in side-chain. - alphabetContract = "alphabet" - balanceContract = "balance" - containerContract = "container" - frostfsIDContract = "frostfsid" - netmapContract = "netmap" - policyContract = "policy" - proxyContract = "proxy" -) - const frostfsIDAdminConfigKey = "frostfsid.admin" var ( contractList = []string{ - balanceContract, - containerContract, - frostfsIDContract, - netmapContract, - policyContract, - proxyContract, + morphUtil.BalanceContract, + morphUtil.ContainerContract, + morphUtil.FrostfsIDContract, + morphUtil.NetmapContract, + morphUtil.PolicyContract, + morphUtil.ProxyContract, } fullContractList = append([]string{ - frostfsContract, - processingContract, - nnsContract, - alphabetContract, + morphUtil.FrostfsContract, + morphUtil.ProcessingContract, + morphUtil.NNSContract, + morphUtil.AlphabetContract, }, contractList...) netmapConfigKeys = []string{ @@ -93,7 +80,7 @@ const ( ) func (c *initializeContext) deployNNS(method string) error { - cs := c.getContract(nnsContract) + cs := c.getContract(morphUtil.NNSContract) h := cs.Hash nnsCs, err := c.nnsContractState() @@ -126,7 +113,7 @@ func (c *initializeContext) deployNNS(method string) error { tx, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) if err != nil { - return fmt.Errorf("failed to create deploy tx for %s: %w", nnsContract, err) + return fmt.Errorf("failed to create deploy tx for %s: %w", morphUtil.NNSContract, err) } if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { @@ -137,7 +124,7 @@ func (c *initializeContext) deployNNS(method string) error { } func (c *initializeContext) updateContracts() error { - alphaCs := c.getContract(alphabetContract) + alphaCs := c.getContract(morphUtil.AlphabetContract) nnsCs, err := c.nnsContractState() if err != nil { @@ -296,7 +283,7 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2. } func (c *initializeContext) deployContracts() error { - alphaCs := c.getContract(alphabetContract) + alphaCs := c.getContract(morphUtil.AlphabetContract) var keysParam []any @@ -422,7 +409,7 @@ func (c *initializeContext) readContracts(names []string) error { } for _, ctrName := range names { - if ctrName != alphabetContract { + if ctrName != morphUtil.AlphabetContract { cs := c.Contracts[ctrName] cs.Hash = state.CreateContractHash(c.CommitteeAcc.Contract.ScriptHash(), cs.NEF.Checksum, cs.Manifest.Name) @@ -524,19 +511,19 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an items := make([]any, 0, 6) switch ctrName { - case frostfsContract: + case morphUtil.FrostfsContract: items = append(items, - c.Contracts[processingContract].Hash, + c.Contracts[morphUtil.ProcessingContract].Hash, keysParam, smartcontract.Parameter{}) - case processingContract: - items = append(items, c.Contracts[frostfsContract].Hash) + case morphUtil.ProcessingContract: + items = append(items, c.Contracts[morphUtil.FrostfsContract].Hash) return items[1:], nil // no notary info - case balanceContract: + case morphUtil.BalanceContract: items = append(items, - c.Contracts[netmapContract].Hash, - c.Contracts[containerContract].Hash) - case containerContract: + c.Contracts[morphUtil.NetmapContract].Hash, + c.Contracts[morphUtil.ContainerContract].Hash) + case morphUtil.ContainerContract: // In case if NNS is updated multiple times, we can't calculate // it's actual hash based on local data, thus query chain. r := management.NewReader(c.ReadOnlyInvoker) @@ -545,12 +532,12 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an return nil, fmt.Errorf("get nns contract: %w", err) } items = append(items, - c.Contracts[netmapContract].Hash, - c.Contracts[balanceContract].Hash, - c.Contracts[frostfsIDContract].Hash, + c.Contracts[morphUtil.NetmapContract].Hash, + c.Contracts[morphUtil.BalanceContract].Hash, + c.Contracts[morphUtil.FrostfsIDContract].Hash, nnsCs.Hash, "container") - case frostfsIDContract: + case morphUtil.FrostfsIDContract: var ( h util.Uint160 found bool @@ -569,9 +556,9 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an if found { items = append(items, h) } else { - items = append(items, c.Contracts[proxyContract].Hash) + items = append(items, c.Contracts[morphUtil.ProxyContract].Hash) } - case netmapContract: + case morphUtil.NetmapContract: md := getDefaultNetmapContractConfigMap() if method == updateMethodName { if err := c.mergeNetmapConfig(md); err != nil { @@ -585,14 +572,14 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an } items = append(items, - c.Contracts[balanceContract].Hash, - c.Contracts[containerContract].Hash, + c.Contracts[morphUtil.BalanceContract].Hash, + c.Contracts[morphUtil.ContainerContract].Hash, keysParam, configParam) - case proxyContract: + case morphUtil.ProxyContract: items = nil - case policyContract: - items = append(items, c.Contracts[proxyContract].Hash) + case morphUtil.PolicyContract: + items = append(items, c.Contracts[morphUtil.ProxyContract].Hash) default: panic(fmt.Sprintf("invalid contract name: %s", ctrName)) } @@ -605,7 +592,7 @@ func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool, if err != nil { return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) } - fidHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(frostfsIDContract)) + fidHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract)) if err != nil { return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) } @@ -634,7 +621,7 @@ func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } - nmHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(netmapContract)) + nmHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract)) if err != nil { return nil, fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -667,8 +654,8 @@ func (c *initializeContext) mergeNetmapConfig(md map[string]any) error { func (c *initializeContext) getAlphabetDeployItems(i, n int) []any { items := make([]any, 5) - items[0] = c.Contracts[netmapContract].Hash - items[1] = c.Contracts[proxyContract].Hash + items[0] = c.Contracts[morphUtil.NetmapContract].Hash + items[1] = c.Contracts[morphUtil.ProxyContract].Hash items[2] = innerring.GlagoliticLetter(i).String() items[3] = int64(i) items[4] = int64(n) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 8267fd04d1..7b0bc81976 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -55,7 +55,7 @@ func (c *initializeContext) setNNS() error { } } - alphaCs := c.getContract(alphabetContract) + alphaCs := c.getContract(morphUtil.AlphabetContract) for i, acc := range c.Accounts { alphaCs.Hash = state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name) @@ -139,7 +139,7 @@ func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHas } func getAlphabetNNSDomain(i int) string { - return alphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs" + return morphUtil.AlphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs" } // wrapRegisterScriptWithPrice wraps a given script with `getPrice`/`setPrice` calls for NNS. diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go index 78c160ec23..04afd7c77c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go @@ -123,7 +123,7 @@ func (c *initializeContext) transferNEOToAlphabetContracts() error { return err } - cs := c.getContract(alphabetContract) + cs := c.getContract(morphUtil.AlphabetContract) amount := initialAlphabetNEOAmount / len(c.Wallets) bw := io.NewBufBinWriter() diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index 90e2164866..a24d3a6f66 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -144,7 +144,7 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin } func (c *initializeContext) transferGASToProxy() error { - proxyCs := c.getContract(proxyContract) + proxyCs := c.getContract(morphUtil.ProxyContract) r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) bal, err := r.BalanceOf(proxyCs.Hash) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go index 623f1d9aeb..c09ba8b8de 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go @@ -21,7 +21,7 @@ func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { cs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) - nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(util.NetmapContract)) commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) res, err := inv.Call(nmHash, "netmapCandidates") diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy.go index 5ae4ae0419..9e973b0de8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy.go @@ -47,7 +47,7 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error return fmt.Errorf("can't get NNS contract info: %w", err) } - proxyHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util2.DomainOf(proxyContract)) + proxyHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util2.DomainOf(util2.ProxyContract)) if err != nil { return fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/remove_node.go b/cmd/frostfs-adm/internal/modules/morph/remove_node.go index 75c486e03e..678bcc7eee 100644 --- a/cmd/frostfs-adm/internal/modules/morph/remove_node.go +++ b/cmd/frostfs-adm/internal/modules/morph/remove_node.go @@ -41,7 +41,7 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(netmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(util.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index d6e5dbc987..bf71b067fd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -17,4 +17,15 @@ const ( SingleAccountName = "single" CommitteeAccountName = "committee" + + NNSContract = "nns" + FrostfsContract = "frostfs" // not deployed in side-chain. + ProcessingContract = "processing" // not deployed in side-chain. + AlphabetContract = "alphabet" + BalanceContract = "balance" + ContainerContract = "container" + FrostfsIDContract = "frostfsid" + NetmapContract = "netmap" + PolicyContract = "policy" + ProxyContract = "proxy" ) From bee3741f4e6895b7dc0ee13258afcc15bc76ec44 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 10:20:17 +0300 Subject: [PATCH 0349/1413] [#932] adm: Move cmd `morph ape` to `ape` package Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/{ => ape}/ape.go | 17 ++++++----------- .../modules/morph/{ => ape}/ape_util.go | 2 +- .../internal/modules/morph/ape/root.go | 16 ++++++++++++++++ cmd/frostfs-adm/internal/modules/morph/root.go | 8 ++------ 4 files changed, 25 insertions(+), 18 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => ape}/ape.go (96%) rename cmd/frostfs-adm/internal/modules/morph/{ => ape}/ape_util.go (99%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/ape/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go similarity index 96% rename from cmd/frostfs-adm/internal/modules/morph/ape.go rename to cmd/frostfs-adm/internal/modules/morph/ape/ape.go index f778a69447..de3765042f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -1,4 +1,4 @@ -package morph +package ape import ( "bytes" @@ -33,11 +33,6 @@ const ( ) var ( - apeCmd = &cobra.Command{ - Use: "ape", - Short: "Section for APE configuration commands", - } - addRuleChainCmd = &cobra.Command{ Use: "add-rule-chain", Short: "Add rule chain", @@ -90,7 +85,7 @@ var ( ) func initAddRuleChainCmd() { - apeCmd.AddCommand(addRuleChainCmd) + Cmd.AddCommand(addRuleChainCmd) addRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) addRuleChainCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) @@ -109,7 +104,7 @@ func initAddRuleChainCmd() { } func initRemoveRuleChainCmd() { - apeCmd.AddCommand(removeRuleChainCmd) + Cmd.AddCommand(removeRuleChainCmd) removeRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) removeRuleChainCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) @@ -123,7 +118,7 @@ func initRemoveRuleChainCmd() { } func initListRuleChainsCmd() { - apeCmd.AddCommand(listRuleChainsCmd) + Cmd.AddCommand(listRuleChainsCmd) listRuleChainsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) listRuleChainsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) @@ -135,7 +130,7 @@ func initListRuleChainsCmd() { } func initSetAdminCmd() { - apeCmd.AddCommand(setAdminCmd) + Cmd.AddCommand(setAdminCmd) setAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) setAdminCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) @@ -144,7 +139,7 @@ func initSetAdminCmd() { } func initGetAdminCmd() { - apeCmd.AddCommand(getAdminCmd) + Cmd.AddCommand(getAdminCmd) getAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) getAdminCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/ape_util.go rename to cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index f9dcdffe85..21f27bfd7e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -1,4 +1,4 @@ -package morph +package ape import ( "encoding/json" diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/root.go b/cmd/frostfs-adm/internal/modules/morph/ape/root.go new file mode 100644 index 0000000000..11b6894cfa --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/ape/root.go @@ -0,0 +1,16 @@ +package ape + +import "github.com/spf13/cobra" + +var Cmd = &cobra.Command{ + Use: "ape", + Short: "Section for APE configuration commands", +} + +func init() { + initAddRuleChainCmd() + initRemoveRuleChainCmd() + initListRuleChainsCmd() + initSetAdminCmd() + initGetAdminCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 5a4fa00638..3288779677 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -1,6 +1,7 @@ package morph import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -283,12 +284,7 @@ func init() { initDepositoryNotaryCmd() initNetmapCandidatesCmd() - RootCmd.AddCommand(apeCmd) - initAddRuleChainCmd() - initRemoveRuleChainCmd() - initListRuleChainsCmd() - initSetAdminCmd() - initGetAdminCmd() + RootCmd.AddCommand(ape.Cmd) initProxyAddAccount() initProxyRemoveAccount() From b68f7be0b6c7c0f58f5c972a309005c811fa9e74 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 14:30:59 +0300 Subject: [PATCH 0350/1413] [#932] adm: Prepare to move `InitializeContext` to `util` package Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/config.go | 6 +- .../internal/modules/morph/container.go | 14 +- .../internal/modules/morph/deploy.go | 14 +- .../internal/modules/morph/dump_hashes.go | 2 +- .../internal/modules/morph/epoch.go | 8 +- .../internal/modules/morph/frostfsid.go | 10 +- .../internal/modules/morph/generate.go | 6 +- .../internal/modules/morph/group.go | 5 +- .../internal/modules/morph/initialize.go | 80 +++++----- .../modules/morph/initialize_deploy.go | 148 ++++++++---------- .../internal/modules/morph/initialize_nns.go | 91 +++-------- .../modules/morph/initialize_register.go | 26 +-- .../modules/morph/initialize_roles.go | 10 +- .../modules/morph/initialize_transfer.go | 24 +-- .../internal/modules/morph/policy.go | 6 +- .../internal/modules/morph/proxy.go | 6 +- .../internal/modules/morph/remove_node.go | 8 +- .../internal/modules/morph/update.go | 6 +- .../internal/modules/morph/util/initialize.go | 43 +++++ .../modules/morph/util/initialize_ctx.go | 34 ++++ 20 files changed, 277 insertions(+), 270 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index 0d042d94a6..2d0f12afe2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -85,7 +85,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { return errors.New("empty config pairs") } - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't initialize context: %w", err) } @@ -119,12 +119,12 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { } } - err = wCtx.sendConsensusTx(bw.Bytes()) + err = wCtx.SendConsensusTx(bw.Bytes()) if err != nil { return err } - return wCtx.awaitTx() + return wCtx.AwaitTx() } func parseConfigPair(kvStr string, force bool) (key string, val any, err error) { diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index 5400a51c97..ab32dcabbe 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -193,11 +193,11 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid filename: %w", err) } - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return err } - defer wCtx.close() + defer wCtx.Close() containers, err := parseContainers(filename) if err != nil { @@ -219,10 +219,10 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return err } - return wCtx.awaitTx() + return wCtx.AwaitTx() } -func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *initializeContext, ch util.Uint160) error { +func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *InitializeContext, ch util.Uint160) error { bw := io.NewBufBinWriter() for _, cnt := range containers { hv := hash.Sha256(cnt.Value) @@ -246,7 +246,7 @@ func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd panic(bw.Err) } - if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil { + if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil { return err } } @@ -262,7 +262,7 @@ func putContainer(bw *io.BufBinWriter, ch util.Uint160, cnt Container) { } } -func isContainerRestored(cmd *cobra.Command, wCtx *initializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { +func isContainerRestored(cmd *cobra.Command, wCtx *InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { emit.AppCall(bw.BinWriter, containerHash, "get", callflag.All, hashValue.BytesBE()) res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil) if err != nil { @@ -300,7 +300,7 @@ func parseContainers(filename string) ([]Container, error) { return containers, nil } -func fetchContainerContractHash(wCtx *initializeContext) (util.Uint160, error) { +func fetchContainerContractHash(wCtx *InitializeContext) (util.Uint160, error) { r := management.NewReader(wCtx.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index 85c207d79d..7f11362e08 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -60,11 +60,11 @@ func init() { func deployContractCmd(cmd *cobra.Command, args []string) error { v := viper.GetViper() - c, err := newInitializeContext(cmd, v) + c, err := NewInitializeContext(cmd, v) if err != nil { return fmt.Errorf("initialization error: %w", err) } - defer c.close() + defer c.Close() ctrPath, _ := cmd.Flags().GetString(contractPathFlag) ctrName, err := probeContractName(ctrPath) @@ -123,13 +123,13 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { panic(fmt.Errorf("BUG: can't create deployment script: %w", writer.Err)) } - if err := c.sendCommitteeTx(writer.Bytes(), false); err != nil { + if err := c.SendCommitteeTx(writer.Bytes(), false); err != nil { return err } - return c.awaitTx() + return c.AwaitTx() } -func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domain string, cs *contractState, writer *io.BufBinWriter) error { +func registerNNS(nnsCs *state.Contract, c *InitializeContext, zone string, domain string, cs *util.ContractState, writer *io.BufBinWriter) error { bw := io.NewBufBinWriter() emit.Instruction(bw.BinWriter, opcode.INITSSLOT, []byte{1}) emit.AppCall(bw.BinWriter, nnsCs.Hash, "getPrice", callflag.All) @@ -139,7 +139,7 @@ func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domai start := bw.Len() needRecord := false - ok, err := c.nnsRootRegistered(nnsCs.Hash, zone) + ok, err := c.NNSRootRegistered(nnsCs.Hash, zone) if err != nil { return err } else if !ok { @@ -155,7 +155,7 @@ func registerNNS(nnsCs *state.Contract, c *initializeContext, zone string, domai frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) } else { - s, ok, err := c.nnsRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) + s, ok, err := c.NNSRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index ce3585c676..79b82ee471 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -54,7 +54,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { irSize := 0 for ; irSize < lastGlagoliticLetter; irSize++ { - ok, err := nnsIsAvailable(c, cs.Hash, getAlphabetNNSDomain(irSize)) + ok, err := morphUtil.NNSIsAvailable(c, cs.Hash, getAlphabetNNSDomain(irSize)) if err != nil { return err } else if ok { diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index 7cb73e2646..0fc25d01df 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -17,7 +17,7 @@ import ( ) func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -38,8 +38,8 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return err } - if err = wCtx.sendConsensusTx(bw.Bytes()); err == nil { - err = wCtx.awaitTx() + if err = wCtx.SendConsensusTx(bw.Bytes()); err == nil { + err = wCtx.AwaitTx() } if err != nil && strings.Contains(err.Error(), "invalid epoch") { cmd.Println("Epoch has already ticked.") @@ -48,7 +48,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return err } -func emitNewEpochCall(bw *io.BufBinWriter, wCtx *initializeContext, nmHash util.Uint160) error { +func emitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160) error { curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch")) if err != nil { return errors.New("can't fetch current epoch from the netmap contract") diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 0ad8fe7631..4adde815d5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -416,11 +416,11 @@ type frostfsidClient struct { bw *io.BufBinWriter contractHash util.Uint160 roCli *frostfsidclient.Client // client can be used only for waiting tx, parsing and forming method params - wCtx *initializeContext + wCtx *InitializeContext } func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return nil, fmt.Errorf("can't to initialize context: %w", err) } @@ -449,16 +449,16 @@ func (f *frostfsidClient) addCall(method string, args []any) { } func (f *frostfsidClient) sendWait() error { - if err := f.wCtx.sendConsensusTx(f.bw.Bytes()); err != nil { + if err := f.wCtx.SendConsensusTx(f.bw.Bytes()); err != nil { return err } f.bw.Reset() - return f.wCtx.awaitTx() + return f.wCtx.AwaitTx() } func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) { - if err := f.wCtx.sendConsensusTx(f.bw.Bytes()); err != nil { + if err := f.wCtx.SendConsensusTx(f.bw.Bytes()); err != nil { return nil, err } f.bw.Reset() diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate.go index a7561b2660..f8e155f5b7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate.go @@ -195,7 +195,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error return err } - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return err } @@ -208,11 +208,11 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err) } - if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil { + if err := wCtx.SendCommitteeTx(bw.Bytes(), false); err != nil { return err } - return wCtx.awaitTx() + return wCtx.AwaitTx() } func parseGASAmount(s string) (fixedn.Fixed8, error) { diff --git a/cmd/frostfs-adm/internal/modules/morph/group.go b/cmd/frostfs-adm/internal/modules/morph/group.go index 3fdffd4e6a..0e6c511daa 100644 --- a/cmd/frostfs-adm/internal/modules/morph/group.go +++ b/cmd/frostfs-adm/internal/modules/morph/group.go @@ -7,6 +7,7 @@ import ( "path/filepath" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/util" @@ -75,8 +76,8 @@ func openContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (* return w, nil } -func (c *initializeContext) addManifestGroup(h util.Uint160, cs *contractState) error { - priv := c.ContractWallet.Accounts[0].PrivateKey() +func addManifestGroup(cw *wallet.Wallet, h util.Uint160, cs *util2.ContractState) error { + priv := cw.Accounts[0].PrivateKey() pub := priv.PublicKey() sig := priv.Sign(h.BytesBE()) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index a432fbc7e7..2057b4a24c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -20,14 +20,14 @@ import ( "github.com/spf13/viper" ) -type cache struct { - nnsCs *state.Contract - groupKey *keys.PublicKey +type Cache struct { + NNSCs *state.Contract + GroupKey *keys.PublicKey } -type initializeContext struct { +type InitializeContext struct { morphUtil.ClientContext - cache + Cache // CommitteeAcc is used for retrieving the committee address and the verification script. CommitteeAcc *wallet.Account // ConsensusAcc is used for retrieving the committee address and the verification script. @@ -37,62 +37,62 @@ type initializeContext struct { ContractWallet *wallet.Wallet // Accounts contains simple signature accounts in the same order as in Wallets. Accounts []*wallet.Account - Contracts map[string]*contractState + Contracts map[string]*morphUtil.ContractState Command *cobra.Command ContractPath string ContractURL string } func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { - initCtx, err := newInitializeContext(cmd, viper.GetViper()) + initCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("initialization error: %w", err) } - defer initCtx.close() + defer initCtx.Close() // 1. Transfer funds to committee accounts. cmd.Println("Stage 1: transfer GAS to alphabet nodes.") - if err := initCtx.transferFunds(); err != nil { + if err := transferFunds(initCtx); err != nil { return err } cmd.Println("Stage 2: set notary and alphabet nodes in designate contract.") - if err := initCtx.setNotaryAndAlphabetNodes(); err != nil { + if err := setNotaryAndAlphabetNodes(initCtx); err != nil { return err } // 3. Deploy NNS contract. cmd.Println("Stage 3: deploy NNS contract.") - if err := initCtx.deployNNS(deployMethodName); err != nil { + if err := deployNNS(initCtx, deployMethodName); err != nil { return err } // 4. Deploy NeoFS contracts. cmd.Println("Stage 4: deploy NeoFS contracts.") - if err := initCtx.deployContracts(); err != nil { + if err := deployContracts(initCtx); err != nil { return err } cmd.Println("Stage 4.1: Transfer GAS to proxy contract.") - if err := initCtx.transferGASToProxy(); err != nil { + if err := transferGASToProxy(initCtx); err != nil { return err } cmd.Println("Stage 5: register candidates.") - if err := initCtx.registerCandidates(); err != nil { + if err := registerCandidates(initCtx); err != nil { return err } cmd.Println("Stage 6: transfer NEO to alphabet contracts.") - if err := initCtx.transferNEOToAlphabetContracts(); err != nil { + if err := transferNEOToAlphabetContracts(initCtx); err != nil { return err } cmd.Println("Stage 7: set addresses in NNS.") - return initCtx.setNNS() + return setNNS(initCtx) } -func (c *initializeContext) close() { +func (c *InitializeContext) Close() { if local, ok := c.Client.(*morphUtil.LocalClient); ok { err := local.Dump() if err != nil { @@ -102,7 +102,7 @@ func (c *initializeContext) close() { } } -func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) { +func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContext, error) { walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag)) wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) if err != nil { @@ -160,7 +160,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex return nil, fmt.Errorf("client context: %w", err) } - initCtx := &initializeContext{ + initCtx := &InitializeContext{ ClientContext: *cliCtx, ConsensusAcc: consensusAcc, CommitteeAcc: committeeAcc, @@ -168,7 +168,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex Wallets: wallets, Accounts: accounts, Command: cmd, - Contracts: make(map[string]*contractState), + Contracts: make(map[string]*morphUtil.ContractState), ContractPath: ctrPath, ContractURL: ctrURL, } @@ -246,13 +246,13 @@ func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { return accounts, nil } -func (c *initializeContext) awaitTx() error { +func (c *InitializeContext) AwaitTx() error { return c.ClientContext.AwaitTx(c.Command) } -func (c *initializeContext) nnsContractState() (*state.Contract, error) { - if c.nnsCs != nil { - return c.nnsCs, nil +func (c *InitializeContext) NNSContractState() (*state.Contract, error) { + if c.NNSCs != nil { + return c.NNSCs, nil } r := management.NewReader(c.ReadOnlyInvoker) @@ -261,16 +261,16 @@ func (c *initializeContext) nnsContractState() (*state.Contract, error) { return nil, err } - c.nnsCs = cs + c.NNSCs = cs return cs, nil } -func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transaction.Signer { - if tryGroup && c.groupKey != nil { +func (c *InitializeContext) GetSigner(tryGroup bool, acc *wallet.Account) transaction.Signer { + if tryGroup && c.GroupKey != nil { return transaction.Signer{ Account: acc.Contract.ScriptHash(), Scopes: transaction.CustomGroups, - AllowedGroups: keys.PublicKeys{c.groupKey}, + AllowedGroups: keys.PublicKeys{c.GroupKey}, } } @@ -283,14 +283,14 @@ func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transa return signer } - nnsCs, err := c.nnsContractState() + nnsCs, err := c.NNSContractState() if err != nil { return signer } - groupKey, err := nnsResolveKey(c.ReadOnlyInvoker, nnsCs.Hash, morphClient.NNSGroupKeyName) + groupKey, err := morphUtil.NNSResolveKey(c.ReadOnlyInvoker, nnsCs.Hash, morphClient.NNSGroupKeyName) if err == nil { - c.groupKey = groupKey + c.GroupKey = groupKey signer.Scopes = transaction.CustomGroups signer.AllowedGroups = keys.PublicKeys{groupKey} @@ -298,21 +298,21 @@ func (c *initializeContext) getSigner(tryGroup bool, acc *wallet.Account) transa return signer } -// sendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC. +// SendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC. // If tryGroup is false, global scope is used for the signer (useful when // working with native contracts). -func (c *initializeContext) sendCommitteeTx(script []byte, tryGroup bool) error { +func (c *InitializeContext) SendCommitteeTx(script []byte, tryGroup bool) error { return c.sendMultiTx(script, tryGroup, false) } -// sendConsensusTx creates transaction from script, signs it by alphabet nodes and sends it to RPC. +// SendConsensusTx creates transaction from script, signs it by alphabet nodes and sends it to RPC. // Not that because this is used only after the contracts were initialized and deployed, // we always try to have a group scope. -func (c *initializeContext) sendConsensusTx(script []byte) error { +func (c *InitializeContext) SendConsensusTx(script []byte) error { return c.sendMultiTx(script, true, true) } -func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error { +func (c *InitializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error { var act *actor.Actor var err error @@ -321,12 +321,12 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen // Even for consensus signatures we need the committee to pay. signers := make([]actor.SignerAccount, 1, 2) signers[0] = actor.SignerAccount{ - Signer: c.getSigner(tryGroup, c.CommitteeAcc), + Signer: c.GetSigner(tryGroup, c.CommitteeAcc), Account: c.CommitteeAcc, } if withConsensus { signers = append(signers, actor.SignerAccount{ - Signer: c.getSigner(tryGroup, c.ConsensusAcc), + Signer: c.GetSigner(tryGroup, c.ConsensusAcc), Account: c.ConsensusAcc, }) } @@ -346,11 +346,11 @@ func (c *initializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen return fmt.Errorf("could not perform test invocation: %w", err) } - if err := c.multiSign(tx, morphUtil.CommitteeAccountName); err != nil { + if err := c.MultiSign(tx, morphUtil.CommitteeAccountName); err != nil { return err } if withConsensus { - if err := c.multiSign(tx, morphUtil.ConsensusAccountName); err != nil { + if err := c.MultiSign(tx, morphUtil.ConsensusAccountName); err != nil { return err } } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index e76a9f0d37..fd27eda6c3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -4,7 +4,6 @@ import ( "archive/tar" "compress/gzip" "encoding/hex" - "encoding/json" "errors" "fmt" "io" @@ -22,12 +21,11 @@ import ( "github.com/nspcc-dev/neo-go/pkg/encoding/address" io2 "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -66,24 +64,16 @@ var ( } ) -type contractState struct { - NEF *nef.File - RawNEF []byte - Manifest *manifest.Manifest - RawManifest []byte - Hash util.Uint160 -} - const ( updateMethodName = "update" deployMethodName = "deploy" ) -func (c *initializeContext) deployNNS(method string) error { - cs := c.getContract(morphUtil.NNSContract) +func deployNNS(c *InitializeContext, method string) error { + cs := c.GetContract(morphUtil.NNSContract) h := cs.Hash - nnsCs, err := c.nnsContractState() + nnsCs, err := c.NNSContractState() if err != nil { return err } @@ -99,7 +89,7 @@ func (c *initializeContext) deployNNS(method string) error { h = nnsCs.Hash } - err = c.addManifestGroup(h, cs) + err = addManifestGroup(c.ContractWallet, h, cs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } @@ -116,17 +106,17 @@ func (c *initializeContext) deployNNS(method string) error { return fmt.Errorf("failed to create deploy tx for %s: %w", morphUtil.NNSContract, err) } - if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { + if err := c.MultiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { return fmt.Errorf("can't send deploy transaction: %w", err) } - return c.awaitTx() + return c.AwaitTx() } -func (c *initializeContext) updateContracts() error { - alphaCs := c.getContract(morphUtil.AlphabetContract) +func updateContractsInternal(c *InitializeContext) error { + alphaCs := c.GetContract(morphUtil.AlphabetContract) - nnsCs, err := c.nnsContractState() + nnsCs, err := c.NNSContractState() if err != nil { return err } @@ -147,19 +137,19 @@ func (c *initializeContext) updateContracts() error { emit.Bytes(w.BinWriter, alphaCs.RawNEF) emit.Opcodes(w.BinWriter, opcode.STSFLD0) - keysParam, err := c.deployAlphabetAccounts(nnsHash, w, alphaCs) + keysParam, err := deployAlphabetAccounts(c, nnsHash, w, alphaCs) if err != nil { return err } w.Reset() - if err = c.deployOrUpdateContracts(w, nnsHash, keysParam); err != nil { + if err = deployOrUpdateContracts(c, w, nnsHash, keysParam); err != nil { return err } groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey() - _, _, err = c.emitUpdateNNSGroupScript(w, nnsHash, groupKey) + _, _, err = c.EmitUpdateNNSGroupScript(w, nnsHash, groupKey) if err != nil { return err } @@ -170,20 +160,20 @@ func (c *initializeContext) updateContracts() error { emit.Opcodes(w.BinWriter, opcode.PACK) emit.AppCallNoArgs(w.BinWriter, nnsHash, "setPrice", callflag.All) - if err := c.sendCommitteeTx(w.Bytes(), false); err != nil { + if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { return err } - return c.awaitTx() + return c.AwaitTx() } -func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error { +func deployOrUpdateContracts(c *InitializeContext, w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error { emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1}) emit.AppCall(w.BinWriter, nnsHash, "getPrice", callflag.All) emit.Opcodes(w.BinWriter, opcode.STSFLD0) emit.AppCall(w.BinWriter, nnsHash, "setPrice", callflag.All, 1) for _, ctrName := range contractList { - cs := c.getContract(ctrName) + cs := c.GetContract(ctrName) method := updateMethodName ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName)) @@ -196,7 +186,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash } } - err = c.addManifestGroup(ctrHash, cs) + err = addManifestGroup(c.ContractWallet, ctrHash, cs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } @@ -206,7 +196,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash invokeHash = ctrHash } - args, err := c.getContractDeployData(ctrName, keysParam, updateMethodName) + args, err := getContractDeployData(c, ctrName, keysParam, updateMethodName) if err != nil { return fmt.Errorf("%s: getting update params: %v", ctrName, err) } @@ -223,9 +213,9 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash w.WriteBytes(res.Script) if method == deployMethodName { - // same actions are done in initializeContext.setNNS, can be unified + // same actions are done in InitializeContext.setNNS, can be unified domain := ctrName + ".frostfs" - script, ok, err := c.nnsRegisterDomainScript(nnsHash, cs.Hash, domain) + script, ok, err := c.NNSRegisterDomainScript(nnsHash, cs.Hash, domain) if err != nil { return err } @@ -243,7 +233,7 @@ func (c *initializeContext) deployOrUpdateContracts(w *io2.BufBinWriter, nnsHash return nil } -func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *contractState) ([]any, error) { +func deployAlphabetAccounts(c *InitializeContext, nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *morphUtil.ContractState) ([]any, error) { var keysParam []any baseGroups := alphaCs.Manifest.Groups @@ -257,11 +247,11 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2. keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes()) - params := c.getAlphabetDeployItems(i, len(c.Wallets)) + params := c.GetAlphabetDeployItems(i, len(c.Wallets)) emit.Array(w.BinWriter, params...) alphaCs.Manifest.Groups = baseGroups - err = c.addManifestGroup(ctrHash, alphaCs) + err = addManifestGroup(c.ContractWallet, ctrHash, alphaCs) if err != nil { return nil, fmt.Errorf("can't sign manifest group: %v", err) } @@ -272,7 +262,7 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2. emit.Opcodes(w.BinWriter, opcode.PACK) emit.AppCallNoArgs(w.BinWriter, ctrHash, updateMethodName, callflag.All) } - if err := c.sendCommitteeTx(w.Bytes(), false); err != nil { + if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { if !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { return nil, err } @@ -282,8 +272,8 @@ func (c *initializeContext) deployAlphabetAccounts(nnsHash util.Uint160, w *io2. return keysParam, nil } -func (c *initializeContext) deployContracts() error { - alphaCs := c.getContract(morphUtil.AlphabetContract) +func deployContracts(c *InitializeContext) error { + alphaCs := c.GetContract(morphUtil.AlphabetContract) var keysParam []any @@ -292,19 +282,19 @@ func (c *initializeContext) deployContracts() error { // alphabet contracts should be deployed by individual nodes to get different hashes. for i, acc := range c.Accounts { ctrHash := state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name) - if c.isUpdated(ctrHash, alphaCs) { + if c.IsUpdated(ctrHash, alphaCs) { c.Command.Printf("Alphabet contract #%d is already deployed.\n", i) continue } alphaCs.Manifest.Groups = baseGroups - err := c.addManifestGroup(ctrHash, alphaCs) + err := addManifestGroup(c.ContractWallet, ctrHash, alphaCs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes()) - params := getContractDeployParameters(alphaCs, c.getAlphabetDeployItems(i, len(c.Wallets))) + params := getContractDeployParameters(alphaCs, c.GetAlphabetDeployItems(i, len(c.Wallets))) act, err := actor.NewSimple(c.Client, acc) if err != nil { @@ -320,20 +310,20 @@ func (c *initializeContext) deployContracts() error { } for _, ctrName := range contractList { - cs := c.getContract(ctrName) + cs := c.GetContract(ctrName) ctrHash := cs.Hash - if c.isUpdated(ctrHash, cs) { + if c.IsUpdated(ctrHash, cs) { c.Command.Printf("%s contract is already deployed.\n", ctrName) continue } - err := c.addManifestGroup(ctrHash, cs) + err := addManifestGroup(c.ContractWallet, ctrHash, cs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } - args, err := c.getContractDeployData(ctrName, keysParam, deployMethodName) + args, err := getContractDeployData(c, ctrName, keysParam, deployMethodName) if err != nil { return fmt.Errorf("%s: getting deploy params: %v", ctrName, err) } @@ -343,25 +333,25 @@ func (c *initializeContext) deployContracts() error { return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) } - if err := c.sendCommitteeTx(res.Script, false); err != nil { + if err := c.SendCommitteeTx(res.Script, false); err != nil { return err } } - return c.awaitTx() + return c.AwaitTx() } -func (c *initializeContext) isUpdated(ctrHash util.Uint160, cs *contractState) bool { +func (c *InitializeContext) IsUpdated(ctrHash util.Uint160, cs *morphUtil.ContractState) bool { r := management.NewReader(c.ReadOnlyInvoker) realCs, err := r.GetContract(ctrHash) return err == nil && realCs != nil && realCs.NEF.Checksum == cs.NEF.Checksum } -func (c *initializeContext) getContract(ctrName string) *contractState { +func (c *InitializeContext) GetContract(ctrName string) *morphUtil.ContractState { return c.Contracts[ctrName] } -func (c *initializeContext) readContracts(names []string) error { +func (c *InitializeContext) readContracts(names []string) error { var ( fi os.FileInfo err error @@ -401,7 +391,7 @@ func (c *initializeContext) readContracts(names []string) error { return err } for _, name := range names { - if err := m[name].parse(); err != nil { + if err := m[name].Parse(); err != nil { return err } c.Contracts[name] = m[name] @@ -418,7 +408,7 @@ func (c *initializeContext) readContracts(names []string) error { return nil } -func readContract(ctrPath, ctrName string) (*contractState, error) { +func readContract(ctrPath, ctrName string) (*morphUtil.ContractState, error) { rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef")) if err != nil { return nil, fmt.Errorf("can't read NEF file for %s contract: %w", ctrName, err) @@ -428,34 +418,18 @@ func readContract(ctrPath, ctrName string) (*contractState, error) { return nil, fmt.Errorf("can't read manifest file for %s contract: %w", ctrName, err) } - cs := &contractState{ + cs := &morphUtil.ContractState{ RawNEF: rawNef, RawManifest: rawManif, } - return cs, cs.parse() + return cs, cs.Parse() } -func (cs *contractState) parse() error { - nf, err := nef.FileFromBytes(cs.RawNEF) - if err != nil { - return fmt.Errorf("can't parse NEF file: %w", err) - } - - m := new(manifest.Manifest) - if err := json.Unmarshal(cs.RawManifest, m); err != nil { - return fmt.Errorf("can't parse manifest file: %w", err) - } - - cs.NEF = &nf - cs.Manifest = m - return nil -} - -func readContractsFromArchive(file io.Reader, names []string) (map[string]*contractState, error) { - m := make(map[string]*contractState, len(names)) +func readContractsFromArchive(file io.Reader, names []string) (map[string]*morphUtil.ContractState, error) { + m := make(map[string]*morphUtil.ContractState, len(names)) for i := range names { - m[names[i]] = new(contractState) + m[names[i]] = new(morphUtil.ContractState) } gr, err := gzip.NewReader(file) @@ -503,11 +477,11 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*contr return m, nil } -func getContractDeployParameters(cs *contractState, deployData []any) []any { +func getContractDeployParameters(cs *morphUtil.ContractState, deployData []any) []any { return []any{cs.RawNEF, cs.RawManifest, deployData} } -func (c *initializeContext) getContractDeployData(ctrName string, keysParam []any, method string) ([]any, error) { +func getContractDeployData(c *InitializeContext, ctrName string, keysParam []any, method string) ([]any, error) { items := make([]any, 0, 6) switch ctrName { @@ -544,7 +518,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an err error ) if method == updateMethodName { - h, found, err = c.getFrostfsIDAdminFromContract() + h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker) } if method != updateMethodName || err == nil && !found { h, found, err = getFrostfsIDAdmin(viper.GetViper()) @@ -561,7 +535,7 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an case morphUtil.NetmapContract: md := getDefaultNetmapContractConfigMap() if method == updateMethodName { - if err := c.mergeNetmapConfig(md); err != nil { + if err := mergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil { return nil, err } } @@ -586,17 +560,17 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []an return items, nil } -func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool, error) { - r := management.NewReader(c.ReadOnlyInvoker) +func getFrostfsIDAdminFromContract(roInvoker *invoker.Invoker) (util.Uint160, bool, error) { + r := management.NewReader(roInvoker) cs, err := r.GetContractByID(1) if err != nil { return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) } - fidHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract)) + fidHash, err := morphUtil.NNSResolveHash(roInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract)) if err != nil { return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) } - item, err := unwrap.Item(c.ReadOnlyInvoker.Call(fidHash, "getAdmin")) + item, err := unwrap.Item(roInvoker.Call(fidHash, "getAdmin")) if err != nil { return util.Uint160{}, false, fmt.Errorf("getAdmin: %w", err) } @@ -615,25 +589,25 @@ func (c *initializeContext) getFrostfsIDAdminFromContract() (util.Uint160, bool, return h, true, nil } -func (c *initializeContext) getNetConfigFromNetmapContract() ([]stackitem.Item, error) { - r := management.NewReader(c.ReadOnlyInvoker) +func getNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Item, error) { + r := management.NewReader(roInvoker) cs, err := r.GetContractByID(1) if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } - nmHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract)) + nmHash, err := morphUtil.NNSResolveHash(roInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract)) if err != nil { return nil, fmt.Errorf("can't get netmap contract hash: %w", err) } - arr, err := unwrap.Array(c.ReadOnlyInvoker.Call(nmHash, "listConfig")) + arr, err := unwrap.Array(roInvoker.Call(nmHash, "listConfig")) if err != nil { return nil, fmt.Errorf("can't fetch list of network config keys from the netmap contract") } return arr, err } -func (c *initializeContext) mergeNetmapConfig(md map[string]any) error { - arr, err := c.getNetConfigFromNetmapContract() +func mergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error { + arr, err := getNetConfigFromNetmapContract(roInvoker) if err != nil { return err } @@ -652,7 +626,7 @@ func (c *initializeContext) mergeNetmapConfig(md map[string]any) error { return nil } -func (c *initializeContext) getAlphabetDeployItems(i, n int) []any { +func (c *InitializeContext) GetAlphabetDeployItems(i, n int) []any { items := make([]any, 5) items[0] = c.Contracts[morphUtil.NetmapContract].Hash items[1] = c.Contracts[morphUtil.ProxyContract].Hash diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 7b0bc81976..2a80077c1e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -14,16 +14,11 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" - nnsClient "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) @@ -31,14 +26,14 @@ const defaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second const frostfsOpsEmail = "ops@frostfs.info" -func (c *initializeContext) setNNS() error { +func setNNS(c *InitializeContext) error { r := management.NewReader(c.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { return err } - ok, err := c.nnsRootRegistered(nnsCs.Hash, "frostfs") + ok, err := c.NNSRootRegistered(nnsCs.Hash, "frostfs") if err != nil { return err } else if !ok { @@ -47,48 +42,48 @@ func (c *initializeContext) setNNS() error { "frostfs", c.CommitteeAcc.Contract.ScriptHash(), frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) - if err := c.sendCommitteeTx(bw.Bytes(), true); err != nil { + if err := c.SendCommitteeTx(bw.Bytes(), true); err != nil { return fmt.Errorf("can't add domain root to NNS: %w", err) } - if err := c.awaitTx(); err != nil { + if err := c.AwaitTx(); err != nil { return err } } - alphaCs := c.getContract(morphUtil.AlphabetContract) + alphaCs := c.GetContract(morphUtil.AlphabetContract) for i, acc := range c.Accounts { alphaCs.Hash = state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name) domain := getAlphabetNNSDomain(i) - if err := c.nnsRegisterDomain(nnsCs.Hash, alphaCs.Hash, domain); err != nil { + if err := nnsRegisterDomain(c, nnsCs.Hash, alphaCs.Hash, domain); err != nil { return err } c.Command.Printf("NNS: Set %s -> %s\n", domain, alphaCs.Hash.StringLE()) } for _, ctrName := range contractList { - cs := c.getContract(ctrName) + cs := c.GetContract(ctrName) domain := ctrName + ".frostfs" - if err := c.nnsRegisterDomain(nnsCs.Hash, cs.Hash, domain); err != nil { + if err := nnsRegisterDomain(c, nnsCs.Hash, cs.Hash, domain); err != nil { return err } c.Command.Printf("NNS: Set %s -> %s\n", domain, cs.Hash.StringLE()) } groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey() - err = c.updateNNSGroup(nnsCs.Hash, groupKey) + err = updateNNSGroup(c, nnsCs.Hash, groupKey) if err != nil { return err } c.Command.Printf("NNS: Set %s -> %s\n", morphClient.NNSGroupKeyName, hex.EncodeToString(groupKey.Bytes())) - return c.awaitTx() + return c.AwaitTx() } -func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.PublicKey) error { +func updateNNSGroup(c *InitializeContext, nnsHash util.Uint160, pub *keys.PublicKey) error { bw := io.NewBufBinWriter() - keyAlreadyAdded, domainRegCodeEmitted, err := c.emitUpdateNNSGroupScript(bw, nnsHash, pub) + keyAlreadyAdded, domainRegCodeEmitted, err := c.EmitUpdateNNSGroupScript(bw, nnsHash, pub) if keyAlreadyAdded || err != nil { return err } @@ -101,20 +96,20 @@ func (c *initializeContext) updateNNSGroup(nnsHash util.Uint160, pub *keys.Publi script = w.Bytes() } - return c.sendCommitteeTx(script, true) + return c.SendCommitteeTx(script, true) } -// emitUpdateNNSGroupScript emits script for updating group key stored in NNS. +// EmitUpdateNNSGroupScript emits script for updating group key stored in NNS. // First return value is true iff the key is already there and nothing should be done. // Second return value is true iff a domain registration code was emitted. -func (c *initializeContext) emitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (bool, bool, error) { - isAvail, err := nnsIsAvailable(c.Client, nnsHash, morphClient.NNSGroupKeyName) +func (c *InitializeContext) EmitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (bool, bool, error) { + isAvail, err := morphUtil.NNSIsAvailable(c.Client, nnsHash, morphClient.NNSGroupKeyName) if err != nil { return false, false, err } if !isAvail { - currentPub, err := nnsResolveKey(c.ReadOnlyInvoker, nnsHash, morphClient.NNSGroupKeyName) + currentPub, err := morphUtil.NNSResolveKey(c.ReadOnlyInvoker, nnsHash, morphClient.NNSGroupKeyName) if err != nil { return false, false, err } @@ -165,8 +160,8 @@ func wrapRegisterScriptWithPrice(w *io.BufBinWriter, nnsHash util.Uint160, s []b } } -func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, bool, error) { - ok, err := nnsIsAvailable(c.Client, nnsHash, domain) +func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, bool, error) { + ok, err := morphUtil.NNSIsAvailable(c.Client, nnsHash, domain) if err != nil { return nil, false, err } @@ -191,8 +186,8 @@ func (c *initializeContext) nnsRegisterDomainScript(nnsHash, expectedHash util.U return nil, s == expectedHash, nil } -func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160, domain string) error { - script, ok, err := c.nnsRegisterDomainScript(nnsHash, expectedHash, domain) +func nnsRegisterDomain(c *InitializeContext, nnsHash, expectedHash util.Uint160, domain string) error { + script, ok, err := c.NNSRegisterDomainScript(nnsHash, expectedHash, domain) if ok || err != nil { return err } @@ -206,10 +201,10 @@ func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160 domain, int64(nns.TXT), expectedHash.StringLE()) emit.AppCall(w.BinWriter, nnsHash, "addRecord", callflag.All, domain, int64(nns.TXT), address.Uint160ToString(expectedHash)) - return c.sendCommitteeTx(w.Bytes(), true) + return c.SendCommitteeTx(w.Bytes(), true) } -func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160, zone string) (bool, error) { +func (c *InitializeContext) NNSRootRegistered(nnsHash util.Uint160, zone string) (bool, error) { res, err := c.CommitteeAct.Call(nnsHash, "isAvailable", "name."+zone) if err != nil { return false, err @@ -219,43 +214,3 @@ func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160, zone string) } var errMissingNNSRecord = errors.New("missing NNS record") - -func nnsResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) { - res, err := morphUtil.NNSResolve(inv, nnsHash, domain) - if err != nil { - return nil, err - } - if _, ok := res.Value().(stackitem.Null); ok { - return nil, errors.New("NNS record is missing") - } - arr, ok := res.Value().([]stackitem.Item) - if !ok { - return nil, errors.New("API of the NNS contract method `resolve` has changed") - } - for i := range arr { - var bs []byte - bs, err = arr[i].TryBytes() - if err != nil { - continue - } - - return keys.NewPublicKeyFromString(string(bs)) - } - return nil, errors.New("no valid keys are found") -} - -func nnsIsAvailable(c morphUtil.Client, nnsHash util.Uint160, name string) (bool, error) { - switch c.(type) { - case *rpcclient.Client: - inv := invoker.New(c, nil) - reader := nnsClient.NewReader(inv, nnsHash) - return reader.IsAvailable(name) - default: - b, err := unwrap.Bool(morphUtil.InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil)) - if err != nil { - return false, fmt.Errorf("`isAvailable`: invalid response: %w", err) - } - - return b, nil - } -} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go index 04afd7c77c..9d3bcff09e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go @@ -28,8 +28,8 @@ const ( registerBatchSize = transaction.MaxAttributes - 1 ) -func (c *initializeContext) registerCandidateRange(start, end int) error { - regPrice, err := c.getCandidateRegisterPrice() +func registerCandidateRange(c *InitializeContext, start, end int) error { + regPrice, err := getCandidateRegisterPrice(c) if err != nil { return fmt.Errorf("can't fetch registration price: %w", err) } @@ -46,7 +46,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error { } signers := []actor.SignerAccount{{ - Signer: c.getSigner(false, c.CommitteeAcc), + Signer: c.GetSigner(false, c.CommitteeAcc), Account: c.CommitteeAcc, }} for _, acc := range c.Accounts[start:end] { @@ -68,7 +68,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error { if err != nil { return fmt.Errorf("can't create tx: %w", err) } - if err := c.multiSign(tx, morphUtil.CommitteeAccountName); err != nil { + if err := c.MultiSign(tx, morphUtil.CommitteeAccountName); err != nil { return fmt.Errorf("can't sign a transaction: %w", err) } @@ -82,7 +82,7 @@ func (c *initializeContext) registerCandidateRange(start, end int) error { return c.SendTx(tx, c.Command, true) } -func (c *initializeContext) registerCandidates() error { +func registerCandidates(c *InitializeContext) error { cc, err := unwrap.Array(c.ReadOnlyInvoker.Call(neo.Hash, "getCandidates")) if err != nil { return fmt.Errorf("`getCandidates`: %w", err) @@ -107,7 +107,7 @@ func (c *initializeContext) registerCandidates() error { if have >= end { continue } - if err := c.registerCandidateRange(start, end); err != nil { + if err := registerCandidateRange(c, start, end); err != nil { return fmt.Errorf("registering candidates %d..%d: %q", start, end-1, err) } } @@ -115,15 +115,15 @@ func (c *initializeContext) registerCandidates() error { return nil } -func (c *initializeContext) transferNEOToAlphabetContracts() error { +func transferNEOToAlphabetContracts(c *InitializeContext) error { neoHash := neo.Hash - ok, err := c.transferNEOFinished(neoHash) + ok, err := transferNEOFinished(c, neoHash) if ok || err != nil { return err } - cs := c.getContract(morphUtil.AlphabetContract) + cs := c.GetContract(morphUtil.AlphabetContract) amount := initialAlphabetNEOAmount / len(c.Wallets) bw := io.NewBufBinWriter() @@ -134,14 +134,14 @@ func (c *initializeContext) transferNEOToAlphabetContracts() error { emit.Opcodes(bw.BinWriter, opcode.ASSERT) } - if err := c.sendCommitteeTx(bw.Bytes(), false); err != nil { + if err := c.SendCommitteeTx(bw.Bytes(), false); err != nil { return err } - return c.awaitTx() + return c.AwaitTx() } -func (c *initializeContext) transferNEOFinished(neoHash util.Uint160) (bool, error) { +func transferNEOFinished(c *InitializeContext, neoHash util.Uint160) (bool, error) { r := nep17.NewReader(c.ReadOnlyInvoker, neoHash) bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash()) return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err @@ -149,7 +149,7 @@ func (c *initializeContext) transferNEOFinished(neoHash util.Uint160) (bool, err var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response") -func (c *initializeContext) getCandidateRegisterPrice() (int64, error) { +func getCandidateRegisterPrice(c *InitializeContext) (int64, error) { switch c.Client.(type) { case *rpcclient.Client: inv := invoker.New(c.Client, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go b/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go index aed35e2308..35750d6029 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go @@ -9,8 +9,8 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/emit" ) -func (c *initializeContext) setNotaryAndAlphabetNodes() error { - if ok, err := c.setRolesFinished(); ok || err != nil { +func setNotaryAndAlphabetNodes(c *InitializeContext) error { + if ok, err := setRolesFinished(c); ok || err != nil { if err == nil { c.Command.Println("Stage 2: already performed.") } @@ -28,14 +28,14 @@ func (c *initializeContext) setNotaryAndAlphabetNodes() error { emit.AppCall(w.BinWriter, rolemgmt.Hash, "designateAsRole", callflag.States|callflag.AllowNotify, int64(noderoles.NeoFSAlphabet), pubs) - if err := c.sendCommitteeTx(w.Bytes(), false); err != nil { + if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { return err } - return c.awaitTx() + return c.AwaitTx() } -func (c *initializeContext) setRolesFinished() (bool, error) { +func setRolesFinished(c *InitializeContext) (bool, error) { height, err := c.Client.GetBlockCount() if err != nil { return false, err diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index a24d3a6f66..634b478927 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -28,8 +28,8 @@ const ( initialProxyGASAmount = 50_000 * native.GASFactor ) -func (c *initializeContext) transferFunds() error { - ok, err := c.transferFundsFinished() +func transferFunds(c *InitializeContext) error { + ok, err := transferFundsFinished(c) if ok || err != nil { if err == nil { c.Command.Println("Stage 1: already performed.") @@ -68,14 +68,14 @@ func (c *initializeContext) transferFunds() error { return fmt.Errorf("can't create transfer transaction: %w", err) } - if err := c.multiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil { + if err := c.MultiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil { return fmt.Errorf("can't send transfer transaction: %w", err) } - return c.awaitTx() + return c.AwaitTx() } -func (c *initializeContext) transferFundsFinished() (bool, error) { +func transferFundsFinished(c *InitializeContext) (bool, error) { acc := c.Accounts[0] r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) @@ -83,15 +83,15 @@ func (c *initializeContext) transferFundsFinished() (bool, error) { return res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) == 1, err } -func (c *initializeContext) multiSignAndSend(tx *transaction.Transaction, accType string) error { - if err := c.multiSign(tx, accType); err != nil { +func (c *InitializeContext) MultiSignAndSend(tx *transaction.Transaction, accType string) error { + if err := c.MultiSign(tx, accType); err != nil { return err } return c.SendTx(tx, c.Command, false) } -func (c *initializeContext) multiSign(tx *transaction.Transaction, accType string) error { +func (c *InitializeContext) MultiSign(tx *transaction.Transaction, accType string) error { version, err := c.Client.GetVersion() if err != nil { // error appears only if client @@ -143,8 +143,8 @@ func (c *initializeContext) multiSign(tx *transaction.Transaction, accType strin return fmt.Errorf("%s account was not found among transaction signers", accType) } -func (c *initializeContext) transferGASToProxy() error { - proxyCs := c.getContract(morphUtil.ProxyContract) +func transferGASToProxy(c *InitializeContext) error { + proxyCs := c.GetContract(morphUtil.ProxyContract) r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) bal, err := r.BalanceOf(proxyCs.Hash) @@ -161,11 +161,11 @@ func (c *initializeContext) transferGASToProxy() error { return err } - if err := c.multiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { + if err := c.MultiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { return err } - return c.awaitTx() + return c.AwaitTx() } type transferTarget struct { diff --git a/cmd/frostfs-adm/internal/modules/morph/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy.go index ba73d132ce..97cc76ab75 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy.go @@ -25,7 +25,7 @@ const ( ) func setPolicyCmd(cmd *cobra.Command, args []string) error { - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -51,11 +51,11 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error { emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value)) } - if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil { + if err := wCtx.SendCommitteeTx(bw.Bytes(), false); err != nil { return err } - return wCtx.awaitTx() + return wCtx.AwaitTx() } func dumpPolicyCmd(cmd *cobra.Command, _ []string) error { diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy.go index 9e973b0de8..4bd461b975 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy.go @@ -36,7 +36,7 @@ func removeProxyAccount(cmd *cobra.Command, _ []string) { } func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error { - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -55,11 +55,11 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error bw := io.NewBufBinWriter() emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr) - if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil { + if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil { return err } - if err = wCtx.awaitTx(); err != nil { + if err = wCtx.AwaitTx(); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/remove_node.go b/cmd/frostfs-adm/internal/modules/morph/remove_node.go index 678bcc7eee..42464e7317 100644 --- a/cmd/frostfs-adm/internal/modules/morph/remove_node.go +++ b/cmd/frostfs-adm/internal/modules/morph/remove_node.go @@ -29,11 +29,11 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { } } - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't initialize context: %w", err) } - defer wCtx.close() + defer wCtx.Close() r := management.NewReader(wCtx.ReadOnlyInvoker) cs, err := r.GetContractByID(1) @@ -56,9 +56,9 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { return err } - if err := wCtx.sendConsensusTx(bw.Bytes()); err != nil { + if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil { return err } - return wCtx.awaitTx() + return wCtx.AwaitTx() } diff --git a/cmd/frostfs-adm/internal/modules/morph/update.go b/cmd/frostfs-adm/internal/modules/morph/update.go index 90b6d6558a..b6fcbb5b72 100644 --- a/cmd/frostfs-adm/internal/modules/morph/update.go +++ b/cmd/frostfs-adm/internal/modules/morph/update.go @@ -8,14 +8,14 @@ import ( ) func updateContracts(cmd *cobra.Command, _ []string) error { - wCtx, err := newInitializeContext(cmd, viper.GetViper()) + wCtx, err := NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("initialization error: %w", err) } - if err := wCtx.deployNNS(updateMethodName); err != nil { + if err := deployNNS(wCtx, updateMethodName); err != nil { return err } - return wCtx.updateContracts() + return updateContractsInternal(wCtx) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go index 923061a099..725181ec71 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go @@ -7,8 +7,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + nns2 "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" @@ -144,3 +147,43 @@ func NNSResolveHash(inv *invoker.Invoker, nnsHash util.Uint160, domain string) ( func DomainOf(contract string) string { return contract + ".frostfs" } + +func NNSResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (*keys.PublicKey, error) { + res, err := NNSResolve(inv, nnsHash, domain) + if err != nil { + return nil, err + } + if _, ok := res.Value().(stackitem.Null); ok { + return nil, errors.New("NNS record is missing") + } + arr, ok := res.Value().([]stackitem.Item) + if !ok { + return nil, errors.New("API of the NNS contract method `resolve` has changed") + } + for i := range arr { + var bs []byte + bs, err = arr[i].TryBytes() + if err != nil { + continue + } + + return keys.NewPublicKeyFromString(string(bs)) + } + return nil, errors.New("no valid keys are found") +} + +func NNSIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) { + switch c.(type) { + case *rpcclient.Client: + inv := invoker.New(c, nil) + reader := nns2.NewReader(inv, nnsHash) + return reader.IsAvailable(name) + default: + b, err := unwrap.Bool(InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil)) + if err != nil { + return false, fmt.Errorf("`isAvailable`: invalid response: %w", err) + } + + return b, nil + } +} diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go new file mode 100644 index 0000000000..be5dcf2db5 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go @@ -0,0 +1,34 @@ +package util + +import ( + "encoding/json" + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +func (cs *ContractState) Parse() error { + nf, err := nef.FileFromBytes(cs.RawNEF) + if err != nil { + return fmt.Errorf("can't parse NEF file: %w", err) + } + + m := new(manifest.Manifest) + if err := json.Unmarshal(cs.RawManifest, m); err != nil { + return fmt.Errorf("can't parse manifest file: %w", err) + } + + cs.NEF = &nf + cs.Manifest = m + return nil +} + +type ContractState struct { + NEF *nef.File + RawNEF []byte + Manifest *manifest.Manifest + RawManifest []byte + Hash util.Uint160 +} From 77694a2f3b4aebf1fd8b19ecd949b96c1608a6f6 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 15:21:51 +0300 Subject: [PATCH 0351/1413] [#932] adm: Move `InitializeContext` to `util` package Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/config.go | 2 +- .../internal/modules/morph/container.go | 8 +- .../internal/modules/morph/deploy.go | 10 +- .../internal/modules/morph/dump_hashes.go | 2 +- .../internal/modules/morph/epoch.go | 4 +- .../internal/modules/morph/frostfsid.go | 4 +- .../internal/modules/morph/generate.go | 4 +- .../internal/modules/morph/generate_test.go | 2 +- .../internal/modules/morph/group.go | 67 --- .../internal/modules/morph/initialize.go | 323 +---------- .../modules/morph/initialize_deploy.go | 206 +------ .../internal/modules/morph/initialize_nns.go | 85 +-- .../modules/morph/initialize_register.go | 10 +- .../modules/morph/initialize_roles.go | 4 +- .../internal/modules/morph/initialize_test.go | 16 +- .../modules/morph/initialize_transfer.go | 67 +-- .../internal/modules/morph/netmap_util.go | 5 +- .../internal/modules/morph/notary.go | 2 +- .../internal/modules/morph/policy.go | 2 +- .../internal/modules/morph/proxy.go | 2 +- .../internal/modules/morph/remove_node.go | 2 +- .../internal/modules/morph/root.go | 47 +- .../internal/modules/morph/update.go | 3 +- .../internal/modules/morph/util/const.go | 34 ++ .../modules/morph/{ => util}/download.go | 2 +- .../internal/modules/morph/util/initialize.go | 21 + .../modules/morph/util/initialize_ctx.go | 521 +++++++++++++++++- .../internal/modules/morph/util/util.go | 73 +++ .../internal/modules/morph/util/wallet.go | 75 +++ 29 files changed, 809 insertions(+), 794 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => util}/download.go (99%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/wallet.go diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index 2d0f12afe2..2cff322d18 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -85,7 +85,7 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { return errors.New("empty config pairs") } - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't initialize context: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container.go index ab32dcabbe..b18fa79ed3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container.go @@ -193,7 +193,7 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid filename: %w", err) } - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return err } @@ -222,7 +222,7 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return wCtx.AwaitTx() } -func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *InitializeContext, ch util.Uint160) error { +func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *morphUtil.InitializeContext, ch util.Uint160) error { bw := io.NewBufBinWriter() for _, cnt := range containers { hv := hash.Sha256(cnt.Value) @@ -262,7 +262,7 @@ func putContainer(bw *io.BufBinWriter, ch util.Uint160, cnt Container) { } } -func isContainerRestored(cmd *cobra.Command, wCtx *InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { +func isContainerRestored(cmd *cobra.Command, wCtx *morphUtil.InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { emit.AppCall(bw.BinWriter, containerHash, "get", callflag.All, hashValue.BytesBE()) res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil) if err != nil { @@ -300,7 +300,7 @@ func parseContainers(filename string) ([]Container, error) { return containers, nil } -func fetchContainerContractHash(wCtx *InitializeContext) (util.Uint160, error) { +func fetchContainerContractHash(wCtx *morphUtil.InitializeContext) (util.Uint160, error) { r := management.NewReader(wCtx.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index 7f11362e08..e6fdbbcf73 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -60,7 +60,7 @@ func init() { func deployContractCmd(cmd *cobra.Command, args []string) error { v := viper.GetViper() - c, err := NewInitializeContext(cmd, v) + c, err := util.NewInitializeContext(cmd, v) if err != nil { return fmt.Errorf("initialization error: %w", err) } @@ -72,7 +72,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { return err } - cs, err := readContract(ctrPath, ctrName) + cs, err := util.ReadContract(ctrPath, ctrName) if err != nil { return err } @@ -129,7 +129,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { return c.AwaitTx() } -func registerNNS(nnsCs *state.Contract, c *InitializeContext, zone string, domain string, cs *util.ContractState, writer *io.BufBinWriter) error { +func registerNNS(nnsCs *state.Contract, c *util.InitializeContext, zone string, domain string, cs *util.ContractState, writer *io.BufBinWriter) error { bw := io.NewBufBinWriter() emit.Instruction(bw.BinWriter, opcode.INITSSLOT, []byte{1}) emit.AppCall(bw.BinWriter, nnsCs.Hash, "getPrice", callflag.All) @@ -147,12 +147,12 @@ func registerNNS(nnsCs *state.Contract, c *InitializeContext, zone string, domai emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, zone, c.CommitteeAcc.Contract.ScriptHash(), - frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + util.FrostfsOpsEmail, int64(3600), int64(600), int64(util.DefaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, domain, c.CommitteeAcc.Contract.ScriptHash(), - frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + util.FrostfsOpsEmail, int64(3600), int64(600), int64(util.DefaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) } else { s, ok, err := c.NNSRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index 79b82ee471..d33311a8bf 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -86,7 +86,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { } } - for _, ctrName := range contractList { + for _, ctrName := range morphUtil.ContractList { bw.Reset() emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, morphUtil.DomainOf(ctrName), int64(nns.TXT)) diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index 0fc25d01df..851f757b05 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -17,7 +17,7 @@ import ( ) func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := util2.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -48,7 +48,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { return err } -func emitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160) error { +func emitNewEpochCall(bw *io.BufBinWriter, wCtx *util2.InitializeContext, nmHash util.Uint160) error { curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch")) if err != nil { return errors.New("can't fetch current epoch from the netmap contract") diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go index 4adde815d5..3e39c3019e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid.go @@ -416,11 +416,11 @@ type frostfsidClient struct { bw *io.BufBinWriter contractHash util.Uint160 roCli *frostfsidclient.Client // client can be used only for waiting tx, parsing and forming method params - wCtx *InitializeContext + wCtx *morphUtil.InitializeContext } func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return nil, fmt.Errorf("can't to initialize context: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate.go index f8e155f5b7..2258eb8324 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate.go @@ -45,7 +45,7 @@ func generateAlphabetCreds(cmd *cobra.Command, _ []string) error { return err } - _, err = initializeContractWallet(v, walletDir) + _, err = morphUtil.InitializeContractWallet(v, walletDir) if err != nil { return err } @@ -195,7 +195,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error return err } - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate_test.go index 207366ec70..e9e942d742 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate_test.go @@ -101,7 +101,7 @@ func TestGenerateAlphabet(t *testing.T) { wg.Wait() t.Run("check contract group wallet", func(t *testing.T) { - p := filepath.Join(walletDir, contractWalletFilename) + p := filepath.Join(walletDir, util.ContractWalletFilename) w, err := wallet.NewWalletFromFile(p) require.NoError(t, err, "contract wallet doesn't exist") require.Equal(t, 1, len(w.Accounts), "contract wallet must have 1 accout") diff --git a/cmd/frostfs-adm/internal/modules/morph/group.go b/cmd/frostfs-adm/internal/modules/morph/group.go index 0e6c511daa..655b8b2c36 100644 --- a/cmd/frostfs-adm/internal/modules/morph/group.go +++ b/cmd/frostfs-adm/internal/modules/morph/group.go @@ -2,80 +2,13 @@ package morph import ( "encoding/json" - "fmt" - "os" - "path/filepath" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" - "github.com/spf13/cobra" - "github.com/spf13/viper" ) -const ( - contractWalletFilename = "contract.json" - contractWalletPasswordKey = "contract" -) - -func initializeContractWallet(v *viper.Viper, walletDir string) (*wallet.Wallet, error) { - password, err := config.GetPassword(v, contractWalletPasswordKey) - if err != nil { - return nil, err - } - - w, err := wallet.NewWallet(filepath.Join(walletDir, contractWalletFilename)) - if err != nil { - return nil, err - } - - acc, err := wallet.NewAccount() - if err != nil { - return nil, err - } - - err = acc.Encrypt(password, keys.NEP2ScryptParams()) - if err != nil { - return nil, err - } - - w.AddAccount(acc) - if err := w.SavePretty(); err != nil { - return nil, err - } - - return w, nil -} - -func openContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (*wallet.Wallet, error) { - p := filepath.Join(walletDir, contractWalletFilename) - w, err := wallet.NewWalletFromFile(p) - if err != nil { - if !os.IsNotExist(err) { - return nil, fmt.Errorf("can't open wallet: %w", err) - } - - cmd.Printf("Contract group wallet is missing, initialize at %s\n", p) - return initializeContractWallet(v, walletDir) - } - - password, err := config.GetPassword(v, contractWalletPasswordKey) - if err != nil { - return nil, err - } - - for i := range w.Accounts { - if err := w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil { - return nil, fmt.Errorf("can't unlock wallet: %w", err) - } - } - - return w, nil -} - func addManifestGroup(cw *wallet.Wallet, h util.Uint160, cs *util2.ContractState) error { priv := cw.Accounts[0].PrivateKey() pub := priv.PublicKey() diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index 2057b4a24c..d4219294c8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -1,50 +1,15 @@ package morph import ( - "errors" "fmt" - "os" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" - morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" - "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" "github.com/spf13/viper" ) -type Cache struct { - NNSCs *state.Contract - GroupKey *keys.PublicKey -} - -type InitializeContext struct { - morphUtil.ClientContext - Cache - // CommitteeAcc is used for retrieving the committee address and the verification script. - CommitteeAcc *wallet.Account - // ConsensusAcc is used for retrieving the committee address and the verification script. - ConsensusAcc *wallet.Account - Wallets []*wallet.Wallet - // ContractWallet is a wallet for providing the contract group signature. - ContractWallet *wallet.Wallet - // Accounts contains simple signature accounts in the same order as in Wallets. - Accounts []*wallet.Account - Contracts map[string]*morphUtil.ContractState - Command *cobra.Command - ContractPath string - ContractURL string -} - func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { - initCtx, err := NewInitializeContext(cmd, viper.GetViper()) + initCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("initialization error: %w", err) } @@ -91,289 +56,3 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { cmd.Println("Stage 7: set addresses in NNS.") return setNNS(initCtx) } - -func (c *InitializeContext) Close() { - if local, ok := c.Client.(*morphUtil.LocalClient); ok { - err := local.Dump() - if err != nil { - c.Command.PrintErrf("Can't write dump: %v\n", err) - os.Exit(1) - } - } -} - -func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContext, error) { - walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag)) - wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) - if err != nil { - return nil, err - } - - needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init" - - var w *wallet.Wallet - w, err = getWallet(cmd, v, needContracts, walletDir) - if err != nil { - return nil, err - } - - c, err := createClient(cmd, v, wallets) - if err != nil { - return nil, err - } - - committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], morphUtil.CommitteeAccountName) - if err != nil { - return nil, fmt.Errorf("can't find committee account: %w", err) - } - - consensusAcc, err := morphUtil.GetWalletAccount(wallets[0], morphUtil.ConsensusAccountName) - if err != nil { - return nil, fmt.Errorf("can't find consensus account: %w", err) - } - - if err := validateInit(cmd); err != nil { - return nil, err - } - - ctrPath, err := getContractsPath(cmd, needContracts) - if err != nil { - return nil, err - } - - var ctrURL string - if needContracts { - ctrURL, _ = cmd.Flags().GetString(contractsURLFlag) - } - - if err := checkNotaryEnabled(c); err != nil { - return nil, err - } - - accounts, err := createWalletAccounts(wallets) - if err != nil { - return nil, err - } - - cliCtx, err := morphUtil.DefaultClientContext(c, committeeAcc) - if err != nil { - return nil, fmt.Errorf("client context: %w", err) - } - - initCtx := &InitializeContext{ - ClientContext: *cliCtx, - ConsensusAcc: consensusAcc, - CommitteeAcc: committeeAcc, - ContractWallet: w, - Wallets: wallets, - Accounts: accounts, - Command: cmd, - Contracts: make(map[string]*morphUtil.ContractState), - ContractPath: ctrPath, - ContractURL: ctrURL, - } - - if needContracts { - err := initCtx.readContracts(fullContractList) - if err != nil { - return nil, err - } - } - - return initCtx, nil -} - -func validateInit(cmd *cobra.Command) error { - if cmd.Name() != "init" { - return nil - } - if viper.GetInt64(epochDurationInitFlag) <= 0 { - return fmt.Errorf("epoch duration must be positive") - } - - if viper.GetInt64(maxObjectSizeInitFlag) <= 0 { - return fmt.Errorf("max object size must be positive") - } - - return nil -} - -func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet) (morphUtil.Client, error) { - var c morphUtil.Client - var err error - if ldf := cmd.Flags().Lookup(localDumpFlag); ldf != nil && ldf.Changed { - if cmd.Flags().Changed(morphUtil.EndpointFlag) { - return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", morphUtil.EndpointFlag, localDumpFlag) - } - c, err = morphUtil.NewLocalClient(cmd, v, wallets, ldf.Value.String()) - } else { - c, err = morphUtil.GetN3Client(v) - } - if err != nil { - return nil, fmt.Errorf("can't create N3 client: %w", err) - } - return c, nil -} - -func getWallet(cmd *cobra.Command, v *viper.Viper, needContracts bool, walletDir string) (*wallet.Wallet, error) { - if !needContracts { - return nil, nil - } - return openContractWallet(v, cmd, walletDir) -} - -func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) { - if !needContracts { - return "", nil - } - - ctrPath, err := cmd.Flags().GetString(contractsInitFlag) - if err != nil { - return "", fmt.Errorf("invalid contracts path: %w", err) - } - return ctrPath, nil -} - -func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { - accounts := make([]*wallet.Account, len(wallets)) - for i, w := range wallets { - acc, err := morphUtil.GetWalletAccount(w, morphUtil.SingleAccountName) - if err != nil { - return nil, fmt.Errorf("wallet %s is invalid (no single account): %w", w.Path(), err) - } - accounts[i] = acc - } - return accounts, nil -} - -func (c *InitializeContext) AwaitTx() error { - return c.ClientContext.AwaitTx(c.Command) -} - -func (c *InitializeContext) NNSContractState() (*state.Contract, error) { - if c.NNSCs != nil { - return c.NNSCs, nil - } - - r := management.NewReader(c.ReadOnlyInvoker) - cs, err := r.GetContractByID(1) - if err != nil { - return nil, err - } - - c.NNSCs = cs - return cs, nil -} - -func (c *InitializeContext) GetSigner(tryGroup bool, acc *wallet.Account) transaction.Signer { - if tryGroup && c.GroupKey != nil { - return transaction.Signer{ - Account: acc.Contract.ScriptHash(), - Scopes: transaction.CustomGroups, - AllowedGroups: keys.PublicKeys{c.GroupKey}, - } - } - - signer := transaction.Signer{ - Account: acc.Contract.ScriptHash(), - Scopes: transaction.Global, // Scope is important, as we have nested call to container contract. - } - - if !tryGroup { - return signer - } - - nnsCs, err := c.NNSContractState() - if err != nil { - return signer - } - - groupKey, err := morphUtil.NNSResolveKey(c.ReadOnlyInvoker, nnsCs.Hash, morphClient.NNSGroupKeyName) - if err == nil { - c.GroupKey = groupKey - - signer.Scopes = transaction.CustomGroups - signer.AllowedGroups = keys.PublicKeys{groupKey} - } - return signer -} - -// SendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC. -// If tryGroup is false, global scope is used for the signer (useful when -// working with native contracts). -func (c *InitializeContext) SendCommitteeTx(script []byte, tryGroup bool) error { - return c.sendMultiTx(script, tryGroup, false) -} - -// SendConsensusTx creates transaction from script, signs it by alphabet nodes and sends it to RPC. -// Not that because this is used only after the contracts were initialized and deployed, -// we always try to have a group scope. -func (c *InitializeContext) SendConsensusTx(script []byte) error { - return c.sendMultiTx(script, true, true) -} - -func (c *InitializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error { - var act *actor.Actor - var err error - - withConsensus = withConsensus && !c.ConsensusAcc.Contract.ScriptHash().Equals(c.CommitteeAcc.ScriptHash()) - if tryGroup { - // Even for consensus signatures we need the committee to pay. - signers := make([]actor.SignerAccount, 1, 2) - signers[0] = actor.SignerAccount{ - Signer: c.GetSigner(tryGroup, c.CommitteeAcc), - Account: c.CommitteeAcc, - } - if withConsensus { - signers = append(signers, actor.SignerAccount{ - Signer: c.GetSigner(tryGroup, c.ConsensusAcc), - Account: c.ConsensusAcc, - }) - } - act, err = actor.New(c.Client, signers) - } else { - if withConsensus { - panic("BUG: should never happen") - } - act, err = c.CommitteeAct, nil - } - if err != nil { - return fmt.Errorf("could not create actor: %w", err) - } - - tx, err := act.MakeUnsignedRun(script, []transaction.Attribute{{Type: transaction.HighPriority}}) - if err != nil { - return fmt.Errorf("could not perform test invocation: %w", err) - } - - if err := c.MultiSign(tx, morphUtil.CommitteeAccountName); err != nil { - return err - } - if withConsensus { - if err := c.MultiSign(tx, morphUtil.ConsensusAccountName); err != nil { - return err - } - } - - return c.SendTx(tx, c.Command, false) -} - -func checkNotaryEnabled(c morphUtil.Client) error { - ns, err := c.GetNativeContracts() - if err != nil { - return fmt.Errorf("can't get native contract hashes: %w", err) - } - - notaryEnabled := false - nativeHashes := make(map[string]util.Uint160, len(ns)) - for i := range ns { - if ns[i].Manifest.Name == nativenames.Notary { - notaryEnabled = true - } - nativeHashes[ns[i].Manifest.Name] = ns[i].Hash - } - if !notaryEnabled { - return errors.New("notary contract must be enabled") - } - return nil -} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index fd27eda6c3..322033abc4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -1,20 +1,14 @@ package morph import ( - "archive/tar" - "compress/gzip" "encoding/hex" "errors" "fmt" - "io" - "os" - "path/filepath" "strings" "git.frostfs.info/TrueCloudLab/frostfs-contract/common" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -35,41 +29,23 @@ import ( const frostfsIDAdminConfigKey = "frostfsid.admin" -var ( - contractList = []string{ - morphUtil.BalanceContract, - morphUtil.ContainerContract, - morphUtil.FrostfsIDContract, - morphUtil.NetmapContract, - morphUtil.PolicyContract, - morphUtil.ProxyContract, - } - - fullContractList = append([]string{ - morphUtil.FrostfsContract, - morphUtil.ProcessingContract, - morphUtil.NNSContract, - morphUtil.AlphabetContract, - }, contractList...) - - netmapConfigKeys = []string{ - netmap.EpochDurationConfig, - netmap.MaxObjectSizeConfig, - netmap.ContainerFeeConfig, - netmap.ContainerAliasFeeConfig, - netmap.IrCandidateFeeConfig, - netmap.WithdrawFeeConfig, - netmap.HomomorphicHashingDisabledKey, - netmap.MaintenanceModeAllowedConfig, - } -) +var netmapConfigKeys = []string{ + netmap.EpochDurationConfig, + netmap.MaxObjectSizeConfig, + netmap.ContainerFeeConfig, + netmap.ContainerAliasFeeConfig, + netmap.IrCandidateFeeConfig, + netmap.WithdrawFeeConfig, + netmap.HomomorphicHashingDisabledKey, + netmap.MaintenanceModeAllowedConfig, +} const ( updateMethodName = "update" deployMethodName = "deploy" ) -func deployNNS(c *InitializeContext, method string) error { +func deployNNS(c *morphUtil.InitializeContext, method string) error { cs := c.GetContract(morphUtil.NNSContract) h := cs.Hash @@ -113,7 +89,7 @@ func deployNNS(c *InitializeContext, method string) error { return c.AwaitTx() } -func updateContractsInternal(c *InitializeContext) error { +func updateContractsInternal(c *morphUtil.InitializeContext) error { alphaCs := c.GetContract(morphUtil.AlphabetContract) nnsCs, err := c.NNSContractState() @@ -166,13 +142,13 @@ func updateContractsInternal(c *InitializeContext) error { return c.AwaitTx() } -func deployOrUpdateContracts(c *InitializeContext, w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error { +func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error { emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1}) emit.AppCall(w.BinWriter, nnsHash, "getPrice", callflag.All) emit.Opcodes(w.BinWriter, opcode.STSFLD0) emit.AppCall(w.BinWriter, nnsHash, "setPrice", callflag.All, 1) - for _, ctrName := range contractList { + for _, ctrName := range morphUtil.ContractList { cs := c.GetContract(ctrName) method := updateMethodName @@ -233,7 +209,7 @@ func deployOrUpdateContracts(c *InitializeContext, w *io2.BufBinWriter, nnsHash return nil } -func deployAlphabetAccounts(c *InitializeContext, nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *morphUtil.ContractState) ([]any, error) { +func deployAlphabetAccounts(c *morphUtil.InitializeContext, nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *morphUtil.ContractState) ([]any, error) { var keysParam []any baseGroups := alphaCs.Manifest.Groups @@ -272,7 +248,7 @@ func deployAlphabetAccounts(c *InitializeContext, nnsHash util.Uint160, w *io2.B return keysParam, nil } -func deployContracts(c *InitializeContext) error { +func deployContracts(c *morphUtil.InitializeContext) error { alphaCs := c.GetContract(morphUtil.AlphabetContract) var keysParam []any @@ -309,7 +285,7 @@ func deployContracts(c *InitializeContext) error { c.SentTxs = append(c.SentTxs, morphUtil.HashVUBPair{Hash: txHash, Vub: vub}) } - for _, ctrName := range contractList { + for _, ctrName := range morphUtil.ContractList { cs := c.GetContract(ctrName) ctrHash := cs.Hash @@ -341,147 +317,11 @@ func deployContracts(c *InitializeContext) error { return c.AwaitTx() } -func (c *InitializeContext) IsUpdated(ctrHash util.Uint160, cs *morphUtil.ContractState) bool { - r := management.NewReader(c.ReadOnlyInvoker) - realCs, err := r.GetContract(ctrHash) - return err == nil && realCs != nil && realCs.NEF.Checksum == cs.NEF.Checksum -} - -func (c *InitializeContext) GetContract(ctrName string) *morphUtil.ContractState { - return c.Contracts[ctrName] -} - -func (c *InitializeContext) readContracts(names []string) error { - var ( - fi os.FileInfo - err error - ) - if c.ContractPath != "" { - fi, err = os.Stat(c.ContractPath) - if err != nil { - return fmt.Errorf("invalid contracts path: %w", err) - } - } - - if c.ContractPath != "" && fi.IsDir() { - for _, ctrName := range names { - cs, err := readContract(filepath.Join(c.ContractPath, ctrName), ctrName) - if err != nil { - return err - } - c.Contracts[ctrName] = cs - } - } else { - var r io.ReadCloser - if c.ContractPath != "" { - r, err = os.Open(c.ContractPath) - } else if c.ContractURL != "" { - r, err = downloadContracts(c.Command, c.ContractURL) - } else { - r, err = downloadContractsFromRepository(c.Command) - } - - if err != nil { - return fmt.Errorf("can't open contracts archive: %w", err) - } - defer r.Close() - - m, err := readContractsFromArchive(r, names) - if err != nil { - return err - } - for _, name := range names { - if err := m[name].Parse(); err != nil { - return err - } - c.Contracts[name] = m[name] - } - } - - for _, ctrName := range names { - if ctrName != morphUtil.AlphabetContract { - cs := c.Contracts[ctrName] - cs.Hash = state.CreateContractHash(c.CommitteeAcc.Contract.ScriptHash(), - cs.NEF.Checksum, cs.Manifest.Name) - } - } - return nil -} - -func readContract(ctrPath, ctrName string) (*morphUtil.ContractState, error) { - rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef")) - if err != nil { - return nil, fmt.Errorf("can't read NEF file for %s contract: %w", ctrName, err) - } - rawManif, err := os.ReadFile(filepath.Join(ctrPath, "config.json")) - if err != nil { - return nil, fmt.Errorf("can't read manifest file for %s contract: %w", ctrName, err) - } - - cs := &morphUtil.ContractState{ - RawNEF: rawNef, - RawManifest: rawManif, - } - - return cs, cs.Parse() -} - -func readContractsFromArchive(file io.Reader, names []string) (map[string]*morphUtil.ContractState, error) { - m := make(map[string]*morphUtil.ContractState, len(names)) - for i := range names { - m[names[i]] = new(morphUtil.ContractState) - } - - gr, err := gzip.NewReader(file) - if err != nil { - return nil, fmt.Errorf("contracts file must be tar.gz archive: %w", err) - } - - r := tar.NewReader(gr) - for h, err := r.Next(); ; h, err = r.Next() { - if err != nil { - break - } - - dir, _ := filepath.Split(h.Name) - ctrName := filepath.Base(dir) - - cs, ok := m[ctrName] - if !ok { - continue - } - - switch { - case strings.HasSuffix(h.Name, filepath.Join(ctrName, ctrName+"_contract.nef")): - cs.RawNEF, err = io.ReadAll(r) - if err != nil { - return nil, fmt.Errorf("can't read NEF file for %s contract: %w", ctrName, err) - } - case strings.HasSuffix(h.Name, "config.json"): - cs.RawManifest, err = io.ReadAll(r) - if err != nil { - return nil, fmt.Errorf("can't read manifest file for %s contract: %w", ctrName, err) - } - } - m[ctrName] = cs - } - - for ctrName, cs := range m { - if cs.RawNEF == nil { - return nil, fmt.Errorf("NEF for %s contract wasn't found", ctrName) - } - if cs.RawManifest == nil { - return nil, fmt.Errorf("manifest for %s contract wasn't found", ctrName) - } - } - return m, nil -} - func getContractDeployParameters(cs *morphUtil.ContractState, deployData []any) []any { return []any{cs.RawNEF, cs.RawManifest, deployData} } -func getContractDeployData(c *InitializeContext, ctrName string, keysParam []any, method string) ([]any, error) { +func getContractDeployData(c *morphUtil.InitializeContext, ctrName string, keysParam []any, method string) ([]any, error) { items := make([]any, 0, 6) switch ctrName { @@ -625,13 +465,3 @@ func mergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error { } return nil } - -func (c *InitializeContext) GetAlphabetDeployItems(i, n int) []any { - items := make([]any, 5) - items[0] = c.Contracts[morphUtil.NetmapContract].Hash - items[1] = c.Contracts[morphUtil.ProxyContract].Hash - items[2] = innerring.GlagoliticLetter(i).String() - items[3] = int64(i) - items[4] = int64(n) - return items -} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 2a80077c1e..8e5223098a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "strconv" - "time" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" @@ -19,14 +18,9 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) -const defaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second - -const frostfsOpsEmail = "ops@frostfs.info" - -func setNNS(c *InitializeContext) error { +func setNNS(c *morphUtil.InitializeContext) error { r := management.NewReader(c.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { @@ -40,7 +34,7 @@ func setNNS(c *InitializeContext) error { bw := io.NewBufBinWriter() emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, "frostfs", c.CommitteeAcc.Contract.ScriptHash(), - frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) + morphUtil.FrostfsOpsEmail, int64(3600), int64(600), int64(morphUtil.DefaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) if err := c.SendCommitteeTx(bw.Bytes(), true); err != nil { return fmt.Errorf("can't add domain root to NNS: %w", err) @@ -61,7 +55,7 @@ func setNNS(c *InitializeContext) error { c.Command.Printf("NNS: Set %s -> %s\n", domain, alphaCs.Hash.StringLE()) } - for _, ctrName := range contractList { + for _, ctrName := range morphUtil.ContractList { cs := c.GetContract(ctrName) domain := ctrName + ".frostfs" @@ -81,7 +75,7 @@ func setNNS(c *InitializeContext) error { return c.AwaitTx() } -func updateNNSGroup(c *InitializeContext, nnsHash util.Uint160, pub *keys.PublicKey) error { +func updateNNSGroup(c *morphUtil.InitializeContext, nnsHash util.Uint160, pub *keys.PublicKey) error { bw := io.NewBufBinWriter() keyAlreadyAdded, domainRegCodeEmitted, err := c.EmitUpdateNNSGroupScript(bw, nnsHash, pub) if keyAlreadyAdded || err != nil { @@ -99,40 +93,6 @@ func updateNNSGroup(c *InitializeContext, nnsHash util.Uint160, pub *keys.Public return c.SendCommitteeTx(script, true) } -// EmitUpdateNNSGroupScript emits script for updating group key stored in NNS. -// First return value is true iff the key is already there and nothing should be done. -// Second return value is true iff a domain registration code was emitted. -func (c *InitializeContext) EmitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (bool, bool, error) { - isAvail, err := morphUtil.NNSIsAvailable(c.Client, nnsHash, morphClient.NNSGroupKeyName) - if err != nil { - return false, false, err - } - - if !isAvail { - currentPub, err := morphUtil.NNSResolveKey(c.ReadOnlyInvoker, nnsHash, morphClient.NNSGroupKeyName) - if err != nil { - return false, false, err - } - - if pub.Equal(currentPub) { - return true, false, nil - } - } - - if isAvail { - emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, - morphClient.NNSGroupKeyName, c.CommitteeAcc.Contract.ScriptHash(), - frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) - emit.Opcodes(bw.BinWriter, opcode.ASSERT) - } - - emit.AppCall(bw.BinWriter, nnsHash, "deleteRecords", callflag.All, "group.frostfs", int64(nns.TXT)) - emit.AppCall(bw.BinWriter, nnsHash, "addRecord", callflag.All, - "group.frostfs", int64(nns.TXT), hex.EncodeToString(pub.Bytes())) - - return false, isAvail, nil -} - func getAlphabetNNSDomain(i int) string { return morphUtil.AlphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs" } @@ -160,33 +120,7 @@ func wrapRegisterScriptWithPrice(w *io.BufBinWriter, nnsHash util.Uint160, s []b } } -func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, bool, error) { - ok, err := morphUtil.NNSIsAvailable(c.Client, nnsHash, domain) - if err != nil { - return nil, false, err - } - - if ok { - bw := io.NewBufBinWriter() - emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, - domain, c.CommitteeAcc.Contract.ScriptHash(), - frostfsOpsEmail, int64(3600), int64(600), int64(defaultExpirationTime), int64(3600)) - emit.Opcodes(bw.BinWriter, opcode.ASSERT) - - if bw.Err != nil { - panic(bw.Err) - } - return bw.Bytes(), false, nil - } - - s, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, domain) - if err != nil { - return nil, false, err - } - return nil, s == expectedHash, nil -} - -func nnsRegisterDomain(c *InitializeContext, nnsHash, expectedHash util.Uint160, domain string) error { +func nnsRegisterDomain(c *morphUtil.InitializeContext, nnsHash, expectedHash util.Uint160, domain string) error { script, ok, err := c.NNSRegisterDomainScript(nnsHash, expectedHash, domain) if ok || err != nil { return err @@ -204,13 +138,4 @@ func nnsRegisterDomain(c *InitializeContext, nnsHash, expectedHash util.Uint160, return c.SendCommitteeTx(w.Bytes(), true) } -func (c *InitializeContext) NNSRootRegistered(nnsHash util.Uint160, zone string) (bool, error) { - res, err := c.CommitteeAct.Call(nnsHash, "isAvailable", "name."+zone) - if err != nil { - return false, err - } - - return res.State == vmstate.Halt.String(), nil -} - var errMissingNNSRecord = errors.New("missing NNS record") diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go index 9d3bcff09e..d6cbd2d560 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_register.go @@ -28,7 +28,7 @@ const ( registerBatchSize = transaction.MaxAttributes - 1 ) -func registerCandidateRange(c *InitializeContext, start, end int) error { +func registerCandidateRange(c *morphUtil.InitializeContext, start, end int) error { regPrice, err := getCandidateRegisterPrice(c) if err != nil { return fmt.Errorf("can't fetch registration price: %w", err) @@ -82,7 +82,7 @@ func registerCandidateRange(c *InitializeContext, start, end int) error { return c.SendTx(tx, c.Command, true) } -func registerCandidates(c *InitializeContext) error { +func registerCandidates(c *morphUtil.InitializeContext) error { cc, err := unwrap.Array(c.ReadOnlyInvoker.Call(neo.Hash, "getCandidates")) if err != nil { return fmt.Errorf("`getCandidates`: %w", err) @@ -115,7 +115,7 @@ func registerCandidates(c *InitializeContext) error { return nil } -func transferNEOToAlphabetContracts(c *InitializeContext) error { +func transferNEOToAlphabetContracts(c *morphUtil.InitializeContext) error { neoHash := neo.Hash ok, err := transferNEOFinished(c, neoHash) @@ -141,7 +141,7 @@ func transferNEOToAlphabetContracts(c *InitializeContext) error { return c.AwaitTx() } -func transferNEOFinished(c *InitializeContext, neoHash util.Uint160) (bool, error) { +func transferNEOFinished(c *morphUtil.InitializeContext, neoHash util.Uint160) (bool, error) { r := nep17.NewReader(c.ReadOnlyInvoker, neoHash) bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash()) return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err @@ -149,7 +149,7 @@ func transferNEOFinished(c *InitializeContext, neoHash util.Uint160) (bool, erro var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response") -func getCandidateRegisterPrice(c *InitializeContext) (int64, error) { +func getCandidateRegisterPrice(c *morphUtil.InitializeContext) (int64, error) { switch c.Client.(type) { case *rpcclient.Client: inv := invoker.New(c.Client, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go b/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go index 35750d6029..9e885d5f8e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go @@ -9,7 +9,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/emit" ) -func setNotaryAndAlphabetNodes(c *InitializeContext) error { +func setNotaryAndAlphabetNodes(c *util.InitializeContext) error { if ok, err := setRolesFinished(c); ok || err != nil { if err == nil { c.Command.Println("Stage 2: already performed.") @@ -35,7 +35,7 @@ func setNotaryAndAlphabetNodes(c *InitializeContext) error { return c.AwaitTx() } -func setRolesFinished(c *InitializeContext) (bool, error) { +func setRolesFinished(c *util.InitializeContext) (bool, error) { height, err := c.Client.GetBlockCount() if err != nil { return false, err diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index d5d50eca8e..63e9887c02 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -58,27 +58,27 @@ func testInitialize(t *testing.T, committeeSize int) { v.Set(util.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) // Set to the path or remove the next statement to download from the network. - require.NoError(t, initCmd.Flags().Set(contractsInitFlag, contractsPath)) + require.NoError(t, initCmd.Flags().Set(util.ContractsInitFlag, contractsPath)) dumpPath := filepath.Join(testdataDir, "out") - require.NoError(t, initCmd.Flags().Set(localDumpFlag, dumpPath)) + require.NoError(t, initCmd.Flags().Set(util.LocalDumpFlag, dumpPath)) v.Set(util.AlphabetWalletsFlag, testdataDir) - v.Set(epochDurationInitFlag, 1) - v.Set(maxObjectSizeInitFlag, 1024) + v.Set(util.EpochDurationInitFlag, 1) + v.Set(util.MaxObjectSizeInitFlag, 1024) setTestCredentials(v, committeeSize) require.NoError(t, initializeSideChainCmd(initCmd, nil)) t.Run("force-new-epoch", func(t *testing.T) { - require.NoError(t, forceNewEpoch.Flags().Set(localDumpFlag, dumpPath)) + require.NoError(t, forceNewEpoch.Flags().Set(util.LocalDumpFlag, dumpPath)) require.NoError(t, forceNewEpochCmd(forceNewEpoch, nil)) }) t.Run("set-config", func(t *testing.T) { - require.NoError(t, setConfig.Flags().Set(localDumpFlag, dumpPath)) + require.NoError(t, setConfig.Flags().Set(util.LocalDumpFlag, dumpPath)) require.NoError(t, setConfigCmd(setConfig, []string{"MaintenanceModeAllowed=true"})) }) t.Run("set-policy", func(t *testing.T) { - require.NoError(t, setPolicy.Flags().Set(localDumpFlag, dumpPath)) + require.NoError(t, setPolicy.Flags().Set(util.LocalDumpFlag, dumpPath)) require.NoError(t, setPolicyCmd(setPolicy, []string{"ExecFeeFactor=1"})) }) t.Run("remove-node", func(t *testing.T) { @@ -86,7 +86,7 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, err) pub := hex.EncodeToString(pk.PublicKey().Bytes()) - require.NoError(t, removeNodes.Flags().Set(localDumpFlag, dumpPath)) + require.NoError(t, removeNodes.Flags().Set(util.LocalDumpFlag, dumpPath)) require.NoError(t, removeNodesCmd(removeNodes, []string{pub})) }) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go index 634b478927..ab4acefee3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go @@ -13,7 +13,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" - scContext "github.com/nspcc-dev/neo-go/pkg/smartcontract/context" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -28,7 +27,7 @@ const ( initialProxyGASAmount = 50_000 * native.GASFactor ) -func transferFunds(c *InitializeContext) error { +func transferFunds(c *morphUtil.InitializeContext) error { ok, err := transferFundsFinished(c) if ok || err != nil { if err == nil { @@ -75,7 +74,7 @@ func transferFunds(c *InitializeContext) error { return c.AwaitTx() } -func transferFundsFinished(c *InitializeContext) (bool, error) { +func transferFundsFinished(c *morphUtil.InitializeContext) (bool, error) { acc := c.Accounts[0] r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) @@ -83,67 +82,7 @@ func transferFundsFinished(c *InitializeContext) (bool, error) { return res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) == 1, err } -func (c *InitializeContext) MultiSignAndSend(tx *transaction.Transaction, accType string) error { - if err := c.MultiSign(tx, accType); err != nil { - return err - } - - return c.SendTx(tx, c.Command, false) -} - -func (c *InitializeContext) MultiSign(tx *transaction.Transaction, accType string) error { - version, err := c.Client.GetVersion() - if err != nil { - // error appears only if client - // has not been initialized - panic(err) - } - network := version.Protocol.Network - - // Use parameter context to avoid dealing with signature order. - pc := scContext.NewParameterContext("", network, tx) - h := c.CommitteeAcc.Contract.ScriptHash() - if accType == morphUtil.ConsensusAccountName { - h = c.ConsensusAcc.Contract.ScriptHash() - } - for _, w := range c.Wallets { - acc, err := morphUtil.GetWalletAccount(w, accType) - if err != nil { - return fmt.Errorf("can't find %s wallet account: %w", accType, err) - } - - priv := acc.PrivateKey() - sign := priv.SignHashable(uint32(network), tx) - if err := pc.AddSignature(h, acc.Contract, priv.PublicKey(), sign); err != nil { - return fmt.Errorf("can't add signature: %w", err) - } - if len(pc.Items[h].Signatures) == len(acc.Contract.Parameters) { - break - } - } - - w, err := pc.GetWitness(h) - if err != nil { - return fmt.Errorf("incomplete signature: %w", err) - } - - for i := range tx.Signers { - if tx.Signers[i].Account == h { - if i < len(tx.Scripts) { - tx.Scripts[i] = *w - } else if i == len(tx.Scripts) { - tx.Scripts = append(tx.Scripts, *w) - } else { - panic("BUG: invalid signing order") - } - return nil - } - } - - return fmt.Errorf("%s account was not found among transaction signers", accType) -} - -func transferGASToProxy(c *InitializeContext) error { +func transferGASToProxy(c *morphUtil.InitializeContext) error { proxyCs := c.GetContract(morphUtil.ProxyContract) r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_util.go b/cmd/frostfs-adm/internal/modules/morph/netmap_util.go index fa7aa0af3c..3cf853ccac 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap_util.go @@ -3,6 +3,7 @@ package morph import ( "errors" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/spf13/viper" @@ -10,8 +11,8 @@ import ( func getDefaultNetmapContractConfigMap() map[string]any { m := make(map[string]any) - m[netmap.EpochDurationConfig] = viper.GetInt64(epochDurationInitFlag) - m[netmap.MaxObjectSizeConfig] = viper.GetInt64(maxObjectSizeInitFlag) + m[netmap.EpochDurationConfig] = viper.GetInt64(util.EpochDurationInitFlag) + m[netmap.MaxObjectSizeConfig] = viper.GetInt64(util.MaxObjectSizeInitFlag) m[netmap.ContainerFeeConfig] = viper.GetInt64(containerFeeInitFlag) m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(containerAliasFeeInitFlag) m[netmap.IrCandidateFeeConfig] = viper.GetInt64(candidateFeeInitFlag) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary.go index 3e7afdbf25..d053077059 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary.go @@ -85,7 +85,7 @@ func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, return err } - if err := checkNotaryEnabled(c); err != nil { + if err := morphUtil.CheckNotaryEnabled(c); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy.go index 97cc76ab75..d01c5e1a51 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy.go @@ -25,7 +25,7 @@ const ( ) func setPolicyCmd(cmd *cobra.Command, args []string) error { - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy.go index 4bd461b975..aa98fb70d8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy.go @@ -36,7 +36,7 @@ func removeProxyAccount(cmd *cobra.Command, _ []string) { } func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error { - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := util2.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/remove_node.go b/cmd/frostfs-adm/internal/modules/morph/remove_node.go index 42464e7317..e63a5dee93 100644 --- a/cmd/frostfs-adm/internal/modules/morph/remove_node.go +++ b/cmd/frostfs-adm/internal/modules/morph/remove_node.go @@ -29,7 +29,7 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { } } - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't initialize context: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 3288779677..7585f58452 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -8,18 +8,14 @@ import ( ) const ( - alphabetSizeFlag = "size" - storageWalletFlag = "storage-wallet" - storageWalletLabelFlag = "label" - storageGasCLIFlag = "initial-gas" - storageGasConfigFlag = "storage.initial_gas" - contractsInitFlag = "contracts" - contractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" - contractsURLFlag = "contracts-url" - contractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" - maxObjectSizeInitFlag = "network.max_object_size" - maxObjectSizeCLIFlag = "max-object-size" - epochDurationInitFlag = "network.epoch_duration" + alphabetSizeFlag = "size" + storageWalletFlag = "storage-wallet" + storageWalletLabelFlag = "label" + storageGasCLIFlag = "initial-gas" + storageGasConfigFlag = "storage.initial_gas" + + maxObjectSizeCLIFlag = "max-object-size" + epochDurationCLIFlag = "epoch-duration" containerFeeInitFlag = "network.fee.container" containerAliasFeeInitFlag = "network.fee.container_alias" @@ -38,7 +34,6 @@ const ( refillGasAmountFlag = "gas" walletAccountFlag = "account" notaryDepositTillFlag = "till" - localDumpFlag = "local-dump" walletAddressFlag = "wallet-address" ) @@ -66,8 +61,8 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(epochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) - _ = viper.BindPFlag(maxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) + _ = viper.BindPFlag(util.EpochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) + _ = viper.BindPFlag(util.MaxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) _ = viper.BindPFlag(homomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) _ = viper.BindPFlag(candidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) _ = viper.BindPFlag(containerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) @@ -365,9 +360,9 @@ func initUpdateContractsCmd() { RootCmd.AddCommand(updateContractsCmd) updateContractsCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) updateContractsCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - updateContractsCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) - updateContractsCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) - updateContractsCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag) + updateContractsCmd.Flags().String(util.ContractsInitFlag, "", util.ContractsInitFlagDesc) + updateContractsCmd.Flags().String(util.ContractsURLFlag, "", util.ContractsURLFlagDesc) + updateContractsCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) } func initDumpBalancesCmd() { @@ -384,7 +379,7 @@ func initSetConfigCmd() { setConfig.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) setConfig.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) setConfig.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") - setConfig.Flags().String(localDumpFlag, "", "Path to the blocks dump file") + setConfig.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") } func initDumpNetworkConfigCmd() { @@ -402,7 +397,7 @@ func initSetPolicyCmd() { RootCmd.AddCommand(setPolicy) setPolicy.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) setPolicy.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - setPolicy.Flags().String(localDumpFlag, "", "Path to the blocks dump file") + setPolicy.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") } func initDumpPolicyCmd() { @@ -414,14 +409,14 @@ func initRemoveNodesCmd() { RootCmd.AddCommand(removeNodes) removeNodes.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) removeNodes.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - removeNodes.Flags().String(localDumpFlag, "", "Path to the blocks dump file") + removeNodes.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") } func initForceNewEpochCmd() { RootCmd.AddCommand(forceNewEpoch) forceNewEpoch.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) forceNewEpoch.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - forceNewEpoch.Flags().String(localDumpFlag, "", "Path to the blocks dump file") + forceNewEpoch.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") } func initGenerateStorageCmd() { @@ -437,8 +432,8 @@ func initInitCmd() { RootCmd.AddCommand(initCmd) initCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) initCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - initCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc) - initCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc) + initCmd.Flags().String(util.ContractsInitFlag, "", util.ContractsInitFlagDesc) + initCmd.Flags().String(util.ContractsURLFlag, "", util.ContractsURLFlagDesc) initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") initCmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes") initCmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing") @@ -446,8 +441,8 @@ func initInitCmd() { initCmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") initCmd.Flags().String(util.ProtoConfigPath, "", "Path to the consensus node configuration") - initCmd.Flags().String(localDumpFlag, "", "Path to the blocks dump file") - initCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag) + initCmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") + initCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) } func initGenerateAlphabetCmd() { diff --git a/cmd/frostfs-adm/internal/modules/morph/update.go b/cmd/frostfs-adm/internal/modules/morph/update.go index b6fcbb5b72..2d5b24712a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/update.go +++ b/cmd/frostfs-adm/internal/modules/morph/update.go @@ -3,12 +3,13 @@ package morph import ( "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) func updateContracts(cmd *cobra.Command, _ []string) error { - wCtx, err := NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("initialization error: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index bf71b067fd..f100ebc612 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -1,5 +1,7 @@ package util +import "time" + const ( ConsensusAccountName = "consensus" ProtoConfigPath = "protocol" @@ -14,6 +16,13 @@ const ( EndpointFlagShort = "r" AlphabetWalletsFlag = "alphabet-wallets" AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" + LocalDumpFlag = "local-dump" + ContractsInitFlag = "contracts" + ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" + ContractsURLFlag = "contracts-url" + ContractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" + EpochDurationInitFlag = "network.epoch_duration" + MaxObjectSizeInitFlag = "network.max_object_size" SingleAccountName = "single" CommitteeAccountName = "committee" @@ -28,4 +37,29 @@ const ( NetmapContract = "netmap" PolicyContract = "policy" ProxyContract = "proxy" + + ContractWalletFilename = "contract.json" + ContractWalletPasswordKey = "contract" + + FrostfsOpsEmail = "ops@frostfs.info" + + DefaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second +) + +var ( + ContractList = []string{ + BalanceContract, + ContainerContract, + FrostfsIDContract, + NetmapContract, + PolicyContract, + ProxyContract, + } + + FullContractList = append([]string{ + FrostfsContract, + ProcessingContract, + NNSContract, + AlphabetContract, + }, ContractList...) ) diff --git a/cmd/frostfs-adm/internal/modules/morph/download.go b/cmd/frostfs-adm/internal/modules/morph/util/download.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/download.go rename to cmd/frostfs-adm/internal/modules/morph/util/download.go index 5bd2d98bde..ff97a7f4a2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/download.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/download.go @@ -1,4 +1,4 @@ -package morph +package util import ( "context" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go index 725181ec71..0e4c22644a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/rpcclient" @@ -187,3 +188,23 @@ func NNSIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) { return b, nil } } + +func CheckNotaryEnabled(c Client) error { + ns, err := c.GetNativeContracts() + if err != nil { + return fmt.Errorf("can't get native contract hashes: %w", err) + } + + notaryEnabled := false + nativeHashes := make(map[string]util.Uint160, len(ns)) + for i := range ns { + if ns[i].Manifest.Name == nativenames.Notary { + notaryEnabled = true + } + nativeHashes[ns[i].Manifest.Name] = ns[i].Hash + } + if !notaryEnabled { + return errors.New("notary contract must be enabled") + } + return nil +} diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go index be5dcf2db5..e7ced2ae6d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go @@ -1,14 +1,67 @@ package util import ( + "encoding/hex" "encoding/json" "fmt" + io2 "io" + "os" + "path/filepath" + "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/context" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" + "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/spf13/cobra" + "github.com/spf13/viper" ) +type ContractState struct { + NEF *nef.File + RawNEF []byte + Manifest *manifest.Manifest + RawManifest []byte + Hash util.Uint160 +} + +type Cache struct { + NNSCs *state.Contract + GroupKey *keys.PublicKey +} + +type InitializeContext struct { + ClientContext + Cache + // CommitteeAcc is used for retrieving the committee address and the verification script. + CommitteeAcc *wallet.Account + // ConsensusAcc is used for retrieving the committee address and the verification script. + ConsensusAcc *wallet.Account + Wallets []*wallet.Wallet + // ContractWallet is a wallet for providing the contract group signature. + ContractWallet *wallet.Wallet + // Accounts contains simple signature accounts in the same order as in Wallets. + Accounts []*wallet.Account + Contracts map[string]*ContractState + Command *cobra.Command + ContractPath string + ContractURL string +} + func (cs *ContractState) Parse() error { nf, err := nef.FileFromBytes(cs.RawNEF) if err != nil { @@ -25,10 +78,466 @@ func (cs *ContractState) Parse() error { return nil } -type ContractState struct { - NEF *nef.File - RawNEF []byte - Manifest *manifest.Manifest - RawManifest []byte - Hash util.Uint160 +func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContext, error) { + walletDir := config.ResolveHomePath(viper.GetString(AlphabetWalletsFlag)) + wallets, err := GetAlphabetWallets(v, walletDir) + if err != nil { + return nil, err + } + + needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init" + + var w *wallet.Wallet + w, err = GetWallet(cmd, v, needContracts, walletDir) + if err != nil { + return nil, err + } + + c, err := createClient(cmd, v, wallets) + if err != nil { + return nil, err + } + + committeeAcc, err := GetWalletAccount(wallets[0], CommitteeAccountName) + if err != nil { + return nil, fmt.Errorf("can't find committee account: %w", err) + } + + consensusAcc, err := GetWalletAccount(wallets[0], ConsensusAccountName) + if err != nil { + return nil, fmt.Errorf("can't find consensus account: %w", err) + } + + if err := validateInit(cmd); err != nil { + return nil, err + } + + ctrPath, err := getContractsPath(cmd, needContracts) + if err != nil { + return nil, err + } + + var ctrURL string + if needContracts { + ctrURL, _ = cmd.Flags().GetString(ContractsURLFlag) + } + + if err := CheckNotaryEnabled(c); err != nil { + return nil, err + } + + accounts, err := createWalletAccounts(wallets) + if err != nil { + return nil, err + } + + cliCtx, err := DefaultClientContext(c, committeeAcc) + if err != nil { + return nil, fmt.Errorf("client context: %w", err) + } + + initCtx := &InitializeContext{ + ClientContext: *cliCtx, + ConsensusAcc: consensusAcc, + CommitteeAcc: committeeAcc, + ContractWallet: w, + Wallets: wallets, + Accounts: accounts, + Command: cmd, + Contracts: make(map[string]*ContractState), + ContractPath: ctrPath, + ContractURL: ctrURL, + } + + if needContracts { + err := readContracts(initCtx, FullContractList) + if err != nil { + return nil, err + } + } + + return initCtx, nil +} + +func validateInit(cmd *cobra.Command) error { + if cmd.Name() != "init" { + return nil + } + if viper.GetInt64(EpochDurationInitFlag) <= 0 { + return fmt.Errorf("epoch duration must be positive") + } + + if viper.GetInt64(MaxObjectSizeInitFlag) <= 0 { + return fmt.Errorf("max object size must be positive") + } + + return nil +} + +func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet) (Client, error) { + var c Client + var err error + if ldf := cmd.Flags().Lookup(LocalDumpFlag); ldf != nil && ldf.Changed { + if cmd.Flags().Changed(EndpointFlag) { + return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", EndpointFlag, LocalDumpFlag) + } + c, err = NewLocalClient(cmd, v, wallets, ldf.Value.String()) + } else { + c, err = GetN3Client(v) + } + if err != nil { + return nil, fmt.Errorf("can't create N3 client: %w", err) + } + return c, nil +} + +func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) { + if !needContracts { + return "", nil + } + + ctrPath, err := cmd.Flags().GetString(ContractsInitFlag) + if err != nil { + return "", fmt.Errorf("invalid contracts path: %w", err) + } + return ctrPath, nil +} + +func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { + accounts := make([]*wallet.Account, len(wallets)) + for i, w := range wallets { + acc, err := GetWalletAccount(w, SingleAccountName) + if err != nil { + return nil, fmt.Errorf("wallet %s is invalid (no single account): %w", w.Path(), err) + } + accounts[i] = acc + } + return accounts, nil +} + +func readContracts(c *InitializeContext, names []string) error { + var ( + fi os.FileInfo + err error + ) + if c.ContractPath != "" { + fi, err = os.Stat(c.ContractPath) + if err != nil { + return fmt.Errorf("invalid contracts path: %w", err) + } + } + + if c.ContractPath != "" && fi.IsDir() { + for _, ctrName := range names { + cs, err := ReadContract(filepath.Join(c.ContractPath, ctrName), ctrName) + if err != nil { + return err + } + c.Contracts[ctrName] = cs + } + } else { + var r io2.ReadCloser + if c.ContractPath != "" { + r, err = os.Open(c.ContractPath) + } else if c.ContractURL != "" { + r, err = downloadContracts(c.Command, c.ContractURL) + } else { + r, err = downloadContractsFromRepository(c.Command) + } + if err != nil { + return fmt.Errorf("can't open contracts archive: %w", err) + } + defer r.Close() + + m, err := ReadContractsFromArchive(r, names) + if err != nil { + return err + } + for _, name := range names { + if err := m[name].Parse(); err != nil { + return err + } + c.Contracts[name] = m[name] + } + } + + for _, ctrName := range names { + if ctrName != AlphabetContract { + cs := c.Contracts[ctrName] + cs.Hash = state.CreateContractHash(c.CommitteeAcc.Contract.ScriptHash(), + cs.NEF.Checksum, cs.Manifest.Name) + } + } + return nil +} + +func (c *InitializeContext) Close() { + if local, ok := c.Client.(*LocalClient); ok { + err := local.Dump() + if err != nil { + c.Command.PrintErrf("Can't write dump: %v\n", err) + os.Exit(1) + } + } +} + +func (c *InitializeContext) AwaitTx() error { + return c.ClientContext.AwaitTx(c.Command) +} + +func (c *InitializeContext) NNSContractState() (*state.Contract, error) { + if c.NNSCs != nil { + return c.NNSCs, nil + } + + r := management.NewReader(c.ReadOnlyInvoker) + cs, err := r.GetContractByID(1) + if err != nil { + return nil, err + } + + c.NNSCs = cs + return cs, nil +} + +func (c *InitializeContext) GetSigner(tryGroup bool, acc *wallet.Account) transaction.Signer { + if tryGroup && c.GroupKey != nil { + return transaction.Signer{ + Account: acc.Contract.ScriptHash(), + Scopes: transaction.CustomGroups, + AllowedGroups: keys.PublicKeys{c.GroupKey}, + } + } + + signer := transaction.Signer{ + Account: acc.Contract.ScriptHash(), + Scopes: transaction.Global, // Scope is important, as we have nested call to container contract. + } + + if !tryGroup { + return signer + } + + nnsCs, err := c.NNSContractState() + if err != nil { + return signer + } + + groupKey, err := NNSResolveKey(c.ReadOnlyInvoker, nnsCs.Hash, client.NNSGroupKeyName) + if err == nil { + c.GroupKey = groupKey + + signer.Scopes = transaction.CustomGroups + signer.AllowedGroups = keys.PublicKeys{groupKey} + } + return signer +} + +// SendCommitteeTx creates transaction from script, signs it by committee nodes and sends it to RPC. +// If tryGroup is false, global scope is used for the signer (useful when +// working with native contracts). +func (c *InitializeContext) SendCommitteeTx(script []byte, tryGroup bool) error { + return c.sendMultiTx(script, tryGroup, false) +} + +// SendConsensusTx creates transaction from script, signs it by alphabet nodes and sends it to RPC. +// Not that because this is used only after the contracts were initialized and deployed, +// we always try to have a group scope. +func (c *InitializeContext) SendConsensusTx(script []byte) error { + return c.sendMultiTx(script, true, true) +} + +func (c *InitializeContext) sendMultiTx(script []byte, tryGroup bool, withConsensus bool) error { + var act *actor.Actor + var err error + + withConsensus = withConsensus && !c.ConsensusAcc.Contract.ScriptHash().Equals(c.CommitteeAcc.ScriptHash()) + if tryGroup { + // Even for consensus signatures we need the committee to pay. + signers := make([]actor.SignerAccount, 1, 2) + signers[0] = actor.SignerAccount{ + Signer: c.GetSigner(tryGroup, c.CommitteeAcc), + Account: c.CommitteeAcc, + } + if withConsensus { + signers = append(signers, actor.SignerAccount{ + Signer: c.GetSigner(tryGroup, c.ConsensusAcc), + Account: c.ConsensusAcc, + }) + } + act, err = actor.New(c.Client, signers) + } else { + if withConsensus { + panic("BUG: should never happen") + } + act, err = c.CommitteeAct, nil + } + if err != nil { + return fmt.Errorf("could not create actor: %w", err) + } + + tx, err := act.MakeUnsignedRun(script, []transaction.Attribute{{Type: transaction.HighPriority}}) + if err != nil { + return fmt.Errorf("could not perform test invocation: %w", err) + } + + if err := c.MultiSign(tx, CommitteeAccountName); err != nil { + return err + } + if withConsensus { + if err := c.MultiSign(tx, ConsensusAccountName); err != nil { + return err + } + } + + return c.SendTx(tx, c.Command, false) +} + +func (c *InitializeContext) MultiSignAndSend(tx *transaction.Transaction, accType string) error { + if err := c.MultiSign(tx, accType); err != nil { + return err + } + + return c.SendTx(tx, c.Command, false) +} + +func (c *InitializeContext) MultiSign(tx *transaction.Transaction, accType string) error { + version, err := c.Client.GetVersion() + if err != nil { + // error appears only if client + // has not been initialized + panic(err) + } + network := version.Protocol.Network + + // Use parameter context to avoid dealing with signature order. + pc := context.NewParameterContext("", network, tx) + h := c.CommitteeAcc.Contract.ScriptHash() + if accType == ConsensusAccountName { + h = c.ConsensusAcc.Contract.ScriptHash() + } + for _, w := range c.Wallets { + acc, err := GetWalletAccount(w, accType) + if err != nil { + return fmt.Errorf("can't find %s wallet account: %w", accType, err) + } + + priv := acc.PrivateKey() + sign := priv.SignHashable(uint32(network), tx) + if err := pc.AddSignature(h, acc.Contract, priv.PublicKey(), sign); err != nil { + return fmt.Errorf("can't add signature: %w", err) + } + if len(pc.Items[h].Signatures) == len(acc.Contract.Parameters) { + break + } + } + + w, err := pc.GetWitness(h) + if err != nil { + return fmt.Errorf("incomplete signature: %w", err) + } + + for i := range tx.Signers { + if tx.Signers[i].Account == h { + if i < len(tx.Scripts) { + tx.Scripts[i] = *w + } else if i == len(tx.Scripts) { + tx.Scripts = append(tx.Scripts, *w) + } else { + panic("BUG: invalid signing order") + } + return nil + } + } + + return fmt.Errorf("%s account was not found among transaction signers", accType) +} + +// EmitUpdateNNSGroupScript emits script for updating group key stored in NNS. +// First return value is true iff the key is already there and nothing should be done. +// Second return value is true iff a domain registration code was emitted. +func (c *InitializeContext) EmitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHash util.Uint160, pub *keys.PublicKey) (bool, bool, error) { + isAvail, err := NNSIsAvailable(c.Client, nnsHash, client.NNSGroupKeyName) + if err != nil { + return false, false, err + } + + if !isAvail { + currentPub, err := NNSResolveKey(c.ReadOnlyInvoker, nnsHash, client.NNSGroupKeyName) + if err != nil { + return false, false, err + } + + if pub.Equal(currentPub) { + return true, false, nil + } + } + + if isAvail { + emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, + client.NNSGroupKeyName, c.CommitteeAcc.Contract.ScriptHash(), + FrostfsOpsEmail, int64(3600), int64(600), int64(DefaultExpirationTime), int64(3600)) + emit.Opcodes(bw.BinWriter, opcode.ASSERT) + } + + emit.AppCall(bw.BinWriter, nnsHash, "deleteRecords", callflag.All, "group.frostfs", int64(nns.TXT)) + emit.AppCall(bw.BinWriter, nnsHash, "addRecord", callflag.All, + "group.frostfs", int64(nns.TXT), hex.EncodeToString(pub.Bytes())) + + return false, isAvail, nil +} + +func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.Uint160, domain string) ([]byte, bool, error) { + ok, err := NNSIsAvailable(c.Client, nnsHash, domain) + if err != nil { + return nil, false, err + } + + if ok { + bw := io.NewBufBinWriter() + emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, + domain, c.CommitteeAcc.Contract.ScriptHash(), + FrostfsOpsEmail, int64(3600), int64(600), int64(DefaultExpirationTime), int64(3600)) + emit.Opcodes(bw.BinWriter, opcode.ASSERT) + + if bw.Err != nil { + panic(bw.Err) + } + return bw.Bytes(), false, nil + } + + s, err := NNSResolveHash(c.ReadOnlyInvoker, nnsHash, domain) + if err != nil { + return nil, false, err + } + return nil, s == expectedHash, nil +} + +func (c *InitializeContext) NNSRootRegistered(nnsHash util.Uint160, zone string) (bool, error) { + res, err := c.CommitteeAct.Call(nnsHash, "isAvailable", "name."+zone) + if err != nil { + return false, err + } + + return res.State == vmstate.Halt.String(), nil +} + +func (c *InitializeContext) IsUpdated(ctrHash util.Uint160, cs *ContractState) bool { + r := management.NewReader(c.ReadOnlyInvoker) + realCs, err := r.GetContract(ctrHash) + return err == nil && realCs != nil && realCs.NEF.Checksum == cs.NEF.Checksum +} + +func (c *InitializeContext) GetContract(ctrName string) *ContractState { + return c.Contracts[ctrName] +} + +func (c *InitializeContext) GetAlphabetDeployItems(i, n int) []any { + items := make([]any, 5) + items[0] = c.Contracts[NetmapContract].Hash + items[1] = c.Contracts[ProxyContract].Hash + items[2] = innerring.GlagoliticLetter(i).String() + items[3] = int64(i) + items[4] = int64(n) + return items } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/util.go b/cmd/frostfs-adm/internal/modules/morph/util/util.go index bbe635a408..abd72b04d9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/util.go @@ -1,10 +1,14 @@ package util import ( + "archive/tar" + "compress/gzip" "errors" "fmt" + "io" "os" "path/filepath" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" @@ -84,3 +88,72 @@ func NewActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, err Account: committeeAcc, }}) } + +func ReadContract(ctrPath, ctrName string) (*ContractState, error) { + rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef")) + if err != nil { + return nil, fmt.Errorf("can't read NEF file for %s contract: %w", ctrName, err) + } + rawManif, err := os.ReadFile(filepath.Join(ctrPath, "config.json")) + if err != nil { + return nil, fmt.Errorf("can't read manifest file for %s contract: %w", ctrName, err) + } + + cs := &ContractState{ + RawNEF: rawNef, + RawManifest: rawManif, + } + + return cs, cs.Parse() +} + +func ReadContractsFromArchive(file io.Reader, names []string) (map[string]*ContractState, error) { + m := make(map[string]*ContractState, len(names)) + for i := range names { + m[names[i]] = new(ContractState) + } + + gr, err := gzip.NewReader(file) + if err != nil { + return nil, fmt.Errorf("contracts file must be tar.gz archive: %w", err) + } + + r := tar.NewReader(gr) + for h, err := r.Next(); ; h, err = r.Next() { + if err != nil { + break + } + + dir, _ := filepath.Split(h.Name) + ctrName := filepath.Base(dir) + + cs, ok := m[ctrName] + if !ok { + continue + } + + switch { + case strings.HasSuffix(h.Name, filepath.Join(ctrName, ctrName+"_contract.nef")): + cs.RawNEF, err = io.ReadAll(r) + if err != nil { + return nil, fmt.Errorf("can't read NEF file for %s contract: %w", ctrName, err) + } + case strings.HasSuffix(h.Name, "config.json"): + cs.RawManifest, err = io.ReadAll(r) + if err != nil { + return nil, fmt.Errorf("can't read manifest file for %s contract: %w", ctrName, err) + } + } + m[ctrName] = cs + } + + for ctrName, cs := range m { + if cs.RawNEF == nil { + return nil, fmt.Errorf("NEF for %s contract wasn't found", ctrName) + } + if cs.RawManifest == nil { + return nil, fmt.Errorf("manifest for %s contract wasn't found", ctrName) + } + } + return m, nil +} diff --git a/cmd/frostfs-adm/internal/modules/morph/util/wallet.go b/cmd/frostfs-adm/internal/modules/morph/util/wallet.go new file mode 100644 index 0000000000..2110adb101 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/wallet.go @@ -0,0 +1,75 @@ +package util + +import ( + "fmt" + "os" + "path/filepath" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func InitializeContractWallet(v *viper.Viper, walletDir string) (*wallet.Wallet, error) { + password, err := config.GetPassword(v, ContractWalletPasswordKey) + if err != nil { + return nil, err + } + + w, err := wallet.NewWallet(filepath.Join(walletDir, ContractWalletFilename)) + if err != nil { + return nil, err + } + + acc, err := wallet.NewAccount() + if err != nil { + return nil, err + } + + err = acc.Encrypt(password, keys.NEP2ScryptParams()) + if err != nil { + return nil, err + } + + w.AddAccount(acc) + if err := w.SavePretty(); err != nil { + return nil, err + } + + return w, nil +} + +func OpenContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (*wallet.Wallet, error) { + p := filepath.Join(walletDir, ContractWalletFilename) + w, err := wallet.NewWalletFromFile(p) + if err != nil { + if !os.IsNotExist(err) { + return nil, fmt.Errorf("can't open wallet: %w", err) + } + + cmd.Printf("Contract group wallet is missing, initialize at %s\n", p) + return InitializeContractWallet(v, walletDir) + } + + password, err := config.GetPassword(v, ContractWalletPasswordKey) + if err != nil { + return nil, err + } + + for i := range w.Accounts { + if err := w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil { + return nil, fmt.Errorf("can't unlock wallet: %w", err) + } + } + + return w, nil +} + +func GetWallet(cmd *cobra.Command, v *viper.Viper, needContracts bool, walletDir string) (*wallet.Wallet, error) { + if !needContracts { + return nil, nil + } + return OpenContractWallet(v, cmd, walletDir) +} From f6ff3de0ae5ddf53b77a7d244ccdb0ca7ed432cf Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 15:55:33 +0300 Subject: [PATCH 0352/1413] [#932] adm: Move `set-/dump-policy` to `policy` package Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/initialize_test.go | 5 +- .../modules/morph/{ => policy}/policy.go | 4 +- .../internal/modules/morph/policy/root.go | 47 +++++++++++++++++++ .../internal/modules/morph/root.go | 40 ++-------------- 4 files changed, 55 insertions(+), 41 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => policy}/policy.go (97%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/policy/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index 63e9887c02..e9571e50ca 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/config" @@ -78,8 +79,8 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, setConfigCmd(setConfig, []string{"MaintenanceModeAllowed=true"})) }) t.Run("set-policy", func(t *testing.T) { - require.NoError(t, setPolicy.Flags().Set(util.LocalDumpFlag, dumpPath)) - require.NoError(t, setPolicyCmd(setPolicy, []string{"ExecFeeFactor=1"})) + require.NoError(t, policy.Set.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, policy.SetPolicyCmd(policy.Set, []string{"ExecFeeFactor=1"})) }) t.Run("remove-node", func(t *testing.T) { pk, err := keys.NewPrivateKey() diff --git a/cmd/frostfs-adm/internal/modules/morph/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go similarity index 97% rename from cmd/frostfs-adm/internal/modules/morph/policy.go rename to cmd/frostfs-adm/internal/modules/morph/policy/policy.go index d01c5e1a51..7f4a8d3269 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go @@ -1,4 +1,4 @@ -package morph +package policy import ( "bytes" @@ -24,7 +24,7 @@ const ( setFeeParam = "FeePerByte" ) -func setPolicyCmd(cmd *cobra.Command, args []string) error { +func SetPolicyCmd(cmd *cobra.Command, args []string) error { wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/root.go b/cmd/frostfs-adm/internal/modules/morph/policy/root.go new file mode 100644 index 0000000000..99ff56ee88 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/policy/root.go @@ -0,0 +1,47 @@ +package policy + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + Set = &cobra.Command{ + Use: "set-policy [ExecFeeFactor=] [StoragePrice=] [FeePerByte=]", + DisableFlagsInUseLine: true, + Short: "Set global policy values", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: SetPolicyCmd, + ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"ExecFeeFactor=", "StoragePrice=", "FeePerByte="}, cobra.ShellCompDirectiveNoSpace + }, + } + + Dump = &cobra.Command{ + Use: "dump-policy", + Short: "Dump FrostFS policy", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: dumpPolicyCmd, + } +) + +func initSetPolicyCmd() { + Set.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + Set.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + Set.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") +} + +func initDumpPolicyCmd() { + Dump.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) +} + +func init() { + initSetPolicyCmd() + initDumpPolicyCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 7585f58452..b53a64486f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -2,6 +2,7 @@ package morph import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -130,29 +131,6 @@ var ( RunE: setConfigCmd, } - setPolicy = &cobra.Command{ - Use: "set-policy [ExecFeeFactor=] [StoragePrice=] [FeePerByte=]", - DisableFlagsInUseLine: true, - Short: "Set global policy values", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: setPolicyCmd, - ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return []string{"ExecFeeFactor=", "StoragePrice=", "FeePerByte="}, cobra.ShellCompDirectiveNoSpace - }, - } - - dumpPolicy = &cobra.Command{ - Use: "dump-policy", - Short: "Dump FrostFS policy", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: dumpPolicyCmd, - } - dumpContractHashesCmd = &cobra.Command{ Use: "dump-hashes", Short: "Dump deployed contract hashes", @@ -265,8 +243,8 @@ func init() { initGenerateStorageCmd() initForceNewEpochCmd() initRemoveNodesCmd() - initSetPolicyCmd() - initDumpPolicyCmd() + RootCmd.AddCommand(policy.Set) + RootCmd.AddCommand(policy.Dump) initDumpContractHashesCmd() initDumpNetworkConfigCmd() initSetConfigCmd() @@ -393,18 +371,6 @@ func initDumpContractHashesCmd() { dumpContractHashesCmd.Flags().String(customZoneFlag, "", "Custom zone to search.") } -func initSetPolicyCmd() { - RootCmd.AddCommand(setPolicy) - setPolicy.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - setPolicy.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - setPolicy.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") -} - -func initDumpPolicyCmd() { - RootCmd.AddCommand(dumpPolicy) - dumpPolicy.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) -} - func initRemoveNodesCmd() { RootCmd.AddCommand(removeNodes) removeNodes.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) From a92188e5f9bef9c426c5d09826afd4ee1bcc01c2 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 16:00:45 +0300 Subject: [PATCH 0353/1413] [#932] adm: Reduce methods visibility in `util` package Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/util/initialize_ctx.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/util/util.go | 6 +++--- cmd/frostfs-adm/internal/modules/morph/util/wallet.go | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go index e7ced2ae6d..4305df1e57 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go @@ -88,7 +88,7 @@ func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContex needContracts := cmd.Name() == "update-contracts" || cmd.Name() == "init" var w *wallet.Wallet - w, err = GetWallet(cmd, v, needContracts, walletDir) + w, err = getWallet(cmd, v, needContracts, walletDir) if err != nil { return nil, err } @@ -249,7 +249,7 @@ func readContracts(c *InitializeContext, names []string) error { } defer r.Close() - m, err := ReadContractsFromArchive(r, names) + m, err := readContractsFromArchive(r, names) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/util.go b/cmd/frostfs-adm/internal/modules/morph/util/util.go index abd72b04d9..4a963d3d89 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/util.go @@ -20,7 +20,7 @@ import ( ) func GetAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { - wallets, err := OpenAlphabetWallets(v, walletDir) + wallets, err := openAlphabetWallets(v, walletDir) if err != nil { return nil, err } @@ -31,7 +31,7 @@ func GetAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, err return wallets, nil } -func OpenAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { +func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { walletFiles, err := os.ReadDir(walletDir) if err != nil { return nil, fmt.Errorf("can't read alphabet wallets dir: %w", err) @@ -107,7 +107,7 @@ func ReadContract(ctrPath, ctrName string) (*ContractState, error) { return cs, cs.Parse() } -func ReadContractsFromArchive(file io.Reader, names []string) (map[string]*ContractState, error) { +func readContractsFromArchive(file io.Reader, names []string) (map[string]*ContractState, error) { m := make(map[string]*ContractState, len(names)) for i := range names { m[names[i]] = new(ContractState) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/wallet.go b/cmd/frostfs-adm/internal/modules/morph/util/wallet.go index 2110adb101..e0e553d06c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/wallet.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/wallet.go @@ -41,7 +41,7 @@ func InitializeContractWallet(v *viper.Viper, walletDir string) (*wallet.Wallet, return w, nil } -func OpenContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (*wallet.Wallet, error) { +func openContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (*wallet.Wallet, error) { p := filepath.Join(walletDir, ContractWalletFilename) w, err := wallet.NewWalletFromFile(p) if err != nil { @@ -67,9 +67,9 @@ func OpenContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (* return w, nil } -func GetWallet(cmd *cobra.Command, v *viper.Viper, needContracts bool, walletDir string) (*wallet.Wallet, error) { +func getWallet(cmd *cobra.Command, v *viper.Viper, needContracts bool, walletDir string) (*wallet.Wallet, error) { if !needContracts { return nil, nil } - return OpenContractWallet(v, cmd, walletDir) + return openContractWallet(v, cmd, walletDir) } From 218bd72f9abbab228f72896b4fb8cbedf944a709 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 16:11:17 +0300 Subject: [PATCH 0354/1413] [#932] adm: Move command `frostfsid` to package `frostfsid` Signed-off-by: Anton Nikiforov --- .../morph/{ => frostfsid}/frostfsid.go | 31 ++++++++++--------- .../morph/{ => frostfsid}/frostfsid_util.go | 4 +-- .../{ => frostfsid}/frostfsid_util_test.go | 8 ++--- .../internal/modules/morph/frostfsid/root.go | 15 +++++++++ .../modules/morph/initialize_deploy.go | 5 ++- .../internal/modules/morph/root.go | 14 ++------- 6 files changed, 41 insertions(+), 36 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => frostfsid}/frostfsid.go (96%) rename cmd/frostfs-adm/internal/modules/morph/{ => frostfsid}/frostfsid_util.go (96%) rename cmd/frostfs-adm/internal/modules/morph/{ => frostfsid}/frostfsid_util_test.go (96%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go similarity index 96% rename from cmd/frostfs-adm/internal/modules/morph/frostfsid.go rename to cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 3e39c3019e..76bbc71488 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -1,4 +1,4 @@ -package morph +package frostfsid import ( "errors" @@ -27,12 +27,13 @@ const ( includeNamesFlag = "include-names" groupNameFlag = "group-name" groupIDFlag = "group-id" + + frostfsIDAdminConfigKey = "frostfsid.admin" + rootNamespacePlaceholder = "" ) -const rootNamespacePlaceholder = "" - var ( - frostfsidCmd = &cobra.Command{ + Cmd = &cobra.Command{ Use: "frostfsid", Short: "Section for frostfsid interactions commands", } @@ -149,20 +150,20 @@ var ( ) func initFrostfsIDCreateNamespaceCmd() { - frostfsidCmd.AddCommand(frostfsidCreateNamespaceCmd) + Cmd.AddCommand(frostfsidCreateNamespaceCmd) frostfsidCreateNamespaceCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateNamespaceCmd.Flags().String(namespaceFlag, "", "Namespace name to create") frostfsidCreateNamespaceCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDListNamespacesCmd() { - frostfsidCmd.AddCommand(frostfsidListNamespacesCmd) + Cmd.AddCommand(frostfsidListNamespacesCmd) frostfsidListNamespacesCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListNamespacesCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDCreateSubjectCmd() { - frostfsidCmd.AddCommand(frostfsidCreateSubjectCmd) + Cmd.AddCommand(frostfsidCreateSubjectCmd) frostfsidCreateSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateSubjectCmd.Flags().String(namespaceFlag, "", "Namespace where create subject") frostfsidCreateSubjectCmd.Flags().String(subjectNameFlag, "", "Subject name, must be unique in namespace") @@ -171,14 +172,14 @@ func initFrostfsIDCreateSubjectCmd() { } func initFrostfsIDDeleteSubjectCmd() { - frostfsidCmd.AddCommand(frostfsidDeleteSubjectCmd) + Cmd.AddCommand(frostfsidDeleteSubjectCmd) frostfsidDeleteSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidDeleteSubjectCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidDeleteSubjectCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDListSubjectsCmd() { - frostfsidCmd.AddCommand(frostfsidListSubjectsCmd) + Cmd.AddCommand(frostfsidListSubjectsCmd) frostfsidListSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") @@ -186,7 +187,7 @@ func initFrostfsIDListSubjectsCmd() { } func initFrostfsIDCreateGroupCmd() { - frostfsidCmd.AddCommand(frostfsidCreateGroupCmd) + Cmd.AddCommand(frostfsidCreateGroupCmd) frostfsidCreateGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidCreateGroupCmd.Flags().String(namespaceFlag, "", "Namespace where create group") frostfsidCreateGroupCmd.Flags().String(groupNameFlag, "", "Group name, must be unique in namespace") @@ -194,7 +195,7 @@ func initFrostfsIDCreateGroupCmd() { } func initFrostfsIDDeleteGroupCmd() { - frostfsidCmd.AddCommand(frostfsidDeleteGroupCmd) + Cmd.AddCommand(frostfsidDeleteGroupCmd) frostfsidDeleteGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidDeleteGroupCmd.Flags().String(namespaceFlag, "", "Namespace to delete group") frostfsidDeleteGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") @@ -202,14 +203,14 @@ func initFrostfsIDDeleteGroupCmd() { } func initFrostfsIDListGroupsCmd() { - frostfsidCmd.AddCommand(frostfsidListGroupsCmd) + Cmd.AddCommand(frostfsidListGroupsCmd) frostfsidListGroupsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") frostfsidListGroupsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) } func initFrostfsIDAddSubjectToGroupCmd() { - frostfsidCmd.AddCommand(frostfsidAddSubjectToGroupCmd) + Cmd.AddCommand(frostfsidAddSubjectToGroupCmd) frostfsidAddSubjectToGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidAddSubjectToGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidAddSubjectToGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") @@ -217,7 +218,7 @@ func initFrostfsIDAddSubjectToGroupCmd() { } func initFrostfsIDRemoveSubjectFromGroupCmd() { - frostfsidCmd.AddCommand(frostfsidRemoveSubjectFromGroupCmd) + Cmd.AddCommand(frostfsidRemoveSubjectFromGroupCmd) frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidRemoveSubjectFromGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidRemoveSubjectFromGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") @@ -225,7 +226,7 @@ func initFrostfsIDRemoveSubjectFromGroupCmd() { } func initFrostfsIDListGroupSubjectsCmd() { - frostfsidCmd.AddCommand(frostfsidListGroupSubjectsCmd) + Cmd.AddCommand(frostfsidListGroupSubjectsCmd) frostfsidListGroupSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util.go similarity index 96% rename from cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go rename to cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util.go index 6b6bdffa9b..99c04f57df 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util.go @@ -1,4 +1,4 @@ -package morph +package frostfsid import ( "errors" @@ -13,7 +13,7 @@ import ( "github.com/spf13/viper" ) -func getFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { +func GetFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { admin := v.GetString(frostfsIDAdminConfigKey) if admin == "" { return util.Uint160{}, false, nil diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go similarity index 96% rename from cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go rename to cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go index 79a0845f94..119e10d15c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid_util_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go @@ -1,4 +1,4 @@ -package morph +package frostfsid import ( "encoding/hex" @@ -30,7 +30,7 @@ func TestFrostfsIDConfig(t *testing.T) { v := viper.New() v.Set("frostfsid.admin", fmts[i]) - actual, found, err := getFrostfsIDAdmin(v) + actual, found, err := GetFrostfsIDAdmin(v) require.NoError(t, err) require.True(t, found) require.Equal(t, pks[i].GetScriptHash(), actual) @@ -40,14 +40,14 @@ func TestFrostfsIDConfig(t *testing.T) { v := viper.New() v.Set("frostfsid.admin", "abc") - _, found, err := getFrostfsIDAdmin(v) + _, found, err := GetFrostfsIDAdmin(v) require.Error(t, err) require.True(t, found) }) t.Run("missing key", func(t *testing.T) { v := viper.New() - _, found, err := getFrostfsIDAdmin(v) + _, found, err := GetFrostfsIDAdmin(v) require.NoError(t, err) require.False(t, found) }) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go new file mode 100644 index 0000000000..8504747945 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go @@ -0,0 +1,15 @@ +package frostfsid + +func init() { + initFrostfsIDCreateNamespaceCmd() + initFrostfsIDListNamespacesCmd() + initFrostfsIDCreateSubjectCmd() + initFrostfsIDDeleteSubjectCmd() + initFrostfsIDListSubjectsCmd() + initFrostfsIDCreateGroupCmd() + initFrostfsIDDeleteGroupCmd() + initFrostfsIDListGroupsCmd() + initFrostfsIDAddSubjectToGroupCmd() + initFrostfsIDRemoveSubjectFromGroupCmd() + initFrostfsIDListGroupSubjectsCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 322033abc4..5cd7b3ba0d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/common" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" @@ -27,8 +28,6 @@ import ( "github.com/spf13/viper" ) -const frostfsIDAdminConfigKey = "frostfsid.admin" - var netmapConfigKeys = []string{ netmap.EpochDurationConfig, netmap.MaxObjectSizeConfig, @@ -361,7 +360,7 @@ func getContractDeployData(c *morphUtil.InitializeContext, ctrName string, keysP h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker) } if method != updateMethodName || err == nil && !found { - h, found, err = getFrostfsIDAdmin(viper.GetViper()) + h, found, err = frostfsid.GetFrostfsIDAdmin(viper.GetViper()) } if err != nil { return nil, err diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index b53a64486f..0d6f48d980 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -2,6 +2,7 @@ package morph import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" @@ -262,18 +263,7 @@ func init() { initProxyAddAccount() initProxyRemoveAccount() - RootCmd.AddCommand(frostfsidCmd) - initFrostfsIDCreateNamespaceCmd() - initFrostfsIDListNamespacesCmd() - initFrostfsIDCreateSubjectCmd() - initFrostfsIDDeleteSubjectCmd() - initFrostfsIDListSubjectsCmd() - initFrostfsIDCreateGroupCmd() - initFrostfsIDDeleteGroupCmd() - initFrostfsIDListGroupsCmd() - initFrostfsIDAddSubjectToGroupCmd() - initFrostfsIDRemoveSubjectFromGroupCmd() - initFrostfsIDListGroupSubjectsCmd() + RootCmd.AddCommand(frostfsid.Cmd) } func initProxyAddAccount() { From 8148c9dc19e8b7fd29d4de916ec66b1772a025ac Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 16:31:46 +0300 Subject: [PATCH 0355/1413] [#932] adm: Move command `morph proxy` to package `proxy` Signed-off-by: Anton Nikiforov --- .../modules/morph/{ => proxy}/proxy.go | 2 +- .../internal/modules/morph/proxy/root.go | 43 +++++++++++++++++++ .../internal/modules/morph/root.go | 38 ++-------------- 3 files changed, 47 insertions(+), 36 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => proxy}/proxy.go (99%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/proxy/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/proxy.go rename to cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go index aa98fb70d8..7455c0bd09 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go @@ -1,4 +1,4 @@ -package morph +package proxy import ( "fmt" diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go new file mode 100644 index 0000000000..14820d5aba --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go @@ -0,0 +1,43 @@ +package proxy + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + AddAccountCmd = &cobra.Command{ + Use: "proxy-add-account", + Short: "Adds account to proxy contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + Run: addProxyAccount, + } + RemoveAccountCmd = &cobra.Command{ + Use: "proxy-remove-account", + Short: "Remove from proxy contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + Run: removeProxyAccount, + } +) + +func initProxyAddAccount() { + AddAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + AddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") +} + +func initProxyRemoveAccount() { + RemoveAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + RemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") +} + +func init() { + initProxyAddAccount() + initProxyRemoveAccount() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 0d6f48d980..7eb41ddc21 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -4,6 +4,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/proxy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -215,26 +216,6 @@ var ( }, Run: listNetmapCandidatesNodes, } - - proxyAddAccountCmd = &cobra.Command{ - Use: "proxy-add-account", - Short: "Adds account to proxy contract", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - Run: addProxyAccount, - } - - proxyRemoveAccountCmd = &cobra.Command{ - Use: "proxy-remove-account", - Short: "Remove from proxy contract", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - Run: removeProxyAccount, - } ) func init() { @@ -259,25 +240,12 @@ func init() { initNetmapCandidatesCmd() RootCmd.AddCommand(ape.Cmd) - - initProxyAddAccount() - initProxyRemoveAccount() + RootCmd.AddCommand(proxy.AddAccountCmd) + RootCmd.AddCommand(proxy.RemoveAccountCmd) RootCmd.AddCommand(frostfsid.Cmd) } -func initProxyAddAccount() { - RootCmd.AddCommand(proxyAddAccountCmd) - proxyAddAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - proxyAddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") -} - -func initProxyRemoveAccount() { - RootCmd.AddCommand(proxyRemoveAccountCmd) - proxyRemoveAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - proxyRemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") -} - func initNetmapCandidatesCmd() { RootCmd.AddCommand(netmapCandidatesCmd) netmapCandidatesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) From beb9d80e348330855c5a943645b666f70004d690 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 16:38:20 +0300 Subject: [PATCH 0356/1413] [#932] adm: Move command `dump-balances` to package `balance` Signed-off-by: Anton Nikiforov --- .../modules/morph/{ => balance}/balance.go | 4 +-- .../internal/modules/morph/balance/root.go | 28 +++++++++++++++++++ .../internal/modules/morph/dump_hashes.go | 4 +-- .../modules/morph/initialize_deploy.go | 2 +- .../internal/modules/morph/initialize_nns.go | 7 +---- .../internal/modules/morph/root.go | 21 ++------------ .../internal/modules/morph/util/util.go | 5 ++++ 7 files changed, 41 insertions(+), 30 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => balance}/balance.go (99%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/balance/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/balance.go rename to cmd/frostfs-adm/internal/modules/morph/balance/balance.go index 451d57954f..9d16ada466 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go @@ -1,4 +1,4 @@ -package morph +package balance import ( "crypto/elliptic" @@ -157,7 +157,7 @@ func printAlphabetContractBalances(cmd *cobra.Command, c morphUtil.Client, inv * w := io.NewBufBinWriter() for i := range alphaList { emit.AppCall(w.BinWriter, nnsHash, "resolve", callflag.ReadOnly, - getAlphabetNNSDomain(i), + morphUtil.GetAlphabetNNSDomain(i), int64(nns.TXT)) } if w.Err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/balance/root.go b/cmd/frostfs-adm/internal/modules/morph/balance/root.go new file mode 100644 index 0000000000..757637e5db --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/balance/root.go @@ -0,0 +1,28 @@ +package balance + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var DumpCmd = &cobra.Command{ + Use: "dump-balances", + Short: "Dump GAS balances", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: dumpBalances, +} + +func initDumpBalancesCmd() { + DumpCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + DumpCmd.Flags().BoolP(dumpBalancesStorageFlag, "s", false, "Dump balances of storage nodes from the current netmap") + DumpCmd.Flags().BoolP(dumpBalancesAlphabetFlag, "a", false, "Dump balances of alphabet contracts") + DumpCmd.Flags().BoolP(dumpBalancesProxyFlag, "p", false, "Dump balances of the proxy contract") + DumpCmd.Flags().Bool(dumpBalancesUseScriptHashFlag, false, "Use script-hash format for addresses") +} + +func init() { + initDumpBalancesCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go index d33311a8bf..c92c256903 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go @@ -54,7 +54,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { irSize := 0 for ; irSize < lastGlagoliticLetter; irSize++ { - ok, err := morphUtil.NNSIsAvailable(c, cs.Hash, getAlphabetNNSDomain(irSize)) + ok, err := morphUtil.NNSIsAvailable(c, cs.Hash, morphUtil.GetAlphabetNNSDomain(irSize)) if err != nil { return err } else if ok { @@ -68,7 +68,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { bw.Reset() for i := 0; i < irSize; i++ { emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, - getAlphabetNNSDomain(i), + morphUtil.GetAlphabetNNSDomain(i), int64(nns.TXT)) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 5cd7b3ba0d..50427c93fc 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -215,7 +215,7 @@ func deployAlphabetAccounts(c *morphUtil.InitializeContext, nnsHash util.Uint160 // alphabet contracts should be deployed by individual nodes to get different hashes. for i, acc := range c.Accounts { - ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, getAlphabetNNSDomain(i)) + ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.GetAlphabetNNSDomain(i)) if err != nil { return nil, fmt.Errorf("can't resolve hash for contract update: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 8e5223098a..53435e67bb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -4,7 +4,6 @@ import ( "encoding/hex" "errors" "fmt" - "strconv" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" @@ -48,7 +47,7 @@ func setNNS(c *morphUtil.InitializeContext) error { for i, acc := range c.Accounts { alphaCs.Hash = state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name) - domain := getAlphabetNNSDomain(i) + domain := morphUtil.GetAlphabetNNSDomain(i) if err := nnsRegisterDomain(c, nnsCs.Hash, alphaCs.Hash, domain); err != nil { return err } @@ -93,10 +92,6 @@ func updateNNSGroup(c *morphUtil.InitializeContext, nnsHash util.Uint160, pub *k return c.SendCommitteeTx(script, true) } -func getAlphabetNNSDomain(i int) string { - return morphUtil.AlphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs" -} - // wrapRegisterScriptWithPrice wraps a given script with `getPrice`/`setPrice` calls for NNS. // It is intended to be used for a single transaction, and not as a part of other scripts. // It is assumed that script already contains static slot initialization code, the first one diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 7eb41ddc21..ac757428ad 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -2,6 +2,7 @@ package morph import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/proxy" @@ -151,15 +152,6 @@ var ( RunE: dumpNetworkConfig, } - dumpBalancesCmd = &cobra.Command{ - Use: "dump-balances", - Short: "Dump GAS balances", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: dumpBalances, - } - updateContractsCmd = &cobra.Command{ Use: "update-contracts", Short: "Update FrostFS contracts", @@ -230,7 +222,7 @@ func init() { initDumpContractHashesCmd() initDumpNetworkConfigCmd() initSetConfigCmd() - initDumpBalancesCmd() + RootCmd.AddCommand(balance.DumpCmd) initUpdateContractsCmd() initDumpContainersCmd() initRestoreContainersCmd() @@ -301,15 +293,6 @@ func initUpdateContractsCmd() { updateContractsCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) } -func initDumpBalancesCmd() { - RootCmd.AddCommand(dumpBalancesCmd) - dumpBalancesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - dumpBalancesCmd.Flags().BoolP(dumpBalancesStorageFlag, "s", false, "Dump balances of storage nodes from the current netmap") - dumpBalancesCmd.Flags().BoolP(dumpBalancesAlphabetFlag, "a", false, "Dump balances of alphabet contracts") - dumpBalancesCmd.Flags().BoolP(dumpBalancesProxyFlag, "p", false, "Dump balances of the proxy contract") - dumpBalancesCmd.Flags().Bool(dumpBalancesUseScriptHashFlag, false, "Use script-hash format for addresses") -} - func initSetConfigCmd() { RootCmd.AddCommand(setConfig) setConfig.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/util.go b/cmd/frostfs-adm/internal/modules/morph/util/util.go index 4a963d3d89..a6f94049b4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/util.go @@ -8,6 +8,7 @@ import ( "io" "os" "path/filepath" + "strconv" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" @@ -157,3 +158,7 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*Contr } return m, nil } + +func GetAlphabetNNSDomain(i int) string { + return AlphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs" +} From f7a8f51c669968a6db1dd5caa49be36d45b5663a Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 16:58:48 +0300 Subject: [PATCH 0357/1413] [#932] adm: Move command `deposit-notary` to package `notary` Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/generate.go | 18 ++------- .../modules/morph/{ => notary}/notary.go | 21 ++++++---- .../internal/modules/morph/notary/root.go | 28 +++++++++++++ .../internal/modules/morph/root.go | 40 +++++-------------- .../internal/modules/morph/util/const.go | 2 + .../internal/modules/morph/util/util.go | 12 ++++++ 6 files changed, 68 insertions(+), 53 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => notary}/notary.go (86%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/notary/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate.go index 2258eb8324..57c40ec9f5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate.go @@ -11,7 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -139,7 +138,7 @@ func generateStorageCreds(cmd *cobra.Command, _ []string) error { func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error) { // storage wallet path is not part of the config - storageWalletPath, _ := cmd.Flags().GetString(storageWalletFlag) + storageWalletPath, _ := cmd.Flags().GetString(morphUtil.StorageWalletFlag) // wallet address is not part of the config walletAddress, _ := cmd.Flags().GetString(walletAddressFlag) @@ -152,7 +151,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error } } else { if storageWalletPath == "" { - return fmt.Errorf("missing wallet path (use '--%s ')", storageWalletFlag) + return fmt.Errorf("missing wallet path (use '--%s ')", morphUtil.StorageWalletFlag) } var w *wallet.Wallet @@ -190,7 +189,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error gasStr := viper.GetString(gasFlag) - gasAmount, err := parseGASAmount(gasStr) + gasAmount, err := morphUtil.ParseGASAmount(gasStr) if err != nil { return err } @@ -214,14 +213,3 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error return wCtx.AwaitTx() } - -func parseGASAmount(s string) (fixedn.Fixed8, error) { - gasAmount, err := fixedn.Fixed8FromString(s) - if err != nil { - return 0, fmt.Errorf("invalid GAS amount %s: %w", s, err) - } - if gasAmount <= 0 { - return 0, fmt.Errorf("GAS amount must be positive (got %d)", gasAmount) - } - return gasAmount, nil -} diff --git a/cmd/frostfs-adm/internal/modules/morph/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go similarity index 86% rename from cmd/frostfs-adm/internal/modules/morph/notary.go rename to cmd/frostfs-adm/internal/modules/morph/notary/notary.go index d053077059..ecf9331b52 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go @@ -1,4 +1,4 @@ -package morph +package notary import ( "fmt" @@ -21,9 +21,14 @@ import ( "github.com/spf13/viper" ) -// defaultNotaryDepositLifetime is an amount of blocks notary deposit stays valid. -// https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/native/notary.go#L48 -const defaultNotaryDepositLifetime = 5760 +const ( + // defaultNotaryDepositLifetime is an amount of blocks notary deposit stays valid. + // https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/native/notary.go#L48 + defaultNotaryDepositLifetime = 5760 + + walletAccountFlag = "account" + notaryDepositTillFlag = "till" +) func depositNotary(cmd *cobra.Command, _ []string) error { w, err := openWallet(cmd) @@ -55,11 +60,11 @@ func depositNotary(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't unlock account: %v", err) } - gasStr, err := cmd.Flags().GetString(refillGasAmountFlag) + gasStr, err := cmd.Flags().GetString(morphUtil.RefillGasAmountFlag) if err != nil { return err } - gasAmount, err := parseGASAmount(gasStr) + gasAmount, err := morphUtil.ParseGASAmount(gasStr) if err != nil { return err } @@ -121,11 +126,11 @@ func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, } func openWallet(cmd *cobra.Command) (*wallet.Wallet, error) { - p, err := cmd.Flags().GetString(storageWalletFlag) + p, err := cmd.Flags().GetString(morphUtil.StorageWalletFlag) if err != nil { return nil, err } else if p == "" { - return nil, fmt.Errorf("missing wallet path (use '--%s ')", storageWalletFlag) + return nil, fmt.Errorf("missing wallet path (use '--%s ')", morphUtil.StorageWalletFlag) } w, err := wallet.NewWalletFromFile(p) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/root.go b/cmd/frostfs-adm/internal/modules/morph/notary/root.go new file mode 100644 index 0000000000..9a4164c7b3 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/notary/root.go @@ -0,0 +1,28 @@ +package notary + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var DepositCmd = &cobra.Command{ + Use: "deposit-notary", + Short: "Deposit GAS for notary service", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: depositNotary, +} + +func initDepositoryNotaryCmd() { + DepositCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + DepositCmd.Flags().String(util.StorageWalletFlag, "", "Path to storage node wallet") + DepositCmd.Flags().String(walletAccountFlag, "", "Wallet account address") + DepositCmd.Flags().String(util.RefillGasAmountFlag, "", "Amount of GAS to deposit") + DepositCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks") +} + +func init() { + initDepositoryNotaryCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index ac757428ad..fdc9bb32c2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -4,6 +4,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/proxy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" @@ -12,8 +13,8 @@ import ( ) const ( - alphabetSizeFlag = "size" - storageWalletFlag = "storage-wallet" + alphabetSizeFlag = "size" + storageWalletLabelFlag = "label" storageGasCLIFlag = "initial-gas" storageGasConfigFlag = "storage.initial_gas" @@ -35,9 +36,6 @@ const ( containerDumpFlag = "dump" containerContractFlag = "container-contract" containerIDsFlag = "cid" - refillGasAmountFlag = "gas" - walletAccountFlag = "account" - notaryDepositTillFlag = "till" walletAddressFlag = "wallet-address" ) @@ -94,10 +92,10 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(refillGasAmountFlag, cmd.Flags().Lookup(refillGasAmountFlag)) + _ = viper.BindPFlag(util.RefillGasAmountFlag, cmd.Flags().Lookup(util.RefillGasAmountFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { - return refillGas(cmd, refillGasAmountFlag, false) + return refillGas(cmd, util.RefillGasAmountFlag, false) }, } @@ -190,15 +188,6 @@ var ( RunE: listContainers, } - depositNotaryCmd = &cobra.Command{ - Use: "deposit-notary", - Short: "Deposit GAS for notary service", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: depositNotary, - } - netmapCandidatesCmd = &cobra.Command{ Use: "netmap-candidates", Short: "List netmap candidates nodes", @@ -228,7 +217,7 @@ func init() { initRestoreContainersCmd() initListContainersCmd() initRefillGasCmd() - initDepositoryNotaryCmd() + RootCmd.AddCommand(notary.DepositCmd) initNetmapCandidatesCmd() RootCmd.AddCommand(ape.Cmd) @@ -243,23 +232,14 @@ func initNetmapCandidatesCmd() { netmapCandidatesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) } -func initDepositoryNotaryCmd() { - RootCmd.AddCommand(depositNotaryCmd) - depositNotaryCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - depositNotaryCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") - depositNotaryCmd.Flags().String(walletAccountFlag, "", "Wallet account address") - depositNotaryCmd.Flags().String(refillGasAmountFlag, "", "Amount of GAS to deposit") - depositNotaryCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks") -} - func initRefillGasCmd() { RootCmd.AddCommand(refillGasCmd) refillGasCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) refillGasCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - refillGasCmd.Flags().String(storageWalletFlag, "", "Path to storage node wallet") + refillGasCmd.Flags().String(util.StorageWalletFlag, "", "Path to storage node wallet") refillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") - refillGasCmd.Flags().String(refillGasAmountFlag, "", "Additional amount of GAS to transfer") - refillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, storageWalletFlag) + refillGasCmd.Flags().String(util.RefillGasAmountFlag, "", "Additional amount of GAS to transfer") + refillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, util.StorageWalletFlag) } func initListContainersCmd() { @@ -330,7 +310,7 @@ func initGenerateStorageCmd() { RootCmd.AddCommand(generateStorageCmd) generateStorageCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) generateStorageCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - generateStorageCmd.Flags().String(storageWalletFlag, "", "Path to new storage node wallet") + generateStorageCmd.Flags().String(util.StorageWalletFlag, "", "Path to new storage node wallet") generateStorageCmd.Flags().String(storageGasCLIFlag, "", "Initial amount of GAS to transfer") generateStorageCmd.Flags().StringP(storageWalletLabelFlag, "l", "", "Wallet label") } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index f100ebc612..a532eb2ab2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -23,6 +23,8 @@ const ( ContractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" EpochDurationInitFlag = "network.epoch_duration" MaxObjectSizeInitFlag = "network.max_object_size" + RefillGasAmountFlag = "gas" + StorageWalletFlag = "storage-wallet" SingleAccountName = "single" CommitteeAccountName = "committee" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/util.go b/cmd/frostfs-adm/internal/modules/morph/util/util.go index a6f94049b4..1fd9695c3a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/util.go @@ -15,6 +15,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/viper" @@ -162,3 +163,14 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*Contr func GetAlphabetNNSDomain(i int) string { return AlphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs" } + +func ParseGASAmount(s string) (fixedn.Fixed8, error) { + gasAmount, err := fixedn.Fixed8FromString(s) + if err != nil { + return 0, fmt.Errorf("invalid GAS amount %s: %w", s, err) + } + if gasAmount <= 0 { + return 0, fmt.Errorf("GAS amount must be positive (got %d)", gasAmount) + } + return gasAmount, nil +} From be15eab82a66d0d10989658231a805c2a7eaaae3 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 17:28:10 +0300 Subject: [PATCH 0358/1413] [#932] adm: Move `dump/set-config` to package `config` Signed-off-by: Anton Nikiforov --- .../modules/morph/{ => config}/config.go | 12 +-- .../internal/modules/morph/config/root.go | 46 +++++++++++ .../modules/morph/initialize_deploy.go | 4 +- .../internal/modules/morph/initialize_test.go | 5 +- .../internal/modules/morph/netmap_util.go | 45 ----------- .../internal/modules/morph/root.go | 77 +++++-------------- .../internal/modules/morph/util/const.go | 28 ++++--- .../internal/modules/morph/util/netmap.go | 49 ++++++++++++ 8 files changed, 142 insertions(+), 124 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => config}/config.go (94%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/config/root.go delete mode 100644 cmd/frostfs-adm/internal/modules/morph/netmap_util.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/netmap.go diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go similarity index 94% rename from cmd/frostfs-adm/internal/modules/morph/config.go rename to cmd/frostfs-adm/internal/modules/morph/config/config.go index 2cff322d18..b1ed1cc219 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -1,4 +1,4 @@ -package morph +package config import ( "bytes" @@ -51,7 +51,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { buf := bytes.NewBuffer(nil) tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) - m, err := parseConfigFromNetmapContract(arr) + m, err := util.ParseConfigFromNetmapContract(arr) if err != nil { return err } @@ -66,7 +66,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%d (int)\n", k, n))) case netmap.HomomorphicHashingDisabledKey, netmap.MaintenanceModeAllowedConfig: if len(v) == 0 || len(v) > 1 { - return invalidConfigValueErr(k) + return util.InvalidConfigValueErr(k) } _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%t (bool)\n", k, v[0] == 1))) default: @@ -80,7 +80,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { return nil } -func setConfigCmd(cmd *cobra.Command, args []string) error { +func SetConfigCmd(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errors.New("empty config pairs") } @@ -162,7 +162,3 @@ func parseConfigPair(kvStr string, force bool) (key string, val any, err error) return } - -func invalidConfigValueErr(key string) error { - return fmt.Errorf("invalid %s config value from netmap contract", key) -} diff --git a/cmd/frostfs-adm/internal/modules/morph/config/root.go b/cmd/frostfs-adm/internal/modules/morph/config/root.go new file mode 100644 index 0000000000..4b53662269 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/config/root.go @@ -0,0 +1,46 @@ +package config + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + SetCmd = &cobra.Command{ + Use: "set-config key1=val1 [key2=val2 ...]", + DisableFlagsInUseLine: true, + Short: "Add/update global config value in the FrostFS network", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + Args: cobra.MinimumNArgs(1), + RunE: SetConfigCmd, + } + + DumpCmd = &cobra.Command{ + Use: "dump-config", + Short: "Dump FrostFS network config", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: dumpNetworkConfig, + } +) + +func initSetConfigCmd() { + SetCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + SetCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + SetCmd.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") + SetCmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") +} + +func initDumpNetworkConfigCmd() { + DumpCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) +} + +func init() { + initSetConfigCmd() + initDumpNetworkConfigCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 50427c93fc..3a78f6042c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -372,7 +372,7 @@ func getContractDeployData(c *morphUtil.InitializeContext, ctrName string, keysP items = append(items, c.Contracts[morphUtil.ProxyContract].Hash) } case morphUtil.NetmapContract: - md := getDefaultNetmapContractConfigMap() + md := morphUtil.GetDefaultNetmapContractConfigMap() if method == updateMethodName { if err := mergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil { return nil, err @@ -450,7 +450,7 @@ func mergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error { if err != nil { return err } - m, err := parseConfigFromNetmapContract(arr) + m, err := morphUtil.ParseConfigFromNetmapContract(arr) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index e9571e50ca..f0ad8044c9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + cmdConfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" @@ -75,8 +76,8 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, forceNewEpochCmd(forceNewEpoch, nil)) }) t.Run("set-config", func(t *testing.T) { - require.NoError(t, setConfig.Flags().Set(util.LocalDumpFlag, dumpPath)) - require.NoError(t, setConfigCmd(setConfig, []string{"MaintenanceModeAllowed=true"})) + require.NoError(t, cmdConfig.SetCmd.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, cmdConfig.SetConfigCmd(cmdConfig.SetCmd, []string{"MaintenanceModeAllowed=true"})) }) t.Run("set-policy", func(t *testing.T) { require.NoError(t, policy.Set.Flags().Set(util.LocalDumpFlag, dumpPath)) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_util.go b/cmd/frostfs-adm/internal/modules/morph/netmap_util.go deleted file mode 100644 index 3cf853ccac..0000000000 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_util.go +++ /dev/null @@ -1,45 +0,0 @@ -package morph - -import ( - "errors" - - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/spf13/viper" -) - -func getDefaultNetmapContractConfigMap() map[string]any { - m := make(map[string]any) - m[netmap.EpochDurationConfig] = viper.GetInt64(util.EpochDurationInitFlag) - m[netmap.MaxObjectSizeConfig] = viper.GetInt64(util.MaxObjectSizeInitFlag) - m[netmap.ContainerFeeConfig] = viper.GetInt64(containerFeeInitFlag) - m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(containerAliasFeeInitFlag) - m[netmap.IrCandidateFeeConfig] = viper.GetInt64(candidateFeeInitFlag) - m[netmap.WithdrawFeeConfig] = viper.GetInt64(withdrawFeeInitFlag) - m[netmap.HomomorphicHashingDisabledKey] = viper.GetBool(homomorphicHashDisabledInitFlag) - m[netmap.MaintenanceModeAllowedConfig] = viper.GetBool(maintenanceModeAllowedInitFlag) - return m -} - -func parseConfigFromNetmapContract(arr []stackitem.Item) (map[string][]byte, error) { - m := make(map[string][]byte, len(arr)) - for _, param := range arr { - tuple, ok := param.Value().([]stackitem.Item) - if !ok || len(tuple) != 2 { - return nil, errors.New("invalid ListConfig response from netmap contract") - } - - k, err := tuple[0].TryBytes() - if err != nil { - return nil, errors.New("invalid config key from netmap contract") - } - - v, err := tuple[1].TryBytes() - if err != nil { - return nil, invalidConfigValueErr(string(k)) - } - m[string(k)] = v - } - return m, nil -} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index fdc9bb32c2..f0e47bc74f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -3,6 +3,7 @@ package morph import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/balance" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" @@ -21,21 +22,19 @@ const ( maxObjectSizeCLIFlag = "max-object-size" - epochDurationCLIFlag = "epoch-duration" - containerFeeInitFlag = "network.fee.container" - containerAliasFeeInitFlag = "network.fee.container_alias" - containerFeeCLIFlag = "container-fee" - containerAliasFeeCLIFlag = "container-alias-fee" - candidateFeeInitFlag = "network.fee.candidate" - candidateFeeCLIFlag = "candidate-fee" - homomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" - maintenanceModeAllowedInitFlag = "network.maintenance_mode_allowed" - homomorphicHashDisabledCLIFlag = "homomorphic-disabled" - withdrawFeeInitFlag = "network.fee.withdraw" - withdrawFeeCLIFlag = "withdraw-fee" - containerDumpFlag = "dump" - containerContractFlag = "container-contract" - containerIDsFlag = "cid" + epochDurationCLIFlag = "epoch-duration" + + containerFeeCLIFlag = "container-fee" + containerAliasFeeCLIFlag = "container-alias-fee" + + candidateFeeCLIFlag = "candidate-fee" + + homomorphicHashDisabledCLIFlag = "homomorphic-disabled" + + withdrawFeeCLIFlag = "withdraw-fee" + containerDumpFlag = "dump" + containerContractFlag = "container-contract" + containerIDsFlag = "cid" walletAddressFlag = "wallet-address" ) @@ -65,11 +64,11 @@ var ( _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(util.EpochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) _ = viper.BindPFlag(util.MaxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) - _ = viper.BindPFlag(homomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) - _ = viper.BindPFlag(candidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) - _ = viper.BindPFlag(containerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) - _ = viper.BindPFlag(containerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) - _ = viper.BindPFlag(withdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) + _ = viper.BindPFlag(util.HomomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) + _ = viper.BindPFlag(util.CandidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) + _ = viper.BindPFlag(util.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) + _ = viper.BindPFlag(util.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) + _ = viper.BindPFlag(util.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) _ = viper.BindPFlag(util.ProtoConfigPath, cmd.Flags().Lookup(util.ProtoConfigPath)) }, RunE: initializeSideChainCmd, @@ -120,18 +119,6 @@ var ( RunE: removeNodesCmd, } - setConfig = &cobra.Command{ - Use: "set-config key1=val1 [key2=val2 ...]", - DisableFlagsInUseLine: true, - Short: "Add/update global config value in the FrostFS network", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - Args: cobra.MinimumNArgs(1), - RunE: setConfigCmd, - } - dumpContractHashesCmd = &cobra.Command{ Use: "dump-hashes", Short: "Dump deployed contract hashes", @@ -141,15 +128,6 @@ var ( RunE: dumpContractHashes, } - dumpNetworkConfigCmd = &cobra.Command{ - Use: "dump-config", - Short: "Dump FrostFS network config", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: dumpNetworkConfig, - } - updateContractsCmd = &cobra.Command{ Use: "update-contracts", Short: "Update FrostFS contracts", @@ -209,8 +187,8 @@ func init() { RootCmd.AddCommand(policy.Set) RootCmd.AddCommand(policy.Dump) initDumpContractHashesCmd() - initDumpNetworkConfigCmd() - initSetConfigCmd() + RootCmd.AddCommand(config.SetCmd) + RootCmd.AddCommand(config.DumpCmd) RootCmd.AddCommand(balance.DumpCmd) initUpdateContractsCmd() initDumpContainersCmd() @@ -273,19 +251,6 @@ func initUpdateContractsCmd() { updateContractsCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) } -func initSetConfigCmd() { - RootCmd.AddCommand(setConfig) - setConfig.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - setConfig.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - setConfig.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") - setConfig.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") -} - -func initDumpNetworkConfigCmd() { - RootCmd.AddCommand(dumpNetworkConfigCmd) - dumpNetworkConfigCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) -} - func initDumpContractHashesCmd() { RootCmd.AddCommand(dumpContractHashesCmd) dumpContractHashesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index a532eb2ab2..c4a674bd65 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -11,20 +11,26 @@ const ( // See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10 MaxAlphabetNodes = 22 - EndpointFlag = "rpc-endpoint" - EndpointFlagDesc = "N3 RPC node endpoint" - EndpointFlagShort = "r" - AlphabetWalletsFlag = "alphabet-wallets" - AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" - LocalDumpFlag = "local-dump" - ContractsInitFlag = "contracts" + EndpointFlag = "rpc-endpoint" + EndpointFlagDesc = "N3 RPC node endpoint" + EndpointFlagShort = "r" + AlphabetWalletsFlag = "alphabet-wallets" + AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" + LocalDumpFlag = "local-dump" + ContractsInitFlag = "contracts" ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" ContractsURLFlag = "contracts-url" ContractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" - EpochDurationInitFlag = "network.epoch_duration" - MaxObjectSizeInitFlag = "network.max_object_size" - RefillGasAmountFlag = "gas" - StorageWalletFlag = "storage-wallet" + EpochDurationInitFlag = "network.epoch_duration" + MaxObjectSizeInitFlag = "network.max_object_size" + RefillGasAmountFlag = "gas" + StorageWalletFlag = "storage-wallet" + ContainerFeeInitFlag = "network.fee.container" + ContainerAliasFeeInitFlag = "network.fee.container_alias" + CandidateFeeInitFlag = "network.fee.candidate" + WithdrawFeeInitFlag = "network.fee.withdraw" + MaintenanceModeAllowedInitFlag = "network.maintenance_mode_allowed" + HomomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" SingleAccountName = "single" CommitteeAccountName = "committee" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go new file mode 100644 index 0000000000..c9dc2e3b59 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go @@ -0,0 +1,49 @@ +package util + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/spf13/viper" +) + +func GetDefaultNetmapContractConfigMap() map[string]any { + m := make(map[string]any) + m[netmap.EpochDurationConfig] = viper.GetInt64(EpochDurationInitFlag) + m[netmap.MaxObjectSizeConfig] = viper.GetInt64(MaxObjectSizeInitFlag) + m[netmap.ContainerFeeConfig] = viper.GetInt64(ContainerFeeInitFlag) + m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(ContainerAliasFeeInitFlag) + m[netmap.IrCandidateFeeConfig] = viper.GetInt64(CandidateFeeInitFlag) + m[netmap.WithdrawFeeConfig] = viper.GetInt64(WithdrawFeeInitFlag) + m[netmap.HomomorphicHashingDisabledKey] = viper.GetBool(HomomorphicHashDisabledInitFlag) + m[netmap.MaintenanceModeAllowedConfig] = viper.GetBool(MaintenanceModeAllowedInitFlag) + return m +} + +func ParseConfigFromNetmapContract(arr []stackitem.Item) (map[string][]byte, error) { + m := make(map[string][]byte, len(arr)) + for _, param := range arr { + tuple, ok := param.Value().([]stackitem.Item) + if !ok || len(tuple) != 2 { + return nil, errors.New("invalid ListConfig response from netmap contract") + } + + k, err := tuple[0].TryBytes() + if err != nil { + return nil, errors.New("invalid config key from netmap contract") + } + + v, err := tuple[1].TryBytes() + if err != nil { + return nil, InvalidConfigValueErr(string(k)) + } + m[string(k)] = v + } + return m, nil +} + +func InvalidConfigValueErr(key string) error { + return fmt.Errorf("invalid %s config value from netmap contract", key) +} From 36fd6c663c6030fb283f540f2d7c31dab878aeef Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 17:36:26 +0300 Subject: [PATCH 0359/1413] [#932] adm: Move `dump/restore/list-containers` to package `container` Signed-off-by: Anton Nikiforov --- .../morph/{ => container}/container.go | 2 +- .../internal/modules/morph/container/root.go | 68 +++++++++++++++++++ .../internal/modules/morph/root.go | 62 ++--------------- 3 files changed, 74 insertions(+), 58 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => container}/container.go (99%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/container/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/container.go rename to cmd/frostfs-adm/internal/modules/morph/container/container.go index b18fa79ed3..46d4921fef 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -1,4 +1,4 @@ -package morph +package container import ( "encoding/json" diff --git a/cmd/frostfs-adm/internal/modules/morph/container/root.go b/cmd/frostfs-adm/internal/modules/morph/container/root.go new file mode 100644 index 0000000000..4cae8cf4f0 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/container/root.go @@ -0,0 +1,68 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + containerDumpFlag = "dump" + containerContractFlag = "container-contract" + containerIDsFlag = "cid" +) + +var ( + DumpCmd = &cobra.Command{ + Use: "dump-containers", + Short: "Dump FrostFS containers to file", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: dumpContainers, + } + + RestoreCmd = &cobra.Command{ + Use: "restore-containers", + Short: "Restore FrostFS containers from file", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: restoreContainers, + } + + ListCmd = &cobra.Command{ + Use: "list-containers", + Short: "List FrostFS containers", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: listContainers, + } +) + +func initListContainersCmd() { + ListCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + ListCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") +} + +func initRestoreContainersCmd() { + RestoreCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + RestoreCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + RestoreCmd.Flags().String(containerDumpFlag, "", "File to restore containers from") + RestoreCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore") +} + +func initDumpContainersCmd() { + DumpCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + DumpCmd.Flags().String(containerDumpFlag, "", "File where to save dumped containers") + DumpCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") + DumpCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to dump") +} + +func init() { + initDumpContainersCmd() + initRestoreContainersCmd() + initListContainersCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index f0e47bc74f..98e72fa517 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -4,6 +4,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/container" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" @@ -31,10 +32,7 @@ const ( homomorphicHashDisabledCLIFlag = "homomorphic-disabled" - withdrawFeeCLIFlag = "withdraw-fee" - containerDumpFlag = "dump" - containerContractFlag = "container-contract" - containerIDsFlag = "cid" + withdrawFeeCLIFlag = "withdraw-fee" walletAddressFlag = "wallet-address" ) @@ -138,34 +136,6 @@ var ( RunE: updateContracts, } - dumpContainersCmd = &cobra.Command{ - Use: "dump-containers", - Short: "Dump FrostFS containers to file", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: dumpContainers, - } - - restoreContainersCmd = &cobra.Command{ - Use: "restore-containers", - Short: "Restore FrostFS containers from file", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: restoreContainers, - } - - listContainersCmd = &cobra.Command{ - Use: "list-containers", - Short: "List FrostFS containers", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: listContainers, - } - netmapCandidatesCmd = &cobra.Command{ Use: "netmap-candidates", Short: "List netmap candidates nodes", @@ -191,9 +161,9 @@ func init() { RootCmd.AddCommand(config.DumpCmd) RootCmd.AddCommand(balance.DumpCmd) initUpdateContractsCmd() - initDumpContainersCmd() - initRestoreContainersCmd() - initListContainersCmd() + RootCmd.AddCommand(container.ListCmd) + RootCmd.AddCommand(container.RestoreCmd) + RootCmd.AddCommand(container.DumpCmd) initRefillGasCmd() RootCmd.AddCommand(notary.DepositCmd) initNetmapCandidatesCmd() @@ -220,28 +190,6 @@ func initRefillGasCmd() { refillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, util.StorageWalletFlag) } -func initListContainersCmd() { - RootCmd.AddCommand(listContainersCmd) - listContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - listContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") -} - -func initRestoreContainersCmd() { - RootCmd.AddCommand(restoreContainersCmd) - restoreContainersCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - restoreContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - restoreContainersCmd.Flags().String(containerDumpFlag, "", "File to restore containers from") - restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore") -} - -func initDumpContainersCmd() { - RootCmd.AddCommand(dumpContainersCmd) - dumpContainersCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - dumpContainersCmd.Flags().String(containerDumpFlag, "", "File where to save dumped containers") - dumpContainersCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") - dumpContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to dump") -} - func initUpdateContractsCmd() { RootCmd.AddCommand(updateContractsCmd) updateContractsCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) From 9690bd02aad0c767740890fd4b5d0f1ef82bed39 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 17:41:44 +0300 Subject: [PATCH 0360/1413] [#932] adm: Move `netmap-candidates` to package `netmap` Signed-off-by: Anton Nikiforov --- .../morph/{ => netmap}/netmap_candidates.go | 2 +- .../internal/modules/morph/netmap/root.go | 25 +++++++++++++++++++ .../internal/modules/morph/root.go | 18 ++----------- 3 files changed, 28 insertions(+), 17 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => netmap}/netmap_candidates.go (98%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/netmap/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go similarity index 98% rename from cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go rename to cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go index c09ba8b8de..f105fe9113 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go @@ -1,4 +1,4 @@ -package morph +package netmap import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go new file mode 100644 index 0000000000..b8f9a61da5 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go @@ -0,0 +1,25 @@ +package netmap + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var CandidatesCmd = &cobra.Command{ + Use: "netmap-candidates", + Short: "List netmap candidates nodes", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + }, + Run: listNetmapCandidatesNodes, +} + +func initNetmapCandidatesCmd() { + CandidatesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) +} + +func init() { + initNetmapCandidatesCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 98e72fa517..908c4183f9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/container" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/proxy" @@ -135,16 +136,6 @@ var ( }, RunE: updateContracts, } - - netmapCandidatesCmd = &cobra.Command{ - Use: "netmap-candidates", - Short: "List netmap candidates nodes", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - }, - Run: listNetmapCandidatesNodes, - } ) func init() { @@ -166,7 +157,7 @@ func init() { RootCmd.AddCommand(container.DumpCmd) initRefillGasCmd() RootCmd.AddCommand(notary.DepositCmd) - initNetmapCandidatesCmd() + RootCmd.AddCommand(netmap.CandidatesCmd) RootCmd.AddCommand(ape.Cmd) RootCmd.AddCommand(proxy.AddAccountCmd) @@ -175,11 +166,6 @@ func init() { RootCmd.AddCommand(frostfsid.Cmd) } -func initNetmapCandidatesCmd() { - RootCmd.AddCommand(netmapCandidatesCmd) - netmapCandidatesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) -} - func initRefillGasCmd() { RootCmd.AddCommand(refillGasCmd) refillGasCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) From ce4254798032d3cc616cf05f2925a69f9a319a2c Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 17:53:00 +0300 Subject: [PATCH 0361/1413] [#932] adm: Move `remove-nodes` to package `node` Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/epoch.go | 22 +-------------- .../internal/modules/morph/initialize_test.go | 5 ++-- .../morph/{remove_node.go => node/remove.go} | 6 ++-- .../internal/modules/morph/node/root.go | 28 +++++++++++++++++++ .../internal/modules/morph/root.go | 21 ++------------ .../internal/modules/morph/util/netmap.go | 20 +++++++++++++ 6 files changed, 57 insertions(+), 45 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{remove_node.go => node/remove.go} (92%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/node/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/epoch.go index 851f757b05..69d4d31517 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/epoch.go @@ -1,17 +1,12 @@ package morph import ( - "errors" "fmt" "strings" util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -34,7 +29,7 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { } bw := io.NewBufBinWriter() - if err := emitNewEpochCall(bw, wCtx, nmHash); err != nil { + if err := util2.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { return err } @@ -47,18 +42,3 @@ func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { } return err } - -func emitNewEpochCall(bw *io.BufBinWriter, wCtx *util2.InitializeContext, nmHash util.Uint160) error { - curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch")) - if err != nil { - return errors.New("can't fetch current epoch from the netmap contract") - } - - newEpoch := curr + 1 - wCtx.Command.Printf("Current epoch: %d, increase to %d.\n", curr, newEpoch) - - // In NeoFS this is done via Notary contract. Here, however, we can form the - // transaction locally. - emit.AppCall(bw.BinWriter, nmHash, "newEpoch", callflag.All, newEpoch) - return bw.Err -} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index f0ad8044c9..02af6458ce 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -10,6 +10,7 @@ import ( "time" cmdConfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" @@ -88,8 +89,8 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, err) pub := hex.EncodeToString(pk.PublicKey().Bytes()) - require.NoError(t, removeNodes.Flags().Set(util.LocalDumpFlag, dumpPath)) - require.NoError(t, removeNodesCmd(removeNodes, []string{pub})) + require.NoError(t, node.RemoveCmd.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, node.RemoveNodesCmd(node.RemoveCmd, []string{pub})) }) } diff --git a/cmd/frostfs-adm/internal/modules/morph/remove_node.go b/cmd/frostfs-adm/internal/modules/morph/node/remove.go similarity index 92% rename from cmd/frostfs-adm/internal/modules/morph/remove_node.go rename to cmd/frostfs-adm/internal/modules/morph/node/remove.go index e63a5dee93..0e305c1f4e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/remove_node.go +++ b/cmd/frostfs-adm/internal/modules/morph/node/remove.go @@ -1,4 +1,4 @@ -package morph +package node import ( "errors" @@ -15,7 +15,7 @@ import ( "github.com/spf13/viper" ) -func removeNodesCmd(cmd *cobra.Command, args []string) error { +func RemoveNodesCmd(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errors.New("at least one node key must be provided") } @@ -52,7 +52,7 @@ func removeNodesCmd(cmd *cobra.Command, args []string) error { int64(netmapcontract.NodeStateOffline), nodeKeys[i].Bytes()) } - if err := emitNewEpochCall(bw, wCtx, nmHash); err != nil { + if err := util.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/node/root.go b/cmd/frostfs-adm/internal/modules/morph/node/root.go new file mode 100644 index 0000000000..e301a1bc34 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/node/root.go @@ -0,0 +1,28 @@ +package node + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var RemoveCmd = &cobra.Command{ + Use: "remove-nodes key1 [key2 [...]]", + Short: "Remove storage nodes from the netmap", + Long: `Move nodes to the Offline state in the candidates list and tick an epoch to update the netmap`, + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: RemoveNodesCmd, +} + +func initRemoveNodesCmd() { + RemoveCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + RemoveCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + RemoveCmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") +} + +func init() { + initRemoveNodesCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 908c4183f9..23c413bfff 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/container" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/proxy" @@ -107,17 +108,6 @@ var ( RunE: forceNewEpochCmd, } - removeNodes = &cobra.Command{ - Use: "remove-nodes key1 [key2 [...]]", - Short: "Remove storage nodes from the netmap", - Long: `Move nodes to the Offline state in the candidates list and tick an epoch to update the netmap`, - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: removeNodesCmd, - } - dumpContractHashesCmd = &cobra.Command{ Use: "dump-hashes", Short: "Dump deployed contract hashes", @@ -144,7 +134,7 @@ func init() { initDeployCmd() initGenerateStorageCmd() initForceNewEpochCmd() - initRemoveNodesCmd() + RootCmd.AddCommand(node.RemoveCmd) RootCmd.AddCommand(policy.Set) RootCmd.AddCommand(policy.Dump) initDumpContractHashesCmd() @@ -191,13 +181,6 @@ func initDumpContractHashesCmd() { dumpContractHashesCmd.Flags().String(customZoneFlag, "", "Custom zone to search.") } -func initRemoveNodesCmd() { - RootCmd.AddCommand(removeNodes) - removeNodes.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - removeNodes.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - removeNodes.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") -} - func initForceNewEpochCmd() { RootCmd.AddCommand(forceNewEpoch) forceNewEpoch.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go index c9dc2e3b59..34c527d0b2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go @@ -5,6 +5,11 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/spf13/viper" ) @@ -47,3 +52,18 @@ func ParseConfigFromNetmapContract(arr []stackitem.Item) (map[string][]byte, err func InvalidConfigValueErr(key string) error { return fmt.Errorf("invalid %s config value from netmap contract", key) } + +func EmitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160) error { + curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch")) + if err != nil { + return errors.New("can't fetch current epoch from the netmap contract") + } + + newEpoch := curr + 1 + wCtx.Command.Printf("Current epoch: %d, increase to %d.\n", curr, newEpoch) + + // In NeoFS this is done via Notary contract. Here, however, we can form the + // transaction locally. + emit.AppCall(bw.BinWriter, nmHash, "newEpoch", callflag.All, newEpoch) + return bw.Err +} From 9b65f1595aef0ebd43fedf419a3a8b96acfb2132 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 1 Feb 2024 17:59:53 +0300 Subject: [PATCH 0362/1413] [#932] adm: Move `force-new-epoch` to package `netmap` Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/initialize_test.go | 5 +-- .../modules/morph/{ => netmap}/epoch.go | 4 +-- .../internal/modules/morph/netmap/root.go | 36 ++++++++++++++----- .../internal/modules/morph/root.go | 19 +--------- 4 files changed, 33 insertions(+), 31 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => netmap}/epoch.go (93%) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index 02af6458ce..8b0fddf3da 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -10,6 +10,7 @@ import ( "time" cmdConfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" @@ -73,8 +74,8 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, initializeSideChainCmd(initCmd, nil)) t.Run("force-new-epoch", func(t *testing.T) { - require.NoError(t, forceNewEpoch.Flags().Set(util.LocalDumpFlag, dumpPath)) - require.NoError(t, forceNewEpochCmd(forceNewEpoch, nil)) + require.NoError(t, netmap.ForceNewEpoch.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, netmap.ForceNewEpochCmd(netmap.ForceNewEpoch, nil)) }) t.Run("set-config", func(t *testing.T) { require.NoError(t, cmdConfig.SetCmd.Flags().Set(util.LocalDumpFlag, dumpPath)) diff --git a/cmd/frostfs-adm/internal/modules/morph/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go similarity index 93% rename from cmd/frostfs-adm/internal/modules/morph/epoch.go rename to cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index 69d4d31517..4d64f190f7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -1,4 +1,4 @@ -package morph +package netmap import ( "fmt" @@ -11,7 +11,7 @@ import ( "github.com/spf13/viper" ) -func forceNewEpochCmd(cmd *cobra.Command, _ []string) error { +func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { wCtx, err := util2.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go index b8f9a61da5..888b994e97 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go @@ -6,20 +6,38 @@ import ( "github.com/spf13/viper" ) -var CandidatesCmd = &cobra.Command{ - Use: "netmap-candidates", - Short: "List netmap candidates nodes", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - }, - Run: listNetmapCandidatesNodes, -} +var ( + CandidatesCmd = &cobra.Command{ + Use: "netmap-candidates", + Short: "List netmap candidates nodes", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + }, + Run: listNetmapCandidatesNodes, + } + ForceNewEpoch = &cobra.Command{ + Use: "force-new-epoch", + Short: "Create new FrostFS epoch event in the side chain", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: ForceNewEpochCmd, + } +) func initNetmapCandidatesCmd() { CandidatesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) } +func initForceNewEpochCmd() { + ForceNewEpoch.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + ForceNewEpoch.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + ForceNewEpoch.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") +} + func init() { initNetmapCandidatesCmd() + initForceNewEpochCmd() } diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 23c413bfff..6546b6dee0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -98,16 +98,6 @@ var ( }, } - forceNewEpoch = &cobra.Command{ - Use: "force-new-epoch", - Short: "Create new FrostFS epoch event in the side chain", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: forceNewEpochCmd, - } - dumpContractHashesCmd = &cobra.Command{ Use: "dump-hashes", Short: "Dump deployed contract hashes", @@ -133,7 +123,7 @@ func init() { initInitCmd() initDeployCmd() initGenerateStorageCmd() - initForceNewEpochCmd() + RootCmd.AddCommand(netmap.ForceNewEpoch) RootCmd.AddCommand(node.RemoveCmd) RootCmd.AddCommand(policy.Set) RootCmd.AddCommand(policy.Dump) @@ -181,13 +171,6 @@ func initDumpContractHashesCmd() { dumpContractHashesCmd.Flags().String(customZoneFlag, "", "Custom zone to search.") } -func initForceNewEpochCmd() { - RootCmd.AddCommand(forceNewEpoch) - forceNewEpoch.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - forceNewEpoch.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - forceNewEpoch.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") -} - func initGenerateStorageCmd() { RootCmd.AddCommand(generateStorageCmd) generateStorageCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) From e2557b2f0b23b0c3163b274d524f9cefb74e77b0 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 09:06:24 +0300 Subject: [PATCH 0363/1413] [#932] adm: Move `dump-hashes` to package `contract` Signed-off-by: Anton Nikiforov --- .../morph/{ => contract}/dump_hashes.go | 4 +-- .../internal/modules/morph/contract/root.go | 25 +++++++++++++++++++ .../internal/modules/morph/deploy.go | 5 ++-- .../internal/modules/morph/root.go | 18 ++----------- .../internal/modules/morph/util/const.go | 1 + 5 files changed, 32 insertions(+), 21 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => contract}/dump_hashes.go (98%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/contract/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go similarity index 98% rename from cmd/frostfs-adm/internal/modules/morph/dump_hashes.go rename to cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index c92c256903..8f7fbe6e0b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -1,4 +1,4 @@ -package morph +package contract import ( "bytes" @@ -45,7 +45,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return err } - zone, _ := cmd.Flags().GetString(customZoneFlag) + zone, _ := cmd.Flags().GetString(morphUtil.CustomZoneFlag) if zone != "" { return dumpCustomZoneHashes(cmd, cs.Hash, zone, c) } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/root.go b/cmd/frostfs-adm/internal/modules/morph/contract/root.go new file mode 100644 index 0000000000..8decfd4a38 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/contract/root.go @@ -0,0 +1,25 @@ +package contract + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var DumpHashesCmd = &cobra.Command{ + Use: "dump-hashes", + Short: "Dump deployed contract hashes", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: dumpContractHashes, +} + +func initDumpContractHashesCmd() { + DumpHashesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + DumpHashesCmd.Flags().String(util.CustomZoneFlag, "", "Custom zone to search.") +} + +func init() { + initDumpContractHashesCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index e6fdbbcf73..a312b34cd1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -24,7 +24,6 @@ import ( const ( contractPathFlag = "contract" updateFlag = "update" - customZoneFlag = "domain" ) var deployCmd = &cobra.Command{ @@ -55,7 +54,7 @@ func init() { _ = deployCmd.MarkFlagFilename(contractPathFlag) ff.Bool(updateFlag, false, "Update an existing contract") - ff.String(customZoneFlag, "frostfs", "Custom zone for NNS") + ff.String(util.CustomZoneFlag, "frostfs", "Custom zone for NNS") } func deployContractCmd(cmd *cobra.Command, args []string) error { @@ -85,7 +84,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { callHash := management.Hash method := deployMethodName - zone, _ := cmd.Flags().GetString(customZoneFlag) + zone, _ := cmd.Flags().GetString(util.CustomZoneFlag) domain := ctrName + "." + zone isUpdate, _ := cmd.Flags().GetBool(updateFlag) if isUpdate { diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 6546b6dee0..66dd77556e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/contract" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" @@ -98,15 +99,6 @@ var ( }, } - dumpContractHashesCmd = &cobra.Command{ - Use: "dump-hashes", - Short: "Dump deployed contract hashes", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: dumpContractHashes, - } - updateContractsCmd = &cobra.Command{ Use: "update-contracts", Short: "Update FrostFS contracts", @@ -127,7 +119,7 @@ func init() { RootCmd.AddCommand(node.RemoveCmd) RootCmd.AddCommand(policy.Set) RootCmd.AddCommand(policy.Dump) - initDumpContractHashesCmd() + RootCmd.AddCommand(contract.DumpHashesCmd) RootCmd.AddCommand(config.SetCmd) RootCmd.AddCommand(config.DumpCmd) RootCmd.AddCommand(balance.DumpCmd) @@ -165,12 +157,6 @@ func initUpdateContractsCmd() { updateContractsCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) } -func initDumpContractHashesCmd() { - RootCmd.AddCommand(dumpContractHashesCmd) - dumpContractHashesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - dumpContractHashesCmd.Flags().String(customZoneFlag, "", "Custom zone to search.") -} - func initGenerateStorageCmd() { RootCmd.AddCommand(generateStorageCmd) generateStorageCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index c4a674bd65..cdf1cd443a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -31,6 +31,7 @@ const ( WithdrawFeeInitFlag = "network.fee.withdraw" MaintenanceModeAllowedInitFlag = "network.maintenance_mode_allowed" HomomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" + CustomZoneFlag = "domain" SingleAccountName = "single" CommitteeAccountName = "committee" From 76343f19e569f01949396a7a442f0004970cd67a Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 09:49:03 +0300 Subject: [PATCH 0364/1413] [#932] adm: Move `update-contracts` to package `contract` Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/contract/root.go | 36 +- .../internal/modules/morph/contract/update.go | 196 +++++++++ .../internal/modules/morph/deploy.go | 4 +- .../modules/morph/frostfsid/frostfsid.go | 1 - .../modules/morph/frostfsid/frostfsid_util.go | 24 -- .../morph/frostfsid/frostfsid_util_test.go | 7 +- .../internal/modules/morph/initialize.go | 2 +- .../modules/morph/initialize_deploy.go | 401 +----------------- .../internal/modules/morph/initialize_nns.go | 3 - .../internal/modules/morph/root.go | 21 +- .../internal/modules/morph/update.go | 22 - .../internal/modules/morph/util/const.go | 3 + .../internal/modules/morph/util/contract.go | 169 ++++++++ .../internal/modules/morph/util/frostfsid.go | 35 ++ .../modules/morph/{ => util}/group.go | 5 +- .../internal/modules/morph/util/netmap.go | 50 +++ 16 files changed, 498 insertions(+), 481 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/contract/update.go delete mode 100644 cmd/frostfs-adm/internal/modules/morph/update.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/contract.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/util/frostfsid.go rename cmd/frostfs-adm/internal/modules/morph/{ => util}/group.go (77%) diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/root.go b/cmd/frostfs-adm/internal/modules/morph/contract/root.go index 8decfd4a38..71feb31cd5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/root.go @@ -6,20 +6,40 @@ import ( "github.com/spf13/viper" ) -var DumpHashesCmd = &cobra.Command{ - Use: "dump-hashes", - Short: "Dump deployed contract hashes", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: dumpContractHashes, -} +var ( + DumpHashesCmd = &cobra.Command{ + Use: "dump-hashes", + Short: "Dump deployed contract hashes", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: dumpContractHashes, + } + UpdateCmd = &cobra.Command{ + Use: "update-contracts", + Short: "Update FrostFS contracts", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: updateContracts, + } +) func initDumpContractHashesCmd() { DumpHashesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) DumpHashesCmd.Flags().String(util.CustomZoneFlag, "", "Custom zone to search.") } +func initUpdateContractsCmd() { + UpdateCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + UpdateCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + UpdateCmd.Flags().String(util.ContractsInitFlag, "", util.ContractsInitFlagDesc) + UpdateCmd.Flags().String(util.ContractsURLFlag, "", util.ContractsURLFlagDesc) + UpdateCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) +} + func init() { initDumpContractHashesCmd() + initUpdateContractsCmd() } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/update.go b/cmd/frostfs-adm/internal/modules/morph/contract/update.go new file mode 100644 index 0000000000..b1b0bf1b31 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/contract/update.go @@ -0,0 +1,196 @@ +package contract + +import ( + "encoding/hex" + "errors" + "fmt" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-contract/common" + "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + io2 "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" + neoUtil "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var errMissingNNSRecord = errors.New("missing NNS record") + +func updateContracts(cmd *cobra.Command, _ []string) error { + wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) + if err != nil { + return fmt.Errorf("initialization error: %w", err) + } + + if err := morphUtil.DeployNNS(wCtx, morphUtil.UpdateMethodName); err != nil { + return err + } + + return updateContractsInternal(wCtx) +} + +func updateContractsInternal(c *morphUtil.InitializeContext) error { + alphaCs := c.GetContract(morphUtil.AlphabetContract) + + nnsCs, err := c.NNSContractState() + if err != nil { + return err + } + nnsHash := nnsCs.Hash + + w := io2.NewBufBinWriter() + + // Update script size for a single-node committee is close to the maximum allowed size of 65535. + // Because of this we want to reuse alphabet contract NEF and manifest for different updates. + // The generated script is as following. + // 1. Initialize static slot for alphabet NEF. + // 2. Store NEF into the static slot. + // 3. Push parameters for each alphabet contract on stack. + // 4. Add contract group to the manifest. + // 5. For each alphabet contract, invoke `update` using parameters on stack and + // NEF from step 2 and manifest from step 4. + emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1}) + emit.Bytes(w.BinWriter, alphaCs.RawNEF) + emit.Opcodes(w.BinWriter, opcode.STSFLD0) + + keysParam, err := deployAlphabetAccounts(c, nnsHash, w, alphaCs) + if err != nil { + return err + } + + w.Reset() + + if err = deployOrUpdateContracts(c, w, nnsHash, keysParam); err != nil { + return err + } + + groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey() + _, _, err = c.EmitUpdateNNSGroupScript(w, nnsHash, groupKey) + if err != nil { + return err + } + c.Command.Printf("NNS: Set %s -> %s\n", morphClient.NNSGroupKeyName, hex.EncodeToString(groupKey.Bytes())) + + emit.Opcodes(w.BinWriter, opcode.LDSFLD0) + emit.Int(w.BinWriter, 1) + emit.Opcodes(w.BinWriter, opcode.PACK) + emit.AppCallNoArgs(w.BinWriter, nnsHash, "setPrice", callflag.All) + + if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { + return err + } + return c.AwaitTx() +} + +func deployAlphabetAccounts(c *morphUtil.InitializeContext, nnsHash neoUtil.Uint160, w *io2.BufBinWriter, alphaCs *morphUtil.ContractState) ([]any, error) { + var keysParam []any + + baseGroups := alphaCs.Manifest.Groups + + // alphabet contracts should be deployed by individual nodes to get different hashes. + for i, acc := range c.Accounts { + ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.GetAlphabetNNSDomain(i)) + if err != nil { + return nil, fmt.Errorf("can't resolve hash for contract update: %w", err) + } + + keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes()) + + params := c.GetAlphabetDeployItems(i, len(c.Wallets)) + emit.Array(w.BinWriter, params...) + + alphaCs.Manifest.Groups = baseGroups + err = morphUtil.AddManifestGroup(c.ContractWallet, ctrHash, alphaCs) + if err != nil { + return nil, fmt.Errorf("can't sign manifest group: %v", err) + } + + emit.Bytes(w.BinWriter, alphaCs.RawManifest) + emit.Opcodes(w.BinWriter, opcode.LDSFLD0) + emit.Int(w.BinWriter, 3) + emit.Opcodes(w.BinWriter, opcode.PACK) + emit.AppCallNoArgs(w.BinWriter, ctrHash, morphUtil.UpdateMethodName, callflag.All) + } + if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { + if !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { + return nil, err + } + c.Command.Println("Alphabet contracts are already updated.") + } + + return keysParam, nil +} + +func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter, nnsHash neoUtil.Uint160, keysParam []any) error { + emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1}) + emit.AppCall(w.BinWriter, nnsHash, "getPrice", callflag.All) + emit.Opcodes(w.BinWriter, opcode.STSFLD0) + emit.AppCall(w.BinWriter, nnsHash, "setPrice", callflag.All, 1) + + for _, ctrName := range morphUtil.ContractList { + cs := c.GetContract(ctrName) + + method := morphUtil.UpdateMethodName + ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName)) + if err != nil { + if errors.Is(err, errMissingNNSRecord) { + // if contract not found we deploy it instead of update + method = morphUtil.DeployMethodName + } else { + return fmt.Errorf("can't resolve hash for contract update: %w", err) + } + } + + err = morphUtil.AddManifestGroup(c.ContractWallet, ctrHash, cs) + if err != nil { + return fmt.Errorf("can't sign manifest group: %v", err) + } + + invokeHash := management.Hash + if method == morphUtil.UpdateMethodName { + invokeHash = ctrHash + } + + args, err := morphUtil.GetContractDeployData(c, ctrName, keysParam, morphUtil.UpdateMethodName) + if err != nil { + return fmt.Errorf("%s: getting update params: %v", ctrName, err) + } + params := morphUtil.GetContractDeployParameters(cs, args) + res, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) + if err != nil { + if method != morphUtil.UpdateMethodName || !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { + return fmt.Errorf("deploy contract: %w", err) + } + c.Command.Printf("%s contract is already updated.\n", ctrName) + continue + } + + w.WriteBytes(res.Script) + + if method == morphUtil.DeployMethodName { + // same actions are done in InitializeContext.setNNS, can be unified + domain := ctrName + ".frostfs" + script, ok, err := c.NNSRegisterDomainScript(nnsHash, cs.Hash, domain) + if err != nil { + return err + } + if !ok { + w.WriteBytes(script) + emit.AppCall(w.BinWriter, nnsHash, "deleteRecords", callflag.All, domain, int64(nns.TXT)) + emit.AppCall(w.BinWriter, nnsHash, "addRecord", callflag.All, + domain, int64(nns.TXT), cs.Hash.StringLE()) + emit.AppCall(w.BinWriter, nnsHash, "addRecord", callflag.All, + domain, int64(nns.TXT), address.Uint160ToString(cs.Hash)) + } + c.Command.Printf("NNS: Set %s -> %s\n", domain, cs.Hash.StringLE()) + } + } + return nil +} diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/deploy.go index a312b34cd1..b5b2794ca3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/deploy.go @@ -83,7 +83,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { } callHash := management.Hash - method := deployMethodName + method := util.DeployMethodName zone, _ := cmd.Flags().GetString(util.CustomZoneFlag) domain := ctrName + "." + zone isUpdate, _ := cmd.Flags().GetBool(updateFlag) @@ -93,7 +93,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't fetch contract hash from NNS: %w", err) } callHash = cs.Hash - method = updateMethodName + method = util.UpdateMethodName } else { cs.Hash = state.CreateContractHash( c.CommitteeAcc.Contract.ScriptHash(), diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 76bbc71488..d40b09da35 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -28,7 +28,6 @@ const ( groupNameFlag = "group-name" groupIDFlag = "group-id" - frostfsIDAdminConfigKey = "frostfsid.admin" rootNamespacePlaceholder = "" ) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util.go index 99c04f57df..541a459c1f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util.go @@ -10,32 +10,8 @@ import ( "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/cobra" - "github.com/spf13/viper" ) -func GetFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { - admin := v.GetString(frostfsIDAdminConfigKey) - if admin == "" { - return util.Uint160{}, false, nil - } - - h, err := address.StringToUint160(admin) - if err == nil { - return h, true, nil - } - - h, err = util.Uint160DecodeStringLE(admin) - if err == nil { - return h, true, nil - } - - pk, err := keys.NewPublicKeyFromString(admin) - if err == nil { - return pk.GetScriptHash(), true, nil - } - return util.Uint160{}, true, fmt.Errorf("frostfsid: admin is invalid: '%s'", admin) -} - func getFrostfsIDSubjectKey(cmd *cobra.Command) *keys.PublicKey { subjKeyHex, _ := cmd.Flags().GetString(subjectKeyFlag) subjKey, err := keys.NewPublicKeyFromString(subjKeyHex) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go index 119e10d15c..fa6d07bf24 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -30,7 +31,7 @@ func TestFrostfsIDConfig(t *testing.T) { v := viper.New() v.Set("frostfsid.admin", fmts[i]) - actual, found, err := GetFrostfsIDAdmin(v) + actual, found, err := util.GetFrostfsIDAdmin(v) require.NoError(t, err) require.True(t, found) require.Equal(t, pks[i].GetScriptHash(), actual) @@ -40,14 +41,14 @@ func TestFrostfsIDConfig(t *testing.T) { v := viper.New() v.Set("frostfsid.admin", "abc") - _, found, err := GetFrostfsIDAdmin(v) + _, found, err := util.GetFrostfsIDAdmin(v) require.Error(t, err) require.True(t, found) }) t.Run("missing key", func(t *testing.T) { v := viper.New() - _, found, err := GetFrostfsIDAdmin(v) + _, found, err := util.GetFrostfsIDAdmin(v) require.NoError(t, err) require.False(t, found) }) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize.go index d4219294c8..30f7248cde 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize.go @@ -28,7 +28,7 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { // 3. Deploy NNS contract. cmd.Println("Stage 3: deploy NNS contract.") - if err := deployNNS(initCtx, deployMethodName); err != nil { + if err := morphUtil.DeployNNS(initCtx, morphUtil.DeployMethodName); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 3a78f6042c..4d54874198 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -1,252 +1,14 @@ package morph import ( - "encoding/hex" - "errors" "fmt" - "strings" - "git.frostfs.info/TrueCloudLab/frostfs-contract/common" - "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" - morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" - io2 "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" - "github.com/nspcc-dev/neo-go/pkg/smartcontract" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/emit" - "github.com/nspcc-dev/neo-go/pkg/vm/opcode" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/spf13/viper" ) -var netmapConfigKeys = []string{ - netmap.EpochDurationConfig, - netmap.MaxObjectSizeConfig, - netmap.ContainerFeeConfig, - netmap.ContainerAliasFeeConfig, - netmap.IrCandidateFeeConfig, - netmap.WithdrawFeeConfig, - netmap.HomomorphicHashingDisabledKey, - netmap.MaintenanceModeAllowedConfig, -} - -const ( - updateMethodName = "update" - deployMethodName = "deploy" -) - -func deployNNS(c *morphUtil.InitializeContext, method string) error { - cs := c.GetContract(morphUtil.NNSContract) - h := cs.Hash - - nnsCs, err := c.NNSContractState() - if err != nil { - return err - } - if nnsCs != nil { - if nnsCs.NEF.Checksum == cs.NEF.Checksum { - if method == deployMethodName { - c.Command.Println("NNS contract is already deployed.") - } else { - c.Command.Println("NNS contract is already updated.") - } - return nil - } - h = nnsCs.Hash - } - - err = addManifestGroup(c.ContractWallet, h, cs) - if err != nil { - return fmt.Errorf("can't sign manifest group: %v", err) - } - - params := getContractDeployParameters(cs, nil) - - invokeHash := management.Hash - if method == updateMethodName { - invokeHash = nnsCs.Hash - } - - tx, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) - if err != nil { - return fmt.Errorf("failed to create deploy tx for %s: %w", morphUtil.NNSContract, err) - } - - if err := c.MultiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { - return fmt.Errorf("can't send deploy transaction: %w", err) - } - - return c.AwaitTx() -} - -func updateContractsInternal(c *morphUtil.InitializeContext) error { - alphaCs := c.GetContract(morphUtil.AlphabetContract) - - nnsCs, err := c.NNSContractState() - if err != nil { - return err - } - nnsHash := nnsCs.Hash - - w := io2.NewBufBinWriter() - - // Update script size for a single-node committee is close to the maximum allowed size of 65535. - // Because of this we want to reuse alphabet contract NEF and manifest for different updates. - // The generated script is as following. - // 1. Initialize static slot for alphabet NEF. - // 2. Store NEF into the static slot. - // 3. Push parameters for each alphabet contract on stack. - // 4. Add contract group to the manifest. - // 5. For each alphabet contract, invoke `update` using parameters on stack and - // NEF from step 2 and manifest from step 4. - emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1}) - emit.Bytes(w.BinWriter, alphaCs.RawNEF) - emit.Opcodes(w.BinWriter, opcode.STSFLD0) - - keysParam, err := deployAlphabetAccounts(c, nnsHash, w, alphaCs) - if err != nil { - return err - } - - w.Reset() - - if err = deployOrUpdateContracts(c, w, nnsHash, keysParam); err != nil { - return err - } - - groupKey := c.ContractWallet.Accounts[0].PrivateKey().PublicKey() - _, _, err = c.EmitUpdateNNSGroupScript(w, nnsHash, groupKey) - if err != nil { - return err - } - c.Command.Printf("NNS: Set %s -> %s\n", morphClient.NNSGroupKeyName, hex.EncodeToString(groupKey.Bytes())) - - emit.Opcodes(w.BinWriter, opcode.LDSFLD0) - emit.Int(w.BinWriter, 1) - emit.Opcodes(w.BinWriter, opcode.PACK) - emit.AppCallNoArgs(w.BinWriter, nnsHash, "setPrice", callflag.All) - - if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { - return err - } - return c.AwaitTx() -} - -func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter, nnsHash util.Uint160, keysParam []any) error { - emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1}) - emit.AppCall(w.BinWriter, nnsHash, "getPrice", callflag.All) - emit.Opcodes(w.BinWriter, opcode.STSFLD0) - emit.AppCall(w.BinWriter, nnsHash, "setPrice", callflag.All, 1) - - for _, ctrName := range morphUtil.ContractList { - cs := c.GetContract(ctrName) - - method := updateMethodName - ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName)) - if err != nil { - if errors.Is(err, errMissingNNSRecord) { - // if contract not found we deploy it instead of update - method = deployMethodName - } else { - return fmt.Errorf("can't resolve hash for contract update: %w", err) - } - } - - err = addManifestGroup(c.ContractWallet, ctrHash, cs) - if err != nil { - return fmt.Errorf("can't sign manifest group: %v", err) - } - - invokeHash := management.Hash - if method == updateMethodName { - invokeHash = ctrHash - } - - args, err := getContractDeployData(c, ctrName, keysParam, updateMethodName) - if err != nil { - return fmt.Errorf("%s: getting update params: %v", ctrName, err) - } - params := getContractDeployParameters(cs, args) - res, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) - if err != nil { - if method != updateMethodName || !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { - return fmt.Errorf("deploy contract: %w", err) - } - c.Command.Printf("%s contract is already updated.\n", ctrName) - continue - } - - w.WriteBytes(res.Script) - - if method == deployMethodName { - // same actions are done in InitializeContext.setNNS, can be unified - domain := ctrName + ".frostfs" - script, ok, err := c.NNSRegisterDomainScript(nnsHash, cs.Hash, domain) - if err != nil { - return err - } - if !ok { - w.WriteBytes(script) - emit.AppCall(w.BinWriter, nnsHash, "deleteRecords", callflag.All, domain, int64(nns.TXT)) - emit.AppCall(w.BinWriter, nnsHash, "addRecord", callflag.All, - domain, int64(nns.TXT), cs.Hash.StringLE()) - emit.AppCall(w.BinWriter, nnsHash, "addRecord", callflag.All, - domain, int64(nns.TXT), address.Uint160ToString(cs.Hash)) - } - c.Command.Printf("NNS: Set %s -> %s\n", domain, cs.Hash.StringLE()) - } - } - return nil -} - -func deployAlphabetAccounts(c *morphUtil.InitializeContext, nnsHash util.Uint160, w *io2.BufBinWriter, alphaCs *morphUtil.ContractState) ([]any, error) { - var keysParam []any - - baseGroups := alphaCs.Manifest.Groups - - // alphabet contracts should be deployed by individual nodes to get different hashes. - for i, acc := range c.Accounts { - ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.GetAlphabetNNSDomain(i)) - if err != nil { - return nil, fmt.Errorf("can't resolve hash for contract update: %w", err) - } - - keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes()) - - params := c.GetAlphabetDeployItems(i, len(c.Wallets)) - emit.Array(w.BinWriter, params...) - - alphaCs.Manifest.Groups = baseGroups - err = addManifestGroup(c.ContractWallet, ctrHash, alphaCs) - if err != nil { - return nil, fmt.Errorf("can't sign manifest group: %v", err) - } - - emit.Bytes(w.BinWriter, alphaCs.RawManifest) - emit.Opcodes(w.BinWriter, opcode.LDSFLD0) - emit.Int(w.BinWriter, 3) - emit.Opcodes(w.BinWriter, opcode.PACK) - emit.AppCallNoArgs(w.BinWriter, ctrHash, updateMethodName, callflag.All) - } - if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { - if !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { - return nil, err - } - c.Command.Println("Alphabet contracts are already updated.") - } - - return keysParam, nil -} - func deployContracts(c *morphUtil.InitializeContext) error { alphaCs := c.GetContract(morphUtil.AlphabetContract) @@ -263,20 +25,20 @@ func deployContracts(c *morphUtil.InitializeContext) error { } alphaCs.Manifest.Groups = baseGroups - err := addManifestGroup(c.ContractWallet, ctrHash, alphaCs) + err := morphUtil.AddManifestGroup(c.ContractWallet, ctrHash, alphaCs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes()) - params := getContractDeployParameters(alphaCs, c.GetAlphabetDeployItems(i, len(c.Wallets))) + params := morphUtil.GetContractDeployParameters(alphaCs, c.GetAlphabetDeployItems(i, len(c.Wallets))) act, err := actor.NewSimple(c.Client, acc) if err != nil { return fmt.Errorf("could not create actor: %w", err) } - txHash, vub, err := act.SendCall(management.Hash, deployMethodName, params...) + txHash, vub, err := act.SendCall(management.Hash, morphUtil.DeployMethodName, params...) if err != nil { return fmt.Errorf("can't deploy alphabet #%d contract: %w", i, err) } @@ -293,17 +55,17 @@ func deployContracts(c *morphUtil.InitializeContext) error { continue } - err := addManifestGroup(c.ContractWallet, ctrHash, cs) + err := morphUtil.AddManifestGroup(c.ContractWallet, ctrHash, cs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } - args, err := getContractDeployData(c, ctrName, keysParam, deployMethodName) + args, err := morphUtil.GetContractDeployData(c, ctrName, keysParam, morphUtil.DeployMethodName) if err != nil { return fmt.Errorf("%s: getting deploy params: %v", ctrName, err) } - params := getContractDeployParameters(cs, args) - res, err := c.CommitteeAct.MakeCall(management.Hash, deployMethodName, params...) + params := morphUtil.GetContractDeployParameters(cs, args) + res, err := c.CommitteeAct.MakeCall(management.Hash, morphUtil.DeployMethodName, params...) if err != nil { return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) } @@ -315,152 +77,3 @@ func deployContracts(c *morphUtil.InitializeContext) error { return c.AwaitTx() } - -func getContractDeployParameters(cs *morphUtil.ContractState, deployData []any) []any { - return []any{cs.RawNEF, cs.RawManifest, deployData} -} - -func getContractDeployData(c *morphUtil.InitializeContext, ctrName string, keysParam []any, method string) ([]any, error) { - items := make([]any, 0, 6) - - switch ctrName { - case morphUtil.FrostfsContract: - items = append(items, - c.Contracts[morphUtil.ProcessingContract].Hash, - keysParam, - smartcontract.Parameter{}) - case morphUtil.ProcessingContract: - items = append(items, c.Contracts[morphUtil.FrostfsContract].Hash) - return items[1:], nil // no notary info - case morphUtil.BalanceContract: - items = append(items, - c.Contracts[morphUtil.NetmapContract].Hash, - c.Contracts[morphUtil.ContainerContract].Hash) - case morphUtil.ContainerContract: - // In case if NNS is updated multiple times, we can't calculate - // it's actual hash based on local data, thus query chain. - r := management.NewReader(c.ReadOnlyInvoker) - nnsCs, err := r.GetContractByID(1) - if err != nil { - return nil, fmt.Errorf("get nns contract: %w", err) - } - items = append(items, - c.Contracts[morphUtil.NetmapContract].Hash, - c.Contracts[morphUtil.BalanceContract].Hash, - c.Contracts[morphUtil.FrostfsIDContract].Hash, - nnsCs.Hash, - "container") - case morphUtil.FrostfsIDContract: - var ( - h util.Uint160 - found bool - err error - ) - if method == updateMethodName { - h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker) - } - if method != updateMethodName || err == nil && !found { - h, found, err = frostfsid.GetFrostfsIDAdmin(viper.GetViper()) - } - if err != nil { - return nil, err - } - - if found { - items = append(items, h) - } else { - items = append(items, c.Contracts[morphUtil.ProxyContract].Hash) - } - case morphUtil.NetmapContract: - md := morphUtil.GetDefaultNetmapContractConfigMap() - if method == updateMethodName { - if err := mergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil { - return nil, err - } - } - - var configParam []any - for k, v := range md { - configParam = append(configParam, k, v) - } - - items = append(items, - c.Contracts[morphUtil.BalanceContract].Hash, - c.Contracts[morphUtil.ContainerContract].Hash, - keysParam, - configParam) - case morphUtil.ProxyContract: - items = nil - case morphUtil.PolicyContract: - items = append(items, c.Contracts[morphUtil.ProxyContract].Hash) - default: - panic(fmt.Sprintf("invalid contract name: %s", ctrName)) - } - return items, nil -} - -func getFrostfsIDAdminFromContract(roInvoker *invoker.Invoker) (util.Uint160, bool, error) { - r := management.NewReader(roInvoker) - cs, err := r.GetContractByID(1) - if err != nil { - return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) - } - fidHash, err := morphUtil.NNSResolveHash(roInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract)) - if err != nil { - return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) - } - item, err := unwrap.Item(roInvoker.Call(fidHash, "getAdmin")) - if err != nil { - return util.Uint160{}, false, fmt.Errorf("getAdmin: %w", err) - } - if _, ok := item.(stackitem.Null); ok { - return util.Uint160{}, false, nil - } - - bs, err := item.TryBytes() - if err != nil { - return util.Uint160{}, true, fmt.Errorf("getAdmin: decode result: %w", err) - } - h, err := util.Uint160DecodeBytesBE(bs) - if err != nil { - return util.Uint160{}, true, fmt.Errorf("getAdmin: decode result: %w", err) - } - return h, true, nil -} - -func getNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Item, error) { - r := management.NewReader(roInvoker) - cs, err := r.GetContractByID(1) - if err != nil { - return nil, fmt.Errorf("get nns contract: %w", err) - } - nmHash, err := morphUtil.NNSResolveHash(roInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract)) - if err != nil { - return nil, fmt.Errorf("can't get netmap contract hash: %w", err) - } - arr, err := unwrap.Array(roInvoker.Call(nmHash, "listConfig")) - if err != nil { - return nil, fmt.Errorf("can't fetch list of network config keys from the netmap contract") - } - return arr, err -} - -func mergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error { - arr, err := getNetConfigFromNetmapContract(roInvoker) - if err != nil { - return err - } - m, err := morphUtil.ParseConfigFromNetmapContract(arr) - if err != nil { - return err - } - for k, v := range m { - for _, key := range netmapConfigKeys { - if k == key { - md[k] = v - break - } - } - } - return nil -} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go index 53435e67bb..f943ac4a1d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go @@ -2,7 +2,6 @@ package morph import ( "encoding/hex" - "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" @@ -132,5 +131,3 @@ func nnsRegisterDomain(c *morphUtil.InitializeContext, nnsHash, expectedHash uti domain, int64(nns.TXT), address.Uint160ToString(expectedHash)) return c.SendCommitteeTx(w.Bytes(), true) } - -var errMissingNNSRecord = errors.New("missing NNS record") diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 66dd77556e..3af6f78a5f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -98,16 +98,6 @@ var ( return refillGas(cmd, util.RefillGasAmountFlag, false) }, } - - updateContractsCmd = &cobra.Command{ - Use: "update-contracts", - Short: "Update FrostFS contracts", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: updateContracts, - } ) func init() { @@ -123,7 +113,7 @@ func init() { RootCmd.AddCommand(config.SetCmd) RootCmd.AddCommand(config.DumpCmd) RootCmd.AddCommand(balance.DumpCmd) - initUpdateContractsCmd() + RootCmd.AddCommand(contract.UpdateCmd) RootCmd.AddCommand(container.ListCmd) RootCmd.AddCommand(container.RestoreCmd) RootCmd.AddCommand(container.DumpCmd) @@ -148,15 +138,6 @@ func initRefillGasCmd() { refillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, util.StorageWalletFlag) } -func initUpdateContractsCmd() { - RootCmd.AddCommand(updateContractsCmd) - updateContractsCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - updateContractsCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - updateContractsCmd.Flags().String(util.ContractsInitFlag, "", util.ContractsInitFlagDesc) - updateContractsCmd.Flags().String(util.ContractsURLFlag, "", util.ContractsURLFlagDesc) - updateContractsCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) -} - func initGenerateStorageCmd() { RootCmd.AddCommand(generateStorageCmd) generateStorageCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) diff --git a/cmd/frostfs-adm/internal/modules/morph/update.go b/cmd/frostfs-adm/internal/modules/morph/update.go deleted file mode 100644 index 2d5b24712a..0000000000 --- a/cmd/frostfs-adm/internal/modules/morph/update.go +++ /dev/null @@ -1,22 +0,0 @@ -package morph - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -func updateContracts(cmd *cobra.Command, _ []string) error { - wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) - if err != nil { - return fmt.Errorf("initialization error: %w", err) - } - - if err := deployNNS(wCtx, updateMethodName); err != nil { - return err - } - - return updateContractsInternal(wCtx) -} diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index cdf1cd443a..a37afc3da0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -53,6 +53,9 @@ const ( FrostfsOpsEmail = "ops@frostfs.info" DefaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second + + DeployMethodName = "deploy" + UpdateMethodName = "update" ) var ( diff --git a/cmd/frostfs-adm/internal/modules/morph/util/contract.go b/cmd/frostfs-adm/internal/modules/morph/util/contract.go new file mode 100644 index 0000000000..8faa49d1cf --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/contract.go @@ -0,0 +1,169 @@ +package util + +import ( + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/spf13/viper" +) + +func getFrostfsIDAdminFromContract(roInvoker *invoker.Invoker) (util.Uint160, bool, error) { + r := management.NewReader(roInvoker) + cs, err := r.GetContractByID(1) + if err != nil { + return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) + } + fidHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(FrostfsIDContract)) + if err != nil { + return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) + } + item, err := unwrap.Item(roInvoker.Call(fidHash, "getAdmin")) + if err != nil { + return util.Uint160{}, false, fmt.Errorf("getAdmin: %w", err) + } + if _, ok := item.(stackitem.Null); ok { + return util.Uint160{}, false, nil + } + + bs, err := item.TryBytes() + if err != nil { + return util.Uint160{}, true, fmt.Errorf("getAdmin: decode result: %w", err) + } + h, err := util.Uint160DecodeBytesBE(bs) + if err != nil { + return util.Uint160{}, true, fmt.Errorf("getAdmin: decode result: %w", err) + } + return h, true, nil +} + +func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any, method string) ([]any, error) { + items := make([]any, 0, 6) + + switch ctrName { + case FrostfsContract: + items = append(items, + c.Contracts[ProcessingContract].Hash, + keysParam, + smartcontract.Parameter{}) + case ProcessingContract: + items = append(items, c.Contracts[FrostfsContract].Hash) + return items[1:], nil // no notary info + case BalanceContract: + items = append(items, + c.Contracts[NetmapContract].Hash, + c.Contracts[ContainerContract].Hash) + case ContainerContract: + // In case if NNS is updated multiple times, we can't calculate + // it's actual hash based on local data, thus query chain. + r := management.NewReader(c.ReadOnlyInvoker) + nnsCs, err := r.GetContractByID(1) + if err != nil { + return nil, fmt.Errorf("get nns contract: %w", err) + } + items = append(items, + c.Contracts[NetmapContract].Hash, + c.Contracts[BalanceContract].Hash, + c.Contracts[FrostfsIDContract].Hash, + nnsCs.Hash, + "container") + case FrostfsIDContract: + var ( + h util.Uint160 + found bool + err error + ) + if method == UpdateMethodName { + h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker) + } + if method != UpdateMethodName || err == nil && !found { + h, found, err = GetFrostfsIDAdmin(viper.GetViper()) + } + if err != nil { + return nil, err + } + + if found { + items = append(items, h) + } else { + items = append(items, c.Contracts[ProxyContract].Hash) + } + case NetmapContract: + md := GetDefaultNetmapContractConfigMap() + if method == UpdateMethodName { + if err := MergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil { + return nil, err + } + } + + var configParam []any + for k, v := range md { + configParam = append(configParam, k, v) + } + + items = append(items, + c.Contracts[BalanceContract].Hash, + c.Contracts[ContainerContract].Hash, + keysParam, + configParam) + case ProxyContract: + items = nil + case PolicyContract: + items = append(items, c.Contracts[ProxyContract].Hash) + default: + panic(fmt.Sprintf("invalid contract name: %s", ctrName)) + } + return items, nil +} + +func GetContractDeployParameters(cs *ContractState, deployData []any) []any { + return []any{cs.RawNEF, cs.RawManifest, deployData} +} + +func DeployNNS(c *InitializeContext, method string) error { + cs := c.GetContract(NNSContract) + h := cs.Hash + + nnsCs, err := c.NNSContractState() + if err != nil { + return err + } + if nnsCs != nil { + if nnsCs.NEF.Checksum == cs.NEF.Checksum { + if method == DeployMethodName { + c.Command.Println("NNS contract is already deployed.") + } else { + c.Command.Println("NNS contract is already updated.") + } + return nil + } + h = nnsCs.Hash + } + + err = AddManifestGroup(c.ContractWallet, h, cs) + if err != nil { + return fmt.Errorf("can't sign manifest group: %v", err) + } + + params := GetContractDeployParameters(cs, nil) + + invokeHash := management.Hash + if method == UpdateMethodName { + invokeHash = nnsCs.Hash + } + + tx, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) + if err != nil { + return fmt.Errorf("failed to create deploy tx for %s: %w", NNSContract, err) + } + + if err := c.MultiSignAndSend(tx, CommitteeAccountName); err != nil { + return fmt.Errorf("can't send deploy transaction: %w", err) + } + + return c.AwaitTx() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/util/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/util/frostfsid.go new file mode 100644 index 0000000000..7aea1c4928 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/frostfsid.go @@ -0,0 +1,35 @@ +package util + +import ( + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/spf13/viper" +) + +const frostfsIDAdminConfigKey = "frostfsid.admin" + +func GetFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { + admin := v.GetString(frostfsIDAdminConfigKey) + if admin == "" { + return util.Uint160{}, false, nil + } + + h, err := address.StringToUint160(admin) + if err == nil { + return h, true, nil + } + + h, err = util.Uint160DecodeStringLE(admin) + if err == nil { + return h, true, nil + } + + pk, err := keys.NewPublicKeyFromString(admin) + if err == nil { + return pk.GetScriptHash(), true, nil + } + return util.Uint160{}, true, fmt.Errorf("frostfsid: admin is invalid: '%s'", admin) +} diff --git a/cmd/frostfs-adm/internal/modules/morph/group.go b/cmd/frostfs-adm/internal/modules/morph/util/group.go similarity index 77% rename from cmd/frostfs-adm/internal/modules/morph/group.go rename to cmd/frostfs-adm/internal/modules/morph/util/group.go index 655b8b2c36..a0306f3bc0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/group.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/group.go @@ -1,15 +1,14 @@ -package morph +package util import ( "encoding/json" - util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" ) -func addManifestGroup(cw *wallet.Wallet, h util.Uint160, cs *util2.ContractState) error { +func AddManifestGroup(cw *wallet.Wallet, h util.Uint160, cs *ContractState) error { priv := cw.Accounts[0].PrivateKey() pub := priv.PublicKey() diff --git a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go index 34c527d0b2..bfe8ea165f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go @@ -6,6 +6,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" @@ -14,6 +16,17 @@ import ( "github.com/spf13/viper" ) +var NetmapConfigKeys = []string{ + netmap.EpochDurationConfig, + netmap.MaxObjectSizeConfig, + netmap.ContainerFeeConfig, + netmap.ContainerAliasFeeConfig, + netmap.IrCandidateFeeConfig, + netmap.WithdrawFeeConfig, + netmap.HomomorphicHashingDisabledKey, + netmap.MaintenanceModeAllowedConfig, +} + func GetDefaultNetmapContractConfigMap() map[string]any { m := make(map[string]any) m[netmap.EpochDurationConfig] = viper.GetInt64(EpochDurationInitFlag) @@ -67,3 +80,40 @@ func EmitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util. emit.AppCall(bw.BinWriter, nmHash, "newEpoch", callflag.All, newEpoch) return bw.Err } + +func GetNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Item, error) { + r := management.NewReader(roInvoker) + cs, err := r.GetContractByID(1) + if err != nil { + return nil, fmt.Errorf("get nns contract: %w", err) + } + nmHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(NetmapContract)) + if err != nil { + return nil, fmt.Errorf("can't get netmap contract hash: %w", err) + } + arr, err := unwrap.Array(roInvoker.Call(nmHash, "listConfig")) + if err != nil { + return nil, fmt.Errorf("can't fetch list of network config keys from the netmap contract") + } + return arr, err +} + +func MergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error { + arr, err := GetNetConfigFromNetmapContract(roInvoker) + if err != nil { + return err + } + m, err := ParseConfigFromNetmapContract(arr) + if err != nil { + return err + } + for k, v := range m { + for _, key := range NetmapConfigKeys { + if k == key { + md[k] = v + break + } + } + } + return nil +} From b8cf0a6b88faff7dc36368a5edbed638f54c09ec Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 09:54:47 +0300 Subject: [PATCH 0365/1413] [#932] adm: Move `deploy` to package `contract` Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/{ => contract}/deploy.go | 10 +++++----- cmd/frostfs-adm/internal/modules/morph/root.go | 6 +----- 2 files changed, 6 insertions(+), 10 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => contract}/deploy.go (97%) diff --git a/cmd/frostfs-adm/internal/modules/morph/deploy.go b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go similarity index 97% rename from cmd/frostfs-adm/internal/modules/morph/deploy.go rename to cmd/frostfs-adm/internal/modules/morph/contract/deploy.go index b5b2794ca3..35007a273a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go @@ -1,4 +1,4 @@ -package morph +package contract import ( "encoding/json" @@ -26,7 +26,7 @@ const ( updateFlag = "update" ) -var deployCmd = &cobra.Command{ +var DeployCmd = &cobra.Command{ Use: "deploy", Short: "Deploy additional smart-contracts", Long: `Deploy additional smart-contract which are not related to core. @@ -44,14 +44,14 @@ NNS name is taken by stripping '_contract.nef' from the NEF file (similar to fro } func init() { - ff := deployCmd.Flags() + ff := DeployCmd.Flags() ff.String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - _ = deployCmd.MarkFlagFilename(util.AlphabetWalletsFlag) + _ = DeployCmd.MarkFlagFilename(util.AlphabetWalletsFlag) ff.StringP(util.EndpointFlag, "r", "", util.EndpointFlagDesc) ff.String(contractPathFlag, "", "Path to the contract directory") - _ = deployCmd.MarkFlagFilename(contractPathFlag) + _ = DeployCmd.MarkFlagFilename(contractPathFlag) ff.Bool(updateFlag, false, "Update an existing contract") ff.String(util.CustomZoneFlag, "frostfs", "Custom zone for NNS") diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 3af6f78a5f..44ff543d9c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -103,7 +103,7 @@ var ( func init() { initGenerateAlphabetCmd() initInitCmd() - initDeployCmd() + RootCmd.AddCommand(contract.DeployCmd) initGenerateStorageCmd() RootCmd.AddCommand(netmap.ForceNewEpoch) RootCmd.AddCommand(node.RemoveCmd) @@ -169,7 +169,3 @@ func initGenerateAlphabetCmd() { generateAlphabetCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) generateAlphabetCmd.Flags().Uint(alphabetSizeFlag, 7, "Amount of alphabet wallets to generate") } - -func initDeployCmd() { - RootCmd.AddCommand(deployCmd) -} From 86b2515744671f1ecf665c97c5a2765d50a9f5a7 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 10:15:55 +0300 Subject: [PATCH 0366/1413] [#932] adm: Move `generate.go` to package `generate` Signed-off-by: Anton Nikiforov --- .../modules/morph/{ => generate}/generate.go | 6 +- .../morph/{ => generate}/generate_test.go | 30 ++++---- .../internal/modules/morph/generate/root.go | 76 +++++++++++++++++++ .../internal/modules/morph/initialize_test.go | 7 +- .../internal/modules/morph/root.go | 74 +----------------- .../internal/modules/morph/util/const.go | 3 + 6 files changed, 104 insertions(+), 92 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => generate}/generate.go (97%) rename cmd/frostfs-adm/internal/modules/morph/{ => generate}/generate_test.go (77%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/generate/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go similarity index 97% rename from cmd/frostfs-adm/internal/modules/morph/generate.go rename to cmd/frostfs-adm/internal/modules/morph/generate/generate.go index 57c40ec9f5..364ce2c6e8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -1,4 +1,4 @@ -package morph +package generate import ( "errors" @@ -24,9 +24,9 @@ import ( "golang.org/x/sync/errgroup" ) -func generateAlphabetCreds(cmd *cobra.Command, _ []string) error { +func AlphabetCreds(cmd *cobra.Command, _ []string) error { // alphabet size is not part of the config - size, err := cmd.Flags().GetUint(alphabetSizeFlag) + size, err := cmd.Flags().GetUint(morphUtil.AlphabetSizeFlag) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go similarity index 77% rename from cmd/frostfs-adm/internal/modules/morph/generate_test.go rename to cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go index e9e942d742..49379ee266 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go @@ -1,4 +1,4 @@ -package morph +package generate import ( "bytes" @@ -21,57 +21,55 @@ import ( "golang.org/x/term" ) -const testContractPassword = "grouppass" - func TestGenerateAlphabet(t *testing.T) { const size = 4 walletDir := t.TempDir() buf := setupTestTerminal(t) - cmd := generateAlphabetCmd + cmd := GenerateAlphabetCmd v := viper.GetViper() t.Run("zero size", func(t *testing.T) { buf.Reset() v.Set(util.AlphabetWalletsFlag, walletDir) - require.NoError(t, cmd.Flags().Set(alphabetSizeFlag, "0")) + require.NoError(t, cmd.Flags().Set(util.AlphabetSizeFlag, "0")) buf.WriteString("pass\r") - require.Error(t, generateAlphabetCreds(cmd, nil)) + require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("no password provided", func(t *testing.T) { buf.Reset() v.Set(util.AlphabetWalletsFlag, walletDir) - require.NoError(t, cmd.Flags().Set(alphabetSizeFlag, "1")) - require.Error(t, generateAlphabetCreds(cmd, nil)) + require.NoError(t, cmd.Flags().Set(util.AlphabetSizeFlag, "1")) + require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("missing directory", func(t *testing.T) { buf.Reset() dir := filepath.Join(os.TempDir(), "notexist."+strconv.FormatUint(rand.Uint64(), 10)) v.Set(util.AlphabetWalletsFlag, dir) - require.NoError(t, cmd.Flags().Set(alphabetSizeFlag, "1")) + require.NoError(t, cmd.Flags().Set(util.AlphabetSizeFlag, "1")) buf.WriteString("pass\r") - require.Error(t, generateAlphabetCreds(cmd, nil)) + require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("no password for contract group wallet", func(t *testing.T) { buf.Reset() v.Set(util.AlphabetWalletsFlag, walletDir) - require.NoError(t, cmd.Flags().Set(alphabetSizeFlag, strconv.FormatUint(size, 10))) + require.NoError(t, cmd.Flags().Set(util.AlphabetSizeFlag, strconv.FormatUint(size, 10))) for i := uint64(0); i < size; i++ { buf.WriteString(strconv.FormatUint(i, 10) + "\r") } - require.Error(t, generateAlphabetCreds(cmd, nil)) + require.Error(t, AlphabetCreds(cmd, nil)) }) buf.Reset() v.Set(util.AlphabetWalletsFlag, walletDir) - require.NoError(t, generateAlphabetCmd.Flags().Set(alphabetSizeFlag, strconv.FormatUint(size, 10))) + require.NoError(t, GenerateAlphabetCmd.Flags().Set(util.AlphabetSizeFlag, strconv.FormatUint(size, 10))) for i := uint64(0); i < size; i++ { buf.WriteString(strconv.FormatUint(i, 10) + "\r") } - buf.WriteString(testContractPassword + "\r") - require.NoError(t, generateAlphabetCreds(generateAlphabetCmd, nil)) + buf.WriteString(util.TestContractPassword + "\r") + require.NoError(t, AlphabetCreds(GenerateAlphabetCmd, nil)) var wg sync.WaitGroup for i := uint64(0); i < size; i++ { @@ -105,7 +103,7 @@ func TestGenerateAlphabet(t *testing.T) { w, err := wallet.NewWalletFromFile(p) require.NoError(t, err, "contract wallet doesn't exist") require.Equal(t, 1, len(w.Accounts), "contract wallet must have 1 accout") - require.NoError(t, w.Accounts[0].Decrypt(testContractPassword, keys.NEP2ScryptParams())) + require.NoError(t, w.Accounts[0].Decrypt(util.TestContractPassword, keys.NEP2ScryptParams())) }) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/root.go b/cmd/frostfs-adm/internal/modules/morph/generate/root.go new file mode 100644 index 0000000000..e5f5b38cde --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/generate/root.go @@ -0,0 +1,76 @@ +package generate + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + storageWalletLabelFlag = "label" + storageGasCLIFlag = "initial-gas" + storageGasConfigFlag = "storage.initial_gas" + walletAddressFlag = "wallet-address" +) + +var ( + GenerateStorageCmd = &cobra.Command{ + Use: "generate-storage-wallet", + Short: "Generate storage node wallet for the morph network", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(storageGasConfigFlag, cmd.Flags().Lookup(storageGasCLIFlag)) + }, + RunE: generateStorageCreds, + } + RefillGasCmd = &cobra.Command{ + Use: "refill-gas", + Short: "Refill GAS of storage node's wallet in the morph network", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(util.RefillGasAmountFlag, cmd.Flags().Lookup(util.RefillGasAmountFlag)) + }, + RunE: func(cmd *cobra.Command, args []string) error { + return refillGas(cmd, util.RefillGasAmountFlag, false) + }, + } + GenerateAlphabetCmd = &cobra.Command{ + Use: "generate-alphabet", + Short: "Generate alphabet wallets for consensus nodes of the morph network", + PreRun: func(cmd *cobra.Command, _ []string) { + // PreRun fixes https://github.com/spf13/viper/issues/233 + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + }, + RunE: AlphabetCreds, + } +) + +func initRefillGasCmd() { + RefillGasCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + RefillGasCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + RefillGasCmd.Flags().String(util.StorageWalletFlag, "", "Path to storage node wallet") + RefillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") + RefillGasCmd.Flags().String(util.RefillGasAmountFlag, "", "Additional amount of GAS to transfer") + RefillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, util.StorageWalletFlag) +} + +func initGenerateStorageCmd() { + GenerateStorageCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + GenerateStorageCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + GenerateStorageCmd.Flags().String(util.StorageWalletFlag, "", "Path to new storage node wallet") + GenerateStorageCmd.Flags().String(storageGasCLIFlag, "", "Initial amount of GAS to transfer") + GenerateStorageCmd.Flags().StringP(storageWalletLabelFlag, "l", "", "Wallet label") +} + +func initGenerateAlphabetCmd() { + GenerateAlphabetCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + GenerateAlphabetCmd.Flags().Uint(util.AlphabetSizeFlag, 7, "Amount of alphabet wallets to generate") +} + +func init() { + initRefillGasCmd() + initGenerateStorageCmd() + initGenerateAlphabetCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index 8b0fddf3da..3315b5d338 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -10,6 +10,7 @@ import ( "time" cmdConfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" @@ -100,12 +101,12 @@ func generateTestData(t *testing.T, dir string, size int) error { v.Set(util.AlphabetWalletsFlag, dir) sizeStr := strconv.FormatUint(uint64(size), 10) - if err := generateAlphabetCmd.Flags().Set(alphabetSizeFlag, sizeStr); err != nil { + if err := generate.GenerateAlphabetCmd.Flags().Set(util.AlphabetSizeFlag, sizeStr); err != nil { return err } setTestCredentials(v, size) - if err := generateAlphabetCreds(generateAlphabetCmd, nil); err != nil { + if err := generate.AlphabetCreds(generate.GenerateAlphabetCmd, nil); err != nil { return err } @@ -148,7 +149,7 @@ func setTestCredentials(v *viper.Viper, size int) { for i := 0; i < size; i++ { v.Set("credentials."+innerring.GlagoliticLetter(i).String(), strconv.FormatUint(uint64(i), 10)) } - v.Set("credentials.contract", testContractPassword) + v.Set("credentials.contract", util.TestContractPassword) } func TestNextPollInterval(t *testing.T) { diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 44ff543d9c..e2a4517f35 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/container" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/contract" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" @@ -18,12 +19,6 @@ import ( ) const ( - alphabetSizeFlag = "size" - - storageWalletLabelFlag = "label" - storageGasCLIFlag = "initial-gas" - storageGasConfigFlag = "storage.initial_gas" - maxObjectSizeCLIFlag = "max-object-size" epochDurationCLIFlag = "epoch-duration" @@ -36,8 +31,6 @@ const ( homomorphicHashDisabledCLIFlag = "homomorphic-disabled" withdrawFeeCLIFlag = "withdraw-fee" - - walletAddressFlag = "wallet-address" ) var ( @@ -47,16 +40,6 @@ var ( Short: "Section for morph network configuration commands", } - generateAlphabetCmd = &cobra.Command{ - Use: "generate-alphabet", - Short: "Generate alphabet wallets for consensus nodes of the morph network", - PreRun: func(cmd *cobra.Command, _ []string) { - // PreRun fixes https://github.com/spf13/viper/issues/233 - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - }, - RunE: generateAlphabetCreds, - } - initCmd = &cobra.Command{ Use: "init", Short: "Initialize side chain network with smart-contracts and network settings", @@ -74,37 +57,13 @@ var ( }, RunE: initializeSideChainCmd, } - - generateStorageCmd = &cobra.Command{ - Use: "generate-storage-wallet", - Short: "Generate storage node wallet for the morph network", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(storageGasConfigFlag, cmd.Flags().Lookup(storageGasCLIFlag)) - }, - RunE: generateStorageCreds, - } - - refillGasCmd = &cobra.Command{ - Use: "refill-gas", - Short: "Refill GAS of storage node's wallet in the morph network", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(util.RefillGasAmountFlag, cmd.Flags().Lookup(util.RefillGasAmountFlag)) - }, - RunE: func(cmd *cobra.Command, args []string) error { - return refillGas(cmd, util.RefillGasAmountFlag, false) - }, - } ) func init() { - initGenerateAlphabetCmd() + RootCmd.AddCommand(generate.RefillGasCmd) initInitCmd() RootCmd.AddCommand(contract.DeployCmd) - initGenerateStorageCmd() + RootCmd.AddCommand(generate.GenerateStorageCmd) RootCmd.AddCommand(netmap.ForceNewEpoch) RootCmd.AddCommand(node.RemoveCmd) RootCmd.AddCommand(policy.Set) @@ -117,7 +76,7 @@ func init() { RootCmd.AddCommand(container.ListCmd) RootCmd.AddCommand(container.RestoreCmd) RootCmd.AddCommand(container.DumpCmd) - initRefillGasCmd() + RootCmd.AddCommand(generate.GenerateAlphabetCmd) RootCmd.AddCommand(notary.DepositCmd) RootCmd.AddCommand(netmap.CandidatesCmd) @@ -128,25 +87,6 @@ func init() { RootCmd.AddCommand(frostfsid.Cmd) } -func initRefillGasCmd() { - RootCmd.AddCommand(refillGasCmd) - refillGasCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - refillGasCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - refillGasCmd.Flags().String(util.StorageWalletFlag, "", "Path to storage node wallet") - refillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") - refillGasCmd.Flags().String(util.RefillGasAmountFlag, "", "Additional amount of GAS to transfer") - refillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, util.StorageWalletFlag) -} - -func initGenerateStorageCmd() { - RootCmd.AddCommand(generateStorageCmd) - generateStorageCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - generateStorageCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - generateStorageCmd.Flags().String(util.StorageWalletFlag, "", "Path to new storage node wallet") - generateStorageCmd.Flags().String(storageGasCLIFlag, "", "Initial amount of GAS to transfer") - generateStorageCmd.Flags().StringP(storageWalletLabelFlag, "l", "", "Wallet label") -} - func initInitCmd() { RootCmd.AddCommand(initCmd) initCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) @@ -163,9 +103,3 @@ func initInitCmd() { initCmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") initCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) } - -func initGenerateAlphabetCmd() { - RootCmd.AddCommand(generateAlphabetCmd) - generateAlphabetCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - generateAlphabetCmd.Flags().Uint(alphabetSizeFlag, 7, "Amount of alphabet wallets to generate") -} diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index a37afc3da0..1128adee99 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -32,6 +32,7 @@ const ( MaintenanceModeAllowedInitFlag = "network.maintenance_mode_allowed" HomomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" CustomZoneFlag = "domain" + AlphabetSizeFlag = "size" SingleAccountName = "single" CommitteeAccountName = "committee" @@ -56,6 +57,8 @@ const ( DeployMethodName = "deploy" UpdateMethodName = "update" + + TestContractPassword = "grouppass" ) var ( From 63c34ea707b6aa3f0cc4ca7640a631bbac182009 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 10:25:04 +0300 Subject: [PATCH 0367/1413] [#932] adm: Move command `init` to package `initialize` Signed-off-by: Anton Nikiforov --- .../morph/{ => initialize}/initialize.go | 2 +- .../{ => initialize}/initialize_deploy.go | 2 +- .../morph/{ => initialize}/initialize_nns.go | 2 +- .../{ => initialize}/initialize_register.go | 2 +- .../{ => initialize}/initialize_roles.go | 2 +- .../morph/{ => initialize}/initialize_test.go | 8 +-- .../{ => initialize}/initialize_transfer.go | 2 +- .../internal/modules/morph/initialize/root.go | 55 +++++++++++++++ .../internal/modules/morph/root.go | 67 ++----------------- 9 files changed, 72 insertions(+), 70 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{ => initialize}/initialize.go (98%) rename cmd/frostfs-adm/internal/modules/morph/{ => initialize}/initialize_deploy.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{ => initialize}/initialize_nns.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{ => initialize}/initialize_register.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{ => initialize}/initialize_roles.go (98%) rename cmd/frostfs-adm/internal/modules/morph/{ => initialize}/initialize_test.go (96%) rename cmd/frostfs-adm/internal/modules/morph/{ => initialize}/initialize_transfer.go (99%) create mode 100644 cmd/frostfs-adm/internal/modules/morph/initialize/root.go diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go similarity index 98% rename from cmd/frostfs-adm/internal/modules/morph/initialize.go rename to cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go index 30f7248cde..d1b766019d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go @@ -1,4 +1,4 @@ -package morph +package initialize import ( "fmt" diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go rename to cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go index 4d54874198..9374b9f7ff 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go @@ -1,4 +1,4 @@ -package morph +package initialize import ( "fmt" diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/initialize_nns.go rename to cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go index f943ac4a1d..a9df7127fe 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go @@ -1,4 +1,4 @@ -package morph +package initialize import ( "encoding/hex" diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/initialize_register.go rename to cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index d6cbd2d560..cb33aa9856 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -1,4 +1,4 @@ -package morph +package initialize import ( "errors" diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go similarity index 98% rename from cmd/frostfs-adm/internal/modules/morph/initialize_roles.go rename to cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go index 9e885d5f8e..d7f17ccfb9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_roles.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go @@ -1,4 +1,4 @@ -package morph +package initialize import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go similarity index 96% rename from cmd/frostfs-adm/internal/modules/morph/initialize_test.go rename to cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go index 3315b5d338..d6b1806095 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go @@ -1,4 +1,4 @@ -package morph +package initialize import ( "encoding/hex" @@ -63,16 +63,16 @@ func testInitialize(t *testing.T, committeeSize int) { v.Set(util.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) // Set to the path or remove the next statement to download from the network. - require.NoError(t, initCmd.Flags().Set(util.ContractsInitFlag, contractsPath)) + require.NoError(t, Cmd.Flags().Set(util.ContractsInitFlag, contractsPath)) dumpPath := filepath.Join(testdataDir, "out") - require.NoError(t, initCmd.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, Cmd.Flags().Set(util.LocalDumpFlag, dumpPath)) v.Set(util.AlphabetWalletsFlag, testdataDir) v.Set(util.EpochDurationInitFlag, 1) v.Set(util.MaxObjectSizeInitFlag, 1024) setTestCredentials(v, committeeSize) - require.NoError(t, initializeSideChainCmd(initCmd, nil)) + require.NoError(t, initializeSideChainCmd(Cmd, nil)) t.Run("force-new-epoch", func(t *testing.T) { require.NoError(t, netmap.ForceNewEpoch.Flags().Set(util.LocalDumpFlag, dumpPath)) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go rename to cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go index ab4acefee3..8e501953bb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go @@ -1,4 +1,4 @@ -package morph +package initialize import ( "fmt" diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go new file mode 100644 index 0000000000..7dd6d17ca4 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go @@ -0,0 +1,55 @@ +package initialize + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + maxObjectSizeCLIFlag = "max-object-size" + epochDurationCLIFlag = "epoch-duration" + containerFeeCLIFlag = "container-fee" + containerAliasFeeCLIFlag = "container-alias-fee" + candidateFeeCLIFlag = "candidate-fee" + homomorphicHashDisabledCLIFlag = "homomorphic-disabled" + withdrawFeeCLIFlag = "withdraw-fee" +) + +var Cmd = &cobra.Command{ + Use: "init", + Short: "Initialize side chain network with smart-contracts and network settings", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(util.EpochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) + _ = viper.BindPFlag(util.MaxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) + _ = viper.BindPFlag(util.HomomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) + _ = viper.BindPFlag(util.CandidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) + _ = viper.BindPFlag(util.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) + _ = viper.BindPFlag(util.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) + _ = viper.BindPFlag(util.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) + _ = viper.BindPFlag(util.ProtoConfigPath, cmd.Flags().Lookup(util.ProtoConfigPath)) + }, + RunE: initializeSideChainCmd, +} + +func initInitCmd() { + Cmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + Cmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + Cmd.Flags().String(util.ContractsInitFlag, "", util.ContractsInitFlagDesc) + Cmd.Flags().String(util.ContractsURLFlag, "", util.ContractsURLFlagDesc) + Cmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") + Cmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes") + Cmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing") + // Defaults are taken from neo-preodolenie. + Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") + Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") + Cmd.Flags().String(util.ProtoConfigPath, "", "Path to the consensus node configuration") + Cmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") + Cmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) +} + +func init() { + initInitCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index e2a4517f35..9d2b25cebe 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -8,60 +8,24 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/contract" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/initialize" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/proxy" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" - "github.com/spf13/viper" ) -const ( - maxObjectSizeCLIFlag = "max-object-size" - - epochDurationCLIFlag = "epoch-duration" - - containerFeeCLIFlag = "container-fee" - containerAliasFeeCLIFlag = "container-alias-fee" - - candidateFeeCLIFlag = "candidate-fee" - - homomorphicHashDisabledCLIFlag = "homomorphic-disabled" - - withdrawFeeCLIFlag = "withdraw-fee" -) - -var ( - // RootCmd is a root command of config section. - RootCmd = &cobra.Command{ - Use: "morph", - Short: "Section for morph network configuration commands", - } - - initCmd = &cobra.Command{ - Use: "init", - Short: "Initialize side chain network with smart-contracts and network settings", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(util.EpochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) - _ = viper.BindPFlag(util.MaxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) - _ = viper.BindPFlag(util.HomomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) - _ = viper.BindPFlag(util.CandidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) - _ = viper.BindPFlag(util.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) - _ = viper.BindPFlag(util.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) - _ = viper.BindPFlag(util.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) - _ = viper.BindPFlag(util.ProtoConfigPath, cmd.Flags().Lookup(util.ProtoConfigPath)) - }, - RunE: initializeSideChainCmd, - } -) +// RootCmd is a root command of config section. +var RootCmd = &cobra.Command{ + Use: "morph", + Short: "Section for morph network configuration commands", +} func init() { RootCmd.AddCommand(generate.RefillGasCmd) - initInitCmd() + RootCmd.AddCommand(initialize.Cmd) RootCmd.AddCommand(contract.DeployCmd) RootCmd.AddCommand(generate.GenerateStorageCmd) RootCmd.AddCommand(netmap.ForceNewEpoch) @@ -86,20 +50,3 @@ func init() { RootCmd.AddCommand(frostfsid.Cmd) } - -func initInitCmd() { - RootCmd.AddCommand(initCmd) - initCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - initCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - initCmd.Flags().String(util.ContractsInitFlag, "", util.ContractsInitFlagDesc) - initCmd.Flags().String(util.ContractsURLFlag, "", util.ContractsURLFlagDesc) - initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") - initCmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes") - initCmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing") - // Defaults are taken from neo-preodolenie. - initCmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") - initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") - initCmd.Flags().String(util.ProtoConfigPath, "", "Path to the consensus node configuration") - initCmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") - initCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) -} From 7b0e3f5010b353987f9d00a41c7e3f409204f588 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 14:30:32 +0300 Subject: [PATCH 0368/1413] [#932] adm: Remove unnecessary import alias usage Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go | 8 ++++---- cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index 4d64f190f7..45e29c0297 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/spf13/cobra" @@ -12,7 +12,7 @@ import ( ) func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { - wCtx, err := util2.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -23,13 +23,13 @@ func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util2.DomainOf(util2.NetmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(util.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } bw := io.NewBufBinWriter() - if err := util2.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { + if err := util.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go index 7455c0bd09..a8fd97be26 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go @@ -3,7 +3,7 @@ package proxy import ( "fmt" - util2 "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" @@ -36,7 +36,7 @@ func removeProxyAccount(cmd *cobra.Command, _ []string) { } func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error { - wCtx, err := util2.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -47,7 +47,7 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error return fmt.Errorf("can't get NNS contract info: %w", err) } - proxyHash, err := util2.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util2.DomainOf(util2.ProxyContract)) + proxyHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.ProxyContract)) if err != nil { return fmt.Errorf("can't get proxy contract hash: %w", err) } From 814c411f4a2129453da58db6acb72a878a8746f7 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 15:04:48 +0300 Subject: [PATCH 0369/1413] [#932] adm: Move flags to package `commonflags` Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/commonflags/flags.go | 25 ++++++ .../internal/modules/morph/ape/ape.go | 42 ++++----- .../internal/modules/morph/ape/ape_util.go | 3 +- .../internal/modules/morph/balance/root.go | 6 +- .../internal/modules/morph/config/root.go | 16 ++-- .../internal/modules/morph/container/root.go | 18 ++-- .../internal/modules/morph/contract/deploy.go | 15 ++-- .../modules/morph/contract/dump_hashes.go | 3 +- .../internal/modules/morph/contract/root.go | 22 ++--- .../modules/morph/frostfsid/frostfsid.go | 89 ++++++++++--------- .../modules/morph/generate/generate.go | 9 +- .../modules/morph/generate/generate_test.go | 21 ++--- .../internal/modules/morph/generate/root.go | 36 ++++---- .../morph/initialize/initialize_test.go | 23 ++--- .../internal/modules/morph/initialize/root.go | 31 +++---- .../internal/modules/morph/netmap/root.go | 18 ++-- .../internal/modules/morph/node/root.go | 12 +-- .../internal/modules/morph/notary/notary.go | 7 +- .../internal/modules/morph/notary/root.go | 10 +-- .../internal/modules/morph/policy/root.go | 16 ++-- .../internal/modules/morph/proxy/root.go | 14 +-- .../internal/modules/morph/util/const.go | 23 ----- .../modules/morph/util/initialize_ctx.go | 17 ++-- .../internal/modules/morph/util/n3client.go | 3 +- .../internal/modules/morph/util/netmap.go | 17 ++-- 25 files changed, 255 insertions(+), 241 deletions(-) diff --git a/cmd/frostfs-adm/internal/commonflags/flags.go b/cmd/frostfs-adm/internal/commonflags/flags.go index 2f1ae4cc52..71c36b71ae 100644 --- a/cmd/frostfs-adm/internal/commonflags/flags.go +++ b/cmd/frostfs-adm/internal/commonflags/flags.go @@ -11,4 +11,29 @@ const ( Verbose = "verbose" VerboseShorthand = "v" VerboseUsage = "Verbose output" + + EndpointFlag = "rpc-endpoint" + EndpointFlagDesc = "N3 RPC node endpoint" + EndpointFlagShort = "r" + + AlphabetWalletsFlag = "alphabet-wallets" + AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" + + LocalDumpFlag = "local-dump" + ContractsInitFlag = "contracts" + ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" + ContractsURLFlag = "contracts-url" + ContractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" + EpochDurationInitFlag = "network.epoch_duration" + MaxObjectSizeInitFlag = "network.max_object_size" + RefillGasAmountFlag = "gas" + StorageWalletFlag = "storage-wallet" + ContainerFeeInitFlag = "network.fee.container" + ContainerAliasFeeInitFlag = "network.fee.container_alias" + CandidateFeeInitFlag = "network.fee.candidate" + WithdrawFeeInitFlag = "network.fee.withdraw" + MaintenanceModeAllowedInitFlag = "network.maintenance_mode_allowed" + HomomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" + CustomZoneFlag = "domain" + AlphabetSizeFlag = "size" ) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index de3765042f..8395fd4ba7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -4,7 +4,7 @@ import ( "bytes" "encoding/json" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -37,8 +37,8 @@ var ( Use: "add-rule-chain", Short: "Add rule chain", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: addRuleChain, } @@ -47,8 +47,8 @@ var ( Use: "rm-rule-chain", Short: "Remove rule chain", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: removeRuleChain, } @@ -57,8 +57,8 @@ var ( Use: "list-rule-chains", Short: "List rule chains", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: listRuleChains, } @@ -67,8 +67,8 @@ var ( Use: "set-admin", Short: "Set admin", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: setAdmin, } @@ -77,8 +77,8 @@ var ( Use: "get-admin", Short: "Get admin", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: getAdmin, } @@ -87,8 +87,8 @@ var ( func initAddRuleChainCmd() { Cmd.AddCommand(addRuleChainCmd) - addRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - addRuleChainCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + addRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + addRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) _ = addRuleChainCmd.MarkFlagRequired(targetTypeFlag) @@ -106,8 +106,8 @@ func initAddRuleChainCmd() { func initRemoveRuleChainCmd() { Cmd.AddCommand(removeRuleChainCmd) - removeRuleChainCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - removeRuleChainCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + removeRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + removeRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) _ = removeRuleChainCmd.MarkFlagRequired(targetTypeFlag) @@ -120,8 +120,8 @@ func initRemoveRuleChainCmd() { func initListRuleChainsCmd() { Cmd.AddCommand(listRuleChainsCmd) - listRuleChainsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - listRuleChainsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + listRuleChainsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + listRuleChainsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) _ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag) listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc) @@ -132,8 +132,8 @@ func initListRuleChainsCmd() { func initSetAdminCmd() { Cmd.AddCommand(setAdminCmd) - setAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - setAdminCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + setAdminCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + setAdminCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) setAdminCmd.Flags().String(addrAdminFlag, "", addrAdminDesc) _ = setAdminCmd.MarkFlagRequired(addrAdminFlag) } @@ -141,8 +141,8 @@ func initSetAdminCmd() { func initGetAdminCmd() { Cmd.AddCommand(getAdminCmd) - getAdminCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - getAdminCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + getAdminCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + getAdminCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func addRuleChain(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 21f27bfd7e..7dc5fa0824 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -5,6 +5,7 @@ import ( "fmt" "os" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" @@ -81,7 +82,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac c, err := morphUtil.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag)) + walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/balance/root.go b/cmd/frostfs-adm/internal/modules/morph/balance/root.go index 757637e5db..3be712367a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance/root.go @@ -1,7 +1,7 @@ package balance import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -10,13 +10,13 @@ var DumpCmd = &cobra.Command{ Use: "dump-balances", Short: "Dump GAS balances", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: dumpBalances, } func initDumpBalancesCmd() { - DumpCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + DumpCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) DumpCmd.Flags().BoolP(dumpBalancesStorageFlag, "s", false, "Dump balances of storage nodes from the current netmap") DumpCmd.Flags().BoolP(dumpBalancesAlphabetFlag, "a", false, "Dump balances of alphabet contracts") DumpCmd.Flags().BoolP(dumpBalancesProxyFlag, "p", false, "Dump balances of the proxy contract") diff --git a/cmd/frostfs-adm/internal/modules/morph/config/root.go b/cmd/frostfs-adm/internal/modules/morph/config/root.go index 4b53662269..6b9094de01 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/root.go @@ -1,7 +1,7 @@ package config import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -12,8 +12,8 @@ var ( DisableFlagsInUseLine: true, Short: "Add/update global config value in the FrostFS network", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Args: cobra.MinimumNArgs(1), RunE: SetConfigCmd, @@ -23,21 +23,21 @@ var ( Use: "dump-config", Short: "Dump FrostFS network config", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: dumpNetworkConfig, } ) func initSetConfigCmd() { - SetCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - SetCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + SetCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + SetCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) SetCmd.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") - SetCmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") + SetCmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") } func initDumpNetworkConfigCmd() { - DumpCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + DumpCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) } func init() { diff --git a/cmd/frostfs-adm/internal/modules/morph/container/root.go b/cmd/frostfs-adm/internal/modules/morph/container/root.go index 4cae8cf4f0..2b314ab09a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/root.go @@ -1,7 +1,7 @@ package container import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,7 +17,7 @@ var ( Use: "dump-containers", Short: "Dump FrostFS containers to file", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: dumpContainers, } @@ -26,8 +26,8 @@ var ( Use: "restore-containers", Short: "Restore FrostFS containers from file", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: restoreContainers, } @@ -36,26 +36,26 @@ var ( Use: "list-containers", Short: "List FrostFS containers", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: listContainers, } ) func initListContainersCmd() { - ListCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + ListCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) ListCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") } func initRestoreContainersCmd() { - RestoreCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - RestoreCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + RestoreCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + RestoreCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) RestoreCmd.Flags().String(containerDumpFlag, "", "File to restore containers from") RestoreCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to restore") } func initDumpContainersCmd() { - DumpCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + DumpCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) DumpCmd.Flags().String(containerDumpFlag, "", "File where to save dumped containers") DumpCmd.Flags().String(containerContractFlag, "", "Container contract hash (for networks without NNS)") DumpCmd.Flags().StringSlice(containerIDsFlag, nil, "Containers to dump") diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go index 35007a273a..67a8d2fac7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go @@ -7,6 +7,7 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -37,8 +38,8 @@ Compiled contract file name must contain '_contract.nef' suffix. Contract's manifest file name must be 'config.json'. NNS name is taken by stripping '_contract.nef' from the NEF file (similar to frostfs contracts).`, PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: deployContractCmd, } @@ -46,15 +47,15 @@ NNS name is taken by stripping '_contract.nef' from the NEF file (similar to fro func init() { ff := DeployCmd.Flags() - ff.String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - _ = DeployCmd.MarkFlagFilename(util.AlphabetWalletsFlag) + ff.String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + _ = DeployCmd.MarkFlagFilename(commonflags.AlphabetWalletsFlag) - ff.StringP(util.EndpointFlag, "r", "", util.EndpointFlagDesc) + ff.StringP(commonflags.EndpointFlag, "r", "", commonflags.EndpointFlagDesc) ff.String(contractPathFlag, "", "Path to the contract directory") _ = DeployCmd.MarkFlagFilename(contractPathFlag) ff.Bool(updateFlag, false, "Update an existing contract") - ff.String(util.CustomZoneFlag, "frostfs", "Custom zone for NNS") + ff.String(commonflags.CustomZoneFlag, "frostfs", "Custom zone for NNS") } func deployContractCmd(cmd *cobra.Command, args []string) error { @@ -84,7 +85,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { callHash := management.Hash method := util.DeployMethodName - zone, _ := cmd.Flags().GetString(util.CustomZoneFlag) + zone, _ := cmd.Flags().GetString(commonflags.CustomZoneFlag) domain := ctrName + "." + zone isUpdate, _ := cmd.Flags().GetBool(updateFlag) if isUpdate { diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index 8f7fbe6e0b..ca1e5433bd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -8,6 +8,7 @@ import ( "text/tabwriter" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/io" @@ -45,7 +46,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return err } - zone, _ := cmd.Flags().GetString(morphUtil.CustomZoneFlag) + zone, _ := cmd.Flags().GetString(commonflags.CustomZoneFlag) if zone != "" { return dumpCustomZoneHashes(cmd, cs.Hash, zone, c) } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/root.go b/cmd/frostfs-adm/internal/modules/morph/contract/root.go index 71feb31cd5..9bad2bd665 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/root.go @@ -1,7 +1,7 @@ package contract import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -11,7 +11,7 @@ var ( Use: "dump-hashes", Short: "Dump deployed contract hashes", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: dumpContractHashes, } @@ -19,24 +19,24 @@ var ( Use: "update-contracts", Short: "Update FrostFS contracts", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: updateContracts, } ) func initDumpContractHashesCmd() { - DumpHashesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - DumpHashesCmd.Flags().String(util.CustomZoneFlag, "", "Custom zone to search.") + DumpHashesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + DumpHashesCmd.Flags().String(commonflags.CustomZoneFlag, "", "Custom zone to search.") } func initUpdateContractsCmd() { - UpdateCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - UpdateCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - UpdateCmd.Flags().String(util.ContractsInitFlag, "", util.ContractsInitFlagDesc) - UpdateCmd.Flags().String(util.ContractsURLFlag, "", util.ContractsURLFlagDesc) - UpdateCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) + UpdateCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + UpdateCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + UpdateCmd.Flags().String(commonflags.ContractsInitFlag, "", commonflags.ContractsInitFlagDesc) + UpdateCmd.Flags().String(commonflags.ContractsURLFlag, "", commonflags.ContractsURLFlagDesc) + UpdateCmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag) } func init() { diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index d40b09da35..0a64b9e167 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -6,6 +6,7 @@ import ( "sort" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -41,8 +42,8 @@ var ( Use: "create-namespace", Short: "Create new namespace in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidCreateNamespace, } @@ -51,8 +52,8 @@ var ( Use: "list-namespaces", Short: "List all namespaces in frostfsid", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidListNamespaces, } @@ -61,8 +62,8 @@ var ( Use: "create-subject", Short: "Create subject in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidCreateSubject, } @@ -71,8 +72,8 @@ var ( Use: "delete-subject", Short: "Delete subject from frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidDeleteSubject, } @@ -81,8 +82,8 @@ var ( Use: "list-subjects", Short: "List subjects in namespace", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidListSubjects, } @@ -91,8 +92,8 @@ var ( Use: "create-group", Short: "Create group in frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidCreateGroup, } @@ -101,8 +102,8 @@ var ( Use: "delete-group", Short: "Delete group from frostfsid contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidDeleteGroup, } @@ -111,8 +112,8 @@ var ( Use: "list-groups", Short: "List groups in namespace", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidListGroups, } @@ -121,8 +122,8 @@ var ( Use: "add-subject-to-group", Short: "Add subject to group", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidAddSubjectToGroup, } @@ -131,8 +132,8 @@ var ( Use: "remove-subject-from-group", Short: "Remove subject from group", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidRemoveSubjectFromGroup, } @@ -141,8 +142,8 @@ var ( Use: "list-group-subjects", Short: "List subjects in group", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(morphUtil.AlphabetWalletsFlag, cmd.Flags().Lookup(morphUtil.AlphabetWalletsFlag)) - _ = viper.BindPFlag(morphUtil.EndpointFlag, cmd.Flags().Lookup(morphUtil.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidListGroupSubjects, } @@ -150,87 +151,87 @@ var ( func initFrostfsIDCreateNamespaceCmd() { Cmd.AddCommand(frostfsidCreateNamespaceCmd) - frostfsidCreateNamespaceCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidCreateNamespaceCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidCreateNamespaceCmd.Flags().String(namespaceFlag, "", "Namespace name to create") - frostfsidCreateNamespaceCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidCreateNamespaceCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDListNamespacesCmd() { Cmd.AddCommand(frostfsidListNamespacesCmd) - frostfsidListNamespacesCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) - frostfsidListNamespacesCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidListNamespacesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + frostfsidListNamespacesCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDCreateSubjectCmd() { Cmd.AddCommand(frostfsidCreateSubjectCmd) - frostfsidCreateSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidCreateSubjectCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidCreateSubjectCmd.Flags().String(namespaceFlag, "", "Namespace where create subject") frostfsidCreateSubjectCmd.Flags().String(subjectNameFlag, "", "Subject name, must be unique in namespace") frostfsidCreateSubjectCmd.Flags().String(subjectKeyFlag, "", "Subject hex-encoded public key") - frostfsidCreateSubjectCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidCreateSubjectCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDDeleteSubjectCmd() { Cmd.AddCommand(frostfsidDeleteSubjectCmd) - frostfsidDeleteSubjectCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidDeleteSubjectCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidDeleteSubjectCmd.Flags().String(subjectAddressFlag, "", "Subject address") - frostfsidDeleteSubjectCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidDeleteSubjectCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDListSubjectsCmd() { Cmd.AddCommand(frostfsidListSubjectsCmd) - frostfsidListSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidListSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") - frostfsidListSubjectsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidListSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDCreateGroupCmd() { Cmd.AddCommand(frostfsidCreateGroupCmd) - frostfsidCreateGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidCreateGroupCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidCreateGroupCmd.Flags().String(namespaceFlag, "", "Namespace where create group") frostfsidCreateGroupCmd.Flags().String(groupNameFlag, "", "Group name, must be unique in namespace") - frostfsidCreateGroupCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidCreateGroupCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDDeleteGroupCmd() { Cmd.AddCommand(frostfsidDeleteGroupCmd) - frostfsidDeleteGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidDeleteGroupCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidDeleteGroupCmd.Flags().String(namespaceFlag, "", "Namespace to delete group") frostfsidDeleteGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") - frostfsidDeleteGroupCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidDeleteGroupCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDListGroupsCmd() { Cmd.AddCommand(frostfsidListGroupsCmd) - frostfsidListGroupsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidListGroupsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") - frostfsidListGroupsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidListGroupsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDAddSubjectToGroupCmd() { Cmd.AddCommand(frostfsidAddSubjectToGroupCmd) - frostfsidAddSubjectToGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidAddSubjectToGroupCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidAddSubjectToGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidAddSubjectToGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") - frostfsidAddSubjectToGroupCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidAddSubjectToGroupCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDRemoveSubjectFromGroupCmd() { Cmd.AddCommand(frostfsidRemoveSubjectFromGroupCmd) - frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidRemoveSubjectFromGroupCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidRemoveSubjectFromGroupCmd.Flags().String(subjectAddressFlag, "", "Subject address") frostfsidRemoveSubjectFromGroupCmd.Flags().Int64(groupIDFlag, 0, "Group id") - frostfsidRemoveSubjectFromGroupCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidRemoveSubjectFromGroupCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDListGroupSubjectsCmd() { Cmd.AddCommand(frostfsidListGroupSubjectsCmd) - frostfsidListGroupSubjectsCmd.Flags().StringP(morphUtil.EndpointFlag, morphUtil.EndpointFlagShort, "", morphUtil.EndpointFlagDesc) + frostfsidListGroupSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") - frostfsidListGroupSubjectsCmd.Flags().String(morphUtil.AlphabetWalletsFlag, "", morphUtil.AlphabetWalletsFlagDesc) + frostfsidListGroupSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go index 364ce2c6e8..8db0aecd23 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -6,6 +6,7 @@ import ( "os" "path/filepath" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" @@ -26,7 +27,7 @@ import ( func AlphabetCreds(cmd *cobra.Command, _ []string) error { // alphabet size is not part of the config - size, err := cmd.Flags().GetUint(morphUtil.AlphabetSizeFlag) + size, err := cmd.Flags().GetUint(commonflags.AlphabetSizeFlag) if err != nil { return err } @@ -38,7 +39,7 @@ func AlphabetCreds(cmd *cobra.Command, _ []string) error { } v := viper.GetViper() - walletDir := config.ResolveHomePath(viper.GetString(morphUtil.AlphabetWalletsFlag)) + walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) pwds, err := initializeWallets(v, walletDir, int(size)) if err != nil { return err @@ -138,7 +139,7 @@ func generateStorageCreds(cmd *cobra.Command, _ []string) error { func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error) { // storage wallet path is not part of the config - storageWalletPath, _ := cmd.Flags().GetString(morphUtil.StorageWalletFlag) + storageWalletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag) // wallet address is not part of the config walletAddress, _ := cmd.Flags().GetString(walletAddressFlag) @@ -151,7 +152,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error } } else { if storageWalletPath == "" { - return fmt.Errorf("missing wallet path (use '--%s ')", morphUtil.StorageWalletFlag) + return fmt.Errorf("missing wallet path (use '--%s ')", commonflags.StorageWalletFlag) } var w *wallet.Wallet diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go index 49379ee266..add00b5ce0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go @@ -10,6 +10,7 @@ import ( "sync" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/cli/input" @@ -32,29 +33,29 @@ func TestGenerateAlphabet(t *testing.T) { t.Run("zero size", func(t *testing.T) { buf.Reset() - v.Set(util.AlphabetWalletsFlag, walletDir) - require.NoError(t, cmd.Flags().Set(util.AlphabetSizeFlag, "0")) + v.Set(commonflags.AlphabetWalletsFlag, walletDir) + require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, "0")) buf.WriteString("pass\r") require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("no password provided", func(t *testing.T) { buf.Reset() - v.Set(util.AlphabetWalletsFlag, walletDir) - require.NoError(t, cmd.Flags().Set(util.AlphabetSizeFlag, "1")) + v.Set(commonflags.AlphabetWalletsFlag, walletDir) + require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, "1")) require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("missing directory", func(t *testing.T) { buf.Reset() dir := filepath.Join(os.TempDir(), "notexist."+strconv.FormatUint(rand.Uint64(), 10)) - v.Set(util.AlphabetWalletsFlag, dir) - require.NoError(t, cmd.Flags().Set(util.AlphabetSizeFlag, "1")) + v.Set(commonflags.AlphabetWalletsFlag, dir) + require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, "1")) buf.WriteString("pass\r") require.Error(t, AlphabetCreds(cmd, nil)) }) t.Run("no password for contract group wallet", func(t *testing.T) { buf.Reset() - v.Set(util.AlphabetWalletsFlag, walletDir) - require.NoError(t, cmd.Flags().Set(util.AlphabetSizeFlag, strconv.FormatUint(size, 10))) + v.Set(commonflags.AlphabetWalletsFlag, walletDir) + require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, strconv.FormatUint(size, 10))) for i := uint64(0); i < size; i++ { buf.WriteString(strconv.FormatUint(i, 10) + "\r") } @@ -62,8 +63,8 @@ func TestGenerateAlphabet(t *testing.T) { }) buf.Reset() - v.Set(util.AlphabetWalletsFlag, walletDir) - require.NoError(t, GenerateAlphabetCmd.Flags().Set(util.AlphabetSizeFlag, strconv.FormatUint(size, 10))) + v.Set(commonflags.AlphabetWalletsFlag, walletDir) + require.NoError(t, GenerateAlphabetCmd.Flags().Set(commonflags.AlphabetSizeFlag, strconv.FormatUint(size, 10))) for i := uint64(0); i < size; i++ { buf.WriteString(strconv.FormatUint(i, 10) + "\r") } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/root.go b/cmd/frostfs-adm/internal/modules/morph/generate/root.go index e5f5b38cde..6b04848ae4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/root.go @@ -1,7 +1,7 @@ package generate import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -18,8 +18,8 @@ var ( Use: "generate-storage-wallet", Short: "Generate storage node wallet for the morph network", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(storageGasConfigFlag, cmd.Flags().Lookup(storageGasCLIFlag)) }, RunE: generateStorageCreds, @@ -28,12 +28,12 @@ var ( Use: "refill-gas", Short: "Refill GAS of storage node's wallet in the morph network", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(util.RefillGasAmountFlag, cmd.Flags().Lookup(util.RefillGasAmountFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.RefillGasAmountFlag, cmd.Flags().Lookup(commonflags.RefillGasAmountFlag)) }, RunE: func(cmd *cobra.Command, args []string) error { - return refillGas(cmd, util.RefillGasAmountFlag, false) + return refillGas(cmd, commonflags.RefillGasAmountFlag, false) }, } GenerateAlphabetCmd = &cobra.Command{ @@ -41,32 +41,32 @@ var ( Short: "Generate alphabet wallets for consensus nodes of the morph network", PreRun: func(cmd *cobra.Command, _ []string) { // PreRun fixes https://github.com/spf13/viper/issues/233 - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, RunE: AlphabetCreds, } ) func initRefillGasCmd() { - RefillGasCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - RefillGasCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - RefillGasCmd.Flags().String(util.StorageWalletFlag, "", "Path to storage node wallet") + RefillGasCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + RefillGasCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + RefillGasCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet") RefillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") - RefillGasCmd.Flags().String(util.RefillGasAmountFlag, "", "Additional amount of GAS to transfer") - RefillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, util.StorageWalletFlag) + RefillGasCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Additional amount of GAS to transfer") + RefillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, commonflags.StorageWalletFlag) } func initGenerateStorageCmd() { - GenerateStorageCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - GenerateStorageCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - GenerateStorageCmd.Flags().String(util.StorageWalletFlag, "", "Path to new storage node wallet") + GenerateStorageCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + GenerateStorageCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + GenerateStorageCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to new storage node wallet") GenerateStorageCmd.Flags().String(storageGasCLIFlag, "", "Initial amount of GAS to transfer") GenerateStorageCmd.Flags().StringP(storageWalletLabelFlag, "l", "", "Wallet label") } func initGenerateAlphabetCmd() { - GenerateAlphabetCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - GenerateAlphabetCmd.Flags().Uint(util.AlphabetSizeFlag, 7, "Amount of alphabet wallets to generate") + GenerateAlphabetCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + GenerateAlphabetCmd.Flags().Uint(commonflags.AlphabetSizeFlag, 7, "Amount of alphabet wallets to generate") } func init() { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go index d6b1806095..88bf0f45f9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" cmdConfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" @@ -63,27 +64,27 @@ func testInitialize(t *testing.T, committeeSize int) { v.Set(util.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) // Set to the path or remove the next statement to download from the network. - require.NoError(t, Cmd.Flags().Set(util.ContractsInitFlag, contractsPath)) + require.NoError(t, Cmd.Flags().Set(commonflags.ContractsInitFlag, contractsPath)) dumpPath := filepath.Join(testdataDir, "out") - require.NoError(t, Cmd.Flags().Set(util.LocalDumpFlag, dumpPath)) - v.Set(util.AlphabetWalletsFlag, testdataDir) - v.Set(util.EpochDurationInitFlag, 1) - v.Set(util.MaxObjectSizeInitFlag, 1024) + require.NoError(t, Cmd.Flags().Set(commonflags.LocalDumpFlag, dumpPath)) + v.Set(commonflags.AlphabetWalletsFlag, testdataDir) + v.Set(commonflags.EpochDurationInitFlag, 1) + v.Set(commonflags.MaxObjectSizeInitFlag, 1024) setTestCredentials(v, committeeSize) require.NoError(t, initializeSideChainCmd(Cmd, nil)) t.Run("force-new-epoch", func(t *testing.T) { - require.NoError(t, netmap.ForceNewEpoch.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, netmap.ForceNewEpoch.Flags().Set(commonflags.LocalDumpFlag, dumpPath)) require.NoError(t, netmap.ForceNewEpochCmd(netmap.ForceNewEpoch, nil)) }) t.Run("set-config", func(t *testing.T) { - require.NoError(t, cmdConfig.SetCmd.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, cmdConfig.SetCmd.Flags().Set(commonflags.LocalDumpFlag, dumpPath)) require.NoError(t, cmdConfig.SetConfigCmd(cmdConfig.SetCmd, []string{"MaintenanceModeAllowed=true"})) }) t.Run("set-policy", func(t *testing.T) { - require.NoError(t, policy.Set.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, policy.Set.Flags().Set(commonflags.LocalDumpFlag, dumpPath)) require.NoError(t, policy.SetPolicyCmd(policy.Set, []string{"ExecFeeFactor=1"})) }) t.Run("remove-node", func(t *testing.T) { @@ -91,17 +92,17 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, err) pub := hex.EncodeToString(pk.PublicKey().Bytes()) - require.NoError(t, node.RemoveCmd.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, node.RemoveCmd.Flags().Set(commonflags.LocalDumpFlag, dumpPath)) require.NoError(t, node.RemoveNodesCmd(node.RemoveCmd, []string{pub})) }) } func generateTestData(t *testing.T, dir string, size int) error { v := viper.GetViper() - v.Set(util.AlphabetWalletsFlag, dir) + v.Set(commonflags.AlphabetWalletsFlag, dir) sizeStr := strconv.FormatUint(uint64(size), 10) - if err := generate.GenerateAlphabetCmd.Flags().Set(util.AlphabetSizeFlag, sizeStr); err != nil { + if err := generate.GenerateAlphabetCmd.Flags().Set(commonflags.AlphabetSizeFlag, sizeStr); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go index 7dd6d17ca4..54958991ed 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go @@ -1,6 +1,7 @@ package initialize import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -20,25 +21,25 @@ var Cmd = &cobra.Command{ Use: "init", Short: "Initialize side chain network with smart-contracts and network settings", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(util.EpochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) - _ = viper.BindPFlag(util.MaxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) - _ = viper.BindPFlag(util.HomomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) - _ = viper.BindPFlag(util.CandidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) - _ = viper.BindPFlag(util.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) - _ = viper.BindPFlag(util.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) - _ = viper.BindPFlag(util.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.EpochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) + _ = viper.BindPFlag(commonflags.MaxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) + _ = viper.BindPFlag(commonflags.HomomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) + _ = viper.BindPFlag(commonflags.CandidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) + _ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) + _ = viper.BindPFlag(commonflags.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) + _ = viper.BindPFlag(commonflags.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) _ = viper.BindPFlag(util.ProtoConfigPath, cmd.Flags().Lookup(util.ProtoConfigPath)) }, RunE: initializeSideChainCmd, } func initInitCmd() { - Cmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - Cmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - Cmd.Flags().String(util.ContractsInitFlag, "", util.ContractsInitFlagDesc) - Cmd.Flags().String(util.ContractsURLFlag, "", util.ContractsURLFlagDesc) + Cmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + Cmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + Cmd.Flags().String(commonflags.ContractsInitFlag, "", commonflags.ContractsInitFlagDesc) + Cmd.Flags().String(commonflags.ContractsURLFlag, "", commonflags.ContractsURLFlagDesc) Cmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") Cmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes") Cmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing") @@ -46,8 +47,8 @@ func initInitCmd() { Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") Cmd.Flags().String(util.ProtoConfigPath, "", "Path to the consensus node configuration") - Cmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") - Cmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) + Cmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") + Cmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag) } func init() { diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go index 888b994e97..31fda860ee 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go @@ -1,7 +1,7 @@ package netmap import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -11,8 +11,8 @@ var ( Use: "netmap-candidates", Short: "List netmap candidates nodes", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: listNetmapCandidatesNodes, } @@ -20,21 +20,21 @@ var ( Use: "force-new-epoch", Short: "Create new FrostFS epoch event in the side chain", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: ForceNewEpochCmd, } ) func initNetmapCandidatesCmd() { - CandidatesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + CandidatesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) } func initForceNewEpochCmd() { - ForceNewEpoch.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - ForceNewEpoch.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - ForceNewEpoch.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") + ForceNewEpoch.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + ForceNewEpoch.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + ForceNewEpoch.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") } func init() { diff --git a/cmd/frostfs-adm/internal/modules/morph/node/root.go b/cmd/frostfs-adm/internal/modules/morph/node/root.go index e301a1bc34..1c38ae8bc7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/node/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/node/root.go @@ -1,7 +1,7 @@ package node import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -11,16 +11,16 @@ var RemoveCmd = &cobra.Command{ Short: "Remove storage nodes from the netmap", Long: `Move nodes to the Offline state in the candidates list and tick an epoch to update the netmap`, PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: RemoveNodesCmd, } func initRemoveNodesCmd() { - RemoveCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - RemoveCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - RemoveCmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") + RemoveCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + RemoveCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + RemoveCmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") } func init() { diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go index ecf9331b52..3b1bb179f4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go @@ -5,6 +5,7 @@ import ( "math/big" "strconv" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -60,7 +61,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't unlock account: %v", err) } - gasStr, err := cmd.Flags().GetString(morphUtil.RefillGasAmountFlag) + gasStr, err := cmd.Flags().GetString(commonflags.RefillGasAmountFlag) if err != nil { return err } @@ -126,11 +127,11 @@ func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, } func openWallet(cmd *cobra.Command) (*wallet.Wallet, error) { - p, err := cmd.Flags().GetString(morphUtil.StorageWalletFlag) + p, err := cmd.Flags().GetString(commonflags.StorageWalletFlag) if err != nil { return nil, err } else if p == "" { - return nil, fmt.Errorf("missing wallet path (use '--%s ')", morphUtil.StorageWalletFlag) + return nil, fmt.Errorf("missing wallet path (use '--%s ')", commonflags.StorageWalletFlag) } w, err := wallet.NewWalletFromFile(p) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/root.go b/cmd/frostfs-adm/internal/modules/morph/notary/root.go index 9a4164c7b3..497ff8ea1d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/root.go @@ -1,7 +1,7 @@ package notary import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -10,16 +10,16 @@ var DepositCmd = &cobra.Command{ Use: "deposit-notary", Short: "Deposit GAS for notary service", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: depositNotary, } func initDepositoryNotaryCmd() { - DepositCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - DepositCmd.Flags().String(util.StorageWalletFlag, "", "Path to storage node wallet") + DepositCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + DepositCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet") DepositCmd.Flags().String(walletAccountFlag, "", "Wallet account address") - DepositCmd.Flags().String(util.RefillGasAmountFlag, "", "Amount of GAS to deposit") + DepositCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Amount of GAS to deposit") DepositCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks") } diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/root.go b/cmd/frostfs-adm/internal/modules/morph/policy/root.go index 99ff56ee88..db50279dca 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/root.go @@ -1,7 +1,7 @@ package policy import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -12,8 +12,8 @@ var ( DisableFlagsInUseLine: true, Short: "Set global policy values", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: SetPolicyCmd, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -25,20 +25,20 @@ var ( Use: "dump-policy", Short: "Dump FrostFS policy", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: dumpPolicyCmd, } ) func initSetPolicyCmd() { - Set.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - Set.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - Set.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") + Set.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + Set.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + Set.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") } func initDumpPolicyCmd() { - Dump.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + Dump.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) } func init() { diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go index 14820d5aba..082bc57d1b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go @@ -1,7 +1,7 @@ package proxy import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -11,8 +11,8 @@ var ( Use: "proxy-add-account", Short: "Adds account to proxy contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: addProxyAccount, } @@ -20,20 +20,20 @@ var ( Use: "proxy-remove-account", Short: "Remove from proxy contract", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: removeProxyAccount, } ) func initProxyAddAccount() { - AddAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + AddAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) AddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") } func initProxyRemoveAccount() { - RemoveAccountCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + RemoveAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) RemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index 1128adee99..7c867db13b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -11,29 +11,6 @@ const ( // See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10 MaxAlphabetNodes = 22 - EndpointFlag = "rpc-endpoint" - EndpointFlagDesc = "N3 RPC node endpoint" - EndpointFlagShort = "r" - AlphabetWalletsFlag = "alphabet-wallets" - AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" - LocalDumpFlag = "local-dump" - ContractsInitFlag = "contracts" - ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" - ContractsURLFlag = "contracts-url" - ContractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" - EpochDurationInitFlag = "network.epoch_duration" - MaxObjectSizeInitFlag = "network.max_object_size" - RefillGasAmountFlag = "gas" - StorageWalletFlag = "storage-wallet" - ContainerFeeInitFlag = "network.fee.container" - ContainerAliasFeeInitFlag = "network.fee.container_alias" - CandidateFeeInitFlag = "network.fee.candidate" - WithdrawFeeInitFlag = "network.fee.withdraw" - MaintenanceModeAllowedInitFlag = "network.maintenance_mode_allowed" - HomomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" - CustomZoneFlag = "domain" - AlphabetSizeFlag = "size" - SingleAccountName = "single" CommitteeAccountName = "committee" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go index 4305df1e57..19f8bbb68f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go @@ -9,6 +9,7 @@ import ( "path/filepath" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -79,7 +80,7 @@ func (cs *ContractState) Parse() error { } func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContext, error) { - walletDir := config.ResolveHomePath(viper.GetString(AlphabetWalletsFlag)) + walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) wallets, err := GetAlphabetWallets(v, walletDir) if err != nil { return nil, err @@ -119,7 +120,7 @@ func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContex var ctrURL string if needContracts { - ctrURL, _ = cmd.Flags().GetString(ContractsURLFlag) + ctrURL, _ = cmd.Flags().GetString(commonflags.ContractsURLFlag) } if err := CheckNotaryEnabled(c); err != nil { @@ -163,11 +164,11 @@ func validateInit(cmd *cobra.Command) error { if cmd.Name() != "init" { return nil } - if viper.GetInt64(EpochDurationInitFlag) <= 0 { + if viper.GetInt64(commonflags.EpochDurationInitFlag) <= 0 { return fmt.Errorf("epoch duration must be positive") } - if viper.GetInt64(MaxObjectSizeInitFlag) <= 0 { + if viper.GetInt64(commonflags.MaxObjectSizeInitFlag) <= 0 { return fmt.Errorf("max object size must be positive") } @@ -177,9 +178,9 @@ func validateInit(cmd *cobra.Command) error { func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet) (Client, error) { var c Client var err error - if ldf := cmd.Flags().Lookup(LocalDumpFlag); ldf != nil && ldf.Changed { - if cmd.Flags().Changed(EndpointFlag) { - return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", EndpointFlag, LocalDumpFlag) + if ldf := cmd.Flags().Lookup(commonflags.LocalDumpFlag); ldf != nil && ldf.Changed { + if cmd.Flags().Changed(commonflags.EndpointFlag) { + return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", commonflags.EndpointFlag, commonflags.LocalDumpFlag) } c, err = NewLocalClient(cmd, v, wallets, ldf.Value.String()) } else { @@ -196,7 +197,7 @@ func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) { return "", nil } - ctrPath, err := cmd.Flags().GetString(ContractsInitFlag) + ctrPath, err := cmd.Flags().GetString(commonflags.ContractsInitFlag) if err != nil { return "", fmt.Errorf("invalid contracts path: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/n3client.go b/cmd/frostfs-adm/internal/modules/morph/util/n3client.go index 0cc751cf1d..56a96c4104 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/n3client.go @@ -6,6 +6,7 @@ import ( "fmt" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -55,7 +56,7 @@ func GetN3Client(v *viper.Viper) (Client, error) { ) ctx := context.Background() - endpoint := v.GetString(EndpointFlag) + endpoint := v.GetString(commonflags.EndpointFlag) if endpoint == "" { return nil, errors.New("missing endpoint") } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go index bfe8ea165f..5aa304732c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -29,14 +30,14 @@ var NetmapConfigKeys = []string{ func GetDefaultNetmapContractConfigMap() map[string]any { m := make(map[string]any) - m[netmap.EpochDurationConfig] = viper.GetInt64(EpochDurationInitFlag) - m[netmap.MaxObjectSizeConfig] = viper.GetInt64(MaxObjectSizeInitFlag) - m[netmap.ContainerFeeConfig] = viper.GetInt64(ContainerFeeInitFlag) - m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(ContainerAliasFeeInitFlag) - m[netmap.IrCandidateFeeConfig] = viper.GetInt64(CandidateFeeInitFlag) - m[netmap.WithdrawFeeConfig] = viper.GetInt64(WithdrawFeeInitFlag) - m[netmap.HomomorphicHashingDisabledKey] = viper.GetBool(HomomorphicHashDisabledInitFlag) - m[netmap.MaintenanceModeAllowedConfig] = viper.GetBool(MaintenanceModeAllowedInitFlag) + m[netmap.EpochDurationConfig] = viper.GetInt64(commonflags.EpochDurationInitFlag) + m[netmap.MaxObjectSizeConfig] = viper.GetInt64(commonflags.MaxObjectSizeInitFlag) + m[netmap.ContainerFeeConfig] = viper.GetInt64(commonflags.ContainerFeeInitFlag) + m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(commonflags.ContainerAliasFeeInitFlag) + m[netmap.IrCandidateFeeConfig] = viper.GetInt64(commonflags.CandidateFeeInitFlag) + m[netmap.WithdrawFeeConfig] = viper.GetInt64(commonflags.WithdrawFeeInitFlag) + m[netmap.HomomorphicHashingDisabledKey] = viper.GetBool(commonflags.HomomorphicHashDisabledInitFlag) + m[netmap.MaintenanceModeAllowedConfig] = viper.GetBool(commonflags.MaintenanceModeAllowedInitFlag) return m } From e2cee4cf09474f757f64958e25f73e3f605e526d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 15:26:57 +0300 Subject: [PATCH 0370/1413] [#932] adm: Move `const` to package `constants` Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/ape/ape_util.go | 5 +- .../internal/modules/morph/balance/balance.go | 5 +- .../internal/modules/morph/config/config.go | 5 +- .../morph/{util => constants}/const.go | 2 +- .../modules/morph/container/container.go | 5 +- .../internal/modules/morph/contract/deploy.go | 9 +-- .../modules/morph/contract/dump_hashes.go | 5 +- .../internal/modules/morph/contract/update.go | 21 +++---- .../modules/morph/frostfsid/frostfsid.go | 3 +- .../modules/morph/generate/generate.go | 11 ++-- .../modules/morph/generate/generate_test.go | 14 ++--- .../modules/morph/initialize/initialize.go | 3 +- .../morph/initialize/initialize_deploy.go | 11 ++-- .../morph/initialize/initialize_nns.go | 7 ++- .../morph/initialize/initialize_register.go | 5 +- .../morph/initialize/initialize_test.go | 11 ++-- .../morph/initialize/initialize_transfer.go | 7 ++- .../internal/modules/morph/initialize/root.go | 6 +- .../internal/modules/morph/netmap/epoch.go | 3 +- .../modules/morph/netmap/netmap_candidates.go | 3 +- .../internal/modules/morph/node/remove.go | 3 +- .../internal/modules/morph/proxy/proxy.go | 3 +- .../internal/modules/morph/util/contract.go | 57 ++++++++++--------- .../internal/modules/morph/util/initialize.go | 3 +- .../modules/morph/util/initialize_ctx.go | 25 ++++---- .../modules/morph/util/local_client.go | 5 +- .../internal/modules/morph/util/netmap.go | 3 +- .../internal/modules/morph/util/util.go | 5 +- .../internal/modules/morph/util/wallet.go | 9 +-- 29 files changed, 140 insertions(+), 114 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{util => constants}/const.go (98%) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 7dc5fa0824..13392b1cea 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" @@ -86,7 +87,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) - committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], morphUtil.CommitteeAccountName) + committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], constants.CommitteeAccountName) commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) ac, err := morphUtil.NewActor(c, committeeAcc) @@ -98,7 +99,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac nnsCs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(morphUtil.PolicyContract)) + ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(constants.PolicyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) return morph.NewContractStorage(ac, ch), ac diff --git a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go index 9d16ada466..019c623466 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go @@ -7,6 +7,7 @@ import ( "math/big" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" @@ -64,7 +65,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(morphUtil.NetmapContract)) + nmHash, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -137,7 +138,7 @@ func printStorageNodeBalances(cmd *cobra.Command, inv *invoker.Invoker, nmHash u } func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash util.Uint160) error { - h, err := morphUtil.NNSResolveHash(inv, nnsHash, morphUtil.DomainOf(morphUtil.ProxyContract)) + h, err := morphUtil.NNSResolveHash(inv, nnsHash, morphUtil.DomainOf(constants.ProxyContract)) if err != nil { return fmt.Errorf("can't get hash of the proxy contract: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index b1ed1cc219..f1845c9ce9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -10,6 +10,7 @@ import ( "strings" "text/tabwriter" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" @@ -38,7 +39,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(util.NetmapContract)) + nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -96,7 +97,7 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(util.NetmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/constants/const.go similarity index 98% rename from cmd/frostfs-adm/internal/modules/morph/util/const.go rename to cmd/frostfs-adm/internal/modules/morph/constants/const.go index 7c867db13b..5a7f8f922e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/constants/const.go @@ -1,4 +1,4 @@ -package util +package constants import "time" diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index 46d4921fef..6ba6a31689 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -7,6 +7,7 @@ import ( "os" "sort" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -36,7 +37,7 @@ func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker) (util.Ui if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(morphUtil.ContainerContract)) + ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(constants.ContainerContract)) if err != nil { return util.Uint160{}, err } @@ -307,7 +308,7 @@ func fetchContainerContractHash(wCtx *morphUtil.InitializeContext) (util.Uint160 return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, morphUtil.DomainOf(morphUtil.ContainerContract)) + ch, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, morphUtil.DomainOf(constants.ContainerContract)) if err != nil { return util.Uint160{}, fmt.Errorf("can't fetch container contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go index 67a8d2fac7..e7c4255b52 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -84,7 +85,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { } callHash := management.Hash - method := util.DeployMethodName + method := constants.DeployMethodName zone, _ := cmd.Flags().GetString(commonflags.CustomZoneFlag) domain := ctrName + "." + zone isUpdate, _ := cmd.Flags().GetBool(updateFlag) @@ -94,7 +95,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't fetch contract hash from NNS: %w", err) } callHash = cs.Hash - method = util.UpdateMethodName + method = constants.UpdateMethodName } else { cs.Hash = state.CreateContractHash( c.CommitteeAcc.Contract.ScriptHash(), @@ -147,12 +148,12 @@ func registerNNS(nnsCs *state.Contract, c *util.InitializeContext, zone string, emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, zone, c.CommitteeAcc.Contract.ScriptHash(), - util.FrostfsOpsEmail, int64(3600), int64(600), int64(util.DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, domain, c.CommitteeAcc.Contract.ScriptHash(), - util.FrostfsOpsEmail, int64(3600), int64(600), int64(util.DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) } else { s, ok, err := c.NNSRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index ca1e5433bd..ae72644051 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/io" @@ -51,7 +52,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return dumpCustomZoneHashes(cmd, cs.Hash, zone, c) } - infos := []contractDumpInfo{{name: morphUtil.NNSContract, hash: cs.Hash}} + infos := []contractDumpInfo{{name: constants.NNSContract, hash: cs.Hash}} irSize := 0 for ; irSize < lastGlagoliticLetter; irSize++ { @@ -87,7 +88,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { } } - for _, ctrName := range morphUtil.ContractList { + for _, ctrName := range constants.ContractList { bw.Reset() emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, morphUtil.DomainOf(ctrName), int64(nns.TXT)) diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/update.go b/cmd/frostfs-adm/internal/modules/morph/contract/update.go index b1b0bf1b31..33e49fad86 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/update.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/update.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/common" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -29,7 +30,7 @@ func updateContracts(cmd *cobra.Command, _ []string) error { return fmt.Errorf("initialization error: %w", err) } - if err := morphUtil.DeployNNS(wCtx, morphUtil.UpdateMethodName); err != nil { + if err := morphUtil.DeployNNS(wCtx, constants.UpdateMethodName); err != nil { return err } @@ -37,7 +38,7 @@ func updateContracts(cmd *cobra.Command, _ []string) error { } func updateContractsInternal(c *morphUtil.InitializeContext) error { - alphaCs := c.GetContract(morphUtil.AlphabetContract) + alphaCs := c.GetContract(constants.AlphabetContract) nnsCs, err := c.NNSContractState() if err != nil { @@ -116,7 +117,7 @@ func deployAlphabetAccounts(c *morphUtil.InitializeContext, nnsHash neoUtil.Uint emit.Opcodes(w.BinWriter, opcode.LDSFLD0) emit.Int(w.BinWriter, 3) emit.Opcodes(w.BinWriter, opcode.PACK) - emit.AppCallNoArgs(w.BinWriter, ctrHash, morphUtil.UpdateMethodName, callflag.All) + emit.AppCallNoArgs(w.BinWriter, ctrHash, constants.UpdateMethodName, callflag.All) } if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { if !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { @@ -134,15 +135,15 @@ func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter emit.Opcodes(w.BinWriter, opcode.STSFLD0) emit.AppCall(w.BinWriter, nnsHash, "setPrice", callflag.All, 1) - for _, ctrName := range morphUtil.ContractList { + for _, ctrName := range constants.ContractList { cs := c.GetContract(ctrName) - method := morphUtil.UpdateMethodName + method := constants.UpdateMethodName ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName)) if err != nil { if errors.Is(err, errMissingNNSRecord) { // if contract not found we deploy it instead of update - method = morphUtil.DeployMethodName + method = constants.DeployMethodName } else { return fmt.Errorf("can't resolve hash for contract update: %w", err) } @@ -154,18 +155,18 @@ func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter } invokeHash := management.Hash - if method == morphUtil.UpdateMethodName { + if method == constants.UpdateMethodName { invokeHash = ctrHash } - args, err := morphUtil.GetContractDeployData(c, ctrName, keysParam, morphUtil.UpdateMethodName) + args, err := morphUtil.GetContractDeployData(c, ctrName, keysParam, constants.UpdateMethodName) if err != nil { return fmt.Errorf("%s: getting update params: %v", ctrName, err) } params := morphUtil.GetContractDeployParameters(cs, args) res, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) if err != nil { - if method != morphUtil.UpdateMethodName || !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { + if method != constants.UpdateMethodName || !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { return fmt.Errorf("deploy contract: %w", err) } c.Command.Printf("%s contract is already updated.\n", ctrName) @@ -174,7 +175,7 @@ func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter w.WriteBytes(res.Script) - if method == morphUtil.DeployMethodName { + if method == constants.DeployMethodName { // same actions are done in InitializeContext.setNNS, can be unified domain := ctrName + ".frostfs" script, ok, err := c.NNSRegisterDomainScript(nnsHash, cs.Hash, domain) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 0a64b9e167..e5d246b4e0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -7,6 +7,7 @@ import ( frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -432,7 +433,7 @@ func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { return nil, fmt.Errorf("can't get NNS contract info: %w", err) } - ffsidHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.FrostfsIDContract)) + ffsidHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(constants.FrostfsIDContract)) if err != nil { return nil, fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go index 8db0aecd23..f032ee7089 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -34,7 +35,7 @@ func AlphabetCreds(cmd *cobra.Command, _ []string) error { if size == 0 { return errors.New("size must be > 0") } - if size > morphUtil.MaxAlphabetNodes { + if size > constants.MaxAlphabetNodes { return morphUtil.ErrTooManyAlphabetNodes } @@ -82,7 +83,7 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er if err != nil { return nil, fmt.Errorf("can't create wallet: %w", err) } - if err := w.CreateAccount(morphUtil.SingleAccountName, password); err != nil { + if err := w.CreateAccount(constants.SingleAccountName, password); err != nil { return nil, fmt.Errorf("can't create account: %w", err) } @@ -101,10 +102,10 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er i := i ps := pubs.Copy() errG.Go(func() error { - if err := addMultisigAccount(wallets[i], majCount, morphUtil.CommitteeAccountName, passwords[i], ps); err != nil { + if err := addMultisigAccount(wallets[i], majCount, constants.CommitteeAccountName, passwords[i], ps); err != nil { return fmt.Errorf("can't create committee account: %w", err) } - if err := addMultisigAccount(wallets[i], bftCount, morphUtil.ConsensusAccountName, passwords[i], ps); err != nil { + if err := addMultisigAccount(wallets[i], bftCount, constants.ConsensusAccountName, passwords[i], ps); err != nil { return fmt.Errorf("can't create consentus account: %w", err) } if err := wallets[i].SavePretty(); err != nil { @@ -177,7 +178,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error } if label == "" { - label = morphUtil.SingleAccountName + label = constants.SingleAccountName } if err := w.CreateAccount(label, password); err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go index add00b5ce0..d4a4fee5db 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go @@ -11,7 +11,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -69,7 +69,7 @@ func TestGenerateAlphabet(t *testing.T) { buf.WriteString(strconv.FormatUint(i, 10) + "\r") } - buf.WriteString(util.TestContractPassword + "\r") + buf.WriteString(constants.TestContractPassword + "\r") require.NoError(t, AlphabetCreds(GenerateAlphabetCmd, nil)) var wg sync.WaitGroup @@ -87,12 +87,12 @@ func TestGenerateAlphabet(t *testing.T) { err := a.Decrypt(strconv.FormatUint(i, 10), keys.NEP2ScryptParams()) require.NoError(t, err, "can't decrypt account") switch a.Label { - case util.ConsensusAccountName: + case constants.ConsensusAccountName: require.Equal(t, smartcontract.GetDefaultHonestNodeCount(size), len(a.Contract.Parameters)) - case util.CommitteeAccountName: + case constants.CommitteeAccountName: require.Equal(t, smartcontract.GetMajorityHonestNodeCount(size), len(a.Contract.Parameters)) default: - require.Equal(t, util.SingleAccountName, a.Label) + require.Equal(t, constants.SingleAccountName, a.Label) } } }() @@ -100,11 +100,11 @@ func TestGenerateAlphabet(t *testing.T) { wg.Wait() t.Run("check contract group wallet", func(t *testing.T) { - p := filepath.Join(walletDir, util.ContractWalletFilename) + p := filepath.Join(walletDir, constants.ContractWalletFilename) w, err := wallet.NewWalletFromFile(p) require.NoError(t, err, "contract wallet doesn't exist") require.Equal(t, 1, len(w.Accounts), "contract wallet must have 1 accout") - require.NoError(t, w.Accounts[0].Decrypt(util.TestContractPassword, keys.NEP2ScryptParams())) + require.NoError(t, w.Accounts[0].Decrypt(constants.TestContractPassword, keys.NEP2ScryptParams())) }) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go index d1b766019d..d3903e2267 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go @@ -3,6 +3,7 @@ package initialize import ( "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -28,7 +29,7 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { // 3. Deploy NNS contract. cmd.Println("Stage 3: deploy NNS contract.") - if err := morphUtil.DeployNNS(initCtx, morphUtil.DeployMethodName); err != nil { + if err := morphUtil.DeployNNS(initCtx, constants.DeployMethodName); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go index 9374b9f7ff..417cab2696 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go @@ -3,6 +3,7 @@ package initialize import ( "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" @@ -10,7 +11,7 @@ import ( ) func deployContracts(c *morphUtil.InitializeContext) error { - alphaCs := c.GetContract(morphUtil.AlphabetContract) + alphaCs := c.GetContract(constants.AlphabetContract) var keysParam []any @@ -38,7 +39,7 @@ func deployContracts(c *morphUtil.InitializeContext) error { return fmt.Errorf("could not create actor: %w", err) } - txHash, vub, err := act.SendCall(management.Hash, morphUtil.DeployMethodName, params...) + txHash, vub, err := act.SendCall(management.Hash, constants.DeployMethodName, params...) if err != nil { return fmt.Errorf("can't deploy alphabet #%d contract: %w", i, err) } @@ -46,7 +47,7 @@ func deployContracts(c *morphUtil.InitializeContext) error { c.SentTxs = append(c.SentTxs, morphUtil.HashVUBPair{Hash: txHash, Vub: vub}) } - for _, ctrName := range morphUtil.ContractList { + for _, ctrName := range constants.ContractList { cs := c.GetContract(ctrName) ctrHash := cs.Hash @@ -60,12 +61,12 @@ func deployContracts(c *morphUtil.InitializeContext) error { return fmt.Errorf("can't sign manifest group: %v", err) } - args, err := morphUtil.GetContractDeployData(c, ctrName, keysParam, morphUtil.DeployMethodName) + args, err := morphUtil.GetContractDeployData(c, ctrName, keysParam, constants.DeployMethodName) if err != nil { return fmt.Errorf("%s: getting deploy params: %v", ctrName, err) } params := morphUtil.GetContractDeployParameters(cs, args) - res, err := c.CommitteeAct.MakeCall(management.Hash, morphUtil.DeployMethodName, params...) + res, err := c.CommitteeAct.MakeCall(management.Hash, constants.DeployMethodName, params...) if err != nil { return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go index a9df7127fe..c7c1d5b671 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go @@ -5,6 +5,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -32,7 +33,7 @@ func setNNS(c *morphUtil.InitializeContext) error { bw := io.NewBufBinWriter() emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, "frostfs", c.CommitteeAcc.Contract.ScriptHash(), - morphUtil.FrostfsOpsEmail, int64(3600), int64(600), int64(morphUtil.DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) if err := c.SendCommitteeTx(bw.Bytes(), true); err != nil { return fmt.Errorf("can't add domain root to NNS: %w", err) @@ -42,7 +43,7 @@ func setNNS(c *morphUtil.InitializeContext) error { } } - alphaCs := c.GetContract(morphUtil.AlphabetContract) + alphaCs := c.GetContract(constants.AlphabetContract) for i, acc := range c.Accounts { alphaCs.Hash = state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name) @@ -53,7 +54,7 @@ func setNNS(c *morphUtil.InitializeContext) error { c.Command.Printf("NNS: Set %s -> %s\n", domain, alphaCs.Hash.StringLE()) } - for _, ctrName := range morphUtil.ContractList { + for _, ctrName := range constants.ContractList { cs := c.GetContract(ctrName) domain := ctrName + ".frostfs" diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index cb33aa9856..d3a30485e8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -68,7 +69,7 @@ func registerCandidateRange(c *morphUtil.InitializeContext, start, end int) erro if err != nil { return fmt.Errorf("can't create tx: %w", err) } - if err := c.MultiSign(tx, morphUtil.CommitteeAccountName); err != nil { + if err := c.MultiSign(tx, constants.CommitteeAccountName); err != nil { return fmt.Errorf("can't sign a transaction: %w", err) } @@ -123,7 +124,7 @@ func transferNEOToAlphabetContracts(c *morphUtil.InitializeContext) error { return err } - cs := c.GetContract(morphUtil.AlphabetContract) + cs := c.GetContract(constants.AlphabetContract) amount := initialAlphabetNEOAmount / len(c.Wallets) bw := io.NewBufBinWriter() diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go index 88bf0f45f9..0114410c74 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" cmdConfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" @@ -49,10 +50,10 @@ func TestInitialize(t *testing.T) { testInitialize(t, 16) }) t.Run("max nodes", func(t *testing.T) { - testInitialize(t, util.MaxAlphabetNodes) + testInitialize(t, constants.MaxAlphabetNodes) }) t.Run("too many nodes", func(t *testing.T) { - require.ErrorIs(t, generateTestData(t, t.TempDir(), util.MaxAlphabetNodes+1), util.ErrTooManyAlphabetNodes) + require.ErrorIs(t, generateTestData(t, t.TempDir(), constants.MaxAlphabetNodes+1), util.ErrTooManyAlphabetNodes) }) } @@ -61,7 +62,7 @@ func testInitialize(t *testing.T, committeeSize int) { v := viper.GetViper() require.NoError(t, generateTestData(t, testdataDir, committeeSize)) - v.Set(util.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) + v.Set(constants.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) // Set to the path or remove the next statement to download from the network. require.NoError(t, Cmd.Flags().Set(commonflags.ContractsInitFlag, contractsPath)) @@ -119,7 +120,7 @@ func generateTestData(t *testing.T, dir string, size int) error { return fmt.Errorf("wallet doesn't exist: %w", err) } for _, acc := range w.Accounts { - if acc.Label == util.SingleAccountName { + if acc.Label == constants.SingleAccountName { pub, ok := vm.ParseSignatureContract(acc.Contract.Script) if !ok { return fmt.Errorf("could not parse signature script for %s", acc.Address) @@ -150,7 +151,7 @@ func setTestCredentials(v *viper.Viper, size int) { for i := 0; i < size; i++ { v.Set("credentials."+innerring.GlagoliticLetter(i).String(), strconv.FormatUint(uint64(i), 10)) } - v.Set("credentials.contract", util.TestContractPassword) + v.Set("credentials.contract", constants.TestContractPassword) } func TestNextPollInterval(t *testing.T) { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go index 8e501953bb..cad5f53c24 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -67,7 +68,7 @@ func transferFunds(c *morphUtil.InitializeContext) error { return fmt.Errorf("can't create transfer transaction: %w", err) } - if err := c.MultiSignAndSend(tx, morphUtil.ConsensusAccountName); err != nil { + if err := c.MultiSignAndSend(tx, constants.ConsensusAccountName); err != nil { return fmt.Errorf("can't send transfer transaction: %w", err) } @@ -83,7 +84,7 @@ func transferFundsFinished(c *morphUtil.InitializeContext) (bool, error) { } func transferGASToProxy(c *morphUtil.InitializeContext) error { - proxyCs := c.GetContract(morphUtil.ProxyContract) + proxyCs := c.GetContract(constants.ProxyContract) r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) bal, err := r.BalanceOf(proxyCs.Hash) @@ -100,7 +101,7 @@ func transferGASToProxy(c *morphUtil.InitializeContext) error { return err } - if err := c.MultiSignAndSend(tx, morphUtil.CommitteeAccountName); err != nil { + if err := c.MultiSignAndSend(tx, constants.CommitteeAccountName); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go index 54958991ed..581bef5322 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go @@ -2,7 +2,7 @@ package initialize import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -30,7 +30,7 @@ var Cmd = &cobra.Command{ _ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) _ = viper.BindPFlag(commonflags.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) _ = viper.BindPFlag(commonflags.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) - _ = viper.BindPFlag(util.ProtoConfigPath, cmd.Flags().Lookup(util.ProtoConfigPath)) + _ = viper.BindPFlag(constants.ProtoConfigPath, cmd.Flags().Lookup(constants.ProtoConfigPath)) }, RunE: initializeSideChainCmd, } @@ -46,7 +46,7 @@ func initInitCmd() { // Defaults are taken from neo-preodolenie. Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") - Cmd.Flags().String(util.ProtoConfigPath, "", "Path to the consensus node configuration") + Cmd.Flags().String(constants.ProtoConfigPath, "", "Path to the consensus node configuration") Cmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") Cmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag) } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index 45e29c0297..8e681cc3b3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" @@ -23,7 +24,7 @@ func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(util.NetmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go index f105fe9113..d7ad601dda 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go @@ -2,6 +2,7 @@ package netmap import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" @@ -21,7 +22,7 @@ func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { cs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) - nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(util.NetmapContract)) + nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(constants.NetmapContract)) commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) res, err := inv.Call(nmHash, "netmapCandidates") diff --git a/cmd/frostfs-adm/internal/modules/morph/node/remove.go b/cmd/frostfs-adm/internal/modules/morph/node/remove.go index 0e305c1f4e..e25cb6efb7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/node/remove.go +++ b/cmd/frostfs-adm/internal/modules/morph/node/remove.go @@ -5,6 +5,7 @@ import ( "fmt" netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" @@ -41,7 +42,7 @@ func RemoveNodesCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(util.NetmapContract)) + nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go index a8fd97be26..2549958ef4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go @@ -3,6 +3,7 @@ package proxy import ( "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -47,7 +48,7 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error return fmt.Errorf("can't get NNS contract info: %w", err) } - proxyHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(morphUtil.ProxyContract)) + proxyHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(constants.ProxyContract)) if err != nil { return fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/contract.go b/cmd/frostfs-adm/internal/modules/morph/util/contract.go index 8faa49d1cf..8f3b20e835 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/contract.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/contract.go @@ -3,6 +3,7 @@ package util import ( "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" @@ -18,7 +19,7 @@ func getFrostfsIDAdminFromContract(roInvoker *invoker.Invoker) (util.Uint160, bo if err != nil { return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) } - fidHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(FrostfsIDContract)) + fidHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(constants.FrostfsIDContract)) if err != nil { return util.Uint160{}, false, fmt.Errorf("resolve frostfsid contract hash: %w", err) } @@ -45,19 +46,19 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any items := make([]any, 0, 6) switch ctrName { - case FrostfsContract: + case constants.FrostfsContract: items = append(items, - c.Contracts[ProcessingContract].Hash, + c.Contracts[constants.ProcessingContract].Hash, keysParam, smartcontract.Parameter{}) - case ProcessingContract: - items = append(items, c.Contracts[FrostfsContract].Hash) + case constants.ProcessingContract: + items = append(items, c.Contracts[constants.FrostfsContract].Hash) return items[1:], nil // no notary info - case BalanceContract: + case constants.BalanceContract: items = append(items, - c.Contracts[NetmapContract].Hash, - c.Contracts[ContainerContract].Hash) - case ContainerContract: + c.Contracts[constants.NetmapContract].Hash, + c.Contracts[constants.ContainerContract].Hash) + case constants.ContainerContract: // In case if NNS is updated multiple times, we can't calculate // it's actual hash based on local data, thus query chain. r := management.NewReader(c.ReadOnlyInvoker) @@ -66,21 +67,21 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any return nil, fmt.Errorf("get nns contract: %w", err) } items = append(items, - c.Contracts[NetmapContract].Hash, - c.Contracts[BalanceContract].Hash, - c.Contracts[FrostfsIDContract].Hash, + c.Contracts[constants.NetmapContract].Hash, + c.Contracts[constants.BalanceContract].Hash, + c.Contracts[constants.FrostfsIDContract].Hash, nnsCs.Hash, "container") - case FrostfsIDContract: + case constants.FrostfsIDContract: var ( h util.Uint160 found bool err error ) - if method == UpdateMethodName { + if method == constants.UpdateMethodName { h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker) } - if method != UpdateMethodName || err == nil && !found { + if method != constants.UpdateMethodName || err == nil && !found { h, found, err = GetFrostfsIDAdmin(viper.GetViper()) } if err != nil { @@ -90,11 +91,11 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any if found { items = append(items, h) } else { - items = append(items, c.Contracts[ProxyContract].Hash) + items = append(items, c.Contracts[constants.ProxyContract].Hash) } - case NetmapContract: + case constants.NetmapContract: md := GetDefaultNetmapContractConfigMap() - if method == UpdateMethodName { + if method == constants.UpdateMethodName { if err := MergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil { return nil, err } @@ -106,14 +107,14 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any } items = append(items, - c.Contracts[BalanceContract].Hash, - c.Contracts[ContainerContract].Hash, + c.Contracts[constants.BalanceContract].Hash, + c.Contracts[constants.ContainerContract].Hash, keysParam, configParam) - case ProxyContract: + case constants.ProxyContract: items = nil - case PolicyContract: - items = append(items, c.Contracts[ProxyContract].Hash) + case constants.PolicyContract: + items = append(items, c.Contracts[constants.ProxyContract].Hash) default: panic(fmt.Sprintf("invalid contract name: %s", ctrName)) } @@ -125,7 +126,7 @@ func GetContractDeployParameters(cs *ContractState, deployData []any) []any { } func DeployNNS(c *InitializeContext, method string) error { - cs := c.GetContract(NNSContract) + cs := c.GetContract(constants.NNSContract) h := cs.Hash nnsCs, err := c.NNSContractState() @@ -134,7 +135,7 @@ func DeployNNS(c *InitializeContext, method string) error { } if nnsCs != nil { if nnsCs.NEF.Checksum == cs.NEF.Checksum { - if method == DeployMethodName { + if method == constants.DeployMethodName { c.Command.Println("NNS contract is already deployed.") } else { c.Command.Println("NNS contract is already updated.") @@ -152,16 +153,16 @@ func DeployNNS(c *InitializeContext, method string) error { params := GetContractDeployParameters(cs, nil) invokeHash := management.Hash - if method == UpdateMethodName { + if method == constants.UpdateMethodName { invokeHash = nnsCs.Hash } tx, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) if err != nil { - return fmt.Errorf("failed to create deploy tx for %s: %w", NNSContract, err) + return fmt.Errorf("failed to create deploy tx for %s: %w", constants.NNSContract, err) } - if err := c.MultiSignAndSend(tx, CommitteeAccountName); err != nil { + if err := c.MultiSignAndSend(tx, constants.CommitteeAccountName); err != nil { return fmt.Errorf("can't send deploy transaction: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go index 0e4c22644a..2d676327d0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -23,7 +24,7 @@ import ( "github.com/spf13/viper" ) -var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", MaxAlphabetNodes) +var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", constants.MaxAlphabetNodes) func AwaitTx(cmd *cobra.Command, c Client, txs []HashVUBPair) error { cmd.Println("Waiting for transactions to persist...") diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go index 19f8bbb68f..907ba57fe6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -99,12 +100,12 @@ func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContex return nil, err } - committeeAcc, err := GetWalletAccount(wallets[0], CommitteeAccountName) + committeeAcc, err := GetWalletAccount(wallets[0], constants.CommitteeAccountName) if err != nil { return nil, fmt.Errorf("can't find committee account: %w", err) } - consensusAcc, err := GetWalletAccount(wallets[0], ConsensusAccountName) + consensusAcc, err := GetWalletAccount(wallets[0], constants.ConsensusAccountName) if err != nil { return nil, fmt.Errorf("can't find consensus account: %w", err) } @@ -151,7 +152,7 @@ func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContex } if needContracts { - err := readContracts(initCtx, FullContractList) + err := readContracts(initCtx, constants.FullContractList) if err != nil { return nil, err } @@ -207,7 +208,7 @@ func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) { func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { accounts := make([]*wallet.Account, len(wallets)) for i, w := range wallets { - acc, err := GetWalletAccount(w, SingleAccountName) + acc, err := GetWalletAccount(w, constants.SingleAccountName) if err != nil { return nil, fmt.Errorf("wallet %s is invalid (no single account): %w", w.Path(), err) } @@ -263,7 +264,7 @@ func readContracts(c *InitializeContext, names []string) error { } for _, ctrName := range names { - if ctrName != AlphabetContract { + if ctrName != constants.AlphabetContract { cs := c.Contracts[ctrName] cs.Hash = state.CreateContractHash(c.CommitteeAcc.Contract.ScriptHash(), cs.NEF.Checksum, cs.Manifest.Name) @@ -382,11 +383,11 @@ func (c *InitializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen return fmt.Errorf("could not perform test invocation: %w", err) } - if err := c.MultiSign(tx, CommitteeAccountName); err != nil { + if err := c.MultiSign(tx, constants.CommitteeAccountName); err != nil { return err } if withConsensus { - if err := c.MultiSign(tx, ConsensusAccountName); err != nil { + if err := c.MultiSign(tx, constants.ConsensusAccountName); err != nil { return err } } @@ -414,7 +415,7 @@ func (c *InitializeContext) MultiSign(tx *transaction.Transaction, accType strin // Use parameter context to avoid dealing with signature order. pc := context.NewParameterContext("", network, tx) h := c.CommitteeAcc.Contract.ScriptHash() - if accType == ConsensusAccountName { + if accType == constants.ConsensusAccountName { h = c.ConsensusAcc.Contract.ScriptHash() } for _, w := range c.Wallets { @@ -477,7 +478,7 @@ func (c *InitializeContext) EmitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHas if isAvail { emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, client.NNSGroupKeyName, c.CommitteeAcc.Contract.ScriptHash(), - FrostfsOpsEmail, int64(3600), int64(600), int64(DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) } @@ -498,7 +499,7 @@ func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.U bw := io.NewBufBinWriter() emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, domain, c.CommitteeAcc.Contract.ScriptHash(), - FrostfsOpsEmail, int64(3600), int64(600), int64(DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) emit.Opcodes(bw.BinWriter, opcode.ASSERT) if bw.Err != nil { @@ -535,8 +536,8 @@ func (c *InitializeContext) GetContract(ctrName string) *ContractState { func (c *InitializeContext) GetAlphabetDeployItems(i, n int) []any { items := make([]any, 5) - items[0] = c.Contracts[NetmapContract].Hash - items[1] = c.Contracts[ProxyContract].Hash + items[0] = c.Contracts[constants.NetmapContract].Hash + items[1] = c.Contracts[constants.ProxyContract].Hash items[2] = innerring.GlagoliticLetter(i).String() items[3] = int64(i) items[4] = int64(n) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/local_client.go b/cmd/frostfs-adm/internal/modules/morph/util/local_client.go index 4b001ca84b..35fb07cc4c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/local_client.go @@ -8,6 +8,7 @@ import ( "sort" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core" @@ -47,7 +48,7 @@ type LocalClient struct { } func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) { - cfg, err := config.LoadFile(v.GetString(ProtoConfigPath)) + cfg, err := config.LoadFile(v.GetString(constants.ProtoConfigPath)) if err != nil { return nil, err } @@ -60,7 +61,7 @@ func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ProtocolConfiguration.ValidatorsCount)) accounts := make([]*wallet.Account, len(wallets)) for i := range accounts { - accounts[i], err = GetWalletAccount(wallets[i], ConsensusAccountName) + accounts[i], err = GetWalletAccount(wallets[i], constants.ConsensusAccountName) if err != nil { return nil, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go index 5aa304732c..fbce8a0fa0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go @@ -5,6 +5,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -88,7 +89,7 @@ func GetNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Ite if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } - nmHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(NetmapContract)) + nmHash, err := NNSResolveHash(roInvoker, cs.Hash, DomainOf(constants.NetmapContract)) if err != nil { return nil, fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/util.go b/cmd/frostfs-adm/internal/modules/morph/util/util.go index 1fd9695c3a..d85fa698e5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/util.go @@ -12,6 +12,7 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -27,7 +28,7 @@ func GetAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, err return nil, err } - if len(wallets) > MaxAlphabetNodes { + if len(wallets) > constants.MaxAlphabetNodes { return nil, ErrTooManyAlphabetNodes } return wallets, nil @@ -161,7 +162,7 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*Contr } func GetAlphabetNNSDomain(i int) string { - return AlphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs" + return constants.AlphabetContract + strconv.FormatUint(uint64(i), 10) + ".frostfs" } func ParseGASAmount(s string) (fixedn.Fixed8, error) { diff --git a/cmd/frostfs-adm/internal/modules/morph/util/wallet.go b/cmd/frostfs-adm/internal/modules/morph/util/wallet.go index e0e553d06c..ca722f241d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/wallet.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/wallet.go @@ -6,6 +6,7 @@ import ( "path/filepath" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" @@ -13,12 +14,12 @@ import ( ) func InitializeContractWallet(v *viper.Viper, walletDir string) (*wallet.Wallet, error) { - password, err := config.GetPassword(v, ContractWalletPasswordKey) + password, err := config.GetPassword(v, constants.ContractWalletPasswordKey) if err != nil { return nil, err } - w, err := wallet.NewWallet(filepath.Join(walletDir, ContractWalletFilename)) + w, err := wallet.NewWallet(filepath.Join(walletDir, constants.ContractWalletFilename)) if err != nil { return nil, err } @@ -42,7 +43,7 @@ func InitializeContractWallet(v *viper.Viper, walletDir string) (*wallet.Wallet, } func openContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (*wallet.Wallet, error) { - p := filepath.Join(walletDir, ContractWalletFilename) + p := filepath.Join(walletDir, constants.ContractWalletFilename) w, err := wallet.NewWalletFromFile(p) if err != nil { if !os.IsNotExist(err) { @@ -53,7 +54,7 @@ func openContractWallet(v *viper.Viper, cmd *cobra.Command, walletDir string) (* return InitializeContractWallet(v, walletDir) } - password, err := config.GetPassword(v, ContractWalletPasswordKey) + password, err := config.GetPassword(v, constants.ContractWalletPasswordKey) if err != nil { return nil, err } From 802192cfef65640f5de193270384d58a6ec1117d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 2 Feb 2024 15:36:14 +0300 Subject: [PATCH 0371/1413] [#932] adm: Rename `util` to `helper` To avoid conflicts with `util` packages in other imports. Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/ape/ape_util.go | 12 +++++----- .../internal/modules/morph/balance/balance.go | 18 +++++++------- .../internal/modules/morph/config/config.go | 14 +++++------ .../modules/morph/container/container.go | 18 +++++++------- .../internal/modules/morph/contract/deploy.go | 10 ++++---- .../modules/morph/contract/dump_hashes.go | 20 ++++++++-------- .../internal/modules/morph/contract/update.go | 24 +++++++++---------- .../modules/morph/frostfsid/frostfsid.go | 8 +++---- .../morph/frostfsid/frostfsid_util_test.go | 8 +++---- .../modules/morph/generate/generate.go | 10 ++++---- .../morph/{util => helper}/contract.go | 2 +- .../morph/{util => helper}/download.go | 2 +- .../morph/{util => helper}/frostfsid.go | 2 +- .../modules/morph/{util => helper}/group.go | 2 +- .../morph/{util => helper}/initialize.go | 2 +- .../morph/{util => helper}/initialize_ctx.go | 2 +- .../morph/{util => helper}/local_client.go | 2 +- .../morph/{util => helper}/n3client.go | 2 +- .../modules/morph/{util => helper}/netmap.go | 2 +- .../modules/morph/{util => helper}/util.go | 2 +- .../modules/morph/{util => helper}/wallet.go | 2 +- .../modules/morph/initialize/initialize.go | 6 ++--- .../morph/initialize/initialize_deploy.go | 16 ++++++------- .../morph/initialize/initialize_nns.go | 10 ++++---- .../morph/initialize/initialize_register.go | 14 +++++------ .../morph/initialize/initialize_roles.go | 8 +++---- .../morph/initialize/initialize_test.go | 16 ++++++------- .../morph/initialize/initialize_transfer.go | 10 ++++---- .../internal/modules/morph/netmap/epoch.go | 8 +++---- .../modules/morph/netmap/netmap_candidates.go | 6 ++--- .../internal/modules/morph/node/remove.go | 8 +++---- .../internal/modules/morph/notary/notary.go | 10 ++++---- .../internal/modules/morph/policy/policy.go | 6 ++--- .../internal/modules/morph/proxy/proxy.go | 6 ++--- 34 files changed, 144 insertions(+), 144 deletions(-) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/contract.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/download.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/frostfsid.go (98%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/group.go (98%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/initialize.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/initialize_ctx.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/local_client.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/n3client.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/netmap.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/util.go (99%) rename cmd/frostfs-adm/internal/modules/morph/{util => helper}/wallet.go (99%) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 13392b1cea..bbbdf78057 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -8,7 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -80,17 +80,17 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *actor.Actor) { v := viper.GetViper() - c, err := morphUtil.GetN3Client(v) + c, err := helper.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) - wallets, err := morphUtil.GetAlphabetWallets(v, walletDir) + wallets, err := helper.GetAlphabetWallets(v, walletDir) commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) - committeeAcc, err := morphUtil.GetWalletAccount(wallets[0], constants.CommitteeAccountName) + committeeAcc, err := helper.GetWalletAccount(wallets[0], constants.CommitteeAccountName) commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) - ac, err := morphUtil.NewActor(c, committeeAcc) + ac, err := helper.NewActor(c, committeeAcc) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) inv := &ac.Invoker @@ -99,7 +99,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac nnsCs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(constants.PolicyContract)) + ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) return morph.NewContractStorage(ac, ch), ac diff --git a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go index 019c623466..428fb98b9c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go @@ -8,7 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -51,7 +51,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { nmHash util.Uint160 ) - c, err := morphUtil.GetN3Client(viper.GetViper()) + c, err := helper.GetN3Client(viper.GetViper()) if err != nil { return err } @@ -65,7 +65,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(constants.NetmapContract)) + nmHash, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -138,7 +138,7 @@ func printStorageNodeBalances(cmd *cobra.Command, inv *invoker.Invoker, nmHash u } func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash util.Uint160) error { - h, err := morphUtil.NNSResolveHash(inv, nnsHash, morphUtil.DomainOf(constants.ProxyContract)) + h, err := helper.NNSResolveHash(inv, nnsHash, helper.DomainOf(constants.ProxyContract)) if err != nil { return fmt.Errorf("can't get hash of the proxy contract: %w", err) } @@ -152,13 +152,13 @@ func printProxyContractBalance(cmd *cobra.Command, inv *invoker.Invoker, nnsHash return nil } -func printAlphabetContractBalances(cmd *cobra.Command, c morphUtil.Client, inv *invoker.Invoker, count int, nnsHash util.Uint160) error { +func printAlphabetContractBalances(cmd *cobra.Command, c helper.Client, inv *invoker.Invoker, count int, nnsHash util.Uint160) error { alphaList := make([]accBalancePair, count) w := io.NewBufBinWriter() for i := range alphaList { emit.AppCall(w.BinWriter, nnsHash, "resolve", callflag.ReadOnly, - morphUtil.GetAlphabetNNSDomain(i), + helper.GetAlphabetNNSDomain(i), int64(nns.TXT)) } if w.Err != nil { @@ -171,7 +171,7 @@ func printAlphabetContractBalances(cmd *cobra.Command, c morphUtil.Client, inv * } for i := range alphaList { - h, err := morphUtil.ParseNNSResolveResult(alphaRes.Stack[i]) + h, err := helper.ParseNNSResolveResult(alphaRes.Stack[i]) if err != nil { return fmt.Errorf("can't fetch the alphabet contract #%d hash: %w", i, err) } @@ -186,7 +186,7 @@ func printAlphabetContractBalances(cmd *cobra.Command, c morphUtil.Client, inv * return nil } -func fetchIRNodes(c morphUtil.Client, desigHash util.Uint160) ([]accBalancePair, error) { +func fetchIRNodes(c helper.Client, desigHash util.Uint160) ([]accBalancePair, error) { inv := invoker.New(c, nil) height, err := c.GetBlockCount() @@ -194,7 +194,7 @@ func fetchIRNodes(c morphUtil.Client, desigHash util.Uint160) ([]accBalancePair, return nil, fmt.Errorf("can't get block height: %w", err) } - arr, err := morphUtil.GetDesignatedByRole(inv, desigHash, noderoles.NeoFSAlphabet, height) + arr, err := helper.GetDesignatedByRole(inv, desigHash, noderoles.NeoFSAlphabet, height) if err != nil { return nil, errors.New("can't fetch list of IR nodes from the netmap contract") } diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index f1845c9ce9..3414a8f7f4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -11,7 +11,7 @@ import ( "text/tabwriter" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -26,7 +26,7 @@ import ( const forceConfigSet = "force" func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { - c, err := util.GetN3Client(viper.GetViper()) + c, err := helper.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -39,7 +39,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(constants.NetmapContract)) + nmHash, err := helper.NNSResolveHash(inv, cs.Hash, helper.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -52,7 +52,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { buf := bytes.NewBuffer(nil) tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) - m, err := util.ParseConfigFromNetmapContract(arr) + m, err := helper.ParseConfigFromNetmapContract(arr) if err != nil { return err } @@ -67,7 +67,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%d (int)\n", k, n))) case netmap.HomomorphicHashingDisabledKey, netmap.MaintenanceModeAllowedConfig: if len(v) == 0 || len(v) > 1 { - return util.InvalidConfigValueErr(k) + return helper.InvalidConfigValueErr(k) } _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%t (bool)\n", k, v[0] == 1))) default: @@ -86,7 +86,7 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { return errors.New("empty config pairs") } - wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't initialize context: %w", err) } @@ -97,7 +97,7 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(constants.NetmapContract)) + nmHash, err := helper.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, helper.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index 6ba6a31689..690db2f4f2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -8,7 +8,7 @@ import ( "sort" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/io" @@ -37,7 +37,7 @@ func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker) (util.Ui if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err = morphUtil.NNSResolveHash(inv, nnsCs.Hash, morphUtil.DomainOf(constants.ContainerContract)) + ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.ContainerContract)) if err != nil { return util.Uint160{}, err } @@ -75,7 +75,7 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid filename: %w", err) } - c, err := morphUtil.GetN3Client(viper.GetViper()) + c, err := helper.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -165,7 +165,7 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo } func listContainers(cmd *cobra.Command, _ []string) error { - c, err := morphUtil.GetN3Client(viper.GetViper()) + c, err := helper.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -194,7 +194,7 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid filename: %w", err) } - wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return err } @@ -223,7 +223,7 @@ func restoreContainers(cmd *cobra.Command, _ []string) error { return wCtx.AwaitTx() } -func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *morphUtil.InitializeContext, ch util.Uint160) error { +func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd *cobra.Command, wCtx *helper.InitializeContext, ch util.Uint160) error { bw := io.NewBufBinWriter() for _, cnt := range containers { hv := hash.Sha256(cnt.Value) @@ -263,7 +263,7 @@ func putContainer(bw *io.BufBinWriter, ch util.Uint160, cnt Container) { } } -func isContainerRestored(cmd *cobra.Command, wCtx *morphUtil.InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { +func isContainerRestored(cmd *cobra.Command, wCtx *helper.InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { emit.AppCall(bw.BinWriter, containerHash, "get", callflag.All, hashValue.BytesBE()) res, err := wCtx.Client.InvokeScript(bw.Bytes(), nil) if err != nil { @@ -301,14 +301,14 @@ func parseContainers(filename string) ([]Container, error) { return containers, nil } -func fetchContainerContractHash(wCtx *morphUtil.InitializeContext) (util.Uint160, error) { +func fetchContainerContractHash(wCtx *helper.InitializeContext) (util.Uint160, error) { r := management.NewReader(wCtx.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } - ch, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, morphUtil.DomainOf(constants.ContainerContract)) + ch, err := helper.NNSResolveHash(wCtx.ReadOnlyInvoker, nnsCs.Hash, helper.DomainOf(constants.ContainerContract)) if err != nil { return util.Uint160{}, fmt.Errorf("can't fetch container contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go index e7c4255b52..9a92e8f19d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -61,7 +61,7 @@ func init() { func deployContractCmd(cmd *cobra.Command, args []string) error { v := viper.GetViper() - c, err := util.NewInitializeContext(cmd, v) + c, err := helper.NewInitializeContext(cmd, v) if err != nil { return fmt.Errorf("initialization error: %w", err) } @@ -73,7 +73,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { return err } - cs, err := util.ReadContract(ctrPath, ctrName) + cs, err := helper.ReadContract(ctrPath, ctrName) if err != nil { return err } @@ -90,7 +90,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { domain := ctrName + "." + zone isUpdate, _ := cmd.Flags().GetBool(updateFlag) if isUpdate { - cs.Hash, err = util.NNSResolveHash(c.ReadOnlyInvoker, nnsCs.Hash, domain) + cs.Hash, err = helper.NNSResolveHash(c.ReadOnlyInvoker, nnsCs.Hash, domain) if err != nil { return fmt.Errorf("can't fetch contract hash from NNS: %w", err) } @@ -130,7 +130,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { return c.AwaitTx() } -func registerNNS(nnsCs *state.Contract, c *util.InitializeContext, zone string, domain string, cs *util.ContractState, writer *io.BufBinWriter) error { +func registerNNS(nnsCs *state.Contract, c *helper.InitializeContext, zone string, domain string, cs *helper.ContractState, writer *io.BufBinWriter) error { bw := io.NewBufBinWriter() emit.Instruction(bw.BinWriter, opcode.INITSSLOT, []byte{1}) emit.AppCall(bw.BinWriter, nnsCs.Hash, "getPrice", callflag.All) diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index ae72644051..6e406be56e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -10,7 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -36,7 +36,7 @@ type contractDumpInfo struct { } func dumpContractHashes(cmd *cobra.Command, _ []string) error { - c, err := morphUtil.GetN3Client(viper.GetViper()) + c, err := helper.GetN3Client(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -56,7 +56,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { irSize := 0 for ; irSize < lastGlagoliticLetter; irSize++ { - ok, err := morphUtil.NNSIsAvailable(c, cs.Hash, morphUtil.GetAlphabetNNSDomain(irSize)) + ok, err := helper.NNSIsAvailable(c, cs.Hash, helper.GetAlphabetNNSDomain(irSize)) if err != nil { return err } else if ok { @@ -70,7 +70,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { bw.Reset() for i := 0; i < irSize; i++ { emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, - morphUtil.GetAlphabetNNSDomain(i), + helper.GetAlphabetNNSDomain(i), int64(nns.TXT)) } @@ -81,7 +81,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { for i := 0; i < irSize; i++ { info := contractDumpInfo{name: fmt.Sprintf("alphabet %d", i)} - if h, err := morphUtil.ParseNNSResolveResult(alphaRes.Stack[i]); err == nil { + if h, err := helper.ParseNNSResolveResult(alphaRes.Stack[i]); err == nil { info.hash = h } infos = append(infos, info) @@ -91,7 +91,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { for _, ctrName := range constants.ContractList { bw.Reset() emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, - morphUtil.DomainOf(ctrName), int64(nns.TXT)) + helper.DomainOf(ctrName), int64(nns.TXT)) res, err := c.InvokeScript(bw.Bytes(), nil) if err != nil { @@ -100,7 +100,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { info := contractDumpInfo{name: ctrName} if len(res.Stack) != 0 { - if h, err := morphUtil.ParseNNSResolveResult(res.Stack[0]); err == nil { + if h, err := helper.ParseNNSResolveResult(res.Stack[0]); err == nil { info.hash = h } } @@ -113,7 +113,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return nil } -func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c morphUtil.Client) error { +func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, c helper.Client) error { const nnsMaxTokens = 100 inv := invoker.New(c, nil) @@ -135,7 +135,7 @@ func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, return } - h, err := morphUtil.NNSResolveHash(inv, nnsHash, string(bs)) + h, err := helper.NNSResolveHash(inv, nnsHash, string(bs)) if err != nil { cmd.PrintErrf("Could not resolve name %s: %v\n", string(bs), err) return @@ -227,7 +227,7 @@ func printContractInfo(cmd *cobra.Command, infos []contractDumpInfo) { cmd.Print(buf.String()) } -func fillContractVersion(cmd *cobra.Command, c morphUtil.Client, infos []contractDumpInfo) { +func fillContractVersion(cmd *cobra.Command, c helper.Client, infos []contractDumpInfo) { bw := io.NewBufBinWriter() sub := io.NewBufBinWriter() for i := range infos { diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/update.go b/cmd/frostfs-adm/internal/modules/morph/contract/update.go index 33e49fad86..109849aab9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/update.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/update.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/common" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/encoding/address" io2 "github.com/nspcc-dev/neo-go/pkg/io" @@ -25,19 +25,19 @@ import ( var errMissingNNSRecord = errors.New("missing NNS record") func updateContracts(cmd *cobra.Command, _ []string) error { - wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("initialization error: %w", err) } - if err := morphUtil.DeployNNS(wCtx, constants.UpdateMethodName); err != nil { + if err := helper.DeployNNS(wCtx, constants.UpdateMethodName); err != nil { return err } return updateContractsInternal(wCtx) } -func updateContractsInternal(c *morphUtil.InitializeContext) error { +func updateContractsInternal(c *helper.InitializeContext) error { alphaCs := c.GetContract(constants.AlphabetContract) nnsCs, err := c.NNSContractState() @@ -90,14 +90,14 @@ func updateContractsInternal(c *morphUtil.InitializeContext) error { return c.AwaitTx() } -func deployAlphabetAccounts(c *morphUtil.InitializeContext, nnsHash neoUtil.Uint160, w *io2.BufBinWriter, alphaCs *morphUtil.ContractState) ([]any, error) { +func deployAlphabetAccounts(c *helper.InitializeContext, nnsHash neoUtil.Uint160, w *io2.BufBinWriter, alphaCs *helper.ContractState) ([]any, error) { var keysParam []any baseGroups := alphaCs.Manifest.Groups // alphabet contracts should be deployed by individual nodes to get different hashes. for i, acc := range c.Accounts { - ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.GetAlphabetNNSDomain(i)) + ctrHash, err := helper.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, helper.GetAlphabetNNSDomain(i)) if err != nil { return nil, fmt.Errorf("can't resolve hash for contract update: %w", err) } @@ -108,7 +108,7 @@ func deployAlphabetAccounts(c *morphUtil.InitializeContext, nnsHash neoUtil.Uint emit.Array(w.BinWriter, params...) alphaCs.Manifest.Groups = baseGroups - err = morphUtil.AddManifestGroup(c.ContractWallet, ctrHash, alphaCs) + err = helper.AddManifestGroup(c.ContractWallet, ctrHash, alphaCs) if err != nil { return nil, fmt.Errorf("can't sign manifest group: %v", err) } @@ -129,7 +129,7 @@ func deployAlphabetAccounts(c *morphUtil.InitializeContext, nnsHash neoUtil.Uint return keysParam, nil } -func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter, nnsHash neoUtil.Uint160, keysParam []any) error { +func deployOrUpdateContracts(c *helper.InitializeContext, w *io2.BufBinWriter, nnsHash neoUtil.Uint160, keysParam []any) error { emit.Instruction(w.BinWriter, opcode.INITSSLOT, []byte{1}) emit.AppCall(w.BinWriter, nnsHash, "getPrice", callflag.All) emit.Opcodes(w.BinWriter, opcode.STSFLD0) @@ -139,7 +139,7 @@ func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter cs := c.GetContract(ctrName) method := constants.UpdateMethodName - ctrHash, err := morphUtil.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, morphUtil.DomainOf(ctrName)) + ctrHash, err := helper.NNSResolveHash(c.ReadOnlyInvoker, nnsHash, helper.DomainOf(ctrName)) if err != nil { if errors.Is(err, errMissingNNSRecord) { // if contract not found we deploy it instead of update @@ -149,7 +149,7 @@ func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter } } - err = morphUtil.AddManifestGroup(c.ContractWallet, ctrHash, cs) + err = helper.AddManifestGroup(c.ContractWallet, ctrHash, cs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } @@ -159,11 +159,11 @@ func deployOrUpdateContracts(c *morphUtil.InitializeContext, w *io2.BufBinWriter invokeHash = ctrHash } - args, err := morphUtil.GetContractDeployData(c, ctrName, keysParam, constants.UpdateMethodName) + args, err := helper.GetContractDeployData(c, ctrName, keysParam, constants.UpdateMethodName) if err != nil { return fmt.Errorf("%s: getting update params: %v", ctrName, err) } - params := morphUtil.GetContractDeployParameters(cs, args) + params := helper.GetContractDeployParameters(cs, args) res, err := c.CommitteeAct.MakeCall(invokeHash, method, params...) if err != nil { if method != constants.UpdateMethodName || !strings.Contains(err.Error(), common.ErrAlreadyUpdated) { diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index e5d246b4e0..0c791d3910 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -8,7 +8,7 @@ import ( frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -418,11 +418,11 @@ type frostfsidClient struct { bw *io.BufBinWriter contractHash util.Uint160 roCli *frostfsidclient.Client // client can be used only for waiting tx, parsing and forming method params - wCtx *morphUtil.InitializeContext + wCtx *helper.InitializeContext } func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { - wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return nil, fmt.Errorf("can't to initialize context: %w", err) } @@ -433,7 +433,7 @@ func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { return nil, fmt.Errorf("can't get NNS contract info: %w", err) } - ffsidHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(constants.FrostfsIDContract)) + ffsidHash, err := helper.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, helper.DomainOf(constants.FrostfsIDContract)) if err != nil { return nil, fmt.Errorf("can't get proxy contract hash: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go index fa6d07bf24..cce859d2fd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go @@ -4,7 +4,7 @@ import ( "encoding/hex" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -31,7 +31,7 @@ func TestFrostfsIDConfig(t *testing.T) { v := viper.New() v.Set("frostfsid.admin", fmts[i]) - actual, found, err := util.GetFrostfsIDAdmin(v) + actual, found, err := helper.GetFrostfsIDAdmin(v) require.NoError(t, err) require.True(t, found) require.Equal(t, pks[i].GetScriptHash(), actual) @@ -41,14 +41,14 @@ func TestFrostfsIDConfig(t *testing.T) { v := viper.New() v.Set("frostfsid.admin", "abc") - _, found, err := util.GetFrostfsIDAdmin(v) + _, found, err := helper.GetFrostfsIDAdmin(v) require.Error(t, err) require.True(t, found) }) t.Run("missing key", func(t *testing.T) { v := viper.New() - _, found, err := util.GetFrostfsIDAdmin(v) + _, found, err := helper.GetFrostfsIDAdmin(v) require.NoError(t, err) require.False(t, found) }) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go index f032ee7089..8ecc9f1b65 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -36,7 +36,7 @@ func AlphabetCreds(cmd *cobra.Command, _ []string) error { return errors.New("size must be > 0") } if size > constants.MaxAlphabetNodes { - return morphUtil.ErrTooManyAlphabetNodes + return helper.ErrTooManyAlphabetNodes } v := viper.GetViper() @@ -46,7 +46,7 @@ func AlphabetCreds(cmd *cobra.Command, _ []string) error { return err } - _, err = morphUtil.InitializeContractWallet(v, walletDir) + _, err = helper.InitializeContractWallet(v, walletDir) if err != nil { return err } @@ -191,12 +191,12 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error gasStr := viper.GetString(gasFlag) - gasAmount, err := morphUtil.ParseGASAmount(gasStr) + gasAmount, err := helper.ParseGASAmount(gasStr) if err != nil { return err } - wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/util/contract.go b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/contract.go rename to cmd/frostfs-adm/internal/modules/morph/helper/contract.go index 8f3b20e835..a740f3f099 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/contract.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go @@ -1,4 +1,4 @@ -package util +package helper import ( "fmt" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/download.go b/cmd/frostfs-adm/internal/modules/morph/helper/download.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/download.go rename to cmd/frostfs-adm/internal/modules/morph/helper/download.go index ff97a7f4a2..08d427a46c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/download.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/download.go @@ -1,4 +1,4 @@ -package util +package helper import ( "context" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid.go similarity index 98% rename from cmd/frostfs-adm/internal/modules/morph/util/frostfsid.go rename to cmd/frostfs-adm/internal/modules/morph/helper/frostfsid.go index 7aea1c4928..f29042b828 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid.go @@ -1,4 +1,4 @@ -package util +package helper import ( "fmt" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/group.go b/cmd/frostfs-adm/internal/modules/morph/helper/group.go similarity index 98% rename from cmd/frostfs-adm/internal/modules/morph/util/group.go rename to cmd/frostfs-adm/internal/modules/morph/helper/group.go index a0306f3bc0..10a164651e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/group.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/group.go @@ -1,4 +1,4 @@ -package util +package helper import ( "encoding/json" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/initialize.go rename to cmd/frostfs-adm/internal/modules/morph/helper/initialize.go index 2d676327d0..00c2fae6d5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go @@ -1,4 +1,4 @@ -package util +package helper import ( "errors" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go rename to cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go index 907ba57fe6..8269f19dc7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go @@ -1,4 +1,4 @@ -package util +package helper import ( "encoding/hex" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/local_client.go rename to cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index 35fb07cc4c..d309e7e5bb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -1,4 +1,4 @@ -package util +package helper import ( "crypto/elliptic" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/n3client.go rename to cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index 56a96c4104..84dd69c79c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -1,4 +1,4 @@ -package util +package helper import ( "context" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/netmap.go rename to cmd/frostfs-adm/internal/modules/morph/helper/netmap.go index fbce8a0fa0..732a5e11fb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go @@ -1,4 +1,4 @@ -package util +package helper import ( "errors" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/util.go b/cmd/frostfs-adm/internal/modules/morph/helper/util.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/util.go rename to cmd/frostfs-adm/internal/modules/morph/helper/util.go index d85fa698e5..f0399ab377 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/util.go @@ -1,4 +1,4 @@ -package util +package helper import ( "archive/tar" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/wallet.go b/cmd/frostfs-adm/internal/modules/morph/helper/wallet.go similarity index 99% rename from cmd/frostfs-adm/internal/modules/morph/util/wallet.go rename to cmd/frostfs-adm/internal/modules/morph/helper/wallet.go index ca722f241d..bd01cd59ed 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/wallet.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/wallet.go @@ -1,4 +1,4 @@ -package util +package helper import ( "fmt" diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go index d3903e2267..cdaf7d3bca 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go @@ -4,13 +4,13 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/spf13/cobra" "github.com/spf13/viper" ) func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { - initCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) + initCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("initialization error: %w", err) } @@ -29,7 +29,7 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { // 3. Deploy NNS contract. cmd.Println("Stage 3: deploy NNS contract.") - if err := morphUtil.DeployNNS(initCtx, constants.DeployMethodName); err != nil { + if err := helper.DeployNNS(initCtx, constants.DeployMethodName); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go index 417cab2696..f40ea732cd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_deploy.go @@ -4,13 +4,13 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" ) -func deployContracts(c *morphUtil.InitializeContext) error { +func deployContracts(c *helper.InitializeContext) error { alphaCs := c.GetContract(constants.AlphabetContract) var keysParam []any @@ -26,13 +26,13 @@ func deployContracts(c *morphUtil.InitializeContext) error { } alphaCs.Manifest.Groups = baseGroups - err := morphUtil.AddManifestGroup(c.ContractWallet, ctrHash, alphaCs) + err := helper.AddManifestGroup(c.ContractWallet, ctrHash, alphaCs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes()) - params := morphUtil.GetContractDeployParameters(alphaCs, c.GetAlphabetDeployItems(i, len(c.Wallets))) + params := helper.GetContractDeployParameters(alphaCs, c.GetAlphabetDeployItems(i, len(c.Wallets))) act, err := actor.NewSimple(c.Client, acc) if err != nil { @@ -44,7 +44,7 @@ func deployContracts(c *morphUtil.InitializeContext) error { return fmt.Errorf("can't deploy alphabet #%d contract: %w", i, err) } - c.SentTxs = append(c.SentTxs, morphUtil.HashVUBPair{Hash: txHash, Vub: vub}) + c.SentTxs = append(c.SentTxs, helper.HashVUBPair{Hash: txHash, Vub: vub}) } for _, ctrName := range constants.ContractList { @@ -56,16 +56,16 @@ func deployContracts(c *morphUtil.InitializeContext) error { continue } - err := morphUtil.AddManifestGroup(c.ContractWallet, ctrHash, cs) + err := helper.AddManifestGroup(c.ContractWallet, ctrHash, cs) if err != nil { return fmt.Errorf("can't sign manifest group: %v", err) } - args, err := morphUtil.GetContractDeployData(c, ctrName, keysParam, constants.DeployMethodName) + args, err := helper.GetContractDeployData(c, ctrName, keysParam, constants.DeployMethodName) if err != nil { return fmt.Errorf("%s: getting deploy params: %v", ctrName, err) } - params := morphUtil.GetContractDeployParameters(cs, args) + params := helper.GetContractDeployParameters(cs, args) res, err := c.CommitteeAct.MakeCall(management.Hash, constants.DeployMethodName, params...) if err != nil { return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go index c7c1d5b671..7a628d5a32 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go @@ -6,7 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -19,7 +19,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/opcode" ) -func setNNS(c *morphUtil.InitializeContext) error { +func setNNS(c *helper.InitializeContext) error { r := management.NewReader(c.ReadOnlyInvoker) nnsCs, err := r.GetContractByID(1) if err != nil { @@ -47,7 +47,7 @@ func setNNS(c *morphUtil.InitializeContext) error { for i, acc := range c.Accounts { alphaCs.Hash = state.CreateContractHash(acc.Contract.ScriptHash(), alphaCs.NEF.Checksum, alphaCs.Manifest.Name) - domain := morphUtil.GetAlphabetNNSDomain(i) + domain := helper.GetAlphabetNNSDomain(i) if err := nnsRegisterDomain(c, nnsCs.Hash, alphaCs.Hash, domain); err != nil { return err } @@ -74,7 +74,7 @@ func setNNS(c *morphUtil.InitializeContext) error { return c.AwaitTx() } -func updateNNSGroup(c *morphUtil.InitializeContext, nnsHash util.Uint160, pub *keys.PublicKey) error { +func updateNNSGroup(c *helper.InitializeContext, nnsHash util.Uint160, pub *keys.PublicKey) error { bw := io.NewBufBinWriter() keyAlreadyAdded, domainRegCodeEmitted, err := c.EmitUpdateNNSGroupScript(bw, nnsHash, pub) if keyAlreadyAdded || err != nil { @@ -115,7 +115,7 @@ func wrapRegisterScriptWithPrice(w *io.BufBinWriter, nnsHash util.Uint160, s []b } } -func nnsRegisterDomain(c *morphUtil.InitializeContext, nnsHash, expectedHash util.Uint160, domain string) error { +func nnsRegisterDomain(c *helper.InitializeContext, nnsHash, expectedHash util.Uint160, domain string) error { script, ok, err := c.NNSRegisterDomainScript(nnsHash, expectedHash, domain) if ok || err != nil { return err diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index d3a30485e8..6a0a880167 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -6,7 +6,7 @@ import ( "math/big" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -29,7 +29,7 @@ const ( registerBatchSize = transaction.MaxAttributes - 1 ) -func registerCandidateRange(c *morphUtil.InitializeContext, start, end int) error { +func registerCandidateRange(c *helper.InitializeContext, start, end int) error { regPrice, err := getCandidateRegisterPrice(c) if err != nil { return fmt.Errorf("can't fetch registration price: %w", err) @@ -83,7 +83,7 @@ func registerCandidateRange(c *morphUtil.InitializeContext, start, end int) erro return c.SendTx(tx, c.Command, true) } -func registerCandidates(c *morphUtil.InitializeContext) error { +func registerCandidates(c *helper.InitializeContext) error { cc, err := unwrap.Array(c.ReadOnlyInvoker.Call(neo.Hash, "getCandidates")) if err != nil { return fmt.Errorf("`getCandidates`: %w", err) @@ -116,7 +116,7 @@ func registerCandidates(c *morphUtil.InitializeContext) error { return nil } -func transferNEOToAlphabetContracts(c *morphUtil.InitializeContext) error { +func transferNEOToAlphabetContracts(c *helper.InitializeContext) error { neoHash := neo.Hash ok, err := transferNEOFinished(c, neoHash) @@ -142,7 +142,7 @@ func transferNEOToAlphabetContracts(c *morphUtil.InitializeContext) error { return c.AwaitTx() } -func transferNEOFinished(c *morphUtil.InitializeContext, neoHash util.Uint160) (bool, error) { +func transferNEOFinished(c *helper.InitializeContext, neoHash util.Uint160) (bool, error) { r := nep17.NewReader(c.ReadOnlyInvoker, neoHash) bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash()) return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err @@ -150,7 +150,7 @@ func transferNEOFinished(c *morphUtil.InitializeContext, neoHash util.Uint160) ( var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response") -func getCandidateRegisterPrice(c *morphUtil.InitializeContext) (int64, error) { +func getCandidateRegisterPrice(c *helper.InitializeContext) (int64, error) { switch c.Client.(type) { case *rpcclient.Client: inv := invoker.New(c.Client, nil) @@ -158,7 +158,7 @@ func getCandidateRegisterPrice(c *morphUtil.InitializeContext) (int64, error) { return reader.GetRegisterPrice() default: neoHash := neo.Hash - res, err := morphUtil.InvokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil) + res, err := helper.InvokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil) if err != nil { return 0, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go index d7f17ccfb9..a6815ee13b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go @@ -1,7 +1,7 @@ package initialize import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/rolemgmt" @@ -9,7 +9,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/emit" ) -func setNotaryAndAlphabetNodes(c *util.InitializeContext) error { +func setNotaryAndAlphabetNodes(c *helper.InitializeContext) error { if ok, err := setRolesFinished(c); ok || err != nil { if err == nil { c.Command.Println("Stage 2: already performed.") @@ -35,12 +35,12 @@ func setNotaryAndAlphabetNodes(c *util.InitializeContext) error { return c.AwaitTx() } -func setRolesFinished(c *util.InitializeContext) (bool, error) { +func setRolesFinished(c *helper.InitializeContext) (bool, error) { height, err := c.Client.GetBlockCount() if err != nil { return false, err } - pubs, err := util.GetDesignatedByRole(c.ReadOnlyInvoker, rolemgmt.Hash, noderoles.NeoFSAlphabet, height) + pubs, err := helper.GetDesignatedByRole(c.ReadOnlyInvoker, rolemgmt.Hash, noderoles.NeoFSAlphabet, height) return len(pubs) == len(c.Wallets), err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go index 0114410c74..a05e995a75 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go @@ -13,10 +13,10 @@ import ( cmdConfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -53,7 +53,7 @@ func TestInitialize(t *testing.T) { testInitialize(t, constants.MaxAlphabetNodes) }) t.Run("too many nodes", func(t *testing.T) { - require.ErrorIs(t, generateTestData(t, t.TempDir(), constants.MaxAlphabetNodes+1), util.ErrTooManyAlphabetNodes) + require.ErrorIs(t, generateTestData(t, t.TempDir(), constants.MaxAlphabetNodes+1), helper.ErrTooManyAlphabetNodes) }) } @@ -158,33 +158,33 @@ func TestNextPollInterval(t *testing.T) { var pollInterval time.Duration var iteration int - pollInterval, hasChanged := util.NextPollInterval(iteration, pollInterval) + pollInterval, hasChanged := helper.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, time.Second, pollInterval) iteration = 4 - pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) require.False(t, hasChanged) require.Equal(t, time.Second, pollInterval) iteration = 5 - pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, 2*time.Second, pollInterval) iteration = 10 - pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) require.Equal(t, 4*time.Second, pollInterval) iteration = 20 pollInterval = 32 * time.Second - pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) require.True(t, hasChanged) // from 32s to 16s require.Equal(t, 16*time.Second, pollInterval) pollInterval = 16 * time.Second - pollInterval, hasChanged = util.NextPollInterval(iteration, pollInterval) + pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) require.False(t, hasChanged) require.Equal(t, 16*time.Second, pollInterval) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go index cad5f53c24..8bcd7eb589 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go @@ -5,7 +5,7 @@ import ( "math/big" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" @@ -28,7 +28,7 @@ const ( initialProxyGASAmount = 50_000 * native.GASFactor ) -func transferFunds(c *morphUtil.InitializeContext) error { +func transferFunds(c *helper.InitializeContext) error { ok, err := transferFundsFinished(c) if ok || err != nil { if err == nil { @@ -75,7 +75,7 @@ func transferFunds(c *morphUtil.InitializeContext) error { return c.AwaitTx() } -func transferFundsFinished(c *morphUtil.InitializeContext) (bool, error) { +func transferFundsFinished(c *helper.InitializeContext) (bool, error) { acc := c.Accounts[0] r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) @@ -83,7 +83,7 @@ func transferFundsFinished(c *morphUtil.InitializeContext) (bool, error) { return res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) == 1, err } -func transferGASToProxy(c *morphUtil.InitializeContext) error { +func transferGASToProxy(c *helper.InitializeContext) error { proxyCs := c.GetContract(constants.ProxyContract) r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) @@ -115,7 +115,7 @@ type transferTarget struct { Data any } -func createNEP17MultiTransferTx(c morphUtil.Client, acc *wallet.Account, recipients []transferTarget) (*transaction.Transaction, error) { +func createNEP17MultiTransferTx(c helper.Client, acc *wallet.Account, recipients []transferTarget) (*transaction.Transaction, error) { from := acc.Contract.ScriptHash() w := io.NewBufBinWriter() diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index 8e681cc3b3..4fd671f2a2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -5,7 +5,7 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/spf13/cobra" @@ -13,7 +13,7 @@ import ( ) func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { - wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -24,13 +24,13 @@ func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(constants.NetmapContract)) + nmHash, err := helper.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, helper.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } bw := io.NewBufBinWriter() - if err := util.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { + if err := helper.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go index d7ad601dda..e9404e910d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go @@ -3,7 +3,7 @@ package netmap import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -13,7 +13,7 @@ import ( ) func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { - c, err := util.GetN3Client(viper.GetViper()) + c, err := helper.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err) inv := invoker.New(c, nil) @@ -22,7 +22,7 @@ func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { cs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) - nmHash, err := util.NNSResolveHash(inv, cs.Hash, util.DomainOf(constants.NetmapContract)) + nmHash, err := helper.NNSResolveHash(inv, cs.Hash, helper.DomainOf(constants.NetmapContract)) commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) res, err := inv.Call(nmHash, "netmapCandidates") diff --git a/cmd/frostfs-adm/internal/modules/morph/node/remove.go b/cmd/frostfs-adm/internal/modules/morph/node/remove.go index e25cb6efb7..0d14bc6463 100644 --- a/cmd/frostfs-adm/internal/modules/morph/node/remove.go +++ b/cmd/frostfs-adm/internal/modules/morph/node/remove.go @@ -6,7 +6,7 @@ import ( netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" @@ -30,7 +30,7 @@ func RemoveNodesCmd(cmd *cobra.Command, args []string) error { } } - wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't initialize context: %w", err) } @@ -42,7 +42,7 @@ func RemoveNodesCmd(cmd *cobra.Command, args []string) error { return fmt.Errorf("can't get NNS contract info: %w", err) } - nmHash, err := util.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, util.DomainOf(constants.NetmapContract)) + nmHash, err := helper.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, helper.DomainOf(constants.NetmapContract)) if err != nil { return fmt.Errorf("can't get netmap contract hash: %w", err) } @@ -53,7 +53,7 @@ func RemoveNodesCmd(cmd *cobra.Command, args []string) error { int64(netmapcontract.NodeStateOffline), nodeKeys[i].Bytes()) } - if err := util.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { + if err := helper.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go index 3b1bb179f4..6d65a82846 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go @@ -6,7 +6,7 @@ import ( "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -65,7 +65,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error { if err != nil { return err } - gasAmount, err := morphUtil.ParseGASAmount(gasStr) + gasAmount, err := helper.ParseGASAmount(gasStr) if err != nil { return err } @@ -86,12 +86,12 @@ func depositNotary(cmd *cobra.Command, _ []string) error { } func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, gasAmount fixedn.Fixed8, till int64) error { - c, err := morphUtil.GetN3Client(viper.GetViper()) + c, err := helper.GetN3Client(viper.GetViper()) if err != nil { return err } - if err := morphUtil.CheckNotaryEnabled(c); err != nil { + if err := helper.CheckNotaryEnabled(c); err != nil { return err } @@ -123,7 +123,7 @@ func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, return fmt.Errorf("could not send tx: %w", err) } - return morphUtil.AwaitTx(cmd, c, []morphUtil.HashVUBPair{{Hash: txHash, Vub: vub}}) + return helper.AwaitTx(cmd, c, []helper.HashVUBPair{{Hash: txHash, Vub: vub}}) } func openWallet(cmd *cobra.Command) (*wallet.Wallet, error) { diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go index 7f4a8d3269..440e73a12a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go @@ -7,7 +7,7 @@ import ( "strings" "text/tabwriter" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -25,7 +25,7 @@ const ( ) func SetPolicyCmd(cmd *cobra.Command, args []string) error { - wCtx, err := util.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -59,7 +59,7 @@ func SetPolicyCmd(cmd *cobra.Command, args []string) error { } func dumpPolicyCmd(cmd *cobra.Command, _ []string) error { - c, err := util.GetN3Client(viper.GetViper()) + c, err := helper.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client:", err) inv := invoker.New(c, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go index 2549958ef4..7e173ac49a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go @@ -4,7 +4,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" - morphUtil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" @@ -37,7 +37,7 @@ func removeProxyAccount(cmd *cobra.Command, _ []string) { } func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error { - wCtx, err := morphUtil.NewInitializeContext(cmd, viper.GetViper()) + wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't to initialize context: %w", err) } @@ -48,7 +48,7 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error return fmt.Errorf("can't get NNS contract info: %w", err) } - proxyHash, err := morphUtil.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, morphUtil.DomainOf(constants.ProxyContract)) + proxyHash, err := helper.NNSResolveHash(wCtx.ReadOnlyInvoker, cs.Hash, helper.DomainOf(constants.ProxyContract)) if err != nil { return fmt.Errorf("can't get proxy contract hash: %w", err) } From 35370283ba1f6ee815102c33938407b4bd029c03 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 13 Feb 2024 10:08:49 +0300 Subject: [PATCH 0372/1413] [#948] adm: Move `TestNextPollInterval` to package `helper` Signed-off-by: Anton Nikiforov --- .../modules/morph/helper/initialize_test.go | 43 +++++++++++++++++++ .../morph/initialize/initialize_test.go | 35 --------------- 2 files changed, 43 insertions(+), 35 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/helper/initialize_test.go diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_test.go new file mode 100644 index 0000000000..f3ce42f510 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_test.go @@ -0,0 +1,43 @@ +package helper + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestNextPollInterval(t *testing.T) { + var pollInterval time.Duration + var iteration int + + pollInterval, hasChanged := NextPollInterval(iteration, pollInterval) + require.True(t, hasChanged) + require.Equal(t, time.Second, pollInterval) + + iteration = 4 + pollInterval, hasChanged = NextPollInterval(iteration, pollInterval) + require.False(t, hasChanged) + require.Equal(t, time.Second, pollInterval) + + iteration = 5 + pollInterval, hasChanged = NextPollInterval(iteration, pollInterval) + require.True(t, hasChanged) + require.Equal(t, 2*time.Second, pollInterval) + + iteration = 10 + pollInterval, hasChanged = NextPollInterval(iteration, pollInterval) + require.True(t, hasChanged) + require.Equal(t, 4*time.Second, pollInterval) + + iteration = 20 + pollInterval = 32 * time.Second + pollInterval, hasChanged = NextPollInterval(iteration, pollInterval) + require.True(t, hasChanged) // from 32s to 16s + require.Equal(t, 16*time.Second, pollInterval) + + pollInterval = 16 * time.Second + pollInterval, hasChanged = NextPollInterval(iteration, pollInterval) + require.False(t, hasChanged) + require.Equal(t, 16*time.Second, pollInterval) +} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go index a05e995a75..e39c7356f2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go @@ -153,38 +153,3 @@ func setTestCredentials(v *viper.Viper, size int) { } v.Set("credentials.contract", constants.TestContractPassword) } - -func TestNextPollInterval(t *testing.T) { - var pollInterval time.Duration - var iteration int - - pollInterval, hasChanged := helper.NextPollInterval(iteration, pollInterval) - require.True(t, hasChanged) - require.Equal(t, time.Second, pollInterval) - - iteration = 4 - pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) - require.False(t, hasChanged) - require.Equal(t, time.Second, pollInterval) - - iteration = 5 - pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) - require.True(t, hasChanged) - require.Equal(t, 2*time.Second, pollInterval) - - iteration = 10 - pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) - require.True(t, hasChanged) - require.Equal(t, 4*time.Second, pollInterval) - - iteration = 20 - pollInterval = 32 * time.Second - pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) - require.True(t, hasChanged) // from 32s to 16s - require.Equal(t, 16*time.Second, pollInterval) - - pollInterval = 16 * time.Second - pollInterval, hasChanged = helper.NextPollInterval(iteration, pollInterval) - require.False(t, hasChanged) - require.Equal(t, 16*time.Second, pollInterval) -} From 5cbf57081f044d843a704b5d2c5da7367c3a040a Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 13 Feb 2024 16:22:08 +0300 Subject: [PATCH 0373/1413] [#980] adm: Introduce flag `chain-name` for APE managing commands Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/ape/ape.go | 44 ++++++++++--------- .../internal/modules/morph/ape/ape_util.go | 20 +++++++++ 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index 8395fd4ba7..c08dc512e0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -14,22 +14,24 @@ import ( ) const ( - namespaceTarget = "namespace" - containerTarget = "container" - jsonFlag = "json" - jsonFlagDesc = "Output rule chains in JSON format" - chainIDFlag = "chain-id" - chainIDDesc = "Rule chain ID" - ruleFlag = "rule" - ruleFlagDesc = "Rule chain in text format" - ruleJSONFlag = "rule-json" - ruleJSONFlagDesc = "Chain rule in JSON format or path to the file" - targetNameFlag = "target-name" - targetNameDesc = "Resource name in APE resource name format" - targetTypeFlag = "target-type" - targetTypeDesc = "Resource type(container/namespace)" - addrAdminFlag = "addr" - addrAdminDesc = "The address of the admins wallet" + namespaceTarget = "namespace" + containerTarget = "container" + jsonFlag = "json" + jsonFlagDesc = "Output rule chains in JSON format" + chainIDFlag = "chain-id" + chainIDDesc = "Rule chain ID" + ruleFlag = "rule" + ruleFlagDesc = "Rule chain in text format" + ruleJSONFlag = "rule-json" + ruleJSONFlagDesc = "Chain rule in JSON format or path to the file" + targetNameFlag = "target-name" + targetNameDesc = "Resource name in APE resource name format" + targetTypeFlag = "target-type" + targetTypeDesc = "Resource type(container/namespace)" + addrAdminFlag = "addr" + addrAdminDesc = "The address of the admins wallet" + chainNameFlag = "chain-name" + chainNameFlagDesc = "Chain name(ingress|s3)" ) var ( @@ -99,7 +101,7 @@ func initAddRuleChainCmd() { _ = addRuleChainCmd.MarkFlagRequired(chainIDFlag) addRuleChainCmd.Flags().String(ruleFlag, "", ruleFlagDesc) addRuleChainCmd.Flags().String(ruleJSONFlag, "", ruleJSONFlagDesc) - + addRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, ruleJSONFlag) } @@ -115,6 +117,7 @@ func initRemoveRuleChainCmd() { _ = removeRuleChainCmd.MarkFlagRequired(targetNameFlag) removeRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) _ = removeRuleChainCmd.MarkFlagRequired(chainIDFlag) + removeRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) } func initListRuleChainsCmd() { @@ -127,6 +130,7 @@ func initListRuleChainsCmd() { listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc) _ = listRuleChainsCmd.MarkFlagRequired(targetNameFlag) listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc) + listRuleChainsCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) } func initSetAdminCmd() { @@ -149,7 +153,7 @@ func addRuleChain(cmd *cobra.Command, _ []string) { chain := parseChain(cmd) target := parseTarget(cmd) pci, ac := newPolicyContractInterface(cmd) - h, vub, err := pci.AddMorphRuleChain(apechain.Ingress, target, chain) + h, vub, err := pci.AddMorphRuleChain(parseChainName(cmd), target, chain) cmd.Println("Waiting for transaction to persist...") _, err = ac.Wait(h, vub, err) commonCmd.ExitOnErr(cmd, "add rule chain error: %w", err) @@ -160,7 +164,7 @@ func removeRuleChain(cmd *cobra.Command, _ []string) { chainID := parseChainID(cmd) target := parseTarget(cmd) pci, ac := newPolicyContractInterface(cmd) - h, vub, err := pci.RemoveMorphRuleChain(apechain.Ingress, target, chainID) + h, vub, err := pci.RemoveMorphRuleChain(parseChainName(cmd), target, chainID) cmd.Println("Waiting for transaction to persist...") _, err = ac.Wait(h, vub, err) commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) @@ -170,7 +174,7 @@ func removeRuleChain(cmd *cobra.Command, _ []string) { func listRuleChains(cmd *cobra.Command, _ []string) { target := parseTarget(cmd) pci, _ := newPolicyContractInterface(cmd) - chains, err := pci.ListMorphRuleChains(apechain.Ingress, target) + chains, err := pci.ListMorphRuleChains(parseChainName(cmd), target) commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err) if len(chains) == 0 { return diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index bbbdf78057..7f23e3754d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "os" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" @@ -21,6 +22,16 @@ import ( "github.com/spf13/viper" ) +const ( + ingress = "ingress" + s3 = "s3" +) + +var mChainName = map[string]apechain.Name{ + ingress: apechain.Ingress, + s3: apechain.S3, +} + func parseTarget(cmd *cobra.Command) policyengine.Target { var targetType policyengine.TargetType typ, _ := cmd.Flags().GetString(targetTypeFlag) @@ -78,6 +89,15 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { return chain } +func parseChainName(cmd *cobra.Command) apechain.Name { + chainName, _ := cmd.Flags().GetString(chainNameFlag) + apeChainName, ok := mChainName[strings.ToLower(chainName)] + if !ok { + commonCmd.ExitOnErr(cmd, "", fmt.Errorf("unsupported chain name")) + } + return apeChainName +} + func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *actor.Actor) { v := viper.GetViper() c, err := helper.GetN3Client(v) From 2429508ac5df680bebc63c339d1e24a527ef1739 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 14 Feb 2024 15:39:28 +0300 Subject: [PATCH 0374/1413] [#959] shard: Skip rebuild in `DEGRADED` mode Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/shard/control.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 408354b557..774fe8045b 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -173,8 +173,9 @@ func (s *Shard) Init(ctx context.Context) error { s.gc.init(ctx) s.rb = newRebuilder(s.rebuildLimiter) - s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) - + if !m.NoMetabase() { + s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) + } return nil } @@ -327,9 +328,11 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { defer unlock() s.rb.Stop(s.log) - defer func() { - s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) - }() + if !s.info.Mode.NoMetabase() { + defer func() { + s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) + }() + } ok, err := s.metaBase.Reload(c.metaOpts...) if err != nil { From 05b5f5ca851a07c4994608e40dd134ff05042822 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 14 Feb 2024 16:10:33 +0300 Subject: [PATCH 0375/1413] [#959] writecache: Fix panic on `Get` when it is not initialized Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/writecache/get.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/local_object_storage/writecache/get.go b/pkg/local_object_storage/writecache/get.go index d2496e447a..5194446ec1 100644 --- a/pkg/local_object_storage/writecache/get.go +++ b/pkg/local_object_storage/writecache/get.go @@ -84,6 +84,9 @@ func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, // // Returns an error of type apistatus.ObjectNotFound if the requested object is missing in db. func Get(db *bbolt.DB, key []byte) ([]byte, error) { + if db == nil { + return nil, ErrNotInitialized + } var value []byte err := db.View(func(tx *bbolt.Tx) error { b := tx.Bucket(defaultBucket) From 6bafdab004304c445c701f64c3e2d90636bb2ceb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 15 Feb 2024 15:30:42 +0300 Subject: [PATCH 0376/1413] [#988] go.mod: Update api-go and sdk-go versions Signed-off-by: Dmitrii Stepanov --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index aa771f1e7e..d86676dd30 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.20 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240215122347-a86170f53af7 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index e152363316..fa5da98cc3 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c h1:dO2VLtoTQre4W28i1gSuW1MO80qFd0Lq9Q46Pu3q3TA= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 h1:EDtL9OJcdeevV/jmNMtHugulAQprdOnknNPvLB3LRgE= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa h1:uuN90s74idThHXi/jF/IlTdFimOIs+IBU44rdTE/Zdo= git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0 h1:jp/Cg6CF3ip0IVRCjt48qKyv1cbMUmNYTn2z1jFLWqc= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240126141009-65b4525b3bf0/go.mod h1:t1akKcUH7iBrFHX8rSXScYMP17k2kYQXMbZooiL5Juw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240215122347-a86170f53af7 h1:3a5g14oC+aMQ1p0bvuqG3JZKGLOcqRvcHzKAFV4eS0w= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240215122347-a86170f53af7/go.mod h1:XcgrbZ88XfvhAMxmZCQJ0dv6FyRSq6Mg2J7nN8uuO0k= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 h1:hkDIg6vzV1c1pyt5uj9EiBikHqKczfoNpPhwWvXaNf8= From 2680192ba036c518445c5a2d19d5cc49a5edfdaa Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 15 Feb 2024 17:13:29 +0300 Subject: [PATCH 0377/1413] [#988] objectSvc: Fix `SetMarshalData` for PutSingle After api-go update it is required to pass marshal data to `SetMarshalData`. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/sign.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 2f4f9cb9ae..4bf581b787 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -122,7 +122,7 @@ func (s *SignService) Head(ctx context.Context, req *object.HeadRequest) (*objec } func (s *SignService) PutSingle(ctx context.Context, req *object.PutSingleRequest) (*object.PutSingleResponse, error) { - req.GetBody().SetMarshalData(nil) + req.GetBody().SetMarshalData(req.GetBody().StableMarshal(nil)) if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(object.PutSingleResponse) return resp, s.sigSvc.SignResponse(resp, err) From 15fc5bac26fb9bf0f31dc293078acdfb6f620a56 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 14 Feb 2024 12:34:25 +0300 Subject: [PATCH 0378/1413] [#972] keyer: Use UncompressedBytes() for marshaling elliptic.Marshal() becomes deprecated in go1.21 Signed-off-by: Evgenii Stratonikov --- pkg/util/keyer/dashboard.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/util/keyer/dashboard.go b/pkg/util/keyer/dashboard.go index bc5f2e76eb..b2942b52a6 100644 --- a/pkg/util/keyer/dashboard.go +++ b/pkg/util/keyer/dashboard.go @@ -1,7 +1,6 @@ package keyer import ( - "crypto/elliptic" "encoding/hex" "fmt" "os" @@ -45,7 +44,7 @@ func (d Dashboard) PrettyPrint(uncompressed, useHex bool) { if d.pubKey != nil { if uncompressed { - data = elliptic.Marshal(elliptic.P256(), d.pubKey.X, d.pubKey.Y) + data = d.pubKey.UncompressedBytes() } else { data = d.pubKey.Bytes() } From e39a714c257248bfaca9086f38e7b1dc15761a6b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 8 Feb 2024 19:14:10 +0300 Subject: [PATCH 0379/1413] [#972] go.mod: Bump go version to go1.21 Signed-off-by: Evgenii Stratonikov --- .docker/Dockerfile.adm | 2 +- .docker/Dockerfile.ci | 2 +- .docker/Dockerfile.cli | 2 +- .docker/Dockerfile.ir | 2 +- .docker/Dockerfile.storage | 2 +- .forgejo/workflows/build.yml | 2 +- .forgejo/workflows/dco.yml | 2 +- .forgejo/workflows/tests.yml | 6 +++--- .forgejo/workflows/vulncheck.yml | 2 +- Makefile | 2 +- README.md | 2 +- go.mod | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.docker/Dockerfile.adm b/.docker/Dockerfile.adm index eeccaab79c..b3dad06d3d 100644 --- a/.docker/Dockerfile.adm +++ b/.docker/Dockerfile.adm @@ -1,4 +1,4 @@ -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ci b/.docker/Dockerfile.ci index ef6586a641..e9077c8313 100644 --- a/.docker/Dockerfile.ci +++ b/.docker/Dockerfile.ci @@ -1,4 +1,4 @@ -FROM golang:1.21 +FROM golang:1.22 WORKDIR /tmp diff --git a/.docker/Dockerfile.cli b/.docker/Dockerfile.cli index 0dd4cebcf9..5adedc1408 100644 --- a/.docker/Dockerfile.cli +++ b/.docker/Dockerfile.cli @@ -1,4 +1,4 @@ -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ir b/.docker/Dockerfile.ir index 4015df6733..25025bb2fa 100644 --- a/.docker/Dockerfile.ir +++ b/.docker/Dockerfile.ir @@ -1,4 +1,4 @@ -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.storage b/.docker/Dockerfile.storage index ced6ea538e..a16005516a 100644 --- a/.docker/Dockerfile.storage +++ b/.docker/Dockerfile.storage @@ -1,4 +1,4 @@ -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 3c74d94347..86943fe88c 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.20', '1.21' ] + go_versions: [ '1.21', '1.22' ] steps: - uses: actions/checkout@v3 diff --git a/.forgejo/workflows/dco.yml b/.forgejo/workflows/dco.yml index 9aa0d31066..7c5af8410b 100644 --- a/.forgejo/workflows/dco.yml +++ b/.forgejo/workflows/dco.yml @@ -13,7 +13,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' - name: Run commit format checker uses: https://git.frostfs.info/TrueCloudLab/dco-go@v3 diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index f66a2c4017..8b0d9220b4 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' cache: true - name: Install linters @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.20', '1.21' ] + go_versions: [ '1.21', '1.22' ] fail-fast: false steps: - uses: actions/checkout@v3 @@ -63,7 +63,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' cache: true - name: Install staticcheck diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index 8ea01749b2..3af564c4b5 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -13,7 +13,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' - name: Install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest diff --git a/Makefile b/Makefile index 4ff42b7e44..e8f61a874e 100755 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 HUB_IMAGE ?= truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" -GO_VERSION ?= 1.21 +GO_VERSION ?= 1.22 LINT_VERSION ?= 1.55.2 TRUECLOUDLAB_LINT_VERSION ?= 0.0.3 PROTOC_VERSION ?= 25.0 diff --git a/README.md b/README.md index ecd162a855..413010372b 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The latest version of frostfs-node works with frostfs-contract # Building -To make all binaries you need Go 1.20+ and `make`: +To make all binaries you need Go 1.21+ and `make`: ``` make all ``` diff --git a/go.mod b/go.mod index d86676dd30..e0c0185cd2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.frostfs.info/TrueCloudLab/frostfs-node -go 1.20 +go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 From 45fd4e4ff16dd63d60afe816c41ee71e1a16db28 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 8 Feb 2024 19:14:34 +0300 Subject: [PATCH 0380/1413] [#972] pilorama: Remove removeDuplicatesInPlace() Also, check that slices.CompareFunc() indeed passes all the tests before removal. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/batch.go | 15 +--- .../pilorama/batch_test.go | 70 ------------------- 2 files changed, 2 insertions(+), 83 deletions(-) delete mode 100644 pkg/local_object_storage/pilorama/batch_test.go diff --git a/pkg/local_object_storage/pilorama/batch.go b/pkg/local_object_storage/pilorama/batch.go index c65488b74d..520c6dfb48 100644 --- a/pkg/local_object_storage/pilorama/batch.go +++ b/pkg/local_object_storage/pilorama/batch.go @@ -2,6 +2,7 @@ package pilorama import ( "encoding/binary" + "slices" "sort" "sync" "time" @@ -50,7 +51,7 @@ func (b *batch) run() { sort.Slice(b.operations, func(i, j int) bool { return b.operations[i].Time < b.operations[j].Time }) - b.operations = removeDuplicatesInPlace(b.operations) + b.operations = slices.CompactFunc(b.operations, func(x, y *Move) bool { return x.Time == y.Time }) // Our main use-case is addition of new items. In this case, // we do not need to perform undo()/redo(), just do(). @@ -115,15 +116,3 @@ func (b *batch) run() { b.results[i] <- err } } - -func removeDuplicatesInPlace(a []*Move) []*Move { - equalCount := 0 - for i := 1; i < len(a); i++ { - if a[i].Time == a[i-1].Time { - equalCount++ - } else { - a[i-equalCount] = a[i] - } - } - return a[:len(a)-equalCount] -} diff --git a/pkg/local_object_storage/pilorama/batch_test.go b/pkg/local_object_storage/pilorama/batch_test.go deleted file mode 100644 index 931fce18cd..0000000000 --- a/pkg/local_object_storage/pilorama/batch_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package pilorama - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_removeDuplicatesInPlace(t *testing.T) { - testCases := []struct { - before []int - after []int - }{ - { - before: []int{}, - after: []int{}, - }, - { - before: []int{1}, - after: []int{1}, - }, - { - before: []int{1, 2}, - after: []int{1, 2}, - }, - { - before: []int{1, 2, 3}, - after: []int{1, 2, 3}, - }, - { - before: []int{1, 1, 2}, - after: []int{1, 2}, - }, - { - before: []int{1, 2, 2}, - after: []int{1, 2}, - }, - { - before: []int{1, 2, 2, 3}, - after: []int{1, 2, 3}, - }, - { - before: []int{1, 1, 1}, - after: []int{1}, - }, - { - before: []int{1, 1, 2, 2}, - after: []int{1, 2}, - }, - { - before: []int{1, 1, 1, 2, 3, 3, 3}, - after: []int{1, 2, 3}, - }, - } - - for _, tc := range testCases { - ops := make([]*Move, len(tc.before)) - for i := range ops { - ops[i] = &Move{Meta: Meta{Time: Timestamp(tc.before[i])}} - } - - expected := make([]*Move, len(tc.after)) - for i := range expected { - expected[i] = &Move{Meta: Meta{Time: Timestamp(tc.after[i])}} - } - - actual := removeDuplicatesInPlace(ops) - require.Equal(t, expected, actual, "%d", tc.before) - } -} From 89784b2e0ab573ffd220c9689dd9911b83984caa Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 14 Feb 2024 10:03:07 +0300 Subject: [PATCH 0381/1413] [#972] Use min/max builtins Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize/initialize_register.go | 5 +---- pkg/innerring/processors/netmap/cleanup_table.go | 5 +---- pkg/local_object_storage/blobovnicza/iterate.go | 8 -------- pkg/local_object_storage/engine/list.go | 5 +---- pkg/local_object_storage/shard/gc.go | 12 ++---------- pkg/morph/client/notary.go | 6 +----- pkg/services/object/internal/client/client.go | 5 +---- pkg/services/object/transport_splitter.go | 5 +---- pkg/services/policer/policer_test.go | 5 +---- pkg/services/tree/sync.go | 8 ++------ 10 files changed, 11 insertions(+), 53 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index 6a0a880167..4c6607f9a7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -100,10 +100,7 @@ func registerCandidates(c *helper.InitializeContext) error { // Register candidates in batches in order to overcome the signers amount limit. // See: https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/transaction/transaction.go#L27 for i := 0; i < need; i += registerBatchSize { - start, end := i, i+registerBatchSize - if end > need { - end = need - } + start, end := i, min(i+registerBatchSize, need) // This check is sound because transactions are accepted/rejected atomically. if have >= end { continue diff --git a/pkg/innerring/processors/netmap/cleanup_table.go b/pkg/innerring/processors/netmap/cleanup_table.go index 705e21d99e..c18611569e 100644 --- a/pkg/innerring/processors/netmap/cleanup_table.go +++ b/pkg/innerring/processors/netmap/cleanup_table.go @@ -82,10 +82,7 @@ func (c *cleanupTable) touch(keyString string, now uint64, binNodeInfo []byte) b result := !ok || access.removeFlag || !bytes.Equal(access.binNodeInfo, binNodeInfo) access.removeFlag = false // reset remove flag on each touch - if now > access.epoch { - access.epoch = now - } - + access.epoch = max(access.epoch, now) access.binNodeInfo = binNodeInfo // update binary node info c.lastAccess[keyString] = access diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index 32b0ccea7a..e87da751db 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -56,14 +56,6 @@ func (b *Blobovnicza) iterateBounds(useObjLimitBound bool, f func(uint64, uint64 return nil } -func max(a, b uint64) uint64 { - if a > b { - return a - } - - return b -} - // IterationElement represents a unit of elements through which Iterate operation passes. type IterationElement struct { addr oid.Address diff --git a/pkg/local_object_storage/engine/list.go b/pkg/local_object_storage/engine/list.go index f9229a2b10..7245caeebc 100644 --- a/pkg/local_object_storage/engine/list.go +++ b/pkg/local_object_storage/engine/list.go @@ -134,10 +134,7 @@ func (e *StorageEngine) ListWithCursor(ctx context.Context, prm ListWithCursorPr continue } - count := prm.count - uint32(len(result)) - if count > batchSize { - count = batchSize - } + count := min(prm.count-uint32(len(result)), batchSize) var shardPrm shard.ListWithCursorPrm shardPrm.WithCount(count) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 83be3259a8..ef8e97d34a 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -343,16 +343,8 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { } func (s *Shard) getExpiredObjectsParameters() (workerCount, batchSize int) { - workerCount = minExpiredWorkers - batchSize = minExpiredBatchSize - - if s.gc.gcCfg.expiredCollectorBatchSize > batchSize { - batchSize = s.gc.gcCfg.expiredCollectorBatchSize - } - - if s.gc.gcCfg.expiredCollectorWorkerCount > workerCount { - workerCount = s.gc.gcCfg.expiredCollectorWorkerCount - } + workerCount = max(minExpiredWorkers, s.gc.gcCfg.expiredCollectorWorkerCount) + batchSize = max(minExpiredBatchSize, s.gc.gcCfg.expiredCollectorBatchSize) return } diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 5b817a8056..febdef4d02 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -162,11 +162,7 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin return util.Uint256{}, fmt.Errorf("can't get previous expiration value: %w", err) } - till := int64(bc + delta) - if till < currentTill { - till = currentTill - } - + till := max(int64(bc+delta), currentTill) return c.depositNotary(amount, till) } diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index dd2de0fd1e..6477faed12 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -343,10 +343,7 @@ func PayloadRange(ctx context.Context, prm PayloadRangePrm) (*PayloadRangeRes, e return nil, new(apistatus.ObjectOutOfRange) } - ln := prm.ln - if ln > maxInitialBufferSize { - ln = maxInitialBufferSize - } + ln := min(prm.ln, maxInitialBufferSize) w := bytes.NewBuffer(make([]byte, ln)) _, err = io.CopyN(w, rdr, int64(prm.ln)) diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index 2d9810cd38..54e49cb129 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -164,10 +164,7 @@ func (s *searchStreamMsgSizeCtrl) Send(resp *object.SearchResponse) error { newResp.SetBody(body) } - cut := s.addrAmount - if cut > ln { - cut = ln - } + cut := min(s.addrAmount, ln) body.SetIDList(ids[:cut]) newResp.SetMetaHeader(resp.GetMetaHeader()) diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 50f206fd9a..be0974c39a 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -388,10 +388,7 @@ func (it *sliceKeySpaceIterator) Next(_ context.Context, size uint32) ([]objectc if it.cur >= len(it.objs) { return nil, engine.ErrEndOfListing } - end := it.cur + int(size) - if end > len(it.objs) { - end = len(it.objs) - } + end := min(it.cur+int(size), len(it.objs)) ret := it.objs[it.cur:end] it.cur = end return ret, nil diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 2a19ae18a5..1fa9a2b6c7 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -167,9 +167,7 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram merged <- ms[minTimeMoveIndex] height := ms[minTimeMoveIndex].Time if ms[minTimeMoveIndex] = <-streams[minTimeMoveIndex]; ms[minTimeMoveIndex] == nil { - if minStreamedLastHeight > height { - minStreamedLastHeight = height - } + minStreamedLastHeight = min(minStreamedLastHeight, height) } } @@ -203,9 +201,7 @@ func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID s errGroup.Go(func() error { if err := s.forest.TreeApply(ctx, cid, treeID, m, true); err != nil { heightMtx.Lock() - if m.Time < unappliedOperationHeight { - unappliedOperationHeight = m.Time - } + unappliedOperationHeight = min(unappliedOperationHeight, m.Time) heightMtx.Unlock() return err } From d2f13a29de7c6e758ac03e29f90c7566ced14b11 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 14 Feb 2024 10:14:32 +0300 Subject: [PATCH 0382/1413] [#972] Adopt slices.BinarySearch() Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/container/container.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index 690db2f4f2..eda388d37c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "slices" "sort" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" @@ -446,7 +447,7 @@ func getCIDFilterFunc(cmd *cobra.Command) (func([]byte) bool, error) { var id cid.ID id.SetSHA256(v) idStr := id.EncodeToString() - n := sort.Search(len(rawIDs), func(i int) bool { return rawIDs[i] >= idStr }) - return n < len(rawIDs) && rawIDs[n] == idStr + _, found := slices.BinarySearch(rawIDs, idStr) + return found }, nil } From 6d9707ff1fcb70b5e6eaf6c1c7cd0a1af597f541 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 14 Feb 2024 10:42:16 +0300 Subject: [PATCH 0383/1413] [#972] Use require.ElementsMatch() where possible Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/list_test.go | 12 +----------- .../metabase/containers_test.go | 12 +----------- pkg/local_object_storage/metabase/list_test.go | 14 +------------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 7bb1ac0fac..4fc9569c7b 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -3,7 +3,6 @@ package engine import ( "context" "path/filepath" - "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -18,13 +17,6 @@ import ( "github.com/stretchr/testify/require" ) -func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { - sort.Slice(addrWithType, func(i, j int) bool { - return addrWithType[i].Address.EncodeToString() < addrWithType[j].Address.EncodeToString() - }) - return addrWithType -} - func TestListWithCursor(t *testing.T) { t.Parallel() @@ -98,7 +90,6 @@ func TestListWithCursor(t *testing.T) { require.NoError(t, err) expected = append(expected, object.AddressWithType{Type: objectSDK.TypeRegular, Address: object.AddressOf(obj)}) } - expected = sortAddresses(expected) var prm ListWithCursorPrm prm.count = tt.batchSize @@ -113,8 +104,7 @@ func TestListWithCursor(t *testing.T) { prm.cursor = res.Cursor() } - got = sortAddresses(got) - require.Equal(t, expected, got) + require.ElementsMatch(t, expected, got) }) } } diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index e7762ded6b..66c5625652 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -3,7 +3,6 @@ package meta_test import ( "context" "math/rand" - "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -125,18 +124,9 @@ func TestDB_ContainersCount(t *testing.T) { } } - sort.Slice(expected, func(i, j int) bool { - return expected[i].EncodeToString() < expected[j].EncodeToString() - }) - got, err := db.Containers(context.Background()) require.NoError(t, err) - - sort.Slice(got, func(i, j int) bool { - return got[i].EncodeToString() < got[j].EncodeToString() - }) - - require.Equal(t, expected, got) + require.ElementsMatch(t, expected, got) } func TestDB_ContainerSize(t *testing.T) { diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 25c0e35bd2..e1ccb4e06f 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -3,7 +3,6 @@ package meta_test import ( "context" "errors" - "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -128,8 +127,6 @@ func TestLisObjectsWithCursor(t *testing.T) { expected = append(expected, object.AddressWithType{Address: object.AddressOf(child), Type: objectSDK.TypeRegular}) } - expected = sortAddresses(expected) - t.Run("success with various count", func(t *testing.T) { for countPerReq := 1; countPerReq <= total; countPerReq++ { got := make([]object.AddressWithType, 0, total) @@ -151,9 +148,7 @@ func TestLisObjectsWithCursor(t *testing.T) { _, _, err = metaListWithCursor(db, uint32(countPerReq), cursor) require.ErrorIs(t, err, meta.ErrEndOfListing, "count:%d", countPerReq, cursor) - - got = sortAddresses(got) - require.Equal(t, expected, got, "count:%d", countPerReq) + require.ElementsMatch(t, expected, got, "count:%d", countPerReq) } }) @@ -216,13 +211,6 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { } } -func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { - sort.Slice(addrWithType, func(i, j int) bool { - return addrWithType[i].Address.EncodeToString() < addrWithType[j].Address.EncodeToString() - }) - return addrWithType -} - func metaListWithCursor(db *meta.DB, count uint32, cursor *meta.Cursor) ([]object.AddressWithType, *meta.Cursor, error) { var listPrm meta.ListPrm listPrm.SetCount(count) From b871d7a5e83a616e4a769d08705ba7ba9394503f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 14 Feb 2024 10:50:27 +0300 Subject: [PATCH 0384/1413] [#972] Use slices.Sort* when useful Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/control/shards_set_mode.go | 7 ++----- pkg/services/tree/getsubtree_test.go | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/shards_set_mode.go b/cmd/frostfs-cli/modules/control/shards_set_mode.go index 1c87b405b0..e73f15178c 100644 --- a/cmd/frostfs-cli/modules/control/shards_set_mode.go +++ b/cmd/frostfs-cli/modules/control/shards_set_mode.go @@ -3,7 +3,7 @@ package control import ( "bytes" "fmt" - "sort" + "slices" "strings" rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" @@ -177,9 +177,6 @@ func getShardIDListFromIDFlag(cmd *cobra.Command, withAllFlag bool) [][]byte { res = append(res, raw) } - sort.Slice(res, func(i, j int) bool { - return bytes.Compare(res[i], res[j]) < 0 - }) - + slices.SortFunc(res, bytes.Compare) return res } diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 63cdc73a2f..d220f1e2b2 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -4,7 +4,7 @@ import ( "context" "errors" "path" - "sort" + "slices" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" @@ -177,9 +177,7 @@ func TestGetSubTreeOrderAsc(t *testing.T) { require.True(t, found, "unknown node") } - require.True(t, sort.SliceIsSorted(paths, func(i, j int) bool { - return paths[i] < paths[j] - })) + require.True(t, slices.IsSorted(paths)) } var ( From f3e50772fd929a39e9fefc1b2a15c49beabdc3a7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 14 Feb 2024 10:52:52 +0300 Subject: [PATCH 0385/1413] [#972] Drop x/exp/slices dependency Signed-off-by: Evgenii Stratonikov --- go.sum | 14 ++++++++++++++ pkg/innerring/processors/frostfs/handlers.go | 2 +- .../internal/testutil/generators_test.go | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index fa5da98cc3..8785ca9753 100644 --- a/go.sum +++ b/go.sum @@ -59,9 +59,11 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etly github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= @@ -96,6 +98,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -135,19 +138,24 @@ github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/4 github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= @@ -229,6 +237,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -305,6 +314,7 @@ go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40 go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -325,6 +335,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -401,12 +412,14 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= @@ -427,6 +440,7 @@ google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/pkg/innerring/processors/frostfs/handlers.go b/pkg/innerring/processors/frostfs/handlers.go index 5782dc7441..c80f9fdc51 100644 --- a/pkg/innerring/processors/frostfs/handlers.go +++ b/pkg/innerring/processors/frostfs/handlers.go @@ -3,13 +3,13 @@ package frostfs import ( "bytes" "encoding/hex" + "slices" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" "go.uber.org/zap" - "golang.org/x/exp/slices" ) func (np *Processor) handleDeposit(ev event.Event) { diff --git a/pkg/local_object_storage/internal/testutil/generators_test.go b/pkg/local_object_storage/internal/testutil/generators_test.go index f2c60f9b4d..f7be6014d6 100644 --- a/pkg/local_object_storage/internal/testutil/generators_test.go +++ b/pkg/local_object_storage/internal/testutil/generators_test.go @@ -2,10 +2,10 @@ package testutil import ( "encoding/binary" + "slices" "testing" "github.com/stretchr/testify/require" - "golang.org/x/exp/slices" ) func TestOverwriteObjGenerator(t *testing.T) { From 13d5cd3e21e1ecac4db7f780fe2a5b2b245ffaf7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 19 Feb 2024 13:08:18 +0300 Subject: [PATCH 0386/1413] [#991] logger: Fix journald logger Allow to change logger level. Signed-off-by: Dmitrii Stepanov --- pkg/util/logger/logger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index c6db04df9f..e67afb36b4 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -147,7 +147,7 @@ func newJournaldLogger(prm *Prm) (*Logger, error) { encoder := zapjournald.NewPartialEncoder(zapcore.NewConsoleEncoder(c.EncoderConfig), zapjournald.SyslogFields) - core := zapjournald.NewCore(zap.NewAtomicLevelAt(prm.level), encoder, &journald.Journal{}, zapjournald.SyslogFields) + core := zapjournald.NewCore(lvl, encoder, &journald.Journal{}, zapjournald.SyslogFields) coreWithContext := core.With([]zapcore.Field{ zapjournald.SyslogFacility(zapjournald.LogDaemon), zapjournald.SyslogIdentifier(), From 9e55836da583f02f64fd002199b127c76ced3b3d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Feb 2024 15:53:38 +0300 Subject: [PATCH 0387/1413] [#994] cli: Output pilorama path in `shards list` Do it for JSON too, not only for human output. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/control/shards_list.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-cli/modules/control/shards_list.go b/cmd/frostfs-cli/modules/control/shards_list.go index 0b5d6b0a34..3eb74ec82a 100644 --- a/cmd/frostfs-cli/modules/control/shards_list.go +++ b/cmd/frostfs-cli/modules/control/shards_list.go @@ -70,6 +70,7 @@ func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) { "metabase": i.GetMetabasePath(), "blobstor": i.GetBlobstor(), "writecache": i.GetWritecachePath(), + "pilorama": i.GetPiloramaPath(), "error_count": i.GetErrorCount(), }) } From 946f2ec2bf4b5e99726811ac8bcb225bbca0708f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Feb 2024 17:02:39 +0300 Subject: [PATCH 0388/1413] Revert "[#972] Drop x/exp/slices dependency" This reverts commit f3e50772fd929a39e9fefc1b2a15c49beabdc3a7. Signed-off-by: Evgenii Stratonikov --- go.sum | 14 -------------- pkg/innerring/processors/frostfs/handlers.go | 2 +- .../internal/testutil/generators_test.go | 2 +- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/go.sum b/go.sum index 8785ca9753..fa5da98cc3 100644 --- a/go.sum +++ b/go.sum @@ -59,11 +59,9 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etly github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= @@ -98,7 +96,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -138,24 +135,19 @@ github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/4 github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= @@ -237,7 +229,6 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -314,7 +305,6 @@ go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40 go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -335,7 +325,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -412,14 +401,12 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= @@ -440,7 +427,6 @@ google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/pkg/innerring/processors/frostfs/handlers.go b/pkg/innerring/processors/frostfs/handlers.go index c80f9fdc51..5782dc7441 100644 --- a/pkg/innerring/processors/frostfs/handlers.go +++ b/pkg/innerring/processors/frostfs/handlers.go @@ -3,13 +3,13 @@ package frostfs import ( "bytes" "encoding/hex" - "slices" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" "go.uber.org/zap" + "golang.org/x/exp/slices" ) func (np *Processor) handleDeposit(ev event.Event) { diff --git a/pkg/local_object_storage/internal/testutil/generators_test.go b/pkg/local_object_storage/internal/testutil/generators_test.go index f7be6014d6..f2c60f9b4d 100644 --- a/pkg/local_object_storage/internal/testutil/generators_test.go +++ b/pkg/local_object_storage/internal/testutil/generators_test.go @@ -2,10 +2,10 @@ package testutil import ( "encoding/binary" - "slices" "testing" "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" ) func TestOverwriteObjGenerator(t *testing.T) { From 3359349acbbfb0aa8e208c5286ff7bd6537df2be Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Feb 2024 17:02:47 +0300 Subject: [PATCH 0389/1413] Revert "[#972] Use slices.Sort* when useful" This reverts commit b871d7a5e83a616e4a769d08705ba7ba9394503f. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/control/shards_set_mode.go | 7 +++++-- pkg/services/tree/getsubtree_test.go | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/shards_set_mode.go b/cmd/frostfs-cli/modules/control/shards_set_mode.go index e73f15178c..1c87b405b0 100644 --- a/cmd/frostfs-cli/modules/control/shards_set_mode.go +++ b/cmd/frostfs-cli/modules/control/shards_set_mode.go @@ -3,7 +3,7 @@ package control import ( "bytes" "fmt" - "slices" + "sort" "strings" rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" @@ -177,6 +177,9 @@ func getShardIDListFromIDFlag(cmd *cobra.Command, withAllFlag bool) [][]byte { res = append(res, raw) } - slices.SortFunc(res, bytes.Compare) + sort.Slice(res, func(i, j int) bool { + return bytes.Compare(res[i], res[j]) < 0 + }) + return res } diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index d220f1e2b2..63cdc73a2f 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -4,7 +4,7 @@ import ( "context" "errors" "path" - "slices" + "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" @@ -177,7 +177,9 @@ func TestGetSubTreeOrderAsc(t *testing.T) { require.True(t, found, "unknown node") } - require.True(t, slices.IsSorted(paths)) + require.True(t, sort.SliceIsSorted(paths, func(i, j int) bool { + return paths[i] < paths[j] + })) } var ( From 7627d08914ab4cfa6fd73f17e586f4b0f1a0bbc1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Feb 2024 17:02:56 +0300 Subject: [PATCH 0390/1413] Revert "[#972] Use require.ElementsMatch() where possible" This reverts commit 6d9707ff1fcb70b5e6eaf6c1c7cd0a1af597f541. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/list_test.go | 12 +++++++++++- .../metabase/containers_test.go | 12 +++++++++++- pkg/local_object_storage/metabase/list_test.go | 14 +++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 4fc9569c7b..7bb1ac0fac 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -3,6 +3,7 @@ package engine import ( "context" "path/filepath" + "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -17,6 +18,13 @@ import ( "github.com/stretchr/testify/require" ) +func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { + sort.Slice(addrWithType, func(i, j int) bool { + return addrWithType[i].Address.EncodeToString() < addrWithType[j].Address.EncodeToString() + }) + return addrWithType +} + func TestListWithCursor(t *testing.T) { t.Parallel() @@ -90,6 +98,7 @@ func TestListWithCursor(t *testing.T) { require.NoError(t, err) expected = append(expected, object.AddressWithType{Type: objectSDK.TypeRegular, Address: object.AddressOf(obj)}) } + expected = sortAddresses(expected) var prm ListWithCursorPrm prm.count = tt.batchSize @@ -104,7 +113,8 @@ func TestListWithCursor(t *testing.T) { prm.cursor = res.Cursor() } - require.ElementsMatch(t, expected, got) + got = sortAddresses(got) + require.Equal(t, expected, got) }) } } diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index 66c5625652..e7762ded6b 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -3,6 +3,7 @@ package meta_test import ( "context" "math/rand" + "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -124,9 +125,18 @@ func TestDB_ContainersCount(t *testing.T) { } } + sort.Slice(expected, func(i, j int) bool { + return expected[i].EncodeToString() < expected[j].EncodeToString() + }) + got, err := db.Containers(context.Background()) require.NoError(t, err) - require.ElementsMatch(t, expected, got) + + sort.Slice(got, func(i, j int) bool { + return got[i].EncodeToString() < got[j].EncodeToString() + }) + + require.Equal(t, expected, got) } func TestDB_ContainerSize(t *testing.T) { diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index e1ccb4e06f..25c0e35bd2 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -3,6 +3,7 @@ package meta_test import ( "context" "errors" + "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -127,6 +128,8 @@ func TestLisObjectsWithCursor(t *testing.T) { expected = append(expected, object.AddressWithType{Address: object.AddressOf(child), Type: objectSDK.TypeRegular}) } + expected = sortAddresses(expected) + t.Run("success with various count", func(t *testing.T) { for countPerReq := 1; countPerReq <= total; countPerReq++ { got := make([]object.AddressWithType, 0, total) @@ -148,7 +151,9 @@ func TestLisObjectsWithCursor(t *testing.T) { _, _, err = metaListWithCursor(db, uint32(countPerReq), cursor) require.ErrorIs(t, err, meta.ErrEndOfListing, "count:%d", countPerReq, cursor) - require.ElementsMatch(t, expected, got, "count:%d", countPerReq) + + got = sortAddresses(got) + require.Equal(t, expected, got, "count:%d", countPerReq) } }) @@ -211,6 +216,13 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { } } +func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { + sort.Slice(addrWithType, func(i, j int) bool { + return addrWithType[i].Address.EncodeToString() < addrWithType[j].Address.EncodeToString() + }) + return addrWithType +} + func metaListWithCursor(db *meta.DB, count uint32, cursor *meta.Cursor) ([]object.AddressWithType, *meta.Cursor, error) { var listPrm meta.ListPrm listPrm.SetCount(count) From 4bfc6d29b910bc8e85852180ca0caabbf2eff2f4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Feb 2024 17:03:04 +0300 Subject: [PATCH 0391/1413] Revert "[#972] Adopt slices.BinarySearch()" This reverts commit d2f13a29de7c6e758ac03e29f90c7566ced14b11. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/container/container.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index eda388d37c..690db2f4f2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "os" - "slices" "sort" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" @@ -447,7 +446,7 @@ func getCIDFilterFunc(cmd *cobra.Command) (func([]byte) bool, error) { var id cid.ID id.SetSHA256(v) idStr := id.EncodeToString() - _, found := slices.BinarySearch(rawIDs, idStr) - return found + n := sort.Search(len(rawIDs), func(i int) bool { return rawIDs[i] >= idStr }) + return n < len(rawIDs) && rawIDs[n] == idStr }, nil } From dad56d2e98179904a9b263103ad04794202a7c1f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Feb 2024 17:03:11 +0300 Subject: [PATCH 0392/1413] Revert "[#972] Use min/max builtins" This reverts commit 89784b2e0ab573ffd220c9689dd9911b83984caa. Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize/initialize_register.go | 5 ++++- pkg/innerring/processors/netmap/cleanup_table.go | 5 ++++- pkg/local_object_storage/blobovnicza/iterate.go | 8 ++++++++ pkg/local_object_storage/engine/list.go | 5 ++++- pkg/local_object_storage/shard/gc.go | 12 ++++++++++-- pkg/morph/client/notary.go | 6 +++++- pkg/services/object/internal/client/client.go | 5 ++++- pkg/services/object/transport_splitter.go | 5 ++++- pkg/services/policer/policer_test.go | 5 ++++- pkg/services/tree/sync.go | 8 ++++++-- 10 files changed, 53 insertions(+), 11 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index 4c6607f9a7..6a0a880167 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -100,7 +100,10 @@ func registerCandidates(c *helper.InitializeContext) error { // Register candidates in batches in order to overcome the signers amount limit. // See: https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/transaction/transaction.go#L27 for i := 0; i < need; i += registerBatchSize { - start, end := i, min(i+registerBatchSize, need) + start, end := i, i+registerBatchSize + if end > need { + end = need + } // This check is sound because transactions are accepted/rejected atomically. if have >= end { continue diff --git a/pkg/innerring/processors/netmap/cleanup_table.go b/pkg/innerring/processors/netmap/cleanup_table.go index c18611569e..705e21d99e 100644 --- a/pkg/innerring/processors/netmap/cleanup_table.go +++ b/pkg/innerring/processors/netmap/cleanup_table.go @@ -82,7 +82,10 @@ func (c *cleanupTable) touch(keyString string, now uint64, binNodeInfo []byte) b result := !ok || access.removeFlag || !bytes.Equal(access.binNodeInfo, binNodeInfo) access.removeFlag = false // reset remove flag on each touch - access.epoch = max(access.epoch, now) + if now > access.epoch { + access.epoch = now + } + access.binNodeInfo = binNodeInfo // update binary node info c.lastAccess[keyString] = access diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index e87da751db..32b0ccea7a 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -56,6 +56,14 @@ func (b *Blobovnicza) iterateBounds(useObjLimitBound bool, f func(uint64, uint64 return nil } +func max(a, b uint64) uint64 { + if a > b { + return a + } + + return b +} + // IterationElement represents a unit of elements through which Iterate operation passes. type IterationElement struct { addr oid.Address diff --git a/pkg/local_object_storage/engine/list.go b/pkg/local_object_storage/engine/list.go index 7245caeebc..f9229a2b10 100644 --- a/pkg/local_object_storage/engine/list.go +++ b/pkg/local_object_storage/engine/list.go @@ -134,7 +134,10 @@ func (e *StorageEngine) ListWithCursor(ctx context.Context, prm ListWithCursorPr continue } - count := min(prm.count-uint32(len(result)), batchSize) + count := prm.count - uint32(len(result)) + if count > batchSize { + count = batchSize + } var shardPrm shard.ListWithCursorPrm shardPrm.WithCount(count) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index ef8e97d34a..83be3259a8 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -343,8 +343,16 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { } func (s *Shard) getExpiredObjectsParameters() (workerCount, batchSize int) { - workerCount = max(minExpiredWorkers, s.gc.gcCfg.expiredCollectorWorkerCount) - batchSize = max(minExpiredBatchSize, s.gc.gcCfg.expiredCollectorBatchSize) + workerCount = minExpiredWorkers + batchSize = minExpiredBatchSize + + if s.gc.gcCfg.expiredCollectorBatchSize > batchSize { + batchSize = s.gc.gcCfg.expiredCollectorBatchSize + } + + if s.gc.gcCfg.expiredCollectorWorkerCount > workerCount { + workerCount = s.gc.gcCfg.expiredCollectorWorkerCount + } return } diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index febdef4d02..5b817a8056 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -162,7 +162,11 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin return util.Uint256{}, fmt.Errorf("can't get previous expiration value: %w", err) } - till := max(int64(bc+delta), currentTill) + till := int64(bc + delta) + if till < currentTill { + till = currentTill + } + return c.depositNotary(amount, till) } diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index 6477faed12..dd2de0fd1e 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -343,7 +343,10 @@ func PayloadRange(ctx context.Context, prm PayloadRangePrm) (*PayloadRangeRes, e return nil, new(apistatus.ObjectOutOfRange) } - ln := min(prm.ln, maxInitialBufferSize) + ln := prm.ln + if ln > maxInitialBufferSize { + ln = maxInitialBufferSize + } w := bytes.NewBuffer(make([]byte, ln)) _, err = io.CopyN(w, rdr, int64(prm.ln)) diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index 54e49cb129..2d9810cd38 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -164,7 +164,10 @@ func (s *searchStreamMsgSizeCtrl) Send(resp *object.SearchResponse) error { newResp.SetBody(body) } - cut := min(s.addrAmount, ln) + cut := s.addrAmount + if cut > ln { + cut = ln + } body.SetIDList(ids[:cut]) newResp.SetMetaHeader(resp.GetMetaHeader()) diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index be0974c39a..50f206fd9a 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -388,7 +388,10 @@ func (it *sliceKeySpaceIterator) Next(_ context.Context, size uint32) ([]objectc if it.cur >= len(it.objs) { return nil, engine.ErrEndOfListing } - end := min(it.cur+int(size), len(it.objs)) + end := it.cur + int(size) + if end > len(it.objs) { + end = len(it.objs) + } ret := it.objs[it.cur:end] it.cur = end return ret, nil diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 1fa9a2b6c7..2a19ae18a5 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -167,7 +167,9 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram merged <- ms[minTimeMoveIndex] height := ms[minTimeMoveIndex].Time if ms[minTimeMoveIndex] = <-streams[minTimeMoveIndex]; ms[minTimeMoveIndex] == nil { - minStreamedLastHeight = min(minStreamedLastHeight, height) + if minStreamedLastHeight > height { + minStreamedLastHeight = height + } } } @@ -201,7 +203,9 @@ func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID s errGroup.Go(func() error { if err := s.forest.TreeApply(ctx, cid, treeID, m, true); err != nil { heightMtx.Lock() - unappliedOperationHeight = min(unappliedOperationHeight, m.Time) + if m.Time < unappliedOperationHeight { + unappliedOperationHeight = m.Time + } heightMtx.Unlock() return err } From 9f68305c2e88b1aea294ac3e75b75038151534e1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Feb 2024 17:03:25 +0300 Subject: [PATCH 0393/1413] Revert "[#972] pilorama: Remove removeDuplicatesInPlace()" This reverts commit 45fd4e4ff16dd63d60afe816c41ee71e1a16db28. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/batch.go | 15 +++- .../pilorama/batch_test.go | 70 +++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 pkg/local_object_storage/pilorama/batch_test.go diff --git a/pkg/local_object_storage/pilorama/batch.go b/pkg/local_object_storage/pilorama/batch.go index 520c6dfb48..c65488b74d 100644 --- a/pkg/local_object_storage/pilorama/batch.go +++ b/pkg/local_object_storage/pilorama/batch.go @@ -2,7 +2,6 @@ package pilorama import ( "encoding/binary" - "slices" "sort" "sync" "time" @@ -51,7 +50,7 @@ func (b *batch) run() { sort.Slice(b.operations, func(i, j int) bool { return b.operations[i].Time < b.operations[j].Time }) - b.operations = slices.CompactFunc(b.operations, func(x, y *Move) bool { return x.Time == y.Time }) + b.operations = removeDuplicatesInPlace(b.operations) // Our main use-case is addition of new items. In this case, // we do not need to perform undo()/redo(), just do(). @@ -116,3 +115,15 @@ func (b *batch) run() { b.results[i] <- err } } + +func removeDuplicatesInPlace(a []*Move) []*Move { + equalCount := 0 + for i := 1; i < len(a); i++ { + if a[i].Time == a[i-1].Time { + equalCount++ + } else { + a[i-equalCount] = a[i] + } + } + return a[:len(a)-equalCount] +} diff --git a/pkg/local_object_storage/pilorama/batch_test.go b/pkg/local_object_storage/pilorama/batch_test.go new file mode 100644 index 0000000000..931fce18cd --- /dev/null +++ b/pkg/local_object_storage/pilorama/batch_test.go @@ -0,0 +1,70 @@ +package pilorama + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func Test_removeDuplicatesInPlace(t *testing.T) { + testCases := []struct { + before []int + after []int + }{ + { + before: []int{}, + after: []int{}, + }, + { + before: []int{1}, + after: []int{1}, + }, + { + before: []int{1, 2}, + after: []int{1, 2}, + }, + { + before: []int{1, 2, 3}, + after: []int{1, 2, 3}, + }, + { + before: []int{1, 1, 2}, + after: []int{1, 2}, + }, + { + before: []int{1, 2, 2}, + after: []int{1, 2}, + }, + { + before: []int{1, 2, 2, 3}, + after: []int{1, 2, 3}, + }, + { + before: []int{1, 1, 1}, + after: []int{1}, + }, + { + before: []int{1, 1, 2, 2}, + after: []int{1, 2}, + }, + { + before: []int{1, 1, 1, 2, 3, 3, 3}, + after: []int{1, 2, 3}, + }, + } + + for _, tc := range testCases { + ops := make([]*Move, len(tc.before)) + for i := range ops { + ops[i] = &Move{Meta: Meta{Time: Timestamp(tc.before[i])}} + } + + expected := make([]*Move, len(tc.after)) + for i := range expected { + expected[i] = &Move{Meta: Meta{Time: Timestamp(tc.after[i])}} + } + + actual := removeDuplicatesInPlace(ops) + require.Equal(t, expected, actual, "%d", tc.before) + } +} From 9adcb253be772bfc4f716307c564ac1f0545f85c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Feb 2024 17:03:32 +0300 Subject: [PATCH 0394/1413] Revert "[#972] go.mod: Bump go version to go1.21" This reverts commit e39a714c257248bfaca9086f38e7b1dc15761a6b. Signed-off-by: Evgenii Stratonikov --- .docker/Dockerfile.adm | 2 +- .docker/Dockerfile.ci | 2 +- .docker/Dockerfile.cli | 2 +- .docker/Dockerfile.ir | 2 +- .docker/Dockerfile.storage | 2 +- .forgejo/workflows/build.yml | 2 +- .forgejo/workflows/dco.yml | 2 +- .forgejo/workflows/tests.yml | 6 +++--- .forgejo/workflows/vulncheck.yml | 2 +- Makefile | 2 +- README.md | 2 +- go.mod | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.docker/Dockerfile.adm b/.docker/Dockerfile.adm index b3dad06d3d..eeccaab79c 100644 --- a/.docker/Dockerfile.adm +++ b/.docker/Dockerfile.adm @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.21 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ci b/.docker/Dockerfile.ci index e9077c8313..ef6586a641 100644 --- a/.docker/Dockerfile.ci +++ b/.docker/Dockerfile.ci @@ -1,4 +1,4 @@ -FROM golang:1.22 +FROM golang:1.21 WORKDIR /tmp diff --git a/.docker/Dockerfile.cli b/.docker/Dockerfile.cli index 5adedc1408..0dd4cebcf9 100644 --- a/.docker/Dockerfile.cli +++ b/.docker/Dockerfile.cli @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.21 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ir b/.docker/Dockerfile.ir index 25025bb2fa..4015df6733 100644 --- a/.docker/Dockerfile.ir +++ b/.docker/Dockerfile.ir @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.21 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.storage b/.docker/Dockerfile.storage index a16005516a..ced6ea538e 100644 --- a/.docker/Dockerfile.storage +++ b/.docker/Dockerfile.storage @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.21 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 86943fe88c..3c74d94347 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.21', '1.22' ] + go_versions: [ '1.20', '1.21' ] steps: - uses: actions/checkout@v3 diff --git a/.forgejo/workflows/dco.yml b/.forgejo/workflows/dco.yml index 7c5af8410b..9aa0d31066 100644 --- a/.forgejo/workflows/dco.yml +++ b/.forgejo/workflows/dco.yml @@ -13,7 +13,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.21' - name: Run commit format checker uses: https://git.frostfs.info/TrueCloudLab/dco-go@v3 diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index 8b0d9220b4..f66a2c4017 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.21' cache: true - name: Install linters @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.21', '1.22' ] + go_versions: [ '1.20', '1.21' ] fail-fast: false steps: - uses: actions/checkout@v3 @@ -63,7 +63,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.21' cache: true - name: Install staticcheck diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index 3af564c4b5..8ea01749b2 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -13,7 +13,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.21' - name: Install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest diff --git a/Makefile b/Makefile index e8f61a874e..4ff42b7e44 100755 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 HUB_IMAGE ?= truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" -GO_VERSION ?= 1.22 +GO_VERSION ?= 1.21 LINT_VERSION ?= 1.55.2 TRUECLOUDLAB_LINT_VERSION ?= 0.0.3 PROTOC_VERSION ?= 25.0 diff --git a/README.md b/README.md index 413010372b..ecd162a855 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The latest version of frostfs-node works with frostfs-contract # Building -To make all binaries you need Go 1.21+ and `make`: +To make all binaries you need Go 1.20+ and `make`: ``` make all ``` diff --git a/go.mod b/go.mod index e0c0185cd2..d86676dd30 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.frostfs.info/TrueCloudLab/frostfs-node -go 1.21 +go 1.20 require ( code.gitea.io/sdk/gitea v0.17.1 From 9611710e190b260a9067d57f64f3678da721e78c Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 16 Feb 2024 12:36:42 +0300 Subject: [PATCH 0395/1413] [#989] cli: Read and parse chains from file * Introduce path flag to make add-rule command read and parse chain from file. File is binary/JSON-encoded chain. Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 37 +++++++++++++++------ cmd/frostfs-cli/modules/util/ape.go | 18 ++++++++++ 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 0f5ac11f3e..45b36bfb18 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -2,6 +2,7 @@ package control import ( "encoding/hex" + "errors" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" @@ -14,6 +15,7 @@ import ( const ( ruleFlag = "rule" + pathFlag = "path" ) var addRuleCmd = &cobra.Command{ @@ -23,15 +25,13 @@ var addRuleCmd = &cobra.Command{ Example: `control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --rule "allow Object.Get *" --rule "deny Object.Get EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr/*" --rule "deny:QuotaLimitReached Object.Put Object.Resource:Department=HR *" + +control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --path some_chain.json `, Run: addRule, } -func addRule(cmd *cobra.Command, _ []string) { - pk := key.Get(cmd) - - target := parseTarget(cmd) - +func parseChain(cmd *cobra.Command) *apechain.Chain { chainID, _ := cmd.Flags().GetString(chainIDFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) @@ -43,20 +43,34 @@ func addRule(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) } - rule, _ := cmd.Flags().GetStringArray(ruleFlag) - chain := new(apechain.Chain) - commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rule)) chain.ID = apechain.ID(chainIDRaw) - serializedChain := chain.Bytes() + + if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { + commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules)) + } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { + commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath)) + } else { + commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed")) + } cmd.Println("Parsed chain:") util.PrintHumanReadableAPEChain(cmd, chain) + return chain +} + +func addRule(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + target := parseTarget(cmd) + + parsed := parseChain(cmd) + req := &control.AddChainLocalOverrideRequest{ Body: &control.AddChainLocalOverrideRequest_Body{ Target: target, - Chain: serializedChain, + Chain: parsed.Bytes(), }, } @@ -81,9 +95,12 @@ func initControlAddRuleCmd() { ff := addRuleCmd.Flags() ff.StringArray(ruleFlag, []string{}, "Rule statement") + ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") ff.String(chainIDFlag, "", "Assign ID to the parsed chain") ff.String(targetNameFlag, "", targetNameDesc) ff.String(targetTypeFlag, "", targetTypeDesc) _ = addRuleCmd.MarkFlagRequired(targetTypeFlag) ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + + addRuleCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag) } diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 6a7eca948c..dfe70e7da3 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -3,6 +3,7 @@ package util import ( "errors" "fmt" + "os" "strconv" "strings" @@ -57,6 +58,23 @@ func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) { } } +func ParseAPEChainBinaryOrJSON(chain *apechain.Chain, path string) error { + data, err := os.ReadFile(path) + if err != nil { + return fmt.Errorf("read file <%s>: %w", path, err) + } + + err = chain.UnmarshalBinary(data) + if err != nil { + err = chain.UnmarshalJSON(data) + if err != nil { + return fmt.Errorf("invalid format: %w", err) + } + } + + return nil +} + // ParseAPEChain parses APE chain rules. func ParseAPEChain(chain *apechain.Chain, rules []string) error { if len(rules) == 0 { From 613e11c4d2dcc0190b0b80b6040ea8d257349c58 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 16 Feb 2024 12:59:48 +0300 Subject: [PATCH 0396/1413] [#989] adm: Read and parse chains from file * Slightly fix the approach to read encoded chain from file in frostfs-adm. Signed-off-by: Airat Arifullin --- .../internal/modules/morph/ape/ape.go | 10 +++---- .../internal/modules/morph/ape/ape_util.go | 28 ++++++------------- 2 files changed, 13 insertions(+), 25 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index c08dc512e0..957c7a15fe 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -22,8 +22,8 @@ const ( chainIDDesc = "Rule chain ID" ruleFlag = "rule" ruleFlagDesc = "Rule chain in text format" - ruleJSONFlag = "rule-json" - ruleJSONFlagDesc = "Chain rule in JSON format or path to the file" + pathFlag = "path" + pathFlagDesc = "path to encoded chain in JSON or binary format" targetNameFlag = "target-name" targetNameDesc = "Resource name in APE resource name format" targetTypeFlag = "target-type" @@ -99,10 +99,10 @@ func initAddRuleChainCmd() { addRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) _ = addRuleChainCmd.MarkFlagRequired(chainIDFlag) - addRuleChainCmd.Flags().String(ruleFlag, "", ruleFlagDesc) - addRuleChainCmd.Flags().String(ruleJSONFlag, "", ruleJSONFlagDesc) + addRuleChainCmd.Flags().StringArray(ruleFlag, []string{}, ruleFlagDesc) + addRuleChainCmd.Flags().String(pathFlag, "", pathFlagDesc) addRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) - addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, ruleJSONFlag) + addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, pathFlag) } func initRemoveRuleChainCmd() { diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 7f23e3754d..fe09776ede 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -1,9 +1,7 @@ package ape import ( - "encoding/json" "fmt" - "os" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" @@ -63,29 +61,19 @@ func parseChainID(cmd *cobra.Command) apechain.ID { func parseChain(cmd *cobra.Command) *apechain.Chain { chain := new(apechain.Chain) - if ruleStmt, _ := cmd.Flags().GetString(ruleFlag); ruleStmt != "" { - parseErr := parseutil.ParseAPEChain(chain, []string{ruleStmt}) - commonCmd.ExitOnErr(cmd, "ape chain parser error: %w", parseErr) - } else if ruleJSON, _ := cmd.Flags().GetString(ruleJSONFlag); ruleJSON != "" { - var rule []byte - if _, err := os.Stat(ruleJSON); err == nil { - rule, err = os.ReadFile(ruleJSON) - commonCmd.ExitOnErr(cmd, "read file error: %w", err) - } else { - rule = []byte(ruleJSON) - if !json.Valid(rule) { - commonCmd.ExitOnErr(cmd, "read raw rule error: %w", - fmt.Errorf("invalid JSON")) - } - } - err := chain.DecodeBytes(rule) - commonCmd.ExitOnErr(cmd, "chain decode error: %w", err) + if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { + commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules)) + } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { + commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) } else { - commonCmd.ExitOnErr(cmd, "", fmt.Errorf("rule is not passed")) + commonCmd.ExitOnErr(cmd, "parser error: %w", fmt.Errorf("rule is not passed")) } chain.ID = parseChainID(cmd) + cmd.Println("Parsed chain:") + parseutil.PrintHumanReadableAPEChain(cmd, chain) + return chain } From 0f064b79628c52779d6fbdebdbcb2e74597240ce Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 16 Feb 2024 13:13:54 +0300 Subject: [PATCH 0397/1413] [#989] util: Introduce any and all statements for ape rule parsing Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/docs/policy.md | 3 +++ cmd/frostfs-cli/modules/util/ape.go | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/cmd/frostfs-cli/docs/policy.md b/cmd/frostfs-cli/docs/policy.md index 06c325c62a..43dd97fcfc 100644 --- a/cmd/frostfs-cli/docs/policy.md +++ b/cmd/frostfs-cli/docs/policy.md @@ -30,6 +30,9 @@ Actions is a regular operations upon FrostFS containers/objects. Like `Object.Pu In status section it is possible to use `allow`, `deny` or `deny:QuotaLimitReached` actions. +If a statement does not contain lexeme `any`, field `Any` is set to `false` by default. Otherwise, it is set +to `true`. Optionally, `all` can be used - it also sets `Any=false`. + It is prohibited to mix operation under FrostFS container and object in one rule. The same statement is equal for conditions and resources - one rule is for one type of items. diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index dfe70e7da3..41d186b0cb 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -100,6 +100,8 @@ func ParseAPEChain(chain *apechain.Chain, rules []string) error { // deny:QuotaLimitReached Object.Put * // allow Object.Put * // allow Object.Get Object.Resource:Department=HR Object.Request:Actor=ownerA * +// allow Object.Get any Object.Resource:Department=HR Object.Request:Actor=ownerA * +// allow Object.Get all Object.Resource:Department=HR Object.Request:Actor=ownerA * // //nolint:godot func ParseAPERule(r *apechain.Rule, rule string) error { @@ -123,6 +125,12 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { var isObject *bool for i, lexeme := range lexemes[1:] { + anyExpr, anyErr := parseAnyAll(lexeme) + if anyErr == nil { + r.Any = anyExpr + continue + } + var name string var actionType bool name, actionType, err = parseAction(lexeme) @@ -158,6 +166,17 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { return nil } +func parseAnyAll(lexeme string) (bool, error) { + switch strings.ToLower(lexeme) { + case "any": + return true, nil + case "all": + return false, nil + default: + return false, fmt.Errorf("any/all is not parsed") + } +} + func parseStatus(lexeme string) (apechain.Status, error) { action, expression, found := strings.Cut(lexeme, ":") switch strings.ToLower(action) { From 47d9ce71be9e9b85a1da639ee2ad152b76659ea3 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 14 Feb 2024 17:57:19 +0300 Subject: [PATCH 0398/1413] [#986] cli: Allow add-rule command to parse new actions * Introduce Object.* and Container.* actions that span all methods for services. Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/docs/policy.md | 1 + cmd/frostfs-cli/modules/util/ape.go | 69 ++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/cmd/frostfs-cli/docs/policy.md b/cmd/frostfs-cli/docs/policy.md index 43dd97fcfc..1d51818ac6 100644 --- a/cmd/frostfs-cli/docs/policy.md +++ b/cmd/frostfs-cli/docs/policy.md @@ -27,6 +27,7 @@ For container it can be represented as: - `/*` all containers in the `root` namespace Actions is a regular operations upon FrostFS containers/objects. Like `Object.Put`, `Container.Get` etc. +You can use `Object.*`, `Container.*` that implies all actions. In status section it is possible to use `allow`, `deny` or `deny:QuotaLimitReached` actions. diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 41d186b0cb..1500f0c5cb 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -102,6 +102,8 @@ func ParseAPEChain(chain *apechain.Chain, rules []string) error { // allow Object.Get Object.Resource:Department=HR Object.Request:Actor=ownerA * // allow Object.Get any Object.Resource:Department=HR Object.Request:Actor=ownerA * // allow Object.Get all Object.Resource:Department=HR Object.Request:Actor=ownerA * +// allow Object.* * +// allow Container.* * // //nolint:godot func ParseAPERule(r *apechain.Rule, rule string) error { @@ -112,6 +114,18 @@ func ParseAPERule(r *apechain.Rule, rule string) error { return parseRuleLexemes(r, lexemes) } +func unique(inputSlice []string) []string { + uniqueSlice := make([]string, 0, len(inputSlice)) + seen := make(map[string]bool, len(inputSlice)) + for _, element := range inputSlice { + if !seen[element] { + uniqueSlice = append(uniqueSlice, element) + seen[element] = true + } + } + return uniqueSlice +} + func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { if len(lexemes) < 2 { return errInvalidStatementFormat @@ -131,9 +145,9 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { continue } - var name string + var names []string var actionType bool - name, actionType, err = parseAction(lexeme) + names, actionType, err = parseAction(lexeme) if err != nil { condition, errCond := parseCondition(lexeme) if errCond != nil { @@ -144,7 +158,7 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { actionType = condition.Object == apechain.ObjectResource || condition.Object == apechain.ObjectRequest r.Condition = append(r.Condition, *condition) } else { - r.Actions.Names = append(r.Actions.Names, name) + r.Actions.Names = append(r.Actions.Names, names...) } if isObject == nil { isObject = &actionType @@ -152,6 +166,7 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { return errMixedTypesInRule } } + r.Actions.Names = unique(r.Actions.Names) if len(r.Actions.Names) == 0 { return fmt.Errorf("%w:%w", err, errNoActionsInRule) } @@ -198,35 +213,55 @@ func parseStatus(lexeme string) (apechain.Status, error) { } } -func parseAction(lexeme string) (string, bool, error) { +func parseAction(lexeme string) ([]string, bool, error) { switch strings.ToLower(lexeme) { case "object.put": - return nativeschema.MethodPutObject, true, nil + return []string{nativeschema.MethodPutObject}, true, nil case "object.get": - return nativeschema.MethodGetObject, true, nil + return []string{nativeschema.MethodGetObject}, true, nil case "object.head": - return nativeschema.MethodHeadObject, true, nil + return []string{nativeschema.MethodHeadObject}, true, nil case "object.delete": - return nativeschema.MethodDeleteObject, true, nil + return []string{nativeschema.MethodDeleteObject}, true, nil case "object.search": - return nativeschema.MethodSearchObject, true, nil + return []string{nativeschema.MethodSearchObject}, true, nil case "object.range": - return nativeschema.MethodRangeObject, true, nil + return []string{nativeschema.MethodRangeObject}, true, nil case "object.hash": - return nativeschema.MethodHashObject, true, nil + return []string{nativeschema.MethodHashObject}, true, nil + case "object.*": + return []string{ + nativeschema.MethodPutObject, + nativeschema.MethodGetObject, + nativeschema.MethodHeadObject, + nativeschema.MethodDeleteObject, + nativeschema.MethodSearchObject, + nativeschema.MethodHashObject, + }, true, nil case "container.put": - return nativeschema.MethodPutContainer, false, nil + return []string{nativeschema.MethodPutContainer}, false, nil case "container.delete": - return nativeschema.MethodDeleteContainer, false, nil + return []string{nativeschema.MethodDeleteContainer}, false, nil case "container.get": - return nativeschema.MethodGetContainer, false, nil + return []string{nativeschema.MethodGetContainer}, false, nil case "container.setcontainereacl": - return nativeschema.MethodSetContainerEACL, false, nil + return []string{nativeschema.MethodSetContainerEACL}, false, nil case "container.getcontainereacl": - return nativeschema.MethodGetContainerEACL, false, nil + return []string{nativeschema.MethodGetContainerEACL}, false, nil + case "container.list": + return []string{nativeschema.MethodListContainers}, false, nil + case "container.*": + return []string{ + nativeschema.MethodPutContainer, + nativeschema.MethodDeleteContainer, + nativeschema.MethodGetContainer, + nativeschema.MethodSetContainerEACL, + nativeschema.MethodGetContainerEACL, + nativeschema.MethodListContainers, + }, false, nil default: } - return "", false, fmt.Errorf("%w: %s", errUnknownAction, lexeme) + return nil, false, fmt.Errorf("%w: %s", errUnknownAction, lexeme) } func parseResource(lexeme string, isObj bool) (string, error) { From adf7ebab5b295070adb3c866058c218f53d07d42 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 16 Feb 2024 22:49:53 +0300 Subject: [PATCH 0399/1413] [#996] metabase: Speed up bucket creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the time it exits, e.g. when it is per-container and use on each object PUT. Bbolt implementation first tries to create bucket and then returns it if it exists. Create operation uses cursor and thus is not very lightweight, we can avoid it. ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ old │ new │ │ sec/op │ sec/op vs base │ Put/parallel-8 174.4µ ± 3% 163.3µ ± 3% -6.39% (p=0.000 n=10) Put/sequential-8 263.3µ ± 2% 259.0µ ± 1% -1.64% (p=0.000 n=10) geomean 214.3µ 205.6µ -4.05% │ old │ new │ │ B/op │ B/op vs base │ Put/parallel-8 275.3Ki ± 3% 281.1Ki ± 4% ~ (p=0.063 n=10) Put/sequential-8 413.0Ki ± 2% 426.6Ki ± 2% +3.29% (p=0.003 n=10) geomean 337.2Ki 346.3Ki +2.70% │ old │ new │ │ allocs/op │ allocs/op vs base │ Put/parallel-8 678.0 ± 1% 524.5 ± 2% -22.64% (p=0.000 n=10) Put/sequential-8 1.329k ± 0% 1.183k ± 0% -10.91% (p=0.000 n=10) geomean 949.1 787.9 -16.98% ``` Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/counter.go | 4 ++-- pkg/local_object_storage/metabase/put.go | 23 +++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index 915fbd957d..ee1ab41de5 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -346,7 +346,7 @@ func (db *DB) incContainerObjectCounter(tx *bbolt.Tx, cnrID cid.ID, isUserObject // Does nothing if counters are not empty and force is false. If force is // true, updates the counters anyway. func syncCounter(tx *bbolt.Tx, force bool) error { - shardInfoB, err := tx.CreateBucketIfNotExists(shardInfoBucket) + shardInfoB, err := createBucketLikelyExists(tx, shardInfoBucket) if err != nil { return fmt.Errorf("could not get shard info bucket: %w", err) } @@ -359,7 +359,7 @@ func syncCounter(tx *bbolt.Tx, force bool) error { return nil } - containerCounterB, err := tx.CreateBucketIfNotExists(containerCounterBucketName) + containerCounterB, err := createBucketLikelyExists(tx, containerCounterBucketName) if err != nil { return fmt.Errorf("could not get container counter bucket: %w", err) } diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 1f00223897..5d8e4d2636 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -356,8 +356,21 @@ func updateFKBTIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun return nil } +type bucketContainer interface { + Bucket([]byte) *bbolt.Bucket + CreateBucket([]byte) (*bbolt.Bucket, error) + CreateBucketIfNotExists([]byte) (*bbolt.Bucket, error) +} + +func createBucketLikelyExists[T bucketContainer](tx T, name []byte) (*bbolt.Bucket, error) { + if bkt := tx.Bucket(name); bkt != nil { + return bkt, nil + } + return tx.CreateBucket(name) +} + func putUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) error { - bkt, err := tx.CreateBucketIfNotExists(item.name) + bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { return fmt.Errorf("can't create index %v: %w", item.name, err) } @@ -366,12 +379,12 @@ func putUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) error { } func putFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { - bkt, err := tx.CreateBucketIfNotExists(item.name) + bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { return fmt.Errorf("can't create index %v: %w", item.name, err) } - fkbtRoot, err := bkt.CreateBucketIfNotExists(item.key) + fkbtRoot, err := createBucketLikelyExists(bkt, item.key) if err != nil { return fmt.Errorf("can't create fake bucket tree index %v: %w", item.key, err) } @@ -380,7 +393,7 @@ func putFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { } func putListIndexItem(tx *bbolt.Tx, item namedBucketItem) error { - bkt, err := tx.CreateBucketIfNotExists(item.name) + bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { return fmt.Errorf("can't create index %v: %w", item.name, err) } @@ -474,7 +487,7 @@ func getVarUint(data []byte) (uint64, int, error) { // storage location to another. func updateStorageID(tx *bbolt.Tx, addr oid.Address, id []byte) error { key := make([]byte, bucketKeySize) - bkt, err := tx.CreateBucketIfNotExists(smallBucketName(addr.Container(), key)) + bkt, err := createBucketLikelyExists(tx, smallBucketName(addr.Container(), key)) if err != nil { return err } From 7470c383dda3cdb86e6c5c4761f67a98a88c7383 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 20 Feb 2024 15:55:18 +0300 Subject: [PATCH 0400/1413] [#997] metabase: Drop toMoveIt bucket It is not used. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 - pkg/local_object_storage/engine/evacuate.go | 2 +- pkg/local_object_storage/engine/put.go | 20 +-- .../metabase/containers_test.go | 17 --- pkg/local_object_storage/metabase/control.go | 13 +- pkg/local_object_storage/metabase/delete.go | 5 - .../metabase/delete_test.go | 14 -- pkg/local_object_storage/metabase/movable.go | 144 ------------------ .../metabase/movable_test.go | 85 ----------- pkg/local_object_storage/shard/move.go | 62 -------- 10 files changed, 16 insertions(+), 347 deletions(-) delete mode 100644 pkg/local_object_storage/metabase/movable.go delete mode 100644 pkg/local_object_storage/metabase/movable_test.go delete mode 100644 pkg/local_object_storage/shard/move.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index d839915d82..6b48940b78 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -220,7 +220,6 @@ const ( EngineCouldNotCloseShard = "could not close shard" EngineCouldNotReloadAShard = "could not reload a shard" EngineAddedNewShard = "added new shard" - EngineCouldNotMarkObjectForShardRelocation = "could not mark object for shard relocation" EngineCouldNotPutObjectToShard = "could not put object to shard" EngineErrorDuringSearchingForObjectChildren = "error during searching for object children" EngineCouldNotInhumeObjectInShard = "could not inhume object in shard" diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index becddfa8b7..67db518c61 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -700,7 +700,7 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add if _, ok := shardsToEvacuate[shards[j].ID().String()]; ok { continue } - switch e.putToShard(ctx, shards[j].hashedShard, j, shards[j].pool, addr, object).status { + switch e.putToShard(ctx, shards[j].hashedShard, shards[j].pool, addr, object).status { case putToShardSuccess: res.objEvacuated.Add(1) e.log.Debug(logs.EngineObjectIsMovedToAnotherShard, diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 2b1712f3f6..c1cd29cb8a 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -84,7 +84,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { } var shRes putToShardRes - e.iterateOverSortedShards(addr, func(ind int, sh hashedShard) (stop bool) { + e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { e.mtx.RLock() pool, ok := e.shardPools[sh.ID().String()] e.mtx.RUnlock() @@ -92,7 +92,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // Shard was concurrently removed, skip. return false } - shRes = e.putToShard(ctx, sh, ind, pool, addr, prm.obj) + shRes = e.putToShard(ctx, sh, pool, addr, prm.obj) return shRes.status != putToShardUnknown }) switch shRes.status { @@ -109,7 +109,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // putToShard puts object to sh. // Return putToShardStatus and error if it is necessary to propagate an error upper. -func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, pool util.WorkerPool, +func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool util.WorkerPool, addr oid.Address, obj *objectSDK.Object, ) (res putToShardRes) { exitCh := make(chan struct{}) @@ -132,20 +132,6 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, ind int, } if exists.Exists() { - if ind != 0 { - var toMoveItPrm shard.ToMoveItPrm - toMoveItPrm.SetAddress(addr) - - _, err = sh.ToMoveIt(ctx, toMoveItPrm) - if err != nil { - e.log.Warn(logs.EngineCouldNotMarkObjectForShardRelocation, - zap.Stringer("shard", sh.ID()), - zap.String("error", err.Error()), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), - ) - } - } - res.status = putToShardExists return } diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index e7762ded6b..a90cd9d972 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -74,23 +74,6 @@ func TestDB_Containers(t *testing.T) { require.NoError(t, err) assertContains(cnrs, cnr) }) - - t.Run("ToMoveIt", func(t *testing.T) { - obj := testutil.GenerateObject() - - require.NoError(t, putBig(db, obj)) - - cnrs, err := db.Containers(context.Background()) - require.NoError(t, err) - cnr, _ := obj.ContainerID() - assertContains(cnrs, cnr) - - require.NoError(t, metaToMoveIt(db, object.AddressOf(obj))) - - cnrs, err = db.Containers(context.Background()) - require.NoError(t, err) - assertContains(cnrs, cnr) - }) } func TestDB_ContainersCount(t *testing.T) { diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index c1a86819de..ec4c29c4bf 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -117,12 +117,16 @@ func (db *DB) init(reset bool) error { string(containerVolumeBucketName): {}, string(containerCounterBucketName): {}, string(graveyardBucketName): {}, - string(toMoveItBucketName): {}, string(garbageBucketName): {}, string(shardInfoBucket): {}, string(bucketNameLocked): {}, } + // buckets that are not used anymore + deprecatedBuckets := [][]byte{ + toMoveItBucketName, + } + return db.boltDB.Update(func(tx *bbolt.Tx) error { var err error if !reset { @@ -147,6 +151,13 @@ func (db *DB) init(reset bool) error { } } + for _, b := range deprecatedBuckets { + err := tx.DeleteBucket(b) + if err != nil && !errors.Is(err, bbolt.ErrBucketNotFound) { + return fmt.Errorf("could not delete deprecated bucket %s: %w", string(b), err) + } + } + if !reset { // counters will be recalculated by refill metabase err = syncCounter(tx, false) if err != nil { diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 8e5557636a..e5a98ff010 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -434,7 +434,6 @@ func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error addr := object.AddressOf(obj) objKey := objectKey(addr.Object(), make([]byte, objectKeySize)) - addrKey := addressKey(addr, make([]byte, addressKeySize)) cnr := addr.Container() bucketName := make([]byte, bucketKeySize) @@ -470,10 +469,6 @@ func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error name: rootBucketName(cnr, bucketName), key: objKey, }) - delUniqueIndexItem(tx, namedBucketItem{ // remove from ToMoveIt index - name: toMoveItBucketName, - key: addrKey, - }) return nil } diff --git a/pkg/local_object_storage/metabase/delete_test.go b/pkg/local_object_storage/metabase/delete_test.go index 649c0ebe3c..2053874d03 100644 --- a/pkg/local_object_storage/metabase/delete_test.go +++ b/pkg/local_object_storage/metabase/delete_test.go @@ -33,15 +33,6 @@ func TestDB_Delete(t *testing.T) { err := putBig(db, child) require.NoError(t, err) - // fill ToMoveIt index - err = metaToMoveIt(db, object.AddressOf(child)) - require.NoError(t, err) - - // check if Movable list is not empty - l, err := metaMovable(db) - require.NoError(t, err) - require.Len(t, l, 1) - // try to remove parent, should be no-op, error-free err = metaDelete(db, object.AddressOf(parent)) require.NoError(t, err) @@ -61,11 +52,6 @@ func TestDB_Delete(t *testing.T) { err = metaDelete(db, object.AddressOf(child)) require.NoError(t, err) - // check if there is no data in Movable index - l, err = metaMovable(db) - require.NoError(t, err) - require.Len(t, l, 0) - // check if they marked as already removed ok, err := metaExists(db, object.AddressOf(child)) diff --git a/pkg/local_object_storage/metabase/movable.go b/pkg/local_object_storage/metabase/movable.go deleted file mode 100644 index 763e49a5d2..0000000000 --- a/pkg/local_object_storage/metabase/movable.go +++ /dev/null @@ -1,144 +0,0 @@ -package meta - -import ( - "context" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.etcd.io/bbolt" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -// ToMoveItPrm groups the parameters of ToMoveIt operation. -type ToMoveItPrm struct { - addr oid.Address -} - -// ToMoveItRes groups the resulting values of ToMoveIt operation. -type ToMoveItRes struct{} - -// SetAddress sets address of the object to move into another shard. -func (p *ToMoveItPrm) SetAddress(addr oid.Address) { - p.addr = addr -} - -// DoNotMovePrm groups the parameters of DoNotMove operation. -type DoNotMovePrm struct { - addr oid.Address -} - -// DoNotMoveRes groups the resulting values of DoNotMove operation. -type DoNotMoveRes struct{} - -// SetAddress sets address of the object to prevent moving into another shard. -func (p *DoNotMovePrm) SetAddress(addr oid.Address) { - p.addr = addr -} - -// MovablePrm groups the parameters of Movable operation. -type MovablePrm struct{} - -// MovableRes groups the resulting values of Movable operation. -type MovableRes struct { - addrList []oid.Address -} - -// AddressList returns resulting addresses of Movable operation. -func (p MovableRes) AddressList() []oid.Address { - return p.addrList -} - -// ToMoveIt marks objects to move it into another shard. This useful for -// faster HRW fetching. -func (db *DB) ToMoveIt(ctx context.Context, prm ToMoveItPrm) (res ToMoveItRes, err error) { - _, span := tracing.StartSpanFromContext(ctx, "metabase.ToMoveIt", - trace.WithAttributes( - attribute.String("address", prm.addr.EncodeToString()), - )) - defer span.End() - - db.modeMtx.RLock() - defer db.modeMtx.RUnlock() - - if db.mode.NoMetabase() { - return res, ErrDegradedMode - } else if db.mode.ReadOnly() { - return res, ErrReadOnlyMode - } - - key := make([]byte, addressKeySize) - key = addressKey(prm.addr, key) - - err = db.boltDB.Update(func(tx *bbolt.Tx) error { - toMoveIt := tx.Bucket(toMoveItBucketName) - return toMoveIt.Put(key, zeroValue) - }) - - return res, metaerr.Wrap(err) -} - -// DoNotMove removes `MoveIt` mark from the object. -func (db *DB) DoNotMove(prm DoNotMovePrm) (res DoNotMoveRes, err error) { - db.modeMtx.RLock() - defer db.modeMtx.RUnlock() - - if db.mode.NoMetabase() { - return res, ErrDegradedMode - } else if db.mode.ReadOnly() { - return res, ErrReadOnlyMode - } - - key := make([]byte, addressKeySize) - key = addressKey(prm.addr, key) - - err = db.boltDB.Update(func(tx *bbolt.Tx) error { - toMoveIt := tx.Bucket(toMoveItBucketName) - return toMoveIt.Delete(key) - }) - - return res, metaerr.Wrap(err) -} - -// Movable returns list of marked objects to move into other shard. -func (db *DB) Movable(_ MovablePrm) (MovableRes, error) { - db.modeMtx.RLock() - defer db.modeMtx.RUnlock() - - if db.mode.NoMetabase() { - return MovableRes{}, ErrDegradedMode - } - - var strAddrs []string - - err := db.boltDB.View(func(tx *bbolt.Tx) error { - toMoveIt := tx.Bucket(toMoveItBucketName) - return toMoveIt.ForEach(func(k, v []byte) error { - strAddrs = append(strAddrs, string(k)) - - return nil - }) - }) - if err != nil { - return MovableRes{}, metaerr.Wrap(err) - } - - // we can parse strings to structures in-place, but probably it seems - // more efficient to keep bolt db TX code smaller because it might be - // bottleneck. - addrs := make([]oid.Address, len(strAddrs)) - - for i := range strAddrs { - err = decodeAddressFromKey(&addrs[i], []byte(strAddrs[i])) - if err != nil { - return MovableRes{}, metaerr.Wrap(fmt.Errorf("can't parse object address %v: %w", - strAddrs[i], err)) - } - } - - return MovableRes{ - addrList: addrs, - }, nil -} diff --git a/pkg/local_object_storage/metabase/movable_test.go b/pkg/local_object_storage/metabase/movable_test.go deleted file mode 100644 index d66d928673..0000000000 --- a/pkg/local_object_storage/metabase/movable_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package meta_test - -import ( - "context" - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/stretchr/testify/require" -) - -func TestDB_Movable(t *testing.T) { - db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() - - raw1 := testutil.GenerateObject() - raw2 := testutil.GenerateObject() - - // put two objects in metabase - err := putBig(db, raw1) - require.NoError(t, err) - - err = putBig(db, raw2) - require.NoError(t, err) - - // check if toMoveIt index empty - toMoveList, err := metaMovable(db) - require.NoError(t, err) - require.Len(t, toMoveList, 0) - - // mark to move object2 - err = metaToMoveIt(db, object.AddressOf(raw2)) - require.NoError(t, err) - - // check if toMoveIt index contains address of object 2 - toMoveList, err = metaMovable(db) - require.NoError(t, err) - require.Len(t, toMoveList, 1) - require.Contains(t, toMoveList, object.AddressOf(raw2)) - - // remove from toMoveIt index non existing address - err = metaDoNotMove(db, object.AddressOf(raw1)) - require.NoError(t, err) - - // check if toMoveIt index hasn't changed - toMoveList, err = metaMovable(db) - require.NoError(t, err) - require.Len(t, toMoveList, 1) - - // remove from toMoveIt index existing address - err = metaDoNotMove(db, object.AddressOf(raw2)) - require.NoError(t, err) - - // check if toMoveIt index is empty now - toMoveList, err = metaMovable(db) - require.NoError(t, err) - require.Len(t, toMoveList, 0) -} - -func metaToMoveIt(db *meta.DB, addr oid.Address) error { - var toMovePrm meta.ToMoveItPrm - toMovePrm.SetAddress(addr) - - _, err := db.ToMoveIt(context.Background(), toMovePrm) - return err -} - -func metaMovable(db *meta.DB) ([]oid.Address, error) { - r, err := db.Movable(meta.MovablePrm{}) - if err != nil { - return nil, err - } - - return r.AddressList(), nil -} - -func metaDoNotMove(db *meta.DB, addr oid.Address) error { - var doNotMovePrm meta.DoNotMovePrm - doNotMovePrm.SetAddress(addr) - - _, err := db.DoNotMove(doNotMovePrm) - return err -} diff --git a/pkg/local_object_storage/shard/move.go b/pkg/local_object_storage/shard/move.go deleted file mode 100644 index 539dbc97f0..0000000000 --- a/pkg/local_object_storage/shard/move.go +++ /dev/null @@ -1,62 +0,0 @@ -package shard - -import ( - "context" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" - "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" -) - -// ToMoveItPrm encapsulates parameters for ToMoveIt operation. -type ToMoveItPrm struct { - addr oid.Address -} - -// ToMoveItRes encapsulates results of ToMoveIt operation. -type ToMoveItRes struct{} - -// SetAddress sets object address that should be marked to move into another -// shard. -func (p *ToMoveItPrm) SetAddress(addr oid.Address) { - p.addr = addr -} - -// ToMoveIt calls metabase.ToMoveIt method to mark object as relocatable to -// another shard. -func (s *Shard) ToMoveIt(ctx context.Context, prm ToMoveItPrm) (ToMoveItRes, error) { - ctx, span := tracing.StartSpanFromContext(ctx, "Shard.ToMoveIt", - trace.WithAttributes( - attribute.String("shard_id", s.ID().String()), - attribute.String("address", prm.addr.EncodeToString()), - )) - defer span.End() - - s.m.RLock() - defer s.m.RUnlock() - - m := s.info.Mode - if m.ReadOnly() { - return ToMoveItRes{}, ErrReadOnlyMode - } else if m.NoMetabase() { - return ToMoveItRes{}, ErrDegradedMode - } - - var toMovePrm meta.ToMoveItPrm - toMovePrm.SetAddress(prm.addr) - - _, err := s.metaBase.ToMoveIt(ctx, toMovePrm) - if err != nil { - s.log.Debug(logs.ShardCouldNotMarkObjectForShardRelocationInMetabase, - zap.String("error", err.Error()), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), - ) - } - - return ToMoveItRes{}, nil -} From e18f0f517856668e35bb8753fa89214803d77f7c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 20 Feb 2024 18:59:35 +0300 Subject: [PATCH 0401/1413] [#999] morph: Use Global scope for proxy contract Proxy contract can now be used as an owner of NNS domains, thus we need it not only to pay for the transaction but also to check domain ownership. CalledByEntry is not enough, because we may register NNS domains owned by proxy indirectly from the container contract. Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/notary.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 5b817a8056..1665fec1de 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -569,7 +569,11 @@ func (c *Client) notaryCosigners(invokedByAlpha bool, ir []*keys.PublicKey, comm s[0] = actor.SignerAccount{ Signer: transaction.Signer{ Account: c.notary.proxy, - Scopes: transaction.None, + // Do not change this: + // We must be able to call NNS contract indirectly from the Container contract. + // Thus, CalledByEntry is not sufficient. + // In future we may restrict this to all the usecases we have. + Scopes: transaction.Global, }, Account: notary.FakeContractAccount(c.notary.proxy), } From 4b13b85173402860f41a2d9aede7c13a4ccc8375 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 21 Feb 2024 15:22:50 +0300 Subject: [PATCH 0402/1413] [#1000] morph: Fix batch size in TraverseIterator() Initial prefetch size can be arbitrary an restricted only by VM/RPC limits. For TraverseIterator() there is an explicit check on the server-side, though. Introduced in df055fead56e6ac. Refs #931. Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/client.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 88f9703e7a..2570bc2c92 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -260,8 +260,13 @@ func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int _ = c.rpcActor.TerminateSession(sid) }() + // Batch size for TraverseIterator() can restricted on the server-side. + traverseBatchSize := batchSize + if invoker.DefaultIteratorResultItems < traverseBatchSize { + traverseBatchSize = invoker.DefaultIteratorResultItems + } for { - items, err := c.rpcActor.TraverseIterator(sid, &r, batchSize) + items, err := c.rpcActor.TraverseIterator(sid, &r, traverseBatchSize) if err != nil { return err } @@ -271,7 +276,7 @@ func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int return err } } - if len(items) < batchSize { + if len(items) < traverseBatchSize { break } } From abea258b657cb5208afae58b08f79e9385fe1825 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 21 Feb 2024 15:29:08 +0300 Subject: [PATCH 0403/1413] [#1000] adm: Use default batch size for TraverseIterator() Nothing is broken now, but will easily become if we change nnsMaxTokens, thus this change. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/contract/dump_hashes.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index 6e406be56e..11cc3bd048 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -177,12 +177,12 @@ func dumpCustomZoneHashes(cmd *cobra.Command, nnsHash util.Uint160, zone string, _ = inv.TerminateSession(sessionID) }() - items, err := inv.TraverseIterator(sessionID, &iter, nnsMaxTokens) + items, err := inv.TraverseIterator(sessionID, &iter, 0) for err == nil && len(items) != 0 { for i := range items { processItem(items[i]) } - items, err = inv.TraverseIterator(sessionID, &iter, nnsMaxTokens) + items, err = inv.TraverseIterator(sessionID, &iter, 0) } if err != nil { return fmt.Errorf("error during NNS domains iteration: %w", err) From 2ad433dbcbab64caea243dbbae4553c7c0931719 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 26 Feb 2024 11:19:52 +0300 Subject: [PATCH 0404/1413] [#1005] engine: Drop shards weights Unused. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 63 +++++++++---------- .../engine/remove_copies.go | 2 +- .../engine/remove_copies_test.go | 2 +- pkg/local_object_storage/engine/shards.go | 21 +------ .../engine/shards_test.go | 25 ++++++++ pkg/local_object_storage/engine/tree.go | 14 ++--- pkg/local_object_storage/shard/info.go | 3 - pkg/local_object_storage/shard/weight.go | 12 ---- 8 files changed, 65 insertions(+), 77 deletions(-) delete mode 100644 pkg/local_object_storage/shard/weight.go diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 67db518c61..45600fe666 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -221,7 +221,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev )) defer span.End() - shards, weights, err := e.getActualShards(shardIDs, prm) + shards, err := e.getActualShards(shardIDs, prm) if err != nil { return nil, err } @@ -243,7 +243,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev } eg.Go(func() error { - return e.evacuateShards(egCtx, shardIDs, prm, res, shards, weights, shardsToEvacuate) + return e.evacuateShards(egCtx, shardIDs, prm, res, shards, shardsToEvacuate) }) if prm.Async { @@ -261,7 +261,7 @@ func ctxOrBackground(ctx context.Context, background bool) context.Context { } func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, + shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { var err error ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShards", @@ -288,7 +288,7 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p } for _, shardID := range shardIDs { - if err = e.evacuateShard(ctx, shardID, prm, res, shards, weights, shardsToEvacuate); err != nil { + if err = e.evacuateShard(ctx, shardID, prm, res, shards, shardsToEvacuate); err != nil { e.log.Error(logs.EngineFinishedWithErrorShardsEvacuation, zap.Error(err), zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) return err @@ -336,7 +336,7 @@ func (e *StorageEngine) getTotals(ctx context.Context, prm EvacuateShardPrm, sha } func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, + shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShard", trace.WithAttributes( @@ -345,13 +345,13 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm E defer span.End() if prm.Scope.WithObjects() { - if err := e.evacuateShardObjects(ctx, shardID, prm, res, shards, weights, shardsToEvacuate); err != nil { + if err := e.evacuateShardObjects(ctx, shardID, prm, res, shards, shardsToEvacuate); err != nil { return err } } if prm.Scope.WithTrees() && shardsToEvacuate[shardID].PiloramaEnabled() { - if err := e.evacuateShardTrees(ctx, shardID, prm, res, shards, weights, shardsToEvacuate); err != nil { + if err := e.evacuateShardTrees(ctx, shardID, prm, res, shards, shardsToEvacuate); err != nil { return err } } @@ -360,7 +360,7 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm E } func (e *StorageEngine) evacuateShardObjects(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, + shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { var listPrm shard.ListWithCursorPrm listPrm.WithCount(defaultEvacuateBatchSize) @@ -383,7 +383,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, shardID string return err } - if err = e.evacuateObjects(ctx, sh, listRes.AddressList(), prm, res, shards, weights, shardsToEvacuate); err != nil { + if err = e.evacuateObjects(ctx, sh, listRes.AddressList(), prm, res, shards, shardsToEvacuate); err != nil { return err } @@ -393,7 +393,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, shardID string } func (e *StorageEngine) evacuateShardTrees(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, + shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { sh := shardsToEvacuate[shardID] @@ -414,7 +414,7 @@ func (e *StorageEngine) evacuateShardTrees(ctx context.Context, shardID string, return err } listPrm.NextPageToken = listRes.NextPageToken - if err := e.evacuateTrees(ctx, sh, listRes.Items, prm, res, shards, weights, shardsToEvacuate); err != nil { + if err := e.evacuateTrees(ctx, sh, listRes.Items, prm, res, shards, shardsToEvacuate); err != nil { return err } } @@ -422,8 +422,7 @@ func (e *StorageEngine) evacuateShardTrees(ctx context.Context, shardID string, } func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, trees []pilorama.ContainerIDTreeID, - prm EvacuateShardPrm, res *EvacuateShardRes, shards []pooledShard, weights []float64, - shardsToEvacuate map[string]*shard.Shard, + prm EvacuateShardPrm, res *EvacuateShardRes, shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateTrees", trace.WithAttributes( @@ -438,7 +437,7 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree default: } - success, shardID, err := e.tryEvacuateTreeLocal(ctx, sh, contTree, prm, shards, weights, shardsToEvacuate) + success, shardID, err := e.tryEvacuateTreeLocal(ctx, sh, contTree, prm, shards, shardsToEvacuate) if err != nil { return err } @@ -477,9 +476,9 @@ func (e *StorageEngine) evacuateTreeToOtherNode(ctx context.Context, sh *shard.S } func (e *StorageEngine) tryEvacuateTreeLocal(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, - prm EvacuateShardPrm, shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, + prm EvacuateShardPrm, shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) (bool, string, error) { - target, found, err := e.findShardToEvacuateTree(ctx, tree, shards, weights, shardsToEvacuate) + target, found, err := e.findShardToEvacuateTree(ctx, tree, shards, shardsToEvacuate) if err != nil { return false, "", err } @@ -547,9 +546,9 @@ func (e *StorageEngine) tryEvacuateTreeLocal(ctx context.Context, sh *shard.Shar // findShardToEvacuateTree returns first shard according HRW or first shard with tree exists. func (e *StorageEngine) findShardToEvacuateTree(ctx context.Context, tree pilorama.ContainerIDTreeID, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, + shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) (pooledShard, bool, error) { - hrw.SortHasherSliceByWeightValue(shards, weights, hrw.StringHash(tree.CID.EncodeToString())) + hrw.SortHasherSliceByValue(shards, hrw.StringHash(tree.CID.EncodeToString())) var result pooledShard var found bool for _, target := range shards { @@ -583,31 +582,31 @@ func (e *StorageEngine) findShardToEvacuateTree(ctx context.Context, tree pilora return result, found, nil } -func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) ([]pooledShard, []float64, error) { +func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) ([]pooledShard, error) { e.mtx.RLock() defer e.mtx.RUnlock() for i := range shardIDs { sh, ok := e.shards[shardIDs[i]] if !ok { - return nil, nil, errShardNotFound + return nil, errShardNotFound } if !sh.GetMode().ReadOnly() { - return nil, nil, ErrMustBeReadOnly + return nil, ErrMustBeReadOnly } if prm.Scope.TreesOnly() && !sh.PiloramaEnabled() { - return nil, nil, fmt.Errorf("shard %s doesn't have pilorama enabled", sh.ID()) + return nil, fmt.Errorf("shard %s doesn't have pilorama enabled", sh.ID()) } } if len(e.shards)-len(shardIDs) < 1 && prm.ObjectsHandler == nil && prm.Scope.WithObjects() { - return nil, nil, errMustHaveTwoShards + return nil, errMustHaveTwoShards } if len(e.shards)-len(shardIDs) < 1 && prm.TreeHandler == nil && prm.Scope.WithTrees() { - return nil, nil, errMustHaveTwoShards + return nil, errMustHaveTwoShards } // We must have all shards, to have correct information about their @@ -620,17 +619,11 @@ func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) pool: e.shardPools[id], }) } - - weights := make([]float64, 0, len(shards)) - for i := range shards { - weights = append(weights, e.shardWeight(shards[i].Shard)) - } - - return shards, weights, nil + return shards, nil } func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, toEvacuate []object.AddressWithType, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, + shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateObjects", trace.WithAttributes( @@ -660,7 +653,7 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to return err } - evacuatedLocal, err := e.tryEvacuateObjectLocal(ctx, addr, getRes.Object(), sh, shards, weights, shardsToEvacuate, res) + evacuatedLocal, err := e.tryEvacuateObjectLocal(ctx, addr, getRes.Object(), sh, shards, shardsToEvacuate, res) if err != nil { return err } @@ -687,9 +680,9 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to } func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Address, object *objectSDK.Object, sh *shard.Shard, - shards []pooledShard, weights []float64, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes, + shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes, ) (bool, error) { - hrw.SortHasherSliceByWeightValue(shards, weights, hrw.StringHash(addr.EncodeToString())) + hrw.SortHasherSliceByValue(shards, hrw.StringHash(addr.EncodeToString())) for j := range shards { select { case <-ctx.Done(): diff --git a/pkg/local_object_storage/engine/remove_copies.go b/pkg/local_object_storage/engine/remove_copies.go index 5731532688..00562e4cbb 100644 --- a/pkg/local_object_storage/engine/remove_copies.go +++ b/pkg/local_object_storage/engine/remove_copies.go @@ -111,7 +111,7 @@ func (e *StorageEngine) removeObjects(ctx context.Context, ch <-chan oid.Address for addr := range ch { h := hrw.StringHash(addr.EncodeToString()) - shards := sortShardsByWeight(shards, h) + hrw.SortHasherSliceByValue(shards, h) found := false for i := range shards { var existsPrm shard.ExistsPrm diff --git a/pkg/local_object_storage/engine/remove_copies_test.go b/pkg/local_object_storage/engine/remove_copies_test.go index dfb2423ffa..99963576cb 100644 --- a/pkg/local_object_storage/engine/remove_copies_test.go +++ b/pkg/local_object_storage/engine/remove_copies_test.go @@ -41,7 +41,7 @@ func TestRebalance(t *testing.T) { obj.SetPayload(make([]byte, errSmallSize)) objects[i].object = obj - shards := te.ng.sortShardsByWeight(object.AddressOf(obj)) + shards := te.ng.sortShards(object.AddressOf(obj)) objects[i].bestShard = *shards[0].Shard.ID() objects[i].worstShard = *shards[1].Shard.ID() } diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 83fa4f5cbe..4bbf7eff0c 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -254,13 +254,7 @@ func generateShardID() (*shard.ID, error) { return shard.NewIDFromBytes(bin), nil } -func (e *StorageEngine) shardWeight(sh *shard.Shard) float64 { - weightValues := sh.WeightValues() - - return float64(weightValues.FreeSpace) -} - -func (e *StorageEngine) sortShardsByWeight(objAddr interface{ EncodeToString() string }) []hashedShard { +func (e *StorageEngine) sortShards(objAddr interface{ EncodeToString() string }) []hashedShard { e.mtx.RLock() defer e.mtx.RUnlock() @@ -269,16 +263,7 @@ func (e *StorageEngine) sortShardsByWeight(objAddr interface{ EncodeToString() s for _, sh := range e.shards { shards = append(shards, hashedShard(sh)) } - return sortShardsByWeight(shards, h) -} - -func sortShardsByWeight(shards []hashedShard, h uint64) []hashedShard { - weights := make([]float64, 0, len(shards)) - for _, sh := range shards { - weights = append(weights, float64(sh.Shard.WeightValues().FreeSpace)) - } - - hrw.SortHasherSliceByWeightValue(shards, weights, h) + hrw.SortHasherSliceByValue(shards, h) return shards } @@ -296,7 +281,7 @@ func (e *StorageEngine) unsortedShards() []hashedShard { } func (e *StorageEngine) iterateOverSortedShards(addr oid.Address, handler func(int, hashedShard) (stop bool)) { - for i, sh := range e.sortShardsByWeight(addr) { + for i, sh := range e.sortShards(addr) { if handler(i, sh) { break } diff --git a/pkg/local_object_storage/engine/shards_test.go b/pkg/local_object_storage/engine/shards_test.go index 3bb602ce40..f4c7a4309b 100644 --- a/pkg/local_object_storage/engine/shards_test.go +++ b/pkg/local_object_storage/engine/shards_test.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/hrw" "github.com/stretchr/testify/require" ) @@ -62,3 +63,27 @@ func TestDisableShards(t *testing.T) { require.Equal(t, 1, len(e.shards)) } + +func TestSortShardsByWeight(t *testing.T) { + t.Parallel() + + const numOfShards = 500 + + var shards1 []hashedShard + var weights1 []float64 + var shards2 []hashedShard + for i := 0; i < numOfShards; i++ { + shards1 = append(shards1, hashedShard{ + hash: uint64(i), + }) + weights1 = append(weights1, 0) + shards2 = append(shards2, hashedShard{ + hash: uint64(i), + }) + } + + hrw.SortHasherSliceByWeightValue(shards1, weights1, 0) + hrw.SortHasherSliceByValue(shards2, 0) + + require.Equal(t, shards1, shards2) +} diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index 6c3594bab4..f50b9cb684 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -125,7 +125,7 @@ func (e *StorageEngine) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID var err error var nodes []pilorama.Node - for _, sh := range e.sortShardsByWeight(cid) { + for _, sh := range e.sortShards(cid) { nodes, err = sh.TreeGetByPath(ctx, cid, treeID, attr, path, latest) if err != nil { if err == shard.ErrPiloramaDisabled { @@ -158,7 +158,7 @@ func (e *StorageEngine) TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID s var err error var m pilorama.Meta var p uint64 - for _, sh := range e.sortShardsByWeight(cid) { + for _, sh := range e.sortShards(cid) { m, p, err = sh.TreeGetMeta(ctx, cid, treeID, nodeID) if err != nil { if err == shard.ErrPiloramaDisabled { @@ -190,7 +190,7 @@ func (e *StorageEngine) TreeGetChildren(ctx context.Context, cid cidSDK.ID, tree var err error var nodes []pilorama.NodeInfo - for _, sh := range e.sortShardsByWeight(cid) { + for _, sh := range e.sortShards(cid) { nodes, err = sh.TreeGetChildren(ctx, cid, treeID, nodeID) if err != nil { if err == shard.ErrPiloramaDisabled { @@ -222,7 +222,7 @@ func (e *StorageEngine) TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID var err error var lm pilorama.Move - for _, sh := range e.sortShardsByWeight(cid) { + for _, sh := range e.sortShards(cid) { lm, err = sh.TreeGetOpLog(ctx, cid, treeID, height) if err != nil { if err == shard.ErrPiloramaDisabled { @@ -252,7 +252,7 @@ func (e *StorageEngine) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID stri defer span.End() var err error - for _, sh := range e.sortShardsByWeight(cid) { + for _, sh := range e.sortShards(cid) { err = sh.TreeDrop(ctx, cid, treeID) if err != nil { if err == shard.ErrPiloramaDisabled { @@ -375,7 +375,7 @@ func (e *StorageEngine) TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, t var err error var height uint64 - for _, sh := range e.sortShardsByWeight(cid) { + for _, sh := range e.sortShards(cid) { height, err = sh.TreeLastSyncHeight(ctx, cid, treeID) if err != nil { if err == shard.ErrPiloramaDisabled { @@ -395,7 +395,7 @@ func (e *StorageEngine) TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, t } func (e *StorageEngine) getTreeShard(ctx context.Context, cid cidSDK.ID, treeID string) (int, []hashedShard, error) { - lst := e.sortShardsByWeight(cid) + lst := e.sortShards(cid) for i, sh := range lst { exists, err := sh.TreeExists(ctx, cid, treeID) if err != nil { diff --git a/pkg/local_object_storage/shard/info.go b/pkg/local_object_storage/shard/info.go index a5b9c1a7d1..1051ab3db3 100644 --- a/pkg/local_object_storage/shard/info.go +++ b/pkg/local_object_storage/shard/info.go @@ -25,9 +25,6 @@ type Info struct { // Information about the Write Cache. WriteCacheInfo writecache.Info - // Weight parameters of the shard. - WeightValues WeightValues - // ErrorCount contains amount of errors occurred in shard operations. ErrorCount uint32 diff --git a/pkg/local_object_storage/shard/weight.go b/pkg/local_object_storage/shard/weight.go deleted file mode 100644 index 0ab5ad61dc..0000000000 --- a/pkg/local_object_storage/shard/weight.go +++ /dev/null @@ -1,12 +0,0 @@ -package shard - -// WeightValues groups values of Shard weight parameters. -type WeightValues struct { - // Amount of free disk space. Measured in kilobytes. - FreeSpace uint64 -} - -// WeightValues returns current weight values of the Shard. -func (s *Shard) WeightValues() WeightValues { - return s.info.WeightValues -} From 918613546f0812234869b4f6906bb74adbba9e15 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 26 Feb 2024 16:30:03 +0300 Subject: [PATCH 0405/1413] [#1008] metabase: Do not update storageID on put There may be a race condition between put an object and flushing the writecache: 1. Put object to the writecache 2. Writecache flushes object to the blobstore and sets blobstore's storageID 3. Put object to the metabase, set writecache's storageID Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/put.go | 20 +++++++------- .../metabase/storage_id.go | 13 +--------- .../metabase/storage_id_test.go | 26 +++++++++++++++++++ 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 5d8e4d2636..429d981fe3 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -137,7 +137,7 @@ func (db *DB) updateObj(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *obje // When storage engine moves objects between different sub-storages, // it calls metabase.Put method with new storage ID, thus triggering this code. if !isParent && id != nil { - return updateStorageID(tx, objectCore.AddressOf(obj), id) + return setStorageID(tx, objectCore.AddressOf(obj), id, true) } // when storage already has last object in split hierarchy and there is @@ -236,12 +236,7 @@ func putUniqueIndexes( // index storageID if it is present if id != nil { - err = putUniqueIndexItem(tx, namedBucketItem{ - name: smallBucketName(cnr, bucketName), - key: objKey, - val: id, - }) - if err != nil { + if err = setStorageID(tx, objectCore.AddressOf(obj), id, false); err != nil { return err } } @@ -483,16 +478,19 @@ func getVarUint(data []byte) (uint64, int, error) { } } -// updateStorageID for existing objects if they were moved from one +// setStorageID for existing objects if they were moved from one // storage location to another. -func updateStorageID(tx *bbolt.Tx, addr oid.Address, id []byte) error { +func setStorageID(tx *bbolt.Tx, addr oid.Address, id []byte, override bool) error { key := make([]byte, bucketKeySize) bkt, err := createBucketLikelyExists(tx, smallBucketName(addr.Container(), key)) if err != nil { return err } - - return bkt.Put(objectKey(addr.Object(), key), id) + key = objectKey(addr.Object(), key) + if override || bkt.Get(key) == nil { + return bkt.Put(key, id) + } + return nil } // updateSpliInfo for existing objects if storage filled with extra information diff --git a/pkg/local_object_storage/metabase/storage_id.go b/pkg/local_object_storage/metabase/storage_id.go index ef6b44dfd5..f9767935c3 100644 --- a/pkg/local_object_storage/metabase/storage_id.go +++ b/pkg/local_object_storage/metabase/storage_id.go @@ -3,11 +3,9 @@ package meta import ( "bytes" "context" - "errors" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -120,17 +118,8 @@ func (db *DB) UpdateStorageID(ctx context.Context, prm UpdateStorageIDPrm) (res return res, ErrReadOnlyMode } - currEpoch := db.epochState.CurrentEpoch() - err = db.boltDB.Batch(func(tx *bbolt.Tx) error { - exists, err := db.exists(tx, prm.addr, currEpoch) - if err == nil && exists { - err = updateStorageID(tx, prm.addr, prm.id) - } else if errors.As(err, new(logicerr.Logical)) { - err = updateStorageID(tx, prm.addr, prm.id) - } - - return err + return setStorageID(tx, prm.addr, prm.id, true) }) success = err == nil return res, metaerr.Wrap(err) diff --git a/pkg/local_object_storage/metabase/storage_id_test.go b/pkg/local_object_storage/metabase/storage_id_test.go index 063dfb2703..aaf6480ab7 100644 --- a/pkg/local_object_storage/metabase/storage_id_test.go +++ b/pkg/local_object_storage/metabase/storage_id_test.go @@ -75,6 +75,32 @@ func TestDB_StorageID(t *testing.T) { }) } +func TestPutWritecacheDataRace(t *testing.T) { + t.Parallel() + + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + putStorageID := []byte{1, 2, 3} + wcStorageID := []byte{1, 2, 3, 4, 5} + o := testutil.GenerateObject() + + fetchedStorageID, err := metaStorageID(db, object.AddressOf(o)) + require.NoError(t, err) + require.Nil(t, fetchedStorageID) + + // writecache flushes object and updates storageID before object actually saved to the metabase + metaUpdateStorageID(db, object.AddressOf(o), wcStorageID) + + // put object completes with writecache's storageID + err = metaPut(db, o, putStorageID) + require.NoError(t, err) + + fetchedStorageID, err = metaStorageID(db, object.AddressOf(o)) + require.NoError(t, err) + require.Equal(t, wcStorageID, fetchedStorageID) +} + func metaUpdateStorageID(db *meta.DB, addr oid.Address, id []byte) error { var sidPrm meta.UpdateStorageIDPrm sidPrm.SetAddress(addr) From 9801d084380f1a5be664ad97e527bce458c7291b Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 13 Feb 2024 14:56:25 +0300 Subject: [PATCH 0406/1413] [#932] adm: Move defaults for NNS to package `constants` Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/constants/const.go | 5 ++++- cmd/frostfs-adm/internal/modules/morph/contract/deploy.go | 6 ++++-- .../internal/modules/morph/helper/initialize_ctx.go | 6 ++++-- .../internal/modules/morph/initialize/initialize_nns.go | 3 ++- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/constants/const.go b/cmd/frostfs-adm/internal/modules/morph/constants/const.go index 5a7f8f922e..a3b4f129a5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/constants/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/constants/const.go @@ -28,7 +28,10 @@ const ( ContractWalletFilename = "contract.json" ContractWalletPasswordKey = "contract" - FrostfsOpsEmail = "ops@frostfs.info" + FrostfsOpsEmail = "ops@frostfs.info" + NNSRefreshDefVal = int64(3600) + NNSRetryDefVal = int64(600) + NNSTtlDefVal = int64(3600) DefaultExpirationTime = 10 * 365 * 24 * time.Hour / time.Second diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go index 9a92e8f19d..7a8f34a5d6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go @@ -148,12 +148,14 @@ func registerNNS(nnsCs *state.Contract, c *helper.InitializeContext, zone string emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, zone, c.CommitteeAcc.Contract.ScriptHash(), - constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, constants.NNSRefreshDefVal, constants.NNSRetryDefVal, + int64(constants.DefaultExpirationTime), constants.NNSTtlDefVal) emit.Opcodes(bw.BinWriter, opcode.ASSERT) emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, domain, c.CommitteeAcc.Contract.ScriptHash(), - constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, constants.NNSRefreshDefVal, constants.NNSRetryDefVal, + int64(constants.DefaultExpirationTime), constants.NNSTtlDefVal) emit.Opcodes(bw.BinWriter, opcode.ASSERT) } else { s, ok, err := c.NNSRegisterDomainScript(nnsCs.Hash, cs.Hash, domain) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go index 8269f19dc7..09d64b352a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go @@ -478,7 +478,8 @@ func (c *InitializeContext) EmitUpdateNNSGroupScript(bw *io.BufBinWriter, nnsHas if isAvail { emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, client.NNSGroupKeyName, c.CommitteeAcc.Contract.ScriptHash(), - constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, constants.NNSRefreshDefVal, constants.NNSRetryDefVal, + int64(constants.DefaultExpirationTime), constants.NNSTtlDefVal) emit.Opcodes(bw.BinWriter, opcode.ASSERT) } @@ -499,7 +500,8 @@ func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.U bw := io.NewBufBinWriter() emit.AppCall(bw.BinWriter, nnsHash, "register", callflag.All, domain, c.CommitteeAcc.Contract.ScriptHash(), - constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, constants.NNSRefreshDefVal, constants.NNSRetryDefVal, + int64(constants.DefaultExpirationTime), constants.NNSTtlDefVal) emit.Opcodes(bw.BinWriter, opcode.ASSERT) if bw.Err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go index 7a628d5a32..14f12cf8ee 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go @@ -33,7 +33,8 @@ func setNNS(c *helper.InitializeContext) error { bw := io.NewBufBinWriter() emit.AppCall(bw.BinWriter, nnsCs.Hash, "register", callflag.All, "frostfs", c.CommitteeAcc.Contract.ScriptHash(), - constants.FrostfsOpsEmail, int64(3600), int64(600), int64(constants.DefaultExpirationTime), int64(3600)) + constants.FrostfsOpsEmail, constants.NNSRefreshDefVal, constants.NNSRetryDefVal, + int64(constants.DefaultExpirationTime), constants.NNSTtlDefVal) emit.Opcodes(bw.BinWriter, opcode.ASSERT) if err := c.SendCommitteeTx(bw.Bytes(), true); err != nil { return fmt.Errorf("can't add domain root to NNS: %w", err) From 61c58e2f927af812473a772bcf1589375784f0d9 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 14 Feb 2024 08:58:43 +0300 Subject: [PATCH 0407/1413] [#932] adm: Add commands to manipulate with `NNS` contract Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/ape/ape_util.go | 10 +- .../modules/morph/helper/initialize.go | 12 ++ .../internal/modules/morph/nns/helper.go | 28 ++++ .../internal/modules/morph/nns/record.go | 148 ++++++++++++++++++ .../internal/modules/morph/nns/register.go | 44 ++++++ .../internal/modules/morph/nns/renew.go | 26 +++ .../internal/modules/morph/nns/root.go | 101 ++++++++++++ .../internal/modules/morph/nns/tokens.go | 24 +++ .../internal/modules/morph/nns/update.go | 50 ++++++ .../internal/modules/morph/root.go | 2 + 10 files changed, 436 insertions(+), 9 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/nns/helper.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/nns/record.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/nns/register.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/nns/renew.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/nns/root.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/nns/tokens.go create mode 100644 cmd/frostfs-adm/internal/modules/morph/nns/update.go diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index fe09776ede..dccd8909f2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -4,8 +4,6 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" @@ -91,13 +89,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *ac c, err := helper.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) - wallets, err := helper.GetAlphabetWallets(v, walletDir) - commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) - - committeeAcc, err := helper.GetWalletAccount(wallets[0], constants.CommitteeAccountName) - commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) - + committeeAcc := helper.GetComitteAcc(cmd, v) ac, err := helper.NewActor(c, committeeAcc) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go index 00c2fae6d5..961ceba536 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go @@ -7,7 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -101,6 +103,16 @@ func GetWalletAccount(w *wallet.Wallet, typ string) (*wallet.Account, error) { return nil, fmt.Errorf("account for '%s' not found", typ) } +func GetComitteAcc(cmd *cobra.Command, v *viper.Viper) *wallet.Account { + walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) + wallets, err := GetAlphabetWallets(v, walletDir) + commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) + + committeeAcc, err := GetWalletAccount(wallets[0], constants.CommitteeAccountName) + commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) + return committeeAcc +} + func NNSResolve(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (stackitem.Item, error) { return unwrap.Item(inv.Call(nnsHash, "resolve", domain, int64(nns.TXT))) } diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go new file mode 100644 index 0000000000..4c9c9e576f --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -0,0 +1,28 @@ +package nns + +import ( + client "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func getRPCClient(cmd *cobra.Command) (*client.Contract, *actor.Actor, util.Uint160) { + v := viper.GetViper() + c, err := helper.GetN3Client(v) + commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) + + committeeAcc := helper.GetComitteAcc(cmd, v) + ac, err := helper.NewActor(c, committeeAcc) + commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) + + inv := &ac.Invoker + r := management.NewReader(inv) + nnsCs, err := r.GetContractByID(1) + commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) + return client.New(ac, nnsCs.Hash), ac, nnsCs.Hash +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/record.go b/cmd/frostfs-adm/internal/modules/morph/nns/record.go new file mode 100644 index 0000000000..0e217eb616 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/nns/record.go @@ -0,0 +1,148 @@ +package nns + +import ( + "errors" + "math/big" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/spf13/cobra" +) + +func initAddRecordCmd() { + Cmd.AddCommand(addRecordCmd) + addRecordCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + addRecordCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + addRecordCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + addRecordCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) + addRecordCmd.Flags().String(nnsRecordDataFlag, "", nnsRecordDataFlagDesc) + + _ = cobra.MarkFlagRequired(addRecordCmd.Flags(), nnsNameFlag) + _ = cobra.MarkFlagRequired(addRecordCmd.Flags(), nnsRecordTypeFlag) + _ = cobra.MarkFlagRequired(addRecordCmd.Flags(), nnsRecordDataFlag) +} + +func initGetRecordsCmd() { + Cmd.AddCommand(getRecordsCmd) + getRecordsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + getRecordsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + getRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + getRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) + + _ = cobra.MarkFlagRequired(getRecordsCmd.Flags(), nnsNameFlag) +} + +func initDelRecordsCmd() { + Cmd.AddCommand(delRecordsCmd) + delRecordsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + delRecordsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + delRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + delRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) + + _ = cobra.MarkFlagRequired(delRecordsCmd.Flags(), nnsNameFlag) + _ = cobra.MarkFlagRequired(delRecordsCmd.Flags(), nnsRecordTypeFlag) +} + +func addRecord(cmd *cobra.Command, _ []string) { + c, actor, _ := getRPCClient(cmd) + name, _ := cmd.Flags().GetString(nnsNameFlag) + data, _ := cmd.Flags().GetString(nnsRecordDataFlag) + recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) + typ, err := getRecordType(recordType) + commonCmd.ExitOnErr(cmd, "unable to parse record type: %w", err) + h, vub, err := c.AddRecord(name, typ, data) + commonCmd.ExitOnErr(cmd, "unable to add record: %w", err) + + cmd.Println("Waiting for transaction to persist...") + _, err = actor.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "renew domain error: %w", err) + cmd.Println("Record added successfully") +} + +func getRecords(cmd *cobra.Command, _ []string) { + c, act, hash := getRPCClient(cmd) + name, _ := cmd.Flags().GetString(nnsNameFlag) + recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) + if recordType == "" { + sid, r, err := unwrap.SessionIterator(act.Invoker.Call(hash, "getAllRecords", name)) + commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) + defer func() { + _ = act.Invoker.TerminateSession(sid) + }() + items, err := act.Invoker.TraverseIterator(sid, &r, 0) + commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) + for len(items) != 0 { + for j := range items { + rs := items[j].Value().([]stackitem.Item) + bs, err := rs[2].TryBytes() + commonCmd.ExitOnErr(cmd, "unable to parse record state: %w", err) + cmd.Printf("%s %s\n", + recordTypeToString(nns.RecordType(rs[1].Value().(*big.Int).Int64())), + string(bs)) + } + items, err = act.Invoker.TraverseIterator(sid, &r, 0) + commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) + } + } else { + typ, err := getRecordType(recordType) + commonCmd.ExitOnErr(cmd, "unable to parse record type: %w", err) + items, err := c.GetRecords(name, typ) + commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) + for _, item := range items { + record, err := item.TryBytes() + commonCmd.ExitOnErr(cmd, "unable to parse response: %w", err) + cmd.Println(string(record)) + } + } +} + +func delRecords(cmd *cobra.Command, _ []string) { + c, actor, _ := getRPCClient(cmd) + name, _ := cmd.Flags().GetString(nnsNameFlag) + recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) + typ, err := getRecordType(recordType) + commonCmd.ExitOnErr(cmd, "unable to parse record type: %w", err) + h, vub, err := c.DeleteRecords(name, typ) + commonCmd.ExitOnErr(cmd, "unable to delete records: %w", err) + + cmd.Println("Waiting for transaction to persist...") + _, err = actor.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "delete records error: %w", err) + cmd.Println("Records removed successfully") +} + +func getRecordType(recordType string) (*big.Int, error) { + switch strings.ToUpper(recordType) { + case "A": + return big.NewInt(int64(nns.A)), nil + case "CNAME": + return big.NewInt(int64(nns.CNAME)), nil + case "SOA": + return big.NewInt(int64(nns.SOA)), nil + case "TXT": + return big.NewInt(int64(nns.TXT)), nil + case "AAAA": + return big.NewInt(int64(nns.AAAA)), nil + } + return nil, errors.New("unsupported record type") +} + +func recordTypeToString(rt nns.RecordType) string { + switch rt { + case nns.A: + return "A" + case nns.CNAME: + return "CNAME" + case nns.SOA: + return "SOA" + case nns.TXT: + return "TXT" + case nns.AAAA: + return "AAAA" + } + return "" +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/register.go b/cmd/frostfs-adm/internal/modules/morph/nns/register.go new file mode 100644 index 0000000000..d05d9f171a --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/nns/register.go @@ -0,0 +1,44 @@ +package nns + +import ( + "math/big" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/spf13/cobra" +) + +func initRegisterCmd() { + Cmd.AddCommand(registerCmd) + registerCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + registerCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + registerCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + registerCmd.Flags().String(nnsEmailFlag, constants.FrostfsOpsEmail, "Domain owner email") + registerCmd.Flags().Int64(nnsRefreshFlag, constants.NNSRefreshDefVal, "SOA record REFRESH parameter") + registerCmd.Flags().Int64(nnsRetryFlag, constants.NNSRetryDefVal, "SOA record RETRY parameter") + registerCmd.Flags().Int64(nnsExpireFlag, int64(constants.DefaultExpirationTime), "SOA record EXPIRE parameter") + registerCmd.Flags().Int64(nnsTTLFlag, constants.NNSTtlDefVal, "SOA record TTL parameter") + + _ = cobra.MarkFlagRequired(registerCmd.Flags(), nnsNameFlag) +} + +func registerDomain(cmd *cobra.Command, _ []string) { + c, actor, _ := getRPCClient(cmd) + + name, _ := cmd.Flags().GetString(nnsNameFlag) + email, _ := cmd.Flags().GetString(nnsEmailFlag) + refresh, _ := cmd.Flags().GetInt64(nnsRefreshFlag) + retry, _ := cmd.Flags().GetInt64(nnsRetryFlag) + expire, _ := cmd.Flags().GetInt64(nnsExpireFlag) + ttl, _ := cmd.Flags().GetInt64(nnsTTLFlag) + + h, vub, err := c.Register(name, actor.Sender(), email, big.NewInt(refresh), + big.NewInt(retry), big.NewInt(expire), big.NewInt(ttl)) + commonCmd.ExitOnErr(cmd, "unable to register domain: %w", err) + + cmd.Println("Waiting for transaction to persist...") + _, err = actor.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "register domain error: %w", err) + cmd.Println("Domain registered successfully") +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/renew.go b/cmd/frostfs-adm/internal/modules/morph/nns/renew.go new file mode 100644 index 0000000000..b13092240e --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/nns/renew.go @@ -0,0 +1,26 @@ +package nns + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/spf13/cobra" +) + +func initRenewCmd() { + Cmd.AddCommand(renewCmd) + renewCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + renewCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + renewCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) +} + +func renewDomain(cmd *cobra.Command, _ []string) { + c, actor, _ := getRPCClient(cmd) + name, _ := cmd.Flags().GetString(nnsNameFlag) + h, vub, err := c.Renew(name) + commonCmd.ExitOnErr(cmd, "unable to renew domain: %w", err) + + cmd.Println("Waiting for transaction to persist...") + _, err = actor.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "renew domain error: %w", err) + cmd.Println("Domain renewed successfully") +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/root.go b/cmd/frostfs-adm/internal/modules/morph/nns/root.go new file mode 100644 index 0000000000..09133f9329 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/nns/root.go @@ -0,0 +1,101 @@ +package nns + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + nnsNameFlag = "name" + nnsNameFlagDesc = "Domain name" + nnsEmailFlag = "email" + nnsRefreshFlag = "refresh" + nnsRetryFlag = "retry" + nnsExpireFlag = "expire" + nnsTTLFlag = "ttl" + nnsRecordTypeFlag = "type" + nnsRecordTypeFlagDesc = "Domain name service record type(A|CNAME|SOA|TXT)" + nnsRecordDataFlag = "data" + nnsRecordDataFlagDesc = "Domain name service record data" +) + +var ( + Cmd = &cobra.Command{ + Use: "nns", + Short: "Section for Neo Name Service (NNS)", + } + tokensCmd = &cobra.Command{ + Use: "tokens", + Short: "List all registered domain names", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: listTokens, + } + registerCmd = &cobra.Command{ + Use: "register", + Short: "Registers a new domain", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: registerDomain, + } + renewCmd = &cobra.Command{ + Use: "renew", + Short: "Increases domain expiration date", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: renewDomain, + } + updateCmd = &cobra.Command{ + Use: "update", + Short: "Updates soa record", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: updateSOA, + } + addRecordCmd = &cobra.Command{ + Use: "add-record", + Short: "Adds a new record of the specified type to the provided domain", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: addRecord, + } + getRecordsCmd = &cobra.Command{ + Use: "get-records", + Short: "Returns domain record of the specified type", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: getRecords, + } + delRecordsCmd = &cobra.Command{ + Use: "delete-records", + Short: "Removes domain records with the specified type", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: delRecords, + } +) + +func init() { + initTokensCmd() + initRegisterCmd() + initRenewCmd() + initUpdateCmd() + initAddRecordCmd() + initGetRecordsCmd() + initDelRecordsCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go b/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go new file mode 100644 index 0000000000..6e8ffb40a4 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go @@ -0,0 +1,24 @@ +package nns + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/spf13/cobra" +) + +func initTokensCmd() { + Cmd.AddCommand(tokensCmd) + tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + tokensCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) +} + +func listTokens(cmd *cobra.Command, _ []string) { + c, _, _ := getRPCClient(cmd) + it, err := c.Tokens() + commonCmd.ExitOnErr(cmd, "unable to get tokens: %w", err) + for toks, err := it.Next(10); err == nil && len(toks) > 0; toks, err = it.Next(10) { + for _, token := range toks { + cmd.Println(string(token)) + } + } +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/update.go b/cmd/frostfs-adm/internal/modules/morph/nns/update.go new file mode 100644 index 0000000000..3437316e36 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/nns/update.go @@ -0,0 +1,50 @@ +package nns + +import ( + "math/big" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/spf13/cobra" +) + +func initUpdateCmd() { + Cmd.AddCommand(updateCmd) + updateCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + updateCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + updateCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + updateCmd.Flags().String(nnsEmailFlag, constants.FrostfsOpsEmail, "Domain owner email") + updateCmd.Flags().Int64(nnsRefreshFlag, constants.NNSRefreshDefVal, + "The number of seconds between update requests from secondary and slave name servers") + updateCmd.Flags().Int64(nnsRetryFlag, constants.NNSRetryDefVal, + "The number of seconds the secondary or slave will wait before retrying when the last attempt has failed") + updateCmd.Flags().Int64(nnsExpireFlag, int64(constants.DefaultExpirationTime), + "The number of seconds a master or slave will wait before considering the data stale "+ + "if it cannot reach the primary name server") + updateCmd.Flags().Int64(nnsTTLFlag, constants.NNSTtlDefVal, + "The number of seconds a domain name is cached locally before expiration and return to authoritative "+ + "nameservers for updated information") + + _ = cobra.MarkFlagRequired(updateCmd.Flags(), nnsNameFlag) +} + +func updateSOA(cmd *cobra.Command, _ []string) { + c, actor, _ := getRPCClient(cmd) + + name, _ := cmd.Flags().GetString(nnsNameFlag) + email, _ := cmd.Flags().GetString(nnsEmailFlag) + refresh, _ := cmd.Flags().GetInt64(nnsRefreshFlag) + retry, _ := cmd.Flags().GetInt64(nnsRetryFlag) + expire, _ := cmd.Flags().GetInt64(nnsExpireFlag) + ttl, _ := cmd.Flags().GetInt64(nnsTTLFlag) + + h, vub, err := c.UpdateSOA(name, email, big.NewInt(refresh), + big.NewInt(retry), big.NewInt(expire), big.NewInt(ttl)) + commonCmd.ExitOnErr(cmd, "unable to send transaction: %w", err) + + cmd.Println("Waiting for transaction to persist...") + _, err = actor.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "register domain error: %w", err) + cmd.Println("SOA records updated successfully") +} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index 9d2b25cebe..e8426d56e7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/initialize" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/node" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" @@ -49,4 +50,5 @@ func init() { RootCmd.AddCommand(proxy.RemoveAccountCmd) RootCmd.AddCommand(frostfsid.Cmd) + RootCmd.AddCommand(nns.Cmd) } From bc9dbb26ec0ca191b2b41e3f71caf6dbd7563346 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 20 Feb 2024 11:36:36 +0300 Subject: [PATCH 0408/1413] [#932] adm: Add custom `Actor` to sign tx by all committee accounts Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/ape/ape_util.go | 14 +- .../internal/modules/morph/helper/actor.go | 169 ++++++++++++++++++ .../internal/modules/morph/nns/helper.go | 9 +- .../internal/modules/morph/nns/root.go | 2 - 4 files changed, 177 insertions(+), 17 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/helper/actor.go diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index dccd8909f2..3a990fe174 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -11,7 +11,6 @@ import ( apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/cobra" @@ -84,22 +83,19 @@ func parseChainName(cmd *cobra.Command) apechain.Name { return apeChainName } -func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *actor.Actor) { - v := viper.GetViper() - c, err := helper.GetN3Client(v) +func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *helper.LocalActor) { + c, err := helper.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - committeeAcc := helper.GetComitteAcc(cmd, v) - ac, err := helper.NewActor(c, committeeAcc) + ac, err := helper.NewLocalActor(cmd, c) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) - inv := &ac.Invoker var ch util.Uint160 - r := management.NewReader(inv) + r := management.NewReader(ac.Invoker) nnsCs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) + ch, err = helper.NNSResolveHash(ac.Invoker, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) return morph.NewContractStorage(ac, ch), ac diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go new file mode 100644 index 0000000000..f920aa5ba0 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go @@ -0,0 +1,169 @@ +package helper + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/context" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// LocalActor is a kludge, do not use it outside of the morph commands. +type LocalActor struct { + neoActor *actor.Actor + accounts []*wallet.Account + Invoker *invoker.Invoker +} + +// NewLocalActor create LocalActor with accounts form provided wallets. +// In case of empty wallets provided created actor with dummy account only for read operation. +func NewLocalActor(cmd *cobra.Command, c actor.RPCActor) (*LocalActor, error) { + walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) + var act *actor.Actor + var accounts []*wallet.Account + if walletDir == "" { + account, err := wallet.NewAccount() + commonCmd.ExitOnErr(cmd, "unable to create dummy account: %w", err) + act, err = actor.New(c, []actor.SignerAccount{{ + Signer: transaction.Signer{ + Account: account.Contract.ScriptHash(), + Scopes: transaction.Global, + }, + Account: account, + }}) + if err != nil { + return nil, err + } + } else { + wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir) + commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) + + for _, w := range wallets { + acc, err := GetWalletAccount(w, constants.CommitteeAccountName) + commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) + accounts = append(accounts, acc) + } + act, err = actor.New(c, []actor.SignerAccount{{ + Signer: transaction.Signer{ + Account: accounts[0].Contract.ScriptHash(), + Scopes: transaction.Global, + }, + Account: accounts[0], + }}) + if err != nil { + return nil, err + } + } + return &LocalActor{ + neoActor: act, + accounts: accounts, + Invoker: &act.Invoker, + }, nil +} + +func (a *LocalActor) SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) { + tx, err := a.neoActor.MakeCall(contract, method, params...) + if err != nil { + return util.Uint256{}, 0, err + } + err = a.resign(tx) + if err != nil { + return util.Uint256{}, 0, err + } + return a.neoActor.Send(tx) +} + +func (a *LocalActor) SendRun(script []byte) (util.Uint256, uint32, error) { + tx, err := a.neoActor.MakeRun(script) + if err != nil { + return util.Uint256{}, 0, err + } + err = a.resign(tx) + if err != nil { + return util.Uint256{}, 0, err + } + return a.neoActor.Send(tx) +} + +// resign is used to sign tx with committee accounts. +// Inside the methods `MakeCall` and `SendRun` of the NeoGO's actor transaction is signing by committee account, +// because actor uses committee wallet. +// But it is not enough, need to sign with another committee accounts. +func (a *LocalActor) resign(tx *transaction.Transaction) error { + if len(a.accounts[0].Contract.Parameters) > 1 { + // Use parameter context to avoid dealing with signature order. + network := a.neoActor.GetNetwork() + pc := context.NewParameterContext("", network, tx) + h := a.accounts[0].Contract.ScriptHash() + for _, acc := range a.accounts { + priv := acc.PrivateKey() + sign := priv.SignHashable(uint32(network), tx) + if err := pc.AddSignature(h, acc.Contract, priv.PublicKey(), sign); err != nil { + return fmt.Errorf("can't add signature: %w", err) + } + if len(pc.Items[h].Signatures) == len(acc.Contract.Parameters) { + break + } + } + + w, err := pc.GetWitness(h) + if err != nil { + return fmt.Errorf("incomplete signature: %w", err) + } + tx.Scripts[0] = *w + } + return nil +} + +func (a *LocalActor) Wait(h util.Uint256, vub uint32, err error) (*state.AppExecResult, error) { + return a.neoActor.Wait(h, vub, err) +} + +func (a *LocalActor) Sender() util.Uint160 { + return a.neoActor.Sender() +} + +func (a *LocalActor) Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) { + return a.neoActor.Call(contract, operation, params...) +} + +func (a *LocalActor) CallAndExpandIterator(_ util.Uint160, _ string, _ int, _ ...any) (*result.Invoke, error) { + panic("unimplemented") +} + +func (a *LocalActor) TerminateSession(_ uuid.UUID) error { + panic("unimplemented") +} + +func (a *LocalActor) TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) { + return a.neoActor.TraverseIterator(sessionID, iterator, num) +} + +func (a *LocalActor) MakeRun(_ []byte) (*transaction.Transaction, error) { + panic("unimplemented") +} + +func (a *LocalActor) MakeUnsignedCall(_ util.Uint160, _ string, _ []transaction.Attribute, _ ...any) (*transaction.Transaction, error) { + panic("unimplemented") +} + +func (a *LocalActor) MakeUnsignedRun(_ []byte, _ []transaction.Attribute) (*transaction.Transaction, error) { + panic("unimplemented") +} + +func (a *LocalActor) MakeCall(_ util.Uint160, _ string, _ ...any) (*transaction.Transaction, error) { + panic("unimplemented") +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index 4c9c9e576f..36c3dd2fd7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -4,24 +4,21 @@ import ( client "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) -func getRPCClient(cmd *cobra.Command) (*client.Contract, *actor.Actor, util.Uint160) { +func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, util.Uint160) { v := viper.GetViper() c, err := helper.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - committeeAcc := helper.GetComitteAcc(cmd, v) - ac, err := helper.NewActor(c, committeeAcc) + ac, err := helper.NewLocalActor(cmd, c) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) - inv := &ac.Invoker - r := management.NewReader(inv) + r := management.NewReader(ac.Invoker) nnsCs, err := r.GetContractByID(1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) return client.New(ac, nnsCs.Hash), ac, nnsCs.Hash diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/root.go b/cmd/frostfs-adm/internal/modules/morph/nns/root.go index 09133f9329..e528e4b7b0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/root.go @@ -30,7 +30,6 @@ var ( Short: "List all registered domain names", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: listTokens, } @@ -75,7 +74,6 @@ var ( Short: "Returns domain record of the specified type", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: getRecords, } From 7cc368e188dc03e761cad0801e7f269a81b1ed83 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 14 Feb 2024 14:14:07 +0300 Subject: [PATCH 0409/1413] [#986] object: Introduce soft ape checks * Soft APE check means that APE should allow request even it gets status NoRuleFound for a request. Otherwise, it is interpreted as Deny. * Soft APE check is performed if basic ACL mask is not set. Signed-off-by: Airat Arifullin --- pkg/services/object/acl/v2/request.go | 7 ++ pkg/services/object/acl/v2/service.go | 107 ++++++++++-------- pkg/services/object/ape/checker.go | 7 +- pkg/services/object/ape/checker_test.go | 18 +++ pkg/services/object/ape/service.go | 143 ++++++++++++++---------- pkg/services/object/request_context.go | 2 + 6 files changed, 176 insertions(+), 108 deletions(-) diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go index c58c00e0e1..74279e4530 100644 --- a/pkg/services/object/acl/v2/request.go +++ b/pkg/services/object/acl/v2/request.go @@ -104,6 +104,13 @@ func (r RequestInfo) RequestRole() acl.Role { return r.requestRole } +// IsSoftAPECheck states if APE should perform soft checks. +// Soft APE check allows a request if CheckAPE returns NoRuleFound for it, +// otherwise it denies the request. +func (r RequestInfo) IsSoftAPECheck() bool { + return r.BasicACL().Bits() != 0 +} + // MetaWithToken groups session and bearer tokens, // verification header and raw API request. type MetaWithToken struct { diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index af26a6fd18..b51386e0c8 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -113,9 +113,10 @@ type wrappedGetObjectStream struct { func (w *wrappedGetObjectStream) Context() context.Context { return context.WithValue(w.GetObjectStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), + Namespace: w.requestInfo.ContainerNamespace(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -136,9 +137,10 @@ type wrappedRangeStream struct { func (w *wrappedRangeStream) Context() context.Context { return context.WithValue(w.GetObjectRangeStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), + Namespace: w.requestInfo.ContainerNamespace(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -159,9 +161,10 @@ type wrappedSearchStream struct { func (w *wrappedSearchStream) Context() context.Context { return context.WithValue(w.SearchStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), + Namespace: w.requestInfo.ContainerNamespace(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -216,10 +219,12 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream reqInfo.obj = obj - if !b.checker.CheckBasicACL(reqInfo) { - return basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return eACLErr(reqInfo, err) + if reqInfo.IsSoftAPECheck() { + if !b.checker.CheckBasicACL(reqInfo) { + return basicACLErr(reqInfo) + } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { + return eACLErr(reqInfo, err) + } } return b.next.Get(request, &getStreamBasicChecker{ @@ -283,10 +288,12 @@ func (b Service) Head( reqInfo.obj = obj - if !b.checker.CheckBasicACL(reqInfo) { - return nil, basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) + if reqInfo.IsSoftAPECheck() { + if !b.checker.CheckBasicACL(reqInfo) { + return nil, basicACLErr(reqInfo) + } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { + return nil, eACLErr(reqInfo, err) + } } resp, err := b.next.Head(requestContext(ctx, reqInfo), request) @@ -334,10 +341,12 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr return err } - if !b.checker.CheckBasicACL(reqInfo) { - return basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return eACLErr(reqInfo, err) + if reqInfo.IsSoftAPECheck() { + if !b.checker.CheckBasicACL(reqInfo) { + return basicACLErr(reqInfo) + } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { + return eACLErr(reqInfo, err) + } } return b.next.Search(request, &searchStreamBasicChecker{ @@ -392,10 +401,12 @@ func (b Service) Delete( reqInfo.obj = obj - if !b.checker.CheckBasicACL(reqInfo) { - return nil, basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) + if reqInfo.IsSoftAPECheck() { + if !b.checker.CheckBasicACL(reqInfo) { + return nil, basicACLErr(reqInfo) + } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { + return nil, eACLErr(reqInfo, err) + } } return b.next.Delete(requestContext(ctx, reqInfo), request) @@ -443,10 +454,12 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb reqInfo.obj = obj - if !b.checker.CheckBasicACL(reqInfo) { - return basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return eACLErr(reqInfo, err) + if reqInfo.IsSoftAPECheck() { + if !b.checker.CheckBasicACL(reqInfo) { + return basicACLErr(reqInfo) + } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { + return eACLErr(reqInfo, err) + } } return b.next.GetRange(request, &rangeStreamBasicChecker{ @@ -458,9 +471,10 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { return context.WithValue(ctx, object.RequestContextKey, &object.RequestContext{ - Namespace: reqInfo.ContainerNamespace(), - SenderKey: reqInfo.SenderKey(), - Role: reqInfo.RequestRole(), + Namespace: reqInfo.ContainerNamespace(), + SenderKey: reqInfo.SenderKey(), + Role: reqInfo.RequestRole(), + SoftAPECheck: reqInfo.IsSoftAPECheck(), }) } @@ -509,10 +523,12 @@ func (b Service) GetRangeHash( reqInfo.obj = obj - if !b.checker.CheckBasicACL(reqInfo) { - return nil, basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) + if reqInfo.IsSoftAPECheck() { + if !b.checker.CheckBasicACL(reqInfo) { + return nil, basicACLErr(reqInfo) + } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { + return nil, eACLErr(reqInfo, err) + } } return b.next.GetRangeHash(requestContext(ctx, reqInfo), request) @@ -566,12 +582,13 @@ func (b Service) PutSingle(ctx context.Context, request *objectV2.PutSingleReque reqInfo.obj = obj - if !b.checker.CheckBasicACL(reqInfo) || !b.checker.StickyBitCheck(reqInfo, idOwner) { - return nil, basicACLErr(reqInfo) - } - - if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) + if reqInfo.IsSoftAPECheck() { + if !b.checker.CheckBasicACL(reqInfo) || !b.checker.StickyBitCheck(reqInfo, idOwner) { + return nil, basicACLErr(reqInfo) + } + if err := b.checker.CheckEACL(request, reqInfo); err != nil { + return nil, eACLErr(reqInfo, err) + } } return b.next.PutSingle(requestContext(ctx, reqInfo), request) @@ -639,8 +656,10 @@ func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRe reqInfo.obj = obj - if !p.source.checker.CheckBasicACL(reqInfo) || !p.source.checker.StickyBitCheck(reqInfo, idOwner) { - return basicACLErr(reqInfo) + if reqInfo.IsSoftAPECheck() { + if !p.source.checker.CheckBasicACL(reqInfo) || !p.source.checker.StickyBitCheck(reqInfo, idOwner) { + return basicACLErr(reqInfo) + } } ctx = requestContext(ctx, reqInfo) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 76ada3d2ba..13b2729e91 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -45,6 +45,9 @@ type Prm struct { // An encoded sender's public key string. SenderKey string + + // If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow. + SoftAPECheck bool } var errMissingOID = fmt.Errorf("object ID is not set") @@ -63,9 +66,9 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { return err } - if !ruleFound || status == apechain.Allow { + if !ruleFound && prm.SoftAPECheck || status == apechain.Allow { return nil } - return fmt.Errorf("found denying rule for %s: %s", prm.Method, status) + return fmt.Errorf("method %s: %s", prm.Method, status) } diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 08d0979071..d7e97064b4 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -165,11 +165,29 @@ func TestAPECheck(t *testing.T) { container: containerID, object: stringPtr(objectID), methods: methodsRequiredOID, + containerRules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + }, + }, }, { name: "oid optional requests are allowed", container: containerID, methods: methodsOptionalOID, + containerRules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{Names: methodsOptionalOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + }, + }, }, { name: "oid required requests are denied", diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 781f9df4b6..f05bdaa835 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -60,9 +60,13 @@ type getStreamBasicChecker struct { apeChecker Checker + namespace string + senderKey []byte role string + + softAPECheck bool } func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { @@ -73,12 +77,14 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { } prm := Prm{ - Container: cnrID, - Object: objID, - Header: partInit.GetHeader(), - Method: nativeschema.MethodGetObject, - SenderKey: hex.EncodeToString(g.senderKey), - Role: g.role, + Namespace: g.namespace, + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodGetObject, + SenderKey: hex.EncodeToString(g.senderKey), + Role: g.role, + SoftAPECheck: g.softAPECheck, } if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { @@ -112,12 +118,13 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodGetObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodGetObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -126,6 +133,10 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt return c.next.Get(request, &getStreamBasicChecker{ GetObjectStream: stream, apeChecker: c.apeChecker, + namespace: reqCtx.Namespace, + senderKey: reqCtx.SenderKey, + role: nativeSchemaRole(reqCtx.Role), + softAPECheck: reqCtx.SoftAPECheck, }) } @@ -148,13 +159,14 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: partInit.GetHeader(), - Method: nativeschema.MethodPutObject, - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - Role: nativeSchemaRole(reqCtx.Role), + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodPutObject, + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Role: nativeSchemaRole(reqCtx.Role), + SoftAPECheck: reqCtx.SoftAPECheck, } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -190,12 +202,13 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, err @@ -226,13 +239,14 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: header, - Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: header, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, err @@ -254,11 +268,12 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Method: nativeschema.MethodSearchObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Namespace: reqCtx.Namespace, + Container: cnrID, + Method: nativeschema.MethodSearchObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -279,12 +294,13 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodDeleteObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodDeleteObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, err @@ -310,12 +326,13 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodRangeObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodRangeObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -336,12 +353,13 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodHashObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHashObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + SoftAPECheck: reqCtx.SoftAPECheck, } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -371,13 +389,14 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: request.GetBody().GetObject().GetHeader(), - Method: nativeschema.MethodPutObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: request.GetBody().GetObject().GetHeader(), + Method: nativeschema.MethodPutObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + SoftAPECheck: reqCtx.SoftAPECheck, } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { diff --git a/pkg/services/object/request_context.go b/pkg/services/object/request_context.go index 4b9aa04d16..e0e6c9ed97 100644 --- a/pkg/services/object/request_context.go +++ b/pkg/services/object/request_context.go @@ -13,4 +13,6 @@ type RequestContext struct { SenderKey []byte Role acl.Role + + SoftAPECheck bool } From b1d171c261a644f538299cbd7a544683e6a4dfe7 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 14 Feb 2024 18:14:06 +0300 Subject: [PATCH 0410/1413] [#986] container: Interpret APE NoRuleFound as request deny * If APE check returns NoRuleFound, then it is taken for request deny. * Add more unit-test for ape container middleware. Signed-off-by: Airat Arifullin --- pkg/services/container/ape.go | 8 +- pkg/services/container/ape_test.go | 155 +++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 4 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index d1b490bdf0..c01ad8a1d4 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -162,7 +162,7 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co return nil, err } - if !found || s == apechain.Allow { + if found && s == apechain.Allow { return ac.next.List(ctx, req) } @@ -207,7 +207,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont return nil, err } - if !found || s == apechain.Allow { + if found && s == apechain.Allow { return ac.next.Put(ctx, req) } @@ -296,13 +296,13 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai } s, found, err := ac.router.IsAllowed(apechain.Ingress, - policyengine.NewRequestTarget(cntNamespace, id.EncodeToString()), + policyengine.NewRequestTarget(namespace, id.EncodeToString()), request) if err != nil { return err } - if !found || s == apechain.Allow { + if found && s == apechain.Allow { return nil } diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index daaacb0319..1af59d1c60 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -39,6 +39,8 @@ const ( func TestAPE(t *testing.T) { t.Parallel() + t.Run("allow then deny get container", testAllowThenDenyGetContainerRuleDefined) + t.Run("deny get container no rule found", testDenyGetContainerNoRuleFound) t.Run("deny get container for others", testDenyGetContainerForOthers) t.Run("deny set container eACL for IR", testDenySetContainerEACLForIR) t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken) @@ -49,6 +51,130 @@ func TestAPE(t *testing.T) { t.Run("deny list containers by namespace invalidation", testDenyListContainersValidationNamespaceError) } +func testAllowThenDenyGetContainerRuleDefined(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{}, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + addDefaultAllowGetPolicy(t, router, contID) + + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + _, err = apeSrv.Get(context.Background(), req) + require.NoError(t, err) + + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + }, + }, + }) + require.NoError(t, err) + + resp, err := apeSrv.Get(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) + require.Contains(t, errAccessDenied.Reason(), chain.AccessDenied.String()) +} + +func testDenyGetContainerNoRuleFound(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{}, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + resp, err := apeSrv.Get(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) + require.Contains(t, errAccessDenied.Reason(), chain.NoRuleFound.String()) +} + func testDenyGetContainerForOthers(t *testing.T) { t.Parallel() srv := &srvStub{ @@ -854,6 +980,8 @@ func TestValidateContainerBoundedOperation(t *testing.T) { }) require.NoError(t, err) + addDefaultAllowGetPolicy(t, components.engine, contID) + req := initTestGetContainerRequest(t, contID) err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) @@ -895,6 +1023,8 @@ func TestValidateContainerBoundedOperation(t *testing.T) { }) require.NoError(t, err) + addDefaultAllowGetPolicy(t, components.engine, contID) + req := initTestGetContainerRequest(t, contID) err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) @@ -936,6 +1066,8 @@ func TestValidateContainerBoundedOperation(t *testing.T) { }) require.NoError(t, err) + addDefaultAllowGetPolicy(t, components.engine, contID) + req := initTestGetContainerRequest(t, contID) err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) @@ -977,6 +1109,8 @@ func TestValidateContainerBoundedOperation(t *testing.T) { }) require.NoError(t, err) + addDefaultAllowGetPolicy(t, components.engine, contID) + req := initTestGetContainerRequest(t, contID) err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) @@ -1128,3 +1262,24 @@ func initListRequest(t *testing.T, actorPK *keys.PrivateKey, ownerPK *keys.Priva require.NoError(t, signature.SignServiceMessage(&actorPK.PrivateKey, req)) return req } + +func addDefaultAllowGetPolicy(t *testing.T, e engine.Engine, contID cid.ID) { + _, _, err := e.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + nativeschema.ResourceFormatAllContainers, + }, + }, + }, + }, + }) + require.NoError(t, err) +} From 75a1a95c2caefb12c91ce08a0b1ea5d5d992af6b Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 15 Feb 2024 13:59:52 +0300 Subject: [PATCH 0411/1413] [#986] tree: Skip ACL checks if basicACL mask is unset Signed-off-by: Airat Arifullin --- pkg/services/tree/signature.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 15067d3cd4..985e1ad94a 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -77,6 +77,11 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op } basicACL := cnr.Value.BasicACL() + // Basic ACL mask can be unset, if a container operations are performed + // with strict APE checks only. + if basicACL == 0x0 { + return nil + } if !basicACL.IsOpAllowed(op, role) { return basicACLErr(op) From 93bf9acbc2e0d2572a9f47299bbd3ea408d6d004 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 27 Feb 2024 12:27:09 +0300 Subject: [PATCH 0412/1413] [#898] control: Remove removed flag from RemoveChainLocalOverrideResponse * Remove removed flag in service.proto for RemoveChainLocalOverrideResponse. * Regenerate control API. * Return error only if RemoveOverride returns non-NotFound code. Signed-off-by: Airat Arifullin --- .../modules/control/remove_rule.go | 6 +- pkg/services/control/server/policy_engine.go | 10 +- pkg/services/control/service.pb.go | 321 +++++++++--------- pkg/services/control/service.proto | 1 - pkg/services/control/service_frostfs.pb.go | 9 - 5 files changed, 158 insertions(+), 189 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index 1c3be375f9..7684ac1dc7 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -57,11 +57,7 @@ func removeRule(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) - if resp.GetBody().GetRemoved() { - cmd.Println("Rule has been removed.") - } else { - cmd.Println("Rule has not been removed.") - } + cmd.Println("Rule has been removed.") } func initControlRemoveRuleCmd() { diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 079b605ac5..4ea863f79e 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -159,19 +159,13 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return nil, err } - removed := true if err = s.localOverrideStorage.LocalStorage().RemoveOverride(apechain.Ingress, target, apechain.ID(req.GetBody().GetChainId())); err != nil { - code := getCodeByLocalStorageErr(err) - if code == codes.NotFound { - removed = false - } else { + if code := getCodeByLocalStorageErr(err); code != codes.NotFound { return nil, status.Error(code, err.Error()) } } resp := &control.RemoveChainLocalOverrideResponse{ - Body: &control.RemoveChainLocalOverrideResponse_Body{ - Removed: removed, - }, + Body: &control.RemoveChainLocalOverrideResponse_Body{}, } err = SignMessage(s.key, resp) if err != nil { diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 4e95ac6173..c24bc15972 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -4086,8 +4086,6 @@ type RemoveChainLocalOverrideResponse_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - Removed bool `protobuf:"varint,1,opt,name=removed,proto3" json:"removed,omitempty"` } func (x *RemoveChainLocalOverrideResponse_Body) Reset() { @@ -4122,13 +4120,6 @@ func (*RemoveChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} } -func (x *RemoveChainLocalOverrideResponse_Body) GetRemoved() bool { - if x != nil { - return x.Removed - } - return false -} - // Request body structure. type SealWriteCacheRequest_Body struct { state protoimpl.MessageState @@ -4816,7 +4807,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, - 0x64, 0x22, 0xba, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x64, 0x22, 0xa0, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, @@ -4825,172 +4816,170 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x20, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x22, 0xca, - 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, - 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, - 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, + 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, - 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, + 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, - 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, - 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, + 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, + 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, + 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, + 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, + 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb1, 0x0d, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, - 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, - 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, - 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, - 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, - 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, + 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, + 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb1, 0x0d, 0x0a, + 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, + 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, + 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, + 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, - 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, - 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, + 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, + 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, + 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, - 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, - 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, - 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, - 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, + 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, + 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, + 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, + 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, + 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, + 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, + 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, + 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, + 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 16e0f707d7..1377965e65 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -566,7 +566,6 @@ message RemoveChainLocalOverrideRequest { message RemoveChainLocalOverrideResponse { message Body { - bool removed = 1; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 37527aa8c7..56b2bd54c8 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2861,7 +2861,6 @@ func (x *RemoveChainLocalOverrideResponse_Body) StableSize() (size int) { if x == nil { return 0 } - size += proto.BoolSize(1, x.Removed) return size } @@ -2874,14 +2873,6 @@ func (x *RemoveChainLocalOverrideResponse_Body) StableSize() (size int) { // // Structures with the same field values have the same binary format. func (x *RemoveChainLocalOverrideResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BoolMarshal(1, buf[offset:], x.Removed) return buf } From 6f25c790aa20a43949fe64cf90d8fe79b437d9b6 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 29 Feb 2024 14:22:10 +0300 Subject: [PATCH 0413/1413] [#1012] cli: Fix messages for list commands Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/list_rules.go | 5 +++-- cmd/frostfs-cli/modules/control/list_targets.go | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index 31f5ff959f..4598320d77 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -69,9 +69,10 @@ func parseTarget(cmd *cobra.Command) *control.ChainTarget { func listRules(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) + target := parseTarget(cmd) req := &control.ListChainLocalOverridesRequest{ Body: &control.ListChainLocalOverridesRequest_Body{ - Target: parseTarget(cmd), + Target: target, }, } @@ -91,7 +92,7 @@ func listRules(cmd *cobra.Command, _ []string) { chains := resp.GetBody().GetChains() if len(chains) == 0 { - cmd.Println("Local overrides are not defined for the container.") + cmd.Printf("Local overrides are not defined for the %s.\n", strings.ToLower(target.GetType().String())) return } diff --git a/cmd/frostfs-cli/modules/control/list_targets.go b/cmd/frostfs-cli/modules/control/list_targets.go index 29033d0176..ddd80b31b9 100644 --- a/cmd/frostfs-cli/modules/control/list_targets.go +++ b/cmd/frostfs-cli/modules/control/list_targets.go @@ -58,7 +58,7 @@ func listTargets(cmd *cobra.Command, _ []string) { targets := resp.GetBody().GetTargets() if len(targets) == 0 { - cmd.Println("Local overrides are not defined for the container.") + cmd.Println("Local overrides are not defined for any target.") return } From 6dbb61caf4f9b99176dc0351cf42c9ed3b3a1db0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 1 Mar 2024 11:44:03 +0300 Subject: [PATCH 0414/1413] [#1016] Makefile: Add gopls check target Signed-off-by: Dmitrii Stepanov --- Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Makefile b/Makefile index 4ff42b7e44..14738272ee 100755 --- a/Makefile +++ b/Makefile @@ -44,6 +44,10 @@ PROTOGEN_FROSTFS_DIR ?= $(PROTOBUF_DIR)/protogen-$(PROTOGEN_FROSTFS_VERSION) STATICCHECK_DIR ?= $(abspath $(BIN))/staticcheck STATICCHECK_VERSION_DIR ?= $(STATICCHECK_DIR)/$(STATICCHECK_VERSION) +GOPLS_VERSION ?= v0.15.1 +GOPLS_DIR ?= $(abspath $(BIN))/gopls +GOPLS_VERSION_DIR ?= $(GOPLS_DIR)/$(GOPLS_VERSION) + FROSTFS_CONTRACTS_PATH=$(abspath ./../frostfs-contract) LOCODE_DB_PATH=$(abspath ./.cache/locode_db) LOCODE_DB_VERSION=v0.4.0 @@ -201,6 +205,19 @@ staticcheck-run: fi @$(STATICCHECK_VERSION_DIR)/staticcheck ./... +gopls-install: + @rm -rf $(GOPLS_DIR) + @mkdir $(GOPLS_DIR) + @GOBIN=$(GOPLS_VERSION_DIR) go install golang.org/x/tools/gopls@$(GOPLS_VERSION) + +gopls-run: + @if [ ! -d "$(GOPLS_VERSION_DIR)" ]; then \ + make gopls-install; \ + fi + @if [[ $$(find . -type f -name "*.go" -print | xargs $(GOPLS_VERSION_DIR)/gopls check | tee /dev/tty | wc -l) -ne 0 ]]; then \ + exit 1; \ + fi + # Run linters in Docker docker/lint: docker run --rm -t \ From d6534fd755c22fd23ed471e2440d95d640903f98 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 1 Mar 2024 11:58:17 +0300 Subject: [PATCH 0415/1413] [#1016] frostfs-node: Fix gopls issues Signed-off-by: Dmitrii Stepanov --- .../morph/initialize/initialize_test.go | 6 ++--- cmd/frostfs-node/cache_test.go | 2 +- cmd/frostfs-node/config/morph/config_test.go | 10 +++++++-- internal/ape/converter_test.go | 22 +++++++++---------- pkg/innerring/initialization.go | 5 ----- .../blobstor/blobovniczatree/cache.go | 2 +- .../engine/delete_test.go | 8 +++---- .../engine/engine_test.go | 12 +++++----- pkg/local_object_storage/engine/head_test.go | 4 ++-- .../engine/inhume_test.go | 4 ++-- pkg/local_object_storage/metabase/put_test.go | 6 ++--- pkg/services/object/ape/checker_test.go | 4 ++-- pkg/services/object/ape/request_test.go | 4 ++-- .../placement/traverser_test.go | 12 +++++----- pkg/services/tree/cache.go | 2 +- pkg/services/tree/sync.go | 2 +- 16 files changed, 53 insertions(+), 52 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go index e39c7356f2..6c52aa2ab4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go @@ -53,7 +53,7 @@ func TestInitialize(t *testing.T) { testInitialize(t, constants.MaxAlphabetNodes) }) t.Run("too many nodes", func(t *testing.T) { - require.ErrorIs(t, generateTestData(t, t.TempDir(), constants.MaxAlphabetNodes+1), helper.ErrTooManyAlphabetNodes) + require.ErrorIs(t, generateTestData(t.TempDir(), constants.MaxAlphabetNodes+1), helper.ErrTooManyAlphabetNodes) }) } @@ -61,7 +61,7 @@ func testInitialize(t *testing.T, committeeSize int) { testdataDir := t.TempDir() v := viper.GetViper() - require.NoError(t, generateTestData(t, testdataDir, committeeSize)) + require.NoError(t, generateTestData(testdataDir, committeeSize)) v.Set(constants.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) // Set to the path or remove the next statement to download from the network. @@ -98,7 +98,7 @@ func testInitialize(t *testing.T, committeeSize int) { }) } -func generateTestData(t *testing.T, dir string, size int) error { +func generateTestData(dir string, size int) error { v := viper.GetViper() v.Set(commonflags.AlphabetWalletsFlag, dir) diff --git a/cmd/frostfs-node/cache_test.go b/cmd/frostfs-node/cache_test.go index 6e076abfc8..6981ac7213 100644 --- a/cmd/frostfs-node/cache_test.go +++ b/cmd/frostfs-node/cache_test.go @@ -10,7 +10,7 @@ import ( func TestTTLNetCache(t *testing.T) { ttlDuration := time.Millisecond * 50 - cache := newNetworkTTLCache[string, time.Time](10, ttlDuration, testNetValueReader) + cache := newNetworkTTLCache(10, ttlDuration, testNetValueReader) key := "key" diff --git a/cmd/frostfs-node/config/morph/config_test.go b/cmd/frostfs-node/config/morph/config_test.go index 192140446e..a30733cd04 100644 --- a/cmd/frostfs-node/config/morph/config_test.go +++ b/cmd/frostfs-node/config/morph/config_test.go @@ -24,8 +24,14 @@ func TestMorphSection(t *testing.T) { const path = "../../../../config/example/node" rpcs := []client.Endpoint{ - {"wss://rpc1.morph.frostfs.info:40341/ws", 1}, - {"wss://rpc2.morph.frostfs.info:40341/ws", 2}, + { + Address: "wss://rpc1.morph.frostfs.info:40341/ws", + Priority: 1, + }, + { + Address: "wss://rpc2.morph.frostfs.info:40341/ws", + Priority: 2, + }, } fileConfigTest := func(c *config.Config) { diff --git a/internal/ape/converter_test.go b/internal/ape/converter_test.go index de72408b1a..b5f8939c41 100644 --- a/internal/ape/converter_test.go +++ b/internal/ape/converter_test.go @@ -27,7 +27,7 @@ func TestEACLTableWithoutRecords(t *testing.T) { res: &testResource{name: nativeschema.ResourceFormatRootObjects}, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) cnrID := cidtest.ID() tb.SetCID(cnrID) @@ -37,7 +37,7 @@ func TestEACLTableWithoutRecords(t *testing.T) { ch, err = ConvertEACLToAPE(tb) require.NoError(t, err) - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } func TestNoTargets(t *testing.T) { @@ -69,7 +69,7 @@ func TestNoTargets(t *testing.T) { }, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } } @@ -109,7 +109,7 @@ func TestNoFilters(t *testing.T) { }, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } }) @@ -155,7 +155,7 @@ func TestNoFilters(t *testing.T) { }, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } }) @@ -199,7 +199,7 @@ func TestNoFilters(t *testing.T) { }, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } }) @@ -236,7 +236,7 @@ func TestNoFilters(t *testing.T) { }, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } }) } @@ -292,7 +292,7 @@ func TestWithFilters(t *testing.T) { }, }, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } }) @@ -342,7 +342,7 @@ func TestWithFilters(t *testing.T) { name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()), }, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } }) } @@ -391,10 +391,10 @@ func TestNoHeader(t *testing.T) { name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()), }, } - compare(t, tb, vu, ch, req) + compare(t, vu, ch, req) } -func compare(t *testing.T, eaclTable *eacl.Table, vu *eacl.ValidationUnit, ch *apechain.Chain, req *testRequest) { +func compare(t *testing.T, vu *eacl.ValidationUnit, ch *apechain.Chain, req *testRequest) { validator := eacl.NewValidator() for eaclOp, apeOp := range eaclOperationToEngineAction { vu.WithOperation(eaclOp) diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index f4d9b41696..1a41742893 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -42,10 +42,6 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper, return err } - if err != nil { - return err - } - netSettings := (*networkSettings)(s.netmapClient) var netMapCandidateStateValidator statevalidation.NetMapCandidateValidator @@ -76,7 +72,6 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper, NodeStateSettings: netSettings, }) - if err != nil { return err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index d8fe6e8b0f..ef1793edfe 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -24,7 +24,7 @@ type dbCache struct { } func newDBCache(size int, ttl time.Duration, dbManager *dbManager) *dbCache { - cache := expirable.NewLRU[string, *sharedDB](size, func(_ string, evictedDB *sharedDB) { + cache := expirable.NewLRU(size, func(_ string, evictedDB *sharedDB) { evictedDB.Close() }, ttl) return &dbCache{ diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 32d07809a4..4a6758012d 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -49,9 +49,9 @@ func TestDeleteBigObject(t *testing.T) { link.SetSplitID(splitID) link.SetChildren(childIDs...) - s1 := testNewShard(t, 1) - s2 := testNewShard(t, 2) - s3 := testNewShard(t, 3) + s1 := testNewShard(t) + s2 := testNewShard(t) + s3 := testNewShard(t) e := testNewEngine(t).setInitializedShards(t, s1, s2, s3).engine e.log = test.NewLogger(t) @@ -119,7 +119,7 @@ func TestDeleteBigObjectWithoutGC(t *testing.T) { link.SetSplitID(splitID) link.SetChildren(childIDs...) - s1 := testNewShard(t, 1, shard.WithDisabledGC()) + s1 := testNewShard(t, shard.WithDisabledGC()) e := testNewEngine(t).setInitializedShards(t, s1).engine e.log = test.NewLogger(t) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index b20f45be50..b6858df493 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -50,7 +50,7 @@ func BenchmarkExists(b *testing.B) { func benchmarkExists(b *testing.B, shardNum int) { shards := make([]*shard.Shard, shardNum) for i := 0; i < shardNum; i++ { - shards[i] = testNewShard(b, i) + shards[i] = testNewShard(b) } e := testNewEngine(b).setInitializedShards(b, shards...).engine @@ -112,7 +112,7 @@ func (te *testEngineWrapper) setShardsNum(t testing.TB, num int) *testEngineWrap shards := make([]*shard.Shard, 0, num) for i := 0; i < num; i++ { - shards = append(shards, testNewShard(t, i)) + shards = append(shards, testNewShard(t)) } return te.setInitializedShards(t, shards...) @@ -130,7 +130,7 @@ func (te *testEngineWrapper) setShardsNumOpts(t testing.TB, num int, shardOpts f func (te *testEngineWrapper) setShardsNumAdditionalOpts(t testing.TB, num int, shardOpts func(id int) []shard.Option) *testEngineWrapper { for i := 0; i < num; i++ { - defaultOpts := testDefaultShardOptions(t, i) + defaultOpts := testDefaultShardOptions(t) opts := append(defaultOpts, shardOpts(i)...) id, err := te.engine.AddShard(context.Background(), opts...) require.NoError(t, err) @@ -187,11 +187,11 @@ func newTestStorages(root string, smallSize uint64) ([]blobstor.SubStorage, *tes }, smallFileStorage, largeFileStorage } -func testNewShard(t testing.TB, id int, opts ...shard.Option) *shard.Shard { +func testNewShard(t testing.TB, opts ...shard.Option) *shard.Shard { sid, err := generateShardID() require.NoError(t, err) - shardOpts := append([]shard.Option{shard.WithID(sid)}, testDefaultShardOptions(t, id)...) + shardOpts := append([]shard.Option{shard.WithID(sid)}, testDefaultShardOptions(t)...) s := shard.New(append(shardOpts, opts...)...) require.NoError(t, s.Open(context.Background())) @@ -200,7 +200,7 @@ func testNewShard(t testing.TB, id int, opts ...shard.Option) *shard.Shard { return s } -func testDefaultShardOptions(t testing.TB, id int) []shard.Option { +func testDefaultShardOptions(t testing.TB) []shard.Option { return []shard.Option{ shard.WithLogger(test.NewLogger(t)), shard.WithBlobStorOptions( diff --git a/pkg/local_object_storage/engine/head_test.go b/pkg/local_object_storage/engine/head_test.go index 5c123d6178..5afc50f078 100644 --- a/pkg/local_object_storage/engine/head_test.go +++ b/pkg/local_object_storage/engine/head_test.go @@ -39,8 +39,8 @@ func TestHeadRaw(t *testing.T) { link.SetSplitID(splitID) t.Run("virtual object split in different shards", func(t *testing.T) { - s1 := testNewShard(t, 1) - s2 := testNewShard(t, 2) + s1 := testNewShard(t) + s2 := testNewShard(t) e := testNewEngine(t).setInitializedShards(t, s1, s2).engine defer e.Close(context.Background()) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 4bb128bd7e..9daa113f8e 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -56,8 +56,8 @@ func TestStorageEngine_Inhume(t *testing.T) { t.Run("delete big object", func(t *testing.T) { t.Parallel() - s1 := testNewShard(t, 1) - s2 := testNewShard(t, 2) + s1 := testNewShard(t) + s2 := testNewShard(t) e := testNewEngine(t).setInitializedShards(t, s1, s2).engine defer e.Close(context.Background()) diff --git a/pkg/local_object_storage/metabase/put_test.go b/pkg/local_object_storage/metabase/put_test.go index 28467199db..84e4029f28 100644 --- a/pkg/local_object_storage/metabase/put_test.go +++ b/pkg/local_object_storage/metabase/put_test.go @@ -18,7 +18,7 @@ import ( "github.com/stretchr/testify/require" ) -func prepareObjects(t testing.TB, n int) []*objectSDK.Object { +func prepareObjects(n int) []*objectSDK.Object { cnr := cidtest.ID() parentID := objecttest.ID() objs := make([]*objectSDK.Object, n) @@ -53,7 +53,7 @@ func BenchmarkPut(b *testing.B) { var index atomic.Int64 index.Store(-1) - objs := prepareObjects(b, b.N) + objs := prepareObjects(b.N) b.ResetTimer() b.ReportAllocs() b.RunParallel(func(pb *testing.PB) { @@ -71,7 +71,7 @@ func BenchmarkPut(b *testing.B) { defer func() { require.NoError(b, db.Close()) }() var index atomic.Int64 index.Store(-1) - objs := prepareObjects(b, b.N) + objs := prepareObjects(b.N) b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index d7e97064b4..4434149596 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -82,7 +82,7 @@ func stringPtr(s string) *string { return &s } -func newHeaderObjectSDK(t *testing.T, cnr cid.ID, oid *oid.ID, headerObjSDK *headerObjectSDKParams) *objectSDK.Object { +func newHeaderObjectSDK(cnr cid.ID, oid *oid.ID, headerObjSDK *headerObjectSDKParams) *objectSDK.Object { objSDK := objectSDK.New() objSDK.SetContainerID(cnr) if oid != nil { @@ -344,7 +344,7 @@ func TestAPECheck(t *testing.T) { var headerObjSDK *objectSDK.Object if test.header.headerObjSDK != nil { - headerObjSDK = newHeaderObjectSDK(t, cnr, obj, test.header.headerObjSDK) + headerObjSDK = newHeaderObjectSDK(cnr, obj, test.header.headerObjSDK) if test.header.fromHeaderProvider { require.NotNil(t, obj, "oid is required if a header is expected to be found in header provider") headerProvider.addHeader(cnr, *obj, headerObjSDK) diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index 55aa691b4e..0dcc0b84bc 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -80,7 +80,7 @@ func TestObjectProperties(t *testing.T) { t.Run(test.name, func(t *testing.T) { cnr := newContainerIDSDK(t, test.container) obj := newObjectIDSDK(t, test.object) - header := newHeaderObjectSDK(t, cnr, obj, test.header) + header := newHeaderObjectSDK(cnr, obj, test.header) props := objectProperties(cnr, obj, header.ToV2().GetHeader()) require.Equal(t, test.container, props[nativeschema.PropertyKeyObjectContainerID]) @@ -223,7 +223,7 @@ func TestNewAPERequest(t *testing.T) { var headerObjSDK *objectSDK.Object if test.header.headerObjSDK != nil { - headerObjSDK = newHeaderObjectSDK(t, cnr, obj, test.header.headerObjSDK) + headerObjSDK = newHeaderObjectSDK(cnr, obj, test.header.headerObjSDK) if test.header.fromHeaderProvider { require.NotNil(t, obj, "oid is required if a header is expected to be found in header provider") headerSource.addHeader(cnr, *obj, headerObjSDK) diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index 9b70efc73b..f5731c81ef 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -40,7 +40,7 @@ func copyVectors(v [][]netmap.NodeInfo) [][]netmap.NodeInfo { return vc } -func testPlacement(t *testing.T, ss, rs []int) ([][]netmap.NodeInfo, container.Container) { +func testPlacement(ss, rs []int) ([][]netmap.NodeInfo, container.Container) { nodes := make([][]netmap.NodeInfo, 0, len(rs)) replicas := make([]netmap.ReplicaDescriptor, 0, len(rs)) num := uint32(0) @@ -83,7 +83,7 @@ func TestTraverserObjectScenarios(t *testing.T) { selectors := []int{2, 3} replicas := []int{1, 2} - nodes, cnr := testPlacement(t, selectors, replicas) + nodes, cnr := testPlacement(selectors, replicas) nodesCopy := copyVectors(nodes) @@ -112,7 +112,7 @@ func TestTraverserObjectScenarios(t *testing.T) { selectors := []int{5, 3} replicas := []int{2, 2} - nodes, cnr := testPlacement(t, selectors, replicas) + nodes, cnr := testPlacement(selectors, replicas) nodesCopy := copyVectors(nodes) @@ -141,7 +141,7 @@ func TestTraverserObjectScenarios(t *testing.T) { selectors := []int{5, 3} replicas := []int{2, 2} - nodes, cnr := testPlacement(t, selectors, replicas) + nodes, cnr := testPlacement(selectors, replicas) nodesCopy := copyVectors(nodes) @@ -184,7 +184,7 @@ func TestTraverserObjectScenarios(t *testing.T) { selectors := []int{2, 3} replicas := []int{1, 2} - nodes, cnr := testPlacement(t, selectors, replicas) + nodes, cnr := testPlacement(selectors, replicas) tr, err := NewTraverser( ForContainer(cnr), @@ -213,7 +213,7 @@ func TestTraverserRemValues(t *testing.T) { selectors := []int{3, 4, 5} replicas := []int{2, 3, 4} - nodes, cnr := testPlacement(t, selectors, replicas) + nodes, cnr := testPlacement(selectors, replicas) nodesCopy := copyVectors(nodes) testCases := [...]struct { diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index f50aa0b0db..1be1c2f830 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -35,7 +35,7 @@ const ( var errRecentlyFailed = errors.New("client has recently failed") func (c *clientCache) init() { - l, _ := simplelru.NewLRU[string, cacheItem](defaultClientCacheSize, func(_ string, value cacheItem) { + l, _ := simplelru.NewLRU(defaultClientCacheSize, func(_ string, value cacheItem) { if conn := value.cc; conn != nil { _ = conn.Close() } diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 2a19ae18a5..064ee5900b 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -251,7 +251,7 @@ func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, } opsCh <- m } - if err != nil && !errors.Is(err, io.EOF) { + if !errors.Is(err, io.EOF) { return err } return nil From 46a04463b2c733e331f8a10a561241e08272856a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 1 Mar 2024 12:00:27 +0300 Subject: [PATCH 0416/1413] [#1016] forgejo: Add gopls check step Signed-off-by: Dmitrii Stepanov --- .forgejo/workflows/tests.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index f66a2c4017..449af3f518 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -71,3 +71,21 @@ jobs: - name: Run staticcheck run: make staticcheck-run + + gopls: + name: gopls check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '1.21' + cache: true + + - name: Install gopls + run: make gopls-install + + - name: Run gopls + run: make gopls-run From ae5bb87e7087245d775352eb2c1a74dd5d38468e Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 1 Mar 2024 19:29:33 +0300 Subject: [PATCH 0417/1413] Revert "[#866] Use TTL for blobovnicza tree cache" This reverts commit d9cbb16bd3cec547ba9621a51ac3d8b0d75b211b. Signed-off-by: Anton Nikiforov --- .../internal/modules/storagecfg/config.go | 1 - cmd/frostfs-node/config.go | 3 --- .../shard/blobstor/blobovnicza/config.go | 21 ------------------- config/example/node.env | 2 -- config/example/node.json | 2 -- config/example/node.yaml | 1 - docs/storage-node-configuration.md | 18 +++++++--------- .../blobstor/blobovniczatree/blobovnicza.go | 2 +- .../blobstor/blobovniczatree/cache.go | 13 +++++++----- .../blobstor/blobovniczatree/option.go | 9 -------- 10 files changed, 17 insertions(+), 55 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/config.go b/cmd/frostfs-adm/internal/modules/storagecfg/config.go index 9f7efe2dfa..a07ce32c66 100644 --- a/cmd/frostfs-adm/internal/modules/storagecfg/config.go +++ b/cmd/frostfs-adm/internal/modules/storagecfg/config.go @@ -61,7 +61,6 @@ storage: depth: 1 # max depth of object tree storage in key-value DB width: 4 # max width of object tree storage in key-value DB opened_cache_capacity: 50 # maximum number of opened database files - opened_cache_ttl: 5m # ttl for opened database file gc: remover_batch_size: 200 # number of objects to be removed by the garbage collector diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 50219a8c7b..360fdbec68 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -182,7 +182,6 @@ type subStorageCfg struct { width uint64 leafWidth uint64 openedCacheSize int - openedCacheTTL time.Duration initWorkerCount int initInAdvance bool } @@ -302,7 +301,6 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol sCfg.width = sub.ShallowWidth() sCfg.leafWidth = sub.LeafWidth() sCfg.openedCacheSize = sub.OpenedCacheSize() - sCfg.openedCacheTTL = sub.OpenedCacheTTL() sCfg.initWorkerCount = sub.InitWorkerCount() sCfg.initInAdvance = sub.InitInAdvance() case fstree.Type: @@ -887,7 +885,6 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { blobovniczatree.WithBlobovniczaShallowWidth(sRead.width), blobovniczatree.WithBlobovniczaLeafWidth(sRead.leafWidth), blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize), - blobovniczatree.WithOpenedCacheTTL(sRead.openedCacheTTL), blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), blobovniczatree.WithInitInAdvance(sRead.initInAdvance), blobovniczatree.WithLogger(c.log), diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go index 0e007b4257..37191cc722 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go @@ -1,8 +1,6 @@ package blobovniczaconfig import ( - "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" boltdbconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/boltdb" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" @@ -25,9 +23,6 @@ const ( // OpenedCacheSizeDefault is a default cache size of opened Blobovnicza's. OpenedCacheSizeDefault = 16 - // OpenedCacheTTLDefault is a default cache ttl of opened Blobovnicza's. - OpenedCacheTTLDefault = 0 // means expiring is off - // InitWorkerCountDefault is a default workers count to initialize Blobovnicza's. InitWorkerCountDefault = 5 ) @@ -106,22 +101,6 @@ func (x *Config) OpenedCacheSize() int { return OpenedCacheSizeDefault } -// OpenedCacheTTL returns the value of "opened_cache_ttl" config parameter. -// -// Returns OpenedCacheTTLDefault if the value is not a positive number. -func (x *Config) OpenedCacheTTL() time.Duration { - d := config.DurationSafe( - (*config.Config)(x), - "opened_cache_ttl", - ) - - if d > 0 { - return d - } - - return OpenedCacheTTLDefault -} - // BoltDB returns config instance for querying bolt db specific parameters. func (x *Config) BoltDB() *boltdbconfig.Config { return (*boltdbconfig.Config)(x) diff --git a/config/example/node.env b/config/example/node.env index a1db0c8761..b0364b7419 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -126,7 +126,6 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_SIZE=4194304 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH=1 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 -FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_TTL=5m FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_IN_ADVANCE=TRUE @@ -176,7 +175,6 @@ FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_SIZE=4194304 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH=1 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 -FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_TTL=5m FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_LEAF_WIDTH=10 ### FSTree config FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE=fstree diff --git a/config/example/node.json b/config/example/node.json index a7d7a36511..495fcb8ce7 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -174,7 +174,6 @@ "depth": 1, "width": 4, "opened_cache_capacity": 50, - "opened_cache_ttl": "5m", "leaf_width": 10, "init_worker_count": 10, "init_in_advance": true @@ -227,7 +226,6 @@ "depth": 1, "width": 4, "opened_cache_capacity": 50, - "opened_cache_ttl": "5m", "leaf_width": 10 }, { diff --git a/config/example/node.yaml b/config/example/node.yaml index 678ee1a87b..96af3b2083 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -150,7 +150,6 @@ storage: depth: 1 # max depth of object tree storage in key-value DB width: 4 # max width of object tree storage in key-value DB opened_cache_capacity: 50 # maximum number of opened database files - opened_cache_ttl: 5m # ttl for opened database file leaf_width: 10 # max count of key-value DB on leafs of object tree storage - perm: 0644 # permissions for blobstor files(directories: +x for current user and group) depth: 5 # max depth of object tree storage in FS diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index e2334f8fbf..6573e3ea22 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -209,7 +209,6 @@ blobstor: depth: 1 width: 4 opened_cache_capacity: 50 - opened_cache_ttl: 5m ``` #### Common options for sub-storages @@ -226,15 +225,14 @@ blobstor: | `depth` | `int` | `4` | File-system tree depth. | #### `blobovnicza` type options -| Parameter | Type | Default value | Description | -|-------------------------|------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `path` | `string` | | Path to the root of the blobstor. | -| `perm` | file mode | `0660` | Default permission for created files and directories. | -| `size` | `size` | `1 G` | Maximum size of a single blobovnicza | -| `depth` | `int` | `2` | Blobovnicza tree depth. | -| `width` | `int` | `16` | Blobovnicza tree width. | -| `opened_cache_capacity` | `int` | `16` | Maximum number of simultaneously opened blobovniczas. | -| `opened_cache_ttl` | `duration` | `0` | TTL in cache for opened blobovniczas(disabled by default). In case of heavy random-read and 10 shards each with 10_000 databases and accessing 400 objects per-second we will access each db approximately once per ((10 * 10_000 / 400) = 250 seconds <= 300 seconds = 5 min). Also take in mind that in this scenario they will probably be closed earlier because of the cache capacity, so bigger values are likely to be of no use. | +| Parameter | Type | Default value | Description | +|-------------------------|-----------|---------------|-------------------------------------------------------| +| `path` | `string` | | Path to the root of the blobstor. | +| `perm` | file mode | `0660` | Default permission for created files and directories. | +| `size` | `size` | `1 G` | Maximum size of a single blobovnicza | +| `depth` | `int` | `2` | Blobovnicza tree depth. | +| `width` | `int` | `16` | Blobovnicza tree width. | +| `opened_cache_capacity` | `int` | `16` | Maximum number of simultaneously opened blobovniczas. | ### `gc` subsection diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 460aebbbaa..9f2950094e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -87,7 +87,7 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) - blz.dbCache = newDBCache(blz.openedCacheSize, blz.openedCacheTTL, blz.commondbManager) + blz.dbCache = newDBCache(blz.openedCacheSize, blz.commondbManager) blz.deleteProtectedObjects = newAddressMap() blz.dbFilesGuard = &sync.RWMutex{} blz.rebuildGuard = &sync.RWMutex{} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index ef1793edfe..766f5ef0aa 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -1,11 +1,10 @@ package blobovniczatree import ( + "fmt" "sync" - "time" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" - "github.com/hashicorp/golang-lru/v2/expirable" "github.com/hashicorp/golang-lru/v2/simplelru" ) @@ -23,10 +22,14 @@ type dbCache struct { dbManager *dbManager } -func newDBCache(size int, ttl time.Duration, dbManager *dbManager) *dbCache { - cache := expirable.NewLRU(size, func(_ string, evictedDB *sharedDB) { +func newDBCache(size int, dbManager *dbManager) *dbCache { + cache, err := simplelru.NewLRU(size, func(_ string, evictedDB *sharedDB) { evictedDB.Close() - }, ttl) + }) + if err != nil { + // occurs only if the size is not positive + panic(fmt.Errorf("could not create LRU cache of size %d: %w", size, err)) + } return &dbCache{ cacheGuard: &sync.RWMutex{}, cache: cache, diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index e93640fae3..d36074dc8b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -16,7 +16,6 @@ type cfg struct { readOnly bool rootPath string openedCacheSize int - openedCacheTTL time.Duration blzShallowDepth uint64 blzShallowWidth uint64 blzLeafWidth uint64 @@ -35,7 +34,6 @@ type Option func(*cfg) const ( defaultPerm = 0o700 defaultOpenedCacheSize = 50 - defaultOpenedCacheTTL = 0 // means expiring is off defaultBlzShallowDepth = 2 defaultBlzShallowWidth = 16 defaultWaitBeforeDropDB = 10 * time.Second @@ -48,7 +46,6 @@ func initConfig(c *cfg) { log: &logger.Logger{Logger: zap.L()}, perm: defaultPerm, openedCacheSize: defaultOpenedCacheSize, - openedCacheTTL: defaultOpenedCacheTTL, blzShallowDepth: defaultBlzShallowDepth, blzShallowWidth: defaultBlzShallowWidth, reportError: func(string, error) {}, @@ -108,12 +105,6 @@ func WithOpenedCacheSize(sz int) Option { } } -func WithOpenedCacheTTL(ttl time.Duration) Option { - return func(c *cfg) { - c.openedCacheTTL = ttl - } -} - func WithObjectSizeLimit(sz uint64) Option { return func(c *cfg) { c.blzOpts = append(c.blzOpts, blobovnicza.WithObjectSizeLimit(sz)) From b38effd799671eebaf56e11e91404e92ed491f86 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 4 Mar 2024 09:37:31 +0300 Subject: [PATCH 0418/1413] [#1019] go.mod: Update sdk-go Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d86676dd30..0b0b03d0a2 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240215122347-a86170f53af7 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index fa5da98cc3..51d68321ea 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240215122347-a86170f53af7 h1:3a5g14oC+aMQ1p0bvuqG3JZKGLOcqRvcHzKAFV4eS0w= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240215122347-a86170f53af7/go.mod h1:XcgrbZ88XfvhAMxmZCQJ0dv6FyRSq6Mg2J7nN8uuO0k= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b h1:nLIWYXe4e1fWgpKeMfVke/CNBn388egh4fArFdvhfHw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b/go.mod h1:XcgrbZ88XfvhAMxmZCQJ0dv6FyRSq6Mg2J7nN8uuO0k= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 h1:hkDIg6vzV1c1pyt5uj9EiBikHqKczfoNpPhwWvXaNf8= From 1c504dca5c09827d331632b1684104f052aba2e7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 4 Mar 2024 16:14:09 +0300 Subject: [PATCH 0419/1413] [#1021] dev: Up neo-go version Current version of neo-go is 0.105. Signed-off-by: Dmitrii Stepanov --- dev/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index 7e68ea02ea..9d026797cd 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -3,7 +3,7 @@ version: "2.4" services: neo-go: - image: nspccdev/neo-go:0.103.0 + image: nspccdev/neo-go:0.105.0 container_name: neo-go command: ["node", "--config-path", "/config", "--privnet", "--debug"] stop_signal: SIGKILL From 702351a5d1b422a12815cbe4598c81e0bf1b503c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 4 Mar 2024 18:01:39 +0300 Subject: [PATCH 0420/1413] [#983] blobstor: Allow to specify wait before drop time Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 15 +++++++++------ cmd/frostfs-node/config/engine/config_test.go | 2 ++ .../shard/blobstor/blobovnicza/config.go | 19 +++++++++++++++++++ config/example/node.env | 1 + config/example/node.json | 3 ++- config/example/node.yaml | 1 + docs/storage-node-configuration.md | 19 +++++++++++-------- 7 files changed, 45 insertions(+), 15 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 360fdbec68..e5d3f7311c 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -178,12 +178,13 @@ type subStorageCfg struct { noSync bool // blobovnicza-specific - size uint64 - width uint64 - leafWidth uint64 - openedCacheSize int - initWorkerCount int - initInAdvance bool + size uint64 + width uint64 + leafWidth uint64 + openedCacheSize int + initWorkerCount int + initInAdvance bool + rebuildDropTimeout time.Duration } // readConfig fills applicationConfiguration with raw configuration values @@ -303,6 +304,7 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol sCfg.openedCacheSize = sub.OpenedCacheSize() sCfg.initWorkerCount = sub.InitWorkerCount() sCfg.initInAdvance = sub.InitInAdvance() + sCfg.rebuildDropTimeout = sub.RebuildDropTimeout() case fstree.Type: sub := fstreeconfig.From((*config.Config)(storagesCfg[i])) sCfg.depth = sub.Depth() @@ -887,6 +889,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize), blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), blobovniczatree.WithInitInAdvance(sRead.initInAdvance), + blobovniczatree.WithWaitBeforeDropDB(sRead.rebuildDropTimeout), blobovniczatree.WithLogger(c.log), blobovniczatree.WithObjectSizeLimit(shCfg.smallSizeObjectLimit), } diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 6c7b23cc43..86c9383096 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -101,6 +101,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 10, blz.LeafWidth()) require.EqualValues(t, 10, blz.InitWorkerCount()) require.EqualValues(t, true, blz.InitInAdvance()) + require.EqualValues(t, 30*time.Second, blz.RebuildDropTimeout()) require.Equal(t, "tmp/0/blob", ss[1].Path()) require.EqualValues(t, 0o644, ss[1].Perm()) @@ -151,6 +152,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 50, blz.OpenedCacheSize()) require.EqualValues(t, 10, blz.LeafWidth()) require.EqualValues(t, blobovniczaconfig.InitWorkerCountDefault, blz.InitWorkerCount()) + require.EqualValues(t, blobovniczaconfig.RebuildDropTimeoutDefault, blz.RebuildDropTimeout()) require.Equal(t, "tmp/1/blob", ss[1].Path()) require.EqualValues(t, 0o644, ss[1].Perm()) diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go index 37191cc722..9619a10273 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go @@ -1,6 +1,8 @@ package blobovniczaconfig import ( + "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" boltdbconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/boltdb" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" @@ -25,6 +27,9 @@ const ( // InitWorkerCountDefault is a default workers count to initialize Blobovnicza's. InitWorkerCountDefault = 5 + + // RebuildDropTimeoutDefault is a default timeout value to wait before drop single blobovnicza. + RebuildDropTimeoutDefault = 10 * time.Second ) // From wraps config section into Config. @@ -141,3 +146,17 @@ func (x *Config) InitInAdvance() bool { "init_in_advance", ) } + +// RebuildDropTimeout returns the value of "rebuild_drop_timeout" config parameter. +// +// Returns RebuildDropTimeoutDefault if the value is not defined or invalid. +func (x *Config) RebuildDropTimeout() time.Duration { + d := config.DurationSafe( + (*config.Config)(x), + "rebuild_drop_timeout", + ) + if d > 0 { + return d + } + return RebuildDropTimeoutDefault +} diff --git a/config/example/node.env b/config/example/node.env index b0364b7419..810a2842ba 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -129,6 +129,7 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_IN_ADVANCE=TRUE +FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_REBUILD_DROP_TIMEOUT=30s ### FSTree config FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE=fstree FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH=tmp/0/blob diff --git a/config/example/node.json b/config/example/node.json index 495fcb8ce7..e24a12f5f8 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -176,7 +176,8 @@ "opened_cache_capacity": 50, "leaf_width": 10, "init_worker_count": 10, - "init_in_advance": true + "init_in_advance": true, + "rebuild_drop_timeout": "30s" }, { "type": "fstree", diff --git a/config/example/node.yaml b/config/example/node.yaml index 96af3b2083..c9886355ff 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -190,6 +190,7 @@ storage: path: tmp/0/blob/blobovnicza init_worker_count: 10 #count of workers to initialize blobovniczas init_in_advance: true + rebuild_drop_timeout: 30s # timeout before drop single blobovnicza - type: fstree path: tmp/0/blob # blobstor path diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 6573e3ea22..15071f23df 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -225,14 +225,17 @@ blobstor: | `depth` | `int` | `4` | File-system tree depth. | #### `blobovnicza` type options -| Parameter | Type | Default value | Description | -|-------------------------|-----------|---------------|-------------------------------------------------------| -| `path` | `string` | | Path to the root of the blobstor. | -| `perm` | file mode | `0660` | Default permission for created files and directories. | -| `size` | `size` | `1 G` | Maximum size of a single blobovnicza | -| `depth` | `int` | `2` | Blobovnicza tree depth. | -| `width` | `int` | `16` | Blobovnicza tree width. | -| `opened_cache_capacity` | `int` | `16` | Maximum number of simultaneously opened blobovniczas. | +| Parameter | Type | Default value | Description | +| ----------------------- | ---------- | ------------- | --------------------------------------------------------------------- | +| `path` | `string` | | Path to the root of the blobstor. | +| `perm` | file mode | `0660` | Default permission for created files and directories. | +| `size` | `size` | `1 G` | Maximum size of a single blobovnicza | +| `depth` | `int` | `2` | Blobovnicza tree depth. | +| `width` | `int` | `16` | Blobovnicza tree width. | +| `opened_cache_capacity` | `int` | `16` | Maximum number of simultaneously opened blobovniczas. | +| `init_worker_count` | `int` | `5` | Maximum number of concurrent initialization workers. | +| `init_in_advance` | `bool` | `false` | If `true`, than all the blobovnicza files will be created on startup. | +| `rebuild_drop_timeout` | `duration` | `10s` | Timeout before drop empty blobovnicza file during rebuild. | ### `gc` subsection From c6f0545298ca0dffffeb5168f0d4aafb58e3cea9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 5 Mar 2024 11:14:21 +0300 Subject: [PATCH 0421/1413] [#1025] Fill last releases changelog Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00837c79b9..bc29022309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,36 @@ Changelog for FrostFS Node ## [Unreleased] +### Added +### Changed +### Fixed +### Removed +### Updated + +## [v0.38.0-rc.2] + +### Added +- Add `trace_id` to logs in `frostfs-node` (#146) +- Allow to forcefully remove container from IR (#733) +- LOKI support (#740) +- Allow sealing writecache (#569) +- Support tree service in data evacuation (#947) +- Use new policy engine mechanism for access control (#770, #804) + +### Changed +- Sort output in `frostfs-cli` subcommands (#333) +- Send bootstrap query at each epoch tick (#721) +- Do not retain garbage in fstree on systems supporting O_TMPFILE (#970) + +### Fixed +- Handle synchronization failures better in tree service (#741) +- Fix invalid batch size for iterator traversal in morph (#1000) + +### Updated +- `neo-go` to `v0.105.0` + +## [v0.37.0] + ### Added - Support impersonate bearer token (#229) - Change log level on SIGHUP for ir (#125) From b84cf91f734627ddf3889910c162a41214af3af4 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 26 Feb 2024 19:23:54 +0300 Subject: [PATCH 0422/1413] [#1009] adm: Make workaround for get-admin and list-rule-chains * Inroduce workaround to create actor for contract storage interface without passing a real alphabet wallet. This is made by creating a dummy account. Signed-off-by: Airat Arifullin --- .../internal/modules/morph/ape/ape.go | 8 ++------ .../internal/modules/morph/ape/ape_util.go | 17 +++++++++++++++++ go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index 957c7a15fe..e3990da079 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -60,7 +60,6 @@ var ( Short: "List rule chains", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: listRuleChains, } @@ -80,7 +79,6 @@ var ( Short: "Get admin", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: getAdmin, } @@ -124,7 +122,6 @@ func initListRuleChainsCmd() { Cmd.AddCommand(listRuleChainsCmd) listRuleChainsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - listRuleChainsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) _ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag) listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc) @@ -146,7 +143,6 @@ func initGetAdminCmd() { Cmd.AddCommand(getAdminCmd) getAdminCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - getAdminCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func addRuleChain(cmd *cobra.Command, _ []string) { @@ -173,7 +169,7 @@ func removeRuleChain(cmd *cobra.Command, _ []string) { func listRuleChains(cmd *cobra.Command, _ []string) { target := parseTarget(cmd) - pci, _ := newPolicyContractInterface(cmd) + pci, _ := newPolicyContractReaderInterface(cmd) chains, err := pci.ListMorphRuleChains(parseChainName(cmd), target) commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err) if len(chains) == 0 { @@ -203,7 +199,7 @@ func setAdmin(cmd *cobra.Command, _ []string) { } func getAdmin(cmd *cobra.Command, _ []string) { - pci, _ := newPolicyContractInterface(cmd) + pci, _ := newPolicyContractReaderInterface(cmd) addr, err := pci.GetAdmin() commonCmd.ExitOnErr(cmd, "unable to get admin: %w", err) cmd.Println(addr.StringLE()) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 3a990fe174..97f748da0c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -11,6 +11,7 @@ import ( apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/cobra" @@ -83,6 +84,22 @@ func parseChainName(cmd *cobra.Command) apechain.Name { return apeChainName } +func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorageReader, *invoker.Invoker) { + c, err := helper.GetN3Client(viper.GetViper()) + commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) + + inv := invoker.New(c, nil) + var ch util.Uint160 + r := management.NewReader(inv) + nnsCs, err := r.GetContractByID(1) + commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) + + ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) + commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) + + return morph.NewContractStorageReader(inv, ch), inv +} + func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *helper.LocalActor) { c, err := helper.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) diff --git a/go.mod b/go.mod index 0b0b03d0a2..926c1b64ee 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240304151211-839f22e1a36d git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 51d68321ea..2b09f5312c 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b/go.mod h1:XcgrbZ88XfvhAMxmZCQJ0dv6FyRSq6Mg2J7nN8uuO0k= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9 h1:hkDIg6vzV1c1pyt5uj9EiBikHqKczfoNpPhwWvXaNf8= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240129064140-8d21ab2d99d9/go.mod h1:YVL7yFaT0QNSpA0z+RHudLvrLwT+lsFYGyBSVc1ustI= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240304151211-839f22e1a36d h1:y7KP7vrX5Cbx9R2nzCFj7Ljjsa/KkWZS4nQIXHEeKdw= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240304151211-839f22e1a36d/go.mod h1:YVL7yFaT0QNSpA0z+RHudLvrLwT+lsFYGyBSVc1ustI= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= From e5d18e7a85b5f96c5ad57fc2eda38275d1b44123 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 5 Mar 2024 16:01:49 +0300 Subject: [PATCH 0423/1413] [#1023] adm: Make --namespace flag required Signed-off-by: Alexander Chuprov --- cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 0c791d3910..d2e45696e9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -155,6 +155,7 @@ func initFrostfsIDCreateNamespaceCmd() { frostfsidCreateNamespaceCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidCreateNamespaceCmd.Flags().String(namespaceFlag, "", "Namespace name to create") frostfsidCreateNamespaceCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + _ = frostfsidCreateNamespaceCmd.MarkFlagRequired(namespaceFlag) } func initFrostfsIDListNamespacesCmd() { From 0882840bf5258233fbc5ba412eb739fcab7d548c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 6 Mar 2024 12:33:30 +0300 Subject: [PATCH 0424/1413] [#634] shard: Add writecache inhume tests Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/gc_test.go | 126 ++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index bd8e0ac58b..a438b5defb 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -7,10 +7,13 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -167,3 +170,126 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { _, err = sh.Get(context.Background(), getPrm) require.True(t, client.IsErrObjectNotFound(err), "expired complex object must be deleted on epoch after lock expires") } + +func TestGCDropsObjectInhumedFromWritecache(t *testing.T) { + t.Parallel() + + t.Run("flush write-cache before inhume", func(t *testing.T) { + t.Parallel() + testGCDropsObjectInhumedFromWritecache(t, true) + }) + + t.Run("don't flush write-cache before inhume", func(t *testing.T) { + t.Parallel() + testGCDropsObjectInhumedFromWritecache(t, false) + }) +} + +func testGCDropsObjectInhumedFromWritecache(t *testing.T, flushbeforeInhume bool) { + sh := newCustomShard(t, true, shardOptions{ + additionalShardOptions: []Option{WithDisabledGC()}, + wcOpts: []writecache.Option{writecache.WithDisableBackgroundFlush()}, + }) + defer func() { require.NoError(t, sh.Close()) }() + + obj := testutil.GenerateObjectWithSize(1024) + + var putPrm PutPrm + putPrm.SetObject(obj) + _, err := sh.Put(context.Background(), putPrm) + require.NoError(t, err) + + // writecache stores object + wcObj, err := sh.writeCache.Head(context.Background(), objectCore.AddressOf(obj)) + require.NoError(t, err) + require.Equal(t, objectCore.AddressOf(obj), objectCore.AddressOf(wcObj)) + + // blobstore doesn't store object + bsRes, err := sh.blobStor.Get(context.Background(), common.GetPrm{ + Address: objectCore.AddressOf(obj), + }) + require.ErrorAs(t, err, new(*apistatus.ObjectNotFound)) + require.Nil(t, bsRes.Object) + require.Nil(t, bsRes.RawData) + + if flushbeforeInhume { + sh.writeCache.Flush(context.Background(), false, false) + } + + var inhumePrm InhumePrm + inhumePrm.MarkAsGarbage(objectCore.AddressOf(obj)) + _, err = sh.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + + // writecache doesn't store object + wcObj, err = sh.writeCache.Head(context.Background(), objectCore.AddressOf(obj)) + require.Error(t, err) + require.Nil(t, wcObj) + + if flushbeforeInhume { + // blobstore store object + bsRes, err = sh.blobStor.Get(context.Background(), common.GetPrm{ + Address: objectCore.AddressOf(obj), + }) + require.NoError(t, err) + require.Equal(t, objectCore.AddressOf(obj), objectCore.AddressOf(bsRes.Object)) + } else { + + // blobstore doesn't store object + bsRes, err = sh.blobStor.Get(context.Background(), common.GetPrm{ + Address: objectCore.AddressOf(obj), + }) + require.ErrorAs(t, err, new(*apistatus.ObjectNotFound)) + require.Nil(t, bsRes.Object) + require.Nil(t, bsRes.RawData) + } + + gcRes := sh.removeGarbage(context.Background()) + require.True(t, gcRes.success) + require.Equal(t, uint64(1), gcRes.deleted) +} + +func TestGCDontDeleteObjectFromWritecache(t *testing.T) { + sh := newCustomShard(t, true, shardOptions{ + additionalShardOptions: []Option{WithDisabledGC()}, + wcOpts: []writecache.Option{writecache.WithDisableBackgroundFlush()}, + }) + defer func() { require.NoError(t, sh.Close()) }() + + obj := testutil.GenerateObjectWithSize(1024) + + var putPrm PutPrm + putPrm.SetObject(obj) + _, err := sh.Put(context.Background(), putPrm) + require.NoError(t, err) + + // writecache stores object + wcObj, err := sh.writeCache.Head(context.Background(), objectCore.AddressOf(obj)) + require.NoError(t, err) + require.Equal(t, objectCore.AddressOf(obj), objectCore.AddressOf(wcObj)) + + // blobstore doesn't store object + bsRes, err := sh.blobStor.Get(context.Background(), common.GetPrm{ + Address: objectCore.AddressOf(obj), + }) + require.ErrorAs(t, err, new(*apistatus.ObjectNotFound)) + require.Nil(t, bsRes.Object) + require.Nil(t, bsRes.RawData) + + var metaInhumePrm meta.InhumePrm + metaInhumePrm.SetAddresses(objectCore.AddressOf(obj)) + metaInhumePrm.SetLockObjectHandling() + metaInhumePrm.SetGCMark() + _, err = sh.metaBase.Inhume(context.Background(), metaInhumePrm) + require.NoError(t, err) + + // logs: WARN shard/delete.go:98 can't remove object: object must be flushed from writecache + gcRes := sh.removeGarbage(context.Background()) + require.True(t, gcRes.success) + require.Equal(t, uint64(0), gcRes.deleted) + + // writecache stores object + wcObj, err = sh.writeCache.Head(context.Background(), objectCore.AddressOf(obj)) + require.NoError(t, err) + require.Equal(t, objectCore.AddressOf(obj), objectCore.AddressOf(wcObj)) +} From 63a29110ee79dba1e16764cf1350f4d4b3f328a0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 6 Mar 2024 12:54:56 +0300 Subject: [PATCH 0425/1413] [#634] go.mod: Bump protobuf version Found by vulncheck: Vulnerability #1: GO-2024-2611 Infinite loop in JSON unmarshaling in google.golang.org/protobuf More info: https://pkg.go.dev/vuln/GO-2024-2611 Module: google.golang.org/protobuf Found in: google.golang.org/protobuf@v1.32.0 Fixed in: google.golang.org/protobuf@v1.33.0 Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 926c1b64ee..6ba1ed73d7 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( golang.org/x/sys v0.16.0 golang.org/x/term v0.16.0 google.golang.org/grpc v1.61.0 - google.golang.org/protobuf v1.32.0 + google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 2b09f5312c..24120b20a3 100644 --- a/go.sum +++ b/go.sum @@ -422,8 +422,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From dacf580b8777250523f4999c3bb6beebd4800336 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Mar 2024 17:02:23 +0300 Subject: [PATCH 0426/1413] [#973] Makefile: Up golangci-lint version Signed-off-by: Dmitrii Stepanov --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 14738272ee..493ef25e57 100755 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ HUB_IMAGE ?= truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.21 -LINT_VERSION ?= 1.55.2 -TRUECLOUDLAB_LINT_VERSION ?= 0.0.3 +LINT_VERSION ?= 1.56.1 +TRUECLOUDLAB_LINT_VERSION ?= 0.0.5 PROTOC_VERSION ?= 25.0 PROTOC_GEN_GO_VERSION ?= $(shell go list -f '{{.Version}}' -m google.golang.org/protobuf) PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) From 66a26b7775106ec0d679ca04899f4ecdac7e98de Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Mar 2024 17:11:49 +0300 Subject: [PATCH 0427/1413] [#973] node: Resolve revive: unused-parameter linter Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-adm/internal/modules/morph/generate/root.go | 2 +- cmd/frostfs-adm/internal/modules/morph/policy/root.go | 2 +- cmd/frostfs-cli/internal/client/client.go | 6 +++--- cmd/frostfs-cli/modules/accounting/balance.go | 2 +- cmd/frostfs-cli/modules/accounting/root.go | 2 +- cmd/frostfs-cli/modules/container/create.go | 2 +- cmd/frostfs-cli/modules/container/delete.go | 2 +- cmd/frostfs-cli/modules/container/get.go | 2 +- cmd/frostfs-cli/modules/container/get_eacl.go | 2 +- cmd/frostfs-cli/modules/container/list.go | 2 +- cmd/frostfs-cli/modules/container/list_objects.go | 2 +- cmd/frostfs-cli/modules/container/nodes.go | 2 +- cmd/frostfs-cli/modules/container/root.go | 2 +- cmd/frostfs-cli/modules/container/set_eacl.go | 2 +- cmd/frostfs-cli/modules/control/drop_objects.go | 2 +- cmd/frostfs-cli/modules/control/root.go | 2 +- cmd/frostfs-cli/modules/netmap/get_epoch.go | 2 +- cmd/frostfs-cli/modules/netmap/netinfo.go | 2 +- cmd/frostfs-cli/modules/netmap/nodeinfo.go | 2 +- cmd/frostfs-cli/modules/netmap/root.go | 2 +- cmd/frostfs-cli/modules/netmap/snapshot.go | 2 +- cmd/frostfs-cli/modules/object/put.go | 4 ++-- cmd/frostfs-cli/modules/object/root.go | 2 +- cmd/frostfs-cli/modules/session/create.go | 2 +- cmd/frostfs-cli/modules/util/root.go | 2 +- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/netmap.go | 4 ++-- pkg/local_object_storage/blobovnicza/control.go | 2 +- pkg/local_object_storage/metabase/control.go | 2 +- pkg/local_object_storage/metabase/inhume.go | 2 +- pkg/local_object_storage/metabase/select.go | 6 +++--- pkg/local_object_storage/shard/shard.go | 2 +- pkg/local_object_storage/writecache/iterate.go | 2 +- pkg/services/notificator/nats/service.go | 4 ++-- 34 files changed, 41 insertions(+), 41 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/root.go b/cmd/frostfs-adm/internal/modules/morph/generate/root.go index 6b04848ae4..3633d9a8ee 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/root.go @@ -32,7 +32,7 @@ var ( _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.RefillGasAmountFlag, cmd.Flags().Lookup(commonflags.RefillGasAmountFlag)) }, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { return refillGas(cmd, commonflags.RefillGasAmountFlag, false) }, } diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/root.go b/cmd/frostfs-adm/internal/modules/morph/policy/root.go index db50279dca..a8a3562075 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/root.go @@ -16,7 +16,7 @@ var ( _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, RunE: SetPolicyCmd, - ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + ValidArgsFunction: func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { return []string{"ExecFeeFactor=", "StoragePrice=", "FeePerByte="}, cobra.ShellCompDirectiveNoSpace }, } diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 9807e111cf..f5ccabbe6c 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -353,7 +353,7 @@ type PutObjectPrm struct { rdr io.Reader - headerCallback func(*objectSDK.Object) + headerCallback func() prepareLocally bool } @@ -370,7 +370,7 @@ func (x *PutObjectPrm) SetPayloadReader(rdr io.Reader) { // SetHeaderCallback sets callback which is called on the object after the header is received // but before the payload is written. -func (x *PutObjectPrm) SetHeaderCallback(f func(*objectSDK.Object)) { +func (x *PutObjectPrm) SetHeaderCallback(f func()) { x.headerCallback = f } @@ -439,7 +439,7 @@ func PutObject(ctx context.Context, prm PutObjectPrm) (*PutObjectRes, error) { if wrt.WriteHeader(ctx, *prm.hdr) { if prm.headerCallback != nil { - prm.headerCallback(prm.hdr) + prm.headerCallback() } sz := prm.hdr.PayloadSize() diff --git a/cmd/frostfs-cli/modules/accounting/balance.go b/cmd/frostfs-cli/modules/accounting/balance.go index d10b9eaa11..1364b5e8ec 100644 --- a/cmd/frostfs-cli/modules/accounting/balance.go +++ b/cmd/frostfs-cli/modules/accounting/balance.go @@ -23,7 +23,7 @@ var accountingBalanceCmd = &cobra.Command{ Use: "balance", Short: "Get internal balance of FrostFS account", Long: `Get internal balance of FrostFS account`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { var idUser user.ID pk := key.GetOrGenerate(cmd) diff --git a/cmd/frostfs-cli/modules/accounting/root.go b/cmd/frostfs-cli/modules/accounting/root.go index 8ab8aa1255..afeca7626e 100644 --- a/cmd/frostfs-cli/modules/accounting/root.go +++ b/cmd/frostfs-cli/modules/accounting/root.go @@ -11,7 +11,7 @@ var Cmd = &cobra.Command{ Use: "accounting", Short: "Operations with accounts and balances", Long: `Operations with accounts and balances`, - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(cmd *cobra.Command, _ []string) { flags := cmd.Flags() _ = viper.BindPFlag(commonflags.WalletPath, flags.Lookup(commonflags.WalletPath)) diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index f670043eab..728332b359 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -38,7 +38,7 @@ var createContainerCmd = &cobra.Command{ Short: "Create new container", Long: `Create new container and register it in the FrostFS. It will be stored in sidechain when inner ring will accepts it.`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { placementPolicy, err := parseContainerPolicy(cmd, containerPolicy) commonCmd.ExitOnErr(cmd, "", err) diff --git a/cmd/frostfs-cli/modules/container/delete.go b/cmd/frostfs-cli/modules/container/delete.go index 20de84f74d..e5425bf252 100644 --- a/cmd/frostfs-cli/modules/container/delete.go +++ b/cmd/frostfs-cli/modules/container/delete.go @@ -20,7 +20,7 @@ var deleteContainerCmd = &cobra.Command{ Short: "Delete existing container", Long: `Delete existing container. Only owner of the container has a permission to remove container.`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { id := parseContainerID(cmd) tok := getSession(cmd) diff --git a/cmd/frostfs-cli/modules/container/get.go b/cmd/frostfs-cli/modules/container/get.go index 1681dc7f3d..8c4ab14f82 100644 --- a/cmd/frostfs-cli/modules/container/get.go +++ b/cmd/frostfs-cli/modules/container/get.go @@ -33,7 +33,7 @@ var getContainerInfoCmd = &cobra.Command{ Use: "get", Short: "Get container field info", Long: `Get container field info`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { cnr, _ := getContainer(cmd) prettyPrintContainer(cmd, cnr, containerJSON) diff --git a/cmd/frostfs-cli/modules/container/get_eacl.go b/cmd/frostfs-cli/modules/container/get_eacl.go index 8896db7696..4ed1c82e1c 100644 --- a/cmd/frostfs-cli/modules/container/get_eacl.go +++ b/cmd/frostfs-cli/modules/container/get_eacl.go @@ -16,7 +16,7 @@ var getExtendedACLCmd = &cobra.Command{ Use: "get-eacl", Short: "Get extended ACL table of container", Long: `Get extended ACL table of container`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { id := parseContainerID(cmd) pk := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index 86c1e5fba3..8f5db49dfc 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -31,7 +31,7 @@ var listContainersCmd = &cobra.Command{ Use: "list", Short: "List all created containers", Long: "List all created containers", - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { var idUser user.ID key := key.GetOrGenerate(cmd) diff --git a/cmd/frostfs-cli/modules/container/list_objects.go b/cmd/frostfs-cli/modules/container/list_objects.go index 1e0aeb4db6..ff2f8cf458 100644 --- a/cmd/frostfs-cli/modules/container/list_objects.go +++ b/cmd/frostfs-cli/modules/container/list_objects.go @@ -28,7 +28,7 @@ var listContainerObjectsCmd = &cobra.Command{ Use: "list-objects", Short: "List existing objects in container", Long: `List existing objects in container`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { id := parseContainerID(cmd) filters := new(objectSDK.SearchFilters) diff --git a/cmd/frostfs-cli/modules/container/nodes.go b/cmd/frostfs-cli/modules/container/nodes.go index 9273dd6513..d785fa23df 100644 --- a/cmd/frostfs-cli/modules/container/nodes.go +++ b/cmd/frostfs-cli/modules/container/nodes.go @@ -19,7 +19,7 @@ var containerNodesCmd = &cobra.Command{ Use: "nodes", Short: "Show nodes for container", Long: "Show nodes taking part in a container at the current epoch.", - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { cnr, pkey := getContainer(cmd) if pkey == nil { diff --git a/cmd/frostfs-cli/modules/container/root.go b/cmd/frostfs-cli/modules/container/root.go index ab7f5fb908..99d1a4231a 100644 --- a/cmd/frostfs-cli/modules/container/root.go +++ b/cmd/frostfs-cli/modules/container/root.go @@ -10,7 +10,7 @@ var Cmd = &cobra.Command{ Use: "container", Short: "Operations with containers", Long: "Operations with containers", - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(cmd *cobra.Command, _ []string) { // bind exactly that cmd's flags to // the viper before execution commonflags.Bind(cmd) diff --git a/cmd/frostfs-cli/modules/container/set_eacl.go b/cmd/frostfs-cli/modules/container/set_eacl.go index f2f60f5c32..86aa50a578 100644 --- a/cmd/frostfs-cli/modules/container/set_eacl.go +++ b/cmd/frostfs-cli/modules/container/set_eacl.go @@ -25,7 +25,7 @@ var setExtendedACLCmd = &cobra.Command{ Short: "Set new extended ACL table for container", Long: `Set new extended ACL table for container. Container ID in EACL table will be substituted with ID from the CLI.`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { id := parseContainerID(cmd) eaclTable := common.ReadEACL(cmd, flagVarsSetEACL.srcPath) diff --git a/cmd/frostfs-cli/modules/control/drop_objects.go b/cmd/frostfs-cli/modules/control/drop_objects.go index 9de3ae8a3a..8c0bb23324 100644 --- a/cmd/frostfs-cli/modules/control/drop_objects.go +++ b/cmd/frostfs-cli/modules/control/drop_objects.go @@ -14,7 +14,7 @@ var dropObjectsCmd = &cobra.Command{ Use: "drop-objects", Short: "Drop objects from the node's local storage", Long: "Drop objects from the node's local storage", - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) dropObjectsList, _ := cmd.Flags().GetStringSlice(dropObjectsFlag) diff --git a/cmd/frostfs-cli/modules/control/root.go b/cmd/frostfs-cli/modules/control/root.go index 41222fc000..b20d3618eb 100644 --- a/cmd/frostfs-cli/modules/control/root.go +++ b/cmd/frostfs-cli/modules/control/root.go @@ -10,7 +10,7 @@ var Cmd = &cobra.Command{ Use: "control", Short: "Operations with storage node", Long: `Operations with storage node`, - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(cmd *cobra.Command, _ []string) { ff := cmd.Flags() _ = viper.BindPFlag(commonflags.WalletPath, ff.Lookup(commonflags.WalletPath)) diff --git a/cmd/frostfs-cli/modules/netmap/get_epoch.go b/cmd/frostfs-cli/modules/netmap/get_epoch.go index 1670f16c0c..8e60e69bf7 100644 --- a/cmd/frostfs-cli/modules/netmap/get_epoch.go +++ b/cmd/frostfs-cli/modules/netmap/get_epoch.go @@ -12,7 +12,7 @@ var getEpochCmd = &cobra.Command{ Use: "epoch", Short: "Get current epoch number", Long: "Get current epoch number", - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { p := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) diff --git a/cmd/frostfs-cli/modules/netmap/netinfo.go b/cmd/frostfs-cli/modules/netmap/netinfo.go index ceea6a890f..cd43ba68df 100644 --- a/cmd/frostfs-cli/modules/netmap/netinfo.go +++ b/cmd/frostfs-cli/modules/netmap/netinfo.go @@ -16,7 +16,7 @@ var netInfoCmd = &cobra.Command{ Use: "netinfo", Short: "Get information about FrostFS network", Long: "Get information about FrostFS network", - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { p := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) diff --git a/cmd/frostfs-cli/modules/netmap/nodeinfo.go b/cmd/frostfs-cli/modules/netmap/nodeinfo.go index bf73286ed7..b6ec48f354 100644 --- a/cmd/frostfs-cli/modules/netmap/nodeinfo.go +++ b/cmd/frostfs-cli/modules/netmap/nodeinfo.go @@ -18,7 +18,7 @@ var nodeInfoCmd = &cobra.Command{ Use: "nodeinfo", Short: "Get target node info", Long: `Get target node info`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { p := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) diff --git a/cmd/frostfs-cli/modules/netmap/root.go b/cmd/frostfs-cli/modules/netmap/root.go index aaa83f12fc..b4f5897e58 100644 --- a/cmd/frostfs-cli/modules/netmap/root.go +++ b/cmd/frostfs-cli/modules/netmap/root.go @@ -9,7 +9,7 @@ var Cmd = &cobra.Command{ Use: "netmap", Short: "Operations with Network Map", Long: `Operations with Network Map`, - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(cmd *cobra.Command, _ []string) { // bind exactly that cmd's flags to // the viper before execution commonflags.Bind(cmd) diff --git a/cmd/frostfs-cli/modules/netmap/snapshot.go b/cmd/frostfs-cli/modules/netmap/snapshot.go index eaaf598b98..650d8a1b90 100644 --- a/cmd/frostfs-cli/modules/netmap/snapshot.go +++ b/cmd/frostfs-cli/modules/netmap/snapshot.go @@ -12,7 +12,7 @@ var snapshotCmd = &cobra.Command{ Use: "snapshot", Short: "Request current local snapshot of the network map", Long: `Request current local snapshot of the network map`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, _ []string) { p := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, p, commonflags.RPC) diff --git a/cmd/frostfs-cli/modules/object/put.go b/cmd/frostfs-cli/modules/object/put.go index a41d3c0aaa..45e02edb34 100644 --- a/cmd/frostfs-cli/modules/object/put.go +++ b/cmd/frostfs-cli/modules/object/put.go @@ -174,7 +174,7 @@ func setFilePayloadReader(cmd *cobra.Command, f *os.File, prm *internalclient.Pu p := pb.New64(fi.Size()) p.Output = cmd.OutOrStdout() prm.SetPayloadReader(p.NewProxyReader(f)) - prm.SetHeaderCallback(func(o *objectSDK.Object) { p.Start() }) + prm.SetHeaderCallback(func() { p.Start() }) return p } @@ -182,7 +182,7 @@ func setBinaryPayloadReader(cmd *cobra.Command, obj *objectSDK.Object, prm *inte p := pb.New(len(obj.Payload())) p.Output = cmd.OutOrStdout() prm.SetPayloadReader(p.NewProxyReader(payloadReader)) - prm.SetHeaderCallback(func(o *objectSDK.Object) { p.Start() }) + prm.SetHeaderCallback(func() { p.Start() }) return p } diff --git a/cmd/frostfs-cli/modules/object/root.go b/cmd/frostfs-cli/modules/object/root.go index e04366f4d3..7d8008b107 100644 --- a/cmd/frostfs-cli/modules/object/root.go +++ b/cmd/frostfs-cli/modules/object/root.go @@ -10,7 +10,7 @@ var Cmd = &cobra.Command{ Use: "object", Short: "Operations with Objects", Long: `Operations with Objects`, - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(cmd *cobra.Command, _ []string) { // bind exactly that cmd's flags to // the viper before execution commonflags.Bind(cmd) diff --git a/cmd/frostfs-cli/modules/session/create.go b/cmd/frostfs-cli/modules/session/create.go index e92e4baa6d..e13200a5d6 100644 --- a/cmd/frostfs-cli/modules/session/create.go +++ b/cmd/frostfs-cli/modules/session/create.go @@ -29,7 +29,7 @@ var createCmd = &cobra.Command{ Use: "create", Short: "Create session token", Run: createSession, - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) _ = viper.BindPFlag(commonflags.Account, cmd.Flags().Lookup(commonflags.Account)) }, diff --git a/cmd/frostfs-cli/modules/util/root.go b/cmd/frostfs-cli/modules/util/root.go index 3cdd236d41..4a6b4403bb 100644 --- a/cmd/frostfs-cli/modules/util/root.go +++ b/cmd/frostfs-cli/modules/util/root.go @@ -9,7 +9,7 @@ import ( var Cmd = &cobra.Command{ Use: "util", Short: "Utility operations", - PersistentPreRun: func(cmd *cobra.Command, args []string) { + PersistentPreRun: func(cmd *cobra.Command, _ []string) { flags := cmd.Flags() _ = viper.BindPFlag(commonflags.GenerateKey, flags.Lookup(commonflags.GenerateKey)) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e5d3f7311c..166d36b0cb 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -925,7 +925,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { ss = append(ss, blobstor.SubStorage{ Storage: fstree.New(fstreeOpts...), - Policy: func(_ *objectSDK.Object, data []byte) bool { + Policy: func(_ *objectSDK.Object, _ []byte) bool { return true }, }) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index b21e842c5e..b1d854da41 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -176,7 +176,7 @@ func addNewEpochNotificationHandlers(c *cfg) { c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber()) }) - addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { + addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { if !c.needBootstrap() || c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470 return } @@ -203,7 +203,7 @@ func addNewEpochNotificationHandlers(c *cfg) { }) if c.cfgMorph.notaryEnabled { - addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { + addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { _, err := makeNotaryDeposit(c) if err != nil { c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit, diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index dfc4f884ff..dab301647a 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -115,7 +115,7 @@ func (b *Blobovnicza) initializeCounters() error { return nil } - return b.iterateAllDataBuckets(tx, func(lower, upper uint64, b *bbolt.Bucket) (bool, error) { + return b.iterateAllDataBuckets(tx, func(_, _ uint64, b *bbolt.Bucket) (bool, error) { return false, b.ForEach(func(k, v []byte) error { size += uint64(len(k) + len(v)) items++ diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index ec4c29c4bf..a275f4560d 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -167,7 +167,7 @@ func (db *DB) init(reset bool) error { return nil } - err = tx.ForEach(func(name []byte, b *bbolt.Bucket) error { + err = tx.ForEach(func(name []byte, _ *bbolt.Bucket) error { if _, ok := mStaticBuckets[string(name)]; !ok { return tx.DeleteBucket(name) } diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index cd83a61597..250504120d 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -354,7 +354,7 @@ func isTomb(graveyardBucket *bbolt.Bucket, key []byte) (bool, error) { // iterate over graveyard and check if target address // is the address of tombstone in graveyard. - err := graveyardBucket.ForEach(func(k, v []byte) error { + err := graveyardBucket.ForEach(func(_, v []byte) error { // check if graveyard has record with key corresponding // to tombstone address (at least one) targetIsTomb = bytes.Equal(v, key) diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 8b086a89f0..e5321c7948 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -174,7 +174,7 @@ func selectAllFromBucket(tx *bbolt.Tx, name []byte, to map[string]int, fNum int) return } - _ = bkt.ForEach(func(k, v []byte) error { + _ = bkt.ForEach(func(k, _ []byte) error { markAddressInCache(to, fNum, string(k)) return nil @@ -386,7 +386,7 @@ func (db *DB) selectFromList( return } - if err = fMatch.matchBucket(bkt, f.Header(), f.Value(), func(key, val []byte) error { + if err = fMatch.matchBucket(bkt, f.Header(), f.Value(), func(_, val []byte) error { l, err := decodeList(val) if err != nil { db.log.Debug(logs.MetabaseCantDecodeListBucketLeaf, @@ -459,7 +459,7 @@ func (db *DB) selectObjectID( return } - err := fMatch.matchBucket(bkt, f.Header(), f.Value(), func(k, v []byte) error { + err := fMatch.matchBucket(bkt, f.Header(), f.Value(), func(k, _ []byte) error { var id oid.ID if err := id.Decode(k); err == nil { appendOID(id) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index e8f1978d20..8368f6db47 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -375,7 +375,7 @@ func WithRebuildWorkerLimiter(l RebuildWorkerLimiter) Option { // For testing purposes only. func WithDisabledGC() Option { return func(c *cfg) { - c.gcCfg.testHookRemover = func(ctx context.Context) gcRunResult { return gcRunResult{} } + c.gcCfg.testHookRemover = func(_ context.Context) gcRunResult { return gcRunResult{} } } } diff --git a/pkg/local_object_storage/writecache/iterate.go b/pkg/local_object_storage/writecache/iterate.go index 5349c069cd..9ec039f914 100644 --- a/pkg/local_object_storage/writecache/iterate.go +++ b/pkg/local_object_storage/writecache/iterate.go @@ -27,7 +27,7 @@ func IterateDB(db *bbolt.DB, f func(oid.Address) error) error { var addr oid.Address - return b.ForEach(func(k, v []byte) error { + return b.ForEach(func(k, _ []byte) error { err := addr.DecodeString(string(k)) if err != nil { return fmt.Errorf("could not parse object address: %w", err) diff --git a/pkg/services/notificator/nats/service.go b/pkg/services/notificator/nats/service.go index 7f525df95f..9de538f2b3 100644 --- a/pkg/services/notificator/nats/service.go +++ b/pkg/services/notificator/nats/service.go @@ -93,10 +93,10 @@ func New(oo ...Option) *Writer { w.opts.nOpts = append(w.opts.nOpts, nats.NoCallbacksAfterClientClose(), // do not call callbacks when it was planned writer stop - nats.DisconnectErrHandler(func(conn *nats.Conn, err error) { + nats.DisconnectErrHandler(func(_ *nats.Conn, err error) { w.log.Error(logs.NatsNatsConnectionWasLost, zap.Error(err)) }), - nats.ReconnectHandler(func(conn *nats.Conn) { + nats.ReconnectHandler(func(_ *nats.Conn) { w.log.Warn(logs.NatsNatsReconnectedToTheServer) }), ) From d433b492658fe50d87a6bb51fde80180fd804d47 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Mar 2024 17:55:50 +0300 Subject: [PATCH 0428/1413] [#973] node: Resolve perfsprint linter `fmt.Errorf can be replaced with errors.New` and `fmt.Sprintf can be replaced with string addition` Signed-off-by: Dmitrii Stepanov --- .../internal/modules/morph/ape/ape_util.go | 17 ++++++++++++----- .../internal/modules/morph/helper/contract.go | 2 +- .../internal/modules/morph/helper/download.go | 4 +++- .../modules/morph/helper/initialize_ctx.go | 10 ++++++++-- .../internal/modules/morph/helper/netmap.go | 4 +++- .../internal/modules/morph/notary/notary.go | 5 ++++- .../internal/modules/morph/policy/policy.go | 5 ++++- cmd/frostfs-cli/internal/client/client.go | 4 +++- cmd/frostfs-cli/modules/control/list_rules.go | 10 ++++++++-- cmd/frostfs-cli/modules/object/nodes.go | 4 +++- cmd/frostfs-cli/modules/util/ape.go | 3 ++- cmd/frostfs-ir/httpcomponent.go | 13 ++++++------- cmd/frostfs-ir/pprof.go | 5 ++--- cmd/frostfs-node/config.go | 4 ++-- cmd/frostfs-node/config/engine/shard/config.go | 4 +--- cmd/frostfs-node/config/morph/config.go | 6 ++++-- cmd/frostfs-node/httpcomponent.go | 3 +-- cmd/frostfs-node/main.go | 6 +++--- cmd/internal/common/config/viper.go | 5 ++++- internal/ape/converter.go | 2 +- pkg/ape/chainbase/boltdb.go | 4 +++- .../processors/container/process_container.go | 5 ++++- .../blobstor/blobovniczatree/blobovnicza.go | 3 +-- pkg/local_object_storage/metabase/counter.go | 9 +++++++-- pkg/local_object_storage/metabase/delete.go | 4 +++- pkg/local_object_storage/metabase/util.go | 6 ++++-- pkg/local_object_storage/pilorama/forest.go | 5 ++++- pkg/morph/client/netmap/peer.go | 5 ++++- pkg/network/address.go | 5 ++++- pkg/services/container/ape.go | 6 ++++-- pkg/services/container/morph/executor.go | 4 +++- pkg/services/control/ir/server/calls.go | 6 +++--- pkg/services/control/server/convert.go | 3 +-- pkg/services/control/server/evacuate.go | 4 +++- pkg/services/object/ape/checker.go | 3 ++- pkg/services/object/ape/errors.go | 4 +--- pkg/services/object/ape/service.go | 5 ++++- pkg/services/object/put/single.go | 4 +++- pkg/util/sdnotify/sdnotify.go | 14 ++++++++++---- 39 files changed, 143 insertions(+), 72 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 97f748da0c..253e130a8d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -1,7 +1,7 @@ package ape import ( - "fmt" + "errors" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" @@ -28,6 +28,13 @@ var mChainName = map[string]apechain.Name{ s3: apechain.S3, } +var ( + errUnknownTargetType = errors.New("unknown target type") + errChainIDCannotBeEmpty = errors.New("chain id cannot be empty") + errRuleIsNotParsed = errors.New("rule is not passed") + errUnsupportedChainName = errors.New("unsupported chain name") +) + func parseTarget(cmd *cobra.Command) policyengine.Target { var targetType policyengine.TargetType typ, _ := cmd.Flags().GetString(targetTypeFlag) @@ -37,7 +44,7 @@ func parseTarget(cmd *cobra.Command) policyengine.Target { case containerTarget: targetType = policyengine.Container default: - commonCmd.ExitOnErr(cmd, "read target type error: %w", fmt.Errorf("unknown target type")) + commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) } name, _ := cmd.Flags().GetString(targetNameFlag) @@ -51,7 +58,7 @@ func parseChainID(cmd *cobra.Command) apechain.ID { chainID, _ := cmd.Flags().GetString(chainIDFlag) if chainID == "" { commonCmd.ExitOnErr(cmd, "read chain id error: %w", - fmt.Errorf("chain id cannot be empty")) + errChainIDCannotBeEmpty) } return apechain.ID(chainID) } @@ -64,7 +71,7 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) } else { - commonCmd.ExitOnErr(cmd, "parser error: %w", fmt.Errorf("rule is not passed")) + commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed) } chain.ID = parseChainID(cmd) @@ -79,7 +86,7 @@ func parseChainName(cmd *cobra.Command) apechain.Name { chainName, _ := cmd.Flags().GetString(chainNameFlag) apeChainName, ok := mChainName[strings.ToLower(chainName)] if !ok { - commonCmd.ExitOnErr(cmd, "", fmt.Errorf("unsupported chain name")) + commonCmd.ExitOnErr(cmd, "", errUnsupportedChainName) } return apeChainName } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/contract.go b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go index a740f3f099..7326ec1f53 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/contract.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go @@ -116,7 +116,7 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any case constants.PolicyContract: items = append(items, c.Contracts[constants.ProxyContract].Hash) default: - panic(fmt.Sprintf("invalid contract name: %s", ctrName)) + panic("invalid contract name: " + ctrName) } return items, nil } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/download.go b/cmd/frostfs-adm/internal/modules/morph/helper/download.go index 08d427a46c..71528a5dbd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/download.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/download.go @@ -14,6 +14,8 @@ import ( "github.com/spf13/cobra" ) +var errNoReleasesFound = errors.New("attempt to fetch contracts archive from the offitial repository failed: no releases found") + func downloadContracts(cmd *cobra.Command, url string) (io.ReadCloser, error) { cmd.Printf("Downloading contracts archive from '%s'\n", url) @@ -61,7 +63,7 @@ func downloadContractsFromRepository(cmd *cobra.Command) (io.ReadCloser, error) } if latestRelease == nil { - return nil, fmt.Errorf("attempt to fetch contracts archive from the offitial repository failed: no releases found") + return nil, errNoReleasesFound } cmd.Printf("Found release %s (%s)\n", latestRelease.TagName, latestRelease.Title) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go index 09d64b352a..b5b6adf05c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go @@ -3,6 +3,7 @@ package helper import ( "encoding/hex" "encoding/json" + "errors" "fmt" io2 "io" "os" @@ -33,6 +34,11 @@ import ( "github.com/spf13/viper" ) +var ( + errNegativeDuration = errors.New("epoch duration must be positive") + errNegativeSize = errors.New("max object size must be positive") +) + type ContractState struct { NEF *nef.File RawNEF []byte @@ -166,11 +172,11 @@ func validateInit(cmd *cobra.Command) error { return nil } if viper.GetInt64(commonflags.EpochDurationInitFlag) <= 0 { - return fmt.Errorf("epoch duration must be positive") + return errNegativeDuration } if viper.GetInt64(commonflags.MaxObjectSizeInitFlag) <= 0 { - return fmt.Errorf("max object size must be positive") + return errNegativeSize } return nil diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go index 732a5e11fb..f68fbefaf6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go @@ -29,6 +29,8 @@ var NetmapConfigKeys = []string{ netmap.MaintenanceModeAllowedConfig, } +var errFailedToFetchListOfNetworkKeys = errors.New("can't fetch list of network config keys from the netmap contract") + func GetDefaultNetmapContractConfigMap() map[string]any { m := make(map[string]any) m[netmap.EpochDurationConfig] = viper.GetInt64(commonflags.EpochDurationInitFlag) @@ -95,7 +97,7 @@ func GetNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Ite } arr, err := unwrap.Array(roInvoker.Call(nmHash, "listConfig")) if err != nil { - return nil, fmt.Errorf("can't fetch list of network config keys from the netmap contract") + return nil, errFailedToFetchListOfNetworkKeys } return arr, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go index 6d65a82846..9b213da4e9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go @@ -1,6 +1,7 @@ package notary import ( + "errors" "fmt" "math/big" "strconv" @@ -31,6 +32,8 @@ const ( notaryDepositTillFlag = "till" ) +var errInvalidNotaryDepositLifetime = errors.New("notary deposit lifetime must be a positive integer") + func depositNotary(cmd *cobra.Command, _ []string) error { w, err := openWallet(cmd) if err != nil { @@ -78,7 +81,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error { if tillStr != "" { till, err = strconv.ParseInt(tillStr, 10, 64) if err != nil || till <= 0 { - return fmt.Errorf("notary deposit lifetime must be a positive integer") + return errInvalidNotaryDepositLifetime } } diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go index 440e73a12a..a11ca2704f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go @@ -2,6 +2,7 @@ package policy import ( "bytes" + "errors" "fmt" "strconv" "strings" @@ -24,6 +25,8 @@ const ( setFeeParam = "FeePerByte" ) +var errInvalidParameterFormat = errors.New("invalid parameter format, must be Parameter=Value") + func SetPolicyCmd(cmd *cobra.Command, args []string) error { wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { @@ -34,7 +37,7 @@ func SetPolicyCmd(cmd *cobra.Command, args []string) error { for i := range args { k, v, found := strings.Cut(args[i], "=") if !found { - return fmt.Errorf("invalid parameter format, must be Parameter=Value") + return errInvalidParameterFormat } switch k { diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index f5ccabbe6c..a6d9968c52 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -21,6 +21,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) +var errMissingHeaderInResponse = errors.New("missing header in response") + // BalanceOfPrm groups parameters of BalanceOf operation. type BalanceOfPrm struct { commonPrm @@ -654,7 +656,7 @@ func HeadObject(ctx context.Context, prm HeadObjectPrm) (*HeadObjectRes, error) var hdr objectSDK.Object if !res.ReadHeader(&hdr) { - return nil, fmt.Errorf("missing header in response") + return nil, errMissingHeaderInResponse } return &HeadObjectRes{ diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index 4598320d77..b345ecbfbf 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -1,6 +1,7 @@ package control import ( + "errors" "fmt" "strings" @@ -35,6 +36,11 @@ const ( targetTypeDesc = "Resource type(container/namespace)" ) +var ( + errSettingDefaultValueWasDeclined = errors.New("setting default value was declined") + errUnknownTargetType = errors.New("unknown target type") +) + func parseTarget(cmd *cobra.Command) *control.ChainTarget { typ, _ := cmd.Flags().GetString(targetTypeFlag) name, _ := cmd.Flags().GetString(targetNameFlag) @@ -45,7 +51,7 @@ func parseTarget(cmd *cobra.Command) *control.ChainTarget { commonCmd.ExitOnErr(cmd, "read line error: %w", err) ln = strings.ToLower(ln) if len(ln) > 0 && (ln[0] == 'n') { - commonCmd.ExitOnErr(cmd, "read namespace error: %w", fmt.Errorf("setting default value was declined")) + commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined) } name = defaultNamespace } @@ -61,7 +67,7 @@ func parseTarget(cmd *cobra.Command) *control.ChainTarget { Type: control.ChainTarget_CONTAINER, } default: - commonCmd.ExitOnErr(cmd, "read target type error: %w", fmt.Errorf("unknown target type")) + commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) } return nil } diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 70a3eb75f3..50c47e8222 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -30,6 +30,8 @@ const ( verifyPresenceAllFlag = "verify-presence-all" ) +var errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint") + type objectNodesInfo struct { containerID cid.ID objectID oid.ID @@ -299,7 +301,7 @@ func createClient(ctx context.Context, cmd *cobra.Command, candidate netmapSDK.N return nil, lastErr } if cli == nil { - return nil, fmt.Errorf("failed to create client: no available endpoint") + return nil, errNoAvailableEndpoint } return cli, nil } diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 1500f0c5cb..d2dd0ced24 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -24,6 +24,7 @@ var ( errMixedTypesInRule = errors.New("found mixed type of actions and conditions in rule") errNoActionsInRule = errors.New("there are no actions in rule") errUnsupportedResourceFormat = errors.New("unsupported resource format") + errFailedToParseAllAny = errors.New("any/all is not parsed") ) // PrintHumanReadableAPEChain print APE chain rules. @@ -188,7 +189,7 @@ func parseAnyAll(lexeme string) (bool, error) { case "all": return false, nil default: - return false, fmt.Errorf("any/all is not parsed") + return false, errFailedToParseAllAny } } diff --git a/cmd/frostfs-ir/httpcomponent.go b/cmd/frostfs-ir/httpcomponent.go index 3a6d77d84c..2792c35486 100644 --- a/cmd/frostfs-ir/httpcomponent.go +++ b/cmd/frostfs-ir/httpcomponent.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "net/http" "time" @@ -26,7 +25,7 @@ const ( ) func (c *httpComponent) init() { - log.Info(fmt.Sprintf("init %s", c.name)) + log.Info("init " + c.name) c.enabled = cfg.GetBool(c.name + enabledKeyPostfix) c.address = cfg.GetString(c.name + addressKeyPostfix) c.shutdownDur = cfg.GetDuration(c.name + shutdownTimeoutKeyPostfix) @@ -40,14 +39,14 @@ func (c *httpComponent) init() { httputil.WithShutdownTimeout(c.shutdownDur), ) } else { - log.Info(fmt.Sprintf("%s is disabled, skip", c.name)) + log.Info(c.name + " is disabled, skip") c.srv = nil } } func (c *httpComponent) start() { if c.srv != nil { - log.Info(fmt.Sprintf("start %s", c.name)) + log.Info("start " + c.name) wg.Add(1) go func() { defer wg.Done() @@ -58,7 +57,7 @@ func (c *httpComponent) start() { func (c *httpComponent) shutdown() error { if c.srv != nil { - log.Info(fmt.Sprintf("shutdown %s", c.name)) + log.Info("shutdown " + c.name) return c.srv.Shutdown() } return nil @@ -72,9 +71,9 @@ func (c *httpComponent) needReload() bool { } func (c *httpComponent) reload() { - log.Info(fmt.Sprintf("reload %s", c.name)) + log.Info("reload " + c.name) if c.needReload() { - log.Info(fmt.Sprintf("%s config updated", c.name)) + log.Info(c.name + " config updated") if err := c.shutdown(); err != nil { log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), diff --git a/cmd/frostfs-ir/pprof.go b/cmd/frostfs-ir/pprof.go index d67c463fcd..ff5642008d 100644 --- a/cmd/frostfs-ir/pprof.go +++ b/cmd/frostfs-ir/pprof.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "runtime" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -53,9 +52,9 @@ func (c *pprofComponent) needReload() bool { } func (c *pprofComponent) reload() { - log.Info(fmt.Sprintf("reload %s", c.name)) + log.Info("reload " + c.name) if c.needReload() { - log.Info(fmt.Sprintf("%s config updated", c.name)) + log.Info(c.name + " config updated") if err := c.shutdown(); err != nil { log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error())) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 166d36b0cb..48b76ac0f9 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1004,12 +1004,12 @@ func (c *cfg) loggerPrm() (*logger.Prm, error) { err := c.dynamicConfiguration.logger.SetLevelString(c.LoggerCfg.level) if err != nil { // not expected since validation should be performed before - panic(fmt.Sprintf("incorrect log level format: %s", c.LoggerCfg.level)) + panic("incorrect log level format: " + c.LoggerCfg.level) } err = c.dynamicConfiguration.logger.SetDestination(c.LoggerCfg.destination) if err != nil { // not expected since validation should be performed before - panic(fmt.Sprintf("incorrect log destination format: %s", c.LoggerCfg.destination)) + panic("incorrect log destination format: " + c.LoggerCfg.destination) } return c.dynamicConfiguration.logger, nil diff --git a/cmd/frostfs-node/config/engine/shard/config.go b/cmd/frostfs-node/config/engine/shard/config.go index 16100c3a78..f9cfdf2a86 100644 --- a/cmd/frostfs-node/config/engine/shard/config.go +++ b/cmd/frostfs-node/config/engine/shard/config.go @@ -1,8 +1,6 @@ package shardconfig import ( - "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" blobstorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor" gcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/gc" @@ -158,7 +156,7 @@ func (x *Config) Mode() (m mode.Mode) { case "disabled": m = mode.Disabled default: - panic(fmt.Sprintf("unknown shard mode: %s", s)) + panic("unknown shard mode: " + s) } return diff --git a/cmd/frostfs-node/config/morph/config.go b/cmd/frostfs-node/config/morph/config.go index 4ab608ef32..866223073a 100644 --- a/cmd/frostfs-node/config/morph/config.go +++ b/cmd/frostfs-node/config/morph/config.go @@ -1,7 +1,7 @@ package morphconfig import ( - "fmt" + "errors" "strconv" "time" @@ -27,6 +27,8 @@ const ( SwitchIntervalDefault = 2 * time.Minute ) +var errNoMorphEndpoints = errors.New("no morph chain RPC endpoints, see `morph.rpc_endpoint` section") + // RPCEndpoint returns list of the values of "rpc_endpoint" config parameter // from "morph" section. // @@ -54,7 +56,7 @@ func RPCEndpoint(c *config.Config) []client.Endpoint { } if len(es) == 0 { - panic(fmt.Errorf("no morph chain RPC endpoints, see `morph.rpc_endpoint` section")) + panic(errNoMorphEndpoints) } return es } diff --git a/cmd/frostfs-node/httpcomponent.go b/cmd/frostfs-node/httpcomponent.go index 373a5e5c86..2ec20d848a 100644 --- a/cmd/frostfs-node/httpcomponent.go +++ b/cmd/frostfs-node/httpcomponent.go @@ -2,7 +2,6 @@ package main import ( "context" - "fmt" "net/http" "time" @@ -23,7 +22,7 @@ type httpComponent struct { func (cmp *httpComponent) init(c *cfg) { if !cmp.enabled { - c.log.Info(fmt.Sprintf("%s is disabled", cmp.name)) + c.log.Info(cmp.name + " is disabled") return } // Init server with parameters diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index f91a6decc5..e1eeb6861d 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -75,7 +75,7 @@ func main() { func initAndLog(c *cfg, name string, initializer func(*cfg)) { c.log.Info(fmt.Sprintf("initializing %s service...", name)) initializer(c) - c.log.Info(fmt.Sprintf("%s service has been successfully initialized", name)) + c.log.Info(name + " service has been successfully initialized") } func initApp(ctx context.Context, c *cfg) { @@ -124,7 +124,7 @@ func runAndLog(ctx context.Context, c *cfg, name string, logSuccess bool, starte starter(ctx, c) if logSuccess { - c.log.Info(fmt.Sprintf("%s service started successfully", name)) + c.log.Info(name + " service started successfully") } } @@ -138,7 +138,7 @@ func stopAndLog(c *cfg, name string, stopper func() error) { ) } - c.log.Debug(fmt.Sprintf("%s service has been stopped", name)) + c.log.Debug(name + " service has been stopped") } func bootUp(ctx context.Context, c *cfg) { diff --git a/cmd/internal/common/config/viper.go b/cmd/internal/common/config/viper.go index 41b8831ff2..f06d407c1c 100644 --- a/cmd/internal/common/config/viper.go +++ b/cmd/internal/common/config/viper.go @@ -1,6 +1,7 @@ package config import ( + "errors" "fmt" "strings" @@ -15,6 +16,8 @@ const ( EnvSeparator = "_" ) +var errProvideViperInOpts = errors.New("provide viper in opts") + func CreateViper(opts ...Option) (*viper.Viper, error) { o := defaultOpts() for i := range opts { @@ -59,7 +62,7 @@ func ReloadViper(opts ...Option) error { } if o.v == nil { - return fmt.Errorf("provide viper in opts") + return errProvideViperInOpts } if o.path != "" { diff --git a/internal/ape/converter.go b/internal/ape/converter.go index f629e262dd..2adc7645a3 100644 --- a/internal/ape/converter.go +++ b/internal/ape/converter.go @@ -18,7 +18,7 @@ func (e *ConvertEACLError) Error() string { if e == nil { return "" } - return fmt.Sprintf("failed to convert eACL table to policy engine chain: %s", e.nested.Error()) + return "failed to convert eACL table to policy engine chain: " + e.nested.Error() } func (e *ConvertEACLError) Unwrap() error { diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index a1dfc2567b..27bfd8468d 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -34,6 +34,8 @@ var ( ErrTargetNameBucketNotFound = logicerr.New("target name bucket not found") ErrBucketNotContainsChainID = logicerr.New("chain id not found in bucket") + + errChainIDIsNotSet = errors.New("chain ID is not set") ) // NewBoltLocalOverrideDatabase returns storage wrapper for storing access policy engine @@ -167,7 +169,7 @@ func getTargetBucketCreateIfEmpty(tx *bbolt.Tx, name chain.Name, target policyen func (cs *boltLocalOverrideStorage) AddOverride(name chain.Name, target policyengine.Target, c *chain.Chain) (chain.ID, error) { if len(c.ID) == 0 { - return chain.ID{}, fmt.Errorf("chain ID is not set") + return chain.ID{}, errChainIDIsNotSet } serializedChain := c.Bytes() diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index 2ad863b27d..a950997fd8 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -1,6 +1,7 @@ package container import ( + "errors" "fmt" "strings" @@ -31,6 +32,8 @@ type putContainerContext struct { d containerSDK.Domain } +var errContainerAndOwnerNamespaceDontMatch = errors.New("container and owner namespaces do not match") + // Process a new container from the user by checking the container sanity // and sending approve tx back to the morph. func (cp *Processor) processContainerPut(put putEvent) bool { @@ -193,7 +196,7 @@ func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Contain } if subject.Namespace != namespace { - return fmt.Errorf("container and owner namespaces do not match") + return errContainerAndOwnerNamespaceDontMatch } return nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 9f2950094e..be51509b6e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -2,7 +2,6 @@ package blobovniczatree import ( "errors" - "fmt" "strconv" "strings" "sync" @@ -117,7 +116,7 @@ func u64ToHexStringExt(ind uint64) string { func u64FromHexString(str string) uint64 { v, err := strconv.ParseUint(strings.TrimSuffix(str, dbExtension), 16, 64) if err != nil { - panic(fmt.Sprintf("blobovnicza name is not an index %s", str)) + panic("blobovnicza name is not an index " + str) } return v diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index ee1ab41de5..dc85b46971 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -24,6 +24,11 @@ var ( objectUserCounterKey = []byte("user_counter") ) +var ( + errInvalidKeyLenght = errors.New("invalid key length") + errInvalidValueLenght = errors.New("invalid value length") +) + type objectType uint8 const ( @@ -474,7 +479,7 @@ func containerCounterValue(entity ObjectCounters) []byte { func parseContainerCounterKey(buf []byte) (cid.ID, error) { if len(buf) != cidSize { - return cid.ID{}, fmt.Errorf("invalid key length") + return cid.ID{}, errInvalidKeyLenght } var cnrID cid.ID if err := cnrID.Decode(buf); err != nil { @@ -486,7 +491,7 @@ func parseContainerCounterKey(buf []byte) (cid.ID, error) { // parseContainerCounterValue return phy, logic values. func parseContainerCounterValue(buf []byte) (ObjectCounters, error) { if len(buf) != 24 { - return ObjectCounters{}, fmt.Errorf("invalid value length") + return ObjectCounters{}, errInvalidValueLenght } return ObjectCounters{ Phy: binary.LittleEndian.Uint64(buf), diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index e5a98ff010..e591b86616 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -20,6 +20,8 @@ import ( "go.opentelemetry.io/otel/trace" ) +var errFailedToRemoveUniqueIndexes = errors.New("can't remove unique indexes") + // DeletePrm groups the parameters of Delete operation. type DeletePrm struct { addrs []oid.Address @@ -325,7 +327,7 @@ func (db *DB) deleteObject( ) error { err := delUniqueIndexes(tx, obj, isParent) if err != nil { - return fmt.Errorf("can't remove unique indexes") + return errFailedToRemoveUniqueIndexes } err = updateListIndexes(tx, obj, delListIndexItem) diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index c04aff61c0..d46a421a3f 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -3,7 +3,7 @@ package meta import ( "bytes" "crypto/sha256" - "fmt" + "errors" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -25,6 +25,8 @@ var ( containerCounterBucketName = []byte{containerCountersPrefix} zeroValue = []byte{0xFF} + + errInvalidLength = errors.New("invalid length") ) // Prefix bytes for database keys. All ids and addresses are encoded in binary @@ -198,7 +200,7 @@ func addressKey(addr oid.Address, key []byte) []byte { // parses object address formed by addressKey. func decodeAddressFromKey(dst *oid.Address, k []byte) error { if len(k) != addressKeySize { - return fmt.Errorf("invalid length") + return errInvalidLength } var cnr cid.ID diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index 8276490b37..dbfc9dccdb 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -2,6 +2,7 @@ package pilorama import ( "context" + "errors" "fmt" "sort" "strings" @@ -10,6 +11,8 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" ) +var errInvalidKeyFormat = errors.New("invalid format: key must be cid and treeID") + // memoryForest represents multiple replicating trees sharing a single storage. type memoryForest struct { // treeMap maps tree identifier (container ID + name) to the replicated log. @@ -291,7 +294,7 @@ func (f *memoryForest) TreeListTrees(_ context.Context, prm TreeListTreesPrm) (* for idx < len(tmpSlice) { cidAndTree := strings.Split(tmpSlice[idx], "/") if len(cidAndTree) != 2 { - return nil, fmt.Errorf("invalid format: key must be cid and treeID") + return nil, errInvalidKeyFormat } var contID cid.ID if err := contID.DecodeString(cidAndTree[0]); err != nil { diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 30f51f699a..764bbc899b 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -1,12 +1,15 @@ package netmap import ( + "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" ) +var errFailedToRemovePeerWithoutNotary = errors.New("peer can be forcefully removed only in notary environment") + // AddPeerPrm groups parameters of AddPeer operation. type AddPeerPrm struct { nodeInfo netmap.NodeInfo @@ -46,7 +49,7 @@ func (c *Client) AddPeer(p AddPeerPrm) error { // If vub > 0, vub will be used as valid until block value. func (c *Client) ForceRemovePeer(nodeInfo netmap.NodeInfo, vub uint32) (uint32, error) { if !c.client.WithNotary() { - return 0, fmt.Errorf("peer can be forcefully removed only in notary environment") + return 0, errFailedToRemovePeerWithoutNotary } prm := UpdatePeerPrm{} diff --git a/pkg/network/address.go b/pkg/network/address.go index aeb6478853..88f4a571d8 100644 --- a/pkg/network/address.go +++ b/pkg/network/address.go @@ -1,6 +1,7 @@ package network import ( + "errors" "fmt" "net" "net/url" @@ -18,6 +19,8 @@ import ( URIAddr strings: "127.0.0.1:8080" */ +var errHostIsEmpty = errors.New("host is empty") + // Address represents the FrostFS node // network address. type Address struct { @@ -89,7 +92,7 @@ func (a *Address) FromString(s string) error { // multiaddrStringFromHostAddr converts "localhost:8080" to "/dns4/localhost/tcp/8080". func multiaddrStringFromHostAddr(host string) (string, error) { if len(host) == 0 { - return "", fmt.Errorf("host is empty") + return "", errHostIsEmpty } endpoint, port, err := net.SplitHostPort(host) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index c01ad8a1d4..83361257ad 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -41,6 +41,8 @@ var ( errEmptyBodySignature = errors.New("malformed request: empty body signature") errMissingOwnerID = errors.New("malformed request: missing owner ID") errSubjectNotFound = errors.New("subject not found") + errOwnerIDIsNotSet = errors.New("owner id is not set") + errInvalidDomainZone = errors.New("invalid domain zone: no namespace is expected") undefinedContainerID = cid.ID{} ) @@ -566,7 +568,7 @@ func isContainerNode(nm *netmapSDK.NetMap, pk, binCnrID []byte, cont *containerc func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { var ownerSDK user.ID if owner == nil { - return "", fmt.Errorf("owner id is not set") + return "", errOwnerIDIsNotSet } if err := ownerSDK.ReadFromV2(*owner); err != nil { return "", err @@ -603,7 +605,7 @@ func validateNamespace(cnrV2 *container.Container, ownerIDNamespace string) erro if hasNamespace { if cntNamespace != ownerIDNamespace { if ownerIDNamespace == "" { - return fmt.Errorf("invalid domain zone: no namespace is expected") + return errInvalidDomainZone } return fmt.Errorf("invalid domain zone: expected namespace %s, but got %s", ownerIDNamespace, cntNamespace) } diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index f1217705ee..a653fa0660 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -16,6 +16,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) +var errMissingUserID = errors.New("missing user ID") + type morphExecutor struct { rdr Reader wrt Writer @@ -177,7 +179,7 @@ func (s *morphExecutor) Get(_ context.Context, body *container.GetRequestBody) ( func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) (*container.ListResponseBody, error) { idV2 := body.GetOwnerID() if idV2 == nil { - return nil, fmt.Errorf("missing user ID") + return nil, errMissingUserID } var id user.ID diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 58610b0d1b..2447a8a749 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -121,7 +121,7 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer if len(req.GetBody().GetContainerId()) > 0 { var containerID cid.ID if err := containerID.Decode(req.GetBody().GetContainerId()); err != nil { - return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to parse container ID: %s", err.Error())) + return nil, status.Error(codes.InvalidArgument, "failed to parse container ID: "+err.Error()) } var err error vub, err = s.removeContainer(containerID, req.GetBody().GetVub()) @@ -131,11 +131,11 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer } else { var ownerID refs.OwnerID if err := ownerID.Unmarshal(req.GetBody().GetOwner()); err != nil { - return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to parse ownerID: %s", err.Error())) + return nil, status.Error(codes.InvalidArgument, "failed to parse ownerID: %s"+err.Error()) } var owner user.ID if err := owner.ReadFromV2(ownerID); err != nil { - return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("failed to read owner: %s", err.Error())) + return nil, status.Error(codes.InvalidArgument, "failed to read owner: "+err.Error()) } cids, err := s.containerClient.ContainersOf(&owner) diff --git a/pkg/services/control/server/convert.go b/pkg/services/control/server/convert.go index 4f3132356b..61d7e41c1f 100644 --- a/pkg/services/control/server/convert.go +++ b/pkg/services/control/server/convert.go @@ -1,7 +1,6 @@ package control import ( - "fmt" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" @@ -16,7 +15,7 @@ func stateToResponse(state *engine.EvacuationState) (*control.GetShardEvacuation for _, shID := range state.ShardIDs() { id, err := base58.Decode(shID) if err != nil { - return nil, status.Error(codes.Internal, fmt.Sprintf("invalid shard id format: %s", shID)) + return nil, status.Error(codes.Internal, "invalid shard id format: "+shID) } shardIDs = append(shardIDs, id) } diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 99082b30dc..462ab211ec 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -23,6 +23,8 @@ import ( "google.golang.org/grpc/status" ) +var errFailedToBuildListOfContainerNodes = errors.New("can't build a list of container nodes") + func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRequest) (*control.EvacuateShardResponse, error) { err := s.isValidRequest(req) if err != nil { @@ -157,7 +159,7 @@ func (s *Server) getContainerNodes(contID cid.ID) ([]netmap.NodeInfo, error) { ns, err := nm.ContainerNodes(c.Value.PlacementPolicy(), binCnr) if err != nil { - return nil, fmt.Errorf("can't build a list of container nodes") + return nil, errFailedToBuildListOfContainerNodes } nodes := placement.FlattenNodes(ns) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 13b2729e91..13dab0ec7f 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -2,6 +2,7 @@ package ape import ( "context" + "errors" "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" @@ -50,7 +51,7 @@ type Prm struct { SoftAPECheck bool } -var errMissingOID = fmt.Errorf("object ID is not set") +var errMissingOID = errors.New("object ID is not set") // CheckAPE checks if a request or a response is permitted creating an ape request and passing // it to chain router. diff --git a/pkg/services/object/ape/errors.go b/pkg/services/object/ape/errors.go index 7c2a82dfdf..1b2024ed5c 100644 --- a/pkg/services/object/ape/errors.go +++ b/pkg/services/object/ape/errors.go @@ -1,13 +1,11 @@ package ape import ( - "fmt" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) func toStatusErr(err error) error { errAccessDenied := &apistatus.ObjectAccessDenied{} - errAccessDenied.WriteReason(fmt.Sprintf("ape denied request: %s", err.Error())) + errAccessDenied.WriteReason("ape denied request: " + err.Error()) return errAccessDenied } diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index f05bdaa835..cc18a0bcf9 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -3,6 +3,7 @@ package ape import ( "context" "encoding/hex" + "errors" "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" @@ -16,6 +17,8 @@ import ( nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) +var errFailedToCastToRequestContext = errors.New("failed cast to RequestContext") + type Service struct { log *logger.Logger @@ -101,7 +104,7 @@ func requestContext(ctx context.Context) (*objectSvc.RequestContext, error) { } rc, ok := untyped.(*objectSvc.RequestContext) if !ok { - return nil, fmt.Errorf("failed cast to RequestContext") + return nil, errFailedToCastToRequestContext } return rc, nil } diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 183b2310d0..09e1eb092a 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -32,6 +32,8 @@ import ( "go.uber.org/zap" ) +var errInvalidPayloadChecksum = errors.New("incorrect payload checksum") + type putSingleRequestSigner struct { req *objectAPI.PutSingleRequest keyStorage *svcutil.KeyStorage @@ -125,7 +127,7 @@ func (s *Service) validatePutSingleChecksum(obj *objectSDK.Object) error { } if !bytes.Equal(hash.Sum(nil), cs.Value()) { - return fmt.Errorf("incorrect payload checksum") + return errInvalidPayloadChecksum } return nil diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go index 7c3d2f1d2a..fe4ad1c3e3 100644 --- a/pkg/util/sdnotify/sdnotify.go +++ b/pkg/util/sdnotify/sdnotify.go @@ -1,6 +1,7 @@ package sdnotify import ( + "errors" "fmt" "net" "os" @@ -13,14 +14,19 @@ const ( ReloadingEnabled = "RELOADING=1" ) -var socket *net.UnixAddr +var ( + socket *net.UnixAddr + + errSocketVariableIsNotPresent = errors.New("\"NOTIFY_SOCKET\" environment variable is not present") + errSocketIsNotInitialized = errors.New("socket is not initialized") +) // Initializes socket with provided name of // environment variable. func InitSocket() error { notifySocket := os.Getenv("NOTIFY_SOCKET") if notifySocket == "" { - return fmt.Errorf("\"NOTIFY_SOCKET\" environment variable is not present") + return errSocketVariableIsNotPresent } socket = &net.UnixAddr{ Name: notifySocket, @@ -38,14 +44,14 @@ func FlagAndStatus(status string) error { // Status sends systemd notify STATUS=%s{status}. func Status(status string) error { - return Send(fmt.Sprintf("STATUS=%s", status)) + return Send("STATUS=" + status) } // Send state through the notify socket if any. // If the notify socket was not detected, it returns an error. func Send(state string) error { if socket == nil { - return fmt.Errorf("socket is not initialized") + return errSocketIsNotInitialized } conn, err := net.DialUnix(socket.Net, nil, socket) if err != nil { From 3195142d671a38ba4b4080f4369fbb4b66f6bb26 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 20 Feb 2024 17:24:57 +0300 Subject: [PATCH 0429/1413] [#959] writecache: Avoid manipulation with cache in `DEGRADED` mode Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/writecache/delete.go | 4 ++++ pkg/local_object_storage/writecache/flush.go | 5 ++++- pkg/local_object_storage/writecache/get.go | 16 ++++++++++++++++ pkg/local_object_storage/writecache/mode.go | 6 ++++++ pkg/local_object_storage/writecache/put.go | 3 +++ .../writecache/writecache.go | 2 ++ 6 files changed, 35 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/writecache/delete.go b/pkg/local_object_storage/writecache/delete.go index cedb9f4aed..b1a0511ee8 100644 --- a/pkg/local_object_storage/writecache/delete.go +++ b/pkg/local_object_storage/writecache/delete.go @@ -19,6 +19,7 @@ import ( // // Returns an error of type apistatus.ObjectNotFound if object is missing in write-cache. // Returns ErrNotInitialized if write-cache has not been initialized yet. +// Returns ErrDegraded if write-cache is in DEGRADED mode. func (c *cache) Delete(ctx context.Context, addr oid.Address) error { ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Delete", trace.WithAttributes( @@ -40,6 +41,9 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { if c.readOnly() { return ErrReadOnly } + if c.noMetabase() { + return ErrDegraded + } saddr := addr.EncodeToString() diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index c4e4b3b34a..c3e19c4d26 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -155,7 +155,7 @@ func (c *cache) workerFlushBig(ctx context.Context) { select { case <-tick.C: c.modeMtx.RLock() - if c.readOnly() { + if c.readOnly() || c.noMetabase() { c.modeMtx.RUnlock() break } @@ -281,6 +281,9 @@ func (c *cache) Flush(ctx context.Context, ignoreErrors, seal bool) error { c.modeMtx.Lock() // exclusive lock to not to conflict with background flush defer c.modeMtx.Unlock() + if c.noMetabase() { + return ErrDegraded + } if err := c.flush(ctx, ignoreErrors); err != nil { return err diff --git a/pkg/local_object_storage/writecache/get.go b/pkg/local_object_storage/writecache/get.go index 5194446ec1..bf26833bd8 100644 --- a/pkg/local_object_storage/writecache/get.go +++ b/pkg/local_object_storage/writecache/get.go @@ -29,6 +29,14 @@ func (c *cache) Get(ctx context.Context, addr oid.Address) (*objectSDK.Object, e )) defer span.End() + if !c.modeMtx.TryRLock() { + return nil, ErrNotInitialized + } + defer c.modeMtx.RUnlock() + if c.mode.NoMetabase() { + return nil, ErrDegraded + } + obj, err := c.getInternal(ctx, saddr, addr) return obj, metaerr.Wrap(err) } @@ -71,6 +79,14 @@ func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, )) defer span.End() + if !c.modeMtx.TryRLock() { + return nil, ErrNotInitialized + } + defer c.modeMtx.RUnlock() + if c.mode.NoMetabase() { + return nil, ErrDegraded + } + obj, err := c.getInternal(ctx, saddr, addr) if err != nil { return nil, metaerr.Wrap(err) diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index 7c6439fe9b..a10e593aa6 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -76,3 +76,9 @@ func (c *cache) setMode(ctx context.Context, m mode.Mode, ignoreErrors bool) err func (c *cache) readOnly() bool { return c.mode.ReadOnly() } + +// noMetabase returns true if c is operating without the metabase. +// `c.modeMtx` must be taken. +func (c *cache) noMetabase() bool { + return c.mode.NoMetabase() +} diff --git a/pkg/local_object_storage/writecache/put.go b/pkg/local_object_storage/writecache/put.go index 8b6c09e9ad..0e419f95b0 100644 --- a/pkg/local_object_storage/writecache/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -41,6 +41,9 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro if c.readOnly() { return common.PutRes{}, ErrReadOnly } + if c.noMetabase() { + return common.PutRes{}, ErrDegraded + } sz := uint64(len(prm.RawData)) if sz > c.maxObjectSize { diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 112594ec09..71dba61cf0 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -59,6 +59,8 @@ type Metabase interface { var ( // ErrReadOnly is returned when Put/Write is performed in a read-only mode. ErrReadOnly = logicerr.New("write-cache is in read-only mode") + // ErrDegraded is returned when writecache is in degraded mode. + ErrDegraded = logicerr.New("write-cache is in degraded mode") // ErrNotInitialized is returned when write-cache is initializing. ErrNotInitialized = logicerr.New("write-cache is not initialized yet") // ErrBigObject is returned when object is too big to be placed in cache. From d9fe63ee03388d80480f8c5ecdb0a747cb01e136 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Mar 2024 10:16:18 +0300 Subject: [PATCH 0430/1413] [#1036] help.mk: Fix target regexp pattern We use no space before the colon, but we use it when declaring a variable. Signed-off-by: Evgenii Stratonikov --- help.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/help.mk b/help.mk index c065ec862d..21408cf171 100644 --- a/help.mk +++ b/help.mk @@ -8,4 +8,4 @@ help: @echo '' @echo ' Targets:' @echo '' - @awk '/^#/{ comment = substr($$0,3) } comment && /^[a-zA-Z][a-zA-Z0-9_-]+ ?:/{ print " ", $$1, comment }' $(MAKEFILE_LIST) | column -t -s ':' | grep -v 'IGNORE' | sort | uniq + @awk '/^#/{ comment = substr($$0,3) } comment && /^[a-zA-Z][a-zA-Z0-9_-]+:/{ print " ", $$1, comment }' $(MAKEFILE_LIST) | column -t -s ':' | grep -v 'IGNORE' | sort | uniq From aa27596d779b195631684a00a4293386b7dc1af7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Mar 2024 10:19:41 +0300 Subject: [PATCH 0431/1413] [#1036] help.mk: Print target without comments Make it easy to notice missing comments and avoid reusing comment from some other place. Signed-off-by: Evgenii Stratonikov --- help.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/help.mk b/help.mk index 21408cf171..a2ac989dcb 100644 --- a/help.mk +++ b/help.mk @@ -8,4 +8,4 @@ help: @echo '' @echo ' Targets:' @echo '' - @awk '/^#/{ comment = substr($$0,3) } comment && /^[a-zA-Z][a-zA-Z0-9_-]+:/{ print " ", $$1, comment }' $(MAKEFILE_LIST) | column -t -s ':' | grep -v 'IGNORE' | sort | uniq + @awk '/^#/{ comment = substr($$0,3) } /^[a-zA-Z][a-zA-Z0-9_-]+:/{ print " ", $$1, comment; comment = "" }' $(MAKEFILE_LIST) | column -t -s ':' | grep -v 'IGNORE' | sort | uniq From 6eb63cf5c7b1a2d32c63cddb51a6d67074fa4852 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Mar 2024 10:24:35 +0300 Subject: [PATCH 0432/1413] [#1036] Makefile: Add missing comments Signed-off-by: Evgenii Stratonikov --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile b/Makefile index 493ef25e57..21d7d42751 100755 --- a/Makefile +++ b/Makefile @@ -115,6 +115,7 @@ protoc: --go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \ done +# Install protoc protoc-install: @rm -rf $(PROTOBUF_DIR) @mkdir $(PROTOBUF_DIR) @@ -161,6 +162,7 @@ imports: @echo "⇒ Processing goimports check" @goimports -w cmd/ pkg/ misc/ +# Run gofumpt fumpt: @echo "⇒ Processing gofumpt check" @gofumpt -l -w cmd/ pkg/ misc/ @@ -170,6 +172,7 @@ test: @echo "⇒ Running go test" @go test ./... -count=1 +# Run pre-commit pre-commit-run: @pre-commit run -a --hook-stage manual @@ -205,11 +208,13 @@ staticcheck-run: fi @$(STATICCHECK_VERSION_DIR)/staticcheck ./... +# Install gopls gopls-install: @rm -rf $(GOPLS_DIR) @mkdir $(GOPLS_DIR) @GOBIN=$(GOPLS_VERSION_DIR) go install golang.org/x/tools/gopls@$(GOPLS_VERSION) +# Run gopls gopls-run: @if [ ! -d "$(GOPLS_VERSION_DIR)" ]; then \ make gopls-install; \ @@ -253,13 +258,16 @@ debpackage: "Please see CHANGELOG.md for code changes for $(VERSION)" dpkg-buildpackage --no-sign -b +# Cleanup deb package build directories debclean: dh clean +# Download locode database locode-download: @wget -q -O ./.cache/locode_db.gz 'https://git.frostfs.info/TrueCloudLab/frostfs-locode-db/releases/download/${LOCODE_DB_VERSION}/locode_db.gz' gzip -dfk ./.cache/locode_db.gz +# Start dev environment env-up: all docker compose -f dev/docker-compose.yml up -d @if [ ! -d "$(FROSTFS_CONTRACTS_PATH)" ]; then \ @@ -271,6 +279,7 @@ env-up: all make locode-download; \ fi +# Shutdown dev environment env-down: docker compose -f dev/docker-compose.yml down docker volume rm -f frostfs-node_neo-go From b4cb54e7ed83c1595129aa29e89db2d003707567 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 29 Feb 2024 18:31:04 +0300 Subject: [PATCH 0433/1413] [#963] node: Go on initialization even deposit notary is hung * Make makeAndWaitNotaryDeposit run asynchronously as worker during application boot-up. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 6 ++++++ cmd/frostfs-node/main.go | 16 ++++++++++++++-- cmd/frostfs-node/morph.go | 2 ++ internal/logs/logs.go | 2 ++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 48b76ac0f9..40fa34a956 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -352,6 +352,12 @@ type internals struct { log *logger.Logger + // Some methods that initialize node components may launch an asynchronous job, + // appending it to workers. That means despite application is already running, + // not all components completely initialized yet. + // initAppWG is used to control this situation. + initAppWG sync.WaitGroup + wg sync.WaitGroup workers []worker closers []closer diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index e1eeb6861d..f82b2f171a 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -67,7 +67,10 @@ func main() { bootUp(ctx, c) - c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY) + go func() { + c.initAppWG.Wait() + c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY) + }() wait(c) } @@ -144,7 +147,16 @@ func stopAndLog(c *cfg, name string, stopper func() error) { func bootUp(ctx context.Context, c *cfg) { runAndLog(ctx, c, "NATS", true, connectNats) runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(c) }) - runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit) + + // It may happen that boot-up waits for the execution of a notary deposit transaction + // and waiting loop may hang for an indefinite time. In this case, we need to let + // frostfs-node go on initialization, although its functionality will be available partially. + // That's why makeAndWaitNotaryDeposit is run asynchroniosly. + c.initAppWG.Add(1) + c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { + defer c.initAppWG.Done() + runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit) + })) bootstrapNode(c) startWorkers(ctx, c) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 698fb3b832..1b148095bd 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -158,6 +158,7 @@ var ( func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { for i := 0; i < notaryDepositRetriesAmount; i++ { + c.log.Debug(logs.ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted) select { case <-ctx.Done(): return ctx.Err() @@ -167,6 +168,7 @@ func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { ok, err := c.cfgMorph.client.TxHalt(tx) if err == nil { if ok { + c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) return nil } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 6b48940b78..bd8b8ed018 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -158,6 +158,8 @@ const ( ClientNotaryDepositInvoke = "notary deposit invoke" ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked" ClientNotaryRequestInvoked = "notary request invoked" + ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted" + ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted = "attempt to wait for notary deposit transaction to get persisted" ClientNeoClientInvoke = "neo client invoke" ClientNativeGasTransferInvoke = "native gas transfer invoke" ClientBatchGasTransferInvoke = "batch gas transfer invoke" From 5c252c9193f638eacce54b580fa7a6493e1651c7 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 12 Mar 2024 15:09:55 +0300 Subject: [PATCH 0434/1413] [#1039] object: Skip APE check for certain request roles * Skip APE check if a role is Container. * Skip APE check if a role is IR and methods are get-like. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/checker.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 13dab0ec7f..1d42d21d45 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -10,6 +10,7 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) type checkerImpl struct { @@ -56,6 +57,21 @@ var errMissingOID = errors.New("object ID is not set") // CheckAPE checks if a request or a response is permitted creating an ape request and passing // it to chain router. func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { + // APE check is ignored for some inter-node requests. + if prm.Role == nativeschema.PropertyValueContainerRoleContainer { + return nil + } else if prm.Role == nativeschema.PropertyValueContainerRoleIR { + switch prm.Method { + case nativeschema.MethodGetObject, + nativeschema.MethodHeadObject, + nativeschema.MethodSearchObject, + nativeschema.MethodRangeObject, + nativeschema.MethodHashObject: + return nil + default: + } + } + r, err := c.newAPERequest(ctx, prm) if err != nil { return fmt.Errorf("failed to create ape request: %w", err) From e3579922d83eef1560779ba02addd2d1cf6ca021 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Mar 2024 12:51:05 +0300 Subject: [PATCH 0435/1413] [#1038] pre-commit: Remove gitlint Signed-off-by: Evgenii Stratonikov --- .gitlint | 11 ----------- .pre-commit-config.yaml | 7 ------- 2 files changed, 18 deletions(-) delete mode 100644 .gitlint diff --git a/.gitlint b/.gitlint deleted file mode 100644 index e7218ac53a..0000000000 --- a/.gitlint +++ /dev/null @@ -1,11 +0,0 @@ -[general] -fail-without-commits=True -regex-style-search=True -contrib=CC1 - -[title-match-regex] -regex=^\[\#[0-9Xx]+\]\s - -[ignore-by-title] -regex=^Release(.*) -ignore=title-match-regex diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f66adda0bb..f1d43ab0a6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,13 +2,6 @@ ci: autofix_prs: false repos: - - repo: https://github.com/jorisroovers/gitlint - rev: v0.19.1 - hooks: - - id: gitlint - stages: [commit-msg] - - id: gitlint-ci - - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: From 179b6e64faf8f4177c765321114eb620bce4e1e5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Mar 2024 13:07:08 +0300 Subject: [PATCH 0436/1413] [#1038] Makefile: Allow to override testflags Signed-off-by: Evgenii Stratonikov --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 21d7d42751..4d3c121bfd 100755 --- a/Makefile +++ b/Makefile @@ -168,9 +168,10 @@ fumpt: @gofumpt -l -w cmd/ pkg/ misc/ # Run Unit Test with go test +test: GOFLAGS ?= "-count=1" test: @echo "⇒ Running go test" - @go test ./... -count=1 + @GOFLAGS="$(GOFLAGS)" go test ./... # Run pre-commit pre-commit-run: From f42a529f49b7b19f5b360cc4057c3f5c365978b5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 12 Mar 2024 13:08:09 +0300 Subject: [PATCH 0437/1413] [#1038] pre-commit: Use cached tests in hook Signed-off-by: Evgenii Stratonikov --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f1d43ab0a6..13284b9c54 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: hooks: - id: go-unit-tests name: go unit tests - entry: make test + entry: make test GOFLAGS='' pass_filenames: false types: [go] language: system From 7a4b6057cebb85ac93cd5b2f0bd60563c229db9b Mon Sep 17 00:00:00 2001 From: aarifullin Date: Wed, 13 Mar 2024 11:53:59 +0300 Subject: [PATCH 0438/1413] Revert "[#963] node: Go on initialization even deposit notary is hung" This reverts commit b4cb54e7ed83c1595129aa29e89db2d003707567. Signed-off-by: aarifullin --- cmd/frostfs-node/config.go | 6 ------ cmd/frostfs-node/main.go | 16 ++-------------- cmd/frostfs-node/morph.go | 2 -- internal/logs/logs.go | 2 -- 4 files changed, 2 insertions(+), 24 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 40fa34a956..48b76ac0f9 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -352,12 +352,6 @@ type internals struct { log *logger.Logger - // Some methods that initialize node components may launch an asynchronous job, - // appending it to workers. That means despite application is already running, - // not all components completely initialized yet. - // initAppWG is used to control this situation. - initAppWG sync.WaitGroup - wg sync.WaitGroup workers []worker closers []closer diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index f82b2f171a..e1eeb6861d 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -67,10 +67,7 @@ func main() { bootUp(ctx, c) - go func() { - c.initAppWG.Wait() - c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY) - }() + c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY) wait(c) } @@ -147,16 +144,7 @@ func stopAndLog(c *cfg, name string, stopper func() error) { func bootUp(ctx context.Context, c *cfg) { runAndLog(ctx, c, "NATS", true, connectNats) runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(c) }) - - // It may happen that boot-up waits for the execution of a notary deposit transaction - // and waiting loop may hang for an indefinite time. In this case, we need to let - // frostfs-node go on initialization, although its functionality will be available partially. - // That's why makeAndWaitNotaryDeposit is run asynchroniosly. - c.initAppWG.Add(1) - c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { - defer c.initAppWG.Done() - runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit) - })) + runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit) bootstrapNode(c) startWorkers(ctx, c) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 1b148095bd..698fb3b832 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -158,7 +158,6 @@ var ( func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { for i := 0; i < notaryDepositRetriesAmount; i++ { - c.log.Debug(logs.ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted) select { case <-ctx.Done(): return ctx.Err() @@ -168,7 +167,6 @@ func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { ok, err := c.cfgMorph.client.TxHalt(tx) if err == nil { if ok { - c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) return nil } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index bd8b8ed018..6b48940b78 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -158,8 +158,6 @@ const ( ClientNotaryDepositInvoke = "notary deposit invoke" ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked" ClientNotaryRequestInvoked = "notary request invoked" - ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted" - ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted = "attempt to wait for notary deposit transaction to get persisted" ClientNeoClientInvoke = "neo client invoke" ClientNativeGasTransferInvoke = "native gas transfer invoke" ClientBatchGasTransferInvoke = "batch gas transfer invoke" From d1d53d2bb686b081a038f3ae11db294df3abdadc Mon Sep 17 00:00:00 2001 From: aarifullin Date: Wed, 13 Mar 2024 11:57:51 +0300 Subject: [PATCH 0439/1413] [#963] node: Add logging for waitNotaryDeposit Signed-off-by: Airat Arifullin --- cmd/frostfs-node/morph.go | 2 ++ internal/logs/logs.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 698fb3b832..1b148095bd 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -158,6 +158,7 @@ var ( func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { for i := 0; i < notaryDepositRetriesAmount; i++ { + c.log.Debug(logs.ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted) select { case <-ctx.Done(): return ctx.Err() @@ -167,6 +168,7 @@ func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { ok, err := c.cfgMorph.client.TxHalt(tx) if err == nil { if ok { + c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) return nil } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 6b48940b78..bd8b8ed018 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -158,6 +158,8 @@ const ( ClientNotaryDepositInvoke = "notary deposit invoke" ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked" ClientNotaryRequestInvoked = "notary request invoked" + ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted" + ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted = "attempt to wait for notary deposit transaction to get persisted" ClientNeoClientInvoke = "neo client invoke" ClientNativeGasTransferInvoke = "native gas transfer invoke" ClientBatchGasTransferInvoke = "batch gas transfer invoke" From 926cdeb0728a1982e96447642093b08a6ef62a4a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 12 Mar 2024 18:41:52 +0300 Subject: [PATCH 0440/1413] [#1043] services: Regenerate proto Signed-off-by: Dmitrii Stepanov --- pkg/services/control/ir/service.pb.go | 2 +- pkg/services/control/ir/types.pb.go | 2 +- pkg/services/control/service.pb.go | 2 +- pkg/services/control/types.pb.go | 2 +- pkg/services/tree/service.pb.go | 2 +- pkg/services/tree/types.pb.go | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/services/control/ir/service.pb.go b/pkg/services/control/ir/service.pb.go index 7dc8f3affa..d1e253bf5b 100644 --- a/pkg/services/control/ir/service.pb.go +++ b/pkg/services/control/ir/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 +// protoc-gen-go v1.33.0 // protoc v4.25.0 // source: pkg/services/control/ir/service.proto diff --git a/pkg/services/control/ir/types.pb.go b/pkg/services/control/ir/types.pb.go index 819cedf6a5..828814b250 100644 --- a/pkg/services/control/ir/types.pb.go +++ b/pkg/services/control/ir/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 +// protoc-gen-go v1.33.0 // protoc v4.25.0 // source: pkg/services/control/ir/types.proto diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index c24bc15972..261065b585 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 +// protoc-gen-go v1.33.0 // protoc v4.25.0 // source: pkg/services/control/service.proto diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index 4556e8a555..2fc16a9263 100644 --- a/pkg/services/control/types.pb.go +++ b/pkg/services/control/types.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 +// protoc-gen-go v1.33.0 // protoc v4.25.0 // source: pkg/services/control/types.proto diff --git a/pkg/services/tree/service.pb.go b/pkg/services/tree/service.pb.go index 441ae79272..7930361e17 100644 --- a/pkg/services/tree/service.pb.go +++ b/pkg/services/tree/service.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 +// protoc-gen-go v1.33.0 // protoc v4.25.0 // source: pkg/services/tree/service.proto diff --git a/pkg/services/tree/types.pb.go b/pkg/services/tree/types.pb.go index e44ac55666..6464ccb776 100644 --- a/pkg/services/tree/types.pb.go +++ b/pkg/services/tree/types.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 +// protoc-gen-go v1.33.0 // protoc v4.25.0 // source: pkg/services/tree/types.proto From 31e2396a5f59990fa5a135dcd6b28e23f603b693 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 12 Mar 2024 18:57:38 +0300 Subject: [PATCH 0441/1413] [#1043] control: Add ResetEvacuationStatus implementation Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 10 + .../engine/evacuate_limiter.go | 15 + .../engine/evacuate_test.go | 12 + pkg/services/control/server/evacuate_async.go | 26 + pkg/services/control/service.pb.go | 1646 ++++++++++------- pkg/services/control/service.proto | 19 + pkg/services/control/service_frostfs.pb.go | 154 ++ pkg/services/control/service_grpc.pb.go | 77 +- 8 files changed, 1254 insertions(+), 705 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 45600fe666..81fe47e657 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -733,3 +733,13 @@ func (e *StorageEngine) EnqueRunningEvacuationStop(ctx context.Context) error { return e.evacuateLimiter.CancelIfRunning() } + +func (e *StorageEngine) ResetEvacuationStatus(ctx context.Context) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + return e.evacuateLimiter.ResetEvacuationStatus() +} diff --git a/pkg/local_object_storage/engine/evacuate_limiter.go b/pkg/local_object_storage/engine/evacuate_limiter.go index 63960e238a..1e6b9ccb1f 100644 --- a/pkg/local_object_storage/engine/evacuate_limiter.go +++ b/pkg/local_object_storage/engine/evacuate_limiter.go @@ -204,3 +204,18 @@ func (l *evacuationLimiter) CancelIfRunning() error { l.cancel() return nil } + +func (l *evacuationLimiter) ResetEvacuationStatus() error { + l.guard.Lock() + defer l.guard.Unlock() + + if l.state.processState == EvacuateProcessStateRunning { + return logicerr.New("there is running evacuation task") + } + + l.state = EvacuationState{} + l.eg = nil + l.cancel = nil + + return nil +} diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 32582cd2a4..e8d9a449f5 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -386,6 +386,8 @@ func TestEvacuateObjectsAsync(t *testing.T) { require.ElementsMatch(t, expectedShardIDs, st.ShardIDs(), "invalid running shard ids") require.Equal(t, "", st.ErrorMessage(), "invalid init error message") + require.Error(t, e.ResetEvacuationStatus(context.Background())) + close(blocker) require.Eventually(t, func() bool { @@ -401,6 +403,16 @@ func TestEvacuateObjectsAsync(t *testing.T) { require.Equal(t, "", st.ErrorMessage(), "invalid final error message") require.NoError(t, eg.Wait()) + + require.NoError(t, e.ResetEvacuationStatus(context.Background())) + st, err = e.GetEvacuationState(context.Background()) + require.NoError(t, err, "get state after reset failed") + require.Equal(t, EvacuateProcessStateUndefined, st.ProcessingStatus(), "invalid state after reset") + require.Equal(t, uint64(0), st.ObjectsEvacuated(), "invalid count after reset") + require.Nil(t, st.StartedAt(), "invalid started at after reset") + require.Nil(t, st.FinishedAt(), "invalid finished at after reset") + require.ElementsMatch(t, []string{}, st.ShardIDs(), "invalid shard ids after reset") + require.Equal(t, "", st.ErrorMessage(), "invalid error message after reset") } func TestEvacuateTreesLocal(t *testing.T) { diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index cd7e8a2c78..42ae2635b9 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -102,3 +102,29 @@ func (s *Server) StopShardEvacuation(ctx context.Context, req *control.StopShard } return resp, nil } + +func (s *Server) ResetShardEvacuationStatus(ctx context.Context, req *control.ResetShardEvacuationStatusRequest) (*control.ResetShardEvacuationStatusResponse, error) { + err := s.isValidRequest(req) + if err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + err = s.s.ResetEvacuationStatus(ctx) + if err != nil { + var logicalErr logicerr.Logical + if errors.As(err, &logicalErr) { + return nil, status.Error(codes.Aborted, err.Error()) + } + return nil, status.Error(codes.Internal, err.Error()) + } + + resp := &control.ResetShardEvacuationStatusResponse{ + Body: &control.ResetShardEvacuationStatusResponse_Body{}, + } + + err = SignMessage(s.key, resp) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return resp, nil +} diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 261065b585..5866197672 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -1375,6 +1375,118 @@ func (x *GetShardEvacuationStatusResponse) GetSignature() *Signature { return nil } +// ResetShardEvacuationStatus request. +type ResetShardEvacuationStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *ResetShardEvacuationStatusRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *ResetShardEvacuationStatusRequest) Reset() { + *x = ResetShardEvacuationStatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResetShardEvacuationStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResetShardEvacuationStatusRequest) ProtoMessage() {} + +func (x *ResetShardEvacuationStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResetShardEvacuationStatusRequest.ProtoReflect.Descriptor instead. +func (*ResetShardEvacuationStatusRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22} +} + +func (x *ResetShardEvacuationStatusRequest) GetBody() *ResetShardEvacuationStatusRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ResetShardEvacuationStatusRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +// ResetShardEvacuationStatus response. +type ResetShardEvacuationStatusResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *ResetShardEvacuationStatusResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *ResetShardEvacuationStatusResponse) Reset() { + *x = ResetShardEvacuationStatusResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResetShardEvacuationStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResetShardEvacuationStatusResponse) ProtoMessage() {} + +func (x *ResetShardEvacuationStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResetShardEvacuationStatusResponse.ProtoReflect.Descriptor instead. +func (*ResetShardEvacuationStatusResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23} +} + +func (x *ResetShardEvacuationStatusResponse) GetBody() *ResetShardEvacuationStatusResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *ResetShardEvacuationStatusResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + // StopShardEvacuation request. type StopShardEvacuationRequest struct { state protoimpl.MessageState @@ -1388,7 +1500,7 @@ type StopShardEvacuationRequest struct { func (x *StopShardEvacuationRequest) Reset() { *x = StopShardEvacuationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[22] + mi := &file_pkg_services_control_service_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1401,7 +1513,7 @@ func (x *StopShardEvacuationRequest) String() string { func (*StopShardEvacuationRequest) ProtoMessage() {} func (x *StopShardEvacuationRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[22] + mi := &file_pkg_services_control_service_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1414,7 +1526,7 @@ func (x *StopShardEvacuationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopShardEvacuationRequest.ProtoReflect.Descriptor instead. func (*StopShardEvacuationRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24} } func (x *StopShardEvacuationRequest) GetBody() *StopShardEvacuationRequest_Body { @@ -1444,7 +1556,7 @@ type StopShardEvacuationResponse struct { func (x *StopShardEvacuationResponse) Reset() { *x = StopShardEvacuationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[23] + mi := &file_pkg_services_control_service_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1457,7 +1569,7 @@ func (x *StopShardEvacuationResponse) String() string { func (*StopShardEvacuationResponse) ProtoMessage() {} func (x *StopShardEvacuationResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[23] + mi := &file_pkg_services_control_service_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1470,7 +1582,7 @@ func (x *StopShardEvacuationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StopShardEvacuationResponse.ProtoReflect.Descriptor instead. func (*StopShardEvacuationResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25} } func (x *StopShardEvacuationResponse) GetBody() *StopShardEvacuationResponse_Body { @@ -1500,7 +1612,7 @@ type AddChainLocalOverrideRequest struct { func (x *AddChainLocalOverrideRequest) Reset() { *x = AddChainLocalOverrideRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[24] + mi := &file_pkg_services_control_service_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1513,7 +1625,7 @@ func (x *AddChainLocalOverrideRequest) String() string { func (*AddChainLocalOverrideRequest) ProtoMessage() {} func (x *AddChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[24] + mi := &file_pkg_services_control_service_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1526,7 +1638,7 @@ func (x *AddChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddChainLocalOverrideRequest.ProtoReflect.Descriptor instead. func (*AddChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26} } func (x *AddChainLocalOverrideRequest) GetBody() *AddChainLocalOverrideRequest_Body { @@ -1556,7 +1668,7 @@ type AddChainLocalOverrideResponse struct { func (x *AddChainLocalOverrideResponse) Reset() { *x = AddChainLocalOverrideResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[25] + mi := &file_pkg_services_control_service_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1569,7 +1681,7 @@ func (x *AddChainLocalOverrideResponse) String() string { func (*AddChainLocalOverrideResponse) ProtoMessage() {} func (x *AddChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[25] + mi := &file_pkg_services_control_service_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1582,7 +1694,7 @@ func (x *AddChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddChainLocalOverrideResponse.ProtoReflect.Descriptor instead. func (*AddChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27} } func (x *AddChainLocalOverrideResponse) GetBody() *AddChainLocalOverrideResponse_Body { @@ -1612,7 +1724,7 @@ type GetChainLocalOverrideRequest struct { func (x *GetChainLocalOverrideRequest) Reset() { *x = GetChainLocalOverrideRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[26] + mi := &file_pkg_services_control_service_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1625,7 +1737,7 @@ func (x *GetChainLocalOverrideRequest) String() string { func (*GetChainLocalOverrideRequest) ProtoMessage() {} func (x *GetChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[26] + mi := &file_pkg_services_control_service_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1638,7 +1750,7 @@ func (x *GetChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetChainLocalOverrideRequest.ProtoReflect.Descriptor instead. func (*GetChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28} } func (x *GetChainLocalOverrideRequest) GetBody() *GetChainLocalOverrideRequest_Body { @@ -1668,7 +1780,7 @@ type GetChainLocalOverrideResponse struct { func (x *GetChainLocalOverrideResponse) Reset() { *x = GetChainLocalOverrideResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[27] + mi := &file_pkg_services_control_service_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1681,7 +1793,7 @@ func (x *GetChainLocalOverrideResponse) String() string { func (*GetChainLocalOverrideResponse) ProtoMessage() {} func (x *GetChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[27] + mi := &file_pkg_services_control_service_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1694,7 +1806,7 @@ func (x *GetChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetChainLocalOverrideResponse.ProtoReflect.Descriptor instead. func (*GetChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29} } func (x *GetChainLocalOverrideResponse) GetBody() *GetChainLocalOverrideResponse_Body { @@ -1724,7 +1836,7 @@ type ListChainLocalOverridesRequest struct { func (x *ListChainLocalOverridesRequest) Reset() { *x = ListChainLocalOverridesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[28] + mi := &file_pkg_services_control_service_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1737,7 +1849,7 @@ func (x *ListChainLocalOverridesRequest) String() string { func (*ListChainLocalOverridesRequest) ProtoMessage() {} func (x *ListChainLocalOverridesRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[28] + mi := &file_pkg_services_control_service_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1750,7 +1862,7 @@ func (x *ListChainLocalOverridesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListChainLocalOverridesRequest.ProtoReflect.Descriptor instead. func (*ListChainLocalOverridesRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30} } func (x *ListChainLocalOverridesRequest) GetBody() *ListChainLocalOverridesRequest_Body { @@ -1780,7 +1892,7 @@ type ListChainLocalOverridesResponse struct { func (x *ListChainLocalOverridesResponse) Reset() { *x = ListChainLocalOverridesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[29] + mi := &file_pkg_services_control_service_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1793,7 +1905,7 @@ func (x *ListChainLocalOverridesResponse) String() string { func (*ListChainLocalOverridesResponse) ProtoMessage() {} func (x *ListChainLocalOverridesResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[29] + mi := &file_pkg_services_control_service_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1806,7 +1918,7 @@ func (x *ListChainLocalOverridesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListChainLocalOverridesResponse.ProtoReflect.Descriptor instead. func (*ListChainLocalOverridesResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31} } func (x *ListChainLocalOverridesResponse) GetBody() *ListChainLocalOverridesResponse_Body { @@ -1836,7 +1948,7 @@ type ListTargetsLocalOverridesRequest struct { func (x *ListTargetsLocalOverridesRequest) Reset() { *x = ListTargetsLocalOverridesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[30] + mi := &file_pkg_services_control_service_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1849,7 +1961,7 @@ func (x *ListTargetsLocalOverridesRequest) String() string { func (*ListTargetsLocalOverridesRequest) ProtoMessage() {} func (x *ListTargetsLocalOverridesRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[30] + mi := &file_pkg_services_control_service_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1862,7 +1974,7 @@ func (x *ListTargetsLocalOverridesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListTargetsLocalOverridesRequest.ProtoReflect.Descriptor instead. func (*ListTargetsLocalOverridesRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32} } func (x *ListTargetsLocalOverridesRequest) GetBody() *ListTargetsLocalOverridesRequest_Body { @@ -1892,7 +2004,7 @@ type ListTargetsLocalOverridesResponse struct { func (x *ListTargetsLocalOverridesResponse) Reset() { *x = ListTargetsLocalOverridesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[31] + mi := &file_pkg_services_control_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1905,7 +2017,7 @@ func (x *ListTargetsLocalOverridesResponse) String() string { func (*ListTargetsLocalOverridesResponse) ProtoMessage() {} func (x *ListTargetsLocalOverridesResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[31] + mi := &file_pkg_services_control_service_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1918,7 +2030,7 @@ func (x *ListTargetsLocalOverridesResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListTargetsLocalOverridesResponse.ProtoReflect.Descriptor instead. func (*ListTargetsLocalOverridesResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33} } func (x *ListTargetsLocalOverridesResponse) GetBody() *ListTargetsLocalOverridesResponse_Body { @@ -1947,7 +2059,7 @@ type RemoveChainLocalOverrideRequest struct { func (x *RemoveChainLocalOverrideRequest) Reset() { *x = RemoveChainLocalOverrideRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1960,7 +2072,7 @@ func (x *RemoveChainLocalOverrideRequest) String() string { func (*RemoveChainLocalOverrideRequest) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1973,7 +2085,7 @@ func (x *RemoveChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveChainLocalOverrideRequest.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34} } func (x *RemoveChainLocalOverrideRequest) GetBody() *RemoveChainLocalOverrideRequest_Body { @@ -2002,7 +2114,7 @@ type RemoveChainLocalOverrideResponse struct { func (x *RemoveChainLocalOverrideResponse) Reset() { *x = RemoveChainLocalOverrideResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2015,7 +2127,7 @@ func (x *RemoveChainLocalOverrideResponse) String() string { func (*RemoveChainLocalOverrideResponse) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2028,7 +2140,7 @@ func (x *RemoveChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveChainLocalOverrideResponse.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35} } func (x *RemoveChainLocalOverrideResponse) GetBody() *RemoveChainLocalOverrideResponse_Body { @@ -2057,7 +2169,7 @@ type SealWriteCacheRequest struct { func (x *SealWriteCacheRequest) Reset() { *x = SealWriteCacheRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2070,7 +2182,7 @@ func (x *SealWriteCacheRequest) String() string { func (*SealWriteCacheRequest) ProtoMessage() {} func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2083,7 +2195,7 @@ func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheRequest.ProtoReflect.Descriptor instead. func (*SealWriteCacheRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36} } func (x *SealWriteCacheRequest) GetBody() *SealWriteCacheRequest_Body { @@ -2112,7 +2224,7 @@ type SealWriteCacheResponse struct { func (x *SealWriteCacheResponse) Reset() { *x = SealWriteCacheResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2125,7 +2237,7 @@ func (x *SealWriteCacheResponse) String() string { func (*SealWriteCacheResponse) ProtoMessage() {} func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2138,7 +2250,7 @@ func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheResponse.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37} } func (x *SealWriteCacheResponse) GetBody() *SealWriteCacheResponse_Body { @@ -2167,7 +2279,7 @@ type DetachShardsRequest struct { func (x *DetachShardsRequest) Reset() { *x = DetachShardsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2180,7 +2292,7 @@ func (x *DetachShardsRequest) String() string { func (*DetachShardsRequest) ProtoMessage() {} func (x *DetachShardsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2193,7 +2305,7 @@ func (x *DetachShardsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsRequest.ProtoReflect.Descriptor instead. func (*DetachShardsRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38} } func (x *DetachShardsRequest) GetBody() *DetachShardsRequest_Body { @@ -2222,7 +2334,7 @@ type DetachShardsResponse struct { func (x *DetachShardsResponse) Reset() { *x = DetachShardsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2235,7 +2347,7 @@ func (x *DetachShardsResponse) String() string { func (*DetachShardsResponse) ProtoMessage() {} func (x *DetachShardsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2248,7 +2360,7 @@ func (x *DetachShardsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsResponse.ProtoReflect.Descriptor instead. func (*DetachShardsResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39} } func (x *DetachShardsResponse) GetBody() *DetachShardsResponse_Body { @@ -2275,7 +2387,7 @@ type HealthCheckRequest_Body struct { func (x *HealthCheckRequest_Body) Reset() { *x = HealthCheckRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2288,7 +2400,7 @@ func (x *HealthCheckRequest_Body) String() string { func (*HealthCheckRequest_Body) ProtoMessage() {} func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2319,7 +2431,7 @@ type HealthCheckResponse_Body struct { func (x *HealthCheckResponse_Body) Reset() { *x = HealthCheckResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2332,7 +2444,7 @@ func (x *HealthCheckResponse_Body) String() string { func (*HealthCheckResponse_Body) ProtoMessage() {} func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2383,7 +2495,7 @@ type SetNetmapStatusRequest_Body struct { func (x *SetNetmapStatusRequest_Body) Reset() { *x = SetNetmapStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2396,7 +2508,7 @@ func (x *SetNetmapStatusRequest_Body) String() string { func (*SetNetmapStatusRequest_Body) ProtoMessage() {} func (x *SetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2436,7 +2548,7 @@ type SetNetmapStatusResponse_Body struct { func (x *SetNetmapStatusResponse_Body) Reset() { *x = SetNetmapStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2449,7 +2561,7 @@ func (x *SetNetmapStatusResponse_Body) String() string { func (*SetNetmapStatusResponse_Body) ProtoMessage() {} func (x *SetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2479,7 +2591,7 @@ type DropObjectsRequest_Body struct { func (x *DropObjectsRequest_Body) Reset() { *x = DropObjectsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2492,7 +2604,7 @@ func (x *DropObjectsRequest_Body) String() string { func (*DropObjectsRequest_Body) ProtoMessage() {} func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2525,7 +2637,7 @@ type DropObjectsResponse_Body struct { func (x *DropObjectsResponse_Body) Reset() { *x = DropObjectsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2538,7 +2650,7 @@ func (x *DropObjectsResponse_Body) String() string { func (*DropObjectsResponse_Body) ProtoMessage() {} func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2564,7 +2676,7 @@ type ListShardsRequest_Body struct { func (x *ListShardsRequest_Body) Reset() { *x = ListShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2577,7 +2689,7 @@ func (x *ListShardsRequest_Body) String() string { func (*ListShardsRequest_Body) ProtoMessage() {} func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2606,7 +2718,7 @@ type ListShardsResponse_Body struct { func (x *ListShardsResponse_Body) Reset() { *x = ListShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2619,7 +2731,7 @@ func (x *ListShardsResponse_Body) String() string { func (*ListShardsResponse_Body) ProtoMessage() {} func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2659,7 +2771,7 @@ type SetShardModeRequest_Body struct { func (x *SetShardModeRequest_Body) Reset() { *x = SetShardModeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2672,7 +2784,7 @@ func (x *SetShardModeRequest_Body) String() string { func (*SetShardModeRequest_Body) ProtoMessage() {} func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2719,7 +2831,7 @@ type SetShardModeResponse_Body struct { func (x *SetShardModeResponse_Body) Reset() { *x = SetShardModeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2732,7 +2844,7 @@ func (x *SetShardModeResponse_Body) String() string { func (*SetShardModeResponse_Body) ProtoMessage() {} func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2763,7 +2875,7 @@ type SynchronizeTreeRequest_Body struct { func (x *SynchronizeTreeRequest_Body) Reset() { *x = SynchronizeTreeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2776,7 +2888,7 @@ func (x *SynchronizeTreeRequest_Body) String() string { func (*SynchronizeTreeRequest_Body) ProtoMessage() {} func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2823,7 +2935,7 @@ type SynchronizeTreeResponse_Body struct { func (x *SynchronizeTreeResponse_Body) Reset() { *x = SynchronizeTreeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2836,7 +2948,7 @@ func (x *SynchronizeTreeResponse_Body) String() string { func (*SynchronizeTreeResponse_Body) ProtoMessage() {} func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2867,7 +2979,7 @@ type EvacuateShardRequest_Body struct { func (x *EvacuateShardRequest_Body) Reset() { *x = EvacuateShardRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2880,7 +2992,7 @@ func (x *EvacuateShardRequest_Body) String() string { func (*EvacuateShardRequest_Body) ProtoMessage() {} func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2922,7 +3034,7 @@ type EvacuateShardResponse_Body struct { func (x *EvacuateShardResponse_Body) Reset() { *x = EvacuateShardResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2935,7 +3047,7 @@ func (x *EvacuateShardResponse_Body) String() string { func (*EvacuateShardResponse_Body) ProtoMessage() {} func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2973,7 +3085,7 @@ type FlushCacheRequest_Body struct { func (x *FlushCacheRequest_Body) Reset() { *x = FlushCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2986,7 +3098,7 @@ func (x *FlushCacheRequest_Body) String() string { func (*FlushCacheRequest_Body) ProtoMessage() {} func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3026,7 +3138,7 @@ type FlushCacheResponse_Body struct { func (x *FlushCacheResponse_Body) Reset() { *x = FlushCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3039,7 +3151,7 @@ func (x *FlushCacheResponse_Body) String() string { func (*FlushCacheResponse_Body) ProtoMessage() {} func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3070,7 +3182,7 @@ type DoctorRequest_Body struct { func (x *DoctorRequest_Body) Reset() { *x = DoctorRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3083,7 +3195,7 @@ func (x *DoctorRequest_Body) String() string { func (*DoctorRequest_Body) ProtoMessage() {} func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3123,7 +3235,7 @@ type DoctorResponse_Body struct { func (x *DoctorResponse_Body) Reset() { *x = DoctorResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3136,7 +3248,7 @@ func (x *DoctorResponse_Body) String() string { func (*DoctorResponse_Body) ProtoMessage() {} func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3169,7 +3281,7 @@ type StartShardEvacuationRequest_Body struct { func (x *StartShardEvacuationRequest_Body) Reset() { *x = StartShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3182,7 +3294,7 @@ func (x *StartShardEvacuationRequest_Body) String() string { func (*StartShardEvacuationRequest_Body) ProtoMessage() {} func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3229,7 +3341,7 @@ type StartShardEvacuationResponse_Body struct { func (x *StartShardEvacuationResponse_Body) Reset() { *x = StartShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3242,7 +3354,7 @@ func (x *StartShardEvacuationResponse_Body) String() string { func (*StartShardEvacuationResponse_Body) ProtoMessage() {} func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3268,7 +3380,7 @@ type GetShardEvacuationStatusRequest_Body struct { func (x *GetShardEvacuationStatusRequest_Body) Reset() { *x = GetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3281,7 +3393,7 @@ func (x *GetShardEvacuationStatusRequest_Body) String() string { func (*GetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3332,7 +3444,7 @@ type GetShardEvacuationStatusResponse_Body struct { func (x *GetShardEvacuationStatusResponse_Body) Reset() { *x = GetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3345,7 +3457,7 @@ func (x *GetShardEvacuationStatusResponse_Body) String() string { func (*GetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3457,7 +3569,7 @@ type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) Reset() { *x = GetShardEvacuationStatusResponse_Body_UnixTimestamp{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3470,7 +3582,7 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) String() string { func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3505,7 +3617,7 @@ type GetShardEvacuationStatusResponse_Body_Duration struct { func (x *GetShardEvacuationStatusResponse_Body_Duration) Reset() { *x = GetShardEvacuationStatusResponse_Body_Duration{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3518,7 +3630,7 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) String() string { func (*GetShardEvacuationStatusResponse_Body_Duration) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3541,6 +3653,82 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) GetSeconds() int64 { return 0 } +type ResetShardEvacuationStatusRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ResetShardEvacuationStatusRequest_Body) Reset() { + *x = ResetShardEvacuationStatusRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[64] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResetShardEvacuationStatusRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResetShardEvacuationStatusRequest_Body) ProtoMessage() {} + +func (x *ResetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[64] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResetShardEvacuationStatusRequest_Body.ProtoReflect.Descriptor instead. +func (*ResetShardEvacuationStatusRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22, 0} +} + +type ResetShardEvacuationStatusResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ResetShardEvacuationStatusResponse_Body) Reset() { + *x = ResetShardEvacuationStatusResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[65] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResetShardEvacuationStatusResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResetShardEvacuationStatusResponse_Body) ProtoMessage() {} + +func (x *ResetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[65] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResetShardEvacuationStatusResponse_Body.ProtoReflect.Descriptor instead. +func (*ResetShardEvacuationStatusResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0} +} + // Request body structure. type StopShardEvacuationRequest_Body struct { state protoimpl.MessageState @@ -3551,7 +3739,7 @@ type StopShardEvacuationRequest_Body struct { func (x *StopShardEvacuationRequest_Body) Reset() { *x = StopShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3564,7 +3752,7 @@ func (x *StopShardEvacuationRequest_Body) String() string { func (*StopShardEvacuationRequest_Body) ProtoMessage() {} func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3577,7 +3765,7 @@ func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use StopShardEvacuationRequest_Body.ProtoReflect.Descriptor instead. func (*StopShardEvacuationRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24, 0} } // Response body structure. @@ -3590,7 +3778,7 @@ type StopShardEvacuationResponse_Body struct { func (x *StopShardEvacuationResponse_Body) Reset() { *x = StopShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3603,7 +3791,7 @@ func (x *StopShardEvacuationResponse_Body) String() string { func (*StopShardEvacuationResponse_Body) ProtoMessage() {} func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3616,7 +3804,7 @@ func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use StopShardEvacuationResponse_Body.ProtoReflect.Descriptor instead. func (*StopShardEvacuationResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25, 0} } type AddChainLocalOverrideRequest_Body struct { @@ -3635,7 +3823,7 @@ type AddChainLocalOverrideRequest_Body struct { func (x *AddChainLocalOverrideRequest_Body) Reset() { *x = AddChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3648,7 +3836,7 @@ func (x *AddChainLocalOverrideRequest_Body) String() string { func (*AddChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3661,7 +3849,7 @@ func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message // Deprecated: Use AddChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. func (*AddChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26, 0} } func (x *AddChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { @@ -3692,7 +3880,7 @@ type AddChainLocalOverrideResponse_Body struct { func (x *AddChainLocalOverrideResponse_Body) Reset() { *x = AddChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3705,7 +3893,7 @@ func (x *AddChainLocalOverrideResponse_Body) String() string { func (*AddChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3718,7 +3906,7 @@ func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message // Deprecated: Use AddChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. func (*AddChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27, 0} } func (x *AddChainLocalOverrideResponse_Body) GetChainId() []byte { @@ -3742,7 +3930,7 @@ type GetChainLocalOverrideRequest_Body struct { func (x *GetChainLocalOverrideRequest_Body) Reset() { *x = GetChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3755,7 +3943,7 @@ func (x *GetChainLocalOverrideRequest_Body) String() string { func (*GetChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3768,7 +3956,7 @@ func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message // Deprecated: Use GetChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. func (*GetChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28, 0} } func (x *GetChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { @@ -3797,7 +3985,7 @@ type GetChainLocalOverrideResponse_Body struct { func (x *GetChainLocalOverrideResponse_Body) Reset() { *x = GetChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3810,7 +3998,7 @@ func (x *GetChainLocalOverrideResponse_Body) String() string { func (*GetChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3823,7 +4011,7 @@ func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message // Deprecated: Use GetChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. func (*GetChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29, 0} } func (x *GetChainLocalOverrideResponse_Body) GetChain() []byte { @@ -3845,7 +4033,7 @@ type ListChainLocalOverridesRequest_Body struct { func (x *ListChainLocalOverridesRequest_Body) Reset() { *x = ListChainLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3858,7 +4046,7 @@ func (x *ListChainLocalOverridesRequest_Body) String() string { func (*ListChainLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3871,7 +4059,7 @@ func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Messag // Deprecated: Use ListChainLocalOverridesRequest_Body.ProtoReflect.Descriptor instead. func (*ListChainLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} } func (x *ListChainLocalOverridesRequest_Body) GetTarget() *ChainTarget { @@ -3893,7 +4081,7 @@ type ListChainLocalOverridesResponse_Body struct { func (x *ListChainLocalOverridesResponse_Body) Reset() { *x = ListChainLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3906,7 +4094,7 @@ func (x *ListChainLocalOverridesResponse_Body) String() string { func (*ListChainLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3919,7 +4107,7 @@ func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Messa // Deprecated: Use ListChainLocalOverridesResponse_Body.ProtoReflect.Descriptor instead. func (*ListChainLocalOverridesResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31, 0} } func (x *ListChainLocalOverridesResponse_Body) GetChains() [][]byte { @@ -3941,7 +4129,7 @@ type ListTargetsLocalOverridesRequest_Body struct { func (x *ListTargetsLocalOverridesRequest_Body) Reset() { *x = ListTargetsLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3954,7 +4142,7 @@ func (x *ListTargetsLocalOverridesRequest_Body) String() string { func (*ListTargetsLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListTargetsLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3967,7 +4155,7 @@ func (x *ListTargetsLocalOverridesRequest_Body) ProtoReflect() protoreflect.Mess // Deprecated: Use ListTargetsLocalOverridesRequest_Body.ProtoReflect.Descriptor instead. func (*ListTargetsLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32, 0} } func (x *ListTargetsLocalOverridesRequest_Body) GetChainName() string { @@ -3989,7 +4177,7 @@ type ListTargetsLocalOverridesResponse_Body struct { func (x *ListTargetsLocalOverridesResponse_Body) Reset() { *x = ListTargetsLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[71] + mi := &file_pkg_services_control_service_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4002,7 +4190,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) String() string { func (*ListTargetsLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListTargetsLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[71] + mi := &file_pkg_services_control_service_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4015,7 +4203,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) ProtoReflect() protoreflect.Mes // Deprecated: Use ListTargetsLocalOverridesResponse_Body.ProtoReflect.Descriptor instead. func (*ListTargetsLocalOverridesResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} } func (x *ListTargetsLocalOverridesResponse_Body) GetTargets() []*ChainTarget { @@ -4039,7 +4227,7 @@ type RemoveChainLocalOverrideRequest_Body struct { func (x *RemoveChainLocalOverrideRequest_Body) Reset() { *x = RemoveChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[72] + mi := &file_pkg_services_control_service_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4052,7 +4240,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) String() string { func (*RemoveChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[72] + mi := &file_pkg_services_control_service_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4065,7 +4253,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Messa // Deprecated: Use RemoveChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34, 0} } func (x *RemoveChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { @@ -4091,7 +4279,7 @@ type RemoveChainLocalOverrideResponse_Body struct { func (x *RemoveChainLocalOverrideResponse_Body) Reset() { *x = RemoveChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[73] + mi := &file_pkg_services_control_service_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4104,7 +4292,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) String() string { func (*RemoveChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[73] + mi := &file_pkg_services_control_service_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4117,7 +4305,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Mess // Deprecated: Use RemoveChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0} } // Request body structure. @@ -4135,7 +4323,7 @@ type SealWriteCacheRequest_Body struct { func (x *SealWriteCacheRequest_Body) Reset() { *x = SealWriteCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[74] + mi := &file_pkg_services_control_service_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4148,7 +4336,7 @@ func (x *SealWriteCacheRequest_Body) String() string { func (*SealWriteCacheRequest_Body) ProtoMessage() {} func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[74] + mi := &file_pkg_services_control_service_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4161,7 +4349,7 @@ func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheRequest_Body.ProtoReflect.Descriptor instead. func (*SealWriteCacheRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36, 0} } func (x *SealWriteCacheRequest_Body) GetShard_ID() [][]byte { @@ -4189,7 +4377,7 @@ type SealWriteCacheResponse_Body struct { func (x *SealWriteCacheResponse_Body) Reset() { *x = SealWriteCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[75] + mi := &file_pkg_services_control_service_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4202,7 +4390,7 @@ func (x *SealWriteCacheResponse_Body) String() string { func (*SealWriteCacheResponse_Body) ProtoMessage() {} func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[75] + mi := &file_pkg_services_control_service_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4215,7 +4403,7 @@ func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheResponse_Body.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0} } func (x *SealWriteCacheResponse_Body) GetResults() []*SealWriteCacheResponse_Body_Status { @@ -4238,7 +4426,7 @@ type SealWriteCacheResponse_Body_Status struct { func (x *SealWriteCacheResponse_Body_Status) Reset() { *x = SealWriteCacheResponse_Body_Status{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[76] + mi := &file_pkg_services_control_service_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4251,7 +4439,7 @@ func (x *SealWriteCacheResponse_Body_Status) String() string { func (*SealWriteCacheResponse_Body_Status) ProtoMessage() {} func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[76] + mi := &file_pkg_services_control_service_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4264,7 +4452,7 @@ func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message // Deprecated: Use SealWriteCacheResponse_Body_Status.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse_Body_Status) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0, 0} } func (x *SealWriteCacheResponse_Body_Status) GetShard_ID() []byte { @@ -4299,7 +4487,7 @@ type DetachShardsRequest_Body struct { func (x *DetachShardsRequest_Body) Reset() { *x = DetachShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[77] + mi := &file_pkg_services_control_service_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4312,7 +4500,7 @@ func (x *DetachShardsRequest_Body) String() string { func (*DetachShardsRequest_Body) ProtoMessage() {} func (x *DetachShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[77] + mi := &file_pkg_services_control_service_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4325,7 +4513,7 @@ func (x *DetachShardsRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsRequest_Body.ProtoReflect.Descriptor instead. func (*DetachShardsRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38, 0} } func (x *DetachShardsRequest_Body) GetShard_ID() [][]byte { @@ -4344,7 +4532,7 @@ type DetachShardsResponse_Body struct { func (x *DetachShardsResponse_Body) Reset() { *x = DetachShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[78] + mi := &file_pkg_services_control_service_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4357,7 +4545,7 @@ func (x *DetachShardsResponse_Body) String() string { func (*DetachShardsResponse_Body) ProtoMessage() {} func (x *DetachShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[78] + mi := &file_pkg_services_control_service_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4370,7 +4558,7 @@ func (x *DetachShardsResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsResponse_Body.ProtoReflect.Descriptor instead. func (*DetachShardsResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39, 0} } var File_pkg_services_control_service_proto protoreflect.FileDescriptor @@ -4672,314 +4860,342 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, - 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0x94, 0x01, - 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, - 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, 0x01, - 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, 0x0a, - 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0xa2, 0x01, + 0x0a, 0x21, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, - 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, + 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x53, 0x74, + 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x1c, 0x41, 0x64, + 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4a, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, 0x1e, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, - 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, - 0x64, 0x22, 0xa0, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, + 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, - 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, - 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, - 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, - 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, - 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, - 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, - 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, - 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, - 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x34, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1e, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0xbe, 0x01, + 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd2, + 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x36, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xa0, 0x01, + 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, + 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, + 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, + 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb1, 0x0d, 0x0a, - 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, - 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, - 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, - 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, - 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, - 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, - 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, - 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, - 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, - 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, - 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, + 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, + 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, + 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, + 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, - 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, - 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, - 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, - 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, + 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xa8, 0x0e, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, + 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, + 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, + 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, + 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, + 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, + 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, + 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, + 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, + 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, + 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, + 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, + 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, + 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, + 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4995,7 +5211,7 @@ func file_pkg_services_control_service_proto_rawDescGZIP() []byte { } var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 79) +var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 83) var file_pkg_services_control_service_proto_goTypes = []interface{}{ (StartShardEvacuationRequest_Body_Scope)(0), // 0: control.StartShardEvacuationRequest.Body.Scope (GetShardEvacuationStatusResponse_Body_Status)(0), // 1: control.GetShardEvacuationStatusResponse.Body.Status @@ -5021,204 +5237,214 @@ var file_pkg_services_control_service_proto_goTypes = []interface{}{ (*StartShardEvacuationResponse)(nil), // 21: control.StartShardEvacuationResponse (*GetShardEvacuationStatusRequest)(nil), // 22: control.GetShardEvacuationStatusRequest (*GetShardEvacuationStatusResponse)(nil), // 23: control.GetShardEvacuationStatusResponse - (*StopShardEvacuationRequest)(nil), // 24: control.StopShardEvacuationRequest - (*StopShardEvacuationResponse)(nil), // 25: control.StopShardEvacuationResponse - (*AddChainLocalOverrideRequest)(nil), // 26: control.AddChainLocalOverrideRequest - (*AddChainLocalOverrideResponse)(nil), // 27: control.AddChainLocalOverrideResponse - (*GetChainLocalOverrideRequest)(nil), // 28: control.GetChainLocalOverrideRequest - (*GetChainLocalOverrideResponse)(nil), // 29: control.GetChainLocalOverrideResponse - (*ListChainLocalOverridesRequest)(nil), // 30: control.ListChainLocalOverridesRequest - (*ListChainLocalOverridesResponse)(nil), // 31: control.ListChainLocalOverridesResponse - (*ListTargetsLocalOverridesRequest)(nil), // 32: control.ListTargetsLocalOverridesRequest - (*ListTargetsLocalOverridesResponse)(nil), // 33: control.ListTargetsLocalOverridesResponse - (*RemoveChainLocalOverrideRequest)(nil), // 34: control.RemoveChainLocalOverrideRequest - (*RemoveChainLocalOverrideResponse)(nil), // 35: control.RemoveChainLocalOverrideResponse - (*SealWriteCacheRequest)(nil), // 36: control.SealWriteCacheRequest - (*SealWriteCacheResponse)(nil), // 37: control.SealWriteCacheResponse - (*DetachShardsRequest)(nil), // 38: control.DetachShardsRequest - (*DetachShardsResponse)(nil), // 39: control.DetachShardsResponse - (*HealthCheckRequest_Body)(nil), // 40: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 41: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 42: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 43: control.SetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 44: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 45: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 46: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 47: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 48: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 49: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 50: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 51: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 52: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 53: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 54: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 55: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 56: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 57: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 58: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 59: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 60: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 61: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 62: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 63: control.GetShardEvacuationStatusResponse.Body.Duration - (*StopShardEvacuationRequest_Body)(nil), // 64: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 65: control.StopShardEvacuationResponse.Body - (*AddChainLocalOverrideRequest_Body)(nil), // 66: control.AddChainLocalOverrideRequest.Body - (*AddChainLocalOverrideResponse_Body)(nil), // 67: control.AddChainLocalOverrideResponse.Body - (*GetChainLocalOverrideRequest_Body)(nil), // 68: control.GetChainLocalOverrideRequest.Body - (*GetChainLocalOverrideResponse_Body)(nil), // 69: control.GetChainLocalOverrideResponse.Body - (*ListChainLocalOverridesRequest_Body)(nil), // 70: control.ListChainLocalOverridesRequest.Body - (*ListChainLocalOverridesResponse_Body)(nil), // 71: control.ListChainLocalOverridesResponse.Body - (*ListTargetsLocalOverridesRequest_Body)(nil), // 72: control.ListTargetsLocalOverridesRequest.Body - (*ListTargetsLocalOverridesResponse_Body)(nil), // 73: control.ListTargetsLocalOverridesResponse.Body - (*RemoveChainLocalOverrideRequest_Body)(nil), // 74: control.RemoveChainLocalOverrideRequest.Body - (*RemoveChainLocalOverrideResponse_Body)(nil), // 75: control.RemoveChainLocalOverrideResponse.Body - (*SealWriteCacheRequest_Body)(nil), // 76: control.SealWriteCacheRequest.Body - (*SealWriteCacheResponse_Body)(nil), // 77: control.SealWriteCacheResponse.Body - (*SealWriteCacheResponse_Body_Status)(nil), // 78: control.SealWriteCacheResponse.Body.Status - (*DetachShardsRequest_Body)(nil), // 79: control.DetachShardsRequest.Body - (*DetachShardsResponse_Body)(nil), // 80: control.DetachShardsResponse.Body - (*Signature)(nil), // 81: control.Signature - (NetmapStatus)(0), // 82: control.NetmapStatus - (HealthStatus)(0), // 83: control.HealthStatus - (*ShardInfo)(nil), // 84: control.ShardInfo - (ShardMode)(0), // 85: control.ShardMode - (*ChainTarget)(nil), // 86: control.ChainTarget + (*ResetShardEvacuationStatusRequest)(nil), // 24: control.ResetShardEvacuationStatusRequest + (*ResetShardEvacuationStatusResponse)(nil), // 25: control.ResetShardEvacuationStatusResponse + (*StopShardEvacuationRequest)(nil), // 26: control.StopShardEvacuationRequest + (*StopShardEvacuationResponse)(nil), // 27: control.StopShardEvacuationResponse + (*AddChainLocalOverrideRequest)(nil), // 28: control.AddChainLocalOverrideRequest + (*AddChainLocalOverrideResponse)(nil), // 29: control.AddChainLocalOverrideResponse + (*GetChainLocalOverrideRequest)(nil), // 30: control.GetChainLocalOverrideRequest + (*GetChainLocalOverrideResponse)(nil), // 31: control.GetChainLocalOverrideResponse + (*ListChainLocalOverridesRequest)(nil), // 32: control.ListChainLocalOverridesRequest + (*ListChainLocalOverridesResponse)(nil), // 33: control.ListChainLocalOverridesResponse + (*ListTargetsLocalOverridesRequest)(nil), // 34: control.ListTargetsLocalOverridesRequest + (*ListTargetsLocalOverridesResponse)(nil), // 35: control.ListTargetsLocalOverridesResponse + (*RemoveChainLocalOverrideRequest)(nil), // 36: control.RemoveChainLocalOverrideRequest + (*RemoveChainLocalOverrideResponse)(nil), // 37: control.RemoveChainLocalOverrideResponse + (*SealWriteCacheRequest)(nil), // 38: control.SealWriteCacheRequest + (*SealWriteCacheResponse)(nil), // 39: control.SealWriteCacheResponse + (*DetachShardsRequest)(nil), // 40: control.DetachShardsRequest + (*DetachShardsResponse)(nil), // 41: control.DetachShardsResponse + (*HealthCheckRequest_Body)(nil), // 42: control.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 43: control.HealthCheckResponse.Body + (*SetNetmapStatusRequest_Body)(nil), // 44: control.SetNetmapStatusRequest.Body + (*SetNetmapStatusResponse_Body)(nil), // 45: control.SetNetmapStatusResponse.Body + (*DropObjectsRequest_Body)(nil), // 46: control.DropObjectsRequest.Body + (*DropObjectsResponse_Body)(nil), // 47: control.DropObjectsResponse.Body + (*ListShardsRequest_Body)(nil), // 48: control.ListShardsRequest.Body + (*ListShardsResponse_Body)(nil), // 49: control.ListShardsResponse.Body + (*SetShardModeRequest_Body)(nil), // 50: control.SetShardModeRequest.Body + (*SetShardModeResponse_Body)(nil), // 51: control.SetShardModeResponse.Body + (*SynchronizeTreeRequest_Body)(nil), // 52: control.SynchronizeTreeRequest.Body + (*SynchronizeTreeResponse_Body)(nil), // 53: control.SynchronizeTreeResponse.Body + (*EvacuateShardRequest_Body)(nil), // 54: control.EvacuateShardRequest.Body + (*EvacuateShardResponse_Body)(nil), // 55: control.EvacuateShardResponse.Body + (*FlushCacheRequest_Body)(nil), // 56: control.FlushCacheRequest.Body + (*FlushCacheResponse_Body)(nil), // 57: control.FlushCacheResponse.Body + (*DoctorRequest_Body)(nil), // 58: control.DoctorRequest.Body + (*DoctorResponse_Body)(nil), // 59: control.DoctorResponse.Body + (*StartShardEvacuationRequest_Body)(nil), // 60: control.StartShardEvacuationRequest.Body + (*StartShardEvacuationResponse_Body)(nil), // 61: control.StartShardEvacuationResponse.Body + (*GetShardEvacuationStatusRequest_Body)(nil), // 62: control.GetShardEvacuationStatusRequest.Body + (*GetShardEvacuationStatusResponse_Body)(nil), // 63: control.GetShardEvacuationStatusResponse.Body + (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 64: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 65: control.GetShardEvacuationStatusResponse.Body.Duration + (*ResetShardEvacuationStatusRequest_Body)(nil), // 66: control.ResetShardEvacuationStatusRequest.Body + (*ResetShardEvacuationStatusResponse_Body)(nil), // 67: control.ResetShardEvacuationStatusResponse.Body + (*StopShardEvacuationRequest_Body)(nil), // 68: control.StopShardEvacuationRequest.Body + (*StopShardEvacuationResponse_Body)(nil), // 69: control.StopShardEvacuationResponse.Body + (*AddChainLocalOverrideRequest_Body)(nil), // 70: control.AddChainLocalOverrideRequest.Body + (*AddChainLocalOverrideResponse_Body)(nil), // 71: control.AddChainLocalOverrideResponse.Body + (*GetChainLocalOverrideRequest_Body)(nil), // 72: control.GetChainLocalOverrideRequest.Body + (*GetChainLocalOverrideResponse_Body)(nil), // 73: control.GetChainLocalOverrideResponse.Body + (*ListChainLocalOverridesRequest_Body)(nil), // 74: control.ListChainLocalOverridesRequest.Body + (*ListChainLocalOverridesResponse_Body)(nil), // 75: control.ListChainLocalOverridesResponse.Body + (*ListTargetsLocalOverridesRequest_Body)(nil), // 76: control.ListTargetsLocalOverridesRequest.Body + (*ListTargetsLocalOverridesResponse_Body)(nil), // 77: control.ListTargetsLocalOverridesResponse.Body + (*RemoveChainLocalOverrideRequest_Body)(nil), // 78: control.RemoveChainLocalOverrideRequest.Body + (*RemoveChainLocalOverrideResponse_Body)(nil), // 79: control.RemoveChainLocalOverrideResponse.Body + (*SealWriteCacheRequest_Body)(nil), // 80: control.SealWriteCacheRequest.Body + (*SealWriteCacheResponse_Body)(nil), // 81: control.SealWriteCacheResponse.Body + (*SealWriteCacheResponse_Body_Status)(nil), // 82: control.SealWriteCacheResponse.Body.Status + (*DetachShardsRequest_Body)(nil), // 83: control.DetachShardsRequest.Body + (*DetachShardsResponse_Body)(nil), // 84: control.DetachShardsResponse.Body + (*Signature)(nil), // 85: control.Signature + (NetmapStatus)(0), // 86: control.NetmapStatus + (HealthStatus)(0), // 87: control.HealthStatus + (*ShardInfo)(nil), // 88: control.ShardInfo + (ShardMode)(0), // 89: control.ShardMode + (*ChainTarget)(nil), // 90: control.ChainTarget } var file_pkg_services_control_service_proto_depIdxs = []int32{ - 40, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 81, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 41, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 81, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 42, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 81, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 43, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 81, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 44, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 81, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature - 45, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 81, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature - 46, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 81, // 13: control.ListShardsRequest.signature:type_name -> control.Signature - 47, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 81, // 15: control.ListShardsResponse.signature:type_name -> control.Signature - 48, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 81, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature - 49, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 81, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature - 50, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 81, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 51, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 81, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 52, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 81, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature - 53, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 81, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature - 54, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 81, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature - 55, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 81, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature - 56, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 81, // 33: control.DoctorRequest.signature:type_name -> control.Signature - 57, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 81, // 35: control.DoctorResponse.signature:type_name -> control.Signature - 58, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 81, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 59, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 81, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 60, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 81, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 61, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 81, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 64, // 44: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 81, // 45: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 65, // 46: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 81, // 47: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 66, // 48: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body - 81, // 49: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature - 67, // 50: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body - 81, // 51: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature - 68, // 52: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body - 81, // 53: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature - 69, // 54: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body - 81, // 55: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature - 70, // 56: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body - 81, // 57: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature - 71, // 58: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body - 81, // 59: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature - 72, // 60: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body - 81, // 61: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature - 73, // 62: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body - 81, // 63: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature - 74, // 64: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body - 81, // 65: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature - 75, // 66: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body - 81, // 67: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature - 76, // 68: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body - 81, // 69: control.SealWriteCacheRequest.signature:type_name -> control.Signature - 77, // 70: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body - 81, // 71: control.SealWriteCacheResponse.signature:type_name -> control.Signature - 79, // 72: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body - 81, // 73: control.DetachShardsRequest.signature:type_name -> control.Signature - 80, // 74: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body - 81, // 75: control.DetachShardsResponse.signature:type_name -> control.Signature - 82, // 76: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 83, // 77: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 82, // 78: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 84, // 79: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 85, // 80: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 1, // 81: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 63, // 82: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 62, // 83: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 86, // 84: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 86, // 85: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 86, // 86: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget - 86, // 87: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget - 86, // 88: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 78, // 89: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status - 2, // 90: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 4, // 91: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 6, // 92: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 8, // 93: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 10, // 94: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 12, // 95: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 14, // 96: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 20, // 97: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 22, // 98: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 24, // 99: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 16, // 100: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 18, // 101: control.ControlService.Doctor:input_type -> control.DoctorRequest - 26, // 102: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 28, // 103: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 30, // 104: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 34, // 105: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 32, // 106: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest - 36, // 107: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest - 38, // 108: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest - 3, // 109: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 5, // 110: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 7, // 111: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 9, // 112: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 11, // 113: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 13, // 114: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 15, // 115: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 21, // 116: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 23, // 117: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 25, // 118: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 17, // 119: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 19, // 120: control.ControlService.Doctor:output_type -> control.DoctorResponse - 27, // 121: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 29, // 122: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 31, // 123: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 35, // 124: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 33, // 125: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse - 37, // 126: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse - 39, // 127: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse - 109, // [109:128] is the sub-list for method output_type - 90, // [90:109] is the sub-list for method input_type - 90, // [90:90] is the sub-list for extension type_name - 90, // [90:90] is the sub-list for extension extendee - 0, // [0:90] is the sub-list for field type_name + 42, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body + 85, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature + 43, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body + 85, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature + 44, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body + 85, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature + 45, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body + 85, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature + 46, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body + 85, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature + 47, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body + 85, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature + 48, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body + 85, // 13: control.ListShardsRequest.signature:type_name -> control.Signature + 49, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body + 85, // 15: control.ListShardsResponse.signature:type_name -> control.Signature + 50, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body + 85, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature + 51, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body + 85, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature + 52, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body + 85, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature + 53, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body + 85, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature + 54, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body + 85, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature + 55, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body + 85, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature + 56, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body + 85, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature + 57, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body + 85, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature + 58, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body + 85, // 33: control.DoctorRequest.signature:type_name -> control.Signature + 59, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body + 85, // 35: control.DoctorResponse.signature:type_name -> control.Signature + 60, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body + 85, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature + 61, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body + 85, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature + 62, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body + 85, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 63, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body + 85, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 66, // 44: control.ResetShardEvacuationStatusRequest.body:type_name -> control.ResetShardEvacuationStatusRequest.Body + 85, // 45: control.ResetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 67, // 46: control.ResetShardEvacuationStatusResponse.body:type_name -> control.ResetShardEvacuationStatusResponse.Body + 85, // 47: control.ResetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 68, // 48: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body + 85, // 49: control.StopShardEvacuationRequest.signature:type_name -> control.Signature + 69, // 50: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body + 85, // 51: control.StopShardEvacuationResponse.signature:type_name -> control.Signature + 70, // 52: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body + 85, // 53: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature + 71, // 54: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body + 85, // 55: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature + 72, // 56: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body + 85, // 57: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature + 73, // 58: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body + 85, // 59: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature + 74, // 60: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body + 85, // 61: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature + 75, // 62: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body + 85, // 63: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature + 76, // 64: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body + 85, // 65: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature + 77, // 66: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body + 85, // 67: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature + 78, // 68: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body + 85, // 69: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature + 79, // 70: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body + 85, // 71: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature + 80, // 72: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body + 85, // 73: control.SealWriteCacheRequest.signature:type_name -> control.Signature + 81, // 74: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body + 85, // 75: control.SealWriteCacheResponse.signature:type_name -> control.Signature + 83, // 76: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body + 85, // 77: control.DetachShardsRequest.signature:type_name -> control.Signature + 84, // 78: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body + 85, // 79: control.DetachShardsResponse.signature:type_name -> control.Signature + 86, // 80: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus + 87, // 81: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus + 86, // 82: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus + 88, // 83: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo + 89, // 84: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode + 1, // 85: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status + 65, // 86: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration + 64, // 87: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + 90, // 88: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 90, // 89: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 90, // 90: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget + 90, // 91: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget + 90, // 92: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 82, // 93: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status + 2, // 94: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 4, // 95: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 6, // 96: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 8, // 97: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 10, // 98: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 12, // 99: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 14, // 100: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 20, // 101: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 22, // 102: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 24, // 103: control.ControlService.ResetShardEvacuationStatus:input_type -> control.ResetShardEvacuationStatusRequest + 26, // 104: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 16, // 105: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 18, // 106: control.ControlService.Doctor:input_type -> control.DoctorRequest + 28, // 107: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 30, // 108: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 32, // 109: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 36, // 110: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 34, // 111: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest + 38, // 112: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest + 40, // 113: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest + 3, // 114: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 5, // 115: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 7, // 116: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 9, // 117: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 11, // 118: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 13, // 119: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 15, // 120: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 21, // 121: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 23, // 122: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 25, // 123: control.ControlService.ResetShardEvacuationStatus:output_type -> control.ResetShardEvacuationStatusResponse + 27, // 124: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 17, // 125: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 19, // 126: control.ControlService.Doctor:output_type -> control.DoctorResponse + 29, // 127: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 31, // 128: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 33, // 129: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 37, // 130: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 35, // 131: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse + 39, // 132: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse + 41, // 133: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse + 114, // [114:134] is the sub-list for method output_type + 94, // [94:114] is the sub-list for method input_type + 94, // [94:94] is the sub-list for extension 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_pkg_services_control_service_proto_init() } @@ -5493,7 +5719,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest); i { + switch v := v.(*ResetShardEvacuationStatusRequest); i { case 0: return &v.state case 1: @@ -5505,7 +5731,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse); i { + switch v := v.(*ResetShardEvacuationStatusResponse); i { case 0: return &v.state case 1: @@ -5517,7 +5743,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest); i { + switch v := v.(*StopShardEvacuationRequest); i { case 0: return &v.state case 1: @@ -5529,7 +5755,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse); i { + switch v := v.(*StopShardEvacuationResponse); i { case 0: return &v.state case 1: @@ -5541,7 +5767,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest); i { + switch v := v.(*AddChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -5553,7 +5779,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse); i { + switch v := v.(*AddChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -5565,7 +5791,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest); i { + switch v := v.(*GetChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -5577,7 +5803,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse); i { + switch v := v.(*GetChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -5589,7 +5815,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesRequest); i { + switch v := v.(*ListChainLocalOverridesRequest); i { case 0: return &v.state case 1: @@ -5601,7 +5827,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesResponse); i { + switch v := v.(*ListChainLocalOverridesResponse); i { case 0: return &v.state case 1: @@ -5613,7 +5839,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest); i { + switch v := v.(*ListTargetsLocalOverridesRequest); i { case 0: return &v.state case 1: @@ -5625,7 +5851,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse); i { + switch v := v.(*ListTargetsLocalOverridesResponse); i { case 0: return &v.state case 1: @@ -5637,7 +5863,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest); i { + switch v := v.(*RemoveChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -5649,7 +5875,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse); i { + switch v := v.(*RemoveChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -5661,7 +5887,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsRequest); i { + switch v := v.(*SealWriteCacheRequest); i { case 0: return &v.state case 1: @@ -5673,7 +5899,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsResponse); i { + switch v := v.(*SealWriteCacheResponse); i { case 0: return &v.state case 1: @@ -5685,7 +5911,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { + switch v := v.(*DetachShardsRequest); i { case 0: return &v.state case 1: @@ -5697,7 +5923,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { + switch v := v.(*DetachShardsResponse); i { case 0: return &v.state case 1: @@ -5709,7 +5935,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest_Body); i { + switch v := v.(*HealthCheckRequest_Body); i { case 0: return &v.state case 1: @@ -5721,7 +5947,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse_Body); i { + switch v := v.(*HealthCheckResponse_Body); i { case 0: return &v.state case 1: @@ -5733,7 +5959,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest_Body); i { + switch v := v.(*SetNetmapStatusRequest_Body); i { case 0: return &v.state case 1: @@ -5745,7 +5971,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse_Body); i { + switch v := v.(*SetNetmapStatusResponse_Body); i { case 0: return &v.state case 1: @@ -5757,7 +5983,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest_Body); i { + switch v := v.(*DropObjectsRequest_Body); i { case 0: return &v.state case 1: @@ -5769,7 +5995,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse_Body); i { + switch v := v.(*DropObjectsResponse_Body); i { case 0: return &v.state case 1: @@ -5781,7 +6007,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest_Body); i { + switch v := v.(*ListShardsRequest_Body); i { case 0: return &v.state case 1: @@ -5793,7 +6019,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse_Body); i { + switch v := v.(*ListShardsResponse_Body); i { case 0: return &v.state case 1: @@ -5805,7 +6031,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest_Body); i { + switch v := v.(*SetShardModeRequest_Body); i { case 0: return &v.state case 1: @@ -5817,7 +6043,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse_Body); i { + switch v := v.(*SetShardModeResponse_Body); i { case 0: return &v.state case 1: @@ -5829,7 +6055,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest_Body); i { + switch v := v.(*SynchronizeTreeRequest_Body); i { case 0: return &v.state case 1: @@ -5841,7 +6067,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse_Body); i { + switch v := v.(*SynchronizeTreeResponse_Body); i { case 0: return &v.state case 1: @@ -5853,7 +6079,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest_Body); i { + switch v := v.(*EvacuateShardRequest_Body); i { case 0: return &v.state case 1: @@ -5865,7 +6091,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse_Body); i { + switch v := v.(*EvacuateShardResponse_Body); i { case 0: return &v.state case 1: @@ -5877,7 +6103,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest_Body); i { + switch v := v.(*FlushCacheRequest_Body); i { case 0: return &v.state case 1: @@ -5889,7 +6115,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse_Body); i { + switch v := v.(*FlushCacheResponse_Body); i { case 0: return &v.state case 1: @@ -5901,7 +6127,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest_Body); i { + switch v := v.(*DoctorRequest_Body); i { case 0: return &v.state case 1: @@ -5913,7 +6139,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse_Body); i { + switch v := v.(*DoctorResponse_Body); i { case 0: return &v.state case 1: @@ -5925,7 +6151,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest_Body); i { + switch v := v.(*StartShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -5937,7 +6163,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body); i { + switch v := v.(*StartShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -5949,7 +6175,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { + switch v := v.(*GetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -5961,7 +6187,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -5973,7 +6199,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { case 0: return &v.state case 1: @@ -5985,7 +6211,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { case 0: return &v.state case 1: @@ -5997,7 +6223,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest_Body); i { + switch v := v.(*ResetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -6009,7 +6235,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse_Body); i { + switch v := v.(*ResetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -6021,7 +6247,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest_Body); i { + switch v := v.(*StopShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -6033,7 +6259,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse_Body); i { + switch v := v.(*StopShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -6045,7 +6271,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest_Body); i { + switch v := v.(*AddChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6057,7 +6283,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse_Body); i { + switch v := v.(*AddChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6069,7 +6295,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { + switch v := v.(*GetChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6081,7 +6307,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { + switch v := v.(*GetChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6093,7 +6319,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + switch v := v.(*ListChainLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -6105,7 +6331,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { + switch v := v.(*ListChainLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -6117,7 +6343,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest_Body); i { + switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -6129,7 +6355,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body); i { + switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -6141,7 +6367,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body_Status); i { + switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6153,7 +6379,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsRequest_Body); i { + switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6165,6 +6391,54 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body_Status); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DetachShardsRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DetachShardsResponse_Body); i { case 0: return &v.state @@ -6183,7 +6457,7 @@ func file_pkg_services_control_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_service_proto_rawDesc, NumEnums: 2, - NumMessages: 79, + NumMessages: 83, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 1377965e65..8501e952f1 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -36,6 +36,9 @@ service ControlService { // GetShardEvacuationStatus returns evacuation status. rpc GetShardEvacuationStatus (GetShardEvacuationStatusRequest) returns (GetShardEvacuationStatusResponse); + // ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process. + rpc ResetShardEvacuationStatus (ResetShardEvacuationStatusRequest) returns (ResetShardEvacuationStatusResponse); + // StopShardEvacuation stops moving all data from one shard to the others. rpc StopShardEvacuation (StopShardEvacuationRequest) returns (StopShardEvacuationResponse); @@ -426,6 +429,22 @@ message GetShardEvacuationStatusResponse { Signature signature = 2; } +// ResetShardEvacuationStatus request. +message ResetShardEvacuationStatusRequest { + message Body {} + + Body body = 1; + Signature signature = 2; +} + +// ResetShardEvacuationStatus response. +message ResetShardEvacuationStatusResponse { + message Body {} + + Body body = 1; + Signature signature = 2; +} + // StopShardEvacuation request. message StopShardEvacuationRequest { // Request body structure. diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 56b2bd54c8..b90749269d 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -1916,6 +1916,160 @@ func (x *GetShardEvacuationStatusResponse) SetSignature(sig *Signature) { x.Signature = sig } +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ResetShardEvacuationStatusRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ResetShardEvacuationStatusRequest_Body) StableMarshal(buf []byte) []byte { + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ResetShardEvacuationStatusRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ResetShardEvacuationStatusRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ResetShardEvacuationStatusRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ResetShardEvacuationStatusRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *ResetShardEvacuationStatusRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ResetShardEvacuationStatusResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ResetShardEvacuationStatusResponse_Body) StableMarshal(buf []byte) []byte { + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ResetShardEvacuationStatusResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *ResetShardEvacuationStatusResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ResetShardEvacuationStatusResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ResetShardEvacuationStatusResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *ResetShardEvacuationStatusResponse) SetSignature(sig *Signature) { + x.Signature = sig +} + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index 69029ccb30..ad33e330ae 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -19,25 +19,26 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - ControlService_HealthCheck_FullMethodName = "/control.ControlService/HealthCheck" - ControlService_SetNetmapStatus_FullMethodName = "/control.ControlService/SetNetmapStatus" - ControlService_DropObjects_FullMethodName = "/control.ControlService/DropObjects" - ControlService_ListShards_FullMethodName = "/control.ControlService/ListShards" - ControlService_SetShardMode_FullMethodName = "/control.ControlService/SetShardMode" - ControlService_SynchronizeTree_FullMethodName = "/control.ControlService/SynchronizeTree" - ControlService_EvacuateShard_FullMethodName = "/control.ControlService/EvacuateShard" - ControlService_StartShardEvacuation_FullMethodName = "/control.ControlService/StartShardEvacuation" - ControlService_GetShardEvacuationStatus_FullMethodName = "/control.ControlService/GetShardEvacuationStatus" - ControlService_StopShardEvacuation_FullMethodName = "/control.ControlService/StopShardEvacuation" - ControlService_FlushCache_FullMethodName = "/control.ControlService/FlushCache" - ControlService_Doctor_FullMethodName = "/control.ControlService/Doctor" - ControlService_AddChainLocalOverride_FullMethodName = "/control.ControlService/AddChainLocalOverride" - ControlService_GetChainLocalOverride_FullMethodName = "/control.ControlService/GetChainLocalOverride" - ControlService_ListChainLocalOverrides_FullMethodName = "/control.ControlService/ListChainLocalOverrides" - ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" - ControlService_ListTargetsLocalOverrides_FullMethodName = "/control.ControlService/ListTargetsLocalOverrides" - ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" - ControlService_DetachShards_FullMethodName = "/control.ControlService/DetachShards" + ControlService_HealthCheck_FullMethodName = "/control.ControlService/HealthCheck" + ControlService_SetNetmapStatus_FullMethodName = "/control.ControlService/SetNetmapStatus" + ControlService_DropObjects_FullMethodName = "/control.ControlService/DropObjects" + ControlService_ListShards_FullMethodName = "/control.ControlService/ListShards" + ControlService_SetShardMode_FullMethodName = "/control.ControlService/SetShardMode" + ControlService_SynchronizeTree_FullMethodName = "/control.ControlService/SynchronizeTree" + ControlService_EvacuateShard_FullMethodName = "/control.ControlService/EvacuateShard" + ControlService_StartShardEvacuation_FullMethodName = "/control.ControlService/StartShardEvacuation" + ControlService_GetShardEvacuationStatus_FullMethodName = "/control.ControlService/GetShardEvacuationStatus" + ControlService_ResetShardEvacuationStatus_FullMethodName = "/control.ControlService/ResetShardEvacuationStatus" + ControlService_StopShardEvacuation_FullMethodName = "/control.ControlService/StopShardEvacuation" + ControlService_FlushCache_FullMethodName = "/control.ControlService/FlushCache" + ControlService_Doctor_FullMethodName = "/control.ControlService/Doctor" + ControlService_AddChainLocalOverride_FullMethodName = "/control.ControlService/AddChainLocalOverride" + ControlService_GetChainLocalOverride_FullMethodName = "/control.ControlService/GetChainLocalOverride" + ControlService_ListChainLocalOverrides_FullMethodName = "/control.ControlService/ListChainLocalOverrides" + ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" + ControlService_ListTargetsLocalOverrides_FullMethodName = "/control.ControlService/ListTargetsLocalOverrides" + ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" + ControlService_DetachShards_FullMethodName = "/control.ControlService/DetachShards" ) // ControlServiceClient is the client API for ControlService service. @@ -63,6 +64,8 @@ type ControlServiceClient interface { StartShardEvacuation(ctx context.Context, in *StartShardEvacuationRequest, opts ...grpc.CallOption) (*StartShardEvacuationResponse, error) // GetShardEvacuationStatus returns evacuation status. GetShardEvacuationStatus(ctx context.Context, in *GetShardEvacuationStatusRequest, opts ...grpc.CallOption) (*GetShardEvacuationStatusResponse, error) + // ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process. + ResetShardEvacuationStatus(ctx context.Context, in *ResetShardEvacuationStatusRequest, opts ...grpc.CallOption) (*ResetShardEvacuationStatusResponse, error) // StopShardEvacuation stops moving all data from one shard to the others. StopShardEvacuation(ctx context.Context, in *StopShardEvacuationRequest, opts ...grpc.CallOption) (*StopShardEvacuationResponse, error) // FlushCache moves all data from one shard to the others. @@ -174,6 +177,15 @@ func (c *controlServiceClient) GetShardEvacuationStatus(ctx context.Context, in return out, nil } +func (c *controlServiceClient) ResetShardEvacuationStatus(ctx context.Context, in *ResetShardEvacuationStatusRequest, opts ...grpc.CallOption) (*ResetShardEvacuationStatusResponse, error) { + out := new(ResetShardEvacuationStatusResponse) + err := c.cc.Invoke(ctx, ControlService_ResetShardEvacuationStatus_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *controlServiceClient) StopShardEvacuation(ctx context.Context, in *StopShardEvacuationRequest, opts ...grpc.CallOption) (*StopShardEvacuationResponse, error) { out := new(StopShardEvacuationResponse) err := c.cc.Invoke(ctx, ControlService_StopShardEvacuation_FullMethodName, in, out, opts...) @@ -287,6 +299,8 @@ type ControlServiceServer interface { StartShardEvacuation(context.Context, *StartShardEvacuationRequest) (*StartShardEvacuationResponse, error) // GetShardEvacuationStatus returns evacuation status. GetShardEvacuationStatus(context.Context, *GetShardEvacuationStatusRequest) (*GetShardEvacuationStatusResponse, error) + // ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process. + ResetShardEvacuationStatus(context.Context, *ResetShardEvacuationStatusRequest) (*ResetShardEvacuationStatusResponse, error) // StopShardEvacuation stops moving all data from one shard to the others. StopShardEvacuation(context.Context, *StopShardEvacuationRequest) (*StopShardEvacuationResponse, error) // FlushCache moves all data from one shard to the others. @@ -340,6 +354,9 @@ func (UnimplementedControlServiceServer) StartShardEvacuation(context.Context, * func (UnimplementedControlServiceServer) GetShardEvacuationStatus(context.Context, *GetShardEvacuationStatusRequest) (*GetShardEvacuationStatusResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetShardEvacuationStatus not implemented") } +func (UnimplementedControlServiceServer) ResetShardEvacuationStatus(context.Context, *ResetShardEvacuationStatusRequest) (*ResetShardEvacuationStatusResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ResetShardEvacuationStatus not implemented") +} func (UnimplementedControlServiceServer) StopShardEvacuation(context.Context, *StopShardEvacuationRequest) (*StopShardEvacuationResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method StopShardEvacuation not implemented") } @@ -544,6 +561,24 @@ func _ControlService_GetShardEvacuationStatus_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _ControlService_ResetShardEvacuationStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ResetShardEvacuationStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).ResetShardEvacuationStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_ResetShardEvacuationStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).ResetShardEvacuationStatus(ctx, req.(*ResetShardEvacuationStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ControlService_StopShardEvacuation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(StopShardEvacuationRequest) if err := dec(in); err != nil { @@ -767,6 +802,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetShardEvacuationStatus", Handler: _ControlService_GetShardEvacuationStatus_Handler, }, + { + MethodName: "ResetShardEvacuationStatus", + Handler: _ControlService_ResetShardEvacuationStatus_Handler, + }, { MethodName: "StopShardEvacuation", Handler: _ControlService_StopShardEvacuation_Handler, From 17f5463389f54f083b6ead323e80d61f137101b7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 13 Mar 2024 10:40:44 +0300 Subject: [PATCH 0442/1413] [#1043] cli: Add reset evacuation status command Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/evacuation.go | 32 ++++++++++++ docs/evacuation.md | 2 + pkg/services/control/rpc.go | 52 ++++++++++++------- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 1d192aa50a..6fa5ed75c6 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -53,6 +53,13 @@ var stopEvacuationShardCmd = &cobra.Command{ Run: stopEvacuateShardStatus, } +var resetEvacuationStatusShardCmd = &cobra.Command{ + Use: "reset", + Short: "Reset evacuate objects from shard status", + Long: "Reset evacuate objects from shard to other shards status", + Run: resetEvacuateShardStatus, +} + func startEvacuateShard(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) @@ -152,6 +159,29 @@ func stopEvacuateShardStatus(cmd *cobra.Command, _ []string) { cmd.Println("Evacuation stopped.") } +func resetEvacuateShardStatus(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + req := &control.ResetShardEvacuationStatusRequest{ + Body: &control.ResetShardEvacuationStatusRequest_Body{}, + } + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.ResetShardEvacuationStatusResponse + var err error + err = cli.ExecRaw(func(client *client.Client) error { + resp, err = control.ResetShardEvacuationStatus(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "Reset shards evacuation status failed, rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + cmd.Println("Shards evacuation status has been reset.") +} + func waitEvacuateCompletion(cmd *cobra.Command, pk *ecdsa.PrivateKey, cli *clientSDK.Client, printProgress, printCompleted bool) { const statusPollingInterval = 1 * time.Second const reportIntervalSeconds = 5 @@ -323,10 +353,12 @@ func initControlEvacuationShardCmd() { evacuationShardCmd.AddCommand(startEvacuationShardCmd) evacuationShardCmd.AddCommand(getEvacuationShardStatusCmd) evacuationShardCmd.AddCommand(stopEvacuationShardCmd) + evacuationShardCmd.AddCommand(resetEvacuationStatusShardCmd) initControlStartEvacuationShardCmd() initControlFlags(getEvacuationShardStatusCmd) initControlFlags(stopEvacuationShardCmd) + initControlFlags(resetEvacuationStatusShardCmd) } func initControlStartEvacuationShardCmd() { diff --git a/docs/evacuation.md b/docs/evacuation.md index 1bccc87bfd..602e32e9b8 100644 --- a/docs/evacuation.md +++ b/docs/evacuation.md @@ -20,6 +20,8 @@ Only one running evacuation process is allowed on the node at a time. `frostfs-cli control shards evacuation status` prints evacuation process status. +`frostfs-cli control shards evacuation reset` resets evacuation process status. + See commands `--help` output for detailed description. ## Examples diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 877bb63c2a..b07b10274a 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -8,25 +8,26 @@ import ( const serviceName = "control.ControlService" const ( - rpcHealthCheck = "HealthCheck" - rpcSetNetmapStatus = "SetNetmapStatus" - rpcDropObjects = "DropObjects" - rpcListShards = "ListShards" - rpcSetShardMode = "SetShardMode" - rpcSynchronizeTree = "SynchronizeTree" - rpcEvacuateShard = "EvacuateShard" - rpcStartShardEvacuation = "StartShardEvacuation" - rpcGetShardEvacuationStatus = "GetShardEvacuationStatus" - rpcStopShardEvacuation = "StopShardEvacuation" - rpcFlushCache = "FlushCache" - rpcDoctor = "Doctor" - rpcAddChainLocalOverride = "AddChainLocalOverride" - rpcGetChainLocalOverride = "GetChainLocalOverride" - rpcListChainLocalOverrides = "ListChainLocalOverrides" - rpcRemoveChainLocalOverride = "RemoveChainLocalOverride" - rpcSealWriteCache = "SealWriteCache" - rpcListTargetsLocalOverrides = "ListTargetsLocalOverrides" - rpcDetachShards = "DetachShards" + rpcHealthCheck = "HealthCheck" + rpcSetNetmapStatus = "SetNetmapStatus" + rpcDropObjects = "DropObjects" + rpcListShards = "ListShards" + rpcSetShardMode = "SetShardMode" + rpcSynchronizeTree = "SynchronizeTree" + rpcEvacuateShard = "EvacuateShard" + rpcStartShardEvacuation = "StartShardEvacuation" + rpcGetShardEvacuationStatus = "GetShardEvacuationStatus" + rpcResetShardEvacuationStatus = "ResetShardEvacuationStatus" + rpcStopShardEvacuation = "StopShardEvacuation" + rpcFlushCache = "FlushCache" + rpcDoctor = "Doctor" + rpcAddChainLocalOverride = "AddChainLocalOverride" + rpcGetChainLocalOverride = "GetChainLocalOverride" + rpcListChainLocalOverrides = "ListChainLocalOverrides" + rpcRemoveChainLocalOverride = "RemoveChainLocalOverride" + rpcSealWriteCache = "SealWriteCache" + rpcListTargetsLocalOverrides = "ListTargetsLocalOverrides" + rpcDetachShards = "DetachShards" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -190,6 +191,19 @@ func StopShardEvacuation(cli *client.Client, req *StopShardEvacuationRequest, op return wResp.message, nil } +// ResetShardEvacuationStatus executes ControlService.ResetShardEvacuationStatus RPC. +func ResetShardEvacuationStatus(cli *client.Client, req *ResetShardEvacuationStatusRequest, opts ...client.CallOption) (*ResetShardEvacuationStatusResponse, error) { + wResp := newResponseWrapper[ResetShardEvacuationStatusResponse]() + wReq := &requestWrapper{m: req} + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcResetShardEvacuationStatus), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.message, nil +} + // FlushCache executes ControlService.FlushCache RPC. func FlushCache(cli *client.Client, req *FlushCacheRequest, opts ...client.CallOption) (*FlushCacheResponse, error) { wResp := newResponseWrapper[FlushCacheResponse]() From 0a600521ad4529ee841ba619fb50c9cb34707f1e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 13 Mar 2024 12:01:06 +0300 Subject: [PATCH 0443/1413] [#1043] dev: Add empty pass config Signed-off-by: Dmitrii Stepanov --- dev/empty_pass.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 dev/empty_pass.yml diff --git a/dev/empty_pass.yml b/dev/empty_pass.yml new file mode 100644 index 0000000000..2a088f9529 --- /dev/null +++ b/dev/empty_pass.yml @@ -0,0 +1 @@ +password: "" \ No newline at end of file From 7ed07d2dfd2a3db38c043232f93525a3b40c640e Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 7 Mar 2024 19:16:40 +0300 Subject: [PATCH 0444/1413] [#976] morph: Implement missing methods for `SwitchRPCGuardedActor` Signed-off-by: Anton Nikiforov --- pkg/morph/client/actor.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/morph/client/actor.go b/pkg/morph/client/actor.go index ea6bc974c4..8c283a6725 100644 --- a/pkg/morph/client/actor.go +++ b/pkg/morph/client/actor.go @@ -1,11 +1,13 @@ package client import ( + "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) type actorProvider interface { @@ -118,3 +120,15 @@ func (a *SwitchRPCGuardedActor) Sign(tx *transaction.Transaction) error { func (a *SwitchRPCGuardedActor) SignAndSend(tx *transaction.Transaction) (util.Uint256, uint32, error) { return a.actorProvider.GetActor().SignAndSend(tx) } + +func (a *SwitchRPCGuardedActor) CallAndExpandIterator(contract util.Uint160, method string, maxItems int, params ...any) (*result.Invoke, error) { + return a.actorProvider.GetActor().CallAndExpandIterator(contract, method, maxItems, params...) +} + +func (a *SwitchRPCGuardedActor) TerminateSession(sessionID uuid.UUID) error { + return a.actorProvider.GetActor().TerminateSession(sessionID) +} + +func (a *SwitchRPCGuardedActor) TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) { + return a.actorProvider.GetActor().TraverseIterator(sessionID, iterator, num) +} From 2d595ec15f516dda5b66bd85d8c08c6136e514ad Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 7 Mar 2024 19:21:18 +0300 Subject: [PATCH 0445/1413] [#976] ape: Update dependency Signed-off-by: Anton Nikiforov --- go.mod | 4 ++-- go.sum | 8 ++++---- pkg/ape/chainbase/boltdb.go | 37 +++++++++++++++++++++++++++---------- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 6ba1ed73d7..2c2eac68f0 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,11 @@ go 1.20 require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa + git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240304151211-839f22e1a36d + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 24120b20a3..d90bf0f6a5 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 h1:EDtL9OJcdeevV/jmNMtHugulAQprdOnknNPvLB3LRgE= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa h1:uuN90s74idThHXi/jF/IlTdFimOIs+IBU44rdTE/Zdo= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 h1:FzurjElUwC7InY9v5rzXReKbfBL5yRJKSWJPq6BKhH0= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= @@ -12,8 +12,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b/go.mod h1:XcgrbZ88XfvhAMxmZCQJ0dv6FyRSq6Mg2J7nN8uuO0k= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240304151211-839f22e1a36d h1:y7KP7vrX5Cbx9R2nzCFj7Ljjsa/KkWZS4nQIXHEeKdw= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240304151211-839f22e1a36d/go.mod h1:YVL7yFaT0QNSpA0z+RHudLvrLwT+lsFYGyBSVc1ustI= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd h1:pyIl9f4nIr7ekJ73W9keLIQ5dpoKb8o6xNmodsXY5+o= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index 27bfd8468d..5f3c342c1a 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -100,7 +100,7 @@ func (cs *boltLocalOverrideStorage) Close() error { return err } -func getTargetBucket(tx *bbolt.Tx, name chain.Name, target policyengine.Target) (*bbolt.Bucket, error) { +func getTypeBucket(tx *bbolt.Tx, name chain.Name, target policyengine.Target) (*bbolt.Bucket, error) { cbucket := tx.Bucket(chainBucket) if cbucket == nil { return nil, ErrRootBucketNotFound @@ -110,16 +110,25 @@ func getTargetBucket(tx *bbolt.Tx, name chain.Name, target policyengine.Target) if nbucket == nil { return nil, fmt.Errorf("%w: %w: %s", policyengine.ErrChainNotFound, ErrGlobalNamespaceBucketNotFound, name) } + return nbucket.Bucket([]byte{byte(target.Type)}), nil +} - typeBucket := nbucket.Bucket([]byte{byte(target.Type)}) +func normalizeTargetName(target *policyengine.Target) { + if target.Type == policyengine.Namespace && target.Name == "" { + target.Name = "root" + } +} + +func getTargetBucket(tx *bbolt.Tx, name chain.Name, target policyengine.Target) (*bbolt.Bucket, error) { + typeBucket, err := getTypeBucket(tx, name, target) + if err != nil { + return nil, err + } if typeBucket == nil { return nil, fmt.Errorf("%w: %w: %c", policyengine.ErrChainNotFound, ErrTargetTypeBucketNotFound, target.Type) } - if target.Type == policyengine.Namespace && target.Name == "" { - target.Name = "root" - } - + normalizeTargetName(&target) rbucket := typeBucket.Bucket([]byte(target.Name)) if rbucket == nil { return nil, fmt.Errorf("%w: %w: %s", policyengine.ErrChainNotFound, ErrTargetNameBucketNotFound, target.Name) @@ -151,10 +160,7 @@ func getTargetBucketCreateIfEmpty(tx *bbolt.Tx, name chain.Name, target policyen } } - if target.Type == policyengine.Namespace && target.Name == "" { - target.Name = "root" - } - + normalizeTargetName(&target) rbucket := typeBucket.Bucket([]byte(target.Name)) if rbucket == nil { var err error @@ -220,6 +226,17 @@ func (cs *boltLocalOverrideStorage) RemoveOverride(name chain.Name, target polic }) } +func (cs *boltLocalOverrideStorage) RemoveOverridesByTarget(name chain.Name, target policyengine.Target) error { + return cs.db.Update(func(tx *bbolt.Tx) error { + typeBucket, err := getTypeBucket(tx, name, target) + if err != nil { + return err + } + normalizeTargetName(&target) + return typeBucket.DeleteBucket([]byte(target.Name)) + }) +} + func (cs *boltLocalOverrideStorage) ListOverrides(name chain.Name, target policyengine.Target) ([]*chain.Chain, error) { var serializedChains [][]byte var serializedChain []byte From 5ee5f1df42aa778c2ad2fb0142147ce7ad632e59 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 7 Mar 2024 14:22:52 +0300 Subject: [PATCH 0446/1413] [#976] control: Introduce new method `RemoveChainLocalOverridesByTarget` Signed-off-by: Anton Nikiforov --- pkg/services/control/rpc.go | 54 +- pkg/services/control/server/policy_engine.go | 25 + pkg/services/control/service.pb.go | 1294 +++++++++++------- pkg/services/control/service.proto | 23 + pkg/services/control/service_frostfs.pb.go | 163 +++ pkg/services/control/service_grpc.pb.go | 79 +- 6 files changed, 1096 insertions(+), 542 deletions(-) diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index b07b10274a..f9397c1282 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -8,26 +8,27 @@ import ( const serviceName = "control.ControlService" const ( - rpcHealthCheck = "HealthCheck" - rpcSetNetmapStatus = "SetNetmapStatus" - rpcDropObjects = "DropObjects" - rpcListShards = "ListShards" - rpcSetShardMode = "SetShardMode" - rpcSynchronizeTree = "SynchronizeTree" - rpcEvacuateShard = "EvacuateShard" - rpcStartShardEvacuation = "StartShardEvacuation" - rpcGetShardEvacuationStatus = "GetShardEvacuationStatus" - rpcResetShardEvacuationStatus = "ResetShardEvacuationStatus" - rpcStopShardEvacuation = "StopShardEvacuation" - rpcFlushCache = "FlushCache" - rpcDoctor = "Doctor" - rpcAddChainLocalOverride = "AddChainLocalOverride" - rpcGetChainLocalOverride = "GetChainLocalOverride" - rpcListChainLocalOverrides = "ListChainLocalOverrides" - rpcRemoveChainLocalOverride = "RemoveChainLocalOverride" - rpcSealWriteCache = "SealWriteCache" - rpcListTargetsLocalOverrides = "ListTargetsLocalOverrides" - rpcDetachShards = "DetachShards" + rpcHealthCheck = "HealthCheck" + rpcSetNetmapStatus = "SetNetmapStatus" + rpcDropObjects = "DropObjects" + rpcListShards = "ListShards" + rpcSetShardMode = "SetShardMode" + rpcSynchronizeTree = "SynchronizeTree" + rpcEvacuateShard = "EvacuateShard" + rpcStartShardEvacuation = "StartShardEvacuation" + rpcGetShardEvacuationStatus = "GetShardEvacuationStatus" + rpcResetShardEvacuationStatus = "ResetShardEvacuationStatus" + rpcStopShardEvacuation = "StopShardEvacuation" + rpcFlushCache = "FlushCache" + rpcDoctor = "Doctor" + rpcAddChainLocalOverride = "AddChainLocalOverride" + rpcGetChainLocalOverride = "GetChainLocalOverride" + rpcListChainLocalOverrides = "ListChainLocalOverrides" + rpcRemoveChainLocalOverride = "RemoveChainLocalOverride" + rpcRemoveChainLocalOverridesByTarget = "RemoveChainLocalOverridesByTarget" + rpcSealWriteCache = "SealWriteCache" + rpcListTargetsLocalOverrides = "ListTargetsLocalOverrides" + rpcDetachShards = "DetachShards" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -295,6 +296,19 @@ func RemoveChainLocalOverride(cli *client.Client, req *RemoveChainLocalOverrideR return wResp.message, nil } +// RemoveChainLocalOverridesByTarget executes ControlService.RemoveChainLocalOverridesByTarget RPC. +func RemoveChainLocalOverridesByTarget(cli *client.Client, req *RemoveChainLocalOverridesByTargetRequest, opts ...client.CallOption) (*RemoveChainLocalOverridesByTargetResponse, error) { + wResp := newResponseWrapper[RemoveChainLocalOverridesByTargetResponse]() + wReq := &requestWrapper{m: req} + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcRemoveChainLocalOverridesByTarget), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.message, nil +} + // SealWriteCache executes ControlService.SealWriteCache RPC. func SealWriteCache(cli *client.Client, req *SealWriteCacheRequest, opts ...client.CallOption) (*SealWriteCacheResponse, error) { wResp := newResponseWrapper[SealWriteCacheResponse]() diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 4ea863f79e..16b365b219 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -174,6 +174,31 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return resp, nil } +func (s *Server) RemoveChainLocalOverridesByTarget(_ context.Context, req *control.RemoveChainLocalOverridesByTargetRequest) (*control.RemoveChainLocalOverridesByTargetResponse, error) { + if err := s.isValidRequest(req); err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + target, err := apeTarget(req.GetBody().GetTarget()) + if err != nil { + return nil, err + } + + if err = s.localOverrideStorage.LocalStorage().RemoveOverridesByTarget(apechain.Ingress, target); err != nil { + if code := getCodeByLocalStorageErr(err); code != codes.NotFound { + return nil, status.Error(code, err.Error()) + } + } + resp := &control.RemoveChainLocalOverridesByTargetResponse{ + Body: &control.RemoveChainLocalOverridesByTargetResponse_Body{}, + } + err = SignMessage(s.key, resp) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return resp, nil +} + func (s *Server) ListTargetsLocalOverrides(_ context.Context, req *control.ListTargetsLocalOverridesRequest) (*control.ListTargetsLocalOverridesResponse, error) { if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 5866197672..345110bab8 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -2157,6 +2157,116 @@ func (x *RemoveChainLocalOverrideResponse) GetSignature() *Signature { return nil } +type RemoveChainLocalOverridesByTargetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *RemoveChainLocalOverridesByTargetRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *RemoveChainLocalOverridesByTargetRequest) Reset() { + *x = RemoveChainLocalOverridesByTargetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveChainLocalOverridesByTargetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveChainLocalOverridesByTargetRequest) ProtoMessage() {} + +func (x *RemoveChainLocalOverridesByTargetRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveChainLocalOverridesByTargetRequest.ProtoReflect.Descriptor instead. +func (*RemoveChainLocalOverridesByTargetRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36} +} + +func (x *RemoveChainLocalOverridesByTargetRequest) GetBody() *RemoveChainLocalOverridesByTargetRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *RemoveChainLocalOverridesByTargetRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +type RemoveChainLocalOverridesByTargetResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Body *RemoveChainLocalOverridesByTargetResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *RemoveChainLocalOverridesByTargetResponse) Reset() { + *x = RemoveChainLocalOverridesByTargetResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveChainLocalOverridesByTargetResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveChainLocalOverridesByTargetResponse) ProtoMessage() {} + +func (x *RemoveChainLocalOverridesByTargetResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[37] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveChainLocalOverridesByTargetResponse.ProtoReflect.Descriptor instead. +func (*RemoveChainLocalOverridesByTargetResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37} +} + +func (x *RemoveChainLocalOverridesByTargetResponse) GetBody() *RemoveChainLocalOverridesByTargetResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *RemoveChainLocalOverridesByTargetResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + type SealWriteCacheRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2169,7 +2279,7 @@ type SealWriteCacheRequest struct { func (x *SealWriteCacheRequest) Reset() { *x = SealWriteCacheRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2182,7 +2292,7 @@ func (x *SealWriteCacheRequest) String() string { func (*SealWriteCacheRequest) ProtoMessage() {} func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2195,7 +2305,7 @@ func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheRequest.ProtoReflect.Descriptor instead. func (*SealWriteCacheRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38} } func (x *SealWriteCacheRequest) GetBody() *SealWriteCacheRequest_Body { @@ -2224,7 +2334,7 @@ type SealWriteCacheResponse struct { func (x *SealWriteCacheResponse) Reset() { *x = SealWriteCacheResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2237,7 +2347,7 @@ func (x *SealWriteCacheResponse) String() string { func (*SealWriteCacheResponse) ProtoMessage() {} func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2250,7 +2360,7 @@ func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheResponse.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39} } func (x *SealWriteCacheResponse) GetBody() *SealWriteCacheResponse_Body { @@ -2279,7 +2389,7 @@ type DetachShardsRequest struct { func (x *DetachShardsRequest) Reset() { *x = DetachShardsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2292,7 +2402,7 @@ func (x *DetachShardsRequest) String() string { func (*DetachShardsRequest) ProtoMessage() {} func (x *DetachShardsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2305,7 +2415,7 @@ func (x *DetachShardsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsRequest.ProtoReflect.Descriptor instead. func (*DetachShardsRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{40} } func (x *DetachShardsRequest) GetBody() *DetachShardsRequest_Body { @@ -2334,7 +2444,7 @@ type DetachShardsResponse struct { func (x *DetachShardsResponse) Reset() { *x = DetachShardsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2347,7 +2457,7 @@ func (x *DetachShardsResponse) String() string { func (*DetachShardsResponse) ProtoMessage() {} func (x *DetachShardsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2360,7 +2470,7 @@ func (x *DetachShardsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsResponse.ProtoReflect.Descriptor instead. func (*DetachShardsResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41} } func (x *DetachShardsResponse) GetBody() *DetachShardsResponse_Body { @@ -2387,7 +2497,7 @@ type HealthCheckRequest_Body struct { func (x *HealthCheckRequest_Body) Reset() { *x = HealthCheckRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2400,7 +2510,7 @@ func (x *HealthCheckRequest_Body) String() string { func (*HealthCheckRequest_Body) ProtoMessage() {} func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2431,7 +2541,7 @@ type HealthCheckResponse_Body struct { func (x *HealthCheckResponse_Body) Reset() { *x = HealthCheckResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2444,7 +2554,7 @@ func (x *HealthCheckResponse_Body) String() string { func (*HealthCheckResponse_Body) ProtoMessage() {} func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2495,7 +2605,7 @@ type SetNetmapStatusRequest_Body struct { func (x *SetNetmapStatusRequest_Body) Reset() { *x = SetNetmapStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2508,7 +2618,7 @@ func (x *SetNetmapStatusRequest_Body) String() string { func (*SetNetmapStatusRequest_Body) ProtoMessage() {} func (x *SetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2548,7 +2658,7 @@ type SetNetmapStatusResponse_Body struct { func (x *SetNetmapStatusResponse_Body) Reset() { *x = SetNetmapStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2561,7 +2671,7 @@ func (x *SetNetmapStatusResponse_Body) String() string { func (*SetNetmapStatusResponse_Body) ProtoMessage() {} func (x *SetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2591,7 +2701,7 @@ type DropObjectsRequest_Body struct { func (x *DropObjectsRequest_Body) Reset() { *x = DropObjectsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2604,7 +2714,7 @@ func (x *DropObjectsRequest_Body) String() string { func (*DropObjectsRequest_Body) ProtoMessage() {} func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2637,7 +2747,7 @@ type DropObjectsResponse_Body struct { func (x *DropObjectsResponse_Body) Reset() { *x = DropObjectsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2650,7 +2760,7 @@ func (x *DropObjectsResponse_Body) String() string { func (*DropObjectsResponse_Body) ProtoMessage() {} func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2676,7 +2786,7 @@ type ListShardsRequest_Body struct { func (x *ListShardsRequest_Body) Reset() { *x = ListShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2689,7 +2799,7 @@ func (x *ListShardsRequest_Body) String() string { func (*ListShardsRequest_Body) ProtoMessage() {} func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[48] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2718,7 +2828,7 @@ type ListShardsResponse_Body struct { func (x *ListShardsResponse_Body) Reset() { *x = ListShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2731,7 +2841,7 @@ func (x *ListShardsResponse_Body) String() string { func (*ListShardsResponse_Body) ProtoMessage() {} func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[49] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2771,7 +2881,7 @@ type SetShardModeRequest_Body struct { func (x *SetShardModeRequest_Body) Reset() { *x = SetShardModeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2784,7 +2894,7 @@ func (x *SetShardModeRequest_Body) String() string { func (*SetShardModeRequest_Body) ProtoMessage() {} func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2831,7 +2941,7 @@ type SetShardModeResponse_Body struct { func (x *SetShardModeResponse_Body) Reset() { *x = SetShardModeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2844,7 +2954,7 @@ func (x *SetShardModeResponse_Body) String() string { func (*SetShardModeResponse_Body) ProtoMessage() {} func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2875,7 +2985,7 @@ type SynchronizeTreeRequest_Body struct { func (x *SynchronizeTreeRequest_Body) Reset() { *x = SynchronizeTreeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2888,7 +2998,7 @@ func (x *SynchronizeTreeRequest_Body) String() string { func (*SynchronizeTreeRequest_Body) ProtoMessage() {} func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2935,7 +3045,7 @@ type SynchronizeTreeResponse_Body struct { func (x *SynchronizeTreeResponse_Body) Reset() { *x = SynchronizeTreeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2948,7 +3058,7 @@ func (x *SynchronizeTreeResponse_Body) String() string { func (*SynchronizeTreeResponse_Body) ProtoMessage() {} func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2979,7 +3089,7 @@ type EvacuateShardRequest_Body struct { func (x *EvacuateShardRequest_Body) Reset() { *x = EvacuateShardRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2992,7 +3102,7 @@ func (x *EvacuateShardRequest_Body) String() string { func (*EvacuateShardRequest_Body) ProtoMessage() {} func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3034,7 +3144,7 @@ type EvacuateShardResponse_Body struct { func (x *EvacuateShardResponse_Body) Reset() { *x = EvacuateShardResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3047,7 +3157,7 @@ func (x *EvacuateShardResponse_Body) String() string { func (*EvacuateShardResponse_Body) ProtoMessage() {} func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3085,7 +3195,7 @@ type FlushCacheRequest_Body struct { func (x *FlushCacheRequest_Body) Reset() { *x = FlushCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3098,7 +3208,7 @@ func (x *FlushCacheRequest_Body) String() string { func (*FlushCacheRequest_Body) ProtoMessage() {} func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3138,7 +3248,7 @@ type FlushCacheResponse_Body struct { func (x *FlushCacheResponse_Body) Reset() { *x = FlushCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3151,7 +3261,7 @@ func (x *FlushCacheResponse_Body) String() string { func (*FlushCacheResponse_Body) ProtoMessage() {} func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3182,7 +3292,7 @@ type DoctorRequest_Body struct { func (x *DoctorRequest_Body) Reset() { *x = DoctorRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3195,7 +3305,7 @@ func (x *DoctorRequest_Body) String() string { func (*DoctorRequest_Body) ProtoMessage() {} func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3235,7 +3345,7 @@ type DoctorResponse_Body struct { func (x *DoctorResponse_Body) Reset() { *x = DoctorResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3248,7 +3358,7 @@ func (x *DoctorResponse_Body) String() string { func (*DoctorResponse_Body) ProtoMessage() {} func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3281,7 +3391,7 @@ type StartShardEvacuationRequest_Body struct { func (x *StartShardEvacuationRequest_Body) Reset() { *x = StartShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3294,7 +3404,7 @@ func (x *StartShardEvacuationRequest_Body) String() string { func (*StartShardEvacuationRequest_Body) ProtoMessage() {} func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3341,7 +3451,7 @@ type StartShardEvacuationResponse_Body struct { func (x *StartShardEvacuationResponse_Body) Reset() { *x = StartShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3354,7 +3464,7 @@ func (x *StartShardEvacuationResponse_Body) String() string { func (*StartShardEvacuationResponse_Body) ProtoMessage() {} func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3380,7 +3490,7 @@ type GetShardEvacuationStatusRequest_Body struct { func (x *GetShardEvacuationStatusRequest_Body) Reset() { *x = GetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3393,7 +3503,7 @@ func (x *GetShardEvacuationStatusRequest_Body) String() string { func (*GetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3444,7 +3554,7 @@ type GetShardEvacuationStatusResponse_Body struct { func (x *GetShardEvacuationStatusResponse_Body) Reset() { *x = GetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3457,7 +3567,7 @@ func (x *GetShardEvacuationStatusResponse_Body) String() string { func (*GetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3569,7 +3679,7 @@ type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) Reset() { *x = GetShardEvacuationStatusResponse_Body_UnixTimestamp{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3582,7 +3692,7 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) String() string { func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3617,7 +3727,7 @@ type GetShardEvacuationStatusResponse_Body_Duration struct { func (x *GetShardEvacuationStatusResponse_Body_Duration) Reset() { *x = GetShardEvacuationStatusResponse_Body_Duration{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3630,7 +3740,7 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) String() string { func (*GetShardEvacuationStatusResponse_Body_Duration) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3662,7 +3772,7 @@ type ResetShardEvacuationStatusRequest_Body struct { func (x *ResetShardEvacuationStatusRequest_Body) Reset() { *x = ResetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3675,7 +3785,7 @@ func (x *ResetShardEvacuationStatusRequest_Body) String() string { func (*ResetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *ResetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3700,7 +3810,7 @@ type ResetShardEvacuationStatusResponse_Body struct { func (x *ResetShardEvacuationStatusResponse_Body) Reset() { *x = ResetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3713,7 +3823,7 @@ func (x *ResetShardEvacuationStatusResponse_Body) String() string { func (*ResetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *ResetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3739,7 +3849,7 @@ type StopShardEvacuationRequest_Body struct { func (x *StopShardEvacuationRequest_Body) Reset() { *x = StopShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3752,7 +3862,7 @@ func (x *StopShardEvacuationRequest_Body) String() string { func (*StopShardEvacuationRequest_Body) ProtoMessage() {} func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3778,7 +3888,7 @@ type StopShardEvacuationResponse_Body struct { func (x *StopShardEvacuationResponse_Body) Reset() { *x = StopShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3791,7 +3901,7 @@ func (x *StopShardEvacuationResponse_Body) String() string { func (*StopShardEvacuationResponse_Body) ProtoMessage() {} func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3823,7 +3933,7 @@ type AddChainLocalOverrideRequest_Body struct { func (x *AddChainLocalOverrideRequest_Body) Reset() { *x = AddChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3836,7 +3946,7 @@ func (x *AddChainLocalOverrideRequest_Body) String() string { func (*AddChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3880,7 +3990,7 @@ type AddChainLocalOverrideResponse_Body struct { func (x *AddChainLocalOverrideResponse_Body) Reset() { *x = AddChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3893,7 +4003,7 @@ func (x *AddChainLocalOverrideResponse_Body) String() string { func (*AddChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3930,7 +4040,7 @@ type GetChainLocalOverrideRequest_Body struct { func (x *GetChainLocalOverrideRequest_Body) Reset() { *x = GetChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3943,7 +4053,7 @@ func (x *GetChainLocalOverrideRequest_Body) String() string { func (*GetChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3985,7 +4095,7 @@ type GetChainLocalOverrideResponse_Body struct { func (x *GetChainLocalOverrideResponse_Body) Reset() { *x = GetChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[71] + mi := &file_pkg_services_control_service_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3998,7 +4108,7 @@ func (x *GetChainLocalOverrideResponse_Body) String() string { func (*GetChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[71] + mi := &file_pkg_services_control_service_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4033,7 +4143,7 @@ type ListChainLocalOverridesRequest_Body struct { func (x *ListChainLocalOverridesRequest_Body) Reset() { *x = ListChainLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[72] + mi := &file_pkg_services_control_service_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4046,7 +4156,7 @@ func (x *ListChainLocalOverridesRequest_Body) String() string { func (*ListChainLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[72] + mi := &file_pkg_services_control_service_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4081,7 +4191,7 @@ type ListChainLocalOverridesResponse_Body struct { func (x *ListChainLocalOverridesResponse_Body) Reset() { *x = ListChainLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[73] + mi := &file_pkg_services_control_service_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4094,7 +4204,7 @@ func (x *ListChainLocalOverridesResponse_Body) String() string { func (*ListChainLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[73] + mi := &file_pkg_services_control_service_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4129,7 +4239,7 @@ type ListTargetsLocalOverridesRequest_Body struct { func (x *ListTargetsLocalOverridesRequest_Body) Reset() { *x = ListTargetsLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[74] + mi := &file_pkg_services_control_service_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4142,7 +4252,7 @@ func (x *ListTargetsLocalOverridesRequest_Body) String() string { func (*ListTargetsLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListTargetsLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[74] + mi := &file_pkg_services_control_service_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4177,7 +4287,7 @@ type ListTargetsLocalOverridesResponse_Body struct { func (x *ListTargetsLocalOverridesResponse_Body) Reset() { *x = ListTargetsLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[75] + mi := &file_pkg_services_control_service_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4190,7 +4300,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) String() string { func (*ListTargetsLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListTargetsLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[75] + mi := &file_pkg_services_control_service_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4227,7 +4337,7 @@ type RemoveChainLocalOverrideRequest_Body struct { func (x *RemoveChainLocalOverrideRequest_Body) Reset() { *x = RemoveChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[76] + mi := &file_pkg_services_control_service_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4240,7 +4350,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) String() string { func (*RemoveChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[76] + mi := &file_pkg_services_control_service_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4279,7 +4389,7 @@ type RemoveChainLocalOverrideResponse_Body struct { func (x *RemoveChainLocalOverrideResponse_Body) Reset() { *x = RemoveChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[77] + mi := &file_pkg_services_control_service_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4292,7 +4402,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) String() string { func (*RemoveChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[77] + mi := &file_pkg_services_control_service_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4308,6 +4418,92 @@ func (*RemoveChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0} } +type RemoveChainLocalOverridesByTargetRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Target for which the overrides are applied. + Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` +} + +func (x *RemoveChainLocalOverridesByTargetRequest_Body) Reset() { + *x = RemoveChainLocalOverridesByTargetRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[80] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveChainLocalOverridesByTargetRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveChainLocalOverridesByTargetRequest_Body) ProtoMessage() {} + +func (x *RemoveChainLocalOverridesByTargetRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[80] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveChainLocalOverridesByTargetRequest_Body.ProtoReflect.Descriptor instead. +func (*RemoveChainLocalOverridesByTargetRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36, 0} +} + +func (x *RemoveChainLocalOverridesByTargetRequest_Body) GetTarget() *ChainTarget { + if x != nil { + return x.Target + } + return nil +} + +type RemoveChainLocalOverridesByTargetResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *RemoveChainLocalOverridesByTargetResponse_Body) Reset() { + *x = RemoveChainLocalOverridesByTargetResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[81] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveChainLocalOverridesByTargetResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveChainLocalOverridesByTargetResponse_Body) ProtoMessage() {} + +func (x *RemoveChainLocalOverridesByTargetResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[81] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveChainLocalOverridesByTargetResponse_Body.ProtoReflect.Descriptor instead. +func (*RemoveChainLocalOverridesByTargetResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0} +} + // Request body structure. type SealWriteCacheRequest_Body struct { state protoimpl.MessageState @@ -4323,7 +4519,7 @@ type SealWriteCacheRequest_Body struct { func (x *SealWriteCacheRequest_Body) Reset() { *x = SealWriteCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[78] + mi := &file_pkg_services_control_service_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4336,7 +4532,7 @@ func (x *SealWriteCacheRequest_Body) String() string { func (*SealWriteCacheRequest_Body) ProtoMessage() {} func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[78] + mi := &file_pkg_services_control_service_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4349,7 +4545,7 @@ func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheRequest_Body.ProtoReflect.Descriptor instead. func (*SealWriteCacheRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38, 0} } func (x *SealWriteCacheRequest_Body) GetShard_ID() [][]byte { @@ -4377,7 +4573,7 @@ type SealWriteCacheResponse_Body struct { func (x *SealWriteCacheResponse_Body) Reset() { *x = SealWriteCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[79] + mi := &file_pkg_services_control_service_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4390,7 +4586,7 @@ func (x *SealWriteCacheResponse_Body) String() string { func (*SealWriteCacheResponse_Body) ProtoMessage() {} func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[79] + mi := &file_pkg_services_control_service_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4403,7 +4599,7 @@ func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheResponse_Body.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39, 0} } func (x *SealWriteCacheResponse_Body) GetResults() []*SealWriteCacheResponse_Body_Status { @@ -4426,7 +4622,7 @@ type SealWriteCacheResponse_Body_Status struct { func (x *SealWriteCacheResponse_Body_Status) Reset() { *x = SealWriteCacheResponse_Body_Status{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[80] + mi := &file_pkg_services_control_service_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4439,7 +4635,7 @@ func (x *SealWriteCacheResponse_Body_Status) String() string { func (*SealWriteCacheResponse_Body_Status) ProtoMessage() {} func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[80] + mi := &file_pkg_services_control_service_proto_msgTypes[84] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4452,7 +4648,7 @@ func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message // Deprecated: Use SealWriteCacheResponse_Body_Status.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse_Body_Status) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39, 0, 0} } func (x *SealWriteCacheResponse_Body_Status) GetShard_ID() []byte { @@ -4487,7 +4683,7 @@ type DetachShardsRequest_Body struct { func (x *DetachShardsRequest_Body) Reset() { *x = DetachShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[81] + mi := &file_pkg_services_control_service_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4500,7 +4696,7 @@ func (x *DetachShardsRequest_Body) String() string { func (*DetachShardsRequest_Body) ProtoMessage() {} func (x *DetachShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[81] + mi := &file_pkg_services_control_service_proto_msgTypes[85] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4513,7 +4709,7 @@ func (x *DetachShardsRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsRequest_Body.ProtoReflect.Descriptor instead. func (*DetachShardsRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{40, 0} } func (x *DetachShardsRequest_Body) GetShard_ID() [][]byte { @@ -4532,7 +4728,7 @@ type DetachShardsResponse_Body struct { func (x *DetachShardsResponse_Body) Reset() { *x = DetachShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[82] + mi := &file_pkg_services_control_service_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4545,7 +4741,7 @@ func (x *DetachShardsResponse_Body) String() string { func (*DetachShardsResponse_Body) ProtoMessage() {} func (x *DetachShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[82] + mi := &file_pkg_services_control_service_proto_msgTypes[86] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4558,7 +4754,7 @@ func (x *DetachShardsResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsResponse_Body.ProtoReflect.Descriptor instead. func (*DetachShardsResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41, 0} } var File_pkg_services_control_service_proto protoreflect.FileDescriptor @@ -5026,176 +5222,211 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, - 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, - 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, - 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, + 0x22, 0xde, 0x01, 0x0a, 0x28, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, + 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x22, 0xb2, 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, + 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, + 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, - 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, - 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, - 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, + 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, - 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, + 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xa8, 0x0e, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, - 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, - 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, - 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, - 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, - 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, - 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb5, + 0x0f, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, + 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, + 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, + 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, + 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, + 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, - 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, - 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, - 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, - 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, - 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, + 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, + 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, + 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, + 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, - 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, - 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, - 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, + 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, + 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, + 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, + 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, + 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, + 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -5211,7 +5442,7 @@ func file_pkg_services_control_service_proto_rawDescGZIP() []byte { } var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 83) +var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 87) var file_pkg_services_control_service_proto_goTypes = []interface{}{ (StartShardEvacuationRequest_Body_Scope)(0), // 0: control.StartShardEvacuationRequest.Body.Scope (GetShardEvacuationStatusResponse_Body_Status)(0), // 1: control.GetShardEvacuationStatusResponse.Body.Status @@ -5251,200 +5482,211 @@ var file_pkg_services_control_service_proto_goTypes = []interface{}{ (*ListTargetsLocalOverridesResponse)(nil), // 35: control.ListTargetsLocalOverridesResponse (*RemoveChainLocalOverrideRequest)(nil), // 36: control.RemoveChainLocalOverrideRequest (*RemoveChainLocalOverrideResponse)(nil), // 37: control.RemoveChainLocalOverrideResponse - (*SealWriteCacheRequest)(nil), // 38: control.SealWriteCacheRequest - (*SealWriteCacheResponse)(nil), // 39: control.SealWriteCacheResponse - (*DetachShardsRequest)(nil), // 40: control.DetachShardsRequest - (*DetachShardsResponse)(nil), // 41: control.DetachShardsResponse - (*HealthCheckRequest_Body)(nil), // 42: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 43: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 44: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 45: control.SetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 46: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 47: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 48: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 49: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 50: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 51: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 52: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 53: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 54: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 55: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 56: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 57: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 58: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 59: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 60: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 61: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 62: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 63: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 64: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 65: control.GetShardEvacuationStatusResponse.Body.Duration - (*ResetShardEvacuationStatusRequest_Body)(nil), // 66: control.ResetShardEvacuationStatusRequest.Body - (*ResetShardEvacuationStatusResponse_Body)(nil), // 67: control.ResetShardEvacuationStatusResponse.Body - (*StopShardEvacuationRequest_Body)(nil), // 68: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 69: control.StopShardEvacuationResponse.Body - (*AddChainLocalOverrideRequest_Body)(nil), // 70: control.AddChainLocalOverrideRequest.Body - (*AddChainLocalOverrideResponse_Body)(nil), // 71: control.AddChainLocalOverrideResponse.Body - (*GetChainLocalOverrideRequest_Body)(nil), // 72: control.GetChainLocalOverrideRequest.Body - (*GetChainLocalOverrideResponse_Body)(nil), // 73: control.GetChainLocalOverrideResponse.Body - (*ListChainLocalOverridesRequest_Body)(nil), // 74: control.ListChainLocalOverridesRequest.Body - (*ListChainLocalOverridesResponse_Body)(nil), // 75: control.ListChainLocalOverridesResponse.Body - (*ListTargetsLocalOverridesRequest_Body)(nil), // 76: control.ListTargetsLocalOverridesRequest.Body - (*ListTargetsLocalOverridesResponse_Body)(nil), // 77: control.ListTargetsLocalOverridesResponse.Body - (*RemoveChainLocalOverrideRequest_Body)(nil), // 78: control.RemoveChainLocalOverrideRequest.Body - (*RemoveChainLocalOverrideResponse_Body)(nil), // 79: control.RemoveChainLocalOverrideResponse.Body - (*SealWriteCacheRequest_Body)(nil), // 80: control.SealWriteCacheRequest.Body - (*SealWriteCacheResponse_Body)(nil), // 81: control.SealWriteCacheResponse.Body - (*SealWriteCacheResponse_Body_Status)(nil), // 82: control.SealWriteCacheResponse.Body.Status - (*DetachShardsRequest_Body)(nil), // 83: control.DetachShardsRequest.Body - (*DetachShardsResponse_Body)(nil), // 84: control.DetachShardsResponse.Body - (*Signature)(nil), // 85: control.Signature - (NetmapStatus)(0), // 86: control.NetmapStatus - (HealthStatus)(0), // 87: control.HealthStatus - (*ShardInfo)(nil), // 88: control.ShardInfo - (ShardMode)(0), // 89: control.ShardMode - (*ChainTarget)(nil), // 90: control.ChainTarget + (*RemoveChainLocalOverridesByTargetRequest)(nil), // 38: control.RemoveChainLocalOverridesByTargetRequest + (*RemoveChainLocalOverridesByTargetResponse)(nil), // 39: control.RemoveChainLocalOverridesByTargetResponse + (*SealWriteCacheRequest)(nil), // 40: control.SealWriteCacheRequest + (*SealWriteCacheResponse)(nil), // 41: control.SealWriteCacheResponse + (*DetachShardsRequest)(nil), // 42: control.DetachShardsRequest + (*DetachShardsResponse)(nil), // 43: control.DetachShardsResponse + (*HealthCheckRequest_Body)(nil), // 44: control.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 45: control.HealthCheckResponse.Body + (*SetNetmapStatusRequest_Body)(nil), // 46: control.SetNetmapStatusRequest.Body + (*SetNetmapStatusResponse_Body)(nil), // 47: control.SetNetmapStatusResponse.Body + (*DropObjectsRequest_Body)(nil), // 48: control.DropObjectsRequest.Body + (*DropObjectsResponse_Body)(nil), // 49: control.DropObjectsResponse.Body + (*ListShardsRequest_Body)(nil), // 50: control.ListShardsRequest.Body + (*ListShardsResponse_Body)(nil), // 51: control.ListShardsResponse.Body + (*SetShardModeRequest_Body)(nil), // 52: control.SetShardModeRequest.Body + (*SetShardModeResponse_Body)(nil), // 53: control.SetShardModeResponse.Body + (*SynchronizeTreeRequest_Body)(nil), // 54: control.SynchronizeTreeRequest.Body + (*SynchronizeTreeResponse_Body)(nil), // 55: control.SynchronizeTreeResponse.Body + (*EvacuateShardRequest_Body)(nil), // 56: control.EvacuateShardRequest.Body + (*EvacuateShardResponse_Body)(nil), // 57: control.EvacuateShardResponse.Body + (*FlushCacheRequest_Body)(nil), // 58: control.FlushCacheRequest.Body + (*FlushCacheResponse_Body)(nil), // 59: control.FlushCacheResponse.Body + (*DoctorRequest_Body)(nil), // 60: control.DoctorRequest.Body + (*DoctorResponse_Body)(nil), // 61: control.DoctorResponse.Body + (*StartShardEvacuationRequest_Body)(nil), // 62: control.StartShardEvacuationRequest.Body + (*StartShardEvacuationResponse_Body)(nil), // 63: control.StartShardEvacuationResponse.Body + (*GetShardEvacuationStatusRequest_Body)(nil), // 64: control.GetShardEvacuationStatusRequest.Body + (*GetShardEvacuationStatusResponse_Body)(nil), // 65: control.GetShardEvacuationStatusResponse.Body + (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 66: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 67: control.GetShardEvacuationStatusResponse.Body.Duration + (*ResetShardEvacuationStatusRequest_Body)(nil), // 68: control.ResetShardEvacuationStatusRequest.Body + (*ResetShardEvacuationStatusResponse_Body)(nil), // 69: control.ResetShardEvacuationStatusResponse.Body + (*StopShardEvacuationRequest_Body)(nil), // 70: control.StopShardEvacuationRequest.Body + (*StopShardEvacuationResponse_Body)(nil), // 71: control.StopShardEvacuationResponse.Body + (*AddChainLocalOverrideRequest_Body)(nil), // 72: control.AddChainLocalOverrideRequest.Body + (*AddChainLocalOverrideResponse_Body)(nil), // 73: control.AddChainLocalOverrideResponse.Body + (*GetChainLocalOverrideRequest_Body)(nil), // 74: control.GetChainLocalOverrideRequest.Body + (*GetChainLocalOverrideResponse_Body)(nil), // 75: control.GetChainLocalOverrideResponse.Body + (*ListChainLocalOverridesRequest_Body)(nil), // 76: control.ListChainLocalOverridesRequest.Body + (*ListChainLocalOverridesResponse_Body)(nil), // 77: control.ListChainLocalOverridesResponse.Body + (*ListTargetsLocalOverridesRequest_Body)(nil), // 78: control.ListTargetsLocalOverridesRequest.Body + (*ListTargetsLocalOverridesResponse_Body)(nil), // 79: control.ListTargetsLocalOverridesResponse.Body + (*RemoveChainLocalOverrideRequest_Body)(nil), // 80: control.RemoveChainLocalOverrideRequest.Body + (*RemoveChainLocalOverrideResponse_Body)(nil), // 81: control.RemoveChainLocalOverrideResponse.Body + (*RemoveChainLocalOverridesByTargetRequest_Body)(nil), // 82: control.RemoveChainLocalOverridesByTargetRequest.Body + (*RemoveChainLocalOverridesByTargetResponse_Body)(nil), // 83: control.RemoveChainLocalOverridesByTargetResponse.Body + (*SealWriteCacheRequest_Body)(nil), // 84: control.SealWriteCacheRequest.Body + (*SealWriteCacheResponse_Body)(nil), // 85: control.SealWriteCacheResponse.Body + (*SealWriteCacheResponse_Body_Status)(nil), // 86: control.SealWriteCacheResponse.Body.Status + (*DetachShardsRequest_Body)(nil), // 87: control.DetachShardsRequest.Body + (*DetachShardsResponse_Body)(nil), // 88: control.DetachShardsResponse.Body + (*Signature)(nil), // 89: control.Signature + (NetmapStatus)(0), // 90: control.NetmapStatus + (HealthStatus)(0), // 91: control.HealthStatus + (*ShardInfo)(nil), // 92: control.ShardInfo + (ShardMode)(0), // 93: control.ShardMode + (*ChainTarget)(nil), // 94: control.ChainTarget } var file_pkg_services_control_service_proto_depIdxs = []int32{ - 42, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 85, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 43, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 85, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 44, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 85, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 45, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 85, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 46, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 85, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature - 47, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 85, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature - 48, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 85, // 13: control.ListShardsRequest.signature:type_name -> control.Signature - 49, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 85, // 15: control.ListShardsResponse.signature:type_name -> control.Signature - 50, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 85, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature - 51, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 85, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature - 52, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 85, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 53, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 85, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 54, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 85, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature - 55, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 85, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature - 56, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 85, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature - 57, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 85, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature - 58, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 85, // 33: control.DoctorRequest.signature:type_name -> control.Signature - 59, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 85, // 35: control.DoctorResponse.signature:type_name -> control.Signature - 60, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 85, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 61, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 85, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 62, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 85, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 63, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 85, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 66, // 44: control.ResetShardEvacuationStatusRequest.body:type_name -> control.ResetShardEvacuationStatusRequest.Body - 85, // 45: control.ResetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 67, // 46: control.ResetShardEvacuationStatusResponse.body:type_name -> control.ResetShardEvacuationStatusResponse.Body - 85, // 47: control.ResetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 68, // 48: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 85, // 49: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 69, // 50: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 85, // 51: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 70, // 52: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body - 85, // 53: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature - 71, // 54: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body - 85, // 55: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature - 72, // 56: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body - 85, // 57: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature - 73, // 58: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body - 85, // 59: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature - 74, // 60: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body - 85, // 61: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature - 75, // 62: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body - 85, // 63: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature - 76, // 64: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body - 85, // 65: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature - 77, // 66: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body - 85, // 67: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature - 78, // 68: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body - 85, // 69: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature - 79, // 70: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body - 85, // 71: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature - 80, // 72: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body - 85, // 73: control.SealWriteCacheRequest.signature:type_name -> control.Signature - 81, // 74: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body - 85, // 75: control.SealWriteCacheResponse.signature:type_name -> control.Signature - 83, // 76: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body - 85, // 77: control.DetachShardsRequest.signature:type_name -> control.Signature - 84, // 78: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body - 85, // 79: control.DetachShardsResponse.signature:type_name -> control.Signature - 86, // 80: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 87, // 81: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 86, // 82: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 88, // 83: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 89, // 84: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 1, // 85: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 65, // 86: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 64, // 87: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 90, // 88: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 90, // 89: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 90, // 90: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget - 90, // 91: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget - 90, // 92: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 82, // 93: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status - 2, // 94: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 4, // 95: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 6, // 96: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 8, // 97: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 10, // 98: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 12, // 99: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 14, // 100: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 20, // 101: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 22, // 102: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 24, // 103: control.ControlService.ResetShardEvacuationStatus:input_type -> control.ResetShardEvacuationStatusRequest - 26, // 104: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 16, // 105: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 18, // 106: control.ControlService.Doctor:input_type -> control.DoctorRequest - 28, // 107: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 30, // 108: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 32, // 109: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 36, // 110: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 34, // 111: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest - 38, // 112: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest - 40, // 113: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest - 3, // 114: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 5, // 115: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 7, // 116: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 9, // 117: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 11, // 118: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 13, // 119: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 15, // 120: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 21, // 121: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 23, // 122: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 25, // 123: control.ControlService.ResetShardEvacuationStatus:output_type -> control.ResetShardEvacuationStatusResponse - 27, // 124: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 17, // 125: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 19, // 126: control.ControlService.Doctor:output_type -> control.DoctorResponse - 29, // 127: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 31, // 128: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 33, // 129: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 37, // 130: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 35, // 131: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse - 39, // 132: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse - 41, // 133: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse - 114, // [114:134] is the sub-list for method output_type - 94, // [94:114] is the sub-list for method input_type - 94, // [94:94] is the sub-list for extension type_name - 94, // [94:94] is the sub-list for extension extendee - 0, // [0:94] is the sub-list for field type_name + 44, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body + 89, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature + 45, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body + 89, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature + 46, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body + 89, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature + 47, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body + 89, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature + 48, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body + 89, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature + 49, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body + 89, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature + 50, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body + 89, // 13: control.ListShardsRequest.signature:type_name -> control.Signature + 51, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body + 89, // 15: control.ListShardsResponse.signature:type_name -> control.Signature + 52, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body + 89, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature + 53, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body + 89, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature + 54, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body + 89, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature + 55, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body + 89, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature + 56, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body + 89, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature + 57, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body + 89, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature + 58, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body + 89, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature + 59, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body + 89, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature + 60, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body + 89, // 33: control.DoctorRequest.signature:type_name -> control.Signature + 61, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body + 89, // 35: control.DoctorResponse.signature:type_name -> control.Signature + 62, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body + 89, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature + 63, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body + 89, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature + 64, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body + 89, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 65, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body + 89, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 68, // 44: control.ResetShardEvacuationStatusRequest.body:type_name -> control.ResetShardEvacuationStatusRequest.Body + 89, // 45: control.ResetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 69, // 46: control.ResetShardEvacuationStatusResponse.body:type_name -> control.ResetShardEvacuationStatusResponse.Body + 89, // 47: control.ResetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 70, // 48: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body + 89, // 49: control.StopShardEvacuationRequest.signature:type_name -> control.Signature + 71, // 50: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body + 89, // 51: control.StopShardEvacuationResponse.signature:type_name -> control.Signature + 72, // 52: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body + 89, // 53: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature + 73, // 54: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body + 89, // 55: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature + 74, // 56: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body + 89, // 57: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature + 75, // 58: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body + 89, // 59: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature + 76, // 60: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body + 89, // 61: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature + 77, // 62: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body + 89, // 63: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature + 78, // 64: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body + 89, // 65: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature + 79, // 66: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body + 89, // 67: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature + 80, // 68: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body + 89, // 69: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature + 81, // 70: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body + 89, // 71: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature + 82, // 72: control.RemoveChainLocalOverridesByTargetRequest.body:type_name -> control.RemoveChainLocalOverridesByTargetRequest.Body + 89, // 73: control.RemoveChainLocalOverridesByTargetRequest.signature:type_name -> control.Signature + 83, // 74: control.RemoveChainLocalOverridesByTargetResponse.body:type_name -> control.RemoveChainLocalOverridesByTargetResponse.Body + 89, // 75: control.RemoveChainLocalOverridesByTargetResponse.signature:type_name -> control.Signature + 84, // 76: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body + 89, // 77: control.SealWriteCacheRequest.signature:type_name -> control.Signature + 85, // 78: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body + 89, // 79: control.SealWriteCacheResponse.signature:type_name -> control.Signature + 87, // 80: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body + 89, // 81: control.DetachShardsRequest.signature:type_name -> control.Signature + 88, // 82: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body + 89, // 83: control.DetachShardsResponse.signature:type_name -> control.Signature + 90, // 84: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus + 91, // 85: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus + 90, // 86: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus + 92, // 87: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo + 93, // 88: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode + 1, // 89: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status + 67, // 90: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration + 66, // 91: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + 94, // 92: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 94, // 93: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 94, // 94: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget + 94, // 95: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget + 94, // 96: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 94, // 97: control.RemoveChainLocalOverridesByTargetRequest.Body.target:type_name -> control.ChainTarget + 86, // 98: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status + 2, // 99: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 4, // 100: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 6, // 101: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 8, // 102: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 10, // 103: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 12, // 104: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 14, // 105: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 20, // 106: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 22, // 107: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 24, // 108: control.ControlService.ResetShardEvacuationStatus:input_type -> control.ResetShardEvacuationStatusRequest + 26, // 109: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 16, // 110: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 18, // 111: control.ControlService.Doctor:input_type -> control.DoctorRequest + 28, // 112: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 30, // 113: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 32, // 114: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 36, // 115: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 38, // 116: control.ControlService.RemoveChainLocalOverridesByTarget:input_type -> control.RemoveChainLocalOverridesByTargetRequest + 34, // 117: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest + 40, // 118: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest + 42, // 119: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest + 3, // 120: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 5, // 121: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 7, // 122: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 9, // 123: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 11, // 124: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 13, // 125: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 15, // 126: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 21, // 127: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 23, // 128: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 25, // 129: control.ControlService.ResetShardEvacuationStatus:output_type -> control.ResetShardEvacuationStatusResponse + 27, // 130: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 17, // 131: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 19, // 132: control.ControlService.Doctor:output_type -> control.DoctorResponse + 29, // 133: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 31, // 134: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 33, // 135: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 37, // 136: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 39, // 137: control.ControlService.RemoveChainLocalOverridesByTarget:output_type -> control.RemoveChainLocalOverridesByTargetResponse + 35, // 138: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse + 41, // 139: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse + 43, // 140: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse + 120, // [120:141] is the sub-list for method output_type + 99, // [99:120] is the sub-list for method input_type + 99, // [99:99] is the sub-list for extension type_name + 99, // [99:99] is the sub-list for extension extendee + 0, // [0:99] is the sub-list for field type_name } func init() { file_pkg_services_control_service_proto_init() } @@ -5887,7 +6129,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest); i { + switch v := v.(*RemoveChainLocalOverridesByTargetRequest); i { case 0: return &v.state case 1: @@ -5899,7 +6141,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse); i { + switch v := v.(*RemoveChainLocalOverridesByTargetResponse); i { case 0: return &v.state case 1: @@ -5911,7 +6153,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsRequest); i { + switch v := v.(*SealWriteCacheRequest); i { case 0: return &v.state case 1: @@ -5923,7 +6165,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsResponse); i { + switch v := v.(*SealWriteCacheResponse); i { case 0: return &v.state case 1: @@ -5935,7 +6177,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { + switch v := v.(*DetachShardsRequest); i { case 0: return &v.state case 1: @@ -5947,7 +6189,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { + switch v := v.(*DetachShardsResponse); i { case 0: return &v.state case 1: @@ -5959,7 +6201,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest_Body); i { + switch v := v.(*HealthCheckRequest_Body); i { case 0: return &v.state case 1: @@ -5971,7 +6213,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse_Body); i { + switch v := v.(*HealthCheckResponse_Body); i { case 0: return &v.state case 1: @@ -5983,7 +6225,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest_Body); i { + switch v := v.(*SetNetmapStatusRequest_Body); i { case 0: return &v.state case 1: @@ -5995,7 +6237,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse_Body); i { + switch v := v.(*SetNetmapStatusResponse_Body); i { case 0: return &v.state case 1: @@ -6007,7 +6249,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest_Body); i { + switch v := v.(*DropObjectsRequest_Body); i { case 0: return &v.state case 1: @@ -6019,7 +6261,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse_Body); i { + switch v := v.(*DropObjectsResponse_Body); i { case 0: return &v.state case 1: @@ -6031,7 +6273,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest_Body); i { + switch v := v.(*ListShardsRequest_Body); i { case 0: return &v.state case 1: @@ -6043,7 +6285,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse_Body); i { + switch v := v.(*ListShardsResponse_Body); i { case 0: return &v.state case 1: @@ -6055,7 +6297,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest_Body); i { + switch v := v.(*SetShardModeRequest_Body); i { case 0: return &v.state case 1: @@ -6067,7 +6309,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse_Body); i { + switch v := v.(*SetShardModeResponse_Body); i { case 0: return &v.state case 1: @@ -6079,7 +6321,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest_Body); i { + switch v := v.(*SynchronizeTreeRequest_Body); i { case 0: return &v.state case 1: @@ -6091,7 +6333,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse_Body); i { + switch v := v.(*SynchronizeTreeResponse_Body); i { case 0: return &v.state case 1: @@ -6103,7 +6345,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest_Body); i { + switch v := v.(*EvacuateShardRequest_Body); i { case 0: return &v.state case 1: @@ -6115,7 +6357,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse_Body); i { + switch v := v.(*EvacuateShardResponse_Body); i { case 0: return &v.state case 1: @@ -6127,7 +6369,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest_Body); i { + switch v := v.(*FlushCacheRequest_Body); i { case 0: return &v.state case 1: @@ -6139,7 +6381,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse_Body); i { + switch v := v.(*FlushCacheResponse_Body); i { case 0: return &v.state case 1: @@ -6151,7 +6393,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest_Body); i { + switch v := v.(*DoctorRequest_Body); i { case 0: return &v.state case 1: @@ -6163,7 +6405,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse_Body); i { + switch v := v.(*DoctorResponse_Body); i { case 0: return &v.state case 1: @@ -6175,7 +6417,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest_Body); i { + switch v := v.(*StartShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -6187,7 +6429,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body); i { + switch v := v.(*StartShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -6199,7 +6441,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { + switch v := v.(*GetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -6211,7 +6453,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -6223,7 +6465,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusRequest_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { case 0: return &v.state case 1: @@ -6235,7 +6477,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusResponse_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { case 0: return &v.state case 1: @@ -6247,7 +6489,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest_Body); i { + switch v := v.(*ResetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -6259,7 +6501,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse_Body); i { + switch v := v.(*ResetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -6271,7 +6513,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest_Body); i { + switch v := v.(*StopShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -6283,7 +6525,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse_Body); i { + switch v := v.(*StopShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -6295,7 +6537,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest_Body); i { + switch v := v.(*AddChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6307,7 +6549,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse_Body); i { + switch v := v.(*AddChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6319,7 +6561,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest_Body); i { + switch v := v.(*GetChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6331,7 +6573,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse_Body); i { + switch v := v.(*GetChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6343,7 +6585,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { + switch v := v.(*ListChainLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -6355,7 +6597,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { + switch v := v.(*ListChainLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -6367,7 +6609,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -6379,7 +6621,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { + switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -6391,7 +6633,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest_Body); i { + switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6403,7 +6645,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body); i { + switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6415,7 +6657,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body_Status); i { + switch v := v.(*RemoveChainLocalOverridesByTargetRequest_Body); i { case 0: return &v.state case 1: @@ -6427,7 +6669,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsRequest_Body); i { + switch v := v.(*RemoveChainLocalOverridesByTargetResponse_Body); i { case 0: return &v.state case 1: @@ -6439,6 +6681,54 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body_Status); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DetachShardsRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DetachShardsResponse_Body); i { case 0: return &v.state @@ -6457,7 +6747,7 @@ func file_pkg_services_control_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_service_proto_rawDesc, NumEnums: 2, - NumMessages: 83, + NumMessages: 87, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 8501e952f1..04ea62e0e5 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -60,6 +60,9 @@ service ControlService { // Remove local access policy engine overrides stored in the node by chaind id. rpc RemoveChainLocalOverride (RemoveChainLocalOverrideRequest) returns (RemoveChainLocalOverrideResponse); + // Remove local access policy engine overrides stored in the node by chaind id. + rpc RemoveChainLocalOverridesByTarget (RemoveChainLocalOverridesByTargetRequest) returns (RemoveChainLocalOverridesByTargetResponse); + // List targets of the local APE overrides stored in the node. rpc ListTargetsLocalOverrides (ListTargetsLocalOverridesRequest) returns (ListTargetsLocalOverridesResponse); @@ -592,6 +595,26 @@ message RemoveChainLocalOverrideResponse { Signature signature = 2; } +message RemoveChainLocalOverridesByTargetRequest { + message Body { + // Target for which the overrides are applied. + ChainTarget target = 1; + } + + Body body = 1; + + Signature signature = 2; +} + +message RemoveChainLocalOverridesByTargetResponse { + message Body { + } + + Body body = 1; + + Signature signature = 2; +} + message SealWriteCacheRequest { // Request body structure. message Body { diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index b90749269d..9d8d6376c9 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -3085,6 +3085,169 @@ func (x *RemoveChainLocalOverrideResponse) SetSignature(sig *Signature) { x.Signature = sig } +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveChainLocalOverridesByTargetRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Target) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveChainLocalOverridesByTargetRequest_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveChainLocalOverridesByTargetRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveChainLocalOverridesByTargetRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *RemoveChainLocalOverridesByTargetRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *RemoveChainLocalOverridesByTargetRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *RemoveChainLocalOverridesByTargetRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveChainLocalOverridesByTargetResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveChainLocalOverridesByTargetResponse_Body) StableMarshal(buf []byte) []byte { + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *RemoveChainLocalOverridesByTargetResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *RemoveChainLocalOverridesByTargetResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *RemoveChainLocalOverridesByTargetResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *RemoveChainLocalOverridesByTargetResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *RemoveChainLocalOverridesByTargetResponse) SetSignature(sig *Signature) { + x.Signature = sig +} + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index ad33e330ae..95264fcd3e 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -19,26 +19,27 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - ControlService_HealthCheck_FullMethodName = "/control.ControlService/HealthCheck" - ControlService_SetNetmapStatus_FullMethodName = "/control.ControlService/SetNetmapStatus" - ControlService_DropObjects_FullMethodName = "/control.ControlService/DropObjects" - ControlService_ListShards_FullMethodName = "/control.ControlService/ListShards" - ControlService_SetShardMode_FullMethodName = "/control.ControlService/SetShardMode" - ControlService_SynchronizeTree_FullMethodName = "/control.ControlService/SynchronizeTree" - ControlService_EvacuateShard_FullMethodName = "/control.ControlService/EvacuateShard" - ControlService_StartShardEvacuation_FullMethodName = "/control.ControlService/StartShardEvacuation" - ControlService_GetShardEvacuationStatus_FullMethodName = "/control.ControlService/GetShardEvacuationStatus" - ControlService_ResetShardEvacuationStatus_FullMethodName = "/control.ControlService/ResetShardEvacuationStatus" - ControlService_StopShardEvacuation_FullMethodName = "/control.ControlService/StopShardEvacuation" - ControlService_FlushCache_FullMethodName = "/control.ControlService/FlushCache" - ControlService_Doctor_FullMethodName = "/control.ControlService/Doctor" - ControlService_AddChainLocalOverride_FullMethodName = "/control.ControlService/AddChainLocalOverride" - ControlService_GetChainLocalOverride_FullMethodName = "/control.ControlService/GetChainLocalOverride" - ControlService_ListChainLocalOverrides_FullMethodName = "/control.ControlService/ListChainLocalOverrides" - ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" - ControlService_ListTargetsLocalOverrides_FullMethodName = "/control.ControlService/ListTargetsLocalOverrides" - ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" - ControlService_DetachShards_FullMethodName = "/control.ControlService/DetachShards" + ControlService_HealthCheck_FullMethodName = "/control.ControlService/HealthCheck" + ControlService_SetNetmapStatus_FullMethodName = "/control.ControlService/SetNetmapStatus" + ControlService_DropObjects_FullMethodName = "/control.ControlService/DropObjects" + ControlService_ListShards_FullMethodName = "/control.ControlService/ListShards" + ControlService_SetShardMode_FullMethodName = "/control.ControlService/SetShardMode" + ControlService_SynchronizeTree_FullMethodName = "/control.ControlService/SynchronizeTree" + ControlService_EvacuateShard_FullMethodName = "/control.ControlService/EvacuateShard" + ControlService_StartShardEvacuation_FullMethodName = "/control.ControlService/StartShardEvacuation" + ControlService_GetShardEvacuationStatus_FullMethodName = "/control.ControlService/GetShardEvacuationStatus" + ControlService_ResetShardEvacuationStatus_FullMethodName = "/control.ControlService/ResetShardEvacuationStatus" + ControlService_StopShardEvacuation_FullMethodName = "/control.ControlService/StopShardEvacuation" + ControlService_FlushCache_FullMethodName = "/control.ControlService/FlushCache" + ControlService_Doctor_FullMethodName = "/control.ControlService/Doctor" + ControlService_AddChainLocalOverride_FullMethodName = "/control.ControlService/AddChainLocalOverride" + ControlService_GetChainLocalOverride_FullMethodName = "/control.ControlService/GetChainLocalOverride" + ControlService_ListChainLocalOverrides_FullMethodName = "/control.ControlService/ListChainLocalOverrides" + ControlService_RemoveChainLocalOverride_FullMethodName = "/control.ControlService/RemoveChainLocalOverride" + ControlService_RemoveChainLocalOverridesByTarget_FullMethodName = "/control.ControlService/RemoveChainLocalOverridesByTarget" + ControlService_ListTargetsLocalOverrides_FullMethodName = "/control.ControlService/ListTargetsLocalOverrides" + ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" + ControlService_DetachShards_FullMethodName = "/control.ControlService/DetachShards" ) // ControlServiceClient is the client API for ControlService service. @@ -80,6 +81,8 @@ type ControlServiceClient interface { ListChainLocalOverrides(ctx context.Context, in *ListChainLocalOverridesRequest, opts ...grpc.CallOption) (*ListChainLocalOverridesResponse, error) // Remove local access policy engine overrides stored in the node by chaind id. RemoveChainLocalOverride(ctx context.Context, in *RemoveChainLocalOverrideRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverrideResponse, error) + // Remove local access policy engine overrides stored in the node by chaind id. + RemoveChainLocalOverridesByTarget(ctx context.Context, in *RemoveChainLocalOverridesByTargetRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverridesByTargetResponse, error) // List targets of the local APE overrides stored in the node. ListTargetsLocalOverrides(ctx context.Context, in *ListTargetsLocalOverridesRequest, opts ...grpc.CallOption) (*ListTargetsLocalOverridesResponse, error) // Flush objects from write-cache and move it to degraded read only mode. @@ -249,6 +252,15 @@ func (c *controlServiceClient) RemoveChainLocalOverride(ctx context.Context, in return out, nil } +func (c *controlServiceClient) RemoveChainLocalOverridesByTarget(ctx context.Context, in *RemoveChainLocalOverridesByTargetRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverridesByTargetResponse, error) { + out := new(RemoveChainLocalOverridesByTargetResponse) + err := c.cc.Invoke(ctx, ControlService_RemoveChainLocalOverridesByTarget_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *controlServiceClient) ListTargetsLocalOverrides(ctx context.Context, in *ListTargetsLocalOverridesRequest, opts ...grpc.CallOption) (*ListTargetsLocalOverridesResponse, error) { out := new(ListTargetsLocalOverridesResponse) err := c.cc.Invoke(ctx, ControlService_ListTargetsLocalOverrides_FullMethodName, in, out, opts...) @@ -315,6 +327,8 @@ type ControlServiceServer interface { ListChainLocalOverrides(context.Context, *ListChainLocalOverridesRequest) (*ListChainLocalOverridesResponse, error) // Remove local access policy engine overrides stored in the node by chaind id. RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) + // Remove local access policy engine overrides stored in the node by chaind id. + RemoveChainLocalOverridesByTarget(context.Context, *RemoveChainLocalOverridesByTargetRequest) (*RemoveChainLocalOverridesByTargetResponse, error) // List targets of the local APE overrides stored in the node. ListTargetsLocalOverrides(context.Context, *ListTargetsLocalOverridesRequest) (*ListTargetsLocalOverridesResponse, error) // Flush objects from write-cache and move it to degraded read only mode. @@ -378,6 +392,9 @@ func (UnimplementedControlServiceServer) ListChainLocalOverrides(context.Context func (UnimplementedControlServiceServer) RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveChainLocalOverride not implemented") } +func (UnimplementedControlServiceServer) RemoveChainLocalOverridesByTarget(context.Context, *RemoveChainLocalOverridesByTargetRequest) (*RemoveChainLocalOverridesByTargetResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveChainLocalOverridesByTarget not implemented") +} func (UnimplementedControlServiceServer) ListTargetsLocalOverrides(context.Context, *ListTargetsLocalOverridesRequest) (*ListTargetsLocalOverridesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListTargetsLocalOverrides not implemented") } @@ -705,6 +722,24 @@ func _ControlService_RemoveChainLocalOverride_Handler(srv interface{}, ctx conte return interceptor(ctx, in, info, handler) } +func _ControlService_RemoveChainLocalOverridesByTarget_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveChainLocalOverridesByTargetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).RemoveChainLocalOverridesByTarget(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_RemoveChainLocalOverridesByTarget_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).RemoveChainLocalOverridesByTarget(ctx, req.(*RemoveChainLocalOverridesByTargetRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ControlService_ListTargetsLocalOverrides_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListTargetsLocalOverridesRequest) if err := dec(in); err != nil { @@ -834,6 +869,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "RemoveChainLocalOverride", Handler: _ControlService_RemoveChainLocalOverride_Handler, }, + { + MethodName: "RemoveChainLocalOverridesByTarget", + Handler: _ControlService_RemoveChainLocalOverridesByTarget_Handler, + }, { MethodName: "ListTargetsLocalOverrides", Handler: _ControlService_ListTargetsLocalOverrides_Handler, From 11fde3cde4d19a274a953a5ea02d5f3aea7c3041 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 12 Mar 2024 13:43:16 +0300 Subject: [PATCH 0447/1413] [#976] cli: Allow to remove all chains by target Signed-off-by: Anton Nikiforov --- .../modules/control/remove_rule.go | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index 7684ac1dc7..4189ea76b2 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -2,6 +2,7 @@ package control import ( "encoding/hex" + "errors" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" @@ -13,21 +14,48 @@ import ( const ( chainIDFlag = "chain-id" chainIDHexFlag = "chain-id-hex" + allFlag = "all" ) -var removeRuleCmd = &cobra.Command{ - Use: "remove-rule", - Short: "Remove local override", - Long: "Remove local APE override of the node", - Run: removeRule, -} +var ( + errEmptyChainID = errors.New("chain id cannot be empty") + + removeRuleCmd = &cobra.Command{ + Use: "remove-rule", + Short: "Remove local override", + Long: "Remove local APE override of the node", + Run: removeRule, + } +) func removeRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) + hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) + removeAll, _ := cmd.Flags().GetBool(allFlag) + if removeAll { + req := &control.RemoveChainLocalOverridesByTargetRequest{ + Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{ + Target: parseTarget(cmd), + }, + } + signRequest(cmd, pk, req) + cli := getClient(cmd, pk) + var resp *control.RemoveChainLocalOverridesByTargetResponse + var err error + err = cli.ExecRaw(func(client *client.Client) error { + resp, err = control.RemoveChainLocalOverridesByTarget(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + cmd.Println("All rules have been removed.") + return + } chainID, _ := cmd.Flags().GetString(chainIDFlag) - hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) - + if chainID == "" { + commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID) + } chainIDRaw := []byte(chainID) if hexEncoded { @@ -69,4 +97,6 @@ func initControlRemoveRuleCmd() { _ = removeRuleCmd.MarkFlagRequired(targetTypeFlag) ff.String(chainIDFlag, "", "Chain id") ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + ff.Bool(allFlag, false, "Remove all chains") + removeRuleCmd.MarkFlagsMutuallyExclusive(allFlag, chainIDFlag) } From bf70d7784457442b30669b123eacb7aa5c24de04 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 7 Mar 2024 14:33:07 +0300 Subject: [PATCH 0448/1413] [#976] adm: Allow to remove all chains by target Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/commonflags/flags.go | 1 + .../internal/modules/morph/ape/ape.go | 24 +++++++++++++------ 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-adm/internal/commonflags/flags.go b/cmd/frostfs-adm/internal/commonflags/flags.go index 71c36b71ae..bf6c17bd11 100644 --- a/cmd/frostfs-adm/internal/commonflags/flags.go +++ b/cmd/frostfs-adm/internal/commonflags/flags.go @@ -36,4 +36,5 @@ const ( HomomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" CustomZoneFlag = "domain" AlphabetSizeFlag = "size" + AllFlag = "all" ) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index e3990da079..fc572f5ff6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -114,8 +114,9 @@ func initRemoveRuleChainCmd() { removeRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc) _ = removeRuleChainCmd.MarkFlagRequired(targetNameFlag) removeRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) - _ = removeRuleChainCmd.MarkFlagRequired(chainIDFlag) removeRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) + removeRuleChainCmd.Flags().Bool(commonflags.AllFlag, false, "Remove all chains for target") + removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, chainIDFlag) } func initListRuleChainsCmd() { @@ -157,14 +158,23 @@ func addRuleChain(cmd *cobra.Command, _ []string) { } func removeRuleChain(cmd *cobra.Command, _ []string) { - chainID := parseChainID(cmd) target := parseTarget(cmd) pci, ac := newPolicyContractInterface(cmd) - h, vub, err := pci.RemoveMorphRuleChain(parseChainName(cmd), target, chainID) - cmd.Println("Waiting for transaction to persist...") - _, err = ac.Wait(h, vub, err) - commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) - cmd.Println("Rule chain removed successfully") + removeAll, _ := cmd.Flags().GetBool(commonflags.AllFlag) + if removeAll { + h, vub, err := pci.RemoveMorphRuleChainsByTarget(parseChainName(cmd), target) + cmd.Println("Waiting for transaction to persist...") + _, err = ac.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) + cmd.Println("All chains for target removed successfully") + } else { + chainID := parseChainID(cmd) + h, vub, err := pci.RemoveMorphRuleChain(parseChainName(cmd), target, chainID) + cmd.Println("Waiting for transaction to persist...") + _, err = ac.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) + cmd.Println("Rule chain removed successfully") + } } func listRuleChains(cmd *cobra.Command, _ []string) { From fb9219af3961aa69c69e80a4526622ce637b0ddb Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 12 Mar 2024 11:02:14 +0300 Subject: [PATCH 0449/1413] [#976] Fix trailing whitespace and end of file Signed-off-by: Anton Nikiforov --- dev/empty_pass.yml | 2 +- docs/evacuation.md | 4 ++-- docs/shard-modes.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dev/empty_pass.yml b/dev/empty_pass.yml index 2a088f9529..1986cf9e44 100644 --- a/dev/empty_pass.yml +++ b/dev/empty_pass.yml @@ -1 +1 @@ -password: "" \ No newline at end of file +password: "" diff --git a/docs/evacuation.md b/docs/evacuation.md index 602e32e9b8..9db514a9e5 100644 --- a/docs/evacuation.md +++ b/docs/evacuation.md @@ -96,9 +96,9 @@ Shard IDs: 54Y8aot9uc7BSadw2XtYr3. Evacuated 618 objects out of 618, failed to e ### Start trees evacuation and await it completes ```bash frostfs-cli control shards evacuation start --id FxR6QujButNCHn7jjdhxGP --endpoint s01.frostfs.devenv:8081 --wallet ./../frostfs-dev-env/services/storage/wallet01.json --await --scope trees -Enter password > +Enter password > Shard evacuation has been successfully started. Progress will be reported every 5 seconds. Shard evacuation has been completed. Shard IDs: FxR6QujButNCHn7jjdhxGP. Evacuated 0 objects out of 0, failed to evacuate: 0, skipped: 0; evacuated 2 trees out of 2, failed to evacuate: 0. Started at: 2024-02-08T08:44:17Z UTC. Duration: 00:00:00. -``` \ No newline at end of file +``` diff --git a/docs/shard-modes.md b/docs/shard-modes.md index 3abc26a603..789a1c241a 100644 --- a/docs/shard-modes.md +++ b/docs/shard-modes.md @@ -51,4 +51,4 @@ Shard can automatically switch to a `degraded-read-only` mode in 3 cases: To detach a shard use `frostfs-cli control shards detach` command. This command removes the shards from the storage engine and closes all resources associated with the shards. -Limitation: `SIGHUP` or storage node restart lead to detached shard will be again online. \ No newline at end of file +Limitation: `SIGHUP` or storage node restart lead to detached shard will be again online. From d7be70e93f851df42d573f7ef736359745e75f0f Mon Sep 17 00:00:00 2001 From: aarifullin Date: Tue, 12 Mar 2024 17:08:09 +0300 Subject: [PATCH 0450/1413] [#1040] object: Wrap CheckAPE errors to status errors * All methods should wrap CheckAPE error, if it occurs, to status error. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/service.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index cc18a0bcf9..8f45a8ffaf 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -214,7 +214,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { - return nil, err + return nil, toStatusErr(err) } resp, err := c.next.Head(ctx, request) @@ -252,7 +252,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { - return nil, err + return nil, toStatusErr(err) } return resp, nil } @@ -306,7 +306,7 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { - return nil, err + return nil, toStatusErr(err) } resp, err := c.next.Delete(ctx, request) @@ -366,7 +366,7 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { - return nil, err + return nil, toStatusErr(err) } resp, err := c.next.GetRangeHash(ctx, request) @@ -375,7 +375,7 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { - return nil, err + return nil, toStatusErr(err) } return resp, nil } From bd216b79cb30e560165095172c44b7e48e2ce362 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 15 Mar 2024 09:54:36 +0300 Subject: [PATCH 0451/1413] Release v0.38.0 Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 3 ++- VERSION | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc29022309..7c69b69d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Changelog for FrostFS Node ### Removed ### Updated -## [v0.38.0-rc.2] +## [v0.38.0] ### Added - Add `trace_id` to logs in `frostfs-node` (#146) @@ -18,6 +18,7 @@ Changelog for FrostFS Node - Allow sealing writecache (#569) - Support tree service in data evacuation (#947) - Use new policy engine mechanism for access control (#770, #804) +- Log about active notary deposit waiting (#963) ### Changed - Sort output in `frostfs-cli` subcommands (#333) diff --git a/VERSION b/VERSION index e1d6235d32..765098dc40 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.36.0 +v0.38.0 From 7278201753e2e0abc3fd6013d8c3d6085dcfb34d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 11 Mar 2024 11:22:56 +0300 Subject: [PATCH 0452/1413] [#1030] adm: Add command `morph ape list-targets` Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/ape/ape.go | 40 +++++++++++++++++++ .../internal/modules/morph/ape/ape_util.go | 25 +++++++----- .../internal/modules/morph/ape/root.go | 1 + 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index fc572f5ff6..710595fe8c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -82,6 +82,15 @@ var ( }, Run: getAdmin, } + + listTargetsCmd = &cobra.Command{ + Use: "list-targets", + Short: "List targets", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + }, + Run: listTargets, + } ) func initAddRuleChainCmd() { @@ -146,6 +155,14 @@ func initGetAdminCmd() { getAdminCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) } +func initListTargetsCmd() { + Cmd.AddCommand(listTargetsCmd) + + listTargetsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + listTargetsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) + _ = listTargetsCmd.MarkFlagRequired(targetTypeFlag) +} + func addRuleChain(cmd *cobra.Command, _ []string) { chain := parseChain(cmd) target := parseTarget(cmd) @@ -215,6 +232,29 @@ func getAdmin(cmd *cobra.Command, _ []string) { cmd.Println(addr.StringLE()) } +func listTargets(cmd *cobra.Command, _ []string) { + typ, err := parseTargetType(cmd) + commonCmd.ExitOnErr(cmd, "parse target type error: %w", err) + pci, inv := newPolicyContractReaderInterface(cmd) + + sid, it, err := pci.ListTargetsIterator(typ) + commonCmd.ExitOnErr(cmd, "list targets error: %w", err) + items, err := inv.TraverseIterator(sid, &it, 0) + for err == nil && len(items) != 0 { + for _, item := range items { + bts, err := item.TryBytes() + commonCmd.ExitOnErr(cmd, "list targets error: %w", err) + if len(bts) == 0 { + cmd.Println("(no name)") + } else { + cmd.Println(string(bts)) + } + } + items, err = inv.TraverseIterator(sid, &it, 0) + commonCmd.ExitOnErr(cmd, "unable to list targets: %w", err) + } +} + func prettyJSONFormat(cmd *cobra.Command, chains []*apechain.Chain) { wr := bytes.NewBufferString("") data, err := json.Marshal(chains) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 253e130a8d..b3610e7f7b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -36,24 +36,27 @@ var ( ) func parseTarget(cmd *cobra.Command) policyengine.Target { - var targetType policyengine.TargetType - typ, _ := cmd.Flags().GetString(targetTypeFlag) - switch typ { - case namespaceTarget: - targetType = policyengine.Namespace - case containerTarget: - targetType = policyengine.Container - default: - commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) - } name, _ := cmd.Flags().GetString(targetNameFlag) + typ, err := parseTargetType(cmd) + commonCmd.ExitOnErr(cmd, "read target type error: %w", err) return policyengine.Target{ Name: name, - Type: targetType, + Type: typ, } } +func parseTargetType(cmd *cobra.Command) (policyengine.TargetType, error) { + typ, _ := cmd.Flags().GetString(targetTypeFlag) + switch typ { + case namespaceTarget: + return policyengine.Namespace, nil + case containerTarget: + return policyengine.Container, nil + } + return -1, errUnknownTargetType +} + func parseChainID(cmd *cobra.Command) apechain.ID { chainID, _ := cmd.Flags().GetString(chainIDFlag) if chainID == "" { diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/root.go b/cmd/frostfs-adm/internal/modules/morph/ape/root.go index 11b6894cfa..a4746cd2ce 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/root.go @@ -13,4 +13,5 @@ func init() { initListRuleChainsCmd() initSetAdminCmd() initGetAdminCmd() + initListTargetsCmd() } From 6959e617c49d5b4f9f66a0c88223cd317c82bb70 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Fri, 15 Mar 2024 15:16:52 +0300 Subject: [PATCH 0453/1413] [#1047] object: Set container owner ID property to ape request * Introduce ContainerOwner field in RequestContext. * Set ContainerOwner in aclv2 middleware. * Set PropertyKeyContainerOwnerID for object ape request. Signed-off-by: Airat Arifullin --- pkg/services/object/acl/v2/service.go | 36 +++--- pkg/services/object/ape/checker.go | 4 + pkg/services/object/ape/request.go | 7 +- pkg/services/object/ape/request_test.go | 29 +++-- pkg/services/object/ape/service.go | 159 +++++++++++++----------- pkg/services/object/request_context.go | 7 +- 6 files changed, 142 insertions(+), 100 deletions(-) diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index b51386e0c8..1f1c275cff 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -113,10 +113,11 @@ type wrappedGetObjectStream struct { func (w *wrappedGetObjectStream) Context() context.Context { return context.WithValue(w.GetObjectStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + Namespace: w.requestInfo.ContainerNamespace(), + ContainerOwner: w.requestInfo.ContainerOwner(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -137,10 +138,11 @@ type wrappedRangeStream struct { func (w *wrappedRangeStream) Context() context.Context { return context.WithValue(w.GetObjectRangeStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + Namespace: w.requestInfo.ContainerNamespace(), + ContainerOwner: w.requestInfo.ContainerOwner(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -161,10 +163,11 @@ type wrappedSearchStream struct { func (w *wrappedSearchStream) Context() context.Context { return context.WithValue(w.SearchStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + Namespace: w.requestInfo.ContainerNamespace(), + ContainerOwner: w.requestInfo.ContainerOwner(), + SenderKey: w.requestInfo.SenderKey(), + Role: w.requestInfo.RequestRole(), + SoftAPECheck: w.requestInfo.IsSoftAPECheck(), }) } @@ -471,10 +474,11 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { return context.WithValue(ctx, object.RequestContextKey, &object.RequestContext{ - Namespace: reqInfo.ContainerNamespace(), - SenderKey: reqInfo.SenderKey(), - Role: reqInfo.RequestRole(), - SoftAPECheck: reqInfo.IsSoftAPECheck(), + Namespace: reqInfo.ContainerNamespace(), + ContainerOwner: reqInfo.ContainerOwner(), + SenderKey: reqInfo.SenderKey(), + Role: reqInfo.RequestRole(), + SoftAPECheck: reqInfo.IsSoftAPECheck(), }) } diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 1d42d21d45..45efce5a7e 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -8,6 +8,7 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" @@ -48,6 +49,9 @@ type Prm struct { // An encoded sender's public key string. SenderKey string + // An encoded container's owner user ID. + ContainerOwner user.ID + // If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow. SoftAPECheck bool } diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index caf52645c6..3689bd1785 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -10,6 +10,7 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) @@ -78,11 +79,13 @@ func resourceName(cid cid.ID, oid *oid.ID, namespace string) string { } // objectProperties collects object properties from address parameters and a header if it is passed. -func objectProperties(cnr cid.ID, oid *oid.ID, header *objectV2.Header) map[string]string { +func objectProperties(cnr cid.ID, oid *oid.ID, cnrOwner user.ID, header *objectV2.Header) map[string]string { objectProps := map[string]string{ nativeschema.PropertyKeyObjectContainerID: cnr.EncodeToString(), } + objectProps[nativeschema.PropertyKeyContainerOwnerID] = cnrOwner.EncodeToString() + if oid != nil { objectProps[nativeschema.PropertyKeyObjectID] = oid.String() } @@ -149,7 +152,7 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (*request, err operation: prm.Method, resource: &resource{ name: resourceName(prm.Container, prm.Object, prm.Namespace), - properties: objectProperties(prm.Container, prm.Object, header), + properties: objectProperties(prm.Container, prm.Object, prm.ContainerOwner, header), }, properties: map[string]string{ nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index 0dcc0b84bc..c5b43fa8b7 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -8,11 +8,16 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" ) +const ( + testOwnerID = "FPPtmAi9TCX329" +) + func TestObjectProperties(t *testing.T) { for _, test := range []struct { name string @@ -82,8 +87,12 @@ func TestObjectProperties(t *testing.T) { obj := newObjectIDSDK(t, test.object) header := newHeaderObjectSDK(cnr, obj, test.header) - props := objectProperties(cnr, obj, header.ToV2().GetHeader()) + var testCnrOwner user.ID + require.NoError(t, testCnrOwner.DecodeString(testOwnerID)) + + props := objectProperties(cnr, obj, testCnrOwner, header.ToV2().GetHeader()) require.Equal(t, test.container, props[nativeschema.PropertyKeyObjectContainerID]) + require.Equal(t, testOwnerID, props[nativeschema.PropertyKeyContainerOwnerID]) if obj != nil { require.Equal(t, *test.object, props[nativeschema.PropertyKeyObjectID]) @@ -210,13 +219,17 @@ func TestNewAPERequest(t *testing.T) { cnr := newContainerIDSDK(t, test.container) obj := newObjectIDSDK(t, test.object) + var testCnrOwner user.ID + require.NoError(t, testCnrOwner.DecodeString(testOwnerID)) + prm := Prm{ - Namespace: test.namespace, - Method: method, - Container: cnr, - Object: obj, - Role: role, - SenderKey: senderKey, + Namespace: test.namespace, + Method: method, + Container: cnr, + Object: obj, + Role: role, + SenderKey: senderKey, + ContainerOwner: testCnrOwner, } headerSource := newHeaderProviderMock() @@ -247,7 +260,7 @@ func TestNewAPERequest(t *testing.T) { operation: method, resource: &resource{ name: resourceName(cnr, obj, prm.Namespace), - properties: objectProperties(cnr, obj, func() *objectV2.Header { + properties: objectProperties(cnr, obj, testCnrOwner, func() *objectV2.Header { if headerObjSDK != nil { return headerObjSDK.ToV2().GetHeader() } diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 8f45a8ffaf..0c203209df 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -14,6 +14,7 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) @@ -67,6 +68,8 @@ type getStreamBasicChecker struct { senderKey []byte + containerOwner user.ID + role string softAPECheck bool @@ -80,14 +83,15 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { } prm := Prm{ - Namespace: g.namespace, - Container: cnrID, - Object: objID, - Header: partInit.GetHeader(), - Method: nativeschema.MethodGetObject, - SenderKey: hex.EncodeToString(g.senderKey), - Role: g.role, - SoftAPECheck: g.softAPECheck, + Namespace: g.namespace, + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodGetObject, + SenderKey: hex.EncodeToString(g.senderKey), + ContainerOwner: g.containerOwner, + Role: g.role, + SoftAPECheck: g.softAPECheck, } if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { @@ -121,13 +125,14 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodGetObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodGetObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -162,14 +167,15 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: partInit.GetHeader(), - Method: nativeschema.MethodPutObject, - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - Role: nativeSchemaRole(reqCtx.Role), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodPutObject, + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + Role: nativeSchemaRole(reqCtx.Role), + SoftAPECheck: reqCtx.SoftAPECheck, } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -205,13 +211,14 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, toStatusErr(err) @@ -242,14 +249,15 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: header, - Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: header, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, toStatusErr(err) @@ -271,12 +279,13 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Method: nativeschema.MethodSearchObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Method: nativeschema.MethodSearchObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -297,13 +306,14 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodDeleteObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodDeleteObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return nil, toStatusErr(err) @@ -329,13 +339,14 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodRangeObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodRangeObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, }) if err != nil { return toStatusErr(err) @@ -356,13 +367,14 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodHashObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHashObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -392,14 +404,15 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Header: request.GetBody().GetObject().GetHeader(), - Method: nativeschema.MethodPutObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Header: request.GetBody().GetObject().GetHeader(), + Method: nativeschema.MethodPutObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { diff --git a/pkg/services/object/request_context.go b/pkg/services/object/request_context.go index e0e6c9ed97..6a0965b408 100644 --- a/pkg/services/object/request_context.go +++ b/pkg/services/object/request_context.go @@ -1,6 +1,9 @@ package object -import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" +) type RequestContextKeyT struct{} @@ -12,6 +15,8 @@ type RequestContext struct { SenderKey []byte + ContainerOwner user.ID + Role acl.Role SoftAPECheck bool From 6bf77cabd452bad85bb3418969a38b8fc24acb59 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 15 Mar 2024 10:10:03 +0300 Subject: [PATCH 0454/1413] [#1044] ape: Add morph chain cache Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 10 ++- cmd/frostfs-node/config/morph/config.go | 15 +++++ cmd/frostfs-node/config/morph/config_test.go | 2 + cmd/frostfs-node/policy_engine.go | 67 ++++++++++++++++++++ config/example/node.env | 1 + config/example/node.json | 3 +- config/example/node.yaml | 1 + docs/storage-node-configuration.md | 40 ++++++------ 8 files changed, 118 insertions(+), 21 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 48b76ac0f9..424970b8ff 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -24,6 +24,7 @@ import ( blobovniczaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza" fstreeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/fstree" loggerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/logger" + morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" objectconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/object" replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" @@ -68,6 +69,7 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + policy_engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" policy_client "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" neogoutil "github.com/nspcc-dev/neo-go/pkg/util" @@ -1074,10 +1076,16 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) { ) } - morphRuleStorage := policy_client.NewContractStorage( + var morphRuleStorage policy_engine.MorphRuleChainStorage + morphRuleStorage = policy_client.NewContractStorage( client.NewSwitchRPCGuardedActor(c.cfgMorph.client), c.cfgObject.cfgAccessPolicyEngine.policyContractHash) + cacheSize := morphconfig.APEChainCacheSize(c.appCfg) + if cacheSize > 0 { + morphRuleStorage = newMorphCache(morphRuleStorage, int(cacheSize), morphconfig.CacheTTL(c.appCfg)) + } + ape := newAccessPolicyEngine(morphRuleStorage, localOverrideDB) c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine = ape diff --git a/cmd/frostfs-node/config/morph/config.go b/cmd/frostfs-node/config/morph/config.go index 866223073a..c32940625b 100644 --- a/cmd/frostfs-node/config/morph/config.go +++ b/cmd/frostfs-node/config/morph/config.go @@ -25,6 +25,9 @@ const ( // SwitchIntervalDefault is a default Neo RPCs switch interval. SwitchIntervalDefault = 2 * time.Minute + + // APEChainCacheSizeDefault is a default value of APE chain cache. + APEChainCacheSizeDefault = 10_000 ) var errNoMorphEndpoints = errors.New("no morph chain RPC endpoints, see `morph.rpc_endpoint` section") @@ -99,3 +102,15 @@ func SwitchInterval(c *config.Config) time.Duration { return SwitchIntervalDefault } + +// APEChainCacheSize returns the value of "ape_chain_cache_size" config parameter +// from "morph" section. +// +// Returns 0 if the value is not positive integer. +// Returns APEChainCacheSizeDefault if the value is missing. +func APEChainCacheSize(c *config.Config) uint32 { + if c.Sub(subsection).Value("ape_chain_cache_size") == nil { + return APEChainCacheSizeDefault + } + return config.Uint32Safe(c.Sub(subsection), "ape_chain_cache_size") +} diff --git a/cmd/frostfs-node/config/morph/config_test.go b/cmd/frostfs-node/config/morph/config_test.go index a30733cd04..13da3d70d9 100644 --- a/cmd/frostfs-node/config/morph/config_test.go +++ b/cmd/frostfs-node/config/morph/config_test.go @@ -19,6 +19,7 @@ func TestMorphSection(t *testing.T) { require.Equal(t, morphconfig.DialTimeoutDefault, morphconfig.DialTimeout(empty)) require.Equal(t, morphconfig.CacheTTLDefault, morphconfig.CacheTTL(empty)) require.Equal(t, morphconfig.SwitchIntervalDefault, morphconfig.SwitchInterval(empty)) + require.Equal(t, uint32(morphconfig.APEChainCacheSizeDefault), morphconfig.APEChainCacheSize(empty)) }) const path = "../../../../config/example/node" @@ -39,6 +40,7 @@ func TestMorphSection(t *testing.T) { require.Equal(t, 30*time.Second, morphconfig.DialTimeout(c)) require.Equal(t, 15*time.Second, morphconfig.CacheTTL(c)) require.Equal(t, 3*time.Minute, morphconfig.SwitchInterval(c)) + require.Equal(t, uint32(100000), morphconfig.APEChainCacheSize(c)) } configtest.ForEachFileType(path, fileConfigTest) diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index 74cbf841c1..100520f508 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -2,11 +2,16 @@ package main import ( "sync" + "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" + "github.com/google/uuid" + "github.com/hashicorp/golang-lru/v2/expirable" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/util" ) type accessPolicyEngine struct { @@ -21,6 +26,68 @@ type accessPolicyEngine struct { var _ engine.LocalOverrideEngine = (*accessPolicyEngine)(nil) +var _ engine.MorphRuleChainStorage = (*morphAPEChainCache)(nil) + +type morphAPEChainCacheKey struct { + name chain.Name + target engine.Target +} + +type morphAPEChainCache struct { + source engine.MorphRuleChainStorage + cache *expirable.LRU[morphAPEChainCacheKey, []*chain.Chain] +} + +func newMorphCache(source engine.MorphRuleChainStorage, size int, ttl time.Duration) engine.MorphRuleChainStorage { + return &morphAPEChainCache{ + source: source, + cache: expirable.NewLRU(size, func(morphAPEChainCacheKey, []*chain.Chain) {}, ttl), + } +} + +func (m *morphAPEChainCache) AddMorphRuleChain(name chain.Name, target engine.Target, c *chain.Chain) (util.Uint256, uint32, error) { + m.cache.Remove(morphAPEChainCacheKey{name: name, target: target}) + return m.source.AddMorphRuleChain(name, target, c) +} + +func (m *morphAPEChainCache) GetAdmin() (util.Uint160, error) { + return m.source.GetAdmin() +} + +func (m *morphAPEChainCache) ListMorphRuleChains(name chain.Name, target engine.Target) ([]*chain.Chain, error) { + key := morphAPEChainCacheKey{name: name, target: target} + result, found := m.cache.Get(key) + if found { + return result, nil + } + + result, err := m.source.ListMorphRuleChains(name, target) + if err != nil { + return nil, err + } + + m.cache.Add(key, result) + return result, nil +} + +func (m *morphAPEChainCache) RemoveMorphRuleChain(name chain.Name, target engine.Target, chainID chain.ID) (util.Uint256, uint32, error) { + m.cache.Remove(morphAPEChainCacheKey{name: name, target: target}) + return m.source.RemoveMorphRuleChain(name, target, chainID) +} + +func (m *morphAPEChainCache) SetAdmin(addr util.Uint160) (util.Uint256, uint32, error) { + return m.source.SetAdmin(addr) +} + +func (m *morphAPEChainCache) ListTargetsIterator(targetType engine.TargetType) (uuid.UUID, result.Iterator, error) { + return m.source.ListTargetsIterator(targetType) +} + +func (m *morphAPEChainCache) RemoveMorphRuleChainsByTarget(name chain.Name, target engine.Target) (util.Uint256, uint32, error) { + m.cache.Remove(morphAPEChainCacheKey{name: name, target: target}) + return m.source.RemoveMorphRuleChainsByTarget(name, target) +} + func newAccessPolicyEngine( morphChainStorage engine.MorphRuleChainStorage, localOverrideDatabase chainbase.LocalOverrideDatabase, diff --git a/config/example/node.env b/config/example/node.env index 810a2842ba..976c426293 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -70,6 +70,7 @@ FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS="wss://rpc1.morph.frostfs.info:40341/ws" FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY=0 FROSTFS_MORPH_RPC_ENDPOINT_1_ADDRESS="wss://rpc2.morph.frostfs.info:40341/ws" FROSTFS_MORPH_RPC_ENDPOINT_1_PRIORITY=2 +FROSTFS_MORPH_APE_CHAIN_CACHE_SIZE=100000 # API Client section FROSTFS_APICLIENT_DIAL_TIMEOUT=15s diff --git a/config/example/node.json b/config/example/node.json index e24a12f5f8..648fb77b02 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -110,7 +110,8 @@ "address": "wss://rpc2.morph.frostfs.info:40341/ws", "priority": 2 } - ] + ], + "ape_chain_cache_size": 100000 }, "apiclient": { "dial_timeout": "15s", diff --git a/config/example/node.yaml b/config/example/node.yaml index c9886355ff..2dcf7c4d90 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -94,6 +94,7 @@ morph: priority: 0 - address: wss://rpc2.morph.frostfs.info:40341/ws priority: 2 + ape_chain_cache_size: 100000 apiclient: dial_timeout: 15s # timeout for FrostFS API client connection diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 15071f23df..02ead30204 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -12,19 +12,19 @@ There are some custom types used for brevity: # Structure -| Section | Description | -|--------------|---------------------------------------------------------| -| `logger` | [Logging parameters](#logger-section) | -| `pprof` | [PProf configuration](#pprof-section) | -| `prometheus` | [Prometheus metrics configuration](#prometheus-section) | -| `control` | [Control service configuration](#control-section) | -| `contracts` | [Override FrostFS contracts hashes](#contracts-section) | -| `morph` | [N3 blockchain client configuration](#morph-section) | -| `apiclient` | [FrostFS API client configuration](#apiclient-section) | -| `policer` | [Policer service configuration](#policer-section) | -| `replicator` | [Replicator service configuration](#replicator-section) | -| `storage` | [Storage engine configuration](#storage-section) | -| `runtime` | [Runtime configuration](#runtime-section) | +| Section | Description | +|------------------------|---------------------------------------------------------------------| +| `logger` | [Logging parameters](#logger-section) | +| `pprof` | [PProf configuration](#pprof-section) | +| `prometheus` | [Prometheus metrics configuration](#prometheus-section) | +| `control` | [Control service configuration](#control-section) | +| `contracts` | [Override FrostFS contracts hashes](#contracts-section) | +| `morph` | [N3 blockchain client configuration](#morph-section) | +| `apiclient` | [FrostFS API client configuration](#apiclient-section) | +| `policer` | [Policer service configuration](#policer-section) | +| `replicator` | [Replicator service configuration](#replicator-section) | +| `storage` | [Storage engine configuration](#storage-section) | +| `runtime` | [Runtime configuration](#runtime-section) | # `control` section @@ -139,6 +139,7 @@ contracts: morph: dial_timeout: 30s cache_ttl: 15s + ape_chain_cache_size: 10000 rpc_endpoint: - address: wss://rpc1.morph.frostfs.info:40341/ws priority: 1 @@ -147,12 +148,13 @@ morph: switch_interval: 2m ``` -| Parameter | Type | Default value | Description | -|-------------------|-----------------------------------------------------------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `dial_timeout` | `duration` | `5s` | Timeout for dialing connections to N3 RPCs. | -| `cache_ttl` | `duration` | Morph block time | Sidechain cache TTL value (min interval between similar calls).
Negative value disables caching.
Cached entities: containers, container lists, eACL tables. | -| `rpc_endpoint` | list of [endpoint descriptions](#rpc_endpoint-subsection) | | Array of endpoint descriptions. | -| `switch_interval` | `duration` | `2m` | Time interval between the attempts to connect to the highest priority RPC node if the connection is not established yet. | +| Parameter | Type | Default value | Description | +| ---------------------- | --------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `dial_timeout` | `duration` | `5s` | Timeout for dialing connections to N3 RPCs. | +| `cache_ttl` | `duration` | Morph block time | Sidechain cache TTL value (min interval between similar calls).
Negative value disables caching.
Cached entities: containers, container lists, eACL tables. | +| `rpc_endpoint` | list of [endpoint descriptions](#rpc_endpoint-subsection) | | Array of endpoint descriptions. | +| `switch_interval` | `duration` | `2m` | Time interval between the attempts to connect to the highest priority RPC node if the connection is not established yet. | +| `ape_chain_cache_size` | `int` | `10000` | Size of the morph cache for APE chains. | ## `rpc_endpoint` subsection | Parameter | Type | Default value | Description | From 5d58b44bc8895350d5aa70da6b71f0ade8847960 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 15 Mar 2024 10:14:17 +0300 Subject: [PATCH 0455/1413] [#1044] node: Drop unused methods from APE implementation Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/policy_engine.go | 40 ++++--------------------------- 2 files changed, 5 insertions(+), 37 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 424970b8ff..a1f7bba40f 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1076,7 +1076,7 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) { ) } - var morphRuleStorage policy_engine.MorphRuleChainStorage + var morphRuleStorage policy_engine.MorphRuleChainStorageReader morphRuleStorage = policy_client.NewContractStorage( client.NewSwitchRPCGuardedActor(c.cfgMorph.client), c.cfgObject.cfgAccessPolicyEngine.policyContractHash) diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index 100520f508..13e30a17e8 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -19,14 +19,10 @@ type accessPolicyEngine struct { chainRouter engine.ChainRouter - morphChainStorage engine.MorphRuleChainStorage - localOverrideDatabase chainbase.LocalOverrideDatabase } -var _ engine.LocalOverrideEngine = (*accessPolicyEngine)(nil) - -var _ engine.MorphRuleChainStorage = (*morphAPEChainCache)(nil) +var _ engine.MorphRuleChainStorageReader = (*morphAPEChainCache)(nil) type morphAPEChainCacheKey struct { name chain.Name @@ -34,22 +30,17 @@ type morphAPEChainCacheKey struct { } type morphAPEChainCache struct { - source engine.MorphRuleChainStorage + source engine.MorphRuleChainStorageReader cache *expirable.LRU[morphAPEChainCacheKey, []*chain.Chain] } -func newMorphCache(source engine.MorphRuleChainStorage, size int, ttl time.Duration) engine.MorphRuleChainStorage { +func newMorphCache(source engine.MorphRuleChainStorageReader, size int, ttl time.Duration) engine.MorphRuleChainStorageReader { return &morphAPEChainCache{ source: source, cache: expirable.NewLRU(size, func(morphAPEChainCacheKey, []*chain.Chain) {}, ttl), } } -func (m *morphAPEChainCache) AddMorphRuleChain(name chain.Name, target engine.Target, c *chain.Chain) (util.Uint256, uint32, error) { - m.cache.Remove(morphAPEChainCacheKey{name: name, target: target}) - return m.source.AddMorphRuleChain(name, target, c) -} - func (m *morphAPEChainCache) GetAdmin() (util.Uint160, error) { return m.source.GetAdmin() } @@ -70,26 +61,12 @@ func (m *morphAPEChainCache) ListMorphRuleChains(name chain.Name, target engine. return result, nil } -func (m *morphAPEChainCache) RemoveMorphRuleChain(name chain.Name, target engine.Target, chainID chain.ID) (util.Uint256, uint32, error) { - m.cache.Remove(morphAPEChainCacheKey{name: name, target: target}) - return m.source.RemoveMorphRuleChain(name, target, chainID) -} - -func (m *morphAPEChainCache) SetAdmin(addr util.Uint160) (util.Uint256, uint32, error) { - return m.source.SetAdmin(addr) -} - func (m *morphAPEChainCache) ListTargetsIterator(targetType engine.TargetType) (uuid.UUID, result.Iterator, error) { return m.source.ListTargetsIterator(targetType) } -func (m *morphAPEChainCache) RemoveMorphRuleChainsByTarget(name chain.Name, target engine.Target) (util.Uint256, uint32, error) { - m.cache.Remove(morphAPEChainCacheKey{name: name, target: target}) - return m.source.RemoveMorphRuleChainsByTarget(name, target) -} - func newAccessPolicyEngine( - morphChainStorage engine.MorphRuleChainStorage, + morphChainStorage engine.MorphRuleChainStorageReader, localOverrideDatabase chainbase.LocalOverrideDatabase, ) *accessPolicyEngine { return &accessPolicyEngine{ @@ -98,8 +75,6 @@ func newAccessPolicyEngine( localOverrideDatabase, ), - morphChainStorage: morphChainStorage, - localOverrideDatabase: localOverrideDatabase, } } @@ -111,13 +86,6 @@ func (a *accessPolicyEngine) IsAllowed(name chain.Name, target engine.RequestTar return a.chainRouter.IsAllowed(name, target, r) } -func (a *accessPolicyEngine) MorphRuleChainStorage() engine.MorphRuleChainStorage { - a.mtx.Lock() - defer a.mtx.Unlock() - - return a.morphChainStorage -} - func (a *accessPolicyEngine) LocalStorage() engine.LocalOverrideStorage { a.mtx.Lock() defer a.mtx.Unlock() From c09c70161395b5d34dc4ea128fc63877e5d1f773 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 19 Mar 2024 11:49:19 +0300 Subject: [PATCH 0456/1413] [#1048] metabase: Fix drop buckets during resync Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/control.go | 46 ++++++++------- .../metabase/reset_test.go | 57 +++++++++++++++++++ 2 files changed, 82 insertions(+), 21 deletions(-) create mode 100644 pkg/local_object_storage/metabase/reset_test.go diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index a275f4560d..83b0b11b6d 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -21,6 +21,22 @@ var ErrDegradedMode = logicerr.New("metabase is in a degraded mode") // ErrReadOnlyMode is returned when metabase is in a read-only mode. var ErrReadOnlyMode = logicerr.New("metabase is in a read-only mode") +var ( + mStaticBuckets = map[string]struct{}{ + string(containerVolumeBucketName): {}, + string(containerCounterBucketName): {}, + string(graveyardBucketName): {}, + string(garbageBucketName): {}, + string(shardInfoBucket): {}, + string(bucketNameLocked): {}, + } + + // deprecatedBuckets buckets that are not used anymore. + deprecatedBuckets = [][]byte{ + toMoveItBucketName, + } +) + // Open boltDB instance for metabase. func (db *DB) Open(_ context.Context, mode mode.Mode) error { db.modeMtx.Lock() @@ -113,20 +129,6 @@ func (db *DB) init(reset bool) error { return nil } - mStaticBuckets := map[string]struct{}{ - string(containerVolumeBucketName): {}, - string(containerCounterBucketName): {}, - string(graveyardBucketName): {}, - string(garbageBucketName): {}, - string(shardInfoBucket): {}, - string(bucketNameLocked): {}, - } - - // buckets that are not used anymore - deprecatedBuckets := [][]byte{ - toMoveItBucketName, - } - return db.boltDB.Update(func(tx *bbolt.Tx) error { var err error if !reset { @@ -167,15 +169,17 @@ func (db *DB) init(reset bool) error { return nil } - err = tx.ForEach(func(name []byte, _ *bbolt.Bucket) error { + bucketCursor := tx.Cursor() + name, _ := bucketCursor.First() + for name != nil { if _, ok := mStaticBuckets[string(name)]; !ok { - return tx.DeleteBucket(name) + if err := tx.DeleteBucket(name); err != nil { + return err + } + name, _ = bucketCursor.Seek(name) + continue } - - return nil - }) - if err != nil { - return err + name, _ = bucketCursor.Next() } return updateVersion(tx, version) }) diff --git a/pkg/local_object_storage/metabase/reset_test.go b/pkg/local_object_storage/metabase/reset_test.go new file mode 100644 index 0000000000..66f5eefc61 --- /dev/null +++ b/pkg/local_object_storage/metabase/reset_test.go @@ -0,0 +1,57 @@ +package meta + +import ( + "context" + "fmt" + "path/filepath" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "github.com/stretchr/testify/require" + "go.etcd.io/bbolt" +) + +type epochState struct{ e uint64 } + +func (s epochState) CurrentEpoch() uint64 { + return s.e +} + +func TestResetDropsContainerBuckets(t *testing.T) { + t.Parallel() + + db := New( + []Option{ + WithPath(filepath.Join(t.TempDir(), "metabase")), + WithPermissions(0o600), + WithEpochState(epochState{}), + }..., + ) + + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.Init()) + + defer func() { require.NoError(t, db.Close()) }() + + for idx := 0; idx < 100; idx++ { + var putPrm PutPrm + putPrm.SetObject(testutil.GenerateObject()) + putPrm.SetStorageID([]byte(fmt.Sprintf("0/%d", idx))) + _, err := db.Put(context.Background(), putPrm) + require.NoError(t, err) + } + + require.NoError(t, db.Reset()) + + var bucketCount int + require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error { + return tx.ForEach(func(name []byte, b *bbolt.Bucket) error { + _, exists := mStaticBuckets[string(name)] + require.True(t, exists, "unexpected bucket:"+string(name)) + bucketCount++ + return nil + }) + })) + require.Equal(t, len(mStaticBuckets), bucketCount) +} From c7a12ca3d8b5b238d8b7fef93470b1d620b5dad1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 21 Mar 2024 18:46:07 +0300 Subject: [PATCH 0457/1413] [#1054] network: Optimize IsTLSEnabled() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No big deal, but it is called multiple times in sorting routine, this easily results in 20 allocations per group traversal. ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ old │ new │ │ sec/op │ sec/op vs base │ AddressTLSEnabled-8 184.6n ± 1% 103.3n ± 6% -44.04% (p=0.000 n=10) │ old │ new │ │ B/op │ B/op vs base │ AddressTLSEnabled-8 704.0 ± 0% 0.0 ± 0% -100.00% (p=0.000 n=10) │ old │ new │ │ allocs/op │ allocs/op vs base │ AddressTLSEnabled-8 1.000 ± 0% 0.000 ± 0% -100.00% (p=0.000 n=10) ``` Signed-off-by: Evgenii Stratonikov --- pkg/network/tls.go | 9 ++------- pkg/network/tls_test.go | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/pkg/network/tls.go b/pkg/network/tls.go index 9aac89c47e..544dc82407 100644 --- a/pkg/network/tls.go +++ b/pkg/network/tls.go @@ -13,11 +13,6 @@ var tls, _ = multiaddr.NewMultiaddr("/" + tlsProtocolName) // IsTLSEnabled searches for wrapped TLS protocol in multiaddr. func (a Address) IsTLSEnabled() bool { - for _, protoc := range a.ma.Protocols() { - if protoc.Code == multiaddr.P_TLS { - return true - } - } - - return false + _, err := a.ma.ValueForProtocol(multiaddr.P_TLS) + return err == nil } diff --git a/pkg/network/tls_test.go b/pkg/network/tls_test.go index d93ea6a128..6c352484b5 100644 --- a/pkg/network/tls_test.go +++ b/pkg/network/tls_test.go @@ -27,3 +27,18 @@ func TestAddress_TLSEnabled(t *testing.T) { require.Equal(t, test.wantTLS, addr.IsTLSEnabled(), test.input) } } + +func BenchmarkAddressTLSEnabled(b *testing.B) { + var addr Address + err := addr.FromString("/dns4/localhost/tcp/8080/tls") + require.NoError(b, err) + + b.ResetTimer() + b.ReportAllocs() + + var enabled bool + for i := 0; i < b.N; i++ { + enabled = addr.IsTLSEnabled() + } + require.True(b, enabled) +} From 8690db697c40926e3e77601fde5977caa4f03b2e Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 26 Mar 2024 14:07:25 +0300 Subject: [PATCH 0458/1413] [#1056] Makefile: fix target locode-download wget fails if .cache dir does not exist Signed-off-by: Ekaterina Lebedeva --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4d3c121bfd..20c84d0416 100755 --- a/Makefile +++ b/Makefile @@ -265,8 +265,9 @@ debclean: # Download locode database locode-download: - @wget -q -O ./.cache/locode_db.gz 'https://git.frostfs.info/TrueCloudLab/frostfs-locode-db/releases/download/${LOCODE_DB_VERSION}/locode_db.gz' - gzip -dfk ./.cache/locode_db.gz + mkdir -p $(TMP_DIR) + @wget -q -O ./$(TMP_DIR)/locode_db.gz 'https://git.frostfs.info/TrueCloudLab/frostfs-locode-db/releases/download/${LOCODE_DB_VERSION}/locode_db.gz' + gzip -dfk ./$(TMP_DIR)/locode_db.gz # Start dev environment env-up: all From 0990a9b0bd8592e8e49f750779197b9c77197095 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Thu, 28 Mar 2024 16:12:33 +0300 Subject: [PATCH 0459/1413] [#1055] blobstor: fix mode metric It used to always show CLOSED after setting shard mode to read-only regardless of actual mode. Now metric represents actual blobstor mode of operations. Signed-off-by: Ekaterina Lebedeva --- pkg/local_object_storage/blobstor/mode.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/local_object_storage/blobstor/mode.go b/pkg/local_object_storage/blobstor/mode.go index dc7dad6877..a579a6f929 100644 --- a/pkg/local_object_storage/blobstor/mode.go +++ b/pkg/local_object_storage/blobstor/mode.go @@ -31,5 +31,6 @@ func (b *BlobStor) SetMode(m mode.Mode) error { } b.mode = m + b.metrics.SetMode(m.ReadOnly()) return nil } From fd8cdb96714b75c90f26a428cb96ed1e68204b63 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 27 Mar 2024 10:18:40 +0300 Subject: [PATCH 0460/1413] [#1057] netmap: Do not iterate over external addresses in Node Signed-off-by: Evgenii Stratonikov --- pkg/core/netmap/nodes.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/core/netmap/nodes.go b/pkg/core/netmap/nodes.go index 17fccc6209..b0c9e1f9e1 100644 --- a/pkg/core/netmap/nodes.go +++ b/pkg/core/netmap/nodes.go @@ -18,11 +18,6 @@ func (x Node) PublicKey() []byte { // and passes them into f. Handler MUST NOT be nil. func (x Node) IterateAddresses(f func(string) bool) { (netmap.NodeInfo)(x).IterateNetworkEndpoints(f) - for _, addr := range (netmap.NodeInfo)(x).ExternalAddresses() { - if f(addr) { - return - } - } } // NumberOfAddresses returns number of announced network addresses. From 942d83611bbebb503a462522c288883ef415ead1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 1 Apr 2024 09:54:42 +0300 Subject: [PATCH 0461/1413] [#874] engine: Revert Check object existance concurrently This reverts commit f526f49995575541626135e7d4542c0e014b63f2. Signed-off-by: Dmitrii Stepanov --- .../blobovnicza/exists.go | 12 ---- pkg/local_object_storage/blobovnicza/get.go | 12 ---- .../blobstor/blobovniczatree/get.go | 5 -- .../blobstor/blobovniczatree/iterate.go | 18 ----- pkg/local_object_storage/blobstor/exists.go | 14 ++-- .../blobstor/fstree/fstree.go | 6 -- .../engine/engine_test.go | 6 -- pkg/local_object_storage/engine/exists.go | 72 ++++++++----------- pkg/local_object_storage/engine/put.go | 2 + pkg/local_object_storage/metabase/exists.go | 6 -- pkg/local_object_storage/shard/exists.go | 6 -- 11 files changed, 35 insertions(+), 124 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/exists.go b/pkg/local_object_storage/blobovnicza/exists.go index b5d723ee6a..f7bc84d4af 100644 --- a/pkg/local_object_storage/blobovnicza/exists.go +++ b/pkg/local_object_storage/blobovnicza/exists.go @@ -21,22 +21,10 @@ func (b *Blobovnicza) Exists(ctx context.Context, addr oid.Address) (bool, error )) defer span.End() - select { - case <-ctx.Done(): - return false, ctx.Err() - default: - } - addrKey := addressKey(addr) err := b.boltDB.View(func(tx *bbolt.Tx) error { return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - if isNonDataBucket(bucketName) { return nil } diff --git a/pkg/local_object_storage/blobovnicza/get.go b/pkg/local_object_storage/blobovnicza/get.go index 36cf69d54b..600323f558 100644 --- a/pkg/local_object_storage/blobovnicza/get.go +++ b/pkg/local_object_storage/blobovnicza/get.go @@ -51,12 +51,6 @@ func (b *Blobovnicza) Get(ctx context.Context, prm GetPrm) (GetRes, error) { )) defer span.End() - select { - case <-ctx.Done(): - return GetRes{}, ctx.Err() - default: - } - var ( data []byte addrKey = addressKey(prm.addr) @@ -64,12 +58,6 @@ func (b *Blobovnicza) Get(ctx context.Context, prm GetPrm) (GetRes, error) { if err := b.boltDB.View(func(tx *bbolt.Tx) error { return tx.ForEach(func(bucketName []byte, buck *bbolt.Bucket) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - if isNonDataBucket(bucketName) { return nil } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 5f18566739..08cacda8ac 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -94,11 +94,6 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G // // returns error if object could not be read from any blobovnicza of the same level. func (b *Blobovniczas) getObjectFromLevel(ctx context.Context, prm blobovnicza.GetPrm, blzPath string) (common.GetRes, error) { - select { - case <-ctx.Done(): - return common.GetRes{}, ctx.Err() - default: - } // open blobovnicza (cached inside) shBlz := b.getBlobovnicza(blzPath) blz, err := shBlz.Open() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 942d73a120..92014fd558 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -230,12 +230,6 @@ func (b *Blobovniczas) iterateSortedDBPaths(ctx context.Context, addr oid.Addres } func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path string, addr oid.Address, f func(string) (bool, error)) (bool, error) { - select { - case <-ctx.Done(): - return false, ctx.Err() - default: - } - sysPath := filepath.Join(b.rootPath, path) entries, err := os.ReadDir(sysPath) if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode @@ -258,12 +252,6 @@ func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path st if len(dbIdxs) > 0 { for _, dbIdx := range dbIdxs { - select { - case <-ctx.Done(): - return false, ctx.Err() - default: - } - dbPath := filepath.Join(path, u64ToHexStringExt(dbIdx)) stop, err := f(dbPath) if err != nil { @@ -278,12 +266,6 @@ func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path st if len(dirIdxs) > 0 { hrw.SortSliceByValue(dirIdxs, addressHash(&addr, path)) for _, dirIdx := range dirIdxs { - select { - case <-ctx.Done(): - return false, ctx.Err() - default: - } - dirPath := filepath.Join(path, u64ToHexString(dirIdx)) stop, err := b.iterateSordedDBPathsInternal(ctx, dirPath, addr, f) if err != nil { diff --git a/pkg/local_object_storage/blobstor/exists.go b/pkg/local_object_storage/blobstor/exists.go index 21b4016d22..43feec7c91 100644 --- a/pkg/local_object_storage/blobstor/exists.go +++ b/pkg/local_object_storage/blobstor/exists.go @@ -3,7 +3,6 @@ package blobstor import ( "context" "encoding/hex" - "errors" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -58,30 +57,27 @@ func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exi // error | found | log the error, return true, nil // error | not found | return the error // error | error | log the first error, return the second - var storageErrors []error + var errors []error for i := range b.storage { res, err := b.storage[i].Storage.Exists(ctx, prm) if err == nil && res.Exists { exists = true return res, nil } else if err != nil { - if errors.Is(err, context.Canceled) { - return common.ExistsRes{}, err - } - storageErrors = append(storageErrors, err) + errors = append(errors, err) } } - if len(storageErrors) == 0 { + if len(errors) == 0 { return common.ExistsRes{}, nil } - for _, err := range storageErrors[:len(storageErrors)-1] { + for _, err := range errors[:len(errors)-1] { b.log.Warn(logs.BlobstorErrorOccurredDuringObjectExistenceChecking, zap.Stringer("address", prm.Address), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } - return common.ExistsRes{}, storageErrors[len(storageErrors)-1] + return common.ExistsRes{}, errors[len(errors)-1] } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 76ce5bf175..420f341a4c 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -285,12 +285,6 @@ func (t *FSTree) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exist )) defer span.End() - select { - case <-ctx.Done(): - return common.ExistsRes{}, ctx.Err() - default: - } - p := t.treePath(prm.Address) _, err := os.Stat(p) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index b6858df493..c41804e073 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -39,12 +39,6 @@ func BenchmarkExists(b *testing.B) { b.Run("8 shards", func(b *testing.B) { benchmarkExists(b, 8) }) - b.Run("12 shards", func(b *testing.B) { - benchmarkExists(b, 12) - }) - b.Run("16 shards", func(b *testing.B) { - benchmarkExists(b, 12) - }) } func benchmarkExists(b *testing.B, shardNum int) { diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index ee4dad341a..ef62927686 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -3,70 +3,54 @@ package engine import ( "context" "errors" - "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "golang.org/x/sync/errgroup" ) func (e *StorageEngine) exists(ctx context.Context, addr oid.Address) (bool, error) { var shPrm shard.ExistsPrm shPrm.SetAddress(addr) - - var exists atomic.Bool - eg, egCtx := errgroup.WithContext(ctx) - egCtx, cancel := context.WithCancel(egCtx) - defer cancel() + alreadyRemoved := false + exists := false e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { - select { - case <-egCtx.Done(): - return true - default: + res, err := sh.Exists(ctx, shPrm) + if err != nil { + if client.IsErrObjectAlreadyRemoved(err) { + alreadyRemoved = true + + return true + } + + var siErr *objectSDK.SplitInfoError + if errors.As(err, &siErr) { + return true + } + + if shard.IsErrObjectExpired(err) { + return true + } + + if !client.IsErrObjectNotFound(err) { + e.reportShardError(sh, "could not check existence of object in shard", err) + } + return false } - eg.Go(func() error { - res, err := sh.Exists(egCtx, shPrm) - if err != nil { - if errors.Is(err, context.Canceled) { - return err - } + if !exists { + exists = res.Exists() + } - if client.IsErrObjectAlreadyRemoved(err) { - return err - } - - var siErr *objectSDK.SplitInfoError - if errors.As(err, &siErr) { - return err - } - - if shard.IsErrObjectExpired(err) { - return err - } - - if !client.IsErrObjectNotFound(err) { - e.reportShardError(sh, "could not check existence of object in shard", err) - } - return nil - } - if res.Exists() { - exists.Store(true) - cancel() - } - return nil - }) return false }) - err := eg.Wait() - if client.IsErrObjectAlreadyRemoved(err) { + if alreadyRemoved { return false, new(apistatus.ObjectAlreadyRemoved) } - return exists.Load(), nil + return exists, nil } diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index c1cd29cb8a..777f728b74 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -78,6 +78,8 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { addr := object.AddressOf(prm.obj) + // In #1146 this check was parallelized, however, it became + // much slower on fast machines for 4 shards. _, err := e.exists(ctx, addr) if err != nil { return err diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index bca18e21ff..aa9aba1064 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -67,12 +67,6 @@ func (db *DB) Exists(ctx context.Context, prm ExistsPrm) (res ExistsRes, err err return res, ErrDegradedMode } - select { - case <-ctx.Done(): - return res, ctx.Err() - default: - } - currEpoch := db.epochState.CurrentEpoch() err = db.boltDB.View(func(tx *bbolt.Tx) error { diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index 7296426a6e..2cdb8dfa8e 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -47,12 +47,6 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { )) defer span.End() - select { - case <-ctx.Done(): - return ExistsRes{}, ctx.Err() - default: - } - var exists bool var err error From f23e38c28569716e2a770ca5f84df723449d597c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 1 Apr 2024 12:48:30 +0300 Subject: [PATCH 0462/1413] Revert "[#446] engine: Move to read-only on blobstor errors" This reverts commit 69df0d21c2d5f14a28d45951c32702ceec9da759. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/engine.go | 34 ++++++++----------- pkg/local_object_storage/engine/error_test.go | 2 +- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index e03a08abc7..558fe92ed2 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" @@ -50,7 +49,6 @@ type shardWrapper struct { type setModeRequest struct { sh *shard.Shard - isMeta bool errorCount uint32 } @@ -76,7 +74,7 @@ func (e *StorageEngine) setModeLoop() { if !ok { inProgress[sid] = struct{}{} go func() { - e.moveToDegraded(r.sh, r.errorCount, r.isMeta) + e.moveToDegraded(r.sh, r.errorCount) mtx.Lock() delete(inProgress, sid) @@ -88,7 +86,7 @@ func (e *StorageEngine) setModeLoop() { } } -func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32, isMeta bool) { +func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32) { sid := sh.ID() log := e.log.With( zap.Stringer("shard_id", sid), @@ -97,23 +95,21 @@ func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32, isMeta e.mtx.RLock() defer e.mtx.RUnlock() - if isMeta { - err := sh.SetMode(mode.DegradedReadOnly) - if err == nil { - log.Info(logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) - return - } + err := sh.SetMode(mode.DegradedReadOnly) + if err != nil { log.Error(logs.EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly, zap.Error(err)) - } - err := sh.SetMode(mode.ReadOnly) - if err != nil { - log.Error(logs.EngineFailedToMoveShardInReadonlyMode, zap.Error(err)) - return + err = sh.SetMode(mode.ReadOnly) + if err != nil { + log.Error(logs.EngineFailedToMoveShardInReadonlyMode, + zap.Error(err)) + } else { + log.Info(logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) + } + } else { + log.Info(logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) } - - log.Info(logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) } // reportShardErrorBackground increases shard error counter and logs an error. @@ -179,13 +175,11 @@ func (e *StorageEngine) reportShardErrorWithFlags( return } - isMeta := errors.As(err, new(metaerr.Error)) if block { - e.moveToDegraded(sh, errCount, isMeta) + e.moveToDegraded(sh, errCount) } else { req := setModeRequest{ errorCount: errCount, - isMeta: isMeta, sh: sh, } diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 7f48da08aa..ec4287bdd7 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -153,7 +153,7 @@ func TestErrorReporting(t *testing.T) { for i := uint32(0); i < 2; i++ { _, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)}) require.Error(t, err) - checkShardState(t, te.ng, te.shards[0].id, errThreshold+i, mode.ReadOnly) + checkShardState(t, te.ng, te.shards[0].id, errThreshold+i, mode.DegradedReadOnly) checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) } From e12fcc041d421c4847b027db3ba0c7525610a321 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 28 Mar 2024 15:53:26 +0300 Subject: [PATCH 0463/1413] [#1059] services/tree: Fast sorted listing Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- pkg/local_object_storage/engine/tree.go | 33 +++ pkg/local_object_storage/pilorama/boltdb.go | 206 +++++++++++++++--- pkg/local_object_storage/pilorama/forest.go | 43 ++++ .../pilorama/forest_test.go | 202 +++++++++++++++++ pkg/local_object_storage/pilorama/heap.go | 64 ++++++ .../pilorama/interface.go | 3 + pkg/local_object_storage/shard/tree.go | 25 +++ pkg/services/tree/getsubtree_test.go | 2 +- pkg/services/tree/service.go | 87 ++++++++ 10 files changed, 638 insertions(+), 29 deletions(-) create mode 100644 pkg/local_object_storage/pilorama/heap.go diff --git a/go.mod b/go.mod index 2c2eac68f0..1d18bb9d3e 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/google/uuid v1.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 @@ -64,7 +65,6 @@ require ( github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index f50b9cb684..52ea399fe6 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -209,6 +209,39 @@ func (e *StorageEngine) TreeGetChildren(ctx context.Context, cid cidSDK.ID, tree return nil, err } +// TreeSortedByFilename implements the pilorama.Forest interface. +func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.Node, last string, count int) ([]pilorama.NodeInfo, string, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.TreeSortedByFilename", + trace.WithAttributes( + attribute.String("container_id", cid.EncodeToString()), + attribute.String("tree_id", treeID), + attribute.String("node_id", strconv.FormatUint(nodeID, 10)), + ), + ) + defer span.End() + + var err error + var nodes []pilorama.NodeInfo + var cursor string + for _, sh := range e.sortShards(cid) { + nodes, cursor, err = sh.TreeSortedByFilename(ctx, cid, treeID, nodeID, last, count) + if err != nil { + if err == shard.ErrPiloramaDisabled { + break + } + if !errors.Is(err, pilorama.ErrTreeNotFound) { + e.reportShardError(sh, "can't perform `TreeSortedByFilename`", err, + zap.Stringer("cid", cid), + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } + continue + } + return nodes, cursor, nil + } + return nil, last, err +} + // TreeGetOpLog implements the pilorama.Forest interface. func (e *StorageEngine) TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID string, height uint64) (pilorama.Move, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.TreeGetOpLog", diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 17133e8f38..1487296a4e 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -9,6 +9,7 @@ import ( "math/rand" "os" "path/filepath" + "sort" "strconv" "sync" "time" @@ -986,6 +987,149 @@ func (t *boltForest) TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID stri return m, parentID, metaerr.Wrap(err) } +func (t *boltForest) hasFewChildren(b *bbolt.Bucket, nodeID Node, threshold int) bool { + key := make([]byte, 9) + key[0] = 'c' + binary.LittleEndian.PutUint64(key[1:], nodeID) + + count := 0 + c := b.Cursor() + for k, _ := c.Seek(key); len(k) == childrenKeySize && binary.LittleEndian.Uint64(k[1:]) == nodeID; k, _ = c.Next() { + if count++; count > threshold { + return false + } + } + return true +} + +// TreeSortedByFilename implements the Forest interface. +func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node, last string, count int) ([]NodeInfo, string, error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + t.metrics.AddMethodDuration("TreeSortedByFilename", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "boltForest.TreeSortedByFilename", + trace.WithAttributes( + attribute.String("container_id", cid.EncodeToString()), + attribute.String("tree_id", treeID), + attribute.String("node_id", strconv.FormatUint(nodeID, 10)), + ), + ) + defer span.End() + + t.modeMtx.RLock() + defer t.modeMtx.RUnlock() + + if t.mode.NoMetabase() { + return nil, "", ErrDegradedMode + } + + h := newHeap(last, count) + key := make([]byte, 9) + + var result []NodeInfo + var fewChildren bool + + err := t.db.View(func(tx *bbolt.Tx) error { + treeRoot := tx.Bucket(bucketName(cid, treeID)) + if treeRoot == nil { + return ErrTreeNotFound + } + + b := treeRoot.Bucket(dataBucket) + + // If the node is a leaf, we could scan all filenames in the tree. + // To prevent this we first count the number of children: if it is less than + // the number of nodes we need to return, fallback to TreeGetChildren() implementation. + if fewChildren = t.hasFewChildren(b, nodeID, count); fewChildren { + var err error + result, err = t.getChildren(b, nodeID) + return err + } + + t.fillSortedChildren(b, nodeID, h) + + for info, ok := h.pop(); ok; info, ok = h.pop() { + childInfo, err := t.getChildInfo(b, key, info.id) + if err != nil { + return err + } + result = append(result, childInfo) + } + return nil + }) + + success = err == nil + if err != nil { + return nil, last, metaerr.Wrap(err) + } + + if fewChildren { + sort.Slice(result, func(i, j int) bool { + return bytes.Compare(result[i].Meta.GetAttr(AttributeFilename), result[j].Meta.GetAttr(AttributeFilename)) == -1 + }) + for i := range result { + if bytes.Compare([]byte(last), result[i].Meta.GetAttr(AttributeFilename)) == -1 { + result = result[i:] + break + } + } + } + if len(result) != 0 { + last = string(result[len(result)-1].Meta.GetAttr(AttributeFilename)) + } + return result, last, metaerr.Wrap(err) +} + +func (t *boltForest) getChildInfo(b *bbolt.Bucket, key []byte, childID Node) (NodeInfo, error) { + childInfo := NodeInfo{ID: childID} + parentID, _, metaBytes, found := t.getState(b, stateKey(key, childID)) + if found { + childInfo.ParentID = parentID + if err := childInfo.Meta.FromBytes(metaBytes); err != nil { + return NodeInfo{}, err + } + } + return childInfo, nil +} + +func (t *boltForest) fillSortedChildren(b *bbolt.Bucket, nodeID Node, h *fixedHeap) { + c := b.Cursor() + prefix := internalKeyPrefix(nil, AttributeFilename) + + length := uint16(0) + count := 0 + for k, _ := c.Seek(prefix); len(k) > 0 && k[0] == 'i'; k, _ = c.Next() { + if len(k) < len(prefix)+2+16 { + continue + } + + parentID := binary.LittleEndian.Uint64(k[len(k)-16:]) + if parentID != nodeID { + continue + } + + actualLength := binary.LittleEndian.Uint16(k[len(prefix):]) + childID := binary.LittleEndian.Uint64(k[len(k)-8:]) + filename := string(k[len(prefix)+2 : len(k)-16]) + processed := h.push(childID, filename) + if actualLength != length { + length = actualLength + count = 1 + } else if processed { + if count++; count > h.count { + length = actualLength + 1 + c.Seek(append(prefix, byte(length), byte(length>>8))) + c.Prev() // c.Next() will be performed by for loop + } + } + } +} + // TreeGetChildren implements the Forest interface. func (t *boltForest) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node) ([]NodeInfo, error) { var ( @@ -1012,10 +1156,6 @@ func (t *boltForest) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID return nil, ErrDegradedMode } - key := make([]byte, 9) - key[0] = 'c' - binary.LittleEndian.PutUint64(key[1:], nodeID) - var result []NodeInfo err := t.db.View(func(tx *bbolt.Tx) error { @@ -1025,27 +1165,34 @@ func (t *boltForest) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID } b := treeRoot.Bucket(dataBucket) - c := b.Cursor() - for k, _ := c.Seek(key); len(k) == childrenKeySize && binary.LittleEndian.Uint64(k[1:]) == nodeID; k, _ = c.Next() { - childID := binary.LittleEndian.Uint64(k[9:]) - childInfo := NodeInfo{ - ID: childID, - } - parentID, _, metaBytes, found := t.getState(b, stateKey(key, childID)) - if found { - childInfo.ParentID = parentID - if err := childInfo.Meta.FromBytes(metaBytes); err != nil { - return err - } - } - result = append(result, childInfo) - } - return nil + + var err error + result, err = t.getChildren(b, nodeID) + return err }) success = err == nil return result, metaerr.Wrap(err) } +func (t *boltForest) getChildren(b *bbolt.Bucket, nodeID Node) ([]NodeInfo, error) { + var result []NodeInfo + + key := make([]byte, 9) + key[0] = 'c' + binary.LittleEndian.PutUint64(key[1:], nodeID) + + c := b.Cursor() + for k, _ := c.Seek(key); len(k) == childrenKeySize && binary.LittleEndian.Uint64(k[1:]) == nodeID; k, _ = c.Next() { + childID := binary.LittleEndian.Uint64(k[9:]) + childInfo, err := t.getChildInfo(b, key, childID) + if err != nil { + return nil, err + } + result = append(result, childInfo) + } + return result, nil +} + // TreeList implements the Forest interface. func (t *boltForest) TreeList(ctx context.Context, cid cidSDK.ID) ([]string, error) { var ( @@ -1358,6 +1505,16 @@ func childrenKey(key []byte, child, parent Node) []byte { return key[:childrenKeySize] } +func internalKeyPrefix(key []byte, k string) []byte { + key = key[:0] + key = append(key, 'i') + + l := len(k) + key = append(key, byte(l), byte(l>>8)) + key = append(key, k...) + return key +} + // 'i' + attribute name (string) + attribute value (string) + parent (id) + node (id) -> 0/1. func internalKey(key []byte, k, v string, parent, node Node) []byte { size := 1 /* prefix */ + 2*2 /* len */ + 2*8 /* nodes */ + len(k) + len(v) @@ -1365,14 +1522,9 @@ func internalKey(key []byte, k, v string, parent, node Node) []byte { key = make([]byte, 0, size) } - key = key[:0] - key = append(key, 'i') + key = internalKeyPrefix(key, k) - l := len(k) - key = append(key, byte(l), byte(l>>8)) - key = append(key, k...) - - l = len(v) + l := len(v) key = append(key, byte(l), byte(l>>8)) key = append(key, v...) diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index dbfc9dccdb..fedd3f90d4 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -1,6 +1,7 @@ package pilorama import ( + "bytes" "context" "errors" "fmt" @@ -154,6 +155,48 @@ func (f *memoryForest) TreeGetMeta(_ context.Context, cid cid.ID, treeID string, return s.infoMap[nodeID].Meta, s.infoMap[nodeID].Parent, nil } +// TreeSortedByFilename implements the Forest interface. +func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeID string, nodeID Node, start string, count int) ([]NodeInfo, string, error) { + fullID := cid.String() + "/" + treeID + s, ok := f.treeMap[fullID] + if !ok { + return nil, "", ErrTreeNotFound + } + if count == 0 { + return nil, start, nil + } + + children := s.tree.getChildren(nodeID) + res := make([]NodeInfo, 0, len(children)) + for _, childID := range children { + if len(s.infoMap[childID].Meta.GetAttr(AttributeFilename)) == 0 { + continue + } + res = append(res, NodeInfo{ + ID: childID, + Meta: s.infoMap[childID].Meta, + ParentID: s.infoMap[childID].Parent, + }) + } + if len(res) == 0 { + return res, "", nil + } + + sort.Slice(res, func(i, j int) bool { + return bytes.Compare(res[i].Meta.GetAttr(AttributeFilename), res[j].Meta.GetAttr(AttributeFilename)) == -1 + }) + for i := range res { + if string(res[i].Meta.GetAttr(AttributeFilename)) > start { + finish := i + count + if len(res) < finish { + finish = len(res) + } + return res[i:finish], string(res[finish-1].Meta.GetAttr(AttributeFilename)), nil + } + } + return nil, string(res[len(res)-1].Meta.GetAttr(AttributeFilename)), nil +} + // TreeGetChildren implements the Forest interface. func (f *memoryForest) TreeGetChildren(_ context.Context, cid cid.ID, treeID string, nodeID Node) ([]NodeInfo, error) { fullID := cid.String() + "/" + treeID diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 383320eb97..6c1bc343f5 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -7,6 +7,7 @@ import ( mrand "math/rand" "path/filepath" "strconv" + "strings" "sync" "testing" "time" @@ -15,6 +16,8 @@ import ( cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "github.com/davecgh/go-spew/spew" + "github.com/google/uuid" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) @@ -178,6 +181,205 @@ func testForestTreeGetChildren(t *testing.T, s ForestStorage) { }) } +func BenchmarkForestSortedIteration(b *testing.B) { + for i := range providers { + if providers[i].name == "inmemory" { + continue + } + + cnr := cidtest.ID() + treeID := "version" + f := providers[i].construct(b) + + const total = 100_000 + d := CIDDescriptor{cnr, 0, 1} + for i := 0; i < total; i++ { + u, err := uuid.NewRandom() + if err != nil { + b.FailNow() + } + + _, err = f.TreeMove(context.Background(), d, treeID, &Move{ + Parent: RootID, + Child: RootID + Node(i+1), + Meta: Meta{ + Time: Timestamp(i + 1), + Items: []KeyValue{{ + Key: AttributeFilename, Value: []byte(u.String()), + }}, + }, + }) + if err != nil { + b.FailNow() + } + } + + b.Run(providers[i].name+",root", func(b *testing.B) { + for i := 0; i < b.N; i++ { + res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, RootID, "", 100) + if err != nil || len(res) != 100 { + b.Fatalf("err %v, count %d", err, len(res)) + } + } + }) + b.Run(providers[i].name+",leaf", func(b *testing.B) { + for i := 0; i < b.N; i++ { + res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, 1, "", 100) + if err != nil || len(res) != 0 { + b.FailNow() + } + } + }) + } +} + +func TestForest_TreeSortedIteration(t *testing.T) { + for i := range providers { + t.Run(providers[i].name, func(t *testing.T) { + testForestTreeSortedIteration(t, providers[i].construct(t)) + }) + } +} + +func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + + cid := cidtest.ID() + d := CIDDescriptor{cid, 0, 1} + treeID := "version" + treeAdd := func(t *testing.T, ts int) { + _, err := s.TreeMove(context.Background(), d, treeID, &Move{ + Child: RootID + uint64(ts), + Parent: RootID, + Meta: Meta{ + Time: Timestamp(ts), + Items: []KeyValue{ + {Key: AttributeFilename, Value: []byte(strconv.Itoa(ts))}, + }, + }, + }) + require.NoError(t, err) + } + + const count = 9 + for i := 0; i < count; i++ { + treeAdd(t, i+1) + } + + var result []NodeInfo + treeAppend := func(t *testing.T, last string, count int) string { + res, cursor, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, RootID, last, count) + require.NoError(t, err) + result = append(result, res...) + spew.Dump(last, res) + return cursor + } + + last := treeAppend(t, "", 2) + last = treeAppend(t, last, 3) + last = treeAppend(t, last, 0) + last = treeAppend(t, last, 1) + _ = treeAppend(t, last, 10) + + require.Len(t, result, count) + for i := range result { + require.Equal(t, RootID+uint64(i+1), result[i].ID) + require.Equal(t, strconv.Itoa(RootID+i+1), string(result[i].Meta.GetAttr(AttributeFilename))) + } +} + +func TestForest_TreeSortedFilename(t *testing.T) { + for i := range providers { + t.Run(providers[i].name, func(t *testing.T) { + testForestTreeSortedByFilename(t, providers[i].construct(t)) + }) + } +} + +func testForestTreeSortedByFilename(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + + const controlAttr = "control_attr" + cid := cidtest.ID() + d := CIDDescriptor{cid, 0, 1} + treeID := "version" + + treeAddByPath := func(t *testing.T, filename string) { + path := strings.Split(filename, "/") + _, err := s.TreeAddByPath(context.Background(), d, treeID, AttributeFilename, path[:len(path)-1], + []KeyValue{ + {Key: AttributeFilename, Value: []byte(path[len(path)-1])}, + {Key: controlAttr, Value: []byte(filename)}, + }, + ) + require.NoError(t, err) + } + + expectAttributes := func(t *testing.T, attr string, expected []string, res []NodeInfo) { + require.Equal(t, len(expected), len(res)) + + actual := make([]string, len(res)) + for i := range actual { + actual[i] = string(res[i].Meta.GetAttr(attr)) + } + require.Equal(t, expected, actual) + } + + items := []string{ + "a/bbb/ccc", + "a/bbb/xxx", + "a/bbb/z", + "b/bbb/ccc", + "b/xxx/z", + "c", + } + + // Ensure we do not depend on insertion order in any way. + mrand.Shuffle(len(items), func(i, j int) { + items[i], items[j] = items[j], items[i] + }) + for i := range items { + treeAddByPath(t, items[i]) + } + + getChildren := func(t *testing.T, id Node) []NodeInfo { + res, _, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, id, "", len(items)) + require.NoError(t, err) + return res + } + + res := getChildren(t, RootID) + expectAttributes(t, AttributeFilename, []string{"a", "b", "c"}, res) + expectAttributes(t, controlAttr, []string{"", "", "c"}, res) + + { + ra := getChildren(t, res[0].ID) + expectAttributes(t, AttributeFilename, []string{"bbb"}, ra) + expectAttributes(t, controlAttr, []string{""}, ra) + + rabbb := getChildren(t, ra[0].ID) + expectAttributes(t, AttributeFilename, []string{"ccc", "xxx", "z"}, rabbb) + expectAttributes(t, controlAttr, []string{"a/bbb/ccc", "a/bbb/xxx", "a/bbb/z"}, rabbb) + } + { + rb := getChildren(t, res[1].ID) + expectAttributes(t, AttributeFilename, []string{"bbb", "xxx"}, rb) + expectAttributes(t, controlAttr, []string{"", ""}, rb) + + rbbbb := getChildren(t, rb[0].ID) + expectAttributes(t, AttributeFilename, []string{"ccc"}, rbbbb) + expectAttributes(t, controlAttr, []string{"b/bbb/ccc"}, rbbbb) + + rbxxx := getChildren(t, rb[1].ID) + expectAttributes(t, AttributeFilename, []string{"z"}, rbxxx) + expectAttributes(t, controlAttr, []string{"b/xxx/z"}, rbxxx) + } + { + rc := getChildren(t, res[2].ID) + require.Len(t, rc, 0) + } +} + func TestForest_TreeDrop(t *testing.T) { for i := range providers { t.Run(providers[i].name, func(t *testing.T) { diff --git a/pkg/local_object_storage/pilorama/heap.go b/pkg/local_object_storage/pilorama/heap.go new file mode 100644 index 0000000000..667283c2af --- /dev/null +++ b/pkg/local_object_storage/pilorama/heap.go @@ -0,0 +1,64 @@ +package pilorama + +import ( + "container/heap" +) + +type heapInfo struct { + id Node + filename string +} + +type filenameHeap []heapInfo + +func (h filenameHeap) Len() int { return len(h) } +func (h filenameHeap) Less(i, j int) bool { return h[i].filename < h[j].filename } +func (h filenameHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *filenameHeap) Push(x any) { + *h = append(*h, x.(heapInfo)) +} +func (h *filenameHeap) Pop() any { + old := *h + n := len(old) + x := old[n-1] + *h = old[0 : n-1] + return x +} + +// fixedHeap maintains a fixed number of smallest elements started at some point. +type fixedHeap struct { + start string + max string + count int + h *filenameHeap +} + +func newHeap(start string, count int) *fixedHeap { + h := new(filenameHeap) + heap.Init(h) + + return &fixedHeap{ + start: start, + max: "", + count: count, + h: h, + } +} + +func (h *fixedHeap) push(id Node, filename string) bool { + if filename == "" || filename <= h.start { + return false + } + heap.Push(h.h, heapInfo{id: id, filename: filename}) + if h.h.Len() > h.count { + heap.Remove(h.h, h.h.Len()-1) + } + return true +} + +func (h *fixedHeap) pop() (heapInfo, bool) { + if h.h.Len() != 0 { + return heap.Pop(h.h).(heapInfo), true + } + return heapInfo{}, false +} diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index 5fefb2e271..79449e080c 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -33,6 +33,9 @@ type Forest interface { // TreeGetChildren returns children of the node with the specified ID. The order is arbitrary. // Should return ErrTreeNotFound if the tree is not found, and empty result if the node is not in the tree. TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node) ([]NodeInfo, error) + // TreeSortedByFilename returns children of the node with the specified ID. The nodes are sorted by the filename attribute.. + // Should return ErrTreeNotFound if the tree is not found, and empty result if the node is not in the tree. + TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node, last string, count int) ([]NodeInfo, string, error) // TreeGetOpLog returns first log operation stored at or above the height. // In case no such operation is found, empty Move and nil error should be returned. TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID string, height uint64) (Move, error) diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index e78f292770..9a78f99ea9 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -183,6 +183,31 @@ func (s *Shard) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID strin return s.pilorama.TreeGetChildren(ctx, cid, treeID, nodeID) } +// TreeSortedByFilename implements the pilorama.Forest interface. +func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.Node, last string, count int) ([]pilorama.NodeInfo, string, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeSortedByFilename", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.String("container_id", cid.EncodeToString()), + attribute.String("tree_id", treeID), + attribute.String("node_id", strconv.FormatUint(nodeID, 10)), + ), + ) + defer span.End() + + if s.pilorama == nil { + return nil, "", ErrPiloramaDisabled + } + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { + return nil, "", ErrDegradedMode + } + return s.pilorama.TreeSortedByFilename(ctx, cid, treeID, nodeID, last, count) +} + // TreeGetOpLog implements the pilorama.Forest interface. func (s *Shard) TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID string, height uint64) (pilorama.Move, error) { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeGetOpLog", diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 63cdc73a2f..4f009adb69 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -174,7 +174,7 @@ func TestGetSubTreeOrderAsc(t *testing.T) { paths = append(paths, path.Join(tree[j].path...)) } } - require.True(t, found, "unknown node") + require.True(t, found, "unknown node %d %v", i, acc.seen[i].GetBody().GetNodeId()) } require.True(t, sort.SliceIsSorted(paths, func(i, j int) bool { diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 59b01796e0..f715d92495 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -440,7 +440,94 @@ func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeS return getSubTree(srv.Context(), srv, cid, b, s.forest) } +func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid cidSDK.ID, b *GetSubTreeRequest_Body, forest pilorama.Forest) error { + const batchSize = 1000 + + type stackItem struct { + values []pilorama.NodeInfo + parent pilorama.Node + last string + } + + // Traverse the tree in a DFS manner. Because we need to support arbitrary depth, + // recursive implementation is not suitable here, so we maintain explicit stack. + m, p, err := forest.TreeGetMeta(ctx, cid, b.GetTreeId(), b.GetRootId()) + if err != nil { + return err + } + + err = srv.Send(&GetSubTreeResponse{ + Body: &GetSubTreeResponse_Body{ + NodeId: b.GetRootId(), + ParentId: p, + Timestamp: m.Time, + Meta: metaToProto(m.Items), + }, + }) + if err != nil { + return err + } + + stack := []stackItem{{ + values: nil, + parent: b.GetRootId(), + last: "", + }} + + for { + if len(stack) == 0 { + break + } else if item := &stack[len(stack)-1]; len(item.values) == 0 { + nodes, last, err := forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), item.parent, item.last, batchSize) + if err != nil { + return err + } + item.values = nodes + item.last = last + + if len(nodes) == 0 { + stack = stack[:len(stack)-1] + continue + } + } + + node := stack[len(stack)-1].values[0] + stack[len(stack)-1].values = stack[len(stack)-1].values[1:] + + err = srv.Send(&GetSubTreeResponse{ + Body: &GetSubTreeResponse_Body{ + NodeId: node.ID, + ParentId: node.ParentID, + Timestamp: node.Meta.Time, + Meta: metaToProto(node.Meta.Items), + }, + }) + if err != nil { + return err + } + + if b.GetDepth() == 0 || uint32(len(stack)) < b.GetDepth() { + children, last, err := forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), node.ID, "", batchSize) + if err != nil { + return err + } + if len(children) != 0 { + stack = append(stack, stackItem{ + values: children, + parent: node.ID, + last: last, + }) + } + } + } + return nil +} + func getSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid cidSDK.ID, b *GetSubTreeRequest_Body, forest pilorama.Forest) error { + if b.GetOrderBy().GetDirection() == GetSubTreeRequest_Body_Order_Asc { + return getSortedSubTree(ctx, srv, cid, b, forest) + } + // Traverse the tree in a DFS manner. Because we need to support arbitrary depth, // recursive implementation is not suitable here, so we maintain explicit stack. m, p, err := forest.TreeGetMeta(ctx, cid, b.GetTreeId(), b.GetRootId()) From 81a0346a960e49f54aa6a032d8bbcbb23d49b0bd Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 19 Mar 2024 01:03:46 +0300 Subject: [PATCH 0464/1413] [#949] metabase: fix metabase mode metric It used to always show CLOSED regardless of actual mode. Now metric represents actual metabase mode of operations. Signed-off-by: Ekaterina Lebedeva --- pkg/local_object_storage/metabase/control.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 83b0b11b6d..f6eb35ee8f 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -42,6 +42,7 @@ func (db *DB) Open(_ context.Context, mode mode.Mode) error { db.modeMtx.Lock() defer db.modeMtx.Unlock() db.mode = mode + db.metrics.SetMode(mode) if mode.NoMetabase() { return nil From d5194ab2a6dacd533daf9bc601622c4ef19b77fa Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 19 Mar 2024 12:40:00 +0300 Subject: [PATCH 0465/1413] [#949] metabase: fix shard.UpdateID() metabase.Open() now reports metabase mode metric. shard.UpdateID() needs to read shard ID from metabase => needs to open metabase. It caused reporting 'shard undefined' metrics. To avoid reporting wrong metrics metabase.GetShardID() was added which also opens metabase and does not report metrics. Signed-off-by: Ekaterina Lebedeva --- pkg/local_object_storage/engine/shards.go | 4 +- pkg/local_object_storage/metabase/control.go | 9 ++- pkg/local_object_storage/metabase/shard_id.go | 63 +++++++++++++++---- .../metabase/version_test.go | 4 +- pkg/local_object_storage/shard/id.go | 27 +++----- 5 files changed, 69 insertions(+), 38 deletions(-) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 4bbf7eff0c..ccf2e9dac5 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -107,7 +107,7 @@ func (e *StorageEngine) AddShard(ctx context.Context, opts ...shard.Option) (*sh return sh.ID(), nil } -func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (*shard.Shard, error) { +func (e *StorageEngine) createShard(_ context.Context, opts []shard.Option) (*shard.Shard, error) { id, err := generateShardID() if err != nil { return nil, fmt.Errorf("could not generate shard ID: %w", err) @@ -126,7 +126,7 @@ func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (* shard.WithZeroCountCallback(e.processZeroCountContainers), )...) - if err := sh.UpdateID(ctx); err != nil { + if err := sh.UpdateID(); err != nil { e.log.Warn(logs.FailedToUpdateShardID, zap.Stringer("shard_id", sh.ID()), zap.String("metabase_path", sh.DumpInfo().MetaBaseInfo.Path), zap.Error(err)) } diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index f6eb35ee8f..cd53f0cd2f 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -202,11 +202,12 @@ func (db *DB) SyncCounters() error { })) } -// Close closes boltDB instance. +// Close closes boltDB instance +// and reports metabase metric. func (db *DB) Close() error { var err error if db.boltDB != nil { - err = metaerr.Wrap(db.boltDB.Close()) + err = db.close() } if err == nil { db.metrics.Close() @@ -214,6 +215,10 @@ func (db *DB) Close() error { return err } +func (db *DB) close() error { + return metaerr.Wrap(db.boltDB.Close()) +} + // Reload reloads part of the configuration. // It returns true iff database was reopened. // If a config option is invalid, it logs an error and returns nil. diff --git a/pkg/local_object_storage/metabase/shard_id.go b/pkg/local_object_storage/metabase/shard_id.go index c1ec8c67e4..7ae336a6cb 100644 --- a/pkg/local_object_storage/metabase/shard_id.go +++ b/pkg/local_object_storage/metabase/shard_id.go @@ -2,8 +2,11 @@ package meta import ( "bytes" + "errors" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" + metamode "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "go.etcd.io/bbolt" ) @@ -12,16 +15,32 @@ var ( shardIDKey = []byte("id") ) -// ReadShardID reads shard id from db. +// GetShardID sets metabase operation mode +// and reads shard id from db. // If id is missing, returns nil, nil. -func (db *DB) ReadShardID() ([]byte, error) { - db.modeMtx.RLock() - defer db.modeMtx.RUnlock() +// +// GetShardID does not report any metrics. +func (db *DB) GetShardID(mode metamode.Mode) ([]byte, error) { + db.modeMtx.Lock() + defer db.modeMtx.Unlock() + db.mode = mode - if db.mode.NoMetabase() { - return nil, ErrDegradedMode + if err := db.openDB(mode); err != nil { + return nil, fmt.Errorf("failed to open metabase: %w", err) } + id, err := db.readShardID() + + if cErr := db.close(); cErr != nil { + err = errors.Join(err, fmt.Errorf("failed to close metabase: %w", cErr)) + } + + return id, metaerr.Wrap(err) +} + +// ReadShardID reads shard id from db. +// If id is missing, returns nil, nil. +func (db *DB) readShardID() ([]byte, error) { var id []byte err := db.boltDB.View(func(tx *bbolt.Tx) error { b := tx.Bucket(shardInfoBucket) @@ -33,17 +52,35 @@ func (db *DB) ReadShardID() ([]byte, error) { return id, metaerr.Wrap(err) } -// WriteShardID writes shard it to db. -func (db *DB) WriteShardID(id []byte) error { - db.modeMtx.RLock() - defer db.modeMtx.RUnlock() +// SetShardID sets metabase operation mode +// and writes shard id to db. +func (db *DB) SetShardID(id []byte, mode metamode.Mode) error { + db.modeMtx.Lock() + defer db.modeMtx.Unlock() + db.mode = mode - if db.mode.NoMetabase() { - return ErrDegradedMode - } else if db.mode.ReadOnly() { + if mode.ReadOnly() { return ErrReadOnlyMode } + if err := db.openDB(mode); err != nil { + return fmt.Errorf("failed to open metabase: %w", err) + } + + err := db.writeShardID(id) + if err == nil { + db.metrics.SetMode(mode) + } + + if cErr := db.close(); cErr != nil { + err = errors.Join(err, fmt.Errorf("failed to close metabase: %w", cErr)) + } + + return metaerr.Wrap(err) +} + +// writeShardID writes shard id to db. +func (db *DB) writeShardID(id []byte) error { return metaerr.Wrap(db.boltDB.Update(func(tx *bbolt.Tx) error { b, err := tx.CreateBucketIfNotExists(shardInfoBucket) if err != nil { diff --git a/pkg/local_object_storage/metabase/version_test.go b/pkg/local_object_storage/metabase/version_test.go index cea42da0f4..b2af428ff6 100644 --- a/pkg/local_object_storage/metabase/version_test.go +++ b/pkg/local_object_storage/metabase/version_test.go @@ -58,9 +58,7 @@ func TestVersion(t *testing.T) { }) t.Run("old data", func(t *testing.T) { db := newDB(t) - require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.WriteShardID([]byte{1, 2, 3, 4})) - require.NoError(t, db.Close()) + require.NoError(t, db.SetShardID([]byte{1, 2, 3, 4}, mode.ReadWrite)) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.Init()) diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index be474e0fa8..2fe68d2705 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -1,9 +1,10 @@ package shard import ( - "context" + "errors" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/mr-tron/base58" "go.uber.org/zap" @@ -30,21 +31,11 @@ func (s *Shard) ID() *ID { } // UpdateID reads shard ID saved in the metabase and updates it if it is missing. -func (s *Shard) UpdateID(ctx context.Context) (err error) { +func (s *Shard) UpdateID() (err error) { var idFromMetabase []byte - metabaseOpened := !s.GetMode().NoMetabase() - if err = s.metaBase.Open(ctx, s.GetMode()); err != nil { - err = fmt.Errorf("failed to open metabase: %w", err) - metabaseOpened = false - } - if metabaseOpened { - defer func() { - cErr := s.metaBase.Close() - if cErr != nil { - err = fmt.Errorf("failed to close metabase: %w", cErr) - } - }() - if idFromMetabase, err = s.metaBase.ReadShardID(); err != nil { + modeDegraded := s.GetMode().NoMetabase() + if !modeDegraded { + if idFromMetabase, err = s.metaBase.GetShardID(mode.ReadOnly); err != nil { err = fmt.Errorf("failed to read shard id from metabase: %w", err) } } @@ -73,9 +64,9 @@ func (s *Shard) UpdateID(ctx context.Context) (err error) { s.pilorama.SetParentID(s.info.ID.String()) } - if len(idFromMetabase) == 0 && metabaseOpened { - if err = s.metaBase.WriteShardID(*s.info.ID); err != nil { - err = fmt.Errorf("failed to write shard id to metabase: %w", err) + if len(idFromMetabase) == 0 && !modeDegraded { + if setErr := s.metaBase.SetShardID(*s.info.ID, s.GetMode()); setErr != nil { + err = errors.Join(err, fmt.Errorf("failed to write shard id to metabase: %w", setErr)) } } return From 4080b99310df4170deadfa3160033304ddd9d442 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 2 Apr 2024 12:40:56 +0300 Subject: [PATCH 0466/1413] [#1061] node: Set TTL for morph rule cache from morph config Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index a1f7bba40f..45ef771f31 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1083,7 +1083,7 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) { cacheSize := morphconfig.APEChainCacheSize(c.appCfg) if cacheSize > 0 { - morphRuleStorage = newMorphCache(morphRuleStorage, int(cacheSize), morphconfig.CacheTTL(c.appCfg)) + morphRuleStorage = newMorphCache(morphRuleStorage, int(cacheSize), c.cfgMorph.cacheTTL) } ape := newAccessPolicyEngine(morphRuleStorage, localOverrideDB) From 17af91619a297354e901aaa1d8cd5be0680a9da5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 2 Apr 2024 15:02:14 +0300 Subject: [PATCH 0467/1413] [#1070] pilorama: Fix cycling behaviour for sorted listing In case there are no items left, return empty slice. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/boltdb.go | 22 ++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 1487296a4e..29a9306b62 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1069,15 +1069,7 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr } if fewChildren { - sort.Slice(result, func(i, j int) bool { - return bytes.Compare(result[i].Meta.GetAttr(AttributeFilename), result[j].Meta.GetAttr(AttributeFilename)) == -1 - }) - for i := range result { - if bytes.Compare([]byte(last), result[i].Meta.GetAttr(AttributeFilename)) == -1 { - result = result[i:] - break - } - } + result = sortAndCut(result, []byte(last)) } if len(result) != 0 { last = string(result[len(result)-1].Meta.GetAttr(AttributeFilename)) @@ -1085,6 +1077,18 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr return result, last, metaerr.Wrap(err) } +func sortAndCut(result []NodeInfo, last []byte) []NodeInfo { + sort.Slice(result, func(i, j int) bool { + return bytes.Compare(result[i].Meta.GetAttr(AttributeFilename), result[j].Meta.GetAttr(AttributeFilename)) == -1 + }) + for i := range result { + if bytes.Compare(last, result[i].Meta.GetAttr(AttributeFilename)) == -1 { + return result[i:] + } + } + return nil +} + func (t *boltForest) getChildInfo(b *bbolt.Bucket, key []byte, childID Node) (NodeInfo, error) { childInfo := NodeInfo{ID: childID} parentID, _, metaBytes, found := t.getState(b, stateKey(key, childID)) From ff4c23f59af4f9d59ac682f99b10abf5efc4914c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 2 Apr 2024 10:41:38 +0300 Subject: [PATCH 0468/1413] [#1070] services/tree: Fix fast listing depth processing For unsorted `GetSubTree()` we return a single node for depth=1. Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/getsubtree_test.go | 96 ++++++++++++++++++++-------- pkg/services/tree/service.go | 25 +++----- 2 files changed, 80 insertions(+), 41 deletions(-) diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 4f009adb69..4bf6799841 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "path" + "path/filepath" "sort" "testing" @@ -123,9 +124,21 @@ func TestGetSubTree(t *testing.T) { } func TestGetSubTreeOrderAsc(t *testing.T) { + t.Run("memory forest", func(t *testing.T) { + testGetSubTreeOrderAsc(t, pilorama.NewMemoryForest()) + }) + + t.Run("boltdb forest", func(t *testing.T) { + p := pilorama.NewBoltForest(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))) + require.NoError(t, p.Open(context.Background(), 0644)) + require.NoError(t, p.Init()) + testGetSubTreeOrderAsc(t, p) + }) +} + +func testGetSubTreeOrderAsc(t *testing.T, p pilorama.ForestStorage) { d := pilorama.CIDDescriptor{CID: cidtest.ID(), Size: 1} treeID := "sometree" - p := pilorama.NewMemoryForest() tree := []struct { path []string @@ -151,35 +164,66 @@ func TestGetSubTreeOrderAsc(t *testing.T) { tree[i].id = lm[0].Child } - acc := subTreeAcc{errIndex: -1} - err := getSubTree(context.Background(), &acc, d.CID, &GetSubTreeRequest_Body{ - TreeId: treeID, - OrderBy: &GetSubTreeRequest_Body_Order{ - Direction: GetSubTreeRequest_Body_Order_Asc, - }, - }, p) - require.NoError(t, err) - // GetSubTree must return child only after is has returned the parent. - require.Equal(t, uint64(0), acc.seen[0].Body.NodeId) + t.Run("total", func(t *testing.T) { + t.Skip() + acc := subTreeAcc{errIndex: -1} + err := getSubTree(context.Background(), &acc, d.CID, &GetSubTreeRequest_Body{ + TreeId: treeID, + OrderBy: &GetSubTreeRequest_Body_Order{ + Direction: GetSubTreeRequest_Body_Order_Asc, + }, + }, p) + require.NoError(t, err) + // GetSubTree must return child only after is has returned the parent. + require.Equal(t, uint64(0), acc.seen[0].Body.NodeId) - paths := make([]string, 0, len(acc.seen)) - for i := range acc.seen { - if i == 0 { - continue - } - found := false - for j := range tree { - if acc.seen[i].Body.NodeId == tree[j].id { - found = true - paths = append(paths, path.Join(tree[j].path...)) + paths := make([]string, 0, len(acc.seen)) + for i := range acc.seen { + if i == 0 { + continue } + found := false + for j := range tree { + if acc.seen[i].Body.NodeId == tree[j].id { + found = true + paths = append(paths, path.Join(tree[j].path...)) + } + } + require.True(t, found, "unknown node %d %v", i, acc.seen[i].GetBody().GetNodeId()) } - require.True(t, found, "unknown node %d %v", i, acc.seen[i].GetBody().GetNodeId()) - } - require.True(t, sort.SliceIsSorted(paths, func(i, j int) bool { - return paths[i] < paths[j] - })) + require.True(t, sort.SliceIsSorted(paths, func(i, j int) bool { + return paths[i] < paths[j] + })) + }) + t.Run("depth=1", func(t *testing.T) { + acc := subTreeAcc{errIndex: -1} + err := getSubTree(context.Background(), &acc, d.CID, &GetSubTreeRequest_Body{ + TreeId: treeID, + Depth: 1, + OrderBy: &GetSubTreeRequest_Body_Order{ + Direction: GetSubTreeRequest_Body_Order_Asc, + }, + }, p) + require.NoError(t, err) + require.Len(t, acc.seen, 1) + require.Equal(t, uint64(0), acc.seen[0].Body.NodeId) + }) + t.Run("depth=2", func(t *testing.T) { + acc := subTreeAcc{errIndex: -1} + err := getSubTree(context.Background(), &acc, d.CID, &GetSubTreeRequest_Body{ + TreeId: treeID, + Depth: 2, + OrderBy: &GetSubTreeRequest_Body_Order{ + Direction: GetSubTreeRequest_Body_Order_Asc, + }, + }, p) + require.NoError(t, err) + require.Len(t, acc.seen, 3) + require.Equal(t, uint64(0), acc.seen[0].Body.NodeId) + require.Equal(t, uint64(0), acc.seen[1].GetBody().GetParentId()) + require.Equal(t, uint64(0), acc.seen[2].GetBody().GetParentId()) + }) } var ( diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index f715d92495..903db4455a 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -456,28 +456,23 @@ func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid return err } - err = srv.Send(&GetSubTreeResponse{ - Body: &GetSubTreeResponse_Body{ - NodeId: b.GetRootId(), - ParentId: p, - Timestamp: m.Time, - Meta: metaToProto(m.Items), - }, - }) - if err != nil { - return err - } - stack := []stackItem{{ - values: nil, - parent: b.GetRootId(), - last: "", + values: []pilorama.NodeInfo{{ + ID: b.GetRootId(), + Meta: m, + ParentID: p, + }}, + parent: p, }} for { if len(stack) == 0 { break } else if item := &stack[len(stack)-1]; len(item.values) == 0 { + if len(stack) == 1 { + break + } + nodes, last, err := forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), item.parent, item.last, batchSize) if err != nil { return err From 4738508ce231fab8b10e3151056474a087c6a382 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Fri, 29 Mar 2024 15:31:37 +0300 Subject: [PATCH 0469/1413] [#1063] go.mod: Update SDK version * Update frostfs-sdk and frostfs-api-go versions. * Refactor depreacted method ReplicaNumberByIndex. Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/container/create.go | 4 ++-- cmd/frostfs-cli/modules/container/nodes.go | 2 +- cmd/frostfs-cli/modules/object/nodes.go | 2 +- go.mod | 4 ++-- go.sum | 8 ++++---- pkg/services/object_manager/placement/traverser.go | 2 +- pkg/services/policer/check.go | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index 728332b359..6d0ed750e0 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -58,12 +58,12 @@ It will be stored in sidechain when inner ring will accepts it.`, "use --force option to skip this check: %w", err) for i, nodes := range nodesByRep { - if placementPolicy.ReplicaNumberByIndex(i) > uint32(len(nodes)) { + if placementPolicy.ReplicaDescriptor(i).NumberOfObjects() > uint32(len(nodes)) { commonCmd.ExitOnErr(cmd, "", fmt.Errorf( "the number of nodes '%d' in selector is not enough for the number of replicas '%d', "+ "use --force option to skip this check", len(nodes), - placementPolicy.ReplicaNumberByIndex(i), + placementPolicy.ReplicaDescriptor(i).NumberOfObjects(), )) } } diff --git a/cmd/frostfs-cli/modules/container/nodes.go b/cmd/frostfs-cli/modules/container/nodes.go index d785fa23df..b8765061c1 100644 --- a/cmd/frostfs-cli/modules/container/nodes.go +++ b/cmd/frostfs-cli/modules/container/nodes.go @@ -46,7 +46,7 @@ var containerNodesCmd = &cobra.Command{ commonCmd.ExitOnErr(cmd, "could not build container nodes for given container: %w", err) for i := range cnrNodes { - cmd.Printf("Descriptor #%d, REP %d:\n", i+1, policy.ReplicaNumberByIndex(i)) + cmd.Printf("Descriptor #%d, REP %d:\n", i+1, policy.ReplicaDescriptor(i).NumberOfObjects()) for j := range cnrNodes[i] { commonCmd.PrettyPrintNodeInfo(cmd, cnrNodes[i][j], j, "\t", short) } diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 50c47e8222..38b9dec82a 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -190,7 +190,7 @@ func getRequiredPlacement(cmd *cobra.Command, objInfo *objectNodesInfo, placemen placement, err := placementBuilder.BuildPlacement(objInfo.containerID, &objInfo.objectID, placementPolicy) commonCmd.ExitOnErr(cmd, "failed to get required placement: %w", err) for repIdx, rep := range placement { - numOfReplicas := placementPolicy.ReplicaNumberByIndex(repIdx) + numOfReplicas := placementPolicy.ReplicaDescriptor(repIdx).NumberOfObjects() var nodeIdx uint32 for _, n := range rep { if !objInfo.isLockOrTombstone && nodeIdx == numOfReplicas { // lock and tombstone objects should be on all container nodes diff --git a/go.mod b/go.mod index 1d18bb9d3e..3159b9c0a4 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.20 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240327095603-491a47e7fe24 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index d90bf0f6a5..e4bd28600d 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715 h1:EDtL9OJcdeevV/jmNMtHugulAQprdOnknNPvLB3LRgE= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240215124401-634e24aba715/go.mod h1:uY0AYmCznjZdghDnAk7THFIe1Vlg531IxUcus7ZfUJI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240327095603-491a47e7fe24 h1:uIkl0mKWwDICUZTbNWZ38HLYDBI9rMgdAhYQWZ0C9iQ= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240327095603-491a47e7fe24/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 h1:FzurjElUwC7InY9v5rzXReKbfBL5yRJKSWJPq6BKhH0= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b h1:nLIWYXe4e1fWgpKeMfVke/CNBn388egh4fArFdvhfHw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240301150205-6fe4e2541d0b/go.mod h1:XcgrbZ88XfvhAMxmZCQJ0dv6FyRSq6Mg2J7nN8uuO0k= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92 h1:hSyM52d8yIaOpYQlLlVYdrGbgCsvIDjwl3AJaJUlYPU= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92/go.mod h1:i0RKqiF4z3UOxLSNwhHw+cUz/JyYWuTRpnn9ere4Y3w= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd h1:pyIl9f4nIr7ekJ73W9keLIQ5dpoKb8o6xNmodsXY5+o= diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 53da186e84..a699b44540 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -137,7 +137,7 @@ func defaultCopiesVector(policy netmap.PlacementPolicy) []int { copyVector := make([]int, 0, replNum) for i := 0; i < replNum; i++ { - copyVector = append(copyVector, int(policy.ReplicaNumberByIndex(i))) + copyVector = append(copyVector, int(policy.ReplicaDescriptor(i).NumberOfObjects())) } return copyVector diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index bb6313d071..d2297fed70 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -63,7 +63,7 @@ func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.Add default: } - p.processNodes(ctx, c, addrWithType, nn[i], policy.ReplicaNumberByIndex(i), checkedNodes) + p.processNodes(ctx, c, addrWithType, nn[i], policy.ReplicaDescriptor(i).NumberOfObjects(), checkedNodes) } if !c.needLocalCopy && c.removeLocalCopy { From 531542ce60a90a01ae04b63c54a92fede1b881c3 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Fri, 29 Mar 2024 15:59:50 +0300 Subject: [PATCH 0470/1413] [#1063] cli: Validate container creation for EC policy Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/container/create.go | 28 +++++++++++++++------ cmd/frostfs-cli/modules/container/nodes.go | 10 +++++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index 6d0ed750e0..c6f5769089 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -58,13 +58,27 @@ It will be stored in sidechain when inner ring will accepts it.`, "use --force option to skip this check: %w", err) for i, nodes := range nodesByRep { - if placementPolicy.ReplicaDescriptor(i).NumberOfObjects() > uint32(len(nodes)) { - commonCmd.ExitOnErr(cmd, "", fmt.Errorf( - "the number of nodes '%d' in selector is not enough for the number of replicas '%d', "+ - "use --force option to skip this check", - len(nodes), - placementPolicy.ReplicaDescriptor(i).NumberOfObjects(), - )) + if repNum := placementPolicy.ReplicaDescriptor(i).NumberOfObjects(); repNum > 0 { + if repNum > uint32(len(nodes)) { + commonCmd.ExitOnErr(cmd, "", fmt.Errorf( + "the number of nodes '%d' in selector is not enough for the number of replicas '%d', "+ + "use --force option to skip this check", + len(nodes), + repNum, + )) + } + } else if ecParts := placementPolicy.ReplicaDescriptor(i).TotalECPartCount(); ecParts > 0 { + if ecParts > uint32(len(nodes)) { + commonCmd.ExitOnErr(cmd, "", fmt.Errorf( + "the number of nodes '%d' in selector is not enough for EC placement '%d.%d', "+ + "use --force option to skip this check", + len(nodes), + placementPolicy.ReplicaDescriptor(i).GetECDataCount(), + placementPolicy.ReplicaDescriptor(i).GetECParityCount(), + )) + } + } else { + commonCmd.ExitOnErr(cmd, "%w", errors.New("no replication policy is set")) } } } diff --git a/cmd/frostfs-cli/modules/container/nodes.go b/cmd/frostfs-cli/modules/container/nodes.go index b8765061c1..1ae8ab6041 100644 --- a/cmd/frostfs-cli/modules/container/nodes.go +++ b/cmd/frostfs-cli/modules/container/nodes.go @@ -2,6 +2,7 @@ package container import ( "crypto/sha256" + "errors" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -46,7 +47,14 @@ var containerNodesCmd = &cobra.Command{ commonCmd.ExitOnErr(cmd, "could not build container nodes for given container: %w", err) for i := range cnrNodes { - cmd.Printf("Descriptor #%d, REP %d:\n", i+1, policy.ReplicaDescriptor(i).NumberOfObjects()) + if repNum := policy.ReplicaDescriptor(i).NumberOfObjects(); repNum > 0 { + cmd.Printf("Descriptor #%d, REP %d:\n", i+1, repNum) + } else if ecParts := policy.ReplicaDescriptor(i).TotalECPartCount(); ecParts > 0 { + cmd.Printf("Descriptor #%d, EC %d.%d:\n", i+1, policy.ReplicaDescriptor(i).GetECDataCount(), + policy.ReplicaDescriptor(i).GetECParityCount()) + } else { + commonCmd.ExitOnErr(cmd, "%w", errors.New("no replication policy is set")) + } for j := range cnrNodes[i] { commonCmd.PrettyPrintNodeInfo(cmd, cnrNodes[i][j], j, "\t", short) } From d614f04a0a29504d82073fc4d69b50b029a7315c Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 3 Apr 2024 11:44:02 +0300 Subject: [PATCH 0471/1413] [#1072] Fix gofumpt issues Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/pilorama/heap.go | 1 + pkg/services/tree/getsubtree_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/pilorama/heap.go b/pkg/local_object_storage/pilorama/heap.go index 667283c2af..50abb663c7 100644 --- a/pkg/local_object_storage/pilorama/heap.go +++ b/pkg/local_object_storage/pilorama/heap.go @@ -17,6 +17,7 @@ func (h filenameHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *filenameHeap) Push(x any) { *h = append(*h, x.(heapInfo)) } + func (h *filenameHeap) Pop() any { old := *h n := len(old) diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 4bf6799841..9a4223e30e 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -130,7 +130,7 @@ func TestGetSubTreeOrderAsc(t *testing.T) { t.Run("boltdb forest", func(t *testing.T) { p := pilorama.NewBoltForest(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))) - require.NoError(t, p.Open(context.Background(), 0644)) + require.NoError(t, p.Open(context.Background(), 0o644)) require.NoError(t, p.Init()) testGetSubTreeOrderAsc(t, p) }) From 9aa533e59a700455fc5aaf47701729767f12241b Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 4 Apr 2024 11:05:25 +0300 Subject: [PATCH 0472/1413] [#1072] node, ir: Add new config option `kludge_compatibility_mode` Signed-off-by: Anton Nikiforov --- cmd/frostfs-ir/config.go | 1 + cmd/frostfs-ir/defaults.go | 2 ++ cmd/frostfs-ir/main.go | 6 +++++- cmd/frostfs-node/config.go | 12 +++++++++++- cmd/frostfs-node/config/node/config.go | 5 +++++ pkg/innerring/innerring.go | 5 ++++- 6 files changed, 28 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index be870052c0..c73b68eb59 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -34,6 +34,7 @@ func reloadConfig() error { if err != nil { return err } + cmode.Store(cfg.GetBool("node.kludge_compatibility_mode")) err = logPrm.SetLevelString(cfg.GetString("logger.level")) if err != nil { return err diff --git a/cmd/frostfs-ir/defaults.go b/cmd/frostfs-ir/defaults.go index 127a68b29b..23a4755910 100644 --- a/cmd/frostfs-ir/defaults.go +++ b/cmd/frostfs-ir/defaults.go @@ -43,6 +43,8 @@ func defaultConfiguration(cfg *viper.Viper) { setControlDefaults(cfg) cfg.SetDefault("governance.disable", false) + + cfg.SetDefault("node.kludge_compatibility_mode", false) } func setControlDefaults(cfg *viper.Viper) { diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 9879342b7e..31390dd74e 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "sync" + "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" @@ -37,6 +38,7 @@ var ( cfg *viper.Viper configFile *string configDir *string + cmode = &atomic.Bool{} ) func exitErr(err error) { @@ -62,6 +64,8 @@ func main() { cfg, err = newConfig() exitErr(err) + cmode.Store(cfg.GetBool("node.kludge_compatibility_mode")) + metrics := irMetrics.NewInnerRingMetrics() err = logPrm.SetLevelString( @@ -84,7 +88,7 @@ func main() { metricsCmp = newMetricsComponent() metricsCmp.init() - innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics) + innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode) exitErr(err) pprofCmp.start() diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 45ef771f31..d78a90cfc9 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -109,6 +109,9 @@ type applicationConfiguration struct { lowMem bool rebuildWorkers uint32 } + + // if need to run node in compatibility with other versions mode + cmode *atomic.Bool } type shardCfg struct { @@ -204,10 +207,13 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { } // clear if it is rereading + cmode := a.cmode *a = applicationConfiguration{} + a.cmode = cmode } a._read = true + a.cmode.Store(nodeconfig.CompatibilityMode(c)) // Logger @@ -648,7 +654,11 @@ type cfgControlService struct { var persistateSideChainLastBlockKey = []byte("side_chain_last_processed_block") func initCfg(appCfg *config.Config) *cfg { - c := &cfg{} + c := &cfg{ + applicationConfiguration: applicationConfiguration{ + cmode: &atomic.Bool{}, + }, + } err := c.readConfig(appCfg) if err != nil { diff --git a/cmd/frostfs-node/config/node/config.go b/cmd/frostfs-node/config/node/config.go index ac76ad47e5..90338556e0 100644 --- a/cmd/frostfs-node/config/node/config.go +++ b/cmd/frostfs-node/config/node/config.go @@ -292,3 +292,8 @@ func (l PersistentPolicyRulesConfig) Perm() fs.FileMode { func (l PersistentPolicyRulesConfig) NoSync() bool { return config.BoolSafe((*config.Config)(l.cfg), "no_sync") } + +// CompatibilityMode returns true if need to run node in compatibility with previous versions mode. +func CompatibilityMode(c *config.Config) bool { + return config.BoolSafe(c.Sub(subsection), "kludge_compatibility_mode") +} diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 5d7dc5a523..11d43f845f 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -103,6 +103,8 @@ type ( // should report start errors // to the application. runners []func(chan<- error) error + + cmode *atomic.Bool } chainParams struct { @@ -330,12 +332,13 @@ func (s *Server) registerStarter(f func() error) { // New creates instance of inner ring sever structure. func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error, - metrics *metrics.InnerRingServiceMetrics, + metrics *metrics.InnerRingServiceMetrics, cmode *atomic.Bool, ) (*Server, error) { var err error server := &Server{ log: log, irMetrics: metrics, + cmode: cmode, } server.sdNotify, err = server.initSdNotify(cfg) From ffb1a6f81a4ea8f249af58de66b2543ed6366a16 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 4 Apr 2024 11:36:38 +0300 Subject: [PATCH 0473/1413] [#1072] Fix issue from `govulncheck` Signed-off-by: Anton Nikiforov --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 3159b9c0a4..2544f0fb9d 100644 --- a/go.mod +++ b/go.mod @@ -40,8 +40,8 @@ require ( go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a golang.org/x/sync v0.6.0 - golang.org/x/sys v0.16.0 - golang.org/x/term v0.16.0 + golang.org/x/sys v0.18.0 + golang.org/x/term v0.18.0 google.golang.org/grpc v1.61.0 google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 @@ -121,8 +121,8 @@ require ( go.opentelemetry.io/otel/sdk v1.22.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/net v0.20.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect diff --git a/go.sum b/go.sum index e4bd28600d..8dbaa53738 100644 --- a/go.sum +++ b/go.sum @@ -316,8 +316,8 @@ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -339,8 +339,8 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -375,15 +375,15 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= From 0290f86579bc92cce094287a6bd00affb51b0f0b Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Sun, 31 Mar 2024 21:36:57 +0300 Subject: [PATCH 0474/1413] [#1065] adm: refactor dump-config Signed-off-by: Alexander Chuprov --- .../internal/modules/morph/config/config.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index 3414a8f7f4..2238a38df5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -105,12 +105,22 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { forceFlag, _ := cmd.Flags().GetBool(forceConfigSet) bw := io.NewBufBinWriter() + prm := make(map[string]any) + for _, arg := range args { k, v, err := parseConfigPair(arg, forceFlag) if err != nil { return err } + prm[k] = v + } + + if err := validateConfig(prm); err != nil { + return err + } + + for k, v := range prm { // In NeoFS this is done via Notary contract. Here, however, we can form the // transaction locally. The first `nil` argument is required only for notary // disabled environment which is not supported by that command. @@ -128,6 +138,16 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { return wCtx.AwaitTx() } +func validateConfig(args map[string]any) error { + for k, v := range args { + value, ok := v.(int64) + if !ok || value < 0 { + return fmt.Errorf("%s must be >= 0, got %v", k, v) + } + } + return nil +} + func parseConfigPair(kvStr string, force bool) (key string, val any, err error) { k, v, found := strings.Cut(kvStr, "=") if !found { From 17f7adb640a18fef40c835acfaa225f26e3da481 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 8 Apr 2024 12:27:30 +0300 Subject: [PATCH 0475/1413] [#1065] adm: Add support EC parameters Signed-off-by: Alexander Chuprov --- cmd/frostfs-adm/docs/deploy.md | 2 ++ cmd/frostfs-adm/internal/commonflags/flags.go | 2 ++ .../internal/modules/config/config.go | 6 ++++ .../internal/modules/config/config_test.go | 2 ++ .../internal/modules/morph/config/config.go | 29 +++++++++++++++---- .../internal/modules/morph/helper/netmap.go | 2 ++ .../internal/modules/morph/initialize/root.go | 2 ++ dev/adm/frostfs-adm.yml | 2 ++ pkg/morph/client/netmap/config.go | 2 ++ 9 files changed, 43 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-adm/docs/deploy.md b/cmd/frostfs-adm/docs/deploy.md index 3b9f4c98c4..e510f478d4 100644 --- a/cmd/frostfs-adm/docs/deploy.md +++ b/cmd/frostfs-adm/docs/deploy.md @@ -34,6 +34,8 @@ alphabet-wallets: /home/user/deploy/alphabet-wallets network: max_object_size: 67108864 epoch_duration: 240 + max_ec_data_count: 12 + max_ec_parity_count: 4 fee: candidate: 0 container: 0 diff --git a/cmd/frostfs-adm/internal/commonflags/flags.go b/cmd/frostfs-adm/internal/commonflags/flags.go index bf6c17bd11..81395edb0f 100644 --- a/cmd/frostfs-adm/internal/commonflags/flags.go +++ b/cmd/frostfs-adm/internal/commonflags/flags.go @@ -26,6 +26,8 @@ const ( ContractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" EpochDurationInitFlag = "network.epoch_duration" MaxObjectSizeInitFlag = "network.max_object_size" + MaxECDataCountFlag = "network.max_ec_data_count" + MaxECParityCounFlag = "network.max_ec_parity_count" RefillGasAmountFlag = "gas" StorageWalletFlag = "storage-wallet" ContainerFeeInitFlag = "network.fee.container" diff --git a/cmd/frostfs-adm/internal/modules/config/config.go b/cmd/frostfs-adm/internal/modules/config/config.go index dd98a98b24..a98245d010 100644 --- a/cmd/frostfs-adm/internal/modules/config/config.go +++ b/cmd/frostfs-adm/internal/modules/config/config.go @@ -21,6 +21,8 @@ type configTemplate struct { CandidateFee int ContainerFee int ContainerAliasFee int + MaxECDataCount int + MaxECParityCount int WithdrawFee int Glagolitics []string HomomorphicHashDisabled bool @@ -31,6 +33,8 @@ alphabet-wallets: {{ .AlphabetDir}} network: max_object_size: {{ .MaxObjectSize}} epoch_duration: {{ .EpochDuration}} + max_ec_data_count: {{ .MaxECDataCount}} + max_ec_parity_count: {{ .MaxECParityCount}} homomorphic_hash_disabled: {{ .HomomorphicHashDisabled}} fee: candidate: {{ .CandidateFee}} @@ -106,6 +110,8 @@ func generateConfigExample(appDir string, credSize int) (string, error) { tmpl := configTemplate{ Endpoint: "https://neo.rpc.node:30333", MaxObjectSize: 67108864, // 64 MiB + MaxECDataCount: 12, // Tested with 16-node networks, assuming 12 data + 4 parity nodes. + MaxECParityCount: 4, // Maximum 4 parity chunks, typically <= 3 for most policies. EpochDuration: 240, // 1 hour with 15s per block HomomorphicHashDisabled: false, // object homomorphic hash is enabled CandidateFee: 100_0000_0000, // 100.0 GAS (Fixed8) diff --git a/cmd/frostfs-adm/internal/modules/config/config_test.go b/cmd/frostfs-adm/internal/modules/config/config_test.go index 3fa800a06b..beb1210e18 100644 --- a/cmd/frostfs-adm/internal/modules/config/config_test.go +++ b/cmd/frostfs-adm/internal/modules/config/config_test.go @@ -27,6 +27,8 @@ func TestGenerateConfigExample(t *testing.T) { require.Equal(t, "https://neo.rpc.node:30333", v.GetString("rpc-endpoint")) require.Equal(t, filepath.Join(appDir, "alphabet-wallets"), v.GetString("alphabet-wallets")) require.Equal(t, 67108864, v.GetInt("network.max_object_size")) + require.Equal(t, 12, v.GetInt("network.max_ec_data_count")) + require.Equal(t, 4, v.GetInt("network.max_ec_parity_count")) require.Equal(t, 240, v.GetInt("network.epoch_duration")) require.Equal(t, 10000000000, v.GetInt("network.fee.candidate")) require.Equal(t, 1000, v.GetInt("network.fee.container")) diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index 2238a38df5..f35e7aa036 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -60,7 +60,8 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { switch k { case netmap.ContainerFeeConfig, netmap.ContainerAliasFeeConfig, netmap.EpochDurationConfig, netmap.IrCandidateFeeConfig, - netmap.MaxObjectSizeConfig, netmap.WithdrawFeeConfig: + netmap.MaxObjectSizeConfig, netmap.WithdrawFeeConfig, + netmap.MaxECDataCountConfig, netmap.MaxECParityCountConfig: nbuf := make([]byte, 8) copy(nbuf[:], v) n := binary.LittleEndian.Uint64(nbuf) @@ -103,10 +104,8 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { } forceFlag, _ := cmd.Flags().GetBool(forceConfigSet) - bw := io.NewBufBinWriter() prm := make(map[string]any) - for _, arg := range args { k, v, err := parseConfigPair(arg, forceFlag) if err != nil { @@ -116,7 +115,7 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { prm[k] = v } - if err := validateConfig(prm); err != nil { + if err := validateConfig(prm, forceFlag); err != nil { return err } @@ -138,12 +137,29 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { return wCtx.AwaitTx() } -func validateConfig(args map[string]any) error { +func validateConfig(args map[string]any, forceFlag bool) error { + var sumEC int64 + _, okData := args[netmap.MaxECDataCountConfig] + _, okParity := args[netmap.MaxECParityCountConfig] + if okData != okParity { + return fmt.Errorf("both %s and %s must be present in the configuration", + netmap.MaxECDataCountConfig, netmap.MaxECParityCountConfig) + } + for k, v := range args { value, ok := v.(int64) if !ok || value < 0 { return fmt.Errorf("%s must be >= 0, got %v", k, v) } + + if k == netmap.MaxECDataCountConfig || k == netmap.MaxECParityCountConfig { + sumEC += value + } + } + + if sumEC > 256 && !forceFlag { + return fmt.Errorf("the sum of %s and %s must be <= 256, got %d", + netmap.MaxECDataCountConfig, netmap.MaxECParityCountConfig, sumEC) } return nil } @@ -160,7 +176,8 @@ func parseConfigPair(kvStr string, force bool) (key string, val any, err error) switch key { case netmap.ContainerFeeConfig, netmap.ContainerAliasFeeConfig, netmap.EpochDurationConfig, netmap.IrCandidateFeeConfig, - netmap.MaxObjectSizeConfig, netmap.WithdrawFeeConfig: + netmap.MaxObjectSizeConfig, netmap.WithdrawFeeConfig, + netmap.MaxECDataCountConfig, netmap.MaxECParityCountConfig: val, err = strconv.ParseInt(valRaw, 10, 64) if err != nil { err = fmt.Errorf("could not parse %s's value '%s' as int: %w", key, valRaw, err) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go index f68fbefaf6..9ea27d3a37 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go @@ -35,6 +35,8 @@ func GetDefaultNetmapContractConfigMap() map[string]any { m := make(map[string]any) m[netmap.EpochDurationConfig] = viper.GetInt64(commonflags.EpochDurationInitFlag) m[netmap.MaxObjectSizeConfig] = viper.GetInt64(commonflags.MaxObjectSizeInitFlag) + m[netmap.MaxECDataCountConfig] = viper.GetInt64(commonflags.MaxECDataCountFlag) + m[netmap.MaxECParityCountConfig] = viper.GetInt64(commonflags.MaxECParityCounFlag) m[netmap.ContainerFeeConfig] = viper.GetInt64(commonflags.ContainerFeeInitFlag) m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(commonflags.ContainerAliasFeeInitFlag) m[netmap.IrCandidateFeeConfig] = viper.GetInt64(commonflags.CandidateFeeInitFlag) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go index 581bef5322..b7885c5124 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go @@ -25,6 +25,8 @@ var Cmd = &cobra.Command{ _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.EpochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) _ = viper.BindPFlag(commonflags.MaxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) + _ = viper.BindPFlag(commonflags.MaxECDataCountFlag, cmd.Flags().Lookup(commonflags.MaxECDataCountFlag)) + _ = viper.BindPFlag(commonflags.MaxECParityCounFlag, cmd.Flags().Lookup(commonflags.MaxECParityCounFlag)) _ = viper.BindPFlag(commonflags.HomomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) _ = viper.BindPFlag(commonflags.CandidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) _ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) diff --git a/dev/adm/frostfs-adm.yml b/dev/adm/frostfs-adm.yml index 5dc87e70c5..e75cc27f07 100644 --- a/dev/adm/frostfs-adm.yml +++ b/dev/adm/frostfs-adm.yml @@ -6,6 +6,8 @@ network: basic_income_rate: 100000000 homomorphic_hash_disabled: false maintenance_mode_allowed: true + max_ec_data_count: 12 + max_ec_parity_count: 4 fee: audit: 10000 candidate: 10000000000 diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index 21ba145d45..2d19a8193c 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -11,6 +11,8 @@ import ( const ( MaxObjectSizeConfig = "MaxObjectSize" + MaxECParityCountConfig = "MaxECParityCount" + MaxECDataCountConfig = "MaxECDataCount" EpochDurationConfig = "EpochDuration" ContainerFeeConfig = "ContainerFee" ContainerAliasFeeConfig = "ContainerAliasFee" From 92569b9bbf7982a802cb3f8fb36406eaf897d701 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 8 Apr 2024 12:27:51 +0300 Subject: [PATCH 0476/1413] [#1065] cli: Add support EC parameters Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/modules/netmap/netinfo.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/frostfs-cli/modules/netmap/netinfo.go b/cmd/frostfs-cli/modules/netmap/netinfo.go index cd43ba68df..2dbd72355e 100644 --- a/cmd/frostfs-cli/modules/netmap/netinfo.go +++ b/cmd/frostfs-cli/modules/netmap/netinfo.go @@ -43,6 +43,8 @@ var netInfoCmd = &cobra.Command{ cmd.Printf(format, "Epoch duration", netInfo.EpochDuration()) cmd.Printf(format, "Inner Ring candidate fee", netInfo.IRCandidateFee()) cmd.Printf(format, "Maximum object size", netInfo.MaxObjectSize()) + cmd.Printf(format, "Maximum count of data shards", netInfo.MaxECDataCount()) + cmd.Printf(format, "Maximum count of parity shards", netInfo.MaxECParityCount()) cmd.Printf(format, "Withdrawal fee", netInfo.WithdrawalFee()) cmd.Printf(format, "Homomorphic hashing disabled", netInfo.HomomorphicHashingDisabled()) cmd.Printf(format, "Maintenance mode allowed", netInfo.MaintenanceModeAllowed()) From 39da6433544be0fd70660181482b5f8247c92e21 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 27 Mar 2024 11:36:58 +0300 Subject: [PATCH 0477/1413] [#1064] putsvc: Refactor distributed target Extract object builder. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/put/builder.go | 54 ++++++++++++++++++++++++++ pkg/services/object/put/distributed.go | 36 +---------------- pkg/services/object/put/streamer.go | 18 +++------ 3 files changed, 60 insertions(+), 48 deletions(-) create mode 100644 pkg/services/object/put/builder.go diff --git a/pkg/services/object/put/builder.go b/pkg/services/object/put/builder.go new file mode 100644 index 0000000000..64baf4e051 --- /dev/null +++ b/pkg/services/object/put/builder.go @@ -0,0 +1,54 @@ +package putsvc + +import ( + "context" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" +) + +var _ transformer.ChunkedObjectWriter = (*inMemoryObjectBuilder)(nil) + +type inMemoryObjectBuilder struct { + objectWriter transformer.ObjectWriter + payload *payload + + obj *objectSDK.Object +} + +func newInMemoryObjectBuilder(objectWriter transformer.ObjectWriter) *inMemoryObjectBuilder { + return &inMemoryObjectBuilder{ + objectWriter: objectWriter, + payload: getPayload(), + } +} + +func (b *inMemoryObjectBuilder) Close(ctx context.Context) (*transformer.AccessIdentifiers, error) { + defer func() { + putPayload(b.payload) + b.payload = nil + }() + + b.obj.SetPayload(b.payload.Data) + + if err := b.objectWriter.WriteObject(ctx, b.obj); err != nil { + return nil, err + } + + id, _ := b.obj.ID() + return &transformer.AccessIdentifiers{ + SelfID: id, + }, nil +} + +func (b *inMemoryObjectBuilder) Write(_ context.Context, p []byte) (int, error) { + b.payload.Data = append(b.payload.Data, p...) + + return len(p), nil +} + +func (b *inMemoryObjectBuilder) WriteHeader(_ context.Context, obj *objectSDK.Object) error { + b.obj = obj + + return nil +} diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index 509f4aee0f..c71427b67b 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" ) type preparedObjectTarget interface { @@ -15,16 +14,13 @@ type preparedObjectTarget interface { } type distributedTarget struct { - placementOpts []placement.Option - extraBroadcastEnabled bool + placementOpts []placement.Option obj *objectSDK.Object objMeta object.ContentMeta *cfg - payload *payload - nodeTargetInitializer func(nodeDesc) preparedObjectTarget relay func(context.Context, nodeDesc) error @@ -91,36 +87,6 @@ func (x errIncompletePut) Error() string { return commonMsg } -func (t *distributedTarget) WriteHeader(_ context.Context, obj *objectSDK.Object) error { - t.obj = obj - - return nil -} - -func (t *distributedTarget) Write(_ context.Context, p []byte) (n int, err error) { - t.payload.Data = append(t.payload.Data, p...) - - return len(p), nil -} - -func (t *distributedTarget) Close(ctx context.Context) (*transformer.AccessIdentifiers, error) { - defer func() { - putPayload(t.payload) - t.payload = nil - }() - - t.obj.SetPayload(t.payload.Data) - - if err := t.WriteObject(ctx, t.obj); err != nil { - return nil, err - } - - id, _ := t.obj.ID() - return &transformer.AccessIdentifiers{ - SelfID: id, - }, nil -} - // WriteObject implements the transformer.ObjectWriter interface. func (t *distributedTarget) WriteObject(ctx context.Context, obj *objectSDK.Object) error { t.obj = obj diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 90d580a1cf..f32b2ab992 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -12,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" pkgutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) @@ -79,7 +78,7 @@ func (p *Streamer) initUntrustedTarget(prm *PutInitPrm) error { // prepare untrusted-Put object target p.target = &validatingPreparedTarget{ - nextTarget: p.newCommonTarget(prm), + nextTarget: newInMemoryObjectBuilder(p.newObjectWriter(prm)), fmt: p.fmtValidator, maxPayloadSz: p.maxPayloadSz, @@ -133,7 +132,7 @@ func (p *Streamer) initTrustedTarget(prm *PutInitPrm) error { fmt: p.fmtValidator, nextTarget: transformer.NewPayloadSizeLimiter(transformer.Params{ Key: sessionKey, - NextTargetInit: func() transformer.ObjectWriter { return p.newCommonTarget(prm) }, + NextTargetInit: func() transformer.ObjectWriter { return p.newObjectWriter(prm) }, NetworkState: p.networkState, MaxSize: p.maxPayloadSz, WithoutHomomorphicHash: containerSDK.IsHomomorphicHashingDisabled(prm.cnr), @@ -196,7 +195,7 @@ func (p *Streamer) preparePrm(prm *PutInitPrm) error { return nil } -func (p *Streamer) newCommonTarget(prm *PutInitPrm) *distributedTarget { +func (p *Streamer) newObjectWriter(prm *PutInitPrm) transformer.ObjectWriter { var relay func(context.Context, nodeDesc) error if p.relay != nil { relay = func(ctx context.Context, node nodeDesc) error { @@ -213,16 +212,9 @@ func (p *Streamer) newCommonTarget(prm *PutInitPrm) *distributedTarget { } } - // enable additional container broadcast on non-local operation - // if object has TOMBSTONE or LOCK type. - typ := prm.hdr.Type() - withBroadcast := !prm.common.LocalOnly() && (typ == objectSDK.TypeTombstone || typ == objectSDK.TypeLock) - return &distributedTarget{ - cfg: p.cfg, - placementOpts: prm.traverseOpts, - extraBroadcastEnabled: withBroadcast, - payload: getPayload(), + cfg: p.cfg, + placementOpts: prm.traverseOpts, nodeTargetInitializer: func(node nodeDesc) preparedObjectTarget { if node.local { return localTarget{ From 1c5e0f90aabaee60f2275b7fb3fead8bedabc019 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 28 Mar 2024 13:46:19 +0300 Subject: [PATCH 0478/1413] [#1064] putsvc: Add EC put Signed-off-by: Dmitrii Stepanov --- go.mod | 1 + go.sum | 2 + internal/logs/logs.go | 2 + pkg/core/container/ec.go | 11 + pkg/core/object/ec.go | 13 + pkg/core/policy/ec.go | 20 ++ pkg/services/object/put/ec.go | 265 ++++++++++++++++++ pkg/services/object/put/single.go | 88 +++++- pkg/services/object/put/streamer.go | 48 +++- pkg/services/object/put/writer.go | 23 ++ .../object_manager/placement/traverser.go | 2 +- 11 files changed, 452 insertions(+), 23 deletions(-) create mode 100644 pkg/core/container/ec.go create mode 100644 pkg/core/object/ec.go create mode 100644 pkg/core/policy/ec.go create mode 100644 pkg/services/object/put/ec.go create mode 100644 pkg/services/object/put/writer.go diff --git a/go.mod b/go.mod index 2544f0fb9d..f940b306ae 100644 --- a/go.mod +++ b/go.mod @@ -85,6 +85,7 @@ require ( github.com/ipfs/go-cid v0.4.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect + github.com/klauspost/reedsolomon v1.12.1 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect diff --git a/go.sum b/go.sum index 8dbaa53738..7f7e843986 100644 --- a/go.sum +++ b/go.sum @@ -133,6 +133,8 @@ github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/reedsolomon v1.12.1 h1:NhWgum1efX1x58daOBGCFWcxtEhOhXKKl1HAPQUp03Q= +github.com/klauspost/reedsolomon v1.12.1/go.mod h1:nEi5Kjb6QqtbofI6s+cbG/j1da11c96IBYBSnVGtuBs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= diff --git a/internal/logs/logs.go b/internal/logs/logs.go index bd8b8ed018..64e5f771e6 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -579,4 +579,6 @@ const ( EngineShardsEvacuationFailedToMoveTree = "failed to evacuate tree to other node" EngineShardsEvacuationTreeEvacuatedLocal = "tree evacuated to local node" EngineShardsEvacuationTreeEvacuatedRemote = "tree evacuated to other node" + ECFailedToSendToContainerNode = "failed to send EC object to container node" + ECFailedToSaveECPart = "failed to save EC part" ) diff --git a/pkg/core/container/ec.go b/pkg/core/container/ec.go new file mode 100644 index 0000000000..1acb87f2b9 --- /dev/null +++ b/pkg/core/container/ec.go @@ -0,0 +1,11 @@ +package container + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" +) + +// IsECContainer returns True if container has erasure coding policy. +func IsECContainer(cnr containerSDK.Container) bool { + return policy.IsECPlacement(cnr.PlacementPolicy()) +} diff --git a/pkg/core/object/ec.go b/pkg/core/object/ec.go new file mode 100644 index 0000000000..549ff7cd37 --- /dev/null +++ b/pkg/core/object/ec.go @@ -0,0 +1,13 @@ +package object + +import ( + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" +) + +// IsECSupported returns True if EC supported for object. +// +// EC supported only for regular, not linking objects. +func IsECSupported(obj *objectSDK.Object) bool { + return obj.Type() == objectSDK.TypeRegular && + len(obj.Children()) == 0 +} diff --git a/pkg/core/policy/ec.go b/pkg/core/policy/ec.go new file mode 100644 index 0000000000..846af775a2 --- /dev/null +++ b/pkg/core/policy/ec.go @@ -0,0 +1,20 @@ +package policy + +import ( + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" +) + +// IsECPlacement returns True if policy is erasure coding policy. +func IsECPlacement(policy netmapSDK.PlacementPolicy) bool { + return policy.NumberOfReplicas() == 1 && policy.ReplicaDescriptor(0).GetECDataCount() > 0 +} + +// ECDataCount returns EC data count for EC placement policy. +func ECDataCount(policy netmapSDK.PlacementPolicy) int { + return int(policy.ReplicaDescriptor(0).GetECDataCount()) +} + +// ECParityCount returns EC parity count for EC placement policy. +func ECParityCount(policy netmapSDK.PlacementPolicy) int { + return int(policy.ReplicaDescriptor(0).GetECParityCount()) +} diff --git a/pkg/services/object/put/ec.go b/pkg/services/object/put/ec.go new file mode 100644 index 0000000000..74db3c31fb --- /dev/null +++ b/pkg/services/object/put/ec.go @@ -0,0 +1,265 @@ +package putsvc + +import ( + "context" + "crypto/ecdsa" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" + svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" + "go.uber.org/zap" + "golang.org/x/sync/errgroup" +) + +var _ transformer.ObjectWriter = (*ecWriter)(nil) + +var errUnsupportedECObject = errors.New("object is not supported for erasure coding") + +type ecWriter struct { + cfg *cfg + placementOpts []placement.Option + container containerSDK.Container + key *ecdsa.PrivateKey + commonPrm *svcutil.CommonPrm + relay func(context.Context, client.NodeInfo, client.MultiAddressClient) error + + objMeta object.ContentMeta + objMetaValid bool +} + +func (e *ecWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error { + relayed, err := e.relayIfNotContainerNode(ctx) + if err != nil { + return err + } + if relayed { + return nil + } + + if !object.IsECSupported(obj) { + // must be resolved by caller + return errUnsupportedECObject + } + + if !e.objMetaValid { + if e.objMeta, err = e.cfg.fmtValidator.ValidateContent(obj); err != nil { + return fmt.Errorf("(%T) could not validate payload content: %w", e, err) + } + e.objMetaValid = true + } + + if obj.ECHeader() != nil { + return e.writeECPart(ctx, obj) + } + return e.writeRawObject(ctx, obj) +} + +func (e *ecWriter) relayIfNotContainerNode(ctx context.Context) (bool, error) { + if e.relay == nil { + return false, nil + } + currentNodeIsContainerNode, err := e.currentNodeIsContainerNode() + if err != nil { + return false, err + } + if currentNodeIsContainerNode { + // object can be splitted or saved local + return false, nil + } + if err := e.relayToContainerNode(ctx); err != nil { + return false, err + } + return true, nil +} + +func (e *ecWriter) currentNodeIsContainerNode() (bool, error) { + t, err := placement.NewTraverser(e.placementOpts...) + if err != nil { + return false, err + } + for { + nodes := t.Next() + if len(nodes) == 0 { + break + } + for _, node := range nodes { + if e.cfg.netmapKeys.IsLocalKey(node.PublicKey()) { + return true, nil + } + } + } + return false, nil +} + +func (e *ecWriter) relayToContainerNode(ctx context.Context) error { + t, err := placement.NewTraverser(e.placementOpts...) + if err != nil { + return err + } + var lastErr error + for { + nodes := t.Next() + if len(nodes) == 0 { + break + } + for _, node := range nodes { + var info client.NodeInfo + client.NodeInfoFromNetmapElement(&info, node) + + c, err := e.cfg.clientConstructor.Get(info) + if err != nil { + return fmt.Errorf("could not create SDK client %s: %w", info.AddressGroup(), err) + } + + completed := make(chan interface{}) + if poolErr := e.cfg.remotePool.Submit(func() { + defer close(completed) + err = e.relay(ctx, info, c) + }); poolErr != nil { + close(completed) + svcutil.LogWorkerPoolError(e.cfg.log, "PUT", poolErr) + return poolErr + } + <-completed + + if err == nil { + return nil + } + e.cfg.log.Logger.Warn(logs.ECFailedToSendToContainerNode, zap.Stringers("address_group", info.AddressGroup())) + lastErr = err + } + } + if lastErr == nil { + return nil + } + return errIncompletePut{ + singleErr: lastErr, + } +} + +func (e *ecWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error { + t, err := placement.NewTraverser(e.placementOpts...) + if err != nil { + return err + } + + eg, egCtx := errgroup.WithContext(ctx) + for { + nodes := t.Next() + if len(nodes) == 0 { + break + } + + eg.Go(func() error { + return e.writePart(egCtx, obj, int(obj.ECHeader().Index()), nodes) + }) + } + if err := eg.Wait(); err != nil { + return errIncompletePut{ + singleErr: err, + } + } + return nil +} + +func (e *ecWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) error { + // now only single EC policy is supported + c, err := erasurecode.NewConstructor(policy.ECDataCount(e.container.PlacementPolicy()), policy.ECParityCount(e.container.PlacementPolicy())) + if err != nil { + return err + } + parts, err := c.Split(obj, e.key) + if err != nil { + return err + } + t, err := placement.NewTraverser(e.placementOpts...) + if err != nil { + return err + } + + eg, egCtx := errgroup.WithContext(ctx) + for { + nodes := t.Next() + if len(nodes) == 0 { + break + } + + for idx := range parts { + idx := idx + eg.Go(func() error { + return e.writePart(egCtx, parts[idx], idx, nodes) + }) + } + } + if err := eg.Wait(); err != nil { + return errIncompletePut{ + singleErr: err, + } + } + return nil +} + +func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx int, nodes []placement.Node) error { + var err error + node := nodes[partIdx%len(nodes)] + if e.cfg.netmapKeys.IsLocalKey(node.PublicKey()) { + err = e.writePartLocal(ctx, obj) + } else { + err = e.writePartRemote(ctx, obj, node) + } + if err == nil { + return nil + } + e.cfg.log.Warn(logs.ECFailedToSaveECPart, zap.Stringer("parent_object", object.AddressOf(obj)), zap.Error(err)) + return err +} + +func (e *ecWriter) writePartLocal(ctx context.Context, obj *objectSDK.Object) error { + var err error + localTarget := localTarget{ + storage: e.cfg.localStore, + } + completed := make(chan interface{}) + if poolErr := e.cfg.localPool.Submit(func() { + defer close(completed) + err = localTarget.WriteObject(ctx, obj, e.objMeta) + }); poolErr != nil { + close(completed) + return poolErr + } + <-completed + return err +} + +func (e *ecWriter) writePartRemote(ctx context.Context, obj *objectSDK.Object, node placement.Node) error { + var clientNodeInfo client.NodeInfo + client.NodeInfoFromNetmapElement(&clientNodeInfo, node) + + remoteTaget := remoteTarget{ + privateKey: e.key, + clientConstructor: e.cfg.clientConstructor, + commonPrm: e.commonPrm, + nodeInfo: clientNodeInfo, + } + + var err error + completed := make(chan interface{}) + if poolErr := e.cfg.remotePool.Submit(func() { + defer close(completed) + err = remoteTaget.WriteObject(ctx, obj, e.objMeta) + }); poolErr != nil { + close(completed) + return poolErr + } + <-completed + return err +} diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 09e1eb092a..43b3b0ac1a 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -16,6 +16,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" @@ -25,6 +26,7 @@ import ( tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/tzhash/tz" "go.opentelemetry.io/otel/attribute" @@ -32,7 +34,10 @@ import ( "go.uber.org/zap" ) -var errInvalidPayloadChecksum = errors.New("incorrect payload checksum") +var ( + errInvalidPayloadChecksum = errors.New("incorrect payload checksum") + errInvalidECObject = errors.New("object must be splitted to EC parts") +) type putSingleRequestSigner struct { req *objectAPI.PutSingleRequest @@ -148,12 +153,20 @@ func (s *Service) validatePutSingleObject(ctx context.Context, obj *objectSDK.Ob func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *objectAPI.PutSingleRequest, meta object.ContentMeta) error { localOnly := req.GetMetaHeader().GetTTL() <= 1 - placementOptions, err := s.getPutSinglePlacementOptions(obj, req.GetBody().GetCopiesNumber(), localOnly) + placement, err := s.getPutSinglePlacementOptions(obj, req.GetBody().GetCopiesNumber(), localOnly) if err != nil { return err } - iter := s.cfg.newNodeIterator(placementOptions) + if placement.isEC { + return s.saveToECReplicas(ctx, placement, obj, req, meta) + } + + return s.saveToREPReplicas(ctx, placement, obj, localOnly, req, meta) +} + +func (s *Service) saveToREPReplicas(ctx context.Context, placement putSinglePlacement, obj *objectSDK.Object, localOnly bool, req *objectAPI.PutSingleRequest, meta object.ContentMeta) error { + iter := s.cfg.newNodeIterator(placement.placementOptions) iter.extraBroadcastEnabled = needAdditionalBroadcast(obj, localOnly) signer := &putSingleRequestSigner{ @@ -167,38 +180,83 @@ func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *o }) } -func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumber []uint32, localOnly bool) ([]placement.Option, error) { - var result []placement.Option - if len(copiesNumber) > 0 { - result = append(result, placement.WithCopyNumbers(copiesNumber)) +func (s *Service) saveToECReplicas(ctx context.Context, placement putSinglePlacement, obj *objectSDK.Object, req *objectAPI.PutSingleRequest, meta object.ContentMeta) error { + if obj.Type() == objectSDK.TypeRegular && obj.ECHeader() == nil { + return errInvalidECObject } + commonPrm, err := svcutil.CommonPrmFromV2(req) + if err != nil { + return err + } + key, err := s.cfg.keyStorage.GetKey(nil) + if err != nil { + return err + } + signer := &putSingleRequestSigner{ + req: req, + keyStorage: s.keyStorage, + signer: &sync.Once{}, + } + + w := ecWriter{ + cfg: s.cfg, + placementOpts: placement.placementOptions, + objMeta: meta, + objMetaValid: true, + commonPrm: commonPrm, + container: placement.container, + key: key, + relay: func(ctx context.Context, ni client.NodeInfo, mac client.MultiAddressClient) error { + return s.redirectPutSingleRequest(ctx, signer, obj, ni, mac) + }, + } + return w.WriteObject(ctx, obj) +} + +type putSinglePlacement struct { + placementOptions []placement.Option + isEC bool + container containerSDK.Container +} + +func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumber []uint32, localOnly bool) (putSinglePlacement, error) { + var result putSinglePlacement + cnrID, ok := obj.ContainerID() if !ok { - return nil, errors.New("missing container ID") + return result, errors.New("missing container ID") } cnrInfo, err := s.cnrSrc.Get(cnrID) if err != nil { - return nil, fmt.Errorf("could not get container by ID: %w", err) + return result, fmt.Errorf("could not get container by ID: %w", err) } - result = append(result, placement.ForContainer(cnrInfo.Value)) + result.container = cnrInfo.Value + result.isEC = container.IsECContainer(cnrInfo.Value) && object.IsECSupported(obj) + if len(copiesNumber) > 0 && !result.isEC { + result.placementOptions = append(result.placementOptions, placement.WithCopyNumbers(copiesNumber)) + } + result.placementOptions = append(result.placementOptions, placement.ForContainer(cnrInfo.Value)) objID, ok := obj.ID() if !ok { - return nil, errors.New("missing object ID") + return result, errors.New("missing object ID") } - result = append(result, placement.ForObject(objID)) + if obj.ECHeader() != nil { + objID = obj.ECHeader().Parent() + } + result.placementOptions = append(result.placementOptions, placement.ForObject(objID)) latestNetmap, err := netmap.GetLatestNetworkMap(s.netMapSrc) if err != nil { - return nil, fmt.Errorf("could not get latest network map: %w", err) + return result, fmt.Errorf("could not get latest network map: %w", err) } builder := placement.NewNetworkMapBuilder(latestNetmap) if localOnly { - result = append(result, placement.SuccessAfter(1)) + result.placementOptions = append(result.placementOptions, placement.SuccessAfter(1)) builder = svcutil.NewLocalPlacement(builder, s.netmapKeys) } - result = append(result, placement.UseBuilder(builder)) + result.placementOptions = append(result.placementOptions, placement.UseBuilder(builder)) return result, nil } diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index f32b2ab992..14dae38d58 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -7,7 +7,9 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" pkgutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" @@ -19,7 +21,7 @@ import ( type Streamer struct { *cfg - sessionKey *ecdsa.PrivateKey + privateKey *ecdsa.PrivateKey target transformer.ChunkedObjectWriter @@ -76,6 +78,12 @@ func (p *Streamer) initTarget(prm *PutInitPrm) error { func (p *Streamer) initUntrustedTarget(prm *PutInitPrm) error { p.relay = prm.relay + nodeKey, err := p.cfg.keyStorage.GetKey(nil) + if err != nil { + return err + } + p.privateKey = nodeKey + // prepare untrusted-Put object target p.target = &validatingPreparedTarget{ nextTarget: newInMemoryObjectBuilder(p.newObjectWriter(prm)), @@ -102,7 +110,7 @@ func (p *Streamer) initTrustedTarget(prm *PutInitPrm) error { } } - sessionKey, err := p.keyStorage.GetKey(sessionInfo) + key, err := p.keyStorage.GetKey(sessionInfo) if err != nil { return fmt.Errorf("(%T) could not receive session key: %w", p, err) } @@ -116,7 +124,7 @@ func (p *Streamer) initTrustedTarget(prm *PutInitPrm) error { if sToken == nil { var ownerSession user.ID - user.IDFromKey(&ownerSession, sessionKey.PublicKey) + user.IDFromKey(&ownerSession, key.PublicKey) if !ownerObj.Equals(ownerSession) { return fmt.Errorf("(%T) session token is missing but object owner id is different from the default key", p) @@ -127,11 +135,11 @@ func (p *Streamer) initTrustedTarget(prm *PutInitPrm) error { } } - p.sessionKey = sessionKey + p.privateKey = key p.target = &validatingTarget{ fmt: p.fmtValidator, nextTarget: transformer.NewPayloadSizeLimiter(transformer.Params{ - Key: sessionKey, + Key: key, NextTargetInit: func() transformer.ObjectWriter { return p.newObjectWriter(prm) }, NetworkState: p.networkState, MaxSize: p.maxPayloadSz, @@ -171,7 +179,12 @@ func (p *Streamer) preparePrm(prm *PutInitPrm) error { placement.ForContainer(prm.cnr), ) - if id, ok := prm.hdr.ID(); ok { + if ech := prm.hdr.ECHeader(); ech != nil { + prm.traverseOpts = append(prm.traverseOpts, + // set identifier of the processing object + placement.ForObject(ech.Parent()), + ) + } else if id, ok := prm.hdr.ID(); ok { prm.traverseOpts = append(prm.traverseOpts, // set identifier of the processing object placement.ForObject(id), @@ -196,6 +209,13 @@ func (p *Streamer) preparePrm(prm *PutInitPrm) error { } func (p *Streamer) newObjectWriter(prm *PutInitPrm) transformer.ObjectWriter { + if container.IsECContainer(prm.cnr) && object.IsECSupported(prm.hdr) { + return p.newECWriter(prm) + } + return p.newDefaultObjectWriter(prm) +} + +func (p *Streamer) newDefaultObjectWriter(prm *PutInitPrm) transformer.ObjectWriter { var relay func(context.Context, nodeDesc) error if p.relay != nil { relay = func(ctx context.Context, node nodeDesc) error { @@ -223,7 +243,7 @@ func (p *Streamer) newObjectWriter(prm *PutInitPrm) transformer.ObjectWriter { } rt := &remoteTarget{ - privateKey: p.sessionKey, + privateKey: p.privateKey, commonPrm: prm.common, clientConstructor: p.clientConstructor, } @@ -236,6 +256,20 @@ func (p *Streamer) newObjectWriter(prm *PutInitPrm) transformer.ObjectWriter { } } +func (p *Streamer) newECWriter(prm *PutInitPrm) transformer.ObjectWriter { + return &objectWriterDispatcher{ + ecWriter: &ecWriter{ + cfg: p.cfg, + placementOpts: append(prm.traverseOpts, placement.WithCopyNumbers(nil)), // copies number ignored for EC + container: prm.cnr, + key: p.privateKey, + commonPrm: prm.common, + relay: p.relay, + }, + repWriter: p.newDefaultObjectWriter(prm), + } +} + func (p *Streamer) SendChunk(ctx context.Context, prm *PutChunkPrm) error { if p.target == nil { return errNotInit diff --git a/pkg/services/object/put/writer.go b/pkg/services/object/put/writer.go new file mode 100644 index 0000000000..53eee6006a --- /dev/null +++ b/pkg/services/object/put/writer.go @@ -0,0 +1,23 @@ +package putsvc + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" +) + +var _ transformer.ObjectWriter = (*objectWriterDispatcher)(nil) + +type objectWriterDispatcher struct { + ecWriter transformer.ObjectWriter + repWriter transformer.ObjectWriter +} + +func (m *objectWriterDispatcher) WriteObject(ctx context.Context, obj *objectSDK.Object) error { + if object.IsECSupported(obj) { + return m.ecWriter.WriteObject(ctx, obj) + } + return m.repWriter.WriteObject(ctx, obj) +} diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index a699b44540..3061695718 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -137,7 +137,7 @@ func defaultCopiesVector(policy netmap.PlacementPolicy) []int { copyVector := make([]int, 0, replNum) for i := 0; i < replNum; i++ { - copyVector = append(copyVector, int(policy.ReplicaDescriptor(i).NumberOfObjects())) + copyVector = append(copyVector, int(policy.ReplicaDescriptor(i).NumberOfObjects()+policy.ReplicaDescriptor(i).GetECDataCount()+policy.ReplicaDescriptor(i).GetECParityCount())) } return copyVector From 8668cbf147759c57c96a015174a51790a2982d1b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 28 Mar 2024 13:47:36 +0300 Subject: [PATCH 0479/1413] [#1064] dev: Add `IR + 4 storage nodes` configuration Signed-off-by: Dmitrii Stepanov --- Makefile | 12 +- dev/.vscode-example/launch.json | 197 +++++++++++++++++++-- dev/storage/{wallet.json => wallet01.json} | 0 dev/storage/wallet02.json | 30 ++++ dev/storage/wallet03.json | 30 ++++ dev/storage/wallet04.json | 30 ++++ 6 files changed, 278 insertions(+), 21 deletions(-) rename dev/storage/{wallet.json => wallet01.json} (100%) create mode 100644 dev/storage/wallet02.json create mode 100644 dev/storage/wallet03.json create mode 100644 dev/storage/wallet04.json diff --git a/Makefile b/Makefile index 20c84d0416..fbf93facd0 100755 --- a/Makefile +++ b/Makefile @@ -276,15 +276,19 @@ env-up: all echo "Frostfs contracts not found"; exit 1; \ fi ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph init --contracts ${FROSTFS_CONTRACTS_PATH} - ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet.json --gas 10.0 + ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet01.json --gas 10.0 + ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet02.json --gas 10.0 + ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet03.json --gas 10.0 + ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet04.json --gas 10.0 @if [ ! -f "$(LOCODE_DB_PATH)" ]; then \ make locode-download; \ fi + mkdir -p ./$(TMP_DIR)/state + mkdir -p ./$(TMP_DIR)/storage # Shutdown dev environment env-down: docker compose -f dev/docker-compose.yml down docker volume rm -f frostfs-node_neo-go - rm -f ./.cache/.frostfs-ir-state - rm -f ./.cache/.frostfs-node-state - rm -rf ./.cache/storage + rm -rf ./$(TMP_DIR)/state + rm -rf ./$(TMP_DIR)/storage diff --git a/dev/.vscode-example/launch.json b/dev/.vscode-example/launch.json index 459350145a..6aedde85ec 100644 --- a/dev/.vscode-example/launch.json +++ b/dev/.vscode-example/launch.json @@ -27,12 +27,12 @@ "FROSTFS_IR_NETMAP_CLEANER_THRESHOLD":"3", "FROSTFS_IR_LOCODE_DB_PATH":"${workspaceFolder}/.cache/locode_db", "FROSTFS_IR_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8090", - "FROSTFS_IR_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/.frostfs-ir-state" + "FROSTFS_IR_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/state/.frostfs-ir-state" }, "postDebugTask": "env-down" }, { - "name": "Storage node", + "name": "Storage node 1", "type": "go", "request": "launch", "mode": "debug", @@ -42,7 +42,8 @@ "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", - "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet.json", + "FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s", + "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet01.json", "FROSTFS_NODE_WALLET_PASSWORD":"", "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8080", "FROSTFS_GRPC_0_ENDPOINT":"127.0.0.1:8080", @@ -50,31 +51,187 @@ "FROSTFS_CONTROL_AUTHORIZED_KEYS":"031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a", "FROSTFS_NODE_ATTRIBUTE_0":"User-Agent:FrostFS/dev", "FROSTFS_NODE_ATTRIBUTE_1":"UN-LOCODE:RU MOW", - "FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/.frostfs-node-state", + "FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/state/.frostfs-node-s1-state", "FROSTFS_TREE_ENABLED":"true", "FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME":"10", "FROSTFS_STORAGE_SHARD_0_WRITECACHE_ENABLED":"true", - "FROSTFS_STORAGE_SHARD_0_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/wc0", - "FROSTFS_STORAGE_SHARD_0_METABASE_PATH":"${workspaceFolder}/.cache/storage/meta0", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/s1/wc0", + "FROSTFS_STORAGE_SHARD_0_METABASE_PATH":"${workspaceFolder}/.cache/storage/s1/meta0", "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_TYPE":"blobovnicza", - "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/blobovnicza0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/s1/blobovnicza0", "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH":"2", "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH":"4", "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE":"fstree", - "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/fstree0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/s1/fstree0", "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_DEPTH":"2", - "FROSTFS_STORAGE_SHARD_0_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/pilorama0", + "FROSTFS_STORAGE_SHARD_0_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s1/pilorama0", "FROSTFS_STORAGE_SHARD_1_WRITECACHE_ENABLED":"true", - "FROSTFS_STORAGE_SHARD_1_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/wc1", - "FROSTFS_STORAGE_SHARD_1_METABASE_PATH":"${workspaceFolder}/.cache/storage/meta1", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/s1/wc1", + "FROSTFS_STORAGE_SHARD_1_METABASE_PATH":"${workspaceFolder}/.cache/storage/s1/meta1", "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_TYPE":"blobovnicza", - "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/blobovnicza1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/s1/blobovnicza1", "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH":"2", "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH":"4", "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE":"fstree", - "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/fstree1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/s1/fstree1", "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_DEPTH":"2", - "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/pilorama1" + "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s1/pilorama1", + "FROSTFS_PROMETHEUS_ENABLED":"true", + "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9090", + "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" + }, + "postDebugTask": "env-down" + }, + { + "name": "Storage node 2", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "cmd/frostfs-node", + "env": { + "FROSTFS_LOGGER_LEVEL":"debug", + "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", + "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", + "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", + "FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s", + "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet02.json", + "FROSTFS_NODE_WALLET_PASSWORD":"", + "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8082", + "FROSTFS_GRPC_0_ENDPOINT":"127.0.0.1:8082", + "FROSTFS_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8083", + "FROSTFS_CONTROL_AUTHORIZED_KEYS":"031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a", + "FROSTFS_NODE_ATTRIBUTE_0":"User-Agent:FrostFS/dev", + "FROSTFS_NODE_ATTRIBUTE_1":"UN-LOCODE:RU MOW", + "FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/state/.frostfs-node-s2-state", + "FROSTFS_TREE_ENABLED":"true", + "FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME":"10", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_ENABLED":"true", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/s2/wc0", + "FROSTFS_STORAGE_SHARD_0_METABASE_PATH":"${workspaceFolder}/.cache/storage/s2/meta0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_TYPE":"blobovnicza", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/s2/blobovnicza0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH":"4", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE":"fstree", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/s2/fstree0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_0_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s2/pilorama0", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_ENABLED":"true", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/s2/wc1", + "FROSTFS_STORAGE_SHARD_1_METABASE_PATH":"${workspaceFolder}/.cache/storage/s2/meta1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_TYPE":"blobovnicza", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/s2/blobovnicza1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH":"4", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE":"fstree", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/s2/fstree1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s2/pilorama1", + "FROSTFS_PROMETHEUS_ENABLED":"true", + "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9091", + "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" + }, + "postDebugTask": "env-down" + }, + { + "name": "Storage node 3", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "cmd/frostfs-node", + "env": { + "FROSTFS_LOGGER_LEVEL":"debug", + "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", + "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", + "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", + "FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s", + "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet03.json", + "FROSTFS_NODE_WALLET_PASSWORD":"", + "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8084", + "FROSTFS_GRPC_0_ENDPOINT":"127.0.0.1:8084", + "FROSTFS_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8085", + "FROSTFS_CONTROL_AUTHORIZED_KEYS":"031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a", + "FROSTFS_NODE_ATTRIBUTE_0":"User-Agent:FrostFS/dev", + "FROSTFS_NODE_ATTRIBUTE_1":"UN-LOCODE:RU MOW", + "FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/state/.frostfs-node-s3-state", + "FROSTFS_TREE_ENABLED":"true", + "FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME":"10", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_ENABLED":"true", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/s3/wc0", + "FROSTFS_STORAGE_SHARD_0_METABASE_PATH":"${workspaceFolder}/.cache/storage/s3/meta0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_TYPE":"blobovnicza", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/s3/blobovnicza0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH":"4", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE":"fstree", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/s3/fstree0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_0_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s3/pilorama0", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_ENABLED":"true", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/s3/wc1", + "FROSTFS_STORAGE_SHARD_1_METABASE_PATH":"${workspaceFolder}/.cache/storage/s3/meta1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_TYPE":"blobovnicza", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/s3/blobovnicza1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH":"4", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE":"fstree", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/s3/fstree1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s3/pilorama1", + "FROSTFS_PROMETHEUS_ENABLED":"true", + "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9092", + "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" + }, + "postDebugTask": "env-down" + }, + { + "name": "Storage node 4", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "cmd/frostfs-node", + "env": { + "FROSTFS_LOGGER_LEVEL":"debug", + "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", + "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", + "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", + "FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s", + "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet04.json", + "FROSTFS_NODE_WALLET_PASSWORD":"", + "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8086", + "FROSTFS_GRPC_0_ENDPOINT":"127.0.0.1:8086", + "FROSTFS_CONTROL_GRPC_ENDPOINT":"127.0.0.1:8087", + "FROSTFS_CONTROL_AUTHORIZED_KEYS":"031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a", + "FROSTFS_NODE_ATTRIBUTE_0":"User-Agent:FrostFS/dev", + "FROSTFS_NODE_ATTRIBUTE_1":"UN-LOCODE:RU MOW", + "FROSTFS_NODE_PERSISTENT_STATE_PATH":"${workspaceFolder}/.cache/state/.frostfs-node-s4-state", + "FROSTFS_TREE_ENABLED":"true", + "FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME":"10", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_ENABLED":"true", + "FROSTFS_STORAGE_SHARD_0_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/s4/wc0", + "FROSTFS_STORAGE_SHARD_0_METABASE_PATH":"${workspaceFolder}/.cache/storage/s4/meta0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_TYPE":"blobovnicza", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/s4/blobovnicza0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH":"4", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE":"fstree", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/s4/fstree0", + "FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_0_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s4/pilorama0", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_ENABLED":"true", + "FROSTFS_STORAGE_SHARD_1_WRITECACHE_PATH":"${workspaceFolder}/.cache/storage/s4/wc1", + "FROSTFS_STORAGE_SHARD_1_METABASE_PATH":"${workspaceFolder}/.cache/storage/s4/meta1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_TYPE":"blobovnicza", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_PATH":"${workspaceFolder}/.cache/storage/s4/blobovnicza1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH":"4", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE":"fstree", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_PATH":"${workspaceFolder}/.cache/storage/s4/fstree1", + "FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_DEPTH":"2", + "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s4/pilorama1", + "FROSTFS_PROMETHEUS_ENABLED":"true", + "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9093", + "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" }, "postDebugTask": "env-down" } @@ -82,9 +239,15 @@ "compounds": [ { "name": "IR+Storage node", - "configurations": ["IR", "Storage node"], + "configurations": ["IR", "Storage node 1"], "preLaunchTask": "env-up", "stopAll": true - } + }, + { + "name": "IR + 4 storage nodes", + "configurations": ["IR", "Storage node 1", "Storage node 2", "Storage node 3", "Storage node 4"], + "preLaunchTask": "env-up", + "stopAll": true + } ] -} +} \ No newline at end of file diff --git a/dev/storage/wallet.json b/dev/storage/wallet01.json similarity index 100% rename from dev/storage/wallet.json rename to dev/storage/wallet01.json diff --git a/dev/storage/wallet02.json b/dev/storage/wallet02.json new file mode 100644 index 0000000000..9c073deef0 --- /dev/null +++ b/dev/storage/wallet02.json @@ -0,0 +1,30 @@ +{ + "version":"3.0", + "accounts":[ + { + "address":"NVXXy3hNTvwVEZa2dAibALyJB3Q86aiHvL", + "key":"6PYXd9hxMYfaCkgeZp3q1RoMB921RQFkRxYftcacTJ2S7MUwnivrxi6Yk5", + "label":"", + "contract":{ + "script":"DCED/2W2rnkTSk3OnQ0504Uem6tO6Xq/hugeHFu8UM0oJq5BVuezJw==", + "parameters":[ + { + "name":"parameter0", + "type":"Signature" + } + ], + "deployed":false + }, + "lock":false, + "isDefault":false + } + ], + "scrypt":{ + "n":16384, + "r":8, + "p":8 + }, + "extra":{ + "Tokens":null + } + } diff --git a/dev/storage/wallet03.json b/dev/storage/wallet03.json new file mode 100644 index 0000000000..c054a3160a --- /dev/null +++ b/dev/storage/wallet03.json @@ -0,0 +1,30 @@ +{ + "version":"3.0", + "accounts":[ + { + "address":"NPTmih9X14Y7xLvmD6RVtDHdH1Y9qJwoTe", + "key":"6PYXNeQzge9fWztVnWYRbr5Mh9q1y4npKVARHYGb484Hct1iNd3vXGR1kk", + "label":"", + "contract":{ + "script":"DCECrJIM198LYbKJBy5rlG4tpOGjG5qxxiG7R14w+kqxAsNBVuezJw==", + "parameters":[ + { + "name":"parameter0", + "type":"Signature" + } + ], + "deployed":false + }, + "lock":false, + "isDefault":false + } + ], + "scrypt":{ + "n":16384, + "r":8, + "p":8 + }, + "extra":{ + "Tokens":null + } + } diff --git a/dev/storage/wallet04.json b/dev/storage/wallet04.json new file mode 100644 index 0000000000..cb4676df69 --- /dev/null +++ b/dev/storage/wallet04.json @@ -0,0 +1,30 @@ +{ + "version":"3.0", + "accounts":[ + { + "address":"Ne2DAQbWvP1s7TbtFc7BStKMnjKJdBaVRm", + "key":"6PYWCsGWx8uSVYK94tvK7Ccit8x8Z3f3dHADTFTgLhT9NBXTBqBECL8AyC", + "label":"", + "contract":{ + "script":"DCEDjIYpWeVrQ+IPeRh8T+ngvHyMZsFgPmzw7H+Hq2sI3DVBVuezJw==", + "parameters":[ + { + "name":"parameter0", + "type":"Signature" + } + ], + "deployed":false + }, + "lock":false, + "isDefault":false + } + ], + "scrypt":{ + "n":16384, + "r":8, + "p":8 + }, + "extra":{ + "Tokens":null + } + } From bdf49909041342266bf2fa6ef548abfcf85652b6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 28 Mar 2024 17:27:22 +0300 Subject: [PATCH 0480/1413] [#1064] cli: Add EC header output to object head Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/head.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cmd/frostfs-cli/modules/object/head.go b/cmd/frostfs-cli/modules/object/head.go index db466e5888..f97ef952df 100644 --- a/cmd/frostfs-cli/modules/object/head.go +++ b/cmd/frostfs-cli/modules/object/head.go @@ -171,6 +171,15 @@ func printHeader(cmd *cobra.Command, obj *objectSDK.Object) error { cmd.Printf(" signature: %s\n", hex.EncodeToString(sigV2.GetSign())) } + if ecHeader := obj.ECHeader(); ecHeader != nil { + cmd.Print("EC header:\n") + + cmd.Printf(" parent object ID: %s\n", ecHeader.Parent().EncodeToString()) + cmd.Printf(" index: %d\n", ecHeader.Index()) + cmd.Printf(" total: %d\n", ecHeader.Total()) + cmd.Printf(" header length: %d\n", ecHeader.HeaderLength()) + } + return printSplitHeader(cmd, obj) } From f5b67c67353cf20d8ab0d0f8dd5fdcca40d363c2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 28 Mar 2024 17:29:30 +0300 Subject: [PATCH 0481/1413] [#1064] policer: Disable EC processing Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/check.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index d2297fed70..d68d99d181 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + policycore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -40,6 +41,10 @@ func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.Add } policy := cnr.Value.PlacementPolicy() + if policycore.IsECPlacement(policy) { + // EC not supported yet by policer + return nil + } nn, err := p.placementBuilder.BuildPlacement(idCnr, &idObj, policy) if err != nil { From 2b8836184971997e24d4c1fa5e9af1b5f0db2740 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 9 Apr 2024 11:53:18 +0300 Subject: [PATCH 0482/1413] [#1062] object: Fix buffer allocation for `PayloadRange` Signed-off-by: Anton Nikiforov --- pkg/services/object/internal/client/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index dd2de0fd1e..4634c96e17 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -348,7 +348,7 @@ func PayloadRange(ctx context.Context, prm PayloadRangePrm) (*PayloadRangeRes, e ln = maxInitialBufferSize } - w := bytes.NewBuffer(make([]byte, ln)) + w := bytes.NewBuffer(make([]byte, 0, ln)) _, err = io.CopyN(w, rdr, int64(prm.ln)) if err != nil { return nil, fmt.Errorf("read payload: %w", err) From 5b8200de8800b1f239e63b0cf004428a19fb3339 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 4 Mar 2024 11:58:36 +0300 Subject: [PATCH 0483/1413] [#984] blobovnicza: Do not fail rebuild on big objects If blobovnicza contains objects larger than object size parameter value, then rebuild fails with an error, because there is no such bucket in database. This commit forces to create bucket on rebuild. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobovnicza/put.go | 17 ++++- .../blobstor/blobovniczatree/rebuild.go | 1 + .../blobstor/blobovniczatree/rebuild_test.go | 67 +++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go index d15b6e2b25..9af8a93fe3 100644 --- a/pkg/local_object_storage/blobovnicza/put.go +++ b/pkg/local_object_storage/blobovnicza/put.go @@ -17,6 +17,8 @@ type PutPrm struct { addr oid.Address objData []byte + + force bool } // PutRes groups the resulting values of Put operation. @@ -32,6 +34,11 @@ func (p *PutPrm) SetMarshaledObject(data []byte) { p.objData = data } +// SetForce sets force option. +func (p *PutPrm) SetForce(f bool) { + p.force = f +} + // Put saves an object in Blobovnicza. // // If binary representation of the object is not set, @@ -66,7 +73,15 @@ func (b *Blobovnicza) Put(ctx context.Context, prm PutPrm) (PutRes, error) { // expected to happen: // - before initialization step (incorrect usage by design) // - if DB is corrupted (in future this case should be handled) - return logicerr.Wrap(fmt.Errorf("(%T) bucket for size %d not created", b, sz)) + // - blobovnicza's object size changed before rebuild (handled if prm.force flag specified) + if !prm.force { + return logicerr.Wrap(fmt.Errorf("(%T) bucket for size %d not created", b, sz)) + } + var err error + buck, err = tx.CreateBucket(bucketName) + if err != nil { + return fmt.Errorf("(%T) failed to create bucket for size %d: %w", b, sz, err) + } } // save the object in bucket diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 2302661d57..93ef8ba2ea 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -402,6 +402,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, var putPrm blobovnicza.PutPrm putPrm.SetAddress(i.Address) putPrm.SetMarshaledObject(i.ObjectData) + putPrm.SetForce(true) _, err = target.Blobovnicza().Put(ctx, putPrm) if err != nil { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 0ac50f36a3..578cb1a7ff 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -38,6 +38,73 @@ func TestBlobovniczaTreeRebuild(t *testing.T) { }) } +func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + b := NewBlobovniczaTree( + WithLogger(test.NewLogger(t)), + WithObjectSizeLimit(64*1024), // 64KB object size limit + WithBlobovniczaShallowWidth(5), + WithBlobovniczaShallowDepth(2), // depth = 2 + WithRootPath(dir), + WithBlobovniczaSize(100*1024), + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) + require.NoError(t, b.Open(false)) + require.NoError(t, b.Init()) + + obj := blobstortest.NewObject(64 * 1024) // 64KB object + data, err := obj.Marshal() + require.NoError(t, err) + var prm common.PutPrm + prm.Address = object.AddressOf(obj) + prm.RawData = data + res, err := b.Put(context.Background(), prm) + require.NoError(t, err) + + storageIDs := make(map[oid.Address][]byte) + storageIDs[prm.Address] = res.StorageID + + require.NoError(t, b.Close()) + + b = NewBlobovniczaTree( + WithLogger(test.NewLogger(t)), + WithObjectSizeLimit(32*1024), // 32KB object size limit + WithBlobovniczaShallowWidth(5), + WithBlobovniczaShallowDepth(3), // depth = 3 + WithRootPath(dir), + WithBlobovniczaSize(100*1024), + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) + require.NoError(t, b.Open(false)) + require.NoError(t, b.Init()) + + metaStub := &storageIDUpdateStub{ + storageIDs: storageIDs, + guard: &sync.Mutex{}, + } + var rPrm common.RebuildPrm + rPrm.MetaStorage = metaStub + rPrm.WorkerLimiter = &rebuildLimiterStub{} + rRes, err := b.Rebuild(context.Background(), rPrm) + require.NoError(t, err) + dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 + require.True(t, dataMigrated) + + for addr, storageID := range storageIDs { + var gPrm common.GetPrm + gPrm.Address = addr + gPrm.StorageID = storageID + _, err := b.Get(context.Background(), gPrm) + require.NoError(t, err) + } + + require.NoError(t, b.Close()) +} + func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, targetDepth, targetWidth uint64, shouldMigrate bool) { dir := t.TempDir() b := NewBlobovniczaTree( From 338d8cbebd235a437250c9c4113fddc74bf9c474 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 4 Apr 2024 14:55:38 +0300 Subject: [PATCH 0484/1413] [#1080] ape: Do not read object headers before Head/Get Signed-off-by: Dmitrii Stepanov --- pkg/services/object/ape/checker.go | 3 +++ pkg/services/object/ape/request.go | 2 +- pkg/services/object/ape/service.go | 34 ++++++++++++++++-------------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 45efce5a7e..119df5fc01 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -54,6 +54,9 @@ type Prm struct { // If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow. SoftAPECheck bool + + // If true, object headers will not retrieved from storage engine. + WithoutHeaderRequest bool } var errMissingOID = errors.New("object ID is not set") diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 3689bd1785..bdce976763 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -141,7 +141,7 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (*request, err var header *objectV2.Header if prm.Header != nil { header = prm.Header - } else if prm.Object != nil { + } else if prm.Object != nil && !prm.WithoutHeaderRequest { headerObjSDK, err := c.headerProvider.GetHeader(ctx, prm.Container, *prm.Object) if err == nil { header = headerObjSDK.ToV2().GetHeader() diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 0c203209df..95f36be79a 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -125,14 +125,15 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodGetObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodGetObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, + WithoutHeaderRequest: true, }) if err != nil { return toStatusErr(err) @@ -211,14 +212,15 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodHeadObject, + Role: nativeSchemaRole(reqCtx.Role), + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + SoftAPECheck: reqCtx.SoftAPECheck, + WithoutHeaderRequest: true, }) if err != nil { return nil, toStatusErr(err) From e74bdaa5d5999774b5d55f006374d228ca3dd161 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 4 Apr 2024 15:42:52 +0300 Subject: [PATCH 0485/1413] [#1080] ape: Use value for APE request Signed-off-by: Dmitrii Stepanov --- pkg/services/object/ape/request.go | 28 +++++++++++++------------ pkg/services/object/ape/request_test.go | 4 ++-- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index bdce976763..b81fe8c323 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -17,36 +17,38 @@ import ( type request struct { operation string - resource *resource + resource resource properties map[string]string } -var _ aperesource.Request = (*request)(nil) +var defaultRequest = request{} + +var _ aperesource.Request = request{} type resource struct { name string properties map[string]string } -var _ aperesource.Resource = (*resource)(nil) +var _ aperesource.Resource = resource{} -func (r *resource) Name() string { +func (r resource) Name() string { return r.name } -func (r *resource) Property(key string) string { +func (r resource) Property(key string) string { return r.properties[key] } -func (r *request) Operation() string { +func (r request) Operation() string { return r.operation } -func (r *request) Property(key string) string { +func (r request) Property(key string) string { return r.properties[key] } -func (r *request) Resource() aperesource.Resource { +func (r request) Resource() aperesource.Resource { return r.resource } @@ -123,7 +125,7 @@ func objectProperties(cnr cid.ID, oid *oid.ID, cnrOwner user.ID, header *objectV // newAPERequest creates an APE request to be passed to a chain router. It collects resource properties from // header provided by headerProvider. If it cannot be found in headerProvider, then properties are // initialized from header given in prm (if it is set). Otherwise, just CID and OID are set to properties. -func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (*request, error) { +func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (request, error) { switch prm.Method { case nativeschema.MethodGetObject, nativeschema.MethodHeadObject, @@ -131,11 +133,11 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (*request, err nativeschema.MethodHashObject, nativeschema.MethodDeleteObject: if prm.Object == nil { - return nil, fmt.Errorf("method %s: %w", prm.Method, errMissingOID) + return defaultRequest, fmt.Errorf("method %s: %w", prm.Method, errMissingOID) } case nativeschema.MethodSearchObject, nativeschema.MethodPutObject: default: - return nil, fmt.Errorf("unknown method: %s", prm.Method) + return defaultRequest, fmt.Errorf("unknown method: %s", prm.Method) } var header *objectV2.Header @@ -148,9 +150,9 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (*request, err } } - return &request{ + return request{ operation: prm.Method, - resource: &resource{ + resource: resource{ name: resourceName(prm.Container, prm.Object, prm.Namespace), properties: objectProperties(prm.Container, prm.Object, prm.ContainerOwner, header), }, diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index c5b43fa8b7..71e234e78b 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -258,7 +258,7 @@ func TestNewAPERequest(t *testing.T) { expectedRequest := request{ operation: method, - resource: &resource{ + resource: resource{ name: resourceName(cnr, obj, prm.Namespace), properties: objectProperties(cnr, obj, testCnrOwner, func() *objectV2.Header { if headerObjSDK != nil { @@ -273,7 +273,7 @@ func TestNewAPERequest(t *testing.T) { }, } - require.Equal(t, expectedRequest, *r) + require.Equal(t, expectedRequest, r) }) } }) From 7b1adfed3e7898400e715251c0e37f89bbb2c279 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 5 Apr 2024 16:42:48 +0300 Subject: [PATCH 0486/1413] [#1080] metabase: Open bucket for container counter once Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/counter.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index dc85b46971..4d860261c0 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -232,14 +232,19 @@ func (db *DB) ContainerCount(ctx context.Context, id cid.ID) (ObjectCounters, er } func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID, isUserObject bool) error { - if err := db.updateShardObjectCounter(tx, phy, 1, true); err != nil { + b := tx.Bucket(shardInfoBucket) + if b == nil { + return db.incContainerObjectCounter(tx, cnrID, isUserObject) + } + + if err := db.updateShardObjectCounterBucket(b, phy, 1, true); err != nil { return fmt.Errorf("could not increase phy object counter: %w", err) } - if err := db.updateShardObjectCounter(tx, logical, 1, true); err != nil { + if err := db.updateShardObjectCounterBucket(b, logical, 1, true); err != nil { return fmt.Errorf("could not increase logical object counter: %w", err) } if isUserObject { - if err := db.updateShardObjectCounter(tx, user, 1, true); err != nil { + if err := db.updateShardObjectCounterBucket(b, user, 1, true); err != nil { return fmt.Errorf("could not increase user object counter: %w", err) } } @@ -252,6 +257,10 @@ func (db *DB) updateShardObjectCounter(tx *bbolt.Tx, typ objectType, delta uint6 return nil } + return db.updateShardObjectCounterBucket(b, typ, delta, inc) +} + +func (*DB) updateShardObjectCounterBucket(b *bbolt.Bucket, typ objectType, delta uint64, inc bool) error { var counter uint64 var counterKey []byte From 76398c06b00922c58363e707727ac227aa81fb13 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 9 Apr 2024 15:29:49 +0300 Subject: [PATCH 0487/1413] [#1080] metabase: Add StorageID metric Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/storage_id.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/storage_id.go b/pkg/local_object_storage/metabase/storage_id.go index f9767935c3..6d620b41a2 100644 --- a/pkg/local_object_storage/metabase/storage_id.go +++ b/pkg/local_object_storage/metabase/storage_id.go @@ -36,6 +36,14 @@ func (r StorageIDRes) StorageID() []byte { // StorageID returns storage descriptor for objects from the blobstor. // It is put together with the object can makes get/delete operation faster. func (db *DB) StorageID(ctx context.Context, prm StorageIDPrm) (res StorageIDRes, err error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("StorageID", time.Since(startedAt), success) + }() + _, span := tracing.StartSpanFromContext(ctx, "metabase.StorageID", trace.WithAttributes( attribute.String("address", prm.addr.EncodeToString()), @@ -54,7 +62,7 @@ func (db *DB) StorageID(ctx context.Context, prm StorageIDPrm) (res StorageIDRes return err }) - + success = err == nil return res, metaerr.Wrap(err) } From 1005bf4f56d98cf09b285ee56ba1d447c508ffd8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 5 Mar 2024 13:41:15 +0300 Subject: [PATCH 0488/1413] [#1024] shard: Add refill metabase benchmark Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/refill_test.go | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 pkg/local_object_storage/shard/refill_test.go diff --git a/pkg/local_object_storage/shard/refill_test.go b/pkg/local_object_storage/shard/refill_test.go new file mode 100644 index 0000000000..07ec9180cf --- /dev/null +++ b/pkg/local_object_storage/shard/refill_test.go @@ -0,0 +1,72 @@ +package shard + +import ( + "context" + "os" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "github.com/stretchr/testify/require" +) + +func BenchmarkRefillMetabase(b *testing.B) { + b.Run("100 objects", func(b *testing.B) { + benchRefillMetabase(b, 100) + }) + + b.Run("1000 objects", func(b *testing.B) { + benchRefillMetabase(b, 1000) + }) + + b.Run("2000 objects", func(b *testing.B) { + benchRefillMetabase(b, 2000) + }) + + b.Run("5000 objects", func(b *testing.B) { + benchRefillMetabase(b, 5000) + }) +} + +func benchRefillMetabase(b *testing.B, objectsCount int) { + sh := newShard(b, false) + defer func() { require.NoError(b, sh.Close()) }() + + var putPrm PutPrm + + for i := 0; i < objectsCount/2; i++ { + obj := testutil.GenerateObject() + testutil.AddAttribute(obj, "foo", "bar") + testutil.AddPayload(obj, 1<<5) // blobvnicza tree obj + + putPrm.SetObject(obj) + + _, err := sh.Put(context.Background(), putPrm) + require.NoError(b, err) + } + + for i := 0; i < objectsCount/2; i++ { + obj := testutil.GenerateObject() + testutil.AddAttribute(obj, "foo", "bar") + obj.SetID(oidtest.ID()) + testutil.AddPayload(obj, 1<<20) // fstree obj + + putPrm.SetObject(obj) + + _, err := sh.Put(context.Background(), putPrm) + require.NoError(b, err) + } + + require.NoError(b, sh.Close()) + require.NoError(b, os.Remove(sh.metaBase.DumpInfo().Path)) + + require.NoError(b, sh.Open(context.Background())) + sh.cfg.refillMetabase = true + + b.ReportAllocs() + b.ResetTimer() + + require.NoError(b, sh.Init(context.Background())) + + require.NoError(b, sh.Close()) +} From 57466594fbef35d014479e7d96ccd17db438fef5 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 5 Mar 2024 15:39:50 +0300 Subject: [PATCH 0489/1413] [#1024] shard: Resync metabase concurrently Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 11 ++- cmd/frostfs-node/config/engine/config_test.go | 2 + .../config/engine/shard/config.go | 15 ++++ config/example/node.env | 1 + config/example/node.json | 1 + config/example/node.yaml | 1 + docs/storage-node-configuration.md | 9 ++- pkg/local_object_storage/shard/control.go | 76 ++++++++++++------- pkg/local_object_storage/shard/refill_test.go | 6 +- pkg/local_object_storage/shard/shard.go | 10 ++- 10 files changed, 93 insertions(+), 39 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index d78a90cfc9..c5ed8b50c6 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -119,10 +119,11 @@ type shardCfg struct { estimateCompressibility bool estimateCompressibilityThreshold float64 - smallSizeObjectLimit uint64 - uncompressableContentType []string - refillMetabase bool - mode shardmode.Mode + smallSizeObjectLimit uint64 + uncompressableContentType []string + refillMetabase bool + refillMetabaseWorkersCount int + mode shardmode.Mode metaCfg struct { path string @@ -234,6 +235,7 @@ func (a *applicationConfiguration) updateShardConfig(c *config.Config, oldConfig var newConfig shardCfg newConfig.refillMetabase = oldConfig.RefillMetabase() + newConfig.refillMetabaseWorkersCount = oldConfig.RefillMetabaseWorkersCount() newConfig.mode = oldConfig.Mode() newConfig.compress = oldConfig.Compress() newConfig.estimateCompressibility = oldConfig.EstimateCompressibility() @@ -986,6 +988,7 @@ func (c *cfg) getShardOpts(shCfg shardCfg) shardOptsWithID { sh.shOpts = []shard.Option{ shard.WithLogger(c.log), shard.WithRefillMetabase(shCfg.refillMetabase), + shard.WithRefillMetabaseWorkersCount(shCfg.refillMetabaseWorkersCount), shard.WithMode(shCfg.mode), shard.WithBlobStorOptions(blobstoreOpts...), shard.WithMetaBaseOptions(mbOptions...), diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 86c9383096..b5c926fc34 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -117,6 +117,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, false, sc.RefillMetabase()) require.Equal(t, mode.ReadOnly, sc.Mode()) + require.Equal(t, 100, sc.RefillMetabaseWorkersCount()) case 1: require.Equal(t, "tmp/1/blob/pilorama.db", pl.Path()) require.Equal(t, fs.FileMode(0o644), pl.Perm()) @@ -168,6 +169,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, true, sc.RefillMetabase()) require.Equal(t, mode.ReadWrite, sc.Mode()) + require.Equal(t, shardconfig.RefillMetabaseWorkersCountDefault, sc.RefillMetabaseWorkersCount()) } return nil }) diff --git a/cmd/frostfs-node/config/engine/shard/config.go b/cmd/frostfs-node/config/engine/shard/config.go index f9cfdf2a86..0620c9f630 100644 --- a/cmd/frostfs-node/config/engine/shard/config.go +++ b/cmd/frostfs-node/config/engine/shard/config.go @@ -18,6 +18,7 @@ const ( // SmallSizeLimitDefault is a default limit of small objects payload in bytes. SmallSizeLimitDefault = 1 << 20 EstimateCompressibilityThresholdDefault = 0.1 + RefillMetabaseWorkersCountDefault = 500 ) // From wraps config section into Config. @@ -134,6 +135,20 @@ func (x *Config) RefillMetabase() bool { ) } +// RefillMetabaseWorkersCount returns the value of "resync_metabase_worker_count" config parameter. +// +// Returns RefillMetabaseWorkersCountDefault if the value is not a positive number. +func (x *Config) RefillMetabaseWorkersCount() int { + v := config.IntSafe( + (*config.Config)(x), + "resync_metabase_worker_count", + ) + if v > 0 { + return int(v) + } + return RefillMetabaseWorkersCountDefault +} + // Mode return the value of "mode" config parameter. // // Panics if read the value is not one of predefined diff --git a/config/example/node.env b/config/example/node.env index 976c426293..9068886d3c 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -98,6 +98,7 @@ FROSTFS_STORAGE_REBUILD_WORKERS_COUNT=1000 ## 0 shard ### Flag to refill Metabase from BlobStor FROSTFS_STORAGE_SHARD_0_RESYNC_METABASE=false +FROSTFS_STORAGE_SHARD_0_RESYNC_METABASE_WORKER_COUNT=100 ### Flag to set shard mode FROSTFS_STORAGE_SHARD_0_MODE=read-only ### Write cache config diff --git a/config/example/node.json b/config/example/node.json index 648fb77b02..bae28720bb 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -144,6 +144,7 @@ "0": { "mode": "read-only", "resync_metabase": false, + "resync_metabase_worker_count": 100, "writecache": { "enabled": false, "no_sync": true, diff --git a/config/example/node.yaml b/config/example/node.yaml index 2dcf7c4d90..7a824adbeb 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -167,6 +167,7 @@ storage: # degraded-read-only # disabled (do not work with the shard, allows to not remove it from the config) resync_metabase: false # sync metabase with blobstor on start, expensive, leave false until complete understanding + resync_metabase_worker_count: 100 writecache: enabled: false diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 02ead30204..aa3a178153 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -179,14 +179,15 @@ Contains configuration for each shard. Keys must be consecutive numbers starting `default` subsection has the same format and specifies defaults for missing values. The following table describes configuration for each shard. -| Parameter | Type | Default value | Description | -|-------------------------------------|---------------------------------------------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Parameter | Type | Default value | Description | +| ------------------------------------------------ | ------------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `compress` | `bool` | `false` | Flag to enable compression. | | `compression_exclude_content_types` | `[]string` | | List of content-types to disable compression for. Content-type is taken from `Content-Type` object attribute. Each element can contain a star `*` as a first (last) character, which matches any prefix (suffix). | -| `compression_estimate_compressibility` | `bool` | `false` | If `true`, then noramalized compressibility estimation is used to decide compress data or not. | -| `compression_estimate_compressibility_threshold` | `float` | `0.1` | Normilized compressibility estimate threshold: data will compress if estimation if greater than this value. | +| `compression_estimate_compressibility` | `bool` | `false` | If `true`, then noramalized compressibility estimation is used to decide compress data or not. | +| `compression_estimate_compressibility_threshold` | `float` | `0.1` | Normilized compressibility estimate threshold: data will compress if estimation if greater than this value. | | `mode` | `string` | `read-write` | Shard Mode.
Possible values: `read-write`, `read-only`, `degraded`, `degraded-read-only`, `disabled` | | `resync_metabase` | `bool` | `false` | Flag to enable metabase resync on start. | +| `resync_metabase_worker_count` | `int` | `1000` | Count of concurrent workers to resync metabase. | | `writecache` | [Writecache config](#writecache-subsection) | | Write-cache configuration. | | `metabase` | [Metabase config](#metabase-subsection) | | Metabase configuration. | | `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 774fe8045b..d080e2919b 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -15,6 +15,7 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" + "golang.org/x/sync/errgroup" ) func (s *Shard) handleMetabaseFailure(stage string, err error) error { @@ -185,39 +186,56 @@ func (s *Shard) refillMetabase(ctx context.Context) error { return fmt.Errorf("could not reset metabase: %w", err) } - obj := objectSDK.New() + eg, egCtx := errgroup.WithContext(ctx) + if s.cfg.refillMetabaseWorkersCount > 0 { + eg.SetLimit(s.cfg.refillMetabaseWorkersCount) + } - err = blobstor.IterateBinaryObjects(ctx, s.blobStor, func(addr oid.Address, data []byte, descriptor []byte) error { - if err := obj.Unmarshal(data); err != nil { - s.log.Warn(logs.ShardCouldNotUnmarshalObject, - zap.Stringer("address", addr), - zap.String("err", err.Error())) + itErr := blobstor.IterateBinaryObjects(egCtx, s.blobStor, func(addr oid.Address, data []byte, descriptor []byte) error { + eg.Go(func() error { + obj := objectSDK.New() + if err := obj.Unmarshal(data); err != nil { + s.log.Warn(logs.ShardCouldNotUnmarshalObject, + zap.Stringer("address", addr), + zap.String("err", err.Error())) + return nil + } + + var err error + switch obj.Type() { + case objectSDK.TypeTombstone: + err = s.refillTombstoneObject(egCtx, obj) + case objectSDK.TypeLock: + err = s.refillLockObject(egCtx, obj) + default: + } + if err != nil { + return err + } + + var mPrm meta.PutPrm + mPrm.SetObject(obj) + mPrm.SetStorageID(descriptor) + + _, err = s.metaBase.Put(egCtx, mPrm) + if err != nil && !client.IsErrObjectAlreadyRemoved(err) && !errors.Is(err, meta.ErrObjectIsExpired) { + return err + } + + return nil + }) + + select { + case <-egCtx.Done(): + return egCtx.Err() + default: return nil } - - var err error - switch obj.Type() { - case objectSDK.TypeTombstone: - err = s.refillTombstoneObject(ctx, obj) - case objectSDK.TypeLock: - err = s.refillLockObject(ctx, obj) - default: - } - if err != nil { - return err - } - - var mPrm meta.PutPrm - mPrm.SetObject(obj) - mPrm.SetStorageID(descriptor) - - _, err = s.metaBase.Put(ctx, mPrm) - if err != nil && !client.IsErrObjectAlreadyRemoved(err) && !errors.Is(err, meta.ErrObjectIsExpired) { - return err - } - - return nil }) + + egErr := eg.Wait() + + err = errors.Join(egErr, itErr) if err != nil { return fmt.Errorf("could not put objects to the meta: %w", err) } diff --git a/pkg/local_object_storage/shard/refill_test.go b/pkg/local_object_storage/shard/refill_test.go index 07ec9180cf..509ccaaa6f 100644 --- a/pkg/local_object_storage/shard/refill_test.go +++ b/pkg/local_object_storage/shard/refill_test.go @@ -5,6 +5,7 @@ import ( "os" "testing" + shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" @@ -29,7 +30,10 @@ func BenchmarkRefillMetabase(b *testing.B) { } func benchRefillMetabase(b *testing.B, objectsCount int) { - sh := newShard(b, false) + sh := newCustomShard(b, false, shardOptions{ + additionalShardOptions: []Option{WithRefillMetabaseWorkersCount(shardconfig.RefillMetabaseWorkersCountDefault)}, + }) + defer func() { require.NoError(b, sh.Close()) }() var putPrm PutPrm diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 8368f6db47..81d8543733 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -95,7 +95,8 @@ type MetricsWriter interface { type cfg struct { m sync.RWMutex - refillMetabase bool + refillMetabase bool + refillMetabaseWorkersCount int rmBatchSize int @@ -300,6 +301,13 @@ func WithRefillMetabase(v bool) Option { } } +// WithRefillMetabaseWorkersCount returns option to set count of workers to refill the Metabase on Shard's initialization step. +func WithRefillMetabaseWorkersCount(v int) Option { + return func(c *cfg) { + c.refillMetabaseWorkersCount = v + } +} + // WithMode returns option to set shard's mode. Mode must be one of the predefined: // - mode.ReadWrite; // - mode.ReadOnly. From e3d9dd6ee8134107926cf4cf58d41899b1eebf96 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 5 Mar 2024 16:08:49 +0300 Subject: [PATCH 0490/1413] [#1024] blobovnicza: Copy data on iterate DB value is only valid while the tx is alive. But handler may to run something in other goroutine. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobovnicza/iterate.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index 32b0ccea7a..b1cb919202 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -1,6 +1,7 @@ package blobovnicza import ( + "bytes" "context" "fmt" "math" @@ -158,7 +159,7 @@ func (b *Blobovnicza) Iterate(ctx context.Context, prm IteratePrm) (IterateRes, } if !prm.withoutData { - elem.data = v + elem.data = bytes.Clone(v) } return prm.handler(elem) From 1b17258c042d3b1f1b4d2bdb530cbb5cd1560139 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 12 Mar 2024 17:36:26 +0300 Subject: [PATCH 0491/1413] [#1029] metabase: Add refill metrics Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 2 + .../blobovnicza/control.go | 4 + .../blobstor/blobovniczatree/count.go | 38 ++++++++ .../blobstor/blobovniczatree/metrics.go | 2 + .../blobstor/common/storage.go | 1 + .../blobstor/fstree/fstree.go | 39 ++++++++ .../blobstor/fstree/metrics.go | 2 + pkg/local_object_storage/blobstor/info.go | 45 +++++++++ .../blobstor/memstore/memstore.go | 7 ++ pkg/local_object_storage/blobstor/metrics.go | 2 + .../blobstor/teststore/teststore.go | 7 ++ pkg/local_object_storage/engine/metrics.go | 4 + pkg/local_object_storage/engine/shards.go | 12 +++ .../metrics/blobovnicza.go | 4 + pkg/local_object_storage/metrics/blobstore.go | 4 + pkg/local_object_storage/metrics/fstree.go | 4 + pkg/local_object_storage/shard/control.go | 94 ++++++++++++++----- .../shard/control_test.go | 16 +++- .../shard/metrics_test.go | 60 +++++++++--- pkg/local_object_storage/shard/reload_test.go | 1 + pkg/local_object_storage/shard/shard.go | 6 ++ pkg/metrics/engine.go | 53 ++++++++++- pkg/metrics/mode.go | 6 ++ 23 files changed, 366 insertions(+), 47 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/count.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 64e5f771e6..d56d425ce1 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -579,6 +579,8 @@ const ( EngineShardsEvacuationFailedToMoveTree = "failed to evacuate tree to other node" EngineShardsEvacuationTreeEvacuatedLocal = "tree evacuated to local node" EngineShardsEvacuationTreeEvacuatedRemote = "tree evacuated to other node" + EngineRefillFailedToGetObjectsCount = "failed to get blobstor objects count, no resync percent estimation is available" + BlobstoreFailedToGetFileinfo = "failed to get file info" ECFailedToSendToContainerNode = "failed to send EC object to container node" ECFailedToSaveECPart = "failed to save EC part" ) diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index dab301647a..aeaa4e1d5c 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -101,6 +101,10 @@ func (b *Blobovnicza) Init() error { return b.initializeCounters() } +func (b *Blobovnicza) ObjectsCount() uint64 { + return b.itemsCount.Load() +} + func (b *Blobovnicza) initializeCounters() error { var size uint64 var items uint64 diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/count.go b/pkg/local_object_storage/blobstor/blobovniczatree/count.go new file mode 100644 index 0000000000..cf91637d70 --- /dev/null +++ b/pkg/local_object_storage/blobstor/blobovniczatree/count.go @@ -0,0 +1,38 @@ +package blobovniczatree + +import ( + "context" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" +) + +func (b *Blobovniczas) ObjectsCount(ctx context.Context) (uint64, error) { + var ( + success bool + startedAt = time.Now() + ) + defer func() { + b.metrics.ObjectsCount(time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "Blobovniczas.ObjectsCount") + defer span.End() + + var result uint64 + err := b.iterateExistingDBPaths(ctx, func(p string) (bool, error) { + shDB := b.getBlobovniczaWithoutCaching(p) + blz, err := shDB.Open() + if err != nil { + return true, err + } + defer shDB.Close() + + result += blz.ObjectsCount() + return false, nil + }) + if err != nil { + return 0, err + } + return result, nil +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go b/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go index ed05f8772c..28289c19e5 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go @@ -24,6 +24,7 @@ type Metrics interface { SetRebuildStatus(status string) ObjectMoved(d time.Duration) SetRebuildPercent(value uint32) + ObjectsCount(d time.Duration, success bool) Delete(d time.Duration, success, withStorageID bool) Exists(d time.Duration, success, withStorageID bool) @@ -47,6 +48,7 @@ func (m *noopMetrics) GetRange(time.Duration, int, bool, bool) {} func (m *noopMetrics) Get(time.Duration, int, bool, bool) {} func (m *noopMetrics) Iterate(time.Duration, bool) {} func (m *noopMetrics) Put(time.Duration, int, bool) {} +func (m *noopMetrics) ObjectsCount(time.Duration, bool) {} func (m *noopMetrics) Blobovnicza() blobovnicza.Metrics { return &blobovnicza.NoopMetrics{} } diff --git a/pkg/local_object_storage/blobstor/common/storage.go b/pkg/local_object_storage/blobstor/common/storage.go index e552fafea0..8f629b1de6 100644 --- a/pkg/local_object_storage/blobstor/common/storage.go +++ b/pkg/local_object_storage/blobstor/common/storage.go @@ -15,6 +15,7 @@ type Storage interface { Type() string Path() string + ObjectsCount(ctx context.Context) (uint64, error) SetCompressor(cc *compression.Config) Compressor() *compression.Config diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 420f341a4c..7a064af6bc 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -467,6 +467,45 @@ func (t *FSTree) countFiles() (uint64, error) { return counter, nil } +func (t *FSTree) ObjectsCount(ctx context.Context) (uint64, error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + t.metrics.ObjectsCount(time.Since(startedAt), success) + }() + + ctx, span := tracing.StartSpanFromContext(ctx, "FSTree.ObjectsCount", + trace.WithAttributes( + attribute.String("path", t.RootPath), + )) + defer span.End() + + var result uint64 + + err := filepath.WalkDir(t.RootPath, + func(_ string, d fs.DirEntry, _ error) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if !d.IsDir() { + result++ + } + + return nil + }, + ) + if err != nil { + return 0, fmt.Errorf("could not walk through %s directory: %w", t.RootPath, err) + } + success = true + return result, nil +} + // Type is fstree storage type used in logs and configuration. const Type = "fstree" diff --git a/pkg/local_object_storage/blobstor/fstree/metrics.go b/pkg/local_object_storage/blobstor/fstree/metrics.go index ca6a549759..eeb6866726 100644 --- a/pkg/local_object_storage/blobstor/fstree/metrics.go +++ b/pkg/local_object_storage/blobstor/fstree/metrics.go @@ -14,6 +14,7 @@ type Metrics interface { Put(d time.Duration, size int, success bool) Get(d time.Duration, size int, success bool) GetRange(d time.Duration, size int, success bool) + ObjectsCount(d time.Duration, success bool) } type noopMetrics struct{} @@ -27,3 +28,4 @@ func (m *noopMetrics) Exists(time.Duration, bool) {} func (m *noopMetrics) Put(time.Duration, int, bool) {} func (m *noopMetrics) Get(time.Duration, int, bool) {} func (m *noopMetrics) GetRange(time.Duration, int, bool) {} +func (m *noopMetrics) ObjectsCount(time.Duration, bool) {} diff --git a/pkg/local_object_storage/blobstor/info.go b/pkg/local_object_storage/blobstor/info.go index 2fd62af818..8a5bb870af 100644 --- a/pkg/local_object_storage/blobstor/info.go +++ b/pkg/local_object_storage/blobstor/info.go @@ -1,5 +1,14 @@ package blobstor +import ( + "context" + "sync/atomic" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "golang.org/x/sync/errgroup" +) + // DumpInfo returns information about blob stor. func (b *BlobStor) DumpInfo() Info { b.modeMtx.RLock() @@ -15,3 +24,39 @@ func (b *BlobStor) DumpInfo() Info { SubStorages: sub, } } + +// ObjectsCount returns Blobstore's total objects count. +func (b *BlobStor) ObjectsCount(ctx context.Context) (uint64, error) { + var err error + startedAt := time.Now() + defer func() { + b.metrics.ObjectsCount(time.Since(startedAt), err == nil) + }() + + ctx, span := tracing.StartSpanFromContext(ctx, "BlobStor.ObjectsCount") + defer span.End() + + b.modeMtx.RLock() + defer b.modeMtx.RUnlock() + + var result atomic.Uint64 + + eg, egCtx := errgroup.WithContext(ctx) + for i := range b.storage { + i := i + eg.Go(func() error { + v, e := b.storage[i].Storage.ObjectsCount(egCtx) + if e != nil { + return e + } + result.Add(v) + return nil + }) + } + + if err = eg.Wait(); err != nil { + return 0, err + } + + return result.Load(), nil +} diff --git a/pkg/local_object_storage/blobstor/memstore/memstore.go b/pkg/local_object_storage/blobstor/memstore/memstore.go index 39bed00bf2..0252c79835 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore.go @@ -163,3 +163,10 @@ func (s *memstoreImpl) Iterate(_ context.Context, req common.IteratePrm) (common func (s *memstoreImpl) Rebuild(_ context.Context, _ common.RebuildPrm) (common.RebuildRes, error) { return common.RebuildRes{}, nil } + +func (s *memstoreImpl) ObjectsCount(_ context.Context) (uint64, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + return uint64(len(s.objs)), nil +} diff --git a/pkg/local_object_storage/blobstor/metrics.go b/pkg/local_object_storage/blobstor/metrics.go index 4a7b400922..aadc237af0 100644 --- a/pkg/local_object_storage/blobstor/metrics.go +++ b/pkg/local_object_storage/blobstor/metrics.go @@ -13,6 +13,7 @@ type Metrics interface { Get(d time.Duration, size int, success, withStorageID bool) Iterate(d time.Duration, success bool) Put(d time.Duration, size int, success bool) + ObjectsCount(d time.Duration, success bool) } type noopMetrics struct{} @@ -26,3 +27,4 @@ func (m *noopMetrics) GetRange(time.Duration, int, bool, bool) {} func (m *noopMetrics) Get(time.Duration, int, bool, bool) {} func (m *noopMetrics) Iterate(time.Duration, bool) {} func (m *noopMetrics) Put(time.Duration, int, bool) {} +func (m *noopMetrics) ObjectsCount(time.Duration, bool) {} diff --git a/pkg/local_object_storage/blobstor/teststore/teststore.go b/pkg/local_object_storage/blobstor/teststore/teststore.go index c0cdfacf8a..016fd520fb 100644 --- a/pkg/local_object_storage/blobstor/teststore/teststore.go +++ b/pkg/local_object_storage/blobstor/teststore/teststore.go @@ -233,3 +233,10 @@ func (s *TestStore) SetParentID(string) {} func (s *TestStore) Rebuild(_ context.Context, _ common.RebuildPrm) (common.RebuildRes, error) { return common.RebuildRes{}, nil } + +func (s *TestStore) ObjectsCount(ctx context.Context) (uint64, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + return s.st.ObjectsCount(ctx) +} diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index 91dfa87625..6b99dff7e2 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -27,6 +27,10 @@ type MetricRegister interface { IncContainerObjectCounter(shardID, contID, objectType string) SubContainerObjectCounter(shardID, contID, objectType string, v uint64) + IncRefillObjectsCount(shardID, path string, size int, success bool) + SetRefillPercent(shardID, path string, percent uint32) + SetRefillStatus(shardID, path, status string) + WriteCache() metrics.WriteCacheMetrics GC() metrics.GCMetrics } diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index ccf2e9dac5..54d3e7d65e 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -85,6 +85,18 @@ func (m *metricsWithID) SubContainerObjectsCount(cnrID string, objectType string m.mw.SubContainerObjectCounter(m.id, cnrID, objectType, value) } +func (m *metricsWithID) IncRefillObjectsCount(path string, size int, success bool) { + m.mw.IncRefillObjectsCount(m.id, path, size, success) +} + +func (m *metricsWithID) SetRefillPercent(path string, percent uint32) { + m.mw.SetRefillPercent(m.id, path, percent) +} + +func (m *metricsWithID) SetRefillStatus(path string, status string) { + m.mw.SetRefillStatus(m.id, path, status) +} + // AddShard adds a new shard to the storage engine. // // Returns any error encountered that did not allow adding a shard. diff --git a/pkg/local_object_storage/metrics/blobovnicza.go b/pkg/local_object_storage/metrics/blobovnicza.go index 3a92a7bc78..1e294efa5a 100644 --- a/pkg/local_object_storage/metrics/blobovnicza.go +++ b/pkg/local_object_storage/metrics/blobovnicza.go @@ -87,6 +87,10 @@ func (m *blobovniczaTreeMetrics) Put(d time.Duration, size int, success bool) { } } +func (m *blobovniczaTreeMetrics) ObjectsCount(d time.Duration, success bool) { + m.m.BlobobvnizcaTreeMethodDuration(m.shardID, m.path, "ObjectsCount", d, success, metrics_impl.NullBool{}) +} + type blobovniczaMetrics struct { m metrics_impl.BlobobvnizcaMetrics shardID func() string diff --git a/pkg/local_object_storage/metrics/blobstore.go b/pkg/local_object_storage/metrics/blobstore.go index 48249e89c9..b3871dfcae 100644 --- a/pkg/local_object_storage/metrics/blobstore.go +++ b/pkg/local_object_storage/metrics/blobstore.go @@ -63,3 +63,7 @@ func (m *blobstoreMetrics) Put(d time.Duration, size int, success bool) { m.m.AddPut(m.shardID, size) } } + +func (m *blobstoreMetrics) ObjectsCount(d time.Duration, success bool) { + m.m.MethodDuration(m.shardID, "ObjectsCount", d, success, metrics_impl.NullBool{}) +} diff --git a/pkg/local_object_storage/metrics/fstree.go b/pkg/local_object_storage/metrics/fstree.go index 0def3210cb..e035b3a46b 100644 --- a/pkg/local_object_storage/metrics/fstree.go +++ b/pkg/local_object_storage/metrics/fstree.go @@ -65,3 +65,7 @@ func (m *fstreeMetrics) GetRange(d time.Duration, size int, success bool) { m.m.AddGet(m.shardID, m.path, size) } } + +func (m *fstreeMetrics) ObjectsCount(d time.Duration, success bool) { + m.m.MethodDuration(m.shardID, m.path, "ObjectsCount", d, success) +} diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index d080e2919b..6712822a0a 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -181,47 +182,54 @@ func (s *Shard) Init(ctx context.Context) error { } func (s *Shard) refillMetabase(ctx context.Context) error { + path := s.metaBase.DumpInfo().Path + s.metricsWriter.SetRefillStatus(path, "running") + s.metricsWriter.SetRefillPercent(path, 0) + var success bool + defer func() { + if success { + s.metricsWriter.SetRefillStatus(path, "completed") + } else { + s.metricsWriter.SetRefillStatus(path, "failed") + } + }() + err := s.metaBase.Reset() if err != nil { return fmt.Errorf("could not reset metabase: %w", err) } + withCount := true + totalObjects, err := s.blobStor.ObjectsCount(ctx) + if err != nil { + s.log.Warn(logs.EngineRefillFailedToGetObjectsCount, zap.Error(err)) + withCount = false + } + eg, egCtx := errgroup.WithContext(ctx) if s.cfg.refillMetabaseWorkersCount > 0 { eg.SetLimit(s.cfg.refillMetabaseWorkersCount) } + var completedCount uint64 + var metricGuard sync.Mutex itErr := blobstor.IterateBinaryObjects(egCtx, s.blobStor, func(addr oid.Address, data []byte, descriptor []byte) error { eg.Go(func() error { - obj := objectSDK.New() - if err := obj.Unmarshal(data); err != nil { - s.log.Warn(logs.ShardCouldNotUnmarshalObject, - zap.Stringer("address", addr), - zap.String("err", err.Error())) - return nil - } + var success bool + defer func() { + s.metricsWriter.IncRefillObjectsCount(path, len(data), success) + if withCount { + metricGuard.Lock() + completedCount++ + s.metricsWriter.SetRefillPercent(path, uint32(completedCount*100/totalObjects)) + metricGuard.Unlock() + } + }() - var err error - switch obj.Type() { - case objectSDK.TypeTombstone: - err = s.refillTombstoneObject(egCtx, obj) - case objectSDK.TypeLock: - err = s.refillLockObject(egCtx, obj) - default: - } - if err != nil { + if err := s.refillObject(egCtx, data, addr, descriptor); err != nil { return err } - - var mPrm meta.PutPrm - mPrm.SetObject(obj) - mPrm.SetStorageID(descriptor) - - _, err = s.metaBase.Put(egCtx, mPrm) - if err != nil && !client.IsErrObjectAlreadyRemoved(err) && !errors.Is(err, meta.ErrObjectIsExpired) { - return err - } - + success = true return nil }) @@ -245,6 +253,40 @@ func (s *Shard) refillMetabase(ctx context.Context) error { return fmt.Errorf("could not sync object counters: %w", err) } + success = true + s.metricsWriter.SetRefillPercent(path, 100) + return nil +} + +func (s *Shard) refillObject(ctx context.Context, data []byte, addr oid.Address, descriptor []byte) error { + obj := objectSDK.New() + if err := obj.Unmarshal(data); err != nil { + s.log.Warn(logs.ShardCouldNotUnmarshalObject, + zap.Stringer("address", addr), + zap.String("err", err.Error())) + return nil + } + + var err error + switch obj.Type() { + case objectSDK.TypeTombstone: + err = s.refillTombstoneObject(ctx, obj) + case objectSDK.TypeLock: + err = s.refillLockObject(ctx, obj) + default: + } + if err != nil { + return err + } + + var mPrm meta.PutPrm + mPrm.SetObject(obj) + mPrm.SetStorageID(descriptor) + + _, err = s.metaBase.Put(ctx, mPrm) + if err != nil && !client.IsErrObjectAlreadyRemoved(err) && !errors.Is(err, meta.ErrObjectIsExpired) { + return err + } return nil } diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index d08747e13e..44fee16360 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -126,11 +126,15 @@ func TestRefillMetabaseCorrupted(t *testing.T) { }), } + mm := NewMetricStore() + sh := New( WithID(NewIDFromBytes([]byte{})), WithBlobStorOptions(blobOpts...), WithPiloramaOptions(pilorama.WithPath(filepath.Join(dir, "pilorama"))), - WithMetaBaseOptions(meta.WithPath(filepath.Join(dir, "meta")), meta.WithEpochState(epochState{}))) + WithMetaBaseOptions(meta.WithPath(filepath.Join(dir, "meta")), meta.WithEpochState(epochState{})), + WithMetricsWriter(mm), + ) require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) @@ -157,7 +161,8 @@ func TestRefillMetabaseCorrupted(t *testing.T) { WithBlobStorOptions(blobOpts...), WithPiloramaOptions(pilorama.WithPath(filepath.Join(dir, "pilorama"))), WithMetaBaseOptions(meta.WithPath(filepath.Join(dir, "meta_new")), meta.WithEpochState(epochState{})), - WithRefillMetabase(true)) + WithRefillMetabase(true), + WithMetricsWriter(mm)) require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) @@ -185,6 +190,8 @@ func TestRefillMetabase(t *testing.T) { }), } + mm := NewMetricStore() + sh := New( WithID(NewIDFromBytes([]byte{})), WithBlobStorOptions(blobOpts...), @@ -194,6 +201,7 @@ func TestRefillMetabase(t *testing.T) { ), WithPiloramaOptions( pilorama.WithPath(filepath.Join(p, "pilorama"))), + WithMetricsWriter(mm), ) // open Blobstor @@ -362,6 +370,7 @@ func TestRefillMetabase(t *testing.T) { ), WithPiloramaOptions( pilorama.WithPath(filepath.Join(p, "pilorama_another"))), + WithMetricsWriter(mm), ) // open Blobstor @@ -389,4 +398,7 @@ func TestRefillMetabase(t *testing.T) { checkObj(object.AddressOf(tombObj), tombObj) checkTombMembers(true) checkLocked(t, cnrLocked, locked) + require.Equal(t, int64(len(mObjs)+2), mm.refillCount) // 1 lock + 1 tomb + require.Equal(t, "completed", mm.refillStatus) + require.Equal(t, uint32(100), mm.refillPercent) } diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 2ab99eed35..38d465f310 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -21,13 +21,28 @@ import ( ) type metricsStore struct { - mtx sync.Mutex - objCounters map[string]uint64 - cnrSize map[string]int64 - cnrCount map[string]uint64 - pldSize int64 - mode mode.Mode - errCounter int64 + mtx sync.Mutex + objCounters map[string]uint64 + cnrSize map[string]int64 + cnrCount map[string]uint64 + pldSize int64 + mode mode.Mode + errCounter int64 + refillCount int64 + refillSize int64 + refillPercent uint32 + refillStatus string +} + +func NewMetricStore() *metricsStore { + return &metricsStore{ + objCounters: map[string]uint64{ + "phy": 0, + "logic": 0, + }, + cnrSize: make(map[string]int64), + cnrCount: make(map[string]uint64), + } } func (m *metricsStore) SetShardID(_ string) {} @@ -155,6 +170,28 @@ func (m *metricsStore) getContainerCount(cnrID, objectType string) (uint64, bool return v, ok } +func (m *metricsStore) IncRefillObjectsCount(_ string, size int, success bool) { + m.mtx.Lock() + defer m.mtx.Unlock() + + m.refillCount++ + m.refillSize += int64(size) +} + +func (m *metricsStore) SetRefillPercent(_ string, percent uint32) { + m.mtx.Lock() + defer m.mtx.Unlock() + + m.refillPercent = percent +} + +func (m *metricsStore) SetRefillStatus(_ string, status string) { + m.mtx.Lock() + defer m.mtx.Unlock() + + m.refillStatus = status +} + func TestCounters(t *testing.T) { t.Parallel() @@ -361,14 +398,7 @@ func shardWithMetrics(t *testing.T, path string) (*Shard, *metricsStore) { }), } - mm := &metricsStore{ - objCounters: map[string]uint64{ - "phy": 0, - "logic": 0, - }, - cnrSize: make(map[string]int64), - cnrCount: make(map[string]uint64), - } + mm := NewMetricStore() sh := New( WithID(NewIDFromBytes([]byte{})), diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index 511ce07210..b5ea2fec76 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -51,6 +51,7 @@ func TestShardReload(t *testing.T) { WithMetaBaseOptions(metaOpts...), WithPiloramaOptions( pilorama.WithPath(filepath.Join(p, "pilorama"))), + WithMetricsWriter(NewMetricStore()), } sh := New(opts...) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 81d8543733..d9cd2b2f4d 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -90,6 +90,12 @@ type MetricsWriter interface { IncContainerObjectsCount(cnrID string, objectType string) // SubContainerObjectsCount subtracts container object count. SubContainerObjectsCount(cnrID string, objectType string, value uint64) + // IncRefillObjectsCount increments refill objects count. + IncRefillObjectsCount(path string, size int, success bool) + // SetRefillPercent sets refill percent. + SetRefillPercent(path string, percent uint32) + // SetRefillStatus sets refill status. + SetRefillStatus(path string, status string) } type cfg struct { diff --git a/pkg/metrics/engine.go b/pkg/metrics/engine.go index 4cc5424703..e37777e409 100644 --- a/pkg/metrics/engine.go +++ b/pkg/metrics/engine.go @@ -1,6 +1,7 @@ package metrics import ( + "strconv" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -23,6 +24,9 @@ type EngineMetrics interface { SetContainerObjectCounter(shardID, contID, objectType string, v uint64) IncContainerObjectCounter(shardID, contID, objectType string) SubContainerObjectCounter(shardID, contID, objectType string, v uint64) + IncRefillObjectsCount(shardID, path string, size int, success bool) + SetRefillPercent(shardID, path string, percent uint32) + SetRefillStatus(shardID, path, status string) WriteCache() WriteCacheMetrics GC() GCMetrics @@ -37,6 +41,11 @@ type engineMetrics struct { mode *shardIDModeValue contObjCounter *prometheus.GaugeVec + refillStatus *shardIDPathModeValue + refillObjCounter *prometheus.GaugeVec + refillPayloadCounter *prometheus.GaugeVec + refillPercentCounter *prometheus.GaugeVec + gc *gcMetrics writeCache *writeCacheMetrics } @@ -55,10 +64,14 @@ func newEngineMetrics() *engineMetrics { objectCounter: newEngineGaugeVector("objects_total", "Objects counters per shards. DEPRECATED: Will be deleted in next releasese, use frostfs_node_engine_container_objects_total metric.", []string{shardIDLabel, typeLabel}), - gc: newGCMetrics(), - writeCache: newWriteCacheMetrics(), - mode: newShardIDMode(engineSubsystem, "mode_info", "Shard mode"), - contObjCounter: newEngineGaugeVector("container_objects_total", "Count of objects for each container", []string{shardIDLabel, containerIDLabelKey, typeLabel}), + gc: newGCMetrics(), + writeCache: newWriteCacheMetrics(), + mode: newShardIDMode(engineSubsystem, "mode_info", "Shard mode"), + contObjCounter: newEngineGaugeVector("container_objects_total", "Count of objects for each container", []string{shardIDLabel, containerIDLabelKey, typeLabel}), + refillStatus: newShardIDPathMode(engineSubsystem, "resync_metabase_status", "Resync from blobstore to metabase status"), + refillObjCounter: newEngineGaugeVector("resync_metabase_objects_total", "Count of objects resynced from blobstore to metabase", []string{shardIDLabel, pathLabel, successLabel}), + refillPayloadCounter: newEngineGaugeVector("resync_metabase_objects_size_bytes", "Size of objects resynced from blobstore to metabase", []string{shardIDLabel, pathLabel, successLabel}), + refillPercentCounter: newEngineGaugeVector("resync_metabase_complete_percent", "Percent of resynced from blobstore to metabase completeness", []string{shardIDLabel, pathLabel}), } } @@ -106,7 +119,11 @@ func (m *engineMetrics) DeleteShardMetrics(shardID string) { m.payloadSize.Delete(prometheus.Labels{shardIDLabel: shardID}) m.objectCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) m.contObjCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) + m.refillObjCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) + m.refillPayloadCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) + m.refillPercentCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) m.mode.Delete(shardID) + m.refillStatus.DeleteByShardID(shardID) } func (m *engineMetrics) AddToObjectCounter(shardID, objectType string, delta int) { @@ -168,3 +185,31 @@ func (m *engineMetrics) WriteCache() WriteCacheMetrics { func (m *engineMetrics) GC() GCMetrics { return m.gc } + +func (m *engineMetrics) IncRefillObjectsCount(shardID, path string, size int, success bool) { + m.refillObjCounter.With( + prometheus.Labels{ + shardIDLabel: shardID, + pathLabel: path, + successLabel: strconv.FormatBool(success), + }, + ).Inc() + m.refillPayloadCounter.With( + prometheus.Labels{ + shardIDLabel: shardID, + pathLabel: path, + successLabel: strconv.FormatBool(success), + }, + ).Add(float64(size)) +} + +func (m *engineMetrics) SetRefillPercent(shardID, path string, percent uint32) { + m.refillPercentCounter.With(prometheus.Labels{ + shardIDLabel: shardID, + pathLabel: path, + }).Set(float64(percent)) +} + +func (m *engineMetrics) SetRefillStatus(shardID, path, status string) { + m.refillStatus.SetMode(shardID, path, status) +} diff --git a/pkg/metrics/mode.go b/pkg/metrics/mode.go index 312a6b33d8..cf6bdac48a 100644 --- a/pkg/metrics/mode.go +++ b/pkg/metrics/mode.go @@ -74,6 +74,12 @@ func (m *shardIDPathModeValue) Delete(shardID, path string) { }) } +func (m *shardIDPathModeValue) DeleteByShardID(shardID string) { + m.modeValue.DeletePartialMatch(prometheus.Labels{ + shardIDLabel: shardID, + }) +} + func modeFromBool(readOnly bool) string { modeValue := readWriteMode if readOnly { From 43fdb1da453cee28a5b6726d1d8bbc15708fe714 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 14:15:42 +0300 Subject: [PATCH 0492/1413] Reapply "[#972] go.mod: Bump go version to go1.21" This reverts commit 9adcb253be772bfc4f716307c564ac1f0545f85c. Signed-off-by: Evgenii Stratonikov --- .docker/Dockerfile.adm | 2 +- .docker/Dockerfile.ci | 2 +- .docker/Dockerfile.cli | 2 +- .docker/Dockerfile.ir | 2 +- .docker/Dockerfile.storage | 2 +- .forgejo/workflows/build.yml | 2 +- .forgejo/workflows/dco.yml | 2 +- .forgejo/workflows/tests.yml | 6 +++--- .forgejo/workflows/vulncheck.yml | 2 +- Makefile | 2 +- README.md | 2 +- go.mod | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.docker/Dockerfile.adm b/.docker/Dockerfile.adm index eeccaab79c..b3dad06d3d 100644 --- a/.docker/Dockerfile.adm +++ b/.docker/Dockerfile.adm @@ -1,4 +1,4 @@ -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ci b/.docker/Dockerfile.ci index ef6586a641..e9077c8313 100644 --- a/.docker/Dockerfile.ci +++ b/.docker/Dockerfile.ci @@ -1,4 +1,4 @@ -FROM golang:1.21 +FROM golang:1.22 WORKDIR /tmp diff --git a/.docker/Dockerfile.cli b/.docker/Dockerfile.cli index 0dd4cebcf9..5adedc1408 100644 --- a/.docker/Dockerfile.cli +++ b/.docker/Dockerfile.cli @@ -1,4 +1,4 @@ -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ir b/.docker/Dockerfile.ir index 4015df6733..25025bb2fa 100644 --- a/.docker/Dockerfile.ir +++ b/.docker/Dockerfile.ir @@ -1,4 +1,4 @@ -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.storage b/.docker/Dockerfile.storage index ced6ea538e..a16005516a 100644 --- a/.docker/Dockerfile.storage +++ b/.docker/Dockerfile.storage @@ -1,4 +1,4 @@ -FROM golang:1.21 as builder +FROM golang:1.22 as builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 3c74d94347..86943fe88c 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.20', '1.21' ] + go_versions: [ '1.21', '1.22' ] steps: - uses: actions/checkout@v3 diff --git a/.forgejo/workflows/dco.yml b/.forgejo/workflows/dco.yml index 9aa0d31066..7c5af8410b 100644 --- a/.forgejo/workflows/dco.yml +++ b/.forgejo/workflows/dco.yml @@ -13,7 +13,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' - name: Run commit format checker uses: https://git.frostfs.info/TrueCloudLab/dco-go@v3 diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index 449af3f518..b0c9adbf27 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' cache: true - name: Install linters @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.20', '1.21' ] + go_versions: [ '1.21', '1.22' ] fail-fast: false steps: - uses: actions/checkout@v3 @@ -63,7 +63,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' cache: true - name: Install staticcheck diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index 8ea01749b2..3af564c4b5 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -13,7 +13,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' - name: Install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest diff --git a/Makefile b/Makefile index fbf93facd0..710c12703d 100755 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 HUB_IMAGE ?= truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" -GO_VERSION ?= 1.21 +GO_VERSION ?= 1.22 LINT_VERSION ?= 1.56.1 TRUECLOUDLAB_LINT_VERSION ?= 0.0.5 PROTOC_VERSION ?= 25.0 diff --git a/README.md b/README.md index ecd162a855..413010372b 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The latest version of frostfs-node works with frostfs-contract # Building -To make all binaries you need Go 1.20+ and `make`: +To make all binaries you need Go 1.21+ and `make`: ``` make all ``` diff --git a/go.mod b/go.mod index f940b306ae..b99799337b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.frostfs.info/TrueCloudLab/frostfs-node -go 1.20 +go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 From d864945961e8d773e9123ce4faafaa33c3a7ee57 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 14:15:48 +0300 Subject: [PATCH 0493/1413] Reapply "[#972] pilorama: Remove removeDuplicatesInPlace()" This reverts commit 9f68305c2e88b1aea294ac3e75b75038151534e1. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/batch.go | 15 +--- .../pilorama/batch_test.go | 70 ------------------- 2 files changed, 2 insertions(+), 83 deletions(-) delete mode 100644 pkg/local_object_storage/pilorama/batch_test.go diff --git a/pkg/local_object_storage/pilorama/batch.go b/pkg/local_object_storage/pilorama/batch.go index c65488b74d..520c6dfb48 100644 --- a/pkg/local_object_storage/pilorama/batch.go +++ b/pkg/local_object_storage/pilorama/batch.go @@ -2,6 +2,7 @@ package pilorama import ( "encoding/binary" + "slices" "sort" "sync" "time" @@ -50,7 +51,7 @@ func (b *batch) run() { sort.Slice(b.operations, func(i, j int) bool { return b.operations[i].Time < b.operations[j].Time }) - b.operations = removeDuplicatesInPlace(b.operations) + b.operations = slices.CompactFunc(b.operations, func(x, y *Move) bool { return x.Time == y.Time }) // Our main use-case is addition of new items. In this case, // we do not need to perform undo()/redo(), just do(). @@ -115,15 +116,3 @@ func (b *batch) run() { b.results[i] <- err } } - -func removeDuplicatesInPlace(a []*Move) []*Move { - equalCount := 0 - for i := 1; i < len(a); i++ { - if a[i].Time == a[i-1].Time { - equalCount++ - } else { - a[i-equalCount] = a[i] - } - } - return a[:len(a)-equalCount] -} diff --git a/pkg/local_object_storage/pilorama/batch_test.go b/pkg/local_object_storage/pilorama/batch_test.go deleted file mode 100644 index 931fce18cd..0000000000 --- a/pkg/local_object_storage/pilorama/batch_test.go +++ /dev/null @@ -1,70 +0,0 @@ -package pilorama - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func Test_removeDuplicatesInPlace(t *testing.T) { - testCases := []struct { - before []int - after []int - }{ - { - before: []int{}, - after: []int{}, - }, - { - before: []int{1}, - after: []int{1}, - }, - { - before: []int{1, 2}, - after: []int{1, 2}, - }, - { - before: []int{1, 2, 3}, - after: []int{1, 2, 3}, - }, - { - before: []int{1, 1, 2}, - after: []int{1, 2}, - }, - { - before: []int{1, 2, 2}, - after: []int{1, 2}, - }, - { - before: []int{1, 2, 2, 3}, - after: []int{1, 2, 3}, - }, - { - before: []int{1, 1, 1}, - after: []int{1}, - }, - { - before: []int{1, 1, 2, 2}, - after: []int{1, 2}, - }, - { - before: []int{1, 1, 1, 2, 3, 3, 3}, - after: []int{1, 2, 3}, - }, - } - - for _, tc := range testCases { - ops := make([]*Move, len(tc.before)) - for i := range ops { - ops[i] = &Move{Meta: Meta{Time: Timestamp(tc.before[i])}} - } - - expected := make([]*Move, len(tc.after)) - for i := range expected { - expected[i] = &Move{Meta: Meta{Time: Timestamp(tc.after[i])}} - } - - actual := removeDuplicatesInPlace(ops) - require.Equal(t, expected, actual, "%d", tc.before) - } -} From 3dc81cb4fcfb8080259115a4649afcec61810630 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 14:16:18 +0300 Subject: [PATCH 0494/1413] Reapply "[#972] Use min/max builtins" This reverts commit dad56d2e98179904a9b263103ad04794202a7c1f. Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize/initialize_register.go | 5 +---- pkg/innerring/processors/netmap/cleanup_table.go | 5 +---- pkg/local_object_storage/blobovnicza/iterate.go | 8 -------- pkg/local_object_storage/engine/list.go | 5 +---- pkg/local_object_storage/shard/gc.go | 12 ++---------- pkg/morph/client/notary.go | 6 +----- pkg/services/object/internal/client/client.go | 5 +---- pkg/services/object/transport_splitter.go | 5 +---- pkg/services/policer/policer_test.go | 5 +---- pkg/services/tree/sync.go | 8 ++------ 10 files changed, 11 insertions(+), 53 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index 6a0a880167..4c6607f9a7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -100,10 +100,7 @@ func registerCandidates(c *helper.InitializeContext) error { // Register candidates in batches in order to overcome the signers amount limit. // See: https://github.com/nspcc-dev/neo-go/blob/master/pkg/core/transaction/transaction.go#L27 for i := 0; i < need; i += registerBatchSize { - start, end := i, i+registerBatchSize - if end > need { - end = need - } + start, end := i, min(i+registerBatchSize, need) // This check is sound because transactions are accepted/rejected atomically. if have >= end { continue diff --git a/pkg/innerring/processors/netmap/cleanup_table.go b/pkg/innerring/processors/netmap/cleanup_table.go index 705e21d99e..c18611569e 100644 --- a/pkg/innerring/processors/netmap/cleanup_table.go +++ b/pkg/innerring/processors/netmap/cleanup_table.go @@ -82,10 +82,7 @@ func (c *cleanupTable) touch(keyString string, now uint64, binNodeInfo []byte) b result := !ok || access.removeFlag || !bytes.Equal(access.binNodeInfo, binNodeInfo) access.removeFlag = false // reset remove flag on each touch - if now > access.epoch { - access.epoch = now - } - + access.epoch = max(access.epoch, now) access.binNodeInfo = binNodeInfo // update binary node info c.lastAccess[keyString] = access diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index b1cb919202..01e5529dae 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -57,14 +57,6 @@ func (b *Blobovnicza) iterateBounds(useObjLimitBound bool, f func(uint64, uint64 return nil } -func max(a, b uint64) uint64 { - if a > b { - return a - } - - return b -} - // IterationElement represents a unit of elements through which Iterate operation passes. type IterationElement struct { addr oid.Address diff --git a/pkg/local_object_storage/engine/list.go b/pkg/local_object_storage/engine/list.go index f9229a2b10..7245caeebc 100644 --- a/pkg/local_object_storage/engine/list.go +++ b/pkg/local_object_storage/engine/list.go @@ -134,10 +134,7 @@ func (e *StorageEngine) ListWithCursor(ctx context.Context, prm ListWithCursorPr continue } - count := prm.count - uint32(len(result)) - if count > batchSize { - count = batchSize - } + count := min(prm.count-uint32(len(result)), batchSize) var shardPrm shard.ListWithCursorPrm shardPrm.WithCount(count) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 83be3259a8..ef8e97d34a 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -343,16 +343,8 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { } func (s *Shard) getExpiredObjectsParameters() (workerCount, batchSize int) { - workerCount = minExpiredWorkers - batchSize = minExpiredBatchSize - - if s.gc.gcCfg.expiredCollectorBatchSize > batchSize { - batchSize = s.gc.gcCfg.expiredCollectorBatchSize - } - - if s.gc.gcCfg.expiredCollectorWorkerCount > workerCount { - workerCount = s.gc.gcCfg.expiredCollectorWorkerCount - } + workerCount = max(minExpiredWorkers, s.gc.gcCfg.expiredCollectorWorkerCount) + batchSize = max(minExpiredBatchSize, s.gc.gcCfg.expiredCollectorBatchSize) return } diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 1665fec1de..4865b43ef1 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -162,11 +162,7 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin return util.Uint256{}, fmt.Errorf("can't get previous expiration value: %w", err) } - till := int64(bc + delta) - if till < currentTill { - till = currentTill - } - + till := max(int64(bc+delta), currentTill) return c.depositNotary(amount, till) } diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index 4634c96e17..2c405070d0 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -343,10 +343,7 @@ func PayloadRange(ctx context.Context, prm PayloadRangePrm) (*PayloadRangeRes, e return nil, new(apistatus.ObjectOutOfRange) } - ln := prm.ln - if ln > maxInitialBufferSize { - ln = maxInitialBufferSize - } + ln := min(prm.ln, maxInitialBufferSize) w := bytes.NewBuffer(make([]byte, 0, ln)) _, err = io.CopyN(w, rdr, int64(prm.ln)) diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index 2d9810cd38..54e49cb129 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -164,10 +164,7 @@ func (s *searchStreamMsgSizeCtrl) Send(resp *object.SearchResponse) error { newResp.SetBody(body) } - cut := s.addrAmount - if cut > ln { - cut = ln - } + cut := min(s.addrAmount, ln) body.SetIDList(ids[:cut]) newResp.SetMetaHeader(resp.GetMetaHeader()) diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 50f206fd9a..be0974c39a 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -388,10 +388,7 @@ func (it *sliceKeySpaceIterator) Next(_ context.Context, size uint32) ([]objectc if it.cur >= len(it.objs) { return nil, engine.ErrEndOfListing } - end := it.cur + int(size) - if end > len(it.objs) { - end = len(it.objs) - } + end := min(it.cur+int(size), len(it.objs)) ret := it.objs[it.cur:end] it.cur = end return ret, nil diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 064ee5900b..0f85f50b12 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -167,9 +167,7 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram merged <- ms[minTimeMoveIndex] height := ms[minTimeMoveIndex].Time if ms[minTimeMoveIndex] = <-streams[minTimeMoveIndex]; ms[minTimeMoveIndex] == nil { - if minStreamedLastHeight > height { - minStreamedLastHeight = height - } + minStreamedLastHeight = min(minStreamedLastHeight, height) } } @@ -203,9 +201,7 @@ func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID s errGroup.Go(func() error { if err := s.forest.TreeApply(ctx, cid, treeID, m, true); err != nil { heightMtx.Lock() - if m.Time < unappliedOperationHeight { - unappliedOperationHeight = m.Time - } + unappliedOperationHeight = min(unappliedOperationHeight, m.Time) heightMtx.Unlock() return err } From 2ca5dfc2f60a5174c8077d4bbc3f5d7963b0f158 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 14:15:56 +0300 Subject: [PATCH 0495/1413] Reapply "[#972] Adopt slices.BinarySearch()" This reverts commit 4bfc6d29b910bc8e85852180ca0caabbf2eff2f4. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/container/container.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index 690db2f4f2..eda388d37c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "slices" "sort" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" @@ -446,7 +447,7 @@ func getCIDFilterFunc(cmd *cobra.Command) (func([]byte) bool, error) { var id cid.ID id.SetSHA256(v) idStr := id.EncodeToString() - n := sort.Search(len(rawIDs), func(i int) bool { return rawIDs[i] >= idStr }) - return n < len(rawIDs) && rawIDs[n] == idStr + _, found := slices.BinarySearch(rawIDs, idStr) + return found }, nil } From 2c4b50a71ed9eaf23a34fe0c327249fc60391cf7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 14:15:57 +0300 Subject: [PATCH 0496/1413] Reapply "[#972] Use require.ElementsMatch() where possible" This reverts commit 7627d08914ab4cfa6fd73f17e586f4b0f1a0bbc1. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/list_test.go | 12 +----------- .../metabase/containers_test.go | 12 +----------- pkg/local_object_storage/metabase/list_test.go | 14 +------------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 7bb1ac0fac..4fc9569c7b 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -3,7 +3,6 @@ package engine import ( "context" "path/filepath" - "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -18,13 +17,6 @@ import ( "github.com/stretchr/testify/require" ) -func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { - sort.Slice(addrWithType, func(i, j int) bool { - return addrWithType[i].Address.EncodeToString() < addrWithType[j].Address.EncodeToString() - }) - return addrWithType -} - func TestListWithCursor(t *testing.T) { t.Parallel() @@ -98,7 +90,6 @@ func TestListWithCursor(t *testing.T) { require.NoError(t, err) expected = append(expected, object.AddressWithType{Type: objectSDK.TypeRegular, Address: object.AddressOf(obj)}) } - expected = sortAddresses(expected) var prm ListWithCursorPrm prm.count = tt.batchSize @@ -113,8 +104,7 @@ func TestListWithCursor(t *testing.T) { prm.cursor = res.Cursor() } - got = sortAddresses(got) - require.Equal(t, expected, got) + require.ElementsMatch(t, expected, got) }) } } diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index a90cd9d972..5d6788d7e9 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -3,7 +3,6 @@ package meta_test import ( "context" "math/rand" - "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -108,18 +107,9 @@ func TestDB_ContainersCount(t *testing.T) { } } - sort.Slice(expected, func(i, j int) bool { - return expected[i].EncodeToString() < expected[j].EncodeToString() - }) - got, err := db.Containers(context.Background()) require.NoError(t, err) - - sort.Slice(got, func(i, j int) bool { - return got[i].EncodeToString() < got[j].EncodeToString() - }) - - require.Equal(t, expected, got) + require.ElementsMatch(t, expected, got) } func TestDB_ContainerSize(t *testing.T) { diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 25c0e35bd2..e1ccb4e06f 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -3,7 +3,6 @@ package meta_test import ( "context" "errors" - "sort" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -128,8 +127,6 @@ func TestLisObjectsWithCursor(t *testing.T) { expected = append(expected, object.AddressWithType{Address: object.AddressOf(child), Type: objectSDK.TypeRegular}) } - expected = sortAddresses(expected) - t.Run("success with various count", func(t *testing.T) { for countPerReq := 1; countPerReq <= total; countPerReq++ { got := make([]object.AddressWithType, 0, total) @@ -151,9 +148,7 @@ func TestLisObjectsWithCursor(t *testing.T) { _, _, err = metaListWithCursor(db, uint32(countPerReq), cursor) require.ErrorIs(t, err, meta.ErrEndOfListing, "count:%d", countPerReq, cursor) - - got = sortAddresses(got) - require.Equal(t, expected, got, "count:%d", countPerReq) + require.ElementsMatch(t, expected, got, "count:%d", countPerReq) } }) @@ -216,13 +211,6 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { } } -func sortAddresses(addrWithType []object.AddressWithType) []object.AddressWithType { - sort.Slice(addrWithType, func(i, j int) bool { - return addrWithType[i].Address.EncodeToString() < addrWithType[j].Address.EncodeToString() - }) - return addrWithType -} - func metaListWithCursor(db *meta.DB, count uint32, cursor *meta.Cursor) ([]object.AddressWithType, *meta.Cursor, error) { var listPrm meta.ListPrm listPrm.SetCount(count) From 669103a33efc1ddedee847689e74c82441dc9916 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 14:15:59 +0300 Subject: [PATCH 0497/1413] Reapply "[#972] Use slices.Sort* when useful" This reverts commit 3359349acbbfb0aa8e208c5286ff7bd6537df2be. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/control/shards_set_mode.go | 7 ++----- pkg/services/tree/getsubtree_test.go | 6 ++---- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/shards_set_mode.go b/cmd/frostfs-cli/modules/control/shards_set_mode.go index 1c87b405b0..e73f15178c 100644 --- a/cmd/frostfs-cli/modules/control/shards_set_mode.go +++ b/cmd/frostfs-cli/modules/control/shards_set_mode.go @@ -3,7 +3,7 @@ package control import ( "bytes" "fmt" - "sort" + "slices" "strings" rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" @@ -177,9 +177,6 @@ func getShardIDListFromIDFlag(cmd *cobra.Command, withAllFlag bool) [][]byte { res = append(res, raw) } - sort.Slice(res, func(i, j int) bool { - return bytes.Compare(res[i], res[j]) < 0 - }) - + slices.SortFunc(res, bytes.Compare) return res } diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 9a4223e30e..305c2bac94 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -5,7 +5,7 @@ import ( "errors" "path" "path/filepath" - "sort" + "slices" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" @@ -192,9 +192,7 @@ func testGetSubTreeOrderAsc(t *testing.T, p pilorama.ForestStorage) { require.True(t, found, "unknown node %d %v", i, acc.seen[i].GetBody().GetNodeId()) } - require.True(t, sort.SliceIsSorted(paths, func(i, j int) bool { - return paths[i] < paths[j] - })) + require.True(t, slices.IsSorted(paths)) }) t.Run("depth=1", func(t *testing.T) { acc := subTreeAcc{errIndex: -1} From 5ef5734c4e2e0011506dca04086ab27c4028fafa Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 14:16:00 +0300 Subject: [PATCH 0498/1413] Reapply "[#972] Drop x/exp/slices dependency" This reverts commit 946f2ec2bf4b5e99726811ac8bcb225bbca0708f. Signed-off-by: Evgenii Stratonikov --- go.sum | 14 ++++++++++++++ pkg/innerring/processors/frostfs/handlers.go | 2 +- .../internal/testutil/generators_test.go | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/go.sum b/go.sum index 7f7e843986..66273b1744 100644 --- a/go.sum +++ b/go.sum @@ -59,9 +59,11 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etly github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= @@ -96,6 +98,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -137,19 +140,24 @@ github.com/klauspost/reedsolomon v1.12.1 h1:NhWgum1efX1x58daOBGCFWcxtEhOhXKKl1HA github.com/klauspost/reedsolomon v1.12.1/go.mod h1:nEi5Kjb6QqtbofI6s+cbG/j1da11c96IBYBSnVGtuBs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= @@ -231,6 +239,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -307,6 +316,7 @@ go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40 go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -327,6 +337,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -403,12 +414,14 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= @@ -429,6 +442,7 @@ google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHh gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= diff --git a/pkg/innerring/processors/frostfs/handlers.go b/pkg/innerring/processors/frostfs/handlers.go index 5782dc7441..c80f9fdc51 100644 --- a/pkg/innerring/processors/frostfs/handlers.go +++ b/pkg/innerring/processors/frostfs/handlers.go @@ -3,13 +3,13 @@ package frostfs import ( "bytes" "encoding/hex" + "slices" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" "go.uber.org/zap" - "golang.org/x/exp/slices" ) func (np *Processor) handleDeposit(ev event.Event) { diff --git a/pkg/local_object_storage/internal/testutil/generators_test.go b/pkg/local_object_storage/internal/testutil/generators_test.go index f2c60f9b4d..f7be6014d6 100644 --- a/pkg/local_object_storage/internal/testutil/generators_test.go +++ b/pkg/local_object_storage/internal/testutil/generators_test.go @@ -2,10 +2,10 @@ package testutil import ( "encoding/binary" + "slices" "testing" "github.com/stretchr/testify/require" - "golang.org/x/exp/slices" ) func TestOverwriteObjGenerator(t *testing.T) { From 40781b3a20240185b2b76e6fc676196ded1d9395 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 10 Apr 2024 11:49:31 +0300 Subject: [PATCH 0499/1413] [#1086] engine: Change mode in case of errors async Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/engine.go | 33 ++++++++----------- pkg/local_object_storage/engine/error_test.go | 7 ++-- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 558fe92ed2..b8ac6cf975 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -133,7 +133,7 @@ func (e *StorageEngine) reportShardErrorBackground(id string, msg string, err er errCount := sh.errorCount.Add(1) sh.Shard.IncErrorCounter() - e.reportShardErrorWithFlags(sh.Shard, errCount, false, msg, err) + e.reportShardErrorWithFlags(sh.Shard, errCount, msg, err) } // reportShardError checks that the amount of errors doesn't exceed the configured threshold. @@ -153,13 +153,12 @@ func (e *StorageEngine) reportShardError( errCount := sh.errorCount.Add(1) sh.Shard.IncErrorCounter() - e.reportShardErrorWithFlags(sh.Shard, errCount, true, msg, err, fields...) + e.reportShardErrorWithFlags(sh.Shard, errCount, msg, err, fields...) } func (e *StorageEngine) reportShardErrorWithFlags( sh *shard.Shard, errCount uint32, - block bool, msg string, err error, fields ...zap.Field, @@ -175,23 +174,19 @@ func (e *StorageEngine) reportShardErrorWithFlags( return } - if block { - e.moveToDegraded(sh, errCount) - } else { - req := setModeRequest{ - errorCount: errCount, - sh: sh, - } + req := setModeRequest{ + errorCount: errCount, + sh: sh, + } - select { - case e.setModeCh <- req: - default: - // For background workers we can have a lot of such errors, - // thus logging is done with DEBUG level. - e.log.Debug(logs.EngineModeChangeIsInProgressIgnoringSetmodeRequest, - zap.Stringer("shard_id", sid), - zap.Uint32("error_count", errCount)) - } + select { + case e.setModeCh <- req: + default: + // For background workers we can have a lot of such errors, + // thus logging is done with DEBUG level. + e.log.Debug(logs.EngineModeChangeIsInProgressIgnoringSetmodeRequest, + zap.Stringer("shard_id", sid), + zap.Uint32("error_count", errCount)) } } diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index ec4287bdd7..6c44966f23 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -7,6 +7,7 @@ import ( "path/filepath" "strconv" "testing" + "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" @@ -229,6 +230,8 @@ func checkShardState(t *testing.T, e *StorageEngine, id *shard.ID, errCount uint sh := e.shards[id.String()] e.mtx.RUnlock() - require.Equal(t, errCount, sh.errorCount.Load()) - require.Equal(t, mode, sh.GetMode()) + require.Eventually(t, func() bool { + return errCount == sh.errorCount.Load() && + mode == sh.GetMode() + }, 10*time.Second, 10*time.Millisecond, "shard mode doesn't changed to expected state in 10 seconds") } From cdae227f82b6aeba684e3efdd66c881d66c2cd65 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 10 Apr 2024 15:26:39 +0300 Subject: [PATCH 0500/1413] [#1083] go.mod: Bump grpc version Signed-off-by: Anton Nikiforov --- go.mod | 7 +++---- go.sum | 18 ++++++++---------- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index b99799337b..4d497b0f99 100644 --- a/go.mod +++ b/go.mod @@ -42,7 +42,7 @@ require ( golang.org/x/sync v0.6.0 golang.org/x/sys v0.18.0 golang.org/x/term v0.18.0 - google.golang.org/grpc v1.61.0 + google.golang.org/grpc v1.63.2 google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -71,7 +71,6 @@ require ( github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect @@ -125,8 +124,8 @@ require ( golang.org/x/crypto v0.21.0 // indirect golang.org/x/net v0.23.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 66273b1744..6c945172e7 100644 --- a/go.sum +++ b/go.sum @@ -87,8 +87,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -420,14 +418,14 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU= -google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= +google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 661faa639e8c3d54dfd1888d0b2d0a9f8f83ce90 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 11 Apr 2024 11:53:01 +0300 Subject: [PATCH 0501/1413] [#1090] go.mod: Update policy-engine version Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 4d497b0f99..7f9c9d4577 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92 git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 6c945172e7..83bb5818d3 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92/go.mod h1:i0RKqiF4z3UOxLSNwhHw+cUz/JyYWuTRpnn9ere4Y3w= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd h1:pyIl9f4nIr7ekJ73W9keLIQ5dpoKb8o6xNmodsXY5+o= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240307151106-2ec958cbfdfd/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec h1:OG8tBs5CN2HKp10sAWdtiFaX8qSGFyLGWfQmf4FQ6bE= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= From f4dcb418f2bf7d733247a6dfd751744309a5a79f Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 11 Apr 2024 12:35:49 +0300 Subject: [PATCH 0502/1413] [#1090] ape: Move ape request and resource implementations to common package Signed-off-by: Airat Arifullin --- pkg/ape/converter/converter.go | 44 +++++++++++++ pkg/ape/request/request.go | 55 ++++++++++++++++ pkg/services/container/ape.go | 84 ++++++++----------------- pkg/services/object/ape/request.go | 57 ++++------------- pkg/services/object/ape/request_test.go | 18 +++--- 5 files changed, 144 insertions(+), 114 deletions(-) create mode 100644 pkg/ape/converter/converter.go create mode 100644 pkg/ape/request/request.go diff --git a/pkg/ape/converter/converter.go b/pkg/ape/converter/converter.go new file mode 100644 index 0000000000..9032680af6 --- /dev/null +++ b/pkg/ape/converter/converter.go @@ -0,0 +1,44 @@ +package converter + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" +) + +func SchemaRoleFromACLRole(role acl.Role) (string, error) { + switch role { + case acl.RoleOwner: + return nativeschema.PropertyValueContainerRoleOwner, nil + case acl.RoleContainer: + return nativeschema.PropertyValueContainerRoleContainer, nil + case acl.RoleInnerRing: + return nativeschema.PropertyValueContainerRoleIR, nil + case acl.RoleOthers: + return nativeschema.PropertyValueContainerRoleOthers, nil + default: + return "", fmt.Errorf("failed to convert %s", role.String()) + } +} + +func SchemaMethodFromACLOperation(op acl.Op) (string, error) { + switch op { + case acl.OpObjectGet: + return nativeschema.MethodGetObject, nil + case acl.OpObjectHead: + return nativeschema.MethodHeadObject, nil + case acl.OpObjectPut: + return nativeschema.MethodPutObject, nil + case acl.OpObjectDelete: + return nativeschema.MethodDeleteObject, nil + case acl.OpObjectSearch: + return nativeschema.MethodSearchObject, nil + case acl.OpObjectRange: + return nativeschema.MethodRangeObject, nil + case acl.OpObjectHash: + return nativeschema.MethodHashObject, nil + default: + return "", fmt.Errorf("operation cannot be converted: %d", op) + } +} diff --git a/pkg/ape/request/request.go b/pkg/ape/request/request.go new file mode 100644 index 0000000000..6d62ef3d55 --- /dev/null +++ b/pkg/ape/request/request.go @@ -0,0 +1,55 @@ +package ape + +import ( + aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" +) + +type Request struct { + operation string + resource Resource + properties map[string]string +} + +func NewRequest(operation string, resource Resource, properties map[string]string) Request { + return Request{ + operation: operation, + resource: resource, + properties: properties, + } +} + +var _ aperesource.Request = Request{} + +func (r Request) Operation() string { + return r.operation +} + +func (r Request) Property(key string) string { + return r.properties[key] +} + +func (r Request) Resource() aperesource.Resource { + return r.resource +} + +type Resource struct { + name string + properties map[string]string +} + +var _ aperesource.Resource = Resource{} + +func NewResource(name string, properties map[string]string) Resource { + return Resource{ + name: name, + properties: properties, + } +} + +func (r Resource) Name() string { + return r.name +} + +func (r Resource) Property(key string) string { + return r.properties[key] +} diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 83361257ad..7622a40bc7 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -15,6 +15,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -26,7 +27,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" - "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" @@ -148,14 +148,14 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co return nil, err } - request := &apeRequest{ - resource: &apeResource{ - name: resourceName(namespace, ""), - props: make(map[string]string), - }, - op: nativeschema.MethodListContainers, - props: reqProps, - } + request := aperequest.NewRequest( + nativeschema.MethodListContainers, + aperequest.NewResource( + resourceName(namespace, ""), + make(map[string]string), + ), + reqProps, + ) s, found, err := ac.router.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithNamespace(namespace), @@ -193,14 +193,14 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont return nil, err } - request := &apeRequest{ - resource: &apeResource{ - name: resourceName(namespace, ""), - props: make(map[string]string), - }, - op: nativeschema.MethodPutContainer, - props: reqProps, - } + request := aperequest.NewRequest( + nativeschema.MethodPutContainer, + aperequest.NewResource( + resourceName(namespace, ""), + make(map[string]string), + ), + reqProps, + ) s, found, err := ac.router.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithNamespace(namespace), @@ -288,14 +288,14 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai namespace = cntNamespace } - request := &apeRequest{ - resource: &apeResource{ - name: resourceName(namespace, id.EncodeToString()), - props: ac.getContainerProps(cont), - }, - op: op, - props: reqProps, - } + request := aperequest.NewRequest( + op, + aperequest.NewResource( + resourceName(namespace, id.EncodeToString()), + ac.getContainerProps(cont), + ), + reqProps, + ) s, found, err := ac.router.IsAllowed(apechain.Ingress, policyengine.NewRequestTarget(namespace, id.EncodeToString()), @@ -329,40 +329,6 @@ func getContainerID(reqContID *refs.ContainerID) (cid.ID, error) { return id, nil } -type apeRequest struct { - resource *apeResource - op string - props map[string]string -} - -// Operation implements resource.Request. -func (r *apeRequest) Operation() string { - return r.op -} - -// Property implements resource.Request. -func (r *apeRequest) Property(key string) string { - return r.props[key] -} - -// Resource implements resource.Request. -func (r *apeRequest) Resource() resource.Resource { - return r.resource -} - -type apeResource struct { - name string - props map[string]string -} - -func (r *apeResource) Name() string { - return r.name -} - -func (r *apeResource) Property(key string) string { - return r.props[key] -} - func resourceName(namespace string, container string) string { if namespace == "" && container == "" { return nativeschema.ResourceFormatRootContainers diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index b81fe8c323..7bbee31c1d 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -6,51 +6,16 @@ import ( "strconv" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) -type request struct { - operation string - resource resource - properties map[string]string -} - -var defaultRequest = request{} - -var _ aperesource.Request = request{} - -type resource struct { - name string - properties map[string]string -} - -var _ aperesource.Resource = resource{} - -func (r resource) Name() string { - return r.name -} - -func (r resource) Property(key string) string { - return r.properties[key] -} - -func (r request) Operation() string { - return r.operation -} - -func (r request) Property(key string) string { - return r.properties[key] -} - -func (r request) Resource() aperesource.Resource { - return r.resource -} +var defaultRequest = aperequest.Request{} func nativeSchemaRole(role acl.Role) string { switch role { @@ -125,7 +90,7 @@ func objectProperties(cnr cid.ID, oid *oid.ID, cnrOwner user.ID, header *objectV // newAPERequest creates an APE request to be passed to a chain router. It collects resource properties from // header provided by headerProvider. If it cannot be found in headerProvider, then properties are // initialized from header given in prm (if it is set). Otherwise, just CID and OID are set to properties. -func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (request, error) { +func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Request, error) { switch prm.Method { case nativeschema.MethodGetObject, nativeschema.MethodHeadObject, @@ -150,15 +115,15 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (request, erro } } - return request{ - operation: prm.Method, - resource: resource{ - name: resourceName(prm.Container, prm.Object, prm.Namespace), - properties: objectProperties(prm.Container, prm.Object, prm.ContainerOwner, header), - }, - properties: map[string]string{ + return aperequest.NewRequest( + prm.Method, + aperequest.NewResource( + resourceName(prm.Container, prm.Object, prm.Namespace), + objectProperties(prm.Container, prm.Object, prm.ContainerOwner, header), + ), + map[string]string{ nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, nativeschema.PropertyKeyActorRole: prm.Role, }, - }, nil + ), nil } diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index 71e234e78b..fdb7af2197 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -6,6 +6,7 @@ import ( "testing" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -256,22 +257,21 @@ func TestNewAPERequest(t *testing.T) { return } - expectedRequest := request{ - operation: method, - resource: resource{ - name: resourceName(cnr, obj, prm.Namespace), - properties: objectProperties(cnr, obj, testCnrOwner, func() *objectV2.Header { + expectedRequest := aperequest.NewRequest( + method, + aperequest.NewResource( + resourceName(cnr, obj, prm.Namespace), + objectProperties(cnr, obj, testCnrOwner, func() *objectV2.Header { if headerObjSDK != nil { return headerObjSDK.ToV2().GetHeader() } return prm.Header - }()), - }, - properties: map[string]string{ + }())), + map[string]string{ nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, nativeschema.PropertyKeyActorRole: prm.Role, }, - } + ) require.Equal(t, expectedRequest, r) }) From 6a46c6d2294d6e6e994fe53c8e0347c8cbbbec88 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 11 Apr 2024 18:10:33 +0300 Subject: [PATCH 0503/1413] [#1090] tree: Make workaround for APE checks * Make `verifyClient` method perform APE check if a container was created with zero-filled basic ACL. * Object verbs are used in APE, until tree verbs are introduced. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/tree.go | 4 +- pkg/services/tree/ape.go | 69 ++++++++++++++++++++++++++++++++++ pkg/services/tree/options.go | 9 +++++ pkg/services/tree/signature.go | 13 ++++--- 4 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 pkg/services/tree/ape.go diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index dced05bc2b..ff00b6fac9 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -63,7 +63,9 @@ func initTreeService(c *cfg) { tree.WithReplicationChannelCapacity(treeConfig.ReplicationChannelCapacity()), tree.WithReplicationWorkerCount(treeConfig.ReplicationWorkerCount()), tree.WithAuthorizedKeys(treeConfig.AuthorizedKeys()), - tree.WithMetrics(c.metricsCollector.TreeService())) + tree.WithMetrics(c.metricsCollector.TreeService()), + tree.WithAPERouter(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine), + ) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { tree.RegisterTreeServiceServer(s, c.treeService) diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go new file mode 100644 index 0000000000..52036074ac --- /dev/null +++ b/pkg/services/tree/ape.go @@ -0,0 +1,69 @@ +package tree + +import ( + "encoding/hex" + "fmt" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter" + aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" + core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error { + namespace := "" + cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns") + if hasNamespace { + namespace = cntNamespace + } + + schemaMethod, err := converter.SchemaMethodFromACLOperation(operation) + if err != nil { + return apeErr(err) + } + schemaRole, err := converter.SchemaRoleFromACLRole(role) + if err != nil { + return apeErr(err) + } + reqProps := map[string]string{ + nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(publicKey.Bytes()), + nativeschema.PropertyKeyActorRole: schemaRole, + } + + var resourceName string + if namespace == "root" || namespace == "" { + resourceName = fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cid.EncodeToString()) + } else { + resourceName = fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainerObjects, namespace, cid.EncodeToString()) + } + + request := aperequest.NewRequest( + schemaMethod, + aperequest.NewResource(resourceName, make(map[string]string)), + reqProps, + ) + + status, found, err := s.router.IsAllowed(apechain.Ingress, engine.NewRequestTarget(namespace, cid.EncodeToString()), request) + if err != nil { + return apeErr(err) + } + if found && status == apechain.Allow { + return nil + } + err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", schemaMethod, status.String()) + return apeErr(err) +} + +func apeErr(err error) error { + errAccessDenied := &apistatus.ObjectAccessDenied{} + errAccessDenied.WriteReason(err.Error()) + return errAccessDenied +} diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index 043e12cb2e..0e5f642747 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) @@ -38,6 +39,8 @@ type cfg struct { containerCacheSize int authorizedKeys [][]byte + router policyengine.ChainRouter + metrics MetricsRegister } @@ -139,3 +142,9 @@ func WithAuthorizedKeys(keys keys.PublicKeys) Option { } } } + +func WithAPERouter(router policyengine.ChainRouter) Option { + return func(c *cfg) { + c.router = router + } +} diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 985e1ad94a..162b189e3c 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -71,7 +71,7 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op return err } - role, err := roleFromReq(cnr, req, bt) + role, pubKey, err := roleAndPubKeyFromReq(cnr, req, bt) if err != nil { return fmt.Errorf("can't get request role: %w", err) } @@ -79,8 +79,11 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op basicACL := cnr.Value.BasicACL() // Basic ACL mask can be unset, if a container operations are performed // with strict APE checks only. + // + // FIXME(@aarifullin): tree service temporiraly performs APE checks on + // object verbs, because tree verbs have not been introduced yet. if basicACL == 0x0 { - return nil + return s.checkAPE(cnr, cid, op, role, pubKey) } if !basicACL.IsOpAllowed(op, role) { @@ -222,7 +225,7 @@ func SignMessage(m message, key *ecdsa.PrivateKey) error { return nil } -func roleFromReq(cnr *core.Container, req message, bt *bearer.Token) (acl.Role, error) { +func roleAndPubKeyFromReq(cnr *core.Container, req message, bt *bearer.Token) (acl.Role, *keys.PublicKey, error) { role := acl.RoleOthers owner := cnr.Value.Owner() @@ -233,7 +236,7 @@ func roleFromReq(cnr *core.Container, req message, bt *bearer.Token) (acl.Role, pub, err := keys.NewPublicKeyFromBytes(rawKey, elliptic.P256()) if err != nil { - return role, fmt.Errorf("invalid public key: %w", err) + return role, nil, fmt.Errorf("invalid public key: %w", err) } var reqSigner user.ID @@ -243,7 +246,7 @@ func roleFromReq(cnr *core.Container, req message, bt *bearer.Token) (acl.Role, role = acl.RoleOwner } - return role, nil + return role, pub, nil } func eACLOp(op acl.Op) eacl.Operation { From 5be36924e3ec84a7069ececa4b3e02212ce57c4e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 11:25:51 +0300 Subject: [PATCH 0504/1413] [#41] log: Log storage operations in only in Debug They are mostly useless unless we need to _debug_ a specific issue. The amount of logs we produce is too big. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/internal/log/log.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/internal/log/log.go b/pkg/local_object_storage/internal/log/log.go index 82024ffa7f..6272067d3d 100644 --- a/pkg/local_object_storage/internal/log/log.go +++ b/pkg/local_object_storage/internal/log/log.go @@ -10,7 +10,7 @@ const headMsg = "local object storage operation" // Write writes message about storage engine's operation to logger. func Write(logger *logger.Logger, fields ...zap.Field) { - logger.Info(headMsg, fields...) + logger.Debug(headMsg, fields...) } // AddressField returns logger's field for object address. From e5e0542482998f0e65cd811ce3ff331def189001 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Apr 2024 11:32:35 +0300 Subject: [PATCH 0505/1413] [#1085] log: Move storage log message to constants package Signed-off-by: Evgenii Stratonikov --- internal/logs/logs.go | 1 + pkg/local_object_storage/internal/log/log.go | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index d56d425ce1..bd67217c40 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -201,6 +201,7 @@ const ( SubscriberCantCastBlockEventValueToBlock = "can't cast block event value to block" SubscriberCantCastNotifyEventValueToTheNotaryRequestStruct = "can't cast notify event value to the notary request struct" SubscriberUnsupportedNotificationFromTheChain = "unsupported notification from the chain" + StorageOperation = "local object storage operation" BlobovniczaCreatingDirectoryForBoltDB = "creating directory for BoltDB" BlobovniczaOpeningBoltDB = "opening BoltDB" BlobovniczaInitializing = "initializing..." diff --git a/pkg/local_object_storage/internal/log/log.go b/pkg/local_object_storage/internal/log/log.go index 6272067d3d..23740868d7 100644 --- a/pkg/local_object_storage/internal/log/log.go +++ b/pkg/local_object_storage/internal/log/log.go @@ -1,16 +1,14 @@ package storagelog import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) -// headMsg is a distinctive part of all messages. -const headMsg = "local object storage operation" - // Write writes message about storage engine's operation to logger. func Write(logger *logger.Logger, fields ...zap.Field) { - logger.Debug(headMsg, fields...) + logger.Debug(logs.StorageOperation, fields...) } // AddressField returns logger's field for object address. From 91e79c98ba5805b3da5358f131a0b301c58b4633 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 11 Apr 2024 13:51:39 +0300 Subject: [PATCH 0506/1413] [#1089] ape: Provide request actor as an additional target Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- pkg/services/container/ape.go | 30 +++++++++++++++---------- pkg/services/object/ape/checker.go | 10 +++++++-- pkg/services/object/ape/checker_test.go | 5 ++++- pkg/services/tree/ape.go | 3 ++- 6 files changed, 35 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 7f9c9d4577..8cfea305db 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92 git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 83bb5818d3..76ed7e5dc9 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92/go.mod h1:i0RKqiF4z3UOxLSNwhHw+cUz/JyYWuTRpnn9ere4Y3w= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec h1:OG8tBs5CN2HKp10sAWdtiFaX8qSGFyLGWfQmf4FQ6bE= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240410114823-1f190e1668ec/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a h1:wbndKvHbwDQiSMQWL75RxiTZCeUyCi7NUj1lsfdAGkc= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 7622a40bc7..02549bdedb 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -157,9 +157,12 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co reqProps, ) - s, found, err := ac.router.IsAllowed(apechain.Ingress, - policyengine.NewRequestTargetWithNamespace(namespace), - request) + rt := policyengine.NewRequestTargetWithNamespace(namespace) + rt.User = &policyengine.Target{ + Type: policyengine.User, + Name: fmt.Sprintf("%s:%s", namespace, pk.Address()), + } + s, found, err := ac.router.IsAllowed(apechain.Ingress, rt, request) if err != nil { return nil, err } @@ -202,9 +205,12 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont reqProps, ) - s, found, err := ac.router.IsAllowed(apechain.Ingress, - policyengine.NewRequestTargetWithNamespace(namespace), - request) + rt := policyengine.NewRequestTargetWithNamespace(namespace) + rt.User = &policyengine.Target{ + Type: policyengine.User, + Name: fmt.Sprintf("%s:%s", namespace, pk.Address()), + } + s, found, err := ac.router.IsAllowed(apechain.Ingress, rt, request) if err != nil { return nil, err } @@ -277,7 +283,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai return err } - reqProps, err := ac.getRequestProps(mh, vh, cont, id) + reqProps, pk, err := ac.getRequestProps(mh, vh, cont, id) if err != nil { return err } @@ -298,7 +304,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai ) s, found, err := ac.router.IsAllowed(apechain.Ingress, - policyengine.NewRequestTarget(namespace, id.EncodeToString()), + policyengine.NewRequestTargetExtended(namespace, id.EncodeToString(), fmt.Sprintf("%s:%s", namespace, pk.Address()), nil), request) if err != nil { return err @@ -350,19 +356,19 @@ func (ac *apeChecker) getContainerProps(c *containercore.Container) map[string]s func (ac *apeChecker) getRequestProps(mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, cont *containercore.Container, cnrID cid.ID, -) (map[string]string, error) { +) (map[string]string, *keys.PublicKey, error) { actor, pk, err := ac.getActorAndPublicKey(mh, vh, cnrID) if err != nil { - return nil, err + return nil, nil, err } role, err := ac.getRole(actor, pk, cont, cnrID) if err != nil { - return nil, err + return nil, nil, err } return map[string]string{ nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(pk.Bytes()), nativeschema.PropertyKeyActorRole: role, - }, nil + }, pk, nil } func (ac *apeChecker) getRole(actor *user.ID, pk *keys.PublicKey, cont *containercore.Container, cnrID cid.ID) (string, error) { diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 119df5fc01..1063bd901b 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -12,6 +12,7 @@ import ( apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) type checkerImpl struct { @@ -84,8 +85,13 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { return fmt.Errorf("failed to create ape request: %w", err) } - status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, - policyengine.NewRequestTarget(prm.Namespace, prm.Container.EncodeToString()), r) + pub, err := keys.NewPublicKeyFromString(prm.SenderKey) + if err != nil { + return err + } + + rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), nil) + status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, rt, r) if err != nil { return err } diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 4434149596..fc915715c4 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -16,6 +16,7 @@ import ( policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) @@ -147,7 +148,9 @@ var ( role = "Container" - senderKey = hex.EncodeToString([]byte{1, 0, 0, 1}) + senderPrivateKey, _ = keys.NewPrivateKey() + + senderKey = hex.EncodeToString(senderPrivateKey.PublicKey().Bytes()) ) func TestAPECheck(t *testing.T) { diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 52036074ac..5da49a5913 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -51,7 +51,8 @@ func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl. reqProps, ) - status, found, err := s.router.IsAllowed(apechain.Ingress, engine.NewRequestTarget(namespace, cid.EncodeToString()), request) + rt := engine.NewRequestTargetExtended(namespace, cid.EncodeToString(), fmt.Sprintf("%s:%s", namespace, publicKey.Address()), nil) + status, found, err := s.router.IsAllowed(apechain.Ingress, rt, request) if err != nil { return apeErr(err) } From 00941862999ef79cc02fdeea720399bb89c3faaf Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 11 Apr 2024 17:01:19 +0300 Subject: [PATCH 0507/1413] [#1089] control: Format proto files with clang-format Signed-off-by: Evgenii Stratonikov --- pkg/services/control/service.proto | 786 ++++++++++++++--------------- pkg/services/control/types.proto | 223 ++++---- 2 files changed, 503 insertions(+), 506 deletions(-) diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 04ea62e0e5..94032b3467 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -6,658 +6,656 @@ import "pkg/services/control/types.proto"; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"; -// `ControlService` provides an interface for internal work with the storage node. +// `ControlService` provides an interface for internal work with the storage +// node. service ControlService { - // Performs health check of the storage node. - rpc HealthCheck (HealthCheckRequest) returns (HealthCheckResponse); + // Performs health check of the storage node. + rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse); - // Sets status of the storage node in FrostFS network map. - rpc SetNetmapStatus (SetNetmapStatusRequest) returns (SetNetmapStatusResponse); + // Sets status of the storage node in FrostFS network map. + rpc SetNetmapStatus(SetNetmapStatusRequest) returns (SetNetmapStatusResponse); - // Mark objects to be removed from node's local object storage. - rpc DropObjects (DropObjectsRequest) returns (DropObjectsResponse); + // Mark objects to be removed from node's local object storage. + rpc DropObjects(DropObjectsRequest) returns (DropObjectsResponse); - // Returns list that contains information about all shards of a node. - rpc ListShards (ListShardsRequest) returns (ListShardsResponse); + // Returns list that contains information about all shards of a node. + rpc ListShards(ListShardsRequest) returns (ListShardsResponse); - // Sets mode of the shard. - rpc SetShardMode (SetShardModeRequest) returns (SetShardModeResponse); + // Sets mode of the shard. + rpc SetShardMode(SetShardModeRequest) returns (SetShardModeResponse); - // Synchronizes all log operations for the specified tree. - rpc SynchronizeTree (SynchronizeTreeRequest) returns (SynchronizeTreeResponse); + // Synchronizes all log operations for the specified tree. + rpc SynchronizeTree(SynchronizeTreeRequest) returns (SynchronizeTreeResponse); - // EvacuateShard moves all data from one shard to the others. - // Deprecated: Use StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation - rpc EvacuateShard (EvacuateShardRequest) returns (EvacuateShardResponse); + // EvacuateShard moves all data from one shard to the others. + // Deprecated: Use + // StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation + rpc EvacuateShard(EvacuateShardRequest) returns (EvacuateShardResponse); - // StartShardEvacuation starts moving all data from one shard to the others. - rpc StartShardEvacuation (StartShardEvacuationRequest) returns (StartShardEvacuationResponse); + // StartShardEvacuation starts moving all data from one shard to the others. + rpc StartShardEvacuation(StartShardEvacuationRequest) + returns (StartShardEvacuationResponse); - // GetShardEvacuationStatus returns evacuation status. - rpc GetShardEvacuationStatus (GetShardEvacuationStatusRequest) returns (GetShardEvacuationStatusResponse); + // GetShardEvacuationStatus returns evacuation status. + rpc GetShardEvacuationStatus(GetShardEvacuationStatusRequest) + returns (GetShardEvacuationStatusResponse); - // ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process. - rpc ResetShardEvacuationStatus (ResetShardEvacuationStatusRequest) returns (ResetShardEvacuationStatusResponse); + // ResetShardEvacuationStatus resets evacuation status if there is no running + // evacuation process. + rpc ResetShardEvacuationStatus(ResetShardEvacuationStatusRequest) + returns (ResetShardEvacuationStatusResponse); - // StopShardEvacuation stops moving all data from one shard to the others. - rpc StopShardEvacuation (StopShardEvacuationRequest) returns (StopShardEvacuationResponse); + // StopShardEvacuation stops moving all data from one shard to the others. + rpc StopShardEvacuation(StopShardEvacuationRequest) + returns (StopShardEvacuationResponse); - // FlushCache moves all data from one shard to the others. - rpc FlushCache (FlushCacheRequest) returns (FlushCacheResponse); + // FlushCache moves all data from one shard to the others. + rpc FlushCache(FlushCacheRequest) returns (FlushCacheResponse); - // Doctor performs storage restructuring operations on engine. - rpc Doctor (DoctorRequest) returns (DoctorResponse); + // Doctor performs storage restructuring operations on engine. + rpc Doctor(DoctorRequest) returns (DoctorResponse); - // Add local access policy engine overrides to a node. - rpc AddChainLocalOverride (AddChainLocalOverrideRequest) returns (AddChainLocalOverrideResponse); + // Add local access policy engine overrides to a node. + rpc AddChainLocalOverride(AddChainLocalOverrideRequest) + returns (AddChainLocalOverrideResponse); - // Get local access policy engine overrides stored in the node by chain id. - rpc GetChainLocalOverride (GetChainLocalOverrideRequest) returns (GetChainLocalOverrideResponse); + // Get local access policy engine overrides stored in the node by chain id. + rpc GetChainLocalOverride(GetChainLocalOverrideRequest) + returns (GetChainLocalOverrideResponse); - // List local access policy engine overrides stored in the node by container id. - rpc ListChainLocalOverrides (ListChainLocalOverridesRequest) returns (ListChainLocalOverridesResponse); + // List local access policy engine overrides stored in the node by container + // id. + rpc ListChainLocalOverrides(ListChainLocalOverridesRequest) + returns (ListChainLocalOverridesResponse); - // Remove local access policy engine overrides stored in the node by chaind id. - rpc RemoveChainLocalOverride (RemoveChainLocalOverrideRequest) returns (RemoveChainLocalOverrideResponse); + // Remove local access policy engine overrides stored in the node by chaind + // id. + rpc RemoveChainLocalOverride(RemoveChainLocalOverrideRequest) + returns (RemoveChainLocalOverrideResponse); - // Remove local access policy engine overrides stored in the node by chaind id. - rpc RemoveChainLocalOverridesByTarget (RemoveChainLocalOverridesByTargetRequest) returns (RemoveChainLocalOverridesByTargetResponse); + // Remove local access policy engine overrides stored in the node by chaind + // id. + rpc RemoveChainLocalOverridesByTarget( + RemoveChainLocalOverridesByTargetRequest) + returns (RemoveChainLocalOverridesByTargetResponse); - // List targets of the local APE overrides stored in the node. - rpc ListTargetsLocalOverrides (ListTargetsLocalOverridesRequest) returns (ListTargetsLocalOverridesResponse); + // List targets of the local APE overrides stored in the node. + rpc ListTargetsLocalOverrides(ListTargetsLocalOverridesRequest) + returns (ListTargetsLocalOverridesResponse); - // Flush objects from write-cache and move it to degraded read only mode. - rpc SealWriteCache(SealWriteCacheRequest) returns (SealWriteCacheResponse); + // Flush objects from write-cache and move it to degraded read only mode. + rpc SealWriteCache(SealWriteCacheRequest) returns (SealWriteCacheResponse); - // DetachShards detaches and closes shards. - rpc DetachShards(DetachShardsRequest) returns (DetachShardsResponse); + // DetachShards detaches and closes shards. + rpc DetachShards(DetachShardsRequest) returns (DetachShardsResponse); } // Health check request. message HealthCheckRequest { - // Health check request body. - message Body { - } + // Health check request body. + message Body {} - // Body of health check request message. - Body body = 1; + // Body of health check request message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // Health check request. message HealthCheckResponse { - // Health check response body - message Body { - // Status of the storage node in FrostFS network map. - NetmapStatus netmap_status = 1; + // Health check response body + message Body { + // Status of the storage node in FrostFS network map. + NetmapStatus netmap_status = 1; - // Health status of storage node application. - HealthStatus health_status = 2; - } + // Health status of storage node application. + HealthStatus health_status = 2; + } - // Body of health check response message. - Body body = 1; + // Body of health check response message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // Set netmap status request. message SetNetmapStatusRequest { - // Set netmap status request body. - message Body { - // New storage node status in FrostFS network map. - // If status is MAINTENANCE, the node checks whether maintenance is - // allowed in the network settings. In case of prohibition, the request - // is denied. Otherwise, node switches to local maintenance state. To - // force local maintenance, use `force_maintenance` flag. - NetmapStatus status = 1; + // Set netmap status request body. + message Body { + // New storage node status in FrostFS network map. + // If status is MAINTENANCE, the node checks whether maintenance is + // allowed in the network settings. In case of prohibition, the request + // is denied. Otherwise, node switches to local maintenance state. To + // force local maintenance, use `force_maintenance` flag. + NetmapStatus status = 1; - // MAINTENANCE status validation skip flag. If set, node starts local - // maintenance regardless of network settings. The flag MUST NOT be - // set for any other status. - bool force_maintenance = 2; - } + // MAINTENANCE status validation skip flag. If set, node starts local + // maintenance regardless of network settings. The flag MUST NOT be + // set for any other status. + bool force_maintenance = 2; + } - // Body of set netmap status request message. - Body body = 1; + // Body of set netmap status request message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // Set netmap status response. message SetNetmapStatusResponse { - // Set netmap status response body - message Body { - } + // Set netmap status response body + message Body {} - // Body of set netmap status response message. - Body body = 1; + // Body of set netmap status response message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // Request to drop the objects. message DropObjectsRequest { - // Request body structure. - message Body { - // List of object addresses to be removed. - // in FrostFS API binary format. - repeated bytes address_list = 1; - } + // Request body structure. + message Body { + // List of object addresses to be removed. + // in FrostFS API binary format. + repeated bytes address_list = 1; + } - // Body of the request message. - Body body = 1; + // Body of the request message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // Response to request to drop the objects. message DropObjectsResponse { - // Response body structure. - message Body { - } + // Response body structure. + message Body {} - // Body of the response message. - Body body = 1; + // Body of the response message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // Request to list all shards of the node. message ListShardsRequest { - // Request body structure. - message Body { - } + // Request body structure. + message Body {} - // Body of the request message. - Body body = 1; + // Body of the request message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // ListShards response. message ListShardsResponse { - // Response body structure. - message Body { - // List of the node's shards. - repeated ShardInfo shards = 1; - } + // Response body structure. + message Body { + // List of the node's shards. + repeated ShardInfo shards = 1; + } - // Body of the response message. - Body body = 1; + // Body of the response message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // Request to set mode of the shard. message SetShardModeRequest { - // Request body structure. - message Body { - // ID of the shard. - repeated bytes shard_ID = 1; + // Request body structure. + message Body { + // ID of the shard. + repeated bytes shard_ID = 1; - // Mode that requested to be set. - ShardMode mode = 2; + // Mode that requested to be set. + ShardMode mode = 2; - // Flag signifying whether error counter should be set to 0. - bool resetErrorCounter = 3; - } + // Flag signifying whether error counter should be set to 0. + bool resetErrorCounter = 3; + } - // Body of set shard mode request message. - Body body = 1; + // Body of set shard mode request message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // SetShardMode response. message SetShardModeResponse { - // Response body structure. - message Body { - } + // Response body structure. + message Body {} - // Body of set shard mode response message. - Body body = 1; + // Body of set shard mode response message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // SynchronizeTree request. message SynchronizeTreeRequest { - // Request body structure. - message Body { - bytes container_id = 1; - string tree_id = 2; - // Starting height for the synchronization. Can be omitted. - uint64 height = 3; - } + // Request body structure. + message Body { + bytes container_id = 1; + string tree_id = 2; + // Starting height for the synchronization. Can be omitted. + uint64 height = 3; + } - // Body of restore shard request message. - Body body = 1; + // Body of restore shard request message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } // SynchronizeTree response. message SynchronizeTreeResponse { - // Response body structure. - message Body { - } + // Response body structure. + message Body {} - // Body of restore shard response message. - Body body = 1; + // Body of restore shard response message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } - // EvacuateShard request. message EvacuateShardRequest { - // Request body structure. - message Body { - // ID of the shard. - repeated bytes shard_ID = 1; + // Request body structure. + message Body { + // ID of the shard. + repeated bytes shard_ID = 1; - // Flag indicating whether object read errors should be ignored. - bool ignore_errors = 2; - } + // Flag indicating whether object read errors should be ignored. + bool ignore_errors = 2; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // EvacuateShard response. message EvacuateShardResponse { - // Response body structure. - message Body { - uint32 count = 1; - } + // Response body structure. + message Body { uint32 count = 1; } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // FlushCache request. message FlushCacheRequest { - // Request body structure. - message Body { - // ID of the shard. - repeated bytes shard_ID = 1; - // If true, then writecache will be left in read-only mode after flush completed. - bool seal = 2; - } + // Request body structure. + message Body { + // ID of the shard. + repeated bytes shard_ID = 1; + // If true, then writecache will be left in read-only mode after flush + // completed. + bool seal = 2; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // FlushCache response. message FlushCacheResponse { - // Response body structure. - message Body { - } + // Response body structure. + message Body {} - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } - // Doctor request. message DoctorRequest { - // Request body structure. - message Body { - // Number of threads to use for the operation. - uint32 concurrency = 1; - // Flag to search engine for duplicate objects and leave only one copy. - bool remove_duplicates = 2; - } + // Request body structure. + message Body { + // Number of threads to use for the operation. + uint32 concurrency = 1; + // Flag to search engine for duplicate objects and leave only one copy. + bool remove_duplicates = 2; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // Doctor response. message DoctorResponse { - // Response body structure. - message Body { - } + // Response body structure. + message Body {} - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // StartShardEvacuation request. message StartShardEvacuationRequest { - // Request body structure. - message Body { - enum Scope { - NONE = 0; - OBJECTS = 1; - TREES = 2; - } - - // IDs of the shards. - repeated bytes shard_ID = 1; - // Flag indicating whether object read errors should be ignored. - bool ignore_errors = 2; - // Evacuation scope. - uint32 scope = 3; + // Request body structure. + message Body { + enum Scope { + NONE = 0; + OBJECTS = 1; + TREES = 2; } - Body body = 1; - Signature signature = 2; + // IDs of the shards. + repeated bytes shard_ID = 1; + // Flag indicating whether object read errors should be ignored. + bool ignore_errors = 2; + // Evacuation scope. + uint32 scope = 3; + } + + Body body = 1; + Signature signature = 2; } // StartShardEvacuation response. message StartShardEvacuationResponse { - // Response body structure. - message Body {} + // Response body structure. + message Body {} - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // GetShardEvacuationStatus request. message GetShardEvacuationStatusRequest { - // Request body structure. - message Body {} + // Request body structure. + message Body {} - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // GetShardEvacuationStatus response. message GetShardEvacuationStatusResponse { - // Response body structure. - message Body { - // Evacuate status enum. - enum Status { - EVACUATE_SHARD_STATUS_UNDEFINED = 0; - RUNNING = 1; - COMPLETED = 2; - } - - // Unix timestamp value. - message UnixTimestamp { - int64 value = 1; - } - - // Duration in seconds. - message Duration { - int64 seconds = 1; - } - - // Total objects to evacuate count. The value is approximate, so evacuated + failed + skipped == total is not guaranteed after completion. - uint64 total_objects = 1; - // Evacuated objects count. - uint64 evacuated_objects = 2; - // Failed objects count. - uint64 failed_objects = 3; - - // Shard IDs. - repeated bytes shard_ID = 4; - // Evacuation process status. - Status status = 5; - // Evacuation process duration. - Duration duration = 6; - // Evacuation process started at timestamp. - UnixTimestamp started_at = 7; - // Error message if evacuation failed. - string error_message = 8; - - // Skipped objects count. - uint64 skipped_objects = 9; - - // Total trees to evacuate count. - uint64 total_trees = 10; - // Evacuated trees count. - uint64 evacuated_trees = 11; - // Failed trees count. - uint64 failed_trees = 12; + // Response body structure. + message Body { + // Evacuate status enum. + enum Status { + EVACUATE_SHARD_STATUS_UNDEFINED = 0; + RUNNING = 1; + COMPLETED = 2; } - Body body = 1; - Signature signature = 2; + // Unix timestamp value. + message UnixTimestamp { int64 value = 1; } + + // Duration in seconds. + message Duration { int64 seconds = 1; } + + // Total objects to evacuate count. The value is approximate, so evacuated + + // failed + skipped == total is not guaranteed after completion. + uint64 total_objects = 1; + // Evacuated objects count. + uint64 evacuated_objects = 2; + // Failed objects count. + uint64 failed_objects = 3; + + // Shard IDs. + repeated bytes shard_ID = 4; + // Evacuation process status. + Status status = 5; + // Evacuation process duration. + Duration duration = 6; + // Evacuation process started at timestamp. + UnixTimestamp started_at = 7; + // Error message if evacuation failed. + string error_message = 8; + + // Skipped objects count. + uint64 skipped_objects = 9; + + // Total trees to evacuate count. + uint64 total_trees = 10; + // Evacuated trees count. + uint64 evacuated_trees = 11; + // Failed trees count. + uint64 failed_trees = 12; + } + + Body body = 1; + Signature signature = 2; } // ResetShardEvacuationStatus request. message ResetShardEvacuationStatusRequest { - message Body {} + message Body {} - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // ResetShardEvacuationStatus response. message ResetShardEvacuationStatusResponse { - message Body {} + message Body {} - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // StopShardEvacuation request. message StopShardEvacuationRequest { - // Request body structure. - message Body {} + // Request body structure. + message Body {} - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // StopShardEvacuation response. message StopShardEvacuationResponse { - // Response body structure. - message Body {} + // Response body structure. + message Body {} - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } // AddChainLocalOverride request. message AddChainLocalOverrideRequest { - message Body { - // Target for which the overrides are applied. - ChainTarget target = 1; + message Body { + // Target for which the overrides are applied. + ChainTarget target = 1; - // Serialized rule chain. If chain ID is left empty - // in the chain, then it will be generated and returned - // in the response. - bytes chain = 2; - } + // Serialized rule chain. If chain ID is left empty + // in the chain, then it will be generated and returned + // in the response. + bytes chain = 2; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } // AddChainLocalOverride response. message AddChainLocalOverrideResponse { - message Body { - // Chain ID assigned for the added rule chain. - // If chain ID is left empty in the request, then - // it will be generated. - bytes chain_id = 1; - } + message Body { + // Chain ID assigned for the added rule chain. + // If chain ID is left empty in the request, then + // it will be generated. + bytes chain_id = 1; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } // GetChainLocalOverride request. message GetChainLocalOverrideRequest { - message Body { - // Target for which the overrides are applied. - ChainTarget target = 1; + message Body { + // Target for which the overrides are applied. + ChainTarget target = 1; - // Chain ID assigned for the added rule chain. - bytes chain_id = 2; - } + // Chain ID assigned for the added rule chain. + bytes chain_id = 2; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } // GetChainLocalOverride response. message GetChainLocalOverrideResponse { - message Body { - // Serialized rule chain. - bytes chain = 1; - } + message Body { + // Serialized rule chain. + bytes chain = 1; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } // ListChainLocalOverrides request. message ListChainLocalOverridesRequest { - message Body { - // Target for which the overrides are applied. - ChainTarget target = 1; - } + message Body { + // Target for which the overrides are applied. + ChainTarget target = 1; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } // ListChainLocalOverrides response. message ListChainLocalOverridesResponse { - message Body { - // The list of serialized rule chain. - repeated bytes chains = 1; - } + message Body { + // The list of serialized rule chain. + repeated bytes chains = 1; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } // ListTargetsLocalOverrides request. message ListTargetsLocalOverridesRequest { - message Body { - // Target for which the overrides are applied. - string chainName = 1; - } + message Body { + // Target for which the overrides are applied. + string chainName = 1; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } // ListTargetsLocalOverrides response. message ListTargetsLocalOverridesResponse { - message Body { - // The list of chain targets. - repeated ChainTarget targets = 1; - } + message Body { + // The list of chain targets. + repeated ChainTarget targets = 1; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } message RemoveChainLocalOverrideRequest { - message Body { - // Target for which the overrides are applied. - ChainTarget target = 1; + message Body { + // Target for which the overrides are applied. + ChainTarget target = 1; - // Chain ID assigned for the added rule chain. - bytes chain_id = 2; - } + // Chain ID assigned for the added rule chain. + bytes chain_id = 2; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } message RemoveChainLocalOverrideResponse { - message Body { - } + message Body {} - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } message RemoveChainLocalOverridesByTargetRequest { - message Body { - // Target for which the overrides are applied. - ChainTarget target = 1; - } + message Body { + // Target for which the overrides are applied. + ChainTarget target = 1; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } -message RemoveChainLocalOverridesByTargetResponse { - message Body { - } +message RemoveChainLocalOverridesByTargetResponse { + message Body {} - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } message SealWriteCacheRequest { - // Request body structure. - message Body { - // ID of the shard. - repeated bytes shard_ID = 1; + // Request body structure. + message Body { + // ID of the shard. + repeated bytes shard_ID = 1; - // Flag indicating whether object read errors should be ignored. - bool ignore_errors = 2; - } + // Flag indicating whether object read errors should be ignored. + bool ignore_errors = 2; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } message SealWriteCacheResponse { - message Body { - message Status { - bytes shard_ID = 1; - bool success = 2; - string error = 3; - } - repeated Status results = 1; + message Body { + message Status { + bytes shard_ID = 1; + bool success = 2; + string error = 3; } + repeated Status results = 1; + } - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } message DetachShardsRequest { - message Body { - repeated bytes shard_ID = 1; - } + message Body { repeated bytes shard_ID = 1; } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } message DetachShardsResponse { - message Body { - } + message Body {} - Body body = 1; + Body body = 1; - Signature signature = 2; + Signature signature = 2; } diff --git a/pkg/services/control/types.proto b/pkg/services/control/types.proto index 00fcb98d1e..3306924ac7 100644 --- a/pkg/services/control/types.proto +++ b/pkg/services/control/types.proto @@ -6,183 +6,182 @@ option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/con // Signature of some message. message Signature { - // Public key used for signing. - bytes key = 1 [json_name = "key"]; + // Public key used for signing. + bytes key = 1 [ json_name = "key" ]; - // Binary signature. - bytes sign = 2 [json_name = "signature"]; + // Binary signature. + bytes sign = 2 [ json_name = "signature" ]; } // Status of the storage node in the FrostFS network map. enum NetmapStatus { - // Undefined status, default value. - STATUS_UNDEFINED = 0; + // Undefined status, default value. + STATUS_UNDEFINED = 0; - // Node is online. - ONLINE = 1; + // Node is online. + ONLINE = 1; - // Node is offline. - OFFLINE = 2; + // Node is offline. + OFFLINE = 2; - // Node is maintained by the owner. - MAINTENANCE = 3; + // Node is maintained by the owner. + MAINTENANCE = 3; } // FrostFS node description. message NodeInfo { - // Public key of the FrostFS node in a binary format. - bytes public_key = 1 [json_name = "publicKey"]; + // Public key of the FrostFS node in a binary format. + bytes public_key = 1 [ json_name = "publicKey" ]; - // Ways to connect to a node. - repeated string addresses = 2 [json_name = "addresses"]; + // Ways to connect to a node. + repeated string addresses = 2 [ json_name = "addresses" ]; - // Administrator-defined Attributes of the FrostFS Storage Node. - // - // `Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8 - // string. Value can't be empty. - // - // Node's attributes are mostly used during Storage Policy evaluation to - // calculate object's placement and find a set of nodes satisfying policy - // requirements. There are some "well-known" node attributes common to all the - // Storage Nodes in the network and used implicitly with default values if not - // explicitly set: - // - // * Capacity \ + // Administrator-defined Attributes of the FrostFS Storage Node. + // + // `Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8 + // string. Value can't be empty. + // + // Node's attributes are mostly used during Storage Policy evaluation to + // calculate object's placement and find a set of nodes satisfying policy + // requirements. There are some "well-known" node attributes common to all the + // Storage Nodes in the network and used implicitly with default values if not + // explicitly set: + // + // * Capacity \ // Total available disk space in Gigabytes. - // * Price \ + // * Price \ // Price in GAS tokens for storing one GB of data during one Epoch. In node - // attributes it's a string presenting floating point number with comma or - // point delimiter for decimal part. In the Network Map it will be saved as - // 64-bit unsigned integer representing number of minimal token fractions. - // * Locode \ + // attributes it's a string presenting floating point number with comma or + // point delimiter for decimal part. In the Network Map it will be saved as + // 64-bit unsigned integer representing number of minimal token fractions. + // * Locode \ // Node's geographic location in - // [UN/LOCODE](https://www.unece.org/cefact/codesfortrade/codes_index.html) - // format approximated to the nearest point defined in standard. - // * Country \ + // [UN/LOCODE](https://www.unece.org/cefact/codesfortrade/codes_index.html) + // format approximated to the nearest point defined in standard. + // * Country \ // Country code in - // [ISO 3166-1_alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) - // format. Calculated automatically from `Locode` attribute - // * Region \ + // [ISO 3166-1_alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) + // format. Calculated automatically from `Locode` attribute + // * Region \ // Country's administative subdivision where node is located. Calculated - // automatically from `Locode` attribute based on `SubDiv` field. Presented - // in [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format. - // * City \ + // automatically from `Locode` attribute based on `SubDiv` field. Presented + // in [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format. + // * City \ // City, town, village or rural area name where node is located written - // without diacritics . Calculated automatically from `Locode` attribute. - // - // For detailed description of each well-known attribute please see the - // corresponding section in FrostFS Technical specification. - message Attribute { - // Key of the node attribute. - string key = 1 [json_name = "key"]; + // without diacritics . Calculated automatically from `Locode` attribute. + // + // For detailed description of each well-known attribute please see the + // corresponding section in FrostFS Technical specification. + message Attribute { + // Key of the node attribute. + string key = 1 [ json_name = "key" ]; - // Value of the node attribute. - string value = 2 [json_name = "value"]; + // Value of the node attribute. + string value = 2 [ json_name = "value" ]; - // Parent keys, if any. For example for `City` it could be `Region` and - // `Country`. - repeated string parents = 3 [json_name = "parents"]; - } - // Carries list of the FrostFS node attributes in a key-value form. Key name - // must be a node-unique valid UTF-8 string. Value can't be empty. NodeInfo - // structures with duplicated attribute names or attributes with empty values - // will be considered invalid. - repeated Attribute attributes = 3 [json_name = "attributes"]; + // Parent keys, if any. For example for `City` it could be `Region` and + // `Country`. + repeated string parents = 3 [ json_name = "parents" ]; + } + // Carries list of the FrostFS node attributes in a key-value form. Key name + // must be a node-unique valid UTF-8 string. Value can't be empty. NodeInfo + // structures with duplicated attribute names or attributes with empty values + // will be considered invalid. + repeated Attribute attributes = 3 [ json_name = "attributes" ]; - // Carries state of the FrostFS node. - NetmapStatus state = 4 [json_name = "state"]; + // Carries state of the FrostFS node. + NetmapStatus state = 4 [ json_name = "state" ]; } // Network map structure. message Netmap { - // Network map revision number. - uint64 epoch = 1 [json_name = "epoch"]; + // Network map revision number. + uint64 epoch = 1 [ json_name = "epoch" ]; - // Nodes presented in network. - repeated NodeInfo nodes = 2 [json_name = "nodes"]; + // Nodes presented in network. + repeated NodeInfo nodes = 2 [ json_name = "nodes" ]; } // Health status of the storage node application. enum HealthStatus { - // Undefined status, default value. - HEALTH_STATUS_UNDEFINED = 0; + // Undefined status, default value. + HEALTH_STATUS_UNDEFINED = 0; - // Storage node application is starting. - STARTING = 1; + // Storage node application is starting. + STARTING = 1; - // Storage node application is started and serves all services. - READY = 2; + // Storage node application is started and serves all services. + READY = 2; - // Storage node application is shutting down. - SHUTTING_DOWN = 3; + // Storage node application is shutting down. + SHUTTING_DOWN = 3; - // Storage node application is reconfiguring. - RECONFIGURING = 4; + // Storage node application is reconfiguring. + RECONFIGURING = 4; } // Shard description. message ShardInfo { - // ID of the shard. - bytes shard_ID = 1 [json_name = "shardID"]; + // ID of the shard. + bytes shard_ID = 1 [ json_name = "shardID" ]; - // Path to shard's metabase. - string metabase_path = 2 [json_name = "metabasePath"]; + // Path to shard's metabase. + string metabase_path = 2 [ json_name = "metabasePath" ]; - // Shard's blobstor info. - repeated BlobstorInfo blobstor = 3 [json_name = "blobstor"]; + // Shard's blobstor info. + repeated BlobstorInfo blobstor = 3 [ json_name = "blobstor" ]; - // Path to shard's write-cache, empty if disabled. - string writecache_path = 4 [json_name = "writecachePath"]; + // Path to shard's write-cache, empty if disabled. + string writecache_path = 4 [ json_name = "writecachePath" ]; - // Work mode of the shard. - ShardMode mode = 5; + // Work mode of the shard. + ShardMode mode = 5; - // Amount of errors occured. - uint32 errorCount = 6; + // Amount of errors occured. + uint32 errorCount = 6; - // Path to shard's pilorama storage. - string pilorama_path = 7 [json_name = "piloramaPath"]; + // Path to shard's pilorama storage. + string pilorama_path = 7 [ json_name = "piloramaPath" ]; } // Blobstor component description. message BlobstorInfo { - // Path to the root. - string path = 1 [json_name = "path"]; - // Component type. - string type = 2 [json_name = "type"]; + // Path to the root. + string path = 1 [ json_name = "path" ]; + // Component type. + string type = 2 [ json_name = "type" ]; } // Work mode of the shard. enum ShardMode { - // Undefined mode, default value. - SHARD_MODE_UNDEFINED = 0; + // Undefined mode, default value. + SHARD_MODE_UNDEFINED = 0; - // Read-write. - READ_WRITE = 1; + // Read-write. + READ_WRITE = 1; - // Read-only. - READ_ONLY = 2; + // Read-only. + READ_ONLY = 2; - // Degraded. - DEGRADED = 3; + // Degraded. + DEGRADED = 3; - // DegradedReadOnly. - DEGRADED_READ_ONLY = 4; + // DegradedReadOnly. + DEGRADED_READ_ONLY = 4; } - // ChainTarget is an object to which local overrides // are applied. message ChainTarget { - enum TargetType { - UNDEFINED = 0; + enum TargetType { + UNDEFINED = 0; - NAMESPACE = 1; + NAMESPACE = 1; - CONTAINER = 2; - } + CONTAINER = 2; + } - TargetType type = 1; + TargetType type = 1; - string Name = 2; + string Name = 2; } From 3ea1d7b7290a2dad4fa2992772006921e848733a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 11 Apr 2024 17:06:09 +0300 Subject: [PATCH 0508/1413] [#1089] control: Add USER and GROUP targets for local override storage Signed-off-by: Evgenii Stratonikov --- pkg/services/control/server/policy_engine.go | 14 +++++ pkg/services/control/service.pb.go | 6 +- pkg/services/control/service_grpc.pb.go | 30 ++++++---- pkg/services/control/types.pb.go | 59 +++++++++++--------- pkg/services/control/types.proto | 4 ++ 5 files changed, 75 insertions(+), 38 deletions(-) diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 16b365b219..7ec3d58ac4 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -19,6 +19,10 @@ func apeTarget(chainTarget *control.ChainTarget) (engine.Target, error) { return engine.ContainerTarget(chainTarget.GetName()), nil case control.ChainTarget_NAMESPACE: return engine.NamespaceTarget(chainTarget.GetName()), nil + case control.ChainTarget_USER: + return engine.UserTarget(chainTarget.GetName()), nil + case control.ChainTarget_GROUP: + return engine.GroupTarget(chainTarget.GetName()), nil default: } return engine.Target{}, status.Error(codes.InvalidArgument, @@ -42,6 +46,16 @@ func controlTarget(chainTarget *engine.Target) (control.ChainTarget, error) { Name: nm, Type: control.ChainTarget_NAMESPACE, }, nil + case engine.User: + return control.ChainTarget{ + Name: chainTarget.Name, + Type: control.ChainTarget_USER, + }, nil + case engine.Group: + return control.ChainTarget{ + Name: chainTarget.Name, + Type: control.ChainTarget_GROUP, + }, nil default: } return control.ChainTarget{}, status.Error(codes.InvalidArgument, diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 345110bab8..9c597beecc 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -3188,7 +3188,8 @@ type FlushCacheRequest_Body struct { // ID of the shard. Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - // If true, then writecache will be left in read-only mode after flush completed. + // If true, then writecache will be left in read-only mode after flush + // completed. Seal bool `protobuf:"varint,2,opt,name=seal,proto3" json:"seal,omitempty"` } @@ -3525,7 +3526,8 @@ type GetShardEvacuationStatusResponse_Body struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // Total objects to evacuate count. The value is approximate, so evacuated + failed + skipped == total is not guaranteed after completion. + // Total objects to evacuate count. The value is approximate, so evacuated + + // failed + skipped == total is not guaranteed after completion. TotalObjects uint64 `protobuf:"varint,1,opt,name=total_objects,json=totalObjects,proto3" json:"total_objects,omitempty"` // Evacuated objects count. EvacuatedObjects uint64 `protobuf:"varint,2,opt,name=evacuated_objects,json=evacuatedObjects,proto3" json:"evacuated_objects,omitempty"` diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index 95264fcd3e..feeee00065 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -59,13 +59,15 @@ type ControlServiceClient interface { // Synchronizes all log operations for the specified tree. SynchronizeTree(ctx context.Context, in *SynchronizeTreeRequest, opts ...grpc.CallOption) (*SynchronizeTreeResponse, error) // EvacuateShard moves all data from one shard to the others. - // Deprecated: Use StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation + // Deprecated: Use + // StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation EvacuateShard(ctx context.Context, in *EvacuateShardRequest, opts ...grpc.CallOption) (*EvacuateShardResponse, error) // StartShardEvacuation starts moving all data from one shard to the others. StartShardEvacuation(ctx context.Context, in *StartShardEvacuationRequest, opts ...grpc.CallOption) (*StartShardEvacuationResponse, error) // GetShardEvacuationStatus returns evacuation status. GetShardEvacuationStatus(ctx context.Context, in *GetShardEvacuationStatusRequest, opts ...grpc.CallOption) (*GetShardEvacuationStatusResponse, error) - // ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process. + // ResetShardEvacuationStatus resets evacuation status if there is no running + // evacuation process. ResetShardEvacuationStatus(ctx context.Context, in *ResetShardEvacuationStatusRequest, opts ...grpc.CallOption) (*ResetShardEvacuationStatusResponse, error) // StopShardEvacuation stops moving all data from one shard to the others. StopShardEvacuation(ctx context.Context, in *StopShardEvacuationRequest, opts ...grpc.CallOption) (*StopShardEvacuationResponse, error) @@ -77,11 +79,14 @@ type ControlServiceClient interface { AddChainLocalOverride(ctx context.Context, in *AddChainLocalOverrideRequest, opts ...grpc.CallOption) (*AddChainLocalOverrideResponse, error) // Get local access policy engine overrides stored in the node by chain id. GetChainLocalOverride(ctx context.Context, in *GetChainLocalOverrideRequest, opts ...grpc.CallOption) (*GetChainLocalOverrideResponse, error) - // List local access policy engine overrides stored in the node by container id. + // List local access policy engine overrides stored in the node by container + // id. ListChainLocalOverrides(ctx context.Context, in *ListChainLocalOverridesRequest, opts ...grpc.CallOption) (*ListChainLocalOverridesResponse, error) - // Remove local access policy engine overrides stored in the node by chaind id. + // Remove local access policy engine overrides stored in the node by chaind + // id. RemoveChainLocalOverride(ctx context.Context, in *RemoveChainLocalOverrideRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverrideResponse, error) - // Remove local access policy engine overrides stored in the node by chaind id. + // Remove local access policy engine overrides stored in the node by chaind + // id. RemoveChainLocalOverridesByTarget(ctx context.Context, in *RemoveChainLocalOverridesByTargetRequest, opts ...grpc.CallOption) (*RemoveChainLocalOverridesByTargetResponse, error) // List targets of the local APE overrides stored in the node. ListTargetsLocalOverrides(ctx context.Context, in *ListTargetsLocalOverridesRequest, opts ...grpc.CallOption) (*ListTargetsLocalOverridesResponse, error) @@ -305,13 +310,15 @@ type ControlServiceServer interface { // Synchronizes all log operations for the specified tree. SynchronizeTree(context.Context, *SynchronizeTreeRequest) (*SynchronizeTreeResponse, error) // EvacuateShard moves all data from one shard to the others. - // Deprecated: Use StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation + // Deprecated: Use + // StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation EvacuateShard(context.Context, *EvacuateShardRequest) (*EvacuateShardResponse, error) // StartShardEvacuation starts moving all data from one shard to the others. StartShardEvacuation(context.Context, *StartShardEvacuationRequest) (*StartShardEvacuationResponse, error) // GetShardEvacuationStatus returns evacuation status. GetShardEvacuationStatus(context.Context, *GetShardEvacuationStatusRequest) (*GetShardEvacuationStatusResponse, error) - // ResetShardEvacuationStatus resets evacuation status if there is no running evacuation process. + // ResetShardEvacuationStatus resets evacuation status if there is no running + // evacuation process. ResetShardEvacuationStatus(context.Context, *ResetShardEvacuationStatusRequest) (*ResetShardEvacuationStatusResponse, error) // StopShardEvacuation stops moving all data from one shard to the others. StopShardEvacuation(context.Context, *StopShardEvacuationRequest) (*StopShardEvacuationResponse, error) @@ -323,11 +330,14 @@ type ControlServiceServer interface { AddChainLocalOverride(context.Context, *AddChainLocalOverrideRequest) (*AddChainLocalOverrideResponse, error) // Get local access policy engine overrides stored in the node by chain id. GetChainLocalOverride(context.Context, *GetChainLocalOverrideRequest) (*GetChainLocalOverrideResponse, error) - // List local access policy engine overrides stored in the node by container id. + // List local access policy engine overrides stored in the node by container + // id. ListChainLocalOverrides(context.Context, *ListChainLocalOverridesRequest) (*ListChainLocalOverridesResponse, error) - // Remove local access policy engine overrides stored in the node by chaind id. + // Remove local access policy engine overrides stored in the node by chaind + // id. RemoveChainLocalOverride(context.Context, *RemoveChainLocalOverrideRequest) (*RemoveChainLocalOverrideResponse, error) - // Remove local access policy engine overrides stored in the node by chaind id. + // Remove local access policy engine overrides stored in the node by chaind + // id. RemoveChainLocalOverridesByTarget(context.Context, *RemoveChainLocalOverridesByTargetRequest) (*RemoveChainLocalOverridesByTargetResponse, error) // List targets of the local APE overrides stored in the node. ListTargetsLocalOverrides(context.Context, *ListTargetsLocalOverridesRequest) (*ListTargetsLocalOverridesResponse, error) diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go index 2fc16a9263..8587556944 100644 --- a/pkg/services/control/types.pb.go +++ b/pkg/services/control/types.pb.go @@ -205,6 +205,8 @@ const ( ChainTarget_UNDEFINED ChainTarget_TargetType = 0 ChainTarget_NAMESPACE ChainTarget_TargetType = 1 ChainTarget_CONTAINER ChainTarget_TargetType = 2 + ChainTarget_USER ChainTarget_TargetType = 3 + ChainTarget_GROUP ChainTarget_TargetType = 4 ) // Enum value maps for ChainTarget_TargetType. @@ -213,11 +215,15 @@ var ( 0: "UNDEFINED", 1: "NAMESPACE", 2: "CONTAINER", + 3: "USER", + 4: "GROUP", } ChainTarget_TargetType_value = map[string]int32{ "UNDEFINED": 0, "NAMESPACE": 1, "CONTAINER": 2, + "USER": 3, + "GROUP": 4, } ) @@ -814,40 +820,41 @@ var file_pkg_services_control_types_proto_rawDesc = []byte{ 0x6d, 0x61, 0x50, 0x61, 0x74, 0x68, 0x22, 0x36, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x91, + 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x4e, 0x0a, 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x50, 0x41, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, - 0x10, 0x02, 0x2a, 0x4e, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, - 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, - 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, - 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, 0x4e, 0x41, 0x4e, 0x43, 0x45, - 0x10, 0x03, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, - 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, - 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54, - 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, - 0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x2a, 0x6a, - 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x53, - 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, - 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x57, 0x52, - 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, - 0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, - 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41, 0x44, 0x45, 0x44, 0x5f, 0x52, - 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, - 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, - 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, - 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, + 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x04, 0x2a, 0x4e, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, + 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, + 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, + 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, + 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, + 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, + 0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, + 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, + 0x47, 0x10, 0x04, 0x2a, 0x6a, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, + 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, + 0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, + 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, + 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41, + 0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, + 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, + 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, + 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, + 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/types.proto b/pkg/services/control/types.proto index 3306924ac7..55636d88a5 100644 --- a/pkg/services/control/types.proto +++ b/pkg/services/control/types.proto @@ -179,6 +179,10 @@ message ChainTarget { NAMESPACE = 1; CONTAINER = 2; + + USER = 3; + + GROUP = 4; } TargetType type = 1; From 46bc6a79308383482711845fa71a11be28b96465 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 15 Apr 2024 10:47:45 +0300 Subject: [PATCH 0509/1413] [#1095] cli: Support user/group target for local overrides Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/control/list_rules.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index b345ecbfbf..f5fc27bda1 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -27,6 +27,8 @@ const ( defaultNamespace = "root" namespaceTarget = "namespace" containerTarget = "container" + userTarget = "user" + groupTarget = "group" ) const ( @@ -66,6 +68,16 @@ func parseTarget(cmd *cobra.Command) *control.ChainTarget { Name: name, Type: control.ChainTarget_CONTAINER, } + case userTarget: + return &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_USER, + } + case groupTarget: + return &control.ChainTarget{ + Name: name, + Type: control.ChainTarget_GROUP, + } default: commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) } From 97e54066d03f5037a0c3d37f9fe737b5ca1d5eb0 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Apr 2024 13:19:16 +0300 Subject: [PATCH 0510/1413] [#1095] adm: Support user/group target for APE Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/ape/ape.go | 2 ++ cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index 710595fe8c..077e037375 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -16,6 +16,8 @@ import ( const ( namespaceTarget = "namespace" containerTarget = "container" + userTarget = "user" + groupTarget = "group" jsonFlag = "json" jsonFlagDesc = "Output rule chains in JSON format" chainIDFlag = "chain-id" diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index b3610e7f7b..42307e78fb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -53,6 +53,10 @@ func parseTargetType(cmd *cobra.Command) (policyengine.TargetType, error) { return policyengine.Namespace, nil case containerTarget: return policyengine.Container, nil + case userTarget: + return policyengine.User, nil + case groupTarget: + return policyengine.Group, nil } return -1, errUnknownTargetType } From 6772976657f7ec4a2263cc9f49abb65aa9943831 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 15 Apr 2024 15:54:16 +0300 Subject: [PATCH 0511/1413] [#1096] container: Make ape middleware fill request with user claim tags Signed-off-by: Airat Arifullin --- pkg/services/container/ape.go | 46 +++++++++++++-- pkg/services/container/ape_test.go | 89 +++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 5 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 02549bdedb..2ce427fa33 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -27,11 +27,16 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" ) +const ( + subjectNotFoundErrorMessage = "subject not found" +) + var ( errMissingContainerID = errors.New("missing container ID") errSessionContainerMissmatch = errors.New("requested container is not related to the session") @@ -40,7 +45,6 @@ var ( errInvalidSessionTokenOwner = errors.New("malformed request: invalid session token owner") errEmptyBodySignature = errors.New("malformed request: empty body signature") errMissingOwnerID = errors.New("malformed request: missing owner ID") - errSubjectNotFound = errors.New("subject not found") errOwnerIDIsNotSet = errors.New("owner id is not set") errInvalidDomainZone = errors.New("invalid domain zone: no namespace is expected") @@ -140,6 +144,11 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co nativeschema.PropertyKeyActorRole: role, } + reqProps, err = ac.fillWithUserClaimTags(reqProps, pk) + if err != nil { + return nil, err + } + namespace, err := ac.namespaceByOwner(req.GetBody().GetOwnerID()) if err != nil { return nil, fmt.Errorf("could not get owner namespace: %w", err) @@ -188,6 +197,11 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont nativeschema.PropertyKeyActorRole: role, } + reqProps, err = ac.fillWithUserClaimTags(reqProps, pk) + if err != nil { + return nil, err + } + namespace, err := ac.namespaceByOwner(req.GetBody().GetContainer().GetOwnerID()) if err != nil { return nil, fmt.Errorf("get namespace error: %w", err) @@ -365,10 +379,15 @@ func (ac *apeChecker) getRequestProps(mh *session.RequestMetaHeader, vh *session if err != nil { return nil, nil, err } - return map[string]string{ + reqProps := map[string]string{ nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(pk.Bytes()), nativeschema.PropertyKeyActorRole: role, - }, pk, nil + } + reqProps, err = ac.fillWithUserClaimTags(reqProps, pk) + if err != nil { + return nil, nil, err + } + return reqProps, pk, nil } func (ac *apeChecker) getRole(actor *user.ID, pk *keys.PublicKey, cont *containercore.Container, cnrID cid.ID) (string, error) { @@ -555,7 +574,7 @@ func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { if err == nil { namespace = subject.Namespace } else { - if !strings.Contains(err.Error(), errSubjectNotFound.Error()) { + if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { return "", fmt.Errorf("get subject error: %w", err) } } @@ -603,3 +622,22 @@ func (ac *apeChecker) validateNamespaceByPublicKey(pk *keys.PublicKey, ownerIDNa } return nil } + +// fillWithUserClaimTags fills ape request properties with user claim tags getting them from frostfsid contract by actor public key. +func (ac *apeChecker) fillWithUserClaimTags(reqProps map[string]string, pk *keys.PublicKey) (map[string]string, error) { + if reqProps == nil { + reqProps = make(map[string]string) + } + subj, err := ac.frostFSIDClient.GetSubject(pk.GetScriptHash()) + if err != nil { + if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + return nil, fmt.Errorf("get subject error: %w", err) + } + return reqProps, nil + } + for k, v := range subj.KV { + properyKey := fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, k) + reqProps[properyKey] = v + } + return reqProps, nil +} diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 1af59d1c60..e26e82d43b 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -26,6 +26,7 @@ import ( "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" @@ -42,6 +43,7 @@ func TestAPE(t *testing.T) { t.Run("allow then deny get container", testAllowThenDenyGetContainerRuleDefined) t.Run("deny get container no rule found", testDenyGetContainerNoRuleFound) t.Run("deny get container for others", testDenyGetContainerForOthers) + t.Run("deny get container by user claim tag", testDenyGetContainerByUserClaimTag) t.Run("deny set container eACL for IR", testDenySetContainerEACLForIR) t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken) t.Run("deny put container for others with session token", testDenyPutContainerForOthersSessionToken) @@ -251,6 +253,91 @@ func testDenyGetContainerForOthers(t *testing.T) { require.ErrorAs(t, err, &errAccessDenied) } +func testDenyGetContainerByUserClaimTag(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + }, + }, + } + + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, "tag-attr1"), + Value: "value100", + Op: chain.CondStringNotEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + resp, err := apeSrv.Get(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) +} + func testDenySetContainerEACLForIR(t *testing.T) { t.Parallel() srv := &srvStub{ @@ -841,7 +928,7 @@ type frostfsidStub struct { func (f *frostfsidStub) GetSubject(owner util.Uint160) (*client.Subject, error) { s, ok := f.subjects[owner] if !ok { - return nil, errSubjectNotFound + return nil, fmt.Errorf("%s", subjectNotFoundErrorMessage) } return s, nil } From c21d72ac238c49f0e482e5ed4a19b45035c7de0d Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 15 Apr 2024 16:51:19 +0300 Subject: [PATCH 0512/1413] [#1096] object: Make ape middleware fill request with user claim tags Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 3 ++ cmd/frostfs-node/container.go | 3 +- cmd/frostfs-node/object.go | 1 + pkg/services/object/ape/checker.go | 12 ++++++- pkg/services/object/ape/checker_test.go | 40 +++++++++++++++++++++- pkg/services/object/ape/request.go | 45 ++++++++++++++++++++++--- pkg/services/object/ape/request_test.go | 11 ++++-- 7 files changed, 105 insertions(+), 10 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index c5ed8b50c6..066d63e652 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -46,6 +46,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" containerClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" + frostfsidClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmap2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" @@ -415,6 +416,8 @@ type shared struct { cnrClient *containerClient.Client + frostfsidClient *frostfsidClient.Client + respSvc *response.Service replicator *replicator.Replicator diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index d566c0af36..e006648ed2 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -35,12 +35,13 @@ func initContainerService(_ context.Context, c *cfg) { frostFSIDClient, err := frostfsid.NewFromMorph(c.cfgMorph.client, c.cfgFrostfsID.scriptHash, 0) fatalOnErr(err) + c.shared.frostfsidClient = frostFSIDClient server := containerTransportGRPC.New( containerService.NewSignService( &c.key.PrivateKey, containerService.NewAPEServer(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine, cnrRdr, - newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, frostFSIDClient, + newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient, containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), ), ), diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 7f1d094fd4..6160bbc76b 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -444,6 +444,7 @@ func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *object objectAPE.NewChecker( c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.chainRouter, objectAPE.NewStorageEngineHeaderProvider(c.cfgObject.cfgLocalStorage.localStorage), + c.shared.frostfsidClient, ), splitSvc, ) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 1063bd901b..170787317d 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -6,6 +6,7 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -13,19 +14,28 @@ import ( policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" ) type checkerImpl struct { chainRouter policyengine.ChainRouter headerProvider HeaderProvider + + frostFSIDClient frostfsidSubjectProvider } -func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider) Checker { +type frostfsidSubjectProvider interface { + GetSubject(util.Uint160) (*client.Subject, error) +} + +func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidSubjectProvider) Checker { return &checkerImpl{ chainRouter: chainRouter, headerProvider: headerProvider, + + frostFSIDClient: frostFSIDClient, } } diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index fc915715c4..9510bf039d 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -6,6 +6,7 @@ import ( "fmt" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -17,6 +18,7 @@ import ( "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" ) @@ -153,6 +155,41 @@ var ( senderKey = hex.EncodeToString(senderPrivateKey.PublicKey().Bytes()) ) +type frostfsIDProviderMock struct { + m map[util.Uint160]*client.Subject +} + +var _ frostfsidSubjectProvider = (*frostfsIDProviderMock)(nil) + +func newFrostfsIDProviderMock(t *testing.T) *frostfsIDProviderMock { + return &frostfsIDProviderMock{ + m: map[util.Uint160]*client.Subject{ + scriptHashFromSenderKey(t, senderKey): { + Namespace: "testnamespace", + Name: "test", + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + }, + }, + } +} + +func scriptHashFromSenderKey(t *testing.T, senderKey string) util.Uint160 { + pk, err := keys.NewPublicKeyFromString(senderKey) + require.NoError(t, err) + return pk.GetScriptHash() +} + +func (f *frostfsIDProviderMock) GetSubject(key util.Uint160) (*client.Subject, error) { + v, ok := f.m[key] + if !ok { + return nil, fmt.Errorf("%s", subjectNotFoundErrorMessage) + } + return v, nil +} + func TestAPECheck(t *testing.T) { for _, test := range []struct { name string @@ -321,6 +358,7 @@ func TestAPECheck(t *testing.T) { for _, method := range test.methods { t.Run(method, func(t *testing.T) { headerProvider := newHeaderProviderMock() + frostfsidProvider := newFrostfsIDProviderMock(t) cnr := newContainerIDSDK(t, test.container) obj := newObjectIDSDK(t, test.object) @@ -335,7 +373,7 @@ func TestAPECheck(t *testing.T) { router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) - checker := NewChecker(router, headerProvider) + checker := NewChecker(router, headerProvider, frostfsidProvider) prm := Prm{ Method: method, diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 7bbee31c1d..5daf8751b0 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strconv" + "strings" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" @@ -12,7 +13,13 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +const ( + subjectNotFoundErrorMessage = "subject not found" ) var defaultRequest = aperequest.Request{} @@ -115,15 +122,45 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re } } + reqProps := map[string]string{ + nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, + nativeschema.PropertyKeyActorRole: prm.Role, + } + var err error + reqProps, err = c.fillWithUserClaimTags(reqProps, prm) + if err != nil { + return defaultRequest, err + } + return aperequest.NewRequest( prm.Method, aperequest.NewResource( resourceName(prm.Container, prm.Object, prm.Namespace), objectProperties(prm.Container, prm.Object, prm.ContainerOwner, header), ), - map[string]string{ - nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, - nativeschema.PropertyKeyActorRole: prm.Role, - }, + reqProps, ), nil } + +// fillWithUserClaimTags fills ape request properties with user claim tags getting them from frostfsid contract by actor public key. +func (c *checkerImpl) fillWithUserClaimTags(reqProps map[string]string, prm Prm) (map[string]string, error) { + if reqProps == nil { + reqProps = make(map[string]string) + } + pk, err := keys.NewPublicKeyFromString(prm.SenderKey) + if err != nil { + return nil, err + } + subj, err := c.frostFSIDClient.GetSubject(pk.GetScriptHash()) + if err != nil { + if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + return nil, fmt.Errorf("get subject error: %w", err) + } + return reqProps, nil + } + for k, v := range subj.KV { + properyKey := fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, k) + reqProps[properyKey] = v + } + return reqProps, nil +} diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index fdb7af2197..cda78e69c4 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -11,6 +11,7 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" ) @@ -234,6 +235,7 @@ func TestNewAPERequest(t *testing.T) { } headerSource := newHeaderProviderMock() + ffidProvider := newFrostfsIDProviderMock(t) var headerObjSDK *objectSDK.Object if test.header.headerObjSDK != nil { @@ -247,7 +249,8 @@ func TestNewAPERequest(t *testing.T) { } c := checkerImpl{ - headerProvider: headerSource, + headerProvider: headerSource, + frostFSIDClient: ffidProvider, } r, err := c.newAPERequest(context.TODO(), prm) @@ -268,8 +271,10 @@ func TestNewAPERequest(t *testing.T) { return prm.Header }())), map[string]string{ - nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, - nativeschema.PropertyKeyActorRole: prm.Role, + nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, + nativeschema.PropertyKeyActorRole: prm.Role, + fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, "tag-attr1"): "value1", + fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, "tag-attr2"): "value2", }, ) From 10ee865e98e87106c42f764849faa1adb0a5c6dc Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 15 Apr 2024 17:04:34 +0300 Subject: [PATCH 0513/1413] [#1096] tree: Make `verifyClient` fill ape request with user claim tags Signed-off-by: Airat Arifullin --- cmd/frostfs-node/tree.go | 1 + pkg/services/tree/ape.go | 28 ++++++++++++++++++++++++++++ pkg/services/tree/options.go | 27 ++++++++++++++++++++------- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index ff00b6fac9..49ecb6fdc8 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -53,6 +53,7 @@ func initTreeService(c *cfg) { src: c.cfgObject.cnrSource, cli: c.shared.cnrClient, }), + tree.WithFrostfsidSubjectProvider(c.shared.frostfsidClient), tree.WithEACLSource(c.cfgObject.eaclSource), tree.WithNetmapSource(c.netMapSource), tree.WithPrivateKey(&c.key.PrivateKey), diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 5da49a5913..f587215096 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -14,10 +14,15 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) +var ( + subjectNotFoundErrorMessage = "subject not found" +) + func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error { namespace := "" cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns") @@ -37,6 +42,10 @@ func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl. nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(publicKey.Bytes()), nativeschema.PropertyKeyActorRole: schemaRole, } + reqProps, err = s.fillWithUserClaimTags(reqProps, publicKey) + if err != nil { + return apeErr(err) + } var resourceName string if namespace == "root" || namespace == "" { @@ -68,3 +77,22 @@ func apeErr(err error) error { errAccessDenied.WriteReason(err.Error()) return errAccessDenied } + +// fillWithUserClaimTags fills ape request properties with user claim tags getting them from frostfsid contract by actor public key. +func (s *Service) fillWithUserClaimTags(reqProps map[string]string, publicKey *keys.PublicKey) (map[string]string, error) { + if reqProps == nil { + reqProps = make(map[string]string) + } + subj, err := s.frostfsidSubjectProvider.GetSubject(publicKey.GetScriptHash()) + if err != nil { + if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + return nil, fmt.Errorf("get subject error: %w", err) + } + return reqProps, nil + } + for k, v := range subj.KV { + properyKey := fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, k) + reqProps[properyKey] = v + } + return reqProps, nil +} diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index 0e5f642747..c4ef80856f 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -4,6 +4,7 @@ import ( "crypto/ecdsa" "time" + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" @@ -11,8 +12,13 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" ) +type FrostfsidSubjectProvider interface { + GetSubject(util.Uint160) (*client.Subject, error) +} + type ContainerSource interface { container.Source @@ -25,13 +31,14 @@ type ContainerSource interface { } type cfg struct { - log *logger.Logger - key *ecdsa.PrivateKey - rawPub []byte - nmSource netmap.Source - cnrSource ContainerSource - eaclSource container.EACLSource - forest pilorama.Forest + log *logger.Logger + key *ecdsa.PrivateKey + rawPub []byte + nmSource netmap.Source + cnrSource ContainerSource + frostfsidSubjectProvider FrostfsidSubjectProvider + eaclSource container.EACLSource + forest pilorama.Forest // replication-related parameters replicatorChannelCapacity int replicatorWorkerCount int @@ -55,6 +62,12 @@ func WithContainerSource(src ContainerSource) Option { } } +func WithFrostfsidSubjectProvider(provider FrostfsidSubjectProvider) Option { + return func(c *cfg) { + c.frostfsidSubjectProvider = provider + } +} + // WithEACLSource sets a eACL table source for a tree service. // This option is required. func WithEACLSource(src container.EACLSource) Option { From 6d4583f5de0dea88e1e57704e2d630b34d745636 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Apr 2024 14:01:25 +0300 Subject: [PATCH 0514/1413] [#1097] docs: Describe authentication mechanisms Signed-off-by: Evgenii Stratonikov --- docs/authentication.md | 57 ++++++++++++++++++++ docs/images/authentication/authoverview.puml | 28 ++++++++++ docs/images/authentication/authoverview.svg | 1 + 3 files changed, 86 insertions(+) create mode 100644 docs/authentication.md create mode 100644 docs/images/authentication/authoverview.puml create mode 100644 docs/images/authentication/authoverview.svg diff --git a/docs/authentication.md b/docs/authentication.md new file mode 100644 index 0000000000..4efb03f934 --- /dev/null +++ b/docs/authentication.md @@ -0,0 +1,57 @@ +# Authentication and signatures + +## General overview + +![Auth general overview](images/authentication/authoverview.svg) + +## Signatures + +Every message in the FrostFS network is signed. +Each signature consists of: +1. Scheme +2. Public key +3. Signature + +If signature check fails, operation is aborted and the error is returned to the user. + +### Schemes +Currently, 3 schemes are defined in the [frostfs-api](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/commit/4bae9dd78abcf1a358a65a45fe7303e37fd98099/refs/types.proto#L105): + +#### ECDSA + +Defined in section 6 of [FIPS 186](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf). +Implemented in the Go stdlib. +This is the primary algorithm used to sign and verify requests. +The hash algorithm used is SHA-512. + +#### RFC6979 + +[RFC 6979](https://www.rfc-editor.org/rfc/rfc6979) defines deterministic algorithm for ECDSA signatures. +It it used primarily used by neo-go and allows us to perform signature checks inside the contract, such as for container. +The hash algorithm used is SHA-256 + +### Public key + +ECDSA public key corresponding to the private key being used to sign a message. +It is the primary user identity and is used to determine the request originator. + +## Session token + +Session token can override the rules of determining request owner. +It is defined in the [frostfs-api](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/branch/master/session/types.proto#L89). +If user A signs a session token for user B, then user B can sign request with its own key, while the node will still process the request as if it was originated from user A. +This is used, for example, when putting objects in system: +1. User creates a session with node, recevieving session token. +2. User signs session token for a freshly generated key, stored on a storage node. +3. User sends raw stream of bytes, while the node signs created objects with the session key. This way other nodes can validate the object owned by user, even though it is signed by a different key. + +Session token may have some restrictions: +1. Lifetime, effectively an epoch after which it becomes invalid. +2. Set of operations it applies to. +3. The entity it is given to. This is provided in `session_key` field containing the public key. + +## Bearer token + +## FrostFS ID + +## APE \ No newline at end of file diff --git a/docs/images/authentication/authoverview.puml b/docs/images/authentication/authoverview.puml new file mode 100644 index 0000000000..1242fdfc6c --- /dev/null +++ b/docs/images/authentication/authoverview.puml @@ -0,0 +1,28 @@ +@startuml authoverview +!include +!include +AddElementTag("smart-contract", $bgColor=#0abab5) + +Person(user, "User", "User with private key") + +Container_Boundary(stor, "FrostFS Storage") { + Component(verify, "Sign Service", $descr="Check request signature") + Component(apesvc, "APE Service") + Component(objsvc, "Object service") +} + +Container_Boundary(neogo, "Blockchain") { + Interface "NeoGo" + Component(ffsid, "FrostFS ID", $tags="smart-contract", $descr="Stores namespaces and users") + Component(policy, "Policy", $tags="smart-contract", $descr="Stores APE rules") +} + +Rel_R(user, verify, "Requests", "gRPC") +Rel_R(verify, apesvc, "Access control") +Rel_R(apesvc, objsvc, "Operation") +Rel_D(apesvc, NeoGo, "Get data to validate request") +Rel("NeoGo", ffsid, "Fetch users") +Rel("NeoGo", policy, "Fetch policies") + +SHOW_LEGEND(true) +@enduml \ No newline at end of file diff --git a/docs/images/authentication/authoverview.svg b/docs/images/authentication/authoverview.svg new file mode 100644 index 0000000000..a34a68da0c --- /dev/null +++ b/docs/images/authentication/authoverview.svg @@ -0,0 +1 @@ +FrostFS Storage[Container]Blockchain[Container]Sign Service Check request signatureAPE ServiceObject serviceNeoGoFrostFS ID Stores namespaces andusersPolicy Stores APE rulesUser User with private keyRequests[gRPC]Access controlOperationGet data to validaterequestFetch usersFetch policiesLegend  person  component  container boundary(dashed)  smart-contract(last text color)  \ No newline at end of file From 7bc30038032825dec6ed122384842ed152098892 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 23 Apr 2024 14:12:37 +0300 Subject: [PATCH 0515/1413] [#1104] docs: Add bearer token description to auth doc This is about authentication only and eACL is deprecated, so only mention `allow_impersonate` flag. Signed-off-by: Evgenii Stratonikov --- docs/authentication.md | 17 +++++++++++++++-- docs/images/authentication/impersonate.puml | 15 +++++++++++++++ docs/images/authentication/impersonate.svg | 1 + 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 docs/images/authentication/impersonate.puml create mode 100644 docs/images/authentication/impersonate.svg diff --git a/docs/authentication.md b/docs/authentication.md index 4efb03f934..544839b2c5 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -35,7 +35,18 @@ The hash algorithm used is SHA-256 ECDSA public key corresponding to the private key being used to sign a message. It is the primary user identity and is used to determine the request originator. -## Session token +## Tokens + +Generally, the request owner, i.e. an account all access control checks are applied to +is taken from the request signature. +However, session and bearer tokens can alter authentication process by making "effective" request owner differ from the actual one. +The general scheme is given by the following picture: + +![Token processing](images/authentication/impersonate.svg) + +It is important to note, that the token is only valid when the request signature corresponds to the actor token is issued to. + +### Session token Session token can override the rules of determining request owner. It is defined in the [frostfs-api](https://git.frostfs.info/TrueCloudLab/frostfs-api/src/branch/master/session/types.proto#L89). @@ -50,7 +61,9 @@ Session token may have some restrictions: 2. Set of operations it applies to. 3. The entity it is given to. This is provided in `session_key` field containing the public key. -## Bearer token +### Bearer token + +Bearer token is generally used for access control but can also affect authentication if `allow_impersonate` flag is set. With this flag it behaves similarly to session token. ## FrostFS ID diff --git a/docs/images/authentication/impersonate.puml b/docs/images/authentication/impersonate.puml new file mode 100644 index 0000000000..e9feae6e58 --- /dev/null +++ b/docs/images/authentication/impersonate.puml @@ -0,0 +1,15 @@ +@startuml impersonate +start + +if (The request has bearer token with allow_impersonate=true?) then (yes) + :Treat bearer token issuer as the request owner.; + end +(no) elseif (The request has session token?) then (yes) + :Treat session token issuer as the request owner.; + end +else (no) + :Determine request owner from the request signature.; + end +endif + +@enduml \ No newline at end of file diff --git a/docs/images/authentication/impersonate.svg b/docs/images/authentication/impersonate.svg new file mode 100644 index 0000000000..add2c5439f --- /dev/null +++ b/docs/images/authentication/impersonate.svg @@ -0,0 +1 @@ +yesThe request has bearer token with allow_impersonate=true?Treat bearer token issuer as the request owner.yesThe request has session token?nonoTreat session token issuer as the request owner.Determine request owner from the request signature. \ No newline at end of file From 1f02ac25665af1c7d9c8b882e2c859147793ba02 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 24 Apr 2024 14:59:41 +0300 Subject: [PATCH 0516/1413] [#1103] pre-commit: Exclude `*.svg` Signed-off-by: Anton Nikiforov --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 13284b9c54..d2d90fa5cb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: trailing-whitespace args: [--markdown-linebreak-ext=md] - id: end-of-file-fixer - exclude: ".key$" + exclude: "(.key|.svg)$" - repo: https://github.com/shellcheck-py/shellcheck-py rev: v0.9.0.6 From 700e891b854f9a21f81614ef968dcc66a4a987da Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 24 Apr 2024 15:01:19 +0300 Subject: [PATCH 0517/1413] [#1103] Fix end of file and trim trailing whitespace Signed-off-by: Anton Nikiforov --- dev/.vscode-example/launch.json | 2 +- docs/authentication.md | 2 +- docs/images/authentication/authoverview.puml | 4 ++-- pkg/services/tree/ape.go | 4 +--- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/dev/.vscode-example/launch.json b/dev/.vscode-example/launch.json index 6aedde85ec..990fd42a82 100644 --- a/dev/.vscode-example/launch.json +++ b/dev/.vscode-example/launch.json @@ -250,4 +250,4 @@ "stopAll": true } ] -} \ No newline at end of file +} diff --git a/docs/authentication.md b/docs/authentication.md index 544839b2c5..3fe5ca512f 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -67,4 +67,4 @@ Bearer token is generally used for access control but can also affect authentica ## FrostFS ID -## APE \ No newline at end of file +## APE diff --git a/docs/images/authentication/authoverview.puml b/docs/images/authentication/authoverview.puml index 1242fdfc6c..20cac9f525 100644 --- a/docs/images/authentication/authoverview.puml +++ b/docs/images/authentication/authoverview.puml @@ -5,7 +5,7 @@ AddElementTag("smart-contract", $bgColor=#0abab5) Person(user, "User", "User with private key") -Container_Boundary(stor, "FrostFS Storage") { +Container_Boundary(stor, "FrostFS Storage") { Component(verify, "Sign Service", $descr="Check request signature") Component(apesvc, "APE Service") Component(objsvc, "Object service") @@ -25,4 +25,4 @@ Rel("NeoGo", ffsid, "Fetch users") Rel("NeoGo", policy, "Fetch policies") SHOW_LEGEND(true) -@enduml \ No newline at end of file +@enduml diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index f587215096..76ec254f05 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -19,9 +19,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) -var ( - subjectNotFoundErrorMessage = "subject not found" -) +var subjectNotFoundErrorMessage = "subject not found" func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error { namespace := "" From 167c52a1a977301f9899d9b617aaa34545c7bd73 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 23 Apr 2024 15:21:29 +0300 Subject: [PATCH 0518/1413] [#1103] node: Reduce amount of lines for method `StorageEngine.head` Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/engine/head.go | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index ba5e7cc1d2..f56e1b7723 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -67,20 +67,17 @@ func (e *StorageEngine) Head(ctx context.Context, prm HeadPrm) (res HeadRes, err func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.head") defer span.End() - if e.metrics != nil { defer elapsed("Head", e.metrics.AddMethodDuration)() } var ( - head *objectSDK.Object - siErr *objectSDK.SplitInfoError - outSI *objectSDK.SplitInfo - + head *objectSDK.Object + siErr *objectSDK.SplitInfoError + outSI *objectSDK.SplitInfo outError error = new(apistatus.ObjectNotFound) + shPrm shard.HeadPrm ) - - var shPrm shard.HeadPrm shPrm.SetAddress(prm.addr) shPrm.SetRaw(prm.raw) @@ -94,44 +91,34 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) if outSI == nil { outSI = objectSDK.NewSplitInfo() } - util.MergeSplitInfo(siErr.SplitInfo(), outSI) - _, withLink := outSI.Link() _, withLast := outSI.LastPart() - // stop iterating over shards if SplitInfo structure is complete if withLink && withLast { return true } - return false case client.IsErrObjectAlreadyRemoved(err): outError = err - return true // stop, return it back case shard.IsErrObjectExpired(err): // object is found but should not // be returned outError = new(apistatus.ObjectNotFound) - return true default: e.reportShardError(sh, "could not head object from shard", err) return false } } - head = res.Object() - return true }) if outSI != nil { return HeadRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(outSI)) - } - - if head == nil { + } else if head == nil { return HeadRes{}, outError } From 112a7c690f55a334eb05ce2b219f4551d928f45f Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 22 Apr 2024 09:43:42 +0300 Subject: [PATCH 0519/1413] [#1103] node: Implement `Get\Head` requests for EC object Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/object/get.go | 4 + cmd/frostfs-cli/modules/object/head.go | 4 + cmd/frostfs-cli/modules/object/range.go | 44 +++++++ cmd/frostfs-node/object.go | 4 +- go.mod | 4 +- go.sum | 8 +- internal/logs/logs.go | 9 ++ pkg/local_object_storage/engine/get.go | 14 +++ pkg/local_object_storage/engine/head.go | 11 ++ pkg/local_object_storage/metabase/exists.go | 4 + pkg/local_object_storage/metabase/get.go | 29 +++++ pkg/local_object_storage/metabase/get_test.go | 39 ++++++ pkg/local_object_storage/metabase/put.go | 39 ++++++ pkg/local_object_storage/metabase/util.go | 10 ++ pkg/local_object_storage/util/ecinfo.go | 25 ++++ pkg/local_object_storage/util/ecinfo_test.go | 56 +++++++++ pkg/network/cache/multi.go | 6 +- pkg/services/object/get/assemble.go | 2 + pkg/services/object/get/assembleec.go | 79 ++++++++++++ pkg/services/object/get/assemblerec.go | 117 ++++++++++++++++++ pkg/services/object/get/get.go | 13 ++ pkg/services/object/get/local.go | 6 + pkg/services/object/get/remote.go | 25 +++- pkg/services/object/get/request.go | 4 + pkg/services/object/get/service.go | 4 + pkg/services/object/get/status.go | 1 + pkg/services/object/get/v2/get_forwarder.go | 3 + pkg/services/object/get/v2/head_forwarder.go | 3 + pkg/services/object/get/v2/service.go | 8 ++ pkg/services/object/get/v2/util.go | 15 +++ 30 files changed, 579 insertions(+), 11 deletions(-) create mode 100644 pkg/local_object_storage/util/ecinfo.go create mode 100644 pkg/local_object_storage/util/ecinfo_test.go create mode 100644 pkg/services/object/get/assembleec.go create mode 100644 pkg/services/object/get/assemblerec.go diff --git a/cmd/frostfs-cli/modules/object/get.go b/cmd/frostfs-cli/modules/object/get.go index 9a888ccd39..f1edccba2f 100644 --- a/cmd/frostfs-cli/modules/object/get.go +++ b/cmd/frostfs-cli/modules/object/get.go @@ -99,6 +99,10 @@ func getObject(cmd *cobra.Command, _ []string) { return } + if ok := printECInfoErr(cmd, err); ok { + return + } + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) } diff --git a/cmd/frostfs-cli/modules/object/head.go b/cmd/frostfs-cli/modules/object/head.go index f97ef952df..14797dc414 100644 --- a/cmd/frostfs-cli/modules/object/head.go +++ b/cmd/frostfs-cli/modules/object/head.go @@ -70,6 +70,10 @@ func getObjectHeader(cmd *cobra.Command, _ []string) { return } + if ok := printECInfoErr(cmd, err); ok { + return + } + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) } diff --git a/cmd/frostfs-cli/modules/object/range.go b/cmd/frostfs-cli/modules/object/range.go index 0eee7bdbab..9ba752237f 100644 --- a/cmd/frostfs-cli/modules/object/range.go +++ b/cmd/frostfs-cli/modules/object/range.go @@ -146,6 +146,50 @@ func marshalSplitInfo(cmd *cobra.Command, info *objectSDK.SplitInfo) ([]byte, er } } +func printECInfoErr(cmd *cobra.Command, err error) bool { + var errECInfo *objectSDK.ECInfoError + + ok := errors.As(err, &errECInfo) + + if ok { + cmd.PrintErrln("Object is erasure-encoded, ec information received.") + printECInfo(cmd, errECInfo.ECInfo()) + } + + return ok +} + +func printECInfo(cmd *cobra.Command, info *objectSDK.ECInfo) { + bs, err := marshalECInfo(cmd, info) + commonCmd.ExitOnErr(cmd, "can't marshal split info: %w", err) + + cmd.Println(string(bs)) +} + +func marshalECInfo(cmd *cobra.Command, info *objectSDK.ECInfo) ([]byte, error) { + toJSON, _ := cmd.Flags().GetBool(commonflags.JSON) + toProto, _ := cmd.Flags().GetBool("proto") + switch { + case toJSON && toProto: + return nil, errors.New("'--json' and '--proto' flags are mutually exclusive") + case toJSON: + return info.MarshalJSON() + case toProto: + return info.Marshal() + default: + b := bytes.NewBuffer(nil) + b.WriteString("Total chunks: " + strconv.Itoa(int(info.Chunks[0].Total))) + for _, chunk := range info.Chunks { + var id oid.ID + if err := id.Decode(chunk.ID.GetValue()); err != nil { + return nil, fmt.Errorf("unable to decode chunk id: %w", err) + } + b.WriteString("\n Index: " + strconv.Itoa(int(chunk.Index)) + " ID: " + id.String()) + } + return b.Bytes(), nil + } +} + func getRangeList(cmd *cobra.Command) ([]objectSDK.Range, error) { v := cmd.Flag("range").Value.String() if len(v) == 0 { diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 6160bbc76b..a7a084fd1c 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -173,7 +173,7 @@ func initObjectService(c *cfg) { sSearchV2 := createSearchSvcV2(sSearch, keyStorage) - sGet := createGetService(c, keyStorage, traverseGen, c.clientCache) + sGet := createGetService(c, keyStorage, traverseGen, c.clientCache, c.cfgObject.cnrSource) *c.cfgObject.getSvc = *sGet // need smth better @@ -358,6 +358,7 @@ func createSearchSvcV2(sSearch *searchsvc.Service, keyStorage *util.KeyStorage) func createGetService(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.TraverserGenerator, coreConstructor *cache.ClientCache, + containerSource containercore.Source, ) *getsvc.Service { ls := c.cfgObject.cfgLocalStorage.localStorage @@ -369,6 +370,7 @@ func createGetService(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.Tra placement.SuccessAfter(1), ), coreConstructor, + containerSource, getsvc.WithLogger(c.log)) } diff --git a/go.mod b/go.mod index 8cfea305db..f5469dee67 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240327095603-491a47e7fe24 + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240424080726-20ab57bf7ec3 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index 76ed7e5dc9..0a885cb2f3 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240327095603-491a47e7fe24 h1:uIkl0mKWwDICUZTbNWZ38HLYDBI9rMgdAhYQWZ0C9iQ= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240327095603-491a47e7fe24/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c h1:RFDrNsF2e+EJfaB8lZrRRxNjQkLfM09gnEyudvGuc10= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 h1:FzurjElUwC7InY9v5rzXReKbfBL5yRJKSWJPq6BKhH0= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92 h1:hSyM52d8yIaOpYQlLlVYdrGbgCsvIDjwl3AJaJUlYPU= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240329104804-ec0cb2169f92/go.mod h1:i0RKqiF4z3UOxLSNwhHw+cUz/JyYWuTRpnn9ere4Y3w= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240424080726-20ab57bf7ec3 h1:7Sd/J2IM0uGpmFKBgseUh6/JsdJN06b8W8UZMKAUDZg= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240424080726-20ab57bf7ec3/go.mod h1:wDFmMP7l00Xd5VZVzF2MuhyJCnotyhfxHYnvrEEG/e4= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a h1:wbndKvHbwDQiSMQWL75RxiTZCeUyCi7NUj1lsfdAGkc= diff --git a/internal/logs/logs.go b/internal/logs/logs.go index bd67217c40..e76ab10b6a 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -99,9 +99,17 @@ const ( GetRemoteCallFailed = "remote call failed" GetCanNotAssembleTheObject = "can not assemble the object" GetTryingToAssembleTheObject = "trying to assemble the object..." + GetTryingToAssembleTheECObject = "trying to assemble the ec object..." GetAssemblingSplittedObject = "assembling splitted object..." + GetAssemblingECObject = "assembling erasure-coded object..." + GetUnableToGetAllPartsECObject = "unable to get all parts, continue to reconstruct with existed" + GetUnableToGetPartECObject = "unable to get part of the erasure-encoded object" + GetUnableToHeadPartECObject = "unable to head part of the erasure-encoded object" + GetUnableToGetECObjectContainer = "unable to get container for erasure-coded object" GetAssemblingSplittedObjectCompleted = "assembling splitted object completed" + GetAssemblingECObjectCompleted = "assembling erasure-coded object completed" GetFailedToAssembleSplittedObject = "failed to assemble splitted object" + GetFailedToAssembleECObject = "failed to assemble erasure-coded object" GetCouldNotGenerateContainerTraverser = "could not generate container traverser" GetCouldNotConstructRemoteNodeClient = "could not construct remote node client" GetCouldNotWriteHeader = "could not write header" @@ -111,6 +119,7 @@ const ( GetCompletingTheOperation = "completing the operation" GetRequestedObjectWasMarkedAsRemoved = "requested object was marked as removed" GetRequestedObjectIsVirtual = "requested object is virtual" + GetRequestedObjectIsEC = "requested object is erasure-coded" GetRequestedRangeIsOutOfObjectBounds = "requested range is out of object bounds" PutAdditionalContainerBroadcastFailure = "additional container broadcast failure" SearchReturnResultDirectly = "return result directly" diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index f77c44226c..991af3d1a3 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -88,6 +88,10 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { return GetRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo)) } + if it.ECInfo != nil { + return GetRes{}, logicerr.Wrap(objectSDK.NewECInfoError(it.ECInfo)) + } + if it.ObjectExpired { return GetRes{}, errNotFound } @@ -119,6 +123,7 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { type getShardIterator struct { Object *objectSDK.Object SplitInfo *objectSDK.SplitInfo + ECInfo *objectSDK.ECInfo OutError error ShardWithMeta hashedShard MetaError error @@ -130,6 +135,7 @@ type getShardIterator struct { Engine *StorageEngine splitInfoErr *objectSDK.SplitInfoError + ecInfoErr *objectSDK.ECInfoError } func (i *getShardIterator) tryGetWithMeta(ctx context.Context) { @@ -164,6 +170,14 @@ func (i *getShardIterator) tryGetWithMeta(ctx context.Context) { // stop iterating over shards if SplitInfo structure is complete return withLink && withLast + case errors.As(err, &i.ecInfoErr): + if i.ECInfo == nil { + i.ECInfo = objectSDK.NewECInfo() + } + + util.MergeECInfo(i.ecInfoErr.ECInfo(), i.ECInfo) + // stop iterating over shards if ECInfo structure is complete + return len(i.ECInfo.Chunks) == int(i.ECInfo.Chunks[0].Total) case client.IsErrObjectAlreadyRemoved(err): i.OutError = err return true // stop, return it back diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index f56e1b7723..1c61ca4555 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -75,6 +75,8 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) head *objectSDK.Object siErr *objectSDK.SplitInfoError outSI *objectSDK.SplitInfo + eiErr *objectSDK.ECInfoError + outEI *objectSDK.ECInfo outError error = new(apistatus.ObjectNotFound) shPrm shard.HeadPrm ) @@ -99,6 +101,13 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) return true } return false + case errors.As(err, &eiErr): + if outEI == nil { + outEI = objectSDK.NewECInfo() + } + util.MergeECInfo(eiErr.ECInfo(), outEI) + // stop iterating over shards if ECInfo structure is complete + return len(outEI.Chunks) == int(outEI.Chunks[0].Total) case client.IsErrObjectAlreadyRemoved(err): outError = err return true // stop, return it back @@ -118,6 +127,8 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) if outSI != nil { return HeadRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(outSI)) + } else if outEI != nil { + return HeadRes{}, logicerr.Wrap(objectSDK.NewECInfoError(outEI)) } else if head == nil { return HeadRes{}, outError } diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index aa9aba1064..bf6766c058 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -108,6 +108,10 @@ func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (exists b return false, logicerr.Wrap(objectSDK.NewSplitInfoError(splitInfo)) } + // if parent bucket is empty, then check if object exists in ec bucket + if data := getFromBucket(tx, ecInfoBucketName(cnr, key), objKey); len(data) != 0 { + return false, getECInfoError(tx, cnr, data) + } // if parent bucket is empty, then check if object exists in typed buckets return firstIrregularObjectType(tx, cnr, objKey) != objectSDK.TypeRegular, nil diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index d18331a3de..aa19502e8b 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -110,6 +110,11 @@ func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw b return obj, obj.Unmarshal(data) } + data = getFromBucket(tx, ecInfoBucketName(cnr, bucketName), key) + if len(data) != 0 { + return nil, getECInfoError(tx, cnr, data) + } + // if not found then check in tombstone index data = getFromBucket(tx, tombstoneBucketName(cnr, bucketName), key) if len(data) != 0 { @@ -185,3 +190,27 @@ func getSplitInfoError(tx *bbolt.Tx, cnr cid.ID, key []byte) error { return logicerr.Wrap(new(apistatus.ObjectNotFound)) } + +func getECInfoError(tx *bbolt.Tx, cnr cid.ID, data []byte) error { + offset := 0 + ecInfo := objectSDK.NewECInfo() + for offset < len(data) { + key := data[offset : offset+objectKeySize] + // check in primary index + ojbData := getFromBucket(tx, primaryBucketName(cnr, make([]byte, bucketKeySize)), key) + if len(data) != 0 { + obj := objectSDK.New() + if err := obj.Unmarshal(ojbData); err != nil { + return err + } + chunk := objectSDK.ECChunk{} + id, _ := obj.ID() + chunk.SetID(id) + chunk.Index = obj.ECHeader().Index() + chunk.Total = obj.ECHeader().Total() + ecInfo.AddChunk(chunk) + } + offset += objectKeySize + } + return logicerr.Wrap(objectSDK.NewECInfoError(ecInfo)) +} diff --git a/pkg/local_object_storage/metabase/get_test.go b/pkg/local_object_storage/metabase/get_test.go index af6b413274..247ddf9cdd 100644 --- a/pkg/local_object_storage/metabase/get_test.go +++ b/pkg/local_object_storage/metabase/get_test.go @@ -3,6 +3,7 @@ package meta_test import ( "bytes" "context" + "errors" "fmt" "os" "runtime" @@ -15,8 +16,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) @@ -109,6 +112,42 @@ func TestDB_Get(t *testing.T) { require.True(t, binaryEqual(child.CutPayload(), newChild)) }) + t.Run("put erasure-coded object", func(t *testing.T) { + cnr := cidtest.ID() + virtual := testutil.GenerateObjectWithCID(cnr) + c, err := erasurecode.NewConstructor(3, 1) + require.NoError(t, err) + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + parts, err := c.Split(virtual, &pk.PrivateKey) + require.NoError(t, err) + for _, part := range parts { + err = putBig(db, part) + var eiError *objectSDK.ECInfoError + if err != nil && !errors.As(err, &eiError) { + require.NoError(t, err) + } + } + _, err = metaGet(db, object.AddressOf(virtual), true) + var eiError *objectSDK.ECInfoError + require.ErrorAs(t, err, &eiError) + require.Equal(t, len(eiError.ECInfo().Chunks), len(parts)) + for _, chunk := range eiError.ECInfo().Chunks { + var found bool + for _, part := range parts { + partID, _ := part.ID() + var chunkID oid.ID + require.NoError(t, chunkID.ReadFromV2(chunk.ID)) + if chunkID.Equals(partID) { + found = true + } + } + if !found { + require.Fail(t, "chunk not found") + } + } + }) + t.Run("get removed object", func(t *testing.T) { obj := oidtest.Address() ts := oidtest.Address() diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 429d981fe3..2822303a0a 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -1,6 +1,7 @@ package meta import ( + "bytes" "context" "encoding/binary" "errors" @@ -264,6 +265,13 @@ func putUniqueIndexes( if err != nil { return err } + + if ecHead := obj.GetECHeader(); ecHead != nil { + err = putECInfo(tx, cnr, objKey, ecHead) + if err != nil { + return err + } + } } return nil @@ -571,3 +579,34 @@ func isLinkObject(obj *objectSDK.Object) bool { func isLastObject(obj *objectSDK.Object) bool { return len(obj.Children()) == 0 && obj.Parent() != nil } + +func putECInfo(tx *bbolt.Tx, + cnr cid.ID, objKey []byte, + ecHead *objectSDK.ECHeader, +) error { + parentID := objectKey(ecHead.Parent(), make([]byte, objectKeySize)) + bucketName := make([]byte, bucketKeySize) + + val := getFromBucket(tx, ecInfoBucketName(cnr, bucketName), parentID) + if len(val) == 0 { + val = objKey + } else { + offset := 0 + found := false + for offset < len(val) { + if bytes.Equal(objKey, val[offset:offset+objectKeySize]) { + found = true + break + } + offset += objectKeySize + } + if !found { + val = append(val, objKey...) + } + } + return putUniqueIndexItem(tx, namedBucketItem{ + name: ecInfoBucketName(cnr, make([]byte, bucketKeySize)), + key: parentID, + val: val, + }) +} diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index d46a421a3f..9249ae49b4 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -119,6 +119,11 @@ const ( // Key: container ID + type // Value: container size in bytes as little-endian uint64 containerCountersPrefix + + // ecInfoPrefix is used for storing relation between EC parent id and chunk id. + // Key: container ID + type + // Value: Object id + ecInfoPrefix ) const ( @@ -190,6 +195,11 @@ func splitBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, splitPrefix, key) } +// ecInfoBucketName returns _ecinfo. +func ecInfoBucketName(cnr cid.ID, key []byte) []byte { + return bucketName(cnr, ecInfoPrefix, key) +} + // addressKey returns key for K-V tables when key is a whole address. func addressKey(addr oid.Address, key []byte) []byte { addr.Container().Encode(key) diff --git a/pkg/local_object_storage/util/ecinfo.go b/pkg/local_object_storage/util/ecinfo.go new file mode 100644 index 0000000000..a92fbceea5 --- /dev/null +++ b/pkg/local_object_storage/util/ecinfo.go @@ -0,0 +1,25 @@ +package util + +import ( + "bytes" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" +) + +// MergeECInfo ignores conflicts and rewrites `to` with non empty values +// from `from`. +func MergeECInfo(from, to *objectSDK.ECInfo) *objectSDK.ECInfo { + for _, fchunk := range from.Chunks { + add := true + for _, tchunk := range to.Chunks { + if bytes.Equal(tchunk.ID.GetValue(), fchunk.ID.GetValue()) { + add = false + break + } + } + if add { + to.AddChunk(*objectSDK.NewECChunkFromV2(&fchunk)) + } + } + return to +} diff --git a/pkg/local_object_storage/util/ecinfo_test.go b/pkg/local_object_storage/util/ecinfo_test.go new file mode 100644 index 0000000000..0810060880 --- /dev/null +++ b/pkg/local_object_storage/util/ecinfo_test.go @@ -0,0 +1,56 @@ +package util + +import ( + "crypto/rand" + "testing" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/stretchr/testify/require" +) + +func TestMergeECInfo(t *testing.T) { + id := generateV2ID() + target := objectSDK.NewECInfo() + var chunk objectSDK.ECChunk + chunk.Total = 2 + chunk.Index = 0 + chunk.SetID(id) + target.AddChunk(chunk) + + t.Run("merge empty", func(t *testing.T) { + to := objectSDK.NewECInfo() + + result := MergeECInfo(target, to) + require.Equal(t, result, target) + }) + + t.Run("merge existed", func(t *testing.T) { + to := objectSDK.NewECInfo() + to.AddChunk(chunk) + + result := MergeECInfo(target, to) + require.Equal(t, result, target) + }) + t.Run("merge extend", func(t *testing.T) { + to := objectSDK.NewECInfo() + var chunk objectSDK.ECChunk + chunk.Total = 2 + chunk.Index = 1 + chunk.SetID(generateV2ID()) + to.AddChunk(chunk) + + result := MergeECInfo(target, to) + require.Equal(t, len(result.Chunks), 2) + }) +} + +func generateV2ID() oid.ID { + var buf [32]byte + _, _ = rand.Read(buf[:]) + + var id oid.ID + _ = id.Decode(buf[:]) + + return id +} diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 5dd206283f..f19510d769 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -167,8 +167,9 @@ func (x *multiClient) iterateClients(ctx context.Context, f func(clientcore.Clie // from the SDK client; should not be considered // as a connection error var siErr *objectSDK.SplitInfoError + var eiErr *objectSDK.ECInfoError - success := err == nil || errors.Is(err, context.Canceled) || errors.As(err, &siErr) + success := err == nil || errors.Is(err, context.Canceled) || errors.As(err, &siErr) || errors.As(err, &eiErr) if success || firstErr == nil || errors.Is(firstErr, errRecentlyFailed) { firstErr = err } @@ -196,7 +197,8 @@ func (x *multiClient) ReportError(err error) { // from the SDK client; should not be considered // as a connection error var siErr *objectSDK.SplitInfoError - if errors.As(err, &siErr) { + var eiErr *objectSDK.ECInfoError + if errors.As(err, &siErr) || errors.As(err, &eiErr) { return } diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index 6a8c5c818a..548e8e45db 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -139,9 +139,11 @@ func (r *request) getObjectWithIndependentRequest(ctx context.Context, prm Reque remoteStorageConstructor: r.remoteStorageConstructor, epochSource: r.epochSource, localStorage: r.localStorage, + containerSource: r.containerSource, prm: prm, infoSplit: objectSDK.NewSplitInfo(), + infoEC: objectSDK.NewECInfo(), log: r.log, } diff --git a/pkg/services/object/get/assembleec.go b/pkg/services/object/get/assembleec.go new file mode 100644 index 0000000000..d288ef2497 --- /dev/null +++ b/pkg/services/object/get/assembleec.go @@ -0,0 +1,79 @@ +package getsvc + +import ( + "context" + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + "go.uber.org/zap" +) + +func (r *request) assembleEC(ctx context.Context) { + if r.isRaw() { + r.log.Debug(logs.GetCanNotAssembleTheObject) + return + } + + // Any access tokens are not expected to be used in the assembly process: + // - there is no requirement to specify child objects in session/bearer + // token for `GET`/`GETRANGE`/`RANGEHASH` requests in the API protocol, + // and, therefore, their missing in the original request should not be + // considered as error; on the other hand, without session for every child + // object, it is impossible to attach bearer token in the new generated + // requests correctly because the token has not been issued for that node's + // key; + // - the assembly process is expected to be handled on a container node + // only since the requests forwarding mechanism presentation; such the + // node should have enough rights for getting any child object by design. + r.prm.common.ForgetTokens() + + // Do not use forwarding during assembly stage. + // Request forwarding closure inherited in produced + // `execCtx` so it should be disabled there. + r.disableForwarding() + + r.log.Debug(logs.GetTryingToAssembleTheECObject) + + assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.containerSource, r.log) + + r.log.Debug(logs.GetAssemblingECObject, + zap.Stringer("address", r.address()), + zap.Uint64("range_offset", r.ctxRange().GetOffset()), + zap.Uint64("range_length", r.ctxRange().GetLength()), + ) + defer r.log.Debug(logs.GetAssemblingECObjectCompleted, + zap.Stringer("address", r.address()), + zap.Uint64("range_offset", r.ctxRange().GetOffset()), + zap.Uint64("range_length", r.ctxRange().GetLength()), + ) + + obj, err := assembler.Assemble(ctx, r.prm.objWriter, r.headOnly()) + if err != nil { + r.log.Warn(logs.GetFailedToAssembleECObject, + zap.Error(err), + zap.Stringer("address", r.address()), + zap.Uint64("range_offset", r.ctxRange().GetOffset()), + zap.Uint64("range_length", r.ctxRange().GetLength()), + ) + } + + var errRemoved *apistatus.ObjectAlreadyRemoved + var errOutOfRange *apistatus.ObjectOutOfRange + + switch { + default: + r.status = statusUndefined + r.err = err + case err == nil: + r.status = statusOK + r.err = nil + r.collectedObject = obj + case errors.As(err, &errRemoved): + r.status = statusINHUMED + r.err = errRemoved + case errors.As(err, &errOutOfRange): + r.status = statusOutOfRange + r.err = errOutOfRange + } +} diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go new file mode 100644 index 0000000000..d73d771cf8 --- /dev/null +++ b/pkg/services/object/get/assemblerec.go @@ -0,0 +1,117 @@ +package getsvc + +import ( + "context" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.uber.org/zap" + "golang.org/x/sync/errgroup" +) + +type assemblerec struct { + addr oid.Address + ecInfo *objectSDK.ECInfo + rng *objectSDK.Range + objGetter objectGetter + cs container.Source + log *logger.Logger +} + +func newAssemblerEC( + addr oid.Address, + ecInfo *objectSDK.ECInfo, + rng *objectSDK.Range, + objGetter objectGetter, + cs container.Source, + log *logger.Logger, +) *assemblerec { + return &assemblerec{ + addr: addr, + rng: rng, + ecInfo: ecInfo, + objGetter: objGetter, + cs: cs, + log: log, + } +} + +// Assemble assembles erasure-coded object and writes it's content to ObjectWriter. +// It returns parent object. +func (a *assemblerec) Assemble(ctx context.Context, writer ObjectWriter, headOnly bool) (*objectSDK.Object, error) { + parts := a.retrieveParts(ctx, headOnly) + cnt, err := a.cs.Get(a.addr.Container()) + if err != nil { + return nil, err + } + c, err := erasurecode.NewConstructor( + policy.ECDataCount(cnt.Value.PlacementPolicy()), + policy.ECParityCount(cnt.Value.PlacementPolicy()), + ) + if err != nil { + return nil, err + } + if headOnly { + obj, err := c.ReconstructHeader(parts) + if err == nil { + return obj, writer.WriteHeader(ctx, obj) + } + return nil, err + } + obj, err := c.Reconstruct(parts) + if err == nil { + err = writer.WriteHeader(ctx, obj.CutPayload()) + if err == nil { + err = writer.WriteChunk(ctx, obj.Payload()) + if err != nil { + return nil, err + } + } + } + return obj, err +} + +func (a *assemblerec) retrieveParts(mainCtx context.Context, headOnly bool) []*objectSDK.Object { + parts := make([]*objectSDK.Object, int(a.ecInfo.Chunks[0].Total)) + errGroup, ctx := errgroup.WithContext(mainCtx) + + for i := range a.ecInfo.Chunks { + chunk := a.ecInfo.Chunks[i] + errGroup.Go(func() error { + objID := new(oid.ID) + err := objID.ReadFromV2(chunk.ID) + if err != nil { + return fmt.Errorf("invalid object ID: %w", err) + } + var obj *objectSDK.Object + if headOnly { + obj, err = a.objGetter.HeadObject(ctx, *objID) + if err != nil { + a.log.Debug(logs.GetUnableToHeadPartECObject, zap.Stringer("part_id", objID), zap.Error(err)) + return nil + } + } else { + sow := NewSimpleObjectWriter() + obj, err = a.objGetter.GetObjectAndWritePayload(ctx, *objID, nil, sow) + if err != nil { + a.log.Debug(logs.GetUnableToGetPartECObject, zap.Stringer("part_id", objID), zap.Error(err)) + return nil + } + obj.SetPayload(sow.pld) + } + parts[chunk.Index] = obj + return nil + }) + } + + if err := errGroup.Wait(); err != nil { + a.log.Debug(logs.GetUnableToGetAllPartsECObject, zap.Error(err)) + } + return parts +} diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 3d5547047c..9738935d2a 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -73,9 +73,12 @@ func (s *Service) get(ctx context.Context, prm RequestParameters) error { remoteStorageConstructor: s.remoteStorageConstructor, epochSource: s.epochSource, localStorage: s.localStorage, + containerSource: s.containerSource, prm: prm, infoSplit: objectSDK.NewSplitInfo(), + infoEC: objectSDK.NewECInfo(), + log: s.log, } exec.setLogger(s.log) @@ -106,6 +109,16 @@ func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) { exec.assemble(ctx) case statusOutOfRange: exec.log.Debug(logs.GetRequestedRangeIsOutOfObjectBounds) + case statusEC: + if !exec.isLocal() { + if execCnr { + exec.executeOnContainer(ctx) + exec.analyzeStatus(ctx, false) + } else { + exec.log.Debug(logs.GetRequestedObjectIsEC) + exec.assembleEC(ctx) + } + } default: exec.log.Debug(logs.OperationFinishedWithError, zap.Error(exec.err), diff --git a/pkg/services/object/get/local.go b/pkg/services/object/get/local.go index 2574650190..fcfc9befcb 100644 --- a/pkg/services/object/get/local.go +++ b/pkg/services/object/get/local.go @@ -5,6 +5,7 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -22,6 +23,7 @@ func (r *request) executeLocal(ctx context.Context) { r.collectedObject, err = r.get(ctx) var errSplitInfo *objectSDK.SplitInfoError + var errECInfo *objectSDK.ECInfoError var errRemoved *apistatus.ObjectAlreadyRemoved var errOutOfRange *apistatus.ObjectOutOfRange @@ -42,6 +44,10 @@ func (r *request) executeLocal(ctx context.Context) { r.status = statusVIRTUAL mergeSplitInfo(r.splitInfo(), errSplitInfo.SplitInfo()) r.err = objectSDK.NewSplitInfoError(r.infoSplit) + case errors.As(err, &errECInfo): + r.status = statusEC + util.MergeECInfo(errECInfo.ECInfo(), r.infoEC) + r.err = objectSDK.NewECInfoError(r.infoEC) case errors.As(err, &errOutOfRange): r.status = statusOutOfRange r.err = errOutOfRange diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index cd94434cf8..302a4a4bc1 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -7,6 +7,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -27,15 +29,20 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { obj, err := r.getRemote(ctx, rs, info) var errSplitInfo *objectSDK.SplitInfoError + var errECInfo *objectSDK.ECInfoError var errRemoved *apistatus.ObjectAlreadyRemoved var errOutOfRange *apistatus.ObjectOutOfRange switch { default: + r.log.Debug(logs.GetRemoteCallFailed, zap.Error(err)) + if r.status == statusEC { + // we need to continue getting another chunks from another nodes + // in case of network issue + return false + } r.status = statusUndefined r.err = new(apistatus.ObjectNotFound) - - r.log.Debug(logs.GetRemoteCallFailed, zap.Error(err)) case err == nil: r.status = statusOK r.err = nil @@ -57,6 +64,20 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { r.status = statusVIRTUAL mergeSplitInfo(r.splitInfo(), errSplitInfo.SplitInfo()) r.err = objectSDK.NewSplitInfoError(r.infoSplit) + case errors.As(err, &errECInfo): + r.status = statusEC + util.MergeECInfo(r.infoEC, errECInfo.ECInfo()) + r.infoEC = errECInfo.ECInfo() + r.err = objectSDK.NewECInfoError(r.infoEC) + if r.isRaw() { + return len(r.infoEC.Chunks) == int(r.infoEC.Chunks[0].Total) + } + cnt, err := r.containerSource.Get(r.address().Container()) + if err == nil { + return len(r.infoEC.Chunks) == policy.ECDataCount(cnt.Value.PlacementPolicy()) + } + r.log.Debug(logs.GetUnableToGetECObjectContainer, zap.Error(err)) + return len(r.infoEC.Chunks) == int(r.infoEC.Chunks[0].Total) } return r.status != statusUndefined diff --git a/pkg/services/object/get/request.go b/pkg/services/object/get/request.go index b9223a6370..d0b79e30c2 100644 --- a/pkg/services/object/get/request.go +++ b/pkg/services/object/get/request.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" @@ -22,6 +23,8 @@ type request struct { infoSplit *objectSDK.SplitInfo + infoEC *objectSDK.ECInfo + log *logger.Logger collectedObject *objectSDK.Object @@ -33,6 +36,7 @@ type request struct { traverserGenerator traverserGenerator remoteStorageConstructor remoteStorageConstructor localStorage localStorage + containerSource container.Source } func (r *request) setLogger(l *logger.Logger) { diff --git a/pkg/services/object/get/service.go b/pkg/services/object/get/service.go index bdf01a977e..3413abeb7d 100644 --- a/pkg/services/object/get/service.go +++ b/pkg/services/object/get/service.go @@ -1,6 +1,7 @@ package getsvc import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) @@ -16,6 +17,7 @@ type Service struct { epochSource epochSource keyStore keyStorage remoteStorageConstructor remoteStorageConstructor + containerSource container.Source } // New creates, initializes and returns utility serving @@ -26,6 +28,7 @@ func New( e localStorageEngine, tg traverserGenerator, cc clientConstructor, + cs container.Source, opts ...Option, ) *Service { result := &Service{ @@ -39,6 +42,7 @@ func New( remoteStorageConstructor: &multiclientRemoteStorageConstructor{ clientConstructor: cc, }, + containerSource: cs, } for _, option := range opts { option(result) diff --git a/pkg/services/object/get/status.go b/pkg/services/object/get/status.go index 3a5eebe329..919338d7fb 100644 --- a/pkg/services/object/get/status.go +++ b/pkg/services/object/get/status.go @@ -6,6 +6,7 @@ const ( statusINHUMED statusVIRTUAL statusOutOfRange + statusEC ) type statusError struct { diff --git a/pkg/services/object/get/v2/get_forwarder.go b/pkg/services/object/get/v2/get_forwarder.go index 40aa3f62e7..774f986435 100644 --- a/pkg/services/object/get/v2/get_forwarder.go +++ b/pkg/services/object/get/v2/get_forwarder.go @@ -166,6 +166,9 @@ func (f *getRequestForwarder) readStream(ctx context.Context, c client.MultiAddr case *objectV2.SplitInfo: si := objectSDK.NewSplitInfoFromV2(v) return objectSDK.NewSplitInfoError(si) + case *objectV2.ECInfo: + ei := objectSDK.NewECInfoFromV2(v) + return objectSDK.NewECInfoError(ei) } } return nil diff --git a/pkg/services/object/get/v2/head_forwarder.go b/pkg/services/object/get/v2/head_forwarder.go index a1bce1517c..11286321a3 100644 --- a/pkg/services/object/get/v2/head_forwarder.go +++ b/pkg/services/object/get/v2/head_forwarder.go @@ -84,6 +84,9 @@ func (f *headRequestForwarder) forwardRequestToNode(ctx context.Context, addr ne case *objectV2.SplitInfo: si := objectSDK.NewSplitInfoFromV2(v) return nil, objectSDK.NewSplitInfoError(si) + case *objectV2.ECInfo: + ei := objectSDK.NewECInfoFromV2(v) + return nil, objectSDK.NewECInfoError(ei) } objv2 := new(objectV2.Object) diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index bcdc4120e9..682128df67 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -82,10 +82,13 @@ func (s *Service) Get(req *objectV2.GetRequest, stream objectSvc.GetObjectStream err = s.svc.Get(stream.Context(), *p) var splitErr *objectSDK.SplitInfoError + var ecErr *objectSDK.ECInfoError switch { case errors.As(err, &splitErr): return stream.Send(splitInfoResponse(splitErr.SplitInfo())) + case errors.As(err, &ecErr): + return stream.Send(ecInfoResponse(ecErr.ECInfo())) default: return err } @@ -123,11 +126,16 @@ func (s *Service) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV err = s.svc.Head(ctx, *p) var splitErr *objectSDK.SplitInfoError + var ecErr *objectSDK.ECInfoError if errors.As(err, &splitErr) { setSplitInfoHeadResponse(splitErr.SplitInfo(), resp) err = nil } + if errors.As(err, &ecErr) { + setECInfoHeadResponse(ecErr.ECInfo(), resp) + err = nil + } return resp, err } diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index 7f7dd74808..da64289852 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -270,6 +270,17 @@ func splitInfoResponse(info *objectSDK.SplitInfo) *objectV2.GetResponse { return resp } +func ecInfoResponse(info *objectSDK.ECInfo) *objectV2.GetResponse { + resp := new(objectV2.GetResponse) + + body := new(objectV2.GetResponseBody) + resp.SetBody(body) + + body.SetObjectPart(info.ToV2()) + + return resp +} + func splitInfoRangeResponse(info *objectSDK.SplitInfo) *objectV2.GetRangeResponse { resp := new(objectV2.GetRangeResponse) @@ -285,6 +296,10 @@ func setSplitInfoHeadResponse(info *objectSDK.SplitInfo, resp *objectV2.HeadResp resp.GetBody().SetHeaderPart(info.ToV2()) } +func setECInfoHeadResponse(info *objectSDK.ECInfo, resp *objectV2.HeadResponse) { + resp.GetBody().SetHeaderPart(info.ToV2()) +} + func toHashResponse(typ refs.ChecksumType, res *getsvc.RangeHashRes) *objectV2.GetRangeHashResponse { resp := new(objectV2.GetRangeHashResponse) From 411a8d0245e00accfc8c9d045f182f7f843faf79 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 1 Mar 2024 14:43:26 +0300 Subject: [PATCH 0520/1413] [#1004] blobovnicza: Use TTL for blobovnicza tree cache Signed-off-by: Anton Nikiforov --- .../internal/modules/storagecfg/config.go | 2 + cmd/frostfs-node/config.go | 36 ++++++---- .../shard/blobstor/blobovnicza/config.go | 38 ++++++++++ config/example/node.env | 4 ++ config/example/node.json | 4 ++ config/example/node.yaml | 2 + docs/storage-node-configuration.md | 26 ++++--- go.mod | 1 + go.sum | 2 + .../blobstor/blobovniczatree/blobovnicza.go | 6 +- .../blobstor/blobovniczatree/cache.go | 69 +++++++++++++------ .../blobovniczatree/concurrency_test.go | 1 + .../blobstor/blobovniczatree/control_test.go | 4 ++ .../blobstor/blobovniczatree/exists_test.go | 1 + .../blobstor/blobovniczatree/generic_test.go | 3 + .../blobstor/blobovniczatree/iterate_test.go | 1 + .../blobstor/blobovniczatree/option.go | 54 ++++++++++----- .../blobovniczatree/rebuild_failover_test.go | 1 + .../blobstor/blobovniczatree/rebuild_test.go | 4 ++ .../blobstor/blobstor_test.go | 2 + .../blobstor/perf_test.go | 1 + .../engine/engine_test.go | 2 + .../shard/gc_internal_test.go | 1 + pkg/local_object_storage/shard/lock_test.go | 1 + pkg/local_object_storage/shard/range_test.go | 1 + pkg/local_object_storage/shard/shard_test.go | 1 + 26 files changed, 203 insertions(+), 65 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/config.go b/cmd/frostfs-adm/internal/modules/storagecfg/config.go index a07ce32c66..77183fb497 100644 --- a/cmd/frostfs-adm/internal/modules/storagecfg/config.go +++ b/cmd/frostfs-adm/internal/modules/storagecfg/config.go @@ -61,6 +61,8 @@ storage: depth: 1 # max depth of object tree storage in key-value DB width: 4 # max width of object tree storage in key-value DB opened_cache_capacity: 50 # maximum number of opened database files + opened_cache_ttl: 5m # ttl for opened database file + opened_cache_exp_interval: 15s # cache cleanup interval for expired blobovnicza's gc: remover_batch_size: 200 # number of objects to be removed by the garbage collector diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 066d63e652..eb9f9fb184 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -185,13 +185,15 @@ type subStorageCfg struct { noSync bool // blobovnicza-specific - size uint64 - width uint64 - leafWidth uint64 - openedCacheSize int - initWorkerCount int - initInAdvance bool - rebuildDropTimeout time.Duration + size uint64 + width uint64 + leafWidth uint64 + openedCacheSize int + initWorkerCount int + initInAdvance bool + rebuildDropTimeout time.Duration + openedCacheTTL time.Duration + openedCacheExpInterval time.Duration } // readConfig fills applicationConfiguration with raw configuration values @@ -313,6 +315,8 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol sCfg.width = sub.ShallowWidth() sCfg.leafWidth = sub.LeafWidth() sCfg.openedCacheSize = sub.OpenedCacheSize() + sCfg.openedCacheTTL = sub.OpenedCacheTTL() + sCfg.openedCacheExpInterval = sub.OpenedCacheExpInterval() sCfg.initWorkerCount = sub.InitWorkerCount() sCfg.initInAdvance = sub.InitInAdvance() sCfg.rebuildDropTimeout = sub.RebuildDropTimeout() @@ -846,11 +850,11 @@ type shardOptsWithID struct { shOpts []shard.Option } -func (c *cfg) shardOpts() []shardOptsWithID { +func (c *cfg) shardOpts(ctx context.Context) []shardOptsWithID { shards := make([]shardOptsWithID, 0, len(c.EngineCfg.shards)) for _, shCfg := range c.EngineCfg.shards { - shards = append(shards, c.getShardOpts(shCfg)) + shards = append(shards, c.getShardOpts(ctx, shCfg)) } return shards @@ -891,7 +895,7 @@ func (c *cfg) getPiloramaOpts(shCfg shardCfg) []pilorama.Option { return piloramaOpts } -func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { +func (c *cfg) getSubstorageOpts(ctx context.Context, shCfg shardCfg) []blobstor.SubStorage { var ss []blobstor.SubStorage for _, sRead := range shCfg.subStorages { switch sRead.typ { @@ -904,6 +908,8 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { blobovniczatree.WithBlobovniczaShallowWidth(sRead.width), blobovniczatree.WithBlobovniczaLeafWidth(sRead.leafWidth), blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize), + blobovniczatree.WithOpenedCacheTTL(sRead.openedCacheTTL), + blobovniczatree.WithOpenedCacheExpInterval(sRead.openedCacheExpInterval), blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), blobovniczatree.WithInitInAdvance(sRead.initInAdvance), blobovniczatree.WithWaitBeforeDropDB(sRead.rebuildDropTimeout), @@ -919,7 +925,7 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { ) } ss = append(ss, blobstor.SubStorage{ - Storage: blobovniczatree.NewBlobovniczaTree(blobTreeOpts...), + Storage: blobovniczatree.NewBlobovniczaTree(ctx, blobTreeOpts...), Policy: func(_ *objectSDK.Object, data []byte) bool { return uint64(len(data)) < shCfg.smallSizeObjectLimit }, @@ -954,10 +960,10 @@ func (c *cfg) getSubstorageOpts(shCfg shardCfg) []blobstor.SubStorage { return ss } -func (c *cfg) getShardOpts(shCfg shardCfg) shardOptsWithID { +func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID { writeCacheOpts := c.getWriteCacheOpts(shCfg) piloramaOpts := c.getPiloramaOpts(shCfg) - ss := c.getSubstorageOpts(shCfg) + ss := c.getSubstorageOpts(ctx, shCfg) blobstoreOpts := []blobstor.Option{ blobstor.WithCompressObjects(shCfg.compress), @@ -1049,7 +1055,7 @@ func initLocalStorage(ctx context.Context, c *cfg) { c.cfgObject.getSvc = new(getsvc.Service) var shardsAttached int - for _, optsWithMeta := range c.shardOpts() { + for _, optsWithMeta := range c.shardOpts(ctx) { id, err := ls.AddShard(ctx, append(optsWithMeta.shOpts, shard.WithTombstoneSource(c.createTombstoneSource()))...) if err != nil { c.log.Error(logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err)) @@ -1289,7 +1295,7 @@ func (c *cfg) reloadConfig(ctx context.Context) { // Storage Engine var rcfg engine.ReConfiguration - for _, optsWithID := range c.shardOpts() { + for _, optsWithID := range c.shardOpts(ctx) { rcfg.AddShard(optsWithID.configID, append(optsWithID.shOpts, shard.WithTombstoneSource(c.createTombstoneSource()))) } diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go index 9619a10273..c8ea4c2cb6 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go @@ -25,6 +25,12 @@ const ( // OpenedCacheSizeDefault is a default cache size of opened Blobovnicza's. OpenedCacheSizeDefault = 16 + // OpenedCacheTTLDefault is a default cache ttl of opened Blobovnicza's. + OpenedCacheTTLDefault = 0 // means expiring is off + + // OpenedCacheExpIntervalDefault is a default cache cleanup interval for expired Blobovnicza's. + OpenedCacheExpIntervalDefault = 15 * time.Second + // InitWorkerCountDefault is a default workers count to initialize Blobovnicza's. InitWorkerCountDefault = 5 @@ -106,6 +112,38 @@ func (x *Config) OpenedCacheSize() int { return OpenedCacheSizeDefault } +// OpenedCacheTTL returns the value of "opened_cache_ttl" config parameter. +// +// Returns OpenedCacheTTLDefault if the value is not a positive number. +func (x *Config) OpenedCacheTTL() time.Duration { + d := config.DurationSafe( + (*config.Config)(x), + "opened_cache_ttl", + ) + + if d > 0 { + return d + } + + return OpenedCacheTTLDefault +} + +// OpenedCacheExpInterval returns the value of "opened_cache_exp_interval" config parameter. +// +// Returns OpenedCacheExpIntervalDefault if the value is not a positive number. +func (x *Config) OpenedCacheExpInterval() time.Duration { + d := config.DurationSafe( + (*config.Config)(x), + "opened_cache_exp_interval", + ) + + if d > 0 { + return d + } + + return OpenedCacheExpIntervalDefault +} + // BoltDB returns config instance for querying bolt db specific parameters. func (x *Config) BoltDB() *boltdbconfig.Config { return (*boltdbconfig.Config)(x) diff --git a/config/example/node.env b/config/example/node.env index 9068886d3c..77733f5682 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -128,6 +128,8 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_SIZE=4194304 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH=1 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 +FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_TTL=5m +FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_EXP_INTERVAL=15s FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_IN_ADVANCE=TRUE @@ -178,6 +180,8 @@ FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_SIZE=4194304 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_DEPTH=1 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 +FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_TTL=5m +FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_EXP_INTERVAL=15s FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_LEAF_WIDTH=10 ### FSTree config FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE=fstree diff --git a/config/example/node.json b/config/example/node.json index bae28720bb..2ac8697bba 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -176,6 +176,8 @@ "depth": 1, "width": 4, "opened_cache_capacity": 50, + "opened_cache_ttl": "5m", + "opened_cache_exp_interval": "15s", "leaf_width": 10, "init_worker_count": 10, "init_in_advance": true, @@ -229,6 +231,8 @@ "depth": 1, "width": 4, "opened_cache_capacity": 50, + "opened_cache_ttl": "5m", + "opened_cache_exp_interval": "15s", "leaf_width": 10 }, { diff --git a/config/example/node.yaml b/config/example/node.yaml index 7a824adbeb..d2109fcc55 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -151,6 +151,8 @@ storage: depth: 1 # max depth of object tree storage in key-value DB width: 4 # max width of object tree storage in key-value DB opened_cache_capacity: 50 # maximum number of opened database files + opened_cache_ttl: 5m # ttl for opened database file + opened_cache_exp_interval: 15s # cache cleanup interval for expired blobovnicza's leaf_width: 10 # max count of key-value DB on leafs of object tree storage - perm: 0644 # permissions for blobstor files(directories: +x for current user and group) depth: 5 # max depth of object tree storage in FS diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index aa3a178153..ce9065ac24 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -212,6 +212,8 @@ blobstor: depth: 1 width: 4 opened_cache_capacity: 50 + opened_cache_ttl: 5m + opened_cache_exp_interval: 15s ``` #### Common options for sub-storages @@ -228,17 +230,19 @@ blobstor: | `depth` | `int` | `4` | File-system tree depth. | #### `blobovnicza` type options -| Parameter | Type | Default value | Description | -| ----------------------- | ---------- | ------------- | --------------------------------------------------------------------- | -| `path` | `string` | | Path to the root of the blobstor. | -| `perm` | file mode | `0660` | Default permission for created files and directories. | -| `size` | `size` | `1 G` | Maximum size of a single blobovnicza | -| `depth` | `int` | `2` | Blobovnicza tree depth. | -| `width` | `int` | `16` | Blobovnicza tree width. | -| `opened_cache_capacity` | `int` | `16` | Maximum number of simultaneously opened blobovniczas. | -| `init_worker_count` | `int` | `5` | Maximum number of concurrent initialization workers. | -| `init_in_advance` | `bool` | `false` | If `true`, than all the blobovnicza files will be created on startup. | -| `rebuild_drop_timeout` | `duration` | `10s` | Timeout before drop empty blobovnicza file during rebuild. | +| Parameter | Type | Default value | Description | +|-----------------------------| ---------- |---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `path` | `string` | | Path to the root of the blobstor. | +| `perm` | file mode | `0660` | Default permission for created files and directories. | +| `size` | `size` | `1 G` | Maximum size of a single blobovnicza | +| `depth` | `int` | `2` | Blobovnicza tree depth. | +| `width` | `int` | `16` | Blobovnicza tree width. | +| `opened_cache_capacity` | `int` | `16` | Maximum number of simultaneously opened blobovniczas. | +| `opened_cache_ttl` | `duration` | `0` | TTL in cache for opened blobovniczas(disabled by default). In case of heavy random-read and 10 shards each with 10_000 databases and accessing 400 objects per-second we will access each db approximately once per ((10 * 10_000 / 400) = 250 seconds <= 300 seconds = 5 min). Also take in mind that in this scenario they will probably be closed earlier because of the cache capacity, so bigger values are likely to be of no use. | +| `opened_cache_exp_interval` | `duration` | `15s` | Cache cleanup interval for expired blobovnicza's. | +| `init_worker_count` | `int` | `5` | Maximum number of concurrent initialization workers. | +| `init_in_advance` | `bool` | `false` | If `true`, than all the blobovnicza files will be created on startup. | +| `rebuild_drop_timeout` | `duration` | `10s` | Timeout before drop empty blobovnicza file during rebuild. | ### `gc` subsection diff --git a/go.mod b/go.mod index f5469dee67..1be2526f20 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/chzyer/readline v1.5.1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 + github.com/go-pkgz/expirable-cache/v3 v3.0.0 github.com/google/uuid v1.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/klauspost/compress v1.17.4 diff --git a/go.sum b/go.sum index 0a885cb2f3..0795c955b7 100644 --- a/go.sum +++ b/go.sum @@ -76,6 +76,8 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-pkgz/expirable-cache/v3 v3.0.0 h1:u3/gcu3sabLYiTCevoRKv+WzjIn5oo7P8XtiXBeRDLw= +github.com/go-pkgz/expirable-cache/v3 v3.0.0/go.mod h1:2OQiDyEGQalYecLWmXprm3maPXeVb5/6/X7yRPYTzec= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index be51509b6e..58466f7592 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -1,6 +1,7 @@ package blobovniczatree import ( + "context" "errors" "strconv" "strings" @@ -72,7 +73,7 @@ const ( ) // NewBlobovniczaTree returns new instance of blobovniczas tree. -func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { +func NewBlobovniczaTree(ctx context.Context, opts ...Option) (blz *Blobovniczas) { blz = new(Blobovniczas) initConfig(&blz.cfg) @@ -86,7 +87,8 @@ func NewBlobovniczaTree(opts ...Option) (blz *Blobovniczas) { blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) - blz.dbCache = newDBCache(blz.openedCacheSize, blz.commondbManager) + blz.dbCache = newDBCache(ctx, blz.openedCacheSize, + blz.openedCacheTTL, blz.openedCacheExpInterval, blz.commondbManager) blz.deleteProtectedObjects = newAddressMap() blz.dbFilesGuard = &sync.RWMutex{} blz.rebuildGuard = &sync.RWMutex{} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index 766f5ef0aa..4fce3e81ac 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -1,11 +1,12 @@ package blobovniczatree import ( - "fmt" + "context" "sync" + "time" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" - "github.com/hashicorp/golang-lru/v2/simplelru" + cache "github.com/go-pkgz/expirable-cache/v3" ) // dbCache caches sharedDB instances that are NOT open for Put. @@ -13,30 +14,55 @@ import ( // Uses dbManager for opening/closing sharedDB instances. // Stores a reference to an cached sharedDB, so dbManager does not close it. type dbCache struct { - cacheGuard *sync.RWMutex - cache simplelru.LRUCache[string, *sharedDB] + cacheGuard *sync.Mutex + cache cache.Cache[string, *sharedDB] pathLock *utilSync.KeyLocker[string] // the order of locks is important: pathLock first, cacheGuard second closed bool nonCached map[string]struct{} + wg sync.WaitGroup + cancel context.CancelFunc dbManager *dbManager } -func newDBCache(size int, dbManager *dbManager) *dbCache { - cache, err := simplelru.NewLRU(size, func(_ string, evictedDB *sharedDB) { - evictedDB.Close() - }) - if err != nil { - // occurs only if the size is not positive - panic(fmt.Errorf("could not create LRU cache of size %d: %w", size, err)) - } - return &dbCache{ - cacheGuard: &sync.RWMutex{}, - cache: cache, +func newDBCache(parentCtx context.Context, size int, + ttl time.Duration, expInterval time.Duration, + dbManager *dbManager, +) *dbCache { + ch := cache.NewCache[string, *sharedDB](). + WithTTL(ttl).WithLRU().WithMaxKeys(size). + WithOnEvicted(func(_ string, db *sharedDB) { + db.Close() + }) + ctx, cancel := context.WithCancel(parentCtx) + res := &dbCache{ + cacheGuard: &sync.Mutex{}, + wg: sync.WaitGroup{}, + cancel: cancel, + cache: ch, dbManager: dbManager, pathLock: utilSync.NewKeyLocker[string](), nonCached: make(map[string]struct{}), } + if ttl > 0 { + res.wg.Add(1) + go func() { + ticker := time.NewTicker(expInterval) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + res.wg.Done() + return + case <-ticker.C: + res.cacheGuard.Lock() + res.cache.DeleteExpired() + res.cacheGuard.Unlock() + } + } + }() + } + return res } func (c *dbCache) Open() { @@ -49,6 +75,8 @@ func (c *dbCache) Open() { func (c *dbCache) Close() { c.cacheGuard.Lock() defer c.cacheGuard.Unlock() + c.cancel() + c.wg.Wait() c.cache.Purge() c.closed = true } @@ -88,6 +116,8 @@ func (c *dbCache) getExisted(path string) *sharedDB { if value, ok := c.cache.Get(path); ok { return value + } else if value != nil { + c.cache.Invalidate(path) } return nil } @@ -119,10 +149,9 @@ func (c *dbCache) put(path string, db *sharedDB) bool { _, isNonCached := c.nonCached[path] - if !isNonCached && !c.closed { - c.cache.Add(path, db) - return true + if isNonCached || c.closed { + return false } - - return false + c.cache.Add(path, db) + return true } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go index e8b148bff5..97606df021 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -17,6 +17,7 @@ func TestBlobovniczaTree_Concurrency(t *testing.T) { const n = 1000 st := NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(1024), WithBlobovniczaShallowWidth(10), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go index 11d4e78fe4..0356fbaaeb 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go @@ -49,6 +49,7 @@ func createTestTree(t *testing.T, currentDepth, depth, width uint64, path string func openAndCloseTestTree(t *testing.T, depth, width uint64, path string) { blz := NewBlobovniczaTree( + context.Background(), WithBlobovniczaShallowDepth(depth), WithBlobovniczaShallowWidth(width), WithRootPath(path), @@ -78,6 +79,7 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { rootDir := t.TempDir() blz := NewBlobovniczaTree( + context.Background(), WithBlobovniczaShallowDepth(3), WithBlobovniczaShallowWidth(5), WithRootPath(rootDir), @@ -115,6 +117,7 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { // change depth and width blz = NewBlobovniczaTree( + context.Background(), WithBlobovniczaShallowDepth(5), WithBlobovniczaShallowWidth(2), WithRootPath(rootDir), @@ -152,6 +155,7 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { // change depth and width back blz = NewBlobovniczaTree( + context.Background(), WithBlobovniczaShallowDepth(3), WithBlobovniczaShallowWidth(5), WithRootPath(rootDir), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index 048f9a2e53..625e620b8e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -17,6 +17,7 @@ import ( func TestExistsInvalidStorageID(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(1024), WithBlobovniczaShallowWidth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go index 1a52eddf82..d390ecf1d1 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go @@ -1,6 +1,7 @@ package blobovniczatree import ( + "context" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" @@ -13,6 +14,7 @@ func TestGeneric(t *testing.T) { helper := func(t *testing.T, dir string) common.Storage { return NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), @@ -40,6 +42,7 @@ func TestControl(t *testing.T) { newTree := func(t *testing.T) common.Storage { return NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go index c322fa7a38..506dd9a4be 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go @@ -12,6 +12,7 @@ func TestIterateSortedLeavesAndDBPathsAreSame(t *testing.T) { t.Parallel() blz := NewBlobovniczaTree( + context.Background(), WithBlobovniczaShallowDepth(3), WithBlobovniczaShallowWidth(5), WithRootPath(t.TempDir()), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index d36074dc8b..6344992750 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -27,32 +27,40 @@ type cfg struct { blzInitWorkerCount int blzMoveBatchSize int createDBInAdvance bool + // TTL for blobovnicza's cache + openedCacheTTL time.Duration + // Interval for deletion expired blobovnicza's + openedCacheExpInterval time.Duration } type Option func(*cfg) const ( - defaultPerm = 0o700 - defaultOpenedCacheSize = 50 - defaultBlzShallowDepth = 2 - defaultBlzShallowWidth = 16 - defaultWaitBeforeDropDB = 10 * time.Second - defaultBlzInitWorkerCount = 5 - defaulBlzMoveBatchSize = 10000 + defaultPerm = 0o700 + defaultOpenedCacheSize = 50 + defaultOpenedCacheTTL = 0 // means expiring is off + defaultOpenedCacheInterval = 15 * time.Second + defaultBlzShallowDepth = 2 + defaultBlzShallowWidth = 16 + defaultWaitBeforeDropDB = 10 * time.Second + defaultBlzInitWorkerCount = 5 + defaulBlzMoveBatchSize = 10000 ) func initConfig(c *cfg) { *c = cfg{ - log: &logger.Logger{Logger: zap.L()}, - perm: defaultPerm, - openedCacheSize: defaultOpenedCacheSize, - blzShallowDepth: defaultBlzShallowDepth, - blzShallowWidth: defaultBlzShallowWidth, - reportError: func(string, error) {}, - metrics: &noopMetrics{}, - waitBeforeDropDB: defaultWaitBeforeDropDB, - blzInitWorkerCount: defaultBlzInitWorkerCount, - blzMoveBatchSize: defaulBlzMoveBatchSize, + log: &logger.Logger{Logger: zap.L()}, + perm: defaultPerm, + openedCacheSize: defaultOpenedCacheSize, + openedCacheTTL: defaultOpenedCacheTTL, + openedCacheExpInterval: defaultOpenedCacheInterval, + blzShallowDepth: defaultBlzShallowDepth, + blzShallowWidth: defaultBlzShallowWidth, + reportError: func(string, error) {}, + metrics: &noopMetrics{}, + waitBeforeDropDB: defaultWaitBeforeDropDB, + blzInitWorkerCount: defaultBlzInitWorkerCount, + blzMoveBatchSize: defaulBlzMoveBatchSize, } } @@ -105,6 +113,18 @@ func WithOpenedCacheSize(sz int) Option { } } +func WithOpenedCacheTTL(ttl time.Duration) Option { + return func(c *cfg) { + c.openedCacheTTL = ttl + } +} + +func WithOpenedCacheExpInterval(expInterval time.Duration) Option { + return func(c *cfg) { + c.openedCacheExpInterval = expInterval + } +} + func WithObjectSizeLimit(sz uint64) Option { return func(c *cfg) { c.blzOpts = append(c.blzOpts, blobovnicza.WithObjectSizeLimit(sz)) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index 855229405f..31dadb533a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -129,6 +129,7 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object, mustUpdateStorageID bool) { b := NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 578cb1a7ff..6b8ae4b5cc 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -43,6 +43,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(64*1024), // 64KB object size limit WithBlobovniczaShallowWidth(5), @@ -70,6 +71,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { require.NoError(t, b.Close()) b = NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(32*1024), // 32KB object size limit WithBlobovniczaShallowWidth(5), @@ -108,6 +110,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, targetDepth, targetWidth uint64, shouldMigrate bool) { dir := t.TempDir() b := NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(sourceWidth), @@ -148,6 +151,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta require.NoError(t, b.Close()) b = NewBlobovniczaTree( + context.Background(), WithLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(targetWidth), diff --git a/pkg/local_object_storage/blobstor/blobstor_test.go b/pkg/local_object_storage/blobstor/blobstor_test.go index 3dac3bfa48..c7d80dc840 100644 --- a/pkg/local_object_storage/blobstor/blobstor_test.go +++ b/pkg/local_object_storage/blobstor/blobstor_test.go @@ -18,6 +18,7 @@ import ( func defaultTestStorages(p string, smallSizeLimit uint64) ([]SubStorage, *teststore.TestStore, *teststore.TestStore) { smallFileStorage := teststore.New(teststore.WithSubstorage(blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithRootPath(filepath.Join(p, "blobovniczas")), blobovniczatree.WithBlobovniczaShallowWidth(1)), // default width is 16, slow init )) @@ -117,6 +118,7 @@ func TestBlobstor_needsCompression(t *testing.T) { WithStorages([]SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithRootPath(filepath.Join(dir, "blobovnicza")), blobovniczatree.WithBlobovniczaShallowWidth(1)), // default width is 16, slow init Policy: func(_ *objectSDK.Object, data []byte) bool { diff --git a/pkg/local_object_storage/blobstor/perf_test.go b/pkg/local_object_storage/blobstor/perf_test.go index 72079acbab..fb5afb88b3 100644 --- a/pkg/local_object_storage/blobstor/perf_test.go +++ b/pkg/local_object_storage/blobstor/perf_test.go @@ -73,6 +73,7 @@ var storages = []storage{ desc: "blobovniczatree", create: func(dir string) common.Storage { return blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithRootPath(dir), ) }, diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index c41804e073..b82700ed84 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -137,6 +137,7 @@ func newStorages(t testing.TB, root string, smallSize uint64) []blobstor.SubStor return []blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithRootPath(filepath.Join(root, "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1), @@ -158,6 +159,7 @@ func newStorages(t testing.TB, root string, smallSize uint64) []blobstor.SubStor func newTestStorages(root string, smallSize uint64) ([]blobstor.SubStorage, *teststore.TestStore, *teststore.TestStore) { smallFileStorage := teststore.New( teststore.WithSubstorage(blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithRootPath(filepath.Join(root, "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1), diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 6a7941e040..3993593ad7 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -36,6 +36,7 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index 91033efb75..9ce95feb13 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -35,6 +35,7 @@ func TestShard_Lock(t *testing.T) { blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(2), blobovniczatree.WithBlobovniczaShallowWidth(2)), diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 5a8a29e0c1..cc73db3168 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -78,6 +78,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(t.TempDir(), "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index a5483f632e..73ba2e82b1 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -59,6 +59,7 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard blobstor.WithStorages([]blobstor.SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( + context.Background(), blobovniczatree.WithLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(o.rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), From 3b9d12b11c45d4029b0990f93b6efa1a91a12198 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 27 Apr 2024 14:17:22 +0300 Subject: [PATCH 0521/1413] [#1110] node: Fix comment about nodeInfo type Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/netmap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index b1d854da41..f3cdfe7111 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -31,7 +31,7 @@ type networkState struct { controlNetStatus atomic.Int32 // control.NetmapStatus - nodeInfo atomic.Value // *netmapSDK.NodeInfo + nodeInfo atomic.Value // netmapSDK.NodeInfo metrics *metrics.NodeMetrics } From c8e2ca2ab4777f0bf830045368ae12c0fd99c6e4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 27 Apr 2024 14:20:06 +0300 Subject: [PATCH 0522/1413] [#1110] node: Rename handleLocalNodeInfo() It is used in "handler" only once, what we really do is set the variable. And we have another "local" node info in `cfgNodeInfo`, this one is not really local (node info), more like (local node) info, so use setContractNodeInfo to distinguish it from the local view on the node info. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 4 ++-- cmd/frostfs-node/netmap.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index eb9f9fb184..cf4a1e4c37 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1157,10 +1157,10 @@ func (c *cfg) LocalNodeInfo() (*netmapV2.NodeInfo, error) { return &res, nil } -// handleLocalNodeInfo rewrites local node info from the FrostFS network map. +// setContractNodeInfo rewrites local node info from the FrostFS network map. // Called with nil when storage node is outside the FrostFS network map // (before entering the network and after leaving it). -func (c *cfg) handleLocalNodeInfo(ni *netmap.NodeInfo) { +func (c *cfg) setContractNodeInfo(ni *netmap.NodeInfo) { c.cfgNetmap.state.setNodeInfo(ni) } diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index f3cdfe7111..683c186faf 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -199,7 +199,7 @@ func addNewEpochNotificationHandlers(c *cfg) { return } - c.handleLocalNodeInfo(ni) + c.setContractNodeInfo(ni) }) if c.cfgMorph.notaryEnabled { @@ -270,7 +270,7 @@ func initNetmapState(c *cfg) { c.cfgNetmap.state.setCurrentEpoch(epoch) c.cfgNetmap.startEpoch = epoch - c.handleLocalNodeInfo(ni) + c.setContractNodeInfo(ni) } func nodeState(ni *netmapSDK.NodeInfo) string { From 4b514f5ba02f6252eb2c721657a87c0da201c71b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 27 Apr 2024 14:48:36 +0300 Subject: [PATCH 0523/1413] [#1110] node: Log maintenance stop only if it was enabled Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index cf4a1e4c37..7bf0077bd2 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -388,8 +388,9 @@ func (c *cfg) startMaintenance() { // stops node's maintenance. func (c *internals) stopMaintenance() { - c.isMaintenance.Store(false) - c.log.Info(logs.FrostFSNodeStoppedLocalNodesMaintenance) + if c.isMaintenance.CompareAndSwap(true, false) { + c.log.Info(logs.FrostFSNodeStoppedLocalNodesMaintenance) + } } // IsMaintenance checks if storage node is under maintenance. From 52bebe9452a2db8239c9c88a8f865ce42786510f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 27 Apr 2024 15:06:19 +0300 Subject: [PATCH 0524/1413] [#1110] node: Use single handler for new epoch event Bootstrap logic depends on the netmap status, which in turn depends on the node info. Updating them in a single thread makes things more predictable. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 12 ++++++++++++ cmd/frostfs-node/netmap.go | 22 +++++----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 7bf0077bd2..5606ed24cc 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1165,6 +1165,18 @@ func (c *cfg) setContractNodeInfo(ni *netmap.NodeInfo) { c.cfgNetmap.state.setNodeInfo(ni) } +func (c *cfg) updateContractNodeInfo(epoch uint64) { + ni, err := c.netmapLocalNodeState(epoch) + if err != nil { + c.log.Error(logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, + zap.Uint64("epoch", epoch), + zap.String("error", err.Error())) + return + } + + c.setContractNodeInfo(ni) +} + // bootstrapWithState calls "addPeer" method of the Sidechain Netmap contract // with the binary-encoded information from the current node's configuration. // The state is set using the provided setter which MUST NOT be nil. diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 683c186faf..56f2ca98fc 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -176,7 +176,11 @@ func addNewEpochNotificationHandlers(c *cfg) { c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber()) }) - addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { + addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { + e := ev.(netmapEvent.NewEpoch).EpochNumber() + + c.updateContractNodeInfo(e) + if !c.needBootstrap() || c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470 return } @@ -186,22 +190,6 @@ func addNewEpochNotificationHandlers(c *cfg) { } }) - addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { - e := ev.(netmapEvent.NewEpoch).EpochNumber() - - ni, err := c.netmapLocalNodeState(e) - if err != nil { - c.log.Error(logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, - zap.Uint64("epoch", e), - zap.String("error", err.Error()), - ) - - return - } - - c.setContractNodeInfo(ni) - }) - if c.cfgMorph.notaryEnabled { addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { _, err := makeNotaryDeposit(c) From 4730ecfdb83dd52c34479167eb3eb630c0cf1862 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Sat, 27 Apr 2024 15:34:29 +0300 Subject: [PATCH 0525/1413] [#966] node: Refactor WriteCacheMetrics interface Grouping common fields of methods will enhance the readability of the interface. Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/engine/writecache.go | 18 +++++++++--------- pkg/metrics/mode.go | 4 ++-- pkg/metrics/writecache.go | 18 +++++++++--------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index f30bce00d7..850e10d17e 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -150,20 +150,20 @@ func (m *writeCacheMetrics) SetShardID(id string) { } func (m *writeCacheMetrics) Get(d time.Duration, success bool, st writecache.StorageType) { - m.metrics.AddMethodDuration(m.shardID, "Get", success, d, st.String()) + m.metrics.AddMethodDuration(m.shardID, st.String(), "Get", success, d) } func (m *writeCacheMetrics) Delete(d time.Duration, success bool, st writecache.StorageType) { - m.metrics.AddMethodDuration(m.shardID, "Delete", success, d, st.String()) + m.metrics.AddMethodDuration(m.shardID, st.String(), "Delete", success, d) } func (m *writeCacheMetrics) Put(d time.Duration, success bool, st writecache.StorageType) { - m.metrics.AddMethodDuration(m.shardID, "Put", success, d, st.String()) + m.metrics.AddMethodDuration(m.shardID, st.String(), "Put", success, d) } func (m *writeCacheMetrics) SetEstimateSize(db, fstree uint64) { - m.metrics.SetEstimateSize(m.shardID, db, writecache.StorageTypeDB.String()) - m.metrics.SetEstimateSize(m.shardID, fstree, writecache.StorageTypeFSTree.String()) + m.metrics.SetEstimateSize(m.shardID, writecache.StorageTypeDB.String(), db) + m.metrics.SetEstimateSize(m.shardID, writecache.StorageTypeFSTree.String(), fstree) } func (m *writeCacheMetrics) SetMode(mode mode.Mode) { @@ -171,16 +171,16 @@ func (m *writeCacheMetrics) SetMode(mode mode.Mode) { } func (m *writeCacheMetrics) SetActualCounters(db, fstree uint64) { - m.metrics.SetActualCount(m.shardID, db, writecache.StorageTypeDB.String()) - m.metrics.SetActualCount(m.shardID, fstree, writecache.StorageTypeFSTree.String()) + m.metrics.SetActualCount(m.shardID, writecache.StorageTypeDB.String(), db) + m.metrics.SetActualCount(m.shardID, writecache.StorageTypeFSTree.String(), fstree) } func (m *writeCacheMetrics) Flush(success bool, st writecache.StorageType) { - m.metrics.IncOperationCounter(m.shardID, "Flush", metrics.NullBool{Bool: success, Valid: true}, st.String()) + m.metrics.IncOperationCounter(m.shardID, st.String(), "Flush", metrics.NullBool{Bool: success, Valid: true}) } func (m *writeCacheMetrics) Evict(st writecache.StorageType) { - m.metrics.IncOperationCounter(m.shardID, "Evict", metrics.NullBool{}, st.String()) + m.metrics.IncOperationCounter(m.shardID, st.String(), "Evict", metrics.NullBool{}) } func (m *writeCacheMetrics) Close() { diff --git a/pkg/metrics/mode.go b/pkg/metrics/mode.go index cf6bdac48a..a9ac47acdd 100644 --- a/pkg/metrics/mode.go +++ b/pkg/metrics/mode.go @@ -21,7 +21,7 @@ func newShardIDMode(subsystem, name, help string) *shardIDModeValue { } } -func (m *shardIDModeValue) SetMode(shardID string, mode string) { +func (m *shardIDModeValue) SetMode(shardID, mode string) { m.modeValue.DeletePartialMatch(prometheus.Labels{ shardIDLabel: shardID, }) @@ -54,7 +54,7 @@ func newShardIDPathMode(subsystem, name, help string) *shardIDPathModeValue { } } -func (m *shardIDPathModeValue) SetMode(shardID, path string, mode string) { +func (m *shardIDPathModeValue) SetMode(shardID, path, mode string) { m.modeValue.DeletePartialMatch(prometheus.Labels{ shardIDLabel: shardID, pathLabel: path, diff --git a/pkg/metrics/writecache.go b/pkg/metrics/writecache.go index ea3d8742ab..70181ee2b4 100644 --- a/pkg/metrics/writecache.go +++ b/pkg/metrics/writecache.go @@ -9,11 +9,11 @@ import ( ) type WriteCacheMetrics interface { - AddMethodDuration(shardID string, method string, success bool, d time.Duration, storageType string) - SetActualCount(shardID string, count uint64, storageType string) - SetEstimateSize(shardID string, size uint64, storageType string) - SetMode(shardID string, mode string) - IncOperationCounter(shardID string, operation string, success NullBool, storageType string) + AddMethodDuration(shardID, storageType, method string, success bool, d time.Duration) + SetActualCount(shardID, storageType string, count uint64) + SetEstimateSize(shardID, storageType string, size uint64) + SetMode(shardID, mode string) + IncOperationCounter(shardID, storageType, operation string, success NullBool) Close(shardID string) } @@ -48,7 +48,7 @@ func newWriteCacheMetrics() *writeCacheMetrics { } } -func (m *writeCacheMetrics) AddMethodDuration(shardID string, method string, success bool, d time.Duration, storageType string) { +func (m *writeCacheMetrics) AddMethodDuration(shardID, storageType, method string, success bool, d time.Duration) { m.methodDuration.With( prometheus.Labels{ shardIDLabel: shardID, @@ -59,14 +59,14 @@ func (m *writeCacheMetrics) AddMethodDuration(shardID string, method string, suc ).Observe(d.Seconds()) } -func (m *writeCacheMetrics) SetActualCount(shardID string, count uint64, storageType string) { +func (m *writeCacheMetrics) SetActualCount(shardID, storageType string, count uint64) { m.actualCount.With(prometheus.Labels{ shardIDLabel: shardID, storageLabel: storageType, }).Set(float64(count)) } -func (m *writeCacheMetrics) SetEstimateSize(shardID string, size uint64, storageType string) { +func (m *writeCacheMetrics) SetEstimateSize(shardID, storageType string, size uint64) { m.estimatedSize.With(prometheus.Labels{ shardIDLabel: shardID, storageLabel: storageType, @@ -77,7 +77,7 @@ func (m *writeCacheMetrics) SetMode(shardID string, mode string) { m.mode.SetMode(shardID, mode) } -func (m *writeCacheMetrics) IncOperationCounter(shardID string, operation string, success NullBool, storageType string) { +func (m *writeCacheMetrics) IncOperationCounter(shardID, storageType, operation string, success NullBool) { m.operationCounter.With(prometheus.Labels{ shardIDLabel: shardID, storageLabel: storageType, From c9efaa5819d40352a9a6ce904876344517010cf5 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Sat, 27 Apr 2024 15:49:07 +0300 Subject: [PATCH 0526/1413] [#966] node: Add path of the write_cache to metric labels Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/engine/writecache.go | 25 +++++++----- pkg/local_object_storage/shard/shard.go | 1 + .../writecache/metrics.go | 3 ++ pkg/metrics/writecache.go | 38 ++++++++++--------- 4 files changed, 40 insertions(+), 27 deletions(-) diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 850e10d17e..670cfcbf59 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -143,6 +143,11 @@ func (e *StorageEngine) SealWriteCache(ctx context.Context, prm SealWriteCachePr type writeCacheMetrics struct { shardID string metrics metrics.WriteCacheMetrics + path string +} + +func (m *writeCacheMetrics) SetPath(path string) { + m.path = path } func (m *writeCacheMetrics) SetShardID(id string) { @@ -150,20 +155,20 @@ func (m *writeCacheMetrics) SetShardID(id string) { } func (m *writeCacheMetrics) Get(d time.Duration, success bool, st writecache.StorageType) { - m.metrics.AddMethodDuration(m.shardID, st.String(), "Get", success, d) + m.metrics.AddMethodDuration(m.shardID, m.path, st.String(), "Get", success, d) } func (m *writeCacheMetrics) Delete(d time.Duration, success bool, st writecache.StorageType) { - m.metrics.AddMethodDuration(m.shardID, st.String(), "Delete", success, d) + m.metrics.AddMethodDuration(m.shardID, m.path, st.String(), "Delete", success, d) } func (m *writeCacheMetrics) Put(d time.Duration, success bool, st writecache.StorageType) { - m.metrics.AddMethodDuration(m.shardID, st.String(), "Put", success, d) + m.metrics.AddMethodDuration(m.shardID, m.path, st.String(), "Put", success, d) } func (m *writeCacheMetrics) SetEstimateSize(db, fstree uint64) { - m.metrics.SetEstimateSize(m.shardID, writecache.StorageTypeDB.String(), db) - m.metrics.SetEstimateSize(m.shardID, writecache.StorageTypeFSTree.String(), fstree) + m.metrics.SetEstimateSize(m.shardID, m.path, writecache.StorageTypeDB.String(), db) + m.metrics.SetEstimateSize(m.shardID, m.path, writecache.StorageTypeFSTree.String(), fstree) } func (m *writeCacheMetrics) SetMode(mode mode.Mode) { @@ -171,18 +176,18 @@ func (m *writeCacheMetrics) SetMode(mode mode.Mode) { } func (m *writeCacheMetrics) SetActualCounters(db, fstree uint64) { - m.metrics.SetActualCount(m.shardID, writecache.StorageTypeDB.String(), db) - m.metrics.SetActualCount(m.shardID, writecache.StorageTypeFSTree.String(), fstree) + m.metrics.SetActualCount(m.shardID, m.path, writecache.StorageTypeDB.String(), db) + m.metrics.SetActualCount(m.shardID, m.path, writecache.StorageTypeFSTree.String(), fstree) } func (m *writeCacheMetrics) Flush(success bool, st writecache.StorageType) { - m.metrics.IncOperationCounter(m.shardID, st.String(), "Flush", metrics.NullBool{Bool: success, Valid: true}) + m.metrics.IncOperationCounter(m.shardID, m.path, st.String(), "Flush", metrics.NullBool{Bool: success, Valid: true}) } func (m *writeCacheMetrics) Evict(st writecache.StorageType) { - m.metrics.IncOperationCounter(m.shardID, st.String(), "Evict", metrics.NullBool{}) + m.metrics.IncOperationCounter(m.shardID, m.path, st.String(), "Evict", metrics.NullBool{}) } func (m *writeCacheMetrics) Close() { - m.metrics.Close(m.shardID) + m.metrics.Close(m.shardID, m.path) } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index d9cd2b2f4d..cf59c0bfc3 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -182,6 +182,7 @@ func New(opts ...Option) *Shard { writecache.WithReportErrorFunc(reportFunc), writecache.WithBlobstor(bs), writecache.WithMetabase(mb))...) + s.writeCache.GetMetrics().SetPath(s.writeCache.DumpInfo().Path) } if s.piloramaOpts != nil { diff --git a/pkg/local_object_storage/writecache/metrics.go b/pkg/local_object_storage/writecache/metrics.go index 492e0973ac..962e22eea5 100644 --- a/pkg/local_object_storage/writecache/metrics.go +++ b/pkg/local_object_storage/writecache/metrics.go @@ -29,6 +29,7 @@ type Metrics interface { SetEstimateSize(db, fstree uint64) SetMode(m mode.Mode) SetActualCounters(db, fstree uint64) + SetPath(path string) Close() } @@ -38,6 +39,8 @@ type metricsStub struct{} func (metricsStub) SetShardID(string) {} +func (metricsStub) SetPath(string) {} + func (metricsStub) Get(time.Duration, bool, StorageType) {} func (metricsStub) Delete(time.Duration, bool, StorageType) {} diff --git a/pkg/metrics/writecache.go b/pkg/metrics/writecache.go index 70181ee2b4..2fe01526ea 100644 --- a/pkg/metrics/writecache.go +++ b/pkg/metrics/writecache.go @@ -9,12 +9,12 @@ import ( ) type WriteCacheMetrics interface { - AddMethodDuration(shardID, storageType, method string, success bool, d time.Duration) - SetActualCount(shardID, storageType string, count uint64) - SetEstimateSize(shardID, storageType string, size uint64) + AddMethodDuration(shardID, path, storageType, method string, success bool, d time.Duration) + SetActualCount(shardID, path, storageType string, count uint64) + SetEstimateSize(shardID, path, storageType string, size uint64) SetMode(shardID, mode string) - IncOperationCounter(shardID, storageType, operation string, success NullBool) - Close(shardID string) + IncOperationCounter(shardID, path, storageType, operation string, success NullBool) + Close(shardID, path string) } type writeCacheMetrics struct { @@ -41,35 +41,38 @@ func newWriteCacheMetrics() *writeCacheMetrics { Subsystem: writeCacheSubsystem, Name: "operations_total", Help: "The number of writecache operations processed", - }, []string{shardIDLabel, storageLabel, successLabel, operationLabel}), - actualCount: newWCGaugeVec("actual_objects_total", "Actual objects count in writecache", []string{shardIDLabel, storageLabel}), - estimatedSize: newWCGaugeVec("estimated_size_bytes", "Estimated writecache size", []string{shardIDLabel, storageLabel}), + }, []string{shardIDLabel, storageLabel, successLabel, operationLabel, pathLabel}), + actualCount: newWCGaugeVec("actual_objects_total", "Actual objects count in writecache", []string{shardIDLabel, storageLabel, pathLabel}), + estimatedSize: newWCGaugeVec("estimated_size_bytes", "Estimated writecache size", []string{shardIDLabel, storageLabel, pathLabel}), mode: newShardIDMode(writeCacheSubsystem, "mode_info", "Writecache mode value"), } } -func (m *writeCacheMetrics) AddMethodDuration(shardID, storageType, method string, success bool, d time.Duration) { +func (m *writeCacheMetrics) AddMethodDuration(shardID, path, storageType, method string, success bool, d time.Duration) { m.methodDuration.With( prometheus.Labels{ shardIDLabel: shardID, successLabel: strconv.FormatBool(success), storageLabel: storageType, methodLabel: method, + pathLabel: path, }, ).Observe(d.Seconds()) } -func (m *writeCacheMetrics) SetActualCount(shardID, storageType string, count uint64) { +func (m *writeCacheMetrics) SetActualCount(shardID, path, storageType string, count uint64) { m.actualCount.With(prometheus.Labels{ shardIDLabel: shardID, storageLabel: storageType, + pathLabel: path, }).Set(float64(count)) } -func (m *writeCacheMetrics) SetEstimateSize(shardID, storageType string, size uint64) { +func (m *writeCacheMetrics) SetEstimateSize(shardID, path, storageType string, size uint64) { m.estimatedSize.With(prometheus.Labels{ shardIDLabel: shardID, storageLabel: storageType, + pathLabel: path, }).Set(float64(size)) } @@ -77,21 +80,22 @@ func (m *writeCacheMetrics) SetMode(shardID string, mode string) { m.mode.SetMode(shardID, mode) } -func (m *writeCacheMetrics) IncOperationCounter(shardID, storageType, operation string, success NullBool) { +func (m *writeCacheMetrics) IncOperationCounter(shardID, path, storageType, operation string, success NullBool) { m.operationCounter.With(prometheus.Labels{ shardIDLabel: shardID, storageLabel: storageType, operationLabel: operation, successLabel: success.String(), + pathLabel: path, }).Inc() } -func (m *writeCacheMetrics) Close(shardID string) { +func (m *writeCacheMetrics) Close(shardID, path string) { m.mode.Delete(shardID) - m.methodDuration.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) - m.operationCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) - m.actualCount.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) - m.estimatedSize.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) + m.methodDuration.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID, pathLabel: path}) + m.operationCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID, pathLabel: path}) + m.actualCount.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID, pathLabel: path}) + m.estimatedSize.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID, pathLabel: path}) } func newWCGaugeVec(name, help string, labels []string) *prometheus.GaugeVec { From 71789676d5b17ea62dc64a6afa5260df90b4fd26 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 2 May 2024 11:56:46 +0300 Subject: [PATCH 0527/1413] [#1114] aclsvc: Add tests for request ownership Signed-off-by: Evgenii Stratonikov --- pkg/services/object/acl/v2/request_test.go | 163 +++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 pkg/services/object/acl/v2/request_test.go diff --git a/pkg/services/object/acl/v2/request_test.go b/pkg/services/object/acl/v2/request_test.go new file mode 100644 index 0000000000..6c6d79adf3 --- /dev/null +++ b/pkg/services/object/acl/v2/request_test.go @@ -0,0 +1,163 @@ +package v2 + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + sigutilV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestRequestOwner(t *testing.T) { + containerOwner, err := keys.NewPrivateKey() + require.NoError(t, err) + + userPk, err := keys.NewPrivateKey() + require.NoError(t, err) + + var userID user.ID + user.IDFromKey(&userID, userPk.PrivateKey.PublicKey) + + var userSignature refs.Signature + userSignature.SetKey(userPk.PublicKey().Bytes()) + + vh := new(sessionV2.RequestVerificationHeader) + vh.SetBodySignature(&userSignature) + + t.Run("empty verification header", func(t *testing.T) { + req := MetaWithToken{} + checkOwner(t, req, nil, errEmptyVerificationHeader) + }) + t.Run("empty verification header signature", func(t *testing.T) { + req := MetaWithToken{ + vheader: new(sessionV2.RequestVerificationHeader), + } + checkOwner(t, req, nil, errEmptyBodySig) + }) + t.Run("no tokens", func(t *testing.T) { + req := MetaWithToken{ + vheader: vh, + } + checkOwner(t, req, userPk.PublicKey(), nil) + }) + + t.Run("bearer without impersonate, no session", func(t *testing.T) { + req := MetaWithToken{ + vheader: vh, + bearer: newBearer(t, containerOwner, userID, false), + } + checkOwner(t, req, userPk.PublicKey(), nil) + }) + t.Run("bearer with impersonate, no session", func(t *testing.T) { + req := MetaWithToken{ + vheader: vh, + bearer: newBearer(t, containerOwner, userID, true), + } + checkOwner(t, req, containerOwner.PublicKey(), nil) + }) + t.Run("bearer with impersonate, with session", func(t *testing.T) { + // To check that bearer token takes priority, use different key to sign session token. + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + req := MetaWithToken{ + vheader: vh, + bearer: newBearer(t, containerOwner, userID, true), + token: newSession(t, pk), + } + checkOwner(t, req, containerOwner.PublicKey(), nil) + }) + t.Run("with session", func(t *testing.T) { + req := MetaWithToken{ + vheader: vh, + token: newSession(t, containerOwner), + } + checkOwner(t, req, containerOwner.PublicKey(), nil) + }) + t.Run("malformed session token", func(t *testing.T) { + // This test is tricky: session token has issuer field and signature, which must correspond to each other. + // SDK prevents constructing such token in the first place, but it is still possible via API. + // Thus, construct v2 token, convert it to SDK one and pass to our function. + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + var user1 user.ID + user.IDFromKey(&user1, pk.PrivateKey.PublicKey) + + var id refs.OwnerID + id.SetValue(user1.WalletBytes()) + + raw, err := uuid.New().MarshalBinary() + require.NoError(t, err) + + var cidV2 refs.ContainerID + cidtest.ID().WriteToV2(&cidV2) + + sessionCtx := new(sessionV2.ObjectSessionContext) + sessionCtx.SetTarget(&cidV2) + + var body sessionV2.TokenBody + body.SetOwnerID(&id) + body.SetID(raw) + body.SetLifetime(new(sessionV2.TokenLifetime)) + body.SetSessionKey(pk.PublicKey().Bytes()) + body.SetContext(sessionCtx) + + var tokV2 sessionV2.Token + tokV2.SetBody(&body) + require.NoError(t, sigutilV2.SignData(&containerOwner.PrivateKey, smWrapper{Token: &tokV2})) + require.NoError(t, sigutilV2.VerifyData(smWrapper{Token: &tokV2})) + + var tok sessionSDK.Object + require.NoError(t, tok.ReadFromV2(tokV2)) + + req := MetaWithToken{ + vheader: vh, + token: &tok, + } + checkOwner(t, req, nil, errInvalidSessionOwner) + }) +} + +type smWrapper struct { + *sessionV2.Token +} + +func (s smWrapper) ReadSignedData(data []byte) ([]byte, error) { + return s.Token.GetBody().StableMarshal(data), nil +} +func (s smWrapper) SignedDataSize() int { + return s.Token.GetBody().StableSize() +} + +func newSession(t *testing.T, pk *keys.PrivateKey) *sessionSDK.Object { + var tok sessionSDK.Object + require.NoError(t, tok.Sign(pk.PrivateKey)) + return &tok +} + +func newBearer(t *testing.T, pk *keys.PrivateKey, user user.ID, impersonate bool) *bearer.Token { + var tok bearer.Token + tok.SetImpersonate(impersonate) + tok.ForUser(user) + require.NoError(t, tok.Sign(pk.PrivateKey)) + return &tok +} + +func checkOwner(t *testing.T, req MetaWithToken, expected *keys.PublicKey, expectedErr error) { + _, actual, err := req.RequestOwner() + if expectedErr != nil { + require.ErrorIs(t, err, expectedErr) + return + } + + require.NoError(t, err) + require.Equal(t, expected, actual) +} From ec2873caa7c67777f5fe96a87818c048754f706e Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 2 May 2024 20:03:33 +0300 Subject: [PATCH 0528/1413] [#1116] node: Fix writecache metrics Signed-off-by: Alexander Chuprov --- pkg/metrics/writecache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/metrics/writecache.go b/pkg/metrics/writecache.go index 2fe01526ea..1b708f7103 100644 --- a/pkg/metrics/writecache.go +++ b/pkg/metrics/writecache.go @@ -35,7 +35,7 @@ func newWriteCacheMetrics() *writeCacheMetrics { Subsystem: writeCacheSubsystem, Name: "request_duration_seconds", Help: "Writecache request process duration", - }, []string{shardIDLabel, successLabel, storageLabel, methodLabel}), + }, []string{shardIDLabel, successLabel, storageLabel, methodLabel, pathLabel}), operationCounter: metrics.NewCounterVec(prometheus.CounterOpts{ Namespace: namespace, Subsystem: writeCacheSubsystem, From e07869a8cf918349acfdcfa5058931352b3a9e71 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Sat, 27 Apr 2024 15:24:11 +0300 Subject: [PATCH 0529/1413] [#1100] Remove unused fields Signed-off-by: Ekaterina Lebedeva --- .../internal/modules/morph/helper/local_client.go | 8 +++----- cmd/frostfs-cli/modules/container/policy_playground.go | 8 +++----- pkg/innerring/innerring.go | 3 --- pkg/local_object_storage/pilorama/heap.go | 2 -- pkg/services/object/acl/v2/request_test.go | 1 + pkg/services/policer/option.go | 3 +-- 6 files changed, 8 insertions(+), 17 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index d309e7e5bb..31203dde66 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -44,7 +44,6 @@ type LocalClient struct { transactions []*transaction.Transaction dumpPath string accounts []*wallet.Account - maxGasInvoke int64 } func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) { @@ -104,10 +103,9 @@ func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet } return &LocalClient{ - bc: bc, - dumpPath: dumpPath, - accounts: accounts[:m], - maxGasInvoke: 15_0000_0000, + bc: bc, + dumpPath: dumpPath, + accounts: accounts[:m], }, nil } diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 1ac41f08ca..095ab64381 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -20,14 +20,12 @@ import ( type policyPlaygroundREPL struct { cmd *cobra.Command - args []string nodes map[string]netmap.NodeInfo } -func newPolicyPlaygroundREPL(cmd *cobra.Command, args []string) (*policyPlaygroundREPL, error) { +func newPolicyPlaygroundREPL(cmd *cobra.Command) (*policyPlaygroundREPL, error) { return &policyPlaygroundREPL{ cmd: cmd, - args: args, nodes: map[string]netmap.NodeInfo{}, }, nil } @@ -221,8 +219,8 @@ var policyPlaygroundCmd = &cobra.Command{ Short: "A REPL for testing placement policies", Long: `A REPL for testing placement policies. If a wallet and endpoint is provided, the initial netmap data will be loaded from the snapshot of the node. Otherwise, an empty playground is created.`, - Run: func(cmd *cobra.Command, args []string) { - repl, err := newPolicyPlaygroundREPL(cmd, args) + Run: func(cmd *cobra.Command, _ []string) { + repl, err := newPolicyPlaygroundREPL(cmd) commonCmd.ExitOnErr(cmd, "could not create policy playground: %w", err) commonCmd.ExitOnErr(cmd, "policy playground failed: %w", repl.run()) }, diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 11d43f845f..5dea18f9d5 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -69,7 +69,6 @@ type ( // internal variables key *keys.PrivateKey - pubKey []byte contracts *contracts predefinedValidators keys.PublicKeys initialEpochTickDelta uint32 @@ -391,8 +390,6 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan return nil, fmt.Errorf("ir: can't parse predefined validators list: %w", err) } - server.pubKey = server.key.PublicKey().Bytes() - var morphClients *serverMorphClients morphClients, err = server.initClientsFromMorph() if err != nil { diff --git a/pkg/local_object_storage/pilorama/heap.go b/pkg/local_object_storage/pilorama/heap.go index 50abb663c7..d81ec735d0 100644 --- a/pkg/local_object_storage/pilorama/heap.go +++ b/pkg/local_object_storage/pilorama/heap.go @@ -29,7 +29,6 @@ func (h *filenameHeap) Pop() any { // fixedHeap maintains a fixed number of smallest elements started at some point. type fixedHeap struct { start string - max string count int h *filenameHeap } @@ -40,7 +39,6 @@ func newHeap(start string, count int) *fixedHeap { return &fixedHeap{ start: start, - max: "", count: count, h: h, } diff --git a/pkg/services/object/acl/v2/request_test.go b/pkg/services/object/acl/v2/request_test.go index 6c6d79adf3..980d1a2e59 100644 --- a/pkg/services/object/acl/v2/request_test.go +++ b/pkg/services/object/acl/v2/request_test.go @@ -133,6 +133,7 @@ type smWrapper struct { func (s smWrapper) ReadSignedData(data []byte) ([]byte, error) { return s.Token.GetBody().StableMarshal(data), nil } + func (s smWrapper) SignedDataSize() int { return s.Token.GetBody().StableSize() } diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 92cf83a842..58c74ee1a5 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -66,7 +66,7 @@ type cfg struct { batchSize, cacheSize uint32 - rebalanceFreq, evictDuration, sleepDuration time.Duration + evictDuration, sleepDuration time.Duration metrics MetricsRegister } @@ -76,7 +76,6 @@ func defaultCfg() *cfg { log: &logger.Logger{Logger: zap.L()}, batchSize: 10, cacheSize: 1024, // 1024 * address size = 1024 * 64 = 64 MiB - rebalanceFreq: 1 * time.Second, sleepDuration: 1 * time.Second, evictDuration: 30 * time.Second, metrics: noopMetrics{}, From 45f4e6939d93925f5cdf3d8bed604ae515711ea6 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 2 May 2024 19:45:09 +0300 Subject: [PATCH 0530/1413] [#1117] morph: Make frostfsid client provide GetSubjectExtended method Signed-off-by: Airat Arifullin --- pkg/morph/client/frostfsid/subject.go | 132 +++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index 52ae98ba57..169be6bc54 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -13,7 +13,10 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) -const methodGetSubject = "getSubject" +const ( + methodGetSubject = "getSubject" + methodGetSubjectExtended = "getSubjectExtended" +) func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) { prm := client.TestInvokePrm{} @@ -33,6 +36,24 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) return subj, nil } +func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.SubjectExtended, error) { + prm := client.TestInvokePrm{} + prm.SetMethod(methodGetSubjectExtended) + prm.SetArgs(addr) + + res, err := c.client.TestInvoke(prm) + if err != nil { + return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) + } + + subj, err := parseSubjectExtended(res) + if err != nil { + return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) + } + + return subj, nil +} + func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) { if ln := len(res); ln != 1 { return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) @@ -79,6 +100,64 @@ func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) { return &subj, nil } +func parseSubjectExtended(res []stackitem.Item) (*frostfsidclient.SubjectExtended, error) { + if ln := len(res); ln != 1 { + return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) + } + + structArr, err := client.ArrayFromStackItem(res[0]) + if err != nil { + return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) + } + + var subj frostfsidclient.SubjectExtended + + subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) + if err != nil { + return nil, err + } + + if !structArr[1].Equals(stackitem.Null{}) { + subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) + if err != nil { + return nil, err + } + } + + if !structArr[2].Equals(stackitem.Null{}) { + subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) + if err != nil { + return nil, err + } + } + + if !structArr[3].Equals(stackitem.Null{}) { + subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) + if err != nil { + return nil, err + } + } + + subj.KV, err = parseMap(structArr[4]) + if err != nil { + return nil, err + } + + if !structArr[5].Equals(stackitem.Null{}) { + groupItems, ok := structArr[5].Value().([]stackitem.Item) + if !ok { + return nil, errors.New("invalid groups field") + } + + subj.Groups, err = parseGroups(groupItems) + if err != nil { + return nil, err + } + } + + return &subj, nil +} + func makeValidRes(item stackitem.Item) (*result.Invoke, error) { return &result.Invoke{ Stack: []stackitem.Item{item}, @@ -116,3 +195,54 @@ func parseMap(item stackitem.Item) (map[string]string, error) { return res, nil } + +func parseGroups(items []stackitem.Item) ([]*frostfsidclient.Group, error) { + var err error + res := make([]*frostfsidclient.Group, len(items)) + + for i := 0; i < len(items); i++ { + arr, ok := items[i].Value().([]stackitem.Item) + if !ok { + return nil, errors.New("invalid group type") + } + res[i], err = parseGroup(arr) + if err != nil { + return nil, err + } + } + + return res, nil +} + +func parseGroup(structArr []stackitem.Item) (*frostfsidclient.Group, error) { + if len(structArr) < 4 { + return nil, errors.New("invalid response group struct") + } + + groupID, err := structArr[0].TryInteger() + if err != nil { + return nil, err + } + + name, err := structArr[1].TryBytes() + if err != nil { + return nil, err + } + + namespace, err := structArr[2].TryBytes() + if err != nil { + return nil, err + } + + kvs, err := parseMap(structArr[3]) + if err != nil { + return nil, err + } + + return &frostfsidclient.Group{ + ID: groupID.Int64(), + Name: string(name), + Namespace: string(namespace), + KV: kvs, + }, nil +} From 6c76c9b457b24349d6fc1ff0d262f57006931b03 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 2 May 2024 20:26:06 +0300 Subject: [PATCH 0531/1413] [#1117] core: Introduce SubjectProvider interface for FrostfsID * Make tree, object and container services use SubjectProvider interface. * Fix unit-tests. Signed-off-by: Airat Arifullin --- pkg/ape/request/request.go | 2 +- pkg/core/frostfsid/subject_provider.go | 16 ++++++++++ pkg/morph/client/frostfsid/client.go | 3 ++ pkg/services/container/ape.go | 19 +++--------- pkg/services/container/ape_test.go | 17 ++++++++-- pkg/services/object/ape/checker.go | 11 ++----- pkg/services/object/ape/checker_test.go | 41 ++++++++++++++++++++++--- pkg/services/object/ape/request.go | 7 ++--- pkg/services/tree/ape.go | 5 ++- pkg/services/tree/options.go | 11 ++----- 10 files changed, 85 insertions(+), 47 deletions(-) create mode 100644 pkg/core/frostfsid/subject_provider.go diff --git a/pkg/ape/request/request.go b/pkg/ape/request/request.go index 6d62ef3d55..de67dea235 100644 --- a/pkg/ape/request/request.go +++ b/pkg/ape/request/request.go @@ -1,4 +1,4 @@ -package ape +package request import ( aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" diff --git a/pkg/core/frostfsid/subject_provider.go b/pkg/core/frostfsid/subject_provider.go new file mode 100644 index 0000000000..ecfd0eb157 --- /dev/null +++ b/pkg/core/frostfsid/subject_provider.go @@ -0,0 +1,16 @@ +package frostfsid + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +const ( + SubjectNotFoundErrorMessage = "subject not found" +) + +// SubjectProvider interface provides methods to get subject from FrostfsID contract. +type SubjectProvider interface { + GetSubject(util.Uint160) (*client.Subject, error) + GetSubjectExtended(util.Uint160) (*client.SubjectExtended, error) +} diff --git a/pkg/morph/client/frostfsid/client.go b/pkg/morph/client/frostfsid/client.go index 3efa522bc3..4c31f42de9 100644 --- a/pkg/morph/client/frostfsid/client.go +++ b/pkg/morph/client/frostfsid/client.go @@ -3,6 +3,7 @@ package frostfsid import ( "fmt" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" @@ -20,6 +21,8 @@ type Client struct { client *client.StaticClient // static FrostFS ID contract client } +var _ frostfsidcore.SubjectProvider = (*Client)(nil) + // NewFromMorph wraps client to work with FrostFS ID contract. func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8) (*Client, error) { sc, err := client.NewStatic(cli, contract, fee, client.TryNotary(), client.AsAlphabet()) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 2ce427fa33..9c38d1bba4 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -14,9 +14,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -30,11 +30,6 @@ import ( commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -const ( - subjectNotFoundErrorMessage = "subject not found" ) var ( @@ -59,22 +54,18 @@ type containers interface { Get(cid.ID) (*containercore.Container, error) } -type frostfsidSubjectProvider interface { - GetSubject(util.Uint160) (*client.Subject, error) -} - type apeChecker struct { router policyengine.ChainRouter reader containers ir ir nm netmap.Source - frostFSIDClient frostfsidSubjectProvider + frostFSIDClient frostfsidcore.SubjectProvider next Server } -func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm netmap.Source, frostFSIDClient frostfsidSubjectProvider, srv Server) Server { +func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm netmap.Source, frostFSIDClient frostfsidcore.SubjectProvider, srv Server) Server { return &apeChecker{ router: router, reader: reader, @@ -574,7 +565,7 @@ func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { if err == nil { namespace = subject.Namespace } else { - if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return "", fmt.Errorf("get subject error: %w", err) } } @@ -630,7 +621,7 @@ func (ac *apeChecker) fillWithUserClaimTags(reqProps map[string]string, pk *keys } subj, err := ac.frostFSIDClient.GetSubject(pk.GetScriptHash()) if err != nil { - if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return nil, fmt.Errorf("get subject error: %w", err) } return reqProps, nil diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index e26e82d43b..a2fe799565 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -15,6 +15,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -922,13 +923,22 @@ func (s *netmapStub) Epoch() (uint64, error) { } type frostfsidStub struct { - subjects map[util.Uint160]*client.Subject + subjects map[util.Uint160]*client.Subject + subjectsExt map[util.Uint160]*client.SubjectExtended } func (f *frostfsidStub) GetSubject(owner util.Uint160) (*client.Subject, error) { s, ok := f.subjects[owner] if !ok { - return nil, fmt.Errorf("%s", subjectNotFoundErrorMessage) + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) + } + return s, nil +} + +func (f *frostfsidStub) GetSubjectExtended(owner util.Uint160) (*client.SubjectExtended, error) { + s, ok := f.subjectsExt[owner] + if !ok { + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) } return s, nil } @@ -965,7 +975,8 @@ func newTestAPEServer() testAPEServer { netmap := &netmapStub{} frostfsIDSubjectReader := &frostfsidStub{ - subjects: map[util.Uint160]*client.Subject{}, + subjects: map[util.Uint160]*client.Subject{}, + subjectsExt: map[util.Uint160]*client.SubjectExtended{}, } apeChecker := &apeChecker{ diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 170787317d..e74b053799 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -6,7 +6,7 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -14,7 +14,6 @@ import ( policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/util" ) type checkerImpl struct { @@ -22,14 +21,10 @@ type checkerImpl struct { headerProvider HeaderProvider - frostFSIDClient frostfsidSubjectProvider + frostFSIDClient frostfsidcore.SubjectProvider } -type frostfsidSubjectProvider interface { - GetSubject(util.Uint160) (*client.Subject, error) -} - -func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidSubjectProvider) Checker { +func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider) Checker { return &checkerImpl{ chainRouter: chainRouter, diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 9510bf039d..c591bc4947 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -7,6 +7,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -156,14 +157,15 @@ var ( ) type frostfsIDProviderMock struct { - m map[util.Uint160]*client.Subject + subjects map[util.Uint160]*client.Subject + subjectsExtended map[util.Uint160]*client.SubjectExtended } -var _ frostfsidSubjectProvider = (*frostfsIDProviderMock)(nil) +var _ frostfsidcore.SubjectProvider = (*frostfsIDProviderMock)(nil) func newFrostfsIDProviderMock(t *testing.T) *frostfsIDProviderMock { return &frostfsIDProviderMock{ - m: map[util.Uint160]*client.Subject{ + subjects: map[util.Uint160]*client.Subject{ scriptHashFromSenderKey(t, senderKey): { Namespace: "testnamespace", Name: "test", @@ -173,6 +175,27 @@ func newFrostfsIDProviderMock(t *testing.T) *frostfsIDProviderMock { }, }, }, + subjectsExtended: map[util.Uint160]*client.SubjectExtended{ + scriptHashFromSenderKey(t, senderKey): { + Namespace: "testnamespace", + Name: "test", + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 1, + Name: "test", + Namespace: "testnamespace", + KV: map[string]string{ + "attr1": "value1", + "attr2": "value2", + }, + }, + }, + }, + }, } } @@ -183,9 +206,17 @@ func scriptHashFromSenderKey(t *testing.T, senderKey string) util.Uint160 { } func (f *frostfsIDProviderMock) GetSubject(key util.Uint160) (*client.Subject, error) { - v, ok := f.m[key] + v, ok := f.subjects[key] if !ok { - return nil, fmt.Errorf("%s", subjectNotFoundErrorMessage) + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) + } + return v, nil +} + +func (f *frostfsIDProviderMock) GetSubjectExtended(key util.Uint160) (*client.SubjectExtended, error) { + v, ok := f.subjectsExtended[key] + if !ok { + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) } return v, nil } diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 5daf8751b0..82b6adb1ff 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -8,6 +8,7 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -18,10 +19,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) -const ( - subjectNotFoundErrorMessage = "subject not found" -) - var defaultRequest = aperequest.Request{} func nativeSchemaRole(role acl.Role) string { @@ -153,7 +150,7 @@ func (c *checkerImpl) fillWithUserClaimTags(reqProps map[string]string, prm Prm) } subj, err := c.frostFSIDClient.GetSubject(pk.GetScriptHash()) if err != nil { - if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return nil, fmt.Errorf("get subject error: %w", err) } return reqProps, nil diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 76ec254f05..47e7cb41db 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" @@ -19,8 +20,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) -var subjectNotFoundErrorMessage = "subject not found" - func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error { namespace := "" cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns") @@ -83,7 +82,7 @@ func (s *Service) fillWithUserClaimTags(reqProps map[string]string, publicKey *k } subj, err := s.frostfsidSubjectProvider.GetSubject(publicKey.GetScriptHash()) if err != nil { - if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return nil, fmt.Errorf("get subject error: %w", err) } return reqProps, nil diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index c4ef80856f..a99ba60467 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -4,21 +4,16 @@ import ( "crypto/ecdsa" "time" - "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/util" ) -type FrostfsidSubjectProvider interface { - GetSubject(util.Uint160) (*client.Subject, error) -} - type ContainerSource interface { container.Source @@ -36,7 +31,7 @@ type cfg struct { rawPub []byte nmSource netmap.Source cnrSource ContainerSource - frostfsidSubjectProvider FrostfsidSubjectProvider + frostfsidSubjectProvider frostfsidcore.SubjectProvider eaclSource container.EACLSource forest pilorama.Forest // replication-related parameters @@ -62,7 +57,7 @@ func WithContainerSource(src ContainerSource) Option { } } -func WithFrostfsidSubjectProvider(provider FrostfsidSubjectProvider) Option { +func WithFrostfsidSubjectProvider(provider frostfsidcore.SubjectProvider) Option { return func(c *cfg) { c.frostfsidSubjectProvider = provider } From b60a51b862eb699478cd5c59b3b9222a5da8c60d Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 2 May 2024 21:15:58 +0300 Subject: [PATCH 0532/1413] [#1117] ape: Introduce `FormFrostfsIDRequestProperties` method * `FormFrostfsIDRequestProperties` gets user claim tags and group id and sets them as ape request properties. * Make tree, container and object service use the method. * Fix unit-tests. Signed-off-by: Airat Arifullin --- pkg/ape/request/frostfsid.go | 36 +++++ pkg/services/container/ape.go | 13 +- pkg/services/container/ape_test.go | 170 ++++++++++++++++++++++++ pkg/services/object/ape/request.go | 15 +-- pkg/services/object/ape/request_test.go | 1 + pkg/services/tree/ape.go | 14 +- 6 files changed, 219 insertions(+), 30 deletions(-) create mode 100644 pkg/ape/request/frostfsid.go diff --git a/pkg/ape/request/frostfsid.go b/pkg/ape/request/frostfsid.go new file mode 100644 index 0000000000..fa620e58ca --- /dev/null +++ b/pkg/ape/request/frostfsid.go @@ -0,0 +1,36 @@ +package request + +import ( + "fmt" + "strconv" + "strings" + + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +// FormFrostfsIDRequestProperties forms frostfsid specific request properties like user-claim tags and group ID. +func FormFrostfsIDRequestProperties(frostFSIDClient frostfsidcore.SubjectProvider, pk *keys.PublicKey) (map[string]string, error) { + reqProps := make(map[string]string) + subj, err := frostFSIDClient.GetSubjectExtended(pk.GetScriptHash()) + if err != nil { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { + return nil, fmt.Errorf("get subject error: %w", err) + } + return reqProps, nil + } + for k, v := range subj.KV { + propertyKey := fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, k) + reqProps[propertyKey] = v + } + + groups := make([]string, len(subj.Groups)) + for i, group := range subj.Groups { + groups[i] = strconv.FormatInt(group.ID, 10) + } + reqProps[commonschema.PropertyKeyFrostFSIDGroupID] = apechain.FormCondSliceContainsValue(groups) + + return reqProps, nil +} diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 9c38d1bba4..22440ab804 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -27,7 +27,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" - commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) @@ -619,16 +618,12 @@ func (ac *apeChecker) fillWithUserClaimTags(reqProps map[string]string, pk *keys if reqProps == nil { reqProps = make(map[string]string) } - subj, err := ac.frostFSIDClient.GetSubject(pk.GetScriptHash()) + props, err := aperequest.FormFrostfsIDRequestProperties(ac.frostFSIDClient, pk) if err != nil { - if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { - return nil, fmt.Errorf("get subject error: %w", err) - } - return reqProps, nil + return reqProps, err } - for k, v := range subj.KV { - properyKey := fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, k) - reqProps[properyKey] = v + for propertyName, properyValue := range props { + reqProps[propertyName] = properyValue } return reqProps, nil } diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index a2fe799565..94c3027c01 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -45,6 +45,7 @@ func TestAPE(t *testing.T) { t.Run("deny get container no rule found", testDenyGetContainerNoRuleFound) t.Run("deny get container for others", testDenyGetContainerForOthers) t.Run("deny get container by user claim tag", testDenyGetContainerByUserClaimTag) + t.Run("deny get container by group id", testDenyGetContainerByGroupID) t.Run("deny set container eACL for IR", testDenySetContainerEACLForIR) t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken) t.Run("deny put container for others with session token", testDenyPutContainerForOthersSessionToken) @@ -279,6 +280,19 @@ func testDenyGetContainerByUserClaimTag(t *testing.T) { }, }, }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 19888, + }, + }, + }, + }, } apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) @@ -339,6 +353,104 @@ func testDenyGetContainerByUserClaimTag(t *testing.T) { require.ErrorAs(t, err, &errAccessDenied) } +func testDenyGetContainerByGroupID(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + }, + }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 19888, + }, + }, + }, + }, + } + + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Object: chain.ObjectRequest, + Key: commonschema.PropertyKeyFrostFSIDGroupID, + Value: "19888", + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + resp, err := apeSrv.Get(context.Background(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) +} + func testDenySetContainerEACLForIR(t *testing.T) { t.Parallel() srv := &srvStub{ @@ -621,6 +733,21 @@ func testDenyPutContainerReadNamespaceFromFrostfsID(t *testing.T) { Name: testDomainName, }, }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + ownerScriptHash: { + Namespace: testDomainName, + Name: testDomainName, + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 19888, + }, + }, + }, + }, } apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) resp, err := apeSrv.Put(context.Background(), req) @@ -690,6 +817,21 @@ func testDenyPutContainerInvalidNamespace(t *testing.T) { Name: testDomainName, }, }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + ownerScriptHash: { + Namespace: testDomainName, + Name: testDomainName, + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 19888, + }, + }, + }, + }, } apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) resp, err := apeSrv.Put(context.Background(), req) @@ -800,6 +942,34 @@ func testDenyListContainersValidationNamespaceError(t *testing.T) { Name: testDomainName, }, }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + actorScriptHash: { + Namespace: actorDomain, + Name: actorDomain, + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 19777, + }, + }, + }, + ownerScriptHash: { + Namespace: testDomainName, + Name: testDomainName, + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 19888, + }, + }, + }, + }, } apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 82b6adb1ff..cbecc73e3d 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -4,17 +4,14 @@ import ( "context" "fmt" "strconv" - "strings" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" - frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) @@ -148,16 +145,12 @@ func (c *checkerImpl) fillWithUserClaimTags(reqProps map[string]string, prm Prm) if err != nil { return nil, err } - subj, err := c.frostFSIDClient.GetSubject(pk.GetScriptHash()) + props, err := aperequest.FormFrostfsIDRequestProperties(c.frostFSIDClient, pk) if err != nil { - if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { - return nil, fmt.Errorf("get subject error: %w", err) - } - return reqProps, nil + return reqProps, err } - for k, v := range subj.KV { - properyKey := fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, k) - reqProps[properyKey] = v + for propertyName, properyValue := range props { + reqProps[propertyName] = properyValue } return reqProps, nil } diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index cda78e69c4..5c74e7d1d2 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -275,6 +275,7 @@ func TestNewAPERequest(t *testing.T) { nativeschema.PropertyKeyActorRole: prm.Role, fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, "tag-attr1"): "value1", fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, "tag-attr2"): "value2", + commonschema.PropertyKeyFrostFSIDGroupID: "1", }, ) diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 47e7cb41db..622049d6a8 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -8,14 +8,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" - commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) @@ -80,16 +78,12 @@ func (s *Service) fillWithUserClaimTags(reqProps map[string]string, publicKey *k if reqProps == nil { reqProps = make(map[string]string) } - subj, err := s.frostfsidSubjectProvider.GetSubject(publicKey.GetScriptHash()) + props, err := aperequest.FormFrostfsIDRequestProperties(s.frostfsidSubjectProvider, publicKey) if err != nil { - if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { - return nil, fmt.Errorf("get subject error: %w", err) - } - return reqProps, nil + return reqProps, err } - for k, v := range subj.KV { - properyKey := fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, k) - reqProps[properyKey] = v + for propertyName, properyValue := range props { + reqProps[propertyName] = properyValue } return reqProps, nil } From 9cc51f86b7c4276a0bec623e494745c92f21fffa Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 6 May 2024 19:30:19 +0300 Subject: [PATCH 0533/1413] [#1117] node: Introduce cache for frostfsid contract client Signed-off-by: Airat Arifullin --- cmd/frostfs-node/config.go | 4 +- cmd/frostfs-node/config/morph/config.go | 15 ++++++ cmd/frostfs-node/container.go | 13 ++++- cmd/frostfs-node/frostfsid.go | 71 +++++++++++++++++++++++++ 4 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 cmd/frostfs-node/frostfsid.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 5606ed24cc..d713cf2fb8 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -32,6 +32,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" @@ -46,7 +47,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" containerClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" - frostfsidClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmap2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" @@ -421,7 +421,7 @@ type shared struct { cnrClient *containerClient.Client - frostfsidClient *frostfsidClient.Client + frostfsidClient frostfsidcore.SubjectProvider respSvc *response.Service diff --git a/cmd/frostfs-node/config/morph/config.go b/cmd/frostfs-node/config/morph/config.go index c32940625b..a240c5d490 100644 --- a/cmd/frostfs-node/config/morph/config.go +++ b/cmd/frostfs-node/config/morph/config.go @@ -28,6 +28,9 @@ const ( // APEChainCacheSizeDefault is a default value of APE chain cache. APEChainCacheSizeDefault = 10_000 + + // FrostfsIDCacheSizeDefault is a default value of APE chain cache. + FrostfsIDCacheSizeDefault = 10_000 ) var errNoMorphEndpoints = errors.New("no morph chain RPC endpoints, see `morph.rpc_endpoint` section") @@ -114,3 +117,15 @@ func APEChainCacheSize(c *config.Config) uint32 { } return config.Uint32Safe(c.Sub(subsection), "ape_chain_cache_size") } + +// FrostfsIDCacheSize returns the value of "frostfsid_cache_size" config parameter +// from "morph" section. +// +// Returns 0 if the value is not positive integer. +// Returns FrostfsIDCacheSizeDefault if the value is missing. +func FrostfsIDCacheSize(c *config.Config) uint32 { + if c.Sub(subsection).Value("frostfsid_cache_size") == nil { + return FrostfsIDCacheSizeDefault + } + return config.Uint32Safe(c.Sub(subsection), "frostfsid_cache_size") +} diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index e006648ed2..61600376ba 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -6,8 +6,10 @@ import ( "net" containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" + morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" @@ -33,9 +35,16 @@ func initContainerService(_ context.Context, c *cfg) { cnrRdr, cnrWrt := configureEACLAndContainerSources(c, wrap, cnrSrc) - frostFSIDClient, err := frostfsid.NewFromMorph(c.cfgMorph.client, c.cfgFrostfsID.scriptHash, 0) + var frostfsIDSubjectProvider frostfsidcore.SubjectProvider + frostfsIDSubjectProvider, err = frostfsid.NewFromMorph(c.cfgMorph.client, c.cfgFrostfsID.scriptHash, 0) fatalOnErr(err) - c.shared.frostfsidClient = frostFSIDClient + + cacheSize := morphconfig.FrostfsIDCacheSize(c.appCfg) + if cacheSize > 0 { + frostfsIDSubjectProvider = newMorphFrostfsIDCache(frostfsIDSubjectProvider, int(cacheSize), c.cfgMorph.cacheTTL) + } + + c.shared.frostfsidClient = frostfsIDSubjectProvider server := containerTransportGRPC.New( containerService.NewSignService( diff --git a/cmd/frostfs-node/frostfsid.go b/cmd/frostfs-node/frostfsid.go new file mode 100644 index 0000000000..68cc1d0407 --- /dev/null +++ b/cmd/frostfs-node/frostfsid.go @@ -0,0 +1,71 @@ +package main + +import ( + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" + "github.com/hashicorp/golang-lru/v2/expirable" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +type morphFrostfsIDCache struct { + subjProvider frostfsidcore.SubjectProvider + + subjCache *expirable.LRU[util.Uint160, *client.Subject] + + subjExtCache *expirable.LRU[util.Uint160, *client.SubjectExtended] +} + +func newMorphFrostfsIDCache(subjProvider frostfsidcore.SubjectProvider, size int, ttl time.Duration) frostfsidcore.SubjectProvider { + return &morphFrostfsIDCache{ + subjProvider: subjProvider, + + subjCache: expirable.NewLRU(size, func(util.Uint160, *client.Subject) {}, ttl), + + subjExtCache: expirable.NewLRU(size, func(util.Uint160, *client.SubjectExtended) {}, ttl), + } +} + +func (m *morphFrostfsIDCache) GetSubject(addr util.Uint160) (*client.Subject, error) { + result, found := m.subjCache.Get(addr) + if found { + return result, nil + } + + result, err := m.subjProvider.GetSubject(addr) + if err != nil { + return nil, err + } + + m.subjCache.Add(addr, result) + return result, nil +} + +func (m *morphFrostfsIDCache) GetSubjectExtended(addr util.Uint160) (*client.SubjectExtended, error) { + subjExt, found := m.subjExtCache.Get(addr) + if found { + return subjExt, nil + } + + var err error + subjExt, err = m.subjProvider.GetSubjectExtended(addr) + if err != nil { + return nil, err + } + + m.subjExtCache.Add(addr, subjExt) + m.subjCache.Add(addr, subjectFromSubjectExtended(subjExt)) + + return subjExt, nil +} + +func subjectFromSubjectExtended(subjExt *client.SubjectExtended) *client.Subject { + return &client.Subject{ + PrimaryKey: subjExt.PrimaryKey, + AdditionalKeys: subjExt.AdditionalKeys, + Namespace: subjExt.Name, + Name: subjExt.Name, + KV: subjExt.KV, + } +} From fc7b07f3145c735a1cf7ab5d1b6b75f4f1aec3e9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 6 May 2024 14:52:15 +0300 Subject: [PATCH 0534/1413] [#1118] docs: Fix pre-commit warnings Signed-off-by: Evgenii Stratonikov --- docs/images/authentication/impersonate.puml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/images/authentication/impersonate.puml b/docs/images/authentication/impersonate.puml index e9feae6e58..f0a5436f96 100644 --- a/docs/images/authentication/impersonate.puml +++ b/docs/images/authentication/impersonate.puml @@ -12,4 +12,4 @@ else (no) end endif -@enduml \ No newline at end of file +@enduml From a23d53b2d499ff87496ffd07b3fd2d267afb1550 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 6 May 2024 08:58:55 +0300 Subject: [PATCH 0535/1413] [#1118] .forgejo: Add pre-commit action Signed-off-by: Evgenii Stratonikov --- .forgejo/workflows/pre-commit.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .forgejo/workflows/pre-commit.yml diff --git a/.forgejo/workflows/pre-commit.yml b/.forgejo/workflows/pre-commit.yml new file mode 100644 index 0000000000..6453b50291 --- /dev/null +++ b/.forgejo/workflows/pre-commit.yml @@ -0,0 +1,25 @@ +name: Pre-commit hooks +on: [pull_request] + +jobs: + precommit: + name: Pre-commit + env: + # Skip pre-commit hooks which are executed by other actions. + SKIP: make-lint,go-staticcheck-repo-mod,go-unit-tests,gofumpt + runs-on: ubuntu-22.04 + # If we use actions/setup-python from either Github or Gitea, + # the line above fails with a cryptic error about not being able to found python. + # So install everything manually. + steps: + - uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.22 + - name: Set up Python + run: | + apt update + apt install -y pre-commit + - name: Run pre-commit + run: pre-commit run --color=always --hook-stage manual --all-files From 00b2b77b261b195df583916660161d45df4a30ae Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 2 May 2024 14:29:59 +0300 Subject: [PATCH 0536/1413] [#1112] node: Implement `Range\RangeHash` requests for EC object Signed-off-by: Anton Nikiforov --- go.mod | 4 +- go.sum | 8 +-- pkg/local_object_storage/engine/range.go | 13 ++++ pkg/services/object/get/assemblerec.go | 62 ++++++++++++++++--- .../object/get/v2/get_range_forwarder.go | 3 + pkg/services/object/get/v2/service.go | 3 + pkg/services/object/get/v2/util.go | 11 ++++ 7 files changed, 88 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 1be2526f20..08a59581d7 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240424080726-20ab57bf7ec3 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index 0795c955b7..6200022c71 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c h1:RFDrNsF2e+EJfaB8lZrRRxNjQkLfM09gnEyudvGuc10= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240422151450-df9b65324a4c/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f h1:YyjsQNtrngQzIKOUtApXoi5r5pewatM+cXfpY19vZWo= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 h1:FzurjElUwC7InY9v5rzXReKbfBL5yRJKSWJPq6BKhH0= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240424080726-20ab57bf7ec3 h1:7Sd/J2IM0uGpmFKBgseUh6/JsdJN06b8W8UZMKAUDZg= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240424080726-20ab57bf7ec3/go.mod h1:wDFmMP7l00Xd5VZVzF2MuhyJCnotyhfxHYnvrEEG/e4= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12 h1:uEAn+TBXxgqXXygrYW2X8dFmGydGyJvBc5ysnfHFhYM= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12/go.mod h1:e7H9nNFpx1Tj3R20Zoxy0Vo6Srlb6zV5L7ZQXqg9rn4= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a h1:wbndKvHbwDQiSMQWL75RxiTZCeUyCi7NUj1lsfdAGkc= diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index e45845d6c2..f5b33a251e 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -102,6 +102,9 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error if it.SplitInfo != nil { return RngRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo)) } + if it.ECInfo != nil { + return RngRes{}, logicerr.Wrap(objectSDK.NewECInfoError(it.ECInfo)) + } if it.Object == nil { // If any shard is in a degraded mode, we should assume that metabase could store @@ -147,6 +150,8 @@ type getRangeShardIterator struct { Object *objectSDK.Object SplitInfoError *objectSDK.SplitInfoError SplitInfo *objectSDK.SplitInfo + ECInfoError *objectSDK.ECInfoError + ECInfo *objectSDK.ECInfo OutError error ShardWithMeta hashedShard MetaError error @@ -188,6 +193,14 @@ func (i *getRangeShardIterator) tryGetWithMeta(ctx context.Context) { // stop iterating over shards if SplitInfo structure is complete return withLink && withLast + case errors.As(err, &i.ECInfoError): + if i.ECInfo == nil { + i.ECInfo = objectSDK.NewECInfo() + } + + util.MergeECInfo(i.ECInfoError.ECInfo(), i.ECInfo) + // stop iterating over shards if ECInfo structure is complete + return len(i.ECInfo.Chunks) == int(i.ECInfo.Chunks[0].Total) case client.IsErrObjectAlreadyRemoved(err), shard.IsErrOutOfRange(err): diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index d73d771cf8..4a624e4676 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -45,23 +46,64 @@ func newAssemblerEC( // Assemble assembles erasure-coded object and writes it's content to ObjectWriter. // It returns parent object. func (a *assemblerec) Assemble(ctx context.Context, writer ObjectWriter, headOnly bool) (*objectSDK.Object, error) { - parts := a.retrieveParts(ctx, headOnly) + if headOnly { + return a.reconstructHeader(ctx, writer) + } else if a.rng != nil { + return a.reconstructRange(ctx, writer) + } + return a.reconstructObject(ctx, writer) +} + +func (a *assemblerec) getConstructor() (*erasurecode.Constructor, error) { cnt, err := a.cs.Get(a.addr.Container()) if err != nil { return nil, err } - c, err := erasurecode.NewConstructor( - policy.ECDataCount(cnt.Value.PlacementPolicy()), - policy.ECParityCount(cnt.Value.PlacementPolicy()), - ) + dataCount := policy.ECDataCount(cnt.Value.PlacementPolicy()) + parityCount := policy.ECParityCount(cnt.Value.PlacementPolicy()) + return erasurecode.NewConstructor(dataCount, parityCount) +} + +func (a *assemblerec) reconstructHeader(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { + parts := a.retrieveParts(ctx, true) + c, err := a.getConstructor() if err != nil { return nil, err } - if headOnly { - obj, err := c.ReconstructHeader(parts) - if err == nil { - return obj, writer.WriteHeader(ctx, obj) - } + obj, err := c.ReconstructHeader(parts) + if err == nil { + return obj, writer.WriteHeader(ctx, obj) + } + return nil, err +} + +func (a *assemblerec) reconstructRange(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { + parts := a.retrieveParts(ctx, false) + c, err := a.getConstructor() + if err != nil { + return nil, err + } + obj, err := c.Reconstruct(parts) + if err != nil { + return nil, err + } + + from := a.rng.GetOffset() + to := from + a.rng.GetLength() + if pLen := uint64(len(obj.Payload())); to < from || pLen < from || pLen < to { + return nil, &apistatus.ObjectOutOfRange{} + } + err = writer.WriteChunk(ctx, obj.Payload()[from:to]) + if err != nil { + return nil, err + } + return obj, err +} + +func (a *assemblerec) reconstructObject(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { + parts := a.retrieveParts(ctx, false) + c, err := a.getConstructor() + if err != nil { return nil, err } obj, err := c.Reconstruct(parts) diff --git a/pkg/services/object/get/v2/get_range_forwarder.go b/pkg/services/object/get/v2/get_range_forwarder.go index 8a56c59a6a..5b05ec3703 100644 --- a/pkg/services/object/get/v2/get_range_forwarder.go +++ b/pkg/services/object/get/v2/get_range_forwarder.go @@ -132,6 +132,9 @@ func (f *getRangeRequestForwarder) readStream(ctx context.Context, rangeStream * case *objectV2.SplitInfo: si := objectSDK.NewSplitInfoFromV2(v) return objectSDK.NewSplitInfoError(si) + case *objectV2.ECInfo: + ei := objectSDK.NewECInfoFromV2(v) + return objectSDK.NewECInfoError(ei) } } return nil diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index 682128df67..edd19b441d 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -104,10 +104,13 @@ func (s *Service) GetRange(req *objectV2.GetRangeRequest, stream objectSvc.GetOb err = s.svc.GetRange(stream.Context(), *p) var splitErr *objectSDK.SplitInfoError + var ecErr *objectSDK.ECInfoError switch { case errors.As(err, &splitErr): return stream.Send(splitInfoRangeResponse(splitErr.SplitInfo())) + case errors.As(err, &ecErr): + return stream.Send(ecInfoRangeResponse(ecErr.ECInfo())) default: return err } diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index da64289852..610076c7a9 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -292,6 +292,17 @@ func splitInfoRangeResponse(info *objectSDK.SplitInfo) *objectV2.GetRangeRespons return resp } +func ecInfoRangeResponse(info *objectSDK.ECInfo) *objectV2.GetRangeResponse { + resp := new(objectV2.GetRangeResponse) + + body := new(objectV2.GetRangeResponseBody) + resp.SetBody(body) + + body.SetRangePart(info.ToV2()) + + return resp +} + func setSplitInfoHeadResponse(info *objectSDK.SplitInfo, resp *objectV2.HeadResponse) { resp.GetBody().SetHeaderPart(info.ToV2()) } From 93c0ccad4ffbda4b5b4a9a99af8ac88c97a9df28 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 5 Apr 2024 15:54:36 +0300 Subject: [PATCH 0537/1413] [#1077] objectsvc: Fix possible panic in GetRange() Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/assembler.go | 2 +- pkg/services/object/get/get_test.go | 220 +++++++++++++++++++++++++-- 2 files changed, 206 insertions(+), 16 deletions(-) diff --git a/pkg/services/object/get/assembler.go b/pkg/services/object/get/assembler.go index f10c67e524..025296ec77 100644 --- a/pkg/services/object/get/assembler.go +++ b/pkg/services/object/get/assembler.go @@ -114,7 +114,7 @@ func (a *assembler) initializeFromSourceObjectID(ctx context.Context, id oid.ID) } to := uint64(0) - if seekOff+seekLen > a.currentOffset+from { + if seekOff+seekLen >= a.currentOffset+from { to = seekOff + seekLen - a.currentOffset } diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 64614d8d83..be1e96c298 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -1,6 +1,7 @@ package getsvc import ( + "bytes" "context" "crypto/ecdsa" "crypto/rand" @@ -25,6 +26,9 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) @@ -61,6 +65,9 @@ type testEpochReceiver uint64 func (e testEpochReceiver) Epoch() (uint64, error) { return uint64(e), nil } +func (e testEpochReceiver) CurrentEpoch() uint64 { + return uint64(e) +} func newTestStorage() *testStorage { return &testStorage{ @@ -555,21 +562,6 @@ func TestGetRemoteSmall(t *testing.T) { return p } - newRngPrm := func(raw bool, w ChunkWriter, off, ln uint64) RangePrm { - p := RangePrm{} - p.SetChunkWriter(w) - p.WithRawFlag(raw) - p.common = new(util.CommonPrm).WithLocalOnly(false) - - r := objectSDK.NewRange() - r.SetOffset(off) - r.SetLength(ln) - - p.SetRange(r) - - return p - } - newHeadPrm := func(raw bool, w ObjectWriter) HeadPrm { p := HeadPrm{} p.SetHeaderWriter(w) @@ -1628,6 +1620,204 @@ func TestGetRemoteSmall(t *testing.T) { }) } +type testTarget struct { + objects []*objectSDK.Object +} + +func (tt *testTarget) WriteObject(_ context.Context, obj *objectSDK.Object) error { + tt.objects = append(tt.objects, obj) + return nil +} + +func objectChain(t *testing.T, cnr cid.ID, singleSize, totalSize uint64) (oid.ID, []*objectSDK.Object, *objectSDK.Object, []byte) { + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + tt := new(testTarget) + p := transformer.NewPayloadSizeLimiter(transformer.Params{ + Key: &pk.PrivateKey, + NextTargetInit: func() transformer.ObjectWriter { return tt }, + NetworkState: testEpochReceiver(1), + MaxSize: singleSize, + }) + + payload := make([]byte, totalSize) + _, err = rand.Read(payload) + require.NoError(t, err) + + ver := version.Current() + hdr := objectSDK.New() + hdr.SetContainerID(cnr) + hdr.SetType(objectSDK.TypeRegular) + hdr.SetVersion(&ver) + + ctx := context.Background() + require.NoError(t, p.WriteHeader(ctx, hdr)) + + _, err = p.Write(ctx, payload) + require.NoError(t, err) + + res, err := p.Close(ctx) + require.NoError(t, err) + + if totalSize <= singleSize { + // Small object, no linking. + require.Len(t, tt.objects, 1) + return res.SelfID, tt.objects, nil, payload + } + + return *res.ParentID, tt.objects[:len(tt.objects)-1], tt.objects[len(tt.objects)-1], bytes.Clone(payload) +} + +func newRngPrm(raw bool, w ChunkWriter, off, ln uint64) RangePrm { + p := RangePrm{} + p.SetChunkWriter(w) + p.WithRawFlag(raw) + p.common = new(util.CommonPrm) + + r := objectSDK.NewRange() + r.SetOffset(off) + r.SetLength(ln) + + p.SetRange(r) + return p +} + +func TestGetRange(t *testing.T) { + var cnr container.Container + cnr.SetPlacementPolicy(netmaptest.PlacementPolicy()) + + var idCnr cid.ID + container.CalculateID(&idCnr, cnr) + + ns, as := testNodeMatrix(t, []int{2}) + + testGetRange := func(t *testing.T, svc *Service, addr oid.Address, from, to uint64, payload []byte) { + w := NewSimpleObjectWriter() + rngPrm := newRngPrm(false, w, from, to-from) + rngPrm.WithAddress(addr) + + err := svc.GetRange(context.Background(), rngPrm) + require.NoError(t, err) + if from == to { + require.Nil(t, w.Object().Payload()) + } else { + require.Equal(t, payload[from:to], w.Object().Payload()) + } + } + + newSvc := func(b *testPlacementBuilder, c *testClientCache) *Service { + const curEpoch = 13 + + return &Service{ + log: test.NewLogger(t), + localStorage: newTestStorage(), + traverserGenerator: &testTraverserGenerator{ + c: cnr, + b: map[uint64]placement.Builder{ + curEpoch: b, + }, + }, + epochSource: testEpochReceiver(curEpoch), + remoteStorageConstructor: c, + keyStore: &testKeyStorage{}, + } + } + + t.Run("small", func(t *testing.T) { + const totalSize = 5 + _, objs, _, payload := objectChain(t, idCnr, totalSize, totalSize) + require.Len(t, objs, 1) + require.Len(t, payload, totalSize) + + obj := objs[0] + addr := object.AddressOf(obj) + builder := &testPlacementBuilder{vectors: map[string][][]netmap.NodeInfo{addr.EncodeToString(): ns}} + + c1 := newTestClient() + c1.addResult(addr, obj, nil) + + svc := newSvc(builder, &testClientCache{ + clients: map[string]*testClient{ + as[0][0]: c1, + as[0][1]: c1, + }, + }) + + for from := 0; from < totalSize-1; from++ { + for to := from; to < totalSize; to++ { + t.Run(fmt.Sprintf("from=%d,to=%d", from, to), func(t *testing.T) { + testGetRange(t, svc, addr, uint64(from), uint64(to), payload) + }) + } + } + + }) + t.Run("big", func(t *testing.T) { + const totalSize = 9 + id, objs, link, payload := objectChain(t, idCnr, 3, totalSize) // 3 parts + require.Equal(t, totalSize, len(payload)) + + builder := &testPlacementBuilder{vectors: map[string][][]netmap.NodeInfo{}} + builder.vectors[idCnr.EncodeToString()+"/"+id.EncodeToString()] = ns + builder.vectors[object.AddressOf(link).EncodeToString()] = ns + for i := range objs { + builder.vectors[object.AddressOf(objs[i]).EncodeToString()] = ns + } + + var addr oid.Address + addr.SetContainer(idCnr) + addr.SetObject(id) + + const ( + linkingLast = "splitinfo=last" + linkingChildren = "splitinfo=children" + linkingBoth = "splitinfo=both" + ) + + lastID, _ := objs[len(objs)-1].ID() + linkID, _ := link.ID() + + for _, kind := range []string{linkingLast, linkingChildren, linkingBoth} { + t.Run(kind, func(t *testing.T) { + c1 := newTestClient() + for i := range objs { + c1.addResult(object.AddressOf(objs[i]), objs[i], nil) + } + + c1.addResult(object.AddressOf(link), link, nil) + + si := objectSDK.NewSplitInfo() + switch kind { + case linkingLast: + si.SetLastPart(lastID) + case linkingChildren: + si.SetLink(linkID) + case linkingBoth: + si.SetLastPart(lastID) + si.SetLink(linkID) + } + c1.addResult(addr, nil, objectSDK.NewSplitInfoError(si)) + + svc := newSvc(builder, &testClientCache{ + clients: map[string]*testClient{ + as[0][0]: c1, + as[0][1]: c1, + }, + }) + + for from := 0; from < totalSize-1; from++ { + for to := from; to < totalSize; to++ { + t.Run(fmt.Sprintf("from=%d,to=%d", from, to), func(t *testing.T) { + testGetRange(t, svc, addr, uint64(from), uint64(to), payload) + }) + } + } + }) + } + }) +} + func TestGetFromPastEpoch(t *testing.T) { ctx := context.Background() From 21a490da8f0399ee180b655c367a9b2a8565a0f8 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 7 May 2024 12:44:50 +0300 Subject: [PATCH 0538/1413] [#1112] Fix issue from `gofumpt` Signed-off-by: Anton Nikiforov --- pkg/services/object/get/get_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index be1e96c298..988cd69829 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -65,6 +65,7 @@ type testEpochReceiver uint64 func (e testEpochReceiver) Epoch() (uint64, error) { return uint64(e), nil } + func (e testEpochReceiver) CurrentEpoch() uint64 { return uint64(e) } @@ -1751,7 +1752,6 @@ func TestGetRange(t *testing.T) { }) } } - }) t.Run("big", func(t *testing.T) { const totalSize = 9 From 3e782527b87019795bbc9702dbbdd3b9c8c2f6cf Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 7 May 2024 12:45:13 +0300 Subject: [PATCH 0539/1413] [#1112] node: Add test for `Range` request for EC object Signed-off-by: Anton Nikiforov --- pkg/services/object/get/getrangeec_test.go | 182 +++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 pkg/services/object/get/getrangeec_test.go diff --git a/pkg/services/object/get/getrangeec_test.go b/pkg/services/object/get/getrangeec_test.go new file mode 100644 index 0000000000..b8497d7d11 --- /dev/null +++ b/pkg/services/object/get/getrangeec_test.go @@ -0,0 +1,182 @@ +package getsvc + +import ( + "context" + "crypto/rand" + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + coreContainer "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +type containerStorage struct { + cnt *container.Container +} + +func (cs *containerStorage) Get(cid.ID) (*coreContainer.Container, error) { + coreCnt := coreContainer.Container{ + Value: *cs.cnt, + } + return &coreCnt, nil +} + +func (cs *containerStorage) DeletionInfo(cid.ID) (*coreContainer.DelInfo, error) { + return nil, nil +} + +func TestGetRangeEC(t *testing.T) { + var dataCount uint32 = 3 + var parityCount uint32 = 1 + cnr := container.Container{} + p := netmap.PlacementPolicy{} + p.SetContainerBackupFactor(1) + x := netmap.ReplicaDescriptor{} + x.SetECDataCount(dataCount) + x.SetECParityCount(parityCount) + p.AddReplicas(x) + cnr.SetPlacementPolicy(p) + + var idCnr cid.ID + container.CalculateID(&idCnr, cnr) + + ns, as := testNodeMatrix(t, []int{4}) + + testGetRange := func(t *testing.T, svc *Service, addr oid.Address, from, to uint64, payload []byte) { + w := NewSimpleObjectWriter() + rngPrm := newRngPrm(false, w, from, to-from) + rngPrm.WithAddress(addr) + + err := svc.GetRange(context.Background(), rngPrm) + require.NoError(t, err) + if from == to { + require.Nil(t, w.Object().Payload()) + } else { + require.Equal(t, payload[from:to], w.Object().Payload()) + } + } + + newSvc := func(b *testPlacementBuilder, c *testClientCache) *Service { + const curEpoch = 13 + + return &Service{ + log: test.NewLogger(t), + localStorage: newTestStorage(), + traverserGenerator: &testTraverserGenerator{ + c: cnr, + b: map[uint64]placement.Builder{ + curEpoch: b, + }, + }, + epochSource: testEpochReceiver(curEpoch), + remoteStorageConstructor: c, + keyStore: &testKeyStorage{}, + containerSource: &containerStorage{ + cnt: &cnr, + }, + } + } + const totalSize = 5 + obj, parts := objectECChain(t, &idCnr, &cnr, totalSize, totalSize) + require.Len(t, parts, int(dataCount+parityCount)) + require.Len(t, obj.Payload(), totalSize) + + addr := object.AddressOf(obj) + builder := &testPlacementBuilder{ + vectors: map[string][][]netmap.NodeInfo{ + addr.EncodeToString(): ns, + }, + } + + clients := map[string]*testClient{} + for i, part := range parts { + builder.vectors[object.AddressOf(part).EncodeToString()] = ns + + tc := newTestClient() + + ecInfo := objectSDK.NewECInfo() + + chunk := objectSDK.ECChunk{} + chunk.Total = uint32(len(parts)) + chunk.Index = uint32(i) + id, _ := part.ID() + idv2 := refs.ObjectID{} + id.WriteToV2(&idv2) + chunk.ID = idv2 + + ecInfo.AddChunk(chunk) + errECInfo := objectSDK.NewECInfoError(ecInfo) + + tc.addResult(addr, nil, errECInfo) + tc.addResult(object.AddressOf(part), part, nil) + + clients[as[0][i]] = tc + } + + svc := newSvc(builder, &testClientCache{ + clients: clients, + }) + + for from := 0; from < totalSize-1; from++ { + for to := from; to < totalSize; to++ { + t.Run(fmt.Sprintf("from=%d,to=%d", from, to), func(t *testing.T) { + testGetRange(t, svc, addr, uint64(from), uint64(to), obj.Payload()) + }) + } + } +} + +func objectECChain(t *testing.T, cnrId *cid.ID, cnr *container.Container, singleSize, totalSize uint64) (*objectSDK.Object, []*objectSDK.Object) { + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + tt := new(testTarget) + p := transformer.NewPayloadSizeLimiter(transformer.Params{ + Key: &pk.PrivateKey, + NextTargetInit: func() transformer.ObjectWriter { return tt }, + NetworkState: testEpochReceiver(1), + MaxSize: singleSize, + }) + + payload := make([]byte, totalSize) + _, err = rand.Read(payload) + require.NoError(t, err) + + ver := version.Current() + hdr := objectSDK.New() + hdr.SetContainerID(*cnrId) + hdr.SetType(objectSDK.TypeRegular) + hdr.SetVersion(&ver) + + ctx := context.Background() + require.NoError(t, p.WriteHeader(ctx, hdr)) + + _, err = p.Write(ctx, payload) + require.NoError(t, err) + + _, err = p.Close(ctx) + require.NoError(t, err) + + require.Len(t, tt.objects, 1) + + c, err := erasurecode.NewConstructor(policy.ECDataCount(cnr.PlacementPolicy()), policy.ECParityCount(cnr.PlacementPolicy())) + require.NoError(t, err) + parts, err := c.Split(tt.objects[0], &pk.PrivateKey) + require.NoError(t, err) + + return tt.objects[0], parts +} From fe2c1c926ff890d64de326b1263ea118d187f797 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 7 May 2024 14:23:23 +0300 Subject: [PATCH 0540/1413] [#1112] node: Fix race warning for `GetObjectAndWritePayload` Signed-off-by: Anton Nikiforov --- pkg/services/object/get/assemble.go | 2 +- pkg/services/object/get/assembleec.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index 548e8e45db..3f4a02c027 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -37,6 +37,7 @@ func (r *request) assemble(ctx context.Context) { r.log.Debug(logs.GetTryingToAssembleTheObject) + r.prm.common = r.prm.common.WithLocalOnly(false) assembler := newAssembler(r.address(), r.splitInfo(), r.ctxRange(), r) r.log.Debug(logs.GetAssemblingSplittedObject, @@ -119,7 +120,6 @@ func (r *request) GetObjectAndWritePayload(ctx context.Context, id oid.ID, rng * } p := r.prm - p.common = p.common.WithLocalOnly(false) p.objWriter = w p.rng = rng diff --git a/pkg/services/object/get/assembleec.go b/pkg/services/object/get/assembleec.go index d288ef2497..58641c975a 100644 --- a/pkg/services/object/get/assembleec.go +++ b/pkg/services/object/get/assembleec.go @@ -35,6 +35,7 @@ func (r *request) assembleEC(ctx context.Context) { r.log.Debug(logs.GetTryingToAssembleTheECObject) + r.prm.common = r.prm.common.WithLocalOnly(false) assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.containerSource, r.log) r.log.Debug(logs.GetAssemblingECObject, From 854200a874919f0bfb6dcb20a790091a621f028c Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 7 May 2024 19:11:21 +0300 Subject: [PATCH 0541/1413] [#1115] node: Remove unused const Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/modules/tree/root.go | 3 +- cmd/frostfs-node/config/morph/config.go | 3 +- internal/logs/logs.go | 1088 +++++++++++------------ 3 files changed, 514 insertions(+), 580 deletions(-) diff --git a/cmd/frostfs-cli/modules/tree/root.go b/cmd/frostfs-cli/modules/tree/root.go index 701a78f2a9..efd1c08b52 100644 --- a/cmd/frostfs-cli/modules/tree/root.go +++ b/cmd/frostfs-cli/modules/tree/root.go @@ -40,8 +40,7 @@ const ( metaFlagKey = "meta" - pathFlagKey = "path" - pathAttributeFlagKey = "pattr" + pathFlagKey = "path" latestOnlyFlagKey = "latest" diff --git a/cmd/frostfs-node/config/morph/config.go b/cmd/frostfs-node/config/morph/config.go index a240c5d490..b0c6527db2 100644 --- a/cmd/frostfs-node/config/morph/config.go +++ b/cmd/frostfs-node/config/morph/config.go @@ -10,8 +10,7 @@ import ( ) const ( - subsection = "morph" - notarySubsection = "notary" + subsection = "morph" // DialTimeoutDefault is a default dial timeout of morph chain client connection. DialTimeoutDefault = 5 * time.Second diff --git a/internal/logs/logs.go b/internal/logs/logs.go index e76ab10b6a..4576e2e594 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -17,580 +17,516 @@ const ( ) const ( - InnerringNonalphabetModeDoNotStopContainerEstimations = "non-alphabet mode, do not stop container estimations" - InnerringCantStopEpochEstimation = "can't stop epoch estimation" - InnerringCantMakeNotaryDepositInMainChain = "can't make notary deposit in main chain" - InnerringCantMakeNotaryDepositInSideChain = "can't make notary deposit in side chain" - InnerringNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made" - InnerringCantGetInnerRingIndex = "can't get inner ring index" - InnerringCantGetInnerRingSize = "can't get inner ring size" - InnerringCantGetAlphabetIndex = "can't get alphabet index" - InnerringIgnoreValidatorVoteNodeNotInAlphabetRange = "ignore validator vote: node not in alphabet range" - InnerringIgnoreValidatorVoteEmptyValidatorsList = "ignore validator vote: empty validators list" - InnerringCantInvokeVoteMethodInAlphabetContract = "can't invoke vote method in alphabet contract" - InnerringCantGetLastProcessedMainChainBlockNumber = "can't get last processed main chain block number" - InnerringNotarySupport = "notary support" - InnerringAlphabetKeysSyncIsDisabled = "alphabet keys sync is disabled" - InnerringNoControlServerEndpointSpecified = "no Control server endpoint specified, service is disabled" - InnerringCantGetLastProcessedSideChainBlockNumber = "can't get last processed side chain block number" - InnerringFailedToSetGroupSignerScope = "failed to set group signer scope, continue with Global" - InnerringCantVoteForPreparedValidators = "can't vote for prepared validators" - InnerringNewBlock = "new block" - InnerringCantUpdatePersistentState = "can't update persistent state" - InnerringCloserError = "closer error" - InnerringReadConfigFromBlockchain = "read config from blockchain" - NotificatorNotificatorStartProcessingObjectNotifications = "notificator: start processing object notifications" - NotificatorNotificatorProcessingObjectNotification = "notificator: processing object notification" - PolicerCouldNotGetContainer = "could not get container" - PolicerCouldNotConfirmContainerRemoval = "could not confirm container removal" - PolicerCouldNotInhumeObjectWithMissingContainer = "could not inhume object with missing container" - PolicerCouldNotBuildPlacementVectorForObject = "could not build placement vector for object" - PolicerRedundantLocalObjectCopyDetected = "redundant local object copy detected" - PolicerReceiveObjectHeaderToCheckPolicyCompliance = "receive object header to check policy compliance" - PolicerConsiderNodeUnderMaintenanceAsOK = "consider node under maintenance as OK" - PolicerShortageOfObjectCopiesDetected = "shortage of object copies detected" - PolicerSomeOfTheCopiesAreStoredOnNodesUnderMaintenance = "some of the copies are stored on nodes under maintenance, save local copy" - PolicerRoutineStopped = "routine stopped" - PolicerFailureAtObjectSelectForReplication = "failure at object select for replication" - PolicerPoolSubmission = "pool submission" - PolicerUnableToProcessObj = "unable to process object" - ReplicatorFinishWork = "finish work" - ReplicatorCouldNotGetObjectFromLocalStorage = "could not get object from local storage" - ReplicatorCouldNotReplicateObject = "could not replicate object" - ReplicatorObjectSuccessfullyReplicated = "object successfully replicated" - TreeRedirectingTreeServiceQuery = "redirecting tree service query" - TreeBearerPresentedButNotAllowedByACL = "bearer presented but not allowed by ACL" - TreeCouldNotGetLastSynchronizedHeightForATree = "could not get last synchronized height for a tree" - TreeCouldNotUpdateLastSynchronizedHeightForATree = "could not update last synchronized height for a tree" - TreeSynchronizeTree = "synchronize tree" - TreeFailedToRunTreeSynchronizationOverAllNodes = "failed to run tree synchronization over all nodes" - TreeFailedToRunTreeSynchronizationForSpecificNode = "failed to run tree synchronization for specific node" - TreeFailedToParseAddressForTreeSynchronization = "failed to parse address for tree synchronization" - TreeFailedToConnectForTreeSynchronization = "failed to connect for tree synchronization" - TreeSyncingTrees = "syncing trees..." - TreeCouldNotFetchContainers = "could not fetch containers" - TreeTreesHaveBeenSynchronized = "trees have been synchronized" - TreeSyncingContainerTrees = "syncing container trees..." - TreeCouldNotSyncTrees = "could not sync trees" - TreeContainerTreesHaveBeenSynced = "container trees have been synced" - TreeCouldNotQueryTreesForSynchronization = "could not query trees for synchronization" - TreeRemovingRedundantTrees = "removing redundant trees..." - TreeCouldNotCheckIfContainerExisted = "could not check if the container ever existed" - TreeCouldNotRemoveRedundantTree = "could not remove redundant tree" - TreeCouldNotCalculateContainerNodes = "could not calculate container nodes" - TreeFailedToApplyReplicatedOperation = "failed to apply replicated operation" - TreeDoNotSendUpdateToTheNode = "do not send update to the node" - TreeFailedToSentUpdateToTheNode = "failed to sent update to the node" - TreeErrorDuringReplication = "error during replication" - PersistentCouldNotGetSessionFromPersistentStorage = "could not get session from persistent storage" - PersistentCouldNotDeleteSToken = "could not delete token" - PersistentCouldNotCleanUpExpiredTokens = "could not clean up expired tokens" - ControllerReportIsAlreadyStarted = "report is already started" - TombstoneCouldNotGetTheTombstoneTheSource = "tombstone getter: could not get the tombstone the source" - DeleteNoSplitInfoObjectIsPHY = "no split info, object is PHY" - DeleteAssemblingChain = "assembling chain..." - DeleteCollectingChildren = "collecting children..." - DeleteSupplementBySplitID = "supplement by split ID" - DeleteFormingTombstoneStructure = "forming tombstone structure..." - DeleteTombstoneStructureSuccessfullyFormedSaving = "tombstone structure successfully formed, saving..." - DeleteFormingSplitInfo = "forming split info..." - DeleteSplitInfoSuccessfullyFormedCollectingMembers = "split info successfully formed, collecting members..." - DeleteMembersSuccessfullyCollected = "members successfully collected" - GetRemoteCallFailed = "remote call failed" - GetCanNotAssembleTheObject = "can not assemble the object" - GetTryingToAssembleTheObject = "trying to assemble the object..." - GetTryingToAssembleTheECObject = "trying to assemble the ec object..." - GetAssemblingSplittedObject = "assembling splitted object..." - GetAssemblingECObject = "assembling erasure-coded object..." - GetUnableToGetAllPartsECObject = "unable to get all parts, continue to reconstruct with existed" - GetUnableToGetPartECObject = "unable to get part of the erasure-encoded object" - GetUnableToHeadPartECObject = "unable to head part of the erasure-encoded object" - GetUnableToGetECObjectContainer = "unable to get container for erasure-coded object" - GetAssemblingSplittedObjectCompleted = "assembling splitted object completed" - GetAssemblingECObjectCompleted = "assembling erasure-coded object completed" - GetFailedToAssembleSplittedObject = "failed to assemble splitted object" - GetFailedToAssembleECObject = "failed to assemble erasure-coded object" - GetCouldNotGenerateContainerTraverser = "could not generate container traverser" - GetCouldNotConstructRemoteNodeClient = "could not construct remote node client" - GetCouldNotWriteHeader = "could not write header" - GetCouldNotWritePayloadChunk = "could not write payload chunk" - GetLocalGetFailed = "local get failed" - GetReturnResultDirectly = "return result directly" - GetCompletingTheOperation = "completing the operation" - GetRequestedObjectWasMarkedAsRemoved = "requested object was marked as removed" - GetRequestedObjectIsVirtual = "requested object is virtual" - GetRequestedObjectIsEC = "requested object is erasure-coded" - GetRequestedRangeIsOutOfObjectBounds = "requested range is out of object bounds" - PutAdditionalContainerBroadcastFailure = "additional container broadcast failure" - SearchReturnResultDirectly = "return result directly" - SearchCouldNotConstructRemoteNodeClient = "could not construct remote node client" - SearchRemoteOperationFailed = "remote operation failed" - SearchCouldNotGenerateContainerTraverser = "could not generate container traverser" - SearchCouldNotWriteObjectIdentifiers = "could not write object identifiers" - SearchLocalOperationFailed = "local operation failed" - UtilObjectServiceError = "object service error" - UtilCouldNotPushTaskToWorkerPool = "could not push task to worker pool" - V2CantCheckIfRequestFromInnerRing = "can't check if request from inner ring" - V2CantCheckIfRequestFromContainerNode = "can't check if request from container node" - NatsNatsConnectionWasLost = "nats: connection was lost" - NatsNatsReconnectedToTheServer = "nats: reconnected to the server" - NatsNatsClosingConnectionAsTheContextIsDone = "nats: closing connection as the context is done" - NatsConnectedToEndpoint = "nats: successfully connected to endpoint" - ControllerStartingToAnnounceTheValuesOfTheMetrics = "starting to announce the values of the metrics" - ControllerCouldNotInitializeIteratorOverLocallyCollectedMetrics = "could not initialize iterator over locally collected metrics" - ControllerCouldNotInitializeAnnouncementAccumulator = "could not initialize announcement accumulator" - ControllerIteratorOverLocallyCollectedMetricsAborted = "iterator over locally collected metrics aborted" - ControllerCouldNotFinishWritingLocalAnnouncements = "could not finish writing local announcements" - ControllerTrustAnnouncementSuccessfullyFinished = "trust announcement successfully finished" - ControllerAnnouncementIsAlreadyStarted = "announcement is already started" - ControllerAnnouncementSuccessfullyInterrupted = "announcement successfully interrupted" - ControllerAnnouncementIsNotStartedOrAlreadyInterrupted = "announcement is not started or already interrupted" - ControllerCouldNotInitializeIteratorOverLocallyAccumulatedAnnouncements = "could not initialize iterator over locally accumulated announcements" - ControllerCouldNotInitializeResultTarget = "could not initialize result target" - ControllerIteratorOverLocalAnnouncementsAborted = "iterator over local announcements aborted" - ControllerCouldNotFinishWritingLoadEstimations = "could not finish writing load estimations" - RouteCouldNotInitializeWriterProvider = "could not initialize writer provider" - RouteCouldNotInitializeWriter = "could not initialize writer" - RouteCouldNotPutTheValue = "could not put the value" - RouteCouldNotCloseRemoteServerWriter = "could not close remote server writer" - ClientCouldNotRestoreBlockSubscriptionAfterRPCSwitch = "could not restore block subscription after RPC switch" - ClientCouldNotRestoreNotificationSubscriptionAfterRPCSwitch = "could not restore notification subscription after RPC switch" - ClientCouldNotRestoreNotaryNotificationSubscriptionAfterRPCSwitch = "could not restore notary notification subscription after RPC switch" - ClientCouldNotEstablishConnectionToTheSwitchedRPCNode = "could not establish connection to the switched RPC node" - ClientConnectionToTheNewRPCNodeHasBeenEstablished = "connection to the new RPC node has been established" - ClientSwitchingToTheNextRPCNode = "switching to the next RPC node" - ClientCouldNotEstablishConnectionToAnyRPCNode = "could not establish connection to any RPC node" - ClientCouldNotCreateClientToTheHigherPriorityNode = "could not create client to the higher priority node" - ClientSwitchedToTheHigherPriorityRPC = "switched to the higher priority RPC" - ClientCouldNotRestoreSideChainSubscriptionsUsingNode = "could not restore side chain subscriptions using node" - ClientNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made" - ClientNotaryDepositInvoke = "notary deposit invoke" - ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked" - ClientNotaryRequestInvoked = "notary request invoked" - ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted" - ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted = "attempt to wait for notary deposit transaction to get persisted" - ClientNeoClientInvoke = "neo client invoke" - ClientNativeGasTransferInvoke = "native gas transfer invoke" - ClientBatchGasTransferInvoke = "batch gas transfer invoke" - ClientCantGetBlockchainHeight = "can't get blockchain height" - ClientCantGetBlockchainHeight243 = "can't get blockchain height" - EventCouldNotSubmitHandlerToWorkerPool = "could not Submit handler to worker pool" - EventCouldNotStartListenToEvents = "could not start listen to events" - EventStopEventListenerByError = "stop event listener by error" - EventStopEventListenerByContext = "stop event listener by context" - EventStopEventListenerByNotificationChannel = "stop event listener by notification channel" - EventNilNotificationEventWasCaught = "nil notification event was caught" - EventStopEventListenerByNotaryChannel = "stop event listener by notary channel" - EventNilNotaryEventWasCaught = "nil notary event was caught" - EventStopEventListenerByBlockChannel = "stop event listener by block channel" - EventNilBlockWasCaught = "nil block was caught" - EventListenerWorkerPoolDrained = "listener worker pool drained" - EventEventParserNotSet = "event parser not set" - EventCouldNotParseNotificationEvent = "could not parse notification event" - EventNotificationHandlersForParsedNotificationEventWereNotRegistered = "notification handlers for parsed notification event were not registered" - EventSkipExpiredMainTXNotaryEvent = "skip expired main TX notary event" - EventCouldNotPrepareAndValidateNotaryEvent = "could not prepare and validate notary event" - EventNotaryParserNotSet = "notary parser not set" - EventCouldNotParseNotaryEvent = "could not parse notary event" - EventNotaryHandlersForParsedNotificationEventWereNotRegistered = "notary handlers for parsed notification event were not registered" - EventIgnoreNilEventParser = "ignore nil event parser" - EventListenerHasBeenAlreadyStartedIgnoreParser = "listener has been already started, ignore parser" - EventRegisteredNewEventParser = "registered new event parser" - EventIgnoreNilEventHandler = "ignore nil event handler" - EventIgnoreHandlerOfEventWoParser = "ignore handler of event w/o parser" - EventRegisteredNewEventHandler = "registered new event handler" - EventIgnoreNilNotaryEventParser = "ignore nil notary event parser" - EventListenerHasBeenAlreadyStartedIgnoreNotaryParser = "listener has been already started, ignore notary parser" - EventIgnoreNilNotaryEventHandler = "ignore nil notary event handler" - EventIgnoreHandlerOfNotaryEventWoParser = "ignore handler of notary event w/o parser" - EventIgnoreNilBlockHandler = "ignore nil block handler" - SubscriberRemoteNotificationChannelHasBeenClosed = "remote notification channel has been closed" - SubscriberCantCastNotifyEventValueToTheNotifyStruct = "can't cast notify event value to the notify struct" - SubscriberNewNotificationEventFromSidechain = "new notification event from sidechain" - SubscriberCantCastBlockEventValueToBlock = "can't cast block event value to block" - SubscriberCantCastNotifyEventValueToTheNotaryRequestStruct = "can't cast notify event value to the notary request struct" - SubscriberUnsupportedNotificationFromTheChain = "unsupported notification from the chain" - StorageOperation = "local object storage operation" - BlobovniczaCreatingDirectoryForBoltDB = "creating directory for BoltDB" - BlobovniczaOpeningBoltDB = "opening BoltDB" - BlobovniczaInitializing = "initializing..." - BlobovniczaAlreadyInitialized = "already initialized" - BlobovniczaCreatingBucketForSizeRange = "creating bucket for size range" - BlobovniczaClosingBoltDB = "closing BoltDB" - BlobovniczaObjectWasRemovedFromBucket = "object was removed from bucket" - BlobstorOpening = "opening..." - BlobstorInitializing = "initializing..." - BlobstorClosing = "closing..." - BlobstorCouldntCloseStorage = "couldn't close storage" - BlobstorErrorOccurredDuringObjectExistenceChecking = "error occurred during object existence checking" - BlobstorErrorOccurredDuringTheIteration = "error occurred during the iteration" - EngineShardHasBeenRemoved = "shard has been removed" - EngineCouldNotCloseRemovedShard = "could not close removed shard" - EngineCouldNotOpenShardClosingAndSkipping = "could not open shard, closing and skipping" - EngineCouldNotClosePartiallyInitializedShard = "could not close partially initialized shard" - EngineCouldNotInitializeShardClosingAndSkipping = "could not initialize shard, closing and skipping" - EngineCouldNotCloseShard = "could not close shard" - EngineCouldNotReloadAShard = "could not reload a shard" - EngineAddedNewShard = "added new shard" - EngineCouldNotPutObjectToShard = "could not put object to shard" - EngineErrorDuringSearchingForObjectChildren = "error during searching for object children" - EngineCouldNotInhumeObjectInShard = "could not inhume object in shard" - EngineStartingRemovalOfLocallyredundantCopies = "starting removal of locally-redundant copies" - EngineStartedDuplicatesRemovalRoutine = "started duplicates removal routine" - EngineFinishedRemovalOfLocallyredundantCopies = "finished removal of locally-redundant copies" - EngineRemovingAnObjectWithoutFullLockingCheck = "removing an object without full locking check" - EngineInterruptProcessingTheExpiredLocks = "interrupt processing the expired locks" - EngineInterruptProcessingTheDeletedLocks = "interrupt processing the deleted locks" - EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly = "failed to move shard in degraded-read-only mode, moving to read-only" - EngineFailedToMoveShardInReadonlyMode = "failed to move shard in read-only mode" - EngineShardIsMovedInReadonlyModeDueToErrorThreshold = "shard is moved in read-only mode due to error threshold" - EngineShardIsMovedInDegradedModeDueToErrorThreshold = "shard is moved in degraded mode due to error threshold" - EngineModeChangeIsInProgressIgnoringSetmodeRequest = "mode change is in progress, ignoring set-mode request" - EngineStartedShardsEvacuation = "started shards evacuation" - EngineFinishedSuccessfullyShardsEvacuation = "shards evacuation finished successfully" - EngineFinishedWithErrorShardsEvacuation = "shards evacuation finished with error" - EngineObjectIsMovedToAnotherShard = "object is moved to another shard" - MetabaseMissingMatcher = "missing matcher" - MetabaseErrorInFKBTSelection = "error in FKBT selection" - MetabaseCantDecodeListBucketLeaf = "can't decode list bucket leaf" - MetabaseUnknownOperation = "unknown operation" - MetabaseCantIterateOverTheBucket = "can't iterate over the bucket" - MetabaseCouldNotIterateOverTheBuckets = "could not iterate over the buckets" - MetabaseCreatedDirectoryForMetabase = "created directory for Metabase" - MetabaseOpenedBoltDBInstanceForMetabase = "opened boltDB instance for Metabase" - MetabaseCheckingMetabaseVersion = "checking metabase version" - ShardCantSelectAllObjects = "can't select all objects" - ShardSettingShardMode = "setting shard mode" - ShardShardModeSetSuccessfully = "shard mode set successfully" - ShardCouldNotMarkObjectForShardRelocationInMetabase = "could not mark object for shard relocation in metabase" - ShardCantDeleteObjectFromWriteCache = "can't delete object from write cache" - ShardCantGetStorageIDFromMetabase = "can't get storage ID from metabase" - ShardCantRemoveObjectFromBlobStor = "can't remove object from blobStor" - ShardFetchingObjectWithoutMeta = "fetching object without meta" - ShardObjectIsMissingInWritecache = "object is missing in write-cache" - ShardFailedToFetchObjectFromWritecache = "failed to fetch object from write-cache" - ShardCantPutObjectToTheWritecacheTryingBlobstor = "can't put object to the write-cache, trying blobstor" - ShardMetaObjectCounterRead = "meta: object counter read" - ShardMetaCantReadContainerList = "meta: can't read container list" - ShardMetaCantReadContainerSize = "meta: can't read container size" - ShardMetaInfoPresentButObjectNotFound = "meta info was present, but the object is missing" - ShardMetabaseFailureSwitchingMode = "metabase failure, switching mode" - ShardCantMoveShardToReadonlySwitchMode = "can't move shard to readonly, switch mode" - ShardCouldNotUnmarshalObject = "could not unmarshal object" - ShardCouldNotCloseShardComponent = "could not close shard component" - ShardCantOpenMetabaseMoveToADegradedMode = "can't open metabase, move to a degraded mode" - ShardCantInitializeMetabaseMoveToADegradedreadonlyMode = "can't initialize metabase, move to a degraded-read-only mode" - ShardTryingToRestoreReadwriteMode = "trying to restore read-write mode" - ShardStopEventListenerByClosedEventChannel = "stop event listener by closed `event` channel" - ShardStopEventListenerByClosedStopChannel = "stop event listener by closed `stop` channel" - ShardStopEventListenerByContext = "stop event listener by context" - ShardCouldNotSubmitGCJobToWorkerPool = "could not submit GC job to worker pool" - ShardGCIsStopped = "GC is stopped" - ShardWaitingForGCWorkersToStop = "waiting for GC workers to stop..." - ShardIteratorOverMetabaseGraveyardFailed = "iterator over metabase graveyard failed" - ShardCouldNotDeleteTheObjects = "could not delete the objects" - ShardIteratorOverExpiredObjectsFailed = "iterator over expired objects failed" - ShardCouldNotInhumeTheObjects = "could not inhume the objects" - ShardStartedExpiredTombstonesHandling = "started expired tombstones handling" - ShardIteratingTombstones = "iterating tombstones" - ShardShardIsInADegradedModeSkipCollectingExpiredTombstones = "shard is in a degraded mode, skip collecting expired tombstones" - ShardIteratorOverGraveyardFailed = "iterator over graveyard failed" - ShardHandlingExpiredTombstonesBatch = "handling expired tombstones batch" - ShardFinishedExpiredTombstonesHandling = "finished expired tombstones handling" - ShardIteratorOverExpiredLocksFailed = "iterator over expired locks failed" - ShardCouldNotMarkTombstonesAsGarbage = "could not mark tombstones as garbage" - ShardCouldNotDropExpiredGraveRecords = "could not drop expired grave records" - ShardFailureToUnlockObjects = "failure to unlock objects" - ShardFailureToMarkLockersAsGarbage = "failure to mark lockers as garbage" - ShardFailureToGetExpiredUnlockedObjects = "failure to get expired unlocked objects" - ShardCouldNotMarkObjectToDeleteInMetabase = "could not mark object to delete in metabase" - WritecacheTriedToFlushItemsFromWritecache = "tried to flush items from write-cache" - WritecacheWaitingForChannelsToFlush = "waiting for channels to flush" - WritecacheFillingFlushMarksForObjectsInFSTree = "filling flush marks for objects in FSTree" - WritecacheFinishedUpdatingFSTreeFlushMarks = "finished updating FSTree flush marks" - WritecacheFillingFlushMarksForObjectsInDatabase = "filling flush marks for objects in database" - WritecacheFinishedUpdatingFlushMarks = "finished updating flush marks" - WritecacheCantRemoveObjectsFromTheDatabase = "can't remove objects from the database" - WritecacheCantRemoveObjectFromWritecache = "can't remove object from write-cache" - BlobovniczatreeCouldNotGetObjectFromLevel = "could not get object from level" - BlobovniczatreeCouldNotReadPayloadRangeFromOpenedBlobovnicza = "could not read payload range from opened blobovnicza" - BlobovniczatreeCouldNotReadPayloadRangeFromActiveBlobovnicza = "could not read payload range from active blobovnicza" - BlobovniczatreeCouldNotCloseBlobovnicza = "could not close Blobovnicza" - BlobovniczatreeBlobovniczaSuccessfullyClosedOnEvict = "blobovnicza successfully closed on evict" - BlobovniczatreeUpdatingActiveBlobovnicza = "updating active blobovnicza..." - BlobovniczatreeActiveBlobovniczaSuccessfullyUpdated = "active blobovnicza successfully updated" - BlobovniczatreeBlobovniczaSuccessfullyActivated = "blobovnicza successfully activated" - BlobovniczatreeCouldNotRemoveObjectFromLevel = "could not remove object from level" - BlobovniczatreeCouldNotRemoveObjectFromOpenedBlobovnicza = "could not remove object from opened blobovnicza" - BlobovniczatreeCouldNotRemoveObjectFromActiveBlobovnicza = "could not remove object from active blobovnicza" - BlobovniczatreeCouldNotGetActiveBlobovnicza = "could not get active blobovnicza" - BlobovniczatreeBlobovniczaOverflowed = "blobovnicza overflowed" - BlobovniczatreeCouldNotUpdateActiveBlobovnicza = "could not update active blobovnicza" - BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza = "could not put object to active blobovnicza" - BlobovniczatreeCouldNotReadObjectFromOpenedBlobovnicza = "could not read object from opened blobovnicza" - BlobovniczatreeCouldNotGetObjectFromActiveBlobovnicza = "could not get object from active blobovnicza" - BlobovniczatreeInitializingBlobovniczas = "initializing Blobovnicza's" - BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization = "read-only mode, skip blobovniczas initialization..." - BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing = "blobovnicza successfully initialized, closing..." - BlobovniczatreeCouldNotCloseActiveBlobovnicza = "could not close active blobovnicza" - AlphabetTick = "tick" - AlphabetAlphabetProcessorWorkerPoolDrained = "alphabet processor worker pool drained" - AlphabetNonAlphabetModeIgnoreGasEmissionEvent = "non alphabet mode, ignore gas emission event" - AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent = "node is out of alphabet range, ignore gas emission event" - AlphabetCantInvokeAlphabetEmitMethod = "can't invoke alphabet emit method" - AlphabetStorageNodeEmissionIsOff = "storage node emission is off" - AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes = "can't get netmap snapshot to emit gas to storage nodes" - AlphabetGasEmission = "gas emission" - AlphabetCantParseNodePublicKey = "can't parse node public key" - AlphabetCantTransferGas = "can't transfer gas" - AlphabetCantTransferGasToWallet = "can't transfer gas to wallet" - AlphabetAlphabetWorkerPool = "alphabet worker pool" - BalanceBalanceWorkerPoolDrained = "balance worker pool drained" - BalanceNonAlphabetModeIgnoreBalanceLock = "non alphabet mode, ignore balance lock" - BalanceCantSendLockAssetTx = "can't send lock asset tx" - BalanceBalanceWorkerPool = "balance worker pool" - ContainerContainerWorkerPool = "container worker pool" - ContainerContainerProcessorWorkerPoolDrained = "container processor worker pool drained" - ContainerNonAlphabetModeIgnoreContainerPut = "non alphabet mode, ignore container put" - ContainerPutContainerCheckFailed = "put container check failed" - ContainerCouldNotApprovePutContainer = "could not approve put container" - ContainerNonAlphabetModeIgnoreContainerDelete = "non alphabet mode, ignore container delete" - ContainerDeleteContainerCheckFailed = "delete container check failed" - ContainerCouldNotApproveDeleteContainer = "could not approve delete container" - ContainerNonAlphabetModeIgnoreSetEACL = "non alphabet mode, ignore set EACL" - ContainerSetEACLCheckFailed = "set EACL check failed" - ContainerCouldNotApproveSetEACL = "could not approve set EACL" - FrostFSNonAlphabetModeIgnoreBind = "non alphabet mode, ignore bind" - FrostFSInvalidManageKeyEvent = "invalid manage key event" - FrostFSCouldNotDecodeScriptHashFromBytes = "could not decode script hash from bytes" - FrostFSNonAlphabetModeIgnoreConfig = "non alphabet mode, ignore config" - FrostFSCantRelaySetConfigEvent = "can't relay set config event" - FrostFSFrostfsWorkerPool = "frostfs worker pool" - FrostFSFrostfsProcessorWorkerPoolDrained = "frostfs processor worker pool drained" - FrostFSNonAlphabetModeIgnoreDeposit = "non alphabet mode, ignore deposit" - FrostFSCantTransferAssetsToBalanceContract = "can't transfer assets to balance contract" - FrostFSDoubleMintEmissionDeclined = "double mint emission declined" - FrostFSCantGetGasBalanceOfTheNode = "can't get gas balance of the node" - FrostFSGasBalanceThresholdHasBeenReached = "gas balance threshold has been reached" - FrostFSCantTransferNativeGasToReceiver = "can't transfer native gas to receiver" - FrostFSNonAlphabetModeIgnoreWithdraw = "non alphabet mode, ignore withdraw" - FrostFSCantCreateLockAccount = "can't create lock account" - FrostFSCantLockAssetsForWithdraw = "can't lock assets for withdraw" - FrostFSNonAlphabetModeIgnoreCheque = "non alphabet mode, ignore cheque" - FrostFSCantTransferAssetsToFedContract = "can't transfer assets to fed contract" - GovernanceNewEvent = "new event" - GovernanceGovernanceWorkerPoolDrained = "governance worker pool drained" - GovernanceNonAlphabetModeIgnoreAlphabetSync = "non alphabet mode, ignore alphabet sync" - GovernanceCantFetchAlphabetListFromMainNet = "can't fetch alphabet list from main net" - GovernanceCantFetchAlphabetListFromSideChain = "can't fetch alphabet list from side chain" - GovernanceCantMergeAlphabetListsFromMainNetAndSideChain = "can't merge alphabet lists from main net and side chain" - GovernanceNoGovernanceUpdateAlphabetListHasNotBeenChanged = "no governance update, alphabet list has not been changed" - GovernanceAlphabetListHasBeenChangedStartingUpdate = "alphabet list has been changed, starting update" - GovernanceCantVoteForSideChainCommittee = "can't vote for side chain committee" - GovernanceFinishedAlphabetListUpdate = "finished alphabet list update" - GovernanceCantFetchInnerRingListFromSideChain = "can't fetch inner ring list from side chain" - GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys = "can't create new inner ring list with new alphabet keys" - GovernanceUpdateOfTheInnerRingList = "update of the inner ring list" - GovernanceCantUpdateInnerRingListWithNewAlphabetKeys = "can't update inner ring list with new alphabet keys" - GovernanceCantUpdateListOfNotaryNodesInSideChain = "can't update list of notary nodes in side chain" - GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract = "can't update list of alphabet nodes in frostfs contract" - NetmapNetmapWorkerPool = "netmap worker pool" - NetmapTick = "tick" - NetmapNetmapWorkerPoolDrained = "netmap worker pool drained" - NetmapNetmapCleanUpRoutineIsDisabled518 = "netmap clean up routine is disabled" - NetmapNonAlphabetModeIgnoreNewNetmapCleanupTick = "non alphabet mode, ignore new netmap cleanup tick" - NetmapCantDecodePublicKeyOfNetmapNode = "can't decode public key of netmap node" - NetmapVoteToRemoveNodeFromNetmap = "vote to remove node from netmap" - NetmapCantInvokeNetmapUpdateState = "can't invoke netmap.UpdateState" - NetmapCantIterateOnNetmapCleanerCache = "can't iterate on netmap cleaner cache" - NetmapCantGetEpochDuration = "can't get epoch duration" - NetmapCantGetTransactionHeight = "can't get transaction height" - NetmapCantResetEpochTimer = "can't reset epoch timer" - NetmapCantGetNetmapSnapshotToPerformCleanup = "can't get netmap snapshot to perform cleanup" - NetmapCantStartContainerSizeEstimation = "can't start container size estimation" - NetmapNonAlphabetModeIgnoreNewEpochTick = "non alphabet mode, ignore new epoch tick" - NetmapNextEpoch = "next epoch" - NetmapCantInvokeNetmapNewEpoch = "can't invoke netmap.NewEpoch" - NetmapNonAlphabetModeIgnoreNewPeerNotification = "non alphabet mode, ignore new peer notification" - NetmapNonhaltNotaryTransaction = "non-halt notary transaction" - NetmapCantParseNetworkMapCandidate = "can't parse network map candidate" - NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate = "could not verify and update information about network map candidate" - NetmapApprovingNetworkMapCandidate = "approving network map candidate" - NetmapCantInvokeNetmapAddPeer = "can't invoke netmap.AddPeer" - NetmapNonAlphabetModeIgnoreUpdatePeerNotification = "non alphabet mode, ignore update peer notification" - NetmapPreventSwitchingNodeToMaintenanceState = "prevent switching node to maintenance state" - NetmapCantInvokeNetmapUpdatePeer = "can't invoke netmap.UpdatePeer" - FrostFSIRInternalError = "internal error" - FrostFSIRCouldNotShutdownHTTPServer = "could not shutdown HTTP server" - FrostFSIRApplicationStopped = "application stopped" - FrostFSIRCouldntCreateRPCClientForEndpoint = "could not create RPC client for endpoint" - FrostFSIRCreatedRPCClientForEndpoint = "created RPC client for endpoint" - FrostFSIRReloadExtraWallets = "reload extra wallets" - FrostFSNodeStartListeningEndpoint = "start listening endpoint" - FrostFSNodeCouldNotReadCertificateFromFile = "could not read certificate from file" - FrostFSNodeCantListenGRPCEndpoint = "can't listen gRPC endpoint" - FrostFSNodeStopListeningGRPCEndpoint = "stop listening gRPC endpoint" - FrostFSNodeStoppingGRPCServer = "stopping gRPC server..." - FrostFSNodeGRPCCannotShutdownGracefullyForcingStop = "gRPC cannot shutdown gracefully, forcing stop" - FrostFSNodeGRPCServerStoppedSuccessfully = "gRPC server stopped successfully" - FrostFSNodeGRPCServerError = "gRPC server error" - FrostFSNodeGRPCReconnecting = "reconnecting gRPC server..." - FrostFSNodeGRPCReconnectedSuccessfully = "gRPC server reconnected successfully" - FrostFSNodeGRPCServerConfigNotFound = "gRPC server config not found" - FrostFSNodeGRPCReconnectFailed = "failed to reconnect gRPC server" - FrostFSNodeWaitingForAllProcessesToStop = "waiting for all processes to stop" - FrostFSNodeStartedLocalNodesMaintenance = "started local node's maintenance" - FrostFSNodeStoppedLocalNodesMaintenance = "stopped local node's maintenance" - FrostFSNodeFailedToAttachShardToEngine = "failed to attach shard to engine" - FrostFSNodeShardAttachedToEngine = "shard attached to engine" - FrostFSNodeClosingComponentsOfTheStorageEngine = "closing components of the storage engine..." - FrostFSNodeAccessPolicyEngineClosingFailure = "ape closing failure" - FrostFSNodeStorageEngineClosingFailure = "storage engine closing failure" - FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed = "persistent rule storage db path is not set: in-memory will be used" - FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully = "all components of the storage engine closed successfully" - FrostFSNodeBootstrappingWithTheMaintenanceState = "bootstrapping with the maintenance state" - FrostFSNodeBootstrappingWithOnlineState = "bootstrapping with online state" - FrostFSNodeTerminationSignalHasBeenReceivedStopping = "termination signal has been received, stopping..." - FrostFSNodeTerminationSignalProcessingIsComplete = "termination signal processing is complete" - FrostFSNodeInternalApplicationError = "internal application error" - FrostFSNodeInternalErrorProcessingIsComplete = "internal error processing is complete" - FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration = "SIGHUP has been received, rereading configuration..." - FrostFSNodeSIGHUPSkip = "node not ready for reconfiguration, skipped SIGHUP" - FrostFSNodeShutdownSkip = "node already is going to shutting down, skipped shutdown" - FrostFSNodeShutdownWhenNotReady = "node is going to shutting down when subsystems still initializing" - FrostFSNodeConfigurationReading = "configuration reading" - FrostFSNodeLoggerConfigurationPreparation = "logger configuration preparation" - FrostFSNodeTracingConfigationUpdated = "tracing configation updated" - FrostFSNodeStorageEngineConfigurationUpdate = "storage engine configuration update" - FrostFSNodePoolConfigurationUpdate = "adjust pool configuration" - FrostFSNodeUpdatedConfigurationApplying = "updated configuration applying" - FrostFSNodeConfigurationHasBeenReloadedSuccessfully = "configuration has been reloaded successfully" - FrostFSNodeReadNewlyCreatedContainerAfterTheNotification = "read newly created container after the notification" - FrostFSNodeContainerCreationEventsReceipt = "container creation event's receipt" - FrostFSNodeContainerRemovalEventsReceipt = "container removal event's receipt" - FrostFSNodeSaveUsedSpaceAnnouncementInContract = "save used space announcement in contract" - FrostFSNodeFailedToCalculateContainerSizeInStorageEngine = "failed to calculate container size in storage engine" - FrostFSNodeContainerSizeInStorageEngineCalculatedSuccessfully = "container size in storage engine calculated successfully" - FrostFSNodeNotificatorCouldNotListContainers = "notificator: could not list containers" - FrostFSNodeNotificatorCouldNotSelectObjectsFromContainer = "notificator: could not select objects from container" - FrostFSNodeNotificatorCouldNotProcessObject = "notificator: could not process object" - FrostFSNodeNotificatorFinishedProcessingObjectNotifications = "notificator: finished processing object notifications" - FrostFSNodeCouldNotWriteObjectNotification = "could not write object notification" - FrostFSNodeCouldNotGetMaxObjectSizeValue = "could not get max object size value" - FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage = "could not inhume mark redundant copy as garbage" - FrostFSNodeFailedInitTracing = "failed init tracing" - FrostFSNodeFailedShutdownTracing = "failed shutdown tracing" - FrostFSNodeFailedToCreateNeoRPCClient = "failed to create neo RPC client" - FrostFSNodeClosingMorphComponents = "closing morph components..." - FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal = "failed to set group signer scope, continue with Global" - FrostFSNodeNotarySupport = "notary support" - FrostFSNodeMorphcacheTTLFetchedFromNetwork = "morph.cache_ttl fetched from network" - FrostFSNodeNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made" - FrostFSNodeCantGetLastProcessedSideChainBlockNumber = "can't get last processed side chain block number" - FrostFSNodeNewEpochEventFromSidechain = "new epoch event from sidechain" - FrostFSNodeNewBlock = "new block" - FrostFSNodeCantUpdatePersistentState = "can't update persistent state" - FrostFSNodeCantSendRebootstrapTx = "can't send re-bootstrap tx" - FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch = "could not update node state on new epoch" - FrostFSNodeCouldNotMakeNotaryDeposit = "could not make notary deposit" - FrostFSNodeInitialNetworkState = "initial network state" - FrostFSNodeTreeServiceIsNotEnabledSkipInitialization = "tree service is not enabled, skip initialization" - FrostFSNodeCouldNotSynchronizeTreeService = "could not synchronize Tree Service" - FrostFSNodeRemovingAllTreesForContainer = "removing all trees for container" - FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved = "container removal event received, but trees weren't removed" - FrostFSNodeCantListenGRPCEndpointControl = "can't listen gRPC endpoint (control)" - FrostFSNodePolicerIsDisabled = "policer is disabled" - CommonApplicationStarted = "application started" - ShardGCCollectingExpiredObjectsStarted = "collecting expired objects started" - ShardGCCollectingExpiredObjectsCompleted = "collecting expired objects completed" - ShardGCCollectingExpiredLocksStarted = "collecting expired locks started" - ShardGCCollectingExpiredLocksCompleted = "collecting expired locks completed" - ShardGCRemoveGarbageStarted = "garbage remove started" - ShardGCRemoveGarbageCompleted = "garbage remove completed" - EngineShardsEvacuationFailedToCount = "failed to get total objects count to evacuate" - EngineShardsEvacuationFailedToListObjects = "failed to list objects to evacuate" - EngineShardsEvacuationFailedToReadObject = "failed to read object to evacuate" - EngineShardsEvacuationFailedToMoveObject = "failed to evacuate object to other node" - ShardGCFailedToGetExpiredWithLinked = "failed to get expired objects with linked" - ShardDeleteCantDeleteFromWriteCache = "can't delete object from write cache" - FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap = "the node is under maintenance, skip initial bootstrap" - EngineCouldNotChangeShardModeToDisabled = "could not change shard mode to disabled" - NetmapNodeAlreadyInCandidateListOnlineSkipInitialBootstrap = "the node is already in candidate list with online state, skip initial bootstrap" - RPConnectionLost = "RPC connection lost, attempting reconnect" - RPCNodeSwitchFailure = "can't switch RPC node" - FSTreeCantReadFile = "can't read a file" - FSTreeCantUnmarshalObject = "can't unmarshal an object" - FSTreeCantFushObjectBlobstor = "can't flush an object to blobstor" - FSTreeCantUpdateID = "can't update object storage ID" - FSTreeCantDecodeDBObjectAddress = "can't decode object address from the DB" - PutSingleRedirectFailure = "failed to redirect PutSingle request" - StorageIDRetrievalFailure = "can't get storage ID from metabase" - ObjectRemovalFailureBlobStor = "can't remove object from blobStor" - CandidateStatusPriority = "candidate status is different from the netmap status, the former takes priority" - TombstoneExpirationParseFailure = "tombstone getter: could not parse tombstone expiration epoch" - FrostFSNodeCantUpdateObjectStorageID = "can't update object storage ID" - FrostFSNodeCantFlushObjectToBlobstor = "can't flush an object to blobstor" - FrostFSNodeCantDecodeObjectAddressFromDB = "can't decode object address from the DB" - FrostFSNodeCantUnmarshalObjectFromDB = "can't unmarshal an object from the DB" - RuntimeSoftMemoryLimitUpdated = "soft runtime memory limit value updated" - RuntimeSoftMemoryDefinedWithGOMEMLIMIT = "soft runtime memory defined with GOMEMLIMIT environment variable, config value skipped" - FailedToCountWritecacheItems = "failed to count writecache items" - AttemtToCloseAlreadyClosedBlobovnicza = "attempt to close an already closed blobovnicza" - FailedToGetContainerCounters = "failed to get container counters values" - FailedToRebuildBlobstore = "failed to rebuild blobstore" - BlobstoreRebuildStarted = "blobstore rebuild started" - BlobstoreRebuildCompletedSuccessfully = "blobstore rebuild completed successfully" - BlobstoreRebuildStopped = "blobstore rebuild stopped" - BlobovniczaTreeFixingFileExtensions = "fixing blobovnicza tree file extensions..." - BlobovniczaTreeFixingFileExtensionsCompletedSuccessfully = "fixing blobovnicza tree file extensions completed successfully" - BlobovniczaTreeFixingFileExtensionsFailed = "failed to fix blobovnicza tree file extensions" - BlobovniczaTreeFixingFileExtensionForFile = "fixing blobovnicza file extension..." - BlobovniczaTreeFixingFileExtensionCompletedSuccessfully = "fixing blobovnicza file extension completed successfully" - BlobovniczaTreeFixingFileExtensionFailed = "failed to fix blobovnicza file extension" - BlobstorRebuildFailedToRebuildStorages = "failed to rebuild storages" - BlobstorRebuildRebuildStoragesCompleted = "storages rebuild completed" - BlobovniczaTreeCollectingDBToRebuild = "collecting blobovniczas to rebuild..." - BlobovniczaTreeCollectingDBToRebuildFailed = "collecting blobovniczas to rebuild failed" - BlobovniczaTreeCollectingDBToRebuildSuccess = "collecting blobovniczas to rebuild completed successfully" - BlobovniczaTreeRebuildingBlobovnicza = "rebuilding blobovnicza..." - BlobovniczaTreeRebuildingBlobovniczaFailed = "rebuilding blobovnicza failed" - BlobovniczaTreeRebuildingBlobovniczaSuccess = "rebuilding blobovnicza completed successfully" - BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza = "could not put move info to source blobovnicza" - BlobovniczatreeCouldNotUpdateStorageID = "could not update storage ID" - BlobovniczatreeCouldNotDropMoveInfo = "could not drop move info from source blobovnicza" - BlobovniczatreeCouldNotDeleteFromSource = "could not delete object from source blobovnicza" - BlobovniczaTreeCompletingPreviousRebuild = "completing previous rebuild if failed..." - BlobovniczaTreeCompletedPreviousRebuildSuccess = "previous rebuild completed successfully" - BlobovniczaTreeCompletedPreviousRebuildFailed = "failed to complete previous rebuild" - BlobovniczatreeCouldNotCheckExistenceInSourceDB = "could not check object existence in source blobovnicza" - BlobovniczatreeCouldNotCheckExistenceInTargetDB = "could not check object existence in target blobovnicza" - BlobovniczatreeCouldNotGetObjectFromSourceDB = "could not get object from source blobovnicza" - BlobovniczatreeCouldNotPutObjectToTargetDB = "could not put object to target blobovnicza" - BlobovniczaSavingCountersToMeta = "saving counters to blobovnicza's meta..." - BlobovniczaSavingCountersToMetaSuccess = "saving counters to blobovnicza's meta completed successfully" - BlobovniczaSavingCountersToMetaFailed = "saving counters to blobovnicza's meta failed" - ObjectRemovalFailureExistsInWritecache = "can't remove object: object must be flushed from writecache" - FailedToReportStatusToSystemd = "failed to report status to systemd" - ShardGCCollectingExpiredMetricsStarted = "collecting expired metrics started" - ShardGCCollectingExpiredMetricsCompleted = "collecting expired metrics completed" - ShardGCFailedToCollectZeroSizeContainers = "failed to collect zero-size containers" - ShardGCFailedToCollectZeroCountContainers = "failed to collect zero-count containers" - EngineFailedToCheckContainerAvailability = "failed to check container availability" - EngineFailedToGetContainerSize = "failed to get container size" - EngineFailedToDeleteContainerSize = "failed to delete container size" - EngineInterruptProcessingZeroSizeContainers = "interrupt processing zero-size containers" - EngineInterruptProcessingZeroCountContainers = "interrupt processing zero-count containers" - EngineFailedToGetContainerCounters = "failed to get container counters" - GetSvcV2FailedToParseNodeEndpoints = "failed to parse node endpoints" - GetSvcV2FailedToParseNodeExternalAddresses = "failed to parse node external addresses" - GetSvcV2FailedToGetRangeHashFromNode = "failed to get range hash from node" - GetSvcV2FailedToGetRangeHashFromAllOfContainerNodes = "failed to get range hash from all of container nodes" - FailedToUpdateShardID = "failed to update shard id" - EngineShardsEvacuationFailedToMoveTree = "failed to evacuate tree to other node" - EngineShardsEvacuationTreeEvacuatedLocal = "tree evacuated to local node" - EngineShardsEvacuationTreeEvacuatedRemote = "tree evacuated to other node" - EngineRefillFailedToGetObjectsCount = "failed to get blobstor objects count, no resync percent estimation is available" - BlobstoreFailedToGetFileinfo = "failed to get file info" - ECFailedToSendToContainerNode = "failed to send EC object to container node" - ECFailedToSaveECPart = "failed to save EC part" + InnerringNonalphabetModeDoNotStopContainerEstimations = "non-alphabet mode, do not stop container estimations" + InnerringCantStopEpochEstimation = "can't stop epoch estimation" + InnerringCantMakeNotaryDepositInMainChain = "can't make notary deposit in main chain" + InnerringCantMakeNotaryDepositInSideChain = "can't make notary deposit in side chain" + InnerringNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made" + InnerringCantGetInnerRingIndex = "can't get inner ring index" + InnerringCantGetInnerRingSize = "can't get inner ring size" + InnerringCantGetAlphabetIndex = "can't get alphabet index" + InnerringIgnoreValidatorVoteNodeNotInAlphabetRange = "ignore validator vote: node not in alphabet range" + InnerringIgnoreValidatorVoteEmptyValidatorsList = "ignore validator vote: empty validators list" + InnerringCantInvokeVoteMethodInAlphabetContract = "can't invoke vote method in alphabet contract" + InnerringCantGetLastProcessedMainChainBlockNumber = "can't get last processed main chain block number" + InnerringNotarySupport = "notary support" + InnerringAlphabetKeysSyncIsDisabled = "alphabet keys sync is disabled" + InnerringNoControlServerEndpointSpecified = "no Control server endpoint specified, service is disabled" + InnerringCantGetLastProcessedSideChainBlockNumber = "can't get last processed side chain block number" + InnerringFailedToSetGroupSignerScope = "failed to set group signer scope, continue with Global" + InnerringCantVoteForPreparedValidators = "can't vote for prepared validators" + InnerringNewBlock = "new block" + InnerringCantUpdatePersistentState = "can't update persistent state" + InnerringCloserError = "closer error" + InnerringReadConfigFromBlockchain = "read config from blockchain" + NotificatorNotificatorStartProcessingObjectNotifications = "notificator: start processing object notifications" + NotificatorNotificatorProcessingObjectNotification = "notificator: processing object notification" + PolicerCouldNotGetContainer = "could not get container" + PolicerCouldNotConfirmContainerRemoval = "could not confirm container removal" + PolicerCouldNotInhumeObjectWithMissingContainer = "could not inhume object with missing container" + PolicerCouldNotBuildPlacementVectorForObject = "could not build placement vector for object" + PolicerRedundantLocalObjectCopyDetected = "redundant local object copy detected" + PolicerReceiveObjectHeaderToCheckPolicyCompliance = "receive object header to check policy compliance" + PolicerConsiderNodeUnderMaintenanceAsOK = "consider node under maintenance as OK" + PolicerShortageOfObjectCopiesDetected = "shortage of object copies detected" + PolicerSomeOfTheCopiesAreStoredOnNodesUnderMaintenance = "some of the copies are stored on nodes under maintenance, save local copy" + PolicerRoutineStopped = "routine stopped" + PolicerFailureAtObjectSelectForReplication = "failure at object select for replication" + PolicerPoolSubmission = "pool submission" + PolicerUnableToProcessObj = "unable to process object" + ReplicatorFinishWork = "finish work" + ReplicatorCouldNotGetObjectFromLocalStorage = "could not get object from local storage" + ReplicatorCouldNotReplicateObject = "could not replicate object" + ReplicatorObjectSuccessfullyReplicated = "object successfully replicated" + TreeRedirectingTreeServiceQuery = "redirecting tree service query" + TreeBearerPresentedButNotAllowedByACL = "bearer presented but not allowed by ACL" + TreeCouldNotGetLastSynchronizedHeightForATree = "could not get last synchronized height for a tree" + TreeCouldNotUpdateLastSynchronizedHeightForATree = "could not update last synchronized height for a tree" + TreeSynchronizeTree = "synchronize tree" + TreeFailedToRunTreeSynchronizationOverAllNodes = "failed to run tree synchronization over all nodes" + TreeFailedToRunTreeSynchronizationForSpecificNode = "failed to run tree synchronization for specific node" + TreeFailedToParseAddressForTreeSynchronization = "failed to parse address for tree synchronization" + TreeFailedToConnectForTreeSynchronization = "failed to connect for tree synchronization" + TreeSyncingTrees = "syncing trees..." + TreeCouldNotFetchContainers = "could not fetch containers" + TreeTreesHaveBeenSynchronized = "trees have been synchronized" + TreeSyncingContainerTrees = "syncing container trees..." + TreeCouldNotSyncTrees = "could not sync trees" + TreeContainerTreesHaveBeenSynced = "container trees have been synced" + TreeCouldNotQueryTreesForSynchronization = "could not query trees for synchronization" + TreeRemovingRedundantTrees = "removing redundant trees..." + TreeCouldNotCheckIfContainerExisted = "could not check if the container ever existed" + TreeCouldNotRemoveRedundantTree = "could not remove redundant tree" + TreeCouldNotCalculateContainerNodes = "could not calculate container nodes" + TreeFailedToApplyReplicatedOperation = "failed to apply replicated operation" + TreeDoNotSendUpdateToTheNode = "do not send update to the node" + TreeFailedToSentUpdateToTheNode = "failed to sent update to the node" + TreeErrorDuringReplication = "error during replication" + PersistentCouldNotGetSessionFromPersistentStorage = "could not get session from persistent storage" + PersistentCouldNotDeleteSToken = "could not delete token" + PersistentCouldNotCleanUpExpiredTokens = "could not clean up expired tokens" + TombstoneCouldNotGetTheTombstoneTheSource = "tombstone getter: could not get the tombstone the source" + DeleteNoSplitInfoObjectIsPHY = "no split info, object is PHY" + DeleteAssemblingChain = "assembling chain..." + DeleteCollectingChildren = "collecting children..." + DeleteSupplementBySplitID = "supplement by split ID" + DeleteFormingTombstoneStructure = "forming tombstone structure..." + DeleteTombstoneStructureSuccessfullyFormedSaving = "tombstone structure successfully formed, saving..." + DeleteFormingSplitInfo = "forming split info..." + DeleteSplitInfoSuccessfullyFormedCollectingMembers = "split info successfully formed, collecting members..." + DeleteMembersSuccessfullyCollected = "members successfully collected" + GetRemoteCallFailed = "remote call failed" + GetCanNotAssembleTheObject = "can not assemble the object" + GetTryingToAssembleTheObject = "trying to assemble the object..." + GetTryingToAssembleTheECObject = "trying to assemble the ec object..." + GetAssemblingSplittedObject = "assembling splitted object..." + GetAssemblingECObject = "assembling erasure-coded object..." + GetUnableToGetAllPartsECObject = "unable to get all parts, continue to reconstruct with existed" + GetUnableToGetPartECObject = "unable to get part of the erasure-encoded object" + GetUnableToHeadPartECObject = "unable to head part of the erasure-encoded object" + GetUnableToGetECObjectContainer = "unable to get container for erasure-coded object" + GetAssemblingSplittedObjectCompleted = "assembling splitted object completed" + GetAssemblingECObjectCompleted = "assembling erasure-coded object completed" + GetFailedToAssembleSplittedObject = "failed to assemble splitted object" + GetFailedToAssembleECObject = "failed to assemble erasure-coded object" + GetCouldNotGenerateContainerTraverser = "could not generate container traverser" + GetCouldNotConstructRemoteNodeClient = "could not construct remote node client" + GetCouldNotWriteHeader = "could not write header" + GetCouldNotWritePayloadChunk = "could not write payload chunk" + GetLocalGetFailed = "local get failed" + GetReturnResultDirectly = "return result directly" + GetCompletingTheOperation = "completing the operation" + GetRequestedObjectWasMarkedAsRemoved = "requested object was marked as removed" + GetRequestedObjectIsVirtual = "requested object is virtual" + GetRequestedObjectIsEC = "requested object is erasure-coded" + GetRequestedRangeIsOutOfObjectBounds = "requested range is out of object bounds" + PutAdditionalContainerBroadcastFailure = "additional container broadcast failure" + SearchReturnResultDirectly = "return result directly" + SearchCouldNotConstructRemoteNodeClient = "could not construct remote node client" + SearchRemoteOperationFailed = "remote operation failed" + SearchCouldNotGenerateContainerTraverser = "could not generate container traverser" + SearchCouldNotWriteObjectIdentifiers = "could not write object identifiers" + SearchLocalOperationFailed = "local operation failed" + UtilObjectServiceError = "object service error" + UtilCouldNotPushTaskToWorkerPool = "could not push task to worker pool" + V2CantCheckIfRequestFromInnerRing = "can't check if request from inner ring" + V2CantCheckIfRequestFromContainerNode = "can't check if request from container node" + NatsNatsConnectionWasLost = "nats: connection was lost" + NatsNatsReconnectedToTheServer = "nats: reconnected to the server" + NatsNatsClosingConnectionAsTheContextIsDone = "nats: closing connection as the context is done" + NatsConnectedToEndpoint = "nats: successfully connected to endpoint" + ClientCouldNotRestoreBlockSubscriptionAfterRPCSwitch = "could not restore block subscription after RPC switch" + ClientCouldNotRestoreNotificationSubscriptionAfterRPCSwitch = "could not restore notification subscription after RPC switch" + ClientCouldNotRestoreNotaryNotificationSubscriptionAfterRPCSwitch = "could not restore notary notification subscription after RPC switch" + ClientCouldNotEstablishConnectionToTheSwitchedRPCNode = "could not establish connection to the switched RPC node" + ClientConnectionToTheNewRPCNodeHasBeenEstablished = "connection to the new RPC node has been established" + ClientCouldNotCreateClientToTheHigherPriorityNode = "could not create client to the higher priority node" + ClientSwitchedToTheHigherPriorityRPC = "switched to the higher priority RPC" + ClientNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made" + ClientNotaryDepositInvoke = "notary deposit invoke" + ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked" + ClientNotaryRequestInvoked = "notary request invoked" + ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted" + ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted = "attempt to wait for notary deposit transaction to get persisted" + ClientNeoClientInvoke = "neo client invoke" + ClientNativeGasTransferInvoke = "native gas transfer invoke" + ClientBatchGasTransferInvoke = "batch gas transfer invoke" + ClientCantGetBlockchainHeight = "can't get blockchain height" + ClientCantGetBlockchainHeight243 = "can't get blockchain height" + EventCouldNotSubmitHandlerToWorkerPool = "could not Submit handler to worker pool" + EventCouldNotStartListenToEvents = "could not start listen to events" + EventStopEventListenerByError = "stop event listener by error" + EventStopEventListenerByContext = "stop event listener by context" + EventStopEventListenerByNotificationChannel = "stop event listener by notification channel" + EventNilNotificationEventWasCaught = "nil notification event was caught" + EventStopEventListenerByNotaryChannel = "stop event listener by notary channel" + EventNilNotaryEventWasCaught = "nil notary event was caught" + EventStopEventListenerByBlockChannel = "stop event listener by block channel" + EventNilBlockWasCaught = "nil block was caught" + EventListenerWorkerPoolDrained = "listener worker pool drained" + EventEventParserNotSet = "event parser not set" + EventCouldNotParseNotificationEvent = "could not parse notification event" + EventNotificationHandlersForParsedNotificationEventWereNotRegistered = "notification handlers for parsed notification event were not registered" + EventSkipExpiredMainTXNotaryEvent = "skip expired main TX notary event" + EventCouldNotPrepareAndValidateNotaryEvent = "could not prepare and validate notary event" + EventNotaryParserNotSet = "notary parser not set" + EventCouldNotParseNotaryEvent = "could not parse notary event" + EventNotaryHandlersForParsedNotificationEventWereNotRegistered = "notary handlers for parsed notification event were not registered" + EventIgnoreNilEventParser = "ignore nil event parser" + EventListenerHasBeenAlreadyStartedIgnoreParser = "listener has been already started, ignore parser" + EventRegisteredNewEventParser = "registered new event parser" + EventIgnoreNilEventHandler = "ignore nil event handler" + EventIgnoreHandlerOfEventWoParser = "ignore handler of event w/o parser" + EventRegisteredNewEventHandler = "registered new event handler" + EventIgnoreNilNotaryEventParser = "ignore nil notary event parser" + EventListenerHasBeenAlreadyStartedIgnoreNotaryParser = "listener has been already started, ignore notary parser" + EventIgnoreNilNotaryEventHandler = "ignore nil notary event handler" + EventIgnoreHandlerOfNotaryEventWoParser = "ignore handler of notary event w/o parser" + EventIgnoreNilBlockHandler = "ignore nil block handler" + StorageOperation = "local object storage operation" + BlobovniczaCreatingDirectoryForBoltDB = "creating directory for BoltDB" + BlobovniczaOpeningBoltDB = "opening BoltDB" + BlobovniczaInitializing = "initializing..." + BlobovniczaAlreadyInitialized = "already initialized" + BlobovniczaCreatingBucketForSizeRange = "creating bucket for size range" + BlobovniczaClosingBoltDB = "closing BoltDB" + BlobovniczaObjectWasRemovedFromBucket = "object was removed from bucket" + BlobstorOpening = "opening..." + BlobstorInitializing = "initializing..." + BlobstorClosing = "closing..." + BlobstorCouldntCloseStorage = "couldn't close storage" + BlobstorErrorOccurredDuringObjectExistenceChecking = "error occurred during object existence checking" + BlobstorErrorOccurredDuringTheIteration = "error occurred during the iteration" + EngineShardHasBeenRemoved = "shard has been removed" + EngineCouldNotCloseRemovedShard = "could not close removed shard" + EngineCouldNotOpenShardClosingAndSkipping = "could not open shard, closing and skipping" + EngineCouldNotClosePartiallyInitializedShard = "could not close partially initialized shard" + EngineCouldNotInitializeShardClosingAndSkipping = "could not initialize shard, closing and skipping" + EngineCouldNotCloseShard = "could not close shard" + EngineCouldNotReloadAShard = "could not reload a shard" + EngineAddedNewShard = "added new shard" + EngineCouldNotPutObjectToShard = "could not put object to shard" + EngineErrorDuringSearchingForObjectChildren = "error during searching for object children" + EngineCouldNotInhumeObjectInShard = "could not inhume object in shard" + EngineStartingRemovalOfLocallyredundantCopies = "starting removal of locally-redundant copies" + EngineStartedDuplicatesRemovalRoutine = "started duplicates removal routine" + EngineFinishedRemovalOfLocallyredundantCopies = "finished removal of locally-redundant copies" + EngineRemovingAnObjectWithoutFullLockingCheck = "removing an object without full locking check" + EngineInterruptProcessingTheExpiredLocks = "interrupt processing the expired locks" + EngineInterruptProcessingTheDeletedLocks = "interrupt processing the deleted locks" + EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly = "failed to move shard in degraded-read-only mode, moving to read-only" + EngineFailedToMoveShardInReadonlyMode = "failed to move shard in read-only mode" + EngineShardIsMovedInReadonlyModeDueToErrorThreshold = "shard is moved in read-only mode due to error threshold" + EngineShardIsMovedInDegradedModeDueToErrorThreshold = "shard is moved in degraded mode due to error threshold" + EngineModeChangeIsInProgressIgnoringSetmodeRequest = "mode change is in progress, ignoring set-mode request" + EngineStartedShardsEvacuation = "started shards evacuation" + EngineFinishedSuccessfullyShardsEvacuation = "shards evacuation finished successfully" + EngineFinishedWithErrorShardsEvacuation = "shards evacuation finished with error" + EngineObjectIsMovedToAnotherShard = "object is moved to another shard" + MetabaseMissingMatcher = "missing matcher" + MetabaseErrorInFKBTSelection = "error in FKBT selection" + MetabaseCantDecodeListBucketLeaf = "can't decode list bucket leaf" + MetabaseUnknownOperation = "unknown operation" + MetabaseCantIterateOverTheBucket = "can't iterate over the bucket" + MetabaseCouldNotIterateOverTheBuckets = "could not iterate over the buckets" + MetabaseCreatedDirectoryForMetabase = "created directory for Metabase" + MetabaseOpenedBoltDBInstanceForMetabase = "opened boltDB instance for Metabase" + MetabaseCheckingMetabaseVersion = "checking metabase version" + ShardCantSelectAllObjects = "can't select all objects" + ShardSettingShardMode = "setting shard mode" + ShardShardModeSetSuccessfully = "shard mode set successfully" + ShardFetchingObjectWithoutMeta = "fetching object without meta" + ShardObjectIsMissingInWritecache = "object is missing in write-cache" + ShardFailedToFetchObjectFromWritecache = "failed to fetch object from write-cache" + ShardCantPutObjectToTheWritecacheTryingBlobstor = "can't put object to the write-cache, trying blobstor" + ShardMetaObjectCounterRead = "meta: object counter read" + ShardMetaCantReadContainerList = "meta: can't read container list" + ShardMetaCantReadContainerSize = "meta: can't read container size" + ShardMetaInfoPresentButObjectNotFound = "meta info was present, but the object is missing" + ShardMetabaseFailureSwitchingMode = "metabase failure, switching mode" + ShardCantMoveShardToReadonlySwitchMode = "can't move shard to readonly, switch mode" + ShardCouldNotUnmarshalObject = "could not unmarshal object" + ShardCouldNotCloseShardComponent = "could not close shard component" + ShardCantOpenMetabaseMoveToADegradedMode = "can't open metabase, move to a degraded mode" + ShardCantInitializeMetabaseMoveToADegradedreadonlyMode = "can't initialize metabase, move to a degraded-read-only mode" + ShardTryingToRestoreReadwriteMode = "trying to restore read-write mode" + ShardStopEventListenerByClosedEventChannel = "stop event listener by closed `event` channel" + ShardStopEventListenerByClosedStopChannel = "stop event listener by closed `stop` channel" + ShardStopEventListenerByContext = "stop event listener by context" + ShardCouldNotSubmitGCJobToWorkerPool = "could not submit GC job to worker pool" + ShardGCIsStopped = "GC is stopped" + ShardWaitingForGCWorkersToStop = "waiting for GC workers to stop..." + ShardIteratorOverMetabaseGraveyardFailed = "iterator over metabase graveyard failed" + ShardCouldNotDeleteTheObjects = "could not delete the objects" + ShardIteratorOverExpiredObjectsFailed = "iterator over expired objects failed" + ShardCouldNotInhumeTheObjects = "could not inhume the objects" + ShardStartedExpiredTombstonesHandling = "started expired tombstones handling" + ShardIteratingTombstones = "iterating tombstones" + ShardShardIsInADegradedModeSkipCollectingExpiredTombstones = "shard is in a degraded mode, skip collecting expired tombstones" + ShardIteratorOverGraveyardFailed = "iterator over graveyard failed" + ShardHandlingExpiredTombstonesBatch = "handling expired tombstones batch" + ShardFinishedExpiredTombstonesHandling = "finished expired tombstones handling" + ShardIteratorOverExpiredLocksFailed = "iterator over expired locks failed" + ShardCouldNotMarkTombstonesAsGarbage = "could not mark tombstones as garbage" + ShardCouldNotDropExpiredGraveRecords = "could not drop expired grave records" + ShardFailureToUnlockObjects = "failure to unlock objects" + ShardFailureToMarkLockersAsGarbage = "failure to mark lockers as garbage" + ShardFailureToGetExpiredUnlockedObjects = "failure to get expired unlocked objects" + ShardCouldNotMarkObjectToDeleteInMetabase = "could not mark object to delete in metabase" + WritecacheTriedToFlushItemsFromWritecache = "tried to flush items from write-cache" + WritecacheWaitingForChannelsToFlush = "waiting for channels to flush" + WritecacheCantRemoveObjectsFromTheDatabase = "can't remove objects from the database" + WritecacheCantRemoveObjectFromWritecache = "can't remove object from write-cache" + BlobovniczatreeCouldNotGetObjectFromLevel = "could not get object from level" + BlobovniczatreeCouldNotCloseBlobovnicza = "could not close Blobovnicza" + BlobovniczatreeCouldNotRemoveObjectFromLevel = "could not remove object from level" + BlobovniczatreeCouldNotGetActiveBlobovnicza = "could not get active blobovnicza" + BlobovniczatreeBlobovniczaOverflowed = "blobovnicza overflowed" + BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza = "could not put object to active blobovnicza" + BlobovniczatreeInitializingBlobovniczas = "initializing Blobovnicza's" + BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization = "read-only mode, skip blobovniczas initialization..." + BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing = "blobovnicza successfully initialized, closing..." + AlphabetTick = "tick" + AlphabetAlphabetProcessorWorkerPoolDrained = "alphabet processor worker pool drained" + AlphabetNonAlphabetModeIgnoreGasEmissionEvent = "non alphabet mode, ignore gas emission event" + AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent = "node is out of alphabet range, ignore gas emission event" + AlphabetCantInvokeAlphabetEmitMethod = "can't invoke alphabet emit method" + AlphabetStorageNodeEmissionIsOff = "storage node emission is off" + AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes = "can't get netmap snapshot to emit gas to storage nodes" + AlphabetGasEmission = "gas emission" + AlphabetCantParseNodePublicKey = "can't parse node public key" + AlphabetCantTransferGas = "can't transfer gas" + AlphabetCantTransferGasToWallet = "can't transfer gas to wallet" + AlphabetAlphabetWorkerPool = "alphabet worker pool" + BalanceBalanceWorkerPoolDrained = "balance worker pool drained" + BalanceNonAlphabetModeIgnoreBalanceLock = "non alphabet mode, ignore balance lock" + BalanceCantSendLockAssetTx = "can't send lock asset tx" + BalanceBalanceWorkerPool = "balance worker pool" + ContainerContainerWorkerPool = "container worker pool" + ContainerContainerProcessorWorkerPoolDrained = "container processor worker pool drained" + ContainerNonAlphabetModeIgnoreContainerPut = "non alphabet mode, ignore container put" + ContainerPutContainerCheckFailed = "put container check failed" + ContainerCouldNotApprovePutContainer = "could not approve put container" + ContainerNonAlphabetModeIgnoreContainerDelete = "non alphabet mode, ignore container delete" + ContainerDeleteContainerCheckFailed = "delete container check failed" + ContainerCouldNotApproveDeleteContainer = "could not approve delete container" + ContainerNonAlphabetModeIgnoreSetEACL = "non alphabet mode, ignore set EACL" + ContainerSetEACLCheckFailed = "set EACL check failed" + ContainerCouldNotApproveSetEACL = "could not approve set EACL" + FrostFSNonAlphabetModeIgnoreConfig = "non alphabet mode, ignore config" + FrostFSCantRelaySetConfigEvent = "can't relay set config event" + FrostFSFrostfsWorkerPool = "frostfs worker pool" + FrostFSFrostfsProcessorWorkerPoolDrained = "frostfs processor worker pool drained" + FrostFSNonAlphabetModeIgnoreDeposit = "non alphabet mode, ignore deposit" + FrostFSCantTransferAssetsToBalanceContract = "can't transfer assets to balance contract" + FrostFSDoubleMintEmissionDeclined = "double mint emission declined" + FrostFSCantGetGasBalanceOfTheNode = "can't get gas balance of the node" + FrostFSGasBalanceThresholdHasBeenReached = "gas balance threshold has been reached" + FrostFSCantTransferNativeGasToReceiver = "can't transfer native gas to receiver" + FrostFSNonAlphabetModeIgnoreWithdraw = "non alphabet mode, ignore withdraw" + FrostFSCantCreateLockAccount = "can't create lock account" + FrostFSCantLockAssetsForWithdraw = "can't lock assets for withdraw" + FrostFSNonAlphabetModeIgnoreCheque = "non alphabet mode, ignore cheque" + FrostFSCantTransferAssetsToFedContract = "can't transfer assets to fed contract" + GovernanceNewEvent = "new event" + GovernanceGovernanceWorkerPoolDrained = "governance worker pool drained" + GovernanceNonAlphabetModeIgnoreAlphabetSync = "non alphabet mode, ignore alphabet sync" + GovernanceCantFetchAlphabetListFromMainNet = "can't fetch alphabet list from main net" + GovernanceCantFetchAlphabetListFromSideChain = "can't fetch alphabet list from side chain" + GovernanceCantMergeAlphabetListsFromMainNetAndSideChain = "can't merge alphabet lists from main net and side chain" + GovernanceNoGovernanceUpdateAlphabetListHasNotBeenChanged = "no governance update, alphabet list has not been changed" + GovernanceAlphabetListHasBeenChangedStartingUpdate = "alphabet list has been changed, starting update" + GovernanceCantVoteForSideChainCommittee = "can't vote for side chain committee" + GovernanceFinishedAlphabetListUpdate = "finished alphabet list update" + GovernanceCantFetchInnerRingListFromSideChain = "can't fetch inner ring list from side chain" + GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys = "can't create new inner ring list with new alphabet keys" + GovernanceUpdateOfTheInnerRingList = "update of the inner ring list" + GovernanceCantUpdateInnerRingListWithNewAlphabetKeys = "can't update inner ring list with new alphabet keys" + GovernanceCantUpdateListOfNotaryNodesInSideChain = "can't update list of notary nodes in side chain" + GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract = "can't update list of alphabet nodes in frostfs contract" + NetmapNetmapWorkerPool = "netmap worker pool" + NetmapTick = "tick" + NetmapNetmapWorkerPoolDrained = "netmap worker pool drained" + NetmapNetmapCleanUpRoutineIsDisabled518 = "netmap clean up routine is disabled" + NetmapNonAlphabetModeIgnoreNewNetmapCleanupTick = "non alphabet mode, ignore new netmap cleanup tick" + NetmapCantDecodePublicKeyOfNetmapNode = "can't decode public key of netmap node" + NetmapVoteToRemoveNodeFromNetmap = "vote to remove node from netmap" + NetmapCantInvokeNetmapUpdateState = "can't invoke netmap.UpdateState" + NetmapCantIterateOnNetmapCleanerCache = "can't iterate on netmap cleaner cache" + NetmapCantGetEpochDuration = "can't get epoch duration" + NetmapCantGetTransactionHeight = "can't get transaction height" + NetmapCantResetEpochTimer = "can't reset epoch timer" + NetmapCantGetNetmapSnapshotToPerformCleanup = "can't get netmap snapshot to perform cleanup" + NetmapCantStartContainerSizeEstimation = "can't start container size estimation" + NetmapNonAlphabetModeIgnoreNewEpochTick = "non alphabet mode, ignore new epoch tick" + NetmapNextEpoch = "next epoch" + NetmapCantInvokeNetmapNewEpoch = "can't invoke netmap.NewEpoch" + NetmapNonAlphabetModeIgnoreNewPeerNotification = "non alphabet mode, ignore new peer notification" + NetmapNonhaltNotaryTransaction = "non-halt notary transaction" + NetmapCantParseNetworkMapCandidate = "can't parse network map candidate" + NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate = "could not verify and update information about network map candidate" + NetmapApprovingNetworkMapCandidate = "approving network map candidate" + NetmapCantInvokeNetmapAddPeer = "can't invoke netmap.AddPeer" + NetmapNonAlphabetModeIgnoreUpdatePeerNotification = "non alphabet mode, ignore update peer notification" + NetmapPreventSwitchingNodeToMaintenanceState = "prevent switching node to maintenance state" + NetmapCantInvokeNetmapUpdatePeer = "can't invoke netmap.UpdatePeer" + FrostFSIRInternalError = "internal error" + FrostFSIRCouldNotShutdownHTTPServer = "could not shutdown HTTP server" + FrostFSIRApplicationStopped = "application stopped" + FrostFSIRCouldntCreateRPCClientForEndpoint = "could not create RPC client for endpoint" + FrostFSIRCreatedRPCClientForEndpoint = "created RPC client for endpoint" + FrostFSIRReloadExtraWallets = "reload extra wallets" + FrostFSNodeStartListeningEndpoint = "start listening endpoint" + FrostFSNodeCouldNotReadCertificateFromFile = "could not read certificate from file" + FrostFSNodeCantListenGRPCEndpoint = "can't listen gRPC endpoint" + FrostFSNodeStopListeningGRPCEndpoint = "stop listening gRPC endpoint" + FrostFSNodeStoppingGRPCServer = "stopping gRPC server..." + FrostFSNodeGRPCCannotShutdownGracefullyForcingStop = "gRPC cannot shutdown gracefully, forcing stop" + FrostFSNodeGRPCServerStoppedSuccessfully = "gRPC server stopped successfully" + FrostFSNodeGRPCServerError = "gRPC server error" + FrostFSNodeGRPCReconnecting = "reconnecting gRPC server..." + FrostFSNodeGRPCReconnectedSuccessfully = "gRPC server reconnected successfully" + FrostFSNodeGRPCServerConfigNotFound = "gRPC server config not found" + FrostFSNodeGRPCReconnectFailed = "failed to reconnect gRPC server" + FrostFSNodeWaitingForAllProcessesToStop = "waiting for all processes to stop" + FrostFSNodeStartedLocalNodesMaintenance = "started local node's maintenance" + FrostFSNodeStoppedLocalNodesMaintenance = "stopped local node's maintenance" + FrostFSNodeFailedToAttachShardToEngine = "failed to attach shard to engine" + FrostFSNodeShardAttachedToEngine = "shard attached to engine" + FrostFSNodeClosingComponentsOfTheStorageEngine = "closing components of the storage engine..." + FrostFSNodeAccessPolicyEngineClosingFailure = "ape closing failure" + FrostFSNodeStorageEngineClosingFailure = "storage engine closing failure" + FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed = "persistent rule storage db path is not set: in-memory will be used" + FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully = "all components of the storage engine closed successfully" + FrostFSNodeBootstrappingWithTheMaintenanceState = "bootstrapping with the maintenance state" + FrostFSNodeBootstrappingWithOnlineState = "bootstrapping with online state" + FrostFSNodeTerminationSignalHasBeenReceivedStopping = "termination signal has been received, stopping..." + FrostFSNodeTerminationSignalProcessingIsComplete = "termination signal processing is complete" + FrostFSNodeInternalApplicationError = "internal application error" + FrostFSNodeInternalErrorProcessingIsComplete = "internal error processing is complete" + FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration = "SIGHUP has been received, rereading configuration..." + FrostFSNodeSIGHUPSkip = "node not ready for reconfiguration, skipped SIGHUP" + FrostFSNodeShutdownSkip = "node already is going to shutting down, skipped shutdown" + FrostFSNodeShutdownWhenNotReady = "node is going to shutting down when subsystems still initializing" + FrostFSNodeConfigurationReading = "configuration reading" + FrostFSNodeLoggerConfigurationPreparation = "logger configuration preparation" + FrostFSNodeTracingConfigationUpdated = "tracing configation updated" + FrostFSNodeStorageEngineConfigurationUpdate = "storage engine configuration update" + FrostFSNodePoolConfigurationUpdate = "adjust pool configuration" + FrostFSNodeUpdatedConfigurationApplying = "updated configuration applying" + FrostFSNodeConfigurationHasBeenReloadedSuccessfully = "configuration has been reloaded successfully" + FrostFSNodeReadNewlyCreatedContainerAfterTheNotification = "read newly created container after the notification" + FrostFSNodeContainerCreationEventsReceipt = "container creation event's receipt" + FrostFSNodeContainerRemovalEventsReceipt = "container removal event's receipt" + FrostFSNodeNotificatorCouldNotListContainers = "notificator: could not list containers" + FrostFSNodeNotificatorCouldNotSelectObjectsFromContainer = "notificator: could not select objects from container" + FrostFSNodeNotificatorCouldNotProcessObject = "notificator: could not process object" + FrostFSNodeNotificatorFinishedProcessingObjectNotifications = "notificator: finished processing object notifications" + FrostFSNodeCouldNotWriteObjectNotification = "could not write object notification" + FrostFSNodeCouldNotGetMaxObjectSizeValue = "could not get max object size value" + FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage = "could not inhume mark redundant copy as garbage" + FrostFSNodeFailedInitTracing = "failed init tracing" + FrostFSNodeFailedShutdownTracing = "failed shutdown tracing" + FrostFSNodeFailedToCreateNeoRPCClient = "failed to create neo RPC client" + FrostFSNodeClosingMorphComponents = "closing morph components..." + FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal = "failed to set group signer scope, continue with Global" + FrostFSNodeNotarySupport = "notary support" + FrostFSNodeMorphcacheTTLFetchedFromNetwork = "morph.cache_ttl fetched from network" + FrostFSNodeNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made" + FrostFSNodeCantGetLastProcessedSideChainBlockNumber = "can't get last processed side chain block number" + FrostFSNodeNewEpochEventFromSidechain = "new epoch event from sidechain" + FrostFSNodeNewBlock = "new block" + FrostFSNodeCantUpdatePersistentState = "can't update persistent state" + FrostFSNodeCantSendRebootstrapTx = "can't send re-bootstrap tx" + FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch = "could not update node state on new epoch" + FrostFSNodeCouldNotMakeNotaryDeposit = "could not make notary deposit" + FrostFSNodeInitialNetworkState = "initial network state" + FrostFSNodeTreeServiceIsNotEnabledSkipInitialization = "tree service is not enabled, skip initialization" + FrostFSNodeCouldNotSynchronizeTreeService = "could not synchronize Tree Service" + FrostFSNodeRemovingAllTreesForContainer = "removing all trees for container" + FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved = "container removal event received, but trees weren't removed" + FrostFSNodeCantListenGRPCEndpointControl = "can't listen gRPC endpoint (control)" + FrostFSNodePolicerIsDisabled = "policer is disabled" + CommonApplicationStarted = "application started" + ShardGCCollectingExpiredObjectsStarted = "collecting expired objects started" + ShardGCCollectingExpiredObjectsCompleted = "collecting expired objects completed" + ShardGCCollectingExpiredLocksStarted = "collecting expired locks started" + ShardGCCollectingExpiredLocksCompleted = "collecting expired locks completed" + ShardGCRemoveGarbageStarted = "garbage remove started" + ShardGCRemoveGarbageCompleted = "garbage remove completed" + EngineShardsEvacuationFailedToCount = "failed to get total objects count to evacuate" + EngineShardsEvacuationFailedToListObjects = "failed to list objects to evacuate" + EngineShardsEvacuationFailedToReadObject = "failed to read object to evacuate" + EngineShardsEvacuationFailedToMoveObject = "failed to evacuate object to other node" + ShardGCFailedToGetExpiredWithLinked = "failed to get expired objects with linked" + FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap = "the node is under maintenance, skip initial bootstrap" + EngineCouldNotChangeShardModeToDisabled = "could not change shard mode to disabled" + RPConnectionLost = "RPC connection lost, attempting reconnect" + RPCNodeSwitchFailure = "can't switch RPC node" + FSTreeCantUnmarshalObject = "can't unmarshal an object" + FSTreeCantFushObjectBlobstor = "can't flush an object to blobstor" + FSTreeCantUpdateID = "can't update object storage ID" + FSTreeCantDecodeDBObjectAddress = "can't decode object address from the DB" + PutSingleRedirectFailure = "failed to redirect PutSingle request" + StorageIDRetrievalFailure = "can't get storage ID from metabase" + ObjectRemovalFailureBlobStor = "can't remove object from blobStor" + CandidateStatusPriority = "candidate status is different from the netmap status, the former takes priority" + TombstoneExpirationParseFailure = "tombstone getter: could not parse tombstone expiration epoch" + RuntimeSoftMemoryLimitUpdated = "soft runtime memory limit value updated" + RuntimeSoftMemoryDefinedWithGOMEMLIMIT = "soft runtime memory defined with GOMEMLIMIT environment variable, config value skipped" + AttemtToCloseAlreadyClosedBlobovnicza = "attempt to close an already closed blobovnicza" + FailedToGetContainerCounters = "failed to get container counters values" + FailedToRebuildBlobstore = "failed to rebuild blobstore" + BlobstoreRebuildStarted = "blobstore rebuild started" + BlobstoreRebuildCompletedSuccessfully = "blobstore rebuild completed successfully" + BlobstoreRebuildStopped = "blobstore rebuild stopped" + BlobovniczaTreeFixingFileExtensions = "fixing blobovnicza tree file extensions..." + BlobovniczaTreeFixingFileExtensionsCompletedSuccessfully = "fixing blobovnicza tree file extensions completed successfully" + BlobovniczaTreeFixingFileExtensionsFailed = "failed to fix blobovnicza tree file extensions" + BlobovniczaTreeFixingFileExtensionForFile = "fixing blobovnicza file extension..." + BlobovniczaTreeFixingFileExtensionCompletedSuccessfully = "fixing blobovnicza file extension completed successfully" + BlobovniczaTreeFixingFileExtensionFailed = "failed to fix blobovnicza file extension" + BlobstorRebuildFailedToRebuildStorages = "failed to rebuild storages" + BlobstorRebuildRebuildStoragesCompleted = "storages rebuild completed" + BlobovniczaTreeCollectingDBToRebuild = "collecting blobovniczas to rebuild..." + BlobovniczaTreeCollectingDBToRebuildFailed = "collecting blobovniczas to rebuild failed" + BlobovniczaTreeCollectingDBToRebuildSuccess = "collecting blobovniczas to rebuild completed successfully" + BlobovniczaTreeRebuildingBlobovnicza = "rebuilding blobovnicza..." + BlobovniczaTreeRebuildingBlobovniczaFailed = "rebuilding blobovnicza failed" + BlobovniczaTreeRebuildingBlobovniczaSuccess = "rebuilding blobovnicza completed successfully" + BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza = "could not put move info to source blobovnicza" + BlobovniczatreeCouldNotUpdateStorageID = "could not update storage ID" + BlobovniczatreeCouldNotDropMoveInfo = "could not drop move info from source blobovnicza" + BlobovniczatreeCouldNotDeleteFromSource = "could not delete object from source blobovnicza" + BlobovniczaTreeCompletingPreviousRebuild = "completing previous rebuild if failed..." + BlobovniczaTreeCompletedPreviousRebuildSuccess = "previous rebuild completed successfully" + BlobovniczaTreeCompletedPreviousRebuildFailed = "failed to complete previous rebuild" + BlobovniczatreeCouldNotCheckExistenceInTargetDB = "could not check object existence in target blobovnicza" + BlobovniczatreeCouldNotPutObjectToTargetDB = "could not put object to target blobovnicza" + BlobovniczaSavingCountersToMeta = "saving counters to blobovnicza's meta..." + BlobovniczaSavingCountersToMetaSuccess = "saving counters to blobovnicza's meta completed successfully" + BlobovniczaSavingCountersToMetaFailed = "saving counters to blobovnicza's meta failed" + ObjectRemovalFailureExistsInWritecache = "can't remove object: object must be flushed from writecache" + FailedToReportStatusToSystemd = "failed to report status to systemd" + ShardGCCollectingExpiredMetricsStarted = "collecting expired metrics started" + ShardGCCollectingExpiredMetricsCompleted = "collecting expired metrics completed" + ShardGCFailedToCollectZeroSizeContainers = "failed to collect zero-size containers" + ShardGCFailedToCollectZeroCountContainers = "failed to collect zero-count containers" + EngineFailedToCheckContainerAvailability = "failed to check container availability" + EngineFailedToGetContainerSize = "failed to get container size" + EngineFailedToDeleteContainerSize = "failed to delete container size" + EngineInterruptProcessingZeroSizeContainers = "interrupt processing zero-size containers" + EngineInterruptProcessingZeroCountContainers = "interrupt processing zero-count containers" + EngineFailedToGetContainerCounters = "failed to get container counters" + GetSvcV2FailedToParseNodeEndpoints = "failed to parse node endpoints" + GetSvcV2FailedToParseNodeExternalAddresses = "failed to parse node external addresses" + GetSvcV2FailedToGetRangeHashFromNode = "failed to get range hash from node" + GetSvcV2FailedToGetRangeHashFromAllOfContainerNodes = "failed to get range hash from all of container nodes" + FailedToUpdateShardID = "failed to update shard id" + EngineShardsEvacuationFailedToMoveTree = "failed to evacuate tree to other node" + EngineShardsEvacuationTreeEvacuatedLocal = "tree evacuated to local node" + EngineShardsEvacuationTreeEvacuatedRemote = "tree evacuated to other node" + EngineRefillFailedToGetObjectsCount = "failed to get blobstor objects count, no resync percent estimation is available" + ECFailedToSendToContainerNode = "failed to send EC object to container node" + ECFailedToSaveECPart = "failed to save EC part" ) From 5c730de96e1cd1dd45f6bd46b79ebbaff3532e18 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 3 May 2024 14:52:28 +0300 Subject: [PATCH 0542/1413] [#1120] cli: Add EC support to `object nodes` command Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 220 ++++++++++++++++-------- 1 file changed, 152 insertions(+), 68 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 38b9dec82a..b33cbf17f3 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" @@ -32,11 +33,16 @@ const ( var errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint") -type objectNodesInfo struct { - containerID cid.ID - objectID oid.ID - relatedObjectIDs []oid.ID - isLockOrTombstone bool +type phyObject struct { + containerID cid.ID + objectID oid.ID + storedOnAllContainerNodes bool + ecHeader *ecHeader +} + +type ecHeader struct { + index uint32 + parent oid.ID } type boolError struct { @@ -49,7 +55,7 @@ var objectNodesCmd = &cobra.Command{ Short: "List of nodes where the object is stored", Long: `List of nodes where the object should be stored and where it is actually stored. Lock objects must exist on all nodes of the container. - For complex objects, a node is considered to store an object if the node stores at least one part of the complex object. + For complex and EC objects, a node is considered to store an object if the node stores at least one part of the complex object or one chunk of the EC object. By default, the actual storage of the object is checked only on the nodes that should store the object. To check all nodes, use the flag --verify-presence-all.`, Run: objectNodes, } @@ -76,18 +82,18 @@ func objectNodes(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) - objectInfo := getObjectInfo(cmd, cnrID, objID, cli, pk) + objects := getPhyObjects(cmd, cnrID, objID, cli, pk) placementPolicy, netmap := getPlacementPolicyAndNetmap(cmd, cnrID, cli) - requiredPlacement := getRequiredPlacement(cmd, objectInfo, placementPolicy, netmap) + requiredPlacement := getRequiredPlacement(cmd, objects, placementPolicy, netmap) - actualPlacement := getActualPlacement(cmd, netmap, requiredPlacement, pk, objectInfo) + actualPlacement := getActualPlacement(cmd, netmap, requiredPlacement, pk, objects) printPlacement(cmd, netmap, requiredPlacement, actualPlacement) } -func getObjectInfo(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey) *objectNodesInfo { +func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey) []phyObject { var addrObj oid.Address addrObj.SetContainer(cnrID) addrObj.SetObject(objID) @@ -102,44 +108,101 @@ func getObjectInfo(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.C res, err := internalclient.HeadObject(cmd.Context(), prmHead) if err == nil { - return &objectNodesInfo{ - containerID: cnrID, - objectID: objID, - isLockOrTombstone: res.Header().Type() == objectSDK.TypeLock || res.Header().Type() == objectSDK.TypeTombstone, + obj := phyObject{ + containerID: cnrID, + objectID: objID, + storedOnAllContainerNodes: res.Header().Type() == objectSDK.TypeLock || res.Header().Type() == objectSDK.TypeTombstone, } + if res.Header().ECHeader() != nil { + obj.ecHeader = &ecHeader{ + index: res.Header().ECHeader().Index(), + parent: res.Header().ECHeader().Parent(), + } + } + return []phyObject{obj} } var errSplitInfo *objectSDK.SplitInfoError - - if !errors.As(err, &errSplitInfo) { - commonCmd.ExitOnErr(cmd, "failed to get object info: %w", err) - return nil + if errors.As(err, &errSplitInfo) { + return getComplexObjectParts(cmd, cnrID, objID, cli, prmHead, errSplitInfo) } + var ecInfoError *objectSDK.ECInfoError + if errors.As(err, &ecInfoError) { + return getECObjectChunks(cmd, cnrID, objID, ecInfoError) + } + commonCmd.ExitOnErr(cmd, "failed to get object info: %w", err) + return nil +} + +func getComplexObjectParts(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, prmHead internalclient.HeadObjectPrm, errSplitInfo *objectSDK.SplitInfoError) []phyObject { + members := getCompexObjectMembers(cmd, cnrID, objID, cli, prmHead, errSplitInfo) + return flattenComplexMembersIfECContainer(cmd, cnrID, members, prmHead) +} + +func getCompexObjectMembers(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, prmHead internalclient.HeadObjectPrm, errSplitInfo *objectSDK.SplitInfoError) []oid.ID { splitInfo := errSplitInfo.SplitInfo() if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnrID); ok { - return &objectNodesInfo{ - containerID: cnrID, - objectID: objID, - relatedObjectIDs: members, - } + return members } if members, ok := tryGetSplitMembersBySplitID(cmd, splitInfo, cli, cnrID); ok { - return &objectNodesInfo{ - containerID: cnrID, - objectID: objID, - relatedObjectIDs: members, - } + return members } - members := tryRestoreChainInReverse(cmd, splitInfo, prmHead, cli, cnrID, objID) - return &objectNodesInfo{ - containerID: cnrID, - objectID: objID, - relatedObjectIDs: members, + return tryRestoreChainInReverse(cmd, splitInfo, prmHead, cli, cnrID, objID) +} + +func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, members []oid.ID, prmHead internalclient.HeadObjectPrm) []phyObject { + result := make([]phyObject, 0, len(members)) + var addrObj oid.Address + addrObj.SetContainer(cnrID) + prmHead.SetRawFlag(true) // to get an error instead of whole object + for _, partObjID := range members { + addrObj.SetObject(partObjID) + prmHead.SetAddress(addrObj) + + _, err := internalclient.HeadObject(cmd.Context(), prmHead) + var ecInfoError *objectSDK.ECInfoError + if errors.As(err, &ecInfoError) { + chunks := getECObjectChunks(cmd, cnrID, partObjID, ecInfoError) + result = append(result, chunks...) + continue + } else if err == nil { // not EC object, so all members must be phy objects + for _, member := range members { + result = append(result, phyObject{ + containerID: cnrID, + objectID: member, + }) + } + break + } + commonCmd.ExitOnErr(cmd, "failed to read EC chunk of complex object: %w", err) } + return result +} + +func getECObjectChunks(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, errECInfo *objectSDK.ECInfoError) []phyObject { + ecInfo := errECInfo.ECInfo() + result := make([]phyObject, 0, len(ecInfo.Chunks)) + for _, ch := range ecInfo.Chunks { + var chID oid.ID + err := chID.ReadFromV2(ch.ID) + if err != nil { + commonCmd.ExitOnErr(cmd, "failed to read EC chunk ID %w", err) + return nil + } + result = append(result, phyObject{ + containerID: cnrID, + objectID: chID, + ecHeader: &ecHeader{ + index: ch.Index, + parent: objID, + }, + }) + } + return result } func getPlacementPolicyAndNetmap(cmd *cobra.Command, cnrID cid.ID, cli *client.Client) (placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) { @@ -184,29 +247,28 @@ func getNetMap(ctx context.Context, cli *client.Client) (*netmapSDK.NetMap, erro return &nm, nil } -func getRequiredPlacement(cmd *cobra.Command, objInfo *objectNodesInfo, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo { +func getRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo { + if policy.IsECPlacement(placementPolicy) { + return getECRequiredPlacement(cmd, objects, placementPolicy, netmap) + } + return getReplicaRequiredPlacement(cmd, objects, placementPolicy, netmap) +} + +func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo { nodes := make(map[uint64]netmapSDK.NodeInfo) placementBuilder := placement.NewNetworkMapBuilder(netmap) - placement, err := placementBuilder.BuildPlacement(objInfo.containerID, &objInfo.objectID, placementPolicy) - commonCmd.ExitOnErr(cmd, "failed to get required placement: %w", err) - for repIdx, rep := range placement { - numOfReplicas := placementPolicy.ReplicaDescriptor(repIdx).NumberOfObjects() - var nodeIdx uint32 - for _, n := range rep { - if !objInfo.isLockOrTombstone && nodeIdx == numOfReplicas { // lock and tombstone objects should be on all container nodes - break - } - nodes[n.Hash()] = n - nodeIdx++ - } - } - - for _, relatedObjID := range objInfo.relatedObjectIDs { - placement, err = placementBuilder.BuildPlacement(objInfo.containerID, &relatedObjID, placementPolicy) - commonCmd.ExitOnErr(cmd, "failed to get required placement for related object: %w", err) - for _, rep := range placement { + for _, object := range objects { + placement, err := placementBuilder.BuildPlacement(object.containerID, &object.objectID, placementPolicy) + commonCmd.ExitOnErr(cmd, "failed to get required placement for object: %w", err) + for repIdx, rep := range placement { + numOfReplicas := placementPolicy.ReplicaDescriptor(repIdx).NumberOfObjects() + var nodeIdx uint32 for _, n := range rep { + if !object.storedOnAllContainerNodes && nodeIdx == numOfReplicas { + break + } nodes[n.Hash()] = n + nodeIdx++ } } } @@ -214,8 +276,42 @@ func getRequiredPlacement(cmd *cobra.Command, objInfo *objectNodesInfo, placemen return nodes } +func getECRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo { + nodes := make(map[uint64]netmapSDK.NodeInfo) + for _, object := range objects { + getECRequiredPlacementInternal(cmd, object, placementPolicy, netmap, nodes) + } + return nodes +} + +func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap, nodes map[uint64]netmapSDK.NodeInfo) { + placementObjectID := object.objectID + if object.ecHeader != nil { + placementObjectID = object.ecHeader.parent + } + placementBuilder := placement.NewNetworkMapBuilder(netmap) + placement, err := placementBuilder.BuildPlacement(object.containerID, &placementObjectID, placementPolicy) + commonCmd.ExitOnErr(cmd, "failed to get required placement: %w", err) + + for _, vector := range placement { + if object.storedOnAllContainerNodes { + for _, node := range vector { + nodes[node.Hash()] = node + } + continue + } + + if object.ecHeader != nil { + chunkIdx := int(object.ecHeader.index) + nodeIdx := chunkIdx % len(vector) + node := vector[nodeIdx] + nodes[node.Hash()] = node + } + } +} + func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo, - pk *ecdsa.PrivateKey, objInfo *objectNodesInfo, + pk *ecdsa.PrivateKey, objects []phyObject, ) map[uint64]boolError { result := make(map[uint64]boolError) resultMtx := &sync.Mutex{} @@ -243,23 +339,11 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPl return nil } - eg.Go(func() error { - var v boolError - v.value, v.err = isObjectStoredOnNode(egCtx, cmd, objInfo.containerID, objInfo.objectID, cli, pk) - resultMtx.Lock() - defer resultMtx.Unlock() - if prev, exists := result[cand.Hash()]; exists && (prev.err != nil || prev.value) { - return nil - } - result[cand.Hash()] = v - return nil - }) - - for _, rObjID := range objInfo.relatedObjectIDs { - rObjID := rObjID + for _, object := range objects { + object := object eg.Go(func() error { var v boolError - v.value, v.err = isObjectStoredOnNode(egCtx, cmd, objInfo.containerID, rObjID, cli, pk) + v.value, v.err = isObjectStoredOnNode(egCtx, cmd, object.containerID, object.objectID, cli, pk) resultMtx.Lock() defer resultMtx.Unlock() if prev, exists := result[cand.Hash()]; exists && (prev.err != nil || prev.value) { From ada1b9f737dce80d05ddb15bde9eb8339ccce4fc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 3 May 2024 17:20:41 +0300 Subject: [PATCH 0543/1413] [#1120] objectSvc: Fix EC put placement Use parent object ID to compute placement. Fix too many copies saving. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/put/ec.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/services/object/put/ec.go b/pkg/services/object/put/ec.go index 74db3c31fb..6237872fbb 100644 --- a/pkg/services/object/put/ec.go +++ b/pkg/services/object/put/ec.go @@ -147,7 +147,7 @@ func (e *ecWriter) relayToContainerNode(ctx context.Context) error { } func (e *ecWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error { - t, err := placement.NewTraverser(e.placementOpts...) + t, err := placement.NewTraverser(append(e.placementOpts, placement.ForObject(obj.ECHeader().Parent()))...) if err != nil { return err } @@ -162,6 +162,7 @@ func (e *ecWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error eg.Go(func() error { return e.writePart(egCtx, obj, int(obj.ECHeader().Index()), nodes) }) + t.SubmitSuccess() } if err := eg.Wait(); err != nil { return errIncompletePut{ @@ -181,7 +182,8 @@ func (e *ecWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er if err != nil { return err } - t, err := placement.NewTraverser(e.placementOpts...) + objID, _ := obj.ID() + t, err := placement.NewTraverser(append(e.placementOpts, placement.ForObject(objID))...) if err != nil { return err } @@ -198,6 +200,7 @@ func (e *ecWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er eg.Go(func() error { return e.writePart(egCtx, parts[idx], idx, nodes) }) + t.SubmitSuccess() } } if err := eg.Wait(); err != nil { From 654384990cc67024586f4a577c2251a1d8e53812 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 6 May 2024 12:37:00 +0300 Subject: [PATCH 0544/1413] [#1120] cli: Fix `object nodes` for linking objects Do not use linking objects to get placement for complex object. Linking objects should be stored on all container nodes, also they are not required. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 11 +++++++---- cmd/frostfs-cli/modules/object/util.go | 10 ++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index b33cbf17f3..c3bf239cc6 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -109,9 +109,11 @@ func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.C res, err := internalclient.HeadObject(cmd.Context(), prmHead) if err == nil { obj := phyObject{ - containerID: cnrID, - objectID: objID, - storedOnAllContainerNodes: res.Header().Type() == objectSDK.TypeLock || res.Header().Type() == objectSDK.TypeTombstone, + containerID: cnrID, + objectID: objID, + storedOnAllContainerNodes: res.Header().Type() == objectSDK.TypeLock || + res.Header().Type() == objectSDK.TypeTombstone || + len(res.Header().Children()) > 0, } if res.Header().ECHeader() != nil { obj.ecHeader = &ecHeader{ @@ -143,7 +145,7 @@ func getComplexObjectParts(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli * func getCompexObjectMembers(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, prmHead internalclient.HeadObjectPrm, errSplitInfo *objectSDK.SplitInfoError) []oid.ID { splitInfo := errSplitInfo.SplitInfo() - if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnrID); ok { + if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnrID, false); ok { return members } @@ -412,6 +414,7 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID, if errors.As(err, ¬Found) || errors.As(err, &removed) { return false, nil } + cmd.Printf("failed to get object %s from client\n", objID.EncodeToString()) return false, err } diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index 37e9f74e08..c8625eb942 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -370,7 +370,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, splitInfo := errSplit.SplitInfo() - if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnr); ok { + if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnr, true); ok { return members } @@ -381,7 +381,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, return tryRestoreChainInReverse(cmd, splitInfo, prmHead, cli, cnr, obj) } -func tryGetSplitMembersByLinkingObject(cmd *cobra.Command, splitInfo *objectSDK.SplitInfo, prmHead internal.HeadObjectPrm, cnr cid.ID) ([]oid.ID, bool) { +func tryGetSplitMembersByLinkingObject(cmd *cobra.Command, splitInfo *objectSDK.SplitInfo, prmHead internal.HeadObjectPrm, cnr cid.ID, withLinking bool) ([]oid.ID, bool) { // collect split chain by the descending ease of operations (ease is evaluated heuristically). // If any approach fails, we don't try the next since we assume that it will fail too. @@ -402,8 +402,10 @@ func tryGetSplitMembersByLinkingObject(cmd *cobra.Command, splitInfo *objectSDK. common.PrintVerbose(cmd, "Received split members from the linking object: %v", children) - // include linking object - return append(children, idLinking), true + if withLinking { + return append(children, idLinking), true + } + return children, true } // linking object is not required for From a45b548a6f28e9ccde71a3b422497e88cc467aa9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 6 May 2024 15:52:41 +0300 Subject: [PATCH 0545/1413] [#1120] cli: Add explain to `object nodes` Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 95 ++++++++++++++++++++----- 1 file changed, 77 insertions(+), 18 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index c3bf239cc6..2e84cc6a53 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -29,6 +29,7 @@ import ( const ( verifyPresenceAllFlag = "verify-presence-all" + explainFlag = "explain" ) var errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint") @@ -50,6 +51,11 @@ type boolError struct { err error } +type objectPlacement struct { + requiredNodes []netmapSDK.NodeInfo + confirmedNodes []netmapSDK.NodeInfo +} + var objectNodesCmd = &cobra.Command{ Use: "nodes", Short: "List of nodes where the object is stored", @@ -71,7 +77,8 @@ func initObjectNodesCmd() { flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) _ = objectGetCmd.MarkFlagRequired(commonflags.OIDFlag) - flags.Bool("verify-presence-all", false, "Verify the actual presence of the object on all netmap nodes") + flags.Bool(verifyPresenceAllFlag, false, "Verify the actual presence of the object on all netmap nodes") + flags.Bool(explainFlag, false, "Show detailed information about the object placement") } func objectNodes(cmd *cobra.Command, _ []string) { @@ -86,11 +93,11 @@ func objectNodes(cmd *cobra.Command, _ []string) { placementPolicy, netmap := getPlacementPolicyAndNetmap(cmd, cnrID, cli) - requiredPlacement := getRequiredPlacement(cmd, objects, placementPolicy, netmap) + requiredNodes, objectsPlacement := getRequiredPlacement(cmd, objects, placementPolicy, netmap) - actualPlacement := getActualPlacement(cmd, netmap, requiredPlacement, pk, objects) + actualPlacement := getActualPlacement(cmd, netmap, requiredNodes, pk, objects, objectsPlacement) - printPlacement(cmd, netmap, requiredPlacement, actualPlacement) + printPlacement(cmd, netmap, requiredNodes, actualPlacement, objID, objects, objectsPlacement) } func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey) []phyObject { @@ -249,15 +256,16 @@ func getNetMap(ctx context.Context, cli *client.Client) (*netmapSDK.NetMap, erro return &nm, nil } -func getRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo { +func getRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) { if policy.IsECPlacement(placementPolicy) { return getECRequiredPlacement(cmd, objects, placementPolicy, netmap) } return getReplicaRequiredPlacement(cmd, objects, placementPolicy, netmap) } -func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo { +func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) { nodes := make(map[uint64]netmapSDK.NodeInfo) + objectsNodes := make(map[oid.ID]objectPlacement) placementBuilder := placement.NewNetworkMapBuilder(netmap) for _, object := range objects { placement, err := placementBuilder.BuildPlacement(object.containerID, &object.objectID, placementPolicy) @@ -270,23 +278,29 @@ func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placem break } nodes[n.Hash()] = n + + op := objectsNodes[object.objectID] + op.requiredNodes = append(op.requiredNodes, n) + objectsNodes[object.objectID] = op + nodeIdx++ } } } - return nodes + return nodes, objectsNodes } -func getECRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) map[uint64]netmapSDK.NodeInfo { +func getECRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) { nodes := make(map[uint64]netmapSDK.NodeInfo) + objectsNodes := make(map[oid.ID]objectPlacement) for _, object := range objects { - getECRequiredPlacementInternal(cmd, object, placementPolicy, netmap, nodes) + getECRequiredPlacementInternal(cmd, object, placementPolicy, netmap, nodes, objectsNodes) } - return nodes + return nodes, objectsNodes } -func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap, nodes map[uint64]netmapSDK.NodeInfo) { +func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap, nodes map[uint64]netmapSDK.NodeInfo, objectNodes map[oid.ID]objectPlacement) { placementObjectID := object.objectID if object.ecHeader != nil { placementObjectID = object.ecHeader.parent @@ -299,6 +313,10 @@ func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placem if object.storedOnAllContainerNodes { for _, node := range vector { nodes[node.Hash()] = node + + op := objectNodes[object.objectID] + op.requiredNodes = append(op.requiredNodes, node) + objectNodes[object.objectID] = op } continue } @@ -308,12 +326,16 @@ func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placem nodeIdx := chunkIdx % len(vector) node := vector[nodeIdx] nodes[node.Hash()] = node + + op := objectNodes[object.objectID] + op.requiredNodes = append(op.requiredNodes, node) + objectNodes[object.objectID] = op } } } func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo, - pk *ecdsa.PrivateKey, objects []phyObject, + pk *ecdsa.PrivateKey, objects []phyObject, objectNodes map[oid.ID]objectPlacement, ) map[uint64]boolError { result := make(map[uint64]boolError) resultMtx := &sync.Mutex{} @@ -348,6 +370,11 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPl v.value, v.err = isObjectStoredOnNode(egCtx, cmd, object.containerID, object.objectID, cli, pk) resultMtx.Lock() defer resultMtx.Unlock() + if v.err == nil && v.value { + op := objectNodes[object.objectID] + op.confirmedNodes = append(op.confirmedNodes, cand) + objectNodes[object.objectID] = op + } if prev, exists := result[cand.Hash()]; exists && (prev.err != nil || prev.value) { return nil } @@ -418,12 +445,12 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID, return false, err } -func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo, actualPlacement map[uint64]boolError) { +func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo, + actualPlacement map[uint64]boolError, objID oid.ID, objects []phyObject, objectNodes map[oid.ID]objectPlacement, +) { w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) - defer func() { - commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", w.Flush()) - }() - fmt.Fprintln(w, "Node ID\tShould contain object\tActually contains object\t") + _, err := fmt.Fprintln(w, "Node ID\tShould contain object\tActually contains object\t") + commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", err) for _, n := range netmap.Nodes() { nodeID := hex.EncodeToString(n.PublicKey()) _, required := requiredPlacement[n.Hash()] @@ -436,6 +463,38 @@ func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacem actualStr = strconv.FormatBool(actual.value) } } - fmt.Fprintf(w, "%s\t%s\t%s\t\n", nodeID, strconv.FormatBool(required), actualStr) + _, err := fmt.Fprintf(w, "%s\t%s\t%s\t\n", nodeID, strconv.FormatBool(required), actualStr) + commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", err) + } + commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", w.Flush()) + + if explain, _ := cmd.Flags().GetBool(explainFlag); !explain { + return + } + + fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects:\n", objID.EncodeToString(), len(objects)) + + for _, object := range objects { + fmt.Fprintf(cmd.OutOrStdout(), "- %s\n", object.objectID) + if object.ecHeader != nil { + fmt.Fprintf(cmd.OutOrStdout(), "\tEC index: %d\n", object.ecHeader.index) + fmt.Fprintf(cmd.OutOrStdout(), "\tEC parent: %s\n", object.ecHeader.parent.EncodeToString()) + } + op, ok := objectNodes[object.objectID] + if !ok { + continue + } + if len(op.requiredNodes) > 0 { + fmt.Fprintf(cmd.OutOrStdout(), "\tRequired nodes:\n") + for _, node := range op.requiredNodes { + fmt.Fprintf(cmd.OutOrStdout(), "\t\t- %s\n", hex.EncodeToString(node.PublicKey())) + } + } + if len(op.confirmedNodes) > 0 { + fmt.Fprintf(cmd.OutOrStdout(), "\tActual nodes:\n") + for _, node := range op.confirmedNodes { + fmt.Fprintf(cmd.OutOrStdout(), "\t\t- %s\n", hex.EncodeToString(node.PublicKey())) + } + } } } From 368218f0cca4d436ff786eb0bf8d9fd1c7a1b7ac Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 7 May 2024 12:12:34 +0300 Subject: [PATCH 0546/1413] [#1120] cli: Edit `object nodes` output Print detailed information only. Allow to output to JSON. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 238 +++++++++++++++--------- 1 file changed, 154 insertions(+), 84 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 2e84cc6a53..b5f839eb8f 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -1,14 +1,16 @@ package object import ( + "bytes" + "cmp" "context" "crypto/ecdsa" "encoding/hex" + "encoding/json" "errors" "fmt" - "strconv" + "slices" "sync" - "text/tabwriter" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -29,7 +31,6 @@ import ( const ( verifyPresenceAllFlag = "verify-presence-all" - explainFlag = "explain" ) var errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint") @@ -46,16 +47,30 @@ type ecHeader struct { parent oid.ID } -type boolError struct { - value bool - err error -} - type objectPlacement struct { requiredNodes []netmapSDK.NodeInfo confirmedNodes []netmapSDK.NodeInfo } +type objectNodesResult struct { + errors []error + placements map[oid.ID]objectPlacement +} + +type ObjNodesDataObject struct { + ObjectID string `json:"object_id"` + RequiredNodes []string `json:"required_nodes,omitempty"` + ConfirmedNodes []string `json:"confirmed_nodes,omitempty"` + ECParentObjectID *string `json:"ec_parent_object_id,omitempty"` + ECIndex *uint32 `json:"ec_index,omitempty"` +} + +type objNodesResultJSON struct { + ObjectID string `json:"object_id"` + DataObjects []ObjNodesDataObject `json:"data_objects,omitempty"` + Errors []string `json:"errors,omitempty"` +} + var objectNodesCmd = &cobra.Command{ Use: "nodes", Short: "List of nodes where the object is stored", @@ -77,8 +92,8 @@ func initObjectNodesCmd() { flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) _ = objectGetCmd.MarkFlagRequired(commonflags.OIDFlag) - flags.Bool(verifyPresenceAllFlag, false, "Verify the actual presence of the object on all netmap nodes") - flags.Bool(explainFlag, false, "Show detailed information about the object placement") + flags.Bool(verifyPresenceAllFlag, false, "Verify the actual presence of the object on all netmap nodes.") + flags.Bool(commonflags.JSON, false, "Print information about the object placement as json.") } func objectNodes(cmd *cobra.Command, _ []string) { @@ -93,11 +108,11 @@ func objectNodes(cmd *cobra.Command, _ []string) { placementPolicy, netmap := getPlacementPolicyAndNetmap(cmd, cnrID, cli) - requiredNodes, objectsPlacement := getRequiredPlacement(cmd, objects, placementPolicy, netmap) + result := getRequiredPlacement(cmd, objects, placementPolicy, netmap) - actualPlacement := getActualPlacement(cmd, netmap, requiredNodes, pk, objects, objectsPlacement) + getActualPlacement(cmd, netmap, pk, objects, result) - printPlacement(cmd, netmap, requiredNodes, actualPlacement, objID, objects, objectsPlacement) + printPlacement(cmd, objID, objects, result) } func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey) []phyObject { @@ -256,16 +271,17 @@ func getNetMap(ctx context.Context, cli *client.Client) (*netmapSDK.NetMap, erro return &nm, nil } -func getRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) { +func getRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) *objectNodesResult { if policy.IsECPlacement(placementPolicy) { return getECRequiredPlacement(cmd, objects, placementPolicy, netmap) } return getReplicaRequiredPlacement(cmd, objects, placementPolicy, netmap) } -func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) { - nodes := make(map[uint64]netmapSDK.NodeInfo) - objectsNodes := make(map[oid.ID]objectPlacement) +func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) *objectNodesResult { + result := &objectNodesResult{ + placements: make(map[oid.ID]objectPlacement), + } placementBuilder := placement.NewNetworkMapBuilder(netmap) for _, object := range objects { placement, err := placementBuilder.BuildPlacement(object.containerID, &object.objectID, placementPolicy) @@ -277,30 +293,30 @@ func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placem if !object.storedOnAllContainerNodes && nodeIdx == numOfReplicas { break } - nodes[n.Hash()] = n - op := objectsNodes[object.objectID] + op := result.placements[object.objectID] op.requiredNodes = append(op.requiredNodes, n) - objectsNodes[object.objectID] = op + result.placements[object.objectID] = op nodeIdx++ } } } - return nodes, objectsNodes + return result } -func getECRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) (map[uint64]netmapSDK.NodeInfo, map[oid.ID]objectPlacement) { - nodes := make(map[uint64]netmapSDK.NodeInfo) - objectsNodes := make(map[oid.ID]objectPlacement) - for _, object := range objects { - getECRequiredPlacementInternal(cmd, object, placementPolicy, netmap, nodes, objectsNodes) +func getECRequiredPlacement(cmd *cobra.Command, objects []phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap) *objectNodesResult { + result := &objectNodesResult{ + placements: make(map[oid.ID]objectPlacement), } - return nodes, objectsNodes + for _, object := range objects { + getECRequiredPlacementInternal(cmd, object, placementPolicy, netmap, result) + } + return result } -func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap, nodes map[uint64]netmapSDK.NodeInfo, objectNodes map[oid.ID]objectPlacement) { +func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placementPolicy netmapSDK.PlacementPolicy, netmap *netmapSDK.NetMap, result *objectNodesResult) { placementObjectID := object.objectID if object.ecHeader != nil { placementObjectID = object.ecHeader.parent @@ -312,11 +328,9 @@ func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placem for _, vector := range placement { if object.storedOnAllContainerNodes { for _, node := range vector { - nodes[node.Hash()] = node - - op := objectNodes[object.objectID] + op := result.placements[object.objectID] op.requiredNodes = append(op.requiredNodes, node) - objectNodes[object.objectID] = op + result.placements[object.objectID] = op } continue } @@ -325,30 +339,18 @@ func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placem chunkIdx := int(object.ecHeader.index) nodeIdx := chunkIdx % len(vector) node := vector[nodeIdx] - nodes[node.Hash()] = node - op := objectNodes[object.objectID] + op := result.placements[object.objectID] op.requiredNodes = append(op.requiredNodes, node) - objectNodes[object.objectID] = op + result.placements[object.objectID] = op } } } -func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo, - pk *ecdsa.PrivateKey, objects []phyObject, objectNodes map[oid.ID]objectPlacement, -) map[uint64]boolError { - result := make(map[uint64]boolError) +func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, pk *ecdsa.PrivateKey, objects []phyObject, result *objectNodesResult) { resultMtx := &sync.Mutex{} - var candidates []netmapSDK.NodeInfo - checkAllNodes, _ := cmd.Flags().GetBool(verifyPresenceAllFlag) - if checkAllNodes { - candidates = netmap.Nodes() - } else { - for _, n := range requiredPlacement { - candidates = append(candidates, n) - } - } + candidates := getNodesToCheckObjectExistance(cmd, netmap, result) eg, egCtx := errgroup.WithContext(cmd.Context()) for _, cand := range candidates { @@ -359,26 +361,24 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPl if err != nil { resultMtx.Lock() defer resultMtx.Unlock() - result[cand.Hash()] = boolError{err: err} + result.errors = append(result.errors, fmt.Errorf("failed to connect to node %s: %w", hex.EncodeToString(cand.PublicKey()), err)) return nil } for _, object := range objects { object := object eg.Go(func() error { - var v boolError - v.value, v.err = isObjectStoredOnNode(egCtx, cmd, object.containerID, object.objectID, cli, pk) + stored, err := isObjectStoredOnNode(egCtx, cmd, object.containerID, object.objectID, cli, pk) resultMtx.Lock() defer resultMtx.Unlock() - if v.err == nil && v.value { - op := objectNodes[object.objectID] + if err == nil && stored { + op := result.placements[object.objectID] op.confirmedNodes = append(op.confirmedNodes, cand) - objectNodes[object.objectID] = op + result.placements[object.objectID] = op } - if prev, exists := result[cand.Hash()]; exists && (prev.err != nil || prev.value) { - return nil + if err != nil { + result.errors = append(result.errors, fmt.Errorf("failed to check object %s existence on node %s: %w", object.objectID.EncodeToString(), hex.EncodeToString(cand.PublicKey()), err)) } - result[cand.Hash()] = v return nil }) } @@ -387,7 +387,24 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPl } commonCmd.ExitOnErr(cmd, "failed to get actual placement: %w", eg.Wait()) - return result +} + +func getNodesToCheckObjectExistance(cmd *cobra.Command, netmap *netmapSDK.NetMap, result *objectNodesResult) []netmapSDK.NodeInfo { + checkAllNodes, _ := cmd.Flags().GetBool(verifyPresenceAllFlag) + if checkAllNodes { + return netmap.Nodes() + } + var nodes []netmapSDK.NodeInfo + visited := make(map[uint64]struct{}) + for _, p := range result.placements { + for _, node := range p.requiredNodes { + if _, ok := visited[node.Hash()]; !ok { + nodes = append(nodes, node) + visited[node.Hash()] = struct{}{} + } + } + } + return nodes } func createClient(ctx context.Context, cmd *cobra.Command, candidate netmapSDK.NodeInfo, pk *ecdsa.PrivateKey) (*client.Client, error) { @@ -445,33 +462,44 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID, return false, err } -func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacement map[uint64]netmapSDK.NodeInfo, - actualPlacement map[uint64]boolError, objID oid.ID, objects []phyObject, objectNodes map[oid.ID]objectPlacement, -) { - w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 0, 1, ' ', tabwriter.AlignRight|tabwriter.Debug) - _, err := fmt.Fprintln(w, "Node ID\tShould contain object\tActually contains object\t") - commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", err) - for _, n := range netmap.Nodes() { - nodeID := hex.EncodeToString(n.PublicKey()) - _, required := requiredPlacement[n.Hash()] - actual, actualExists := actualPlacement[n.Hash()] - actualStr := "" - if actualExists { - if actual.err != nil { - actualStr = fmt.Sprintf("error: %v", actual.err) - } else { - actualStr = strconv.FormatBool(actual.value) - } +func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) { + normilizeObjectNodesResult(objects, result) + if json, _ := cmd.Flags().GetBool(commonflags.JSON); json { + printObjectNodesAsJSON(cmd, objID, objects, result) + } else { + printObjectNodesAsText(cmd, objID, objects, result) + } +} + +func normilizeObjectNodesResult(objects []phyObject, result *objectNodesResult) { + slices.SortFunc(objects, func(lhs, rhs phyObject) int { + if lhs.ecHeader == nil && rhs.ecHeader == nil { + return bytes.Compare(lhs.objectID[:], rhs.objectID[:]) } - _, err := fmt.Fprintf(w, "%s\t%s\t%s\t\n", nodeID, strconv.FormatBool(required), actualStr) - commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", err) - } - commonCmd.ExitOnErr(cmd, "failed to print placement info: %w", w.Flush()) - - if explain, _ := cmd.Flags().GetBool(explainFlag); !explain { - return + if lhs.ecHeader == nil { + return -1 + } + if rhs.ecHeader == nil { + return 1 + } + if lhs.ecHeader.parent == rhs.ecHeader.parent { + return cmp.Compare(lhs.ecHeader.index, rhs.ecHeader.index) + } + return bytes.Compare(lhs.ecHeader.parent[:], rhs.ecHeader.parent[:]) + }) + for _, obj := range objects { + op := result.placements[obj.objectID] + slices.SortFunc(op.confirmedNodes, func(lhs, rhs netmapSDK.NodeInfo) int { + return bytes.Compare(lhs.PublicKey(), rhs.PublicKey()) + }) + slices.SortFunc(op.requiredNodes, func(lhs, rhs netmapSDK.NodeInfo) int { + return bytes.Compare(lhs.PublicKey(), rhs.PublicKey()) + }) + result.placements[obj.objectID] = op } +} +func printObjectNodesAsText(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) { fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects:\n", objID.EncodeToString(), len(objects)) for _, object := range objects { @@ -480,7 +508,7 @@ func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacem fmt.Fprintf(cmd.OutOrStdout(), "\tEC index: %d\n", object.ecHeader.index) fmt.Fprintf(cmd.OutOrStdout(), "\tEC parent: %s\n", object.ecHeader.parent.EncodeToString()) } - op, ok := objectNodes[object.objectID] + op, ok := result.placements[object.objectID] if !ok { continue } @@ -491,10 +519,52 @@ func printPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, requiredPlacem } } if len(op.confirmedNodes) > 0 { - fmt.Fprintf(cmd.OutOrStdout(), "\tActual nodes:\n") + fmt.Fprintf(cmd.OutOrStdout(), "\tConfirmed nodes:\n") for _, node := range op.confirmedNodes { fmt.Fprintf(cmd.OutOrStdout(), "\t\t- %s\n", hex.EncodeToString(node.PublicKey())) } } } + + if len(result.errors) == 0 { + return + } + fmt.Fprintf(cmd.OutOrStdout(), "Errors:\n") + for _, err := range result.errors { + fmt.Fprintf(cmd.OutOrStdout(), "\t%s\n", err.Error()) + } +} + +func printObjectNodesAsJSON(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) { + jsonResult := &objNodesResultJSON{ + ObjectID: objID.EncodeToString(), + } + + for _, object := range objects { + do := ObjNodesDataObject{ + ObjectID: object.objectID.EncodeToString(), + } + if object.ecHeader != nil { + do.ECIndex = &object.ecHeader.index + ecParent := object.ecHeader.parent.EncodeToString() + do.ECParentObjectID = &ecParent + } + op, ok := result.placements[object.objectID] + if !ok { + continue + } + for _, rn := range op.requiredNodes { + do.RequiredNodes = append(do.RequiredNodes, hex.EncodeToString(rn.PublicKey())) + } + for _, cn := range op.confirmedNodes { + do.ConfirmedNodes = append(do.ConfirmedNodes, hex.EncodeToString(cn.PublicKey())) + } + jsonResult.DataObjects = append(jsonResult.DataObjects, do) + } + for _, err := range result.errors { + jsonResult.Errors = append(jsonResult.Errors, err.Error()) + } + b, err := json.Marshal(jsonResult) + commonCmd.ExitOnErr(cmd, "failed to marshal json: %w", err) + cmd.Println(string(b)) } From 0144117cc97f1221f7f018c84c0203b5a5ba9400 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 8 May 2024 10:02:54 +0300 Subject: [PATCH 0547/1413] [#1125] objectSvc: Add EC header APE check Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 5 +- pkg/core/object/sender_classifier.go | 10 +- pkg/services/object/ape/checker.go | 22 +-- pkg/services/object/ape/checker_test.go | 169 +++++++++++++++++++++++- pkg/services/object/ape/request.go | 66 ++++++++- pkg/services/object/ape/service.go | 23 +++- 6 files changed, 272 insertions(+), 23 deletions(-) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index a7a084fd1c..833daf6283 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -445,8 +445,11 @@ func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *object c.log, objectAPE.NewChecker( c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.chainRouter, - objectAPE.NewStorageEngineHeaderProvider(c.cfgObject.cfgLocalStorage.localStorage), + objectAPE.NewStorageEngineHeaderProvider(c.cfgObject.cfgLocalStorage.localStorage, c.cfgObject.getSvc), c.shared.frostfsidClient, + c.netMapSource, + c.cfgObject.cnrSource, + c.binPublicKey, ), splitSvc, ) diff --git a/pkg/core/object/sender_classifier.go b/pkg/core/object/sender_classifier.go index ac881431e7..13d0ebfb1c 100644 --- a/pkg/core/object/sender_classifier.go +++ b/pkg/core/object/sender_classifier.go @@ -122,7 +122,7 @@ func (c SenderClassifier) isContainerKey( return false, err } - in, err := lookupKeyInContainer(nm, owner, idCnr, cnr) + in, err := LookupKeyInContainer(nm, owner, idCnr, cnr) if err != nil { return false, err } else if in { @@ -136,12 +136,12 @@ func (c SenderClassifier) isContainerKey( return false, err } - return lookupKeyInContainer(nm, owner, idCnr, cnr) + return LookupKeyInContainer(nm, owner, idCnr, cnr) } -func lookupKeyInContainer( +func LookupKeyInContainer( nm *netmap.NetMap, - owner, idCnr []byte, + pkey, idCnr []byte, cnr container.Container, ) (bool, error) { cnrVectors, err := nm.ContainerNodes(cnr.PlacementPolicy(), idCnr) @@ -151,7 +151,7 @@ func lookupKeyInContainer( for i := range cnrVectors { for j := range cnrVectors[i] { - if bytes.Equal(cnrVectors[i][j].PublicKey(), owner) { + if bytes.Equal(cnrVectors[i][j].PublicKey(), pkey) { return true, nil } } diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index e74b053799..c39f922f79 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -6,7 +6,9 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -17,20 +19,22 @@ import ( ) type checkerImpl struct { - chainRouter policyengine.ChainRouter - - headerProvider HeaderProvider - + chainRouter policyengine.ChainRouter + headerProvider HeaderProvider frostFSIDClient frostfsidcore.SubjectProvider + nm netmap.Source + cnrSource container.Source + nodePK []byte } -func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider) Checker { +func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider, nm netmap.Source, cnrSource container.Source, nodePK []byte) Checker { return &checkerImpl{ - chainRouter: chainRouter, - - headerProvider: headerProvider, - + chainRouter: chainRouter, + headerProvider: headerProvider, frostFSIDClient: frostFSIDClient, + nm: nm, + cnrSource: cnrSource, + nodePK: nodePK, } } diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index c591bc4947..b5f0644282 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -3,15 +3,22 @@ package ape import ( "context" "encoding/hex" + "errors" "fmt" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -36,7 +43,7 @@ func (h *headerProviderMock) addHeader(c cid.ID, o oid.ID, header *objectSDK.Obj h.m[addr] = header } -func (h *headerProviderMock) GetHeader(_ context.Context, c cid.ID, o oid.ID) (*objectSDK.Object, error) { +func (h *headerProviderMock) GetHeader(_ context.Context, c cid.ID, o oid.ID, _ bool) (*objectSDK.Object, error) { var addr oid.Address addr.SetContainer(c) addr.SetObject(o) @@ -404,7 +411,7 @@ func TestAPECheck(t *testing.T) { router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) - checker := NewChecker(router, headerProvider, frostfsidProvider) + checker := NewChecker(router, headerProvider, frostfsidProvider, nil, nil, nil) prm := Prm{ Method: method, @@ -436,3 +443,161 @@ func TestAPECheck(t *testing.T) { }) } } + +type netmapStub struct { + netmaps map[uint64]*netmapSDK.NetMap + currentEpoch uint64 +} + +func (s *netmapStub) GetNetMap(diff uint64) (*netmapSDK.NetMap, error) { + if diff >= s.currentEpoch { + return nil, errors.New("invalid diff") + } + return s.GetNetMapByEpoch(s.currentEpoch - diff) +} + +func (s *netmapStub) GetNetMapByEpoch(epoch uint64) (*netmapSDK.NetMap, error) { + if nm, found := s.netmaps[epoch]; found { + return nm, nil + } + return nil, errors.New("netmap not found") +} + +func (s *netmapStub) Epoch() (uint64, error) { + return s.currentEpoch, nil +} + +type testContainerSource struct { + containers map[cid.ID]*container.Container +} + +func (s *testContainerSource) Get(cnrID cid.ID) (*container.Container, error) { + if cnr, found := s.containers[cnrID]; found { + return cnr, nil + } + return nil, fmt.Errorf("container not found") +} + +func (s *testContainerSource) DeletionInfo(cid.ID) (*container.DelInfo, error) { + return nil, nil +} + +func TestPutECChunk(t *testing.T) { + headerProvider := newHeaderProviderMock() + frostfsidProvider := newFrostfsIDProviderMock(t) + + cnr := newContainerIDSDK(t, containerID) + obj := newObjectIDSDK(t, &objectID) + + ls := inmemory.NewInmemoryLocalStorage() + ms := inmemory.NewInmemoryMorphRuleChainStorage() + + ls.AddOverride(chain.Ingress, policyengine.ContainerTarget(containerID), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsOptionalOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Object: chain.ObjectResource, + Key: "attr1", + Value: "value", + }, + }, + }, + }, + MatchType: chain.MatchTypeFirstMatch, + }) + + router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) + + node1Key, err := keys.NewPrivateKey() + require.NoError(t, err) + node1 := netmapSDK.NodeInfo{} + node1.SetPublicKey(node1Key.PublicKey().Bytes()) + netmap := &netmapSDK.NetMap{} + netmap.SetEpoch(100) + netmap.SetNodes([]netmapSDK.NodeInfo{node1}) + + nm := &netmapStub{ + currentEpoch: 100, + netmaps: map[uint64]*netmapSDK.NetMap{ + 100: netmap, + }, + } + + cont := containerSDK.Container{} + cont.Init() + pp := netmapSDK.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + cont.SetPlacementPolicy(pp) + cs := &testContainerSource{ + containers: map[cid.ID]*container.Container{ + cnr: { + Value: cont, + }, + }, + } + + checker := NewChecker(router, headerProvider, frostfsidProvider, nm, cs, node1Key.PublicKey().Bytes()) + + ecParentID := oidtest.ID() + chunkHeader := newHeaderObjectSDK(cnr, obj, nil).ToV2().GetHeader() + ecHeader := object.ECHeader{ + Index: 1, + Total: 5, + Parent: &refs.ObjectID{}, + } + chunkHeader.SetEC(&ecHeader) + ecParentID.WriteToV2(ecHeader.Parent) + + parentHeader := newHeaderObjectSDK(cnr, &ecParentID, &headerObjectSDKParams{ + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "value", + }, + }, + }) + headerProvider.addHeader(cnr, ecParentID, parentHeader) + + t.Run("access denied for container node", func(t *testing.T) { + prm := Prm{ + Method: nativeschema.MethodPutObject, + Container: cnr, + Object: obj, + Role: role, + SenderKey: senderKey, + Header: chunkHeader, + SoftAPECheck: true, + } + + err = checker.CheckAPE(context.Background(), prm) + require.Error(t, err) + }) + t.Run("access allowed for non container node", func(t *testing.T) { + otherKey, err := keys.NewPrivateKey() + require.NoError(t, err) + checker = NewChecker(router, headerProvider, frostfsidProvider, nm, cs, otherKey.PublicKey().Bytes()) + prm := Prm{ + Method: nativeschema.MethodPutObject, + Container: cnr, + Object: obj, + Role: nativeschema.PropertyValueContainerRoleOthers, + SenderKey: senderKey, + Header: chunkHeader, + SoftAPECheck: true, + } + + err = checker.CheckAPE(context.Background(), prm) + require.NoError(t, err) + }) +} diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index cbecc73e3d..71a9aec2c5 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -2,11 +2,14 @@ package ape import ( "context" + "crypto/sha256" "fmt" "strconv" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -110,12 +113,12 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re if prm.Header != nil { header = prm.Header } else if prm.Object != nil && !prm.WithoutHeaderRequest { - headerObjSDK, err := c.headerProvider.GetHeader(ctx, prm.Container, *prm.Object) + headerObjSDK, err := c.headerProvider.GetHeader(ctx, prm.Container, *prm.Object, true) if err == nil { header = headerObjSDK.ToV2().GetHeader() } } - + header = c.fillHeaderWithECParent(ctx, prm, header) reqProps := map[string]string{ nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, nativeschema.PropertyKeyActorRole: prm.Role, @@ -136,6 +139,65 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re ), nil } +func (c *checkerImpl) fillHeaderWithECParent(ctx context.Context, prm Prm, header *objectV2.Header) *objectV2.Header { + if header == nil { + return header + } + if header.GetEC() == nil { + return header + } + if prm.Role == nativeschema.PropertyValueContainerRoleContainer || + prm.Role == nativeschema.PropertyValueContainerRoleIR { + return header + } + parentObjRefID := header.GetEC().Parent + if parentObjRefID == nil { + return header + } + var parentObjID oid.ID + if err := parentObjID.ReadFromV2(*parentObjRefID); err != nil { + return header + } + // only container node have access to collect parent object + contNode, err := c.currentNodeIsContainerNode(prm.Container) + if err != nil || !contNode { + return header + } + parentObj, err := c.headerProvider.GetHeader(ctx, prm.Container, parentObjID, false) + if err != nil { + return header + } + return parentObj.ToV2().GetHeader() +} + +func (c *checkerImpl) currentNodeIsContainerNode(cnrID cid.ID) (bool, error) { + cnr, err := c.cnrSource.Get(cnrID) + if err != nil { + return false, err + } + + nm, err := netmap.GetLatestNetworkMap(c.nm) + if err != nil { + return false, err + } + idCnr := make([]byte, sha256.Size) + cnrID.Encode(idCnr) + + in, err := object.LookupKeyInContainer(nm, c.nodePK, idCnr, cnr.Value) + if err != nil { + return false, err + } else if in { + return true, nil + } + + nm, err = netmap.GetPreviousNetworkMap(c.nm) + if err != nil { + return false, err + } + + return object.LookupKeyInContainer(nm, c.nodePK, idCnr, cnr.Value) +} + // fillWithUserClaimTags fills ape request properties with user claim tags getting them from frostfsid contract by actor public key. func (c *checkerImpl) fillWithUserClaimTags(reqProps map[string]string, prm Prm) (map[string]string, error) { if reqProps == nil { diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 95f36be79a..63c2a99091 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -10,6 +10,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" + getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -31,23 +33,36 @@ type Service struct { var _ objectSvc.ServiceServer = (*Service)(nil) type HeaderProvider interface { - GetHeader(ctx context.Context, cnr cid.ID, oid oid.ID) (*objectSDK.Object, error) + GetHeader(ctx context.Context, cnr cid.ID, oid oid.ID, local bool) (*objectSDK.Object, error) } type storageEngineHeaderProvider struct { storageEngine *engine.StorageEngine + getSvc *getsvc.Service } -func (p storageEngineHeaderProvider) GetHeader(ctx context.Context, cnr cid.ID, objID oid.ID) (*objectSDK.Object, error) { +func (p storageEngineHeaderProvider) GetHeader(ctx context.Context, cnr cid.ID, objID oid.ID, local bool) (*objectSDK.Object, error) { var addr oid.Address addr.SetContainer(cnr) addr.SetObject(objID) - return engine.Head(ctx, p.storageEngine, addr) + if local { + return engine.Head(ctx, p.storageEngine, addr) + } + w := getsvc.NewSimpleObjectWriter() + var headPrm getsvc.HeadPrm + headPrm.WithAddress(addr) + headPrm.SetHeaderWriter(w) + headPrm.SetCommonParameters(&util.CommonPrm{}) // default values are ok + if err := p.getSvc.Head(ctx, headPrm); err != nil { + return nil, err + } + return w.Object(), nil } -func NewStorageEngineHeaderProvider(e *engine.StorageEngine) HeaderProvider { +func NewStorageEngineHeaderProvider(e *engine.StorageEngine, s *getsvc.Service) HeaderProvider { return storageEngineHeaderProvider{ storageEngine: e, + getSvc: s, } } From 74135776c744ef10da22c53cf57107b035b686a2 Mon Sep 17 00:00:00 2001 From: Anoke Date: Wed, 8 May 2024 01:08:50 +0300 Subject: [PATCH 0548/1413] [#1067] adm: Fix panic on negative value Signed-off-by: Anoke --- cmd/frostfs-adm/internal/modules/morph/policy/policy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go index a11ca2704f..5ab05e4295 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go @@ -48,7 +48,7 @@ func SetPolicyCmd(cmd *cobra.Command, args []string) error { value, err := strconv.ParseUint(v, 10, 32) if err != nil { - return fmt.Errorf("can't parse parameter value '%s': %w", args[1], err) + return fmt.Errorf("can't parse parameter value '%s': %w", args[i], err) } emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value)) From 20baf6e112e8e91a06a372c78e0f4d5604f2b282 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Fri, 26 Apr 2024 17:27:56 +0300 Subject: [PATCH 0549/1413] [#1108] ape: Update policy-engine version for listing by iteration * Update go.mod with a new version of policy-engine pacakge. * Adapt SwitchRPCGuardedActor to ContractStorage interface. * Fix `frostfs-adm` util. Signed-off-by: Airat Arifullin --- .../internal/modules/morph/ape/ape_util.go | 17 ++++++++++++++++- .../internal/modules/morph/helper/actor.go | 18 ++++++++++++------ go.mod | 4 ++-- go.sum | 8 ++++---- pkg/morph/client/actor.go | 10 ++++++++++ pkg/morph/client/client.go | 7 +++++++ 6 files changed, 51 insertions(+), 13 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 42307e78fb..dfa7c63924 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -98,6 +98,16 @@ func parseChainName(cmd *cobra.Command) apechain.Name { return apeChainName } +// invokerAdapter adapats invoker.Invoker to ContractStorageInvoker interface. +type invokerAdapter struct { + *invoker.Invoker + rpcActor invoker.RPCInvoke +} + +func (n *invokerAdapter) GetRPCInvoker() invoker.RPCInvoke { + return n.rpcActor +} + func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorageReader, *invoker.Invoker) { c, err := helper.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) @@ -111,7 +121,12 @@ func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorag ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) - return morph.NewContractStorageReader(inv, ch), inv + invokerAdapter := &invokerAdapter{ + Invoker: inv, + rpcActor: c, + } + + return morph.NewContractStorageReader(invokerAdapter, ch), inv } func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *helper.LocalActor) { diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go index f920aa5ba0..1ca246f9f8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go @@ -23,9 +23,10 @@ import ( // LocalActor is a kludge, do not use it outside of the morph commands. type LocalActor struct { - neoActor *actor.Actor - accounts []*wallet.Account - Invoker *invoker.Invoker + neoActor *actor.Actor + accounts []*wallet.Account + Invoker *invoker.Invoker + rpcInvoker invoker.RPCInvoke } // NewLocalActor create LocalActor with accounts form provided wallets. @@ -68,9 +69,10 @@ func NewLocalActor(cmd *cobra.Command, c actor.RPCActor) (*LocalActor, error) { } } return &LocalActor{ - neoActor: act, - accounts: accounts, - Invoker: &act.Invoker, + neoActor: act, + accounts: accounts, + Invoker: &act.Invoker, + rpcInvoker: c, }, nil } @@ -167,3 +169,7 @@ func (a *LocalActor) MakeUnsignedRun(_ []byte, _ []transaction.Attribute) (*tran func (a *LocalActor) MakeCall(_ util.Uint160, _ string, _ ...any) (*transaction.Transaction, error) { panic("unimplemented") } + +func (a *LocalActor) GetRPCInvoker() invoker.RPCInvoke { + return a.rpcInvoker +} diff --git a/go.mod b/go.mod index 08a59581d7..142ce02ccf 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,11 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f - git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12 git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240426062043-c5397286410f git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 6200022c71..241e25d8fc 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f h1:YyjsQNtrngQzIKOUtApXoi5r5pewatM+cXfpY19vZWo= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0 h1:FzurjElUwC7InY9v5rzXReKbfBL5yRJKSWJPq6BKhH0= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.0/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 h1:Tp4I+XOLp3VCJORfxSamQtj3RZNISbaLM4WD5iIzXxg= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= @@ -12,8 +12,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12/go.mod h1:e7H9nNFpx1Tj3R20Zoxy0Vo6Srlb6zV5L7ZQXqg9rn4= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a h1:wbndKvHbwDQiSMQWL75RxiTZCeUyCi7NUj1lsfdAGkc= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240412130734-0e69e485115a/go.mod h1:H/AW85RtYxVTbcgwHW76DqXeKlsiCIOeNXHPqyDBrfQ= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240426062043-c5397286410f h1:z+AqVpjWIZVh91eIt+lBTK1AwWtj2EBv+YE2PJKvvuk= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240426062043-c5397286410f/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/pkg/morph/client/actor.go b/pkg/morph/client/actor.go index 8c283a6725..b6718dea5a 100644 --- a/pkg/morph/client/actor.go +++ b/pkg/morph/client/actor.go @@ -6,12 +6,14 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) type actorProvider interface { GetActor() *actor.Actor + GetRPCActor() actor.RPCActor } // Client switches an established connection with neo-go if it is broken. @@ -132,3 +134,11 @@ func (a *SwitchRPCGuardedActor) TerminateSession(sessionID uuid.UUID) error { func (a *SwitchRPCGuardedActor) TraverseIterator(sessionID uuid.UUID, iterator *result.Iterator, num int) ([]stackitem.Item, error) { return a.actorProvider.GetActor().TraverseIterator(sessionID, iterator, num) } + +func (a *SwitchRPCGuardedActor) GetRPCActor() actor.RPCActor { + return a.actorProvider.GetRPCActor() +} + +func (a *SwitchRPCGuardedActor) GetRPCInvoker() invoker.RPCInvoke { + return a.actorProvider.GetRPCActor() +} diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 2570bc2c92..c9f819f042 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -579,3 +579,10 @@ func (c *Client) GetActor() *actor.Actor { return c.rpcActor } + +func (c *Client) GetRPCActor() actor.RPCActor { + c.switchLock.RLock() + defer c.switchLock.RUnlock() + + return c.client +} From 952d13cd2b078dad97bdd38a71896eefe9de0d99 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 14 May 2024 12:23:26 +0300 Subject: [PATCH 0550/1413] [#1124] cli: Improve APE rule parsing * Make APE rule parser to read condition's kind in unambiguous using lexemes `ResourceCondition`, `RequestCondition` instead confusing `Object.Request`, `Object.Resource`. * Fix unit-tests. Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 2 +- cmd/frostfs-cli/modules/util/ape.go | 58 ++++----- cmd/frostfs-cli/modules/util/ape_test.go | 60 ++++----- go.mod | 2 +- go.sum | 4 +- internal/ape/converter.go | 12 +- pkg/services/container/ape_test.go | 128 ++++++++++---------- pkg/services/object/ape/checker_test.go | 32 ++--- 8 files changed, 151 insertions(+), 147 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 45b36bfb18..a22d0525df 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -24,7 +24,7 @@ var addRuleCmd = &cobra.Command{ Long: "Add local APE rule to a node with following format:\n[:action_detail] [ ...] ", Example: `control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --rule "allow Object.Get *" --rule "deny Object.Get EbxzAdz5LB4uqxuz6crWKAumBNtZyK2rKsqQP7TdZvwr/*" ---rule "deny:QuotaLimitReached Object.Put Object.Resource:Department=HR *" +--rule "deny:QuotaLimitReached Object.Put ResourceCondition:Department=HR *" control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid ... --path some_chain.json `, diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index d2dd0ced24..50253b366e 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -21,7 +21,7 @@ var ( errUnknownAction = errors.New("action is not recognized") errUnknownBinaryOperator = errors.New("binary operator is not recognized") errUnknownCondObjectType = errors.New("condition object type is not recognized") - errMixedTypesInRule = errors.New("found mixed type of actions and conditions in rule") + errMixedTypesInRule = errors.New("found mixed type of actions in rule") errNoActionsInRule = errors.New("there are no actions in rule") errUnsupportedResourceFormat = errors.New("unsupported resource format") errFailedToParseAllAny = errors.New("any/all is not parsed") @@ -38,10 +38,10 @@ func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) { cmd.Println("\tConditions:") for _, c := range rule.Condition { var ot string - switch c.Object { - case apechain.ObjectResource: + switch c.Kind { + case apechain.KindResource: ot = "Resource" - case apechain.ObjectRequest: + case apechain.KindRequest: ot = "Request" default: panic("unknown object type") @@ -100,9 +100,9 @@ func ParseAPEChain(chain *apechain.Chain, rules []string) error { // deny Object.Put * // deny:QuotaLimitReached Object.Put * // allow Object.Put * -// allow Object.Get Object.Resource:Department=HR Object.Request:Actor=ownerA * -// allow Object.Get any Object.Resource:Department=HR Object.Request:Actor=ownerA * -// allow Object.Get all Object.Resource:Department=HR Object.Request:Actor=ownerA * +// allow Object.Get ResourceCondition:Department=HR RequestCondition:Actor=ownerA * +// allow Object.Get any ResourceCondition:Department=HR RequestCondition:Actor=ownerA * +// allow Object.Get all ResourceCondition:Department=HR RequestCondition:Actor=ownerA * // allow Object.* * // allow Container.* * // @@ -138,7 +138,9 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { return err } - var isObject *bool + var objectTargeted bool + var containerTargeted bool + for i, lexeme := range lexemes[1:] { anyExpr, anyErr := parseAnyAll(lexeme) if anyErr == nil { @@ -156,23 +158,30 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error { lexemes = lexemes[i+1:] break } - actionType = condition.Object == apechain.ObjectResource || condition.Object == apechain.ObjectRequest r.Condition = append(r.Condition, *condition) } else { + if actionType { + objectTargeted = true + } else { + containerTargeted = true + } + if objectTargeted && containerTargeted { + // Actually, APE chain allows to define rules for several resources, for example, if + // chain target is namespace, but the parser primitevly compiles verbs, + // conditions and resources in one rule. So, for the parser, one rule relates only to + // one resource type - object or container. + return errMixedTypesInRule + } + r.Actions.Names = append(r.Actions.Names, names...) } - if isObject == nil { - isObject = &actionType - } else if actionType != *isObject { - return errMixedTypesInRule - } } r.Actions.Names = unique(r.Actions.Names) if len(r.Actions.Names) == 0 { return fmt.Errorf("%w:%w", err, errNoActionsInRule) } for _, lexeme := range lexemes { - resource, errRes := parseResource(lexeme, *isObject) + resource, errRes := parseResource(lexeme, objectTargeted) if errRes != nil { return fmt.Errorf("%w:%w", err, errRes) } @@ -308,32 +317,27 @@ func parseResource(lexeme string, isObj bool) (string, error) { } const ( - ObjectResource = "object.resource" - ObjectRequest = "object.request" - - ContainerResource = "container.resource" - ContainerRequest = "container.request" + ResourceCondition = "resourcecondition" + RequestCondition = "requestcondition" ) -var typeToCondObject = map[string]apechain.ObjectType{ - ObjectResource: apechain.ObjectResource, - ObjectRequest: apechain.ObjectRequest, - ContainerResource: apechain.ContainerResource, - ContainerRequest: apechain.ContainerRequest, +var typeToCondKindType = map[string]apechain.ConditionKindType{ + ResourceCondition: apechain.KindResource, + RequestCondition: apechain.KindRequest, } func parseCondition(lexeme string) (*apechain.Condition, error) { typ, expression, found := strings.Cut(lexeme, ":") typ = strings.ToLower(typ) - objType, ok := typeToCondObject[typ] + condKindType, ok := typeToCondKindType[typ] if ok { if !found { return nil, fmt.Errorf("%w: %s", errInvalidConditionFormat, lexeme) } var cond apechain.Condition - cond.Object = objType + cond.Kind = condKindType lhs, rhs, binExpFound := strings.Cut(expression, "!=") if !binExpFound { diff --git a/cmd/frostfs-cli/modules/util/ape_test.go b/cmd/frostfs-cli/modules/util/ape_test.go index 3e47660989..d93210f41e 100644 --- a/cmd/frostfs-cli/modules/util/ape_test.go +++ b/cmd/frostfs-cli/modules/util/ape_test.go @@ -109,46 +109,46 @@ func TestParseAPERule(t *testing.T) { }, { name: "Valid allow rule with conditions", - rule: "allow Object.Get Object.Resource:Department=HR Object.Request:Actor!=ownerA *", + rule: "allow Object.Get ResourceCondition:Department=HR RequestCondition:Actor!=ownerA *", expectRule: policyengine.Rule{ Status: policyengine.Allow, Actions: policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatAllObjects}}, Condition: []policyengine.Condition{ { - Op: policyengine.CondStringEquals, - Object: policyengine.ObjectResource, - Key: "Department", - Value: "HR", + Op: policyengine.CondStringEquals, + Kind: policyengine.KindResource, + Key: "Department", + Value: "HR", }, { - Op: policyengine.CondStringNotEquals, - Object: policyengine.ObjectRequest, - Key: "Actor", - Value: "ownerA", + Op: policyengine.CondStringNotEquals, + Kind: policyengine.KindRequest, + Key: "Actor", + Value: "ownerA", }, }, }, }, { name: "Valid rule for object with conditions with action detail", - rule: "deny:QuotaLimitReached Object.Get Object.Resource:Department=HR Object.Request:Actor!=ownerA *", + rule: "deny:QuotaLimitReached Object.Get ResourceCondition:Department=HR RequestCondition:Actor!=ownerA *", expectRule: policyengine.Rule{ Status: policyengine.QuotaLimitReached, Actions: policyengine.Actions{Names: []string{nativeschema.MethodGetObject}}, Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatAllObjects}}, Condition: []policyengine.Condition{ { - Op: policyengine.CondStringEquals, - Object: policyengine.ObjectResource, - Key: "Department", - Value: "HR", + Op: policyengine.CondStringEquals, + Kind: policyengine.KindResource, + Key: "Department", + Value: "HR", }, { - Op: policyengine.CondStringNotEquals, - Object: policyengine.ObjectRequest, - Key: "Actor", - Value: "ownerA", + Op: policyengine.CondStringNotEquals, + Kind: policyengine.KindRequest, + Key: "Actor", + Value: "ownerA", }, }, }, @@ -170,12 +170,12 @@ func TestParseAPERule(t *testing.T) { }, { name: "Invalid rule with unknown condition binary operator", - rule: "deny Object.Put Object.Resource:Department
Date: Mon, 13 May 2024 15:46:15 +0300 Subject: [PATCH 0551/1413] [#1128] util/test: Remove unused package Signed-off-by: Evgenii Stratonikov --- pkg/util/test/keys.go | 137 ------------------------------------------ 1 file changed, 137 deletions(-) delete mode 100644 pkg/util/test/keys.go diff --git a/pkg/util/test/keys.go b/pkg/util/test/keys.go deleted file mode 100644 index d233a633a8..0000000000 --- a/pkg/util/test/keys.go +++ /dev/null @@ -1,137 +0,0 @@ -package test - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "crypto/x509" - "encoding/hex" - "testing" - - "github.com/stretchr/testify/require" -) - -// Keys is a list of test private keys in hex format. -var Keys = []string{ - "307702010104203ee1fd84dd7199925f8d32f897aaa7f2d6484aa3738e5e0abd03f8240d7c6d8ca00a06082a8648ce3d030107a1440342000475099c302b77664a2508bec1cae47903857b762c62713f190e8d99912ef76737f36191e4c0ea50e47b0e0edbae24fd6529df84f9bd63f87219df3a086efe9195", - "3077020101042035f2b425109b17b1d8f3b5c50daea1091e27d2452bce1126080bd4b98de9bb67a00a06082a8648ce3d030107a144034200045188d33a3113ac77fea0c17137e434d704283c234400b9b70bcdf4829094374abb5818767e460a94f36046ffcef44576fa59ef0e5f31fb86351c06c3d84e156c", - "30770201010420f20cd67ed4ea58307945f5e89a5e016b463fbcad610ee9a7b5e0094a780c63afa00a06082a8648ce3d030107a14403420004c4c574d1bbe7efb2feaeed99e6c03924d6d3c9ad76530437d75c07bff3ddcc0f3f7ef209b4c5156b7395dfa4479dd6aca00d8b0419c2d0ff34de73fad4515694", - "30770201010420335cd4300acc9594cc9a0b8c5b3b3148b29061d019daac1b97d0fbc884f0281ea00a06082a8648ce3d030107a14403420004563eece0b9035e679d28e2d548072773c43ce44a53cb7f30d3597052210dbb70674d8eefac71ca17b3dc6499c9167e833b2c079b2abfe87a5564c2014c6132ca", - "30770201010420063a502c7127688e152ce705f626ca75bf0b62c5106018460f1b2a0d86567546a00a06082a8648ce3d030107a14403420004f8152966ad33b3c2622bdd032f5989fbd63a9a3af34e12eefee912c37defc8801ef16cc2c16120b3359b7426a7609af8f4185a05dcd42e115ae0df0758bc4b4c", - "30770201010420714c3ae55534a1d065ea1213f40a3b276ec50c75eb37ee5934780e1a48027fa2a00a06082a8648ce3d030107a1440342000452d9fd2376f6b3bcb4706cad54ec031d95a1a70414129286c247cd2bc521f73fa8874a6a6466b9d111631645d891e3692688d19c052c244e592a742173ea8984", - "30770201010420324b97d5f2c68e402b6723c600c3a7350559cc90018f9bfce0deed3d57890916a00a06082a8648ce3d030107a1440342000451ec65b2496b1d8ece3efe68a8b57ce7bc75b4171f07fa5b26c63a27fb4f92169c1b15150a8bace13f322b554127eca12155130c0b729872935fd714df05df5e", - "3077020101042086ebcc716545e69a52a7f9a41404583e17984a20d96fafe9a98de0ac420a2f88a00a06082a8648ce3d030107a144034200045f7d63e18e6b896730f45989b7a8d00c0b86c75c2b834d903bc681833592bdcc25cf189e6ddef7b22217fd442b9825f17a985e7e2020b20188486dd53be9073e", - "3077020101042021a5b7932133e23d4ebb7a39713defd99fc94edfc909cf24722754c9077f0d61a00a06082a8648ce3d030107a14403420004d351a4c87ec3b33e62610cb3fd197962c0081bbe1b1b888bc41844f4c6df9cd3fd4637a6f35aa3d4531fecc156b1707504f37f9ef154beebc622afc29ab3f896", - "3077020101042081ef410f78e459fa110908048fc8923fe1e84d7ce75f78f32b8c114c572bfb87a00a06082a8648ce3d030107a144034200046e3859e6ab43c0f45b7891761f0da86a7b62f931f3d963efd3103924920a73b32ce5bc8f14d8fb31e63ccd336b0016eeb951323c915339ca6c4c1ebc01bbeb2b", - "307702010104209dd827fa67faf3912e981b8dbccafb6ded908957ba67cf4c5f37c07d33abb6c5a00a06082a8648ce3d030107a14403420004e5cb5ae6a1bd3861a6b233c9e13fa0183319f601d0f4e99b27461e28f473e822de395d15c1e14d29a6bd4b597547e8c5d09a7dd3a722a739bb76936c1ad43c0e", - "3077020101042005a03e332e1aff5273c52c38ec6c5a1593170ddf8d13989a8a160d894566fc6ba00a06082a8648ce3d030107a144034200045a11611542f07f2d5666de502994ef61f069674513811df42290254c26f71134100fed43ea8ecd9833be9abb42d95be8661f790c15b41ca20db5b4df4f664fb4", - "307702010104206e833f66daf44696cafc63297ff88e16ba13feefa5b6ab3b92a771ff593e96d0a00a06082a8648ce3d030107a14403420004434e0e3ec85c1edaf614f91b7e3203ab4d8e7e1c8a2042223f882fc04da7b1f77f8f2ee3b290ecfa6470a1c416a22b368d05578beb25ec31bcf60aff2e3ffcd4", - "30770201010420937c4796b9fc62fde4521c18289f0e610cf9b5ebf976be8d292bc8306cee2011a00a06082a8648ce3d030107a14403420004ba5951adddf8eb9bc5dac2c03a33584d321f902353c0aadccd3158256b294f5aa9cd5215201d74de2906630d8cefb4f298ff89caa29b5c90f9d15294f8d785bc", - "307702010104204b002204533f9b2fb035087df7f4288e496fc84e09299765de7a6cd61e6a32bca00a06082a8648ce3d030107a1440342000441abcf37a4d0962156c549de8497120b87e5e370a967188ab1d2d7abce53711dfd692a37f30018e2d14030185b16a8e0b9ca61dca82bfe6d8fc55c836355b770", - "3077020101042093ffa35f1977b170a0343986537de367f59ea5a8bd4a8fdd01c5d9700a7282dba00a06082a8648ce3d030107a144034200040e01090b297cf536740b5c0abb15afba03139b0d4b647fdd0c01d457936499c19283cf7b1aee2899923e879c97ddeffe4a1fa2bffc59d331b55982972524b45b", - "307702010104201c1a2209a2b6f445fb63b9c6469d3edc01c99bab10957f0cbe5fad2b1c548975a00a06082a8648ce3d030107a144034200040c8fd2da7bad95b6b3782c0a742476ffcb35e5bc539ea19bbccb5ed05265da3ab51ec39afd01fbee800e05ec0eb94b68854cd9c3de6ab028d011c53085ffc1b3", - "30770201010420b524d8cba99619f1f9559e2fe38b2c6d84a484d38574a92e56977f79eac8b537a00a06082a8648ce3d030107a14403420004a6d7d0db0cc0a46860fb912a7ace42c801d8d693e2678f07c3f5b9ea3cb0311169cbd96b0b9fc78f81e73d2d432b2c224d8d84380125ecc126481ee322335740", - "307702010104207681725fec424a0c75985acfb7be7baed18b43ec7a18c0b47aa757849444557ca00a06082a8648ce3d030107a14403420004bd4453efc74d7dedf442b6fc249848c461a0c636bb6a85c86a194add1f8a5fac9bf0c04ece3f233c5aba2dee0d8a2a11b6a297edae60c0bc0536454ce0b5f9dd", - "30770201010420ae43929b14666baa934684c20a03358cda860b89208824fac56b48f80920edc4a00a06082a8648ce3d030107a14403420004d706b0d86743d6052375aa5aa1a3613c87dccfe704dc85b4ed4f49a84a248a94582202927ec0c082234919f3ce6617152ba0d02497b81c61284261ce86cef905", - "3077020101042089d600f43c47ab98e00225e9b2d4a6c7ab771490f856d4679d9e1e0cca3009d0a00a06082a8648ce3d030107a144034200048515055045543e429173fc8f9f56a070bd4314b2b3005437d8504e6b6885f85101409b933e27c0de11415aee516d0d1b474088a437ece496ceb4f1c131e9ea40", - "3077020101042015518dcf888c7b241dac1c8bfa19d99f7fdba7ba37ed57d69bbbd95bb376ea4ca00a06082a8648ce3d030107a1440342000459e88d92efaa5277d60948feaa0bcd14388da00e35f9bae8282985441788f8beb2b84b71b1ae8aa24d64bb83759b80e3f05c07a791ffe10079c0e1694d74618c", - "307702010104203e840868a96e59ca10f048202cce02e51655a932ff0ac98a7b5589a8df17f580a00a06082a8648ce3d030107a14403420004f296414e914dcefd29bc8a493f8aedc683e5514a8ec5160637bee40ebaa85a421a363c8f7ce3ed113e97d2c4b6d9cd31d21698a54fce8d8e280a6be9ee4fbca9", - "30770201010420aa746067891cf005286d56d53092f77961f828bf5bf11aade18c8a458090d39aa00a06082a8648ce3d030107a144034200044af5ad2dacbb32ab795ab734d26bae6c098bd2ba9ca607542174d61b49ca3c07786aeb0c96908793a63d4f20cd370a77b7ec65e6b285c6337764e7ae3cd5fa1c", - "307702010104207135cbd831d52e778622c21ed035df9e3c6e4128de38fbf4d165a0583b5b4a29a00a06082a8648ce3d030107a1440342000412e2b9e11f288d8db60fbb00456f5969e2816a214a295d8e4d38fbacab6b0a7e0cdb8557e53d408244083f192d8a604d5b764ab44b467e34664ca82e012b60ab", - "3077020101042064b839ca26c42e2e97e94da5589db2de18597a12d6167fdfe0d20e932de747a2a00a06082a8648ce3d030107a1440342000481e90c2173b720447ae28361149598a7245ed51c3881a89353da25b8e574b8c9b2d80b2563efe5d9a0184b57af2431116c8a4ad8071ef2764ca3d3744c638401", - "30770201010420a56df8e6349520d27c36eb1e9675720c702d562842c859cd54b3d866f2cada30a00a06082a8648ce3d030107a14403420004dc08beb5b857f6da13ae1116e40a6e4e4b5aaebc8040eae0b3037c243b1c24def39de670380472df7aa98cb9e0f1132bc4afc0629d80a24c54b8ad600cb24cd4", - "30770201010420bd2dd18485a9667673b2c38c2ad51cc756a199d18fe1100acf29b647a549171ea00a06082a8648ce3d030107a1440342000422825ffe8b3416b6755a7076a7dc6f746ff29ee0a4455dceb0f3262127d51c9bb53f2c204636da8d7a09961274d7c7ba2ef3c771e83fb996ffe3f9882c530ffd", - "307702010104203058a0c8de5c6d4a5c7f64883e7d3c9f5097c8bc073cc482421e903b37123c06a00a06082a8648ce3d030107a14403420004f959705673c2f4112673e43d1d876ca71c64153abb6c9f58d1c3b3c1f8c213ee346833fb695eb533664d596a68e42150a21b405e3a08ed70af5f568275a7a79f", - "307702010104202bd9035bf38e7c4580abc377a6e9c31aa9bdaff90af2ce688eda9a532c83875ea00a06082a8648ce3d030107a14403420004918010ea3387786c6a257996ec74d7ee4e1703b3b811118f4e89fabfef7c694495191848a0d590313a0be9784644ef98e0f0f7e50fed5bee3fa48d66edbcd2b5", - "30770201010420aa055d6cbe96e1cfbe39530bc4b7a976baff53ce399956f0d8241750d3379990a00a06082a8648ce3d030107a1440342000444e8b6deda76c12320a8c5b7a48141ebf5dc9288df79a0f418ab92d82061d10118b8bce9fb200e5009a19fb0e19036762b3ef85440405f43225d6ee3350bf96c", - "30770201010420b8712525a79c7bd3df2a9dbabde1a111078a7ef30687a2efe0f0c4b4a23f2aa0a00a06082a8648ce3d030107a144034200049dc9e3d836a834f6d14ae99dfc70ad9b65c84f351c8dbc4f9b1b61c238051fb1db23e43d4b6e17803e21ebc44fe2f66742e306daa8c4ca7d79c6dd01fc1a4e4e", - "3077020101042086c18b56c4a2264b37c18a7937f026ab07ca6076eeea1ab90376492efb7875d9a00a06082a8648ce3d030107a144034200042f169311f2fae406de3c4a64fec94a22c35972281922a69e7657185997ae59fb3f69ac94295e58681cfbd263f8e6fbce144cc7925b71d90f57de3f3e10588321", - "30770201010420f58221355e1b2da73d66de482ec1edcb8597f3967d00d1356f4678fea6ad67e6a00a06082a8648ce3d030107a14403420004238cc44f02fa566e249a9697a078b9d38eba06012d54a29a430843a18df7a0a4207d704a360399db95eca591f2f81b6c50390467f293a1623b4757bdb4138101", - "30770201010420b10888a0157d524667fd575683bdcded4628a65149fde59b7340781b0cf2e36ea00a06082a8648ce3d030107a14403420004222ba11430b8719929c726aec74e8e70893e2960bc2bbee70fbaa6d88fa2a346adf0c450ea9823f0ba77d334fcd476ea036a62199338d7aa32e56c708d7a8caa", - "30770201010420edf001bd24c92e4f65789aae228223e77df71ce9bbfd7ce4d236ea3648e1f7fea00a06082a8648ce3d030107a1440342000472693c95786ab9f4e7c923338ce98bd068e28b71f84b77e7adb378c2ce2d8f1a2e13833df1afe4569367d7a4eee3abf50124299a28045a0073ea324f5ddb45ea", - "30770201010420e2649e591fc9072dd55573e41fc4ebfdf1db118951e4b7b2a98027ac9a4f7702a00a06082a8648ce3d030107a144034200046e34c9dea1836671f1ef259d7c3ee678c2f92d092af2518413fe9ba153a07ca8e9938784876e90cfa2989a00a83b1ac599c87a8d15be8001e46dfbfe018156a2", - "3077020101042069cd9b710f25613794751aed951004c888d4611aefa45abc23abff218e608290a00a06082a8648ce3d030107a14403420004dcf8ff34ab841720ff8dc08b60a14f41689e65f979a1af69b5e106f4262a2cb0947c9619e980caf20b3e7c8f15e60fc31c5b611c8a58370ba8201c9b6b932bd4", - "307702010104202898cef1944aaf90fddf433390323a02a79938568cf99f6c25bc9aa9e5cddb0aa00a06082a8648ce3d030107a1440342000491a1c20420f5005f5761419e4dcd0d9da0cf2ea4733f6d98a3d0c124f284cabdc65eafd9d2cad9b1122fca791c8b37997feed130c5725ea797cf07c61fb82734", - "30770201010420e568bd3ffa639aa418e7d5bc9e83f3f56690ebf645015ff7f0e216d76045efd5a00a06082a8648ce3d030107a144034200042424b498297124037db950bf2a1e652ba7f977363f4f69d7308531d27bf392219d93cb78f4379b7ffb16f3e7be311e208af2409bd33000fd25a8707ac6bec76b", - "307702010104205163d5d5eea4db97fccc692871f257842fdaca0eca967d29924242f7a2c56ad7a00a06082a8648ce3d030107a144034200044e2ca8312122039c3374db08851710d3b9a2efcbd8f5df004ec7b60a348aee32466f799b5957d39845f451071bb1f3bb99f25bf43196e7c772f7b84f39221b3a", - "30770201010420301eb936d2737886ab2fbf670952f9ba0d324827b81801810bfd60c89e8ca862a00a06082a8648ce3d030107a14403420004455454b1f3828a2328a8925c4c98bd6e37dece276efb3299d8b7d78c9d7e6f978b14d021c07bae0c18a623fc52ab2fec1523a89b2fd0cda373e9c9442a3545f2", - "3077020101042032c12a9bca8070c131b0a46944c17adf35eb44079f3c887fc3b93740bb9c03fca00a06082a8648ce3d030107a14403420004e61da413c4d5dbc6c004089d96a3cb55f4b20b70c544f3823a7a6322c53e134fcb8a885729ef284d68d23e0a58009d48b369f9c4f5a665a8880a48606491dd8a", - "30770201010420aa2b40742722b81c6ffd5c47b94b8be747da259e172a82d27ebc525c8f46d17aa00a06082a8648ce3d030107a14403420004f87a863ed11592cf4f96e837038b105d155f5e09a31386ab4604234e8a975d49a9612b4597b7fb206087b70a26bce4aca31edb253530e6da83ce16beefa99f60", - "307702010104202a70a0c827b4ce8d433e800ab0818b1401b220fadea75feff655251ee4317556a00a06082a8648ce3d030107a14403420004a5c9209fd53dc1ce2c873782ec507db5e0f9cc78292a84ecafc5bab16c2e4d786a882ad77ad999f3d6ba676ad80354ad376dabc4fa03a6c15ead3aa16f213bc5", - "307702010104202787d04901f48c81774171ef2e2a4d440b81f7fa1f12ab93d8e79ffab3416a1ca00a06082a8648ce3d030107a14403420004010d32df4d50343609932a923f11422e3bea5fa1319fb8ce0cc800f66aa38b3f7fda1bc17c824278734baa3d9b7f52262eeacbca21304b74ba4795b5055b1e9f", - "3077020101042032423728a897144d4fb95090ca0ac67a23eb22e2f7f925cbddaf542eeaec8faaa00a06082a8648ce3d030107a14403420004c37f9fec5b1be5b0286300ace6a5d25df8189d29604145a77b6578a4e3956ed3d9af48f8ee1e39868bba9e359e5444984f0428755e29d2012f235c9a56749148", - "30770201010420d5bd2a3867937e0b903d19113e859ca9f6497f4af082894a6911cef3a3a12d35a00a06082a8648ce3d030107a14403420004435b2e891c46023f422119f18a04c75b9322ea4aaddd10a0568438310896388bf7037e98bd5979a6f0839acb07dead1f2f973640dcc11dcee1de8a07c0b3dd80", - "30770201010420590edcf1f2b6ee6c1b836ace33b934597883a00ce84fe812a4b3e22432846972a00a06082a8648ce3d030107a14403420004183d7cad633cb0f4ab774f4dc19b9db87e7ef97b0f4d43ac395d2409dabbe5339dbad661c7c2fd05606e2edb08f8ace660f73bf5232011262d563603f61d2353", - "30770201010420a0ea4e16cf8c7c641d70aea82192fb9303aab6e7b5cd72586ba287d50f4612d6a00a06082a8648ce3d030107a1440342000482a72d31e71f0aea778cb42b324abf853cb4e4e8d4b2ae0e5130480073e911f183134c047a7e1cd41a845a38057ea51a1527923518cbf47c3e195a9f44e1d242", - "307702010104209e04b00c8d0f96ddb2fbb48cfc199905bfbfcc894acb77b56bf16a945a7c7d08a00a06082a8648ce3d030107a1440342000405efd203dcddfb66d514be0de2b35050b83e3738096cd35398165bfdbe34d34c0d96a4e6df503903c75c2c06b66b02b15cd7bf74c147d7a9f0a5e53b83c5762d", - "30770201010420aa69f1cc2cb3482a12af4b1614d6dde01216f1cad1c9f03c681daa8648b75b37a00a06082a8648ce3d030107a1440342000474ffec1297420d0cf730b42942058699d803ab618e1e40ccf9cc17f71f62b3123d863fbf8fae37b6c958892af6151159f74e2a568917bfc2f4e00c55c32b52e7", - "3077020101042090a04300e8d6ed9f44422a2cf93817604bf1f6233c4333ba0db20ab726852fa4a00a06082a8648ce3d030107a144034200049e6f2001baf2b6fb25e3273907ed7320f494de6b5882c4c4b9bcee7ddc60274e064cc68c64325c001f07a505722062d1ca9774a2cc1e0cd28fe5f807865bfcc1", - "3077020101042088945c19c6ce3e63f8d8a421616391d83bec79a0c590f1607b247ffa0c677dd3a00a06082a8648ce3d030107a1440342000492d17d410f9eabf7ae4509a92494e9fe94a72947f24e60c5bb6e12b2cde3c1bfe5305a0d759138069d44268f174136971ecb752df602c282e48d40f43a8734e3", - "3077020101042079d14eacdc4f21dc5284bd8487dcb2c22e9e53e71909474f922bf695f49cf23ea00a06082a8648ce3d030107a1440342000428039292c5bcf3593639bf5835ec9411ffd3ac236c0186697623930b5ca63f32ff41df5217e7def770d9a0de87f61526497bd9aaa95d924e0a17d85958e7c095", - "30770201010420a6ac867ff8d00aaad23198415868a64e59217b4d22474752a146fcb52204dfa5a00a06082a8648ce3d030107a14403420004a5f37a779265c55cd4f5a7f3bffc4679395898046eb9d67d8670be39001de5a7bc010b0d218561626272989c5952e8e0d95d2590f78eec44dc62a46184956301", - "30770201010420df446014577f6081113cd7d33c6ba91b9ac3d083e76f8873358f83129e2d0111a00a06082a8648ce3d030107a14403420004da0c932759f50ad705507f876138c2c6e012764abc8764a6dd609e6ad06099952b120be71690bc091591f1aa8d7d6e9365deddbc958bc87ff150358ad33f7537", - "30770201010420b3351033eaaee3a9ea27cd7dc54aa2c8d787b14b7d428165f1a04a59c6d5b0f2a00a06082a8648ce3d030107a14403420004da3984fb8152403a9fb9068b16f9afb5c900f24230e205567b4405ee3cad2db3ff46968489d494b38d0c85fcc4aecccb61fc00dca54c8fd99ee5bf5e2616f1b7", - "30770201010420deedbcef7f6821f6aab2b15ce198f5eb2064f6eb461a6b7776b4da35c81b1506a00a06082a8648ce3d030107a1440342000405422b86ce66b18e68f0fb14f28e4ed9b1f7ee84f57957f4e4b4c6b0c392e6357e4698fb707f590be1b915622ec8da476071a56919211f6e5e888284d4e33f06", - "3077020101042078c3db0d3b1114cb99f1d0bea0d3aec9067b26964e2b85fe9df4789b24cb3da5a00a06082a8648ce3d030107a144034200046874e52d7d58b6697b407b0c0eea3cfeb528e34fca1589c5031e11aae1ad1f9280e7a4c37ddf28479cd07b4246ce9398e0e24f99946f87e08532fa26b8fb8016", - "30770201010420f0ba42553b146cf088d3a5a3645782fe675d23561897ced7f1270a8d05cfdaaaa00a06082a8648ce3d030107a14403420004c250e12f3aa1fb6261c57cdb091cd90d82917e103711425888477b9da4359d2803aaf0015638294c7c0baa4ec77ba8fceff5ee7f15ea087a4174f58d518006dd", - "307702010104207f2c0fc4b0e418b2d4c72a63fdc27f158f6ad44c26d161f489714525b6a13db1a00a06082a8648ce3d030107a144034200041d83885672021e783d8bd995d187f407bbda2c6bed5e8fabc7c6c5cb304a85eaffa12dad7ba874ac45f4258fffe07534843ff7fe76075470f2c77104d781688f", - "30770201010420d3de828ac9742704d4e6981ce1fc8c473e508eda3a121cda420dacbdf39d48e9a00a06082a8648ce3d030107a14403420004c78abfc4a5c0eb3ee0c9817d1790b7ca9fd528d0bc727f9daf63f4212097538b6888b9de2ae4dff29895500be456fe0ccbee340aecb546d1558b08c3718aaa4a", - "30770201010420d9c4e477b56f2ff0b211acd82b450336276534b350747315152a4923e6e65294a00a06082a8648ce3d030107a14403420004fbd540966b03fe2c2314f20248d345e3e9b92d6a7cfea22d1b5367f01b32d616f317e00cea1f659437b4302610abba8abb0f2bfce0a91b952e9565159c1e464e", - "30770201010420fb84f4a426fa12920c2cf7c2d821280530c0fa93960ded8c20120511dc1d5069a00a06082a8648ce3d030107a14403420004c0177f13c6e00bb9029df089006a332192bdf12a782c60a8d00d110c53db67c344584f22677695a7f1629db1600b0559ced49ac931b08cc6a58e5ea436bde2f8", - "30770201010420653ce060214028f7aa584910f0925d702bde18d52d8e530f07dd5004076eb614a00a06082a8648ce3d030107a1440342000433668d0c9085feae4b285fe260a316e24f24c0bb8e442583e23284bf5a962cd0357cd63ac4d1cdda58afb201bceee911ebe7cf134652dc4390f4e328f6cb5d65", - "307702010104206123b7d5b8c53b2a2a95dd2e42fe550617b7520fe9bd94a99045addb828ad847a00a06082a8648ce3d030107a1440342000487c10fdeaabf8072dcea0dc5b18be4d72f2b8298bc891ea0a11d202438b7598ac588f16a9cd697f8220434d4e15ff4c82daaae63955525633335843069434aea", - "3077020101042000b793c9b8553ee7bec21cd966f5aaff59a07d1fa3fa86e0164bcd2f7f4dd586a00a06082a8648ce3d030107a1440342000419d4179dbeae7fa87e356f0406c327239d34e540cd7db5174a81bd6197738bc72e46fe4bd1512dc4b35950b2c1e78e6f8f54980193be78d45e4d97a837455777", - "307702010104200fb1a771004f6be6300eccd603b9c9e269fbdd69e5eb183d7acad51b0b205b88a00a06082a8648ce3d030107a14403420004d3b7fa62bacff49714ef28a955cdc30f4aef323293ac3aebab824892dfa3306f2ec319f5bca1771b956b4a9b1c2f565dc08b29c07ec84623932a5d6fb59be6c7", - "30770201010420fe6907b91407619fdc95153cd59df061e88095678801008d3901f29c7c434243a00a06082a8648ce3d030107a14403420004796fcea7889128f8060b04e9000381fd3d80fe68f000063b182fe9d8984e740c387c4ed4c6729e8c715c576fe355a9b7dda6890c55b15ae6013fd51e8858b2f2", - "30770201010420111eaff6db3b279d014b45b3da091909f054f37c350c237fe9d51b4342811299a00a06082a8648ce3d030107a144034200047d51f9178725c4134579ac6d0cb84745e0d2068ccf72d30c02dd431547f868d1cb93b5774c7e1eb9582e2151521ff16cdf80b3ba4646d64f7982066f9eb679f0", - "30770201010420631d01e6aaa68e6c36e3425b984df02bc5b54e81951479f7cea8fd1b804bab57a00a06082a8648ce3d030107a14403420004fa1b1ed9ff904f1f050577e05b5175e897d462598fdd323c8ef25f6072dfa43034baa0119e64092fb44f7a04d59d16ba8645f52cfb7775a6536c00f7fc2ee2f1", - "307702010104201ec553d14d45acdf147dba5fcbc3a42a1f763411d5c206d03600ed810b0cf106a00a06082a8648ce3d030107a14403420004e9a309a24d1061204087de10e5bc64b6d45369399a5a402d630ca2d04b34ae9d27d491e5fadd5d082e14454e6b2a572a24904ba2a8dc7430b20d361134188589", - "307702010104206d31e401bb20968106a058f8df70cd5fb8e9aaca0b01a176649712aa594ff600a00a06082a8648ce3d030107a144034200048555a2f9e7256c57b406c729d2d8da12c009f219e81cecb522cb3c494dcc1c76ac6d2f641dafe816065482fb88916e1a719672c82406556e16c32cf90752a92f", - "307702010104208ada3d6ea6000cecbfcc3eafc5d1b0674fabece2b4ed8e9192200021b8861da0a00a06082a8648ce3d030107a14403420004a99e7ed75a2e28e30d8bad1a779f2a48bded02db32b22715c804d8eeadfbf453d063f099874cb170a10d613f6b6b3be0dbdb44c79fc34f81f68aeff570193e78", - "30770201010420d066dfb8f6ba957e19656d5b2362df0fb27075836ec7141ce344f76aa364c3cea00a06082a8648ce3d030107a14403420004597fd2183c21f6d04fa686e813cf7f838594e2e9c95b86ce34b8871674d78cc685b0918fd623e3019d8c7b67104395b1f94fc3338d0772e306572236bab59c39", - "307702010104202c291b04d43060f4c2fd896b7a9b6b4f847fb590f6774b78a0dff2513b32f55ca00a06082a8648ce3d030107a14403420004e80bd7e6445ee6947616e235f59bbecbaa0a49737be3b969363ee8d3cfccbbc42a0a1282de0f27c135c34afad7e5c563c674e3d18f8abcad4a73c8c79dad3efa", - "3077020101042029af306b5c8e677768355076ba86113411023024189e687d8b9c4dee12f156fda00a06082a8648ce3d030107a144034200049d7d21e6e1e586b5868853a3751618de597241215fb2328331d2f273299a11295fe6ccd5d990bf33cf0cdcda9944bf34094d5ffa4e5512ee4a55c9f5a8c25294", - "3077020101042022e65c9fc484173b9c931261d54d2cf34b70deccb19ce0a84ce3b08bc2e0648ba00a06082a8648ce3d030107a14403420004ea9ee4ab7475ebaff6ea2a290fc77aafa4b893447d1a033f40400b4d62ee923a31d06fe5f28dbc2ebec467ebd2e002a9ea72057f0b0c60fe564584a6539376ad", - "307702010104205000583dc21cb6fd26df1c7d6e4efb9b47ceff73c0d94ed453bae0c13a9e5795a00a06082a8648ce3d030107a144034200045a6a5b5886b01f54dfa0788f15d3542aec160843a57e723008d1b984dd572ecb8935662daaba53d756d45442efbae067f52b0b151899a645afb663205babddd3", - "30770201010420997431e73eae00f476bb1a221b4cc9dfd18d787be207b7069141627f61ba752da00a06082a8648ce3d030107a144034200047c89dc8c46a27e20c37b0ecf1150e8b92c2dd4dc534a25545f87a5f0c44fdbf4dee2af5bcdc4012f0acee168aeb55bb4d24738fac105fc056928ff5870491047", - "307702010104207dc10db95a597a80e916d7f8e4e419b609d767538fe9732bcc5f9d783c605a2ba00a06082a8648ce3d030107a144034200042e2ae4fae087a11fcdf9565670164c229337ed87b5056687c6bceeb84108db9a88b9e5d96a0cf121255ceefce0bb5239608768bb841e6687dbd9626222eb5187", - "307702010104209056e22b347f5f1839f1a53f1250d098616ff04db0b49b1fddb18b987930cec7a00a06082a8648ce3d030107a1440342000427cc4c7fb5d7ac047161aee78e812ad264ba25dd878684637308674ea693817b20a5e3672de6a92dfbf82f641268052fa742e6f35ff91c617334f09f89bd1218", - "30770201010420554ea6cfeb2cc4f1e29c08e65317d72731ee03940af9ff6a141b761d5d054db6a00a06082a8648ce3d030107a14403420004a6121746c0553ede0944da8a7f304831fcefb51b40acf78016d41cc45cc5f7e9a1b22bbea028daab5cb4c39cadf84da442749cbfc04536d6f85c3254ec7a0805", - "30770201010420f53ff1c7db3c4e7c734bf7396a1a5364ac2dfe4b794b118aada6bab72cde8969a00a06082a8648ce3d030107a1440342000414b11ec158e3f9d558bd1da1ed0e38c92b1ad55834f3ce08e456747279dd9ed1143cff4f5e8d70189f4b114e3cd609105d6eb8f431f392487e4c9e16a152dba1", - "30770201010420b3f394090547f5dcb2e77cef65e03a3b7d1c953cd0e069553da2795ab0adc950a00a06082a8648ce3d030107a14403420004a1a9dbe5d6dfa2dfb039aebabe96b12faf97c994e1430323d074ecbd90ef075e0fe9dc7d5eef2483d485ffb0b4a01b01e131754fb38059a1365d342d5175397a", - "30770201010420bf13c42fa84c409161f9d73ce20fd85b20c5381914aa2a2375452b34cd352022a00a06082a8648ce3d030107a14403420004e0134214a5349a235cee406ad942ca105ef871a7e4c922ef4769466d8495c78b82f6c49270c8cd913e0cf407cdab679dd9914090ea91122ca9fb654ebcfce57d", - "30770201010420440d975b65bf585d0813137fe041461de59221856eaf255479b5e69721cfb30da00a06082a8648ce3d030107a14403420004935a9626ddb7bd6fbcd2ad9d9333851bbc64b9997cb8e43b1a17f8e9968ed6b0e5d2edf105fbabc9bd745fa2120ac527bbfefb6e8ed96844f80b8e27b6d9a549", - "307702010104209ea2dc59260408165d6c42205aa52e275f81c39d9bf5b1b9c8187ade875e8068a00a06082a8648ce3d030107a14403420004bc570aa24df0306cb761ee9fb22e61f59ae4f11e8804491d8651084f191c800d1e6b16e4bc3693b88f9bef82849f3cd6914a15cae60322c1f4822a2bdf426782", - "30770201010420505b596fb71a2e36c0ba07da03442a721f3f1832dcac19631d6c11b36ab81986a00a06082a8648ce3d030107a1440342000472cfb26cf07faa4e6e9d328214677b5eb51cd2e35717ac661d732115e592a07482bf966a31792cc993bdf816a732069ed423871b53fb3c7eabab2f4d3d272013", - "3077020101042089a9d5b397c521db4bb4a5f3e8f2043e43bb5617a2070e7bfa30dd2dbf1815a1a00a06082a8648ce3d030107a1440342000468d2aeaf641b839095644cfd4b72ab97d0bf3fae1ed36e9f81d9aff333b0123f7b846f6ca61dbbd4e10988e740463addef793994a1498987883ecf237f18bc40", - "307702010104200919a89aedb4e20cfcd2cb568c8de18b1b60b5da17aaea3be9804eb5bc3280f5a00a06082a8648ce3d030107a14403420004139812ec6bd62fd3ce71040d87cc07671948ff82300fae5f3af80dcd4e22c870c0102c4add460b2cbbeeb298f58037fc645da20aa8f5531a5ff56d3e5b2d1944", - "30770201010420b145fc69cfabff378f390f0a99fb98ddc8ba9228cb1adf9c7099c6393a24567aa00a06082a8648ce3d030107a14403420004b660084cb05e005fb163011663fee6946f354714565069968f16e89e9a7aac45610f05502ff9d9e3cd0fdc88083bd8840a518b71135e59a0f0f235636d5eb7c4", - "3077020101042082d39168f289e784ace49bfdd523297b524c494f83fe7d04dd2f055b48d636b9a00a06082a8648ce3d030107a14403420004ea4021da5eec4e7f333059625ecbad3969676cf625cbf0da316f55f50ccd40e6174fdb7023c07abdb3ca91203acbcb5e78e1601f1a9aa616c5019ac5b2222ff4", - "3077020101042066a1ebc23e993674bfdc3b9721c280b7f3c1599903063ea7899b848b942a6169a00a06082a8648ce3d030107a144034200046bdb182c6c0c1f9ea898c3847bc4b46014cb8da6a02d75b7bed3c4a9a4e9c8836d4ce22fe68b68ae56a91fb435c7ea8f05bca8e8fcb1d6b77770d419f99e51da", - "30770201010420fa2cda21b761c46fcc5b54d47b045e24affdb95425e859bb367a07950119ab6ba00a06082a8648ce3d030107a144034200044b9e4cee102ad23fea3357f8f5f95ab9d60d34086ba4b39d5f37cbc61998ac9658ec56033ad72977d41e449d449f5aac2bc653ea8038fc04a011ff02ec49e088", - "3077020101042028acfb3c41b7be1d9d0506ac3702c363ffd767dd738dc8ab581ad7add2ec8872a00a06082a8648ce3d030107a144034200047467dedfb8c9a7d9496d4898d6ace0fba063545ab0d345d8b63b90871927ed269645a745a7335ca511d86a366f24e7832477842b4041a9ab564c5fbce49e4df8", - "307702010104202e57b8b867bd95a8dfcdd2cb8f82ea41bff21610019afd6e2367e755dec5b944a00a06082a8648ce3d030107a144034200048f97eb2d6ee2d3da8746d8d4f84469ea765fb0d1412b167b6d8a916b5f968b4d64ede5ea6d6e08ec0de192262fcb3ebed49e9d17858261affed84827b38c6cc9", - "3077020101042021a904281e4c31386ce34a5b52af3a068caa65819fbcf0ca76ab6041ecdaf454a00a06082a8648ce3d030107a1440342000405f9b7894a97fcddfc3285b8e974718606616fe07c70b7ab2bfb28a85fb3014c2610ab9e8e6da8ae3da032837d3a14b1e791d2633bdd8551b4817a080b9aa697", - "3077020101042089c2c73d08bd03da4c3111aa0b78bb1edc5243d8e119513035d3741e851dec1ca00a06082a8648ce3d030107a14403420004ec9ebc34f45150334fd1d8c92274fe43c5b3b059f15cb1963f6cf7d54bc6b1b0b4ef1c5d56d2d06ab54ce2e7606e0fa5d2f188a2d593b22d9cf6a0098aa00cb6", -} - -// DecodeKey creates a test private key. -func DecodeKey(t testing.TB, i int) *ecdsa.PrivateKey { - if i < 0 { - key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - require.NoError(t, err, "could not generate uniq key") - - return key - } - - if current, size := i, len(Keys); current >= size { - t.Fatalf("add more test keys, used %d from %d", current, size) - } - - buf, err := hex.DecodeString(Keys[i]) - require.NoError(t, err, "could not to decode hex string") - - key, err := x509.ParseECPrivateKey(buf) - require.NoError(t, err, "could not to parse ec private key") - return key -} From 6e71ae3bda05fbfc6404dc72b10de6ce1926e0a7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 14 May 2024 16:04:09 +0300 Subject: [PATCH 0552/1413] [#1130] fstree: Remove useless Stat() call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ old │ new │ │ sec/op │ sec/op vs base │ SubstorageReadPerf/fstree_nosync-seq100-8 2.689µ ± 2% 2.428µ ± 4% -9.72% (p=0.000 n=10) SubstorageReadPerf/fstree_nosync-rand100-8 2.727µ ± 1% 2.497µ ± 2% -8.42% (p=0.000 n=10) geomean 2.708µ 2.462µ -9.07% ``` Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/blobstor/fstree/fstree.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 7a064af6bc..02580dbfaa 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -358,10 +358,6 @@ func (t *FSTree) Get(ctx context.Context, prm common.GetPrm) (common.GetRes, err p := t.treePath(prm.Address) - if _, err := os.Stat(p); os.IsNotExist(err) { - return common.GetRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) - } - var data []byte var err error { From d0f64c23a5d96937210c1b9aafbdd235674fab57 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 14 May 2024 17:02:00 +0300 Subject: [PATCH 0553/1413] Release v0.39.0 Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 19 +++++++++++++++++++ VERSION | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c69b69d66..53e2c0bc76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,25 @@ Changelog for FrostFS Node ### Removed ### Updated +## [v0.39.0] + +### Added +- Preliminary erasure coding support (#1065, #1112, #1103, #1120) +- TTL cache for blobovnicza tree (#1004) +- Cache for frostfsid and policy contracts (#1117) +- Writecache path to metric labels (#966) +- Documentation for authentication mechanisms (#1097, #1104) +- Metrics for metabase resync status (#1029) + +### Changed +- Speed up metabase resync (#1024) + +### Fixed +- Possible panic in GET_RANGE (#1077) + +### Updated +- Minimum required Go version to 1.21 + ## [v0.38.0] ### Added diff --git a/VERSION b/VERSION index 765098dc40..2302e306cd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.38.0 +v0.39.0 From b4cfc80579a2b21196f4a44ad45ac2dcc619ed5c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 May 2024 09:45:31 +0300 Subject: [PATCH 0554/1413] [#1133] node: Improve tests for shards.default config section Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config/engine/config_test.go | 4 ++++ config/example/node.env | 4 ++-- config/example/node.json | 4 ++-- config/example/node.yaml | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index b5c926fc34..3f9c7ec71c 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -98,6 +98,8 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 1, blz.ShallowDepth()) require.EqualValues(t, 4, blz.ShallowWidth()) require.EqualValues(t, 50, blz.OpenedCacheSize()) + require.EqualValues(t, time.Minute, blz.OpenedCacheTTL()) + require.EqualValues(t, 30*time.Second, blz.OpenedCacheExpInterval()) require.EqualValues(t, 10, blz.LeafWidth()) require.EqualValues(t, 10, blz.InitWorkerCount()) require.EqualValues(t, true, blz.InitInAdvance()) @@ -151,6 +153,8 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 1, blz.ShallowDepth()) require.EqualValues(t, 4, blz.ShallowWidth()) require.EqualValues(t, 50, blz.OpenedCacheSize()) + require.EqualValues(t, 5*time.Minute, blz.OpenedCacheTTL()) + require.EqualValues(t, 15*time.Second, blz.OpenedCacheExpInterval()) require.EqualValues(t, 10, blz.LeafWidth()) require.EqualValues(t, blobovniczaconfig.InitWorkerCountDefault, blz.InitWorkerCount()) require.EqualValues(t, blobovniczaconfig.RebuildDropTimeoutDefault, blz.RebuildDropTimeout()) diff --git a/config/example/node.env b/config/example/node.env index 77733f5682..db31ae35a2 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -128,8 +128,8 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_SIZE=4194304 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_DEPTH=1 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 -FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_TTL=5m -FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_EXP_INTERVAL=15s +FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_TTL=1m +FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_EXP_INTERVAL=30s FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_IN_ADVANCE=TRUE diff --git a/config/example/node.json b/config/example/node.json index 2ac8697bba..80140e5a21 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -176,8 +176,8 @@ "depth": 1, "width": 4, "opened_cache_capacity": 50, - "opened_cache_ttl": "5m", - "opened_cache_exp_interval": "15s", + "opened_cache_ttl": "1m", + "opened_cache_exp_interval": "30s", "leaf_width": 10, "init_worker_count": 10, "init_in_advance": true, diff --git a/config/example/node.yaml b/config/example/node.yaml index d2109fcc55..13c1823d8e 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -195,6 +195,8 @@ storage: init_worker_count: 10 #count of workers to initialize blobovniczas init_in_advance: true rebuild_drop_timeout: 30s # timeout before drop single blobovnicza + opened_cache_ttl: 1m + opened_cache_exp_interval: 30s - type: fstree path: tmp/0/blob # blobstor path From 300654b045dbd5ebcb05e601aa51c76321f2c30c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 May 2024 11:51:38 +0300 Subject: [PATCH 0555/1413] [#1083] objsvc/v2: Properly check response status after forwarding Previously we had cryptic error: ``` debug get/remote.go:38 remote call failed {"component": "Object.Get service", "request": "HEAD", "address": "9sTxoVrhJ7WBtXQfK2NJ7zDV5yCF7BPLKK1XTxYPdGsP/BbHV4KZZ8y2BPqAT5kyjdHRLkfbtY2xf5uYoMVqxACn1", "raw": false, "local": false, "with session": false, "with bearer": false, "error": "unexpected header type "} ``` Now we have and expected error: ``` debug get/remote.go:38 remote call failed {"component": "Object.Get service", "request": "HEAD", "address": "D2rqaMG4D2VHdv3HKky8UYSYmwQFH2v9oXXqtyRZPTMy/BbHV4KZZ8y2BPqAT5kyjdHRLkfbtY2xf5uYoMVqxACn1", "raw": false, "local": false, "with session": false, "with bearer": false, "error": "status: code = 2049 message = object not found"} ``` Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/v2/head_forwarder.go | 3 +-- pkg/services/object/get/v2/util.go | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/services/object/get/v2/head_forwarder.go b/pkg/services/object/get/v2/head_forwarder.go index 11286321a3..0c29258598 100644 --- a/pkg/services/object/get/v2/head_forwarder.go +++ b/pkg/services/object/get/v2/head_forwarder.go @@ -24,7 +24,6 @@ import ( type headRequestForwarder struct { Request *objectV2.HeadRequest - Response *objectV2.HeadResponse OnceResign sync.Once ObjectAddr oid.Address Key *ecdsa.PrivateKey @@ -172,5 +171,5 @@ func (f *headRequestForwarder) verifyResponse(headResp *objectV2.HeadResponse, p return errResponseVerificationFailed(err) } - return checkStatus(f.Response.GetMetaHeader().GetStatus()) + return checkStatus(headResp.GetMetaHeader().GetStatus()) } diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index 610076c7a9..d71b381e77 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -249,7 +249,6 @@ func (s *Service) toHeadPrm(req *objectV2.HeadRequest, resp *objectV2.HeadRespon forwarder := &headRequestForwarder{ Request: req, - Response: resp, ObjectAddr: objAddr, Key: key, } From 0924b62a95889e731890ff5725fc38871a2c3601 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 May 2024 11:56:17 +0300 Subject: [PATCH 0556/1413] [#1083] objsvc/v2: Unify response verification after forwarding 1. Use the same routine for HEAD/GET_RANGE methods. 2. Make error message similar. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/v2/errors.go | 4 ---- .../object/get/v2/get_range_forwarder.go | 17 +---------------- pkg/services/object/get/v2/head_forwarder.go | 17 +---------------- pkg/services/object/get/v2/util.go | 19 +++++++++++++++++++ 4 files changed, 21 insertions(+), 36 deletions(-) diff --git a/pkg/services/object/get/v2/errors.go b/pkg/services/object/get/v2/errors.go index 01b57f1f2b..213455e10e 100644 --- a/pkg/services/object/get/v2/errors.go +++ b/pkg/services/object/get/v2/errors.go @@ -63,10 +63,6 @@ func errCouldNotWriteObjChunk(forwarder string, err error) error { return fmt.Errorf("could not write object chunk in %s forwarder: %w", forwarder, err) } -func errCouldNotVerifyRangeResponse(resp *objectV2.GetRangeResponse, err error) error { - return fmt.Errorf("could not verify %T: %w", resp, err) -} - func errCouldNotCreateGetRangeStream(err error) error { return fmt.Errorf("could not create Get payload range stream: %w", err) } diff --git a/pkg/services/object/get/v2/get_range_forwarder.go b/pkg/services/object/get/v2/get_range_forwarder.go index 5b05ec3703..10ecfc4a37 100644 --- a/pkg/services/object/get/v2/get_range_forwarder.go +++ b/pkg/services/object/get/v2/get_range_forwarder.go @@ -14,7 +14,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -64,20 +63,6 @@ func (f *getRangeRequestForwarder) forwardRequestToNode(ctx context.Context, add return nil, f.readStream(ctx, rangeStream, c, pubkey) } -func (f *getRangeRequestForwarder) verifyResponse(resp *objectV2.GetRangeResponse, pubkey []byte) error { - // verify response key - if err := internal.VerifyResponseKeyV2(pubkey, resp); err != nil { - return err - } - - // verify response structure - if err := signature.VerifyServiceMessage(resp); err != nil { - return errCouldNotVerifyRangeResponse(resp, err) - } - - return checkStatus(resp.GetMetaHeader().GetStatus()) -} - func (f *getRangeRequestForwarder) openStream(ctx context.Context, addr network.Address, c client.MultiAddressClient) (*rpc.ObjectRangeResponseReader, error) { // open stream var rangeStream *rpc.ObjectRangeResponseReader @@ -107,7 +92,7 @@ func (f *getRangeRequestForwarder) readStream(ctx context.Context, rangeStream * return errReadingResponseFailed(err) } - if err := f.verifyResponse(resp, pubkey); err != nil { + if err := verifyResponse(resp, pubkey); err != nil { return err } diff --git a/pkg/services/object/get/v2/head_forwarder.go b/pkg/services/object/get/v2/head_forwarder.go index 0c29258598..5e16008b8f 100644 --- a/pkg/services/object/get/v2/head_forwarder.go +++ b/pkg/services/object/get/v2/head_forwarder.go @@ -13,7 +13,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -60,7 +59,7 @@ func (f *headRequestForwarder) forwardRequestToNode(ctx context.Context, addr ne return nil, err } - if err := f.verifyResponse(headResp, pubkey); err != nil { + if err := verifyResponse(headResp, pubkey); err != nil { return nil, err } @@ -159,17 +158,3 @@ func (f *headRequestForwarder) sendHeadRequest(ctx context.Context, addr network } return headResp, nil } - -func (f *headRequestForwarder) verifyResponse(headResp *objectV2.HeadResponse, pubkey []byte) error { - // verify response key - if err := internal.VerifyResponseKeyV2(pubkey, headResp); err != nil { - return err - } - - // verify response structure - if err := signature.VerifyServiceMessage(headResp); err != nil { - return errResponseVerificationFailed(err) - } - - return checkStatus(headResp.GetMetaHeader().GetStatus()) -} diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index d71b381e77..852c2aec39 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -8,11 +8,13 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -408,3 +410,20 @@ func chunkToSend(global, local int, chunk []byte) []byte { return chunk[global-local:] } + +type apiResponse interface { + GetMetaHeader() *session.ResponseMetaHeader + GetVerificationHeader() *session.ResponseVerificationHeader +} + +func verifyResponse(resp apiResponse, pubkey []byte) error { + if err := internal.VerifyResponseKeyV2(pubkey, resp); err != nil { + return err + } + + if err := signature.VerifyServiceMessage(resp); err != nil { + return errResponseVerificationFailed(err) + } + + return checkStatus(resp.GetMetaHeader().GetStatus()) +} From b3eaa8a9bcf0933f511adbc7bfea6a8d67b2c679 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 May 2024 12:03:32 +0300 Subject: [PATCH 0557/1413] [#1083] objsvc/v2: Check response status in RANGE_HASH forwarder Fixes #1083 Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/v2/get_range_hash.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/services/object/get/v2/get_range_hash.go b/pkg/services/object/get/v2/get_range_hash.go index 0054f0e9f6..e97b60f668 100644 --- a/pkg/services/object/get/v2/get_range_hash.go +++ b/pkg/services/object/get/v2/get_range_hash.go @@ -142,6 +142,9 @@ func (s *Service) forwardGetRangeHashRequest(ctx context.Context, req *objectV2. resp, err := s.performGetRangeHashOnNode(ctx, req, info) if err == nil { + if err := verifyResponse(resp, info.PublicKey()); err != nil { + return nil, err + } return resp, nil } if firstErr == nil { From 5c582e96fdb65fb37251dfddd21a4c8d92cc4043 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 15 May 2024 13:06:50 +0300 Subject: [PATCH 0558/1413] [#1136] metabase: Fix creation of `ECInfoError` Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/metabase/get.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index aa19502e8b..355f629330 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -198,7 +198,7 @@ func getECInfoError(tx *bbolt.Tx, cnr cid.ID, data []byte) error { key := data[offset : offset+objectKeySize] // check in primary index ojbData := getFromBucket(tx, primaryBucketName(cnr, make([]byte, bucketKeySize)), key) - if len(data) != 0 { + if len(ojbData) != 0 { obj := objectSDK.New() if err := obj.Unmarshal(ojbData); err != nil { return err From f3e09cb09b78c08dab1fb904e22243f11ddd4731 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 May 2024 13:23:59 +0300 Subject: [PATCH 0559/1413] [#1135] sdnotify: Send MONOTONIC_USEC on reload Fixes #1135 Signed-off-by: Evgenii Stratonikov --- pkg/util/sdnotify/clock.go | 10 ++++++++++ pkg/util/sdnotify/clock.s | 2 ++ pkg/util/sdnotify/sdnotify.go | 15 +++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 pkg/util/sdnotify/clock.go create mode 100644 pkg/util/sdnotify/clock.s diff --git a/pkg/util/sdnotify/clock.go b/pkg/util/sdnotify/clock.go new file mode 100644 index 0000000000..f5419d0274 --- /dev/null +++ b/pkg/util/sdnotify/clock.go @@ -0,0 +1,10 @@ +package sdnotify + +import ( + // For go:linkname to work. + _ "unsafe" +) + +//go:noescape +//go:linkname nanotime runtime.nanotime +func nanotime() int64 diff --git a/pkg/util/sdnotify/clock.s b/pkg/util/sdnotify/clock.s new file mode 100644 index 0000000000..ad033ff4f7 --- /dev/null +++ b/pkg/util/sdnotify/clock.s @@ -0,0 +1,2 @@ +// The file is intentionally empty. +// It is a workaround for https://github.com/golang/go/issues/15006 diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go index fe4ad1c3e3..16a3f11c1e 100644 --- a/pkg/util/sdnotify/sdnotify.go +++ b/pkg/util/sdnotify/sdnotify.go @@ -38,6 +38,21 @@ func InitSocket() error { // FlagAndStatus sends systemd a combination of a // well-known status and STATUS=%s{status}, separated by newline. func FlagAndStatus(status string) error { + if status == ReloadingEnabled { + // From https://www.man7.org/linux/man-pages/man5/systemd.service.5.html + // + // When initiating the reload process the service is + // expected to reply with a notification message via + // sd_notify(3) that contains the "RELOADING=1" field in + // combination with "MONOTONIC_USEC=" set to the current + // monotonic time (i.e. CLOCK_MONOTONIC in + // clock_gettime(2)) in μs, formatted as decimal string. + // Once reloading is complete another notification message + // must be sent, containing "READY=1". + // + // For MONOTONIC_USEC format refer to https://www.man7.org/linux/man-pages/man3/sd_notify.3.html + status += fmt.Sprintf("\nMONOTONIC_USEC=%d", uint64(nanotime())/1e3 /* microseconds in nanoseconds */) + } status += "\nSTATUS=" + strings.TrimSuffix(status, "=1") return Send(status) } From b078fe5ba10e110d6323b49fd48974d869cd3e66 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 16 May 2024 12:11:57 +0300 Subject: [PATCH 0560/1413] [#1092] control: Move SignMessage to separate package Signed-off-by: Alexander Chuprov --- .../modules/control/synchronize_tree.go | 4 +- cmd/frostfs-cli/modules/control/util.go | 6 +-- .../control/server/ctrlmessage/sign.go | 44 +++++++++++++++++++ pkg/services/control/server/detach_shards.go | 3 +- pkg/services/control/server/doctor.go | 3 +- pkg/services/control/server/evacuate.go | 5 ++- pkg/services/control/server/evacuate_async.go | 9 ++-- pkg/services/control/server/flush_cache.go | 3 +- pkg/services/control/server/gc.go | 3 +- pkg/services/control/server/healthcheck.go | 3 +- pkg/services/control/server/list_shards.go | 3 +- pkg/services/control/server/policy_engine.go | 13 +++--- .../control/server/seal_writecache.go | 3 +- .../control/server/set_netmap_status.go | 3 +- pkg/services/control/server/set_shard_mode.go | 3 +- pkg/services/control/server/sign.go | 40 +---------------- .../control/server/syncronize_tree.go | 3 +- 17 files changed, 86 insertions(+), 65 deletions(-) create mode 100644 pkg/services/control/server/ctrlmessage/sign.go diff --git a/cmd/frostfs-cli/modules/control/synchronize_tree.go b/cmd/frostfs-cli/modules/control/synchronize_tree.go index 2287344d66..5f2e4da965 100644 --- a/cmd/frostfs-cli/modules/control/synchronize_tree.go +++ b/cmd/frostfs-cli/modules/control/synchronize_tree.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) @@ -60,7 +60,7 @@ func synchronizeTree(cmd *cobra.Command, _ []string) { }, } - err := controlSvc.SignMessage(pk, req) + err := ctrlmessage.Sign(pk, req) commonCmd.ExitOnErr(cmd, "could not sign request: %w", err) cli := getClient(cmd, pk) diff --git a/cmd/frostfs-cli/modules/control/util.go b/cmd/frostfs-cli/modules/control/util.go index ffaceff13d..c0577ac0c6 100644 --- a/cmd/frostfs-cli/modules/control/util.go +++ b/cmd/frostfs-cli/modules/control/util.go @@ -8,7 +8,7 @@ import ( internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" "github.com/spf13/cobra" @@ -33,8 +33,8 @@ func initControlIRFlags(cmd *cobra.Command) { ff.Uint32(irFlagNameVUB, 0, "Valid until block value for notary transaction") } -func signRequest(cmd *cobra.Command, pk *ecdsa.PrivateKey, req controlSvc.SignedMessage) { - err := controlSvc.SignMessage(pk, req) +func signRequest(cmd *cobra.Command, pk *ecdsa.PrivateKey, req ctrlmessage.SignedMessage) { + err := ctrlmessage.Sign(pk, req) commonCmd.ExitOnErr(cmd, "could not sign request: %w", err) } diff --git a/pkg/services/control/server/ctrlmessage/sign.go b/pkg/services/control/server/ctrlmessage/sign.go new file mode 100644 index 0000000000..31425b337a --- /dev/null +++ b/pkg/services/control/server/ctrlmessage/sign.go @@ -0,0 +1,44 @@ +package ctrlmessage + +import ( + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" + frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" +) + +type SignedMessage interface { + ReadSignedData([]byte) ([]byte, error) + GetSignature() *control.Signature + SetSignature(*control.Signature) +} + +// Sign signs Control service ctrlmessage with private key. +func Sign(key *ecdsa.PrivateKey, msg SignedMessage) error { + binBody, err := msg.ReadSignedData(nil) + if err != nil { + return fmt.Errorf("marshal request body: %w", err) + } + + var sig frostfscrypto.Signature + + err = sig.Calculate(frostfsecdsa.Signer(*key), binBody) + if err != nil { + return fmt.Errorf("calculate signature: %w", err) + } + + // TODO(@cthulhu-rider): #468 use Signature ctrlmessage from FrostFS API to avoid conversion + var sigV2 refs.Signature + sig.WriteToV2(&sigV2) + + var sigControl control.Signature + sigControl.SetKey(sigV2.GetKey()) + sigControl.SetSign(sigV2.GetSign()) + + msg.SetSignature(&sigControl) + + return nil +} diff --git a/pkg/services/control/server/detach_shards.go b/pkg/services/control/server/detach_shards.go index c8bea97b43..a4111bddb3 100644 --- a/pkg/services/control/server/detach_shards.go +++ b/pkg/services/control/server/detach_shards.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -29,7 +30,7 @@ func (s *Server) DetachShards(_ context.Context, req *control.DetachShardsReques Body: &control.DetachShardsResponse_Body{}, } - if err = SignMessage(s.key, resp); err != nil { + if err = ctrlmessage.Sign(s.key, resp); err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/doctor.go b/pkg/services/control/server/doctor.go index 707a6c9834..80041de44e 100644 --- a/pkg/services/control/server/doctor.go +++ b/pkg/services/control/server/doctor.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -29,7 +30,7 @@ func (s *Server) Doctor(ctx context.Context, req *control.DoctorRequest) (*contr resp := &control.DoctorResponse{Body: &control.DoctorResponse_Body{}} - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 462ab211ec..3b65bff2ca 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" @@ -49,7 +50,7 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe }, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -131,7 +132,7 @@ func (s *Server) replicateTreeToNode(ctx context.Context, forest pilorama.Forest err = tree.SignMessage(req, s.key) if err != nil { - return fmt.Errorf("can't sign apply request: %w", err) + return fmt.Errorf("can't message apply request: %w", err) } err = s.treeService.ReplicateTreeOp(ctx, node, req) diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index 42ae2635b9..b829573ec5 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -43,7 +44,7 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha Body: &control.StartShardEvacuationResponse_Body{}, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -70,7 +71,7 @@ func (s *Server) GetShardEvacuationStatus(ctx context.Context, req *control.GetS return nil, err } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -96,7 +97,7 @@ func (s *Server) StopShardEvacuation(ctx context.Context, req *control.StopShard Body: &control.StopShardEvacuationResponse_Body{}, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -122,7 +123,7 @@ func (s *Server) ResetShardEvacuationStatus(ctx context.Context, req *control.Re Body: &control.ResetShardEvacuationStatusResponse_Body{}, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/flush_cache.go b/pkg/services/control/server/flush_cache.go index 67ffa1f2c2..031002d717 100644 --- a/pkg/services/control/server/flush_cache.go +++ b/pkg/services/control/server/flush_cache.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -28,7 +29,7 @@ func (s *Server) FlushCache(ctx context.Context, req *control.FlushCacheRequest) resp := &control.FlushCacheResponse{Body: &control.FlushCacheResponse_Body{}} - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/gc.go b/pkg/services/control/server/gc.go index d382dd7e51..d9fefc38e6 100644 --- a/pkg/services/control/server/gc.go +++ b/pkg/services/control/server/gc.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -58,7 +59,7 @@ func (s *Server) DropObjects(ctx context.Context, req *control.DropObjectsReques resp.SetBody(body) // sign the response - if err := SignMessage(s.key, resp); err != nil { + if err := ctrlmessage.Sign(s.key, resp); err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/healthcheck.go b/pkg/services/control/server/healthcheck.go index 9e87caa49c..121c51280b 100644 --- a/pkg/services/control/server/healthcheck.go +++ b/pkg/services/control/server/healthcheck.go @@ -4,6 +4,7 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -27,7 +28,7 @@ func (s *Server) HealthCheck(_ context.Context, req *control.HealthCheckRequest) body.SetHealthStatus(s.healthChecker.HealthStatus()) // sign the response - if err := SignMessage(s.key, resp); err != nil { + if err := ctrlmessage.Sign(s.key, resp); err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/list_shards.go b/pkg/services/control/server/list_shards.go index a020547a2a..d6531b947f 100644 --- a/pkg/services/control/server/list_shards.go +++ b/pkg/services/control/server/list_shards.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -59,7 +60,7 @@ func (s *Server) ListShards(_ context.Context, req *control.ListShardsRequest) ( body.SetShards(shardInfos) // sign the response - if err := SignMessage(s.key, resp); err != nil { + if err := ctrlmessage.Sign(s.key, resp); err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 7ec3d58ac4..e2e1fd7310 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ape" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "google.golang.org/grpc/codes" @@ -99,7 +100,7 @@ func (s *Server) AddChainLocalOverride(_ context.Context, req *control.AddChainL ChainId: []byte(chain.ID), }, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -125,7 +126,7 @@ func (s *Server) GetChainLocalOverride(_ context.Context, req *control.GetChainL Chain: chain.Bytes(), }, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -156,7 +157,7 @@ func (s *Server) ListChainLocalOverrides(_ context.Context, req *control.ListCha Chains: serializedChains, }, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -181,7 +182,7 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove resp := &control.RemoveChainLocalOverrideResponse{ Body: &control.RemoveChainLocalOverrideResponse_Body{}, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -206,7 +207,7 @@ func (s *Server) RemoveChainLocalOverridesByTarget(_ context.Context, req *contr resp := &control.RemoveChainLocalOverridesByTargetResponse{ Body: &control.RemoveChainLocalOverridesByTargetResponse_Body{}, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } @@ -237,7 +238,7 @@ func (s *Server) ListTargetsLocalOverrides(_ context.Context, req *control.ListT Targets: targets, }, } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/seal_writecache.go b/pkg/services/control/server/seal_writecache.go index 5c39cf4849..e3f8b8caf6 100644 --- a/pkg/services/control/server/seal_writecache.go +++ b/pkg/services/control/server/seal_writecache.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -40,7 +41,7 @@ func (s *Server) SealWriteCache(ctx context.Context, req *control.SealWriteCache } } - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, err } diff --git a/pkg/services/control/server/set_netmap_status.go b/pkg/services/control/server/set_netmap_status.go index d4a856952f..3fd69df12f 100644 --- a/pkg/services/control/server/set_netmap_status.go +++ b/pkg/services/control/server/set_netmap_status.go @@ -4,6 +4,7 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -44,7 +45,7 @@ func (s *Server) SetNetmapStatus(_ context.Context, req *control.SetNetmapStatus resp.SetBody(body) // sign the response - if err := SignMessage(s.key, resp); err != nil { + if err := ctrlmessage.Sign(s.key, resp); err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/set_shard_mode.go b/pkg/services/control/server/set_shard_mode.go index 18a7eb3272..52835c41d1 100644 --- a/pkg/services/control/server/set_shard_mode.go +++ b/pkg/services/control/server/set_shard_mode.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -50,7 +51,7 @@ func (s *Server) SetShardMode(_ context.Context, req *control.SetShardModeReques resp.SetBody(body) // sign the response - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } diff --git a/pkg/services/control/server/sign.go b/pkg/services/control/server/sign.go index acc405821e..514af273f2 100644 --- a/pkg/services/control/server/sign.go +++ b/pkg/services/control/server/sign.go @@ -2,26 +2,17 @@ package control import ( "bytes" - "crypto/ecdsa" "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" ) -// SignedMessage is an interface of Control service message. -type SignedMessage interface { - ReadSignedData([]byte) ([]byte, error) - GetSignature() *control.Signature - SetSignature(*control.Signature) -} - var errDisallowedKey = errors.New("key is not in the allowed list") -func (s *Server) isValidRequest(req SignedMessage) error { +func (s *Server) isValidRequest(req ctrlmessage.SignedMessage) error { sign := req.GetSignature() if sign == nil { // TODO(@cthulhu-rider): #468 use "const" error @@ -68,30 +59,3 @@ func (s *Server) isValidRequest(req SignedMessage) error { return nil } - -// SignMessage signs Control service message with private key. -func SignMessage(key *ecdsa.PrivateKey, msg SignedMessage) error { - binBody, err := msg.ReadSignedData(nil) - if err != nil { - return fmt.Errorf("marshal request body: %w", err) - } - - var sig frostfscrypto.Signature - - err = sig.Calculate(frostfsecdsa.Signer(*key), binBody) - if err != nil { - return fmt.Errorf("calculate signature: %w", err) - } - - // TODO(@cthulhu-rider): #468 use Signature message from FrostFS API to avoid conversion - var sigV2 refs.Signature - sig.WriteToV2(&sigV2) - - var sigControl control.Signature - sigControl.SetKey(sigV2.GetKey()) - sigControl.SetSign(sigV2.GetSign()) - - msg.SetSignature(&sigControl) - - return nil -} diff --git a/pkg/services/control/server/syncronize_tree.go b/pkg/services/control/server/syncronize_tree.go index 678f87d0a9..b2a966b2ca 100644 --- a/pkg/services/control/server/syncronize_tree.go +++ b/pkg/services/control/server/syncronize_tree.go @@ -4,6 +4,7 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -42,7 +43,7 @@ func (s *Server) SynchronizeTree(ctx context.Context, req *control.SynchronizeTr resp := new(control.SynchronizeTreeResponse) resp.SetBody(new(control.SynchronizeTreeResponse_Body)) - err = SignMessage(s.key, resp) + err = ctrlmessage.Sign(s.key, resp) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } From 2f04ce2f7946d1bcafe0280488f42806f106df8c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 May 2024 16:04:01 +0300 Subject: [PATCH 0561/1413] [#1138] adm: Parallelize `generate-alphabet` command This is the longest test in our suite, try to help CI a bit. Before: ``` $ go test -run=TestGenerateAlphabet -count=10 . ok git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate 45.400s ``` After: ``` $ go test -run=TestGenerateAlphabet -count=10 . ok git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/generate 33.267s ``` Signed-off-by: Evgenii Stratonikov --- .../modules/morph/generate/generate.go | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go index 8ecc9f1b65..c7de599e57 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -65,34 +65,42 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er pubs := make(keys.PublicKeys, size) passwords := make([]string, size) + var errG errgroup.Group + for i := range wallets { password, err := config.GetPassword(v, innerring.GlagoliticLetter(i).String()) if err != nil { return nil, fmt.Errorf("can't fetch password: %w", err) } - p := filepath.Join(walletDir, innerring.GlagoliticLetter(i).String()+".json") - f, err := os.OpenFile(p, os.O_CREATE, 0o644) - if err != nil { - return nil, fmt.Errorf("can't create wallet file: %w", err) - } - if err := f.Close(); err != nil { - return nil, fmt.Errorf("can't close wallet file: %w", err) - } - w, err := wallet.NewWallet(p) - if err != nil { - return nil, fmt.Errorf("can't create wallet: %w", err) - } - if err := w.CreateAccount(constants.SingleAccountName, password); err != nil { - return nil, fmt.Errorf("can't create account: %w", err) - } + i := i + errG.Go(func() error { + p := filepath.Join(walletDir, innerring.GlagoliticLetter(i).String()+".json") + f, err := os.OpenFile(p, os.O_CREATE, 0o644) + if err != nil { + return fmt.Errorf("can't create wallet file: %w", err) + } + if err := f.Close(); err != nil { + return fmt.Errorf("can't close wallet file: %w", err) + } + w, err := wallet.NewWallet(p) + if err != nil { + return fmt.Errorf("can't create wallet: %w", err) + } + if err := w.CreateAccount(constants.SingleAccountName, password); err != nil { + return fmt.Errorf("can't create account: %w", err) + } - passwords[i] = password - wallets[i] = w - pubs[i] = w.Accounts[0].PrivateKey().PublicKey() + passwords[i] = password + wallets[i] = w + pubs[i] = w.Accounts[0].PrivateKey().PublicKey() + return nil + }) } - var errG errgroup.Group + if err := errG.Wait(); err != nil { + return nil, err + } // Create committee account with N/2+1 multi-signature. majCount := smartcontract.GetMajorityHonestNodeCount(size) From af57d5a6a12f1be58c836e079ff3fc73acca39b3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 15 May 2024 16:12:41 +0300 Subject: [PATCH 0562/1413] [#1138] adm/test: Use `--size=1` for negative tests Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/generate/generate_test.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go index d4a4fee5db..1dd6420eba 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go @@ -23,8 +23,6 @@ import ( ) func TestGenerateAlphabet(t *testing.T) { - const size = 4 - walletDir := t.TempDir() buf := setupTestTerminal(t) @@ -55,13 +53,13 @@ func TestGenerateAlphabet(t *testing.T) { t.Run("no password for contract group wallet", func(t *testing.T) { buf.Reset() v.Set(commonflags.AlphabetWalletsFlag, walletDir) - require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, strconv.FormatUint(size, 10))) - for i := uint64(0); i < size; i++ { - buf.WriteString(strconv.FormatUint(i, 10) + "\r") - } + require.NoError(t, cmd.Flags().Set(commonflags.AlphabetSizeFlag, "1")) + buf.WriteString("pass\r") require.Error(t, AlphabetCreds(cmd, nil)) }) + const size = 4 + buf.Reset() v.Set(commonflags.AlphabetWalletsFlag, walletDir) require.NoError(t, GenerateAlphabetCmd.Flags().Set(commonflags.AlphabetSizeFlag, strconv.FormatUint(size, 10))) From d45d086acd0f7b60a288bc69fd70ec8513ea23b7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 13 May 2024 16:50:21 +0300 Subject: [PATCH 0563/1413] [#1129] policer: Add EC chunk replication Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/keyspaceiterator.go | 2 +- internal/logs/logs.go | 1 + pkg/core/object/{address.go => info.go} | 15 +- pkg/local_object_storage/engine/evacuate.go | 2 +- pkg/local_object_storage/engine/list.go | 6 +- pkg/local_object_storage/engine/list_test.go | 6 +- pkg/local_object_storage/metabase/list.go | 23 ++- .../metabase/list_test.go | 14 +- pkg/local_object_storage/shard/list.go | 4 +- pkg/services/control/server/evacuate.go | 2 +- pkg/services/policer/check.go | 41 +++--- pkg/services/policer/ec.go | 137 ++++++++++++++++++ pkg/services/policer/option.go | 4 +- pkg/services/policer/policer_test.go | 64 ++++++-- pkg/services/replicator/process.go | 4 +- 15 files changed, 263 insertions(+), 62 deletions(-) rename pkg/core/object/{address.go => info.go} (62%) create mode 100644 pkg/services/policer/ec.go diff --git a/cmd/frostfs-node/keyspaceiterator.go b/cmd/frostfs-node/keyspaceiterator.go index e7214aacb3..09a8f7f73f 100644 --- a/cmd/frostfs-node/keyspaceiterator.go +++ b/cmd/frostfs-node/keyspaceiterator.go @@ -13,7 +13,7 @@ type keySpaceIterator struct { cur *engine.Cursor } -func (it *keySpaceIterator) Next(ctx context.Context, batchSize uint32) ([]objectcore.AddressWithType, error) { +func (it *keySpaceIterator) Next(ctx context.Context, batchSize uint32) ([]objectcore.Info, error) { var prm engine.ListWithCursorPrm prm.WithCursor(it.cur) prm.WithCount(batchSize) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 4576e2e594..f51c72e733 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -529,4 +529,5 @@ const ( EngineRefillFailedToGetObjectsCount = "failed to get blobstor objects count, no resync percent estimation is available" ECFailedToSendToContainerNode = "failed to send EC object to container node" ECFailedToSaveECPart = "failed to save EC part" + PolicerNodeIsNotContainerNodeForECObject = "current node is not container node for EC object" ) diff --git a/pkg/core/object/address.go b/pkg/core/object/info.go similarity index 62% rename from pkg/core/object/address.go rename to pkg/core/object/info.go index a25d853eb8..67c9a31882 100644 --- a/pkg/core/object/address.go +++ b/pkg/core/object/info.go @@ -7,14 +7,21 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) -// AddressWithType groups object address with its FrostFS -// object type. -type AddressWithType struct { +type ECInfo struct { + ParentID oid.ID + Index uint32 + Total uint32 +} + +// Info groups object address with its FrostFS +// object info. +type Info struct { Address oid.Address Type objectSDK.Type IsLinkingObject bool + ECInfo *ECInfo } -func (v AddressWithType) String() string { +func (v Info) String() string { return fmt.Sprintf("address: %s, type: %s, is linking: %t", v.Address, v.Type, v.IsLinkingObject) } diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 81fe47e657..87542eec17 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -622,7 +622,7 @@ func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) return shards, nil } -func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, toEvacuate []object.AddressWithType, prm EvacuateShardPrm, res *EvacuateShardRes, +func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, toEvacuate []object.Info, prm EvacuateShardPrm, res *EvacuateShardRes, shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateObjects", diff --git a/pkg/local_object_storage/engine/list.go b/pkg/local_object_storage/engine/list.go index 7245caeebc..cb3830b7c7 100644 --- a/pkg/local_object_storage/engine/list.go +++ b/pkg/local_object_storage/engine/list.go @@ -68,12 +68,12 @@ func (p *ListWithCursorPrm) WithCursor(cursor *Cursor) { // ListWithCursorRes contains values returned from ListWithCursor operation. type ListWithCursorRes struct { - addrList []objectcore.AddressWithType + addrList []objectcore.Info cursor *Cursor } // AddressList returns addresses selected by ListWithCursor operation. -func (l ListWithCursorRes) AddressList() []objectcore.AddressWithType { +func (l ListWithCursorRes) AddressList() []objectcore.Info { return l.addrList } @@ -98,7 +98,7 @@ func (l ListWithCursorRes) Cursor() *Cursor { // Returns ErrEndOfListing if there are no more objects to return or count // parameter set to zero. func (e *StorageEngine) ListWithCursor(ctx context.Context, prm ListWithCursorPrm) (ListWithCursorRes, error) { - result := make([]objectcore.AddressWithType, 0, prm.count) + result := make([]objectcore.Info, 0, prm.count) // Set initial cursors cursor := prm.cursor diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 4fc9569c7b..dd8a2e8a09 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -76,8 +76,8 @@ func TestListWithCursor(t *testing.T) { require.NoError(t, e.Close(context.Background())) }() - expected := make([]object.AddressWithType, 0, tt.objectNum) - got := make([]object.AddressWithType, 0, tt.objectNum) + expected := make([]object.Info, 0, tt.objectNum) + got := make([]object.Info, 0, tt.objectNum) for i := 0; i < tt.objectNum; i++ { containerID := cidtest.ID() @@ -88,7 +88,7 @@ func TestListWithCursor(t *testing.T) { err := e.Put(context.Background(), prm) require.NoError(t, err) - expected = append(expected, object.AddressWithType{Type: objectSDK.TypeRegular, Address: object.AddressOf(obj)}) + expected = append(expected, object.Info{Type: objectSDK.TypeRegular, Address: object.AddressOf(obj)}) } var prm ListWithCursorPrm diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index f7a314452d..544b2e6666 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -47,12 +47,12 @@ func (l *ListPrm) SetCursor(cursor *Cursor) { // ListRes contains values returned from ListWithCursor operation. type ListRes struct { - addrList []objectcore.AddressWithType + addrList []objectcore.Info cursor *Cursor } // AddressList returns addresses selected by ListWithCursor operation. -func (l ListRes) AddressList() []objectcore.AddressWithType { +func (l ListRes) AddressList() []objectcore.Info { return l.addrList } @@ -89,7 +89,7 @@ func (db *DB) ListWithCursor(ctx context.Context, prm ListPrm) (res ListRes, err return res, ErrDegradedMode } - result := make([]objectcore.AddressWithType, 0, prm.count) + result := make([]objectcore.Info, 0, prm.count) err = db.boltDB.View(func(tx *bbolt.Tx) error { res.addrList, res.cursor, err = db.listWithCursor(tx, result, prm.count, prm.cursor) @@ -99,7 +99,7 @@ func (db *DB) ListWithCursor(ctx context.Context, prm ListPrm) (res ListRes, err return res, metaerr.Wrap(err) } -func (db *DB) listWithCursor(tx *bbolt.Tx, result []objectcore.AddressWithType, count int, cursor *Cursor) ([]objectcore.AddressWithType, *Cursor, error) { +func (db *DB) listWithCursor(tx *bbolt.Tx, result []objectcore.Info, count int, cursor *Cursor) ([]objectcore.Info, *Cursor, error) { threshold := cursor == nil // threshold is a flag to ignore cursor var bucketName []byte var err error @@ -183,11 +183,11 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket graveyardBkt, garbageBkt *bbolt.Bucket, // cached graveyard buckets cidRaw []byte, // container ID prefix, optimization cnt cid.ID, // container ID - to []objectcore.AddressWithType, // listing result + to []objectcore.Info, // listing result limit int, // stop listing at `limit` items in result cursor *Cursor, // start from cursor object threshold bool, // ignore cursor and start immediately -) ([]objectcore.AddressWithType, []byte, *Cursor, error) { +) ([]objectcore.Info, []byte, *Cursor, error) { if cursor == nil { cursor = new(Cursor) } @@ -219,18 +219,27 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket } var isLinkingObj bool + var ecInfo *objectcore.ECInfo if objType == objectSDK.TypeRegular { var o objectSDK.Object if err := o.Unmarshal(v); err != nil { return nil, nil, nil, err } isLinkingObj = isLinkObject(&o) + ecHeader := o.ECHeader() + if ecHeader != nil { + ecInfo = &objectcore.ECInfo{ + ParentID: ecHeader.Parent(), + Index: ecHeader.Index(), + Total: ecHeader.Total(), + } + } } var a oid.Address a.SetContainer(cnt) a.SetObject(obj) - to = append(to, objectcore.AddressWithType{Address: a, Type: objType, IsLinkingObject: isLinkingObj}) + to = append(to, objectcore.Info{Address: a, Type: objType, IsLinkingObject: isLinkingObj, ECInfo: ecInfo}) count++ } diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index e1ccb4e06f..a92e2eff4f 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -77,7 +77,7 @@ func TestLisObjectsWithCursor(t *testing.T) { total = containers * 4 // regular + ts + child + lock ) - expected := make([]object.AddressWithType, 0, total) + expected := make([]object.Info, 0, total) // fill metabase with objects for i := 0; i < containers; i++ { @@ -88,21 +88,21 @@ func TestLisObjectsWithCursor(t *testing.T) { obj.SetType(objectSDK.TypeRegular) err := putBig(db, obj) require.NoError(t, err) - expected = append(expected, object.AddressWithType{Address: object.AddressOf(obj), Type: objectSDK.TypeRegular}) + expected = append(expected, object.Info{Address: object.AddressOf(obj), Type: objectSDK.TypeRegular}) // add one tombstone obj = testutil.GenerateObjectWithCID(containerID) obj.SetType(objectSDK.TypeTombstone) err = putBig(db, obj) require.NoError(t, err) - expected = append(expected, object.AddressWithType{Address: object.AddressOf(obj), Type: objectSDK.TypeTombstone}) + expected = append(expected, object.Info{Address: object.AddressOf(obj), Type: objectSDK.TypeTombstone}) // add one lock obj = testutil.GenerateObjectWithCID(containerID) obj.SetType(objectSDK.TypeLock) err = putBig(db, obj) require.NoError(t, err) - expected = append(expected, object.AddressWithType{Address: object.AddressOf(obj), Type: objectSDK.TypeLock}) + expected = append(expected, object.Info{Address: object.AddressOf(obj), Type: objectSDK.TypeLock}) // add one inhumed (do not include into expected) obj = testutil.GenerateObjectWithCID(containerID) @@ -124,12 +124,12 @@ func TestLisObjectsWithCursor(t *testing.T) { child.SetSplitID(splitID) err = putBig(db, child) require.NoError(t, err) - expected = append(expected, object.AddressWithType{Address: object.AddressOf(child), Type: objectSDK.TypeRegular}) + expected = append(expected, object.Info{Address: object.AddressOf(child), Type: objectSDK.TypeRegular}) } t.Run("success with various count", func(t *testing.T) { for countPerReq := 1; countPerReq <= total; countPerReq++ { - got := make([]object.AddressWithType, 0, total) + got := make([]object.Info, 0, total) res, cursor, err := metaListWithCursor(db, uint32(countPerReq), nil) require.NoError(t, err, "count:%d", countPerReq) @@ -211,7 +211,7 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { } } -func metaListWithCursor(db *meta.DB, count uint32, cursor *meta.Cursor) ([]object.AddressWithType, *meta.Cursor, error) { +func metaListWithCursor(db *meta.DB, count uint32, cursor *meta.Cursor) ([]object.Info, *meta.Cursor, error) { var listPrm meta.ListPrm listPrm.SetCount(count) listPrm.SetCursor(cursor) diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index d6e4d7e504..08ea81a0cf 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -42,7 +42,7 @@ type ListWithCursorPrm struct { // ListWithCursorRes contains values returned from ListWithCursor operation. type ListWithCursorRes struct { - addrList []objectcore.AddressWithType + addrList []objectcore.Info cursor *Cursor } @@ -59,7 +59,7 @@ func (p *ListWithCursorPrm) WithCursor(cursor *Cursor) { } // AddressList returns addresses selected by ListWithCursor operation. -func (r ListWithCursorRes) AddressList() []objectcore.AddressWithType { +func (r ListWithCursorRes) AddressList() []objectcore.Info { return r.addrList } diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 3b65bff2ca..794bc199a7 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -77,7 +77,7 @@ func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *obj Obj: obj, Nodes: nodes, } - s.replicator.HandleTask(ctx, task, &res) + s.replicator.HandleReplicationTask(ctx, task, &res) if res.count == 0 { return errors.New("object was not replicated") diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index d68d99d181..2153275cc1 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -18,19 +18,15 @@ import ( "go.uber.org/zap" ) -func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.AddressWithType) error { - addr := addrWithType.Address - idCnr := addr.Container() - idObj := addr.Object() - - cnr, err := p.cnrSrc.Get(idCnr) +func (p *Policer) processObject(ctx context.Context, objInfo objectcore.Info) error { + cnr, err := p.cnrSrc.Get(objInfo.Address.Container()) if err != nil { if client.IsErrContainerNotFound(err) { - existed, errWasRemoved := containercore.WasRemoved(p.cnrSrc, idCnr) + existed, errWasRemoved := containercore.WasRemoved(p.cnrSrc, objInfo.Address.Container()) if errWasRemoved != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotConfirmContainerRemoval, errWasRemoved) } else if existed { - err := p.buryFn(ctx, addrWithType.Address) + err := p.buryFn(ctx, objInfo.Address) if err != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotInhumeObjectWithMissingContainer, err) } @@ -41,11 +37,16 @@ func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.Add } policy := cnr.Value.PlacementPolicy() - if policycore.IsECPlacement(policy) { - // EC not supported yet by policer - return nil - } + if policycore.IsECPlacement(policy) { + return p.processECContainerObject(ctx, objInfo, policy) + } + return p.processRepContainerObject(ctx, objInfo, policy) +} + +func (p *Policer) processRepContainerObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { + idObj := objInfo.Address.Object() + idCnr := objInfo.Address.Container() nn, err := p.placementBuilder.BuildPlacement(idCnr, &idObj, policy) if err != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) @@ -68,15 +69,15 @@ func (p *Policer) processObject(ctx context.Context, addrWithType objectcore.Add default: } - p.processNodes(ctx, c, addrWithType, nn[i], policy.ReplicaDescriptor(i).NumberOfObjects(), checkedNodes) + p.processRepNodes(ctx, c, objInfo, nn[i], policy.ReplicaDescriptor(i).NumberOfObjects(), checkedNodes) } if !c.needLocalCopy && c.removeLocalCopy { p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, - zap.Stringer("object", addr), + zap.Stringer("object", objInfo.Address), ) - p.cbRedundantCopy(ctx, addr) + p.cbRedundantCopy(ctx, objInfo.Address) } return nil } @@ -89,16 +90,16 @@ type placementRequirements struct { removeLocalCopy bool } -func (p *Policer) processNodes(ctx context.Context, requirements *placementRequirements, addrWithType objectcore.AddressWithType, +func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRequirements, objInfo objectcore.Info, nodes []netmap.NodeInfo, shortage uint32, checkedNodes nodeCache, ) { - addr := addrWithType.Address - typ := addrWithType.Type + addr := objInfo.Address + typ := objInfo.Type // Number of copies that are stored on maintenance nodes. var uncheckedCopies int - if typ == objectSDK.TypeLock || typ == objectSDK.TypeTombstone || addrWithType.IsLinkingObject { + if typ == objectSDK.TypeLock || typ == objectSDK.TypeTombstone || objInfo.IsLinkingObject { // all nodes of a container must store the `LOCK`, `TOMBSTONE` and linking objects // for correct object removal protection: // - `LOCK`, `TOMBSTONE` and linking objects are broadcast on their PUT requests; @@ -196,7 +197,7 @@ func (p *Policer) handleProcessNodesResult(ctx context.Context, addr oid.Address Nodes: nodes, } - p.replicator.HandleTask(ctx, task, checkedNodes) + p.replicator.HandleReplicationTask(ctx, task, checkedNodes) case uncheckedCopies > 0: // If we have more copies than needed, but some of them are from the maintenance nodes, diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go new file mode 100644 index 0000000000..194b0ddbea --- /dev/null +++ b/pkg/services/policer/ec.go @@ -0,0 +1,137 @@ +package policer + +import ( + "context" + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "go.uber.org/zap" +) + +var errInvalidECPlacement = errors.New("invalid EC placement: EC placement must have one placement vector") + +func (p *Policer) processECContainerObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { + if objInfo.ECInfo == nil { + return p.processECContainerRepObject(ctx, objInfo, policy) + } + return p.processECContainerECObject(ctx, objInfo, policy) +} + +// processECContainerRepObject processes non erasure coded objects in EC container: tombstones, locks and linking objects. +// All of them must be stored on all of the container nodes. +func (p *Policer) processECContainerRepObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { + objID := objInfo.Address.Object() + nn, err := p.placementBuilder.BuildPlacement(objInfo.Address.Container(), &objID, policy) + if err != nil { + return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) + } + if len(nn) != 1 { + return errInvalidECPlacement + } + + c := &placementRequirements{} + checkedNodes := newNodeCache() + + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + rd := policy.ReplicaDescriptor(0) + // processNodes replaces rd.GetECDataCount() + rd.GetECParityCount() for len(nn[0]) for locks, tomstones and linking objects. + p.processRepNodes(ctx, c, objInfo, nn[0], rd.GetECDataCount()+rd.GetECParityCount(), checkedNodes) + + if !c.needLocalCopy && c.removeLocalCopy { + p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, + zap.Stringer("object", objInfo.Address), + ) + + p.cbRedundantCopy(ctx, objInfo.Address) + } + return nil +} + +func (p *Policer) processECContainerECObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { + nn, err := p.placementBuilder.BuildPlacement(objInfo.Address.Container(), &objInfo.ECInfo.ParentID, policy) + if err != nil { + return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) + } + if len(nn) != 1 { + return errInvalidECPlacement + } + + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + validPlacement := p.processECChunk(ctx, objInfo, nn[0]) + if !validPlacement { + p.pullRequiredECChunks(ctx, objInfo, nn[0]) + } + return nil +} + +// processECChunk replicates EC chunk if needed. +// Returns True if current chunk should be stored on current node. +func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) bool { + var removeLocalChunk bool + requiredNode := nodes[int(objInfo.ECInfo.Index)%(len(nodes))] + if p.cfg.netmapKeys.IsLocalKey(requiredNode.PublicKey()) { + // current node is required node, we are happy + return true + } + if requiredNode.IsMaintenance() { + // consider maintenance mode has object, but do not drop local copy + p.log.Debug(logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) + return false + } + + callCtx, cancel := context.WithTimeout(ctx, p.headTimeout) + _, err := p.remoteHeader(callCtx, requiredNode, objInfo.Address) + cancel() + + if err == nil { + removeLocalChunk = true + } else if client.IsErrObjectNotFound(err) { + p.log.Debug(logs.PolicerShortageOfObjectCopiesDetected, zap.Stringer("object", objInfo.Address), zap.Uint32("shortage", 1)) + task := replicator.Task{ + NumCopies: 1, + Addr: objInfo.Address, + Nodes: []netmap.NodeInfo{requiredNode}, + } + p.replicator.HandleReplicationTask(ctx, task, newNodeCache()) + } else if isClientErrMaintenance(err) { + // consider maintenance mode has object, but do not drop local copy + p.log.Debug(logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) + } else { + p.log.Error(logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", objInfo.Address), zap.String("error", err.Error())) + } + + if removeLocalChunk { + p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address)) + p.cbRedundantCopy(ctx, objInfo.Address) + } + + return false +} + +func (p *Policer) pullRequiredECChunks(_ context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) { + requiredChunkIndexes := make(map[uint32]struct{}) + for i, n := range nodes { + if p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) { + requiredChunkIndexes[uint32(i)] = struct{}{} + } + } + if len(requiredChunkIndexes) == 0 { + p.log.Info(logs.PolicerNodeIsNotContainerNodeForECObject, zap.Stringer("object", objInfo.ECInfo.ParentID)) + return + } +} diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 58c74ee1a5..849e5ed8b8 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -22,7 +22,7 @@ import ( // Note that the underlying implementation might be circular: i.e. it can restart // when the end of the key space is reached. type KeySpaceIterator interface { - Next(context.Context, uint32) ([]objectcore.AddressWithType, error) + Next(context.Context, uint32) ([]objectcore.Info, error) Rewind() } @@ -35,7 +35,7 @@ type BuryFunc func(context.Context, oid.Address) error // Replicator is the interface to a consumer of replication tasks. type Replicator interface { - HandleTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) + HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) } // RemoteObjectHeaderFunc is the function to obtain HEAD info from a specific remote node. diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index be0974c39a..2c70b1c045 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -26,7 +26,7 @@ import ( func TestBuryObjectWithoutContainer(t *testing.T) { // Key space addr := oidtest.Address() - objs := []objectcore.AddressWithType{ + objs := []objectcore.Info{ { Address: addr, Type: objectSDK.TypeRegular, @@ -78,6 +78,7 @@ func TestProcessObject(t *testing.T) { maintenanceNodes []int wantRemoveRedundant bool wantReplicateTo []int + ecInfo *objectcore.ECInfo }{ { desc: "1 copy already held by local node", @@ -144,6 +145,47 @@ func TestProcessObject(t *testing.T) { objHolders: []int{1}, maintenanceNodes: []int{2}, }, + { + desc: "lock object must be replicated to all EC nodes", + objType: objectSDK.TypeLock, + nodeCount: 3, + policy: `EC 1.1`, + placement: [][]int{{0, 1, 2}}, + wantReplicateTo: []int{1, 2}, + }, + { + desc: "tombstone object must be replicated to all EC nodes", + objType: objectSDK.TypeTombstone, + nodeCount: 3, + policy: `EC 1.1`, + placement: [][]int{{0, 1, 2}}, + wantReplicateTo: []int{1, 2}, + }, + { + desc: "EC chunk stored valid on current node", + objType: objectSDK.TypeRegular, + nodeCount: 2, + policy: `EC 1.1`, + placement: [][]int{{0}}, + ecInfo: &objectcore.ECInfo{ + ParentID: oidtest.ID(), + Index: 1, + Total: 2, + }, + }, + { + desc: "EC chunk must be replicated to other EC node", + objType: objectSDK.TypeRegular, + nodeCount: 2, + policy: `EC 1.1`, + placement: [][]int{{1}}, + wantReplicateTo: []int{1}, + ecInfo: &objectcore.ECInfo{ + ParentID: oidtest.ID(), + Index: 1, + Total: 2, + }, + }, } for i := range tests { @@ -173,6 +215,9 @@ func TestProcessObject(t *testing.T) { if cnr.Equals(addr.Container()) && obj != nil && obj.Equals(addr.Object()) { return placementVectors, nil } + if ti.ecInfo != nil && cnr.Equals(addr.Container()) && obj != nil && obj.Equals(ti.ecInfo.ParentID) { + return placementVectors, nil + } t.Errorf("unexpected placement build: cid=%v oid=%v", cnr, obj) return nil, errors.New("unexpected placement build") } @@ -238,9 +283,10 @@ func TestProcessObject(t *testing.T) { WithPool(testPool(t)), ) - addrWithType := objectcore.AddressWithType{ + addrWithType := objectcore.Info{ Address: addr, Type: ti.objType, + ECInfo: ti.ecInfo, } err := p.processObject(context.Background(), addrWithType) @@ -276,7 +322,7 @@ func TestProcessObjectError(t *testing.T) { WithPool(testPool(t)), ) - addrWithType := objectcore.AddressWithType{ + addrWithType := objectcore.Info{ Address: addr, } @@ -285,7 +331,7 @@ func TestProcessObjectError(t *testing.T) { func TestIteratorContract(t *testing.T) { addr := oidtest.Address() - objs := []objectcore.AddressWithType{{ + objs := []objectcore.Info{{ Address: addr, Type: objectSDK.TypeRegular, }} @@ -350,7 +396,7 @@ func testPool(t *testing.T) *ants.Pool { } type nextResult struct { - objs []objectcore.AddressWithType + objs []objectcore.Info err error } @@ -361,7 +407,7 @@ type predefinedIterator struct { calls []string } -func (it *predefinedIterator) Next(ctx context.Context, size uint32) ([]objectcore.AddressWithType, error) { +func (it *predefinedIterator) Next(ctx context.Context, size uint32) ([]objectcore.Info, error) { if it.pos == len(it.scenario) { close(it.finishCh) <-ctx.Done() @@ -380,11 +426,11 @@ func (it *predefinedIterator) Rewind() { // sliceKeySpaceIterator is a KeySpaceIterator backed by a slice. type sliceKeySpaceIterator struct { - objs []objectcore.AddressWithType + objs []objectcore.Info cur int } -func (it *sliceKeySpaceIterator) Next(_ context.Context, size uint32) ([]objectcore.AddressWithType, error) { +func (it *sliceKeySpaceIterator) Next(_ context.Context, size uint32) ([]objectcore.Info, error) { if it.cur >= len(it.objs) { return nil, engine.ErrEndOfListing } @@ -422,6 +468,6 @@ func (f announcedKeysFunc) IsLocalKey(k []byte) bool { return f(k) } // replicatorFunc is a Replicator backed by a function. type replicatorFunc func(context.Context, replicator.Task, replicator.TaskResult) -func (f replicatorFunc) HandleTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) { +func (f replicatorFunc) HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) { f(ctx, task, res) } diff --git a/pkg/services/replicator/process.go b/pkg/services/replicator/process.go index 3a46e5f041..06d41b74e9 100644 --- a/pkg/services/replicator/process.go +++ b/pkg/services/replicator/process.go @@ -21,9 +21,9 @@ type TaskResult interface { SubmitSuccessfulReplication(netmap.NodeInfo) } -// HandleTask executes replication task inside invoking goroutine. +// HandleReplicationTask executes replication task inside invoking goroutine. // Passes all the nodes that accepted the replication to the TaskResult. -func (p *Replicator) HandleTask(ctx context.Context, task Task, res TaskResult) { +func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res TaskResult) { p.metrics.IncInFlightRequest() defer p.metrics.DecInFlightRequest() defer func() { From cbe9757490a44436683a406f7917222190ab7dd6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 14 May 2024 14:43:21 +0300 Subject: [PATCH 0564/1413] [#1129] policer: Pull required EC chunks Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 16 +- internal/logs/logs.go | 8 +- pkg/services/object/get/remote_getter.go | 55 ++++ pkg/services/object/head/prm.go | 17 - pkg/services/object/head/remote.go | 18 +- pkg/services/policer/check.go | 2 +- pkg/services/policer/ec.go | 166 +++++++++- pkg/services/policer/ec_test.go | 402 +++++++++++++++++++++++ pkg/services/policer/option.go | 17 +- pkg/services/policer/policer_test.go | 31 +- pkg/services/replicator/process.go | 2 +- pkg/services/replicator/pull.go | 72 ++++ pkg/services/replicator/replicator.go | 9 + 13 files changed, 744 insertions(+), 71 deletions(-) create mode 100644 pkg/services/object/get/remote_getter.go delete mode 100644 pkg/services/object/head/prm.go create mode 100644 pkg/services/policer/ec_test.go create mode 100644 pkg/services/replicator/pull.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 833daf6283..af185a8da9 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -242,11 +242,20 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl placement.NewNetworkMapSourceBuilder(c.netMapSource), ), policer.WithRemoteObjectHeaderFunc( - func(ctx context.Context, ni netmapSDK.NodeInfo, a oid.Address) (*objectSDK.Object, error) { - prm := new(headsvc.RemoteHeadPrm).WithNodeInfo(ni).WithObjectAddress(a) + func(ctx context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { + prm := new(headsvc.RemoteHeadPrm).WithNodeInfo(ni).WithObjectAddress(a).WithRaw(raw) return remoteHeader.Head(ctx, prm) }, ), + policer.WithLocalObjectHeaderFunc(func(ctx context.Context, a oid.Address) (*objectSDK.Object, error) { + var prm engine.HeadPrm + prm.WithAddress(a) + res, err := c.cfgObject.cfgLocalStorage.localStorage.Head(ctx, prm) + if err != nil { + return nil, err + } + return res.Header(), nil + }), policer.WithNetmapKeys(c), policer.WithHeadTimeout( policerconfig.HeadTimeout(c.appCfg), @@ -297,6 +306,9 @@ func createReplicator(c *cfg, keyStorage *util.KeyStorage, cache *cache.ClientCa replicator.WithRemoteSender( putsvc.NewRemoteSender(keyStorage, cache), ), + replicator.WithRemoteGetter( + getsvc.NewRemoteGetter(c.clientCache, c.netMapSource, keyStorage), + ), replicator.WithMetrics(c.metricsCollector.Replicator()), ) } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index f51c72e733..2e89e43040 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -529,5 +529,11 @@ const ( EngineRefillFailedToGetObjectsCount = "failed to get blobstor objects count, no resync percent estimation is available" ECFailedToSendToContainerNode = "failed to send EC object to container node" ECFailedToSaveECPart = "failed to save EC part" - PolicerNodeIsNotContainerNodeForECObject = "current node is not container node for EC object" + PolicerNodeIsNotECObjectNode = "current node is not EC object node" + PolicerFailedToGetLocalECChunks = "failed to get local EC chunks" + PolicerMissingECChunk = "failed to find EC chunk on any of the nodes" + PolicerFailedToDecodeECChunkID = "failed to decode EC chunk ID" + PolicerDifferentObjectIDForTheSameECChunk = "different object IDs for the same EC chunk" + ReplicatorCouldNotGetObjectFromRemoteStorage = "could not get object from remote storage" + ReplicatorCouldNotPutObjectToLocalStorage = "could not put object to local storage" ) diff --git a/pkg/services/object/get/remote_getter.go b/pkg/services/object/get/remote_getter.go new file mode 100644 index 0000000000..0df67dec9c --- /dev/null +++ b/pkg/services/object/get/remote_getter.go @@ -0,0 +1,55 @@ +package getsvc + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +) + +type RemoteGetPrm struct { + Address oid.Address + Node netmapSDK.NodeInfo +} + +type RemoteGetter struct { + s remoteStorageConstructor + es epochSource + ks keyStorage +} + +func (g *RemoteGetter) Get(ctx context.Context, prm RemoteGetPrm) (*objectSDK.Object, error) { + var nodeInfo client.NodeInfo + if err := client.NodeInfoFromRawNetmapElement(&nodeInfo, netmapCore.Node(prm.Node)); err != nil { + return nil, err + } + rs, err := g.s.Get(nodeInfo) + if err != nil { + return nil, err + } + epoch, err := g.es.Epoch() + if err != nil { + return nil, err + } + key, err := g.ks.GetKey(nil) + if err != nil { + return nil, err + } + r := RemoteRequestParams{ + Epoch: epoch, + TTL: 1, + PrivateKey: key, + } + return rs.Get(ctx, prm.Address, r) +} + +func NewRemoteGetter(cc clientConstructor, es epochSource, ks keyStorage) *RemoteGetter { + return &RemoteGetter{ + s: &multiclientRemoteStorageConstructor{clientConstructor: cc}, + es: es, + ks: ks, + } +} diff --git a/pkg/services/object/head/prm.go b/pkg/services/object/head/prm.go deleted file mode 100644 index 5566e48fe1..0000000000 --- a/pkg/services/object/head/prm.go +++ /dev/null @@ -1,17 +0,0 @@ -package headsvc - -import ( - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" -) - -type Prm struct { - addr oid.Address -} - -func (p *Prm) WithAddress(v oid.Address) *Prm { - if p != nil { - p.addr = v - } - - return p -} diff --git a/pkg/services/object/head/remote.go b/pkg/services/object/head/remote.go index c9c17d4d8b..6d47e37eb6 100644 --- a/pkg/services/object/head/remote.go +++ b/pkg/services/object/head/remote.go @@ -28,8 +28,8 @@ type RemoteHeader struct { // RemoteHeadPrm groups remote header operation parameters. type RemoteHeadPrm struct { - commonHeadPrm *Prm - + addr oid.Address + raw bool node netmap.NodeInfo } @@ -57,12 +57,19 @@ func (p *RemoteHeadPrm) WithNodeInfo(v netmap.NodeInfo) *RemoteHeadPrm { // WithObjectAddress sets object address. func (p *RemoteHeadPrm) WithObjectAddress(v oid.Address) *RemoteHeadPrm { if p != nil { - p.commonHeadPrm = new(Prm).WithAddress(v) + p.addr = v } return p } +func (p *RemoteHeadPrm) WithRaw(v bool) *RemoteHeadPrm { + if p != nil { + p.raw = v + } + return p +} + // Head requests object header from the remote node. func (h *RemoteHeader) Head(ctx context.Context, prm *RemoteHeadPrm) (*objectSDK.Object, error) { key, err := h.keyStorage.GetKey(nil) @@ -86,8 +93,11 @@ func (h *RemoteHeader) Head(ctx context.Context, prm *RemoteHeadPrm) (*objectSDK headPrm.SetClient(c) headPrm.SetPrivateKey(key) - headPrm.SetAddress(prm.commonHeadPrm.addr) + headPrm.SetAddress(prm.addr) headPrm.SetTTL(remoteOpTTL) + if prm.raw { + headPrm.SetRawFlag() + } res, err := internalclient.HeadObject(ctx, headPrm) if err != nil { diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 2153275cc1..2cdb725051 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -134,7 +134,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe callCtx, cancel := context.WithTimeout(ctx, p.headTimeout) - _, err := p.remoteHeader(callCtx, nodes[i], addr) + _, err := p.remoteHeader(callCtx, nodes[i], addr, false) cancel() diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index 194b0ddbea..6eca3bc005 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -10,9 +10,18 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) +var errNoECinfoReturnded = errors.New("no EC info returned") + +type ecChunkProcessResult struct { + validPlacement bool + removeLocal bool +} + var errInvalidECPlacement = errors.New("invalid EC placement: EC placement must have one placement vector") func (p *Policer) processECContainerObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { @@ -72,30 +81,38 @@ func (p *Policer) processECContainerECObject(ctx context.Context, objInfo object default: } - validPlacement := p.processECChunk(ctx, objInfo, nn[0]) - if !validPlacement { - p.pullRequiredECChunks(ctx, objInfo, nn[0]) + res := p.processECChunk(ctx, objInfo, nn[0]) + if !res.validPlacement { + // drop local chunk only if all required chunks are in place + res.removeLocal = res.removeLocal && p.pullRequiredECChunks(ctx, objInfo, nn[0]) + } + p.adjustECPlacement(ctx, objInfo, nn[0]) + + if res.removeLocal { + p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address)) + p.cbRedundantCopy(ctx, objInfo.Address) } return nil } // processECChunk replicates EC chunk if needed. -// Returns True if current chunk should be stored on current node. -func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) bool { +func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) ecChunkProcessResult { var removeLocalChunk bool requiredNode := nodes[int(objInfo.ECInfo.Index)%(len(nodes))] if p.cfg.netmapKeys.IsLocalKey(requiredNode.PublicKey()) { // current node is required node, we are happy - return true + return ecChunkProcessResult{ + validPlacement: true, + } } if requiredNode.IsMaintenance() { // consider maintenance mode has object, but do not drop local copy p.log.Debug(logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) - return false + return ecChunkProcessResult{} } callCtx, cancel := context.WithTimeout(ctx, p.headTimeout) - _, err := p.remoteHeader(callCtx, requiredNode, objInfo.Address) + _, err := p.remoteHeader(callCtx, requiredNode, objInfo.Address, false) cancel() if err == nil { @@ -115,23 +132,138 @@ func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, n p.log.Error(logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", objInfo.Address), zap.String("error", err.Error())) } - if removeLocalChunk { - p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address)) - p.cbRedundantCopy(ctx, objInfo.Address) + return ecChunkProcessResult{ + removeLocal: removeLocalChunk, + } +} + +func (p *Policer) pullRequiredECChunks(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) bool { + var parentAddress oid.Address + parentAddress.SetContainer(objInfo.Address.Container()) + parentAddress.SetObject(objInfo.ECInfo.ParentID) + + requiredChunkIndexes := p.collectRequiredECChunks(nodes, objInfo) + if len(requiredChunkIndexes) == 0 { + p.log.Info(logs.PolicerNodeIsNotECObjectNode, zap.Stringer("object", objInfo.ECInfo.ParentID)) + return true } + err := p.resolveLocalECChunks(ctx, parentAddress, requiredChunkIndexes) + if err != nil { + p.log.Error(logs.PolicerFailedToGetLocalECChunks, zap.Error(err), zap.Stringer("object", parentAddress)) + return false + } + if len(requiredChunkIndexes) == 0 { + return true + } + + indexToObjectID := make(map[uint32]oid.ID) + success := p.resolveRemoteECChunks(ctx, parentAddress, nodes, requiredChunkIndexes, indexToObjectID) + if !success { + return false + } + + for index, candidates := range requiredChunkIndexes { + var addr oid.Address + addr.SetContainer(objInfo.Address.Container()) + addr.SetObject(indexToObjectID[index]) + p.replicator.HandlePullTask(ctx, replicator.Task{ + Addr: addr, + Nodes: candidates, + }) + } + // there was some missing chunks, it's not ok return false } -func (p *Policer) pullRequiredECChunks(_ context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) { - requiredChunkIndexes := make(map[uint32]struct{}) +func (p *Policer) collectRequiredECChunks(nodes []netmap.NodeInfo, objInfo objectcore.Info) map[uint32][]netmap.NodeInfo { + requiredChunkIndexes := make(map[uint32][]netmap.NodeInfo) for i, n := range nodes { + if uint32(i) == objInfo.ECInfo.Total { + break + } if p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) { - requiredChunkIndexes[uint32(i)] = struct{}{} + requiredChunkIndexes[uint32(i)] = []netmap.NodeInfo{} } } - if len(requiredChunkIndexes) == 0 { - p.log.Info(logs.PolicerNodeIsNotContainerNodeForECObject, zap.Stringer("object", objInfo.ECInfo.ParentID)) - return + return requiredChunkIndexes +} + +func (p *Policer) resolveLocalECChunks(ctx context.Context, parentAddress oid.Address, required map[uint32][]netmap.NodeInfo) error { + _, err := p.localHeader(ctx, parentAddress) + var eiErr *objectSDK.ECInfoError + if err == nil { // should not be happen + return errNoECinfoReturnded + } + if !errors.As(err, &eiErr) { + return err + } + for _, ch := range eiErr.ECInfo().Chunks { + delete(required, ch.Index) + } + return nil +} + +func (p *Policer) resolveRemoteECChunks(ctx context.Context, parentAddress oid.Address, nodes []netmap.NodeInfo, required map[uint32][]netmap.NodeInfo, indexToObjectID map[uint32]oid.ID) bool { + var eiErr *objectSDK.ECInfoError + for _, n := range nodes { + if p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) { + continue + } + _, err := p.remoteHeader(ctx, n, parentAddress, true) + if !errors.As(err, &eiErr) { + continue + } + for _, ch := range eiErr.ECInfo().Chunks { + if candidates, ok := required[ch.Index]; ok { + candidates = append(candidates, n) + required[ch.Index] = candidates + + var chunkID oid.ID + if err := chunkID.ReadFromV2(ch.ID); err != nil { + p.log.Error(logs.PolicerFailedToDecodeECChunkID, zap.Error(err), zap.Stringer("object", parentAddress)) + return false + } + if existed, ok := indexToObjectID[ch.Index]; ok && existed != chunkID { + p.log.Error(logs.PolicerDifferentObjectIDForTheSameECChunk, zap.Stringer("first", existed), + zap.Stringer("second", chunkID), zap.Stringer("object", parentAddress)) + return false + } + indexToObjectID[ch.Index] = chunkID + } + } + } + + for index, candidates := range required { + if len(candidates) == 0 { + p.log.Error(logs.PolicerMissingECChunk, zap.Stringer("object", parentAddress), zap.Uint32("index", index)) + return false + } + } + + return true +} + +func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) { + var parentAddress oid.Address + parentAddress.SetContainer(objInfo.Address.Container()) + parentAddress.SetObject(objInfo.ECInfo.ParentID) + var eiErr *objectSDK.ECInfoError + for idx, n := range nodes { + if uint32(idx) == objInfo.ECInfo.Total { + return + } + if p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) { + continue + } + _, err := p.remoteHeader(ctx, n, parentAddress, true) + if errors.As(err, &eiErr) { + continue + } + p.replicator.HandleReplicationTask(ctx, replicator.Task{ + NumCopies: 1, + Addr: objInfo.Address, + Nodes: []netmap.NodeInfo{n}, + }, newNodeCache()) } } diff --git a/pkg/services/policer/ec_test.go b/pkg/services/policer/ec_test.go new file mode 100644 index 0000000000..3957c112b9 --- /dev/null +++ b/pkg/services/policer/ec_test.go @@ -0,0 +1,402 @@ +package policer + +import ( + "bytes" + "context" + "errors" + "fmt" + "sync/atomic" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "github.com/stretchr/testify/require" +) + +func TestECChunkHasValidPlacement(t *testing.T) { + t.Parallel() + chunkAddress := oidtest.Address() + parentID := oidtest.ID() + + var policy netmapSDK.PlacementPolicy + require.NoError(t, policy.DecodeString("EC 2.1")) + + cnr := &container.Container{} + cnr.Value.Init() + cnr.Value.SetPlacementPolicy(policy) + containerSrc := containerSrc{ + get: func(id cid.ID) (*container.Container, error) { + if id.Equals(chunkAddress.Container()) { + return cnr, nil + } + return nil, new(apistatus.ContainerNotFound) + }, + } + + nodes := make([]netmapSDK.NodeInfo, 4) + for i := range nodes { + nodes[i].SetPublicKey([]byte{byte(i)}) + } + + placementBuilder := func(cnr cid.ID, obj *oid.ID, p netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { + if cnr.Equals(chunkAddress.Container()) && obj.Equals(parentID) { + return [][]netmapSDK.NodeInfo{nodes}, nil + } + return nil, errors.New("unexpected placement build") + } + + headFn := func(_ context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { + require.True(t, raw, "remote header for parent object must be called with raw flag") + index := int(ni.PublicKey()[0]) + require.True(t, index == 1 || index == 2, "invalid node to get parent header") + require.True(t, a.Container() == chunkAddress.Container() && a.Object() == parentID, "invalid address to get remote header") + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(oidtest.ID()) + ch.Index = uint32(index) + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + + p := New( + WithContainerSource(containerSrc), + WithPlacementBuilder(placementBuilderFunc(placementBuilder)), + WithNetmapKeys(announcedKeysFunc(func(k []byte) bool { + return bytes.Equal(k, nodes[0].PublicKey()) + })), + WithRemoteObjectHeaderFunc(headFn), + WithPool(testPool(t)), + ) + + objInfo := objectcore.Info{ + Address: chunkAddress, + Type: objectSDK.TypeRegular, + ECInfo: &objectcore.ECInfo{ + ParentID: parentID, + Index: 0, + Total: 3, + }, + } + err := p.processObject(context.Background(), objInfo) + require.NoError(t, err) +} + +func TestECChunkHasInvalidPlacement(t *testing.T) { + t.Parallel() + chunkAddress := oidtest.Address() + parentID := oidtest.ID() + chunkObject := objectSDK.New() + chunkObject.SetContainerID(chunkAddress.Container()) + chunkObject.SetID(chunkAddress.Object()) + chunkObject.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) + chunkObject.SetPayloadSize(uint64(10)) + chunkObject.SetECHeader(objectSDK.NewECHeader(parentID, 1, 3, []byte{}, 0)) + + var policy netmapSDK.PlacementPolicy + require.NoError(t, policy.DecodeString("EC 2.1")) + + cnr := &container.Container{} + cnr.Value.Init() + cnr.Value.SetPlacementPolicy(policy) + containerSrc := containerSrc{ + get: func(id cid.ID) (*container.Container, error) { + if id.Equals(chunkAddress.Container()) { + return cnr, nil + } + return nil, new(apistatus.ContainerNotFound) + }, + } + + nodes := make([]netmapSDK.NodeInfo, 4) + for i := range nodes { + nodes[i].SetPublicKey([]byte{byte(i)}) + } + + placementBuilder := func(cnr cid.ID, obj *oid.ID, p netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { + if cnr.Equals(chunkAddress.Container()) && obj.Equals(parentID) { + return [][]netmapSDK.NodeInfo{nodes}, nil + } + return nil, errors.New("unexpected placement build") + } + + objInfo := objectcore.Info{ + Address: chunkAddress, + Type: objectSDK.TypeRegular, + ECInfo: &objectcore.ECInfo{ + ParentID: parentID, + Index: 1, + Total: 3, + }, + } + + t.Run("node0 has chunk1, node1 has chunk0 and chunk1", func(t *testing.T) { + // policer should pull chunk0 on first run and drop chunk1 on second run + var allowDrop bool + requiredChunkID := oidtest.ID() + headFn := func(_ context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { + if bytes.Equal(ni.PublicKey(), nodes[1].PublicKey()) && a == chunkAddress && !raw { + return chunkObject, nil + } + if bytes.Equal(ni.PublicKey(), nodes[1].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(oidtest.ID()) + ch.Index = 1 + ch.Total = 3 + ei.AddChunk(ch) + ch.Index = 0 + ch.SetID(requiredChunkID) + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + if bytes.Equal(ni.PublicKey(), nodes[2].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(oidtest.ID()) + ch.Index = 2 + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + if bytes.Equal(ni.PublicKey(), nodes[3].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + return nil, new(apistatus.ObjectNotFound) + } + require.Fail(t, "unexpected remote HEAD") + return nil, fmt.Errorf("unexpected remote HEAD") + } + + localHeadF := func(_ context.Context, addr oid.Address) (*objectSDK.Object, error) { + require.True(t, addr.Container() == chunkAddress.Container() && addr.Object() == parentID, "unexpected local HEAD") + if allowDrop { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(oidtest.ID()) + ch.Index = 1 + ch.Total = 3 + ei.AddChunk(ch) + ch.SetID(requiredChunkID) + ch.Index = 0 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(oidtest.ID()) + ch.Index = 1 + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + + var pullCounter atomic.Int64 + var dropped []oid.Address + p := New( + WithContainerSource(containerSrc), + WithPlacementBuilder(placementBuilderFunc(placementBuilder)), + WithNetmapKeys(announcedKeysFunc(func(k []byte) bool { + return bytes.Equal(k, nodes[0].PublicKey()) + })), + WithRemoteObjectHeaderFunc(headFn), + WithLocalObjectHeaderFunc(localHeadF), + WithReplicator(pullFunc(func(ctx context.Context, r replicator.Task) { + require.True(t, r.Addr.Container() == chunkAddress.Container() && r.Addr.Object() == requiredChunkID && + len(r.Nodes) == 1 && bytes.Equal(r.Nodes[0].PublicKey(), nodes[1].PublicKey()), "invalid pull task") + pullCounter.Add(1) + })), + WithRedundantCopyCallback(func(ctx context.Context, a oid.Address) { + require.True(t, allowDrop, "invalid redundent copy call") + dropped = append(dropped, a) + }), + WithPool(testPool(t)), + ) + + err := p.processObject(context.Background(), objInfo) + require.NoError(t, err) + require.Equal(t, int64(1), pullCounter.Load(), "invalid pull count") + require.Equal(t, 0, len(dropped), "invalid dropped count") + allowDrop = true + err = p.processObject(context.Background(), objInfo) + require.NoError(t, err) + require.Equal(t, int64(1), pullCounter.Load(), "invalid pull count") + require.Equal(t, 1, len(dropped), "invalid dropped count") + require.True(t, chunkAddress.Equals(dropped[0]), "invalid dropped object") + }) + + t.Run("node0 has chunk0 and chunk1, node1 has chunk1", func(t *testing.T) { + // policer should drop chunk1 + headFn := func(_ context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { + if bytes.Equal(ni.PublicKey(), nodes[1].PublicKey()) && a == chunkAddress && !raw { + return chunkObject, nil + } + if bytes.Equal(ni.PublicKey(), nodes[1].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkAddress.Object()) + ch.Index = 1 + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + if bytes.Equal(ni.PublicKey(), nodes[2].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(oidtest.ID()) + ch.Index = 2 + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + if bytes.Equal(ni.PublicKey(), nodes[3].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + return nil, new(apistatus.ObjectNotFound) + } + require.Fail(t, "unexpected remote HEAD") + return nil, fmt.Errorf("unexpected remote HEAD") + } + + localHeadF := func(_ context.Context, addr oid.Address) (*objectSDK.Object, error) { + require.True(t, addr.Container() == chunkAddress.Container() && addr.Object() == parentID, "unexpected local HEAD") + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkAddress.Object()) + ch.Index = 1 + ch.Total = 3 + ei.AddChunk(ch) + ch.SetID(oidtest.ID()) + ch.Index = 0 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + + var dropped []oid.Address + p := New( + WithContainerSource(containerSrc), + WithPlacementBuilder(placementBuilderFunc(placementBuilder)), + WithNetmapKeys(announcedKeysFunc(func(k []byte) bool { + return bytes.Equal(k, nodes[0].PublicKey()) + })), + WithRemoteObjectHeaderFunc(headFn), + WithLocalObjectHeaderFunc(localHeadF), + WithRedundantCopyCallback(func(ctx context.Context, a oid.Address) { + dropped = append(dropped, a) + }), + WithPool(testPool(t)), + ) + + err := p.processObject(context.Background(), objInfo) + require.NoError(t, err) + require.Equal(t, 1, len(dropped), "invalid dropped count") + require.True(t, chunkAddress.Equals(dropped[0]), "invalid dropped object") + }) + + t.Run("node0 has chunk0 and chunk1, node1 has no chunks", func(t *testing.T) { + // policer should replicate chunk1 to node1 on first run and drop chunk1 on node0 on second run + var secondRun bool + headFn := func(_ context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { + if bytes.Equal(ni.PublicKey(), nodes[1].PublicKey()) && a == chunkAddress && !raw { + if !secondRun { + return nil, new(apistatus.ObjectNotFound) + } + return chunkObject, nil + } + if bytes.Equal(ni.PublicKey(), nodes[1].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkAddress.Object()) + ch.Index = 1 + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + if bytes.Equal(ni.PublicKey(), nodes[2].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(oidtest.ID()) + ch.Index = 2 + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + if bytes.Equal(ni.PublicKey(), nodes[3].PublicKey()) && a.Container() == chunkAddress.Container() && + a.Object() == parentID && raw { + return nil, new(apistatus.ObjectNotFound) + } + require.Fail(t, "unexpected remote HEAD") + return nil, fmt.Errorf("unexpected remote HEAD") + } + + localHeadF := func(_ context.Context, addr oid.Address) (*objectSDK.Object, error) { + require.True(t, addr.Container() == chunkAddress.Container() && addr.Object() == parentID, "unexpected local HEAD") + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkAddress.Object()) + ch.Index = 1 + ch.Total = 3 + ei.AddChunk(ch) + ch.SetID(oidtest.ID()) + ch.Index = 0 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + + var dropped []oid.Address + var replicated []replicator.Task + p := New( + WithContainerSource(containerSrc), + WithPlacementBuilder(placementBuilderFunc(placementBuilder)), + WithNetmapKeys(announcedKeysFunc(func(k []byte) bool { + return bytes.Equal(k, nodes[0].PublicKey()) + })), + WithRemoteObjectHeaderFunc(headFn), + WithLocalObjectHeaderFunc(localHeadF), + WithRedundantCopyCallback(func(ctx context.Context, a oid.Address) { + dropped = append(dropped, a) + }), + WithReplicator(replicatorFunc(func(ctx context.Context, t replicator.Task, tr replicator.TaskResult) { + replicated = append(replicated, t) + })), + WithPool(testPool(t)), + ) + + err := p.processObject(context.Background(), objInfo) + require.NoError(t, err) + require.Equal(t, 0, len(dropped), "invalid dropped count") + require.Equal(t, 1, len(replicated), "invalid replicated count") + require.Equal(t, chunkAddress, replicated[0].Addr, "invalid replicated object") + require.True(t, bytes.Equal(replicated[0].Nodes[0].PublicKey(), nodes[1].PublicKey()), "invalid replicate target") + + secondRun = true + err = p.processObject(context.Background(), objInfo) + require.NoError(t, err) + require.Equal(t, 1, len(replicated), "invalid replicated count") + require.Equal(t, chunkAddress, replicated[0].Addr, "invalid replicated object") + require.True(t, bytes.Equal(replicated[0].Nodes[0].PublicKey(), nodes[1].PublicKey()), "invalid replicate target") + require.Equal(t, 1, len(dropped), "invalid dropped count") + require.True(t, chunkAddress.Equals(dropped[0]), "invalid dropped object") + }) +} + +type pullFunc func(context.Context, replicator.Task) + +func (f pullFunc) HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) { + panic("not implemented") +} + +func (f pullFunc) HandlePullTask(ctx context.Context, task replicator.Task) { + f(ctx, task) +} diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 849e5ed8b8..9a646eea64 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -36,10 +36,14 @@ type BuryFunc func(context.Context, oid.Address) error // Replicator is the interface to a consumer of replication tasks. type Replicator interface { HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) + HandlePullTask(ctx context.Context, task replicator.Task) } // RemoteObjectHeaderFunc is the function to obtain HEAD info from a specific remote node. -type RemoteObjectHeaderFunc func(context.Context, netmapSDK.NodeInfo, oid.Address) (*objectSDK.Object, error) +type RemoteObjectHeaderFunc func(context.Context, netmapSDK.NodeInfo, oid.Address, bool) (*objectSDK.Object, error) + +// LocalObjectHeaderFunc is the function to obtain HEAD info from the current node. +type LocalObjectHeaderFunc func(context.Context, oid.Address) (*objectSDK.Object, error) type cfg struct { headTimeout time.Duration @@ -56,6 +60,8 @@ type cfg struct { remoteHeader RemoteObjectHeaderFunc + localHeader LocalObjectHeaderFunc + netmapKeys netmap.AnnouncedKeys replicator Replicator @@ -125,13 +131,20 @@ func WithPlacementBuilder(v placement.Builder) Option { } } -// WithRemoteObjectHeader returns option to set object header receiver of Policer. +// WithRemoteObjectHeader returns option to set remote object header receiver of Policer. func WithRemoteObjectHeaderFunc(v RemoteObjectHeaderFunc) Option { return func(c *cfg) { c.remoteHeader = v } } +// WithLocalObjectHeaderFunc returns option to set local object header receiver of Policer. +func WithLocalObjectHeaderFunc(v LocalObjectHeaderFunc) Option { + return func(c *cfg) { + c.localHeader = v + } +} + // WithNetmapKeys returns option to set tool to work with announced public keys. func WithNetmapKeys(v netmap.AnnouncedKeys) Option { return func(c *cfg) { diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 2c70b1c045..072f21a6f0 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -161,31 +161,6 @@ func TestProcessObject(t *testing.T) { placement: [][]int{{0, 1, 2}}, wantReplicateTo: []int{1, 2}, }, - { - desc: "EC chunk stored valid on current node", - objType: objectSDK.TypeRegular, - nodeCount: 2, - policy: `EC 1.1`, - placement: [][]int{{0}}, - ecInfo: &objectcore.ECInfo{ - ParentID: oidtest.ID(), - Index: 1, - Total: 2, - }, - }, - { - desc: "EC chunk must be replicated to other EC node", - objType: objectSDK.TypeRegular, - nodeCount: 2, - policy: `EC 1.1`, - placement: [][]int{{1}}, - wantReplicateTo: []int{1}, - ecInfo: &objectcore.ECInfo{ - ParentID: oidtest.ID(), - Index: 1, - Total: 2, - }, - }, } for i := range tests { @@ -223,7 +198,7 @@ func TestProcessObject(t *testing.T) { } // Object remote header - headFn := func(_ context.Context, ni netmap.NodeInfo, a oid.Address) (*objectSDK.Object, error) { + headFn := func(_ context.Context, ni netmap.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { index := int(ni.PublicKey()[0]) if a != addr || index < 1 || index >= ti.nodeCount { t.Errorf("unexpected remote object head: node=%+v addr=%v", ni, a) @@ -471,3 +446,7 @@ type replicatorFunc func(context.Context, replicator.Task, replicator.TaskResult func (f replicatorFunc) HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) { f(ctx, task, res) } + +func (f replicatorFunc) HandlePullTask(ctx context.Context, task replicator.Task) { + panic("not implemented") +} diff --git a/pkg/services/replicator/process.go b/pkg/services/replicator/process.go index 06d41b74e9..3d04b70841 100644 --- a/pkg/services/replicator/process.go +++ b/pkg/services/replicator/process.go @@ -32,7 +32,7 @@ func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res T ) }() - ctx, span := tracing.StartSpanFromContext(ctx, "Replicator.HandleTask", + ctx, span := tracing.StartSpanFromContext(ctx, "Replicator.HandleReplicateTask", trace.WithAttributes( attribute.Stringer("address", task.Addr), attribute.Int64("number_of_copies", int64(task.NumCopies)), diff --git a/pkg/services/replicator/pull.go b/pkg/services/replicator/pull.go new file mode 100644 index 0000000000..d178700f67 --- /dev/null +++ b/pkg/services/replicator/pull.go @@ -0,0 +1,72 @@ +package replicator + +import ( + "context" + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" +) + +var errFailedToGetObjectFromAnyNode = errors.New("failed to get object from any node") + +func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { + p.metrics.IncInFlightRequest() + defer p.metrics.DecInFlightRequest() + defer func() { + p.log.Debug(logs.ReplicatorFinishWork, zap.String("type", "pull")) + }() + + ctx, span := tracing.StartSpanFromContext(ctx, "Replicator.HandlePullTask", + trace.WithAttributes( + attribute.Stringer("address", task.Addr), + attribute.Int("nodes_count", len(task.Nodes)), + )) + defer span.End() + + var obj *objectSDK.Object + + for _, node := range task.Nodes { + var err error + obj, err = p.remoteGetter.Get(ctx, getsvc.RemoteGetPrm{ + Address: task.Addr, + Node: node, + }) + if err == nil { + break + } + var endpoints []string + node.IterateNetworkEndpoints(func(s string) bool { + endpoints = append(endpoints, s) + return false + }) + p.log.Error(logs.ReplicatorCouldNotGetObjectFromRemoteStorage, + zap.Stringer("object", task.Addr), + zap.Error(err), + zap.Strings("endpoints", endpoints), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } + + if obj == nil { + p.log.Error(logs.ReplicatorCouldNotGetObjectFromRemoteStorage, + zap.Stringer("object", task.Addr), + zap.Error(errFailedToGetObjectFromAnyNode), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + return + } + + err := engine.Put(ctx, p.localStorage, obj) + if err != nil { + p.log.Error(logs.ReplicatorCouldNotPutObjectToLocalStorage, + zap.Stringer("object", task.Addr), + zap.Error(err), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } +} diff --git a/pkg/services/replicator/replicator.go b/pkg/services/replicator/replicator.go index bb817cb327..a67f2e766f 100644 --- a/pkg/services/replicator/replicator.go +++ b/pkg/services/replicator/replicator.go @@ -4,6 +4,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" @@ -25,6 +26,8 @@ type cfg struct { remoteSender *putsvc.RemoteSender + remoteGetter *getsvc.RemoteGetter + localStorage *engine.StorageEngine metrics MetricsRegister @@ -70,6 +73,12 @@ func WithRemoteSender(v *putsvc.RemoteSender) Option { } } +func WithRemoteGetter(v *getsvc.RemoteGetter) Option { + return func(c *cfg) { + c.remoteGetter = v + } +} + // WithLocalStorage returns option to set local object storage of Replicator. func WithLocalStorage(v *engine.StorageEngine) Option { return func(c *cfg) { From 4ab6c404f7cf401935af4fd1e1a7aa7c22a09dd0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 15 May 2024 15:50:16 +0300 Subject: [PATCH 0565/1413] [#1129] policer: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/check.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 2cdb725051..04456fb207 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -54,11 +54,6 @@ func (p *Policer) processRepContainerObject(ctx context.Context, objInfo objectc c := &placementRequirements{} - var numOfContainerNodes int - for i := range nn { - numOfContainerNodes += len(nn[i]) - } - // cached info about already checked nodes checkedNodes := newNodeCache() From 1cd8562db83b89134c1e4e17085c9713a911c97b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 15 May 2024 16:11:51 +0300 Subject: [PATCH 0566/1413] [#1129] policer: Refactor shortage Drop override inside method. Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/check.go | 21 ++++++++++----------- pkg/services/policer/ec.go | 4 +--- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 04456fb207..7120ba0b86 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -64,7 +64,16 @@ func (p *Policer) processRepContainerObject(ctx context.Context, objInfo objectc default: } - p.processRepNodes(ctx, c, objInfo, nn[i], policy.ReplicaDescriptor(i).NumberOfObjects(), checkedNodes) + shortage := policy.ReplicaDescriptor(i).NumberOfObjects() + if objInfo.Type == objectSDK.TypeLock || objInfo.Type == objectSDK.TypeTombstone || objInfo.IsLinkingObject { + // all nodes of a container must store the `LOCK`, `TOMBSTONE` and linking objects + // for correct object removal protection: + // - `LOCK`, `TOMBSTONE` and linking objects are broadcast on their PUT requests; + // - `LOCK` object removal is a prohibited action in the GC. + shortage = uint32(len(nn[i])) + } + + p.processRepNodes(ctx, c, objInfo, nn[i], shortage, checkedNodes) } if !c.needLocalCopy && c.removeLocalCopy { @@ -89,19 +98,9 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe nodes []netmap.NodeInfo, shortage uint32, checkedNodes nodeCache, ) { addr := objInfo.Address - typ := objInfo.Type // Number of copies that are stored on maintenance nodes. var uncheckedCopies int - - if typ == objectSDK.TypeLock || typ == objectSDK.TypeTombstone || objInfo.IsLinkingObject { - // all nodes of a container must store the `LOCK`, `TOMBSTONE` and linking objects - // for correct object removal protection: - // - `LOCK`, `TOMBSTONE` and linking objects are broadcast on their PUT requests; - // - `LOCK` object removal is a prohibited action in the GC. - shortage = uint32(len(nodes)) - } - for i := 0; shortage > 0 && i < len(nodes); i++ { select { case <-ctx.Done(): diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index 6eca3bc005..fbd389d713 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -52,9 +52,7 @@ func (p *Policer) processECContainerRepObject(ctx context.Context, objInfo objec default: } - rd := policy.ReplicaDescriptor(0) - // processNodes replaces rd.GetECDataCount() + rd.GetECParityCount() for len(nn[0]) for locks, tomstones and linking objects. - p.processRepNodes(ctx, c, objInfo, nn[0], rd.GetECDataCount()+rd.GetECParityCount(), checkedNodes) + p.processRepNodes(ctx, c, objInfo, nn[0], uint32(len(nn[0])), checkedNodes) if !c.needLocalCopy && c.removeLocalCopy { p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, From 0e42126ddcc7d42db01935cd7ba7a4ff4df712c9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 16 May 2024 10:02:41 +0300 Subject: [PATCH 0567/1413] [#1129] object: Fix check owner for EC part Do not validate EC part owner if request from container node. Signed-off-by: Dmitrii Stepanov --- pkg/core/object/fmt.go | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index e266800b25..fa1e40dd0f 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -167,17 +167,29 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { token := obj.SessionToken() ownerID := obj.OwnerID() + if token == nil && obj.ECHeader() != nil { + role, err := v.isIROrContainerNode(obj, binKey) + if err != nil { + return err + } + if role == acl.RoleContainer { + // EC part could be restored or created by container node, so ownerID could not match object signature + return nil + } + return v.checkOwnerKey(ownerID, key) + } + if token == nil || !token.AssertAuthKey(&key) { return v.checkOwnerKey(ownerID, key) } if v.verifyTokenIssuer { - signerIsIROrContainerNode, err := v.isIROrContainerNode(obj, binKey) + role, err := v.isIROrContainerNode(obj, binKey) if err != nil { return err } - if signerIsIROrContainerNode { + if role == acl.RoleContainer || role == acl.RoleInnerRing { return nil } @@ -190,10 +202,10 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { return nil } -func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey []byte) (bool, error) { +func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey []byte) (acl.Role, error) { cnrID, containerIDSet := obj.ContainerID() if !containerIDSet { - return false, errNilCID + return acl.RoleOthers, errNilCID } cnrIDBin := make([]byte, sha256.Size) @@ -201,14 +213,14 @@ func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey [ cnr, err := v.containers.Get(cnrID) if err != nil { - return false, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err) + return acl.RoleOthers, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err) } res, err := v.senderClassifier.IsInnerRingOrContainerNode(signerKey, cnrID, cnr.Value) if err != nil { - return false, err + return acl.RoleOthers, err } - return res.Role == acl.RoleContainer || res.Role == acl.RoleInnerRing, nil + return res.Role, nil } func (v *FormatValidator) checkOwnerKey(id user.ID, key frostfsecdsa.PublicKey) error { From 44f2e8f27fcf6a10ae2b0dc0fdc8842026bcd386 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 16 May 2024 10:05:17 +0300 Subject: [PATCH 0568/1413] [#1129] putSvc: Allow to put single unprepared object to EC container Signed-off-by: Dmitrii Stepanov --- pkg/services/object/put/single.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 43b3b0ac1a..6d2f3dba8b 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -34,10 +34,7 @@ import ( "go.uber.org/zap" ) -var ( - errInvalidPayloadChecksum = errors.New("incorrect payload checksum") - errInvalidECObject = errors.New("object must be splitted to EC parts") -) +var errInvalidPayloadChecksum = errors.New("incorrect payload checksum") type putSingleRequestSigner struct { req *objectAPI.PutSingleRequest @@ -181,10 +178,6 @@ func (s *Service) saveToREPReplicas(ctx context.Context, placement putSinglePlac } func (s *Service) saveToECReplicas(ctx context.Context, placement putSinglePlacement, obj *objectSDK.Object, req *objectAPI.PutSingleRequest, meta object.ContentMeta) error { - if obj.Type() == objectSDK.TypeRegular && obj.ECHeader() == nil { - return errInvalidECObject - } - commonPrm, err := svcutil.CommonPrmFromV2(req) if err != nil { return err From 436c9f555803b67b31a4098a12c6854fad182ba7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 16 May 2024 12:26:49 +0300 Subject: [PATCH 0569/1413] [#1129] policer: Restore EC object Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 21 +- internal/logs/logs.go | 5 + .../{head/remote.go => remote_reader.go} | 62 ++++-- pkg/services/policer/ec.go | 145 ++++++++++++- pkg/services/policer/ec_test.go | 195 ++++++++++++++++-- pkg/services/policer/option.go | 30 +++ pkg/services/policer/policer_test.go | 35 ++-- pkg/services/replicator/put.go | 47 +++++ 8 files changed, 483 insertions(+), 57 deletions(-) rename pkg/services/object/{head/remote.go => remote_reader.go} (55%) create mode 100644 pkg/services/replicator/put.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index af185a8da9..9f34896bc2 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -29,7 +29,6 @@ import ( deletesvcV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete/v2" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" getsvcV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get/v2" - headsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/head" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" putsvcV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put/v2" searchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search" @@ -231,7 +230,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl return err } - remoteHeader := headsvc.NewRemoteHeader(keyStorage, clientConstructor) + remoteReader := objectService.NewRemoteReader(keyStorage, clientConstructor) pol := policer.New( policer.WithLogger(c.log), @@ -243,8 +242,8 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl ), policer.WithRemoteObjectHeaderFunc( func(ctx context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { - prm := new(headsvc.RemoteHeadPrm).WithNodeInfo(ni).WithObjectAddress(a).WithRaw(raw) - return remoteHeader.Head(ctx, prm) + prm := new(objectService.RemoteRequestPrm).WithNodeInfo(ni).WithObjectAddress(a).WithRaw(raw) + return remoteReader.Head(ctx, prm) }, ), policer.WithLocalObjectHeaderFunc(func(ctx context.Context, a oid.Address) (*objectSDK.Object, error) { @@ -256,6 +255,19 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl } return res.Header(), nil }), + policer.WithRemoteObjectGetFunc(func(ctx context.Context, ni netmapSDK.NodeInfo, a oid.Address) (*objectSDK.Object, error) { + prm := new(objectService.RemoteRequestPrm).WithNodeInfo(ni).WithObjectAddress(a) + return remoteReader.Get(ctx, prm) + }), + policer.WithLocalObjectGetFunc(func(ctx context.Context, a oid.Address) (*objectSDK.Object, error) { + var prm engine.GetPrm + prm.WithAddress(a) + res, err := c.cfgObject.cfgLocalStorage.localStorage.Get(ctx, prm) + if err != nil { + return nil, err + } + return res.Object(), nil + }), policer.WithNetmapKeys(c), policer.WithHeadTimeout( policerconfig.HeadTimeout(c.appCfg), @@ -274,6 +286,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl }), policer.WithPool(c.cfgObject.pool.replication), policer.WithMetrics(c.metricsCollector.PolicerMetrics()), + policer.WithKeyStorage(keyStorage), ) c.workers = append(c.workers, worker{ diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 2e89e43040..43fd776242 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -536,4 +536,9 @@ const ( PolicerDifferentObjectIDForTheSameECChunk = "different object IDs for the same EC chunk" ReplicatorCouldNotGetObjectFromRemoteStorage = "could not get object from remote storage" ReplicatorCouldNotPutObjectToLocalStorage = "could not put object to local storage" + PolicerCouldNotGetObjectFromNodeMoving = "could not get EC object from the node, moving current chunk to the node" + PolicerCouldNotRestoreObjectNotEnoughChunks = "could not restore EC object: not enough chunks" + PolicerFailedToRestoreObject = "failed to restore EC object" + PolicerCouldNotGetChunk = "could not get EC chunk" + PolicerCouldNotGetChunks = "could not get EC chunks" ) diff --git a/pkg/services/object/head/remote.go b/pkg/services/object/remote_reader.go similarity index 55% rename from pkg/services/object/head/remote.go rename to pkg/services/object/remote_reader.go index 6d47e37eb6..18b6107cfa 100644 --- a/pkg/services/object/head/remote.go +++ b/pkg/services/object/remote_reader.go @@ -1,4 +1,4 @@ -package headsvc +package object import ( "context" @@ -18,16 +18,16 @@ type ClientConstructor interface { Get(clientcore.NodeInfo) (clientcore.MultiAddressClient, error) } -// RemoteHeader represents utility for getting -// the object header from a remote host. -type RemoteHeader struct { +// RemoteReader represents utility for getting +// the object from a remote host. +type RemoteReader struct { keyStorage *util.KeyStorage clientCache ClientConstructor } -// RemoteHeadPrm groups remote header operation parameters. -type RemoteHeadPrm struct { +// RemoteRequestPrm groups remote operation parameters. +type RemoteRequestPrm struct { addr oid.Address raw bool node netmap.NodeInfo @@ -37,16 +37,16 @@ const remoteOpTTL = 1 var ErrNotFound = errors.New("object header not found") -// NewRemoteHeader creates, initializes and returns new RemoteHeader instance. -func NewRemoteHeader(keyStorage *util.KeyStorage, cache ClientConstructor) *RemoteHeader { - return &RemoteHeader{ +// NewRemoteReader creates, initializes and returns new RemoteHeader instance. +func NewRemoteReader(keyStorage *util.KeyStorage, cache ClientConstructor) *RemoteReader { + return &RemoteReader{ keyStorage: keyStorage, clientCache: cache, } } // WithNodeInfo sets information about the remote node. -func (p *RemoteHeadPrm) WithNodeInfo(v netmap.NodeInfo) *RemoteHeadPrm { +func (p *RemoteRequestPrm) WithNodeInfo(v netmap.NodeInfo) *RemoteRequestPrm { if p != nil { p.node = v } @@ -55,7 +55,7 @@ func (p *RemoteHeadPrm) WithNodeInfo(v netmap.NodeInfo) *RemoteHeadPrm { } // WithObjectAddress sets object address. -func (p *RemoteHeadPrm) WithObjectAddress(v oid.Address) *RemoteHeadPrm { +func (p *RemoteRequestPrm) WithObjectAddress(v oid.Address) *RemoteRequestPrm { if p != nil { p.addr = v } @@ -63,7 +63,7 @@ func (p *RemoteHeadPrm) WithObjectAddress(v oid.Address) *RemoteHeadPrm { return p } -func (p *RemoteHeadPrm) WithRaw(v bool) *RemoteHeadPrm { +func (p *RemoteRequestPrm) WithRaw(v bool) *RemoteRequestPrm { if p != nil { p.raw = v } @@ -71,7 +71,7 @@ func (p *RemoteHeadPrm) WithRaw(v bool) *RemoteHeadPrm { } // Head requests object header from the remote node. -func (h *RemoteHeader) Head(ctx context.Context, prm *RemoteHeadPrm) (*objectSDK.Object, error) { +func (h *RemoteReader) Head(ctx context.Context, prm *RemoteRequestPrm) (*objectSDK.Object, error) { key, err := h.keyStorage.GetKey(nil) if err != nil { return nil, fmt.Errorf("(%T) could not receive private key: %w", h, err) @@ -106,3 +106,39 @@ func (h *RemoteHeader) Head(ctx context.Context, prm *RemoteHeadPrm) (*objectSDK return res.Header(), nil } + +func (h *RemoteReader) Get(ctx context.Context, prm *RemoteRequestPrm) (*objectSDK.Object, error) { + key, err := h.keyStorage.GetKey(nil) + if err != nil { + return nil, fmt.Errorf("(%T) could not receive private key: %w", h, err) + } + + var info clientcore.NodeInfo + + err = clientcore.NodeInfoFromRawNetmapElement(&info, netmapCore.Node(prm.node)) + if err != nil { + return nil, fmt.Errorf("parse client node info: %w", err) + } + + c, err := h.clientCache.Get(info) + if err != nil { + return nil, fmt.Errorf("(%T) could not create SDK client %s: %w", h, info.AddressGroup(), err) + } + + var getPrm internalclient.GetObjectPrm + + getPrm.SetClient(c) + getPrm.SetPrivateKey(key) + getPrm.SetAddress(prm.addr) + getPrm.SetTTL(remoteOpTTL) + if prm.raw { + getPrm.SetRawFlag() + } + + res, err := internalclient.GetObject(ctx, getPrm) + if err != nil { + return nil, fmt.Errorf("(%T) could not head object in %s: %w", h, info.AddressGroup(), err) + } + + return res.Object(), nil +} diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index fbd389d713..b15efdd159 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -2,6 +2,7 @@ package policer import ( "context" + "encoding/hex" "errors" "fmt" @@ -11,8 +12,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" + "golang.org/x/sync/errgroup" ) var errNoECinfoReturnded = errors.New("no EC info returned") @@ -84,7 +87,7 @@ func (p *Policer) processECContainerECObject(ctx context.Context, objInfo object // drop local chunk only if all required chunks are in place res.removeLocal = res.removeLocal && p.pullRequiredECChunks(ctx, objInfo, nn[0]) } - p.adjustECPlacement(ctx, objInfo, nn[0]) + p.adjustECPlacement(ctx, objInfo, nn[0], policy) if res.removeLocal { p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address)) @@ -224,7 +227,7 @@ func (p *Policer) resolveRemoteECChunks(ctx context.Context, parentAddress oid.A } if existed, ok := indexToObjectID[ch.Index]; ok && existed != chunkID { p.log.Error(logs.PolicerDifferentObjectIDForTheSameECChunk, zap.Stringer("first", existed), - zap.Stringer("second", chunkID), zap.Stringer("object", parentAddress)) + zap.Stringer("second", chunkID), zap.Stringer("object", parentAddress), zap.Uint32("index", ch.Index)) return false } indexToObjectID[ch.Index] = chunkID @@ -242,26 +245,146 @@ func (p *Policer) resolveRemoteECChunks(ctx context.Context, parentAddress oid.A return true } -func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) { +func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo, policy netmap.PlacementPolicy) { var parentAddress oid.Address parentAddress.SetContainer(objInfo.Address.Container()) parentAddress.SetObject(objInfo.ECInfo.ParentID) var eiErr *objectSDK.ECInfoError + resolved := make(map[uint32][]netmap.NodeInfo) + chunkIDs := make(map[uint32]oid.ID) + restore := true // do not restore EC chunks if some node returned error for idx, n := range nodes { - if uint32(idx) == objInfo.ECInfo.Total { + if uint32(idx) >= objInfo.ECInfo.Total && uint32(len(resolved)) == objInfo.ECInfo.Total { return } + var err error if p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) { - continue + _, err = p.localHeader(ctx, parentAddress) + } else { + _, err = p.remoteHeader(ctx, n, parentAddress, true) } - _, err := p.remoteHeader(ctx, n, parentAddress, true) + if errors.As(err, &eiErr) { + for _, ch := range eiErr.ECInfo().Chunks { + resolved[ch.Index] = append(resolved[ch.Index], n) + var ecInfoChunkID oid.ID + if err := ecInfoChunkID.ReadFromV2(ch.ID); err != nil { + p.log.Error(logs.PolicerFailedToDecodeECChunkID, zap.Error(err), zap.Stringer("object", parentAddress)) + return + } + if chunkID, exist := chunkIDs[ch.Index]; exist && chunkID != ecInfoChunkID { + p.log.Error(logs.PolicerDifferentObjectIDForTheSameECChunk, zap.Stringer("first", chunkID), + zap.Stringer("second", ecInfoChunkID), zap.Stringer("object", parentAddress), zap.Uint32("index", ch.Index)) + return + } + chunkIDs[ch.Index] = ecInfoChunkID + } + } else if !p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) && uint32(idx) < objInfo.ECInfo.Total { + p.log.Warn(logs.PolicerCouldNotGetObjectFromNodeMoving, zap.String("node", hex.EncodeToString(n.PublicKey())), zap.Stringer("object", parentAddress), zap.Error(err)) + p.replicator.HandleReplicationTask(ctx, replicator.Task{ + NumCopies: 1, + Addr: objInfo.Address, + Nodes: []netmap.NodeInfo{n}, + }, newNodeCache()) + restore = false + } + } + if !restore || uint32(len(resolved)) == objInfo.ECInfo.Total { + return + } + if objInfo.ECInfo.Total-uint32(len(resolved)) > policy.ReplicaDescriptor(0).GetECParityCount() { + var found []uint32 + for i := range resolved { + found = append(found, i) + } + p.log.Error(logs.PolicerCouldNotRestoreObjectNotEnoughChunks, zap.Stringer("object", parentAddress), zap.Uint32s("found_chunks", found)) + return + } + p.restoreECObject(ctx, objInfo, parentAddress, nodes, resolved, chunkIDs, policy) +} + +func (p *Policer) restoreECObject(ctx context.Context, objInfo objectcore.Info, parentAddress oid.Address, nodes []netmap.NodeInfo, existedChunks map[uint32][]netmap.NodeInfo, chunkIDs map[uint32]oid.ID, policy netmap.PlacementPolicy) { + c, err := erasurecode.NewConstructor(int(policy.ReplicaDescriptor(0).GetECDataCount()), int(policy.ReplicaDescriptor(0).GetECParityCount())) + if err != nil { + p.log.Error(logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) + return + } + parts := p.collectExistedChunks(ctx, objInfo, existedChunks, parentAddress, chunkIDs) + if parts == nil { + return + } + key, err := p.keyStorage.GetKey(nil) + if err != nil { + p.log.Error(logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) + return + } + required := make([]bool, len(parts)) + for i, p := range parts { + if p == nil { + required[i] = true + } + } + if err := c.ReconstructParts(parts, required, key); err != nil { + p.log.Error(logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) + return + } + for idx, part := range parts { + if _, exists := existedChunks[uint32(idx)]; exists { continue } - p.replicator.HandleReplicationTask(ctx, replicator.Task{ - NumCopies: 1, - Addr: objInfo.Address, - Nodes: []netmap.NodeInfo{n}, - }, newNodeCache()) + var addr oid.Address + addr.SetContainer(parentAddress.Container()) + pID, _ := part.ID() + addr.SetObject(pID) + targetNode := nodes[idx%len(nodes)] + if p.cfg.netmapKeys.IsLocalKey(targetNode.PublicKey()) { + p.replicator.HandleLocalPutTask(ctx, replicator.Task{ + Addr: addr, + Obj: part, + }) + } else { + p.replicator.HandleReplicationTask(ctx, replicator.Task{ + NumCopies: 1, + Addr: addr, + Nodes: []netmap.NodeInfo{targetNode}, + Obj: part, + }, newNodeCache()) + } } } + +func (p *Policer) collectExistedChunks(ctx context.Context, objInfo objectcore.Info, existedChunks map[uint32][]netmap.NodeInfo, parentAddress oid.Address, chunkIDs map[uint32]oid.ID) []*objectSDK.Object { + parts := make([]*objectSDK.Object, objInfo.ECInfo.Total) + errGroup, egCtx := errgroup.WithContext(ctx) + for idx, nodes := range existedChunks { + idx := idx + nodes := nodes + errGroup.Go(func() error { + var objID oid.Address + objID.SetContainer(parentAddress.Container()) + objID.SetObject(chunkIDs[idx]) + var obj *objectSDK.Object + var err error + for _, node := range nodes { + if p.cfg.netmapKeys.IsLocalKey(node.PublicKey()) { + obj, err = p.localObject(egCtx, objID) + } else { + obj, err = p.remoteObject(egCtx, node, objID) + } + if err == nil { + break + } + p.log.Warn(logs.PolicerCouldNotGetChunk, zap.Stringer("object", parentAddress), zap.Stringer("chunkID", objID), zap.Error(err), zap.String("node", hex.EncodeToString(node.PublicKey()))) + } + if obj != nil { + parts[idx] = obj + } + return nil + }) + } + if err := errGroup.Wait(); err != nil { + p.log.Error(logs.PolicerCouldNotGetChunks, zap.Stringer("object", parentAddress), zap.Error(err)) + return nil + } + return parts +} diff --git a/pkg/services/policer/ec_test.go b/pkg/services/policer/ec_test.go index 3957c112b9..3ac9699f0b 100644 --- a/pkg/services/policer/ec_test.go +++ b/pkg/services/policer/ec_test.go @@ -3,6 +3,7 @@ package policer import ( "bytes" "context" + "crypto/rand" "errors" "fmt" "sync/atomic" @@ -10,13 +11,16 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) @@ -52,7 +56,7 @@ func TestECChunkHasValidPlacement(t *testing.T) { return nil, errors.New("unexpected placement build") } - headFn := func(_ context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { + remoteHeadFn := func(_ context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { require.True(t, raw, "remote header for parent object must be called with raw flag") index := int(ni.PublicKey()[0]) require.True(t, index == 1 || index == 2, "invalid node to get parent header") @@ -66,13 +70,25 @@ func TestECChunkHasValidPlacement(t *testing.T) { return nil, objectSDK.NewECInfoError(ei) } + localHeadFn := func(_ context.Context, a oid.Address) (*objectSDK.Object, error) { + require.True(t, a.Container() == chunkAddress.Container() && a.Object() == parentID, "invalid address to get remote header") + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(oidtest.ID()) + ch.Index = uint32(0) + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + p := New( WithContainerSource(containerSrc), WithPlacementBuilder(placementBuilderFunc(placementBuilder)), WithNetmapKeys(announcedKeysFunc(func(k []byte) bool { return bytes.Equal(k, nodes[0].PublicKey()) })), - WithRemoteObjectHeaderFunc(headFn), + WithRemoteObjectHeaderFunc(remoteHeadFn), + WithLocalObjectHeaderFunc(localHeadFn), WithPool(testPool(t)), ) @@ -209,11 +225,13 @@ func TestECChunkHasInvalidPlacement(t *testing.T) { })), WithRemoteObjectHeaderFunc(headFn), WithLocalObjectHeaderFunc(localHeadF), - WithReplicator(pullFunc(func(ctx context.Context, r replicator.Task) { - require.True(t, r.Addr.Container() == chunkAddress.Container() && r.Addr.Object() == requiredChunkID && - len(r.Nodes) == 1 && bytes.Equal(r.Nodes[0].PublicKey(), nodes[1].PublicKey()), "invalid pull task") - pullCounter.Add(1) - })), + WithReplicator(&testReplicator{ + handlePullTask: (func(ctx context.Context, r replicator.Task) { + require.True(t, r.Addr.Container() == chunkAddress.Container() && r.Addr.Object() == requiredChunkID && + len(r.Nodes) == 1 && bytes.Equal(r.Nodes[0].PublicKey(), nodes[1].PublicKey()), "invalid pull task") + pullCounter.Add(1) + }), + }), WithRedundantCopyCallback(func(ctx context.Context, a oid.Address) { require.True(t, allowDrop, "invalid redundent copy call") dropped = append(dropped, a) @@ -367,9 +385,11 @@ func TestECChunkHasInvalidPlacement(t *testing.T) { WithRedundantCopyCallback(func(ctx context.Context, a oid.Address) { dropped = append(dropped, a) }), - WithReplicator(replicatorFunc(func(ctx context.Context, t replicator.Task, tr replicator.TaskResult) { - replicated = append(replicated, t) - })), + WithReplicator(&testReplicator{ + handleReplicationTask: func(ctx context.Context, t replicator.Task, tr replicator.TaskResult) { + replicated = append(replicated, t) + }, + }), WithPool(testPool(t)), ) @@ -391,12 +411,155 @@ func TestECChunkHasInvalidPlacement(t *testing.T) { }) } -type pullFunc func(context.Context, replicator.Task) +func TestECChunkRestore(t *testing.T) { + // node0 has chunk0, node1 has chunk1 + // policer should replicate chunk0 to node2 on the first run + // then restore EC object and replicate chunk2 to node2 on the second run + t.Parallel() -func (f pullFunc) HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) { - panic("not implemented") -} + payload := make([]byte, 64) + rand.Read(payload) + parentAddress := oidtest.Address() + parentObject := objectSDK.New() + parentObject.SetContainerID(parentAddress.Container()) + parentObject.SetPayload(payload) + parentObject.SetPayloadSize(64) + objectSDK.CalculateAndSetPayloadChecksum(parentObject) + err := objectSDK.CalculateAndSetID(parentObject) + require.NoError(t, err) + id, _ := parentObject.ID() + parentAddress.SetObject(id) -func (f pullFunc) HandlePullTask(ctx context.Context, task replicator.Task) { - f(ctx, task) + chunkIDs := make([]oid.ID, 3) + c, err := erasurecode.NewConstructor(2, 1) + require.NoError(t, err) + key, err := keys.NewPrivateKey() + require.NoError(t, err) + chunks, err := c.Split(parentObject, &key.PrivateKey) + require.NoError(t, err) + for i, ch := range chunks { + chunkIDs[i], _ = ch.ID() + } + + var policy netmapSDK.PlacementPolicy + require.NoError(t, policy.DecodeString("EC 2.1")) + + cnr := &container.Container{} + cnr.Value.Init() + cnr.Value.SetPlacementPolicy(policy) + containerSrc := containerSrc{ + get: func(id cid.ID) (*container.Container, error) { + if id.Equals(parentAddress.Container()) { + return cnr, nil + } + return nil, new(apistatus.ContainerNotFound) + }, + } + + nodes := make([]netmapSDK.NodeInfo, 4) + for i := range nodes { + nodes[i].SetPublicKey([]byte{byte(i)}) + } + + placementBuilder := func(cnr cid.ID, obj *oid.ID, p netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { + if cnr.Equals(parentAddress.Container()) && obj.Equals(parentAddress.Object()) { + return [][]netmapSDK.NodeInfo{nodes}, nil + } + return nil, errors.New("unexpected placement build") + } + var secondRun bool + remoteHeadFn := func(_ context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { + require.True(t, raw, "remote header for parent object must be called with raw flag") + index := int(ni.PublicKey()[0]) + require.True(t, index == 1 || index == 2 || index == 3, "invalid node to get parent header") + require.True(t, a == parentAddress, "invalid address to get remote header") + if index == 1 { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkIDs[1]) + ch.Index = uint32(1) + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + if index == 2 && secondRun { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkIDs[0]) + ch.Index = uint32(0) + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + return nil, new(apistatus.ObjectNotFound) + } + + localHeadFn := func(_ context.Context, a oid.Address) (*objectSDK.Object, error) { + require.True(t, a == parentAddress, "invalid address to get remote header") + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkIDs[0]) + ch.Index = uint32(0) + ch.Total = 3 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + + var replicatedObj []*objectSDK.Object + p := New( + WithContainerSource(containerSrc), + WithPlacementBuilder(placementBuilderFunc(placementBuilder)), + WithNetmapKeys(announcedKeysFunc(func(k []byte) bool { + return bytes.Equal(k, nodes[0].PublicKey()) + })), + WithRemoteObjectHeaderFunc(remoteHeadFn), + WithLocalObjectHeaderFunc(localHeadFn), + WithReplicator(&testReplicator{ + handleReplicationTask: func(ctx context.Context, t replicator.Task, tr replicator.TaskResult) { + if t.Obj != nil { + replicatedObj = append(replicatedObj, t.Obj) + } + }, + }), + WithLocalObjectGetFunc(func(ctx context.Context, a oid.Address) (*objectSDK.Object, error) { + require.True(t, a.Container() == parentAddress.Container() && a.Object() == chunkIDs[0], "invalid local object request") + return chunks[0], nil + }), + WithRemoteObjectGetFunc(func(ctx context.Context, ni netmapSDK.NodeInfo, a oid.Address) (*objectSDK.Object, error) { + index := ni.PublicKey()[0] + if index == 2 { + return nil, new(apistatus.ObjectNotFound) + } + return chunks[index], nil + }), + WithPool(testPool(t)), + WithKeyStorage(util.NewKeyStorage(&key.PrivateKey, nil, nil)), + ) + + var chunkAddress oid.Address + chunkAddress.SetContainer(parentAddress.Container()) + chunkAddress.SetObject(chunkIDs[0]) + objInfo := objectcore.Info{ + Address: chunkAddress, + Type: objectSDK.TypeRegular, + ECInfo: &objectcore.ECInfo{ + ParentID: parentAddress.Object(), + Index: 0, + Total: 3, + }, + } + err = p.processObject(context.Background(), objInfo) + require.NoError(t, err) + secondRun = true + err = p.processObject(context.Background(), objInfo) + require.NoError(t, err) + + require.Equal(t, 1, len(replicatedObj), "invalid replicated objects count") + chunks[2].SetSignature(nil) + expectedData, err := chunks[2].MarshalJSON() + require.NoError(t, err) + replicatedObj[0].SetSignature(nil) + actualData, err := replicatedObj[0].MarshalJSON() + require.NoError(t, err) + require.EqualValues(t, string(expectedData), string(actualData), "invalid restored objects") } diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 9a646eea64..9dbfd8b9ff 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" @@ -37,6 +38,7 @@ type BuryFunc func(context.Context, oid.Address) error type Replicator interface { HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) HandlePullTask(ctx context.Context, task replicator.Task) + HandleLocalPutTask(ctx context.Context, task replicator.Task) } // RemoteObjectHeaderFunc is the function to obtain HEAD info from a specific remote node. @@ -45,6 +47,10 @@ type RemoteObjectHeaderFunc func(context.Context, netmapSDK.NodeInfo, oid.Addres // LocalObjectHeaderFunc is the function to obtain HEAD info from the current node. type LocalObjectHeaderFunc func(context.Context, oid.Address) (*objectSDK.Object, error) +type RemoteObjectGetFunc func(context.Context, netmapSDK.NodeInfo, oid.Address) (*objectSDK.Object, error) + +type LocalObjectGetFunc func(context.Context, oid.Address) (*objectSDK.Object, error) + type cfg struct { headTimeout time.Duration @@ -75,6 +81,12 @@ type cfg struct { evictDuration, sleepDuration time.Duration metrics MetricsRegister + + remoteObject RemoteObjectGetFunc + + localObject LocalObjectGetFunc + + keyStorage *util.KeyStorage } func defaultCfg() *cfg { @@ -145,6 +157,18 @@ func WithLocalObjectHeaderFunc(v LocalObjectHeaderFunc) Option { } } +func WithRemoteObjectGetFunc(v RemoteObjectGetFunc) Option { + return func(c *cfg) { + c.remoteObject = v + } +} + +func WithLocalObjectGetFunc(v LocalObjectGetFunc) Option { + return func(c *cfg) { + c.localObject = v + } +} + // WithNetmapKeys returns option to set tool to work with announced public keys. func WithNetmapKeys(v netmap.AnnouncedKeys) Option { return func(c *cfg) { @@ -182,3 +206,9 @@ func WithMetrics(m MetricsRegister) Option { c.metrics = m } } + +func WithKeyStorage(ks *util.KeyStorage) Option { + return func(c *cfg) { + c.keyStorage = ks + } +} diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 072f21a6f0..e353ea4286 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -249,12 +249,14 @@ func TestProcessObject(t *testing.T) { require.True(t, a.Equals(addr), "unexpected redundant copy callback: a=%v", a) gotRemoveRedundant = true }), - WithReplicator(replicatorFunc(func(_ context.Context, task replicator.Task, res replicator.TaskResult) { - require.True(t, task.Addr.Equals(addr), "unexpected replicator task: %+v", task) - for _, node := range task.Nodes { - gotReplicateTo = append(gotReplicateTo, int(node.PublicKey()[0])) - } - })), + WithReplicator(&testReplicator{ + handleReplicationTask: func(_ context.Context, task replicator.Task, res replicator.TaskResult) { + require.True(t, task.Addr.Equals(addr), "unexpected replicator task: %+v", task) + for _, node := range task.Nodes { + gotReplicateTo = append(gotReplicateTo, int(node.PublicKey()[0])) + } + }, + }), WithPool(testPool(t)), ) @@ -440,13 +442,20 @@ type announcedKeysFunc func([]byte) bool func (f announcedKeysFunc) IsLocalKey(k []byte) bool { return f(k) } -// replicatorFunc is a Replicator backed by a function. -type replicatorFunc func(context.Context, replicator.Task, replicator.TaskResult) - -func (f replicatorFunc) HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) { - f(ctx, task, res) +type testReplicator struct { + handleReplicationTask func(ctx context.Context, task replicator.Task, res replicator.TaskResult) + handleLocalPutTask func(ctx context.Context, task replicator.Task) + handlePullTask func(ctx context.Context, task replicator.Task) } -func (f replicatorFunc) HandlePullTask(ctx context.Context, task replicator.Task) { - panic("not implemented") +func (r *testReplicator) HandleReplicationTask(ctx context.Context, task replicator.Task, res replicator.TaskResult) { + r.handleReplicationTask(ctx, task, res) +} + +func (r *testReplicator) HandleLocalPutTask(ctx context.Context, task replicator.Task) { + r.handleLocalPutTask(ctx, task) +} + +func (r *testReplicator) HandlePullTask(ctx context.Context, task replicator.Task) { + r.handlePullTask(ctx, task) } diff --git a/pkg/services/replicator/put.go b/pkg/services/replicator/put.go new file mode 100644 index 0000000000..c06ec3f659 --- /dev/null +++ b/pkg/services/replicator/put.go @@ -0,0 +1,47 @@ +package replicator + +import ( + "context" + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" +) + +var errObjectNotDefined = errors.New("object is not defined") + +func (p *Replicator) HandleLocalPutTask(ctx context.Context, task Task) { + p.metrics.IncInFlightRequest() + defer p.metrics.DecInFlightRequest() + defer func() { + p.log.Debug(logs.ReplicatorFinishWork, zap.String("type", "pull")) + }() + + ctx, span := tracing.StartSpanFromContext(ctx, "Replicator.HandleLocalPutTask", + trace.WithAttributes( + attribute.Stringer("address", task.Addr), + attribute.Int("nodes_count", len(task.Nodes)), + )) + defer span.End() + + if task.Obj == nil { + p.log.Error(logs.ReplicatorCouldNotPutObjectToLocalStorage, + zap.Stringer("object", task.Addr), + zap.Error(errObjectNotDefined), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + return + } + + err := engine.Put(ctx, p.localStorage, task.Obj) + if err != nil { + p.log.Error(logs.ReplicatorCouldNotPutObjectToLocalStorage, + zap.Stringer("object", task.Addr), + zap.Error(err), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } +} From 8fd678e269cda0808cc57fc628ef2d38ea67ca23 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 20 May 2024 11:45:40 +0300 Subject: [PATCH 0570/1413] [#1141] go.mod: Update frostfs-sdk-go and frostfs-api-go/v2 * Also fix unit-test. Signed-off-by: Airat Arifullin --- go.mod | 4 ++-- go.sum | 8 ++++---- pkg/services/policer/ec_test.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 875385203e..81e2fa9890 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240516133103-0803bc6ded00 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240517121628-3de256d05e32 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index 9bb97cbe17..5dd9b24239 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f h1:YyjsQNtrngQzIKOUtApXoi5r5pewatM+cXfpY19vZWo= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240427200446-67c6f305b21f/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240516133103-0803bc6ded00 h1:Q3B9WtFh05AXhUFs/2CLvhh9tuFs/Zd/XemWBbuzvg8= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240516133103-0803bc6ded00/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 h1:Tp4I+XOLp3VCJORfxSamQtj3RZNISbaLM4WD5iIzXxg= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12 h1:uEAn+TBXxgqXXygrYW2X8dFmGydGyJvBc5ysnfHFhYM= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240507063414-99e02858af12/go.mod h1:e7H9nNFpx1Tj3R20Zoxy0Vo6Srlb6zV5L7ZQXqg9rn4= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240517121628-3de256d05e32 h1:ebXBsKCAINoJLhBUqi1x3fToxUHUsUjEBGKo86JQoho= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240517121628-3de256d05e32/go.mod h1:Wu1jsGM6JhZwS5oMWeslKvMcvRbg8nGt/B/TfsQPoFA= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d h1:hHk8FWbWgEnwm2I045CaBIrZBjy/o81CehIVOySA/pQ= diff --git a/pkg/services/policer/ec_test.go b/pkg/services/policer/ec_test.go index 3ac9699f0b..11e7a8cdfc 100644 --- a/pkg/services/policer/ec_test.go +++ b/pkg/services/policer/ec_test.go @@ -114,7 +114,7 @@ func TestECChunkHasInvalidPlacement(t *testing.T) { chunkObject.SetID(chunkAddress.Object()) chunkObject.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) chunkObject.SetPayloadSize(uint64(10)) - chunkObject.SetECHeader(objectSDK.NewECHeader(parentID, 1, 3, []byte{}, 0)) + chunkObject.SetECHeader(objectSDK.NewECHeader(parentID, nil, nil, 1, 3, []byte{}, 0)) var policy netmapSDK.PlacementPolicy require.NoError(t, policy.DecodeString("EC 2.1")) From 89a80e9a0f007793bc08eb094c91576c7307827f Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 20 May 2024 13:14:27 +0300 Subject: [PATCH 0571/1413] [#1141] metabase: Fix `putUniqueIndexItem` * `GetECHeader` is not correct way to determine if an object's got EC-header: `ECHeader` must be used for that. Signed-off-by: Airat Arifullin --- pkg/local_object_storage/metabase/put.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 2822303a0a..8b7b830166 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -266,7 +266,7 @@ func putUniqueIndexes( return err } - if ecHead := obj.GetECHeader(); ecHead != nil { + if ecHead := obj.ECHeader(); ecHead != nil { err = putECInfo(tx, cnr, objKey, ecHead) if err != nil { return err From 40b04c00efb305596f7db82ef771a5ac65b20bed Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 20 May 2024 13:19:51 +0300 Subject: [PATCH 0572/1413] [#1141] metabase: Fix `IsUserObject` method Signed-off-by: Airat Arifullin --- pkg/local_object_storage/metabase/counter.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index 4d860261c0..275099ff2b 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -527,10 +527,14 @@ func containerObjectCounterInitialized(tx *bbolt.Tx) bool { } func IsUserObject(obj *objectSDK.Object) bool { - _, hasParentID := obj.ParentID() - return obj.Type() == objectSDK.TypeRegular && - (obj.SplitID() == nil || - (hasParentID && len(obj.Children()) == 0)) + ech := obj.ECHeader() + if ech == nil { + _, hasParentID := obj.ParentID() + return obj.Type() == objectSDK.TypeRegular && + (obj.SplitID() == nil || + (hasParentID && len(obj.Children()) == 0)) + } + return ech.Index() == 0 && (ech.ParentSplitID() == nil || ech.ParentSplitParentID() != nil) } // ZeroSizeContainers returns containers with size = 0. From 2697d4d1fe0fae4f684521fdfbd6408b9fcd1099 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 20 May 2024 18:40:16 +0300 Subject: [PATCH 0573/1413] [#1143] node: Fix frostfsid cache * Fix `subjectFromSubjectExtended` converter. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/frostfsid.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-node/frostfsid.go b/cmd/frostfs-node/frostfsid.go index 68cc1d0407..fb55a60190 100644 --- a/cmd/frostfs-node/frostfsid.go +++ b/cmd/frostfs-node/frostfsid.go @@ -64,7 +64,7 @@ func subjectFromSubjectExtended(subjExt *client.SubjectExtended) *client.Subject return &client.Subject{ PrimaryKey: subjExt.PrimaryKey, AdditionalKeys: subjExt.AdditionalKeys, - Namespace: subjExt.Name, + Namespace: subjExt.Namespace, Name: subjExt.Name, KV: subjExt.KV, } From 51ade979e863af0bd20c5694f750633f9dd9b066 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 24 Apr 2024 19:46:59 +0300 Subject: [PATCH 0574/1413] [#1105] ape: Introduce contract storage with proxy contract verification * `ProxyVerificationContractStorage` uses Proxy contract as a cosigner. * `ProxyVerificationContractStorage` recreates a contract storage for each handler invocation because of an issue: rpc-actor from morph client may be expired. This way won't create a bottlenecks because it is expected that this contract storage implementation will be used not so often. * Make morph client return `RPCActor` (that is websocket client in fact). * Make `SwitchRPCGuardedActor` return `RPCActor` as it will be used for `ProxyVerificationContractStorage`. Signed-off-by: Airat Arifullin --- pkg/ape/contract_storage/proxy.go | 128 ++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 pkg/ape/contract_storage/proxy.go diff --git a/pkg/ape/contract_storage/proxy.go b/pkg/ape/contract_storage/proxy.go new file mode 100644 index 0000000000..953b91a796 --- /dev/null +++ b/pkg/ape/contract_storage/proxy.go @@ -0,0 +1,128 @@ +package contractstorage + +import ( + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + policy_morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" + "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/notary" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/wallet" +) + +type ProxyAdaptedContractStorage interface { + AddMorphRuleChain(name chain.Name, target engine.Target, c *chain.Chain) (util.Uint256, uint32, error) + + RemoveMorphRuleChain(name chain.Name, target engine.Target, chainID chain.ID) (util.Uint256, uint32, error) + + ListMorphRuleChains(name chain.Name, target engine.Target) ([]*chain.Chain, error) +} + +var _ ProxyAdaptedContractStorage = (engine.MorphRuleChainStorage)(nil) + +type RPCActorProvider interface { + GetRPCActor() actor.RPCActor +} + +// ProxyVerificationContractStorage uses decorated MorphRuleChainStorage with actor where cosigner is a proxy contract. +type ProxyVerificationContractStorage struct { + rpcActorProvider RPCActorProvider + + acc *wallet.Account + + proxyScriptHash util.Uint160 + + policyScriptHash util.Uint160 +} + +var _ ProxyAdaptedContractStorage = (*ProxyVerificationContractStorage)(nil) + +func NewProxyVerificationContractStorage(rpcActorProvider RPCActorProvider, key *keys.PrivateKey, proxyScriptHash, policyScriptHash util.Uint160) *ProxyVerificationContractStorage { + return &ProxyVerificationContractStorage{ + rpcActorProvider: rpcActorProvider, + + acc: wallet.NewAccountFromPrivateKey(key), + + proxyScriptHash: proxyScriptHash, + + policyScriptHash: policyScriptHash, + } +} + +// contractStorageActorAdapter adapats *actor.Actor to policy_morph.ContractStorageActor interface. +type contractStorageActorAdapter struct { + *actor.Actor + rpcActor invoker.RPCInvoke +} + +func (n *contractStorageActorAdapter) GetRPCInvoker() invoker.RPCInvoke { + return n.rpcActor +} + +func (contractStorage *ProxyVerificationContractStorage) newContractStorageActor() (policy_morph.ContractStorageActor, error) { + rpcActor := contractStorage.rpcActorProvider.GetRPCActor() + act, err := actor.New(rpcActor, cosigners(contractStorage.acc, contractStorage.proxyScriptHash, contractStorage.policyScriptHash)) + if err != nil { + return nil, err + } + return &contractStorageActorAdapter{ + Actor: act, + rpcActor: rpcActor, + }, nil +} + +// AddMorphRuleChain add morph rule chain to Policy contract using both Proxy contract and storage account as consigners. +func (contractStorage *ProxyVerificationContractStorage) AddMorphRuleChain(name chain.Name, target engine.Target, c *chain.Chain) (util.Uint256, uint32, error) { + // contractStorageActor is reconstructed per each method invocation because RPCActor's (that is, basically, WSClient) connection may get invalidated, but + // ProxyVerificationContractStorage does not manage reconnections. + contractStorageActor, err := contractStorage.newContractStorageActor() + if err != nil { + return util.Uint256{}, 0, err + } + return policy_morph.NewContractStorage(contractStorageActor, contractStorage.policyScriptHash).AddMorphRuleChain(name, target, c) +} + +// RemoveMorphRuleChain removes morph rule chain from Policy contract using both Proxy contract and storage account as consigners. +func (contractStorage *ProxyVerificationContractStorage) RemoveMorphRuleChain(name chain.Name, target engine.Target, chainID chain.ID) (util.Uint256, uint32, error) { + // contractStorageActor is reconstructed per each method invocation because RPCActor's (that is, basically, WSClient) connection may get invalidated, but + // ProxyVerificationContractStorage does not manage reconnections. + contractStorageActor, err := contractStorage.newContractStorageActor() + if err != nil { + return util.Uint256{}, 0, err + } + return policy_morph.NewContractStorage(contractStorageActor, contractStorage.policyScriptHash).RemoveMorphRuleChain(name, target, chainID) +} + +// ListMorphRuleChains lists morph rule chains from Policy contract using both Proxy contract and storage account as consigners. +func (contractStorage *ProxyVerificationContractStorage) ListMorphRuleChains(name chain.Name, target engine.Target) ([]*chain.Chain, error) { + // contractStorageActor is reconstructed per each method invocation because RPCActor's (that is, basically, WSClient) connection may get invalidated, but + // ProxyVerificationContractStorage does not manage reconnections. + contractStorageActor, err := contractStorage.newContractStorageActor() + if err != nil { + return nil, err + } + return policy_morph.NewContractStorage(contractStorageActor, contractStorage.policyScriptHash).ListMorphRuleChains(name, target) +} + +func cosigners(acc *wallet.Account, proxyScriptHash, policyScriptHash util.Uint160) []actor.SignerAccount { + return []actor.SignerAccount{ + { + Signer: transaction.Signer{ + Account: proxyScriptHash, + Scopes: transaction.CustomContracts, + AllowedContracts: []util.Uint160{policyScriptHash}, + }, + Account: notary.FakeContractAccount(proxyScriptHash), + }, + { + Signer: transaction.Signer{ + Account: acc.Contract.ScriptHash(), + Scopes: transaction.CalledByEntry, + }, + Account: acc, + }, + } +} From 542d3adcb2b78ea1dee6f546a933802b2f1d5c56 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 24 Apr 2024 20:23:15 +0300 Subject: [PATCH 0575/1413] [#1105] apemanager: Implement apemanager service * Introduce grpc server for apemanager service and its implementation in `pkg/services/apemanager`. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/apemanager.go | 29 +++ cmd/frostfs-node/main.go | 1 + .../transport/apemanager/grpc/service.go | 63 +++++ pkg/services/apemanager/errors/errors.go | 11 + pkg/services/apemanager/executor.go | 245 ++++++++++++++++++ pkg/services/apemanager/server.go | 13 + pkg/services/apemanager/sign.go | 49 ++++ pkg/services/apemanager/validation.go | 23 ++ 8 files changed, 434 insertions(+) create mode 100644 cmd/frostfs-node/apemanager.go create mode 100644 pkg/network/transport/apemanager/grpc/service.go create mode 100644 pkg/services/apemanager/errors/errors.go create mode 100644 pkg/services/apemanager/executor.go create mode 100644 pkg/services/apemanager/server.go create mode 100644 pkg/services/apemanager/sign.go create mode 100644 pkg/services/apemanager/validation.go diff --git a/cmd/frostfs-node/apemanager.go b/cmd/frostfs-node/apemanager.go new file mode 100644 index 0000000000..b9928faaf6 --- /dev/null +++ b/cmd/frostfs-node/apemanager.go @@ -0,0 +1,29 @@ +package main + +import ( + "net" + + apemanager_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc" + ape_contract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/contract_storage" + morph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + apemanager_transport "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/apemanager/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/apemanager" + "google.golang.org/grpc" +) + +func initAPEManagerService(c *cfg) { + contractStorage := ape_contract.NewProxyVerificationContractStorage( + morph.NewSwitchRPCGuardedActor(c.cfgMorph.client), + c.shared.key, + c.cfgMorph.proxyScriptHash, + c.cfgObject.cfgAccessPolicyEngine.policyContractHash) + + execsvc := apemanager.New(c.cfgObject.cnrSource, contractStorage, + apemanager.WithLogger(c.log)) + sigsvc := apemanager.NewSignService(&c.key.PrivateKey, execsvc) + server := apemanager_transport.New(sigsvc) + + c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { + apemanager_grpc.RegisterAPEManagerServiceServer(s, server) + }) +} diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index e1eeb6861d..dbef1e494c 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -114,6 +114,7 @@ func initApp(ctx context.Context, c *cfg) { initAndLog(c, "notification", func(c *cfg) { initNotifications(ctx, c) }) initAndLog(c, "object", initObjectService) initAndLog(c, "tree", initTreeService) + initAndLog(c, "apemanager", initAPEManagerService) initAndLog(c, "control", initControlService) initAndLog(c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) }) diff --git a/pkg/network/transport/apemanager/grpc/service.go b/pkg/network/transport/apemanager/grpc/service.go new file mode 100644 index 0000000000..59783cfc09 --- /dev/null +++ b/pkg/network/transport/apemanager/grpc/service.go @@ -0,0 +1,63 @@ +package apemanager + +import ( + "context" + + apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" + apemanager_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc" + apemanager_svc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/apemanager" +) + +type Server struct { + srv apemanager_svc.Server +} + +var _ apemanager_grpc.APEManagerServiceServer = (*Server)(nil) + +func New(c apemanager_svc.Server) *Server { + return &Server{ + srv: c, + } +} + +func (s *Server) AddChain(ctx context.Context, req *apemanager_grpc.AddChainRequest) (*apemanager_grpc.AddChainResponse, error) { + v2req := new(apemanager_v2.AddChainRequest) + if err := v2req.FromGRPCMessage(req); err != nil { + return nil, err + } + + resp, err := s.srv.AddChain(ctx, v2req) + if err != nil { + return nil, err + } + + return resp.ToGRPCMessage().(*apemanager_grpc.AddChainResponse), nil +} + +func (s *Server) RemoveChain(ctx context.Context, req *apemanager_grpc.RemoveChainRequest) (*apemanager_grpc.RemoveChainResponse, error) { + v2req := new(apemanager_v2.RemoveChainRequest) + if err := v2req.FromGRPCMessage(req); err != nil { + return nil, err + } + + resp, err := s.srv.RemoveChain(ctx, v2req) + if err != nil { + return nil, err + } + + return resp.ToGRPCMessage().(*apemanager_grpc.RemoveChainResponse), nil +} + +func (s *Server) ListChains(ctx context.Context, req *apemanager_grpc.ListChainsRequest) (*apemanager_grpc.ListChainsResponse, error) { + v2req := new(apemanager_v2.ListChainsRequest) + if err := v2req.FromGRPCMessage(req); err != nil { + return nil, err + } + + resp, err := s.srv.ListChains(ctx, v2req) + if err != nil { + return nil, err + } + + return resp.ToGRPCMessage().(*apemanager_grpc.ListChainsResponse), nil +} diff --git a/pkg/services/apemanager/errors/errors.go b/pkg/services/apemanager/errors/errors.go new file mode 100644 index 0000000000..e64f9a8d13 --- /dev/null +++ b/pkg/services/apemanager/errors/errors.go @@ -0,0 +1,11 @@ +package errors + +import ( + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" +) + +func ErrAPEManagerAccessDenied(reason string) error { + err := new(apistatus.APEManagerAccessDenied) + err.WriteReason(reason) + return err +} diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go new file mode 100644 index 0000000000..bad43b5fa0 --- /dev/null +++ b/pkg/services/apemanager/executor.go @@ -0,0 +1,245 @@ +package apemanager + +import ( + "context" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "errors" + "fmt" + + apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + ape_contract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/contract_storage" + containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + apemanager_errors "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/apemanager/errors" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policy_engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "github.com/mr-tron/base58/base58" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "go.uber.org/zap" +) + +var ( + errEmptyBodySignature = errors.New("malformed request: empty body signature") +) + +type cfg struct { + log *logger.Logger +} + +type Service struct { + cfg + + cnrSrc containercore.Source + + contractStorage ape_contract.ProxyAdaptedContractStorage +} + +type Option func(*cfg) + +func New(cnrSrc containercore.Source, contractStorage ape_contract.ProxyAdaptedContractStorage, opts ...Option) *Service { + s := &Service{ + cnrSrc: cnrSrc, + + contractStorage: contractStorage, + } + + for i := range opts { + opts[i](&s.cfg) + } + + if s.log == nil { + s.log = &logger.Logger{Logger: zap.NewNop()} + } + + return s +} + +func WithLogger(log *logger.Logger) Option { + return func(c *cfg) { + c.log = log + } +} + +var _ Server = (*Service)(nil) + +// validateContainerTargetRequest validates request for the container target. +// It checks if request actor is the owner of the container, otherwise it denies the request. +func (s *Service) validateContainerTargetRequest(cid string, pubKey *keys.PublicKey) error { + var cidSDK cidSDK.ID + if err := cidSDK.DecodeString(cid); err != nil { + return fmt.Errorf("invalid CID format: %w", err) + } + isOwner, err := s.isActorContainerOwner(cidSDK, pubKey) + if err != nil { + return fmt.Errorf("failed to check owner: %w", err) + } + if !isOwner { + return apemanager_errors.ErrAPEManagerAccessDenied("actor must be container owner") + } + return nil +} + +func (s *Service) AddChain(_ context.Context, req *apemanager_v2.AddChainRequest) (*apemanager_v2.AddChainResponse, error) { + pub, err := getSignaturePublicKey(req.GetVerificationHeader()) + if err != nil { + return nil, err + } + + chain, err := decodeAndValidateChain(req.GetBody().GetChain().GetKind().(*apemanager_v2.ChainRaw).GetRaw()) + if err != nil { + return nil, err + } + if len(chain.ID) == 0 { + const randomIDLength = 10 + randID, err := base58Str(randomIDLength) + if err != nil { + return nil, fmt.Errorf("randomize chain ID error: %w", err) + } + chain.ID = apechain.ID(randID) + } + + var target policy_engine.Target + + switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { + case apemanager_v2.TargetTypeContainer: + reqCID := req.GetBody().GetTarget().GetName() + if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { + return nil, err + } + target = policy_engine.ContainerTarget(reqCID) + default: + return nil, fmt.Errorf("unsupported target type: %s", targetType) + } + + if _, _, err = s.contractStorage.AddMorphRuleChain(apechain.Ingress, target, &chain); err != nil { + return nil, err + } + + body := new(apemanager_v2.AddChainResponseBody) + body.SetChainID(chain.ID) + + resp := new(apemanager_v2.AddChainResponse) + resp.SetBody(body) + + return resp, nil +} + +func (s *Service) RemoveChain(_ context.Context, req *apemanager_v2.RemoveChainRequest) (*apemanager_v2.RemoveChainResponse, error) { + pub, err := getSignaturePublicKey(req.GetVerificationHeader()) + if err != nil { + return nil, err + } + + var target policy_engine.Target + + switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { + case apemanager_v2.TargetTypeContainer: + reqCID := req.GetBody().GetTarget().GetName() + if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { + return nil, err + } + target = policy_engine.ContainerTarget(reqCID) + default: + return nil, fmt.Errorf("unsupported target type: %s", targetType) + } + + if _, _, err = s.contractStorage.RemoveMorphRuleChain(apechain.Ingress, target, req.GetBody().GetChainID()); err != nil { + return nil, err + } + + body := new(apemanager_v2.RemoveChainResponseBody) + + resp := new(apemanager_v2.RemoveChainResponse) + resp.SetBody(body) + + return resp, nil +} + +func (s *Service) ListChains(_ context.Context, req *apemanager_v2.ListChainsRequest) (*apemanager_v2.ListChainsResponse, error) { + pub, err := getSignaturePublicKey(req.GetVerificationHeader()) + if err != nil { + return nil, err + } + + var target policy_engine.Target + + switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { + case apemanager_v2.TargetTypeContainer: + reqCID := req.GetBody().GetTarget().GetName() + if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { + return nil, err + } + target = policy_engine.ContainerTarget(reqCID) + default: + return nil, fmt.Errorf("unsupported target type: %s", targetType) + } + + chs, err := s.contractStorage.ListMorphRuleChains(apechain.Ingress, target) + if err != nil { + return nil, err + } + + res := make([]*apemanager_v2.Chain, 0, len(chs)) + for _, ch := range chs { + v2chraw := new(apemanager_v2.ChainRaw) + v2chraw.SetRaw(ch.Bytes()) + + v2ch := new(apemanager_v2.Chain) + v2ch.SetKind(v2chraw) + + res = append(res, v2ch) + } + + body := new(apemanager_v2.ListChainsResponseBody) + body.SetChains(res) + + resp := new(apemanager_v2.ListChainsResponse) + resp.SetBody(body) + + return resp, nil +} + +func getSignaturePublicKey(vh *session.RequestVerificationHeader) (*keys.PublicKey, error) { + for vh.GetOrigin() != nil { + vh = vh.GetOrigin() + } + sig := vh.GetBodySignature() + if sig == nil { + return nil, errEmptyBodySignature + } + key, err := keys.NewPublicKeyFromBytes(sig.GetKey(), elliptic.P256()) + if err != nil { + return nil, fmt.Errorf("invalid signature key: %w", err) + } + + return key, nil +} + +func (s *Service) isActorContainerOwner(cid cidSDK.ID, pk *keys.PublicKey) (bool, error) { + var actor user.ID + user.IDFromKey(&actor, (ecdsa.PublicKey)(*pk)) + actorOwnerID := new(refs.OwnerID) + actor.WriteToV2(actorOwnerID) + + cnr, err := s.cnrSrc.Get(cid) + if err != nil { + return false, fmt.Errorf("get container error: %w", err) + } + return cnr.Value.Owner().Equals(actor), nil +} + +// base58Str generates base58 string. +func base58Str(n int) (string, error) { + b := make([]byte, n) + _, err := rand.Read(b) + if err != nil { + return "", err + } + return base58.FastBase58Encoding(b), nil +} diff --git a/pkg/services/apemanager/server.go b/pkg/services/apemanager/server.go new file mode 100644 index 0000000000..90b2d92aec --- /dev/null +++ b/pkg/services/apemanager/server.go @@ -0,0 +1,13 @@ +package apemanager + +import ( + "context" + + apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" +) + +type Server interface { + AddChain(context.Context, *apemanager_v2.AddChainRequest) (*apemanager_v2.AddChainResponse, error) + RemoveChain(context.Context, *apemanager_v2.RemoveChainRequest) (*apemanager_v2.RemoveChainResponse, error) + ListChains(context.Context, *apemanager_v2.ListChainsRequest) (*apemanager_v2.ListChainsResponse, error) +} diff --git a/pkg/services/apemanager/sign.go b/pkg/services/apemanager/sign.go new file mode 100644 index 0000000000..eda2a7342f --- /dev/null +++ b/pkg/services/apemanager/sign.go @@ -0,0 +1,49 @@ +package apemanager + +import ( + "context" + "crypto/ecdsa" + + apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" +) + +type signService struct { + sigSvc *util.SignService + + next Server +} + +func NewSignService(key *ecdsa.PrivateKey, next Server) Server { + return &signService{ + sigSvc: util.NewUnarySignService(key), + next: next, + } +} + +func (s *signService) AddChain(ctx context.Context, req *apemanager_v2.AddChainRequest) (*apemanager_v2.AddChainResponse, error) { + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(apemanager_v2.AddChainResponse) + return resp, s.sigSvc.SignResponse(resp, err) + } + resp, err := util.EnsureNonNilResponse(s.next.AddChain(ctx, req)) + return resp, s.sigSvc.SignResponse(resp, err) +} + +func (s *signService) RemoveChain(ctx context.Context, req *apemanager_v2.RemoveChainRequest) (*apemanager_v2.RemoveChainResponse, error) { + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(apemanager_v2.RemoveChainResponse) + return resp, s.sigSvc.SignResponse(resp, err) + } + resp, err := util.EnsureNonNilResponse(s.next.RemoveChain(ctx, req)) + return resp, s.sigSvc.SignResponse(resp, err) +} + +func (s *signService) ListChains(ctx context.Context, req *apemanager_v2.ListChainsRequest) (*apemanager_v2.ListChainsResponse, error) { + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(apemanager_v2.ListChainsResponse) + return resp, s.sigSvc.SignResponse(resp, err) + } + resp, err := util.EnsureNonNilResponse(s.next.ListChains(ctx, req)) + return resp, s.sigSvc.SignResponse(resp, err) +} diff --git a/pkg/services/apemanager/validation.go b/pkg/services/apemanager/validation.go new file mode 100644 index 0000000000..b26fcf8eef --- /dev/null +++ b/pkg/services/apemanager/validation.go @@ -0,0 +1,23 @@ +package apemanager + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ape" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" +) + +func decodeAndValidateChain(encodedChain []byte) (chain apechain.Chain, err error) { + if err = chain.DecodeBytes(encodedChain); err != nil { + return + } + for _, rule := range chain.Rules { + for _, name := range rule.Resources.Names { + if err = ape.ValidateResourceName(name); err != nil { + err = fmt.Errorf("invalid resource: %w", err) + return + } + } + } + return +} From 2b02f52cd9cdc7fd7e930dac16d7fff0ceebc129 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 13 May 2024 19:07:44 +0300 Subject: [PATCH 0576/1413] [#1105] cli: Add apemanager commands Signed-off-by: Airat Arifullin --- .../modules/ape_manager/add_chain.go | 141 ++++++++++++++++++ .../modules/ape_manager/list_chain.go | 49 ++++++ .../modules/ape_manager/remove_chain.go | 66 ++++++++ cmd/frostfs-cli/modules/ape_manager/root.go | 21 +++ cmd/frostfs-cli/modules/root.go | 2 + 5 files changed, 279 insertions(+) create mode 100644 cmd/frostfs-cli/modules/ape_manager/add_chain.go create mode 100644 cmd/frostfs-cli/modules/ape_manager/list_chain.go create mode 100644 cmd/frostfs-cli/modules/ape_manager/remove_chain.go create mode 100644 cmd/frostfs-cli/modules/ape_manager/root.go diff --git a/cmd/frostfs-cli/modules/ape_manager/add_chain.go b/cmd/frostfs-cli/modules/ape_manager/add_chain.go new file mode 100644 index 0000000000..7e6614392a --- /dev/null +++ b/cmd/frostfs-cli/modules/ape_manager/add_chain.go @@ -0,0 +1,141 @@ +package apemanager + +import ( + "encoding/hex" + "errors" + + internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apemanager_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager" + client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "github.com/spf13/cobra" +) + +const ( + chainIDFlag = "chain-id" + chainIDHexFlag = "chain-id-hex" + ruleFlag = "rule" + pathFlag = "path" +) + +const ( + targetNameFlag = "target-name" + targetNameDesc = "Resource name in APE resource name format" + targetTypeFlag = "target-type" + targetTypeDesc = "Resource type(container/namespace)" +) + +const ( + defaultNamespace = "" + namespaceTarget = "namespace" + containerTarget = "container" + userTarget = "user" + groupTarget = "group" +) + +var ( + errUnknownTargetType = errors.New("unknown target type") +) + +var addCmd = &cobra.Command{ + Use: "add", + Short: "Add rule chain for a target", + Run: add, + PersistentPreRun: func(cmd *cobra.Command, _ []string) { + commonflags.Bind(cmd) + }, +} + +func parseTarget(cmd *cobra.Command) (ct apemanager_sdk.ChainTarget) { + typ, _ := cmd.Flags().GetString(targetTypeFlag) + name, _ := cmd.Flags().GetString(targetNameFlag) + + ct.Name = name + + switch typ { + case namespaceTarget: + ct.TargetType = apemanager_sdk.TargetTypeNamespace + case containerTarget: + var cnr cid.ID + commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name)) + ct.TargetType = apemanager_sdk.TargetTypeContainer + case userTarget: + ct.TargetType = apemanager_sdk.TargetTypeUser + case groupTarget: + ct.TargetType = apemanager_sdk.TargetTypeGroup + default: + commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) + } + return ct +} + +func parseChain(cmd *cobra.Command) apemanager_sdk.Chain { + chainID, _ := cmd.Flags().GetString(chainIDFlag) + hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) + + chainIDRaw := []byte(chainID) + + if hexEncoded { + var err error + chainIDRaw, err = hex.DecodeString(chainID) + commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) + } + + chain := new(apechain.Chain) + chain.ID = apechain.ID(chainIDRaw) + + if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { + commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules)) + } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { + commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath)) + } else { + commonCmd.ExitOnErr(cmd, "parser error: %w", errors.New("rule is not passed")) + } + + cmd.Println("Parsed chain:") + util.PrintHumanReadableAPEChain(cmd, chain) + + serialized := chain.Bytes() + return apemanager_sdk.Chain{ + Raw: serialized, + } +} + +func add(cmd *cobra.Command, _ []string) { + c := parseChain(cmd) + + target := parseTarget(cmd) + + key := key.Get(cmd) + cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC) + + res, err := cli.APEManagerAddChain(cmd.Context(), client_sdk.PrmAPEManagerAddChain{ + ChainTarget: target, + Chain: c, + }) + + commonCmd.ExitOnErr(cmd, "add chain error: %w", err) + + cmd.Println("Rule has been added.") + cmd.Println("Chain ID: ", string(res.ChainID)) +} + +func initAddCmd() { + commonflags.Init(addCmd) + + ff := addCmd.Flags() + ff.StringArray(ruleFlag, []string{}, "Rule statement") + ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") + ff.String(chainIDFlag, "", "Assign ID to the parsed chain") + ff.String(targetNameFlag, "", targetNameDesc) + ff.String(targetTypeFlag, "", targetTypeDesc) + _ = addCmd.MarkFlagRequired(targetTypeFlag) + ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + + addCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag) +} diff --git a/cmd/frostfs-cli/modules/ape_manager/list_chain.go b/cmd/frostfs-cli/modules/ape_manager/list_chain.go new file mode 100644 index 0000000000..a5dd446147 --- /dev/null +++ b/cmd/frostfs-cli/modules/ape_manager/list_chain.go @@ -0,0 +1,49 @@ +package apemanager + +import ( + internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "github.com/spf13/cobra" +) + +var listCmd = &cobra.Command{ + Use: "list", + Short: "List rule chains defined on target", + Run: list, + PersistentPreRun: func(cmd *cobra.Command, _ []string) { + commonflags.Bind(cmd) + }, +} + +func list(cmd *cobra.Command, _ []string) { + target := parseTarget(cmd) + + key := key.Get(cmd) + cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC) + + resp, err := cli.APEManagerListChains(cmd.Context(), + client_sdk.PrmAPEManagerListChains{ + ChainTarget: target, + }) + commonCmd.ExitOnErr(cmd, "list chains call error: %w", err) + + for _, respChain := range resp.Chains { + var chain apechain.Chain + commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(respChain.Raw)) + apeutil.PrintHumanReadableAPEChain(cmd, &chain) + } +} + +func initListCmd() { + commonflags.Init(listCmd) + + ff := listCmd.Flags() + ff.String(targetNameFlag, "", targetNameDesc) + ff.String(targetTypeFlag, "", targetTypeDesc) + _ = listCmd.MarkFlagRequired(targetTypeFlag) +} diff --git a/cmd/frostfs-cli/modules/ape_manager/remove_chain.go b/cmd/frostfs-cli/modules/ape_manager/remove_chain.go new file mode 100644 index 0000000000..179bd5c9e7 --- /dev/null +++ b/cmd/frostfs-cli/modules/ape_manager/remove_chain.go @@ -0,0 +1,66 @@ +package apemanager + +import ( + "encoding/hex" + "errors" + + internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + "github.com/spf13/cobra" +) + +var ( + errEmptyChainID = errors.New("chain id cannot be empty") + + removeCmd = &cobra.Command{ + Use: "remove", + Short: "Remove rule chain for a target", + Run: remove, + PersistentPreRun: func(cmd *cobra.Command, _ []string) { + commonflags.Bind(cmd) + }, + } +) + +func remove(cmd *cobra.Command, _ []string) { + target := parseTarget(cmd) + + key := key.Get(cmd) + cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC) + + chainID, _ := cmd.Flags().GetString(chainIDFlag) + if chainID == "" { + commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID) + } + chainIDRaw := []byte(chainID) + + hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) + if hexEncoded { + var err error + chainIDRaw, err = hex.DecodeString(chainID) + commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) + } + + _, err := cli.APEManagerRemoveChain(cmd.Context(), client_sdk.PrmAPEManagerRemoveChain{ + ChainTarget: target, + ChainID: chainIDRaw, + }) + + commonCmd.ExitOnErr(cmd, "remove chain error: %w", err) + + cmd.Println("\nRule has been removed.") +} + +func initRemoveCmd() { + commonflags.Init(removeCmd) + + ff := removeCmd.Flags() + ff.String(targetNameFlag, "", targetNameDesc) + ff.String(targetTypeFlag, "", targetTypeDesc) + _ = removeCmd.MarkFlagRequired(targetTypeFlag) + ff.String(chainIDFlag, "", "Chain id") + ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") +} diff --git a/cmd/frostfs-cli/modules/ape_manager/root.go b/cmd/frostfs-cli/modules/ape_manager/root.go new file mode 100644 index 0000000000..7b4f92921d --- /dev/null +++ b/cmd/frostfs-cli/modules/ape_manager/root.go @@ -0,0 +1,21 @@ +package apemanager + +import ( + "github.com/spf13/cobra" +) + +var Cmd = &cobra.Command{ + Use: "ape-manager", + Short: "Operations with APE manager", + Long: `Operations with APE manager`, +} + +func init() { + Cmd.AddCommand(addCmd) + Cmd.AddCommand(removeCmd) + Cmd.AddCommand(listCmd) + + initAddCmd() + initRemoveCmd() + initListCmd() +} diff --git a/cmd/frostfs-cli/modules/root.go b/cmd/frostfs-cli/modules/root.go index 87e6a905ff..21c367d29d 100644 --- a/cmd/frostfs-cli/modules/root.go +++ b/cmd/frostfs-cli/modules/root.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" accountingCli "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/accounting" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/acl" + apemanager "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/ape_manager" bearerCli "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/bearer" containerCli "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/container" controlCli "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/control" @@ -81,6 +82,7 @@ func init() { rootCmd.Flags().Bool("version", false, "Application version and FrostFS API compatibility") rootCmd.AddCommand(acl.Cmd) + rootCmd.AddCommand(apemanager.Cmd) rootCmd.AddCommand(bearerCli.Cmd) rootCmd.AddCommand(sessionCli.Cmd) rootCmd.AddCommand(accountingCli.Cmd) From 43625e7536a15cc625597a495858aea5a8812f09 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 20 May 2024 16:11:44 +0300 Subject: [PATCH 0577/1413] [#1142] container: Fill APE-request property with source IP Signed-off-by: Airat Arifullin --- pkg/services/container/ape.go | 32 ++++++-- pkg/services/container/ape_test.go | 127 +++++++++++++++++++++++++++-- 2 files changed, 146 insertions(+), 13 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 22440ab804..fb1cc8121c 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -9,6 +9,7 @@ import ( "encoding/hex" "errors" "fmt" + "net" "strings" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" @@ -27,8 +28,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "google.golang.org/grpc/peer" ) var ( @@ -88,7 +91,7 @@ func (ac *apeChecker) Delete(ctx context.Context, req *container.DeleteRequest) ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Delete") defer span.End() - if err := ac.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), + if err := ac.validateContainerBoundedOperation(ctx, req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodDeleteContainer); err != nil { return nil, err } @@ -100,7 +103,7 @@ func (ac *apeChecker) Get(ctx context.Context, req *container.GetRequest) (*cont ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Get") defer span.End() - if err := ac.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), + if err := ac.validateContainerBoundedOperation(ctx, req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer); err != nil { return nil, err } @@ -112,7 +115,7 @@ func (ac *apeChecker) GetExtendedACL(ctx context.Context, req *container.GetExte ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.GetExtendedACL") defer span.End() - if err := ac.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), + if err := ac.validateContainerBoundedOperation(ctx, req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainerEACL); err != nil { return nil, err } @@ -138,6 +141,11 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co if err != nil { return nil, err } + if p, ok := peer.FromContext(ctx); ok { + if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok { + reqProps[commonschema.PropertyKeyFrostFSSourceIP] = tcpAddr.IP.String() + } + } namespace, err := ac.namespaceByOwner(req.GetBody().GetOwnerID()) if err != nil { @@ -191,6 +199,11 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont if err != nil { return nil, err } + if p, ok := peer.FromContext(ctx); ok { + if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok { + reqProps[commonschema.PropertyKeyFrostFSSourceIP] = tcpAddr.IP.String() + } + } namespace, err := ac.namespaceByOwner(req.GetBody().GetContainer().GetOwnerID()) if err != nil { @@ -264,7 +277,7 @@ func (ac *apeChecker) SetExtendedACL(ctx context.Context, req *container.SetExte ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.SetExtendedACL") defer span.End() - if err := ac.validateContainerBoundedOperation(req.GetBody().GetEACL().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), + if err := ac.validateContainerBoundedOperation(ctx, req.GetBody().GetEACL().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodSetContainerEACL); err != nil { return nil, err } @@ -272,7 +285,7 @@ func (ac *apeChecker) SetExtendedACL(ctx context.Context, req *container.SetExte return ac.next.SetExtendedACL(ctx, req) } -func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.ContainerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, op string) error { +func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, containerID *refs.ContainerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, op string) error { if vh == nil { return errMissingVerificationHeader } @@ -287,7 +300,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(containerID *refs.Contai return err } - reqProps, pk, err := ac.getRequestProps(mh, vh, cont, id) + reqProps, pk, err := ac.getRequestProps(ctx, mh, vh, cont, id) if err != nil { return err } @@ -358,7 +371,7 @@ func (ac *apeChecker) getContainerProps(c *containercore.Container) map[string]s } } -func (ac *apeChecker) getRequestProps(mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, +func (ac *apeChecker) getRequestProps(ctx context.Context, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, cont *containercore.Container, cnrID cid.ID, ) (map[string]string, *keys.PublicKey, error) { actor, pk, err := ac.getActorAndPublicKey(mh, vh, cnrID) @@ -377,6 +390,11 @@ func (ac *apeChecker) getRequestProps(mh *session.RequestMetaHeader, vh *session if err != nil { return nil, nil, err } + if p, ok := peer.FromContext(ctx); ok { + if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok { + reqProps[commonschema.PropertyKeyFrostFSSourceIP] = tcpAddr.IP.String() + } + } return reqProps, pk, nil } diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 01a0fa4d27..90c0225dd6 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "errors" "fmt" + "net" "testing" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" @@ -32,6 +33,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" + "google.golang.org/grpc/peer" ) const ( @@ -45,6 +47,7 @@ func TestAPE(t *testing.T) { t.Run("deny get container no rule found", testDenyGetContainerNoRuleFound) t.Run("deny get container for others", testDenyGetContainerForOthers) t.Run("deny get container by user claim tag", testDenyGetContainerByUserClaimTag) + t.Run("deny get container by IP", testDenyGetContainerByIP) t.Run("deny get container by group id", testDenyGetContainerByGroupID) t.Run("deny set container eACL for IR", testDenySetContainerEACLForIR) t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken) @@ -55,6 +58,19 @@ func TestAPE(t *testing.T) { t.Run("deny list containers by namespace invalidation", testDenyListContainersValidationNamespaceError) } +const ( + incomingIP = "192.92.33.1" +) + +func ctxWithPeerInfo() context.Context { + return peer.NewContext(context.Background(), &peer.Peer{ + Addr: &net.TCPAddr{ + IP: net.ParseIP(incomingIP), + Port: 41111, + }, + }) +} + func testAllowThenDenyGetContainerRuleDefined(t *testing.T) { t.Parallel() srv := &srvStub{ @@ -353,6 +369,105 @@ func testDenyGetContainerByUserClaimTag(t *testing.T) { require.ErrorAs(t, err, &errAccessDenied) } +func testDenyGetContainerByIP(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + }, + }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 19888, + }, + }, + }, + }, + } + + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Kind: chain.KindRequest, + Key: commonschema.PropertyKeyFrostFSSourceIP, + Value: incomingIP + "/16", + Op: chain.CondIPAddress, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + resp, err := apeSrv.Get(ctxWithPeerInfo(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) + require.Contains(t, errAccessDenied.Reason(), chain.AccessDenied.String()) +} + func testDenyGetContainerByGroupID(t *testing.T) { t.Parallel() srv := &srvStub{ @@ -1208,7 +1323,7 @@ func TestValidateContainerBoundedOperation(t *testing.T) { req := initTestGetContainerRequest(t, contID) - err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + err = components.apeChecker.validateContainerBoundedOperation(ctxWithPeerInfo(), req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) aErr := apeErr(nativeschema.MethodGetContainer, chain.AccessDenied) require.ErrorContains(t, err, aErr.Error()) }) @@ -1252,7 +1367,7 @@ func TestValidateContainerBoundedOperation(t *testing.T) { req := initTestGetContainerRequest(t, contID) - err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + err = components.apeChecker.validateContainerBoundedOperation(ctxWithPeerInfo(), req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) require.NoError(t, err) }) @@ -1295,7 +1410,7 @@ func TestValidateContainerBoundedOperation(t *testing.T) { req := initTestGetContainerRequest(t, contID) - err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + err = components.apeChecker.validateContainerBoundedOperation(ctxWithPeerInfo(), req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) require.NoError(t, err) }) @@ -1338,7 +1453,7 @@ func TestValidateContainerBoundedOperation(t *testing.T) { req := initTestGetContainerRequest(t, contID) - err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + err = components.apeChecker.validateContainerBoundedOperation(ctxWithPeerInfo(), req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) require.NoError(t, err) }) @@ -1381,7 +1496,7 @@ func TestValidateContainerBoundedOperation(t *testing.T) { req := initTestGetContainerRequest(t, contID) - err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + err = components.apeChecker.validateContainerBoundedOperation(ctxWithPeerInfo(), req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) aErr := apeErr(nativeschema.MethodGetContainer, chain.AccessDenied) require.ErrorContains(t, err, aErr.Error()) }) @@ -1423,7 +1538,7 @@ func TestValidateContainerBoundedOperation(t *testing.T) { req := initTestGetContainerRequest(t, contID) - err = components.apeChecker.validateContainerBoundedOperation(req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) + err = components.apeChecker.validateContainerBoundedOperation(ctxWithPeerInfo(), req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), nativeschema.MethodGetContainer) aErr := apeErr(nativeschema.MethodGetContainer, chain.AccessDenied) require.ErrorContains(t, err, aErr.Error()) }) From 482c5129ac37f1b816afbadfed4c231c3a53a24f Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 20 May 2024 16:19:00 +0300 Subject: [PATCH 0578/1413] [#1142] object: Fill APE-request with source IP property Signed-off-by: Airat Arifullin --- pkg/services/object/ape/request.go | 9 +++++++++ pkg/services/object/ape/request_test.go | 16 +++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 71a9aec2c5..02ead8c605 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -4,6 +4,7 @@ import ( "context" "crypto/sha256" "fmt" + "net" "strconv" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" @@ -15,8 +16,10 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "google.golang.org/grpc/peer" ) var defaultRequest = aperequest.Request{} @@ -129,6 +132,12 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re return defaultRequest, err } + if p, ok := peer.FromContext(ctx); ok { + if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok { + reqProps[commonschema.PropertyKeyFrostFSSourceIP] = tcpAddr.IP.String() + } + } + return aperequest.NewRequest( prm.Method, aperequest.NewResource( diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index 5c74e7d1d2..9dad69d17c 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -3,6 +3,7 @@ package ape import ( "context" "fmt" + "net" "testing" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" @@ -14,12 +15,24 @@ import ( commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/stretchr/testify/require" + "google.golang.org/grpc/peer" ) const ( testOwnerID = "FPPtmAi9TCX329" + + incomingIP = "192.92.33.1" ) +func ctxWithPeerInfo() context.Context { + return peer.NewContext(context.Background(), &peer.Peer{ + Addr: &net.TCPAddr{ + IP: net.ParseIP(incomingIP), + Port: 41111, + }, + }) +} + func TestObjectProperties(t *testing.T) { for _, test := range []struct { name string @@ -253,7 +266,7 @@ func TestNewAPERequest(t *testing.T) { frostFSIDClient: ffidProvider, } - r, err := c.newAPERequest(context.TODO(), prm) + r, err := c.newAPERequest(ctxWithPeerInfo(), prm) if test.expectErr != nil { require.Error(t, err) require.ErrorIs(t, err, test.expectErr) @@ -276,6 +289,7 @@ func TestNewAPERequest(t *testing.T) { fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, "tag-attr1"): "value1", fmt.Sprintf(commonschema.PropertyKeyFormatFrostFSIDUserClaim, "tag-attr2"): "value2", commonschema.PropertyKeyFrostFSIDGroupID: "1", + commonschema.PropertyKeyFrostFSSourceIP: incomingIP, }, ) From 3627b44e92395d2be7eeda9790513021b9f345ca Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 20 May 2024 16:34:31 +0300 Subject: [PATCH 0579/1413] [#1142] tree: Fill APE-request with source IP property Signed-off-by: Airat Arifullin --- pkg/services/tree/ape.go | 11 ++++++++- pkg/services/tree/service.go | 12 +++++----- pkg/services/tree/signature.go | 5 +++-- pkg/services/tree/signature_test.go | 35 +++++++++++++++-------------- 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 622049d6a8..eabc02bd70 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -1,8 +1,10 @@ package tree import ( + "context" "encoding/hex" "fmt" + "net" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter" @@ -14,11 +16,13 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "google.golang.org/grpc/peer" ) -func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error { +func (s *Service) checkAPE(ctx context.Context, container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error { namespace := "" cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns") if hasNamespace { @@ -41,6 +45,11 @@ func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl. if err != nil { return apeErr(err) } + if p, ok := peer.FromContext(ctx); ok { + if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok { + reqProps[commonschema.PropertyKeyFrostFSSourceIP] = tcpAddr.IP.String() + } + } var resourceName string if namespace == "root" || namespace == "" { diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 903db4455a..cce41e94dd 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -105,7 +105,7 @@ func (s *Service) Add(ctx context.Context, req *AddRequest) (*AddResponse, error return nil, err } - err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectPut) + err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut) if err != nil { return nil, err } @@ -157,7 +157,7 @@ func (s *Service) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByP return nil, err } - err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectPut) + err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut) if err != nil { return nil, err } @@ -221,7 +221,7 @@ func (s *Service) Remove(ctx context.Context, req *RemoveRequest) (*RemoveRespon return nil, err } - err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectPut) + err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut) if err != nil { return nil, err } @@ -274,7 +274,7 @@ func (s *Service) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, er return nil, err } - err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectPut) + err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut) if err != nil { return nil, err } @@ -326,7 +326,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) return nil, err } - err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectGet) + err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectGet) if err != nil { return nil, err } @@ -408,7 +408,7 @@ func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeS return err } - err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectGet) + err := s.verifyClient(srv.Context(), req, cid, b.GetBearerToken(), acl.OpObjectGet) if err != nil { return err } diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 162b189e3c..0445ccfabc 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -2,6 +2,7 @@ package tree import ( "bytes" + "context" "crypto/ecdsa" "crypto/elliptic" "errors" @@ -48,7 +49,7 @@ var ( // Operation must be one of: // - 1. ObjectPut; // - 2. ObjectGet. -func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op acl.Op) error { +func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, rawBearer []byte, op acl.Op) error { err := verifyMessage(req) if err != nil { return err @@ -83,7 +84,7 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op // FIXME(@aarifullin): tree service temporiraly performs APE checks on // object verbs, because tree verbs have not been introduced yet. if basicACL == 0x0 { - return s.checkAPE(cnr, cid, op, role, pubKey) + return s.checkAPE(ctx, cnr, cid, op, role, pubKey) } if !basicACL.IsOpAllowed(op, role) { diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index b55f4d4fce..ce5039f7cb 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -1,6 +1,7 @@ package tree import ( + "context" "crypto/ecdsa" "crypto/sha256" "errors" @@ -132,26 +133,26 @@ func TestMessageSign(t *testing.T) { cnr.Value.SetBasicACL(acl.PublicRW) t.Run("missing signature, no panic", func(t *testing.T) { - require.Error(t, s.verifyClient(req, cid2, nil, op)) + require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op)) }) require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) - require.NoError(t, s.verifyClient(req, cid1, nil, op)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, nil, op)) t.Run("invalid CID", func(t *testing.T) { - require.Error(t, s.verifyClient(req, cid2, nil, op)) + require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op)) }) cnr.Value.SetBasicACL(acl.Private) t.Run("extension disabled", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) - require.Error(t, s.verifyClient(req, cid2, nil, op)) + require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op)) }) t.Run("invalid key", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.Error(t, s.verifyClient(req, cid1, nil, op)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, nil, op)) }) t.Run("bearer", func(t *testing.T) { @@ -164,7 +165,7 @@ func TestMessageSign(t *testing.T) { t.Run("invalid bearer", func(t *testing.T) { req.Body.BearerToken = []byte{0xFF} require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) - require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) t.Run("invalid bearer CID", func(t *testing.T) { @@ -173,7 +174,7 @@ func TestMessageSign(t *testing.T) { req.Body.BearerToken = bt.Marshal() require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) t.Run("invalid bearer owner", func(t *testing.T) { bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey()) @@ -181,7 +182,7 @@ func TestMessageSign(t *testing.T) { req.Body.BearerToken = bt.Marshal() require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) t.Run("invalid bearer signature", func(t *testing.T) { bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey()) @@ -193,7 +194,7 @@ func TestMessageSign(t *testing.T) { req.Body.BearerToken = bv2.StableMarshal(nil) require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) t.Run("impersonate", func(t *testing.T) { @@ -205,8 +206,8 @@ func TestMessageSign(t *testing.T) { req.Body.BearerToken = bt.Marshal() require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) - require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.NoError(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey()) @@ -216,18 +217,18 @@ func TestMessageSign(t *testing.T) { t.Run("put and get", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.NoError(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.NoError(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) t.Run("only get", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[2].PrivateKey)) - require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.NoError(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) t.Run("none", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[3].PrivateKey)) - require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) }) } From cc3f762cf29935bd06ee1c9c00ea1790703ba10d Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 28 May 2024 15:08:28 +0300 Subject: [PATCH 0580/1413] [#12] cli: clarify `-g` usage in `container list` Add usage replacement for `container list -g` and verbose warning when using `-g` without `--owner`. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/internal/commonflags/flags.go | 8 ++++---- cmd/frostfs-cli/modules/container/list.go | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-cli/internal/commonflags/flags.go b/cmd/frostfs-cli/internal/commonflags/flags.go index 5049dc3b15..6915ef42b2 100644 --- a/cmd/frostfs-cli/internal/commonflags/flags.go +++ b/cmd/frostfs-cli/internal/commonflags/flags.go @@ -11,9 +11,9 @@ import ( // values and their usage descriptions. const ( GenerateKey = "generate-key" - generateKeyShorthand = "g" - generateKeyDefault = false - generateKeyUsage = "Generate new private key" + GenerateKeyShorthand = "g" + GenerateKeyDefault = false + GenerateKeyUsage = "Generate new private key" WalletPath = "wallet" WalletPathShorthand = "w" @@ -72,7 +72,7 @@ func Init(cmd *cobra.Command) { func InitWithoutRPC(cmd *cobra.Command) { ff := cmd.Flags() - ff.BoolP(GenerateKey, generateKeyShorthand, generateKeyDefault, generateKeyUsage) + ff.BoolP(GenerateKey, GenerateKeyShorthand, GenerateKeyDefault, GenerateKeyUsage) ff.StringP(WalletPath, WalletPathShorthand, WalletPathDefault, WalletPathUsage) ff.StringP(Account, AccountShorthand, AccountDefault, AccountUsage) } diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index 8f5db49dfc..a1410d7a07 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -18,6 +18,8 @@ const ( flagListPrintAttr = "with-attr" flagListContainerOwner = "owner" flagListName = "name" + + generateKeyContainerUsage = commonflags.GenerateKeyUsage + ", should be used with --owner flag" ) // flag vars of list command. @@ -34,6 +36,11 @@ var listContainersCmd = &cobra.Command{ Run: func(cmd *cobra.Command, _ []string) { var idUser user.ID + generateKey, _ := cmd.Flags().GetBool(commonflags.GenerateKey) + if flagVarListContainerOwner == "" && generateKey { + cmd.PrintErrln("WARN: using -g without --owner - output will be empty") + } + key := key.GetOrGenerate(cmd) if flagVarListContainerOwner == "" { @@ -104,4 +111,5 @@ func initContainerListContainersCmd() { flags.BoolVar(&flagVarListPrintAttr, flagListPrintAttr, false, "Request and print attributes of each container", ) + flags.Lookup(commonflags.GenerateKey).Usage = generateKeyContainerUsage } From 4a34d0d40e6dcedd8da9a64ac6d9a53613498697 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Wed, 29 May 2024 11:01:01 +0300 Subject: [PATCH 0581/1413] [#1149] go.mod: Bump neo-go up to v0.106.0 Required to work with neo-go v0.106.0 node with default hardfork configuration. Without neo-go client version bump, it throws error. failed to get network magic: unexpected hardfork: Cockatrice Signed-off-by: Alex Vanin --- .../modules/morph/helper/local_client.go | 2 +- .../internal/modules/morph/helper/n3client.go | 2 +- go.mod | 19 ++++---- go.sum | 47 +++++++++---------- pkg/ape/chainbase/boltdb.go | 8 ++-- 5 files changed, 37 insertions(+), 41 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index 31203dde66..44d1b4ecf0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -113,7 +113,7 @@ func (l *LocalClient) GetBlockCount() (uint32, error) { return l.bc.BlockHeight(), nil } -func (l *LocalClient) GetNativeContracts() ([]state.NativeContract, error) { +func (l *LocalClient) GetNativeContracts() ([]state.Contract, error) { return l.bc.GetNatives(), nil } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index 84dd69c79c..55449b4357 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -27,7 +27,7 @@ type Client interface { invoker.RPCInvoke GetBlockCount() (uint32, error) - GetNativeContracts() ([]state.NativeContract, error) + GetNativeContracts() ([]state.Contract, error) GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error) GetVersion() (*result.Version, error) SendRawTransaction(*transaction.Transaction) (util.Uint256, error) diff --git a/go.mod b/go.mod index 81e2fa9890..1335747aad 100644 --- a/go.mod +++ b/go.mod @@ -24,21 +24,21 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.12.1 github.com/nats-io/nats.go v1.32.0 - github.com/nspcc-dev/neo-go v0.105.1 + github.com/nspcc-dev/neo-go v0.106.0 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 github.com/paulmach/orb v0.11.0 - github.com/prometheus/client_golang v1.18.0 + github.com/prometheus/client_golang v1.19.0 github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.18.2 github.com/ssgreg/journald v1.0.0 - github.com/stretchr/testify v1.8.4 - go.etcd.io/bbolt v1.3.8 + github.com/stretchr/testify v1.9.0 + go.etcd.io/bbolt v1.3.9 go.opentelemetry.io/otel v1.22.0 go.opentelemetry.io/otel/trace v1.22.0 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a golang.org/x/sync v0.6.0 golang.org/x/sys v0.18.0 @@ -78,7 +78,6 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -99,13 +98,13 @@ require ( github.com/multiformats/go-varint v0.0.7 // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect - github.com/nspcc-dev/go-ordered-json v0.0.0-20240112074137-296698a162ae // indirect - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240122090917-ef99a7a9e33f // indirect - github.com/nspcc-dev/rfc6979 v0.2.0 // indirect + github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 // indirect + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d // indirect + github.com/nspcc-dev/rfc6979 v0.2.1 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.46.0 // indirect + github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index 5dd9b24239..ce68ddb222 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,6 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= -github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -192,14 +190,14 @@ github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nspcc-dev/go-ordered-json v0.0.0-20240112074137-296698a162ae h1:UFgMXcZthqiCqCyr3dOAtGICJ10gM8q0mFHyLR0UPQU= -github.com/nspcc-dev/go-ordered-json v0.0.0-20240112074137-296698a162ae/go.mod h1:79bEUDEviBHJMFV6Iq6in57FEOCMcRhfQnfaf0ETA5U= -github.com/nspcc-dev/neo-go v0.105.1 h1:r0b2yIwLBi+ARBKU94gHL9oTFEB/XMJ0YlS2HN9Qw34= -github.com/nspcc-dev/neo-go v0.105.1/go.mod h1:GNh0cRALV/cuj+/xg2ZHDsrFbqcInqG7jjhqsLEnlNc= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240122090917-ef99a7a9e33f h1:6h0zgQGKdStROXRlWhz2dZmrKkSmOJ4oiDs06nO39XI= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240122090917-ef99a7a9e33f/go.mod h1:J/Mk6+nKeKSW4wygkZQFLQ6SkLOSGX5Ga0RuuuktEag= -github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= -github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= +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/go.mod h1:U5VfmPNM88P4RORFb6KSUVBdJBDhlqggJZYGXGPxOcc= +github.com/nspcc-dev/neo-go v0.106.0 h1:YiOdW/GcLmbVSvxMRfD5aytO6n3TDHrEA97VHMawy6g= +github.com/nspcc-dev/neo-go v0.106.0/go.mod h1:9k7vBqqQeePuj4c2CqMN9uPFsfxvwSk9vnQFrkE5eg8= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY= +github.com/nspcc-dev/rfc6979 v0.2.1 h1:8wWxkamHWFmO790GsewSoKUSJjVnL1fmdRpokU/RgRM= +github.com/nspcc-dev/rfc6979 v0.2.1/go.mod h1:Tk7h5kyUWkhjyO3zUgFFhy1v2vQv3BvQEntakdtqrWc= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -227,12 +225,12 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y= -github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ= +github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -272,8 +270,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= @@ -283,8 +282,6 @@ github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= -github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= -github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= @@ -294,8 +291,8 @@ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7Jul github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= @@ -319,8 +316,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -336,8 +333,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= +golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -413,8 +410,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= +golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/ape/chainbase/boltdb.go b/pkg/ape/chainbase/boltdb.go index 5f3c342c1a..005b3bd84d 100644 --- a/pkg/ape/chainbase/boltdb.go +++ b/pkg/ape/chainbase/boltdb.go @@ -1,6 +1,7 @@ package chainbase import ( + "bytes" "context" "errors" "fmt" @@ -11,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" - "github.com/nspcc-dev/neo-go/pkg/util/slice" "go.etcd.io/bbolt" ) @@ -203,7 +203,7 @@ func (cs *boltLocalOverrideStorage) GetOverride(name chain.Name, target policyen if serializedChain == nil { return fmt.Errorf("%w: %w: %s", policyengine.ErrChainNotFound, ErrBucketNotContainsChainID, chainID) } - serializedChain = slice.Copy(serializedChain) + serializedChain = bytes.Clone(serializedChain) return nil }); err != nil { return nil, err @@ -246,7 +246,7 @@ func (cs *boltLocalOverrideStorage) ListOverrides(name chain.Name, target policy return err } return rbuck.ForEach(func(_, v []byte) error { - serializedChain = slice.Copy(v) + serializedChain = bytes.Clone(v) serializedChains = append(serializedChains, serializedChain) return nil }) @@ -315,7 +315,7 @@ func getTargets(tx *bbolt.Tx, name chain.Name) ([]policyengine.Target, error) { if err := nbucket.Bucket(k).ForEachBucket(func(k []byte) error { targets = append(targets, policyengine.Target{ Type: ttype, - Name: string(slice.Copy(k)), + Name: string(bytes.Clone(k)), }) return nil }); err != nil { From 50923ed81c085fa6556ac58c4dd7f7d6cc06d76c Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 27 May 2024 15:57:02 +0300 Subject: [PATCH 0582/1413] [#1147] Fix gofumpt issue Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/ape_manager/add_chain.go | 4 +--- pkg/services/apemanager/executor.go | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/ape_manager/add_chain.go b/cmd/frostfs-cli/modules/ape_manager/add_chain.go index 7e6614392a..dea7fb36e1 100644 --- a/cmd/frostfs-cli/modules/ape_manager/add_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/add_chain.go @@ -38,9 +38,7 @@ const ( groupTarget = "group" ) -var ( - errUnknownTargetType = errors.New("unknown target type") -) +var errUnknownTargetType = errors.New("unknown target type") var addCmd = &cobra.Command{ Use: "add", diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go index bad43b5fa0..9cfc97473f 100644 --- a/pkg/services/apemanager/executor.go +++ b/pkg/services/apemanager/executor.go @@ -24,9 +24,7 @@ import ( "go.uber.org/zap" ) -var ( - errEmptyBodySignature = errors.New("malformed request: empty body signature") -) +var errEmptyBodySignature = errors.New("malformed request: empty body signature") type cfg struct { log *logger.Logger From e43e7bec3a9c8ea39e75e949c40a3996138b51d0 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 27 May 2024 15:57:48 +0300 Subject: [PATCH 0583/1413] [#1147] log: Remove redundant `address` field from log Filled when logger created for `request` object from package `getsvc`. Signed-off-by: Anton Nikiforov --- pkg/services/object/get/assemble.go | 3 --- pkg/services/object/get/assembleec.go | 3 --- 2 files changed, 6 deletions(-) diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index 3f4a02c027..66c4580b06 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -41,12 +41,10 @@ func (r *request) assemble(ctx context.Context) { assembler := newAssembler(r.address(), r.splitInfo(), r.ctxRange(), r) r.log.Debug(logs.GetAssemblingSplittedObject, - zap.Stringer("address", r.address()), zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) defer r.log.Debug(logs.GetAssemblingSplittedObjectCompleted, - zap.Stringer("address", r.address()), zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) @@ -55,7 +53,6 @@ func (r *request) assemble(ctx context.Context) { if err != nil { r.log.Warn(logs.GetFailedToAssembleSplittedObject, zap.Error(err), - zap.Stringer("address", r.address()), zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) diff --git a/pkg/services/object/get/assembleec.go b/pkg/services/object/get/assembleec.go index 58641c975a..5c999929af 100644 --- a/pkg/services/object/get/assembleec.go +++ b/pkg/services/object/get/assembleec.go @@ -39,12 +39,10 @@ func (r *request) assembleEC(ctx context.Context) { assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.containerSource, r.log) r.log.Debug(logs.GetAssemblingECObject, - zap.Stringer("address", r.address()), zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) defer r.log.Debug(logs.GetAssemblingECObjectCompleted, - zap.Stringer("address", r.address()), zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) @@ -53,7 +51,6 @@ func (r *request) assembleEC(ctx context.Context) { if err != nil { r.log.Warn(logs.GetFailedToAssembleECObject, zap.Error(err), - zap.Stringer("address", r.address()), zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) From 3555c73225dfe87e0a7eb8a8a801f8880f0c23c3 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 27 May 2024 16:03:22 +0300 Subject: [PATCH 0584/1413] [#1147] object: Use methods on pointer for `deletesvc.execCtx` Signed-off-by: Anton Nikiforov --- pkg/services/object/delete/exec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index d48f8ab7b4..d119328a6e 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -40,7 +40,7 @@ func (exec *execCtx) setLogger(l *logger.Logger) { )} } -func (exec execCtx) isLocal() bool { +func (exec *execCtx) isLocal() bool { return exec.prm.common.LocalOnly() } From d355274cd0f708022382ddda78ccdfdb85d2854f Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 27 May 2024 16:05:20 +0300 Subject: [PATCH 0585/1413] [#1147] object: Use methods on pointer for `searchsvc.execCtx` Signed-off-by: Anton Nikiforov --- pkg/services/object/search/exec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index 2e0d487734..4a2c04ecd6 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -28,7 +28,7 @@ func (exec *execCtx) setLogger(l *logger.Logger) { )} } -func (exec execCtx) isLocal() bool { +func (exec *execCtx) isLocal() bool { return exec.prm.common.LocalOnly() } From a82c8cc5b87c3511e75aec7f52289bea8175ad90 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 27 May 2024 16:11:57 +0300 Subject: [PATCH 0586/1413] [#1147] gc: Execute callback for expired tombstones when they exists Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/shard/gc.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index ef8e97d34a..d605746e84 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -525,7 +525,9 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { } log.Debug(logs.ShardHandlingExpiredTombstonesBatch, zap.Int("number", len(tssExp))) - s.expiredTombstonesCallback(ctx, tssExp) + if len(tssExp) > 0 { + s.expiredTombstonesCallback(ctx, tssExp) + } iterPrm.SetOffset(tss[tssLen-1].Address()) tss = tss[:0] From 88b8ddd9023670893bb8f0950caf80de6f541f39 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 27 May 2024 21:31:59 +0300 Subject: [PATCH 0587/1413] [#1147] cli: Fix output when print EC info with flags `json` & `proto` Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/object/range.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/modules/object/range.go b/cmd/frostfs-cli/modules/object/range.go index 9ba752237f..ad4bc3d598 100644 --- a/cmd/frostfs-cli/modules/object/range.go +++ b/cmd/frostfs-cli/modules/object/range.go @@ -152,7 +152,11 @@ func printECInfoErr(cmd *cobra.Command, err error) bool { ok := errors.As(err, &errECInfo) if ok { - cmd.PrintErrln("Object is erasure-encoded, ec information received.") + toJSON, _ := cmd.Flags().GetBool(commonflags.JSON) + toProto, _ := cmd.Flags().GetBool("proto") + if !(toJSON || toProto) { + cmd.PrintErrln("Object is erasure-encoded, ec information received.") + } printECInfo(cmd, errECInfo.ECInfo()) } From 6130650bb6e7501f22b176b90eb3e5274b009f6e Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 27 May 2024 22:07:43 +0300 Subject: [PATCH 0588/1413] [#1147] node: Implement `Lock\Delete` requests for EC object Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/object/util.go | 28 +++++---- internal/logs/logs.go | 2 + pkg/local_object_storage/engine/delete.go | 38 +++++++++++- .../engine/engine_test.go | 3 +- pkg/local_object_storage/engine/exists.go | 11 +++- pkg/local_object_storage/engine/inhume.go | 30 +++++++++- pkg/local_object_storage/engine/lock.go | 21 ++++++- pkg/local_object_storage/engine/put.go | 20 ++++++- pkg/local_object_storage/metabase/delete.go | 44 +++++++++++++- pkg/local_object_storage/metabase/exists.go | 38 ++++++++---- pkg/local_object_storage/metabase/inhume.go | 43 ++++++++++++++ pkg/local_object_storage/metabase/lock.go | 58 +++++++++++++++++++ pkg/local_object_storage/metabase/put.go | 2 +- pkg/local_object_storage/metabase/select.go | 2 +- pkg/local_object_storage/shard/exists.go | 18 +++++- pkg/local_object_storage/shard/lock.go | 17 ++++++ pkg/services/object/delete/exec.go | 30 +++++++++- pkg/services/object/delete/local.go | 14 +---- pkg/services/object/delete/service.go | 2 +- pkg/services/object/delete/util.go | 16 +---- 20 files changed, 371 insertions(+), 66 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index c8625eb942..ff6b3219d6 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -357,6 +357,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, _, err := internal.HeadObject(cmd.Context(), prmHead) var errSplit *objectSDK.SplitInfoError + var errEC *objectSDK.ECInfoError switch { default: @@ -366,19 +367,22 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, return nil case errors.As(err, &errSplit): common.PrintVerbose(cmd, "Split information received - object is virtual.") + splitInfo := errSplit.SplitInfo() + + if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnr, true); ok { + return members + } + + if members, ok := tryGetSplitMembersBySplitID(cmd, splitInfo, cli, cnr); ok { + return members + } + + return tryRestoreChainInReverse(cmd, splitInfo, prmHead, cli, cnr, obj) + case errors.As(err, &errEC): + common.PrintVerbose(cmd, "Object is erasure-coded.") + return nil } - - splitInfo := errSplit.SplitInfo() - - if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnr, true); ok { - return members - } - - if members, ok := tryGetSplitMembersBySplitID(cmd, splitInfo, cli, cnr); ok { - return members - } - - return tryRestoreChainInReverse(cmd, splitInfo, prmHead, cli, cnr, obj) + return nil } func tryGetSplitMembersByLinkingObject(cmd *cobra.Command, splitInfo *objectSDK.SplitInfo, prmHead internal.HeadObjectPrm, cnr cid.ID, withLinking bool) ([]oid.ID, bool) { diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 43fd776242..7dc63341da 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -95,6 +95,7 @@ const ( DeleteFormingSplitInfo = "forming split info..." DeleteSplitInfoSuccessfullyFormedCollectingMembers = "split info successfully formed, collecting members..." DeleteMembersSuccessfullyCollected = "members successfully collected" + DeleteECObjectReceived = "erasure-coded object received, form tombstone" GetRemoteCallFailed = "remote call failed" GetCanNotAssembleTheObject = "can not assemble the object" GetTryingToAssembleTheObject = "trying to assemble the object..." @@ -213,6 +214,7 @@ const ( EngineFinishedRemovalOfLocallyredundantCopies = "finished removal of locally-redundant copies" EngineRemovingAnObjectWithoutFullLockingCheck = "removing an object without full locking check" EngineInterruptProcessingTheExpiredLocks = "interrupt processing the expired locks" + EngineInterruptGettingLockers = "can't get object's lockers" EngineInterruptProcessingTheDeletedLocks = "interrupt processing the deleted locks" EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly = "failed to move shard in degraded-read-only mode, moving to read-only" EngineFailedToMoveShardInReadonlyMode = "failed to move shard in read-only mode" diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 68a7325c65..44a6122133 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -76,6 +76,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e is bool } var splitInfo *objectSDK.SplitInfo + var ecInfo *objectSDK.ECInfo // Removal of a big object is done in multiple stages: // 1. Remove the parent object. If it is locked or already removed, return immediately. @@ -91,13 +92,18 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e } var splitErr *objectSDK.SplitInfoError - if !errors.As(err, &splitErr) { + var ecErr *objectSDK.ECInfoError + if errors.As(err, &splitErr) { + splitInfo = splitErr.SplitInfo() + } else if errors.As(err, &ecErr) { + e.deleteChunks(ctx, sh, ecInfo, prm) + return false + } else { if !client.IsErrObjectNotFound(err) { e.reportShardError(sh, "could not check object existence", err) } return false } - splitInfo = splitErr.SplitInfo() } else if !resExists.Exists() { return false } @@ -171,3 +177,31 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo return false }) } + +func (e *StorageEngine) deleteChunks( + ctx context.Context, sh hashedShard, ecInfo *objectSDK.ECInfo, prm DeletePrm, +) { + var inhumePrm shard.InhumePrm + if prm.forceRemoval { + inhumePrm.ForceRemoval() + } + for _, chunk := range ecInfo.Chunks { + var addr oid.Address + addr.SetContainer(prm.addr.Container()) + var objID oid.ID + err := objID.ReadFromV2(chunk.ID) + if err != nil { + e.reportShardError(sh, "could not delete EC chunk", err) + } + addr.SetObject(objID) + inhumePrm.MarkAsGarbage(addr) + _, err = sh.Inhume(ctx, inhumePrm) + if err != nil { + e.log.Debug(logs.EngineCouldNotInhumeObjectInShard, + zap.Stringer("addr", addr), + zap.String("err", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + continue + } + } +} diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index b82700ed84..70c54590f7 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -17,6 +17,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "git.frostfs.info/TrueCloudLab/hrw" "github.com/panjf2000/ants/v2" @@ -62,7 +63,7 @@ func benchmarkExists(b *testing.B, shardNum int) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - ok, err := e.exists(context.Background(), addr) + ok, _, err := e.exists(context.Background(), addr, oid.Address{}) if err != nil || ok { b.Fatalf("%t %v", ok, err) } diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index ef62927686..ce669ec5ed 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -11,11 +11,13 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) -func (e *StorageEngine) exists(ctx context.Context, addr oid.Address) (bool, error) { +func (e *StorageEngine) exists(ctx context.Context, addr oid.Address, parentAddr oid.Address) (bool, bool, error) { var shPrm shard.ExistsPrm shPrm.SetAddress(addr) + shPrm.SetParentAddress(parentAddr) alreadyRemoved := false exists := false + locked := false e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { res, err := sh.Exists(ctx, shPrm) @@ -44,13 +46,16 @@ func (e *StorageEngine) exists(ctx context.Context, addr oid.Address) (bool, err if !exists { exists = res.Exists() } + if !locked { + locked = res.Locked() + } return false }) if alreadyRemoved { - return false, new(apistatus.ObjectAlreadyRemoved) + return false, false, new(apistatus.ObjectAlreadyRemoved) } - return exists, nil + return exists, locked, nil } diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 80eda2204b..62e7be933e 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -152,7 +152,8 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh } var siErr *objectSDK.SplitInfoError - if !errors.As(err, &siErr) { + var ecErr *objectSDK.ECInfoError + if !(errors.As(err, &siErr) || errors.As(err, &ecErr)) { e.reportShardError(sh, "could not check for presents in shard", err) return } @@ -220,6 +221,33 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e return locked, outErr } +// GetLocked return lock id's if object is locked according to StorageEngine's state. +func (e *StorageEngine) GetLocked(ctx context.Context, addr oid.Address) ([]oid.ID, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.GetLocked", + trace.WithAttributes( + attribute.String("address", addr.EncodeToString()), + )) + defer span.End() + + var locked []oid.ID + var outErr error + + e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { + ld, err := h.Shard.GetLocked(ctx, addr) + if err != nil { + e.reportShardError(h, logs.EngineInterruptGettingLockers, err, zap.Stringer("addr", addr), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + outErr = err + } + locked = append(locked, ld...) + return false + }) + if len(locked) > 0 { + return locked, nil + } + return locked, outErr +} + func (e *StorageEngine) processExpiredTombstones(ctx context.Context, addrs []meta.TombstonedObject) { e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { sh.HandleExpiredTombstones(ctx, addrs) diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index 5ad6034210..af56c3e1e1 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -83,7 +83,26 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo exRes, err := sh.Exists(ctx, existsPrm) if err != nil { var siErr *objectSDK.SplitInfoError - if !errors.As(err, &siErr) { + var eiErr *objectSDK.ECInfoError + if errors.As(err, &eiErr) { + eclocked := []oid.ID{locked} + for _, chunk := range eiErr.ECInfo().Chunks { + var objID oid.ID + err = objID.ReadFromV2(chunk.ID) + if err != nil { + e.reportShardError(sh, "could not lock object in shard", err) + return false + } + eclocked = append(eclocked, objID) + } + err = sh.Lock(ctx, idCnr, locker, eclocked) + if err != nil { + e.reportShardError(sh, "could not lock object in shard", err) + return false + } + root = true + return false + } else if !errors.As(err, &siErr) { if shard.IsErrObjectExpired(err) { // object is already expired => // do not lock it diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 777f728b74..aa94ef22ea 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -80,11 +80,29 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // In #1146 this check was parallelized, however, it became // much slower on fast machines for 4 shards. - _, err := e.exists(ctx, addr) + var parent oid.Address + if prm.obj.ECHeader() != nil { + parent.SetObject(prm.obj.ECHeader().Parent()) + parent.SetContainer(addr.Container()) + } + existed, locked, err := e.exists(ctx, addr, parent) if err != nil { return err } + if !existed && locked { + lockers, err := e.GetLocked(ctx, parent) + if err != nil { + return err + } + for _, locker := range lockers { + err = e.lock(ctx, addr.Container(), locker, []oid.ID{addr.Object()}) + if err != nil { + return err + } + } + } + var shRes putToShardRes e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { e.mtx.RLock() diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index e591b86616..4addeae770 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -267,8 +267,10 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter return deleteSingleResult{}, nil } var siErr *objectSDK.SplitInfoError - if errors.As(err, &siErr) { + var ecErr *objectSDK.ECInfoError + if errors.As(err, &siErr) || errors.As(err, &ecErr) { // if object is virtual (parent) then do nothing, it will be deleted with last child + // if object is erasure-coded it will be deleted with the last chunk presented on the shard return deleteSingleResult{}, nil } @@ -471,6 +473,46 @@ func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error name: rootBucketName(cnr, bucketName), key: objKey, }) + if obj.ECHeader() != nil { + err := delECInfo(tx, cnr, objKey, obj.ECHeader()) + if err != nil { + return err + } + } return nil } + +func delECInfo(tx *bbolt.Tx, cnr cid.ID, objKey []byte, ecHead *objectSDK.ECHeader) error { + parentID := objectKey(ecHead.Parent(), make([]byte, objectKeySize)) + bucketName := make([]byte, bucketKeySize) + + val := getFromBucket(tx, ecInfoBucketName(cnr, bucketName), parentID) + if len(val) > 0 { + if bytes.Equal(val, objKey) { + delUniqueIndexItem(tx, namedBucketItem{ + name: ecInfoBucketName(cnr, bucketName), + key: parentID, + }) + } else { + val = bytes.Clone(val) + offset := 0 + for offset < len(val) { + if bytes.Equal(objKey, val[offset:offset+objectKeySize]) { + val = append(val[:offset], val[offset+objectKeySize:]...) + break + } + offset += objectKeySize + } + err := putUniqueIndexItem(tx, namedBucketItem{ + name: ecInfoBucketName(cnr, make([]byte, bucketKeySize)), + key: parentID, + val: val, + }) + if err != nil { + return err + } + } + } + return nil +} diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index bf6766c058..153d921103 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -20,12 +20,14 @@ import ( // ExistsPrm groups the parameters of Exists operation. type ExistsPrm struct { - addr oid.Address + addr oid.Address + paddr oid.Address } // ExistsRes groups the resulting values of Exists operation. type ExistsRes struct { exists bool + locked bool } var ErrLackSplitInfo = logicerr.New("no split info on parent object") @@ -35,11 +37,21 @@ func (p *ExistsPrm) SetAddress(addr oid.Address) { p.addr = addr } +// SetParent is an Exists option to set objects parent. +func (p *ExistsPrm) SetParent(addr oid.Address) { + p.paddr = addr +} + // Exists returns the fact that the object is in the metabase. func (p ExistsRes) Exists() bool { return p.exists } +// Locked returns the fact that the object is locked. +func (p ExistsRes) Locked() bool { + return p.locked +} + // Exists returns ErrAlreadyRemoved if addr was marked as removed. Otherwise it // returns true if addr is in primary index or false if it is not. // @@ -70,7 +82,7 @@ func (db *DB) Exists(ctx context.Context, prm ExistsPrm) (res ExistsRes, err err currEpoch := db.epochState.CurrentEpoch() err = db.boltDB.View(func(tx *bbolt.Tx) error { - res.exists, err = db.exists(tx, prm.addr, currEpoch) + res.exists, res.locked, err = db.exists(tx, prm.addr, prm.paddr, currEpoch) return err }) @@ -78,15 +90,19 @@ func (db *DB) Exists(ctx context.Context, prm ExistsPrm) (res ExistsRes, err err return res, metaerr.Wrap(err) } -func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (exists bool, err error) { +func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, parent oid.Address, currEpoch uint64) (bool, bool, error) { + var locked bool + if !parent.Equals(oid.Address{}) { + locked = objectLocked(tx, parent.Container(), parent.Object()) + } // check graveyard and object expiration first switch objectStatus(tx, addr, currEpoch) { case 1: - return false, logicerr.Wrap(new(apistatus.ObjectNotFound)) + return false, locked, logicerr.Wrap(new(apistatus.ObjectNotFound)) case 2: - return false, logicerr.Wrap(new(apistatus.ObjectAlreadyRemoved)) + return false, locked, logicerr.Wrap(new(apistatus.ObjectAlreadyRemoved)) case 3: - return false, ErrObjectIsExpired + return false, locked, ErrObjectIsExpired } objKey := objectKey(addr.Object(), make([]byte, objectKeySize)) @@ -96,25 +112,25 @@ func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (exists b // if graveyard is empty, then check if object exists in primary bucket if inBucket(tx, primaryBucketName(cnr, key), objKey) { - return true, nil + return true, locked, nil } // if primary bucket is empty, then check if object exists in parent bucket if inBucket(tx, parentBucketName(cnr, key), objKey) { splitInfo, err := getSplitInfo(tx, cnr, objKey) if err != nil { - return false, err + return false, locked, err } - return false, logicerr.Wrap(objectSDK.NewSplitInfoError(splitInfo)) + return false, locked, logicerr.Wrap(objectSDK.NewSplitInfoError(splitInfo)) } // if parent bucket is empty, then check if object exists in ec bucket if data := getFromBucket(tx, ecInfoBucketName(cnr, key), objKey); len(data) != 0 { - return false, getECInfoError(tx, cnr, data) + return false, locked, getECInfoError(tx, cnr, data) } // if parent bucket is empty, then check if object exists in typed buckets - return firstIrregularObjectType(tx, cnr, objKey) != objectSDK.TypeRegular, nil + return firstIrregularObjectType(tx, cnr, objKey) != objectSDK.TypeRegular, locked, nil } // objectStatus returns: diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 250504120d..c265fb2173 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -229,11 +229,17 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes obj, err := db.get(tx, prm.target[i], buf, false, true, epoch) targetKey := addressKey(prm.target[i], buf) + var ecErr *objectSDK.ECInfoError if err == nil { err = db.updateDeleteInfo(tx, garbageBKT, graveyardBKT, targetKey, cnr, obj, res) if err != nil { return err } + } else if errors.As(err, &ecErr) { + err = db.inhumeECInfo(tx, epoch, prm.tomb, res, garbageBKT, graveyardBKT, ecErr.ECInfo(), cnr, bkt, value, targetKey) + if err != nil { + return err + } } if prm.tomb != nil { @@ -272,6 +278,43 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes return db.applyInhumeResToCounters(tx, res) } +func (db *DB) inhumeECInfo(tx *bbolt.Tx, epoch uint64, tomb *oid.Address, res *InhumeRes, + garbageBKT *bbolt.Bucket, graveyardBKT *bbolt.Bucket, + ecInfo *objectSDK.ECInfo, cnr cid.ID, targetBucket *bbolt.Bucket, value []byte, targetKey []byte, +) error { + for _, chunk := range ecInfo.Chunks { + chunkBuf := make([]byte, addressKeySize) + var chunkAddr oid.Address + chunkAddr.SetContainer(cnr) + var chunkID oid.ID + err := chunkID.ReadFromV2(chunk.ID) + if err != nil { + return err + } + chunkAddr.SetObject(chunkID) + chunkObj, err := db.get(tx, chunkAddr, chunkBuf, false, true, epoch) + if err != nil { + return err + } + err = db.updateDeleteInfo(tx, garbageBKT, graveyardBKT, targetKey, cnr, chunkObj, res) + if err != nil { + return err + } + chunkKey := addressKey(chunkAddr, chunkBuf) + if tomb != nil { + _, err = db.markAsGC(graveyardBKT, garbageBKT, chunkKey) + if err != nil { + return err + } + } + err = targetBucket.Put(chunkKey, value) + if err != nil { + return err + } + } + return nil +} + func (db *DB) applyInhumeResToCounters(tx *bbolt.Tx, res *InhumeRes) error { if err := db.updateShardObjectCounter(tx, logical, res.LogicInhumed(), false); err != nil { return err diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index 0bc2b06f0c..732ba426dd 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -175,6 +175,31 @@ func objectLocked(tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) bool { return false } +// return `LOCK` id's if specified object is locked in the specified container. +func getLocked(tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) ([]oid.ID, error) { + var lockers []oid.ID + bucketLocked := tx.Bucket(bucketNameLocked) + if bucketLocked != nil { + key := make([]byte, cidSize) + idCnr.Encode(key) + bucketLockedContainer := bucketLocked.Bucket(key) + if bucketLockedContainer != nil { + binObjIDs, err := decodeList(bucketLockedContainer.Get(objectKey(idObj, key))) + if err != nil { + return nil, fmt.Errorf("decode list of object lockers: %w", err) + } + for _, binObjID := range binObjIDs { + var id oid.ID + if err = id.Decode(binObjID); err != nil { + return nil, err + } + lockers = append(lockers, id) + } + } + } + return lockers, nil +} + // releases all records about the objects locked by the locker. // Returns slice of unlocked object ID's or an error. // @@ -325,3 +350,36 @@ func (db *DB) IsLocked(ctx context.Context, prm IsLockedPrm) (res IsLockedRes, e success = err == nil return res, err } + +// GetLocked return `LOCK` id's if provided object is locked by any `LOCK`. Not found +// object is considered as non-locked. +// +// Returns only non-logical errors related to underlying database. +func (db *DB) GetLocked(ctx context.Context, addr oid.Address) (res []oid.ID, err error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("GetLocked", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "metabase.GetLocked", + trace.WithAttributes( + attribute.String("address", addr.EncodeToString()), + )) + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return res, ErrDegradedMode + } + err = metaerr.Wrap(db.boltDB.View(func(tx *bbolt.Tx) error { + res, err = getLocked(tx, addr.Container(), addr.Object()) + return nil + })) + success = err == nil + return res, err +} diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 8b7b830166..94e68d85af 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -115,7 +115,7 @@ func (db *DB) put(tx *bbolt.Tx, isParent := si != nil - exists, err := db.exists(tx, objectCore.AddressOf(obj), currEpoch) + exists, _, err := db.exists(tx, objectCore.AddressOf(obj), oid.Address{}, currEpoch) var splitInfoError *objectSDK.SplitInfoError if errors.As(err, &splitInfoError) { diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index e5321c7948..65d0111c46 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -428,7 +428,7 @@ func (db *DB) selectObjectID( addr.SetObject(id) var splitInfoError *objectSDK.SplitInfoError - ok, err := db.exists(tx, addr, currEpoch) + ok, _, err := db.exists(tx, addr, oid.Address{}, currEpoch) if (err == nil && ok) || errors.As(err, &splitInfoError) { raw := make([]byte, objectKeySize) id.Encode(raw) diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index 2cdb8dfa8e..12c339c057 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -13,12 +13,14 @@ import ( // ExistsPrm groups the parameters of Exists operation. type ExistsPrm struct { - addr oid.Address + addr oid.Address + paddr oid.Address } // ExistsRes groups the resulting values of Exists operation. type ExistsRes struct { ex bool + lc bool } // SetAddress is an Exists option to set object checked for existence. @@ -26,11 +28,21 @@ func (p *ExistsPrm) SetAddress(addr oid.Address) { p.addr = addr } +// SetParentAddress is an Exists option to set parent object checked for existence. +func (p *ExistsPrm) SetParentAddress(addr oid.Address) { + p.paddr = addr +} + // Exists returns the fact that the object is in the shard. func (p ExistsRes) Exists() bool { return p.ex } +// Locked returns the fact that the object is locked. +func (p ExistsRes) Locked() bool { + return p.lc +} + // Exists checks if object is presented in shard. // // Returns any error encountered that does not allow to @@ -48,6 +60,7 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { defer span.End() var exists bool + var locked bool var err error s.m.RLock() @@ -65,13 +78,16 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { } else { var existsPrm meta.ExistsPrm existsPrm.SetAddress(prm.addr) + existsPrm.SetParent(prm.paddr) var res meta.ExistsRes res, err = s.metaBase.Exists(ctx, existsPrm) exists = res.Exists() + locked = res.Locked() } return ExistsRes{ ex: exists, + lc: locked, }, err } diff --git a/pkg/local_object_storage/shard/lock.go b/pkg/local_object_storage/shard/lock.go index 52186cbfdb..4a8d89d630 100644 --- a/pkg/local_object_storage/shard/lock.go +++ b/pkg/local_object_storage/shard/lock.go @@ -71,3 +71,20 @@ func (s *Shard) IsLocked(ctx context.Context, addr oid.Address) (bool, error) { return res.Locked(), nil } + +// GetLocked return lock id's of the provided object. Not found object is +// considered as not locked. Requires healthy metabase, returns ErrDegradedMode otherwise. +func (s *Shard) GetLocked(ctx context.Context, addr oid.Address) ([]oid.ID, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.GetLocked", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.String("address", addr.EncodeToString()), + )) + defer span.End() + + m := s.GetMode() + if m.NoMetabase() { + return nil, ErrDegradedMode + } + return s.metaBase.GetLocked(ctx, addr) +} diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index d119328a6e..45bd89d36d 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -2,6 +2,7 @@ package deletesvc import ( "context" + "errors" "fmt" "strconv" @@ -64,9 +65,32 @@ func (exec *execCtx) newAddress(id oid.ID) oid.Address { return a } -func (exec *execCtx) formSplitInfo(ctx context.Context) error { - var err error - exec.splitInfo, err = exec.svc.header.splitInfo(ctx, exec) +func (exec *execCtx) formExtendedInfo(ctx context.Context) error { + _, err := exec.svc.header.head(ctx, exec) + + var errSplitInfo *objectSDK.SplitInfoError + var errECInfo *objectSDK.ECInfoError + + switch { + case err == nil: + return nil + case errors.As(err, &errSplitInfo): + exec.splitInfo = errSplitInfo.SplitInfo() + exec.tombstone.SetSplitID(exec.splitInfo.SplitID()) + + exec.log.Debug(logs.DeleteSplitInfoSuccessfullyFormedCollectingMembers) + + if err := exec.collectMembers(ctx); err != nil { + return err + } + + exec.log.Debug(logs.DeleteMembersSuccessfullyCollected) + return nil + case errors.As(err, &errECInfo): + exec.log.Debug(logs.DeleteECObjectReceived) + return nil + } + if err != nil && !apiclient.IsErrObjectAlreadyRemoved(err) { // IsErrObjectAlreadyRemoved check is required because splitInfo // implicitly performs Head request that may return ObjectAlreadyRemoved diff --git a/pkg/services/object/delete/local.go b/pkg/services/object/delete/local.go index 55ce4408d9..2c3c47f491 100644 --- a/pkg/services/object/delete/local.go +++ b/pkg/services/object/delete/local.go @@ -35,19 +35,9 @@ func (exec *execCtx) formTombstone(ctx context.Context) error { exec.log.Debug(logs.DeleteFormingSplitInfo) - if err := exec.formSplitInfo(ctx); err != nil { - return fmt.Errorf("form split info: %w", err) + if err := exec.formExtendedInfo(ctx); err != nil { + return fmt.Errorf("form extended info: %w", err) } - exec.log.Debug(logs.DeleteSplitInfoSuccessfullyFormedCollectingMembers) - - exec.tombstone.SetSplitID(exec.splitInfo.SplitID()) - - if err := exec.collectMembers(ctx); err != nil { - return err - } - - exec.log.Debug(logs.DeleteMembersSuccessfullyCollected) - return exec.initTombstoneObject() } diff --git a/pkg/services/object/delete/service.go b/pkg/services/object/delete/service.go index 0ba4da4379..0ba21eee38 100644 --- a/pkg/services/object/delete/service.go +++ b/pkg/services/object/delete/service.go @@ -41,7 +41,7 @@ type cfg struct { header interface { // must return (nil, nil) for PHY objects - splitInfo(context.Context, *execCtx) (*objectSDK.SplitInfo, error) + head(context.Context, *execCtx) (*objectSDK.Object, error) children(context.Context, *execCtx) ([]oid.ID, error) diff --git a/pkg/services/object/delete/util.go b/pkg/services/object/delete/util.go index 439abca2ba..bb2b5f00b7 100644 --- a/pkg/services/object/delete/util.go +++ b/pkg/services/object/delete/util.go @@ -2,7 +2,6 @@ package deletesvc import ( "context" - "errors" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" @@ -44,19 +43,8 @@ func (w *headSvcWrapper) headAddress(ctx context.Context, exec *execCtx, addr oi return wr.Object(), nil } -func (w *headSvcWrapper) splitInfo(ctx context.Context, exec *execCtx) (*objectSDK.SplitInfo, error) { - _, err := w.headAddress(ctx, exec, exec.address()) - - var errSplitInfo *objectSDK.SplitInfoError - - switch { - case err == nil: - return nil, nil - case errors.As(err, &errSplitInfo): - return errSplitInfo.SplitInfo(), nil - default: - return nil, err - } +func (w *headSvcWrapper) head(ctx context.Context, exec *execCtx) (*objectSDK.Object, error) { + return w.headAddress(ctx, exec, exec.address()) } func (w *headSvcWrapper) children(ctx context.Context, exec *execCtx) ([]oid.ID, error) { From 9f80d6d9a20e1d027f768f1b3c3737f960ebc40f Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 28 May 2024 12:14:13 +0300 Subject: [PATCH 0589/1413] [#1147] Makefile: Fix `gopls-run` target Signed-off-by: Anton Nikiforov --- Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 710c12703d..c93d06aa87 100755 --- a/Makefile +++ b/Makefile @@ -44,9 +44,12 @@ PROTOGEN_FROSTFS_DIR ?= $(PROTOBUF_DIR)/protogen-$(PROTOGEN_FROSTFS_VERSION) STATICCHECK_DIR ?= $(abspath $(BIN))/staticcheck STATICCHECK_VERSION_DIR ?= $(STATICCHECK_DIR)/$(STATICCHECK_VERSION) +SOURCES = $(shell find . -type f -name "*.go" -print) + GOPLS_VERSION ?= v0.15.1 GOPLS_DIR ?= $(abspath $(BIN))/gopls GOPLS_VERSION_DIR ?= $(GOPLS_DIR)/$(GOPLS_VERSION) +GOPLS_TEMP_FILE := $(shell mktemp) FROSTFS_CONTRACTS_PATH=$(abspath ./../frostfs-contract) LOCODE_DB_PATH=$(abspath ./.cache/locode_db) @@ -220,9 +223,12 @@ gopls-run: @if [ ! -d "$(GOPLS_VERSION_DIR)" ]; then \ make gopls-install; \ fi - @if [[ $$(find . -type f -name "*.go" -print | xargs $(GOPLS_VERSION_DIR)/gopls check | tee /dev/tty | wc -l) -ne 0 ]]; then \ + $(GOPLS_VERSION_DIR)/gopls check $(SOURCES) 2>&1 >$(GOPLS_TEMP_FILE) + @if [[ $$(wc -l < $(GOPLS_TEMP_FILE)) -ne 0 ]]; then \ + cat $(GOPLS_TEMP_FILE); \ exit 1; \ fi + rm $(GOPLS_TEMP_FILE) # Run linters in Docker docker/lint: From c1af13b47e234a91cc8e1909920ac0ea2faf8a07 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 28 May 2024 12:21:08 +0300 Subject: [PATCH 0590/1413] [#1147] node: Fix issue from `gopls` Signed-off-by: Anton Nikiforov --- pkg/services/object/delete/exec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index 45bd89d36d..22928dcd5b 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -91,7 +91,7 @@ func (exec *execCtx) formExtendedInfo(ctx context.Context) error { return nil } - if err != nil && !apiclient.IsErrObjectAlreadyRemoved(err) { + if !apiclient.IsErrObjectAlreadyRemoved(err) { // IsErrObjectAlreadyRemoved check is required because splitInfo // implicitly performs Head request that may return ObjectAlreadyRemoved // status that is not specified for Delete. From 92e19feb577242aea36639e554b3cf71fc7085d1 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 30 May 2024 09:26:06 +0300 Subject: [PATCH 0591/1413] [#1147] node: Use public fields for `shard.ExistsPrm` Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/engine/delete.go | 2 +- .../engine/engine_test.go | 5 +++- pkg/local_object_storage/engine/exists.go | 10 ++++---- pkg/local_object_storage/engine/inhume.go | 2 +- pkg/local_object_storage/engine/lock.go | 2 +- pkg/local_object_storage/engine/put.go | 7 ++++-- .../engine/remove_copies.go | 2 +- pkg/local_object_storage/shard/exists.go | 24 +++++++------------ pkg/local_object_storage/shard/reload_test.go | 2 +- 9 files changed, 26 insertions(+), 30 deletions(-) diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 44a6122133..0965289672 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -83,7 +83,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e // 2. Otherwise, search for all objects with a particular SplitID and delete them too. e.iterateOverSortedShards(prm.addr, func(_ int, sh hashedShard) (stop bool) { var existsPrm shard.ExistsPrm - existsPrm.SetAddress(prm.addr) + existsPrm.Address = prm.addr resExists, err := sh.Exists(ctx, existsPrm) if err != nil { diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 70c54590f7..49976abbb6 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -63,7 +63,10 @@ func benchmarkExists(b *testing.B, shardNum int) { b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { - ok, _, err := e.exists(context.Background(), addr, oid.Address{}) + var shPrm shard.ExistsPrm + shPrm.Address = addr + shPrm.ParentAddress = oid.Address{} + ok, _, err := e.exists(context.Background(), shPrm) if err != nil || ok { b.Fatalf("%t %v", ok, err) } diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index ce669ec5ed..c57f796912 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -8,18 +8,16 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) -func (e *StorageEngine) exists(ctx context.Context, addr oid.Address, parentAddr oid.Address) (bool, bool, error) { - var shPrm shard.ExistsPrm - shPrm.SetAddress(addr) - shPrm.SetParentAddress(parentAddr) +// exists return in the first value true if object exists. +// Second return value marks is parent object locked. +func (e *StorageEngine) exists(ctx context.Context, shPrm shard.ExistsPrm) (bool, bool, error) { alreadyRemoved := false exists := false locked := false - e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { + e.iterateOverSortedShards(shPrm.Address, func(_ int, sh hashedShard) (stop bool) { res, err := sh.Exists(ctx, shPrm) if err != nil { if client.IsErrObjectAlreadyRemoved(err) { diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 62e7be933e..991305af09 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -142,7 +142,7 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh }() if checkExists { - existPrm.SetAddress(addr) + existPrm.Address = addr exRes, err := sh.Exists(ctx, existPrm) if err != nil { if client.IsErrObjectAlreadyRemoved(err) || shard.IsErrObjectExpired(err) { diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index af56c3e1e1..5354c205f2 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -78,7 +78,7 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo if checkExists { var existsPrm shard.ExistsPrm - existsPrm.SetAddress(addrLocked) + existsPrm.Address = addrLocked exRes, err := sh.Exists(ctx, existsPrm) if err != nil { diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index aa94ef22ea..2a78febed6 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -85,7 +85,10 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { parent.SetObject(prm.obj.ECHeader().Parent()) parent.SetContainer(addr.Container()) } - existed, locked, err := e.exists(ctx, addr, parent) + var shPrm shard.ExistsPrm + shPrm.Address = addr + shPrm.ParentAddress = parent + existed, locked, err := e.exists(ctx, shPrm) if err != nil { return err } @@ -138,7 +141,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti defer close(exitCh) var existPrm shard.ExistsPrm - existPrm.SetAddress(addr) + existPrm.Address = addr exists, err := sh.Exists(ctx, existPrm) if err != nil { diff --git a/pkg/local_object_storage/engine/remove_copies.go b/pkg/local_object_storage/engine/remove_copies.go index 00562e4cbb..b99cf4f444 100644 --- a/pkg/local_object_storage/engine/remove_copies.go +++ b/pkg/local_object_storage/engine/remove_copies.go @@ -115,7 +115,7 @@ func (e *StorageEngine) removeObjects(ctx context.Context, ch <-chan oid.Address found := false for i := range shards { var existsPrm shard.ExistsPrm - existsPrm.SetAddress(addr) + existsPrm.Address = addr res, err := shards[i].Exists(ctx, existsPrm) if err != nil { diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index 12c339c057..b5a9604b46 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -13,8 +13,10 @@ import ( // ExistsPrm groups the parameters of Exists operation. type ExistsPrm struct { - addr oid.Address - paddr oid.Address + // Exists option to set object checked for existence. + Address oid.Address + // Exists option to set parent object checked for existence. + ParentAddress oid.Address } // ExistsRes groups the resulting values of Exists operation. @@ -23,16 +25,6 @@ type ExistsRes struct { lc bool } -// SetAddress is an Exists option to set object checked for existence. -func (p *ExistsPrm) SetAddress(addr oid.Address) { - p.addr = addr -} - -// SetParentAddress is an Exists option to set parent object checked for existence. -func (p *ExistsPrm) SetParentAddress(addr oid.Address) { - p.paddr = addr -} - // Exists returns the fact that the object is in the shard. func (p ExistsRes) Exists() bool { return p.ex @@ -55,7 +47,7 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.Exists", trace.WithAttributes( attribute.String("shard_id", s.ID().String()), - attribute.String("address", prm.addr.EncodeToString()), + attribute.String("address", prm.Address.EncodeToString()), )) defer span.End() @@ -70,15 +62,15 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { return ExistsRes{}, ErrShardDisabled } else if s.info.Mode.NoMetabase() { var p common.ExistsPrm - p.Address = prm.addr + p.Address = prm.Address var res common.ExistsRes res, err = s.blobStor.Exists(ctx, p) exists = res.Exists } else { var existsPrm meta.ExistsPrm - existsPrm.SetAddress(prm.addr) - existsPrm.SetParent(prm.paddr) + existsPrm.SetAddress(prm.Address) + existsPrm.SetParent(prm.ParentAddress) var res meta.ExistsRes res, err = s.metaBase.Exists(ctx, existsPrm) diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index b5ea2fec76..7dacbfa6c8 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -72,7 +72,7 @@ func TestShardReload(t *testing.T) { checkHasObjects := func(t *testing.T, exists bool) { for i := range objects { var prm ExistsPrm - prm.SetAddress(objects[i].addr) + prm.Address = objects[i].addr res, err := sh.Exists(context.Background(), prm) require.NoError(t, err) From 0b367007fc0d37d009de7cd7f90ab2964c5ab85c Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 28 May 2024 16:12:14 +0300 Subject: [PATCH 0592/1413] [#1152] go.mod: Update api-go and sdk versions * Resolve conflicts for apemanager since api-go contains ape and apemanager packages and SDK only ape package. Signed-off-by: Airat Arifullin --- .../modules/ape_manager/add_chain.go | 16 ++++----- go.mod | 4 +-- go.sum | 8 ++--- pkg/services/apemanager/executor.go | 35 ++++++++++--------- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/cmd/frostfs-cli/modules/ape_manager/add_chain.go b/cmd/frostfs-cli/modules/ape_manager/add_chain.go index dea7fb36e1..c6622da255 100644 --- a/cmd/frostfs-cli/modules/ape_manager/add_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/add_chain.go @@ -9,7 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - apemanager_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/apemanager" + apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -49,7 +49,7 @@ var addCmd = &cobra.Command{ }, } -func parseTarget(cmd *cobra.Command) (ct apemanager_sdk.ChainTarget) { +func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) { typ, _ := cmd.Flags().GetString(targetTypeFlag) name, _ := cmd.Flags().GetString(targetNameFlag) @@ -57,22 +57,22 @@ func parseTarget(cmd *cobra.Command) (ct apemanager_sdk.ChainTarget) { switch typ { case namespaceTarget: - ct.TargetType = apemanager_sdk.TargetTypeNamespace + ct.TargetType = apeSDK.TargetTypeNamespace case containerTarget: var cnr cid.ID commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name)) - ct.TargetType = apemanager_sdk.TargetTypeContainer + ct.TargetType = apeSDK.TargetTypeContainer case userTarget: - ct.TargetType = apemanager_sdk.TargetTypeUser + ct.TargetType = apeSDK.TargetTypeUser case groupTarget: - ct.TargetType = apemanager_sdk.TargetTypeGroup + ct.TargetType = apeSDK.TargetTypeGroup default: commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) } return ct } -func parseChain(cmd *cobra.Command) apemanager_sdk.Chain { +func parseChain(cmd *cobra.Command) apeSDK.Chain { chainID, _ := cmd.Flags().GetString(chainIDFlag) hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) @@ -99,7 +99,7 @@ func parseChain(cmd *cobra.Command) apemanager_sdk.Chain { util.PrintHumanReadableAPEChain(cmd, chain) serialized := chain.Bytes() - return apemanager_sdk.Chain{ + return apeSDK.Chain{ Raw: serialized, } } diff --git a/go.mod b/go.mod index 1335747aad..6edd305bb8 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,10 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240516133103-0803bc6ded00 + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240517121628-3de256d05e32 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531121442-717a7d00ef21 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index ce68ddb222..dcae21bc30 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240516133103-0803bc6ded00 h1:Q3B9WtFh05AXhUFs/2CLvhh9tuFs/Zd/XemWBbuzvg8= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240516133103-0803bc6ded00/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 h1:H5GvrVlowIMWfzqQkhY0p0myooJxQ1sMRVSFfXawwWg= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 h1:Tp4I+XOLp3VCJORfxSamQtj3RZNISbaLM4WD5iIzXxg= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240517121628-3de256d05e32 h1:ebXBsKCAINoJLhBUqi1x3fToxUHUsUjEBGKo86JQoho= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240517121628-3de256d05e32/go.mod h1:Wu1jsGM6JhZwS5oMWeslKvMcvRbg8nGt/B/TfsQPoFA= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531121442-717a7d00ef21 h1:ugo9k9s0+51BCMhD4mqHD+qD5P4BOTfDxcEMqTsM9+A= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531121442-717a7d00ef21/go.mod h1:dwBHqBoseOpU4EiIPSGxhNeQx2QOEao/1r8h26syswI= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d h1:hHk8FWbWgEnwm2I045CaBIrZBjy/o81CehIVOySA/pQ= diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go index 9cfc97473f..25f43486a1 100644 --- a/pkg/services/apemanager/executor.go +++ b/pkg/services/apemanager/executor.go @@ -8,7 +8,8 @@ import ( "errors" "fmt" - apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" + apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape" + apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" ape_contract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/contract_storage" @@ -83,13 +84,13 @@ func (s *Service) validateContainerTargetRequest(cid string, pubKey *keys.Public return nil } -func (s *Service) AddChain(_ context.Context, req *apemanager_v2.AddChainRequest) (*apemanager_v2.AddChainResponse, error) { +func (s *Service) AddChain(_ context.Context, req *apemanagerV2.AddChainRequest) (*apemanagerV2.AddChainResponse, error) { pub, err := getSignaturePublicKey(req.GetVerificationHeader()) if err != nil { return nil, err } - chain, err := decodeAndValidateChain(req.GetBody().GetChain().GetKind().(*apemanager_v2.ChainRaw).GetRaw()) + chain, err := decodeAndValidateChain(req.GetBody().GetChain().GetKind().(*apeV2.ChainRaw).GetRaw()) if err != nil { return nil, err } @@ -105,7 +106,7 @@ func (s *Service) AddChain(_ context.Context, req *apemanager_v2.AddChainRequest var target policy_engine.Target switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { - case apemanager_v2.TargetTypeContainer: + case apeV2.TargetTypeContainer: reqCID := req.GetBody().GetTarget().GetName() if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { return nil, err @@ -119,16 +120,16 @@ func (s *Service) AddChain(_ context.Context, req *apemanager_v2.AddChainRequest return nil, err } - body := new(apemanager_v2.AddChainResponseBody) + body := new(apemanagerV2.AddChainResponseBody) body.SetChainID(chain.ID) - resp := new(apemanager_v2.AddChainResponse) + resp := new(apemanagerV2.AddChainResponse) resp.SetBody(body) return resp, nil } -func (s *Service) RemoveChain(_ context.Context, req *apemanager_v2.RemoveChainRequest) (*apemanager_v2.RemoveChainResponse, error) { +func (s *Service) RemoveChain(_ context.Context, req *apemanagerV2.RemoveChainRequest) (*apemanagerV2.RemoveChainResponse, error) { pub, err := getSignaturePublicKey(req.GetVerificationHeader()) if err != nil { return nil, err @@ -137,7 +138,7 @@ func (s *Service) RemoveChain(_ context.Context, req *apemanager_v2.RemoveChainR var target policy_engine.Target switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { - case apemanager_v2.TargetTypeContainer: + case apeV2.TargetTypeContainer: reqCID := req.GetBody().GetTarget().GetName() if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { return nil, err @@ -151,15 +152,15 @@ func (s *Service) RemoveChain(_ context.Context, req *apemanager_v2.RemoveChainR return nil, err } - body := new(apemanager_v2.RemoveChainResponseBody) + body := new(apemanagerV2.RemoveChainResponseBody) - resp := new(apemanager_v2.RemoveChainResponse) + resp := new(apemanagerV2.RemoveChainResponse) resp.SetBody(body) return resp, nil } -func (s *Service) ListChains(_ context.Context, req *apemanager_v2.ListChainsRequest) (*apemanager_v2.ListChainsResponse, error) { +func (s *Service) ListChains(_ context.Context, req *apemanagerV2.ListChainsRequest) (*apemanagerV2.ListChainsResponse, error) { pub, err := getSignaturePublicKey(req.GetVerificationHeader()) if err != nil { return nil, err @@ -168,7 +169,7 @@ func (s *Service) ListChains(_ context.Context, req *apemanager_v2.ListChainsReq var target policy_engine.Target switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { - case apemanager_v2.TargetTypeContainer: + case apeV2.TargetTypeContainer: reqCID := req.GetBody().GetTarget().GetName() if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { return nil, err @@ -183,21 +184,21 @@ func (s *Service) ListChains(_ context.Context, req *apemanager_v2.ListChainsReq return nil, err } - res := make([]*apemanager_v2.Chain, 0, len(chs)) + res := make([]*apeV2.Chain, 0, len(chs)) for _, ch := range chs { - v2chraw := new(apemanager_v2.ChainRaw) + v2chraw := new(apeV2.ChainRaw) v2chraw.SetRaw(ch.Bytes()) - v2ch := new(apemanager_v2.Chain) + v2ch := new(apeV2.Chain) v2ch.SetKind(v2chraw) res = append(res, v2ch) } - body := new(apemanager_v2.ListChainsResponseBody) + body := new(apemanagerV2.ListChainsResponseBody) body.SetChains(res) - resp := new(apemanager_v2.ListChainsResponse) + resp := new(apemanagerV2.ListChainsResponse) resp.SetBody(body) return resp, nil From f0edebea1820d96b9219917d34c7649f31db3782 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 21 May 2024 14:19:22 +0300 Subject: [PATCH 0593/1413] [#1144] metabase: Support ec parent filter for `Search` Signed-off-by: Airat Arifullin --- pkg/local_object_storage/metabase/db.go | 2 +- pkg/local_object_storage/metabase/put.go | 11 +++++++++++ pkg/local_object_storage/metabase/select.go | 3 +++ pkg/local_object_storage/metabase/util.go | 11 +++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/db.go b/pkg/local_object_storage/metabase/db.go index f5341ff2ea..f2203f4d9e 100644 --- a/pkg/local_object_storage/metabase/db.go +++ b/pkg/local_object_storage/metabase/db.go @@ -262,7 +262,7 @@ func unknownMatcherBucket(_ *bbolt.Bucket, _ string, _ string, _ func([]byte, [] // in boltDB. Useful for getting filter values from unique and list indexes. func bucketKeyHelper(hdr string, val string) []byte { switch hdr { - case v2object.FilterHeaderParent: + case v2object.FilterHeaderParent, v2object.FilterHeaderECParent: v, err := base58.Decode(val) if err != nil { return nil diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 94e68d85af..bb5976ec41 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -323,6 +323,17 @@ func updateListIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun } } + if ech := obj.ECHeader(); ech != nil { + err := f(tx, namedBucketItem{ + name: ecParentToChunksBucketName(cnr, bucketName), + key: objectKey(ech.Parent(), make([]byte, objectKeySize)), + val: objKey, + }) + if err != nil { + return err + } + } + return nil } diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 65d0111c46..f544f95e24 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -211,6 +211,9 @@ func (db *DB) selectFastFilter( case v2object.FilterHeaderSplitID: bucketName := splitBucketName(cnr, bucketName) db.selectFromList(tx, bucketName, f, to, fNum) + case v2object.FilterHeaderECParent: + bucketName := ecParentToChunksBucketName(cnr, bucketName) + db.selectFromList(tx, bucketName, f, to, fNum) case v2object.FilterPropertyRoot: selectAllFromBucket(tx, rootBucketName(cnr, bucketName), to, fNum) case v2object.FilterPropertyPhy: diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index 9249ae49b4..cfccff394e 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -124,6 +124,12 @@ const ( // Key: container ID + type // Value: Object id ecInfoPrefix + + // ecParentToChunksPrefix is used to store a relation between EC parent ID and chunks, + // but unlike for ecInfoPrefix the list of chunk IDs is encoded with encodeList. + // Key: EC parent ID + // Value: list of EC chunk IDs + ecParentToChunksPrefix ) const ( @@ -200,6 +206,11 @@ func ecInfoBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, ecInfoPrefix, key) } +// ecParentToChunksBucketName returns _ecParentToChunks. +func ecParentToChunksBucketName(cnr cid.ID, key []byte) []byte { + return bucketName(cnr, ecParentToChunksPrefix, key) +} + // addressKey returns key for K-V tables when key is a whole address. func addressKey(addr oid.Address, key []byte) []byte { addr.Container().Encode(key) From f8e33f8e3ad90ff01d85c33cbeb21a5c9a7dfa16 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 21 May 2024 14:25:15 +0300 Subject: [PATCH 0594/1413] [#1144] metabase: Proprely choose root OID for EC-splitted objects * If EC-parent is a part of Split itself, then save to root bucket its parent; * If EC-parent is not a part of Split itself, then save to root bucket OID of this EC-parent. Signed-off-by: Airat Arifullin --- pkg/local_object_storage/metabase/put.go | 39 ++++++++++++++++++------ 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index bb5976ec41..8a08adc36f 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -257,17 +257,19 @@ func putUniqueIndexes( } } - err = putUniqueIndexItem(tx, namedBucketItem{ - name: rootBucketName(cnr, bucketName), - key: objKey, - val: splitInfo, - }) - if err != nil { - return err - } - + isObjKeySet := true if ecHead := obj.ECHeader(); ecHead != nil { - err = putECInfo(tx, cnr, objKey, ecHead) + if err = putECInfo(tx, cnr, objKey, ecHead); err != nil { + return err + } + objKey, isObjKeySet = objectKeyByECHeader(ecHead) + } + if isObjKeySet { + err = putUniqueIndexItem(tx, namedBucketItem{ + name: rootBucketName(cnr, bucketName), + key: objKey, + val: splitInfo, + }) if err != nil { return err } @@ -277,6 +279,23 @@ func putUniqueIndexes( return nil } +// objectKeyByECHeader returns objectKey for an object that has EC Header. +// If object's parent is in Split, then parent's non-nil Split parent ID is set to object key. +// If object's parent is not in Split, then its ID is set to object key. +// Otherwise, such object keys should be ignored -- they are not put to the root bucket. +func objectKeyByECHeader(ech *objectSDK.ECHeader) (objKey []byte, isSet bool) { + if ech.ParentSplitID() != nil { + if parentSplitParentID := ech.ParentSplitParentID(); parentSplitParentID != nil { + isSet = true + objKey = objectKey(*parentSplitParentID, make([]byte, objectKeySize)) + } + return + } + isSet = true + objKey = objectKey(ech.Parent(), make([]byte, objectKeySize)) + return +} + type updateIndexItemFunc = func(tx *bbolt.Tx, item namedBucketItem) error func updateListIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFunc) error { From 5aacb8fc86210ee6a7da02ba15a9edc4a250f269 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 27 May 2024 15:52:08 +0300 Subject: [PATCH 0595/1413] [#1144] metabase: Save parent attributes for ec-chunks Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- pkg/local_object_storage/metabase/put.go | 10 ++++++++-- pkg/services/policer/ec_test.go | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 6edd305bb8..0935609538 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531121442-717a7d00ef21 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index dcae21bc30..6f5034f007 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531121442-717a7d00ef21 h1:ugo9k9s0+51BCMhD4mqHD+qD5P4BOTfDxcEMqTsM9+A= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531121442-717a7d00ef21/go.mod h1:dwBHqBoseOpU4EiIPSGxhNeQx2QOEao/1r8h26syswI= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f h1:vBLC1OSGMSn7lRJv/p1of0veifuBdZdztVrF9Vn+UFk= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f/go.mod h1:4AObM67VUqkXQJlODTFThFnuMGEuK8h9DrAXHDZqvCU= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d h1:hHk8FWbWgEnwm2I045CaBIrZBjy/o81CehIVOySA/pQ= diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 8a08adc36f..966db94015 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -361,8 +361,6 @@ func updateFKBTIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun cnr, _ := obj.ContainerID() objKey := objectKey(id, make([]byte, objectKeySize)) - attrs := obj.Attributes() - key := make([]byte, bucketKeySize) err := f(tx, namedBucketItem{ name: ownerBucketName(cnr, key), @@ -373,6 +371,14 @@ func updateFKBTIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun return err } + var attrs []objectSDK.Attribute + if obj.ECHeader() != nil { + attrs = obj.ECHeader().ParentAttributes() + objKey = objectKey(obj.ECHeader().Parent(), make([]byte, objectKeySize)) + } else { + attrs = obj.Attributes() + } + // user specified attributes for i := range attrs { key = attributeBucketName(cnr, attrs[i].Key(), key) diff --git a/pkg/services/policer/ec_test.go b/pkg/services/policer/ec_test.go index 11e7a8cdfc..9492787dca 100644 --- a/pkg/services/policer/ec_test.go +++ b/pkg/services/policer/ec_test.go @@ -114,7 +114,7 @@ func TestECChunkHasInvalidPlacement(t *testing.T) { chunkObject.SetID(chunkAddress.Object()) chunkObject.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) chunkObject.SetPayloadSize(uint64(10)) - chunkObject.SetECHeader(objectSDK.NewECHeader(parentID, nil, nil, 1, 3, []byte{}, 0)) + chunkObject.SetECHeader(objectSDK.NewECHeader(objectSDK.ECParentInfo{ID: parentID}, 0, 3, []byte{}, 0)) var policy netmapSDK.PlacementPolicy require.NoError(t, policy.DecodeString("EC 2.1")) From f2d2908745a5fc55593e853faabca989b9896495 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 31 May 2024 21:58:09 +0300 Subject: [PATCH 0596/1413] Release v0.40.0 Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 14 ++++++++++++++ VERSION | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53e2c0bc76..0382d0316f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,20 @@ Changelog for FrostFS Node ### Removed ### Updated +## [v0.40.0] + +### Added +- Support EC chunk reconstruction in policer (#1129) +- Support LOCK, DELETE and SEARCH methods on EC objects (#1147, 1144) +- apemanager service to manage APE chains (#1105) + +### Fixed +- Properly verify GetRangeHash response (#1083) +- Send `MONOTONIC_USEC` in sdnotify on reload (#1135) + +### Updated +- neo-go to `v0.106.0` + ## [v0.39.0] ### Added diff --git a/VERSION b/VERSION index 2302e306cd..707d5fac27 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.39.0 +v0.40.0 From 643480d6fa2585035457e647dcf840f2f34167e5 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 3 Jun 2024 13:54:59 +0300 Subject: [PATCH 0597/1413] [#1146] adm: Make --group-name flag required Signed-off-by: Alexander Chuprov --- cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index d2e45696e9..541282967b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -194,6 +194,7 @@ func initFrostfsIDCreateGroupCmd() { frostfsidCreateGroupCmd.Flags().String(namespaceFlag, "", "Namespace where create group") frostfsidCreateGroupCmd.Flags().String(groupNameFlag, "", "Group name, must be unique in namespace") frostfsidCreateGroupCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + _ = frostfsidCreateGroupCmd.MarkFlagRequired(groupNameFlag) } func initFrostfsIDDeleteGroupCmd() { From cc2449beafb6407e48524a2f2cbece90f331d9c4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 4 Jun 2024 13:30:30 +0300 Subject: [PATCH 0598/1413] [#1158] metabase: Fix EC storage schema Do not store EC info twice. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete.go | 40 --------------------- pkg/local_object_storage/metabase/get.go | 9 ++--- pkg/local_object_storage/metabase/put.go | 37 +------------------ pkg/local_object_storage/metabase/select.go | 2 +- pkg/local_object_storage/metabase/util.go | 11 ------ 5 files changed, 7 insertions(+), 92 deletions(-) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 4addeae770..21b98fca17 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -473,46 +473,6 @@ func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error name: rootBucketName(cnr, bucketName), key: objKey, }) - if obj.ECHeader() != nil { - err := delECInfo(tx, cnr, objKey, obj.ECHeader()) - if err != nil { - return err - } - } return nil } - -func delECInfo(tx *bbolt.Tx, cnr cid.ID, objKey []byte, ecHead *objectSDK.ECHeader) error { - parentID := objectKey(ecHead.Parent(), make([]byte, objectKeySize)) - bucketName := make([]byte, bucketKeySize) - - val := getFromBucket(tx, ecInfoBucketName(cnr, bucketName), parentID) - if len(val) > 0 { - if bytes.Equal(val, objKey) { - delUniqueIndexItem(tx, namedBucketItem{ - name: ecInfoBucketName(cnr, bucketName), - key: parentID, - }) - } else { - val = bytes.Clone(val) - offset := 0 - for offset < len(val) { - if bytes.Equal(objKey, val[offset:offset+objectKeySize]) { - val = append(val[:offset], val[offset+objectKeySize:]...) - break - } - offset += objectKeySize - } - err := putUniqueIndexItem(tx, namedBucketItem{ - name: ecInfoBucketName(cnr, make([]byte, bucketKeySize)), - key: parentID, - val: val, - }) - if err != nil { - return err - } - } - } - return nil -} diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index 355f629330..d9acd4ce2a 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -192,10 +192,12 @@ func getSplitInfoError(tx *bbolt.Tx, cnr cid.ID, key []byte) error { } func getECInfoError(tx *bbolt.Tx, cnr cid.ID, data []byte) error { - offset := 0 + keys, err := decodeList(data) + if err != nil { + return err + } ecInfo := objectSDK.NewECInfo() - for offset < len(data) { - key := data[offset : offset+objectKeySize] + for _, key := range keys { // check in primary index ojbData := getFromBucket(tx, primaryBucketName(cnr, make([]byte, bucketKeySize)), key) if len(ojbData) != 0 { @@ -210,7 +212,6 @@ func getECInfoError(tx *bbolt.Tx, cnr cid.ID, data []byte) error { chunk.Total = obj.ECHeader().Total() ecInfo.AddChunk(chunk) } - offset += objectKeySize } return logicerr.Wrap(objectSDK.NewECInfoError(ecInfo)) } diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 966db94015..4b6359ebf2 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -1,7 +1,6 @@ package meta import ( - "bytes" "context" "encoding/binary" "errors" @@ -259,9 +258,6 @@ func putUniqueIndexes( isObjKeySet := true if ecHead := obj.ECHeader(); ecHead != nil { - if err = putECInfo(tx, cnr, objKey, ecHead); err != nil { - return err - } objKey, isObjKeySet = objectKeyByECHeader(ecHead) } if isObjKeySet { @@ -344,7 +340,7 @@ func updateListIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun if ech := obj.ECHeader(); ech != nil { err := f(tx, namedBucketItem{ - name: ecParentToChunksBucketName(cnr, bucketName), + name: ecInfoBucketName(cnr, bucketName), key: objectKey(ech.Parent(), make([]byte, objectKeySize)), val: objKey, }) @@ -615,34 +611,3 @@ func isLinkObject(obj *objectSDK.Object) bool { func isLastObject(obj *objectSDK.Object) bool { return len(obj.Children()) == 0 && obj.Parent() != nil } - -func putECInfo(tx *bbolt.Tx, - cnr cid.ID, objKey []byte, - ecHead *objectSDK.ECHeader, -) error { - parentID := objectKey(ecHead.Parent(), make([]byte, objectKeySize)) - bucketName := make([]byte, bucketKeySize) - - val := getFromBucket(tx, ecInfoBucketName(cnr, bucketName), parentID) - if len(val) == 0 { - val = objKey - } else { - offset := 0 - found := false - for offset < len(val) { - if bytes.Equal(objKey, val[offset:offset+objectKeySize]) { - found = true - break - } - offset += objectKeySize - } - if !found { - val = append(val, objKey...) - } - } - return putUniqueIndexItem(tx, namedBucketItem{ - name: ecInfoBucketName(cnr, make([]byte, bucketKeySize)), - key: parentID, - val: val, - }) -} diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index f544f95e24..3a4d7a2273 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -212,7 +212,7 @@ func (db *DB) selectFastFilter( bucketName := splitBucketName(cnr, bucketName) db.selectFromList(tx, bucketName, f, to, fNum) case v2object.FilterHeaderECParent: - bucketName := ecParentToChunksBucketName(cnr, bucketName) + bucketName := ecInfoBucketName(cnr, bucketName) db.selectFromList(tx, bucketName, f, to, fNum) case v2object.FilterPropertyRoot: selectAllFromBucket(tx, rootBucketName(cnr, bucketName), to, fNum) diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index cfccff394e..9249ae49b4 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -124,12 +124,6 @@ const ( // Key: container ID + type // Value: Object id ecInfoPrefix - - // ecParentToChunksPrefix is used to store a relation between EC parent ID and chunks, - // but unlike for ecInfoPrefix the list of chunk IDs is encoded with encodeList. - // Key: EC parent ID - // Value: list of EC chunk IDs - ecParentToChunksPrefix ) const ( @@ -206,11 +200,6 @@ func ecInfoBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, ecInfoPrefix, key) } -// ecParentToChunksBucketName returns _ecParentToChunks. -func ecParentToChunksBucketName(cnr cid.ID, key []byte) []byte { - return bucketName(cnr, ecParentToChunksPrefix, key) -} - // addressKey returns key for K-V tables when key is a whole address. func addressKey(addr oid.Address, key []byte) []byte { addr.Container().Encode(key) From 6f2187a420e9c9c7bd2e1fa978a24720224efbd2 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 14 May 2024 14:44:55 +0300 Subject: [PATCH 0599/1413] [#1121] node: Refactor mods of shard Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/shard/mode/mode.go | 28 ++++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/pkg/local_object_storage/shard/mode/mode.go b/pkg/local_object_storage/shard/mode/mode.go index 49c888d631..461611465a 100644 --- a/pkg/local_object_storage/shard/mode/mode.go +++ b/pkg/local_object_storage/shard/mode/mode.go @@ -8,27 +8,25 @@ type Mode uint32 const ( // ReadWrite is a Mode value for shard that is available // for read and write operations. Default shard mode. - ReadWrite Mode = 0 + ReadWrite Mode = 0b000 - // DegradedReadOnly is a Mode value for shard that is set automatically - // after a certain number of errors is encountered. It is the same as - // `mode.Degraded` but also is read-only. - DegradedReadOnly = Degraded | ReadOnly + // ReadOnly is a Mode value for shard that does not + // accept write operation but is readable. + ReadOnly Mode = 0b001 + + // Degraded is a Mode value for shard when the metabase is unavailable. + // It is hard to perform some modifying operations in this mode, thus it can only be set by an administrator. + Degraded Mode = 0b010 // Disabled mode is a mode where a shard is disabled. // An existing shard can't have this mode, but it can be used in // the configuration or control service commands. - Disabled = math.MaxUint32 -) + Disabled Mode = math.MaxUint32 -const ( - // ReadOnly is a Mode value for shard that does not - // accept write operation but is readable. - ReadOnly Mode = 1 << iota - - // Degraded is a Mode value for shard when the metabase is unavailable. - // It is hard to perform some modifying operations in this mode, thus it can only be set by an administrator. - Degraded + // DegradedReadOnly is a Mode value for shard that is set automatically + // after a certain number of errors is encountered. It is the same as + // `mode.Degraded` but also is read-only. + DegradedReadOnly Mode = Degraded | ReadOnly ) func (m Mode) String() string { From 806236da781d2c1cfd74faee2ff0da62ffd43485 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 4 Jun 2024 16:28:47 +0300 Subject: [PATCH 0600/1413] [#1121] node: Change mode of shard components Signed-off-by: Alexander Chuprov --- .../blobovniczatree/concurrency_test.go | 3 +- .../blobstor/blobovniczatree/control.go | 7 ++- .../blobstor/blobovniczatree/control_test.go | 9 +-- .../blobstor/blobovniczatree/exists_test.go | 3 +- .../blobstor/blobovniczatree/iterate_test.go | 3 +- .../blobstor/blobovniczatree/metrics.go | 5 +- .../blobovniczatree/rebuild_failover_test.go | 3 +- .../blobstor/blobovniczatree/rebuild_test.go | 9 +-- .../blobstor/common/storage.go | 3 +- pkg/local_object_storage/blobstor/control.go | 5 +- .../blobstor/fstree/control.go | 7 ++- .../blobstor/fstree/fstree_test.go | 3 +- .../blobstor/fstree/metrics.go | 10 ++- .../blobstor/internal/blobstortest/control.go | 5 +- .../blobstor/internal/blobstortest/delete.go | 3 +- .../blobstor/internal/blobstortest/exists.go | 3 +- .../blobstor/internal/blobstortest/get.go | 3 +- .../internal/blobstortest/get_range.go | 3 +- .../blobstor/internal/blobstortest/iterate.go | 3 +- .../blobstor/memstore/control.go | 9 ++- .../blobstor/memstore/memstore_test.go | 3 +- .../blobstor/perf_test.go | 3 +- .../blobstor/teststore/option.go | 9 +-- .../blobstor/teststore/teststore.go | 9 +-- .../engine/control_test.go | 2 +- pkg/local_object_storage/engine/writecache.go | 4 +- pkg/local_object_storage/metabase/control.go | 16 ++--- pkg/local_object_storage/metabase/metrics.go | 4 +- pkg/local_object_storage/metabase/mode.go | 2 +- pkg/local_object_storage/metabase/shard_id.go | 2 +- .../metrics/blobovnicza.go | 5 +- pkg/local_object_storage/metrics/fstree.go | 5 +- pkg/local_object_storage/metrics/metabase.go | 2 +- pkg/local_object_storage/metrics/pilorama.go | 4 +- pkg/local_object_storage/pilorama/boltdb.go | 8 +-- pkg/local_object_storage/pilorama/metrics.go | 4 +- pkg/local_object_storage/shard/control.go | 2 +- pkg/local_object_storage/shard/mode/mode.go | 62 +++++++++++++++++++ .../writecache/cachebbolt.go | 10 +-- pkg/local_object_storage/writecache/flush.go | 2 +- .../writecache/metrics.go | 4 +- pkg/local_object_storage/writecache/mode.go | 4 +- pkg/local_object_storage/writecache/seal.go | 2 +- .../writecache/storage.go | 9 +-- pkg/metrics/blobovnicza.go | 7 ++- pkg/metrics/fstree.go | 7 ++- pkg/metrics/pilorama.go | 4 +- 47 files changed, 194 insertions(+), 100 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go index 97606df021..5bed861421 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "github.com/stretchr/testify/require" ) @@ -23,7 +24,7 @@ func TestBlobovniczaTree_Concurrency(t *testing.T) { WithBlobovniczaShallowWidth(10), WithBlobovniczaShallowDepth(1), WithRootPath(t.TempDir())) - require.NoError(t, st.Open(false)) + require.NoError(t, st.Open(mode.ComponentReadWrite)) require.NoError(t, st.Init()) defer func() { require.NoError(t, st.Close()) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index bd98967cbb..67e8c8f18d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -8,6 +8,7 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "go.uber.org/zap" "golang.org/x/sync/errgroup" @@ -16,9 +17,9 @@ import ( var errFailedToChangeExtensionReadOnly = errors.New("failed to change blobovnicza extension: read only mode") // Open opens blobovnicza tree. -func (b *Blobovniczas) Open(readOnly bool) error { - b.readOnly = readOnly - b.metrics.SetMode(readOnly) +func (b *Blobovniczas) Open(mode mode.ComponentMode) error { + b.readOnly = mode.ReadOnly() + b.metrics.SetMode(mode) b.metrics.SetRebuildStatus(rebuildStatusNotStarted) b.openManagers() return nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go index 0356fbaaeb..7218cd6bba 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" ) @@ -54,7 +55,7 @@ func openAndCloseTestTree(t *testing.T, depth, width uint64, path string) { WithBlobovniczaShallowWidth(width), WithRootPath(path), ) - require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Open(mode.ComponentReadWrite)) require.NoError(t, blz.Init()) require.NoError(t, blz.Close()) } @@ -85,7 +86,7 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { WithRootPath(rootDir), ) - require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Open(mode.ComponentReadWrite)) require.NoError(t, blz.Init()) obj35 := blobstortest.NewObject(10 * 1024) @@ -123,7 +124,7 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { WithRootPath(rootDir), ) - require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Open(mode.ComponentReadWrite)) require.NoError(t, blz.Init()) gRes, err = blz.Get(context.Background(), common.GetPrm{ @@ -160,7 +161,7 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { WithBlobovniczaShallowWidth(5), WithRootPath(rootDir), ) - require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Open(mode.ComponentReadWrite)) require.NoError(t, blz.Init()) gRes, err = blz.Get(context.Background(), common.GetPrm{ diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index 625e620b8e..d6ffd8bcee 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "github.com/stretchr/testify/require" ) @@ -24,7 +25,7 @@ func TestExistsInvalidStorageID(t *testing.T) { WithBlobovniczaShallowDepth(2), WithRootPath(dir), WithBlobovniczaSize(1<<20)) - require.NoError(t, b.Open(false)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) require.NoError(t, b.Init()) defer func() { require.NoError(t, b.Close()) }() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go index 506dd9a4be..b067a164b0 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) @@ -18,7 +19,7 @@ func TestIterateSortedLeavesAndDBPathsAreSame(t *testing.T) { WithRootPath(t.TempDir()), ) blz.createDBInAdvance = true - require.NoError(t, blz.Open(false)) + require.NoError(t, blz.Open(mode.ComponentReadWrite)) require.NoError(t, blz.Init()) defer func() { require.NoError(t, blz.Close()) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go b/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go index 28289c19e5..68dc7ff381 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/metrics.go @@ -4,6 +4,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" ) const ( @@ -18,7 +19,7 @@ type Metrics interface { SetParentID(parentID string) - SetMode(readOnly bool) + SetMode(mode.ComponentMode) Close() SetRebuildStatus(status string) @@ -37,7 +38,7 @@ type Metrics interface { type noopMetrics struct{} func (m *noopMetrics) SetParentID(string) {} -func (m *noopMetrics) SetMode(bool) {} +func (m *noopMetrics) SetMode(mode.ComponentMode) {} func (m *noopMetrics) Close() {} func (m *noopMetrics) SetRebuildStatus(string) {} func (m *noopMetrics) SetRebuildPercent(uint32) {} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index 31dadb533a..a6afed60c6 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -138,7 +139,7 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object WithBlobovniczaSize(100*1024*1024), WithWaitBeforeDropDB(0), WithOpenedCacheSize(1000)) - require.NoError(t, b.Open(false)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) require.NoError(t, b.Init()) var dPrm common.DeletePrm diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 6b8ae4b5cc..7a1de4c130 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" @@ -53,7 +54,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { WithWaitBeforeDropDB(0), WithOpenedCacheSize(1000), WithMoveBatchSize(3)) - require.NoError(t, b.Open(false)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) require.NoError(t, b.Init()) obj := blobstortest.NewObject(64 * 1024) // 64KB object @@ -81,7 +82,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { WithWaitBeforeDropDB(0), WithOpenedCacheSize(1000), WithMoveBatchSize(3)) - require.NoError(t, b.Open(false)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) require.NoError(t, b.Init()) metaStub := &storageIDUpdateStub{ @@ -120,7 +121,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta WithWaitBeforeDropDB(0), WithOpenedCacheSize(1000), WithMoveBatchSize(3)) - require.NoError(t, b.Open(false)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) require.NoError(t, b.Init()) eg, egCtx := errgroup.WithContext(context.Background()) @@ -161,7 +162,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta WithWaitBeforeDropDB(0), WithOpenedCacheSize(1000), WithMoveBatchSize(50)) - require.NoError(t, b.Open(false)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) require.NoError(t, b.Init()) for addr, storageID := range storageIDs { diff --git a/pkg/local_object_storage/blobstor/common/storage.go b/pkg/local_object_storage/blobstor/common/storage.go index 8f629b1de6..4f3a209937 100644 --- a/pkg/local_object_storage/blobstor/common/storage.go +++ b/pkg/local_object_storage/blobstor/common/storage.go @@ -4,12 +4,13 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" ) // Storage represents key-value object storage. // It is used as a building block for a blobstor of a shard. type Storage interface { - Open(readOnly bool) error + Open(mode mode.ComponentMode) error Init() error Close() error diff --git a/pkg/local_object_storage/blobstor/control.go b/pkg/local_object_storage/blobstor/control.go index 45b0c3f10b..9b414a9be7 100644 --- a/pkg/local_object_storage/blobstor/control.go +++ b/pkg/local_object_storage/blobstor/control.go @@ -27,15 +27,14 @@ func (b *BlobStor) Open(ctx context.Context, mode mode.Mode) error { return nil } -func (b *BlobStor) openBlobStor(ctx context.Context, mode mode.Mode) error { - readOnly := mode.ReadOnly() +func (b *BlobStor) openBlobStor(ctx context.Context, mod mode.Mode) error { for i := range b.storage { select { case <-ctx.Done(): return ctx.Err() default: } - err := b.storage[i].Storage.Open(readOnly) + err := b.storage[i].Storage.Open(mode.ConvertToComponentMode(mod)) if err != nil { return err } diff --git a/pkg/local_object_storage/blobstor/fstree/control.go b/pkg/local_object_storage/blobstor/fstree/control.go index cec531f2e8..c21d79f09c 100644 --- a/pkg/local_object_storage/blobstor/fstree/control.go +++ b/pkg/local_object_storage/blobstor/fstree/control.go @@ -1,13 +1,14 @@ package fstree import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" ) // Open implements common.Storage. -func (t *FSTree) Open(ro bool) error { - t.readOnly = ro - t.metrics.SetMode(ro) +func (t *FSTree) Open(mode mode.ComponentMode) error { + t.readOnly = mode.ReadOnly() + t.metrics.SetMode(mode) return nil } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_test.go b/pkg/local_object_storage/blobstor/fstree/fstree_test.go index b81ce43f18..d633cbac36 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_test.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_test.go @@ -6,6 +6,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -43,7 +44,7 @@ func TestObjectCounter(t *testing.T) { WithDepth(2), WithDirNameLen(2), WithFileCounter(counter)) - require.NoError(t, fst.Open(false)) + require.NoError(t, fst.Open(mode.ComponentReadWrite)) require.NoError(t, fst.Init()) counterValue := counter.Value() diff --git a/pkg/local_object_storage/blobstor/fstree/metrics.go b/pkg/local_object_storage/blobstor/fstree/metrics.go index eeb6866726..10de935eb1 100644 --- a/pkg/local_object_storage/blobstor/fstree/metrics.go +++ b/pkg/local_object_storage/blobstor/fstree/metrics.go @@ -1,11 +1,15 @@ package fstree -import "time" +import ( + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" +) type Metrics interface { SetParentID(parentID string) - SetMode(readOnly bool) + SetMode(mode mode.ComponentMode) Close() Iterate(d time.Duration, success bool) @@ -20,7 +24,7 @@ type Metrics interface { type noopMetrics struct{} func (m *noopMetrics) SetParentID(string) {} -func (m *noopMetrics) SetMode(bool) {} +func (m *noopMetrics) SetMode(mode.ComponentMode) {} func (m *noopMetrics) Close() {} func (m *noopMetrics) Iterate(time.Duration, bool) {} func (m *noopMetrics) Delete(time.Duration, bool) {} diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/control.go b/pkg/local_object_storage/blobstor/internal/blobstortest/control.go index 96d54dec37..a3bbc021d9 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/control.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/control.go @@ -7,6 +7,7 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" ) @@ -14,13 +15,13 @@ import ( // cons must return a storage which is NOT opened. func TestControl(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) objects := prepare(t, 10, s, min, max) require.NoError(t, s.Close()) - require.NoError(t, s.Open(true)) + require.NoError(t, s.Open(mode.ComponentReadOnly)) for i := range objects { var prm common.GetPrm prm.Address = objects[i].addr diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go index f551cbf5f6..750619a30a 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go @@ -5,6 +5,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" @@ -12,7 +13,7 @@ import ( func TestDelete(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go index 29d8bafee7..33b50b12fd 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go @@ -5,13 +5,14 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) func TestExists(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go index 65c0c31337..12f73c3e9a 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go @@ -5,6 +5,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" @@ -12,7 +13,7 @@ import ( func TestGet(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go index 9b99c12d5e..93de683c21 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go @@ -6,6 +6,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -14,7 +15,7 @@ import ( func TestGetRange(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index 45c68cebca..e66fe87b6b 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -6,12 +6,13 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" ) func TestIterate(t *testing.T, cons Constructor, min, max uint64) { s := cons(t) - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() diff --git a/pkg/local_object_storage/blobstor/memstore/control.go b/pkg/local_object_storage/blobstor/memstore/control.go index 7f6e85a16d..449d4352ae 100644 --- a/pkg/local_object_storage/blobstor/memstore/control.go +++ b/pkg/local_object_storage/blobstor/memstore/control.go @@ -1,9 +1,12 @@ package memstore -import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" +) -func (s *memstoreImpl) Open(readOnly bool) error { - s.readOnly = readOnly +func (s *memstoreImpl) Open(mod mode.ComponentMode) error { + s.readOnly = mod.ReadOnly() return nil } diff --git a/pkg/local_object_storage/blobstor/memstore/memstore_test.go b/pkg/local_object_storage/blobstor/memstore/memstore_test.go index bc9436350e..8d1480dff4 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore_test.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore_test.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" @@ -18,7 +19,7 @@ func TestSimpleLifecycle(t *testing.T) { WithLogger(test.NewLogger(t)), ) defer func() { require.NoError(t, s.Close()) }() - require.NoError(t, s.Open(false)) + require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) obj := blobstortest.NewObject(1024) diff --git a/pkg/local_object_storage/blobstor/perf_test.go b/pkg/local_object_storage/blobstor/perf_test.go index fb5afb88b3..501c95a1dc 100644 --- a/pkg/local_object_storage/blobstor/perf_test.go +++ b/pkg/local_object_storage/blobstor/perf_test.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/memstore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) @@ -22,7 +23,7 @@ type storage struct { func (s storage) open(b *testing.B) common.Storage { st := s.create(b.TempDir()) - require.NoError(b, st.Open(false)) + require.NoError(b, st.Open(mode.ComponentReadWrite)) require.NoError(b, st.Init()) return st diff --git a/pkg/local_object_storage/blobstor/teststore/option.go b/pkg/local_object_storage/blobstor/teststore/option.go index b897832cfd..bc0bed49d6 100644 --- a/pkg/local_object_storage/blobstor/teststore/option.go +++ b/pkg/local_object_storage/blobstor/teststore/option.go @@ -3,12 +3,13 @@ package teststore import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" ) type cfg struct { st common.Storage overrides struct { - Open func(readOnly bool) error + Open func(mode mode.ComponentMode) error Init func() error Close func() error @@ -35,9 +36,9 @@ func WithSubstorage(st common.Storage) Option { } } -func WithOpen(f func(bool) error) Option { return func(c *cfg) { c.overrides.Open = f } } -func WithInit(f func() error) Option { return func(c *cfg) { c.overrides.Init = f } } -func WithClose(f func() error) Option { return func(c *cfg) { c.overrides.Close = f } } +func WithOpen(f func(mode.ComponentMode) error) Option { return func(c *cfg) { c.overrides.Open = f } } +func WithInit(f func() error) Option { return func(c *cfg) { c.overrides.Init = f } } +func WithClose(f func() error) Option { return func(c *cfg) { c.overrides.Close = f } } func WithType(f func() string) Option { return func(c *cfg) { c.overrides.Type = f } } func WithPath(f func() string) Option { return func(c *cfg) { c.overrides.Path = f } } diff --git a/pkg/local_object_storage/blobstor/teststore/teststore.go b/pkg/local_object_storage/blobstor/teststore/teststore.go index 016fd520fb..fea4a2d49b 100644 --- a/pkg/local_object_storage/blobstor/teststore/teststore.go +++ b/pkg/local_object_storage/blobstor/teststore/teststore.go @@ -20,6 +20,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" ) // TestStore is a common.Storage implementation for testing/mocking purposes. @@ -50,16 +51,16 @@ func (s *TestStore) SetOption(opt Option) { opt(s.cfg) } -func (s *TestStore) Open(readOnly bool) error { +func (s *TestStore) Open(mod mode.ComponentMode) error { s.mu.RLock() defer s.mu.RUnlock() switch { case s.overrides.Open != nil: - return s.overrides.Open(readOnly) + return s.overrides.Open(mod) case s.st != nil: - return s.st.Open(readOnly) + return s.st.Open(mod) default: - panic(fmt.Sprintf("unexpected storage call: Open(%v)", readOnly)) + panic(fmt.Sprintf("unexpected storage call: Open(%v)", mod.String())) } } diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 6bf6beac6f..f0809883c8 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -74,7 +74,7 @@ func TestInitializationFailure(t *testing.T) { openFileMetabase: os.OpenFile, openFilePilorama: os.OpenFile, }) - largeFileStorage.SetOption(teststore.WithOpen(func(ro bool) error { + largeFileStorage.SetOption(teststore.WithOpen(func(primitiveMode mode.ComponentMode) error { return teststore.ErrDiskExploded })) beforeReload := func() { diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 670cfcbf59..0235767163 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -171,8 +171,8 @@ func (m *writeCacheMetrics) SetEstimateSize(db, fstree uint64) { m.metrics.SetEstimateSize(m.shardID, m.path, writecache.StorageTypeFSTree.String(), fstree) } -func (m *writeCacheMetrics) SetMode(mode mode.Mode) { - m.metrics.SetMode(m.shardID, mode.String()) +func (m *writeCacheMetrics) SetMode(mod mode.ComponentMode) { + m.metrics.SetMode(m.shardID, mod.String()) } func (m *writeCacheMetrics) SetActualCounters(db, fstree uint64) { diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index cd53f0cd2f..891a1e9b22 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -38,16 +38,16 @@ var ( ) // Open boltDB instance for metabase. -func (db *DB) Open(_ context.Context, mode mode.Mode) error { +func (db *DB) Open(_ context.Context, m mode.Mode) error { db.modeMtx.Lock() defer db.modeMtx.Unlock() - db.mode = mode - db.metrics.SetMode(mode) + db.mode = m + db.metrics.SetMode(mode.ConvertToComponentModeDegraded(m)) - if mode.NoMetabase() { + if m.NoMetabase() { return nil } - return db.openDB(mode) + return db.openDB(m) } func (db *DB) openDB(mode mode.Mode) error { @@ -239,15 +239,15 @@ func (db *DB) Reload(opts ...Option) (bool, error) { return false, err } - db.mode = mode.Degraded - db.metrics.SetMode(mode.Degraded) + db.mode = mode.Disabled + db.metrics.SetMode(mode.ComponentDisabled) db.info.Path = c.info.Path if err := db.openBolt(); err != nil { return false, metaerr.Wrap(fmt.Errorf("%w: %v", ErrDegradedMode, err)) } db.mode = mode.ReadWrite - db.metrics.SetMode(mode.ReadWrite) + db.metrics.SetMode(mode.ComponentReadWrite) return true, nil } diff --git a/pkg/local_object_storage/metabase/metrics.go b/pkg/local_object_storage/metabase/metrics.go index fc971bd815..d673560c77 100644 --- a/pkg/local_object_storage/metabase/metrics.go +++ b/pkg/local_object_storage/metabase/metrics.go @@ -9,7 +9,7 @@ import ( type Metrics interface { SetParentID(parentID string) - SetMode(m mode.Mode) + SetMode(m mode.ComponentMode) Close() AddMethodDuration(method string, d time.Duration, success bool) @@ -18,6 +18,6 @@ type Metrics interface { type noopMetrics struct{} func (m *noopMetrics) SetParentID(string) {} -func (m *noopMetrics) SetMode(mode.Mode) {} +func (m *noopMetrics) SetMode(mode.ComponentMode) {} func (m *noopMetrics) Close() {} func (m *noopMetrics) AddMethodDuration(string, time.Duration, bool) {} diff --git a/pkg/local_object_storage/metabase/mode.go b/pkg/local_object_storage/metabase/mode.go index b382e99c26..2032ed6b20 100644 --- a/pkg/local_object_storage/metabase/mode.go +++ b/pkg/local_object_storage/metabase/mode.go @@ -35,6 +35,6 @@ func (db *DB) SetMode(m mode.Mode) error { } db.mode = m - db.metrics.SetMode(m) + db.metrics.SetMode(mode.ConvertToComponentModeDegraded(m)) return nil } diff --git a/pkg/local_object_storage/metabase/shard_id.go b/pkg/local_object_storage/metabase/shard_id.go index 7ae336a6cb..9b24e98d74 100644 --- a/pkg/local_object_storage/metabase/shard_id.go +++ b/pkg/local_object_storage/metabase/shard_id.go @@ -69,7 +69,7 @@ func (db *DB) SetShardID(id []byte, mode metamode.Mode) error { err := db.writeShardID(id) if err == nil { - db.metrics.SetMode(mode) + db.metrics.SetMode(metamode.ConvertToComponentModeDegraded(mode)) } if cErr := db.close(); cErr != nil { diff --git a/pkg/local_object_storage/metrics/blobovnicza.go b/pkg/local_object_storage/metrics/blobovnicza.go index 1e294efa5a..6886bbc1dc 100644 --- a/pkg/local_object_storage/metrics/blobovnicza.go +++ b/pkg/local_object_storage/metrics/blobovnicza.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" ) @@ -34,8 +35,8 @@ func (m *blobovniczaTreeMetrics) SetParentID(parentID string) { m.shardID = parentID } -func (m *blobovniczaTreeMetrics) SetMode(readOnly bool) { - m.m.SetBlobobvnizcaTreeMode(m.shardID, m.path, readOnly) +func (m *blobovniczaTreeMetrics) SetMode(mod mode.ComponentMode) { + m.m.SetBlobobvnizcaTreeMode(m.shardID, m.path, mod) } func (m *blobovniczaTreeMetrics) Close() { diff --git a/pkg/local_object_storage/metrics/fstree.go b/pkg/local_object_storage/metrics/fstree.go index e035b3a46b..e6b3175bee 100644 --- a/pkg/local_object_storage/metrics/fstree.go +++ b/pkg/local_object_storage/metrics/fstree.go @@ -4,6 +4,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" ) @@ -25,8 +26,8 @@ func (m *fstreeMetrics) SetParentID(parentID string) { m.shardID = parentID } -func (m *fstreeMetrics) SetMode(readOnly bool) { - m.m.SetMode(m.shardID, m.path, readOnly) +func (m *fstreeMetrics) SetMode(mod mode.ComponentMode) { + m.m.SetMode(m.shardID, m.path, mod) } func (m *fstreeMetrics) Close() { diff --git a/pkg/local_object_storage/metrics/metabase.go b/pkg/local_object_storage/metrics/metabase.go index d0fb319366..1a02f27059 100644 --- a/pkg/local_object_storage/metrics/metabase.go +++ b/pkg/local_object_storage/metrics/metabase.go @@ -26,7 +26,7 @@ func (m *metabaseMetrics) SetParentID(parentID string) { m.shardID = parentID } -func (m *metabaseMetrics) SetMode(mode mode.Mode) { +func (m *metabaseMetrics) SetMode(mode mode.ComponentMode) { m.m.SetMode(m.shardID, m.path, mode.String()) } diff --git a/pkg/local_object_storage/metrics/pilorama.go b/pkg/local_object_storage/metrics/pilorama.go index 21f027a6e7..1b715c2bd3 100644 --- a/pkg/local_object_storage/metrics/pilorama.go +++ b/pkg/local_object_storage/metrics/pilorama.go @@ -24,8 +24,8 @@ func (m *piloramaMetrics) SetParentID(id string) { m.shardID = id } -func (m *piloramaMetrics) SetMode(mode mode.Mode) { - m.m.SetMode(m.shardID, mode) +func (m *piloramaMetrics) SetMode(mod mode.ComponentMode) { + m.m.SetMode(m.shardID, mod) } func (m *piloramaMetrics) Close() { diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 29a9306b62..fe6bf4fed4 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -109,7 +109,7 @@ func (t *boltForest) SetMode(m mode.Mode) error { } t.mode = m - t.metrics.SetMode(m) + t.metrics.SetMode(mode.ConvertToComponentModeDegraded(m)) return nil } @@ -123,8 +123,8 @@ func (t *boltForest) Open(_ context.Context, mode mode.Mode) error { return t.openBolt(mode) } -func (t *boltForest) openBolt(mode mode.Mode) error { - readOnly := mode.ReadOnly() +func (t *boltForest) openBolt(m mode.Mode) error { + readOnly := m.ReadOnly() err := util.MkdirAllX(filepath.Dir(t.path), t.perm) if err != nil { return metaerr.Wrap(fmt.Errorf("can't create dir %s for the pilorama: %w", t.path, err)) @@ -143,7 +143,7 @@ func (t *boltForest) openBolt(mode mode.Mode) error { t.db.MaxBatchSize = t.maxBatchSize t.db.MaxBatchDelay = t.maxBatchDelay - t.metrics.SetMode(mode) + t.metrics.SetMode(mode.ConvertToComponentModeDegraded(m)) return nil } diff --git a/pkg/local_object_storage/pilorama/metrics.go b/pkg/local_object_storage/pilorama/metrics.go index 543ad3e318..6ffc479e41 100644 --- a/pkg/local_object_storage/pilorama/metrics.go +++ b/pkg/local_object_storage/pilorama/metrics.go @@ -9,7 +9,7 @@ import ( type Metrics interface { SetParentID(id string) - SetMode(m mode.Mode) + SetMode(m mode.ComponentMode) Close() AddMethodDuration(method string, d time.Duration, success bool) @@ -18,6 +18,6 @@ type Metrics interface { type noopMetrics struct{} func (m *noopMetrics) SetParentID(string) {} -func (m *noopMetrics) SetMode(mode.Mode) {} +func (m *noopMetrics) SetMode(mode.ComponentMode) {} func (m *noopMetrics) Close() {} func (m *noopMetrics) AddMethodDuration(string, time.Duration, bool) {} diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 6712822a0a..38a29cb122 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -37,7 +37,7 @@ func (s *Shard) handleMetabaseFailure(stage string, err error) error { err = s.SetMode(mode.DegradedReadOnly) if err != nil { - return fmt.Errorf("could not switch to mode %s", mode.DegradedReadOnly) + return fmt.Errorf("could not switch to mode %s", mode.Mode(mode.DegradedReadOnly)) } return nil } diff --git a/pkg/local_object_storage/shard/mode/mode.go b/pkg/local_object_storage/shard/mode/mode.go index 461611465a..dc4d52b0e5 100644 --- a/pkg/local_object_storage/shard/mode/mode.go +++ b/pkg/local_object_storage/shard/mode/mode.go @@ -29,6 +29,22 @@ const ( DegradedReadOnly Mode = Degraded | ReadOnly ) +// ComponentMode represents basic operation modes for shared components, including READ, READ_WRITE, and DISABLED. +type ComponentMode uint32 + +const ( + // ComponentReadWrite is a Mode value for component that is available + // for read and write operations. Default component mode. + ComponentReadWrite ComponentMode = 0 + + // ComponentReadOnly is a Mode value for component that does not + // accept write operation but is readable. + ComponentReadOnly ComponentMode = 0b001 + + // ComponentDisabled mode is a mode where a component is disabled. + ComponentDisabled ComponentMode = math.MaxUint32 +) + func (m Mode) String() string { switch m { default: @@ -46,6 +62,19 @@ func (m Mode) String() string { } } +func (m ComponentMode) String() string { + switch m { + default: + return "UNDEFINED" + case ComponentReadWrite: + return "READ_WRITE" + case ComponentReadOnly: + return "READ_ONLY" + case ComponentDisabled: + return "CLOSED" + } +} + // NoMetabase returns true iff m is operating without the metabase. func (m Mode) NoMetabase() bool { return m&Degraded != 0 @@ -56,6 +85,39 @@ func (m Mode) ReadOnly() bool { return m&ReadOnly != 0 } +// ReadOnly returns true iff m prohibits modifying operations with shard. +func (m ComponentMode) ReadOnly() bool { + return m&ComponentReadOnly != 0 +} + func (m Mode) Disabled() bool { return m == Disabled } + +func (m ComponentMode) Disabled() bool { + return m == ComponentDisabled +} + +// ConvertToComponentModeDegraded converts a ShardMode to a corresponding ComponentMode. +// Disables the component if the node is in degraded mode. Used in Metabase, Writecache, Pilorama. +func ConvertToComponentModeDegraded(m Mode) ComponentMode { + if m.NoMetabase() || m.Disabled() { + return ComponentDisabled + } + if m.ReadOnly() { + return ComponentReadOnly + } + return ComponentReadWrite +} + +// ConvertToComponentMode converts a ShardMode to a corresponding ComponentMode. +// Ignores the degraded mode of the node. Used in Blobstore. +func ConvertToComponentMode(m Mode) ComponentMode { + if m.Disabled() { + return ComponentDisabled + } + if m.ReadOnly() { + return ComponentReadOnly + } + return ComponentReadWrite +} diff --git a/pkg/local_object_storage/writecache/cachebbolt.go b/pkg/local_object_storage/writecache/cachebbolt.go index fdba8d409c..f2b48d7469 100644 --- a/pkg/local_object_storage/writecache/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cachebbolt.go @@ -95,14 +95,14 @@ func (c *cache) DumpInfo() Info { } // Open opens and initializes database. Reads object counters from the ObjectCounters instance. -func (c *cache) Open(_ context.Context, mode mode.Mode) error { +func (c *cache) Open(_ context.Context, mod mode.Mode) error { c.modeMtx.Lock() defer c.modeMtx.Unlock() - c.mode = mode - if mode.NoMetabase() { + c.mode = mod + if mod.NoMetabase() { return nil } - err := c.openStore(mode.ReadOnly()) + err := c.openStore(mode.ConvertToComponentModeDegraded(mod)) if err != nil { return metaerr.Wrap(err) } @@ -112,7 +112,7 @@ func (c *cache) Open(_ context.Context, mode mode.Mode) error { // Init runs necessary services. func (c *cache) Init() error { - c.metrics.SetMode(c.mode) + c.metrics.SetMode(mode.ConvertToComponentModeDegraded(c.mode)) ctx, cancel := context.WithCancel(context.Background()) c.cancel = cancel c.runFlushLoop(ctx) diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index c3e19c4d26..da7feda9a5 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -294,7 +294,7 @@ func (c *cache) Flush(ctx context.Context, ignoreErrors, seal bool) error { if err := c.setMode(ctx, m, ignoreErrors); err != nil { return err } - c.metrics.SetMode(m) + c.metrics.SetMode(mode.ConvertToComponentModeDegraded(m)) } return nil } diff --git a/pkg/local_object_storage/writecache/metrics.go b/pkg/local_object_storage/writecache/metrics.go index 962e22eea5..e68b6d8bee 100644 --- a/pkg/local_object_storage/writecache/metrics.go +++ b/pkg/local_object_storage/writecache/metrics.go @@ -27,7 +27,7 @@ type Metrics interface { Evict(st StorageType) SetEstimateSize(db, fstree uint64) - SetMode(m mode.Mode) + SetMode(m mode.ComponentMode) SetActualCounters(db, fstree uint64) SetPath(path string) Close() @@ -49,7 +49,7 @@ func (metricsStub) Put(time.Duration, bool, StorageType) {} func (metricsStub) SetEstimateSize(uint64, uint64) {} -func (metricsStub) SetMode(mode.Mode) {} +func (metricsStub) SetMode(mode.ComponentMode) {} func (metricsStub) SetActualCounters(uint64, uint64) {} diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index a10e593aa6..4172cfbc88 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -27,7 +27,7 @@ func (c *cache) SetMode(m mode.Mode) error { err := c.setMode(ctx, m, true) if err == nil { - c.metrics.SetMode(m) + c.metrics.SetMode(mode.ConvertToComponentModeDegraded(m)) } return err } @@ -63,7 +63,7 @@ func (c *cache) setMode(ctx context.Context, m mode.Mode, ignoreErrors bool) err return nil } - if err = c.openStore(m.ReadOnly()); err != nil { + if err = c.openStore(mode.ConvertToComponentModeDegraded(m)); err != nil { return err } diff --git a/pkg/local_object_storage/writecache/seal.go b/pkg/local_object_storage/writecache/seal.go index be4fec3678..48107a75f6 100644 --- a/pkg/local_object_storage/writecache/seal.go +++ b/pkg/local_object_storage/writecache/seal.go @@ -22,7 +22,7 @@ func (c *cache) Seal(ctx context.Context, ignoreErrors bool) error { // flush will be done by setMode err := c.setMode(ctx, mode.DegradedReadOnly, ignoreErrors) if err == nil { - c.metrics.SetMode(mode.DegradedReadOnly) + c.metrics.SetMode(mode.ComponentDisabled) } return err } diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index 6cc3b06d03..caf997af87 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -25,13 +26,13 @@ type store struct { const dbName = "small.bolt" -func (c *cache) openStore(readOnly bool) error { +func (c *cache) openStore(mod mode.ComponentMode) error { err := util.MkdirAllX(c.path, os.ModePerm) if err != nil { return err } - c.db, err = OpenDB(c.path, readOnly, c.openFile) + c.db, err = OpenDB(c.path, mod.ReadOnly(), c.openFile) if err != nil { return fmt.Errorf("could not open database: %w", err) } @@ -39,7 +40,7 @@ func (c *cache) openStore(readOnly bool) error { c.db.MaxBatchSize = c.maxBatchSize c.db.MaxBatchDelay = c.maxBatchDelay - if !readOnly { + if !mod.ReadOnly() { err = c.db.Update(func(tx *bbolt.Tx) error { _, err := tx.CreateBucketIfNotExists(defaultBucket) return err @@ -57,7 +58,7 @@ func (c *cache) openStore(readOnly bool) error { fstree.WithNoSync(c.noSync), fstree.WithFileCounter(&c.objCounters), ) - if err := c.fsTree.Open(readOnly); err != nil { + if err := c.fsTree.Open(mod); err != nil { return fmt.Errorf("could not open FSTree: %w", err) } if err := c.fsTree.Init(); err != nil { diff --git a/pkg/metrics/blobovnicza.go b/pkg/metrics/blobovnicza.go index f3a14a96e9..948272c881 100644 --- a/pkg/metrics/blobovnicza.go +++ b/pkg/metrics/blobovnicza.go @@ -4,12 +4,13 @@ import ( "strconv" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" "github.com/prometheus/client_golang/prometheus" ) type BlobobvnizcaMetrics interface { - SetBlobobvnizcaTreeMode(shardID, path string, readOnly bool) + SetBlobobvnizcaTreeMode(shardID, path string, mode mode.ComponentMode) CloseBlobobvnizcaTree(shardID, path string) BlobobvnizcaTreeMethodDuration(shardID, path string, method string, d time.Duration, success bool, withStorageID NullBool) AddBlobobvnizcaTreePut(shardID, path string, size int) @@ -98,8 +99,8 @@ func newBlobovnicza() *blobovnicza { } } -func (b *blobovnicza) SetBlobobvnizcaTreeMode(shardID, path string, readOnly bool) { - b.treeMode.SetMode(shardID, path, modeFromBool(readOnly)) +func (b *blobovnicza) SetBlobobvnizcaTreeMode(shardID, path string, mod mode.ComponentMode) { + b.treeMode.SetMode(shardID, path, mod.String()) } func (b *blobovnicza) CloseBlobobvnizcaTree(shardID, path string) { diff --git a/pkg/metrics/fstree.go b/pkg/metrics/fstree.go index 4d4f0693b8..ecd4352bbf 100644 --- a/pkg/metrics/fstree.go +++ b/pkg/metrics/fstree.go @@ -4,12 +4,13 @@ import ( "strconv" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" "github.com/prometheus/client_golang/prometheus" ) type FSTreeMetrics interface { - SetMode(shardID, path string, readOnly bool) + SetMode(shardID, path string, mode mode.ComponentMode) Close(shardID, path string) MethodDuration(shardID, path string, method string, d time.Duration, success bool) @@ -48,8 +49,8 @@ func newFSTreeMetrics() *fstreeMetrics { } } -func (m *fstreeMetrics) SetMode(shardID, path string, readOnly bool) { - m.mode.SetMode(shardID, path, modeFromBool(readOnly)) +func (m *fstreeMetrics) SetMode(shardID, path string, mod mode.ComponentMode) { + m.mode.SetMode(shardID, path, mod.String()) } func (m *fstreeMetrics) Close(shardID, path string) { diff --git a/pkg/metrics/pilorama.go b/pkg/metrics/pilorama.go index 41672a4b56..c669275fe0 100644 --- a/pkg/metrics/pilorama.go +++ b/pkg/metrics/pilorama.go @@ -10,7 +10,7 @@ import ( ) type PiloramaMetrics interface { - SetMode(shardID string, m mode.Mode) + SetMode(shardID string, m mode.ComponentMode) Close(shardID string) AddMethodDuration(shardID string, method string, d time.Duration, success bool) @@ -33,7 +33,7 @@ type piloramaMetrics struct { reqDuration *prometheus.HistogramVec } -func (m *piloramaMetrics) SetMode(shardID string, mode mode.Mode) { +func (m *piloramaMetrics) SetMode(shardID string, mode mode.ComponentMode) { m.mode.SetMode(shardID, mode.String()) } From 8fcd0f8f8d40a0e882cf341384d5987c455e2e47 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 4 Jun 2024 16:29:27 +0300 Subject: [PATCH 0601/1413] [#1121] docs: Change mode of shard components Signed-off-by: Alexander Chuprov --- docs/shard-modes.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/shard-modes.md b/docs/shard-modes.md index 789a1c241a..3b459335b8 100644 --- a/docs/shard-modes.md +++ b/docs/shard-modes.md @@ -14,7 +14,16 @@ Each mode is characterized by two important properties: | `read-only` | Read-only mode, only read operations are allowed, metabase is available. | | `degraded` | Degraded mode in which metabase and write-cache is disabled. It shouldn't be used at all, because metabase can contain important indices, such as LOCK objects info and modifying operation in this mode can lead to unexpected behaviour. The purpose of this mode is to allow PUT/DELETE operations without the metabase if really necessary. | | `degraded-read-only` | Same as `degraded`, but with only read operations allowed. This mode is used during SSD replacement and/or when the metabase error counter exceeds threshold. | -| `disabled` | Currently used only in config file to temporarily disable a shard. | +| `disabled` | Currently used only in config file to temporarily disable a shard. + +## Shard and Component Status + +| Shard Mode | Metabase Mode | Blobstore Mode | Writecache Mode | Pilorama Mode | Blobovnicza Tree Mode | FSTree Mode | +|-----------------------|---------------|----------------|-----------------|---------------|-----------------------|-------------| +| `Read-Write` | READ_WRITE | READ_WRITE | READ_WRITE | READ_WRITE | READ_WRITE | READ_WRITE | +| `Read-Only` | READ_ONLY | READ_ONLY | READ_ONLY | READ_ONLY | READ_ONLY | READ_ONLY | +| `Degraded-Read-Write` | CLOSED | READ_WRITE | CLOSED | CLOSED | READ_WRITE | READ_WRITE | +| `Degraded-Read-Only` | CLOSED | READ_ONLY | CLOSED | CLOSED | READ_ONLY | READ_ONLY | ## Transition order From 2e074d3846cc41c234b0165c21221b6aadf98e5b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 5 Jun 2024 11:14:06 +0300 Subject: [PATCH 0602/1413] [#1163] metabase: Properly save EC parent split ID Search by SplitID should return all parts of a complex object. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/put.go | 12 ++ .../metabase/select_test.go | 103 ++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 4b6359ebf2..05922d1bd9 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -347,6 +347,18 @@ func updateListIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun if err != nil { return err } + + if ech.ParentSplitID() != nil { + objKey := objectKey(ech.Parent(), make([]byte, objectKeySize)) + err := f(tx, namedBucketItem{ + name: splitBucketName(cnr, bucketName), + key: ech.ParentSplitID().ToV2(), + val: objKey, + }) + if err != nil { + return err + } + } } return nil diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 9ff2fd65ef..8951a2dbe8 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -3,6 +3,7 @@ package meta_test import ( "context" "encoding/hex" + "math/rand" "strconv" "testing" @@ -13,9 +14,13 @@ import ( cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" + usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" ) @@ -628,6 +633,104 @@ func TestDB_SelectObjectID(t *testing.T) { }) } +type testTarget struct { + objects []*objectSDK.Object +} + +func (tt *testTarget) WriteObject(_ context.Context, obj *objectSDK.Object) error { + tt.objects = append(tt.objects, obj) + return nil +} + +func cutObject(t *testing.T, p transformer.ChunkedObjectWriter, hdr *objectSDK.Object, size int) { + ctx := context.Background() + require.NoError(t, p.WriteHeader(ctx, hdr)) + + payload := make([]byte, size) + rand.New(rand.NewSource(0)).Read(payload) + + _, err := p.Write(ctx, payload) + require.NoError(t, err) + + _, err = p.Close(ctx) + require.NoError(t, err) +} + +func TestDB_SelectSplitID_EC(t *testing.T) { + t.Parallel() + + const ( + partSize = 10 + partCount = 2 + dataCount = 2 + parityCount = 1 + ) + + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + tt := new(testTarget) + p := transformer.NewPayloadSizeLimiter(transformer.Params{ + Key: &pk.PrivateKey, + NextTargetInit: func() transformer.ObjectWriter { return tt }, + NetworkState: epochState{e: 1}, + MaxSize: partSize, + }) + + hdr := objectSDK.New() + hdr.SetContainerID(cnr) + hdr.SetOwnerID(usertest.ID()) + cutObject(t, p, hdr, partSize*partCount) + require.Equal(t, len(tt.objects), partCount+1) + + split := tt.objects[0].SplitID() + require.NotNil(t, split) + + ec, err := erasurecode.NewConstructor(dataCount, parityCount) + require.NoError(t, err) + + for i := 0; i < partCount; i++ { + cs, err := ec.Split(tt.objects[i], &pk.PrivateKey) + require.NoError(t, err) + + require.NoError(t, putBig(db, cs[0])) + } + + t.Run("not present", func(t *testing.T) { + fs := objectSDK.SearchFilters{} + fs.AddFilter(v2object.FilterHeaderSplitID, "", objectSDK.MatchNotPresent) + testSelect(t, db, cnr, fs) + }) + + t.Run("split id", func(t *testing.T) { + fs := objectSDK.SearchFilters{} + fs.AddFilter(v2object.FilterHeaderSplitID, split.String(), objectSDK.MatchStringEqual) + testSelect(t, db, cnr, fs, + object.AddressOf(tt.objects[0]), + object.AddressOf(tt.objects[1]), + ) + }) + + t.Run("empty split", func(t *testing.T) { + fs := objectSDK.SearchFilters{} + fs.AddFilter(v2object.FilterHeaderSplitID, "", objectSDK.MatchStringEqual) + testSelect(t, db, cnr, fs) + }) + + t.Run("unknown split id", func(t *testing.T) { + fs := objectSDK.SearchFilters{} + fs.AddFilter(v2object.FilterHeaderSplitID, + objectSDK.NewSplitID().String(), + objectSDK.MatchStringEqual) + testSelect(t, db, cnr, fs) + }) +} + func TestDB_SelectSplitID(t *testing.T) { t.Parallel() From 3f1961157ec794af9a36df858f2cb32f2a42907f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 6 Jun 2024 10:52:17 +0300 Subject: [PATCH 0603/1413] [#1163] metabase: Handle multiple splitInfos for EC For REP updating split info is handled explicitly by a high-level PUT logic. For EC it is trickier, because the address of an object we put is only distantly related to a split info. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/put.go | 115 +++++++--------- .../metabase/select_test.go | 124 +++++++++++++++++- 2 files changed, 168 insertions(+), 71 deletions(-) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 05922d1bd9..ceb79758f1 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -244,52 +244,49 @@ func putUniqueIndexes( // index root object if obj.Type() == objectSDK.TypeRegular && !obj.HasParent() { - var ( - err error - splitInfo []byte - ) - - if isParent { - splitInfo, err = si.Marshal() - if err != nil { - return fmt.Errorf("can't marshal split info: %w", err) - } - } - - isObjKeySet := true if ecHead := obj.ECHeader(); ecHead != nil { - objKey, isObjKeySet = objectKeyByECHeader(ecHead) - } - if isObjKeySet { - err = putUniqueIndexItem(tx, namedBucketItem{ - name: rootBucketName(cnr, bucketName), - key: objKey, - val: splitInfo, - }) - if err != nil { - return err + parentID := ecHead.Parent() + if ecHead.ParentSplitID() != nil { + parentSplitParentID := ecHead.ParentSplitParentID() + if parentSplitParentID == nil { + return nil + } + + si = objectSDK.NewSplitInfo() + si.SetSplitID(ecHead.ParentSplitID()) + si.SetLastPart(ecHead.Parent()) + + parentID = *parentSplitParentID } + objKey = objectKey(parentID, objKey) } + return updateSplitInfoIndex(tx, objKey, cnr, bucketName, si) } return nil } -// objectKeyByECHeader returns objectKey for an object that has EC Header. -// If object's parent is in Split, then parent's non-nil Split parent ID is set to object key. -// If object's parent is not in Split, then its ID is set to object key. -// Otherwise, such object keys should be ignored -- they are not put to the root bucket. -func objectKeyByECHeader(ech *objectSDK.ECHeader) (objKey []byte, isSet bool) { - if ech.ParentSplitID() != nil { - if parentSplitParentID := ech.ParentSplitParentID(); parentSplitParentID != nil { - isSet = true - objKey = objectKey(*parentSplitParentID, make([]byte, objectKeySize)) +func updateSplitInfoIndex(tx *bbolt.Tx, objKey []byte, cnr cid.ID, bucketName []byte, si *objectSDK.SplitInfo) error { + return updateUniqueIndexItem(tx, namedBucketItem{ + name: rootBucketName(cnr, bucketName), + key: objKey, + }, func(old, _ []byte) ([]byte, error) { + switch { + case si == nil && old == nil: + return []byte{}, nil + case si == nil: + return old, nil + case old == nil: + return si.Marshal() + default: + oldSI := objectSDK.NewSplitInfo() + if err := oldSI.Unmarshal(old); err != nil { + return nil, err + } + si = util.MergeSplitInfo(si, oldSI) + return si.Marshal() } - return - } - isSet = true - objKey = objectKey(ech.Parent(), make([]byte, objectKeySize)) - return + }) } type updateIndexItemFunc = func(tx *bbolt.Tx, item namedBucketItem) error @@ -416,13 +413,21 @@ func createBucketLikelyExists[T bucketContainer](tx T, name []byte) (*bbolt.Buck return tx.CreateBucket(name) } -func putUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) error { +func updateUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem, update func(oldData, newData []byte) ([]byte, error)) error { bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { return fmt.Errorf("can't create index %v: %w", item.name, err) } - return bkt.Put(item.key, item.val) + data, err := update(bkt.Get(item.key), item.val) + if err != nil { + return err + } + return bkt.Put(item.key, data) +} + +func putUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) error { + return updateUniqueIndexItem(tx, item, func(_, val []byte) ([]byte, error) { return val, nil }) } func putFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { @@ -548,36 +553,8 @@ func setStorageID(tx *bbolt.Tx, addr oid.Address, id []byte, override bool) erro // updateSpliInfo for existing objects if storage filled with extra information // about last object in split hierarchy or linking object. func updateSplitInfo(tx *bbolt.Tx, addr oid.Address, from *objectSDK.SplitInfo) error { - key := make([]byte, bucketKeySize) - bkt := tx.Bucket(rootBucketName(addr.Container(), key)) - if bkt == nil { - // if object doesn't exists and we want to update split info on it - // then ignore, this should never happen - return ErrIncorrectSplitInfoUpdate - } - - objectKey := objectKey(addr.Object(), key) - - rawSplitInfo := bkt.Get(objectKey) - if len(rawSplitInfo) == 0 { - return ErrIncorrectSplitInfoUpdate - } - - to := objectSDK.NewSplitInfo() - - err := to.Unmarshal(rawSplitInfo) - if err != nil { - return fmt.Errorf("can't unmarshal split info from root index: %w", err) - } - - result := util.MergeSplitInfo(from, to) - - rawSplitInfo, err = result.Marshal() - if err != nil { - return fmt.Errorf("can't marhsal merged split info: %w", err) - } - - return bkt.Put(objectKey, rawSplitInfo) + objKey := objectKey(addr.Object(), make([]byte, bucketKeySize)) + return updateSplitInfoIndex(tx, objKey, addr.Container(), make([]byte, bucketKeySize), from) } // splitInfoFromObject returns split info based on last or linkin object. diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 8951a2dbe8..8f9294d072 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -642,7 +642,7 @@ func (tt *testTarget) WriteObject(_ context.Context, obj *objectSDK.Object) erro return nil } -func cutObject(t *testing.T, p transformer.ChunkedObjectWriter, hdr *objectSDK.Object, size int) { +func cutObject(t *testing.T, p transformer.ChunkedObjectWriter, hdr *objectSDK.Object, size int) *transformer.AccessIdentifiers { ctx := context.Background() require.NoError(t, p.WriteHeader(ctx, hdr)) @@ -652,8 +652,128 @@ func cutObject(t *testing.T, p transformer.ChunkedObjectWriter, hdr *objectSDK.O _, err := p.Write(ctx, payload) require.NoError(t, err) - _, err = p.Close(ctx) + ids, err := p.Close(ctx) require.NoError(t, err) + return ids +} + +func TestDB_RawHead_SplitInfo(t *testing.T) { + t.Parallel() + + const ( + partSize = 10 + partCount = 2 + dataCount = 2 + parityCount = 1 + ) + + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + tt := new(testTarget) + p := transformer.NewPayloadSizeLimiter(transformer.Params{ + Key: &pk.PrivateKey, + NextTargetInit: func() transformer.ObjectWriter { return tt }, + NetworkState: epochState{e: 1}, + MaxSize: partSize, + }) + + hdr := objectSDK.New() + hdr.SetContainerID(cnr) + hdr.SetOwnerID(usertest.ID()) + ids := cutObject(t, p, hdr, partSize*partCount) + require.Equal(t, len(tt.objects), partCount+1) + + t.Run("rep", func(t *testing.T) { + testGetRawSplitInfo(t, cnr, ids, tt.objects[partCount], tt.objects[partCount-1]) + }) + t.Run("with ec", func(t *testing.T) { + ec, err := erasurecode.NewConstructor(dataCount, parityCount) + require.NoError(t, err) + + cs, err := ec.Split(tt.objects[partCount-1], &pk.PrivateKey) + require.NoError(t, err) + + testGetRawSplitInfo(t, cnr, ids, tt.objects[partCount], cs[0]) + }) +} + +func testGetRawSplitInfo(t *testing.T, cnr cidSDK.ID, ids *transformer.AccessIdentifiers, linking, lastPart *objectSDK.Object) { + expectedLinkID, ok := linking.ID() + require.True(t, ok) + + t.Run("first last, then linking", func(t *testing.T) { + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + require.NoError(t, metaPut(db, lastPart, nil)) + require.NoError(t, metaPut(db, linking, nil)) + + var addr oid.Address + addr.SetContainer(cnr) + addr.SetObject(*ids.ParentID) + + _, err := metaGet(db, addr, true) + + var siErr *objectSDK.SplitInfoError + require.ErrorAs(t, err, &siErr) + + lastID, ok := siErr.SplitInfo().LastPart() + require.True(t, ok) + require.Equal(t, ids.SelfID, lastID) + + linkID, ok := siErr.SplitInfo().Link() + require.True(t, ok) + require.Equal(t, expectedLinkID, linkID) + }) + t.Run("first linking, then last", func(t *testing.T) { + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + require.NoError(t, metaPut(db, linking, nil)) + require.NoError(t, metaPut(db, lastPart, nil)) + + var addr oid.Address + addr.SetContainer(cnr) + addr.SetObject(*ids.ParentID) + + _, err := metaGet(db, addr, true) + + var siErr *objectSDK.SplitInfoError + require.ErrorAs(t, err, &siErr) + + lastID, ok := siErr.SplitInfo().LastPart() + require.True(t, ok) + require.Equal(t, ids.SelfID, lastID) + + linkID, ok := siErr.SplitInfo().Link() + require.True(t, ok) + require.Equal(t, expectedLinkID, linkID) + }) + t.Run("only last part", func(t *testing.T) { + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + require.NoError(t, metaPut(db, lastPart, nil)) + + var addr oid.Address + addr.SetContainer(cnr) + addr.SetObject(*ids.ParentID) + + _, err := metaGet(db, addr, true) + + var siErr *objectSDK.SplitInfoError + require.ErrorAs(t, err, &siErr) + + lastPart, ok := siErr.SplitInfo().LastPart() + require.True(t, ok) + require.Equal(t, ids.SelfID, lastPart) + }) } func TestDB_SelectSplitID_EC(t *testing.T) { From 67b3002743f056ab20abb0b5b59d520e6fe2a286 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 6 Jun 2024 15:25:51 +0300 Subject: [PATCH 0604/1413] [#951] adm: Check for error when reading contracts from archive Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/helper/util.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/util.go b/cmd/frostfs-adm/internal/modules/morph/helper/util.go index f0399ab377..ba557a0332 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/util.go @@ -122,11 +122,11 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*Contr } r := tar.NewReader(gr) - for h, err := r.Next(); ; h, err = r.Next() { - if err != nil { - break + var h *tar.Header + for h, err = r.Next(); err == nil && h != nil; h, err = r.Next() { + if h.Typeflag != tar.TypeReg { + continue } - dir, _ := filepath.Split(h.Name) ctrName := filepath.Base(dir) @@ -149,6 +149,9 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*Contr } m[ctrName] = cs } + if err != nil && err != io.EOF { + return nil, fmt.Errorf("can't read contracts from archive: %w", err) + } for ctrName, cs := range m { if cs.RawNEF == nil { From a849236b687e4cd9fe86960102da5e04de147b0f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 4 Jun 2024 15:31:47 +0300 Subject: [PATCH 0605/1413] [#1161] node: Remove notification functionality It is unused and will be reworked in future. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 7 - cmd/frostfs-node/config/node/config.go | 80 --------- cmd/frostfs-node/config/node/config_test.go | 29 ---- cmd/frostfs-node/main.go | 2 - cmd/frostfs-node/notificator.go | 172 -------------------- cmd/frostfs-node/object.go | 51 ------ config/example/node.env | 7 - config/example/node.json | 9 - config/example/node.yaml | 8 - docs/storage-node-configuration.md | 23 --- go.mod | 3 - go.sum | 6 - internal/logs/logs.go | 4 - pkg/services/notificator/deps.go | 22 --- pkg/services/notificator/nats/options.go | 38 ----- pkg/services/notificator/nats/service.go | 129 --------------- pkg/services/notificator/service.go | 88 ---------- 17 files changed, 678 deletions(-) delete mode 100644 cmd/frostfs-node/notificator.go delete mode 100644 pkg/services/notificator/deps.go delete mode 100644 pkg/services/notificator/nats/options.go delete mode 100644 pkg/services/notificator/nats/service.go delete mode 100644 pkg/services/notificator/service.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index d713cf2fb8..cdfa2118ce 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -474,7 +474,6 @@ type cfg struct { cfgNetmap cfgNetmap cfgControlService cfgControlService cfgObject cfgObject - cfgNotifications cfgNotifications } // ReadCurrentNetMap reads network map which has been cached at the @@ -633,12 +632,6 @@ type cfgObject struct { skipSessionTokenIssuerVerification bool } -type cfgNotifications struct { - enabled bool - nw notificationWriter - defaultTopic string -} - type cfgLocalStorage struct { localStorage *engine.StorageEngine } diff --git a/cmd/frostfs-node/config/node/config.go b/cmd/frostfs-node/config/node/config.go index 90338556e0..97aca274ab 100644 --- a/cmd/frostfs-node/config/node/config.go +++ b/cmd/frostfs-node/config/node/config.go @@ -5,7 +5,6 @@ import ( "io/fs" "os" "strconv" - "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" @@ -25,12 +24,6 @@ type PersistentStateConfig struct { cfg *config.Config } -// NotificationConfig is a wrapper over "notification" config section -// which provides access to object notification configuration of node. -type NotificationConfig struct { - cfg *config.Config -} - // PersistentPolicyRulesConfig is a wrapper over "persistent_policy_rules" config section // which provides access to persistent policy rules storage configuration of node. type PersistentPolicyRulesConfig struct { @@ -41,16 +34,12 @@ const ( subsection = "node" persistentSessionsSubsection = "persistent_sessions" persistentStateSubsection = "persistent_state" - notificationSubsection = "notification" persistentPolicyRulesSubsection = "persistent_policy_rules" attributePrefix = "attribute" // PersistentStatePathDefault is a default path for persistent state file. PersistentStatePathDefault = ".frostfs-storage-state" - - // NotificationTimeoutDefault is a default timeout for object notification operation. - NotificationTimeoutDefault = 5 * time.Second ) // Key returns the value of "key" config parameter @@ -185,75 +174,6 @@ func (p PersistentStateConfig) Path() string { return PersistentStatePathDefault } -// Notification returns structure that provides access to "notification" -// subsection of "node" section. -func Notification(c *config.Config) NotificationConfig { - return NotificationConfig{ - c.Sub(subsection).Sub(notificationSubsection), - } -} - -// Enabled returns the value of "enabled" config parameter from "notification" -// subsection of "node" section. -// -// Returns false if the value is not presented. -func (n NotificationConfig) Enabled() bool { - return config.BoolSafe(n.cfg, "enabled") -} - -// DefaultTopic returns the value of "default_topic" config parameter from -// "notification" subsection of "node" section. -// -// Returns empty string if the value is not presented. -func (n NotificationConfig) DefaultTopic() string { - return config.StringSafe(n.cfg, "default_topic") -} - -// Endpoint returns the value of "endpoint" config parameter from "notification" -// subsection of "node" section. -// -// Returns empty string if the value is not presented. -func (n NotificationConfig) Endpoint() string { - return config.StringSafe(n.cfg, "endpoint") -} - -// Timeout returns the value of "timeout" config parameter from "notification" -// subsection of "node" section. -// -// Returns NotificationTimeoutDefault if the value is not positive. -func (n NotificationConfig) Timeout() time.Duration { - v := config.DurationSafe(n.cfg, "timeout") - if v > 0 { - return v - } - - return NotificationTimeoutDefault -} - -// CertPath returns the value of "certificate_path" config parameter from "notification" -// subsection of "node" section. -// -// Returns empty string if the value is not presented. -func (n NotificationConfig) CertPath() string { - return config.StringSafe(n.cfg, "certificate") -} - -// KeyPath returns the value of "key_path" config parameter from -// "notification" subsection of "node" section. -// -// Returns empty string if the value is not presented. -func (n NotificationConfig) KeyPath() string { - return config.StringSafe(n.cfg, "key") -} - -// CAPath returns the value of "ca_path" config parameter from -// "notification" subsection of "node" section. -// -// Returns empty string if the value is not presented. -func (n NotificationConfig) CAPath() string { - return config.StringSafe(n.cfg, "ca") -} - const ( // PermDefault is a default permission bits for local override storage file. PermDefault = 0o644 diff --git a/cmd/frostfs-node/config/node/config_test.go b/cmd/frostfs-node/config/node/config_test.go index b0041c8706..7b9adecf4d 100644 --- a/cmd/frostfs-node/config/node/config_test.go +++ b/cmd/frostfs-node/config/node/config_test.go @@ -2,7 +2,6 @@ package nodeconfig import ( "testing" - "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" @@ -33,25 +32,11 @@ func TestNodeSection(t *testing.T) { relay := Relay(empty) persisessionsPath := PersistentSessions(empty).Path() persistatePath := PersistentState(empty).Path() - notificationDefaultEnabled := Notification(empty).Enabled() - notificationDefaultEndpoint := Notification(empty).Endpoint() - notificationDefaultTimeout := Notification(empty).Timeout() - notificationDefaultTopic := Notification(empty).DefaultTopic() - notificationDefaultCertPath := Notification(empty).CertPath() - notificationDefaultKeyPath := Notification(empty).KeyPath() - notificationDefaultCAPath := Notification(empty).CAPath() require.Empty(t, attribute) require.Equal(t, false, relay) require.Equal(t, "", persisessionsPath) require.Equal(t, PersistentStatePathDefault, persistatePath) - require.Equal(t, false, notificationDefaultEnabled) - require.Equal(t, "", notificationDefaultEndpoint) - require.Equal(t, NotificationTimeoutDefault, notificationDefaultTimeout) - require.Equal(t, "", notificationDefaultTopic) - require.Equal(t, "", notificationDefaultCertPath) - require.Equal(t, "", notificationDefaultKeyPath) - require.Equal(t, "", notificationDefaultCAPath) }) const path = "../../../../config/example/node" @@ -64,13 +49,6 @@ func TestNodeSection(t *testing.T) { wKey := Wallet(c) persisessionsPath := PersistentSessions(c).Path() persistatePath := PersistentState(c).Path() - notificationEnabled := Notification(c).Enabled() - notificationEndpoint := Notification(c).Endpoint() - notificationTimeout := Notification(c).Timeout() - notificationDefaultTopic := Notification(c).DefaultTopic() - notificationCertPath := Notification(c).CertPath() - notificationKeyPath := Notification(c).KeyPath() - notificationCAPath := Notification(c).CAPath() expectedAddr := []struct { str string @@ -122,13 +100,6 @@ func TestNodeSection(t *testing.T) { require.Equal(t, "/sessions", persisessionsPath) require.Equal(t, "/state", persistatePath) - require.Equal(t, true, notificationEnabled) - require.Equal(t, "tls://localhost:4222", notificationEndpoint) - require.Equal(t, 6*time.Second, notificationTimeout) - require.Equal(t, "topic", notificationDefaultTopic) - require.Equal(t, "/cert/path", notificationCertPath) - require.Equal(t, "/key/path", notificationKeyPath) - require.Equal(t, "/ca/path", notificationCAPath) } configtest.ForEachFileType(path, fileConfigTest) diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index dbef1e494c..e4f0a434c2 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -111,7 +111,6 @@ func initApp(ctx context.Context, c *cfg) { initAndLog(c, "accounting", func(c *cfg) { initAccountingService(ctx, c) }) initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) }) initAndLog(c, "session", initSessionService) - initAndLog(c, "notification", func(c *cfg) { initNotifications(ctx, c) }) initAndLog(c, "object", initObjectService) initAndLog(c, "tree", initTreeService) initAndLog(c, "apemanager", initAPEManagerService) @@ -143,7 +142,6 @@ func stopAndLog(c *cfg, name string, stopper func() error) { } func bootUp(ctx context.Context, c *cfg) { - runAndLog(ctx, c, "NATS", true, connectNats) runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(c) }) runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit) diff --git a/cmd/frostfs-node/notificator.go b/cmd/frostfs-node/notificator.go deleted file mode 100644 index f9bb31fed5..0000000000 --- a/cmd/frostfs-node/notificator.go +++ /dev/null @@ -1,172 +0,0 @@ -package main - -import ( - "context" - "encoding/hex" - "fmt" - - nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/notificator" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/notificator/nats" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.uber.org/zap" -) - -type notificationSource struct { - e *engine.StorageEngine - l *logger.Logger - defaultTopic string -} - -func (n *notificationSource) Iterate(ctx context.Context, epoch uint64, handler func(topic string, addr oid.Address)) { - log := n.l.With(zap.Uint64("epoch", epoch)) - - listRes, err := n.e.ListContainers(ctx, engine.ListContainersPrm{}) - if err != nil { - log.Error(logs.FrostFSNodeNotificatorCouldNotListContainers, zap.Error(err)) - return - } - - filters := objectSDK.NewSearchFilters() - filters.AddNotificationEpochFilter(epoch) - - var selectPrm engine.SelectPrm - selectPrm.WithFilters(filters) - - for _, c := range listRes.Containers() { - selectPrm.WithContainerID(c) - - selectRes, err := n.e.Select(ctx, selectPrm) - if err != nil { - log.Error(logs.FrostFSNodeNotificatorCouldNotSelectObjectsFromContainer, - zap.Stringer("cid", c), - zap.Error(err), - ) - continue - } - - for _, a := range selectRes.AddressList() { - err = n.processAddress(ctx, a, handler) - if err != nil { - log.Error(logs.FrostFSNodeNotificatorCouldNotProcessObject, - zap.Stringer("address", a), - zap.Error(err), - ) - continue - } - } - } - - log.Debug(logs.FrostFSNodeNotificatorFinishedProcessingObjectNotifications) -} - -func (n *notificationSource) processAddress( - ctx context.Context, - a oid.Address, - h func(topic string, addr oid.Address), -) error { - var prm engine.HeadPrm - prm.WithAddress(a) - - res, err := n.e.Head(ctx, prm) - if err != nil { - return err - } - - ni, err := res.Header().NotificationInfo() - if err != nil { - return fmt.Errorf("could not retrieve notification topic from object: %w", err) - } - - topic := ni.Topic() - - if topic == "" { - topic = n.defaultTopic - } - - h(topic, a) - - return nil -} - -type notificationWriter struct { - l *logger.Logger - w *nats.Writer -} - -func (n notificationWriter) Notify(topic string, address oid.Address) { - if err := n.w.Notify(topic, address); err != nil { - n.l.Warn(logs.FrostFSNodeCouldNotWriteObjectNotification, - zap.Stringer("address", address), - zap.String("topic", topic), - zap.Error(err), - ) - } -} - -func initNotifications(ctx context.Context, c *cfg) { - if nodeconfig.Notification(c.appCfg).Enabled() { - topic := nodeconfig.Notification(c.appCfg).DefaultTopic() - pubKey := hex.EncodeToString(c.cfgNodeInfo.localInfo.PublicKey()) - - if topic == "" { - topic = pubKey - } - - natsSvc := nats.New( - nats.WithConnectionName("FrostFS Storage Node: "+pubKey), // connection name is used in the server side logs - nats.WithTimeout(nodeconfig.Notification(c.appCfg).Timeout()), - nats.WithClientCert( - nodeconfig.Notification(c.appCfg).CertPath(), - nodeconfig.Notification(c.appCfg).KeyPath(), - ), - nats.WithRootCA(nodeconfig.Notification(c.appCfg).CAPath()), - nats.WithLogger(c.log), - ) - - c.cfgNotifications = cfgNotifications{ - enabled: true, - nw: notificationWriter{ - l: c.log, - w: natsSvc, - }, - defaultTopic: topic, - } - - n := notificator.New(new(notificator.Prm). - SetLogger(c.log). - SetNotificationSource( - ¬ificationSource{ - e: c.cfgObject.cfgLocalStorage.localStorage, - l: c.log, - defaultTopic: topic, - }). - SetWriter(c.cfgNotifications.nw), - ) - - addNewEpochAsyncNotificationHandler(c, func(e event.Event) { - ev := e.(netmap.NewEpoch) - - n.ProcessEpoch(ctx, ev.EpochNumber()) - }) - } -} - -func connectNats(ctx context.Context, c *cfg) { - if !c.cfgNotifications.enabled { - return - } - - endpoint := nodeconfig.Notification(c.appCfg).Endpoint() - err := c.cfgNotifications.nw.w.Connect(ctx, endpoint) - if err != nil { - panic(fmt.Sprintf("could not connect to a nats endpoint %s: %v", endpoint, err)) - } - c.log.Info(logs.NatsConnectedToEndpoint, zap.String("endpoint", endpoint)) -} diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 9f34896bc2..9d1e2218f3 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -14,7 +14,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" @@ -333,15 +332,6 @@ func createPutSvc(c *cfg, keyStorage *util.KeyStorage, irFetcher *cachedIRFetche engine: ls, } - if c.cfgNotifications.enabled { - os = engineWithNotifications{ - base: os, - nw: c.cfgNotifications.nw, - ns: c.cfgNetmap.state, - defaultTopic: c.cfgNotifications.defaultTopic, - } - } - return putsvc.NewService( keyStorage, c.putClientCache, @@ -503,47 +493,6 @@ func (s *morphEACLFetcher) GetEACL(cnr cid.ID) (*containercore.EACL, error) { return eaclInfo, nil } -type engineWithNotifications struct { - base putsvc.ObjectStorage - nw notificationWriter - ns netmap.State - - defaultTopic string -} - -func (e engineWithNotifications) IsLocked(ctx context.Context, address oid.Address) (bool, error) { - return e.base.IsLocked(ctx, address) -} - -func (e engineWithNotifications) Delete(ctx context.Context, tombstone oid.Address, toDelete []oid.ID) error { - return e.base.Delete(ctx, tombstone, toDelete) -} - -func (e engineWithNotifications) Lock(ctx context.Context, locker oid.Address, toLock []oid.ID) error { - return e.base.Lock(ctx, locker, toLock) -} - -func (e engineWithNotifications) Put(ctx context.Context, o *objectSDK.Object) error { - if err := e.base.Put(ctx, o); err != nil { - return err - } - - ni, err := o.NotificationInfo() - if err == nil { - if epoch := ni.Epoch(); epoch == 0 || epoch == e.ns.CurrentEpoch() { - topic := ni.Topic() - - if topic == "" { - topic = e.defaultTopic - } - - e.nw.Notify(topic, objectCore.AddressOf(o)) - } - } - - return nil -} - type engineWithoutNotifications struct { engine *engine.StorageEngine } diff --git a/config/example/node.env b/config/example/node.env index db31ae35a2..9f15c40428 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -22,13 +22,6 @@ FROSTFS_NODE_ATTRIBUTE_1="UN-LOCODE:RU MSK" FROSTFS_NODE_RELAY=true FROSTFS_NODE_PERSISTENT_SESSIONS_PATH=/sessions FROSTFS_NODE_PERSISTENT_STATE_PATH=/state -FROSTFS_NODE_NOTIFICATION_ENABLED=true -FROSTFS_NODE_NOTIFICATION_ENDPOINT=tls://localhost:4222 -FROSTFS_NODE_NOTIFICATION_TIMEOUT=6s -FROSTFS_NODE_NOTIFICATION_DEFAULT_TOPIC=topic -FROSTFS_NODE_NOTIFICATION_CERTIFICATE=/cert/path -FROSTFS_NODE_NOTIFICATION_KEY=/key/path -FROSTFS_NODE_NOTIFICATION_CA=/ca/path # Tree service section FROSTFS_TREE_ENABLED=true diff --git a/config/example/node.json b/config/example/node.json index 80140e5a21..79e6fe89ac 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -36,15 +36,6 @@ }, "persistent_state": { "path": "/state" - }, - "notification": { - "enabled": true, - "endpoint": "tls://localhost:4222", - "timeout": "6s", - "default_topic": "topic", - "certificate": "/cert/path", - "key": "/key/path", - "ca": "/ca/path" } }, "grpc": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 13c1823d8e..34e796ac46 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -35,14 +35,6 @@ node: path: /sessions # path to persistent session tokens file of Storage node (default: in-memory sessions) persistent_state: path: /state # path to persistent state file of Storage node - notification: - enabled: true # turn on object notification service - endpoint: "tls://localhost:4222" # notification server endpoint - timeout: "6s" # timeout for object notification client connection - default_topic: "topic" # default topic for object notifications if not found in object's meta - certificate: "/cert/path" # path to TLS certificate - key: "/key/path" # path to TLS key - ca: "/ca/path" # path to optional CA certificate grpc: - endpoint: s01.frostfs.devenv:8080 # endpoint for gRPC server diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index ce9065ac24..3a6969abdf 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -322,14 +322,6 @@ node: path: /sessions persistent_state: path: /state - notification: - enabled: true - endpoint: tls://localhost:4222 - timeout: 6s - default_topic: topic - certificate: /path/to/cert.pem - key: /path/to/key.pem - ca: /path/to/ca.pem ``` | Parameter | Type | Default value | Description | @@ -341,8 +333,6 @@ node: | `relay` | `bool` | | Enable relay mode. | | `persistent_sessions` | [Persistent sessions config](#persistent_sessions-subsection) | | Persistent session token store configuration. | | `persistent_state` | [Persistent state config](#persistent_state-subsection) | | Persistent state configuration. | -| `notification` | [Notification config](#notification-subsection) | | NATS configuration. | - ## `wallet` subsection N3 wallet configuration. @@ -369,19 +359,6 @@ It is used to correctly handle node restarts or crashes. |-----------|----------|------------------------|------------------------| | `path` | `string` | `.frostfs-storage-state` | Path to the database. | -## `notification` subsection -This is an advanced section, use with caution. - -| Parameter | Type | Default value | Description | -|-----------------|------------|-------------------|-------------------------------------------------------------------| -| `enabled` | `bool` | `false` | Flag to enable the service. | -| `endpoint` | `string` | | NATS endpoint to connect to. | -| `timeout` | `duration` | `5s` | Timeout for the object notification operation. | -| `default_topic` | `string` | node's public key | Default topic to use if an object has no corresponding attribute. | -| `certificate` | `string` | | Path to the client certificate. | -| `key` | `string` | | Path to the client key. | -| `ca` | `string` | | Override root CA used to verify server certificates. | - # `apiclient` section Configuration for the FrostFS API client used for communication with other FrostFS nodes. diff --git a/go.mod b/go.mod index 0935609538..42896ed8c0 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,6 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.12.1 - github.com/nats-io/nats.go v1.32.0 github.com/nspcc-dev/neo-go v0.106.0 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 @@ -96,8 +95,6 @@ require ( github.com/multiformats/go-multibase v0.2.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-varint v0.0.7 // indirect - github.com/nats-io/nkeys v0.4.7 // indirect - github.com/nats-io/nuid v1.0.1 // indirect github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 // indirect github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d // indirect github.com/nspcc-dev/rfc6979 v0.2.1 // indirect diff --git a/go.sum b/go.sum index 6f5034f007..07632a032d 100644 --- a/go.sum +++ b/go.sum @@ -184,12 +184,6 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= 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/nats-io/nats.go v1.32.0 h1:Bx9BZS+aXYlxW08k8Gd3yR2s73pV5XSoAQUyp1Kwvp0= -github.com/nats-io/nats.go v1.32.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= -github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= -github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 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/go.mod h1:U5VfmPNM88P4RORFb6KSUVBdJBDhlqggJZYGXGPxOcc= github.com/nspcc-dev/neo-go v0.106.0 h1:YiOdW/GcLmbVSvxMRfD5aytO6n3TDHrEA97VHMawy6g= diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 7dc63341da..8dae61c3d0 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -132,10 +132,6 @@ const ( UtilCouldNotPushTaskToWorkerPool = "could not push task to worker pool" V2CantCheckIfRequestFromInnerRing = "can't check if request from inner ring" V2CantCheckIfRequestFromContainerNode = "can't check if request from container node" - NatsNatsConnectionWasLost = "nats: connection was lost" - NatsNatsReconnectedToTheServer = "nats: reconnected to the server" - NatsNatsClosingConnectionAsTheContextIsDone = "nats: closing connection as the context is done" - NatsConnectedToEndpoint = "nats: successfully connected to endpoint" ClientCouldNotRestoreBlockSubscriptionAfterRPCSwitch = "could not restore block subscription after RPC switch" ClientCouldNotRestoreNotificationSubscriptionAfterRPCSwitch = "could not restore notification subscription after RPC switch" ClientCouldNotRestoreNotaryNotificationSubscriptionAfterRPCSwitch = "could not restore notary notification subscription after RPC switch" diff --git a/pkg/services/notificator/deps.go b/pkg/services/notificator/deps.go deleted file mode 100644 index d6330f7889..0000000000 --- a/pkg/services/notificator/deps.go +++ /dev/null @@ -1,22 +0,0 @@ -package notificator - -import ( - "context" - - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" -) - -// NotificationSource is a source of object notifications. -type NotificationSource interface { - // Iterate must iterate over all notifications for the - // provided epoch and call handler for all of them. - Iterate(ctx context.Context, epoch uint64, handler func(topic string, addr oid.Address)) -} - -// NotificationWriter notifies all the subscribers -// about new object notifications. -type NotificationWriter interface { - // Notify must notify about an event generated - // from an object with a specific topic. - Notify(topic string, address oid.Address) -} diff --git a/pkg/services/notificator/nats/options.go b/pkg/services/notificator/nats/options.go deleted file mode 100644 index c9ba2ed260..0000000000 --- a/pkg/services/notificator/nats/options.go +++ /dev/null @@ -1,38 +0,0 @@ -package nats - -import ( - "time" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "github.com/nats-io/nats.go" -) - -func WithClientCert(certPath, keyPath string) Option { - return func(o *opts) { - o.nOpts = append(o.nOpts, nats.ClientCert(certPath, keyPath)) - } -} - -func WithRootCA(paths ...string) Option { - return func(o *opts) { - o.nOpts = append(o.nOpts, nats.RootCAs(paths...)) - } -} - -func WithTimeout(timeout time.Duration) Option { - return func(o *opts) { - o.nOpts = append(o.nOpts, nats.Timeout(timeout)) - } -} - -func WithConnectionName(name string) Option { - return func(o *opts) { - o.nOpts = append(o.nOpts, nats.Name(name)) - } -} - -func WithLogger(logger *logger.Logger) Option { - return func(o *opts) { - o.log = logger - } -} diff --git a/pkg/services/notificator/nats/service.go b/pkg/services/notificator/nats/service.go deleted file mode 100644 index 9de538f2b3..0000000000 --- a/pkg/services/notificator/nats/service.go +++ /dev/null @@ -1,129 +0,0 @@ -package nats - -import ( - "context" - "errors" - "fmt" - "sync" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/nats-io/nats.go" - "go.uber.org/zap" -) - -// Writer is a NATS object notification writer. -// It handles NATS JetStream connections and allows -// sending string representation of the address to -// the NATS server. -// -// For correct operation must be created via New function. -// new(Writer) or Writer{} construction leads to undefined -// behaviour and is not safe. -type Writer struct { - js nats.JetStreamContext - nc *nats.Conn - - m sync.RWMutex - createdStreams map[string]struct{} - opts -} - -type opts struct { - log *logger.Logger - nOpts []nats.Option -} - -type Option func(*opts) - -var errConnIsClosed = errors.New("connection to the server is closed") - -// Notify sends object address's string representation to the provided topic. -// Uses first 4 bytes of object ID as a message ID to support 'exactly once' -// message delivery. -// -// Returns error only if: -// 1. underlying connection was closed and has not been established again; -// 2. NATS server could not respond that it has saved the message. -func (n *Writer) Notify(topic string, address oid.Address) error { - if !n.nc.IsConnected() { - return errConnIsClosed - } - - // use first 4 byte of the encoded string as - // message ID for the 'exactly once' delivery - messageID := address.Object().EncodeToString()[:4] - - // check if the stream was previously created - n.m.RLock() - _, created := n.createdStreams[topic] - n.m.RUnlock() - - if !created { - _, err := n.js.AddStream(&nats.StreamConfig{ - Name: topic, - }) - if err != nil { - return fmt.Errorf("could not add stream: %w", err) - } - - n.m.Lock() - n.createdStreams[topic] = struct{}{} - n.m.Unlock() - } - - _, err := n.js.Publish(topic, []byte(address.EncodeToString()), nats.MsgId(messageID)) - return err -} - -// New creates new Writer. -func New(oo ...Option) *Writer { - w := &Writer{ - createdStreams: make(map[string]struct{}), - opts: opts{ - log: &logger.Logger{Logger: zap.L()}, - nOpts: make([]nats.Option, 0, len(oo)+3), - }, - } - - for _, o := range oo { - o(&w.opts) - } - - w.opts.nOpts = append(w.opts.nOpts, - nats.NoCallbacksAfterClientClose(), // do not call callbacks when it was planned writer stop - nats.DisconnectErrHandler(func(_ *nats.Conn, err error) { - w.log.Error(logs.NatsNatsConnectionWasLost, zap.Error(err)) - }), - nats.ReconnectHandler(func(_ *nats.Conn) { - w.log.Warn(logs.NatsNatsReconnectedToTheServer) - }), - ) - - return w -} - -// Connect tries to connect to a specified NATS endpoint. -// -// Connection is closed when passed context is done. -func (n *Writer) Connect(ctx context.Context, endpoint string) error { - nc, err := nats.Connect(endpoint, n.opts.nOpts...) - if err != nil { - return fmt.Errorf("could not connect to server: %w", err) - } - - n.nc = nc - - // usage w/o options is error-free - n.js, _ = nc.JetStream() - - go func() { - <-ctx.Done() - n.opts.log.Info(logs.NatsNatsClosingConnectionAsTheContextIsDone) - - nc.Close() - }() - - return nil -} diff --git a/pkg/services/notificator/service.go b/pkg/services/notificator/service.go deleted file mode 100644 index bbf4e48238..0000000000 --- a/pkg/services/notificator/service.go +++ /dev/null @@ -1,88 +0,0 @@ -package notificator - -import ( - "context" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.uber.org/zap" -) - -// Prm groups Notificator constructor's -// parameters. All are required. -type Prm struct { - writer NotificationWriter - notificationSource NotificationSource - logger *logger.Logger -} - -// SetLogger sets a logger. -func (prm *Prm) SetLogger(v *logger.Logger) *Prm { - prm.logger = v - return prm -} - -// SetWriter sets notification writer. -func (prm *Prm) SetWriter(v NotificationWriter) *Prm { - prm.writer = v - return prm -} - -// SetNotificationSource sets notification source. -func (prm *Prm) SetNotificationSource(v NotificationSource) *Prm { - prm.notificationSource = v - return prm -} - -// Notificator is a notification producer that handles -// objects with defined notification epoch. -// -// Working client must be created via constructor New. -// Using the Client that has been created with new(Client) -// expression (or just declaring a Client variable) is unsafe -// and can lead to panic. -type Notificator struct { - w NotificationWriter - ns NotificationSource - l *logger.Logger -} - -// New creates, initializes and returns the Notificator instance. -// -// Panics if any field of the passed Prm structure is not set/set -// to nil. -func New(prm *Prm) *Notificator { - panicOnNil := func(v any, name string) { - if v == nil { - panic(fmt.Sprintf("Notificator constructor: %s is nil\n", name)) - } - } - - panicOnNil(prm.writer, "NotificationWriter") - panicOnNil(prm.notificationSource, "NotificationSource") - panicOnNil(prm.logger, "Logger") - - return &Notificator{ - w: prm.writer, - ns: prm.notificationSource, - l: prm.logger, - } -} - -// ProcessEpoch looks for all objects with defined epoch in the storage -// and passes their addresses to the NotificationWriter. -func (n *Notificator) ProcessEpoch(ctx context.Context, epoch uint64) { - logger := n.l.With(zap.Uint64("epoch", epoch)) - logger.Debug(logs.NotificatorNotificatorStartProcessingObjectNotifications) - - n.ns.Iterate(ctx, epoch, func(topic string, addr oid.Address) { - n.l.Debug(logs.NotificatorNotificatorProcessingObjectNotification, - zap.String("topic", topic), - zap.Stringer("address", addr), - ) - - n.w.Notify(topic, addr) - }) -} From a90310335d0b802700627fa91399ba1a0a4dc0f9 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 4 Jun 2024 18:27:37 +0300 Subject: [PATCH 0606/1413] [#1156] ape: Return `not found` when removing local overrides Signed-off-by: Anton Nikiforov --- pkg/services/control/server/policy_engine.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index e2e1fd7310..98daac8a66 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -174,10 +174,8 @@ func (s *Server) RemoveChainLocalOverride(_ context.Context, req *control.Remove return nil, err } - if err = s.localOverrideStorage.LocalStorage().RemoveOverride(apechain.Ingress, target, apechain.ID(req.GetBody().GetChainId())); err != nil { - if code := getCodeByLocalStorageErr(err); code != codes.NotFound { - return nil, status.Error(code, err.Error()) - } + if err = s.localOverrideStorage.LocalStorage().RemoveOverride(apechain.Ingress, target, req.GetBody().GetChainId()); err != nil { + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } resp := &control.RemoveChainLocalOverrideResponse{ Body: &control.RemoveChainLocalOverrideResponse_Body{}, @@ -200,9 +198,7 @@ func (s *Server) RemoveChainLocalOverridesByTarget(_ context.Context, req *contr } if err = s.localOverrideStorage.LocalStorage().RemoveOverridesByTarget(apechain.Ingress, target); err != nil { - if code := getCodeByLocalStorageErr(err); code != codes.NotFound { - return nil, status.Error(code, err.Error()) - } + return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } resp := &control.RemoveChainLocalOverridesByTargetResponse{ Body: &control.RemoveChainLocalOverridesByTargetResponse_Body{}, @@ -246,7 +242,8 @@ func (s *Server) ListTargetsLocalOverrides(_ context.Context, req *control.ListT } func getCodeByLocalStorageErr(err error) codes.Code { - if errors.Is(err, engine.ErrChainNotFound) || errors.Is(err, engine.ErrChainNameNotFound) { + if errors.Is(err, engine.ErrChainNotFound) || errors.Is(err, engine.ErrChainNameNotFound) || + errors.Is(err, engine.ErrResourceNotFound) { return codes.NotFound } return codes.Internal From 4edff5eea60d8106f24d138582ea3e9c1a6fbffa Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 3 Jun 2024 15:32:54 +0300 Subject: [PATCH 0607/1413] [#1157] ape: Introduce single-run chain router Signed-off-by: Airat Arifullin --- pkg/ape/router/single_pass.go | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 pkg/ape/router/single_pass.go diff --git a/pkg/ape/router/single_pass.go b/pkg/ape/router/single_pass.go new file mode 100644 index 0000000000..c0c78db769 --- /dev/null +++ b/pkg/ape/router/single_pass.go @@ -0,0 +1,55 @@ +package router + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" +) + +func newTarget(ct ape.ChainTarget) (engine.Target, error) { + var target engine.Target + switch ct.TargetType { + case ape.TargetTypeContainer: + var cid cidSDK.ID + err := cid.DecodeString(ct.Name) + if err != nil { + return target, fmt.Errorf("invalid cid format: %s", target.Name) + } + target.Type = engine.Container + case ape.TargetTypeGroup: + target.Type = engine.Group + case ape.TargetTypeNamespace: + target.Type = engine.Namespace + case ape.TargetTypeUser: + target.Type = engine.User + default: + return target, fmt.Errorf("unsupported target type: %v", ct.TargetType) + } + target.Name = ct.Name + return target, nil +} + +// SingleUseRouterWithBearerTokenChains creates chain router with inmemory storage implementation and +// fed with APE chains defined in Bearer token. +func SingleUseRouterWithBearerTokenChains(overrides []bearer.APEOverride) (engine.ChainRouter, error) { + storage := inmemory.NewInmemoryMorphRuleChainStorage() + for _, override := range overrides { + target, err := newTarget(override.Target) + if err != nil { + return nil, err + } + for i := range override.Chains { + chain := new(apechain.Chain) + if err := chain.DecodeBytes(override.Chains[i].Raw); err != nil { + return nil, fmt.Errorf("invalid ape chain: %w", err) + } + _, _, _ = storage.AddMorphRuleChain(apechain.Ingress, target, chain) + } + } + return engine.NewDefaultChainRouter(storage), nil +} From 04a3f891fda3f01e7f8eb4a55b5ec8f3b5c9f4eb Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 29 May 2024 11:11:45 +0300 Subject: [PATCH 0608/1413] [#1157] object: Make APE checker use Bearer-token's APE overrides Signed-off-by: Airat Arifullin --- cmd/frostfs-node/object.go | 1 + pkg/services/object/acl/v2/service.go | 4 + pkg/services/object/ape/checker.go | 90 +++++- pkg/services/object/ape/checker_test.go | 414 ++++++++++++++---------- pkg/services/object/ape/service.go | 14 + pkg/services/object/request_context.go | 3 + 6 files changed, 358 insertions(+), 168 deletions(-) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 9d1e2218f3..907e517a54 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -463,6 +463,7 @@ func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *object objectAPE.NewStorageEngineHeaderProvider(c.cfgObject.cfgLocalStorage.localStorage, c.cfgObject.getSvc), c.shared.frostfsidClient, c.netMapSource, + c.cfgNetmap.state, c.cfgObject.cnrSource, c.binPublicKey, ), diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 1f1c275cff..3e128836fc 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -118,6 +118,7 @@ func (w *wrappedGetObjectStream) Context() context.Context { SenderKey: w.requestInfo.SenderKey(), Role: w.requestInfo.RequestRole(), SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + BearerToken: w.requestInfo.Bearer(), }) } @@ -143,6 +144,7 @@ func (w *wrappedRangeStream) Context() context.Context { SenderKey: w.requestInfo.SenderKey(), Role: w.requestInfo.RequestRole(), SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + BearerToken: w.requestInfo.Bearer(), }) } @@ -168,6 +170,7 @@ func (w *wrappedSearchStream) Context() context.Context { SenderKey: w.requestInfo.SenderKey(), Role: w.requestInfo.RequestRole(), SoftAPECheck: w.requestInfo.IsSoftAPECheck(), + BearerToken: w.requestInfo.Bearer(), }) } @@ -479,6 +482,7 @@ func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { SenderKey: reqInfo.SenderKey(), Role: reqInfo.RequestRole(), SoftAPECheck: reqInfo.IsSoftAPECheck(), + BearerToken: reqInfo.Bearer(), }) } diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index c39f922f79..ee71e6e1dd 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -2,13 +2,17 @@ package ape import ( "context" + "crypto/ecdsa" "errors" "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -23,16 +27,18 @@ type checkerImpl struct { headerProvider HeaderProvider frostFSIDClient frostfsidcore.SubjectProvider nm netmap.Source + st netmap.State cnrSource container.Source nodePK []byte } -func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider, nm netmap.Source, cnrSource container.Source, nodePK []byte) Checker { +func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider, nm netmap.Source, st netmap.State, cnrSource container.Source, nodePK []byte) Checker { return &checkerImpl{ chainRouter: chainRouter, headerProvider: headerProvider, frostFSIDClient: frostFSIDClient, nm: nm, + st: st, cnrSource: cnrSource, nodePK: nodePK, } @@ -67,9 +73,69 @@ type Prm struct { // If true, object headers will not retrieved from storage engine. WithoutHeaderRequest bool + + // The request's bearer token. It is used in order to check APE overrides with the token. + BearerToken *bearer.Token } -var errMissingOID = errors.New("object ID is not set") +var ( + errMissingOID = errors.New("object ID is not set") + errInvalidTargetType = errors.New("bearer token defines non-container target override") + errBearerExpired = errors.New("bearer token has expired") + errBearerInvalidSignature = errors.New("bearer token has invalid signature") + errBearerInvalidContainerID = errors.New("bearer token was created for another container") + errBearerNotSignedByOwner = errors.New("bearer token is not signed by the container owner") + errBearerInvalidOwner = errors.New("bearer token owner differs from the request sender") +) + +// isValidBearer checks whether bearer token was correctly signed by authorized +// entity. This method might be defined on whole ACL service because it will +// require fetching current epoch to check lifetime. +func isValidBearer(token *bearer.Token, ownerCnr user.ID, containerID cid.ID, publicKey *keys.PublicKey, st netmap.State) error { + if token == nil { + return nil + } + + // 1. First check token lifetime. Simplest verification. + if token.InvalidAt(st.CurrentEpoch()) { + return errBearerExpired + } + + // 2. Then check if bearer token is signed correctly. + if !token.VerifySignature() { + return errBearerInvalidSignature + } + + // 3. Then check if container is either empty or equal to the container in the request. + apeOverride := token.APEOverride() + if apeOverride.Target.TargetType != ape.TargetTypeContainer { + return errInvalidTargetType + } + + var targetCnr cid.ID + err := targetCnr.DecodeString(apeOverride.Target.Name) + if err != nil { + return fmt.Errorf("invalid cid format: %s", apeOverride.Target.Name) + } + if !containerID.Equals(targetCnr) { + return errBearerInvalidContainerID + } + + // 4. Then check if container owner signed this token. + if !bearer.ResolveIssuer(*token).Equals(ownerCnr) { + return errBearerNotSignedByOwner + } + + // 5. Then check if request sender has rights to use this token. + var usrSender user.ID + user.IDFromKey(&usrSender, (ecdsa.PublicKey)(*publicKey)) + + if !token.AssertUser(usrSender) { + return errBearerInvalidOwner + } + + return nil +} // CheckAPE checks if a request or a response is permitted creating an ape request and passing // it to chain router. @@ -99,6 +165,26 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { return err } + if prm.BearerToken != nil && !prm.BearerToken.Impersonate() { + if err := isValidBearer(prm.BearerToken, prm.ContainerOwner, prm.Container, pub, c.st); err != nil { + return fmt.Errorf("bearer token validation error: %w", err) + } + btRouter, err := router.SingleUseRouterWithBearerTokenChains([]bearer.APEOverride{prm.BearerToken.APEOverride()}) + if err != nil { + return err + } + status, found, err := btRouter.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(prm.Container.EncodeToString()), r) + if err != nil { + return err + } + if found && status == apechain.Allow { + return nil + } + if status != apechain.NoRuleFound { + return fmt.Errorf("bearer token: method %s: %s", prm.Method, status) + } + } + rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), nil) status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, rt, r) if err != nil { diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index ddb3361277..09954602c4 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -2,6 +2,7 @@ package ape import ( "context" + "crypto/ecdsa" "encoding/hex" "errors" "fmt" @@ -12,6 +13,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" + apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -228,170 +231,249 @@ func (f *frostfsIDProviderMock) GetSubjectExtended(key util.Uint160) (*client.Su return v, nil } +var apeCheckTestCases = []struct { + name string + container string + object *string + methods []string + header testHeader + containerRules []chain.Rule + expectAPEErr bool +}{ + { + name: "oid required requests are allowed", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + containerRules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + }, + }, + }, + { + name: "oid optional requests are allowed", + container: containerID, + methods: methodsOptionalOID, + containerRules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{Names: methodsOptionalOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + }, + }, + }, + { + name: "oid required requests are denied", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + containerRules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + }, + }, + expectAPEErr: true, + }, + { + name: "oid required requests are denied by an attribute", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "attribute_value", + }, + }, + }, + fromHeaderProvider: true, + }, + containerRules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringLike, + Kind: chain.KindResource, + Key: "attr1", + Value: "attribute*", + }, + }, + }, + }, + expectAPEErr: true, + }, + { + name: "oid required requests are denied by sender", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "attribute_value", + }, + }, + }, + fromHeaderProvider: true, + }, + containerRules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringLike, + Kind: chain.KindRequest, + Key: nativeschema.PropertyKeyActorPublicKey, + Value: senderKey, + }, + }, + }, + }, + expectAPEErr: true, + }, + { + name: "optional oid requests reached quota limit by an attribute", + container: containerID, + methods: methodsOptionalOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + payloadSize: 1000, + }, + fromRequestResponseHeader: true, + }, + containerRules: []chain.Rule{ + { + Status: chain.QuotaLimitReached, + Actions: chain.Actions{Names: methodsOptionalOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Kind: chain.KindResource, + Key: nativeschema.PropertyKeyObjectPayloadLength, + Value: "1000", + }, + }, + }, + }, + expectAPEErr: true, + }, +} + +type stMock struct{} + +func (m *stMock) CurrentEpoch() uint64 { + return 8 +} + +func TestAPECheck_BearerTokenOverrides(t *testing.T) { + for _, test := range apeCheckTestCases { + t.Run(test.name, func(t *testing.T) { + chain := chain.Chain{ + Rules: test.containerRules, + MatchType: chain.MatchTypeFirstMatch, + } + chainSDK := apeSDK.Chain{ + Raw: chain.Bytes(), + } + bt := new(bearer.Token) + bt.SetIat(1) + bt.SetExp(10) + bt.SetAPEOverride(bearer.APEOverride{ + Target: apeSDK.ChainTarget{ + TargetType: apeSDK.TargetTypeContainer, + Name: test.container, + }, + Chains: []apeSDK.Chain{chainSDK}, + }) + bt.Sign(senderPrivateKey.PrivateKey) + var cnrOwner user.ID + user.IDFromKey(&cnrOwner, (ecdsa.PublicKey)(*senderPrivateKey.PublicKey())) + + for _, method := range test.methods { + t.Run(method, func(t *testing.T) { + headerProvider := newHeaderProviderMock() + frostfsidProvider := newFrostfsIDProviderMock(t) + + cnr := newContainerIDSDK(t, test.container) + obj := newObjectIDSDK(t, test.object) + + ls := inmemory.NewInmemoryLocalStorage() + ms := inmemory.NewInmemoryMorphRuleChainStorage() + r := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) + + checker := NewChecker(r, headerProvider, frostfsidProvider, nil, &stMock{}, nil, nil) + + prm := Prm{ + Method: method, + Container: cnr, + Object: obj, + Role: role, + ContainerOwner: cnrOwner, + SenderKey: senderKey, + BearerToken: bt, + } + + var headerObjSDK *objectSDK.Object + if test.header.headerObjSDK != nil { + headerObjSDK = newHeaderObjectSDK(cnr, obj, test.header.headerObjSDK) + if test.header.fromHeaderProvider { + require.NotNil(t, obj, "oid is required if a header is expected to be found in header provider") + headerProvider.addHeader(cnr, *obj, headerObjSDK) + } else if test.header.fromRequestResponseHeader { + prm.Header = headerObjSDK.ToV2().GetHeader() + } + } + + err := checker.CheckAPE(context.Background(), prm) + if test.expectAPEErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } + }) + } +} + func TestAPECheck(t *testing.T) { - for _, test := range []struct { - name string - container string - object *string - methods []string - header testHeader - containerRules []chain.Rule - expectAPEErr bool - }{ - { - name: "oid required requests are allowed", - container: containerID, - object: stringPtr(objectID), - methods: methodsRequiredOID, - containerRules: []chain.Rule{ - { - Status: chain.Allow, - Actions: chain.Actions{Names: methodsRequiredOID}, - Resources: chain.Resources{ - Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, - }, - }, - }, - }, - { - name: "oid optional requests are allowed", - container: containerID, - methods: methodsOptionalOID, - containerRules: []chain.Rule{ - { - Status: chain.Allow, - Actions: chain.Actions{Names: methodsOptionalOID}, - Resources: chain.Resources{ - Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, - }, - }, - }, - }, - { - name: "oid required requests are denied", - container: containerID, - object: stringPtr(objectID), - methods: methodsRequiredOID, - containerRules: []chain.Rule{ - { - Status: chain.AccessDenied, - Actions: chain.Actions{Names: methodsRequiredOID}, - Resources: chain.Resources{ - Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, - }, - }, - }, - expectAPEErr: true, - }, - { - name: "oid required requests are denied by an attribute", - container: containerID, - object: stringPtr(objectID), - methods: methodsRequiredOID, - header: testHeader{ - headerObjSDK: &headerObjectSDKParams{ - attributes: []struct { - key string - val string - }{ - { - key: "attr1", - val: "attribute_value", - }, - }, - }, - fromHeaderProvider: true, - }, - containerRules: []chain.Rule{ - { - Status: chain.AccessDenied, - Actions: chain.Actions{Names: methodsRequiredOID}, - Resources: chain.Resources{ - Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, - }, - Any: true, - Condition: []chain.Condition{ - { - Op: chain.CondStringLike, - Kind: chain.KindResource, - Key: "attr1", - Value: "attribute*", - }, - }, - }, - }, - expectAPEErr: true, - }, - { - name: "oid required requests are denied by sender", - container: containerID, - object: stringPtr(objectID), - methods: methodsRequiredOID, - header: testHeader{ - headerObjSDK: &headerObjectSDKParams{ - attributes: []struct { - key string - val string - }{ - { - key: "attr1", - val: "attribute_value", - }, - }, - }, - fromHeaderProvider: true, - }, - containerRules: []chain.Rule{ - { - Status: chain.AccessDenied, - Actions: chain.Actions{Names: methodsRequiredOID}, - Resources: chain.Resources{ - Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, - }, - Any: true, - Condition: []chain.Condition{ - { - Op: chain.CondStringLike, - Kind: chain.KindRequest, - Key: nativeschema.PropertyKeyActorPublicKey, - Value: senderKey, - }, - }, - }, - }, - expectAPEErr: true, - }, - { - name: "optional oid requests reached quota limit by an attribute", - container: containerID, - methods: methodsOptionalOID, - header: testHeader{ - headerObjSDK: &headerObjectSDKParams{ - payloadSize: 1000, - }, - fromRequestResponseHeader: true, - }, - containerRules: []chain.Rule{ - { - Status: chain.QuotaLimitReached, - Actions: chain.Actions{Names: methodsOptionalOID}, - Resources: chain.Resources{ - Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, - }, - Any: true, - Condition: []chain.Condition{ - { - Op: chain.CondStringEquals, - Kind: chain.KindResource, - Key: nativeschema.PropertyKeyObjectPayloadLength, - Value: "1000", - }, - }, - }, - }, - expectAPEErr: true, - }, - } { + for _, test := range apeCheckTestCases { t.Run(test.name, func(t *testing.T) { for _, method := range test.methods { t.Run(method, func(t *testing.T) { @@ -411,7 +493,7 @@ func TestAPECheck(t *testing.T) { router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) - checker := NewChecker(router, headerProvider, frostfsidProvider, nil, nil, nil) + checker := NewChecker(router, headerProvider, frostfsidProvider, nil, &stMock{}, nil, nil) prm := Prm{ Method: method, @@ -544,7 +626,7 @@ func TestPutECChunk(t *testing.T) { }, } - checker := NewChecker(router, headerProvider, frostfsidProvider, nm, cs, node1Key.PublicKey().Bytes()) + checker := NewChecker(router, headerProvider, frostfsidProvider, nm, &stMock{}, cs, node1Key.PublicKey().Bytes()) ecParentID := oidtest.ID() chunkHeader := newHeaderObjectSDK(cnr, obj, nil).ToV2().GetHeader() @@ -586,7 +668,7 @@ func TestPutECChunk(t *testing.T) { t.Run("access allowed for non container node", func(t *testing.T) { otherKey, err := keys.NewPrivateKey() require.NoError(t, err) - checker = NewChecker(router, headerProvider, frostfsidProvider, nm, cs, otherKey.PublicKey().Bytes()) + checker = NewChecker(router, headerProvider, frostfsidProvider, nm, &stMock{}, cs, otherKey.PublicKey().Bytes()) prm := Prm{ Method: nativeschema.MethodPutObject, Container: cnr, diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 63c2a99091..609b117d04 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -13,6 +13,7 @@ import ( getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -88,6 +89,8 @@ type getStreamBasicChecker struct { role string softAPECheck bool + + bearerToken *bearer.Token } func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { @@ -107,6 +110,7 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { ContainerOwner: g.containerOwner, Role: g.role, SoftAPECheck: g.softAPECheck, + BearerToken: g.bearerToken, } if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { @@ -149,6 +153,7 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, WithoutHeaderRequest: true, + BearerToken: reqCtx.BearerToken, }) if err != nil { return toStatusErr(err) @@ -161,6 +166,7 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt senderKey: reqCtx.SenderKey, role: nativeSchemaRole(reqCtx.Role), softAPECheck: reqCtx.SoftAPECheck, + bearerToken: reqCtx.BearerToken, }) } @@ -192,6 +198,7 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR ContainerOwner: reqCtx.ContainerOwner, Role: nativeSchemaRole(reqCtx.Role), SoftAPECheck: reqCtx.SoftAPECheck, + BearerToken: reqCtx.BearerToken, } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -236,6 +243,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, WithoutHeaderRequest: true, + BearerToken: reqCtx.BearerToken, }) if err != nil { return nil, toStatusErr(err) @@ -275,6 +283,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, + BearerToken: reqCtx.BearerToken, }) if err != nil { return nil, toStatusErr(err) @@ -303,6 +312,7 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, + BearerToken: reqCtx.BearerToken, }) if err != nil { return toStatusErr(err) @@ -331,6 +341,7 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, + BearerToken: reqCtx.BearerToken, }) if err != nil { return nil, toStatusErr(err) @@ -364,6 +375,7 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, + BearerToken: reqCtx.BearerToken, }) if err != nil { return toStatusErr(err) @@ -392,6 +404,7 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, + BearerToken: reqCtx.BearerToken, } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -430,6 +443,7 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, + BearerToken: reqCtx.BearerToken, } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { diff --git a/pkg/services/object/request_context.go b/pkg/services/object/request_context.go index 6a0965b408..95d4c9d935 100644 --- a/pkg/services/object/request_context.go +++ b/pkg/services/object/request_context.go @@ -1,6 +1,7 @@ package object import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) @@ -20,4 +21,6 @@ type RequestContext struct { Role acl.Role SoftAPECheck bool + + BearerToken *bearer.Token } From 239323eeef0bf518630d4acb3e8b92d7b2629f8b Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 29 May 2024 11:18:31 +0300 Subject: [PATCH 0609/1413] [#1157] tree: Make tree service use Bearer token's APE overrides Signed-off-by: Airat Arifullin --- cmd/frostfs-node/tree.go | 1 + pkg/services/tree/ape.go | 121 +++++++++++++++++++++++++++++---- pkg/services/tree/options.go | 7 ++ pkg/services/tree/signature.go | 2 +- 4 files changed, 118 insertions(+), 13 deletions(-) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index 49ecb6fdc8..daaaa64a24 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -66,6 +66,7 @@ func initTreeService(c *cfg) { tree.WithAuthorizedKeys(treeConfig.AuthorizedKeys()), tree.WithMetrics(c.metricsCollector.TreeService()), tree.WithAPERouter(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine), + tree.WithNetmapState(c.cfgNetmap.state), ) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index eabc02bd70..475567c5f8 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -2,18 +2,25 @@ package tree import ( "context" + "crypto/ecdsa" "encoding/hex" + "errors" "fmt" "net" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" @@ -22,20 +29,25 @@ import ( "google.golang.org/grpc/peer" ) -func (s *Service) checkAPE(ctx context.Context, container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error { - namespace := "" - cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns") - if hasNamespace { - namespace = cntNamespace - } +var ( + errInvalidTargetType = errors.New("bearer token defines non-container target override") + errBearerExpired = errors.New("bearer token has expired") + errBearerInvalidSignature = errors.New("bearer token has invalid signature") + errBearerInvalidContainerID = errors.New("bearer token was created for another container") + errBearerNotSignedByOwner = errors.New("bearer token is not signed by the container owner") + errBearerInvalidOwner = errors.New("bearer token owner differs from the request sender") +) +func (s *Service) newAPERequest(ctx context.Context, namespace string, + cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey, +) (aperequest.Request, error) { schemaMethod, err := converter.SchemaMethodFromACLOperation(operation) if err != nil { - return apeErr(err) + return aperequest.Request{}, err } schemaRole, err := converter.SchemaRoleFromACLRole(role) if err != nil { - return apeErr(err) + return aperequest.Request{}, err } reqProps := map[string]string{ nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(publicKey.Bytes()), @@ -43,7 +55,7 @@ func (s *Service) checkAPE(ctx context.Context, container *core.Container, cid c } reqProps, err = s.fillWithUserClaimTags(reqProps, publicKey) if err != nil { - return apeErr(err) + return aperequest.Request{}, err } if p, ok := peer.FromContext(ctx); ok { if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok { @@ -58,11 +70,96 @@ func (s *Service) checkAPE(ctx context.Context, container *core.Container, cid c resourceName = fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainerObjects, namespace, cid.EncodeToString()) } - request := aperequest.NewRequest( + return aperequest.NewRequest( schemaMethod, aperequest.NewResource(resourceName, make(map[string]string)), reqProps, - ) + ), nil +} + +// isValidBearer checks whether bearer token was correctly signed by authorized +// entity. This method might be defined on whole ACL service because it will +// require fetching current epoch to check lifetime. +func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKey *keys.PublicKey, st netmap.State) error { + if token == nil { + return nil + } + + // 1. First check token lifetime. Simplest verification. + if token.InvalidAt(st.CurrentEpoch()) { + return errBearerExpired + } + + // 2. Then check if bearer token is signed correctly. + if !token.VerifySignature() { + return errBearerInvalidSignature + } + + // 3. Then check if container is either empty or equal to the container in the request. + apeOverride := token.APEOverride() + if apeOverride.Target.TargetType != ape.TargetTypeContainer { + return errInvalidTargetType + } + + var targetCnr cid.ID + err := targetCnr.DecodeString(apeOverride.Target.Name) + if err != nil { + return fmt.Errorf("invalid cid format: %s", apeOverride.Target.Name) + } + if !cntID.Equals(targetCnr) { + return errBearerInvalidContainerID + } + + // 4. Then check if container owner signed this token. + if !bearer.ResolveIssuer(*token).Equals(ownerCnr) { + return errBearerNotSignedByOwner + } + + // 5. Then check if request sender has rights to use this token. + var usrSender user.ID + user.IDFromKey(&usrSender, (ecdsa.PublicKey)(*publicKey)) + + if !token.AssertUser(usrSender) { + return errBearerInvalidOwner + } + + return nil +} + +func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, + container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey, +) error { + namespace := "" + cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns") + if hasNamespace { + namespace = cntNamespace + } + + request, err := s.newAPERequest(ctx, namespace, cid, operation, role, publicKey) + if err != nil { + return apeErr(err) + } + + if bt != nil && !bt.Impersonate() { + if err := isValidBearer(bt, container.Value.Owner(), cid, publicKey, s.state); err != nil { + return fmt.Errorf("bearer validation error: %w", err) + } + btRouter, err := router.SingleUseRouterWithBearerTokenChains([]bearer.APEOverride{bt.APEOverride()}) + if err != nil { + return apeErr(err) + } + status, found, err := btRouter.IsAllowed(apechain.Ingress, engine.NewRequestTargetWithContainer(cid.EncodeToString()), request) + if err != nil { + return apeErr(err) + } + if found && status == apechain.Allow { + return nil + } + if status != apechain.NoRuleFound { + err = fmt.Errorf("access to operation %s is denied by access policy engine (bearer token): %s", request.Operation(), status.String()) + return apeErr(err) + } + } rt := engine.NewRequestTargetExtended(namespace, cid.EncodeToString(), fmt.Sprintf("%s:%s", namespace, publicKey.Address()), nil) status, found, err := s.router.IsAllowed(apechain.Ingress, rt, request) @@ -72,7 +169,7 @@ func (s *Service) checkAPE(ctx context.Context, container *core.Container, cid c if found && status == apechain.Allow { return nil } - err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", schemaMethod, status.String()) + err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", request.Operation(), status.String()) return apeErr(err) } diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index a99ba60467..ea55399386 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -29,6 +29,7 @@ type cfg struct { log *logger.Logger key *ecdsa.PrivateKey rawPub []byte + state netmap.State nmSource netmap.Source cnrSource ContainerSource frostfsidSubjectProvider frostfsidcore.SubjectProvider @@ -156,3 +157,9 @@ func WithAPERouter(router policyengine.ChainRouter) Option { c.router = router } } + +func WithNetmapState(state netmap.State) Option { + return func(c *cfg) { + c.state = state + } +} diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 0445ccfabc..58cab659fc 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -84,7 +84,7 @@ func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, // FIXME(@aarifullin): tree service temporiraly performs APE checks on // object verbs, because tree verbs have not been introduced yet. if basicACL == 0x0 { - return s.checkAPE(ctx, cnr, cid, op, role, pubKey) + return s.checkAPE(ctx, bt, cnr, cid, op, role, pubKey) } if !basicACL.IsOpAllowed(op, role) { From a0c588263bd550bb131a8ed2f1a5ad318811018c Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 3 Jun 2024 16:13:29 +0300 Subject: [PATCH 0610/1413] [#1157] cli: Support adding APE overrides to Bearer token Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/bearer/create.go | 24 +++- .../modules/bearer/generate_override.go | 115 ++++++++++++++++++ cmd/frostfs-cli/modules/bearer/root.go | 1 + 3 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 cmd/frostfs-cli/modules/bearer/generate_override.go diff --git a/cmd/frostfs-cli/modules/bearer/create.go b/cmd/frostfs-cli/modules/bearer/create.go index 8a7500db30..d94b39207c 100644 --- a/cmd/frostfs-cli/modules/bearer/create.go +++ b/cmd/frostfs-cli/modules/bearer/create.go @@ -15,10 +15,12 @@ import ( eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/spf13/cobra" + "github.com/spf13/viper" ) const ( eaclFlag = "eacl" + apeFlag = "ape" issuedAtFlag = "issued-at" notValidBeforeFlag = "not-valid-before" ownerFlag = "owner" @@ -37,10 +39,17 @@ In this case --` + commonflags.RPC + ` flag should be specified and the epoch in is set to current epoch + n. `, Run: createToken, + PersistentPreRun: func(cmd *cobra.Command, _ []string) { + ff := cmd.Flags() + + _ = viper.BindPFlag(commonflags.WalletPath, ff.Lookup(commonflags.WalletPath)) + _ = viper.BindPFlag(commonflags.Account, ff.Lookup(commonflags.Account)) + }, } func init() { - createCmd.Flags().StringP(eaclFlag, "e", "", "Path to the extended ACL table (mutually exclusive with --impersonate flag)") + createCmd.Flags().StringP(eaclFlag, "e", "", "Path to the extended ACL table (mutually exclusive with --impersonate and --ape flag)") + createCmd.Flags().StringP(apeFlag, "a", "", "Path to the JSON-encoded APE override (mutually exclusive with --impersonate and --eacl flag)") createCmd.Flags().StringP(issuedAtFlag, "i", "+0", "Epoch to issue token at") createCmd.Flags().StringP(notValidBeforeFlag, "n", "+0", "Not valid before epoch") createCmd.Flags().StringP(commonflags.ExpireAt, "x", "", "The last active epoch for the token") @@ -49,10 +58,13 @@ func init() { createCmd.Flags().Bool(jsonFlag, false, "Output token in JSON") createCmd.Flags().Bool(impersonateFlag, false, "Mark token as impersonate to consider the token signer as the request owner (mutually exclusive with --eacl flag)") createCmd.Flags().StringP(commonflags.RPC, commonflags.RPCShorthand, commonflags.RPCDefault, commonflags.RPCUsage) + createCmd.Flags().StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage) + createCmd.Flags().StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage) - createCmd.MarkFlagsMutuallyExclusive(eaclFlag, impersonateFlag) + createCmd.MarkFlagsMutuallyExclusive(eaclFlag, apeFlag, impersonateFlag) _ = cobra.MarkFlagFilename(createCmd.Flags(), eaclFlag) + _ = cobra.MarkFlagFilename(createCmd.Flags(), apeFlag) _ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.ExpireAt) _ = cobra.MarkFlagRequired(createCmd.Flags(), ownerFlag) @@ -119,6 +131,14 @@ func createToken(cmd *cobra.Command, _ []string) { b.SetEACLTable(*table) } + apePath, _ := cmd.Flags().GetString(apeFlag) + if apePath != "" { + var apeOverride bearer.APEOverride + raw, err := os.ReadFile(apePath) + commonCmd.ExitOnErr(cmd, "can't read APE rules: %w", err) + commonCmd.ExitOnErr(cmd, "can't parse APE rules: %w", json.Unmarshal(raw, &apeOverride)) + b.SetAPEOverride(apeOverride) + } var data []byte toJSON, _ := cmd.Flags().GetBool(jsonFlag) diff --git a/cmd/frostfs-cli/modules/bearer/generate_override.go b/cmd/frostfs-cli/modules/bearer/generate_override.go new file mode 100644 index 0000000000..482c0027e1 --- /dev/null +++ b/cmd/frostfs-cli/modules/bearer/generate_override.go @@ -0,0 +1,115 @@ +package bearer + +import ( + "errors" + "fmt" + "os" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "github.com/spf13/cobra" +) + +var ( + errChainIDCannotBeEmpty = errors.New("chain id cannot be empty") + errRuleIsNotParsed = errors.New("rule is not passed") +) + +const ( + chainIDFlag = "chain-id" + chainIDHexFlag = "chain-id-hex" + ruleFlag = "rule" + pathFlag = "path" + outputFlag = "output" +) + +var generateAPEOverrideCmd = &cobra.Command{ + Use: "generate-ape-override", + Short: "Generate APE override.", + Long: `Generate APE override by target and APE chains. Util command. + +Generated APE override can be dumped to a file in JSON format that is passed to +"create" command. +`, + Run: genereateAPEOverride, +} + +func genereateAPEOverride(cmd *cobra.Command, _ []string) { + c := parseChain(cmd) + + targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag) + var cid cidSDK.ID + commonCmd.ExitOnErr(cmd, "invalid cid format: %w", cid.DecodeString(targetCID)) + + override := &bearer.APEOverride{ + Target: apeSDK.ChainTarget{ + TargetType: apeSDK.TargetTypeContainer, + Name: targetCID, + }, + Chains: []apeSDK.Chain{ + { + Raw: c.Bytes(), + }, + }, + } + + overrideMarshalled, err := override.MarshalJSON() + commonCmd.ExitOnErr(cmd, "failed to marshal APE override: %w", err) + + outputPath, _ := cmd.Flags().GetString(outputFlag) + if outputPath != "" { + err := os.WriteFile(outputPath, []byte(overrideMarshalled), 0o644) + commonCmd.ExitOnErr(cmd, "dump error: %w", err) + } else { + fmt.Print("\n") + fmt.Println(string(overrideMarshalled)) + } +} + +func init() { + ff := generateAPEOverrideCmd.Flags() + + ff.StringP(commonflags.CIDFlag, "", "", "Target container ID.") + _ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.CIDFlag) + + ff.StringArray(ruleFlag, []string{}, "Rule statement") + ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") + ff.String(chainIDFlag, "", "Assign ID to the parsed chain") + ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + + ff.String(outputFlag, "", "Output path to dump result JSON-encoded APE override") + _ = cobra.MarkFlagFilename(createCmd.Flags(), outputFlag) +} + +func parseChainID(cmd *cobra.Command) apechain.ID { + chainID, _ := cmd.Flags().GetString(chainIDFlag) + if chainID == "" { + commonCmd.ExitOnErr(cmd, "read chain id error: %w", + errChainIDCannotBeEmpty) + } + return apechain.ID(chainID) +} + +func parseChain(cmd *cobra.Command) *apechain.Chain { + chain := new(apechain.Chain) + + if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { + commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules)) + } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { + commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) + } else { + commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed) + } + + chain.ID = parseChainID(cmd) + + cmd.Println("Parsed chain:") + parseutil.PrintHumanReadableAPEChain(cmd, chain) + + return chain +} diff --git a/cmd/frostfs-cli/modules/bearer/root.go b/cmd/frostfs-cli/modules/bearer/root.go index 200d096acf..fa6aef6fb0 100644 --- a/cmd/frostfs-cli/modules/bearer/root.go +++ b/cmd/frostfs-cli/modules/bearer/root.go @@ -11,4 +11,5 @@ var Cmd = &cobra.Command{ func init() { Cmd.AddCommand(createCmd) + Cmd.AddCommand(generateAPEOverrideCmd) } From e7d479f4c2bb0af1b1204a6acf13ce72a8b4f1ea Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 6 Jun 2024 19:00:07 +0300 Subject: [PATCH 0611/1413] [#1166] blobovnicza: Return NoSpaceLeft error instead of syscall.ENOSPC Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobovnicza/delete.go | 6 ++++++ pkg/local_object_storage/blobovnicza/errors.go | 6 ++++++ pkg/local_object_storage/blobovnicza/move.go | 15 +++++++++++++-- pkg/local_object_storage/blobovnicza/put.go | 4 ++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 pkg/local_object_storage/blobovnicza/errors.go diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index ab8575ad7a..5d6787897e 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -2,6 +2,8 @@ package blobovnicza import ( "context" + "errors" + "syscall" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" @@ -97,5 +99,9 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err b.itemDeleted(recordSize) } + if errors.Is(err, syscall.ENOSPC) { + err = ErrNoSpace + } + return DeleteRes{}, err } diff --git a/pkg/local_object_storage/blobovnicza/errors.go b/pkg/local_object_storage/blobovnicza/errors.go new file mode 100644 index 0000000000..cff8c17766 --- /dev/null +++ b/pkg/local_object_storage/blobovnicza/errors.go @@ -0,0 +1,6 @@ +package blobovnicza + +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + +// ErrNoSpace returned if blobovnicza failed to perform an operation because of syscall.ENOSPC. +var ErrNoSpace = logicerr.New("no space left on device with blobovnicza") diff --git a/pkg/local_object_storage/blobovnicza/move.go b/pkg/local_object_storage/blobovnicza/move.go index 255198f665..420e22a487 100644 --- a/pkg/local_object_storage/blobovnicza/move.go +++ b/pkg/local_object_storage/blobovnicza/move.go @@ -2,7 +2,9 @@ package blobovnicza import ( "context" + "errors" "fmt" + "syscall" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -29,7 +31,7 @@ func (b *Blobovnicza) PutMoveInfo(ctx context.Context, prm MoveInfo) error { key := addressKey(prm.Address) - return b.boltDB.Update(func(tx *bbolt.Tx) error { + err := b.boltDB.Update(func(tx *bbolt.Tx) error { bucket, err := tx.CreateBucketIfNotExists(incompletedMoveBucketName) if err != nil { return err @@ -41,6 +43,11 @@ func (b *Blobovnicza) PutMoveInfo(ctx context.Context, prm MoveInfo) error { return nil }) + + if errors.Is(err, syscall.ENOSPC) { + err = ErrNoSpace + } + return err } func (b *Blobovnicza) DropMoveInfo(ctx context.Context, address oid.Address) error { @@ -53,7 +60,7 @@ func (b *Blobovnicza) DropMoveInfo(ctx context.Context, address oid.Address) err key := addressKey(address) - return b.boltDB.Update(func(tx *bbolt.Tx) error { + err := b.boltDB.Update(func(tx *bbolt.Tx) error { bucket := tx.Bucket(incompletedMoveBucketName) if bucket == nil { return nil @@ -72,6 +79,10 @@ func (b *Blobovnicza) DropMoveInfo(ctx context.Context, address oid.Address) err return nil }) + if errors.Is(err, syscall.ENOSPC) { + err = ErrNoSpace + } + return err } func (b *Blobovnicza) ListMoveInfo(ctx context.Context) ([]MoveInfo, error) { diff --git a/pkg/local_object_storage/blobovnicza/put.go b/pkg/local_object_storage/blobovnicza/put.go index 9af8a93fe3..ff223ba365 100644 --- a/pkg/local_object_storage/blobovnicza/put.go +++ b/pkg/local_object_storage/blobovnicza/put.go @@ -2,7 +2,9 @@ package blobovnicza import ( "context" + "errors" "fmt" + "syscall" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -95,6 +97,8 @@ func (b *Blobovnicza) Put(ctx context.Context, prm PutPrm) (PutRes, error) { }) if err == nil { b.itemAdded(recordSize) + } else if errors.Is(err, syscall.ENOSPC) { + err = ErrNoSpace } return PutRes{}, err From 6cf512e574694cdbdcbc88f114b8a45a4843c526 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 6 Jun 2024 19:01:25 +0300 Subject: [PATCH 0612/1413] [#1166] blobovniczatree: Handle blobovnicza's NoSpaceLeft error Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobstor/blobovniczatree/put.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 96c4db67d3..76c4953e4f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -2,6 +2,7 @@ package blobovniczatree import ( "context" + "errors" "path/filepath" "time" @@ -108,7 +109,9 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } - + if errors.Is(err, blobovnicza.ErrNoSpace) { + i.AllFull = true + } return false, nil } From 069c1559ccd083cac87fb36d7b0cfc1168a5e393 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 7 Jun 2024 16:18:31 +0300 Subject: [PATCH 0613/1413] [#1164] cli: Improve `object nodes` performance Do complex EC object parts flatten concurrently. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 79 ++++++++++++++++++------- 1 file changed, 59 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index b5f839eb8f..cdce7cd7b0 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -33,7 +33,10 @@ const ( verifyPresenceAllFlag = "verify-presence-all" ) -var errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint") +var ( + errNoAvailableEndpoint = errors.New("failed to create client: no available endpoint") + errMalformedComplexObject = errors.New("object consists of EC and non EC parts") +) type phyObject struct { containerID cid.ID @@ -180,30 +183,66 @@ func getCompexObjectMembers(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, members []oid.ID, prmHead internalclient.HeadObjectPrm) []phyObject { result := make([]phyObject, 0, len(members)) + var resultGuard sync.Mutex + + if len(members) == 0 { + return result + } + + prmHead.SetRawFlag(true) // to get an error instead of whole object + + first := members[0] var addrObj oid.Address addrObj.SetContainer(cnrID) - prmHead.SetRawFlag(true) // to get an error instead of whole object - for _, partObjID := range members { - addrObj.SetObject(partObjID) - prmHead.SetAddress(addrObj) + addrObj.SetObject(first) + prmHead.SetAddress(addrObj) - _, err := internalclient.HeadObject(cmd.Context(), prmHead) - var ecInfoError *objectSDK.ECInfoError - if errors.As(err, &ecInfoError) { - chunks := getECObjectChunks(cmd, cnrID, partObjID, ecInfoError) - result = append(result, chunks...) - continue - } else if err == nil { // not EC object, so all members must be phy objects - for _, member := range members { - result = append(result, phyObject{ - containerID: cnrID, - objectID: member, - }) - } - break + _, err := internalclient.HeadObject(cmd.Context(), prmHead) + var ecInfoError *objectSDK.ECInfoError + if errors.As(err, &ecInfoError) { + chunks := getECObjectChunks(cmd, cnrID, first, ecInfoError) + result = append(result, chunks...) + } else if err == nil { // not EC object, so all members must be phy objects + for _, member := range members { + result = append(result, phyObject{ + containerID: cnrID, + objectID: member, + }) } - commonCmd.ExitOnErr(cmd, "failed to read EC chunk of complex object: %w", err) + return result + } else { + commonCmd.ExitOnErr(cmd, "failed to flatten parts of complex object: %w", err) } + + eg, egCtx := errgroup.WithContext(cmd.Context()) + for idx := 1; idx < len(members); idx++ { + partObjID := members[idx] + + eg.Go(func() error { + partHeadPrm := prmHead + var partAddr oid.Address + partAddr.SetContainer(cnrID) + partAddr.SetObject(partObjID) + partHeadPrm.SetAddress(partAddr) + + _, err := internalclient.HeadObject(egCtx, partHeadPrm) + var ecInfoError *objectSDK.ECInfoError + if errors.As(err, &ecInfoError) { + chunks := getECObjectChunks(cmd, cnrID, partObjID, ecInfoError) + + resultGuard.Lock() + defer resultGuard.Unlock() + result = append(result, chunks...) + + return nil + } else if err == nil { + return errMalformedComplexObject + } + return err + }) + } + + commonCmd.ExitOnErr(cmd, "failed to flatten parts of complex object: %w", eg.Wait()) return result } From b9fcaad21f03da4bf1562700c76b6e61e5cdc47e Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 10 Jun 2024 17:48:05 +0300 Subject: [PATCH 0614/1413] [#1168] shard: Set `Disabled` as default `mode` for components Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/blobstor/blobstor.go | 1 + pkg/local_object_storage/metabase/db.go | 1 + pkg/local_object_storage/pilorama/boltdb.go | 1 + pkg/local_object_storage/writecache/cachebbolt.go | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index bc9ab2b994..6f579a8ca9 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -54,6 +54,7 @@ func initConfig(c *cfg) { // New creates, initializes and returns new BlobStor instance. func New(opts ...Option) *BlobStor { bs := new(BlobStor) + bs.mode = mode.Disabled initConfig(&bs.cfg) for i := range opts { diff --git a/pkg/local_object_storage/metabase/db.go b/pkg/local_object_storage/metabase/db.go index f2203f4d9e..1f444a3ef8 100644 --- a/pkg/local_object_storage/metabase/db.go +++ b/pkg/local_object_storage/metabase/db.go @@ -107,6 +107,7 @@ func New(opts ...Option) *DB { matchBucket: stringCommonPrefixMatcherBucket, }, }, + mode: mode.Disabled, } } diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index fe6bf4fed4..d4ae35ff40 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -81,6 +81,7 @@ func NewBoltForest(opts ...Option) ForestStorage { openFile: os.OpenFile, metrics: &noopMetrics{}, }, + mode: mode.Disabled, } for i := range opts { diff --git a/pkg/local_object_storage/writecache/cachebbolt.go b/pkg/local_object_storage/writecache/cachebbolt.go index f2b48d7469..254d8754fa 100644 --- a/pkg/local_object_storage/writecache/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cachebbolt.go @@ -60,7 +60,7 @@ var defaultBucket = []byte{0} func New(opts ...Option) Cache { c := &cache{ flushCh: make(chan objectInfo), - mode: mode.ReadWrite, + mode: mode.Disabled, compressFlags: make(map[string]struct{}), options: options{ From d4f425f86ab690935788db6f4268c297624abc76 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 7 Jun 2024 16:22:46 +0300 Subject: [PATCH 0615/1413] [#1167] adm/morph: Fix set-config parameter validation Signed-off-by: Alexander Chuprov --- .../internal/modules/morph/config/config.go | 27 +++++++++++---- .../modules/morph/config/config_test.go | 34 +++++++++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/config/config_test.go diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index f35e7aa036..bfcd4ac003 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -147,13 +147,28 @@ func validateConfig(args map[string]any, forceFlag bool) error { } for k, v := range args { - value, ok := v.(int64) - if !ok || value < 0 { - return fmt.Errorf("%s must be >= 0, got %v", k, v) - } + switch k { + case netmap.ContainerFeeConfig, netmap.ContainerAliasFeeConfig, + netmap.EpochDurationConfig, netmap.IrCandidateFeeConfig, + netmap.MaxObjectSizeConfig, netmap.WithdrawFeeConfig, + netmap.MaxECDataCountConfig, netmap.MaxECParityCountConfig: + value, ok := v.(int64) + if !ok { + return fmt.Errorf("%s has an invalid type. Expected type: int", k) + } - if k == netmap.MaxECDataCountConfig || k == netmap.MaxECParityCountConfig { - sumEC += value + if value < 0 { + return fmt.Errorf("%s must be >= 0, got %v", k, v) + } + + if k == netmap.MaxECDataCountConfig || k == netmap.MaxECParityCountConfig { + sumEC += value + } + case netmap.HomomorphicHashingDisabledKey, netmap.MaintenanceModeAllowedConfig: + _, ok := v.(bool) + if !ok { + return fmt.Errorf("%s has an invalid type. Expected type: bool", k) + } } } diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config_test.go b/cmd/frostfs-adm/internal/modules/morph/config/config_test.go new file mode 100644 index 0000000000..c6d5b28278 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/config/config_test.go @@ -0,0 +1,34 @@ +package config + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + "github.com/stretchr/testify/require" +) + +func Test_ValidateConfig(t *testing.T) { + testArgs := make(map[string]any) + + testArgs[netmap.MaxECDataCountConfig] = int64(11) + require.Error(t, validateConfig(testArgs, false)) + + testArgs[netmap.MaxECParityCountConfig] = int64(256) + require.Error(t, validateConfig(testArgs, false)) + require.NoError(t, validateConfig(testArgs, true)) + + testArgs[netmap.MaxECParityCountConfig] = int64(-1) + require.Error(t, validateConfig(testArgs, false)) + + testArgs[netmap.MaxECParityCountConfig] = int64(55) + require.NoError(t, validateConfig(testArgs, false)) + + testArgs[netmap.HomomorphicHashingDisabledKey] = "1" + require.Error(t, validateConfig(testArgs, false)) + + testArgs[netmap.HomomorphicHashingDisabledKey] = true + require.NoError(t, validateConfig(testArgs, false)) + + testArgs["not-well-known-configuration-key"] = "key" + require.NoError(t, validateConfig(testArgs, false)) +} From 41e670c9ba6ec026c4c00b8267e6950eb0cb494f Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 7 Jun 2024 16:33:03 +0300 Subject: [PATCH 0616/1413] [#1167] adm/morph: Move literal to const Signed-off-by: Alexander Chuprov --- cmd/frostfs-adm/internal/modules/morph/config/config.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index bfcd4ac003..ba6e515c16 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -137,6 +137,8 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { return wCtx.AwaitTx() } +const maxECSum = 256 + func validateConfig(args map[string]any, forceFlag bool) error { var sumEC int64 _, okData := args[netmap.MaxECDataCountConfig] @@ -172,9 +174,9 @@ func validateConfig(args map[string]any, forceFlag bool) error { } } - if sumEC > 256 && !forceFlag { - return fmt.Errorf("the sum of %s and %s must be <= 256, got %d", - netmap.MaxECDataCountConfig, netmap.MaxECParityCountConfig, sumEC) + if sumEC > maxECSum && !forceFlag { + return fmt.Errorf("the sum of %s and %s must be <= %d, got %d", + netmap.MaxECDataCountConfig, netmap.MaxECParityCountConfig, maxECSum, sumEC) } return nil } From 9d73f9c2c6571c0be0f64d50b235074b3e7b45ab Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 11 Jun 2024 17:05:21 +0300 Subject: [PATCH 0617/1413] Reapply "[#446] engine: Move to read-only on blobstor errors" Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/engine.go | 33 +++++++++++-------- pkg/local_object_storage/engine/error_test.go | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index b8ac6cf975..b87d77e6c2 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" @@ -49,6 +50,7 @@ type shardWrapper struct { type setModeRequest struct { sh *shard.Shard + isMeta bool errorCount uint32 } @@ -74,7 +76,7 @@ func (e *StorageEngine) setModeLoop() { if !ok { inProgress[sid] = struct{}{} go func() { - e.moveToDegraded(r.sh, r.errorCount) + e.moveToDegraded(r.sh, r.errorCount, r.isMeta) mtx.Lock() delete(inProgress, sid) @@ -86,7 +88,7 @@ func (e *StorageEngine) setModeLoop() { } } -func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32) { +func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32, isMeta bool) { sid := sh.ID() log := e.log.With( zap.Stringer("shard_id", sid), @@ -95,21 +97,23 @@ func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32) { e.mtx.RLock() defer e.mtx.RUnlock() - err := sh.SetMode(mode.DegradedReadOnly) - if err != nil { + if isMeta { + err := sh.SetMode(mode.DegradedReadOnly) + if err == nil { + log.Info(logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) + return + } log.Error(logs.EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly, zap.Error(err)) - - err = sh.SetMode(mode.ReadOnly) - if err != nil { - log.Error(logs.EngineFailedToMoveShardInReadonlyMode, - zap.Error(err)) - } else { - log.Info(logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) - } - } else { - log.Info(logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) } + + err := sh.SetMode(mode.ReadOnly) + if err != nil { + log.Error(logs.EngineFailedToMoveShardInReadonlyMode, zap.Error(err)) + return + } + + log.Info(logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) } // reportShardErrorBackground increases shard error counter and logs an error. @@ -177,6 +181,7 @@ func (e *StorageEngine) reportShardErrorWithFlags( req := setModeRequest{ errorCount: errCount, sh: sh, + isMeta: errors.As(err, new(metaerr.Error)), } select { diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 6c44966f23..535435ceb5 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -154,7 +154,7 @@ func TestErrorReporting(t *testing.T) { for i := uint32(0); i < 2; i++ { _, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)}) require.Error(t, err) - checkShardState(t, te.ng, te.shards[0].id, errThreshold+i, mode.DegradedReadOnly) + checkShardState(t, te.ng, te.shards[0].id, errThreshold+i, mode.ReadOnly) checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) } From 6a39c3d15e9be1f78ea16f622de0d41a94dc5a81 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 17 Apr 2024 14:15:08 +0300 Subject: [PATCH 0618/1413] [#1086] engine: Do not use metabase if shard looks bad Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/head.go | 1 + pkg/local_object_storage/shard/head.go | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index 1c61ca4555..97fb5be3a9 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -84,6 +84,7 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) shPrm.SetRaw(prm.raw) e.iterateOverSortedShards(prm.addr, func(_ int, sh hashedShard) (stop bool) { + shPrm.ShardLooksBad = sh.errorCount.Load() >= e.errorsThreshold res, err := sh.Head(ctx, shPrm) if err != nil { switch { diff --git a/pkg/local_object_storage/shard/head.go b/pkg/local_object_storage/shard/head.go index a0ec231af6..9d5d312608 100644 --- a/pkg/local_object_storage/shard/head.go +++ b/pkg/local_object_storage/shard/head.go @@ -13,8 +13,9 @@ import ( // HeadPrm groups the parameters of Head operation. type HeadPrm struct { - addr oid.Address - raw bool + addr oid.Address + raw bool + ShardLooksBad bool } // HeadRes groups the resulting values of Head operation. @@ -59,7 +60,8 @@ func (s *Shard) Head(ctx context.Context, prm HeadPrm) (HeadRes, error) { var obj *objectSDK.Object var err error - if s.GetMode().NoMetabase() { + mode := s.GetMode() + if mode.NoMetabase() || (mode.ReadOnly() && prm.ShardLooksBad) { var getPrm GetPrm getPrm.SetAddress(prm.addr) getPrm.SetIgnoreMeta(true) From 68ac490729e4a436926c1f9aa81219452eea2950 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 13 Jun 2024 10:10:55 +0300 Subject: [PATCH 0619/1413] [#1174] shard: Update metric `mode_info` on `Init` Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/shard/shard.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index cf59c0bfc3..94f22feb56 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -484,6 +484,7 @@ func (s *Shard) updateMetrics(ctx context.Context) { s.setContainerObjectsCount(contID.EncodeToString(), logical, count.Logic) s.setContainerObjectsCount(contID.EncodeToString(), user, count.User) } + s.cfg.metricsWriter.SetMode(s.info.Mode) } // incObjectCounter increment both physical and logical object From 42ecc2f2b9c7750a864b6388c1d29c9802ca4fb1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 10 Jun 2024 11:48:14 +0300 Subject: [PATCH 0620/1413] [#1170] morph: Support mTLS Signed-off-by: Evgenii Stratonikov --- go.mod | 2 ++ go.sum | 4 ++-- pkg/morph/client/constructor.go | 13 +++++++++---- pkg/morph/client/mtls.go | 22 ++++++++++++++++++++++ pkg/morph/client/multi.go | 13 +++++++------ 5 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 pkg/morph/client/mtls.go diff --git a/go.mod b/go.mod index 42896ed8c0..4ce8a0d277 100644 --- a/go.mod +++ b/go.mod @@ -127,3 +127,5 @@ require ( lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) + +replace github.com/nspcc-dev/neo-go => git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18 diff --git a/go.sum b/go.sum index 07632a032d..cb97af3d42 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f/go.mod h1:4AObM67VUqkXQJlODTFThFnuMGEuK8h9DrAXHDZqvCU= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= +git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18 h1:JRjwcHaQajTbSCBCK3yZnqvyHvgWBaoThDGuT4kvIIc= +git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d h1:hHk8FWbWgEnwm2I045CaBIrZBjy/o81CehIVOySA/pQ= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= @@ -186,8 +188,6 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n 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/go.mod h1:U5VfmPNM88P4RORFb6KSUVBdJBDhlqggJZYGXGPxOcc= -github.com/nspcc-dev/neo-go v0.106.0 h1:YiOdW/GcLmbVSvxMRfD5aytO6n3TDHrEA97VHMawy6g= -github.com/nspcc-dev/neo-go v0.106.0/go.mod h1:9k7vBqqQeePuj4c2CqMN9uPFsfxvwSk9vnQFrkE5eg8= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k= github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY= github.com/nspcc-dev/rfc6979 v0.2.1 h1:8wWxkamHWFmO790GsewSoKUSJjVnL1fmdRpokU/RgRM= diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index 50a9572d46..c499aa892c 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -141,7 +141,7 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er } else { var endpoint Endpoint for cli.endpoints.curr, endpoint = range cli.endpoints.list { - cli.client, act, err = cli.newCli(ctx, endpoint.Address) + cli.client, act, err = cli.newCli(ctx, endpoint) if err != nil { cli.logger.Warn(logs.FrostFSIRCouldntCreateRPCClientForEndpoint, zap.Error(err), zap.String("endpoint", endpoint.Address)) @@ -162,10 +162,15 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er return cli, nil } -func (c *Client) newCli(ctx context.Context, endpoint string) (*rpcclient.WSClient, *actor.Actor, error) { - cli, err := rpcclient.NewWS(ctx, endpoint, rpcclient.WSOptions{ +func (c *Client) newCli(ctx context.Context, endpoint Endpoint) (*rpcclient.WSClient, *actor.Actor, error) { + cfg, err := endpoint.MTLSConfig.parse() + if err != nil { + return nil, nil, fmt.Errorf("read mtls certificates: %w", err) + } + cli, err := rpcclient.NewWS(ctx, endpoint.Address, rpcclient.WSOptions{ Options: rpcclient.Options{ - DialTimeout: c.cfg.dialTimeout, + DialTimeout: c.cfg.dialTimeout, + TLSClientConfig: cfg, }, }) if err != nil { diff --git a/pkg/morph/client/mtls.go b/pkg/morph/client/mtls.go new file mode 100644 index 0000000000..3de51afe78 --- /dev/null +++ b/pkg/morph/client/mtls.go @@ -0,0 +1,22 @@ +package client + +import ( + "crypto/tls" + + "github.com/nspcc-dev/neo-go/pkg/rpcclient" +) + +// MTLSConfig represents endpoint mTLS configuration. +type MTLSConfig struct { + TrustedCAList []string + KeyFile string + CertFile string +} + +func (m *MTLSConfig) parse() (*tls.Config, error) { + if m == nil { + return nil, nil + } + + return rpcclient.TLSClientConfig(m.TrustedCAList, m.CertFile, m.KeyFile) +} diff --git a/pkg/morph/client/multi.go b/pkg/morph/client/multi.go index 25ec626d14..10ed215826 100644 --- a/pkg/morph/client/multi.go +++ b/pkg/morph/client/multi.go @@ -11,8 +11,9 @@ import ( // Endpoint represents morph endpoint together with its priority. type Endpoint struct { - Address string - Priority int + Address string + Priority int + MTLSConfig *MTLSConfig } type endpoints struct { @@ -38,11 +39,11 @@ func (c *Client) SwitchRPC(ctx context.Context) bool { // Iterate endpoints in the order of decreasing priority. for c.endpoints.curr = range c.endpoints.list { - newEndpoint := c.endpoints.list[c.endpoints.curr].Address + newEndpoint := c.endpoints.list[c.endpoints.curr] cli, act, err := c.newCli(ctx, newEndpoint) if err != nil { c.logger.Warn(logs.ClientCouldNotEstablishConnectionToTheSwitchedRPCNode, - zap.String("endpoint", newEndpoint), + zap.String("endpoint", newEndpoint.Address), zap.Error(err), ) @@ -52,7 +53,7 @@ func (c *Client) SwitchRPC(ctx context.Context) bool { c.cache.invalidate() c.logger.Info(logs.ClientConnectionToTheNewRPCNodeHasBeenEstablished, - zap.String("endpoint", newEndpoint)) + zap.String("endpoint", newEndpoint.Address)) c.client = cli c.setActor(act) @@ -119,7 +120,7 @@ mainLoop: tryE := e.Address - cli, act, err := c.newCli(ctx, tryE) + cli, act, err := c.newCli(ctx, e) if err != nil { c.logger.Warn(logs.ClientCouldNotCreateClientToTheHigherPriorityNode, zap.String("endpoint", tryE), From a0e49fa5a5b33359ef2def3777aac250022dc225 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 11 Jun 2024 15:46:10 +0300 Subject: [PATCH 0621/1413] [#1170] adm: Support morph mTLS Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/n3client.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index 55449b4357..e62a21b3f8 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -2,6 +2,7 @@ package helper import ( "context" + "crypto/tls" "errors" "fmt" "time" @@ -60,9 +61,23 @@ func GetN3Client(v *viper.Viper) (Client, error) { if endpoint == "" { return nil, errors.New("missing endpoint") } + + var cfg *tls.Config + if rootCAs := v.GetStringSlice("tls.trusted_ca_list"); len(rootCAs) != 0 { + certFile := v.GetString("tls.certificate") + keyFile := v.GetString("tls.key") + + tlsConfig, err := rpcclient.TLSClientConfig(rootCAs, certFile, keyFile) + if err != nil { + return nil, err + } + + cfg = tlsConfig + } c, err := rpcclient.New(ctx, endpoint, rpcclient.Options{ MaxConnsPerHost: maxConnsPerHost, RequestTimeout: requestTimeout, + TLSClientConfig: cfg, }) if err != nil { return nil, err From 96fe271babcd538015ff04968f1cc1b7ff913c56 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 11 Jun 2024 15:47:37 +0300 Subject: [PATCH 0622/1413] [#1170] innerring: Support morph mTLS Signed-off-by: Evgenii Stratonikov --- pkg/innerring/innerring.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 5dea18f9d5..86424abef6 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -463,9 +463,20 @@ func createClient(ctx context.Context, p *chainParams, errChan chan<- error) (*c priority = defaultPriority } + var mtlsConfig *client.MTLSConfig + rootCAs := p.cfg.GetStringSlice(fmt.Sprintf("%s.%d.trusted_ca_list", section, i)) + if len(rootCAs) != 0 { + mtlsConfig = &client.MTLSConfig{ + TrustedCAList: rootCAs, + KeyFile: p.cfg.GetString(fmt.Sprintf("%s.%d.key", section, i)), + CertFile: p.cfg.GetString(fmt.Sprintf("%s.%d.certificate", section, i)), + } + } + endpoints = append(endpoints, client.Endpoint{ - Address: addr, - Priority: priority, + Address: addr, + Priority: priority, + MTLSConfig: mtlsConfig, }) } From dbd3b238f75eab70d50cea01569269d505cb2b13 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 11 Jun 2024 15:48:06 +0300 Subject: [PATCH 0623/1413] [#1170] node: Support morph mTLS Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config/morph/config.go | 15 +++++++++++++-- cmd/frostfs-node/config/morph/config_test.go | 7 +++++++ config/example/node.env | 3 +++ config/example/node.json | 7 ++++++- config/example/node.yaml | 4 ++++ 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-node/config/morph/config.go b/cmd/frostfs-node/config/morph/config.go index b0c6527db2..1c536a0e26 100644 --- a/cmd/frostfs-node/config/morph/config.go +++ b/cmd/frostfs-node/config/morph/config.go @@ -54,9 +54,20 @@ func RPCEndpoint(c *config.Config) []client.Endpoint { priority = PriorityDefault } + var mtlsConfig *client.MTLSConfig + rootCAs := config.StringSliceSafe(s, "trusted_ca_list") + if len(rootCAs) != 0 { + mtlsConfig = &client.MTLSConfig{ + TrustedCAList: rootCAs, + KeyFile: config.StringSafe(s, "key"), + CertFile: config.StringSafe(s, "certificate"), + } + } + es = append(es, client.Endpoint{ - Address: addr, - Priority: priority, + Address: addr, + Priority: priority, + MTLSConfig: mtlsConfig, }) } diff --git a/cmd/frostfs-node/config/morph/config_test.go b/cmd/frostfs-node/config/morph/config_test.go index 13da3d70d9..5a021abc36 100644 --- a/cmd/frostfs-node/config/morph/config_test.go +++ b/cmd/frostfs-node/config/morph/config_test.go @@ -28,6 +28,13 @@ func TestMorphSection(t *testing.T) { { Address: "wss://rpc1.morph.frostfs.info:40341/ws", Priority: 1, + MTLSConfig: &client.MTLSConfig{ + TrustedCAList: []string{ + "/path/to/ca.pem", + }, + KeyFile: "/path/to/key", + CertFile: "/path/to/cert", + }, }, { Address: "wss://rpc2.morph.frostfs.info:40341/ws", diff --git a/config/example/node.env b/config/example/node.env index 9f15c40428..eedbe501d3 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -61,6 +61,9 @@ FROSTFS_MORPH_CACHE_TTL=15s FROSTFS_MORPH_SWITCH_INTERVAL=3m FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS="wss://rpc1.morph.frostfs.info:40341/ws" FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY=0 +FROSTFS_MORPH_RPC_ENDPOINT_0_TRUSTED_CA_LIST="/path/to/ca.pem" +FROSTFS_MORPH_RPC_ENDPOINT_0_CERTIFICATE="/path/to/cert" +FROSTFS_MORPH_RPC_ENDPOINT_0_KEY="/path/to/key" FROSTFS_MORPH_RPC_ENDPOINT_1_ADDRESS="wss://rpc2.morph.frostfs.info:40341/ws" FROSTFS_MORPH_RPC_ENDPOINT_1_PRIORITY=2 FROSTFS_MORPH_APE_CHAIN_CACHE_SIZE=100000 diff --git a/config/example/node.json b/config/example/node.json index 79e6fe89ac..2589f2c341 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -95,7 +95,12 @@ "rpc_endpoint": [ { "address": "wss://rpc1.morph.frostfs.info:40341/ws", - "priority": 0 + "priority": 0, + "trusted_ca_list": [ + "/path/to/ca.pem" + ], + "certificate": "/path/to/cert", + "key": "/path/to/key" }, { "address": "wss://rpc2.morph.frostfs.info:40341/ws", diff --git a/config/example/node.yaml b/config/example/node.yaml index 34e796ac46..1a9516ef34 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -84,6 +84,10 @@ morph: rpc_endpoint: # side chain NEO RPC endpoints; are shuffled and used one by one until the first success - address: wss://rpc1.morph.frostfs.info:40341/ws priority: 0 + trusted_ca_list: + - "/path/to/ca.pem" + certificate: "/path/to/cert" + key: "/path/to/key" - address: wss://rpc2.morph.frostfs.info:40341/ws priority: 2 ape_chain_cache_size: 100000 From 3fc8e0e08c15927620c98b471c8ef05811a3127d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 14 Jun 2024 09:57:47 +0300 Subject: [PATCH 0624/1413] Release v0.41.0 Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 11 +++++++++++ VERSION | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0382d0316f..2abba1d094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,17 @@ Changelog for FrostFS Node ### Removed ### Updated +## [v0.41.0] + +### Added +- Support mTLS for morph client (#1170) + +### Fixed +- Update shard state metric during shard init (#1174) +- Handle ENOSPC in blobovnicza (#1166) +- Handle multiple split-infos for EC objects (#1163) +- Set `Disabled` mode as the default for components (#1168) + ## [v0.40.0] ### Added diff --git a/VERSION b/VERSION index 707d5fac27..9dedf1e9be 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.40.0 +v0.41.0 From b9d6c9d10c793f021eea1d83ba019cec7fbfbdd2 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 14 Jun 2024 13:06:11 +0300 Subject: [PATCH 0625/1413] [#1177] cli: Fix resource name parsing * If `root` name is given explicitly, then it should be translated to `//` but not `/root/`. Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/util/ape.go | 2 +- cmd/frostfs-cli/modules/util/ape_test.go | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 50253b366e..680e24d82a 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -279,7 +279,7 @@ func parseResource(lexeme string, isObj bool) (string, error) { if isObj { if lexeme == "*" { return nativeschema.ResourceFormatAllObjects, nil - } else if lexeme == "/*" { + } else if lexeme == "/*" || lexeme == "root/*" { return nativeschema.ResourceFormatRootObjects, nil } else if strings.HasPrefix(lexeme, "/") { lexeme = lexeme[1:] diff --git a/cmd/frostfs-cli/modules/util/ape_test.go b/cmd/frostfs-cli/modules/util/ape_test.go index d93210f41e..b275803dff 100644 --- a/cmd/frostfs-cli/modules/util/ape_test.go +++ b/cmd/frostfs-cli/modules/util/ape_test.go @@ -26,7 +26,7 @@ func TestParseAPERule(t *testing.T) { }, }, { - name: "Valid rule for all objects in root namespace", + name: "Valid rule for all objects in implicit root namespace", rule: "allow Object.Put /*", expectRule: policyengine.Rule{ Status: policyengine.Allow, @@ -34,6 +34,15 @@ func TestParseAPERule(t *testing.T) { Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, }, }, + { + name: "Valid rule for all objects in explicit root namespace", + rule: "allow Object.Put root/*", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, + }, + }, { name: "Valid rule for all objects in root namespace and container", rule: "allow Object.Put /cid/*", From 76cf7a051b9bd33997dfb21df46e727e3a6cda38 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 17 Jun 2024 09:47:53 +0300 Subject: [PATCH 0626/1413] [#1178] shard: Check metabase existence before read shard ID Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/shard_id.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/local_object_storage/metabase/shard_id.go b/pkg/local_object_storage/metabase/shard_id.go index 9b24e98d74..88446494ee 100644 --- a/pkg/local_object_storage/metabase/shard_id.go +++ b/pkg/local_object_storage/metabase/shard_id.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "os" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" metamode "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -25,6 +26,10 @@ func (db *DB) GetShardID(mode metamode.Mode) ([]byte, error) { defer db.modeMtx.Unlock() db.mode = mode + if _, err := os.Stat(db.info.Path); errors.Is(err, os.ErrNotExist) { + return nil, nil + } + if err := db.openDB(mode); err != nil { return nil, fmt.Errorf("failed to open metabase: %w", err) } From 5b100699d7c9b2446539cbf19518bca963c5fc35 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 18 Jun 2024 10:20:45 +0300 Subject: [PATCH 0627/1413] [#566] policer: Move isClientErrMaintenance to frostfs-sdk-go Signed-off-by: Ekaterina Lebedeva --- go.mod | 2 +- go.sum | 4 ++-- pkg/services/policer/check.go | 27 +-------------------------- pkg/services/policer/ec.go | 2 +- 4 files changed, 5 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index 4ce8a0d277..a04b94220f 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index cb97af3d42..0849b74a11 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f h1:vBLC1OSGMSn7lRJv/p1of0veifuBdZdztVrF9Vn+UFk= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240531132048-ebd8fcd1685f/go.mod h1:4AObM67VUqkXQJlODTFThFnuMGEuK8h9DrAXHDZqvCU= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de h1:OjsWY0jpGJV1t87XgwL/3PsDx7fJ6lfNMXtY8UhoUbM= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de/go.mod h1:4AObM67VUqkXQJlODTFThFnuMGEuK8h9DrAXHDZqvCU= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18 h1:JRjwcHaQajTbSCBCK3yZnqvyHvgWBaoThDGuT4kvIIc= diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 7120ba0b86..bf67ec4d45 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -2,7 +2,6 @@ package policer import ( "context" - "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -11,7 +10,6 @@ import ( policycore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -139,7 +137,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe if client.IsErrObjectNotFound(err) { checkedNodes.submitReplicaCandidate(nodes[i]) continue - } else if isClientErrMaintenance(err) { + } else if client.IsErrNodeUnderMaintenance(err) { shortage, uncheckedCopies = p.handleMaintenance(nodes[i], checkedNodes, shortage, uncheckedCopies) } else { p.log.Error(logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, @@ -204,26 +202,3 @@ func (p *Policer) handleProcessNodesResult(ctx context.Context, addr oid.Address requirements.removeLocalCopy = true } } - -// isClientErrMaintenance checks if err corresponds to FrostFS status return -// which tells that node is currently under maintenance. Supports wrapped -// errors. -// -// Similar to client.IsErr___ errors, consider replacing to FrostFS SDK. -func isClientErrMaintenance(err error) bool { - switch unwrapErr(err).(type) { - default: - return false - case *apistatus.NodeUnderMaintenance: - return true - } -} - -// unwrapErr unwraps error using errors.Unwrap. -func unwrapErr(err error) error { - for e := errors.Unwrap(err); e != nil; e = errors.Unwrap(err) { - err = e - } - - return err -} diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index b15efdd159..5b3793f7b3 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -126,7 +126,7 @@ func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, n Nodes: []netmap.NodeInfo{requiredNode}, } p.replicator.HandleReplicationTask(ctx, task, newNodeCache()) - } else if isClientErrMaintenance(err) { + } else if client.IsErrNodeUnderMaintenance(err) { // consider maintenance mode has object, but do not drop local copy p.log.Debug(logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) } else { From 75eedf71f31c8d0d68500779954e708fa884c3ee Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 18 Jun 2024 15:06:09 +0300 Subject: [PATCH 0628/1413] [#1187] pilorama/test: Remove debug print Introduced in e12fcc041d. Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- pkg/local_object_storage/pilorama/forest_test.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a04b94220f..ddc1938973 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,6 @@ require ( git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/go-pkgz/expirable-cache/v3 v3.0.0 github.com/google/uuid v1.6.0 @@ -65,6 +64,7 @@ require ( github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 6c1bc343f5..9c343f6329 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -16,7 +16,6 @@ import ( cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - "github.com/davecgh/go-spew/spew" "github.com/google/uuid" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" @@ -271,7 +270,6 @@ func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { res, cursor, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, RootID, last, count) require.NoError(t, err) result = append(result, res...) - spew.Dump(last, res) return cursor } From 7b8937ec3555b950d4fa36428391f3e973d4f2c2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 18 Jun 2024 12:34:42 +0300 Subject: [PATCH 0629/1413] [#1184] config: Add audit.enabled parameter for node Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 10 +++++++ cmd/frostfs-node/config/audit/config.go | 12 +++++++++ cmd/frostfs-node/config/audit/config_test.go | 28 ++++++++++++++++++++ config/example/node.env | 3 +++ config/example/node.json | 3 +++ config/example/node.yaml | 3 +++ docs/storage-node-configuration.md | 13 +++++++++ 7 files changed, 72 insertions(+) create mode 100644 cmd/frostfs-node/config/audit/config.go create mode 100644 cmd/frostfs-node/config/audit/config_test.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index cdfa2118ce..2b185cfc8c 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -18,6 +18,7 @@ import ( netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" apiclientconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/apiclient" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/audit" contractsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/contracts" engineconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine" shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard" @@ -375,6 +376,7 @@ type internals struct { healthStatus *atomic.Int32 // is node under maintenance isMaintenance atomic.Bool + audit *atomic.Bool sdNotify bool } @@ -722,6 +724,9 @@ func initInternals(appCfg *config.Config, log *logger.Logger) internals { var healthStatus atomic.Int32 healthStatus.Store(int32(control.HealthStatus_HEALTH_STATUS_UNDEFINED)) + var auditRequests atomic.Bool + auditRequests.Store(audit.Enabled(appCfg)) + return internals{ done: make(chan struct{}), appCfg: appCfg, @@ -730,6 +735,7 @@ func initInternals(appCfg *config.Config, log *logger.Logger) internals { apiVersion: version.Current(), healthStatus: &healthStatus, sdNotify: initSdNotify(appCfg), + audit: &auditRequests, } } @@ -1278,6 +1284,10 @@ func (c *cfg) reloadConfig(ctx context.Context) { setRuntimeParameters(c) return nil }}) + components = append(components, dCmp{"audit", func() error { + c.audit.Store(audit.Enabled(c.appCfg)) + return nil + }}) components = append(components, dCmp{"pools", c.reloadPools}) components = append(components, dCmp{"tracing", func() error { updated, err := tracing.Setup(ctx, *tracingconfig.ToTracingConfig(c.appCfg)) diff --git a/cmd/frostfs-node/config/audit/config.go b/cmd/frostfs-node/config/audit/config.go new file mode 100644 index 0000000000..8f728c8506 --- /dev/null +++ b/cmd/frostfs-node/config/audit/config.go @@ -0,0 +1,12 @@ +package audit + +import "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + +const ( + subsection = "audit" +) + +// Enabled returns the value of "enabled" config parameter from "audit" section. +func Enabled(c *config.Config) bool { + return config.BoolSafe(c.Sub(subsection), "enabled") +} diff --git a/cmd/frostfs-node/config/audit/config_test.go b/cmd/frostfs-node/config/audit/config_test.go new file mode 100644 index 0000000000..7731cc8e6a --- /dev/null +++ b/cmd/frostfs-node/config/audit/config_test.go @@ -0,0 +1,28 @@ +package audit + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" + "github.com/stretchr/testify/require" +) + +func TestAuditSection(t *testing.T) { + t.Run("defaults", func(t *testing.T) { + empty := configtest.EmptyConfig() + require.Equal(t, false, Enabled(empty)) + }) + + const path = "../../../../config/example/node" + + fileConfigTest := func(c *config.Config) { + require.Equal(t, true, Enabled(c)) + } + + configtest.ForEachFileType(path, fileConfigTest) + + t.Run("ENV", func(t *testing.T) { + configtest.ForEnvFileType(t, path, fileConfigTest) + }) +} diff --git a/config/example/node.env b/config/example/node.env index eedbe501d3..72f56e96c9 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -202,3 +202,6 @@ FROSTFS_TRACING_ENDPOINT="localhost" FROSTFS_TRACING_EXPORTER="otlp_grpc" FROSTFS_RUNTIME_SOFT_MEMORY_LIMIT=1073741824 + +# AUDIT section +FROSTFS_AUDIT_ENABLED=true diff --git a/config/example/node.json b/config/example/node.json index 2589f2c341..b9dc6014cd 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -260,5 +260,8 @@ }, "runtime": { "soft_memory_limit": 1073741824 + }, + "audit": { + "enabled": true } } diff --git a/config/example/node.yaml b/config/example/node.yaml index 1a9516ef34..bad67816a2 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -234,3 +234,6 @@ tracing: runtime: soft_memory_limit: 1gb + +audit: + enabled: true diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 3a6969abdf..5389bfbb55 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -25,6 +25,7 @@ There are some custom types used for brevity: | `replicator` | [Replicator service configuration](#replicator-section) | | `storage` | [Storage engine configuration](#storage-section) | | `runtime` | [Runtime configuration](#runtime-section) | +| `audit` | [Audit configuration](#audit-section) | # `control` section @@ -428,3 +429,15 @@ runtime: | Parameter | Type | Default value | Description | |---------------------|--------|---------------|--------------------------------------------------------------------------| | `soft_memory_limit` | `size` | 0 | Soft memory limit for the runtime. Zero or no value stands for no limit. If `GOMEMLIMIT` environment variable is set, the value from the configuration file will be ignored. | + +# `audit` section +Contains audit parameters. + +```yaml +audit: + enabled: true +``` + +| Parameter | Type | Default value | Description | +|---------------------|--------|---------------|---------------------------------------------------| +| `soft_memory_limit` | `bool` | false | If `true` then audit event logs will be recorded. | From ac1f0147476395617a35152c6c5b83f1ebf67bfb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 18 Jun 2024 12:38:39 +0300 Subject: [PATCH 0630/1413] [#1184] node: Add audit package Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- internal/audit/consts.go | 7 ++ internal/audit/request.go | 41 ++++++++++ internal/audit/target.go | 158 ++++++++++++++++++++++++++++++++++++++ internal/logs/logs.go | 1 + 5 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 internal/audit/consts.go create mode 100644 internal/audit/request.go create mode 100644 internal/audit/target.go diff --git a/go.mod b/go.mod index ddc1938973..38e66a20fa 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 + git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de git.frostfs.info/TrueCloudLab/hrw v1.2.1 @@ -54,7 +55,6 @@ require ( ) require ( - git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 // indirect git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect diff --git a/internal/audit/consts.go b/internal/audit/consts.go new file mode 100644 index 0000000000..f4fa19ab9c --- /dev/null +++ b/internal/audit/consts.go @@ -0,0 +1,7 @@ +package audit + +const ( + InvalidValue = "invalid_value" + NotDefined = "not_defined" + Empty = "empty" +) diff --git a/internal/audit/request.go b/internal/audit/request.go new file mode 100644 index 0000000000..cd1771013f --- /dev/null +++ b/internal/audit/request.go @@ -0,0 +1,41 @@ +package audit + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "go.uber.org/zap" +) + +type Request interface { + GetVerificationHeader() *session.RequestVerificationHeader +} + +type Target interface { + String() string +} + +func LogRequest(log *logger.Logger, operation string, req Request, target Target, status bool) { + LogRequestWithKey(log, operation, req.GetVerificationHeader().GetBodySignature().GetKey(), target, status) +} + +func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target Target, status bool) { + object, subject := NotDefined, NotDefined + + publicKey := crypto.UnmarshalPublicKey(key) + if publicKey != nil { + subject = ((*keys.PublicKey)(publicKey)).StringCompressed() + } + + if target != nil { + object = target.String() + } + + log.Info(logs.AuditEventLogRecord, + zap.String("operation", operation), + zap.String("object", object), + zap.String("subject", subject), + zap.Bool("success", status)) +} diff --git a/internal/audit/target.go b/internal/audit/target.go new file mode 100644 index 0000000000..1d760eca6e --- /dev/null +++ b/internal/audit/target.go @@ -0,0 +1,158 @@ +package audit + +import ( + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/mr-tron/base58" +) + +type ModelType[T any] interface { + ReadFromV2(m T) error + String() string +} + +func TargetFromRef[T any](ref *T, model ModelType[T]) Target { + if ref == nil { + return stringTarget{s: NotDefined} + } + if err := model.ReadFromV2(*ref); err != nil { + return stringTarget{s: InvalidValue} + } + return stringTarget{s: model.String()} +} + +func TargetFromRefs[T any](refs []*T, model ModelType[T]) Target { + if len(refs) == 0 { + return stringTarget{s: NotDefined} + } + sb := &strings.Builder{} + for idx, ref := range refs { + if idx > 0 { + sb.WriteString(";") + } + if ref == nil { + sb.WriteString(Empty) + continue + } + if err := model.ReadFromV2(*ref); err != nil { + sb.WriteString(InvalidValue) + } else { + sb.WriteString(model.String()) + } + } + return sb +} + +type stringTarget struct { + s string +} + +func (t stringTarget) String() string { + return t.s +} + +func TargetFromString(s string) Target { + if len(s) == 0 { + s = Empty + } + return stringTarget{s: s} +} + +func TargetFromStringSlice(s []string) Target { + if len(s) == 0 { + return stringTarget{s: NotDefined} + } + sb := &strings.Builder{} + for i, v := range s { + if i > 0 { + sb.WriteString(";") + } + if len(v) == 0 { + sb.WriteString(Empty) + } else { + sb.WriteString(v) + } + } + return sb +} + +func TargetFromChainID(chainTargetType, chainTargetName string, chainID []byte) Target { + if len(chainTargetType) == 0 && len(chainTargetName) == 0 && len(chainID) == 0 { + return stringTarget{s: NotDefined} + } + t, n, c := Empty, Empty, Empty + if len(chainTargetType) > 0 { + t = chainTargetType + } + if len(chainTargetName) > 0 { + n = chainTargetName + } + if len(chainID) > 0 { + c = string(chainID) + } + return stringTarget{s: t + ":" + n + ":" + c} +} + +func TargetFromShardIDs(v [][]byte) Target { + if len(v) == 0 { + return stringTarget{s: NotDefined} + } + sb := &strings.Builder{} + for i, s := range v { + if i > 0 { + sb.WriteString(";") + } + if len(s) == 0 { + sb.WriteString(Empty) + } else { + sb.WriteString(base58.Encode(s)) + } + } + return sb +} + +func TargetFromTreeID(containerID []byte, treeID string) Target { + if len(containerID) == 0 && len(treeID) == 0 { + return stringTarget{s: NotDefined} + } + c, t := Empty, Empty + if len(containerID) > 0 { + var cnr cid.ID + if err := cnr.Decode(containerID); err != nil { + c = InvalidValue + } else { + c = cnr.EncodeToString() + } + } + if len(treeID) > 0 { + t = treeID + } + return stringTarget{s: c + ":" + t} +} + +func TargetFromContainerIDObjectID(containerID *refs.ContainerID, objectID *refs.ObjectID) Target { + if containerID == nil && objectID == nil { + return stringTarget{s: NotDefined} + } + c, o := Empty, Empty + if containerID != nil { + var cnr cid.ID + if err := cnr.ReadFromV2(*containerID); err != nil { + c = InvalidValue + } else { + c = cnr.EncodeToString() + } + } + if objectID != nil { + var obj oid.ID + if err := obj.ReadFromV2(*objectID); err != nil { + o = InvalidValue + } else { + o = obj.EncodeToString() + } + } + return stringTarget{s: c + "/" + o} +} diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 8dae61c3d0..eeb2fbf3fd 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -539,4 +539,5 @@ const ( PolicerFailedToRestoreObject = "failed to restore EC object" PolicerCouldNotGetChunk = "could not get EC chunk" PolicerCouldNotGetChunks = "could not get EC chunks" + AuditEventLogRecord = "audit event log record" ) From ecd1ed7a5e461c2b48e67949b4b2ef2a353e5307 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 18 Jun 2024 12:40:03 +0300 Subject: [PATCH 0631/1413] [#1184] node: Add audit middleware for grpc services Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/accounting.go | 15 +- cmd/frostfs-node/apemanager.go | 3 +- cmd/frostfs-node/container.go | 14 +- cmd/frostfs-node/control.go | 5 +- cmd/frostfs-node/netmap.go | 28 +-- cmd/frostfs-node/object.go | 5 +- cmd/frostfs-node/session.go | 5 +- cmd/frostfs-node/tree.go | 2 +- pkg/services/accounting/audit.go | 42 ++++ pkg/services/apemanager/audit.go | 75 +++++++ pkg/services/container/audit.go | 116 +++++++++++ pkg/services/control/server/audit.go | 287 +++++++++++++++++++++++++++ pkg/services/netmap/audit.go | 60 ++++++ pkg/services/object/audit.go | 172 ++++++++++++++++ pkg/services/session/audit.go | 39 ++++ pkg/services/tree/audit.go | 135 +++++++++++++ 16 files changed, 967 insertions(+), 36 deletions(-) create mode 100644 pkg/services/accounting/audit.go create mode 100644 pkg/services/apemanager/audit.go create mode 100644 pkg/services/container/audit.go create mode 100644 pkg/services/control/server/audit.go create mode 100644 pkg/services/netmap/audit.go create mode 100644 pkg/services/object/audit.go create mode 100644 pkg/services/session/audit.go create mode 100644 pkg/services/tree/audit.go diff --git a/cmd/frostfs-node/accounting.go b/cmd/frostfs-node/accounting.go index ec737f8a01..f0e2abf385 100644 --- a/cmd/frostfs-node/accounting.go +++ b/cmd/frostfs-node/accounting.go @@ -20,15 +20,16 @@ func initAccountingService(ctx context.Context, c *cfg) { balanceMorphWrapper, err := balance.NewFromMorph(c.cfgMorph.client, c.cfgAccounting.scriptHash, 0) fatalOnErr(err) - server := accountingTransportGRPC.New( - accountingService.NewSignService( - &c.key.PrivateKey, - accountingService.NewExecutionService( - accounting.NewExecutor(balanceMorphWrapper), - c.respSvc, - ), + service := accountingService.NewSignService( + &c.key.PrivateKey, + accountingService.NewExecutionService( + accounting.NewExecutor(balanceMorphWrapper), + c.respSvc, ), ) + service = accountingService.NewAuditService(service, c.log, c.audit) + + server := accountingTransportGRPC.New(service) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { accountingGRPC.RegisterAccountingServiceServer(s, server) diff --git a/cmd/frostfs-node/apemanager.go b/cmd/frostfs-node/apemanager.go index b9928faaf6..79c45c2546 100644 --- a/cmd/frostfs-node/apemanager.go +++ b/cmd/frostfs-node/apemanager.go @@ -21,7 +21,8 @@ func initAPEManagerService(c *cfg) { execsvc := apemanager.New(c.cfgObject.cnrSource, contractStorage, apemanager.WithLogger(c.log)) sigsvc := apemanager.NewSignService(&c.key.PrivateKey, execsvc) - server := apemanager_transport.New(sigsvc) + auditSvc := apemanager.NewAuditService(sigsvc, c.log, c.audit) + server := apemanager_transport.New(auditSvc) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { apemanager_grpc.RegisterAPEManagerServiceServer(s, server) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 61600376ba..b14e19161d 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -46,15 +46,15 @@ func initContainerService(_ context.Context, c *cfg) { c.shared.frostfsidClient = frostfsIDSubjectProvider - server := containerTransportGRPC.New( - containerService.NewSignService( - &c.key.PrivateKey, - containerService.NewAPEServer(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine, cnrRdr, - newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient, - containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), - ), + service := containerService.NewSignService( + &c.key.PrivateKey, + containerService.NewAPEServer(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine, cnrRdr, + newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient, + containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), ), ) + service = containerService.NewAuditService(service, c.log, c.audit) + server := containerTransportGRPC.New(service) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { containerGRPC.RegisterContainerServiceServer(s, server) diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index e1e6e3ac9e..8ee1ab69f4 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -30,8 +30,8 @@ func initControlService(c *cfg) { for i := range pubs { rawPubs = append(rawPubs, pubs[i].Bytes()) } - - ctlSvc := controlSvc.New( + var ctlSvc control.ControlServiceServer + ctlSvc = controlSvc.New( controlSvc.WithKey(&c.key.PrivateKey), controlSvc.WithAuthorizedKeys(rawPubs), controlSvc.WithHealthChecker(c), @@ -43,6 +43,7 @@ func initControlService(c *cfg) { controlSvc.WithTreeService(c.treeService), controlSvc.WithLocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine), ) + ctlSvc = controlSvc.NewAuditService(ctlSvc, c.log, c.audit) lis, err := net.Listen("tcp", endpoint) if err != nil { diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 56f2ca98fc..6aff8ddf2d 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -147,22 +147,22 @@ func initNetmapService(ctx context.Context, c *cfg) { initNetmapState(c) - server := netmapTransportGRPC.New( - netmapService.NewSignService( - &c.key.PrivateKey, - netmapService.NewExecutionService( - c, - c.apiVersion, - &netInfo{ - netState: c.cfgNetmap.state, - magic: c.cfgMorph.client, - morphClientNetMap: c.cfgNetmap.wrapper, - msPerBlockRdr: c.cfgMorph.client.MsPerBlock, - }, - c.respSvc, - ), + svc := netmapService.NewSignService( + &c.key.PrivateKey, + netmapService.NewExecutionService( + c, + c.apiVersion, + &netInfo{ + netState: c.cfgNetmap.state, + magic: c.cfgMorph.client, + morphClientNetMap: c.cfgNetmap.wrapper, + msPerBlockRdr: c.cfgMorph.client.MsPerBlock, + }, + c.respSvc, ), ) + svc = netmapService.NewAuditService(svc, c.log, c.audit) + server := netmapTransportGRPC.New(svc) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { netmapGRPC.RegisterNetmapServiceServer(s, server) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 907e517a54..62183d3140 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -182,7 +182,7 @@ func initObjectService(c *cfg) { sDeleteV2 := createDeleteServiceV2(sDelete) // build service pipeline - // grpc | | signature | response | acl | ape | split + // grpc | audit | | signature | response | acl | ape | split splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2) @@ -205,7 +205,8 @@ func initObjectService(c *cfg) { c.shared.metricsSvc = objectService.NewMetricCollector( signSvc, c.metricsCollector.ObjectService(), metricsconfig.Enabled(c.appCfg)) - server := objectTransportGRPC.New(c.shared.metricsSvc) + auditSvc := objectService.NewAuditService(c.shared.metricsSvc, c.log, c.audit) + server := objectTransportGRPC.New(auditSvc) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { objectGRPC.RegisterObjectServiceServer(s, server) diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index ee21ec230c..d286fc6312 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -52,12 +52,13 @@ func initSessionService(c *cfg) { c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber()) }) - server := sessionTransportGRPC.New( + svc := sessionSvc.NewAuditService( sessionSvc.NewSignService( &c.key.PrivateKey, sessionSvc.NewExecutionService(c.privateTokenStore, c.respSvc, c.log), ), - ) + c.log, c.audit) + server := sessionTransportGRPC.New(svc) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { sessionGRPC.RegisterSessionServiceServer(s, server) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index daaaa64a24..9f5c89ef03 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -70,7 +70,7 @@ func initTreeService(c *cfg) { ) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { - tree.RegisterTreeServiceServer(s, c.treeService) + tree.RegisterTreeServiceServer(s, tree.NewAuditService(c.treeService, c.log, c.audit)) }) c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { diff --git a/pkg/services/accounting/audit.go b/pkg/services/accounting/audit.go new file mode 100644 index 0000000000..1d8f8836fa --- /dev/null +++ b/pkg/services/accounting/audit.go @@ -0,0 +1,42 @@ +package accounting + +import ( + "context" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" + acc_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" +) + +var _ Server = (*auditService)(nil) + +type auditService struct { + next Server + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// Balance implements Server. +func (l *auditService) Balance(ctx context.Context, req *accounting.BalanceRequest) (*accounting.BalanceResponse, error) { + res, err := l.next.Balance(ctx, req) + + if !l.enabled.Load() { + return res, err + } + + audit.LogRequest(l.log, acc_grpc.AccountingService_Balance_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil) + + return res, err +} diff --git a/pkg/services/apemanager/audit.go b/pkg/services/apemanager/audit.go new file mode 100644 index 0000000000..d132ae7dbf --- /dev/null +++ b/pkg/services/apemanager/audit.go @@ -0,0 +1,75 @@ +package apemanager + +import ( + "context" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" + ape_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" +) + +var _ Server = (*auditService)(nil) + +type auditService struct { + next Server + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// AddChain implements Server. +func (a *auditService) AddChain(ctx context.Context, req *apemanager.AddChainRequest) (*apemanager.AddChainResponse, error) { + res, err := a.next.AddChain(ctx, req) + if !a.enabled.Load() { + return res, err + } + + audit.LogRequest(a.log, ape_grpc.APEManagerService_AddChain_FullMethodName, req, + audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(), + req.GetBody().GetTarget().GetName(), + res.GetBody().GetChainID()), + err == nil) + + return res, err +} + +// ListChains implements Server. +func (a *auditService) ListChains(ctx context.Context, req *apemanager.ListChainsRequest) (*apemanager.ListChainsResponse, error) { + res, err := a.next.ListChains(ctx, req) + if !a.enabled.Load() { + return res, err + } + + audit.LogRequest(a.log, ape_grpc.APEManagerService_ListChains_FullMethodName, req, + audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(), + req.GetBody().GetTarget().GetName(), + nil), + err == nil) + + return res, err +} + +// RemoveChain implements Server. +func (a *auditService) RemoveChain(ctx context.Context, req *apemanager.RemoveChainRequest) (*apemanager.RemoveChainResponse, error) { + res, err := a.next.RemoveChain(ctx, req) + if !a.enabled.Load() { + return res, err + } + + audit.LogRequest(a.log, ape_grpc.APEManagerService_RemoveChain_FullMethodName, req, + audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(), + req.GetBody().GetTarget().GetName(), + req.GetBody().GetChainID()), + err == nil) + + return res, err +} diff --git a/pkg/services/container/audit.go b/pkg/services/container/audit.go new file mode 100644 index 0000000000..7ef432bb11 --- /dev/null +++ b/pkg/services/container/audit.go @@ -0,0 +1,116 @@ +package container + +import ( + "context" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" + container_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" +) + +var _ Server = (*auditService)(nil) + +type auditService struct { + next Server + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// AnnounceUsedSpace implements Server. +func (a *auditService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { + res, err := a.next.AnnounceUsedSpace(ctx, req) + if !a.enabled.Load() { + return res, err + } + + var ids []*refs.ContainerID + for _, v := range req.GetBody().GetAnnouncements() { + ids = append(ids, v.GetContainerID()) + } + + audit.LogRequest(a.log, container_grpc.ContainerService_AnnounceUsedSpace_FullMethodName, req, + audit.TargetFromRefs(ids, &cid.ID{}), err == nil) + + return res, err +} + +// Delete implements Server. +func (a *auditService) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) { + res, err := a.next.Delete(ctx, req) + if !a.enabled.Load() { + return res, err + } + + audit.LogRequest(a.log, container_grpc.ContainerService_Delete_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil) + + return res, err +} + +// Get implements Server. +func (a *auditService) Get(ctx context.Context, req *container.GetRequest) (*container.GetResponse, error) { + res, err := a.next.Get(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, container_grpc.ContainerService_Get_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil) + return res, err +} + +// GetExtendedACL implements Server. +func (a *auditService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { + res, err := a.next.GetExtendedACL(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, container_grpc.ContainerService_GetExtendedACL_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil) + return res, err +} + +// List implements Server. +func (a *auditService) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) { + res, err := a.next.List(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, container_grpc.ContainerService_List_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil) + return res, err +} + +// Put implements Server. +func (a *auditService) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) { + res, err := a.next.Put(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, container_grpc.ContainerService_Put_FullMethodName, req, + audit.TargetFromRef(res.GetBody().GetContainerID(), &cid.ID{}), err == nil) + return res, err +} + +// SetExtendedACL implements Server. +func (a *auditService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { + res, err := a.next.SetExtendedACL(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, container_grpc.ContainerService_SetExtendedACL_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetEACL().GetContainerID(), &cid.ID{}), err == nil) + return res, err +} diff --git a/pkg/services/control/server/audit.go b/pkg/services/control/server/audit.go new file mode 100644 index 0000000000..16c04a8c9e --- /dev/null +++ b/pkg/services/control/server/audit.go @@ -0,0 +1,287 @@ +package control + +import ( + "context" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + ctl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +) + +var _ ctl.ControlServiceServer = (*auditService)(nil) + +type auditService struct { + next ctl.ControlServiceServer + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next ctl.ControlServiceServer, log *logger.Logger, enabled *atomic.Bool) ctl.ControlServiceServer { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// AddChainLocalOverride implements control.ControlServiceServer. +func (a *auditService) AddChainLocalOverride(ctx context.Context, req *ctl.AddChainLocalOverrideRequest) (*ctl.AddChainLocalOverrideResponse, error) { + res, err := a.next.AddChainLocalOverride(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_AddChainLocalOverride_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(), + req.GetBody().GetTarget().GetName(), + res.GetBody().GetChainId()), + err == nil) + return res, err +} + +// DetachShards implements control.ControlServiceServer. +func (a *auditService) DetachShards(ctx context.Context, req *ctl.DetachShardsRequest) (*ctl.DetachShardsResponse, error) { + res, err := a.next.DetachShards(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_DetachShards_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) + return res, err +} + +// Doctor implements control.ControlServiceServer. +func (a *auditService) Doctor(ctx context.Context, req *ctl.DoctorRequest) (*ctl.DoctorResponse, error) { + res, err := a.next.Doctor(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_Doctor_FullMethodName, req.GetSignature().GetKey(), nil, err == nil) + return res, err +} + +// DropObjects implements control.ControlServiceServer. +func (a *auditService) DropObjects(ctx context.Context, req *ctl.DropObjectsRequest) (*ctl.DropObjectsResponse, error) { + res, err := a.next.DropObjects(ctx, req) + if !a.enabled.Load() { + return res, err + } + var list []string + for _, v := range req.GetBody().GetAddressList() { + if len(v) == 0 { + list = append(list, audit.Empty) + continue + } + var a oid.Address + if e := a.DecodeString(string(v)); e != nil { + list = append(list, audit.InvalidValue) + } else { + list = append(list, a.EncodeToString()) + } + } + + audit.LogRequestWithKey(a.log, ctl.ControlService_DropObjects_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromStringSlice(list), err == nil) + return res, err +} + +// EvacuateShard implements control.ControlServiceServer. +func (a *auditService) EvacuateShard(ctx context.Context, req *ctl.EvacuateShardRequest) (*ctl.EvacuateShardResponse, error) { + res, err := a.next.EvacuateShard(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_EvacuateShard_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) + return res, err +} + +// FlushCache implements control.ControlServiceServer. +func (a *auditService) FlushCache(ctx context.Context, req *ctl.FlushCacheRequest) (*ctl.FlushCacheResponse, error) { + res, err := a.next.FlushCache(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_FlushCache_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) + return res, err +} + +// GetChainLocalOverride implements control.ControlServiceServer. +func (a *auditService) GetChainLocalOverride(ctx context.Context, req *ctl.GetChainLocalOverrideRequest) (*ctl.GetChainLocalOverrideResponse, error) { + res, err := a.next.GetChainLocalOverride(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_GetChainLocalOverride_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromChainID( + req.GetBody().GetTarget().GetType().String(), + req.GetBody().GetTarget().GetName(), + req.GetBody().GetChainId()), + err == nil) + return res, err +} + +// GetShardEvacuationStatus implements control.ControlServiceServer. +func (a *auditService) GetShardEvacuationStatus(ctx context.Context, req *ctl.GetShardEvacuationStatusRequest) (*ctl.GetShardEvacuationStatusResponse, error) { + res, err := a.next.GetShardEvacuationStatus(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_GetShardEvacuationStatus_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} + +// HealthCheck implements control.ControlServiceServer. +func (a *auditService) HealthCheck(ctx context.Context, req *ctl.HealthCheckRequest) (*ctl.HealthCheckResponse, error) { + res, err := a.next.HealthCheck(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_HealthCheck_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} + +// ListChainLocalOverrides implements control.ControlServiceServer. +func (a *auditService) ListChainLocalOverrides(ctx context.Context, req *ctl.ListChainLocalOverridesRequest) (*ctl.ListChainLocalOverridesResponse, error) { + res, err := a.next.ListChainLocalOverrides(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_ListChainLocalOverrides_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(), + req.GetBody().GetTarget().GetName(), + nil), + err == nil) + return res, err +} + +// ListShards implements control.ControlServiceServer. +func (a *auditService) ListShards(ctx context.Context, req *ctl.ListShardsRequest) (*ctl.ListShardsResponse, error) { + res, err := a.next.ListShards(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_ListShards_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} + +// ListTargetsLocalOverrides implements control.ControlServiceServer. +func (a *auditService) ListTargetsLocalOverrides(ctx context.Context, req *ctl.ListTargetsLocalOverridesRequest) (*ctl.ListTargetsLocalOverridesResponse, error) { + res, err := a.next.ListTargetsLocalOverrides(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_ListTargetsLocalOverrides_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromString(req.GetBody().GetChainName()), err == nil) + return res, err +} + +// RemoveChainLocalOverride implements control.ControlServiceServer. +func (a *auditService) RemoveChainLocalOverride(ctx context.Context, req *ctl.RemoveChainLocalOverrideRequest) (*ctl.RemoveChainLocalOverrideResponse, error) { + res, err := a.next.RemoveChainLocalOverride(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_RemoveChainLocalOverride_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(), + req.GetBody().GetTarget().GetName(), + req.GetBody().GetChainId()), + err == nil) + return res, err +} + +// RemoveChainLocalOverridesByTarget implements control.ControlServiceServer. +func (a *auditService) RemoveChainLocalOverridesByTarget(ctx context.Context, req *ctl.RemoveChainLocalOverridesByTargetRequest) (*ctl.RemoveChainLocalOverridesByTargetResponse, error) { + res, err := a.next.RemoveChainLocalOverridesByTarget(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_RemoveChainLocalOverridesByTarget_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(), + req.GetBody().GetTarget().GetName(), + nil), + err == nil) + return res, err +} + +// ResetShardEvacuationStatus implements control.ControlServiceServer. +func (a *auditService) ResetShardEvacuationStatus(ctx context.Context, req *ctl.ResetShardEvacuationStatusRequest) (*ctl.ResetShardEvacuationStatusResponse, error) { + res, err := a.next.ResetShardEvacuationStatus(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_ResetShardEvacuationStatus_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} + +// SealWriteCache implements control.ControlServiceServer. +func (a *auditService) SealWriteCache(ctx context.Context, req *ctl.SealWriteCacheRequest) (*ctl.SealWriteCacheResponse, error) { + res, err := a.next.SealWriteCache(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_SealWriteCache_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) + return res, err +} + +// SetNetmapStatus implements control.ControlServiceServer. +func (a *auditService) SetNetmapStatus(ctx context.Context, req *ctl.SetNetmapStatusRequest) (*ctl.SetNetmapStatusResponse, error) { + res, err := a.next.SetNetmapStatus(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_SetNetmapStatus_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} + +// SetShardMode implements control.ControlServiceServer. +func (a *auditService) SetShardMode(ctx context.Context, req *ctl.SetShardModeRequest) (*ctl.SetShardModeResponse, error) { + res, err := a.next.SetShardMode(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_SetShardMode_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) + return res, err +} + +// StartShardEvacuation implements control.ControlServiceServer. +func (a *auditService) StartShardEvacuation(ctx context.Context, req *ctl.StartShardEvacuationRequest) (*ctl.StartShardEvacuationResponse, error) { + res, err := a.next.StartShardEvacuation(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_StartShardEvacuation_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) + return res, err +} + +// StopShardEvacuation implements control.ControlServiceServer. +func (a *auditService) StopShardEvacuation(ctx context.Context, req *ctl.StopShardEvacuationRequest) (*ctl.StopShardEvacuationResponse, error) { + res, err := a.next.StopShardEvacuation(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_StopShardEvacuation_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} + +// SynchronizeTree implements control.ControlServiceServer. +func (a *auditService) SynchronizeTree(ctx context.Context, req *ctl.SynchronizeTreeRequest) (*ctl.SynchronizeTreeResponse, error) { + res, err := a.next.SynchronizeTree(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_SynchronizeTree_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return res, err +} diff --git a/pkg/services/netmap/audit.go b/pkg/services/netmap/audit.go new file mode 100644 index 0000000000..906fd398e3 --- /dev/null +++ b/pkg/services/netmap/audit.go @@ -0,0 +1,60 @@ +package netmap + +import ( + "context" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" +) + +var _ Server = (*auditService)(nil) + +type auditService struct { + next Server + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// LocalNodeInfo implements Server. +func (a *auditService) LocalNodeInfo(ctx context.Context, req *netmap.LocalNodeInfoRequest) (*netmap.LocalNodeInfoResponse, error) { + res, err := a.next.LocalNodeInfo(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, netmapGRPC.NetmapService_LocalNodeInfo_FullMethodName, req, + nil, err == nil) + return res, err +} + +// NetworkInfo implements Server. +func (a *auditService) NetworkInfo(ctx context.Context, req *netmap.NetworkInfoRequest) (*netmap.NetworkInfoResponse, error) { + res, err := a.next.NetworkInfo(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, netmapGRPC.NetmapService_NetworkInfo_FullMethodName, req, + nil, err == nil) + return res, err +} + +// Snapshot implements Server. +func (a *auditService) Snapshot(ctx context.Context, req *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) { + res, err := a.next.Snapshot(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, netmapGRPC.NetmapService_NetmapSnapshot_FullMethodName, req, + nil, err == nil) + return res, err +} diff --git a/pkg/services/object/audit.go b/pkg/services/object/audit.go new file mode 100644 index 0000000000..1305fa0087 --- /dev/null +++ b/pkg/services/object/audit.go @@ -0,0 +1,172 @@ +package object + +import ( + "context" + "errors" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +) + +var _ ServiceServer = (*auditService)(nil) + +type auditService struct { + next ServiceServer + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next ServiceServer, log *logger.Logger, enabled *atomic.Bool) ServiceServer { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// Delete implements ServiceServer. +func (a *auditService) Delete(ctx context.Context, req *object.DeleteRequest) (*object.DeleteResponse, error) { + res, err := a.next.Delete(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, objectGRPC.ObjectService_Delete_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) + return res, err +} + +// Get implements ServiceServer. +func (a *auditService) Get(req *object.GetRequest, stream GetObjectStream) error { + err := a.next.Get(req, stream) + if !a.enabled.Load() { + return err + } + audit.LogRequest(a.log, objectGRPC.ObjectService_Get_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) + return err +} + +// GetRange implements ServiceServer. +func (a *auditService) GetRange(req *object.GetRangeRequest, stream GetObjectRangeStream) error { + err := a.next.GetRange(req, stream) + if !a.enabled.Load() { + return err + } + audit.LogRequest(a.log, objectGRPC.ObjectService_GetRange_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) + return err +} + +// GetRangeHash implements ServiceServer. +func (a *auditService) GetRangeHash(ctx context.Context, req *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) { + resp, err := a.next.GetRangeHash(ctx, req) + if !a.enabled.Load() { + return resp, err + } + audit.LogRequest(a.log, objectGRPC.ObjectService_GetRangeHash_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) + return resp, err +} + +// Head implements ServiceServer. +func (a *auditService) Head(ctx context.Context, req *object.HeadRequest) (*object.HeadResponse, error) { + resp, err := a.next.Head(ctx, req) + if !a.enabled.Load() { + return resp, err + } + audit.LogRequest(a.log, objectGRPC.ObjectService_Head_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) + return resp, err +} + +// Put implements ServiceServer. +func (a *auditService) Put() (PutObjectStream, error) { + res, err := a.next.Put() + if !a.enabled.Load() { + return res, err + } + if err != nil { + audit.LogRequest(a.log, objectGRPC.ObjectService_Put_FullMethodName, nil, nil, false) + return res, err + } + return &auditPutStream{ + stream: res, + log: a.log, + }, nil +} + +// PutSingle implements ServiceServer. +func (a *auditService) PutSingle(ctx context.Context, req *object.PutSingleRequest) (*object.PutSingleResponse, error) { + resp, err := a.next.PutSingle(ctx, req) + if !a.enabled.Load() { + return resp, err + } + audit.LogRequest(a.log, objectGRPC.ObjectService_PutSingle_FullMethodName, req, + audit.TargetFromContainerIDObjectID(req.GetBody().GetObject().GetHeader().GetContainerID(), + req.GetBody().GetObject().GetObjectID()), + err == nil) + return resp, err +} + +// Search implements ServiceServer. +func (a *auditService) Search(req *object.SearchRequest, stream SearchStream) error { + err := a.next.Search(req, stream) + if !a.enabled.Load() { + return err + } + audit.LogRequest(a.log, objectGRPC.ObjectService_Search_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil) + return err +} + +var _ PutObjectStream = (*auditPutStream)(nil) + +type auditPutStream struct { + stream PutObjectStream + log *logger.Logger + + failed bool + key []byte + containerID *refs.ContainerID + objectID *refs.ObjectID +} + +// CloseAndRecv implements PutObjectStream. +func (a *auditPutStream) CloseAndRecv(ctx context.Context) (*object.PutResponse, error) { + resp, err := a.stream.CloseAndRecv(ctx) + if err != nil { + a.failed = true + } + a.objectID = resp.GetBody().GetObjectID() + audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key, + audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), + !a.failed) + return resp, err +} + +// Send implements PutObjectStream. +func (a *auditPutStream) Send(ctx context.Context, req *object.PutRequest) error { + if partInit, ok := req.GetBody().GetObjectPart().(*object.PutObjectPartInit); ok { + a.containerID = partInit.GetHeader().GetContainerID() + a.objectID = partInit.GetObjectID() + a.key = req.GetVerificationHeader().GetBodySignature().GetKey() + } + + err := a.stream.Send(ctx, req) + if err != nil { + a.failed = true + } + if !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here + audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key, + audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), + !a.failed) + } + return err +} diff --git a/pkg/services/session/audit.go b/pkg/services/session/audit.go new file mode 100644 index 0000000000..19d3383d9b --- /dev/null +++ b/pkg/services/session/audit.go @@ -0,0 +1,39 @@ +package session + +import ( + "context" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" +) + +var _ Server = (*auditService)(nil) + +type auditService struct { + next Server + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// Create implements Server. +func (a *auditService) Create(ctx context.Context, req *session.CreateRequest) (*session.CreateResponse, error) { + res, err := a.next.Create(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequest(a.log, sessionGRPC.SessionService_Create_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil) + return res, err +} diff --git a/pkg/services/tree/audit.go b/pkg/services/tree/audit.go new file mode 100644 index 0000000000..bec71f5d44 --- /dev/null +++ b/pkg/services/tree/audit.go @@ -0,0 +1,135 @@ +package tree + +import ( + "context" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" +) + +var _ TreeServiceServer = (*auditService)(nil) + +type auditService struct { + next TreeServiceServer + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next TreeServiceServer, log *logger.Logger, enabled *atomic.Bool) TreeServiceServer { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// Add implements TreeServiceServer. +func (a *auditService) Add(ctx context.Context, req *AddRequest) (*AddResponse, error) { + res, err := a.next.Add(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, TreeService_Add_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return res, err +} + +// AddByPath implements TreeServiceServer. +func (a *auditService) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByPathResponse, error) { + res, err := a.next.AddByPath(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, TreeService_AddByPath_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return res, err +} + +// Apply implements TreeServiceServer. +func (a *auditService) Apply(ctx context.Context, req *ApplyRequest) (*ApplyResponse, error) { + res, err := a.next.Apply(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, TreeService_Apply_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return res, err +} + +// GetNodeByPath implements TreeServiceServer. +func (a *auditService) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) (*GetNodeByPathResponse, error) { + res, err := a.next.GetNodeByPath(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, TreeService_GetNodeByPath_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return res, err +} + +// GetOpLog implements TreeServiceServer. +func (a *auditService) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) error { + err := a.next.GetOpLog(req, srv) + if !a.enabled.Load() { + return err + } + audit.LogRequestWithKey(a.log, TreeService_GetOpLog_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return err +} + +// GetSubTree implements TreeServiceServer. +func (a *auditService) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeServer) error { + err := a.next.GetSubTree(req, srv) + if !a.enabled.Load() { + return err + } + audit.LogRequestWithKey(a.log, TreeService_GetSubTree_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return err +} + +// Healthcheck implements TreeServiceServer. +func (a *auditService) Healthcheck(ctx context.Context, req *HealthcheckRequest) (*HealthcheckResponse, error) { + res, err := a.next.Healthcheck(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, TreeService_Healthcheck_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} + +// Move implements TreeServiceServer. +func (a *auditService) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, error) { + res, err := a.next.Move(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, TreeService_Move_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return res, err +} + +// Remove implements TreeServiceServer. +func (a *auditService) Remove(ctx context.Context, req *RemoveRequest) (*RemoveResponse, error) { + res, err := a.next.Remove(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, TreeService_Remove_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) + return res, err +} + +// TreeList implements TreeServiceServer. +func (a *auditService) TreeList(ctx context.Context, req *TreeListRequest) (*TreeListResponse, error) { + res, err := a.next.TreeList(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, TreeService_TreeList_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromTreeID(req.GetBody().GetContainerId(), ""), err == nil) + return res, err +} From fd28461def3bc9af15c699b071f0b179b1cf5e00 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 18 Jun 2024 12:40:38 +0300 Subject: [PATCH 0632/1413] [#1184] ir: Add grpc middleware for control service Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-ir/config.go | 1 + cmd/frostfs-ir/defaults.go | 2 + cmd/frostfs-ir/main.go | 4 +- pkg/innerring/initialization.go | 8 +- pkg/innerring/innerring.go | 4 +- pkg/services/control/ir/server/audit.go | 108 ++++++++++++++++++++++++ 6 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 pkg/services/control/ir/server/audit.go diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index c73b68eb59..c3227a182a 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -35,6 +35,7 @@ func reloadConfig() error { return err } cmode.Store(cfg.GetBool("node.kludge_compatibility_mode")) + audit.Store(cfg.GetBool("audit.enabled")) err = logPrm.SetLevelString(cfg.GetString("logger.level")) if err != nil { return err diff --git a/cmd/frostfs-ir/defaults.go b/cmd/frostfs-ir/defaults.go index 23a4755910..e703301ae2 100644 --- a/cmd/frostfs-ir/defaults.go +++ b/cmd/frostfs-ir/defaults.go @@ -45,6 +45,8 @@ func defaultConfiguration(cfg *viper.Viper) { cfg.SetDefault("governance.disable", false) cfg.SetDefault("node.kludge_compatibility_mode", false) + + cfg.SetDefault("audit.enabled", false) } func setControlDefaults(cfg *viper.Viper) { diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 31390dd74e..206059b5d6 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -39,6 +39,7 @@ var ( configFile *string configDir *string cmode = &atomic.Bool{} + audit = &atomic.Bool{} ) func exitErr(err error) { @@ -87,8 +88,9 @@ func main() { metricsCmp = newMetricsComponent() metricsCmp.init() + audit.Store(cfg.GetBool("audit.enabled")) - innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode) + innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode, audit) exitErr(err) pprofCmp.start() diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index 1a41742893..7da0a9794e 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "net" + "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet" @@ -26,6 +27,7 @@ import ( control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" controlsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" utilConfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/spf13/viper" @@ -310,7 +312,7 @@ func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error { return bindMainnetProcessor(frostfsProcessor, s) } -func (s *Server) initGRPCServer(cfg *viper.Viper) error { +func (s *Server) initGRPCServer(cfg *viper.Viper, log *logger.Logger, audit *atomic.Bool) error { controlSvcEndpoint := cfg.GetString("control.grpc.endpoint") if controlSvcEndpoint == "" { s.log.Info(logs.InnerringNoControlServerEndpointSpecified) @@ -337,9 +339,9 @@ func (s *Server) initGRPCServer(cfg *viper.Viper) error { p.SetPrivateKey(*s.key) p.SetHealthChecker(s) - controlSvc := controlsrv.New(p, s.netmapClient, s.containerClient, + controlSvc := controlsrv.NewAuditService(controlsrv.New(p, s.netmapClient, s.containerClient, controlsrv.WithAllowedKeys(authKeys), - ) + ), log, audit) grpcControlSrv := grpc.NewServer() control.RegisterControlServiceServer(grpcControlSrv, controlSvc) diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 86424abef6..944aa8b76b 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -331,7 +331,7 @@ func (s *Server) registerStarter(f func() error) { // New creates instance of inner ring sever structure. func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error, - metrics *metrics.InnerRingServiceMetrics, cmode *atomic.Bool, + metrics *metrics.InnerRingServiceMetrics, cmode *atomic.Bool, audit *atomic.Bool, ) (*Server, error) { var err error server := &Server{ @@ -403,7 +403,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan server.initTimers(cfg, morphClients) - err = server.initGRPCServer(cfg) + err = server.initGRPCServer(cfg, log, audit) if err != nil { return nil, err } diff --git a/pkg/services/control/ir/server/audit.go b/pkg/services/control/ir/server/audit.go new file mode 100644 index 0000000000..9f7a8b8799 --- /dev/null +++ b/pkg/services/control/ir/server/audit.go @@ -0,0 +1,108 @@ +package control + +import ( + "context" + "encoding/hex" + "strings" + "sync/atomic" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" + control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" +) + +var _ control.ControlServiceServer = (*auditService)(nil) + +type auditService struct { + next *Server + log *logger.Logger + enabled *atomic.Bool +} + +func NewAuditService(next *Server, log *logger.Logger, enabled *atomic.Bool) control.ControlServiceServer { + return &auditService{ + next: next, + log: log, + enabled: enabled, + } +} + +// HealthCheck implements control.ControlServiceServer. +func (a *auditService) HealthCheck(ctx context.Context, req *control.HealthCheckRequest) (*control.HealthCheckResponse, error) { + res, err := a.next.HealthCheck(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, control.ControlService_HealthCheck_FullMethodName, req.GetSignature().GetKey(), nil, err == nil) + return res, err +} + +// RemoveContainer implements control.ControlServiceServer. +func (a *auditService) RemoveContainer(ctx context.Context, req *control.RemoveContainerRequest) (*control.RemoveContainerResponse, error) { + res, err := a.next.RemoveContainer(ctx, req) + if !a.enabled.Load() { + return res, err + } + + sb := &strings.Builder{} + var withConatiner bool + if len(req.GetBody().GetContainerId()) > 0 { + withConatiner = true + sb.WriteString("containerID:") + var containerID cid.ID + if err := containerID.Decode(req.GetBody().GetContainerId()); err != nil { + sb.WriteString(audit.InvalidValue) + } else { + sb.WriteString(containerID.EncodeToString()) + } + } + + if len(req.GetBody().GetOwner()) > 0 { + if withConatiner { + sb.WriteString(";") + } + sb.WriteString("owner:") + + var ownerID refs.OwnerID + if err := ownerID.Unmarshal(req.GetBody().GetOwner()); err != nil { + sb.WriteString(audit.InvalidValue) + } else { + var owner user.ID + if err := owner.ReadFromV2(ownerID); err != nil { + sb.WriteString(audit.InvalidValue) + } else { + sb.WriteString(owner.EncodeToString()) + } + } + } + + audit.LogRequestWithKey(a.log, control.ControlService_RemoveContainer_FullMethodName, req.GetSignature().GetKey(), sb, err == nil) + return res, err +} + +// RemoveNode implements control.ControlServiceServer. +func (a *auditService) RemoveNode(ctx context.Context, req *control.RemoveNodeRequest) (*control.RemoveNodeResponse, error) { + res, err := a.next.RemoveNode(ctx, req) + if !a.enabled.Load() { + return res, err + } + + audit.LogRequestWithKey(a.log, control.ControlService_RemoveNode_FullMethodName, req.GetSignature().GetKey(), + audit.TargetFromString(hex.EncodeToString(req.GetBody().GetKey())), err == nil) + return res, err +} + +// TickEpoch implements control.ControlServiceServer. +func (a *auditService) TickEpoch(ctx context.Context, req *control.TickEpochRequest) (*control.TickEpochResponse, error) { + res, err := a.next.TickEpoch(ctx, req) + if !a.enabled.Load() { + return res, err + } + + audit.LogRequestWithKey(a.log, control.ControlService_TickEpoch_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} From 40b68bcb6c16331fd8036a0b730ee7442025ccdb Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 18 Jun 2024 15:06:54 +0300 Subject: [PATCH 0633/1413] [#1109] object: Validate attribute `EXPIRATION_EPOCH` on `put` Signed-off-by: Anton Nikiforov --- pkg/core/object/fmt.go | 56 +++++++++++++++++-------------------- pkg/core/object/fmt_test.go | 2 ++ 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index fa1e40dd0f..b997aa1822 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -124,15 +124,22 @@ func (v *FormatValidator) Validate(ctx context.Context, obj *objectSDK.Object, u return fmt.Errorf("invalid attributes: %w", err) } + exp, err := expirationEpochAttribute(obj) + if err != nil { + if !errors.Is(err, errNoExpirationEpoch) { + return fmt.Errorf("object did not pass expiration check: %w", err) + } + } else if !unprepared && exp < v.netState.CurrentEpoch() { + if err := v.checkIfExpired(ctx, obj); err != nil { + return fmt.Errorf("object did not pass expiration check: %w", err) + } + } + if !unprepared { if err := v.validateSignatureKey(obj); err != nil { return fmt.Errorf("(%T) could not validate signature key: %w", v, err) } - if err := v.checkExpiration(ctx, obj); err != nil { - return fmt.Errorf("object did not pass expiration check: %w", err) - } - if err := objectSDK.CheckHeaderVerificationFields(obj); err != nil { return fmt.Errorf("(%T) could not validate header fields: %w", v, err) } @@ -348,35 +355,24 @@ func (v *FormatValidator) fillAndValidateTombstoneMeta(o *objectSDK.Object, meta var errExpired = errors.New("object has expired") -func (v *FormatValidator) checkExpiration(ctx context.Context, obj *objectSDK.Object) error { - exp, err := expirationEpochAttribute(obj) - if err != nil { - if errors.Is(err, errNoExpirationEpoch) { - return nil // objects without expiration attribute are valid - } +func (v *FormatValidator) checkIfExpired(ctx context.Context, obj *objectSDK.Object) error { + // an object could be expired but locked; + // put such an object is a correct operation - return err + cID, _ := obj.ContainerID() + oID, _ := obj.ID() + + var addr oid.Address + addr.SetContainer(cID) + addr.SetObject(oID) + + locked, err := v.e.IsLocked(ctx, addr) + if err != nil { + return fmt.Errorf("locking status check for an expired object: %w", err) } - if exp < v.netState.CurrentEpoch() { - // an object could be expired but locked; - // put such an object is a correct operation - - cID, _ := obj.ContainerID() - oID, _ := obj.ID() - - var addr oid.Address - addr.SetContainer(cID) - addr.SetObject(oID) - - locked, err := v.e.IsLocked(ctx, addr) - if err != nil { - return fmt.Errorf("locking status check for an expired object: %w", err) - } - - if !locked { - return errExpired - } + if !locked { + return errExpired } return nil diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index a8901ad6d9..77afbfc459 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -195,6 +195,8 @@ func TestFormatValidator_Validate(t *testing.T) { val := "text" err := v.Validate(context.Background(), fn(val), false) require.Error(t, err) + err = v.Validate(context.Background(), fn(val), true) + require.Error(t, err) }) t.Run("expired object", func(t *testing.T) { From 11e880de7f87498385006b9c96f85e972ad65950 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 18 Jun 2024 14:33:45 +0300 Subject: [PATCH 0634/1413] [#1186] cli: Make owner field optional for bearer token Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/bearer/create.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-cli/modules/bearer/create.go b/cmd/frostfs-cli/modules/bearer/create.go index d94b39207c..a86506c375 100644 --- a/cmd/frostfs-cli/modules/bearer/create.go +++ b/cmd/frostfs-cli/modules/bearer/create.go @@ -67,7 +67,6 @@ func init() { _ = cobra.MarkFlagFilename(createCmd.Flags(), apeFlag) _ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.ExpireAt) - _ = cobra.MarkFlagRequired(createCmd.Flags(), ownerFlag) _ = cobra.MarkFlagRequired(createCmd.Flags(), outFlag) } @@ -108,16 +107,16 @@ func createToken(cmd *cobra.Command, _ []string) { fmt.Errorf("expiration epoch is less than not-valid-before epoch: %d < %d", exp, nvb)) } - ownerStr, _ := cmd.Flags().GetString(ownerFlag) - - var ownerID user.ID - commonCmd.ExitOnErr(cmd, "can't parse recipient: %w", ownerID.DecodeString(ownerStr)) - var b bearer.Token b.SetExp(exp) b.SetNbf(nvb) b.SetIat(iat) - b.ForUser(ownerID) + + if ownerStr, _ := cmd.Flags().GetString(ownerFlag); ownerStr != "" { + var ownerID user.ID + commonCmd.ExitOnErr(cmd, "can't parse recipient: %w", ownerID.DecodeString(ownerStr)) + b.ForUser(ownerID) + } impersonate, _ := cmd.Flags().GetBool(impersonateFlag) b.SetImpersonate(impersonate) From 68eb68f59a10284025ae345407f486f63a7b620a Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 18 Jun 2024 18:29:56 +0300 Subject: [PATCH 0635/1413] [#1189] cli: Make util subcommand convert eACL to APE chains Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/util/convert_eacl.go | 33 ++++++++--- internal/ape/converter.go | 60 +++++++++++++++----- 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/cmd/frostfs-cli/modules/util/convert_eacl.go b/cmd/frostfs-cli/modules/util/convert_eacl.go index 774d500bc6..d588ba35d6 100644 --- a/cmd/frostfs-cli/modules/util/convert_eacl.go +++ b/cmd/frostfs-cli/modules/util/convert_eacl.go @@ -6,9 +6,17 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) +const ( + fromFlagStr = "from" + toFlagStr = "to" + apeFlagStr = "ape" +) + var convertEACLCmd = &cobra.Command{ Use: "eacl", Short: "Convert representation of extended ACL table", @@ -18,24 +26,35 @@ var convertEACLCmd = &cobra.Command{ func initConvertEACLCmd() { flags := convertEACLCmd.Flags() - flags.String("from", "", "File with JSON or binary encoded extended ACL table") - _ = convertEACLCmd.MarkFlagFilename("from") - _ = convertEACLCmd.MarkFlagRequired("from") + flags.String(fromFlagStr, "", "File with JSON or binary encoded extended ACL table") + _ = convertEACLCmd.MarkFlagFilename(fromFlagStr) + _ = convertEACLCmd.MarkFlagRequired(fromFlagStr) - flags.String("to", "", "File to dump extended ACL table (default: binary encoded)") + flags.String(toFlagStr, "", "File to dump extended ACL table (default: binary encoded)") flags.Bool(commonflags.JSON, false, "Dump extended ACL table in JSON encoding") + + flags.Bool(apeFlagStr, false, "Dump converted eACL table to APE chain format") + + convertEACLCmd.MarkFlagsMutuallyExclusive(apeFlagStr, commonflags.JSON) } func convertEACLTable(cmd *cobra.Command, _ []string) { - pathFrom := cmd.Flag("from").Value.String() - to := cmd.Flag("to").Value.String() + pathFrom := cmd.Flag(fromFlagStr).Value.String() + to := cmd.Flag(toFlagStr).Value.String() jsonFlag, _ := cmd.Flags().GetBool(commonflags.JSON) + apeFlag, _ := cmd.Flags().GetBool(apeFlagStr) table := common.ReadEACL(cmd, pathFrom) var data []byte var err error - if jsonFlag || len(to) == 0 { + + if apeFlag { + var ch *chain.Chain + ch, err = apeutil.ConvertEACLToAPE(table) + commonCmd.ExitOnErr(cmd, "convert eACL table to APE chain error: %w", err) + data = ch.Bytes() + } else if jsonFlag || len(to) == 0 { data, err = table.MarshalJSON() commonCmd.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err) } else { diff --git a/internal/ape/converter.go b/internal/ape/converter.go index a0cc138d10..eb80e7ded1 100644 --- a/internal/ape/converter.go +++ b/internal/ape/converter.go @@ -69,6 +69,50 @@ func ConvertEACLToAPE(eaclTable *eacl.Table) (*apechain.Chain, error) { return res, nil } +func apeRoleConds(role eacl.Role) (res []apechain.Condition) { + switch role { + case eacl.RoleSystem: + res = append(res, + apechain.Condition{ + Op: apechain.CondStringEquals, + Kind: apechain.KindRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleContainer, + }, + ) + res = append(res, + apechain.Condition{ + Op: apechain.CondStringEquals, + Kind: apechain.KindRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleIR, + }, + ) + case eacl.RoleOthers: + res = append(res, + apechain.Condition{ + Op: apechain.CondStringEquals, + Kind: apechain.KindRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOthers, + }, + ) + case eacl.RoleUser: + res = append(res, + apechain.Condition{ + Op: apechain.CondStringEquals, + Kind: apechain.KindRequest, + Key: nativeschema.PropertyKeyActorRole, + Value: nativeschema.PropertyValueContainerRoleOwner, + }, + ) + case eacl.RoleUnknown: + // such condition has no effect + default: + } + return +} + func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain.Actions, res apechain.Resources, targets []eacl.Target) []apechain.Rule { // see https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/src/commit/ab75edd70939564421936d207ef80d6c1398b51b/eacl/validator.go#L101 // role OR public key must be equal @@ -79,13 +123,7 @@ func appendTargetsOnly(source []apechain.Rule, st apechain.Status, act apechain. Any: true, } for _, target := range targets { - var roleCondition apechain.Condition - roleCondition.Kind = apechain.KindRequest - roleCondition.Key = nativeschema.PropertyKeyActorRole - roleCondition.Value = target.Role().String() - roleCondition.Op = apechain.CondStringEquals - rule.Condition = append(rule.Condition, roleCondition) - + rule.Condition = append(rule.Condition, apeRoleConds(target.Role())...) for _, binKey := range target.BinaryKeys() { var pubKeyCondition apechain.Condition pubKeyCondition.Kind = apechain.KindRequest @@ -111,13 +149,7 @@ func appendTargetsAndFilters(source []apechain.Rule, st apechain.Status, act ape Actions: act, Resources: res, } - var roleCondition apechain.Condition - roleCondition.Kind = apechain.KindRequest - roleCondition.Key = nativeschema.PropertyKeyActorRole - roleCondition.Value = target.Role().String() - roleCondition.Op = apechain.CondStringEquals - - rule.Condition = append(rule.Condition, roleCondition) + rule.Condition = append(rule.Condition, apeRoleConds(target.Role())...) rule.Condition, err = appendFilters(rule.Condition, filters) if err != nil { return nil, err From ec76689ab796b1ba3ecca1c21893e337ec853695 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 20 Jun 2024 11:45:25 +0300 Subject: [PATCH 0636/1413] [#1189] cli: Fix unit-test for eACL converter Signed-off-by: Airat Arifullin --- internal/ape/converter_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/ape/converter_test.go b/internal/ape/converter_test.go index b5f8939c41..28125606cf 100644 --- a/internal/ape/converter_test.go +++ b/internal/ape/converter_test.go @@ -105,7 +105,7 @@ func TestNoFilters(t *testing.T) { req := &testRequest{ props: map[string]string{ - nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + nativeschema.PropertyKeyActorRole: nativeschema.PropertyValueContainerRoleOthers, }, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, } @@ -150,7 +150,7 @@ func TestNoFilters(t *testing.T) { req := &testRequest{ props: map[string]string{ - nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + nativeschema.PropertyKeyActorRole: nativeschema.PropertyValueContainerRoleOthers, nativeschema.PropertyKeyActorPublicKey: string(p2.PublicKey().Bytes()), }, res: &testResource{name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString())}, @@ -283,7 +283,7 @@ func TestWithFilters(t *testing.T) { req := &testRequest{ props: map[string]string{ - nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + nativeschema.PropertyKeyActorRole: nativeschema.PropertyValueContainerRoleOthers, }, res: &testResource{ name: fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, cnrID.EncodeToString()), @@ -335,7 +335,7 @@ func TestWithFilters(t *testing.T) { req := &testRequest{ props: map[string]string{ - nativeschema.PropertyKeyActorRole: eacl.RoleOthers.String(), + nativeschema.PropertyKeyActorRole: nativeschema.PropertyValueContainerRoleOthers, attrKey: attrValue, }, res: &testResource{ From 9ac74efc41882d1b5e88756197187ae4e78871ab Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 18 Jun 2024 11:11:56 +0300 Subject: [PATCH 0637/1413] [#1173] shard: Use `mode` from config on `reload` Signed-off-by: Anton Nikiforov --- internal/logs/logs.go | 1 - pkg/local_object_storage/shard/control.go | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index eeb2fbf3fd..78f00c4ee1 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -247,7 +247,6 @@ const ( ShardCouldNotCloseShardComponent = "could not close shard component" ShardCantOpenMetabaseMoveToADegradedMode = "can't open metabase, move to a degraded mode" ShardCantInitializeMetabaseMoveToADegradedreadonlyMode = "can't initialize metabase, move to a degraded-read-only mode" - ShardTryingToRestoreReadwriteMode = "trying to restore read-write mode" ShardStopEventListenerByClosedEventChannel = "stop event listener by closed `event` channel" ShardStopEventListenerByClosedStopChannel = "stop event listener by closed `stop` channel" ShardStopEventListenerByContext = "stop event listener by context" diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 38a29cb122..90d7afdd4d 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -418,9 +418,7 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { return err } } - - s.log.Info(logs.ShardTryingToRestoreReadwriteMode) - return s.setMode(mode.ReadWrite) + return s.setMode(c.info.Mode) } func (s *Shard) lockExclusive() func() { From a83eeddb1d041611666c8481b275c5d2ce249293 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 20 Jun 2024 16:03:58 +0300 Subject: [PATCH 0638/1413] [#60] control: Add GetNetmapStatus method Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/netmap.go | 9 + pkg/services/control/rpc.go | 21 + pkg/services/control/server/audit.go | 11 + .../control/server/get_netmap_status.go | 35 + pkg/services/control/server/server.go | 2 + pkg/services/control/service.pb.go | 2617 +++++++++-------- pkg/services/control/service.proto | 31 + pkg/services/control/service_frostfs.pb.go | 165 ++ pkg/services/control/service_grpc.pb.go | 39 + 9 files changed, 1770 insertions(+), 1160 deletions(-) create mode 100644 pkg/services/control/server/get_netmap_status.go diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 6aff8ddf2d..2d424eec68 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -374,6 +374,15 @@ func (c *cfg) SetNetmapStatus(st control.NetmapStatus) error { return c.updateNetMapState(func(*nmClient.UpdatePeerPrm) {}) } +func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) { + epoch, err := c.netMapSource.Epoch() + if err != nil { + return control.NetmapStatus_STATUS_UNDEFINED, 0, fmt.Errorf("failed to get current epoch: %w", err) + } + st := c.NetmapStatus() + return st, epoch, nil +} + func (c *cfg) ForceMaintenance() error { return c.setMaintenanceStatus(true) } diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index f9397c1282..a90e58a651 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -10,6 +10,7 @@ const serviceName = "control.ControlService" const ( rpcHealthCheck = "HealthCheck" rpcSetNetmapStatus = "SetNetmapStatus" + rpcGetNetmapStatus = "GetNetmapStatus" rpcDropObjects = "DropObjects" rpcListShards = "ListShards" rpcSetShardMode = "SetShardMode" @@ -70,6 +71,26 @@ func SetNetmapStatus( return wResp.message, nil } +// GetNetmapStatus executes ControlService.GetNetmapStatus RPC. +func GetNetmapStatus( + cli *client.Client, + req *GetNetmapStatusRequest, + opts ...client.CallOption, +) (*GetNetmapStatusResponse, error) { + wResp := newResponseWrapper[GetNetmapStatusResponse]() + + wReq := &requestWrapper{ + m: req, + } + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcGetNetmapStatus), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.message, nil +} + // DropObjects executes ControlService.DropObjects RPC. func DropObjects( cli *client.Client, diff --git a/pkg/services/control/server/audit.go b/pkg/services/control/server/audit.go index 16c04a8c9e..6443ea378c 100644 --- a/pkg/services/control/server/audit.go +++ b/pkg/services/control/server/audit.go @@ -242,6 +242,17 @@ func (a *auditService) SetNetmapStatus(ctx context.Context, req *ctl.SetNetmapSt return res, err } +// GetNetmapStatus implements control.ControlServiceServer. +func (a *auditService) GetNetmapStatus(ctx context.Context, req *ctl.GetNetmapStatusRequest) (*ctl.GetNetmapStatusResponse, error) { + res, err := a.next.GetNetmapStatus(ctx, req) + if !a.enabled.Load() { + return res, err + } + audit.LogRequestWithKey(a.log, ctl.ControlService_GetNetmapStatus_FullMethodName, req.GetSignature().GetKey(), + nil, err == nil) + return res, err +} + // SetShardMode implements control.ControlServiceServer. func (a *auditService) SetShardMode(ctx context.Context, req *ctl.SetShardModeRequest) (*ctl.SetShardModeResponse, error) { res, err := a.next.SetShardMode(ctx, req) diff --git a/pkg/services/control/server/get_netmap_status.go b/pkg/services/control/server/get_netmap_status.go new file mode 100644 index 0000000000..1c038253aa --- /dev/null +++ b/pkg/services/control/server/get_netmap_status.go @@ -0,0 +1,35 @@ +package control + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// GetNetmapStatus gets node status in FrostFS network. +func (s *Server) GetNetmapStatus(_ context.Context, req *control.GetNetmapStatusRequest) (*control.GetNetmapStatusResponse, error) { + if err := s.isValidRequest(req); err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + st, epoch, err := s.nodeState.GetNetmapStatus() + if err != nil { + return nil, err + } + + resp := &control.GetNetmapStatusResponse{ + Body: &control.GetNetmapStatusResponse_Body{ + Status: st, + Epoch: epoch, + }, + } + + if err := ctrlmessage.Sign(s.key, resp); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + return resp, nil +} diff --git a/pkg/services/control/server/server.go b/pkg/services/control/server/server.go index 7cfa93f05c..f3fe56a46c 100644 --- a/pkg/services/control/server/server.go +++ b/pkg/services/control/server/server.go @@ -50,6 +50,8 @@ type NodeState interface { // ForceMaintenance works like SetNetmapStatus(control.NetmapStatus_MAINTENANCE) // but starts local maintenance regardless of the network settings. ForceMaintenance() error + + GetNetmapStatus() (control.NetmapStatus, uint64, error) } // LocalOverrideStorageDecorator interface provides methods to decorate LocalOverrideEngine diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 9c597beecc..727dd1218b 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -66,7 +66,7 @@ func (x StartShardEvacuationRequest_Body_Scope) Number() protoreflect.EnumNumber // Deprecated: Use StartShardEvacuationRequest_Body_Scope.Descriptor instead. func (StartShardEvacuationRequest_Body_Scope) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{18, 0, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{20, 0, 0} } // Evacuate status enum. @@ -116,7 +116,7 @@ func (x GetShardEvacuationStatusResponse_Body_Status) Number() protoreflect.Enum // Deprecated: Use GetShardEvacuationStatusResponse_Body_Status.Descriptor instead. func (GetShardEvacuationStatusResponse_Body_Status) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21, 0, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0, 0} } // Health check request. @@ -351,6 +351,122 @@ func (x *SetNetmapStatusResponse) GetSignature() *Signature { return nil } +// Get netmap status request. +type GetNetmapStatusRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of set netmap status request message. + Body *GetNetmapStatusRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Body signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetNetmapStatusRequest) Reset() { + *x = GetNetmapStatusRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNetmapStatusRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNetmapStatusRequest) ProtoMessage() {} + +func (x *GetNetmapStatusRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNetmapStatusRequest.ProtoReflect.Descriptor instead. +func (*GetNetmapStatusRequest) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{4} +} + +func (x *GetNetmapStatusRequest) GetBody() *GetNetmapStatusRequest_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetNetmapStatusRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + +// Get netmap status response. +type GetNetmapStatusResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Body of get netmap status response message. + Body *GetNetmapStatusResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` + // Body signature. + Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` +} + +func (x *GetNetmapStatusResponse) Reset() { + *x = GetNetmapStatusResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNetmapStatusResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNetmapStatusResponse) ProtoMessage() {} + +func (x *GetNetmapStatusResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNetmapStatusResponse.ProtoReflect.Descriptor instead. +func (*GetNetmapStatusResponse) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{5} +} + +func (x *GetNetmapStatusResponse) GetBody() *GetNetmapStatusResponse_Body { + if x != nil { + return x.Body + } + return nil +} + +func (x *GetNetmapStatusResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} + // Request to drop the objects. type DropObjectsRequest struct { state protoimpl.MessageState @@ -366,7 +482,7 @@ type DropObjectsRequest struct { func (x *DropObjectsRequest) Reset() { *x = DropObjectsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[4] + mi := &file_pkg_services_control_service_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -379,7 +495,7 @@ func (x *DropObjectsRequest) String() string { func (*DropObjectsRequest) ProtoMessage() {} func (x *DropObjectsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[4] + mi := &file_pkg_services_control_service_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -392,7 +508,7 @@ func (x *DropObjectsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DropObjectsRequest.ProtoReflect.Descriptor instead. func (*DropObjectsRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{4} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{6} } func (x *DropObjectsRequest) GetBody() *DropObjectsRequest_Body { @@ -424,7 +540,7 @@ type DropObjectsResponse struct { func (x *DropObjectsResponse) Reset() { *x = DropObjectsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[5] + mi := &file_pkg_services_control_service_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -437,7 +553,7 @@ func (x *DropObjectsResponse) String() string { func (*DropObjectsResponse) ProtoMessage() {} func (x *DropObjectsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[5] + mi := &file_pkg_services_control_service_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -450,7 +566,7 @@ func (x *DropObjectsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DropObjectsResponse.ProtoReflect.Descriptor instead. func (*DropObjectsResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{5} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{7} } func (x *DropObjectsResponse) GetBody() *DropObjectsResponse_Body { @@ -482,7 +598,7 @@ type ListShardsRequest struct { func (x *ListShardsRequest) Reset() { *x = ListShardsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[6] + mi := &file_pkg_services_control_service_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -495,7 +611,7 @@ func (x *ListShardsRequest) String() string { func (*ListShardsRequest) ProtoMessage() {} func (x *ListShardsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[6] + mi := &file_pkg_services_control_service_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -508,7 +624,7 @@ func (x *ListShardsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListShardsRequest.ProtoReflect.Descriptor instead. func (*ListShardsRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{6} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{8} } func (x *ListShardsRequest) GetBody() *ListShardsRequest_Body { @@ -540,7 +656,7 @@ type ListShardsResponse struct { func (x *ListShardsResponse) Reset() { *x = ListShardsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[7] + mi := &file_pkg_services_control_service_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -553,7 +669,7 @@ func (x *ListShardsResponse) String() string { func (*ListShardsResponse) ProtoMessage() {} func (x *ListShardsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[7] + mi := &file_pkg_services_control_service_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -566,7 +682,7 @@ func (x *ListShardsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListShardsResponse.ProtoReflect.Descriptor instead. func (*ListShardsResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{7} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{9} } func (x *ListShardsResponse) GetBody() *ListShardsResponse_Body { @@ -598,7 +714,7 @@ type SetShardModeRequest struct { func (x *SetShardModeRequest) Reset() { *x = SetShardModeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[8] + mi := &file_pkg_services_control_service_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -611,7 +727,7 @@ func (x *SetShardModeRequest) String() string { func (*SetShardModeRequest) ProtoMessage() {} func (x *SetShardModeRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[8] + mi := &file_pkg_services_control_service_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -624,7 +740,7 @@ func (x *SetShardModeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SetShardModeRequest.ProtoReflect.Descriptor instead. func (*SetShardModeRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{8} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{10} } func (x *SetShardModeRequest) GetBody() *SetShardModeRequest_Body { @@ -656,7 +772,7 @@ type SetShardModeResponse struct { func (x *SetShardModeResponse) Reset() { *x = SetShardModeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[9] + mi := &file_pkg_services_control_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -669,7 +785,7 @@ func (x *SetShardModeResponse) String() string { func (*SetShardModeResponse) ProtoMessage() {} func (x *SetShardModeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[9] + mi := &file_pkg_services_control_service_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -682,7 +798,7 @@ func (x *SetShardModeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SetShardModeResponse.ProtoReflect.Descriptor instead. func (*SetShardModeResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{9} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{11} } func (x *SetShardModeResponse) GetBody() *SetShardModeResponse_Body { @@ -714,7 +830,7 @@ type SynchronizeTreeRequest struct { func (x *SynchronizeTreeRequest) Reset() { *x = SynchronizeTreeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[10] + mi := &file_pkg_services_control_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -727,7 +843,7 @@ func (x *SynchronizeTreeRequest) String() string { func (*SynchronizeTreeRequest) ProtoMessage() {} func (x *SynchronizeTreeRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[10] + mi := &file_pkg_services_control_service_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -740,7 +856,7 @@ func (x *SynchronizeTreeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SynchronizeTreeRequest.ProtoReflect.Descriptor instead. func (*SynchronizeTreeRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{10} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{12} } func (x *SynchronizeTreeRequest) GetBody() *SynchronizeTreeRequest_Body { @@ -772,7 +888,7 @@ type SynchronizeTreeResponse struct { func (x *SynchronizeTreeResponse) Reset() { *x = SynchronizeTreeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[11] + mi := &file_pkg_services_control_service_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -785,7 +901,7 @@ func (x *SynchronizeTreeResponse) String() string { func (*SynchronizeTreeResponse) ProtoMessage() {} func (x *SynchronizeTreeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[11] + mi := &file_pkg_services_control_service_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -798,7 +914,7 @@ func (x *SynchronizeTreeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SynchronizeTreeResponse.ProtoReflect.Descriptor instead. func (*SynchronizeTreeResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{11} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{13} } func (x *SynchronizeTreeResponse) GetBody() *SynchronizeTreeResponse_Body { @@ -828,7 +944,7 @@ type EvacuateShardRequest struct { func (x *EvacuateShardRequest) Reset() { *x = EvacuateShardRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[12] + mi := &file_pkg_services_control_service_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -841,7 +957,7 @@ func (x *EvacuateShardRequest) String() string { func (*EvacuateShardRequest) ProtoMessage() {} func (x *EvacuateShardRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[12] + mi := &file_pkg_services_control_service_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -854,7 +970,7 @@ func (x *EvacuateShardRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EvacuateShardRequest.ProtoReflect.Descriptor instead. func (*EvacuateShardRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{12} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{14} } func (x *EvacuateShardRequest) GetBody() *EvacuateShardRequest_Body { @@ -884,7 +1000,7 @@ type EvacuateShardResponse struct { func (x *EvacuateShardResponse) Reset() { *x = EvacuateShardResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[13] + mi := &file_pkg_services_control_service_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -897,7 +1013,7 @@ func (x *EvacuateShardResponse) String() string { func (*EvacuateShardResponse) ProtoMessage() {} func (x *EvacuateShardResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[13] + mi := &file_pkg_services_control_service_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -910,7 +1026,7 @@ func (x *EvacuateShardResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EvacuateShardResponse.ProtoReflect.Descriptor instead. func (*EvacuateShardResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{13} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{15} } func (x *EvacuateShardResponse) GetBody() *EvacuateShardResponse_Body { @@ -940,7 +1056,7 @@ type FlushCacheRequest struct { func (x *FlushCacheRequest) Reset() { *x = FlushCacheRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[14] + mi := &file_pkg_services_control_service_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -953,7 +1069,7 @@ func (x *FlushCacheRequest) String() string { func (*FlushCacheRequest) ProtoMessage() {} func (x *FlushCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[14] + mi := &file_pkg_services_control_service_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -966,7 +1082,7 @@ func (x *FlushCacheRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FlushCacheRequest.ProtoReflect.Descriptor instead. func (*FlushCacheRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{14} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{16} } func (x *FlushCacheRequest) GetBody() *FlushCacheRequest_Body { @@ -996,7 +1112,7 @@ type FlushCacheResponse struct { func (x *FlushCacheResponse) Reset() { *x = FlushCacheResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[15] + mi := &file_pkg_services_control_service_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1009,7 +1125,7 @@ func (x *FlushCacheResponse) String() string { func (*FlushCacheResponse) ProtoMessage() {} func (x *FlushCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[15] + mi := &file_pkg_services_control_service_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1022,7 +1138,7 @@ func (x *FlushCacheResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FlushCacheResponse.ProtoReflect.Descriptor instead. func (*FlushCacheResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{15} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{17} } func (x *FlushCacheResponse) GetBody() *FlushCacheResponse_Body { @@ -1052,7 +1168,7 @@ type DoctorRequest struct { func (x *DoctorRequest) Reset() { *x = DoctorRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[16] + mi := &file_pkg_services_control_service_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1065,7 +1181,7 @@ func (x *DoctorRequest) String() string { func (*DoctorRequest) ProtoMessage() {} func (x *DoctorRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[16] + mi := &file_pkg_services_control_service_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1078,7 +1194,7 @@ func (x *DoctorRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DoctorRequest.ProtoReflect.Descriptor instead. func (*DoctorRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{16} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{18} } func (x *DoctorRequest) GetBody() *DoctorRequest_Body { @@ -1108,7 +1224,7 @@ type DoctorResponse struct { func (x *DoctorResponse) Reset() { *x = DoctorResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[17] + mi := &file_pkg_services_control_service_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1121,7 +1237,7 @@ func (x *DoctorResponse) String() string { func (*DoctorResponse) ProtoMessage() {} func (x *DoctorResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[17] + mi := &file_pkg_services_control_service_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1134,7 +1250,7 @@ func (x *DoctorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DoctorResponse.ProtoReflect.Descriptor instead. func (*DoctorResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{17} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{19} } func (x *DoctorResponse) GetBody() *DoctorResponse_Body { @@ -1164,7 +1280,7 @@ type StartShardEvacuationRequest struct { func (x *StartShardEvacuationRequest) Reset() { *x = StartShardEvacuationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[18] + mi := &file_pkg_services_control_service_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1177,7 +1293,7 @@ func (x *StartShardEvacuationRequest) String() string { func (*StartShardEvacuationRequest) ProtoMessage() {} func (x *StartShardEvacuationRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[18] + mi := &file_pkg_services_control_service_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1190,7 +1306,7 @@ func (x *StartShardEvacuationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartShardEvacuationRequest.ProtoReflect.Descriptor instead. func (*StartShardEvacuationRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{18} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{20} } func (x *StartShardEvacuationRequest) GetBody() *StartShardEvacuationRequest_Body { @@ -1220,7 +1336,7 @@ type StartShardEvacuationResponse struct { func (x *StartShardEvacuationResponse) Reset() { *x = StartShardEvacuationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[19] + mi := &file_pkg_services_control_service_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1233,7 +1349,7 @@ func (x *StartShardEvacuationResponse) String() string { func (*StartShardEvacuationResponse) ProtoMessage() {} func (x *StartShardEvacuationResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[19] + mi := &file_pkg_services_control_service_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1246,7 +1362,7 @@ func (x *StartShardEvacuationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartShardEvacuationResponse.ProtoReflect.Descriptor instead. func (*StartShardEvacuationResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{19} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21} } func (x *StartShardEvacuationResponse) GetBody() *StartShardEvacuationResponse_Body { @@ -1276,7 +1392,7 @@ type GetShardEvacuationStatusRequest struct { func (x *GetShardEvacuationStatusRequest) Reset() { *x = GetShardEvacuationStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[20] + mi := &file_pkg_services_control_service_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1289,7 +1405,7 @@ func (x *GetShardEvacuationStatusRequest) String() string { func (*GetShardEvacuationStatusRequest) ProtoMessage() {} func (x *GetShardEvacuationStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[20] + mi := &file_pkg_services_control_service_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1302,7 +1418,7 @@ func (x *GetShardEvacuationStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetShardEvacuationStatusRequest.ProtoReflect.Descriptor instead. func (*GetShardEvacuationStatusRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{20} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22} } func (x *GetShardEvacuationStatusRequest) GetBody() *GetShardEvacuationStatusRequest_Body { @@ -1332,7 +1448,7 @@ type GetShardEvacuationStatusResponse struct { func (x *GetShardEvacuationStatusResponse) Reset() { *x = GetShardEvacuationStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[21] + mi := &file_pkg_services_control_service_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1345,7 +1461,7 @@ func (x *GetShardEvacuationStatusResponse) String() string { func (*GetShardEvacuationStatusResponse) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[21] + mi := &file_pkg_services_control_service_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1358,7 +1474,7 @@ func (x *GetShardEvacuationStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetShardEvacuationStatusResponse.ProtoReflect.Descriptor instead. func (*GetShardEvacuationStatusResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23} } func (x *GetShardEvacuationStatusResponse) GetBody() *GetShardEvacuationStatusResponse_Body { @@ -1388,7 +1504,7 @@ type ResetShardEvacuationStatusRequest struct { func (x *ResetShardEvacuationStatusRequest) Reset() { *x = ResetShardEvacuationStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[22] + mi := &file_pkg_services_control_service_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1401,7 +1517,7 @@ func (x *ResetShardEvacuationStatusRequest) String() string { func (*ResetShardEvacuationStatusRequest) ProtoMessage() {} func (x *ResetShardEvacuationStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[22] + mi := &file_pkg_services_control_service_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1414,7 +1530,7 @@ func (x *ResetShardEvacuationStatusRequest) ProtoReflect() protoreflect.Message // Deprecated: Use ResetShardEvacuationStatusRequest.ProtoReflect.Descriptor instead. func (*ResetShardEvacuationStatusRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24} } func (x *ResetShardEvacuationStatusRequest) GetBody() *ResetShardEvacuationStatusRequest_Body { @@ -1444,7 +1560,7 @@ type ResetShardEvacuationStatusResponse struct { func (x *ResetShardEvacuationStatusResponse) Reset() { *x = ResetShardEvacuationStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[23] + mi := &file_pkg_services_control_service_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1457,7 +1573,7 @@ func (x *ResetShardEvacuationStatusResponse) String() string { func (*ResetShardEvacuationStatusResponse) ProtoMessage() {} func (x *ResetShardEvacuationStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[23] + mi := &file_pkg_services_control_service_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1470,7 +1586,7 @@ func (x *ResetShardEvacuationStatusResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ResetShardEvacuationStatusResponse.ProtoReflect.Descriptor instead. func (*ResetShardEvacuationStatusResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25} } func (x *ResetShardEvacuationStatusResponse) GetBody() *ResetShardEvacuationStatusResponse_Body { @@ -1500,7 +1616,7 @@ type StopShardEvacuationRequest struct { func (x *StopShardEvacuationRequest) Reset() { *x = StopShardEvacuationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[24] + mi := &file_pkg_services_control_service_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1513,7 +1629,7 @@ func (x *StopShardEvacuationRequest) String() string { func (*StopShardEvacuationRequest) ProtoMessage() {} func (x *StopShardEvacuationRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[24] + mi := &file_pkg_services_control_service_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1526,7 +1642,7 @@ func (x *StopShardEvacuationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StopShardEvacuationRequest.ProtoReflect.Descriptor instead. func (*StopShardEvacuationRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26} } func (x *StopShardEvacuationRequest) GetBody() *StopShardEvacuationRequest_Body { @@ -1556,7 +1672,7 @@ type StopShardEvacuationResponse struct { func (x *StopShardEvacuationResponse) Reset() { *x = StopShardEvacuationResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[25] + mi := &file_pkg_services_control_service_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1569,7 +1685,7 @@ func (x *StopShardEvacuationResponse) String() string { func (*StopShardEvacuationResponse) ProtoMessage() {} func (x *StopShardEvacuationResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[25] + mi := &file_pkg_services_control_service_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1582,7 +1698,7 @@ func (x *StopShardEvacuationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StopShardEvacuationResponse.ProtoReflect.Descriptor instead. func (*StopShardEvacuationResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27} } func (x *StopShardEvacuationResponse) GetBody() *StopShardEvacuationResponse_Body { @@ -1612,7 +1728,7 @@ type AddChainLocalOverrideRequest struct { func (x *AddChainLocalOverrideRequest) Reset() { *x = AddChainLocalOverrideRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[26] + mi := &file_pkg_services_control_service_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1625,7 +1741,7 @@ func (x *AddChainLocalOverrideRequest) String() string { func (*AddChainLocalOverrideRequest) ProtoMessage() {} func (x *AddChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[26] + mi := &file_pkg_services_control_service_proto_msgTypes[28] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1638,7 +1754,7 @@ func (x *AddChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddChainLocalOverrideRequest.ProtoReflect.Descriptor instead. func (*AddChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28} } func (x *AddChainLocalOverrideRequest) GetBody() *AddChainLocalOverrideRequest_Body { @@ -1668,7 +1784,7 @@ type AddChainLocalOverrideResponse struct { func (x *AddChainLocalOverrideResponse) Reset() { *x = AddChainLocalOverrideResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[27] + mi := &file_pkg_services_control_service_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1681,7 +1797,7 @@ func (x *AddChainLocalOverrideResponse) String() string { func (*AddChainLocalOverrideResponse) ProtoMessage() {} func (x *AddChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[27] + mi := &file_pkg_services_control_service_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1694,7 +1810,7 @@ func (x *AddChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddChainLocalOverrideResponse.ProtoReflect.Descriptor instead. func (*AddChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29} } func (x *AddChainLocalOverrideResponse) GetBody() *AddChainLocalOverrideResponse_Body { @@ -1724,7 +1840,7 @@ type GetChainLocalOverrideRequest struct { func (x *GetChainLocalOverrideRequest) Reset() { *x = GetChainLocalOverrideRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[28] + mi := &file_pkg_services_control_service_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1737,7 +1853,7 @@ func (x *GetChainLocalOverrideRequest) String() string { func (*GetChainLocalOverrideRequest) ProtoMessage() {} func (x *GetChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[28] + mi := &file_pkg_services_control_service_proto_msgTypes[30] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1750,7 +1866,7 @@ func (x *GetChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetChainLocalOverrideRequest.ProtoReflect.Descriptor instead. func (*GetChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30} } func (x *GetChainLocalOverrideRequest) GetBody() *GetChainLocalOverrideRequest_Body { @@ -1780,7 +1896,7 @@ type GetChainLocalOverrideResponse struct { func (x *GetChainLocalOverrideResponse) Reset() { *x = GetChainLocalOverrideResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[29] + mi := &file_pkg_services_control_service_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1793,7 +1909,7 @@ func (x *GetChainLocalOverrideResponse) String() string { func (*GetChainLocalOverrideResponse) ProtoMessage() {} func (x *GetChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[29] + mi := &file_pkg_services_control_service_proto_msgTypes[31] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1806,7 +1922,7 @@ func (x *GetChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetChainLocalOverrideResponse.ProtoReflect.Descriptor instead. func (*GetChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31} } func (x *GetChainLocalOverrideResponse) GetBody() *GetChainLocalOverrideResponse_Body { @@ -1836,7 +1952,7 @@ type ListChainLocalOverridesRequest struct { func (x *ListChainLocalOverridesRequest) Reset() { *x = ListChainLocalOverridesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[30] + mi := &file_pkg_services_control_service_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1849,7 +1965,7 @@ func (x *ListChainLocalOverridesRequest) String() string { func (*ListChainLocalOverridesRequest) ProtoMessage() {} func (x *ListChainLocalOverridesRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[30] + mi := &file_pkg_services_control_service_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1862,7 +1978,7 @@ func (x *ListChainLocalOverridesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListChainLocalOverridesRequest.ProtoReflect.Descriptor instead. func (*ListChainLocalOverridesRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32} } func (x *ListChainLocalOverridesRequest) GetBody() *ListChainLocalOverridesRequest_Body { @@ -1892,7 +2008,7 @@ type ListChainLocalOverridesResponse struct { func (x *ListChainLocalOverridesResponse) Reset() { *x = ListChainLocalOverridesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[31] + mi := &file_pkg_services_control_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1905,7 +2021,7 @@ func (x *ListChainLocalOverridesResponse) String() string { func (*ListChainLocalOverridesResponse) ProtoMessage() {} func (x *ListChainLocalOverridesResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[31] + mi := &file_pkg_services_control_service_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1918,7 +2034,7 @@ func (x *ListChainLocalOverridesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListChainLocalOverridesResponse.ProtoReflect.Descriptor instead. func (*ListChainLocalOverridesResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33} } func (x *ListChainLocalOverridesResponse) GetBody() *ListChainLocalOverridesResponse_Body { @@ -1948,7 +2064,7 @@ type ListTargetsLocalOverridesRequest struct { func (x *ListTargetsLocalOverridesRequest) Reset() { *x = ListTargetsLocalOverridesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1961,7 +2077,7 @@ func (x *ListTargetsLocalOverridesRequest) String() string { func (*ListTargetsLocalOverridesRequest) ProtoMessage() {} func (x *ListTargetsLocalOverridesRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[32] + mi := &file_pkg_services_control_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1974,7 +2090,7 @@ func (x *ListTargetsLocalOverridesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListTargetsLocalOverridesRequest.ProtoReflect.Descriptor instead. func (*ListTargetsLocalOverridesRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34} } func (x *ListTargetsLocalOverridesRequest) GetBody() *ListTargetsLocalOverridesRequest_Body { @@ -2004,7 +2120,7 @@ type ListTargetsLocalOverridesResponse struct { func (x *ListTargetsLocalOverridesResponse) Reset() { *x = ListTargetsLocalOverridesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2017,7 +2133,7 @@ func (x *ListTargetsLocalOverridesResponse) String() string { func (*ListTargetsLocalOverridesResponse) ProtoMessage() {} func (x *ListTargetsLocalOverridesResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[33] + mi := &file_pkg_services_control_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2030,7 +2146,7 @@ func (x *ListTargetsLocalOverridesResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListTargetsLocalOverridesResponse.ProtoReflect.Descriptor instead. func (*ListTargetsLocalOverridesResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35} } func (x *ListTargetsLocalOverridesResponse) GetBody() *ListTargetsLocalOverridesResponse_Body { @@ -2059,7 +2175,7 @@ type RemoveChainLocalOverrideRequest struct { func (x *RemoveChainLocalOverrideRequest) Reset() { *x = RemoveChainLocalOverrideRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2072,7 +2188,7 @@ func (x *RemoveChainLocalOverrideRequest) String() string { func (*RemoveChainLocalOverrideRequest) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[34] + mi := &file_pkg_services_control_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2085,7 +2201,7 @@ func (x *RemoveChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveChainLocalOverrideRequest.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36} } func (x *RemoveChainLocalOverrideRequest) GetBody() *RemoveChainLocalOverrideRequest_Body { @@ -2114,7 +2230,7 @@ type RemoveChainLocalOverrideResponse struct { func (x *RemoveChainLocalOverrideResponse) Reset() { *x = RemoveChainLocalOverrideResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2127,7 +2243,7 @@ func (x *RemoveChainLocalOverrideResponse) String() string { func (*RemoveChainLocalOverrideResponse) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[35] + mi := &file_pkg_services_control_service_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2140,7 +2256,7 @@ func (x *RemoveChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveChainLocalOverrideResponse.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37} } func (x *RemoveChainLocalOverrideResponse) GetBody() *RemoveChainLocalOverrideResponse_Body { @@ -2169,7 +2285,7 @@ type RemoveChainLocalOverridesByTargetRequest struct { func (x *RemoveChainLocalOverridesByTargetRequest) Reset() { *x = RemoveChainLocalOverridesByTargetRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2182,7 +2298,7 @@ func (x *RemoveChainLocalOverridesByTargetRequest) String() string { func (*RemoveChainLocalOverridesByTargetRequest) ProtoMessage() {} func (x *RemoveChainLocalOverridesByTargetRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[36] + mi := &file_pkg_services_control_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2195,7 +2311,7 @@ func (x *RemoveChainLocalOverridesByTargetRequest) ProtoReflect() protoreflect.M // Deprecated: Use RemoveChainLocalOverridesByTargetRequest.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverridesByTargetRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38} } func (x *RemoveChainLocalOverridesByTargetRequest) GetBody() *RemoveChainLocalOverridesByTargetRequest_Body { @@ -2224,7 +2340,7 @@ type RemoveChainLocalOverridesByTargetResponse struct { func (x *RemoveChainLocalOverridesByTargetResponse) Reset() { *x = RemoveChainLocalOverridesByTargetResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2237,7 +2353,7 @@ func (x *RemoveChainLocalOverridesByTargetResponse) String() string { func (*RemoveChainLocalOverridesByTargetResponse) ProtoMessage() {} func (x *RemoveChainLocalOverridesByTargetResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[37] + mi := &file_pkg_services_control_service_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2250,7 +2366,7 @@ func (x *RemoveChainLocalOverridesByTargetResponse) ProtoReflect() protoreflect. // Deprecated: Use RemoveChainLocalOverridesByTargetResponse.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverridesByTargetResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39} } func (x *RemoveChainLocalOverridesByTargetResponse) GetBody() *RemoveChainLocalOverridesByTargetResponse_Body { @@ -2279,7 +2395,7 @@ type SealWriteCacheRequest struct { func (x *SealWriteCacheRequest) Reset() { *x = SealWriteCacheRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2292,7 +2408,7 @@ func (x *SealWriteCacheRequest) String() string { func (*SealWriteCacheRequest) ProtoMessage() {} func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[38] + mi := &file_pkg_services_control_service_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2305,7 +2421,7 @@ func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheRequest.ProtoReflect.Descriptor instead. func (*SealWriteCacheRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{40} } func (x *SealWriteCacheRequest) GetBody() *SealWriteCacheRequest_Body { @@ -2334,7 +2450,7 @@ type SealWriteCacheResponse struct { func (x *SealWriteCacheResponse) Reset() { *x = SealWriteCacheResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2347,7 +2463,7 @@ func (x *SealWriteCacheResponse) String() string { func (*SealWriteCacheResponse) ProtoMessage() {} func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[39] + mi := &file_pkg_services_control_service_proto_msgTypes[41] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2360,7 +2476,7 @@ func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheResponse.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41} } func (x *SealWriteCacheResponse) GetBody() *SealWriteCacheResponse_Body { @@ -2389,7 +2505,7 @@ type DetachShardsRequest struct { func (x *DetachShardsRequest) Reset() { *x = DetachShardsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2402,7 +2518,7 @@ func (x *DetachShardsRequest) String() string { func (*DetachShardsRequest) ProtoMessage() {} func (x *DetachShardsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[40] + mi := &file_pkg_services_control_service_proto_msgTypes[42] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2415,7 +2531,7 @@ func (x *DetachShardsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsRequest.ProtoReflect.Descriptor instead. func (*DetachShardsRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{40} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{42} } func (x *DetachShardsRequest) GetBody() *DetachShardsRequest_Body { @@ -2444,7 +2560,7 @@ type DetachShardsResponse struct { func (x *DetachShardsResponse) Reset() { *x = DetachShardsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2457,7 +2573,7 @@ func (x *DetachShardsResponse) String() string { func (*DetachShardsResponse) ProtoMessage() {} func (x *DetachShardsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[41] + mi := &file_pkg_services_control_service_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2470,7 +2586,7 @@ func (x *DetachShardsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsResponse.ProtoReflect.Descriptor instead. func (*DetachShardsResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{43} } func (x *DetachShardsResponse) GetBody() *DetachShardsResponse_Body { @@ -2497,7 +2613,7 @@ type HealthCheckRequest_Body struct { func (x *HealthCheckRequest_Body) Reset() { *x = HealthCheckRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2510,7 +2626,7 @@ func (x *HealthCheckRequest_Body) String() string { func (*HealthCheckRequest_Body) ProtoMessage() {} func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[42] + mi := &file_pkg_services_control_service_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2541,7 +2657,7 @@ type HealthCheckResponse_Body struct { func (x *HealthCheckResponse_Body) Reset() { *x = HealthCheckResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2554,7 +2670,7 @@ func (x *HealthCheckResponse_Body) String() string { func (*HealthCheckResponse_Body) ProtoMessage() {} func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[43] + mi := &file_pkg_services_control_service_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2605,7 +2721,7 @@ type SetNetmapStatusRequest_Body struct { func (x *SetNetmapStatusRequest_Body) Reset() { *x = SetNetmapStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2618,7 +2734,7 @@ func (x *SetNetmapStatusRequest_Body) String() string { func (*SetNetmapStatusRequest_Body) ProtoMessage() {} func (x *SetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[44] + mi := &file_pkg_services_control_service_proto_msgTypes[46] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2658,7 +2774,7 @@ type SetNetmapStatusResponse_Body struct { func (x *SetNetmapStatusResponse_Body) Reset() { *x = SetNetmapStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2671,7 +2787,7 @@ func (x *SetNetmapStatusResponse_Body) String() string { func (*SetNetmapStatusResponse_Body) ProtoMessage() {} func (x *SetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[45] + mi := &file_pkg_services_control_service_proto_msgTypes[47] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2687,6 +2803,101 @@ func (*SetNetmapStatusResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_control_service_proto_rawDescGZIP(), []int{3, 0} } +type GetNetmapStatusRequest_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetNetmapStatusRequest_Body) Reset() { + *x = GetNetmapStatusRequest_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNetmapStatusRequest_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNetmapStatusRequest_Body) ProtoMessage() {} + +func (x *GetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[48] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNetmapStatusRequest_Body.ProtoReflect.Descriptor instead. +func (*GetNetmapStatusRequest_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{4, 0} +} + +type GetNetmapStatusResponse_Body struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Storage node status in FrostFS network map. + Status NetmapStatus `protobuf:"varint,1,opt,name=status,proto3,enum=control.NetmapStatus" json:"status,omitempty"` + // Network map epoch. + Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` +} + +func (x *GetNetmapStatusResponse_Body) Reset() { + *x = GetNetmapStatusResponse_Body{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_services_control_service_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetNetmapStatusResponse_Body) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetNetmapStatusResponse_Body) ProtoMessage() {} + +func (x *GetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { + mi := &file_pkg_services_control_service_proto_msgTypes[49] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetNetmapStatusResponse_Body.ProtoReflect.Descriptor instead. +func (*GetNetmapStatusResponse_Body) Descriptor() ([]byte, []int) { + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *GetNetmapStatusResponse_Body) GetStatus() NetmapStatus { + if x != nil { + return x.Status + } + return NetmapStatus_STATUS_UNDEFINED +} + +func (x *GetNetmapStatusResponse_Body) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} + // Request body structure. type DropObjectsRequest_Body struct { state protoimpl.MessageState @@ -2701,7 +2912,7 @@ type DropObjectsRequest_Body struct { func (x *DropObjectsRequest_Body) Reset() { *x = DropObjectsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2714,7 +2925,7 @@ func (x *DropObjectsRequest_Body) String() string { func (*DropObjectsRequest_Body) ProtoMessage() {} func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[46] + mi := &file_pkg_services_control_service_proto_msgTypes[50] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2727,7 +2938,7 @@ func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DropObjectsRequest_Body.ProtoReflect.Descriptor instead. func (*DropObjectsRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{4, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{6, 0} } func (x *DropObjectsRequest_Body) GetAddressList() [][]byte { @@ -2747,7 +2958,7 @@ type DropObjectsResponse_Body struct { func (x *DropObjectsResponse_Body) Reset() { *x = DropObjectsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2760,7 +2971,7 @@ func (x *DropObjectsResponse_Body) String() string { func (*DropObjectsResponse_Body) ProtoMessage() {} func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[47] + mi := &file_pkg_services_control_service_proto_msgTypes[51] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2773,7 +2984,7 @@ func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DropObjectsResponse_Body.ProtoReflect.Descriptor instead. func (*DropObjectsResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{5, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{7, 0} } // Request body structure. @@ -2786,7 +2997,7 @@ type ListShardsRequest_Body struct { func (x *ListShardsRequest_Body) Reset() { *x = ListShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2799,7 +3010,7 @@ func (x *ListShardsRequest_Body) String() string { func (*ListShardsRequest_Body) ProtoMessage() {} func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[48] + mi := &file_pkg_services_control_service_proto_msgTypes[52] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2812,7 +3023,7 @@ func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use ListShardsRequest_Body.ProtoReflect.Descriptor instead. func (*ListShardsRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{6, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{8, 0} } // Response body structure. @@ -2828,7 +3039,7 @@ type ListShardsResponse_Body struct { func (x *ListShardsResponse_Body) Reset() { *x = ListShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2841,7 +3052,7 @@ func (x *ListShardsResponse_Body) String() string { func (*ListShardsResponse_Body) ProtoMessage() {} func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[49] + mi := &file_pkg_services_control_service_proto_msgTypes[53] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2854,7 +3065,7 @@ func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use ListShardsResponse_Body.ProtoReflect.Descriptor instead. func (*ListShardsResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{7, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{9, 0} } func (x *ListShardsResponse_Body) GetShards() []*ShardInfo { @@ -2881,7 +3092,7 @@ type SetShardModeRequest_Body struct { func (x *SetShardModeRequest_Body) Reset() { *x = SetShardModeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2894,7 +3105,7 @@ func (x *SetShardModeRequest_Body) String() string { func (*SetShardModeRequest_Body) ProtoMessage() {} func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[50] + mi := &file_pkg_services_control_service_proto_msgTypes[54] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2907,7 +3118,7 @@ func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SetShardModeRequest_Body.ProtoReflect.Descriptor instead. func (*SetShardModeRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{8, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{10, 0} } func (x *SetShardModeRequest_Body) GetShard_ID() [][]byte { @@ -2941,7 +3152,7 @@ type SetShardModeResponse_Body struct { func (x *SetShardModeResponse_Body) Reset() { *x = SetShardModeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2954,7 +3165,7 @@ func (x *SetShardModeResponse_Body) String() string { func (*SetShardModeResponse_Body) ProtoMessage() {} func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[51] + mi := &file_pkg_services_control_service_proto_msgTypes[55] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2967,7 +3178,7 @@ func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SetShardModeResponse_Body.ProtoReflect.Descriptor instead. func (*SetShardModeResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{9, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{11, 0} } // Request body structure. @@ -2985,7 +3196,7 @@ type SynchronizeTreeRequest_Body struct { func (x *SynchronizeTreeRequest_Body) Reset() { *x = SynchronizeTreeRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2998,7 +3209,7 @@ func (x *SynchronizeTreeRequest_Body) String() string { func (*SynchronizeTreeRequest_Body) ProtoMessage() {} func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[52] + mi := &file_pkg_services_control_service_proto_msgTypes[56] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3011,7 +3222,7 @@ func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SynchronizeTreeRequest_Body.ProtoReflect.Descriptor instead. func (*SynchronizeTreeRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{10, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{12, 0} } func (x *SynchronizeTreeRequest_Body) GetContainerId() []byte { @@ -3045,7 +3256,7 @@ type SynchronizeTreeResponse_Body struct { func (x *SynchronizeTreeResponse_Body) Reset() { *x = SynchronizeTreeResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3058,7 +3269,7 @@ func (x *SynchronizeTreeResponse_Body) String() string { func (*SynchronizeTreeResponse_Body) ProtoMessage() {} func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[53] + mi := &file_pkg_services_control_service_proto_msgTypes[57] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3071,7 +3282,7 @@ func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SynchronizeTreeResponse_Body.ProtoReflect.Descriptor instead. func (*SynchronizeTreeResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{11, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{13, 0} } // Request body structure. @@ -3089,7 +3300,7 @@ type EvacuateShardRequest_Body struct { func (x *EvacuateShardRequest_Body) Reset() { *x = EvacuateShardRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3102,7 +3313,7 @@ func (x *EvacuateShardRequest_Body) String() string { func (*EvacuateShardRequest_Body) ProtoMessage() {} func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[54] + mi := &file_pkg_services_control_service_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3115,7 +3326,7 @@ func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use EvacuateShardRequest_Body.ProtoReflect.Descriptor instead. func (*EvacuateShardRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{12, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{14, 0} } func (x *EvacuateShardRequest_Body) GetShard_ID() [][]byte { @@ -3144,7 +3355,7 @@ type EvacuateShardResponse_Body struct { func (x *EvacuateShardResponse_Body) Reset() { *x = EvacuateShardResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3157,7 +3368,7 @@ func (x *EvacuateShardResponse_Body) String() string { func (*EvacuateShardResponse_Body) ProtoMessage() {} func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[55] + mi := &file_pkg_services_control_service_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3170,7 +3381,7 @@ func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use EvacuateShardResponse_Body.ProtoReflect.Descriptor instead. func (*EvacuateShardResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{13, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{15, 0} } func (x *EvacuateShardResponse_Body) GetCount() uint32 { @@ -3196,7 +3407,7 @@ type FlushCacheRequest_Body struct { func (x *FlushCacheRequest_Body) Reset() { *x = FlushCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3209,7 +3420,7 @@ func (x *FlushCacheRequest_Body) String() string { func (*FlushCacheRequest_Body) ProtoMessage() {} func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[56] + mi := &file_pkg_services_control_service_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3222,7 +3433,7 @@ func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use FlushCacheRequest_Body.ProtoReflect.Descriptor instead. func (*FlushCacheRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{14, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{16, 0} } func (x *FlushCacheRequest_Body) GetShard_ID() [][]byte { @@ -3249,7 +3460,7 @@ type FlushCacheResponse_Body struct { func (x *FlushCacheResponse_Body) Reset() { *x = FlushCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3262,7 +3473,7 @@ func (x *FlushCacheResponse_Body) String() string { func (*FlushCacheResponse_Body) ProtoMessage() {} func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[57] + mi := &file_pkg_services_control_service_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3275,7 +3486,7 @@ func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use FlushCacheResponse_Body.ProtoReflect.Descriptor instead. func (*FlushCacheResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{15, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{17, 0} } // Request body structure. @@ -3293,7 +3504,7 @@ type DoctorRequest_Body struct { func (x *DoctorRequest_Body) Reset() { *x = DoctorRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3306,7 +3517,7 @@ func (x *DoctorRequest_Body) String() string { func (*DoctorRequest_Body) ProtoMessage() {} func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[58] + mi := &file_pkg_services_control_service_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3319,7 +3530,7 @@ func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DoctorRequest_Body.ProtoReflect.Descriptor instead. func (*DoctorRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{16, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{18, 0} } func (x *DoctorRequest_Body) GetConcurrency() uint32 { @@ -3346,7 +3557,7 @@ type DoctorResponse_Body struct { func (x *DoctorResponse_Body) Reset() { *x = DoctorResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3359,7 +3570,7 @@ func (x *DoctorResponse_Body) String() string { func (*DoctorResponse_Body) ProtoMessage() {} func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[59] + mi := &file_pkg_services_control_service_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3372,7 +3583,7 @@ func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DoctorResponse_Body.ProtoReflect.Descriptor instead. func (*DoctorResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{17, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{19, 0} } // Request body structure. @@ -3392,7 +3603,7 @@ type StartShardEvacuationRequest_Body struct { func (x *StartShardEvacuationRequest_Body) Reset() { *x = StartShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3405,7 +3616,7 @@ func (x *StartShardEvacuationRequest_Body) String() string { func (*StartShardEvacuationRequest_Body) ProtoMessage() {} func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[60] + mi := &file_pkg_services_control_service_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3418,7 +3629,7 @@ func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use StartShardEvacuationRequest_Body.ProtoReflect.Descriptor instead. func (*StartShardEvacuationRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{18, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{20, 0} } func (x *StartShardEvacuationRequest_Body) GetShard_ID() [][]byte { @@ -3452,7 +3663,7 @@ type StartShardEvacuationResponse_Body struct { func (x *StartShardEvacuationResponse_Body) Reset() { *x = StartShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3465,7 +3676,7 @@ func (x *StartShardEvacuationResponse_Body) String() string { func (*StartShardEvacuationResponse_Body) ProtoMessage() {} func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[61] + mi := &file_pkg_services_control_service_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3478,7 +3689,7 @@ func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message // Deprecated: Use StartShardEvacuationResponse_Body.ProtoReflect.Descriptor instead. func (*StartShardEvacuationResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{19, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21, 0} } // Request body structure. @@ -3491,7 +3702,7 @@ type GetShardEvacuationStatusRequest_Body struct { func (x *GetShardEvacuationStatusRequest_Body) Reset() { *x = GetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3504,7 +3715,7 @@ func (x *GetShardEvacuationStatusRequest_Body) String() string { func (*GetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[62] + mi := &file_pkg_services_control_service_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3517,7 +3728,7 @@ func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Messa // Deprecated: Use GetShardEvacuationStatusRequest_Body.ProtoReflect.Descriptor instead. func (*GetShardEvacuationStatusRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{20, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22, 0} } // Response body structure. @@ -3556,7 +3767,7 @@ type GetShardEvacuationStatusResponse_Body struct { func (x *GetShardEvacuationStatusResponse_Body) Reset() { *x = GetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3569,7 +3780,7 @@ func (x *GetShardEvacuationStatusResponse_Body) String() string { func (*GetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[63] + mi := &file_pkg_services_control_service_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3582,7 +3793,7 @@ func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Mess // Deprecated: Use GetShardEvacuationStatusResponse_Body.ProtoReflect.Descriptor instead. func (*GetShardEvacuationStatusResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0} } func (x *GetShardEvacuationStatusResponse_Body) GetTotalObjects() uint64 { @@ -3681,7 +3892,7 @@ type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) Reset() { *x = GetShardEvacuationStatusResponse_Body_UnixTimestamp{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3694,7 +3905,7 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) String() string { func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[64] + mi := &file_pkg_services_control_service_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3707,7 +3918,7 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() pro // Deprecated: Use GetShardEvacuationStatusResponse_Body_UnixTimestamp.ProtoReflect.Descriptor instead. func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21, 0, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0, 0} } func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) GetValue() int64 { @@ -3729,7 +3940,7 @@ type GetShardEvacuationStatusResponse_Body_Duration struct { func (x *GetShardEvacuationStatusResponse_Body_Duration) Reset() { *x = GetShardEvacuationStatusResponse_Body_Duration{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3742,7 +3953,7 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) String() string { func (*GetShardEvacuationStatusResponse_Body_Duration) ProtoMessage() {} func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[65] + mi := &file_pkg_services_control_service_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3755,7 +3966,7 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoref // Deprecated: Use GetShardEvacuationStatusResponse_Body_Duration.ProtoReflect.Descriptor instead. func (*GetShardEvacuationStatusResponse_Body_Duration) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21, 0, 1} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0, 1} } func (x *GetShardEvacuationStatusResponse_Body_Duration) GetSeconds() int64 { @@ -3774,7 +3985,7 @@ type ResetShardEvacuationStatusRequest_Body struct { func (x *ResetShardEvacuationStatusRequest_Body) Reset() { *x = ResetShardEvacuationStatusRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3787,7 +3998,7 @@ func (x *ResetShardEvacuationStatusRequest_Body) String() string { func (*ResetShardEvacuationStatusRequest_Body) ProtoMessage() {} func (x *ResetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[66] + mi := &file_pkg_services_control_service_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3800,7 +4011,7 @@ func (x *ResetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Mes // Deprecated: Use ResetShardEvacuationStatusRequest_Body.ProtoReflect.Descriptor instead. func (*ResetShardEvacuationStatusRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24, 0} } type ResetShardEvacuationStatusResponse_Body struct { @@ -3812,7 +4023,7 @@ type ResetShardEvacuationStatusResponse_Body struct { func (x *ResetShardEvacuationStatusResponse_Body) Reset() { *x = ResetShardEvacuationStatusResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3825,7 +4036,7 @@ func (x *ResetShardEvacuationStatusResponse_Body) String() string { func (*ResetShardEvacuationStatusResponse_Body) ProtoMessage() {} func (x *ResetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[67] + mi := &file_pkg_services_control_service_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3838,7 +4049,7 @@ func (x *ResetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Me // Deprecated: Use ResetShardEvacuationStatusResponse_Body.ProtoReflect.Descriptor instead. func (*ResetShardEvacuationStatusResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25, 0} } // Request body structure. @@ -3851,7 +4062,7 @@ type StopShardEvacuationRequest_Body struct { func (x *StopShardEvacuationRequest_Body) Reset() { *x = StopShardEvacuationRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3864,7 +4075,7 @@ func (x *StopShardEvacuationRequest_Body) String() string { func (*StopShardEvacuationRequest_Body) ProtoMessage() {} func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[68] + mi := &file_pkg_services_control_service_proto_msgTypes[72] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3877,7 +4088,7 @@ func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use StopShardEvacuationRequest_Body.ProtoReflect.Descriptor instead. func (*StopShardEvacuationRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26, 0} } // Response body structure. @@ -3890,7 +4101,7 @@ type StopShardEvacuationResponse_Body struct { func (x *StopShardEvacuationResponse_Body) Reset() { *x = StopShardEvacuationResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3903,7 +4114,7 @@ func (x *StopShardEvacuationResponse_Body) String() string { func (*StopShardEvacuationResponse_Body) ProtoMessage() {} func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[69] + mi := &file_pkg_services_control_service_proto_msgTypes[73] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3916,7 +4127,7 @@ func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use StopShardEvacuationResponse_Body.ProtoReflect.Descriptor instead. func (*StopShardEvacuationResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27, 0} } type AddChainLocalOverrideRequest_Body struct { @@ -3935,7 +4146,7 @@ type AddChainLocalOverrideRequest_Body struct { func (x *AddChainLocalOverrideRequest_Body) Reset() { *x = AddChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3948,7 +4159,7 @@ func (x *AddChainLocalOverrideRequest_Body) String() string { func (*AddChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[70] + mi := &file_pkg_services_control_service_proto_msgTypes[74] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3961,7 +4172,7 @@ func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message // Deprecated: Use AddChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. func (*AddChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28, 0} } func (x *AddChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { @@ -3992,7 +4203,7 @@ type AddChainLocalOverrideResponse_Body struct { func (x *AddChainLocalOverrideResponse_Body) Reset() { *x = AddChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[71] + mi := &file_pkg_services_control_service_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4005,7 +4216,7 @@ func (x *AddChainLocalOverrideResponse_Body) String() string { func (*AddChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[71] + mi := &file_pkg_services_control_service_proto_msgTypes[75] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4018,7 +4229,7 @@ func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message // Deprecated: Use AddChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. func (*AddChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29, 0} } func (x *AddChainLocalOverrideResponse_Body) GetChainId() []byte { @@ -4042,7 +4253,7 @@ type GetChainLocalOverrideRequest_Body struct { func (x *GetChainLocalOverrideRequest_Body) Reset() { *x = GetChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[72] + mi := &file_pkg_services_control_service_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4055,7 +4266,7 @@ func (x *GetChainLocalOverrideRequest_Body) String() string { func (*GetChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[72] + mi := &file_pkg_services_control_service_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4068,7 +4279,7 @@ func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message // Deprecated: Use GetChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. func (*GetChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} } func (x *GetChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { @@ -4097,7 +4308,7 @@ type GetChainLocalOverrideResponse_Body struct { func (x *GetChainLocalOverrideResponse_Body) Reset() { *x = GetChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[73] + mi := &file_pkg_services_control_service_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4110,7 +4321,7 @@ func (x *GetChainLocalOverrideResponse_Body) String() string { func (*GetChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[73] + mi := &file_pkg_services_control_service_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4123,7 +4334,7 @@ func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message // Deprecated: Use GetChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. func (*GetChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31, 0} } func (x *GetChainLocalOverrideResponse_Body) GetChain() []byte { @@ -4145,7 +4356,7 @@ type ListChainLocalOverridesRequest_Body struct { func (x *ListChainLocalOverridesRequest_Body) Reset() { *x = ListChainLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[74] + mi := &file_pkg_services_control_service_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4158,7 +4369,7 @@ func (x *ListChainLocalOverridesRequest_Body) String() string { func (*ListChainLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[74] + mi := &file_pkg_services_control_service_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4171,7 +4382,7 @@ func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Messag // Deprecated: Use ListChainLocalOverridesRequest_Body.ProtoReflect.Descriptor instead. func (*ListChainLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32, 0} } func (x *ListChainLocalOverridesRequest_Body) GetTarget() *ChainTarget { @@ -4193,7 +4404,7 @@ type ListChainLocalOverridesResponse_Body struct { func (x *ListChainLocalOverridesResponse_Body) Reset() { *x = ListChainLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[75] + mi := &file_pkg_services_control_service_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4206,7 +4417,7 @@ func (x *ListChainLocalOverridesResponse_Body) String() string { func (*ListChainLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[75] + mi := &file_pkg_services_control_service_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4219,7 +4430,7 @@ func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Messa // Deprecated: Use ListChainLocalOverridesResponse_Body.ProtoReflect.Descriptor instead. func (*ListChainLocalOverridesResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} } func (x *ListChainLocalOverridesResponse_Body) GetChains() [][]byte { @@ -4241,7 +4452,7 @@ type ListTargetsLocalOverridesRequest_Body struct { func (x *ListTargetsLocalOverridesRequest_Body) Reset() { *x = ListTargetsLocalOverridesRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[76] + mi := &file_pkg_services_control_service_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4254,7 +4465,7 @@ func (x *ListTargetsLocalOverridesRequest_Body) String() string { func (*ListTargetsLocalOverridesRequest_Body) ProtoMessage() {} func (x *ListTargetsLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[76] + mi := &file_pkg_services_control_service_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4267,7 +4478,7 @@ func (x *ListTargetsLocalOverridesRequest_Body) ProtoReflect() protoreflect.Mess // Deprecated: Use ListTargetsLocalOverridesRequest_Body.ProtoReflect.Descriptor instead. func (*ListTargetsLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34, 0} } func (x *ListTargetsLocalOverridesRequest_Body) GetChainName() string { @@ -4289,7 +4500,7 @@ type ListTargetsLocalOverridesResponse_Body struct { func (x *ListTargetsLocalOverridesResponse_Body) Reset() { *x = ListTargetsLocalOverridesResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[77] + mi := &file_pkg_services_control_service_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4302,7 +4513,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) String() string { func (*ListTargetsLocalOverridesResponse_Body) ProtoMessage() {} func (x *ListTargetsLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[77] + mi := &file_pkg_services_control_service_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4315,7 +4526,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) ProtoReflect() protoreflect.Mes // Deprecated: Use ListTargetsLocalOverridesResponse_Body.ProtoReflect.Descriptor instead. func (*ListTargetsLocalOverridesResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0} } func (x *ListTargetsLocalOverridesResponse_Body) GetTargets() []*ChainTarget { @@ -4339,7 +4550,7 @@ type RemoveChainLocalOverrideRequest_Body struct { func (x *RemoveChainLocalOverrideRequest_Body) Reset() { *x = RemoveChainLocalOverrideRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[78] + mi := &file_pkg_services_control_service_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4352,7 +4563,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) String() string { func (*RemoveChainLocalOverrideRequest_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[78] + mi := &file_pkg_services_control_service_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4365,7 +4576,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Messa // Deprecated: Use RemoveChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36, 0} } func (x *RemoveChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { @@ -4391,7 +4602,7 @@ type RemoveChainLocalOverrideResponse_Body struct { func (x *RemoveChainLocalOverrideResponse_Body) Reset() { *x = RemoveChainLocalOverrideResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[79] + mi := &file_pkg_services_control_service_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4404,7 +4615,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) String() string { func (*RemoveChainLocalOverrideResponse_Body) ProtoMessage() {} func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[79] + mi := &file_pkg_services_control_service_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4417,7 +4628,7 @@ func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Mess // Deprecated: Use RemoveChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0} } type RemoveChainLocalOverridesByTargetRequest_Body struct { @@ -4432,7 +4643,7 @@ type RemoveChainLocalOverridesByTargetRequest_Body struct { func (x *RemoveChainLocalOverridesByTargetRequest_Body) Reset() { *x = RemoveChainLocalOverridesByTargetRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[80] + mi := &file_pkg_services_control_service_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4445,7 +4656,7 @@ func (x *RemoveChainLocalOverridesByTargetRequest_Body) String() string { func (*RemoveChainLocalOverridesByTargetRequest_Body) ProtoMessage() {} func (x *RemoveChainLocalOverridesByTargetRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[80] + mi := &file_pkg_services_control_service_proto_msgTypes[84] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4458,7 +4669,7 @@ func (x *RemoveChainLocalOverridesByTargetRequest_Body) ProtoReflect() protorefl // Deprecated: Use RemoveChainLocalOverridesByTargetRequest_Body.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverridesByTargetRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38, 0} } func (x *RemoveChainLocalOverridesByTargetRequest_Body) GetTarget() *ChainTarget { @@ -4477,7 +4688,7 @@ type RemoveChainLocalOverridesByTargetResponse_Body struct { func (x *RemoveChainLocalOverridesByTargetResponse_Body) Reset() { *x = RemoveChainLocalOverridesByTargetResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[81] + mi := &file_pkg_services_control_service_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4490,7 +4701,7 @@ func (x *RemoveChainLocalOverridesByTargetResponse_Body) String() string { func (*RemoveChainLocalOverridesByTargetResponse_Body) ProtoMessage() {} func (x *RemoveChainLocalOverridesByTargetResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[81] + mi := &file_pkg_services_control_service_proto_msgTypes[85] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4503,7 +4714,7 @@ func (x *RemoveChainLocalOverridesByTargetResponse_Body) ProtoReflect() protoref // Deprecated: Use RemoveChainLocalOverridesByTargetResponse_Body.ProtoReflect.Descriptor instead. func (*RemoveChainLocalOverridesByTargetResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39, 0} } // Request body structure. @@ -4521,7 +4732,7 @@ type SealWriteCacheRequest_Body struct { func (x *SealWriteCacheRequest_Body) Reset() { *x = SealWriteCacheRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[82] + mi := &file_pkg_services_control_service_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4534,7 +4745,7 @@ func (x *SealWriteCacheRequest_Body) String() string { func (*SealWriteCacheRequest_Body) ProtoMessage() {} func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[82] + mi := &file_pkg_services_control_service_proto_msgTypes[86] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4547,7 +4758,7 @@ func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheRequest_Body.ProtoReflect.Descriptor instead. func (*SealWriteCacheRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{40, 0} } func (x *SealWriteCacheRequest_Body) GetShard_ID() [][]byte { @@ -4575,7 +4786,7 @@ type SealWriteCacheResponse_Body struct { func (x *SealWriteCacheResponse_Body) Reset() { *x = SealWriteCacheResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[83] + mi := &file_pkg_services_control_service_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4588,7 +4799,7 @@ func (x *SealWriteCacheResponse_Body) String() string { func (*SealWriteCacheResponse_Body) ProtoMessage() {} func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[83] + mi := &file_pkg_services_control_service_proto_msgTypes[87] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4601,7 +4812,7 @@ func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use SealWriteCacheResponse_Body.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41, 0} } func (x *SealWriteCacheResponse_Body) GetResults() []*SealWriteCacheResponse_Body_Status { @@ -4624,7 +4835,7 @@ type SealWriteCacheResponse_Body_Status struct { func (x *SealWriteCacheResponse_Body_Status) Reset() { *x = SealWriteCacheResponse_Body_Status{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[84] + mi := &file_pkg_services_control_service_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4637,7 +4848,7 @@ func (x *SealWriteCacheResponse_Body_Status) String() string { func (*SealWriteCacheResponse_Body_Status) ProtoMessage() {} func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[84] + mi := &file_pkg_services_control_service_proto_msgTypes[88] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4650,7 +4861,7 @@ func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message // Deprecated: Use SealWriteCacheResponse_Body_Status.ProtoReflect.Descriptor instead. func (*SealWriteCacheResponse_Body_Status) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39, 0, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41, 0, 0} } func (x *SealWriteCacheResponse_Body_Status) GetShard_ID() []byte { @@ -4685,7 +4896,7 @@ type DetachShardsRequest_Body struct { func (x *DetachShardsRequest_Body) Reset() { *x = DetachShardsRequest_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[85] + mi := &file_pkg_services_control_service_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4698,7 +4909,7 @@ func (x *DetachShardsRequest_Body) String() string { func (*DetachShardsRequest_Body) ProtoMessage() {} func (x *DetachShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[85] + mi := &file_pkg_services_control_service_proto_msgTypes[89] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4711,7 +4922,7 @@ func (x *DetachShardsRequest_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsRequest_Body.ProtoReflect.Descriptor instead. func (*DetachShardsRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{40, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{42, 0} } func (x *DetachShardsRequest_Body) GetShard_ID() [][]byte { @@ -4730,7 +4941,7 @@ type DetachShardsResponse_Body struct { func (x *DetachShardsResponse_Body) Reset() { *x = DetachShardsResponse_Body{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[86] + mi := &file_pkg_services_control_service_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4743,7 +4954,7 @@ func (x *DetachShardsResponse_Body) String() string { func (*DetachShardsResponse_Body) ProtoMessage() {} func (x *DetachShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[86] + mi := &file_pkg_services_control_service_proto_msgTypes[90] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4756,7 +4967,7 @@ func (x *DetachShardsResponse_Body) ProtoReflect() protoreflect.Message { // Deprecated: Use DetachShardsResponse_Body.ProtoReflect.Descriptor instead. func (*DetachShardsResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41, 0} + return file_pkg_services_control_service_proto_rawDescGZIP(), []int{43, 0} } var File_pkg_services_control_service_proto protoreflect.FileDescriptor @@ -4815,620 +5026,647 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x22, 0xa7, 0x01, 0x0a, 0x12, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x29, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, - 0x52, 0x0b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x86, 0x01, - 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, - 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x82, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xb0, 0x01, 0x0a, 0x12, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x32, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, 0x73, 0x22, 0xf7, - 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x77, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x49, 0x44, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x72, 0x65, - 0x73, 0x65, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x73, 0x65, 0x74, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x53, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x22, 0xe0, 0x01, 0x0a, 0x16, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, - 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, + 0x6f, 0x64, 0x79, 0x22, 0x8c, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, - 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x5a, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x8e, 0x01, 0x0a, 0x17, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xc8, 0x01, 0x0a, 0x14, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, - 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x15, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xb1, 0x01, 0x0a, 0x11, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x35, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, - 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x61, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x65, 0x61, 0x6c, 0x22, 0x84, 0x01, 0x0a, 0x12, 0x46, 0x6c, - 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x55, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x20, 0x0a, - 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, - 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x22, 0x7c, 0x0a, 0x0e, - 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x98, 0x02, 0x0a, 0x1b, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x87, 0x01, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, - 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, - 0x72, 0x6f, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, 0x29, 0x0a, 0x05, 0x53, 0x63, - 0x6f, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0b, 0x0a, - 0x07, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, - 0x45, 0x45, 0x53, 0x10, 0x02, 0x22, 0x98, 0x01, 0x0a, 0x1c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x22, 0x9e, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, - 0x79, 0x22, 0x89, 0x07, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xee, 0x05, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x6f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x19, - 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, - 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, - 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x27, 0x0a, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, - 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, - 0x6c, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x74, - 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0e, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x54, 0x72, 0x65, - 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x65, - 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, - 0x54, 0x72, 0x65, 0x65, 0x73, 0x1a, 0x25, 0x0a, 0x0d, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x24, 0x0a, 0x08, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x63, 0x6f, - 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x1f, - 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, - 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x02, 0x22, 0xa2, 0x01, - 0x0a, 0x21, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x64, 0x79, 0x22, 0xd3, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4b, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4e, 0x65, + 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0xa7, 0x01, 0x0a, 0x12, 0x44, 0x72, 0x6f, + 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x29, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x21, 0x0a, 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, + 0x73, 0x74, 0x22, 0x86, 0x01, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x82, 0x01, 0x0a, 0x11, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x33, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x22, 0xb0, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0x32, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x73, 0x22, 0xf7, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x1a, 0x77, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, + 0x2c, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x65, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x73, 0x65, + 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x88, 0x01, + 0x0a, 0x14, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe0, 0x01, 0x0a, 0x16, 0x53, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0x5a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, + 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, + 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x8e, 0x01, 0x0a, 0x17, + 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xc8, 0x01, 0x0a, + 0x14, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, + 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, + 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x15, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xb1, 0x01, 0x0a, 0x11, 0x46, + 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x33, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x35, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, + 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x65, 0x61, 0x6c, 0x22, 0x84, + 0x01, 0x0a, 0x12, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, + 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x55, 0x0a, 0x04, 0x42, 0x6f, + 0x64, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, + 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x73, 0x22, 0x7c, 0x0a, 0x0e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, + 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, + 0x98, 0x02, 0x0a, 0x1b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x87, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, + 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, + 0x29, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, + 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, + 0x09, 0x0a, 0x05, 0x54, 0x52, 0x45, 0x45, 0x53, 0x10, 0x02, 0x22, 0x98, 0x01, 0x0a, 0x1c, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x9e, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x89, 0x07, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x94, 0x01, 0x0a, 0x1a, 0x53, 0x74, - 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, 0x01, 0x0a, 0x1c, 0x41, 0x64, - 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4a, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, 0x0a, 0x1d, 0x41, 0x64, 0x64, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, - 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, 0x42, 0x6f, 0x64, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x34, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1e, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x22, 0xbe, 0x01, - 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0xd2, - 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x36, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xa0, 0x01, - 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x22, 0xde, 0x01, 0x0a, 0x28, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4a, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, - 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x22, 0xb2, 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, - 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xca, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, - 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x46, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, - 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, - 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, - 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, - 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x65, 0x1a, 0xee, 0x05, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, + 0x2b, 0x0a, 0x11, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, + 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, + 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, + 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, + 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, + 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1f, 0x0a, + 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x73, 0x12, 0x27, + 0x0a, 0x0f, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, + 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, + 0x61, 0x69, 0x6c, 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x73, 0x1a, 0x25, 0x0a, 0x0d, 0x55, 0x6e, + 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x1a, 0x24, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, + 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, + 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, + 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, + 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, + 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, + 0x10, 0x02, 0x22, 0xa2, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x73, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0xb5, - 0x0f, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, - 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, - 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, - 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, - 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, - 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, - 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, - 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, - 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, - 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, - 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, - 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x94, + 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, + 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, + 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, + 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, + 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, + 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, + 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, + 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, + 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, + 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, + 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x49, 0x64, 0x22, 0xa0, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xde, 0x01, 0x0a, 0x28, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, - 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, + 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, + 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb2, 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xca, 0x01, 0x0a, 0x15, + 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, + 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, + 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, + 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, + 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, + 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, + 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, + 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, + 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, + 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, + 0x6f, 0x64, 0x79, 0x32, 0x8b, 0x10, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, + 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, + 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, + 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, + 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, + 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, + 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, + 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, + 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, - 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x8a, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, + 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, - 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, - 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, - 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, - 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, + 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, + 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, + 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, + 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -5444,7 +5682,7 @@ func file_pkg_services_control_service_proto_rawDescGZIP() []byte { } var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 87) +var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 91) var file_pkg_services_control_service_proto_goTypes = []interface{}{ (StartShardEvacuationRequest_Body_Scope)(0), // 0: control.StartShardEvacuationRequest.Body.Scope (GetShardEvacuationStatusResponse_Body_Status)(0), // 1: control.GetShardEvacuationStatusResponse.Body.Status @@ -5452,243 +5690,254 @@ var file_pkg_services_control_service_proto_goTypes = []interface{}{ (*HealthCheckResponse)(nil), // 3: control.HealthCheckResponse (*SetNetmapStatusRequest)(nil), // 4: control.SetNetmapStatusRequest (*SetNetmapStatusResponse)(nil), // 5: control.SetNetmapStatusResponse - (*DropObjectsRequest)(nil), // 6: control.DropObjectsRequest - (*DropObjectsResponse)(nil), // 7: control.DropObjectsResponse - (*ListShardsRequest)(nil), // 8: control.ListShardsRequest - (*ListShardsResponse)(nil), // 9: control.ListShardsResponse - (*SetShardModeRequest)(nil), // 10: control.SetShardModeRequest - (*SetShardModeResponse)(nil), // 11: control.SetShardModeResponse - (*SynchronizeTreeRequest)(nil), // 12: control.SynchronizeTreeRequest - (*SynchronizeTreeResponse)(nil), // 13: control.SynchronizeTreeResponse - (*EvacuateShardRequest)(nil), // 14: control.EvacuateShardRequest - (*EvacuateShardResponse)(nil), // 15: control.EvacuateShardResponse - (*FlushCacheRequest)(nil), // 16: control.FlushCacheRequest - (*FlushCacheResponse)(nil), // 17: control.FlushCacheResponse - (*DoctorRequest)(nil), // 18: control.DoctorRequest - (*DoctorResponse)(nil), // 19: control.DoctorResponse - (*StartShardEvacuationRequest)(nil), // 20: control.StartShardEvacuationRequest - (*StartShardEvacuationResponse)(nil), // 21: control.StartShardEvacuationResponse - (*GetShardEvacuationStatusRequest)(nil), // 22: control.GetShardEvacuationStatusRequest - (*GetShardEvacuationStatusResponse)(nil), // 23: control.GetShardEvacuationStatusResponse - (*ResetShardEvacuationStatusRequest)(nil), // 24: control.ResetShardEvacuationStatusRequest - (*ResetShardEvacuationStatusResponse)(nil), // 25: control.ResetShardEvacuationStatusResponse - (*StopShardEvacuationRequest)(nil), // 26: control.StopShardEvacuationRequest - (*StopShardEvacuationResponse)(nil), // 27: control.StopShardEvacuationResponse - (*AddChainLocalOverrideRequest)(nil), // 28: control.AddChainLocalOverrideRequest - (*AddChainLocalOverrideResponse)(nil), // 29: control.AddChainLocalOverrideResponse - (*GetChainLocalOverrideRequest)(nil), // 30: control.GetChainLocalOverrideRequest - (*GetChainLocalOverrideResponse)(nil), // 31: control.GetChainLocalOverrideResponse - (*ListChainLocalOverridesRequest)(nil), // 32: control.ListChainLocalOverridesRequest - (*ListChainLocalOverridesResponse)(nil), // 33: control.ListChainLocalOverridesResponse - (*ListTargetsLocalOverridesRequest)(nil), // 34: control.ListTargetsLocalOverridesRequest - (*ListTargetsLocalOverridesResponse)(nil), // 35: control.ListTargetsLocalOverridesResponse - (*RemoveChainLocalOverrideRequest)(nil), // 36: control.RemoveChainLocalOverrideRequest - (*RemoveChainLocalOverrideResponse)(nil), // 37: control.RemoveChainLocalOverrideResponse - (*RemoveChainLocalOverridesByTargetRequest)(nil), // 38: control.RemoveChainLocalOverridesByTargetRequest - (*RemoveChainLocalOverridesByTargetResponse)(nil), // 39: control.RemoveChainLocalOverridesByTargetResponse - (*SealWriteCacheRequest)(nil), // 40: control.SealWriteCacheRequest - (*SealWriteCacheResponse)(nil), // 41: control.SealWriteCacheResponse - (*DetachShardsRequest)(nil), // 42: control.DetachShardsRequest - (*DetachShardsResponse)(nil), // 43: control.DetachShardsResponse - (*HealthCheckRequest_Body)(nil), // 44: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 45: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 46: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 47: control.SetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 48: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 49: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 50: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 51: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 52: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 53: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 54: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 55: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 56: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 57: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 58: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 59: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 60: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 61: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 62: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 63: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 64: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 65: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 66: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 67: control.GetShardEvacuationStatusResponse.Body.Duration - (*ResetShardEvacuationStatusRequest_Body)(nil), // 68: control.ResetShardEvacuationStatusRequest.Body - (*ResetShardEvacuationStatusResponse_Body)(nil), // 69: control.ResetShardEvacuationStatusResponse.Body - (*StopShardEvacuationRequest_Body)(nil), // 70: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 71: control.StopShardEvacuationResponse.Body - (*AddChainLocalOverrideRequest_Body)(nil), // 72: control.AddChainLocalOverrideRequest.Body - (*AddChainLocalOverrideResponse_Body)(nil), // 73: control.AddChainLocalOverrideResponse.Body - (*GetChainLocalOverrideRequest_Body)(nil), // 74: control.GetChainLocalOverrideRequest.Body - (*GetChainLocalOverrideResponse_Body)(nil), // 75: control.GetChainLocalOverrideResponse.Body - (*ListChainLocalOverridesRequest_Body)(nil), // 76: control.ListChainLocalOverridesRequest.Body - (*ListChainLocalOverridesResponse_Body)(nil), // 77: control.ListChainLocalOverridesResponse.Body - (*ListTargetsLocalOverridesRequest_Body)(nil), // 78: control.ListTargetsLocalOverridesRequest.Body - (*ListTargetsLocalOverridesResponse_Body)(nil), // 79: control.ListTargetsLocalOverridesResponse.Body - (*RemoveChainLocalOverrideRequest_Body)(nil), // 80: control.RemoveChainLocalOverrideRequest.Body - (*RemoveChainLocalOverrideResponse_Body)(nil), // 81: control.RemoveChainLocalOverrideResponse.Body - (*RemoveChainLocalOverridesByTargetRequest_Body)(nil), // 82: control.RemoveChainLocalOverridesByTargetRequest.Body - (*RemoveChainLocalOverridesByTargetResponse_Body)(nil), // 83: control.RemoveChainLocalOverridesByTargetResponse.Body - (*SealWriteCacheRequest_Body)(nil), // 84: control.SealWriteCacheRequest.Body - (*SealWriteCacheResponse_Body)(nil), // 85: control.SealWriteCacheResponse.Body - (*SealWriteCacheResponse_Body_Status)(nil), // 86: control.SealWriteCacheResponse.Body.Status - (*DetachShardsRequest_Body)(nil), // 87: control.DetachShardsRequest.Body - (*DetachShardsResponse_Body)(nil), // 88: control.DetachShardsResponse.Body - (*Signature)(nil), // 89: control.Signature - (NetmapStatus)(0), // 90: control.NetmapStatus - (HealthStatus)(0), // 91: control.HealthStatus - (*ShardInfo)(nil), // 92: control.ShardInfo - (ShardMode)(0), // 93: control.ShardMode - (*ChainTarget)(nil), // 94: control.ChainTarget + (*GetNetmapStatusRequest)(nil), // 6: control.GetNetmapStatusRequest + (*GetNetmapStatusResponse)(nil), // 7: control.GetNetmapStatusResponse + (*DropObjectsRequest)(nil), // 8: control.DropObjectsRequest + (*DropObjectsResponse)(nil), // 9: control.DropObjectsResponse + (*ListShardsRequest)(nil), // 10: control.ListShardsRequest + (*ListShardsResponse)(nil), // 11: control.ListShardsResponse + (*SetShardModeRequest)(nil), // 12: control.SetShardModeRequest + (*SetShardModeResponse)(nil), // 13: control.SetShardModeResponse + (*SynchronizeTreeRequest)(nil), // 14: control.SynchronizeTreeRequest + (*SynchronizeTreeResponse)(nil), // 15: control.SynchronizeTreeResponse + (*EvacuateShardRequest)(nil), // 16: control.EvacuateShardRequest + (*EvacuateShardResponse)(nil), // 17: control.EvacuateShardResponse + (*FlushCacheRequest)(nil), // 18: control.FlushCacheRequest + (*FlushCacheResponse)(nil), // 19: control.FlushCacheResponse + (*DoctorRequest)(nil), // 20: control.DoctorRequest + (*DoctorResponse)(nil), // 21: control.DoctorResponse + (*StartShardEvacuationRequest)(nil), // 22: control.StartShardEvacuationRequest + (*StartShardEvacuationResponse)(nil), // 23: control.StartShardEvacuationResponse + (*GetShardEvacuationStatusRequest)(nil), // 24: control.GetShardEvacuationStatusRequest + (*GetShardEvacuationStatusResponse)(nil), // 25: control.GetShardEvacuationStatusResponse + (*ResetShardEvacuationStatusRequest)(nil), // 26: control.ResetShardEvacuationStatusRequest + (*ResetShardEvacuationStatusResponse)(nil), // 27: control.ResetShardEvacuationStatusResponse + (*StopShardEvacuationRequest)(nil), // 28: control.StopShardEvacuationRequest + (*StopShardEvacuationResponse)(nil), // 29: control.StopShardEvacuationResponse + (*AddChainLocalOverrideRequest)(nil), // 30: control.AddChainLocalOverrideRequest + (*AddChainLocalOverrideResponse)(nil), // 31: control.AddChainLocalOverrideResponse + (*GetChainLocalOverrideRequest)(nil), // 32: control.GetChainLocalOverrideRequest + (*GetChainLocalOverrideResponse)(nil), // 33: control.GetChainLocalOverrideResponse + (*ListChainLocalOverridesRequest)(nil), // 34: control.ListChainLocalOverridesRequest + (*ListChainLocalOverridesResponse)(nil), // 35: control.ListChainLocalOverridesResponse + (*ListTargetsLocalOverridesRequest)(nil), // 36: control.ListTargetsLocalOverridesRequest + (*ListTargetsLocalOverridesResponse)(nil), // 37: control.ListTargetsLocalOverridesResponse + (*RemoveChainLocalOverrideRequest)(nil), // 38: control.RemoveChainLocalOverrideRequest + (*RemoveChainLocalOverrideResponse)(nil), // 39: control.RemoveChainLocalOverrideResponse + (*RemoveChainLocalOverridesByTargetRequest)(nil), // 40: control.RemoveChainLocalOverridesByTargetRequest + (*RemoveChainLocalOverridesByTargetResponse)(nil), // 41: control.RemoveChainLocalOverridesByTargetResponse + (*SealWriteCacheRequest)(nil), // 42: control.SealWriteCacheRequest + (*SealWriteCacheResponse)(nil), // 43: control.SealWriteCacheResponse + (*DetachShardsRequest)(nil), // 44: control.DetachShardsRequest + (*DetachShardsResponse)(nil), // 45: control.DetachShardsResponse + (*HealthCheckRequest_Body)(nil), // 46: control.HealthCheckRequest.Body + (*HealthCheckResponse_Body)(nil), // 47: control.HealthCheckResponse.Body + (*SetNetmapStatusRequest_Body)(nil), // 48: control.SetNetmapStatusRequest.Body + (*SetNetmapStatusResponse_Body)(nil), // 49: control.SetNetmapStatusResponse.Body + (*GetNetmapStatusRequest_Body)(nil), // 50: control.GetNetmapStatusRequest.Body + (*GetNetmapStatusResponse_Body)(nil), // 51: control.GetNetmapStatusResponse.Body + (*DropObjectsRequest_Body)(nil), // 52: control.DropObjectsRequest.Body + (*DropObjectsResponse_Body)(nil), // 53: control.DropObjectsResponse.Body + (*ListShardsRequest_Body)(nil), // 54: control.ListShardsRequest.Body + (*ListShardsResponse_Body)(nil), // 55: control.ListShardsResponse.Body + (*SetShardModeRequest_Body)(nil), // 56: control.SetShardModeRequest.Body + (*SetShardModeResponse_Body)(nil), // 57: control.SetShardModeResponse.Body + (*SynchronizeTreeRequest_Body)(nil), // 58: control.SynchronizeTreeRequest.Body + (*SynchronizeTreeResponse_Body)(nil), // 59: control.SynchronizeTreeResponse.Body + (*EvacuateShardRequest_Body)(nil), // 60: control.EvacuateShardRequest.Body + (*EvacuateShardResponse_Body)(nil), // 61: control.EvacuateShardResponse.Body + (*FlushCacheRequest_Body)(nil), // 62: control.FlushCacheRequest.Body + (*FlushCacheResponse_Body)(nil), // 63: control.FlushCacheResponse.Body + (*DoctorRequest_Body)(nil), // 64: control.DoctorRequest.Body + (*DoctorResponse_Body)(nil), // 65: control.DoctorResponse.Body + (*StartShardEvacuationRequest_Body)(nil), // 66: control.StartShardEvacuationRequest.Body + (*StartShardEvacuationResponse_Body)(nil), // 67: control.StartShardEvacuationResponse.Body + (*GetShardEvacuationStatusRequest_Body)(nil), // 68: control.GetShardEvacuationStatusRequest.Body + (*GetShardEvacuationStatusResponse_Body)(nil), // 69: control.GetShardEvacuationStatusResponse.Body + (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 70: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 71: control.GetShardEvacuationStatusResponse.Body.Duration + (*ResetShardEvacuationStatusRequest_Body)(nil), // 72: control.ResetShardEvacuationStatusRequest.Body + (*ResetShardEvacuationStatusResponse_Body)(nil), // 73: control.ResetShardEvacuationStatusResponse.Body + (*StopShardEvacuationRequest_Body)(nil), // 74: control.StopShardEvacuationRequest.Body + (*StopShardEvacuationResponse_Body)(nil), // 75: control.StopShardEvacuationResponse.Body + (*AddChainLocalOverrideRequest_Body)(nil), // 76: control.AddChainLocalOverrideRequest.Body + (*AddChainLocalOverrideResponse_Body)(nil), // 77: control.AddChainLocalOverrideResponse.Body + (*GetChainLocalOverrideRequest_Body)(nil), // 78: control.GetChainLocalOverrideRequest.Body + (*GetChainLocalOverrideResponse_Body)(nil), // 79: control.GetChainLocalOverrideResponse.Body + (*ListChainLocalOverridesRequest_Body)(nil), // 80: control.ListChainLocalOverridesRequest.Body + (*ListChainLocalOverridesResponse_Body)(nil), // 81: control.ListChainLocalOverridesResponse.Body + (*ListTargetsLocalOverridesRequest_Body)(nil), // 82: control.ListTargetsLocalOverridesRequest.Body + (*ListTargetsLocalOverridesResponse_Body)(nil), // 83: control.ListTargetsLocalOverridesResponse.Body + (*RemoveChainLocalOverrideRequest_Body)(nil), // 84: control.RemoveChainLocalOverrideRequest.Body + (*RemoveChainLocalOverrideResponse_Body)(nil), // 85: control.RemoveChainLocalOverrideResponse.Body + (*RemoveChainLocalOverridesByTargetRequest_Body)(nil), // 86: control.RemoveChainLocalOverridesByTargetRequest.Body + (*RemoveChainLocalOverridesByTargetResponse_Body)(nil), // 87: control.RemoveChainLocalOverridesByTargetResponse.Body + (*SealWriteCacheRequest_Body)(nil), // 88: control.SealWriteCacheRequest.Body + (*SealWriteCacheResponse_Body)(nil), // 89: control.SealWriteCacheResponse.Body + (*SealWriteCacheResponse_Body_Status)(nil), // 90: control.SealWriteCacheResponse.Body.Status + (*DetachShardsRequest_Body)(nil), // 91: control.DetachShardsRequest.Body + (*DetachShardsResponse_Body)(nil), // 92: control.DetachShardsResponse.Body + (*Signature)(nil), // 93: control.Signature + (NetmapStatus)(0), // 94: control.NetmapStatus + (HealthStatus)(0), // 95: control.HealthStatus + (*ShardInfo)(nil), // 96: control.ShardInfo + (ShardMode)(0), // 97: control.ShardMode + (*ChainTarget)(nil), // 98: control.ChainTarget } var file_pkg_services_control_service_proto_depIdxs = []int32{ - 44, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 89, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 45, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 89, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 46, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 89, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 47, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 89, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 48, // 8: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 89, // 9: control.DropObjectsRequest.signature:type_name -> control.Signature - 49, // 10: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 89, // 11: control.DropObjectsResponse.signature:type_name -> control.Signature - 50, // 12: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 89, // 13: control.ListShardsRequest.signature:type_name -> control.Signature - 51, // 14: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 89, // 15: control.ListShardsResponse.signature:type_name -> control.Signature - 52, // 16: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 89, // 17: control.SetShardModeRequest.signature:type_name -> control.Signature - 53, // 18: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 89, // 19: control.SetShardModeResponse.signature:type_name -> control.Signature - 54, // 20: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 89, // 21: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 55, // 22: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 89, // 23: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 56, // 24: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 89, // 25: control.EvacuateShardRequest.signature:type_name -> control.Signature - 57, // 26: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 89, // 27: control.EvacuateShardResponse.signature:type_name -> control.Signature - 58, // 28: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 89, // 29: control.FlushCacheRequest.signature:type_name -> control.Signature - 59, // 30: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 89, // 31: control.FlushCacheResponse.signature:type_name -> control.Signature - 60, // 32: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 89, // 33: control.DoctorRequest.signature:type_name -> control.Signature - 61, // 34: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 89, // 35: control.DoctorResponse.signature:type_name -> control.Signature - 62, // 36: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 89, // 37: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 63, // 38: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 89, // 39: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 64, // 40: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 89, // 41: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 65, // 42: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 89, // 43: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 68, // 44: control.ResetShardEvacuationStatusRequest.body:type_name -> control.ResetShardEvacuationStatusRequest.Body - 89, // 45: control.ResetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 69, // 46: control.ResetShardEvacuationStatusResponse.body:type_name -> control.ResetShardEvacuationStatusResponse.Body - 89, // 47: control.ResetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 70, // 48: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 89, // 49: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 71, // 50: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 89, // 51: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 72, // 52: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body - 89, // 53: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature - 73, // 54: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body - 89, // 55: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature - 74, // 56: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body - 89, // 57: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature - 75, // 58: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body - 89, // 59: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature - 76, // 60: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body - 89, // 61: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature - 77, // 62: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body - 89, // 63: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature - 78, // 64: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body - 89, // 65: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature - 79, // 66: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body - 89, // 67: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature - 80, // 68: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body - 89, // 69: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature - 81, // 70: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body - 89, // 71: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature - 82, // 72: control.RemoveChainLocalOverridesByTargetRequest.body:type_name -> control.RemoveChainLocalOverridesByTargetRequest.Body - 89, // 73: control.RemoveChainLocalOverridesByTargetRequest.signature:type_name -> control.Signature - 83, // 74: control.RemoveChainLocalOverridesByTargetResponse.body:type_name -> control.RemoveChainLocalOverridesByTargetResponse.Body - 89, // 75: control.RemoveChainLocalOverridesByTargetResponse.signature:type_name -> control.Signature - 84, // 76: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body - 89, // 77: control.SealWriteCacheRequest.signature:type_name -> control.Signature - 85, // 78: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body - 89, // 79: control.SealWriteCacheResponse.signature:type_name -> control.Signature - 87, // 80: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body - 89, // 81: control.DetachShardsRequest.signature:type_name -> control.Signature - 88, // 82: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body - 89, // 83: control.DetachShardsResponse.signature:type_name -> control.Signature - 90, // 84: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 91, // 85: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 90, // 86: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 92, // 87: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 93, // 88: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 1, // 89: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 67, // 90: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 66, // 91: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 94, // 92: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 94, // 93: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 94, // 94: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget - 94, // 95: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget - 94, // 96: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 94, // 97: control.RemoveChainLocalOverridesByTargetRequest.Body.target:type_name -> control.ChainTarget - 86, // 98: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status - 2, // 99: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 4, // 100: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 6, // 101: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 8, // 102: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 10, // 103: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 12, // 104: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 14, // 105: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 20, // 106: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 22, // 107: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 24, // 108: control.ControlService.ResetShardEvacuationStatus:input_type -> control.ResetShardEvacuationStatusRequest - 26, // 109: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 16, // 110: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 18, // 111: control.ControlService.Doctor:input_type -> control.DoctorRequest - 28, // 112: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 30, // 113: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 32, // 114: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 36, // 115: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 38, // 116: control.ControlService.RemoveChainLocalOverridesByTarget:input_type -> control.RemoveChainLocalOverridesByTargetRequest - 34, // 117: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest - 40, // 118: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest - 42, // 119: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest - 3, // 120: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 5, // 121: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 7, // 122: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 9, // 123: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 11, // 124: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 13, // 125: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 15, // 126: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 21, // 127: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 23, // 128: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 25, // 129: control.ControlService.ResetShardEvacuationStatus:output_type -> control.ResetShardEvacuationStatusResponse - 27, // 130: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 17, // 131: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 19, // 132: control.ControlService.Doctor:output_type -> control.DoctorResponse - 29, // 133: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 31, // 134: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 33, // 135: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 37, // 136: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 39, // 137: control.ControlService.RemoveChainLocalOverridesByTarget:output_type -> control.RemoveChainLocalOverridesByTargetResponse - 35, // 138: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse - 41, // 139: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse - 43, // 140: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse - 120, // [120:141] is the sub-list for method output_type - 99, // [99:120] is the sub-list for method input_type - 99, // [99:99] is the sub-list for extension type_name - 99, // [99:99] is the sub-list for extension extendee - 0, // [0:99] is the sub-list for field type_name + 46, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body + 93, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature + 47, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body + 93, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature + 48, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body + 93, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature + 49, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body + 93, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature + 50, // 8: control.GetNetmapStatusRequest.body:type_name -> control.GetNetmapStatusRequest.Body + 93, // 9: control.GetNetmapStatusRequest.signature:type_name -> control.Signature + 51, // 10: control.GetNetmapStatusResponse.body:type_name -> control.GetNetmapStatusResponse.Body + 93, // 11: control.GetNetmapStatusResponse.signature:type_name -> control.Signature + 52, // 12: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body + 93, // 13: control.DropObjectsRequest.signature:type_name -> control.Signature + 53, // 14: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body + 93, // 15: control.DropObjectsResponse.signature:type_name -> control.Signature + 54, // 16: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body + 93, // 17: control.ListShardsRequest.signature:type_name -> control.Signature + 55, // 18: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body + 93, // 19: control.ListShardsResponse.signature:type_name -> control.Signature + 56, // 20: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body + 93, // 21: control.SetShardModeRequest.signature:type_name -> control.Signature + 57, // 22: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body + 93, // 23: control.SetShardModeResponse.signature:type_name -> control.Signature + 58, // 24: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body + 93, // 25: control.SynchronizeTreeRequest.signature:type_name -> control.Signature + 59, // 26: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body + 93, // 27: control.SynchronizeTreeResponse.signature:type_name -> control.Signature + 60, // 28: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body + 93, // 29: control.EvacuateShardRequest.signature:type_name -> control.Signature + 61, // 30: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body + 93, // 31: control.EvacuateShardResponse.signature:type_name -> control.Signature + 62, // 32: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body + 93, // 33: control.FlushCacheRequest.signature:type_name -> control.Signature + 63, // 34: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body + 93, // 35: control.FlushCacheResponse.signature:type_name -> control.Signature + 64, // 36: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body + 93, // 37: control.DoctorRequest.signature:type_name -> control.Signature + 65, // 38: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body + 93, // 39: control.DoctorResponse.signature:type_name -> control.Signature + 66, // 40: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body + 93, // 41: control.StartShardEvacuationRequest.signature:type_name -> control.Signature + 67, // 42: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body + 93, // 43: control.StartShardEvacuationResponse.signature:type_name -> control.Signature + 68, // 44: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body + 93, // 45: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 69, // 46: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body + 93, // 47: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 72, // 48: control.ResetShardEvacuationStatusRequest.body:type_name -> control.ResetShardEvacuationStatusRequest.Body + 93, // 49: control.ResetShardEvacuationStatusRequest.signature:type_name -> control.Signature + 73, // 50: control.ResetShardEvacuationStatusResponse.body:type_name -> control.ResetShardEvacuationStatusResponse.Body + 93, // 51: control.ResetShardEvacuationStatusResponse.signature:type_name -> control.Signature + 74, // 52: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body + 93, // 53: control.StopShardEvacuationRequest.signature:type_name -> control.Signature + 75, // 54: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body + 93, // 55: control.StopShardEvacuationResponse.signature:type_name -> control.Signature + 76, // 56: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body + 93, // 57: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature + 77, // 58: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body + 93, // 59: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature + 78, // 60: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body + 93, // 61: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature + 79, // 62: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body + 93, // 63: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature + 80, // 64: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body + 93, // 65: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature + 81, // 66: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body + 93, // 67: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature + 82, // 68: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body + 93, // 69: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature + 83, // 70: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body + 93, // 71: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature + 84, // 72: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body + 93, // 73: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature + 85, // 74: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body + 93, // 75: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature + 86, // 76: control.RemoveChainLocalOverridesByTargetRequest.body:type_name -> control.RemoveChainLocalOverridesByTargetRequest.Body + 93, // 77: control.RemoveChainLocalOverridesByTargetRequest.signature:type_name -> control.Signature + 87, // 78: control.RemoveChainLocalOverridesByTargetResponse.body:type_name -> control.RemoveChainLocalOverridesByTargetResponse.Body + 93, // 79: control.RemoveChainLocalOverridesByTargetResponse.signature:type_name -> control.Signature + 88, // 80: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body + 93, // 81: control.SealWriteCacheRequest.signature:type_name -> control.Signature + 89, // 82: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body + 93, // 83: control.SealWriteCacheResponse.signature:type_name -> control.Signature + 91, // 84: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body + 93, // 85: control.DetachShardsRequest.signature:type_name -> control.Signature + 92, // 86: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body + 93, // 87: control.DetachShardsResponse.signature:type_name -> control.Signature + 94, // 88: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus + 95, // 89: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus + 94, // 90: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus + 94, // 91: control.GetNetmapStatusResponse.Body.status:type_name -> control.NetmapStatus + 96, // 92: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo + 97, // 93: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode + 1, // 94: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status + 71, // 95: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration + 70, // 96: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp + 98, // 97: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 98, // 98: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 98, // 99: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget + 98, // 100: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget + 98, // 101: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget + 98, // 102: control.RemoveChainLocalOverridesByTargetRequest.Body.target:type_name -> control.ChainTarget + 90, // 103: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status + 2, // 104: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest + 4, // 105: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest + 6, // 106: control.ControlService.GetNetmapStatus:input_type -> control.GetNetmapStatusRequest + 8, // 107: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest + 10, // 108: control.ControlService.ListShards:input_type -> control.ListShardsRequest + 12, // 109: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest + 14, // 110: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest + 16, // 111: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest + 22, // 112: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest + 24, // 113: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest + 26, // 114: control.ControlService.ResetShardEvacuationStatus:input_type -> control.ResetShardEvacuationStatusRequest + 28, // 115: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest + 18, // 116: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest + 20, // 117: control.ControlService.Doctor:input_type -> control.DoctorRequest + 30, // 118: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest + 32, // 119: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest + 34, // 120: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest + 38, // 121: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest + 40, // 122: control.ControlService.RemoveChainLocalOverridesByTarget:input_type -> control.RemoveChainLocalOverridesByTargetRequest + 36, // 123: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest + 42, // 124: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest + 44, // 125: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest + 3, // 126: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse + 5, // 127: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse + 7, // 128: control.ControlService.GetNetmapStatus:output_type -> control.GetNetmapStatusResponse + 9, // 129: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse + 11, // 130: control.ControlService.ListShards:output_type -> control.ListShardsResponse + 13, // 131: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse + 15, // 132: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse + 17, // 133: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse + 23, // 134: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse + 25, // 135: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse + 27, // 136: control.ControlService.ResetShardEvacuationStatus:output_type -> control.ResetShardEvacuationStatusResponse + 29, // 137: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse + 19, // 138: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse + 21, // 139: control.ControlService.Doctor:output_type -> control.DoctorResponse + 31, // 140: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse + 33, // 141: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse + 35, // 142: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse + 39, // 143: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse + 41, // 144: control.ControlService.RemoveChainLocalOverridesByTarget:output_type -> control.RemoveChainLocalOverridesByTargetResponse + 37, // 145: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse + 43, // 146: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse + 45, // 147: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse + 126, // [126:148] is the sub-list for method output_type + 104, // [104:126] is the sub-list for method input_type + 104, // [104:104] is the sub-list for extension type_name + 104, // [104:104] is the sub-list for extension extendee + 0, // [0:104] is the sub-list for field type_name } func init() { file_pkg_services_control_service_proto_init() } @@ -5747,7 +5996,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest); i { + switch v := v.(*GetNetmapStatusRequest); i { case 0: return &v.state case 1: @@ -5759,7 +6008,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse); i { + switch v := v.(*GetNetmapStatusResponse); i { case 0: return &v.state case 1: @@ -5771,7 +6020,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest); i { + switch v := v.(*DropObjectsRequest); i { case 0: return &v.state case 1: @@ -5783,7 +6032,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse); i { + switch v := v.(*DropObjectsResponse); i { case 0: return &v.state case 1: @@ -5795,7 +6044,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest); i { + switch v := v.(*ListShardsRequest); i { case 0: return &v.state case 1: @@ -5807,7 +6056,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse); i { + switch v := v.(*ListShardsResponse); i { case 0: return &v.state case 1: @@ -5819,7 +6068,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest); i { + switch v := v.(*SetShardModeRequest); i { case 0: return &v.state case 1: @@ -5831,7 +6080,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse); i { + switch v := v.(*SetShardModeResponse); i { case 0: return &v.state case 1: @@ -5843,7 +6092,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest); i { + switch v := v.(*SynchronizeTreeRequest); i { case 0: return &v.state case 1: @@ -5855,7 +6104,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse); i { + switch v := v.(*SynchronizeTreeResponse); i { case 0: return &v.state case 1: @@ -5867,7 +6116,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest); i { + switch v := v.(*EvacuateShardRequest); i { case 0: return &v.state case 1: @@ -5879,7 +6128,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse); i { + switch v := v.(*EvacuateShardResponse); i { case 0: return &v.state case 1: @@ -5891,7 +6140,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest); i { + switch v := v.(*FlushCacheRequest); i { case 0: return &v.state case 1: @@ -5903,7 +6152,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse); i { + switch v := v.(*FlushCacheResponse); i { case 0: return &v.state case 1: @@ -5915,7 +6164,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest); i { + switch v := v.(*DoctorRequest); i { case 0: return &v.state case 1: @@ -5927,7 +6176,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse); i { + switch v := v.(*DoctorResponse); i { case 0: return &v.state case 1: @@ -5939,7 +6188,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest); i { + switch v := v.(*StartShardEvacuationRequest); i { case 0: return &v.state case 1: @@ -5951,7 +6200,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse); i { + switch v := v.(*StartShardEvacuationResponse); i { case 0: return &v.state case 1: @@ -5963,7 +6212,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusRequest); i { + switch v := v.(*GetShardEvacuationStatusRequest); i { case 0: return &v.state case 1: @@ -5975,7 +6224,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusResponse); i { + switch v := v.(*GetShardEvacuationStatusResponse); i { case 0: return &v.state case 1: @@ -5987,7 +6236,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest); i { + switch v := v.(*ResetShardEvacuationStatusRequest); i { case 0: return &v.state case 1: @@ -5999,7 +6248,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse); i { + switch v := v.(*ResetShardEvacuationStatusResponse); i { case 0: return &v.state case 1: @@ -6011,7 +6260,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest); i { + switch v := v.(*StopShardEvacuationRequest); i { case 0: return &v.state case 1: @@ -6023,7 +6272,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse); i { + switch v := v.(*StopShardEvacuationResponse); i { case 0: return &v.state case 1: @@ -6035,7 +6284,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest); i { + switch v := v.(*AddChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -6047,7 +6296,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse); i { + switch v := v.(*AddChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -6059,7 +6308,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest); i { + switch v := v.(*GetChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -6071,7 +6320,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse); i { + switch v := v.(*GetChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -6083,7 +6332,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesRequest); i { + switch v := v.(*ListChainLocalOverridesRequest); i { case 0: return &v.state case 1: @@ -6095,7 +6344,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesResponse); i { + switch v := v.(*ListChainLocalOverridesResponse); i { case 0: return &v.state case 1: @@ -6107,7 +6356,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest); i { + switch v := v.(*ListTargetsLocalOverridesRequest); i { case 0: return &v.state case 1: @@ -6119,7 +6368,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse); i { + switch v := v.(*ListTargetsLocalOverridesResponse); i { case 0: return &v.state case 1: @@ -6131,7 +6380,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverridesByTargetRequest); i { + switch v := v.(*RemoveChainLocalOverrideRequest); i { case 0: return &v.state case 1: @@ -6143,7 +6392,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverridesByTargetResponse); i { + switch v := v.(*RemoveChainLocalOverrideResponse); i { case 0: return &v.state case 1: @@ -6155,7 +6404,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest); i { + switch v := v.(*RemoveChainLocalOverridesByTargetRequest); i { case 0: return &v.state case 1: @@ -6167,7 +6416,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse); i { + switch v := v.(*RemoveChainLocalOverridesByTargetResponse); i { case 0: return &v.state case 1: @@ -6179,7 +6428,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsRequest); i { + switch v := v.(*SealWriteCacheRequest); i { case 0: return &v.state case 1: @@ -6191,7 +6440,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsResponse); i { + switch v := v.(*SealWriteCacheResponse); i { case 0: return &v.state case 1: @@ -6203,7 +6452,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { + switch v := v.(*DetachShardsRequest); i { case 0: return &v.state case 1: @@ -6215,7 +6464,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { + switch v := v.(*DetachShardsResponse); i { case 0: return &v.state case 1: @@ -6227,7 +6476,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest_Body); i { + switch v := v.(*HealthCheckRequest_Body); i { case 0: return &v.state case 1: @@ -6239,7 +6488,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse_Body); i { + switch v := v.(*HealthCheckResponse_Body); i { case 0: return &v.state case 1: @@ -6251,7 +6500,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest_Body); i { + switch v := v.(*SetNetmapStatusRequest_Body); i { case 0: return &v.state case 1: @@ -6263,7 +6512,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse_Body); i { + switch v := v.(*SetNetmapStatusResponse_Body); i { case 0: return &v.state case 1: @@ -6275,7 +6524,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest_Body); i { + switch v := v.(*GetNetmapStatusRequest_Body); i { case 0: return &v.state case 1: @@ -6287,7 +6536,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse_Body); i { + switch v := v.(*GetNetmapStatusResponse_Body); i { case 0: return &v.state case 1: @@ -6299,7 +6548,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest_Body); i { + switch v := v.(*DropObjectsRequest_Body); i { case 0: return &v.state case 1: @@ -6311,7 +6560,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse_Body); i { + switch v := v.(*DropObjectsResponse_Body); i { case 0: return &v.state case 1: @@ -6323,7 +6572,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest_Body); i { + switch v := v.(*ListShardsRequest_Body); i { case 0: return &v.state case 1: @@ -6335,7 +6584,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse_Body); i { + switch v := v.(*ListShardsResponse_Body); i { case 0: return &v.state case 1: @@ -6347,7 +6596,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest_Body); i { + switch v := v.(*SetShardModeRequest_Body); i { case 0: return &v.state case 1: @@ -6359,7 +6608,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse_Body); i { + switch v := v.(*SetShardModeResponse_Body); i { case 0: return &v.state case 1: @@ -6371,7 +6620,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest_Body); i { + switch v := v.(*SynchronizeTreeRequest_Body); i { case 0: return &v.state case 1: @@ -6383,7 +6632,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse_Body); i { + switch v := v.(*SynchronizeTreeResponse_Body); i { case 0: return &v.state case 1: @@ -6395,7 +6644,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest_Body); i { + switch v := v.(*EvacuateShardRequest_Body); i { case 0: return &v.state case 1: @@ -6407,7 +6656,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse_Body); i { + switch v := v.(*EvacuateShardResponse_Body); i { case 0: return &v.state case 1: @@ -6419,7 +6668,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest_Body); i { + switch v := v.(*FlushCacheRequest_Body); i { case 0: return &v.state case 1: @@ -6431,7 +6680,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse_Body); i { + switch v := v.(*FlushCacheResponse_Body); i { case 0: return &v.state case 1: @@ -6443,7 +6692,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest_Body); i { + switch v := v.(*DoctorRequest_Body); i { case 0: return &v.state case 1: @@ -6455,7 +6704,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body); i { + switch v := v.(*DoctorResponse_Body); i { case 0: return &v.state case 1: @@ -6467,7 +6716,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { + switch v := v.(*StartShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -6479,7 +6728,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { + switch v := v.(*StartShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -6491,7 +6740,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusRequest_Body); i { + switch v := v.(*GetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -6503,7 +6752,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusResponse_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -6515,7 +6764,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { case 0: return &v.state case 1: @@ -6527,7 +6776,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse_Body); i { + switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { case 0: return &v.state case 1: @@ -6539,7 +6788,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest_Body); i { + switch v := v.(*ResetShardEvacuationStatusRequest_Body); i { case 0: return &v.state case 1: @@ -6551,7 +6800,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse_Body); i { + switch v := v.(*ResetShardEvacuationStatusResponse_Body); i { case 0: return &v.state case 1: @@ -6563,7 +6812,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest_Body); i { + switch v := v.(*StopShardEvacuationRequest_Body); i { case 0: return &v.state case 1: @@ -6575,7 +6824,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse_Body); i { + switch v := v.(*StopShardEvacuationResponse_Body); i { case 0: return &v.state case 1: @@ -6587,7 +6836,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest_Body); i { + switch v := v.(*AddChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6599,7 +6848,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse_Body); i { + switch v := v.(*AddChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6611,7 +6860,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { + switch v := v.(*GetChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6623,7 +6872,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { + switch v := v.(*GetChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6635,7 +6884,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { + switch v := v.(*ListChainLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -6647,7 +6896,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { + switch v := v.(*ListChainLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -6659,7 +6908,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverridesByTargetRequest_Body); i { + switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { case 0: return &v.state case 1: @@ -6671,7 +6920,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverridesByTargetResponse_Body); i { + switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { case 0: return &v.state case 1: @@ -6683,7 +6932,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest_Body); i { + switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { case 0: return &v.state case 1: @@ -6695,7 +6944,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body); i { + switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { case 0: return &v.state case 1: @@ -6707,7 +6956,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body_Status); i { + switch v := v.(*RemoveChainLocalOverridesByTargetRequest_Body); i { case 0: return &v.state case 1: @@ -6719,7 +6968,7 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsRequest_Body); i { + switch v := v.(*RemoveChainLocalOverridesByTargetResponse_Body); i { case 0: return &v.state case 1: @@ -6731,6 +6980,54 @@ func file_pkg_services_control_service_proto_init() { } } file_pkg_services_control_service_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SealWriteCacheResponse_Body_Status); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DetachShardsRequest_Body); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_services_control_service_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DetachShardsResponse_Body); i { case 0: return &v.state @@ -6749,7 +7046,7 @@ func file_pkg_services_control_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_services_control_service_proto_rawDesc, NumEnums: 2, - NumMessages: 87, + NumMessages: 91, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 94032b3467..2cd8434fc9 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -15,6 +15,9 @@ service ControlService { // Sets status of the storage node in FrostFS network map. rpc SetNetmapStatus(SetNetmapStatusRequest) returns (SetNetmapStatusResponse); + // Gets status of the storage node in FrostFS network map. + rpc GetNetmapStatus(GetNetmapStatusRequest) returns (GetNetmapStatusResponse); + // Mark objects to be removed from node's local object storage. rpc DropObjects(DropObjectsRequest) returns (DropObjectsResponse); @@ -156,6 +159,34 @@ message SetNetmapStatusResponse { Signature signature = 2; } +// Get netmap status request. +message GetNetmapStatusRequest { + message Body {} + + // Body of set netmap status request message. + Body body = 1; + + // Body signature. + Signature signature = 2; +} + +// Get netmap status response. +message GetNetmapStatusResponse { + message Body { + // Storage node status in FrostFS network map. + NetmapStatus status = 1; + + // Network map epoch. + uint64 epoch = 2; + } + + // Body of get netmap status response message. + Body body = 1; + + // Body signature. + Signature signature = 2; +} + // Request to drop the objects. message DropObjectsRequest { // Request body structure. diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 9d8d6376c9..a287606fa2 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -334,6 +334,171 @@ func (x *SetNetmapStatusResponse) SetSignature(sig *Signature) { x.Signature = sig } +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *GetNetmapStatusRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *GetNetmapStatusRequest_Body) StableMarshal(buf []byte) []byte { + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *GetNetmapStatusRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *GetNetmapStatusRequest) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *GetNetmapStatusRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *GetNetmapStatusRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *GetNetmapStatusRequest) SetSignature(sig *Signature) { + x.Signature = sig +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *GetNetmapStatusResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.EnumSize(1, int32(x.Status)) + size += proto.UInt64Size(2, x.Epoch) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *GetNetmapStatusResponse_Body) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.EnumMarshal(1, buf[offset:], int32(x.Status)) + offset += proto.UInt64Marshal(2, buf[offset:], x.Epoch) + return buf +} + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *GetNetmapStatusResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// StableMarshal marshals x in protobuf binary format with stable field order. +// +// If buffer length is less than x.StableSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same binary format. +func (x *GetNetmapStatusResponse) StableMarshal(buf []byte) []byte { + if x == nil { + return []byte{} + } + if buf == nil { + buf = make([]byte, x.StableSize()) + } + var offset int + offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) + offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) + return buf +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *GetNetmapStatusResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *GetNetmapStatusResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().StableMarshal(buf), nil +} + +func (x *GetNetmapStatusResponse) SetSignature(sig *Signature) { + x.Signature = sig +} + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index feeee00065..fa9de974a1 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -21,6 +21,7 @@ const _ = grpc.SupportPackageIsVersion7 const ( ControlService_HealthCheck_FullMethodName = "/control.ControlService/HealthCheck" ControlService_SetNetmapStatus_FullMethodName = "/control.ControlService/SetNetmapStatus" + ControlService_GetNetmapStatus_FullMethodName = "/control.ControlService/GetNetmapStatus" ControlService_DropObjects_FullMethodName = "/control.ControlService/DropObjects" ControlService_ListShards_FullMethodName = "/control.ControlService/ListShards" ControlService_SetShardMode_FullMethodName = "/control.ControlService/SetShardMode" @@ -50,6 +51,8 @@ type ControlServiceClient interface { HealthCheck(ctx context.Context, in *HealthCheckRequest, opts ...grpc.CallOption) (*HealthCheckResponse, error) // Sets status of the storage node in FrostFS network map. SetNetmapStatus(ctx context.Context, in *SetNetmapStatusRequest, opts ...grpc.CallOption) (*SetNetmapStatusResponse, error) + // Gets status of the storage node in FrostFS network map. + GetNetmapStatus(ctx context.Context, in *GetNetmapStatusRequest, opts ...grpc.CallOption) (*GetNetmapStatusResponse, error) // Mark objects to be removed from node's local object storage. DropObjects(ctx context.Context, in *DropObjectsRequest, opts ...grpc.CallOption) (*DropObjectsResponse, error) // Returns list that contains information about all shards of a node. @@ -122,6 +125,15 @@ func (c *controlServiceClient) SetNetmapStatus(ctx context.Context, in *SetNetma return out, nil } +func (c *controlServiceClient) GetNetmapStatus(ctx context.Context, in *GetNetmapStatusRequest, opts ...grpc.CallOption) (*GetNetmapStatusResponse, error) { + out := new(GetNetmapStatusResponse) + err := c.cc.Invoke(ctx, ControlService_GetNetmapStatus_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *controlServiceClient) DropObjects(ctx context.Context, in *DropObjectsRequest, opts ...grpc.CallOption) (*DropObjectsResponse, error) { out := new(DropObjectsResponse) err := c.cc.Invoke(ctx, ControlService_DropObjects_FullMethodName, in, out, opts...) @@ -301,6 +313,8 @@ type ControlServiceServer interface { HealthCheck(context.Context, *HealthCheckRequest) (*HealthCheckResponse, error) // Sets status of the storage node in FrostFS network map. SetNetmapStatus(context.Context, *SetNetmapStatusRequest) (*SetNetmapStatusResponse, error) + // Gets status of the storage node in FrostFS network map. + GetNetmapStatus(context.Context, *GetNetmapStatusRequest) (*GetNetmapStatusResponse, error) // Mark objects to be removed from node's local object storage. DropObjects(context.Context, *DropObjectsRequest) (*DropObjectsResponse, error) // Returns list that contains information about all shards of a node. @@ -357,6 +371,9 @@ func (UnimplementedControlServiceServer) HealthCheck(context.Context, *HealthChe func (UnimplementedControlServiceServer) SetNetmapStatus(context.Context, *SetNetmapStatusRequest) (*SetNetmapStatusResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SetNetmapStatus not implemented") } +func (UnimplementedControlServiceServer) GetNetmapStatus(context.Context, *GetNetmapStatusRequest) (*GetNetmapStatusResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetNetmapStatus not implemented") +} func (UnimplementedControlServiceServer) DropObjects(context.Context, *DropObjectsRequest) (*DropObjectsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DropObjects not implemented") } @@ -462,6 +479,24 @@ func _ControlService_SetNetmapStatus_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _ControlService_GetNetmapStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetNetmapStatusRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).GetNetmapStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_GetNetmapStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).GetNetmapStatus(ctx, req.(*GetNetmapStatusRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ControlService_DropObjects_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(DropObjectsRequest) if err := dec(in); err != nil { @@ -819,6 +854,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "SetNetmapStatus", Handler: _ControlService_SetNetmapStatus_Handler, }, + { + MethodName: "GetNetmapStatus", + Handler: _ControlService_GetNetmapStatus_Handler, + }, { MethodName: "DropObjects", Handler: _ControlService_DropObjects_Handler, From 46732b61d7399f9b067c1490d719bdb959d5de40 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 20 Jun 2024 16:04:55 +0300 Subject: [PATCH 0639/1413] [#60] cli: Add `await` flag to `control set-status` Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/internal/commonflags/flags.go | 3 + .../modules/control/set_netmap_status.go | 64 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/cmd/frostfs-cli/internal/commonflags/flags.go b/cmd/frostfs-cli/internal/commonflags/flags.go index 6915ef42b2..23dbc8c2b8 100644 --- a/cmd/frostfs-cli/internal/commonflags/flags.go +++ b/cmd/frostfs-cli/internal/commonflags/flags.go @@ -50,6 +50,9 @@ const ( TracingFlag = "trace" TracingFlagUsage = "Generate trace ID and print it." + + AwaitFlag = "await" + AwaitFlagUsage = "Wait for the operation to complete" ) // Init adds common flags to the command: diff --git a/cmd/frostfs-cli/modules/control/set_netmap_status.go b/cmd/frostfs-cli/modules/control/set_netmap_status.go index 3aa7416899..31ade1eb90 100644 --- a/cmd/frostfs-cli/modules/control/set_netmap_status.go +++ b/cmd/frostfs-cli/modules/control/set_netmap_status.go @@ -1,7 +1,10 @@ package control import ( + "crypto/ecdsa" + "errors" "fmt" + "time" rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" @@ -9,6 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "github.com/spf13/cobra" ) @@ -18,8 +22,13 @@ const ( netmapStatusOnline = "online" netmapStatusOffline = "offline" netmapStatusMaintenance = "maintenance" + + maxSetStatusMaxWaitTime = 30 * time.Minute + setStatusWaitTimeout = 30 * time.Second ) +var errNetmapStatusAwaitFailed = errors.New("netmap status hasn't changed for 30 minutes") + var setNetmapStatusCmd = &cobra.Command{ Use: "set-status", Short: "Set status of the storage node in FrostFS network map", @@ -43,6 +52,8 @@ func initControlSetNetmapStatusCmd() { flags.BoolP(commonflags.ForceFlag, commonflags.ForceFlagShorthand, false, "Force turning to local maintenance") + + flags.Bool(commonflags.AwaitFlag, false, commonflags.AwaitFlagUsage) } func setNetmapStatus(cmd *cobra.Command, _ []string) { @@ -56,15 +67,19 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) { } } + await, _ := cmd.Flags().GetBool(commonflags.AwaitFlag) + var targetStatus control.NetmapStatus switch st, _ := cmd.Flags().GetString(netmapStatusFlag); st { default: commonCmd.ExitOnErr(cmd, "", fmt.Errorf("unsupported status %s", st)) case netmapStatusOnline: body.SetStatus(control.NetmapStatus_ONLINE) printIgnoreForce(control.NetmapStatus_ONLINE) + targetStatus = control.NetmapStatus_ONLINE case netmapStatusOffline: body.SetStatus(control.NetmapStatus_OFFLINE) printIgnoreForce(control.NetmapStatus_OFFLINE) + targetStatus = control.NetmapStatus_OFFLINE case netmapStatusMaintenance: body.SetStatus(control.NetmapStatus_MAINTENANCE) @@ -72,6 +87,7 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) { body.SetForceMaintenance() common.PrintVerbose(cmd, "Local maintenance will be forced.") } + targetStatus = control.NetmapStatus_MAINTENANCE } req := new(control.SetNetmapStatusRequest) @@ -92,4 +108,52 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) { verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) cmd.Println("Network status update request successfully sent.") + + if await { + awaitSetNetmapStatus(cmd, pk, cli, targetStatus) + } +} + +func awaitSetNetmapStatus(cmd *cobra.Command, pk *ecdsa.PrivateKey, cli *client.Client, targetStatus control.NetmapStatus) { + req := &control.GetNetmapStatusRequest{ + Body: &control.GetNetmapStatusRequest_Body{}, + } + signRequest(cmd, pk, req) + var epoch uint64 + var status control.NetmapStatus + startTime := time.Now() + cmd.Println("Wait until epoch and netmap status change...") + for { + var resp *control.GetNetmapStatusResponse + var err error + err = cli.ExecRaw(func(client *rawclient.Client) error { + resp, err = control.GetNetmapStatus(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "failed to get current netmap status: %w", err) + + if epoch == 0 { + epoch = resp.GetBody().GetEpoch() + } + + status = resp.GetBody().GetStatus() + if resp.GetBody().GetEpoch() > epoch { + epoch = resp.GetBody().GetEpoch() + cmd.Printf("Epoch changed to %d\n", resp.GetBody().GetEpoch()) + } + + if status == targetStatus { + break + } + + if time.Since(startTime) > maxSetStatusMaxWaitTime { + commonCmd.ExitOnErr(cmd, "failed to wait netmap status: %w", errNetmapStatusAwaitFailed) + return + } + + time.Sleep(setStatusWaitTimeout) + + cmd.Printf("Current netmap status '%s', target status '%s'\n", status.String(), targetStatus.String()) + } + cmd.Printf("Netmap status changed to '%s' successfully.\n", status.String()) } From a1f7615b7e97c47a194715ede85189b61a34c84c Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 20 Jun 2024 14:50:17 +0300 Subject: [PATCH 0640/1413] [#1190] ape: Introduce `Groups` util function to retrieve actor's groupIDs Signed-off-by: Airat Arifullin --- pkg/ape/request/frostfsid.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pkg/ape/request/frostfsid.go b/pkg/ape/request/frostfsid.go index fa620e58ca..c0413678d0 100644 --- a/pkg/ape/request/frostfsid.go +++ b/pkg/ape/request/frostfsid.go @@ -34,3 +34,19 @@ func FormFrostfsIDRequestProperties(frostFSIDClient frostfsidcore.SubjectProvide return reqProps, nil } + +// Groups return the actor's group ids from frostfsid contract. +func Groups(frostFSIDClient frostfsidcore.SubjectProvider, pk *keys.PublicKey) ([]string, error) { + subj, err := frostFSIDClient.GetSubjectExtended(pk.GetScriptHash()) + if err != nil { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { + return nil, fmt.Errorf("get subject error: %w", err) + } + return []string{}, nil + } + groups := make([]string, len(subj.Groups)) + for i, group := range subj.Groups { + groups[i] = strconv.FormatInt(group.ID, 10) + } + return groups, nil +} From 621dbf58abe4401971d497f79fd52987e6b6d3c5 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 20 Jun 2024 15:20:48 +0300 Subject: [PATCH 0641/1413] [#1190] container: GroupIDs must also be target of APE checks * Also add new test case for ape middleware in container service. Signed-off-by: Airat Arifullin --- pkg/services/container/ape.go | 42 ++++++++++++- pkg/services/container/ape_test.go | 99 ++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index fb1cc8121c..3ea591c6a9 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -164,11 +164,26 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co reqProps, ) + groups, err := aperequest.Groups(ac.frostFSIDClient, pk) + if err != nil { + return nil, fmt.Errorf("failed to get group ids: %w", err) + } + + // Policy contract keeps group related chains as namespace-group pair. + for i := range groups { + groups[i] = fmt.Sprintf("%s:%s", namespace, groups[i]) + } + rt := policyengine.NewRequestTargetWithNamespace(namespace) rt.User = &policyengine.Target{ Type: policyengine.User, Name: fmt.Sprintf("%s:%s", namespace, pk.Address()), } + rt.Groups = make([]policyengine.Target, len(groups)) + for i := range groups { + rt.Groups[i] = policyengine.GroupTarget(groups[i]) + } + s, found, err := ac.router.IsAllowed(apechain.Ingress, rt, request) if err != nil { return nil, err @@ -222,11 +237,26 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont reqProps, ) + groups, err := aperequest.Groups(ac.frostFSIDClient, pk) + if err != nil { + return nil, fmt.Errorf("failed to get group ids: %w", err) + } + + // Policy contract keeps group related chains as namespace-group pair. + for i := range groups { + groups[i] = fmt.Sprintf("%s:%s", namespace, groups[i]) + } + rt := policyengine.NewRequestTargetWithNamespace(namespace) rt.User = &policyengine.Target{ Type: policyengine.User, Name: fmt.Sprintf("%s:%s", namespace, pk.Address()), } + rt.Groups = make([]policyengine.Target, len(groups)) + for i := range groups { + rt.Groups[i] = policyengine.GroupTarget(groups[i]) + } + s, found, err := ac.router.IsAllowed(apechain.Ingress, rt, request) if err != nil { return nil, err @@ -311,6 +341,16 @@ func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, con namespace = cntNamespace } + groups, err := aperequest.Groups(ac.frostFSIDClient, pk) + if err != nil { + return fmt.Errorf("failed to get group ids: %w", err) + } + + // Policy contract keeps group related chains as namespace-group pair. + for i := range groups { + groups[i] = fmt.Sprintf("%s:%s", namespace, groups[i]) + } + request := aperequest.NewRequest( op, aperequest.NewResource( @@ -321,7 +361,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, con ) s, found, err := ac.router.IsAllowed(apechain.Ingress, - policyengine.NewRequestTargetExtended(namespace, id.EncodeToString(), fmt.Sprintf("%s:%s", namespace, pk.Address()), nil), + policyengine.NewRequestTargetExtended(namespace, id.EncodeToString(), fmt.Sprintf("%s:%s", namespace, pk.Address()), groups), request) if err != nil { return err diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 90c0225dd6..a6f0fb2221 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -44,6 +44,7 @@ const ( func TestAPE(t *testing.T) { t.Parallel() t.Run("allow then deny get container", testAllowThenDenyGetContainerRuleDefined) + t.Run("allow by group id", TestAllowByGroupIDs) t.Run("deny get container no rule found", testDenyGetContainerNoRuleFound) t.Run("deny get container for others", testDenyGetContainerForOthers) t.Run("deny get container by user claim tag", testDenyGetContainerByUserClaimTag) @@ -145,6 +146,104 @@ func testAllowThenDenyGetContainerRuleDefined(t *testing.T) { require.Contains(t, errAccessDenied.Reason(), chain.AccessDenied.String()) } +func TestAllowByGroupIDs(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + }, + }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 1, + Name: "Group#1", + }, + }, + }, + }, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.GroupTarget(":1"), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Kind: chain.KindRequest, + Key: commonschema.PropertyKeyFrostFSIDGroupID, + Value: "1", + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + resp, err := apeSrv.Get(context.Background(), req) + require.NotNil(t, resp) + require.NoError(t, err) +} + func testDenyGetContainerNoRuleFound(t *testing.T) { t.Parallel() srv := &srvStub{ From 0b87388c183618882b8a1bf8d446c69ceb4df8a6 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 20 Jun 2024 15:39:39 +0300 Subject: [PATCH 0642/1413] [#1190] object: GroupIDs must also be target of APE checks * Also add new test case for ape middleware in container service. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/checker.go | 13 ++++++- pkg/services/object/ape/checker_test.go | 51 +++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index ee71e6e1dd..ee12d7b973 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -7,6 +7,7 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" @@ -159,11 +160,19 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { if err != nil { return fmt.Errorf("failed to create ape request: %w", err) } - pub, err := keys.NewPublicKeyFromString(prm.SenderKey) if err != nil { return err } + groups, err := aperequest.Groups(c.frostFSIDClient, pub) + if err != nil { + return fmt.Errorf("failed to get group ids: %w", err) + } + + // Policy contract keeps group related chains as namespace-group pair. + for i := range groups { + groups[i] = fmt.Sprintf("%s:%s", prm.Namespace, groups[i]) + } if prm.BearerToken != nil && !prm.BearerToken.Impersonate() { if err := isValidBearer(prm.BearerToken, prm.ContainerOwner, prm.Container, pub, c.st); err != nil { @@ -185,7 +194,7 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { } } - rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), nil) + rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), groups) status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, rt, r) if err != nil { return err diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 09954602c4..5efd3669b5 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -27,6 +27,7 @@ import ( "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" @@ -159,6 +160,8 @@ var ( objectID = "BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R" + groupID = "1" + role = "Container" senderPrivateKey, _ = keys.NewPrivateKey() @@ -238,6 +241,7 @@ var apeCheckTestCases = []struct { methods []string header testHeader containerRules []chain.Rule + groupidRules []chain.Rule expectAPEErr bool }{ { @@ -393,6 +397,36 @@ var apeCheckTestCases = []struct { }, expectAPEErr: true, }, + { + name: "optional oid requests reached quota limit by group-id", + container: containerID, + methods: methodsOptionalOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + payloadSize: 1000, + }, + fromRequestResponseHeader: true, + }, + groupidRules: []chain.Rule{ + { + Status: chain.QuotaLimitReached, + Actions: chain.Actions{Names: methodsOptionalOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Kind: chain.KindRequest, + Key: commonschema.PropertyKeyFrostFSIDGroupID, + Value: groupID, + }, + }, + }, + }, + expectAPEErr: true, + }, } type stMock struct{} @@ -486,10 +520,19 @@ func TestAPECheck(t *testing.T) { ls := inmemory.NewInmemoryLocalStorage() ms := inmemory.NewInmemoryMorphRuleChainStorage() - ls.AddOverride(chain.Ingress, policyengine.ContainerTarget(test.container), &chain.Chain{ - Rules: test.containerRules, - MatchType: chain.MatchTypeFirstMatch, - }) + if len(test.containerRules) > 0 { + ls.AddOverride(chain.Ingress, policyengine.ContainerTarget(test.container), &chain.Chain{ + Rules: test.containerRules, + MatchType: chain.MatchTypeFirstMatch, + }) + } + + if len(test.groupidRules) > 0 { + ls.AddOverride(chain.Ingress, policyengine.GroupTarget(":"+groupID), &chain.Chain{ + Rules: test.groupidRules, + MatchType: chain.MatchTypeFirstMatch, + }) + } router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) From 11a38a0a8426de556ac17d4518cded38fa98e902 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 20 Jun 2024 15:49:22 +0300 Subject: [PATCH 0643/1413] [#1190] tree: GroupIDs must also be target of APE checks Signed-off-by: Airat Arifullin --- pkg/services/tree/ape.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 475567c5f8..116adf5dbd 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -161,7 +161,17 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, } } - rt := engine.NewRequestTargetExtended(namespace, cid.EncodeToString(), fmt.Sprintf("%s:%s", namespace, publicKey.Address()), nil) + groups, err := aperequest.Groups(s.frostfsidSubjectProvider, publicKey) + if err != nil { + return fmt.Errorf("failed to get group ids: %w", err) + } + + // Policy contract keeps group related chains as namespace-group pair. + for i := range groups { + groups[i] = fmt.Sprintf("%s:%s", namespace, groups[i]) + } + + rt := engine.NewRequestTargetExtended(namespace, cid.EncodeToString(), fmt.Sprintf("%s:%s", namespace, publicKey.Address()), groups) status, found, err := s.router.IsAllowed(apechain.Ingress, rt, request) if err != nil { return apeErr(err) From 81ea91de52956ff0db8fe31728a172ab7f2b7711 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 24 Jun 2024 17:12:26 +0300 Subject: [PATCH 0644/1413] [#451] metrics: Move to internal `metrics` don't look like something others want to import. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-ir/main.go | 2 +- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/netmap.go | 2 +- {pkg => internal}/metrics/blobovnicza.go | 0 {pkg => internal}/metrics/blobstore.go | 0 {pkg => internal}/metrics/consts.go | 0 {pkg => internal}/metrics/engine.go | 0 {pkg => internal}/metrics/fstree.go | 0 {pkg => internal}/metrics/gc.go | 0 {pkg => internal}/metrics/grpc.go | 0 {pkg => internal}/metrics/innerring.go | 0 {pkg => internal}/metrics/metabase.go | 0 {pkg => internal}/metrics/mode.go | 0 {pkg => internal}/metrics/morph.go | 0 {pkg => internal}/metrics/morphcache.go | 0 {pkg => internal}/metrics/node.go | 0 {pkg => internal}/metrics/object.go | 0 {pkg => internal}/metrics/pilorama.go | 0 {pkg => internal}/metrics/policer.go | 0 {pkg => internal}/metrics/replicator.go | 0 {pkg => internal}/metrics/state.go | 0 {pkg => internal}/metrics/treeservice.go | 0 {pkg => internal}/metrics/types.go | 0 {pkg => internal}/metrics/writecache.go | 0 pkg/innerring/innerring.go | 2 +- pkg/local_object_storage/engine/metrics.go | 2 +- pkg/local_object_storage/engine/writecache.go | 2 +- pkg/local_object_storage/metrics/blobovnicza.go | 2 +- pkg/local_object_storage/metrics/blobstore.go | 2 +- pkg/local_object_storage/metrics/fstree.go | 2 +- pkg/local_object_storage/metrics/metabase.go | 2 +- pkg/local_object_storage/metrics/pilorama.go | 2 +- pkg/morph/client/client.go | 2 +- pkg/morph/client/constructor.go | 2 +- scripts/export-metrics/main.go | 2 +- 35 files changed, 14 insertions(+), 14 deletions(-) rename {pkg => internal}/metrics/blobovnicza.go (100%) rename {pkg => internal}/metrics/blobstore.go (100%) rename {pkg => internal}/metrics/consts.go (100%) rename {pkg => internal}/metrics/engine.go (100%) rename {pkg => internal}/metrics/fstree.go (100%) rename {pkg => internal}/metrics/gc.go (100%) rename {pkg => internal}/metrics/grpc.go (100%) rename {pkg => internal}/metrics/innerring.go (100%) rename {pkg => internal}/metrics/metabase.go (100%) rename {pkg => internal}/metrics/mode.go (100%) rename {pkg => internal}/metrics/morph.go (100%) rename {pkg => internal}/metrics/morphcache.go (100%) rename {pkg => internal}/metrics/node.go (100%) rename {pkg => internal}/metrics/object.go (100%) rename {pkg => internal}/metrics/pilorama.go (100%) rename {pkg => internal}/metrics/policer.go (100%) rename {pkg => internal}/metrics/replicator.go (100%) rename {pkg => internal}/metrics/state.go (100%) rename {pkg => internal}/metrics/treeservice.go (100%) rename {pkg => internal}/metrics/types.go (100%) rename {pkg => internal}/metrics/writecache.go (100%) diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 206059b5d6..5b852c37ca 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -9,9 +9,9 @@ import ( "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + irMetrics "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" - irMetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/spf13/viper" "go.uber.org/zap" diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 2b185cfc8c..ef2c0424b1 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -31,6 +31,7 @@ import ( replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" @@ -45,7 +46,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" shardmode "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" containerClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 2d424eec68..d2c0af52dc 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -10,8 +10,8 @@ import ( netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" diff --git a/pkg/metrics/blobovnicza.go b/internal/metrics/blobovnicza.go similarity index 100% rename from pkg/metrics/blobovnicza.go rename to internal/metrics/blobovnicza.go diff --git a/pkg/metrics/blobstore.go b/internal/metrics/blobstore.go similarity index 100% rename from pkg/metrics/blobstore.go rename to internal/metrics/blobstore.go diff --git a/pkg/metrics/consts.go b/internal/metrics/consts.go similarity index 100% rename from pkg/metrics/consts.go rename to internal/metrics/consts.go diff --git a/pkg/metrics/engine.go b/internal/metrics/engine.go similarity index 100% rename from pkg/metrics/engine.go rename to internal/metrics/engine.go diff --git a/pkg/metrics/fstree.go b/internal/metrics/fstree.go similarity index 100% rename from pkg/metrics/fstree.go rename to internal/metrics/fstree.go diff --git a/pkg/metrics/gc.go b/internal/metrics/gc.go similarity index 100% rename from pkg/metrics/gc.go rename to internal/metrics/gc.go diff --git a/pkg/metrics/grpc.go b/internal/metrics/grpc.go similarity index 100% rename from pkg/metrics/grpc.go rename to internal/metrics/grpc.go diff --git a/pkg/metrics/innerring.go b/internal/metrics/innerring.go similarity index 100% rename from pkg/metrics/innerring.go rename to internal/metrics/innerring.go diff --git a/pkg/metrics/metabase.go b/internal/metrics/metabase.go similarity index 100% rename from pkg/metrics/metabase.go rename to internal/metrics/metabase.go diff --git a/pkg/metrics/mode.go b/internal/metrics/mode.go similarity index 100% rename from pkg/metrics/mode.go rename to internal/metrics/mode.go diff --git a/pkg/metrics/morph.go b/internal/metrics/morph.go similarity index 100% rename from pkg/metrics/morph.go rename to internal/metrics/morph.go diff --git a/pkg/metrics/morphcache.go b/internal/metrics/morphcache.go similarity index 100% rename from pkg/metrics/morphcache.go rename to internal/metrics/morphcache.go diff --git a/pkg/metrics/node.go b/internal/metrics/node.go similarity index 100% rename from pkg/metrics/node.go rename to internal/metrics/node.go diff --git a/pkg/metrics/object.go b/internal/metrics/object.go similarity index 100% rename from pkg/metrics/object.go rename to internal/metrics/object.go diff --git a/pkg/metrics/pilorama.go b/internal/metrics/pilorama.go similarity index 100% rename from pkg/metrics/pilorama.go rename to internal/metrics/pilorama.go diff --git a/pkg/metrics/policer.go b/internal/metrics/policer.go similarity index 100% rename from pkg/metrics/policer.go rename to internal/metrics/policer.go diff --git a/pkg/metrics/replicator.go b/internal/metrics/replicator.go similarity index 100% rename from pkg/metrics/replicator.go rename to internal/metrics/replicator.go diff --git a/pkg/metrics/state.go b/internal/metrics/state.go similarity index 100% rename from pkg/metrics/state.go rename to internal/metrics/state.go diff --git a/pkg/metrics/treeservice.go b/internal/metrics/treeservice.go similarity index 100% rename from pkg/metrics/treeservice.go rename to internal/metrics/treeservice.go diff --git a/pkg/metrics/types.go b/internal/metrics/types.go similarity index 100% rename from pkg/metrics/types.go rename to internal/metrics/types.go diff --git a/pkg/metrics/writecache.go b/internal/metrics/writecache.go similarity index 100% rename from pkg/metrics/writecache.go rename to internal/metrics/writecache.go diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 944aa8b76b..50a37845b3 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -8,12 +8,12 @@ import ( "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap" timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" balanceClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index 6b99dff7e2..72b5ae2528 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -3,8 +3,8 @@ package engine import ( "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" ) type MetricRegister interface { diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 0235767163..da488260a4 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -5,10 +5,10 @@ import ( "sync" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/local_object_storage/metrics/blobovnicza.go b/pkg/local_object_storage/metrics/blobovnicza.go index 6886bbc1dc..460d6e638a 100644 --- a/pkg/local_object_storage/metrics/blobovnicza.go +++ b/pkg/local_object_storage/metrics/blobovnicza.go @@ -3,10 +3,10 @@ package metrics import ( "time" + metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" ) func NewBlobovniczaTreeMetrics(path string, m metrics_impl.BlobobvnizcaMetrics) blobovniczatree.Metrics { diff --git a/pkg/local_object_storage/metrics/blobstore.go b/pkg/local_object_storage/metrics/blobstore.go index b3871dfcae..9a41f01d07 100644 --- a/pkg/local_object_storage/metrics/blobstore.go +++ b/pkg/local_object_storage/metrics/blobstore.go @@ -3,8 +3,8 @@ package metrics import ( "time" + metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" - metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" ) type blobstoreMetrics struct { diff --git a/pkg/local_object_storage/metrics/fstree.go b/pkg/local_object_storage/metrics/fstree.go index e6b3175bee..76822ac2c9 100644 --- a/pkg/local_object_storage/metrics/fstree.go +++ b/pkg/local_object_storage/metrics/fstree.go @@ -3,9 +3,9 @@ package metrics import ( "time" + metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" ) func NewFSTreeMetricsWithoutShardID(path string, m metrics_impl.FSTreeMetrics) fstree.Metrics { diff --git a/pkg/local_object_storage/metrics/metabase.go b/pkg/local_object_storage/metrics/metabase.go index 1a02f27059..e962e37cbb 100644 --- a/pkg/local_object_storage/metrics/metabase.go +++ b/pkg/local_object_storage/metrics/metabase.go @@ -3,9 +3,9 @@ package metrics import ( "time" + metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" ) func NewMetabaseMetrics(path string, m metrics_impl.MetabaseMetrics) meta.Metrics { diff --git a/pkg/local_object_storage/metrics/pilorama.go b/pkg/local_object_storage/metrics/pilorama.go index 1b715c2bd3..050b769a04 100644 --- a/pkg/local_object_storage/metrics/pilorama.go +++ b/pkg/local_object_storage/metrics/pilorama.go @@ -3,9 +3,9 @@ package metrics import ( "time" + metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - metrics_impl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" ) func NewPiloramaMetrics(m metrics_impl.PiloramaMetrics) pilorama.Metrics { diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index c9f819f042..df521f56bc 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -10,7 +10,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/google/uuid" diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index c499aa892c..648c7d3c0d 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -7,7 +7,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" lru "github.com/hashicorp/golang-lru/v2" diff --git a/scripts/export-metrics/main.go b/scripts/export-metrics/main.go index 63571e96d4..51705ee497 100644 --- a/scripts/export-metrics/main.go +++ b/scripts/export-metrics/main.go @@ -6,7 +6,7 @@ import ( "fmt" "os" - local_metrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/metrics" + local_metrics "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" ) From df894fbac7689082da2f44c73b3a8f5d3dce6156 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 24 Jun 2024 18:04:35 +0300 Subject: [PATCH 0645/1413] [#451] frostfs-node: Add cache metrics Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/cache.go | 67 ++++++++++++++++++++++++++++------ cmd/frostfs-node/cache_test.go | 6 ++- internal/metrics/cache.go | 35 ++++++++++++++++++ internal/metrics/consts.go | 3 ++ 4 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 internal/metrics/cache.go diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index bf68d245f1..81d552729f 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -4,6 +4,7 @@ import ( "sync" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" @@ -28,15 +29,17 @@ type ttlNetCache[K comparable, V any] struct { cache *expirable.LRU[K, *valueWithError[V]] netRdr netValueReader[K, V] keyLocker *utilSync.KeyLocker[K] + metrics cacheMetrics } // complicates netValueReader with TTL caching mechanism. -func newNetworkTTLCache[K comparable, V any](sz int, ttl time.Duration, netRdr netValueReader[K, V]) *ttlNetCache[K, V] { +func newNetworkTTLCache[K comparable, V any](sz int, ttl time.Duration, netRdr netValueReader[K, V], metrics cacheMetrics) *ttlNetCache[K, V] { cache := expirable.NewLRU[K, *valueWithError[V]](sz, nil, ttl) return &ttlNetCache[K, V]{ cache: cache, netRdr: netRdr, + metrics: metrics, keyLocker: utilSync.NewKeyLocker[K](), } } @@ -47,8 +50,15 @@ func newNetworkTTLCache[K comparable, V any](sz int, ttl time.Duration, netRdr n // // returned value should not be modified. func (c *ttlNetCache[K, V]) get(key K) (V, error) { + hit := false + startedAt := time.Now() + defer func() { + c.metrics.AddMethodDuration("Get", time.Since(startedAt), hit) + }() + val, ok := c.cache.Peek(key) if ok { + hit = true return val.v, val.e } @@ -57,6 +67,7 @@ func (c *ttlNetCache[K, V]) get(key K) (V, error) { val, ok = c.cache.Peek(key) if ok { + hit = true return val.v, val.e } @@ -71,6 +82,11 @@ func (c *ttlNetCache[K, V]) get(key K) (V, error) { } func (c *ttlNetCache[K, V]) set(k K, v V, e error) { + startedAt := time.Now() + defer func() { + c.metrics.AddMethodDuration("Set", time.Since(startedAt), false) + }() + c.keyLocker.Lock(k) defer c.keyLocker.Unlock(k) @@ -81,10 +97,16 @@ func (c *ttlNetCache[K, V]) set(k K, v V, e error) { } func (c *ttlNetCache[K, V]) remove(key K) { + hit := false + startedAt := time.Now() + defer func() { + c.metrics.AddMethodDuration("Remove", time.Since(startedAt), hit) + }() + c.keyLocker.Lock(key) defer c.keyLocker.Unlock(key) - c.cache.Remove(key) + hit = c.cache.Remove(key) } // entity that provides LRU cache interface. @@ -92,16 +114,19 @@ type lruNetCache struct { cache *lru.Cache[uint64, *netmapSDK.NetMap] netRdr netValueReader[uint64, *netmapSDK.NetMap] + + metrics cacheMetrics } // newNetworkLRUCache returns wrapper over netValueReader with LRU cache. -func newNetworkLRUCache(sz int, netRdr netValueReader[uint64, *netmapSDK.NetMap]) *lruNetCache { +func newNetworkLRUCache(sz int, netRdr netValueReader[uint64, *netmapSDK.NetMap], metrics cacheMetrics) *lruNetCache { cache, err := lru.New[uint64, *netmapSDK.NetMap](sz) fatalOnErr(err) return &lruNetCache{ - cache: cache, - netRdr: netRdr, + cache: cache, + netRdr: netRdr, + metrics: metrics, } } @@ -111,8 +136,15 @@ func newNetworkLRUCache(sz int, netRdr netValueReader[uint64, *netmapSDK.NetMap] // // returned value should not be modified. func (c *lruNetCache) get(key uint64) (*netmapSDK.NetMap, error) { + hit := false + startedAt := time.Now() + defer func() { + c.metrics.AddMethodDuration("Get", time.Since(startedAt), hit) + }() + val, ok := c.cache.Get(key) if ok { + hit = true return val, nil } @@ -138,10 +170,10 @@ func newCachedContainerStorage(v container.Source, ttl time.Duration) ttlContain lruCnrCache := newNetworkTTLCache(containerCacheSize, ttl, func(id cid.ID) (*container.Container, error) { return v.Get(id) - }) + }, metrics.NewCacheMetrics("container")) lruDelInfoCache := newNetworkTTLCache(containerCacheSize, ttl, func(id cid.ID) (*container.DelInfo, error) { return v.DeletionInfo(id) - }) + }, metrics.NewCacheMetrics("container_deletion_info")) return ttlContainerStorage{ containerCache: lruCnrCache, @@ -175,7 +207,7 @@ func newCachedEACLStorage(v container.EACLSource, ttl time.Duration) ttlEACLStor lruCnrCache := newNetworkTTLCache(eaclCacheSize, ttl, func(id cid.ID) (*container.EACL, error) { return v.GetEACL(id) - }) + }, metrics.NewCacheMetrics("eacl")) return ttlEACLStorage{lruCnrCache} } @@ -202,7 +234,7 @@ func newCachedNetmapStorage(s netmap.State, v netmap.Source) netmap.Source { lruNetmapCache := newNetworkLRUCache(netmapCacheSize, func(key uint64) (*netmapSDK.NetMap, error) { return v.GetNetMapByEpoch(key) - }) + }, metrics.NewCacheMetrics("netmap")) return &lruNetmapSource{ netState: s, @@ -251,7 +283,7 @@ func newCachedIRFetcher(f interface{ InnerRingKeys() ([][]byte, error) }) cached irFetcherCache := newNetworkTTLCache(irFetcherCacheSize, irFetcherCacheTTL, func(_ struct{}) ([][]byte, error) { return f.InnerRingKeys() - }, + }, metrics.NewCacheMetrics("ir_keys"), ) return cachedIRFetcher{irFetcherCache} @@ -274,23 +306,32 @@ type ttlMaxObjectSizeCache struct { lastUpdated time.Time lastSize uint64 src putsvc.MaxSizeSource + metrics cacheMetrics } func newCachedMaxObjectSizeSource(src putsvc.MaxSizeSource) putsvc.MaxSizeSource { return &ttlMaxObjectSizeCache{ - src: src, + src: src, + metrics: metrics.NewCacheMetrics("max_object_size"), } } func (c *ttlMaxObjectSizeCache) MaxObjectSize() uint64 { const ttl = time.Second * 30 + hit := false + startedAt := time.Now() + defer func() { + c.metrics.AddMethodDuration("Get", time.Since(startedAt), hit) + }() + c.mtx.RLock() prevUpdated := c.lastUpdated size := c.lastSize c.mtx.RUnlock() if time.Since(prevUpdated) < ttl { + hit = true return size } @@ -305,3 +346,7 @@ func (c *ttlMaxObjectSizeCache) MaxObjectSize() uint64 { return size } + +type cacheMetrics interface { + AddMethodDuration(method string, d time.Duration, hit bool) +} diff --git a/cmd/frostfs-node/cache_test.go b/cmd/frostfs-node/cache_test.go index 6981ac7213..f8c324a2f5 100644 --- a/cmd/frostfs-node/cache_test.go +++ b/cmd/frostfs-node/cache_test.go @@ -10,7 +10,7 @@ import ( func TestTTLNetCache(t *testing.T) { ttlDuration := time.Millisecond * 50 - cache := newNetworkTTLCache(10, ttlDuration, testNetValueReader) + cache := newNetworkTTLCache(10, ttlDuration, testNetValueReader, &noopCacheMetricts{}) key := "key" @@ -54,3 +54,7 @@ func testNetValueReader(key string) (time.Time, error) { } return time.Now(), nil } + +type noopCacheMetricts struct{} + +func (m *noopCacheMetricts) AddMethodDuration(method string, d time.Duration, hit bool) {} diff --git a/internal/metrics/cache.go b/internal/metrics/cache.go new file mode 100644 index 0000000000..8181586e25 --- /dev/null +++ b/internal/metrics/cache.go @@ -0,0 +1,35 @@ +package metrics + +import ( + "strconv" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +var cacheRequests = metrics.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: namespace, + Subsystem: commonCacheSubsystem, + Name: "request_duration_seconds", + Help: "Accumulated common cache request process duration", +}, []string{hitLabel, methodLabel, cacheLabel}) + +type CacheMetrics struct { + cache string +} + +// NewCacheMetrics returns new CacheMetrics instance for cache specified. +func NewCacheMetrics(cache string) *CacheMetrics { + return &CacheMetrics{ + cache: cache, + } +} + +func (m *CacheMetrics) AddMethodDuration(method string, d time.Duration, hit bool) { + cacheRequests.With(prometheus.Labels{ + hitLabel: strconv.FormatBool(hit), + methodLabel: method, + cacheLabel: m.cache, + }).Observe(d.Seconds()) +} diff --git a/internal/metrics/consts.go b/internal/metrics/consts.go index f3b83a2e5e..3aa51c0f01 100644 --- a/internal/metrics/consts.go +++ b/internal/metrics/consts.go @@ -21,6 +21,7 @@ const ( writeCacheSubsystem = "writecache" grpcServerSubsystem = "grpc_server" policerSubsystem = "policer" + commonCacheSubsystem = "common_cache" successLabel = "success" shardIDLabel = "shard_id" @@ -38,6 +39,8 @@ const ( storageLabel = "storage" operationLabel = "operation" endpointLabel = "endpoint" + hitLabel = "hit" + cacheLabel = "cache" readWriteMode = "READ_WRITE" readOnlyMode = "READ_ONLY" From a0e5fc733e412beb674f38d4b5994e443e63c937 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 24 Jun 2024 15:05:25 +0300 Subject: [PATCH 0646/1413] [#1145] node/ir: Handle double SIGHUP correctly Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-ir/config.go | 39 ++++++++++++++++++++++++---------- cmd/frostfs-node/config.go | 43 ++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index c3227a182a..9551954774 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -45,18 +45,41 @@ func reloadConfig() error { func watchForSignal(cancel func()) { ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) + + sighupCh := make(chan os.Signal, 1) + signal.Notify(sighupCh, syscall.SIGHUP) for { select { - case err := <-intErr: + // signals causing application to shut down should have priority over + // reconfiguration signal + case <-ch: + log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + cancel() + shutdown() + log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) + return + case err := <-intErr: // internal application error log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error())) cancel() shutdown() return - case sig := <-ch: - switch sig { - case syscall.SIGHUP: + default: + // block until any signal is receieved + select { + case <-ch: + log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + cancel() + shutdown() + log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) + return + case err := <-intErr: // internal application error + log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error())) + cancel() + shutdown() + return + case <-sighupCh: log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) err := reloadConfig() if err != nil { @@ -70,12 +93,6 @@ func watchForSignal(cancel func()) { log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) } log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) - case syscall.SIGTERM, syscall.SIGINT: - log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) - cancel() - shutdown() - log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) - return } } } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index ef2c0424b1..3aded7020a 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1224,22 +1224,22 @@ type dCmp struct { func (c *cfg) signalWatcher(ctx context.Context) { ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) + signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) + + sighupCh := make(chan os.Signal, 1) + signal.Notify(sighupCh, syscall.SIGHUP) for { select { - case sig := <-ch: - switch sig { - case syscall.SIGHUP: - c.reloadConfig(ctx) - case syscall.SIGTERM, syscall.SIGINT: - c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + // signals causing application to shut down should have priority over + // reconfiguration signal + case <-ch: + c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) - c.shutdown() + c.shutdown() - c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) - return - } + c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) + return case err := <-c.internalErr: // internal application error c.log.Warn(logs.FrostFSNodeInternalApplicationError, zap.String("message", err.Error())) @@ -1248,6 +1248,27 @@ func (c *cfg) signalWatcher(ctx context.Context) { c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete) return + default: + // block until any signal is receieved + select { + case <-sighupCh: + c.reloadConfig(ctx) + case <-ch: + c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + + c.shutdown() + + c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) + return + case err := <-c.internalErr: // internal application error + c.log.Warn(logs.FrostFSNodeInternalApplicationError, + zap.String("message", err.Error())) + + c.shutdown() + + c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete) + return + } } } } From 4951babd5f2e87823e71f4459caba8eaaeb8a44f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 27 Jun 2024 11:55:00 +0300 Subject: [PATCH 0647/1413] [#1208] blobstor: Fix delete without storage id Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobstor/delete.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/local_object_storage/blobstor/delete.go b/pkg/local_object_storage/blobstor/delete.go index 8930980a65..c91508e6d2 100644 --- a/pkg/local_object_storage/blobstor/delete.go +++ b/pkg/local_object_storage/blobstor/delete.go @@ -6,8 +6,10 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) @@ -42,6 +44,7 @@ func (b *BlobStor) Delete(ctx context.Context, prm common.DeletePrm) (common.Del return res, err } } + return common.DeleteRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) } var st common.Storage From 4f7d76c9eff284cb8f3aa432999a808e515f8011 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 26 Jun 2024 12:37:20 +0300 Subject: [PATCH 0648/1413] [#1206] audit: Drop not required events Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/accounting.go | 15 +- cmd/frostfs-node/control.go | 5 +- cmd/frostfs-node/netmap.go | 28 +-- cmd/frostfs-node/session.go | 5 +- cmd/frostfs-node/tree.go | 2 +- internal/audit/target.go | 56 ----- pkg/services/accounting/audit.go | 42 ---- pkg/services/control/server/audit.go | 298 --------------------------- pkg/services/netmap/audit.go | 60 ------ pkg/services/session/audit.go | 39 ---- pkg/services/tree/audit.go | 135 ------------ 11 files changed, 26 insertions(+), 659 deletions(-) delete mode 100644 pkg/services/accounting/audit.go delete mode 100644 pkg/services/control/server/audit.go delete mode 100644 pkg/services/netmap/audit.go delete mode 100644 pkg/services/session/audit.go delete mode 100644 pkg/services/tree/audit.go diff --git a/cmd/frostfs-node/accounting.go b/cmd/frostfs-node/accounting.go index f0e2abf385..ec737f8a01 100644 --- a/cmd/frostfs-node/accounting.go +++ b/cmd/frostfs-node/accounting.go @@ -20,16 +20,15 @@ func initAccountingService(ctx context.Context, c *cfg) { balanceMorphWrapper, err := balance.NewFromMorph(c.cfgMorph.client, c.cfgAccounting.scriptHash, 0) fatalOnErr(err) - service := accountingService.NewSignService( - &c.key.PrivateKey, - accountingService.NewExecutionService( - accounting.NewExecutor(balanceMorphWrapper), - c.respSvc, + server := accountingTransportGRPC.New( + accountingService.NewSignService( + &c.key.PrivateKey, + accountingService.NewExecutionService( + accounting.NewExecutor(balanceMorphWrapper), + c.respSvc, + ), ), ) - service = accountingService.NewAuditService(service, c.log, c.audit) - - server := accountingTransportGRPC.New(service) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { accountingGRPC.RegisterAccountingServiceServer(s, server) diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index 8ee1ab69f4..e1e6e3ac9e 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -30,8 +30,8 @@ func initControlService(c *cfg) { for i := range pubs { rawPubs = append(rawPubs, pubs[i].Bytes()) } - var ctlSvc control.ControlServiceServer - ctlSvc = controlSvc.New( + + ctlSvc := controlSvc.New( controlSvc.WithKey(&c.key.PrivateKey), controlSvc.WithAuthorizedKeys(rawPubs), controlSvc.WithHealthChecker(c), @@ -43,7 +43,6 @@ func initControlService(c *cfg) { controlSvc.WithTreeService(c.treeService), controlSvc.WithLocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine), ) - ctlSvc = controlSvc.NewAuditService(ctlSvc, c.log, c.audit) lis, err := net.Listen("tcp", endpoint) if err != nil { diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index d2c0af52dc..128cc30054 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -147,22 +147,22 @@ func initNetmapService(ctx context.Context, c *cfg) { initNetmapState(c) - svc := netmapService.NewSignService( - &c.key.PrivateKey, - netmapService.NewExecutionService( - c, - c.apiVersion, - &netInfo{ - netState: c.cfgNetmap.state, - magic: c.cfgMorph.client, - morphClientNetMap: c.cfgNetmap.wrapper, - msPerBlockRdr: c.cfgMorph.client.MsPerBlock, - }, - c.respSvc, + server := netmapTransportGRPC.New( + netmapService.NewSignService( + &c.key.PrivateKey, + netmapService.NewExecutionService( + c, + c.apiVersion, + &netInfo{ + netState: c.cfgNetmap.state, + magic: c.cfgMorph.client, + morphClientNetMap: c.cfgNetmap.wrapper, + msPerBlockRdr: c.cfgMorph.client.MsPerBlock, + }, + c.respSvc, + ), ), ) - svc = netmapService.NewAuditService(svc, c.log, c.audit) - server := netmapTransportGRPC.New(svc) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { netmapGRPC.RegisterNetmapServiceServer(s, server) diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index d286fc6312..ee21ec230c 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -52,13 +52,12 @@ func initSessionService(c *cfg) { c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber()) }) - svc := sessionSvc.NewAuditService( + server := sessionTransportGRPC.New( sessionSvc.NewSignService( &c.key.PrivateKey, sessionSvc.NewExecutionService(c.privateTokenStore, c.respSvc, c.log), ), - c.log, c.audit) - server := sessionTransportGRPC.New(svc) + ) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { sessionGRPC.RegisterSessionServiceServer(s, server) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index 9f5c89ef03..daaaa64a24 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -70,7 +70,7 @@ func initTreeService(c *cfg) { ) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { - tree.RegisterTreeServiceServer(s, tree.NewAuditService(c.treeService, c.log, c.audit)) + tree.RegisterTreeServiceServer(s, c.treeService) }) c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { diff --git a/internal/audit/target.go b/internal/audit/target.go index 1d760eca6e..8bc87ee8e6 100644 --- a/internal/audit/target.go +++ b/internal/audit/target.go @@ -6,7 +6,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/mr-tron/base58" ) type ModelType[T any] interface { @@ -61,24 +60,6 @@ func TargetFromString(s string) Target { return stringTarget{s: s} } -func TargetFromStringSlice(s []string) Target { - if len(s) == 0 { - return stringTarget{s: NotDefined} - } - sb := &strings.Builder{} - for i, v := range s { - if i > 0 { - sb.WriteString(";") - } - if len(v) == 0 { - sb.WriteString(Empty) - } else { - sb.WriteString(v) - } - } - return sb -} - func TargetFromChainID(chainTargetType, chainTargetName string, chainID []byte) Target { if len(chainTargetType) == 0 && len(chainTargetName) == 0 && len(chainID) == 0 { return stringTarget{s: NotDefined} @@ -96,43 +77,6 @@ func TargetFromChainID(chainTargetType, chainTargetName string, chainID []byte) return stringTarget{s: t + ":" + n + ":" + c} } -func TargetFromShardIDs(v [][]byte) Target { - if len(v) == 0 { - return stringTarget{s: NotDefined} - } - sb := &strings.Builder{} - for i, s := range v { - if i > 0 { - sb.WriteString(";") - } - if len(s) == 0 { - sb.WriteString(Empty) - } else { - sb.WriteString(base58.Encode(s)) - } - } - return sb -} - -func TargetFromTreeID(containerID []byte, treeID string) Target { - if len(containerID) == 0 && len(treeID) == 0 { - return stringTarget{s: NotDefined} - } - c, t := Empty, Empty - if len(containerID) > 0 { - var cnr cid.ID - if err := cnr.Decode(containerID); err != nil { - c = InvalidValue - } else { - c = cnr.EncodeToString() - } - } - if len(treeID) > 0 { - t = treeID - } - return stringTarget{s: c + ":" + t} -} - func TargetFromContainerIDObjectID(containerID *refs.ContainerID, objectID *refs.ObjectID) Target { if containerID == nil && objectID == nil { return stringTarget{s: NotDefined} diff --git a/pkg/services/accounting/audit.go b/pkg/services/accounting/audit.go deleted file mode 100644 index 1d8f8836fa..0000000000 --- a/pkg/services/accounting/audit.go +++ /dev/null @@ -1,42 +0,0 @@ -package accounting - -import ( - "context" - "sync/atomic" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" - acc_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" -) - -var _ Server = (*auditService)(nil) - -type auditService struct { - next Server - log *logger.Logger - enabled *atomic.Bool -} - -func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server { - return &auditService{ - next: next, - log: log, - enabled: enabled, - } -} - -// Balance implements Server. -func (l *auditService) Balance(ctx context.Context, req *accounting.BalanceRequest) (*accounting.BalanceResponse, error) { - res, err := l.next.Balance(ctx, req) - - if !l.enabled.Load() { - return res, err - } - - audit.LogRequest(l.log, acc_grpc.AccountingService_Balance_FullMethodName, req, - audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil) - - return res, err -} diff --git a/pkg/services/control/server/audit.go b/pkg/services/control/server/audit.go deleted file mode 100644 index 6443ea378c..0000000000 --- a/pkg/services/control/server/audit.go +++ /dev/null @@ -1,298 +0,0 @@ -package control - -import ( - "context" - "sync/atomic" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" - ctl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" -) - -var _ ctl.ControlServiceServer = (*auditService)(nil) - -type auditService struct { - next ctl.ControlServiceServer - log *logger.Logger - enabled *atomic.Bool -} - -func NewAuditService(next ctl.ControlServiceServer, log *logger.Logger, enabled *atomic.Bool) ctl.ControlServiceServer { - return &auditService{ - next: next, - log: log, - enabled: enabled, - } -} - -// AddChainLocalOverride implements control.ControlServiceServer. -func (a *auditService) AddChainLocalOverride(ctx context.Context, req *ctl.AddChainLocalOverrideRequest) (*ctl.AddChainLocalOverrideResponse, error) { - res, err := a.next.AddChainLocalOverride(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_AddChainLocalOverride_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(), - req.GetBody().GetTarget().GetName(), - res.GetBody().GetChainId()), - err == nil) - return res, err -} - -// DetachShards implements control.ControlServiceServer. -func (a *auditService) DetachShards(ctx context.Context, req *ctl.DetachShardsRequest) (*ctl.DetachShardsResponse, error) { - res, err := a.next.DetachShards(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_DetachShards_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) - return res, err -} - -// Doctor implements control.ControlServiceServer. -func (a *auditService) Doctor(ctx context.Context, req *ctl.DoctorRequest) (*ctl.DoctorResponse, error) { - res, err := a.next.Doctor(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_Doctor_FullMethodName, req.GetSignature().GetKey(), nil, err == nil) - return res, err -} - -// DropObjects implements control.ControlServiceServer. -func (a *auditService) DropObjects(ctx context.Context, req *ctl.DropObjectsRequest) (*ctl.DropObjectsResponse, error) { - res, err := a.next.DropObjects(ctx, req) - if !a.enabled.Load() { - return res, err - } - var list []string - for _, v := range req.GetBody().GetAddressList() { - if len(v) == 0 { - list = append(list, audit.Empty) - continue - } - var a oid.Address - if e := a.DecodeString(string(v)); e != nil { - list = append(list, audit.InvalidValue) - } else { - list = append(list, a.EncodeToString()) - } - } - - audit.LogRequestWithKey(a.log, ctl.ControlService_DropObjects_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromStringSlice(list), err == nil) - return res, err -} - -// EvacuateShard implements control.ControlServiceServer. -func (a *auditService) EvacuateShard(ctx context.Context, req *ctl.EvacuateShardRequest) (*ctl.EvacuateShardResponse, error) { - res, err := a.next.EvacuateShard(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_EvacuateShard_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) - return res, err -} - -// FlushCache implements control.ControlServiceServer. -func (a *auditService) FlushCache(ctx context.Context, req *ctl.FlushCacheRequest) (*ctl.FlushCacheResponse, error) { - res, err := a.next.FlushCache(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_FlushCache_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) - return res, err -} - -// GetChainLocalOverride implements control.ControlServiceServer. -func (a *auditService) GetChainLocalOverride(ctx context.Context, req *ctl.GetChainLocalOverrideRequest) (*ctl.GetChainLocalOverrideResponse, error) { - res, err := a.next.GetChainLocalOverride(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_GetChainLocalOverride_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromChainID( - req.GetBody().GetTarget().GetType().String(), - req.GetBody().GetTarget().GetName(), - req.GetBody().GetChainId()), - err == nil) - return res, err -} - -// GetShardEvacuationStatus implements control.ControlServiceServer. -func (a *auditService) GetShardEvacuationStatus(ctx context.Context, req *ctl.GetShardEvacuationStatusRequest) (*ctl.GetShardEvacuationStatusResponse, error) { - res, err := a.next.GetShardEvacuationStatus(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_GetShardEvacuationStatus_FullMethodName, req.GetSignature().GetKey(), - nil, err == nil) - return res, err -} - -// HealthCheck implements control.ControlServiceServer. -func (a *auditService) HealthCheck(ctx context.Context, req *ctl.HealthCheckRequest) (*ctl.HealthCheckResponse, error) { - res, err := a.next.HealthCheck(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_HealthCheck_FullMethodName, req.GetSignature().GetKey(), - nil, err == nil) - return res, err -} - -// ListChainLocalOverrides implements control.ControlServiceServer. -func (a *auditService) ListChainLocalOverrides(ctx context.Context, req *ctl.ListChainLocalOverridesRequest) (*ctl.ListChainLocalOverridesResponse, error) { - res, err := a.next.ListChainLocalOverrides(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_ListChainLocalOverrides_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(), - req.GetBody().GetTarget().GetName(), - nil), - err == nil) - return res, err -} - -// ListShards implements control.ControlServiceServer. -func (a *auditService) ListShards(ctx context.Context, req *ctl.ListShardsRequest) (*ctl.ListShardsResponse, error) { - res, err := a.next.ListShards(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_ListShards_FullMethodName, req.GetSignature().GetKey(), - nil, err == nil) - return res, err -} - -// ListTargetsLocalOverrides implements control.ControlServiceServer. -func (a *auditService) ListTargetsLocalOverrides(ctx context.Context, req *ctl.ListTargetsLocalOverridesRequest) (*ctl.ListTargetsLocalOverridesResponse, error) { - res, err := a.next.ListTargetsLocalOverrides(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_ListTargetsLocalOverrides_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromString(req.GetBody().GetChainName()), err == nil) - return res, err -} - -// RemoveChainLocalOverride implements control.ControlServiceServer. -func (a *auditService) RemoveChainLocalOverride(ctx context.Context, req *ctl.RemoveChainLocalOverrideRequest) (*ctl.RemoveChainLocalOverrideResponse, error) { - res, err := a.next.RemoveChainLocalOverride(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_RemoveChainLocalOverride_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(), - req.GetBody().GetTarget().GetName(), - req.GetBody().GetChainId()), - err == nil) - return res, err -} - -// RemoveChainLocalOverridesByTarget implements control.ControlServiceServer. -func (a *auditService) RemoveChainLocalOverridesByTarget(ctx context.Context, req *ctl.RemoveChainLocalOverridesByTargetRequest) (*ctl.RemoveChainLocalOverridesByTargetResponse, error) { - res, err := a.next.RemoveChainLocalOverridesByTarget(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_RemoveChainLocalOverridesByTarget_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(), - req.GetBody().GetTarget().GetName(), - nil), - err == nil) - return res, err -} - -// ResetShardEvacuationStatus implements control.ControlServiceServer. -func (a *auditService) ResetShardEvacuationStatus(ctx context.Context, req *ctl.ResetShardEvacuationStatusRequest) (*ctl.ResetShardEvacuationStatusResponse, error) { - res, err := a.next.ResetShardEvacuationStatus(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_ResetShardEvacuationStatus_FullMethodName, req.GetSignature().GetKey(), - nil, err == nil) - return res, err -} - -// SealWriteCache implements control.ControlServiceServer. -func (a *auditService) SealWriteCache(ctx context.Context, req *ctl.SealWriteCacheRequest) (*ctl.SealWriteCacheResponse, error) { - res, err := a.next.SealWriteCache(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_SealWriteCache_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) - return res, err -} - -// SetNetmapStatus implements control.ControlServiceServer. -func (a *auditService) SetNetmapStatus(ctx context.Context, req *ctl.SetNetmapStatusRequest) (*ctl.SetNetmapStatusResponse, error) { - res, err := a.next.SetNetmapStatus(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_SetNetmapStatus_FullMethodName, req.GetSignature().GetKey(), - nil, err == nil) - return res, err -} - -// GetNetmapStatus implements control.ControlServiceServer. -func (a *auditService) GetNetmapStatus(ctx context.Context, req *ctl.GetNetmapStatusRequest) (*ctl.GetNetmapStatusResponse, error) { - res, err := a.next.GetNetmapStatus(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_GetNetmapStatus_FullMethodName, req.GetSignature().GetKey(), - nil, err == nil) - return res, err -} - -// SetShardMode implements control.ControlServiceServer. -func (a *auditService) SetShardMode(ctx context.Context, req *ctl.SetShardModeRequest) (*ctl.SetShardModeResponse, error) { - res, err := a.next.SetShardMode(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_SetShardMode_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) - return res, err -} - -// StartShardEvacuation implements control.ControlServiceServer. -func (a *auditService) StartShardEvacuation(ctx context.Context, req *ctl.StartShardEvacuationRequest) (*ctl.StartShardEvacuationResponse, error) { - res, err := a.next.StartShardEvacuation(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_StartShardEvacuation_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil) - return res, err -} - -// StopShardEvacuation implements control.ControlServiceServer. -func (a *auditService) StopShardEvacuation(ctx context.Context, req *ctl.StopShardEvacuationRequest) (*ctl.StopShardEvacuationResponse, error) { - res, err := a.next.StopShardEvacuation(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_StopShardEvacuation_FullMethodName, req.GetSignature().GetKey(), - nil, err == nil) - return res, err -} - -// SynchronizeTree implements control.ControlServiceServer. -func (a *auditService) SynchronizeTree(ctx context.Context, req *ctl.SynchronizeTreeRequest) (*ctl.SynchronizeTreeResponse, error) { - res, err := a.next.SynchronizeTree(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, ctl.ControlService_SynchronizeTree_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return res, err -} diff --git a/pkg/services/netmap/audit.go b/pkg/services/netmap/audit.go deleted file mode 100644 index 906fd398e3..0000000000 --- a/pkg/services/netmap/audit.go +++ /dev/null @@ -1,60 +0,0 @@ -package netmap - -import ( - "context" - "sync/atomic" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" -) - -var _ Server = (*auditService)(nil) - -type auditService struct { - next Server - log *logger.Logger - enabled *atomic.Bool -} - -func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server { - return &auditService{ - next: next, - log: log, - enabled: enabled, - } -} - -// LocalNodeInfo implements Server. -func (a *auditService) LocalNodeInfo(ctx context.Context, req *netmap.LocalNodeInfoRequest) (*netmap.LocalNodeInfoResponse, error) { - res, err := a.next.LocalNodeInfo(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequest(a.log, netmapGRPC.NetmapService_LocalNodeInfo_FullMethodName, req, - nil, err == nil) - return res, err -} - -// NetworkInfo implements Server. -func (a *auditService) NetworkInfo(ctx context.Context, req *netmap.NetworkInfoRequest) (*netmap.NetworkInfoResponse, error) { - res, err := a.next.NetworkInfo(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequest(a.log, netmapGRPC.NetmapService_NetworkInfo_FullMethodName, req, - nil, err == nil) - return res, err -} - -// Snapshot implements Server. -func (a *auditService) Snapshot(ctx context.Context, req *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) { - res, err := a.next.Snapshot(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequest(a.log, netmapGRPC.NetmapService_NetmapSnapshot_FullMethodName, req, - nil, err == nil) - return res, err -} diff --git a/pkg/services/session/audit.go b/pkg/services/session/audit.go deleted file mode 100644 index 19d3383d9b..0000000000 --- a/pkg/services/session/audit.go +++ /dev/null @@ -1,39 +0,0 @@ -package session - -import ( - "context" - "sync/atomic" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" -) - -var _ Server = (*auditService)(nil) - -type auditService struct { - next Server - log *logger.Logger - enabled *atomic.Bool -} - -func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server { - return &auditService{ - next: next, - log: log, - enabled: enabled, - } -} - -// Create implements Server. -func (a *auditService) Create(ctx context.Context, req *session.CreateRequest) (*session.CreateResponse, error) { - res, err := a.next.Create(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequest(a.log, sessionGRPC.SessionService_Create_FullMethodName, req, - audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil) - return res, err -} diff --git a/pkg/services/tree/audit.go b/pkg/services/tree/audit.go deleted file mode 100644 index bec71f5d44..0000000000 --- a/pkg/services/tree/audit.go +++ /dev/null @@ -1,135 +0,0 @@ -package tree - -import ( - "context" - "sync/atomic" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" -) - -var _ TreeServiceServer = (*auditService)(nil) - -type auditService struct { - next TreeServiceServer - log *logger.Logger - enabled *atomic.Bool -} - -func NewAuditService(next TreeServiceServer, log *logger.Logger, enabled *atomic.Bool) TreeServiceServer { - return &auditService{ - next: next, - log: log, - enabled: enabled, - } -} - -// Add implements TreeServiceServer. -func (a *auditService) Add(ctx context.Context, req *AddRequest) (*AddResponse, error) { - res, err := a.next.Add(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, TreeService_Add_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return res, err -} - -// AddByPath implements TreeServiceServer. -func (a *auditService) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByPathResponse, error) { - res, err := a.next.AddByPath(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, TreeService_AddByPath_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return res, err -} - -// Apply implements TreeServiceServer. -func (a *auditService) Apply(ctx context.Context, req *ApplyRequest) (*ApplyResponse, error) { - res, err := a.next.Apply(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, TreeService_Apply_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return res, err -} - -// GetNodeByPath implements TreeServiceServer. -func (a *auditService) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) (*GetNodeByPathResponse, error) { - res, err := a.next.GetNodeByPath(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, TreeService_GetNodeByPath_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return res, err -} - -// GetOpLog implements TreeServiceServer. -func (a *auditService) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) error { - err := a.next.GetOpLog(req, srv) - if !a.enabled.Load() { - return err - } - audit.LogRequestWithKey(a.log, TreeService_GetOpLog_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return err -} - -// GetSubTree implements TreeServiceServer. -func (a *auditService) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeServer) error { - err := a.next.GetSubTree(req, srv) - if !a.enabled.Load() { - return err - } - audit.LogRequestWithKey(a.log, TreeService_GetSubTree_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return err -} - -// Healthcheck implements TreeServiceServer. -func (a *auditService) Healthcheck(ctx context.Context, req *HealthcheckRequest) (*HealthcheckResponse, error) { - res, err := a.next.Healthcheck(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, TreeService_Healthcheck_FullMethodName, req.GetSignature().GetKey(), - nil, err == nil) - return res, err -} - -// Move implements TreeServiceServer. -func (a *auditService) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, error) { - res, err := a.next.Move(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, TreeService_Move_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return res, err -} - -// Remove implements TreeServiceServer. -func (a *auditService) Remove(ctx context.Context, req *RemoveRequest) (*RemoveResponse, error) { - res, err := a.next.Remove(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, TreeService_Remove_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil) - return res, err -} - -// TreeList implements TreeServiceServer. -func (a *auditService) TreeList(ctx context.Context, req *TreeListRequest) (*TreeListResponse, error) { - res, err := a.next.TreeList(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequestWithKey(a.log, TreeService_TreeList_FullMethodName, req.GetSignature().GetKey(), - audit.TargetFromTreeID(req.GetBody().GetContainerId(), ""), err == nil) - return res, err -} From 87a4a6e8d05b766b29db2b593350ba79186b72c9 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 26 Jun 2024 14:46:32 +0300 Subject: [PATCH 0649/1413] [#1154] node: Add info metric Signed-off-by: Alexander Chuprov --- internal/metrics/application.go | 21 +++++++++++++++++++++ internal/metrics/node.go | 3 +++ 2 files changed, 24 insertions(+) create mode 100644 internal/metrics/application.go diff --git a/internal/metrics/application.go b/internal/metrics/application.go new file mode 100644 index 0000000000..8bc408ab65 --- /dev/null +++ b/internal/metrics/application.go @@ -0,0 +1,21 @@ +package metrics + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +type ApplicationInfo struct { + versionValue *prometheus.GaugeVec +} + +func NewApplicationInfo(version string) *ApplicationInfo { + appInfo := &ApplicationInfo{ + versionValue: metrics.NewGaugeVec(prometheus.GaugeOpts{ + Name: "app_info", + Help: "General information about the application.", + }, []string{"version"}), + } + appInfo.versionValue.With(prometheus.Labels{"version": version}) + return appInfo +} diff --git a/internal/metrics/node.go b/internal/metrics/node.go index 0dd86d90ec..d9e4014467 100644 --- a/internal/metrics/node.go +++ b/internal/metrics/node.go @@ -1,6 +1,7 @@ package metrics import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/misc" morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" @@ -24,6 +25,7 @@ type NodeMetrics struct { morphClient *morphClientMetrics morphCache *morphCacheMetrics log logger.LogMetrics + appInfo *ApplicationInfo } func NewNodeMetrics() *NodeMetrics { @@ -49,6 +51,7 @@ func NewNodeMetrics() *NodeMetrics { morphClient: newMorphClientMetrics(), morphCache: newMorphCacheMetrics(namespace), log: logger.NewLogMetrics(namespace), + appInfo: NewApplicationInfo(misc.Version), } } From 452faa3c893ec31eb09c43008eb503e0f1616857 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 26 Jun 2024 14:47:16 +0300 Subject: [PATCH 0650/1413] [#1154] ir: Add info metric Signed-off-by: Alexander Chuprov --- internal/metrics/innerring.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/metrics/innerring.go b/internal/metrics/innerring.go index 3e438a01be..f6b14a6320 100644 --- a/internal/metrics/innerring.go +++ b/internal/metrics/innerring.go @@ -4,6 +4,7 @@ import ( "strconv" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" "github.com/prometheus/client_golang/prometheus" @@ -16,6 +17,7 @@ type InnerRingServiceMetrics struct { eventDuration *prometheus.HistogramVec morphCacheMetrics *morphCacheMetrics logMetrics logger.LogMetrics + appInfo *ApplicationInfo } // NewInnerRingMetrics returns new instance of metrics collectors for inner ring. @@ -46,6 +48,7 @@ func NewInnerRingMetrics() *InnerRingServiceMetrics { health: health, eventDuration: eventDuration, morphCacheMetrics: newMorphCacheMetrics(innerRingNamespace), + appInfo: NewApplicationInfo(misc.Version), logMetrics: logger.NewLogMetrics(innerRingNamespace), } } From 81070ada01cc071dc1f211d852ff0d0667605454 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 26 Jun 2024 14:44:41 +0300 Subject: [PATCH 0651/1413] [#1091] cli: Check `NotFound` properly for `control list-targets` Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/control/list_targets.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmd/frostfs-cli/modules/control/list_targets.go b/cmd/frostfs-cli/modules/control/list_targets.go index ddd80b31b9..6a988c355e 100644 --- a/cmd/frostfs-cli/modules/control/list_targets.go +++ b/cmd/frostfs-cli/modules/control/list_targets.go @@ -13,6 +13,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) const ( @@ -52,6 +54,10 @@ func listTargets(cmd *cobra.Command, _ []string) { resp, err = control.ListTargetsLocalOverrides(client, req) return err }) + if err != nil && status.Code(err) == codes.NotFound { + cmd.Println("Local overrides are not defined for any target.") + return + } commonCmd.ExitOnErr(cmd, "rpc error: %w", err) verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) From 4c7ff159ec90579b962c1d81454047c0752c17ad Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 26 Jun 2024 11:19:33 +0300 Subject: [PATCH 0652/1413] [#1201] writecache: Cancel background flush without lock Signed-off-by: Dmitrii Stepanov --- .../writecache/cachebbolt.go | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/writecache/cachebbolt.go b/pkg/local_object_storage/writecache/cachebbolt.go index 254d8754fa..cdd4ed4423 100644 --- a/pkg/local_object_storage/writecache/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cachebbolt.go @@ -4,6 +4,7 @@ import ( "context" "os" "sync" + "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" @@ -30,7 +31,7 @@ type cache struct { // flushCh is a channel with objects to flush. flushCh chan objectInfo // cancel is cancel function, protected by modeMtx in Close. - cancel func() + cancel atomic.Value // wg is a wait group for flush workers. wg sync.WaitGroup // store contains underlying database. @@ -54,7 +55,10 @@ const ( defaultMaxCacheSize = 1 << 30 // 1 GiB ) -var defaultBucket = []byte{0} +var ( + defaultBucket = []byte{0} + dummyCanceler context.CancelFunc = func() {} +) // New creates new writecache instance. func New(opts ...Option) Cache { @@ -114,20 +118,19 @@ func (c *cache) Open(_ context.Context, mod mode.Mode) error { func (c *cache) Init() error { c.metrics.SetMode(mode.ConvertToComponentModeDegraded(c.mode)) ctx, cancel := context.WithCancel(context.Background()) - c.cancel = cancel + c.cancel.Store(cancel) c.runFlushLoop(ctx) return nil } // Close closes db connection and stops services. Executes ObjectCounters.FlushAndClose op. func (c *cache) Close() error { + if cancelValue := c.cancel.Swap(dummyCanceler); cancelValue != nil { + cancelValue.(context.CancelFunc)() + } // We cannot lock mutex for the whole operation duration // because it is taken by some background workers, so `wg.Wait()` is done without modeMtx. c.modeMtx.Lock() - if c.cancel != nil { - c.cancel() - c.cancel = nil - } c.mode = mode.DegradedReadOnly // prevent new operations from being processed c.modeMtx.Unlock() From 7085723c6bde2e2cf90dc5029bd6a170db621753 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 4 Apr 2024 10:40:21 +0300 Subject: [PATCH 0653/1413] [#1074] pilorama: Allow empty filenames in SortedByFilename() Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/tree.go | 4 +-- pkg/local_object_storage/pilorama/boltdb.go | 17 ++++++++----- pkg/local_object_storage/pilorama/forest.go | 23 +++++++++++------ .../pilorama/forest_test.go | 25 +++++++++++-------- pkg/local_object_storage/pilorama/heap.go | 6 ++--- .../pilorama/interface.go | 2 +- pkg/local_object_storage/shard/tree.go | 6 ++--- pkg/services/tree/service.go | 4 +-- 8 files changed, 53 insertions(+), 34 deletions(-) diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index 52ea399fe6..8bacdba767 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -210,7 +210,7 @@ func (e *StorageEngine) TreeGetChildren(ctx context.Context, cid cidSDK.ID, tree } // TreeSortedByFilename implements the pilorama.Forest interface. -func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.Node, last string, count int) ([]pilorama.NodeInfo, string, error) { +func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.Node, last *string, count int) ([]pilorama.NodeInfo, *string, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.TreeSortedByFilename", trace.WithAttributes( attribute.String("container_id", cid.EncodeToString()), @@ -222,7 +222,7 @@ func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, var err error var nodes []pilorama.NodeInfo - var cursor string + var cursor *string for _, sh := range e.sortShards(cid) { nodes, cursor, err = sh.TreeSortedByFilename(ctx, cid, treeID, nodeID, last, count) if err != nil { diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index d4ae35ff40..9fc95dbbb7 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1004,7 +1004,7 @@ func (t *boltForest) hasFewChildren(b *bbolt.Bucket, nodeID Node, threshold int) } // TreeSortedByFilename implements the Forest interface. -func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node, last string, count int) ([]NodeInfo, string, error) { +func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node, last *string, count int) ([]NodeInfo, *string, error) { var ( startedAt = time.Now() success = false @@ -1026,7 +1026,7 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr defer t.modeMtx.RUnlock() if t.mode.NoMetabase() { - return nil, "", ErrDegradedMode + return nil, last, ErrDegradedMode } h := newHeap(last, count) @@ -1070,20 +1070,25 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr } if fewChildren { - result = sortAndCut(result, []byte(last)) + result = sortAndCut(result, last) } if len(result) != 0 { - last = string(result[len(result)-1].Meta.GetAttr(AttributeFilename)) + s := string(result[len(result)-1].Meta.GetAttr(AttributeFilename)) + last = &s } return result, last, metaerr.Wrap(err) } -func sortAndCut(result []NodeInfo, last []byte) []NodeInfo { +func sortAndCut(result []NodeInfo, last *string) []NodeInfo { + var lastBytes []byte + if last != nil { + lastBytes = []byte(*last) + } sort.Slice(result, func(i, j int) bool { return bytes.Compare(result[i].Meta.GetAttr(AttributeFilename), result[j].Meta.GetAttr(AttributeFilename)) == -1 }) for i := range result { - if bytes.Compare(last, result[i].Meta.GetAttr(AttributeFilename)) == -1 { + if lastBytes == nil || bytes.Compare(lastBytes, result[i].Meta.GetAttr(AttributeFilename)) == -1 { return result[i:] } } diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index fedd3f90d4..b45a77b99d 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -156,11 +156,11 @@ func (f *memoryForest) TreeGetMeta(_ context.Context, cid cid.ID, treeID string, } // TreeSortedByFilename implements the Forest interface. -func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeID string, nodeID Node, start string, count int) ([]NodeInfo, string, error) { +func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeID string, nodeID Node, start *string, count int) ([]NodeInfo, *string, error) { fullID := cid.String() + "/" + treeID s, ok := f.treeMap[fullID] if !ok { - return nil, "", ErrTreeNotFound + return nil, start, ErrTreeNotFound } if count == 0 { return nil, start, nil @@ -169,7 +169,14 @@ func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeI children := s.tree.getChildren(nodeID) res := make([]NodeInfo, 0, len(children)) for _, childID := range children { - if len(s.infoMap[childID].Meta.GetAttr(AttributeFilename)) == 0 { + var found bool + for _, kv := range s.infoMap[childID].Meta.Items { + if kv.Key == AttributeFilename { + found = true + break + } + } + if !found { continue } res = append(res, NodeInfo{ @@ -179,22 +186,24 @@ func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeI }) } if len(res) == 0 { - return res, "", nil + return res, start, nil } sort.Slice(res, func(i, j int) bool { return bytes.Compare(res[i].Meta.GetAttr(AttributeFilename), res[j].Meta.GetAttr(AttributeFilename)) == -1 }) for i := range res { - if string(res[i].Meta.GetAttr(AttributeFilename)) > start { + if start == nil || string(res[i].Meta.GetAttr(AttributeFilename)) > *start { finish := i + count if len(res) < finish { finish = len(res) } - return res[i:finish], string(res[finish-1].Meta.GetAttr(AttributeFilename)), nil + last := string(res[finish-1].Meta.GetAttr(AttributeFilename)) + return res[i:finish], &last, nil } } - return nil, string(res[len(res)-1].Meta.GetAttr(AttributeFilename)), nil + last := string(res[len(res)-1].Meta.GetAttr(AttributeFilename)) + return nil, &last, nil } // TreeGetChildren implements the Forest interface. diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 9c343f6329..9da0177cca 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -215,7 +215,7 @@ func BenchmarkForestSortedIteration(b *testing.B) { b.Run(providers[i].name+",root", func(b *testing.B) { for i := 0; i < b.N; i++ { - res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, RootID, "", 100) + res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, RootID, nil, 100) if err != nil || len(res) != 100 { b.Fatalf("err %v, count %d", err, len(res)) } @@ -223,7 +223,7 @@ func BenchmarkForestSortedIteration(b *testing.B) { }) b.Run(providers[i].name+",leaf", func(b *testing.B) { for i := 0; i < b.N; i++ { - res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, 1, "", 100) + res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, 1, nil, 100) if err != nil || len(res) != 0 { b.FailNow() } @@ -246,14 +246,14 @@ func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} treeID := "version" - treeAdd := func(t *testing.T, ts int) { + treeAdd := func(t *testing.T, ts int, filename string) { _, err := s.TreeMove(context.Background(), d, treeID, &Move{ Child: RootID + uint64(ts), Parent: RootID, Meta: Meta{ Time: Timestamp(ts), Items: []KeyValue{ - {Key: AttributeFilename, Value: []byte(strconv.Itoa(ts))}, + {Key: AttributeFilename, Value: []byte(filename)}, }, }, }) @@ -261,19 +261,20 @@ func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { } const count = 9 - for i := 0; i < count; i++ { - treeAdd(t, i+1) + treeAdd(t, 1, "") + for i := 1; i < count; i++ { + treeAdd(t, i+1, strconv.Itoa(i+1)) } var result []NodeInfo - treeAppend := func(t *testing.T, last string, count int) string { + treeAppend := func(t *testing.T, last *string, count int) *string { res, cursor, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, RootID, last, count) require.NoError(t, err) result = append(result, res...) return cursor } - last := treeAppend(t, "", 2) + last := treeAppend(t, nil, 2) last = treeAppend(t, last, 3) last = treeAppend(t, last, 0) last = treeAppend(t, last, 1) @@ -282,7 +283,11 @@ func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { require.Len(t, result, count) for i := range result { require.Equal(t, RootID+uint64(i+1), result[i].ID) - require.Equal(t, strconv.Itoa(RootID+i+1), string(result[i].Meta.GetAttr(AttributeFilename))) + if i == 0 { + require.Equal(t, "", string(result[i].Meta.GetAttr(AttributeFilename))) + } else { + require.Equal(t, strconv.Itoa(RootID+i+1), string(result[i].Meta.GetAttr(AttributeFilename))) + } } } @@ -341,7 +346,7 @@ func testForestTreeSortedByFilename(t *testing.T, s ForestStorage) { } getChildren := func(t *testing.T, id Node) []NodeInfo { - res, _, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, id, "", len(items)) + res, _, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, id, nil, len(items)) require.NoError(t, err) return res } diff --git a/pkg/local_object_storage/pilorama/heap.go b/pkg/local_object_storage/pilorama/heap.go index d81ec735d0..e8a21e221c 100644 --- a/pkg/local_object_storage/pilorama/heap.go +++ b/pkg/local_object_storage/pilorama/heap.go @@ -28,12 +28,12 @@ func (h *filenameHeap) Pop() any { // fixedHeap maintains a fixed number of smallest elements started at some point. type fixedHeap struct { - start string + start *string count int h *filenameHeap } -func newHeap(start string, count int) *fixedHeap { +func newHeap(start *string, count int) *fixedHeap { h := new(filenameHeap) heap.Init(h) @@ -45,7 +45,7 @@ func newHeap(start string, count int) *fixedHeap { } func (h *fixedHeap) push(id Node, filename string) bool { - if filename == "" || filename <= h.start { + if h.start != nil && filename <= *h.start { return false } heap.Push(h.h, heapInfo{id: id, filename: filename}) diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index 79449e080c..f7f5a85b1b 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -35,7 +35,7 @@ type Forest interface { TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node) ([]NodeInfo, error) // TreeSortedByFilename returns children of the node with the specified ID. The nodes are sorted by the filename attribute.. // Should return ErrTreeNotFound if the tree is not found, and empty result if the node is not in the tree. - TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node, last string, count int) ([]NodeInfo, string, error) + TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node, last *string, count int) ([]NodeInfo, *string, error) // TreeGetOpLog returns first log operation stored at or above the height. // In case no such operation is found, empty Move and nil error should be returned. TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID string, height uint64) (Move, error) diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index 9a78f99ea9..e92a61e5b7 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -184,7 +184,7 @@ func (s *Shard) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID strin } // TreeSortedByFilename implements the pilorama.Forest interface. -func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.Node, last string, count int) ([]pilorama.NodeInfo, string, error) { +func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.Node, last *string, count int) ([]pilorama.NodeInfo, *string, error) { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeSortedByFilename", trace.WithAttributes( attribute.String("shard_id", s.ID().String()), @@ -196,14 +196,14 @@ func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID defer span.End() if s.pilorama == nil { - return nil, "", ErrPiloramaDisabled + return nil, last, ErrPiloramaDisabled } s.m.RLock() defer s.m.RUnlock() if s.info.Mode.NoMetabase() { - return nil, "", ErrDegradedMode + return nil, last, ErrDegradedMode } return s.pilorama.TreeSortedByFilename(ctx, cid, treeID, nodeID, last, count) } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index cce41e94dd..85f5314660 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -446,7 +446,7 @@ func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid type stackItem struct { values []pilorama.NodeInfo parent pilorama.Node - last string + last *string } // Traverse the tree in a DFS manner. Because we need to support arbitrary depth, @@ -502,7 +502,7 @@ func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid } if b.GetDepth() == 0 || uint32(len(stack)) < b.GetDepth() { - children, last, err := forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), node.ID, "", batchSize) + children, last, err := forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), node.ID, nil, batchSize) if err != nil { return err } From dc6778f38516eaa3f75e7d0b868a725efe1a5ec0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Jun 2024 16:22:12 +0300 Subject: [PATCH 0654/1413] [#1213] fmt: Drop unused interfaces Signed-off-by: Dmitrii Stepanov --- pkg/core/object/fmt.go | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index b997aa1822..96f7218061 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -14,7 +14,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -41,30 +40,12 @@ type cfg struct { verifyTokenIssuer bool } -// DeleteHandler is an interface of delete queue processor. -type DeleteHandler interface { - // DeleteObjects places objects to a removal queue. - // - // Returns apistatus.LockNonRegularObject if at least one object - // is locked. - DeleteObjects(oid.Address, ...oid.Address) error -} - // LockSource is a source of lock relations between the objects. type LockSource interface { // IsLocked must clarify object's lock status. IsLocked(ctx context.Context, address oid.Address) (bool, error) } -// Locker is an object lock storage interface. -type Locker interface { - // Lock list of objects as locked by locker in the specified container. - // - // Returns apistatus.LockNonRegularObject if at least object in locked - // list is irregular (not type of REGULAR). - Lock(idCnr cid.ID, locker oid.ID, locked []oid.ID) error -} - var errNilObject = errors.New("object is nil") var errNilID = errors.New("missing identifier") From dc2867682fb89c10618a463ce7d422f39c12ca4f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Jun 2024 16:22:37 +0300 Subject: [PATCH 0655/1413] [#1213] deleteSvc: Do not allow to delete EC chunks Signed-off-by: Dmitrii Stepanov --- pkg/services/object/delete/exec.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index 22928dcd5b..c2f92950fb 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -17,6 +17,8 @@ import ( "go.uber.org/zap" ) +var errDeleteECChunk = errors.New("invalid operation: delete EC object chunk") + type execCtx struct { svc *Service @@ -66,13 +68,16 @@ func (exec *execCtx) newAddress(id oid.ID) oid.Address { } func (exec *execCtx) formExtendedInfo(ctx context.Context) error { - _, err := exec.svc.header.head(ctx, exec) + obj, err := exec.svc.header.head(ctx, exec) var errSplitInfo *objectSDK.SplitInfoError var errECInfo *objectSDK.ECInfoError switch { case err == nil: + if ech := obj.ECHeader(); ech != nil { + return errDeleteECChunk + } return nil case errors.As(err, &errSplitInfo): exec.splitInfo = errSplitInfo.SplitInfo() From 10497e913697741840278eb134efb6588a8b4f0a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Jun 2024 17:45:00 +0300 Subject: [PATCH 0656/1413] [#1213] cli: Do not allow to lock EC chunks Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/util.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index ff6b3219d6..381c790e95 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -354,7 +354,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, Prepare(cmd, &prmHead) - _, err := internal.HeadObject(cmd.Context(), prmHead) + o, err := internal.HeadObject(cmd.Context(), prmHead) var errSplit *objectSDK.SplitInfoError var errEC *objectSDK.ECInfoError @@ -364,6 +364,9 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, commonCmd.ExitOnErr(cmd, "failed to get raw object header: %w", err) case err == nil: common.PrintVerbose(cmd, "Raw header received - object is singular.") + if ech := o.Header().ECHeader(); ech != nil { + commonCmd.ExitOnErr(cmd, "Lock EC chunk failed: %w", errors.ErrUnsupported) + } return nil case errors.As(err, &errSplit): common.PrintVerbose(cmd, "Split information received - object is virtual.") From 7a8ac4907a39a12c907c7e1167909ef4447b570c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Jun 2024 22:36:29 +0300 Subject: [PATCH 0657/1413] [#1213] engine: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/head.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index 97fb5be3a9..92d1b20fc2 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -151,18 +151,3 @@ func Head(ctx context.Context, storage *StorageEngine, addr oid.Address) (*objec return res.Header(), nil } - -// HeadRaw reads object header from local storage by provided address and raw -// flag. -func HeadRaw(ctx context.Context, storage *StorageEngine, addr oid.Address, raw bool) (*objectSDK.Object, error) { - var headPrm HeadPrm - headPrm.WithAddress(addr) - headPrm.WithRaw(raw) - - res, err := storage.Head(ctx, headPrm) - if err != nil { - return nil, err - } - - return res.Header(), nil -} From 72ab373b719887dd04859adbd945d6ac29a752ba Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 26 Jun 2024 17:10:27 +0300 Subject: [PATCH 0658/1413] [#218] adm: Update doc for `morph generate-alphabet` Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/README.md | 3 ++- cmd/frostfs-adm/docs/deploy.md | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/README.md b/cmd/frostfs-adm/README.md index f3dbe6950b..3dfcc87818 100644 --- a/cmd/frostfs-adm/README.md +++ b/cmd/frostfs-adm/README.md @@ -56,7 +56,8 @@ credentials: # passwords for consensus node / alphabet wallets #### Network deployment - `generate-alphabet` generates a set of wallets for consensus and - Alphabet nodes. + Alphabet nodes. The list of the name for alphabet wallets(no gaps between names allowed, order is important): + - az, buky, vedi, glagoli, dobro, yest, zhivete, dzelo, zemlja, izhe, izhei, gerv, kako, ljudi, mislete, nash, on, pokoj, rtsi, slovo, tverdo, uk - `init` initializes the sidechain by deploying smart contracts and setting provided FrostFS network configuration. diff --git a/cmd/frostfs-adm/docs/deploy.md b/cmd/frostfs-adm/docs/deploy.md index e510f478d4..87d2e47c1b 100644 --- a/cmd/frostfs-adm/docs/deploy.md +++ b/cmd/frostfs-adm/docs/deploy.md @@ -64,6 +64,11 @@ alphabet-wallets: /home/user/deploy/alphabet-wallets wallet[0]: hunter2 ``` +This command generates wallets with the following names: + - az, buky, vedi, glagoli, dobro, yest, zhivete, dzelo, zemlja, izhe, izhei, gerv, kako, ljudi, mislete, nash, on, pokoj, rtsi, slovo, tverdo, uk + +No gaps between names allowed, order is important. + Do not lose wallet files and network config. Store it in an encrypted backed up storage. From 36eab4059c43af7f1d7f27b91cde85450a166dcb Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 26 Jun 2024 14:30:31 +0300 Subject: [PATCH 0659/1413] [#218] adm: Refactor `helper` in part of reading alphabet wallets Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/helper/util.go | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/util.go b/cmd/frostfs-adm/internal/modules/morph/helper/util.go index ba557a0332..ea8266b38a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/util.go @@ -40,45 +40,48 @@ func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, er return nil, fmt.Errorf("can't read alphabet wallets dir: %w", err) } - var size int -loop: - for i := 0; i < len(walletFiles); i++ { - name := innerring.GlagoliticLetter(i).String() + ".json" - for j := range walletFiles { - if walletFiles[j].Name() == name { - size++ - continue loop - } - } - break - } - if size == 0 { - return nil, errors.New("alphabet wallets dir is empty (run `generate-alphabet` command first)") - } - - wallets := make([]*wallet.Wallet, size) - for i := 0; i < size; i++ { - letter := innerring.GlagoliticLetter(i).String() + var wallets []*wallet.Wallet + var letter string + for i := 0; i < constants.MaxAlphabetNodes; i++ { + letter = innerring.GlagoliticLetter(i).String() p := filepath.Join(walletDir, letter+".json") - w, err := wallet.NewWalletFromFile(p) + var w *wallet.Wallet + w, err = wallet.NewWalletFromFile(p) if err != nil { - return nil, fmt.Errorf("can't open wallet: %w", err) + if errors.Is(err, os.ErrNotExist) { + err = nil + } else { + err = fmt.Errorf("can't open wallet: %w", err) + } + break } - password, err := config.GetPassword(v, letter) + var password string + password, err = config.GetPassword(v, letter) if err != nil { - return nil, fmt.Errorf("can't fetch password: %w", err) + err = fmt.Errorf("can't fetch password: %w", err) + break } for i := range w.Accounts { - if err := w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil { - return nil, fmt.Errorf("can't unlock wallet: %w", err) + if err = w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil { + err = fmt.Errorf("can't unlock wallet: %w", err) + break } } - wallets[i] = w + wallets = append(wallets, w) + } + if err != nil { + return nil, fmt.Errorf("can't read wallet for letter '%s': %w", letter, err) + } + if len(wallets) == 0 { + err = errors.New("there are no alphabet wallets in dir (run `generate-alphabet` command first)") + if len(walletFiles) > 0 { + err = fmt.Errorf("use glagolitic names for wallets(run `print-alphabet`): %w", err) + } + return nil, err } - return wallets, nil } From 56eeb630b6fbe67a26e043e6de8d523839327723 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 1 Jul 2024 18:58:37 +0300 Subject: [PATCH 0660/1413] [#1217] Fix grammar mistakes and misspelling Signed-off-by: Ekaterina Lebedeva --- .forgejo/workflows/pre-commit.yml | 2 +- .../internal/modules/morph/frostfsid/frostfsid.go | 2 +- cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go | 2 +- cmd/frostfs-adm/internal/modules/morph/policy/policy.go | 2 +- cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go | 2 +- cmd/frostfs-cli/modules/control/shards_list.go | 2 +- cmd/frostfs-cli/modules/tree/add.go | 2 +- cmd/frostfs-node/config/cast.go | 8 ++++---- internal/logs/logs.go | 6 +++--- .../blobstor/blobovniczatree/cache.go | 2 +- pkg/local_object_storage/metabase/graveyard.go | 2 +- pkg/local_object_storage/metabase/list.go | 2 +- 12 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.forgejo/workflows/pre-commit.yml b/.forgejo/workflows/pre-commit.yml index 6453b50291..117cda93bb 100644 --- a/.forgejo/workflows/pre-commit.yml +++ b/.forgejo/workflows/pre-commit.yml @@ -9,7 +9,7 @@ jobs: SKIP: make-lint,go-staticcheck-repo-mod,go-unit-tests,gofumpt runs-on: ubuntu-22.04 # If we use actions/setup-python from either Github or Gitea, - # the line above fails with a cryptic error about not being able to found python. + # the line above fails with a cryptic error about not being able to find python. # So install everything manually. steps: - uses: actions/checkout@v3 diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 541282967b..6b274ddfb5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -426,7 +426,7 @@ type frostfsidClient struct { func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { - return nil, fmt.Errorf("can't to initialize context: %w", err) + return nil, fmt.Errorf("can't initialize context: %w", err) } r := management.NewReader(wCtx.ReadOnlyInvoker) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index 4fd671f2a2..e60dc5673b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -15,7 +15,7 @@ import ( func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { - return fmt.Errorf("can't to initialize context: %w", err) + return fmt.Errorf("can't initialize context: %w", err) } r := management.NewReader(wCtx.ReadOnlyInvoker) diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go index 5ab05e4295..36547e22c0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go @@ -30,7 +30,7 @@ var errInvalidParameterFormat = errors.New("invalid parameter format, must be Pa func SetPolicyCmd(cmd *cobra.Command, args []string) error { wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { - return fmt.Errorf("can't to initialize context: %w", err) + return fmt.Errorf("can't initialize context: %w", err) } bw := io.NewBufBinWriter() diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go index 7e173ac49a..ba48465f7e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go @@ -39,7 +39,7 @@ func removeProxyAccount(cmd *cobra.Command, _ []string) { func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error { wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { - return fmt.Errorf("can't to initialize context: %w", err) + return fmt.Errorf("can't initialize context: %w", err) } r := management.NewReader(wCtx.ReadOnlyInvoker) diff --git a/cmd/frostfs-cli/modules/control/shards_list.go b/cmd/frostfs-cli/modules/control/shards_list.go index 3eb74ec82a..07c5bcd9ad 100644 --- a/cmd/frostfs-cli/modules/control/shards_list.go +++ b/cmd/frostfs-cli/modules/control/shards_list.go @@ -80,7 +80,7 @@ func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) { enc.SetIndent("", " ") commonCmd.ExitOnErr(cmd, "cannot shard info to JSON: %w", enc.Encode(out)) - cmd.Print(buf.String()) // pretty printer emits newline, to no need for Println + cmd.Print(buf.String()) // pretty printer emits newline, so no need for Println } func prettyPrintShards(cmd *cobra.Command, ii []*control.ShardInfo) { diff --git a/cmd/frostfs-cli/modules/tree/add.go b/cmd/frostfs-cli/modules/tree/add.go index 8ceea4173d..068b1d185d 100644 --- a/cmd/frostfs-cli/modules/tree/add.go +++ b/cmd/frostfs-cli/modules/tree/add.go @@ -72,7 +72,7 @@ func add(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "signing message: %w", tree.SignMessage(req, pk)) resp, err := cli.Add(ctx, req) - commonCmd.ExitOnErr(cmd, "failed to cal add: %w", err) + commonCmd.ExitOnErr(cmd, "failed to call add: %w", err) cmd.Println("Node ID: ", resp.GetBody().GetNodeId()) } diff --git a/cmd/frostfs-node/config/cast.go b/cmd/frostfs-node/config/cast.go index c99d335692..beec09a9e9 100644 --- a/cmd/frostfs-node/config/cast.go +++ b/cmd/frostfs-node/config/cast.go @@ -16,7 +16,7 @@ func panicOnErr(err error) { } // StringSlice reads a configuration value -// from c by name and casts it to a []string. +// from c by name and casts it to []string. // // Panics if the value can not be casted. func StringSlice(c *Config, name string) []string { @@ -27,7 +27,7 @@ func StringSlice(c *Config, name string) []string { } // StringSliceSafe reads a configuration value -// from c by name and casts it to a []string. +// from c by name and casts it to []string. // // Returns nil if the value can not be casted. func StringSliceSafe(c *Config, name string) []string { @@ -35,7 +35,7 @@ func StringSliceSafe(c *Config, name string) []string { } // String reads a configuration value -// from c by name and casts it to a string. +// from c by name and casts it to string. // // Panics if the value can not be casted. func String(c *Config, name string) string { @@ -46,7 +46,7 @@ func String(c *Config, name string) string { } // StringSafe reads a configuration value -// from c by name and casts it to a string. +// from c by name and casts it to string. // // Returns "" if the value can not be casted. func StringSafe(c *Config, name string) string { diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 78f00c4ee1..c5e4a8e286 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -402,9 +402,9 @@ const ( FrostFSNodeInternalApplicationError = "internal application error" FrostFSNodeInternalErrorProcessingIsComplete = "internal error processing is complete" FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration = "SIGHUP has been received, rereading configuration..." - FrostFSNodeSIGHUPSkip = "node not ready for reconfiguration, skipped SIGHUP" - FrostFSNodeShutdownSkip = "node already is going to shutting down, skipped shutdown" - FrostFSNodeShutdownWhenNotReady = "node is going to shutting down when subsystems still initializing" + FrostFSNodeSIGHUPSkip = "node is not ready for reconfiguration, skipped SIGHUP" + FrostFSNodeShutdownSkip = "node is already shutting down, skipped shutdown" + FrostFSNodeShutdownWhenNotReady = "node is going to shut down when subsystems are still initializing" FrostFSNodeConfigurationReading = "configuration reading" FrostFSNodeLoggerConfigurationPreparation = "logger configuration preparation" FrostFSNodeTracingConfigationUpdated = "tracing configation updated" diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index 4fce3e81ac..5c103c1bb3 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -12,7 +12,7 @@ import ( // dbCache caches sharedDB instances that are NOT open for Put. // // Uses dbManager for opening/closing sharedDB instances. -// Stores a reference to an cached sharedDB, so dbManager does not close it. +// Stores a reference to a cached sharedDB, so dbManager does not close it. type dbCache struct { cacheGuard *sync.Mutex cache cache.Cache[string, *sharedDB] diff --git a/pkg/local_object_storage/metabase/graveyard.go b/pkg/local_object_storage/metabase/graveyard.go index df9a3d3028..80d40fb780 100644 --- a/pkg/local_object_storage/metabase/graveyard.go +++ b/pkg/local_object_storage/metabase/graveyard.go @@ -128,7 +128,7 @@ func (g *GraveyardIterationPrm) SetHandler(h TombstonedHandler) { // Note: if offset is not found in db, iteration starts // from the element that WOULD BE the following after the // offset if offset was presented. That means that it is -// safe to delete offset element and pass if to the +// safe to delete offset element and pass it to the // iteration once again: iteration would start from the // next element. // diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 544b2e6666..b4326a92c7 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -66,7 +66,7 @@ func (l ListRes) Cursor() *Cursor { // Use cursor value from response for consecutive requests. // // Returns ErrEndOfListing if there are no more objects to return or count -// parameter set to zero. +// parameter is set to zero. func (db *DB) ListWithCursor(ctx context.Context, prm ListPrm) (res ListRes, err error) { var ( startedAt = time.Now() From 259007540fc8ca0899a3cd4598f9e2e33a442e01 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 2 Jul 2024 15:11:35 +0300 Subject: [PATCH 0661/1413] [#1196] morph/client: Remove duplicate utility functions We used several utility functions to parse frostfsid client subject and extended subject. However, following the changes in TrueCloudLab/frostfs-contract#97, these utility functions have become public. So there is no more need to have them here. Signed-off-by: Ekaterina Lebedeva --- go.mod | 2 +- go.sum | 4 +- pkg/morph/client/frostfsid/subject.go | 202 +------------------------- 3 files changed, 5 insertions(+), 203 deletions(-) diff --git a/go.mod b/go.mod index 38e66a20fa..d4eb52f4d6 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de diff --git a/go.sum b/go.sum index 0849b74a11..84fdbd47a3 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 h1:H5GvrVlowIMWfzqQkhY0p0myooJxQ1sMRVSFfXawwWg= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 h1:Tp4I+XOLp3VCJORfxSamQtj3RZNISbaLM4WD5iIzXxg= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index 169be6bc54..50733d89af 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -1,16 +1,11 @@ package frostfsid import ( - "errors" "fmt" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) const ( @@ -28,7 +23,7 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) } - subj, err := parseSubject(res) + subj, err := frostfsidclient.ParseSubject(res) if err != nil { return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) } @@ -46,203 +41,10 @@ func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.Subject return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) } - subj, err := parseSubjectExtended(res) + subj, err := frostfsidclient.ParseSubjectExtended(res) if err != nil { return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) } return subj, nil } - -func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) { - if ln := len(res); ln != 1 { - return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) - } - - structArr, err := client.ArrayFromStackItem(res[0]) - if err != nil { - return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) - } - - var subj frostfsidclient.Subject - - subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) - if err != nil { - return nil, err - } - - if !structArr[1].Equals(stackitem.Null{}) { - subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) - if err != nil { - return nil, err - } - } - - if !structArr[2].Equals(stackitem.Null{}) { - subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) - if err != nil { - return nil, err - } - } - - if !structArr[3].Equals(stackitem.Null{}) { - subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) - if err != nil { - return nil, err - } - } - - subj.KV, err = parseMap(structArr[4]) - if err != nil { - return nil, err - } - - return &subj, nil -} - -func parseSubjectExtended(res []stackitem.Item) (*frostfsidclient.SubjectExtended, error) { - if ln := len(res); ln != 1 { - return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) - } - - structArr, err := client.ArrayFromStackItem(res[0]) - if err != nil { - return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) - } - - var subj frostfsidclient.SubjectExtended - - subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) - if err != nil { - return nil, err - } - - if !structArr[1].Equals(stackitem.Null{}) { - subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) - if err != nil { - return nil, err - } - } - - if !structArr[2].Equals(stackitem.Null{}) { - subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) - if err != nil { - return nil, err - } - } - - if !structArr[3].Equals(stackitem.Null{}) { - subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) - if err != nil { - return nil, err - } - } - - subj.KV, err = parseMap(structArr[4]) - if err != nil { - return nil, err - } - - if !structArr[5].Equals(stackitem.Null{}) { - groupItems, ok := structArr[5].Value().([]stackitem.Item) - if !ok { - return nil, errors.New("invalid groups field") - } - - subj.Groups, err = parseGroups(groupItems) - if err != nil { - return nil, err - } - } - - return &subj, nil -} - -func makeValidRes(item stackitem.Item) (*result.Invoke, error) { - return &result.Invoke{ - Stack: []stackitem.Item{item}, - State: vmstate.Halt.String(), - }, nil -} - -func parseMap(item stackitem.Item) (map[string]string, error) { - if item.Equals(stackitem.Null{}) { - return nil, nil - } - - metaMap, err := unwrap.Map(makeValidRes(item)) - if err != nil { - return nil, err - } - - meta, ok := metaMap.Value().([]stackitem.MapElement) - if !ok { - return nil, errors.New("invalid map type") - } - - res := make(map[string]string, len(meta)) - for _, element := range meta { - key, err := element.Key.TryBytes() - if err != nil { - return nil, err - } - val, err := element.Value.TryBytes() - if err != nil { - return nil, err - } - res[string(key)] = string(val) - } - - return res, nil -} - -func parseGroups(items []stackitem.Item) ([]*frostfsidclient.Group, error) { - var err error - res := make([]*frostfsidclient.Group, len(items)) - - for i := 0; i < len(items); i++ { - arr, ok := items[i].Value().([]stackitem.Item) - if !ok { - return nil, errors.New("invalid group type") - } - res[i], err = parseGroup(arr) - if err != nil { - return nil, err - } - } - - return res, nil -} - -func parseGroup(structArr []stackitem.Item) (*frostfsidclient.Group, error) { - if len(structArr) < 4 { - return nil, errors.New("invalid response group struct") - } - - groupID, err := structArr[0].TryInteger() - if err != nil { - return nil, err - } - - name, err := structArr[1].TryBytes() - if err != nil { - return nil, err - } - - namespace, err := structArr[2].TryBytes() - if err != nil { - return nil, err - } - - kvs, err := parseMap(structArr[3]) - if err != nil { - return nil, err - } - - return &frostfsidclient.Group{ - ID: groupID.Int64(), - Name: string(name), - Namespace: string(namespace), - KV: kvs, - }, nil -} From 74842e7f4337154a0d047461b8b011c1ff7e4127 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 28 Jun 2024 16:35:18 +0300 Subject: [PATCH 0662/1413] [#1210] adm: Fix error handling when contract not found Signed-off-by: Alexander Chuprov --- .../internal/modules/morph/ape/ape_util.go | 4 ++-- .../internal/modules/morph/balance/balance.go | 2 +- .../internal/modules/morph/config/config.go | 4 ++-- .../modules/morph/container/container.go | 4 ++-- .../internal/modules/morph/contract/deploy.go | 2 +- .../modules/morph/contract/dump_hashes.go | 2 +- .../modules/morph/frostfsid/frostfsid.go | 2 +- .../internal/modules/morph/helper/contract.go | 4 ++-- .../internal/modules/morph/helper/netmap.go | 2 +- .../internal/modules/morph/helper/util.go | 17 +++++++++++++++++ .../modules/morph/initialize/initialize_nns.go | 2 +- .../internal/modules/morph/netmap/epoch.go | 2 +- .../modules/morph/netmap/netmap_candidates.go | 2 +- .../internal/modules/morph/nns/helper.go | 2 +- .../internal/modules/morph/node/remove.go | 2 +- .../internal/modules/morph/proxy/proxy.go | 2 +- 16 files changed, 36 insertions(+), 19 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index dfa7c63924..5e17f40142 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -115,7 +115,7 @@ func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorag inv := invoker.New(c, nil) var ch util.Uint160 r := management.NewReader(inv) - nnsCs, err := r.GetContractByID(1) + nnsCs, err := helper.GetContractByID(r, 1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) @@ -138,7 +138,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *he var ch util.Uint160 r := management.NewReader(ac.Invoker) - nnsCs, err := r.GetContractByID(1) + nnsCs, err := helper.GetContractByID(r, 1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) ch, err = helper.NNSResolveHash(ac.Invoker, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) diff --git a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go index 428fb98b9c..5519705d46 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go @@ -60,7 +60,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { if dumpStorage || dumpAlphabet || dumpProxy { r := management.NewReader(inv) - nnsCs, err = r.GetContractByID(1) + nnsCs, err = helper.GetContractByID(r, 1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index ba6e515c16..3a7f84acb9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -34,7 +34,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { inv := invoker.New(c, nil) r := management.NewReader(inv) - cs, err := r.GetContractByID(1) + cs, err := helper.GetContractByID(r, 1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } @@ -93,7 +93,7 @@ func SetConfigCmd(cmd *cobra.Command, args []string) error { } r := management.NewReader(wCtx.ReadOnlyInvoker) - cs, err := r.GetContractByID(1) + cs, err := helper.GetContractByID(r, 1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index eda388d37c..a664389753 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -34,7 +34,7 @@ func getContainerContractHash(cmd *cobra.Command, inv *invoker.Invoker) (util.Ui } if err != nil { r := management.NewReader(inv) - nnsCs, err := r.GetContractByID(1) + nnsCs, err := helper.GetContractByID(r, 1) if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } @@ -304,7 +304,7 @@ func parseContainers(filename string) ([]Container, error) { func fetchContainerContractHash(wCtx *helper.InitializeContext) (util.Uint160, error) { r := management.NewReader(wCtx.ReadOnlyInvoker) - nnsCs, err := r.GetContractByID(1) + nnsCs, err := helper.GetContractByID(r, 1) if err != nil { return util.Uint160{}, fmt.Errorf("can't get NNS contract state: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go index 7a8f34a5d6..5adb480da9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go @@ -79,7 +79,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { } r := management.NewReader(c.ReadOnlyInvoker) - nnsCs, err := r.GetContractByID(1) + nnsCs, err := helper.GetContractByID(r, 1) if err != nil { return fmt.Errorf("can't fetch NNS contract state: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index 11cc3bd048..5a0d295502 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -42,7 +42,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { } r := management.NewReader(invoker.New(c, nil)) - cs, err := r.GetContractByID(1) + cs, err := helper.GetContractByID(r, 1) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 6b274ddfb5..442920912e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -430,7 +430,7 @@ func newFrostfsIDClient(cmd *cobra.Command) (*frostfsidClient, error) { } r := management.NewReader(wCtx.ReadOnlyInvoker) - cs, err := r.GetContractByID(1) + cs, err := helper.GetContractByID(r, 1) if err != nil { return nil, fmt.Errorf("can't get NNS contract info: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/contract.go b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go index 7326ec1f53..2011301d17 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/contract.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go @@ -15,7 +15,7 @@ import ( func getFrostfsIDAdminFromContract(roInvoker *invoker.Invoker) (util.Uint160, bool, error) { r := management.NewReader(roInvoker) - cs, err := r.GetContractByID(1) + cs, err := GetContractByID(r, 1) if err != nil { return util.Uint160{}, false, fmt.Errorf("get nns contract: %w", err) } @@ -62,7 +62,7 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any // In case if NNS is updated multiple times, we can't calculate // it's actual hash based on local data, thus query chain. r := management.NewReader(c.ReadOnlyInvoker) - nnsCs, err := r.GetContractByID(1) + nnsCs, err := GetContractByID(r, 1) if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go index 9ea27d3a37..7a778f8c33 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go @@ -89,7 +89,7 @@ func EmitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util. func GetNetConfigFromNetmapContract(roInvoker *invoker.Invoker) ([]stackitem.Item, error) { r := management.NewReader(roInvoker) - cs, err := r.GetContractByID(1) + cs, err := GetContractByID(r, 1) if err != nil { return nil, fmt.Errorf("get nns contract: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/util.go b/cmd/frostfs-adm/internal/modules/morph/helper/util.go index ea8266b38a..2d9281c245 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/util.go @@ -14,10 +14,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" + "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/viper" ) @@ -181,3 +183,18 @@ func ParseGASAmount(s string) (fixedn.Fixed8, error) { } return gasAmount, nil } + +// GetContractByID retrieves a contract by its ID using the standard GetContractByID method. +// However, if the returned state.Contract is nil, it returns an error indicating that the contract was not found. +// See https://git.frostfs.info/TrueCloudLab/frostfs-node/issues/1210 +func GetContractByID(r *management.ContractReader, id int32) (*state.Contract, error) { + cs, err := r.GetContractByID(id) + if err != nil { + return nil, err + } + + if cs == nil { + return nil, errors.New("contract not found") + } + return cs, nil +} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go index 14f12cf8ee..e127ca5453 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go @@ -21,7 +21,7 @@ import ( func setNNS(c *helper.InitializeContext) error { r := management.NewReader(c.ReadOnlyInvoker) - nnsCs, err := r.GetContractByID(1) + nnsCs, err := helper.GetContractByID(r, 1) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index e60dc5673b..df9a03fd1a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -19,7 +19,7 @@ func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { } r := management.NewReader(wCtx.ReadOnlyInvoker) - cs, err := r.GetContractByID(1) + cs, err := helper.GetContractByID(r, 1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go index e9404e910d..d8471bb9aa 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go @@ -19,7 +19,7 @@ func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { inv := invoker.New(c, nil) r := management.NewReader(inv) - cs, err := r.GetContractByID(1) + cs, err := helper.GetContractByID(r, 1) commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) nmHash, err := helper.NNSResolveHash(inv, cs.Hash, helper.DomainOf(constants.NetmapContract)) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index 36c3dd2fd7..0eaa5ac58e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -19,7 +19,7 @@ func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, uti commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) r := management.NewReader(ac.Invoker) - nnsCs, err := r.GetContractByID(1) + nnsCs, err := helper.GetContractByID(r, 1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) return client.New(ac, nnsCs.Hash), ac, nnsCs.Hash } diff --git a/cmd/frostfs-adm/internal/modules/morph/node/remove.go b/cmd/frostfs-adm/internal/modules/morph/node/remove.go index 0d14bc6463..0a19102ba5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/node/remove.go +++ b/cmd/frostfs-adm/internal/modules/morph/node/remove.go @@ -37,7 +37,7 @@ func RemoveNodesCmd(cmd *cobra.Command, args []string) error { defer wCtx.Close() r := management.NewReader(wCtx.ReadOnlyInvoker) - cs, err := r.GetContractByID(1) + cs, err := helper.GetContractByID(r, 1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go index ba48465f7e..cb575b657b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go @@ -43,7 +43,7 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error } r := management.NewReader(wCtx.ReadOnlyInvoker) - cs, err := r.GetContractByID(1) + cs, err := helper.GetContractByID(r, 1) if err != nil { return fmt.Errorf("can't get NNS contract info: %w", err) } From 91bed3b0ba596a70f7365385ddc1dabf0a7bb9b4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 2 Jul 2024 14:09:03 +0300 Subject: [PATCH 0663/1413] [#1219] Remove Container.SetEACL method Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/container.go | 14 --- internal/logs/logs.go | 2 + .../processors/container/handlers.go | 19 +--- .../processors/container/handlers_test.go | 87 ----------------- .../processors/container/process_eacl.go | 82 ---------------- pkg/morph/client/container/eacl_set.go | 93 ------------------- pkg/services/container/morph/executor.go | 38 +------- pkg/services/container/morph/executor_test.go | 11 --- 8 files changed, 8 insertions(+), 338 deletions(-) delete mode 100644 pkg/innerring/processors/container/process_eacl.go delete mode 100644 pkg/morph/client/container/eacl_set.go diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index b14e19161d..99831fe982 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -254,17 +254,3 @@ func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error) func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error { return cntClient.Delete(m.neoClient, witness) } - -func (m morphContainerWriter) PutEACL(eaclInfo containerCore.EACL) error { - err := cntClient.PutEACL(m.neoClient, eaclInfo) - if err != nil { - return err - } - - if m.cacheEnabled { - id, _ := eaclInfo.Value.CID() - m.eacls.InvalidateEACL(id) - } - - return nil -} diff --git a/internal/logs/logs.go b/internal/logs/logs.go index c5e4a8e286..2addc44827 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -14,6 +14,8 @@ const ( InterruptPlacementIterationByContext = "interrupt placement iteration by context" Notification = "notification" + + SkipDeprecatedNotification = "skip deprecated notification" ) const ( diff --git a/pkg/innerring/processors/container/handlers.go b/pkg/innerring/processors/container/handlers.go index 3ec10b889b..8bb89abe2d 100644 --- a/pkg/innerring/processors/container/handlers.go +++ b/pkg/innerring/processors/container/handlers.go @@ -49,21 +49,6 @@ func (cp *Processor) handleDelete(ev event.Event) { } } -func (cp *Processor) handleSetEACL(ev event.Event) { - e := ev.(containerEvent.SetEACL) - - cp.log.Info(logs.Notification, - zap.String("type", "set EACL"), - ) - - // send an event to the worker pool - - err := processors.SubmitEvent(cp.pool, cp.metrics, "container_set_eacl", func() bool { - return cp.processSetEACL(e) - }) - if err != nil { - // there system can be moved into controlled degradation stage - cp.log.Warn(logs.ContainerContainerProcessorWorkerPoolDrained, - zap.Int("capacity", cp.pool.Cap())) - } +func (cp *Processor) handleSetEACL(_ event.Event) { + cp.log.Warn(logs.SkipDeprecatedNotification, zap.String("type", "set EACL")) } diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index a69d0e4c42..1aac31ae3b 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -18,10 +18,8 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/network/payload" @@ -159,91 +157,6 @@ func TestDeleteEvent(t *testing.T) { require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests") } -func TestSetEACLEvent(t *testing.T) { - t.Parallel() - nst := &testNetworkState{ - homHashDisabled: true, - epoch: 100, - } - cc := &testContainerClient{ - get: make(map[string]*containercore.Container), - } - mc := &testMorphClient{} - - proc, err := New(&Params{ - Log: test.NewLogger(t), - PoolSize: 2, - AlphabetState: &testAlphabetState{isAlphabet: true}, - NetworkState: nst, - ContainerClient: cc, - MorphClient: mc, - FrostFSIDClient: &testFrostFSIDClient{}, - }) - require.NoError(t, err, "failed to create processor") - - p, err := keys.NewPrivateKey() - require.NoError(t, err) - - var usr user.ID - user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey())) - - var pp netmap.PlacementPolicy - pp.AddReplicas(netmap.ReplicaDescriptor{}) - - var cnr containerSDK.Container - cnr.Init() - cnr.SetOwner(usr) - cnr.SetPlacementPolicy(pp) - cnr.SetBasicACL(acl.PrivateExtended) - containerSDK.DisableHomomorphicHashing(&cnr) - - var cid cid.ID - containerSDK.CalculateID(&cid, cnr) - cidBytes := make([]byte, 32) - cid.Encode(cidBytes) - - var signature frostfscrypto.Signature - signer := frostfsecdsa.Signer(p.PrivateKey) - require.NoError(t, signature.Calculate(signer, cidBytes), "failed to calculate signature") - - cc.get[hex.EncodeToString(cidBytes)] = &containercore.Container{ - Value: cnr, - Signature: signature, - } - - table := eacl.NewTable() - table.SetCID(cid) - table.SetVersion(version.Current()) - - r := &eacl.Record{} - r.AddObjectContainerIDFilter(eacl.MatchStringEqual, cid) - - table.AddRecord(r) - - nr := &payload.P2PNotaryRequest{ - MainTransaction: &transaction.Transaction{}, - } - event := containerEvent.SetEACL{ - TableValue: table.ToV2().StableMarshal(nil), - PublicKeyValue: p.PublicKey().Bytes(), - SignatureValue: p.Sign(table.ToV2().StableMarshal(nil)), - NotaryRequestValue: nr, - } - - proc.handleSetEACL(event) - - for proc.pool.Running() > 0 { - time.Sleep(10 * time.Millisecond) - } - - var expectedPutEACL cntClient.PutEACLPrm - expectedPutEACL.SetTable(table.ToV2().StableMarshal(nil)) - expectedPutEACL.SetKey(p.PublicKey().Bytes()) - expectedPutEACL.SetSignature(p.Sign(table.ToV2().StableMarshal(nil))) - - require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests") -} - type testAlphabetState struct { isAlphabet bool } diff --git a/pkg/innerring/processors/container/process_eacl.go b/pkg/innerring/processors/container/process_eacl.go deleted file mode 100644 index 8ab0d5c396..0000000000 --- a/pkg/innerring/processors/container/process_eacl.go +++ /dev/null @@ -1,82 +0,0 @@ -package container - -import ( - "errors" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" - containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "go.uber.org/zap" -) - -func (cp *Processor) processSetEACL(e containerEvent.SetEACL) bool { - if !cp.alphabetState.IsAlphabet() { - cp.log.Info(logs.ContainerNonAlphabetModeIgnoreSetEACL) - return true - } - - err := cp.checkSetEACL(e) - if err != nil { - cp.log.Error(logs.ContainerSetEACLCheckFailed, - zap.String("error", err.Error()), - ) - - return false - } - - if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil { - cp.log.Error(logs.ContainerCouldNotApproveSetEACL, - zap.String("error", err.Error()), - ) - return false - } - - return true -} - -func (cp *Processor) checkSetEACL(e containerEvent.SetEACL) error { - binTable := e.Table() - - // unmarshal table - table := eacl.NewTable() - - err := table.Unmarshal(binTable) - if err != nil { - return fmt.Errorf("invalid binary table: %w", err) - } - - idCnr, ok := table.CID() - if !ok { - return errors.New("missing container ID in eACL table") - } - - // receive owner of the related container - cnr, err := cntClient.Get(cp.cnrClient, idCnr) - if err != nil { - return fmt.Errorf("could not receive the container: %w", err) - } - - // ACL extensions can be disabled by basic ACL, check it - if !cnr.Value.BasicACL().Extendable() { - return errors.New("ACL extension disabled by container basic ACL") - } - - err = cp.verifySignature(signatureVerificationData{ - ownerContainer: cnr.Value.Owner(), - verb: session.VerbContainerSetEACL, - idContainerSet: true, - idContainer: idCnr, - binTokenSession: e.SessionToken(), - binPublicKey: e.PublicKey(), - signature: e.Signature(), - signedData: binTable, - }) - if err != nil { - return fmt.Errorf("auth eACL table setting: %w", err) - } - - return nil -} diff --git a/pkg/morph/client/container/eacl_set.go b/pkg/morph/client/container/eacl_set.go deleted file mode 100644 index c68104593a..0000000000 --- a/pkg/morph/client/container/eacl_set.go +++ /dev/null @@ -1,93 +0,0 @@ -package container - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" -) - -// PutEACL marshals table, and passes it to Wrapper's PutEACLBinary method -// along with sig.Key() and sig.Sign(). -// -// Returns error if table is nil. -// -// If TryNotary is provided, calls notary contract. -func PutEACL(c *Client, eaclInfo containercore.EACL) error { - if eaclInfo.Value == nil { - return errNilArgument - } - - data, err := eaclInfo.Value.Marshal() - if err != nil { - return fmt.Errorf("can't marshal eacl table: %w", err) - } - - var prm PutEACLPrm - prm.SetTable(data) - - if eaclInfo.Session != nil { - prm.SetToken(eaclInfo.Session.Marshal()) - } - - // TODO(@cthulhu-rider): #468 implement and use another approach to avoid conversion - var sigV2 refs.Signature - eaclInfo.Signature.WriteToV2(&sigV2) - - prm.SetKey(sigV2.GetKey()) - prm.SetSignature(sigV2.GetSign()) - - return c.PutEACL(prm) -} - -// PutEACLPrm groups parameters of PutEACL operation. -type PutEACLPrm struct { - table []byte - key []byte - sig []byte - token []byte - - client.InvokePrmOptional -} - -// SetTable sets table. -func (p *PutEACLPrm) SetTable(table []byte) { - p.table = table -} - -// SetKey sets key. -func (p *PutEACLPrm) SetKey(key []byte) { - p.key = key -} - -// SetSignature sets signature. -func (p *PutEACLPrm) SetSignature(sig []byte) { - p.sig = sig -} - -// SetToken sets session token. -func (p *PutEACLPrm) SetToken(token []byte) { - p.token = token -} - -// PutEACL saves binary eACL table with its session token, key and signature -// in FrostFS system through Container contract call. -// -// Returns any error encountered that caused the saving to interrupt. -func (c *Client) PutEACL(p PutEACLPrm) error { - if len(p.sig) == 0 || len(p.key) == 0 { - return errNilArgument - } - - prm := client.InvokePrm{} - prm.SetMethod(setEACLMethod) - prm.SetArgs(p.table, p.sig, p.key, p.token) - prm.InvokePrmOptional = p.InvokePrmOptional - - _, err := c.client.Invoke(prm) - if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", setEACLMethod, err) - } - return nil -} diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index a653fa0660..e2e79f3d2d 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -11,9 +11,10 @@ import ( containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) var errMissingUserID = errors.New("missing user ID") @@ -40,8 +41,6 @@ type Writer interface { Put(containercore.Container) (*cid.ID, error) // Delete removes specified container from the side chain. Delete(containercore.RemovalWitness) error - // PutEACL updates extended ACL table of specified container in the side chain. - PutEACL(containercore.EACL) error } func NewExecutor(rdr Reader, wrt Writer) containerSvc.ServiceExecutor { @@ -205,37 +204,8 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) return res, nil } -func (s *morphExecutor) SetExtendedACL(_ context.Context, tokV2 *sessionV2.Token, body *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) { - sigV2 := body.GetSignature() - if sigV2 == nil { - // TODO(@cthulhu-rider): #468 use "const" error - return nil, errors.New("missing signature") - } - - eaclInfo := containercore.EACL{ - Value: eaclSDK.NewTableFromV2(body.GetEACL()), - } - - err := eaclInfo.Signature.ReadFromV2(*sigV2) - if err != nil { - return nil, fmt.Errorf("can't read signature: %w", err) - } - - if tokV2 != nil { - eaclInfo.Session = new(session.Container) - - err := eaclInfo.Session.ReadFromV2(*tokV2) - if err != nil { - return nil, fmt.Errorf("invalid session token: %w", err) - } - } - - err = s.wrt.PutEACL(eaclInfo) - if err != nil { - return nil, err - } - - return new(container.SetExtendedACLResponseBody), nil +func (s *morphExecutor) SetExtendedACL(_ context.Context, _ *sessionV2.Token, _ *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetExtendedACL not implemented") } func (s *morphExecutor) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) { diff --git a/pkg/services/container/morph/executor_test.go b/pkg/services/container/morph/executor_test.go index 42dd0b77ee..560c69232b 100644 --- a/pkg/services/container/morph/executor_test.go +++ b/pkg/services/container/morph/executor_test.go @@ -96,17 +96,6 @@ func TestInvalidToken(t *testing.T) { return }, }, - { - name: "setEACL", - op: func(e containerSvc.ServiceExecutor, tokV2 *session.Token) (err error) { - var reqBody container.SetExtendedACLRequestBody - reqBody.SetSignature(new(refs.Signature)) - sign(&reqBody) - - _, err = e.SetExtendedACL(context.TODO(), tokV2, &reqBody) - return - }, - }, } for _, test := range tests { From a378ff9cf6c5ded5edc32891d586729a9fdbf05b Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 2 Jul 2024 13:02:26 +0300 Subject: [PATCH 0664/1413] [#1218] object: Pass container owner for backward get method check * `getStreamBasicChecker` must define `containerOwner` for backward checks, otherwise bearer token cannot be validated for the token issuer. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/service.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 609b117d04..853c3b80d8 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -164,6 +164,7 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt apeChecker: c.apeChecker, namespace: reqCtx.Namespace, senderKey: reqCtx.SenderKey, + containerOwner: reqCtx.ContainerOwner, role: nativeSchemaRole(reqCtx.Role), softAPECheck: reqCtx.SoftAPECheck, bearerToken: reqCtx.BearerToken, From f3a861806e135eff2b317cffa7105a6769f55b3e Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 2 Jul 2024 13:08:59 +0300 Subject: [PATCH 0665/1413] [#1218] object: Fix bearer token validation Signed-off-by: Airat Arifullin --- pkg/services/object/ape/checker.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index ee12d7b973..7541ad1163 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -97,22 +97,23 @@ func isValidBearer(token *bearer.Token, ownerCnr user.ID, containerID cid.ID, pu return nil } - // 1. First check token lifetime. Simplest verification. + // First check token lifetime. Simplest verification. if token.InvalidAt(st.CurrentEpoch()) { return errBearerExpired } - // 2. Then check if bearer token is signed correctly. + // Then check if bearer token is signed correctly. if !token.VerifySignature() { return errBearerInvalidSignature } - // 3. Then check if container is either empty or equal to the container in the request. + // Check for ape overrides defined in the bearer token. apeOverride := token.APEOverride() - if apeOverride.Target.TargetType != ape.TargetTypeContainer { - return errInvalidTargetType + if len(apeOverride.Chains) > 0 && apeOverride.Target.TargetType != ape.TargetTypeContainer { + return fmt.Errorf("%w: %s", errInvalidTargetType, apeOverride.Target.TargetType.ToV2().String()) } + // Then check if container is either empty or equal to the container in the request. var targetCnr cid.ID err := targetCnr.DecodeString(apeOverride.Target.Name) if err != nil { @@ -122,12 +123,12 @@ func isValidBearer(token *bearer.Token, ownerCnr user.ID, containerID cid.ID, pu return errBearerInvalidContainerID } - // 4. Then check if container owner signed this token. + // Then check if container owner signed this token. if !bearer.ResolveIssuer(*token).Equals(ownerCnr) { return errBearerNotSignedByOwner } - // 5. Then check if request sender has rights to use this token. + // Then check if request sender has rights to use this token. var usrSender user.ID user.IDFromKey(&usrSender, (ecdsa.PublicKey)(*publicKey)) From 4bd466779112cb7bf215d1ae5bfbe2daf9502eef Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 2 Jul 2024 13:10:32 +0300 Subject: [PATCH 0666/1413] [#1218] tree: Fix bearer token validation Signed-off-by: Airat Arifullin --- pkg/services/tree/ape.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 116adf5dbd..a6202d1a3f 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -85,22 +85,23 @@ func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKe return nil } - // 1. First check token lifetime. Simplest verification. + // First check token lifetime. Simplest verification. if token.InvalidAt(st.CurrentEpoch()) { return errBearerExpired } - // 2. Then check if bearer token is signed correctly. + // Then check if bearer token is signed correctly. if !token.VerifySignature() { return errBearerInvalidSignature } - // 3. Then check if container is either empty or equal to the container in the request. + // Check for ape overrides defined in the bearer token. apeOverride := token.APEOverride() - if apeOverride.Target.TargetType != ape.TargetTypeContainer { - return errInvalidTargetType + if len(apeOverride.Chains) > 0 && apeOverride.Target.TargetType != ape.TargetTypeContainer { + return fmt.Errorf("%w: %s", errInvalidTargetType, apeOverride.Target.TargetType.ToV2().String()) } + // Then check if container is either empty or equal to the container in the request. var targetCnr cid.ID err := targetCnr.DecodeString(apeOverride.Target.Name) if err != nil { @@ -110,12 +111,12 @@ func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKe return errBearerInvalidContainerID } - // 4. Then check if container owner signed this token. + // Then check if container owner signed this token. if !bearer.ResolveIssuer(*token).Equals(ownerCnr) { return errBearerNotSignedByOwner } - // 5. Then check if request sender has rights to use this token. + // Then check if request sender has rights to use this token. var usrSender user.ID user.IDFromKey(&usrSender, (ecdsa.PublicKey)(*publicKey)) From 80d7459560e85a256081ba09b44aa690344482e3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 3 Jul 2024 15:31:39 +0300 Subject: [PATCH 0667/1413] Revert "[#1196] morph/client: Remove duplicate utility functions" This reverts commit 259007540fc8ca0899a3cd4598f9e2e33a442e01. Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 +- pkg/morph/client/frostfsid/subject.go | 202 +++++++++++++++++++++++++- 3 files changed, 203 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index d4eb52f4d6..38e66a20fa 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e + git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de diff --git a/go.sum b/go.sum index 84fdbd47a3..0849b74a11 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 h1:H5GvrVlowIMWfzqQkhY0p0myooJxQ1sMRVSFfXawwWg= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 h1:Tp4I+XOLp3VCJORfxSamQtj3RZNISbaLM4WD5iIzXxg= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index 50733d89af..169be6bc54 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -1,11 +1,16 @@ package frostfsid import ( + "errors" "fmt" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) const ( @@ -23,7 +28,7 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) } - subj, err := frostfsidclient.ParseSubject(res) + subj, err := parseSubject(res) if err != nil { return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) } @@ -41,10 +46,203 @@ func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.Subject return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) } - subj, err := frostfsidclient.ParseSubjectExtended(res) + subj, err := parseSubjectExtended(res) if err != nil { return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) } return subj, nil } + +func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) { + if ln := len(res); ln != 1 { + return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) + } + + structArr, err := client.ArrayFromStackItem(res[0]) + if err != nil { + return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) + } + + var subj frostfsidclient.Subject + + subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) + if err != nil { + return nil, err + } + + if !structArr[1].Equals(stackitem.Null{}) { + subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) + if err != nil { + return nil, err + } + } + + if !structArr[2].Equals(stackitem.Null{}) { + subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) + if err != nil { + return nil, err + } + } + + if !structArr[3].Equals(stackitem.Null{}) { + subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) + if err != nil { + return nil, err + } + } + + subj.KV, err = parseMap(structArr[4]) + if err != nil { + return nil, err + } + + return &subj, nil +} + +func parseSubjectExtended(res []stackitem.Item) (*frostfsidclient.SubjectExtended, error) { + if ln := len(res); ln != 1 { + return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) + } + + structArr, err := client.ArrayFromStackItem(res[0]) + if err != nil { + return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) + } + + var subj frostfsidclient.SubjectExtended + + subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) + if err != nil { + return nil, err + } + + if !structArr[1].Equals(stackitem.Null{}) { + subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) + if err != nil { + return nil, err + } + } + + if !structArr[2].Equals(stackitem.Null{}) { + subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) + if err != nil { + return nil, err + } + } + + if !structArr[3].Equals(stackitem.Null{}) { + subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) + if err != nil { + return nil, err + } + } + + subj.KV, err = parseMap(structArr[4]) + if err != nil { + return nil, err + } + + if !structArr[5].Equals(stackitem.Null{}) { + groupItems, ok := structArr[5].Value().([]stackitem.Item) + if !ok { + return nil, errors.New("invalid groups field") + } + + subj.Groups, err = parseGroups(groupItems) + if err != nil { + return nil, err + } + } + + return &subj, nil +} + +func makeValidRes(item stackitem.Item) (*result.Invoke, error) { + return &result.Invoke{ + Stack: []stackitem.Item{item}, + State: vmstate.Halt.String(), + }, nil +} + +func parseMap(item stackitem.Item) (map[string]string, error) { + if item.Equals(stackitem.Null{}) { + return nil, nil + } + + metaMap, err := unwrap.Map(makeValidRes(item)) + if err != nil { + return nil, err + } + + meta, ok := metaMap.Value().([]stackitem.MapElement) + if !ok { + return nil, errors.New("invalid map type") + } + + res := make(map[string]string, len(meta)) + for _, element := range meta { + key, err := element.Key.TryBytes() + if err != nil { + return nil, err + } + val, err := element.Value.TryBytes() + if err != nil { + return nil, err + } + res[string(key)] = string(val) + } + + return res, nil +} + +func parseGroups(items []stackitem.Item) ([]*frostfsidclient.Group, error) { + var err error + res := make([]*frostfsidclient.Group, len(items)) + + for i := 0; i < len(items); i++ { + arr, ok := items[i].Value().([]stackitem.Item) + if !ok { + return nil, errors.New("invalid group type") + } + res[i], err = parseGroup(arr) + if err != nil { + return nil, err + } + } + + return res, nil +} + +func parseGroup(structArr []stackitem.Item) (*frostfsidclient.Group, error) { + if len(structArr) < 4 { + return nil, errors.New("invalid response group struct") + } + + groupID, err := structArr[0].TryInteger() + if err != nil { + return nil, err + } + + name, err := structArr[1].TryBytes() + if err != nil { + return nil, err + } + + namespace, err := structArr[2].TryBytes() + if err != nil { + return nil, err + } + + kvs, err := parseMap(structArr[3]) + if err != nil { + return nil, err + } + + return &frostfsidclient.Group{ + ID: groupID.Int64(), + Name: string(name), + Namespace: string(namespace), + KV: kvs, + }, nil +} From bbe95dac8b37fd11eb474acfc60514c2f5b350aa Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 3 Jul 2024 17:14:47 +0300 Subject: [PATCH 0668/1413] [#1225] engine: Log the error when check object existence Signed-off-by: Anton Nikiforov --- internal/logs/logs.go | 1 + pkg/local_object_storage/engine/put.go | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 2addc44827..4f0b291243 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -205,6 +205,7 @@ const ( EngineCouldNotReloadAShard = "could not reload a shard" EngineAddedNewShard = "added new shard" EngineCouldNotPutObjectToShard = "could not put object to shard" + EngineCouldNotCheckObjectExistence = "could not check object existence when put object to shard" EngineErrorDuringSearchingForObjectChildren = "error during searching for object children" EngineCouldNotInhumeObjectInShard = "could not inhume object in shard" EngineStartingRemovalOfLocallyredundantCopies = "starting removal of locally-redundant copies" diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 2a78febed6..54385910be 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -149,6 +149,11 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti // object is already found but // expired => do nothing with it res.status = putToShardExists + } else { + e.log.Warn(logs.EngineCouldNotCheckObjectExistence, + zap.Stringer("shard_id", sh.ID()), + zap.String("error", err.Error()), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return // this is not ErrAlreadyRemoved error so we can go to the next shard From 2bac82cd6fd378b1958e1e9633b5ef98d2ff6553 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 3 Jul 2024 09:55:04 +0300 Subject: [PATCH 0669/1413] [#1222] engine: Fix object evacuation Do not fail evacuation if it unable to evacuate object to other node. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 14 +++++++++--- .../engine/evacuate_test.go | 22 +++++++++---------- pkg/services/control/server/evacuate.go | 14 +++++++----- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 87542eec17..0ce59a0bec 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -74,7 +74,7 @@ func (s EvacuateScope) TreesOnly() bool { // EvacuateShardPrm represents parameters for the EvacuateShard operation. type EvacuateShardPrm struct { ShardID []*shard.ID - ObjectsHandler func(context.Context, oid.Address, *objectSDK.Object) error + ObjectsHandler func(context.Context, oid.Address, *objectSDK.Object) (bool, error) TreeHandler func(context.Context, cid.ID, string, pilorama.Forest) (string, error) IgnoreErrors bool Async bool @@ -668,13 +668,21 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to return fmt.Errorf("%w: %s", errPutShard, toEvacuate[i]) } - err = prm.ObjectsHandler(ctx, addr, getRes.Object()) + moved, err := prm.ObjectsHandler(ctx, addr, getRes.Object()) if err != nil { e.log.Error(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } - res.objEvacuated.Add(1) + if moved { + res.objEvacuated.Add(1) + } else if prm.IgnoreErrors { + res.objFailed.Add(1) + e.log.Warn(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } else { + return fmt.Errorf("object %s was not replicated", addr) + } } return nil } diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index e8d9a449f5..f097665bf9 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -145,18 +145,18 @@ func TestEvacuateObjectsNetwork(t *testing.T) { errReplication := errors.New("handler error") - acceptOneOf := func(objects []*objectSDK.Object, max uint64) func(context.Context, oid.Address, *objectSDK.Object) error { + acceptOneOf := func(objects []*objectSDK.Object, max uint64) func(context.Context, oid.Address, *objectSDK.Object) (bool, error) { var n uint64 - return func(_ context.Context, addr oid.Address, obj *objectSDK.Object) error { + return func(_ context.Context, addr oid.Address, obj *objectSDK.Object) (bool, error) { if n == max { - return errReplication + return false, errReplication } n++ for i := range objects { if addr == objectCore.AddressOf(objects[i]) { require.Equal(t, objects[i], obj) - return nil + return true, nil } } require.FailNow(t, "handler was called with an unexpected object: %s", addr) @@ -268,13 +268,13 @@ func TestEvacuateCancellation(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] - prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) (bool, error) { select { case <-ctx.Done(): - return ctx.Err() + return false, ctx.Err() default: } - return nil + return true, nil } prm.Scope = EvacuateScopeObjects @@ -301,14 +301,14 @@ func TestEvacuateSingleProcess(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] prm.Scope = EvacuateScopeObjects - prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) (bool, error) { select { case <-running: default: close(running) } <-blocker - return nil + return true, nil } eg, egCtx := errgroup.WithContext(context.Background()) @@ -344,14 +344,14 @@ func TestEvacuateObjectsAsync(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids[1:2] prm.Scope = EvacuateScopeObjects - prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) error { + prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) (bool, error) { select { case <-running: default: close(running) } <-blocker - return nil + return true, nil } st, err := e.GetEvacuationState(context.Background()) diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 794bc199a7..dd609caec9 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -57,17 +57,21 @@ func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRe return resp, nil } -func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *objectSDK.Object) error { +func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *objectSDK.Object) (bool, error) { cid, ok := obj.ContainerID() if !ok { // Return nil to prevent situations where a shard can't be evacuated // because of a single bad/corrupted object. - return nil + return false, nil } nodes, err := s.getContainerNodes(cid) if err != nil { - return err + return false, err + } + + if len(nodes) == 0 { + return false, nil } var res replicatorResult @@ -80,9 +84,9 @@ func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *obj s.replicator.HandleReplicationTask(ctx, task, &res) if res.count == 0 { - return errors.New("object was not replicated") + return false, errors.New("object was not replicated") } - return nil + return true, nil } func (s *Server) replicateTree(ctx context.Context, contID cid.ID, treeID string, forest pilorama.Forest) (string, error) { From 3a797e46826e82575bb572192a35fe2afc439813 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 3 Jul 2024 11:47:50 +0300 Subject: [PATCH 0670/1413] [#1222] engine: Fix tree evacuation Do not fail if it is unable to evacuate tree to other node. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 32 +++++++++++++------ .../engine/evacuate_test.go | 4 +-- pkg/services/control/server/evacuate.go | 10 +++--- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 0ce59a0bec..04e427e490 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -75,7 +75,7 @@ func (s EvacuateScope) TreesOnly() bool { type EvacuateShardPrm struct { ShardID []*shard.ID ObjectsHandler func(context.Context, oid.Address, *objectSDK.Object) (bool, error) - TreeHandler func(context.Context, cid.ID, string, pilorama.Forest) (string, error) + TreeHandler func(context.Context, cid.ID, string, pilorama.Forest) (bool, string, error) IgnoreErrors bool Async bool Scope EvacuateScope @@ -450,7 +450,7 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree continue } - nodePK, err := e.evacuateTreeToOtherNode(ctx, sh, contTree, prm) + moved, nodePK, err := e.evacuateTreeToOtherNode(ctx, sh, contTree, prm) if err != nil { e.log.Error(logs.EngineShardsEvacuationFailedToMoveTree, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), @@ -458,18 +458,32 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } - e.log.Debug(logs.EngineShardsEvacuationTreeEvacuatedRemote, - zap.String("cid", contTree.CID.EncodeToString()), zap.String("treeID", contTree.TreeID), - zap.String("from_shardID", sh.ID().String()), zap.String("to_node", nodePK), - evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) - res.trEvacuated.Add(1) + if moved { + e.log.Debug(logs.EngineShardsEvacuationTreeEvacuatedRemote, + zap.String("cid", contTree.CID.EncodeToString()), zap.String("treeID", contTree.TreeID), + zap.String("from_shardID", sh.ID().String()), zap.String("to_node", nodePK), + evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + res.trEvacuated.Add(1) + } else if prm.IgnoreErrors { + res.trFailed.Add(1) + e.log.Warn(logs.EngineShardsEvacuationFailedToMoveTree, + zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), + zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } else { + e.log.Error(logs.EngineShardsEvacuationFailedToMoveTree, + zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), + zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + return fmt.Errorf("no remote nodes available to replicate tree '%s' of container %s", contTree.TreeID, contTree.CID) + } } return nil } -func (e *StorageEngine) evacuateTreeToOtherNode(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, prm EvacuateShardPrm) (string, error) { +func (e *StorageEngine) evacuateTreeToOtherNode(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, prm EvacuateShardPrm) (bool, string, error) { if prm.TreeHandler == nil { - return "", fmt.Errorf("failed to evacuate tree '%s' for container %s from shard %s: local evacuation failed, but no remote evacuation available", tree.TreeID, tree.CID, sh.ID()) + return false, "", fmt.Errorf("failed to evacuate tree '%s' for container %s from shard %s: local evacuation failed, but no remote evacuation available", tree.TreeID, tree.CID, sh.ID()) } return prm.TreeHandler(ctx, tree.CID, tree.TreeID, sh) diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index f097665bf9..55268b549b 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -507,7 +507,7 @@ func TestEvacuateTreesRemote(t *testing.T) { var prm EvacuateShardPrm prm.ShardID = ids prm.Scope = EvacuateScopeTrees - prm.TreeHandler = func(ctx context.Context, contID cid.ID, treeID string, f pilorama.Forest) (string, error) { + prm.TreeHandler = func(ctx context.Context, contID cid.ID, treeID string, f pilorama.Forest) (bool, string, error) { key := contID.String() + treeID var height uint64 for { @@ -515,7 +515,7 @@ func TestEvacuateTreesRemote(t *testing.T) { require.NoError(t, err) if op.Time == 0 { - return "", nil + return true, "", nil } evacuatedTreeOps[key] = append(evacuatedTreeOps[key], &op) height = op.Time + 1 diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index dd609caec9..0ba8be7655 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -89,22 +89,22 @@ func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *obj return true, nil } -func (s *Server) replicateTree(ctx context.Context, contID cid.ID, treeID string, forest pilorama.Forest) (string, error) { +func (s *Server) replicateTree(ctx context.Context, contID cid.ID, treeID string, forest pilorama.Forest) (bool, string, error) { nodes, err := s.getContainerNodes(contID) if err != nil { - return "", err + return false, "", err } if len(nodes) == 0 { - return "", fmt.Errorf("no remote nodes available to replicate tree '%s' of container %s", treeID, contID) + return false, "", nil } for _, node := range nodes { err = s.replicateTreeToNode(ctx, forest, contID, treeID, node) if err == nil { - return hex.EncodeToString(node.PublicKey()), nil + return true, hex.EncodeToString(node.PublicKey()), nil } } - return "", err + return false, "", err } func (s *Server) replicateTreeToNode(ctx context.Context, forest pilorama.Forest, contID cid.ID, treeID string, node netmap.NodeInfo) error { From 40c9ddb6bac36e31189ced1e97f178192180310b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 3 Jul 2024 16:45:30 +0300 Subject: [PATCH 0671/1413] [#1226] blobovniczatree: Drop init in advance option To make blobovniczatree unlimited. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 -- cmd/frostfs-node/config/engine/config_test.go | 1 - .../shard/blobstor/blobovnicza/config.go | 10 ----- config/example/node.env | 1 - config/example/node.json | 1 - config/example/node.yaml | 1 - docs/storage-node-configuration.md | 1 - .../blobstor/blobovniczatree/control.go | 25 ----------- .../blobstor/blobovniczatree/iterate_test.go | 44 ------------------- .../blobstor/blobovniczatree/option.go | 8 ---- 10 files changed, 95 deletions(-) delete mode 100644 pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 3aded7020a..b51073d4e4 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -191,7 +191,6 @@ type subStorageCfg struct { leafWidth uint64 openedCacheSize int initWorkerCount int - initInAdvance bool rebuildDropTimeout time.Duration openedCacheTTL time.Duration openedCacheExpInterval time.Duration @@ -319,7 +318,6 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol sCfg.openedCacheTTL = sub.OpenedCacheTTL() sCfg.openedCacheExpInterval = sub.OpenedCacheExpInterval() sCfg.initWorkerCount = sub.InitWorkerCount() - sCfg.initInAdvance = sub.InitInAdvance() sCfg.rebuildDropTimeout = sub.RebuildDropTimeout() case fstree.Type: sub := fstreeconfig.From((*config.Config)(storagesCfg[i])) @@ -911,7 +909,6 @@ func (c *cfg) getSubstorageOpts(ctx context.Context, shCfg shardCfg) []blobstor. blobovniczatree.WithOpenedCacheTTL(sRead.openedCacheTTL), blobovniczatree.WithOpenedCacheExpInterval(sRead.openedCacheExpInterval), blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), - blobovniczatree.WithInitInAdvance(sRead.initInAdvance), blobovniczatree.WithWaitBeforeDropDB(sRead.rebuildDropTimeout), blobovniczatree.WithLogger(c.log), blobovniczatree.WithObjectSizeLimit(shCfg.smallSizeObjectLimit), diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 3f9c7ec71c..8e95b97b0a 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -102,7 +102,6 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 30*time.Second, blz.OpenedCacheExpInterval()) require.EqualValues(t, 10, blz.LeafWidth()) require.EqualValues(t, 10, blz.InitWorkerCount()) - require.EqualValues(t, true, blz.InitInAdvance()) require.EqualValues(t, 30*time.Second, blz.RebuildDropTimeout()) require.Equal(t, "tmp/0/blob", ss[1].Path()) diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go index c8ea4c2cb6..9feee4f641 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go @@ -175,16 +175,6 @@ func (x *Config) InitWorkerCount() int { return InitWorkerCountDefault } -// InitInAdvance returns the value of "init_in_advance" config parameter. -// -// Returns False if the value is not defined or invalid. -func (x *Config) InitInAdvance() bool { - return config.BoolSafe( - (*config.Config)(x), - "init_in_advance", - ) -} - // RebuildDropTimeout returns the value of "rebuild_drop_timeout" config parameter. // // Returns RebuildDropTimeoutDefault if the value is not defined or invalid. diff --git a/config/example/node.env b/config/example/node.env index 72f56e96c9..ca4351363d 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -128,7 +128,6 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_TTL=1m FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_EXP_INTERVAL=30s FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 -FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_IN_ADVANCE=TRUE FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_REBUILD_DROP_TIMEOUT=30s ### FSTree config FROSTFS_STORAGE_SHARD_0_BLOBSTOR_1_TYPE=fstree diff --git a/config/example/node.json b/config/example/node.json index b9dc6014cd..7b502b6bd7 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -176,7 +176,6 @@ "opened_cache_exp_interval": "30s", "leaf_width": 10, "init_worker_count": 10, - "init_in_advance": true, "rebuild_drop_timeout": "30s" }, { diff --git a/config/example/node.yaml b/config/example/node.yaml index bad67816a2..c02f9d37b3 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -189,7 +189,6 @@ storage: - type: blobovnicza path: tmp/0/blob/blobovnicza init_worker_count: 10 #count of workers to initialize blobovniczas - init_in_advance: true rebuild_drop_timeout: 30s # timeout before drop single blobovnicza opened_cache_ttl: 1m opened_cache_exp_interval: 30s diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 5389bfbb55..4a6e5ba6d9 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -242,7 +242,6 @@ blobstor: | `opened_cache_ttl` | `duration` | `0` | TTL in cache for opened blobovniczas(disabled by default). In case of heavy random-read and 10 shards each with 10_000 databases and accessing 400 objects per-second we will access each db approximately once per ((10 * 10_000 / 400) = 250 seconds <= 300 seconds = 5 min). Also take in mind that in this scenario they will probably be closed earlier because of the cache capacity, so bigger values are likely to be of no use. | | `opened_cache_exp_interval` | `duration` | `15s` | Cache cleanup interval for expired blobovnicza's. | | `init_worker_count` | `int` | `5` | Maximum number of concurrent initialization workers. | -| `init_in_advance` | `bool` | `false` | If `true`, than all the blobovnicza files will be created on startup. | | `rebuild_drop_timeout` | `duration` | `10s` | Timeout before drop empty blobovnicza file during rebuild. | ### `gc` subsection diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 67e8c8f18d..eeade94254 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -83,31 +83,6 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { return err } - if b.createDBInAdvance { - err = b.iterateSortedLeaves(egCtx, nil, func(p string) (bool, error) { - if _, found := visited[p]; found { - return false, nil - } - eg.Go(func() error { - shBlz := b.getBlobovniczaWithoutCaching(p) - _, err := shBlz.Open() - if err != nil { - return err - } - defer shBlz.Close() - - b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) - return nil - }) - return false, nil - }) - - if err != nil { - _ = eg.Wait() - return err - } - } - return eg.Wait() } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go deleted file mode 100644 index b067a164b0..0000000000 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package blobovniczatree - -import ( - "context" - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - "github.com/stretchr/testify/require" -) - -func TestIterateSortedLeavesAndDBPathsAreSame(t *testing.T) { - t.Parallel() - - blz := NewBlobovniczaTree( - context.Background(), - WithBlobovniczaShallowDepth(3), - WithBlobovniczaShallowWidth(5), - WithRootPath(t.TempDir()), - ) - blz.createDBInAdvance = true - require.NoError(t, blz.Open(mode.ComponentReadWrite)) - require.NoError(t, blz.Init()) - defer func() { - require.NoError(t, blz.Close()) - }() - - addr := oidtest.Address() - - var leaves []string - var dbPaths []string - - blz.iterateSortedLeaves(context.Background(), &addr, func(s string) (bool, error) { - leaves = append(leaves, s) - return false, nil - }) - - blz.iterateSortedDBPaths(context.Background(), addr, func(s string) (bool, error) { - dbPaths = append(dbPaths, s) - return false, nil - }) - - require.Equal(t, leaves, dbPaths) -} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index 6344992750..1bf7b2207b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -26,7 +26,6 @@ type cfg struct { waitBeforeDropDB time.Duration blzInitWorkerCount int blzMoveBatchSize int - createDBInAdvance bool // TTL for blobovnicza's cache openedCacheTTL time.Duration // Interval for deletion expired blobovnicza's @@ -160,10 +159,3 @@ func WithInitWorkerCount(v int) Option { c.blzInitWorkerCount = v } } - -// WithInitInAdvance returns an option to create blobovnicza tree DB's in advance. -func WithInitInAdvance(v bool) Option { - return func(c *cfg) { - c.createDBInAdvance = v - } -} From 78b1d9b18db2b15a53955d331bfebade29498846 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 4 Jul 2024 09:18:17 +0300 Subject: [PATCH 0672/1413] [#1226] blobovniczatree: Drop leaf width limitation Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 -- cmd/frostfs-node/config/engine/config_test.go | 2 - .../shard/blobstor/blobovnicza/config.go | 10 ----- config/example/node.env | 2 - config/example/node.json | 4 +- config/example/node.yaml | 1 - .../blobstor/blobovniczatree/active.go | 37 ++++++++----------- .../blobstor/blobovniczatree/blobovnicza.go | 30 ++++++++++++--- .../blobstor/blobovniczatree/iterate.go | 9 ++++- .../blobstor/blobovniczatree/option.go | 7 ---- 10 files changed, 50 insertions(+), 55 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index b51073d4e4..5b91e78191 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -188,7 +188,6 @@ type subStorageCfg struct { // blobovnicza-specific size uint64 width uint64 - leafWidth uint64 openedCacheSize int initWorkerCount int rebuildDropTimeout time.Duration @@ -313,7 +312,6 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol sCfg.size = sub.Size() sCfg.depth = sub.ShallowDepth() sCfg.width = sub.ShallowWidth() - sCfg.leafWidth = sub.LeafWidth() sCfg.openedCacheSize = sub.OpenedCacheSize() sCfg.openedCacheTTL = sub.OpenedCacheTTL() sCfg.openedCacheExpInterval = sub.OpenedCacheExpInterval() @@ -904,7 +902,6 @@ func (c *cfg) getSubstorageOpts(ctx context.Context, shCfg shardCfg) []blobstor. blobovniczatree.WithBlobovniczaSize(sRead.size), blobovniczatree.WithBlobovniczaShallowDepth(sRead.depth), blobovniczatree.WithBlobovniczaShallowWidth(sRead.width), - blobovniczatree.WithBlobovniczaLeafWidth(sRead.leafWidth), blobovniczatree.WithOpenedCacheSize(sRead.openedCacheSize), blobovniczatree.WithOpenedCacheTTL(sRead.openedCacheTTL), blobovniczatree.WithOpenedCacheExpInterval(sRead.openedCacheExpInterval), diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 8e95b97b0a..7473afefb4 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -100,7 +100,6 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 50, blz.OpenedCacheSize()) require.EqualValues(t, time.Minute, blz.OpenedCacheTTL()) require.EqualValues(t, 30*time.Second, blz.OpenedCacheExpInterval()) - require.EqualValues(t, 10, blz.LeafWidth()) require.EqualValues(t, 10, blz.InitWorkerCount()) require.EqualValues(t, 30*time.Second, blz.RebuildDropTimeout()) @@ -154,7 +153,6 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 50, blz.OpenedCacheSize()) require.EqualValues(t, 5*time.Minute, blz.OpenedCacheTTL()) require.EqualValues(t, 15*time.Second, blz.OpenedCacheExpInterval()) - require.EqualValues(t, 10, blz.LeafWidth()) require.EqualValues(t, blobovniczaconfig.InitWorkerCountDefault, blz.InitWorkerCount()) require.EqualValues(t, blobovniczaconfig.RebuildDropTimeoutDefault, blz.RebuildDropTimeout()) diff --git a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go index 9feee4f641..ac69c4c4f9 100644 --- a/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go +++ b/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza/config.go @@ -149,16 +149,6 @@ func (x *Config) BoltDB() *boltdbconfig.Config { return (*boltdbconfig.Config)(x) } -// LeafWidth returns the value of "leaf_width" config parameter. -// -// Returns 0 if the value is not a positive number. -func (x *Config) LeafWidth() uint64 { - return config.UintSafe( - (*config.Config)(x), - "leaf_width", - ) -} - // InitWorkerCount returns the value of "init_worker_count" config parameter. // // Returns InitWorkerCountDefault if the value is not a positive number. diff --git a/config/example/node.env b/config/example/node.env index ca4351363d..00190eb39f 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -126,7 +126,6 @@ FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_TTL=1m FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_OPENED_CACHE_EXP_INTERVAL=30s -FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_LEAF_WIDTH=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_INIT_WORKER_COUNT=10 FROSTFS_STORAGE_SHARD_0_BLOBSTOR_0_REBUILD_DROP_TIMEOUT=30s ### FSTree config @@ -177,7 +176,6 @@ FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_WIDTH=4 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_CAPACITY=50 FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_TTL=5m FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_OPENED_CACHE_EXP_INTERVAL=15s -FROSTFS_STORAGE_SHARD_1_BLOBSTOR_0_LEAF_WIDTH=10 ### FSTree config FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_TYPE=fstree FROSTFS_STORAGE_SHARD_1_BLOBSTOR_1_PATH=tmp/1/blob diff --git a/config/example/node.json b/config/example/node.json index 7b502b6bd7..9051d2bb7c 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -174,7 +174,6 @@ "opened_cache_capacity": 50, "opened_cache_ttl": "1m", "opened_cache_exp_interval": "30s", - "leaf_width": 10, "init_worker_count": 10, "rebuild_drop_timeout": "30s" }, @@ -227,8 +226,7 @@ "width": 4, "opened_cache_capacity": 50, "opened_cache_ttl": "5m", - "opened_cache_exp_interval": "15s", - "leaf_width": 10 + "opened_cache_exp_interval": "15s" }, { "type": "fstree", diff --git a/config/example/node.yaml b/config/example/node.yaml index c02f9d37b3..bcc8552b30 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -149,7 +149,6 @@ storage: opened_cache_capacity: 50 # maximum number of opened database files opened_cache_ttl: 5m # ttl for opened database file opened_cache_exp_interval: 15s # cache cleanup interval for expired blobovnicza's - leaf_width: 10 # max count of key-value DB on leafs of object tree storage - perm: 0644 # permissions for blobstor files(directories: +x for current user and group) depth: 5 # max depth of object tree storage in FS diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/active.go b/pkg/local_object_storage/blobstor/blobovniczatree/active.go index 0e3497383e..603c6abe3c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/active.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/active.go @@ -37,17 +37,17 @@ type activeDBManager struct { closed bool dbManager *dbManager - leafWidth uint64 + rootPath string } -func newActiveDBManager(dbManager *dbManager, leafWidth uint64) *activeDBManager { +func newActiveDBManager(dbManager *dbManager, rootPath string) *activeDBManager { return &activeDBManager{ levelToActiveDBGuard: &sync.RWMutex{}, levelToActiveDB: make(map[string]*sharedDB), levelLock: utilSync.NewKeyLocker[string](), dbManager: dbManager, - leafWidth: leafWidth, + rootPath: rootPath, } } @@ -144,30 +144,25 @@ func (m *activeDBManager) updateAndGetActive(lvlPath string) (*activeDB, error) } func (m *activeDBManager) getNextSharedDB(lvlPath string) (*sharedDB, error) { - var idx uint64 - var iterCount uint64 + var nextActiveDBIdx uint64 hasActive, currentIdx := m.hasActiveDB(lvlPath) if hasActive { - idx = (currentIdx + 1) % m.leafWidth - } - - var next *sharedDB - - for iterCount < m.leafWidth { - path := filepath.Join(lvlPath, u64ToHexStringExt(idx)) - shDB := m.dbManager.GetByPath(path) - db, err := shDB.Open() // open db to hold active DB open, will be closed if db is full, after m.replace or by activeDBManager.Close() + nextActiveDBIdx = currentIdx + 1 + } else { + hasDBs, maxIdx, err := getBlobovniczaMaxIndex(filepath.Join(m.rootPath, lvlPath)) if err != nil { return nil, err } - if db.IsFull() { - shDB.Close() - } else { - next = shDB - break + if hasDBs { + nextActiveDBIdx = maxIdx } - idx = (idx + 1) % m.leafWidth - iterCount++ + } + + path := filepath.Join(lvlPath, u64ToHexStringExt(nextActiveDBIdx)) + next := m.dbManager.GetByPath(path) + _, err := next.Open() // open db to hold active DB open, will be closed if db is full, after m.replace or by activeDBManager.Close() + if err != nil { + return nil, err } previous, updated := m.replace(lvlPath, next) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 58466f7592..952203367a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -3,6 +3,7 @@ package blobovniczatree import ( "context" "errors" + "os" "strconv" "strings" "sync" @@ -81,12 +82,8 @@ func NewBlobovniczaTree(ctx context.Context, opts ...Option) (blz *Blobovniczas) opts[i](&blz.cfg) } - if blz.blzLeafWidth == 0 { - blz.blzLeafWidth = blz.blzShallowWidth - } - blz.commondbManager = newDBManager(blz.rootPath, blz.blzOpts, blz.readOnly, blz.metrics.Blobovnicza(), blz.log) - blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.blzLeafWidth) + blz.activeDBManager = newActiveDBManager(blz.commondbManager, blz.rootPath) blz.dbCache = newDBCache(ctx, blz.openedCacheSize, blz.openedCacheTTL, blz.openedCacheExpInterval, blz.commondbManager) blz.deleteProtectedObjects = newAddressMap() @@ -124,6 +121,29 @@ func u64FromHexString(str string) uint64 { return v } +func getBlobovniczaMaxIndex(directory string) (bool, uint64, error) { + entries, err := os.ReadDir(directory) + if os.IsNotExist(err) { // non initialized tree + return false, 0, nil + } + if err != nil { + return false, 0, err + } + if len(entries) == 0 { + return false, 0, nil + } + var hasDBs bool + var maxIdx uint64 + for _, e := range entries { + if e.IsDir() { + continue + } + hasDBs = true + maxIdx = max(u64FromHexString(e.Name()), maxIdx) + } + return hasDBs, maxIdx, nil +} + // Type is blobovniczatree storage type used in logs and configuration. const Type = "blobovnicza" diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 92014fd558..af3d9e7206 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -130,7 +130,14 @@ func (b *Blobovniczas) iterateSorted(ctx context.Context, addr *oid.Address, cur isLeafLevel := uint64(len(curPath)) == b.blzShallowDepth levelWidth := b.blzShallowWidth if isLeafLevel { - levelWidth = b.blzLeafWidth + hasDBs, maxIdx, err := getBlobovniczaMaxIndex(filepath.Join(append([]string{b.rootPath}, curPath...)...)) + if err != nil { + return false, err + } + levelWidth = 0 + if hasDBs { + levelWidth = maxIdx + 1 + } } indices := indexSlice(levelWidth) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index 1bf7b2207b..008be95436 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -18,7 +18,6 @@ type cfg struct { openedCacheSize int blzShallowDepth uint64 blzShallowWidth uint64 - blzLeafWidth uint64 compression *compression.Config blzOpts []blobovnicza.Option reportError func(string, error) // reportError is the function called when encountering disk errors. @@ -82,12 +81,6 @@ func WithBlobovniczaShallowWidth(width uint64) Option { } } -func WithBlobovniczaLeafWidth(w uint64) Option { - return func(c *cfg) { - c.blzLeafWidth = w - } -} - func WithBlobovniczaShallowDepth(depth uint64) Option { return func(c *cfg) { c.blzShallowDepth = depth From 62cbb72a5edd045d7d037402fe68b98a615d7abe Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 4 Jul 2024 10:11:30 +0300 Subject: [PATCH 0673/1413] [#1226] blobovniczatree: Delete fix db extensions in Init() Since several releases have been released, this code is not relevant. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 6 -- .../blobstor/blobovniczatree/control.go | 47 -------------- .../blobstor/blobovniczatree/control_test.go | 63 ------------------- 3 files changed, 116 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 4f0b291243..ae88345173 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -480,12 +480,6 @@ const ( BlobstoreRebuildStarted = "blobstore rebuild started" BlobstoreRebuildCompletedSuccessfully = "blobstore rebuild completed successfully" BlobstoreRebuildStopped = "blobstore rebuild stopped" - BlobovniczaTreeFixingFileExtensions = "fixing blobovnicza tree file extensions..." - BlobovniczaTreeFixingFileExtensionsCompletedSuccessfully = "fixing blobovnicza tree file extensions completed successfully" - BlobovniczaTreeFixingFileExtensionsFailed = "failed to fix blobovnicza tree file extensions" - BlobovniczaTreeFixingFileExtensionForFile = "fixing blobovnicza file extension..." - BlobovniczaTreeFixingFileExtensionCompletedSuccessfully = "fixing blobovnicza file extension completed successfully" - BlobovniczaTreeFixingFileExtensionFailed = "failed to fix blobovnicza file extension" BlobstorRebuildFailedToRebuildStorages = "failed to rebuild storages" BlobstorRebuildRebuildStoragesCompleted = "storages rebuild completed" BlobovniczaTreeCollectingDBToRebuild = "collecting blobovniczas to rebuild..." diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index eeade94254..a31e9d6cbb 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -2,10 +2,6 @@ package blobovniczatree import ( "context" - "errors" - "os" - "path/filepath" - "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -14,8 +10,6 @@ import ( "golang.org/x/sync/errgroup" ) -var errFailedToChangeExtensionReadOnly = errors.New("failed to change blobovnicza extension: read only mode") - // Open opens blobovnicza tree. func (b *Blobovniczas) Open(mode mode.ComponentMode) error { b.readOnly = mode.ReadOnly() @@ -31,13 +25,6 @@ func (b *Blobovniczas) Open(mode mode.ComponentMode) error { func (b *Blobovniczas) Init() error { b.log.Debug(logs.BlobovniczatreeInitializingBlobovniczas) - b.log.Debug(logs.BlobovniczaTreeFixingFileExtensions) - if err := b.addDBExtensionToDBs(b.rootPath, 0); err != nil { - b.log.Error(logs.BlobovniczaTreeFixingFileExtensionsFailed, zap.Error(err)) - return err - } - b.log.Debug(logs.BlobovniczaTreeFixingFileExtensionsCompletedSuccessfully) - if b.readOnly { b.log.Debug(logs.BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization) return nil @@ -111,37 +98,3 @@ func (b *Blobovniczas) getBlobovnicza(p string) *sharedDB { func (b *Blobovniczas) getBlobovniczaWithoutCaching(p string) *sharedDB { return b.commondbManager.GetByPath(p) } - -func (b *Blobovniczas) addDBExtensionToDBs(path string, depth uint64) error { - entries, err := os.ReadDir(path) - if os.IsNotExist(err) && depth == 0 { - return nil - } - - for _, entry := range entries { - if entry.IsDir() { - if err := b.addDBExtensionToDBs(filepath.Join(path, entry.Name()), depth+1); err != nil { - return err - } - continue - } - - if strings.HasSuffix(entry.Name(), dbExtension) { - continue - } - if b.readOnly { - return errFailedToChangeExtensionReadOnly - } - - sourcePath := filepath.Join(path, entry.Name()) - targetPath := filepath.Join(path, entry.Name()+dbExtension) - b.log.Debug(logs.BlobovniczaTreeFixingFileExtensionForFile, zap.String("source", sourcePath), zap.String("target", targetPath)) - if err := os.Rename(sourcePath, targetPath); err != nil { - b.log.Error(logs.BlobovniczaTreeFixingFileExtensionFailed, zap.String("source", sourcePath), zap.String("target", targetPath), zap.Error(err)) - return err - } - b.log.Debug(logs.BlobovniczaTreeFixingFileExtensionCompletedSuccessfully, zap.String("source", sourcePath), zap.String("target", targetPath)) - } - - return nil -} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go index 7218cd6bba..f0a32ded14 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go @@ -2,78 +2,15 @@ package blobovniczatree import ( "context" - "os" - "path/filepath" - "strings" "testing" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" ) -func TestDBExtensionFix(t *testing.T) { - root := t.TempDir() - createTestTree(t, 0, 2, 3, root) - t.Run("adds suffix if not exists", func(t *testing.T) { - openAndCloseTestTree(t, 2, 3, root) - validateTestTree(t, root) - }) - - t.Run("not adds second suffix if exists", func(t *testing.T) { - openAndCloseTestTree(t, 2, 3, root) - validateTestTree(t, root) - }) -} - -func createTestTree(t *testing.T, currentDepth, depth, width uint64, path string) { - if currentDepth == depth { - var w uint64 - for ; w < width; w++ { - dbPath := filepath.Join(path, u64ToHexString(w)) - b := blobovnicza.New(blobovnicza.WithPath(dbPath)) - require.NoError(t, b.Open()) - require.NoError(t, b.Init()) - require.NoError(t, b.Close()) - } - return - } - - var w uint64 - for ; w < width; w++ { - createTestTree(t, currentDepth+1, depth, width, filepath.Join(path, u64ToHexString(w))) - } -} - -func openAndCloseTestTree(t *testing.T, depth, width uint64, path string) { - blz := NewBlobovniczaTree( - context.Background(), - WithBlobovniczaShallowDepth(depth), - WithBlobovniczaShallowWidth(width), - WithRootPath(path), - ) - require.NoError(t, blz.Open(mode.ComponentReadWrite)) - require.NoError(t, blz.Init()) - require.NoError(t, blz.Close()) -} - -func validateTestTree(t *testing.T, path string) { - entries, err := os.ReadDir(path) - require.NoError(t, err) - - for _, entry := range entries { - if entry.IsDir() { - validateTestTree(t, filepath.Join(path, entry.Name())) - } else { - require.True(t, strings.HasSuffix(entry.Name(), dbExtension)) - require.False(t, strings.HasSuffix(strings.TrimSuffix(entry.Name(), dbExtension), dbExtension)) - } - } -} - func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { t.Parallel() From cfd5e3d40371cb3e26c0637e3773135d7bfd0058 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Thu, 4 Jul 2024 12:09:18 +0300 Subject: [PATCH 0674/1413] [#1227] morph/event: Release ants.Pool on listener stopping Signed-off-by: Denis Kirillov --- pkg/morph/event/listener.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 4fb92da50e..dd3c7d2164 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -621,6 +621,7 @@ func (l *listener) RegisterNotaryHandler(hi NotaryHandlerInfo) { func (l *listener) Stop() { l.stopOnce.Do(func() { l.subscriber.Close() + l.pool.Release() }) l.wg.Wait() } From 8eb591d668817ee0e438522845bb3e9ff1b574c8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 5 Jul 2024 12:06:28 +0300 Subject: [PATCH 0675/1413] [#1231] policer: Add EC node-off unit test Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/ec_test.go | 145 ++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) diff --git a/pkg/services/policer/ec_test.go b/pkg/services/policer/ec_test.go index 9492787dca..e230153f93 100644 --- a/pkg/services/policer/ec_test.go +++ b/pkg/services/policer/ec_test.go @@ -563,3 +563,148 @@ func TestECChunkRestore(t *testing.T) { require.NoError(t, err) require.EqualValues(t, string(expectedData), string(actualData), "invalid restored objects") } + +func TestECChunkRestoreNodeOff(t *testing.T) { + // node0 has chunk0, node1 has chunk1, node2 has chunk2, node3 is out of netmap + t.Parallel() + + payload := make([]byte, 64) + rand.Read(payload) + parentAddress := oidtest.Address() + parentObject := objectSDK.New() + parentObject.SetContainerID(parentAddress.Container()) + parentObject.SetPayload(payload) + parentObject.SetPayloadSize(64) + objectSDK.CalculateAndSetPayloadChecksum(parentObject) + err := objectSDK.CalculateAndSetID(parentObject) + require.NoError(t, err) + id, _ := parentObject.ID() + parentAddress.SetObject(id) + + chunkIDs := make([]oid.ID, 4) + c, err := erasurecode.NewConstructor(3, 1) + require.NoError(t, err) + key, err := keys.NewPrivateKey() + require.NoError(t, err) + chunks, err := c.Split(parentObject, &key.PrivateKey) + require.NoError(t, err) + for i, ch := range chunks { + chunkIDs[i], _ = ch.ID() + } + + var policy netmapSDK.PlacementPolicy + require.NoError(t, policy.DecodeString("EC 3.1")) + + cnr := &container.Container{} + cnr.Value.Init() + cnr.Value.SetPlacementPolicy(policy) + containerSrc := containerSrc{ + get: func(id cid.ID) (*container.Container, error) { + if id.Equals(parentAddress.Container()) { + return cnr, nil + } + return nil, new(apistatus.ContainerNotFound) + }, + } + + nodes := make([]netmapSDK.NodeInfo, 3) + for i := range nodes { + nodes[i].SetPublicKey([]byte{byte(i)}) + } + + placementBuilder := func(cnr cid.ID, obj *oid.ID, p netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { + if cnr.Equals(parentAddress.Container()) && obj.Equals(parentAddress.Object()) { + return [][]netmapSDK.NodeInfo{nodes}, nil + } + return nil, errors.New("unexpected placement build") + } + remoteHeadFn := func(_ context.Context, ni netmapSDK.NodeInfo, a oid.Address, raw bool) (*objectSDK.Object, error) { + require.True(t, raw, "remote header for parent object must be called with raw flag") + index := int(ni.PublicKey()[0]) + require.True(t, index == 1 || index == 2, "invalid node to get parent header") + require.True(t, a == parentAddress, "invalid address to get remote header") + if index == 1 { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkIDs[1]) + ch.Index = uint32(1) + ch.Total = 4 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + if index == 2 { + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkIDs[2]) + ch.Index = uint32(2) + ch.Total = 4 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + + return nil, new(apistatus.ObjectNotFound) + } + + localHeadFn := func(_ context.Context, a oid.Address) (*objectSDK.Object, error) { + require.True(t, a == parentAddress, "invalid address to get remote header") + ei := objectSDK.NewECInfo() + var ch objectSDK.ECChunk + ch.SetID(chunkIDs[0]) + ch.Index = uint32(0) + ch.Total = 4 + ei.AddChunk(ch) + return nil, objectSDK.NewECInfoError(ei) + } + + var replicatedObj []*objectSDK.Object + p := New( + WithContainerSource(containerSrc), + WithPlacementBuilder(placementBuilderFunc(placementBuilder)), + WithNetmapKeys(announcedKeysFunc(func(k []byte) bool { + return bytes.Equal(k, nodes[0].PublicKey()) + })), + WithRemoteObjectHeaderFunc(remoteHeadFn), + WithLocalObjectHeaderFunc(localHeadFn), + WithReplicator(&testReplicator{ + handleLocalPutTask: func(ctx context.Context, task replicator.Task) { + if task.Obj != nil { + replicatedObj = append(replicatedObj, task.Obj) + } + }, + }), + WithLocalObjectGetFunc(func(ctx context.Context, a oid.Address) (*objectSDK.Object, error) { + require.True(t, a.Container() == parentAddress.Container() && a.Object() == chunkIDs[0], "invalid local object request") + return chunks[0], nil + }), + WithRemoteObjectGetFunc(func(ctx context.Context, ni netmapSDK.NodeInfo, a oid.Address) (*objectSDK.Object, error) { + index := ni.PublicKey()[0] + return chunks[index], nil + }), + WithPool(testPool(t)), + WithKeyStorage(util.NewKeyStorage(&key.PrivateKey, nil, nil)), + ) + + var chunkAddress oid.Address + chunkAddress.SetContainer(parentAddress.Container()) + chunkAddress.SetObject(chunkIDs[0]) + objInfo := objectcore.Info{ + Address: chunkAddress, + Type: objectSDK.TypeRegular, + ECInfo: &objectcore.ECInfo{ + ParentID: parentAddress.Object(), + Index: 0, + Total: 4, + }, + } + err = p.processObject(context.Background(), objInfo) + require.NoError(t, err) + + require.Equal(t, 1, len(replicatedObj), "invalid replicated objects count") + chunks[3].SetSignature(nil) + expectedData, err := chunks[3].MarshalJSON() + require.NoError(t, err) + replicatedObj[0].SetSignature(nil) + actualData, err := replicatedObj[0].MarshalJSON() + require.NoError(t, err) + require.EqualValues(t, string(expectedData), string(actualData), "invalid restored objects") +} From 47bcd346d3bdc9fd50e9fc98c8ee485da5b7f2c6 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 1 Jul 2024 16:37:56 +0300 Subject: [PATCH 0676/1413] [#1216] ape: Introduce `BearerChainFeedRouter` * Unlike default chain router, `BearerChainFedRouter` performs checks for overrides defined in the bearer token; * Add unit-test for the introduced router. Signed-off-by: Airat Arifullin --- pkg/ape/router/bearer_overrides.go | 94 ++++++++++++++ pkg/ape/router/bearer_overrides_test.go | 165 ++++++++++++++++++++++++ pkg/ape/router/single_pass.go | 25 ---- 3 files changed, 259 insertions(+), 25 deletions(-) create mode 100644 pkg/ape/router/bearer_overrides.go create mode 100644 pkg/ape/router/bearer_overrides_test.go diff --git a/pkg/ape/router/bearer_overrides.go b/pkg/ape/router/bearer_overrides.go new file mode 100644 index 0000000000..2bc8ad614d --- /dev/null +++ b/pkg/ape/router/bearer_overrides.go @@ -0,0 +1,94 @@ +package router + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" +) + +func newTarget(ct ape.ChainTarget) (policyengine.Target, error) { + var target policyengine.Target + switch ct.TargetType { + case ape.TargetTypeContainer: + var cid cidSDK.ID + err := cid.DecodeString(ct.Name) + if err != nil { + return target, fmt.Errorf("invalid cid format: %s", target.Name) + } + target.Type = policyengine.Container + case ape.TargetTypeGroup: + target.Type = policyengine.Group + case ape.TargetTypeNamespace: + target.Type = policyengine.Namespace + case ape.TargetTypeUser: + target.Type = policyengine.User + default: + return target, fmt.Errorf("unsupported target type: %v", ct.TargetType) + } + target.Name = ct.Name + return target, nil +} + +type morphReaderDecorator struct { + policyengine.MorphRuleChainStorageReader + + bearerTokenTarget policyengine.Target + + bearerTokenChains []*chain.Chain +} + +func newMorphReaderDecorator(r policyengine.MorphRuleChainStorageReader, override bearer.APEOverride) (*morphReaderDecorator, error) { + if r == nil { + return nil, errors.New("empty morph chain rule reader") + } + t, err := newTarget(override.Target) + if err != nil { + return nil, err + } + + bearerTokenChains := make([]*chain.Chain, len(override.Chains)) + for i := range override.Chains { + chain := new(chain.Chain) + if err := chain.DecodeBytes(override.Chains[i].Raw); err != nil { + return nil, fmt.Errorf("invalid ape chain: %w", err) + } + bearerTokenChains[i] = chain + } + + return &morphReaderDecorator{ + MorphRuleChainStorageReader: r, + bearerTokenTarget: t, + bearerTokenChains: bearerTokenChains, + }, nil +} + +func (m *morphReaderDecorator) ListMorphRuleChains(name chain.Name, target policyengine.Target) ([]*chain.Chain, error) { + if len(m.bearerTokenChains) > 0 && m.bearerTokenTarget.Type == target.Type { + if m.bearerTokenTarget.Name != target.Name { + return nil, fmt.Errorf("unexpected bearer token target: %s", m.bearerTokenTarget.Name) + } + return m.bearerTokenChains, nil + } + return m.MorphRuleChainStorageReader.ListMorphRuleChains(name, target) +} + +// BearerChainFeedRouter creates a chain router emplacing bearer token rule chains. +// Bearer token chains override only container target chains within Policy contract. This means the order of checking +// is as follows: +// +// 1. Local overrides; +// 2. Policy contract chains for a namespace target (as namespace chains have higher priority); +// 3. Bearer token chains for a container target - if they're not defined, then it checks Policy contract chains; +// 4. Checks for the remaining targets. +func BearerChainFeedRouter(localOverrideStorage policyengine.LocalOverrideStorage, morphChainStorage policyengine.MorphRuleChainStorageReader, override bearer.APEOverride) (policyengine.ChainRouter, error) { + mr, err := newMorphReaderDecorator(morphChainStorage, override) + if err != nil { + return nil, fmt.Errorf("create morph reader with bearer override error: %w", err) + } + return policyengine.NewDefaultChainRouterWithLocalOverrides(mr, localOverrideStorage), nil +} diff --git a/pkg/ape/router/bearer_overrides_test.go b/pkg/ape/router/bearer_overrides_test.go new file mode 100644 index 0000000000..3c12ee6fa2 --- /dev/null +++ b/pkg/ape/router/bearer_overrides_test.go @@ -0,0 +1,165 @@ +package router_test + +import ( + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" + apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + bearerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + resourcetest "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource/testutil" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/stretchr/testify/require" +) + +const ( + container = "67ETTZzbzJC6WxdQhHHHsJNCttVMBqYrSoFaUFVDNfiX" + rootNs = "" +) + +var ( + allowBySourceIP = &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: chain.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container)}}, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Kind: chain.KindRequest, + Key: "SourceIP", + Value: "10.122.1.20", + }, + }, + }, + }, + } + + denyBySourceIP = &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: chain.Resources{Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container)}}, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Kind: chain.KindRequest, + Key: "SourceIP", + Value: "10.122.1.20", + }, + }, + }, + }, + } +) + +func TestBearerChainFedRouter(t *testing.T) { + t.Run("no bearer token overrides", func(t *testing.T) { + inmem := inmemory.NewInMemoryLocalOverrides() + + inmem.LocalStorage().AddOverride(chain.Ingress, engine.ContainerTarget(container), denyBySourceIP) + inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(container), allowBySourceIP) + + _, err := router.BearerChainFeedRouter(inmem.LocalStorage(), inmem.MorphRuleChainStorage(), bearerSDK.APEOverride{}) + require.Error(t, err) + }) + t.Run("allow by container with deny by bearer overrides", func(t *testing.T) { + inmem := inmemory.NewInMemoryLocalOverrides() + + inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(container), allowBySourceIP) + + bt := bearerSDK.APEOverride{ + Target: apeSDK.ChainTarget{ + TargetType: apeSDK.TargetTypeContainer, + Name: container, + }, + Chains: []apeSDK.Chain{{ + Raw: denyBySourceIP.Bytes(), + }}, + } + + r, err := router.BearerChainFeedRouter(inmem.LocalStorage(), inmem.MorphRuleChainStorage(), bt) + require.NoError(t, err) + + req := resourcetest.NewRequest(nativeschema.MethodPutObject, + resourcetest.NewResource(fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container), map[string]string{}), + map[string]string{ + "SourceIP": "10.122.1.20", + "Actor": "someOwner", + }, + ) + + st, found, err := r.IsAllowed(chain.Ingress, engine.NewRequestTarget(rootNs, container), req) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, st, chain.AccessDenied) + }) + t.Run("allow by namespace with deny by bearer overrides", func(t *testing.T) { + inmem := inmemory.NewInMemoryLocalOverrides() + + inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(container), allowBySourceIP) + inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(rootNs), allowBySourceIP) + + bt := bearerSDK.APEOverride{ + Target: apeSDK.ChainTarget{ + TargetType: apeSDK.TargetTypeContainer, + Name: container, + }, + Chains: []apeSDK.Chain{{ + Raw: denyBySourceIP.Bytes(), + }}, + } + + r, err := router.BearerChainFeedRouter(inmem.LocalStorage(), inmem.MorphRuleChainStorage(), bt) + require.NoError(t, err) + + req := resourcetest.NewRequest(nativeschema.MethodPutObject, + resourcetest.NewResource(fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container), map[string]string{}), + map[string]string{ + "SourceIP": "10.122.1.20", + "Actor": "someOwner", + }, + ) + + st, found, err := r.IsAllowed(chain.Ingress, engine.NewRequestTarget(rootNs, container), req) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, st, chain.AccessDenied) + }) + t.Run("deny by namespace with allow by bearer overrides", func(t *testing.T) { + inmem := inmemory.NewInMemoryLocalOverrides() + + inmem.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(rootNs), denyBySourceIP) + + bt := bearerSDK.APEOverride{ + Target: apeSDK.ChainTarget{ + TargetType: apeSDK.TargetTypeContainer, + Name: container, + }, + Chains: []apeSDK.Chain{{ + Raw: allowBySourceIP.Bytes(), + }}, + } + + r, err := router.BearerChainFeedRouter(inmem.LocalStorage(), inmem.MorphRuleChainStorage(), bt) + require.NoError(t, err) + + req := resourcetest.NewRequest(nativeschema.MethodPutObject, + resourcetest.NewResource(fmt.Sprintf(nativeschema.ResourceFormatRootContainer, container), map[string]string{}), + map[string]string{ + "SourceIP": "10.122.1.20", + "Actor": "someOwner", + }, + ) + + st, found, err := r.IsAllowed(chain.Ingress, engine.NewRequestTarget(rootNs, container), req) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, st, chain.AccessDenied) + }) +} diff --git a/pkg/ape/router/single_pass.go b/pkg/ape/router/single_pass.go index c0c78db769..ec9244baee 100644 --- a/pkg/ape/router/single_pass.go +++ b/pkg/ape/router/single_pass.go @@ -3,37 +3,12 @@ package router import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" ) -func newTarget(ct ape.ChainTarget) (engine.Target, error) { - var target engine.Target - switch ct.TargetType { - case ape.TargetTypeContainer: - var cid cidSDK.ID - err := cid.DecodeString(ct.Name) - if err != nil { - return target, fmt.Errorf("invalid cid format: %s", target.Name) - } - target.Type = engine.Container - case ape.TargetTypeGroup: - target.Type = engine.Group - case ape.TargetTypeNamespace: - target.Type = engine.Namespace - case ape.TargetTypeUser: - target.Type = engine.User - default: - return target, fmt.Errorf("unsupported target type: %v", ct.TargetType) - } - target.Name = ct.Name - return target, nil -} - // SingleUseRouterWithBearerTokenChains creates chain router with inmemory storage implementation and // fed with APE chains defined in Bearer token. func SingleUseRouterWithBearerTokenChains(overrides []bearer.APEOverride) (engine.ChainRouter, error) { From 0c2b6f3dac70c1f0e72918d3acfb9f64ec7c6f34 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 1 Jul 2024 18:42:15 +0300 Subject: [PATCH 0677/1413] [#1216] ape: Make services use bearer chains fed router * Refactor object and tree service - they should instantiate chain router cheking the bearer token. If there are no bearer token rules, then defaul chain router is used. * Fix unit-tests. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/container.go | 7 +++- cmd/frostfs-node/object.go | 3 +- cmd/frostfs-node/policy_engine.go | 30 ++++----------- cmd/frostfs-node/tree.go | 3 +- pkg/services/object/ape/checker.go | 51 +++++++++++-------------- pkg/services/object/ape/checker_test.go | 13 ++----- pkg/services/tree/ape.go | 20 +++------- pkg/services/tree/options.go | 13 +++++-- 8 files changed, 60 insertions(+), 80 deletions(-) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 99831fe982..5a29aac769 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -19,6 +19,7 @@ import ( containerMorph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/morph" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "go.uber.org/zap" "google.golang.org/grpc" ) @@ -46,9 +47,13 @@ func initContainerService(_ context.Context, c *cfg) { c.shared.frostfsidClient = frostfsIDSubjectProvider + defaultChainRouter := engine.NewDefaultChainRouterWithLocalOverrides( + c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage(), + c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage(), + ) service := containerService.NewSignService( &c.key.PrivateKey, - containerService.NewAPEServer(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine, cnrRdr, + containerService.NewAPEServer(defaultChainRouter, cnrRdr, newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient, containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), ), diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 62183d3140..0124bf772d 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -460,7 +460,8 @@ func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *object return objectAPE.NewService( c.log, objectAPE.NewChecker( - c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.chainRouter, + c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage(), + c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage(), objectAPE.NewStorageEngineHeaderProvider(c.cfgObject.cfgLocalStorage.localStorage, c.cfgObject.getSvc), c.shared.frostfsidClient, c.netMapSource, diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index 13e30a17e8..22fda2b4cc 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -1,13 +1,11 @@ package main import ( - "sync" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" - "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" "github.com/google/uuid" "github.com/hashicorp/golang-lru/v2/expirable" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" @@ -15,11 +13,9 @@ import ( ) type accessPolicyEngine struct { - mtx sync.RWMutex - - chainRouter engine.ChainRouter - localOverrideDatabase chainbase.LocalOverrideDatabase + + morphChainStorage engine.MorphRuleChainStorageReader } var _ engine.MorphRuleChainStorageReader = (*morphAPEChainCache)(nil) @@ -70,32 +66,20 @@ func newAccessPolicyEngine( localOverrideDatabase chainbase.LocalOverrideDatabase, ) *accessPolicyEngine { return &accessPolicyEngine{ - chainRouter: engine.NewDefaultChainRouterWithLocalOverrides( - morphChainStorage, - localOverrideDatabase, - ), + morphChainStorage: morphChainStorage, localOverrideDatabase: localOverrideDatabase, } } -func (a *accessPolicyEngine) IsAllowed(name chain.Name, target engine.RequestTarget, r resource.Request) (status chain.Status, found bool, err error) { - a.mtx.RLock() - defer a.mtx.RUnlock() - - return a.chainRouter.IsAllowed(name, target, r) +func (a *accessPolicyEngine) LocalStorage() engine.LocalOverrideStorage { + return a.localOverrideDatabase } -func (a *accessPolicyEngine) LocalStorage() engine.LocalOverrideStorage { - a.mtx.Lock() - defer a.mtx.Unlock() - - return a.localOverrideDatabase +func (a *accessPolicyEngine) MorphRuleChainStorage() engine.MorphRuleChainStorageReader { + return a.morphChainStorage } func (a *accessPolicyEngine) LocalOverrideDatabaseCore() chainbase.DatabaseCore { - a.mtx.Lock() - defer a.mtx.Unlock() - return a.localOverrideDatabase } diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index daaaa64a24..d22e510ded 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -65,7 +65,8 @@ func initTreeService(c *cfg) { tree.WithReplicationWorkerCount(treeConfig.ReplicationWorkerCount()), tree.WithAuthorizedKeys(treeConfig.AuthorizedKeys()), tree.WithMetrics(c.metricsCollector.TreeService()), - tree.WithAPERouter(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine), + tree.WithAPELocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage()), + tree.WithAPEMorphRuleStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage()), tree.WithNetmapState(c.cfgNetmap.state), ) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 7541ad1163..c6f9b711dd 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -24,24 +24,26 @@ import ( ) type checkerImpl struct { - chainRouter policyengine.ChainRouter - headerProvider HeaderProvider - frostFSIDClient frostfsidcore.SubjectProvider - nm netmap.Source - st netmap.State - cnrSource container.Source - nodePK []byte + localOverrideStorage policyengine.LocalOverrideStorage + morphChainStorage policyengine.MorphRuleChainStorageReader + headerProvider HeaderProvider + frostFSIDClient frostfsidcore.SubjectProvider + nm netmap.Source + st netmap.State + cnrSource container.Source + nodePK []byte } -func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider, nm netmap.Source, st netmap.State, cnrSource container.Source, nodePK []byte) Checker { +func NewChecker(localOverrideStorage policyengine.LocalOverrideStorage, morphChainStorage policyengine.MorphRuleChainStorageReader, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider, nm netmap.Source, st netmap.State, cnrSource container.Source, nodePK []byte) Checker { return &checkerImpl{ - chainRouter: chainRouter, - headerProvider: headerProvider, - frostFSIDClient: frostFSIDClient, - nm: nm, - st: st, - cnrSource: cnrSource, - nodePK: nodePK, + localOverrideStorage: localOverrideStorage, + morphChainStorage: morphChainStorage, + headerProvider: headerProvider, + frostFSIDClient: frostFSIDClient, + nm: nm, + st: st, + cnrSource: cnrSource, + nodePK: nodePK, } } @@ -175,28 +177,21 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { groups[i] = fmt.Sprintf("%s:%s", prm.Namespace, groups[i]) } + var cr policyengine.ChainRouter if prm.BearerToken != nil && !prm.BearerToken.Impersonate() { if err := isValidBearer(prm.BearerToken, prm.ContainerOwner, prm.Container, pub, c.st); err != nil { return fmt.Errorf("bearer token validation error: %w", err) } - btRouter, err := router.SingleUseRouterWithBearerTokenChains([]bearer.APEOverride{prm.BearerToken.APEOverride()}) + cr, err = router.BearerChainFeedRouter(c.localOverrideStorage, c.morphChainStorage, prm.BearerToken.APEOverride()) if err != nil { - return err - } - status, found, err := btRouter.IsAllowed(apechain.Ingress, policyengine.NewRequestTargetWithContainer(prm.Container.EncodeToString()), r) - if err != nil { - return err - } - if found && status == apechain.Allow { - return nil - } - if status != apechain.NoRuleFound { - return fmt.Errorf("bearer token: method %s: %s", prm.Method, status) + return fmt.Errorf("create chain router error: %w", err) } + } else { + cr = policyengine.NewDefaultChainRouterWithLocalOverrides(c.morphChainStorage, c.localOverrideStorage) } rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), groups) - status, ruleFound, err := c.chainRouter.IsAllowed(apechain.Ingress, rt, r) + status, ruleFound, err := cr.IsAllowed(apechain.Ingress, rt, r) if err != nil { return err } diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 5efd3669b5..27c314dfb7 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -469,9 +469,8 @@ func TestAPECheck_BearerTokenOverrides(t *testing.T) { ls := inmemory.NewInmemoryLocalStorage() ms := inmemory.NewInmemoryMorphRuleChainStorage() - r := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) - checker := NewChecker(r, headerProvider, frostfsidProvider, nil, &stMock{}, nil, nil) + checker := NewChecker(ls, ms, headerProvider, frostfsidProvider, nil, &stMock{}, nil, nil) prm := Prm{ Method: method, @@ -534,9 +533,7 @@ func TestAPECheck(t *testing.T) { }) } - router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) - - checker := NewChecker(router, headerProvider, frostfsidProvider, nil, &stMock{}, nil, nil) + checker := NewChecker(ls, ms, headerProvider, frostfsidProvider, nil, &stMock{}, nil, nil) prm := Prm{ Method: method, @@ -639,8 +636,6 @@ func TestPutECChunk(t *testing.T) { MatchType: chain.MatchTypeFirstMatch, }) - router := policyengine.NewDefaultChainRouterWithLocalOverrides(ms, ls) - node1Key, err := keys.NewPrivateKey() require.NoError(t, err) node1 := netmapSDK.NodeInfo{} @@ -669,7 +664,7 @@ func TestPutECChunk(t *testing.T) { }, } - checker := NewChecker(router, headerProvider, frostfsidProvider, nm, &stMock{}, cs, node1Key.PublicKey().Bytes()) + checker := NewChecker(ls, ms, headerProvider, frostfsidProvider, nm, &stMock{}, cs, node1Key.PublicKey().Bytes()) ecParentID := oidtest.ID() chunkHeader := newHeaderObjectSDK(cnr, obj, nil).ToV2().GetHeader() @@ -711,7 +706,7 @@ func TestPutECChunk(t *testing.T) { t.Run("access allowed for non container node", func(t *testing.T) { otherKey, err := keys.NewPrivateKey() require.NoError(t, err) - checker = NewChecker(router, headerProvider, frostfsidProvider, nm, &stMock{}, cs, otherKey.PublicKey().Bytes()) + checker = NewChecker(ls, ms, headerProvider, frostfsidProvider, nm, &stMock{}, cs, otherKey.PublicKey().Bytes()) prm := Prm{ Method: nativeschema.MethodPutObject, Container: cnr, diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index a6202d1a3f..6e78bf4ecb 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -141,25 +141,17 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, return apeErr(err) } + var cr engine.ChainRouter if bt != nil && !bt.Impersonate() { if err := isValidBearer(bt, container.Value.Owner(), cid, publicKey, s.state); err != nil { return fmt.Errorf("bearer validation error: %w", err) } - btRouter, err := router.SingleUseRouterWithBearerTokenChains([]bearer.APEOverride{bt.APEOverride()}) + cr, err = router.BearerChainFeedRouter(s.localOverrideStorage, s.morphChainStorage, bt.APEOverride()) if err != nil { - return apeErr(err) - } - status, found, err := btRouter.IsAllowed(apechain.Ingress, engine.NewRequestTargetWithContainer(cid.EncodeToString()), request) - if err != nil { - return apeErr(err) - } - if found && status == apechain.Allow { - return nil - } - if status != apechain.NoRuleFound { - err = fmt.Errorf("access to operation %s is denied by access policy engine (bearer token): %s", request.Operation(), status.String()) - return apeErr(err) + return fmt.Errorf("create chain router error: %w", err) } + } else { + cr = engine.NewDefaultChainRouterWithLocalOverrides(s.morphChainStorage, s.localOverrideStorage) } groups, err := aperequest.Groups(s.frostfsidSubjectProvider, publicKey) @@ -173,7 +165,7 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, } rt := engine.NewRequestTargetExtended(namespace, cid.EncodeToString(), fmt.Sprintf("%s:%s", namespace, publicKey.Address()), groups) - status, found, err := s.router.IsAllowed(apechain.Ingress, rt, request) + status, found, err := cr.IsAllowed(apechain.Ingress, rt, request) if err != nil { return apeErr(err) } diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index ea55399386..6a20fe5cc1 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -42,7 +42,8 @@ type cfg struct { containerCacheSize int authorizedKeys [][]byte - router policyengine.ChainRouter + localOverrideStorage policyengine.LocalOverrideStorage + morphChainStorage policyengine.MorphRuleChainStorageReader metrics MetricsRegister } @@ -152,9 +153,15 @@ func WithAuthorizedKeys(keys keys.PublicKeys) Option { } } -func WithAPERouter(router policyengine.ChainRouter) Option { +func WithAPELocalOverrideStorage(localOverrideStorage policyengine.LocalOverrideStorage) Option { return func(c *cfg) { - c.router = router + c.localOverrideStorage = localOverrideStorage + } +} + +func WithAPEMorphRuleStorage(morphRuleStorage policyengine.MorphRuleChainStorageReader) Option { + return func(c *cfg) { + c.morphChainStorage = morphRuleStorage } } From d90aab54541f459b673ca9908e6c020e5373e7a5 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 5 Jul 2024 11:50:11 +0300 Subject: [PATCH 0678/1413] [#1229] util: Fix session token expiration check * Make session token expired at `current_epoch + 1` but not at `current_epoch` when it's still valid. Signed-off-by: Airat Arifullin --- pkg/services/object/util/key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/util/key.go b/pkg/services/object/util/key.go index 8304bf13a0..23d6c1c68d 100644 --- a/pkg/services/object/util/key.go +++ b/pkg/services/object/util/key.go @@ -67,7 +67,7 @@ func (s *KeyStorage) GetKey(info *SessionInfo) (*ecdsa.PrivateKey, error) { pToken := s.tokenStore.Get(info.Owner, binID) if pToken != nil { - if pToken.ExpiredAt() <= s.networkState.CurrentEpoch() { + if pToken.ExpiredAt() < s.networkState.CurrentEpoch() { return nil, new(apistatus.SessionTokenExpired) } return pToken.SessionKey(), nil From 6ef38c07bdb80be33f51096d1a29fe7641a32ab3 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 8 Jul 2024 15:29:29 +0300 Subject: [PATCH 0679/1413] [#1235] cli: Fix parse action * Parsed `object.*` lexeme should also include `MethodRangeObject` constant. Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/util/ape.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 680e24d82a..532dc0a501 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -246,6 +246,7 @@ func parseAction(lexeme string) ([]string, bool, error) { nativeschema.MethodHeadObject, nativeschema.MethodDeleteObject, nativeschema.MethodSearchObject, + nativeschema.MethodRangeObject, nativeschema.MethodHashObject, }, true, nil case "container.put": From 84ecd61dfd8154a8155b66e8bfa802e00ff96669 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 8 Jul 2024 11:33:40 +0300 Subject: [PATCH 0680/1413] [#1233] putSvc: Try to put EC chunk to any node Signed-off-by: Dmitrii Stepanov --- pkg/services/object/put/ec.go | 91 ++++++++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 11 deletions(-) diff --git a/pkg/services/object/put/ec.go b/pkg/services/object/put/ec.go index 6237872fbb..6da50195ec 100644 --- a/pkg/services/object/put/ec.go +++ b/pkg/services/object/put/ec.go @@ -3,8 +3,10 @@ package putsvc import ( "context" "crypto/ecdsa" + "encoding/hex" "errors" "fmt" + "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" @@ -160,7 +162,7 @@ func (e *ecWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error } eg.Go(func() error { - return e.writePart(egCtx, obj, int(obj.ECHeader().Index()), nodes) + return e.writePart(egCtx, obj, int(obj.ECHeader().Index()), nodes, make([]atomic.Bool, len(nodes))) }) t.SubmitSuccess() } @@ -195,10 +197,15 @@ func (e *ecWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er break } + visited := make([]atomic.Bool, len(nodes)) + for idx := range parts { + visited[idx%len(nodes)].Store(true) + } + for idx := range parts { idx := idx eg.Go(func() error { - return e.writePart(egCtx, parts[idx], idx, nodes) + return e.writePart(egCtx, parts[idx], idx, nodes, visited) }) t.SubmitSuccess() } @@ -211,19 +218,81 @@ func (e *ecWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er return nil } -func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx int, nodes []placement.Node) error { - var err error - node := nodes[partIdx%len(nodes)] - if e.cfg.netmapKeys.IsLocalKey(node.PublicKey()) { - err = e.writePartLocal(ctx, obj) - } else { - err = e.writePartRemote(ctx, obj, node) +func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx int, nodes []placement.Node, visited []atomic.Bool) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: } + + // try to save to node for current part index + node := nodes[partIdx%len(nodes)] + err := e.putECPartToNode(ctx, obj, node) if err == nil { return nil } - e.cfg.log.Warn(logs.ECFailedToSaveECPart, zap.Stringer("parent_object", object.AddressOf(obj)), zap.Error(err)) - return err + e.cfg.log.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), + zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) + + partVisited := make([]bool, len(nodes)) + partVisited[partIdx%len(nodes)] = true + + // try to save to any node not visited by any of other parts + for i := 1; i < len(nodes); i++ { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + idx := (partIdx + i) % len(nodes) + if !visited[idx].CompareAndSwap(false, true) { + continue + } + node = nodes[idx] + err := e.putECPartToNode(ctx, obj, node) + if err == nil { + return nil + } + e.cfg.log.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), + zap.String("node", hex.EncodeToString(node.PublicKey())), + zap.Error(err)) + + partVisited[idx] = true + } + + // try to save to any node not visited by current part + for i := 0; i < len(nodes); i++ { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if partVisited[i] { + continue + } + node = nodes[i] + err := e.putECPartToNode(ctx, obj, node) + if err == nil { + return nil + } + e.cfg.log.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), + zap.String("node", hex.EncodeToString(node.PublicKey())), + zap.Error(err)) + } + + return fmt.Errorf("failed to save EC chunk %s to any node", object.AddressOf(obj)) +} + +func (e *ecWriter) putECPartToNode(ctx context.Context, obj *objectSDK.Object, node placement.Node) error { + if e.cfg.netmapKeys.IsLocalKey(node.PublicKey()) { + return e.writePartLocal(ctx, obj) + } + return e.writePartRemote(ctx, obj, node) } func (e *ecWriter) writePartLocal(ctx context.Context, obj *objectSDK.Object) error { From ca974b8b4c1c3be1a08811e0522552e93027f481 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 8 Jul 2024 11:36:58 +0300 Subject: [PATCH 0681/1413] [#1233] cli: Drop debugee from `object nodes` Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index cdce7cd7b0..d04cf6f049 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -497,7 +497,6 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID, if errors.As(err, ¬Found) || errors.As(err, &removed) { return false, nil } - cmd.Printf("failed to get object %s from client\n", objID.EncodeToString()) return false, err } From 784e8ef85775f4f388d03453eba670a9cd0ca1f9 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 8 Jul 2024 18:04:30 +0300 Subject: [PATCH 0682/1413] [#1209] cli: Add --quiet flag to healthcheck command Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/internal/commonflags/flags.go | 4 ++++ cmd/frostfs-cli/modules/control/healthcheck.go | 10 ++++++++++ cmd/frostfs-cli/modules/control/ir_healthcheck.go | 11 +++++++++++ 3 files changed, 25 insertions(+) diff --git a/cmd/frostfs-cli/internal/commonflags/flags.go b/cmd/frostfs-cli/internal/commonflags/flags.go index 23dbc8c2b8..cd46d63eb5 100644 --- a/cmd/frostfs-cli/internal/commonflags/flags.go +++ b/cmd/frostfs-cli/internal/commonflags/flags.go @@ -53,6 +53,10 @@ const ( AwaitFlag = "await" AwaitFlagUsage = "Wait for the operation to complete" + + QuietFlag = "quiet" + QuietFlagShorthand = "q" + QuietFlagUsage = "Print nothing and exit with non-zero code on failure" ) // Init adds common flags to the command: diff --git a/cmd/frostfs-cli/modules/control/healthcheck.go b/cmd/frostfs-cli/modules/control/healthcheck.go index 097fba540e..2241a403fb 100644 --- a/cmd/frostfs-cli/modules/control/healthcheck.go +++ b/cmd/frostfs-cli/modules/control/healthcheck.go @@ -1,7 +1,10 @@ package control import ( + "os" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" @@ -24,6 +27,7 @@ func initControlHealthCheckCmd() { flags := healthCheckCmd.Flags() flags.Bool(healthcheckIRFlag, false, "Communicate with IR node") + flags.BoolP(commonflags.QuietFlag, commonflags.QuietFlagShorthand, false, commonflags.QuietFlagUsage) _ = flags.MarkDeprecated(healthcheckIRFlag, "for health check of inner ring nodes, use the 'control ir healthcheck' command instead.") } @@ -50,6 +54,12 @@ func healthCheck(cmd *cobra.Command, args []string) { commonCmd.ExitOnErr(cmd, "rpc error: %w", err) verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + if quietFlag, _ := cmd.Flags().GetBool(commonflags.QuietFlag); quietFlag { + if resp.GetBody().GetHealthStatus() == control.HealthStatus_READY { + return + } + os.Exit(1) + } cmd.Printf("Network status: %s\n", resp.GetBody().GetNetmapStatus()) cmd.Printf("Health status: %s\n", resp.GetBody().GetHealthStatus()) diff --git a/cmd/frostfs-cli/modules/control/ir_healthcheck.go b/cmd/frostfs-cli/modules/control/ir_healthcheck.go index e70538ce20..4f272c1b4f 100644 --- a/cmd/frostfs-cli/modules/control/ir_healthcheck.go +++ b/cmd/frostfs-cli/modules/control/ir_healthcheck.go @@ -1,7 +1,10 @@ package control import ( + "os" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" @@ -18,6 +21,8 @@ var irHealthCheckCmd = &cobra.Command{ func initControlIRHealthCheckCmd() { initControlFlags(irHealthCheckCmd) + flags := irHealthCheckCmd.Flags() + flags.BoolP(commonflags.QuietFlag, commonflags.QuietFlagShorthand, false, commonflags.QuietFlagUsage) } func irHealthCheck(cmd *cobra.Command, _ []string) { @@ -39,6 +44,12 @@ func irHealthCheck(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "rpc error: %w", err) verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + if quietFlag, _ := cmd.Flags().GetBool(commonflags.QuietFlag); quietFlag { + if resp.GetBody().GetHealthStatus() == ircontrol.HealthStatus_READY { + return + } + os.Exit(1) + } cmd.Printf("Health status: %s\n", resp.GetBody().GetHealthStatus()) } From 6ace2f597e8ee86b324abe029859b5d75de11549 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 8 Jul 2024 13:48:39 +0300 Subject: [PATCH 0683/1413] [#1234] pilorama: Add test for duplicate directory behaviour When AddByPath() is called concurrently on 2 different nodes, internal path components may be created twice. This violates some of our assumptions in GetByPath() and, indirectly, in S3 handling of GetSubTree() results. Add a test for the correct behaviour, fixes will follow. Signed-off-by: Evgenii Stratonikov --- .../pilorama/split_test.go | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 pkg/local_object_storage/pilorama/split_test.go diff --git a/pkg/local_object_storage/pilorama/split_test.go b/pkg/local_object_storage/pilorama/split_test.go new file mode 100644 index 0000000000..85c6c3097c --- /dev/null +++ b/pkg/local_object_storage/pilorama/split_test.go @@ -0,0 +1,99 @@ +package pilorama + +import ( + "context" + "strings" + "testing" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + "github.com/stretchr/testify/require" +) + +func TestDuplicateDirectory(t *testing.T) { + t.Skip() + for i := range providers { + if providers[i].name == "inmemory" { + continue + } + t.Run(providers[i].name, func(t *testing.T) { + testDuplicateDirectory(t, providers[i].construct(t)) + }) + } +} + +func testDuplicateDirectory(t *testing.T, f Forest) { + ctx := context.Background() + d := CIDDescriptor{CID: cidtest.ID(), Size: 1} + treeID := "sometree" + + treeApply := func(t *testing.T, parent, child uint64, filename string, internal bool) { + // Nothing magic here, we add items in order and children are unique. + // This simplifies function interface a bit. + ts := child + + kv := []KeyValue{{Key: AttributeFilename, Value: []byte(filename)}} + if !internal { + kv = append(kv, KeyValue{Key: "uniqueAttr", Value: []byte{byte(child)}}) + } + + err := f.TreeApply(ctx, d.CID, treeID, &Move{ + Parent: parent, + Child: child, + Meta: Meta{ + Time: ts, + Items: kv, + }, + }, true) + require.NoError(t, err) + } + + // The following tree is constructed: + // 0 + // [1] |-- dir1 (internal) + // [2] |-- value1 + // [3] |-- dir3 (internal) + // [4] |-- value3 + // [5] |-- dir1 (internal) + // [6] |-- value2 + // [7] |-- dir3 (internal) + // [8] |-- value4 + // [9] |-- dir2 (internal) + // [10] |-- value0 + treeApply(t, RootID, 1, "dir1", true) + treeApply(t, 1, 2, "value1", false) + treeApply(t, 1, 3, "dir3", true) + treeApply(t, 3, 4, "value3", false) + treeApply(t, RootID, 5, "dir1", true) + treeApply(t, 5, 6, "value2", false) + treeApply(t, 5, 7, "dir3", true) + treeApply(t, 7, 8, "value4", false) + treeApply(t, RootID, 9, "dir2", true) + treeApply(t, RootID, 10, "value0", false) + + // The compacted view: + // 0 + // [1,5] |-- dir1 (internal) + // [2] |-- value1 + // [3,7] |-- dir3 (internal) + // [4] |-- value3 + // [8] |-- value4 + // [6] |-- value2 + // [9] |-- dir2 (internal) + // [10] |-- value0 + testGetByPath := func(t *testing.T, p string) []byte { + pp := strings.Split(p, "/") + nodes, err := f.TreeGetByPath(context.Background(), d.CID, treeID, AttributeFilename, pp, false) + require.NoError(t, err) + require.Equal(t, 1, len(nodes)) + + meta, _, err := f.TreeGetMeta(ctx, d.CID, treeID, nodes[0]) + require.NoError(t, err) + require.Equal(t, []byte(pp[len(pp)-1]), meta.GetAttr(AttributeFilename)) + return meta.GetAttr("uniqueAttr") + } + + require.Equal(t, []byte{2}, testGetByPath(t, "dir1/value1")) + require.Equal(t, []byte{4}, testGetByPath(t, "dir1/dir3/value3")) + require.Equal(t, []byte{8}, testGetByPath(t, "dir1/dir3/value4")) + require.Equal(t, []byte{10}, testGetByPath(t, "value0")) +} From b027a7f91e550ff2e24779c648c3511f39339bba Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 8 Jul 2024 13:52:59 +0300 Subject: [PATCH 0684/1413] [#1234] pilorama: Fix GetByPath() on duplicate directories Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/boltdb.go | 60 ++++++++++++++----- .../pilorama/split_test.go | 1 - 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 9fc95dbbb7..ee28df426a 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -906,7 +906,7 @@ func (t *boltForest) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID st b := treeRoot.Bucket(dataBucket) - i, curNode, err := t.getPathPrefix(b, attr, path[:len(path)-1]) + i, curNodes, err := t.getPathPrefixMultiTraversal(b, attr, path[:len(path)-1]) if err != nil { return err } @@ -918,21 +918,23 @@ func (t *boltForest) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID st c := b.Cursor() - attrKey := internalKey(nil, attr, path[len(path)-1], curNode, 0) - attrKey = attrKey[:len(attrKey)-8] - childKey, _ := c.Seek(attrKey) - for len(childKey) == len(attrKey)+8 && bytes.Equal(attrKey, childKey[:len(childKey)-8]) { - child := binary.LittleEndian.Uint64(childKey[len(childKey)-8:]) - if latest { - _, ts, _, _ := t.getState(b, stateKey(make([]byte, 9), child)) - if ts >= maxTimestamp { - nodes = append(nodes[:0], child) - maxTimestamp = ts + for i := range curNodes { + attrKey := internalKey(nil, attr, path[len(path)-1], curNodes[i], 0) + attrKey = attrKey[:len(attrKey)-8] + childKey, _ := c.Seek(attrKey) + for len(childKey) == len(attrKey)+8 && bytes.Equal(attrKey, childKey[:len(childKey)-8]) { + child := binary.LittleEndian.Uint64(childKey[len(childKey)-8:]) + if latest { + _, ts, _, _ := t.getState(b, stateKey(make([]byte, 9), child)) + if ts >= maxTimestamp { + nodes = append(nodes[:0], child) + maxTimestamp = ts + } + } else { + nodes = append(nodes, child) } - } else { - nodes = append(nodes, child) + childKey, _ = c.Next() } - childKey, _ = c.Next() } return nil })) @@ -1412,6 +1414,36 @@ func (t *boltForest) TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (* return &res, nil } +func (t *boltForest) getPathPrefixMultiTraversal(bTree *bbolt.Bucket, attr string, path []string) (int, []Node, error) { + c := bTree.Cursor() + + var curNodes []Node + nextNodes := []Node{RootID} + var attrKey []byte + + for i := range path { + curNodes, nextNodes = nextNodes, curNodes[:0] + for j := range curNodes { + attrKey = internalKey(attrKey, attr, path[i], curNodes[j], 0) + attrKey = attrKey[:len(attrKey)-8] + + childKey, value := c.Seek(attrKey) + for len(childKey) == len(attrKey)+8 && bytes.Equal(attrKey, childKey[:len(childKey)-8]) { + if len(value) == 1 && value[0] == 1 { + nextNodes = append(nextNodes, binary.LittleEndian.Uint64(childKey[len(childKey)-8:])) + } + childKey, value = c.Next() + } + } + + if len(nextNodes) == 0 { + return i, curNodes, nil + } + } + + return len(path), nextNodes, nil +} + func (t *boltForest) getPathPrefix(bTree *bbolt.Bucket, attr string, path []string) (int, Node, error) { c := bTree.Cursor() diff --git a/pkg/local_object_storage/pilorama/split_test.go b/pkg/local_object_storage/pilorama/split_test.go index 85c6c3097c..3bd581ce6e 100644 --- a/pkg/local_object_storage/pilorama/split_test.go +++ b/pkg/local_object_storage/pilorama/split_test.go @@ -10,7 +10,6 @@ import ( ) func TestDuplicateDirectory(t *testing.T) { - t.Skip() for i := range providers { if providers[i].name == "inmemory" { continue From 3bf6e6dde60f15f4f90caf44eda429e8f6269cc1 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 10 Jul 2024 11:27:40 +0300 Subject: [PATCH 0685/1413] [#1238] engine: Add non-blocking send in the shard's notification channel Signed-off-by: Anton Nikiforov --- internal/logs/logs.go | 1 + pkg/local_object_storage/engine/shards.go | 3 +++ 2 files changed, 4 insertions(+) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index ae88345173..5a195f6882 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -252,6 +252,7 @@ const ( ShardCantInitializeMetabaseMoveToADegradedreadonlyMode = "can't initialize metabase, move to a degraded-read-only mode" ShardStopEventListenerByClosedEventChannel = "stop event listener by closed `event` channel" ShardStopEventListenerByClosedStopChannel = "stop event listener by closed `stop` channel" + ShardEventProcessingInProgress = "event processing is in progress, skip the received" ShardStopEventListenerByContext = "stop event listener by context" ShardCouldNotSubmitGCJobToWorkerPool = "could not submit GC job to worker pool" ShardGCIsStopped = "GC is stopped" diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 54d3e7d65e..56d4fcd4af 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -340,6 +340,9 @@ func (e *StorageEngine) HandleNewEpoch(ctx context.Context, epoch uint64) { case <-ctx.Done(): return case sh.NotificationChannel() <- ev: + default: + e.log.Debug(logs.ShardEventProcessingInProgress, + zap.Uint64("epoch", epoch), zap.Stringer("shard", sh.ID())) } } } From 36956db12305fd7d58e5b9cabe6bfd9334b329e4 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 3 Jul 2024 12:03:53 +0300 Subject: [PATCH 0686/1413] [#1159] adm/frostfsid: Remove wallet requirement for list-* Signed-off-by: Alexander Chuprov --- .../modules/morph/frostfsid/frostfsid.go | 110 ++++++++++++++---- 1 file changed, 86 insertions(+), 24 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 442920912e..091d6634ad 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -3,24 +3,32 @@ package frostfsid import ( "errors" "fmt" + "math/big" "sort" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + frostfsidrpclient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/spf13/cobra" "github.com/spf13/viper" ) +const iteratorBatchSize = 1 + const ( namespaceFlag = "namespace" subjectNameFlag = "subject-name" @@ -250,12 +258,15 @@ func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { } func frostfsidListNamespaces(cmd *cobra.Command, _ []string) { - ffsid, err := newFrostfsIDClient(cmd) - commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) - - namespaces, err := ffsid.roCli.ListNamespaces() - commonCmd.ExitOnErr(cmd, "list namespaces: %w", err) + inv, _, hash := initInvoker(cmd) + reader := frostfsidrpclient.NewReader(inv, hash) + sessionID, it, err := reader.ListNamespaces() + commonCmd.ExitOnErr(cmd, "can't get namespace: %w", err) + items, err := readIterator(inv, &it, iteratorBatchSize, sessionID) + commonCmd.ExitOnErr(cmd, "can't read iterator: %w", err) + namespaces, err := frostfsidclient.ParseNamespaces(items) + commonCmd.ExitOnErr(cmd, "can't parse namespace: %w", err) sort.Slice(namespaces, func(i, j int) bool { return namespaces[i].Name < namespaces[j].Name }) for _, namespace := range namespaces { @@ -296,14 +307,15 @@ func frostfsidDeleteSubject(cmd *cobra.Command, _ []string) { } func frostfsidListSubjects(cmd *cobra.Command, _ []string) { - ns := getFrostfsIDNamespace(cmd) includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) + ns := getFrostfsIDNamespace(cmd) + inv, _, hash := initInvoker(cmd) + reader := frostfsidrpclient.NewReader(inv, hash) + sessionID, it, err := reader.ListNamespaceSubjects(ns) + commonCmd.ExitOnErr(cmd, "can't get namespace: %w", err) - ffsid, err := newFrostfsIDClient(cmd) - commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) - - subAddresses, err := ffsid.roCli.ListNamespaceSubjects(ns) - commonCmd.ExitOnErr(cmd, "list subjects: %w", err) + subAddresses, err := frostfsidclient.UnwrapArrayOfUint160(readIterator(inv, &it, iteratorBatchSize, sessionID)) + commonCmd.ExitOnErr(cmd, "can't unwrap: %w", err) sort.Slice(subAddresses, func(i, j int) bool { return subAddresses[i].Less(subAddresses[j]) }) @@ -313,8 +325,14 @@ func frostfsidListSubjects(cmd *cobra.Command, _ []string) { continue } - subj, err := ffsid.roCli.GetSubject(addr) - commonCmd.ExitOnErr(cmd, "get subject: %w", err) + sessionID, it, err := reader.ListSubjects() + commonCmd.ExitOnErr(cmd, "can't get subject: %w", err) + + items, err := readIterator(inv, &it, iteratorBatchSize, sessionID) + commonCmd.ExitOnErr(cmd, "can't read iterator: %w", err) + + subj, err := frostfsidclient.ParseSubject(items) + commonCmd.ExitOnErr(cmd, "can't parse subject: %w", err) cmd.Printf("%s (%s)\n", address.Uint160ToString(addr), subj.Name) } @@ -349,13 +367,17 @@ func frostfsidDeleteGroup(cmd *cobra.Command, _ []string) { } func frostfsidListGroups(cmd *cobra.Command, _ []string) { + inv, _, hash := initInvoker(cmd) ns := getFrostfsIDNamespace(cmd) - ffsid, err := newFrostfsIDClient(cmd) - commonCmd.ExitOnErr(cmd, "init contract invoker: %w", err) + reader := frostfsidrpclient.NewReader(inv, hash) + sessionID, it, err := reader.ListGroups(ns) + commonCmd.ExitOnErr(cmd, "can't get namespace: %w", err) - groups, err := ffsid.roCli.ListGroups(ns) - commonCmd.ExitOnErr(cmd, "list groups: %w", err) + items, err := readIterator(inv, &it, iteratorBatchSize, sessionID) + commonCmd.ExitOnErr(cmd, "can't list groups: %w", err) + groups, err := frostfsidclient.ParseGroups(items) + commonCmd.ExitOnErr(cmd, "can't parse groups: %w", err) sort.Slice(groups, func(i, j int) bool { return groups[i].Name < groups[j].Name }) @@ -394,12 +416,19 @@ func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { ns := getFrostfsIDNamespace(cmd) groupID := getFrostfsIDGroupID(cmd) includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) + inv, cs, hash := initInvoker(cmd) + _, err := helper.NNSResolveHash(inv, cs.Hash, helper.DomainOf(constants.FrostfsIDContract)) + commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) - ffsid, err := newFrostfsIDClient(cmd) - commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + reader := frostfsidrpclient.NewReader(inv, hash) + sessionID, it, err := reader.ListGroupSubjects(ns, big.NewInt(groupID)) + commonCmd.ExitOnErr(cmd, "can't list groups: %w", err) - subjects, err := ffsid.roCli.ListGroupSubjects(ns, groupID) - commonCmd.ExitOnErr(cmd, "list group subjects: %w", err) + items, err := readIterator(inv, &it, iteratorBatchSize, sessionID) + commonCmd.ExitOnErr(cmd, "can't read iterator: %w", err) + + subjects, err := frostfsidclient.UnwrapArrayOfUint160(items, err) + commonCmd.ExitOnErr(cmd, "can't unwrap: %w", err) sort.Slice(subjects, func(i, j int) bool { return subjects[i].Less(subjects[j]) }) @@ -409,9 +438,10 @@ func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { continue } - subj, err := ffsid.roCli.GetSubject(subjAddr) - commonCmd.ExitOnErr(cmd, "get subject: %w", err) - + items, err := reader.GetSubject(subjAddr) + commonCmd.ExitOnErr(cmd, "can't get subject: %w", err) + subj, err := frostfsidclient.ParseSubject(items) + commonCmd.ExitOnErr(cmd, "can't parse subject: %w", err) cmd.Printf("%s (%s)\n", address.Uint160ToString(subjAddr), subj.Name) } } @@ -474,3 +504,35 @@ func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) { f.wCtx.Command.Println("Waiting for transactions to persist...") return f.roCli.Wait(f.wCtx.SentTxs[0].Hash, f.wCtx.SentTxs[0].Vub, nil) } + +func readIterator(inv *invoker.Invoker, iter *result.Iterator, batchSize int, sessionID uuid.UUID) ([]stackitem.Item, error) { + var shouldStop bool + res := make([]stackitem.Item, 0) + for !shouldStop { + items, err := inv.TraverseIterator(sessionID, iter, batchSize) + if err != nil { + return nil, err + } + + res = append(res, items...) + shouldStop = len(items) < batchSize + } + + return res, nil +} + +func initInvoker(cmd *cobra.Command) (*invoker.Invoker, *state.Contract, util.Uint160) { + c, err := helper.GetN3Client(viper.GetViper()) + commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err) + + inv := invoker.New(c, nil) + r := management.NewReader(inv) + + cs, err := r.GetContractByID(1) + commonCmd.ExitOnErr(cmd, "can't get NNS contract info: %w", err) + + nmHash, err := helper.NNSResolveHash(inv, cs.Hash, helper.DomainOf(constants.FrostfsIDContract)) + commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) + + return inv, cs, nmHash +} From 0308835d48c8b8d62f8e062e0d7d90b4197e14fd Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 10 Jul 2024 16:25:42 +0300 Subject: [PATCH 0687/1413] [#1159] adm/frostfsid: Update frostfs-contract version Signed-off-by: Alexander Chuprov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 38e66a20fa..d4eb52f4d6 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de diff --git a/go.sum b/go.sum index 0849b74a11..84fdbd47a3 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 h1:H5GvrVlowIMWfzqQkhY0p0myooJxQ1sMRVSFfXawwWg= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45 h1:Tp4I+XOLp3VCJORfxSamQtj3RZNISbaLM4WD5iIzXxg= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= From 08953a2f94ecb50ff8b006d25ac34b4b2c623418 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 11 Jul 2024 18:28:14 +0300 Subject: [PATCH 0688/1413] [#1239] adm/morph: Fix transfer GAS to alphabet nodes Signed-off-by: Alexander Chuprov --- .../modules/morph/initialize/initialize_transfer.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go index 8bcd7eb589..b7102fa139 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go @@ -26,6 +26,10 @@ const ( initialAlphabetGASAmount = 10_000 * native.GASFactor // initialProxyGASAmount represents the amount of GAS given to a proxy contract. initialProxyGASAmount = 50_000 * native.GASFactor + // alphabetGasRatio is a coefficient that defines the threshold below which + // the balance of the alphabet node is considered not replenished. The value + // of this coefficient is determined empirically. + alphabetGasRatio = 5 ) func transferFunds(c *helper.InitializeContext) error { @@ -80,7 +84,7 @@ func transferFundsFinished(c *helper.InitializeContext) (bool, error) { r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) res, err := r.BalanceOf(acc.Contract.ScriptHash()) - return res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) == 1, err + return res.Cmp(big.NewInt(alphabetGasRatio*native.GASFactor)) == 1, err } func transferGASToProxy(c *helper.InitializeContext) error { From d02a7c2d383e832c1cef9fcbb77bd1a6653218db Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 12 Jul 2024 17:56:04 +0300 Subject: [PATCH 0689/1413] [#1196] morph/client: Remove duplicate utility functions * We used several utility functions to parse frostfsid client subject and extended subject. However, following the changes in TrueCloudLab/frostfs-contract#97, these utility functions have become public. So there is no more need to have them here. * There was a mismatch of slice parameter required length between frostfs-node's and frostfs-contract's utility functions, `checkStackItem()` solves this problem. Signed-off-by: Ekaterina Lebedeva --- pkg/morph/client/frostfsid/subject.go | 207 ++------------------------ 1 file changed, 16 insertions(+), 191 deletions(-) diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index 169be6bc54..0852f536cf 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -1,16 +1,12 @@ package frostfsid import ( - "errors" "fmt" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) const ( @@ -28,7 +24,12 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) } - subj, err := parseSubject(res) + structArr, err := checkStackItem(res) + if err != nil { + return nil, fmt.Errorf("invalid test invocation result (%s): %w", methodGetSubjectExtended, err) + } + + subj, err := frostfsidclient.ParseSubject(structArr) if err != nil { return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) } @@ -43,10 +44,15 @@ func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.Subject res, err := c.client.TestInvoke(prm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) + return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubjectExtended, err) } - subj, err := parseSubjectExtended(res) + structArr, err := checkStackItem(res) + if err != nil { + return nil, fmt.Errorf("invalid test invocation result (%s): %w", methodGetSubjectExtended, err) + } + + subj, err := frostfsidclient.ParseSubjectExtended(structArr) if err != nil { return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) } @@ -54,195 +60,14 @@ func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.Subject return subj, nil } -func parseSubject(res []stackitem.Item) (*frostfsidclient.Subject, error) { +func checkStackItem(res []stackitem.Item) (structArr []stackitem.Item, err error) { if ln := len(res); ln != 1 { return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) } - structArr, err := client.ArrayFromStackItem(res[0]) + structArr, err = client.ArrayFromStackItem(res[0]) if err != nil { return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) } - - var subj frostfsidclient.Subject - - subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) - if err != nil { - return nil, err - } - - if !structArr[1].Equals(stackitem.Null{}) { - subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) - if err != nil { - return nil, err - } - } - - if !structArr[2].Equals(stackitem.Null{}) { - subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) - if err != nil { - return nil, err - } - } - - if !structArr[3].Equals(stackitem.Null{}) { - subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) - if err != nil { - return nil, err - } - } - - subj.KV, err = parseMap(structArr[4]) - if err != nil { - return nil, err - } - - return &subj, nil -} - -func parseSubjectExtended(res []stackitem.Item) (*frostfsidclient.SubjectExtended, error) { - if ln := len(res); ln != 1 { - return nil, fmt.Errorf("unexpected stack item count (%s): %d", methodGetSubject, ln) - } - - structArr, err := client.ArrayFromStackItem(res[0]) - if err != nil { - return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) - } - - var subj frostfsidclient.SubjectExtended - - subj.PrimaryKey, err = unwrap.PublicKey(makeValidRes(structArr[0])) - if err != nil { - return nil, err - } - - if !structArr[1].Equals(stackitem.Null{}) { - subj.AdditionalKeys, err = unwrap.ArrayOfPublicKeys(makeValidRes(structArr[1])) - if err != nil { - return nil, err - } - } - - if !structArr[2].Equals(stackitem.Null{}) { - subj.Namespace, err = unwrap.UTF8String(makeValidRes(structArr[2])) - if err != nil { - return nil, err - } - } - - if !structArr[3].Equals(stackitem.Null{}) { - subj.Name, err = unwrap.UTF8String(makeValidRes(structArr[3])) - if err != nil { - return nil, err - } - } - - subj.KV, err = parseMap(structArr[4]) - if err != nil { - return nil, err - } - - if !structArr[5].Equals(stackitem.Null{}) { - groupItems, ok := structArr[5].Value().([]stackitem.Item) - if !ok { - return nil, errors.New("invalid groups field") - } - - subj.Groups, err = parseGroups(groupItems) - if err != nil { - return nil, err - } - } - - return &subj, nil -} - -func makeValidRes(item stackitem.Item) (*result.Invoke, error) { - return &result.Invoke{ - Stack: []stackitem.Item{item}, - State: vmstate.Halt.String(), - }, nil -} - -func parseMap(item stackitem.Item) (map[string]string, error) { - if item.Equals(stackitem.Null{}) { - return nil, nil - } - - metaMap, err := unwrap.Map(makeValidRes(item)) - if err != nil { - return nil, err - } - - meta, ok := metaMap.Value().([]stackitem.MapElement) - if !ok { - return nil, errors.New("invalid map type") - } - - res := make(map[string]string, len(meta)) - for _, element := range meta { - key, err := element.Key.TryBytes() - if err != nil { - return nil, err - } - val, err := element.Value.TryBytes() - if err != nil { - return nil, err - } - res[string(key)] = string(val) - } - - return res, nil -} - -func parseGroups(items []stackitem.Item) ([]*frostfsidclient.Group, error) { - var err error - res := make([]*frostfsidclient.Group, len(items)) - - for i := 0; i < len(items); i++ { - arr, ok := items[i].Value().([]stackitem.Item) - if !ok { - return nil, errors.New("invalid group type") - } - res[i], err = parseGroup(arr) - if err != nil { - return nil, err - } - } - - return res, nil -} - -func parseGroup(structArr []stackitem.Item) (*frostfsidclient.Group, error) { - if len(structArr) < 4 { - return nil, errors.New("invalid response group struct") - } - - groupID, err := structArr[0].TryInteger() - if err != nil { - return nil, err - } - - name, err := structArr[1].TryBytes() - if err != nil { - return nil, err - } - - namespace, err := structArr[2].TryBytes() - if err != nil { - return nil, err - } - - kvs, err := parseMap(structArr[3]) - if err != nil { - return nil, err - } - - return &frostfsidclient.Group{ - ID: groupID.Int64(), - Name: string(name), - Namespace: string(namespace), - KV: kvs, - }, nil + return } From 39866a957c2f67801d30a70b8c1430cd3a1d8b4b Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 12 Jul 2024 17:57:11 +0300 Subject: [PATCH 0690/1413] [#1196] morph/client: Fix `ArrayFromStackItem()` description Signed-off-by: Ekaterina Lebedeva --- pkg/morph/client/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/morph/client/util.go b/pkg/morph/client/util.go index ff8e507fec..cd55d6bd2b 100644 --- a/pkg/morph/client/util.go +++ b/pkg/morph/client/util.go @@ -69,7 +69,7 @@ func BytesFromStackItem(param stackitem.Item) ([]byte, error) { // ArrayFromStackItem returns the slice contract parameters from passed parameter. // -// If passed parameter carries boolean false value, (nil, nil) returns. +// If passed parameter carries boolean false value, returns (nil, nil). func ArrayFromStackItem(param stackitem.Item) ([]stackitem.Item, error) { switch param.Type() { case stackitem.AnyT: From d5dc14c639a99b7c0338dea665851e88a5a59202 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 12 Jul 2024 12:02:20 +0300 Subject: [PATCH 0691/1413] [#1243] object: Make APE checker set x-headers to request properties * Update go.mod, go.sum; * Add x-headers to request properties; * Add a unit-test. Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 +-- pkg/services/object/ape/checker.go | 4 +++ pkg/services/object/ape/checker_test.go | 48 +++++++++++++++++++++++++ pkg/services/object/ape/request.go | 6 ++++ pkg/services/object/ape/service.go | 10 ++++++ 6 files changed, 71 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d4eb52f4d6..ee8b1bb16e 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index 84fdbd47a3..c7c3b87eb4 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8l git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18 h1:JRjwcHaQajTbSCBCK3yZnqvyHvgWBaoThDGuT4kvIIc= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d h1:hHk8FWbWgEnwm2I045CaBIrZBjy/o81CehIVOySA/pQ= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240513163744-1f6f4163d40d/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 h1:O3F2Grz07RWZ68mRz1xsYsNPNvZLwY00BM+xoYb1kNk= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index c6f9b711dd..a1972292e3 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -7,6 +7,7 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" @@ -79,6 +80,9 @@ type Prm struct { // The request's bearer token. It is used in order to check APE overrides with the token. BearerToken *bearer.Token + + // XHeaders from the request. + XHeaders []session.XHeader } var ( diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 27c314dfb7..090f6a83ca 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" @@ -240,6 +241,7 @@ var apeCheckTestCases = []struct { object *string methods []string header testHeader + xHeaders []session.XHeader containerRules []chain.Rule groupidRules []chain.Rule expectAPEErr bool @@ -367,6 +369,52 @@ var apeCheckTestCases = []struct { }, expectAPEErr: true, }, + { + name: "oid required requests are denied by xheader", + container: containerID, + object: stringPtr(objectID), + methods: methodsRequiredOID, + header: testHeader{ + headerObjSDK: &headerObjectSDKParams{ + attributes: []struct { + key string + val string + }{ + { + key: "attr1", + val: "attribute_value", + }, + }, + }, + fromHeaderProvider: true, + }, + xHeaders: []session.XHeader{ + func() (xhead session.XHeader) { + xhead.SetKey("X-Test-ID") + xhead.SetValue("aezakmi") + return + }(), + }, + containerRules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObject, containerID, objectID)}, + }, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringLike, + Kind: chain.KindRequest, + Key: fmt.Sprintf(commonschema.PropertyKeyFrostFSXHeader, "X-Test-ID"), + Value: "aezakmi", + }, + }, + }, + }, + expectAPEErr: true, + }, { name: "optional oid requests reached quota limit by an attribute", container: containerID, diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 02ead8c605..1c129f65f2 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -126,6 +126,12 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, nativeschema.PropertyKeyActorRole: prm.Role, } + + for _, xhead := range prm.XHeaders { + xheadKey := fmt.Sprintf(commonschema.PropertyKeyFrostFSXHeader, xhead.GetKey()) + reqProps[xheadKey] = xhead.GetValue() + } + var err error reqProps, err = c.fillWithUserClaimTags(reqProps, prm) if err != nil { diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 853c3b80d8..56c66002d2 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -111,6 +111,7 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { Role: g.role, SoftAPECheck: g.softAPECheck, BearerToken: g.bearerToken, + XHeaders: resp.GetMetaHeader().GetXHeaders(), } if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { @@ -154,6 +155,7 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt SoftAPECheck: reqCtx.SoftAPECheck, WithoutHeaderRequest: true, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -200,6 +202,7 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR Role: nativeSchemaRole(reqCtx.Role), SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -245,6 +248,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj SoftAPECheck: reqCtx.SoftAPECheck, WithoutHeaderRequest: true, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -285,6 +289,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -314,6 +319,7 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -343,6 +349,7 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -377,6 +384,7 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -406,6 +414,7 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -445,6 +454,7 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ ContainerOwner: reqCtx.ContainerOwner, SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { From 21431f22c0c5c90efb24a5c0937ea525f10a6849 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 12 Jul 2024 17:04:07 +0300 Subject: [PATCH 0692/1413] [#1248] placement: Use cid.ID as key in the cache Signed-off-by: Evgenii Stratonikov --- pkg/services/object_manager/placement/netmap.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/services/object_manager/placement/netmap.go b/pkg/services/object_manager/placement/netmap.go index 787c04421f..41267dbae2 100644 --- a/pkg/services/object_manager/placement/netmap.go +++ b/pkg/services/object_manager/placement/netmap.go @@ -19,7 +19,7 @@ type netMapBuilder struct { lastNm *netmapSDK.NetMap // containerCache caches container nodes by ID. It is used to skip `GetContainerNodes` invocation if // neither netmap nor container has changed. - containerCache simplelru.LRUCache[string, [][]netmapSDK.NodeInfo] + containerCache simplelru.LRUCache[cid.ID, [][]netmapSDK.NodeInfo] } type netMapSrc struct { @@ -32,7 +32,7 @@ type netMapSrc struct { const defaultContainerCacheSize = 10 func NewNetworkMapBuilder(nm *netmapSDK.NetMap) Builder { - cache, _ := simplelru.NewLRU[string, [][]netmapSDK.NodeInfo](defaultContainerCacheSize, nil) // no error + cache, _ := simplelru.NewLRU[cid.ID, [][]netmapSDK.NodeInfo](defaultContainerCacheSize, nil) // no error return &netMapBuilder{ nmSrc: &netMapSrc{nm: nm}, containerCache: cache, @@ -40,7 +40,7 @@ func NewNetworkMapBuilder(nm *netmapSDK.NetMap) Builder { } func NewNetworkMapSourceBuilder(nmSrc netmap.Source) Builder { - cache, _ := simplelru.NewLRU[string, [][]netmapSDK.NodeInfo](defaultContainerCacheSize, nil) // no error + cache, _ := simplelru.NewLRU[cid.ID, [][]netmapSDK.NodeInfo](defaultContainerCacheSize, nil) // no error return &netMapBuilder{ nmSrc: nmSrc, containerCache: cache, @@ -62,7 +62,7 @@ func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.Plac b.mtx.Lock() if nm == b.lastNm { - raw, ok := b.containerCache.Get(string(binCnr)) + raw, ok := b.containerCache.Get(cnr) b.mtx.Unlock() if ok { return BuildObjectPlacement(nm, raw, obj) @@ -78,7 +78,7 @@ func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.Plac } b.mtx.Lock() - b.containerCache.Add(string(binCnr), cn) + b.containerCache.Add(cnr, cn) b.mtx.Unlock() return BuildObjectPlacement(nm, cn, obj) From 3a48b282b64429149ca7f9770eacb8a5bdc7173a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 12 Jul 2024 17:16:06 +0300 Subject: [PATCH 0693/1413] [#1248] placement: Use epoch to track netmap versions Previously we used pointer, this could have worked, because most of the time, the netmap is cached. This didn't work, however, because `lastNm` field was always nil. Rework the mechanism completely: 1. Use epoch to track netmap versions, as it it simpler and is unrelated to the TTL of an underlying cache. 2. Fix a bug where the epoch could change while mutex was unlocked. Signed-off-by: Evgenii Stratonikov --- pkg/services/object_manager/placement/netmap.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pkg/services/object_manager/placement/netmap.go b/pkg/services/object_manager/placement/netmap.go index 41267dbae2..8163529ed7 100644 --- a/pkg/services/object_manager/placement/netmap.go +++ b/pkg/services/object_manager/placement/netmap.go @@ -14,9 +14,10 @@ import ( type netMapBuilder struct { nmSrc netmap.Source - // mtx protects lastNm and containerCache fields. - mtx sync.Mutex - lastNm *netmapSDK.NetMap + // mtx protects lastEpoch and containerCache fields. + mtx sync.Mutex + // lastEpoch contains contains network map epoch for all values in the container cache. + lastEpoch uint64 // containerCache caches container nodes by ID. It is used to skip `GetContainerNodes` invocation if // neither netmap nor container has changed. containerCache simplelru.LRUCache[cid.ID, [][]netmapSDK.NodeInfo] @@ -61,13 +62,14 @@ func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.Plac cnr.Encode(binCnr) b.mtx.Lock() - if nm == b.lastNm { + if nm.Epoch() == b.lastEpoch { raw, ok := b.containerCache.Get(cnr) b.mtx.Unlock() if ok { return BuildObjectPlacement(nm, raw, obj) } } else { + b.lastEpoch = nm.Epoch() b.containerCache.Purge() b.mtx.Unlock() } @@ -78,7 +80,9 @@ func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.Plac } b.mtx.Lock() - b.containerCache.Add(cnr, cn) + if b.lastEpoch == nm.Epoch() { + b.containerCache.Add(cnr, cn) + } b.mtx.Unlock() return BuildObjectPlacement(nm, cn, obj) From 286df198c9401706f5152b31dbecab3ff2df6271 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 12 Jul 2024 17:27:59 +0300 Subject: [PATCH 0694/1413] [#1248] placement: Decouple ContainerNodes() cache from the placement builder. Also, write tests. Signed-off-by: Evgenii Stratonikov --- .../object_manager/placement/cache.go | 69 ++++++++++++++ .../object_manager/placement/cache_test.go | 95 +++++++++++++++++++ .../object_manager/placement/netmap.go | 47 ++------- 3 files changed, 170 insertions(+), 41 deletions(-) create mode 100644 pkg/services/object_manager/placement/cache.go create mode 100644 pkg/services/object_manager/placement/cache_test.go diff --git a/pkg/services/object_manager/placement/cache.go b/pkg/services/object_manager/placement/cache.go new file mode 100644 index 0000000000..217261877a --- /dev/null +++ b/pkg/services/object_manager/placement/cache.go @@ -0,0 +1,69 @@ +package placement + +import ( + "crypto/sha256" + "fmt" + "sync" + + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "github.com/hashicorp/golang-lru/v2/simplelru" +) + +// ContainerNodesCache caches results of ContainerNodes() invocation between epochs. +type ContainerNodesCache struct { + // mtx protects lastEpoch and containerCache fields. + mtx sync.Mutex + // lastEpoch contains network map epoch for all values in the container cache. + lastEpoch uint64 + // containerCache caches container nodes by ID. It is used to skip `GetContainerNodes` invocation if + // neither netmap nor container has changed. + containerCache simplelru.LRUCache[cid.ID, [][]netmapSDK.NodeInfo] +} + +// defaultContainerCacheSize is the default size for the container cache. +const defaultContainerCacheSize = 10 + +// NewContainerNodesCache creates new cache which saves the result of the ContainerNodes() invocations. +// If size is <= 0, defaultContainerCacheSize (10) is used. +func NewContainerNodesCache(size int) *ContainerNodesCache { + if size <= 0 { + size = defaultContainerCacheSize + } + + cache, _ := simplelru.NewLRU[cid.ID, [][]netmapSDK.NodeInfo](size, nil) // no error + return &ContainerNodesCache{ + containerCache: cache, + } +} + +// ContainerNodes returns the result of nm.ContainerNodes(), possibly from the cache. +func (c *ContainerNodesCache) ContainerNodes(nm *netmapSDK.NetMap, cnr cid.ID, p netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { + c.mtx.Lock() + if nm.Epoch() == c.lastEpoch { + raw, ok := c.containerCache.Get(cnr) + c.mtx.Unlock() + if ok { + return raw, nil + } + } else { + c.lastEpoch = nm.Epoch() + c.containerCache.Purge() + c.mtx.Unlock() + } + + binCnr := make([]byte, sha256.Size) + cnr.Encode(binCnr) + + cn, err := nm.ContainerNodes(p, binCnr) + if err != nil { + return nil, fmt.Errorf("could not get container nodes: %w", err) + } + + c.mtx.Lock() + if c.lastEpoch == nm.Epoch() { + c.containerCache.Add(cnr, cn) + } + c.mtx.Unlock() + return cn, nil +} diff --git a/pkg/services/object_manager/placement/cache_test.go b/pkg/services/object_manager/placement/cache_test.go new file mode 100644 index 0000000000..5816d59fe7 --- /dev/null +++ b/pkg/services/object_manager/placement/cache_test.go @@ -0,0 +1,95 @@ +package placement_test + +import ( + "strconv" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "github.com/stretchr/testify/require" +) + +func TestContainerNodesCache(t *testing.T) { + const size = 3 + + nodes := [6]netmapSDK.NodeInfo{} + for i := range nodes { + nodes[i].SetAttribute("ATTR", strconv.Itoa(i)) + } + + nm := func(epoch uint64, nodes []netmapSDK.NodeInfo) *netmapSDK.NetMap { + var nm netmapSDK.NetMap + nm.SetEpoch(epoch) + nm.SetNodes(nodes) + return &nm + } + + var pp netmapSDK.PlacementPolicy + require.NoError(t, pp.DecodeString("REP 1")) + + t.Run("update netmap on the new epoch", func(t *testing.T) { + c := placement.NewContainerNodesCache(size) + + cnr := cidtest.ID() + res, err := c.ContainerNodes(nm(1, nodes[0:1]), cnr, pp) + require.NoError(t, err) + + // Use other nodes in the argument to ensure the result is taken from cache. + resCached, err := c.ContainerNodes(nm(1, nodes[1:2]), cnr, pp) + require.NoError(t, err) + require.Equal(t, res, resCached) + + // Update epoch, netmap should be purged. + resCached, err = c.ContainerNodes(nm(2, nodes[2:3]), cnr, pp) + require.NoError(t, err) + require.NotEqual(t, res, resCached) + }) + t.Run("cache uses container as a key", func(t *testing.T) { + c := placement.NewContainerNodesCache(size) + + res1, err := c.ContainerNodes(nm(1, nodes[0:1]), cidtest.ID(), pp) + require.NoError(t, err) + + res2, err := c.ContainerNodes(nm(1, nodes[1:2]), cidtest.ID(), pp) + require.NoError(t, err) + + require.NotEqual(t, res1, res2) + }) + t.Run("cache respects size parameter", func(t *testing.T) { + c := placement.NewContainerNodesCache(size) + + nm1 := nm(1, nodes[0:1]) + nm2 := nm(1, nodes[1:2]) + cnr := [size * 2]cid.ID{} + res := [size * 2][][]netmapSDK.NodeInfo{} + for i := 0; i < size*2; i++ { + cnr[i] = cidtest.ID() + + var err error + res[i], err = c.ContainerNodes(nm1, cnr[i], pp) + require.NoError(t, err) + } + + for i := size; i < size*2; i++ { + r, err := c.ContainerNodes(nm2, cnr[i], pp) + require.NoError(t, err) + require.Equal(t, res[i], r) + } + for i := 0; i < size; i++ { + r, err := c.ContainerNodes(nm2, cnr[i], pp) + require.NoError(t, err) + require.NotEqual(t, res[i], r) + } + }) + t.Run("the error is propagated", func(t *testing.T) { + var pp netmapSDK.PlacementPolicy + require.NoError(t, pp.DecodeString("REP 1 SELECT 1 FROM X FILTER ATTR EQ 42 AS X")) + + c := placement.NewContainerNodesCache(size) + _, err := c.ContainerNodes(nm(1, nodes[0:1]), cidtest.ID(), pp) + require.Error(t, err) + }) + +} diff --git a/pkg/services/object_manager/placement/netmap.go b/pkg/services/object_manager/placement/netmap.go index 8163529ed7..1782e27ea3 100644 --- a/pkg/services/object_manager/placement/netmap.go +++ b/pkg/services/object_manager/placement/netmap.go @@ -3,24 +3,16 @@ package placement import ( "crypto/sha256" "fmt" - "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/hashicorp/golang-lru/v2/simplelru" ) type netMapBuilder struct { - nmSrc netmap.Source - // mtx protects lastEpoch and containerCache fields. - mtx sync.Mutex - // lastEpoch contains contains network map epoch for all values in the container cache. - lastEpoch uint64 - // containerCache caches container nodes by ID. It is used to skip `GetContainerNodes` invocation if - // neither netmap nor container has changed. - containerCache simplelru.LRUCache[cid.ID, [][]netmapSDK.NodeInfo] + nmSrc netmap.Source + containerCache *ContainerNodesCache } type netMapSrc struct { @@ -29,22 +21,17 @@ type netMapSrc struct { nm *netmapSDK.NetMap } -// defaultContainerCacheSize is the default size for the container cache. -const defaultContainerCacheSize = 10 - func NewNetworkMapBuilder(nm *netmapSDK.NetMap) Builder { - cache, _ := simplelru.NewLRU[cid.ID, [][]netmapSDK.NodeInfo](defaultContainerCacheSize, nil) // no error return &netMapBuilder{ nmSrc: &netMapSrc{nm: nm}, - containerCache: cache, + containerCache: NewContainerNodesCache(0), } } func NewNetworkMapSourceBuilder(nmSrc netmap.Source) Builder { - cache, _ := simplelru.NewLRU[cid.ID, [][]netmapSDK.NodeInfo](defaultContainerCacheSize, nil) // no error return &netMapBuilder{ nmSrc: nmSrc, - containerCache: cache, + containerCache: NewContainerNodesCache(0), } } @@ -58,33 +45,11 @@ func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.Plac return nil, fmt.Errorf("could not get network map: %w", err) } - binCnr := make([]byte, sha256.Size) - cnr.Encode(binCnr) - - b.mtx.Lock() - if nm.Epoch() == b.lastEpoch { - raw, ok := b.containerCache.Get(cnr) - b.mtx.Unlock() - if ok { - return BuildObjectPlacement(nm, raw, obj) - } - } else { - b.lastEpoch = nm.Epoch() - b.containerCache.Purge() - b.mtx.Unlock() - } - - cn, err := nm.ContainerNodes(p, binCnr) + cn, err := b.containerCache.ContainerNodes(nm, cnr, p) if err != nil { - return nil, fmt.Errorf("could not get container nodes: %w", err) + return nil, err } - b.mtx.Lock() - if b.lastEpoch == nm.Epoch() { - b.containerCache.Add(cnr, cn) - } - b.mtx.Unlock() - return BuildObjectPlacement(nm, cn, obj) } From e5767c90021eb0383db2b6fcde4fb8fed8ce68d0 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 16 Jul 2024 15:20:07 +0300 Subject: [PATCH 0695/1413] [#1250] *: Reformat proto filets with clang-format Signed-off-by: Evgenii Stratonikov --- pkg/services/control/ir/service.proto | 132 +++++++++++++------------- pkg/services/control/ir/types.proto | 24 ++--- pkg/services/tree/service.proto | 38 +++----- pkg/services/tree/types.proto | 14 +-- 4 files changed, 99 insertions(+), 109 deletions(-) diff --git a/pkg/services/control/ir/service.proto b/pkg/services/control/ir/service.proto index 967ff979e9..fa58db568b 100644 --- a/pkg/services/control/ir/service.proto +++ b/pkg/services/control/ir/service.proto @@ -6,106 +6,108 @@ import "pkg/services/control/ir/types.proto"; option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/ir/control"; -// `ControlService` provides an interface for internal work with the Inner Ring node. +// `ControlService` provides an interface for internal work with the Inner Ring +// node. service ControlService { - // Performs health check of the IR node. - rpc HealthCheck (HealthCheckRequest) returns (HealthCheckResponse); - // Forces a new epoch to be signaled by the IR node with high probability. - rpc TickEpoch (TickEpochRequest) returns (TickEpochResponse); - // Forces a node removal to be signaled by the IR node with high probability. - rpc RemoveNode (RemoveNodeRequest) returns (RemoveNodeResponse); - // Forces a container removal to be signaled by the IR node with high probability. - rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse); + // Performs health check of the IR node. + rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse); + // Forces a new epoch to be signaled by the IR node with high probability. + rpc TickEpoch(TickEpochRequest) returns (TickEpochResponse); + // Forces a node removal to be signaled by the IR node with high probability. + rpc RemoveNode(RemoveNodeRequest) returns (RemoveNodeResponse); + // Forces a container removal to be signaled by the IR node with high + // probability. + rpc RemoveContainer(RemoveContainerRequest) returns (RemoveContainerResponse); } // Health check request. message HealthCheckRequest { - // Health check request body. - message Body {} + // Health check request body. + message Body {} - // Body of health check request message. - Body body = 1; + // Body of health check request message. + Body body = 1; - // Body signature. - // Should be signed by node key or one of - // the keys configured by the node. - Signature signature = 2; + // Body signature. + // Should be signed by node key or one of + // the keys configured by the node. + Signature signature = 2; } // Health check response. message HealthCheckResponse { - // Health check response body - message Body { - // Health status of IR node application. - HealthStatus health_status = 1; - } + // Health check response body + message Body { + // Health status of IR node application. + HealthStatus health_status = 1; + } - // Body of health check response message. - Body body = 1; + // Body of health check response message. + Body body = 1; - // Body signature. - Signature signature = 2; + // Body signature. + Signature signature = 2; } message TickEpochRequest { - message Body{ - // Valid until block value override. - uint32 vub = 1; - } + message Body { + // Valid until block value override. + uint32 vub = 1; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } message TickEpochResponse { - message Body{ - // Valid until block value for transaction. - uint32 vub = 1; - } + message Body { + // Valid until block value for transaction. + uint32 vub = 1; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } message RemoveNodeRequest { - message Body{ - bytes key = 1; - // Valid until block value override. - uint32 vub = 2; - } + message Body { + bytes key = 1; + // Valid until block value override. + uint32 vub = 2; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } message RemoveNodeResponse { - message Body{ - // Valid until block value for transaction. - uint32 vub = 1; - } + message Body { + // Valid until block value for transaction. + uint32 vub = 1; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } message RemoveContainerRequest { - message Body{ - bytes container_id = 1; - bytes owner = 2; - // Valid until block value override. - uint32 vub = 3; - } + message Body { + bytes container_id = 1; + bytes owner = 2; + // Valid until block value override. + uint32 vub = 3; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } message RemoveContainerResponse { - message Body{ - // Valid until block value for transaction. - uint32 vub = 1; - } + message Body { + // Valid until block value for transaction. + uint32 vub = 1; + } - Body body = 1; - Signature signature = 2; + Body body = 1; + Signature signature = 2; } diff --git a/pkg/services/control/ir/types.proto b/pkg/services/control/ir/types.proto index a6897fad16..9b6731cf85 100644 --- a/pkg/services/control/ir/types.proto +++ b/pkg/services/control/ir/types.proto @@ -6,24 +6,24 @@ option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/ir/ // Signature of some message. message Signature { - // Public key used for signing. - bytes key = 1 [json_name = "key"]; + // Public key used for signing. + bytes key = 1 [ json_name = "key" ]; - // Binary signature. - bytes sign = 2 [json_name = "signature"]; + // Binary signature. + bytes sign = 2 [ json_name = "signature" ]; } // Health status of the IR application. enum HealthStatus { - // Undefined status, default value. - HEALTH_STATUS_UNDEFINED = 0; + // Undefined status, default value. + HEALTH_STATUS_UNDEFINED = 0; - // IR application is starting. - STARTING = 1; + // IR application is starting. + STARTING = 1; - // IR application is started and serves all services. - READY = 2; + // IR application is started and serves all services. + READY = 2; - // IR application is shutting down. - SHUTTING_DOWN = 3; + // IR application is shutting down. + SHUTTING_DOWN = 3; } diff --git a/pkg/services/tree/service.proto b/pkg/services/tree/service.proto index ec63d88ec8..582e748470 100644 --- a/pkg/services/tree/service.proto +++ b/pkg/services/tree/service.proto @@ -28,25 +28,25 @@ service TreeService { // Otherwise, a request is denied. // Add adds new node to the tree. Invoked by a client. - rpc Add (AddRequest) returns (AddResponse); + rpc Add(AddRequest) returns (AddResponse); // AddByPath adds new node to the tree by path. Invoked by a client. - rpc AddByPath (AddByPathRequest) returns (AddByPathResponse); + rpc AddByPath(AddByPathRequest) returns (AddByPathResponse); // Remove removes node from the tree. Invoked by a client. - rpc Remove (RemoveRequest) returns (RemoveResponse); + rpc Remove(RemoveRequest) returns (RemoveResponse); // Move moves node from one parent to another. Invoked by a client. - rpc Move (MoveRequest) returns (MoveResponse); + rpc Move(MoveRequest) returns (MoveResponse); // GetNodeByPath returns list of IDs corresponding to a specific filepath. - rpc GetNodeByPath (GetNodeByPathRequest) returns (GetNodeByPathResponse); + rpc GetNodeByPath(GetNodeByPathRequest) returns (GetNodeByPathResponse); // GetSubTree returns tree corresponding to a specific node. - rpc GetSubTree (GetSubTreeRequest) returns (stream GetSubTreeResponse); + rpc GetSubTree(GetSubTreeRequest) returns (stream GetSubTreeResponse); // TreeList return list of the existing trees in the container. - rpc TreeList (TreeListRequest) returns (TreeListResponse); + rpc TreeList(TreeListRequest) returns (TreeListResponse); /* Synchronization API */ // Apply pushes log operation from another node to the current. // The request must be signed by a container node. - rpc Apply (ApplyRequest) returns (ApplyResponse); + rpc Apply(ApplyRequest) returns (ApplyResponse); // GetOpLog returns a stream of logged operations starting from some height. rpc GetOpLog(GetOpLogRequest) returns (stream GetOpLogResponse); // Healthcheck is a dummy rpc to check service availability @@ -85,7 +85,6 @@ message AddResponse { Signature signature = 2; }; - message AddByPathRequest { message Body { // Container ID in V2 format. @@ -122,7 +121,6 @@ message AddByPathResponse { Signature signature = 2; }; - message RemoveRequest { message Body { // Container ID in V2 format. @@ -142,8 +140,7 @@ message RemoveRequest { } message RemoveResponse { - message Body { - } + message Body {} // Response body. Body body = 1; @@ -151,7 +148,6 @@ message RemoveResponse { Signature signature = 2; }; - message MoveRequest { message Body { // TODO import neo.fs.v2.refs.ContainerID directly. @@ -176,8 +172,7 @@ message MoveRequest { } message MoveResponse { - message Body { - } + message Body {} // Response body. Body body = 1; @@ -185,7 +180,6 @@ message MoveResponse { Signature signature = 2; }; - message GetNodeByPathRequest { message Body { // Container ID in V2 format. @@ -235,7 +229,6 @@ message GetNodeByPathResponse { Signature signature = 2; }; - message GetSubTreeRequest { message Body { message Order { @@ -307,7 +300,6 @@ message TreeListResponse { Signature signature = 2; } - message ApplyRequest { message Body { // Container ID in V2 format. @@ -325,8 +317,7 @@ message ApplyRequest { } message ApplyResponse { - message Body { - } + message Body {} // Response body. Body body = 1; @@ -334,7 +325,6 @@ message ApplyResponse { Signature signature = 2; }; - message GetOpLogRequest { message Body { // Container ID in V2 format. @@ -366,8 +356,7 @@ message GetOpLogResponse { }; message HealthcheckResponse { - message Body { - } + message Body {} // Response body. Body body = 1; @@ -376,8 +365,7 @@ message HealthcheckResponse { }; message HealthcheckRequest { - message Body { - } + message Body {} // Request body. Body body = 1; diff --git a/pkg/services/tree/types.proto b/pkg/services/tree/types.proto index 23d73b9ad1..f122c7cf4c 100644 --- a/pkg/services/tree/types.proto +++ b/pkg/services/tree/types.proto @@ -10,25 +10,25 @@ option go_package = "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tre // KeyValue represents key-value pair attached to an object. message KeyValue { // Attribute name. - string key = 1 [json_name = "key"]; + string key = 1 [ json_name = "key" ]; // Attribute value. - bytes value = 2 [json_name = "value"]; + bytes value = 2 [ json_name = "value" ]; } // LogMove represents log-entry for a single move operation. message LogMove { // ID of the parent node. - uint64 parent_id = 1 [json_name = "parentID"]; + uint64 parent_id = 1 [ json_name = "parentID" ]; // Node meta information, including operation timestamp. - bytes meta = 2 [json_name = "meta"]; + bytes meta = 2 [ json_name = "meta" ]; // ID of the node to move. - uint64 child_id = 3 [json_name = "childID"]; + uint64 child_id = 3 [ json_name = "childID" ]; } // Signature of a message. message Signature { // Serialized public key as defined in FrostFS API. - bytes key = 1 [json_name = "key"]; + bytes key = 1 [ json_name = "key" ]; // Signature of a message body. - bytes sign = 2 [json_name = "signature"]; + bytes sign = 2 [ json_name = "signature" ]; } From 3940bc17c10473440cb78ea81553d8fe42d187a1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 10 Jul 2024 09:30:01 +0300 Subject: [PATCH 0696/1413] [#1251] pilorama: Allow traversing multiple branches in parallel Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/tree/move.go | 2 +- cmd/frostfs-cli/modules/tree/subtree.go | 15 +- pkg/local_object_storage/engine/tree.go | 5 +- pkg/local_object_storage/pilorama/boltdb.go | 113 +++--- pkg/local_object_storage/pilorama/forest.go | 49 +-- .../pilorama/forest_test.go | 34 +- pkg/local_object_storage/pilorama/heap.go | 4 +- .../pilorama/interface.go | 2 +- pkg/local_object_storage/pilorama/meta.go | 6 +- .../pilorama/multinode.go | 49 +++ .../pilorama/split_test.go | 57 +++ pkg/local_object_storage/shard/tree.go | 3 +- pkg/services/tree/getsubtree_test.go | 35 +- pkg/services/tree/service.go | 92 +++-- pkg/services/tree/service.pb.go | 326 +++++++++--------- pkg/services/tree/service.proto | 10 +- pkg/services/tree/service_frostfs.pb.go | 53 ++- pkg/services/tree/service_grpc.pb.go | 44 ++- 18 files changed, 571 insertions(+), 328 deletions(-) create mode 100644 pkg/local_object_storage/pilorama/multinode.go diff --git a/cmd/frostfs-cli/modules/tree/move.go b/cmd/frostfs-cli/modules/tree/move.go index 84b2fb80e7..95516940c3 100644 --- a/cmd/frostfs-cli/modules/tree/move.go +++ b/cmd/frostfs-cli/modules/tree/move.go @@ -66,7 +66,7 @@ func move(cmd *cobra.Command, _ []string) { Body: &tree.GetSubTreeRequest_Body{ ContainerId: rawCID, TreeId: tid, - RootId: nid, + RootId: []uint64{nid}, Depth: 1, BearerToken: bt, }, diff --git a/cmd/frostfs-cli/modules/tree/subtree.go b/cmd/frostfs-cli/modules/tree/subtree.go index 64cb351ec0..e58a13fd66 100644 --- a/cmd/frostfs-cli/modules/tree/subtree.go +++ b/cmd/frostfs-cli/modules/tree/subtree.go @@ -68,7 +68,7 @@ func getSubTree(cmd *cobra.Command, _ []string) { Body: &tree.GetSubTreeRequest_Body{ ContainerId: rawCID, TreeId: tid, - RootId: rid, + RootId: []uint64{rid}, Depth: depth, BearerToken: bt, }, @@ -83,10 +83,15 @@ func getSubTree(cmd *cobra.Command, _ []string) { for ; err == nil; subtreeResp, err = resp.Recv() { b := subtreeResp.GetBody() - cmd.Printf("Node ID: %d\n", b.GetNodeId()) - - cmd.Println("\tParent ID: ", b.GetParentId()) - cmd.Println("\tTimestamp: ", b.GetTimestamp()) + if len(b.GetNodeId()) == 1 { + cmd.Printf("Node ID: %d\n", b.GetNodeId()) + cmd.Println("\tParent ID: ", b.GetParentId()) + cmd.Println("\tTimestamp: ", b.GetTimestamp()) + } else { + cmd.Printf("Node IDs: %v\n", b.GetNodeId()) + cmd.Println("\tParent IDs: ", b.GetParentId()) + cmd.Println("\tTimestamps: ", b.GetTimestamp()) + } if meta := b.GetMeta(); len(meta) > 0 { cmd.Println("\tMeta pairs: ") diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index 8bacdba767..39122628f2 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -210,18 +210,17 @@ func (e *StorageEngine) TreeGetChildren(ctx context.Context, cid cidSDK.ID, tree } // TreeSortedByFilename implements the pilorama.Forest interface. -func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.Node, last *string, count int) ([]pilorama.NodeInfo, *string, error) { +func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.MultiNode, last *string, count int) ([]pilorama.MultiNodeInfo, *string, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.TreeSortedByFilename", trace.WithAttributes( attribute.String("container_id", cid.EncodeToString()), attribute.String("tree_id", treeID), - attribute.String("node_id", strconv.FormatUint(nodeID, 10)), ), ) defer span.End() var err error - var nodes []pilorama.NodeInfo + var nodes []pilorama.MultiNodeInfo var cursor *string for _, sh := range e.sortShards(cid) { nodes, cursor, err = sh.TreeSortedByFilename(ctx, cid, treeID, nodeID, last, count) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index ee28df426a..48363ceacd 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -9,6 +9,7 @@ import ( "math/rand" "os" "path/filepath" + "slices" "sort" "strconv" "sync" @@ -990,23 +991,26 @@ func (t *boltForest) TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID stri return m, parentID, metaerr.Wrap(err) } -func (t *boltForest) hasFewChildren(b *bbolt.Bucket, nodeID Node, threshold int) bool { +func (t *boltForest) hasFewChildren(b *bbolt.Bucket, nodeIDs MultiNode, threshold int) bool { key := make([]byte, 9) key[0] = 'c' - binary.LittleEndian.PutUint64(key[1:], nodeID) count := 0 - c := b.Cursor() - for k, _ := c.Seek(key); len(k) == childrenKeySize && binary.LittleEndian.Uint64(k[1:]) == nodeID; k, _ = c.Next() { - if count++; count > threshold { - return false + for _, nodeID := range nodeIDs { + binary.LittleEndian.PutUint64(key[1:], nodeID) + + c := b.Cursor() + for k, _ := c.Seek(key); len(k) == childrenKeySize && binary.LittleEndian.Uint64(k[1:]) == nodeID; k, _ = c.Next() { + if count++; count > threshold { + return false + } } } return true } // TreeSortedByFilename implements the Forest interface. -func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node, last *string, count int) ([]NodeInfo, *string, error) { +func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeIDs MultiNode, last *string, count int) ([]MultiNodeInfo, *string, error) { var ( startedAt = time.Now() success = false @@ -1019,7 +1023,6 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr trace.WithAttributes( attribute.String("container_id", cid.EncodeToString()), attribute.String("tree_id", treeID), - attribute.String("node_id", strconv.FormatUint(nodeID, 10)), ), ) defer span.End() @@ -1030,6 +1033,9 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr if t.mode.NoMetabase() { return nil, last, ErrDegradedMode } + if len(nodeIDs) == 0 { + return nil, last, errors.New("empty node list") + } h := newHeap(last, count) key := make([]byte, 9) @@ -1048,20 +1054,22 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr // If the node is a leaf, we could scan all filenames in the tree. // To prevent this we first count the number of children: if it is less than // the number of nodes we need to return, fallback to TreeGetChildren() implementation. - if fewChildren = t.hasFewChildren(b, nodeID, count); fewChildren { + if fewChildren = t.hasFewChildren(b, nodeIDs, count); fewChildren { var err error - result, err = t.getChildren(b, nodeID) + result, err = t.getChildren(b, nodeIDs) return err } - t.fillSortedChildren(b, nodeID, h) + t.fillSortedChildren(b, nodeIDs, h) for info, ok := h.pop(); ok; info, ok = h.pop() { - childInfo, err := t.getChildInfo(b, key, info.id) - if err != nil { - return err + for _, id := range info.id { + childInfo, err := t.getChildInfo(b, key, id) + if err != nil { + return err + } + result = append(result, childInfo) } - result = append(result, childInfo) } return nil }) @@ -1074,11 +1082,15 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr if fewChildren { result = sortAndCut(result, last) } - if len(result) != 0 { - s := string(result[len(result)-1].Meta.GetAttr(AttributeFilename)) + res := mergeNodeInfos(result) + if len(res) > count { + res = res[:count] + } + if len(res) != 0 { + s := string(findAttr(res[len(res)-1].Meta, AttributeFilename)) last = &s } - return result, last, metaerr.Wrap(err) + return res, last, metaerr.Wrap(err) } func sortAndCut(result []NodeInfo, last *string) []NodeInfo { @@ -1109,37 +1121,56 @@ func (t *boltForest) getChildInfo(b *bbolt.Bucket, key []byte, childID Node) (No return childInfo, nil } -func (t *boltForest) fillSortedChildren(b *bbolt.Bucket, nodeID Node, h *fixedHeap) { +func (t *boltForest) fillSortedChildren(b *bbolt.Bucket, nodeIDs MultiNode, h *fixedHeap) { c := b.Cursor() prefix := internalKeyPrefix(nil, AttributeFilename) length := uint16(0) count := 0 + + var nodes []uint64 + var lastFilename *string for k, _ := c.Seek(prefix); len(k) > 0 && k[0] == 'i'; k, _ = c.Next() { if len(k) < len(prefix)+2+16 { continue } parentID := binary.LittleEndian.Uint64(k[len(k)-16:]) - if parentID != nodeID { + if !slices.Contains(nodeIDs, parentID) { continue } actualLength := binary.LittleEndian.Uint16(k[len(prefix):]) childID := binary.LittleEndian.Uint64(k[len(k)-8:]) filename := string(k[len(prefix)+2 : len(k)-16]) - processed := h.push(childID, filename) - if actualLength != length { - length = actualLength - count = 1 - } else if processed { - if count++; count > h.count { - length = actualLength + 1 - c.Seek(append(prefix, byte(length), byte(length>>8))) - c.Prev() // c.Next() will be performed by for loop + + if lastFilename == nil { + lastFilename = &filename + nodes = append(nodes, childID) + } else if *lastFilename == filename { + nodes = append(nodes, childID) + } else { + processed := h.push(nodes, *lastFilename) + nodes = MultiNode{childID} + lastFilename = &filename + if actualLength != length { + length = actualLength + count = 1 + } else if processed { + if count++; count > h.count { + lastFilename = nil + nodes = nil + length = actualLength + 1 + c.Seek(append(prefix, byte(length), byte(length>>8))) + c.Prev() // c.Next() will be performed by for loop + } } } } + + if len(nodes) != 0 && lastFilename != nil { + h.push(nodes, *lastFilename) + } } // TreeGetChildren implements the Forest interface. @@ -1179,28 +1210,30 @@ func (t *boltForest) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID b := treeRoot.Bucket(dataBucket) var err error - result, err = t.getChildren(b, nodeID) + result, err = t.getChildren(b, []Node{nodeID}) return err }) success = err == nil return result, metaerr.Wrap(err) } -func (t *boltForest) getChildren(b *bbolt.Bucket, nodeID Node) ([]NodeInfo, error) { +func (t *boltForest) getChildren(b *bbolt.Bucket, nodeIDs MultiNode) ([]NodeInfo, error) { var result []NodeInfo key := make([]byte, 9) - key[0] = 'c' - binary.LittleEndian.PutUint64(key[1:], nodeID) + for _, nodeID := range nodeIDs { + key[0] = 'c' + binary.LittleEndian.PutUint64(key[1:], nodeID) - c := b.Cursor() - for k, _ := c.Seek(key); len(k) == childrenKeySize && binary.LittleEndian.Uint64(k[1:]) == nodeID; k, _ = c.Next() { - childID := binary.LittleEndian.Uint64(k[9:]) - childInfo, err := t.getChildInfo(b, key, childID) - if err != nil { - return nil, err + c := b.Cursor() + for k, _ := c.Seek(key); len(k) == childrenKeySize && binary.LittleEndian.Uint64(k[1:]) == nodeID; k, _ = c.Next() { + childID := binary.LittleEndian.Uint64(k[9:]) + childInfo, err := t.getChildInfo(b, key, childID) + if err != nil { + return nil, err + } + result = append(result, childInfo) } - result = append(result, childInfo) } return result, nil } diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index b45a77b99d..78503bada6 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -156,7 +156,7 @@ func (f *memoryForest) TreeGetMeta(_ context.Context, cid cid.ID, treeID string, } // TreeSortedByFilename implements the Forest interface. -func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeID string, nodeID Node, start *string, count int) ([]NodeInfo, *string, error) { +func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeID string, nodeIDs MultiNode, start *string, count int) ([]MultiNodeInfo, *string, error) { fullID := cid.String() + "/" + treeID s, ok := f.treeMap[fullID] if !ok { @@ -166,40 +166,45 @@ func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeI return nil, start, nil } - children := s.tree.getChildren(nodeID) - res := make([]NodeInfo, 0, len(children)) - for _, childID := range children { - var found bool - for _, kv := range s.infoMap[childID].Meta.Items { - if kv.Key == AttributeFilename { - found = true - break + var res []NodeInfo + + for _, nodeID := range nodeIDs { + children := s.tree.getChildren(nodeID) + for _, childID := range children { + var found bool + for _, kv := range s.infoMap[childID].Meta.Items { + if kv.Key == AttributeFilename { + found = true + break + } } + if !found { + continue + } + res = append(res, NodeInfo{ + ID: childID, + Meta: s.infoMap[childID].Meta, + ParentID: s.infoMap[childID].Parent, + }) } - if !found { - continue - } - res = append(res, NodeInfo{ - ID: childID, - Meta: s.infoMap[childID].Meta, - ParentID: s.infoMap[childID].Parent, - }) } if len(res) == 0 { - return res, start, nil + return nil, start, nil } sort.Slice(res, func(i, j int) bool { return bytes.Compare(res[i].Meta.GetAttr(AttributeFilename), res[j].Meta.GetAttr(AttributeFilename)) == -1 }) - for i := range res { - if start == nil || string(res[i].Meta.GetAttr(AttributeFilename)) > *start { + + r := mergeNodeInfos(res) + for i := range r { + if start == nil || string(findAttr(r[i].Meta, AttributeFilename)) > *start { finish := i + count if len(res) < finish { finish = len(res) } - last := string(res[finish-1].Meta.GetAttr(AttributeFilename)) - return res[i:finish], &last, nil + last := string(findAttr(r[finish-1].Meta, AttributeFilename)) + return r[i:finish], &last, nil } } last := string(res[len(res)-1].Meta.GetAttr(AttributeFilename)) diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 9da0177cca..001d095c80 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -215,7 +215,7 @@ func BenchmarkForestSortedIteration(b *testing.B) { b.Run(providers[i].name+",root", func(b *testing.B) { for i := 0; i < b.N; i++ { - res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, RootID, nil, 100) + res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, MultiNode{RootID}, nil, 100) if err != nil || len(res) != 100 { b.Fatalf("err %v, count %d", err, len(res)) } @@ -223,7 +223,7 @@ func BenchmarkForestSortedIteration(b *testing.B) { }) b.Run(providers[i].name+",leaf", func(b *testing.B) { for i := 0; i < b.N; i++ { - res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, 1, nil, 100) + res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, MultiNode{1}, nil, 100) if err != nil || len(res) != 0 { b.FailNow() } @@ -266,9 +266,9 @@ func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { treeAdd(t, i+1, strconv.Itoa(i+1)) } - var result []NodeInfo + var result []MultiNodeInfo treeAppend := func(t *testing.T, last *string, count int) *string { - res, cursor, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, RootID, last, count) + res, cursor, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, MultiNode{RootID}, last, count) require.NoError(t, err) result = append(result, res...) return cursor @@ -282,11 +282,11 @@ func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { require.Len(t, result, count) for i := range result { - require.Equal(t, RootID+uint64(i+1), result[i].ID) + require.Equal(t, MultiNode{RootID + uint64(i+1)}, result[i].Children) if i == 0 { - require.Equal(t, "", string(result[i].Meta.GetAttr(AttributeFilename))) + require.Equal(t, "", string(findAttr(result[i].Meta, AttributeFilename))) } else { - require.Equal(t, strconv.Itoa(RootID+i+1), string(result[i].Meta.GetAttr(AttributeFilename))) + require.Equal(t, strconv.Itoa(RootID+i+1), string(findAttr(result[i].Meta, AttributeFilename))) } } } @@ -318,12 +318,12 @@ func testForestTreeSortedByFilename(t *testing.T, s ForestStorage) { require.NoError(t, err) } - expectAttributes := func(t *testing.T, attr string, expected []string, res []NodeInfo) { + expectAttributes := func(t *testing.T, attr string, expected []string, res []MultiNodeInfo) { require.Equal(t, len(expected), len(res)) actual := make([]string, len(res)) for i := range actual { - actual[i] = string(res[i].Meta.GetAttr(attr)) + actual[i] = string(findAttr(res[i].Meta, attr)) } require.Equal(t, expected, actual) } @@ -345,40 +345,40 @@ func testForestTreeSortedByFilename(t *testing.T, s ForestStorage) { treeAddByPath(t, items[i]) } - getChildren := func(t *testing.T, id Node) []NodeInfo { + getChildren := func(t *testing.T, id MultiNode) []MultiNodeInfo { res, _, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, id, nil, len(items)) require.NoError(t, err) return res } - res := getChildren(t, RootID) + res := getChildren(t, MultiNode{RootID}) expectAttributes(t, AttributeFilename, []string{"a", "b", "c"}, res) expectAttributes(t, controlAttr, []string{"", "", "c"}, res) { - ra := getChildren(t, res[0].ID) + ra := getChildren(t, res[0].Children) expectAttributes(t, AttributeFilename, []string{"bbb"}, ra) expectAttributes(t, controlAttr, []string{""}, ra) - rabbb := getChildren(t, ra[0].ID) + rabbb := getChildren(t, ra[0].Children) expectAttributes(t, AttributeFilename, []string{"ccc", "xxx", "z"}, rabbb) expectAttributes(t, controlAttr, []string{"a/bbb/ccc", "a/bbb/xxx", "a/bbb/z"}, rabbb) } { - rb := getChildren(t, res[1].ID) + rb := getChildren(t, res[1].Children) expectAttributes(t, AttributeFilename, []string{"bbb", "xxx"}, rb) expectAttributes(t, controlAttr, []string{"", ""}, rb) - rbbbb := getChildren(t, rb[0].ID) + rbbbb := getChildren(t, rb[0].Children) expectAttributes(t, AttributeFilename, []string{"ccc"}, rbbbb) expectAttributes(t, controlAttr, []string{"b/bbb/ccc"}, rbbbb) - rbxxx := getChildren(t, rb[1].ID) + rbxxx := getChildren(t, rb[1].Children) expectAttributes(t, AttributeFilename, []string{"z"}, rbxxx) expectAttributes(t, controlAttr, []string{"b/xxx/z"}, rbxxx) } { - rc := getChildren(t, res[2].ID) + rc := getChildren(t, res[2].Children) require.Len(t, rc, 0) } } diff --git a/pkg/local_object_storage/pilorama/heap.go b/pkg/local_object_storage/pilorama/heap.go index e8a21e221c..ec57b9e1fd 100644 --- a/pkg/local_object_storage/pilorama/heap.go +++ b/pkg/local_object_storage/pilorama/heap.go @@ -5,7 +5,7 @@ import ( ) type heapInfo struct { - id Node + id MultiNode filename string } @@ -44,7 +44,7 @@ func newHeap(start *string, count int) *fixedHeap { } } -func (h *fixedHeap) push(id Node, filename string) bool { +func (h *fixedHeap) push(id MultiNode, filename string) bool { if h.start != nil && filename <= *h.start { return false } diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index f7f5a85b1b..61a3849bf6 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -35,7 +35,7 @@ type Forest interface { TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node) ([]NodeInfo, error) // TreeSortedByFilename returns children of the node with the specified ID. The nodes are sorted by the filename attribute.. // Should return ErrTreeNotFound if the tree is not found, and empty result if the node is not in the tree. - TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node, last *string, count int) ([]NodeInfo, *string, error) + TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID MultiNode, last *string, count int) ([]MultiNodeInfo, *string, error) // TreeGetOpLog returns first log operation stored at or above the height. // In case no such operation is found, empty Move and nil error should be returned. TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID string, height uint64) (Move, error) diff --git a/pkg/local_object_storage/pilorama/meta.go b/pkg/local_object_storage/pilorama/meta.go index 49b7f64774..45e9c2f790 100644 --- a/pkg/local_object_storage/pilorama/meta.go +++ b/pkg/local_object_storage/pilorama/meta.go @@ -21,7 +21,11 @@ func (x Meta) Bytes() []byte { } func (x Meta) GetAttr(name string) []byte { - for _, kv := range x.Items { + return findAttr(x.Items, name) +} + +func findAttr(ms []KeyValue, name string) []byte { + for _, kv := range ms { if kv.Key == name { return kv.Value } diff --git a/pkg/local_object_storage/pilorama/multinode.go b/pkg/local_object_storage/pilorama/multinode.go new file mode 100644 index 0000000000..106ba6ae9c --- /dev/null +++ b/pkg/local_object_storage/pilorama/multinode.go @@ -0,0 +1,49 @@ +package pilorama + +import "bytes" + +// MultiNode represents a group of internal nodes accessible by the same path, but having different id. +type MultiNode []Node + +// MultiNodeInfo represents a group of internal nodes accessible by the same path, but having different id. +type MultiNodeInfo struct { + Children MultiNode + Parents MultiNode + Timestamps []uint64 + Meta []KeyValue +} + +func (r *MultiNodeInfo) Add(info NodeInfo) bool { + if !isInternal(info.Meta.Items) || !isInternal(r.Meta) || + !bytes.Equal(r.Meta[0].Value, info.Meta.Items[0].Value) { + return false + } + + r.Children = append(r.Children, info.ID) + r.Parents = append(r.Parents, info.ParentID) + r.Timestamps = append(r.Timestamps, info.Meta.Time) + return true +} + +func (n NodeInfo) ToMultiNode() MultiNodeInfo { + return MultiNodeInfo{ + Children: MultiNode{n.ID}, + Parents: MultiNode{n.ParentID}, + Timestamps: []uint64{n.Meta.Time}, + Meta: n.Meta.Items, + } +} + +func isInternal(m []KeyValue) bool { + return len(m) == 1 && m[0].Key == AttributeFilename +} + +func mergeNodeInfos(ns []NodeInfo) []MultiNodeInfo { + var r []MultiNodeInfo + for _, info := range ns { + if len(r) == 0 || !r[len(r)-1].Add(info) { + r = append(r, info.ToMultiNode()) + } + } + return r +} diff --git a/pkg/local_object_storage/pilorama/split_test.go b/pkg/local_object_storage/pilorama/split_test.go index 3bd581ce6e..54c2b90a65 100644 --- a/pkg/local_object_storage/pilorama/split_test.go +++ b/pkg/local_object_storage/pilorama/split_test.go @@ -95,4 +95,61 @@ func testDuplicateDirectory(t *testing.T, f Forest) { require.Equal(t, []byte{4}, testGetByPath(t, "dir1/dir3/value3")) require.Equal(t, []byte{8}, testGetByPath(t, "dir1/dir3/value4")) require.Equal(t, []byte{10}, testGetByPath(t, "value0")) + + testSortedByFilename := func(t *testing.T, root MultiNode, last *string, batchSize int) ([]MultiNodeInfo, *string) { + res, last, err := f.TreeSortedByFilename(context.Background(), d.CID, treeID, root, last, batchSize) + require.NoError(t, err) + return res, last + } + + t.Run("test sorted listing, full children branch", func(t *testing.T) { + t.Run("big batch size", func(t *testing.T) { + res, _ := testSortedByFilename(t, MultiNode{RootID}, nil, 10) + require.Equal(t, 3, len(res)) + require.Equal(t, MultiNode{1, 5}, res[0].Children) + require.Equal(t, MultiNode{9}, res[1].Children) + require.Equal(t, MultiNode{10}, res[2].Children) + + t.Run("multi-root", func(t *testing.T) { + res, _ := testSortedByFilename(t, MultiNode{1, 5}, nil, 10) + require.Equal(t, 3, len(res)) + require.Equal(t, MultiNode{3, 7}, res[0].Children) + require.Equal(t, MultiNode{2}, res[1].Children) + require.Equal(t, MultiNode{6}, res[2].Children) + }) + }) + t.Run("small batch size", func(t *testing.T) { + res, last := testSortedByFilename(t, MultiNode{RootID}, nil, 1) + require.Equal(t, 1, len(res)) + require.Equal(t, MultiNode{1, 5}, res[0].Children) + + res, last = testSortedByFilename(t, MultiNode{RootID}, last, 1) + require.Equal(t, 1, len(res)) + require.Equal(t, MultiNode{9}, res[0].Children) + + res, last = testSortedByFilename(t, MultiNode{RootID}, last, 1) + require.Equal(t, 1, len(res)) + require.Equal(t, MultiNode{10}, res[0].Children) + + res, _ = testSortedByFilename(t, MultiNode{RootID}, last, 1) + require.Equal(t, 0, len(res)) + + t.Run("multi-root", func(t *testing.T) { + res, last := testSortedByFilename(t, MultiNode{1, 5}, nil, 1) + require.Equal(t, 1, len(res)) + require.Equal(t, MultiNode{3, 7}, res[0].Children) + + res, last = testSortedByFilename(t, MultiNode{1, 5}, last, 1) + require.Equal(t, 1, len(res)) + require.Equal(t, MultiNode{2}, res[0].Children) + + res, last = testSortedByFilename(t, MultiNode{1, 5}, last, 1) + require.Equal(t, 1, len(res)) + require.Equal(t, MultiNode{6}, res[0].Children) + + res, _ = testSortedByFilename(t, MultiNode{RootID}, last, 1) + require.Equal(t, 0, len(res)) + }) + }) + }) } diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index e92a61e5b7..26dc8ec1eb 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -184,13 +184,12 @@ func (s *Shard) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID strin } // TreeSortedByFilename implements the pilorama.Forest interface. -func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.Node, last *string, count int) ([]pilorama.NodeInfo, *string, error) { +func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.MultiNode, last *string, count int) ([]pilorama.MultiNodeInfo, *string, error) { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeSortedByFilename", trace.WithAttributes( attribute.String("shard_id", s.ID().String()), attribute.String("container_id", cid.EncodeToString()), attribute.String("tree_id", treeID), - attribute.String("node_id", strconv.FormatUint(nodeID, 10)), ), ) defer span.End() diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 305c2bac94..677431889d 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -48,7 +48,7 @@ func TestGetSubTree(t *testing.T) { acc := subTreeAcc{errIndex: errIndex} err := getSubTree(context.Background(), &acc, d.CID, &GetSubTreeRequest_Body{ TreeId: treeID, - RootId: rootID, + RootId: []uint64{rootID}, Depth: depth, }, p) if errIndex == -1 { @@ -58,12 +58,12 @@ func TestGetSubTree(t *testing.T) { } // GetSubTree must return child only after is has returned the parent. - require.Equal(t, rootID, acc.seen[0].Body.NodeId) + require.Equal(t, rootID, acc.seen[0].Body.NodeId[0]) loop: for i := 1; i < len(acc.seen); i++ { parent := acc.seen[i].Body.ParentId for j := 0; j < i; j++ { - if acc.seen[j].Body.NodeId == parent { + if acc.seen[j].Body.NodeId[0] == parent[0] { continue loop } } @@ -73,16 +73,16 @@ func TestGetSubTree(t *testing.T) { // GetSubTree must return valid meta. for i := range acc.seen { b := acc.seen[i].Body - meta, node, err := p.TreeGetMeta(context.Background(), d.CID, treeID, b.NodeId) + meta, node, err := p.TreeGetMeta(context.Background(), d.CID, treeID, b.NodeId[0]) require.NoError(t, err) - require.Equal(t, node, b.ParentId) - require.Equal(t, meta.Time, b.Timestamp) + require.Equal(t, node, b.ParentId[0]) + require.Equal(t, meta.Time, b.Timestamp[0]) require.Equal(t, metaToProto(meta.Items), b.Meta) } ordered := make([]uint64, len(acc.seen)) for i := range acc.seen { - ordered[i] = acc.seen[i].Body.NodeId + ordered[i] = acc.seen[i].Body.NodeId[0] } return ordered } @@ -184,7 +184,7 @@ func testGetSubTreeOrderAsc(t *testing.T, p pilorama.ForestStorage) { } found := false for j := range tree { - if acc.seen[i].Body.NodeId == tree[j].id { + if acc.seen[i].Body.NodeId[0] == tree[j].id { found = true paths = append(paths, path.Join(tree[j].path...)) } @@ -205,7 +205,7 @@ func testGetSubTreeOrderAsc(t *testing.T, p pilorama.ForestStorage) { }, p) require.NoError(t, err) require.Len(t, acc.seen, 1) - require.Equal(t, uint64(0), acc.seen[0].Body.NodeId) + require.Equal(t, uint64(0), acc.seen[0].Body.NodeId[0]) }) t.Run("depth=2", func(t *testing.T) { acc := subTreeAcc{errIndex: -1} @@ -218,15 +218,16 @@ func testGetSubTreeOrderAsc(t *testing.T, p pilorama.ForestStorage) { }, p) require.NoError(t, err) require.Len(t, acc.seen, 3) - require.Equal(t, uint64(0), acc.seen[0].Body.NodeId) - require.Equal(t, uint64(0), acc.seen[1].GetBody().GetParentId()) - require.Equal(t, uint64(0), acc.seen[2].GetBody().GetParentId()) + require.Equal(t, uint64(0), acc.seen[0].Body.NodeId[0]) + require.Equal(t, uint64(0), acc.seen[1].GetBody().GetParentId()[0]) + require.Equal(t, uint64(0), acc.seen[2].GetBody().GetParentId()[0]) }) } var ( errSubTreeSend = errors.New("send finished with error") errSubTreeSendAfterError = errors.New("send was invoked after an error occurred") + errInvalidResponse = errors.New("send got invalid response") ) type subTreeAcc struct { @@ -239,6 +240,16 @@ type subTreeAcc struct { var _ TreeService_GetSubTreeServer = &subTreeAcc{} func (s *subTreeAcc) Send(r *GetSubTreeResponse) error { + b := r.GetBody() + if len(b.GetNodeId()) > 1 { + return errInvalidResponse + } + if len(b.GetParentId()) > 1 { + return errInvalidResponse + } + if len(b.GetTimestamp()) > 1 { + return errInvalidResponse + } s.seen = append(s.seen, r) if s.errIndex >= 0 { if len(s.seen) == s.errIndex+1 { diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 85f5314660..2012f53d28 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -16,6 +16,8 @@ import ( netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/panjf2000/ants/v2" "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) // Service represents tree-service capable of working with multiple @@ -440,29 +442,50 @@ func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeS return getSubTree(srv.Context(), srv, cid, b, s.forest) } +type stackItem struct { + values []pilorama.MultiNodeInfo + parent pilorama.MultiNode + last *string +} + func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid cidSDK.ID, b *GetSubTreeRequest_Body, forest pilorama.Forest) error { const batchSize = 1000 - type stackItem struct { - values []pilorama.NodeInfo - parent pilorama.Node - last *string + // For backward compatibility. + rootIDs := b.GetRootId() + if len(rootIDs) == 0 { + rootIDs = []uint64{0} } // Traverse the tree in a DFS manner. Because we need to support arbitrary depth, // recursive implementation is not suitable here, so we maintain explicit stack. - m, p, err := forest.TreeGetMeta(ctx, cid, b.GetTreeId(), b.GetRootId()) - if err != nil { - return err + var ms []pilorama.KeyValue + var ps []uint64 + var ts []uint64 + for _, rootID := range rootIDs { + m, p, err := forest.TreeGetMeta(ctx, cid, b.GetTreeId(), rootID) + if err != nil { + return err + } + if ms == nil { + ms = m.Items + } else { + if len(m.Items) != 1 { + return status.Error(codes.InvalidArgument, "multiple non-internal nodes provided") + } + } + ts = append(ts, m.Time) + ps = append(ps, p) } stack := []stackItem{{ - values: []pilorama.NodeInfo{{ - ID: b.GetRootId(), - Meta: m, - ParentID: p, + values: []pilorama.MultiNodeInfo{{ + Children: rootIDs, + Timestamps: ts, + Meta: ms, + Parents: ps, }}, - parent: p, + parent: ps, }} for { @@ -486,30 +509,20 @@ func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid } } - node := stack[len(stack)-1].values[0] - stack[len(stack)-1].values = stack[len(stack)-1].values[1:] - - err = srv.Send(&GetSubTreeResponse{ - Body: &GetSubTreeResponse_Body{ - NodeId: node.ID, - ParentId: node.ParentID, - Timestamp: node.Meta.Time, - Meta: metaToProto(node.Meta.Items), - }, - }) + node, err := stackPopAndSend(stack, srv) if err != nil { return err } if b.GetDepth() == 0 || uint32(len(stack)) < b.GetDepth() { - children, last, err := forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), node.ID, nil, batchSize) + children, last, err := forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), node.Children, nil, batchSize) if err != nil { return err } if len(children) != 0 { stack = append(stack, stackItem{ values: children, - parent: node.ID, + parent: node.Children, last: last, }) } @@ -518,19 +531,38 @@ func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid return nil } +func stackPopAndSend(stack []stackItem, srv TreeService_GetSubTreeServer) (pilorama.MultiNodeInfo, error) { + node := stack[len(stack)-1].values[0] + stack[len(stack)-1].values = stack[len(stack)-1].values[1:] + + return node, srv.Send(&GetSubTreeResponse{ + Body: &GetSubTreeResponse_Body{ + NodeId: node.Children, + ParentId: node.Parents, + Timestamp: node.Timestamps, + Meta: metaToProto(node.Meta), + }, + }) +} + func getSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid cidSDK.ID, b *GetSubTreeRequest_Body, forest pilorama.Forest) error { if b.GetOrderBy().GetDirection() == GetSubTreeRequest_Body_Order_Asc { return getSortedSubTree(ctx, srv, cid, b, forest) } + var rootID uint64 + if len(b.GetRootId()) > 0 { + rootID = b.GetRootId()[0] + } + // Traverse the tree in a DFS manner. Because we need to support arbitrary depth, // recursive implementation is not suitable here, so we maintain explicit stack. - m, p, err := forest.TreeGetMeta(ctx, cid, b.GetTreeId(), b.GetRootId()) + m, p, err := forest.TreeGetMeta(ctx, cid, b.GetTreeId(), rootID) if err != nil { return err } stack := [][]pilorama.NodeInfo{{{ - ID: b.GetRootId(), + ID: rootID, Meta: m, ParentID: p, }}} @@ -548,9 +580,9 @@ func getSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid cidSD err = srv.Send(&GetSubTreeResponse{ Body: &GetSubTreeResponse_Body{ - NodeId: node.ID, - ParentId: node.ParentID, - Timestamp: node.Meta.Time, + NodeId: []uint64{node.ID}, + ParentId: []uint64{node.ParentID}, + Timestamp: []uint64{node.Meta.Time}, Meta: metaToProto(node.Meta.Items), }, }) diff --git a/pkg/services/tree/service.pb.go b/pkg/services/tree/service.pb.go index 7930361e17..f439e3f282 100644 --- a/pkg/services/tree/service.pb.go +++ b/pkg/services/tree/service.pb.go @@ -1979,8 +1979,8 @@ type GetSubTreeRequest_Body struct { ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` // The name of the tree. TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // ID of the root node of a subtree. - RootId uint64 `protobuf:"varint,3,opt,name=root_id,json=rootId,proto3" json:"root_id,omitempty"` + // IDs of the root nodes of a subtree forest. + RootId []uint64 `protobuf:"varint,3,rep,name=root_id,json=rootId,proto3" json:"root_id,omitempty"` // Optional depth of the traversal. Zero means return only root. // Maximum depth is 10. Depth uint32 `protobuf:"varint,4,opt,name=depth,proto3" json:"depth,omitempty"` @@ -2036,11 +2036,11 @@ func (x *GetSubTreeRequest_Body) GetTreeId() string { return "" } -func (x *GetSubTreeRequest_Body) GetRootId() uint64 { +func (x *GetSubTreeRequest_Body) GetRootId() []uint64 { if x != nil { return x.RootId } - return 0 + return nil } func (x *GetSubTreeRequest_Body) GetDepth() uint32 { @@ -2117,11 +2117,11 @@ type GetSubTreeResponse_Body struct { unknownFields protoimpl.UnknownFields // ID of the node. - NodeId uint64 `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` + NodeId []uint64 `protobuf:"varint,1,rep,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` // ID of the parent. - ParentId uint64 `protobuf:"varint,2,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` + ParentId []uint64 `protobuf:"varint,2,rep,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` // Time node was first added to a tree. - Timestamp uint64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Timestamp []uint64 `protobuf:"varint,3,rep,name=timestamp,proto3" json:"timestamp,omitempty"` // Node meta-information. Meta []*KeyValue `protobuf:"bytes,4,rep,name=meta,proto3" json:"meta,omitempty"` } @@ -2158,25 +2158,25 @@ func (*GetSubTreeResponse_Body) Descriptor() ([]byte, []int) { return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{11, 0} } -func (x *GetSubTreeResponse_Body) GetNodeId() uint64 { +func (x *GetSubTreeResponse_Body) GetNodeId() []uint64 { if x != nil { return x.NodeId } - return 0 + return nil } -func (x *GetSubTreeResponse_Body) GetParentId() uint64 { +func (x *GetSubTreeResponse_Body) GetParentId() []uint64 { if x != nil { return x.ParentId } - return 0 + return nil } -func (x *GetSubTreeResponse_Body) GetTimestamp() uint64 { +func (x *GetSubTreeResponse_Body) GetTimestamp() []uint64 { if x != nil { return x.Timestamp } - return 0 + return nil } func (x *GetSubTreeResponse_Body) GetMeta() []*KeyValue { @@ -2742,173 +2742,175 @@ var file_pkg_services_tree_service_proto_rawDesc = []byte{ 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x22, 0xbf, 0x03, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, + 0x73, 0x22, 0xc3, 0x03, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc8, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xcc, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, - 0x07, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, 0x12, 0x21, 0x0a, 0x0c, - 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, - 0x3d, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, - 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x1a, 0x73, - 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e, 0x74, 0x72, 0x65, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x44, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x22, 0x1e, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x73, - 0x63, 0x10, 0x01, 0x22, 0xf6, 0x01, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, - 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x7e, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, - 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, 0x65, - 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x9b, 0x01, 0x0a, - 0x0f, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x29, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x10, 0x54, - 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x0c, 0x41, 0x70, - 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, - 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, - 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x6f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, - 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x09, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x09, 0x6f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x74, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, - 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe2, 0x01, - 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, + 0x07, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x02, + 0x10, 0x00, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, + 0x70, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, + 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x12, 0x3d, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x42, 0x79, 0x1a, 0x73, 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x09, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1e, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x07, + 0x0a, 0x03, 0x41, 0x73, 0x63, 0x10, 0x01, 0x22, 0x83, 0x02, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, + 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, + 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x8a, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1b, 0x0a, 0x07, 0x6e, 0x6f, 0x64, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x02, 0x10, 0x00, 0x52, 0x06, + 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x02, 0x10, 0x00, 0x52, 0x08, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x02, 0x10, 0x00, 0x52, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, + 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, + 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x9b, 0x01, + 0x0a, 0x0f, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, + 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x70, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, + 0x1a, 0x29, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, - 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, - 0x65, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x22, 0xa7, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, - 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x10, + 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x1a, 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x0c, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x62, + 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, + 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x33, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x2b, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, 0x76, - 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x80, 0x01, 0x0a, - 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, - 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, - 0x7e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, - 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, - 0xd6, 0x04, 0x0a, 0x0b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x2a, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x12, 0x10, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, - 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x09, 0x41, - 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, - 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, - 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x12, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, - 0x0a, 0x04, 0x4d, 0x6f, 0x76, 0x65, 0x12, 0x11, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4d, 0x6f, - 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x74, 0x72, 0x65, 0x65, - 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, - 0x0d, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1a, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, - 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x72, 0x65, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x75, - 0x62, 0x54, 0x72, 0x65, 0x65, 0x12, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x39, 0x0a, 0x08, 0x54, 0x72, - 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, - 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x12, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4f, 0x70, - 0x4c, 0x6f, 0x67, 0x12, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, - 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x72, 0x65, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, - 0x65, 0x63, 0x6b, 0x12, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x2e, - 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, - 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, - 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x6f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x09, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x09, 0x6f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x74, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, + 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, + 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe2, + 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x70, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, + 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, + 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x22, 0xa7, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, + 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, + 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x33, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x2b, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, + 0x76, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x80, 0x01, + 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, + 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x22, 0x7e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, + 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x32, 0xd6, 0x04, 0x0a, 0x0b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x2a, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x12, 0x10, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, + 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x72, 0x65, 0x65, + 0x2e, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x09, + 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x74, 0x72, 0x65, 0x65, + 0x2e, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, + 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x72, 0x65, 0x65, + 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x2d, 0x0a, 0x04, 0x4d, 0x6f, 0x76, 0x65, 0x12, 0x11, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4d, + 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x74, 0x72, 0x65, + 0x65, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, + 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, + 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x72, + 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, + 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x12, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, + 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x39, 0x0a, 0x08, 0x54, + 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, + 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, + 0x12, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4f, + 0x70, 0x4c, 0x6f, 0x67, 0x12, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, + 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x72, + 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, + 0x68, 0x65, 0x63, 0x6b, 0x12, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, + 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, + 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, + 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( diff --git a/pkg/services/tree/service.proto b/pkg/services/tree/service.proto index 582e748470..88bf0bca45 100644 --- a/pkg/services/tree/service.proto +++ b/pkg/services/tree/service.proto @@ -242,8 +242,8 @@ message GetSubTreeRequest { bytes container_id = 1; // The name of the tree. string tree_id = 2; - // ID of the root node of a subtree. - uint64 root_id = 3; + // IDs of the root nodes of a subtree forest. + repeated uint64 root_id = 3 [ packed = false ]; // Optional depth of the traversal. Zero means return only root. // Maximum depth is 10. uint32 depth = 4; @@ -262,11 +262,11 @@ message GetSubTreeRequest { message GetSubTreeResponse { message Body { // ID of the node. - uint64 node_id = 1; + repeated uint64 node_id = 1 [ packed = false ]; // ID of the parent. - uint64 parent_id = 2; + repeated uint64 parent_id = 2 [ packed = false ]; // Time node was first added to a tree. - uint64 timestamp = 3; + repeated uint64 timestamp = 3 [ packed = false ]; // Node meta-information. repeated KeyValue meta = 4; } diff --git a/pkg/services/tree/service_frostfs.pb.go b/pkg/services/tree/service_frostfs.pb.go index 4b50af2aac..1a49c5c0c1 100644 --- a/pkg/services/tree/service_frostfs.pb.go +++ b/pkg/services/tree/service_frostfs.pb.go @@ -2,6 +2,11 @@ package tree +import ( + binary "encoding/binary" + protowire "google.golang.org/protobuf/encoding/protowire" +) + import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" // StableSize returns the size of x in protobuf format. @@ -995,7 +1000,9 @@ func (x *GetSubTreeRequest_Body) StableSize() (size int) { } size += proto.BytesSize(1, x.ContainerId) size += proto.StringSize(2, x.TreeId) - size += proto.UInt64Size(3, x.RootId) + for i := range x.RootId { + size += protowire.SizeGroup(protowire.Number(3), protowire.SizeVarint(x.RootId[i])) + } size += proto.UInt32Size(4, x.Depth) size += proto.BytesSize(5, x.BearerToken) size += proto.NestedStructureSize(6, x.OrderBy) @@ -1020,7 +1027,13 @@ func (x *GetSubTreeRequest_Body) StableMarshal(buf []byte) []byte { var offset int offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.UInt64Marshal(3, buf[offset:], x.RootId) + for i := range x.RootId { + { + prefix := protowire.EncodeTag(protowire.Number(3), protowire.VarintType) + offset += binary.PutUvarint(buf[offset:], uint64(prefix)) + offset += binary.PutUvarint(buf[offset:], x.RootId[i]) + } + } offset += proto.UInt32Marshal(4, buf[offset:], x.Depth) offset += proto.BytesMarshal(5, buf[offset:], x.BearerToken) offset += proto.NestedStructureMarshal(6, buf[offset:], x.OrderBy) @@ -1089,9 +1102,15 @@ func (x *GetSubTreeResponse_Body) StableSize() (size int) { if x == nil { return 0 } - size += proto.UInt64Size(1, x.NodeId) - size += proto.UInt64Size(2, x.ParentId) - size += proto.UInt64Size(3, x.Timestamp) + for i := range x.NodeId { + size += protowire.SizeGroup(protowire.Number(1), protowire.SizeVarint(x.NodeId[i])) + } + for i := range x.ParentId { + size += protowire.SizeGroup(protowire.Number(2), protowire.SizeVarint(x.ParentId[i])) + } + for i := range x.Timestamp { + size += protowire.SizeGroup(protowire.Number(3), protowire.SizeVarint(x.Timestamp[i])) + } for i := range x.Meta { size += proto.NestedStructureSize(4, x.Meta[i]) } @@ -1114,9 +1133,27 @@ func (x *GetSubTreeResponse_Body) StableMarshal(buf []byte) []byte { buf = make([]byte, x.StableSize()) } var offset int - offset += proto.UInt64Marshal(1, buf[offset:], x.NodeId) - offset += proto.UInt64Marshal(2, buf[offset:], x.ParentId) - offset += proto.UInt64Marshal(3, buf[offset:], x.Timestamp) + for i := range x.NodeId { + { + prefix := protowire.EncodeTag(protowire.Number(1), protowire.VarintType) + offset += binary.PutUvarint(buf[offset:], uint64(prefix)) + offset += binary.PutUvarint(buf[offset:], x.NodeId[i]) + } + } + for i := range x.ParentId { + { + prefix := protowire.EncodeTag(protowire.Number(2), protowire.VarintType) + offset += binary.PutUvarint(buf[offset:], uint64(prefix)) + offset += binary.PutUvarint(buf[offset:], x.ParentId[i]) + } + } + for i := range x.Timestamp { + { + prefix := protowire.EncodeTag(protowire.Number(3), protowire.VarintType) + offset += binary.PutUvarint(buf[offset:], uint64(prefix)) + offset += binary.PutUvarint(buf[offset:], x.Timestamp[i]) + } + } for i := range x.Meta { offset += proto.NestedStructureMarshal(4, buf[offset:], x.Meta[i]) } diff --git a/pkg/services/tree/service_grpc.pb.go b/pkg/services/tree/service_grpc.pb.go index 63f96e11a5..4c293a4c03 100644 --- a/pkg/services/tree/service_grpc.pb.go +++ b/pkg/services/tree/service_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.3.0 +// - protoc-gen-go-grpc v1.4.0 // - protoc v4.25.0 // source: pkg/services/tree/service.proto @@ -18,8 +18,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 +// Requires gRPC-Go v1.62.0 or later. +const _ = grpc.SupportPackageIsVersion8 const ( TreeService_Add_FullMethodName = "/tree.TreeService/Add" @@ -70,8 +70,9 @@ func NewTreeServiceClient(cc grpc.ClientConnInterface) TreeServiceClient { } func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AddResponse) - err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -79,8 +80,9 @@ func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grp } func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, opts ...grpc.CallOption) (*AddByPathResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AddByPathResponse) - err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -88,8 +90,9 @@ func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, } func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts ...grpc.CallOption) (*RemoveResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(RemoveResponse) - err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -97,8 +100,9 @@ func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts } func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...grpc.CallOption) (*MoveResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MoveResponse) - err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -106,8 +110,9 @@ func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...g } func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPathRequest, opts ...grpc.CallOption) (*GetNodeByPathResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetNodeByPathResponse) - err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -115,11 +120,12 @@ func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPath } func (c *treeServiceClient) GetSubTree(ctx context.Context, in *GetSubTreeRequest, opts ...grpc.CallOption) (TreeService_GetSubTreeClient, error) { - stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, opts...) + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &treeServiceGetSubTreeClient{stream} + x := &treeServiceGetSubTreeClient{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -147,8 +153,9 @@ func (x *treeServiceGetSubTreeClient) Recv() (*GetSubTreeResponse, error) { } func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, opts ...grpc.CallOption) (*TreeListResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(TreeListResponse) - err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -156,8 +163,9 @@ func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, o } func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts ...grpc.CallOption) (*ApplyResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ApplyResponse) - err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -165,11 +173,12 @@ func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts .. } func (c *treeServiceClient) GetOpLog(ctx context.Context, in *GetOpLogRequest, opts ...grpc.CallOption) (TreeService_GetOpLogClient, error) { - stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, opts...) + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, cOpts...) if err != nil { return nil, err } - x := &treeServiceGetOpLogClient{stream} + x := &treeServiceGetOpLogClient{ClientStream: stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -197,8 +206,9 @@ func (x *treeServiceGetOpLogClient) Recv() (*GetOpLogResponse, error) { } func (c *treeServiceClient) Healthcheck(ctx context.Context, in *HealthcheckRequest, opts ...grpc.CallOption) (*HealthcheckResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(HealthcheckResponse) - err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, opts...) + err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, cOpts...) if err != nil { return nil, err } @@ -373,7 +383,7 @@ func _TreeService_GetSubTree_Handler(srv interface{}, stream grpc.ServerStream) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(TreeServiceServer).GetSubTree(m, &treeServiceGetSubTreeServer{stream}) + return srv.(TreeServiceServer).GetSubTree(m, &treeServiceGetSubTreeServer{ServerStream: stream}) } type TreeService_GetSubTreeServer interface { @@ -430,7 +440,7 @@ func _TreeService_GetOpLog_Handler(srv interface{}, stream grpc.ServerStream) er if err := stream.RecvMsg(m); err != nil { return err } - return srv.(TreeServiceServer).GetOpLog(m, &treeServiceGetOpLogServer{stream}) + return srv.(TreeServiceServer).GetOpLog(m, &treeServiceGetOpLogServer{ServerStream: stream}) } type TreeService_GetOpLogServer interface { From 00a88b99368d7141380f65d9cb446f1e4771ba01 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 17 Jul 2024 09:54:03 +0300 Subject: [PATCH 0697/1413] [#1251] *: Run gofumpt Signed-off-by: Evgenii Stratonikov --- pkg/services/object_manager/placement/cache_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/services/object_manager/placement/cache_test.go b/pkg/services/object_manager/placement/cache_test.go index 5816d59fe7..07e9340dcf 100644 --- a/pkg/services/object_manager/placement/cache_test.go +++ b/pkg/services/object_manager/placement/cache_test.go @@ -91,5 +91,4 @@ func TestContainerNodesCache(t *testing.T) { _, err := c.ContainerNodes(nm(1, nodes[0:1]), cidtest.ID(), pp) require.Error(t, err) }) - } From fc383ea6ae3bfa98ade02a53bb591f5ad0cb4780 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 15 Jul 2024 18:03:43 +0300 Subject: [PATCH 0698/1413] [#1253] getSvc: Fix EC objects get Now EC objects assembling is performed concurrently. Also fixed issue with an error in case of getting EC object via non-container node. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 2 + pkg/services/object/get/assemble.go | 2 +- pkg/services/object/get/assembleec.go | 19 +- pkg/services/object/get/assemblerec.go | 358 +++++++++++++++++----- pkg/services/object/get/get.go | 13 +- pkg/services/object/get/get_test.go | 9 +- pkg/services/object/get/local.go | 4 +- pkg/services/object/get/remote.go | 68 ++-- pkg/services/object/get/request.go | 4 +- pkg/services/object/get/types.go | 51 ++- pkg/services/object/search/container.go | 2 +- pkg/services/object/search/search_test.go | 6 +- pkg/services/object/search/service.go | 3 +- pkg/services/object/util/placement.go | 12 +- 14 files changed, 429 insertions(+), 124 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 5a195f6882..67f173f29f 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -108,6 +108,7 @@ const ( GetUnableToGetPartECObject = "unable to get part of the erasure-encoded object" GetUnableToHeadPartECObject = "unable to head part of the erasure-encoded object" GetUnableToGetECObjectContainer = "unable to get container for erasure-coded object" + GetUnableToHeadPartsECObject = "unable to head parts of the erasure-encoded object" GetAssemblingSplittedObjectCompleted = "assembling splitted object completed" GetAssemblingECObjectCompleted = "assembling erasure-coded object completed" GetFailedToAssembleSplittedObject = "failed to assemble splitted object" @@ -123,6 +124,7 @@ const ( GetRequestedObjectIsVirtual = "requested object is virtual" GetRequestedObjectIsEC = "requested object is erasure-coded" GetRequestedRangeIsOutOfObjectBounds = "requested range is out of object bounds" + GetUnexpectedECObject = "failed to get EC object from node: expected EC info, but got full object" PutAdditionalContainerBroadcastFailure = "additional container broadcast failure" SearchReturnResultDirectly = "return result directly" SearchCouldNotConstructRemoteNodeClient = "could not construct remote node client" diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index 66c4580b06..ba6fddec5a 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -140,7 +140,7 @@ func (r *request) getObjectWithIndependentRequest(ctx context.Context, prm Reque prm: prm, infoSplit: objectSDK.NewSplitInfo(), - infoEC: objectSDK.NewECInfo(), + infoEC: newECInfo(), log: r.log, } diff --git a/pkg/services/object/get/assembleec.go b/pkg/services/object/get/assembleec.go index 5c999929af..7bbd9ca1e0 100644 --- a/pkg/services/object/get/assembleec.go +++ b/pkg/services/object/get/assembleec.go @@ -6,11 +6,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) func (r *request) assembleEC(ctx context.Context) { - if r.isRaw() { + if r.isRaw() && r.isLocal() { r.log.Debug(logs.GetCanNotAssembleTheObject) return } @@ -35,8 +36,14 @@ func (r *request) assembleEC(ctx context.Context) { r.log.Debug(logs.GetTryingToAssembleTheECObject) + // initialize epoch number + ok := r.initEpoch() + if !ok { + return + } + r.prm.common = r.prm.common.WithLocalOnly(false) - assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.containerSource, r.log) + assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.localStorage, r.containerSource, r.log, r.headOnly(), r.isRaw(), r.traverserGenerator, r.curProcEpoch) r.log.Debug(logs.GetAssemblingECObject, zap.Uint64("range_offset", r.ctxRange().GetOffset()), @@ -47,8 +54,8 @@ func (r *request) assembleEC(ctx context.Context) { zap.Uint64("range_length", r.ctxRange().GetLength()), ) - obj, err := assembler.Assemble(ctx, r.prm.objWriter, r.headOnly()) - if err != nil { + obj, err := assembler.Assemble(ctx, r.prm.objWriter) + if err != nil && !errors.As(err, new(*objectSDK.ECInfoError)) { r.log.Warn(logs.GetFailedToAssembleECObject, zap.Error(err), zap.Uint64("range_offset", r.ctxRange().GetOffset()), @@ -58,6 +65,7 @@ func (r *request) assembleEC(ctx context.Context) { var errRemoved *apistatus.ObjectAlreadyRemoved var errOutOfRange *apistatus.ObjectOutOfRange + var errECInfo *objectSDK.ECInfoError switch { default: @@ -73,5 +81,8 @@ func (r *request) assembleEC(ctx context.Context) { case errors.As(err, &errOutOfRange): r.status = statusOutOfRange r.err = errOutOfRange + case errors.As(err, &errECInfo): + r.status = statusEC + r.err = err } } diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index 4a624e4676..a4021ee5e9 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -2,11 +2,16 @@ package getsvc import ( "context" + "encoding/hex" + "errors" "fmt" + "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -16,61 +21,79 @@ import ( "golang.org/x/sync/errgroup" ) +var errECPartsRetrieveCompleted = errors.New("EC parts receive completed") + +type ecRemoteStorage interface { + getObjectFromNode(ctx context.Context, addr oid.Address, info client.NodeInfo) (*objectSDK.Object, error) + headObjectFromNode(ctx context.Context, addr oid.Address, info client.NodeInfo, raw bool) (*objectSDK.Object, error) +} + type assemblerec struct { - addr oid.Address - ecInfo *objectSDK.ECInfo - rng *objectSDK.Range - objGetter objectGetter - cs container.Source - log *logger.Logger + addr oid.Address + ecInfo *ecInfo + rng *objectSDK.Range + remoteStorage ecRemoteStorage + localStorage localStorage + cs container.Source + log *logger.Logger + head bool + raw bool + traverserGenerator traverserGenerator + epoch uint64 } func newAssemblerEC( addr oid.Address, - ecInfo *objectSDK.ECInfo, + ecInfo *ecInfo, rng *objectSDK.Range, - objGetter objectGetter, + remoteStorage ecRemoteStorage, + localStorage localStorage, cs container.Source, log *logger.Logger, + head bool, + raw bool, + tg traverserGenerator, + epoch uint64, ) *assemblerec { return &assemblerec{ - addr: addr, - rng: rng, - ecInfo: ecInfo, - objGetter: objGetter, - cs: cs, - log: log, + addr: addr, + rng: rng, + ecInfo: ecInfo, + remoteStorage: remoteStorage, + localStorage: localStorage, + cs: cs, + log: log, + head: head, + raw: raw, + traverserGenerator: tg, + epoch: epoch, } } // Assemble assembles erasure-coded object and writes it's content to ObjectWriter. // It returns parent object. -func (a *assemblerec) Assemble(ctx context.Context, writer ObjectWriter, headOnly bool) (*objectSDK.Object, error) { - if headOnly { +func (a *assemblerec) Assemble(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { + switch { + case a.raw: + err := a.reconstructRawError(ctx) + return nil, err + case a.head: return a.reconstructHeader(ctx, writer) - } else if a.rng != nil { + case a.rng != nil: return a.reconstructRange(ctx, writer) + default: + return a.reconstructObject(ctx, writer) } - return a.reconstructObject(ctx, writer) } -func (a *assemblerec) getConstructor() (*erasurecode.Constructor, error) { - cnt, err := a.cs.Get(a.addr.Container()) - if err != nil { - return nil, err - } - dataCount := policy.ECDataCount(cnt.Value.PlacementPolicy()) - parityCount := policy.ECParityCount(cnt.Value.PlacementPolicy()) +func (a *assemblerec) getConstructor(cnr *container.Container) (*erasurecode.Constructor, error) { + dataCount := policy.ECDataCount(cnr.Value.PlacementPolicy()) + parityCount := policy.ECParityCount(cnr.Value.PlacementPolicy()) return erasurecode.NewConstructor(dataCount, parityCount) } func (a *assemblerec) reconstructHeader(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { - parts := a.retrieveParts(ctx, true) - c, err := a.getConstructor() - if err != nil { - return nil, err - } - obj, err := c.ReconstructHeader(parts) + obj, err := a.reconstructObjectFromParts(ctx, true) if err == nil { return obj, writer.WriteHeader(ctx, obj) } @@ -78,12 +101,7 @@ func (a *assemblerec) reconstructHeader(ctx context.Context, writer ObjectWriter } func (a *assemblerec) reconstructRange(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { - parts := a.retrieveParts(ctx, false) - c, err := a.getConstructor() - if err != nil { - return nil, err - } - obj, err := c.Reconstruct(parts) + obj, err := a.reconstructObjectFromParts(ctx, false) if err != nil { return nil, err } @@ -101,12 +119,7 @@ func (a *assemblerec) reconstructRange(ctx context.Context, writer ObjectWriter) } func (a *assemblerec) reconstructObject(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { - parts := a.retrieveParts(ctx, false) - c, err := a.getConstructor() - if err != nil { - return nil, err - } - obj, err := c.Reconstruct(parts) + obj, err := a.reconstructObjectFromParts(ctx, false) if err == nil { err = writer.WriteHeader(ctx, obj.CutPayload()) if err == nil { @@ -119,41 +132,238 @@ func (a *assemblerec) reconstructObject(ctx context.Context, writer ObjectWriter return obj, err } -func (a *assemblerec) retrieveParts(mainCtx context.Context, headOnly bool) []*objectSDK.Object { - parts := make([]*objectSDK.Object, int(a.ecInfo.Chunks[0].Total)) - errGroup, ctx := errgroup.WithContext(mainCtx) +func (a *assemblerec) reconstructObjectFromParts(ctx context.Context, headers bool) (*objectSDK.Object, error) { + objID := a.addr.Object() + trav, cnr, err := a.traverserGenerator.GenerateTraverser(a.addr.Container(), &objID, a.epoch) + if err != nil { + return nil, err + } + c, err := a.getConstructor(cnr) + if err != nil { + return nil, err + } + parts := a.retrieveParts(ctx, trav, cnr) + if headers { + return c.ReconstructHeader(parts) + } + return c.Reconstruct(parts) +} - for i := range a.ecInfo.Chunks { - chunk := a.ecInfo.Chunks[i] - errGroup.Go(func() error { - objID := new(oid.ID) - err := objID.ReadFromV2(chunk.ID) - if err != nil { - return fmt.Errorf("invalid object ID: %w", err) - } - var obj *objectSDK.Object - if headOnly { - obj, err = a.objGetter.HeadObject(ctx, *objID) - if err != nil { - a.log.Debug(logs.GetUnableToHeadPartECObject, zap.Stringer("part_id", objID), zap.Error(err)) - return nil - } - } else { - sow := NewSimpleObjectWriter() - obj, err = a.objGetter.GetObjectAndWritePayload(ctx, *objID, nil, sow) - if err != nil { - a.log.Debug(logs.GetUnableToGetPartECObject, zap.Stringer("part_id", objID), zap.Error(err)) - return nil - } - obj.SetPayload(sow.pld) - } - parts[chunk.Index] = obj - return nil - }) +func (a *assemblerec) reconstructRawError(ctx context.Context) error { + chunks := make(map[string]objectSDK.ECChunk) + var chunksGuard sync.Mutex + for _, ch := range a.ecInfo.localChunks { + chunks[string(ch.ID.GetValue())] = ch } - if err := errGroup.Wait(); err != nil { + objID := a.addr.Object() + trav, _, err := a.traverserGenerator.GenerateTraverser(a.addr.Container(), &objID, a.epoch) + if err != nil { + return err + } + + eg, ctx := errgroup.WithContext(ctx) + for { + batch := trav.Next() + if len(batch) == 0 { + break + } + for _, node := range batch { + var info client.NodeInfo + client.NodeInfoFromNetmapElement(&info, node) + eg.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if _, found := a.ecInfo.remoteChunks[string(info.PublicKey())]; found { + return nil + } + + nodeChunks := a.tryGetChunkListFromNode(ctx, info) + + chunksGuard.Lock() + defer chunksGuard.Unlock() + for _, ch := range nodeChunks { + chunks[string(ch.ID.GetValue())] = ch + } + return nil + }) + } + } + if err = eg.Wait(); err != nil { + return err + } + return createECInfoErr(chunks) +} + +func (a *assemblerec) retrieveParts(ctx context.Context, trav *placement.Traverser, cnr *container.Container) []*objectSDK.Object { + dataCount := policy.ECDataCount(cnr.Value.PlacementPolicy()) + parityCount := policy.ECParityCount(cnr.Value.PlacementPolicy()) + + remoteNodes := make([]placement.Node, 0) + for { + batch := trav.Next() + if len(batch) == 0 { + break + } + remoteNodes = append(remoteNodes, batch...) + } + + parts, err := a.processECNodesRequests(ctx, remoteNodes, dataCount, parityCount) + if err != nil { a.log.Debug(logs.GetUnableToGetAllPartsECObject, zap.Error(err)) } return parts } + +func (a *assemblerec) processECNodesRequests(ctx context.Context, nodes []placement.Node, dataCount, parityCount int) ([]*objectSDK.Object, error) { + foundChunks := make(map[uint32]*objectSDK.Object) + var foundChunksGuard sync.Mutex + eg, ctx := errgroup.WithContext(ctx) + eg.SetLimit(dataCount) + + for _, ch := range a.ecInfo.localChunks { + ch := ch + eg.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + object := a.tryGetChunkFromLocalStorage(ctx, ch) + if object == nil { + return nil + } + foundChunksGuard.Lock() + foundChunks[ch.Index] = object + count := len(foundChunks) + foundChunksGuard.Unlock() + if count >= dataCount { + return errECPartsRetrieveCompleted + } + return nil + }) + } + + for _, node := range nodes { + var info client.NodeInfo + client.NodeInfoFromNetmapElement(&info, node) + eg.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + chunks := a.tryGetChunkListFromNode(ctx, info) + for _, ch := range chunks { + object := a.tryGetChunkFromRemoteStorage(ctx, info, ch) + if object == nil { + continue + } + foundChunksGuard.Lock() + foundChunks[ch.Index] = object + count := len(foundChunks) + foundChunksGuard.Unlock() + if count >= dataCount { + return errECPartsRetrieveCompleted + } + } + return nil + }) + } + err := eg.Wait() + if err == nil || errors.Is(err, errECPartsRetrieveCompleted) { + parts := make([]*objectSDK.Object, dataCount+parityCount) + for idx, chunk := range foundChunks { + parts[idx] = chunk + } + return parts, nil + } + return nil, err +} + +func (a *assemblerec) tryGetChunkFromLocalStorage(ctx context.Context, ch objectSDK.ECChunk) *objectSDK.Object { + var objID oid.ID + err := objID.ReadFromV2(ch.ID) + if err != nil { + a.log.Error(logs.GetUnableToHeadPartECObject, zap.String("node", "local"), zap.Uint32("part_index", ch.Index), zap.Error(fmt.Errorf("invalid object ID: %w", err))) + return nil + } + var addr oid.Address + addr.SetContainer(addr.Container()) + addr.SetObject(objID) + var object *objectSDK.Object + if a.head { + object, err = a.localStorage.Head(ctx, addr, false) + if err != nil { + a.log.Warn(logs.GetUnableToHeadPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) + return nil + } + } else { + object, err = a.localStorage.Get(ctx, addr) + if err != nil { + a.log.Warn(logs.GetUnableToGetPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) + return nil + } + } + return object +} + +func (a *assemblerec) tryGetChunkListFromNode(ctx context.Context, node client.NodeInfo) []objectSDK.ECChunk { + if chunks, found := a.ecInfo.remoteChunks[string(node.PublicKey())]; found { + return chunks + } + var errECInfo *objectSDK.ECInfoError + _, err := a.remoteStorage.headObjectFromNode(ctx, a.addr, node, true) + if err == nil { + a.log.Error(logs.GetUnexpectedECObject, zap.String("node", hex.EncodeToString(node.PublicKey()))) + return nil + } + if !errors.As(err, &errECInfo) { + a.log.Warn(logs.GetUnableToHeadPartsECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) + return nil + } + result := make([]objectSDK.ECChunk, 0, len(errECInfo.ECInfo().Chunks)) + for _, ch := range errECInfo.ECInfo().Chunks { + result = append(result, objectSDK.ECChunk(ch)) + } + return result +} + +func (a *assemblerec) tryGetChunkFromRemoteStorage(ctx context.Context, node client.NodeInfo, ch objectSDK.ECChunk) *objectSDK.Object { + var objID oid.ID + err := objID.ReadFromV2(ch.ID) + if err != nil { + a.log.Error(logs.GetUnableToHeadPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Uint32("part_index", ch.Index), zap.Error(fmt.Errorf("invalid object ID: %w", err))) + return nil + } + var addr oid.Address + addr.SetContainer(a.addr.Container()) + addr.SetObject(objID) + var object *objectSDK.Object + if a.head { + object, err = a.remoteStorage.headObjectFromNode(ctx, addr, node, false) + if err != nil { + a.log.Warn(logs.GetUnableToHeadPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) + return nil + } + } else { + object, err = a.remoteStorage.getObjectFromNode(ctx, addr, node) + if err != nil { + a.log.Warn(logs.GetUnableToGetPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) + return nil + } + } + return object +} + +func createECInfoErr(chunks map[string]objectSDK.ECChunk) *objectSDK.ECInfoError { + info := objectSDK.NewECInfo() + for _, ch := range chunks { + info.AddChunk(ch) + } + return objectSDK.NewECInfoError(info) +} diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 9738935d2a..5a57bc56e0 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -77,7 +77,7 @@ func (s *Service) get(ctx context.Context, prm RequestParameters) error { prm: prm, infoSplit: objectSDK.NewSplitInfo(), - infoEC: objectSDK.NewECInfo(), + infoEC: newECInfo(), log: s.log, } @@ -110,15 +110,8 @@ func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) { case statusOutOfRange: exec.log.Debug(logs.GetRequestedRangeIsOutOfObjectBounds) case statusEC: - if !exec.isLocal() { - if execCnr { - exec.executeOnContainer(ctx) - exec.analyzeStatus(ctx, false) - } else { - exec.log.Debug(logs.GetRequestedObjectIsEC) - exec.assembleEC(ctx) - } - } + exec.log.Debug(logs.GetRequestedObjectIsEC) + exec.assembleEC(ctx) default: exec.log.Debug(logs.OperationFinishedWithError, zap.Error(exec.err), diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 988cd69829..29a15ba786 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -11,6 +11,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" @@ -78,7 +79,7 @@ func newTestStorage() *testStorage { } } -func (g *testTraverserGenerator) GenerateTraverser(cnr cid.ID, obj *oid.ID, e uint64) (*placement.Traverser, error) { +func (g *testTraverserGenerator) GenerateTraverser(cnr cid.ID, obj *oid.ID, e uint64) (*placement.Traverser, *containerCore.Container, error) { opts := make([]placement.Option, 0, 4) opts = append(opts, placement.ForContainer(g.c), @@ -90,7 +91,10 @@ func (g *testTraverserGenerator) GenerateTraverser(cnr cid.ID, obj *oid.ID, e ui opts = append(opts, placement.ForObject(*obj)) } - return placement.NewTraverser(opts...) + t, err := placement.NewTraverser(opts...) + return t, &containerCore.Container{ + Value: g.c, + }, err } func (p *testPlacementBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, _ netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { @@ -474,6 +478,7 @@ func testNodeMatrix(t testing.TB, dim []int) ([][]netmap.NodeInfo, [][]string) { var ni netmap.NodeInfo ni.SetNetworkEndpoints(a) + ni.SetPublicKey([]byte(a)) var na network.AddressGroup diff --git a/pkg/services/object/get/local.go b/pkg/services/object/get/local.go index fcfc9befcb..1cd5e549c7 100644 --- a/pkg/services/object/get/local.go +++ b/pkg/services/object/get/local.go @@ -5,7 +5,6 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -46,8 +45,7 @@ func (r *request) executeLocal(ctx context.Context) { r.err = objectSDK.NewSplitInfoError(r.infoSplit) case errors.As(err, &errECInfo): r.status = statusEC - util.MergeECInfo(errECInfo.ECInfo(), r.infoEC) - r.err = objectSDK.NewECInfoError(r.infoEC) + r.err = r.infoEC.addLocal(errECInfo.ECInfo()) case errors.As(err, &errOutOfRange): r.status = statusOutOfRange r.err = errOutOfRange diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index 302a4a4bc1..4dee152427 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -7,11 +7,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" ) @@ -36,11 +35,6 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { switch { default: r.log.Debug(logs.GetRemoteCallFailed, zap.Error(err)) - if r.status == statusEC { - // we need to continue getting another chunks from another nodes - // in case of network issue - return false - } r.status = statusUndefined r.err = new(apistatus.ObjectNotFound) case err == nil: @@ -66,18 +60,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { r.err = objectSDK.NewSplitInfoError(r.infoSplit) case errors.As(err, &errECInfo): r.status = statusEC - util.MergeECInfo(r.infoEC, errECInfo.ECInfo()) - r.infoEC = errECInfo.ECInfo() - r.err = objectSDK.NewECInfoError(r.infoEC) - if r.isRaw() { - return len(r.infoEC.Chunks) == int(r.infoEC.Chunks[0].Total) - } - cnt, err := r.containerSource.Get(r.address().Container()) - if err == nil { - return len(r.infoEC.Chunks) == policy.ECDataCount(cnt.Value.PlacementPolicy()) - } - r.log.Debug(logs.GetUnableToGetECObjectContainer, zap.Error(err)) - return len(r.infoEC.Chunks) == int(r.infoEC.Chunks[0].Total) + r.err = r.infoEC.addRemote(string(info.PublicKey()), errECInfo.ECInfo()) } return r.status != statusUndefined @@ -116,3 +99,50 @@ func (r *request) getRemote(ctx context.Context, rs remoteStorage, info client.N return rs.Get(ctx, r.address(), prm) } + +func (r *request) getObjectFromNode(ctx context.Context, addr oid.Address, info client.NodeInfo) (*objectSDK.Object, error) { + rs, err := r.remoteStorageConstructor.Get(info) + if err != nil { + return nil, err + } + + key, err := r.key() + if err != nil { + return nil, err + } + + prm := RemoteRequestParams{ + Epoch: r.curProcEpoch, + TTL: 1, + PrivateKey: key, + SessionToken: r.prm.common.SessionToken(), + BearerToken: r.prm.common.BearerToken(), + XHeaders: r.prm.common.XHeaders(), + } + + return rs.Get(ctx, addr, prm) +} + +func (r *request) headObjectFromNode(ctx context.Context, addr oid.Address, info client.NodeInfo, raw bool) (*objectSDK.Object, error) { + rs, err := r.remoteStorageConstructor.Get(info) + if err != nil { + return nil, err + } + + key, err := r.key() + if err != nil { + return nil, err + } + + prm := RemoteRequestParams{ + Epoch: r.curProcEpoch, + TTL: 1, + PrivateKey: key, + SessionToken: r.prm.common.SessionToken(), + BearerToken: r.prm.common.BearerToken(), + XHeaders: r.prm.common.XHeaders(), + IsRaw: raw, + } + + return rs.Head(ctx, addr, prm) +} diff --git a/pkg/services/object/get/request.go b/pkg/services/object/get/request.go index d0b79e30c2..9ddfeddf28 100644 --- a/pkg/services/object/get/request.go +++ b/pkg/services/object/get/request.go @@ -23,7 +23,7 @@ type request struct { infoSplit *objectSDK.SplitInfo - infoEC *objectSDK.ECInfo + infoEC *ecInfo log *logger.Logger @@ -141,7 +141,7 @@ func (r *request) initEpoch() bool { func (r *request) generateTraverser(addr oid.Address) (*placement.Traverser, bool) { obj := addr.Object() - t, err := r.traverserGenerator.GenerateTraverser(addr.Container(), &obj, r.curProcEpoch) + t, _, err := r.traverserGenerator.GenerateTraverser(addr.Container(), &obj, r.curProcEpoch) switch { default: diff --git a/pkg/services/object/get/types.go b/pkg/services/object/get/types.go index a866132ccd..9669afdba1 100644 --- a/pkg/services/object/get/types.go +++ b/pkg/services/object/get/types.go @@ -6,6 +6,7 @@ import ( "errors" coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -23,7 +24,7 @@ type epochSource interface { } type traverserGenerator interface { - GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, error) + GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, *container.Container, error) } type keyStorage interface { @@ -236,3 +237,51 @@ type RangeHashRes struct { func (r *RangeHashRes) Hashes() [][]byte { return r.hashes } + +type ecInfo struct { + localChunks []objectSDK.ECChunk + remoteChunks map[string][]objectSDK.ECChunk // node pk -> chunk slice +} + +func newECInfo() *ecInfo { + return &ecInfo{ + localChunks: make([]objectSDK.ECChunk, 0), + remoteChunks: make(map[string][]objectSDK.ECChunk), + } +} + +func (e *ecInfo) addLocal(ecInfo *objectSDK.ECInfo) *objectSDK.ECInfoError { + for _, ch := range ecInfo.Chunks { + e.localChunks = append(e.localChunks, objectSDK.ECChunk(ch)) + } + return e.createECInfoErr() +} + +func (e *ecInfo) addRemote(nodePK string, ecInfo *objectSDK.ECInfo) *objectSDK.ECInfoError { + for _, ch := range ecInfo.Chunks { + e.remoteChunks[nodePK] = append(e.remoteChunks[nodePK], objectSDK.ECChunk(ch)) + } + return e.createECInfoErr() +} + +func (e *ecInfo) createECInfoErr() *objectSDK.ECInfoError { + unique := make(map[string]struct{}) + result := objectSDK.NewECInfo() + for _, ch := range e.localChunks { + if _, found := unique[string(ch.ID.GetValue())]; found { + continue + } + result.AddChunk(ch) + unique[string(ch.ID.GetValue())] = struct{}{} + } + for _, chunks := range e.remoteChunks { + for _, ch := range chunks { + if _, found := unique[string(ch.ID.GetValue())]; found { + continue + } + result.AddChunk(ch) + unique[string(ch.ID.GetValue())] = struct{}{} + } + } + return objectSDK.NewECInfoError(result) +} diff --git a/pkg/services/object/search/container.go b/pkg/services/object/search/container.go index a8865f5f0d..d705741568 100644 --- a/pkg/services/object/search/container.go +++ b/pkg/services/object/search/container.go @@ -47,7 +47,7 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { zap.Uint64("number", exec.curProcEpoch), ) - traverser, err := exec.svc.traverserGenerator.GenerateTraverser(exec.containerID(), nil, exec.curProcEpoch) + traverser, _, err := exec.svc.traverserGenerator.GenerateTraverser(exec.containerID(), nil, exec.curProcEpoch) if err != nil { return fmt.Errorf("%s: %w", logs.SearchCouldNotGenerateContainerTraverser, err) } diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 802fa33efa..6793804029 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -80,12 +81,13 @@ func newTestStorage() *testStorage { } } -func (g *testTraverserGenerator) GenerateTraverser(_ cid.ID, _ *oid.ID, epoch uint64) (*placement.Traverser, error) { - return placement.NewTraverser( +func (g *testTraverserGenerator) GenerateTraverser(_ cid.ID, _ *oid.ID, epoch uint64) (*placement.Traverser, *containerCore.Container, error) { + t, err := placement.NewTraverser( placement.ForContainer(g.c), placement.UseBuilder(g.b[epoch]), placement.WithoutSuccessTracking(), ) + return t, &containerCore.Container{Value: g.c}, err } func (p *testPlacementBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, _ netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index 0a54f54c5c..cc388c1b21 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -4,6 +4,7 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -45,7 +46,7 @@ type cfg struct { } traverserGenerator interface { - GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, error) + GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, *container.Container, error) } currentEpochReceiver interface { diff --git a/pkg/services/object/util/placement.go b/pkg/services/object/util/placement.go index 6cd3856f47..1bd39f9ead 100644 --- a/pkg/services/object/util/placement.go +++ b/pkg/services/object/util/placement.go @@ -122,17 +122,17 @@ func (g *TraverserGenerator) WithTraverseOptions(opts ...placement.Option) *Trav // GenerateTraverser generates placement Traverser for provided object address // using epoch-th network map. -func (g *TraverserGenerator) GenerateTraverser(idCnr cid.ID, idObj *oid.ID, epoch uint64) (*placement.Traverser, error) { +func (g *TraverserGenerator) GenerateTraverser(idCnr cid.ID, idObj *oid.ID, epoch uint64) (*placement.Traverser, *container.Container, error) { // get network map by epoch nm, err := g.netMapSrc.GetNetMapByEpoch(epoch) if err != nil { - return nil, fmt.Errorf("could not get network map #%d: %w", epoch, err) + return nil, nil, fmt.Errorf("could not get network map #%d: %w", epoch, err) } // get container related container cnr, err := g.cnrSrc.Get(idCnr) if err != nil { - return nil, fmt.Errorf("could not get container: %w", err) + return nil, nil, fmt.Errorf("could not get container: %w", err) } // allocate placement traverser options @@ -160,5 +160,9 @@ func (g *TraverserGenerator) GenerateTraverser(idCnr cid.ID, idObj *oid.ID, epoc ) } - return placement.NewTraverser(traverseOpts...) + t, err := placement.NewTraverser(traverseOpts...) + if err != nil { + return nil, nil, err + } + return t, cnr, nil } From e83d39e33f901a2158f82434fb8b98bd0b0d9b2e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 15 Jul 2024 23:04:41 +0300 Subject: [PATCH 0699/1413] [#1253] deleteSvc: Use copy of common parameters getSvc may change the values of some fields, so Head will affect Delete or Put. In this case, the change is necessary so that the session token is stored in the tombstone object (EC assemble calls `ForgetTokens`). Signed-off-by: Dmitrii Stepanov --- pkg/services/object/delete/util.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/services/object/delete/util.go b/pkg/services/object/delete/util.go index bb2b5f00b7..a78fd77471 100644 --- a/pkg/services/object/delete/util.go +++ b/pkg/services/object/delete/util.go @@ -30,7 +30,12 @@ func (w *headSvcWrapper) headAddress(ctx context.Context, exec *execCtx, addr oi wr := getsvc.NewSimpleObjectWriter() p := getsvc.HeadPrm{} - p.SetCommonParameters(exec.commonParameters()) + + if cp := exec.commonParameters(); cp != nil { + commonParameters := *cp + p.SetCommonParameters(&commonParameters) + } + p.SetHeaderWriter(wr) p.WithRawFlag(true) p.WithAddress(addr) From 27caa8a72f68924721496be17d549e2325b0d081 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 17 Jul 2024 16:48:10 +0300 Subject: [PATCH 0700/1413] [#1256] metabase: Put split parent object ID for EC chunks It is required to save split parent ID too, not only split ID. Otherwise inhume operation works incorrect: shard with last part may be skipped and parent object will be available. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/put.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index ceb79758f1..f351cb485b 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -356,6 +356,18 @@ func updateListIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun return err } } + + if parentSplitParentID := ech.ParentSplitParentID(); parentSplitParentID != nil { + objKey := objectKey(ech.Parent(), make([]byte, objectKeySize)) + err := f(tx, namedBucketItem{ + name: parentBucketName(cnr, bucketName), + key: objectKey(*parentSplitParentID, make([]byte, objectKeySize)), + val: objKey, + }) + if err != nil { + return err + } + } } return nil From 5e5ee545b6c0f42c08c492fa325e0d43de0e93c2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 17 Jul 2024 14:30:51 +0300 Subject: [PATCH 0701/1413] [#1254] policer: Fix svacer warning Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/ec.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index 5b3793f7b3..0a118797dd 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -25,7 +25,7 @@ type ecChunkProcessResult struct { removeLocal bool } -var errInvalidECPlacement = errors.New("invalid EC placement: EC placement must have one placement vector") +var errInvalidECPlacement = errors.New("invalid EC placement: EC placement must have one placement vector with at least one node") func (p *Policer) processECContainerObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { if objInfo.ECInfo == nil { @@ -42,7 +42,7 @@ func (p *Policer) processECContainerRepObject(ctx context.Context, objInfo objec if err != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) } - if len(nn) != 1 { + if len(nn) != 1 || len(nn[0]) == 0 { return errInvalidECPlacement } @@ -72,7 +72,7 @@ func (p *Policer) processECContainerECObject(ctx context.Context, objInfo object if err != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) } - if len(nn) != 1 { + if len(nn) != 1 || len(nn[0]) == 0 { return errInvalidECPlacement } From eadcea8df057d6eb502161c0a2d1f202f0f843be Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 18 Jul 2024 13:23:17 +0300 Subject: [PATCH 0702/1413] [#1249] object: Remove all APE pre-checks in handlers * Methods `Head`, `Get`, `GetRangeHash` should no longer use APE pre-checks as that leads only to incorrect rule chain processing for requests: 1. Immediate return with `NoRuleFound` may be unexpected as some `Allow` rule is actually defined but can't be matched yet as it gets no object attributes; 2. Immdediate return with `Allow` may be incorrect as some `Deny` rule is actually defined but can't bet matched yet as it gets no object attirbutes; 3. Pre-check breaks compatibility for converted EACL-tables. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/service.go | 43 ------------------------------ 1 file changed, 43 deletions(-) diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 56c66002d2..2adb1b7367 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -134,33 +134,11 @@ func requestContext(ctx context.Context) (*objectSvc.RequestContext, error) { } func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectStream) error { - cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) - if err != nil { - return toStatusErr(err) - } - reqCtx, err := requestContext(stream.Context()) if err != nil { return toStatusErr(err) } - err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodGetObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, - WithoutHeaderRequest: true, - BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), - }) - if err != nil { - return toStatusErr(err) - } - return c.next.Get(request, &getStreamBasicChecker{ GetObjectStream: stream, apeChecker: c.apeChecker, @@ -237,23 +215,6 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj return nil, err } - err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, - Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, - WithoutHeaderRequest: true, - BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), - }) - if err != nil { - return nil, toStatusErr(err) - } - resp, err := c.next.Head(ctx, request) if err != nil { return nil, err @@ -417,10 +378,6 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa XHeaders: request.GetMetaHeader().GetXHeaders(), } - if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { - return nil, toStatusErr(err) - } - resp, err := c.next.GetRangeHash(ctx, request) if err != nil { return nil, err From e377a92d97f6732a1bbe9e815bd25e17fc02c6d3 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 19 Jul 2024 11:23:02 +0300 Subject: [PATCH 0703/1413] [#1258] audit: Fix panic in LogRequest method * Make `LogRequest` process `req=nil` to avoid panic. Signed-off-by: Airat Arifullin --- internal/audit/request.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/audit/request.go b/internal/audit/request.go index cd1771013f..cf07973004 100644 --- a/internal/audit/request.go +++ b/internal/audit/request.go @@ -18,7 +18,11 @@ type Target interface { } func LogRequest(log *logger.Logger, operation string, req Request, target Target, status bool) { - LogRequestWithKey(log, operation, req.GetVerificationHeader().GetBodySignature().GetKey(), target, status) + var key []byte + if req != nil { + key = req.GetVerificationHeader().GetBodySignature().GetKey() + } + LogRequestWithKey(log, operation, key, target, status) } func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target Target, status bool) { From 3119f2fbc3b3a38b9b4b8011cf0859235ab2963e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 18 Jul 2024 16:14:36 +0300 Subject: [PATCH 0704/1413] [#1257] metabase: Delete EC gc marks and split info EC parent and split gc marks should be deleted after last EC chunk delete. Also should delete split info for EC parent and split parent. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete.go | 75 +++ .../metabase/delete_ec_test.go | 459 ++++++++++++++++++ 2 files changed, 534 insertions(+) create mode 100644 pkg/local_object_storage/metabase/delete_ec_test.go diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 21b98fca17..ae10564a8a 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -314,6 +314,10 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter return deleteSingleResult{}, fmt.Errorf("could not remove object: %w", err) } + if err := deleteECRelatedInfo(tx, garbageBKT, obj, addr.Container(), refCounter); err != nil { + return deleteSingleResult{}, err + } + return deleteSingleResult{ Phy: true, Logic: removeAvailableObject, @@ -476,3 +480,74 @@ func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error return nil } + +func deleteECRelatedInfo(tx *bbolt.Tx, garbageBKT *bbolt.Bucket, obj *objectSDK.Object, cnr cid.ID, refCounter referenceCounter) error { + ech := obj.ECHeader() + if ech == nil { + return nil + } + + hasAnyChunks := hasAnyECChunks(tx, ech, cnr) + // drop EC parent GC mark if current EC chunk is the last one + if !hasAnyChunks && garbageBKT != nil { + var ecParentAddress oid.Address + ecParentAddress.SetContainer(cnr) + ecParentAddress.SetObject(ech.Parent()) + addrKey := addressKey(ecParentAddress, make([]byte, addressKeySize)) + err := garbageBKT.Delete(addrKey) + if err != nil { + return fmt.Errorf("could not remove EC parent from garbage bucket: %w", err) + } + } + + // also drop EC parent root info if current EC chunk is the last one + if !hasAnyChunks { + delUniqueIndexItem(tx, namedBucketItem{ + name: rootBucketName(cnr, make([]byte, bucketKeySize)), + key: objectKey(ech.Parent(), make([]byte, objectKeySize)), + }) + } + + if ech.ParentSplitParentID() == nil { + return nil + } + + var splitParentAddress oid.Address + splitParentAddress.SetContainer(cnr) + splitParentAddress.SetObject(*ech.ParentSplitParentID()) + + if ref, ok := refCounter[string(addressKey(splitParentAddress, make([]byte, addressKeySize)))]; ok { + // linking object is already processing + // so just inform that one more reference was deleted + // split info and gc marks will be deleted after linking object delete + ref.cur++ + return nil + } + + if parentLength(tx, splitParentAddress) > 0 { + // linking object still exists, so leave split info and gc mark deletion for linking object processing + return nil + } + + // drop split parent gc mark + if garbageBKT != nil { + addrKey := addressKey(splitParentAddress, make([]byte, addressKeySize)) + err := garbageBKT.Delete(addrKey) + if err != nil { + return fmt.Errorf("could not remove EC parent from garbage bucket: %w", err) + } + } + + // drop split info + delUniqueIndexItem(tx, namedBucketItem{ + name: rootBucketName(cnr, make([]byte, bucketKeySize)), + key: objectKey(*ech.ParentSplitParentID(), make([]byte, objectKeySize)), + }) + return nil +} + +func hasAnyECChunks(tx *bbolt.Tx, ech *objectSDK.ECHeader, cnr cid.ID) bool { + data := getFromBucket(tx, ecInfoBucketName(cnr, make([]byte, bucketKeySize)), + objectKey(ech.Parent(), make([]byte, objectKeySize))) + return len(data) > 0 +} diff --git a/pkg/local_object_storage/metabase/delete_ec_test.go b/pkg/local_object_storage/metabase/delete_ec_test.go new file mode 100644 index 0000000000..0e627f0959 --- /dev/null +++ b/pkg/local_object_storage/metabase/delete_ec_test.go @@ -0,0 +1,459 @@ +package meta + +import ( + "bytes" + "context" + "fmt" + "path/filepath" + "slices" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "github.com/stretchr/testify/require" + "go.etcd.io/bbolt" +) + +func TestDeleteECObject_WithoutSplit(t *testing.T) { + t.Parallel() + + db := New( + WithPath(filepath.Join(t.TempDir(), "metabase")), + WithPermissions(0o600), + WithEpochState(epochState{uint64(12)}), + ) + + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.Init()) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + ecChunk := oidtest.ID() + ecParent := oidtest.ID() + tombstoneID := oidtest.ID() + + chunkObj := testutil.GenerateObjectWithCID(cnr) + chunkObj.SetContainerID(cnr) + chunkObj.SetID(ecChunk) + chunkObj.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) + chunkObj.SetPayloadSize(uint64(10)) + chunkObj.SetECHeader(objectSDK.NewECHeader(objectSDK.ECParentInfo{ID: ecParent}, 0, 3, []byte{}, 0)) + + // put object with EC + + var prm PutPrm + prm.SetObject(chunkObj) + prm.SetStorageID([]byte("0/0")) + _, err := db.Put(context.Background(), prm) + require.NoError(t, err) + + var ecChunkAddress oid.Address + ecChunkAddress.SetContainer(cnr) + ecChunkAddress.SetObject(ecChunk) + + var ecParentAddress oid.Address + ecParentAddress.SetContainer(cnr) + ecParentAddress.SetObject(ecParent) + + var getPrm GetPrm + + getPrm.SetAddress(ecChunkAddress) + _, err = db.Get(context.Background(), getPrm) + require.NoError(t, err) + + var ecInfoError *objectSDK.ECInfoError + getPrm.SetAddress(ecParentAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, &ecInfoError) + require.True(t, len(ecInfoError.ECInfo().Chunks) == 1 && + ecInfoError.ECInfo().Chunks[0].Index == 0 && + ecInfoError.ECInfo().Chunks[0].Total == 3) + + // inhume EC parent (like Delete does) + + var inhumePrm InhumePrm + var tombAddress oid.Address + tombAddress.SetContainer(cnr) + tombAddress.SetObject(tombstoneID) + inhumePrm.SetAddresses(ecParentAddress) + inhumePrm.SetTombstoneAddress(tombAddress) + _, err = db.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + + getPrm.SetAddress(ecParentAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved)) + + getPrm.SetAddress(ecChunkAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved)) + + // GC finds and deletes split, EC parent and EC chunk + + var garbageAddresses []oid.Address + var itPrm GarbageIterationPrm + itPrm.SetHandler(func(g GarbageObject) error { + garbageAddresses = append(garbageAddresses, g.Address()) + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + require.Equal(t, 2, len(garbageAddresses)) + require.True(t, slices.Contains(garbageAddresses, ecParentAddress)) + require.True(t, slices.Contains(garbageAddresses, ecChunkAddress)) + + var deletePrm DeletePrm + deletePrm.SetAddresses(garbageAddresses...) + _, err = db.Delete(context.Background(), deletePrm) + require.NoError(t, err) + + garbageAddresses = nil + itPrm.SetHandler(func(g GarbageObject) error { + garbageAddresses = append(garbageAddresses, g.Address()) + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + require.Equal(t, 0, len(garbageAddresses)) + + // after tombstone expired GC inhumes tombstone and drops graves + + var tombstonedObjects []TombstonedObject + var graveyardIterationPrm GraveyardIterationPrm + graveyardIterationPrm.SetHandler(func(object TombstonedObject) error { + tombstonedObjects = append(tombstonedObjects, object) + return nil + }) + require.NoError(t, db.IterateOverGraveyard(context.Background(), graveyardIterationPrm)) + require.Equal(t, 2, len(tombstonedObjects)) + + var tombstones []oid.Address + for _, tss := range tombstonedObjects { + tombstones = append(tombstones, tss.tomb) + } + inhumePrm.SetAddresses(tombstones...) + inhumePrm.SetGCMark() + _, err = db.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + + require.NoError(t, db.DropGraves(context.Background(), tombstonedObjects)) + + // GC finds tombstone as garbage and deletes it + + garbageAddresses = nil + itPrm.SetHandler(func(g GarbageObject) error { + garbageAddresses = append(garbageAddresses, g.Address()) + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + require.Equal(t, 1, len(garbageAddresses)) + require.Equal(t, tombstoneID, garbageAddresses[0].Object()) + + deletePrm.SetAddresses(garbageAddresses...) + _, err = db.Delete(context.Background(), deletePrm) + require.NoError(t, err) + + // no more objects should left as garbage + + itPrm.SetHandler(func(g GarbageObject) error { + require.FailNow(t, "no garbage objects should left") + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + + require.NoError(t, db.boltDB.View(testVerifyNoObjectDataLeft)) + + require.NoError(t, testCountersAreZero(db, cnr)) +} + +func TestDeleteECObject_WithSplit(t *testing.T) { + t.Parallel() + for _, c := range []int{1, 2, 3} { + for _, l := range []bool{true, false} { + test := fmt.Sprintf("%d EC chunks with split info without linking object", c) + if l { + test = fmt.Sprintf("%d EC chunks with split info with linking object", c) + } + t.Run(test, func(t *testing.T) { + testDeleteECObjectWithSplit(t, c, l) + }) + } + } +} + +func testDeleteECObjectWithSplit(t *testing.T, chunksCount int, withLinking bool) { + t.Parallel() + + db := New( + WithPath(filepath.Join(t.TempDir(), "metabase")), + WithPermissions(0o600), + WithEpochState(epochState{uint64(12)}), + ) + + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.Init()) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + ecChunks := make([]oid.ID, chunksCount) + for idx := range ecChunks { + ecChunks[idx] = oidtest.ID() + } + ecParentID := oidtest.ID() + splitParentID := oidtest.ID() + tombstoneID := oidtest.ID() + splitID := objectSDK.NewSplitID() + linkingID := oidtest.ID() + + ecChunkObjects := make([]*objectSDK.Object, chunksCount) + for idx := range ecChunkObjects { + ecChunkObjects[idx] = testutil.GenerateObjectWithCID(cnr) + ecChunkObjects[idx].SetContainerID(cnr) + ecChunkObjects[idx].SetID(ecChunks[idx]) + ecChunkObjects[idx].SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) + ecChunkObjects[idx].SetPayloadSize(uint64(10)) + ecChunkObjects[idx].SetECHeader(objectSDK.NewECHeader( + objectSDK.ECParentInfo{ + ID: ecParentID, + SplitParentID: &splitParentID, SplitID: splitID, + }, uint32(idx), uint32(chunksCount+1), []byte{}, 0)) + } + + splitParentObj := testutil.GenerateObjectWithCID(cnr) + splitParentObj.SetID(splitParentID) + + var linkingAddress oid.Address + linkingAddress.SetContainer(cnr) + linkingAddress.SetObject(linkingID) + + linkingObj := testutil.GenerateObjectWithCID(cnr) + linkingObj.SetID(linkingID) + linkingObj.SetParent(splitParentObj) + linkingObj.SetParentID(splitParentID) + linkingObj.SetChildren(ecParentID, oidtest.ID(), oidtest.ID()) + linkingObj.SetSplitID(splitID) + + // put object with EC and split info + + var prm PutPrm + prm.SetStorageID([]byte("0/0")) + for _, obj := range ecChunkObjects { + prm.SetObject(obj) + _, err := db.Put(context.Background(), prm) + require.NoError(t, err) + } + + if withLinking { + prm.SetObject(linkingObj) + _, err := db.Put(context.Background(), prm) + require.NoError(t, err) + } + + var ecParentAddress oid.Address + ecParentAddress.SetContainer(cnr) + ecParentAddress.SetObject(ecParentID) + + var getPrm GetPrm + var ecInfoError *objectSDK.ECInfoError + getPrm.SetAddress(ecParentAddress) + _, err := db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, &ecInfoError) + require.True(t, len(ecInfoError.ECInfo().Chunks) == chunksCount) + + var splitParentAddress oid.Address + splitParentAddress.SetContainer(cnr) + splitParentAddress.SetObject(splitParentID) + + var splitInfoError *objectSDK.SplitInfoError + getPrm.SetAddress(splitParentAddress) + getPrm.SetRaw(true) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, &splitInfoError) + require.True(t, splitInfoError.SplitInfo() != nil) + require.Equal(t, splitID, splitInfoError.SplitInfo().SplitID()) + lastPart, set := splitInfoError.SplitInfo().LastPart() + require.True(t, set) + require.Equal(t, lastPart, ecParentID) + if withLinking { + l, ok := splitInfoError.SplitInfo().Link() + require.True(t, ok) + require.Equal(t, linkingID, l) + } + getPrm.SetRaw(false) + + // inhume EC parent and split objects (like Delete does) + + inhumeAddresses := []oid.Address{splitParentAddress, ecParentAddress} + if withLinking { + inhumeAddresses = append(inhumeAddresses, linkingAddress) + } + + var inhumePrm InhumePrm + var tombAddress oid.Address + tombAddress.SetContainer(cnr) + tombAddress.SetObject(tombstoneID) + inhumePrm.SetAddresses(inhumeAddresses...) + inhumePrm.SetTombstoneAddress(tombAddress) + _, err = db.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + + getPrm.SetAddress(ecParentAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved)) + + getPrm.SetAddress(splitParentAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved)) + + if withLinking { + getPrm.SetAddress(linkingAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved)) + } + + for _, id := range ecChunks { + var ecChunkAddress oid.Address + ecChunkAddress.SetContainer(cnr) + ecChunkAddress.SetObject(id) + getPrm.SetAddress(ecChunkAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved)) + } + + // GC finds and deletes split, EC parent and EC chunks + + parentCount := 2 // split + ec + if withLinking { + parentCount = 3 + } + + var garbageAddresses []oid.Address + var itPrm GarbageIterationPrm + itPrm.SetHandler(func(g GarbageObject) error { + garbageAddresses = append(garbageAddresses, g.Address()) + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + require.Equal(t, parentCount+chunksCount, len(garbageAddresses)) + require.True(t, slices.Contains(garbageAddresses, splitParentAddress)) + require.True(t, slices.Contains(garbageAddresses, ecParentAddress)) + if withLinking { + require.True(t, slices.Contains(garbageAddresses, linkingAddress)) + } + for _, id := range ecChunks { + var ecChunkAddress oid.Address + ecChunkAddress.SetContainer(cnr) + ecChunkAddress.SetObject(id) + require.True(t, slices.Contains(garbageAddresses, ecChunkAddress)) + } + + var deletePrm DeletePrm + deletePrm.SetAddresses(garbageAddresses...) + _, err = db.Delete(context.Background(), deletePrm) + require.NoError(t, err) + + var garbageStub []oid.Address + itPrm.SetHandler(func(g GarbageObject) error { + garbageStub = append(garbageStub, g.Address()) + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + require.Equal(t, 0, len(garbageStub)) + + // after tombstone expired GC inhumes tombstone and drops graves + + var tombstonedObjects []TombstonedObject + var graveyardIterationPrm GraveyardIterationPrm + graveyardIterationPrm.SetHandler(func(object TombstonedObject) error { + tombstonedObjects = append(tombstonedObjects, object) + return nil + }) + require.NoError(t, db.IterateOverGraveyard(context.Background(), graveyardIterationPrm)) + require.True(t, len(tombstonedObjects) == parentCount+chunksCount) + + var tombstones []oid.Address + for _, tss := range tombstonedObjects { + tombstones = append(tombstones, tss.tomb) + } + inhumePrm.SetAddresses(tombstones...) + inhumePrm.SetGCMark() + _, err = db.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + + require.NoError(t, db.DropGraves(context.Background(), tombstonedObjects)) + + // GC finds tombstone as garbage and deletes it + + garbageAddresses = nil + itPrm.SetHandler(func(g GarbageObject) error { + garbageAddresses = append(garbageAddresses, g.Address()) + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + require.Equal(t, 1, len(garbageAddresses)) + require.Equal(t, tombstoneID, garbageAddresses[0].Object()) + + deletePrm.SetAddresses(garbageAddresses...) + _, err = db.Delete(context.Background(), deletePrm) + require.NoError(t, err) + + // no more objects should left as garbage + + itPrm.SetHandler(func(g GarbageObject) error { + require.FailNow(t, "no garbage objects should left") + return nil + }) + require.NoError(t, db.IterateOverGarbage(context.Background(), itPrm)) + + require.NoError(t, db.boltDB.View(testVerifyNoObjectDataLeft)) + + require.NoError(t, testCountersAreZero(db, cnr)) +} + +func testVerifyNoObjectDataLeft(tx *bbolt.Tx) error { + return tx.ForEach(func(name []byte, b *bbolt.Bucket) error { + if bytes.Equal(name, shardInfoBucket) || + bytes.Equal(name, containerCounterBucketName) || + bytes.Equal(name, containerVolumeBucketName) { + return nil + } + return testBucketEmpty(name, b) + }) +} + +func testBucketEmpty(name []byte, b *bbolt.Bucket) error { + err := b.ForEach(func(k, v []byte) error { + if len(v) > 0 { + return fmt.Errorf("bucket %v is not empty", name) + } + return nil + }) + if err != nil { + return err + } + return b.ForEachBucket(func(k []byte) error { + return testBucketEmpty(k, b.Bucket(k)) + }) +} + +func testCountersAreZero(db *DB, cnr cid.ID) error { + c, err := db.ContainerCount(context.Background(), cnr) + if err != nil { + return err + } + if !c.IsZero() { + return fmt.Errorf("container %s has non zero counters", cnr.EncodeToString()) + } + s, err := db.ContainerSize(cnr) + if err != nil { + return err + } + if s != 0 { + return fmt.Errorf("container %s has non zero size", cnr.EncodeToString()) + } + return nil +} From 18182e578ec55fd035403e3915f5e4f66ad4c8c3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 22 Jul 2024 13:54:06 +0300 Subject: [PATCH 0705/1413] [#1261] shard: Fix delete objects from FSTree Replace nil storageID with empty like by shard.Get. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/delete.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index 44f6c6b487..c898fdf41b 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -117,6 +117,12 @@ func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error return err } storageID := res.StorageID() + if storageID == nil { + // if storageID is nil it means: + // 1. there is no such object + // 2. object stored by writecache: should not happen, as `validateWritecacheDoesntContainObject` called before `deleteFromBlobstor` + return nil + } var delPrm common.DeletePrm delPrm.Address = addr From ca4d6df1ccfd5e44093d313f8531451a28ffa0f4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 19 Jul 2024 09:28:36 +0300 Subject: [PATCH 0706/1413] Release v0.42.0 Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 24 ++++++++++++++++++++++++ VERSION | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2abba1d094..e4ba6a5d60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,30 @@ Changelog for FrostFS Node ### Removed ### Updated +## [v0.42.0] + +### Added +- Add audit logs for gRPC requests (#1184) +- Add CLI command to convert eACL to APE (#1189) +- Add `--await` flag to `control set-status` (#60) +- `app_info` metric for binary version (#1154) +- `--quiet` flag for healthcheck command (#1209) + +### Changed +- Deprecate Container.SetEACL RPC (#1219) + +### Fixed +- Take groups into account during APE processing (#1190) +- Handle double SIGHUP correctly (#1145) +- Handle empty filenames in tree listing (#1074) +- Handle duplicate tree nodes in the split-brain scenario (#1234, #1251) +- Remove APE pre-check in Object.GET/HEAD/RANGE RPC (#1249) +- Delete EC gc marks and split info (#1257) +- Do not search for non-existent objects on deletion (#1261) + +### Updated +- Make putting EC chunks more robust (#1233) + ## [v0.41.0] ### Added diff --git a/VERSION b/VERSION index 9dedf1e9be..01efe7f3aa 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.41.0 +v0.42.0 From 9ee1bd36697276bf2c91aad7e6f5d55ca5cbe376 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 23 Jul 2024 10:31:37 +0300 Subject: [PATCH 0707/1413] [#1265] *: Run gofumpt Signed-off-by: Aleksey Savchuk --- pkg/innerring/processors/netmap/process_epoch.go | 1 - pkg/innerring/processors/netmap/process_peers.go | 1 - 2 files changed, 2 deletions(-) diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index f3cb9837f9..4dfa3997b4 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -51,7 +51,6 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool { if epoch > 0 && np.alphabetState.IsAlphabet() { // estimates are invalid in genesis epoch err = np.containerWrp.StartEstimation(prm) - if err != nil { np.log.Warn(logs.NetmapCantStartContainerSizeEstimation, zap.Uint64("epoch", epoch), diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index 41e4bfb7ed..9e6e8c283a 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -83,7 +83,6 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { methodAddPeerNotary, nodeInfoBinary, ) - if err != nil { np.log.Error(logs.NetmapCantInvokeNetmapAddPeer, zap.Error(err)) return false From 658e3cb92f2901c95a28e6eb742aecfb63835469 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 23 Jul 2024 09:35:41 +0300 Subject: [PATCH 0708/1413] [#1264] go.mod: Update bbolt to v1.3.10 Signed-off-by: Evgenii Stratonikov --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ee8b1bb16e..a89520e348 100644 --- a/go.mod +++ b/go.mod @@ -34,13 +34,13 @@ require ( github.com/spf13/viper v1.18.2 github.com/ssgreg/journald v1.0.0 github.com/stretchr/testify v1.9.0 - go.etcd.io/bbolt v1.3.9 + go.etcd.io/bbolt v1.3.10 go.opentelemetry.io/otel v1.22.0 go.opentelemetry.io/otel/trace v1.22.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a golang.org/x/sync v0.6.0 - golang.org/x/sys v0.18.0 + golang.org/x/sys v0.22.0 golang.org/x/term v0.18.0 google.golang.org/grpc v1.63.2 google.golang.org/protobuf v1.33.0 diff --git a/go.sum b/go.sum index c7c3b87eb4..163c53b27f 100644 --- a/go.sum +++ b/go.sum @@ -285,8 +285,8 @@ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7Jul github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= -go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= +go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= @@ -379,8 +379,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= From 7ddba70030118f681396f3eae37b6e3de3b06162 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 23 Jul 2024 09:39:14 +0300 Subject: [PATCH 0709/1413] [#1264] go.mod: Update dependencies Signed-off-by: Evgenii Stratonikov --- go.mod | 26 ++++++++++++------------ go.sum | 62 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/go.mod b/go.mod index a89520e348..0f608f74d6 100644 --- a/go.mod +++ b/go.mod @@ -29,17 +29,17 @@ require ( github.com/paulmach/orb v0.11.0 github.com/prometheus/client_golang v1.19.0 github.com/spf13/cast v1.6.0 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 - github.com/spf13/viper v1.18.2 + github.com/spf13/viper v1.19.0 github.com/ssgreg/journald v1.0.0 github.com/stretchr/testify v1.9.0 go.etcd.io/bbolt v1.3.10 - go.opentelemetry.io/otel v1.22.0 - go.opentelemetry.io/otel/trace v1.22.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a - golang.org/x/sync v0.6.0 + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 + golang.org/x/sync v0.7.0 golang.org/x/sys v0.22.0 golang.org/x/term v0.18.0 google.golang.org/grpc v1.63.2 @@ -48,7 +48,7 @@ require ( ) require ( - github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect go.mongodb.org/mongo-driver v1.13.1 // indirect @@ -63,7 +63,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -98,7 +98,7 @@ require ( github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 // indirect github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d // indirect github.com/nspcc-dev/rfc6979 v0.2.1 // indirect - github.com/pelletier/go-toml/v2 v2.1.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect @@ -114,15 +114,15 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/sdk v1.22.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/net v0.23.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + golang.org/x/text v0.16.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 163c53b27f..355e176f7f 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 h1:tYj5Ydh5D7Xg2R1tJnoG36Yta7NVB8C0vx36oPA3Bbw= github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -213,8 +213,8 @@ github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnl github.com/paulmach/orb v0.11.0 h1:JfVXJUBeH9ifc/OrhBY0lL16QsmPgpCHMlqSSYhcgAA= github.com/paulmach/orb v0.11.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= @@ -234,8 +234,8 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= -github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= +github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -246,17 +246,18 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/ssgreg/journald v1.0.0 h1:0YmTDPJXxcWDPba12qNMdO6TxvfkFSYpFIJ31CwmLcU= github.com/ssgreg/journald v1.0.0/go.mod h1:RUckwmTM8ghGWPslq2+ZBZzbb9/2KgjzYZ4JEP+oRt0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -290,20 +291,20 @@ go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0 h1:zr8ymM5OWWjjiWRzwTfZ67c905+2TMHYp2lMJ52QTyM= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0/go.mod h1:sQs7FT2iLVJ+67vYngGJkPe1qr39IzaBzaj9IDNNY8k= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -321,14 +322,14 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= -golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -353,8 +354,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -395,8 +396,9 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -404,19 +406,17 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= -golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= -google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0= -google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= From 94f07b4778693842cbc7ac8e6b9228a688e71da1 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 23 Jul 2024 12:15:20 +0300 Subject: [PATCH 0710/1413] [#1245] docker: Fix warnings Signed-off-by: Ekaterina Lebedeva --- .docker/Dockerfile.adm | 2 +- .docker/Dockerfile.cli | 2 +- .docker/Dockerfile.ir | 2 +- .docker/Dockerfile.storage | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.docker/Dockerfile.adm b/.docker/Dockerfile.adm index b3dad06d3d..5d67a1d04c 100644 --- a/.docker/Dockerfile.adm +++ b/.docker/Dockerfile.adm @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.22 AS builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.cli b/.docker/Dockerfile.cli index 5adedc1408..16f643b614 100644 --- a/.docker/Dockerfile.cli +++ b/.docker/Dockerfile.cli @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.22 AS builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ir b/.docker/Dockerfile.ir index 25025bb2fa..f2cb764e53 100644 --- a/.docker/Dockerfile.ir +++ b/.docker/Dockerfile.ir @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.22 AS builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.storage b/.docker/Dockerfile.storage index a16005516a..cf7f977480 100644 --- a/.docker/Dockerfile.storage +++ b/.docker/Dockerfile.storage @@ -1,4 +1,4 @@ -FROM golang:1.22 as builder +FROM golang:1.22 AS builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository From 1032075a2195c07a46d303b254c6f08cb032f93c Mon Sep 17 00:00:00 2001 From: George Bartolomey Date: Mon, 22 Jul 2024 11:08:09 +0300 Subject: [PATCH 0711/1413] [#1259] cli: Remove locode subcommand Removed `frostfs-cli util locode` subcommand. Alternative command could be found in `git.frostfs.info/TrueCloudLab/frostfs-locode-db`. Signed-off-by: George Bartolomey --- cmd/frostfs-cli/modules/util/locode.go | 18 ---- .../modules/util/locode_generate.go | 96 ------------------- cmd/frostfs-cli/modules/util/locode_info.go | 56 ----------- cmd/frostfs-cli/modules/util/root.go | 2 - 4 files changed, 172 deletions(-) delete mode 100644 cmd/frostfs-cli/modules/util/locode.go delete mode 100644 cmd/frostfs-cli/modules/util/locode_generate.go delete mode 100644 cmd/frostfs-cli/modules/util/locode_info.go diff --git a/cmd/frostfs-cli/modules/util/locode.go b/cmd/frostfs-cli/modules/util/locode.go deleted file mode 100644 index a1f0f4d3fd..0000000000 --- a/cmd/frostfs-cli/modules/util/locode.go +++ /dev/null @@ -1,18 +0,0 @@ -package util - -import ( - "github.com/spf13/cobra" -) - -// locode section. -var locodeCmd = &cobra.Command{ - Use: "locode", - Short: "Working with FrostFS UN/LOCODE database", -} - -func initLocodeCmd() { - locodeCmd.AddCommand(locodeGenerateCmd, locodeInfoCmd) - - initUtilLocodeInfoCmd() - initUtilLocodeGenerateCmd() -} diff --git a/cmd/frostfs-cli/modules/util/locode_generate.go b/cmd/frostfs-cli/modules/util/locode_generate.go deleted file mode 100644 index 319dee1c6b..0000000000 --- a/cmd/frostfs-cli/modules/util/locode_generate.go +++ /dev/null @@ -1,96 +0,0 @@ -package util - -import ( - commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" - airportsdb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db/airports" - locodebolt "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db/boltdb" - continentsdb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db/continents/geojson" - csvlocode "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/table/csv" - "github.com/spf13/cobra" -) - -type namesDB struct { - *airportsdb.DB - *csvlocode.Table -} - -const ( - locodeGenerateInputFlag = "in" - locodeGenerateSubDivFlag = "subdiv" - locodeGenerateAirportsFlag = "airports" - locodeGenerateCountriesFlag = "countries" - locodeGenerateContinentsFlag = "continents" - locodeGenerateOutputFlag = "out" -) - -var ( - locodeGenerateInPaths []string - locodeGenerateSubDivPath string - locodeGenerateAirportsPath string - locodeGenerateCountriesPath string - locodeGenerateContinentsPath string - locodeGenerateOutPath string - - locodeGenerateCmd = &cobra.Command{ - Use: "generate", - Short: "Generate UN/LOCODE database for FrostFS", - Run: func(cmd *cobra.Command, _ []string) { - locodeDB := csvlocode.New( - csvlocode.Prm{ - Path: locodeGenerateInPaths[0], - SubDivPath: locodeGenerateSubDivPath, - }, - csvlocode.WithExtraPaths(locodeGenerateInPaths[1:]...), - ) - - airportDB := airportsdb.New(airportsdb.Prm{ - AirportsPath: locodeGenerateAirportsPath, - CountriesPath: locodeGenerateCountriesPath, - }) - - continentsDB := continentsdb.New(continentsdb.Prm{ - Path: locodeGenerateContinentsPath, - }) - - targetDB := locodebolt.New(locodebolt.Prm{ - Path: locodeGenerateOutPath, - }) - - err := targetDB.Open() - commonCmd.ExitOnErr(cmd, "", err) - - defer targetDB.Close() - - names := &namesDB{ - DB: airportDB, - Table: locodeDB, - } - - err = locodedb.FillDatabase(locodeDB, airportDB, continentsDB, names, targetDB) - commonCmd.ExitOnErr(cmd, "", err) - }, - } -) - -func initUtilLocodeGenerateCmd() { - flags := locodeGenerateCmd.Flags() - - flags.StringSliceVar(&locodeGenerateInPaths, locodeGenerateInputFlag, nil, "List of paths to UN/LOCODE tables (csv)") - _ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateInputFlag) - - flags.StringVar(&locodeGenerateSubDivPath, locodeGenerateSubDivFlag, "", "Path to UN/LOCODE subdivision database (csv)") - _ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateSubDivFlag) - - flags.StringVar(&locodeGenerateAirportsPath, locodeGenerateAirportsFlag, "", "Path to OpenFlights airport database (csv)") - _ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateAirportsFlag) - - flags.StringVar(&locodeGenerateCountriesPath, locodeGenerateCountriesFlag, "", "Path to OpenFlights country database (csv)") - _ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateCountriesFlag) - - flags.StringVar(&locodeGenerateContinentsPath, locodeGenerateContinentsFlag, "", "Path to continent polygons (GeoJSON)") - _ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateContinentsFlag) - - flags.StringVar(&locodeGenerateOutPath, locodeGenerateOutputFlag, "", "Target path for generated database") - _ = locodeGenerateCmd.MarkFlagRequired(locodeGenerateOutputFlag) -} diff --git a/cmd/frostfs-cli/modules/util/locode_info.go b/cmd/frostfs-cli/modules/util/locode_info.go deleted file mode 100644 index e89252dea5..0000000000 --- a/cmd/frostfs-cli/modules/util/locode_info.go +++ /dev/null @@ -1,56 +0,0 @@ -package util - -import ( - commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" - locodebolt "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db/boltdb" - "github.com/spf13/cobra" -) - -const ( - locodeInfoDBFlag = "db" - locodeInfoCodeFlag = "locode" -) - -var ( - locodeInfoDBPath string - locodeInfoCode string - - locodeInfoCmd = &cobra.Command{ - Use: "info", - Short: "Print information about UN/LOCODE from FrostFS database", - Run: func(cmd *cobra.Command, _ []string) { - targetDB := locodebolt.New(locodebolt.Prm{ - Path: locodeInfoDBPath, - }, locodebolt.ReadOnly()) - - err := targetDB.Open() - commonCmd.ExitOnErr(cmd, "", err) - - defer targetDB.Close() - - record, err := locodedb.LocodeRecord(targetDB, locodeInfoCode) - commonCmd.ExitOnErr(cmd, "", err) - - cmd.Printf("Country: %s\n", record.CountryName()) - cmd.Printf("Location: %s\n", record.LocationName()) - cmd.Printf("Continent: %s\n", record.Continent()) - if subDivCode := record.SubDivCode(); subDivCode != "" { - cmd.Printf("Subdivision: [%s] %s\n", subDivCode, record.SubDivName()) - } - - geoPoint := record.GeoPoint() - cmd.Printf("Coordinates: %0.2f, %0.2f\n", geoPoint.Latitude(), geoPoint.Longitude()) - }, - } -) - -func initUtilLocodeInfoCmd() { - flags := locodeInfoCmd.Flags() - - flags.StringVar(&locodeInfoDBPath, locodeInfoDBFlag, "", "Path to FrostFS UN/LOCODE database") - _ = locodeInfoCmd.MarkFlagRequired(locodeInfoDBFlag) - - flags.StringVar(&locodeInfoCode, locodeInfoCodeFlag, "", "UN/LOCODE") - _ = locodeInfoCmd.MarkFlagRequired(locodeInfoCodeFlag) -} diff --git a/cmd/frostfs-cli/modules/util/root.go b/cmd/frostfs-cli/modules/util/root.go index 4a6b4403bb..a909e68990 100644 --- a/cmd/frostfs-cli/modules/util/root.go +++ b/cmd/frostfs-cli/modules/util/root.go @@ -23,11 +23,9 @@ func init() { signCmd, convertCmd, keyerCmd, - locodeCmd, ) initSignCmd() initConvertCmd() initKeyerCmd() - initLocodeCmd() } From 9c2c76ca32be3aef1169480fdce203e3947805d3 Mon Sep 17 00:00:00 2001 From: George Bartolomey Date: Mon, 22 Jul 2024 11:12:41 +0300 Subject: [PATCH 0712/1413] [#1259] Move pkg/util/locode to frostfs-locode-db Removed pkg/util/locode package, added git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode dependency. Signed-off-by: George Bartolomey --- go.mod | 3 +- go.sum | 39 +--- pkg/innerring/locode.go | 6 +- .../netmap/nodevalidation/locode/calls.go | 2 +- .../nodevalidation/locode/calls_test.go | 4 +- .../netmap/nodevalidation/locode/deps.go | 4 +- pkg/util/locode/column/coordinates.go | 193 ----------------- pkg/util/locode/column/country.go | 38 ---- pkg/util/locode/column/location.go | 38 ---- pkg/util/locode/column/util.go | 9 - pkg/util/locode/db/airports/calls.go | 194 ------------------ pkg/util/locode/db/airports/db.go | 83 -------- pkg/util/locode/db/airports/opts.go | 19 -- pkg/util/locode/db/boltdb/calls.go | 166 --------------- pkg/util/locode/db/boltdb/db.go | 73 ------- pkg/util/locode/db/boltdb/opts.go | 37 ---- pkg/util/locode/db/continent.go | 81 -------- .../locode/db/continents/geojson/calls.go | 98 --------- pkg/util/locode/db/continents/geojson/db.go | 63 ------ pkg/util/locode/db/continents/geojson/opts.go | 10 - pkg/util/locode/db/country.go | 32 --- pkg/util/locode/db/db.go | 183 ----------------- pkg/util/locode/db/location.go | 32 --- pkg/util/locode/db/point.go | 93 --------- pkg/util/locode/db/point_test.go | 51 ----- pkg/util/locode/db/record.go | 140 ------------- pkg/util/locode/record.go | 83 -------- pkg/util/locode/table/csv/calls.go | 156 -------------- pkg/util/locode/table/csv/opts.go | 28 --- pkg/util/locode/table/csv/table.go | 75 ------- 30 files changed, 11 insertions(+), 2022 deletions(-) delete mode 100644 pkg/util/locode/column/coordinates.go delete mode 100644 pkg/util/locode/column/country.go delete mode 100644 pkg/util/locode/column/location.go delete mode 100644 pkg/util/locode/column/util.go delete mode 100644 pkg/util/locode/db/airports/calls.go delete mode 100644 pkg/util/locode/db/airports/db.go delete mode 100644 pkg/util/locode/db/airports/opts.go delete mode 100644 pkg/util/locode/db/boltdb/calls.go delete mode 100644 pkg/util/locode/db/boltdb/db.go delete mode 100644 pkg/util/locode/db/boltdb/opts.go delete mode 100644 pkg/util/locode/db/continent.go delete mode 100644 pkg/util/locode/db/continents/geojson/calls.go delete mode 100644 pkg/util/locode/db/continents/geojson/db.go delete mode 100644 pkg/util/locode/db/continents/geojson/opts.go delete mode 100644 pkg/util/locode/db/country.go delete mode 100644 pkg/util/locode/db/db.go delete mode 100644 pkg/util/locode/db/location.go delete mode 100644 pkg/util/locode/db/point.go delete mode 100644 pkg/util/locode/db/point_test.go delete mode 100644 pkg/util/locode/db/record.go delete mode 100644 pkg/util/locode/record.go delete mode 100644 pkg/util/locode/table/csv/calls.go delete mode 100644 pkg/util/locode/table/csv/opts.go delete mode 100644 pkg/util/locode/table/csv/table.go diff --git a/go.mod b/go.mod index 0f608f74d6..6a97f7850f 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 + git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de git.frostfs.info/TrueCloudLab/hrw v1.2.1 @@ -26,7 +27,6 @@ require ( github.com/nspcc-dev/neo-go v0.106.0 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 - github.com/paulmach/orb v0.11.0 github.com/prometheus/client_golang v1.19.0 github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.1 @@ -51,7 +51,6 @@ require ( github.com/sagikazarmark/locafero v0.6.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect - go.mongodb.org/mongo-driver v1.13.1 // indirect ) require ( diff --git a/go.sum b/go.sum index 355e176f7f..d4cf863fab 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= +git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= +git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de h1:OjsWY0jpGJV1t87XgwL/3PsDx7fJ6lfNMXtY8UhoUbM= @@ -81,7 +83,6 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-pkgz/expirable-cache/v3 v3.0.0 h1:u3/gcu3sabLYiTCevoRKv+WzjIn5oo7P8XtiXBeRDLw= github.com/go-pkgz/expirable-cache/v3 v3.0.0/go.mod h1:2OQiDyEGQalYecLWmXprm3maPXeVb5/6/X7yRPYTzec= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -91,13 +92,11 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -129,20 +128,14 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= 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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/reedsolomon v1.12.1 h1:NhWgum1efX1x58daOBGCFWcxtEhOhXKKl1HAPQUp03Q= github.com/klauspost/reedsolomon v1.12.1/go.mod h1:nEi5Kjb6QqtbofI6s+cbG/j1da11c96IBYBSnVGtuBs= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= @@ -171,7 +164,6 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR 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/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= 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/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= @@ -210,12 +202,8 @@ github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo= github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= -github.com/paulmach/orb v0.11.0 h1:JfVXJUBeH9ifc/OrhBY0lL16QsmPgpCHMlqSSYhcgAA= -github.com/paulmach/orb v0.11.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= -github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -259,7 +247,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= @@ -272,25 +259,14 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= -go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= -go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= -go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= @@ -318,13 +294,11 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -333,12 +307,10 @@ golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -348,9 +320,7 @@ golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -393,7 +363,6 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= @@ -401,9 +370,7 @@ golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= @@ -427,11 +394,9 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/pkg/innerring/locode.go b/pkg/innerring/locode.go index a9a9498b6e..a0c3ea7518 100644 --- a/pkg/innerring/locode.go +++ b/pkg/innerring/locode.go @@ -1,11 +1,11 @@ package innerring import ( + "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode" + locodedb "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode/db" + locodebolt "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode/db/boltdb" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap" irlocode "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/locode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" - locodebolt "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db/boltdb" "github.com/spf13/viper" ) diff --git a/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go b/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go index d071a7792a..5e0558344f 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go +++ b/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" + "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" ) diff --git a/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go b/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go index 6697391e88..8ab174dfda 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go +++ b/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go @@ -5,9 +5,9 @@ import ( "fmt" "testing" + locodestd "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode" + locodedb "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode/db" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/locode" - locodestd "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/stretchr/testify/require" ) diff --git a/pkg/innerring/processors/netmap/nodevalidation/locode/deps.go b/pkg/innerring/processors/netmap/nodevalidation/locode/deps.go index e6332261ea..8f66679339 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/locode/deps.go +++ b/pkg/innerring/processors/netmap/nodevalidation/locode/deps.go @@ -1,8 +1,8 @@ package locode import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" + "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode" + locodedb "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode/db" ) // Record is an interface of read-only diff --git a/pkg/util/locode/column/coordinates.go b/pkg/util/locode/column/coordinates.go deleted file mode 100644 index 5e32c016e1..0000000000 --- a/pkg/util/locode/column/coordinates.go +++ /dev/null @@ -1,193 +0,0 @@ -package locodecolumn - -import ( - "fmt" - "strings" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" -) - -const ( - minutesDigits = 2 - hemisphereSymbols = 1 -) - -const ( - latDegDigits = 2 - lngDegDigits = 3 -) - -type coordinateCode struct { - degDigits int - value []uint8 -} - -// LongitudeCode represents the value of the longitude -// of the location conforming to UN/LOCODE specification. -type LongitudeCode coordinateCode - -// LongitudeHemisphere represents the hemisphere of the earth -// // along the Greenwich meridian. -type LongitudeHemisphere [hemisphereSymbols]uint8 - -// LatitudeCode represents the value of the latitude -// of the location conforming to UN/LOCODE specification. -type LatitudeCode coordinateCode - -// LatitudeHemisphere represents the hemisphere of the earth -// along the equator. -type LatitudeHemisphere [hemisphereSymbols]uint8 - -func coordinateFromString(s string, degDigits int, hemisphereAlphabet []uint8) (*coordinateCode, error) { - if len(s) != degDigits+minutesDigits+hemisphereSymbols { - return nil, locode.ErrInvalidString - } - - for i := range s[:degDigits+minutesDigits] { - if !isDigit(s[i]) { - return nil, locode.ErrInvalidString - } - } - -loop: - for _, sym := range s[degDigits+minutesDigits:] { - for j := range hemisphereAlphabet { - if hemisphereAlphabet[j] == uint8(sym) { - continue loop - } - } - - return nil, locode.ErrInvalidString - } - - return &coordinateCode{ - degDigits: degDigits, - value: []uint8(s), - }, nil -} - -// LongitudeFromString parses a string and returns the location's longitude. -func LongitudeFromString(s string) (*LongitudeCode, error) { - cc, err := coordinateFromString(s, lngDegDigits, []uint8{'W', 'E'}) - if err != nil { - return nil, err - } - - return (*LongitudeCode)(cc), nil -} - -// LatitudeFromString parses a string and returns the location's latitude. -func LatitudeFromString(s string) (*LatitudeCode, error) { - cc, err := coordinateFromString(s, latDegDigits, []uint8{'N', 'S'}) - if err != nil { - return nil, err - } - - return (*LatitudeCode)(cc), nil -} - -func (cc *coordinateCode) degrees() []uint8 { - return cc.value[:cc.degDigits] -} - -// Degrees returns the longitude's degrees. -func (lc *LongitudeCode) Degrees() (l [lngDegDigits]uint8) { - copy(l[:], (*coordinateCode)(lc).degrees()) - return -} - -// Degrees returns the latitude's degrees. -func (lc *LatitudeCode) Degrees() (l [latDegDigits]uint8) { - copy(l[:], (*coordinateCode)(lc).degrees()) - return -} - -func (cc *coordinateCode) minutes() (mnt [minutesDigits]uint8) { - for i := 0; i < minutesDigits; i++ { - mnt[i] = cc.value[cc.degDigits+i] - } - - return -} - -// Minutes returns the longitude's minutes. -func (lc *LongitudeCode) Minutes() [minutesDigits]uint8 { - return (*coordinateCode)(lc).minutes() -} - -// Minutes returns the latitude's minutes. -func (lc *LatitudeCode) Minutes() [minutesDigits]uint8 { - return (*coordinateCode)(lc).minutes() -} - -// Hemisphere returns the longitude's hemisphere code. -func (lc *LongitudeCode) Hemisphere() LongitudeHemisphere { - return (*coordinateCode)(lc).hemisphere() -} - -// Hemisphere returns the latitude's hemisphere code. -func (lc *LatitudeCode) Hemisphere() LatitudeHemisphere { - return (*coordinateCode)(lc).hemisphere() -} - -func (cc *coordinateCode) hemisphere() (h [hemisphereSymbols]uint8) { - for i := 0; i < hemisphereSymbols; i++ { - h[i] = cc.value[cc.degDigits+minutesDigits+i] - } - - return h -} - -// North returns true for the northern hemisphere. -func (h LatitudeHemisphere) North() bool { - return h[0] == 'N' -} - -// East returns true for the eastern hemisphere. -func (h LongitudeHemisphere) East() bool { - return h[0] == 'E' -} - -// Coordinates represents the coordinates of the location from UN/LOCODE table. -type Coordinates struct { - lat *LatitudeCode - - lng *LongitudeCode -} - -// Latitude returns the location's latitude. -func (c *Coordinates) Latitude() *LatitudeCode { - return c.lat -} - -// Longitude returns the location's longitude. -func (c *Coordinates) Longitude() *LongitudeCode { - return c.lng -} - -// CoordinatesFromString parses a string and returns the location's coordinates. -func CoordinatesFromString(s string) (*Coordinates, error) { - if len(s) == 0 { - return nil, nil - } - - strs := strings.Split(s, " ") - if len(strs) != 2 { - return nil, locode.ErrInvalidString - } - - lat, err := LatitudeFromString(strs[0]) - if err != nil { - return nil, fmt.Errorf("could not parse latitude: %w", err) - } - - lng, err := LongitudeFromString(strs[1]) - if err != nil { - return nil, fmt.Errorf("could not parse longitude: %w", err) - } - - return &Coordinates{ - lat: lat, - lng: lng, - }, nil -} diff --git a/pkg/util/locode/column/country.go b/pkg/util/locode/column/country.go deleted file mode 100644 index 7b29a97c5e..0000000000 --- a/pkg/util/locode/column/country.go +++ /dev/null @@ -1,38 +0,0 @@ -package locodecolumn - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" -) - -const countryCodeLen = 2 - -// CountryCode represents ISO 3166 alpha-2 Country Code. -type CountryCode [countryCodeLen]uint8 - -// Symbols returns digits of the country code. -func (cc *CountryCode) Symbols() [countryCodeLen]uint8 { - return *cc -} - -// CountryCodeFromString parses a string and returns the country code. -func CountryCodeFromString(s string) (*CountryCode, error) { - if l := len(s); l != countryCodeLen { - return nil, fmt.Errorf("incorrect country code length: expect: %d, got: %d", - countryCodeLen, - l, - ) - } - - for i := range s { - if !isUpperAlpha(s[i]) { - return nil, locode.ErrInvalidString - } - } - - cc := CountryCode{} - copy(cc[:], s) - - return &cc, nil -} diff --git a/pkg/util/locode/column/location.go b/pkg/util/locode/column/location.go deleted file mode 100644 index 4303228fb7..0000000000 --- a/pkg/util/locode/column/location.go +++ /dev/null @@ -1,38 +0,0 @@ -package locodecolumn - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" -) - -const locationCodeLen = 3 - -// LocationCode represents 3-character code for the location. -type LocationCode [locationCodeLen]uint8 - -// Symbols returns characters of the location code. -func (lc *LocationCode) Symbols() [locationCodeLen]uint8 { - return *lc -} - -// LocationCodeFromString parses a string and returns the location code. -func LocationCodeFromString(s string) (*LocationCode, error) { - if l := len(s); l != locationCodeLen { - return nil, fmt.Errorf("incorrect location code length: expect: %d, got: %d", - locationCodeLen, - l, - ) - } - - for i := range s { - if !isUpperAlpha(s[i]) && !isDigit(s[i]) { - return nil, locode.ErrInvalidString - } - } - - lc := LocationCode{} - copy(lc[:], s) - - return &lc, nil -} diff --git a/pkg/util/locode/column/util.go b/pkg/util/locode/column/util.go deleted file mode 100644 index 8da1f9a257..0000000000 --- a/pkg/util/locode/column/util.go +++ /dev/null @@ -1,9 +0,0 @@ -package locodecolumn - -func isDigit(sym uint8) bool { - return sym >= '0' && sym <= '9' -} - -func isUpperAlpha(sym uint8) bool { - return sym >= 'A' && sym <= 'Z' -} diff --git a/pkg/util/locode/db/airports/calls.go b/pkg/util/locode/db/airports/calls.go deleted file mode 100644 index dac8cce8b8..0000000000 --- a/pkg/util/locode/db/airports/calls.go +++ /dev/null @@ -1,194 +0,0 @@ -package airportsdb - -import ( - "encoding/csv" - "errors" - "fmt" - "io" - "os" - "strconv" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" -) - -const ( - _ = iota - 1 - - _ // Airport ID - _ // Name - airportCity - airportCountry - airportIATA - _ // ICAO - airportLatitude - airportLongitude - _ // Altitude - _ // Timezone - _ // DST - _ // Tz database time zone - _ // Type - _ // Source - - airportFldNum -) - -type record struct { - city, - country, - iata, - lat, - lng string -} - -// Get scans the records of the OpenFlights Airport to an in-memory table (once), -// and returns an entry that matches the passed UN/LOCODE record. -// -// Records are matched if they have the same country code and either -// same IATA code or same city name (location name in UN/LOCODE). -// -// Returns locodedb.ErrAirportNotFound if no entry matches. -func (db *DB) Get(locodeRecord locode.Record) (*locodedb.AirportRecord, error) { - if err := db.initAirports(); err != nil { - return nil, err - } - - records := db.mAirports[locodeRecord.LOCODE.CountryCode()] - - for i := range records { - if locodeRecord.LOCODE.LocationCode() != records[i].iata && - locodeRecord.NameWoDiacritics != records[i].city { - continue - } - - lat, err := strconv.ParseFloat(records[i].lat, 64) - if err != nil { - return nil, err - } - - lng, err := strconv.ParseFloat(records[i].lng, 64) - if err != nil { - return nil, err - } - - return &locodedb.AirportRecord{ - CountryName: records[i].country, - Point: locodedb.NewPoint(lat, lng), - }, nil - } - - return nil, locodedb.ErrAirportNotFound -} - -const ( - _ = iota - 1 - - countryName - countryISOCode - _ // dafif_code - - countryFldNum -) - -// CountryName scans the records of the OpenFlights Country table to an in-memory table (once), -// and returns the name of the country by code. -// -// Returns locodedb.ErrCountryNotFound if no entry matches. -func (db *DB) CountryName(code *locodedb.CountryCode) (name string, err error) { - if err = db.initCountries(); err != nil { - return - } - - argCode := code.String() - - for cName, cCode := range db.mCountries { - if cCode == argCode { - name = cName - break - } - } - - if name == "" { - err = locodedb.ErrCountryNotFound - } - - return -} - -func (db *DB) initAirports() (err error) { - db.airportsOnce.Do(func() { - db.mAirports = make(map[string][]record) - - if err = db.initCountries(); err != nil { - return - } - - err = db.scanWords(db.airports, airportFldNum, func(words []string) error { - countryCode := db.mCountries[words[airportCountry]] - if countryCode != "" { - db.mAirports[countryCode] = append(db.mAirports[countryCode], record{ - city: words[airportCity], - country: words[airportCountry], - iata: words[airportIATA], - lat: words[airportLatitude], - lng: words[airportLongitude], - }) - } - - return nil - }) - }) - - return -} - -func (db *DB) initCountries() (err error) { - db.countriesOnce.Do(func() { - db.mCountries = make(map[string]string) - - err = db.scanWords(db.countries, countryFldNum, func(words []string) error { - db.mCountries[words[countryName]] = words[countryISOCode] - - return nil - }) - }) - - return -} - -var errScanInt = errors.New("interrupt scan") - -func (db *DB) scanWords(pm pathMode, num int, wordsHandler func([]string) error) error { - tableFile, err := os.OpenFile(pm.path, os.O_RDONLY, pm.mode) - if err != nil { - return err - } - - defer tableFile.Close() - - r := csv.NewReader(tableFile) - r.ReuseRecord = true - - for { - words, err := r.Read() - if err != nil { - if errors.Is(err, io.EOF) { - break - } - - return err - } else if ln := len(words); ln != num { - return fmt.Errorf("unexpected number of words %d", ln) - } - - if err := wordsHandler(words); err != nil { - if errors.Is(err, errScanInt) { - break - } - - return err - } - } - - return nil -} diff --git a/pkg/util/locode/db/airports/db.go b/pkg/util/locode/db/airports/db.go deleted file mode 100644 index acfa3fd607..0000000000 --- a/pkg/util/locode/db/airports/db.go +++ /dev/null @@ -1,83 +0,0 @@ -package airportsdb - -import ( - "fmt" - "io/fs" - "sync" -) - -// Prm groups the required parameters of the DB's constructor. -// -// All values must comply with the requirements imposed on them. -// Passing incorrect parameter values will result in constructor -// failure (error or panic depending on the implementation). -type Prm struct { - // Path to OpenFlights Airport csv table. - // - // Must not be empty. - AirportsPath string - - // Path to OpenFlights Countries csv table. - // - // Must not be empty. - CountriesPath string -} - -// DB is a descriptor of the OpenFlights database in csv format. -// -// For correct operation, DB must be created -// using the constructor (New) based on the required parameters -// and optional components. After successful creation, -// The DB is immediately ready to work through API. -type DB struct { - airports, countries pathMode - - airportsOnce, countriesOnce sync.Once - - mCountries map[string]string - - mAirports map[string][]record -} - -type pathMode struct { - path string - mode fs.FileMode -} - -const invalidPrmValFmt = "invalid parameter %s (%T):%v" - -func panicOnPrmValue(n string, v any) { - panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) -} - -// New creates a new instance of the DB. -// -// Panics if at least one value of the parameters is invalid. -// -// The created DB does not require additional -// initialization and is completely ready for work. -func New(prm Prm, opts ...Option) *DB { - switch { - case prm.AirportsPath == "": - panicOnPrmValue("AirportsPath", prm.AirportsPath) - case prm.CountriesPath == "": - panicOnPrmValue("CountriesPath", prm.CountriesPath) - } - - o := defaultOpts() - - for i := range opts { - opts[i](o) - } - - return &DB{ - airports: pathMode{ - path: prm.AirportsPath, - mode: o.airportMode, - }, - countries: pathMode{ - path: prm.CountriesPath, - mode: o.countryMode, - }, - } -} diff --git a/pkg/util/locode/db/airports/opts.go b/pkg/util/locode/db/airports/opts.go deleted file mode 100644 index 3799d9e270..0000000000 --- a/pkg/util/locode/db/airports/opts.go +++ /dev/null @@ -1,19 +0,0 @@ -package airportsdb - -import ( - "io/fs" -) - -// Option sets an optional parameter of DB. -type Option func(*options) - -type options struct { - airportMode, countryMode fs.FileMode -} - -func defaultOpts() *options { - return &options{ - airportMode: fs.ModePerm, // 0777 - countryMode: fs.ModePerm, // 0777 - } -} diff --git a/pkg/util/locode/db/boltdb/calls.go b/pkg/util/locode/db/boltdb/calls.go deleted file mode 100644 index 6a80def3a9..0000000000 --- a/pkg/util/locode/db/boltdb/calls.go +++ /dev/null @@ -1,166 +0,0 @@ -package locodebolt - -import ( - "encoding/json" - "errors" - "fmt" - "path/filepath" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" - "go.etcd.io/bbolt" -) - -// Open opens an underlying BoltDB instance. -// -// Timeout of BoltDB opening is 3s (only for Linux or Darwin). -// -// Opens BoltDB in read-only mode if DB is read-only. -func (db *DB) Open() error { - // copy-paste from metabase: - // consider universal Open/Close for BoltDB wrappers - - err := util.MkdirAllX(filepath.Dir(db.path), db.mode) - if err != nil { - return fmt.Errorf("could not create dir for BoltDB: %w", err) - } - - db.bolt, err = bbolt.Open(db.path, db.mode, db.boltOpts) - if err != nil { - return fmt.Errorf("could not open BoltDB: %w", err) - } - - return nil -} - -// Close closes an underlying BoltDB instance. -// -// Must not be called before successful Open call. -func (db *DB) Close() error { - return db.bolt.Close() -} - -func countryBucketKey(cc *locodedb.CountryCode) ([]byte, error) { - return []byte(cc.String()), nil -} - -func locationBucketKey(lc *locodedb.LocationCode) ([]byte, error) { - return []byte(lc.String()), nil -} - -type recordJSON struct { - CountryName string - LocationName string - SubDivName string - SubDivCode string - Latitude float64 - Longitude float64 - Continent string -} - -func recordValue(r locodedb.Record) ([]byte, error) { - p := r.GeoPoint() - - rj := &recordJSON{ - CountryName: r.CountryName(), - LocationName: r.LocationName(), - SubDivName: r.SubDivName(), - SubDivCode: r.SubDivCode(), - Latitude: p.Latitude(), - Longitude: p.Longitude(), - Continent: r.Continent().String(), - } - - return json.Marshal(rj) -} - -func recordFromValue(data []byte) (*locodedb.Record, error) { - rj := new(recordJSON) - - if err := json.Unmarshal(data, rj); err != nil { - return nil, err - } - - r := new(locodedb.Record) - r.SetCountryName(rj.CountryName) - r.SetLocationName(rj.LocationName) - r.SetSubDivName(rj.SubDivName) - r.SetSubDivCode(rj.SubDivCode) - r.SetGeoPoint(locodedb.NewPoint(rj.Latitude, rj.Longitude)) - - cont := locodedb.ContinentFromString(rj.Continent) - r.SetContinent(&cont) - - return r, nil -} - -// Put saves the record by key in an underlying BoltDB instance. -// -// Country code from the key is used for allocating the 1st level buckets. -// Records are stored in country buckets by the location code from the key. -// The records are stored in internal binary JSON format. -// -// Must not be called before successful Open call. -// Must not be called in read-only mode: behavior is undefined. -func (db *DB) Put(key locodedb.Key, rec locodedb.Record) error { - return db.bolt.Batch(func(tx *bbolt.Tx) error { - countryKey, err := countryBucketKey(key.CountryCode()) - if err != nil { - return err - } - - bktCountry, err := tx.CreateBucketIfNotExists(countryKey) - if err != nil { - return fmt.Errorf("could not create country bucket: %w", err) - } - - locationKey, err := locationBucketKey(key.LocationCode()) - if err != nil { - return err - } - - cont, err := recordValue(rec) - if err != nil { - return err - } - - return bktCountry.Put(locationKey, cont) - }) -} - -var errRecordNotFound = errors.New("record not found") - -// Get reads the record by key from underlying BoltDB instance. -// -// Returns an error if no record is presented by key in DB. -// -// Must not be called before successful Open call. -func (db *DB) Get(key locodedb.Key) (rec *locodedb.Record, err error) { - err = db.bolt.View(func(tx *bbolt.Tx) error { - countryKey, err := countryBucketKey(key.CountryCode()) - if err != nil { - return err - } - - bktCountry := tx.Bucket(countryKey) - if bktCountry == nil { - return errRecordNotFound - } - - locationKey, err := locationBucketKey(key.LocationCode()) - if err != nil { - return err - } - - data := bktCountry.Get(locationKey) - if data == nil { - return errRecordNotFound - } - - rec, err = recordFromValue(data) - - return err - }) - - return -} diff --git a/pkg/util/locode/db/boltdb/db.go b/pkg/util/locode/db/boltdb/db.go deleted file mode 100644 index 3d09a797da..0000000000 --- a/pkg/util/locode/db/boltdb/db.go +++ /dev/null @@ -1,73 +0,0 @@ -package locodebolt - -import ( - "fmt" - "io/fs" - - "go.etcd.io/bbolt" -) - -// Prm groups the required parameters of the DB's constructor. -// -// All values must comply with the requirements imposed on them. -// Passing incorrect parameter values will result in constructor -// failure (error or panic depending on the implementation). -type Prm struct { - // Path to BoltDB file with FrostFS location database. - // - // Must not be empty. - Path string -} - -// DB is a descriptor of the FrostFS BoltDB location database. -// -// For correct operation, DB must be created -// using the constructor (New) based on the required parameters -// and optional components. -// -// After successful creation, -// DB must be opened through Open call. After successful opening, -// DB is ready to work through API (until Close call). -// -// Upon completion of work with the DB, it must be closed -// by Close method. -type DB struct { - path string - - mode fs.FileMode - - boltOpts *bbolt.Options - - bolt *bbolt.DB -} - -const invalidPrmValFmt = "invalid parameter %s (%T):%v" - -func panicOnPrmValue(n string, v any) { - panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) -} - -// New creates a new instance of the DB. -// -// Panics if at least one value of the parameters is invalid. -// -// The created DB requires calling the Open method in order -// to initialize required resources. -func New(prm Prm, opts ...Option) *DB { - switch { - case prm.Path == "": - panicOnPrmValue("Path", prm.Path) - } - - o := defaultOpts() - - for i := range opts { - opts[i](o) - } - - return &DB{ - path: prm.Path, - mode: o.mode, - boltOpts: o.boltOpts, - } -} diff --git a/pkg/util/locode/db/boltdb/opts.go b/pkg/util/locode/db/boltdb/opts.go deleted file mode 100644 index db0cccd3a0..0000000000 --- a/pkg/util/locode/db/boltdb/opts.go +++ /dev/null @@ -1,37 +0,0 @@ -package locodebolt - -import ( - "io/fs" - "os" - "time" - - "go.etcd.io/bbolt" -) - -// Option sets an optional parameter of DB. -type Option func(*options) - -type options struct { - mode fs.FileMode - - boltOpts *bbolt.Options -} - -func defaultOpts() *options { - return &options{ - mode: os.ModePerm, // 0777 - boltOpts: &bbolt.Options{ - Timeout: 3 * time.Second, - }, - } -} - -// ReadOnly enables read-only mode of the DB. -// -// Do not call DB.Put method on instances with -// this option: the behavior is undefined. -func ReadOnly() Option { - return func(o *options) { - o.boltOpts.ReadOnly = true - } -} diff --git a/pkg/util/locode/db/continent.go b/pkg/util/locode/db/continent.go deleted file mode 100644 index 863af7b571..0000000000 --- a/pkg/util/locode/db/continent.go +++ /dev/null @@ -1,81 +0,0 @@ -package locodedb - -// Continent is an enumeration of Earth's continent. -type Continent uint8 - -const ( - // ContinentUnknown is an undefined Continent value. - ContinentUnknown = iota - - // ContinentEurope corresponds to Europe. - ContinentEurope - - // ContinentAfrica corresponds to Africa. - ContinentAfrica - - // ContinentNorthAmerica corresponds to North America. - ContinentNorthAmerica - - // ContinentSouthAmerica corresponds to South America. - ContinentSouthAmerica - - // ContinentAsia corresponds to Asia. - ContinentAsia - - // ContinentAntarctica corresponds to Antarctica. - ContinentAntarctica - - // ContinentOceania corresponds to Oceania. - ContinentOceania -) - -// Is checks if c is the same continent as c2. -func (c *Continent) Is(c2 Continent) bool { - return *c == c2 -} - -func (c Continent) String() string { - switch c { - case ContinentUnknown: - fallthrough - default: - return "Unknown" - case ContinentEurope: - return "Europe" - case ContinentAfrica: - return "Africa" - case ContinentNorthAmerica: - return "North America" - case ContinentSouthAmerica: - return "South America" - case ContinentAsia: - return "Asia" - case ContinentAntarctica: - return "Antarctica" - case ContinentOceania: - return "Oceania" - } -} - -// ContinentFromString returns Continent value -// corresponding to the passed string representation. -func ContinentFromString(str string) Continent { - switch str { - default: - return ContinentUnknown - case "Europe": - return ContinentEurope - case "Africa": - return ContinentAfrica - case "North America": - return ContinentNorthAmerica - case "South America": - return ContinentSouthAmerica - case "Asia": - return ContinentAsia - case "Antarctica": - return ContinentAntarctica - case "Oceania": - return ContinentOceania - } -} diff --git a/pkg/util/locode/db/continents/geojson/calls.go b/pkg/util/locode/db/continents/geojson/calls.go deleted file mode 100644 index 34467d5a25..0000000000 --- a/pkg/util/locode/db/continents/geojson/calls.go +++ /dev/null @@ -1,98 +0,0 @@ -package continentsdb - -import ( - "fmt" - "os" - - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" - "github.com/paulmach/orb" - "github.com/paulmach/orb/geojson" - "github.com/paulmach/orb/planar" -) - -const continentProperty = "Continent" - -// PointContinent goes through all polygons and returns the continent -// in which the point is located. -// -// Returns locodedb.ContinentUnknown if no entry matches. -// -// All GeoJSON feature are parsed from file once and stored in memory. -func (db *DB) PointContinent(point *locodedb.Point) (*locodedb.Continent, error) { - var err error - - db.once.Do(func() { - err = db.init() - }) - - if err != nil { - return nil, err - } - - planarPoint := orb.Point{point.Longitude(), point.Latitude()} - - var ( - continent string - minDst float64 - ) - - for _, feature := range db.features { - if multiPolygon, ok := feature.Geometry.(orb.MultiPolygon); ok { - if planar.MultiPolygonContains(multiPolygon, planarPoint) { - continent = feature.Properties.MustString(continentProperty) - break - } - } else if polygon, ok := feature.Geometry.(orb.Polygon); ok { - if planar.PolygonContains(polygon, planarPoint) { - continent = feature.Properties.MustString(continentProperty) - break - } - } - distance := planar.DistanceFrom(feature.Geometry, planarPoint) - if minDst == 0 || minDst > distance { - minDst = distance - continent = feature.Properties.MustString(continentProperty) - } - } - - c := continentFromString(continent) - - return &c, nil -} - -func (db *DB) init() error { - data, err := os.ReadFile(db.path) - if err != nil { - return fmt.Errorf("could not read data file: %w", err) - } - - features, err := geojson.UnmarshalFeatureCollection(data) - if err != nil { - return fmt.Errorf("could not unmarshal GeoJSON feature collection: %w", err) - } - - db.features = features.Features - - return nil -} - -func continentFromString(c string) locodedb.Continent { - switch c { - default: - return locodedb.ContinentUnknown - case "Africa": - return locodedb.ContinentAfrica - case "Asia": - return locodedb.ContinentAsia - case "Europe": - return locodedb.ContinentEurope - case "North America": - return locodedb.ContinentNorthAmerica - case "South America": - return locodedb.ContinentSouthAmerica - case "Antarctica": - return locodedb.ContinentAntarctica - case "Australia", "Oceania": - return locodedb.ContinentOceania - } -} diff --git a/pkg/util/locode/db/continents/geojson/db.go b/pkg/util/locode/db/continents/geojson/db.go deleted file mode 100644 index ee43bd8108..0000000000 --- a/pkg/util/locode/db/continents/geojson/db.go +++ /dev/null @@ -1,63 +0,0 @@ -package continentsdb - -import ( - "fmt" - "sync" - - "github.com/paulmach/orb/geojson" -) - -// Prm groups the required parameters of the DB's constructor. -// -// All values must comply with the requirements imposed on them. -// Passing incorrect parameter values will result in constructor -// failure (error or panic depending on the implementation). -type Prm struct { - // Path to polygons of Earth's continents in GeoJSON format. - // - // Must not be empty. - Path string -} - -// DB is a descriptor of the Earth's polygons in GeoJSON format. -// -// For correct operation, DB must be created -// using the constructor (New) based on the required parameters -// and optional components. After successful creation, -// The DB is immediately ready to work through API. -type DB struct { - path string - - once sync.Once - - features []*geojson.Feature -} - -const invalidPrmValFmt = "invalid parameter %s (%T):%v" - -func panicOnPrmValue(n string, v any) { - panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) -} - -// New creates a new instance of the DB. -// -// Panics if at least one value of the parameters is invalid. -// -// The created DB does not require additional -// initialization and is completely ready for work. -func New(prm Prm, opts ...Option) *DB { - switch { - case prm.Path == "": - panicOnPrmValue("Path", prm.Path) - } - - o := defaultOpts() - - for i := range opts { - opts[i](o) - } - - return &DB{ - path: prm.Path, - } -} diff --git a/pkg/util/locode/db/continents/geojson/opts.go b/pkg/util/locode/db/continents/geojson/opts.go deleted file mode 100644 index 59831fcc5f..0000000000 --- a/pkg/util/locode/db/continents/geojson/opts.go +++ /dev/null @@ -1,10 +0,0 @@ -package continentsdb - -// Option sets an optional parameter of DB. -type Option func(*options) - -type options struct{} - -func defaultOpts() *options { - return &options{} -} diff --git a/pkg/util/locode/db/country.go b/pkg/util/locode/db/country.go deleted file mode 100644 index 2d13c6ef97..0000000000 --- a/pkg/util/locode/db/country.go +++ /dev/null @@ -1,32 +0,0 @@ -package locodedb - -import ( - "fmt" - - locodecolumn "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/column" -) - -// CountryCode represents a country code for -// the storage in the FrostFS location database. -type CountryCode locodecolumn.CountryCode - -// CountryCodeFromString parses a string UN/LOCODE country code -// and returns a CountryCode. -func CountryCodeFromString(s string) (*CountryCode, error) { - cc, err := locodecolumn.CountryCodeFromString(s) - if err != nil { - return nil, fmt.Errorf("could not parse country code: %w", err) - } - - return CountryFromColumn(cc) -} - -// CountryFromColumn converts a UN/LOCODE country code to a CountryCode. -func CountryFromColumn(cc *locodecolumn.CountryCode) (*CountryCode, error) { - return (*CountryCode)(cc), nil -} - -func (c *CountryCode) String() string { - syms := (*locodecolumn.CountryCode)(c).Symbols() - return string(syms[:]) -} diff --git a/pkg/util/locode/db/db.go b/pkg/util/locode/db/db.go deleted file mode 100644 index 8c71ea7943..0000000000 --- a/pkg/util/locode/db/db.go +++ /dev/null @@ -1,183 +0,0 @@ -package locodedb - -import ( - "errors" - "fmt" - "runtime" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" - "golang.org/x/sync/errgroup" -) - -// SourceTable is an interface of the UN/LOCODE table. -type SourceTable interface { - // Must iterate over all entries of the table - // and pass next entry to the handler. - // - // Must return handler's errors directly. - IterateAll(func(locode.Record) error) error -} - -// DB is an interface of FrostFS location database. -type DB interface { - // Must save the record by key in the database. - Put(Key, Record) error - - // Must return the record by key from the database. - Get(Key) (*Record, error) -} - -// AirportRecord represents the entry in FrostFS airport database. -type AirportRecord struct { - // Name of the country where airport is located. - CountryName string - - // Geo point where airport is located. - Point *Point -} - -// ErrAirportNotFound is returned by AirportRecord readers -// when the required airport is not found. -var ErrAirportNotFound = errors.New("airport not found") - -// AirportDB is an interface of FrostFS airport database. -type AirportDB interface { - // Must return the record by UN/LOCODE table record. - // - // Must return ErrAirportNotFound if there is no - // related airport in the database. - Get(locode.Record) (*AirportRecord, error) -} - -// ContinentsDB is an interface of FrostFS continent database. -type ContinentsDB interface { - // Must return continent of the geo point. - PointContinent(*Point) (*Continent, error) -} - -var ErrSubDivNotFound = errors.New("subdivision not found") - -var ErrCountryNotFound = errors.New("country not found") - -// NamesDB is an interface of the FrostFS location namespace. -type NamesDB interface { - // Must resolve a country code to a country name. - // - // Must return ErrCountryNotFound if there is no - // country with the provided code. - CountryName(*CountryCode) (string, error) - - // Must resolve (country code, subdivision code) to - // a subdivision name. - // - // Must return ErrSubDivNotFound if either country or - // subdivision is not presented in database. - SubDivName(*CountryCode, string) (string, error) -} - -// FillDatabase generates the FrostFS location database based on the UN/LOCODE table. -func FillDatabase(table SourceTable, airports AirportDB, continents ContinentsDB, names NamesDB, db DB) error { - var errG errgroup.Group - - // Pick some sane default, after this the performance stopped increasing. - errG.SetLimit(runtime.NumCPU() * 4) - _ = table.IterateAll(func(tableRecord locode.Record) error { - errG.Go(func() error { - return processTableRecord(tableRecord, airports, continents, names, db) - }) - return nil - }) - return errG.Wait() -} - -func processTableRecord(tableRecord locode.Record, airports AirportDB, continents ContinentsDB, names NamesDB, db DB) error { - if tableRecord.LOCODE.LocationCode() == "" { - return nil - } - - dbKey, err := NewKey(tableRecord.LOCODE) - if err != nil { - return err - } - - dbRecord, err := NewRecord(tableRecord) - if err != nil { - if errors.Is(err, errParseCoordinates) { - return nil - } - - return err - } - - geoPoint := dbRecord.GeoPoint() - countryName := "" - - if geoPoint == nil { - airportRecord, err := airports.Get(tableRecord) - if err != nil { - if errors.Is(err, ErrAirportNotFound) { - return nil - } - - return err - } - - geoPoint = airportRecord.Point - countryName = airportRecord.CountryName - } - - dbRecord.SetGeoPoint(geoPoint) - - if countryName == "" { - countryName, err = names.CountryName(dbKey.CountryCode()) - if err != nil { - if errors.Is(err, ErrCountryNotFound) { - return nil - } - - return err - } - } - - dbRecord.SetCountryName(countryName) - - if subDivCode := dbRecord.SubDivCode(); subDivCode != "" { - subDivName, err := names.SubDivName(dbKey.CountryCode(), subDivCode) - if err != nil { - if errors.Is(err, ErrSubDivNotFound) { - return nil - } - - return err - } - - dbRecord.SetSubDivName(subDivName) - } - - continent, err := continents.PointContinent(geoPoint) - if err != nil { - return fmt.Errorf("could not calculate continent geo point: %w", err) - } else if continent.Is(ContinentUnknown) { - return nil - } - - dbRecord.SetContinent(continent) - - return db.Put(*dbKey, *dbRecord) -} - -// LocodeRecord returns the record from the FrostFS location database -// corresponding to the string representation of UN/LOCODE. -func LocodeRecord(db DB, sLocode string) (*Record, error) { - lc, err := locode.FromString(sLocode) - if err != nil { - return nil, fmt.Errorf("could not parse locode: %w", err) - } - - key, err := NewKey(*lc) - if err != nil { - return nil, err - } - - return db.Get(*key) -} diff --git a/pkg/util/locode/db/location.go b/pkg/util/locode/db/location.go deleted file mode 100644 index d22979170b..0000000000 --- a/pkg/util/locode/db/location.go +++ /dev/null @@ -1,32 +0,0 @@ -package locodedb - -import ( - "fmt" - - locodecolumn "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/column" -) - -// LocationCode represents a location code for -// the storage in the FrostFS location database. -type LocationCode locodecolumn.LocationCode - -// LocationCodeFromString parses a string UN/LOCODE location code -// and returns a LocationCode. -func LocationCodeFromString(s string) (*LocationCode, error) { - lc, err := locodecolumn.LocationCodeFromString(s) - if err != nil { - return nil, fmt.Errorf("could not parse location code: %w", err) - } - - return LocationFromColumn(lc) -} - -// LocationFromColumn converts a UN/LOCODE country code to a LocationCode. -func LocationFromColumn(cc *locodecolumn.LocationCode) (*LocationCode, error) { - return (*LocationCode)(cc), nil -} - -func (l *LocationCode) String() string { - syms := (*locodecolumn.LocationCode)(l).Symbols() - return string(syms[:]) -} diff --git a/pkg/util/locode/db/point.go b/pkg/util/locode/db/point.go deleted file mode 100644 index 72daebb2c5..0000000000 --- a/pkg/util/locode/db/point.go +++ /dev/null @@ -1,93 +0,0 @@ -package locodedb - -import ( - "fmt" - "strconv" - - locodecolumn "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/column" -) - -// Point represents a 2D geographic point. -type Point struct { - lat, lng float64 -} - -// NewPoint creates, initializes and returns a new Point. -func NewPoint(lat, lng float64) *Point { - return &Point{ - lat: lat, - lng: lng, - } -} - -// Latitude returns the Point's latitude. -func (p Point) Latitude() float64 { - return p.lat -} - -// Longitude returns the Point's longitude. -func (p Point) Longitude() float64 { - return p.lng -} - -// PointFromCoordinates converts a UN/LOCODE coordinates to a Point. -func PointFromCoordinates(crd *locodecolumn.Coordinates) (*Point, error) { - if crd == nil { - return nil, nil - } - - cLat := crd.Latitude() - cLatDeg := cLat.Degrees() - cLatMnt := cLat.Minutes() - - lat, err := toDecimal(cLatDeg[:], cLatMnt[:]) - if err != nil { - return nil, fmt.Errorf("could not parse latitude: %w", err) - } - - if !cLat.Hemisphere().North() { - lat = -lat - } - - cLng := crd.Longitude() - cLngDeg := cLng.Degrees() - cLngMnt := cLng.Minutes() - - lng, err := toDecimal(cLngDeg[:], cLngMnt[:]) - if err != nil { - return nil, fmt.Errorf("could not parse longitude: %w", err) - } - - if !cLng.Hemisphere().East() { - lng = -lng - } - - return &Point{ - lat: lat, - lng: lng, - }, nil -} - -func toDecimal(intRaw, minutesRaw []byte) (float64, error) { - integer, err := strconv.ParseFloat(string(intRaw), 64) - if err != nil { - return 0, fmt.Errorf("could not parse integer part: %w", err) - } - - decimal, err := minutesToDegrees(minutesRaw) - if err != nil { - return 0, fmt.Errorf("could not parse decimal part: %w", err) - } - - return integer + decimal, nil -} - -// minutesToDegrees converts minutes to decimal part of a degree. -func minutesToDegrees(raw []byte) (float64, error) { - minutes, err := strconv.ParseFloat(string(raw), 64) - if err != nil { - return 0, err - } - - return minutes / 60, nil -} diff --git a/pkg/util/locode/db/point_test.go b/pkg/util/locode/db/point_test.go deleted file mode 100644 index f91c0cf87f..0000000000 --- a/pkg/util/locode/db/point_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package locodedb - -import ( - "testing" - - locodecolumn "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/column" - "github.com/stretchr/testify/require" -) - -func TestPointFromCoordinates(t *testing.T) { - testCases := []struct { - latGot, longGot string - latWant, longWant float64 - }{ - { - latGot: "5915N", - longGot: "01806E", - latWant: 59.25, - longWant: 18.10, - }, - { - latGot: "1000N", - longGot: "02030E", - latWant: 10.00, - longWant: 20.50, - }, - { - latGot: "0145S", - longGot: "03512W", - latWant: -01.75, - longWant: -35.20, - }, - } - - var ( - crd *locodecolumn.Coordinates - point *Point - err error - ) - - for _, test := range testCases { - crd, err = locodecolumn.CoordinatesFromString(test.latGot + " " + test.longGot) - require.NoError(t, err) - - point, err = PointFromCoordinates(crd) - require.NoError(t, err) - - require.Equal(t, test.latWant, point.Latitude()) - require.Equal(t, test.longWant, point.Longitude()) - } -} diff --git a/pkg/util/locode/db/record.go b/pkg/util/locode/db/record.go deleted file mode 100644 index 4c414079f5..0000000000 --- a/pkg/util/locode/db/record.go +++ /dev/null @@ -1,140 +0,0 @@ -package locodedb - -import ( - "errors" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" - locodecolumn "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/column" -) - -// Key represents the key in FrostFS location database. -type Key struct { - cc *CountryCode - - lc *LocationCode -} - -// NewKey calculates Key from LOCODE. -func NewKey(lc locode.LOCODE) (*Key, error) { - country, err := CountryCodeFromString(lc.CountryCode()) - if err != nil { - return nil, fmt.Errorf("could not parse country: %w", err) - } - - location, err := LocationCodeFromString(lc.LocationCode()) - if err != nil { - return nil, fmt.Errorf("could not parse location: %w", err) - } - - return &Key{ - cc: country, - lc: location, - }, nil -} - -// CountryCode returns the location's country code. -func (k *Key) CountryCode() *CountryCode { - return k.cc -} - -// LocationCode returns the location code. -func (k *Key) LocationCode() *LocationCode { - return k.lc -} - -// Record represents the entry in FrostFS location database. -type Record struct { - countryName string - - locationName string - - subDivName string - - subDivCode string - - p *Point - - cont *Continent -} - -var errParseCoordinates = errors.New("invalid coordinates") - -// NewRecord calculates the Record from the UN/LOCODE table record. -func NewRecord(r locode.Record) (*Record, error) { - crd, err := locodecolumn.CoordinatesFromString(r.Coordinates) - if err != nil { - return nil, fmt.Errorf("%w: %v", errParseCoordinates, err) - } - - point, err := PointFromCoordinates(crd) - if err != nil { - return nil, fmt.Errorf("could not parse geo point: %w", err) - } - - return &Record{ - locationName: r.NameWoDiacritics, - subDivCode: r.SubDiv, - p: point, - }, nil -} - -// CountryName returns the country name. -func (r *Record) CountryName() string { - return r.countryName -} - -// SetCountryName sets the country name. -func (r *Record) SetCountryName(name string) { - r.countryName = name -} - -// LocationName returns the location name. -func (r *Record) LocationName() string { - return r.locationName -} - -// SetLocationName sets the location name. -func (r *Record) SetLocationName(name string) { - r.locationName = name -} - -// SubDivCode returns the subdivision code. -func (r *Record) SubDivCode() string { - return r.subDivCode -} - -// SetSubDivCode sets the subdivision code. -func (r *Record) SetSubDivCode(name string) { - r.subDivCode = name -} - -// SubDivName returns the subdivision name. -func (r *Record) SubDivName() string { - return r.subDivName -} - -// SetSubDivName sets the subdivision name. -func (r *Record) SetSubDivName(name string) { - r.subDivName = name -} - -// GeoPoint returns geo point of the location. -func (r *Record) GeoPoint() *Point { - return r.p -} - -// SetGeoPoint sets geo point of the location. -func (r *Record) SetGeoPoint(p *Point) { - r.p = p -} - -// Continent returns the location continent. -func (r *Record) Continent() *Continent { - return r.cont -} - -// SetContinent sets the location continent. -func (r *Record) SetContinent(c *Continent) { - r.cont = c -} diff --git a/pkg/util/locode/record.go b/pkg/util/locode/record.go deleted file mode 100644 index 7db746ff3b..0000000000 --- a/pkg/util/locode/record.go +++ /dev/null @@ -1,83 +0,0 @@ -package locode - -import ( - "errors" - "fmt" - "strings" -) - -// LOCODE represents code from UN/LOCODE coding scheme. -type LOCODE [2]string - -// Record represents a single record of the UN/LOCODE table. -type Record struct { - // Change Indicator. - Ch string - - // Combination of a 2-character country code and a 3-character location code. - LOCODE LOCODE - - // Name of the locations which has been allocated a UN/LOCODE. - Name string - - // Names of the locations which have been allocated a UN/LOCODE without diacritic signs. - NameWoDiacritics string - - // ISO 1-3 character alphabetic and/or numeric code for the administrative division of the country concerned. - SubDiv string - - // 8-digit function classifier code for the location. - Function string - - // Status of the entry by a 2-character code. - Status string - - // Last date when the location was updated/entered. - Date string - - // The IATA code for the location if different from location code in column LOCODE. - IATA string - - // Geographical coordinates (latitude/longitude) of the location, if there is any. - Coordinates string - - // Some general remarks regarding the UN/LOCODE in question. - Remarks string -} - -// ErrInvalidString is the error of incorrect string format of the LOCODE. -var ErrInvalidString = errors.New("invalid string format in UN/Locode") - -// FromString parses string and returns LOCODE. -// -// If string has incorrect format, ErrInvalidString returns. -func FromString(s string) (*LOCODE, error) { - const ( - locationSeparator = " " - locodePartsNumber = 2 - ) - - words := strings.Split(s, locationSeparator) - if ln := len(words); ln != locodePartsNumber { - return nil, fmt.Errorf( - "incorrect locode: it must consist of %d codes separated with a witespase, got: %d", - locodePartsNumber, - ln, - ) - } - - l := new(LOCODE) - copy(l[:], words) - - return l, nil -} - -// CountryCode returns a string representation of country code. -func (l *LOCODE) CountryCode() string { - return l[0] -} - -// LocationCode returns a string representation of location code. -func (l *LOCODE) LocationCode() string { - return l[1] -} diff --git a/pkg/util/locode/table/csv/calls.go b/pkg/util/locode/table/csv/calls.go deleted file mode 100644 index 5f40865be3..0000000000 --- a/pkg/util/locode/table/csv/calls.go +++ /dev/null @@ -1,156 +0,0 @@ -package csvlocode - -import ( - "encoding/csv" - "errors" - "io" - "os" - "strings" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode" - locodedb "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/locode/db" -) - -var errInvalidRecord = errors.New("invalid table record") - -// IterateAll scans a table record one-by-one, parses a UN/LOCODE record -// from it and passes it to f. -// -// Returns f's errors directly. -func (t *Table) IterateAll(f func(locode.Record) error) error { - const wordsPerRecord = 12 - - return t.scanWords(t.paths, wordsPerRecord, func(words []string) error { - lc, err := locode.FromString(strings.Join(words[1:3], " ")) - if err != nil { - return err - } - - record := locode.Record{ - Ch: words[0], - LOCODE: *lc, - Name: words[3], - NameWoDiacritics: words[4], - SubDiv: words[5], - Function: words[6], - Status: words[7], - Date: words[8], - IATA: words[9], - Coordinates: words[10], - Remarks: words[11], - } - - return f(record) - }) -} - -const ( - _ = iota - 1 - - subDivCountry - subDivSubdivision - subDivName - _ // subDivLevel - - subDivFldNum -) - -type subDivKey struct { - countryCode, - subDivCode string -} - -type subDivRecord struct { - name string -} - -// SubDivName scans a table record to an in-memory table (once), -// and returns the subdivision name of the country and the subdivision codes match. -// -// Returns locodedb.ErrSubDivNotFound if no entry matches. -func (t *Table) SubDivName(countryCode *locodedb.CountryCode, code string) (string, error) { - if err := t.initSubDiv(); err != nil { - return "", err - } - - rec, ok := t.mSubDiv[subDivKey{ - countryCode: countryCode.String(), - subDivCode: code, - }] - if !ok { - return "", locodedb.ErrSubDivNotFound - } - - return rec.name, nil -} - -func (t *Table) initSubDiv() (err error) { - t.subDivOnce.Do(func() { - t.mSubDiv = make(map[subDivKey]subDivRecord) - - err = t.scanWords([]string{t.subDivPath}, subDivFldNum, func(words []string) error { - t.mSubDiv[subDivKey{ - countryCode: words[subDivCountry], - subDivCode: words[subDivSubdivision], - }] = subDivRecord{ - name: words[subDivName], - } - - return nil - }) - }) - - return -} - -var errScanInt = errors.New("interrupt scan") - -func (t *Table) scanWords(paths []string, fpr int, wordsHandler func([]string) error) error { - var ( - rdrs = make([]io.Reader, 0, len(t.paths)) - closers = make([]io.Closer, 0, len(t.paths)) - ) - - for i := range paths { - file, err := os.OpenFile(paths[i], os.O_RDONLY, t.mode) - if err != nil { - return err - } - - rdrs = append(rdrs, file) - closers = append(closers, file) - } - - defer func() { - for i := range closers { - _ = closers[i].Close() - } - }() - - r := csv.NewReader(io.MultiReader(rdrs...)) - r.ReuseRecord = true - r.FieldsPerRecord = fpr - - for { - words, err := r.Read() - if err != nil { - if errors.Is(err, io.EOF) { - break - } - - return err - } else if len(words) != fpr { - return errInvalidRecord - } - - if err := wordsHandler(words); err != nil { - if errors.Is(err, errScanInt) { - break - } - - return err - } - } - - return nil -} diff --git a/pkg/util/locode/table/csv/opts.go b/pkg/util/locode/table/csv/opts.go deleted file mode 100644 index 68e442899c..0000000000 --- a/pkg/util/locode/table/csv/opts.go +++ /dev/null @@ -1,28 +0,0 @@ -package csvlocode - -import ( - "io/fs" -) - -// Option sets an optional parameter of Table. -type Option func(*options) - -type options struct { - mode fs.FileMode - - extraPaths []string -} - -func defaultOpts() *options { - return &options{ - mode: 0o700, - } -} - -// WithExtraPaths returns an option to add extra paths -// to UN/LOCODE tables in csv format. -func WithExtraPaths(ps ...string) Option { - return func(o *options) { - o.extraPaths = append(o.extraPaths, ps...) - } -} diff --git a/pkg/util/locode/table/csv/table.go b/pkg/util/locode/table/csv/table.go deleted file mode 100644 index b84c2b705e..0000000000 --- a/pkg/util/locode/table/csv/table.go +++ /dev/null @@ -1,75 +0,0 @@ -package csvlocode - -import ( - "fmt" - "io/fs" - "sync" -) - -// Prm groups the required parameters of the Table's constructor. -// -// All values must comply with the requirements imposed on them. -// Passing incorrect parameter values will result in constructor -// failure (error or panic depending on the implementation). -type Prm struct { - // Path to UN/LOCODE csv table. - // - // Must not be empty. - Path string - - // Path to csv table of UN/LOCODE Subdivisions. - // - // Must not be empty. - SubDivPath string -} - -// Table is a descriptor of the UN/LOCODE table in csv format. -// -// For correct operation, Table must be created -// using the constructor (New) based on the required parameters -// and optional components. After successful creation, -// The Table is immediately ready to work through API. -type Table struct { - paths []string - - mode fs.FileMode - - subDivPath string - - subDivOnce sync.Once - - mSubDiv map[subDivKey]subDivRecord -} - -const invalidPrmValFmt = "invalid parameter %s (%T):%v" - -func panicOnPrmValue(n string, v any) { - panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) -} - -// New creates a new instance of the Table. -// -// Panics if at least one value of the parameters is invalid. -// -// The created Table does not require additional -// initialization and is completely ready for work. -func New(prm Prm, opts ...Option) *Table { - switch { - case prm.Path == "": - panicOnPrmValue("Path", prm.Path) - case prm.SubDivPath == "": - panicOnPrmValue("SubDivPath", prm.SubDivPath) - } - - o := defaultOpts() - - for i := range opts { - opts[i](o) - } - - return &Table{ - paths: append(o.extraPaths, prm.Path), - mode: o.mode, - subDivPath: prm.SubDivPath, - } -} From 8398a8b4b3d4eff5f3759a5d5dafaa4ba9046a4c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 23 Jul 2024 17:46:02 +0300 Subject: [PATCH 0713/1413] [#1271] getSvc: Fix `head --raw` assemble for EC Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/assembleec.go | 4 +- pkg/services/object/get/assemblerec.go | 64 -------------------------- pkg/services/object/get/get.go | 4 ++ pkg/services/object/get/remote.go | 18 ++++++-- 4 files changed, 20 insertions(+), 70 deletions(-) diff --git a/pkg/services/object/get/assembleec.go b/pkg/services/object/get/assembleec.go index 7bbd9ca1e0..a58602bf76 100644 --- a/pkg/services/object/get/assembleec.go +++ b/pkg/services/object/get/assembleec.go @@ -11,7 +11,7 @@ import ( ) func (r *request) assembleEC(ctx context.Context) { - if r.isRaw() && r.isLocal() { + if r.isRaw() { r.log.Debug(logs.GetCanNotAssembleTheObject) return } @@ -43,7 +43,7 @@ func (r *request) assembleEC(ctx context.Context) { } r.prm.common = r.prm.common.WithLocalOnly(false) - assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.localStorage, r.containerSource, r.log, r.headOnly(), r.isRaw(), r.traverserGenerator, r.curProcEpoch) + assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.localStorage, r.containerSource, r.log, r.headOnly(), r.traverserGenerator, r.curProcEpoch) r.log.Debug(logs.GetAssemblingECObject, zap.Uint64("range_offset", r.ctxRange().GetOffset()), diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index a4021ee5e9..d64984d5cf 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -37,7 +37,6 @@ type assemblerec struct { cs container.Source log *logger.Logger head bool - raw bool traverserGenerator traverserGenerator epoch uint64 } @@ -51,7 +50,6 @@ func newAssemblerEC( cs container.Source, log *logger.Logger, head bool, - raw bool, tg traverserGenerator, epoch uint64, ) *assemblerec { @@ -64,7 +62,6 @@ func newAssemblerEC( cs: cs, log: log, head: head, - raw: raw, traverserGenerator: tg, epoch: epoch, } @@ -74,9 +71,6 @@ func newAssemblerEC( // It returns parent object. func (a *assemblerec) Assemble(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { switch { - case a.raw: - err := a.reconstructRawError(ctx) - return nil, err case a.head: return a.reconstructHeader(ctx, writer) case a.rng != nil: @@ -149,56 +143,6 @@ func (a *assemblerec) reconstructObjectFromParts(ctx context.Context, headers bo return c.Reconstruct(parts) } -func (a *assemblerec) reconstructRawError(ctx context.Context) error { - chunks := make(map[string]objectSDK.ECChunk) - var chunksGuard sync.Mutex - for _, ch := range a.ecInfo.localChunks { - chunks[string(ch.ID.GetValue())] = ch - } - - objID := a.addr.Object() - trav, _, err := a.traverserGenerator.GenerateTraverser(a.addr.Container(), &objID, a.epoch) - if err != nil { - return err - } - - eg, ctx := errgroup.WithContext(ctx) - for { - batch := trav.Next() - if len(batch) == 0 { - break - } - for _, node := range batch { - var info client.NodeInfo - client.NodeInfoFromNetmapElement(&info, node) - eg.Go(func() error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - if _, found := a.ecInfo.remoteChunks[string(info.PublicKey())]; found { - return nil - } - - nodeChunks := a.tryGetChunkListFromNode(ctx, info) - - chunksGuard.Lock() - defer chunksGuard.Unlock() - for _, ch := range nodeChunks { - chunks[string(ch.ID.GetValue())] = ch - } - return nil - }) - } - } - if err = eg.Wait(); err != nil { - return err - } - return createECInfoErr(chunks) -} - func (a *assemblerec) retrieveParts(ctx context.Context, trav *placement.Traverser, cnr *container.Container) []*objectSDK.Object { dataCount := policy.ECDataCount(cnr.Value.PlacementPolicy()) parityCount := policy.ECParityCount(cnr.Value.PlacementPolicy()) @@ -359,11 +303,3 @@ func (a *assemblerec) tryGetChunkFromRemoteStorage(ctx context.Context, node cli } return object } - -func createECInfoErr(chunks map[string]objectSDK.ECChunk) *objectSDK.ECInfoError { - info := objectSDK.NewECInfo() - for _, ch := range chunks { - info.AddChunk(ch) - } - return objectSDK.NewECInfoError(info) -} diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 5a57bc56e0..07a2f3a724 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -111,6 +111,10 @@ func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) { exec.log.Debug(logs.GetRequestedRangeIsOutOfObjectBounds) case statusEC: exec.log.Debug(logs.GetRequestedObjectIsEC) + if exec.isRaw() && execCnr { + exec.executeOnContainer(ctx) + exec.analyzeStatus(ctx, false) + } exec.assembleEC(ctx) default: exec.log.Debug(logs.OperationFinishedWithError, diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index 4dee152427..ce9abfe1cb 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -35,8 +35,12 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { switch { default: r.log.Debug(logs.GetRemoteCallFailed, zap.Error(err)) - r.status = statusUndefined - r.err = new(apistatus.ObjectNotFound) + if r.status != statusEC { + // for raw requests, continue to collect other parts + r.status = statusUndefined + r.err = new(apistatus.ObjectNotFound) + } + return false case err == nil: r.status = statusOK r.err = nil @@ -48,22 +52,28 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { r.collectedObject = obj r.writeCollectedObject(ctx) } + return true case errors.As(err, &errRemoved): r.status = statusINHUMED r.err = errRemoved + return true case errors.As(err, &errOutOfRange): r.status = statusOutOfRange r.err = errOutOfRange + return true case errors.As(err, &errSplitInfo): r.status = statusVIRTUAL mergeSplitInfo(r.splitInfo(), errSplitInfo.SplitInfo()) r.err = objectSDK.NewSplitInfoError(r.infoSplit) + return true case errors.As(err, &errECInfo): r.status = statusEC r.err = r.infoEC.addRemote(string(info.PublicKey()), errECInfo.ECInfo()) + if r.isRaw() { + return false // continue to collect all parts + } + return true } - - return r.status != statusUndefined } func (r *request) getRemote(ctx context.Context, rs remoteStorage, info client.NodeInfo) (*objectSDK.Object, error) { From 7fd7961dfa9ffef87f17382da758c4d74b54cd4f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 23 Jul 2024 22:15:13 +0300 Subject: [PATCH 0714/1413] [#1271] getSvc: Fix local EC chunk get Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/assemblerec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index d64984d5cf..6a02673c36 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -237,7 +237,7 @@ func (a *assemblerec) tryGetChunkFromLocalStorage(ctx context.Context, ch object return nil } var addr oid.Address - addr.SetContainer(addr.Container()) + addr.SetContainer(a.addr.Container()) addr.SetObject(objID) var object *objectSDK.Object if a.head { From dd459d399f11d8e49fa841f1372563453bc41a77 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 25 Jul 2024 22:52:48 +0300 Subject: [PATCH 0715/1413] [#1274] go.mod: Update neo-go version that fixes ws-client * Update go.mod; * This neo-go package version contains fix for the wsclient that allows to morph event listener refresh the invalidated websocket connection to neo-go. Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 6a97f7850f..c63eabe0d9 100644 --- a/go.mod +++ b/go.mod @@ -127,4 +127,4 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/nspcc-dev/neo-go => git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18 +replace github.com/nspcc-dev/neo-go => git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 diff --git a/go.sum b/go.sum index d4cf863fab..965bffd2d8 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de/go.mod h1:4AObM67VUqkXQJlODTFThFnuMGEuK8h9DrAXHDZqvCU= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= -git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18 h1:JRjwcHaQajTbSCBCK3yZnqvyHvgWBaoThDGuT4kvIIc= -git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240611123832-594f716b3d18/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= +git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= +git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 h1:O3F2Grz07RWZ68mRz1xsYsNPNvZLwY00BM+xoYb1kNk= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= From 8377372a40a699a029f185be6e355748931e8234 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 26 Jul 2024 16:37:05 +0300 Subject: [PATCH 0716/1413] [#1276] go.mod: Update api-go Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/internal/client/client.go | 23 ---- cmd/frostfs-cli/modules/container/root.go | 3 - cmd/frostfs-cli/modules/container/set_eacl.go | 108 ------------------ cmd/frostfs-cli/modules/container/util.go | 5 +- go.mod | 6 +- go.sum | 8 +- pkg/core/client/client.go | 1 - pkg/morph/client/container/load.go | 40 ------- pkg/network/cache/multi.go | 9 -- .../transport/container/grpc/service.go | 30 ----- pkg/services/container/ape.go | 21 ---- pkg/services/container/ape_test.go | 90 --------------- pkg/services/container/audit.go | 30 ----- pkg/services/container/executor.go | 19 --- pkg/services/container/morph/executor.go | 6 - pkg/services/container/server.go | 2 - pkg/services/container/sign.go | 18 --- 17 files changed, 9 insertions(+), 410 deletions(-) delete mode 100644 cmd/frostfs-cli/modules/container/set_eacl.go diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index a6d9968c52..215490dbeb 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -214,29 +214,6 @@ func EACL(ctx context.Context, prm EACLPrm) (res EACLRes, err error) { return } -// SetEACLPrm groups parameters of SetEACL operation. -type SetEACLPrm struct { - Client *client.Client - ClientParams client.PrmContainerSetEACL -} - -// SetEACLRes groups the resulting values of SetEACL operation. -type SetEACLRes struct{} - -// SetEACL requests to save an eACL table in FrostFS. -// -// Operation is asynchronous and no guaranteed even in the absence of errors. -// The required time is also not predictable. -// -// Success can be verified by reading by container identifier. -// -// Returns any error which prevented the operation from completing correctly in error return. -func SetEACL(ctx context.Context, prm SetEACLPrm) (res SetEACLRes, err error) { - _, err = prm.Client.ContainerSetEACL(ctx, prm.ClientParams) - - return -} - // NetworkInfoPrm groups parameters of NetworkInfo operation. type NetworkInfoPrm struct { Client *client.Client diff --git a/cmd/frostfs-cli/modules/container/root.go b/cmd/frostfs-cli/modules/container/root.go index 99d1a4231a..d5f0fd776e 100644 --- a/cmd/frostfs-cli/modules/container/root.go +++ b/cmd/frostfs-cli/modules/container/root.go @@ -26,7 +26,6 @@ func init() { listContainerObjectsCmd, getContainerInfoCmd, getExtendedACLCmd, - setExtendedACLCmd, containerNodesCmd, policyPlaygroundCmd, } @@ -39,7 +38,6 @@ func init() { initContainerListObjectsCmd() initContainerInfoCmd() initContainerGetEACLCmd() - initContainerSetEACLCmd() initContainerNodesCmd() initContainerPolicyPlaygroundCmd() @@ -53,7 +51,6 @@ func init() { }{ {createContainerCmd, "PUT"}, {deleteContainerCmd, "DELETE"}, - {setExtendedACLCmd, "SETEACL"}, } { commonflags.InitSession(el.cmd, "container "+el.verb) } diff --git a/cmd/frostfs-cli/modules/container/set_eacl.go b/cmd/frostfs-cli/modules/container/set_eacl.go deleted file mode 100644 index 86aa50a578..0000000000 --- a/cmd/frostfs-cli/modules/container/set_eacl.go +++ /dev/null @@ -1,108 +0,0 @@ -package container - -import ( - "bytes" - "errors" - "time" - - internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" - commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - "github.com/spf13/cobra" -) - -var flagVarsSetEACL struct { - noPreCheck bool - - srcPath string -} - -var setExtendedACLCmd = &cobra.Command{ - Use: "set-eacl", - Short: "Set new extended ACL table for container", - Long: `Set new extended ACL table for container. -Container ID in EACL table will be substituted with ID from the CLI.`, - Run: func(cmd *cobra.Command, _ []string) { - id := parseContainerID(cmd) - eaclTable := common.ReadEACL(cmd, flagVarsSetEACL.srcPath) - - tok := getSession(cmd) - - eaclTable.SetCID(id) - - pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) - - if !flagVarsSetEACL.noPreCheck { - cmd.Println("Checking the ability to modify access rights in the container...") - - extendable, err := internalclient.IsACLExtendable(cmd.Context(), cli, id) - commonCmd.ExitOnErr(cmd, "Extensibility check failure: %w", err) - - if !extendable { - commonCmd.ExitOnErr(cmd, "", errors.New("container ACL is immutable")) - } - - cmd.Println("ACL extension is enabled in the container, continue processing.") - } - - setEACLPrm := internalclient.SetEACLPrm{ - Client: cli, - ClientParams: client.PrmContainerSetEACL{ - Table: eaclTable, - Session: tok, - }, - } - - _, err := internalclient.SetEACL(cmd.Context(), setEACLPrm) - commonCmd.ExitOnErr(cmd, "rpc error: %w", err) - - if containerAwait { - exp, err := eaclTable.Marshal() - commonCmd.ExitOnErr(cmd, "broken EACL table: %w", err) - - cmd.Println("awaiting...") - - getEACLPrm := internalclient.EACLPrm{ - Client: cli, - ClientParams: client.PrmContainerEACL{ - ContainerID: &id, - }, - } - - for i := 0; i < awaitTimeout; i++ { - time.Sleep(1 * time.Second) - - res, err := internalclient.EACL(cmd.Context(), getEACLPrm) - if err == nil { - // compare binary values because EACL could have been set already - table := res.EACL() - got, err := table.Marshal() - if err != nil { - continue - } - - if bytes.Equal(exp, got) { - cmd.Println("EACL has been persisted on sidechain") - return - } - } - } - - commonCmd.ExitOnErr(cmd, "", errSetEACLTimeout) - } - }, -} - -func initContainerSetEACLCmd() { - commonflags.Init(setExtendedACLCmd) - - flags := setExtendedACLCmd.Flags() - flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage) - flags.StringVar(&flagVarsSetEACL.srcPath, "table", "", "path to file with JSON or binary encoded EACL table") - flags.BoolVar(&containerAwait, "await", false, "block execution until EACL is persisted") - flags.BoolVar(&flagVarsSetEACL.noPreCheck, "no-precheck", false, "do not pre-check the extensibility of the container ACL") -} diff --git a/cmd/frostfs-cli/modules/container/util.go b/cmd/frostfs-cli/modules/container/util.go index 48265f7851..4cb268ec59 100644 --- a/cmd/frostfs-cli/modules/container/util.go +++ b/cmd/frostfs-cli/modules/container/util.go @@ -18,9 +18,8 @@ const ( ) var ( - errCreateTimeout = errors.New("timeout: container has not been persisted on sidechain") - errDeleteTimeout = errors.New("timeout: container has not been removed from sidechain") - errSetEACLTimeout = errors.New("timeout: EACL has not been persisted on sidechain") + errCreateTimeout = errors.New("timeout: container has not been persisted on sidechain") + errDeleteTimeout = errors.New("timeout: container has not been removed from sidechain") ) func parseContainerID(cmd *cobra.Command) cid.ID { diff --git a/go.mod b/go.mod index c63eabe0d9..09a0985020 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 @@ -24,7 +24,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.12.1 - github.com/nspcc-dev/neo-go v0.106.0 + github.com/nspcc-dev/neo-go v0.106.2 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 github.com/prometheus/client_golang v1.19.0 diff --git a/go.sum b/go.sum index 965bffd2d8..1034ff61fe 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3 h1:H5GvrVlowIMWfzqQkhY0p0myooJxQ1sMRVSFfXawwWg= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e h1:gEWT+70E/RvGkxtSv+PlyUN2vtJVymhQa1mypvrXukM= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de h1:OjsWY0jpGJV1t87XgwL/3PsDx7fJ6lfNMXtY8UhoUbM= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de/go.mod h1:4AObM67VUqkXQJlODTFThFnuMGEuK8h9DrAXHDZqvCU= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec h1:A09Swh7yogmmiABUf7Ht6MTQXJ07MyGx4+ziUQNelec= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec/go.mod h1:DlJmgV4/qkFkx2ab+YWznlMijiF2yZHnrJswJOB7XGs= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= diff --git a/pkg/core/client/client.go b/pkg/core/client/client.go index 8c92901f23..854fbc49fe 100644 --- a/pkg/core/client/client.go +++ b/pkg/core/client/client.go @@ -11,7 +11,6 @@ import ( // Client is an interface of FrostFS storage // node's client. type Client interface { - ContainerAnnounceUsedSpace(context.Context, client.PrmAnnounceSpace) (*client.ResAnnounceSpace, error) ObjectPutInit(context.Context, client.PrmObjectPutInit) (client.ObjectWriter, error) ObjectPutSingle(context.Context, client.PrmObjectPutSingle) (*client.ResObjectPutSingle, error) ObjectDelete(context.Context, client.PrmObjectDelete) (*client.ResObjectDelete, error) diff --git a/pkg/morph/client/container/load.go b/pkg/morph/client/container/load.go index b5263d7a63..5e2c3c2c3d 100644 --- a/pkg/morph/client/container/load.go +++ b/pkg/morph/client/container/load.go @@ -1,53 +1,13 @@ package container import ( - "crypto/sha256" "fmt" v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" ) -// AnnounceLoadPrm groups parameters of AnnounceLoad operation. -type AnnounceLoadPrm struct { - a container.SizeEstimation - key []byte - - client.InvokePrmOptional -} - -// SetAnnouncement sets announcement. -func (a2 *AnnounceLoadPrm) SetAnnouncement(a container.SizeEstimation) { - a2.a = a -} - -// SetReporter sets public key of the reporter. -func (a2 *AnnounceLoadPrm) SetReporter(key []byte) { - a2.key = key -} - -// AnnounceLoad saves container size estimation calculated by storage node -// with key in FrostFS system through Container contract call. -// -// Returns any error encountered that caused the saving to interrupt. -func (c *Client) AnnounceLoad(p AnnounceLoadPrm) error { - binCnr := make([]byte, sha256.Size) - p.a.Container().Encode(binCnr) - - prm := client.InvokePrm{} - prm.SetMethod(putSizeMethod) - prm.SetArgs(p.a.Epoch(), binCnr, p.a.Value(), p.key) - prm.InvokePrmOptional = p.InvokePrmOptional - - _, err := c.client.Invoke(prm) - if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", putSizeMethod, err) - } - return nil -} - // EstimationID is an identity of container load estimation inside Container contract. type EstimationID []byte diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index f19510d769..9305c143b8 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -239,15 +239,6 @@ func (x *multiClient) ObjectPutSingle(ctx context.Context, p client.PrmObjectPut return } -func (x *multiClient) ContainerAnnounceUsedSpace(ctx context.Context, prm client.PrmAnnounceSpace) (res *client.ResAnnounceSpace, err error) { - err = x.iterateClients(ctx, func(c clientcore.Client) error { - res, err = c.ContainerAnnounceUsedSpace(ctx, prm) - return err - }) - - return -} - func (x *multiClient) ObjectDelete(ctx context.Context, p client.PrmObjectDelete) (res *client.ResObjectDelete, err error) { err = x.iterateClients(ctx, func(c clientcore.Client) error { res, err = c.ObjectDelete(ctx, p) diff --git a/pkg/network/transport/container/grpc/service.go b/pkg/network/transport/container/grpc/service.go index ed514d6d4a..f0206dd5c4 100644 --- a/pkg/network/transport/container/grpc/service.go +++ b/pkg/network/transport/container/grpc/service.go @@ -81,21 +81,6 @@ func (s *Server) List(ctx context.Context, req *containerGRPC.ListRequest) (*con return resp.ToGRPCMessage().(*containerGRPC.ListResponse), nil } -// SetExtendedACL converts gRPC SetExtendedACLRequest message and passes it to internal Container service. -func (s *Server) SetExtendedACL(ctx context.Context, req *containerGRPC.SetExtendedACLRequest) (*containerGRPC.SetExtendedACLResponse, error) { - setEACLReq := new(container.SetExtendedACLRequest) - if err := setEACLReq.FromGRPCMessage(req); err != nil { - return nil, err - } - - resp, err := s.srv.SetExtendedACL(ctx, setEACLReq) - if err != nil { - return nil, err - } - - return resp.ToGRPCMessage().(*containerGRPC.SetExtendedACLResponse), nil -} - // GetExtendedACL converts gRPC GetExtendedACLRequest message and passes it to internal Container service. func (s *Server) GetExtendedACL(ctx context.Context, req *containerGRPC.GetExtendedACLRequest) (*containerGRPC.GetExtendedACLResponse, error) { getEACLReq := new(container.GetExtendedACLRequest) @@ -110,18 +95,3 @@ func (s *Server) GetExtendedACL(ctx context.Context, req *containerGRPC.GetExten return resp.ToGRPCMessage().(*containerGRPC.GetExtendedACLResponse), nil } - -// AnnounceUsedSpace converts gRPC AnnounceUsedSpaceRequest message and passes it to internal Container service. -func (s *Server) AnnounceUsedSpace(ctx context.Context, req *containerGRPC.AnnounceUsedSpaceRequest) (*containerGRPC.AnnounceUsedSpaceResponse, error) { - announceReq := new(container.AnnounceUsedSpaceRequest) - if err := announceReq.FromGRPCMessage(req); err != nil { - return nil, err - } - - resp, err := s.srv.AnnounceUsedSpace(ctx, announceReq) - if err != nil { - return nil, err - } - - return resp.ToGRPCMessage().(*containerGRPC.AnnounceUsedSpaceResponse), nil -} diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 3ea591c6a9..8fe4dd2d94 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -78,15 +78,6 @@ func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm } } -func (ac *apeChecker) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { - ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.AnnounceUsedSpace") - defer span.End() - - // this method is not used, so not checked - - return ac.next.AnnounceUsedSpace(ctx, req) -} - func (ac *apeChecker) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) { ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Delete") defer span.End() @@ -303,18 +294,6 @@ func (ac *apeChecker) getRoleWithoutContainerID(oID *refs.OwnerID, mh *session.R return nativeschema.PropertyValueContainerRoleOthers, pk, nil } -func (ac *apeChecker) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { - ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.SetExtendedACL") - defer span.End() - - if err := ac.validateContainerBoundedOperation(ctx, req.GetBody().GetEACL().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), - nativeschema.MethodSetContainerEACL); err != nil { - return nil, err - } - - return ac.next.SetExtendedACL(ctx, req) -} - func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, containerID *refs.ContainerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, op string) error { if vh == nil { return errMissingVerificationHeader diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index a6f0fb2221..9eed469ca3 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -9,7 +9,6 @@ import ( "net" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" @@ -50,7 +49,6 @@ func TestAPE(t *testing.T) { t.Run("deny get container by user claim tag", testDenyGetContainerByUserClaimTag) t.Run("deny get container by IP", testDenyGetContainerByIP) t.Run("deny get container by group id", testDenyGetContainerByGroupID) - t.Run("deny set container eACL for IR", testDenySetContainerEACLForIR) t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken) t.Run("deny put container for others with session token", testDenyPutContainerForOthersSessionToken) t.Run("deny put container, read namespace from frostfsID", testDenyPutContainerReadNamespaceFromFrostfsID) @@ -665,84 +663,6 @@ func testDenyGetContainerByGroupID(t *testing.T) { require.ErrorAs(t, err, &errAccessDenied) } -func testDenySetContainerEACLForIR(t *testing.T) { - t.Parallel() - srv := &srvStub{ - calls: map[string]int{}, - } - router := inmemory.NewInMemory() - contRdr := &containerStub{ - c: map[cid.ID]*containercore.Container{}, - } - ir := &irStub{ - keys: [][]byte{}, - } - nm := &netmapStub{} - frostfsIDSubjectReader := &frostfsidStub{ - subjects: map[util.Uint160]*client.Subject{}, - } - apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) - - contID := cidtest.ID() - testContainer := containertest.Container() - pp := netmap.PlacementPolicy{} - require.NoError(t, pp.DecodeString("REP 1")) - testContainer.SetPlacementPolicy(pp) - contRdr.c[contID] = &containercore.Container{Value: testContainer} - - nm.currentEpoch = 100 - nm.netmaps = map[uint64]*netmap.NetMap{} - var testNetmap netmap.NetMap - testNetmap.SetEpoch(nm.currentEpoch) - testNetmap.SetNodes([]netmap.NodeInfo{{}}) - nm.netmaps[nm.currentEpoch] = &testNetmap - nm.netmaps[nm.currentEpoch-1] = &testNetmap - - _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ - Rules: []chain.Rule{ - { - Status: chain.AccessDenied, - Actions: chain.Actions{ - Names: []string{ - nativeschema.MethodSetContainerEACL, - }, - }, - Resources: chain.Resources{ - Names: []string{ - fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), - }, - }, - Condition: []chain.Condition{ - { - Kind: chain.KindRequest, - Key: nativeschema.PropertyKeyActorRole, - Value: nativeschema.PropertyValueContainerRoleIR, - Op: chain.CondStringEquals, - }, - }, - }, - }, - }) - require.NoError(t, err) - - req := &container.SetExtendedACLRequest{} - req.SetBody(&container.SetExtendedACLRequestBody{}) - var refContID refs.ContainerID - contID.WriteToV2(&refContID) - req.GetBody().SetEACL(&acl.Table{}) - req.GetBody().GetEACL().SetContainerID(&refContID) - - pk, err := keys.NewPrivateKey() - require.NoError(t, err) - require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) - ir.keys = append(ir.keys, pk.PublicKey().Bytes()) - - resp, err := apeSrv.SetExtendedACL(context.Background(), req) - require.Nil(t, resp) - var errAccessDenied *apistatus.ObjectAccessDenied - require.ErrorAs(t, err, &errAccessDenied) -} - func testDenyGetContainerEACLForIRSessionToken(t *testing.T) { t.Parallel() srv := &srvStub{ @@ -1229,11 +1149,6 @@ type srvStub struct { calls map[string]int } -func (s *srvStub) AnnounceUsedSpace(context.Context, *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { - s.calls["AnnounceUsedSpace"]++ - return &container.AnnounceUsedSpaceResponse{}, nil -} - func (s *srvStub) Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error) { s.calls["Delete"]++ return &container.DeleteResponse{}, nil @@ -1259,11 +1174,6 @@ func (s *srvStub) Put(context.Context, *container.PutRequest) (*container.PutRes return &container.PutResponse{}, nil } -func (s *srvStub) SetExtendedACL(context.Context, *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { - s.calls["SetExtendedACL"]++ - return &container.SetExtendedACLResponse{}, nil -} - type irStub struct { keys [][]byte } diff --git a/pkg/services/container/audit.go b/pkg/services/container/audit.go index 7ef432bb11..34fd5923fa 100644 --- a/pkg/services/container/audit.go +++ b/pkg/services/container/audit.go @@ -6,7 +6,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" container_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -29,24 +28,6 @@ func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Serv } } -// AnnounceUsedSpace implements Server. -func (a *auditService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { - res, err := a.next.AnnounceUsedSpace(ctx, req) - if !a.enabled.Load() { - return res, err - } - - var ids []*refs.ContainerID - for _, v := range req.GetBody().GetAnnouncements() { - ids = append(ids, v.GetContainerID()) - } - - audit.LogRequest(a.log, container_grpc.ContainerService_AnnounceUsedSpace_FullMethodName, req, - audit.TargetFromRefs(ids, &cid.ID{}), err == nil) - - return res, err -} - // Delete implements Server. func (a *auditService) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) { res, err := a.next.Delete(ctx, req) @@ -103,14 +84,3 @@ func (a *auditService) Put(ctx context.Context, req *container.PutRequest) (*con audit.TargetFromRef(res.GetBody().GetContainerID(), &cid.ID{}), err == nil) return res, err } - -// SetExtendedACL implements Server. -func (a *auditService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { - res, err := a.next.SetExtendedACL(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequest(a.log, container_grpc.ContainerService_SetExtendedACL_FullMethodName, req, - audit.TargetFromRef(req.GetBody().GetEACL().GetContainerID(), &cid.ID{}), err == nil) - return res, err -} diff --git a/pkg/services/container/executor.go b/pkg/services/container/executor.go index d4ae11d62b..b64963e25b 100644 --- a/pkg/services/container/executor.go +++ b/pkg/services/container/executor.go @@ -14,7 +14,6 @@ type ServiceExecutor interface { Delete(context.Context, *session.Token, *container.DeleteRequestBody) (*container.DeleteResponseBody, error) Get(context.Context, *container.GetRequestBody) (*container.GetResponseBody, error) List(context.Context, *container.ListRequestBody) (*container.ListResponseBody, error) - SetExtendedACL(context.Context, *session.Token, *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) GetExtendedACL(context.Context, *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) } @@ -96,24 +95,6 @@ func (s *executorSvc) List(ctx context.Context, req *container.ListRequest) (*co return resp, nil } -func (s *executorSvc) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { - meta := req.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - - respBody, err := s.exec.SetExtendedACL(ctx, meta.GetSessionToken(), req.GetBody()) - if err != nil { - return nil, fmt.Errorf("could not execute SetEACL request: %w", err) - } - - resp := new(container.SetExtendedACLResponse) - resp.SetBody(respBody) - - s.respSvc.SetMeta(resp) - return resp, nil -} - func (s *executorSvc) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { respBody, err := s.exec.GetExtendedACL(ctx, req.GetBody()) if err != nil { diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index e2e79f3d2d..57dac32f04 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -13,8 +13,6 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) var errMissingUserID = errors.New("missing user ID") @@ -204,10 +202,6 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) return res, nil } -func (s *morphExecutor) SetExtendedACL(_ context.Context, _ *sessionV2.Token, _ *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) { - return nil, status.Errorf(codes.Unimplemented, "method SetExtendedACL not implemented") -} - func (s *morphExecutor) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) { idV2 := body.GetContainerID() if idV2 == nil { diff --git a/pkg/services/container/server.go b/pkg/services/container/server.go index 052a8c945c..d714d7f029 100644 --- a/pkg/services/container/server.go +++ b/pkg/services/container/server.go @@ -12,7 +12,5 @@ type Server interface { Get(context.Context, *container.GetRequest) (*container.GetResponse, error) Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error) List(context.Context, *container.ListRequest) (*container.ListResponse, error) - SetExtendedACL(context.Context, *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) GetExtendedACL(context.Context, *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) - AnnounceUsedSpace(context.Context, *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) } diff --git a/pkg/services/container/sign.go b/pkg/services/container/sign.go index bba717f60b..62aa3fe27f 100644 --- a/pkg/services/container/sign.go +++ b/pkg/services/container/sign.go @@ -57,15 +57,6 @@ func (s *signService) List(ctx context.Context, req *container.ListRequest) (*co return resp, s.sigSvc.SignResponse(resp, err) } -func (s *signService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) { - if err := s.sigSvc.VerifyRequest(req); err != nil { - resp := new(container.SetExtendedACLResponse) - return resp, s.sigSvc.SignResponse(resp, err) - } - resp, err := util.EnsureNonNilResponse(s.svc.SetExtendedACL(ctx, req)) - return resp, s.sigSvc.SignResponse(resp, err) -} - func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(container.GetExtendedACLResponse) @@ -74,12 +65,3 @@ func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExte resp, err := util.EnsureNonNilResponse(s.svc.GetExtendedACL(ctx, req)) return resp, s.sigSvc.SignResponse(resp, err) } - -func (s *signService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) { - if err := s.sigSvc.VerifyRequest(req); err != nil { - resp := new(container.AnnounceUsedSpaceResponse) - return resp, s.sigSvc.SignResponse(resp, err) - } - resp, err := util.EnsureNonNilResponse(s.svc.AnnounceUsedSpace(ctx, req)) - return resp, s.sigSvc.SignResponse(resp, err) -} From 85a77b7c21accc667f4f5cb50ea1a0bf8632cedb Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 29 Jul 2024 15:33:36 +0300 Subject: [PATCH 0717/1413] [#1279] adm: Interpret "root" name as empty for namespace target type Signed-off-by: Airat Arifullin --- cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 5e17f40142..d4aedda2ec 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -38,6 +38,12 @@ var ( func parseTarget(cmd *cobra.Command) policyengine.Target { name, _ := cmd.Flags().GetString(targetNameFlag) typ, err := parseTargetType(cmd) + + // interpret "root" namespace as empty + if typ == policyengine.Namespace && name == "root" { + name = "" + } + commonCmd.ExitOnErr(cmd, "read target type error: %w", err) return policyengine.Target{ From a12c39667d2b95f65697205b90f5d2e61d09132e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 29 Jul 2024 11:31:05 +0300 Subject: [PATCH 0718/1413] [#1278] ir: Do not allow to create container without FrostFSID record Signed-off-by: Dmitrii Stepanov --- pkg/innerring/processors/container/handlers_test.go | 3 +-- .../processors/container/process_container.go | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index 1aac31ae3b..dc1e919bbd 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -3,7 +3,6 @@ package container import ( "crypto/ecdsa" "encoding/hex" - "fmt" "testing" "time" @@ -238,5 +237,5 @@ func (c *testMorphClient) NotarySignAndInvokeTX(mainTx *transaction.Transaction) type testFrostFSIDClient struct{} func (c *testFrostFSIDClient) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) { - return nil, fmt.Errorf("subject not found") + return &frostfsidclient.Subject{}, nil } diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index a950997fd8..d89b63e82f 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -180,11 +180,6 @@ func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Contain } } - namespace, hasNamespace := strings.CutSuffix(ctx.d.Zone(), ".ns") - if !hasNamespace { - return nil - } - addr, err := util.Uint160DecodeBytesBE(cnr.Owner().WalletBytes()[1 : 1+util.Uint160Size]) if err != nil { return fmt.Errorf("could not get container owner address: %w", err) @@ -195,6 +190,11 @@ func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Contain return fmt.Errorf("could not get subject from FrostfsID contract: %w", err) } + namespace, hasNamespace := strings.CutSuffix(ctx.d.Zone(), ".ns") + if !hasNamespace { + return nil + } + if subject.Namespace != namespace { return errContainerAndOwnerNamespaceDontMatch } From 7e04083c273c7c50eebd76cde5d46d91fcc494a2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 29 Jul 2024 13:03:55 +0300 Subject: [PATCH 0719/1413] [#1278] containerSvc: Validate FrostFSID subject exitence on Put Signed-off-by: Dmitrii Stepanov --- pkg/services/container/ape.go | 21 ++++++++++++++++++++- pkg/services/container/ape_test.go | 15 ++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 8fe4dd2d94..6f8a8e0e63 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -211,7 +211,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont } } - namespace, err := ac.namespaceByOwner(req.GetBody().GetContainer().GetOwnerID()) + namespace, err := ac.namespaceByKnownOwner(req.GetBody().GetContainer().GetOwnerID()) if err != nil { return nil, fmt.Errorf("get namespace error: %w", err) } @@ -608,6 +608,25 @@ func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { return namespace, nil } +func (ac *apeChecker) namespaceByKnownOwner(owner *refs.OwnerID) (string, error) { + var ownerSDK user.ID + if owner == nil { + return "", errOwnerIDIsNotSet + } + if err := ownerSDK.ReadFromV2(*owner); err != nil { + return "", err + } + addr, err := ownerSDK.ScriptHash() + if err != nil { + return "", err + } + subject, err := ac.frostFSIDClient.GetSubject(addr) + if err != nil { + return "", fmt.Errorf("get subject error: %w", err) + } + return subject.Namespace, nil +} + // validateNamespace validates a namespace set in a container. // If frostfs-id contract stores a namespace N1 for an owner ID and a container within a request // is set with namespace N2 (via Zone() property), then N2 is invalid and the request is denied. diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 9eed469ca3..68c1158a64 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -765,17 +765,22 @@ func testDenyPutContainerForOthersSessionToken(t *testing.T) { keys: [][]byte{}, } nm := &netmapStub{} - frostfsIDSubjectReader := &frostfsidStub{ - subjects: map[util.Uint160]*client.Subject{}, - } - apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) testContainer := containertest.Container() + owner := testContainer.Owner() + ownerAddr, err := owner.ScriptHash() + require.NoError(t, err) + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + ownerAddr: {}, + }, + } + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) nm.currentEpoch = 100 nm.netmaps = map[uint64]*netmap.NetMap{} - _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{ + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{ Rules: []chain.Rule{ { Status: chain.AccessDenied, From c49982d22ac0f2f4314ba2d79ab835d93cc437c6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 30 Jul 2024 15:41:57 +0300 Subject: [PATCH 0720/1413] [#1282] cli: Allow to external addresses first for `object nodes` Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index d04cf6f049..42ae7324ea 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -30,7 +30,8 @@ import ( ) const ( - verifyPresenceAllFlag = "verify-presence-all" + verifyPresenceAllFlag = "verify-presence-all" + preferInternalAddressesFlag = "prefer-internal-addresses" ) var ( @@ -97,6 +98,7 @@ func initObjectNodesCmd() { flags.Bool(verifyPresenceAllFlag, false, "Verify the actual presence of the object on all netmap nodes.") flags.Bool(commonflags.JSON, false, "Print information about the object placement as json.") + flags.Bool(preferInternalAddressesFlag, false, "Use internal addresses first to get object info.") } func objectNodes(cmd *cobra.Command, _ []string) { @@ -449,11 +451,20 @@ func getNodesToCheckObjectExistance(cmd *cobra.Command, netmap *netmapSDK.NetMap func createClient(ctx context.Context, cmd *cobra.Command, candidate netmapSDK.NodeInfo, pk *ecdsa.PrivateKey) (*client.Client, error) { var cli *client.Client var addresses []string - candidate.IterateNetworkEndpoints(func(s string) bool { - addresses = append(addresses, s) - return false - }) - addresses = append(addresses, candidate.ExternalAddresses()...) + if preferInternal, _ := cmd.Flags().GetBool(preferInternalAddressesFlag); preferInternal { + candidate.IterateNetworkEndpoints(func(s string) bool { + addresses = append(addresses, s) + return false + }) + addresses = append(addresses, candidate.ExternalAddresses()...) + } else { + addresses = append(addresses, candidate.ExternalAddresses()...) + candidate.IterateNetworkEndpoints(func(s string) bool { + addresses = append(addresses, s) + return false + }) + } + var lastErr error for _, address := range addresses { var networkAddr network.Address From a55600893efeadfc48a83f3f2529d846f4d534c3 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 2 Aug 2024 12:31:59 +0300 Subject: [PATCH 0721/1413] [#1266] Makefile: Specify gofumpt version Add target to install gofumpt, fix target to run gofumpt. Signed-off-by: Ekaterina Lebedeva --- Makefile | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c93d06aa87..11111d9a7e 100755 --- a/Makefile +++ b/Makefile @@ -46,6 +46,10 @@ STATICCHECK_VERSION_DIR ?= $(STATICCHECK_DIR)/$(STATICCHECK_VERSION) SOURCES = $(shell find . -type f -name "*.go" -print) +GOFUMPT_VERSION ?= v0.6.0 +GOFUMPT_DIR ?= $(abspath $(BIN))/gofumpt +GOFUMPT_VERSION_DIR ?= $(GOFUMPT_DIR)/$(GOFUMPT_VERSION) + GOPLS_VERSION ?= v0.15.1 GOPLS_DIR ?= $(abspath $(BIN))/gopls GOPLS_VERSION_DIR ?= $(GOPLS_DIR)/$(GOPLS_VERSION) @@ -165,10 +169,19 @@ imports: @echo "⇒ Processing goimports check" @goimports -w cmd/ pkg/ misc/ +# Install gofumpt +fumpt-install: + @rm -rf $(GOFUMPT_DIR) + @mkdir $(GOFUMPT_DIR) + @GOBIN=$(GOFUMPT_VERSION_DIR) go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION) + # Run gofumpt fumpt: + @if [ ! -d "$(GOFUMPT_VERSION_DIR)" ]; then \ + make fumpt-install; \ + fi @echo "⇒ Processing gofumpt check" - @gofumpt -l -w cmd/ pkg/ misc/ + $(GOFUMPT_VERSION_DIR)/gofumpt -l -w cmd/ pkg/ misc/ # Run Unit Test with go test test: GOFLAGS ?= "-count=1" From ef4cea6d19eb8a4d05e47647f00d874c892c17ea Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 2 Aug 2024 12:34:04 +0300 Subject: [PATCH 0722/1413] [#1266] .forgejo: Add gofumpt action `gofumpt` was skipped by pre-commit on CI, and now is used in a separate action. Signed-off-by: Ekaterina Lebedeva --- .forgejo/workflows/tests.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index b0c9adbf27..5d64d7bc44 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -89,3 +89,21 @@ jobs: - name: Run gopls run: make gopls-run + + fumpt: + name: Run gofumpt + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '1.22' + cache: true + + - name: Install gofumpt + run: make fumpt-install + + - name: Run gofumpt + run: make fumpt From 8021bacc43c1ae065033bfefa163d802b9eaeb33 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 1 Aug 2024 16:08:50 +0300 Subject: [PATCH 0723/1413] [#1288] putSvc: Respect TTL for EC put Signed-off-by: Dmitrii Stepanov --- pkg/services/object/put/ec.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/pkg/services/object/put/ec.go b/pkg/services/object/put/ec.go index 6da50195ec..fbb51912c9 100644 --- a/pkg/services/object/put/ec.go +++ b/pkg/services/object/put/ec.go @@ -17,6 +17,7 @@ import ( containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" "go.uber.org/zap" "golang.org/x/sync/errgroup" @@ -39,7 +40,7 @@ type ecWriter struct { } func (e *ecWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error { - relayed, err := e.relayIfNotContainerNode(ctx) + relayed, err := e.relayIfNotContainerNode(ctx, obj) if err != nil { return err } @@ -65,7 +66,7 @@ func (e *ecWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error return e.writeRawObject(ctx, obj) } -func (e *ecWriter) relayIfNotContainerNode(ctx context.Context) (bool, error) { +func (e *ecWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.Object) (bool, error) { if e.relay == nil { return false, nil } @@ -77,7 +78,13 @@ func (e *ecWriter) relayIfNotContainerNode(ctx context.Context) (bool, error) { // object can be splitted or saved local return false, nil } - if err := e.relayToContainerNode(ctx); err != nil { + objID := object.AddressOf(obj).Object() + var index uint32 + if obj.ECHeader() != nil { + objID = obj.ECHeader().Parent() + index = obj.ECHeader().Index() + } + if err := e.relayToContainerNode(ctx, objID, index); err != nil { return false, err } return true, nil @@ -102,18 +109,20 @@ func (e *ecWriter) currentNodeIsContainerNode() (bool, error) { return false, nil } -func (e *ecWriter) relayToContainerNode(ctx context.Context) error { - t, err := placement.NewTraverser(e.placementOpts...) +func (e *ecWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index uint32) error { + t, err := placement.NewTraverser(append(e.placementOpts, placement.ForObject(objID))...) if err != nil { return err } var lastErr error + offset := int(index) for { nodes := t.Next() if len(nodes) == 0 { break } - for _, node := range nodes { + for idx := range nodes { + node := nodes[(idx+offset)%len(nodes)] var info client.NodeInfo client.NodeInfoFromNetmapElement(&info, node) @@ -149,6 +158,10 @@ func (e *ecWriter) relayToContainerNode(ctx context.Context) error { } func (e *ecWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error { + if e.commonPrm.LocalOnly() { + return e.writePartLocal(ctx, obj) + } + t, err := placement.NewTraverser(append(e.placementOpts, placement.ForObject(obj.ECHeader().Parent()))...) if err != nil { return err From dc3dcabadca1d1bfb20dab5947ec4c22f3d2362b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 2 Aug 2024 17:50:49 +0300 Subject: [PATCH 0724/1413] [#1291] morph: Reconnect to the highest priority endpoint Signed-off-by: Dmitrii Stepanov --- pkg/morph/client/constructor.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index 648c7d3c0d..78cb3e82f5 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -148,6 +148,10 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er } else { cli.logger.Info(logs.FrostFSIRCreatedRPCClientForEndpoint, zap.String("endpoint", endpoint.Address)) + if cli.endpoints.curr > 0 && cli.cfg.switchInterval != 0 { + cli.switchIsActive.Store(true) + go cli.switchToMostPrioritized(ctx) + } break } } From 327d364f34de730879f330ea51d8801f5c6bddc9 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 2 Aug 2024 16:20:51 +0300 Subject: [PATCH 0725/1413] [#1262] sdnotify: Get rid of go:linkname for nanotime Signed-off-by: Ekaterina Lebedeva --- pkg/util/sdnotify/clock.go | 10 ---------- pkg/util/sdnotify/clock.s | 2 -- pkg/util/sdnotify/sdnotify.go | 4 +++- 3 files changed, 3 insertions(+), 13 deletions(-) delete mode 100644 pkg/util/sdnotify/clock.go delete mode 100644 pkg/util/sdnotify/clock.s diff --git a/pkg/util/sdnotify/clock.go b/pkg/util/sdnotify/clock.go deleted file mode 100644 index f5419d0274..0000000000 --- a/pkg/util/sdnotify/clock.go +++ /dev/null @@ -1,10 +0,0 @@ -package sdnotify - -import ( - // For go:linkname to work. - _ "unsafe" -) - -//go:noescape -//go:linkname nanotime runtime.nanotime -func nanotime() int64 diff --git a/pkg/util/sdnotify/clock.s b/pkg/util/sdnotify/clock.s deleted file mode 100644 index ad033ff4f7..0000000000 --- a/pkg/util/sdnotify/clock.s +++ /dev/null @@ -1,2 +0,0 @@ -// The file is intentionally empty. -// It is a workaround for https://github.com/golang/go/issues/15006 diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go index 16a3f11c1e..a3af50b22a 100644 --- a/pkg/util/sdnotify/sdnotify.go +++ b/pkg/util/sdnotify/sdnotify.go @@ -6,6 +6,7 @@ import ( "net" "os" "strings" + "time" ) const ( @@ -16,6 +17,7 @@ const ( var ( socket *net.UnixAddr + start = time.Now() errSocketVariableIsNotPresent = errors.New("\"NOTIFY_SOCKET\" environment variable is not present") errSocketIsNotInitialized = errors.New("socket is not initialized") @@ -51,7 +53,7 @@ func FlagAndStatus(status string) error { // must be sent, containing "READY=1". // // For MONOTONIC_USEC format refer to https://www.man7.org/linux/man-pages/man3/sd_notify.3.html - status += fmt.Sprintf("\nMONOTONIC_USEC=%d", uint64(nanotime())/1e3 /* microseconds in nanoseconds */) + status += fmt.Sprintf("\nMONOTONIC_USEC=%d", uint64(time.Since(start))/1e3 /* microseconds in nanoseconds */) } status += "\nSTATUS=" + strings.TrimSuffix(status, "=1") return Send(status) From eeca796d2e5f60b0331e05e29735d7651e9794ae Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 5 Aug 2024 13:24:48 +0300 Subject: [PATCH 0726/1413] [#1295] engine: Log object address in case of error Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/delete.go | 6 +++--- pkg/local_object_storage/engine/exists.go | 3 ++- pkg/local_object_storage/engine/get.go | 2 +- pkg/local_object_storage/engine/head.go | 3 ++- pkg/local_object_storage/engine/inhume.go | 8 ++++---- pkg/local_object_storage/engine/lock.go | 13 +++++++++---- pkg/local_object_storage/engine/put.go | 2 +- pkg/local_object_storage/engine/range.go | 2 +- 8 files changed, 23 insertions(+), 16 deletions(-) diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 0965289672..318f938fb3 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -100,7 +100,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e return false } else { if !client.IsErrObjectNotFound(err) { - e.reportShardError(sh, "could not check object existence", err) + e.reportShardError(sh, "could not check object existence", err, zap.Stringer("address", prm.addr)) } return false } @@ -116,7 +116,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e _, err = sh.Inhume(ctx, shPrm) if err != nil { - e.reportShardError(sh, "could not inhume object in shard", err) + e.reportShardError(sh, "could not inhume object in shard", err, zap.Stringer("address", prm.addr)) var target *apistatus.ObjectLocked locked.is = errors.As(err, &target) @@ -191,7 +191,7 @@ func (e *StorageEngine) deleteChunks( var objID oid.ID err := objID.ReadFromV2(chunk.ID) if err != nil { - e.reportShardError(sh, "could not delete EC chunk", err) + e.reportShardError(sh, "could not delete EC chunk", err, zap.Stringer("address", prm.addr)) } addr.SetObject(objID) inhumePrm.MarkAsGarbage(addr) diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index c57f796912..d981013064 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "go.uber.org/zap" ) // exists return in the first value true if object exists. @@ -36,7 +37,7 @@ func (e *StorageEngine) exists(ctx context.Context, shPrm shard.ExistsPrm) (bool } if !client.IsErrObjectNotFound(err) { - e.reportShardError(sh, "could not check existence of object in shard", err) + e.reportShardError(sh, "could not check existence of object in shard", err, zap.Stringer("address", shPrm.Address)) } return false } diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index 991af3d1a3..253256c342 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -186,7 +186,7 @@ func (i *getShardIterator) tryGetWithMeta(ctx context.Context) { i.ObjectExpired = true return true default: - i.Engine.reportShardError(sh, "could not get object from shard", err) + i.Engine.reportShardError(sh, "could not get object from shard", err, zap.Stringer("address", i.Address)) return false } }) diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index 92d1b20fc2..dfe5e48a13 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -12,6 +12,7 @@ import ( apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.uber.org/zap" ) // HeadPrm groups the parameters of Head operation. @@ -118,7 +119,7 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) outError = new(apistatus.ObjectNotFound) return true default: - e.reportShardError(sh, "could not head object from shard", err) + e.reportShardError(sh, "could not head object from shard", err, zap.Stringer("address", prm.addr)) return false } } diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 991305af09..683713f943 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -154,7 +154,7 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh var siErr *objectSDK.SplitInfoError var ecErr *objectSDK.ECInfoError if !(errors.As(err, &siErr) || errors.As(err, &ecErr)) { - e.reportShardError(sh, "could not check for presents in shard", err) + e.reportShardError(sh, "could not check for presents in shard", err, zap.Stringer("address", addr)) return } @@ -179,7 +179,7 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh return true } - e.reportShardError(sh, "could not inhume object in shard", err) + e.reportShardError(sh, "could not inhume object in shard", err, zap.Stringer("address", addr)) return false } @@ -205,7 +205,7 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { locked, err = h.Shard.IsLocked(ctx, addr) if err != nil { - e.reportShardError(h, "can't check object's lockers", err, zap.Stringer("addr", addr), + e.reportShardError(h, "can't check object's lockers", err, zap.Stringer("address", addr), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) outErr = err return false @@ -235,7 +235,7 @@ func (e *StorageEngine) GetLocked(ctx context.Context, addr oid.Address) ([]oid. e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { ld, err := h.Shard.GetLocked(ctx, addr) if err != nil { - e.reportShardError(h, logs.EngineInterruptGettingLockers, err, zap.Stringer("addr", addr), + e.reportShardError(h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) outErr = err } diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index 5354c205f2..3a41a78485 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -13,6 +13,7 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" ) var errLockFailed = errors.New("lock operation failed") @@ -90,14 +91,16 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo var objID oid.ID err = objID.ReadFromV2(chunk.ID) if err != nil { - e.reportShardError(sh, "could not lock object in shard", err) + e.reportShardError(sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), + zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) return false } eclocked = append(eclocked, objID) } err = sh.Lock(ctx, idCnr, locker, eclocked) if err != nil { - e.reportShardError(sh, "could not lock object in shard", err) + e.reportShardError(sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), + zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) return false } root = true @@ -109,7 +112,8 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo return true } - e.reportShardError(sh, "could not check locked object for presence in shard", err) + e.reportShardError(sh, "could not check locked object for presence in shard", err, zap.Stringer("container_id", idCnr), + zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) return } @@ -121,7 +125,8 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo err := sh.Lock(ctx, idCnr, locker, []oid.ID{locked}) if err != nil { - e.reportShardError(sh, "could not lock object in shard", err) + e.reportShardError(sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), + zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) var errIrregular *apistatus.LockNonRegularObject if errors.As(err, &errIrregular) { diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 54385910be..f92d837454 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -187,7 +187,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti return } - e.reportShardError(sh, "could not put object to shard", err) + e.reportShardError(sh, "could not put object to shard", err, zap.Stringer("address", addr)) return } diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index f5b33a251e..cbf26ff4e8 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -208,7 +208,7 @@ func (i *getRangeShardIterator) tryGetWithMeta(ctx context.Context) { return true // stop, return it back default: - i.Engine.reportShardError(sh, "could not get object from shard", err) + i.Engine.reportShardError(sh, "could not get object from shard", err, zap.Stringer("address", i.Address)) return false } }) From 10602b55b1974512b5cac603b87ae6f1b2fe84b5 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 5 Aug 2024 16:13:43 +0300 Subject: [PATCH 0727/1413] [#1295] engine: Resolve funlen linter Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/lock.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index 3a41a78485..ac8fa9c6fc 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -63,11 +63,9 @@ func (e *StorageEngine) lock(ctx context.Context, idCnr cid.ID, locker oid.ID, l func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, locked oid.ID, checkExists bool) (status uint8) { // code is pretty similar to inhumeAddr, maybe unify? root := false - var addrLocked oid.Address addrLocked.SetContainer(idCnr) addrLocked.SetObject(locked) - e.iterateOverSortedShards(addrLocked, func(_ int, sh hashedShard) (stop bool) { defer func() { // if object is root we continue since information about it @@ -80,7 +78,6 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo if checkExists { var existsPrm shard.ExistsPrm existsPrm.Address = addrLocked - exRes, err := sh.Exists(ctx, existsPrm) if err != nil { var siErr *objectSDK.SplitInfoError @@ -111,7 +108,6 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo // do not lock it return true } - e.reportShardError(sh, "could not check locked object for presence in shard", err, zap.Stringer("container_id", idCnr), zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) return @@ -133,14 +129,10 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo status = 1 return true } - return false } - status = 2 - return true }) - return } From 8e51d7849a41c1135695650d9a748d0ba29a9dfb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 6 Aug 2024 09:32:40 +0300 Subject: [PATCH 0728/1413] [#1295] getSvc: Assemble complex EC object headers without linking object Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/head.go | 15 ++++----- pkg/local_object_storage/metabase/get.go | 22 +++++++++--- pkg/services/object/get/assemble.go | 4 +-- pkg/services/object/get/assembler.go | 43 ++++++++++++++++++++++++ pkg/services/object/get/get_test.go | 2 +- pkg/services/object/get/request.go | 4 +-- 6 files changed, 72 insertions(+), 18 deletions(-) diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index dfe5e48a13..6857a36319 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -127,17 +127,16 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) return true }) + if head != nil { + return HeadRes{head: head}, nil + } if outSI != nil { return HeadRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(outSI)) - } else if outEI != nil { - return HeadRes{}, logicerr.Wrap(objectSDK.NewECInfoError(outEI)) - } else if head == nil { - return HeadRes{}, outError } - - return HeadRes{ - head: head, - }, nil + if outEI != nil { + return HeadRes{}, logicerr.Wrap(objectSDK.NewECInfoError(outEI)) + } + return HeadRes{}, outError } // Head reads object header from local storage by provided address. diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index d9acd4ce2a..b79f6cb14a 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -160,11 +160,23 @@ func getVirtualObject(tx *bbolt.Tx, cnr cid.ID, key []byte, raw bool) (*objectSD return nil, logicerr.Wrap(new(apistatus.ObjectNotFound)) } - // pick last item, for now there is not difference which address to pick - // but later list might be sorted so first or last value can be more - // prioritized to choose - virtualOID := relativeLst[len(relativeLst)-1] - data := getFromBucket(tx, primaryBucketName(cnr, bucketName), virtualOID) + var data []byte + for i := 0; i < len(relativeLst) && len(data) == 0; i++ { + virtualOID := relativeLst[len(relativeLst)-i-1] + data = getFromBucket(tx, primaryBucketName(cnr, bucketName), virtualOID) + } + + if len(data) == 0 { + // check if any of the relatives is an EC object + for _, relative := range relativeLst { + data = getFromBucket(tx, ecInfoBucketName(cnr, bucketName), relative) + if len(data) > 0 { + // we can't return object headers, but can return error, + // so assembler can try to assemble complex object + return nil, getSplitInfoError(tx, cnr, key) + } + } + } child := objectSDK.New() diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index ba6fddec5a..9f17f1e4c3 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -12,7 +12,7 @@ import ( ) func (r *request) assemble(ctx context.Context) { - if !r.canAssemble() { + if !r.canAssembleComplexObject() { r.log.Debug(logs.GetCanNotAssembleTheObject) return } @@ -38,7 +38,7 @@ func (r *request) assemble(ctx context.Context) { r.log.Debug(logs.GetTryingToAssembleTheObject) r.prm.common = r.prm.common.WithLocalOnly(false) - assembler := newAssembler(r.address(), r.splitInfo(), r.ctxRange(), r) + assembler := newAssembler(r.address(), r.splitInfo(), r.ctxRange(), r, r.headOnly()) r.log.Debug(logs.GetAssemblingSplittedObject, zap.Uint64("range_offset", r.ctxRange().GetOffset()), diff --git a/pkg/services/object/get/assembler.go b/pkg/services/object/get/assembler.go index 025296ec77..ff3f90bf2d 100644 --- a/pkg/services/object/get/assembler.go +++ b/pkg/services/object/get/assembler.go @@ -19,6 +19,7 @@ type assembler struct { splitInfo *objectSDK.SplitInfo rng *objectSDK.Range objGetter objectGetter + head bool currentOffset uint64 @@ -30,18 +31,23 @@ func newAssembler( splitInfo *objectSDK.SplitInfo, rng *objectSDK.Range, objGetter objectGetter, + head bool, ) *assembler { return &assembler{ addr: addr, rng: rng, splitInfo: splitInfo, objGetter: objGetter, + head: head, } } // Assemble assembles splitted large object and writes it's content to ObjectWriter. // It returns parent object. func (a *assembler) Assemble(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { + if a.head { + return a.assembleHeader(ctx, writer) + } sourceObjectID, ok := a.getLastPartOrLinkObjectID() if !ok { return nil, objectSDK.NewSplitInfoError(a.splitInfo) @@ -65,6 +71,43 @@ func (a *assembler) Assemble(ctx context.Context, writer ObjectWriter) (*objectS return a.parentObject, nil } +func (a *assembler) assembleHeader(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { + var sourceObjectIDs []oid.ID + sourceObjectID, ok := a.splitInfo.Link() + if ok { + sourceObjectIDs = append(sourceObjectIDs, sourceObjectID) + } + sourceObjectID, ok = a.splitInfo.LastPart() + if ok { + sourceObjectIDs = append(sourceObjectIDs, sourceObjectID) + } + if len(sourceObjectIDs) == 0 { + return nil, objectSDK.NewSplitInfoError(a.splitInfo) + } + for _, sourceObjectID = range sourceObjectIDs { + obj, err := a.getParent(ctx, sourceObjectID, writer) + if err == nil { + return obj, nil + } + } + return nil, objectSDK.NewSplitInfoError(a.splitInfo) +} + +func (a *assembler) getParent(ctx context.Context, sourceObjectID oid.ID, writer ObjectWriter) (*objectSDK.Object, error) { + obj, err := a.objGetter.HeadObject(ctx, sourceObjectID) + if err != nil { + return nil, err + } + parent := obj.Parent() + if parent == nil { + return nil, objectSDK.NewSplitInfoError(a.splitInfo) + } + if err := writer.WriteHeader(ctx, parent); err != nil { + return nil, err + } + return obj, nil +} + func (a *assembler) getLastPartOrLinkObjectID() (oid.ID, bool) { sourceObjectID, ok := a.splitInfo.Link() if ok { diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 29a15ba786..1fc6b7b20a 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -730,7 +730,7 @@ func TestGetRemoteSmall(t *testing.T) { t.Run("VIRTUAL", func(t *testing.T) { testHeadVirtual := func(svc *Service, addr oid.Address, i *objectSDK.SplitInfo) { - headPrm := newHeadPrm(false, nil) + headPrm := newHeadPrm(true, nil) headPrm.WithAddress(addr) errSplit := objectSDK.NewSplitInfoError(objectSDK.NewSplitInfo()) diff --git a/pkg/services/object/get/request.go b/pkg/services/object/get/request.go index 9ddfeddf28..1a7a43a351 100644 --- a/pkg/services/object/get/request.go +++ b/pkg/services/object/get/request.go @@ -88,8 +88,8 @@ func (r *request) key() (*ecdsa.PrivateKey, error) { return r.keyStore.GetKey(sessionInfo) } -func (r *request) canAssemble() bool { - return !r.isRaw() && !r.headOnly() +func (r *request) canAssembleComplexObject() bool { + return !r.isRaw() } func (r *request) splitInfo() *objectSDK.SplitInfo { From 5c01bd5be89b40f2bd5edd4526b474644e053f11 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 6 Aug 2024 13:20:33 +0300 Subject: [PATCH 0729/1413] [#1298] writecache: Add `restore-mode` flag for Seal command Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/writecache.go | 5 + pkg/local_object_storage/engine/writecache.go | 4 +- pkg/local_object_storage/shard/writecache.go | 5 +- pkg/local_object_storage/writecache/seal.go | 19 +- .../writecache/writecache.go | 7 +- pkg/services/control/ir/service_grpc.pb.go | 6 +- .../control/server/seal_writecache.go | 1 + pkg/services/control/service.pb.go | 347 +++++++++--------- pkg/services/control/service.proto | 3 + pkg/services/control/service_frostfs.pb.go | 2 + pkg/services/tree/service_grpc.pb.go | 44 +-- 11 files changed, 238 insertions(+), 205 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/writecache.go b/cmd/frostfs-cli/modules/control/writecache.go index abc4ed2e6f..a665ccae87 100644 --- a/cmd/frostfs-cli/modules/control/writecache.go +++ b/cmd/frostfs-cli/modules/control/writecache.go @@ -9,6 +9,8 @@ import ( "github.com/spf13/cobra" ) +const restoreModeFlag = "restore-mode" + var writecacheShardCmd = &cobra.Command{ Use: "writecache", Short: "Operations with storage node's write-cache", @@ -26,10 +28,12 @@ func sealWritecache(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) ignoreErrors, _ := cmd.Flags().GetBool(ignoreErrorsFlag) + restoreMode, _ := cmd.Flags().GetBool(restoreModeFlag) req := &control.SealWriteCacheRequest{Body: &control.SealWriteCacheRequest_Body{ Shard_ID: getShardIDList(cmd), IgnoreErrors: ignoreErrors, + RestoreMode: restoreMode, }} signRequest(cmd, pk, req) @@ -68,6 +72,7 @@ func initControlShardsWritecacheCmd() { ff.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") ff.Bool(shardAllFlag, false, "Process all shards") ff.Bool(ignoreErrorsFlag, true, "Skip invalid/unreadable objects") + ff.Bool(restoreModeFlag, false, "Restore writecache's mode after sealing") sealWritecacheShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag) } diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index da488260a4..8f37d78609 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -70,6 +70,7 @@ func (e *StorageEngine) FlushWriteCache(ctx context.Context, p FlushWriteCachePr type SealWriteCachePrm struct { ShardIDs []*shard.ID IgnoreErrors bool + RestoreMode bool } type ShardSealResult struct { @@ -88,6 +89,7 @@ func (e *StorageEngine) SealWriteCache(ctx context.Context, prm SealWriteCachePr trace.WithAttributes( attribute.Int("shard_id_count", len(prm.ShardIDs)), attribute.Bool("ignore_errors", prm.IgnoreErrors), + attribute.Bool("restore_mode", prm.RestoreMode), )) defer span.End() @@ -114,7 +116,7 @@ func (e *StorageEngine) SealWriteCache(ctx context.Context, prm SealWriteCachePr return nil } - err := sh.SealWriteCache(egCtx, shard.SealWriteCachePrm{IgnoreErrors: prm.IgnoreErrors}) + err := sh.SealWriteCache(egCtx, shard.SealWriteCachePrm{IgnoreErrors: prm.IgnoreErrors, RestoreMode: prm.RestoreMode}) resGuard.Lock() defer resGuard.Unlock() diff --git a/pkg/local_object_storage/shard/writecache.go b/pkg/local_object_storage/shard/writecache.go index 05e014d29c..9edad71705 100644 --- a/pkg/local_object_storage/shard/writecache.go +++ b/pkg/local_object_storage/shard/writecache.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -59,6 +60,7 @@ func (s *Shard) FlushWriteCache(ctx context.Context, p FlushWriteCachePrm) error type SealWriteCachePrm struct { IgnoreErrors bool + RestoreMode bool } // SealWriteCache flushes all data from the write-cache and moves it to degraded read only mode. @@ -67,6 +69,7 @@ func (s *Shard) SealWriteCache(ctx context.Context, p SealWriteCachePrm) error { trace.WithAttributes( attribute.String("shard_id", s.ID().String()), attribute.Bool("ignore_errors", p.IgnoreErrors), + attribute.Bool("restore_mode", p.RestoreMode), )) defer span.End() @@ -84,5 +87,5 @@ func (s *Shard) SealWriteCache(ctx context.Context, p SealWriteCachePrm) error { return ErrDegradedMode } - return s.writeCache.Seal(ctx, p.IgnoreErrors) + return s.writeCache.Seal(ctx, writecache.SealPrm{IgnoreErrors: p.IgnoreErrors, RestoreMode: p.RestoreMode}) } diff --git a/pkg/local_object_storage/writecache/seal.go b/pkg/local_object_storage/writecache/seal.go index 48107a75f6..22b4e0988c 100644 --- a/pkg/local_object_storage/writecache/seal.go +++ b/pkg/local_object_storage/writecache/seal.go @@ -9,20 +9,29 @@ import ( "go.opentelemetry.io/otel/trace" ) -func (c *cache) Seal(ctx context.Context, ignoreErrors bool) error { +func (c *cache) Seal(ctx context.Context, prm SealPrm) error { ctx, span := tracing.StartSpanFromContext(ctx, "writecache.Seal", trace.WithAttributes( - attribute.Bool("ignore_errors", ignoreErrors), + attribute.Bool("ignore_errors", prm.IgnoreErrors), + attribute.Bool("restore_mode", prm.RestoreMode), )) defer span.End() c.modeMtx.Lock() defer c.modeMtx.Unlock() + sourceMode := c.mode // flush will be done by setMode - err := c.setMode(ctx, mode.DegradedReadOnly, ignoreErrors) - if err == nil { - c.metrics.SetMode(mode.ComponentDisabled) + err := c.setMode(ctx, mode.DegradedReadOnly, prm.IgnoreErrors) + if err != nil { + return err + } + c.metrics.SetMode(mode.ComponentDisabled) + if prm.RestoreMode { + err = c.setMode(ctx, sourceMode, prm.IgnoreErrors) + if err == nil { + c.metrics.SetMode(mode.ConvertToComponentMode(sourceMode)) + } } return err } diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 71dba61cf0..7085a57b2a 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -20,6 +20,11 @@ type Info struct { Path string } +type SealPrm struct { + IgnoreErrors bool + RestoreMode bool +} + // Cache represents write-cache for objects. type Cache interface { Get(ctx context.Context, address oid.Address) (*objectSDK.Object, error) @@ -36,7 +41,7 @@ type Cache interface { SetLogger(*logger.Logger) DumpInfo() Info Flush(context.Context, bool, bool) error - Seal(context.Context, bool) error + Seal(context.Context, SealPrm) error Init() error Open(ctx context.Context, mode mode.Mode) error diff --git a/pkg/services/control/ir/service_grpc.pb.go b/pkg/services/control/ir/service_grpc.pb.go index 724149c441..336bf5f70d 100644 --- a/pkg/services/control/ir/service_grpc.pb.go +++ b/pkg/services/control/ir/service_grpc.pb.go @@ -35,7 +35,8 @@ type ControlServiceClient interface { TickEpoch(ctx context.Context, in *TickEpochRequest, opts ...grpc.CallOption) (*TickEpochResponse, error) // Forces a node removal to be signaled by the IR node with high probability. RemoveNode(ctx context.Context, in *RemoveNodeRequest, opts ...grpc.CallOption) (*RemoveNodeResponse, error) - // Forces a container removal to be signaled by the IR node with high probability. + // Forces a container removal to be signaled by the IR node with high + // probability. RemoveContainer(ctx context.Context, in *RemoveContainerRequest, opts ...grpc.CallOption) (*RemoveContainerResponse, error) } @@ -93,7 +94,8 @@ type ControlServiceServer interface { TickEpoch(context.Context, *TickEpochRequest) (*TickEpochResponse, error) // Forces a node removal to be signaled by the IR node with high probability. RemoveNode(context.Context, *RemoveNodeRequest) (*RemoveNodeResponse, error) - // Forces a container removal to be signaled by the IR node with high probability. + // Forces a container removal to be signaled by the IR node with high + // probability. RemoveContainer(context.Context, *RemoveContainerRequest) (*RemoveContainerResponse, error) } diff --git a/pkg/services/control/server/seal_writecache.go b/pkg/services/control/server/seal_writecache.go index e3f8b8caf6..b663cfc815 100644 --- a/pkg/services/control/server/seal_writecache.go +++ b/pkg/services/control/server/seal_writecache.go @@ -19,6 +19,7 @@ func (s *Server) SealWriteCache(ctx context.Context, req *control.SealWriteCache prm := engine.SealWriteCachePrm{ ShardIDs: s.getShardIDList(req.GetBody().GetShard_ID()), IgnoreErrors: req.GetBody().GetIgnoreErrors(), + RestoreMode: req.GetBody().GetRestoreMode(), } res, err := s.s.SealWriteCache(ctx, prm) diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 727dd1218b..895b743684 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -4727,6 +4727,8 @@ type SealWriteCacheRequest_Body struct { Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` // Flag indicating whether object read errors should be ignored. IgnoreErrors bool `protobuf:"varint,2,opt,name=ignore_errors,json=ignoreErrors,proto3" json:"ignore_errors,omitempty"` + // If true, then writecache will be sealed, but mode will be restored to the current one. + RestoreMode bool `protobuf:"varint,4,opt,name=restore_mode,json=restoreMode,proto3" json:"restore_mode,omitempty"` } func (x *SealWriteCacheRequest_Body) Reset() { @@ -4775,6 +4777,13 @@ func (x *SealWriteCacheRequest_Body) GetIgnoreErrors() bool { return false } +func (x *SealWriteCacheRequest_Body) GetRestoreMode() bool { + if x != nil { + return x.RestoreMode + } + return false +} + type SealWriteCacheResponse_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -5482,7 +5491,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xca, 0x01, 0x0a, 0x15, + 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xed, 0x01, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, @@ -5491,182 +5500,184 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, + 0x1a, 0x69, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, - 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, - 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, - 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, - 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, + 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xa9, 0x02, 0x0a, 0x16, + 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, + 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, + 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, + 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, + 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, + 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x32, 0x8b, 0x10, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, - 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, - 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, + 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, + 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, + 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0x8b, 0x10, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, + 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, + 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, - 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, - 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, - 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, - 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, + 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, + 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, + 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, + 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, - 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, - 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, - 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, + 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, + 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, + 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, + 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, + 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, + 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x8a, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, - 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, - 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, - 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, - 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, + 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, + 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, + 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, + 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 2cd8434fc9..a10410025a 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -655,6 +655,9 @@ message SealWriteCacheRequest { // Flag indicating whether object read errors should be ignored. bool ignore_errors = 2; + + // If true, then writecache will be sealed, but mode will be restored to the current one. + bool restore_mode = 4; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index a287606fa2..b6b064973d 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -3422,6 +3422,7 @@ func (x *SealWriteCacheRequest_Body) StableSize() (size int) { } size += proto.RepeatedBytesSize(1, x.Shard_ID) size += proto.BoolSize(2, x.IgnoreErrors) + size += proto.BoolSize(4, x.RestoreMode) return size } @@ -3443,6 +3444,7 @@ func (x *SealWriteCacheRequest_Body) StableMarshal(buf []byte) []byte { var offset int offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) offset += proto.BoolMarshal(2, buf[offset:], x.IgnoreErrors) + offset += proto.BoolMarshal(4, buf[offset:], x.RestoreMode) return buf } diff --git a/pkg/services/tree/service_grpc.pb.go b/pkg/services/tree/service_grpc.pb.go index 4c293a4c03..63f96e11a5 100644 --- a/pkg/services/tree/service_grpc.pb.go +++ b/pkg/services/tree/service_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.4.0 +// - protoc-gen-go-grpc v1.3.0 // - protoc v4.25.0 // source: pkg/services/tree/service.proto @@ -18,8 +18,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.62.0 or later. -const _ = grpc.SupportPackageIsVersion8 +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 const ( TreeService_Add_FullMethodName = "/tree.TreeService/Add" @@ -70,9 +70,8 @@ func NewTreeServiceClient(cc grpc.ClientConnInterface) TreeServiceClient { } func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grpc.CallOption) (*AddResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AddResponse) - err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, TreeService_Add_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -80,9 +79,8 @@ func (c *treeServiceClient) Add(ctx context.Context, in *AddRequest, opts ...grp } func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, opts ...grpc.CallOption) (*AddByPathResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(AddByPathResponse) - err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, TreeService_AddByPath_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -90,9 +88,8 @@ func (c *treeServiceClient) AddByPath(ctx context.Context, in *AddByPathRequest, } func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts ...grpc.CallOption) (*RemoveResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(RemoveResponse) - err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, TreeService_Remove_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -100,9 +97,8 @@ func (c *treeServiceClient) Remove(ctx context.Context, in *RemoveRequest, opts } func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...grpc.CallOption) (*MoveResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(MoveResponse) - err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, TreeService_Move_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -110,9 +106,8 @@ func (c *treeServiceClient) Move(ctx context.Context, in *MoveRequest, opts ...g } func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPathRequest, opts ...grpc.CallOption) (*GetNodeByPathResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetNodeByPathResponse) - err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, TreeService_GetNodeByPath_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -120,12 +115,11 @@ func (c *treeServiceClient) GetNodeByPath(ctx context.Context, in *GetNodeByPath } func (c *treeServiceClient) GetSubTree(ctx context.Context, in *GetSubTreeRequest, opts ...grpc.CallOption) (TreeService_GetSubTreeClient, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, cOpts...) + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[0], TreeService_GetSubTree_FullMethodName, opts...) if err != nil { return nil, err } - x := &treeServiceGetSubTreeClient{ClientStream: stream} + x := &treeServiceGetSubTreeClient{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -153,9 +147,8 @@ func (x *treeServiceGetSubTreeClient) Recv() (*GetSubTreeResponse, error) { } func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, opts ...grpc.CallOption) (*TreeListResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(TreeListResponse) - err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, TreeService_TreeList_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -163,9 +156,8 @@ func (c *treeServiceClient) TreeList(ctx context.Context, in *TreeListRequest, o } func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts ...grpc.CallOption) (*ApplyResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ApplyResponse) - err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, TreeService_Apply_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -173,12 +165,11 @@ func (c *treeServiceClient) Apply(ctx context.Context, in *ApplyRequest, opts .. } func (c *treeServiceClient) GetOpLog(ctx context.Context, in *GetOpLogRequest, opts ...grpc.CallOption) (TreeService_GetOpLogClient, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, cOpts...) + stream, err := c.cc.NewStream(ctx, &TreeService_ServiceDesc.Streams[1], TreeService_GetOpLog_FullMethodName, opts...) if err != nil { return nil, err } - x := &treeServiceGetOpLogClient{ClientStream: stream} + x := &treeServiceGetOpLogClient{stream} if err := x.ClientStream.SendMsg(in); err != nil { return nil, err } @@ -206,9 +197,8 @@ func (x *treeServiceGetOpLogClient) Recv() (*GetOpLogResponse, error) { } func (c *treeServiceClient) Healthcheck(ctx context.Context, in *HealthcheckRequest, opts ...grpc.CallOption) (*HealthcheckResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(HealthcheckResponse) - err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, cOpts...) + err := c.cc.Invoke(ctx, TreeService_Healthcheck_FullMethodName, in, out, opts...) if err != nil { return nil, err } @@ -383,7 +373,7 @@ func _TreeService_GetSubTree_Handler(srv interface{}, stream grpc.ServerStream) if err := stream.RecvMsg(m); err != nil { return err } - return srv.(TreeServiceServer).GetSubTree(m, &treeServiceGetSubTreeServer{ServerStream: stream}) + return srv.(TreeServiceServer).GetSubTree(m, &treeServiceGetSubTreeServer{stream}) } type TreeService_GetSubTreeServer interface { @@ -440,7 +430,7 @@ func _TreeService_GetOpLog_Handler(srv interface{}, stream grpc.ServerStream) er if err := stream.RecvMsg(m); err != nil { return err } - return srv.(TreeServiceServer).GetOpLog(m, &treeServiceGetOpLogServer{ServerStream: stream}) + return srv.(TreeServiceServer).GetOpLog(m, &treeServiceGetOpLogServer{stream}) } type TreeService_GetOpLogServer interface { From 36efccd86251a8445e6efe1550d342db10b0230a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 6 Aug 2024 15:45:53 +0300 Subject: [PATCH 0730/1413] [#1298] writecache: Add `shrink` flag for Seal command Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/writecache.go | 8 +- internal/logs/logs.go | 1 + pkg/local_object_storage/engine/writecache.go | 3 +- pkg/local_object_storage/shard/writecache.go | 3 +- pkg/local_object_storage/writecache/flush.go | 2 +- pkg/local_object_storage/writecache/mode.go | 55 ++- pkg/local_object_storage/writecache/seal.go | 4 +- .../writecache/writecache.go | 1 + .../control/server/seal_writecache.go | 1 + pkg/services/control/service.pb.go | 359 +++++++++--------- pkg/services/control/service.proto | 3 + pkg/services/control/service_frostfs.pb.go | 2 + 12 files changed, 255 insertions(+), 187 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/writecache.go b/cmd/frostfs-cli/modules/control/writecache.go index a665ccae87..b725d8471d 100644 --- a/cmd/frostfs-cli/modules/control/writecache.go +++ b/cmd/frostfs-cli/modules/control/writecache.go @@ -9,7 +9,10 @@ import ( "github.com/spf13/cobra" ) -const restoreModeFlag = "restore-mode" +const ( + restoreModeFlag = "restore-mode" + shrinkFlag = "shrink" +) var writecacheShardCmd = &cobra.Command{ Use: "writecache", @@ -29,11 +32,13 @@ func sealWritecache(cmd *cobra.Command, _ []string) { ignoreErrors, _ := cmd.Flags().GetBool(ignoreErrorsFlag) restoreMode, _ := cmd.Flags().GetBool(restoreModeFlag) + shrink, _ := cmd.Flags().GetBool(shrinkFlag) req := &control.SealWriteCacheRequest{Body: &control.SealWriteCacheRequest_Body{ Shard_ID: getShardIDList(cmd), IgnoreErrors: ignoreErrors, RestoreMode: restoreMode, + Shrink: shrink, }} signRequest(cmd, pk, req) @@ -73,6 +78,7 @@ func initControlShardsWritecacheCmd() { ff.Bool(shardAllFlag, false, "Process all shards") ff.Bool(ignoreErrorsFlag, true, "Skip invalid/unreadable objects") ff.Bool(restoreModeFlag, false, "Restore writecache's mode after sealing") + ff.Bool(shrinkFlag, false, "Shrink writecache's internal storage") sealWritecacheShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag) } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 67f173f29f..ebb822e1ce 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -539,4 +539,5 @@ const ( PolicerCouldNotGetChunk = "could not get EC chunk" PolicerCouldNotGetChunks = "could not get EC chunks" AuditEventLogRecord = "audit event log record" + WritecacheShrinkSkippedNotEmpty = "writecache shrink skipped: database is not empty" ) diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 8f37d78609..2c5e8cc3a8 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -71,6 +71,7 @@ type SealWriteCachePrm struct { ShardIDs []*shard.ID IgnoreErrors bool RestoreMode bool + Shrink bool } type ShardSealResult struct { @@ -116,7 +117,7 @@ func (e *StorageEngine) SealWriteCache(ctx context.Context, prm SealWriteCachePr return nil } - err := sh.SealWriteCache(egCtx, shard.SealWriteCachePrm{IgnoreErrors: prm.IgnoreErrors, RestoreMode: prm.RestoreMode}) + err := sh.SealWriteCache(egCtx, shard.SealWriteCachePrm{IgnoreErrors: prm.IgnoreErrors, RestoreMode: prm.RestoreMode, Shrink: prm.Shrink}) resGuard.Lock() defer resGuard.Unlock() diff --git a/pkg/local_object_storage/shard/writecache.go b/pkg/local_object_storage/shard/writecache.go index 9edad71705..c297109305 100644 --- a/pkg/local_object_storage/shard/writecache.go +++ b/pkg/local_object_storage/shard/writecache.go @@ -61,6 +61,7 @@ func (s *Shard) FlushWriteCache(ctx context.Context, p FlushWriteCachePrm) error type SealWriteCachePrm struct { IgnoreErrors bool RestoreMode bool + Shrink bool } // SealWriteCache flushes all data from the write-cache and moves it to degraded read only mode. @@ -87,5 +88,5 @@ func (s *Shard) SealWriteCache(ctx context.Context, p SealWriteCachePrm) error { return ErrDegradedMode } - return s.writeCache.Seal(ctx, writecache.SealPrm{IgnoreErrors: p.IgnoreErrors, RestoreMode: p.RestoreMode}) + return s.writeCache.Seal(ctx, writecache.SealPrm{IgnoreErrors: p.IgnoreErrors, RestoreMode: p.RestoreMode, Shrink: p.Shrink}) } diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index da7feda9a5..e34f5a76b3 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -291,7 +291,7 @@ func (c *cache) Flush(ctx context.Context, ignoreErrors, seal bool) error { if seal { m := c.mode | mode.ReadOnly - if err := c.setMode(ctx, m, ignoreErrors); err != nil { + if err := c.setMode(ctx, m, setModePrm{ignoreErrors: ignoreErrors}); err != nil { return err } c.metrics.SetMode(mode.ConvertToComponentModeDegraded(m)) diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index 4172cfbc88..44da9b36e1 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -2,16 +2,25 @@ package writecache import ( "context" + "errors" "fmt" + "os" + "path/filepath" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) +type setModePrm struct { + ignoreErrors bool + shrink bool +} + // SetMode sets write-cache mode of operation. // When shard is put in read-only mode all objects in memory are flushed to disk // and all background jobs are suspended. @@ -25,7 +34,7 @@ func (c *cache) SetMode(m mode.Mode) error { c.modeMtx.Lock() defer c.modeMtx.Unlock() - err := c.setMode(ctx, m, true) + err := c.setMode(ctx, m, setModePrm{ignoreErrors: true}) if err == nil { c.metrics.SetMode(mode.ConvertToComponentModeDegraded(m)) } @@ -33,21 +42,19 @@ func (c *cache) SetMode(m mode.Mode) error { } // setMode applies new mode. Must be called with cache.modeMtx lock taken. -func (c *cache) setMode(ctx context.Context, m mode.Mode, ignoreErrors bool) error { +func (c *cache) setMode(ctx context.Context, m mode.Mode, prm setModePrm) error { var err error turnOffMeta := m.NoMetabase() if turnOffMeta && !c.mode.NoMetabase() { - err = c.flush(ctx, ignoreErrors) + err = c.flush(ctx, prm.ignoreErrors) if err != nil { return err } } - if c.db != nil { - if err = c.db.Close(); err != nil { - return fmt.Errorf("can't close write-cache database: %w", err) - } + if err := c.closeDB(prm.shrink); err != nil { + return err } // Suspend producers to ensure there are channel send operations in fly. @@ -71,6 +78,40 @@ func (c *cache) setMode(ctx context.Context, m mode.Mode, ignoreErrors bool) err return nil } +func (c *cache) closeDB(shrink bool) error { + if c.db == nil { + return nil + } + if !shrink { + if err := c.db.Close(); err != nil { + return fmt.Errorf("can't close write-cache database: %w", err) + } + return nil + } + + var empty bool + err := c.db.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(defaultBucket) + empty = b == nil || b.Stats().KeyN == 0 + return nil + }) + if err != nil && !errors.Is(err, bbolt.ErrDatabaseNotOpen) { + return fmt.Errorf("failed to check DB items: %w", err) + } + if err := c.db.Close(); err != nil { + return fmt.Errorf("can't close write-cache database: %w", err) + } + if empty { + err := os.Remove(filepath.Join(c.path, dbName)) + if err != nil && !os.IsNotExist(err) { + return fmt.Errorf("failed to remove DB file: %w", err) + } + } else { + c.log.Info(logs.WritecacheShrinkSkippedNotEmpty) + } + return nil +} + // readOnly returns true if current mode is read-only. // `c.modeMtx` must be taken. func (c *cache) readOnly() bool { diff --git a/pkg/local_object_storage/writecache/seal.go b/pkg/local_object_storage/writecache/seal.go index 22b4e0988c..fa224f5e0c 100644 --- a/pkg/local_object_storage/writecache/seal.go +++ b/pkg/local_object_storage/writecache/seal.go @@ -22,13 +22,13 @@ func (c *cache) Seal(ctx context.Context, prm SealPrm) error { sourceMode := c.mode // flush will be done by setMode - err := c.setMode(ctx, mode.DegradedReadOnly, prm.IgnoreErrors) + err := c.setMode(ctx, mode.DegradedReadOnly, setModePrm{ignoreErrors: prm.IgnoreErrors, shrink: prm.Shrink}) if err != nil { return err } c.metrics.SetMode(mode.ComponentDisabled) if prm.RestoreMode { - err = c.setMode(ctx, sourceMode, prm.IgnoreErrors) + err = c.setMode(ctx, sourceMode, setModePrm{ignoreErrors: prm.IgnoreErrors}) if err == nil { c.metrics.SetMode(mode.ConvertToComponentMode(sourceMode)) } diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 7085a57b2a..a973df604e 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -23,6 +23,7 @@ type Info struct { type SealPrm struct { IgnoreErrors bool RestoreMode bool + Shrink bool } // Cache represents write-cache for objects. diff --git a/pkg/services/control/server/seal_writecache.go b/pkg/services/control/server/seal_writecache.go index b663cfc815..697b91918f 100644 --- a/pkg/services/control/server/seal_writecache.go +++ b/pkg/services/control/server/seal_writecache.go @@ -20,6 +20,7 @@ func (s *Server) SealWriteCache(ctx context.Context, req *control.SealWriteCache ShardIDs: s.getShardIDList(req.GetBody().GetShard_ID()), IgnoreErrors: req.GetBody().GetIgnoreErrors(), RestoreMode: req.GetBody().GetRestoreMode(), + Shrink: req.GetBody().GetShrink(), } res, err := s.s.SealWriteCache(ctx, prm) diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index 895b743684..ac512f1a55 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -4729,6 +4729,8 @@ type SealWriteCacheRequest_Body struct { IgnoreErrors bool `protobuf:"varint,2,opt,name=ignore_errors,json=ignoreErrors,proto3" json:"ignore_errors,omitempty"` // If true, then writecache will be sealed, but mode will be restored to the current one. RestoreMode bool `protobuf:"varint,4,opt,name=restore_mode,json=restoreMode,proto3" json:"restore_mode,omitempty"` + // If true, then writecache will shrink internal storage. + Shrink bool `protobuf:"varint,5,opt,name=shrink,proto3" json:"shrink,omitempty"` } func (x *SealWriteCacheRequest_Body) Reset() { @@ -4784,6 +4786,13 @@ func (x *SealWriteCacheRequest_Body) GetRestoreMode() bool { return false } +func (x *SealWriteCacheRequest_Body) GetShrink() bool { + if x != nil { + return x.Shrink + } + return false +} + type SealWriteCacheResponse_Body struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -5491,7 +5500,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xed, 0x01, 0x0a, 0x15, + 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x86, 0x02, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, @@ -5500,184 +5509,186 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x69, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, - 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, - 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xa9, 0x02, 0x0a, 0x16, + 0x1a, 0x81, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, + 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0b, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x73, 0x68, 0x72, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x68, + 0x72, 0x69, 0x6e, 0x6b, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, + 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, + 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, + 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, + 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, - 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, - 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, - 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, - 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, - 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0x8b, 0x10, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, - 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, - 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, - 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, - 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, + 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, + 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, + 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, + 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, + 0x8b, 0x10, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, + 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, + 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, + 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, + 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, + 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, + 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, + 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, + 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, - 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, - 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, - 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, + 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, + 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, + 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, + 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, - 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, - 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, + 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, - 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, - 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, - 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, - 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, + 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, + 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, + 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, + 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, + 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, + 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, + 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, + 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, + 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, + 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, + 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, + 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index a10410025a..486f30a936 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -658,6 +658,9 @@ message SealWriteCacheRequest { // If true, then writecache will be sealed, but mode will be restored to the current one. bool restore_mode = 4; + + // If true, then writecache will shrink internal storage. + bool shrink = 5; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index b6b064973d..417d25c05e 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -3423,6 +3423,7 @@ func (x *SealWriteCacheRequest_Body) StableSize() (size int) { size += proto.RepeatedBytesSize(1, x.Shard_ID) size += proto.BoolSize(2, x.IgnoreErrors) size += proto.BoolSize(4, x.RestoreMode) + size += proto.BoolSize(5, x.Shrink) return size } @@ -3445,6 +3446,7 @@ func (x *SealWriteCacheRequest_Body) StableMarshal(buf []byte) []byte { offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) offset += proto.BoolMarshal(2, buf[offset:], x.IgnoreErrors) offset += proto.BoolMarshal(4, buf[offset:], x.RestoreMode) + offset += proto.BoolMarshal(5, buf[offset:], x.Shrink) return buf } From 08b1f18bca97c100831b8ded4d9e6633a5aae138 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 6 Aug 2024 15:09:12 +0300 Subject: [PATCH 0731/1413] [#1296] writecache: Add count limit Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 +++ cmd/frostfs-node/config/engine/config_test.go | 3 +++ .../config/engine/shard/writecache/config.go | 19 ++++++++++++++++++ config/example/node.env | 1 + config/example/node.json | 3 ++- config/example/node.yaml | 1 + docs/storage-node-configuration.md | 19 +++++++++--------- .../writecache/options.go | 10 ++++++++++ pkg/local_object_storage/writecache/put.go | 6 ++---- pkg/local_object_storage/writecache/state.go | 20 +++++++++++++------ 10 files changed, 65 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 5b91e78191..a3dd806845 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -152,6 +152,7 @@ type shardCfg struct { maxObjSize uint64 flushWorkerCount int sizeLimit uint64 + countLimit uint64 noSync bool } @@ -275,6 +276,7 @@ func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, wc.smallObjectSize = writeCacheCfg.SmallObjectSize() wc.flushWorkerCount = writeCacheCfg.WorkerCount() wc.sizeLimit = writeCacheCfg.SizeLimit() + wc.countLimit = writeCacheCfg.CountLimit() wc.noSync = writeCacheCfg.NoSync() } } @@ -867,6 +869,7 @@ func (c *cfg) getWriteCacheOpts(shCfg shardCfg) []writecache.Option { writecache.WithSmallObjectSize(wcRead.smallObjectSize), writecache.WithFlushWorkersCount(wcRead.flushWorkerCount), writecache.WithMaxCacheSize(wcRead.sizeLimit), + writecache.WithMaxCacheCount(wcRead.countLimit), writecache.WithNoSync(wcRead.noSync), writecache.WithLogger(c.log), ) diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 7473afefb4..da4eeabfd5 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -12,6 +12,7 @@ import ( fstreeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/fstree" gcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/gc" piloramaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/pilorama" + writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/writecache" configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" @@ -78,6 +79,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 134217728, wc.MaxObjectSize()) require.EqualValues(t, 30, wc.WorkerCount()) require.EqualValues(t, 3221225472, wc.SizeLimit()) + require.EqualValues(t, 49, wc.CountLimit()) require.Equal(t, "tmp/0/meta", meta.Path()) require.Equal(t, fs.FileMode(0o644), meta.BoltDB().Perm()) @@ -133,6 +135,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 134217728, wc.MaxObjectSize()) require.EqualValues(t, 30, wc.WorkerCount()) require.EqualValues(t, 4294967296, wc.SizeLimit()) + require.EqualValues(t, writecacheconfig.CountLimitDefault, wc.CountLimit()) require.Equal(t, "tmp/1/meta", meta.Path()) require.Equal(t, fs.FileMode(0o644), meta.BoltDB().Perm()) diff --git a/cmd/frostfs-node/config/engine/shard/writecache/config.go b/cmd/frostfs-node/config/engine/shard/writecache/config.go index 5e31e04ad9..bfe8144dfb 100644 --- a/cmd/frostfs-node/config/engine/shard/writecache/config.go +++ b/cmd/frostfs-node/config/engine/shard/writecache/config.go @@ -21,6 +21,9 @@ const ( // SizeLimitDefault is a default write-cache size limit. SizeLimitDefault = 1 << 30 + + // CountLimitDefault is a default write-cache count limit. + CountLimitDefault = 0 ) // From wraps config section into Config. @@ -115,6 +118,22 @@ func (x *Config) SizeLimit() uint64 { return SizeLimitDefault } +// CountLimit returns the value of "max_object_count" config parameter. +// +// Returns CountLimitDefault if the value is not a positive number. +func (x *Config) CountLimit() uint64 { + c := config.SizeInBytesSafe( + (*config.Config)(x), + "max_object_count", + ) + + if c > 0 { + return c + } + + return CountLimitDefault +} + // NoSync returns the value of "no_sync" config parameter. // // Returns false if the value is not a boolean. diff --git a/config/example/node.env b/config/example/node.env index 00190eb39f..fc42cc3bfe 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -105,6 +105,7 @@ FROSTFS_STORAGE_SHARD_0_WRITECACHE_SMALL_OBJECT_SIZE=16384 FROSTFS_STORAGE_SHARD_0_WRITECACHE_MAX_OBJECT_SIZE=134217728 FROSTFS_STORAGE_SHARD_0_WRITECACHE_FLUSH_WORKER_COUNT=30 FROSTFS_STORAGE_SHARD_0_WRITECACHE_CAPACITY=3221225472 +FROSTFS_STORAGE_SHARD_0_WRITECACHE_MAX_OBJECT_COUNT=49 ### Metabase config FROSTFS_STORAGE_SHARD_0_METABASE_PATH=tmp/0/meta FROSTFS_STORAGE_SHARD_0_METABASE_PERM=0644 diff --git a/config/example/node.json b/config/example/node.json index 9051d2bb7c..9aa0dac539 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -148,7 +148,8 @@ "small_object_size": 16384, "max_object_size": 134217728, "flush_worker_count": 30, - "capacity": 3221225472 + "capacity": 3221225472, + "max_object_count": 49 }, "metabase": { "path": "tmp/0/meta", diff --git a/config/example/node.yaml b/config/example/node.yaml index bcc8552b30..2e6affae9f 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -171,6 +171,7 @@ storage: no_sync: true path: tmp/0/cache # write-cache root directory capacity: 3221225472 # approximate write-cache total size, bytes + max_object_count: 49 metabase: path: tmp/0/meta # metabase path diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 4a6e5ba6d9..424172ff5a 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -292,15 +292,16 @@ writecache: flush_worker_count: 30 ``` -| Parameter | Type | Default value | Description | -|----------------------|------------|---------------|----------------------------------------------------------------------------------------------------------------------| -| `path` | `string` | | Path to the metabase file. | -| `capacity` | `size` | unrestricted | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | -| `small_object_size` | `size` | `32K` | Maximum object size for "small" objects. This objects are stored in a key-value database instead of a file-system. | -| `max_object_size` | `size` | `64M` | Maximum object size allowed to be stored in the writecache. | -| `flush_worker_count` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | -| `max_batch_size` | `int` | `1000` | Maximum amount of small object `PUT` operations to perform in a single transaction. | -| `max_batch_delay` | `duration` | `10ms` | Maximum delay before a batch starts. | +| Parameter | Type | Default value | Description | +|----------------------|------------|---------------|-------------------------------------------------------------------------------------------------------------------------------| +| `path` | `string` | | Path to the metabase file. | +| `capacity` | `size` | `1G` | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | +| `max_object_count` | `int` | unrestricted | Approximate maximum objects count in the writecache. If the writecache is full, objects are written to the blobstor directly. | +| `small_object_size` | `size` | `32K` | Maximum object size for "small" objects. This objects are stored in a key-value database instead of a file-system. | +| `max_object_size` | `size` | `64M` | Maximum object size allowed to be stored in the writecache. | +| `flush_worker_count` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | +| `max_batch_size` | `int` | `1000` | Maximum amount of small object `PUT` operations to perform in a single transaction. | +| `max_batch_delay` | `duration` | `10ms` | Maximum delay before a batch starts. | # `node` section diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index c8eb1bc45c..66cd79bea3 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -29,6 +29,9 @@ type options struct { // maxCacheSize is the maximum total size of all objects saved in cache (DB + FS). // 1 GiB by default. maxCacheSize uint64 + // maxCacheCount is the maximum total count of all object saved in cache. + // 0 (no limit) by default. + maxCacheCount uint64 // objCounters contains atomic counters for the number of objects stored in cache. objCounters counters // maxBatchSize is the maximum batch size for the small object database. @@ -108,6 +111,13 @@ func WithMaxCacheSize(sz uint64) Option { } } +// WithMaxCacheCount sets maximum write-cache objects count. +func WithMaxCacheCount(v uint64) Option { + return func(o *options) { + o.maxCacheCount = v + } +} + // WithMaxBatchSize sets max batch size for the small object database. func WithMaxBatchSize(sz int) Option { return func(o *options) { diff --git a/pkg/local_object_storage/writecache/put.go b/pkg/local_object_storage/writecache/put.go index 0e419f95b0..150399de80 100644 --- a/pkg/local_object_storage/writecache/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -76,8 +76,7 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro // putSmall persists small objects to the write-cache database and // pushes the to the flush workers queue. func (c *cache) putSmall(obj objectInfo) error { - cacheSize := c.estimateCacheSize() - if c.maxCacheSize < c.incSizeDB(cacheSize) { + if !c.hasEnoughSpaceDB() { return ErrOutOfSpace } @@ -107,8 +106,7 @@ func (c *cache) putSmall(obj objectInfo) error { // putBig writes object to FSTree and pushes it to the flush workers queue. func (c *cache) putBig(ctx context.Context, addr string, prm common.PutPrm) error { - cacheSz := c.estimateCacheSize() - if c.maxCacheSize < c.incSizeFS(cacheSz) { + if !c.hasEnoughSpaceFS() { return ErrOutOfSpace } diff --git a/pkg/local_object_storage/writecache/state.go b/pkg/local_object_storage/writecache/state.go index bc75aaf275..d03f4a63e3 100644 --- a/pkg/local_object_storage/writecache/state.go +++ b/pkg/local_object_storage/writecache/state.go @@ -9,7 +9,7 @@ import ( "go.etcd.io/bbolt" ) -func (c *cache) estimateCacheSize() uint64 { +func (c *cache) estimateCacheSize() (uint64, uint64) { dbCount := c.objCounters.DB() fsCount := c.objCounters.FS() if fsCount > 0 { @@ -19,15 +19,23 @@ func (c *cache) estimateCacheSize() uint64 { fsSize := fsCount * c.maxObjectSize c.metrics.SetEstimateSize(dbSize, fsSize) c.metrics.SetActualCounters(dbCount, fsCount) - return dbSize + fsSize + return dbCount + fsCount, dbSize + fsSize } -func (c *cache) incSizeDB(sz uint64) uint64 { - return sz + c.smallObjectSize +func (c *cache) hasEnoughSpaceDB() bool { + return c.hasEnoughSpace(c.smallObjectSize) } -func (c *cache) incSizeFS(sz uint64) uint64 { - return sz + c.maxObjectSize +func (c *cache) hasEnoughSpaceFS() bool { + return c.hasEnoughSpace(c.maxObjectSize) +} + +func (c *cache) hasEnoughSpace(objectSize uint64) bool { + count, size := c.estimateCacheSize() + if c.maxCacheCount > 0 && count+1 > c.maxCacheCount { + return false + } + return c.maxCacheSize >= size+objectSize } var _ fstree.FileCounter = &counters{} From c985b1198f8ed2ec1ecb6e239503ff4ad3f59439 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 9 Aug 2024 10:38:45 +0300 Subject: [PATCH 0732/1413] [#1302] putSvc: Override SuccessAfter for non-regular objects in EC containers Signed-off-by: Dmitrii Stepanov --- pkg/services/object/put/single.go | 4 ++++ pkg/services/object/put/streamer.go | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 6d2f3dba8b..9fa8ddb67c 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -19,6 +19,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -229,6 +230,9 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb if len(copiesNumber) > 0 && !result.isEC { result.placementOptions = append(result.placementOptions, placement.WithCopyNumbers(copiesNumber)) } + if container.IsECContainer(cnrInfo.Value) && !object.IsECSupported(obj) && !localOnly { + result.placementOptions = append(result.placementOptions, placement.SuccessAfter(uint32(policy.ECParityCount(cnrInfo.Value.PlacementPolicy())+1))) + } result.placementOptions = append(result.placementOptions, placement.ForContainer(cnrInfo.Value)) objID, ok := obj.ID() diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 14dae38d58..4e655ed541 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" pkgutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" @@ -212,10 +213,10 @@ func (p *Streamer) newObjectWriter(prm *PutInitPrm) transformer.ObjectWriter { if container.IsECContainer(prm.cnr) && object.IsECSupported(prm.hdr) { return p.newECWriter(prm) } - return p.newDefaultObjectWriter(prm) + return p.newDefaultObjectWriter(prm, false) } -func (p *Streamer) newDefaultObjectWriter(prm *PutInitPrm) transformer.ObjectWriter { +func (p *Streamer) newDefaultObjectWriter(prm *PutInitPrm, forECPlacement bool) transformer.ObjectWriter { var relay func(context.Context, nodeDesc) error if p.relay != nil { relay = func(ctx context.Context, node nodeDesc) error { @@ -232,9 +233,16 @@ func (p *Streamer) newDefaultObjectWriter(prm *PutInitPrm) transformer.ObjectWri } } + traverseOpts := prm.traverseOpts + if forECPlacement && !prm.common.LocalOnly() { + // save non-regular and linking object to EC container. + // EC 2.1 -> REP 2, EC 2.2 -> REP 3 etc. + traverseOpts = append(traverseOpts, placement.SuccessAfter(uint32(policy.ECParityCount(prm.cnr.PlacementPolicy())+1))) + } + return &distributedTarget{ cfg: p.cfg, - placementOpts: prm.traverseOpts, + placementOpts: traverseOpts, nodeTargetInitializer: func(node nodeDesc) preparedObjectTarget { if node.local { return localTarget{ @@ -266,7 +274,7 @@ func (p *Streamer) newECWriter(prm *PutInitPrm) transformer.ObjectWriter { commonPrm: prm.common, relay: p.relay, }, - repWriter: p.newDefaultObjectWriter(prm), + repWriter: p.newDefaultObjectWriter(prm, true), } } From fa82854af4c0ec18a058eabede3da35715061125 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 8 Aug 2024 13:15:22 +0300 Subject: [PATCH 0733/1413] [#1302] writecache: Add put->flush->put benchmark Signed-off-by: Dmitrii Stepanov --- .../writecache/benchmark/writecache_test.go | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index c1c0e88b3c..4f4398452e 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -2,6 +2,7 @@ package benchmark import ( "context" + "fmt" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" @@ -27,6 +28,24 @@ func BenchmarkWritecachePar(b *testing.B) { }) } +func BenchmarkWriteAfterDelete(b *testing.B) { + const payloadSize = 32 << 10 + const parallel = 25 + + cache := newCache(b) + benchmarkPutPrepare(b, cache) + b.Run(fmt.Sprintf("%dB_before", payloadSize), func(b *testing.B) { + b.SetParallelism(parallel) + benchmarkRunPar(b, cache, payloadSize) + }) + require.NoError(b, cache.Flush(context.Background(), false, false)) + b.Run(fmt.Sprintf("%dB_after", payloadSize), func(b *testing.B) { + b.SetParallelism(parallel) + benchmarkRunPar(b, cache, payloadSize) + }) + require.NoError(b, cache.Close()) +} + func benchmarkPutSeq(b *testing.B, cache writecache.Cache, size uint64) { benchmarkPutPrepare(b, cache) defer func() { require.NoError(b, cache.Close()) }() @@ -54,6 +73,10 @@ func benchmarkPutPar(b *testing.B, cache writecache.Cache, size uint64) { benchmarkPutPrepare(b, cache) defer func() { require.NoError(b, cache.Close()) }() + benchmarkRunPar(b, cache, size) +} + +func benchmarkRunPar(b *testing.B, cache writecache.Cache, size uint64) { ctx := context.Background() b.ResetTimer() From 68029d756e59d036b11b95153d70e64588ee720e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 8 Aug 2024 13:32:18 +0300 Subject: [PATCH 0734/1413] [#1302] writecache: Allow to specify custom page size Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-lens/internal/writecache/inspect.go | 2 +- cmd/frostfs-lens/internal/writecache/list.go | 2 +- cmd/frostfs-node/config.go | 3 +++ cmd/frostfs-node/config/engine/config_test.go | 2 ++ cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go | 11 +++++++++++ config/example/node.env | 1 + config/example/node.json | 1 + config/example/node.yaml | 1 + docs/storage-node-configuration.md | 2 ++ pkg/local_object_storage/writecache/options.go | 9 +++++++++ pkg/local_object_storage/writecache/storage.go | 2 +- pkg/local_object_storage/writecache/util.go | 3 ++- 12 files changed, 35 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-lens/internal/writecache/inspect.go b/cmd/frostfs-lens/internal/writecache/inspect.go index afc986c8b9..63c669a355 100644 --- a/cmd/frostfs-lens/internal/writecache/inspect.go +++ b/cmd/frostfs-lens/internal/writecache/inspect.go @@ -25,7 +25,7 @@ func init() { func inspectFunc(cmd *cobra.Command, _ []string) { var data []byte - db, err := writecache.OpenDB(vPath, true, os.OpenFile) + db, err := writecache.OpenDB(vPath, true, os.OpenFile, 0) common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) defer db.Close() diff --git a/cmd/frostfs-lens/internal/writecache/list.go b/cmd/frostfs-lens/internal/writecache/list.go index bcbae0ec9b..9c8fa6138a 100644 --- a/cmd/frostfs-lens/internal/writecache/list.go +++ b/cmd/frostfs-lens/internal/writecache/list.go @@ -31,7 +31,7 @@ func listFunc(cmd *cobra.Command, _ []string) { return err } - db, err := writecache.OpenDB(vPath, true, os.OpenFile) + db, err := writecache.OpenDB(vPath, true, os.OpenFile, 0) common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) defer db.Close() diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index a3dd806845..1af27d7330 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -154,6 +154,7 @@ type shardCfg struct { sizeLimit uint64 countLimit uint64 noSync bool + pageSize int } piloramaCfg struct { @@ -272,6 +273,7 @@ func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, wc.path = writeCacheCfg.Path() wc.maxBatchSize = writeCacheCfg.BoltDB().MaxBatchSize() wc.maxBatchDelay = writeCacheCfg.BoltDB().MaxBatchDelay() + wc.pageSize = writeCacheCfg.BoltDB().PageSize() wc.maxObjSize = writeCacheCfg.MaxObjectSize() wc.smallObjectSize = writeCacheCfg.SmallObjectSize() wc.flushWorkerCount = writeCacheCfg.WorkerCount() @@ -865,6 +867,7 @@ func (c *cfg) getWriteCacheOpts(shCfg shardCfg) []writecache.Option { writecache.WithPath(wcRead.path), writecache.WithMaxBatchSize(wcRead.maxBatchSize), writecache.WithMaxBatchDelay(wcRead.maxBatchDelay), + writecache.WithPageSize(wcRead.pageSize), writecache.WithMaxObjectSize(wcRead.maxObjSize), writecache.WithSmallObjectSize(wcRead.smallObjectSize), writecache.WithFlushWorkersCount(wcRead.flushWorkerCount), diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index da4eeabfd5..d53207ccc0 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -79,6 +79,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 134217728, wc.MaxObjectSize()) require.EqualValues(t, 30, wc.WorkerCount()) require.EqualValues(t, 3221225472, wc.SizeLimit()) + require.EqualValues(t, 4096, wc.BoltDB().PageSize()) require.EqualValues(t, 49, wc.CountLimit()) require.Equal(t, "tmp/0/meta", meta.Path()) @@ -135,6 +136,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 134217728, wc.MaxObjectSize()) require.EqualValues(t, 30, wc.WorkerCount()) require.EqualValues(t, 4294967296, wc.SizeLimit()) + require.EqualValues(t, 0, wc.BoltDB().PageSize()) require.EqualValues(t, writecacheconfig.CountLimitDefault, wc.CountLimit()) require.Equal(t, "tmp/1/meta", meta.Path()) diff --git a/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go b/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go index 9e334cd8f4..a51308b5ba 100644 --- a/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go +++ b/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go @@ -60,3 +60,14 @@ func (x *Config) MaxBatchSize() int { func (x *Config) NoSync() bool { return config.BoolSafe((*config.Config)(x), "no_sync") } + +// PageSize returns the value of "page_size" config parameter. +// +// Returns 0 if the value is not a positive number. +func (x *Config) PageSize() int { + s := int(config.SizeInBytesSafe((*config.Config)(x), "page_size")) + if s < 0 { + s = 0 + } + return s +} diff --git a/config/example/node.env b/config/example/node.env index fc42cc3bfe..b39423ffb8 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -105,6 +105,7 @@ FROSTFS_STORAGE_SHARD_0_WRITECACHE_SMALL_OBJECT_SIZE=16384 FROSTFS_STORAGE_SHARD_0_WRITECACHE_MAX_OBJECT_SIZE=134217728 FROSTFS_STORAGE_SHARD_0_WRITECACHE_FLUSH_WORKER_COUNT=30 FROSTFS_STORAGE_SHARD_0_WRITECACHE_CAPACITY=3221225472 +FROSTFS_STORAGE_SHARD_0_WRITECACHE_PAGE_SIZE=4096 FROSTFS_STORAGE_SHARD_0_WRITECACHE_MAX_OBJECT_COUNT=49 ### Metabase config FROSTFS_STORAGE_SHARD_0_METABASE_PATH=tmp/0/meta diff --git a/config/example/node.json b/config/example/node.json index 9aa0dac539..fe2de0e018 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -149,6 +149,7 @@ "max_object_size": 134217728, "flush_worker_count": 30, "capacity": 3221225472, + "page_size": 4096, "max_object_count": 49 }, "metabase": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 2e6affae9f..cc339a427f 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -172,6 +172,7 @@ storage: path: tmp/0/cache # write-cache root directory capacity: 3221225472 # approximate write-cache total size, bytes max_object_count: 49 + page_size: 4k metabase: path: tmp/0/meta # metabase path diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 424172ff5a..5bf35cd657 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -290,6 +290,7 @@ writecache: small_object_size: 16384 max_object_size: 134217728 flush_worker_count: 30 + page_size: '4k' ``` | Parameter | Type | Default value | Description | @@ -302,6 +303,7 @@ writecache: | `flush_worker_count` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | | `max_batch_size` | `int` | `1000` | Maximum amount of small object `PUT` operations to perform in a single transaction. | | `max_batch_delay` | `duration` | `10ms` | Maximum delay before a batch starts. | +| `page_size` | `size` | `0` | Page size overrides the default OS page size for small objects storage. Does not affect the existing storage. | # `node` section diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index 66cd79bea3..980cf93037 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -48,6 +48,8 @@ type options struct { metrics Metrics // disableBackgroundFlush is for testing purposes only. disableBackgroundFlush bool + // pageSize is bbolt's page size config value + pageSize int } // WithLogger sets logger. @@ -173,3 +175,10 @@ func WithDisableBackgroundFlush() Option { o.disableBackgroundFlush = true } } + +// WithPageSize sets bbolt's page size. +func WithPageSize(s int) Option { + return func(o *options) { + o.pageSize = s + } +} diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index caf997af87..57021cc177 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -32,7 +32,7 @@ func (c *cache) openStore(mod mode.ComponentMode) error { return err } - c.db, err = OpenDB(c.path, mod.ReadOnly(), c.openFile) + c.db, err = OpenDB(c.path, mod.ReadOnly(), c.openFile, c.pageSize) if err != nil { return fmt.Errorf("could not open database: %w", err) } diff --git a/pkg/local_object_storage/writecache/util.go b/pkg/local_object_storage/writecache/util.go index 0ed4a954e1..ad3b443f33 100644 --- a/pkg/local_object_storage/writecache/util.go +++ b/pkg/local_object_storage/writecache/util.go @@ -10,11 +10,12 @@ import ( ) // OpenDB opens BoltDB instance for write-cache. Opens in read-only mode if ro is true. -func OpenDB(p string, ro bool, openFile func(string, int, fs.FileMode) (*os.File, error)) (*bbolt.DB, error) { +func OpenDB(p string, ro bool, openFile func(string, int, fs.FileMode) (*os.File, error), pageSize int) (*bbolt.DB, error) { return bbolt.Open(filepath.Join(p, dbName), os.ModePerm, &bbolt.Options{ NoFreelistSync: true, ReadOnly: ro, Timeout: 100 * time.Millisecond, OpenFile: openFile, + PageSize: pageSize, }) } From 93d63e1632f54869ca1c155cdd11d2c9966c3090 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 31 Jul 2024 16:30:07 +0300 Subject: [PATCH 0735/1413] [#1284] writecache: Allow to seal writecache async Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/writecache.go | 4 + internal/logs/logs.go | 3 + pkg/local_object_storage/engine/writecache.go | 3 +- pkg/local_object_storage/shard/control.go | 6 + pkg/local_object_storage/shard/shard.go | 6 +- pkg/local_object_storage/shard/writecache.go | 54 ++- .../control/server/seal_writecache.go | 1 + pkg/services/control/service.pb.go | 340 +++++++++--------- pkg/services/control/service.proto | 3 + pkg/services/control/service_frostfs.pb.go | 2 + 10 files changed, 252 insertions(+), 170 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/writecache.go b/cmd/frostfs-cli/modules/control/writecache.go index b725d8471d..ffe9009ab4 100644 --- a/cmd/frostfs-cli/modules/control/writecache.go +++ b/cmd/frostfs-cli/modules/control/writecache.go @@ -10,6 +10,7 @@ import ( ) const ( + asyncFlag = "async" restoreModeFlag = "restore-mode" shrinkFlag = "shrink" ) @@ -31,12 +32,14 @@ func sealWritecache(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) ignoreErrors, _ := cmd.Flags().GetBool(ignoreErrorsFlag) + async, _ := cmd.Flags().GetBool(asyncFlag) restoreMode, _ := cmd.Flags().GetBool(restoreModeFlag) shrink, _ := cmd.Flags().GetBool(shrinkFlag) req := &control.SealWriteCacheRequest{Body: &control.SealWriteCacheRequest_Body{ Shard_ID: getShardIDList(cmd), IgnoreErrors: ignoreErrors, + Async: async, RestoreMode: restoreMode, Shrink: shrink, }} @@ -77,6 +80,7 @@ func initControlShardsWritecacheCmd() { ff.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") ff.Bool(shardAllFlag, false, "Process all shards") ff.Bool(ignoreErrorsFlag, true, "Skip invalid/unreadable objects") + ff.Bool(asyncFlag, false, "Run operation in background") ff.Bool(restoreModeFlag, false, "Restore writecache's mode after sealing") ff.Bool(shrinkFlag, false, "Shrink writecache's internal storage") diff --git a/internal/logs/logs.go b/internal/logs/logs.go index ebb822e1ce..78bcd0c0ee 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -539,5 +539,8 @@ const ( PolicerCouldNotGetChunk = "could not get EC chunk" PolicerCouldNotGetChunks = "could not get EC chunks" AuditEventLogRecord = "audit event log record" + StartedWritecacheSealAsync = "started writecache seal async" + WritecacheSealCompletedAsync = "writecache seal completed successfully" + FailedToSealWritecacheAsync = "failed to seal writecache async" WritecacheShrinkSkippedNotEmpty = "writecache shrink skipped: database is not empty" ) diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 2c5e8cc3a8..3e8f387ef8 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -70,6 +70,7 @@ func (e *StorageEngine) FlushWriteCache(ctx context.Context, p FlushWriteCachePr type SealWriteCachePrm struct { ShardIDs []*shard.ID IgnoreErrors bool + Async bool RestoreMode bool Shrink bool } @@ -117,7 +118,7 @@ func (e *StorageEngine) SealWriteCache(ctx context.Context, prm SealWriteCachePr return nil } - err := sh.SealWriteCache(egCtx, shard.SealWriteCachePrm{IgnoreErrors: prm.IgnoreErrors, RestoreMode: prm.RestoreMode, Shrink: prm.Shrink}) + err := sh.SealWriteCache(egCtx, shard.SealWriteCachePrm{IgnoreErrors: prm.IgnoreErrors, Async: prm.Async, RestoreMode: prm.RestoreMode, Shrink: prm.Shrink}) resGuard.Lock() defer resGuard.Unlock() diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 90d7afdd4d..2107447020 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -178,6 +178,7 @@ func (s *Shard) Init(ctx context.Context) error { if !m.NoMetabase() { s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) } + s.writecacheSealCancel.Store(dummyCancel) return nil } @@ -350,6 +351,8 @@ func (s *Shard) Close() error { } if s.hasWriteCache() { + prev := s.writecacheSealCancel.Swap(notInitializedCancel) + prev.cancel() // no need to wait: writecache.Seal and writecache.Close lock the same mutex components = append(components, s.writeCache) } @@ -428,6 +431,9 @@ func (s *Shard) lockExclusive() func() { cancelGC := val.(context.CancelFunc) cancelGC() } + if c := s.writecacheSealCancel.Load(); c != nil { + c.cancel() + } s.m.Lock() s.setModeRequested.Store(false) return s.m.Unlock diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 94f22feb56..93f5354a7f 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -37,8 +37,9 @@ type Shard struct { rb *rebuilder - gcCancel atomic.Value - setModeRequested atomic.Bool + gcCancel atomic.Value + setModeRequested atomic.Bool + writecacheSealCancel atomic.Pointer[writecacheSealCanceler] } // Option represents Shard's constructor option. @@ -190,6 +191,7 @@ func New(opts ...Option) *Shard { } s.fillInfo() + s.writecacheSealCancel.Store(notInitializedCancel) return s } diff --git a/pkg/local_object_storage/shard/writecache.go b/pkg/local_object_storage/shard/writecache.go index c297109305..a6de07f033 100644 --- a/pkg/local_object_storage/shard/writecache.go +++ b/pkg/local_object_storage/shard/writecache.go @@ -4,12 +4,24 @@ import ( "context" "errors" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" + "go.uber.org/zap" ) +var ( + dummyCancel = &writecacheSealCanceler{cancel: func() {}} + notInitializedCancel = &writecacheSealCanceler{cancel: func() {}} + errWriteCacheSealing = errors.New("writecache is already sealing or shard is not initialized") +) + +type writecacheSealCanceler struct { + cancel context.CancelFunc +} + // FlushWriteCachePrm represents parameters of a `FlushWriteCache` operation. type FlushWriteCachePrm struct { ignoreErrors bool @@ -60,6 +72,7 @@ func (s *Shard) FlushWriteCache(ctx context.Context, p FlushWriteCachePrm) error type SealWriteCachePrm struct { IgnoreErrors bool + Async bool RestoreMode bool Shrink bool } @@ -78,15 +91,52 @@ func (s *Shard) SealWriteCache(ctx context.Context, p SealWriteCachePrm) error { return errWriteCacheDisabled } + if p.Async { + ctx = context.WithoutCancel(ctx) + } + ctx, cancel := context.WithCancel(ctx) + canceler := &writecacheSealCanceler{cancel: cancel} + if !s.writecacheSealCancel.CompareAndSwap(dummyCancel, canceler) { + return errWriteCacheSealing + } s.m.RLock() - defer s.m.RUnlock() + cleanup := func() { + s.m.RUnlock() + s.writecacheSealCancel.Store(dummyCancel) + } if s.info.Mode.ReadOnly() { + cleanup() return ErrReadOnlyMode } if s.info.Mode.NoMetabase() { + cleanup() return ErrDegradedMode } - return s.writeCache.Seal(ctx, writecache.SealPrm{IgnoreErrors: p.IgnoreErrors, RestoreMode: p.RestoreMode, Shrink: p.Shrink}) + if !p.Async { + defer cleanup() + } + prm := writecache.SealPrm{IgnoreErrors: p.IgnoreErrors, RestoreMode: p.RestoreMode, Shrink: p.Shrink} + if p.Async { + started := make(chan struct{}) + go func() { + close(started) + defer cleanup() + + s.log.Info(logs.StartedWritecacheSealAsync) + if err := s.writeCache.Seal(ctx, prm); err != nil { + s.log.Warn(logs.FailedToSealWritecacheAsync, zap.Error(err)) + return + } + s.log.Info(logs.WritecacheSealCompletedAsync) + }() + select { + case <-ctx.Done(): + return ctx.Err() + case <-started: + return nil + } + } + return s.writeCache.Seal(ctx, prm) } diff --git a/pkg/services/control/server/seal_writecache.go b/pkg/services/control/server/seal_writecache.go index 697b91918f..1737677b7d 100644 --- a/pkg/services/control/server/seal_writecache.go +++ b/pkg/services/control/server/seal_writecache.go @@ -19,6 +19,7 @@ func (s *Server) SealWriteCache(ctx context.Context, req *control.SealWriteCache prm := engine.SealWriteCachePrm{ ShardIDs: s.getShardIDList(req.GetBody().GetShard_ID()), IgnoreErrors: req.GetBody().GetIgnoreErrors(), + Async: req.GetBody().GetAsync(), RestoreMode: req.GetBody().GetRestoreMode(), Shrink: req.GetBody().GetShrink(), } diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go index ac512f1a55..e5a5ce24c1 100644 --- a/pkg/services/control/service.pb.go +++ b/pkg/services/control/service.pb.go @@ -4727,6 +4727,8 @@ type SealWriteCacheRequest_Body struct { Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` // Flag indicating whether object read errors should be ignored. IgnoreErrors bool `protobuf:"varint,2,opt,name=ignore_errors,json=ignoreErrors,proto3" json:"ignore_errors,omitempty"` + // Flag indicating whether writecache will be sealed async. + Async bool `protobuf:"varint,3,opt,name=async,proto3" json:"async,omitempty"` // If true, then writecache will be sealed, but mode will be restored to the current one. RestoreMode bool `protobuf:"varint,4,opt,name=restore_mode,json=restoreMode,proto3" json:"restore_mode,omitempty"` // If true, then writecache will shrink internal storage. @@ -4779,6 +4781,13 @@ func (x *SealWriteCacheRequest_Body) GetIgnoreErrors() bool { return false } +func (x *SealWriteCacheRequest_Body) GetAsync() bool { + if x != nil { + return x.Async + } + return false +} + func (x *SealWriteCacheRequest_Body) GetRestoreMode() bool { if x != nil { return x.RestoreMode @@ -5500,7 +5509,7 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x86, 0x02, 0x0a, 0x15, + 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x9c, 0x02, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, @@ -5509,186 +5518,187 @@ var file_pkg_services_control_service_proto_rawDesc = []byte{ 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x81, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, + 0x1a, 0x97, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, - 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, - 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0b, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x68, 0x72, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x68, - 0x72, 0x69, 0x6e, 0x6b, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, - 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, - 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, - 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x79, + 0x6e, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x12, + 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x6f, + 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x72, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x73, 0x68, 0x72, 0x69, 0x6e, 0x6b, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, + 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, + 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, + 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, + 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, + 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, + 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, - 0x8b, 0x10, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, - 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, - 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, - 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, + 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, + 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, + 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0x8b, 0x10, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, - 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, - 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, - 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, - 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, - 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, + 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, + 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, + 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, + 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, + 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, + 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, + 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, + 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, + 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, + 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, + 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, + 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, + 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, + 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, + 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, + 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, + 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, + 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, + 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, + 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, + 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, + 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, + 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, + 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, - 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, - 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, - 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, - 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, - 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, - 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, - 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, - 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, - 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, - 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, - 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, - 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, - 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, - 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, - 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, + 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, + 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, + 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, + 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, + 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, + 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, + 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, + 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, + 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 486f30a936..d6639cb489 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -656,6 +656,9 @@ message SealWriteCacheRequest { // Flag indicating whether object read errors should be ignored. bool ignore_errors = 2; + // Flag indicating whether writecache will be sealed async. + bool async = 3; + // If true, then writecache will be sealed, but mode will be restored to the current one. bool restore_mode = 4; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 417d25c05e..822244e77d 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -3422,6 +3422,7 @@ func (x *SealWriteCacheRequest_Body) StableSize() (size int) { } size += proto.RepeatedBytesSize(1, x.Shard_ID) size += proto.BoolSize(2, x.IgnoreErrors) + size += proto.BoolSize(3, x.Async) size += proto.BoolSize(4, x.RestoreMode) size += proto.BoolSize(5, x.Shrink) return size @@ -3445,6 +3446,7 @@ func (x *SealWriteCacheRequest_Body) StableMarshal(buf []byte) []byte { var offset int offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) offset += proto.BoolMarshal(2, buf[offset:], x.IgnoreErrors) + offset += proto.BoolMarshal(3, buf[offset:], x.Async) offset += proto.BoolMarshal(4, buf[offset:], x.RestoreMode) offset += proto.BoolMarshal(5, buf[offset:], x.Shrink) return buf From 80ce7c3a0095e707e44accf30be6bf7f61bfacc4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 31 Jul 2024 16:33:31 +0300 Subject: [PATCH 0736/1413] [#1284] shard: Resolve funlen linter Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/control.go | 71 +++++++++++++---------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 2107447020..936a506c09 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -99,12 +99,50 @@ func (x *metabaseSynchronizer) Init() error { // Init initializes all Shard's components. func (s *Shard) Init(ctx context.Context) error { + m := s.GetMode() + if err := s.initializeComponents(m); err != nil { + return err + } + + s.updateMetrics(ctx) + + s.gc = &gc{ + gcCfg: &s.gcCfg, + remover: s.removeGarbage, + stopChannel: make(chan struct{}), + eventChan: make(chan Event), + mEventHandler: map[eventType]*eventHandlers{ + eventNewEpoch: { + cancelFunc: func() {}, + handlers: []eventHandler{ + s.collectExpiredLocks, + s.collectExpiredObjects, + s.collectExpiredTombstones, + s.collectExpiredMetrics, + }, + }, + }, + } + if s.gc.metrics != nil { + s.gc.metrics.SetShardID(s.info.ID.String()) + } + + s.gc.init(ctx) + + s.rb = newRebuilder(s.rebuildLimiter) + if !m.NoMetabase() { + s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) + } + s.writecacheSealCancel.Store(dummyCancel) + return nil +} + +func (s *Shard) initializeComponents(m mode.Mode) error { type initializer interface { Init() error } var components []initializer - m := s.GetMode() if !m.NoMetabase() { var initMetabase initializer @@ -148,37 +186,6 @@ func (s *Shard) Init(ctx context.Context) error { return fmt.Errorf("could not initialize %T: %w", component, err) } } - - s.updateMetrics(ctx) - - s.gc = &gc{ - gcCfg: &s.gcCfg, - remover: s.removeGarbage, - stopChannel: make(chan struct{}), - eventChan: make(chan Event), - mEventHandler: map[eventType]*eventHandlers{ - eventNewEpoch: { - cancelFunc: func() {}, - handlers: []eventHandler{ - s.collectExpiredLocks, - s.collectExpiredObjects, - s.collectExpiredTombstones, - s.collectExpiredMetrics, - }, - }, - }, - } - if s.gc.metrics != nil { - s.gc.metrics.SetShardID(s.info.ID.String()) - } - - s.gc.init(ctx) - - s.rb = newRebuilder(s.rebuildLimiter) - if !m.NoMetabase() { - s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) - } - s.writecacheSealCancel.Store(dummyCancel) return nil } From d055168e2a9651c357e4358c1dcc392bb4ae4718 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Wed, 14 Aug 2024 13:47:50 +0300 Subject: [PATCH 0737/1413] [#1135] ir: Add healthstatus RECONFIGURING Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-ir/config.go | 6 ++++++ go.mod | 6 +++--- go.sum | 12 ++++++------ pkg/innerring/state.go | 12 ++++++++++++ pkg/services/control/ir/types.pb.go | 18 ++++++++++++------ pkg/services/control/ir/types.proto | 3 +++ 6 files changed, 42 insertions(+), 15 deletions(-) diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index 9551954774..4eaac845cd 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -7,6 +7,7 @@ import ( configViper "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/config" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" "github.com/spf13/viper" "go.uber.org/zap" ) @@ -81,6 +82,10 @@ func watchForSignal(cancel func()) { return case <-sighupCh: log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) + if !innerRing.CompareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { + log.Info(logs.FrostFSNodeSIGHUPSkip) + break + } err := reloadConfig() if err != nil { log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) @@ -92,6 +97,7 @@ func watchForSignal(cancel func()) { if err != nil { log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) } + innerRing.CompareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) } } diff --git a/go.mod b/go.mod index 09a0985020..196b4d4639 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect @@ -120,8 +120,8 @@ require ( golang.org/x/crypto v0.21.0 // indirect golang.org/x/net v0.23.0 // indirect golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 1034ff61fe..bd6d858829 100644 --- a/go.sum +++ b/go.sum @@ -33,8 +33,8 @@ github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJR github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -380,10 +380,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index 1616dbb9f8..d3071faadc 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -161,6 +161,16 @@ func (s *Server) setHealthStatus(hs control.HealthStatus) { } } +func (s *Server) CompareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swapped bool) { + if swapped = s.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped { + s.notifySystemd(newSt) + if s.irMetrics != nil { + s.irMetrics.SetHealth(int32(newSt)) + } + } + return +} + // HealthStatus returns the current health status of the IR application. func (s *Server) HealthStatus() control.HealthStatus { return control.HealthStatus(s.healthStatus.Load()) @@ -186,6 +196,8 @@ func (s *Server) notifySystemd(st control.HealthStatus) { err = sdnotify.FlagAndStatus(sdnotify.ReadyEnabled) case control.HealthStatus_SHUTTING_DOWN: err = sdnotify.FlagAndStatus(sdnotify.StoppingEnabled) + case control.HealthStatus_RECONFIGURING: + err = sdnotify.FlagAndStatus(sdnotify.ReloadingEnabled) default: err = sdnotify.Status(fmt.Sprintf("%v", st)) } diff --git a/pkg/services/control/ir/types.pb.go b/pkg/services/control/ir/types.pb.go index 828814b250..840e0be677 100644 --- a/pkg/services/control/ir/types.pb.go +++ b/pkg/services/control/ir/types.pb.go @@ -32,6 +32,8 @@ const ( HealthStatus_READY HealthStatus = 2 // IR application is shutting down. HealthStatus_SHUTTING_DOWN HealthStatus = 3 + // IR application is reconfiguring. + HealthStatus_RECONFIGURING HealthStatus = 4 ) // Enum value maps for HealthStatus. @@ -41,12 +43,14 @@ var ( 1: "STARTING", 2: "READY", 3: "SHUTTING_DOWN", + 4: "RECONFIGURING", } HealthStatus_value = map[string]int32{ "HEALTH_STATUS_UNDEFINED": 0, "STARTING": 1, "READY": 2, "SHUTTING_DOWN": 3, + "RECONFIGURING": 4, } ) @@ -144,17 +148,19 @@ var file_pkg_services_control_ir_types_proto_rawDesc = []byte{ 0x22, 0x36, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0x57, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, - 0x03, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, - 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, - 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x69, 0x72, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, + 0x4e, 0x47, 0x10, 0x04, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, + 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, + 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, + 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, + 0x69, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/pkg/services/control/ir/types.proto b/pkg/services/control/ir/types.proto index 9b6731cf85..901a55918b 100644 --- a/pkg/services/control/ir/types.proto +++ b/pkg/services/control/ir/types.proto @@ -26,4 +26,7 @@ enum HealthStatus { // IR application is shutting down. SHUTTING_DOWN = 3; + + // IR application is reconfiguring. + RECONFIGURING = 4; } From 5da41f1fe55f6bb906f0e05d2539ccf9a21cdfa6 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Wed, 14 Aug 2024 13:55:34 +0300 Subject: [PATCH 0738/1413] Revert "[#1262] sdnotify: Get rid of go:linkname for nanotime" This reverts commit 327d364f34de730879f330ea51d8801f5c6bddc9. Reverted due to the problem with reload signal sent by systemd. `frostfs-ir` service reconfigures correctly and service's statuses are being reported to systemd. However, since we replaced `go:linkname` & `nanotime()` with `time.Since()`, systemd refuses to accept reload signal response from `frostfs-ir`. To maintain correct behaviour it was decided to revevrt systemd-related changes until a better solution is found. Signed-off-by: Ekaterina Lebedeva --- pkg/util/sdnotify/clock.go | 10 ++++++++++ pkg/util/sdnotify/clock.s | 2 ++ pkg/util/sdnotify/sdnotify.go | 4 +--- 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 pkg/util/sdnotify/clock.go create mode 100644 pkg/util/sdnotify/clock.s diff --git a/pkg/util/sdnotify/clock.go b/pkg/util/sdnotify/clock.go new file mode 100644 index 0000000000..f5419d0274 --- /dev/null +++ b/pkg/util/sdnotify/clock.go @@ -0,0 +1,10 @@ +package sdnotify + +import ( + // For go:linkname to work. + _ "unsafe" +) + +//go:noescape +//go:linkname nanotime runtime.nanotime +func nanotime() int64 diff --git a/pkg/util/sdnotify/clock.s b/pkg/util/sdnotify/clock.s new file mode 100644 index 0000000000..ad033ff4f7 --- /dev/null +++ b/pkg/util/sdnotify/clock.s @@ -0,0 +1,2 @@ +// The file is intentionally empty. +// It is a workaround for https://github.com/golang/go/issues/15006 diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go index a3af50b22a..16a3f11c1e 100644 --- a/pkg/util/sdnotify/sdnotify.go +++ b/pkg/util/sdnotify/sdnotify.go @@ -6,7 +6,6 @@ import ( "net" "os" "strings" - "time" ) const ( @@ -17,7 +16,6 @@ const ( var ( socket *net.UnixAddr - start = time.Now() errSocketVariableIsNotPresent = errors.New("\"NOTIFY_SOCKET\" environment variable is not present") errSocketIsNotInitialized = errors.New("socket is not initialized") @@ -53,7 +51,7 @@ func FlagAndStatus(status string) error { // must be sent, containing "READY=1". // // For MONOTONIC_USEC format refer to https://www.man7.org/linux/man-pages/man3/sd_notify.3.html - status += fmt.Sprintf("\nMONOTONIC_USEC=%d", uint64(time.Since(start))/1e3 /* microseconds in nanoseconds */) + status += fmt.Sprintf("\nMONOTONIC_USEC=%d", uint64(nanotime())/1e3 /* microseconds in nanoseconds */) } status += "\nSTATUS=" + strings.TrimSuffix(status, "=1") return Send(status) From ec1509de4ebbccbade51115c434996cd1fd9be7e Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Thu, 15 Aug 2024 17:12:38 +0300 Subject: [PATCH 0739/1413] [#1262] sdnotify: Send system monotonic time on reload The synchronized service reload protocol added in systemd version 253 requires that the service provides a MONOTONIC_USEC field alongside the RELOADING=1 notification message for synchronization purposes. The value carried in this field must be the system CLOCK_MONOTONIC timestamp at the time the notification message was generated as systemd compares it to other CLOCK_MONOTONIC timestamps taken by pid1. Signed-off-by: Ekaterina Lebedeva --- pkg/util/sdnotify/clock.go | 10 ---------- pkg/util/sdnotify/clock.s | 2 -- pkg/util/sdnotify/sdnotify.go | 9 ++++++++- 3 files changed, 8 insertions(+), 13 deletions(-) delete mode 100644 pkg/util/sdnotify/clock.go delete mode 100644 pkg/util/sdnotify/clock.s diff --git a/pkg/util/sdnotify/clock.go b/pkg/util/sdnotify/clock.go deleted file mode 100644 index f5419d0274..0000000000 --- a/pkg/util/sdnotify/clock.go +++ /dev/null @@ -1,10 +0,0 @@ -package sdnotify - -import ( - // For go:linkname to work. - _ "unsafe" -) - -//go:noescape -//go:linkname nanotime runtime.nanotime -func nanotime() int64 diff --git a/pkg/util/sdnotify/clock.s b/pkg/util/sdnotify/clock.s deleted file mode 100644 index ad033ff4f7..0000000000 --- a/pkg/util/sdnotify/clock.s +++ /dev/null @@ -1,2 +0,0 @@ -// The file is intentionally empty. -// It is a workaround for https://github.com/golang/go/issues/15006 diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go index 16a3f11c1e..5235315cc9 100644 --- a/pkg/util/sdnotify/sdnotify.go +++ b/pkg/util/sdnotify/sdnotify.go @@ -5,7 +5,10 @@ import ( "fmt" "net" "os" + "strconv" "strings" + + "golang.org/x/sys/unix" ) const ( @@ -51,7 +54,11 @@ func FlagAndStatus(status string) error { // must be sent, containing "READY=1". // // For MONOTONIC_USEC format refer to https://www.man7.org/linux/man-pages/man3/sd_notify.3.html - status += fmt.Sprintf("\nMONOTONIC_USEC=%d", uint64(nanotime())/1e3 /* microseconds in nanoseconds */) + var ts unix.Timespec + if err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts); err != nil { + return fmt.Errorf("clock_gettime: %w", err) + } + status += "\nMONOTONIC_USEC=" + strconv.FormatInt(ts.Nano()/1000, 10) } status += "\nSTATUS=" + strings.TrimSuffix(status, "=1") return Send(status) From a4a1c3f18ba75ba73de0fbc97bbccacf68625ee5 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 12 Aug 2024 13:01:57 +0300 Subject: [PATCH 0740/1413] [#1307] go.mod: Bump frostfs-sdk-go/frostfs-api-go/v2 versions * Also, resolve dependencies and conflicts for object service by creating stub for `Patch` method. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/object.go | 18 ++++++- go.mod | 6 +-- go.sum | 12 ++--- pkg/network/transport/object/grpc/service.go | 42 +++++++++++++++ pkg/services/object/acl/v2/service.go | 20 +++++++ pkg/services/object/ape/service.go | 20 +++++++ pkg/services/object/audit.go | 56 ++++++++++++++++++++ pkg/services/object/common.go | 8 +++ pkg/services/object/metrics.go | 37 +++++++++++++ pkg/services/object/patch/service.go | 22 ++++++++ pkg/services/object/patch/streamer.go | 28 ++++++++++ pkg/services/object/response.go | 34 ++++++++++++ pkg/services/object/server.go | 7 +++ pkg/services/object/sign.go | 42 +++++++++++++++ pkg/services/object/transport_splitter.go | 4 ++ 15 files changed, 345 insertions(+), 11 deletions(-) create mode 100644 pkg/services/object/patch/service.go create mode 100644 pkg/services/object/patch/streamer.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 0124bf772d..eef1424153 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -28,6 +28,7 @@ import ( deletesvcV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete/v2" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" getsvcV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get/v2" + patchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/patch" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" putsvcV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put/v2" searchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search" @@ -54,6 +55,8 @@ type objectSvc struct { get *getsvcV2.Service delete *deletesvcV2.Service + + patch *patchsvc.Service } func (c *cfg) MaxObjectSize() uint64 { @@ -71,6 +74,10 @@ func (s *objectSvc) Put() (objectService.PutObjectStream, error) { return s.put.Put() } +func (s *objectSvc) Patch() (objectService.PatchObjectstream, error) { + return s.patch.Patch() +} + func (s *objectSvc) PutSingle(ctx context.Context, req *object.PutSingleRequest) (*object.PutSingleResponse, error) { return s.put.PutSingle(ctx, req) } @@ -181,10 +188,12 @@ func initObjectService(c *cfg) { sDeleteV2 := createDeleteServiceV2(sDelete) + sPatch := createPatchSvc(sGet, sPut, keyStorage) + // build service pipeline // grpc | audit | | signature | response | acl | ape | split - splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2) + splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2, sPatch) apeSvc := createAPEService(c, splitSvc) @@ -353,6 +362,10 @@ func createPutSvcV2(sPut *putsvc.Service, keyStorage *util.KeyStorage) *putsvcV2 return putsvcV2.NewService(sPut, keyStorage) } +func createPatchSvc(sGet *getsvc.Service, sPut *putsvc.Service, keyStorage *util.KeyStorage) *patchsvc.Service { + return patchsvc.NewService(keyStorage, sGet, sPut) +} + func createSearchSvc(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.TraverserGenerator, coreConstructor *cache.ClientCache) *searchsvc.Service { ls := c.cfgObject.cfgLocalStorage.localStorage @@ -425,7 +438,7 @@ func createDeleteServiceV2(sDelete *deletesvc.Service) *deletesvcV2.Service { } func createSplitService(c *cfg, sPutV2 *putsvcV2.Service, sGetV2 *getsvcV2.Service, - sSearchV2 *searchsvcV2.Service, sDeleteV2 *deletesvcV2.Service, + sSearchV2 *searchsvcV2.Service, sDeleteV2 *deletesvcV2.Service, sPatch *patchsvc.Service, ) *objectService.TransportSplitter { return objectService.NewTransportSplitter( c.cfgGRPC.maxChunkSize, @@ -435,6 +448,7 @@ func createSplitService(c *cfg, sPutV2 *putsvcV2.Service, sGetV2 *getsvcV2.Servi search: sSearchV2, get: sGetV2, delete: sDeleteV2, + patch: sPatch, }, ) } diff --git a/go.mod b/go.mod index 196b4d4639..93ed7d7505 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,14 @@ go 1.21 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240813155151-d112a28d382f git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240813155821-98aabc45a720 git.frostfs.info/TrueCloudLab/hrw v1.2.1 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/cheggaaa/pb v1.0.29 diff --git a/go.sum b/go.sum index bd6d858829..803a065c3d 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e h1:gEWT+70E/RvGkxtSv+PlyUN2vtJVymhQa1mypvrXukM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240726072425-3dfa2f4fd65e/go.mod h1:OBDSr+DqV1z4VDouoX3YMleNc4DPBVBWTG3WDT2PK1o= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240813155151-d112a28d382f h1:xrJqsXOZeSkBFMSyN+PQ9DiCGxVULU3VIN/tuH/vtb8= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240813155151-d112a28d382f/go.mod h1:mc7j6Cc1GU1tJZNmDwEYiJJ339biNnU1Bz3wZGogMe0= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= @@ -10,14 +10,14 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec h1:A09Swh7yogmmiABUf7Ht6MTQXJ07MyGx4+ziUQNelec= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240726111349-9da46f566fec/go.mod h1:DlJmgV4/qkFkx2ab+YWznlMijiF2yZHnrJswJOB7XGs= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240813155821-98aabc45a720 h1:15UXpW42bfshIv/X5kww92jG2o0drHgsdFd+UJ6zD7g= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240813155821-98aabc45a720/go.mod h1:XRX/bBQsDJKr040N/a0YnDhxJqaUv1XyMVj3qxnb5K0= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984 h1:O3F2Grz07RWZ68mRz1xsYsNPNvZLwY00BM+xoYb1kNk= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240712081403-2628f6184984/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 h1:vgbfkcnIexZUm3vREBBSa/Gv1Whjd1SFCUd0A+IaGPQ= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= diff --git a/pkg/network/transport/object/grpc/service.go b/pkg/network/transport/object/grpc/service.go index 7c6b395d5a..d55e3d87f9 100644 --- a/pkg/network/transport/object/grpc/service.go +++ b/pkg/network/transport/object/grpc/service.go @@ -24,6 +24,48 @@ func New(c objectSvc.ServiceServer) *Server { } } +// Patch opens internal Object patch stream and feeds it by the data read from gRPC stream. +func (s *Server) Patch(gStream objectGRPC.ObjectService_PatchServer) error { + stream, err := s.srv.Patch() + if err != nil { + return err + } + + for { + req, err := gStream.Recv() + if err != nil { + if errors.Is(err, io.EOF) { + resp, err := stream.CloseAndRecv(gStream.Context()) + if err != nil { + return err + } + + return gStream.SendAndClose(resp.ToGRPCMessage().(*objectGRPC.PatchResponse)) + } + + return err + } + + patchReq := new(object.PatchRequest) + if err := patchReq.FromGRPCMessage(req); err != nil { + return err + } + + if err := stream.Send(gStream.Context(), patchReq); err != nil { + if errors.Is(err, util.ErrAbortStream) { + resp, err := stream.CloseAndRecv(gStream.Context()) + if err != nil { + return err + } + + return gStream.SendAndClose(resp.ToGRPCMessage().(*objectGRPC.PatchResponse)) + } + + return err + } + } +} + // Put opens internal Object service Put stream and overtakes data from gRPC stream to it. func (s *Server) Put(gStream objectGRPC.ObjectService_PutServer) error { stream, err := s.srv.Put() diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 3e128836fc..58557d6111 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -249,6 +249,26 @@ func (b Service) Put() (object.PutObjectStream, error) { }, err } +type patchStreamBasicChecker struct { + next object.PatchObjectstream +} + +func (p patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { + return p.next.Send(ctx, request) +} + +func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { + return p.next.CloseAndRecv(ctx) +} + +func (b Service) Patch() (object.PatchObjectstream, error) { + streamer, err := b.next.Patch() + + return &patchStreamBasicChecker{ + next: streamer, + }, err +} + func (b Service) Head( ctx context.Context, request *objectV2.HeadRequest, diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 2adb1b7367..f005d0873a 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -204,6 +204,26 @@ func (c *Service) Put() (objectSvc.PutObjectStream, error) { }, err } +type patchStreamBasicChecker struct { + next objectSvc.PatchObjectstream +} + +func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { + return p.next.Send(ctx, request) +} + +func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { + return p.next.CloseAndRecv(ctx) +} + +func (c *Service) Patch() (objectSvc.PatchObjectstream, error) { + streamer, err := c.next.Patch() + + return &patchStreamBasicChecker{ + next: streamer, + }, err +} + func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { diff --git a/pkg/services/object/audit.go b/pkg/services/object/audit.go index 1305fa0087..680a96c403 100644 --- a/pkg/services/object/audit.go +++ b/pkg/services/object/audit.go @@ -170,3 +170,59 @@ func (a *auditPutStream) Send(ctx context.Context, req *object.PutRequest) error } return err } + +type auditPatchStream struct { + stream PatchObjectstream + log *logger.Logger + + failed bool + key []byte + containerID *refs.ContainerID + objectID *refs.ObjectID +} + +func (a *auditService) Patch() (PatchObjectstream, error) { + res, err := a.next.Patch() + if !a.enabled.Load() { + return res, err + } + if err != nil { + audit.LogRequest(a.log, objectGRPC.ObjectService_Patch_FullMethodName, nil, nil, false) + return res, err + } + return &auditPatchStream{ + stream: res, + log: a.log, + }, nil +} + +// CloseAndRecv implements PutObjectStream. +func (a *auditPatchStream) CloseAndRecv(ctx context.Context) (*object.PatchResponse, error) { + resp, err := a.stream.CloseAndRecv(ctx) + if err != nil { + a.failed = true + } + a.objectID = resp.GetBody().ObjectID + audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Patch_FullMethodName, a.key, + audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), + !a.failed) + return resp, err +} + +// Send implements PutObjectStream. +func (a *auditPatchStream) Send(ctx context.Context, req *object.PatchRequest) error { + a.containerID = req.GetBody().GetAddress().GetContainerID() + a.objectID = req.GetBody().GetAddress().GetObjectID() + a.key = req.GetVerificationHeader().GetBodySignature().GetKey() + + err := a.stream.Send(ctx, req) + if err != nil { + a.failed = true + } + if !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here + audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Patch_FullMethodName, a.key, + audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), + !a.failed) + } + return err +} diff --git a/pkg/services/object/common.go b/pkg/services/object/common.go index 73ee9f81b3..841a3d021b 100644 --- a/pkg/services/object/common.go +++ b/pkg/services/object/common.go @@ -48,6 +48,14 @@ func (x *Common) Put() (PutObjectStream, error) { return x.nextHandler.Put() } +func (x *Common) Patch() (PatchObjectstream, error) { + if x.state.IsMaintenance() { + return nil, new(apistatus.NodeUnderMaintenance) + } + + return x.nextHandler.Patch() +} + func (x *Common) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { if x.state.IsMaintenance() { return nil, new(apistatus.NodeUnderMaintenance) diff --git a/pkg/services/object/metrics.go b/pkg/services/object/metrics.go index f972f43ae6..b64f879ac1 100644 --- a/pkg/services/object/metrics.go +++ b/pkg/services/object/metrics.go @@ -27,6 +27,12 @@ type ( start time.Time } + patchStreamMetric struct { + stream PatchObjectstream + metrics MetricRegister + start time.Time + } + MetricRegister interface { AddRequestDuration(string, time.Duration, bool) AddPayloadSize(string, int) @@ -76,6 +82,24 @@ func (m MetricCollector) Put() (PutObjectStream, error) { return m.next.Put() } +func (m MetricCollector) Patch() (PatchObjectstream, error) { + if m.enabled { + t := time.Now() + + stream, err := m.next.Patch() + if err != nil { + return nil, err + } + + return &patchStreamMetric{ + stream: stream, + metrics: m.metrics, + start: t, + }, nil + } + return m.next.Patch() +} + func (m MetricCollector) PutSingle(ctx context.Context, request *object.PutSingleRequest) (*object.PutSingleResponse, error) { if m.enabled { t := time.Now() @@ -189,3 +213,16 @@ func (s putStreamMetric) CloseAndRecv(ctx context.Context) (*object.PutResponse, return res, err } +func (s patchStreamMetric) Send(ctx context.Context, req *object.PatchRequest) error { + s.metrics.AddPayloadSize("Patch", len(req.GetBody().GetPatch().Chunk)) + + return s.stream.Send(ctx, req) +} + +func (s patchStreamMetric) CloseAndRecv(ctx context.Context) (*object.PatchResponse, error) { + res, err := s.stream.CloseAndRecv(ctx) + + s.metrics.AddRequestDuration("Patch", time.Since(s.start), err == nil) + + return res, err +} diff --git a/pkg/services/object/patch/service.go b/pkg/services/object/patch/service.go new file mode 100644 index 0000000000..df6926e84b --- /dev/null +++ b/pkg/services/object/patch/service.go @@ -0,0 +1,22 @@ +package patchsvc + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" + getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" + putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" +) + +// Service implements Put operation of Object service v2. +type Service struct { +} + +// NewService constructs Service instance from provided options. +func NewService(_ *util.KeyStorage, _ *getsvc.Service, _ *putsvc.Service) *Service { + return &Service{} +} + +// Put calls internal service and returns v2 object streamer. +func (s *Service) Patch() (object.PatchObjectstream, error) { + return &Streamer{}, nil +} diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go new file mode 100644 index 0000000000..5d021b9c3e --- /dev/null +++ b/pkg/services/object/patch/streamer.go @@ -0,0 +1,28 @@ +package patchsvc + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" +) + +// Streamer for the patch handler is a pipeline that merges two incoming +// streams of patches and original object payload chunks. +// The merged result is fed to Put stream target. +type Streamer struct{} + +func (s *Streamer) Send(ctx context.Context, _ *object.PatchRequest) error { + _, span := tracing.StartSpanFromContext(ctx, "patch.streamer.Send") + defer span.End() + + return nil +} + +func (s *Streamer) CloseAndRecv(_ context.Context) (*object.PatchResponse, error) { + return &object.PatchResponse{ + Body: &object.PatchResponseBody{ + ObjectID: nil, + }, + }, nil +} diff --git a/pkg/services/object/response.go b/pkg/services/object/response.go index a10f26a349..c85259c1f7 100644 --- a/pkg/services/object/response.go +++ b/pkg/services/object/response.go @@ -37,6 +37,11 @@ type putStreamResponser struct { respSvc *response.Service } +type patchStreamResponser struct { + stream PatchObjectstream + respSvc *response.Service +} + // NewResponseService returns object service instance that passes internal service // call to response service. func NewResponseService(objSvc ServiceServer, respSvc *response.Service) *ResponseService { @@ -87,6 +92,35 @@ func (s *ResponseService) Put() (PutObjectStream, error) { }, nil } +func (s *patchStreamResponser) Send(ctx context.Context, req *object.PatchRequest) error { + if err := s.stream.Send(ctx, req); err != nil { + return fmt.Errorf("could not send the request: %w", err) + } + return nil +} + +func (s *patchStreamResponser) CloseAndRecv(ctx context.Context) (*object.PatchResponse, error) { + r, err := s.stream.CloseAndRecv(ctx) + if err != nil { + return nil, fmt.Errorf("could not close stream and receive response: %w", err) + } + + s.respSvc.SetMeta(r) + return r, nil +} + +func (s *ResponseService) Patch() (PatchObjectstream, error) { + stream, err := s.svc.Patch() + if err != nil { + return nil, fmt.Errorf("could not create Put object streamer: %w", err) + } + + return &patchStreamResponser{ + stream: stream, + respSvc: s.respSvc, + }, nil +} + func (s *ResponseService) PutSingle(ctx context.Context, req *object.PutSingleRequest) (*object.PutSingleResponse, error) { resp, err := s.svc.PutSingle(ctx, req) if err != nil { diff --git a/pkg/services/object/server.go b/pkg/services/object/server.go index 73b88f2339..c1b036ab33 100644 --- a/pkg/services/object/server.go +++ b/pkg/services/object/server.go @@ -31,11 +31,18 @@ type PutObjectStream interface { CloseAndRecv(context.Context) (*object.PutResponse, error) } +// PatchObjectstream is an interface of FrostFS API v2 compatible patch streamer. +type PatchObjectstream interface { + Send(context.Context, *object.PatchRequest) error + CloseAndRecv(context.Context) (*object.PatchResponse, error) +} + // ServiceServer is an interface of utility // serving v2 Object service. type ServiceServer interface { Get(*object.GetRequest, GetObjectStream) error Put() (PutObjectStream, error) + Patch() (PatchObjectstream, error) Head(context.Context, *object.HeadRequest) (*object.HeadResponse, error) Search(*object.SearchRequest, SearchStream) error Delete(context.Context, *object.DeleteRequest) (*object.DeleteResponse, error) diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 4bf581b787..631c539af3 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -35,6 +35,12 @@ type putStreamSigner struct { err error } +type patchStreamSigner struct { + sigSvc *util.SignService + stream PatchObjectstream + err error +} + type getRangeStreamSigner struct { GetObjectRangeStream sigSvc *util.SignService @@ -112,6 +118,42 @@ func (s *SignService) Put() (PutObjectStream, error) { }, nil } +func (s *patchStreamSigner) Send(ctx context.Context, req *object.PatchRequest) error { + if s.err = s.sigSvc.VerifyRequest(req); s.err != nil { + return util.ErrAbortStream + } + if s.err = s.stream.Send(ctx, req); s.err != nil { + return util.ErrAbortStream + } + return nil +} + +func (s *patchStreamSigner) CloseAndRecv(ctx context.Context) (resp *object.PatchResponse, err error) { + if s.err != nil { + err = s.err + resp = new(object.PatchResponse) + } else { + resp, err = s.stream.CloseAndRecv(ctx) + if err != nil { + return nil, fmt.Errorf("could not close stream and receive response: %w", err) + } + } + + return resp, s.sigSvc.SignResponse(resp, err) +} + +func (s *SignService) Patch() (PatchObjectstream, error) { + stream, err := s.svc.Patch() + if err != nil { + return nil, fmt.Errorf("could not create Put object streamer: %w", err) + } + + return &patchStreamSigner{ + stream: stream, + sigSvc: s.sigSvc, + }, nil +} + func (s *SignService) Head(ctx context.Context, req *object.HeadRequest) (*object.HeadResponse, error) { if err := s.sigSvc.VerifyRequest(req); err != nil { resp := new(object.HeadResponse) diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index 54e49cb129..5acfac06b6 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -91,6 +91,10 @@ func (c TransportSplitter) Put() (PutObjectStream, error) { return c.next.Put() } +func (c TransportSplitter) Patch() (PatchObjectstream, error) { + return c.next.Patch() +} + func (c TransportSplitter) Head(ctx context.Context, request *object.HeadRequest) (*object.HeadResponse, error) { return c.next.Head(ctx, request) } From e890f1b4b17d62cd95fe22d018212f91ff2be95d Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 12 Aug 2024 17:11:10 +0300 Subject: [PATCH 0741/1413] [#1307] object: Implement `Patch` method Signed-off-by: Airat Arifullin --- cmd/frostfs-node/object.go | 2 +- pkg/services/object/acl/v2/service.go | 20 +- pkg/services/object/acl/v2/util.go | 8 +- pkg/services/object/ape/checker_test.go | 19 +- pkg/services/object/ape/service.go | 20 +- pkg/services/object/audit.go | 19 +- pkg/services/object/common.go | 2 +- pkg/services/object/get/prm.go | 4 + pkg/services/object/metrics.go | 6 +- pkg/services/object/patch/range_provider.go | 63 ++++++ pkg/services/object/patch/service.go | 30 ++- pkg/services/object/patch/streamer.go | 215 +++++++++++++++++++- pkg/services/object/patch/util.go | 53 +++++ pkg/services/object/put/prm.go | 11 + pkg/services/object/put/streamer.go | 23 ++- pkg/services/object/response.go | 4 +- pkg/services/object/server.go | 6 +- pkg/services/object/sign.go | 4 +- pkg/services/object/transport_splitter.go | 2 +- 19 files changed, 430 insertions(+), 81 deletions(-) create mode 100644 pkg/services/object/patch/range_provider.go create mode 100644 pkg/services/object/patch/util.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index eef1424153..467c5901b8 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -74,7 +74,7 @@ func (s *objectSvc) Put() (objectService.PutObjectStream, error) { return s.put.Put() } -func (s *objectSvc) Patch() (objectService.PatchObjectstream, error) { +func (s *objectSvc) Patch() (objectService.PatchObjectStream, error) { return s.patch.Patch() } diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 58557d6111..a9ddad7cab 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -249,24 +249,8 @@ func (b Service) Put() (object.PutObjectStream, error) { }, err } -type patchStreamBasicChecker struct { - next object.PatchObjectstream -} - -func (p patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { - return p.next.Send(ctx, request) -} - -func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { - return p.next.CloseAndRecv(ctx) -} - -func (b Service) Patch() (object.PatchObjectstream, error) { - streamer, err := b.next.Patch() - - return &patchStreamBasicChecker{ - next: streamer, - }, err +func (b Service) Patch() (object.PatchObjectStream, error) { + return b.next.Patch() } func (b Service) Head( diff --git a/pkg/services/object/acl/v2/util.go b/pkg/services/object/acl/v2/util.go index feda6a3cf6..76fd9651d3 100644 --- a/pkg/services/object/acl/v2/util.go +++ b/pkg/services/object/acl/v2/util.go @@ -174,7 +174,7 @@ func isOwnerFromKey(id user.ID, key *keys.PublicKey) bool { func assertVerb(tok sessionSDK.Object, op acl.Op) bool { switch op { case acl.OpObjectPut: - return tok.AssertVerb(sessionSDK.VerbObjectPut, sessionSDK.VerbObjectDelete) + return tok.AssertVerb(sessionSDK.VerbObjectPut, sessionSDK.VerbObjectDelete, sessionSDK.VerbObjectPatch) case acl.OpObjectDelete: return tok.AssertVerb(sessionSDK.VerbObjectDelete) case acl.OpObjectGet: @@ -185,11 +185,13 @@ func assertVerb(tok sessionSDK.Object, op acl.Op) bool { sessionSDK.VerbObjectGet, sessionSDK.VerbObjectDelete, sessionSDK.VerbObjectRange, - sessionSDK.VerbObjectRangeHash) + sessionSDK.VerbObjectRangeHash, + sessionSDK.VerbObjectPatch, + ) case acl.OpObjectSearch: return tok.AssertVerb(sessionSDK.VerbObjectSearch, sessionSDK.VerbObjectDelete) case acl.OpObjectRange: - return tok.AssertVerb(sessionSDK.VerbObjectRange, sessionSDK.VerbObjectRangeHash) + return tok.AssertVerb(sessionSDK.VerbObjectRange, sessionSDK.VerbObjectRangeHash, sessionSDK.VerbObjectPatch) case acl.OpObjectHash: return tok.AssertVerb(sessionSDK.VerbObjectRangeHash) } diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 090f6a83ca..afe19fc513 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -518,7 +518,22 @@ func TestAPECheck_BearerTokenOverrides(t *testing.T) { ls := inmemory.NewInmemoryLocalStorage() ms := inmemory.NewInmemoryMorphRuleChainStorage() - checker := NewChecker(ls, ms, headerProvider, frostfsidProvider, nil, &stMock{}, nil, nil) + node1Key, err := keys.NewPrivateKey() + require.NoError(t, err) + node1 := netmapSDK.NodeInfo{} + node1.SetPublicKey(node1Key.PublicKey().Bytes()) + netmap := &netmapSDK.NetMap{} + netmap.SetEpoch(100) + netmap.SetNodes([]netmapSDK.NodeInfo{node1}) + + nm := &netmapStub{ + currentEpoch: 100, + netmaps: map[uint64]*netmapSDK.NetMap{ + 100: netmap, + }, + } + + checker := NewChecker(ls, ms, headerProvider, frostfsidProvider, nm, &stMock{}, nil, nil) prm := Prm{ Method: method, @@ -541,7 +556,7 @@ func TestAPECheck_BearerTokenOverrides(t *testing.T) { } } - err := checker.CheckAPE(context.Background(), prm) + err = checker.CheckAPE(context.Background(), prm) if test.expectAPEErr { require.Error(t, err) } else { diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index f005d0873a..64dd19c24c 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -204,24 +204,8 @@ func (c *Service) Put() (objectSvc.PutObjectStream, error) { }, err } -type patchStreamBasicChecker struct { - next objectSvc.PatchObjectstream -} - -func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { - return p.next.Send(ctx, request) -} - -func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { - return p.next.CloseAndRecv(ctx) -} - -func (c *Service) Patch() (objectSvc.PatchObjectstream, error) { - streamer, err := c.next.Patch() - - return &patchStreamBasicChecker{ - next: streamer, - }, err +func (c *Service) Patch() (objectSvc.PatchObjectStream, error) { + return c.next.Patch() } func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { diff --git a/pkg/services/object/audit.go b/pkg/services/object/audit.go index 680a96c403..b924386d1c 100644 --- a/pkg/services/object/audit.go +++ b/pkg/services/object/audit.go @@ -172,16 +172,18 @@ func (a *auditPutStream) Send(ctx context.Context, req *object.PutRequest) error } type auditPatchStream struct { - stream PatchObjectstream + stream PatchObjectStream log *logger.Logger failed bool key []byte containerID *refs.ContainerID objectID *refs.ObjectID + + nonFirstSend bool } -func (a *auditService) Patch() (PatchObjectstream, error) { +func (a *auditService) Patch() (PatchObjectStream, error) { res, err := a.next.Patch() if !a.enabled.Load() { return res, err @@ -196,7 +198,7 @@ func (a *auditService) Patch() (PatchObjectstream, error) { }, nil } -// CloseAndRecv implements PutObjectStream. +// CloseAndRecv implements PatchObjectStream. func (a *auditPatchStream) CloseAndRecv(ctx context.Context) (*object.PatchResponse, error) { resp, err := a.stream.CloseAndRecv(ctx) if err != nil { @@ -209,11 +211,14 @@ func (a *auditPatchStream) CloseAndRecv(ctx context.Context) (*object.PatchRespo return resp, err } -// Send implements PutObjectStream. +// Send implements PatchObjectStream. func (a *auditPatchStream) Send(ctx context.Context, req *object.PatchRequest) error { - a.containerID = req.GetBody().GetAddress().GetContainerID() - a.objectID = req.GetBody().GetAddress().GetObjectID() - a.key = req.GetVerificationHeader().GetBodySignature().GetKey() + if !a.nonFirstSend { + a.containerID = req.GetBody().GetAddress().GetContainerID() + a.objectID = req.GetBody().GetAddress().GetObjectID() + a.key = req.GetVerificationHeader().GetBodySignature().GetKey() + a.nonFirstSend = true + } err := a.stream.Send(ctx, req) if err != nil { diff --git a/pkg/services/object/common.go b/pkg/services/object/common.go index 841a3d021b..f48cc5b3d0 100644 --- a/pkg/services/object/common.go +++ b/pkg/services/object/common.go @@ -48,7 +48,7 @@ func (x *Common) Put() (PutObjectStream, error) { return x.nextHandler.Put() } -func (x *Common) Patch() (PatchObjectstream, error) { +func (x *Common) Patch() (PatchObjectStream, error) { if x.state.IsMaintenance() { return nil, new(apistatus.NodeUnderMaintenance) } diff --git a/pkg/services/object/get/prm.go b/pkg/services/object/get/prm.go index cbdb7a3e24..94c07381c5 100644 --- a/pkg/services/object/get/prm.go +++ b/pkg/services/object/get/prm.go @@ -124,6 +124,10 @@ func (p *commonPrm) SetRequestForwarder(f RequestForwarder) { p.forwarder = f } +func (p *commonPrm) SetSignerKey(signerKey *ecdsa.PrivateKey) { + p.signerKey = signerKey +} + // WithAddress sets object address to be read. func (p *commonPrm) WithAddress(addr oid.Address) { p.addr = addr diff --git a/pkg/services/object/metrics.go b/pkg/services/object/metrics.go index b64f879ac1..e53b7584f3 100644 --- a/pkg/services/object/metrics.go +++ b/pkg/services/object/metrics.go @@ -28,7 +28,7 @@ type ( } patchStreamMetric struct { - stream PatchObjectstream + stream PatchObjectStream metrics MetricRegister start time.Time } @@ -82,7 +82,7 @@ func (m MetricCollector) Put() (PutObjectStream, error) { return m.next.Put() } -func (m MetricCollector) Patch() (PatchObjectstream, error) { +func (m MetricCollector) Patch() (PatchObjectStream, error) { if m.enabled { t := time.Now() @@ -214,7 +214,7 @@ func (s putStreamMetric) CloseAndRecv(ctx context.Context) (*object.PutResponse, return res, err } func (s patchStreamMetric) Send(ctx context.Context, req *object.PatchRequest) error { - s.metrics.AddPayloadSize("Patch", len(req.GetBody().GetPatch().Chunk)) + s.metrics.AddPayloadSize("Patch", len(req.GetBody().GetPatch().GetChunk())) return s.stream.Send(ctx, req) } diff --git a/pkg/services/object/patch/range_provider.go b/pkg/services/object/patch/range_provider.go new file mode 100644 index 0000000000..755c5bf60b --- /dev/null +++ b/pkg/services/object/patch/range_provider.go @@ -0,0 +1,63 @@ +package patchsvc + +import ( + "context" + "crypto/ecdsa" + "io" + + getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" + objectUtil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + patcherSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/patcher" +) + +func (p *pipeChunkWriter) WriteChunk(_ context.Context, chunk []byte) error { + _, err := p.wr.Write(chunk) + return err +} + +type rangeProvider struct { + getSvc *getsvc.Service + + addr oid.Address + + commonPrm *objectUtil.CommonPrm + + localNodeKey *ecdsa.PrivateKey +} + +var _ patcherSDK.RangeProvider = (*rangeProvider)(nil) + +func (r *rangeProvider) GetRange(ctx context.Context, rng *objectSDK.Range) io.Reader { + pipeReader, pipeWriter := io.Pipe() + + var rngPrm getsvc.RangePrm + rngPrm.SetSignerKey(r.localNodeKey) + rngPrm.SetCommonParameters(r.commonPrm) + + rngPrm.WithAddress(r.addr) + rngPrm.SetChunkWriter(&pipeChunkWriter{ + wr: pipeWriter, + }) + rngPrm.SetRange(rng) + + getRangeErr := make(chan error) + + go func() { + defer pipeWriter.Close() + + select { + case <-ctx.Done(): + pipeWriter.CloseWithError(ctx.Err()) + case err := <-getRangeErr: + pipeWriter.CloseWithError(err) + } + }() + + go func() { + getRangeErr <- r.getSvc.GetRange(ctx, rngPrm) + }() + + return pipeReader +} diff --git a/pkg/services/object/patch/service.go b/pkg/services/object/patch/service.go index df6926e84b..c4ab15abff 100644 --- a/pkg/services/object/patch/service.go +++ b/pkg/services/object/patch/service.go @@ -9,14 +9,36 @@ import ( // Service implements Put operation of Object service v2. type Service struct { + keyStorage *util.KeyStorage + + getSvc *getsvc.Service + + putSvc *putsvc.Service } // NewService constructs Service instance from provided options. -func NewService(_ *util.KeyStorage, _ *getsvc.Service, _ *putsvc.Service) *Service { - return &Service{} +func NewService(ks *util.KeyStorage, getSvc *getsvc.Service, putSvc *putsvc.Service) *Service { + return &Service{ + keyStorage: ks, + + getSvc: getSvc, + + putSvc: putSvc, + } } // Put calls internal service and returns v2 object streamer. -func (s *Service) Patch() (object.PatchObjectstream, error) { - return &Streamer{}, nil +func (s *Service) Patch() (object.PatchObjectStream, error) { + nodeKey, err := s.keyStorage.GetKey(nil) + if err != nil { + return nil, err + } + + return &Streamer{ + getSvc: s.getSvc, + + putSvc: s.putSvc, + + localNodeKey: nodeKey, + }, nil } diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index 5d021b9c3e..84363530e1 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -2,27 +2,220 @@ package patchsvc import ( "context" + "crypto/ecdsa" + "errors" + "fmt" + "io" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" + putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/patcher" ) -// Streamer for the patch handler is a pipeline that merges two incoming -// streams of patches and original object payload chunks. -// The merged result is fed to Put stream target. -type Streamer struct{} +// Streamer for the patch handler is a pipeline that merges two incoming streams of patches +// and original object payload chunks. The merged result is fed to Put stream target. +type Streamer struct { + // Patcher must be initialized at first Streamer.Send call. + patcher patcher.PatchApplier -func (s *Streamer) Send(ctx context.Context, _ *object.PatchRequest) error { - _, span := tracing.StartSpanFromContext(ctx, "patch.streamer.Send") + nonFirstSend bool + + getSvc *getsvc.Service + + putSvc *putsvc.Service + + localNodeKey *ecdsa.PrivateKey +} + +type pipeChunkWriter struct { + wr *io.PipeWriter +} + +type headResponseWriter struct { + body *objectV2.HeadResponseBody +} + +func (w *headResponseWriter) WriteHeader(_ context.Context, hdr *objectSDK.Object) error { + w.body.SetHeaderPart(toFullObjectHeader(hdr)) + return nil +} + +func toFullObjectHeader(hdr *objectSDK.Object) objectV2.GetHeaderPart { + obj := hdr.ToV2() + + hs := new(objectV2.HeaderWithSignature) + hs.SetHeader(obj.GetHeader()) + hs.SetSignature(obj.GetSignature()) + + return hs +} + +func (s *Streamer) init(ctx context.Context, req *objectV2.PatchRequest) error { + hdrWithSig, addr, err := s.readHeader(ctx, req) + if err != nil { + return err + } + + commonPrm, err := util.CommonPrmFromV2(req) + if err != nil { + return err + } + commonPrm.WithLocalOnly(false) + + rangeProvider := &rangeProvider{ + getSvc: s.getSvc, + + addr: addr, + + commonPrm: commonPrm, + + localNodeKey: s.localNodeKey, + } + + putstm, err := s.putSvc.Put() + if err != nil { + return err + } + + hdr := hdrWithSig.GetHeader() + oV2 := new(objectV2.Object) + hV2 := new(objectV2.Header) + oV2.SetHeader(hV2) + oV2.GetHeader().SetContainerID(hdr.GetContainerID()) + oV2.GetHeader().SetPayloadLength(hdr.GetPayloadLength()) + oV2.GetHeader().SetAttributes(hdr.GetAttributes()) + + ownerID, err := newOwnerID(req.GetVerificationHeader()) + if err != nil { + return err + } + oV2.GetHeader().SetOwnerID(ownerID) + + prm, err := s.putInitPrm(req, oV2) + if err != nil { + return err + } + + err = putstm.Init(ctx, prm) + if err != nil { + return err + } + + patcherPrm := patcher.Params{ + Header: objectSDK.NewFromV2(oV2), + + RangeProvider: rangeProvider, + + ObjectWriter: putstm.Target(), + } + + s.patcher = patcher.New(patcherPrm) + return nil +} + +func (s *Streamer) readHeader(ctx context.Context, req *objectV2.PatchRequest) (hdrWithSig *objectV2.HeaderWithSignature, addr oid.Address, err error) { + addrV2 := req.GetBody().GetAddress() + if addrV2 == nil { + err = errors.New("patch request has nil-address") + return + } + + if err = addr.ReadFromV2(*addrV2); err != nil { + err = fmt.Errorf("read address error: %w", err) + return + } + + commonPrm, err := util.CommonPrmFromV2(req) + if err != nil { + return + } + commonPrm.WithLocalOnly(false) + + var p getsvc.HeadPrm + p.SetSignerKey(s.localNodeKey) + p.SetCommonParameters(commonPrm) + + resp := new(objectV2.HeadResponse) + resp.SetBody(new(objectV2.HeadResponseBody)) + + p.WithAddress(addr) + p.SetHeaderWriter(&headResponseWriter{ + body: resp.GetBody(), + }) + + err = s.getSvc.Head(ctx, p) + if err != nil { + err = fmt.Errorf("get header error: %w", err) + return + } + + var ok bool + hdrPart := resp.GetBody().GetHeaderPart() + if hdrWithSig, ok = hdrPart.(*objectV2.HeaderWithSignature); !ok { + err = fmt.Errorf("unexpected header type: %T", hdrPart) + } + return +} + +func (s *Streamer) Send(ctx context.Context, req *objectV2.PatchRequest) error { + ctx, span := tracing.StartSpanFromContext(ctx, "patch.streamer.Send") defer span.End() + defer func() { + s.nonFirstSend = true + }() + + if !s.nonFirstSend { + if err := s.init(ctx, req); err != nil { + return fmt.Errorf("streamer init error: %w", err) + } + } + + patch := new(objectSDK.Patch) + patch.FromV2(req.GetBody()) + + if !s.nonFirstSend { + err := s.patcher.ApplyAttributesPatch(ctx, patch.NewAttributes, patch.ReplaceAttributes) + if err != nil { + return fmt.Errorf("patch attributes: %w", err) + } + } + + if patch.PayloadPatch != nil { + err := s.patcher.ApplyPayloadPatch(ctx, patch.PayloadPatch) + if err != nil { + return fmt.Errorf("patch payload: %w", err) + } + } else if s.nonFirstSend { + return errors.New("invalid non-first patch: empty payload") + } + return nil } -func (s *Streamer) CloseAndRecv(_ context.Context) (*object.PatchResponse, error) { - return &object.PatchResponse{ - Body: &object.PatchResponseBody{ - ObjectID: nil, +func (s *Streamer) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { + patcherResp, err := s.patcher.Close(ctx) + if err != nil { + return nil, err + } + + oidV2 := new(refsV2.ObjectID) + + if patcherResp.AccessIdentifiers.ParentID != nil { + patcherResp.AccessIdentifiers.ParentID.WriteToV2(oidV2) + } else { + patcherResp.AccessIdentifiers.SelfID.WriteToV2(oidV2) + } + + return &objectV2.PatchResponse{ + Body: &objectV2.PatchResponseBody{ + ObjectID: oidV2, }, }, nil } diff --git a/pkg/services/object/patch/util.go b/pkg/services/object/patch/util.go new file mode 100644 index 0000000000..1218d66949 --- /dev/null +++ b/pkg/services/object/patch/util.go @@ -0,0 +1,53 @@ +package patchsvc + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "errors" + "fmt" + + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +// putInitPrm initializes put paramerer for Put stream. +func (s *Streamer) putInitPrm(req *objectV2.PatchRequest, obj *objectV2.Object) (*putsvc.PutInitPrm, error) { + commonPrm, err := util.CommonPrmFromV2(req) + if err != nil { + return nil, err + } + + prm := new(putsvc.PutInitPrm) + prm.WithObject(objectSDK.NewFromV2(obj)). + WithCommonPrm(commonPrm). + WithPrivateKey(s.localNodeKey) + + return prm, nil +} + +func newOwnerID(vh *session.RequestVerificationHeader) (*refs.OwnerID, error) { + for vh.GetOrigin() != nil { + vh = vh.GetOrigin() + } + sig := vh.GetBodySignature() + if sig == nil { + return nil, errors.New("empty body signature") + } + key, err := keys.NewPublicKeyFromBytes(sig.GetKey(), elliptic.P256()) + if err != nil { + return nil, fmt.Errorf("invalid signature key: %w", err) + } + + var userID user.ID + user.IDFromKey(&userID, (ecdsa.PublicKey)(*key)) + ownID := new(refs.OwnerID) + userID.WriteToV2(ownID) + + return ownID, nil +} diff --git a/pkg/services/object/put/prm.go b/pkg/services/object/put/prm.go index 52a7c102c3..0c8f12b45e 100644 --- a/pkg/services/object/put/prm.go +++ b/pkg/services/object/put/prm.go @@ -2,6 +2,7 @@ package putsvc import ( "context" + "crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -20,6 +21,8 @@ type PutInitPrm struct { traverseOpts []placement.Option relay func(context.Context, client.NodeInfo, client.MultiAddressClient) error + + privateKey *ecdsa.PrivateKey } type PutChunkPrm struct { @@ -65,3 +68,11 @@ func (p *PutChunkPrm) WithChunk(v []byte) *PutChunkPrm { return p } + +func (p *PutInitPrm) WithPrivateKey(v *ecdsa.PrivateKey) *PutInitPrm { + if p != nil { + p.privateKey = v + } + + return p +} diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 4e655ed541..969c8fa19f 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -47,6 +47,11 @@ func (p *Streamer) Init(ctx context.Context, prm *PutInitPrm) error { return nil } +// Target accesses underlying target chunked object writer. +func (p *Streamer) Target() transformer.ChunkedObjectWriter { + return p.target +} + // MaxObjectSize returns maximum payload size for the streaming session. // // Must be called after the successful Init. @@ -79,11 +84,15 @@ func (p *Streamer) initTarget(prm *PutInitPrm) error { func (p *Streamer) initUntrustedTarget(prm *PutInitPrm) error { p.relay = prm.relay - nodeKey, err := p.cfg.keyStorage.GetKey(nil) - if err != nil { - return err + if prm.privateKey != nil { + p.privateKey = prm.privateKey + } else { + nodeKey, err := p.cfg.keyStorage.GetKey(nil) + if err != nil { + return err + } + p.privateKey = nodeKey } - p.privateKey = nodeKey // prepare untrusted-Put object target p.target = &validatingPreparedTarget{ @@ -136,7 +145,11 @@ func (p *Streamer) initTrustedTarget(prm *PutInitPrm) error { } } - p.privateKey = key + if prm.privateKey != nil { + p.privateKey = prm.privateKey + } else { + p.privateKey = key + } p.target = &validatingTarget{ fmt: p.fmtValidator, nextTarget: transformer.NewPayloadSizeLimiter(transformer.Params{ diff --git a/pkg/services/object/response.go b/pkg/services/object/response.go index c85259c1f7..d7ba9f8433 100644 --- a/pkg/services/object/response.go +++ b/pkg/services/object/response.go @@ -38,7 +38,7 @@ type putStreamResponser struct { } type patchStreamResponser struct { - stream PatchObjectstream + stream PatchObjectStream respSvc *response.Service } @@ -109,7 +109,7 @@ func (s *patchStreamResponser) CloseAndRecv(ctx context.Context) (*object.PatchR return r, nil } -func (s *ResponseService) Patch() (PatchObjectstream, error) { +func (s *ResponseService) Patch() (PatchObjectStream, error) { stream, err := s.svc.Patch() if err != nil { return nil, fmt.Errorf("could not create Put object streamer: %w", err) diff --git a/pkg/services/object/server.go b/pkg/services/object/server.go index c1b036ab33..da98ce245c 100644 --- a/pkg/services/object/server.go +++ b/pkg/services/object/server.go @@ -31,8 +31,8 @@ type PutObjectStream interface { CloseAndRecv(context.Context) (*object.PutResponse, error) } -// PatchObjectstream is an interface of FrostFS API v2 compatible patch streamer. -type PatchObjectstream interface { +// PatchObjectStream is an interface of FrostFS API v2 compatible patch streamer. +type PatchObjectStream interface { Send(context.Context, *object.PatchRequest) error CloseAndRecv(context.Context) (*object.PatchResponse, error) } @@ -42,7 +42,7 @@ type PatchObjectstream interface { type ServiceServer interface { Get(*object.GetRequest, GetObjectStream) error Put() (PutObjectStream, error) - Patch() (PatchObjectstream, error) + Patch() (PatchObjectStream, error) Head(context.Context, *object.HeadRequest) (*object.HeadResponse, error) Search(*object.SearchRequest, SearchStream) error Delete(context.Context, *object.DeleteRequest) (*object.DeleteResponse, error) diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 631c539af3..35367aafe2 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -37,7 +37,7 @@ type putStreamSigner struct { type patchStreamSigner struct { sigSvc *util.SignService - stream PatchObjectstream + stream PatchObjectStream err error } @@ -142,7 +142,7 @@ func (s *patchStreamSigner) CloseAndRecv(ctx context.Context) (resp *object.Patc return resp, s.sigSvc.SignResponse(resp, err) } -func (s *SignService) Patch() (PatchObjectstream, error) { +func (s *SignService) Patch() (PatchObjectStream, error) { stream, err := s.svc.Patch() if err != nil { return nil, fmt.Errorf("could not create Put object streamer: %w", err) diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index 5acfac06b6..e560d6d8c1 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -91,7 +91,7 @@ func (c TransportSplitter) Put() (PutObjectStream, error) { return c.next.Put() } -func (c TransportSplitter) Patch() (PatchObjectstream, error) { +func (c TransportSplitter) Patch() (PatchObjectStream, error) { return c.next.Patch() } From 5ed317e24c8ddc505051a3d012eff73828238a4d Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 13 Aug 2024 15:01:01 +0300 Subject: [PATCH 0742/1413] [#1307] cli: Introduce `object patch` command Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/client.go | 65 ++++++++++ cmd/frostfs-cli/modules/object/patch.go | 151 ++++++++++++++++++++++ cmd/frostfs-cli/modules/object/root.go | 2 + cmd/frostfs-cli/modules/object/util.go | 2 + 4 files changed, 220 insertions(+) create mode 100644 cmd/frostfs-cli/modules/object/patch.go diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 215490dbeb..a0fa224108 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -2,10 +2,13 @@ package internal import ( "bytes" + "cmp" "context" "errors" "fmt" "io" + "os" + "slices" "sort" "strings" @@ -869,3 +872,65 @@ func SyncContainerSettings(ctx context.Context, prm SyncContainerPrm) (*SyncCont return new(SyncContainerRes), nil } + +// PatchObjectPrm groups parameters of PatchObject operation. +type PatchObjectPrm struct { + commonObjectPrm + objectAddressPrm + + NewAttributes []objectSDK.Attribute + + ReplaceAttribute bool + + PayloadPatches []PayloadPatch +} + +type PayloadPatch struct { + Range objectSDK.Range + + PayloadPath string +} + +type PatchRes struct { + OID oid.ID +} + +func Patch(ctx context.Context, prm PatchObjectPrm) (*PatchRes, error) { + patchPrm := client.PrmObjectPatch{ + XHeaders: prm.xHeaders, + BearerToken: prm.bearerToken, + Session: prm.sessionToken, + Address: prm.objAddr, + } + + slices.SortFunc(prm.PayloadPatches, func(a, b PayloadPatch) int { + return cmp.Compare(a.Range.GetOffset(), b.Range.GetOffset()) + }) + + patcher, err := prm.cli.ObjectPatchInit(ctx, patchPrm) + if err != nil { + return nil, fmt.Errorf("init payload reading: %w", err) + } + + if patcher.PatchAttributes(ctx, prm.NewAttributes, prm.ReplaceAttribute) { + for _, pp := range prm.PayloadPatches { + payloadFile, err := os.OpenFile(pp.PayloadPath, os.O_RDONLY, os.ModePerm) + if err != nil { + return nil, err + } + applied := patcher.PatchPayload(ctx, &pp.Range, payloadFile) + _ = payloadFile.Close() + if !applied { + break + } + } + } + + res, err := patcher.Close(ctx) + if err != nil { + return nil, err + } + return &PatchRes{ + OID: res.ObjectID(), + }, nil +} diff --git a/cmd/frostfs-cli/modules/object/patch.go b/cmd/frostfs-cli/modules/object/patch.go new file mode 100644 index 0000000000..8f03885ab8 --- /dev/null +++ b/cmd/frostfs-cli/modules/object/patch.go @@ -0,0 +1,151 @@ +package object + +import ( + "fmt" + "strconv" + "strings" + + internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/spf13/cobra" +) + +const ( + newAttrsFlagName = "new-attrs" + replaceAttrsFlagName = "replace-attrs" + rangeFlagName = "range" + payloadFlagName = "payload" +) + +var objectPatchCmd = &cobra.Command{ + Use: "patch", + Run: patch, + Short: "Patch FrostFS object", + Long: "Patch FrostFS object. Each range passed to the command requires to pass a corresponding patch payload.", + Example: ` +frostfs-cli -c config.yml -r 127.0.0.1:8080 object patch --cid --oid --new-attrs 'key1=val1,key2=val2' --replace-attrs +frostfs-cli -c config.yml -r 127.0.0.1:8080 object patch --cid --oid --range offX:lnX --payload /path/to/payloadX --range offY:lnY --payload /path/to/payloadY +frostfs-cli -c config.yml -r 127.0.0.1:8080 object patch --cid --oid --new-attrs 'key1=val1,key2=val2' --replace-attrs --range offX:lnX --payload /path/to/payload +`, +} + +func initObjectPatchCmd() { + commonflags.Init(objectPatchCmd) + initFlagSession(objectPatchCmd, "PATCH") + + flags := objectPatchCmd.Flags() + + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = objectRangeCmd.MarkFlagRequired(commonflags.CIDFlag) + + flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) + _ = objectRangeCmd.MarkFlagRequired(commonflags.OIDFlag) + + flags.String(newAttrsFlagName, "", "New object attributes in form of Key1=Value1,Key2=Value2") + flags.Bool(replaceAttrsFlagName, false, "Replace object attributes by new ones.") + flags.StringSlice(rangeFlagName, []string{}, "Range to which patch payload is applied. Format: offset:length") + flags.StringSlice(payloadFlagName, []string{}, "Path to file with patch payload.") +} + +func patch(cmd *cobra.Command, _ []string) { + var cnr cid.ID + var obj oid.ID + + objAddr := readObjectAddress(cmd, &cnr, &obj) + + ranges, err := getRangeSlice(cmd) + commonCmd.ExitOnErr(cmd, "", err) + + payloads := patchPayloadPaths(cmd) + + if len(ranges) != len(payloads) { + commonCmd.ExitOnErr(cmd, "", fmt.Errorf("the number of ranges and payloads are not equal: ranges = %d, payloads = %d", len(ranges), len(payloads))) + } + + newAttrs, err := parseNewObjectAttrs(cmd) + commonCmd.ExitOnErr(cmd, "can't parse new object attributes: %w", err) + replaceAttrs, _ := cmd.Flags().GetBool(replaceAttrsFlagName) + + pk := key.GetOrGenerate(cmd) + + cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) + + var prm internalclient.PatchObjectPrm + prm.SetClient(cli) + Prepare(cmd, &prm) + ReadOrOpenSession(cmd, &prm, pk, cnr, nil) + + prm.SetAddress(objAddr) + prm.NewAttributes = newAttrs + prm.ReplaceAttribute = replaceAttrs + + for i := range ranges { + prm.PayloadPatches = append(prm.PayloadPatches, internalclient.PayloadPatch{ + Range: ranges[i], + PayloadPath: payloads[i], + }) + } + + res, err := internalclient.Patch(cmd.Context(), prm) + if err != nil { + commonCmd.ExitOnErr(cmd, "can't patch the object: %w", err) + } + cmd.Println("Patched object ID: ", res.OID.EncodeToString()) +} + +func parseNewObjectAttrs(cmd *cobra.Command) ([]objectSDK.Attribute, error) { + var rawAttrs []string + + raw := cmd.Flag(newAttrsFlagName).Value.String() + if len(raw) != 0 { + rawAttrs = strings.Split(raw, ",") + } + + attrs := make([]objectSDK.Attribute, len(rawAttrs), len(rawAttrs)+2) // name + timestamp attributes + for i := range rawAttrs { + k, v, found := strings.Cut(rawAttrs[i], "=") + if !found { + return nil, fmt.Errorf("invalid attribute format: %s", rawAttrs[i]) + } + attrs[i].SetKey(k) + attrs[i].SetValue(v) + } + return attrs, nil +} + +func getRangeSlice(cmd *cobra.Command) ([]objectSDK.Range, error) { + v, _ := cmd.Flags().GetStringSlice(rangeFlagName) + if len(v) == 0 { + return []objectSDK.Range{}, nil + } + rs := make([]objectSDK.Range, len(v)) + for i := range v { + before, after, found := strings.Cut(v[i], rangeSep) + if !found { + return nil, fmt.Errorf("invalid range specifier: %s", v[i]) + } + + offset, err := strconv.ParseUint(before, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid '%s' range offset specifier: %w", v[i], err) + } + length, err := strconv.ParseUint(after, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid '%s' range length specifier: %w", v[i], err) + } + + rs[i].SetOffset(offset) + rs[i].SetLength(length) + } + return rs, nil +} + +func patchPayloadPaths(cmd *cobra.Command) []string { + v, _ := cmd.Flags().GetStringSlice(payloadFlagName) + return v +} diff --git a/cmd/frostfs-cli/modules/object/root.go b/cmd/frostfs-cli/modules/object/root.go index 7d8008b107..b808a509e7 100644 --- a/cmd/frostfs-cli/modules/object/root.go +++ b/cmd/frostfs-cli/modules/object/root.go @@ -29,6 +29,7 @@ func init() { objectRangeCmd, objectLockCmd, objectNodesCmd, + objectPatchCmd, } Cmd.AddCommand(objectChildCommands...) @@ -39,6 +40,7 @@ func init() { } initObjectPutCmd() + initObjectPatchCmd() initObjectDeleteCmd() initObjectGetCmd() initObjectSearchCmd() diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index 381c790e95..96b80fe1b3 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -306,6 +306,8 @@ func finalizeSession(cmd *cobra.Command, dst SessionPrm, tok *session.Object, ke case *internal.PutObjectPrm: common.PrintVerbose(cmd, "Binding session to object PUT...") tok.ForVerb(session.VerbObjectPut) + case *internal.PatchObjectPrm: + tok.ForVerb(session.VerbObjectPatch) case *internal.DeleteObjectPrm: common.PrintVerbose(cmd, "Binding session to object DELETE...") tok.ForVerb(session.VerbObjectDelete) From eeab417dcf75846b69c0567b118dab5fb27a28a2 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 14 Aug 2024 14:38:01 +0300 Subject: [PATCH 0743/1413] [#1307] object: Add APE check for `Patch` handler Signed-off-by: Airat Arifullin --- pkg/services/object/acl/v2/service.go | 125 +++++++++++++++++++++++- pkg/services/object/acl/v2/util.go | 2 + pkg/services/object/ape/checker_test.go | 19 +--- pkg/services/object/ape/request.go | 3 +- pkg/services/object/ape/service.go | 54 +++++++++- 5 files changed, 183 insertions(+), 20 deletions(-) diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index a9ddad7cab..5a8e8b0655 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -35,6 +35,12 @@ type putStreamBasicChecker struct { next object.PutObjectStream } +type patchStreamBasicChecker struct { + source *Service + next object.PatchObjectStream + nonFirstSend bool +} + type getStreamBasicChecker struct { checker ACLChecker @@ -250,7 +256,12 @@ func (b Service) Put() (object.PutObjectStream, error) { } func (b Service) Patch() (object.PatchObjectStream, error) { - return b.next.Patch() + streamer, err := b.next.Patch() + + return &patchStreamBasicChecker{ + source: &b, + next: streamer, + }, err } func (b Service) Head( @@ -738,6 +749,65 @@ func (g *searchStreamBasicChecker) Send(resp *objectV2.SearchResponse) error { return g.SearchStream.Send(resp) } +func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { + body := request.GetBody() + if body == nil { + return errEmptyBody + } + + if !p.nonFirstSend { + p.nonFirstSend = true + + cnr, err := getContainerIDFromRequest(request) + if err != nil { + return err + } + + objV2 := request.GetBody().GetAddress().GetObjectID() + if objV2 == nil { + return errors.New("missing oid") + } + obj := new(oid.ID) + err = obj.ReadFromV2(*objV2) + if err != nil { + return err + } + + var sTok *sessionSDK.Object + sTok, err = readSessionToken(cnr, obj, request.GetMetaHeader().GetSessionToken()) + if err != nil { + return err + } + + bTok, err := originalBearerToken(request.GetMetaHeader()) + if err != nil { + return err + } + + req := MetaWithToken{ + vheader: request.GetVerificationHeader(), + token: sTok, + bearer: bTok, + src: request, + } + + reqInfo, err := p.source.findRequestInfoWithoutACLOperationAssert(req, cnr) + if err != nil { + return err + } + + reqInfo.obj = obj + + ctx = requestContext(ctx, reqInfo) + } + + return p.next.Send(ctx, request) +} + +func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { + return p.next.CloseAndRecv(ctx) +} + func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (info RequestInfo, err error) { cnr, err := b.containers.Get(idCnr) // fetch actual container if err != nil { @@ -794,3 +864,56 @@ func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (in return info, nil } + +// findRequestInfoWithoutACLOperationAssert is findRequestInfo without session token verb assert. +func (b Service) findRequestInfoWithoutACLOperationAssert(req MetaWithToken, idCnr cid.ID) (info RequestInfo, err error) { + cnr, err := b.containers.Get(idCnr) // fetch actual container + if err != nil { + return info, err + } + + if req.token != nil { + currentEpoch, err := b.nm.Epoch() + if err != nil { + return info, errors.New("can't fetch current epoch") + } + if req.token.ExpiredAt(currentEpoch) { + return info, new(apistatus.SessionTokenExpired) + } + if req.token.InvalidAt(currentEpoch) { + return info, fmt.Errorf("%s: token is invalid at %d epoch)", + invalidRequestMessage, currentEpoch) + } + } + + // find request role and key + ownerID, ownerKey, err := req.RequestOwner() + if err != nil { + return info, err + } + res, err := b.c.Classify(ownerID, ownerKey, idCnr, cnr.Value) + if err != nil { + return info, err + } + + info.basicACL = cnr.Value.BasicACL() + info.requestRole = res.Role + info.cnrOwner = cnr.Value.Owner() + info.idCnr = idCnr + + cnrNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cnr.Value).Zone(), ".ns") + if hasNamespace { + info.cnrNamespace = cnrNamespace + } + + // it is assumed that at the moment the key will be valid, + // otherwise the request would not pass validation + info.senderKey = res.Key + + // add bearer token if it is present in request + info.bearer = req.bearer + + info.srcRequest = req.src + + return info, nil +} diff --git a/pkg/services/object/acl/v2/util.go b/pkg/services/object/acl/v2/util.go index 76fd9651d3..c5225e8c40 100644 --- a/pkg/services/object/acl/v2/util.go +++ b/pkg/services/object/acl/v2/util.go @@ -46,6 +46,8 @@ func getContainerIDFromRequest(req any) (cid.ID, error) { idV2 = v.GetBody().GetAddress().GetContainerID() case *objectV2.PutSingleRequest: idV2 = v.GetBody().GetObject().GetHeader().GetContainerID() + case *objectV2.PatchRequest: + idV2 = v.GetBody().GetAddress().GetContainerID() default: return cid.ID{}, errors.New("unknown request type") } diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index afe19fc513..090f6a83ca 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -518,22 +518,7 @@ func TestAPECheck_BearerTokenOverrides(t *testing.T) { ls := inmemory.NewInmemoryLocalStorage() ms := inmemory.NewInmemoryMorphRuleChainStorage() - node1Key, err := keys.NewPrivateKey() - require.NoError(t, err) - node1 := netmapSDK.NodeInfo{} - node1.SetPublicKey(node1Key.PublicKey().Bytes()) - netmap := &netmapSDK.NetMap{} - netmap.SetEpoch(100) - netmap.SetNodes([]netmapSDK.NodeInfo{node1}) - - nm := &netmapStub{ - currentEpoch: 100, - netmaps: map[uint64]*netmapSDK.NetMap{ - 100: netmap, - }, - } - - checker := NewChecker(ls, ms, headerProvider, frostfsidProvider, nm, &stMock{}, nil, nil) + checker := NewChecker(ls, ms, headerProvider, frostfsidProvider, nil, &stMock{}, nil, nil) prm := Prm{ Method: method, @@ -556,7 +541,7 @@ func TestAPECheck_BearerTokenOverrides(t *testing.T) { } } - err = checker.CheckAPE(context.Background(), prm) + err := checker.CheckAPE(context.Background(), prm) if test.expectAPEErr { require.Error(t, err) } else { diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 1c129f65f2..da5307ca7b 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -103,7 +103,8 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re nativeschema.MethodHeadObject, nativeschema.MethodRangeObject, nativeschema.MethodHashObject, - nativeschema.MethodDeleteObject: + nativeschema.MethodDeleteObject, + nativeschema.MethodPatchObject: if prm.Object == nil { return defaultRequest, fmt.Errorf("method %s: %w", prm.Method, errMissingOID) } diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 64dd19c24c..a1634e7c5e 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -204,8 +204,60 @@ func (c *Service) Put() (objectSvc.PutObjectStream, error) { }, err } +type patchStreamBasicChecker struct { + apeChecker Checker + + next objectSvc.PatchObjectStream + + nonFirstSend bool +} + +func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { + if !p.nonFirstSend { + p.nonFirstSend = true + + reqCtx, err := requestContext(ctx) + if err != nil { + return toStatusErr(err) + } + + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + if err != nil { + return toStatusErr(err) + } + + prm := Prm{ + Namespace: reqCtx.Namespace, + Container: cnrID, + Object: objID, + Method: nativeschema.MethodPatchObject, + SenderKey: hex.EncodeToString(reqCtx.SenderKey), + ContainerOwner: reqCtx.ContainerOwner, + Role: nativeSchemaRole(reqCtx.Role), + SoftAPECheck: reqCtx.SoftAPECheck, + BearerToken: reqCtx.BearerToken, + XHeaders: request.GetMetaHeader().GetXHeaders(), + } + + if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { + return toStatusErr(err) + } + } + + return p.next.Send(ctx, request) +} + +func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { + return p.next.CloseAndRecv(ctx) +} + func (c *Service) Patch() (objectSvc.PatchObjectStream, error) { - return c.next.Patch() + streamer, err := c.next.Patch() + + return &patchStreamBasicChecker{ + apeChecker: c.apeChecker, + next: streamer, + }, err } func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { From 41104f2383226b9e92c13b1907403c3f9176bbae Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 14 Aug 2024 14:39:13 +0300 Subject: [PATCH 0744/1413] [#1307] cli: Make cli process object.patch Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/util/ape.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 532dc0a501..9af57434ab 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -239,6 +239,8 @@ func parseAction(lexeme string) ([]string, bool, error) { return []string{nativeschema.MethodRangeObject}, true, nil case "object.hash": return []string{nativeschema.MethodHashObject}, true, nil + case "object.patch": + return []string{nativeschema.MethodPatchObject}, true, nil case "object.*": return []string{ nativeschema.MethodPutObject, @@ -248,6 +250,7 @@ func parseAction(lexeme string) ([]string, bool, error) { nativeschema.MethodSearchObject, nativeschema.MethodRangeObject, nativeschema.MethodHashObject, + nativeschema.MethodPatchObject, }, true, nil case "container.put": return []string{nativeschema.MethodPutContainer}, false, nil From b7acb34fa4377a690f5f7fbe18c580c2d785b772 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 19 Aug 2024 15:50:35 +0300 Subject: [PATCH 0745/1413] [#1319] treeSvc: Do not wrap error from APE Signed-off-by: Dmitrii Stepanov --- pkg/services/tree/ape.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 6e78bf4ecb..ee4687911f 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -138,7 +138,7 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, request, err := s.newAPERequest(ctx, namespace, cid, operation, role, publicKey) if err != nil { - return apeErr(err) + return fmt.Errorf("failed to create ape request: %w", err) } var cr engine.ChainRouter @@ -167,7 +167,7 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, rt := engine.NewRequestTargetExtended(namespace, cid.EncodeToString(), fmt.Sprintf("%s:%s", namespace, publicKey.Address()), groups) status, found, err := cr.IsAllowed(apechain.Ingress, rt, request) if err != nil { - return apeErr(err) + return err } if found && status == apechain.Allow { return nil From 8319b59238925960597650d3227310d8b6f187ec Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 19 Aug 2024 12:33:15 +0300 Subject: [PATCH 0746/1413] [#1318] Fix gofumpt issue Signed-off-by: Anton Nikiforov --- pkg/services/object/metrics.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/services/object/metrics.go b/pkg/services/object/metrics.go index e53b7584f3..61aed50035 100644 --- a/pkg/services/object/metrics.go +++ b/pkg/services/object/metrics.go @@ -213,6 +213,7 @@ func (s putStreamMetric) CloseAndRecv(ctx context.Context) (*object.PutResponse, return res, err } + func (s patchStreamMetric) Send(ctx context.Context, req *object.PatchRequest) error { s.metrics.AddPayloadSize("Patch", len(req.GetBody().GetPatch().GetChunk())) From 6ff0b0996b31d0de3bbb12d41edb19bdd0c16dda Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 19 Aug 2024 12:34:05 +0300 Subject: [PATCH 0747/1413] [#1318] metrics: Fix `container_size_bytes` for EC When node put chunk into EC container, `policer` may remove it as redundant. This chunk marked as removed. When parent object removed and `gc` start iterating over chunk, node count removing chunk twice. Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/metabase/inhume.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index c265fb2173..b62accc43e 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -236,7 +236,7 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes return err } } else if errors.As(err, &ecErr) { - err = db.inhumeECInfo(tx, epoch, prm.tomb, res, garbageBKT, graveyardBKT, ecErr.ECInfo(), cnr, bkt, value, targetKey) + err = db.inhumeECInfo(tx, epoch, prm.tomb, res, garbageBKT, graveyardBKT, ecErr.ECInfo(), cnr, bkt, value) if err != nil { return err } @@ -280,7 +280,7 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes func (db *DB) inhumeECInfo(tx *bbolt.Tx, epoch uint64, tomb *oid.Address, res *InhumeRes, garbageBKT *bbolt.Bucket, graveyardBKT *bbolt.Bucket, - ecInfo *objectSDK.ECInfo, cnr cid.ID, targetBucket *bbolt.Bucket, value []byte, targetKey []byte, + ecInfo *objectSDK.ECInfo, cnr cid.ID, targetBucket *bbolt.Bucket, value []byte, ) error { for _, chunk := range ecInfo.Chunks { chunkBuf := make([]byte, addressKeySize) @@ -296,11 +296,11 @@ func (db *DB) inhumeECInfo(tx *bbolt.Tx, epoch uint64, tomb *oid.Address, res *I if err != nil { return err } - err = db.updateDeleteInfo(tx, garbageBKT, graveyardBKT, targetKey, cnr, chunkObj, res) + chunkKey := addressKey(chunkAddr, chunkBuf) + err = db.updateDeleteInfo(tx, garbageBKT, graveyardBKT, chunkKey, cnr, chunkObj, res) if err != nil { return err } - chunkKey := addressKey(chunkAddr, chunkBuf) if tomb != nil { _, err = db.markAsGC(graveyardBKT, garbageBKT, chunkKey) if err != nil { From cfda9003a7d4283946e9cbe742702114f93bbdce Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 20 Aug 2024 16:18:46 +0300 Subject: [PATCH 0748/1413] [#1318] meta: Add test `TestInhumeECObject` Signed-off-by: Anton Nikiforov --- .../metabase/inhume_ec_test.go | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 pkg/local_object_storage/metabase/inhume_ec_test.go diff --git a/pkg/local_object_storage/metabase/inhume_ec_test.go b/pkg/local_object_storage/metabase/inhume_ec_test.go new file mode 100644 index 0000000000..c3b1e72da2 --- /dev/null +++ b/pkg/local_object_storage/metabase/inhume_ec_test.go @@ -0,0 +1,116 @@ +package meta + +import ( + "context" + "path/filepath" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "github.com/stretchr/testify/require" +) + +func TestInhumeECObject(t *testing.T) { + t.Parallel() + + db := New( + WithPath(filepath.Join(t.TempDir(), "metabase")), + WithPermissions(0o600), + WithEpochState(epochState{uint64(12)}), + ) + + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.Init()) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + ecChunk := oidtest.ID() + ecChunk2 := oidtest.ID() + ecParent := oidtest.ID() + tombstoneID := oidtest.ID() + + chunkObj := testutil.GenerateObjectWithCID(cnr) + chunkObj.SetContainerID(cnr) + chunkObj.SetID(ecChunk) + chunkObj.SetPayload([]byte{0, 1, 2, 3, 4}) + chunkObj.SetPayloadSize(uint64(5)) + chunkObj.SetECHeader(objectSDK.NewECHeader(objectSDK.ECParentInfo{ID: ecParent}, 0, 3, []byte{}, 0)) + + chunkObj2 := testutil.GenerateObjectWithCID(cnr) + chunkObj2.SetContainerID(cnr) + chunkObj2.SetID(ecChunk2) + chunkObj2.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) + chunkObj2.SetPayloadSize(uint64(10)) + chunkObj2.SetECHeader(objectSDK.NewECHeader(objectSDK.ECParentInfo{ID: ecParent}, 1, 3, []byte{}, 0)) + + // put object with EC + + var prm PutPrm + prm.SetObject(chunkObj) + prm.SetStorageID([]byte("0/0")) + _, err := db.Put(context.Background(), prm) + require.NoError(t, err) + + prm.SetObject(chunkObj2) + _, err = db.Put(context.Background(), prm) + require.NoError(t, err) + + var ecChunkAddress oid.Address + ecChunkAddress.SetContainer(cnr) + ecChunkAddress.SetObject(ecChunk) + + var ecParentAddress oid.Address + ecParentAddress.SetContainer(cnr) + ecParentAddress.SetObject(ecParent) + + var chunkObjectAddress oid.Address + chunkObjectAddress.SetContainer(cnr) + chunkObjectAddress.SetObject(ecChunk) + + var getPrm GetPrm + + getPrm.SetAddress(ecChunkAddress) + _, err = db.Get(context.Background(), getPrm) + require.NoError(t, err) + + var ecInfoError *objectSDK.ECInfoError + getPrm.SetAddress(ecParentAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, &ecInfoError) + require.True(t, len(ecInfoError.ECInfo().Chunks) == 2 && + ecInfoError.ECInfo().Chunks[0].Index == 0 && + ecInfoError.ECInfo().Chunks[0].Total == 3) + + // inhume Chunk + var inhumePrm InhumePrm + var tombAddress oid.Address + inhumePrm.SetAddresses(chunkObjectAddress) + res, err := db.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + require.True(t, len(res.deletionDetails) == 1) + require.True(t, res.deletionDetails[0].Size == 5) + + // inhume EC parent (like Delete does) + tombAddress.SetContainer(cnr) + tombAddress.SetObject(tombstoneID) + inhumePrm.SetAddresses(ecParentAddress) + inhumePrm.SetTombstoneAddress(tombAddress) + res, err = db.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + // Previously deleted chunk shouldn't be in the details, because it is marked as garbage + require.True(t, len(res.deletionDetails) == 1) + require.True(t, res.deletionDetails[0].Size == 10) + + getPrm.SetAddress(ecParentAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved)) + + getPrm.SetAddress(ecChunkAddress) + _, err = db.Get(context.Background(), getPrm) + require.ErrorAs(t, err, new(*apistatus.ObjectAlreadyRemoved)) +} From 8c1082b31a990273020bde006f63d160b51620df Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 20 Aug 2024 15:35:45 +0300 Subject: [PATCH 0749/1413] [#1316] go.mod: Bump go version to 1.22 Signed-off-by: Ekaterina Lebedeva --- .forgejo/workflows/build.yml | 2 +- .forgejo/workflows/pre-commit.yml | 2 +- .forgejo/workflows/tests.yml | 12 ++++++------ .forgejo/workflows/vulncheck.yml | 2 +- Makefile | 8 ++++---- README.md | 2 +- go.mod | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 86943fe88c..ce2d64dd99 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.21', '1.22' ] + go_versions: [ '1.22', '1.23' ] steps: - uses: actions/checkout@v3 diff --git a/.forgejo/workflows/pre-commit.yml b/.forgejo/workflows/pre-commit.yml index 117cda93bb..8b06a2fdfb 100644 --- a/.forgejo/workflows/pre-commit.yml +++ b/.forgejo/workflows/pre-commit.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.22 + go-version: 1.23 - name: Set up Python run: | apt update diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index 5d64d7bc44..a908c62781 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.23' cache: true - name: Install linters @@ -25,7 +25,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.21', '1.22' ] + go_versions: [ '1.22', '1.23' ] fail-fast: false steps: - uses: actions/checkout@v3 @@ -48,7 +48,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' cache: true - name: Run tests @@ -63,7 +63,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.23' cache: true - name: Install staticcheck @@ -81,7 +81,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.21' + go-version: '1.22' cache: true - name: Install gopls @@ -99,7 +99,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.23' cache: true - name: Install gofumpt diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index 3af564c4b5..2951a80595 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -13,7 +13,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.23' - name: Install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest diff --git a/Makefile b/Makefile index 11111d9a7e..8d1238b6f3 100755 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ HUB_IMAGE ?= truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.22 -LINT_VERSION ?= 1.56.1 -TRUECLOUDLAB_LINT_VERSION ?= 0.0.5 +LINT_VERSION ?= 1.60.1 +TRUECLOUDLAB_LINT_VERSION ?= 0.0.6 PROTOC_VERSION ?= 25.0 PROTOC_GEN_GO_VERSION ?= $(shell go list -f '{{.Version}}' -m google.golang.org/protobuf) PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) @@ -17,7 +17,7 @@ PROTOC_OS_VERSION=osx-x86_64 ifeq ($(shell uname), Linux) PROTOC_OS_VERSION=linux-x86_64 endif -STATICCHECK_VERSION ?= 2023.1.6 +STATICCHECK_VERSION ?= 2024.1.1 ARCH = amd64 BIN = bin @@ -46,7 +46,7 @@ STATICCHECK_VERSION_DIR ?= $(STATICCHECK_DIR)/$(STATICCHECK_VERSION) SOURCES = $(shell find . -type f -name "*.go" -print) -GOFUMPT_VERSION ?= v0.6.0 +GOFUMPT_VERSION ?= v0.7.0 GOFUMPT_DIR ?= $(abspath $(BIN))/gofumpt GOFUMPT_VERSION_DIR ?= $(GOFUMPT_DIR)/$(GOFUMPT_VERSION) diff --git a/README.md b/README.md index 413010372b..8225f56c50 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The latest version of frostfs-node works with frostfs-contract # Building -To make all binaries you need Go 1.21+ and `make`: +To make all binaries you need Go 1.22+ and `make`: ``` make all ``` diff --git a/go.mod b/go.mod index 93ed7d7505..79dcc95532 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.frostfs.info/TrueCloudLab/frostfs-node -go 1.21 +go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 From a345c972bffd63c5df513a4e6770b5bc12811e3b Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 20 Aug 2024 18:37:04 +0300 Subject: [PATCH 0750/1413] [#1316] lint: Fix warnings Renamed parameters `min/max` to avoid conflicts with predeclared identifiers. Replaced background context with parent context without cancellation in closer functions in frostfs-node. Signed-off-by: Ekaterina Lebedeva --- .golangci.yml | 3 ++- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/tracing.go | 2 +- .../blobstor/internal/blobstortest/common.go | 16 ++++++++-------- .../blobstor/internal/blobstortest/control.go | 6 +++--- .../blobstor/internal/blobstortest/delete.go | 4 ++-- .../blobstor/internal/blobstortest/exists.go | 4 ++-- .../blobstor/internal/blobstortest/get.go | 4 ++-- .../blobstor/internal/blobstortest/get_range.go | 4 ++-- .../blobstor/internal/blobstortest/iterate.go | 4 ++-- pkg/morph/client/notary.go | 4 ++-- 11 files changed, 27 insertions(+), 26 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d209693aa2..2e9e78fc3b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,7 +12,8 @@ run: # output configuration options output: # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" - format: tab + formats: + - format: tab # all available settings of specific linters linters-settings: diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 1af27d7330..1102814185 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1073,7 +1073,7 @@ func initLocalStorage(ctx context.Context, c *cfg) { c.onShutdown(func() { c.log.Info(logs.FrostFSNodeClosingComponentsOfTheStorageEngine) - err := ls.Close(context.Background()) + err := ls.Close(context.WithoutCancel(ctx)) if err != nil { c.log.Info(logs.FrostFSNodeStorageEngineClosingFailure, zap.String("error", err.Error()), diff --git a/cmd/frostfs-node/tracing.go b/cmd/frostfs-node/tracing.go index 312adfb8d3..675c31374f 100644 --- a/cmd/frostfs-node/tracing.go +++ b/cmd/frostfs-node/tracing.go @@ -21,7 +21,7 @@ func initTracing(ctx context.Context, c *cfg) { c.closers = append(c.closers, closer{ name: "tracing", fn: func() { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) + ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), time.Second*5) defer cancel() err := tracing.Shutdown(ctx) // cfg context cancels before close if err != nil { diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/common.go b/pkg/local_object_storage/blobstor/internal/blobstortest/common.go index c08e39bf15..5d14a9a3ae 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/common.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/common.go @@ -27,21 +27,21 @@ type objectDesc struct { storageID []byte } -func TestAll(t *testing.T, cons Constructor, min, max uint64) { +func TestAll(t *testing.T, cons Constructor, minSize, maxSize uint64) { t.Run("get", func(t *testing.T) { - TestGet(t, cons, min, max) + TestGet(t, cons, minSize, maxSize) }) t.Run("get range", func(t *testing.T) { - TestGetRange(t, cons, min, max) + TestGetRange(t, cons, minSize, maxSize) }) t.Run("delete", func(t *testing.T) { - TestDelete(t, cons, min, max) + TestDelete(t, cons, minSize, maxSize) }) t.Run("exists", func(t *testing.T) { - TestExists(t, cons, min, max) + TestExists(t, cons, minSize, maxSize) }) t.Run("iterate", func(t *testing.T) { - TestIterate(t, cons, min, max) + TestIterate(t, cons, minSize, maxSize) }) } @@ -51,12 +51,12 @@ func TestInfo(t *testing.T, cons Constructor, expectedType string, expectedPath require.Equal(t, expectedPath, s.Path()) } -func prepare(t *testing.T, count int, s common.Storage, min, max uint64) []objectDesc { +func prepare(t *testing.T, count int, s common.Storage, minSize, maxSize uint64) []objectDesc { objects := make([]objectDesc, count) r := mrand.New(mrand.NewSource(0)) for i := range objects { - objects[i].obj = NewObject(min + uint64(r.Intn(int(max-min+1)))) // not too large + objects[i].obj = NewObject(minSize + uint64(r.Intn(int(maxSize-minSize+1)))) // not too large objects[i].addr = objectCore.AddressOf(objects[i].obj) raw, err := objects[i].obj.Marshal() diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/control.go b/pkg/local_object_storage/blobstor/internal/blobstortest/control.go index a3bbc021d9..21c80b0898 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/control.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/control.go @@ -13,12 +13,12 @@ import ( // TestControl checks correctness of a read-only mode. // cons must return a storage which is NOT opened. -func TestControl(t *testing.T, cons Constructor, min, max uint64) { +func TestControl(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) - objects := prepare(t, 10, s, min, max) + objects := prepare(t, 10, s, minSize, maxSize) require.NoError(t, s.Close()) require.NoError(t, s.Open(mode.ComponentReadOnly)) @@ -34,7 +34,7 @@ func TestControl(t *testing.T, cons Constructor, min, max uint64) { t.Run("put fails", func(t *testing.T) { var prm common.PutPrm - prm.Object = NewObject(min + uint64(rand.Intn(int(max-min+1)))) + prm.Object = NewObject(minSize + uint64(rand.Intn(int(maxSize-minSize+1)))) prm.Address = objectCore.AddressOf(prm.Object) _, err := s.Put(context.Background(), prm) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go index 750619a30a..cf4e765132 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go @@ -11,13 +11,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestDelete(t *testing.T, cons Constructor, min, max uint64) { +func TestDelete(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() - objects := prepare(t, 4, s, min, max) + objects := prepare(t, 4, s, minSize, maxSize) t.Run("delete non-existent", func(t *testing.T) { var prm common.DeletePrm diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go index 33b50b12fd..08465ed5ea 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go @@ -10,13 +10,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestExists(t *testing.T, cons Constructor, min, max uint64) { +func TestExists(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() - objects := prepare(t, 1, s, min, max) + objects := prepare(t, 1, s, minSize, maxSize) t.Run("missing object", func(t *testing.T) { prm := common.ExistsPrm{Address: oidtest.Address()} diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go index 12f73c3e9a..d1f709b0cd 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go @@ -11,13 +11,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestGet(t *testing.T, cons Constructor, min, max uint64) { +func TestGet(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() - objects := prepare(t, 2, s, min, max) + objects := prepare(t, 2, s, minSize, maxSize) t.Run("missing object", func(t *testing.T) { gPrm := common.GetPrm{Address: oidtest.Address()} diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go index 93de683c21..fcbeddac74 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go @@ -13,13 +13,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestGetRange(t *testing.T, cons Constructor, min, max uint64) { +func TestGetRange(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() - objects := prepare(t, 1, s, min, max) + objects := prepare(t, 1, s, minSize, maxSize) t.Run("missing object", func(t *testing.T) { gPrm := common.GetRangePrm{Address: oidtest.Address()} diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index e66fe87b6b..3a6c8b699d 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -10,13 +10,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestIterate(t *testing.T, cons Constructor, min, max uint64) { +func TestIterate(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) defer func() { require.NoError(t, s.Close()) }() - objects := prepare(t, 10, s, min, max) + objects := prepare(t, 10, s, minSize, maxSize) // Delete random object to ensure it is not iterated over. const delID = 2 diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 4865b43ef1..616b3b5c3e 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -641,8 +641,8 @@ func (c *Client) notaryTxValidationLimit() (uint32, error) { return 0, fmt.Errorf("can't get current blockchain height: %w", err) } - min := bc + c.notary.txValidTime - rounded := (min/c.notary.roundTime + 1) * c.notary.roundTime + minTime := bc + c.notary.txValidTime + rounded := (minTime/c.notary.roundTime + 1) * c.notary.roundTime return rounded, nil } From 7bca428db03716e37e1fec315ef974886a2e9fea Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 19 Aug 2024 18:28:53 +0300 Subject: [PATCH 0751/1413] [#1322] Use new protobuf marshaler Signed-off-by: Evgenii Stratonikov --- Makefile | 8 +- .../modules/control/set_netmap_status.go | 2 +- .../modules/control/shards_set_mode.go | 4 +- cmd/frostfs-cli/modules/control/util.go | 4 +- cmd/frostfs-node/netmap.go | 2 +- go.mod | 7 +- go.sum | 10 +- pkg/local_object_storage/metabase/get.go | 7 +- pkg/services/control/common_test.go | 33 - pkg/services/control/ir/service.go | 46 - pkg/services/control/ir/service.pb.go | 1277 -- pkg/services/control/ir/service_frostfs.pb.go | 2584 ++- pkg/services/control/ir/service_test.go | 44 - pkg/services/control/ir/types.go | 15 - pkg/services/control/ir/types.pb.go | 230 - pkg/services/control/ir/types_frostfs.pb.go | 218 +- pkg/services/control/server/list_shards.go | 4 +- pkg/services/control/service.go | 142 - pkg/services/control/service.pb.go | 7094 -------- pkg/services/control/service_frostfs.pb.go | 14829 ++++++++++++++-- pkg/services/control/service_test.go | 181 - pkg/services/control/types.go | 118 - pkg/services/control/types.pb.go | 1011 -- pkg/services/control/types_frostfs.pb.go | 1721 +- pkg/services/control/types_test.go | 151 - pkg/services/tree/service.pb.go | 3587 ---- pkg/services/tree/service_frostfs.pb.go | 7928 ++++++++- pkg/services/tree/types.pb.go | 320 - pkg/services/tree/types_frostfs.pb.go | 537 +- 29 files changed, 24581 insertions(+), 17533 deletions(-) delete mode 100644 pkg/services/control/common_test.go delete mode 100644 pkg/services/control/ir/service.go delete mode 100644 pkg/services/control/ir/service.pb.go delete mode 100644 pkg/services/control/ir/service_test.go delete mode 100644 pkg/services/control/ir/types.go delete mode 100644 pkg/services/control/ir/types.pb.go delete mode 100644 pkg/services/control/service.go delete mode 100644 pkg/services/control/service.pb.go delete mode 100644 pkg/services/control/service_test.go delete mode 100644 pkg/services/control/types.go delete mode 100644 pkg/services/control/types.pb.go delete mode 100644 pkg/services/control/types_test.go delete mode 100644 pkg/services/tree/service.pb.go delete mode 100644 pkg/services/tree/types.pb.go diff --git a/Makefile b/Makefile index 8d1238b6f3..94a8a14c36 100755 --- a/Makefile +++ b/Makefile @@ -11,7 +11,6 @@ GO_VERSION ?= 1.22 LINT_VERSION ?= 1.60.1 TRUECLOUDLAB_LINT_VERSION ?= 0.0.6 PROTOC_VERSION ?= 25.0 -PROTOC_GEN_GO_VERSION ?= $(shell go list -f '{{.Version}}' -m google.golang.org/protobuf) PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) PROTOC_OS_VERSION=osx-x86_64 ifeq ($(shell uname), Linux) @@ -39,7 +38,6 @@ LINT_DIR = $(OUTPUT_LINT_DIR)/golangci-lint-$(LINT_VERSION)-v$(TRUECLOUDLAB_LINT TMP_DIR := .cache PROTOBUF_DIR ?= $(abspath $(BIN))/protobuf PROTOC_DIR ?= $(PROTOBUF_DIR)/protoc-v$(PROTOC_VERSION) -PROTOC_GEN_GO_DIR ?= $(PROTOBUF_DIR)/protoc-gen-go-$(PROTOC_GEN_GO_VERSION) PROTOGEN_FROSTFS_DIR ?= $(PROTOBUF_DIR)/protogen-$(PROTOGEN_FROSTFS_VERSION) STATICCHECK_DIR ?= $(abspath $(BIN))/staticcheck STATICCHECK_VERSION_DIR ?= $(STATICCHECK_DIR)/$(STATICCHECK_VERSION) @@ -107,17 +105,15 @@ export-metrics: dep # Regenerate proto files: protoc: - @if [ ! -d "$(PROTOC_DIR)" ] || [ ! -d "$(PROTOC_GEN_GO_DIR)" ] || [ ! -d "$(PROTOGEN_FROSTFS_DIR)" ]; then \ + @if [ ! -d "$(PROTOC_DIR)" ] || [ ! -d "$(PROTOGEN_FROSTFS_DIR)" ]; then \ make protoc-install; \ fi @for f in `find . -type f -name '*.proto' -not -path './bin/*'`; do \ echo "⇒ Processing $$f "; \ $(PROTOC_DIR)/bin/protoc \ --proto_path=.:$(PROTOC_DIR)/include:/usr/local/include \ - --plugin=protoc-gen-go=$(PROTOC_GEN_GO_DIR)/protoc-gen-go \ --plugin=protoc-gen-go-frostfs=$(PROTOGEN_FROSTFS_DIR)/protogen \ --go-frostfs_out=. --go-frostfs_opt=paths=source_relative \ - --go_out=. --go_opt=paths=source_relative \ --go-grpc_opt=require_unimplemented_servers=false \ --go-grpc_out=. --go-grpc_opt=paths=source_relative $$f; \ done @@ -130,8 +126,6 @@ protoc-install: @wget -q -O $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip 'https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(PROTOC_OS_VERSION).zip' @unzip -q -o $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip -d $(PROTOC_DIR) @rm $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip - @echo "⇒ Installing protoc-gen-go..." - @GOBIN=$(PROTOC_GEN_GO_DIR) go install -v google.golang.org/protobuf/...@$(PROTOC_GEN_GO_VERSION) @echo "⇒ Instaling protogen FrostFS plugin..." @GOBIN=$(PROTOGEN_FROSTFS_DIR) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/protogen@$(PROTOGEN_FROSTFS_VERSION) diff --git a/cmd/frostfs-cli/modules/control/set_netmap_status.go b/cmd/frostfs-cli/modules/control/set_netmap_status.go index 31ade1eb90..a107b2b531 100644 --- a/cmd/frostfs-cli/modules/control/set_netmap_status.go +++ b/cmd/frostfs-cli/modules/control/set_netmap_status.go @@ -84,7 +84,7 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) { body.SetStatus(control.NetmapStatus_MAINTENANCE) if force { - body.SetForceMaintenance() + body.SetForceMaintenance(true) common.PrintVerbose(cmd, "Local maintenance will be forced.") } targetStatus = control.NetmapStatus_MAINTENANCE diff --git a/cmd/frostfs-cli/modules/control/shards_set_mode.go b/cmd/frostfs-cli/modules/control/shards_set_mode.go index e73f15178c..dd0d77748b 100644 --- a/cmd/frostfs-cli/modules/control/shards_set_mode.go +++ b/cmd/frostfs-cli/modules/control/shards_set_mode.go @@ -117,10 +117,10 @@ func setShardMode(cmd *cobra.Command, _ []string) { req.SetBody(body) body.SetMode(mode) - body.SetShardIDList(getShardIDList(cmd)) + body.SetShard_ID(getShardIDList(cmd)) reset, _ := cmd.Flags().GetBool(shardClearErrorsFlag) - body.ClearErrorCounter(reset) + body.SetResetErrorCounter(reset) signRequest(cmd, pk, req) diff --git a/cmd/frostfs-cli/modules/control/util.go b/cmd/frostfs-cli/modules/control/util.go index c0577ac0c6..ef547681f3 100644 --- a/cmd/frostfs-cli/modules/control/util.go +++ b/cmd/frostfs-cli/modules/control/util.go @@ -44,7 +44,7 @@ func verifyResponse(cmd *cobra.Command, GetSign() []byte }, body interface { - StableMarshal([]byte) []byte + MarshalProtobuf([]byte) []byte }, ) { if sigControl == nil { @@ -60,7 +60,7 @@ func verifyResponse(cmd *cobra.Command, var sig frostfscrypto.Signature commonCmd.ExitOnErr(cmd, "can't read signature: %w", sig.ReadFromV2(sigV2)) - if !sig.Verify(body.StableMarshal(nil)) { + if !sig.Verify(body.MarshalProtobuf(nil)) { commonCmd.ExitOnErr(cmd, "", errors.New("invalid response signature")) } } diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 128cc30054..8104b1dc1f 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -84,7 +84,7 @@ func (s *networkState) setNodeInfo(ni *netmapSDK.NodeInfo) { } } - s.setControlNetmapStatus(ctrlNetSt) + s.setControlNetmapStatus(control.NetmapStatus(ctrlNetSt)) } // sets the current node state to the given value. Subsequent cfg.bootstrap diff --git a/go.mod b/go.mod index 79dcc95532..b665709cc3 100644 --- a/go.mod +++ b/go.mod @@ -4,16 +4,17 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240813155151-d112a28d382f + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240819074700-a43110e36326 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240813155821-98aabc45a720 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240820072028-6dd7be11d13b git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 + github.com/VictoriaMetrics/easyproto v0.1.4 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 @@ -21,6 +22,7 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/klauspost/compress v1.17.4 + github.com/mailru/easyjson v0.7.7 github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.12.1 @@ -84,7 +86,6 @@ require ( github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/klauspost/reedsolomon v1.12.1 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect diff --git a/go.sum b/go.sum index 803a065c3d..54e0d0301a 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240813155151-d112a28d382f h1:xrJqsXOZeSkBFMSyN+PQ9DiCGxVULU3VIN/tuH/vtb8= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240813155151-d112a28d382f/go.mod h1:mc7j6Cc1GU1tJZNmDwEYiJJ339biNnU1Bz3wZGogMe0= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240819074700-a43110e36326 h1:TkH+NSsY4C/Z8MocIJyMcqLm5vEhZcSowOldJyilKKA= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240819074700-a43110e36326/go.mod h1:zZnHiRv9m5+ESYLhBXY9Jds9A/YIDEUGiuyPUS09HwM= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240813155821-98aabc45a720 h1:15UXpW42bfshIv/X5kww92jG2o0drHgsdFd+UJ6zD7g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240813155821-98aabc45a720/go.mod h1:XRX/bBQsDJKr040N/a0YnDhxJqaUv1XyMVj3qxnb5K0= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240820072028-6dd7be11d13b h1:ZCJBVmQDcdv0twpX9xJU/AQwX+dXyvVfqr0Pq3x+3yk= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240820072028-6dd7be11d13b/go.mod h1:aaC2OR34tVrBwd0Z2gqoN5WLtV/idKqpqPDhb4XqmCo= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= @@ -25,6 +25,8 @@ git.frostfs.info/TrueCloudLab/tzhash v1.8.0/go.mod h1:dhY+oy274hV8wGvGL4MwwMpdL3 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 h1:HeY8n27VyPRQe49l/fzyVMkWEB2fsLJYKp64pwA7tz4= git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02/go.mod h1:rQFJJdEOV7KbbMtQYR2lNfiZk+ONRDJSbMCTWxKt8Fw= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/VictoriaMetrics/easyproto v0.1.4 h1:r8cNvo8o6sR4QShBXQd1bKw/VVLSQma/V2KhTBPf+Sc= +github.com/VictoriaMetrics/easyproto v0.1.4/go.mod h1:QlGlzaJnDfFd8Lk6Ci/fuLxfTo3/GThPs2KH23mv710= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index b79f6cb14a..d979b4f0f1 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -1,6 +1,7 @@ package meta import ( + "bytes" "context" "fmt" "time" @@ -107,7 +108,7 @@ func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw b // check in primary index data := getFromBucket(tx, primaryBucketName(cnr, bucketName), key) if len(data) != 0 { - return obj, obj.Unmarshal(data) + return obj, obj.Unmarshal(bytes.Clone(data)) } data = getFromBucket(tx, ecInfoBucketName(cnr, bucketName), key) @@ -118,13 +119,13 @@ func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw b // if not found then check in tombstone index data = getFromBucket(tx, tombstoneBucketName(cnr, bucketName), key) if len(data) != 0 { - return obj, obj.Unmarshal(data) + return obj, obj.Unmarshal(bytes.Clone(data)) } // if not found then check in locker index data = getFromBucket(tx, bucketNameLockers(cnr, bucketName), key) if len(data) != 0 { - return obj, obj.Unmarshal(data) + return obj, obj.Unmarshal(bytes.Clone(data)) } // if not found then check if object is a virtual diff --git a/pkg/services/control/common_test.go b/pkg/services/control/common_test.go deleted file mode 100644 index bc512b4bec..0000000000 --- a/pkg/services/control/common_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package control_test - -import ( - "crypto/rand" - "testing" - - "github.com/mr-tron/base58" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -type protoMessage interface { - StableMarshal([]byte) []byte - proto.Message -} - -func testStableMarshal(t *testing.T, m1, m2 protoMessage, cmp func(m1, m2 protoMessage) bool) { - require.NoError(t, proto.Unmarshal(m1.StableMarshal(nil), m2)) - - require.True(t, cmp(m1, m2)) -} - -func testData(sz int) []byte { - d := make([]byte, sz) - - _, _ = rand.Read(d) - - return d -} - -func testString() string { - return base58.Encode(testData(10)) -} diff --git a/pkg/services/control/ir/service.go b/pkg/services/control/ir/service.go deleted file mode 100644 index b2db2b43a6..0000000000 --- a/pkg/services/control/ir/service.go +++ /dev/null @@ -1,46 +0,0 @@ -package control - -// SetBody sets health check request body. -func (x *HealthCheckRequest) SetBody(v *HealthCheckRequest_Body) { - if x != nil { - x.Body = v - } -} - -// SetHealthStatus sets health status of the IR application. -func (x *HealthCheckResponse_Body) SetHealthStatus(v HealthStatus) { - if x != nil { - x.HealthStatus = v - } -} - -// SetBody sets health check response body. -func (x *HealthCheckResponse) SetBody(v *HealthCheckResponse_Body) { - if x != nil { - x.Body = v - } -} - -func (x *TickEpochRequest) SetBody(v *TickEpochRequest_Body) { - if x != nil { - x.Body = v - } -} - -func (x *TickEpochResponse) SetBody(v *TickEpochResponse_Body) { - if x != nil { - x.Body = v - } -} - -func (x *RemoveNodeRequest) SetBody(v *RemoveNodeRequest_Body) { - if x != nil { - x.Body = v - } -} - -func (x *RemoveNodeResponse) SetBody(v *RemoveNodeResponse_Body) { - if x != nil { - x.Body = v - } -} diff --git a/pkg/services/control/ir/service.pb.go b/pkg/services/control/ir/service.pb.go deleted file mode 100644 index d1e253bf5b..0000000000 --- a/pkg/services/control/ir/service.pb.go +++ /dev/null @@ -1,1277 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.33.0 -// protoc v4.25.0 -// source: pkg/services/control/ir/service.proto - -package control - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Health check request. -type HealthCheckRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of health check request message. - Body *HealthCheckRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - // Should be signed by node key or one of - // the keys configured by the node. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *HealthCheckRequest) Reset() { - *x = HealthCheckRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheckRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckRequest) ProtoMessage() {} - -func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckRequest.ProtoReflect.Descriptor instead. -func (*HealthCheckRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{0} -} - -func (x *HealthCheckRequest) GetBody() *HealthCheckRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *HealthCheckRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Health check response. -type HealthCheckResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of health check response message. - Body *HealthCheckResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *HealthCheckResponse) Reset() { - *x = HealthCheckResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheckResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckResponse) ProtoMessage() {} - -func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckResponse.ProtoReflect.Descriptor instead. -func (*HealthCheckResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{1} -} - -func (x *HealthCheckResponse) GetBody() *HealthCheckResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *HealthCheckResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type TickEpochRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *TickEpochRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *TickEpochRequest) Reset() { - *x = TickEpochRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TickEpochRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TickEpochRequest) ProtoMessage() {} - -func (x *TickEpochRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TickEpochRequest.ProtoReflect.Descriptor instead. -func (*TickEpochRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{2} -} - -func (x *TickEpochRequest) GetBody() *TickEpochRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *TickEpochRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type TickEpochResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *TickEpochResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *TickEpochResponse) Reset() { - *x = TickEpochResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TickEpochResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TickEpochResponse) ProtoMessage() {} - -func (x *TickEpochResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TickEpochResponse.ProtoReflect.Descriptor instead. -func (*TickEpochResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{3} -} - -func (x *TickEpochResponse) GetBody() *TickEpochResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *TickEpochResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveNodeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *RemoveNodeRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveNodeRequest) Reset() { - *x = RemoveNodeRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveNodeRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveNodeRequest) ProtoMessage() {} - -func (x *RemoveNodeRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveNodeRequest.ProtoReflect.Descriptor instead. -func (*RemoveNodeRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{4} -} - -func (x *RemoveNodeRequest) GetBody() *RemoveNodeRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveNodeRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveNodeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *RemoveNodeResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveNodeResponse) Reset() { - *x = RemoveNodeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveNodeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveNodeResponse) ProtoMessage() {} - -func (x *RemoveNodeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveNodeResponse.ProtoReflect.Descriptor instead. -func (*RemoveNodeResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{5} -} - -func (x *RemoveNodeResponse) GetBody() *RemoveNodeResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveNodeResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveContainerRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *RemoveContainerRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveContainerRequest) Reset() { - *x = RemoveContainerRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveContainerRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveContainerRequest) ProtoMessage() {} - -func (x *RemoveContainerRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveContainerRequest.ProtoReflect.Descriptor instead. -func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{6} -} - -func (x *RemoveContainerRequest) GetBody() *RemoveContainerRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveContainerRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveContainerResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *RemoveContainerResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveContainerResponse) Reset() { - *x = RemoveContainerResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveContainerResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveContainerResponse) ProtoMessage() {} - -func (x *RemoveContainerResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveContainerResponse.ProtoReflect.Descriptor instead. -func (*RemoveContainerResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{7} -} - -func (x *RemoveContainerResponse) GetBody() *RemoveContainerResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveContainerResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Health check request body. -type HealthCheckRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *HealthCheckRequest_Body) Reset() { - *x = HealthCheckRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheckRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckRequest_Body) ProtoMessage() {} - -func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckRequest_Body.ProtoReflect.Descriptor instead. -func (*HealthCheckRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{0, 0} -} - -// Health check response body -type HealthCheckResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Health status of IR node application. - HealthStatus HealthStatus `protobuf:"varint,1,opt,name=health_status,json=healthStatus,proto3,enum=ircontrol.HealthStatus" json:"health_status,omitempty"` -} - -func (x *HealthCheckResponse_Body) Reset() { - *x = HealthCheckResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheckResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckResponse_Body) ProtoMessage() {} - -func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckResponse_Body.ProtoReflect.Descriptor instead. -func (*HealthCheckResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{1, 0} -} - -func (x *HealthCheckResponse_Body) GetHealthStatus() HealthStatus { - if x != nil { - return x.HealthStatus - } - return HealthStatus_HEALTH_STATUS_UNDEFINED -} - -type TickEpochRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Valid until block value override. - Vub uint32 `protobuf:"varint,1,opt,name=vub,proto3" json:"vub,omitempty"` -} - -func (x *TickEpochRequest_Body) Reset() { - *x = TickEpochRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TickEpochRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TickEpochRequest_Body) ProtoMessage() {} - -func (x *TickEpochRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TickEpochRequest_Body.ProtoReflect.Descriptor instead. -func (*TickEpochRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{2, 0} -} - -func (x *TickEpochRequest_Body) GetVub() uint32 { - if x != nil { - return x.Vub - } - return 0 -} - -type TickEpochResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Valid until block value for transaction. - Vub uint32 `protobuf:"varint,1,opt,name=vub,proto3" json:"vub,omitempty"` -} - -func (x *TickEpochResponse_Body) Reset() { - *x = TickEpochResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TickEpochResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TickEpochResponse_Body) ProtoMessage() {} - -func (x *TickEpochResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TickEpochResponse_Body.ProtoReflect.Descriptor instead. -func (*TickEpochResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{3, 0} -} - -func (x *TickEpochResponse_Body) GetVub() uint32 { - if x != nil { - return x.Vub - } - return 0 -} - -type RemoveNodeRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - // Valid until block value override. - Vub uint32 `protobuf:"varint,2,opt,name=vub,proto3" json:"vub,omitempty"` -} - -func (x *RemoveNodeRequest_Body) Reset() { - *x = RemoveNodeRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveNodeRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveNodeRequest_Body) ProtoMessage() {} - -func (x *RemoveNodeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveNodeRequest_Body.ProtoReflect.Descriptor instead. -func (*RemoveNodeRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{4, 0} -} - -func (x *RemoveNodeRequest_Body) GetKey() []byte { - if x != nil { - return x.Key - } - return nil -} - -func (x *RemoveNodeRequest_Body) GetVub() uint32 { - if x != nil { - return x.Vub - } - return 0 -} - -type RemoveNodeResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Valid until block value for transaction. - Vub uint32 `protobuf:"varint,1,opt,name=vub,proto3" json:"vub,omitempty"` -} - -func (x *RemoveNodeResponse_Body) Reset() { - *x = RemoveNodeResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveNodeResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveNodeResponse_Body) ProtoMessage() {} - -func (x *RemoveNodeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveNodeResponse_Body.ProtoReflect.Descriptor instead. -func (*RemoveNodeResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{5, 0} -} - -func (x *RemoveNodeResponse_Body) GetVub() uint32 { - if x != nil { - return x.Vub - } - return 0 -} - -type RemoveContainerRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - Owner []byte `protobuf:"bytes,2,opt,name=owner,proto3" json:"owner,omitempty"` - // Valid until block value override. - Vub uint32 `protobuf:"varint,3,opt,name=vub,proto3" json:"vub,omitempty"` -} - -func (x *RemoveContainerRequest_Body) Reset() { - *x = RemoveContainerRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveContainerRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveContainerRequest_Body) ProtoMessage() {} - -func (x *RemoveContainerRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveContainerRequest_Body.ProtoReflect.Descriptor instead. -func (*RemoveContainerRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{6, 0} -} - -func (x *RemoveContainerRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *RemoveContainerRequest_Body) GetOwner() []byte { - if x != nil { - return x.Owner - } - return nil -} - -func (x *RemoveContainerRequest_Body) GetVub() uint32 { - if x != nil { - return x.Vub - } - return 0 -} - -type RemoveContainerResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Valid until block value for transaction. - Vub uint32 `protobuf:"varint,1,opt,name=vub,proto3" json:"vub,omitempty"` -} - -func (x *RemoveContainerResponse_Body) Reset() { - *x = RemoveContainerResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveContainerResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveContainerResponse_Body) ProtoMessage() {} - -func (x *RemoveContainerResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_service_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveContainerResponse_Body.ProtoReflect.Descriptor instead. -func (*RemoveContainerResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_service_proto_rawDescGZIP(), []int{7, 0} -} - -func (x *RemoveContainerResponse_Body) GetVub() uint32 { - if x != nil { - return x.Vub - } - return 0 -} - -var File_pkg_services_control_ir_service_proto protoreflect.FileDescriptor - -var file_pkg_services_control_ir_service_proto_rawDesc = []byte{ - 0x0a, 0x25, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x69, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x1a, 0x23, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x69, 0x72, 0x2f, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, - 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x22, 0xc8, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x44, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x3c, 0x0a, 0x0d, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x96, 0x01, - 0x0a, 0x10, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x20, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, - 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x18, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, 0x22, 0x98, 0x01, 0x0a, 0x11, 0x54, 0x69, 0x63, 0x6b, 0x45, - 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x72, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x76, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, - 0x62, 0x22, 0xaa, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x2a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x76, 0x75, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, 0x22, 0x9a, - 0x01, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x32, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x75, 0x62, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, 0x22, 0xdb, 0x01, 0x0a, 0x16, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x51, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, - 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x76, 0x75, 0x62, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, 0x22, 0xa4, 0x01, 0x0a, 0x17, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x32, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x76, 0x75, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x76, 0x75, 0x62, - 0x32, 0xcb, 0x02, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x12, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1e, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x46, 0x0a, 0x09, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x1b, - 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, - 0x70, 0x6f, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x69, 0x72, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x45, 0x70, 0x6f, 0x63, - 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0a, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x21, 0x2e, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x69, 0x72, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x44, - 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, - 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, - 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, - 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x69, 0x72, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pkg_services_control_ir_service_proto_rawDescOnce sync.Once - file_pkg_services_control_ir_service_proto_rawDescData = file_pkg_services_control_ir_service_proto_rawDesc -) - -func file_pkg_services_control_ir_service_proto_rawDescGZIP() []byte { - file_pkg_services_control_ir_service_proto_rawDescOnce.Do(func() { - file_pkg_services_control_ir_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_control_ir_service_proto_rawDescData) - }) - return file_pkg_services_control_ir_service_proto_rawDescData -} - -var file_pkg_services_control_ir_service_proto_msgTypes = make([]protoimpl.MessageInfo, 16) -var file_pkg_services_control_ir_service_proto_goTypes = []interface{}{ - (*HealthCheckRequest)(nil), // 0: ircontrol.HealthCheckRequest - (*HealthCheckResponse)(nil), // 1: ircontrol.HealthCheckResponse - (*TickEpochRequest)(nil), // 2: ircontrol.TickEpochRequest - (*TickEpochResponse)(nil), // 3: ircontrol.TickEpochResponse - (*RemoveNodeRequest)(nil), // 4: ircontrol.RemoveNodeRequest - (*RemoveNodeResponse)(nil), // 5: ircontrol.RemoveNodeResponse - (*RemoveContainerRequest)(nil), // 6: ircontrol.RemoveContainerRequest - (*RemoveContainerResponse)(nil), // 7: ircontrol.RemoveContainerResponse - (*HealthCheckRequest_Body)(nil), // 8: ircontrol.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 9: ircontrol.HealthCheckResponse.Body - (*TickEpochRequest_Body)(nil), // 10: ircontrol.TickEpochRequest.Body - (*TickEpochResponse_Body)(nil), // 11: ircontrol.TickEpochResponse.Body - (*RemoveNodeRequest_Body)(nil), // 12: ircontrol.RemoveNodeRequest.Body - (*RemoveNodeResponse_Body)(nil), // 13: ircontrol.RemoveNodeResponse.Body - (*RemoveContainerRequest_Body)(nil), // 14: ircontrol.RemoveContainerRequest.Body - (*RemoveContainerResponse_Body)(nil), // 15: ircontrol.RemoveContainerResponse.Body - (*Signature)(nil), // 16: ircontrol.Signature - (HealthStatus)(0), // 17: ircontrol.HealthStatus -} -var file_pkg_services_control_ir_service_proto_depIdxs = []int32{ - 8, // 0: ircontrol.HealthCheckRequest.body:type_name -> ircontrol.HealthCheckRequest.Body - 16, // 1: ircontrol.HealthCheckRequest.signature:type_name -> ircontrol.Signature - 9, // 2: ircontrol.HealthCheckResponse.body:type_name -> ircontrol.HealthCheckResponse.Body - 16, // 3: ircontrol.HealthCheckResponse.signature:type_name -> ircontrol.Signature - 10, // 4: ircontrol.TickEpochRequest.body:type_name -> ircontrol.TickEpochRequest.Body - 16, // 5: ircontrol.TickEpochRequest.signature:type_name -> ircontrol.Signature - 11, // 6: ircontrol.TickEpochResponse.body:type_name -> ircontrol.TickEpochResponse.Body - 16, // 7: ircontrol.TickEpochResponse.signature:type_name -> ircontrol.Signature - 12, // 8: ircontrol.RemoveNodeRequest.body:type_name -> ircontrol.RemoveNodeRequest.Body - 16, // 9: ircontrol.RemoveNodeRequest.signature:type_name -> ircontrol.Signature - 13, // 10: ircontrol.RemoveNodeResponse.body:type_name -> ircontrol.RemoveNodeResponse.Body - 16, // 11: ircontrol.RemoveNodeResponse.signature:type_name -> ircontrol.Signature - 14, // 12: ircontrol.RemoveContainerRequest.body:type_name -> ircontrol.RemoveContainerRequest.Body - 16, // 13: ircontrol.RemoveContainerRequest.signature:type_name -> ircontrol.Signature - 15, // 14: ircontrol.RemoveContainerResponse.body:type_name -> ircontrol.RemoveContainerResponse.Body - 16, // 15: ircontrol.RemoveContainerResponse.signature:type_name -> ircontrol.Signature - 17, // 16: ircontrol.HealthCheckResponse.Body.health_status:type_name -> ircontrol.HealthStatus - 0, // 17: ircontrol.ControlService.HealthCheck:input_type -> ircontrol.HealthCheckRequest - 2, // 18: ircontrol.ControlService.TickEpoch:input_type -> ircontrol.TickEpochRequest - 4, // 19: ircontrol.ControlService.RemoveNode:input_type -> ircontrol.RemoveNodeRequest - 6, // 20: ircontrol.ControlService.RemoveContainer:input_type -> ircontrol.RemoveContainerRequest - 1, // 21: ircontrol.ControlService.HealthCheck:output_type -> ircontrol.HealthCheckResponse - 3, // 22: ircontrol.ControlService.TickEpoch:output_type -> ircontrol.TickEpochResponse - 5, // 23: ircontrol.ControlService.RemoveNode:output_type -> ircontrol.RemoveNodeResponse - 7, // 24: ircontrol.ControlService.RemoveContainer:output_type -> ircontrol.RemoveContainerResponse - 21, // [21:25] is the sub-list for method output_type - 17, // [17:21] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name -} - -func init() { file_pkg_services_control_ir_service_proto_init() } -func file_pkg_services_control_ir_service_proto_init() { - if File_pkg_services_control_ir_service_proto != nil { - return - } - file_pkg_services_control_ir_types_proto_init() - if !protoimpl.UnsafeEnabled { - file_pkg_services_control_ir_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TickEpochRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TickEpochResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveNodeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveNodeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveContainerRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveContainerResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TickEpochRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TickEpochResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveNodeRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveNodeResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveContainerRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_ir_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveContainerResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pkg_services_control_ir_service_proto_rawDesc, - NumEnums: 0, - NumMessages: 16, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_pkg_services_control_ir_service_proto_goTypes, - DependencyIndexes: file_pkg_services_control_ir_service_proto_depIdxs, - MessageInfos: file_pkg_services_control_ir_service_proto_msgTypes, - }.Build() - File_pkg_services_control_ir_service_proto = out.File - file_pkg_services_control_ir_service_proto_rawDesc = nil - file_pkg_services_control_ir_service_proto_goTypes = nil - file_pkg_services_control_ir_service_proto_depIdxs = nil -} diff --git a/pkg/services/control/ir/service_frostfs.pb.go b/pkg/services/control/ir/service_frostfs.pb.go index e22d0013f2..7860958028 100644 --- a/pkg/services/control/ir/service_frostfs.pb.go +++ b/pkg/services/control/ir/service_frostfs.pb.go @@ -2,7 +2,27 @@ package control -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import ( + json "encoding/json" + fmt "fmt" + pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + easyproto "github.com/VictoriaMetrics/easyproto" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" + strconv "strconv" +) + +type HealthCheckRequest_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*HealthCheckRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*HealthCheckRequest_Body)(nil) + _ json.Marshaler = (*HealthCheckRequest_Body)(nil) + _ json.Unmarshaler = (*HealthCheckRequest_Body)(nil) +) // StableSize returns the size of x in protobuf format. // @@ -14,18 +34,93 @@ func (x *HealthCheckRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthCheckRequest_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthCheckRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthCheckRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthCheckRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthCheckRequest_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthCheckRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthCheckRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthCheckRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthCheckRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthCheckRequest struct { + Body *HealthCheckRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*HealthCheckRequest)(nil) + _ encoding.ProtoUnmarshaler = (*HealthCheckRequest)(nil) + _ json.Marshaler = (*HealthCheckRequest)(nil) + _ json.Unmarshaler = (*HealthCheckRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -38,27 +133,6 @@ func (x *HealthCheckRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthCheckRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -74,13 +148,164 @@ func (x *HealthCheckRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *HealthCheckRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *HealthCheckRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthCheckRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthCheckRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthCheckRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthCheckRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(HealthCheckRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *HealthCheckRequest) GetBody() *HealthCheckRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *HealthCheckRequest) SetBody(v *HealthCheckRequest_Body) { + x.Body = v +} +func (x *HealthCheckRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *HealthCheckRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthCheckRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthCheckRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthCheckRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthCheckRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *HealthCheckRequest_Body + f = new(HealthCheckRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthCheckResponse_Body struct { + HealthStatus HealthStatus `json:"healthStatus"` +} + +var ( + _ encoding.ProtoMarshaler = (*HealthCheckResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*HealthCheckResponse_Body)(nil) + _ json.Marshaler = (*HealthCheckResponse_Body)(nil) + _ json.Unmarshaler = (*HealthCheckResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -92,26 +317,141 @@ func (x *HealthCheckResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthCheckResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.EnumMarshal(1, buf[offset:], int32(x.HealthStatus)) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthCheckResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthCheckResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if int32(x.HealthStatus) != 0 { + mm.AppendInt32(1, int32(x.HealthStatus)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthCheckResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthCheckResponse_Body") + } + switch fc.FieldNum { + case 1: // HealthStatus + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "HealthStatus") + } + x.HealthStatus = HealthStatus(data) + } + } + return nil +} +func (x *HealthCheckResponse_Body) GetHealthStatus() HealthStatus { + if x != nil { + return x.HealthStatus + } + return 0 +} +func (x *HealthCheckResponse_Body) SetHealthStatus(v HealthStatus) { + x.HealthStatus = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthCheckResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthCheckResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"healthStatus\":" + out.RawString(prefix[1:]) + out.Int32(int32(x.HealthStatus)) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthCheckResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthCheckResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "healthStatus": + { + var f HealthStatus + var parsedValue HealthStatus + switch v := in.Interface().(type) { + case string: + if vv, ok := HealthStatus_value[v]; ok { + parsedValue = HealthStatus(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = HealthStatus(vv) + case float64: + parsedValue = HealthStatus(v) + } + f = parsedValue + x.HealthStatus = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthCheckResponse struct { + Body *HealthCheckResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*HealthCheckResponse)(nil) + _ encoding.ProtoUnmarshaler = (*HealthCheckResponse)(nil) + _ json.Marshaler = (*HealthCheckResponse)(nil) + _ json.Unmarshaler = (*HealthCheckResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -124,27 +464,6 @@ func (x *HealthCheckResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthCheckResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -160,13 +479,164 @@ func (x *HealthCheckResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *HealthCheckResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *HealthCheckResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthCheckResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthCheckResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthCheckResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthCheckResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(HealthCheckResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *HealthCheckResponse) GetBody() *HealthCheckResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *HealthCheckResponse) SetBody(v *HealthCheckResponse_Body) { + x.Body = v +} +func (x *HealthCheckResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *HealthCheckResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthCheckResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthCheckResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthCheckResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthCheckResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *HealthCheckResponse_Body + f = new(HealthCheckResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type TickEpochRequest_Body struct { + Vub uint32 `json:"vub"` +} + +var ( + _ encoding.ProtoMarshaler = (*TickEpochRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*TickEpochRequest_Body)(nil) + _ json.Marshaler = (*TickEpochRequest_Body)(nil) + _ json.Unmarshaler = (*TickEpochRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -178,26 +648,125 @@ func (x *TickEpochRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *TickEpochRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt32Marshal(1, buf[offset:], x.Vub) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *TickEpochRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *TickEpochRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Vub != 0 { + mm.AppendUint32(1, x.Vub) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *TickEpochRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "TickEpochRequest_Body") + } + switch fc.FieldNum { + case 1: // Vub + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Vub") + } + x.Vub = data + } + } + return nil +} +func (x *TickEpochRequest_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} +func (x *TickEpochRequest_Body) SetVub(v uint32) { + x.Vub = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *TickEpochRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *TickEpochRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"vub\":" + out.RawString(prefix[1:]) + out.Uint32(x.Vub) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *TickEpochRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *TickEpochRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "vub": + { + var f uint32 + f = in.Uint32() + x.Vub = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type TickEpochRequest struct { + Body *TickEpochRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*TickEpochRequest)(nil) + _ encoding.ProtoUnmarshaler = (*TickEpochRequest)(nil) + _ json.Marshaler = (*TickEpochRequest)(nil) + _ json.Unmarshaler = (*TickEpochRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -210,27 +779,6 @@ func (x *TickEpochRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *TickEpochRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -246,13 +794,164 @@ func (x *TickEpochRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *TickEpochRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *TickEpochRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *TickEpochRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *TickEpochRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *TickEpochRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "TickEpochRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(TickEpochRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *TickEpochRequest) GetBody() *TickEpochRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *TickEpochRequest) SetBody(v *TickEpochRequest_Body) { + x.Body = v +} +func (x *TickEpochRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *TickEpochRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *TickEpochRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *TickEpochRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *TickEpochRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *TickEpochRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *TickEpochRequest_Body + f = new(TickEpochRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type TickEpochResponse_Body struct { + Vub uint32 `json:"vub"` +} + +var ( + _ encoding.ProtoMarshaler = (*TickEpochResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*TickEpochResponse_Body)(nil) + _ json.Marshaler = (*TickEpochResponse_Body)(nil) + _ json.Unmarshaler = (*TickEpochResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -264,26 +963,125 @@ func (x *TickEpochResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *TickEpochResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt32Marshal(1, buf[offset:], x.Vub) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *TickEpochResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *TickEpochResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Vub != 0 { + mm.AppendUint32(1, x.Vub) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *TickEpochResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "TickEpochResponse_Body") + } + switch fc.FieldNum { + case 1: // Vub + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Vub") + } + x.Vub = data + } + } + return nil +} +func (x *TickEpochResponse_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} +func (x *TickEpochResponse_Body) SetVub(v uint32) { + x.Vub = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *TickEpochResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *TickEpochResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"vub\":" + out.RawString(prefix[1:]) + out.Uint32(x.Vub) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *TickEpochResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *TickEpochResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "vub": + { + var f uint32 + f = in.Uint32() + x.Vub = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type TickEpochResponse struct { + Body *TickEpochResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*TickEpochResponse)(nil) + _ encoding.ProtoUnmarshaler = (*TickEpochResponse)(nil) + _ json.Marshaler = (*TickEpochResponse)(nil) + _ json.Unmarshaler = (*TickEpochResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -296,27 +1094,6 @@ func (x *TickEpochResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *TickEpochResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -332,13 +1109,165 @@ func (x *TickEpochResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *TickEpochResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *TickEpochResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *TickEpochResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *TickEpochResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *TickEpochResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "TickEpochResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(TickEpochResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *TickEpochResponse) GetBody() *TickEpochResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *TickEpochResponse) SetBody(v *TickEpochResponse_Body) { + x.Body = v +} +func (x *TickEpochResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *TickEpochResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *TickEpochResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *TickEpochResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *TickEpochResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *TickEpochResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *TickEpochResponse_Body + f = new(TickEpochResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveNodeRequest_Body struct { + Key []byte `json:"key"` + Vub uint32 `json:"vub"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveNodeRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveNodeRequest_Body)(nil) + _ json.Marshaler = (*RemoveNodeRequest_Body)(nil) + _ json.Unmarshaler = (*RemoveNodeRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -351,27 +1280,154 @@ func (x *RemoveNodeRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveNodeRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.Key) - offset += proto.UInt32Marshal(2, buf[offset:], x.Vub) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveNodeRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveNodeRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Key) != 0 { + mm.AppendBytes(1, x.Key) + } + if x.Vub != 0 { + mm.AppendUint32(2, x.Vub) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveNodeRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveNodeRequest_Body") + } + switch fc.FieldNum { + case 1: // Key + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Key") + } + x.Key = data + case 2: // Vub + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Vub") + } + x.Vub = data + } + } + return nil +} +func (x *RemoveNodeRequest_Body) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} +func (x *RemoveNodeRequest_Body) SetKey(v []byte) { + x.Key = v +} +func (x *RemoveNodeRequest_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} +func (x *RemoveNodeRequest_Body) SetVub(v uint32) { + x.Vub = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveNodeRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveNodeRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"key\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.Key) + } + { + const prefix string = ",\"vub\":" + out.RawString(prefix) + out.Uint32(x.Vub) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveNodeRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveNodeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "key": + { + var f []byte + f = in.Bytes() + x.Key = f + } + case "vub": + { + var f uint32 + f = in.Uint32() + x.Vub = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveNodeRequest struct { + Body *RemoveNodeRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveNodeRequest)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveNodeRequest)(nil) + _ json.Marshaler = (*RemoveNodeRequest)(nil) + _ json.Unmarshaler = (*RemoveNodeRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -384,27 +1440,6 @@ func (x *RemoveNodeRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveNodeRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -420,13 +1455,164 @@ func (x *RemoveNodeRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveNodeRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveNodeRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveNodeRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveNodeRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveNodeRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveNodeRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveNodeRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveNodeRequest) GetBody() *RemoveNodeRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveNodeRequest) SetBody(v *RemoveNodeRequest_Body) { + x.Body = v +} +func (x *RemoveNodeRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveNodeRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveNodeRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveNodeRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveNodeRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveNodeRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveNodeRequest_Body + f = new(RemoveNodeRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveNodeResponse_Body struct { + Vub uint32 `json:"vub"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveNodeResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveNodeResponse_Body)(nil) + _ json.Marshaler = (*RemoveNodeResponse_Body)(nil) + _ json.Unmarshaler = (*RemoveNodeResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -438,26 +1624,125 @@ func (x *RemoveNodeResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveNodeResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt32Marshal(1, buf[offset:], x.Vub) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveNodeResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveNodeResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Vub != 0 { + mm.AppendUint32(1, x.Vub) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveNodeResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveNodeResponse_Body") + } + switch fc.FieldNum { + case 1: // Vub + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Vub") + } + x.Vub = data + } + } + return nil +} +func (x *RemoveNodeResponse_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} +func (x *RemoveNodeResponse_Body) SetVub(v uint32) { + x.Vub = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveNodeResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveNodeResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"vub\":" + out.RawString(prefix[1:]) + out.Uint32(x.Vub) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveNodeResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveNodeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "vub": + { + var f uint32 + f = in.Uint32() + x.Vub = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveNodeResponse struct { + Body *RemoveNodeResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveNodeResponse)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveNodeResponse)(nil) + _ json.Marshaler = (*RemoveNodeResponse)(nil) + _ json.Unmarshaler = (*RemoveNodeResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -470,27 +1755,6 @@ func (x *RemoveNodeResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveNodeResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -506,13 +1770,166 @@ func (x *RemoveNodeResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveNodeResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveNodeResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveNodeResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveNodeResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveNodeResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveNodeResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveNodeResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveNodeResponse) GetBody() *RemoveNodeResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveNodeResponse) SetBody(v *RemoveNodeResponse_Body) { + x.Body = v +} +func (x *RemoveNodeResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveNodeResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveNodeResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveNodeResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveNodeResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveNodeResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveNodeResponse_Body + f = new(RemoveNodeResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveContainerRequest_Body struct { + ContainerId []byte `json:"containerId"` + Owner []byte `json:"owner"` + Vub uint32 `json:"vub"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveContainerRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveContainerRequest_Body)(nil) + _ json.Marshaler = (*RemoveContainerRequest_Body)(nil) + _ json.Unmarshaler = (*RemoveContainerRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -526,28 +1943,183 @@ func (x *RemoveContainerRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveContainerRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.BytesMarshal(2, buf[offset:], x.Owner) - offset += proto.UInt32Marshal(3, buf[offset:], x.Vub) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveContainerRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveContainerRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.Owner) != 0 { + mm.AppendBytes(2, x.Owner) + } + if x.Vub != 0 { + mm.AppendUint32(3, x.Vub) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveContainerRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveContainerRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // Owner + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Owner") + } + x.Owner = data + case 3: // Vub + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Vub") + } + x.Vub = data + } + } + return nil +} +func (x *RemoveContainerRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *RemoveContainerRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *RemoveContainerRequest_Body) GetOwner() []byte { + if x != nil { + return x.Owner + } + return nil +} +func (x *RemoveContainerRequest_Body) SetOwner(v []byte) { + x.Owner = v +} +func (x *RemoveContainerRequest_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} +func (x *RemoveContainerRequest_Body) SetVub(v uint32) { + x.Vub = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveContainerRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveContainerRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"owner\":" + out.RawString(prefix) + out.Base64Bytes(x.Owner) + } + { + const prefix string = ",\"vub\":" + out.RawString(prefix) + out.Uint32(x.Vub) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveContainerRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveContainerRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "owner": + { + var f []byte + f = in.Bytes() + x.Owner = f + } + case "vub": + { + var f uint32 + f = in.Uint32() + x.Vub = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveContainerRequest struct { + Body *RemoveContainerRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveContainerRequest)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveContainerRequest)(nil) + _ json.Marshaler = (*RemoveContainerRequest)(nil) + _ json.Unmarshaler = (*RemoveContainerRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -560,27 +2132,6 @@ func (x *RemoveContainerRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveContainerRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -596,13 +2147,164 @@ func (x *RemoveContainerRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveContainerRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveContainerRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveContainerRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveContainerRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveContainerRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveContainerRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveContainerRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveContainerRequest) GetBody() *RemoveContainerRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveContainerRequest) SetBody(v *RemoveContainerRequest_Body) { + x.Body = v +} +func (x *RemoveContainerRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveContainerRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveContainerRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveContainerRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveContainerRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveContainerRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveContainerRequest_Body + f = new(RemoveContainerRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveContainerResponse_Body struct { + Vub uint32 `json:"vub"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveContainerResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveContainerResponse_Body)(nil) + _ json.Marshaler = (*RemoveContainerResponse_Body)(nil) + _ json.Unmarshaler = (*RemoveContainerResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -614,26 +2316,125 @@ func (x *RemoveContainerResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveContainerResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt32Marshal(1, buf[offset:], x.Vub) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveContainerResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveContainerResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Vub != 0 { + mm.AppendUint32(1, x.Vub) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveContainerResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveContainerResponse_Body") + } + switch fc.FieldNum { + case 1: // Vub + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Vub") + } + x.Vub = data + } + } + return nil +} +func (x *RemoveContainerResponse_Body) GetVub() uint32 { + if x != nil { + return x.Vub + } + return 0 +} +func (x *RemoveContainerResponse_Body) SetVub(v uint32) { + x.Vub = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveContainerResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveContainerResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"vub\":" + out.RawString(prefix[1:]) + out.Uint32(x.Vub) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveContainerResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveContainerResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "vub": + { + var f uint32 + f = in.Uint32() + x.Vub = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveContainerResponse struct { + Body *RemoveContainerResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveContainerResponse)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveContainerResponse)(nil) + _ json.Marshaler = (*RemoveContainerResponse)(nil) + _ json.Unmarshaler = (*RemoveContainerResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -646,27 +2447,6 @@ func (x *RemoveContainerResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveContainerResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -682,9 +2462,149 @@ func (x *RemoveContainerResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveContainerResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveContainerResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveContainerResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *RemoveContainerResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveContainerResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveContainerResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveContainerResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveContainerResponse) GetBody() *RemoveContainerResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveContainerResponse) SetBody(v *RemoveContainerResponse_Body) { + x.Body = v +} +func (x *RemoveContainerResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveContainerResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveContainerResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveContainerResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveContainerResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveContainerResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveContainerResponse_Body + f = new(RemoveContainerResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } } diff --git a/pkg/services/control/ir/service_test.go b/pkg/services/control/ir/service_test.go deleted file mode 100644 index 54eef51484..0000000000 --- a/pkg/services/control/ir/service_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package control_test - -import ( - "testing" - - control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" - "github.com/stretchr/testify/require" - "google.golang.org/protobuf/proto" -) - -type protoMessage interface { - StableMarshal([]byte) []byte - proto.Message -} - -func testStableMarshal(t *testing.T, m1, m2 protoMessage, cmp func(m1, m2 protoMessage) bool) { - require.NoError(t, proto.Unmarshal(m1.StableMarshal(nil), m2)) - - require.True(t, cmp(m1, m2)) -} - -func TestHealthCheckResponse_Body_StableMarshal(t *testing.T) { - testStableMarshal(t, - generateHealthCheckResponseBody(), - new(control.HealthCheckResponse_Body), - func(m1, m2 protoMessage) bool { - return equalHealthCheckResponseBodies( - m1.(*control.HealthCheckResponse_Body), - m2.(*control.HealthCheckResponse_Body), - ) - }, - ) -} - -func generateHealthCheckResponseBody() *control.HealthCheckResponse_Body { - body := new(control.HealthCheckResponse_Body) - body.SetHealthStatus(control.HealthStatus_SHUTTING_DOWN) - - return body -} - -func equalHealthCheckResponseBodies(b1, b2 *control.HealthCheckResponse_Body) bool { - return b1.GetHealthStatus() == b2.GetHealthStatus() -} diff --git a/pkg/services/control/ir/types.go b/pkg/services/control/ir/types.go deleted file mode 100644 index 97ffd3ce33..0000000000 --- a/pkg/services/control/ir/types.go +++ /dev/null @@ -1,15 +0,0 @@ -package control - -// SetKey sets public key used for signing. -func (x *Signature) SetKey(v []byte) { - if x != nil { - x.Key = v - } -} - -// SetSign sets binary signature. -func (x *Signature) SetSign(v []byte) { - if x != nil { - x.Sign = v - } -} diff --git a/pkg/services/control/ir/types.pb.go b/pkg/services/control/ir/types.pb.go deleted file mode 100644 index 840e0be677..0000000000 --- a/pkg/services/control/ir/types.pb.go +++ /dev/null @@ -1,230 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.33.0 -// protoc v4.25.0 -// source: pkg/services/control/ir/types.proto - -package control - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Health status of the IR application. -type HealthStatus int32 - -const ( - // Undefined status, default value. - HealthStatus_HEALTH_STATUS_UNDEFINED HealthStatus = 0 - // IR application is starting. - HealthStatus_STARTING HealthStatus = 1 - // IR application is started and serves all services. - HealthStatus_READY HealthStatus = 2 - // IR application is shutting down. - HealthStatus_SHUTTING_DOWN HealthStatus = 3 - // IR application is reconfiguring. - HealthStatus_RECONFIGURING HealthStatus = 4 -) - -// Enum value maps for HealthStatus. -var ( - HealthStatus_name = map[int32]string{ - 0: "HEALTH_STATUS_UNDEFINED", - 1: "STARTING", - 2: "READY", - 3: "SHUTTING_DOWN", - 4: "RECONFIGURING", - } - HealthStatus_value = map[string]int32{ - "HEALTH_STATUS_UNDEFINED": 0, - "STARTING": 1, - "READY": 2, - "SHUTTING_DOWN": 3, - "RECONFIGURING": 4, - } -) - -func (x HealthStatus) Enum() *HealthStatus { - p := new(HealthStatus) - *p = x - return p -} - -func (x HealthStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HealthStatus) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_control_ir_types_proto_enumTypes[0].Descriptor() -} - -func (HealthStatus) Type() protoreflect.EnumType { - return &file_pkg_services_control_ir_types_proto_enumTypes[0] -} - -func (x HealthStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HealthStatus.Descriptor instead. -func (HealthStatus) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_ir_types_proto_rawDescGZIP(), []int{0} -} - -// Signature of some message. -type Signature struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Public key used for signing. - Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - // Binary signature. - Sign []byte `protobuf:"bytes,2,opt,name=sign,json=signature,proto3" json:"sign,omitempty"` -} - -func (x *Signature) Reset() { - *x = Signature{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_ir_types_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Signature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Signature) ProtoMessage() {} - -func (x *Signature) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_ir_types_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Signature.ProtoReflect.Descriptor instead. -func (*Signature) Descriptor() ([]byte, []int) { - return file_pkg_services_control_ir_types_proto_rawDescGZIP(), []int{0} -} - -func (x *Signature) GetKey() []byte { - if x != nil { - return x.Key - } - return nil -} - -func (x *Signature) GetSign() []byte { - if x != nil { - return x.Sign - } - return nil -} - -var File_pkg_services_control_ir_types_proto protoreflect.FileDescriptor - -var file_pkg_services_control_ir_types_proto_rawDesc = []byte{ - 0x0a, 0x23, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x69, 0x72, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x69, 0x72, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x22, 0x36, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x17, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, - 0x54, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, - 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, - 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, - 0x0a, 0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, - 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, - 0x4e, 0x47, 0x10, 0x04, 0x42, 0x44, 0x5a, 0x42, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, - 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, - 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, - 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, - 0x69, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_pkg_services_control_ir_types_proto_rawDescOnce sync.Once - file_pkg_services_control_ir_types_proto_rawDescData = file_pkg_services_control_ir_types_proto_rawDesc -) - -func file_pkg_services_control_ir_types_proto_rawDescGZIP() []byte { - file_pkg_services_control_ir_types_proto_rawDescOnce.Do(func() { - file_pkg_services_control_ir_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_control_ir_types_proto_rawDescData) - }) - return file_pkg_services_control_ir_types_proto_rawDescData -} - -var file_pkg_services_control_ir_types_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pkg_services_control_ir_types_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_pkg_services_control_ir_types_proto_goTypes = []interface{}{ - (HealthStatus)(0), // 0: ircontrol.HealthStatus - (*Signature)(nil), // 1: ircontrol.Signature -} -var file_pkg_services_control_ir_types_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pkg_services_control_ir_types_proto_init() } -func file_pkg_services_control_ir_types_proto_init() { - if File_pkg_services_control_ir_types_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pkg_services_control_ir_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Signature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pkg_services_control_ir_types_proto_rawDesc, - NumEnums: 1, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pkg_services_control_ir_types_proto_goTypes, - DependencyIndexes: file_pkg_services_control_ir_types_proto_depIdxs, - EnumInfos: file_pkg_services_control_ir_types_proto_enumTypes, - MessageInfos: file_pkg_services_control_ir_types_proto_msgTypes, - }.Build() - File_pkg_services_control_ir_types_proto = out.File - file_pkg_services_control_ir_types_proto_rawDesc = nil - file_pkg_services_control_ir_types_proto_goTypes = nil - file_pkg_services_control_ir_types_proto_depIdxs = nil -} diff --git a/pkg/services/control/ir/types_frostfs.pb.go b/pkg/services/control/ir/types_frostfs.pb.go index ef2fc458ec..b230726a93 100644 --- a/pkg/services/control/ir/types_frostfs.pb.go +++ b/pkg/services/control/ir/types_frostfs.pb.go @@ -2,7 +2,70 @@ package control -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import ( + json "encoding/json" + fmt "fmt" + pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + easyproto "github.com/VictoriaMetrics/easyproto" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" + strconv "strconv" +) + +type HealthStatus int32 + +const ( + HealthStatus_HEALTH_STATUS_UNDEFINED HealthStatus = 0 + HealthStatus_STARTING HealthStatus = 1 + HealthStatus_READY HealthStatus = 2 + HealthStatus_SHUTTING_DOWN HealthStatus = 3 + HealthStatus_RECONFIGURING HealthStatus = 4 +) + +var ( + HealthStatus_name = map[int32]string{ + 0: "HEALTH_STATUS_UNDEFINED", + 1: "STARTING", + 2: "READY", + 3: "SHUTTING_DOWN", + 4: "RECONFIGURING", + } + HealthStatus_value = map[string]int32{ + "HEALTH_STATUS_UNDEFINED": 0, + "STARTING": 1, + "READY": 2, + "SHUTTING_DOWN": 3, + "RECONFIGURING": 4, + } +) + +func (x HealthStatus) String() string { + if v, ok := HealthStatus_name[int32(x)]; ok { + return v + } + return strconv.FormatInt(int64(x), 10) +} +func (x *HealthStatus) FromString(s string) bool { + if v, ok := HealthStatus_value[s]; ok { + *x = HealthStatus(v) + return true + } + return false +} + +type Signature struct { + Key []byte `json:"key"` + Sign []byte `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*Signature)(nil) + _ encoding.ProtoUnmarshaler = (*Signature)(nil) + _ json.Marshaler = (*Signature)(nil) + _ json.Unmarshaler = (*Signature)(nil) +) // StableSize returns the size of x in protobuf format. // @@ -16,23 +79,138 @@ func (x *Signature) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *Signature) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.Key) - offset += proto.BytesMarshal(2, buf[offset:], x.Sign) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *Signature) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *Signature) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Key) != 0 { + mm.AppendBytes(1, x.Key) + } + if len(x.Sign) != 0 { + mm.AppendBytes(2, x.Sign) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *Signature) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "Signature") + } + switch fc.FieldNum { + case 1: // Key + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Key") + } + x.Key = data + case 2: // Sign + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Sign") + } + x.Sign = data + } + } + return nil +} +func (x *Signature) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} +func (x *Signature) SetKey(v []byte) { + x.Key = v +} +func (x *Signature) GetSign() []byte { + if x != nil { + return x.Sign + } + return nil +} +func (x *Signature) SetSign(v []byte) { + x.Sign = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *Signature) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *Signature) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"key\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.Key) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + out.Base64Bytes(x.Sign) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *Signature) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *Signature) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "key": + { + var f []byte + f = in.Bytes() + x.Key = f + } + case "signature": + { + var f []byte + f = in.Bytes() + x.Sign = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } } diff --git a/pkg/services/control/server/list_shards.go b/pkg/services/control/server/list_shards.go index d6531b947f..b639245c14 100644 --- a/pkg/services/control/server/list_shards.go +++ b/pkg/services/control/server/list_shards.go @@ -30,10 +30,10 @@ func (s *Server) ListShards(_ context.Context, req *control.ListShardsRequest) ( for _, sh := range info.Shards { si := new(control.ShardInfo) - si.SetID(*sh.ID) + si.SetShard_ID(*sh.ID) si.SetMetabasePath(sh.MetaBaseInfo.Path) si.Blobstor = blobstorInfoToProto(sh.BlobStorInfo) - si.SetWriteCachePath(sh.WriteCacheInfo.Path) + si.SetWritecachePath(sh.WriteCacheInfo.Path) si.SetPiloramaPath(sh.PiloramaInfo.Path) var m control.ShardMode diff --git a/pkg/services/control/service.go b/pkg/services/control/service.go deleted file mode 100644 index ef0c0a8d27..0000000000 --- a/pkg/services/control/service.go +++ /dev/null @@ -1,142 +0,0 @@ -package control - -// SetBody sets health check request body. -func (x *HealthCheckRequest) SetBody(v *HealthCheckRequest_Body) { - if x != nil { - x.Body = v - } -} - -// SetNetmapStatus sets status of the storage node in FrostFS network map. -func (x *HealthCheckResponse_Body) SetNetmapStatus(v NetmapStatus) { - if x != nil { - x.NetmapStatus = v - } -} - -// SetHealthStatus sets health status of the storage node application. -func (x *HealthCheckResponse_Body) SetHealthStatus(v HealthStatus) { - if x != nil { - x.HealthStatus = v - } -} - -// SetBody sets health check response body. -func (x *HealthCheckResponse) SetBody(v *HealthCheckResponse_Body) { - if x != nil { - x.Body = v - } -} - -// SetStatus sets new storage node status in FrostFS network map. -func (x *SetNetmapStatusRequest_Body) SetStatus(v NetmapStatus) { - if x != nil { - x.Status = v - } -} - -// SetForceMaintenance sets force_maintenance flag in the message. -func (x *SetNetmapStatusRequest_Body) SetForceMaintenance() { - x.ForceMaintenance = true -} - -// SetBody sets body of the set netmap status request . -func (x *SetNetmapStatusRequest) SetBody(v *SetNetmapStatusRequest_Body) { - if x != nil { - x.Body = v - } -} - -// SetBody sets set body of the netmap status response. -func (x *SetNetmapStatusResponse) SetBody(v *SetNetmapStatusResponse_Body) { - if x != nil { - x.Body = v - } -} - -// SetAddressList sets list of objects to be removed in FrostFS API binary format. -func (x *DropObjectsRequest_Body) SetAddressList(v [][]byte) { - if x != nil { - x.AddressList = v - } -} - -// SetBody sets body of the set "Drop objects" request. -func (x *DropObjectsRequest) SetBody(v *DropObjectsRequest_Body) { - if x != nil { - x.Body = v - } -} - -// SetBody sets set body of the "Drop objects" response. -func (x *DropObjectsResponse) SetBody(v *DropObjectsResponse_Body) { - if x != nil { - x.Body = v - } -} - -// SetBody sets list shards request body. -func (x *ListShardsRequest) SetBody(v *ListShardsRequest_Body) { - if x != nil { - x.Body = v - } -} - -// SetShards sets shards of the storage node. -func (x *ListShardsResponse_Body) SetShards(v []*ShardInfo) { - if x != nil { - x.Shards = v - } -} - -// SetBody sets list shards response body. -func (x *ListShardsResponse) SetBody(v *ListShardsResponse_Body) { - if x != nil { - x.Body = v - } -} - -// SetShardIDList sets shard ID whose mode is requested to be set. -func (x *SetShardModeRequest_Body) SetShardIDList(v [][]byte) { - if v != nil { - x.Shard_ID = v - } -} - -// SetMode sets mode of the shard. -func (x *SetShardModeRequest_Body) SetMode(v ShardMode) { - x.Mode = v -} - -// ClearErrorCounter sets flag signifying whether error counter for shard should be cleared. -func (x *SetShardModeRequest_Body) ClearErrorCounter(reset bool) { - x.ResetErrorCounter = reset -} - -// SetBody sets request body. -func (x *SetShardModeRequest) SetBody(v *SetShardModeRequest_Body) { - if x != nil { - x.Body = v - } -} - -// SetBody sets body of the set shard mode response. -func (x *SetShardModeResponse) SetBody(v *SetShardModeResponse_Body) { - if x != nil { - x.Body = v - } -} - -// SetBody sets list shards request body. -func (x *SynchronizeTreeRequest) SetBody(v *SynchronizeTreeRequest_Body) { - if x != nil { - x.Body = v - } -} - -// SetBody sets list shards response body. -func (x *SynchronizeTreeResponse) SetBody(v *SynchronizeTreeResponse_Body) { - if x != nil { - x.Body = v - } -} diff --git a/pkg/services/control/service.pb.go b/pkg/services/control/service.pb.go deleted file mode 100644 index e5a5ce24c1..0000000000 --- a/pkg/services/control/service.pb.go +++ /dev/null @@ -1,7094 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.33.0 -// protoc v4.25.0 -// source: pkg/services/control/service.proto - -package control - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type StartShardEvacuationRequest_Body_Scope int32 - -const ( - StartShardEvacuationRequest_Body_NONE StartShardEvacuationRequest_Body_Scope = 0 - StartShardEvacuationRequest_Body_OBJECTS StartShardEvacuationRequest_Body_Scope = 1 - StartShardEvacuationRequest_Body_TREES StartShardEvacuationRequest_Body_Scope = 2 -) - -// Enum value maps for StartShardEvacuationRequest_Body_Scope. -var ( - StartShardEvacuationRequest_Body_Scope_name = map[int32]string{ - 0: "NONE", - 1: "OBJECTS", - 2: "TREES", - } - StartShardEvacuationRequest_Body_Scope_value = map[string]int32{ - "NONE": 0, - "OBJECTS": 1, - "TREES": 2, - } -) - -func (x StartShardEvacuationRequest_Body_Scope) Enum() *StartShardEvacuationRequest_Body_Scope { - p := new(StartShardEvacuationRequest_Body_Scope) - *p = x - return p -} - -func (x StartShardEvacuationRequest_Body_Scope) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (StartShardEvacuationRequest_Body_Scope) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_control_service_proto_enumTypes[0].Descriptor() -} - -func (StartShardEvacuationRequest_Body_Scope) Type() protoreflect.EnumType { - return &file_pkg_services_control_service_proto_enumTypes[0] -} - -func (x StartShardEvacuationRequest_Body_Scope) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use StartShardEvacuationRequest_Body_Scope.Descriptor instead. -func (StartShardEvacuationRequest_Body_Scope) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{20, 0, 0} -} - -// Evacuate status enum. -type GetShardEvacuationStatusResponse_Body_Status int32 - -const ( - GetShardEvacuationStatusResponse_Body_EVACUATE_SHARD_STATUS_UNDEFINED GetShardEvacuationStatusResponse_Body_Status = 0 - GetShardEvacuationStatusResponse_Body_RUNNING GetShardEvacuationStatusResponse_Body_Status = 1 - GetShardEvacuationStatusResponse_Body_COMPLETED GetShardEvacuationStatusResponse_Body_Status = 2 -) - -// Enum value maps for GetShardEvacuationStatusResponse_Body_Status. -var ( - GetShardEvacuationStatusResponse_Body_Status_name = map[int32]string{ - 0: "EVACUATE_SHARD_STATUS_UNDEFINED", - 1: "RUNNING", - 2: "COMPLETED", - } - GetShardEvacuationStatusResponse_Body_Status_value = map[string]int32{ - "EVACUATE_SHARD_STATUS_UNDEFINED": 0, - "RUNNING": 1, - "COMPLETED": 2, - } -) - -func (x GetShardEvacuationStatusResponse_Body_Status) Enum() *GetShardEvacuationStatusResponse_Body_Status { - p := new(GetShardEvacuationStatusResponse_Body_Status) - *p = x - return p -} - -func (x GetShardEvacuationStatusResponse_Body_Status) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GetShardEvacuationStatusResponse_Body_Status) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_control_service_proto_enumTypes[1].Descriptor() -} - -func (GetShardEvacuationStatusResponse_Body_Status) Type() protoreflect.EnumType { - return &file_pkg_services_control_service_proto_enumTypes[1] -} - -func (x GetShardEvacuationStatusResponse_Body_Status) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use GetShardEvacuationStatusResponse_Body_Status.Descriptor instead. -func (GetShardEvacuationStatusResponse_Body_Status) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0, 0} -} - -// Health check request. -type HealthCheckRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of health check request message. - Body *HealthCheckRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *HealthCheckRequest) Reset() { - *x = HealthCheckRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheckRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckRequest) ProtoMessage() {} - -func (x *HealthCheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckRequest.ProtoReflect.Descriptor instead. -func (*HealthCheckRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{0} -} - -func (x *HealthCheckRequest) GetBody() *HealthCheckRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *HealthCheckRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Health check request. -type HealthCheckResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of health check response message. - Body *HealthCheckResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *HealthCheckResponse) Reset() { - *x = HealthCheckResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheckResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckResponse) ProtoMessage() {} - -func (x *HealthCheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckResponse.ProtoReflect.Descriptor instead. -func (*HealthCheckResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{1} -} - -func (x *HealthCheckResponse) GetBody() *HealthCheckResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *HealthCheckResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Set netmap status request. -type SetNetmapStatusRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of set netmap status request message. - Body *SetNetmapStatusRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SetNetmapStatusRequest) Reset() { - *x = SetNetmapStatusRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetNetmapStatusRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetNetmapStatusRequest) ProtoMessage() {} - -func (x *SetNetmapStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetNetmapStatusRequest.ProtoReflect.Descriptor instead. -func (*SetNetmapStatusRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{2} -} - -func (x *SetNetmapStatusRequest) GetBody() *SetNetmapStatusRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *SetNetmapStatusRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Set netmap status response. -type SetNetmapStatusResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of set netmap status response message. - Body *SetNetmapStatusResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SetNetmapStatusResponse) Reset() { - *x = SetNetmapStatusResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetNetmapStatusResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetNetmapStatusResponse) ProtoMessage() {} - -func (x *SetNetmapStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetNetmapStatusResponse.ProtoReflect.Descriptor instead. -func (*SetNetmapStatusResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{3} -} - -func (x *SetNetmapStatusResponse) GetBody() *SetNetmapStatusResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *SetNetmapStatusResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Get netmap status request. -type GetNetmapStatusRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of set netmap status request message. - Body *GetNetmapStatusRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetNetmapStatusRequest) Reset() { - *x = GetNetmapStatusRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNetmapStatusRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNetmapStatusRequest) ProtoMessage() {} - -func (x *GetNetmapStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNetmapStatusRequest.ProtoReflect.Descriptor instead. -func (*GetNetmapStatusRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{4} -} - -func (x *GetNetmapStatusRequest) GetBody() *GetNetmapStatusRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetNetmapStatusRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Get netmap status response. -type GetNetmapStatusResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of get netmap status response message. - Body *GetNetmapStatusResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetNetmapStatusResponse) Reset() { - *x = GetNetmapStatusResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNetmapStatusResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNetmapStatusResponse) ProtoMessage() {} - -func (x *GetNetmapStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNetmapStatusResponse.ProtoReflect.Descriptor instead. -func (*GetNetmapStatusResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{5} -} - -func (x *GetNetmapStatusResponse) GetBody() *GetNetmapStatusResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetNetmapStatusResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Request to drop the objects. -type DropObjectsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of the request message. - Body *DropObjectsRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *DropObjectsRequest) Reset() { - *x = DropObjectsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DropObjectsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DropObjectsRequest) ProtoMessage() {} - -func (x *DropObjectsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DropObjectsRequest.ProtoReflect.Descriptor instead. -func (*DropObjectsRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{6} -} - -func (x *DropObjectsRequest) GetBody() *DropObjectsRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *DropObjectsRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Response to request to drop the objects. -type DropObjectsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of the response message. - Body *DropObjectsResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *DropObjectsResponse) Reset() { - *x = DropObjectsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DropObjectsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DropObjectsResponse) ProtoMessage() {} - -func (x *DropObjectsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DropObjectsResponse.ProtoReflect.Descriptor instead. -func (*DropObjectsResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{7} -} - -func (x *DropObjectsResponse) GetBody() *DropObjectsResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *DropObjectsResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Request to list all shards of the node. -type ListShardsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of the request message. - Body *ListShardsRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ListShardsRequest) Reset() { - *x = ListShardsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListShardsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListShardsRequest) ProtoMessage() {} - -func (x *ListShardsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListShardsRequest.ProtoReflect.Descriptor instead. -func (*ListShardsRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{8} -} - -func (x *ListShardsRequest) GetBody() *ListShardsRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ListShardsRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// ListShards response. -type ListShardsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of the response message. - Body *ListShardsResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ListShardsResponse) Reset() { - *x = ListShardsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListShardsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListShardsResponse) ProtoMessage() {} - -func (x *ListShardsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListShardsResponse.ProtoReflect.Descriptor instead. -func (*ListShardsResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{9} -} - -func (x *ListShardsResponse) GetBody() *ListShardsResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ListShardsResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Request to set mode of the shard. -type SetShardModeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of set shard mode request message. - Body *SetShardModeRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SetShardModeRequest) Reset() { - *x = SetShardModeRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetShardModeRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetShardModeRequest) ProtoMessage() {} - -func (x *SetShardModeRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetShardModeRequest.ProtoReflect.Descriptor instead. -func (*SetShardModeRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{10} -} - -func (x *SetShardModeRequest) GetBody() *SetShardModeRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *SetShardModeRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// SetShardMode response. -type SetShardModeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of set shard mode response message. - Body *SetShardModeResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SetShardModeResponse) Reset() { - *x = SetShardModeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetShardModeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetShardModeResponse) ProtoMessage() {} - -func (x *SetShardModeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetShardModeResponse.ProtoReflect.Descriptor instead. -func (*SetShardModeResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{11} -} - -func (x *SetShardModeResponse) GetBody() *SetShardModeResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *SetShardModeResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// SynchronizeTree request. -type SynchronizeTreeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of restore shard request message. - Body *SynchronizeTreeRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SynchronizeTreeRequest) Reset() { - *x = SynchronizeTreeRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SynchronizeTreeRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SynchronizeTreeRequest) ProtoMessage() {} - -func (x *SynchronizeTreeRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SynchronizeTreeRequest.ProtoReflect.Descriptor instead. -func (*SynchronizeTreeRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{12} -} - -func (x *SynchronizeTreeRequest) GetBody() *SynchronizeTreeRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *SynchronizeTreeRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// SynchronizeTree response. -type SynchronizeTreeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Body of restore shard response message. - Body *SynchronizeTreeResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Body signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SynchronizeTreeResponse) Reset() { - *x = SynchronizeTreeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SynchronizeTreeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SynchronizeTreeResponse) ProtoMessage() {} - -func (x *SynchronizeTreeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SynchronizeTreeResponse.ProtoReflect.Descriptor instead. -func (*SynchronizeTreeResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{13} -} - -func (x *SynchronizeTreeResponse) GetBody() *SynchronizeTreeResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *SynchronizeTreeResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// EvacuateShard request. -type EvacuateShardRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *EvacuateShardRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *EvacuateShardRequest) Reset() { - *x = EvacuateShardRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EvacuateShardRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EvacuateShardRequest) ProtoMessage() {} - -func (x *EvacuateShardRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EvacuateShardRequest.ProtoReflect.Descriptor instead. -func (*EvacuateShardRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{14} -} - -func (x *EvacuateShardRequest) GetBody() *EvacuateShardRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *EvacuateShardRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// EvacuateShard response. -type EvacuateShardResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *EvacuateShardResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *EvacuateShardResponse) Reset() { - *x = EvacuateShardResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EvacuateShardResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EvacuateShardResponse) ProtoMessage() {} - -func (x *EvacuateShardResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EvacuateShardResponse.ProtoReflect.Descriptor instead. -func (*EvacuateShardResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{15} -} - -func (x *EvacuateShardResponse) GetBody() *EvacuateShardResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *EvacuateShardResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// FlushCache request. -type FlushCacheRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *FlushCacheRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *FlushCacheRequest) Reset() { - *x = FlushCacheRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FlushCacheRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FlushCacheRequest) ProtoMessage() {} - -func (x *FlushCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FlushCacheRequest.ProtoReflect.Descriptor instead. -func (*FlushCacheRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{16} -} - -func (x *FlushCacheRequest) GetBody() *FlushCacheRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *FlushCacheRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// FlushCache response. -type FlushCacheResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *FlushCacheResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *FlushCacheResponse) Reset() { - *x = FlushCacheResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FlushCacheResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FlushCacheResponse) ProtoMessage() {} - -func (x *FlushCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FlushCacheResponse.ProtoReflect.Descriptor instead. -func (*FlushCacheResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{17} -} - -func (x *FlushCacheResponse) GetBody() *FlushCacheResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *FlushCacheResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Doctor request. -type DoctorRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *DoctorRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *DoctorRequest) Reset() { - *x = DoctorRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DoctorRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DoctorRequest) ProtoMessage() {} - -func (x *DoctorRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DoctorRequest.ProtoReflect.Descriptor instead. -func (*DoctorRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{18} -} - -func (x *DoctorRequest) GetBody() *DoctorRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *DoctorRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Doctor response. -type DoctorResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *DoctorResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *DoctorResponse) Reset() { - *x = DoctorResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DoctorResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DoctorResponse) ProtoMessage() {} - -func (x *DoctorResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DoctorResponse.ProtoReflect.Descriptor instead. -func (*DoctorResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{19} -} - -func (x *DoctorResponse) GetBody() *DoctorResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *DoctorResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// StartShardEvacuation request. -type StartShardEvacuationRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *StartShardEvacuationRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *StartShardEvacuationRequest) Reset() { - *x = StartShardEvacuationRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StartShardEvacuationRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartShardEvacuationRequest) ProtoMessage() {} - -func (x *StartShardEvacuationRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartShardEvacuationRequest.ProtoReflect.Descriptor instead. -func (*StartShardEvacuationRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{20} -} - -func (x *StartShardEvacuationRequest) GetBody() *StartShardEvacuationRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *StartShardEvacuationRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// StartShardEvacuation response. -type StartShardEvacuationResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *StartShardEvacuationResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *StartShardEvacuationResponse) Reset() { - *x = StartShardEvacuationResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StartShardEvacuationResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartShardEvacuationResponse) ProtoMessage() {} - -func (x *StartShardEvacuationResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartShardEvacuationResponse.ProtoReflect.Descriptor instead. -func (*StartShardEvacuationResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21} -} - -func (x *StartShardEvacuationResponse) GetBody() *StartShardEvacuationResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *StartShardEvacuationResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// GetShardEvacuationStatus request. -type GetShardEvacuationStatusRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *GetShardEvacuationStatusRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetShardEvacuationStatusRequest) Reset() { - *x = GetShardEvacuationStatusRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetShardEvacuationStatusRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetShardEvacuationStatusRequest) ProtoMessage() {} - -func (x *GetShardEvacuationStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetShardEvacuationStatusRequest.ProtoReflect.Descriptor instead. -func (*GetShardEvacuationStatusRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22} -} - -func (x *GetShardEvacuationStatusRequest) GetBody() *GetShardEvacuationStatusRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetShardEvacuationStatusRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// GetShardEvacuationStatus response. -type GetShardEvacuationStatusResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *GetShardEvacuationStatusResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetShardEvacuationStatusResponse) Reset() { - *x = GetShardEvacuationStatusResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetShardEvacuationStatusResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetShardEvacuationStatusResponse) ProtoMessage() {} - -func (x *GetShardEvacuationStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetShardEvacuationStatusResponse.ProtoReflect.Descriptor instead. -func (*GetShardEvacuationStatusResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23} -} - -func (x *GetShardEvacuationStatusResponse) GetBody() *GetShardEvacuationStatusResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetShardEvacuationStatusResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// ResetShardEvacuationStatus request. -type ResetShardEvacuationStatusRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *ResetShardEvacuationStatusRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ResetShardEvacuationStatusRequest) Reset() { - *x = ResetShardEvacuationStatusRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResetShardEvacuationStatusRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResetShardEvacuationStatusRequest) ProtoMessage() {} - -func (x *ResetShardEvacuationStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResetShardEvacuationStatusRequest.ProtoReflect.Descriptor instead. -func (*ResetShardEvacuationStatusRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24} -} - -func (x *ResetShardEvacuationStatusRequest) GetBody() *ResetShardEvacuationStatusRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ResetShardEvacuationStatusRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// ResetShardEvacuationStatus response. -type ResetShardEvacuationStatusResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *ResetShardEvacuationStatusResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ResetShardEvacuationStatusResponse) Reset() { - *x = ResetShardEvacuationStatusResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResetShardEvacuationStatusResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResetShardEvacuationStatusResponse) ProtoMessage() {} - -func (x *ResetShardEvacuationStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResetShardEvacuationStatusResponse.ProtoReflect.Descriptor instead. -func (*ResetShardEvacuationStatusResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25} -} - -func (x *ResetShardEvacuationStatusResponse) GetBody() *ResetShardEvacuationStatusResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ResetShardEvacuationStatusResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// StopShardEvacuation request. -type StopShardEvacuationRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *StopShardEvacuationRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *StopShardEvacuationRequest) Reset() { - *x = StopShardEvacuationRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StopShardEvacuationRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StopShardEvacuationRequest) ProtoMessage() {} - -func (x *StopShardEvacuationRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StopShardEvacuationRequest.ProtoReflect.Descriptor instead. -func (*StopShardEvacuationRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26} -} - -func (x *StopShardEvacuationRequest) GetBody() *StopShardEvacuationRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *StopShardEvacuationRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// StopShardEvacuation response. -type StopShardEvacuationResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *StopShardEvacuationResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *StopShardEvacuationResponse) Reset() { - *x = StopShardEvacuationResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StopShardEvacuationResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StopShardEvacuationResponse) ProtoMessage() {} - -func (x *StopShardEvacuationResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StopShardEvacuationResponse.ProtoReflect.Descriptor instead. -func (*StopShardEvacuationResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27} -} - -func (x *StopShardEvacuationResponse) GetBody() *StopShardEvacuationResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *StopShardEvacuationResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// AddChainLocalOverride request. -type AddChainLocalOverrideRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *AddChainLocalOverrideRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *AddChainLocalOverrideRequest) Reset() { - *x = AddChainLocalOverrideRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddChainLocalOverrideRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddChainLocalOverrideRequest) ProtoMessage() {} - -func (x *AddChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddChainLocalOverrideRequest.ProtoReflect.Descriptor instead. -func (*AddChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28} -} - -func (x *AddChainLocalOverrideRequest) GetBody() *AddChainLocalOverrideRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *AddChainLocalOverrideRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// AddChainLocalOverride response. -type AddChainLocalOverrideResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *AddChainLocalOverrideResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *AddChainLocalOverrideResponse) Reset() { - *x = AddChainLocalOverrideResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddChainLocalOverrideResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddChainLocalOverrideResponse) ProtoMessage() {} - -func (x *AddChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddChainLocalOverrideResponse.ProtoReflect.Descriptor instead. -func (*AddChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29} -} - -func (x *AddChainLocalOverrideResponse) GetBody() *AddChainLocalOverrideResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *AddChainLocalOverrideResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// GetChainLocalOverride request. -type GetChainLocalOverrideRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *GetChainLocalOverrideRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetChainLocalOverrideRequest) Reset() { - *x = GetChainLocalOverrideRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetChainLocalOverrideRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetChainLocalOverrideRequest) ProtoMessage() {} - -func (x *GetChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetChainLocalOverrideRequest.ProtoReflect.Descriptor instead. -func (*GetChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30} -} - -func (x *GetChainLocalOverrideRequest) GetBody() *GetChainLocalOverrideRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetChainLocalOverrideRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// GetChainLocalOverride response. -type GetChainLocalOverrideResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *GetChainLocalOverrideResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetChainLocalOverrideResponse) Reset() { - *x = GetChainLocalOverrideResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetChainLocalOverrideResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetChainLocalOverrideResponse) ProtoMessage() {} - -func (x *GetChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetChainLocalOverrideResponse.ProtoReflect.Descriptor instead. -func (*GetChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31} -} - -func (x *GetChainLocalOverrideResponse) GetBody() *GetChainLocalOverrideResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetChainLocalOverrideResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// ListChainLocalOverrides request. -type ListChainLocalOverridesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *ListChainLocalOverridesRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ListChainLocalOverridesRequest) Reset() { - *x = ListChainLocalOverridesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListChainLocalOverridesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListChainLocalOverridesRequest) ProtoMessage() {} - -func (x *ListChainLocalOverridesRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[32] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListChainLocalOverridesRequest.ProtoReflect.Descriptor instead. -func (*ListChainLocalOverridesRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32} -} - -func (x *ListChainLocalOverridesRequest) GetBody() *ListChainLocalOverridesRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ListChainLocalOverridesRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// ListChainLocalOverrides response. -type ListChainLocalOverridesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *ListChainLocalOverridesResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ListChainLocalOverridesResponse) Reset() { - *x = ListChainLocalOverridesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListChainLocalOverridesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListChainLocalOverridesResponse) ProtoMessage() {} - -func (x *ListChainLocalOverridesResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[33] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListChainLocalOverridesResponse.ProtoReflect.Descriptor instead. -func (*ListChainLocalOverridesResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33} -} - -func (x *ListChainLocalOverridesResponse) GetBody() *ListChainLocalOverridesResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ListChainLocalOverridesResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// ListTargetsLocalOverrides request. -type ListTargetsLocalOverridesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *ListTargetsLocalOverridesRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ListTargetsLocalOverridesRequest) Reset() { - *x = ListTargetsLocalOverridesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListTargetsLocalOverridesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListTargetsLocalOverridesRequest) ProtoMessage() {} - -func (x *ListTargetsLocalOverridesRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[34] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListTargetsLocalOverridesRequest.ProtoReflect.Descriptor instead. -func (*ListTargetsLocalOverridesRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34} -} - -func (x *ListTargetsLocalOverridesRequest) GetBody() *ListTargetsLocalOverridesRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ListTargetsLocalOverridesRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// ListTargetsLocalOverrides response. -type ListTargetsLocalOverridesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *ListTargetsLocalOverridesResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ListTargetsLocalOverridesResponse) Reset() { - *x = ListTargetsLocalOverridesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[35] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListTargetsLocalOverridesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListTargetsLocalOverridesResponse) ProtoMessage() {} - -func (x *ListTargetsLocalOverridesResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[35] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListTargetsLocalOverridesResponse.ProtoReflect.Descriptor instead. -func (*ListTargetsLocalOverridesResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35} -} - -func (x *ListTargetsLocalOverridesResponse) GetBody() *ListTargetsLocalOverridesResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ListTargetsLocalOverridesResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveChainLocalOverrideRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *RemoveChainLocalOverrideRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveChainLocalOverrideRequest) Reset() { - *x = RemoveChainLocalOverrideRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[36] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveChainLocalOverrideRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveChainLocalOverrideRequest) ProtoMessage() {} - -func (x *RemoveChainLocalOverrideRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[36] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveChainLocalOverrideRequest.ProtoReflect.Descriptor instead. -func (*RemoveChainLocalOverrideRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36} -} - -func (x *RemoveChainLocalOverrideRequest) GetBody() *RemoveChainLocalOverrideRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveChainLocalOverrideRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveChainLocalOverrideResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *RemoveChainLocalOverrideResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveChainLocalOverrideResponse) Reset() { - *x = RemoveChainLocalOverrideResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[37] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveChainLocalOverrideResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveChainLocalOverrideResponse) ProtoMessage() {} - -func (x *RemoveChainLocalOverrideResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[37] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveChainLocalOverrideResponse.ProtoReflect.Descriptor instead. -func (*RemoveChainLocalOverrideResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37} -} - -func (x *RemoveChainLocalOverrideResponse) GetBody() *RemoveChainLocalOverrideResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveChainLocalOverrideResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveChainLocalOverridesByTargetRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *RemoveChainLocalOverridesByTargetRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveChainLocalOverridesByTargetRequest) Reset() { - *x = RemoveChainLocalOverridesByTargetRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[38] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveChainLocalOverridesByTargetRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveChainLocalOverridesByTargetRequest) ProtoMessage() {} - -func (x *RemoveChainLocalOverridesByTargetRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[38] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveChainLocalOverridesByTargetRequest.ProtoReflect.Descriptor instead. -func (*RemoveChainLocalOverridesByTargetRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38} -} - -func (x *RemoveChainLocalOverridesByTargetRequest) GetBody() *RemoveChainLocalOverridesByTargetRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveChainLocalOverridesByTargetRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveChainLocalOverridesByTargetResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *RemoveChainLocalOverridesByTargetResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveChainLocalOverridesByTargetResponse) Reset() { - *x = RemoveChainLocalOverridesByTargetResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[39] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveChainLocalOverridesByTargetResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveChainLocalOverridesByTargetResponse) ProtoMessage() {} - -func (x *RemoveChainLocalOverridesByTargetResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[39] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveChainLocalOverridesByTargetResponse.ProtoReflect.Descriptor instead. -func (*RemoveChainLocalOverridesByTargetResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39} -} - -func (x *RemoveChainLocalOverridesByTargetResponse) GetBody() *RemoveChainLocalOverridesByTargetResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveChainLocalOverridesByTargetResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type SealWriteCacheRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *SealWriteCacheRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SealWriteCacheRequest) Reset() { - *x = SealWriteCacheRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[40] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SealWriteCacheRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SealWriteCacheRequest) ProtoMessage() {} - -func (x *SealWriteCacheRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[40] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SealWriteCacheRequest.ProtoReflect.Descriptor instead. -func (*SealWriteCacheRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{40} -} - -func (x *SealWriteCacheRequest) GetBody() *SealWriteCacheRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *SealWriteCacheRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type SealWriteCacheResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *SealWriteCacheResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *SealWriteCacheResponse) Reset() { - *x = SealWriteCacheResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[41] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SealWriteCacheResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SealWriteCacheResponse) ProtoMessage() {} - -func (x *SealWriteCacheResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[41] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SealWriteCacheResponse.ProtoReflect.Descriptor instead. -func (*SealWriteCacheResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41} -} - -func (x *SealWriteCacheResponse) GetBody() *SealWriteCacheResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *SealWriteCacheResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type DetachShardsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *DetachShardsRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *DetachShardsRequest) Reset() { - *x = DetachShardsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[42] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DetachShardsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DetachShardsRequest) ProtoMessage() {} - -func (x *DetachShardsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[42] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DetachShardsRequest.ProtoReflect.Descriptor instead. -func (*DetachShardsRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{42} -} - -func (x *DetachShardsRequest) GetBody() *DetachShardsRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *DetachShardsRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type DetachShardsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Body *DetachShardsResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *DetachShardsResponse) Reset() { - *x = DetachShardsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[43] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DetachShardsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DetachShardsResponse) ProtoMessage() {} - -func (x *DetachShardsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[43] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DetachShardsResponse.ProtoReflect.Descriptor instead. -func (*DetachShardsResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{43} -} - -func (x *DetachShardsResponse) GetBody() *DetachShardsResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *DetachShardsResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -// Health check request body. -type HealthCheckRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *HealthCheckRequest_Body) Reset() { - *x = HealthCheckRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[44] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheckRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckRequest_Body) ProtoMessage() {} - -func (x *HealthCheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[44] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckRequest_Body.ProtoReflect.Descriptor instead. -func (*HealthCheckRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{0, 0} -} - -// Health check response body -type HealthCheckResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Status of the storage node in FrostFS network map. - NetmapStatus NetmapStatus `protobuf:"varint,1,opt,name=netmap_status,json=netmapStatus,proto3,enum=control.NetmapStatus" json:"netmap_status,omitempty"` - // Health status of storage node application. - HealthStatus HealthStatus `protobuf:"varint,2,opt,name=health_status,json=healthStatus,proto3,enum=control.HealthStatus" json:"health_status,omitempty"` -} - -func (x *HealthCheckResponse_Body) Reset() { - *x = HealthCheckResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[45] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthCheckResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthCheckResponse_Body) ProtoMessage() {} - -func (x *HealthCheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[45] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthCheckResponse_Body.ProtoReflect.Descriptor instead. -func (*HealthCheckResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{1, 0} -} - -func (x *HealthCheckResponse_Body) GetNetmapStatus() NetmapStatus { - if x != nil { - return x.NetmapStatus - } - return NetmapStatus_STATUS_UNDEFINED -} - -func (x *HealthCheckResponse_Body) GetHealthStatus() HealthStatus { - if x != nil { - return x.HealthStatus - } - return HealthStatus_HEALTH_STATUS_UNDEFINED -} - -// Set netmap status request body. -type SetNetmapStatusRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // New storage node status in FrostFS network map. - // If status is MAINTENANCE, the node checks whether maintenance is - // allowed in the network settings. In case of prohibition, the request - // is denied. Otherwise, node switches to local maintenance state. To - // force local maintenance, use `force_maintenance` flag. - Status NetmapStatus `protobuf:"varint,1,opt,name=status,proto3,enum=control.NetmapStatus" json:"status,omitempty"` - // MAINTENANCE status validation skip flag. If set, node starts local - // maintenance regardless of network settings. The flag MUST NOT be - // set for any other status. - ForceMaintenance bool `protobuf:"varint,2,opt,name=force_maintenance,json=forceMaintenance,proto3" json:"force_maintenance,omitempty"` -} - -func (x *SetNetmapStatusRequest_Body) Reset() { - *x = SetNetmapStatusRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[46] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetNetmapStatusRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetNetmapStatusRequest_Body) ProtoMessage() {} - -func (x *SetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[46] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetNetmapStatusRequest_Body.ProtoReflect.Descriptor instead. -func (*SetNetmapStatusRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{2, 0} -} - -func (x *SetNetmapStatusRequest_Body) GetStatus() NetmapStatus { - if x != nil { - return x.Status - } - return NetmapStatus_STATUS_UNDEFINED -} - -func (x *SetNetmapStatusRequest_Body) GetForceMaintenance() bool { - if x != nil { - return x.ForceMaintenance - } - return false -} - -// Set netmap status response body -type SetNetmapStatusResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *SetNetmapStatusResponse_Body) Reset() { - *x = SetNetmapStatusResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[47] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetNetmapStatusResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetNetmapStatusResponse_Body) ProtoMessage() {} - -func (x *SetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[47] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetNetmapStatusResponse_Body.ProtoReflect.Descriptor instead. -func (*SetNetmapStatusResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{3, 0} -} - -type GetNetmapStatusRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetNetmapStatusRequest_Body) Reset() { - *x = GetNetmapStatusRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[48] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNetmapStatusRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNetmapStatusRequest_Body) ProtoMessage() {} - -func (x *GetNetmapStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[48] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNetmapStatusRequest_Body.ProtoReflect.Descriptor instead. -func (*GetNetmapStatusRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{4, 0} -} - -type GetNetmapStatusResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Storage node status in FrostFS network map. - Status NetmapStatus `protobuf:"varint,1,opt,name=status,proto3,enum=control.NetmapStatus" json:"status,omitempty"` - // Network map epoch. - Epoch uint64 `protobuf:"varint,2,opt,name=epoch,proto3" json:"epoch,omitempty"` -} - -func (x *GetNetmapStatusResponse_Body) Reset() { - *x = GetNetmapStatusResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[49] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNetmapStatusResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNetmapStatusResponse_Body) ProtoMessage() {} - -func (x *GetNetmapStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[49] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNetmapStatusResponse_Body.ProtoReflect.Descriptor instead. -func (*GetNetmapStatusResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{5, 0} -} - -func (x *GetNetmapStatusResponse_Body) GetStatus() NetmapStatus { - if x != nil { - return x.Status - } - return NetmapStatus_STATUS_UNDEFINED -} - -func (x *GetNetmapStatusResponse_Body) GetEpoch() uint64 { - if x != nil { - return x.Epoch - } - return 0 -} - -// Request body structure. -type DropObjectsRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of object addresses to be removed. - // in FrostFS API binary format. - AddressList [][]byte `protobuf:"bytes,1,rep,name=address_list,json=addressList,proto3" json:"address_list,omitempty"` -} - -func (x *DropObjectsRequest_Body) Reset() { - *x = DropObjectsRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[50] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DropObjectsRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DropObjectsRequest_Body) ProtoMessage() {} - -func (x *DropObjectsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[50] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DropObjectsRequest_Body.ProtoReflect.Descriptor instead. -func (*DropObjectsRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{6, 0} -} - -func (x *DropObjectsRequest_Body) GetAddressList() [][]byte { - if x != nil { - return x.AddressList - } - return nil -} - -// Response body structure. -type DropObjectsResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *DropObjectsResponse_Body) Reset() { - *x = DropObjectsResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[51] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DropObjectsResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DropObjectsResponse_Body) ProtoMessage() {} - -func (x *DropObjectsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[51] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DropObjectsResponse_Body.ProtoReflect.Descriptor instead. -func (*DropObjectsResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{7, 0} -} - -// Request body structure. -type ListShardsRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ListShardsRequest_Body) Reset() { - *x = ListShardsRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[52] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListShardsRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListShardsRequest_Body) ProtoMessage() {} - -func (x *ListShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[52] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListShardsRequest_Body.ProtoReflect.Descriptor instead. -func (*ListShardsRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{8, 0} -} - -// Response body structure. -type ListShardsResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of the node's shards. - Shards []*ShardInfo `protobuf:"bytes,1,rep,name=shards,proto3" json:"shards,omitempty"` -} - -func (x *ListShardsResponse_Body) Reset() { - *x = ListShardsResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[53] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListShardsResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListShardsResponse_Body) ProtoMessage() {} - -func (x *ListShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[53] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListShardsResponse_Body.ProtoReflect.Descriptor instead. -func (*ListShardsResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{9, 0} -} - -func (x *ListShardsResponse_Body) GetShards() []*ShardInfo { - if x != nil { - return x.Shards - } - return nil -} - -// Request body structure. -type SetShardModeRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the shard. - Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - // Mode that requested to be set. - Mode ShardMode `protobuf:"varint,2,opt,name=mode,proto3,enum=control.ShardMode" json:"mode,omitempty"` - // Flag signifying whether error counter should be set to 0. - ResetErrorCounter bool `protobuf:"varint,3,opt,name=resetErrorCounter,proto3" json:"resetErrorCounter,omitempty"` -} - -func (x *SetShardModeRequest_Body) Reset() { - *x = SetShardModeRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[54] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetShardModeRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetShardModeRequest_Body) ProtoMessage() {} - -func (x *SetShardModeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[54] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetShardModeRequest_Body.ProtoReflect.Descriptor instead. -func (*SetShardModeRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{10, 0} -} - -func (x *SetShardModeRequest_Body) GetShard_ID() [][]byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -func (x *SetShardModeRequest_Body) GetMode() ShardMode { - if x != nil { - return x.Mode - } - return ShardMode_SHARD_MODE_UNDEFINED -} - -func (x *SetShardModeRequest_Body) GetResetErrorCounter() bool { - if x != nil { - return x.ResetErrorCounter - } - return false -} - -// Response body structure. -type SetShardModeResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *SetShardModeResponse_Body) Reset() { - *x = SetShardModeResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[55] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SetShardModeResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SetShardModeResponse_Body) ProtoMessage() {} - -func (x *SetShardModeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[55] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SetShardModeResponse_Body.ProtoReflect.Descriptor instead. -func (*SetShardModeResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{11, 0} -} - -// Request body structure. -type SynchronizeTreeRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // Starting height for the synchronization. Can be omitted. - Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` -} - -func (x *SynchronizeTreeRequest_Body) Reset() { - *x = SynchronizeTreeRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[56] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SynchronizeTreeRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SynchronizeTreeRequest_Body) ProtoMessage() {} - -func (x *SynchronizeTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[56] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SynchronizeTreeRequest_Body.ProtoReflect.Descriptor instead. -func (*SynchronizeTreeRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{12, 0} -} - -func (x *SynchronizeTreeRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *SynchronizeTreeRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *SynchronizeTreeRequest_Body) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -// Response body structure. -type SynchronizeTreeResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *SynchronizeTreeResponse_Body) Reset() { - *x = SynchronizeTreeResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[57] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SynchronizeTreeResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SynchronizeTreeResponse_Body) ProtoMessage() {} - -func (x *SynchronizeTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[57] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SynchronizeTreeResponse_Body.ProtoReflect.Descriptor instead. -func (*SynchronizeTreeResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{13, 0} -} - -// Request body structure. -type EvacuateShardRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the shard. - Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - // Flag indicating whether object read errors should be ignored. - IgnoreErrors bool `protobuf:"varint,2,opt,name=ignore_errors,json=ignoreErrors,proto3" json:"ignore_errors,omitempty"` -} - -func (x *EvacuateShardRequest_Body) Reset() { - *x = EvacuateShardRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[58] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EvacuateShardRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EvacuateShardRequest_Body) ProtoMessage() {} - -func (x *EvacuateShardRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[58] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EvacuateShardRequest_Body.ProtoReflect.Descriptor instead. -func (*EvacuateShardRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{14, 0} -} - -func (x *EvacuateShardRequest_Body) GetShard_ID() [][]byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -func (x *EvacuateShardRequest_Body) GetIgnoreErrors() bool { - if x != nil { - return x.IgnoreErrors - } - return false -} - -// Response body structure. -type EvacuateShardResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Count uint32 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` -} - -func (x *EvacuateShardResponse_Body) Reset() { - *x = EvacuateShardResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[59] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *EvacuateShardResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EvacuateShardResponse_Body) ProtoMessage() {} - -func (x *EvacuateShardResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[59] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EvacuateShardResponse_Body.ProtoReflect.Descriptor instead. -func (*EvacuateShardResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{15, 0} -} - -func (x *EvacuateShardResponse_Body) GetCount() uint32 { - if x != nil { - return x.Count - } - return 0 -} - -// Request body structure. -type FlushCacheRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the shard. - Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - // If true, then writecache will be left in read-only mode after flush - // completed. - Seal bool `protobuf:"varint,2,opt,name=seal,proto3" json:"seal,omitempty"` -} - -func (x *FlushCacheRequest_Body) Reset() { - *x = FlushCacheRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[60] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FlushCacheRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FlushCacheRequest_Body) ProtoMessage() {} - -func (x *FlushCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[60] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FlushCacheRequest_Body.ProtoReflect.Descriptor instead. -func (*FlushCacheRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{16, 0} -} - -func (x *FlushCacheRequest_Body) GetShard_ID() [][]byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -func (x *FlushCacheRequest_Body) GetSeal() bool { - if x != nil { - return x.Seal - } - return false -} - -// Response body structure. -type FlushCacheResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *FlushCacheResponse_Body) Reset() { - *x = FlushCacheResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[61] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FlushCacheResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FlushCacheResponse_Body) ProtoMessage() {} - -func (x *FlushCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[61] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FlushCacheResponse_Body.ProtoReflect.Descriptor instead. -func (*FlushCacheResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{17, 0} -} - -// Request body structure. -type DoctorRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Number of threads to use for the operation. - Concurrency uint32 `protobuf:"varint,1,opt,name=concurrency,proto3" json:"concurrency,omitempty"` - // Flag to search engine for duplicate objects and leave only one copy. - RemoveDuplicates bool `protobuf:"varint,2,opt,name=remove_duplicates,json=removeDuplicates,proto3" json:"remove_duplicates,omitempty"` -} - -func (x *DoctorRequest_Body) Reset() { - *x = DoctorRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[62] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DoctorRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DoctorRequest_Body) ProtoMessage() {} - -func (x *DoctorRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[62] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DoctorRequest_Body.ProtoReflect.Descriptor instead. -func (*DoctorRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{18, 0} -} - -func (x *DoctorRequest_Body) GetConcurrency() uint32 { - if x != nil { - return x.Concurrency - } - return 0 -} - -func (x *DoctorRequest_Body) GetRemoveDuplicates() bool { - if x != nil { - return x.RemoveDuplicates - } - return false -} - -// Response body structure. -type DoctorResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *DoctorResponse_Body) Reset() { - *x = DoctorResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[63] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DoctorResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DoctorResponse_Body) ProtoMessage() {} - -func (x *DoctorResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[63] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DoctorResponse_Body.ProtoReflect.Descriptor instead. -func (*DoctorResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{19, 0} -} - -// Request body structure. -type StartShardEvacuationRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // IDs of the shards. - Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - // Flag indicating whether object read errors should be ignored. - IgnoreErrors bool `protobuf:"varint,2,opt,name=ignore_errors,json=ignoreErrors,proto3" json:"ignore_errors,omitempty"` - // Evacuation scope. - Scope uint32 `protobuf:"varint,3,opt,name=scope,proto3" json:"scope,omitempty"` -} - -func (x *StartShardEvacuationRequest_Body) Reset() { - *x = StartShardEvacuationRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[64] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StartShardEvacuationRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartShardEvacuationRequest_Body) ProtoMessage() {} - -func (x *StartShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[64] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartShardEvacuationRequest_Body.ProtoReflect.Descriptor instead. -func (*StartShardEvacuationRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{20, 0} -} - -func (x *StartShardEvacuationRequest_Body) GetShard_ID() [][]byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -func (x *StartShardEvacuationRequest_Body) GetIgnoreErrors() bool { - if x != nil { - return x.IgnoreErrors - } - return false -} - -func (x *StartShardEvacuationRequest_Body) GetScope() uint32 { - if x != nil { - return x.Scope - } - return 0 -} - -// Response body structure. -type StartShardEvacuationResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *StartShardEvacuationResponse_Body) Reset() { - *x = StartShardEvacuationResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[65] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StartShardEvacuationResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StartShardEvacuationResponse_Body) ProtoMessage() {} - -func (x *StartShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[65] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StartShardEvacuationResponse_Body.ProtoReflect.Descriptor instead. -func (*StartShardEvacuationResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{21, 0} -} - -// Request body structure. -type GetShardEvacuationStatusRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetShardEvacuationStatusRequest_Body) Reset() { - *x = GetShardEvacuationStatusRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[66] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetShardEvacuationStatusRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetShardEvacuationStatusRequest_Body) ProtoMessage() {} - -func (x *GetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[66] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetShardEvacuationStatusRequest_Body.ProtoReflect.Descriptor instead. -func (*GetShardEvacuationStatusRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{22, 0} -} - -// Response body structure. -type GetShardEvacuationStatusResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Total objects to evacuate count. The value is approximate, so evacuated + - // failed + skipped == total is not guaranteed after completion. - TotalObjects uint64 `protobuf:"varint,1,opt,name=total_objects,json=totalObjects,proto3" json:"total_objects,omitempty"` - // Evacuated objects count. - EvacuatedObjects uint64 `protobuf:"varint,2,opt,name=evacuated_objects,json=evacuatedObjects,proto3" json:"evacuated_objects,omitempty"` - // Failed objects count. - FailedObjects uint64 `protobuf:"varint,3,opt,name=failed_objects,json=failedObjects,proto3" json:"failed_objects,omitempty"` - // Shard IDs. - Shard_ID [][]byte `protobuf:"bytes,4,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - // Evacuation process status. - Status GetShardEvacuationStatusResponse_Body_Status `protobuf:"varint,5,opt,name=status,proto3,enum=control.GetShardEvacuationStatusResponse_Body_Status" json:"status,omitempty"` - // Evacuation process duration. - Duration *GetShardEvacuationStatusResponse_Body_Duration `protobuf:"bytes,6,opt,name=duration,proto3" json:"duration,omitempty"` - // Evacuation process started at timestamp. - StartedAt *GetShardEvacuationStatusResponse_Body_UnixTimestamp `protobuf:"bytes,7,opt,name=started_at,json=startedAt,proto3" json:"started_at,omitempty"` - // Error message if evacuation failed. - ErrorMessage string `protobuf:"bytes,8,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` - // Skipped objects count. - SkippedObjects uint64 `protobuf:"varint,9,opt,name=skipped_objects,json=skippedObjects,proto3" json:"skipped_objects,omitempty"` - // Total trees to evacuate count. - TotalTrees uint64 `protobuf:"varint,10,opt,name=total_trees,json=totalTrees,proto3" json:"total_trees,omitempty"` - // Evacuated trees count. - EvacuatedTrees uint64 `protobuf:"varint,11,opt,name=evacuated_trees,json=evacuatedTrees,proto3" json:"evacuated_trees,omitempty"` - // Failed trees count. - FailedTrees uint64 `protobuf:"varint,12,opt,name=failed_trees,json=failedTrees,proto3" json:"failed_trees,omitempty"` -} - -func (x *GetShardEvacuationStatusResponse_Body) Reset() { - *x = GetShardEvacuationStatusResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[67] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetShardEvacuationStatusResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetShardEvacuationStatusResponse_Body) ProtoMessage() {} - -func (x *GetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[67] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetShardEvacuationStatusResponse_Body.ProtoReflect.Descriptor instead. -func (*GetShardEvacuationStatusResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0} -} - -func (x *GetShardEvacuationStatusResponse_Body) GetTotalObjects() uint64 { - if x != nil { - return x.TotalObjects - } - return 0 -} - -func (x *GetShardEvacuationStatusResponse_Body) GetEvacuatedObjects() uint64 { - if x != nil { - return x.EvacuatedObjects - } - return 0 -} - -func (x *GetShardEvacuationStatusResponse_Body) GetFailedObjects() uint64 { - if x != nil { - return x.FailedObjects - } - return 0 -} - -func (x *GetShardEvacuationStatusResponse_Body) GetShard_ID() [][]byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -func (x *GetShardEvacuationStatusResponse_Body) GetStatus() GetShardEvacuationStatusResponse_Body_Status { - if x != nil { - return x.Status - } - return GetShardEvacuationStatusResponse_Body_EVACUATE_SHARD_STATUS_UNDEFINED -} - -func (x *GetShardEvacuationStatusResponse_Body) GetDuration() *GetShardEvacuationStatusResponse_Body_Duration { - if x != nil { - return x.Duration - } - return nil -} - -func (x *GetShardEvacuationStatusResponse_Body) GetStartedAt() *GetShardEvacuationStatusResponse_Body_UnixTimestamp { - if x != nil { - return x.StartedAt - } - return nil -} - -func (x *GetShardEvacuationStatusResponse_Body) GetErrorMessage() string { - if x != nil { - return x.ErrorMessage - } - return "" -} - -func (x *GetShardEvacuationStatusResponse_Body) GetSkippedObjects() uint64 { - if x != nil { - return x.SkippedObjects - } - return 0 -} - -func (x *GetShardEvacuationStatusResponse_Body) GetTotalTrees() uint64 { - if x != nil { - return x.TotalTrees - } - return 0 -} - -func (x *GetShardEvacuationStatusResponse_Body) GetEvacuatedTrees() uint64 { - if x != nil { - return x.EvacuatedTrees - } - return 0 -} - -func (x *GetShardEvacuationStatusResponse_Body) GetFailedTrees() uint64 { - if x != nil { - return x.FailedTrees - } - return 0 -} - -// Unix timestamp value. -type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) Reset() { - *x = GetShardEvacuationStatusResponse_Body_UnixTimestamp{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[68] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoMessage() {} - -func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[68] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetShardEvacuationStatusResponse_Body_UnixTimestamp.ProtoReflect.Descriptor instead. -func (*GetShardEvacuationStatusResponse_Body_UnixTimestamp) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0, 0} -} - -func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) GetValue() int64 { - if x != nil { - return x.Value - } - return 0 -} - -// Duration in seconds. -type GetShardEvacuationStatusResponse_Body_Duration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"` -} - -func (x *GetShardEvacuationStatusResponse_Body_Duration) Reset() { - *x = GetShardEvacuationStatusResponse_Body_Duration{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[69] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetShardEvacuationStatusResponse_Body_Duration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetShardEvacuationStatusResponse_Body_Duration) ProtoMessage() {} - -func (x *GetShardEvacuationStatusResponse_Body_Duration) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[69] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetShardEvacuationStatusResponse_Body_Duration.ProtoReflect.Descriptor instead. -func (*GetShardEvacuationStatusResponse_Body_Duration) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{23, 0, 1} -} - -func (x *GetShardEvacuationStatusResponse_Body_Duration) GetSeconds() int64 { - if x != nil { - return x.Seconds - } - return 0 -} - -type ResetShardEvacuationStatusRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ResetShardEvacuationStatusRequest_Body) Reset() { - *x = ResetShardEvacuationStatusRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[70] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResetShardEvacuationStatusRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResetShardEvacuationStatusRequest_Body) ProtoMessage() {} - -func (x *ResetShardEvacuationStatusRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[70] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResetShardEvacuationStatusRequest_Body.ProtoReflect.Descriptor instead. -func (*ResetShardEvacuationStatusRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{24, 0} -} - -type ResetShardEvacuationStatusResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ResetShardEvacuationStatusResponse_Body) Reset() { - *x = ResetShardEvacuationStatusResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[71] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ResetShardEvacuationStatusResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ResetShardEvacuationStatusResponse_Body) ProtoMessage() {} - -func (x *ResetShardEvacuationStatusResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[71] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ResetShardEvacuationStatusResponse_Body.ProtoReflect.Descriptor instead. -func (*ResetShardEvacuationStatusResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{25, 0} -} - -// Request body structure. -type StopShardEvacuationRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *StopShardEvacuationRequest_Body) Reset() { - *x = StopShardEvacuationRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[72] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StopShardEvacuationRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StopShardEvacuationRequest_Body) ProtoMessage() {} - -func (x *StopShardEvacuationRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[72] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StopShardEvacuationRequest_Body.ProtoReflect.Descriptor instead. -func (*StopShardEvacuationRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{26, 0} -} - -// Response body structure. -type StopShardEvacuationResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *StopShardEvacuationResponse_Body) Reset() { - *x = StopShardEvacuationResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[73] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *StopShardEvacuationResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StopShardEvacuationResponse_Body) ProtoMessage() {} - -func (x *StopShardEvacuationResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[73] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use StopShardEvacuationResponse_Body.ProtoReflect.Descriptor instead. -func (*StopShardEvacuationResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{27, 0} -} - -type AddChainLocalOverrideRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Target for which the overrides are applied. - Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` - // Serialized rule chain. If chain ID is left empty - // in the chain, then it will be generated and returned - // in the response. - Chain []byte `protobuf:"bytes,2,opt,name=chain,proto3" json:"chain,omitempty"` -} - -func (x *AddChainLocalOverrideRequest_Body) Reset() { - *x = AddChainLocalOverrideRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[74] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddChainLocalOverrideRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddChainLocalOverrideRequest_Body) ProtoMessage() {} - -func (x *AddChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[74] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. -func (*AddChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{28, 0} -} - -func (x *AddChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { - if x != nil { - return x.Target - } - return nil -} - -func (x *AddChainLocalOverrideRequest_Body) GetChain() []byte { - if x != nil { - return x.Chain - } - return nil -} - -type AddChainLocalOverrideResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Chain ID assigned for the added rule chain. - // If chain ID is left empty in the request, then - // it will be generated. - ChainId []byte `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` -} - -func (x *AddChainLocalOverrideResponse_Body) Reset() { - *x = AddChainLocalOverrideResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[75] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddChainLocalOverrideResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddChainLocalOverrideResponse_Body) ProtoMessage() {} - -func (x *AddChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[75] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. -func (*AddChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{29, 0} -} - -func (x *AddChainLocalOverrideResponse_Body) GetChainId() []byte { - if x != nil { - return x.ChainId - } - return nil -} - -type GetChainLocalOverrideRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Target for which the overrides are applied. - Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` - // Chain ID assigned for the added rule chain. - ChainId []byte `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` -} - -func (x *GetChainLocalOverrideRequest_Body) Reset() { - *x = GetChainLocalOverrideRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[76] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetChainLocalOverrideRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetChainLocalOverrideRequest_Body) ProtoMessage() {} - -func (x *GetChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[76] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. -func (*GetChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{30, 0} -} - -func (x *GetChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { - if x != nil { - return x.Target - } - return nil -} - -func (x *GetChainLocalOverrideRequest_Body) GetChainId() []byte { - if x != nil { - return x.ChainId - } - return nil -} - -type GetChainLocalOverrideResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Serialized rule chain. - Chain []byte `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` -} - -func (x *GetChainLocalOverrideResponse_Body) Reset() { - *x = GetChainLocalOverrideResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[77] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetChainLocalOverrideResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetChainLocalOverrideResponse_Body) ProtoMessage() {} - -func (x *GetChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[77] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. -func (*GetChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{31, 0} -} - -func (x *GetChainLocalOverrideResponse_Body) GetChain() []byte { - if x != nil { - return x.Chain - } - return nil -} - -type ListChainLocalOverridesRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Target for which the overrides are applied. - Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` -} - -func (x *ListChainLocalOverridesRequest_Body) Reset() { - *x = ListChainLocalOverridesRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[78] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListChainLocalOverridesRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListChainLocalOverridesRequest_Body) ProtoMessage() {} - -func (x *ListChainLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[78] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListChainLocalOverridesRequest_Body.ProtoReflect.Descriptor instead. -func (*ListChainLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{32, 0} -} - -func (x *ListChainLocalOverridesRequest_Body) GetTarget() *ChainTarget { - if x != nil { - return x.Target - } - return nil -} - -type ListChainLocalOverridesResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The list of serialized rule chain. - Chains [][]byte `protobuf:"bytes,1,rep,name=chains,proto3" json:"chains,omitempty"` -} - -func (x *ListChainLocalOverridesResponse_Body) Reset() { - *x = ListChainLocalOverridesResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[79] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListChainLocalOverridesResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListChainLocalOverridesResponse_Body) ProtoMessage() {} - -func (x *ListChainLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[79] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListChainLocalOverridesResponse_Body.ProtoReflect.Descriptor instead. -func (*ListChainLocalOverridesResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{33, 0} -} - -func (x *ListChainLocalOverridesResponse_Body) GetChains() [][]byte { - if x != nil { - return x.Chains - } - return nil -} - -type ListTargetsLocalOverridesRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Target for which the overrides are applied. - ChainName string `protobuf:"bytes,1,opt,name=chainName,proto3" json:"chainName,omitempty"` -} - -func (x *ListTargetsLocalOverridesRequest_Body) Reset() { - *x = ListTargetsLocalOverridesRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[80] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListTargetsLocalOverridesRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListTargetsLocalOverridesRequest_Body) ProtoMessage() {} - -func (x *ListTargetsLocalOverridesRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[80] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListTargetsLocalOverridesRequest_Body.ProtoReflect.Descriptor instead. -func (*ListTargetsLocalOverridesRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{34, 0} -} - -func (x *ListTargetsLocalOverridesRequest_Body) GetChainName() string { - if x != nil { - return x.ChainName - } - return "" -} - -type ListTargetsLocalOverridesResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The list of chain targets. - Targets []*ChainTarget `protobuf:"bytes,1,rep,name=targets,proto3" json:"targets,omitempty"` -} - -func (x *ListTargetsLocalOverridesResponse_Body) Reset() { - *x = ListTargetsLocalOverridesResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[81] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListTargetsLocalOverridesResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListTargetsLocalOverridesResponse_Body) ProtoMessage() {} - -func (x *ListTargetsLocalOverridesResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[81] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListTargetsLocalOverridesResponse_Body.ProtoReflect.Descriptor instead. -func (*ListTargetsLocalOverridesResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{35, 0} -} - -func (x *ListTargetsLocalOverridesResponse_Body) GetTargets() []*ChainTarget { - if x != nil { - return x.Targets - } - return nil -} - -type RemoveChainLocalOverrideRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Target for which the overrides are applied. - Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` - // Chain ID assigned for the added rule chain. - ChainId []byte `protobuf:"bytes,2,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` -} - -func (x *RemoveChainLocalOverrideRequest_Body) Reset() { - *x = RemoveChainLocalOverrideRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[82] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveChainLocalOverrideRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveChainLocalOverrideRequest_Body) ProtoMessage() {} - -func (x *RemoveChainLocalOverrideRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[82] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveChainLocalOverrideRequest_Body.ProtoReflect.Descriptor instead. -func (*RemoveChainLocalOverrideRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{36, 0} -} - -func (x *RemoveChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { - if x != nil { - return x.Target - } - return nil -} - -func (x *RemoveChainLocalOverrideRequest_Body) GetChainId() []byte { - if x != nil { - return x.ChainId - } - return nil -} - -type RemoveChainLocalOverrideResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *RemoveChainLocalOverrideResponse_Body) Reset() { - *x = RemoveChainLocalOverrideResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[83] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveChainLocalOverrideResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveChainLocalOverrideResponse_Body) ProtoMessage() {} - -func (x *RemoveChainLocalOverrideResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[83] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveChainLocalOverrideResponse_Body.ProtoReflect.Descriptor instead. -func (*RemoveChainLocalOverrideResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{37, 0} -} - -type RemoveChainLocalOverridesByTargetRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Target for which the overrides are applied. - Target *ChainTarget `protobuf:"bytes,1,opt,name=target,proto3" json:"target,omitempty"` -} - -func (x *RemoveChainLocalOverridesByTargetRequest_Body) Reset() { - *x = RemoveChainLocalOverridesByTargetRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[84] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveChainLocalOverridesByTargetRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveChainLocalOverridesByTargetRequest_Body) ProtoMessage() {} - -func (x *RemoveChainLocalOverridesByTargetRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[84] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveChainLocalOverridesByTargetRequest_Body.ProtoReflect.Descriptor instead. -func (*RemoveChainLocalOverridesByTargetRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{38, 0} -} - -func (x *RemoveChainLocalOverridesByTargetRequest_Body) GetTarget() *ChainTarget { - if x != nil { - return x.Target - } - return nil -} - -type RemoveChainLocalOverridesByTargetResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *RemoveChainLocalOverridesByTargetResponse_Body) Reset() { - *x = RemoveChainLocalOverridesByTargetResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[85] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveChainLocalOverridesByTargetResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveChainLocalOverridesByTargetResponse_Body) ProtoMessage() {} - -func (x *RemoveChainLocalOverridesByTargetResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[85] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveChainLocalOverridesByTargetResponse_Body.ProtoReflect.Descriptor instead. -func (*RemoveChainLocalOverridesByTargetResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{39, 0} -} - -// Request body structure. -type SealWriteCacheRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the shard. - Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - // Flag indicating whether object read errors should be ignored. - IgnoreErrors bool `protobuf:"varint,2,opt,name=ignore_errors,json=ignoreErrors,proto3" json:"ignore_errors,omitempty"` - // Flag indicating whether writecache will be sealed async. - Async bool `protobuf:"varint,3,opt,name=async,proto3" json:"async,omitempty"` - // If true, then writecache will be sealed, but mode will be restored to the current one. - RestoreMode bool `protobuf:"varint,4,opt,name=restore_mode,json=restoreMode,proto3" json:"restore_mode,omitempty"` - // If true, then writecache will shrink internal storage. - Shrink bool `protobuf:"varint,5,opt,name=shrink,proto3" json:"shrink,omitempty"` -} - -func (x *SealWriteCacheRequest_Body) Reset() { - *x = SealWriteCacheRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[86] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SealWriteCacheRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SealWriteCacheRequest_Body) ProtoMessage() {} - -func (x *SealWriteCacheRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[86] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SealWriteCacheRequest_Body.ProtoReflect.Descriptor instead. -func (*SealWriteCacheRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{40, 0} -} - -func (x *SealWriteCacheRequest_Body) GetShard_ID() [][]byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -func (x *SealWriteCacheRequest_Body) GetIgnoreErrors() bool { - if x != nil { - return x.IgnoreErrors - } - return false -} - -func (x *SealWriteCacheRequest_Body) GetAsync() bool { - if x != nil { - return x.Async - } - return false -} - -func (x *SealWriteCacheRequest_Body) GetRestoreMode() bool { - if x != nil { - return x.RestoreMode - } - return false -} - -func (x *SealWriteCacheRequest_Body) GetShrink() bool { - if x != nil { - return x.Shrink - } - return false -} - -type SealWriteCacheResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Results []*SealWriteCacheResponse_Body_Status `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` -} - -func (x *SealWriteCacheResponse_Body) Reset() { - *x = SealWriteCacheResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[87] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SealWriteCacheResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SealWriteCacheResponse_Body) ProtoMessage() {} - -func (x *SealWriteCacheResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[87] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SealWriteCacheResponse_Body.ProtoReflect.Descriptor instead. -func (*SealWriteCacheResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41, 0} -} - -func (x *SealWriteCacheResponse_Body) GetResults() []*SealWriteCacheResponse_Body_Status { - if x != nil { - return x.Results - } - return nil -} - -type SealWriteCacheResponse_Body_Status struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Shard_ID []byte `protobuf:"bytes,1,opt,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` - Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"` -} - -func (x *SealWriteCacheResponse_Body_Status) Reset() { - *x = SealWriteCacheResponse_Body_Status{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[88] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SealWriteCacheResponse_Body_Status) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SealWriteCacheResponse_Body_Status) ProtoMessage() {} - -func (x *SealWriteCacheResponse_Body_Status) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[88] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SealWriteCacheResponse_Body_Status.ProtoReflect.Descriptor instead. -func (*SealWriteCacheResponse_Body_Status) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{41, 0, 0} -} - -func (x *SealWriteCacheResponse_Body_Status) GetShard_ID() []byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -func (x *SealWriteCacheResponse_Body_Status) GetSuccess() bool { - if x != nil { - return x.Success - } - return false -} - -func (x *SealWriteCacheResponse_Body_Status) GetError() string { - if x != nil { - return x.Error - } - return "" -} - -type DetachShardsRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Shard_ID [][]byte `protobuf:"bytes,1,rep,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` -} - -func (x *DetachShardsRequest_Body) Reset() { - *x = DetachShardsRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[89] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DetachShardsRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DetachShardsRequest_Body) ProtoMessage() {} - -func (x *DetachShardsRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[89] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DetachShardsRequest_Body.ProtoReflect.Descriptor instead. -func (*DetachShardsRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{42, 0} -} - -func (x *DetachShardsRequest_Body) GetShard_ID() [][]byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -type DetachShardsResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *DetachShardsResponse_Body) Reset() { - *x = DetachShardsResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_service_proto_msgTypes[90] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DetachShardsResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DetachShardsResponse_Body) ProtoMessage() {} - -func (x *DetachShardsResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_service_proto_msgTypes[90] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DetachShardsResponse_Body.ProtoReflect.Descriptor instead. -func (*DetachShardsResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_control_service_proto_rawDescGZIP(), []int{43, 0} -} - -var File_pkg_services_control_service_proto protoreflect.FileDescriptor - -var file_pkg_services_control_service_proto_rawDesc = []byte{ - 0x0a, 0x22, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x1a, 0x20, 0x70, - 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x84, 0x01, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xfe, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x7e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x3a, 0x0a, 0x0d, 0x6e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x6e, - 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3a, 0x0a, 0x0d, 0x68, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0c, 0x68, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xe8, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x4e, - 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, - 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x62, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x6d, - 0x61, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x10, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x4d, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, - 0x63, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x22, 0x8c, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x22, 0xd3, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4b, 0x0a, 0x04, 0x42, - 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4e, 0x65, - 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x22, 0xa7, 0x01, 0x0a, 0x12, 0x44, 0x72, 0x6f, - 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x29, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x21, 0x0a, 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x0b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, - 0x73, 0x74, 0x22, 0x86, 0x01, 0x0a, 0x13, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x82, 0x01, 0x0a, 0x11, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x33, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x22, 0xb0, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x32, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x73, 0x22, 0xf7, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x1a, 0x77, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, - 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, - 0x2c, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x65, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, - 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x73, 0x65, - 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x88, 0x01, - 0x0a, 0x14, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe0, 0x01, 0x0a, 0x16, 0x53, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x5a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, - 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, - 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, - 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x8e, 0x01, 0x0a, 0x17, - 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xc8, 0x01, 0x0a, - 0x14, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x46, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, - 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, 0x6f, 0x72, - 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x22, 0xa0, 0x01, 0x0a, 0x15, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, 0x0a, 0x04, - 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xb1, 0x01, 0x0a, 0x11, 0x46, - 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x33, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, - 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x35, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, - 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x73, 0x65, 0x61, 0x6c, 0x22, 0x84, - 0x01, 0x0a, 0x12, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, - 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x55, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x64, - 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x10, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x73, 0x22, 0x7c, 0x0a, 0x0e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, - 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, - 0x98, 0x02, 0x0a, 0x1b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x87, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, - 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, - 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, - 0x29, 0x0a, 0x05, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, - 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, - 0x09, 0x0a, 0x05, 0x54, 0x52, 0x45, 0x45, 0x53, 0x10, 0x02, 0x22, 0x98, 0x01, 0x0a, 0x1c, 0x53, - 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x9e, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x89, 0x07, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0xee, 0x05, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, - 0x2b, 0x0a, 0x11, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x65, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, - 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x4d, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x53, 0x0a, - 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x55, 0x6e, 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, - 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x5f, - 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x73, - 0x6b, 0x69, 0x70, 0x70, 0x65, 0x64, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1f, 0x0a, - 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x73, 0x12, 0x27, - 0x0a, 0x0f, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, - 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x65, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, - 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x66, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x73, 0x1a, 0x25, 0x0a, 0x0d, 0x55, 0x6e, - 0x69, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x1a, 0x24, 0x0a, 0x08, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, - 0x07, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, - 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0x49, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x23, 0x0a, 0x1f, 0x45, 0x56, 0x41, 0x43, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x48, - 0x41, 0x52, 0x44, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, - 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x52, 0x55, 0x4e, 0x4e, 0x49, 0x4e, - 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44, - 0x10, 0x02, 0x22, 0xa2, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, - 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x22, 0x52, 0x65, 0x73, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, - 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x94, - 0x01, 0x0a, 0x1a, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x96, 0x01, 0x0a, 0x1b, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, - 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xdc, - 0x01, 0x0a, 0x1c, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x4a, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xb5, 0x01, - 0x0a, 0x1d, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xe1, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, - 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, - 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0xb0, 0x01, 0x0a, 0x1d, 0x47, 0x65, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x1c, - 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xca, 0x01, 0x0a, - 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x40, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb6, 0x01, 0x0a, 0x1f, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x1e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x73, 0x22, 0xbe, 0x01, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x24, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x4e, - 0x61, 0x6d, 0x65, 0x22, 0xd2, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x36, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2e, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, - 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0xe7, 0x01, 0x0a, 0x1f, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x4f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, - 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x49, 0x64, 0x22, 0xa0, 0x01, 0x0a, 0x20, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x42, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xde, 0x01, 0x0a, 0x28, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, - 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x4a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x34, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x06, - 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xb2, 0x01, 0x0a, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x9c, 0x02, 0x0a, 0x15, - 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x97, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, - 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x67, 0x6e, - 0x6f, 0x72, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x79, - 0x6e, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x12, - 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x4d, 0x6f, - 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x68, 0x72, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x06, 0x73, 0x68, 0x72, 0x69, 0x6e, 0x6b, 0x22, 0xa9, 0x02, 0x0a, 0x16, 0x53, - 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, - 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0xa2, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x45, 0x0a, 0x07, 0x72, 0x65, - 0x73, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x73, 0x1a, 0x53, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x73, - 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x13, 0x44, 0x65, 0x74, 0x61, 0x63, - 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x21, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x19, 0x0a, 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0c, 0x52, 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x44, - 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x65, 0x74, 0x61, - 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x30, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, - 0x04, 0x42, 0x6f, 0x64, 0x79, 0x32, 0x8b, 0x10, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x48, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, - 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, - 0x0a, 0x0b, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1b, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x72, 0x6f, 0x70, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x4b, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, - 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, - 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, - 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x12, - 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, - 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x12, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, - 0x61, 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x45, 0x76, 0x61, - 0x63, 0x75, 0x61, 0x74, 0x65, 0x53, 0x68, 0x61, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x63, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x53, 0x68, - 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, - 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x75, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x65, - 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x73, - 0x65, 0x74, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x60, 0x0a, 0x13, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, - 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, 0x76, 0x61, 0x63, 0x75, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x53, 0x68, 0x61, 0x72, 0x64, 0x45, - 0x76, 0x61, 0x63, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, - 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, - 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x43, 0x61, 0x63, 0x68, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x44, 0x6f, 0x63, 0x74, - 0x6f, 0x72, 0x12, 0x16, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, - 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, 0x6f, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x41, 0x64, - 0x64, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, - 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x66, 0x0a, 0x15, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x12, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, - 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x6c, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x27, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x6f, 0x0a, 0x18, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x28, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x8a, 0x01, 0x0a, 0x21, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x42, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, 0x79, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x42, - 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x72, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x12, 0x29, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x73, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x53, 0x65, 0x61, 0x6c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, - 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x2e, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x44, - 0x65, 0x74, 0x61, 0x63, 0x68, 0x53, 0x68, 0x61, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, - 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, - 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pkg_services_control_service_proto_rawDescOnce sync.Once - file_pkg_services_control_service_proto_rawDescData = file_pkg_services_control_service_proto_rawDesc -) - -func file_pkg_services_control_service_proto_rawDescGZIP() []byte { - file_pkg_services_control_service_proto_rawDescOnce.Do(func() { - file_pkg_services_control_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_control_service_proto_rawDescData) - }) - return file_pkg_services_control_service_proto_rawDescData -} - -var file_pkg_services_control_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_pkg_services_control_service_proto_msgTypes = make([]protoimpl.MessageInfo, 91) -var file_pkg_services_control_service_proto_goTypes = []interface{}{ - (StartShardEvacuationRequest_Body_Scope)(0), // 0: control.StartShardEvacuationRequest.Body.Scope - (GetShardEvacuationStatusResponse_Body_Status)(0), // 1: control.GetShardEvacuationStatusResponse.Body.Status - (*HealthCheckRequest)(nil), // 2: control.HealthCheckRequest - (*HealthCheckResponse)(nil), // 3: control.HealthCheckResponse - (*SetNetmapStatusRequest)(nil), // 4: control.SetNetmapStatusRequest - (*SetNetmapStatusResponse)(nil), // 5: control.SetNetmapStatusResponse - (*GetNetmapStatusRequest)(nil), // 6: control.GetNetmapStatusRequest - (*GetNetmapStatusResponse)(nil), // 7: control.GetNetmapStatusResponse - (*DropObjectsRequest)(nil), // 8: control.DropObjectsRequest - (*DropObjectsResponse)(nil), // 9: control.DropObjectsResponse - (*ListShardsRequest)(nil), // 10: control.ListShardsRequest - (*ListShardsResponse)(nil), // 11: control.ListShardsResponse - (*SetShardModeRequest)(nil), // 12: control.SetShardModeRequest - (*SetShardModeResponse)(nil), // 13: control.SetShardModeResponse - (*SynchronizeTreeRequest)(nil), // 14: control.SynchronizeTreeRequest - (*SynchronizeTreeResponse)(nil), // 15: control.SynchronizeTreeResponse - (*EvacuateShardRequest)(nil), // 16: control.EvacuateShardRequest - (*EvacuateShardResponse)(nil), // 17: control.EvacuateShardResponse - (*FlushCacheRequest)(nil), // 18: control.FlushCacheRequest - (*FlushCacheResponse)(nil), // 19: control.FlushCacheResponse - (*DoctorRequest)(nil), // 20: control.DoctorRequest - (*DoctorResponse)(nil), // 21: control.DoctorResponse - (*StartShardEvacuationRequest)(nil), // 22: control.StartShardEvacuationRequest - (*StartShardEvacuationResponse)(nil), // 23: control.StartShardEvacuationResponse - (*GetShardEvacuationStatusRequest)(nil), // 24: control.GetShardEvacuationStatusRequest - (*GetShardEvacuationStatusResponse)(nil), // 25: control.GetShardEvacuationStatusResponse - (*ResetShardEvacuationStatusRequest)(nil), // 26: control.ResetShardEvacuationStatusRequest - (*ResetShardEvacuationStatusResponse)(nil), // 27: control.ResetShardEvacuationStatusResponse - (*StopShardEvacuationRequest)(nil), // 28: control.StopShardEvacuationRequest - (*StopShardEvacuationResponse)(nil), // 29: control.StopShardEvacuationResponse - (*AddChainLocalOverrideRequest)(nil), // 30: control.AddChainLocalOverrideRequest - (*AddChainLocalOverrideResponse)(nil), // 31: control.AddChainLocalOverrideResponse - (*GetChainLocalOverrideRequest)(nil), // 32: control.GetChainLocalOverrideRequest - (*GetChainLocalOverrideResponse)(nil), // 33: control.GetChainLocalOverrideResponse - (*ListChainLocalOverridesRequest)(nil), // 34: control.ListChainLocalOverridesRequest - (*ListChainLocalOverridesResponse)(nil), // 35: control.ListChainLocalOverridesResponse - (*ListTargetsLocalOverridesRequest)(nil), // 36: control.ListTargetsLocalOverridesRequest - (*ListTargetsLocalOverridesResponse)(nil), // 37: control.ListTargetsLocalOverridesResponse - (*RemoveChainLocalOverrideRequest)(nil), // 38: control.RemoveChainLocalOverrideRequest - (*RemoveChainLocalOverrideResponse)(nil), // 39: control.RemoveChainLocalOverrideResponse - (*RemoveChainLocalOverridesByTargetRequest)(nil), // 40: control.RemoveChainLocalOverridesByTargetRequest - (*RemoveChainLocalOverridesByTargetResponse)(nil), // 41: control.RemoveChainLocalOverridesByTargetResponse - (*SealWriteCacheRequest)(nil), // 42: control.SealWriteCacheRequest - (*SealWriteCacheResponse)(nil), // 43: control.SealWriteCacheResponse - (*DetachShardsRequest)(nil), // 44: control.DetachShardsRequest - (*DetachShardsResponse)(nil), // 45: control.DetachShardsResponse - (*HealthCheckRequest_Body)(nil), // 46: control.HealthCheckRequest.Body - (*HealthCheckResponse_Body)(nil), // 47: control.HealthCheckResponse.Body - (*SetNetmapStatusRequest_Body)(nil), // 48: control.SetNetmapStatusRequest.Body - (*SetNetmapStatusResponse_Body)(nil), // 49: control.SetNetmapStatusResponse.Body - (*GetNetmapStatusRequest_Body)(nil), // 50: control.GetNetmapStatusRequest.Body - (*GetNetmapStatusResponse_Body)(nil), // 51: control.GetNetmapStatusResponse.Body - (*DropObjectsRequest_Body)(nil), // 52: control.DropObjectsRequest.Body - (*DropObjectsResponse_Body)(nil), // 53: control.DropObjectsResponse.Body - (*ListShardsRequest_Body)(nil), // 54: control.ListShardsRequest.Body - (*ListShardsResponse_Body)(nil), // 55: control.ListShardsResponse.Body - (*SetShardModeRequest_Body)(nil), // 56: control.SetShardModeRequest.Body - (*SetShardModeResponse_Body)(nil), // 57: control.SetShardModeResponse.Body - (*SynchronizeTreeRequest_Body)(nil), // 58: control.SynchronizeTreeRequest.Body - (*SynchronizeTreeResponse_Body)(nil), // 59: control.SynchronizeTreeResponse.Body - (*EvacuateShardRequest_Body)(nil), // 60: control.EvacuateShardRequest.Body - (*EvacuateShardResponse_Body)(nil), // 61: control.EvacuateShardResponse.Body - (*FlushCacheRequest_Body)(nil), // 62: control.FlushCacheRequest.Body - (*FlushCacheResponse_Body)(nil), // 63: control.FlushCacheResponse.Body - (*DoctorRequest_Body)(nil), // 64: control.DoctorRequest.Body - (*DoctorResponse_Body)(nil), // 65: control.DoctorResponse.Body - (*StartShardEvacuationRequest_Body)(nil), // 66: control.StartShardEvacuationRequest.Body - (*StartShardEvacuationResponse_Body)(nil), // 67: control.StartShardEvacuationResponse.Body - (*GetShardEvacuationStatusRequest_Body)(nil), // 68: control.GetShardEvacuationStatusRequest.Body - (*GetShardEvacuationStatusResponse_Body)(nil), // 69: control.GetShardEvacuationStatusResponse.Body - (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil), // 70: control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - (*GetShardEvacuationStatusResponse_Body_Duration)(nil), // 71: control.GetShardEvacuationStatusResponse.Body.Duration - (*ResetShardEvacuationStatusRequest_Body)(nil), // 72: control.ResetShardEvacuationStatusRequest.Body - (*ResetShardEvacuationStatusResponse_Body)(nil), // 73: control.ResetShardEvacuationStatusResponse.Body - (*StopShardEvacuationRequest_Body)(nil), // 74: control.StopShardEvacuationRequest.Body - (*StopShardEvacuationResponse_Body)(nil), // 75: control.StopShardEvacuationResponse.Body - (*AddChainLocalOverrideRequest_Body)(nil), // 76: control.AddChainLocalOverrideRequest.Body - (*AddChainLocalOverrideResponse_Body)(nil), // 77: control.AddChainLocalOverrideResponse.Body - (*GetChainLocalOverrideRequest_Body)(nil), // 78: control.GetChainLocalOverrideRequest.Body - (*GetChainLocalOverrideResponse_Body)(nil), // 79: control.GetChainLocalOverrideResponse.Body - (*ListChainLocalOverridesRequest_Body)(nil), // 80: control.ListChainLocalOverridesRequest.Body - (*ListChainLocalOverridesResponse_Body)(nil), // 81: control.ListChainLocalOverridesResponse.Body - (*ListTargetsLocalOverridesRequest_Body)(nil), // 82: control.ListTargetsLocalOverridesRequest.Body - (*ListTargetsLocalOverridesResponse_Body)(nil), // 83: control.ListTargetsLocalOverridesResponse.Body - (*RemoveChainLocalOverrideRequest_Body)(nil), // 84: control.RemoveChainLocalOverrideRequest.Body - (*RemoveChainLocalOverrideResponse_Body)(nil), // 85: control.RemoveChainLocalOverrideResponse.Body - (*RemoveChainLocalOverridesByTargetRequest_Body)(nil), // 86: control.RemoveChainLocalOverridesByTargetRequest.Body - (*RemoveChainLocalOverridesByTargetResponse_Body)(nil), // 87: control.RemoveChainLocalOverridesByTargetResponse.Body - (*SealWriteCacheRequest_Body)(nil), // 88: control.SealWriteCacheRequest.Body - (*SealWriteCacheResponse_Body)(nil), // 89: control.SealWriteCacheResponse.Body - (*SealWriteCacheResponse_Body_Status)(nil), // 90: control.SealWriteCacheResponse.Body.Status - (*DetachShardsRequest_Body)(nil), // 91: control.DetachShardsRequest.Body - (*DetachShardsResponse_Body)(nil), // 92: control.DetachShardsResponse.Body - (*Signature)(nil), // 93: control.Signature - (NetmapStatus)(0), // 94: control.NetmapStatus - (HealthStatus)(0), // 95: control.HealthStatus - (*ShardInfo)(nil), // 96: control.ShardInfo - (ShardMode)(0), // 97: control.ShardMode - (*ChainTarget)(nil), // 98: control.ChainTarget -} -var file_pkg_services_control_service_proto_depIdxs = []int32{ - 46, // 0: control.HealthCheckRequest.body:type_name -> control.HealthCheckRequest.Body - 93, // 1: control.HealthCheckRequest.signature:type_name -> control.Signature - 47, // 2: control.HealthCheckResponse.body:type_name -> control.HealthCheckResponse.Body - 93, // 3: control.HealthCheckResponse.signature:type_name -> control.Signature - 48, // 4: control.SetNetmapStatusRequest.body:type_name -> control.SetNetmapStatusRequest.Body - 93, // 5: control.SetNetmapStatusRequest.signature:type_name -> control.Signature - 49, // 6: control.SetNetmapStatusResponse.body:type_name -> control.SetNetmapStatusResponse.Body - 93, // 7: control.SetNetmapStatusResponse.signature:type_name -> control.Signature - 50, // 8: control.GetNetmapStatusRequest.body:type_name -> control.GetNetmapStatusRequest.Body - 93, // 9: control.GetNetmapStatusRequest.signature:type_name -> control.Signature - 51, // 10: control.GetNetmapStatusResponse.body:type_name -> control.GetNetmapStatusResponse.Body - 93, // 11: control.GetNetmapStatusResponse.signature:type_name -> control.Signature - 52, // 12: control.DropObjectsRequest.body:type_name -> control.DropObjectsRequest.Body - 93, // 13: control.DropObjectsRequest.signature:type_name -> control.Signature - 53, // 14: control.DropObjectsResponse.body:type_name -> control.DropObjectsResponse.Body - 93, // 15: control.DropObjectsResponse.signature:type_name -> control.Signature - 54, // 16: control.ListShardsRequest.body:type_name -> control.ListShardsRequest.Body - 93, // 17: control.ListShardsRequest.signature:type_name -> control.Signature - 55, // 18: control.ListShardsResponse.body:type_name -> control.ListShardsResponse.Body - 93, // 19: control.ListShardsResponse.signature:type_name -> control.Signature - 56, // 20: control.SetShardModeRequest.body:type_name -> control.SetShardModeRequest.Body - 93, // 21: control.SetShardModeRequest.signature:type_name -> control.Signature - 57, // 22: control.SetShardModeResponse.body:type_name -> control.SetShardModeResponse.Body - 93, // 23: control.SetShardModeResponse.signature:type_name -> control.Signature - 58, // 24: control.SynchronizeTreeRequest.body:type_name -> control.SynchronizeTreeRequest.Body - 93, // 25: control.SynchronizeTreeRequest.signature:type_name -> control.Signature - 59, // 26: control.SynchronizeTreeResponse.body:type_name -> control.SynchronizeTreeResponse.Body - 93, // 27: control.SynchronizeTreeResponse.signature:type_name -> control.Signature - 60, // 28: control.EvacuateShardRequest.body:type_name -> control.EvacuateShardRequest.Body - 93, // 29: control.EvacuateShardRequest.signature:type_name -> control.Signature - 61, // 30: control.EvacuateShardResponse.body:type_name -> control.EvacuateShardResponse.Body - 93, // 31: control.EvacuateShardResponse.signature:type_name -> control.Signature - 62, // 32: control.FlushCacheRequest.body:type_name -> control.FlushCacheRequest.Body - 93, // 33: control.FlushCacheRequest.signature:type_name -> control.Signature - 63, // 34: control.FlushCacheResponse.body:type_name -> control.FlushCacheResponse.Body - 93, // 35: control.FlushCacheResponse.signature:type_name -> control.Signature - 64, // 36: control.DoctorRequest.body:type_name -> control.DoctorRequest.Body - 93, // 37: control.DoctorRequest.signature:type_name -> control.Signature - 65, // 38: control.DoctorResponse.body:type_name -> control.DoctorResponse.Body - 93, // 39: control.DoctorResponse.signature:type_name -> control.Signature - 66, // 40: control.StartShardEvacuationRequest.body:type_name -> control.StartShardEvacuationRequest.Body - 93, // 41: control.StartShardEvacuationRequest.signature:type_name -> control.Signature - 67, // 42: control.StartShardEvacuationResponse.body:type_name -> control.StartShardEvacuationResponse.Body - 93, // 43: control.StartShardEvacuationResponse.signature:type_name -> control.Signature - 68, // 44: control.GetShardEvacuationStatusRequest.body:type_name -> control.GetShardEvacuationStatusRequest.Body - 93, // 45: control.GetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 69, // 46: control.GetShardEvacuationStatusResponse.body:type_name -> control.GetShardEvacuationStatusResponse.Body - 93, // 47: control.GetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 72, // 48: control.ResetShardEvacuationStatusRequest.body:type_name -> control.ResetShardEvacuationStatusRequest.Body - 93, // 49: control.ResetShardEvacuationStatusRequest.signature:type_name -> control.Signature - 73, // 50: control.ResetShardEvacuationStatusResponse.body:type_name -> control.ResetShardEvacuationStatusResponse.Body - 93, // 51: control.ResetShardEvacuationStatusResponse.signature:type_name -> control.Signature - 74, // 52: control.StopShardEvacuationRequest.body:type_name -> control.StopShardEvacuationRequest.Body - 93, // 53: control.StopShardEvacuationRequest.signature:type_name -> control.Signature - 75, // 54: control.StopShardEvacuationResponse.body:type_name -> control.StopShardEvacuationResponse.Body - 93, // 55: control.StopShardEvacuationResponse.signature:type_name -> control.Signature - 76, // 56: control.AddChainLocalOverrideRequest.body:type_name -> control.AddChainLocalOverrideRequest.Body - 93, // 57: control.AddChainLocalOverrideRequest.signature:type_name -> control.Signature - 77, // 58: control.AddChainLocalOverrideResponse.body:type_name -> control.AddChainLocalOverrideResponse.Body - 93, // 59: control.AddChainLocalOverrideResponse.signature:type_name -> control.Signature - 78, // 60: control.GetChainLocalOverrideRequest.body:type_name -> control.GetChainLocalOverrideRequest.Body - 93, // 61: control.GetChainLocalOverrideRequest.signature:type_name -> control.Signature - 79, // 62: control.GetChainLocalOverrideResponse.body:type_name -> control.GetChainLocalOverrideResponse.Body - 93, // 63: control.GetChainLocalOverrideResponse.signature:type_name -> control.Signature - 80, // 64: control.ListChainLocalOverridesRequest.body:type_name -> control.ListChainLocalOverridesRequest.Body - 93, // 65: control.ListChainLocalOverridesRequest.signature:type_name -> control.Signature - 81, // 66: control.ListChainLocalOverridesResponse.body:type_name -> control.ListChainLocalOverridesResponse.Body - 93, // 67: control.ListChainLocalOverridesResponse.signature:type_name -> control.Signature - 82, // 68: control.ListTargetsLocalOverridesRequest.body:type_name -> control.ListTargetsLocalOverridesRequest.Body - 93, // 69: control.ListTargetsLocalOverridesRequest.signature:type_name -> control.Signature - 83, // 70: control.ListTargetsLocalOverridesResponse.body:type_name -> control.ListTargetsLocalOverridesResponse.Body - 93, // 71: control.ListTargetsLocalOverridesResponse.signature:type_name -> control.Signature - 84, // 72: control.RemoveChainLocalOverrideRequest.body:type_name -> control.RemoveChainLocalOverrideRequest.Body - 93, // 73: control.RemoveChainLocalOverrideRequest.signature:type_name -> control.Signature - 85, // 74: control.RemoveChainLocalOverrideResponse.body:type_name -> control.RemoveChainLocalOverrideResponse.Body - 93, // 75: control.RemoveChainLocalOverrideResponse.signature:type_name -> control.Signature - 86, // 76: control.RemoveChainLocalOverridesByTargetRequest.body:type_name -> control.RemoveChainLocalOverridesByTargetRequest.Body - 93, // 77: control.RemoveChainLocalOverridesByTargetRequest.signature:type_name -> control.Signature - 87, // 78: control.RemoveChainLocalOverridesByTargetResponse.body:type_name -> control.RemoveChainLocalOverridesByTargetResponse.Body - 93, // 79: control.RemoveChainLocalOverridesByTargetResponse.signature:type_name -> control.Signature - 88, // 80: control.SealWriteCacheRequest.body:type_name -> control.SealWriteCacheRequest.Body - 93, // 81: control.SealWriteCacheRequest.signature:type_name -> control.Signature - 89, // 82: control.SealWriteCacheResponse.body:type_name -> control.SealWriteCacheResponse.Body - 93, // 83: control.SealWriteCacheResponse.signature:type_name -> control.Signature - 91, // 84: control.DetachShardsRequest.body:type_name -> control.DetachShardsRequest.Body - 93, // 85: control.DetachShardsRequest.signature:type_name -> control.Signature - 92, // 86: control.DetachShardsResponse.body:type_name -> control.DetachShardsResponse.Body - 93, // 87: control.DetachShardsResponse.signature:type_name -> control.Signature - 94, // 88: control.HealthCheckResponse.Body.netmap_status:type_name -> control.NetmapStatus - 95, // 89: control.HealthCheckResponse.Body.health_status:type_name -> control.HealthStatus - 94, // 90: control.SetNetmapStatusRequest.Body.status:type_name -> control.NetmapStatus - 94, // 91: control.GetNetmapStatusResponse.Body.status:type_name -> control.NetmapStatus - 96, // 92: control.ListShardsResponse.Body.shards:type_name -> control.ShardInfo - 97, // 93: control.SetShardModeRequest.Body.mode:type_name -> control.ShardMode - 1, // 94: control.GetShardEvacuationStatusResponse.Body.status:type_name -> control.GetShardEvacuationStatusResponse.Body.Status - 71, // 95: control.GetShardEvacuationStatusResponse.Body.duration:type_name -> control.GetShardEvacuationStatusResponse.Body.Duration - 70, // 96: control.GetShardEvacuationStatusResponse.Body.started_at:type_name -> control.GetShardEvacuationStatusResponse.Body.UnixTimestamp - 98, // 97: control.AddChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 98, // 98: control.GetChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 98, // 99: control.ListChainLocalOverridesRequest.Body.target:type_name -> control.ChainTarget - 98, // 100: control.ListTargetsLocalOverridesResponse.Body.targets:type_name -> control.ChainTarget - 98, // 101: control.RemoveChainLocalOverrideRequest.Body.target:type_name -> control.ChainTarget - 98, // 102: control.RemoveChainLocalOverridesByTargetRequest.Body.target:type_name -> control.ChainTarget - 90, // 103: control.SealWriteCacheResponse.Body.results:type_name -> control.SealWriteCacheResponse.Body.Status - 2, // 104: control.ControlService.HealthCheck:input_type -> control.HealthCheckRequest - 4, // 105: control.ControlService.SetNetmapStatus:input_type -> control.SetNetmapStatusRequest - 6, // 106: control.ControlService.GetNetmapStatus:input_type -> control.GetNetmapStatusRequest - 8, // 107: control.ControlService.DropObjects:input_type -> control.DropObjectsRequest - 10, // 108: control.ControlService.ListShards:input_type -> control.ListShardsRequest - 12, // 109: control.ControlService.SetShardMode:input_type -> control.SetShardModeRequest - 14, // 110: control.ControlService.SynchronizeTree:input_type -> control.SynchronizeTreeRequest - 16, // 111: control.ControlService.EvacuateShard:input_type -> control.EvacuateShardRequest - 22, // 112: control.ControlService.StartShardEvacuation:input_type -> control.StartShardEvacuationRequest - 24, // 113: control.ControlService.GetShardEvacuationStatus:input_type -> control.GetShardEvacuationStatusRequest - 26, // 114: control.ControlService.ResetShardEvacuationStatus:input_type -> control.ResetShardEvacuationStatusRequest - 28, // 115: control.ControlService.StopShardEvacuation:input_type -> control.StopShardEvacuationRequest - 18, // 116: control.ControlService.FlushCache:input_type -> control.FlushCacheRequest - 20, // 117: control.ControlService.Doctor:input_type -> control.DoctorRequest - 30, // 118: control.ControlService.AddChainLocalOverride:input_type -> control.AddChainLocalOverrideRequest - 32, // 119: control.ControlService.GetChainLocalOverride:input_type -> control.GetChainLocalOverrideRequest - 34, // 120: control.ControlService.ListChainLocalOverrides:input_type -> control.ListChainLocalOverridesRequest - 38, // 121: control.ControlService.RemoveChainLocalOverride:input_type -> control.RemoveChainLocalOverrideRequest - 40, // 122: control.ControlService.RemoveChainLocalOverridesByTarget:input_type -> control.RemoveChainLocalOverridesByTargetRequest - 36, // 123: control.ControlService.ListTargetsLocalOverrides:input_type -> control.ListTargetsLocalOverridesRequest - 42, // 124: control.ControlService.SealWriteCache:input_type -> control.SealWriteCacheRequest - 44, // 125: control.ControlService.DetachShards:input_type -> control.DetachShardsRequest - 3, // 126: control.ControlService.HealthCheck:output_type -> control.HealthCheckResponse - 5, // 127: control.ControlService.SetNetmapStatus:output_type -> control.SetNetmapStatusResponse - 7, // 128: control.ControlService.GetNetmapStatus:output_type -> control.GetNetmapStatusResponse - 9, // 129: control.ControlService.DropObjects:output_type -> control.DropObjectsResponse - 11, // 130: control.ControlService.ListShards:output_type -> control.ListShardsResponse - 13, // 131: control.ControlService.SetShardMode:output_type -> control.SetShardModeResponse - 15, // 132: control.ControlService.SynchronizeTree:output_type -> control.SynchronizeTreeResponse - 17, // 133: control.ControlService.EvacuateShard:output_type -> control.EvacuateShardResponse - 23, // 134: control.ControlService.StartShardEvacuation:output_type -> control.StartShardEvacuationResponse - 25, // 135: control.ControlService.GetShardEvacuationStatus:output_type -> control.GetShardEvacuationStatusResponse - 27, // 136: control.ControlService.ResetShardEvacuationStatus:output_type -> control.ResetShardEvacuationStatusResponse - 29, // 137: control.ControlService.StopShardEvacuation:output_type -> control.StopShardEvacuationResponse - 19, // 138: control.ControlService.FlushCache:output_type -> control.FlushCacheResponse - 21, // 139: control.ControlService.Doctor:output_type -> control.DoctorResponse - 31, // 140: control.ControlService.AddChainLocalOverride:output_type -> control.AddChainLocalOverrideResponse - 33, // 141: control.ControlService.GetChainLocalOverride:output_type -> control.GetChainLocalOverrideResponse - 35, // 142: control.ControlService.ListChainLocalOverrides:output_type -> control.ListChainLocalOverridesResponse - 39, // 143: control.ControlService.RemoveChainLocalOverride:output_type -> control.RemoveChainLocalOverrideResponse - 41, // 144: control.ControlService.RemoveChainLocalOverridesByTarget:output_type -> control.RemoveChainLocalOverridesByTargetResponse - 37, // 145: control.ControlService.ListTargetsLocalOverrides:output_type -> control.ListTargetsLocalOverridesResponse - 43, // 146: control.ControlService.SealWriteCache:output_type -> control.SealWriteCacheResponse - 45, // 147: control.ControlService.DetachShards:output_type -> control.DetachShardsResponse - 126, // [126:148] is the sub-list for method output_type - 104, // [104:126] is the sub-list for method input_type - 104, // [104:104] is the sub-list for extension type_name - 104, // [104:104] is the sub-list for extension extendee - 0, // [0:104] is the sub-list for field type_name -} - -func init() { file_pkg_services_control_service_proto_init() } -func file_pkg_services_control_service_proto_init() { - if File_pkg_services_control_service_proto != nil { - return - } - file_pkg_services_control_types_proto_init() - if !protoimpl.UnsafeEnabled { - file_pkg_services_control_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNetmapStatusRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNetmapStatusResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverridesByTargetRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverridesByTargetResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthCheckResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetNetmapStatusResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNetmapStatusRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNetmapStatusResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DropObjectsResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListShardsResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SetShardModeResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SynchronizeTreeResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EvacuateShardResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FlushCacheResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DoctorResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StartShardEvacuationResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_UnixTimestamp); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetShardEvacuationStatusResponse_Body_Duration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ResetShardEvacuationStatusResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StopShardEvacuationResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddChainLocalOverrideResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetChainLocalOverrideResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListChainLocalOverridesResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListTargetsLocalOverridesResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverrideResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverridesByTargetRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveChainLocalOverridesByTargetResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SealWriteCacheResponse_Body_Status); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_service_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DetachShardsResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pkg_services_control_service_proto_rawDesc, - NumEnums: 2, - NumMessages: 91, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_pkg_services_control_service_proto_goTypes, - DependencyIndexes: file_pkg_services_control_service_proto_depIdxs, - EnumInfos: file_pkg_services_control_service_proto_enumTypes, - MessageInfos: file_pkg_services_control_service_proto_msgTypes, - }.Build() - File_pkg_services_control_service_proto = out.File - file_pkg_services_control_service_proto_rawDesc = nil - file_pkg_services_control_service_proto_goTypes = nil - file_pkg_services_control_service_proto_depIdxs = nil -} diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 822244e77d..afd1c3c41d 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2,7 +2,27 @@ package control -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import ( + json "encoding/json" + fmt "fmt" + pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + easyproto "github.com/VictoriaMetrics/easyproto" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" + strconv "strconv" +) + +type HealthCheckRequest_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*HealthCheckRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*HealthCheckRequest_Body)(nil) + _ json.Marshaler = (*HealthCheckRequest_Body)(nil) + _ json.Unmarshaler = (*HealthCheckRequest_Body)(nil) +) // StableSize returns the size of x in protobuf format. // @@ -14,18 +34,93 @@ func (x *HealthCheckRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthCheckRequest_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthCheckRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthCheckRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthCheckRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthCheckRequest_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthCheckRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthCheckRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthCheckRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthCheckRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthCheckRequest struct { + Body *HealthCheckRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*HealthCheckRequest)(nil) + _ encoding.ProtoUnmarshaler = (*HealthCheckRequest)(nil) + _ json.Marshaler = (*HealthCheckRequest)(nil) + _ json.Unmarshaler = (*HealthCheckRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -38,27 +133,6 @@ func (x *HealthCheckRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthCheckRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -74,13 +148,165 @@ func (x *HealthCheckRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *HealthCheckRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *HealthCheckRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthCheckRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthCheckRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthCheckRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthCheckRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(HealthCheckRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *HealthCheckRequest) GetBody() *HealthCheckRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *HealthCheckRequest) SetBody(v *HealthCheckRequest_Body) { + x.Body = v +} +func (x *HealthCheckRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *HealthCheckRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthCheckRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthCheckRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthCheckRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthCheckRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *HealthCheckRequest_Body + f = new(HealthCheckRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthCheckResponse_Body struct { + NetmapStatus NetmapStatus `json:"netmapStatus"` + HealthStatus HealthStatus `json:"healthStatus"` +} + +var ( + _ encoding.ProtoMarshaler = (*HealthCheckResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*HealthCheckResponse_Body)(nil) + _ json.Marshaler = (*HealthCheckResponse_Body)(nil) + _ json.Unmarshaler = (*HealthCheckResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -93,27 +319,186 @@ func (x *HealthCheckResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthCheckResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.EnumMarshal(1, buf[offset:], int32(x.NetmapStatus)) - offset += proto.EnumMarshal(2, buf[offset:], int32(x.HealthStatus)) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthCheckResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthCheckResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if int32(x.NetmapStatus) != 0 { + mm.AppendInt32(1, int32(x.NetmapStatus)) + } + if int32(x.HealthStatus) != 0 { + mm.AppendInt32(2, int32(x.HealthStatus)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthCheckResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthCheckResponse_Body") + } + switch fc.FieldNum { + case 1: // NetmapStatus + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "NetmapStatus") + } + x.NetmapStatus = NetmapStatus(data) + case 2: // HealthStatus + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "HealthStatus") + } + x.HealthStatus = HealthStatus(data) + } + } + return nil +} +func (x *HealthCheckResponse_Body) GetNetmapStatus() NetmapStatus { + if x != nil { + return x.NetmapStatus + } + return 0 +} +func (x *HealthCheckResponse_Body) SetNetmapStatus(v NetmapStatus) { + x.NetmapStatus = v +} +func (x *HealthCheckResponse_Body) GetHealthStatus() HealthStatus { + if x != nil { + return x.HealthStatus + } + return 0 +} +func (x *HealthCheckResponse_Body) SetHealthStatus(v HealthStatus) { + x.HealthStatus = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthCheckResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthCheckResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"netmapStatus\":" + out.RawString(prefix[1:]) + out.Int32(int32(x.NetmapStatus)) + } + { + const prefix string = ",\"healthStatus\":" + out.RawString(prefix) + out.Int32(int32(x.HealthStatus)) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthCheckResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthCheckResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "netmapStatus": + { + var f NetmapStatus + var parsedValue NetmapStatus + switch v := in.Interface().(type) { + case string: + if vv, ok := NetmapStatus_value[v]; ok { + parsedValue = NetmapStatus(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = NetmapStatus(vv) + case float64: + parsedValue = NetmapStatus(v) + } + f = parsedValue + x.NetmapStatus = f + } + case "healthStatus": + { + var f HealthStatus + var parsedValue HealthStatus + switch v := in.Interface().(type) { + case string: + if vv, ok := HealthStatus_value[v]; ok { + parsedValue = HealthStatus(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = HealthStatus(vv) + case float64: + parsedValue = HealthStatus(v) + } + f = parsedValue + x.HealthStatus = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthCheckResponse struct { + Body *HealthCheckResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*HealthCheckResponse)(nil) + _ encoding.ProtoUnmarshaler = (*HealthCheckResponse)(nil) + _ json.Marshaler = (*HealthCheckResponse)(nil) + _ json.Unmarshaler = (*HealthCheckResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -126,27 +511,6 @@ func (x *HealthCheckResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthCheckResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -162,13 +526,165 @@ func (x *HealthCheckResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *HealthCheckResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *HealthCheckResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthCheckResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthCheckResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthCheckResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthCheckResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(HealthCheckResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *HealthCheckResponse) GetBody() *HealthCheckResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *HealthCheckResponse) SetBody(v *HealthCheckResponse_Body) { + x.Body = v +} +func (x *HealthCheckResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *HealthCheckResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthCheckResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthCheckResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthCheckResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthCheckResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *HealthCheckResponse_Body + f = new(HealthCheckResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SetNetmapStatusRequest_Body struct { + Status NetmapStatus `json:"status"` + ForceMaintenance bool `json:"forceMaintenance"` +} + +var ( + _ encoding.ProtoMarshaler = (*SetNetmapStatusRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*SetNetmapStatusRequest_Body)(nil) + _ json.Marshaler = (*SetNetmapStatusRequest_Body)(nil) + _ json.Unmarshaler = (*SetNetmapStatusRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -181,27 +697,170 @@ func (x *SetNetmapStatusRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SetNetmapStatusRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.EnumMarshal(1, buf[offset:], int32(x.Status)) - offset += proto.BoolMarshal(2, buf[offset:], x.ForceMaintenance) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SetNetmapStatusRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SetNetmapStatusRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if int32(x.Status) != 0 { + mm.AppendInt32(1, int32(x.Status)) + } + if x.ForceMaintenance { + mm.AppendBool(2, x.ForceMaintenance) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SetNetmapStatusRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SetNetmapStatusRequest_Body") + } + switch fc.FieldNum { + case 1: // Status + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Status") + } + x.Status = NetmapStatus(data) + case 2: // ForceMaintenance + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ForceMaintenance") + } + x.ForceMaintenance = data + } + } + return nil +} +func (x *SetNetmapStatusRequest_Body) GetStatus() NetmapStatus { + if x != nil { + return x.Status + } + return 0 +} +func (x *SetNetmapStatusRequest_Body) SetStatus(v NetmapStatus) { + x.Status = v +} +func (x *SetNetmapStatusRequest_Body) GetForceMaintenance() bool { + if x != nil { + return x.ForceMaintenance + } + return false +} +func (x *SetNetmapStatusRequest_Body) SetForceMaintenance(v bool) { + x.ForceMaintenance = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SetNetmapStatusRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SetNetmapStatusRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"status\":" + out.RawString(prefix[1:]) + out.Int32(int32(x.Status)) + } + { + const prefix string = ",\"forceMaintenance\":" + out.RawString(prefix) + out.Bool(x.ForceMaintenance) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SetNetmapStatusRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SetNetmapStatusRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "status": + { + var f NetmapStatus + var parsedValue NetmapStatus + switch v := in.Interface().(type) { + case string: + if vv, ok := NetmapStatus_value[v]; ok { + parsedValue = NetmapStatus(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = NetmapStatus(vv) + case float64: + parsedValue = NetmapStatus(v) + } + f = parsedValue + x.Status = f + } + case "forceMaintenance": + { + var f bool + f = in.Bool() + x.ForceMaintenance = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SetNetmapStatusRequest struct { + Body *SetNetmapStatusRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*SetNetmapStatusRequest)(nil) + _ encoding.ProtoUnmarshaler = (*SetNetmapStatusRequest)(nil) + _ json.Marshaler = (*SetNetmapStatusRequest)(nil) + _ json.Unmarshaler = (*SetNetmapStatusRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -214,27 +873,6 @@ func (x *SetNetmapStatusRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SetNetmapStatusRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -250,13 +888,163 @@ func (x *SetNetmapStatusRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *SetNetmapStatusRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *SetNetmapStatusRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SetNetmapStatusRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SetNetmapStatusRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SetNetmapStatusRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SetNetmapStatusRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(SetNetmapStatusRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SetNetmapStatusRequest) GetBody() *SetNetmapStatusRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *SetNetmapStatusRequest) SetBody(v *SetNetmapStatusRequest_Body) { + x.Body = v +} +func (x *SetNetmapStatusRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *SetNetmapStatusRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SetNetmapStatusRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SetNetmapStatusRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SetNetmapStatusRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SetNetmapStatusRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *SetNetmapStatusRequest_Body + f = new(SetNetmapStatusRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SetNetmapStatusResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*SetNetmapStatusResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*SetNetmapStatusResponse_Body)(nil) + _ json.Marshaler = (*SetNetmapStatusResponse_Body)(nil) + _ json.Unmarshaler = (*SetNetmapStatusResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -267,18 +1055,93 @@ func (x *SetNetmapStatusResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SetNetmapStatusResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SetNetmapStatusResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SetNetmapStatusResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SetNetmapStatusResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SetNetmapStatusResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SetNetmapStatusResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SetNetmapStatusResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SetNetmapStatusResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SetNetmapStatusResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SetNetmapStatusResponse struct { + Body *SetNetmapStatusResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*SetNetmapStatusResponse)(nil) + _ encoding.ProtoUnmarshaler = (*SetNetmapStatusResponse)(nil) + _ json.Marshaler = (*SetNetmapStatusResponse)(nil) + _ json.Unmarshaler = (*SetNetmapStatusResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -291,27 +1154,6 @@ func (x *SetNetmapStatusResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SetNetmapStatusResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -327,13 +1169,163 @@ func (x *SetNetmapStatusResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *SetNetmapStatusResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *SetNetmapStatusResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SetNetmapStatusResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SetNetmapStatusResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SetNetmapStatusResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SetNetmapStatusResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(SetNetmapStatusResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SetNetmapStatusResponse) GetBody() *SetNetmapStatusResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *SetNetmapStatusResponse) SetBody(v *SetNetmapStatusResponse_Body) { + x.Body = v +} +func (x *SetNetmapStatusResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *SetNetmapStatusResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SetNetmapStatusResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SetNetmapStatusResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SetNetmapStatusResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SetNetmapStatusResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *SetNetmapStatusResponse_Body + f = new(SetNetmapStatusResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNetmapStatusRequest_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*GetNetmapStatusRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetNetmapStatusRequest_Body)(nil) + _ json.Marshaler = (*GetNetmapStatusRequest_Body)(nil) + _ json.Unmarshaler = (*GetNetmapStatusRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -344,18 +1336,93 @@ func (x *GetNetmapStatusRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNetmapStatusRequest_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNetmapStatusRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNetmapStatusRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNetmapStatusRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNetmapStatusRequest_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNetmapStatusRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNetmapStatusRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNetmapStatusRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNetmapStatusRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNetmapStatusRequest struct { + Body *GetNetmapStatusRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetNetmapStatusRequest)(nil) + _ encoding.ProtoUnmarshaler = (*GetNetmapStatusRequest)(nil) + _ json.Marshaler = (*GetNetmapStatusRequest)(nil) + _ json.Unmarshaler = (*GetNetmapStatusRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -368,27 +1435,6 @@ func (x *GetNetmapStatusRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNetmapStatusRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -404,13 +1450,165 @@ func (x *GetNetmapStatusRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetNetmapStatusRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetNetmapStatusRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNetmapStatusRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNetmapStatusRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNetmapStatusRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNetmapStatusRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetNetmapStatusRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetNetmapStatusRequest) GetBody() *GetNetmapStatusRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetNetmapStatusRequest) SetBody(v *GetNetmapStatusRequest_Body) { + x.Body = v +} +func (x *GetNetmapStatusRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetNetmapStatusRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNetmapStatusRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNetmapStatusRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNetmapStatusRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNetmapStatusRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetNetmapStatusRequest_Body + f = new(GetNetmapStatusRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNetmapStatusResponse_Body struct { + Status NetmapStatus `json:"status"` + Epoch uint64 `json:"epoch"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetNetmapStatusResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetNetmapStatusResponse_Body)(nil) + _ json.Marshaler = (*GetNetmapStatusResponse_Body)(nil) + _ json.Unmarshaler = (*GetNetmapStatusResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -423,27 +1621,170 @@ func (x *GetNetmapStatusResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNetmapStatusResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.EnumMarshal(1, buf[offset:], int32(x.Status)) - offset += proto.UInt64Marshal(2, buf[offset:], x.Epoch) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNetmapStatusResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNetmapStatusResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if int32(x.Status) != 0 { + mm.AppendInt32(1, int32(x.Status)) + } + if x.Epoch != 0 { + mm.AppendUint64(2, x.Epoch) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNetmapStatusResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNetmapStatusResponse_Body") + } + switch fc.FieldNum { + case 1: // Status + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Status") + } + x.Status = NetmapStatus(data) + case 2: // Epoch + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Epoch") + } + x.Epoch = data + } + } + return nil +} +func (x *GetNetmapStatusResponse_Body) GetStatus() NetmapStatus { + if x != nil { + return x.Status + } + return 0 +} +func (x *GetNetmapStatusResponse_Body) SetStatus(v NetmapStatus) { + x.Status = v +} +func (x *GetNetmapStatusResponse_Body) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} +func (x *GetNetmapStatusResponse_Body) SetEpoch(v uint64) { + x.Epoch = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNetmapStatusResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNetmapStatusResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"status\":" + out.RawString(prefix[1:]) + out.Int32(int32(x.Status)) + } + { + const prefix string = ",\"epoch\":" + out.RawString(prefix) + out.Uint64(x.Epoch) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNetmapStatusResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNetmapStatusResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "status": + { + var f NetmapStatus + var parsedValue NetmapStatus + switch v := in.Interface().(type) { + case string: + if vv, ok := NetmapStatus_value[v]; ok { + parsedValue = NetmapStatus(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = NetmapStatus(vv) + case float64: + parsedValue = NetmapStatus(v) + } + f = parsedValue + x.Status = f + } + case "epoch": + { + var f uint64 + f = in.Uint64() + x.Epoch = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNetmapStatusResponse struct { + Body *GetNetmapStatusResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetNetmapStatusResponse)(nil) + _ encoding.ProtoUnmarshaler = (*GetNetmapStatusResponse)(nil) + _ json.Marshaler = (*GetNetmapStatusResponse)(nil) + _ json.Unmarshaler = (*GetNetmapStatusResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -456,27 +1797,6 @@ func (x *GetNetmapStatusResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNetmapStatusResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -492,13 +1812,164 @@ func (x *GetNetmapStatusResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetNetmapStatusResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetNetmapStatusResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNetmapStatusResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNetmapStatusResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNetmapStatusResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNetmapStatusResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetNetmapStatusResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetNetmapStatusResponse) GetBody() *GetNetmapStatusResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetNetmapStatusResponse) SetBody(v *GetNetmapStatusResponse_Body) { + x.Body = v +} +func (x *GetNetmapStatusResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetNetmapStatusResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNetmapStatusResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNetmapStatusResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNetmapStatusResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNetmapStatusResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetNetmapStatusResponse_Body + f = new(GetNetmapStatusResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DropObjectsRequest_Body struct { + AddressList [][]byte `json:"addressList"` +} + +var ( + _ encoding.ProtoMarshaler = (*DropObjectsRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*DropObjectsRequest_Body)(nil) + _ json.Marshaler = (*DropObjectsRequest_Body)(nil) + _ json.Unmarshaler = (*DropObjectsRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -510,26 +1981,139 @@ func (x *DropObjectsRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DropObjectsRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.AddressList) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DropObjectsRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DropObjectsRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.AddressList { + mm.AppendBytes(1, x.AddressList[j]) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DropObjectsRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DropObjectsRequest_Body") + } + switch fc.FieldNum { + case 1: // AddressList + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "AddressList") + } + x.AddressList = append(x.AddressList, data) + } + } + return nil +} +func (x *DropObjectsRequest_Body) GetAddressList() [][]byte { + if x != nil { + return x.AddressList + } + return nil +} +func (x *DropObjectsRequest_Body) SetAddressList(v [][]byte) { + x.AddressList = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DropObjectsRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DropObjectsRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"addressList\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.AddressList { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.AddressList[i]) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DropObjectsRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DropObjectsRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "addressList": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.AddressList = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DropObjectsRequest struct { + Body *DropObjectsRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*DropObjectsRequest)(nil) + _ encoding.ProtoUnmarshaler = (*DropObjectsRequest)(nil) + _ json.Marshaler = (*DropObjectsRequest)(nil) + _ json.Unmarshaler = (*DropObjectsRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -542,27 +2126,6 @@ func (x *DropObjectsRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DropObjectsRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -578,13 +2141,163 @@ func (x *DropObjectsRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *DropObjectsRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *DropObjectsRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DropObjectsRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DropObjectsRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DropObjectsRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DropObjectsRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(DropObjectsRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *DropObjectsRequest) GetBody() *DropObjectsRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *DropObjectsRequest) SetBody(v *DropObjectsRequest_Body) { + x.Body = v +} +func (x *DropObjectsRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *DropObjectsRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DropObjectsRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DropObjectsRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DropObjectsRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DropObjectsRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *DropObjectsRequest_Body + f = new(DropObjectsRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DropObjectsResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*DropObjectsResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*DropObjectsResponse_Body)(nil) + _ json.Marshaler = (*DropObjectsResponse_Body)(nil) + _ json.Unmarshaler = (*DropObjectsResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -595,18 +2308,93 @@ func (x *DropObjectsResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DropObjectsResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DropObjectsResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DropObjectsResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DropObjectsResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DropObjectsResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DropObjectsResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DropObjectsResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DropObjectsResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DropObjectsResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DropObjectsResponse struct { + Body *DropObjectsResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*DropObjectsResponse)(nil) + _ encoding.ProtoUnmarshaler = (*DropObjectsResponse)(nil) + _ json.Marshaler = (*DropObjectsResponse)(nil) + _ json.Unmarshaler = (*DropObjectsResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -619,27 +2407,6 @@ func (x *DropObjectsResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DropObjectsResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -655,13 +2422,163 @@ func (x *DropObjectsResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *DropObjectsResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *DropObjectsResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DropObjectsResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DropObjectsResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DropObjectsResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DropObjectsResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(DropObjectsResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *DropObjectsResponse) GetBody() *DropObjectsResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *DropObjectsResponse) SetBody(v *DropObjectsResponse_Body) { + x.Body = v +} +func (x *DropObjectsResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *DropObjectsResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DropObjectsResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DropObjectsResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DropObjectsResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DropObjectsResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *DropObjectsResponse_Body + f = new(DropObjectsResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListShardsRequest_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*ListShardsRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListShardsRequest_Body)(nil) + _ json.Marshaler = (*ListShardsRequest_Body)(nil) + _ json.Unmarshaler = (*ListShardsRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -672,18 +2589,93 @@ func (x *ListShardsRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListShardsRequest_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListShardsRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListShardsRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListShardsRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListShardsRequest_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListShardsRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListShardsRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListShardsRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListShardsRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListShardsRequest struct { + Body *ListShardsRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListShardsRequest)(nil) + _ encoding.ProtoUnmarshaler = (*ListShardsRequest)(nil) + _ json.Marshaler = (*ListShardsRequest)(nil) + _ json.Unmarshaler = (*ListShardsRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -696,27 +2688,6 @@ func (x *ListShardsRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListShardsRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -732,13 +2703,164 @@ func (x *ListShardsRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ListShardsRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ListShardsRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListShardsRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListShardsRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListShardsRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListShardsRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListShardsRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListShardsRequest) GetBody() *ListShardsRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListShardsRequest) SetBody(v *ListShardsRequest_Body) { + x.Body = v +} +func (x *ListShardsRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ListShardsRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListShardsRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListShardsRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListShardsRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListShardsRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListShardsRequest_Body + f = new(ListShardsRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListShardsResponse_Body struct { + Shards []*ShardInfo `json:"shards"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListShardsResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListShardsResponse_Body)(nil) + _ json.Marshaler = (*ListShardsResponse_Body)(nil) + _ json.Unmarshaler = (*ListShardsResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -752,28 +2874,146 @@ func (x *ListShardsResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListShardsResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - for i := range x.Shards { - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Shards[i]) - } - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListShardsResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListShardsResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for i := range x.Shards { + if x.Shards[i] != nil && x.Shards[i].StableSize() != 0 { + x.Shards[i].EmitProtobuf(mm.AppendMessage(1)) + } + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListShardsResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListShardsResponse_Body") + } + switch fc.FieldNum { + case 1: // Shards + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shards") + } + x.Shards = append(x.Shards, new(ShardInfo)) + ff := x.Shards[len(x.Shards)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListShardsResponse_Body) GetShards() []*ShardInfo { + if x != nil { + return x.Shards + } + return nil +} +func (x *ListShardsResponse_Body) SetShards(v []*ShardInfo) { + x.Shards = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListShardsResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListShardsResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shards\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Shards { + if i != 0 { + out.RawByte(',') + } + x.Shards[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListShardsResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListShardsResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shards": + { + var f *ShardInfo + var list []*ShardInfo + in.Delim('[') + for !in.IsDelim(']') { + f = new(ShardInfo) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Shards = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListShardsResponse struct { + Body *ListShardsResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListShardsResponse)(nil) + _ encoding.ProtoUnmarshaler = (*ListShardsResponse)(nil) + _ json.Marshaler = (*ListShardsResponse)(nil) + _ json.Unmarshaler = (*ListShardsResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -786,27 +3026,6 @@ func (x *ListShardsResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListShardsResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -822,13 +3041,166 @@ func (x *ListShardsResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ListShardsResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ListShardsResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListShardsResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListShardsResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListShardsResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListShardsResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListShardsResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListShardsResponse) GetBody() *ListShardsResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListShardsResponse) SetBody(v *ListShardsResponse_Body) { + x.Body = v +} +func (x *ListShardsResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ListShardsResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListShardsResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListShardsResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListShardsResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListShardsResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListShardsResponse_Body + f = new(ListShardsResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SetShardModeRequest_Body struct { + Shard_ID [][]byte `json:"shardID"` + Mode ShardMode `json:"mode"` + ResetErrorCounter bool `json:"resetErrorCounter"` +} + +var ( + _ encoding.ProtoMarshaler = (*SetShardModeRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*SetShardModeRequest_Body)(nil) + _ json.Marshaler = (*SetShardModeRequest_Body)(nil) + _ json.Unmarshaler = (*SetShardModeRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -842,28 +3214,213 @@ func (x *SetShardModeRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SetShardModeRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) - offset += proto.EnumMarshal(2, buf[offset:], int32(x.Mode)) - offset += proto.BoolMarshal(3, buf[offset:], x.ResetErrorCounter) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SetShardModeRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SetShardModeRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Shard_ID { + mm.AppendBytes(1, x.Shard_ID[j]) + } + if int32(x.Mode) != 0 { + mm.AppendInt32(2, int32(x.Mode)) + } + if x.ResetErrorCounter { + mm.AppendBool(3, x.ResetErrorCounter) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SetShardModeRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SetShardModeRequest_Body") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + case 2: // Mode + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Mode") + } + x.Mode = ShardMode(data) + case 3: // ResetErrorCounter + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ResetErrorCounter") + } + x.ResetErrorCounter = data + } + } + return nil +} +func (x *SetShardModeRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *SetShardModeRequest_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} +func (x *SetShardModeRequest_Body) GetMode() ShardMode { + if x != nil { + return x.Mode + } + return 0 +} +func (x *SetShardModeRequest_Body) SetMode(v ShardMode) { + x.Mode = v +} +func (x *SetShardModeRequest_Body) GetResetErrorCounter() bool { + if x != nil { + return x.ResetErrorCounter + } + return false +} +func (x *SetShardModeRequest_Body) SetResetErrorCounter(v bool) { + x.ResetErrorCounter = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SetShardModeRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SetShardModeRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Shard_ID[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"mode\":" + out.RawString(prefix) + out.Int32(int32(x.Mode)) + } + { + const prefix string = ",\"resetErrorCounter\":" + out.RawString(prefix) + out.Bool(x.ResetErrorCounter) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SetShardModeRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SetShardModeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + case "mode": + { + var f ShardMode + var parsedValue ShardMode + switch v := in.Interface().(type) { + case string: + if vv, ok := ShardMode_value[v]; ok { + parsedValue = ShardMode(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = ShardMode(vv) + case float64: + parsedValue = ShardMode(v) + } + f = parsedValue + x.Mode = f + } + case "resetErrorCounter": + { + var f bool + f = in.Bool() + x.ResetErrorCounter = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SetShardModeRequest struct { + Body *SetShardModeRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*SetShardModeRequest)(nil) + _ encoding.ProtoUnmarshaler = (*SetShardModeRequest)(nil) + _ json.Marshaler = (*SetShardModeRequest)(nil) + _ json.Unmarshaler = (*SetShardModeRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -876,27 +3433,6 @@ func (x *SetShardModeRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SetShardModeRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -912,13 +3448,163 @@ func (x *SetShardModeRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *SetShardModeRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *SetShardModeRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SetShardModeRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SetShardModeRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SetShardModeRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SetShardModeRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(SetShardModeRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SetShardModeRequest) GetBody() *SetShardModeRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *SetShardModeRequest) SetBody(v *SetShardModeRequest_Body) { + x.Body = v +} +func (x *SetShardModeRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *SetShardModeRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SetShardModeRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SetShardModeRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SetShardModeRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SetShardModeRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *SetShardModeRequest_Body + f = new(SetShardModeRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SetShardModeResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*SetShardModeResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*SetShardModeResponse_Body)(nil) + _ json.Marshaler = (*SetShardModeResponse_Body)(nil) + _ json.Unmarshaler = (*SetShardModeResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -929,18 +3615,93 @@ func (x *SetShardModeResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SetShardModeResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SetShardModeResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SetShardModeResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SetShardModeResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SetShardModeResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SetShardModeResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SetShardModeResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SetShardModeResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SetShardModeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SetShardModeResponse struct { + Body *SetShardModeResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*SetShardModeResponse)(nil) + _ encoding.ProtoUnmarshaler = (*SetShardModeResponse)(nil) + _ json.Marshaler = (*SetShardModeResponse)(nil) + _ json.Unmarshaler = (*SetShardModeResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -953,27 +3714,6 @@ func (x *SetShardModeResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SetShardModeResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -989,13 +3729,166 @@ func (x *SetShardModeResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *SetShardModeResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *SetShardModeResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SetShardModeResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SetShardModeResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SetShardModeResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SetShardModeResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(SetShardModeResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SetShardModeResponse) GetBody() *SetShardModeResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *SetShardModeResponse) SetBody(v *SetShardModeResponse_Body) { + x.Body = v +} +func (x *SetShardModeResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *SetShardModeResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SetShardModeResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SetShardModeResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SetShardModeResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SetShardModeResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *SetShardModeResponse_Body + f = new(SetShardModeResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SynchronizeTreeRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + Height uint64 `json:"height"` +} + +var ( + _ encoding.ProtoMarshaler = (*SynchronizeTreeRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*SynchronizeTreeRequest_Body)(nil) + _ json.Marshaler = (*SynchronizeTreeRequest_Body)(nil) + _ json.Unmarshaler = (*SynchronizeTreeRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1009,28 +3902,183 @@ func (x *SynchronizeTreeRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SynchronizeTreeRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.UInt64Marshal(3, buf[offset:], x.Height) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SynchronizeTreeRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SynchronizeTreeRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + if x.Height != 0 { + mm.AppendUint64(3, x.Height) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SynchronizeTreeRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SynchronizeTreeRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // Height + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Height") + } + x.Height = data + } + } + return nil +} +func (x *SynchronizeTreeRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *SynchronizeTreeRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *SynchronizeTreeRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *SynchronizeTreeRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *SynchronizeTreeRequest_Body) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} +func (x *SynchronizeTreeRequest_Body) SetHeight(v uint64) { + x.Height = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SynchronizeTreeRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SynchronizeTreeRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"height\":" + out.RawString(prefix) + out.Uint64(x.Height) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SynchronizeTreeRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SynchronizeTreeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "height": + { + var f uint64 + f = in.Uint64() + x.Height = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SynchronizeTreeRequest struct { + Body *SynchronizeTreeRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*SynchronizeTreeRequest)(nil) + _ encoding.ProtoUnmarshaler = (*SynchronizeTreeRequest)(nil) + _ json.Marshaler = (*SynchronizeTreeRequest)(nil) + _ json.Unmarshaler = (*SynchronizeTreeRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1043,27 +4091,6 @@ func (x *SynchronizeTreeRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SynchronizeTreeRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1079,13 +4106,163 @@ func (x *SynchronizeTreeRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *SynchronizeTreeRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *SynchronizeTreeRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SynchronizeTreeRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SynchronizeTreeRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SynchronizeTreeRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SynchronizeTreeRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(SynchronizeTreeRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SynchronizeTreeRequest) GetBody() *SynchronizeTreeRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *SynchronizeTreeRequest) SetBody(v *SynchronizeTreeRequest_Body) { + x.Body = v +} +func (x *SynchronizeTreeRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *SynchronizeTreeRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SynchronizeTreeRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SynchronizeTreeRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SynchronizeTreeRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SynchronizeTreeRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *SynchronizeTreeRequest_Body + f = new(SynchronizeTreeRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SynchronizeTreeResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*SynchronizeTreeResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*SynchronizeTreeResponse_Body)(nil) + _ json.Marshaler = (*SynchronizeTreeResponse_Body)(nil) + _ json.Unmarshaler = (*SynchronizeTreeResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1096,18 +4273,93 @@ func (x *SynchronizeTreeResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SynchronizeTreeResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SynchronizeTreeResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SynchronizeTreeResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SynchronizeTreeResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SynchronizeTreeResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SynchronizeTreeResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SynchronizeTreeResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SynchronizeTreeResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SynchronizeTreeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SynchronizeTreeResponse struct { + Body *SynchronizeTreeResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*SynchronizeTreeResponse)(nil) + _ encoding.ProtoUnmarshaler = (*SynchronizeTreeResponse)(nil) + _ json.Marshaler = (*SynchronizeTreeResponse)(nil) + _ json.Unmarshaler = (*SynchronizeTreeResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1120,27 +4372,6 @@ func (x *SynchronizeTreeResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SynchronizeTreeResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1156,13 +4387,165 @@ func (x *SynchronizeTreeResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *SynchronizeTreeResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *SynchronizeTreeResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SynchronizeTreeResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SynchronizeTreeResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SynchronizeTreeResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SynchronizeTreeResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(SynchronizeTreeResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SynchronizeTreeResponse) GetBody() *SynchronizeTreeResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *SynchronizeTreeResponse) SetBody(v *SynchronizeTreeResponse_Body) { + x.Body = v +} +func (x *SynchronizeTreeResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *SynchronizeTreeResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SynchronizeTreeResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SynchronizeTreeResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SynchronizeTreeResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SynchronizeTreeResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *SynchronizeTreeResponse_Body + f = new(SynchronizeTreeResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type EvacuateShardRequest_Body struct { + Shard_ID [][]byte `json:"shardID"` + IgnoreErrors bool `json:"ignoreErrors"` +} + +var ( + _ encoding.ProtoMarshaler = (*EvacuateShardRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*EvacuateShardRequest_Body)(nil) + _ json.Marshaler = (*EvacuateShardRequest_Body)(nil) + _ json.Unmarshaler = (*EvacuateShardRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1175,27 +4558,168 @@ func (x *EvacuateShardRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *EvacuateShardRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) - offset += proto.BoolMarshal(2, buf[offset:], x.IgnoreErrors) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *EvacuateShardRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *EvacuateShardRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Shard_ID { + mm.AppendBytes(1, x.Shard_ID[j]) + } + if x.IgnoreErrors { + mm.AppendBool(2, x.IgnoreErrors) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *EvacuateShardRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "EvacuateShardRequest_Body") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + case 2: // IgnoreErrors + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "IgnoreErrors") + } + x.IgnoreErrors = data + } + } + return nil +} +func (x *EvacuateShardRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *EvacuateShardRequest_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} +func (x *EvacuateShardRequest_Body) GetIgnoreErrors() bool { + if x != nil { + return x.IgnoreErrors + } + return false +} +func (x *EvacuateShardRequest_Body) SetIgnoreErrors(v bool) { + x.IgnoreErrors = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *EvacuateShardRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *EvacuateShardRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Shard_ID[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"ignoreErrors\":" + out.RawString(prefix) + out.Bool(x.IgnoreErrors) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *EvacuateShardRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *EvacuateShardRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + case "ignoreErrors": + { + var f bool + f = in.Bool() + x.IgnoreErrors = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type EvacuateShardRequest struct { + Body *EvacuateShardRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*EvacuateShardRequest)(nil) + _ encoding.ProtoUnmarshaler = (*EvacuateShardRequest)(nil) + _ json.Marshaler = (*EvacuateShardRequest)(nil) + _ json.Unmarshaler = (*EvacuateShardRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1208,27 +4732,6 @@ func (x *EvacuateShardRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *EvacuateShardRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1244,13 +4747,164 @@ func (x *EvacuateShardRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *EvacuateShardRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *EvacuateShardRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *EvacuateShardRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *EvacuateShardRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *EvacuateShardRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "EvacuateShardRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(EvacuateShardRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *EvacuateShardRequest) GetBody() *EvacuateShardRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *EvacuateShardRequest) SetBody(v *EvacuateShardRequest_Body) { + x.Body = v +} +func (x *EvacuateShardRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *EvacuateShardRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *EvacuateShardRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *EvacuateShardRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *EvacuateShardRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *EvacuateShardRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *EvacuateShardRequest_Body + f = new(EvacuateShardRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type EvacuateShardResponse_Body struct { + Count uint32 `json:"count"` +} + +var ( + _ encoding.ProtoMarshaler = (*EvacuateShardResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*EvacuateShardResponse_Body)(nil) + _ json.Marshaler = (*EvacuateShardResponse_Body)(nil) + _ json.Unmarshaler = (*EvacuateShardResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1262,26 +4916,125 @@ func (x *EvacuateShardResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *EvacuateShardResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt32Marshal(1, buf[offset:], x.Count) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *EvacuateShardResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *EvacuateShardResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Count != 0 { + mm.AppendUint32(1, x.Count) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *EvacuateShardResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "EvacuateShardResponse_Body") + } + switch fc.FieldNum { + case 1: // Count + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Count") + } + x.Count = data + } + } + return nil +} +func (x *EvacuateShardResponse_Body) GetCount() uint32 { + if x != nil { + return x.Count + } + return 0 +} +func (x *EvacuateShardResponse_Body) SetCount(v uint32) { + x.Count = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *EvacuateShardResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *EvacuateShardResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"count\":" + out.RawString(prefix[1:]) + out.Uint32(x.Count) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *EvacuateShardResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *EvacuateShardResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "count": + { + var f uint32 + f = in.Uint32() + x.Count = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type EvacuateShardResponse struct { + Body *EvacuateShardResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*EvacuateShardResponse)(nil) + _ encoding.ProtoUnmarshaler = (*EvacuateShardResponse)(nil) + _ json.Marshaler = (*EvacuateShardResponse)(nil) + _ json.Unmarshaler = (*EvacuateShardResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1294,27 +5047,6 @@ func (x *EvacuateShardResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *EvacuateShardResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1330,13 +5062,165 @@ func (x *EvacuateShardResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *EvacuateShardResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *EvacuateShardResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *EvacuateShardResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *EvacuateShardResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *EvacuateShardResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "EvacuateShardResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(EvacuateShardResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *EvacuateShardResponse) GetBody() *EvacuateShardResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *EvacuateShardResponse) SetBody(v *EvacuateShardResponse_Body) { + x.Body = v +} +func (x *EvacuateShardResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *EvacuateShardResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *EvacuateShardResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *EvacuateShardResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *EvacuateShardResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *EvacuateShardResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *EvacuateShardResponse_Body + f = new(EvacuateShardResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type FlushCacheRequest_Body struct { + Shard_ID [][]byte `json:"shardID"` + Seal bool `json:"seal"` +} + +var ( + _ encoding.ProtoMarshaler = (*FlushCacheRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*FlushCacheRequest_Body)(nil) + _ json.Marshaler = (*FlushCacheRequest_Body)(nil) + _ json.Unmarshaler = (*FlushCacheRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1349,27 +5233,168 @@ func (x *FlushCacheRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *FlushCacheRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) - offset += proto.BoolMarshal(2, buf[offset:], x.Seal) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *FlushCacheRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *FlushCacheRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Shard_ID { + mm.AppendBytes(1, x.Shard_ID[j]) + } + if x.Seal { + mm.AppendBool(2, x.Seal) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *FlushCacheRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "FlushCacheRequest_Body") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + case 2: // Seal + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Seal") + } + x.Seal = data + } + } + return nil +} +func (x *FlushCacheRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *FlushCacheRequest_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} +func (x *FlushCacheRequest_Body) GetSeal() bool { + if x != nil { + return x.Seal + } + return false +} +func (x *FlushCacheRequest_Body) SetSeal(v bool) { + x.Seal = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *FlushCacheRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *FlushCacheRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Shard_ID[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"seal\":" + out.RawString(prefix) + out.Bool(x.Seal) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *FlushCacheRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *FlushCacheRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + case "seal": + { + var f bool + f = in.Bool() + x.Seal = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type FlushCacheRequest struct { + Body *FlushCacheRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*FlushCacheRequest)(nil) + _ encoding.ProtoUnmarshaler = (*FlushCacheRequest)(nil) + _ json.Marshaler = (*FlushCacheRequest)(nil) + _ json.Unmarshaler = (*FlushCacheRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1382,27 +5407,6 @@ func (x *FlushCacheRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *FlushCacheRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1418,13 +5422,163 @@ func (x *FlushCacheRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *FlushCacheRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *FlushCacheRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *FlushCacheRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *FlushCacheRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *FlushCacheRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "FlushCacheRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(FlushCacheRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *FlushCacheRequest) GetBody() *FlushCacheRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *FlushCacheRequest) SetBody(v *FlushCacheRequest_Body) { + x.Body = v +} +func (x *FlushCacheRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *FlushCacheRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *FlushCacheRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *FlushCacheRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *FlushCacheRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *FlushCacheRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *FlushCacheRequest_Body + f = new(FlushCacheRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type FlushCacheResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*FlushCacheResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*FlushCacheResponse_Body)(nil) + _ json.Marshaler = (*FlushCacheResponse_Body)(nil) + _ json.Unmarshaler = (*FlushCacheResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1435,18 +5589,93 @@ func (x *FlushCacheResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *FlushCacheResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *FlushCacheResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *FlushCacheResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *FlushCacheResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "FlushCacheResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *FlushCacheResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *FlushCacheResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *FlushCacheResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *FlushCacheResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type FlushCacheResponse struct { + Body *FlushCacheResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*FlushCacheResponse)(nil) + _ encoding.ProtoUnmarshaler = (*FlushCacheResponse)(nil) + _ json.Marshaler = (*FlushCacheResponse)(nil) + _ json.Unmarshaler = (*FlushCacheResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1459,27 +5688,6 @@ func (x *FlushCacheResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *FlushCacheResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1495,13 +5703,165 @@ func (x *FlushCacheResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *FlushCacheResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *FlushCacheResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *FlushCacheResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *FlushCacheResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *FlushCacheResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "FlushCacheResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(FlushCacheResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *FlushCacheResponse) GetBody() *FlushCacheResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *FlushCacheResponse) SetBody(v *FlushCacheResponse_Body) { + x.Body = v +} +func (x *FlushCacheResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *FlushCacheResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *FlushCacheResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *FlushCacheResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *FlushCacheResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *FlushCacheResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *FlushCacheResponse_Body + f = new(FlushCacheResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DoctorRequest_Body struct { + Concurrency uint32 `json:"concurrency"` + RemoveDuplicates bool `json:"removeDuplicates"` +} + +var ( + _ encoding.ProtoMarshaler = (*DoctorRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*DoctorRequest_Body)(nil) + _ json.Marshaler = (*DoctorRequest_Body)(nil) + _ json.Unmarshaler = (*DoctorRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1514,27 +5874,154 @@ func (x *DoctorRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DoctorRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt32Marshal(1, buf[offset:], x.Concurrency) - offset += proto.BoolMarshal(2, buf[offset:], x.RemoveDuplicates) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DoctorRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DoctorRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Concurrency != 0 { + mm.AppendUint32(1, x.Concurrency) + } + if x.RemoveDuplicates { + mm.AppendBool(2, x.RemoveDuplicates) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DoctorRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DoctorRequest_Body") + } + switch fc.FieldNum { + case 1: // Concurrency + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Concurrency") + } + x.Concurrency = data + case 2: // RemoveDuplicates + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "RemoveDuplicates") + } + x.RemoveDuplicates = data + } + } + return nil +} +func (x *DoctorRequest_Body) GetConcurrency() uint32 { + if x != nil { + return x.Concurrency + } + return 0 +} +func (x *DoctorRequest_Body) SetConcurrency(v uint32) { + x.Concurrency = v +} +func (x *DoctorRequest_Body) GetRemoveDuplicates() bool { + if x != nil { + return x.RemoveDuplicates + } + return false +} +func (x *DoctorRequest_Body) SetRemoveDuplicates(v bool) { + x.RemoveDuplicates = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DoctorRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DoctorRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"concurrency\":" + out.RawString(prefix[1:]) + out.Uint32(x.Concurrency) + } + { + const prefix string = ",\"removeDuplicates\":" + out.RawString(prefix) + out.Bool(x.RemoveDuplicates) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DoctorRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DoctorRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "concurrency": + { + var f uint32 + f = in.Uint32() + x.Concurrency = f + } + case "removeDuplicates": + { + var f bool + f = in.Bool() + x.RemoveDuplicates = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DoctorRequest struct { + Body *DoctorRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*DoctorRequest)(nil) + _ encoding.ProtoUnmarshaler = (*DoctorRequest)(nil) + _ json.Marshaler = (*DoctorRequest)(nil) + _ json.Unmarshaler = (*DoctorRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1547,27 +6034,6 @@ func (x *DoctorRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DoctorRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1583,13 +6049,163 @@ func (x *DoctorRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *DoctorRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *DoctorRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DoctorRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DoctorRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DoctorRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DoctorRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(DoctorRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *DoctorRequest) GetBody() *DoctorRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *DoctorRequest) SetBody(v *DoctorRequest_Body) { + x.Body = v +} +func (x *DoctorRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *DoctorRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DoctorRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DoctorRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DoctorRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DoctorRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *DoctorRequest_Body + f = new(DoctorRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DoctorResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*DoctorResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*DoctorResponse_Body)(nil) + _ json.Marshaler = (*DoctorResponse_Body)(nil) + _ json.Unmarshaler = (*DoctorResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1600,18 +6216,93 @@ func (x *DoctorResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DoctorResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DoctorResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DoctorResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DoctorResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DoctorResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DoctorResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DoctorResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DoctorResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DoctorResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DoctorResponse struct { + Body *DoctorResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*DoctorResponse)(nil) + _ encoding.ProtoUnmarshaler = (*DoctorResponse)(nil) + _ json.Marshaler = (*DoctorResponse)(nil) + _ json.Unmarshaler = (*DoctorResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1624,27 +6315,6 @@ func (x *DoctorResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DoctorResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1660,13 +6330,201 @@ func (x *DoctorResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *DoctorResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *DoctorResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DoctorResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DoctorResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DoctorResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DoctorResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(DoctorResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *DoctorResponse) GetBody() *DoctorResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *DoctorResponse) SetBody(v *DoctorResponse_Body) { + x.Body = v +} +func (x *DoctorResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *DoctorResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DoctorResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DoctorResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DoctorResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DoctorResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *DoctorResponse_Body + f = new(DoctorResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StartShardEvacuationRequest_Body_Scope int32 + +const ( + StartShardEvacuationRequest_Body_NONE StartShardEvacuationRequest_Body_Scope = 0 + StartShardEvacuationRequest_Body_OBJECTS StartShardEvacuationRequest_Body_Scope = 1 + StartShardEvacuationRequest_Body_TREES StartShardEvacuationRequest_Body_Scope = 2 +) + +var ( + StartShardEvacuationRequest_Body_Scope_name = map[int32]string{ + 0: "NONE", + 1: "OBJECTS", + 2: "TREES", + } + StartShardEvacuationRequest_Body_Scope_value = map[string]int32{ + "NONE": 0, + "OBJECTS": 1, + "TREES": 2, + } +) + +func (x StartShardEvacuationRequest_Body_Scope) String() string { + if v, ok := StartShardEvacuationRequest_Body_Scope_name[int32(x)]; ok { + return v + } + return strconv.FormatInt(int64(x), 10) +} +func (x *StartShardEvacuationRequest_Body_Scope) FromString(s string) bool { + if v, ok := StartShardEvacuationRequest_Body_Scope_value[s]; ok { + *x = StartShardEvacuationRequest_Body_Scope(v) + return true + } + return false +} + +type StartShardEvacuationRequest_Body struct { + Shard_ID [][]byte `json:"shardID"` + IgnoreErrors bool `json:"ignoreErrors"` + Scope uint32 `json:"scope"` +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardEvacuationRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardEvacuationRequest_Body)(nil) + _ json.Marshaler = (*StartShardEvacuationRequest_Body)(nil) + _ json.Unmarshaler = (*StartShardEvacuationRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1680,28 +6538,197 @@ func (x *StartShardEvacuationRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *StartShardEvacuationRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) - offset += proto.BoolMarshal(2, buf[offset:], x.IgnoreErrors) - offset += proto.UInt32Marshal(3, buf[offset:], x.Scope) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardEvacuationRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *StartShardEvacuationRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Shard_ID { + mm.AppendBytes(1, x.Shard_ID[j]) + } + if x.IgnoreErrors { + mm.AppendBool(2, x.IgnoreErrors) + } + if x.Scope != 0 { + mm.AppendUint32(3, x.Scope) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardEvacuationRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardEvacuationRequest_Body") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + case 2: // IgnoreErrors + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "IgnoreErrors") + } + x.IgnoreErrors = data + case 3: // Scope + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Scope") + } + x.Scope = data + } + } + return nil +} +func (x *StartShardEvacuationRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *StartShardEvacuationRequest_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} +func (x *StartShardEvacuationRequest_Body) GetIgnoreErrors() bool { + if x != nil { + return x.IgnoreErrors + } + return false +} +func (x *StartShardEvacuationRequest_Body) SetIgnoreErrors(v bool) { + x.IgnoreErrors = v +} +func (x *StartShardEvacuationRequest_Body) GetScope() uint32 { + if x != nil { + return x.Scope + } + return 0 +} +func (x *StartShardEvacuationRequest_Body) SetScope(v uint32) { + x.Scope = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardEvacuationRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardEvacuationRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Shard_ID[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"ignoreErrors\":" + out.RawString(prefix) + out.Bool(x.IgnoreErrors) + } + { + const prefix string = ",\"scope\":" + out.RawString(prefix) + out.Uint32(x.Scope) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardEvacuationRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardEvacuationRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + case "ignoreErrors": + { + var f bool + f = in.Bool() + x.IgnoreErrors = f + } + case "scope": + { + var f uint32 + f = in.Uint32() + x.Scope = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StartShardEvacuationRequest struct { + Body *StartShardEvacuationRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardEvacuationRequest)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardEvacuationRequest)(nil) + _ json.Marshaler = (*StartShardEvacuationRequest)(nil) + _ json.Unmarshaler = (*StartShardEvacuationRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1714,27 +6741,6 @@ func (x *StartShardEvacuationRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *StartShardEvacuationRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1750,13 +6756,163 @@ func (x *StartShardEvacuationRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *StartShardEvacuationRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *StartShardEvacuationRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardEvacuationRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *StartShardEvacuationRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardEvacuationRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardEvacuationRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(StartShardEvacuationRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *StartShardEvacuationRequest) GetBody() *StartShardEvacuationRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *StartShardEvacuationRequest) SetBody(v *StartShardEvacuationRequest_Body) { + x.Body = v +} +func (x *StartShardEvacuationRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *StartShardEvacuationRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardEvacuationRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardEvacuationRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardEvacuationRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardEvacuationRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *StartShardEvacuationRequest_Body + f = new(StartShardEvacuationRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StartShardEvacuationResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardEvacuationResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardEvacuationResponse_Body)(nil) + _ json.Marshaler = (*StartShardEvacuationResponse_Body)(nil) + _ json.Unmarshaler = (*StartShardEvacuationResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1767,18 +6923,93 @@ func (x *StartShardEvacuationResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *StartShardEvacuationResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardEvacuationResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *StartShardEvacuationResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardEvacuationResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardEvacuationResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardEvacuationResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardEvacuationResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardEvacuationResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardEvacuationResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StartShardEvacuationResponse struct { + Body *StartShardEvacuationResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardEvacuationResponse)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardEvacuationResponse)(nil) + _ json.Marshaler = (*StartShardEvacuationResponse)(nil) + _ json.Unmarshaler = (*StartShardEvacuationResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1791,27 +7022,6 @@ func (x *StartShardEvacuationResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *StartShardEvacuationResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1827,13 +7037,163 @@ func (x *StartShardEvacuationResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *StartShardEvacuationResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *StartShardEvacuationResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardEvacuationResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *StartShardEvacuationResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardEvacuationResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardEvacuationResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(StartShardEvacuationResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *StartShardEvacuationResponse) GetBody() *StartShardEvacuationResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *StartShardEvacuationResponse) SetBody(v *StartShardEvacuationResponse_Body) { + x.Body = v +} +func (x *StartShardEvacuationResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *StartShardEvacuationResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardEvacuationResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardEvacuationResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardEvacuationResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardEvacuationResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *StartShardEvacuationResponse_Body + f = new(StartShardEvacuationResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetShardEvacuationStatusRequest_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*GetShardEvacuationStatusRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetShardEvacuationStatusRequest_Body)(nil) + _ json.Marshaler = (*GetShardEvacuationStatusRequest_Body)(nil) + _ json.Unmarshaler = (*GetShardEvacuationStatusRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1844,18 +7204,93 @@ func (x *GetShardEvacuationStatusRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetShardEvacuationStatusRequest_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetShardEvacuationStatusRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetShardEvacuationStatusRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetShardEvacuationStatusRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetShardEvacuationStatusRequest_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetShardEvacuationStatusRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetShardEvacuationStatusRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetShardEvacuationStatusRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetShardEvacuationStatusRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetShardEvacuationStatusRequest struct { + Body *GetShardEvacuationStatusRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetShardEvacuationStatusRequest)(nil) + _ encoding.ProtoUnmarshaler = (*GetShardEvacuationStatusRequest)(nil) + _ json.Marshaler = (*GetShardEvacuationStatusRequest)(nil) + _ json.Unmarshaler = (*GetShardEvacuationStatusRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1868,27 +7303,6 @@ func (x *GetShardEvacuationStatusRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetShardEvacuationStatusRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1904,13 +7318,199 @@ func (x *GetShardEvacuationStatusRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetShardEvacuationStatusRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetShardEvacuationStatusRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetShardEvacuationStatusRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetShardEvacuationStatusRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetShardEvacuationStatusRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetShardEvacuationStatusRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetShardEvacuationStatusRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetShardEvacuationStatusRequest) GetBody() *GetShardEvacuationStatusRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetShardEvacuationStatusRequest) SetBody(v *GetShardEvacuationStatusRequest_Body) { + x.Body = v +} +func (x *GetShardEvacuationStatusRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetShardEvacuationStatusRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetShardEvacuationStatusRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetShardEvacuationStatusRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetShardEvacuationStatusRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetShardEvacuationStatusRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetShardEvacuationStatusRequest_Body + f = new(GetShardEvacuationStatusRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetShardEvacuationStatusResponse_Body_Status int32 + +const ( + GetShardEvacuationStatusResponse_Body_EVACUATE_SHARD_STATUS_UNDEFINED GetShardEvacuationStatusResponse_Body_Status = 0 + GetShardEvacuationStatusResponse_Body_RUNNING GetShardEvacuationStatusResponse_Body_Status = 1 + GetShardEvacuationStatusResponse_Body_COMPLETED GetShardEvacuationStatusResponse_Body_Status = 2 +) + +var ( + GetShardEvacuationStatusResponse_Body_Status_name = map[int32]string{ + 0: "EVACUATE_SHARD_STATUS_UNDEFINED", + 1: "RUNNING", + 2: "COMPLETED", + } + GetShardEvacuationStatusResponse_Body_Status_value = map[string]int32{ + "EVACUATE_SHARD_STATUS_UNDEFINED": 0, + "RUNNING": 1, + "COMPLETED": 2, + } +) + +func (x GetShardEvacuationStatusResponse_Body_Status) String() string { + if v, ok := GetShardEvacuationStatusResponse_Body_Status_name[int32(x)]; ok { + return v + } + return strconv.FormatInt(int64(x), 10) +} +func (x *GetShardEvacuationStatusResponse_Body_Status) FromString(s string) bool { + if v, ok := GetShardEvacuationStatusResponse_Body_Status_value[s]; ok { + *x = GetShardEvacuationStatusResponse_Body_Status(v) + return true + } + return false +} + +type GetShardEvacuationStatusResponse_Body_UnixTimestamp struct { + Value int64 `json:"value"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil) + _ encoding.ProtoUnmarshaler = (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil) + _ json.Marshaler = (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil) + _ json.Unmarshaler = (*GetShardEvacuationStatusResponse_Body_UnixTimestamp)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1922,26 +7522,124 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) StableSize() (size return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.Int64Marshal(1, buf[offset:], x.Value) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Value != 0 { + mm.AppendInt64(1, x.Value) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetShardEvacuationStatusResponse_Body_UnixTimestamp") + } + switch fc.FieldNum { + case 1: // Value + data, ok := fc.Int64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Value") + } + x.Value = data + } + } + return nil +} +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) GetValue() int64 { + if x != nil { + return x.Value + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) SetValue(v int64) { + x.Value = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"value\":" + out.RawString(prefix[1:]) + out.Int64(x.Value) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "value": + { + var f int64 + f = in.Int64() + x.Value = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetShardEvacuationStatusResponse_Body_Duration struct { + Seconds int64 `json:"seconds"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetShardEvacuationStatusResponse_Body_Duration)(nil) + _ encoding.ProtoUnmarshaler = (*GetShardEvacuationStatusResponse_Body_Duration)(nil) + _ json.Marshaler = (*GetShardEvacuationStatusResponse_Body_Duration)(nil) + _ json.Unmarshaler = (*GetShardEvacuationStatusResponse_Body_Duration)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1953,26 +7651,135 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) StableSize() (size int) return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetShardEvacuationStatusResponse_Body_Duration) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.Int64Marshal(1, buf[offset:], x.Seconds) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body_Duration) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetShardEvacuationStatusResponse_Body_Duration) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Seconds != 0 { + mm.AppendInt64(1, x.Seconds) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body_Duration) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetShardEvacuationStatusResponse_Body_Duration") + } + switch fc.FieldNum { + case 1: // Seconds + data, ok := fc.Int64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Seconds") + } + x.Seconds = data + } + } + return nil +} +func (x *GetShardEvacuationStatusResponse_Body_Duration) GetSeconds() int64 { + if x != nil { + return x.Seconds + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body_Duration) SetSeconds(v int64) { + x.Seconds = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetShardEvacuationStatusResponse_Body_Duration) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetShardEvacuationStatusResponse_Body_Duration) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"seconds\":" + out.RawString(prefix[1:]) + out.Int64(x.Seconds) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body_Duration) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetShardEvacuationStatusResponse_Body_Duration) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "seconds": + { + var f int64 + f = in.Int64() + x.Seconds = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetShardEvacuationStatusResponse_Body struct { + TotalObjects uint64 `json:"totalObjects"` + EvacuatedObjects uint64 `json:"evacuatedObjects"` + FailedObjects uint64 `json:"failedObjects"` + Shard_ID [][]byte `json:"shardID"` + Status GetShardEvacuationStatusResponse_Body_Status `json:"status"` + Duration *GetShardEvacuationStatusResponse_Body_Duration `json:"duration"` + StartedAt *GetShardEvacuationStatusResponse_Body_UnixTimestamp `json:"startedAt"` + ErrorMessage string `json:"errorMessage"` + SkippedObjects uint64 `json:"skippedObjects"` + TotalTrees uint64 `json:"totalTrees"` + EvacuatedTrees uint64 `json:"evacuatedTrees"` + FailedTrees uint64 `json:"failedTrees"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetShardEvacuationStatusResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetShardEvacuationStatusResponse_Body)(nil) + _ json.Marshaler = (*GetShardEvacuationStatusResponse_Body)(nil) + _ json.Unmarshaler = (*GetShardEvacuationStatusResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1995,37 +7802,482 @@ func (x *GetShardEvacuationStatusResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetShardEvacuationStatusResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt64Marshal(1, buf[offset:], x.TotalObjects) - offset += proto.UInt64Marshal(2, buf[offset:], x.EvacuatedObjects) - offset += proto.UInt64Marshal(3, buf[offset:], x.FailedObjects) - offset += proto.RepeatedBytesMarshal(4, buf[offset:], x.Shard_ID) - offset += proto.EnumMarshal(5, buf[offset:], int32(x.Status)) - offset += proto.NestedStructureMarshal(6, buf[offset:], x.Duration) - offset += proto.NestedStructureMarshal(7, buf[offset:], x.StartedAt) - offset += proto.StringMarshal(8, buf[offset:], x.ErrorMessage) - offset += proto.UInt64Marshal(9, buf[offset:], x.SkippedObjects) - offset += proto.UInt64Marshal(10, buf[offset:], x.TotalTrees) - offset += proto.UInt64Marshal(11, buf[offset:], x.EvacuatedTrees) - offset += proto.UInt64Marshal(12, buf[offset:], x.FailedTrees) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetShardEvacuationStatusResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.TotalObjects != 0 { + mm.AppendUint64(1, x.TotalObjects) + } + if x.EvacuatedObjects != 0 { + mm.AppendUint64(2, x.EvacuatedObjects) + } + if x.FailedObjects != 0 { + mm.AppendUint64(3, x.FailedObjects) + } + for j := range x.Shard_ID { + mm.AppendBytes(4, x.Shard_ID[j]) + } + if int32(x.Status) != 0 { + mm.AppendInt32(5, int32(x.Status)) + } + if x.Duration != nil && x.Duration.StableSize() != 0 { + x.Duration.EmitProtobuf(mm.AppendMessage(6)) + } + if x.StartedAt != nil && x.StartedAt.StableSize() != 0 { + x.StartedAt.EmitProtobuf(mm.AppendMessage(7)) + } + if len(x.ErrorMessage) != 0 { + mm.AppendString(8, x.ErrorMessage) + } + if x.SkippedObjects != 0 { + mm.AppendUint64(9, x.SkippedObjects) + } + if x.TotalTrees != 0 { + mm.AppendUint64(10, x.TotalTrees) + } + if x.EvacuatedTrees != 0 { + mm.AppendUint64(11, x.EvacuatedTrees) + } + if x.FailedTrees != 0 { + mm.AppendUint64(12, x.FailedTrees) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetShardEvacuationStatusResponse_Body") + } + switch fc.FieldNum { + case 1: // TotalObjects + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TotalObjects") + } + x.TotalObjects = data + case 2: // EvacuatedObjects + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "EvacuatedObjects") + } + x.EvacuatedObjects = data + case 3: // FailedObjects + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "FailedObjects") + } + x.FailedObjects = data + case 4: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + case 5: // Status + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Status") + } + x.Status = GetShardEvacuationStatusResponse_Body_Status(data) + case 6: // Duration + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Duration") + } + x.Duration = new(GetShardEvacuationStatusResponse_Body_Duration) + if err := x.Duration.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 7: // StartedAt + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "StartedAt") + } + x.StartedAt = new(GetShardEvacuationStatusResponse_Body_UnixTimestamp) + if err := x.StartedAt.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 8: // ErrorMessage + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ErrorMessage") + } + x.ErrorMessage = data + case 9: // SkippedObjects + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "SkippedObjects") + } + x.SkippedObjects = data + case 10: // TotalTrees + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TotalTrees") + } + x.TotalTrees = data + case 11: // EvacuatedTrees + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "EvacuatedTrees") + } + x.EvacuatedTrees = data + case 12: // FailedTrees + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "FailedTrees") + } + x.FailedTrees = data + } + } + return nil +} +func (x *GetShardEvacuationStatusResponse_Body) GetTotalObjects() uint64 { + if x != nil { + return x.TotalObjects + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body) SetTotalObjects(v uint64) { + x.TotalObjects = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetEvacuatedObjects() uint64 { + if x != nil { + return x.EvacuatedObjects + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body) SetEvacuatedObjects(v uint64) { + x.EvacuatedObjects = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetFailedObjects() uint64 { + if x != nil { + return x.FailedObjects + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body) SetFailedObjects(v uint64) { + x.FailedObjects = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *GetShardEvacuationStatusResponse_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetStatus() GetShardEvacuationStatusResponse_Body_Status { + if x != nil { + return x.Status + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body) SetStatus(v GetShardEvacuationStatusResponse_Body_Status) { + x.Status = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetDuration() *GetShardEvacuationStatusResponse_Body_Duration { + if x != nil { + return x.Duration + } + return nil +} +func (x *GetShardEvacuationStatusResponse_Body) SetDuration(v *GetShardEvacuationStatusResponse_Body_Duration) { + x.Duration = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetStartedAt() *GetShardEvacuationStatusResponse_Body_UnixTimestamp { + if x != nil { + return x.StartedAt + } + return nil +} +func (x *GetShardEvacuationStatusResponse_Body) SetStartedAt(v *GetShardEvacuationStatusResponse_Body_UnixTimestamp) { + x.StartedAt = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} +func (x *GetShardEvacuationStatusResponse_Body) SetErrorMessage(v string) { + x.ErrorMessage = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetSkippedObjects() uint64 { + if x != nil { + return x.SkippedObjects + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body) SetSkippedObjects(v uint64) { + x.SkippedObjects = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetTotalTrees() uint64 { + if x != nil { + return x.TotalTrees + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body) SetTotalTrees(v uint64) { + x.TotalTrees = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetEvacuatedTrees() uint64 { + if x != nil { + return x.EvacuatedTrees + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body) SetEvacuatedTrees(v uint64) { + x.EvacuatedTrees = v +} +func (x *GetShardEvacuationStatusResponse_Body) GetFailedTrees() uint64 { + if x != nil { + return x.FailedTrees + } + return 0 +} +func (x *GetShardEvacuationStatusResponse_Body) SetFailedTrees(v uint64) { + x.FailedTrees = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetShardEvacuationStatusResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetShardEvacuationStatusResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"totalObjects\":" + out.RawString(prefix[1:]) + out.Uint64(x.TotalObjects) + } + { + const prefix string = ",\"evacuatedObjects\":" + out.RawString(prefix) + out.Uint64(x.EvacuatedObjects) + } + { + const prefix string = ",\"failedObjects\":" + out.RawString(prefix) + out.Uint64(x.FailedObjects) + } + { + const prefix string = ",\"shardID\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Shard_ID[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"status\":" + out.RawString(prefix) + out.Int32(int32(x.Status)) + } + { + const prefix string = ",\"duration\":" + out.RawString(prefix) + x.Duration.MarshalEasyJSON(out) + } + { + const prefix string = ",\"startedAt\":" + out.RawString(prefix) + x.StartedAt.MarshalEasyJSON(out) + } + { + const prefix string = ",\"errorMessage\":" + out.RawString(prefix) + out.String(x.ErrorMessage) + } + { + const prefix string = ",\"skippedObjects\":" + out.RawString(prefix) + out.Uint64(x.SkippedObjects) + } + { + const prefix string = ",\"totalTrees\":" + out.RawString(prefix) + out.Uint64(x.TotalTrees) + } + { + const prefix string = ",\"evacuatedTrees\":" + out.RawString(prefix) + out.Uint64(x.EvacuatedTrees) + } + { + const prefix string = ",\"failedTrees\":" + out.RawString(prefix) + out.Uint64(x.FailedTrees) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetShardEvacuationStatusResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetShardEvacuationStatusResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "totalObjects": + { + var f uint64 + f = in.Uint64() + x.TotalObjects = f + } + case "evacuatedObjects": + { + var f uint64 + f = in.Uint64() + x.EvacuatedObjects = f + } + case "failedObjects": + { + var f uint64 + f = in.Uint64() + x.FailedObjects = f + } + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + case "status": + { + var f GetShardEvacuationStatusResponse_Body_Status + var parsedValue GetShardEvacuationStatusResponse_Body_Status + switch v := in.Interface().(type) { + case string: + if vv, ok := GetShardEvacuationStatusResponse_Body_Status_value[v]; ok { + parsedValue = GetShardEvacuationStatusResponse_Body_Status(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = GetShardEvacuationStatusResponse_Body_Status(vv) + case float64: + parsedValue = GetShardEvacuationStatusResponse_Body_Status(v) + } + f = parsedValue + x.Status = f + } + case "duration": + { + var f *GetShardEvacuationStatusResponse_Body_Duration + f = new(GetShardEvacuationStatusResponse_Body_Duration) + f.UnmarshalEasyJSON(in) + x.Duration = f + } + case "startedAt": + { + var f *GetShardEvacuationStatusResponse_Body_UnixTimestamp + f = new(GetShardEvacuationStatusResponse_Body_UnixTimestamp) + f.UnmarshalEasyJSON(in) + x.StartedAt = f + } + case "errorMessage": + { + var f string + f = in.String() + x.ErrorMessage = f + } + case "skippedObjects": + { + var f uint64 + f = in.Uint64() + x.SkippedObjects = f + } + case "totalTrees": + { + var f uint64 + f = in.Uint64() + x.TotalTrees = f + } + case "evacuatedTrees": + { + var f uint64 + f = in.Uint64() + x.EvacuatedTrees = f + } + case "failedTrees": + { + var f uint64 + f = in.Uint64() + x.FailedTrees = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetShardEvacuationStatusResponse struct { + Body *GetShardEvacuationStatusResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetShardEvacuationStatusResponse)(nil) + _ encoding.ProtoUnmarshaler = (*GetShardEvacuationStatusResponse)(nil) + _ json.Marshaler = (*GetShardEvacuationStatusResponse)(nil) + _ json.Unmarshaler = (*GetShardEvacuationStatusResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2038,27 +8290,6 @@ func (x *GetShardEvacuationStatusResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetShardEvacuationStatusResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2074,13 +8305,163 @@ func (x *GetShardEvacuationStatusResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetShardEvacuationStatusResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetShardEvacuationStatusResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetShardEvacuationStatusResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetShardEvacuationStatusResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetShardEvacuationStatusResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetShardEvacuationStatusResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetShardEvacuationStatusResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetShardEvacuationStatusResponse) GetBody() *GetShardEvacuationStatusResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetShardEvacuationStatusResponse) SetBody(v *GetShardEvacuationStatusResponse_Body) { + x.Body = v +} +func (x *GetShardEvacuationStatusResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetShardEvacuationStatusResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetShardEvacuationStatusResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetShardEvacuationStatusResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetShardEvacuationStatusResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetShardEvacuationStatusResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetShardEvacuationStatusResponse_Body + f = new(GetShardEvacuationStatusResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ResetShardEvacuationStatusRequest_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*ResetShardEvacuationStatusRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ResetShardEvacuationStatusRequest_Body)(nil) + _ json.Marshaler = (*ResetShardEvacuationStatusRequest_Body)(nil) + _ json.Unmarshaler = (*ResetShardEvacuationStatusRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2091,18 +8472,93 @@ func (x *ResetShardEvacuationStatusRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ResetShardEvacuationStatusRequest_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ResetShardEvacuationStatusRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ResetShardEvacuationStatusRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ResetShardEvacuationStatusRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ResetShardEvacuationStatusRequest_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ResetShardEvacuationStatusRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ResetShardEvacuationStatusRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ResetShardEvacuationStatusRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ResetShardEvacuationStatusRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ResetShardEvacuationStatusRequest struct { + Body *ResetShardEvacuationStatusRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ResetShardEvacuationStatusRequest)(nil) + _ encoding.ProtoUnmarshaler = (*ResetShardEvacuationStatusRequest)(nil) + _ json.Marshaler = (*ResetShardEvacuationStatusRequest)(nil) + _ json.Unmarshaler = (*ResetShardEvacuationStatusRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2115,27 +8571,6 @@ func (x *ResetShardEvacuationStatusRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ResetShardEvacuationStatusRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2151,13 +8586,163 @@ func (x *ResetShardEvacuationStatusRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ResetShardEvacuationStatusRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ResetShardEvacuationStatusRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ResetShardEvacuationStatusRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ResetShardEvacuationStatusRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ResetShardEvacuationStatusRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ResetShardEvacuationStatusRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ResetShardEvacuationStatusRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ResetShardEvacuationStatusRequest) GetBody() *ResetShardEvacuationStatusRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ResetShardEvacuationStatusRequest) SetBody(v *ResetShardEvacuationStatusRequest_Body) { + x.Body = v +} +func (x *ResetShardEvacuationStatusRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ResetShardEvacuationStatusRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ResetShardEvacuationStatusRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ResetShardEvacuationStatusRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ResetShardEvacuationStatusRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ResetShardEvacuationStatusRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ResetShardEvacuationStatusRequest_Body + f = new(ResetShardEvacuationStatusRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ResetShardEvacuationStatusResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*ResetShardEvacuationStatusResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ResetShardEvacuationStatusResponse_Body)(nil) + _ json.Marshaler = (*ResetShardEvacuationStatusResponse_Body)(nil) + _ json.Unmarshaler = (*ResetShardEvacuationStatusResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2168,18 +8753,93 @@ func (x *ResetShardEvacuationStatusResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ResetShardEvacuationStatusResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ResetShardEvacuationStatusResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ResetShardEvacuationStatusResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ResetShardEvacuationStatusResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ResetShardEvacuationStatusResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ResetShardEvacuationStatusResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ResetShardEvacuationStatusResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ResetShardEvacuationStatusResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ResetShardEvacuationStatusResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ResetShardEvacuationStatusResponse struct { + Body *ResetShardEvacuationStatusResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ResetShardEvacuationStatusResponse)(nil) + _ encoding.ProtoUnmarshaler = (*ResetShardEvacuationStatusResponse)(nil) + _ json.Marshaler = (*ResetShardEvacuationStatusResponse)(nil) + _ json.Unmarshaler = (*ResetShardEvacuationStatusResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2192,27 +8852,6 @@ func (x *ResetShardEvacuationStatusResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ResetShardEvacuationStatusResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2228,13 +8867,163 @@ func (x *ResetShardEvacuationStatusResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ResetShardEvacuationStatusResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ResetShardEvacuationStatusResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ResetShardEvacuationStatusResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ResetShardEvacuationStatusResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ResetShardEvacuationStatusResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ResetShardEvacuationStatusResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ResetShardEvacuationStatusResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ResetShardEvacuationStatusResponse) GetBody() *ResetShardEvacuationStatusResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ResetShardEvacuationStatusResponse) SetBody(v *ResetShardEvacuationStatusResponse_Body) { + x.Body = v +} +func (x *ResetShardEvacuationStatusResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ResetShardEvacuationStatusResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ResetShardEvacuationStatusResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ResetShardEvacuationStatusResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ResetShardEvacuationStatusResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ResetShardEvacuationStatusResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ResetShardEvacuationStatusResponse_Body + f = new(ResetShardEvacuationStatusResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StopShardEvacuationRequest_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*StopShardEvacuationRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*StopShardEvacuationRequest_Body)(nil) + _ json.Marshaler = (*StopShardEvacuationRequest_Body)(nil) + _ json.Unmarshaler = (*StopShardEvacuationRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2245,18 +9034,93 @@ func (x *StopShardEvacuationRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *StopShardEvacuationRequest_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StopShardEvacuationRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *StopShardEvacuationRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StopShardEvacuationRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StopShardEvacuationRequest_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StopShardEvacuationRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StopShardEvacuationRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StopShardEvacuationRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StopShardEvacuationRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StopShardEvacuationRequest struct { + Body *StopShardEvacuationRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*StopShardEvacuationRequest)(nil) + _ encoding.ProtoUnmarshaler = (*StopShardEvacuationRequest)(nil) + _ json.Marshaler = (*StopShardEvacuationRequest)(nil) + _ json.Unmarshaler = (*StopShardEvacuationRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2269,27 +9133,6 @@ func (x *StopShardEvacuationRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *StopShardEvacuationRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2305,13 +9148,163 @@ func (x *StopShardEvacuationRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *StopShardEvacuationRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *StopShardEvacuationRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StopShardEvacuationRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *StopShardEvacuationRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StopShardEvacuationRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StopShardEvacuationRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(StopShardEvacuationRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *StopShardEvacuationRequest) GetBody() *StopShardEvacuationRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *StopShardEvacuationRequest) SetBody(v *StopShardEvacuationRequest_Body) { + x.Body = v +} +func (x *StopShardEvacuationRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *StopShardEvacuationRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StopShardEvacuationRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StopShardEvacuationRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StopShardEvacuationRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StopShardEvacuationRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *StopShardEvacuationRequest_Body + f = new(StopShardEvacuationRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StopShardEvacuationResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*StopShardEvacuationResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*StopShardEvacuationResponse_Body)(nil) + _ json.Marshaler = (*StopShardEvacuationResponse_Body)(nil) + _ json.Unmarshaler = (*StopShardEvacuationResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2322,18 +9315,93 @@ func (x *StopShardEvacuationResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *StopShardEvacuationResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StopShardEvacuationResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *StopShardEvacuationResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StopShardEvacuationResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StopShardEvacuationResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StopShardEvacuationResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StopShardEvacuationResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StopShardEvacuationResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StopShardEvacuationResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StopShardEvacuationResponse struct { + Body *StopShardEvacuationResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*StopShardEvacuationResponse)(nil) + _ encoding.ProtoUnmarshaler = (*StopShardEvacuationResponse)(nil) + _ json.Marshaler = (*StopShardEvacuationResponse)(nil) + _ json.Unmarshaler = (*StopShardEvacuationResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2346,27 +9414,6 @@ func (x *StopShardEvacuationResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *StopShardEvacuationResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2382,13 +9429,165 @@ func (x *StopShardEvacuationResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *StopShardEvacuationResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *StopShardEvacuationResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StopShardEvacuationResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *StopShardEvacuationResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StopShardEvacuationResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StopShardEvacuationResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(StopShardEvacuationResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *StopShardEvacuationResponse) GetBody() *StopShardEvacuationResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *StopShardEvacuationResponse) SetBody(v *StopShardEvacuationResponse_Body) { + x.Body = v +} +func (x *StopShardEvacuationResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *StopShardEvacuationResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StopShardEvacuationResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StopShardEvacuationResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StopShardEvacuationResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StopShardEvacuationResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *StopShardEvacuationResponse_Body + f = new(StopShardEvacuationResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddChainLocalOverrideRequest_Body struct { + Target *ChainTarget `json:"target"` + Chain []byte `json:"chain"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddChainLocalOverrideRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*AddChainLocalOverrideRequest_Body)(nil) + _ json.Marshaler = (*AddChainLocalOverrideRequest_Body)(nil) + _ json.Unmarshaler = (*AddChainLocalOverrideRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2401,27 +9600,158 @@ func (x *AddChainLocalOverrideRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) - offset += proto.BytesMarshal(2, buf[offset:], x.Chain) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddChainLocalOverrideRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddChainLocalOverrideRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Target != nil && x.Target.StableSize() != 0 { + x.Target.EmitProtobuf(mm.AppendMessage(1)) + } + if len(x.Chain) != 0 { + mm.AppendBytes(2, x.Chain) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddChainLocalOverrideRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddChainLocalOverrideRequest_Body") + } + switch fc.FieldNum { + case 1: // Target + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Target") + } + x.Target = new(ChainTarget) + if err := x.Target.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Chain + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Chain") + } + x.Chain = data + } + } + return nil +} +func (x *AddChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { + if x != nil { + return x.Target + } + return nil +} +func (x *AddChainLocalOverrideRequest_Body) SetTarget(v *ChainTarget) { + x.Target = v +} +func (x *AddChainLocalOverrideRequest_Body) GetChain() []byte { + if x != nil { + return x.Chain + } + return nil +} +func (x *AddChainLocalOverrideRequest_Body) SetChain(v []byte) { + x.Chain = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddChainLocalOverrideRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddChainLocalOverrideRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"target\":" + out.RawString(prefix[1:]) + x.Target.MarshalEasyJSON(out) + } + { + const prefix string = ",\"chain\":" + out.RawString(prefix) + out.Base64Bytes(x.Chain) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddChainLocalOverrideRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddChainLocalOverrideRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "target": + { + var f *ChainTarget + f = new(ChainTarget) + f.UnmarshalEasyJSON(in) + x.Target = f + } + case "chain": + { + var f []byte + f = in.Bytes() + x.Chain = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddChainLocalOverrideRequest struct { + Body *AddChainLocalOverrideRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddChainLocalOverrideRequest)(nil) + _ encoding.ProtoUnmarshaler = (*AddChainLocalOverrideRequest)(nil) + _ json.Marshaler = (*AddChainLocalOverrideRequest)(nil) + _ json.Unmarshaler = (*AddChainLocalOverrideRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2434,27 +9764,6 @@ func (x *AddChainLocalOverrideRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddChainLocalOverrideRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2470,13 +9779,164 @@ func (x *AddChainLocalOverrideRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *AddChainLocalOverrideRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *AddChainLocalOverrideRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddChainLocalOverrideRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddChainLocalOverrideRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddChainLocalOverrideRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddChainLocalOverrideRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(AddChainLocalOverrideRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *AddChainLocalOverrideRequest) GetBody() *AddChainLocalOverrideRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *AddChainLocalOverrideRequest) SetBody(v *AddChainLocalOverrideRequest_Body) { + x.Body = v +} +func (x *AddChainLocalOverrideRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *AddChainLocalOverrideRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddChainLocalOverrideRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddChainLocalOverrideRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddChainLocalOverrideRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddChainLocalOverrideRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *AddChainLocalOverrideRequest_Body + f = new(AddChainLocalOverrideRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddChainLocalOverrideResponse_Body struct { + ChainId []byte `json:"chainId"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddChainLocalOverrideResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*AddChainLocalOverrideResponse_Body)(nil) + _ json.Marshaler = (*AddChainLocalOverrideResponse_Body)(nil) + _ json.Unmarshaler = (*AddChainLocalOverrideResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2488,26 +9948,125 @@ func (x *AddChainLocalOverrideResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddChainLocalOverrideResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ChainId) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddChainLocalOverrideResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddChainLocalOverrideResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ChainId) != 0 { + mm.AppendBytes(1, x.ChainId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddChainLocalOverrideResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddChainLocalOverrideResponse_Body") + } + switch fc.FieldNum { + case 1: // ChainId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ChainId") + } + x.ChainId = data + } + } + return nil +} +func (x *AddChainLocalOverrideResponse_Body) GetChainId() []byte { + if x != nil { + return x.ChainId + } + return nil +} +func (x *AddChainLocalOverrideResponse_Body) SetChainId(v []byte) { + x.ChainId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddChainLocalOverrideResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddChainLocalOverrideResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"chainId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ChainId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddChainLocalOverrideResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddChainLocalOverrideResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "chainId": + { + var f []byte + f = in.Bytes() + x.ChainId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddChainLocalOverrideResponse struct { + Body *AddChainLocalOverrideResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddChainLocalOverrideResponse)(nil) + _ encoding.ProtoUnmarshaler = (*AddChainLocalOverrideResponse)(nil) + _ json.Marshaler = (*AddChainLocalOverrideResponse)(nil) + _ json.Unmarshaler = (*AddChainLocalOverrideResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2520,27 +10079,6 @@ func (x *AddChainLocalOverrideResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddChainLocalOverrideResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2556,13 +10094,165 @@ func (x *AddChainLocalOverrideResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *AddChainLocalOverrideResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *AddChainLocalOverrideResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddChainLocalOverrideResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddChainLocalOverrideResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddChainLocalOverrideResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddChainLocalOverrideResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(AddChainLocalOverrideResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *AddChainLocalOverrideResponse) GetBody() *AddChainLocalOverrideResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *AddChainLocalOverrideResponse) SetBody(v *AddChainLocalOverrideResponse_Body) { + x.Body = v +} +func (x *AddChainLocalOverrideResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *AddChainLocalOverrideResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddChainLocalOverrideResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddChainLocalOverrideResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddChainLocalOverrideResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddChainLocalOverrideResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *AddChainLocalOverrideResponse_Body + f = new(AddChainLocalOverrideResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetChainLocalOverrideRequest_Body struct { + Target *ChainTarget `json:"target"` + ChainId []byte `json:"chainId"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetChainLocalOverrideRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetChainLocalOverrideRequest_Body)(nil) + _ json.Marshaler = (*GetChainLocalOverrideRequest_Body)(nil) + _ json.Unmarshaler = (*GetChainLocalOverrideRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2575,27 +10265,158 @@ func (x *GetChainLocalOverrideRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) - offset += proto.BytesMarshal(2, buf[offset:], x.ChainId) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetChainLocalOverrideRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetChainLocalOverrideRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Target != nil && x.Target.StableSize() != 0 { + x.Target.EmitProtobuf(mm.AppendMessage(1)) + } + if len(x.ChainId) != 0 { + mm.AppendBytes(2, x.ChainId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetChainLocalOverrideRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetChainLocalOverrideRequest_Body") + } + switch fc.FieldNum { + case 1: // Target + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Target") + } + x.Target = new(ChainTarget) + if err := x.Target.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // ChainId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ChainId") + } + x.ChainId = data + } + } + return nil +} +func (x *GetChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { + if x != nil { + return x.Target + } + return nil +} +func (x *GetChainLocalOverrideRequest_Body) SetTarget(v *ChainTarget) { + x.Target = v +} +func (x *GetChainLocalOverrideRequest_Body) GetChainId() []byte { + if x != nil { + return x.ChainId + } + return nil +} +func (x *GetChainLocalOverrideRequest_Body) SetChainId(v []byte) { + x.ChainId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetChainLocalOverrideRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetChainLocalOverrideRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"target\":" + out.RawString(prefix[1:]) + x.Target.MarshalEasyJSON(out) + } + { + const prefix string = ",\"chainId\":" + out.RawString(prefix) + out.Base64Bytes(x.ChainId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetChainLocalOverrideRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetChainLocalOverrideRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "target": + { + var f *ChainTarget + f = new(ChainTarget) + f.UnmarshalEasyJSON(in) + x.Target = f + } + case "chainId": + { + var f []byte + f = in.Bytes() + x.ChainId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetChainLocalOverrideRequest struct { + Body *GetChainLocalOverrideRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetChainLocalOverrideRequest)(nil) + _ encoding.ProtoUnmarshaler = (*GetChainLocalOverrideRequest)(nil) + _ json.Marshaler = (*GetChainLocalOverrideRequest)(nil) + _ json.Unmarshaler = (*GetChainLocalOverrideRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2608,27 +10429,6 @@ func (x *GetChainLocalOverrideRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetChainLocalOverrideRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2644,13 +10444,164 @@ func (x *GetChainLocalOverrideRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetChainLocalOverrideRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetChainLocalOverrideRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetChainLocalOverrideRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetChainLocalOverrideRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetChainLocalOverrideRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetChainLocalOverrideRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetChainLocalOverrideRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetChainLocalOverrideRequest) GetBody() *GetChainLocalOverrideRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetChainLocalOverrideRequest) SetBody(v *GetChainLocalOverrideRequest_Body) { + x.Body = v +} +func (x *GetChainLocalOverrideRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetChainLocalOverrideRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetChainLocalOverrideRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetChainLocalOverrideRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetChainLocalOverrideRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetChainLocalOverrideRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetChainLocalOverrideRequest_Body + f = new(GetChainLocalOverrideRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetChainLocalOverrideResponse_Body struct { + Chain []byte `json:"chain"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetChainLocalOverrideResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetChainLocalOverrideResponse_Body)(nil) + _ json.Marshaler = (*GetChainLocalOverrideResponse_Body)(nil) + _ json.Unmarshaler = (*GetChainLocalOverrideResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2662,26 +10613,125 @@ func (x *GetChainLocalOverrideResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetChainLocalOverrideResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.Chain) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetChainLocalOverrideResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetChainLocalOverrideResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Chain) != 0 { + mm.AppendBytes(1, x.Chain) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetChainLocalOverrideResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetChainLocalOverrideResponse_Body") + } + switch fc.FieldNum { + case 1: // Chain + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Chain") + } + x.Chain = data + } + } + return nil +} +func (x *GetChainLocalOverrideResponse_Body) GetChain() []byte { + if x != nil { + return x.Chain + } + return nil +} +func (x *GetChainLocalOverrideResponse_Body) SetChain(v []byte) { + x.Chain = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetChainLocalOverrideResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetChainLocalOverrideResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"chain\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.Chain) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetChainLocalOverrideResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetChainLocalOverrideResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "chain": + { + var f []byte + f = in.Bytes() + x.Chain = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetChainLocalOverrideResponse struct { + Body *GetChainLocalOverrideResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetChainLocalOverrideResponse)(nil) + _ encoding.ProtoUnmarshaler = (*GetChainLocalOverrideResponse)(nil) + _ json.Marshaler = (*GetChainLocalOverrideResponse)(nil) + _ json.Unmarshaler = (*GetChainLocalOverrideResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2694,27 +10744,6 @@ func (x *GetChainLocalOverrideResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetChainLocalOverrideResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2730,13 +10759,164 @@ func (x *GetChainLocalOverrideResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetChainLocalOverrideResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetChainLocalOverrideResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetChainLocalOverrideResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetChainLocalOverrideResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetChainLocalOverrideResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetChainLocalOverrideResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetChainLocalOverrideResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetChainLocalOverrideResponse) GetBody() *GetChainLocalOverrideResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetChainLocalOverrideResponse) SetBody(v *GetChainLocalOverrideResponse_Body) { + x.Body = v +} +func (x *GetChainLocalOverrideResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetChainLocalOverrideResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetChainLocalOverrideResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetChainLocalOverrideResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetChainLocalOverrideResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetChainLocalOverrideResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetChainLocalOverrideResponse_Body + f = new(GetChainLocalOverrideResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListChainLocalOverridesRequest_Body struct { + Target *ChainTarget `json:"target"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListChainLocalOverridesRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListChainLocalOverridesRequest_Body)(nil) + _ json.Marshaler = (*ListChainLocalOverridesRequest_Body)(nil) + _ json.Unmarshaler = (*ListChainLocalOverridesRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2748,26 +10928,129 @@ func (x *ListChainLocalOverridesRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListChainLocalOverridesRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListChainLocalOverridesRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListChainLocalOverridesRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Target != nil && x.Target.StableSize() != 0 { + x.Target.EmitProtobuf(mm.AppendMessage(1)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListChainLocalOverridesRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListChainLocalOverridesRequest_Body") + } + switch fc.FieldNum { + case 1: // Target + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Target") + } + x.Target = new(ChainTarget) + if err := x.Target.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListChainLocalOverridesRequest_Body) GetTarget() *ChainTarget { + if x != nil { + return x.Target + } + return nil +} +func (x *ListChainLocalOverridesRequest_Body) SetTarget(v *ChainTarget) { + x.Target = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListChainLocalOverridesRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListChainLocalOverridesRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"target\":" + out.RawString(prefix[1:]) + x.Target.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListChainLocalOverridesRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListChainLocalOverridesRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "target": + { + var f *ChainTarget + f = new(ChainTarget) + f.UnmarshalEasyJSON(in) + x.Target = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListChainLocalOverridesRequest struct { + Body *ListChainLocalOverridesRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListChainLocalOverridesRequest)(nil) + _ encoding.ProtoUnmarshaler = (*ListChainLocalOverridesRequest)(nil) + _ json.Marshaler = (*ListChainLocalOverridesRequest)(nil) + _ json.Unmarshaler = (*ListChainLocalOverridesRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2780,27 +11063,6 @@ func (x *ListChainLocalOverridesRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListChainLocalOverridesRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2816,13 +11078,164 @@ func (x *ListChainLocalOverridesRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ListChainLocalOverridesRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ListChainLocalOverridesRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListChainLocalOverridesRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListChainLocalOverridesRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListChainLocalOverridesRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListChainLocalOverridesRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListChainLocalOverridesRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListChainLocalOverridesRequest) GetBody() *ListChainLocalOverridesRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListChainLocalOverridesRequest) SetBody(v *ListChainLocalOverridesRequest_Body) { + x.Body = v +} +func (x *ListChainLocalOverridesRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ListChainLocalOverridesRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListChainLocalOverridesRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListChainLocalOverridesRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListChainLocalOverridesRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListChainLocalOverridesRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListChainLocalOverridesRequest_Body + f = new(ListChainLocalOverridesRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListChainLocalOverridesResponse_Body struct { + Chains [][]byte `json:"chains"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListChainLocalOverridesResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListChainLocalOverridesResponse_Body)(nil) + _ json.Marshaler = (*ListChainLocalOverridesResponse_Body)(nil) + _ json.Unmarshaler = (*ListChainLocalOverridesResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2834,26 +11247,139 @@ func (x *ListChainLocalOverridesResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListChainLocalOverridesResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Chains) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListChainLocalOverridesResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListChainLocalOverridesResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Chains { + mm.AppendBytes(1, x.Chains[j]) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListChainLocalOverridesResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListChainLocalOverridesResponse_Body") + } + switch fc.FieldNum { + case 1: // Chains + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Chains") + } + x.Chains = append(x.Chains, data) + } + } + return nil +} +func (x *ListChainLocalOverridesResponse_Body) GetChains() [][]byte { + if x != nil { + return x.Chains + } + return nil +} +func (x *ListChainLocalOverridesResponse_Body) SetChains(v [][]byte) { + x.Chains = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListChainLocalOverridesResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListChainLocalOverridesResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"chains\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Chains { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Chains[i]) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListChainLocalOverridesResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListChainLocalOverridesResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "chains": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Chains = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListChainLocalOverridesResponse struct { + Body *ListChainLocalOverridesResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListChainLocalOverridesResponse)(nil) + _ encoding.ProtoUnmarshaler = (*ListChainLocalOverridesResponse)(nil) + _ json.Marshaler = (*ListChainLocalOverridesResponse)(nil) + _ json.Unmarshaler = (*ListChainLocalOverridesResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2866,27 +11392,6 @@ func (x *ListChainLocalOverridesResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListChainLocalOverridesResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2902,13 +11407,164 @@ func (x *ListChainLocalOverridesResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ListChainLocalOverridesResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ListChainLocalOverridesResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListChainLocalOverridesResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListChainLocalOverridesResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListChainLocalOverridesResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListChainLocalOverridesResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListChainLocalOverridesResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListChainLocalOverridesResponse) GetBody() *ListChainLocalOverridesResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListChainLocalOverridesResponse) SetBody(v *ListChainLocalOverridesResponse_Body) { + x.Body = v +} +func (x *ListChainLocalOverridesResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ListChainLocalOverridesResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListChainLocalOverridesResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListChainLocalOverridesResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListChainLocalOverridesResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListChainLocalOverridesResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListChainLocalOverridesResponse_Body + f = new(ListChainLocalOverridesResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListTargetsLocalOverridesRequest_Body struct { + ChainName string `json:"chainName"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListTargetsLocalOverridesRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListTargetsLocalOverridesRequest_Body)(nil) + _ json.Marshaler = (*ListTargetsLocalOverridesRequest_Body)(nil) + _ json.Unmarshaler = (*ListTargetsLocalOverridesRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2920,26 +11576,125 @@ func (x *ListTargetsLocalOverridesRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListTargetsLocalOverridesRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.StringMarshal(1, buf[offset:], x.ChainName) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListTargetsLocalOverridesRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListTargetsLocalOverridesRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ChainName) != 0 { + mm.AppendString(1, x.ChainName) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListTargetsLocalOverridesRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListTargetsLocalOverridesRequest_Body") + } + switch fc.FieldNum { + case 1: // ChainName + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ChainName") + } + x.ChainName = data + } + } + return nil +} +func (x *ListTargetsLocalOverridesRequest_Body) GetChainName() string { + if x != nil { + return x.ChainName + } + return "" +} +func (x *ListTargetsLocalOverridesRequest_Body) SetChainName(v string) { + x.ChainName = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListTargetsLocalOverridesRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListTargetsLocalOverridesRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"chainName\":" + out.RawString(prefix[1:]) + out.String(x.ChainName) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListTargetsLocalOverridesRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListTargetsLocalOverridesRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "chainName": + { + var f string + f = in.String() + x.ChainName = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListTargetsLocalOverridesRequest struct { + Body *ListTargetsLocalOverridesRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListTargetsLocalOverridesRequest)(nil) + _ encoding.ProtoUnmarshaler = (*ListTargetsLocalOverridesRequest)(nil) + _ json.Marshaler = (*ListTargetsLocalOverridesRequest)(nil) + _ json.Unmarshaler = (*ListTargetsLocalOverridesRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -2952,27 +11707,6 @@ func (x *ListTargetsLocalOverridesRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListTargetsLocalOverridesRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -2988,13 +11722,164 @@ func (x *ListTargetsLocalOverridesRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ListTargetsLocalOverridesRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ListTargetsLocalOverridesRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListTargetsLocalOverridesRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListTargetsLocalOverridesRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListTargetsLocalOverridesRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListTargetsLocalOverridesRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListTargetsLocalOverridesRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListTargetsLocalOverridesRequest) GetBody() *ListTargetsLocalOverridesRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListTargetsLocalOverridesRequest) SetBody(v *ListTargetsLocalOverridesRequest_Body) { + x.Body = v +} +func (x *ListTargetsLocalOverridesRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ListTargetsLocalOverridesRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListTargetsLocalOverridesRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListTargetsLocalOverridesRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListTargetsLocalOverridesRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListTargetsLocalOverridesRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListTargetsLocalOverridesRequest_Body + f = new(ListTargetsLocalOverridesRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListTargetsLocalOverridesResponse_Body struct { + Targets []*ChainTarget `json:"targets"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListTargetsLocalOverridesResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListTargetsLocalOverridesResponse_Body)(nil) + _ json.Marshaler = (*ListTargetsLocalOverridesResponse_Body)(nil) + _ json.Unmarshaler = (*ListTargetsLocalOverridesResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3008,28 +11893,146 @@ func (x *ListTargetsLocalOverridesResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListTargetsLocalOverridesResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - for i := range x.Targets { - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Targets[i]) - } - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListTargetsLocalOverridesResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListTargetsLocalOverridesResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for i := range x.Targets { + if x.Targets[i] != nil && x.Targets[i].StableSize() != 0 { + x.Targets[i].EmitProtobuf(mm.AppendMessage(1)) + } + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListTargetsLocalOverridesResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListTargetsLocalOverridesResponse_Body") + } + switch fc.FieldNum { + case 1: // Targets + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Targets") + } + x.Targets = append(x.Targets, new(ChainTarget)) + ff := x.Targets[len(x.Targets)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListTargetsLocalOverridesResponse_Body) GetTargets() []*ChainTarget { + if x != nil { + return x.Targets + } + return nil +} +func (x *ListTargetsLocalOverridesResponse_Body) SetTargets(v []*ChainTarget) { + x.Targets = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListTargetsLocalOverridesResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListTargetsLocalOverridesResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"targets\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Targets { + if i != 0 { + out.RawByte(',') + } + x.Targets[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListTargetsLocalOverridesResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListTargetsLocalOverridesResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "targets": + { + var f *ChainTarget + var list []*ChainTarget + in.Delim('[') + for !in.IsDelim(']') { + f = new(ChainTarget) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Targets = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListTargetsLocalOverridesResponse struct { + Body *ListTargetsLocalOverridesResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListTargetsLocalOverridesResponse)(nil) + _ encoding.ProtoUnmarshaler = (*ListTargetsLocalOverridesResponse)(nil) + _ json.Marshaler = (*ListTargetsLocalOverridesResponse)(nil) + _ json.Unmarshaler = (*ListTargetsLocalOverridesResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3042,27 +12045,6 @@ func (x *ListTargetsLocalOverridesResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ListTargetsLocalOverridesResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3078,13 +12060,165 @@ func (x *ListTargetsLocalOverridesResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ListTargetsLocalOverridesResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ListTargetsLocalOverridesResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListTargetsLocalOverridesResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ListTargetsLocalOverridesResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListTargetsLocalOverridesResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListTargetsLocalOverridesResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListTargetsLocalOverridesResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListTargetsLocalOverridesResponse) GetBody() *ListTargetsLocalOverridesResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListTargetsLocalOverridesResponse) SetBody(v *ListTargetsLocalOverridesResponse_Body) { + x.Body = v +} +func (x *ListTargetsLocalOverridesResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ListTargetsLocalOverridesResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListTargetsLocalOverridesResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListTargetsLocalOverridesResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListTargetsLocalOverridesResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListTargetsLocalOverridesResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListTargetsLocalOverridesResponse_Body + f = new(ListTargetsLocalOverridesResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveChainLocalOverrideRequest_Body struct { + Target *ChainTarget `json:"target"` + ChainId []byte `json:"chainId"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveChainLocalOverrideRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveChainLocalOverrideRequest_Body)(nil) + _ json.Marshaler = (*RemoveChainLocalOverrideRequest_Body)(nil) + _ json.Unmarshaler = (*RemoveChainLocalOverrideRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3097,27 +12231,158 @@ func (x *RemoveChainLocalOverrideRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveChainLocalOverrideRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) - offset += proto.BytesMarshal(2, buf[offset:], x.ChainId) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveChainLocalOverrideRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveChainLocalOverrideRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Target != nil && x.Target.StableSize() != 0 { + x.Target.EmitProtobuf(mm.AppendMessage(1)) + } + if len(x.ChainId) != 0 { + mm.AppendBytes(2, x.ChainId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveChainLocalOverrideRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveChainLocalOverrideRequest_Body") + } + switch fc.FieldNum { + case 1: // Target + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Target") + } + x.Target = new(ChainTarget) + if err := x.Target.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // ChainId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ChainId") + } + x.ChainId = data + } + } + return nil +} +func (x *RemoveChainLocalOverrideRequest_Body) GetTarget() *ChainTarget { + if x != nil { + return x.Target + } + return nil +} +func (x *RemoveChainLocalOverrideRequest_Body) SetTarget(v *ChainTarget) { + x.Target = v +} +func (x *RemoveChainLocalOverrideRequest_Body) GetChainId() []byte { + if x != nil { + return x.ChainId + } + return nil +} +func (x *RemoveChainLocalOverrideRequest_Body) SetChainId(v []byte) { + x.ChainId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveChainLocalOverrideRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveChainLocalOverrideRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"target\":" + out.RawString(prefix[1:]) + x.Target.MarshalEasyJSON(out) + } + { + const prefix string = ",\"chainId\":" + out.RawString(prefix) + out.Base64Bytes(x.ChainId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveChainLocalOverrideRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveChainLocalOverrideRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "target": + { + var f *ChainTarget + f = new(ChainTarget) + f.UnmarshalEasyJSON(in) + x.Target = f + } + case "chainId": + { + var f []byte + f = in.Bytes() + x.ChainId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveChainLocalOverrideRequest struct { + Body *RemoveChainLocalOverrideRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveChainLocalOverrideRequest)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveChainLocalOverrideRequest)(nil) + _ json.Marshaler = (*RemoveChainLocalOverrideRequest)(nil) + _ json.Unmarshaler = (*RemoveChainLocalOverrideRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3130,27 +12395,6 @@ func (x *RemoveChainLocalOverrideRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveChainLocalOverrideRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3166,13 +12410,163 @@ func (x *RemoveChainLocalOverrideRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveChainLocalOverrideRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveChainLocalOverrideRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveChainLocalOverrideRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveChainLocalOverrideRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveChainLocalOverrideRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveChainLocalOverrideRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveChainLocalOverrideRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveChainLocalOverrideRequest) GetBody() *RemoveChainLocalOverrideRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveChainLocalOverrideRequest) SetBody(v *RemoveChainLocalOverrideRequest_Body) { + x.Body = v +} +func (x *RemoveChainLocalOverrideRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveChainLocalOverrideRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveChainLocalOverrideRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveChainLocalOverrideRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveChainLocalOverrideRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveChainLocalOverrideRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveChainLocalOverrideRequest_Body + f = new(RemoveChainLocalOverrideRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveChainLocalOverrideResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveChainLocalOverrideResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveChainLocalOverrideResponse_Body)(nil) + _ json.Marshaler = (*RemoveChainLocalOverrideResponse_Body)(nil) + _ json.Unmarshaler = (*RemoveChainLocalOverrideResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3183,18 +12577,93 @@ func (x *RemoveChainLocalOverrideResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveChainLocalOverrideResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveChainLocalOverrideResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveChainLocalOverrideResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveChainLocalOverrideResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveChainLocalOverrideResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveChainLocalOverrideResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveChainLocalOverrideResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveChainLocalOverrideResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveChainLocalOverrideResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveChainLocalOverrideResponse struct { + Body *RemoveChainLocalOverrideResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveChainLocalOverrideResponse)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveChainLocalOverrideResponse)(nil) + _ json.Marshaler = (*RemoveChainLocalOverrideResponse)(nil) + _ json.Unmarshaler = (*RemoveChainLocalOverrideResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3207,27 +12676,6 @@ func (x *RemoveChainLocalOverrideResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveChainLocalOverrideResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3243,13 +12691,164 @@ func (x *RemoveChainLocalOverrideResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveChainLocalOverrideResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveChainLocalOverrideResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveChainLocalOverrideResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveChainLocalOverrideResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveChainLocalOverrideResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveChainLocalOverrideResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveChainLocalOverrideResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveChainLocalOverrideResponse) GetBody() *RemoveChainLocalOverrideResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveChainLocalOverrideResponse) SetBody(v *RemoveChainLocalOverrideResponse_Body) { + x.Body = v +} +func (x *RemoveChainLocalOverrideResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveChainLocalOverrideResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveChainLocalOverrideResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveChainLocalOverrideResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveChainLocalOverrideResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveChainLocalOverrideResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveChainLocalOverrideResponse_Body + f = new(RemoveChainLocalOverrideResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveChainLocalOverridesByTargetRequest_Body struct { + Target *ChainTarget `json:"target"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveChainLocalOverridesByTargetRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveChainLocalOverridesByTargetRequest_Body)(nil) + _ json.Marshaler = (*RemoveChainLocalOverridesByTargetRequest_Body)(nil) + _ json.Unmarshaler = (*RemoveChainLocalOverridesByTargetRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3261,26 +12860,129 @@ func (x *RemoveChainLocalOverridesByTargetRequest_Body) StableSize() (size int) return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveChainLocalOverridesByTargetRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Target) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveChainLocalOverridesByTargetRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveChainLocalOverridesByTargetRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Target != nil && x.Target.StableSize() != 0 { + x.Target.EmitProtobuf(mm.AppendMessage(1)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveChainLocalOverridesByTargetRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveChainLocalOverridesByTargetRequest_Body") + } + switch fc.FieldNum { + case 1: // Target + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Target") + } + x.Target = new(ChainTarget) + if err := x.Target.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveChainLocalOverridesByTargetRequest_Body) GetTarget() *ChainTarget { + if x != nil { + return x.Target + } + return nil +} +func (x *RemoveChainLocalOverridesByTargetRequest_Body) SetTarget(v *ChainTarget) { + x.Target = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveChainLocalOverridesByTargetRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveChainLocalOverridesByTargetRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"target\":" + out.RawString(prefix[1:]) + x.Target.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveChainLocalOverridesByTargetRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveChainLocalOverridesByTargetRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "target": + { + var f *ChainTarget + f = new(ChainTarget) + f.UnmarshalEasyJSON(in) + x.Target = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveChainLocalOverridesByTargetRequest struct { + Body *RemoveChainLocalOverridesByTargetRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveChainLocalOverridesByTargetRequest)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveChainLocalOverridesByTargetRequest)(nil) + _ json.Marshaler = (*RemoveChainLocalOverridesByTargetRequest)(nil) + _ json.Unmarshaler = (*RemoveChainLocalOverridesByTargetRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3293,27 +12995,6 @@ func (x *RemoveChainLocalOverridesByTargetRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveChainLocalOverridesByTargetRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3329,13 +13010,163 @@ func (x *RemoveChainLocalOverridesByTargetRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveChainLocalOverridesByTargetRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveChainLocalOverridesByTargetRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveChainLocalOverridesByTargetRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveChainLocalOverridesByTargetRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveChainLocalOverridesByTargetRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveChainLocalOverridesByTargetRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveChainLocalOverridesByTargetRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveChainLocalOverridesByTargetRequest) GetBody() *RemoveChainLocalOverridesByTargetRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveChainLocalOverridesByTargetRequest) SetBody(v *RemoveChainLocalOverridesByTargetRequest_Body) { + x.Body = v +} +func (x *RemoveChainLocalOverridesByTargetRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveChainLocalOverridesByTargetRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveChainLocalOverridesByTargetRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveChainLocalOverridesByTargetRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveChainLocalOverridesByTargetRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveChainLocalOverridesByTargetRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveChainLocalOverridesByTargetRequest_Body + f = new(RemoveChainLocalOverridesByTargetRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveChainLocalOverridesByTargetResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveChainLocalOverridesByTargetResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveChainLocalOverridesByTargetResponse_Body)(nil) + _ json.Marshaler = (*RemoveChainLocalOverridesByTargetResponse_Body)(nil) + _ json.Unmarshaler = (*RemoveChainLocalOverridesByTargetResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3346,18 +13177,93 @@ func (x *RemoveChainLocalOverridesByTargetResponse_Body) StableSize() (size int) return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveChainLocalOverridesByTargetResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveChainLocalOverridesByTargetResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveChainLocalOverridesByTargetResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveChainLocalOverridesByTargetResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveChainLocalOverridesByTargetResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveChainLocalOverridesByTargetResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveChainLocalOverridesByTargetResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveChainLocalOverridesByTargetResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveChainLocalOverridesByTargetResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveChainLocalOverridesByTargetResponse struct { + Body *RemoveChainLocalOverridesByTargetResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveChainLocalOverridesByTargetResponse)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveChainLocalOverridesByTargetResponse)(nil) + _ json.Marshaler = (*RemoveChainLocalOverridesByTargetResponse)(nil) + _ json.Unmarshaler = (*RemoveChainLocalOverridesByTargetResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3370,27 +13276,6 @@ func (x *RemoveChainLocalOverridesByTargetResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveChainLocalOverridesByTargetResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3406,13 +13291,168 @@ func (x *RemoveChainLocalOverridesByTargetResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveChainLocalOverridesByTargetResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveChainLocalOverridesByTargetResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveChainLocalOverridesByTargetResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveChainLocalOverridesByTargetResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveChainLocalOverridesByTargetResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveChainLocalOverridesByTargetResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveChainLocalOverridesByTargetResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveChainLocalOverridesByTargetResponse) GetBody() *RemoveChainLocalOverridesByTargetResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveChainLocalOverridesByTargetResponse) SetBody(v *RemoveChainLocalOverridesByTargetResponse_Body) { + x.Body = v +} +func (x *RemoveChainLocalOverridesByTargetResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveChainLocalOverridesByTargetResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveChainLocalOverridesByTargetResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveChainLocalOverridesByTargetResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveChainLocalOverridesByTargetResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveChainLocalOverridesByTargetResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveChainLocalOverridesByTargetResponse_Body + f = new(RemoveChainLocalOverridesByTargetResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SealWriteCacheRequest_Body struct { + Shard_ID [][]byte `json:"shardID"` + IgnoreErrors bool `json:"ignoreErrors"` + Async bool `json:"async"` + RestoreMode bool `json:"restoreMode"` + Shrink bool `json:"shrink"` +} + +var ( + _ encoding.ProtoMarshaler = (*SealWriteCacheRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*SealWriteCacheRequest_Body)(nil) + _ json.Marshaler = (*SealWriteCacheRequest_Body)(nil) + _ json.Unmarshaler = (*SealWriteCacheRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3428,30 +13468,255 @@ func (x *SealWriteCacheRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SealWriteCacheRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) - offset += proto.BoolMarshal(2, buf[offset:], x.IgnoreErrors) - offset += proto.BoolMarshal(3, buf[offset:], x.Async) - offset += proto.BoolMarshal(4, buf[offset:], x.RestoreMode) - offset += proto.BoolMarshal(5, buf[offset:], x.Shrink) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SealWriteCacheRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SealWriteCacheRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Shard_ID { + mm.AppendBytes(1, x.Shard_ID[j]) + } + if x.IgnoreErrors { + mm.AppendBool(2, x.IgnoreErrors) + } + if x.Async { + mm.AppendBool(3, x.Async) + } + if x.RestoreMode { + mm.AppendBool(4, x.RestoreMode) + } + if x.Shrink { + mm.AppendBool(5, x.Shrink) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SealWriteCacheRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SealWriteCacheRequest_Body") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + case 2: // IgnoreErrors + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "IgnoreErrors") + } + x.IgnoreErrors = data + case 3: // Async + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Async") + } + x.Async = data + case 4: // RestoreMode + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "RestoreMode") + } + x.RestoreMode = data + case 5: // Shrink + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shrink") + } + x.Shrink = data + } + } + return nil +} +func (x *SealWriteCacheRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *SealWriteCacheRequest_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} +func (x *SealWriteCacheRequest_Body) GetIgnoreErrors() bool { + if x != nil { + return x.IgnoreErrors + } + return false +} +func (x *SealWriteCacheRequest_Body) SetIgnoreErrors(v bool) { + x.IgnoreErrors = v +} +func (x *SealWriteCacheRequest_Body) GetAsync() bool { + if x != nil { + return x.Async + } + return false +} +func (x *SealWriteCacheRequest_Body) SetAsync(v bool) { + x.Async = v +} +func (x *SealWriteCacheRequest_Body) GetRestoreMode() bool { + if x != nil { + return x.RestoreMode + } + return false +} +func (x *SealWriteCacheRequest_Body) SetRestoreMode(v bool) { + x.RestoreMode = v +} +func (x *SealWriteCacheRequest_Body) GetShrink() bool { + if x != nil { + return x.Shrink + } + return false +} +func (x *SealWriteCacheRequest_Body) SetShrink(v bool) { + x.Shrink = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SealWriteCacheRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SealWriteCacheRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Shard_ID[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"ignoreErrors\":" + out.RawString(prefix) + out.Bool(x.IgnoreErrors) + } + { + const prefix string = ",\"async\":" + out.RawString(prefix) + out.Bool(x.Async) + } + { + const prefix string = ",\"restoreMode\":" + out.RawString(prefix) + out.Bool(x.RestoreMode) + } + { + const prefix string = ",\"shrink\":" + out.RawString(prefix) + out.Bool(x.Shrink) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SealWriteCacheRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SealWriteCacheRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + case "ignoreErrors": + { + var f bool + f = in.Bool() + x.IgnoreErrors = f + } + case "async": + { + var f bool + f = in.Bool() + x.Async = f + } + case "restoreMode": + { + var f bool + f = in.Bool() + x.RestoreMode = f + } + case "shrink": + { + var f bool + f = in.Bool() + x.Shrink = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SealWriteCacheRequest struct { + Body *SealWriteCacheRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*SealWriteCacheRequest)(nil) + _ encoding.ProtoUnmarshaler = (*SealWriteCacheRequest)(nil) + _ json.Marshaler = (*SealWriteCacheRequest)(nil) + _ json.Unmarshaler = (*SealWriteCacheRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3464,27 +13729,6 @@ func (x *SealWriteCacheRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SealWriteCacheRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3500,13 +13744,166 @@ func (x *SealWriteCacheRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *SealWriteCacheRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *SealWriteCacheRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SealWriteCacheRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SealWriteCacheRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SealWriteCacheRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SealWriteCacheRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(SealWriteCacheRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SealWriteCacheRequest) GetBody() *SealWriteCacheRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *SealWriteCacheRequest) SetBody(v *SealWriteCacheRequest_Body) { + x.Body = v +} +func (x *SealWriteCacheRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *SealWriteCacheRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SealWriteCacheRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SealWriteCacheRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SealWriteCacheRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SealWriteCacheRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *SealWriteCacheRequest_Body + f = new(SealWriteCacheRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SealWriteCacheResponse_Body_Status struct { + Shard_ID []byte `json:"shardID"` + Success bool `json:"success"` + Error string `json:"error"` +} + +var ( + _ encoding.ProtoMarshaler = (*SealWriteCacheResponse_Body_Status)(nil) + _ encoding.ProtoUnmarshaler = (*SealWriteCacheResponse_Body_Status)(nil) + _ json.Marshaler = (*SealWriteCacheResponse_Body_Status)(nil) + _ json.Unmarshaler = (*SealWriteCacheResponse_Body_Status)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3520,28 +13917,182 @@ func (x *SealWriteCacheResponse_Body_Status) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SealWriteCacheResponse_Body_Status) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.Shard_ID) - offset += proto.BoolMarshal(2, buf[offset:], x.Success) - offset += proto.StringMarshal(3, buf[offset:], x.Error) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SealWriteCacheResponse_Body_Status) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SealWriteCacheResponse_Body_Status) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Shard_ID) != 0 { + mm.AppendBytes(1, x.Shard_ID) + } + if x.Success { + mm.AppendBool(2, x.Success) + } + if len(x.Error) != 0 { + mm.AppendString(3, x.Error) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SealWriteCacheResponse_Body_Status) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SealWriteCacheResponse_Body_Status") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = data + case 2: // Success + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Success") + } + x.Success = data + case 3: // Error + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Error") + } + x.Error = data + } + } + return nil +} +func (x *SealWriteCacheResponse_Body_Status) GetShard_ID() []byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *SealWriteCacheResponse_Body_Status) SetShard_ID(v []byte) { + x.Shard_ID = v +} +func (x *SealWriteCacheResponse_Body_Status) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} +func (x *SealWriteCacheResponse_Body_Status) SetSuccess(v bool) { + x.Success = v +} +func (x *SealWriteCacheResponse_Body_Status) GetError() string { + if x != nil { + return x.Error + } + return "" +} +func (x *SealWriteCacheResponse_Body_Status) SetError(v string) { + x.Error = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SealWriteCacheResponse_Body_Status) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SealWriteCacheResponse_Body_Status) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.Shard_ID) + } + { + const prefix string = ",\"success\":" + out.RawString(prefix) + out.Bool(x.Success) + } + { + const prefix string = ",\"error\":" + out.RawString(prefix) + out.String(x.Error) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SealWriteCacheResponse_Body_Status) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SealWriteCacheResponse_Body_Status) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + f = in.Bytes() + x.Shard_ID = f + } + case "success": + { + var f bool + f = in.Bool() + x.Success = f + } + case "error": + { + var f string + f = in.String() + x.Error = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SealWriteCacheResponse_Body struct { + Results []*SealWriteCacheResponse_Body_Status `json:"results"` +} + +var ( + _ encoding.ProtoMarshaler = (*SealWriteCacheResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*SealWriteCacheResponse_Body)(nil) + _ json.Marshaler = (*SealWriteCacheResponse_Body)(nil) + _ json.Unmarshaler = (*SealWriteCacheResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3555,28 +14106,146 @@ func (x *SealWriteCacheResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SealWriteCacheResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - for i := range x.Results { - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Results[i]) - } - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SealWriteCacheResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SealWriteCacheResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for i := range x.Results { + if x.Results[i] != nil && x.Results[i].StableSize() != 0 { + x.Results[i].EmitProtobuf(mm.AppendMessage(1)) + } + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SealWriteCacheResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SealWriteCacheResponse_Body") + } + switch fc.FieldNum { + case 1: // Results + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Results") + } + x.Results = append(x.Results, new(SealWriteCacheResponse_Body_Status)) + ff := x.Results[len(x.Results)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SealWriteCacheResponse_Body) GetResults() []*SealWriteCacheResponse_Body_Status { + if x != nil { + return x.Results + } + return nil +} +func (x *SealWriteCacheResponse_Body) SetResults(v []*SealWriteCacheResponse_Body_Status) { + x.Results = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SealWriteCacheResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SealWriteCacheResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"results\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Results { + if i != 0 { + out.RawByte(',') + } + x.Results[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SealWriteCacheResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SealWriteCacheResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "results": + { + var f *SealWriteCacheResponse_Body_Status + var list []*SealWriteCacheResponse_Body_Status + in.Delim('[') + for !in.IsDelim(']') { + f = new(SealWriteCacheResponse_Body_Status) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Results = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type SealWriteCacheResponse struct { + Body *SealWriteCacheResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*SealWriteCacheResponse)(nil) + _ encoding.ProtoUnmarshaler = (*SealWriteCacheResponse)(nil) + _ json.Marshaler = (*SealWriteCacheResponse)(nil) + _ json.Unmarshaler = (*SealWriteCacheResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3589,27 +14258,6 @@ func (x *SealWriteCacheResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *SealWriteCacheResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3625,13 +14273,164 @@ func (x *SealWriteCacheResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *SealWriteCacheResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *SealWriteCacheResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *SealWriteCacheResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *SealWriteCacheResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *SealWriteCacheResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "SealWriteCacheResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(SealWriteCacheResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *SealWriteCacheResponse) GetBody() *SealWriteCacheResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *SealWriteCacheResponse) SetBody(v *SealWriteCacheResponse_Body) { + x.Body = v +} +func (x *SealWriteCacheResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *SealWriteCacheResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *SealWriteCacheResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *SealWriteCacheResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *SealWriteCacheResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *SealWriteCacheResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *SealWriteCacheResponse_Body + f = new(SealWriteCacheResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DetachShardsRequest_Body struct { + Shard_ID [][]byte `json:"shardID"` +} + +var ( + _ encoding.ProtoMarshaler = (*DetachShardsRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*DetachShardsRequest_Body)(nil) + _ json.Marshaler = (*DetachShardsRequest_Body)(nil) + _ json.Unmarshaler = (*DetachShardsRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3643,26 +14442,139 @@ func (x *DetachShardsRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DetachShardsRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedBytesMarshal(1, buf[offset:], x.Shard_ID) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DetachShardsRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DetachShardsRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Shard_ID { + mm.AppendBytes(1, x.Shard_ID[j]) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DetachShardsRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DetachShardsRequest_Body") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + } + } + return nil +} +func (x *DetachShardsRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *DetachShardsRequest_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DetachShardsRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DetachShardsRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Shard_ID[i]) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DetachShardsRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DetachShardsRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DetachShardsRequest struct { + Body *DetachShardsRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*DetachShardsRequest)(nil) + _ encoding.ProtoUnmarshaler = (*DetachShardsRequest)(nil) + _ json.Marshaler = (*DetachShardsRequest)(nil) + _ json.Unmarshaler = (*DetachShardsRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3675,27 +14587,6 @@ func (x *DetachShardsRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DetachShardsRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3711,13 +14602,163 @@ func (x *DetachShardsRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *DetachShardsRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *DetachShardsRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DetachShardsRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DetachShardsRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DetachShardsRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DetachShardsRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(DetachShardsRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *DetachShardsRequest) GetBody() *DetachShardsRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *DetachShardsRequest) SetBody(v *DetachShardsRequest_Body) { + x.Body = v +} +func (x *DetachShardsRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *DetachShardsRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DetachShardsRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DetachShardsRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DetachShardsRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DetachShardsRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *DetachShardsRequest_Body + f = new(DetachShardsRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DetachShardsResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*DetachShardsResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*DetachShardsResponse_Body)(nil) + _ json.Marshaler = (*DetachShardsResponse_Body)(nil) + _ json.Unmarshaler = (*DetachShardsResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3728,18 +14769,93 @@ func (x *DetachShardsResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DetachShardsResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DetachShardsResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *DetachShardsResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DetachShardsResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DetachShardsResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DetachShardsResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DetachShardsResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DetachShardsResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DetachShardsResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type DetachShardsResponse struct { + Body *DetachShardsResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*DetachShardsResponse)(nil) + _ encoding.ProtoUnmarshaler = (*DetachShardsResponse)(nil) + _ json.Marshaler = (*DetachShardsResponse)(nil) + _ json.Unmarshaler = (*DetachShardsResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -3752,27 +14868,6 @@ func (x *DetachShardsResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *DetachShardsResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -3788,9 +14883,149 @@ func (x *DetachShardsResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *DetachShardsResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *DetachShardsResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *DetachShardsResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *DetachShardsResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *DetachShardsResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "DetachShardsResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(DetachShardsResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *DetachShardsResponse) GetBody() *DetachShardsResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *DetachShardsResponse) SetBody(v *DetachShardsResponse_Body) { + x.Body = v +} +func (x *DetachShardsResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *DetachShardsResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *DetachShardsResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *DetachShardsResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *DetachShardsResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *DetachShardsResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *DetachShardsResponse_Body + f = new(DetachShardsResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } } diff --git a/pkg/services/control/service_test.go b/pkg/services/control/service_test.go deleted file mode 100644 index 1d98cc6f1e..0000000000 --- a/pkg/services/control/service_test.go +++ /dev/null @@ -1,181 +0,0 @@ -package control_test - -import ( - "bytes" - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" -) - -func TestHealthCheckResponse_Body_StableMarshal(t *testing.T) { - testStableMarshal(t, - generateHealthCheckResponseBody(), - new(control.HealthCheckResponse_Body), - func(m1, m2 protoMessage) bool { - return equalHealthCheckResponseBodies( - m1.(*control.HealthCheckResponse_Body), - m2.(*control.HealthCheckResponse_Body), - ) - }, - ) -} - -func generateHealthCheckResponseBody() *control.HealthCheckResponse_Body { - body := new(control.HealthCheckResponse_Body) - body.SetNetmapStatus(control.NetmapStatus_ONLINE) - body.SetHealthStatus(control.HealthStatus_SHUTTING_DOWN) - - return body -} - -func equalHealthCheckResponseBodies(b1, b2 *control.HealthCheckResponse_Body) bool { - return b1.GetNetmapStatus() == b2.GetNetmapStatus() && - b1.GetHealthStatus() == b2.GetHealthStatus() -} - -func TestSetNetmapStatusRequest_Body_StableMarshal(t *testing.T) { - testStableMarshal(t, - generateSetNetmapStatusRequestBody(), - new(control.SetNetmapStatusRequest_Body), - func(m1, m2 protoMessage) bool { - return equalSetnetmapStatusRequestBodies( - m1.(*control.SetNetmapStatusRequest_Body), - m2.(*control.SetNetmapStatusRequest_Body), - ) - }, - ) -} - -func generateSetNetmapStatusRequestBody() *control.SetNetmapStatusRequest_Body { - body := new(control.SetNetmapStatusRequest_Body) - body.SetStatus(control.NetmapStatus_ONLINE) - - return body -} - -func equalSetnetmapStatusRequestBodies(b1, b2 *control.SetNetmapStatusRequest_Body) bool { - return b1.GetStatus() == b2.GetStatus() -} - -func TestListShardsResponse_Body_StableMarshal(t *testing.T) { - testStableMarshal(t, - generateListShardsResponseBody(), - new(control.ListShardsResponse_Body), - func(m1, m2 protoMessage) bool { - return equalListShardResponseBodies( - m1.(*control.ListShardsResponse_Body), - m2.(*control.ListShardsResponse_Body), - ) - }, - ) -} - -func equalListShardResponseBodies(b1, b2 *control.ListShardsResponse_Body) bool { - if len(b1.Shards) != len(b2.Shards) { - return false - } - - for i := range b1.Shards { - if b1.Shards[i].GetMetabasePath() != b2.Shards[i].GetMetabasePath() || - b1.Shards[i].GetWritecachePath() != b2.Shards[i].GetWritecachePath() || - b1.Shards[i].GetPiloramaPath() != b2.Shards[i].GetPiloramaPath() || - !bytes.Equal(b1.Shards[i].GetShard_ID(), b2.Shards[i].GetShard_ID()) { - return false - } - - info1 := b1.Shards[i].GetBlobstor() - info2 := b2.Shards[i].GetBlobstor() - if !compareBlobstorInfo(info1, info2) { - return false - } - } - - for i := range b1.Shards { - for j := i + 1; j < len(b1.Shards); j++ { - if b1.Shards[i].GetMetabasePath() == b2.Shards[j].GetMetabasePath() || - !compareBlobstorInfo(b1.Shards[i].Blobstor, b2.Shards[i].Blobstor) || - b1.Shards[i].GetWritecachePath() == b2.Shards[j].GetWritecachePath() || - bytes.Equal(b1.Shards[i].GetShard_ID(), b2.Shards[j].GetShard_ID()) { - return false - } - } - } - - return true -} - -func compareBlobstorInfo(a, b []*control.BlobstorInfo) bool { - if len(a) != len(b) { - return false - } - for i := range a { - if a[i].Type != b[i].Type || - a[i].Path != b[i].Path { - return false - } - } - return true -} - -func generateListShardsResponseBody() *control.ListShardsResponse_Body { - body := new(control.ListShardsResponse_Body) - body.SetShards([]*control.ShardInfo{ - generateShardInfo(0), - generateShardInfo(1), - }) - - return body -} - -func TestSetShardModeRequest_Body_StableMarshal(t *testing.T) { - testStableMarshal(t, - generateSetShardModeRequestBody(), - new(control.SetShardModeRequest_Body), - func(m1, m2 protoMessage) bool { - return equalSetShardModeRequestBodies( - m1.(*control.SetShardModeRequest_Body), - m2.(*control.SetShardModeRequest_Body), - ) - }, - ) -} - -func generateSetShardModeRequestBody() *control.SetShardModeRequest_Body { - body := new(control.SetShardModeRequest_Body) - body.SetShardIDList([][]byte{{0, 1, 2, 3, 4}}) - body.SetMode(control.ShardMode_READ_WRITE) - - return body -} - -func equalSetShardModeRequestBodies(b1, b2 *control.SetShardModeRequest_Body) bool { - if b1.GetMode() != b2.GetMode() || len(b1.Shard_ID) != len(b2.Shard_ID) { - return false - } - - for i := range b1.Shard_ID { - if !bytes.Equal(b1.Shard_ID[i], b2.Shard_ID[i]) { - return false - } - } - - return true -} - -func TestSynchronizeTreeRequest_Body_StableMarshal(t *testing.T) { - testStableMarshal(t, - &control.SynchronizeTreeRequest_Body{ - ContainerId: []byte{1, 2, 3, 4, 5, 6, 7}, - TreeId: "someID", - Height: 42, - }, - new(control.SynchronizeTreeRequest_Body), - func(m1, m2 protoMessage) bool { - b1 := m1.(*control.SynchronizeTreeRequest_Body) - b2 := m2.(*control.SynchronizeTreeRequest_Body) - return bytes.Equal(b1.GetContainerId(), b2.GetContainerId()) && - b1.GetTreeId() == b2.GetTreeId() && - b1.GetHeight() == b2.GetHeight() - }, - ) -} diff --git a/pkg/services/control/types.go b/pkg/services/control/types.go deleted file mode 100644 index 94f681c557..0000000000 --- a/pkg/services/control/types.go +++ /dev/null @@ -1,118 +0,0 @@ -package control - -import ( - "google.golang.org/protobuf/encoding/protojson" -) - -// SetKey sets public key used for signing. -func (x *Signature) SetKey(v []byte) { - if x != nil { - x.Key = v - } -} - -// SetSign sets binary signature. -func (x *Signature) SetSign(v []byte) { - if x != nil { - x.Sign = v - } -} - -// SetKey sets key of the node attribute. -func (x *NodeInfo_Attribute) SetKey(v string) { - if x != nil { - x.Key = v - } -} - -// SetValue sets value of the node attribute. -func (x *NodeInfo_Attribute) SetValue(v string) { - if x != nil { - x.Value = v - } -} - -// SetParents sets parent keys. -func (x *NodeInfo_Attribute) SetParents(v []string) { - if x != nil { - x.Parents = v - } -} - -// SetPublicKey sets public key of the FrostFS node in a binary format. -func (x *NodeInfo) SetPublicKey(v []byte) { - if x != nil { - x.PublicKey = v - } -} - -// SetAddresses sets ways to connect to a node. -func (x *NodeInfo) SetAddresses(v []string) { - if x != nil { - x.Addresses = v - } -} - -// SetAttributes sets attributes of the FrostFS Storage Node. -func (x *NodeInfo) SetAttributes(v []*NodeInfo_Attribute) { - if x != nil { - x.Attributes = v - } -} - -// SetState sets state of the FrostFS node. -func (x *NodeInfo) SetState(v NetmapStatus) { - if x != nil { - x.State = v - } -} - -// SetEpoch sets revision number of the network map. -func (x *Netmap) SetEpoch(v uint64) { - if x != nil { - x.Epoch = v - } -} - -// SetNodes sets nodes presented in network. -func (x *Netmap) SetNodes(v []*NodeInfo) { - if x != nil { - x.Nodes = v - } -} - -func (x *Netmap) MarshalJSON() ([]byte, error) { - return protojson.MarshalOptions{ - EmitUnpopulated: true, - }.Marshal(x) -} - -// SetID sets identificator of the shard. -func (x *ShardInfo) SetID(v []byte) { - x.Shard_ID = v -} - -// SetMetabasePath sets path to shard's metabase. -func (x *ShardInfo) SetMetabasePath(v string) { - x.MetabasePath = v -} - -// SetWriteCachePath sets path to shard's write-cache. -func (x *ShardInfo) SetWriteCachePath(v string) { - x.WritecachePath = v -} - -// SetPiloramaPath sets path to shard's pilorama. -func (x *ShardInfo) SetPiloramaPath(v string) { - x.PiloramaPath = v -} - -// SetMode sets path to shard's work mode. -func (x *ShardInfo) SetMode(v ShardMode) { - x.Mode = v -} - -// SetErrorCount sets shard's error counter. -func (x *ShardInfo) SetErrorCount(count uint32) { - x.ErrorCount = count -} diff --git a/pkg/services/control/types.pb.go b/pkg/services/control/types.pb.go deleted file mode 100644 index 8587556944..0000000000 --- a/pkg/services/control/types.pb.go +++ /dev/null @@ -1,1011 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.33.0 -// protoc v4.25.0 -// source: pkg/services/control/types.proto - -package control - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Status of the storage node in the FrostFS network map. -type NetmapStatus int32 - -const ( - // Undefined status, default value. - NetmapStatus_STATUS_UNDEFINED NetmapStatus = 0 - // Node is online. - NetmapStatus_ONLINE NetmapStatus = 1 - // Node is offline. - NetmapStatus_OFFLINE NetmapStatus = 2 - // Node is maintained by the owner. - NetmapStatus_MAINTENANCE NetmapStatus = 3 -) - -// Enum value maps for NetmapStatus. -var ( - NetmapStatus_name = map[int32]string{ - 0: "STATUS_UNDEFINED", - 1: "ONLINE", - 2: "OFFLINE", - 3: "MAINTENANCE", - } - NetmapStatus_value = map[string]int32{ - "STATUS_UNDEFINED": 0, - "ONLINE": 1, - "OFFLINE": 2, - "MAINTENANCE": 3, - } -) - -func (x NetmapStatus) Enum() *NetmapStatus { - p := new(NetmapStatus) - *p = x - return p -} - -func (x NetmapStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (NetmapStatus) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_control_types_proto_enumTypes[0].Descriptor() -} - -func (NetmapStatus) Type() protoreflect.EnumType { - return &file_pkg_services_control_types_proto_enumTypes[0] -} - -func (x NetmapStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use NetmapStatus.Descriptor instead. -func (NetmapStatus) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{0} -} - -// Health status of the storage node application. -type HealthStatus int32 - -const ( - // Undefined status, default value. - HealthStatus_HEALTH_STATUS_UNDEFINED HealthStatus = 0 - // Storage node application is starting. - HealthStatus_STARTING HealthStatus = 1 - // Storage node application is started and serves all services. - HealthStatus_READY HealthStatus = 2 - // Storage node application is shutting down. - HealthStatus_SHUTTING_DOWN HealthStatus = 3 - // Storage node application is reconfiguring. - HealthStatus_RECONFIGURING HealthStatus = 4 -) - -// Enum value maps for HealthStatus. -var ( - HealthStatus_name = map[int32]string{ - 0: "HEALTH_STATUS_UNDEFINED", - 1: "STARTING", - 2: "READY", - 3: "SHUTTING_DOWN", - 4: "RECONFIGURING", - } - HealthStatus_value = map[string]int32{ - "HEALTH_STATUS_UNDEFINED": 0, - "STARTING": 1, - "READY": 2, - "SHUTTING_DOWN": 3, - "RECONFIGURING": 4, - } -) - -func (x HealthStatus) Enum() *HealthStatus { - p := new(HealthStatus) - *p = x - return p -} - -func (x HealthStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (HealthStatus) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_control_types_proto_enumTypes[1].Descriptor() -} - -func (HealthStatus) Type() protoreflect.EnumType { - return &file_pkg_services_control_types_proto_enumTypes[1] -} - -func (x HealthStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use HealthStatus.Descriptor instead. -func (HealthStatus) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{1} -} - -// Work mode of the shard. -type ShardMode int32 - -const ( - // Undefined mode, default value. - ShardMode_SHARD_MODE_UNDEFINED ShardMode = 0 - // Read-write. - ShardMode_READ_WRITE ShardMode = 1 - // Read-only. - ShardMode_READ_ONLY ShardMode = 2 - // Degraded. - ShardMode_DEGRADED ShardMode = 3 - // DegradedReadOnly. - ShardMode_DEGRADED_READ_ONLY ShardMode = 4 -) - -// Enum value maps for ShardMode. -var ( - ShardMode_name = map[int32]string{ - 0: "SHARD_MODE_UNDEFINED", - 1: "READ_WRITE", - 2: "READ_ONLY", - 3: "DEGRADED", - 4: "DEGRADED_READ_ONLY", - } - ShardMode_value = map[string]int32{ - "SHARD_MODE_UNDEFINED": 0, - "READ_WRITE": 1, - "READ_ONLY": 2, - "DEGRADED": 3, - "DEGRADED_READ_ONLY": 4, - } -) - -func (x ShardMode) Enum() *ShardMode { - p := new(ShardMode) - *p = x - return p -} - -func (x ShardMode) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ShardMode) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_control_types_proto_enumTypes[2].Descriptor() -} - -func (ShardMode) Type() protoreflect.EnumType { - return &file_pkg_services_control_types_proto_enumTypes[2] -} - -func (x ShardMode) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ShardMode.Descriptor instead. -func (ShardMode) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{2} -} - -type ChainTarget_TargetType int32 - -const ( - ChainTarget_UNDEFINED ChainTarget_TargetType = 0 - ChainTarget_NAMESPACE ChainTarget_TargetType = 1 - ChainTarget_CONTAINER ChainTarget_TargetType = 2 - ChainTarget_USER ChainTarget_TargetType = 3 - ChainTarget_GROUP ChainTarget_TargetType = 4 -) - -// Enum value maps for ChainTarget_TargetType. -var ( - ChainTarget_TargetType_name = map[int32]string{ - 0: "UNDEFINED", - 1: "NAMESPACE", - 2: "CONTAINER", - 3: "USER", - 4: "GROUP", - } - ChainTarget_TargetType_value = map[string]int32{ - "UNDEFINED": 0, - "NAMESPACE": 1, - "CONTAINER": 2, - "USER": 3, - "GROUP": 4, - } -) - -func (x ChainTarget_TargetType) Enum() *ChainTarget_TargetType { - p := new(ChainTarget_TargetType) - *p = x - return p -} - -func (x ChainTarget_TargetType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ChainTarget_TargetType) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_control_types_proto_enumTypes[3].Descriptor() -} - -func (ChainTarget_TargetType) Type() protoreflect.EnumType { - return &file_pkg_services_control_types_proto_enumTypes[3] -} - -func (x ChainTarget_TargetType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ChainTarget_TargetType.Descriptor instead. -func (ChainTarget_TargetType) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{5, 0} -} - -// Signature of some message. -type Signature struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Public key used for signing. - Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - // Binary signature. - Sign []byte `protobuf:"bytes,2,opt,name=sign,json=signature,proto3" json:"sign,omitempty"` -} - -func (x *Signature) Reset() { - *x = Signature{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Signature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Signature) ProtoMessage() {} - -func (x *Signature) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Signature.ProtoReflect.Descriptor instead. -func (*Signature) Descriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{0} -} - -func (x *Signature) GetKey() []byte { - if x != nil { - return x.Key - } - return nil -} - -func (x *Signature) GetSign() []byte { - if x != nil { - return x.Sign - } - return nil -} - -// FrostFS node description. -type NodeInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Public key of the FrostFS node in a binary format. - PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` - // Ways to connect to a node. - Addresses []string `protobuf:"bytes,2,rep,name=addresses,proto3" json:"addresses,omitempty"` - // Carries list of the FrostFS node attributes in a key-value form. Key name - // must be a node-unique valid UTF-8 string. Value can't be empty. NodeInfo - // structures with duplicated attribute names or attributes with empty values - // will be considered invalid. - Attributes []*NodeInfo_Attribute `protobuf:"bytes,3,rep,name=attributes,proto3" json:"attributes,omitempty"` - // Carries state of the FrostFS node. - State NetmapStatus `protobuf:"varint,4,opt,name=state,proto3,enum=control.NetmapStatus" json:"state,omitempty"` -} - -func (x *NodeInfo) Reset() { - *x = NodeInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NodeInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NodeInfo) ProtoMessage() {} - -func (x *NodeInfo) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NodeInfo.ProtoReflect.Descriptor instead. -func (*NodeInfo) Descriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{1} -} - -func (x *NodeInfo) GetPublicKey() []byte { - if x != nil { - return x.PublicKey - } - return nil -} - -func (x *NodeInfo) GetAddresses() []string { - if x != nil { - return x.Addresses - } - return nil -} - -func (x *NodeInfo) GetAttributes() []*NodeInfo_Attribute { - if x != nil { - return x.Attributes - } - return nil -} - -func (x *NodeInfo) GetState() NetmapStatus { - if x != nil { - return x.State - } - return NetmapStatus_STATUS_UNDEFINED -} - -// Network map structure. -type Netmap struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Network map revision number. - Epoch uint64 `protobuf:"varint,1,opt,name=epoch,proto3" json:"epoch,omitempty"` - // Nodes presented in network. - Nodes []*NodeInfo `protobuf:"bytes,2,rep,name=nodes,proto3" json:"nodes,omitempty"` -} - -func (x *Netmap) Reset() { - *x = Netmap{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Netmap) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Netmap) ProtoMessage() {} - -func (x *Netmap) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Netmap.ProtoReflect.Descriptor instead. -func (*Netmap) Descriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{2} -} - -func (x *Netmap) GetEpoch() uint64 { - if x != nil { - return x.Epoch - } - return 0 -} - -func (x *Netmap) GetNodes() []*NodeInfo { - if x != nil { - return x.Nodes - } - return nil -} - -// Shard description. -type ShardInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the shard. - Shard_ID []byte `protobuf:"bytes,1,opt,name=shard_ID,json=shardID,proto3" json:"shard_ID,omitempty"` - // Path to shard's metabase. - MetabasePath string `protobuf:"bytes,2,opt,name=metabase_path,json=metabasePath,proto3" json:"metabase_path,omitempty"` - // Shard's blobstor info. - Blobstor []*BlobstorInfo `protobuf:"bytes,3,rep,name=blobstor,proto3" json:"blobstor,omitempty"` - // Path to shard's write-cache, empty if disabled. - WritecachePath string `protobuf:"bytes,4,opt,name=writecache_path,json=writecachePath,proto3" json:"writecache_path,omitempty"` - // Work mode of the shard. - Mode ShardMode `protobuf:"varint,5,opt,name=mode,proto3,enum=control.ShardMode" json:"mode,omitempty"` - // Amount of errors occured. - ErrorCount uint32 `protobuf:"varint,6,opt,name=errorCount,proto3" json:"errorCount,omitempty"` - // Path to shard's pilorama storage. - PiloramaPath string `protobuf:"bytes,7,opt,name=pilorama_path,json=piloramaPath,proto3" json:"pilorama_path,omitempty"` -} - -func (x *ShardInfo) Reset() { - *x = ShardInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ShardInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ShardInfo) ProtoMessage() {} - -func (x *ShardInfo) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ShardInfo.ProtoReflect.Descriptor instead. -func (*ShardInfo) Descriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{3} -} - -func (x *ShardInfo) GetShard_ID() []byte { - if x != nil { - return x.Shard_ID - } - return nil -} - -func (x *ShardInfo) GetMetabasePath() string { - if x != nil { - return x.MetabasePath - } - return "" -} - -func (x *ShardInfo) GetBlobstor() []*BlobstorInfo { - if x != nil { - return x.Blobstor - } - return nil -} - -func (x *ShardInfo) GetWritecachePath() string { - if x != nil { - return x.WritecachePath - } - return "" -} - -func (x *ShardInfo) GetMode() ShardMode { - if x != nil { - return x.Mode - } - return ShardMode_SHARD_MODE_UNDEFINED -} - -func (x *ShardInfo) GetErrorCount() uint32 { - if x != nil { - return x.ErrorCount - } - return 0 -} - -func (x *ShardInfo) GetPiloramaPath() string { - if x != nil { - return x.PiloramaPath - } - return "" -} - -// Blobstor component description. -type BlobstorInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Path to the root. - Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` - // Component type. - Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` -} - -func (x *BlobstorInfo) Reset() { - *x = BlobstorInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *BlobstorInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlobstorInfo) ProtoMessage() {} - -func (x *BlobstorInfo) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use BlobstorInfo.ProtoReflect.Descriptor instead. -func (*BlobstorInfo) Descriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{4} -} - -func (x *BlobstorInfo) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *BlobstorInfo) GetType() string { - if x != nil { - return x.Type - } - return "" -} - -// ChainTarget is an object to which local overrides -// are applied. -type ChainTarget struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Type ChainTarget_TargetType `protobuf:"varint,1,opt,name=type,proto3,enum=control.ChainTarget_TargetType" json:"type,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` -} - -func (x *ChainTarget) Reset() { - *x = ChainTarget{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ChainTarget) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ChainTarget) ProtoMessage() {} - -func (x *ChainTarget) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ChainTarget.ProtoReflect.Descriptor instead. -func (*ChainTarget) Descriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{5} -} - -func (x *ChainTarget) GetType() ChainTarget_TargetType { - if x != nil { - return x.Type - } - return ChainTarget_UNDEFINED -} - -func (x *ChainTarget) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -// Administrator-defined Attributes of the FrostFS Storage Node. -// -// `Attribute` is a Key-Value metadata pair. Key name must be a valid UTF-8 -// string. Value can't be empty. -// -// Node's attributes are mostly used during Storage Policy evaluation to -// calculate object's placement and find a set of nodes satisfying policy -// requirements. There are some "well-known" node attributes common to all the -// Storage Nodes in the network and used implicitly with default values if not -// explicitly set: -// -// - Capacity \ -// Total available disk space in Gigabytes. -// - Price \ -// Price in GAS tokens for storing one GB of data during one Epoch. In node -// attributes it's a string presenting floating point number with comma or -// point delimiter for decimal part. In the Network Map it will be saved as -// 64-bit unsigned integer representing number of minimal token fractions. -// - Locode \ -// Node's geographic location in -// [UN/LOCODE](https://www.unece.org/cefact/codesfortrade/codes_index.html) -// format approximated to the nearest point defined in standard. -// - Country \ -// Country code in -// [ISO 3166-1_alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) -// format. Calculated automatically from `Locode` attribute -// - Region \ -// Country's administative subdivision where node is located. Calculated -// automatically from `Locode` attribute based on `SubDiv` field. Presented -// in [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) format. -// - City \ -// City, town, village or rural area name where node is located written -// without diacritics . Calculated automatically from `Locode` attribute. -// -// For detailed description of each well-known attribute please see the -// corresponding section in FrostFS Technical specification. -type NodeInfo_Attribute struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Key of the node attribute. - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - // Value of the node attribute. - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - // Parent keys, if any. For example for `City` it could be `Region` and - // `Country`. - Parents []string `protobuf:"bytes,3,rep,name=parents,proto3" json:"parents,omitempty"` -} - -func (x *NodeInfo_Attribute) Reset() { - *x = NodeInfo_Attribute{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_control_types_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *NodeInfo_Attribute) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NodeInfo_Attribute) ProtoMessage() {} - -func (x *NodeInfo_Attribute) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_control_types_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NodeInfo_Attribute.ProtoReflect.Descriptor instead. -func (*NodeInfo_Attribute) Descriptor() ([]byte, []int) { - return file_pkg_services_control_types_proto_rawDescGZIP(), []int{1, 0} -} - -func (x *NodeInfo_Attribute) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *NodeInfo_Attribute) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -func (x *NodeInfo_Attribute) GetParents() []string { - if x != nil { - return x.Parents - } - return nil -} - -var File_pkg_services_control_types_proto protoreflect.FileDescriptor - -var file_pkg_services_control_types_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x22, 0x36, 0x0a, 0x09, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x04, 0x73, 0x69, - 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x22, 0x80, 0x02, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, - 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x3b, 0x0a, - 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x4e, 0x6f, 0x64, 0x65, - 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x0a, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x2e, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x4d, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x47, 0x0a, 0x06, 0x4e, 0x65, 0x74, 0x6d, 0x61, 0x70, - 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x27, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, - 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x94, 0x02, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, - 0x08, 0x73, 0x68, 0x61, 0x72, 0x64, 0x5f, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x07, 0x73, 0x68, 0x61, 0x72, 0x64, 0x49, 0x44, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, - 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x31, 0x0a, - 0x08, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x74, - 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x74, 0x6f, 0x72, - 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x77, 0x72, 0x69, 0x74, 0x65, - 0x63, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x6f, 0x64, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x2e, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, - 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x75, 0x6e, - 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x69, 0x6c, 0x6f, 0x72, 0x61, 0x6d, 0x61, 0x5f, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x69, 0x6c, 0x6f, 0x72, 0x61, - 0x6d, 0x61, 0x50, 0x61, 0x74, 0x68, 0x22, 0x36, 0x0a, 0x0c, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x74, - 0x6f, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xa6, - 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x33, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x4e, 0x0a, 0x0a, 0x54, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x41, 0x4d, 0x45, 0x53, 0x50, 0x41, 0x43, - 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, - 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, - 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x04, 0x2a, 0x4e, 0x0a, 0x0c, 0x4e, 0x65, 0x74, 0x6d, 0x61, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, - 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, - 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x4d, 0x41, 0x49, 0x4e, 0x54, 0x45, - 0x4e, 0x41, 0x4e, 0x43, 0x45, 0x10, 0x03, 0x2a, 0x6a, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x17, 0x48, 0x45, 0x41, 0x4c, 0x54, - 0x48, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x54, 0x41, 0x52, 0x54, 0x49, 0x4e, 0x47, - 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x41, 0x44, 0x59, 0x10, 0x02, 0x12, 0x11, 0x0a, - 0x0d, 0x53, 0x48, 0x55, 0x54, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x44, 0x4f, 0x57, 0x4e, 0x10, 0x03, - 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x45, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x55, 0x52, 0x49, 0x4e, - 0x47, 0x10, 0x04, 0x2a, 0x6a, 0x0a, 0x09, 0x53, 0x68, 0x61, 0x72, 0x64, 0x4d, 0x6f, 0x64, 0x65, - 0x12, 0x18, 0x0a, 0x14, 0x53, 0x48, 0x41, 0x52, 0x44, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x55, - 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, - 0x41, 0x44, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, - 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x47, - 0x52, 0x41, 0x44, 0x45, 0x44, 0x10, 0x03, 0x12, 0x16, 0x0a, 0x12, 0x44, 0x45, 0x47, 0x52, 0x41, - 0x44, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x04, 0x42, - 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, - 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, - 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pkg_services_control_types_proto_rawDescOnce sync.Once - file_pkg_services_control_types_proto_rawDescData = file_pkg_services_control_types_proto_rawDesc -) - -func file_pkg_services_control_types_proto_rawDescGZIP() []byte { - file_pkg_services_control_types_proto_rawDescOnce.Do(func() { - file_pkg_services_control_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_control_types_proto_rawDescData) - }) - return file_pkg_services_control_types_proto_rawDescData -} - -var file_pkg_services_control_types_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_pkg_services_control_types_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_pkg_services_control_types_proto_goTypes = []interface{}{ - (NetmapStatus)(0), // 0: control.NetmapStatus - (HealthStatus)(0), // 1: control.HealthStatus - (ShardMode)(0), // 2: control.ShardMode - (ChainTarget_TargetType)(0), // 3: control.ChainTarget.TargetType - (*Signature)(nil), // 4: control.Signature - (*NodeInfo)(nil), // 5: control.NodeInfo - (*Netmap)(nil), // 6: control.Netmap - (*ShardInfo)(nil), // 7: control.ShardInfo - (*BlobstorInfo)(nil), // 8: control.BlobstorInfo - (*ChainTarget)(nil), // 9: control.ChainTarget - (*NodeInfo_Attribute)(nil), // 10: control.NodeInfo.Attribute -} -var file_pkg_services_control_types_proto_depIdxs = []int32{ - 10, // 0: control.NodeInfo.attributes:type_name -> control.NodeInfo.Attribute - 0, // 1: control.NodeInfo.state:type_name -> control.NetmapStatus - 5, // 2: control.Netmap.nodes:type_name -> control.NodeInfo - 8, // 3: control.ShardInfo.blobstor:type_name -> control.BlobstorInfo - 2, // 4: control.ShardInfo.mode:type_name -> control.ShardMode - 3, // 5: control.ChainTarget.type:type_name -> control.ChainTarget.TargetType - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name -} - -func init() { file_pkg_services_control_types_proto_init() } -func file_pkg_services_control_types_proto_init() { - if File_pkg_services_control_types_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pkg_services_control_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Signature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Netmap); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_types_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ShardInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_types_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*BlobstorInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_types_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainTarget); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_control_types_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NodeInfo_Attribute); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pkg_services_control_types_proto_rawDesc, - NumEnums: 4, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pkg_services_control_types_proto_goTypes, - DependencyIndexes: file_pkg_services_control_types_proto_depIdxs, - EnumInfos: file_pkg_services_control_types_proto_enumTypes, - MessageInfos: file_pkg_services_control_types_proto_msgTypes, - }.Build() - File_pkg_services_control_types_proto = out.File - file_pkg_services_control_types_proto_rawDesc = nil - file_pkg_services_control_types_proto_goTypes = nil - file_pkg_services_control_types_proto_depIdxs = nil -} diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index 858d85a1c7..9aff26a98b 100644 --- a/pkg/services/control/types_frostfs.pb.go +++ b/pkg/services/control/types_frostfs.pb.go @@ -2,7 +2,149 @@ package control -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import ( + json "encoding/json" + fmt "fmt" + pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + easyproto "github.com/VictoriaMetrics/easyproto" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" + strconv "strconv" +) + +type NetmapStatus int32 + +const ( + NetmapStatus_STATUS_UNDEFINED NetmapStatus = 0 + NetmapStatus_ONLINE NetmapStatus = 1 + NetmapStatus_OFFLINE NetmapStatus = 2 + NetmapStatus_MAINTENANCE NetmapStatus = 3 +) + +var ( + NetmapStatus_name = map[int32]string{ + 0: "STATUS_UNDEFINED", + 1: "ONLINE", + 2: "OFFLINE", + 3: "MAINTENANCE", + } + NetmapStatus_value = map[string]int32{ + "STATUS_UNDEFINED": 0, + "ONLINE": 1, + "OFFLINE": 2, + "MAINTENANCE": 3, + } +) + +func (x NetmapStatus) String() string { + if v, ok := NetmapStatus_name[int32(x)]; ok { + return v + } + return strconv.FormatInt(int64(x), 10) +} +func (x *NetmapStatus) FromString(s string) bool { + if v, ok := NetmapStatus_value[s]; ok { + *x = NetmapStatus(v) + return true + } + return false +} + +type HealthStatus int32 + +const ( + HealthStatus_HEALTH_STATUS_UNDEFINED HealthStatus = 0 + HealthStatus_STARTING HealthStatus = 1 + HealthStatus_READY HealthStatus = 2 + HealthStatus_SHUTTING_DOWN HealthStatus = 3 + HealthStatus_RECONFIGURING HealthStatus = 4 +) + +var ( + HealthStatus_name = map[int32]string{ + 0: "HEALTH_STATUS_UNDEFINED", + 1: "STARTING", + 2: "READY", + 3: "SHUTTING_DOWN", + 4: "RECONFIGURING", + } + HealthStatus_value = map[string]int32{ + "HEALTH_STATUS_UNDEFINED": 0, + "STARTING": 1, + "READY": 2, + "SHUTTING_DOWN": 3, + "RECONFIGURING": 4, + } +) + +func (x HealthStatus) String() string { + if v, ok := HealthStatus_name[int32(x)]; ok { + return v + } + return strconv.FormatInt(int64(x), 10) +} +func (x *HealthStatus) FromString(s string) bool { + if v, ok := HealthStatus_value[s]; ok { + *x = HealthStatus(v) + return true + } + return false +} + +type ShardMode int32 + +const ( + ShardMode_SHARD_MODE_UNDEFINED ShardMode = 0 + ShardMode_READ_WRITE ShardMode = 1 + ShardMode_READ_ONLY ShardMode = 2 + ShardMode_DEGRADED ShardMode = 3 + ShardMode_DEGRADED_READ_ONLY ShardMode = 4 +) + +var ( + ShardMode_name = map[int32]string{ + 0: "SHARD_MODE_UNDEFINED", + 1: "READ_WRITE", + 2: "READ_ONLY", + 3: "DEGRADED", + 4: "DEGRADED_READ_ONLY", + } + ShardMode_value = map[string]int32{ + "SHARD_MODE_UNDEFINED": 0, + "READ_WRITE": 1, + "READ_ONLY": 2, + "DEGRADED": 3, + "DEGRADED_READ_ONLY": 4, + } +) + +func (x ShardMode) String() string { + if v, ok := ShardMode_name[int32(x)]; ok { + return v + } + return strconv.FormatInt(int64(x), 10) +} +func (x *ShardMode) FromString(s string) bool { + if v, ok := ShardMode_value[s]; ok { + *x = ShardMode(v) + return true + } + return false +} + +type Signature struct { + Key []byte `json:"key"` + Sign []byte `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*Signature)(nil) + _ encoding.ProtoUnmarshaler = (*Signature)(nil) + _ json.Marshaler = (*Signature)(nil) + _ json.Unmarshaler = (*Signature)(nil) +) // StableSize returns the size of x in protobuf format. // @@ -16,27 +158,155 @@ func (x *Signature) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *Signature) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.Key) - offset += proto.BytesMarshal(2, buf[offset:], x.Sign) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *Signature) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *Signature) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Key) != 0 { + mm.AppendBytes(1, x.Key) + } + if len(x.Sign) != 0 { + mm.AppendBytes(2, x.Sign) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *Signature) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "Signature") + } + switch fc.FieldNum { + case 1: // Key + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Key") + } + x.Key = data + case 2: // Sign + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Sign") + } + x.Sign = data + } + } + return nil +} +func (x *Signature) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} +func (x *Signature) SetKey(v []byte) { + x.Key = v +} +func (x *Signature) GetSign() []byte { + if x != nil { + return x.Sign + } + return nil +} +func (x *Signature) SetSign(v []byte) { + x.Sign = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *Signature) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *Signature) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"key\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.Key) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + out.Base64Bytes(x.Sign) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *Signature) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *Signature) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "key": + { + var f []byte + f = in.Bytes() + x.Key = f + } + case "signature": + { + var f []byte + f = in.Bytes() + x.Sign = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type NodeInfo_Attribute struct { + Key string `json:"key"` + Value string `json:"value"` + Parents []string `json:"parents"` +} + +var ( + _ encoding.ProtoMarshaler = (*NodeInfo_Attribute)(nil) + _ encoding.ProtoUnmarshaler = (*NodeInfo_Attribute)(nil) + _ json.Marshaler = (*NodeInfo_Attribute)(nil) + _ json.Unmarshaler = (*NodeInfo_Attribute)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -50,28 +320,199 @@ func (x *NodeInfo_Attribute) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *NodeInfo_Attribute) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.StringMarshal(1, buf[offset:], x.Key) - offset += proto.StringMarshal(2, buf[offset:], x.Value) - offset += proto.RepeatedStringMarshal(3, buf[offset:], x.Parents) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *NodeInfo_Attribute) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *NodeInfo_Attribute) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Key) != 0 { + mm.AppendString(1, x.Key) + } + if len(x.Value) != 0 { + mm.AppendString(2, x.Value) + } + for j := range x.Parents { + mm.AppendString(3, x.Parents[j]) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *NodeInfo_Attribute) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "NodeInfo_Attribute") + } + switch fc.FieldNum { + case 1: // Key + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Key") + } + x.Key = data + case 2: // Value + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Value") + } + x.Value = data + case 3: // Parents + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Parents") + } + x.Parents = append(x.Parents, data) + } + } + return nil +} +func (x *NodeInfo_Attribute) GetKey() string { + if x != nil { + return x.Key + } + return "" +} +func (x *NodeInfo_Attribute) SetKey(v string) { + x.Key = v +} +func (x *NodeInfo_Attribute) GetValue() string { + if x != nil { + return x.Value + } + return "" +} +func (x *NodeInfo_Attribute) SetValue(v string) { + x.Value = v +} +func (x *NodeInfo_Attribute) GetParents() []string { + if x != nil { + return x.Parents + } + return nil +} +func (x *NodeInfo_Attribute) SetParents(v []string) { + x.Parents = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *NodeInfo_Attribute) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *NodeInfo_Attribute) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"key\":" + out.RawString(prefix[1:]) + out.String(x.Key) + } + { + const prefix string = ",\"value\":" + out.RawString(prefix) + out.String(x.Value) + } + { + const prefix string = ",\"parents\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Parents { + if i != 0 { + out.RawByte(',') + } + out.String(x.Parents[i]) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *NodeInfo_Attribute) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *NodeInfo_Attribute) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "key": + { + var f string + f = in.String() + x.Key = f + } + case "value": + { + var f string + f = in.String() + x.Value = f + } + case "parents": + { + var f string + var list []string + in.Delim('[') + for !in.IsDelim(']') { + f = in.String() + list = append(list, f) + in.WantComma() + } + x.Parents = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type NodeInfo struct { + PublicKey []byte `json:"publicKey"` + Addresses []string `json:"addresses"` + Attributes []*NodeInfo_Attribute `json:"attributes"` + State NetmapStatus `json:"state"` +} + +var ( + _ encoding.ProtoMarshaler = (*NodeInfo)(nil) + _ encoding.ProtoUnmarshaler = (*NodeInfo)(nil) + _ json.Marshaler = (*NodeInfo)(nil) + _ json.Unmarshaler = (*NodeInfo)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -88,31 +529,263 @@ func (x *NodeInfo) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *NodeInfo) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.PublicKey) - offset += proto.RepeatedStringMarshal(2, buf[offset:], x.Addresses) - for i := range x.Attributes { - offset += proto.NestedStructureMarshal(3, buf[offset:], x.Attributes[i]) - } - offset += proto.EnumMarshal(4, buf[offset:], int32(x.State)) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *NodeInfo) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *NodeInfo) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.PublicKey) != 0 { + mm.AppendBytes(1, x.PublicKey) + } + for j := range x.Addresses { + mm.AppendString(2, x.Addresses[j]) + } + for i := range x.Attributes { + if x.Attributes[i] != nil && x.Attributes[i].StableSize() != 0 { + x.Attributes[i].EmitProtobuf(mm.AppendMessage(3)) + } + } + if int32(x.State) != 0 { + mm.AppendInt32(4, int32(x.State)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *NodeInfo) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "NodeInfo") + } + switch fc.FieldNum { + case 1: // PublicKey + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "PublicKey") + } + x.PublicKey = data + case 2: // Addresses + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Addresses") + } + x.Addresses = append(x.Addresses, data) + case 3: // Attributes + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Attributes") + } + x.Attributes = append(x.Attributes, new(NodeInfo_Attribute)) + ff := x.Attributes[len(x.Attributes)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 4: // State + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "State") + } + x.State = NetmapStatus(data) + } + } + return nil +} +func (x *NodeInfo) GetPublicKey() []byte { + if x != nil { + return x.PublicKey + } + return nil +} +func (x *NodeInfo) SetPublicKey(v []byte) { + x.PublicKey = v +} +func (x *NodeInfo) GetAddresses() []string { + if x != nil { + return x.Addresses + } + return nil +} +func (x *NodeInfo) SetAddresses(v []string) { + x.Addresses = v +} +func (x *NodeInfo) GetAttributes() []*NodeInfo_Attribute { + if x != nil { + return x.Attributes + } + return nil +} +func (x *NodeInfo) SetAttributes(v []*NodeInfo_Attribute) { + x.Attributes = v +} +func (x *NodeInfo) GetState() NetmapStatus { + if x != nil { + return x.State + } + return 0 +} +func (x *NodeInfo) SetState(v NetmapStatus) { + x.State = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *NodeInfo) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *NodeInfo) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"publicKey\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.PublicKey) + } + { + const prefix string = ",\"addresses\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Addresses { + if i != 0 { + out.RawByte(',') + } + out.String(x.Addresses[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"attributes\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Attributes { + if i != 0 { + out.RawByte(',') + } + x.Attributes[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + { + const prefix string = ",\"state\":" + out.RawString(prefix) + out.Int32(int32(x.State)) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *NodeInfo) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *NodeInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "publicKey": + { + var f []byte + f = in.Bytes() + x.PublicKey = f + } + case "addresses": + { + var f string + var list []string + in.Delim('[') + for !in.IsDelim(']') { + f = in.String() + list = append(list, f) + in.WantComma() + } + x.Addresses = list + in.Delim(']') + } + case "attributes": + { + var f *NodeInfo_Attribute + var list []*NodeInfo_Attribute + in.Delim('[') + for !in.IsDelim(']') { + f = new(NodeInfo_Attribute) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Attributes = list + in.Delim(']') + } + case "state": + { + var f NetmapStatus + var parsedValue NetmapStatus + switch v := in.Interface().(type) { + case string: + if vv, ok := NetmapStatus_value[v]; ok { + parsedValue = NetmapStatus(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = NetmapStatus(vv) + case float64: + parsedValue = NetmapStatus(v) + } + f = parsedValue + x.State = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type Netmap struct { + Epoch uint64 `json:"epoch"` + Nodes []*NodeInfo `json:"nodes"` +} + +var ( + _ encoding.ProtoMarshaler = (*Netmap)(nil) + _ encoding.ProtoUnmarshaler = (*Netmap)(nil) + _ json.Marshaler = (*Netmap)(nil) + _ json.Unmarshaler = (*Netmap)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -127,29 +800,180 @@ func (x *Netmap) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *Netmap) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt64Marshal(1, buf[offset:], x.Epoch) - for i := range x.Nodes { - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Nodes[i]) - } - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *Netmap) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *Netmap) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Epoch != 0 { + mm.AppendUint64(1, x.Epoch) + } + for i := range x.Nodes { + if x.Nodes[i] != nil && x.Nodes[i].StableSize() != 0 { + x.Nodes[i].EmitProtobuf(mm.AppendMessage(2)) + } + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *Netmap) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "Netmap") + } + switch fc.FieldNum { + case 1: // Epoch + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Epoch") + } + x.Epoch = data + case 2: // Nodes + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Nodes") + } + x.Nodes = append(x.Nodes, new(NodeInfo)) + ff := x.Nodes[len(x.Nodes)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *Netmap) GetEpoch() uint64 { + if x != nil { + return x.Epoch + } + return 0 +} +func (x *Netmap) SetEpoch(v uint64) { + x.Epoch = v +} +func (x *Netmap) GetNodes() []*NodeInfo { + if x != nil { + return x.Nodes + } + return nil +} +func (x *Netmap) SetNodes(v []*NodeInfo) { + x.Nodes = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *Netmap) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *Netmap) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"epoch\":" + out.RawString(prefix[1:]) + out.Uint64(x.Epoch) + } + { + const prefix string = ",\"nodes\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Nodes { + if i != 0 { + out.RawByte(',') + } + x.Nodes[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *Netmap) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *Netmap) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "epoch": + { + var f uint64 + f = in.Uint64() + x.Epoch = f + } + case "nodes": + { + var f *NodeInfo + var list []*NodeInfo + in.Delim('[') + for !in.IsDelim(']') { + f = new(NodeInfo) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Nodes = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ShardInfo struct { + Shard_ID []byte `json:"shardID"` + MetabasePath string `json:"metabasePath"` + Blobstor []*BlobstorInfo `json:"blobstor"` + WritecachePath string `json:"writecachePath"` + Mode ShardMode `json:"mode"` + ErrorCount uint32 `json:"errorCount"` + PiloramaPath string `json:"piloramaPath"` +} + +var ( + _ encoding.ProtoMarshaler = (*ShardInfo)(nil) + _ encoding.ProtoUnmarshaler = (*ShardInfo)(nil) + _ json.Marshaler = (*ShardInfo)(nil) + _ json.Unmarshaler = (*ShardInfo)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -169,34 +993,336 @@ func (x *ShardInfo) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ShardInfo) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.Shard_ID) - offset += proto.StringMarshal(2, buf[offset:], x.MetabasePath) - for i := range x.Blobstor { - offset += proto.NestedStructureMarshal(3, buf[offset:], x.Blobstor[i]) - } - offset += proto.StringMarshal(4, buf[offset:], x.WritecachePath) - offset += proto.EnumMarshal(5, buf[offset:], int32(x.Mode)) - offset += proto.UInt32Marshal(6, buf[offset:], x.ErrorCount) - offset += proto.StringMarshal(7, buf[offset:], x.PiloramaPath) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ShardInfo) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ShardInfo) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Shard_ID) != 0 { + mm.AppendBytes(1, x.Shard_ID) + } + if len(x.MetabasePath) != 0 { + mm.AppendString(2, x.MetabasePath) + } + for i := range x.Blobstor { + if x.Blobstor[i] != nil && x.Blobstor[i].StableSize() != 0 { + x.Blobstor[i].EmitProtobuf(mm.AppendMessage(3)) + } + } + if len(x.WritecachePath) != 0 { + mm.AppendString(4, x.WritecachePath) + } + if int32(x.Mode) != 0 { + mm.AppendInt32(5, int32(x.Mode)) + } + if x.ErrorCount != 0 { + mm.AppendUint32(6, x.ErrorCount) + } + if len(x.PiloramaPath) != 0 { + mm.AppendString(7, x.PiloramaPath) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ShardInfo) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ShardInfo") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = data + case 2: // MetabasePath + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "MetabasePath") + } + x.MetabasePath = data + case 3: // Blobstor + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Blobstor") + } + x.Blobstor = append(x.Blobstor, new(BlobstorInfo)) + ff := x.Blobstor[len(x.Blobstor)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 4: // WritecachePath + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "WritecachePath") + } + x.WritecachePath = data + case 5: // Mode + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Mode") + } + x.Mode = ShardMode(data) + case 6: // ErrorCount + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ErrorCount") + } + x.ErrorCount = data + case 7: // PiloramaPath + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "PiloramaPath") + } + x.PiloramaPath = data + } + } + return nil +} +func (x *ShardInfo) GetShard_ID() []byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *ShardInfo) SetShard_ID(v []byte) { + x.Shard_ID = v +} +func (x *ShardInfo) GetMetabasePath() string { + if x != nil { + return x.MetabasePath + } + return "" +} +func (x *ShardInfo) SetMetabasePath(v string) { + x.MetabasePath = v +} +func (x *ShardInfo) GetBlobstor() []*BlobstorInfo { + if x != nil { + return x.Blobstor + } + return nil +} +func (x *ShardInfo) SetBlobstor(v []*BlobstorInfo) { + x.Blobstor = v +} +func (x *ShardInfo) GetWritecachePath() string { + if x != nil { + return x.WritecachePath + } + return "" +} +func (x *ShardInfo) SetWritecachePath(v string) { + x.WritecachePath = v +} +func (x *ShardInfo) GetMode() ShardMode { + if x != nil { + return x.Mode + } + return 0 +} +func (x *ShardInfo) SetMode(v ShardMode) { + x.Mode = v +} +func (x *ShardInfo) GetErrorCount() uint32 { + if x != nil { + return x.ErrorCount + } + return 0 +} +func (x *ShardInfo) SetErrorCount(v uint32) { + x.ErrorCount = v +} +func (x *ShardInfo) GetPiloramaPath() string { + if x != nil { + return x.PiloramaPath + } + return "" +} +func (x *ShardInfo) SetPiloramaPath(v string) { + x.PiloramaPath = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ShardInfo) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ShardInfo) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.Shard_ID) + } + { + const prefix string = ",\"metabasePath\":" + out.RawString(prefix) + out.String(x.MetabasePath) + } + { + const prefix string = ",\"blobstor\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Blobstor { + if i != 0 { + out.RawByte(',') + } + x.Blobstor[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + { + const prefix string = ",\"writecachePath\":" + out.RawString(prefix) + out.String(x.WritecachePath) + } + { + const prefix string = ",\"mode\":" + out.RawString(prefix) + out.Int32(int32(x.Mode)) + } + { + const prefix string = ",\"errorCount\":" + out.RawString(prefix) + out.Uint32(x.ErrorCount) + } + { + const prefix string = ",\"piloramaPath\":" + out.RawString(prefix) + out.String(x.PiloramaPath) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ShardInfo) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ShardInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + f = in.Bytes() + x.Shard_ID = f + } + case "metabasePath": + { + var f string + f = in.String() + x.MetabasePath = f + } + case "blobstor": + { + var f *BlobstorInfo + var list []*BlobstorInfo + in.Delim('[') + for !in.IsDelim(']') { + f = new(BlobstorInfo) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Blobstor = list + in.Delim(']') + } + case "writecachePath": + { + var f string + f = in.String() + x.WritecachePath = f + } + case "mode": + { + var f ShardMode + var parsedValue ShardMode + switch v := in.Interface().(type) { + case string: + if vv, ok := ShardMode_value[v]; ok { + parsedValue = ShardMode(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = ShardMode(vv) + case float64: + parsedValue = ShardMode(v) + } + f = parsedValue + x.Mode = f + } + case "errorCount": + { + var f uint32 + f = in.Uint32() + x.ErrorCount = f + } + case "piloramaPath": + { + var f string + f = in.String() + x.PiloramaPath = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type BlobstorInfo struct { + Path string `json:"path"` + Type string `json:"type"` +} + +var ( + _ encoding.ProtoMarshaler = (*BlobstorInfo)(nil) + _ encoding.ProtoUnmarshaler = (*BlobstorInfo)(nil) + _ json.Marshaler = (*BlobstorInfo)(nil) + _ json.Unmarshaler = (*BlobstorInfo)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -209,27 +1335,195 @@ func (x *BlobstorInfo) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *BlobstorInfo) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.StringMarshal(1, buf[offset:], x.Path) - offset += proto.StringMarshal(2, buf[offset:], x.Type) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *BlobstorInfo) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *BlobstorInfo) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Path) != 0 { + mm.AppendString(1, x.Path) + } + if len(x.Type) != 0 { + mm.AppendString(2, x.Type) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *BlobstorInfo) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "BlobstorInfo") + } + switch fc.FieldNum { + case 1: // Path + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Path") + } + x.Path = data + case 2: // Type + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Type") + } + x.Type = data + } + } + return nil +} +func (x *BlobstorInfo) GetPath() string { + if x != nil { + return x.Path + } + return "" +} +func (x *BlobstorInfo) SetPath(v string) { + x.Path = v +} +func (x *BlobstorInfo) GetType() string { + if x != nil { + return x.Type + } + return "" +} +func (x *BlobstorInfo) SetType(v string) { + x.Type = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *BlobstorInfo) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *BlobstorInfo) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"path\":" + out.RawString(prefix[1:]) + out.String(x.Path) + } + { + const prefix string = ",\"type\":" + out.RawString(prefix) + out.String(x.Type) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *BlobstorInfo) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *BlobstorInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "path": + { + var f string + f = in.String() + x.Path = f + } + case "type": + { + var f string + f = in.String() + x.Type = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ChainTarget_TargetType int32 + +const ( + ChainTarget_UNDEFINED ChainTarget_TargetType = 0 + ChainTarget_NAMESPACE ChainTarget_TargetType = 1 + ChainTarget_CONTAINER ChainTarget_TargetType = 2 + ChainTarget_USER ChainTarget_TargetType = 3 + ChainTarget_GROUP ChainTarget_TargetType = 4 +) + +var ( + ChainTarget_TargetType_name = map[int32]string{ + 0: "UNDEFINED", + 1: "NAMESPACE", + 2: "CONTAINER", + 3: "USER", + 4: "GROUP", + } + ChainTarget_TargetType_value = map[string]int32{ + "UNDEFINED": 0, + "NAMESPACE": 1, + "CONTAINER": 2, + "USER": 3, + "GROUP": 4, + } +) + +func (x ChainTarget_TargetType) String() string { + if v, ok := ChainTarget_TargetType_name[int32(x)]; ok { + return v + } + return strconv.FormatInt(int64(x), 10) +} +func (x *ChainTarget_TargetType) FromString(s string) bool { + if v, ok := ChainTarget_TargetType_value[s]; ok { + *x = ChainTarget_TargetType(v) + return true + } + return false +} + +type ChainTarget struct { + Type ChainTarget_TargetType `json:"type"` + Name string `json:"Name"` +} + +var ( + _ encoding.ProtoMarshaler = (*ChainTarget)(nil) + _ encoding.ProtoUnmarshaler = (*ChainTarget)(nil) + _ json.Marshaler = (*ChainTarget)(nil) + _ json.Unmarshaler = (*ChainTarget)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -242,23 +1536,154 @@ func (x *ChainTarget) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ChainTarget) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.EnumMarshal(1, buf[offset:], int32(x.Type)) - offset += proto.StringMarshal(2, buf[offset:], x.Name) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ChainTarget) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ChainTarget) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if int32(x.Type) != 0 { + mm.AppendInt32(1, int32(x.Type)) + } + if len(x.Name) != 0 { + mm.AppendString(2, x.Name) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ChainTarget) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ChainTarget") + } + switch fc.FieldNum { + case 1: // Type + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Type") + } + x.Type = ChainTarget_TargetType(data) + case 2: // Name + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Name") + } + x.Name = data + } + } + return nil +} +func (x *ChainTarget) GetType() ChainTarget_TargetType { + if x != nil { + return x.Type + } + return 0 +} +func (x *ChainTarget) SetType(v ChainTarget_TargetType) { + x.Type = v +} +func (x *ChainTarget) GetName() string { + if x != nil { + return x.Name + } + return "" +} +func (x *ChainTarget) SetName(v string) { + x.Name = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ChainTarget) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ChainTarget) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"type\":" + out.RawString(prefix[1:]) + out.Int32(int32(x.Type)) + } + { + const prefix string = ",\"Name\":" + out.RawString(prefix) + out.String(x.Name) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ChainTarget) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ChainTarget) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "type": + { + var f ChainTarget_TargetType + var parsedValue ChainTarget_TargetType + switch v := in.Interface().(type) { + case string: + if vv, ok := ChainTarget_TargetType_value[v]; ok { + parsedValue = ChainTarget_TargetType(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = ChainTarget_TargetType(vv) + case float64: + parsedValue = ChainTarget_TargetType(v) + } + f = parsedValue + x.Type = f + } + case "Name": + { + var f string + f = in.String() + x.Name = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } } diff --git a/pkg/services/control/types_test.go b/pkg/services/control/types_test.go deleted file mode 100644 index df0cdf141a..0000000000 --- a/pkg/services/control/types_test.go +++ /dev/null @@ -1,151 +0,0 @@ -package control_test - -import ( - "bytes" - "path/filepath" - "strconv" - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - "github.com/google/uuid" -) - -func TestNetmap_StableMarshal(t *testing.T) { - testStableMarshal(t, generateNetmap(), new(control.Netmap), func(m1, m2 protoMessage) bool { - return equalNetmaps(m1.(*control.Netmap), m2.(*control.Netmap)) - }) -} - -func generateNetmap() *control.Netmap { - nm := new(control.Netmap) - nm.SetEpoch(13) - - const nodeCount = 2 - - nodes := make([]*control.NodeInfo, 0, nodeCount) - - for i := 0; i < nodeCount; i++ { - n := new(control.NodeInfo) - n.SetPublicKey(testData(33)) - n.SetAddresses([]string{testString(), testString()}) - n.SetState(control.NetmapStatus_ONLINE) - - const attrCount = 2 - - attrs := make([]*control.NodeInfo_Attribute, 0, attrCount) - - for j := 0; j < attrCount; j++ { - a := new(control.NodeInfo_Attribute) - a.SetKey(testString()) - a.SetValue(testString()) - - const parentsCount = 2 - - parents := make([]string, 0, parentsCount) - - for k := 0; k < parentsCount; k++ { - parents = append(parents, testString()) - } - - a.SetParents(parents) - - attrs = append(attrs, a) - } - - n.SetAttributes(attrs) - - nodes = append(nodes, n) - } - - nm.SetNodes(nodes) - - return nm -} - -func equalNetmaps(nm1, nm2 *control.Netmap) bool { - if nm1.GetEpoch() != nm2.GetEpoch() { - return false - } - - n1, n2 := nm1.GetNodes(), nm2.GetNodes() - - if len(n1) != len(n2) { - return false - } - - for i := range n1 { - if !equalNodeInfos(n1[i], n2[i]) { - return false - } - } - - return true -} - -func equalNodeInfos(n1, n2 *control.NodeInfo) bool { - if !bytes.Equal(n1.GetPublicKey(), n2.GetPublicKey()) || - n1.GetState() != n2.GetState() { - return false - } - - na1, na2 := n1.GetAddresses(), n2.GetAddresses() - - if len(na1) != len(na2) { - return false - } - - for i := range na1 { - if na1[i] != na2[i] { - return false - } - } - - a1, a2 := n1.GetAttributes(), n2.GetAttributes() - - if len(a1) != len(a2) { - return false - } - - for i := range a1 { - if a1[i].GetKey() != a2[i].GetKey() || a1[i].GetValue() != a2[i].GetValue() { - return false - } - - p1, p2 := a1[i].GetParents(), a2[i].GetParents() - - if len(p1) != len(p2) { - return false - } - - for j := range p1 { - if p1[j] != p2[j] { - return false - } - } - } - - return true -} - -func generateShardInfo(id int) *control.ShardInfo { - si := new(control.ShardInfo) - - path := "/nice/dir/awesome/files/" + strconv.Itoa(id) - - uid, _ := uuid.NewRandom() - bin, _ := uid.MarshalBinary() - - si.SetID(bin) - si.SetMode(control.ShardMode_READ_WRITE) - si.SetMetabasePath(filepath.Join(path, "meta")) - si.Blobstor = []*control.BlobstorInfo{ - {Type: fstree.Type, Path: filepath.Join(path, "fstree")}, - {Type: blobovniczatree.Type, Path: filepath.Join(path, "blobtree")}, - } - si.SetWriteCachePath(filepath.Join(path, "writecache")) - si.SetPiloramaPath(filepath.Join(path, "pilorama")) - - return si -} diff --git a/pkg/services/tree/service.pb.go b/pkg/services/tree/service.pb.go deleted file mode 100644 index f439e3f282..0000000000 --- a/pkg/services/tree/service.pb.go +++ /dev/null @@ -1,3587 +0,0 @@ -//* -// Service for working with CRDT tree. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.33.0 -// protoc v4.25.0 -// source: pkg/services/tree/service.proto - -package tree - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type GetSubTreeRequest_Body_Order_Direction int32 - -const ( - GetSubTreeRequest_Body_Order_None GetSubTreeRequest_Body_Order_Direction = 0 - GetSubTreeRequest_Body_Order_Asc GetSubTreeRequest_Body_Order_Direction = 1 -) - -// Enum value maps for GetSubTreeRequest_Body_Order_Direction. -var ( - GetSubTreeRequest_Body_Order_Direction_name = map[int32]string{ - 0: "None", - 1: "Asc", - } - GetSubTreeRequest_Body_Order_Direction_value = map[string]int32{ - "None": 0, - "Asc": 1, - } -) - -func (x GetSubTreeRequest_Body_Order_Direction) Enum() *GetSubTreeRequest_Body_Order_Direction { - p := new(GetSubTreeRequest_Body_Order_Direction) - *p = x - return p -} - -func (x GetSubTreeRequest_Body_Order_Direction) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (GetSubTreeRequest_Body_Order_Direction) Descriptor() protoreflect.EnumDescriptor { - return file_pkg_services_tree_service_proto_enumTypes[0].Descriptor() -} - -func (GetSubTreeRequest_Body_Order_Direction) Type() protoreflect.EnumType { - return &file_pkg_services_tree_service_proto_enumTypes[0] -} - -func (x GetSubTreeRequest_Body_Order_Direction) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use GetSubTreeRequest_Body_Order_Direction.Descriptor instead. -func (GetSubTreeRequest_Body_Order_Direction) EnumDescriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{10, 0, 0, 0} -} - -type AddRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *AddRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *AddRequest) Reset() { - *x = AddRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddRequest) ProtoMessage() {} - -func (x *AddRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddRequest.ProtoReflect.Descriptor instead. -func (*AddRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{0} -} - -func (x *AddRequest) GetBody() *AddRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *AddRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type AddResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *AddResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *AddResponse) Reset() { - *x = AddResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddResponse) ProtoMessage() {} - -func (x *AddResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddResponse.ProtoReflect.Descriptor instead. -func (*AddResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{1} -} - -func (x *AddResponse) GetBody() *AddResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *AddResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type AddByPathRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *AddByPathRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *AddByPathRequest) Reset() { - *x = AddByPathRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddByPathRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddByPathRequest) ProtoMessage() {} - -func (x *AddByPathRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddByPathRequest.ProtoReflect.Descriptor instead. -func (*AddByPathRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{2} -} - -func (x *AddByPathRequest) GetBody() *AddByPathRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *AddByPathRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type AddByPathResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *AddByPathResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *AddByPathResponse) Reset() { - *x = AddByPathResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddByPathResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddByPathResponse) ProtoMessage() {} - -func (x *AddByPathResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddByPathResponse.ProtoReflect.Descriptor instead. -func (*AddByPathResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{3} -} - -func (x *AddByPathResponse) GetBody() *AddByPathResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *AddByPathResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *RemoveRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveRequest) Reset() { - *x = RemoveRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveRequest) ProtoMessage() {} - -func (x *RemoveRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveRequest.ProtoReflect.Descriptor instead. -func (*RemoveRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{4} -} - -func (x *RemoveRequest) GetBody() *RemoveRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type RemoveResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *RemoveResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *RemoveResponse) Reset() { - *x = RemoveResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveResponse) ProtoMessage() {} - -func (x *RemoveResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveResponse.ProtoReflect.Descriptor instead. -func (*RemoveResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{5} -} - -func (x *RemoveResponse) GetBody() *RemoveResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *RemoveResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type MoveRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *MoveRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *MoveRequest) Reset() { - *x = MoveRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MoveRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MoveRequest) ProtoMessage() {} - -func (x *MoveRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MoveRequest.ProtoReflect.Descriptor instead. -func (*MoveRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{6} -} - -func (x *MoveRequest) GetBody() *MoveRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *MoveRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type MoveResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *MoveResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *MoveResponse) Reset() { - *x = MoveResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MoveResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MoveResponse) ProtoMessage() {} - -func (x *MoveResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MoveResponse.ProtoReflect.Descriptor instead. -func (*MoveResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{7} -} - -func (x *MoveResponse) GetBody() *MoveResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *MoveResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type GetNodeByPathRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *GetNodeByPathRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetNodeByPathRequest) Reset() { - *x = GetNodeByPathRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNodeByPathRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNodeByPathRequest) ProtoMessage() {} - -func (x *GetNodeByPathRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNodeByPathRequest.ProtoReflect.Descriptor instead. -func (*GetNodeByPathRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{8} -} - -func (x *GetNodeByPathRequest) GetBody() *GetNodeByPathRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetNodeByPathRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type GetNodeByPathResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *GetNodeByPathResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetNodeByPathResponse) Reset() { - *x = GetNodeByPathResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNodeByPathResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNodeByPathResponse) ProtoMessage() {} - -func (x *GetNodeByPathResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNodeByPathResponse.ProtoReflect.Descriptor instead. -func (*GetNodeByPathResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{9} -} - -func (x *GetNodeByPathResponse) GetBody() *GetNodeByPathResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetNodeByPathResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type GetSubTreeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *GetSubTreeRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetSubTreeRequest) Reset() { - *x = GetSubTreeRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetSubTreeRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSubTreeRequest) ProtoMessage() {} - -func (x *GetSubTreeRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetSubTreeRequest.ProtoReflect.Descriptor instead. -func (*GetSubTreeRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{10} -} - -func (x *GetSubTreeRequest) GetBody() *GetSubTreeRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetSubTreeRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type GetSubTreeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *GetSubTreeResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetSubTreeResponse) Reset() { - *x = GetSubTreeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetSubTreeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSubTreeResponse) ProtoMessage() {} - -func (x *GetSubTreeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetSubTreeResponse.ProtoReflect.Descriptor instead. -func (*GetSubTreeResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{11} -} - -func (x *GetSubTreeResponse) GetBody() *GetSubTreeResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetSubTreeResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type TreeListRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *TreeListRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *TreeListRequest) Reset() { - *x = TreeListRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TreeListRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TreeListRequest) ProtoMessage() {} - -func (x *TreeListRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TreeListRequest.ProtoReflect.Descriptor instead. -func (*TreeListRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{12} -} - -func (x *TreeListRequest) GetBody() *TreeListRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *TreeListRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type TreeListResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *TreeListResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *TreeListResponse) Reset() { - *x = TreeListResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TreeListResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TreeListResponse) ProtoMessage() {} - -func (x *TreeListResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TreeListResponse.ProtoReflect.Descriptor instead. -func (*TreeListResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{13} -} - -func (x *TreeListResponse) GetBody() *TreeListResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *TreeListResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type ApplyRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *ApplyRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ApplyRequest) Reset() { - *x = ApplyRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApplyRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyRequest) ProtoMessage() {} - -func (x *ApplyRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApplyRequest.ProtoReflect.Descriptor instead. -func (*ApplyRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{14} -} - -func (x *ApplyRequest) GetBody() *ApplyRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ApplyRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type ApplyResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *ApplyResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *ApplyResponse) Reset() { - *x = ApplyResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApplyResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyResponse) ProtoMessage() {} - -func (x *ApplyResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApplyResponse.ProtoReflect.Descriptor instead. -func (*ApplyResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{15} -} - -func (x *ApplyResponse) GetBody() *ApplyResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *ApplyResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type GetOpLogRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *GetOpLogRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetOpLogRequest) Reset() { - *x = GetOpLogRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOpLogRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOpLogRequest) ProtoMessage() {} - -func (x *GetOpLogRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOpLogRequest.ProtoReflect.Descriptor instead. -func (*GetOpLogRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{16} -} - -func (x *GetOpLogRequest) GetBody() *GetOpLogRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetOpLogRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type GetOpLogResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *GetOpLogResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *GetOpLogResponse) Reset() { - *x = GetOpLogResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOpLogResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOpLogResponse) ProtoMessage() {} - -func (x *GetOpLogResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOpLogResponse.ProtoReflect.Descriptor instead. -func (*GetOpLogResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{17} -} - -func (x *GetOpLogResponse) GetBody() *GetOpLogResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *GetOpLogResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type HealthcheckResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Response body. - Body *HealthcheckResponse_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Response signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *HealthcheckResponse) Reset() { - *x = HealthcheckResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthcheckResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthcheckResponse) ProtoMessage() {} - -func (x *HealthcheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[18] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthcheckResponse.ProtoReflect.Descriptor instead. -func (*HealthcheckResponse) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{18} -} - -func (x *HealthcheckResponse) GetBody() *HealthcheckResponse_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *HealthcheckResponse) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type HealthcheckRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Request body. - Body *HealthcheckRequest_Body `protobuf:"bytes,1,opt,name=body,proto3" json:"body,omitempty"` - // Request signature. - Signature *Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` -} - -func (x *HealthcheckRequest) Reset() { - *x = HealthcheckRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthcheckRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthcheckRequest) ProtoMessage() {} - -func (x *HealthcheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[19] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthcheckRequest.ProtoReflect.Descriptor instead. -func (*HealthcheckRequest) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{19} -} - -func (x *HealthcheckRequest) GetBody() *HealthcheckRequest_Body { - if x != nil { - return x.Body - } - return nil -} - -func (x *HealthcheckRequest) GetSignature() *Signature { - if x != nil { - return x.Signature - } - return nil -} - -type AddRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // The name of the tree. - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // ID of the parent to attach node to. - ParentId uint64 `protobuf:"varint,3,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` - // Key-Value pairs with meta information. - Meta []*KeyValue `protobuf:"bytes,4,rep,name=meta,proto3" json:"meta,omitempty"` - // Bearer token in V2 format. - BearerToken []byte `protobuf:"bytes,5,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` -} - -func (x *AddRequest_Body) Reset() { - *x = AddRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddRequest_Body) ProtoMessage() {} - -func (x *AddRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[20] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddRequest_Body.ProtoReflect.Descriptor instead. -func (*AddRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{0, 0} -} - -func (x *AddRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *AddRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *AddRequest_Body) GetParentId() uint64 { - if x != nil { - return x.ParentId - } - return 0 -} - -func (x *AddRequest_Body) GetMeta() []*KeyValue { - if x != nil { - return x.Meta - } - return nil -} - -func (x *AddRequest_Body) GetBearerToken() []byte { - if x != nil { - return x.BearerToken - } - return nil -} - -type AddResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the created node. - NodeId uint64 `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` -} - -func (x *AddResponse_Body) Reset() { - *x = AddResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddResponse_Body) ProtoMessage() {} - -func (x *AddResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[21] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddResponse_Body.ProtoReflect.Descriptor instead. -func (*AddResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{1, 0} -} - -func (x *AddResponse_Body) GetNodeId() uint64 { - if x != nil { - return x.NodeId - } - return 0 -} - -type AddByPathRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // The name of the tree. - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // Attribute to build path with. Default: "FileName". - PathAttribute string `protobuf:"bytes,3,opt,name=path_attribute,json=pathAttribute,proto3" json:"path_attribute,omitempty"` - // List of path components. - Path []string `protobuf:"bytes,4,rep,name=path,proto3" json:"path,omitempty"` - // Node meta-information. - Meta []*KeyValue `protobuf:"bytes,5,rep,name=meta,proto3" json:"meta,omitempty"` - // Bearer token in V2 format. - BearerToken []byte `protobuf:"bytes,6,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` -} - -func (x *AddByPathRequest_Body) Reset() { - *x = AddByPathRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddByPathRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddByPathRequest_Body) ProtoMessage() {} - -func (x *AddByPathRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[22] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddByPathRequest_Body.ProtoReflect.Descriptor instead. -func (*AddByPathRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{2, 0} -} - -func (x *AddByPathRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *AddByPathRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *AddByPathRequest_Body) GetPathAttribute() string { - if x != nil { - return x.PathAttribute - } - return "" -} - -func (x *AddByPathRequest_Body) GetPath() []string { - if x != nil { - return x.Path - } - return nil -} - -func (x *AddByPathRequest_Body) GetMeta() []*KeyValue { - if x != nil { - return x.Meta - } - return nil -} - -func (x *AddByPathRequest_Body) GetBearerToken() []byte { - if x != nil { - return x.BearerToken - } - return nil -} - -type AddByPathResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of all created nodes. The first one is the leaf. - Nodes []uint64 `protobuf:"varint,1,rep,packed,name=nodes,proto3" json:"nodes,omitempty"` - // ID of the parent node where new nodes were attached. - ParentId uint64 `protobuf:"varint,2,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` -} - -func (x *AddByPathResponse_Body) Reset() { - *x = AddByPathResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddByPathResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddByPathResponse_Body) ProtoMessage() {} - -func (x *AddByPathResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AddByPathResponse_Body.ProtoReflect.Descriptor instead. -func (*AddByPathResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{3, 0} -} - -func (x *AddByPathResponse_Body) GetNodes() []uint64 { - if x != nil { - return x.Nodes - } - return nil -} - -func (x *AddByPathResponse_Body) GetParentId() uint64 { - if x != nil { - return x.ParentId - } - return 0 -} - -type RemoveRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // The name of the tree. - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // ID of the node to remove. - NodeId uint64 `protobuf:"varint,3,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` - // Bearer token in V2 format. - BearerToken []byte `protobuf:"bytes,4,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` -} - -func (x *RemoveRequest_Body) Reset() { - *x = RemoveRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveRequest_Body) ProtoMessage() {} - -func (x *RemoveRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveRequest_Body.ProtoReflect.Descriptor instead. -func (*RemoveRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{4, 0} -} - -func (x *RemoveRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *RemoveRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *RemoveRequest_Body) GetNodeId() uint64 { - if x != nil { - return x.NodeId - } - return 0 -} - -func (x *RemoveRequest_Body) GetBearerToken() []byte { - if x != nil { - return x.BearerToken - } - return nil -} - -type RemoveResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *RemoveResponse_Body) Reset() { - *x = RemoveResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveResponse_Body) ProtoMessage() {} - -func (x *RemoveResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoveResponse_Body.ProtoReflect.Descriptor instead. -func (*RemoveResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{5, 0} -} - -type MoveRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // TODO import neo.fs.v2.refs.ContainerID directly. - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // The name of the tree. - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // ID of the new parent. - ParentId uint64 `protobuf:"varint,3,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` - // ID of the node to move. - NodeId uint64 `protobuf:"varint,4,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` - // Node meta-information. - Meta []*KeyValue `protobuf:"bytes,5,rep,name=meta,proto3" json:"meta,omitempty"` - // Bearer token in V2 format. - BearerToken []byte `protobuf:"bytes,6,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` -} - -func (x *MoveRequest_Body) Reset() { - *x = MoveRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MoveRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MoveRequest_Body) ProtoMessage() {} - -func (x *MoveRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[26] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MoveRequest_Body.ProtoReflect.Descriptor instead. -func (*MoveRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{6, 0} -} - -func (x *MoveRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *MoveRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *MoveRequest_Body) GetParentId() uint64 { - if x != nil { - return x.ParentId - } - return 0 -} - -func (x *MoveRequest_Body) GetNodeId() uint64 { - if x != nil { - return x.NodeId - } - return 0 -} - -func (x *MoveRequest_Body) GetMeta() []*KeyValue { - if x != nil { - return x.Meta - } - return nil -} - -func (x *MoveRequest_Body) GetBearerToken() []byte { - if x != nil { - return x.BearerToken - } - return nil -} - -type MoveResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *MoveResponse_Body) Reset() { - *x = MoveResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *MoveResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MoveResponse_Body) ProtoMessage() {} - -func (x *MoveResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[27] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MoveResponse_Body.ProtoReflect.Descriptor instead. -func (*MoveResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{7, 0} -} - -type GetNodeByPathRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // The name of the tree. - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // Attribute to build path with. Default: "FileName". - PathAttribute string `protobuf:"bytes,3,opt,name=path_attribute,json=pathAttribute,proto3" json:"path_attribute,omitempty"` - // List of path components. - Path []string `protobuf:"bytes,4,rep,name=path,proto3" json:"path,omitempty"` - // List of attributes to include in response. - Attributes []string `protobuf:"bytes,5,rep,name=attributes,proto3" json:"attributes,omitempty"` - // Flag to return only the latest version of node. - LatestOnly bool `protobuf:"varint,6,opt,name=latest_only,json=latestOnly,proto3" json:"latest_only,omitempty"` - // Flag to return all stored attributes. - AllAttributes bool `protobuf:"varint,7,opt,name=all_attributes,json=allAttributes,proto3" json:"all_attributes,omitempty"` - // Bearer token in V2 format. - BearerToken []byte `protobuf:"bytes,8,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` -} - -func (x *GetNodeByPathRequest_Body) Reset() { - *x = GetNodeByPathRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNodeByPathRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNodeByPathRequest_Body) ProtoMessage() {} - -func (x *GetNodeByPathRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[28] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNodeByPathRequest_Body.ProtoReflect.Descriptor instead. -func (*GetNodeByPathRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{8, 0} -} - -func (x *GetNodeByPathRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *GetNodeByPathRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *GetNodeByPathRequest_Body) GetPathAttribute() string { - if x != nil { - return x.PathAttribute - } - return "" -} - -func (x *GetNodeByPathRequest_Body) GetPath() []string { - if x != nil { - return x.Path - } - return nil -} - -func (x *GetNodeByPathRequest_Body) GetAttributes() []string { - if x != nil { - return x.Attributes - } - return nil -} - -func (x *GetNodeByPathRequest_Body) GetLatestOnly() bool { - if x != nil { - return x.LatestOnly - } - return false -} - -func (x *GetNodeByPathRequest_Body) GetAllAttributes() bool { - if x != nil { - return x.AllAttributes - } - return false -} - -func (x *GetNodeByPathRequest_Body) GetBearerToken() []byte { - if x != nil { - return x.BearerToken - } - return nil -} - -// Information about a single tree node. -type GetNodeByPathResponse_Info struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Node ID. - NodeId uint64 `protobuf:"varint,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` - // Timestamp of the last operation with the node. - Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - // Node meta-information. - Meta []*KeyValue `protobuf:"bytes,3,rep,name=meta,proto3" json:"meta,omitempty"` - // Parent ID. - ParentId uint64 `protobuf:"varint,4,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` -} - -func (x *GetNodeByPathResponse_Info) Reset() { - *x = GetNodeByPathResponse_Info{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNodeByPathResponse_Info) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNodeByPathResponse_Info) ProtoMessage() {} - -func (x *GetNodeByPathResponse_Info) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[29] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNodeByPathResponse_Info.ProtoReflect.Descriptor instead. -func (*GetNodeByPathResponse_Info) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{9, 0} -} - -func (x *GetNodeByPathResponse_Info) GetNodeId() uint64 { - if x != nil { - return x.NodeId - } - return 0 -} - -func (x *GetNodeByPathResponse_Info) GetTimestamp() uint64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *GetNodeByPathResponse_Info) GetMeta() []*KeyValue { - if x != nil { - return x.Meta - } - return nil -} - -func (x *GetNodeByPathResponse_Info) GetParentId() uint64 { - if x != nil { - return x.ParentId - } - return 0 -} - -type GetNodeByPathResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of nodes stored by path. - Nodes []*GetNodeByPathResponse_Info `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` -} - -func (x *GetNodeByPathResponse_Body) Reset() { - *x = GetNodeByPathResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNodeByPathResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNodeByPathResponse_Body) ProtoMessage() {} - -func (x *GetNodeByPathResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNodeByPathResponse_Body.ProtoReflect.Descriptor instead. -func (*GetNodeByPathResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{9, 1} -} - -func (x *GetNodeByPathResponse_Body) GetNodes() []*GetNodeByPathResponse_Info { - if x != nil { - return x.Nodes - } - return nil -} - -type GetSubTreeRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // The name of the tree. - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // IDs of the root nodes of a subtree forest. - RootId []uint64 `protobuf:"varint,3,rep,name=root_id,json=rootId,proto3" json:"root_id,omitempty"` - // Optional depth of the traversal. Zero means return only root. - // Maximum depth is 10. - Depth uint32 `protobuf:"varint,4,opt,name=depth,proto3" json:"depth,omitempty"` - // Bearer token in V2 format. - BearerToken []byte `protobuf:"bytes,5,opt,name=bearer_token,json=bearerToken,proto3" json:"bearer_token,omitempty"` - // Result ordering. - OrderBy *GetSubTreeRequest_Body_Order `protobuf:"bytes,6,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"` -} - -func (x *GetSubTreeRequest_Body) Reset() { - *x = GetSubTreeRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetSubTreeRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSubTreeRequest_Body) ProtoMessage() {} - -func (x *GetSubTreeRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetSubTreeRequest_Body.ProtoReflect.Descriptor instead. -func (*GetSubTreeRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{10, 0} -} - -func (x *GetSubTreeRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *GetSubTreeRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *GetSubTreeRequest_Body) GetRootId() []uint64 { - if x != nil { - return x.RootId - } - return nil -} - -func (x *GetSubTreeRequest_Body) GetDepth() uint32 { - if x != nil { - return x.Depth - } - return 0 -} - -func (x *GetSubTreeRequest_Body) GetBearerToken() []byte { - if x != nil { - return x.BearerToken - } - return nil -} - -func (x *GetSubTreeRequest_Body) GetOrderBy() *GetSubTreeRequest_Body_Order { - if x != nil { - return x.OrderBy - } - return nil -} - -type GetSubTreeRequest_Body_Order struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Direction GetSubTreeRequest_Body_Order_Direction `protobuf:"varint,1,opt,name=direction,proto3,enum=tree.GetSubTreeRequest_Body_Order_Direction" json:"direction,omitempty"` -} - -func (x *GetSubTreeRequest_Body_Order) Reset() { - *x = GetSubTreeRequest_Body_Order{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetSubTreeRequest_Body_Order) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSubTreeRequest_Body_Order) ProtoMessage() {} - -func (x *GetSubTreeRequest_Body_Order) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[32] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetSubTreeRequest_Body_Order.ProtoReflect.Descriptor instead. -func (*GetSubTreeRequest_Body_Order) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{10, 0, 0} -} - -func (x *GetSubTreeRequest_Body_Order) GetDirection() GetSubTreeRequest_Body_Order_Direction { - if x != nil { - return x.Direction - } - return GetSubTreeRequest_Body_Order_None -} - -type GetSubTreeResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the node. - NodeId []uint64 `protobuf:"varint,1,rep,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` - // ID of the parent. - ParentId []uint64 `protobuf:"varint,2,rep,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` - // Time node was first added to a tree. - Timestamp []uint64 `protobuf:"varint,3,rep,name=timestamp,proto3" json:"timestamp,omitempty"` - // Node meta-information. - Meta []*KeyValue `protobuf:"bytes,4,rep,name=meta,proto3" json:"meta,omitempty"` -} - -func (x *GetSubTreeResponse_Body) Reset() { - *x = GetSubTreeResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetSubTreeResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSubTreeResponse_Body) ProtoMessage() {} - -func (x *GetSubTreeResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[33] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetSubTreeResponse_Body.ProtoReflect.Descriptor instead. -func (*GetSubTreeResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{11, 0} -} - -func (x *GetSubTreeResponse_Body) GetNodeId() []uint64 { - if x != nil { - return x.NodeId - } - return nil -} - -func (x *GetSubTreeResponse_Body) GetParentId() []uint64 { - if x != nil { - return x.ParentId - } - return nil -} - -func (x *GetSubTreeResponse_Body) GetTimestamp() []uint64 { - if x != nil { - return x.Timestamp - } - return nil -} - -func (x *GetSubTreeResponse_Body) GetMeta() []*KeyValue { - if x != nil { - return x.Meta - } - return nil -} - -type TreeListRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` -} - -func (x *TreeListRequest_Body) Reset() { - *x = TreeListRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TreeListRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TreeListRequest_Body) ProtoMessage() {} - -func (x *TreeListRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[34] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TreeListRequest_Body.ProtoReflect.Descriptor instead. -func (*TreeListRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{12, 0} -} - -func (x *TreeListRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -type TreeListResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Tree IDs. - Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` -} - -func (x *TreeListResponse_Body) Reset() { - *x = TreeListResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[35] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *TreeListResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TreeListResponse_Body) ProtoMessage() {} - -func (x *TreeListResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[35] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use TreeListResponse_Body.ProtoReflect.Descriptor instead. -func (*TreeListResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{13, 0} -} - -func (x *TreeListResponse_Body) GetIds() []string { - if x != nil { - return x.Ids - } - return nil -} - -type ApplyRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // The name of the tree. - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // Operation to be applied. - Operation *LogMove `protobuf:"bytes,3,opt,name=operation,proto3" json:"operation,omitempty"` -} - -func (x *ApplyRequest_Body) Reset() { - *x = ApplyRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[36] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApplyRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyRequest_Body) ProtoMessage() {} - -func (x *ApplyRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[36] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApplyRequest_Body.ProtoReflect.Descriptor instead. -func (*ApplyRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{14, 0} -} - -func (x *ApplyRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *ApplyRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *ApplyRequest_Body) GetOperation() *LogMove { - if x != nil { - return x.Operation - } - return nil -} - -type ApplyResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ApplyResponse_Body) Reset() { - *x = ApplyResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[37] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ApplyResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ApplyResponse_Body) ProtoMessage() {} - -func (x *ApplyResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[37] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ApplyResponse_Body.ProtoReflect.Descriptor instead. -func (*ApplyResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{15, 0} -} - -type GetOpLogRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Container ID in V2 format. - ContainerId []byte `protobuf:"bytes,1,opt,name=container_id,json=containerId,proto3" json:"container_id,omitempty"` - // The name of the tree. - TreeId string `protobuf:"bytes,2,opt,name=tree_id,json=treeId,proto3" json:"tree_id,omitempty"` - // Starting height to return logs from. - Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` - // Amount of operations to return. - Count uint64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"` -} - -func (x *GetOpLogRequest_Body) Reset() { - *x = GetOpLogRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[38] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOpLogRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOpLogRequest_Body) ProtoMessage() {} - -func (x *GetOpLogRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[38] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOpLogRequest_Body.ProtoReflect.Descriptor instead. -func (*GetOpLogRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{16, 0} -} - -func (x *GetOpLogRequest_Body) GetContainerId() []byte { - if x != nil { - return x.ContainerId - } - return nil -} - -func (x *GetOpLogRequest_Body) GetTreeId() string { - if x != nil { - return x.TreeId - } - return "" -} - -func (x *GetOpLogRequest_Body) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *GetOpLogRequest_Body) GetCount() uint64 { - if x != nil { - return x.Count - } - return 0 -} - -type GetOpLogResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Operation on a tree. - Operation *LogMove `protobuf:"bytes,1,opt,name=operation,proto3" json:"operation,omitempty"` -} - -func (x *GetOpLogResponse_Body) Reset() { - *x = GetOpLogResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[39] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetOpLogResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetOpLogResponse_Body) ProtoMessage() {} - -func (x *GetOpLogResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[39] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetOpLogResponse_Body.ProtoReflect.Descriptor instead. -func (*GetOpLogResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{17, 0} -} - -func (x *GetOpLogResponse_Body) GetOperation() *LogMove { - if x != nil { - return x.Operation - } - return nil -} - -type HealthcheckResponse_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *HealthcheckResponse_Body) Reset() { - *x = HealthcheckResponse_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[40] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthcheckResponse_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthcheckResponse_Body) ProtoMessage() {} - -func (x *HealthcheckResponse_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[40] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthcheckResponse_Body.ProtoReflect.Descriptor instead. -func (*HealthcheckResponse_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{18, 0} -} - -type HealthcheckRequest_Body struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *HealthcheckRequest_Body) Reset() { - *x = HealthcheckRequest_Body{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_service_proto_msgTypes[41] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthcheckRequest_Body) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthcheckRequest_Body) ProtoMessage() {} - -func (x *HealthcheckRequest_Body) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_service_proto_msgTypes[41] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthcheckRequest_Body.ProtoReflect.Descriptor instead. -func (*HealthcheckRequest_Body) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_service_proto_rawDescGZIP(), []int{19, 0} -} - -var File_pkg_services_tree_service_proto protoreflect.FileDescriptor - -var file_pkg_services_tree_service_proto_rawDesc = []byte{ - 0x0a, 0x1f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, - 0x72, 0x65, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x04, 0x74, 0x72, 0x65, 0x65, 0x1a, 0x1d, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8f, 0x02, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, - 0xa6, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, - 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, - 0x65, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x0e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, - 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x89, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x1a, 0x1f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x6e, - 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, - 0x64, 0x65, 0x49, 0x64, 0x22, 0xb9, 0x02, 0x0a, 0x10, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, - 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, - 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, - 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, - 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xc4, 0x01, 0x0a, 0x04, 0x42, 0x6f, - 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x25, - 0x0a, 0x0e, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, - 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, - 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, - 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x22, 0xaf, 0x01, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x42, - 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, - 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x39, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52, 0x05, - 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x49, 0x64, 0x22, 0xec, 0x01, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x7e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, - 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, - 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x21, - 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x22, 0x76, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xaa, 0x02, 0x0a, 0x0b, 0x4d, 0x6f, - 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4d, - 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, - 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x1a, 0xbf, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, - 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, - 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, - 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6d, - 0x65, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, - 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x72, 0x0a, 0x0c, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4d, 0x6f, 0x76, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x85, 0x03, 0x0a, 0x14, 0x47, - 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x33, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, - 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, - 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x88, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, - 0x70, 0x61, 0x74, 0x68, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x74, 0x68, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x6c, 0x61, 0x74, 0x65, 0x73, - 0x74, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x6c, 0x61, - 0x74, 0x65, 0x73, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x5f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, - 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x22, 0xbc, 0x02, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, - 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x04, - 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x72, 0x65, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x7e, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, - 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, - 0x6d, 0x65, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x1a, 0x3e, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x22, 0xc3, 0x03, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, - 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0xcc, 0x02, 0x0a, 0x04, 0x42, 0x6f, 0x64, - 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, - 0x07, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x02, - 0x10, 0x00, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, - 0x70, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x64, 0x65, 0x70, 0x74, 0x68, - 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x65, 0x61, 0x72, 0x65, 0x72, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x12, 0x3d, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x42, 0x79, 0x1a, 0x73, 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x09, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x2e, 0x4f, 0x72, 0x64, - 0x65, 0x72, 0x2e, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1e, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x07, - 0x0a, 0x03, 0x41, 0x73, 0x63, 0x10, 0x01, 0x22, 0x83, 0x02, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, - 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, - 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x8a, 0x01, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1b, 0x0a, 0x07, 0x6e, 0x6f, 0x64, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x42, 0x02, 0x10, 0x00, 0x52, 0x06, - 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x04, 0x42, 0x02, 0x10, 0x00, 0x52, 0x08, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x04, 0x42, 0x02, 0x10, 0x00, 0x52, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x22, 0x0a, 0x04, 0x6d, 0x65, 0x74, - 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4b, - 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0x9b, 0x01, - 0x0a, 0x0f, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x29, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, - 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x10, - 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x1a, 0x18, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x22, 0xdb, 0x01, 0x0a, 0x0c, 0x41, - 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, - 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, - 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, - 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x6f, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, - 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x09, 0x6f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x09, 0x6f, - 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x74, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, - 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, 0x6f, 0x64, - 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, - 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, - 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x22, 0xe2, - 0x01, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x1a, 0x70, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, - 0x74, 0x72, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, - 0x72, 0x65, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, - 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x22, 0xa7, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, - 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, - 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x33, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x12, 0x2b, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4c, 0x6f, 0x67, 0x4d, 0x6f, - 0x76, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x80, 0x01, - 0x0a, 0x13, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, - 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x22, 0x7e, 0x0a, 0x12, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x42, - 0x6f, 0x64, 0x79, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x2d, 0x0a, 0x09, 0x73, 0x69, 0x67, - 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, - 0x72, 0x65, 0x65, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x1a, 0x06, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, - 0x32, 0xd6, 0x04, 0x0a, 0x0b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x2a, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x12, 0x10, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, - 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x74, 0x72, 0x65, 0x65, - 0x2e, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x09, - 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x74, 0x72, 0x65, 0x65, - 0x2e, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x42, 0x79, 0x50, 0x61, - 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x74, 0x72, 0x65, 0x65, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2d, 0x0a, 0x04, 0x4d, 0x6f, 0x76, 0x65, 0x12, 0x11, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x4d, - 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x74, 0x72, 0x65, - 0x65, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x48, - 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x1a, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, - 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x74, 0x72, - 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x42, 0x79, 0x50, 0x61, 0x74, 0x68, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x12, 0x17, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, - 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x54, 0x72, 0x65, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x39, 0x0a, 0x08, 0x54, - 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, - 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x12, - 0x12, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4f, - 0x70, 0x4c, 0x6f, 0x67, 0x12, 0x15, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, - 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x72, - 0x65, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x12, 0x18, 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x74, 0x72, 0x65, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, - 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, - 0x2e, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, - 0x75, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, - 0x66, 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_pkg_services_tree_service_proto_rawDescOnce sync.Once - file_pkg_services_tree_service_proto_rawDescData = file_pkg_services_tree_service_proto_rawDesc -) - -func file_pkg_services_tree_service_proto_rawDescGZIP() []byte { - file_pkg_services_tree_service_proto_rawDescOnce.Do(func() { - file_pkg_services_tree_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_tree_service_proto_rawDescData) - }) - return file_pkg_services_tree_service_proto_rawDescData -} - -var file_pkg_services_tree_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_pkg_services_tree_service_proto_msgTypes = make([]protoimpl.MessageInfo, 42) -var file_pkg_services_tree_service_proto_goTypes = []interface{}{ - (GetSubTreeRequest_Body_Order_Direction)(0), // 0: tree.GetSubTreeRequest.Body.Order.Direction - (*AddRequest)(nil), // 1: tree.AddRequest - (*AddResponse)(nil), // 2: tree.AddResponse - (*AddByPathRequest)(nil), // 3: tree.AddByPathRequest - (*AddByPathResponse)(nil), // 4: tree.AddByPathResponse - (*RemoveRequest)(nil), // 5: tree.RemoveRequest - (*RemoveResponse)(nil), // 6: tree.RemoveResponse - (*MoveRequest)(nil), // 7: tree.MoveRequest - (*MoveResponse)(nil), // 8: tree.MoveResponse - (*GetNodeByPathRequest)(nil), // 9: tree.GetNodeByPathRequest - (*GetNodeByPathResponse)(nil), // 10: tree.GetNodeByPathResponse - (*GetSubTreeRequest)(nil), // 11: tree.GetSubTreeRequest - (*GetSubTreeResponse)(nil), // 12: tree.GetSubTreeResponse - (*TreeListRequest)(nil), // 13: tree.TreeListRequest - (*TreeListResponse)(nil), // 14: tree.TreeListResponse - (*ApplyRequest)(nil), // 15: tree.ApplyRequest - (*ApplyResponse)(nil), // 16: tree.ApplyResponse - (*GetOpLogRequest)(nil), // 17: tree.GetOpLogRequest - (*GetOpLogResponse)(nil), // 18: tree.GetOpLogResponse - (*HealthcheckResponse)(nil), // 19: tree.HealthcheckResponse - (*HealthcheckRequest)(nil), // 20: tree.HealthcheckRequest - (*AddRequest_Body)(nil), // 21: tree.AddRequest.Body - (*AddResponse_Body)(nil), // 22: tree.AddResponse.Body - (*AddByPathRequest_Body)(nil), // 23: tree.AddByPathRequest.Body - (*AddByPathResponse_Body)(nil), // 24: tree.AddByPathResponse.Body - (*RemoveRequest_Body)(nil), // 25: tree.RemoveRequest.Body - (*RemoveResponse_Body)(nil), // 26: tree.RemoveResponse.Body - (*MoveRequest_Body)(nil), // 27: tree.MoveRequest.Body - (*MoveResponse_Body)(nil), // 28: tree.MoveResponse.Body - (*GetNodeByPathRequest_Body)(nil), // 29: tree.GetNodeByPathRequest.Body - (*GetNodeByPathResponse_Info)(nil), // 30: tree.GetNodeByPathResponse.Info - (*GetNodeByPathResponse_Body)(nil), // 31: tree.GetNodeByPathResponse.Body - (*GetSubTreeRequest_Body)(nil), // 32: tree.GetSubTreeRequest.Body - (*GetSubTreeRequest_Body_Order)(nil), // 33: tree.GetSubTreeRequest.Body.Order - (*GetSubTreeResponse_Body)(nil), // 34: tree.GetSubTreeResponse.Body - (*TreeListRequest_Body)(nil), // 35: tree.TreeListRequest.Body - (*TreeListResponse_Body)(nil), // 36: tree.TreeListResponse.Body - (*ApplyRequest_Body)(nil), // 37: tree.ApplyRequest.Body - (*ApplyResponse_Body)(nil), // 38: tree.ApplyResponse.Body - (*GetOpLogRequest_Body)(nil), // 39: tree.GetOpLogRequest.Body - (*GetOpLogResponse_Body)(nil), // 40: tree.GetOpLogResponse.Body - (*HealthcheckResponse_Body)(nil), // 41: tree.HealthcheckResponse.Body - (*HealthcheckRequest_Body)(nil), // 42: tree.HealthcheckRequest.Body - (*Signature)(nil), // 43: tree.Signature - (*KeyValue)(nil), // 44: tree.KeyValue - (*LogMove)(nil), // 45: tree.LogMove -} -var file_pkg_services_tree_service_proto_depIdxs = []int32{ - 21, // 0: tree.AddRequest.body:type_name -> tree.AddRequest.Body - 43, // 1: tree.AddRequest.signature:type_name -> tree.Signature - 22, // 2: tree.AddResponse.body:type_name -> tree.AddResponse.Body - 43, // 3: tree.AddResponse.signature:type_name -> tree.Signature - 23, // 4: tree.AddByPathRequest.body:type_name -> tree.AddByPathRequest.Body - 43, // 5: tree.AddByPathRequest.signature:type_name -> tree.Signature - 24, // 6: tree.AddByPathResponse.body:type_name -> tree.AddByPathResponse.Body - 43, // 7: tree.AddByPathResponse.signature:type_name -> tree.Signature - 25, // 8: tree.RemoveRequest.body:type_name -> tree.RemoveRequest.Body - 43, // 9: tree.RemoveRequest.signature:type_name -> tree.Signature - 26, // 10: tree.RemoveResponse.body:type_name -> tree.RemoveResponse.Body - 43, // 11: tree.RemoveResponse.signature:type_name -> tree.Signature - 27, // 12: tree.MoveRequest.body:type_name -> tree.MoveRequest.Body - 43, // 13: tree.MoveRequest.signature:type_name -> tree.Signature - 28, // 14: tree.MoveResponse.body:type_name -> tree.MoveResponse.Body - 43, // 15: tree.MoveResponse.signature:type_name -> tree.Signature - 29, // 16: tree.GetNodeByPathRequest.body:type_name -> tree.GetNodeByPathRequest.Body - 43, // 17: tree.GetNodeByPathRequest.signature:type_name -> tree.Signature - 31, // 18: tree.GetNodeByPathResponse.body:type_name -> tree.GetNodeByPathResponse.Body - 43, // 19: tree.GetNodeByPathResponse.signature:type_name -> tree.Signature - 32, // 20: tree.GetSubTreeRequest.body:type_name -> tree.GetSubTreeRequest.Body - 43, // 21: tree.GetSubTreeRequest.signature:type_name -> tree.Signature - 34, // 22: tree.GetSubTreeResponse.body:type_name -> tree.GetSubTreeResponse.Body - 43, // 23: tree.GetSubTreeResponse.signature:type_name -> tree.Signature - 35, // 24: tree.TreeListRequest.body:type_name -> tree.TreeListRequest.Body - 43, // 25: tree.TreeListRequest.signature:type_name -> tree.Signature - 36, // 26: tree.TreeListResponse.body:type_name -> tree.TreeListResponse.Body - 43, // 27: tree.TreeListResponse.signature:type_name -> tree.Signature - 37, // 28: tree.ApplyRequest.body:type_name -> tree.ApplyRequest.Body - 43, // 29: tree.ApplyRequest.signature:type_name -> tree.Signature - 38, // 30: tree.ApplyResponse.body:type_name -> tree.ApplyResponse.Body - 43, // 31: tree.ApplyResponse.signature:type_name -> tree.Signature - 39, // 32: tree.GetOpLogRequest.body:type_name -> tree.GetOpLogRequest.Body - 43, // 33: tree.GetOpLogRequest.signature:type_name -> tree.Signature - 40, // 34: tree.GetOpLogResponse.body:type_name -> tree.GetOpLogResponse.Body - 43, // 35: tree.GetOpLogResponse.signature:type_name -> tree.Signature - 41, // 36: tree.HealthcheckResponse.body:type_name -> tree.HealthcheckResponse.Body - 43, // 37: tree.HealthcheckResponse.signature:type_name -> tree.Signature - 42, // 38: tree.HealthcheckRequest.body:type_name -> tree.HealthcheckRequest.Body - 43, // 39: tree.HealthcheckRequest.signature:type_name -> tree.Signature - 44, // 40: tree.AddRequest.Body.meta:type_name -> tree.KeyValue - 44, // 41: tree.AddByPathRequest.Body.meta:type_name -> tree.KeyValue - 44, // 42: tree.MoveRequest.Body.meta:type_name -> tree.KeyValue - 44, // 43: tree.GetNodeByPathResponse.Info.meta:type_name -> tree.KeyValue - 30, // 44: tree.GetNodeByPathResponse.Body.nodes:type_name -> tree.GetNodeByPathResponse.Info - 33, // 45: tree.GetSubTreeRequest.Body.order_by:type_name -> tree.GetSubTreeRequest.Body.Order - 0, // 46: tree.GetSubTreeRequest.Body.Order.direction:type_name -> tree.GetSubTreeRequest.Body.Order.Direction - 44, // 47: tree.GetSubTreeResponse.Body.meta:type_name -> tree.KeyValue - 45, // 48: tree.ApplyRequest.Body.operation:type_name -> tree.LogMove - 45, // 49: tree.GetOpLogResponse.Body.operation:type_name -> tree.LogMove - 1, // 50: tree.TreeService.Add:input_type -> tree.AddRequest - 3, // 51: tree.TreeService.AddByPath:input_type -> tree.AddByPathRequest - 5, // 52: tree.TreeService.Remove:input_type -> tree.RemoveRequest - 7, // 53: tree.TreeService.Move:input_type -> tree.MoveRequest - 9, // 54: tree.TreeService.GetNodeByPath:input_type -> tree.GetNodeByPathRequest - 11, // 55: tree.TreeService.GetSubTree:input_type -> tree.GetSubTreeRequest - 13, // 56: tree.TreeService.TreeList:input_type -> tree.TreeListRequest - 15, // 57: tree.TreeService.Apply:input_type -> tree.ApplyRequest - 17, // 58: tree.TreeService.GetOpLog:input_type -> tree.GetOpLogRequest - 20, // 59: tree.TreeService.Healthcheck:input_type -> tree.HealthcheckRequest - 2, // 60: tree.TreeService.Add:output_type -> tree.AddResponse - 4, // 61: tree.TreeService.AddByPath:output_type -> tree.AddByPathResponse - 6, // 62: tree.TreeService.Remove:output_type -> tree.RemoveResponse - 8, // 63: tree.TreeService.Move:output_type -> tree.MoveResponse - 10, // 64: tree.TreeService.GetNodeByPath:output_type -> tree.GetNodeByPathResponse - 12, // 65: tree.TreeService.GetSubTree:output_type -> tree.GetSubTreeResponse - 14, // 66: tree.TreeService.TreeList:output_type -> tree.TreeListResponse - 16, // 67: tree.TreeService.Apply:output_type -> tree.ApplyResponse - 18, // 68: tree.TreeService.GetOpLog:output_type -> tree.GetOpLogResponse - 19, // 69: tree.TreeService.Healthcheck:output_type -> tree.HealthcheckResponse - 60, // [60:70] is the sub-list for method output_type - 50, // [50:60] is the sub-list for method input_type - 50, // [50:50] is the sub-list for extension type_name - 50, // [50:50] is the sub-list for extension extendee - 0, // [0:50] is the sub-list for field type_name -} - -func init() { file_pkg_services_tree_service_proto_init() } -func file_pkg_services_tree_service_proto_init() { - if File_pkg_services_tree_service_proto != nil { - return - } - file_pkg_services_tree_types_proto_init() - if !protoimpl.UnsafeEnabled { - file_pkg_services_tree_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddByPathRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddByPathResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MoveRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MoveResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNodeByPathRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNodeByPathResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSubTreeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSubTreeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TreeListRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TreeListResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOpLogRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOpLogResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthcheckResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthcheckRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddByPathRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddByPathResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MoveRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*MoveResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNodeByPathRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNodeByPathResponse_Info); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNodeByPathResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSubTreeRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSubTreeRequest_Body_Order); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSubTreeResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TreeListRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TreeListResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ApplyResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOpLogRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetOpLogResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthcheckResponse_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_service_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthcheckRequest_Body); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pkg_services_tree_service_proto_rawDesc, - NumEnums: 1, - NumMessages: 42, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_pkg_services_tree_service_proto_goTypes, - DependencyIndexes: file_pkg_services_tree_service_proto_depIdxs, - EnumInfos: file_pkg_services_tree_service_proto_enumTypes, - MessageInfos: file_pkg_services_tree_service_proto_msgTypes, - }.Build() - File_pkg_services_tree_service_proto = out.File - file_pkg_services_tree_service_proto_rawDesc = nil - file_pkg_services_tree_service_proto_goTypes = nil - file_pkg_services_tree_service_proto_depIdxs = nil -} diff --git a/pkg/services/tree/service_frostfs.pb.go b/pkg/services/tree/service_frostfs.pb.go index 1a49c5c0c1..c4d44253d6 100644 --- a/pkg/services/tree/service_frostfs.pb.go +++ b/pkg/services/tree/service_frostfs.pb.go @@ -3,11 +3,32 @@ package tree import ( - binary "encoding/binary" + json "encoding/json" + fmt "fmt" + pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + easyproto "github.com/VictoriaMetrics/easyproto" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" protowire "google.golang.org/protobuf/encoding/protowire" + strconv "strconv" ) -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +type AddRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + ParentId uint64 `json:"parentId"` + Meta []*KeyValue `json:"meta"` + BearerToken []byte `json:"bearerToken"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*AddRequest_Body)(nil) + _ json.Marshaler = (*AddRequest_Body)(nil) + _ json.Unmarshaler = (*AddRequest_Body)(nil) +) // StableSize returns the size of x in protobuf format. // @@ -26,32 +47,262 @@ func (x *AddRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.UInt64Marshal(3, buf[offset:], x.ParentId) - for i := range x.Meta { - offset += proto.NestedStructureMarshal(4, buf[offset:], x.Meta[i]) - } - offset += proto.BytesMarshal(5, buf[offset:], x.BearerToken) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + if x.ParentId != 0 { + mm.AppendUint64(3, x.ParentId) + } + for i := range x.Meta { + if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + x.Meta[i].EmitProtobuf(mm.AppendMessage(4)) + } + } + if len(x.BearerToken) != 0 { + mm.AppendBytes(5, x.BearerToken) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // ParentId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ParentId") + } + x.ParentId = data + case 4: // Meta + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Meta") + } + x.Meta = append(x.Meta, new(KeyValue)) + ff := x.Meta[len(x.Meta)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 5: // BearerToken + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "BearerToken") + } + x.BearerToken = data + } + } + return nil +} +func (x *AddRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *AddRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *AddRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *AddRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *AddRequest_Body) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} +func (x *AddRequest_Body) SetParentId(v uint64) { + x.ParentId = v +} +func (x *AddRequest_Body) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} +func (x *AddRequest_Body) SetMeta(v []*KeyValue) { + x.Meta = v +} +func (x *AddRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} +func (x *AddRequest_Body) SetBearerToken(v []byte) { + x.BearerToken = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"parentId\":" + out.RawString(prefix) + out.Uint64(x.ParentId) + } + { + const prefix string = ",\"meta\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Meta { + if i != 0 { + out.RawByte(',') + } + x.Meta[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + { + const prefix string = ",\"bearerToken\":" + out.RawString(prefix) + out.Base64Bytes(x.BearerToken) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "parentId": + { + var f uint64 + f = in.Uint64() + x.ParentId = f + } + case "meta": + { + var f *KeyValue + var list []*KeyValue + in.Delim('[') + for !in.IsDelim(']') { + f = new(KeyValue) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Meta = list + in.Delim(']') + } + case "bearerToken": + { + var f []byte + f = in.Bytes() + x.BearerToken = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddRequest struct { + Body *AddRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddRequest)(nil) + _ encoding.ProtoUnmarshaler = (*AddRequest)(nil) + _ json.Marshaler = (*AddRequest)(nil) + _ json.Unmarshaler = (*AddRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -64,27 +315,6 @@ func (x *AddRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -100,13 +330,164 @@ func (x *AddRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *AddRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *AddRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(AddRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *AddRequest) GetBody() *AddRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *AddRequest) SetBody(v *AddRequest_Body) { + x.Body = v +} +func (x *AddRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *AddRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *AddRequest_Body + f = new(AddRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddResponse_Body struct { + NodeId uint64 `json:"nodeId"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*AddResponse_Body)(nil) + _ json.Marshaler = (*AddResponse_Body)(nil) + _ json.Unmarshaler = (*AddResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -118,26 +499,125 @@ func (x *AddResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt64Marshal(1, buf[offset:], x.NodeId) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.NodeId != 0 { + mm.AppendUint64(1, x.NodeId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddResponse_Body") + } + switch fc.FieldNum { + case 1: // NodeId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "NodeId") + } + x.NodeId = data + } + } + return nil +} +func (x *AddResponse_Body) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} +func (x *AddResponse_Body) SetNodeId(v uint64) { + x.NodeId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"nodeId\":" + out.RawString(prefix[1:]) + out.Uint64(x.NodeId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "nodeId": + { + var f uint64 + f = in.Uint64() + x.NodeId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddResponse struct { + Body *AddResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddResponse)(nil) + _ encoding.ProtoUnmarshaler = (*AddResponse)(nil) + _ json.Marshaler = (*AddResponse)(nil) + _ json.Unmarshaler = (*AddResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -150,27 +630,6 @@ func (x *AddResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -186,13 +645,169 @@ func (x *AddResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *AddResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *AddResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(AddResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *AddResponse) GetBody() *AddResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *AddResponse) SetBody(v *AddResponse_Body) { + x.Body = v +} +func (x *AddResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *AddResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *AddResponse_Body + f = new(AddResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddByPathRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + PathAttribute string `json:"pathAttribute"` + Path []string `json:"path"` + Meta []*KeyValue `json:"meta"` + BearerToken []byte `json:"bearerToken"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddByPathRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*AddByPathRequest_Body)(nil) + _ json.Marshaler = (*AddByPathRequest_Body)(nil) + _ json.Unmarshaler = (*AddByPathRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -211,33 +826,305 @@ func (x *AddByPathRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddByPathRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.StringMarshal(3, buf[offset:], x.PathAttribute) - offset += proto.RepeatedStringMarshal(4, buf[offset:], x.Path) - for i := range x.Meta { - offset += proto.NestedStructureMarshal(5, buf[offset:], x.Meta[i]) - } - offset += proto.BytesMarshal(6, buf[offset:], x.BearerToken) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddByPathRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddByPathRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + if len(x.PathAttribute) != 0 { + mm.AppendString(3, x.PathAttribute) + } + for j := range x.Path { + mm.AppendString(4, x.Path[j]) + } + for i := range x.Meta { + if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + x.Meta[i].EmitProtobuf(mm.AppendMessage(5)) + } + } + if len(x.BearerToken) != 0 { + mm.AppendBytes(6, x.BearerToken) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddByPathRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddByPathRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // PathAttribute + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "PathAttribute") + } + x.PathAttribute = data + case 4: // Path + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Path") + } + x.Path = append(x.Path, data) + case 5: // Meta + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Meta") + } + x.Meta = append(x.Meta, new(KeyValue)) + ff := x.Meta[len(x.Meta)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 6: // BearerToken + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "BearerToken") + } + x.BearerToken = data + } + } + return nil +} +func (x *AddByPathRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *AddByPathRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *AddByPathRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *AddByPathRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *AddByPathRequest_Body) GetPathAttribute() string { + if x != nil { + return x.PathAttribute + } + return "" +} +func (x *AddByPathRequest_Body) SetPathAttribute(v string) { + x.PathAttribute = v +} +func (x *AddByPathRequest_Body) GetPath() []string { + if x != nil { + return x.Path + } + return nil +} +func (x *AddByPathRequest_Body) SetPath(v []string) { + x.Path = v +} +func (x *AddByPathRequest_Body) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} +func (x *AddByPathRequest_Body) SetMeta(v []*KeyValue) { + x.Meta = v +} +func (x *AddByPathRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} +func (x *AddByPathRequest_Body) SetBearerToken(v []byte) { + x.BearerToken = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddByPathRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddByPathRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"pathAttribute\":" + out.RawString(prefix) + out.String(x.PathAttribute) + } + { + const prefix string = ",\"path\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Path { + if i != 0 { + out.RawByte(',') + } + out.String(x.Path[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"meta\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Meta { + if i != 0 { + out.RawByte(',') + } + x.Meta[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + { + const prefix string = ",\"bearerToken\":" + out.RawString(prefix) + out.Base64Bytes(x.BearerToken) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddByPathRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddByPathRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "pathAttribute": + { + var f string + f = in.String() + x.PathAttribute = f + } + case "path": + { + var f string + var list []string + in.Delim('[') + for !in.IsDelim(']') { + f = in.String() + list = append(list, f) + in.WantComma() + } + x.Path = list + in.Delim(']') + } + case "meta": + { + var f *KeyValue + var list []*KeyValue + in.Delim('[') + for !in.IsDelim(']') { + f = new(KeyValue) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Meta = list + in.Delim(']') + } + case "bearerToken": + { + var f []byte + f = in.Bytes() + x.BearerToken = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddByPathRequest struct { + Body *AddByPathRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddByPathRequest)(nil) + _ encoding.ProtoUnmarshaler = (*AddByPathRequest)(nil) + _ json.Marshaler = (*AddByPathRequest)(nil) + _ json.Unmarshaler = (*AddByPathRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -250,27 +1137,6 @@ func (x *AddByPathRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddByPathRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -286,13 +1152,165 @@ func (x *AddByPathRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *AddByPathRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *AddByPathRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddByPathRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddByPathRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddByPathRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddByPathRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(AddByPathRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *AddByPathRequest) GetBody() *AddByPathRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *AddByPathRequest) SetBody(v *AddByPathRequest_Body) { + x.Body = v +} +func (x *AddByPathRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *AddByPathRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddByPathRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddByPathRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddByPathRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddByPathRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *AddByPathRequest_Body + f = new(AddByPathRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddByPathResponse_Body struct { + Nodes []uint64 `json:"nodes"` + ParentId uint64 `json:"parentId"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddByPathResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*AddByPathResponse_Body)(nil) + _ json.Marshaler = (*AddByPathResponse_Body)(nil) + _ json.Unmarshaler = (*AddByPathResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -307,27 +1325,168 @@ func (x *AddByPathResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddByPathResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedUInt64Marshal(1, buf[offset:], x.Nodes) - offset += proto.UInt64Marshal(2, buf[offset:], x.ParentId) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddByPathResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddByPathResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Nodes) != 0 { + mm.AppendUint64s(1, x.Nodes) + } + if x.ParentId != 0 { + mm.AppendUint64(2, x.ParentId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddByPathResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddByPathResponse_Body") + } + switch fc.FieldNum { + case 1: // Nodes + data, ok := fc.UnpackUint64s(nil) + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Nodes") + } + x.Nodes = data + case 2: // ParentId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ParentId") + } + x.ParentId = data + } + } + return nil +} +func (x *AddByPathResponse_Body) GetNodes() []uint64 { + if x != nil { + return x.Nodes + } + return nil +} +func (x *AddByPathResponse_Body) SetNodes(v []uint64) { + x.Nodes = v +} +func (x *AddByPathResponse_Body) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} +func (x *AddByPathResponse_Body) SetParentId(v uint64) { + x.ParentId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddByPathResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddByPathResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"nodes\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Nodes { + if i != 0 { + out.RawByte(',') + } + out.Uint64(x.Nodes[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"parentId\":" + out.RawString(prefix) + out.Uint64(x.ParentId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddByPathResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddByPathResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "nodes": + { + var f uint64 + var list []uint64 + in.Delim('[') + for !in.IsDelim(']') { + f = in.Uint64() + list = append(list, f) + in.WantComma() + } + x.Nodes = list + in.Delim(']') + } + case "parentId": + { + var f uint64 + f = in.Uint64() + x.ParentId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type AddByPathResponse struct { + Body *AddByPathResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*AddByPathResponse)(nil) + _ encoding.ProtoUnmarshaler = (*AddByPathResponse)(nil) + _ json.Marshaler = (*AddByPathResponse)(nil) + _ json.Unmarshaler = (*AddByPathResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -340,27 +1499,6 @@ func (x *AddByPathResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *AddByPathResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -376,13 +1514,167 @@ func (x *AddByPathResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *AddByPathResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *AddByPathResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *AddByPathResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *AddByPathResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *AddByPathResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "AddByPathResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(AddByPathResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *AddByPathResponse) GetBody() *AddByPathResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *AddByPathResponse) SetBody(v *AddByPathResponse_Body) { + x.Body = v +} +func (x *AddByPathResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *AddByPathResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *AddByPathResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *AddByPathResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *AddByPathResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *AddByPathResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *AddByPathResponse_Body + f = new(AddByPathResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + NodeId uint64 `json:"nodeId"` + BearerToken []byte `json:"bearerToken"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveRequest_Body)(nil) + _ json.Marshaler = (*RemoveRequest_Body)(nil) + _ json.Unmarshaler = (*RemoveRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -397,29 +1689,212 @@ func (x *RemoveRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.UInt64Marshal(3, buf[offset:], x.NodeId) - offset += proto.BytesMarshal(4, buf[offset:], x.BearerToken) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + if x.NodeId != 0 { + mm.AppendUint64(3, x.NodeId) + } + if len(x.BearerToken) != 0 { + mm.AppendBytes(4, x.BearerToken) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // NodeId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "NodeId") + } + x.NodeId = data + case 4: // BearerToken + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "BearerToken") + } + x.BearerToken = data + } + } + return nil +} +func (x *RemoveRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *RemoveRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *RemoveRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *RemoveRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *RemoveRequest_Body) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} +func (x *RemoveRequest_Body) SetNodeId(v uint64) { + x.NodeId = v +} +func (x *RemoveRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} +func (x *RemoveRequest_Body) SetBearerToken(v []byte) { + x.BearerToken = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"nodeId\":" + out.RawString(prefix) + out.Uint64(x.NodeId) + } + { + const prefix string = ",\"bearerToken\":" + out.RawString(prefix) + out.Base64Bytes(x.BearerToken) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "nodeId": + { + var f uint64 + f = in.Uint64() + x.NodeId = f + } + case "bearerToken": + { + var f []byte + f = in.Bytes() + x.BearerToken = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveRequest struct { + Body *RemoveRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveRequest)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveRequest)(nil) + _ json.Marshaler = (*RemoveRequest)(nil) + _ json.Unmarshaler = (*RemoveRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -432,27 +1907,6 @@ func (x *RemoveRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -468,13 +1922,163 @@ func (x *RemoveRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveRequest) GetBody() *RemoveRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveRequest) SetBody(v *RemoveRequest_Body) { + x.Body = v +} +func (x *RemoveRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveRequest_Body + f = new(RemoveRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveResponse_Body)(nil) + _ json.Marshaler = (*RemoveResponse_Body)(nil) + _ json.Unmarshaler = (*RemoveResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -485,18 +2089,93 @@ func (x *RemoveResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type RemoveResponse struct { + Body *RemoveResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*RemoveResponse)(nil) + _ encoding.ProtoUnmarshaler = (*RemoveResponse)(nil) + _ json.Marshaler = (*RemoveResponse)(nil) + _ json.Unmarshaler = (*RemoveResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -509,27 +2188,6 @@ func (x *RemoveResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *RemoveResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -545,13 +2203,169 @@ func (x *RemoveResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *RemoveResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *RemoveResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *RemoveResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *RemoveResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *RemoveResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "RemoveResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(RemoveResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *RemoveResponse) GetBody() *RemoveResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *RemoveResponse) SetBody(v *RemoveResponse_Body) { + x.Body = v +} +func (x *RemoveResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *RemoveResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *RemoveResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *RemoveResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *RemoveResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *RemoveResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *RemoveResponse_Body + f = new(RemoveResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type MoveRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + ParentId uint64 `json:"parentId"` + NodeId uint64 `json:"nodeId"` + Meta []*KeyValue `json:"meta"` + BearerToken []byte `json:"bearerToken"` +} + +var ( + _ encoding.ProtoMarshaler = (*MoveRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*MoveRequest_Body)(nil) + _ json.Marshaler = (*MoveRequest_Body)(nil) + _ json.Unmarshaler = (*MoveRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -570,33 +2384,291 @@ func (x *MoveRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *MoveRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.UInt64Marshal(3, buf[offset:], x.ParentId) - offset += proto.UInt64Marshal(4, buf[offset:], x.NodeId) - for i := range x.Meta { - offset += proto.NestedStructureMarshal(5, buf[offset:], x.Meta[i]) - } - offset += proto.BytesMarshal(6, buf[offset:], x.BearerToken) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *MoveRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *MoveRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + if x.ParentId != 0 { + mm.AppendUint64(3, x.ParentId) + } + if x.NodeId != 0 { + mm.AppendUint64(4, x.NodeId) + } + for i := range x.Meta { + if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + x.Meta[i].EmitProtobuf(mm.AppendMessage(5)) + } + } + if len(x.BearerToken) != 0 { + mm.AppendBytes(6, x.BearerToken) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *MoveRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "MoveRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // ParentId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ParentId") + } + x.ParentId = data + case 4: // NodeId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "NodeId") + } + x.NodeId = data + case 5: // Meta + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Meta") + } + x.Meta = append(x.Meta, new(KeyValue)) + ff := x.Meta[len(x.Meta)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 6: // BearerToken + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "BearerToken") + } + x.BearerToken = data + } + } + return nil +} +func (x *MoveRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *MoveRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *MoveRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *MoveRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *MoveRequest_Body) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} +func (x *MoveRequest_Body) SetParentId(v uint64) { + x.ParentId = v +} +func (x *MoveRequest_Body) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} +func (x *MoveRequest_Body) SetNodeId(v uint64) { + x.NodeId = v +} +func (x *MoveRequest_Body) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} +func (x *MoveRequest_Body) SetMeta(v []*KeyValue) { + x.Meta = v +} +func (x *MoveRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} +func (x *MoveRequest_Body) SetBearerToken(v []byte) { + x.BearerToken = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *MoveRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *MoveRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"parentId\":" + out.RawString(prefix) + out.Uint64(x.ParentId) + } + { + const prefix string = ",\"nodeId\":" + out.RawString(prefix) + out.Uint64(x.NodeId) + } + { + const prefix string = ",\"meta\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Meta { + if i != 0 { + out.RawByte(',') + } + x.Meta[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + { + const prefix string = ",\"bearerToken\":" + out.RawString(prefix) + out.Base64Bytes(x.BearerToken) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *MoveRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *MoveRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "parentId": + { + var f uint64 + f = in.Uint64() + x.ParentId = f + } + case "nodeId": + { + var f uint64 + f = in.Uint64() + x.NodeId = f + } + case "meta": + { + var f *KeyValue + var list []*KeyValue + in.Delim('[') + for !in.IsDelim(']') { + f = new(KeyValue) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Meta = list + in.Delim(']') + } + case "bearerToken": + { + var f []byte + f = in.Bytes() + x.BearerToken = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type MoveRequest struct { + Body *MoveRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*MoveRequest)(nil) + _ encoding.ProtoUnmarshaler = (*MoveRequest)(nil) + _ json.Marshaler = (*MoveRequest)(nil) + _ json.Unmarshaler = (*MoveRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -609,27 +2681,6 @@ func (x *MoveRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *MoveRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -645,13 +2696,163 @@ func (x *MoveRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *MoveRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *MoveRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *MoveRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *MoveRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *MoveRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "MoveRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(MoveRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *MoveRequest) GetBody() *MoveRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *MoveRequest) SetBody(v *MoveRequest_Body) { + x.Body = v +} +func (x *MoveRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *MoveRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *MoveRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *MoveRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *MoveRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *MoveRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *MoveRequest_Body + f = new(MoveRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type MoveResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*MoveResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*MoveResponse_Body)(nil) + _ json.Marshaler = (*MoveResponse_Body)(nil) + _ json.Unmarshaler = (*MoveResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -662,18 +2863,93 @@ func (x *MoveResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *MoveResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *MoveResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *MoveResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *MoveResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "MoveResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *MoveResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *MoveResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *MoveResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *MoveResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type MoveResponse struct { + Body *MoveResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*MoveResponse)(nil) + _ encoding.ProtoUnmarshaler = (*MoveResponse)(nil) + _ json.Marshaler = (*MoveResponse)(nil) + _ json.Unmarshaler = (*MoveResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -686,27 +2962,6 @@ func (x *MoveResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *MoveResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -722,13 +2977,171 @@ func (x *MoveResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *MoveResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *MoveResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *MoveResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *MoveResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *MoveResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "MoveResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(MoveResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *MoveResponse) GetBody() *MoveResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *MoveResponse) SetBody(v *MoveResponse_Body) { + x.Body = v +} +func (x *MoveResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *MoveResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *MoveResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *MoveResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *MoveResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *MoveResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *MoveResponse_Body + f = new(MoveResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNodeByPathRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + PathAttribute string `json:"pathAttribute"` + Path []string `json:"path"` + Attributes []string `json:"attributes"` + LatestOnly bool `json:"latestOnly"` + AllAttributes bool `json:"allAttributes"` + BearerToken []byte `json:"bearerToken"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetNodeByPathRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetNodeByPathRequest_Body)(nil) + _ json.Marshaler = (*GetNodeByPathRequest_Body)(nil) + _ json.Unmarshaler = (*GetNodeByPathRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -747,33 +3160,356 @@ func (x *GetNodeByPathRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNodeByPathRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.StringMarshal(3, buf[offset:], x.PathAttribute) - offset += proto.RepeatedStringMarshal(4, buf[offset:], x.Path) - offset += proto.RepeatedStringMarshal(5, buf[offset:], x.Attributes) - offset += proto.BoolMarshal(6, buf[offset:], x.LatestOnly) - offset += proto.BoolMarshal(7, buf[offset:], x.AllAttributes) - offset += proto.BytesMarshal(8, buf[offset:], x.BearerToken) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNodeByPathRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNodeByPathRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + if len(x.PathAttribute) != 0 { + mm.AppendString(3, x.PathAttribute) + } + for j := range x.Path { + mm.AppendString(4, x.Path[j]) + } + for j := range x.Attributes { + mm.AppendString(5, x.Attributes[j]) + } + if x.LatestOnly { + mm.AppendBool(6, x.LatestOnly) + } + if x.AllAttributes { + mm.AppendBool(7, x.AllAttributes) + } + if len(x.BearerToken) != 0 { + mm.AppendBytes(8, x.BearerToken) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNodeByPathRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNodeByPathRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // PathAttribute + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "PathAttribute") + } + x.PathAttribute = data + case 4: // Path + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Path") + } + x.Path = append(x.Path, data) + case 5: // Attributes + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Attributes") + } + x.Attributes = append(x.Attributes, data) + case 6: // LatestOnly + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "LatestOnly") + } + x.LatestOnly = data + case 7: // AllAttributes + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "AllAttributes") + } + x.AllAttributes = data + case 8: // BearerToken + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "BearerToken") + } + x.BearerToken = data + } + } + return nil +} +func (x *GetNodeByPathRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *GetNodeByPathRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *GetNodeByPathRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *GetNodeByPathRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *GetNodeByPathRequest_Body) GetPathAttribute() string { + if x != nil { + return x.PathAttribute + } + return "" +} +func (x *GetNodeByPathRequest_Body) SetPathAttribute(v string) { + x.PathAttribute = v +} +func (x *GetNodeByPathRequest_Body) GetPath() []string { + if x != nil { + return x.Path + } + return nil +} +func (x *GetNodeByPathRequest_Body) SetPath(v []string) { + x.Path = v +} +func (x *GetNodeByPathRequest_Body) GetAttributes() []string { + if x != nil { + return x.Attributes + } + return nil +} +func (x *GetNodeByPathRequest_Body) SetAttributes(v []string) { + x.Attributes = v +} +func (x *GetNodeByPathRequest_Body) GetLatestOnly() bool { + if x != nil { + return x.LatestOnly + } + return false +} +func (x *GetNodeByPathRequest_Body) SetLatestOnly(v bool) { + x.LatestOnly = v +} +func (x *GetNodeByPathRequest_Body) GetAllAttributes() bool { + if x != nil { + return x.AllAttributes + } + return false +} +func (x *GetNodeByPathRequest_Body) SetAllAttributes(v bool) { + x.AllAttributes = v +} +func (x *GetNodeByPathRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} +func (x *GetNodeByPathRequest_Body) SetBearerToken(v []byte) { + x.BearerToken = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNodeByPathRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNodeByPathRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"pathAttribute\":" + out.RawString(prefix) + out.String(x.PathAttribute) + } + { + const prefix string = ",\"path\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Path { + if i != 0 { + out.RawByte(',') + } + out.String(x.Path[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"attributes\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Attributes { + if i != 0 { + out.RawByte(',') + } + out.String(x.Attributes[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"latestOnly\":" + out.RawString(prefix) + out.Bool(x.LatestOnly) + } + { + const prefix string = ",\"allAttributes\":" + out.RawString(prefix) + out.Bool(x.AllAttributes) + } + { + const prefix string = ",\"bearerToken\":" + out.RawString(prefix) + out.Base64Bytes(x.BearerToken) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNodeByPathRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNodeByPathRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "pathAttribute": + { + var f string + f = in.String() + x.PathAttribute = f + } + case "path": + { + var f string + var list []string + in.Delim('[') + for !in.IsDelim(']') { + f = in.String() + list = append(list, f) + in.WantComma() + } + x.Path = list + in.Delim(']') + } + case "attributes": + { + var f string + var list []string + in.Delim('[') + for !in.IsDelim(']') { + f = in.String() + list = append(list, f) + in.WantComma() + } + x.Attributes = list + in.Delim(']') + } + case "latestOnly": + { + var f bool + f = in.Bool() + x.LatestOnly = f + } + case "allAttributes": + { + var f bool + f = in.Bool() + x.AllAttributes = f + } + case "bearerToken": + { + var f []byte + f = in.Bytes() + x.BearerToken = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNodeByPathRequest struct { + Body *GetNodeByPathRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetNodeByPathRequest)(nil) + _ encoding.ProtoUnmarshaler = (*GetNodeByPathRequest)(nil) + _ json.Marshaler = (*GetNodeByPathRequest)(nil) + _ json.Unmarshaler = (*GetNodeByPathRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -786,27 +3522,6 @@ func (x *GetNodeByPathRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNodeByPathRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -822,13 +3537,167 @@ func (x *GetNodeByPathRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetNodeByPathRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetNodeByPathRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNodeByPathRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNodeByPathRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNodeByPathRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNodeByPathRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetNodeByPathRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetNodeByPathRequest) GetBody() *GetNodeByPathRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetNodeByPathRequest) SetBody(v *GetNodeByPathRequest_Body) { + x.Body = v +} +func (x *GetNodeByPathRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetNodeByPathRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNodeByPathRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNodeByPathRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNodeByPathRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNodeByPathRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetNodeByPathRequest_Body + f = new(GetNodeByPathRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNodeByPathResponse_Info struct { + NodeId uint64 `json:"nodeId"` + Timestamp uint64 `json:"timestamp"` + Meta []*KeyValue `json:"meta"` + ParentId uint64 `json:"parentId"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetNodeByPathResponse_Info)(nil) + _ encoding.ProtoUnmarshaler = (*GetNodeByPathResponse_Info)(nil) + _ json.Marshaler = (*GetNodeByPathResponse_Info)(nil) + _ json.Unmarshaler = (*GetNodeByPathResponse_Info)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -845,31 +3714,232 @@ func (x *GetNodeByPathResponse_Info) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNodeByPathResponse_Info) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt64Marshal(1, buf[offset:], x.NodeId) - offset += proto.UInt64Marshal(2, buf[offset:], x.Timestamp) - for i := range x.Meta { - offset += proto.NestedStructureMarshal(3, buf[offset:], x.Meta[i]) - } - offset += proto.UInt64Marshal(4, buf[offset:], x.ParentId) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNodeByPathResponse_Info) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNodeByPathResponse_Info) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.NodeId != 0 { + mm.AppendUint64(1, x.NodeId) + } + if x.Timestamp != 0 { + mm.AppendUint64(2, x.Timestamp) + } + for i := range x.Meta { + if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + x.Meta[i].EmitProtobuf(mm.AppendMessage(3)) + } + } + if x.ParentId != 0 { + mm.AppendUint64(4, x.ParentId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNodeByPathResponse_Info) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNodeByPathResponse_Info") + } + switch fc.FieldNum { + case 1: // NodeId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "NodeId") + } + x.NodeId = data + case 2: // Timestamp + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Timestamp") + } + x.Timestamp = data + case 3: // Meta + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Meta") + } + x.Meta = append(x.Meta, new(KeyValue)) + ff := x.Meta[len(x.Meta)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 4: // ParentId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ParentId") + } + x.ParentId = data + } + } + return nil +} +func (x *GetNodeByPathResponse_Info) GetNodeId() uint64 { + if x != nil { + return x.NodeId + } + return 0 +} +func (x *GetNodeByPathResponse_Info) SetNodeId(v uint64) { + x.NodeId = v +} +func (x *GetNodeByPathResponse_Info) GetTimestamp() uint64 { + if x != nil { + return x.Timestamp + } + return 0 +} +func (x *GetNodeByPathResponse_Info) SetTimestamp(v uint64) { + x.Timestamp = v +} +func (x *GetNodeByPathResponse_Info) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} +func (x *GetNodeByPathResponse_Info) SetMeta(v []*KeyValue) { + x.Meta = v +} +func (x *GetNodeByPathResponse_Info) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} +func (x *GetNodeByPathResponse_Info) SetParentId(v uint64) { + x.ParentId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNodeByPathResponse_Info) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNodeByPathResponse_Info) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"nodeId\":" + out.RawString(prefix[1:]) + out.Uint64(x.NodeId) + } + { + const prefix string = ",\"timestamp\":" + out.RawString(prefix) + out.Uint64(x.Timestamp) + } + { + const prefix string = ",\"meta\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Meta { + if i != 0 { + out.RawByte(',') + } + x.Meta[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + { + const prefix string = ",\"parentId\":" + out.RawString(prefix) + out.Uint64(x.ParentId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNodeByPathResponse_Info) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNodeByPathResponse_Info) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "nodeId": + { + var f uint64 + f = in.Uint64() + x.NodeId = f + } + case "timestamp": + { + var f uint64 + f = in.Uint64() + x.Timestamp = f + } + case "meta": + { + var f *KeyValue + var list []*KeyValue + in.Delim('[') + for !in.IsDelim(']') { + f = new(KeyValue) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Meta = list + in.Delim(']') + } + case "parentId": + { + var f uint64 + f = in.Uint64() + x.ParentId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNodeByPathResponse_Body struct { + Nodes []*GetNodeByPathResponse_Info `json:"nodes"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetNodeByPathResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetNodeByPathResponse_Body)(nil) + _ json.Marshaler = (*GetNodeByPathResponse_Body)(nil) + _ json.Unmarshaler = (*GetNodeByPathResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -883,28 +3953,146 @@ func (x *GetNodeByPathResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNodeByPathResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - for i := range x.Nodes { - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Nodes[i]) - } - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNodeByPathResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNodeByPathResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for i := range x.Nodes { + if x.Nodes[i] != nil && x.Nodes[i].StableSize() != 0 { + x.Nodes[i].EmitProtobuf(mm.AppendMessage(1)) + } + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNodeByPathResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNodeByPathResponse_Body") + } + switch fc.FieldNum { + case 1: // Nodes + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Nodes") + } + x.Nodes = append(x.Nodes, new(GetNodeByPathResponse_Info)) + ff := x.Nodes[len(x.Nodes)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetNodeByPathResponse_Body) GetNodes() []*GetNodeByPathResponse_Info { + if x != nil { + return x.Nodes + } + return nil +} +func (x *GetNodeByPathResponse_Body) SetNodes(v []*GetNodeByPathResponse_Info) { + x.Nodes = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNodeByPathResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNodeByPathResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"nodes\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Nodes { + if i != 0 { + out.RawByte(',') + } + x.Nodes[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNodeByPathResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNodeByPathResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "nodes": + { + var f *GetNodeByPathResponse_Info + var list []*GetNodeByPathResponse_Info + in.Delim('[') + for !in.IsDelim(']') { + f = new(GetNodeByPathResponse_Info) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Nodes = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetNodeByPathResponse struct { + Body *GetNodeByPathResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetNodeByPathResponse)(nil) + _ encoding.ProtoUnmarshaler = (*GetNodeByPathResponse)(nil) + _ json.Marshaler = (*GetNodeByPathResponse)(nil) + _ json.Unmarshaler = (*GetNodeByPathResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -917,27 +4105,6 @@ func (x *GetNodeByPathResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetNodeByPathResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -953,13 +4120,196 @@ func (x *GetNodeByPathResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetNodeByPathResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetNodeByPathResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetNodeByPathResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetNodeByPathResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetNodeByPathResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetNodeByPathResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetNodeByPathResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetNodeByPathResponse) GetBody() *GetNodeByPathResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetNodeByPathResponse) SetBody(v *GetNodeByPathResponse_Body) { + x.Body = v +} +func (x *GetNodeByPathResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetNodeByPathResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetNodeByPathResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetNodeByPathResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetNodeByPathResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetNodeByPathResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetNodeByPathResponse_Body + f = new(GetNodeByPathResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetSubTreeRequest_Body_Order_Direction int32 + +const ( + GetSubTreeRequest_Body_Order_None GetSubTreeRequest_Body_Order_Direction = 0 + GetSubTreeRequest_Body_Order_Asc GetSubTreeRequest_Body_Order_Direction = 1 +) + +var ( + GetSubTreeRequest_Body_Order_Direction_name = map[int32]string{ + 0: "None", + 1: "Asc", + } + GetSubTreeRequest_Body_Order_Direction_value = map[string]int32{ + "None": 0, + "Asc": 1, + } +) + +func (x GetSubTreeRequest_Body_Order_Direction) String() string { + if v, ok := GetSubTreeRequest_Body_Order_Direction_name[int32(x)]; ok { + return v + } + return strconv.FormatInt(int64(x), 10) +} +func (x *GetSubTreeRequest_Body_Order_Direction) FromString(s string) bool { + if v, ok := GetSubTreeRequest_Body_Order_Direction_value[s]; ok { + *x = GetSubTreeRequest_Body_Order_Direction(v) + return true + } + return false +} + +type GetSubTreeRequest_Body_Order struct { + Direction GetSubTreeRequest_Body_Order_Direction `json:"direction"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetSubTreeRequest_Body_Order)(nil) + _ encoding.ProtoUnmarshaler = (*GetSubTreeRequest_Body_Order)(nil) + _ json.Marshaler = (*GetSubTreeRequest_Body_Order)(nil) + _ json.Unmarshaler = (*GetSubTreeRequest_Body_Order)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -971,26 +4321,145 @@ func (x *GetSubTreeRequest_Body_Order) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetSubTreeRequest_Body_Order) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.EnumMarshal(1, buf[offset:], int32(x.Direction)) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetSubTreeRequest_Body_Order) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetSubTreeRequest_Body_Order) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if int32(x.Direction) != 0 { + mm.AppendInt32(1, int32(x.Direction)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetSubTreeRequest_Body_Order) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetSubTreeRequest_Body_Order") + } + switch fc.FieldNum { + case 1: // Direction + data, ok := fc.Int32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Direction") + } + x.Direction = GetSubTreeRequest_Body_Order_Direction(data) + } + } + return nil +} +func (x *GetSubTreeRequest_Body_Order) GetDirection() GetSubTreeRequest_Body_Order_Direction { + if x != nil { + return x.Direction + } + return 0 +} +func (x *GetSubTreeRequest_Body_Order) SetDirection(v GetSubTreeRequest_Body_Order_Direction) { + x.Direction = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetSubTreeRequest_Body_Order) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetSubTreeRequest_Body_Order) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"direction\":" + out.RawString(prefix[1:]) + out.Int32(int32(x.Direction)) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetSubTreeRequest_Body_Order) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetSubTreeRequest_Body_Order) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "direction": + { + var f GetSubTreeRequest_Body_Order_Direction + var parsedValue GetSubTreeRequest_Body_Order_Direction + switch v := in.Interface().(type) { + case string: + if vv, ok := GetSubTreeRequest_Body_Order_Direction_value[v]; ok { + parsedValue = GetSubTreeRequest_Body_Order_Direction(vv) + break + } + vv, err := strconv.ParseInt(v, 10, 32) + if err != nil { + in.AddError(err) + return + } + parsedValue = GetSubTreeRequest_Body_Order_Direction(vv) + case float64: + parsedValue = GetSubTreeRequest_Body_Order_Direction(v) + } + f = parsedValue + x.Direction = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetSubTreeRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + RootId []uint64 `json:"rootId"` + Depth uint32 `json:"depth"` + BearerToken []byte `json:"bearerToken"` + OrderBy *GetSubTreeRequest_Body_Order `json:"orderBy"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetSubTreeRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetSubTreeRequest_Body)(nil) + _ json.Marshaler = (*GetSubTreeRequest_Body)(nil) + _ json.Unmarshaler = (*GetSubTreeRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1009,36 +4478,287 @@ func (x *GetSubTreeRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetSubTreeRequest_Body) StableMarshal(buf []byte) []byte { +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetSubTreeRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *GetSubTreeRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { - return []byte{} + return } - if buf == nil { - buf = make([]byte, x.StableSize()) + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - for i := range x.RootId { - { - prefix := protowire.EncodeTag(protowire.Number(3), protowire.VarintType) - offset += binary.PutUvarint(buf[offset:], uint64(prefix)) - offset += binary.PutUvarint(buf[offset:], x.RootId[i]) + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + for j := range x.RootId { + mm.AppendUint64(3, x.RootId[j]) + } + if x.Depth != 0 { + mm.AppendUint32(4, x.Depth) + } + if len(x.BearerToken) != 0 { + mm.AppendBytes(5, x.BearerToken) + } + if x.OrderBy != nil && x.OrderBy.StableSize() != 0 { + x.OrderBy.EmitProtobuf(mm.AppendMessage(6)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetSubTreeRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetSubTreeRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // RootId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "RootId") + } + x.RootId = append(x.RootId, data) + case 4: // Depth + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Depth") + } + x.Depth = data + case 5: // BearerToken + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "BearerToken") + } + x.BearerToken = data + case 6: // OrderBy + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "OrderBy") + } + x.OrderBy = new(GetSubTreeRequest_Body_Order) + if err := x.OrderBy.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } } } - offset += proto.UInt32Marshal(4, buf[offset:], x.Depth) - offset += proto.BytesMarshal(5, buf[offset:], x.BearerToken) - offset += proto.NestedStructureMarshal(6, buf[offset:], x.OrderBy) - return buf + return nil } +func (x *GetSubTreeRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *GetSubTreeRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *GetSubTreeRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *GetSubTreeRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *GetSubTreeRequest_Body) GetRootId() []uint64 { + if x != nil { + return x.RootId + } + return nil +} +func (x *GetSubTreeRequest_Body) SetRootId(v []uint64) { + x.RootId = v +} +func (x *GetSubTreeRequest_Body) GetDepth() uint32 { + if x != nil { + return x.Depth + } + return 0 +} +func (x *GetSubTreeRequest_Body) SetDepth(v uint32) { + x.Depth = v +} +func (x *GetSubTreeRequest_Body) GetBearerToken() []byte { + if x != nil { + return x.BearerToken + } + return nil +} +func (x *GetSubTreeRequest_Body) SetBearerToken(v []byte) { + x.BearerToken = v +} +func (x *GetSubTreeRequest_Body) GetOrderBy() *GetSubTreeRequest_Body_Order { + if x != nil { + return x.OrderBy + } + return nil +} +func (x *GetSubTreeRequest_Body) SetOrderBy(v *GetSubTreeRequest_Body_Order) { + x.OrderBy = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetSubTreeRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetSubTreeRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"rootId\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.RootId { + if i != 0 { + out.RawByte(',') + } + out.Uint64(x.RootId[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"depth\":" + out.RawString(prefix) + out.Uint32(x.Depth) + } + { + const prefix string = ",\"bearerToken\":" + out.RawString(prefix) + out.Base64Bytes(x.BearerToken) + } + { + const prefix string = ",\"orderBy\":" + out.RawString(prefix) + x.OrderBy.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetSubTreeRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetSubTreeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "rootId": + { + var f uint64 + var list []uint64 + in.Delim('[') + for !in.IsDelim(']') { + f = in.Uint64() + list = append(list, f) + in.WantComma() + } + x.RootId = list + in.Delim(']') + } + case "depth": + { + var f uint32 + f = in.Uint32() + x.Depth = f + } + case "bearerToken": + { + var f []byte + f = in.Bytes() + x.BearerToken = f + } + case "orderBy": + { + var f *GetSubTreeRequest_Body_Order + f = new(GetSubTreeRequest_Body_Order) + f.UnmarshalEasyJSON(in) + x.OrderBy = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetSubTreeRequest struct { + Body *GetSubTreeRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetSubTreeRequest)(nil) + _ encoding.ProtoUnmarshaler = (*GetSubTreeRequest)(nil) + _ json.Marshaler = (*GetSubTreeRequest)(nil) + _ json.Unmarshaler = (*GetSubTreeRequest)(nil) +) // StableSize returns the size of x in protobuf format. // @@ -1052,27 +4772,6 @@ func (x *GetSubTreeRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetSubTreeRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1088,13 +4787,167 @@ func (x *GetSubTreeRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetSubTreeRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetSubTreeRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetSubTreeRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetSubTreeRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetSubTreeRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetSubTreeRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetSubTreeRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetSubTreeRequest) GetBody() *GetSubTreeRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetSubTreeRequest) SetBody(v *GetSubTreeRequest_Body) { + x.Body = v +} +func (x *GetSubTreeRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetSubTreeRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetSubTreeRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetSubTreeRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetSubTreeRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetSubTreeRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetSubTreeRequest_Body + f = new(GetSubTreeRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetSubTreeResponse_Body struct { + NodeId []uint64 `json:"nodeId"` + ParentId []uint64 `json:"parentId"` + Timestamp []uint64 `json:"timestamp"` + Meta []*KeyValue `json:"meta"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetSubTreeResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetSubTreeResponse_Body)(nil) + _ json.Marshaler = (*GetSubTreeResponse_Body)(nil) + _ json.Unmarshaler = (*GetSubTreeResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1117,49 +4970,275 @@ func (x *GetSubTreeResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetSubTreeResponse_Body) StableMarshal(buf []byte) []byte { +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetSubTreeResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *GetSubTreeResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { - return []byte{} + return } - if buf == nil { - buf = make([]byte, x.StableSize()) + for j := range x.NodeId { + mm.AppendUint64(1, x.NodeId[j]) } - var offset int - for i := range x.NodeId { - { - prefix := protowire.EncodeTag(protowire.Number(1), protowire.VarintType) - offset += binary.PutUvarint(buf[offset:], uint64(prefix)) - offset += binary.PutUvarint(buf[offset:], x.NodeId[i]) - } + for j := range x.ParentId { + mm.AppendUint64(2, x.ParentId[j]) } - for i := range x.ParentId { - { - prefix := protowire.EncodeTag(protowire.Number(2), protowire.VarintType) - offset += binary.PutUvarint(buf[offset:], uint64(prefix)) - offset += binary.PutUvarint(buf[offset:], x.ParentId[i]) - } - } - for i := range x.Timestamp { - { - prefix := protowire.EncodeTag(protowire.Number(3), protowire.VarintType) - offset += binary.PutUvarint(buf[offset:], uint64(prefix)) - offset += binary.PutUvarint(buf[offset:], x.Timestamp[i]) - } + for j := range x.Timestamp { + mm.AppendUint64(3, x.Timestamp[j]) } for i := range x.Meta { - offset += proto.NestedStructureMarshal(4, buf[offset:], x.Meta[i]) + if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + x.Meta[i].EmitProtobuf(mm.AppendMessage(4)) + } } - return buf } +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetSubTreeResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetSubTreeResponse_Body") + } + switch fc.FieldNum { + case 1: // NodeId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "NodeId") + } + x.NodeId = append(x.NodeId, data) + case 2: // ParentId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ParentId") + } + x.ParentId = append(x.ParentId, data) + case 3: // Timestamp + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Timestamp") + } + x.Timestamp = append(x.Timestamp, data) + case 4: // Meta + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Meta") + } + x.Meta = append(x.Meta, new(KeyValue)) + ff := x.Meta[len(x.Meta)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetSubTreeResponse_Body) GetNodeId() []uint64 { + if x != nil { + return x.NodeId + } + return nil +} +func (x *GetSubTreeResponse_Body) SetNodeId(v []uint64) { + x.NodeId = v +} +func (x *GetSubTreeResponse_Body) GetParentId() []uint64 { + if x != nil { + return x.ParentId + } + return nil +} +func (x *GetSubTreeResponse_Body) SetParentId(v []uint64) { + x.ParentId = v +} +func (x *GetSubTreeResponse_Body) GetTimestamp() []uint64 { + if x != nil { + return x.Timestamp + } + return nil +} +func (x *GetSubTreeResponse_Body) SetTimestamp(v []uint64) { + x.Timestamp = v +} +func (x *GetSubTreeResponse_Body) GetMeta() []*KeyValue { + if x != nil { + return x.Meta + } + return nil +} +func (x *GetSubTreeResponse_Body) SetMeta(v []*KeyValue) { + x.Meta = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetSubTreeResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetSubTreeResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"nodeId\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.NodeId { + if i != 0 { + out.RawByte(',') + } + out.Uint64(x.NodeId[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"parentId\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.ParentId { + if i != 0 { + out.RawByte(',') + } + out.Uint64(x.ParentId[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"timestamp\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Timestamp { + if i != 0 { + out.RawByte(',') + } + out.Uint64(x.Timestamp[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"meta\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Meta { + if i != 0 { + out.RawByte(',') + } + x.Meta[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetSubTreeResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetSubTreeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "nodeId": + { + var f uint64 + var list []uint64 + in.Delim('[') + for !in.IsDelim(']') { + f = in.Uint64() + list = append(list, f) + in.WantComma() + } + x.NodeId = list + in.Delim(']') + } + case "parentId": + { + var f uint64 + var list []uint64 + in.Delim('[') + for !in.IsDelim(']') { + f = in.Uint64() + list = append(list, f) + in.WantComma() + } + x.ParentId = list + in.Delim(']') + } + case "timestamp": + { + var f uint64 + var list []uint64 + in.Delim('[') + for !in.IsDelim(']') { + f = in.Uint64() + list = append(list, f) + in.WantComma() + } + x.Timestamp = list + in.Delim(']') + } + case "meta": + { + var f *KeyValue + var list []*KeyValue + in.Delim('[') + for !in.IsDelim(']') { + f = new(KeyValue) + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Meta = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetSubTreeResponse struct { + Body *GetSubTreeResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetSubTreeResponse)(nil) + _ encoding.ProtoUnmarshaler = (*GetSubTreeResponse)(nil) + _ json.Marshaler = (*GetSubTreeResponse)(nil) + _ json.Unmarshaler = (*GetSubTreeResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1172,27 +5251,6 @@ func (x *GetSubTreeResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetSubTreeResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1208,13 +5266,164 @@ func (x *GetSubTreeResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetSubTreeResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetSubTreeResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetSubTreeResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetSubTreeResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetSubTreeResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetSubTreeResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetSubTreeResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetSubTreeResponse) GetBody() *GetSubTreeResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetSubTreeResponse) SetBody(v *GetSubTreeResponse_Body) { + x.Body = v +} +func (x *GetSubTreeResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetSubTreeResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetSubTreeResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetSubTreeResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetSubTreeResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetSubTreeResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetSubTreeResponse_Body + f = new(GetSubTreeResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type TreeListRequest_Body struct { + ContainerId []byte `json:"containerId"` +} + +var ( + _ encoding.ProtoMarshaler = (*TreeListRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*TreeListRequest_Body)(nil) + _ json.Marshaler = (*TreeListRequest_Body)(nil) + _ json.Unmarshaler = (*TreeListRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1226,26 +5435,125 @@ func (x *TreeListRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *TreeListRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *TreeListRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *TreeListRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *TreeListRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "TreeListRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + } + } + return nil +} +func (x *TreeListRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *TreeListRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *TreeListRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *TreeListRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *TreeListRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *TreeListRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type TreeListRequest struct { + Body *TreeListRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*TreeListRequest)(nil) + _ encoding.ProtoUnmarshaler = (*TreeListRequest)(nil) + _ json.Marshaler = (*TreeListRequest)(nil) + _ json.Unmarshaler = (*TreeListRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1258,27 +5566,6 @@ func (x *TreeListRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *TreeListRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1294,13 +5581,164 @@ func (x *TreeListRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *TreeListRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *TreeListRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *TreeListRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *TreeListRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *TreeListRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "TreeListRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(TreeListRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *TreeListRequest) GetBody() *TreeListRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *TreeListRequest) SetBody(v *TreeListRequest_Body) { + x.Body = v +} +func (x *TreeListRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *TreeListRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *TreeListRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *TreeListRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *TreeListRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *TreeListRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *TreeListRequest_Body + f = new(TreeListRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type TreeListResponse_Body struct { + Ids []string `json:"ids"` +} + +var ( + _ encoding.ProtoMarshaler = (*TreeListResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*TreeListResponse_Body)(nil) + _ json.Marshaler = (*TreeListResponse_Body)(nil) + _ json.Unmarshaler = (*TreeListResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1312,26 +5750,139 @@ func (x *TreeListResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *TreeListResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.RepeatedStringMarshal(1, buf[offset:], x.Ids) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *TreeListResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *TreeListResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Ids { + mm.AppendString(1, x.Ids[j]) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *TreeListResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "TreeListResponse_Body") + } + switch fc.FieldNum { + case 1: // Ids + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Ids") + } + x.Ids = append(x.Ids, data) + } + } + return nil +} +func (x *TreeListResponse_Body) GetIds() []string { + if x != nil { + return x.Ids + } + return nil +} +func (x *TreeListResponse_Body) SetIds(v []string) { + x.Ids = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *TreeListResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *TreeListResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"ids\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Ids { + if i != 0 { + out.RawByte(',') + } + out.String(x.Ids[i]) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *TreeListResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *TreeListResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "ids": + { + var f string + var list []string + in.Delim('[') + for !in.IsDelim(']') { + f = in.String() + list = append(list, f) + in.WantComma() + } + x.Ids = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type TreeListResponse struct { + Body *TreeListResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*TreeListResponse)(nil) + _ encoding.ProtoUnmarshaler = (*TreeListResponse)(nil) + _ json.Marshaler = (*TreeListResponse)(nil) + _ json.Unmarshaler = (*TreeListResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1344,27 +5895,6 @@ func (x *TreeListResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *TreeListResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1380,13 +5910,166 @@ func (x *TreeListResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *TreeListResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *TreeListResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *TreeListResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *TreeListResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *TreeListResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "TreeListResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(TreeListResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *TreeListResponse) GetBody() *TreeListResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *TreeListResponse) SetBody(v *TreeListResponse_Body) { + x.Body = v +} +func (x *TreeListResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *TreeListResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *TreeListResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *TreeListResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *TreeListResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *TreeListResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *TreeListResponse_Body + f = new(TreeListResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ApplyRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + Operation *LogMove `json:"operation"` +} + +var ( + _ encoding.ProtoMarshaler = (*ApplyRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ApplyRequest_Body)(nil) + _ json.Marshaler = (*ApplyRequest_Body)(nil) + _ json.Unmarshaler = (*ApplyRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1400,28 +6083,187 @@ func (x *ApplyRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ApplyRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.NestedStructureMarshal(3, buf[offset:], x.Operation) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ApplyRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ApplyRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + if x.Operation != nil && x.Operation.StableSize() != 0 { + x.Operation.EmitProtobuf(mm.AppendMessage(3)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ApplyRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ApplyRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // Operation + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Operation") + } + x.Operation = new(LogMove) + if err := x.Operation.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ApplyRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *ApplyRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *ApplyRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *ApplyRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *ApplyRequest_Body) GetOperation() *LogMove { + if x != nil { + return x.Operation + } + return nil +} +func (x *ApplyRequest_Body) SetOperation(v *LogMove) { + x.Operation = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ApplyRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ApplyRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"operation\":" + out.RawString(prefix) + x.Operation.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ApplyRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ApplyRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "operation": + { + var f *LogMove + f = new(LogMove) + f.UnmarshalEasyJSON(in) + x.Operation = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ApplyRequest struct { + Body *ApplyRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ApplyRequest)(nil) + _ encoding.ProtoUnmarshaler = (*ApplyRequest)(nil) + _ json.Marshaler = (*ApplyRequest)(nil) + _ json.Unmarshaler = (*ApplyRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1434,27 +6276,6 @@ func (x *ApplyRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ApplyRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1470,13 +6291,163 @@ func (x *ApplyRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ApplyRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ApplyRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ApplyRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ApplyRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ApplyRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ApplyRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ApplyRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ApplyRequest) GetBody() *ApplyRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ApplyRequest) SetBody(v *ApplyRequest_Body) { + x.Body = v +} +func (x *ApplyRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ApplyRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ApplyRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ApplyRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ApplyRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ApplyRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ApplyRequest_Body + f = new(ApplyRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ApplyResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*ApplyResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ApplyResponse_Body)(nil) + _ json.Marshaler = (*ApplyResponse_Body)(nil) + _ json.Unmarshaler = (*ApplyResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1487,18 +6458,93 @@ func (x *ApplyResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ApplyResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ApplyResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ApplyResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ApplyResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ApplyResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ApplyResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ApplyResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ApplyResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ApplyResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ApplyResponse struct { + Body *ApplyResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ApplyResponse)(nil) + _ encoding.ProtoUnmarshaler = (*ApplyResponse)(nil) + _ json.Marshaler = (*ApplyResponse)(nil) + _ json.Unmarshaler = (*ApplyResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1511,27 +6557,6 @@ func (x *ApplyResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *ApplyResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1547,13 +6572,167 @@ func (x *ApplyResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *ApplyResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *ApplyResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ApplyResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *ApplyResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ApplyResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ApplyResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ApplyResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ApplyResponse) GetBody() *ApplyResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ApplyResponse) SetBody(v *ApplyResponse_Body) { + x.Body = v +} +func (x *ApplyResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ApplyResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ApplyResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ApplyResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ApplyResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ApplyResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ApplyResponse_Body + f = new(ApplyResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetOpLogRequest_Body struct { + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + Height uint64 `json:"height"` + Count uint64 `json:"count"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetOpLogRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetOpLogRequest_Body)(nil) + _ json.Marshaler = (*GetOpLogRequest_Body)(nil) + _ json.Unmarshaler = (*GetOpLogRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1568,29 +6747,212 @@ func (x *GetOpLogRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetOpLogRequest_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.ContainerId) - offset += proto.StringMarshal(2, buf[offset:], x.TreeId) - offset += proto.UInt64Marshal(3, buf[offset:], x.Height) - offset += proto.UInt64Marshal(4, buf[offset:], x.Count) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetOpLogRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetOpLogRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ContainerId) != 0 { + mm.AppendBytes(1, x.ContainerId) + } + if len(x.TreeId) != 0 { + mm.AppendString(2, x.TreeId) + } + if x.Height != 0 { + mm.AppendUint64(3, x.Height) + } + if x.Count != 0 { + mm.AppendUint64(4, x.Count) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetOpLogRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetOpLogRequest_Body") + } + switch fc.FieldNum { + case 1: // ContainerId + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + case 2: // TreeId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TreeId") + } + x.TreeId = data + case 3: // Height + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Height") + } + x.Height = data + case 4: // Count + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Count") + } + x.Count = data + } + } + return nil +} +func (x *GetOpLogRequest_Body) GetContainerId() []byte { + if x != nil { + return x.ContainerId + } + return nil +} +func (x *GetOpLogRequest_Body) SetContainerId(v []byte) { + x.ContainerId = v +} +func (x *GetOpLogRequest_Body) GetTreeId() string { + if x != nil { + return x.TreeId + } + return "" +} +func (x *GetOpLogRequest_Body) SetTreeId(v string) { + x.TreeId = v +} +func (x *GetOpLogRequest_Body) GetHeight() uint64 { + if x != nil { + return x.Height + } + return 0 +} +func (x *GetOpLogRequest_Body) SetHeight(v uint64) { + x.Height = v +} +func (x *GetOpLogRequest_Body) GetCount() uint64 { + if x != nil { + return x.Count + } + return 0 +} +func (x *GetOpLogRequest_Body) SetCount(v uint64) { + x.Count = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetOpLogRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetOpLogRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"containerId\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.ContainerId) + } + { + const prefix string = ",\"treeId\":" + out.RawString(prefix) + out.String(x.TreeId) + } + { + const prefix string = ",\"height\":" + out.RawString(prefix) + out.Uint64(x.Height) + } + { + const prefix string = ",\"count\":" + out.RawString(prefix) + out.Uint64(x.Count) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetOpLogRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetOpLogRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "containerId": + { + var f []byte + f = in.Bytes() + x.ContainerId = f + } + case "treeId": + { + var f string + f = in.String() + x.TreeId = f + } + case "height": + { + var f uint64 + f = in.Uint64() + x.Height = f + } + case "count": + { + var f uint64 + f = in.Uint64() + x.Count = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetOpLogRequest struct { + Body *GetOpLogRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetOpLogRequest)(nil) + _ encoding.ProtoUnmarshaler = (*GetOpLogRequest)(nil) + _ json.Marshaler = (*GetOpLogRequest)(nil) + _ json.Unmarshaler = (*GetOpLogRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1603,27 +6965,6 @@ func (x *GetOpLogRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetOpLogRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1639,13 +6980,164 @@ func (x *GetOpLogRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetOpLogRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetOpLogRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetOpLogRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetOpLogRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetOpLogRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetOpLogRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetOpLogRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetOpLogRequest) GetBody() *GetOpLogRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetOpLogRequest) SetBody(v *GetOpLogRequest_Body) { + x.Body = v +} +func (x *GetOpLogRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetOpLogRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetOpLogRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetOpLogRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetOpLogRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetOpLogRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetOpLogRequest_Body + f = new(GetOpLogRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetOpLogResponse_Body struct { + Operation *LogMove `json:"operation"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetOpLogResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*GetOpLogResponse_Body)(nil) + _ json.Marshaler = (*GetOpLogResponse_Body)(nil) + _ json.Unmarshaler = (*GetOpLogResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1657,26 +7149,129 @@ func (x *GetOpLogResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetOpLogResponse_Body) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Operation) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetOpLogResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetOpLogResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Operation != nil && x.Operation.StableSize() != 0 { + x.Operation.EmitProtobuf(mm.AppendMessage(1)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetOpLogResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetOpLogResponse_Body") + } + switch fc.FieldNum { + case 1: // Operation + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Operation") + } + x.Operation = new(LogMove) + if err := x.Operation.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetOpLogResponse_Body) GetOperation() *LogMove { + if x != nil { + return x.Operation + } + return nil +} +func (x *GetOpLogResponse_Body) SetOperation(v *LogMove) { + x.Operation = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetOpLogResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetOpLogResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"operation\":" + out.RawString(prefix[1:]) + x.Operation.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetOpLogResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetOpLogResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "operation": + { + var f *LogMove + f = new(LogMove) + f.UnmarshalEasyJSON(in) + x.Operation = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type GetOpLogResponse struct { + Body *GetOpLogResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*GetOpLogResponse)(nil) + _ encoding.ProtoUnmarshaler = (*GetOpLogResponse)(nil) + _ json.Marshaler = (*GetOpLogResponse)(nil) + _ json.Unmarshaler = (*GetOpLogResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1689,27 +7284,6 @@ func (x *GetOpLogResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *GetOpLogResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1725,13 +7299,163 @@ func (x *GetOpLogResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *GetOpLogResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *GetOpLogResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *GetOpLogResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *GetOpLogResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *GetOpLogResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "GetOpLogResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(GetOpLogResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *GetOpLogResponse) GetBody() *GetOpLogResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *GetOpLogResponse) SetBody(v *GetOpLogResponse_Body) { + x.Body = v +} +func (x *GetOpLogResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *GetOpLogResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *GetOpLogResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *GetOpLogResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *GetOpLogResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *GetOpLogResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *GetOpLogResponse_Body + f = new(GetOpLogResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthcheckResponse_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*HealthcheckResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*HealthcheckResponse_Body)(nil) + _ json.Marshaler = (*HealthcheckResponse_Body)(nil) + _ json.Unmarshaler = (*HealthcheckResponse_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1742,18 +7466,93 @@ func (x *HealthcheckResponse_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthcheckResponse_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthcheckResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthcheckResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthcheckResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthcheckResponse_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthcheckResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthcheckResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthcheckResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthcheckResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthcheckResponse struct { + Body *HealthcheckResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*HealthcheckResponse)(nil) + _ encoding.ProtoUnmarshaler = (*HealthcheckResponse)(nil) + _ json.Marshaler = (*HealthcheckResponse)(nil) + _ json.Unmarshaler = (*HealthcheckResponse)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1766,27 +7565,6 @@ func (x *HealthcheckResponse) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthcheckResponse) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1802,13 +7580,163 @@ func (x *HealthcheckResponse) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *HealthcheckResponse) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *HealthcheckResponse) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthcheckResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthcheckResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthcheckResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthcheckResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(HealthcheckResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *HealthcheckResponse) GetBody() *HealthcheckResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *HealthcheckResponse) SetBody(v *HealthcheckResponse_Body) { + x.Body = v +} +func (x *HealthcheckResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *HealthcheckResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthcheckResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthcheckResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthcheckResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthcheckResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *HealthcheckResponse_Body + f = new(HealthcheckResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthcheckRequest_Body struct { +} + +var ( + _ encoding.ProtoMarshaler = (*HealthcheckRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*HealthcheckRequest_Body)(nil) + _ json.Marshaler = (*HealthcheckRequest_Body)(nil) + _ json.Unmarshaler = (*HealthcheckRequest_Body)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1819,18 +7747,93 @@ func (x *HealthcheckRequest_Body) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthcheckRequest_Body) StableMarshal(buf []byte) []byte { - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthcheckRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *HealthcheckRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthcheckRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthcheckRequest_Body") + } + switch fc.FieldNum { + } + } + return nil +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthcheckRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthcheckRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthcheckRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthcheckRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type HealthcheckRequest struct { + Body *HealthcheckRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*HealthcheckRequest)(nil) + _ encoding.ProtoUnmarshaler = (*HealthcheckRequest)(nil) + _ json.Marshaler = (*HealthcheckRequest)(nil) + _ json.Unmarshaler = (*HealthcheckRequest)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -1843,27 +7846,6 @@ func (x *HealthcheckRequest) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *HealthcheckRequest) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.NestedStructureMarshal(1, buf[offset:], x.Body) - offset += proto.NestedStructureMarshal(2, buf[offset:], x.Signature) - return buf -} - // ReadSignedData fills buf with signed data of x. // If buffer length is less than x.SignedDataSize(), new buffer is allocated. // @@ -1879,9 +7861,149 @@ func (x *HealthcheckRequest) SignedDataSize() int { // // Structures with the same field values have the same signed data size. func (x *HealthcheckRequest) ReadSignedData(buf []byte) ([]byte, error) { - return x.GetBody().StableMarshal(buf), nil + return x.GetBody().MarshalProtobuf(buf), nil } -func (x *HealthcheckRequest) SetSignature(sig *Signature) { - x.Signature = sig +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *HealthcheckRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *HealthcheckRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil && x.Body.StableSize() != 0 { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil && x.Signature.StableSize() != 0 { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *HealthcheckRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "HealthcheckRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(HealthcheckRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *HealthcheckRequest) GetBody() *HealthcheckRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *HealthcheckRequest) SetBody(v *HealthcheckRequest_Body) { + x.Body = v +} +func (x *HealthcheckRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *HealthcheckRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *HealthcheckRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *HealthcheckRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *HealthcheckRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *HealthcheckRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *HealthcheckRequest_Body + f = new(HealthcheckRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } } diff --git a/pkg/services/tree/types.pb.go b/pkg/services/tree/types.pb.go deleted file mode 100644 index 6464ccb776..0000000000 --- a/pkg/services/tree/types.pb.go +++ /dev/null @@ -1,320 +0,0 @@ -//* -// Auxiliary structures to use with tree service. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.33.0 -// protoc v4.25.0 -// source: pkg/services/tree/types.proto - -package tree - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// KeyValue represents key-value pair attached to an object. -type KeyValue struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Attribute name. - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - // Attribute value. - Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *KeyValue) Reset() { - *x = KeyValue{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_types_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *KeyValue) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*KeyValue) ProtoMessage() {} - -func (x *KeyValue) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_types_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use KeyValue.ProtoReflect.Descriptor instead. -func (*KeyValue) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_types_proto_rawDescGZIP(), []int{0} -} - -func (x *KeyValue) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *KeyValue) GetValue() []byte { - if x != nil { - return x.Value - } - return nil -} - -// LogMove represents log-entry for a single move operation. -type LogMove struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the parent node. - ParentId uint64 `protobuf:"varint,1,opt,name=parent_id,json=parentID,proto3" json:"parent_id,omitempty"` - // Node meta information, including operation timestamp. - Meta []byte `protobuf:"bytes,2,opt,name=meta,proto3" json:"meta,omitempty"` - // ID of the node to move. - ChildId uint64 `protobuf:"varint,3,opt,name=child_id,json=childID,proto3" json:"child_id,omitempty"` -} - -func (x *LogMove) Reset() { - *x = LogMove{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_types_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LogMove) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LogMove) ProtoMessage() {} - -func (x *LogMove) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_types_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LogMove.ProtoReflect.Descriptor instead. -func (*LogMove) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_types_proto_rawDescGZIP(), []int{1} -} - -func (x *LogMove) GetParentId() uint64 { - if x != nil { - return x.ParentId - } - return 0 -} - -func (x *LogMove) GetMeta() []byte { - if x != nil { - return x.Meta - } - return nil -} - -func (x *LogMove) GetChildId() uint64 { - if x != nil { - return x.ChildId - } - return 0 -} - -// Signature of a message. -type Signature struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Serialized public key as defined in FrostFS API. - Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - // Signature of a message body. - Sign []byte `protobuf:"bytes,2,opt,name=sign,json=signature,proto3" json:"sign,omitempty"` -} - -func (x *Signature) Reset() { - *x = Signature{} - if protoimpl.UnsafeEnabled { - mi := &file_pkg_services_tree_types_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Signature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Signature) ProtoMessage() {} - -func (x *Signature) ProtoReflect() protoreflect.Message { - mi := &file_pkg_services_tree_types_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Signature.ProtoReflect.Descriptor instead. -func (*Signature) Descriptor() ([]byte, []int) { - return file_pkg_services_tree_types_proto_rawDescGZIP(), []int{2} -} - -func (x *Signature) GetKey() []byte { - if x != nil { - return x.Key - } - return nil -} - -func (x *Signature) GetSign() []byte { - if x != nil { - return x.Sign - } - return nil -} - -var File_pkg_services_tree_types_proto protoreflect.FileDescriptor - -var file_pkg_services_tree_types_proto_rawDesc = []byte{ - 0x0a, 0x1d, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x74, - 0x72, 0x65, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x04, 0x74, 0x72, 0x65, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x55, 0x0a, 0x07, 0x4c, 0x6f, 0x67, - 0x4d, 0x6f, 0x76, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, - 0x44, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x04, 0x6d, 0x65, 0x74, 0x61, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x49, 0x44, - 0x22, 0x36, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x17, 0x0a, 0x04, 0x73, 0x69, 0x67, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x2e, - 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, 0x73, 0x2e, 0x69, 0x6e, 0x66, 0x6f, 0x2f, 0x54, 0x72, 0x75, - 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x4c, 0x61, 0x62, 0x2f, 0x66, 0x72, 0x6f, 0x73, 0x74, 0x66, - 0x73, 0x2d, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_pkg_services_tree_types_proto_rawDescOnce sync.Once - file_pkg_services_tree_types_proto_rawDescData = file_pkg_services_tree_types_proto_rawDesc -) - -func file_pkg_services_tree_types_proto_rawDescGZIP() []byte { - file_pkg_services_tree_types_proto_rawDescOnce.Do(func() { - file_pkg_services_tree_types_proto_rawDescData = protoimpl.X.CompressGZIP(file_pkg_services_tree_types_proto_rawDescData) - }) - return file_pkg_services_tree_types_proto_rawDescData -} - -var file_pkg_services_tree_types_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_pkg_services_tree_types_proto_goTypes = []interface{}{ - (*KeyValue)(nil), // 0: tree.KeyValue - (*LogMove)(nil), // 1: tree.LogMove - (*Signature)(nil), // 2: tree.Signature -} -var file_pkg_services_tree_types_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_pkg_services_tree_types_proto_init() } -func file_pkg_services_tree_types_proto_init() { - if File_pkg_services_tree_types_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_pkg_services_tree_types_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyValue); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_types_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LogMove); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_pkg_services_tree_types_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Signature); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_pkg_services_tree_types_proto_rawDesc, - NumEnums: 0, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_pkg_services_tree_types_proto_goTypes, - DependencyIndexes: file_pkg_services_tree_types_proto_depIdxs, - MessageInfos: file_pkg_services_tree_types_proto_msgTypes, - }.Build() - File_pkg_services_tree_types_proto = out.File - file_pkg_services_tree_types_proto_rawDesc = nil - file_pkg_services_tree_types_proto_goTypes = nil - file_pkg_services_tree_types_proto_depIdxs = nil -} diff --git a/pkg/services/tree/types_frostfs.pb.go b/pkg/services/tree/types_frostfs.pb.go index 707fcc3ccd..4399f8a8b1 100644 --- a/pkg/services/tree/types_frostfs.pb.go +++ b/pkg/services/tree/types_frostfs.pb.go @@ -2,7 +2,28 @@ package tree -import "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" +import ( + json "encoding/json" + fmt "fmt" + pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + easyproto "github.com/VictoriaMetrics/easyproto" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" +) + +type KeyValue struct { + Key string `json:"key"` + Value []byte `json:"value"` +} + +var ( + _ encoding.ProtoMarshaler = (*KeyValue)(nil) + _ encoding.ProtoUnmarshaler = (*KeyValue)(nil) + _ json.Marshaler = (*KeyValue)(nil) + _ json.Unmarshaler = (*KeyValue)(nil) +) // StableSize returns the size of x in protobuf format. // @@ -16,27 +37,155 @@ func (x *KeyValue) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *KeyValue) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.StringMarshal(1, buf[offset:], x.Key) - offset += proto.BytesMarshal(2, buf[offset:], x.Value) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *KeyValue) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *KeyValue) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Key) != 0 { + mm.AppendString(1, x.Key) + } + if len(x.Value) != 0 { + mm.AppendBytes(2, x.Value) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *KeyValue) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "KeyValue") + } + switch fc.FieldNum { + case 1: // Key + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Key") + } + x.Key = data + case 2: // Value + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Value") + } + x.Value = data + } + } + return nil +} +func (x *KeyValue) GetKey() string { + if x != nil { + return x.Key + } + return "" +} +func (x *KeyValue) SetKey(v string) { + x.Key = v +} +func (x *KeyValue) GetValue() []byte { + if x != nil { + return x.Value + } + return nil +} +func (x *KeyValue) SetValue(v []byte) { + x.Value = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *KeyValue) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *KeyValue) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"key\":" + out.RawString(prefix[1:]) + out.String(x.Key) + } + { + const prefix string = ",\"value\":" + out.RawString(prefix) + out.Base64Bytes(x.Value) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *KeyValue) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *KeyValue) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "key": + { + var f string + f = in.String() + x.Key = f + } + case "value": + { + var f []byte + f = in.Bytes() + x.Value = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type LogMove struct { + ParentId uint64 `json:"parentID"` + Meta []byte `json:"meta"` + ChildId uint64 `json:"childID"` +} + +var ( + _ encoding.ProtoMarshaler = (*LogMove)(nil) + _ encoding.ProtoUnmarshaler = (*LogMove)(nil) + _ json.Marshaler = (*LogMove)(nil) + _ json.Unmarshaler = (*LogMove)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -50,28 +199,183 @@ func (x *LogMove) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *LogMove) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.UInt64Marshal(1, buf[offset:], x.ParentId) - offset += proto.BytesMarshal(2, buf[offset:], x.Meta) - offset += proto.UInt64Marshal(3, buf[offset:], x.ChildId) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *LogMove) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst } +func (x *LogMove) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.ParentId != 0 { + mm.AppendUint64(1, x.ParentId) + } + if len(x.Meta) != 0 { + mm.AppendBytes(2, x.Meta) + } + if x.ChildId != 0 { + mm.AppendUint64(3, x.ChildId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *LogMove) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "LogMove") + } + switch fc.FieldNum { + case 1: // ParentId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ParentId") + } + x.ParentId = data + case 2: // Meta + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Meta") + } + x.Meta = data + case 3: // ChildId + data, ok := fc.Uint64() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ChildId") + } + x.ChildId = data + } + } + return nil +} +func (x *LogMove) GetParentId() uint64 { + if x != nil { + return x.ParentId + } + return 0 +} +func (x *LogMove) SetParentId(v uint64) { + x.ParentId = v +} +func (x *LogMove) GetMeta() []byte { + if x != nil { + return x.Meta + } + return nil +} +func (x *LogMove) SetMeta(v []byte) { + x.Meta = v +} +func (x *LogMove) GetChildId() uint64 { + if x != nil { + return x.ChildId + } + return 0 +} +func (x *LogMove) SetChildId(v uint64) { + x.ChildId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *LogMove) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *LogMove) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"parentID\":" + out.RawString(prefix[1:]) + out.Uint64(x.ParentId) + } + { + const prefix string = ",\"meta\":" + out.RawString(prefix) + out.Base64Bytes(x.Meta) + } + { + const prefix string = ",\"childID\":" + out.RawString(prefix) + out.Uint64(x.ChildId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *LogMove) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *LogMove) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "parentID": + { + var f uint64 + f = in.Uint64() + x.ParentId = f + } + case "meta": + { + var f []byte + f = in.Bytes() + x.Meta = f + } + case "childID": + { + var f uint64 + f = in.Uint64() + x.ChildId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type Signature struct { + Key []byte `json:"key"` + Sign []byte `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*Signature)(nil) + _ encoding.ProtoUnmarshaler = (*Signature)(nil) + _ json.Marshaler = (*Signature)(nil) + _ json.Unmarshaler = (*Signature)(nil) +) + // StableSize returns the size of x in protobuf format. // // Structures with the same field values have the same binary size. @@ -84,23 +388,138 @@ func (x *Signature) StableSize() (size int) { return size } -// StableMarshal marshals x in protobuf binary format with stable field order. -// -// If buffer length is less than x.StableSize(), new buffer is allocated. -// -// Returns any error encountered which did not allow writing the data completely. -// Otherwise, returns the buffer in which the data is written. -// -// Structures with the same field values have the same binary format. -func (x *Signature) StableMarshal(buf []byte) []byte { - if x == nil { - return []byte{} - } - if buf == nil { - buf = make([]byte, x.StableSize()) - } - var offset int - offset += proto.BytesMarshal(1, buf[offset:], x.Key) - offset += proto.BytesMarshal(2, buf[offset:], x.Sign) - return buf +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *Signature) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *Signature) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Key) != 0 { + mm.AppendBytes(1, x.Key) + } + if len(x.Sign) != 0 { + mm.AppendBytes(2, x.Sign) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *Signature) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "Signature") + } + switch fc.FieldNum { + case 1: // Key + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Key") + } + x.Key = data + case 2: // Sign + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Sign") + } + x.Sign = data + } + } + return nil +} +func (x *Signature) GetKey() []byte { + if x != nil { + return x.Key + } + return nil +} +func (x *Signature) SetKey(v []byte) { + x.Key = v +} +func (x *Signature) GetSign() []byte { + if x != nil { + return x.Sign + } + return nil +} +func (x *Signature) SetSign(v []byte) { + x.Sign = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *Signature) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *Signature) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"key\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.Key) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + out.Base64Bytes(x.Sign) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *Signature) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *Signature) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "key": + { + var f []byte + f = in.Bytes() + x.Key = f + } + case "signature": + { + var f []byte + f = in.Bytes() + x.Sign = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } } From 15dae8685e48bf9c271039bd109a21a1612e4a3b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 19 Aug 2024 17:13:39 +0300 Subject: [PATCH 0752/1413] [#1323] metabase: Drop ownerID index Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/put.go | 9 -- pkg/local_object_storage/metabase/select.go | 8 +- .../metabase/select_test.go | 106 ++++++++++++++++++ pkg/local_object_storage/metabase/util.go | 9 +- 4 files changed, 113 insertions(+), 19 deletions(-) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index f351cb485b..366cc13614 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -379,15 +379,6 @@ func updateFKBTIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun objKey := objectKey(id, make([]byte, objectKeySize)) key := make([]byte, bucketKeySize) - err := f(tx, namedBucketItem{ - name: ownerBucketName(cnr, key), - key: []byte(obj.OwnerID().EncodeToString()), - val: objKey, - }) - if err != nil { - return err - } - var attrs []objectSDK.Attribute if obj.ECHeader() != nil { attrs = obj.ECHeader().ParentAttributes() diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 3a4d7a2273..cc40b81ba2 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -196,8 +196,7 @@ func (db *DB) selectFastFilter( case v2object.FilterHeaderObjectID: db.selectObjectID(tx, f, cnr, to, fNum, currEpoch) case v2object.FilterHeaderOwnerID: - bucketName := ownerBucketName(cnr, bucketName) - db.selectFromFKBT(tx, bucketName, f, to, fNum) + return // moved to slow filters case v2object.FilterHeaderPayloadHash: bucketName := payloadHashBucketName(cnr, bucketName) db.selectFromList(tx, bucketName, f, to, fNum) @@ -510,6 +509,8 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc case v2object.FilterHeaderPayloadLength: data = make([]byte, 8) binary.LittleEndian.PutUint64(data, obj.PayloadSize()) + case v2object.FilterHeaderOwnerID: + data = []byte(obj.OwnerID().EncodeToString()) default: continue // ignore unknown search attributes } @@ -544,7 +545,8 @@ func groupFilters(filters objectSDK.SearchFilters) (filterGroup, error) { v2object.FilterHeaderVersion, v2object.FilterHeaderCreationEpoch, v2object.FilterHeaderPayloadLength, - v2object.FilterHeaderHomomorphicHash: + v2object.FilterHeaderHomomorphicHash, + v2object.FilterHeaderOwnerID: res.slowFilters = append(res.slowFilters, filters[i]) default: // fast filters or user attributes if unknown res.fastFilters = append(res.fastFilters, filters[i]) diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 8f9294d072..4fbc5910ea 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -633,6 +633,112 @@ func TestDB_SelectObjectID(t *testing.T) { }) } +func TestDB_SelectOwnerID(t *testing.T) { + t.Parallel() + + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + + // prepare + + parent := testutil.GenerateObjectWithCID(cnr) + + regular := testutil.GenerateObjectWithCID(cnr) + idParent, _ := parent.ID() + regular.SetParentID(idParent) + regular.SetParent(parent) + + err := putBig(db, regular) + require.NoError(t, err) + + ts := testutil.GenerateObjectWithCID(cnr) + ts.SetType(objectSDK.TypeTombstone) + err = putBig(db, ts) + require.NoError(t, err) + + lock := testutil.GenerateObjectWithCID(cnr) + lock.SetType(objectSDK.TypeLock) + err = putBig(db, lock) + require.NoError(t, err) + + t.Run("not found objects", func(t *testing.T) { + raw := testutil.GenerateObjectWithCID(cnr) + + fs := objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringEqual, raw.OwnerID()) + + testSelect(t, db, cnr, fs) + + fs = objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringNotEqual, raw.OwnerID()) + + testSelect(t, db, cnr, fs, + object.AddressOf(regular), + object.AddressOf(parent), + object.AddressOf(ts), + object.AddressOf(lock), + ) + }) + + t.Run("regular objects", func(t *testing.T) { + fs := objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringEqual, regular.OwnerID()) + testSelect(t, db, cnr, fs, object.AddressOf(regular)) + + fs = objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringNotEqual, regular.OwnerID()) + testSelect(t, db, cnr, fs, + object.AddressOf(parent), + object.AddressOf(ts), + object.AddressOf(lock), + ) + }) + + t.Run("tombstone objects", func(t *testing.T) { + fs := objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringEqual, ts.OwnerID()) + testSelect(t, db, cnr, fs, object.AddressOf(ts)) + + fs = objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringNotEqual, ts.OwnerID()) + testSelect(t, db, cnr, fs, + object.AddressOf(regular), + object.AddressOf(parent), + object.AddressOf(lock), + ) + }) + + t.Run("parent objects", func(t *testing.T) { + fs := objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringEqual, parent.OwnerID()) + testSelect(t, db, cnr, fs, object.AddressOf(parent)) + + fs = objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringNotEqual, parent.OwnerID()) + testSelect(t, db, cnr, fs, + object.AddressOf(regular), + object.AddressOf(ts), + object.AddressOf(lock), + ) + }) + + t.Run("lock objects", func(t *testing.T) { + fs := objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringEqual, lock.OwnerID()) + testSelect(t, db, cnr, fs, object.AddressOf(lock)) + + fs = objectSDK.SearchFilters{} + fs.AddObjectOwnerIDFilter(objectSDK.MatchStringNotEqual, lock.OwnerID()) + testSelect(t, db, cnr, fs, + object.AddressOf(regular), + object.AddressOf(parent), + object.AddressOf(ts), + ) + }) +} + type testTarget struct { objects []*objectSDK.Object } diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index 9249ae49b4..f9f9898e93 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -89,10 +89,10 @@ const ( // FKBT index buckets. // ==================== - // ownerPrefix is used for prefixing FKBT index buckets mapping owner to object IDs. + // ownerPrefix was used for prefixing FKBT index buckets mapping owner to object IDs. // Key: owner ID // Value: bucket containing object IDs as keys - ownerPrefix + _ // userAttributePrefix is used for prefixing FKBT index buckets containing objects. // Key: attribute value // Value: bucket containing object IDs as keys @@ -180,11 +180,6 @@ func rootBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, rootPrefix, key) } -// ownerBucketName returns _ownerid. -func ownerBucketName(cnr cid.ID, key []byte) []byte { - return bucketName(cnr, ownerPrefix, key) -} - // parentBucketName returns _parent. func parentBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, parentPrefix, key) From 2542d4f5dfda623a42ae144cc28ebfeb3d16ea89 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 19 Aug 2024 17:20:55 +0300 Subject: [PATCH 0753/1413] [#1323] metabase: Drop payload checksum index Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/put.go | 12 ------------ pkg/local_object_storage/metabase/select.go | 12 +++++++----- pkg/local_object_storage/metabase/util.go | 9 ++------- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 366cc13614..3fa79f1e20 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -297,18 +297,6 @@ func updateListIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun objKey := objectKey(idObj, make([]byte, objectKeySize)) bucketName := make([]byte, bucketKeySize) - cs, _ := obj.PayloadChecksum() - - // index payload hashes - err := f(tx, namedBucketItem{ - name: payloadHashBucketName(cnr, bucketName), - key: cs.Value(), - val: objKey, - }) - if err != nil { - return err - } - idParent, ok := obj.ParentID() // index parent ids diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index cc40b81ba2..720b7b5b9b 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -195,11 +195,9 @@ func (db *DB) selectFastFilter( switch f.Header() { case v2object.FilterHeaderObjectID: db.selectObjectID(tx, f, cnr, to, fNum, currEpoch) - case v2object.FilterHeaderOwnerID: + case v2object.FilterHeaderOwnerID, + v2object.FilterHeaderPayloadHash: return // moved to slow filters - case v2object.FilterHeaderPayloadHash: - bucketName := payloadHashBucketName(cnr, bucketName) - db.selectFromList(tx, bucketName, f, to, fNum) case v2object.FilterHeaderObjectType: for _, bucketName := range bucketNamesForType(cnr, f.Operation(), f.Value()) { selectAllFromBucket(tx, bucketName, to, fNum) @@ -511,6 +509,9 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc binary.LittleEndian.PutUint64(data, obj.PayloadSize()) case v2object.FilterHeaderOwnerID: data = []byte(obj.OwnerID().EncodeToString()) + case v2object.FilterHeaderPayloadHash: + cs, _ := obj.PayloadChecksum() + data = cs.Value() default: continue // ignore unknown search attributes } @@ -546,7 +547,8 @@ func groupFilters(filters objectSDK.SearchFilters) (filterGroup, error) { v2object.FilterHeaderCreationEpoch, v2object.FilterHeaderPayloadLength, v2object.FilterHeaderHomomorphicHash, - v2object.FilterHeaderOwnerID: + v2object.FilterHeaderOwnerID, + v2object.FilterHeaderPayloadHash: res.slowFilters = append(res.slowFilters, filters[i]) default: // fast filters or user attributes if unknown res.fastFilters = append(res.fastFilters, filters[i]) diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index f9f9898e93..ebf1713d0e 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -102,10 +102,10 @@ const ( // List index buckets. // ==================== - // payloadHashPrefix is used for prefixing List index buckets mapping payload hash to a list of object IDs. + // payloadHashPrefix was used for prefixing List index buckets mapping payload hash to a list of object IDs. // Key: payload hash // Value: list of object IDs - payloadHashPrefix + _ // parentPrefix is used for prefixing List index buckets mapping parent ID to a list of children IDs. // Key: parent ID // Value: list of object IDs @@ -170,11 +170,6 @@ func cidFromAttributeBucket(val []byte, attributeKey string) []byte { return val[1:bucketKeySize] } -// payloadHashBucketName returns _payloadhash. -func payloadHashBucketName(cnr cid.ID, key []byte) []byte { - return bucketName(cnr, payloadHashPrefix, key) -} - // rootBucketName returns _root. func rootBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, rootPrefix, key) From 7bf20c9f1f06975a53184c0803dbc7bc5ca4eaf5 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 20 Aug 2024 11:59:42 +0300 Subject: [PATCH 0754/1413] [#1323] metabase: Add expiration epoch buckets Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/control.go | 1 + pkg/local_object_storage/metabase/delete.go | 11 ++ .../metabase/delete_ec_test.go | 3 +- pkg/local_object_storage/metabase/exists.go | 26 ++-- pkg/local_object_storage/metabase/expired.go | 118 +++++------------- pkg/local_object_storage/metabase/get.go | 6 +- .../metabase/iterators.go | 81 ++++-------- pkg/local_object_storage/metabase/put.go | 41 ++++++ pkg/local_object_storage/metabase/select.go | 7 +- pkg/local_object_storage/metabase/util.go | 53 ++++++-- pkg/local_object_storage/shard/gc_test.go | 4 +- 11 files changed, 181 insertions(+), 170 deletions(-) diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 891a1e9b22..d6546d922c 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -29,6 +29,7 @@ var ( string(garbageBucketName): {}, string(shardInfoBucket): {}, string(bucketNameLocked): {}, + string(expEpochToObjectBucketName): {}, } // deprecatedBuckets buckets that are not used anymore. diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index ae10564a8a..683bd445f2 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -478,6 +478,17 @@ func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error key: objKey, }) + if expEpoch, ok := hasExpirationEpoch(obj); ok { + delUniqueIndexItem(tx, namedBucketItem{ + name: expEpochToObjectBucketName, + key: expirationEpochKey(expEpoch, cnr, addr.Object()), + }) + delUniqueIndexItem(tx, namedBucketItem{ + name: objectToExpirationEpochBucketName(cnr, make([]byte, bucketKeySize)), + key: objKey, + }) + } + return nil } diff --git a/pkg/local_object_storage/metabase/delete_ec_test.go b/pkg/local_object_storage/metabase/delete_ec_test.go index 0e627f0959..66c79ecd7c 100644 --- a/pkg/local_object_storage/metabase/delete_ec_test.go +++ b/pkg/local_object_storage/metabase/delete_ec_test.go @@ -418,7 +418,8 @@ func testVerifyNoObjectDataLeft(tx *bbolt.Tx) error { return tx.ForEach(func(name []byte, b *bbolt.Bucket) error { if bytes.Equal(name, shardInfoBucket) || bytes.Equal(name, containerCounterBucketName) || - bytes.Equal(name, containerVolumeBucketName) { + bytes.Equal(name, containerVolumeBucketName) || + bytes.Equal(name, expEpochToObjectBucketName) { return nil } return testBucketEmpty(name, b) diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index 153d921103..2e1b1dce87 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -5,7 +5,6 @@ import ( "fmt" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -96,7 +95,11 @@ func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, parent oid.Address, currEpo locked = objectLocked(tx, parent.Container(), parent.Object()) } // check graveyard and object expiration first - switch objectStatus(tx, addr, currEpoch) { + st, err := objectStatus(tx, addr, currEpoch) + if err != nil { + return false, false, err + } + switch st { case 1: return false, locked, logicerr.Wrap(new(apistatus.ObjectNotFound)) case 2: @@ -138,30 +141,25 @@ func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, parent oid.Address, currEpo // - 1 if object with GC mark; // - 2 if object is covered with tombstone; // - 3 if object is expired. -func objectStatus(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) uint8 { +func objectStatus(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (uint8, error) { // locked object could not be removed/marked with GC/expired if objectLocked(tx, addr.Container(), addr.Object()) { - return 0 + return 0, nil } - // we check only if the object is expired in the current - // epoch since it is considered the only corner case: the - // GC is expected to collect all the objects that have - // expired previously for less than the one epoch duration - - expired := isExpiredWithAttribute(tx, objectV2.SysAttributeExpEpoch, addr, currEpoch) - if !expired { - expired = isExpiredWithAttribute(tx, objectV2.SysAttributeExpEpochNeoFS, addr, currEpoch) + expired, err := isExpired(tx, addr, currEpoch) + if err != nil { + return 0, err } if expired { - return 3 + return 3, nil } graveyardBkt := tx.Bucket(graveyardBucketName) garbageBkt := tx.Bucket(garbageBucketName) addrKey := addressKey(addr, make([]byte, addressKeySize)) - return inGraveyardWithKey(addrKey, graveyardBkt, garbageBkt) + return inGraveyardWithKey(addrKey, graveyardBkt, garbageBkt), nil } func inGraveyardWithKey(addrKey []byte, graveyard, garbageBCK *bbolt.Bucket) uint8 { diff --git a/pkg/local_object_storage/metabase/expired.go b/pkg/local_object_storage/metabase/expired.go index aa2cb6f20e..68144d8b18 100644 --- a/pkg/local_object_storage/metabase/expired.go +++ b/pkg/local_object_storage/metabase/expired.go @@ -2,12 +2,11 @@ package meta import ( "context" + "encoding/binary" "errors" - "fmt" "strconv" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -17,6 +16,8 @@ import ( "go.opentelemetry.io/otel/trace" ) +var errInvalidEpochValueLength = errors.New("could not parse expiration epoch: invalid data length") + // FilterExpired return expired items from addresses. // Address considered expired if metabase does contain information about expiration and // expiration epoch is less than epoch. @@ -57,29 +58,11 @@ func (db *DB) FilterExpired(ctx context.Context, epoch uint64, addresses []oid.A default: } - expiredNeoFS, err := selectExpiredObjectIDs(tx, objectV2.SysAttributeExpEpochNeoFS, epoch, containerID, objectIDs) + expired, err := selectExpiredObjects(tx, epoch, containerID, objectIDs) if err != nil { return err } - - expiredSys, err := selectExpiredObjectIDs(tx, objectV2.SysAttributeExpEpoch, epoch, containerID, objectIDs) - if err != nil { - return err - } - - for _, o := range expiredNeoFS { - var a oid.Address - a.SetContainer(containerID) - a.SetObject(o) - result = append(result, a) - } - - for _, o := range expiredSys { - var a oid.Address - a.SetContainer(containerID) - a.SetObject(o) - result = append(result, a) - } + result = append(result, expired...) } return nil }) @@ -90,76 +73,39 @@ func (db *DB) FilterExpired(ctx context.Context, epoch uint64, addresses []oid.A return result, nil } -func isExpiredWithAttribute(tx *bbolt.Tx, attr string, addr oid.Address, currEpoch uint64) bool { - // bucket with objects that have expiration attr - attrKey := make([]byte, bucketKeySize+len(attr)) - expirationBucket := tx.Bucket(attributeBucketName(addr.Container(), attr, attrKey)) - if expirationBucket != nil { - // bucket that contains objects that expire in the current epoch - prevEpochBkt := expirationBucket.Bucket([]byte(strconv.FormatUint(currEpoch-1, 10))) - if prevEpochBkt != nil { - rawOID := objectKey(addr.Object(), make([]byte, objectKeySize)) - if prevEpochBkt.Get(rawOID) != nil { - return true - } - } +func isExpired(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (bool, error) { + bucketName := make([]byte, bucketKeySize) + bucketName = objectToExpirationEpochBucketName(addr.Container(), bucketName) + b := tx.Bucket(bucketName) + if b == nil { + return false, nil } - - return false + key := make([]byte, objectKeySize) + addr.Object().Encode(key) + val := b.Get(key) + if len(val) == 0 { + return false, nil + } + if len(val) != epochSize { + return false, errInvalidEpochValueLength + } + expEpoch := binary.LittleEndian.Uint64(val) + return expEpoch < currEpoch, nil } -func selectExpiredObjectIDs(tx *bbolt.Tx, attr string, epoch uint64, containerID cid.ID, objectIDs []oid.ID) ([]oid.ID, error) { - result := make([]oid.ID, 0) - notResolved := make(map[oid.ID]struct{}) - for _, oid := range objectIDs { - notResolved[oid] = struct{}{} - } - - expiredBuffer := make([]oid.ID, 0) - objectKeyBuffer := make([]byte, objectKeySize) - - expirationBucketKey := make([]byte, bucketKeySize+len(attr)) - expirationBucket := tx.Bucket(attributeBucketName(containerID, attr, expirationBucketKey)) - if expirationBucket == nil { - return result, nil // all not expired - } - - err := expirationBucket.ForEach(func(epochExpBucketKey, _ []byte) error { - bucketExpiresAfter, err := strconv.ParseUint(string(epochExpBucketKey), 10, 64) +func selectExpiredObjects(tx *bbolt.Tx, epoch uint64, containerID cid.ID, objectIDs []oid.ID) ([]oid.Address, error) { + result := make([]oid.Address, 0) + var addr oid.Address + addr.SetContainer(containerID) + for _, objID := range objectIDs { + addr.SetObject(objID) + expired, err := isExpired(tx, addr, epoch) if err != nil { - return fmt.Errorf("could not parse expiration epoch: %w", err) - } else if bucketExpiresAfter >= epoch { - return nil + return nil, err } - - epochExpirationBucket := expirationBucket.Bucket(epochExpBucketKey) - if epochExpirationBucket == nil { - return nil + if expired { + result = append(result, addr) } - - expiredBuffer = expiredBuffer[:0] - for oid := range notResolved { - key := objectKey(oid, objectKeyBuffer) - if epochExpirationBucket.Get(key) != nil { - expiredBuffer = append(expiredBuffer, oid) - } - } - - for _, oid := range expiredBuffer { - delete(notResolved, oid) - result = append(result, oid) - } - - if len(notResolved) == 0 { - return errBreakBucketForEach - } - - return nil - }) - - if err != nil && !errors.Is(err, errBreakBucketForEach) { - return nil, err } - return result, nil } diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index d979b4f0f1..776f5d27c3 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -90,7 +90,11 @@ func (db *DB) Get(ctx context.Context, prm GetPrm) (res GetRes, err error) { func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw bool, currEpoch uint64) (*objectSDK.Object, error) { if checkStatus { - switch objectStatus(tx, addr, currEpoch) { + st, err := objectStatus(tx, addr, currEpoch) + if err != nil { + return nil, err + } + switch st { case 1: return nil, logicerr.Wrap(new(apistatus.ObjectNotFound)) case 2: diff --git a/pkg/local_object_storage/metabase/iterators.go b/pkg/local_object_storage/metabase/iterators.go index 7b60b7d50a..d44c51fb29 100644 --- a/pkg/local_object_storage/metabase/iterators.go +++ b/pkg/local_object_storage/metabase/iterators.go @@ -7,7 +7,6 @@ import ( "strconv" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -79,63 +78,37 @@ func (db *DB) IterateExpired(ctx context.Context, epoch uint64, h ExpiredObjectH } func (db *DB) iterateExpired(tx *bbolt.Tx, epoch uint64, h ExpiredObjectHandler) error { - err := tx.ForEach(func(name []byte, b *bbolt.Bucket) error { - cidBytes := cidFromAttributeBucket(name, objectV2.SysAttributeExpEpoch) - if cidBytes == nil { - cidBytes = cidFromAttributeBucket(name, objectV2.SysAttributeExpEpochNeoFS) - if cidBytes == nil { - return nil - } - } - - var cnrID cid.ID - err := cnrID.Decode(cidBytes) + b := tx.Bucket(expEpochToObjectBucketName) + c := b.Cursor() + for k, _ := c.First(); k != nil; k, _ = c.Next() { + expiresAfter, cnr, obj, err := parseExpirationEpochKey(k) if err != nil { - return fmt.Errorf("could not parse container ID of expired bucket: %w", err) + return err } - - return b.ForEachBucket(func(expKey []byte) error { - bktExpired := b.Bucket(expKey) - expiresAfter, err := strconv.ParseUint(string(expKey), 10, 64) - if err != nil { - return fmt.Errorf("could not parse expiration epoch: %w", err) - } else if expiresAfter >= epoch { - return nil - } - - return bktExpired.ForEach(func(idKey, _ []byte) error { - var id oid.ID - - err = id.Decode(idKey) - if err != nil { - return fmt.Errorf("could not parse ID of expired object: %w", err) - } - - // Ignore locked objects. - // - // To slightly optimize performance we can check only REGULAR objects - // (only they can be locked), but it's more reliable. - if objectLocked(tx, cnrID, id) { - return nil - } - - var addr oid.Address - addr.SetContainer(cnrID) - addr.SetObject(id) - - return h(&ExpiredObject{ - typ: firstIrregularObjectType(tx, cnrID, idKey), - addr: addr, - }) - }) + // bucket keys ordered by epoch, no need to continue lookup + if expiresAfter >= epoch { + return nil + } + if objectLocked(tx, cnr, obj) { + continue + } + var addr oid.Address + addr.SetContainer(cnr) + addr.SetObject(obj) + objKey := objectKey(addr.Object(), make([]byte, objectKeySize)) + err = h(&ExpiredObject{ + typ: firstIrregularObjectType(tx, cnr, objKey), + addr: addr, }) - }) - - if errors.Is(err, ErrInterruptIterator) { - err = nil + if err == nil { + continue + } + if errors.Is(err, ErrInterruptIterator) { + return nil + } + return err } - - return err + return nil } // IterateCoveredByTombstones iterates over all objects in DB which are covered diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 3fa79f1e20..d1706a7abf 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -6,8 +6,10 @@ import ( "errors" "fmt" gio "io" + "strconv" "time" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" @@ -242,6 +244,27 @@ func putUniqueIndexes( } } + if expEpoch, ok := hasExpirationEpoch(obj); ok { + err := putUniqueIndexItem(tx, namedBucketItem{ + name: expEpochToObjectBucketName, + key: expirationEpochKey(expEpoch, cnr, addr.Object()), + val: zeroValue, + }) + if err != nil { + return err + } + val := make([]byte, epochSize) + binary.LittleEndian.PutUint64(val, expEpoch) + err = putUniqueIndexItem(tx, namedBucketItem{ + name: objectToExpirationEpochBucketName(cnr, make([]byte, bucketKeySize)), + key: objKey, + val: val, + }) + if err != nil { + return err + } + } + // index root object if obj.Type() == objectSDK.TypeRegular && !obj.HasParent() { if ecHead := obj.ECHeader(); ecHead != nil { @@ -361,6 +384,24 @@ func updateListIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun return nil } +func hasExpirationEpoch(obj *objectSDK.Object) (uint64, bool) { + attributes := obj.Attributes() + if ech := obj.ECHeader(); ech != nil { + attributes = ech.ParentAttributes() + } + for _, attr := range attributes { + if attr.Key() == objectV2.SysAttributeExpEpochNeoFS { + expEpoch, err := strconv.ParseUint(attr.Value(), 10, 64) + return expEpoch, err == nil + } + if attr.Key() == objectV2.SysAttributeExpEpoch { + expEpoch, err := strconv.ParseUint(attr.Value(), 10, 64) + return expEpoch, err == nil + } + } + return 0, false +} + func updateFKBTIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFunc) error { id, _ := obj.ID() cnr, _ := obj.ContainerID() diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 720b7b5b9b..42737a41a3 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -142,8 +142,11 @@ func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters var addr oid.Address addr.SetContainer(cnr) addr.SetObject(id) - - if objectStatus(tx, addr, currEpoch) > 0 { + st, err := objectStatus(tx, addr, currEpoch) + if err != nil { + return nil, err + } + if st > 0 { continue // ignore removed objects } diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index ebf1713d0e..012c0dcc80 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -1,9 +1,10 @@ package meta import ( - "bytes" "crypto/sha256" + "encoding/binary" "errors" + "fmt" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -23,6 +24,7 @@ var ( toMoveItBucketName = []byte{toMoveItPrefix} containerVolumeBucketName = []byte{containerVolumePrefix} containerCounterBucketName = []byte{containerCountersPrefix} + expEpochToObjectBucketName = []byte{expirationEpochToObjectPrefix} zeroValue = []byte{0xFF} @@ -124,6 +126,16 @@ const ( // Key: container ID + type // Value: Object id ecInfoPrefix + + // expirationEpochToObjectPrefix is used for storing relation between expiration epoch and object id. + // Key: expiration epoch + object address + // Value: zero + expirationEpochToObjectPrefix + + // objectToExpirationEpochPrefix is used for storing relation between expiration epoch and object id. + // Key: object address + // Value: expiration epoch + objectToExpirationEpochPrefix ) const ( @@ -131,6 +143,7 @@ const ( bucketKeySize = 1 + cidSize objectKeySize = sha256.Size addressKeySize = cidSize + objectKeySize + epochSize = 8 ) func bucketName(cnr cid.ID, prefix byte, key []byte) []byte { @@ -161,15 +174,6 @@ func attributeBucketName(cnr cid.ID, attributeKey string, key []byte) []byte { return append(key[:bucketKeySize], attributeKey...) } -// returns from attributeBucketName result, nil otherwise. -func cidFromAttributeBucket(val []byte, attributeKey string) []byte { - if len(val) < bucketKeySize || val[0] != userAttributePrefix || !bytes.Equal(val[bucketKeySize:], []byte(attributeKey)) { - return nil - } - - return val[1:bucketKeySize] -} - // rootBucketName returns _root. func rootBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, rootPrefix, key) @@ -190,6 +194,35 @@ func ecInfoBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, ecInfoPrefix, key) } +// objectToExpirationEpochBucketName returns objectToExpirationEpochPrefix_. +func objectToExpirationEpochBucketName(cnr cid.ID, key []byte) []byte { + return bucketName(cnr, objectToExpirationEpochPrefix, key) +} + +func expirationEpochKey(epoch uint64, cnr cid.ID, obj oid.ID) []byte { + result := make([]byte, epochSize+addressKeySize) + binary.BigEndian.PutUint64(result, epoch) + cnr.Encode(result[epochSize:]) + obj.Encode(result[epochSize+cidSize:]) + return result +} + +func parseExpirationEpochKey(key []byte) (uint64, cid.ID, oid.ID, error) { + if len(key) != epochSize+addressKeySize { + return 0, cid.ID{}, oid.ID{}, fmt.Errorf("unexpected expiration epoch to object key length: %d", len(key)) + } + epoch := binary.BigEndian.Uint64(key) + var cnr cid.ID + if err := cnr.Decode(key[epochSize : epochSize+cidSize]); err != nil { + return 0, cid.ID{}, oid.ID{}, fmt.Errorf("failed to decode expiration epoch to object key (container ID): %w", err) + } + var obj oid.ID + if err := obj.Decode(key[epochSize+cidSize:]); err != nil { + return 0, cid.ID{}, oid.ID{}, fmt.Errorf("failed to decode expiration epoch to object key (object ID): %w", err) + } + return epoch, cnr, obj, nil +} + // addressKey returns key for K-V tables when key is a whole address. func addressKey(addr oid.Address, key []byte) []byte { addr.Container().Encode(key) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index a438b5defb..90958cd355 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -74,7 +74,7 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { var getPrm GetPrm getPrm.SetAddress(objectCore.AddressOf(obj)) _, err = sh.Get(context.Background(), getPrm) - require.True(t, client.IsErrObjectNotFound(err), "expired object must be deleted") + require.True(t, client.IsErrObjectNotFound(err) || IsErrObjectExpired(err), "expired object must be deleted") } func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { @@ -168,7 +168,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { sh.gc.handleEvent(context.Background(), EventNewEpoch(epoch.Value)) _, err = sh.Get(context.Background(), getPrm) - require.True(t, client.IsErrObjectNotFound(err), "expired complex object must be deleted on epoch after lock expires") + require.True(t, client.IsErrObjectNotFound(err) || IsErrObjectExpired(err), "expired complex object must be deleted on epoch after lock expires") } func TestGCDropsObjectInhumedFromWritecache(t *testing.T) { From 0f08a2efba6a39ec8a1c8f733729d510e3ea36bd Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 20 Aug 2024 12:21:39 +0300 Subject: [PATCH 0755/1413] [#1323] metabase: Resolve funlen linter Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/put.go | 74 ++++++++++++------------ 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index d1706a7abf..015f87f920 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -197,46 +197,17 @@ func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *o return nil } -func putUniqueIndexes( - tx *bbolt.Tx, - obj *objectSDK.Object, - si *objectSDK.SplitInfo, - id []byte, -) error { +func putUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, si *objectSDK.SplitInfo, id []byte) error { isParent := si != nil addr := objectCore.AddressOf(obj) - cnr := addr.Container() objKey := objectKey(addr.Object(), make([]byte, objectKeySize)) bucketName := make([]byte, bucketKeySize) - // add value to primary unique bucket if !isParent { - switch obj.Type() { - case objectSDK.TypeRegular: - bucketName = primaryBucketName(cnr, bucketName) - case objectSDK.TypeTombstone: - bucketName = tombstoneBucketName(cnr, bucketName) - case objectSDK.TypeLock: - bucketName = bucketNameLockers(cnr, bucketName) - default: - return ErrUnknownObjectType - } - - rawObject, err := obj.CutPayload().Marshal() - if err != nil { - return fmt.Errorf("can't marshal object header: %w", err) - } - - err = putUniqueIndexItem(tx, namedBucketItem{ - name: bucketName, - key: objKey, - val: rawObject, - }) + err := putRawObjectData(tx, obj, bucketName, addr, objKey) if err != nil { return err } - - // index storageID if it is present if id != nil { if err = setStorageID(tx, objectCore.AddressOf(obj), id, false); err != nil { return err @@ -244,10 +215,40 @@ func putUniqueIndexes( } } + if err := putExpirationEpoch(tx, obj, addr, objKey); err != nil { + return err + } + + return putSplitInfo(tx, obj, bucketName, addr, si, objKey) +} + +func putRawObjectData(tx *bbolt.Tx, obj *objectSDK.Object, bucketName []byte, addr oid.Address, objKey []byte) error { + switch obj.Type() { + case objectSDK.TypeRegular: + bucketName = primaryBucketName(addr.Container(), bucketName) + case objectSDK.TypeTombstone: + bucketName = tombstoneBucketName(addr.Container(), bucketName) + case objectSDK.TypeLock: + bucketName = bucketNameLockers(addr.Container(), bucketName) + default: + return ErrUnknownObjectType + } + rawObject, err := obj.CutPayload().Marshal() + if err != nil { + return fmt.Errorf("can't marshal object header: %w", err) + } + return putUniqueIndexItem(tx, namedBucketItem{ + name: bucketName, + key: objKey, + val: rawObject, + }) +} + +func putExpirationEpoch(tx *bbolt.Tx, obj *objectSDK.Object, addr oid.Address, objKey []byte) error { if expEpoch, ok := hasExpirationEpoch(obj); ok { err := putUniqueIndexItem(tx, namedBucketItem{ name: expEpochToObjectBucketName, - key: expirationEpochKey(expEpoch, cnr, addr.Object()), + key: expirationEpochKey(expEpoch, addr.Container(), addr.Object()), val: zeroValue, }) if err != nil { @@ -256,7 +257,7 @@ func putUniqueIndexes( val := make([]byte, epochSize) binary.LittleEndian.PutUint64(val, expEpoch) err = putUniqueIndexItem(tx, namedBucketItem{ - name: objectToExpirationEpochBucketName(cnr, make([]byte, bucketKeySize)), + name: objectToExpirationEpochBucketName(addr.Container(), make([]byte, bucketKeySize)), key: objKey, val: val, }) @@ -264,8 +265,10 @@ func putUniqueIndexes( return err } } + return nil +} - // index root object +func putSplitInfo(tx *bbolt.Tx, obj *objectSDK.Object, bucketName []byte, addr oid.Address, si *objectSDK.SplitInfo, objKey []byte) error { if obj.Type() == objectSDK.TypeRegular && !obj.HasParent() { if ecHead := obj.ECHeader(); ecHead != nil { parentID := ecHead.Parent() @@ -283,9 +286,8 @@ func putUniqueIndexes( } objKey = objectKey(parentID, objKey) } - return updateSplitInfoIndex(tx, objKey, cnr, bucketName, si) + return updateSplitInfoIndex(tx, objKey, addr.Container(), bucketName, si) } - return nil } From 7d0d781db1b1d674b319a012d653f2bb510f82ca Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 20 Aug 2024 12:59:59 +0300 Subject: [PATCH 0756/1413] [#1323] metabase: Drop user attribute index Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete.go | 20 --- pkg/local_object_storage/metabase/put.go | 49 ------- pkg/local_object_storage/metabase/select.go | 151 +++++--------------- pkg/local_object_storage/metabase/util.go | 11 +- 4 files changed, 38 insertions(+), 193 deletions(-) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 683bd445f2..00c8d06e04 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -341,11 +341,6 @@ func (db *DB) deleteObject( return fmt.Errorf("can't remove list indexes: %w", err) } - err = updateFKBTIndexes(tx, obj, delFKBTIndexItem) - if err != nil { - return fmt.Errorf("can't remove fake bucket tree indexes: %w", err) - } - if isParent { // remove record from the garbage bucket, because regular object deletion does nothing for virtual object garbageBKT := tx.Bucket(garbageBucketName) @@ -386,21 +381,6 @@ func delUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) { } } -func delFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { - bkt := tx.Bucket(item.name) - if bkt == nil { - return nil - } - - fkbtRoot := bkt.Bucket(item.key) - if fkbtRoot == nil { - return nil - } - - _ = fkbtRoot.Delete(item.val) // ignore error, best effort there - return nil -} - func delListIndexItem(tx *bbolt.Tx, item namedBucketItem) error { bkt := tx.Bucket(item.name) if bkt == nil { diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 015f87f920..ff79a0387b 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -175,11 +175,6 @@ func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *o return fmt.Errorf("can't put list indexes: %w", err) } - err = updateFKBTIndexes(tx, obj, putFKBTIndexItem) - if err != nil { - return fmt.Errorf("can't put fake bucket tree indexes: %w", err) - } - // update container volume size estimation if obj.Type() == objectSDK.TypeRegular && !isParent { err = changeContainerSize(tx, cnr, obj.PayloadSize(), true) @@ -404,36 +399,6 @@ func hasExpirationEpoch(obj *objectSDK.Object) (uint64, bool) { return 0, false } -func updateFKBTIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFunc) error { - id, _ := obj.ID() - cnr, _ := obj.ContainerID() - objKey := objectKey(id, make([]byte, objectKeySize)) - - key := make([]byte, bucketKeySize) - var attrs []objectSDK.Attribute - if obj.ECHeader() != nil { - attrs = obj.ECHeader().ParentAttributes() - objKey = objectKey(obj.ECHeader().Parent(), make([]byte, objectKeySize)) - } else { - attrs = obj.Attributes() - } - - // user specified attributes - for i := range attrs { - key = attributeBucketName(cnr, attrs[i].Key(), key) - err := f(tx, namedBucketItem{ - name: key, - key: []byte(attrs[i].Value()), - val: objKey, - }) - if err != nil { - return err - } - } - - return nil -} - type bucketContainer interface { Bucket([]byte) *bbolt.Bucket CreateBucket([]byte) (*bbolt.Bucket, error) @@ -464,20 +429,6 @@ func putUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) error { return updateUniqueIndexItem(tx, item, func(_, val []byte) ([]byte, error) { return val, nil }) } -func putFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { - bkt, err := createBucketLikelyExists(tx, item.name) - if err != nil { - return fmt.Errorf("can't create index %v: %w", item.name, err) - } - - fkbtRoot, err := createBucketLikelyExists(bkt, item.key) - if err != nil { - return fmt.Errorf("can't create fake bucket tree index %v: %w", item.key, err) - } - - return fkbtRoot.Put(item.val, zeroValue) -} - func putListIndexItem(tx *bbolt.Tx, item namedBucketItem) error { bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 42737a41a3..1863fc25e5 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -198,9 +198,6 @@ func (db *DB) selectFastFilter( switch f.Header() { case v2object.FilterHeaderObjectID: db.selectObjectID(tx, f, cnr, to, fNum, currEpoch) - case v2object.FilterHeaderOwnerID, - v2object.FilterHeaderPayloadHash: - return // moved to slow filters case v2object.FilterHeaderObjectType: for _, bucketName := range bucketNamesForType(cnr, f.Operation(), f.Value()) { selectAllFromBucket(tx, bucketName, to, fNum) @@ -220,14 +217,7 @@ func (db *DB) selectFastFilter( selectAllFromBucket(tx, primaryBucketName(cnr, bucketName), to, fNum) selectAllFromBucket(tx, tombstoneBucketName(cnr, bucketName), to, fNum) selectAllFromBucket(tx, bucketNameLockers(cnr, bucketName), to, fNum) - default: // user attribute - bucketName := attributeBucketName(cnr, f.Header(), bucketName) - - if f.Operation() == objectSDK.MatchNotPresent { - selectOutsideFKBT(tx, allBucketNames(cnr), bucketName, to, fNum) - } else { - db.selectFromFKBT(tx, bucketName, f, to, fNum) - } + default: } } @@ -237,16 +227,6 @@ var mBucketNaming = map[string][]func(cid.ID, []byte) []byte{ v2object.TypeLock.String(): {bucketNameLockers}, } -func allBucketNames(cnr cid.ID) (names [][]byte) { - for _, fns := range mBucketNaming { - for _, fn := range fns { - names = append(names, fn(cnr, make([]byte, bucketKeySize))) - } - } - - return -} - func bucketNamesForType(cnr cid.ID, mType objectSDK.SearchMatchType, typeVal string) (names [][]byte) { appendNames := func(key string) { fns, ok := mBucketNaming[key] @@ -278,83 +258,6 @@ func bucketNamesForType(cnr cid.ID, mType objectSDK.SearchMatchType, typeVal str return } -// selectFromList looks into index to find list of addresses to add in -// resulting cache. -func (db *DB) selectFromFKBT( - tx *bbolt.Tx, - name []byte, // fkbt root bucket name - f objectSDK.SearchFilter, // filter for operation and value - to map[string]int, // resulting cache - fNum int, // index of filter -) { // - matchFunc, ok := db.matchers[f.Operation()] - if !ok { - db.log.Debug(logs.MetabaseMissingMatcher, zap.Uint32("operation", uint32(f.Operation()))) - - return - } - - fkbtRoot := tx.Bucket(name) - if fkbtRoot == nil { - return - } - - err := matchFunc.matchBucket(fkbtRoot, f.Header(), f.Value(), func(k, _ []byte) error { - fkbtLeaf := fkbtRoot.Bucket(k) - if fkbtLeaf == nil { - return nil - } - - return fkbtLeaf.ForEach(func(k, _ []byte) error { - markAddressInCache(to, fNum, string(k)) - - return nil - }) - }) - if err != nil { - db.log.Debug(logs.MetabaseErrorInFKBTSelection, zap.String("error", err.Error())) - } -} - -// selectOutsideFKBT looks into all incl buckets to find list of addresses outside to add in -// resulting cache. -func selectOutsideFKBT( - tx *bbolt.Tx, - incl [][]byte, // buckets - name []byte, // fkbt root bucket name - to map[string]int, // resulting cache - fNum int, // index of filter -) { - mExcl := make(map[string]struct{}) - - bktExcl := tx.Bucket(name) - if bktExcl != nil { - _ = bktExcl.ForEachBucket(func(k []byte) error { - exclBktLeaf := bktExcl.Bucket(k) - return exclBktLeaf.ForEach(func(k, _ []byte) error { - mExcl[string(k)] = struct{}{} - - return nil - }) - }) - } - - for i := range incl { - bktIncl := tx.Bucket(incl[i]) - if bktIncl == nil { - continue - } - - _ = bktIncl.ForEach(func(k, _ []byte) error { - if _, ok := mExcl[string(k)]; !ok { - markAddressInCache(to, fNum, string(k)) - } - - return nil - }) - } -} - // selectFromList looks into index to find list of addresses to add in // resulting cache. func (db *DB) selectFromList( @@ -491,13 +394,7 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc } for i := range f { - matchFunc, ok := db.matchers[f[i].Operation()] - if !ok { - return false - } - var data []byte - switch f[i].Header() { case v2object.FilterHeaderVersion: data = []byte(obj.Version().String()) @@ -515,8 +412,18 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc case v2object.FilterHeaderPayloadHash: cs, _ := obj.PayloadChecksum() data = cs.Value() - default: - continue // ignore unknown search attributes + default: // user attribute + v, ok := attributeValue(obj, f[i].Header()) + if ok { + data = []byte(v) + } else { + return f[i].Operation() == objectSDK.MatchNotPresent + } + } + + matchFunc, ok := db.matchers[f[i].Operation()] + if !ok { + return false } if !matchFunc.matchSlow(f[i].Header(), data, f[i].Value()) { @@ -527,6 +434,19 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc return true } +func attributeValue(obj *objectSDK.Object, attribute string) (string, bool) { + objectAttributes := obj.Attributes() + if ech := obj.ECHeader(); ech != nil { + objectAttributes = ech.ParentAttributes() + } + for _, attr := range objectAttributes { + if attr.Key() == attribute { + return attr.Value(), true + } + } + return "", false +} + // groupFilters divides filters in two groups: fast and slow. Fast filters // processed by indexes and slow filters processed after by unmarshaling // object headers. @@ -545,16 +465,17 @@ func groupFilters(filters objectSDK.SearchFilters) (filterGroup, error) { } res.withCnrFilter = true - case // slow filters - v2object.FilterHeaderVersion, - v2object.FilterHeaderCreationEpoch, - v2object.FilterHeaderPayloadLength, - v2object.FilterHeaderHomomorphicHash, - v2object.FilterHeaderOwnerID, - v2object.FilterHeaderPayloadHash: - res.slowFilters = append(res.slowFilters, filters[i]) - default: // fast filters or user attributes if unknown + case // fast filters + v2object.FilterHeaderObjectID, + v2object.FilterHeaderObjectType, + v2object.FilterHeaderParent, + v2object.FilterHeaderSplitID, + v2object.FilterHeaderECParent, + v2object.FilterPropertyRoot, + v2object.FilterPropertyPhy: res.fastFilters = append(res.fastFilters, filters[i]) + default: + res.slowFilters = append(res.slowFilters, filters[i]) } } diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index 012c0dcc80..9134616fe3 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -95,10 +95,10 @@ const ( // Key: owner ID // Value: bucket containing object IDs as keys _ - // userAttributePrefix is used for prefixing FKBT index buckets containing objects. + // userAttributePrefix was used for prefixing FKBT index buckets containing objects. // Key: attribute value // Value: bucket containing object IDs as keys - userAttributePrefix + _ // ==================== // List index buckets. @@ -167,13 +167,6 @@ func smallBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, smallPrefix, key) } -// attributeBucketName returns _attr_. -func attributeBucketName(cnr cid.ID, attributeKey string, key []byte) []byte { - key[0] = userAttributePrefix - cnr.Encode(key[1:]) - return append(key[:bucketKeySize], attributeKey...) -} - // rootBucketName returns _root. func rootBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, rootPrefix, key) From 76f67ea34ea316a4b4f05bedb7a5aa2d9599912e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 20 Aug 2024 15:39:44 +0300 Subject: [PATCH 0757/1413] [#1323] metabase: Bump version Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/VERSION.md | 7 +++++++ pkg/local_object_storage/metabase/version.go | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/VERSION.md b/pkg/local_object_storage/metabase/VERSION.md index 97e514db1f..9cfc95332f 100644 --- a/pkg/local_object_storage/metabase/VERSION.md +++ b/pkg/local_object_storage/metabase/VERSION.md @@ -2,6 +2,8 @@ This file describes changes between the metabase versions. +Warning: database schema below is outdated and incomplete, see source code. + ## Current ### Primary buckets @@ -86,6 +88,11 @@ This file describes changes between the metabase versions. # History +## Version 3 + +- Payload hash, owner ID and FKBT buckets deleted +- Expiration epoch to object ID and object ID to expiration epoch added + ## Version 2 - Container ID is encoded as 32-byte slice diff --git a/pkg/local_object_storage/metabase/version.go b/pkg/local_object_storage/metabase/version.go index 5748b64ee9..bb2b66d9bc 100644 --- a/pkg/local_object_storage/metabase/version.go +++ b/pkg/local_object_storage/metabase/version.go @@ -9,7 +9,7 @@ import ( ) // version contains current metabase version. -const version = 2 +const version = 3 var versionKey = []byte("version") From dfe825b81b5eead451ae20b76a50b382618ae7ba Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 21 Aug 2024 17:08:44 +0300 Subject: [PATCH 0758/1413] [#1309] test: Clean up config after tests Signed-off-by: Aleksey Savchuk --- cmd/frostfs-cli/internal/key/key_test.go | 2 ++ cmd/frostfs-node/config/test/config.go | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/cmd/frostfs-cli/internal/key/key_test.go b/cmd/frostfs-cli/internal/key/key_test.go index e3127a3fee..37e4fd4eee 100644 --- a/cmd/frostfs-cli/internal/key/key_test.go +++ b/cmd/frostfs-cli/internal/key/key_test.go @@ -24,6 +24,8 @@ var testCmd = &cobra.Command{ } func Test_getOrGenerate(t *testing.T) { + t.Cleanup(viper.Reset) + dir := t.TempDir() wallPath := filepath.Join(dir, "wallet.json") diff --git a/cmd/frostfs-node/config/test/config.go b/cmd/frostfs-node/config/test/config.go index 28ec652912..a93d7e6489 100644 --- a/cmd/frostfs-node/config/test/config.go +++ b/cmd/frostfs-node/config/test/config.go @@ -40,6 +40,15 @@ func ForEachFileType(pref string, f func(*config.Config)) { // ForEnvFileType creates config from `.env` file. func ForEnvFileType(t testing.TB, pref string, f func(*config.Config)) { + envs := os.Environ() + t.Cleanup(func() { + os.Clearenv() + for _, env := range envs { + keyValue := strings.Split(env, "=") + os.Setenv(keyValue[0], keyValue[1]) + } + }) + f(fromEnvFile(t, pref+".env")) } From bd24beecf8652ca3662b4339b2799bf0385507a8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 23 Aug 2024 12:28:09 +0300 Subject: [PATCH 0759/1413] [#1329] putSvc: Reset SuccessAfter for non-EC objects in EC container broadcasting Signed-off-by: Dmitrii Stepanov --- pkg/services/object/put/distributed.go | 9 +++++++++ pkg/services/object/put/single.go | 9 ++++++--- pkg/services/object/put/streamer.go | 7 +++++-- pkg/services/object_manager/placement/traverser.go | 7 +++++++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/put/distributed.go index c71427b67b..5176f7a54b 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/put/distributed.go @@ -24,6 +24,8 @@ type distributedTarget struct { nodeTargetInitializer func(nodeDesc) preparedObjectTarget relay func(context.Context, nodeDesc) error + + resetSuccessAfterOnBroadcast bool } // parameters and state of container traversal. @@ -35,6 +37,8 @@ type traversal struct { // container nodes which was processed during the primary object placement mExclude map[string]*bool + + resetSuccessAfterOnBroadcast bool } // updates traversal parameters after the primary placement finish and @@ -44,6 +48,10 @@ func (x *traversal) submitPrimaryPlacementFinish() bool { // do not track success during container broadcast (best-effort) x.opts = append(x.opts, placement.WithoutSuccessTracking()) + if x.resetSuccessAfterOnBroadcast { + x.opts = append(x.opts, placement.ResetSuccessAfter()) + } + // avoid 2nd broadcast x.extraBroadcastEnabled = false @@ -118,5 +126,6 @@ func (t *distributedTarget) iteratePlacement(ctx context.Context) error { iter := t.cfg.newNodeIterator(append(t.placementOpts, placement.ForObject(id))) iter.extraBroadcastEnabled = needAdditionalBroadcast(t.obj, false /* Distributed target is for cluster-wide PUT */) + iter.resetSuccessAfterOnBroadcast = t.resetSuccessAfterOnBroadcast return iter.forEachNode(ctx, t.sendObject) } diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 9fa8ddb67c..3cc8518f5f 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -166,6 +166,7 @@ func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *o func (s *Service) saveToREPReplicas(ctx context.Context, placement putSinglePlacement, obj *objectSDK.Object, localOnly bool, req *objectAPI.PutSingleRequest, meta object.ContentMeta) error { iter := s.cfg.newNodeIterator(placement.placementOptions) iter.extraBroadcastEnabled = needAdditionalBroadcast(obj, localOnly) + iter.resetSuccessAfterOnBroadcast = placement.resetSuccessAfterOnBroadcast signer := &putSingleRequestSigner{ req: req, @@ -209,9 +210,10 @@ func (s *Service) saveToECReplicas(ctx context.Context, placement putSinglePlace } type putSinglePlacement struct { - placementOptions []placement.Option - isEC bool - container containerSDK.Container + placementOptions []placement.Option + isEC bool + container containerSDK.Container + resetSuccessAfterOnBroadcast bool } func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumber []uint32, localOnly bool) (putSinglePlacement, error) { @@ -232,6 +234,7 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb } if container.IsECContainer(cnrInfo.Value) && !object.IsECSupported(obj) && !localOnly { result.placementOptions = append(result.placementOptions, placement.SuccessAfter(uint32(policy.ECParityCount(cnrInfo.Value.PlacementPolicy())+1))) + result.resetSuccessAfterOnBroadcast = true } result.placementOptions = append(result.placementOptions, placement.ForContainer(cnrInfo.Value)) diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 969c8fa19f..6b396ec967 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -246,16 +246,19 @@ func (p *Streamer) newDefaultObjectWriter(prm *PutInitPrm, forECPlacement bool) } } + var resetSuccessAfterOnBroadcast bool traverseOpts := prm.traverseOpts if forECPlacement && !prm.common.LocalOnly() { // save non-regular and linking object to EC container. // EC 2.1 -> REP 2, EC 2.2 -> REP 3 etc. traverseOpts = append(traverseOpts, placement.SuccessAfter(uint32(policy.ECParityCount(prm.cnr.PlacementPolicy())+1))) + resetSuccessAfterOnBroadcast = true } return &distributedTarget{ - cfg: p.cfg, - placementOpts: traverseOpts, + cfg: p.cfg, + placementOpts: traverseOpts, + resetSuccessAfterOnBroadcast: resetSuccessAfterOnBroadcast, nodeTargetInitializer: func(node nodeDesc) preparedObjectTarget { if node.local { return localTarget{ diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 3061695718..9a5877c527 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -303,6 +303,13 @@ func SuccessAfter(v uint32) Option { } } +// ResetSuccessAfter resets flat success number setting option. +func ResetSuccessAfter() Option { + return func(c *cfg) { + c.flatSuccess = nil + } +} + // WithoutSuccessTracking disables success tracking in traversal. func WithoutSuccessTracking() Option { return func(c *cfg) { From a059a7dcf06ed41354f1defe5d1822b79d4c1deb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 23 Aug 2024 13:36:52 +0300 Subject: [PATCH 0760/1413] [#1329] cli: Skip linking objects in complex object processing Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/nodes.go | 74 ++++++++++++------------- cmd/frostfs-cli/modules/object/util.go | 9 +-- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 42ae7324ea..4efe04d162 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -172,7 +172,7 @@ func getComplexObjectParts(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli * func getCompexObjectMembers(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, prmHead internalclient.HeadObjectPrm, errSplitInfo *objectSDK.SplitInfoError) []oid.ID { splitInfo := errSplitInfo.SplitInfo() - if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnrID, false); ok { + if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnrID); ok { return members } @@ -185,6 +185,7 @@ func getCompexObjectMembers(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, members []oid.ID, prmHead internalclient.HeadObjectPrm) []phyObject { result := make([]phyObject, 0, len(members)) + var hasNonEC, hasEC bool var resultGuard sync.Mutex if len(members) == 0 { @@ -193,31 +194,8 @@ func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, member prmHead.SetRawFlag(true) // to get an error instead of whole object - first := members[0] - var addrObj oid.Address - addrObj.SetContainer(cnrID) - addrObj.SetObject(first) - prmHead.SetAddress(addrObj) - - _, err := internalclient.HeadObject(cmd.Context(), prmHead) - var ecInfoError *objectSDK.ECInfoError - if errors.As(err, &ecInfoError) { - chunks := getECObjectChunks(cmd, cnrID, first, ecInfoError) - result = append(result, chunks...) - } else if err == nil { // not EC object, so all members must be phy objects - for _, member := range members { - result = append(result, phyObject{ - containerID: cnrID, - objectID: member, - }) - } - return result - } else { - commonCmd.ExitOnErr(cmd, "failed to flatten parts of complex object: %w", err) - } - eg, egCtx := errgroup.WithContext(cmd.Context()) - for idx := 1; idx < len(members); idx++ { + for idx := 0; idx < len(members); idx++ { partObjID := members[idx] eg.Go(func() error { @@ -227,24 +205,44 @@ func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, member partAddr.SetObject(partObjID) partHeadPrm.SetAddress(partAddr) - _, err := internalclient.HeadObject(egCtx, partHeadPrm) - var ecInfoError *objectSDK.ECInfoError - if errors.As(err, &ecInfoError) { - chunks := getECObjectChunks(cmd, cnrID, partObjID, ecInfoError) - - resultGuard.Lock() - defer resultGuard.Unlock() - result = append(result, chunks...) - - return nil - } else if err == nil { - return errMalformedComplexObject + obj, err := internalclient.HeadObject(egCtx, partHeadPrm) + if err != nil { + var ecInfoError *objectSDK.ECInfoError + if errors.As(err, &ecInfoError) { + resultGuard.Lock() + defer resultGuard.Unlock() + result = append(result, getECObjectChunks(cmd, cnrID, partObjID, ecInfoError)...) + hasEC = true + return nil + } + return err } - return err + + if obj.Header().Type() != objectSDK.TypeRegular { + commonCmd.ExitOnErr(cmd, "failed to flatten parts of complex object: %w", fmt.Errorf("object '%s' with type '%s' is not supported as part of complex object", partAddr, obj.Header().Type())) + } + + if len(obj.Header().Children()) > 0 { + // linking object is not data object, so skip it + return nil + } + + resultGuard.Lock() + defer resultGuard.Unlock() + result = append(result, phyObject{ + containerID: cnrID, + objectID: partObjID, + }) + hasNonEC = true + + return nil }) } commonCmd.ExitOnErr(cmd, "failed to flatten parts of complex object: %w", eg.Wait()) + if hasEC && hasNonEC { + commonCmd.ExitOnErr(cmd, "failed to flatten parts of complex object: %w", errMalformedComplexObject) + } return result } diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index 96b80fe1b3..b090c9f8c4 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -374,7 +374,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, common.PrintVerbose(cmd, "Split information received - object is virtual.") splitInfo := errSplit.SplitInfo() - if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnr, true); ok { + if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnr); ok { return members } @@ -390,7 +390,7 @@ func collectObjectRelatives(cmd *cobra.Command, cli *client.Client, cnr cid.ID, return nil } -func tryGetSplitMembersByLinkingObject(cmd *cobra.Command, splitInfo *objectSDK.SplitInfo, prmHead internal.HeadObjectPrm, cnr cid.ID, withLinking bool) ([]oid.ID, bool) { +func tryGetSplitMembersByLinkingObject(cmd *cobra.Command, splitInfo *objectSDK.SplitInfo, prmHead internal.HeadObjectPrm, cnr cid.ID) ([]oid.ID, bool) { // collect split chain by the descending ease of operations (ease is evaluated heuristically). // If any approach fails, we don't try the next since we assume that it will fail too. @@ -411,10 +411,7 @@ func tryGetSplitMembersByLinkingObject(cmd *cobra.Command, splitInfo *objectSDK. common.PrintVerbose(cmd, "Received split members from the linking object: %v", children) - if withLinking { - return append(children, idLinking), true - } - return children, true + return append(children, idLinking), true } // linking object is not required for From 80099d9a2ff1685ecc08b6f71bcba777ca51ca1d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 23 Aug 2024 10:57:03 +0300 Subject: [PATCH 0761/1413] [#1328] pilorama: Add tricky test for SortedByFilename Signed-off-by: Evgenii Stratonikov --- .../pilorama/forest_test.go | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 001d095c80..c6c6e8c8b4 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -1,11 +1,13 @@ package pilorama import ( + "bytes" "context" "crypto/rand" "fmt" mrand "math/rand" "path/filepath" + "slices" "strconv" "strings" "sync" @@ -232,6 +234,66 @@ func BenchmarkForestSortedIteration(b *testing.B) { } } +// The issue which we call "BugWithSkip" is easiest to understand when filenames are +// monotonically increasing numbers. We want the list of sorted filenames to have different length interleaved. +// The bug happens when we switch between length during listing. +// Thus this test contains numbers from 1 to 1000 and batch size of size 100. +func TestForest_TreeSortedIterationBugWithSkip(t *testing.T) { + t.Skip() + for i := range providers { + t.Run(providers[i].name, func(t *testing.T) { + testForestTreeSortedIterationBugWithSkip(t, providers[i].construct(t)) + }) + } +} + +func testForestTreeSortedIterationBugWithSkip(t *testing.T, s ForestStorage) { + defer func() { require.NoError(t, s.Close()) }() + + cid := cidtest.ID() + d := CIDDescriptor{cid, 0, 1} + treeID := "version" + treeAdd := func(t *testing.T, ts int, filename string) { + _, err := s.TreeMove(context.Background(), d, treeID, &Move{ + Child: RootID + uint64(ts), + Parent: RootID, + Meta: Meta{ + Time: Timestamp(ts), + Items: []KeyValue{ + {Key: AttributeFilename, Value: []byte(filename)}, + }, + }, + }) + require.NoError(t, err) + } + + const count = 2000 + treeAdd(t, 1, "") + for i := 1; i < count; i++ { + treeAdd(t, i+1, strconv.Itoa(i+1)) + } + + var result []MultiNodeInfo + treeAppend := func(t *testing.T, last *string, count int) *string { + res, cursor, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, MultiNode{RootID}, last, count) + require.NoError(t, err) + result = append(result, res...) + return cursor + } + + const batchSize = 10 + last := treeAppend(t, nil, batchSize) + for i := 1; i < count/batchSize; i++ { + last = treeAppend(t, last, batchSize) + } + require.Len(t, result, count) + require.True(t, slices.IsSortedFunc(result, func(a, b MultiNodeInfo) int { + filenameA := findAttr(a.Meta, AttributeFilename) + filenameB := findAttr(b.Meta, AttributeFilename) + return bytes.Compare(filenameA, filenameB) + })) +} + func TestForest_TreeSortedIteration(t *testing.T) { for i := range providers { t.Run(providers[i].name, func(t *testing.T) { From 806ea37101fc35cedca3e10681e43d7a91968d67 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 23 Aug 2024 10:58:33 +0300 Subject: [PATCH 0762/1413] [#1328] pilorama: Do not skip items in SortedByFilename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Benchmark results: ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ old │ new │ │ sec/op │ sec/op vs base │ ForestSortedIteration/bbolt,root-8 207.2µ ± 6% 173.6µ ± 6% -16.23% (p=0.000 n=10) ForestSortedIteration/bbolt,leaf-8 3.910µ ± 5% 3.928µ ± 7% ~ (p=0.529 n=10) geomean 28.46µ 26.11µ -8.27% ``` They are not representative, as the worst case is when we have multiple items of different lengths. However, `FileName` is usually less than 100 in practice, so the asymptotics is the same. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/boltdb.go | 1 + .../pilorama/forest_test.go | 3 +- pkg/local_object_storage/pilorama/heap.go | 38 +++++++++++++++---- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 48363ceacd..29941be837 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1161,6 +1161,7 @@ func (t *boltForest) fillSortedChildren(b *bbolt.Bucket, nodeIDs MultiNode, h *f lastFilename = nil nodes = nil length = actualLength + 1 + count = 0 c.Seek(append(prefix, byte(length), byte(length>>8))) c.Prev() // c.Next() will be performed by for loop } diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index c6c6e8c8b4..ecca9842f1 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -237,9 +237,8 @@ func BenchmarkForestSortedIteration(b *testing.B) { // The issue which we call "BugWithSkip" is easiest to understand when filenames are // monotonically increasing numbers. We want the list of sorted filenames to have different length interleaved. // The bug happens when we switch between length during listing. -// Thus this test contains numbers from 1 to 1000 and batch size of size 100. +// Thus this test contains numbers from 1 to 2000 and batch size of size 10. func TestForest_TreeSortedIterationBugWithSkip(t *testing.T) { - t.Skip() for i := range providers { t.Run(providers[i].name, func(t *testing.T) { testForestTreeSortedIterationBugWithSkip(t, providers[i].construct(t)) diff --git a/pkg/local_object_storage/pilorama/heap.go b/pkg/local_object_storage/pilorama/heap.go index ec57b9e1fd..5a00bcf7a3 100644 --- a/pkg/local_object_storage/pilorama/heap.go +++ b/pkg/local_object_storage/pilorama/heap.go @@ -2,6 +2,8 @@ package pilorama import ( "container/heap" + "slices" + "strings" ) type heapInfo struct { @@ -28,9 +30,10 @@ func (h *filenameHeap) Pop() any { // fixedHeap maintains a fixed number of smallest elements started at some point. type fixedHeap struct { - start *string - count int - h *filenameHeap + start *string + sorted bool + count int + h *filenameHeap } func newHeap(start *string, count int) *fixedHeap { @@ -44,20 +47,39 @@ func newHeap(start *string, count int) *fixedHeap { } } +const amortizationMultiplier = 5 + func (h *fixedHeap) push(id MultiNode, filename string) bool { if h.start != nil && filename <= *h.start { return false } - heap.Push(h.h, heapInfo{id: id, filename: filename}) - if h.h.Len() > h.count { - heap.Remove(h.h, h.h.Len()-1) + + *h.h = append(*h.h, heapInfo{id: id, filename: filename}) + h.sorted = false + + if h.h.Len() > h.count*amortizationMultiplier { + slices.SortFunc(*h.h, func(a, b heapInfo) int { + return strings.Compare(a.filename, b.filename) + }) + *h.h = (*h.h)[:h.count] } return true } func (h *fixedHeap) pop() (heapInfo, bool) { - if h.h.Len() != 0 { - return heap.Pop(h.h).(heapInfo), true + if !h.sorted { + slices.SortFunc(*h.h, func(a, b heapInfo) int { + return strings.Compare(a.filename, b.filename) + }) + if len(*h.h) > h.count { + *h.h = (*h.h)[:h.count] + } + h.sorted = true + } + if len(*h.h) != 0 { + info := (*h.h)[0] + *h.h = (*h.h)[1:] + return info, true } return heapInfo{}, false } From fa7f9fbce240dde6e0a3c6ded13cb769bbe3b2bf Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 26 Aug 2024 15:36:39 +0300 Subject: [PATCH 0763/1413] [#1333] go.mod: Update api-go Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b665709cc3..b0df975113 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240819074700-a43110e36326 + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240826113619-9e82a5a31a88 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d diff --git a/go.sum b/go.sum index 54e0d0301a..f3a17363da 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240819074700-a43110e36326 h1:TkH+NSsY4C/Z8MocIJyMcqLm5vEhZcSowOldJyilKKA= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240819074700-a43110e36326/go.mod h1:zZnHiRv9m5+ESYLhBXY9Jds9A/YIDEUGiuyPUS09HwM= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240826113619-9e82a5a31a88 h1:ckD87Z4pvPtu2hjpRcqPHlAtgOHPZfSW3x+zzwZztiY= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240826113619-9e82a5a31a88/go.mod h1:BDnEpkKMykCS8u1nLzR6SgNzCv6885RWlo5TnravQuI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= From 5e9a97fd3eabc58347260b06fc6e1da4f5cf2185 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 27 Aug 2024 14:46:56 +0300 Subject: [PATCH 0764/1413] [#1336] go.mod: Update api-go and sdk-go Signed-off-by: Evgenii Stratonikov --- go.mod | 4 +- go.sum | 8 +- pkg/services/control/ir/service_frostfs.pb.go | 32 +-- pkg/services/control/service_frostfs.pb.go | 196 +++++++++--------- pkg/services/control/types_frostfs.pb.go | 6 +- pkg/services/tree/service_frostfs.pb.go | 98 ++++----- 6 files changed, 172 insertions(+), 172 deletions(-) diff --git a/go.mod b/go.mod index b0df975113..b7f59c8232 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240826113619-9e82a5a31a88 + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240827104600-eba18f6e67ac git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240820072028-6dd7be11d13b + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240827083309-f0b9493ce3f7 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index f3a17363da..d2f926151e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240826113619-9e82a5a31a88 h1:ckD87Z4pvPtu2hjpRcqPHlAtgOHPZfSW3x+zzwZztiY= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240826113619-9e82a5a31a88/go.mod h1:BDnEpkKMykCS8u1nLzR6SgNzCv6885RWlo5TnravQuI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240827104600-eba18f6e67ac h1:Gu3oiPnsSZPgwsUYs2f3xTQwndM/OWM/zo3zbN4rOb8= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240827104600-eba18f6e67ac/go.mod h1:BDnEpkKMykCS8u1nLzR6SgNzCv6885RWlo5TnravQuI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240820072028-6dd7be11d13b h1:ZCJBVmQDcdv0twpX9xJU/AQwX+dXyvVfqr0Pq3x+3yk= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240820072028-6dd7be11d13b/go.mod h1:aaC2OR34tVrBwd0Z2gqoN5WLtV/idKqpqPDhb4XqmCo= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240827083309-f0b9493ce3f7 h1:9eZidZMT4tHOdc6GZRPlZR12IToKqHhUd5wzevdDUqo= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240827083309-f0b9493ce3f7/go.mod h1:VzVYcwo/eXjkdo5ktPdZeAE4fsnZX6zEun3g+5E2weo= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= diff --git a/pkg/services/control/ir/service_frostfs.pb.go b/pkg/services/control/ir/service_frostfs.pb.go index 7860958028..66d1966170 100644 --- a/pkg/services/control/ir/service_frostfs.pb.go +++ b/pkg/services/control/ir/service_frostfs.pb.go @@ -164,10 +164,10 @@ func (x *HealthCheckRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -495,10 +495,10 @@ func (x *HealthCheckResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -810,10 +810,10 @@ func (x *TickEpochRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -1125,10 +1125,10 @@ func (x *TickEpochResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -1471,10 +1471,10 @@ func (x *RemoveNodeRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -1786,10 +1786,10 @@ func (x *RemoveNodeResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2163,10 +2163,10 @@ func (x *RemoveContainerRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2478,10 +2478,10 @@ func (x *RemoveContainerResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index afd1c3c41d..a446c5e59b 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -164,10 +164,10 @@ func (x *HealthCheckRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -542,10 +542,10 @@ func (x *HealthCheckResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -904,10 +904,10 @@ func (x *SetNetmapStatusRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -1185,10 +1185,10 @@ func (x *SetNetmapStatusResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -1466,10 +1466,10 @@ func (x *GetNetmapStatusRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -1828,10 +1828,10 @@ func (x *GetNetmapStatusResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2157,10 +2157,10 @@ func (x *DropObjectsRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2438,10 +2438,10 @@ func (x *DropObjectsResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2719,10 +2719,10 @@ func (x *ListShardsRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2888,7 +2888,7 @@ func (x *ListShardsResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { return } for i := range x.Shards { - if x.Shards[i] != nil && x.Shards[i].StableSize() != 0 { + if x.Shards[i] != nil { x.Shards[i].EmitProtobuf(mm.AppendMessage(1)) } } @@ -3057,10 +3057,10 @@ func (x *ListShardsResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -3464,10 +3464,10 @@ func (x *SetShardModeRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -3745,10 +3745,10 @@ func (x *SetShardModeResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -4122,10 +4122,10 @@ func (x *SynchronizeTreeRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -4403,10 +4403,10 @@ func (x *SynchronizeTreeResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -4763,10 +4763,10 @@ func (x *EvacuateShardRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -5078,10 +5078,10 @@ func (x *EvacuateShardResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -5438,10 +5438,10 @@ func (x *FlushCacheRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -5719,10 +5719,10 @@ func (x *FlushCacheResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -6065,10 +6065,10 @@ func (x *DoctorRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -6346,10 +6346,10 @@ func (x *DoctorResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -6772,10 +6772,10 @@ func (x *StartShardEvacuationRequest) EmitProtobuf(mm *easyproto.MessageMarshale if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -7053,10 +7053,10 @@ func (x *StartShardEvacuationResponse) EmitProtobuf(mm *easyproto.MessageMarshal if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -7334,10 +7334,10 @@ func (x *GetShardEvacuationStatusRequest) EmitProtobuf(mm *easyproto.MessageMars if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -7830,10 +7830,10 @@ func (x *GetShardEvacuationStatusResponse_Body) EmitProtobuf(mm *easyproto.Messa if int32(x.Status) != 0 { mm.AppendInt32(5, int32(x.Status)) } - if x.Duration != nil && x.Duration.StableSize() != 0 { + if x.Duration != nil { x.Duration.EmitProtobuf(mm.AppendMessage(6)) } - if x.StartedAt != nil && x.StartedAt.StableSize() != 0 { + if x.StartedAt != nil { x.StartedAt.EmitProtobuf(mm.AppendMessage(7)) } if len(x.ErrorMessage) != 0 { @@ -8321,10 +8321,10 @@ func (x *GetShardEvacuationStatusResponse) EmitProtobuf(mm *easyproto.MessageMar if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -8602,10 +8602,10 @@ func (x *ResetShardEvacuationStatusRequest) EmitProtobuf(mm *easyproto.MessageMa if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -8883,10 +8883,10 @@ func (x *ResetShardEvacuationStatusResponse) EmitProtobuf(mm *easyproto.MessageM if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -9164,10 +9164,10 @@ func (x *StopShardEvacuationRequest) EmitProtobuf(mm *easyproto.MessageMarshaler if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -9445,10 +9445,10 @@ func (x *StopShardEvacuationResponse) EmitProtobuf(mm *easyproto.MessageMarshale if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -9613,7 +9613,7 @@ func (x *AddChainLocalOverrideRequest_Body) EmitProtobuf(mm *easyproto.MessageMa if x == nil { return } - if x.Target != nil && x.Target.StableSize() != 0 { + if x.Target != nil { x.Target.EmitProtobuf(mm.AppendMessage(1)) } if len(x.Chain) != 0 { @@ -9795,10 +9795,10 @@ func (x *AddChainLocalOverrideRequest) EmitProtobuf(mm *easyproto.MessageMarshal if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -10110,10 +10110,10 @@ func (x *AddChainLocalOverrideResponse) EmitProtobuf(mm *easyproto.MessageMarsha if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -10278,7 +10278,7 @@ func (x *GetChainLocalOverrideRequest_Body) EmitProtobuf(mm *easyproto.MessageMa if x == nil { return } - if x.Target != nil && x.Target.StableSize() != 0 { + if x.Target != nil { x.Target.EmitProtobuf(mm.AppendMessage(1)) } if len(x.ChainId) != 0 { @@ -10460,10 +10460,10 @@ func (x *GetChainLocalOverrideRequest) EmitProtobuf(mm *easyproto.MessageMarshal if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -10775,10 +10775,10 @@ func (x *GetChainLocalOverrideResponse) EmitProtobuf(mm *easyproto.MessageMarsha if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -10941,7 +10941,7 @@ func (x *ListChainLocalOverridesRequest_Body) EmitProtobuf(mm *easyproto.Message if x == nil { return } - if x.Target != nil && x.Target.StableSize() != 0 { + if x.Target != nil { x.Target.EmitProtobuf(mm.AppendMessage(1)) } } @@ -11094,10 +11094,10 @@ func (x *ListChainLocalOverridesRequest) EmitProtobuf(mm *easyproto.MessageMarsh if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -11423,10 +11423,10 @@ func (x *ListChainLocalOverridesResponse) EmitProtobuf(mm *easyproto.MessageMars if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -11738,10 +11738,10 @@ func (x *ListTargetsLocalOverridesRequest) EmitProtobuf(mm *easyproto.MessageMar if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -11907,7 +11907,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) EmitProtobuf(mm *easyproto.Mess return } for i := range x.Targets { - if x.Targets[i] != nil && x.Targets[i].StableSize() != 0 { + if x.Targets[i] != nil { x.Targets[i].EmitProtobuf(mm.AppendMessage(1)) } } @@ -12076,10 +12076,10 @@ func (x *ListTargetsLocalOverridesResponse) EmitProtobuf(mm *easyproto.MessageMa if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -12244,7 +12244,7 @@ func (x *RemoveChainLocalOverrideRequest_Body) EmitProtobuf(mm *easyproto.Messag if x == nil { return } - if x.Target != nil && x.Target.StableSize() != 0 { + if x.Target != nil { x.Target.EmitProtobuf(mm.AppendMessage(1)) } if len(x.ChainId) != 0 { @@ -12426,10 +12426,10 @@ func (x *RemoveChainLocalOverrideRequest) EmitProtobuf(mm *easyproto.MessageMars if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -12707,10 +12707,10 @@ func (x *RemoveChainLocalOverrideResponse) EmitProtobuf(mm *easyproto.MessageMar if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -12873,7 +12873,7 @@ func (x *RemoveChainLocalOverridesByTargetRequest_Body) EmitProtobuf(mm *easypro if x == nil { return } - if x.Target != nil && x.Target.StableSize() != 0 { + if x.Target != nil { x.Target.EmitProtobuf(mm.AppendMessage(1)) } } @@ -13026,10 +13026,10 @@ func (x *RemoveChainLocalOverridesByTargetRequest) EmitProtobuf(mm *easyproto.Me if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -13307,10 +13307,10 @@ func (x *RemoveChainLocalOverridesByTargetResponse) EmitProtobuf(mm *easyproto.M if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -13760,10 +13760,10 @@ func (x *SealWriteCacheRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -14120,7 +14120,7 @@ func (x *SealWriteCacheResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshale return } for i := range x.Results { - if x.Results[i] != nil && x.Results[i].StableSize() != 0 { + if x.Results[i] != nil { x.Results[i].EmitProtobuf(mm.AppendMessage(1)) } } @@ -14289,10 +14289,10 @@ func (x *SealWriteCacheResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -14618,10 +14618,10 @@ func (x *DetachShardsRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -14899,10 +14899,10 @@ func (x *DetachShardsResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index 9aff26a98b..3cc37245f0 100644 --- a/pkg/services/control/types_frostfs.pb.go +++ b/pkg/services/control/types_frostfs.pb.go @@ -549,7 +549,7 @@ func (x *NodeInfo) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendString(2, x.Addresses[j]) } for i := range x.Attributes { - if x.Attributes[i] != nil && x.Attributes[i].StableSize() != 0 { + if x.Attributes[i] != nil { x.Attributes[i].EmitProtobuf(mm.AppendMessage(3)) } } @@ -817,7 +817,7 @@ func (x *Netmap) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendUint64(1, x.Epoch) } for i := range x.Nodes { - if x.Nodes[i] != nil && x.Nodes[i].StableSize() != 0 { + if x.Nodes[i] != nil { x.Nodes[i].EmitProtobuf(mm.AppendMessage(2)) } } @@ -1013,7 +1013,7 @@ func (x *ShardInfo) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendString(2, x.MetabasePath) } for i := range x.Blobstor { - if x.Blobstor[i] != nil && x.Blobstor[i].StableSize() != 0 { + if x.Blobstor[i] != nil { x.Blobstor[i].EmitProtobuf(mm.AppendMessage(3)) } } diff --git a/pkg/services/tree/service_frostfs.pb.go b/pkg/services/tree/service_frostfs.pb.go index c4d44253d6..3c6ba21b78 100644 --- a/pkg/services/tree/service_frostfs.pb.go +++ b/pkg/services/tree/service_frostfs.pb.go @@ -70,7 +70,7 @@ func (x *AddRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendUint64(3, x.ParentId) } for i := range x.Meta { - if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + if x.Meta[i] != nil { x.Meta[i].EmitProtobuf(mm.AppendMessage(4)) } } @@ -346,10 +346,10 @@ func (x *AddRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -661,10 +661,10 @@ func (x *AddResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -852,7 +852,7 @@ func (x *AddByPathRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendString(4, x.Path[j]) } for i := range x.Meta { - if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + if x.Meta[i] != nil { x.Meta[i].EmitProtobuf(mm.AppendMessage(5)) } } @@ -1168,10 +1168,10 @@ func (x *AddByPathRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -1530,10 +1530,10 @@ func (x *AddByPathResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -1938,10 +1938,10 @@ func (x *RemoveRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2219,10 +2219,10 @@ func (x *RemoveResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2410,7 +2410,7 @@ func (x *MoveRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendUint64(4, x.NodeId) } for i := range x.Meta { - if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + if x.Meta[i] != nil { x.Meta[i].EmitProtobuf(mm.AppendMessage(5)) } } @@ -2712,10 +2712,10 @@ func (x *MoveRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -2993,10 +2993,10 @@ func (x *MoveResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -3553,10 +3553,10 @@ func (x *GetNodeByPathRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -3734,7 +3734,7 @@ func (x *GetNodeByPathResponse_Info) EmitProtobuf(mm *easyproto.MessageMarshaler mm.AppendUint64(2, x.Timestamp) } for i := range x.Meta { - if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + if x.Meta[i] != nil { x.Meta[i].EmitProtobuf(mm.AppendMessage(3)) } } @@ -3967,7 +3967,7 @@ func (x *GetNodeByPathResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler return } for i := range x.Nodes { - if x.Nodes[i] != nil && x.Nodes[i].StableSize() != 0 { + if x.Nodes[i] != nil { x.Nodes[i].EmitProtobuf(mm.AppendMessage(1)) } } @@ -4136,10 +4136,10 @@ func (x *GetNodeByPathResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -4506,7 +4506,7 @@ func (x *GetSubTreeRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { if len(x.BearerToken) != 0 { mm.AppendBytes(5, x.BearerToken) } - if x.OrderBy != nil && x.OrderBy.StableSize() != 0 { + if x.OrderBy != nil { x.OrderBy.EmitProtobuf(mm.AppendMessage(6)) } } @@ -4803,10 +4803,10 @@ func (x *GetSubTreeRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -4993,7 +4993,7 @@ func (x *GetSubTreeResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendUint64(3, x.Timestamp[j]) } for i := range x.Meta { - if x.Meta[i] != nil && x.Meta[i].StableSize() != 0 { + if x.Meta[i] != nil { x.Meta[i].EmitProtobuf(mm.AppendMessage(4)) } } @@ -5282,10 +5282,10 @@ func (x *GetSubTreeResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -5597,10 +5597,10 @@ func (x *TreeListRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -5926,10 +5926,10 @@ func (x *TreeListResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -6102,7 +6102,7 @@ func (x *ApplyRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { if len(x.TreeId) != 0 { mm.AppendString(2, x.TreeId) } - if x.Operation != nil && x.Operation.StableSize() != 0 { + if x.Operation != nil { x.Operation.EmitProtobuf(mm.AppendMessage(3)) } } @@ -6307,10 +6307,10 @@ func (x *ApplyRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -6588,10 +6588,10 @@ func (x *ApplyResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -6996,10 +6996,10 @@ func (x *GetOpLogRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -7162,7 +7162,7 @@ func (x *GetOpLogResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Operation != nil && x.Operation.StableSize() != 0 { + if x.Operation != nil { x.Operation.EmitProtobuf(mm.AppendMessage(1)) } } @@ -7315,10 +7315,10 @@ func (x *GetOpLogResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -7596,10 +7596,10 @@ func (x *HealthcheckResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } @@ -7877,10 +7877,10 @@ func (x *HealthcheckRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { if x == nil { return } - if x.Body != nil && x.Body.StableSize() != 0 { + if x.Body != nil { x.Body.EmitProtobuf(mm.AppendMessage(1)) } - if x.Signature != nil && x.Signature.StableSize() != 0 { + if x.Signature != nil { x.Signature.EmitProtobuf(mm.AppendMessage(2)) } } From d6b42972a81f18d4351d81b154f75815f39546ea Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 27 Aug 2024 16:09:13 +0300 Subject: [PATCH 0765/1413] [#1338] object: Fix audit patch stream Signed-off-by: Airat Arifullin --- pkg/services/object/audit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/audit.go b/pkg/services/object/audit.go index b924386d1c..39e1f9f2d5 100644 --- a/pkg/services/object/audit.go +++ b/pkg/services/object/audit.go @@ -204,7 +204,7 @@ func (a *auditPatchStream) CloseAndRecv(ctx context.Context) (*object.PatchRespo if err != nil { a.failed = true } - a.objectID = resp.GetBody().ObjectID + a.objectID = resp.GetBody().GetObjectID() audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Patch_FullMethodName, a.key, audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), !a.failed) From 6488ddee882ddb2facd8554aa274986076de0bbc Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 27 Aug 2024 16:09:59 +0300 Subject: [PATCH 0766/1413] [#1338] object: Fix range provider in `Patch` handler Signed-off-by: Airat Arifullin --- pkg/services/object/patch/range_provider.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/services/object/patch/range_provider.go b/pkg/services/object/patch/range_provider.go index 755c5bf60b..cb3f7c342b 100644 --- a/pkg/services/object/patch/range_provider.go +++ b/pkg/services/object/patch/range_provider.go @@ -30,6 +30,12 @@ type rangeProvider struct { var _ patcherSDK.RangeProvider = (*rangeProvider)(nil) func (r *rangeProvider) GetRange(ctx context.Context, rng *objectSDK.Range) io.Reader { + // Remote GetRange request to a container node uses an SDK-client that fails range validation + // with zero-length. However, from the patcher's point of view, such request is still valid. + if rng.GetLength() == 0 { + return &nopReader{} + } + pipeReader, pipeWriter := io.Pipe() var rngPrm getsvc.RangePrm @@ -61,3 +67,9 @@ func (r *rangeProvider) GetRange(ctx context.Context, rng *objectSDK.Range) io.R return pipeReader } + +type nopReader struct{} + +func (nopReader) Read(_ []byte) (int, error) { + return 0, io.EOF +} From 7abbdca0641f1526c347da60012f437be57254e8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 28 Aug 2024 13:56:45 +0300 Subject: [PATCH 0767/1413] [#1340] getSvc: Fix access denied error handling Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/get.go | 8 +++++++ pkg/services/object/get/remote.go | 7 +++++- pkg/services/object/get/v2/get_forwarder.go | 26 ++++++++++++--------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 07a2f3a724..03b7f8bf2f 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -2,9 +2,11 @@ package getsvc import ( "context" + "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) @@ -120,6 +122,12 @@ func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) { exec.log.Debug(logs.OperationFinishedWithError, zap.Error(exec.err), ) + var errAccessDenied *apistatus.ObjectAccessDenied + if execCnr && errors.As(exec.err, &errAccessDenied) { + // Local get can't return access denied error, so this error was returned by + // write to the output stream. So there is no need to try to find object on other nodes. + return + } if execCnr { exec.executeOnContainer(ctx) diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index ce9abfe1cb..163767c432 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -31,6 +31,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { var errECInfo *objectSDK.ECInfoError var errRemoved *apistatus.ObjectAlreadyRemoved var errOutOfRange *apistatus.ObjectOutOfRange + var errAccessDenied *apistatus.ObjectAccessDenied switch { default: @@ -38,7 +39,11 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { if r.status != statusEC { // for raw requests, continue to collect other parts r.status = statusUndefined - r.err = new(apistatus.ObjectNotFound) + if errors.As(err, &errAccessDenied) { + r.err = err + } else { + r.err = new(apistatus.ObjectNotFound) + } } return false case err == nil: diff --git a/pkg/services/object/get/v2/get_forwarder.go b/pkg/services/object/get/v2/get_forwarder.go index 774f986435..18194c740c 100644 --- a/pkg/services/object/get/v2/get_forwarder.go +++ b/pkg/services/object/get/v2/get_forwarder.go @@ -23,12 +23,14 @@ import ( ) type getRequestForwarder struct { - OnceResign sync.Once - OnceHeaderSending sync.Once - GlobalProgress int - Key *ecdsa.PrivateKey - Request *objectV2.GetRequest - Stream *streamObjectWriter + OnceResign sync.Once + GlobalProgress int + Key *ecdsa.PrivateKey + Request *objectV2.GetRequest + Stream *streamObjectWriter + + headerSent bool + headerSentGuard sync.Mutex } func (f *getRequestForwarder) forwardRequestToNode(ctx context.Context, addr network.Address, c client.MultiAddressClient, pubkey []byte) (*objectSDK.Object, error) { @@ -83,13 +85,15 @@ func (f *getRequestForwarder) writeHeader(ctx context.Context, v *objectV2.GetOb obj.SetSignature(v.GetSignature()) obj.SetHeader(v.GetHeader()) - var err error - f.OnceHeaderSending.Do(func() { - err = f.Stream.WriteHeader(ctx, objectSDK.NewFromV2(obj)) - }) - if err != nil { + f.headerSentGuard.Lock() + defer f.headerSentGuard.Unlock() + if f.headerSent { + return nil + } + if err := f.Stream.WriteHeader(ctx, objectSDK.NewFromV2(obj)); err != nil { return errCouldNotWriteObjHeader(err) } + f.headerSent = true return nil } From 01b6f1733cbc9d0ce133b5970a28817423686e2c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 28 Aug 2024 14:29:07 +0300 Subject: [PATCH 0768/1413] [#1341] Makefile: Build linter with -trimpath Fix error with go1.23: ``` Error: build linters: unable to load custom analyzer "truecloudlab-linters": ../linters/bin/external_linters.so, plugin.Open("/repo/frostfs/linters/bin/external_linters"): plugin was built with a different version of package cmp Failed executing command with error: build linters: unable to load custom analyzer "truecloudlab-linters": ../linters/bin/external_linters.so, plugin.Open("/repo/frostfs/linters/bin/external_linters"): plugin was built with a different version of package cmp ``` Signed-off-by: Evgenii Stratonikov --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 94a8a14c36..3a6dea7c3b 100755 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.22 LINT_VERSION ?= 1.60.1 -TRUECLOUDLAB_LINT_VERSION ?= 0.0.6 +TRUECLOUDLAB_LINT_VERSION ?= 0.0.7 PROTOC_VERSION ?= 25.0 PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) PROTOC_OS_VERSION=osx-x86_64 @@ -197,7 +197,7 @@ lint-install: @@make -C $(TMP_DIR)/linters lib CGO_ENABLED=1 OUT_DIR=$(OUTPUT_LINT_DIR) @rm -rf $(TMP_DIR)/linters @rmdir $(TMP_DIR) 2>/dev/null || true - @CGO_ENABLED=1 GOBIN=$(LINT_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@v$(LINT_VERSION) + @CGO_ENABLED=1 GOBIN=$(LINT_DIR) go install -trimpath github.com/golangci/golangci-lint/cmd/golangci-lint@v$(LINT_VERSION) # Run linters lint: From 7e97df4878b9bf95f88712394bb21201eb072012 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 28 Aug 2024 14:31:35 +0300 Subject: [PATCH 0769/1413] [#1341] Makefile: Update golangci-lint Signed-off-by: Evgenii Stratonikov --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3a6dea7c3b..71492ef171 100755 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ HUB_IMAGE ?= truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.22 -LINT_VERSION ?= 1.60.1 +LINT_VERSION ?= 1.60.3 TRUECLOUDLAB_LINT_VERSION ?= 0.0.7 PROTOC_VERSION ?= 25.0 PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) From 03976c6ed5df58b83f788a18416e27f9144342b1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 28 Aug 2024 14:45:57 +0300 Subject: [PATCH 0770/1413] [#1341] .golangci.yml: Replace exportloopref with copyloopvar exportloopref is deprecated. gopatch: ``` @@ var index, value identifier var slice expression @@ for index, value := range slice { ... -value := value ... } @@ var index, value identifier var slice expression @@ for index, value := range slice { ... -index := index ... } @@ var value identifier var channel expression @@ for value := range channel { ... -value := value ... } ``` Signed-off-by: Evgenii Stratonikov --- .golangci.yml | 2 +- cmd/frostfs-adm/internal/modules/morph/generate/generate.go | 2 -- cmd/frostfs-cli/modules/container/list.go | 1 - cmd/frostfs-cli/modules/object/nodes.go | 3 --- .../blobstor/blobovniczatree/rebuild.go | 3 --- pkg/local_object_storage/blobstor/info.go | 1 - pkg/local_object_storage/engine/control.go | 2 -- pkg/local_object_storage/engine/shards.go | 1 - pkg/local_object_storage/engine/writecache.go | 1 - pkg/local_object_storage/pilorama/forest_test.go | 1 - pkg/local_object_storage/writecache/flush_test.go | 1 - pkg/services/object/get/assemblerec.go | 1 - pkg/services/object/put/common.go | 1 - pkg/services/object/put/ec.go | 1 - pkg/services/policer/ec.go | 2 -- pkg/services/tree/sync.go | 6 +----- pkg/services/tree/sync_test.go | 2 -- 17 files changed, 2 insertions(+), 29 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 2e9e78fc3b..971f0d0e79 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -67,7 +67,7 @@ linters: - bidichk - durationcheck - exhaustive - - exportloopref + - copyloopvar - gofmt - goimports - misspell diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go index c7de599e57..7af7767975 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -73,7 +73,6 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er return nil, fmt.Errorf("can't fetch password: %w", err) } - i := i errG.Go(func() error { p := filepath.Join(walletDir, innerring.GlagoliticLetter(i).String()+".json") f, err := os.OpenFile(p, os.O_CREATE, 0o644) @@ -107,7 +106,6 @@ func initializeWallets(v *viper.Viper, walletDir string, size int) ([]string, er // Create consensus account with 2*N/3+1 multi-signature. bftCount := smartcontract.GetDefaultHonestNodeCount(size) for i := range wallets { - i := i ps := pubs.Copy() errG.Go(func() error { if err := addMultisigAccount(wallets[i], majCount, constants.CommitteeAccountName, passwords[i], ps); err != nil { diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index a1410d7a07..6d0019ec4c 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -70,7 +70,6 @@ var listContainersCmd = &cobra.Command{ continue } - cnrID := cnrID prmGet.ClientParams.ContainerID = &cnrID res, err := internalclient.GetContainer(cmd.Context(), prmGet) if err != nil { diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 4efe04d162..896f6f17f0 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -393,8 +393,6 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, pk *ecdsa. eg, egCtx := errgroup.WithContext(cmd.Context()) for _, cand := range candidates { - cand := cand - eg.Go(func() error { cli, err := createClient(egCtx, cmd, cand, pk) if err != nil { @@ -405,7 +403,6 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, pk *ecdsa. } for _, object := range objects { - object := object eg.Go(func() error { stored, err := isObjectStoredOnNode(egCtx, cmd, object.containerID, object.objectID, cli, pk) resultMtx.Lock() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 93ef8ba2ea..cfc17cfaee 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -160,9 +160,6 @@ func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovn eg, egCtx := errgroup.WithContext(ctx) for addr, data := range batch { - addr := addr - data := data - if err := limiter.AcquireWorkSlot(egCtx); err != nil { _ = eg.Wait() return result.Load(), err diff --git a/pkg/local_object_storage/blobstor/info.go b/pkg/local_object_storage/blobstor/info.go index 8a5bb870af..c1c47f3bb1 100644 --- a/pkg/local_object_storage/blobstor/info.go +++ b/pkg/local_object_storage/blobstor/info.go @@ -43,7 +43,6 @@ func (b *BlobStor) ObjectsCount(ctx context.Context) (uint64, error) { eg, egCtx := errgroup.WithContext(ctx) for i := range b.storage { - i := i eg.Go(func() error { v, e := b.storage[i].Storage.ObjectsCount(egCtx) if e != nil { diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index 03196400a0..4778cf539b 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -82,8 +82,6 @@ func (e *StorageEngine) Init(ctx context.Context) error { } for id, sh := range e.shards { - id := id - sh := sh eg.Go(func() error { if err := sh.Init(ctx); err != nil { errCh <- shardInitError{ diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 56d4fcd4af..980b38a632 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -367,7 +367,6 @@ func (e *StorageEngine) closeShards(deletedShards []hashedShard) error { var multiErrGuard sync.Mutex var eg errgroup.Group for _, sh := range deletedShards { - sh := sh eg.Go(func() error { err := sh.SetMode(mode.Disabled) if err != nil { diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 3e8f387ef8..7710bc7f4c 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -102,7 +102,6 @@ func (e *StorageEngine) SealWriteCache(ctx context.Context, prm SealWriteCachePr eg, egCtx := errgroup.WithContext(ctx) for _, shardID := range prm.ShardIDs { - shardID := shardID eg.Go(func() error { e.mtx.RLock() sh, ok := e.shards[shardID.String()] diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index ecca9842f1..41d7a567c3 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -1459,7 +1459,6 @@ func testTreeLastSyncHeight(t *testing.T, f ForestStorage) { func TestForest_ListTrees(t *testing.T) { for i := range providers { - i := i t.Run(providers[i].name, func(t *testing.T) { testTreeListTrees(t, providers[i].construct) }) diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index 3c951bebed..a637da45d0 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -170,7 +170,6 @@ func runFlushTest[Option any]( t.Run("ignore errors", func(t *testing.T) { for _, f := range failures { - f := f t.Run(f.Desc, func(t *testing.T) { errCountOpt, errCount := errCountOption() wc, bs, mb := newCache(t, createCacheFn, smallSize, errCountOpt) diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index 6a02673c36..dde0d7dada 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -170,7 +170,6 @@ func (a *assemblerec) processECNodesRequests(ctx context.Context, nodes []placem eg.SetLimit(dataCount) for _, ch := range a.ecInfo.localChunks { - ch := ch eg.Go(func() error { select { case <-ctx.Done(): diff --git a/pkg/services/object/put/common.go b/pkg/services/object/put/common.go index 6696a192b9..cbb7f5f333 100644 --- a/pkg/services/object/put/common.go +++ b/pkg/services/object/put/common.go @@ -71,7 +71,6 @@ func (n *nodeIterator) forEachAddress(ctx context.Context, traverser *placement. var wg sync.WaitGroup for _, addr := range addrs { - addr := addr if ok := n.mExclude[string(addr.PublicKey())]; ok != nil { if *ok { traverser.SubmitSuccess() diff --git a/pkg/services/object/put/ec.go b/pkg/services/object/put/ec.go index fbb51912c9..1fadf65fe3 100644 --- a/pkg/services/object/put/ec.go +++ b/pkg/services/object/put/ec.go @@ -216,7 +216,6 @@ func (e *ecWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er } for idx := range parts { - idx := idx eg.Go(func() error { return e.writePart(egCtx, parts[idx], idx, nodes, visited) }) diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index 0a118797dd..61a65fc21f 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -357,8 +357,6 @@ func (p *Policer) collectExistedChunks(ctx context.Context, objInfo objectcore.I parts := make([]*objectSDK.Object, objInfo.ECInfo.Total) errGroup, egCtx := errgroup.WithContext(ctx) for idx, nodes := range existedChunks { - idx := idx - nodes := nodes errGroup.Go(func() error { var objID oid.Address objID.SetContainer(parentAddress.Container()) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 0f85f50b12..be22074a51 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -190,8 +190,6 @@ func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID s var prev *pilorama.Move for m := range operationStream { - m := m - // skip already applied op if prev != nil && prev.Time == m.Time { continue @@ -287,8 +285,6 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, allNodesSynced.Store(true) for i, n := range nodes { - i := i - n := n errGroup.Go(func() error { var nodeSynced bool n.IterateNetworkEndpoints(func(addr string) bool { @@ -421,7 +417,7 @@ func (s *Service) syncContainers(ctx context.Context, cnrs []cid.ID) { var wg sync.WaitGroup for _, cnr := range cnrs { wg.Add(1) - cnr := cnr + err := s.syncPool.Submit(func() { defer wg.Done() s.log.Debug(logs.TreeSyncingContainerTrees, zap.Stringer("cid", cnr)) diff --git a/pkg/services/tree/sync_test.go b/pkg/services/tree/sync_test.go index 190b4ccbbe..497d90554e 100644 --- a/pkg/services/tree/sync_test.go +++ b/pkg/services/tree/sync_test.go @@ -51,8 +51,6 @@ func Test_mergeOperationStreams(t *testing.T) { // generate and put values to all chans for i, ch := range nodeOpChans { - i := i - ch := ch go func() { for _, tm := range tt.opTimes[i] { op := &pilorama.Move{} From 6c2146bbc13e118d1518010d144ebc4dfadd5d6d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 28 Aug 2024 18:32:30 +0300 Subject: [PATCH 0771/1413] [#1334] metabase: Add upgrade from v2 to v3 Signed-off-by: Dmitrii Stepanov --- .../internal/modules/metabase/root.go | 15 + .../internal/modules/metabase/upgrade.go | 86 +++++ cmd/frostfs-adm/internal/modules/root.go | 2 + pkg/local_object_storage/metabase/upgrade.go | 364 ++++++++++++++++++ .../metabase/upgrade_test.go | 215 +++++++++++ pkg/local_object_storage/metabase/util.go | 9 +- pkg/local_object_storage/metabase/version.go | 15 + 7 files changed, 703 insertions(+), 3 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/metabase/root.go create mode 100644 cmd/frostfs-adm/internal/modules/metabase/upgrade.go create mode 100644 pkg/local_object_storage/metabase/upgrade.go create mode 100644 pkg/local_object_storage/metabase/upgrade_test.go diff --git a/cmd/frostfs-adm/internal/modules/metabase/root.go b/cmd/frostfs-adm/internal/modules/metabase/root.go new file mode 100644 index 0000000000..5b21ed2730 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/metabase/root.go @@ -0,0 +1,15 @@ +package metabase + +import "github.com/spf13/cobra" + +// RootCmd is a root command of config section. +var RootCmd = &cobra.Command{ + Use: "metabase", + Short: "Section for metabase commands", +} + +func init() { + RootCmd.AddCommand(UpgradeCmd) + + initUpgradeCommand() +} diff --git a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go new file mode 100644 index 0000000000..83e085df48 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go @@ -0,0 +1,86 @@ +package metabase + +import ( + "errors" + "fmt" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + engineconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine" + shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard" + meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "github.com/spf13/cobra" +) + +const ( + pathFlag = "path" + noCompactFlag = "no-compact" +) + +var errNoPathsFound = errors.New("no metabase paths found") + +var path string + +var UpgradeCmd = &cobra.Command{ + Use: "upgrade", + Short: "Upgrade metabase to latest version", + RunE: upgrade, +} + +func upgrade(cmd *cobra.Command, _ []string) error { + configFile, err := cmd.Flags().GetString(commonflags.ConfigFlag) + if err != nil { + return err + } + configDir, err := cmd.Flags().GetString(commonflags.ConfigDirFlag) + if err != nil { + return err + } + noCompact, _ := cmd.Flags().GetBool(noCompactFlag) + var paths []string + if path != "" { + paths = append(paths, path) + } + appCfg := config.New(configFile, configDir, config.EnvPrefix) + if err := engineconfig.IterateShards(appCfg, false, func(sc *shardconfig.Config) error { + paths = append(paths, sc.Metabase().Path()) + return nil + }); err != nil { + return fmt.Errorf("failed to get metabase paths: %w", err) + } + if len(paths) == 0 { + return errNoPathsFound + } + cmd.Println("found", len(paths), "metabases:") + for i, path := range paths { + cmd.Println(i+1, ":", path) + } + result := make(map[string]bool) + for _, path := range paths { + cmd.Println("upgrading metabase", path, "...") + if err := meta.Upgrade(cmd.Context(), path, !noCompact, func(a ...any) { + cmd.Println(append([]any{time.Now().Format(time.RFC3339), ":", path, ":"}, a...)...) + }); err != nil { + result[path] = false + cmd.Println("error: failed to upgrade metabase", path, ":", err) + } else { + result[path] = true + cmd.Println("metabase", path, "upgraded successfully") + } + } + for mb, ok := range result { + if ok { + cmd.Println(mb, ": success") + } else { + cmd.Println(mb, ": failed") + } + } + return nil +} + +func initUpgradeCommand() { + flags := UpgradeCmd.Flags() + flags.StringVar(&path, pathFlag, "", "Path to metabase file") + flags.Bool(noCompactFlag, false, "Do not compact upgraded metabase file") +} diff --git a/cmd/frostfs-adm/internal/modules/root.go b/cmd/frostfs-adm/internal/modules/root.go index 8595483ab9..defd898c8d 100644 --- a/cmd/frostfs-adm/internal/modules/root.go +++ b/cmd/frostfs-adm/internal/modules/root.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/storagecfg" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" @@ -41,6 +42,7 @@ func init() { rootCmd.AddCommand(config.RootCmd) rootCmd.AddCommand(morph.RootCmd) rootCmd.AddCommand(storagecfg.RootCmd) + rootCmd.AddCommand(metabase.RootCmd) rootCmd.AddCommand(autocomplete.Command("frostfs-adm")) rootCmd.AddCommand(gendoc.Command(rootCmd, gendoc.Options{})) diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go new file mode 100644 index 0000000000..014e50286b --- /dev/null +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -0,0 +1,364 @@ +package meta + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "os" + "strconv" + "sync/atomic" + "time" + + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.etcd.io/bbolt" + "golang.org/x/sync/errgroup" +) + +const ( + upgradeLogFrequency = 50_000 + upgradeWorkersCount = 1_000 + compactMaxTxSize = 256 << 20 + upgradeTimeout = 1 * time.Second +) + +var updates = map[uint64]func(ctx context.Context, db *bbolt.DB, log func(a ...any)) error{ + 2: upgradeFromV2ToV3, +} + +func Upgrade(ctx context.Context, path string, compact bool, log func(a ...any)) error { + if _, err := os.Stat(path); err != nil { + return fmt.Errorf("check metabase existence: %w", err) + } + opts := bbolt.DefaultOptions + opts.Timeout = upgradeTimeout + db, err := bbolt.Open(path, os.ModePerm, opts) + if err != nil { + return fmt.Errorf("open metabase: %w", err) + } + var version uint64 + if err := db.View(func(tx *bbolt.Tx) error { + var e error + version, e = currentVersion(tx) + return e + }); err != nil { + return err + } + updater, found := updates[version] + if !found { + return fmt.Errorf("unsupported version %d: no update available", version) + } + if err := updater(ctx, db, log); err != nil { + return fmt.Errorf("update metabase schema: %w", err) + } + if compact { + log("compacting metabase...") + err := compactDB(db) + if err != nil { + return fmt.Errorf("compact metabase: %w", err) + } + log("metabase compacted") + } + return db.Close() +} + +func compactDB(db *bbolt.DB) error { + sourcePath := db.Path() + tmpFileName := sourcePath + "." + time.Now().Format(time.RFC3339) + f, err := os.Stat(sourcePath) + if err != nil { + return err + } + dst, err := bbolt.Open(tmpFileName, f.Mode(), &bbolt.Options{ + Timeout: 100 * time.Millisecond, + }) + if err != nil { + return fmt.Errorf("can't open new metabase to compact: %w", err) + } + if err := bbolt.Compact(dst, db, compactMaxTxSize); err != nil { + return fmt.Errorf("compact metabase: %w", errors.Join(err, dst.Close(), os.Remove(tmpFileName))) + } + if err := dst.Close(); err != nil { + return fmt.Errorf("close compacted metabase: %w", errors.Join(err, os.Remove(tmpFileName))) + } + if err := db.Close(); err != nil { + return fmt.Errorf("close source metabase: %w", errors.Join(err, os.Remove(tmpFileName))) + } + if err := os.Rename(tmpFileName, sourcePath); err != nil { + return fmt.Errorf("replace source metabase with compacted: %w", errors.Join(err, os.Remove(tmpFileName))) + } + return nil +} + +func upgradeFromV2ToV3(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { + if err := createExpirationEpochBuckets(ctx, db, log); err != nil { + return err + } + if err := dropUserAttributes(ctx, db, log); err != nil { + return err + } + if err := dropOwnerIDIndex(ctx, db, log); err != nil { + return err + } + if err := dropPayloadChecksumIndex(ctx, db, log); err != nil { + return err + } + return db.Update(func(tx *bbolt.Tx) error { + return updateVersion(tx, version) + }) +} + +type objectIDToExpEpoch struct { + containerID cid.ID + objectID oid.ID + expirationEpoch uint64 +} + +func createExpirationEpochBuckets(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { + log("filling expiration epoch buckets...") + if err := db.Update(func(tx *bbolt.Tx) error { + _, err := tx.CreateBucketIfNotExists(expEpochToObjectBucketName) + return err + }); err != nil { + return err + } + objects := make(chan objectIDToExpEpoch) + eg, ctx := errgroup.WithContext(ctx) + eg.Go(func() error { + return selectObjectsWithExpirationEpoch(ctx, db, objects) + }) + var count atomic.Uint64 + for i := 0; i < upgradeWorkersCount; i++ { + eg.Go(func() error { + for { + select { + case <-ctx.Done(): + return ctx.Err() + case obj, ok := <-objects: + if !ok { + return nil + } + if err := db.Batch(func(tx *bbolt.Tx) error { + if err := putUniqueIndexItem(tx, namedBucketItem{ + name: expEpochToObjectBucketName, + key: expirationEpochKey(obj.expirationEpoch, obj.containerID, obj.objectID), + val: zeroValue, + }); err != nil { + return err + } + val := make([]byte, epochSize) + binary.LittleEndian.PutUint64(val, obj.expirationEpoch) + return putUniqueIndexItem(tx, namedBucketItem{ + name: objectToExpirationEpochBucketName(obj.containerID, make([]byte, bucketKeySize)), + key: objectKey(obj.objectID, make([]byte, objectKeySize)), + val: val, + }) + }); err != nil { + return err + } + } + if c := count.Add(1); c%upgradeLogFrequency == 0 { + log("expiration epoch filled for", c, "objects...") + } + } + }) + } + err := eg.Wait() + if err != nil { + log("expiration epoch buckets completed completed with error:", err) + return err + } + log("filling expiration epoch buckets completed successfully, total", count.Load(), "objects") + return nil +} + +func selectObjectsWithExpirationEpoch(ctx context.Context, db *bbolt.DB, objects chan objectIDToExpEpoch) error { + defer close(objects) + + const batchSize = 1000 + it := &objectsWithExpirationEpochBatchIterator{ + lastAttributeKey: usrAttrPrefix, + } + for { + if err := getNextObjectsWithExpirationEpochBatch(ctx, db, it, batchSize); err != nil { + return err + } + for _, item := range it.items { + select { + case <-ctx.Done(): + return ctx.Err() + case objects <- item: + } + } + + if len(it.items) < batchSize { + return nil + } + it.items = nil + } +} + +var ( + usrAttrPrefix = []byte{userAttributePrefix} + errBatchSizeLimit = errors.New("batch size limit") +) + +type objectsWithExpirationEpochBatchIterator struct { + lastAttributeKey []byte + lastAttributeValue []byte + lastAttrKeyValueItem []byte + items []objectIDToExpEpoch +} + +// - {prefix}{containerID}{attributeKey} <- bucket +// -- {attributeValue} <- bucket, expirationEpoch +// --- {objectID}: zeroValue <- record + +func getNextObjectsWithExpirationEpochBatch(ctx context.Context, db *bbolt.DB, it *objectsWithExpirationEpochBatchIterator, batchSize int) error { + seekAttrValue := it.lastAttributeValue + seekAttrKVItem := it.lastAttrKeyValueItem + err := db.View(func(tx *bbolt.Tx) error { + attrKeyC := tx.Cursor() + for attrKey, _ := attrKeyC.Seek(it.lastAttributeKey); attrKey != nil && bytes.HasPrefix(attrKey, usrAttrPrefix); attrKey, _ = attrKeyC.Next() { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if len(attrKey) <= 1+cidSize { + continue + } + attributeKey := string(attrKey[1+cidSize:]) + if attributeKey != objectV2.SysAttributeExpEpochNeoFS && attributeKey != objectV2.SysAttributeExpEpoch { + continue + } + var containerID cid.ID + if err := containerID.Decode(attrKey[1 : 1+cidSize]); err != nil { + return fmt.Errorf("decode container id from user attribute bucket: %w", err) + } + if err := iterateExpirationAttributeKeyBucket(ctx, tx.Bucket(attrKey), it, batchSize, containerID, attrKey, seekAttrValue, seekAttrKVItem); err != nil { + return err + } + seekAttrValue = nil + seekAttrKVItem = nil + } + return nil + }) + if err != nil && !errors.Is(err, errBatchSizeLimit) { + return err + } + return nil +} + +func iterateExpirationAttributeKeyBucket(ctx context.Context, b *bbolt.Bucket, it *objectsWithExpirationEpochBatchIterator, batchSize int, containerID cid.ID, attrKey, seekAttrValue, seekAttrKVItem []byte) error { + attrValueC := b.Cursor() + for attrValue, v := attrValueC.Seek(seekAttrValue); attrValue != nil; attrValue, v = attrValueC.Next() { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if v != nil { + continue // need to iterate over buckets, not records + } + expirationEpoch, err := strconv.ParseUint(string(attrValue), 10, 64) + if err != nil { + return fmt.Errorf("could not parse expiration epoch: %w", err) + } + expirationEpochBucket := b.Bucket(attrValue) + attrKeyValueC := expirationEpochBucket.Cursor() + for attrKeyValueItem, v := attrKeyValueC.Seek(seekAttrKVItem); attrKeyValueItem != nil; attrKeyValueItem, v = attrKeyValueC.Next() { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + if v == nil { + continue // need to iterate over records, not buckets + } + if bytes.Equal(it.lastAttributeKey, attrKey) && bytes.Equal(it.lastAttributeValue, attrValue) && bytes.Equal(it.lastAttrKeyValueItem, attrKeyValueItem) { + continue + } + var objectID oid.ID + if err := objectID.Decode(attrKeyValueItem); err != nil { + return fmt.Errorf("decode object id from container '%s' expiration epoch %d: %w", containerID, expirationEpoch, err) + } + it.lastAttributeKey = bytes.Clone(attrKey) + it.lastAttributeValue = bytes.Clone(attrValue) + it.lastAttrKeyValueItem = bytes.Clone(attrKeyValueItem) + it.items = append(it.items, objectIDToExpEpoch{ + containerID: containerID, + objectID: objectID, + expirationEpoch: expirationEpoch, + }) + if len(it.items) == batchSize { + return errBatchSizeLimit + } + } + seekAttrKVItem = nil + } + return nil +} + +func dropUserAttributes(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { + return dropBucketsByPrefix(ctx, db, []byte{userAttributePrefix}, func(a ...any) { + log(append([]any{"user attributes:"}, a...)...) + }) +} + +func dropOwnerIDIndex(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { + return dropBucketsByPrefix(ctx, db, []byte{ownerPrefix}, func(a ...any) { + log(append([]any{"owner ID index:"}, a...)...) + }) +} + +func dropPayloadChecksumIndex(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { + return dropBucketsByPrefix(ctx, db, []byte{payloadHashPrefix}, func(a ...any) { + log(append([]any{"payload checksum:"}, a...)...) + }) +} + +func dropBucketsByPrefix(ctx context.Context, db *bbolt.DB, prefix []byte, log func(a ...any)) error { + log("deleting buckets...") + const batch = 1000 + var count uint64 + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + var keys [][]byte + if err := db.View(func(tx *bbolt.Tx) error { + c := tx.Cursor() + for k, _ := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix) && len(keys) < batch; k, _ = c.Next() { + keys = append(keys, bytes.Clone(k)) + } + return nil + }); err != nil { + log("deleting buckets completed with an error:", err) + return err + } + if len(keys) == 0 { + log("deleting buckets completed successfully, deleted", count, "buckets") + return nil + } + if err := db.Update(func(tx *bbolt.Tx) error { + for _, k := range keys { + if err := tx.DeleteBucket(k); err != nil { + return err + } + } + return nil + }); err != nil { + log("deleting buckets completed with an error:", err) + return err + } + if count += uint64(len(keys)); count%upgradeLogFrequency == 0 { + log("deleted", count, "buckets") + } + } +} diff --git a/pkg/local_object_storage/metabase/upgrade_test.go b/pkg/local_object_storage/metabase/upgrade_test.go new file mode 100644 index 0000000000..dc3d7d07dc --- /dev/null +++ b/pkg/local_object_storage/metabase/upgrade_test.go @@ -0,0 +1,215 @@ +//go:build integration + +package meta + +import ( + "context" + "fmt" + "io" + "os" + "strconv" + "testing" + "time" + + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" +) + +const upgradeFilePath = "/path/to/metabase.v2" + +func TestUpgradeV2ToV3(t *testing.T) { + path := createTempCopy(t, upgradeFilePath) + defer func() { + require.NoError(t, os.Remove(path)) + }() + db := New(WithPath(path), WithEpochState(epochState{e: 1000}), WithLogger(test.NewLogger(t))) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.ErrorIs(t, db.Init(), ErrOutdatedVersion) + require.NoError(t, db.Close()) + require.NoError(t, Upgrade(context.Background(), path, true, t.Log)) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.Init()) + require.NoError(t, db.Close()) + fmt.Println() +} + +func createTempCopy(t *testing.T, path string) string { + src, err := os.Open(path) + require.NoError(t, err) + + tmpPath := upgradeFilePath + time.Now().Format(time.RFC3339) + dest, err := os.Create(tmpPath) + require.NoError(t, err) + + _, err = io.Copy(dest, src) + require.NoError(t, err) + + require.NoError(t, src.Close()) + require.NoError(t, dest.Close()) + + return tmpPath +} + +func TestGenerateMetabaseFile(t *testing.T) { + t.Skip("for generating db") + const ( + containersCount = 10_000 + simpleObjectsCount = 500_000 + complexObjectsCount = 500_000 // x2 + deletedByGCMarksCount = 100_000 + deletedByTombstoneCount = 100_000 // x2 + lockedCount = 100_000 // x2 + + allocSize = 128 << 20 + generateWorkersCount = 1_000 + minEpoch = 1_000 + maxFilename = 1_000 + maxStorageID = 10_000 + ) + + db := New(WithPath(upgradeFilePath), WithEpochState(epochState{e: minEpoch}), WithLogger(test.NewLogger(t))) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + db.boltDB.AllocSize = allocSize + db.boltDB.NoSync = true + require.NoError(t, db.Init()) + containers := make([]cid.ID, containersCount) + for i := range containers { + containers[i] = cidtest.ID() + } + oc, err := db.ObjectCounters() + require.NoError(t, err) + require.True(t, oc.IsZero()) + eg, ctx := errgroup.WithContext(context.Background()) + eg.SetLimit(generateWorkersCount) + // simple objects + for i := 0; i < simpleObjectsCount; i++ { + i := i + eg.Go(func() error { + obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) + testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(obj, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10)) + _, err := db.Put(ctx, PutPrm{ + obj: obj, + id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), + }) + require.NoError(t, err) + return nil + }) + } + require.NoError(t, eg.Wait()) + db.log.Info("simple objects generated") + eg, ctx = errgroup.WithContext(context.Background()) + eg.SetLimit(generateWorkersCount) + // complex objects + for i := 0; i < complexObjectsCount; i++ { + i := i + eg.Go(func() error { + parent := testutil.GenerateObjectWithCID(containers[i%len(containers)]) + child := testutil.GenerateObjectWithCID(containers[i%len(containers)]) + child.SetParent(parent) + idParent, _ := parent.ID() + child.SetParentID(idParent) + testutil.AddAttribute(child, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(parent, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(child, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10)) + testutil.AddAttribute(parent, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10)) + _, err := db.Put(ctx, PutPrm{ + obj: child, + }) + require.NoError(t, err) + return nil + }) + } + require.NoError(t, eg.Wait()) + db.log.Info("complex objects generated") + eg, ctx = errgroup.WithContext(context.Background()) + eg.SetLimit(generateWorkersCount) + // simple objects deleted by gc marks + for i := 0; i < deletedByGCMarksCount; i++ { + i := i + eg.Go(func() error { + obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) + testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + _, err := db.Put(ctx, PutPrm{ + obj: obj, + id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), + }) + require.NoError(t, err) + _, err = db.Inhume(ctx, InhumePrm{ + target: []oid.Address{object.AddressOf(obj)}, + }) + require.NoError(t, err) + return nil + }) + } + require.NoError(t, eg.Wait()) + db.log.Info("simple objects deleted by gc marks generated") + eg, ctx = errgroup.WithContext(context.Background()) + eg.SetLimit(10000) + // simple objects deleted by tombstones + for i := 0; i < deletedByTombstoneCount; i++ { + i := i + eg.Go(func() error { + obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) + testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + _, err := db.Put(ctx, PutPrm{ + obj: obj, + id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), + }) + tomb := testutil.GenerateObjectWithCID(containers[i%len(containers)]) + tomb.SetType(objectSDK.TypeTombstone) + _, err = db.Put(ctx, PutPrm{ + obj: tomb, + id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), + }) + require.NoError(t, err) + tombAddr := object.AddressOf(tomb) + _, err = db.Inhume(ctx, InhumePrm{ + target: []oid.Address{object.AddressOf(obj)}, + tomb: &tombAddr, + }) + require.NoError(t, err) + return nil + }) + } + require.NoError(t, eg.Wait()) + db.log.Info("simple objects deleted by tombstones generated") + eg, ctx = errgroup.WithContext(context.Background()) + eg.SetLimit(generateWorkersCount) + // simple objects locked by locks + for i := 0; i < lockedCount; i++ { + i := i + eg.Go(func() error { + obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) + testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + _, err := db.Put(ctx, PutPrm{ + obj: obj, + id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), + }) + lock := testutil.GenerateObjectWithCID(containers[i%len(containers)]) + lock.SetType(objectSDK.TypeLock) + testutil.AddAttribute(lock, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10)) + _, err = db.Put(ctx, PutPrm{ + obj: lock, + id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), + }) + require.NoError(t, err) + err = db.Lock(ctx, containers[i%len(containers)], object.AddressOf(lock).Object(), []oid.ID{object.AddressOf(obj).Object()}) + require.NoError(t, err) + return nil + }) + } + require.NoError(t, eg.Wait()) + db.log.Info("simple objects locked by locks generated") + require.NoError(t, db.boltDB.Sync()) + require.NoError(t, db.Close()) +} diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index 9134616fe3..eef7210dc2 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -94,11 +94,13 @@ const ( // ownerPrefix was used for prefixing FKBT index buckets mapping owner to object IDs. // Key: owner ID // Value: bucket containing object IDs as keys - _ + // removed in version 3 + ownerPrefix // userAttributePrefix was used for prefixing FKBT index buckets containing objects. // Key: attribute value // Value: bucket containing object IDs as keys - _ + // removed in version 3 + userAttributePrefix // ==================== // List index buckets. @@ -107,7 +109,8 @@ const ( // payloadHashPrefix was used for prefixing List index buckets mapping payload hash to a list of object IDs. // Key: payload hash // Value: list of object IDs - _ + // removed in version 3 + payloadHashPrefix // parentPrefix is used for prefixing List index buckets mapping parent ID to a list of children IDs. // Key: parent ID // Value: list of object IDs diff --git a/pkg/local_object_storage/metabase/version.go b/pkg/local_object_storage/metabase/version.go index bb2b66d9bc..9e15babbcc 100644 --- a/pkg/local_object_storage/metabase/version.go +++ b/pkg/local_object_storage/metabase/version.go @@ -2,6 +2,7 @@ package meta import ( "encoding/binary" + "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" @@ -18,6 +19,8 @@ var versionKey = []byte("version") // the current code version. var ErrOutdatedVersion = logicerr.New("invalid version, resynchronization is required") +var errVersionUndefinedNoInfoBucket = errors.New("version undefined: no info bucket") + func checkVersion(tx *bbolt.Tx, initialized bool) error { var knownVersion bool @@ -59,3 +62,15 @@ func updateVersion(tx *bbolt.Tx, version uint64) error { } return b.Put(versionKey, data) } + +func currentVersion(tx *bbolt.Tx) (uint64, error) { + b := tx.Bucket(shardInfoBucket) + if b == nil { + return 0, errVersionUndefinedNoInfoBucket + } + data := b.Get(versionKey) + if len(data) != 8 { + return 0, fmt.Errorf("version undefined: invalid version data length %d", len(data)) + } + return binary.LittleEndian.Uint64(data), nil +} From 882c068410628e4e8a7fe929189e97f4e796a5d1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 29 Aug 2024 16:33:30 +0300 Subject: [PATCH 0772/1413] [#1334] metabase: Store upgrade flag This allows to check if metabase upgrade was not completed. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/upgrade.go | 12 +++++++++++ pkg/local_object_storage/metabase/version.go | 11 +++++++++- .../metabase/version_test.go | 20 +++++++++++++++++++ pkg/local_object_storage/shard/control.go | 2 +- 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index 014e50286b..a4c7707b44 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -51,9 +51,21 @@ func Upgrade(ctx context.Context, path string, compact bool, log func(a ...any)) if !found { return fmt.Errorf("unsupported version %d: no update available", version) } + if err := db.Update(func(tx *bbolt.Tx) error { + b := tx.Bucket(shardInfoBucket) + return b.Put(upgradeKey, zeroValue) + }); err != nil { + return fmt.Errorf("set upgrade key %w", err) + } if err := updater(ctx, db, log); err != nil { return fmt.Errorf("update metabase schema: %w", err) } + if err := db.Update(func(tx *bbolt.Tx) error { + b := tx.Bucket(shardInfoBucket) + return b.Delete(upgradeKey) + }); err != nil { + return fmt.Errorf("delete upgrade key %w", err) + } if compact { log("compacting metabase...") err := compactDB(db) diff --git a/pkg/local_object_storage/metabase/version.go b/pkg/local_object_storage/metabase/version.go index 9e15babbcc..048bb9af64 100644 --- a/pkg/local_object_storage/metabase/version.go +++ b/pkg/local_object_storage/metabase/version.go @@ -12,13 +12,18 @@ import ( // version contains current metabase version. const version = 3 -var versionKey = []byte("version") +var ( + versionKey = []byte("version") + upgradeKey = []byte("upgrade") +) // ErrOutdatedVersion is returned on initializing // an existing metabase that is not compatible with // the current code version. var ErrOutdatedVersion = logicerr.New("invalid version, resynchronization is required") +var ErrIncompletedUpgrade = logicerr.New("metabase upgrade is not completed") + var errVersionUndefinedNoInfoBucket = errors.New("version undefined: no info bucket") func checkVersion(tx *bbolt.Tx, initialized bool) error { @@ -35,6 +40,10 @@ func checkVersion(tx *bbolt.Tx, initialized bool) error { return fmt.Errorf("%w: expected=%d, stored=%d", ErrOutdatedVersion, version, stored) } } + data = b.Get(upgradeKey) + if len(data) > 0 { + return ErrIncompletedUpgrade + } } if !initialized { diff --git a/pkg/local_object_storage/metabase/version_test.go b/pkg/local_object_storage/metabase/version_test.go index b2af428ff6..75229a1b44 100644 --- a/pkg/local_object_storage/metabase/version_test.go +++ b/pkg/local_object_storage/metabase/version_test.go @@ -84,4 +84,24 @@ func TestVersion(t *testing.T) { require.NoError(t, db.Close()) }) }) + t.Run("incompleted upgrade", func(t *testing.T) { + db := newDB(t) + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.Init()) + require.NoError(t, db.Close()) + + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error { + return tx.Bucket(shardInfoBucket).Put(upgradeKey, zeroValue) + })) + require.ErrorIs(t, db.Init(), ErrIncompletedUpgrade) + require.NoError(t, db.Close()) + + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error { + return tx.Bucket(shardInfoBucket).Delete(upgradeKey) + })) + require.NoError(t, db.Init()) + require.NoError(t, db.Close()) + }) } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 936a506c09..1626d58040 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -171,7 +171,7 @@ func (s *Shard) initializeComponents(m mode.Mode) error { for _, component := range components { if err := component.Init(); err != nil { if component == s.metaBase { - if errors.Is(err, meta.ErrOutdatedVersion) { + if errors.Is(err, meta.ErrOutdatedVersion) || errors.Is(err, meta.ErrIncompletedUpgrade) { return fmt.Errorf("metabase initialization: %w", err) } From 98fe24cdb7347b9b4ddfb1c8fe5e2025465d7692 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 29 Aug 2024 15:45:33 +0300 Subject: [PATCH 0773/1413] [#1343] go.mod: Update api-go Signed-off-by: Evgenii Stratonikov --- .../modules/control/shards_list.go | 6 +- cmd/frostfs-cli/modules/tree/add.go | 6 +- cmd/frostfs-cli/modules/tree/move.go | 2 +- go.mod | 2 +- go.sum | 4 +- pkg/services/control/server/list_shards.go | 10 +- pkg/services/control/server/policy_engine.go | 4 +- .../control/server/seal_writecache.go | 4 +- pkg/services/control/service_frostfs.pb.go | 66 +++---- pkg/services/control/types_frostfs.pb.go | 86 ++++----- pkg/services/tree/service.go | 22 +-- pkg/services/tree/service_frostfs.pb.go | 172 ++++++++---------- pkg/services/tree/signature_test.go | 2 +- 13 files changed, 180 insertions(+), 206 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/shards_list.go b/cmd/frostfs-cli/modules/control/shards_list.go index 07c5bcd9ad..e9e49bb299 100644 --- a/cmd/frostfs-cli/modules/control/shards_list.go +++ b/cmd/frostfs-cli/modules/control/shards_list.go @@ -61,7 +61,7 @@ func listShards(cmd *cobra.Command, _ []string) { } } -func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) { +func prettyPrintShardsJSON(cmd *cobra.Command, ii []control.ShardInfo) { out := make([]map[string]any, 0, len(ii)) for _, i := range ii { out = append(out, map[string]any{ @@ -83,7 +83,7 @@ func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) { cmd.Print(buf.String()) // pretty printer emits newline, so no need for Println } -func prettyPrintShards(cmd *cobra.Command, ii []*control.ShardInfo) { +func prettyPrintShards(cmd *cobra.Command, ii []control.ShardInfo) { for _, i := range ii { pathPrinter := func(name, path string) string { if path == "" { @@ -121,7 +121,7 @@ func shardModeToString(m control.ShardMode) string { return "unknown" } -func sortShardsByID(ii []*control.ShardInfo) { +func sortShardsByID(ii []control.ShardInfo) { sort.Slice(ii, func(i, j int) bool { return bytes.Compare(ii[i].GetShard_ID(), ii[j].GetShard_ID()) < 0 }) diff --git a/cmd/frostfs-cli/modules/tree/add.go b/cmd/frostfs-cli/modules/tree/add.go index 068b1d185d..0b8dc292f2 100644 --- a/cmd/frostfs-cli/modules/tree/add.go +++ b/cmd/frostfs-cli/modules/tree/add.go @@ -77,13 +77,13 @@ func add(cmd *cobra.Command, _ []string) { cmd.Println("Node ID: ", resp.GetBody().GetNodeId()) } -func parseMeta(cmd *cobra.Command) ([]*tree.KeyValue, error) { +func parseMeta(cmd *cobra.Command) ([]tree.KeyValue, error) { raws, _ := cmd.Flags().GetStringSlice(metaFlagKey) if len(raws) == 0 { return nil, nil } - pairs := make([]*tree.KeyValue, 0, len(raws)) + pairs := make([]tree.KeyValue, 0, len(raws)) for i := range raws { k, v, found := strings.Cut(raws[i], "=") if !found { @@ -94,7 +94,7 @@ func parseMeta(cmd *cobra.Command) ([]*tree.KeyValue, error) { pair.Key = k pair.Value = []byte(v) - pairs = append(pairs, &pair) + pairs = append(pairs, pair) } return pairs, nil diff --git a/cmd/frostfs-cli/modules/tree/move.go b/cmd/frostfs-cli/modules/tree/move.go index 95516940c3..24abbd6505 100644 --- a/cmd/frostfs-cli/modules/tree/move.go +++ b/cmd/frostfs-cli/modules/tree/move.go @@ -75,7 +75,7 @@ func move(cmd *cobra.Command, _ []string) { resp, err := cli.GetSubTree(ctx, subTreeReq) commonCmd.ExitOnErr(cmd, "rpc call: %w", err) - var meta []*tree.KeyValue + var meta []tree.KeyValue subtreeResp, err := resp.Recv() for ; err == nil; subtreeResp, err = resp.Recv() { meta = subtreeResp.GetBody().GetMeta() diff --git a/go.mod b/go.mod index b7f59c8232..358370201e 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240827104600-eba18f6e67ac + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240828085308-5e1c6a908f61 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d diff --git a/go.sum b/go.sum index d2f926151e..be82bff70b 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240827104600-eba18f6e67ac h1:Gu3oiPnsSZPgwsUYs2f3xTQwndM/OWM/zo3zbN4rOb8= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240827104600-eba18f6e67ac/go.mod h1:BDnEpkKMykCS8u1nLzR6SgNzCv6885RWlo5TnravQuI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240828085308-5e1c6a908f61 h1:bw9EVGWnfY9awFb5XYR52AGbzgg3o04gZF66yHob48c= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240828085308-5e1c6a908f61/go.mod h1:BDnEpkKMykCS8u1nLzR6SgNzCv6885RWlo5TnravQuI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= diff --git a/pkg/services/control/server/list_shards.go b/pkg/services/control/server/list_shards.go index b639245c14..56bd9fc1ff 100644 --- a/pkg/services/control/server/list_shards.go +++ b/pkg/services/control/server/list_shards.go @@ -25,7 +25,7 @@ func (s *Server) ListShards(_ context.Context, req *control.ListShardsRequest) ( info := s.s.DumpInfo() - shardInfos := make([]*control.ShardInfo, 0, len(info.Shards)) + shardInfos := make([]control.ShardInfo, 0, len(info.Shards)) for _, sh := range info.Shards { si := new(control.ShardInfo) @@ -54,7 +54,7 @@ func (s *Server) ListShards(_ context.Context, req *control.ListShardsRequest) ( si.SetMode(m) si.SetErrorCount(sh.ErrorCount) - shardInfos = append(shardInfos, si) + shardInfos = append(shardInfos, *si) } body.SetShards(shardInfos) @@ -67,10 +67,10 @@ func (s *Server) ListShards(_ context.Context, req *control.ListShardsRequest) ( return resp, nil } -func blobstorInfoToProto(info blobstor.Info) []*control.BlobstorInfo { - res := make([]*control.BlobstorInfo, len(info.SubStorages)) +func blobstorInfoToProto(info blobstor.Info) []control.BlobstorInfo { + res := make([]control.BlobstorInfo, len(info.SubStorages)) for i := range info.SubStorages { - res[i] = &control.BlobstorInfo{ + res[i] = control.BlobstorInfo{ Path: info.SubStorages[i].Path, Type: info.SubStorages[i].Type, } diff --git a/pkg/services/control/server/policy_engine.go b/pkg/services/control/server/policy_engine.go index 98daac8a66..ab8258e27e 100644 --- a/pkg/services/control/server/policy_engine.go +++ b/pkg/services/control/server/policy_engine.go @@ -220,13 +220,13 @@ func (s *Server) ListTargetsLocalOverrides(_ context.Context, req *control.ListT if err != nil { return nil, status.Error(getCodeByLocalStorageErr(err), err.Error()) } - targets := make([]*control.ChainTarget, 0, len(apeTargets)) + targets := make([]control.ChainTarget, 0, len(apeTargets)) for i := range apeTargets { target, err := controlTarget(&apeTargets[i]) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } - targets = append(targets, &target) + targets = append(targets, target) } resp := &control.ListTargetsLocalOverridesResponse{ diff --git a/pkg/services/control/server/seal_writecache.go b/pkg/services/control/server/seal_writecache.go index 1737677b7d..6799bdcac5 100644 --- a/pkg/services/control/server/seal_writecache.go +++ b/pkg/services/control/server/seal_writecache.go @@ -32,12 +32,12 @@ func (s *Server) SealWriteCache(ctx context.Context, req *control.SealWriteCache resp := &control.SealWriteCacheResponse{Body: &control.SealWriteCacheResponse_Body{}} for _, r := range res.ShardResults { if r.Success { - resp.Body.Results = append(resp.GetBody().GetResults(), &control.SealWriteCacheResponse_Body_Status{ + resp.Body.Results = append(resp.GetBody().GetResults(), control.SealWriteCacheResponse_Body_Status{ Shard_ID: *r.ShardID, Success: true, }) } else { - resp.Body.Results = append(resp.GetBody().GetResults(), &control.SealWriteCacheResponse_Body_Status{ + resp.Body.Results = append(resp.GetBody().GetResults(), control.SealWriteCacheResponse_Body_Status{ Shard_ID: *r.ShardID, Error: r.ErrorMsg, }) diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index a446c5e59b..eb0d95c64e 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -2851,7 +2851,7 @@ func (x *ListShardsRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { } type ListShardsResponse_Body struct { - Shards []*ShardInfo `json:"shards"` + Shards []ShardInfo `json:"shards"` } var ( @@ -2869,7 +2869,7 @@ func (x *ListShardsResponse_Body) StableSize() (size int) { return 0 } for i := range x.Shards { - size += proto.NestedStructureSize(1, x.Shards[i]) + size += proto.NestedStructureSizeUnchecked(1, &x.Shards[i]) } return size } @@ -2888,9 +2888,7 @@ func (x *ListShardsResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { return } for i := range x.Shards { - if x.Shards[i] != nil { - x.Shards[i].EmitProtobuf(mm.AppendMessage(1)) - } + x.Shards[i].EmitProtobuf(mm.AppendMessage(1)) } } @@ -2908,8 +2906,8 @@ func (x *ListShardsResponse_Body) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Shards") } - x.Shards = append(x.Shards, new(ShardInfo)) - ff := x.Shards[len(x.Shards)-1] + x.Shards = append(x.Shards, ShardInfo{}) + ff := &x.Shards[len(x.Shards)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -2917,13 +2915,13 @@ func (x *ListShardsResponse_Body) UnmarshalProtobuf(src []byte) (err error) { } return nil } -func (x *ListShardsResponse_Body) GetShards() []*ShardInfo { +func (x *ListShardsResponse_Body) GetShards() []ShardInfo { if x != nil { return x.Shards } return nil } -func (x *ListShardsResponse_Body) SetShards(v []*ShardInfo) { +func (x *ListShardsResponse_Body) SetShards(v []ShardInfo) { x.Shards = v } @@ -2981,11 +2979,11 @@ func (x *ListShardsResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { switch key { case "shards": { - var f *ShardInfo - var list []*ShardInfo + var f ShardInfo + var list []ShardInfo in.Delim('[') for !in.IsDelim(']') { - f = new(ShardInfo) + f = ShardInfo{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -11870,7 +11868,7 @@ func (x *ListTargetsLocalOverridesRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { } type ListTargetsLocalOverridesResponse_Body struct { - Targets []*ChainTarget `json:"targets"` + Targets []ChainTarget `json:"targets"` } var ( @@ -11888,7 +11886,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) StableSize() (size int) { return 0 } for i := range x.Targets { - size += proto.NestedStructureSize(1, x.Targets[i]) + size += proto.NestedStructureSizeUnchecked(1, &x.Targets[i]) } return size } @@ -11907,9 +11905,7 @@ func (x *ListTargetsLocalOverridesResponse_Body) EmitProtobuf(mm *easyproto.Mess return } for i := range x.Targets { - if x.Targets[i] != nil { - x.Targets[i].EmitProtobuf(mm.AppendMessage(1)) - } + x.Targets[i].EmitProtobuf(mm.AppendMessage(1)) } } @@ -11927,8 +11923,8 @@ func (x *ListTargetsLocalOverridesResponse_Body) UnmarshalProtobuf(src []byte) ( if !ok { return fmt.Errorf("cannot unmarshal field %s", "Targets") } - x.Targets = append(x.Targets, new(ChainTarget)) - ff := x.Targets[len(x.Targets)-1] + x.Targets = append(x.Targets, ChainTarget{}) + ff := &x.Targets[len(x.Targets)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -11936,13 +11932,13 @@ func (x *ListTargetsLocalOverridesResponse_Body) UnmarshalProtobuf(src []byte) ( } return nil } -func (x *ListTargetsLocalOverridesResponse_Body) GetTargets() []*ChainTarget { +func (x *ListTargetsLocalOverridesResponse_Body) GetTargets() []ChainTarget { if x != nil { return x.Targets } return nil } -func (x *ListTargetsLocalOverridesResponse_Body) SetTargets(v []*ChainTarget) { +func (x *ListTargetsLocalOverridesResponse_Body) SetTargets(v []ChainTarget) { x.Targets = v } @@ -12000,11 +11996,11 @@ func (x *ListTargetsLocalOverridesResponse_Body) UnmarshalEasyJSON(in *jlexer.Le switch key { case "targets": { - var f *ChainTarget - var list []*ChainTarget + var f ChainTarget + var list []ChainTarget in.Delim('[') for !in.IsDelim(']') { - f = new(ChainTarget) + f = ChainTarget{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -14083,7 +14079,7 @@ func (x *SealWriteCacheResponse_Body_Status) UnmarshalEasyJSON(in *jlexer.Lexer) } type SealWriteCacheResponse_Body struct { - Results []*SealWriteCacheResponse_Body_Status `json:"results"` + Results []SealWriteCacheResponse_Body_Status `json:"results"` } var ( @@ -14101,7 +14097,7 @@ func (x *SealWriteCacheResponse_Body) StableSize() (size int) { return 0 } for i := range x.Results { - size += proto.NestedStructureSize(1, x.Results[i]) + size += proto.NestedStructureSizeUnchecked(1, &x.Results[i]) } return size } @@ -14120,9 +14116,7 @@ func (x *SealWriteCacheResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshale return } for i := range x.Results { - if x.Results[i] != nil { - x.Results[i].EmitProtobuf(mm.AppendMessage(1)) - } + x.Results[i].EmitProtobuf(mm.AppendMessage(1)) } } @@ -14140,8 +14134,8 @@ func (x *SealWriteCacheResponse_Body) UnmarshalProtobuf(src []byte) (err error) if !ok { return fmt.Errorf("cannot unmarshal field %s", "Results") } - x.Results = append(x.Results, new(SealWriteCacheResponse_Body_Status)) - ff := x.Results[len(x.Results)-1] + x.Results = append(x.Results, SealWriteCacheResponse_Body_Status{}) + ff := &x.Results[len(x.Results)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -14149,13 +14143,13 @@ func (x *SealWriteCacheResponse_Body) UnmarshalProtobuf(src []byte) (err error) } return nil } -func (x *SealWriteCacheResponse_Body) GetResults() []*SealWriteCacheResponse_Body_Status { +func (x *SealWriteCacheResponse_Body) GetResults() []SealWriteCacheResponse_Body_Status { if x != nil { return x.Results } return nil } -func (x *SealWriteCacheResponse_Body) SetResults(v []*SealWriteCacheResponse_Body_Status) { +func (x *SealWriteCacheResponse_Body) SetResults(v []SealWriteCacheResponse_Body_Status) { x.Results = v } @@ -14213,11 +14207,11 @@ func (x *SealWriteCacheResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { switch key { case "results": { - var f *SealWriteCacheResponse_Body_Status - var list []*SealWriteCacheResponse_Body_Status + var f SealWriteCacheResponse_Body_Status + var list []SealWriteCacheResponse_Body_Status in.Delim('[') for !in.IsDelim(']') { - f = new(SealWriteCacheResponse_Body_Status) + f = SealWriteCacheResponse_Body_Status{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index 3cc37245f0..42c1afa524 100644 --- a/pkg/services/control/types_frostfs.pb.go +++ b/pkg/services/control/types_frostfs.pb.go @@ -500,10 +500,10 @@ func (x *NodeInfo_Attribute) UnmarshalEasyJSON(in *jlexer.Lexer) { } type NodeInfo struct { - PublicKey []byte `json:"publicKey"` - Addresses []string `json:"addresses"` - Attributes []*NodeInfo_Attribute `json:"attributes"` - State NetmapStatus `json:"state"` + PublicKey []byte `json:"publicKey"` + Addresses []string `json:"addresses"` + Attributes []NodeInfo_Attribute `json:"attributes"` + State NetmapStatus `json:"state"` } var ( @@ -523,7 +523,7 @@ func (x *NodeInfo) StableSize() (size int) { size += proto.BytesSize(1, x.PublicKey) size += proto.RepeatedStringSize(2, x.Addresses) for i := range x.Attributes { - size += proto.NestedStructureSize(3, x.Attributes[i]) + size += proto.NestedStructureSizeUnchecked(3, &x.Attributes[i]) } size += proto.EnumSize(4, int32(x.State)) return size @@ -549,9 +549,7 @@ func (x *NodeInfo) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendString(2, x.Addresses[j]) } for i := range x.Attributes { - if x.Attributes[i] != nil { - x.Attributes[i].EmitProtobuf(mm.AppendMessage(3)) - } + x.Attributes[i].EmitProtobuf(mm.AppendMessage(3)) } if int32(x.State) != 0 { mm.AppendInt32(4, int32(x.State)) @@ -584,8 +582,8 @@ func (x *NodeInfo) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Attributes") } - x.Attributes = append(x.Attributes, new(NodeInfo_Attribute)) - ff := x.Attributes[len(x.Attributes)-1] + x.Attributes = append(x.Attributes, NodeInfo_Attribute{}) + ff := &x.Attributes[len(x.Attributes)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -617,13 +615,13 @@ func (x *NodeInfo) GetAddresses() []string { func (x *NodeInfo) SetAddresses(v []string) { x.Addresses = v } -func (x *NodeInfo) GetAttributes() []*NodeInfo_Attribute { +func (x *NodeInfo) GetAttributes() []NodeInfo_Attribute { if x != nil { return x.Attributes } return nil } -func (x *NodeInfo) SetAttributes(v []*NodeInfo_Attribute) { +func (x *NodeInfo) SetAttributes(v []NodeInfo_Attribute) { x.Attributes = v } func (x *NodeInfo) GetState() NetmapStatus { @@ -731,11 +729,11 @@ func (x *NodeInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { } case "attributes": { - var f *NodeInfo_Attribute - var list []*NodeInfo_Attribute + var f NodeInfo_Attribute + var list []NodeInfo_Attribute in.Delim('[') for !in.IsDelim(']') { - f = new(NodeInfo_Attribute) + f = NodeInfo_Attribute{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -775,8 +773,8 @@ func (x *NodeInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { } type Netmap struct { - Epoch uint64 `json:"epoch"` - Nodes []*NodeInfo `json:"nodes"` + Epoch uint64 `json:"epoch"` + Nodes []NodeInfo `json:"nodes"` } var ( @@ -795,7 +793,7 @@ func (x *Netmap) StableSize() (size int) { } size += proto.UInt64Size(1, x.Epoch) for i := range x.Nodes { - size += proto.NestedStructureSize(2, x.Nodes[i]) + size += proto.NestedStructureSizeUnchecked(2, &x.Nodes[i]) } return size } @@ -817,9 +815,7 @@ func (x *Netmap) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendUint64(1, x.Epoch) } for i := range x.Nodes { - if x.Nodes[i] != nil { - x.Nodes[i].EmitProtobuf(mm.AppendMessage(2)) - } + x.Nodes[i].EmitProtobuf(mm.AppendMessage(2)) } } @@ -843,8 +839,8 @@ func (x *Netmap) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Nodes") } - x.Nodes = append(x.Nodes, new(NodeInfo)) - ff := x.Nodes[len(x.Nodes)-1] + x.Nodes = append(x.Nodes, NodeInfo{}) + ff := &x.Nodes[len(x.Nodes)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -861,13 +857,13 @@ func (x *Netmap) GetEpoch() uint64 { func (x *Netmap) SetEpoch(v uint64) { x.Epoch = v } -func (x *Netmap) GetNodes() []*NodeInfo { +func (x *Netmap) GetNodes() []NodeInfo { if x != nil { return x.Nodes } return nil } -func (x *Netmap) SetNodes(v []*NodeInfo) { +func (x *Netmap) SetNodes(v []NodeInfo) { x.Nodes = v } @@ -936,11 +932,11 @@ func (x *Netmap) UnmarshalEasyJSON(in *jlexer.Lexer) { } case "nodes": { - var f *NodeInfo - var list []*NodeInfo + var f NodeInfo + var list []NodeInfo in.Delim('[') for !in.IsDelim(']') { - f = new(NodeInfo) + f = NodeInfo{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -958,13 +954,13 @@ func (x *Netmap) UnmarshalEasyJSON(in *jlexer.Lexer) { } type ShardInfo struct { - Shard_ID []byte `json:"shardID"` - MetabasePath string `json:"metabasePath"` - Blobstor []*BlobstorInfo `json:"blobstor"` - WritecachePath string `json:"writecachePath"` - Mode ShardMode `json:"mode"` - ErrorCount uint32 `json:"errorCount"` - PiloramaPath string `json:"piloramaPath"` + Shard_ID []byte `json:"shardID"` + MetabasePath string `json:"metabasePath"` + Blobstor []BlobstorInfo `json:"blobstor"` + WritecachePath string `json:"writecachePath"` + Mode ShardMode `json:"mode"` + ErrorCount uint32 `json:"errorCount"` + PiloramaPath string `json:"piloramaPath"` } var ( @@ -984,7 +980,7 @@ func (x *ShardInfo) StableSize() (size int) { size += proto.BytesSize(1, x.Shard_ID) size += proto.StringSize(2, x.MetabasePath) for i := range x.Blobstor { - size += proto.NestedStructureSize(3, x.Blobstor[i]) + size += proto.NestedStructureSizeUnchecked(3, &x.Blobstor[i]) } size += proto.StringSize(4, x.WritecachePath) size += proto.EnumSize(5, int32(x.Mode)) @@ -1013,9 +1009,7 @@ func (x *ShardInfo) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendString(2, x.MetabasePath) } for i := range x.Blobstor { - if x.Blobstor[i] != nil { - x.Blobstor[i].EmitProtobuf(mm.AppendMessage(3)) - } + x.Blobstor[i].EmitProtobuf(mm.AppendMessage(3)) } if len(x.WritecachePath) != 0 { mm.AppendString(4, x.WritecachePath) @@ -1057,8 +1051,8 @@ func (x *ShardInfo) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Blobstor") } - x.Blobstor = append(x.Blobstor, new(BlobstorInfo)) - ff := x.Blobstor[len(x.Blobstor)-1] + x.Blobstor = append(x.Blobstor, BlobstorInfo{}) + ff := &x.Blobstor[len(x.Blobstor)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -1108,13 +1102,13 @@ func (x *ShardInfo) GetMetabasePath() string { func (x *ShardInfo) SetMetabasePath(v string) { x.MetabasePath = v } -func (x *ShardInfo) GetBlobstor() []*BlobstorInfo { +func (x *ShardInfo) GetBlobstor() []BlobstorInfo { if x != nil { return x.Blobstor } return nil } -func (x *ShardInfo) SetBlobstor(v []*BlobstorInfo) { +func (x *ShardInfo) SetBlobstor(v []BlobstorInfo) { x.Blobstor = v } func (x *ShardInfo) GetWritecachePath() string { @@ -1250,11 +1244,11 @@ func (x *ShardInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { } case "blobstor": { - var f *BlobstorInfo - var list []*BlobstorInfo + var f BlobstorInfo + var list []BlobstorInfo in.Delim('[') for !in.IsDelim(']') { - f = new(BlobstorInfo) + f = BlobstorInfo{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 2012f53d28..4da61617f7 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -360,7 +360,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) return nil, err } - info := make([]*GetNodeByPathResponse_Info, 0, len(nodes)) + info := make([]GetNodeByPathResponse_Info, 0, len(nodes)) for _, node := range nodes { m, parent, err := s.forest.TreeGetMeta(ctx, cid, b.GetTreeId(), node) if err != nil { @@ -374,11 +374,11 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) if b.GetAllAttributes() { x.Meta = metaToProto(m.Items) } else { - var metaValue []*KeyValue + var metaValue []KeyValue for _, kv := range m.Items { for _, attr := range b.GetAttributes() { if kv.Key == attr { - metaValue = append(metaValue, &KeyValue{ + metaValue = append(metaValue, KeyValue{ Key: kv.Key, Value: kv.Value, }) @@ -388,7 +388,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) } x.Meta = metaValue } - info = append(info, &x) + info = append(info, x) } return &GetNodeByPathResponse{ @@ -782,21 +782,19 @@ func (s *Service) TreeList(ctx context.Context, req *TreeListRequest) (*TreeList }, nil } -func protoToMeta(arr []*KeyValue) []pilorama.KeyValue { +func protoToMeta(arr []KeyValue) []pilorama.KeyValue { meta := make([]pilorama.KeyValue, len(arr)) for i, kv := range arr { - if kv != nil { - meta[i].Key = kv.GetKey() - meta[i].Value = kv.GetValue() - } + meta[i].Key = kv.GetKey() + meta[i].Value = kv.GetValue() } return meta } -func metaToProto(arr []pilorama.KeyValue) []*KeyValue { - meta := make([]*KeyValue, len(arr)) +func metaToProto(arr []pilorama.KeyValue) []KeyValue { + meta := make([]KeyValue, len(arr)) for i, kv := range arr { - meta[i] = &KeyValue{ + meta[i] = KeyValue{ Key: kv.Key, Value: kv.Value, } diff --git a/pkg/services/tree/service_frostfs.pb.go b/pkg/services/tree/service_frostfs.pb.go index 3c6ba21b78..7b6abb1dd7 100644 --- a/pkg/services/tree/service_frostfs.pb.go +++ b/pkg/services/tree/service_frostfs.pb.go @@ -16,11 +16,11 @@ import ( ) type AddRequest_Body struct { - ContainerId []byte `json:"containerId"` - TreeId string `json:"treeId"` - ParentId uint64 `json:"parentId"` - Meta []*KeyValue `json:"meta"` - BearerToken []byte `json:"bearerToken"` + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + ParentId uint64 `json:"parentId"` + Meta []KeyValue `json:"meta"` + BearerToken []byte `json:"bearerToken"` } var ( @@ -41,7 +41,7 @@ func (x *AddRequest_Body) StableSize() (size int) { size += proto.StringSize(2, x.TreeId) size += proto.UInt64Size(3, x.ParentId) for i := range x.Meta { - size += proto.NestedStructureSize(4, x.Meta[i]) + size += proto.NestedStructureSizeUnchecked(4, &x.Meta[i]) } size += proto.BytesSize(5, x.BearerToken) return size @@ -70,9 +70,7 @@ func (x *AddRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendUint64(3, x.ParentId) } for i := range x.Meta { - if x.Meta[i] != nil { - x.Meta[i].EmitProtobuf(mm.AppendMessage(4)) - } + x.Meta[i].EmitProtobuf(mm.AppendMessage(4)) } if len(x.BearerToken) != 0 { mm.AppendBytes(5, x.BearerToken) @@ -111,8 +109,8 @@ func (x *AddRequest_Body) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Meta") } - x.Meta = append(x.Meta, new(KeyValue)) - ff := x.Meta[len(x.Meta)-1] + x.Meta = append(x.Meta, KeyValue{}) + ff := &x.Meta[len(x.Meta)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -153,13 +151,13 @@ func (x *AddRequest_Body) GetParentId() uint64 { func (x *AddRequest_Body) SetParentId(v uint64) { x.ParentId = v } -func (x *AddRequest_Body) GetMeta() []*KeyValue { +func (x *AddRequest_Body) GetMeta() []KeyValue { if x != nil { return x.Meta } return nil } -func (x *AddRequest_Body) SetMeta(v []*KeyValue) { +func (x *AddRequest_Body) SetMeta(v []KeyValue) { x.Meta = v } func (x *AddRequest_Body) GetBearerToken() []byte { @@ -264,11 +262,11 @@ func (x *AddRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { } case "meta": { - var f *KeyValue - var list []*KeyValue + var f KeyValue + var list []KeyValue in.Delim('[') for !in.IsDelim(']') { - f = new(KeyValue) + f = KeyValue{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -793,12 +791,12 @@ func (x *AddResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { } type AddByPathRequest_Body struct { - ContainerId []byte `json:"containerId"` - TreeId string `json:"treeId"` - PathAttribute string `json:"pathAttribute"` - Path []string `json:"path"` - Meta []*KeyValue `json:"meta"` - BearerToken []byte `json:"bearerToken"` + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + PathAttribute string `json:"pathAttribute"` + Path []string `json:"path"` + Meta []KeyValue `json:"meta"` + BearerToken []byte `json:"bearerToken"` } var ( @@ -820,7 +818,7 @@ func (x *AddByPathRequest_Body) StableSize() (size int) { size += proto.StringSize(3, x.PathAttribute) size += proto.RepeatedStringSize(4, x.Path) for i := range x.Meta { - size += proto.NestedStructureSize(5, x.Meta[i]) + size += proto.NestedStructureSizeUnchecked(5, &x.Meta[i]) } size += proto.BytesSize(6, x.BearerToken) return size @@ -852,9 +850,7 @@ func (x *AddByPathRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendString(4, x.Path[j]) } for i := range x.Meta { - if x.Meta[i] != nil { - x.Meta[i].EmitProtobuf(mm.AppendMessage(5)) - } + x.Meta[i].EmitProtobuf(mm.AppendMessage(5)) } if len(x.BearerToken) != 0 { mm.AppendBytes(6, x.BearerToken) @@ -899,8 +895,8 @@ func (x *AddByPathRequest_Body) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Meta") } - x.Meta = append(x.Meta, new(KeyValue)) - ff := x.Meta[len(x.Meta)-1] + x.Meta = append(x.Meta, KeyValue{}) + ff := &x.Meta[len(x.Meta)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -950,13 +946,13 @@ func (x *AddByPathRequest_Body) GetPath() []string { func (x *AddByPathRequest_Body) SetPath(v []string) { x.Path = v } -func (x *AddByPathRequest_Body) GetMeta() []*KeyValue { +func (x *AddByPathRequest_Body) GetMeta() []KeyValue { if x != nil { return x.Meta } return nil } -func (x *AddByPathRequest_Body) SetMeta(v []*KeyValue) { +func (x *AddByPathRequest_Body) SetMeta(v []KeyValue) { x.Meta = v } func (x *AddByPathRequest_Body) GetBearerToken() []byte { @@ -1086,11 +1082,11 @@ func (x *AddByPathRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { } case "meta": { - var f *KeyValue - var list []*KeyValue + var f KeyValue + var list []KeyValue in.Delim('[') for !in.IsDelim(']') { - f = new(KeyValue) + f = KeyValue{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -2351,12 +2347,12 @@ func (x *RemoveResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { } type MoveRequest_Body struct { - ContainerId []byte `json:"containerId"` - TreeId string `json:"treeId"` - ParentId uint64 `json:"parentId"` - NodeId uint64 `json:"nodeId"` - Meta []*KeyValue `json:"meta"` - BearerToken []byte `json:"bearerToken"` + ContainerId []byte `json:"containerId"` + TreeId string `json:"treeId"` + ParentId uint64 `json:"parentId"` + NodeId uint64 `json:"nodeId"` + Meta []KeyValue `json:"meta"` + BearerToken []byte `json:"bearerToken"` } var ( @@ -2378,7 +2374,7 @@ func (x *MoveRequest_Body) StableSize() (size int) { size += proto.UInt64Size(3, x.ParentId) size += proto.UInt64Size(4, x.NodeId) for i := range x.Meta { - size += proto.NestedStructureSize(5, x.Meta[i]) + size += proto.NestedStructureSizeUnchecked(5, &x.Meta[i]) } size += proto.BytesSize(6, x.BearerToken) return size @@ -2410,9 +2406,7 @@ func (x *MoveRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendUint64(4, x.NodeId) } for i := range x.Meta { - if x.Meta[i] != nil { - x.Meta[i].EmitProtobuf(mm.AppendMessage(5)) - } + x.Meta[i].EmitProtobuf(mm.AppendMessage(5)) } if len(x.BearerToken) != 0 { mm.AppendBytes(6, x.BearerToken) @@ -2457,8 +2451,8 @@ func (x *MoveRequest_Body) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Meta") } - x.Meta = append(x.Meta, new(KeyValue)) - ff := x.Meta[len(x.Meta)-1] + x.Meta = append(x.Meta, KeyValue{}) + ff := &x.Meta[len(x.Meta)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -2508,13 +2502,13 @@ func (x *MoveRequest_Body) GetNodeId() uint64 { func (x *MoveRequest_Body) SetNodeId(v uint64) { x.NodeId = v } -func (x *MoveRequest_Body) GetMeta() []*KeyValue { +func (x *MoveRequest_Body) GetMeta() []KeyValue { if x != nil { return x.Meta } return nil } -func (x *MoveRequest_Body) SetMeta(v []*KeyValue) { +func (x *MoveRequest_Body) SetMeta(v []KeyValue) { x.Meta = v } func (x *MoveRequest_Body) GetBearerToken() []byte { @@ -2630,11 +2624,11 @@ func (x *MoveRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { } case "meta": { - var f *KeyValue - var list []*KeyValue + var f KeyValue + var list []KeyValue in.Delim('[') for !in.IsDelim(']') { - f = new(KeyValue) + f = KeyValue{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -3685,10 +3679,10 @@ func (x *GetNodeByPathRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { } type GetNodeByPathResponse_Info struct { - NodeId uint64 `json:"nodeId"` - Timestamp uint64 `json:"timestamp"` - Meta []*KeyValue `json:"meta"` - ParentId uint64 `json:"parentId"` + NodeId uint64 `json:"nodeId"` + Timestamp uint64 `json:"timestamp"` + Meta []KeyValue `json:"meta"` + ParentId uint64 `json:"parentId"` } var ( @@ -3708,7 +3702,7 @@ func (x *GetNodeByPathResponse_Info) StableSize() (size int) { size += proto.UInt64Size(1, x.NodeId) size += proto.UInt64Size(2, x.Timestamp) for i := range x.Meta { - size += proto.NestedStructureSize(3, x.Meta[i]) + size += proto.NestedStructureSizeUnchecked(3, &x.Meta[i]) } size += proto.UInt64Size(4, x.ParentId) return size @@ -3734,9 +3728,7 @@ func (x *GetNodeByPathResponse_Info) EmitProtobuf(mm *easyproto.MessageMarshaler mm.AppendUint64(2, x.Timestamp) } for i := range x.Meta { - if x.Meta[i] != nil { - x.Meta[i].EmitProtobuf(mm.AppendMessage(3)) - } + x.Meta[i].EmitProtobuf(mm.AppendMessage(3)) } if x.ParentId != 0 { mm.AppendUint64(4, x.ParentId) @@ -3769,8 +3761,8 @@ func (x *GetNodeByPathResponse_Info) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Meta") } - x.Meta = append(x.Meta, new(KeyValue)) - ff := x.Meta[len(x.Meta)-1] + x.Meta = append(x.Meta, KeyValue{}) + ff := &x.Meta[len(x.Meta)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -3802,13 +3794,13 @@ func (x *GetNodeByPathResponse_Info) GetTimestamp() uint64 { func (x *GetNodeByPathResponse_Info) SetTimestamp(v uint64) { x.Timestamp = v } -func (x *GetNodeByPathResponse_Info) GetMeta() []*KeyValue { +func (x *GetNodeByPathResponse_Info) GetMeta() []KeyValue { if x != nil { return x.Meta } return nil } -func (x *GetNodeByPathResponse_Info) SetMeta(v []*KeyValue) { +func (x *GetNodeByPathResponse_Info) SetMeta(v []KeyValue) { x.Meta = v } func (x *GetNodeByPathResponse_Info) GetParentId() uint64 { @@ -3902,11 +3894,11 @@ func (x *GetNodeByPathResponse_Info) UnmarshalEasyJSON(in *jlexer.Lexer) { } case "meta": { - var f *KeyValue - var list []*KeyValue + var f KeyValue + var list []KeyValue in.Delim('[') for !in.IsDelim(']') { - f = new(KeyValue) + f = KeyValue{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -3930,7 +3922,7 @@ func (x *GetNodeByPathResponse_Info) UnmarshalEasyJSON(in *jlexer.Lexer) { } type GetNodeByPathResponse_Body struct { - Nodes []*GetNodeByPathResponse_Info `json:"nodes"` + Nodes []GetNodeByPathResponse_Info `json:"nodes"` } var ( @@ -3948,7 +3940,7 @@ func (x *GetNodeByPathResponse_Body) StableSize() (size int) { return 0 } for i := range x.Nodes { - size += proto.NestedStructureSize(1, x.Nodes[i]) + size += proto.NestedStructureSizeUnchecked(1, &x.Nodes[i]) } return size } @@ -3967,9 +3959,7 @@ func (x *GetNodeByPathResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler return } for i := range x.Nodes { - if x.Nodes[i] != nil { - x.Nodes[i].EmitProtobuf(mm.AppendMessage(1)) - } + x.Nodes[i].EmitProtobuf(mm.AppendMessage(1)) } } @@ -3987,8 +3977,8 @@ func (x *GetNodeByPathResponse_Body) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Nodes") } - x.Nodes = append(x.Nodes, new(GetNodeByPathResponse_Info)) - ff := x.Nodes[len(x.Nodes)-1] + x.Nodes = append(x.Nodes, GetNodeByPathResponse_Info{}) + ff := &x.Nodes[len(x.Nodes)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -3996,13 +3986,13 @@ func (x *GetNodeByPathResponse_Body) UnmarshalProtobuf(src []byte) (err error) { } return nil } -func (x *GetNodeByPathResponse_Body) GetNodes() []*GetNodeByPathResponse_Info { +func (x *GetNodeByPathResponse_Body) GetNodes() []GetNodeByPathResponse_Info { if x != nil { return x.Nodes } return nil } -func (x *GetNodeByPathResponse_Body) SetNodes(v []*GetNodeByPathResponse_Info) { +func (x *GetNodeByPathResponse_Body) SetNodes(v []GetNodeByPathResponse_Info) { x.Nodes = v } @@ -4060,11 +4050,11 @@ func (x *GetNodeByPathResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { switch key { case "nodes": { - var f *GetNodeByPathResponse_Info - var list []*GetNodeByPathResponse_Info + var f GetNodeByPathResponse_Info + var list []GetNodeByPathResponse_Info in.Delim('[') for !in.IsDelim(']') { - f = new(GetNodeByPathResponse_Info) + f = GetNodeByPathResponse_Info{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() @@ -4935,10 +4925,10 @@ func (x *GetSubTreeRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { } type GetSubTreeResponse_Body struct { - NodeId []uint64 `json:"nodeId"` - ParentId []uint64 `json:"parentId"` - Timestamp []uint64 `json:"timestamp"` - Meta []*KeyValue `json:"meta"` + NodeId []uint64 `json:"nodeId"` + ParentId []uint64 `json:"parentId"` + Timestamp []uint64 `json:"timestamp"` + Meta []KeyValue `json:"meta"` } var ( @@ -4965,7 +4955,7 @@ func (x *GetSubTreeResponse_Body) StableSize() (size int) { size += protowire.SizeGroup(protowire.Number(3), protowire.SizeVarint(x.Timestamp[i])) } for i := range x.Meta { - size += proto.NestedStructureSize(4, x.Meta[i]) + size += proto.NestedStructureSizeUnchecked(4, &x.Meta[i]) } return size } @@ -4993,9 +4983,7 @@ func (x *GetSubTreeResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { mm.AppendUint64(3, x.Timestamp[j]) } for i := range x.Meta { - if x.Meta[i] != nil { - x.Meta[i].EmitProtobuf(mm.AppendMessage(4)) - } + x.Meta[i].EmitProtobuf(mm.AppendMessage(4)) } } @@ -5031,8 +5019,8 @@ func (x *GetSubTreeResponse_Body) UnmarshalProtobuf(src []byte) (err error) { if !ok { return fmt.Errorf("cannot unmarshal field %s", "Meta") } - x.Meta = append(x.Meta, new(KeyValue)) - ff := x.Meta[len(x.Meta)-1] + x.Meta = append(x.Meta, KeyValue{}) + ff := &x.Meta[len(x.Meta)-1] if err := ff.UnmarshalProtobuf(data); err != nil { return fmt.Errorf("unmarshal: %w", err) } @@ -5067,13 +5055,13 @@ func (x *GetSubTreeResponse_Body) GetTimestamp() []uint64 { func (x *GetSubTreeResponse_Body) SetTimestamp(v []uint64) { x.Timestamp = v } -func (x *GetSubTreeResponse_Body) GetMeta() []*KeyValue { +func (x *GetSubTreeResponse_Body) GetMeta() []KeyValue { if x != nil { return x.Meta } return nil } -func (x *GetSubTreeResponse_Body) SetMeta(v []*KeyValue) { +func (x *GetSubTreeResponse_Body) SetMeta(v []KeyValue) { x.Meta = v } @@ -5206,11 +5194,11 @@ func (x *GetSubTreeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { } case "meta": { - var f *KeyValue - var list []*KeyValue + var f KeyValue + var list []KeyValue in.Delim('[') for !in.IsDelim(']') { - f = new(KeyValue) + f = KeyValue{} f.UnmarshalEasyJSON(in) list = append(list, f) in.WantComma() diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index ce5039f7cb..3c3ebfe892 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -123,7 +123,7 @@ func TestMessageSign(t *testing.T) { ContainerId: rawCID1, ParentId: 1, NodeId: 2, - Meta: []*KeyValue{ + Meta: []KeyValue{ {Key: "kkk", Value: []byte("vvv")}, }, }, From 2b3fc50681f7e463a74c6075ad16788fc52cfa3f Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 30 Aug 2024 14:02:57 +0300 Subject: [PATCH 0774/1413] [#1320] shard: Fix TestGCDropsObjectInhumedFromWritecache flaky test The `TestGCDropsObjectInhumedFromWritecache` test was flaky because a running asynchronous rebuild operation prevented GC from deleting the object. A test-only shard option `WithDisabledRebuild` has been added to fix this. Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/shard/control.go | 4 ++-- pkg/local_object_storage/shard/gc_test.go | 2 +- pkg/local_object_storage/shard/shard.go | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 1626d58040..6efe4ec379 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -130,7 +130,7 @@ func (s *Shard) Init(ctx context.Context) error { s.gc.init(ctx) s.rb = newRebuilder(s.rebuildLimiter) - if !m.NoMetabase() { + if !m.NoMetabase() && !s.rebuildDisabled { s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) } s.writecacheSealCancel.Store(dummyCancel) @@ -398,7 +398,7 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { defer unlock() s.rb.Stop(s.log) - if !s.info.Mode.NoMetabase() { + if !s.info.Mode.NoMetabase() && !s.rebuildDisabled { defer func() { s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) }() diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index 90958cd355..1c0ef1c2ea 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -187,7 +187,7 @@ func TestGCDropsObjectInhumedFromWritecache(t *testing.T) { func testGCDropsObjectInhumedFromWritecache(t *testing.T, flushbeforeInhume bool) { sh := newCustomShard(t, true, shardOptions{ - additionalShardOptions: []Option{WithDisabledGC()}, + additionalShardOptions: []Option{WithDisabledGC(), WithDisabledRebuild()}, wcOpts: []writecache.Option{writecache.WithDisableBackgroundFlush()}, }) defer func() { require.NoError(t, sh.Close()) }() diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 93f5354a7f..d11bcc36b8 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -139,6 +139,8 @@ type cfg struct { reportErrorFunc func(selfID string, message string, err error) rebuildLimiter RebuildWorkerLimiter + + rebuildDisabled bool } func defaultCfg() *cfg { @@ -410,6 +412,14 @@ func WithZeroCountCallback(cb EmptyContainersCallback) Option { } } +// WithDisabledRebuild returns an option to disable a shard rebuild. +// For testing purposes only. +func WithDisabledRebuild() Option { + return func(c *cfg) { + c.rebuildDisabled = true + } +} + func (s *Shard) fillInfo() { s.cfg.info.MetaBaseInfo = s.metaBase.DumpInfo() s.cfg.info.BlobStorInfo = s.blobStor.DumpInfo() From a685fcdc963b0f58003059bb2dae2d21c925e25a Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 30 Aug 2024 19:20:55 +0300 Subject: [PATCH 0775/1413] [#1317] go.mod: Use range over int Since Go 1.22 a "for" statement with a "range" clause is able to iterate through integer values from zero to an upper limit. gopatch script: @@ var i, e expression @@ -for i := 0; i <= e - 1; i++ { +for i := range e { ... } @@ var i, e expression @@ -for i := 0; i <= e; i++ { +for i := range e + 1 { ... } @@ var i, e expression @@ -for i := 0; i < e; i++ { +for i := range e { ... } Signed-off-by: Ekaterina Lebedeva --- .../modules/morph/contract/dump_hashes.go | 4 ++-- .../modules/morph/helper/local_client.go | 2 +- .../internal/modules/morph/helper/util.go | 2 +- .../morph/initialize/initialize_test.go | 4 ++-- cmd/frostfs-cli/internal/client/client.go | 2 +- cmd/frostfs-cli/modules/container/create.go | 2 +- cmd/frostfs-cli/modules/container/delete.go | 2 +- cmd/frostfs-cli/modules/object/nodes.go | 2 +- cmd/frostfs-cli/modules/util/acl.go | 2 +- cmd/frostfs-node/config/node/config.go | 2 +- cmd/frostfs-node/morph.go | 2 +- pkg/innerring/indexer_test.go | 2 +- pkg/innerring/notary.go | 2 +- .../processors/alphabet/handlers_test.go | 6 ++--- .../processors/governance/handlers_test.go | 2 +- .../processors/governance/list_test.go | 4 ++-- .../blobovnicza/sizes_test.go | 2 +- .../blobovniczatree/concurrency_test.go | 2 +- .../blobstor/blobovniczatree/rebuild_test.go | 2 +- .../blobstor/blobstor_test.go | 12 +++++----- .../blobstor/compression/bench_test.go | 2 +- .../blobstor/fstree/fstree_test.go | 6 ++--- .../blobstor/perf_test.go | 4 ++-- .../engine/control_test.go | 4 ++-- .../engine/engine_test.go | 12 +++++----- .../engine/evacuate_test.go | 4 ++-- pkg/local_object_storage/engine/list_test.go | 2 +- .../engine/remove_copies.go | 2 +- .../engine/remove_copies_test.go | 4 ++-- .../engine/shards_test.go | 2 +- pkg/local_object_storage/engine/tree_test.go | 6 ++--- .../internal/testutil/generators_test.go | 6 ++--- .../metabase/containers_test.go | 8 +++---- .../metabase/counter_test.go | 8 +++---- .../metabase/delete_test.go | 2 +- pkg/local_object_storage/metabase/get_test.go | 4 ++-- .../metabase/list_test.go | 12 +++++----- .../metabase/lock_test.go | 4 ++-- pkg/local_object_storage/metabase/put_test.go | 2 +- .../metabase/reset_test.go | 2 +- .../metabase/select_test.go | 6 ++--- pkg/local_object_storage/metabase/upgrade.go | 2 +- .../metabase/upgrade_test.go | 10 ++++---- pkg/local_object_storage/pilorama/boltdb.go | 2 +- .../pilorama/forest_test.go | 24 +++++++++---------- pkg/local_object_storage/shard/list_test.go | 4 ++-- .../shard/metrics_test.go | 10 ++++---- pkg/local_object_storage/shard/refill_test.go | 4 ++-- .../writecache/benchmark/writecache_test.go | 2 +- pkg/local_object_storage/writecache/flush.go | 2 +- pkg/morph/event/notary_preparator_test.go | 2 +- pkg/morph/timer/block_test.go | 2 +- pkg/network/tls_test.go | 2 +- pkg/services/control/server/evacuate.go | 2 +- pkg/services/object/acl/v2/util_test.go | 2 +- pkg/services/object/get/get_test.go | 8 +++---- pkg/services/object/get/getrangeec_test.go | 2 +- pkg/services/object/put/ec.go | 2 +- pkg/services/object/search/search_test.go | 4 ++-- .../object_manager/placement/cache_test.go | 4 ++-- .../object_manager/placement/traverser.go | 4 ++-- .../placement/traverser_test.go | 6 ++--- .../storage/persistent/executor_test.go | 2 +- pkg/services/tree/getsubtree_test.go | 2 +- pkg/services/tree/replicator.go | 2 +- pkg/util/sync/key_locker_test.go | 2 +- 66 files changed, 135 insertions(+), 135 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index 5a0d295502..be2134b775 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -68,7 +68,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { if irSize != 0 { bw.Reset() - for i := 0; i < irSize; i++ { + for i := range irSize { emit.AppCall(bw.BinWriter, cs.Hash, "resolve", callflag.ReadOnly, helper.GetAlphabetNNSDomain(i), int64(nns.TXT)) @@ -79,7 +79,7 @@ func dumpContractHashes(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't fetch info from NNS: %w", err) } - for i := 0; i < irSize; i++ { + for i := range irSize { info := contractDumpInfo{name: fmt.Sprintf("alphabet %d", i)} if h, err := helper.ParseNNSResolveResult(alphaRes.Stack[i]); err == nil { info.hash = h diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index 44d1b4ecf0..375fa84d74 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -224,7 +224,7 @@ func (l *LocalClient) CalculateNetworkFee(tx *transaction.Transaction) (int64, e paramz = []manifest.Parameter{{Type: smartcontract.SignatureType}} } else if nSigs, _, ok := vm.ParseMultiSigContract(w.VerificationScript); ok { paramz = make([]manifest.Parameter, nSigs) - for j := 0; j < nSigs; j++ { + for j := range nSigs { paramz[j] = manifest.Parameter{Type: smartcontract.SignatureType} } } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/util.go b/cmd/frostfs-adm/internal/modules/morph/helper/util.go index 2d9281c245..8c6b905394 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/util.go @@ -44,7 +44,7 @@ func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, er var wallets []*wallet.Wallet var letter string - for i := 0; i < constants.MaxAlphabetNodes; i++ { + for i := range constants.MaxAlphabetNodes { letter = innerring.GlagoliticLetter(i).String() p := filepath.Join(walletDir, letter+".json") var w *wallet.Wallet diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go index 6c52aa2ab4..74f5d3e888 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go @@ -113,7 +113,7 @@ func generateTestData(dir string, size int) error { } var pubs []string - for i := 0; i < size; i++ { + for i := range size { p := filepath.Join(dir, innerring.GlagoliticLetter(i).String()+".json") w, err := wallet.NewWalletFromFile(p) if err != nil { @@ -148,7 +148,7 @@ func generateTestData(dir string, size int) error { } func setTestCredentials(v *viper.Viper, size int) { - for i := 0; i < size; i++ { + for i := range size { v.Set("credentials."+innerring.GlagoliticLetter(i).String(), strconv.FormatUint(uint64(i), 10)) } v.Set("credentials.contract", constants.TestContractPassword) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index a0fa224108..57bcf5620c 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -692,7 +692,7 @@ func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes for { n, ok = rdr.Read(buf) - for i := 0; i < n; i++ { + for i := range n { list = append(list, buf[i]) } if !ok { diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index c6f5769089..f37b169ce8 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -139,7 +139,7 @@ It will be stored in sidechain when inner ring will accepts it.`, }, } - for i := 0; i < awaitTimeout; i++ { + for range awaitTimeout { time.Sleep(1 * time.Second) _, err := internalclient.GetContainer(cmd.Context(), getPrm) diff --git a/cmd/frostfs-cli/modules/container/delete.go b/cmd/frostfs-cli/modules/container/delete.go index e5425bf252..c20188884b 100644 --- a/cmd/frostfs-cli/modules/container/delete.go +++ b/cmd/frostfs-cli/modules/container/delete.go @@ -110,7 +110,7 @@ Only owner of the container has a permission to remove container.`, }, } - for i := 0; i < awaitTimeout; i++ { + for range awaitTimeout { time.Sleep(1 * time.Second) _, err := internalclient.GetContainer(cmd.Context(), getPrm) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 896f6f17f0..0eac4e6d26 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -195,7 +195,7 @@ func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, member prmHead.SetRawFlag(true) // to get an error instead of whole object eg, egCtx := errgroup.WithContext(cmd.Context()) - for idx := 0; idx < len(members); idx++ { + for idx := range len(members) { partObjID := members[idx] eg.Go(func() error { diff --git a/cmd/frostfs-cli/modules/util/acl.go b/cmd/frostfs-cli/modules/util/acl.go index 4c2e324b3b..145dcc756b 100644 --- a/cmd/frostfs-cli/modules/util/acl.go +++ b/cmd/frostfs-cli/modules/util/acl.go @@ -33,7 +33,7 @@ func PrettyPrintTableBACL(cmd *cobra.Command, bacl *acl.Basic) { fmt.Fprintln(w, strings.Join(bits, "\t")) // Footer footer := []string{"X F"} - for i := 0; i < 7; i++ { + for range 7 { footer = append(footer, "U S O B") } fmt.Fprintln(w, strings.Join(footer, "\t")) diff --git a/cmd/frostfs-node/config/node/config.go b/cmd/frostfs-node/config/node/config.go index 97aca274ab..4d063245b2 100644 --- a/cmd/frostfs-node/config/node/config.go +++ b/cmd/frostfs-node/config/node/config.go @@ -121,7 +121,7 @@ func BootstrapAddresses(c *config.Config) (addr network.AddressGroup) { func Attributes(c *config.Config) (attrs []string) { const maxAttributes = 100 - for i := 0; i < maxAttributes; i++ { + for i := range maxAttributes { attr := config.StringSafe(c.Sub(subsection), attributePrefix+"_"+strconv.Itoa(i)) if attr == "" { return diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 1b148095bd..7178cd97d7 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -157,7 +157,7 @@ var ( ) func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { - for i := 0; i < notaryDepositRetriesAmount; i++ { + for range notaryDepositRetriesAmount { c.log.Debug(logs.ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted) select { case <-ctx.Done(): diff --git a/pkg/innerring/indexer_test.go b/pkg/innerring/indexer_test.go index 5bc2cc9881..c8a819b5be 100644 --- a/pkg/innerring/indexer_test.go +++ b/pkg/innerring/indexer_test.go @@ -237,7 +237,7 @@ func BenchmarkKeyPosition(b *testing.B) { b.ResetTimer() b.ReportAllocs() - for i := 0; i < b.N; i++ { + for range b.N { if keyPosition(key, list) != 5 { b.FailNow() } diff --git a/pkg/innerring/notary.go b/pkg/innerring/notary.go index c601f55876..e6f2b1de4c 100644 --- a/pkg/innerring/notary.go +++ b/pkg/innerring/notary.go @@ -90,7 +90,7 @@ func (s *Server) initNotary(ctx context.Context, deposit depositor, await awaite } func awaitNotaryDepositInClient(ctx context.Context, cli *client.Client, txHash util.Uint256) error { - for i := 0; i < notaryDepositTimeout; i++ { + for range notaryDepositTimeout { select { case <-ctx.Done(): return ctx.Err() diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index 346901949b..dfda374727 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -21,7 +21,7 @@ func TestProcessorEmitsGasToNetmapAndAlphabet(t *testing.T) { var parsedWallets []util.Uint160 = []util.Uint160{{20}, {25}} alphabetContracts := innerring.NewAlphabetContracts() - for i := 0; i <= index; i++ { + for i := range index + 1 { alphabetContracts[innerring.GlagoliticLetter(i)] = util.Uint160{uint8(i)} } @@ -98,7 +98,7 @@ func TestProcessorEmitsGasToNetmapIfNoParsedWallets(t *testing.T) { var parsedWallets []util.Uint160 = []util.Uint160{} alphabetContracts := innerring.NewAlphabetContracts() - for i := 0; i <= index; i++ { + for i := range index + 1 { alphabetContracts[innerring.GlagoliticLetter(i)] = util.Uint160{uint8(i)} } @@ -170,7 +170,7 @@ func TestProcessorDoesntEmitGasIfNoNetmapOrParsedWallets(t *testing.T) { var parsedWallets []util.Uint160 = []util.Uint160{} alphabetContracts := innerring.NewAlphabetContracts() - for i := 0; i <= index; i++ { + for i := range index + 1 { alphabetContracts[innerring.GlagoliticLetter(i)] = util.Uint160{uint8(i)} } diff --git a/pkg/innerring/processors/governance/handlers_test.go b/pkg/innerring/processors/governance/handlers_test.go index 2a505f8d1e..b73e24318c 100644 --- a/pkg/innerring/processors/governance/handlers_test.go +++ b/pkg/innerring/processors/governance/handlers_test.go @@ -190,7 +190,7 @@ func generateTestKeys(t *testing.T) testKeys { for { var result testKeys - for i := 0; i < 4; i++ { + for range 4 { pk, err := keys.NewPrivateKey() require.NoError(t, err, "failed to create private key") result.sidechainKeys = append(result.sidechainKeys, pk.PublicKey()) diff --git a/pkg/innerring/processors/governance/list_test.go b/pkg/innerring/processors/governance/list_test.go index d099ec837a..4ecebf05b4 100644 --- a/pkg/innerring/processors/governance/list_test.go +++ b/pkg/innerring/processors/governance/list_test.go @@ -49,7 +49,7 @@ func TestNewAlphabetList(t *testing.T) { } ln := len(rounds) - for i := 0; i < ln; i++ { + for i := range ln { list, err = newAlphabetList(list, exp) require.NoError(t, err) require.True(t, equalPublicKeyLists(list, rounds[i])) @@ -131,7 +131,7 @@ func TestUpdateInnerRing(t *testing.T) { func generateKeys(n int) (keys.PublicKeys, error) { pubKeys := make(keys.PublicKeys, 0, n) - for i := 0; i < n; i++ { + for range n { privKey, err := keys.NewPrivateKey() if err != nil { return nil, err diff --git a/pkg/local_object_storage/blobovnicza/sizes_test.go b/pkg/local_object_storage/blobovnicza/sizes_test.go index 01093b8d75..d582fc5e49 100644 --- a/pkg/local_object_storage/blobovnicza/sizes_test.go +++ b/pkg/local_object_storage/blobovnicza/sizes_test.go @@ -42,7 +42,7 @@ func TestSizes(t *testing.T) { func BenchmarkUpperBound(b *testing.B) { for _, size := range []uint64{1, 1023, 65 * 1024, 40 * 1024 * 1024} { b.Run(fmt.Sprintf("size=%d", size), func(b *testing.B) { - for i := 0; i < b.N; i++ { + for range b.N { _ = upperPowerOfTwo(size) } }) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go index 5bed861421..cc8a52d036 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -34,7 +34,7 @@ func TestBlobovniczaTree_Concurrency(t *testing.T) { var cnt atomic.Int64 var wg sync.WaitGroup - for i := 0; i < 1000; i++ { + for range 1000 { wg.Add(1) go func() { defer wg.Done() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 7a1de4c130..4a51fd86a7 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -127,7 +127,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta eg, egCtx := errgroup.WithContext(context.Background()) storageIDs := make(map[oid.Address][]byte) storageIDsGuard := &sync.Mutex{} - for i := 0; i < 100; i++ { + for range 100 { eg.Go(func() error { obj := blobstortest.NewObject(1024) data, err := obj.Marshal() diff --git a/pkg/local_object_storage/blobstor/blobstor_test.go b/pkg/local_object_storage/blobstor/blobstor_test.go index c7d80dc840..bed5e0eb96 100644 --- a/pkg/local_object_storage/blobstor/blobstor_test.go +++ b/pkg/local_object_storage/blobstor/blobstor_test.go @@ -60,7 +60,7 @@ func TestCompression(t *testing.T) { bigObj := make([]*objectSDK.Object, objCount) smallObj := make([]*objectSDK.Object, objCount) - for i := 0; i < objCount; i++ { + for i := range objCount { bigObj[i] = testObject(smallSizeLimit * 2) smallObj[i] = testObject(smallSizeLimit / 2) } @@ -219,7 +219,7 @@ func TestConcurrentPut(t *testing.T) { bigObj := testObject(smallSizeLimit * 2) var wg sync.WaitGroup - for i := 0; i < concurrentPutCount; i++ { + for range concurrentPutCount { wg.Add(1) go func() { testPut(t, blobStor, bigObj) @@ -235,7 +235,7 @@ func TestConcurrentPut(t *testing.T) { bigObj := testObject(smallSizeLimit * 2) var wg sync.WaitGroup - for i := 0; i < concurrentPutCount+1; i++ { + for range concurrentPutCount + 1 { wg.Add(1) go func() { testPutFileExistsError(t, blobStor, bigObj) @@ -251,7 +251,7 @@ func TestConcurrentPut(t *testing.T) { smallObj := testObject(smallSizeLimit / 2) var wg sync.WaitGroup - for i := 0; i < concurrentPutCount; i++ { + for range concurrentPutCount { wg.Add(1) go func() { testPut(t, blobStor, smallObj) @@ -302,7 +302,7 @@ func TestConcurrentDelete(t *testing.T) { testPut(t, blobStor, bigObj) var wg sync.WaitGroup - for i := 0; i < 2; i++ { + for range 2 { wg.Add(1) go func() { testDelete(t, blobStor, bigObj) @@ -319,7 +319,7 @@ func TestConcurrentDelete(t *testing.T) { testPut(t, blobStor, smallObj) var wg sync.WaitGroup - for i := 0; i < 2; i++ { + for range 2 { wg.Add(1) go func() { testDelete(t, blobStor, smallObj) diff --git a/pkg/local_object_storage/blobstor/compression/bench_test.go b/pkg/local_object_storage/blobstor/compression/bench_test.go index 986912985b..9f70f8ec2a 100644 --- a/pkg/local_object_storage/blobstor/compression/bench_test.go +++ b/pkg/local_object_storage/blobstor/compression/bench_test.go @@ -36,7 +36,7 @@ func BenchmarkCompression(b *testing.B) { func benchWith(b *testing.B, c Config, data []byte) { b.ResetTimer() b.ReportAllocs() - for i := 0; i < b.N; i++ { + for range b.N { _ = c.Compress(data) } } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_test.go b/pkg/local_object_storage/blobstor/fstree/fstree_test.go index d633cbac36..5786dfd3b2 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_test.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_test.go @@ -28,7 +28,7 @@ func Benchmark_addressFromString(b *testing.B) { b.ReportAllocs() b.ResetTimer() - for i := 0; i < b.N; i++ { + for range b.N { _, err := addressFromString(s) if err != nil { b.Fatalf("benchmark error: %v", err) @@ -73,7 +73,7 @@ func TestObjectCounter(t *testing.T) { eg, egCtx := errgroup.WithContext(context.Background()) eg.Go(func() error { - for j := 0; j < 1_000; j++ { + for range 1_000 { _, err := fst.Put(egCtx, putPrm) if err != nil { return err @@ -84,7 +84,7 @@ func TestObjectCounter(t *testing.T) { eg.Go(func() error { var le logicerr.Logical - for j := 0; j < 1_000; j++ { + for range 1_000 { _, err := fst.Delete(egCtx, delPrm) if err != nil && !errors.As(err, &le) { return err diff --git a/pkg/local_object_storage/blobstor/perf_test.go b/pkg/local_object_storage/blobstor/perf_test.go index 501c95a1dc..1ac769e367 100644 --- a/pkg/local_object_storage/blobstor/perf_test.go +++ b/pkg/local_object_storage/blobstor/perf_test.go @@ -110,7 +110,7 @@ func BenchmarkSubstorageReadPerf(b *testing.B) { // Fill database var errG errgroup.Group - for i := 0; i < tt.size; i++ { + for range tt.size { obj := objGen.Next() addr := testutil.AddressFromObject(b, obj) errG.Go(func() error { @@ -203,7 +203,7 @@ func BenchmarkSubstorageIteratePerf(b *testing.B) { defer func() { require.NoError(b, st.Close()) }() // Fill database - for i := 0; i < tt.size; i++ { + for range tt.size { obj := objGen.Next() addr := testutil.AddressFromObject(b, obj) raw, err := obj.Marshal() diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index f0809883c8..2de92ae844 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -208,7 +208,7 @@ func TestPersistentShardID(t *testing.T) { require.NoError(t, te.ng.Close(context.Background())) newTe := newEngineWithErrorThreshold(t, dir, 1) - for i := 0; i < len(newTe.shards); i++ { + for i := range len(newTe.shards) { require.Equal(t, te.shards[i].id, newTe.shards[i].id) } require.NoError(t, newTe.ng.Close(context.Background())) @@ -269,7 +269,7 @@ func TestReload(t *testing.T) { e, currShards := engineWithShards(t, removePath, shardNum) var rcfg ReConfiguration - for i := 0; i < len(currShards)-1; i++ { // without one of the shards + for i := range len(currShards) - 1 { // without one of the shards rcfg.AddShard(currShards[i], nil) } diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 49976abbb6..525e17f341 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -44,7 +44,7 @@ func BenchmarkExists(b *testing.B) { func benchmarkExists(b *testing.B, shardNum int) { shards := make([]*shard.Shard, shardNum) - for i := 0; i < shardNum; i++ { + for i := range shardNum { shards[i] = testNewShard(b) } @@ -52,7 +52,7 @@ func benchmarkExists(b *testing.B, shardNum int) { defer func() { require.NoError(b, e.Close(context.Background())) }() addr := oidtest.Address() - for i := 0; i < 100; i++ { + for range 100 { obj := testutil.GenerateObjectWithCID(cidtest.ID()) err := Put(context.Background(), e, obj) if err != nil { @@ -62,7 +62,7 @@ func benchmarkExists(b *testing.B, shardNum int) { b.ReportAllocs() b.ResetTimer() - for i := 0; i < b.N; i++ { + for range b.N { var shPrm shard.ExistsPrm shPrm.Address = addr shPrm.ParentAddress = oid.Address{} @@ -109,7 +109,7 @@ func (te *testEngineWrapper) setInitializedShards(t testing.TB, shards ...*shard func (te *testEngineWrapper) setShardsNum(t testing.TB, num int) *testEngineWrapper { shards := make([]*shard.Shard, 0, num) - for i := 0; i < num; i++ { + for range num { shards = append(shards, testNewShard(t)) } @@ -117,7 +117,7 @@ func (te *testEngineWrapper) setShardsNum(t testing.TB, num int) *testEngineWrap } func (te *testEngineWrapper) setShardsNumOpts(t testing.TB, num int, shardOpts func(id int) []shard.Option) *testEngineWrapper { - for i := 0; i < num; i++ { + for i := range num { opts := shardOpts(i) id, err := te.engine.AddShard(context.Background(), opts...) require.NoError(t, err) @@ -127,7 +127,7 @@ func (te *testEngineWrapper) setShardsNumOpts(t testing.TB, num int, shardOpts f } func (te *testEngineWrapper) setShardsNumAdditionalOpts(t testing.TB, num int, shardOpts func(id int) []shard.Option) *testEngineWrapper { - for i := 0; i < num; i++ { + for i := range num { defaultOpts := testDefaultShardOptions(t) opts := append(defaultOpts, shardOpts(i)...) id, err := te.engine.AddShard(context.Background(), opts...) diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 55268b549b..8d25dad4a6 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -61,7 +61,7 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng } for _, sh := range ids { - for i := 0; i < objPerShard; i++ { + for range objPerShard { contID := cidtest.ID() obj := testutil.GenerateObjectWithCID(contID) objects = append(objects, obj) @@ -554,7 +554,7 @@ func TestEvacuateTreesRemote(t *testing.T) { require.Equal(t, "", st.ErrorMessage(), "invalid final error message") expectedTreeOps := make(map[string][]*pilorama.Move) - for i := 0; i < len(e.shards); i++ { + for i := range len(e.shards) { sourceTrees, err := pilorama.TreeListAll(context.Background(), e.shards[ids[i].String()]) require.NoError(t, err, "list source trees failed") require.Len(t, sourceTrees, 3) diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index dd8a2e8a09..11a6c7841b 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -79,7 +79,7 @@ func TestListWithCursor(t *testing.T) { expected := make([]object.Info, 0, tt.objectNum) got := make([]object.Info, 0, tt.objectNum) - for i := 0; i < tt.objectNum; i++ { + for range tt.objectNum { containerID := cidtest.ID() obj := testutil.GenerateObjectWithCIDWithPayload(containerID, []byte{'a'}) diff --git a/pkg/local_object_storage/engine/remove_copies.go b/pkg/local_object_storage/engine/remove_copies.go index b99cf4f444..5e1ced56a3 100644 --- a/pkg/local_object_storage/engine/remove_copies.go +++ b/pkg/local_object_storage/engine/remove_copies.go @@ -87,7 +87,7 @@ func (e *StorageEngine) RemoveDuplicates(ctx context.Context, prm RemoveDuplicat } }) - for i := 0; i < prm.Concurrency; i++ { + for range prm.Concurrency { errG.Go(func() error { return e.removeObjects(ctx, ch) }) diff --git a/pkg/local_object_storage/engine/remove_copies_test.go b/pkg/local_object_storage/engine/remove_copies_test.go index 99963576cb..6d2291c744 100644 --- a/pkg/local_object_storage/engine/remove_copies_test.go +++ b/pkg/local_object_storage/engine/remove_copies_test.go @@ -96,7 +96,7 @@ loop: require.FailNow(t, "unexpected object was removed", removed[i].addr) } - for i := 0; i < copyCount; i++ { + for i := range copyCount { if i%3 == 0 { require.True(t, removedMask[i], "object %d was expected to be removed", i) } else { @@ -207,7 +207,7 @@ func TestRebalanceExitByContext(t *testing.T) { }() const removeCount = 3 - for i := 0; i < removeCount-1; i++ { + for range removeCount - 1 { <-deleteCh signal <- struct{}{} } diff --git a/pkg/local_object_storage/engine/shards_test.go b/pkg/local_object_storage/engine/shards_test.go index f4c7a4309b..3347d58f19 100644 --- a/pkg/local_object_storage/engine/shards_test.go +++ b/pkg/local_object_storage/engine/shards_test.go @@ -72,7 +72,7 @@ func TestSortShardsByWeight(t *testing.T) { var shards1 []hashedShard var weights1 []float64 var shards2 []hashedShard - for i := 0; i < numOfShards; i++ { + for i := range numOfShards { shards1 = append(shards1, hashedShard{ hash: uint64(i), }) diff --git a/pkg/local_object_storage/engine/tree_test.go b/pkg/local_object_storage/engine/tree_test.go index 2739058e94..6f694f0821 100644 --- a/pkg/local_object_storage/engine/tree_test.go +++ b/pkg/local_object_storage/engine/tree_test.go @@ -34,7 +34,7 @@ func benchmarkTreeVsSearch(b *testing.B, objCount int) { d := pilorama.CIDDescriptor{CID: cid, Position: 0, Size: 1} treeID := "someTree" - for i := 0; i < objCount; i++ { + for i := range objCount { obj := testutil.GenerateObjectWithCID(cid) testutil.AddAttribute(obj, pilorama.AttributeFilename, strconv.Itoa(i)) err := Put(context.Background(), te.ng, obj) @@ -56,7 +56,7 @@ func benchmarkTreeVsSearch(b *testing.B, objCount int) { fs.AddFilter(pilorama.AttributeFilename, strconv.Itoa(objCount/2), objectSDK.MatchStringEqual) prm.WithFilters(fs) - for i := 0; i < b.N; i++ { + for range b.N { res, err := te.ng.Select(context.Background(), prm) if err != nil { b.Fatal(err) @@ -67,7 +67,7 @@ func benchmarkTreeVsSearch(b *testing.B, objCount int) { } }) b.Run("TreeGetByPath", func(b *testing.B) { - for i := 0; i < b.N; i++ { + for range b.N { nodes, err := te.ng.TreeGetByPath(context.Background(), cid, treeID, pilorama.AttributeFilename, []string{strconv.Itoa(objCount / 2)}, true) if err != nil { b.Fatal(err) diff --git a/pkg/local_object_storage/internal/testutil/generators_test.go b/pkg/local_object_storage/internal/testutil/generators_test.go index f7be6014d6..cc6f726a40 100644 --- a/pkg/local_object_storage/internal/testutil/generators_test.go +++ b/pkg/local_object_storage/internal/testutil/generators_test.go @@ -13,7 +13,7 @@ func TestOverwriteObjGenerator(t *testing.T) { ObjSize: 10, MaxObjects: 4, } - for i := 0; i < 40; i++ { + for range 40 { obj := gen.Next() id, isSet := obj.ID() i := binary.LittleEndian.Uint64(id[:]) @@ -26,7 +26,7 @@ func TestOverwriteObjGenerator(t *testing.T) { func TestRandObjGenerator(t *testing.T) { gen := &RandObjGenerator{ObjSize: 10} - for i := 0; i < 10; i++ { + for range 10 { obj := gen.Next() require.Equal(t, gen.ObjSize, uint64(len(obj.Payload()))) @@ -50,7 +50,7 @@ func TestSeqObjGenerator(t *testing.T) { func TestRandAddrGenerator(t *testing.T) { gen := RandAddrGenerator(5) - for i := 0; i < 50; i++ { + for range 50 { addr := gen.Next() id := addr.Object() k := binary.LittleEndian.Uint64(id[:]) diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index 5d6788d7e9..8b18744585 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -24,7 +24,7 @@ func TestDB_Containers(t *testing.T) { cids := make(map[string]int, N) - for i := 0; i < N; i++ { + for range N { obj := testutil.GenerateObject() cnr, _ := obj.ContainerID() @@ -95,7 +95,7 @@ func TestDB_ContainersCount(t *testing.T) { expected := make([]cid.ID, 0, R+T+SG+L) for _, upload := range uploadObjects { - for i := 0; i < upload.amount; i++ { + for range upload.amount { obj := testutil.GenerateObject() obj.SetType(upload.typ) @@ -126,11 +126,11 @@ func TestDB_ContainerSize(t *testing.T) { cids := make(map[cid.ID]int, C) objs := make(map[cid.ID][]*objectSDK.Object, C*N) - for i := 0; i < C; i++ { + for range C { cnr := cidtest.ID() cids[cnr] = 0 - for j := 0; j < N; j++ { + for range N { size := rand.Intn(1024) parent := testutil.GenerateObjectWithCID(cnr) diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index 1797fc0aa3..d1f808a633 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -39,14 +39,14 @@ func TestCounters(t *testing.T) { db := newDB(t) defer func() { require.NoError(t, db.Close()) }() oo := make([]*objectSDK.Object, 0, objCount) - for i := 0; i < objCount; i++ { + for range objCount { oo = append(oo, testutil.GenerateObject()) } var prm meta.PutPrm exp := make(map[cid.ID]meta.ObjectCounters) - for i := 0; i < objCount; i++ { + for i := range objCount { prm.SetObject(oo[i]) cnrID, _ := oo[i].ContainerID() c := meta.ObjectCounters{} @@ -187,7 +187,7 @@ func TestCounters(t *testing.T) { // put objects and check that parent info // does not affect the counter - for i := 0; i < objCount; i++ { + for i := range objCount { o := testutil.GenerateObject() if i < objCount/2 { // half of the objs will have the parent o.SetParent(parObj) @@ -535,7 +535,7 @@ func putObjs(t *testing.T, db *meta.DB, count int, withParent bool) []*objectSDK parent := testutil.GenerateObject() oo := make([]*objectSDK.Object, 0, count) - for i := 0; i < count; i++ { + for i := range count { o := testutil.GenerateObject() if withParent { o.SetParent(parent) diff --git a/pkg/local_object_storage/metabase/delete_test.go b/pkg/local_object_storage/metabase/delete_test.go index 2053874d03..cb85157e78 100644 --- a/pkg/local_object_storage/metabase/delete_test.go +++ b/pkg/local_object_storage/metabase/delete_test.go @@ -131,7 +131,7 @@ func TestDelete(t *testing.T) { defer func() { require.NoError(t, db.Close()) }() cnr := cidtest.ID() - for i := 0; i < 10; i++ { + for range 10 { obj := testutil.GenerateObjectWithCID(cnr) var prm meta.PutPrm diff --git a/pkg/local_object_storage/metabase/get_test.go b/pkg/local_object_storage/metabase/get_test.go index 247ddf9cdd..7654d2cd88 100644 --- a/pkg/local_object_storage/metabase/get_test.go +++ b/pkg/local_object_storage/metabase/get_test.go @@ -223,7 +223,7 @@ func benchmarkGet(b *testing.B, numOfObj int) { defer func() { require.NoError(b, db.Close()) }() addrs := make([]oid.Address, 0, numOfObj) - for i := 0; i < numOfObj; i++ { + for range numOfObj { raw := testutil.GenerateObject() addrs = append(addrs, object.AddressOf(raw)) @@ -261,7 +261,7 @@ func benchmarkGet(b *testing.B, numOfObj int) { b.Run("serial", func(b *testing.B) { b.ReportAllocs() - for i := 0; i < b.N; i++ { + for i := range b.N { var getPrm meta.GetPrm getPrm.SetAddress(addrs[i%len(addrs)]) diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index a92e2eff4f..6207497b1a 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -35,7 +35,7 @@ func listWithCursorPrepareDB(b *testing.B) *meta.DB { defer func() { require.NoError(b, db.Close()) }() obj := testutil.GenerateObject() - for i := 0; i < 100_000; i++ { // should be a multiple of all batch sizes + for i := range 100_000 { // should be a multiple of all batch sizes obj.SetID(oidtest.ID()) if i%9 == 0 { // let's have 9 objects per container obj.SetContainerID(cidtest.ID()) @@ -51,7 +51,7 @@ func benchmarkListWithCursor(b *testing.B, db *meta.DB, batchSize int) { b.ResetTimer() b.ReportAllocs() - for i := 0; i < b.N; i++ { + for range b.N { res, err := db.ListWithCursor(context.Background(), prm) if err != nil { if err != meta.ErrEndOfListing { @@ -80,7 +80,7 @@ func TestLisObjectsWithCursor(t *testing.T) { expected := make([]object.Info, 0, total) // fill metabase with objects - for i := 0; i < containers; i++ { + for range containers { containerID := cidtest.ID() // add one regular object @@ -140,7 +140,7 @@ func TestLisObjectsWithCursor(t *testing.T) { expectedIterations-- } - for i := 0; i < expectedIterations; i++ { + for range expectedIterations { res, cursor, err = metaListWithCursor(db, uint32(countPerReq), cursor) require.NoError(t, err, "count:%d", countPerReq) got = append(got, res...) @@ -169,7 +169,7 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { expected := make(map[string]int, total) // fill metabase with objects - for i := 0; i < total; i++ { + for range total { obj := testutil.GenerateObject() err := putBig(db, obj) require.NoError(t, err) @@ -186,7 +186,7 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { } // add new objects - for i := 0; i < total; i++ { + for range total { obj := testutil.GenerateObject() err = putBig(db, obj) require.NoError(t, err) diff --git a/pkg/local_object_storage/metabase/lock_test.go b/pkg/local_object_storage/metabase/lock_test.go index 2d7bfc1cc5..62a109b023 100644 --- a/pkg/local_object_storage/metabase/lock_test.go +++ b/pkg/local_object_storage/metabase/lock_test.go @@ -155,7 +155,7 @@ func TestDB_Lock(t *testing.T) { inhumePrm.SetGCMark() - for i := 0; i < objsNum; i++ { + for i := range objsNum { inhumePrm.SetAddresses(objectcore.AddressOf(objs[i])) res, err = db.Inhume(context.Background(), inhumePrm) @@ -255,7 +255,7 @@ func putAndLockObj(t *testing.T, db *meta.DB, numOfLockedObjs int) ([]*objectSDK lockedObjs := make([]*objectSDK.Object, 0, numOfLockedObjs) lockedObjIDs := make([]oid.ID, 0, numOfLockedObjs) - for i := 0; i < numOfLockedObjs; i++ { + for range numOfLockedObjs { obj := testutil.GenerateObjectWithCID(cnr) err := putBig(db, obj) require.NoError(t, err) diff --git a/pkg/local_object_storage/metabase/put_test.go b/pkg/local_object_storage/metabase/put_test.go index 84e4029f28..914f5ef065 100644 --- a/pkg/local_object_storage/metabase/put_test.go +++ b/pkg/local_object_storage/metabase/put_test.go @@ -74,7 +74,7 @@ func BenchmarkPut(b *testing.B) { objs := prepareObjects(b.N) b.ResetTimer() b.ReportAllocs() - for i := 0; i < b.N; i++ { + for range b.N { if err := metaPut(db, objs[index.Add(1)], nil); err != nil { b.Fatal(err) } diff --git a/pkg/local_object_storage/metabase/reset_test.go b/pkg/local_object_storage/metabase/reset_test.go index 66f5eefc61..993079dcec 100644 --- a/pkg/local_object_storage/metabase/reset_test.go +++ b/pkg/local_object_storage/metabase/reset_test.go @@ -34,7 +34,7 @@ func TestResetDropsContainerBuckets(t *testing.T) { defer func() { require.NoError(t, db.Close()) }() - for idx := 0; idx < 100; idx++ { + for idx := range 100 { var putPrm PutPrm putPrm.SetObject(testutil.GenerateObject()) putPrm.SetStorageID([]byte(fmt.Sprintf("0/%d", idx))) diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 4fbc5910ea..0fab3a1085 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -920,7 +920,7 @@ func TestDB_SelectSplitID_EC(t *testing.T) { ec, err := erasurecode.NewConstructor(dataCount, parityCount) require.NoError(t, err) - for i := 0; i < partCount; i++ { + for i := range partCount { cs, err := ec.Split(tt.objects[i], &pk.PrivateKey) require.NoError(t, err) @@ -1070,7 +1070,7 @@ func BenchmarkSelect(b *testing.B) { cid := cidtest.ID() - for i := 0; i < objCount; i++ { + for i := range objCount { var attr objectSDK.Attribute attr.SetKey("myHeader") attr.SetValue(strconv.Itoa(i)) @@ -1129,7 +1129,7 @@ func benchmarkSelect(b *testing.B, db *meta.DB, cid cidSDK.ID, fs objectSDK.Sear prm.SetContainerID(cid) prm.SetFilters(fs) - for i := 0; i < b.N; i++ { + for range b.N { res, err := db.Select(context.Background(), prm) if err != nil { b.Fatal(err) diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index a4c7707b44..e9abd746cb 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -143,7 +143,7 @@ func createExpirationEpochBuckets(ctx context.Context, db *bbolt.DB, log func(a return selectObjectsWithExpirationEpoch(ctx, db, objects) }) var count atomic.Uint64 - for i := 0; i < upgradeWorkersCount; i++ { + for range upgradeWorkersCount { eg.Go(func() error { for { select { diff --git a/pkg/local_object_storage/metabase/upgrade_test.go b/pkg/local_object_storage/metabase/upgrade_test.go index dc3d7d07dc..3797de0a45 100644 --- a/pkg/local_object_storage/metabase/upgrade_test.go +++ b/pkg/local_object_storage/metabase/upgrade_test.go @@ -91,7 +91,7 @@ func TestGenerateMetabaseFile(t *testing.T) { eg, ctx := errgroup.WithContext(context.Background()) eg.SetLimit(generateWorkersCount) // simple objects - for i := 0; i < simpleObjectsCount; i++ { + for i := range simpleObjectsCount { i := i eg.Go(func() error { obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) @@ -110,7 +110,7 @@ func TestGenerateMetabaseFile(t *testing.T) { eg, ctx = errgroup.WithContext(context.Background()) eg.SetLimit(generateWorkersCount) // complex objects - for i := 0; i < complexObjectsCount; i++ { + for i := range complexObjectsCount { i := i eg.Go(func() error { parent := testutil.GenerateObjectWithCID(containers[i%len(containers)]) @@ -134,7 +134,7 @@ func TestGenerateMetabaseFile(t *testing.T) { eg, ctx = errgroup.WithContext(context.Background()) eg.SetLimit(generateWorkersCount) // simple objects deleted by gc marks - for i := 0; i < deletedByGCMarksCount; i++ { + for i := range deletedByGCMarksCount { i := i eg.Go(func() error { obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) @@ -156,7 +156,7 @@ func TestGenerateMetabaseFile(t *testing.T) { eg, ctx = errgroup.WithContext(context.Background()) eg.SetLimit(10000) // simple objects deleted by tombstones - for i := 0; i < deletedByTombstoneCount; i++ { + for i := range deletedByTombstoneCount { i := i eg.Go(func() error { obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) @@ -186,7 +186,7 @@ func TestGenerateMetabaseFile(t *testing.T) { eg, ctx = errgroup.WithContext(context.Background()) eg.SetLimit(generateWorkersCount) // simple objects locked by locks - for i := 0; i < lockedCount; i++ { + for i := range lockedCount { i := i eg.Go(func() error { obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 29941be837..e2d69cafa4 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -705,7 +705,7 @@ func (t *boltForest) applyOperation(logBucket, treeBucket *bbolt.Bucket, ms []*M key, value = c.Prev() } - for i := 0; i < len(ms); i++ { + for i := range len(ms) { // Loop invariant: key represents the next stored timestamp after ms[i].Time. // 2. Insert the operation. diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 41d7a567c3..854fe0aadc 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -194,7 +194,7 @@ func BenchmarkForestSortedIteration(b *testing.B) { const total = 100_000 d := CIDDescriptor{cnr, 0, 1} - for i := 0; i < total; i++ { + for i := range total { u, err := uuid.NewRandom() if err != nil { b.FailNow() @@ -216,7 +216,7 @@ func BenchmarkForestSortedIteration(b *testing.B) { } b.Run(providers[i].name+",root", func(b *testing.B) { - for i := 0; i < b.N; i++ { + for range b.N { res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, MultiNode{RootID}, nil, 100) if err != nil || len(res) != 100 { b.Fatalf("err %v, count %d", err, len(res)) @@ -224,7 +224,7 @@ func BenchmarkForestSortedIteration(b *testing.B) { } }) b.Run(providers[i].name+",leaf", func(b *testing.B) { - for i := 0; i < b.N; i++ { + for range b.N { res, _, err := f.TreeSortedByFilename(context.Background(), cnr, treeID, MultiNode{1}, nil, 100) if err != nil || len(res) != 0 { b.FailNow() @@ -804,7 +804,7 @@ func testForestApplySameOperation(t *testing.T, constructor func(t testing.TB, _ defer func() { require.NoError(t, s.Close()) }() require.NoError(t, s.TreeApply(ctx, cid, treeID, &logs[0], false)) - for i := 0; i < batchSize; i++ { + for range batchSize { errG.Go(func() error { return s.TreeApply(ctx, cid, treeID, &logs[2], false) }) @@ -1043,7 +1043,7 @@ func TestForest_ParallelApply(t *testing.T) { // The operations are guaranteed to be applied and returned sorted by `Time`. func prepareRandomTree(nodeCount, opCount int) []Move { ops := make([]Move, nodeCount+opCount) - for i := 0; i < nodeCount; i++ { + for i := range nodeCount { ops[i] = Move{ Parent: 0, Meta: Meta{ @@ -1121,14 +1121,14 @@ func testForestTreeParallelApply(t *testing.T, constructor func(t testing.TB, _ require.NoError(t, expected.TreeApply(context.Background(), cid, treeID, &ops[i], false)) } - for i := 0; i < iterCount; i++ { + for range iterCount { // Shuffle random operations, leave initialization in place. r.Shuffle(len(ops), func(i, j int) { ops[i], ops[j] = ops[j], ops[i] }) actual := constructor(t, WithMaxBatchSize(batchSize), WithNoSync(true)) wg := new(sync.WaitGroup) ch := make(chan *Move) - for i := 0; i < batchSize; i++ { + for range batchSize { wg.Add(1) go func() { defer wg.Done() @@ -1170,7 +1170,7 @@ func testForestTreeApplyRandom(t *testing.T, constructor func(t testing.TB, _ .. } const iterCount = 200 - for i := 0; i < iterCount; i++ { + for range iterCount { // Shuffle random operations, leave initialization in place. r.Shuffle(len(ops), func(i, j int) { ops[i], ops[j] = ops[j], ops[i] }) @@ -1247,7 +1247,7 @@ func BenchmarkApplyReorderLast(b *testing.B) { Child: uint64(r.Intn(benchNodeCount)), } if i != 0 && i%blockSize == 0 { - for j := 0; j < blockSize/2; j++ { + for j := range blockSize / 2 { ops[i-j], ops[i+j-blockSize] = ops[i+j-blockSize], ops[i-j] } } @@ -1265,7 +1265,7 @@ func benchmarkApply(b *testing.B, s Forest, genFunc func(int) []Move) { cid := cidtest.ID() treeID := "version" ch := make(chan int, b.N) - for i := 0; i < b.N; i++ { + for i := range b.N { ch <- i } @@ -1311,7 +1311,7 @@ func testTreeGetByPath(t *testing.T, s ForestStorage) { if mf, ok := s.(*memoryForest); ok { single := mf.treeMap[cid.String()+"/"+treeID] t.Run("test meta", func(t *testing.T) { - for i := 0; i < 6; i++ { + for i := range 6 { require.Equal(t, uint64(i), single.infoMap[Node(i+1)].Meta.Time) } }) @@ -1492,7 +1492,7 @@ func testTreeListTreesCount(t *testing.T, constructor func(t testing.TB, _ ...Op var expected []ContainerIDTreeID treeIDs := []string{"version", "system", "s", "avada kedavra"} - for i := 0; i < count; i++ { + for i := range count { cid := cidtest.ID() treeID := treeIDs[i%len(treeIDs)] expected = append(expected, ContainerIDTreeID{ diff --git a/pkg/local_object_storage/shard/list_test.go b/pkg/local_object_storage/shard/list_test.go index 8a49a36fdd..3414dc76a6 100644 --- a/pkg/local_object_storage/shard/list_test.go +++ b/pkg/local_object_storage/shard/list_test.go @@ -39,11 +39,11 @@ func testShardList(t *testing.T, sh *Shard) { var errG errgroup.Group errG.SetLimit(C * N) - for i := 0; i < C; i++ { + for range C { errG.Go(func() error { cnr := cidtest.ID() - for j := 0; j < N; j++ { + for range N { errG.Go(func() error { obj := testutil.GenerateObjectWithCID(cnr) testutil.AddPayload(obj, 1<<2) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 38d465f310..1ef849c02f 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -206,7 +206,7 @@ func TestCounters(t *testing.T) { const objNumber = 10 oo := make([]*objectSDK.Object, objNumber) - for i := 0; i < objNumber; i++ { + for i := range objNumber { oo[i] = testutil.GenerateObject() } @@ -248,7 +248,7 @@ func TestCounters(t *testing.T) { var prm PutPrm - for i := 0; i < objNumber; i++ { + for i := range objNumber { prm.SetObject(oo[i]) _, err := sh.Put(context.Background(), prm) @@ -269,7 +269,7 @@ func TestCounters(t *testing.T) { var prm InhumePrm inhumedNumber := objNumber / 4 - for i := 0; i < inhumedNumber; i++ { + for i := range inhumedNumber { prm.MarkAsGarbage(objectcore.AddressOf(oo[i])) _, err := sh.Inhume(context.Background(), prm) @@ -317,7 +317,7 @@ func TestCounters(t *testing.T) { _, err := sh.Inhume(context.Background(), prm) require.NoError(t, err) - for i := 0; i < inhumedNumber; i++ { + for i := range inhumedNumber { cid, ok := oo[i].ContainerID() require.True(t, ok) expectedLogicalSizes[cid.EncodeToString()] -= int64(oo[i].PayloadSize()) @@ -419,7 +419,7 @@ func shardWithMetrics(t *testing.T, path string) (*Shard, *metricsStore) { func addrFromObjs(oo []*objectSDK.Object) []oid.Address { aa := make([]oid.Address, len(oo)) - for i := 0; i < len(oo); i++ { + for i := range len(oo) { aa[i] = objectcore.AddressOf(oo[i]) } diff --git a/pkg/local_object_storage/shard/refill_test.go b/pkg/local_object_storage/shard/refill_test.go index 509ccaaa6f..0025bb45ae 100644 --- a/pkg/local_object_storage/shard/refill_test.go +++ b/pkg/local_object_storage/shard/refill_test.go @@ -38,7 +38,7 @@ func benchRefillMetabase(b *testing.B, objectsCount int) { var putPrm PutPrm - for i := 0; i < objectsCount/2; i++ { + for range objectsCount / 2 { obj := testutil.GenerateObject() testutil.AddAttribute(obj, "foo", "bar") testutil.AddPayload(obj, 1<<5) // blobvnicza tree obj @@ -49,7 +49,7 @@ func benchRefillMetabase(b *testing.B, objectsCount int) { require.NoError(b, err) } - for i := 0; i < objectsCount/2; i++ { + for range objectsCount / 2 { obj := testutil.GenerateObject() testutil.AddAttribute(obj, "foo", "bar") obj.SetID(oidtest.ID()) diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index 4f4398452e..4da9a26d76 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -54,7 +54,7 @@ func benchmarkPutSeq(b *testing.B, cache writecache.Cache, size uint64) { objGen := testutil.RandObjGenerator{ObjSize: size} b.ResetTimer() - for n := 0; n < b.N; n++ { + for range b.N { obj := objGen.Next() rawData, err := obj.Marshal() require.NoError(b, err, "marshaling object") diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index e34f5a76b3..930ac84312 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -41,7 +41,7 @@ func (c *cache) runFlushLoop(ctx context.Context) { if c.disableBackgroundFlush { return } - for i := 0; i < c.workersCount; i++ { + for range c.workersCount { c.wg.Add(1) go c.workerFlushSmall(ctx) } diff --git a/pkg/morph/event/notary_preparator_test.go b/pkg/morph/event/notary_preparator_test.go index 8da9d868a8..4c269bcbdb 100644 --- a/pkg/morph/event/notary_preparator_test.go +++ b/pkg/morph/event/notary_preparator_test.go @@ -439,7 +439,7 @@ func TestPrepare_CorrectNR(t *testing.T) { ) for _, test := range tests { - for i := 0; i < 1; i++ { // run tests against 3 and 4 witness NR + for i := range 1 { // run tests against 3 and 4 witness NR for _, dummyMultisig := range []bool{true, false} { // run tests against empty and dummy multisig/Notary witness additionalWitness := i == 0 nr := correctNR(script(test.hash, test.method, test.args...), dummyMultisig, additionalWitness) diff --git a/pkg/morph/timer/block_test.go b/pkg/morph/timer/block_test.go index 93bb04de5e..7929754c12 100644 --- a/pkg/morph/timer/block_test.go +++ b/pkg/morph/timer/block_test.go @@ -208,7 +208,7 @@ func TestBlockTimer_TickSameHeight(t *testing.T) { require.NoError(t, bt.Reset()) check := func(t *testing.T, h uint32, base, delta int) { - for i := 0; i < 2*int(blockDur); i++ { + for range 2 * int(blockDur) { bt.Tick(h) require.Equal(t, base, baseCounter) require.Equal(t, delta, deltaCounter) diff --git a/pkg/network/tls_test.go b/pkg/network/tls_test.go index 6c352484b5..14729f4c2b 100644 --- a/pkg/network/tls_test.go +++ b/pkg/network/tls_test.go @@ -37,7 +37,7 @@ func BenchmarkAddressTLSEnabled(b *testing.B) { b.ReportAllocs() var enabled bool - for i := 0; i < b.N; i++ { + for range b.N { enabled = addr.IsTLSEnabled() } require.True(b, enabled) diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 0ba8be7655..300cb9dc9d 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -169,7 +169,7 @@ func (s *Server) getContainerNodes(contID cid.ID) ([]netmap.NodeInfo, error) { nodes := placement.FlattenNodes(ns) bs := (*keys.PublicKey)(&s.key.PublicKey).Bytes() - for i := 0; i < len(nodes); i++ { + for i := range len(nodes) { if bytes.Equal(nodes[i].PublicKey(), bs) { copy(nodes[i:], nodes[i+1:]) nodes = nodes[:len(nodes)-1] diff --git a/pkg/services/object/acl/v2/util_test.go b/pkg/services/object/acl/v2/util_test.go index 394feef4ef..4353396830 100644 --- a/pkg/services/object/acl/v2/util_test.go +++ b/pkg/services/object/acl/v2/util_test.go @@ -33,7 +33,7 @@ func TestOriginalTokens(t *testing.T) { var sTokenV2 session.Token sToken.WriteToV2(&sTokenV2) - for i := 0; i < 10; i++ { + for i := range 10 { metaHeaders := testGenerateMetaHeader(uint32(i), &bTokenV2, &sTokenV2) res, err := originalSessionToken(metaHeaders) require.NoError(t, err) diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 1fc6b7b20a..6827018dcf 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -470,7 +470,7 @@ func testNodeMatrix(t testing.TB, dim []int) ([][]netmap.NodeInfo, [][]string) { ns := make([]netmap.NodeInfo, dim[i]) as := make([]string, dim[i]) - for j := 0; j < dim[i]; j++ { + for j := range dim[i] { a := fmt.Sprintf("/ip4/192.168.0.%s/tcp/%s", strconv.Itoa(i), strconv.Itoa(60000+j), @@ -508,7 +508,7 @@ func generateChain(ln int, cnr cid.ID) ([]*objectSDK.Object, []oid.ID, []byte) { ids := make([]oid.ID, 0, ln) payload := make([]byte, 0, ln*10) - for i := 0; i < ln; i++ { + for i := range ln { ids = append(ids, curID) addr.SetObject(curID) @@ -1750,7 +1750,7 @@ func TestGetRange(t *testing.T) { }, }) - for from := 0; from < totalSize-1; from++ { + for from := range totalSize - 1 { for to := from; to < totalSize; to++ { t.Run(fmt.Sprintf("from=%d,to=%d", from, to), func(t *testing.T) { testGetRange(t, svc, addr, uint64(from), uint64(to), payload) @@ -1811,7 +1811,7 @@ func TestGetRange(t *testing.T) { }, }) - for from := 0; from < totalSize-1; from++ { + for from := range totalSize - 1 { for to := from; to < totalSize; to++ { t.Run(fmt.Sprintf("from=%d,to=%d", from, to), func(t *testing.T) { testGetRange(t, svc, addr, uint64(from), uint64(to), payload) diff --git a/pkg/services/object/get/getrangeec_test.go b/pkg/services/object/get/getrangeec_test.go index b8497d7d11..a6882d4a88 100644 --- a/pkg/services/object/get/getrangeec_test.go +++ b/pkg/services/object/get/getrangeec_test.go @@ -131,7 +131,7 @@ func TestGetRangeEC(t *testing.T) { clients: clients, }) - for from := 0; from < totalSize-1; from++ { + for from := range totalSize - 1 { for to := from; to < totalSize; to++ { t.Run(fmt.Sprintf("from=%d,to=%d", from, to), func(t *testing.T) { testGetRange(t, svc, addr, uint64(from), uint64(to), obj.Payload()) diff --git a/pkg/services/object/put/ec.go b/pkg/services/object/put/ec.go index 1fadf65fe3..9980f6d617 100644 --- a/pkg/services/object/put/ec.go +++ b/pkg/services/object/put/ec.go @@ -276,7 +276,7 @@ func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx } // try to save to any node not visited by current part - for i := 0; i < len(nodes); i++ { + for i := range len(nodes) { select { case <-ctx.Done(): return ctx.Err() diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 6793804029..44abcfe5b5 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -151,7 +151,7 @@ func testSHA256() (cs [sha256.Size]byte) { func generateIDs(num int) []oid.ID { res := make([]oid.ID, num) - for i := 0; i < num; i++ { + for i := range num { res[i].SetSHA256(testSHA256()) } @@ -232,7 +232,7 @@ func testNodeMatrix(t testing.TB, dim []int) ([][]netmap.NodeInfo, [][]string) { ns := make([]netmap.NodeInfo, dim[i]) as := make([]string, dim[i]) - for j := 0; j < dim[i]; j++ { + for j := range dim[i] { a := fmt.Sprintf("/ip4/192.168.0.%s/tcp/%s", strconv.Itoa(i), strconv.Itoa(60000+j), diff --git a/pkg/services/object_manager/placement/cache_test.go b/pkg/services/object_manager/placement/cache_test.go index 07e9340dcf..a890d53577 100644 --- a/pkg/services/object_manager/placement/cache_test.go +++ b/pkg/services/object_manager/placement/cache_test.go @@ -64,7 +64,7 @@ func TestContainerNodesCache(t *testing.T) { nm2 := nm(1, nodes[1:2]) cnr := [size * 2]cid.ID{} res := [size * 2][][]netmapSDK.NodeInfo{} - for i := 0; i < size*2; i++ { + for i := range size * 2 { cnr[i] = cidtest.ID() var err error @@ -77,7 +77,7 @@ func TestContainerNodesCache(t *testing.T) { require.NoError(t, err) require.Equal(t, res[i], r) } - for i := 0; i < size; i++ { + for i := range size { r, err := c.ContainerNodes(nm2, cnr[i], pp) require.NoError(t, err) require.NotEqual(t, res[i], r) diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 9a5877c527..4e790628fa 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -136,7 +136,7 @@ func defaultCopiesVector(policy netmap.PlacementPolicy) []int { replNum := policy.NumberOfReplicas() copyVector := make([]int, 0, replNum) - for i := 0; i < replNum; i++ { + for i := range replNum { copyVector = append(copyVector, int(policy.ReplicaDescriptor(i).NumberOfObjects()+policy.ReplicaDescriptor(i).GetECDataCount()+policy.ReplicaDescriptor(i).GetECParityCount())) } @@ -212,7 +212,7 @@ func (t *Traverser) Next() []Node { nodes := make([]Node, count) - for i := 0; i < count; i++ { + for i := range count { err := nodes[i].addresses.FromIterator(network.NodeEndpointsIterator(t.vectors[0][i])) if err != nil { return nil diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index f5731c81ef..b3b57677d9 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -48,7 +48,7 @@ func testPlacement(ss, rs []int) ([][]netmap.NodeInfo, container.Container) { for i := range ss { ns := make([]netmap.NodeInfo, 0, ss[i]) - for j := 0; j < ss[i]; j++ { + for range ss[i] { ns = append(ns, testNode(num)) num++ } @@ -125,7 +125,7 @@ func TestTraverserObjectScenarios(t *testing.T) { ) require.NoError(t, err) - for i := 0; i < len(nodes[0]); i++ { + for range len(nodes[0]) { require.NotNil(t, tr.Next()) } @@ -164,7 +164,7 @@ func TestTraverserObjectScenarios(t *testing.T) { require.Empty(t, tr.Next()) require.False(t, tr.Success()) - for i := 0; i < replicas[curVector]; i++ { + for range replicas[curVector] { tr.SubmitSuccess() } } diff --git a/pkg/services/session/storage/persistent/executor_test.go b/pkg/services/session/storage/persistent/executor_test.go index 39cb143595..124d36930b 100644 --- a/pkg/services/session/storage/persistent/executor_test.go +++ b/pkg/services/session/storage/persistent/executor_test.go @@ -39,7 +39,7 @@ func TestTokenStore(t *testing.T) { tokens := make([]tok, 0, tokenNumber) - for i := 0; i < tokenNumber; i++ { + for i := range tokenNumber { req.SetExpiration(uint64(i)) res, err := ts.Create(context.Background(), req) diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 677431889d..95bdda34b7 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -62,7 +62,7 @@ func TestGetSubTree(t *testing.T) { loop: for i := 1; i < len(acc.seen); i++ { parent := acc.seen[i].Body.ParentId - for j := 0; j < i; j++ { + for j := range i { if acc.seen[j].Body.NodeId[0] == parent[0] { continue loop } diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 346198b3c1..95c8f80134 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -133,7 +133,7 @@ func (s *Service) ReplicateTreeOp(ctx context.Context, n netmapSDK.NodeInfo, req } func (s *Service) replicateLoop(ctx context.Context) { - for i := 0; i < s.replicatorWorkerCount; i++ { + for range s.replicatorWorkerCount { go s.replicationWorker(ctx) go s.localReplicationWorker(ctx) } diff --git a/pkg/util/sync/key_locker_test.go b/pkg/util/sync/key_locker_test.go index 3b3e6a6944..259064ecf8 100644 --- a/pkg/util/sync/key_locker_test.go +++ b/pkg/util/sync/key_locker_test.go @@ -13,7 +13,7 @@ func TestKeyLocker(t *testing.T) { taken := false eg, _ := errgroup.WithContext(context.Background()) keyLocker := NewKeyLocker[int]() - for i := 0; i < 100; i++ { + for range 100 { eg.Go(func() error { keyLocker.Lock(0) defer keyLocker.Unlock(0) From a4fb7f085b4cd2c5d7bb2ec91e6e626238dead54 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 3 Sep 2024 11:39:02 +0300 Subject: [PATCH 0776/1413] [#1348] go.mod: Update api-go and sdk-go Signed-off-by: Aleksey Savchuk --- cmd/frostfs-cli/internal/client/client.go | 26 ----- cmd/frostfs-cli/modules/container/get_eacl.go | 68 ------------- cmd/frostfs-cli/modules/container/root.go | 2 - cmd/frostfs-cli/modules/util/ape.go | 6 -- go.mod | 4 +- go.sum | 8 +- .../transport/container/grpc/service.go | 15 --- pkg/services/container/ape.go | 12 --- pkg/services/container/ape_test.go | 95 ------------------- pkg/services/container/audit.go | 11 --- pkg/services/container/executor.go | 14 --- pkg/services/container/morph/executor.go | 37 -------- pkg/services/container/server.go | 1 - pkg/services/container/sign.go | 9 -- 14 files changed, 6 insertions(+), 302 deletions(-) delete mode 100644 cmd/frostfs-cli/modules/container/get_eacl.go diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 57bcf5620c..03a987a57d 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -17,7 +17,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -192,31 +191,6 @@ func DeleteContainer(ctx context.Context, prm DeleteContainerPrm) (res DeleteCon return } -// EACLPrm groups parameters of EACL operation. -type EACLPrm struct { - Client *client.Client - ClientParams client.PrmContainerEACL -} - -// EACLRes groups the resulting values of EACL operation. -type EACLRes struct { - cliRes *client.ResContainerEACL -} - -// EACL returns requested eACL table. -func (x EACLRes) EACL() eacl.Table { - return x.cliRes.Table() -} - -// EACL reads eACL table from FrostFS by container ID. -// -// Returns any error which prevented the operation from completing correctly in error return. -func EACL(ctx context.Context, prm EACLPrm) (res EACLRes, err error) { - res.cliRes, err = prm.Client.ContainerEACL(ctx, prm.ClientParams) - - return -} - // NetworkInfoPrm groups parameters of NetworkInfo operation. type NetworkInfoPrm struct { Client *client.Client diff --git a/cmd/frostfs-cli/modules/container/get_eacl.go b/cmd/frostfs-cli/modules/container/get_eacl.go deleted file mode 100644 index 4ed1c82e1c..0000000000 --- a/cmd/frostfs-cli/modules/container/get_eacl.go +++ /dev/null @@ -1,68 +0,0 @@ -package container - -import ( - "os" - - internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" - commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - "github.com/spf13/cobra" -) - -var getExtendedACLCmd = &cobra.Command{ - Use: "get-eacl", - Short: "Get extended ACL table of container", - Long: `Get extended ACL table of container`, - Run: func(cmd *cobra.Command, _ []string) { - id := parseContainerID(cmd) - pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) - - eaclPrm := internalclient.EACLPrm{ - Client: cli, - ClientParams: client.PrmContainerEACL{ - ContainerID: &id, - }, - } - - res, err := internalclient.EACL(cmd.Context(), eaclPrm) - commonCmd.ExitOnErr(cmd, "rpc error: %w", err) - - eaclTable := res.EACL() - - if containerPathTo == "" { - cmd.Println("eACL: ") - common.PrettyPrintJSON(cmd, &eaclTable, "eACL") - - return - } - - var data []byte - - if containerJSON { - data, err = eaclTable.MarshalJSON() - commonCmd.ExitOnErr(cmd, "can't encode to JSON: %w", err) - } else { - data, err = eaclTable.Marshal() - commonCmd.ExitOnErr(cmd, "can't encode to binary: %w", err) - } - - cmd.Println("dumping data to file:", containerPathTo) - - err = os.WriteFile(containerPathTo, data, 0o644) - commonCmd.ExitOnErr(cmd, "could not write eACL to file: %w", err) - }, -} - -func initContainerGetEACLCmd() { - commonflags.Init(getExtendedACLCmd) - - flags := getExtendedACLCmd.Flags() - - flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage) - flags.StringVar(&containerPathTo, "to", "", "Path to dump encoded container (default: binary encoded)") - flags.BoolVar(&containerJSON, commonflags.JSON, false, "Encode EACL table in json format") -} diff --git a/cmd/frostfs-cli/modules/container/root.go b/cmd/frostfs-cli/modules/container/root.go index d5f0fd776e..2da21e767d 100644 --- a/cmd/frostfs-cli/modules/container/root.go +++ b/cmd/frostfs-cli/modules/container/root.go @@ -25,7 +25,6 @@ func init() { deleteContainerCmd, listContainerObjectsCmd, getContainerInfoCmd, - getExtendedACLCmd, containerNodesCmd, policyPlaygroundCmd, } @@ -37,7 +36,6 @@ func init() { initContainerDeleteCmd() initContainerListObjectsCmd() initContainerInfoCmd() - initContainerGetEACLCmd() initContainerNodesCmd() initContainerPolicyPlaygroundCmd() diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 9af57434ab..73c3685103 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -258,10 +258,6 @@ func parseAction(lexeme string) ([]string, bool, error) { return []string{nativeschema.MethodDeleteContainer}, false, nil case "container.get": return []string{nativeschema.MethodGetContainer}, false, nil - case "container.setcontainereacl": - return []string{nativeschema.MethodSetContainerEACL}, false, nil - case "container.getcontainereacl": - return []string{nativeschema.MethodGetContainerEACL}, false, nil case "container.list": return []string{nativeschema.MethodListContainers}, false, nil case "container.*": @@ -269,8 +265,6 @@ func parseAction(lexeme string) ([]string, bool, error) { nativeschema.MethodPutContainer, nativeschema.MethodDeleteContainer, nativeschema.MethodGetContainer, - nativeschema.MethodSetContainerEACL, - nativeschema.MethodGetContainerEACL, nativeschema.MethodListContainers, }, false, nil default: diff --git a/go.mod b/go.mod index 358370201e..19bf7852fe 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240828085308-5e1c6a908f61 + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240902111049-c11f50efeccb git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240827083309-f0b9493ce3f7 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index be82bff70b..8ebd59157b 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240828085308-5e1c6a908f61 h1:bw9EVGWnfY9awFb5XYR52AGbzgg3o04gZF66yHob48c= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240828085308-5e1c6a908f61/go.mod h1:BDnEpkKMykCS8u1nLzR6SgNzCv6885RWlo5TnravQuI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240902111049-c11f50efeccb h1:p9ByDsw+H6p6LyYSx8LKFtAG/oPKQpDVMNfjPqdevTw= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240902111049-c11f50efeccb/go.mod h1:BDnEpkKMykCS8u1nLzR6SgNzCv6885RWlo5TnravQuI= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240827083309-f0b9493ce3f7 h1:9eZidZMT4tHOdc6GZRPlZR12IToKqHhUd5wzevdDUqo= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240827083309-f0b9493ce3f7/go.mod h1:VzVYcwo/eXjkdo5ktPdZeAE4fsnZX6zEun3g+5E2weo= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad h1:cJGK/bXSF/0KMr6zkIy06qekQhQRU7eYzh+lWdQ0U8w= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad/go.mod h1:I4GzeEnftO++N2JHQn9QR88eV0rjQkGqlUCNMnCz1CY= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= diff --git a/pkg/network/transport/container/grpc/service.go b/pkg/network/transport/container/grpc/service.go index f0206dd5c4..9fae22b45a 100644 --- a/pkg/network/transport/container/grpc/service.go +++ b/pkg/network/transport/container/grpc/service.go @@ -80,18 +80,3 @@ func (s *Server) List(ctx context.Context, req *containerGRPC.ListRequest) (*con return resp.ToGRPCMessage().(*containerGRPC.ListResponse), nil } - -// GetExtendedACL converts gRPC GetExtendedACLRequest message and passes it to internal Container service. -func (s *Server) GetExtendedACL(ctx context.Context, req *containerGRPC.GetExtendedACLRequest) (*containerGRPC.GetExtendedACLResponse, error) { - getEACLReq := new(container.GetExtendedACLRequest) - if err := getEACLReq.FromGRPCMessage(req); err != nil { - return nil, err - } - - resp, err := s.srv.GetExtendedACL(ctx, getEACLReq) - if err != nil { - return nil, err - } - - return resp.ToGRPCMessage().(*containerGRPC.GetExtendedACLResponse), nil -} diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 6f8a8e0e63..d92ecf58b1 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -102,18 +102,6 @@ func (ac *apeChecker) Get(ctx context.Context, req *container.GetRequest) (*cont return ac.next.Get(ctx, req) } -func (ac *apeChecker) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { - ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.GetExtendedACL") - defer span.End() - - if err := ac.validateContainerBoundedOperation(ctx, req.GetBody().GetContainerID(), req.GetMetaHeader(), req.GetVerificationHeader(), - nativeschema.MethodGetContainerEACL); err != nil { - return nil, err - } - - return ac.next.GetExtendedACL(ctx, req) -} - func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) { ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.List") defer span.End() diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 68c1158a64..d6f9b75ef2 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -49,7 +49,6 @@ func TestAPE(t *testing.T) { t.Run("deny get container by user claim tag", testDenyGetContainerByUserClaimTag) t.Run("deny get container by IP", testDenyGetContainerByIP) t.Run("deny get container by group id", testDenyGetContainerByGroupID) - t.Run("deny get container eACL for IR with session token", testDenyGetContainerEACLForIRSessionToken) t.Run("deny put container for others with session token", testDenyPutContainerForOthersSessionToken) t.Run("deny put container, read namespace from frostfsID", testDenyPutContainerReadNamespaceFromFrostfsID) t.Run("deny put container with invlaid namespace", testDenyPutContainerInvalidNamespace) @@ -663,95 +662,6 @@ func testDenyGetContainerByGroupID(t *testing.T) { require.ErrorAs(t, err, &errAccessDenied) } -func testDenyGetContainerEACLForIRSessionToken(t *testing.T) { - t.Parallel() - srv := &srvStub{ - calls: map[string]int{}, - } - router := inmemory.NewInMemory() - contRdr := &containerStub{ - c: map[cid.ID]*containercore.Container{}, - } - ir := &irStub{ - keys: [][]byte{}, - } - nm := &netmapStub{} - frostfsIDSubjectReader := &frostfsidStub{ - subjects: map[util.Uint160]*client.Subject{}, - } - apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) - - contID := cidtest.ID() - testContainer := containertest.Container() - pp := netmap.PlacementPolicy{} - require.NoError(t, pp.DecodeString("REP 1")) - testContainer.SetPlacementPolicy(pp) - contRdr.c[contID] = &containercore.Container{Value: testContainer} - - nm.currentEpoch = 100 - nm.netmaps = map[uint64]*netmap.NetMap{} - var testNetmap netmap.NetMap - testNetmap.SetEpoch(nm.currentEpoch) - testNetmap.SetNodes([]netmap.NodeInfo{{}}) - nm.netmaps[nm.currentEpoch] = &testNetmap - nm.netmaps[nm.currentEpoch-1] = &testNetmap - - _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ - Rules: []chain.Rule{ - { - Status: chain.AccessDenied, - Actions: chain.Actions{ - Names: []string{ - nativeschema.MethodGetContainerEACL, - }, - }, - Resources: chain.Resources{ - Names: []string{ - fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), - }, - }, - Condition: []chain.Condition{ - { - Kind: chain.KindRequest, - Key: nativeschema.PropertyKeyActorRole, - Value: nativeschema.PropertyValueContainerRoleIR, - Op: chain.CondStringEquals, - }, - }, - }, - }, - }) - require.NoError(t, err) - - req := &container.GetExtendedACLRequest{} - req.SetBody(&container.GetExtendedACLRequestBody{}) - var refContID refs.ContainerID - contID.WriteToV2(&refContID) - req.GetBody().SetContainerID(&refContID) - - pk, err := keys.NewPrivateKey() - require.NoError(t, err) - require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) - - sessionPK, err := keys.NewPrivateKey() - require.NoError(t, err) - sToken := sessiontest.ContainerSigned() - sToken.ApplyOnlyTo(contID) - require.NoError(t, sToken.Sign(sessionPK.PrivateKey)) - var sTokenV2 session.Token - sToken.WriteToV2(&sTokenV2) - metaHeader := new(session.RequestMetaHeader) - metaHeader.SetSessionToken(&sTokenV2) - req.SetMetaHeader(metaHeader) - - ir.keys = append(ir.keys, sessionPK.PublicKey().Bytes()) - - resp, err := apeSrv.GetExtendedACL(context.Background(), req) - require.Nil(t, resp) - var errAccessDenied *apistatus.ObjectAccessDenied - require.ErrorAs(t, err, &errAccessDenied) -} - func testDenyPutContainerForOthersSessionToken(t *testing.T) { t.Parallel() srv := &srvStub{ @@ -1164,11 +1074,6 @@ func (s *srvStub) Get(context.Context, *container.GetRequest) (*container.GetRes return &container.GetResponse{}, nil } -func (s *srvStub) GetExtendedACL(context.Context, *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { - s.calls["GetExtendedACL"]++ - return &container.GetExtendedACLResponse{}, nil -} - func (s *srvStub) List(context.Context, *container.ListRequest) (*container.ListResponse, error) { s.calls["List"]++ return &container.ListResponse{}, nil diff --git a/pkg/services/container/audit.go b/pkg/services/container/audit.go index 34fd5923fa..b257272f52 100644 --- a/pkg/services/container/audit.go +++ b/pkg/services/container/audit.go @@ -52,17 +52,6 @@ func (a *auditService) Get(ctx context.Context, req *container.GetRequest) (*con return res, err } -// GetExtendedACL implements Server. -func (a *auditService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { - res, err := a.next.GetExtendedACL(ctx, req) - if !a.enabled.Load() { - return res, err - } - audit.LogRequest(a.log, container_grpc.ContainerService_GetExtendedACL_FullMethodName, req, - audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil) - return res, err -} - // List implements Server. func (a *auditService) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) { res, err := a.next.List(ctx, req) diff --git a/pkg/services/container/executor.go b/pkg/services/container/executor.go index b64963e25b..0917e3bd08 100644 --- a/pkg/services/container/executor.go +++ b/pkg/services/container/executor.go @@ -14,7 +14,6 @@ type ServiceExecutor interface { Delete(context.Context, *session.Token, *container.DeleteRequestBody) (*container.DeleteResponseBody, error) Get(context.Context, *container.GetRequestBody) (*container.GetResponseBody, error) List(context.Context, *container.ListRequestBody) (*container.ListResponseBody, error) - GetExtendedACL(context.Context, *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) } type executorSvc struct { @@ -94,16 +93,3 @@ func (s *executorSvc) List(ctx context.Context, req *container.ListRequest) (*co s.respSvc.SetMeta(resp) return resp, nil } - -func (s *executorSvc) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { - respBody, err := s.exec.GetExtendedACL(ctx, req.GetBody()) - if err != nil { - return nil, fmt.Errorf("could not execute GetEACL request: %w", err) - } - - resp := new(container.GetExtendedACLResponse) - resp.SetBody(respBody) - - s.respSvc.SetMeta(resp) - return resp, nil -} diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index 57dac32f04..05d8749cf8 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -201,40 +201,3 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) return res, nil } - -func (s *morphExecutor) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) { - idV2 := body.GetContainerID() - if idV2 == nil { - return nil, errors.New("missing container ID") - } - - var id cid.ID - - err := id.ReadFromV2(*idV2) - if err != nil { - return nil, fmt.Errorf("invalid container ID: %w", err) - } - - eaclInfo, err := s.rdr.GetEACL(id) - if err != nil { - return nil, err - } - - var sigV2 refs.Signature - eaclInfo.Signature.WriteToV2(&sigV2) - - var tokV2 *sessionV2.Token - - if eaclInfo.Session != nil { - tokV2 = new(sessionV2.Token) - - eaclInfo.Session.WriteToV2(tokV2) - } - - res := new(container.GetExtendedACLResponseBody) - res.SetEACL(eaclInfo.Value.ToV2()) - res.SetSignature(&sigV2) - res.SetSessionToken(tokV2) - - return res, nil -} diff --git a/pkg/services/container/server.go b/pkg/services/container/server.go index d714d7f029..a19d83c565 100644 --- a/pkg/services/container/server.go +++ b/pkg/services/container/server.go @@ -12,5 +12,4 @@ type Server interface { Get(context.Context, *container.GetRequest) (*container.GetResponse, error) Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error) List(context.Context, *container.ListRequest) (*container.ListResponse, error) - GetExtendedACL(context.Context, *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) } diff --git a/pkg/services/container/sign.go b/pkg/services/container/sign.go index 62aa3fe27f..f7f5d6486e 100644 --- a/pkg/services/container/sign.go +++ b/pkg/services/container/sign.go @@ -56,12 +56,3 @@ func (s *signService) List(ctx context.Context, req *container.ListRequest) (*co resp, err := util.EnsureNonNilResponse(s.svc.List(ctx, req)) return resp, s.sigSvc.SignResponse(resp, err) } - -func (s *signService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) { - if err := s.sigSvc.VerifyRequest(req); err != nil { - resp := new(container.GetExtendedACLResponse) - return resp, s.sigSvc.SignResponse(resp, err) - } - resp, err := util.EnsureNonNilResponse(s.svc.GetExtendedACL(ctx, req)) - return resp, s.sigSvc.SignResponse(resp, err) -} From b9043433a098ae242c559a79afe6f1ced5068e68 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 15 Jul 2024 14:07:32 +0300 Subject: [PATCH 0777/1413] [#1223] scripts: Add script to populate metabase Signed-off-by: Aleksey Savchuk --- .../populate-metabase/internal/generate.go | 132 +++++++++ .../populate-metabase/internal/populate.go | 263 ++++++++++++++++++ scripts/populate-metabase/main.go | 159 +++++++++++ 3 files changed, 554 insertions(+) create mode 100644 scripts/populate-metabase/internal/generate.go create mode 100644 scripts/populate-metabase/internal/populate.go create mode 100644 scripts/populate-metabase/main.go diff --git a/scripts/populate-metabase/internal/generate.go b/scripts/populate-metabase/internal/generate.go new file mode 100644 index 0000000000..d2004b6734 --- /dev/null +++ b/scripts/populate-metabase/internal/generate.go @@ -0,0 +1,132 @@ +package internal + +import ( + "crypto/sha256" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/tzhash/tz" + "golang.org/x/exp/rand" +) + +func GeneratePayloadPool(count uint, size uint) [][]byte { + pool := [][]byte{} + for i := uint(0); i < count; i++ { + payload := make([]byte, size) + _, _ = rand.Read(payload) + + pool = append(pool, payload) + } + return pool +} + +func GenerateAttributePool(count uint) []objectSDK.Attribute { + pool := []objectSDK.Attribute{} + for i := uint(0); i < count; i++ { + for j := uint(0); j < count; j++ { + attr := *objectSDK.NewAttribute() + attr.SetKey(fmt.Sprintf("key%d", i)) + attr.SetValue(fmt.Sprintf("value%d", j)) + pool = append(pool, attr) + } + } + return pool +} + +func GenerateOwnerPool(count uint) []user.ID { + pool := []user.ID{} + for i := uint(0); i < count; i++ { + pool = append(pool, usertest.ID()) + } + return pool +} + +type ObjectOption func(obj *objectSDK.Object) + +func GenerateObject(options ...ObjectOption) *objectSDK.Object { + var ver version.Version + ver.SetMajor(2) + ver.SetMinor(1) + + payload := make([]byte, 0) + + var csum checksum.Checksum + csum.SetSHA256(sha256.Sum256(payload)) + + var csumTZ checksum.Checksum + csumTZ.SetTillichZemor(tz.Sum(csum.Value())) + + obj := objectSDK.New() + obj.SetID(oidtest.ID()) + obj.SetOwnerID(usertest.ID()) + obj.SetContainerID(cidtest.ID()) + + header := objecttest.Object().GetECHeader() + header.SetParent(oidtest.ID()) + obj.SetECHeader(header) + + obj.SetVersion(&ver) + obj.SetPayload(payload) + obj.SetPayloadSize(uint64(len(payload))) + obj.SetPayloadChecksum(csum) + obj.SetPayloadHomomorphicHash(csumTZ) + + for _, option := range options { + option(obj) + } + + return obj +} + +func WithContainerID(cid cid.ID) ObjectOption { + return func(obj *objectSDK.Object) { + obj.SetContainerID(cid) + } +} + +func WithType(typ objectSDK.Type) ObjectOption { + return func(obj *objectSDK.Object) { + obj.SetType(typ) + } +} + +func WithPayloadFromPool(pool [][]byte) ObjectOption { + payload := pool[rand.Intn(len(pool))] + + var csum checksum.Checksum + csum.SetSHA256(sha256.Sum256(payload)) + + var csumTZ checksum.Checksum + csumTZ.SetTillichZemor(tz.Sum(csum.Value())) + + return func(obj *objectSDK.Object) { + obj.SetPayload(payload) + obj.SetPayloadSize(uint64(len(payload))) + obj.SetPayloadChecksum(csum) + obj.SetPayloadHomomorphicHash(csumTZ) + } +} + +func WithAttributesFromPool(pool []objectSDK.Attribute, count uint) ObjectOption { + return func(obj *objectSDK.Object) { + attrs := []objectSDK.Attribute{} + for i := uint(0); i < count; i++ { + attrs = append(attrs, pool[rand.Intn(len(pool))]) + } + obj.SetAttributes(attrs...) + } +} + +func WithOwnerIDFromPool(pool []user.ID) ObjectOption { + return func(obj *objectSDK.Object) { + obj.SetOwnerID(pool[rand.Intn(len(pool))]) + } +} diff --git a/scripts/populate-metabase/internal/populate.go b/scripts/populate-metabase/internal/populate.go new file mode 100644 index 0000000000..390c1cdc07 --- /dev/null +++ b/scripts/populate-metabase/internal/populate.go @@ -0,0 +1,263 @@ +package internal + +import ( + "context" + "fmt" + "math/rand" + "sync" + + meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "golang.org/x/sync/errgroup" +) + +type EpochState struct{} + +func (s EpochState) CurrentEpoch() uint64 { + return 0 +} + +func PopulateWithObjects( + ctx context.Context, + db *meta.DB, + group *errgroup.Group, + count uint, + factory func() *objectSDK.Object, +) { + digits := "0123456789" + + for i := uint(0); i < count; i++ { + obj := factory() + + id := []byte(fmt.Sprintf( + "%c/%c/%c", + digits[rand.Int()%len(digits)], + digits[rand.Int()%len(digits)], + digits[rand.Int()%len(digits)], + )) + + prm := meta.PutPrm{} + prm.SetObject(obj) + prm.SetStorageID(id) + + group.Go(func() error { + if _, err := db.Put(ctx, prm); err != nil { + return fmt.Errorf("couldn't put an object: %w", err) + } + return nil + }) + } +} + +func PopulateWithBigObjects( + ctx context.Context, + db *meta.DB, + group *errgroup.Group, + count uint, + factory func() *objectSDK.Object, +) { + for i := uint(0); i < count; i++ { + group.Go(func() error { + if err := populateWithBigObject(ctx, db, factory); err != nil { + return fmt.Errorf("couldn't put a big object: %w", err) + } + return nil + }) + } +} + +func populateWithBigObject( + ctx context.Context, + db *meta.DB, + factory func() *objectSDK.Object, +) error { + t := &target{db: db} + + pk, _ := keys.NewPrivateKey() + p := transformer.NewPayloadSizeLimiter(transformer.Params{ + Key: &pk.PrivateKey, + NextTargetInit: func() transformer.ObjectWriter { return t }, + NetworkState: EpochState{}, + MaxSize: 10, + }) + + obj := factory() + payload := make([]byte, 30) + + err := p.WriteHeader(ctx, obj) + if err != nil { + return err + } + + _, err = p.Write(ctx, payload) + if err != nil { + return err + } + + _, err = p.Close(ctx) + if err != nil { + return err + } + + return nil +} + +type target struct { + db *meta.DB +} + +func (t *target) WriteObject(ctx context.Context, obj *objectSDK.Object) error { + prm := meta.PutPrm{} + prm.SetObject(obj) + + _, err := t.db.Put(ctx, prm) + return err +} + +func PopulateGraveyard( + ctx context.Context, + db *meta.DB, + group *errgroup.Group, + workBufferSize int, + count uint, + factory func() *objectSDK.Object, +) { + ts := factory() + ts.SetType(objectSDK.TypeTombstone) + + prm := meta.PutPrm{} + prm.SetObject(ts) + + group.Go(func() error { + if _, err := db.Put(ctx, prm); err != nil { + return fmt.Errorf("couldn't put a tombstone object: %w", err) + } + return nil + }) + + cID, _ := ts.ContainerID() + oID, _ := ts.ID() + + var tsAddr oid.Address + + tsAddr.SetContainer(cID) + tsAddr.SetObject(oID) + + addrs := make(chan oid.Address, workBufferSize) + + go func() { + defer close(addrs) + + wg := &sync.WaitGroup{} + wg.Add(int(count)) + + for i := uint(0); i < count; i++ { + obj := factory() + + prm := meta.PutPrm{} + prm.SetObject(obj) + + group.Go(func() error { + defer wg.Done() + + if _, err := db.Put(ctx, prm); err != nil { + return fmt.Errorf("couldn't put an object: %w", err) + } + + cID, _ := obj.ContainerID() + oID, _ := obj.ID() + + var addr oid.Address + addr.SetContainer(cID) + addr.SetObject(oID) + + addrs <- addr + return nil + }) + } + wg.Wait() + }() + + go func() { + for addr := range addrs { + prm := meta.InhumePrm{} + prm.SetAddresses(addr) + prm.SetTombstoneAddress(tsAddr) + + group.Go(func() error { + if _, err := db.Inhume(ctx, prm); err != nil { + return fmt.Errorf("couldn't inhume an object: %w", err) + } + return nil + }) + } + }() +} + +func PopulateLocked( + ctx context.Context, + db *meta.DB, + group *errgroup.Group, + workBufferSize int, + count uint, + factory func() *objectSDK.Object, +) { + locker := factory() + locker.SetType(objectSDK.TypeLock) + + prm := meta.PutPrm{} + prm.SetObject(locker) + + group.Go(func() error { + if _, err := db.Put(ctx, prm); err != nil { + return fmt.Errorf("couldn't put a locker object: %w", err) + } + return nil + }) + + ids := make(chan oid.ID, workBufferSize) + + go func() { + defer close(ids) + + wg := &sync.WaitGroup{} + wg.Add(int(count)) + + for i := uint(0); i < count; i++ { + defer wg.Done() + + obj := factory() + + prm := meta.PutPrm{} + prm.SetObject(obj) + + group.Go(func() error { + if _, err := db.Put(ctx, prm); err != nil { + return fmt.Errorf("couldn't put an object: %w", err) + } + + id, _ := obj.ID() + ids <- id + return nil + }) + } + wg.Wait() + }() + + go func() { + for id := range ids { + lockerCID, _ := locker.ContainerID() + lockerOID, _ := locker.ID() + + group.Go(func() error { + if err := db.Lock(ctx, lockerCID, lockerOID, []oid.ID{id}); err != nil { + return fmt.Errorf("couldn't lock an object: %w", err) + } + return nil + }) + } + }() +} diff --git a/scripts/populate-metabase/main.go b/scripts/populate-metabase/main.go new file mode 100644 index 0000000000..2bc7a5553f --- /dev/null +++ b/scripts/populate-metabase/main.go @@ -0,0 +1,159 @@ +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "os" + + meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "git.frostfs.info/TrueCloudLab/frostfs-node/scripts/populate-metabase/internal" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "golang.org/x/sync/errgroup" +) + +var ( + path string + force bool + jobs uint + + numContainers, + numObjects, + numAttributesPerObj, + numOwners, + numPayloads, + numAttributes uint +) + +func main() { + flag.StringVar(&path, "path", "", "Path to metabase") + flag.BoolVar(&force, "force", false, "Rewrite existing database") + flag.UintVar(&jobs, "j", 10000, "Number of jobs to run") + + flag.UintVar(&numContainers, "containers", 0, "Number of containers to be created") + flag.UintVar(&numObjects, "objects", 0, "Number of objects per container") + flag.UintVar(&numAttributesPerObj, "attributes", 0, "Number of attributes per object") + + flag.UintVar(&numOwners, "distinct-owners", 10, "Number of distinct owners to be used") + flag.UintVar(&numPayloads, "distinct-payloads", 10, "Number of distinct payloads to be used") + flag.UintVar(&numAttributes, "distinct-attributes", 10, "Number of distinct attributes to be used") + + flag.Parse() + + exitIf(numPayloads == 0, "must have payloads\n") + exitIf(numAttributes == 0, "must have attributes\n") + exitIf(numOwners == 0, "must have owners\n") + exitIf(len(path) == 0, "path to metabase not specified\n") + exitIf( + numAttributesPerObj > numAttributes, + "object can't have more attributes than available\n", + ) + + info, err := os.Stat(path) + exitIf( + err != nil && !errors.Is(err, os.ErrNotExist), + "couldn't get path info: %s\n", err, + ) + + // Path exits. + if err == nil { + exitIf(info.IsDir(), "path is a directory\n") + exitIf(!force, "couldn't rewrite existing file, use '-force' flag\n") + + err = os.Remove(path) + exitIf(err != nil, "couldn't remove existing file: %s\n", err) + } + + err = populate() + exitIf(err != nil, "couldn't populate the metabase: %s\n", err) +} + +func getObjectFactory(opts ...internal.ObjectOption) func() *objectSDK.Object { + return func() *objectSDK.Object { + return internal.GenerateObject(opts...) + } +} + +func populate() (err error) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + db := meta.New([]meta.Option{ + meta.WithPath(path), + meta.WithPermissions(0o600), + meta.WithEpochState(internal.EpochState{}), + }...) + + if err = db.Open(ctx, mode.ReadWrite); err != nil { + return fmt.Errorf("couldn't open the metabase: %w", err) + } + defer func() { + if errOnClose := db.Close(); errOnClose != nil { + err = errors.Join( + err, + fmt.Errorf("couldn't close the metabase: %w", db.Close()), + ) + } + }() + + if err = db.Init(); err != nil { + return fmt.Errorf("couldn't init the metabase: %w", err) + } + + payloads := internal.GeneratePayloadPool(numPayloads, 32) + attributes := internal.GenerateAttributePool(numAttributes) + owners := internal.GenerateOwnerPool(numOwners) + + types := []objectSDK.Type{ + objectSDK.TypeRegular, + objectSDK.TypeLock, + objectSDK.TypeTombstone, + } + + eg, ctx := errgroup.WithContext(ctx) + eg.SetLimit(int(jobs)) + + for i := uint(0); i < numContainers; i++ { + cid := cidtest.ID() + + for _, typ := range types { + internal.PopulateWithObjects(ctx, db, eg, numObjects, getObjectFactory( + internal.WithContainerID(cid), + internal.WithType(typ), + internal.WithPayloadFromPool(payloads), + internal.WithOwnerIDFromPool(owners), + internal.WithAttributesFromPool(attributes, numAttributesPerObj), + )) + } + internal.PopulateWithBigObjects(ctx, db, eg, numObjects, getObjectFactory( + internal.WithContainerID(cid), + internal.WithType(objectSDK.TypeRegular), + internal.WithAttributesFromPool(attributes, numAttributesPerObj), + internal.WithOwnerIDFromPool(owners), + )) + internal.PopulateGraveyard(ctx, db, eg, int(jobs), numObjects, getObjectFactory( + internal.WithContainerID(cid), + internal.WithType(objectSDK.TypeRegular), + internal.WithAttributesFromPool(attributes, numAttributesPerObj), + internal.WithOwnerIDFromPool(owners), + )) + internal.PopulateLocked(ctx, db, eg, int(jobs), numObjects, getObjectFactory( + internal.WithContainerID(cid), + internal.WithType(objectSDK.TypeRegular), + internal.WithAttributesFromPool(attributes, numAttributesPerObj), + internal.WithOwnerIDFromPool(owners), + )) + } + + return eg.Wait() +} + +func exitIf(cond bool, format string, args ...any) { + if cond { + fmt.Fprintf(os.Stderr, format, args...) + os.Exit(1) + } +} From 1ae86f35a8d95a3f2258eaefb772482d0af873f6 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 18 Jul 2024 18:26:11 +0300 Subject: [PATCH 0778/1413] [#1223] lens/tui: Add metabase schema Signed-off-by: Aleksey Savchuk --- .../internal/schema/common/format.go | 43 +++ .../internal/schema/common/raw.go | 29 ++ .../internal/schema/common/schema.go | 81 ++++++ .../schema/metabase/buckets/detailed.go | 29 ++ .../schema/metabase/buckets/filter.go | 81 ++++++ .../schema/metabase/buckets/parsers.go | 111 ++++++++ .../schema/metabase/buckets/prefix.go | 53 ++++ .../schema/metabase/buckets/string.go | 48 ++++ .../internal/schema/metabase/buckets/types.go | 166 ++++++++++++ .../internal/schema/metabase/parser.go | 29 ++ .../schema/metabase/records/detailed.go | 65 +++++ .../schema/metabase/records/filter.go | 145 ++++++++++ .../schema/metabase/records/parsers.go | 251 ++++++++++++++++++ .../schema/metabase/records/string.go | 135 ++++++++++ .../internal/schema/metabase/records/types.go | 82 ++++++ .../internal/schema/metabase/records/util.go | 20 ++ go.mod | 5 +- go.sum | 9 + 18 files changed, 1381 insertions(+), 1 deletion(-) create mode 100644 cmd/frostfs-lens/internal/schema/common/format.go create mode 100644 cmd/frostfs-lens/internal/schema/common/raw.go create mode 100644 cmd/frostfs-lens/internal/schema/common/schema.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/buckets/detailed.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/buckets/filter.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/buckets/parsers.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/buckets/prefix.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/buckets/string.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/buckets/types.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/parser.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/records/detailed.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/records/filter.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/records/parsers.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/records/string.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/records/types.go create mode 100644 cmd/frostfs-lens/internal/schema/metabase/records/util.go diff --git a/cmd/frostfs-lens/internal/schema/common/format.go b/cmd/frostfs-lens/internal/schema/common/format.go new file mode 100644 index 0000000000..4ed7e96f2f --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/common/format.go @@ -0,0 +1,43 @@ +package common + +import ( + "fmt" + "strconv" + + "github.com/gdamore/tcell/v2" +) + +type FormatOptions struct { + Color tcell.Color + + Bold, + Italic, + Underline, + StrikeThrough bool +} + +func Format(s string, opts FormatOptions) string { + var boldTag, italicTag, underlineTag, strikeThroughTag string + + switch { + case opts.Bold: + boldTag = "b" + case opts.Italic: + italicTag = "i" + case opts.Underline: + underlineTag = "u" + case opts.StrikeThrough: + strikeThroughTag = "s" + } + + attrs := fmt.Sprintf( + "%s%s%s%s", boldTag, italicTag, underlineTag, strikeThroughTag, + ) + color := strconv.FormatInt(int64(opts.Color.Hex()), 16) + + return fmt.Sprintf("[#%06s::%s]%s[-::-]", color, attrs, s) +} + +func FormatSimple(s string, c tcell.Color) string { + return Format(s, FormatOptions{Color: c}) +} diff --git a/cmd/frostfs-lens/internal/schema/common/raw.go b/cmd/frostfs-lens/internal/schema/common/raw.go new file mode 100644 index 0000000000..0990e24c34 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/common/raw.go @@ -0,0 +1,29 @@ +package common + +import ( + "github.com/davecgh/go-spew/spew" + "github.com/gdamore/tcell/v2" + "github.com/mr-tron/base58" +) + +type RawEntry struct { + key, value []byte +} + +var RawParser Parser = rawParser + +func rawParser(key, value []byte) (SchemaEntry, Parser, error) { + return &RawEntry{key: key, value: value}, rawParser, nil +} + +func (r *RawEntry) String() string { + return FormatSimple(base58.Encode(r.key), tcell.ColorRed) +} + +func (r *RawEntry) DetailedString() string { + return spew.Sdump(r) +} + +func (r *RawEntry) Filter(string, any) FilterResult { + return No +} diff --git a/cmd/frostfs-lens/internal/schema/common/schema.go b/cmd/frostfs-lens/internal/schema/common/schema.go new file mode 100644 index 0000000000..9bad190320 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/common/schema.go @@ -0,0 +1,81 @@ +package common + +import ( + "errors" + "fmt" +) + +type FilterResult byte + +const ( + No FilterResult = iota + Maybe + Yes +) + +func IfThenElse(condition bool, onSuccess, onFailure FilterResult) FilterResult { + var res FilterResult + if condition { + res = onSuccess + } else { + res = onFailure + } + return res +} + +type SchemaEntry interface { + String() string + DetailedString() string + Filter(typ string, val any) FilterResult +} + +type ( + Parser func(key, value []byte) (SchemaEntry, Parser, error) + FallbackParser func(key, value []byte) (SchemaEntry, Parser) +) + +func Any(parsers ...Parser) Parser { + return func(key, value []byte) (SchemaEntry, Parser, error) { + var errs error + for _, parser := range parsers { + ret, next, err := parser(key, value) + if err == nil { + return ret, next, nil + } + errs = errors.Join(errs, err) + } + return nil, nil, fmt.Errorf("no parser succeeded: %w", errs) + } +} + +func WithFallback(parser Parser, fallback FallbackParser) Parser { + if parser == nil { + return fallback.ToParser() + } + return func(key, value []byte) (SchemaEntry, Parser, error) { + entry, next, err := parser(key, value) + if err == nil { + return entry, WithFallback(next, fallback), nil + } + return fallback.ToParser()(key, value) + } +} + +func (fp FallbackParser) ToParser() Parser { + return func(key, value []byte) (SchemaEntry, Parser, error) { + entry, next := fp(key, value) + return entry, next, nil + } +} + +func (p Parser) ToFallbackParser() FallbackParser { + return func(key, value []byte) (SchemaEntry, Parser) { + entry, next, err := p(key, value) + if err != nil { + panic(fmt.Errorf( + "couldn't use that parser as a fallback parser, it returned an error: %w", err, + )) + } + return entry, next + } +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/detailed.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/detailed.go new file mode 100644 index 0000000000..6a08a723e7 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/detailed.go @@ -0,0 +1,29 @@ +package buckets + +import ( + "github.com/davecgh/go-spew/spew" +) + +func (b *PrefixBucket) DetailedString() string { + return spew.Sdump(*b) +} + +func (b *PrefixContainerBucket) DetailedString() string { + return spew.Sdump(*b) +} + +func (b *UserBucket) DetailedString() string { + return spew.Sdump(*b) +} + +func (b *ContainerBucket) DetailedString() string { + return spew.Sdump(*b) +} + +func (b *UserAttributeKeyBucket) DetailedString() string { + return spew.Sdump(*b) +} + +func (b *UserAttributeValueBucket) DetailedString() string { + return spew.Sdump(*b) +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/filter.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/filter.go new file mode 100644 index 0000000000..891c4004f0 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/filter.go @@ -0,0 +1,81 @@ +package buckets + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" +) + +func (b *PrefixBucket) Filter(typ string, _ any) common.FilterResult { + switch typ { + case "cid": + return b.resolvers.cidResolver(false) + case "oid": + return b.resolvers.oidResolver(false) + default: + return common.No + } +} + +func (b *PrefixContainerBucket) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return b.resolvers.cidResolver(b.id.Equals(id)) + case "oid": + return b.resolvers.oidResolver(false) + default: + return common.No + } +} + +func (b *UserBucket) Filter(typ string, _ any) common.FilterResult { + switch typ { + case "cid": + return b.resolvers.cidResolver(false) + case "oid": + return b.resolvers.oidResolver(false) + default: + return common.No + } +} + +func (b *ContainerBucket) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return b.resolvers.cidResolver(b.id.Equals(id)) + case "oid": + return b.resolvers.oidResolver(false) + default: + return common.No + } +} + +func (b *UserAttributeKeyBucket) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return common.IfThenElse(b.id.Equals(id), common.Yes, common.No) + case "oid": + return common.Maybe + case "key": + key := val.(string) + return common.IfThenElse(b.key == key, common.Yes, common.No) + case "value": + return common.Maybe + default: + return common.No + } +} + +func (b *UserAttributeValueBucket) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + return common.Maybe + case "value": + value := val.(string) + return common.IfThenElse(b.value == value, common.Yes, common.No) + default: + return common.No + } +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/parsers.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/parsers.go new file mode 100644 index 0000000000..24cc0e52d1 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/parsers.go @@ -0,0 +1,111 @@ +package buckets + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/metabase/records" +) + +var ( + GraveyardParser = NewPrefixBucketParser(Graveyard, records.GraveyardRecordParser, Resolvers{ + cidResolver: LenientResolver, + oidResolver: LenientResolver, + }) + + GarbageParser = NewPrefixBucketParser(Garbage, records.GarbageRecordParser, Resolvers{ + cidResolver: LenientResolver, + oidResolver: LenientResolver, + }) + + ContainerVolumeParser = NewPrefixBucketParser(ContainerVolume, records.ContainerVolumeRecordParser, Resolvers{ + cidResolver: LenientResolver, + oidResolver: StrictResolver, + }) + + LockedParser = NewPrefixBucketParser( + Locked, + NewContainerBucketParser( + records.LockedRecordParser, + Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }, + ), + Resolvers{ + cidResolver: LenientResolver, + oidResolver: LenientResolver, + }, + ) + + ShardInfoParser = NewPrefixBucketParser(ShardInfo, records.ShardInfoRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: StrictResolver, + }) + + PrimaryParser = NewPrefixContainerBucketParser(Primary, records.ObjectRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }) + + LockersParser = NewPrefixContainerBucketParser(Lockers, records.ObjectRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }) + + TombstoneParser = NewPrefixContainerBucketParser(Tombstone, records.ObjectRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }) + + SmallParser = NewPrefixContainerBucketParser(Small, records.SmallRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }) + + RootParser = NewPrefixContainerBucketParser(Root, records.RootRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }) + + OwnerParser = NewPrefixContainerBucketParser( + Owner, + NewUserBucketParser( + records.OwnerRecordParser, + Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }, + ), + Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }, + ) + + UserAttributeParser = NewUserAttributeKeyBucketParser( + NewUserAttributeValueBucketParser(records.UserAttributeRecordParser), + ) + + PayloadHashParser = NewPrefixContainerBucketParser(PayloadHash, records.PayloadHashRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: StrictResolver, + }) + + ParentParser = NewPrefixContainerBucketParser(Parent, records.ParentRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }) + + SplitParser = NewPrefixContainerBucketParser(Split, records.SplitRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: StrictResolver, + }) + + ContainerCountersParser = NewPrefixBucketParser(ContainerCounters, records.ContainerCountersRecordParser, Resolvers{ + cidResolver: LenientResolver, + oidResolver: StrictResolver, + }) + + ECInfoParser = NewPrefixContainerBucketParser(ECInfo, records.ECInfoRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }) +) diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/prefix.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/prefix.go new file mode 100644 index 0000000000..2fb122940d --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/prefix.go @@ -0,0 +1,53 @@ +package buckets + +type Prefix byte + +const ( + Graveyard Prefix = iota + Garbage + ToMoveIt + ContainerVolume + Locked + ShardInfo + Primary + Lockers + _ + Tombstone + Small + Root + Owner + UserAttribute + PayloadHash + Parent + Split + ContainerCounters + ECInfo +) + +var x = map[Prefix]string{ + Graveyard: "Graveyard", + Garbage: "Garbage", + ToMoveIt: "To Move It", + ContainerVolume: "Container Volume", + Locked: "Locked", + ShardInfo: "Shard Info", + Primary: "Primary", + Lockers: "Lockers", + Tombstone: "Tombstone", + Small: "Small", + Root: "Root", + Owner: "Owner", + UserAttribute: "User Attribute", + PayloadHash: "Payload Hash", + Parent: "Parent", + Split: "Split", + ContainerCounters: "Container Counters", + ECInfo: "EC Info", +} + +func (p Prefix) String() string { + if s, ok := x[p]; ok { + return s + } + return "Unknown Prefix" +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/string.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/string.go new file mode 100644 index 0000000000..db90bddbd9 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/string.go @@ -0,0 +1,48 @@ +package buckets + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + "github.com/gdamore/tcell/v2" +) + +func (b *PrefixBucket) String() string { + return common.FormatSimple( + fmt.Sprintf("(%2d %-18s)", b.prefix, b.prefix), tcell.ColorLime, + ) +} + +func (b *PrefixContainerBucket) String() string { + return fmt.Sprintf( + "%s CID %s", + common.FormatSimple( + fmt.Sprintf("(%2d %-18s)", b.prefix, b.prefix), tcell.ColorLime, + ), + common.FormatSimple(b.id.String(), tcell.ColorAqua), + ) +} + +func (b *UserBucket) String() string { + return "UID " + common.FormatSimple(b.id.String(), tcell.ColorAqua) +} + +func (b *ContainerBucket) String() string { + return "CID " + common.FormatSimple(b.id.String(), tcell.ColorAqua) +} + +func (b *UserAttributeKeyBucket) String() string { + return fmt.Sprintf("%s CID %s ATTR-KEY %s", + common.FormatSimple( + fmt.Sprintf("(%2d %-18s)", b.prefix, b.prefix), tcell.ColorLime, + ), + common.FormatSimple( + fmt.Sprintf("%-44s", b.id), tcell.ColorAqua, + ), + common.FormatSimple(b.key, tcell.ColorAqua), + ) +} + +func (b *UserAttributeValueBucket) String() string { + return "ATTR-VALUE " + common.FormatSimple(b.value, tcell.ColorAqua) +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/types.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/types.go new file mode 100644 index 0000000000..82b47dd855 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/types.go @@ -0,0 +1,166 @@ +package buckets + +import ( + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/mr-tron/base58" +) + +type ( + PrefixBucket struct { + prefix Prefix + resolvers Resolvers + } + + PrefixContainerBucket struct { + prefix Prefix + id cid.ID + resolvers Resolvers + } + + ContainerBucket struct { + id cid.ID + resolvers Resolvers + } + + UserBucket struct { + id user.ID + resolvers Resolvers + } + + UserAttributeKeyBucket struct { + prefix Prefix + id cid.ID + key string + } + + UserAttributeValueBucket struct { + value string + } +) + +type ( + FilterResolver = func(result bool) common.FilterResult + + Resolvers struct { + cidResolver FilterResolver + oidResolver FilterResolver + } +) + +var ( + StrictResolver = func(x bool) common.FilterResult { return common.IfThenElse(x, common.Yes, common.No) } + LenientResolver = func(x bool) common.FilterResult { return common.IfThenElse(x, common.Yes, common.Maybe) } +) + +var ( + ErrNotBucket = errors.New("not a bucket") + ErrInvalidKeyLength = errors.New("invalid key length") + ErrInvalidValueLength = errors.New("invalid value length") + ErrInvalidPrefix = errors.New("invalid prefix") +) + +func NewPrefixBucketParser(prefix Prefix, next common.Parser, resolvers Resolvers) common.Parser { + return func(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, ErrNotBucket + } + if len(key) != 1 { + return nil, nil, ErrInvalidKeyLength + } + var b PrefixBucket + if b.prefix = Prefix(key[0]); b.prefix != prefix { + return nil, nil, ErrInvalidPrefix + } + b.resolvers = resolvers + return &b, next, nil + } +} + +func NewPrefixContainerBucketParser(prefix Prefix, next common.Parser, resolvers Resolvers) common.Parser { + return func(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, ErrNotBucket + } + if len(key) != 33 { + return nil, nil, ErrInvalidKeyLength + } + var b PrefixContainerBucket + if b.prefix = Prefix(key[0]); b.prefix != prefix { + return nil, nil, ErrInvalidPrefix + } + if err := b.id.Decode(key[1:]); err != nil { + return nil, nil, err + } + b.resolvers = resolvers + return &b, next, nil + } +} + +func NewUserBucketParser(next common.Parser, resolvers Resolvers) common.Parser { + return func(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, ErrNotBucket + } + var b UserBucket + if err := b.id.DecodeString(base58.Encode(key)); err != nil { + return nil, nil, err + } + b.resolvers = resolvers + return &b, next, nil + } +} + +func NewContainerBucketParser(next common.Parser, resolvers Resolvers) common.Parser { + return func(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, ErrNotBucket + } + if len(key) != 32 { + return nil, nil, ErrInvalidKeyLength + } + var b ContainerBucket + if err := b.id.Decode(key); err != nil { + return nil, nil, err + } + b.resolvers = resolvers + return &b, next, nil + } +} + +func NewUserAttributeKeyBucketParser(next common.Parser) common.Parser { + return func(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, ErrNotBucket + } + if len(key) < 34 { + return nil, nil, ErrInvalidKeyLength + } + var b UserAttributeKeyBucket + if b.prefix = Prefix(key[0]); b.prefix != UserAttribute { + return nil, nil, ErrInvalidPrefix + } + if err := b.id.Decode(key[1:33]); err != nil { + return nil, nil, err + } + b.key = string(key[33:]) + return &b, next, nil + } +} + +func NewUserAttributeValueBucketParser(next common.Parser) common.Parser { + return func(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, ErrNotBucket + } + if len(key) == 0 { + return nil, nil, ErrInvalidKeyLength + } + var b UserAttributeValueBucket + b.value = string(key) + return &b, next, nil + } +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/parser.go b/cmd/frostfs-lens/internal/schema/metabase/parser.go new file mode 100644 index 0000000000..ea095e2071 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/parser.go @@ -0,0 +1,29 @@ +package metabase + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/metabase/buckets" +) + +var MetabaseParser = common.WithFallback( + common.Any( + buckets.GraveyardParser, + buckets.GarbageParser, + buckets.ContainerVolumeParser, + buckets.LockedParser, + buckets.ShardInfoParser, + buckets.PrimaryParser, + buckets.LockersParser, + buckets.TombstoneParser, + buckets.SmallParser, + buckets.RootParser, + buckets.OwnerParser, + buckets.UserAttributeParser, + buckets.PayloadHashParser, + buckets.ParentParser, + buckets.SplitParser, + buckets.ContainerCountersParser, + buckets.ECInfoParser, + ), + common.RawParser.ToFallbackParser(), +) diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/detailed.go b/cmd/frostfs-lens/internal/schema/metabase/records/detailed.go new file mode 100644 index 0000000000..2dda15b4f1 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/records/detailed.go @@ -0,0 +1,65 @@ +package records + +import ( + "github.com/davecgh/go-spew/spew" +) + +func (r *GraveyardRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *GarbageRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *ContainerVolumeRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *LockedRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *ShardInfoRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *ObjectRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *SmallRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *RootRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *OwnerRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *UserAttributeRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *PayloadHashRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *ParentRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *SplitRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *ContainerCountersRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *ECInfoRecord) DetailedString() string { + return spew.Sdump(*r) +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/filter.go b/cmd/frostfs-lens/internal/schema/metabase/records/filter.go new file mode 100644 index 0000000000..880a7a8ff2 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/records/filter.go @@ -0,0 +1,145 @@ +package records + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +) + +func (r *GraveyardRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return common.IfThenElse(r.object.Container().Equals(id), common.Yes, common.No) + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.object.Object().Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *GarbageRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return common.IfThenElse(r.addr.Container().Equals(id), common.Yes, common.No) + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.addr.Object().Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *ContainerVolumeRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *ShardInfoRecord) Filter(string, any) common.FilterResult { + return common.No +} + +func (r *LockedRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *ObjectRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *SmallRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *RootRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *OwnerRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *UserAttributeRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *PayloadHashRecord) Filter(string, any) common.FilterResult { + return common.No +} + +func (r *ParentRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.parent.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *SplitRecord) Filter(string, any) common.FilterResult { + return common.No +} + +func (r *ContainerCountersRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *ECInfoRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.id.Equals(id), common.Yes, common.No) + default: + return common.No + } +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/parsers.go b/cmd/frostfs-lens/internal/schema/metabase/records/parsers.go new file mode 100644 index 0000000000..1b070e2a02 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/records/parsers.go @@ -0,0 +1,251 @@ +package records + +import ( + "encoding/binary" + "errors" + "strconv" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +) + +var ( + ErrInvalidKeyLength = errors.New("invalid key length") + ErrInvalidValueLength = errors.New("invalid value length") + ErrInvalidPrefix = errors.New("invalid prefix") +) + +func GraveyardRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if len(key) != 64 { + return nil, nil, ErrInvalidKeyLength + } + if len(value) != 64 { + return nil, nil, ErrInvalidValueLength + } + var ( + cnr cid.ID + obj oid.ID + r GraveyardRecord + ) + + _ = cnr.Decode(key[:32]) + _ = obj.Decode(key[32:]) + + r.object.SetContainer(cnr) + r.object.SetObject(obj) + + _ = cnr.Decode(value[:32]) + _ = obj.Decode(value[32:]) + + r.tombstone.SetContainer(cnr) + r.tombstone.SetObject(obj) + + return &r, nil, nil +} + +func GarbageRecordParser(key, _ []byte) (common.SchemaEntry, common.Parser, error) { + if len(key) != 64 { + return nil, nil, ErrInvalidKeyLength + } + var ( + cnr cid.ID + obj oid.ID + r GarbageRecord + ) + + _ = cnr.Decode(key[:32]) + _ = obj.Decode(key[32:]) + + r.addr.SetContainer(cnr) + r.addr.SetObject(obj) + + return &r, nil, nil +} + +func ContainerVolumeRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if len(key) != 32 { + return nil, nil, ErrInvalidKeyLength + } + if len(value) != 8 { + return nil, nil, ErrInvalidValueLength + } + var r ContainerVolumeRecord + + _ = r.id.Decode(key) + r.volume = binary.LittleEndian.Uint64(value) + + return &r, nil, nil +} + +func LockedRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + var ( + r LockedRecord + err error + ) + + if err := r.id.Decode(key); err != nil { + return nil, nil, err + } + if r.ids, err = DecodeOIDs(value); err != nil { + return nil, nil, err + } + return &r, nil, nil +} + +func ShardInfoRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if len(key) == 0 { + return nil, nil, ErrInvalidKeyLength + } + + var r ShardInfoRecord + if string(key) == "id" { + r.label = string(key) + r.value = shard.ID(value).String() + + return &r, nil, nil + } + + if len(value) != 8 { + return nil, nil, ErrInvalidValueLength + } + r.label = string(key) + r.value = strconv.FormatUint(binary.LittleEndian.Uint64(value), 10) + + return &r, nil, nil +} + +func ObjectRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if len(key) != 32 { + return nil, nil, ErrInvalidKeyLength + } + var r ObjectRecord + + _ = r.id.Decode(key) + if err := r.object.Unmarshal(value); err != nil { + return nil, nil, err + } + + return &r, nil, nil +} + +func SmallRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + var r SmallRecord + if err := r.id.Decode(key); err != nil { + return nil, nil, err + } + if len(value) != 0 { + x := string(value) + r.storageID = &x + } + return &r, nil, nil +} + +func RootRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + var r RootRecord + if err := r.id.Decode(key); err != nil { + return nil, nil, err + } + if len(value) == 0 { + return &r, nil, nil + } + r.info = &objectSDK.SplitInfo{} + if err := r.info.Unmarshal(value); err != nil { + return nil, nil, err + } + return &r, nil, nil +} + +func OwnerRecordParser(key, _ []byte) (common.SchemaEntry, common.Parser, error) { + var r OwnerRecord + if err := r.id.Decode(key); err != nil { + return nil, nil, err + } + return &r, nil, nil +} + +func UserAttributeRecordParser(key, _ []byte) (common.SchemaEntry, common.Parser, error) { + var r UserAttributeRecord + if err := r.id.Decode(key); err != nil { + return nil, nil, err + } + return &r, nil, nil +} + +func PayloadHashRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if len(key) != 32 { + return nil, nil, ErrInvalidKeyLength + } + var ( + err error + r PayloadHashRecord + ) + + r.checksum.SetSHA256([32]byte(key)) + if r.ids, err = DecodeOIDs(value); err != nil { + return nil, nil, err + } + return &r, nil, nil +} + +func ParentRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + var ( + r ParentRecord + err error + ) + if err = r.parent.Decode(key); err != nil { + return nil, nil, err + } + if r.ids, err = DecodeOIDs(value); err != nil { + return nil, nil, err + } + return &r, nil, nil +} + +func SplitRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + var ( + err error + r SplitRecord + ) + if err = r.id.UnmarshalBinary(key); err != nil { + return nil, nil, err + } + if r.ids, err = DecodeOIDs(value); err != nil { + return nil, nil, err + } + return &r, nil, nil +} + +func ContainerCountersRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if len(value) != 24 { + return nil, nil, ErrInvalidValueLength + } + + var r ContainerCountersRecord + if err := r.id.Decode(key); err != nil { + return nil, nil, err + } + + r.logical = binary.LittleEndian.Uint64(value[:8]) + r.physical = binary.LittleEndian.Uint64(value[8:16]) + r.user = binary.LittleEndian.Uint64(value[16:24]) + + return &r, nil, nil +} + +func ECInfoRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + var ( + r ECInfoRecord + err error + ) + + if err := r.id.Decode(key); err != nil { + return nil, nil, err + } + if r.ids, err = DecodeOIDs(value); err != nil { + return nil, nil, err + } + return &r, nil, nil +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/string.go b/cmd/frostfs-lens/internal/schema/metabase/records/string.go new file mode 100644 index 0000000000..a6c70d537d --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/records/string.go @@ -0,0 +1,135 @@ +package records + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +func (r *GraveyardRecord) String() string { + return fmt.Sprintf( + "Object CID %s OID %s %c Tombstone CID %s OID %s", + common.FormatSimple(fmt.Sprintf("%-44s", r.object.Container()), tcell.ColorAqua), + common.FormatSimple(fmt.Sprintf("%-44s", r.object.Object()), tcell.ColorAqua), + tview.Borders.Vertical, + common.FormatSimple(fmt.Sprintf("%-44s", r.tombstone.Container()), tcell.ColorAqua), + common.FormatSimple(fmt.Sprintf("%-44s", r.tombstone.Object()), tcell.ColorAqua), + ) +} + +func (r *GarbageRecord) String() string { + return fmt.Sprintf( + "CID %-44s OID %-44s", + common.FormatSimple(fmt.Sprintf("%-44s", r.addr.Container()), tcell.ColorAqua), + common.FormatSimple(fmt.Sprintf("%-44s", r.addr.Object()), tcell.ColorAqua), + ) +} + +func (r *ContainerVolumeRecord) String() string { + return fmt.Sprintf( + "CID %-44s %c %d", + common.FormatSimple(fmt.Sprintf("%-44s", r.id), tcell.ColorAqua), + tview.Borders.Vertical, + r.volume, + ) +} + +func (r *LockedRecord) String() string { + return fmt.Sprintf( + "Locker OID %s %c Locked [%d]OID {...}", + common.FormatSimple(fmt.Sprintf("%-44s", r.id), tcell.ColorAqua), + tview.Borders.Vertical, + len(r.ids), + ) +} + +func (r *ShardInfoRecord) String() string { + return fmt.Sprintf("%-13s %c %s", r.label, tview.Borders.Vertical, r.value) +} + +func (r *ObjectRecord) String() string { + return fmt.Sprintf( + "OID %s %c Object {...}", + common.FormatSimple(fmt.Sprintf("%-44s", r.id), tcell.ColorAqua), + tview.Borders.Vertical, + ) +} + +func (r *SmallRecord) String() string { + s := fmt.Sprintf( + "OID %s %c", + common.FormatSimple(fmt.Sprintf("%-44s", r.id), tcell.ColorAqua), + tview.Borders.Vertical, + ) + if r.storageID != nil { + s = fmt.Sprintf("%s %s", s, *r.storageID) + } + return s +} + +func (r *RootRecord) String() string { + s := fmt.Sprintf( + "Root OID %s %c", + common.FormatSimple(fmt.Sprintf("%-44s", r.id), tcell.ColorAqua), + tview.Borders.Vertical, + ) + if r.info != nil { + s += " Split info {...}" + } + return s +} + +func (r *OwnerRecord) String() string { + return "OID " + common.FormatSimple(r.id.String(), tcell.ColorAqua) +} + +func (r *UserAttributeRecord) String() string { + return "OID " + common.FormatSimple(r.id.String(), tcell.ColorAqua) +} + +func (r *PayloadHashRecord) String() string { + return fmt.Sprintf( + "Checksum %s %c [%d]OID {...}", + common.FormatSimple(r.checksum.String(), tcell.ColorAqua), + tview.Borders.Vertical, + len(r.ids), + ) +} + +func (r *ParentRecord) String() string { + return fmt.Sprintf( + "Parent OID %s %c [%d]OID {...}", + common.FormatSimple(fmt.Sprintf("%-44s", r.parent), tcell.ColorAqua), + tview.Borders.Vertical, + len(r.ids), + ) +} + +func (r *SplitRecord) String() string { + return fmt.Sprintf( + "Split ID %s %c [%d]OID {...}", + common.FormatSimple(r.id.String(), tcell.ColorAqua), + tview.Borders.Vertical, + len(r.ids), + ) +} + +func (r *ContainerCountersRecord) String() string { + return fmt.Sprintf( + "CID %s %c logical %d, physical %d, user %d", + common.FormatSimple(fmt.Sprintf("%-44s", r.id), tcell.ColorAqua), + tview.Borders.Vertical, + r.logical, r.physical, r.user, + ) +} + +func (r *ECInfoRecord) String() string { + return fmt.Sprintf( + "OID %s %c [%d]OID {...}", + common.FormatSimple(fmt.Sprintf("%-44s", r.id), tcell.ColorAqua), + tview.Borders.Vertical, + len(r.ids), + ) +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/types.go b/cmd/frostfs-lens/internal/schema/metabase/records/types.go new file mode 100644 index 0000000000..34c1c29fdf --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/records/types.go @@ -0,0 +1,82 @@ +package records + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/google/uuid" +) + +type ( + GraveyardRecord struct { + object, tombstone oid.Address + } + + GarbageRecord struct { + addr oid.Address + } + + ContainerVolumeRecord struct { + id cid.ID + volume uint64 + } + + LockedRecord struct { + id oid.ID + ids []oid.ID + } + + ShardInfoRecord struct { + label string + value string + } + + ObjectRecord struct { + id oid.ID + object objectSDK.Object + } + + SmallRecord struct { + id oid.ID + storageID *string // optional + } + + RootRecord struct { + id oid.ID + info *objectSDK.SplitInfo // optional + } + + OwnerRecord struct { + id oid.ID + } + + UserAttributeRecord struct { + id oid.ID + } + + PayloadHashRecord struct { + checksum checksum.Checksum + ids []oid.ID + } + + ParentRecord struct { + parent oid.ID + ids []oid.ID + } + + SplitRecord struct { + id uuid.UUID + ids []oid.ID + } + + ContainerCountersRecord struct { + id cid.ID + logical, physical, user uint64 + } + + ECInfoRecord struct { + id oid.ID + ids []oid.ID + } +) diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/util.go b/cmd/frostfs-lens/internal/schema/metabase/records/util.go new file mode 100644 index 0000000000..f50ebe9513 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/metabase/records/util.go @@ -0,0 +1,20 @@ +package records + +import ( + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/nspcc-dev/neo-go/pkg/io" +) + +func DecodeOIDs(data []byte) ([]oid.ID, error) { + r := io.NewBinReaderFromBuf(data) + + size := r.ReadVarUint() + oids := make([]oid.ID, size) + + for i := uint64(0); i < size; i++ { + if err := oids[i].Decode(r.ReadVarBytes()); err != nil { + return nil, err + } + } + return oids, nil +} diff --git a/go.mod b/go.mod index 19bf7852fe..be3c6e74df 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,9 @@ require ( github.com/VictoriaMetrics/easyproto v0.1.4 github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 + github.com/gdamore/tcell/v2 v2.7.4 github.com/go-pkgz/expirable-cache/v3 v3.0.0 github.com/google/uuid v1.6.0 github.com/hashicorp/golang-lru/v2 v2.0.7 @@ -65,10 +67,10 @@ require ( github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect - github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davidmz/go-pageant v1.0.2 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gdamore/encoding v1.0.0 // indirect github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -85,6 +87,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/klauspost/reedsolomon v1.12.1 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/minio/sha256-simd v1.0.1 // indirect diff --git a/go.sum b/go.sum index 8ebd59157b..d0218a348b 100644 --- a/go.sum +++ b/go.sum @@ -75,6 +75,10 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU= +github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -142,6 +146,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -218,6 +224,7 @@ github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5E github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= @@ -352,6 +359,7 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -359,6 +367,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 9cbd32bce8524e32711287f86196382517f37562 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 16 Aug 2024 14:33:03 +0300 Subject: [PATCH 0779/1413] [#1223] lens/tui: Add writecache schema Signed-off-by: Aleksey Savchuk --- .../internal/schema/writecache/parsers.go | 63 ++++++++++++++++++ .../internal/schema/writecache/types.go | 66 +++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 cmd/frostfs-lens/internal/schema/writecache/parsers.go create mode 100644 cmd/frostfs-lens/internal/schema/writecache/types.go diff --git a/cmd/frostfs-lens/internal/schema/writecache/parsers.go b/cmd/frostfs-lens/internal/schema/writecache/parsers.go new file mode 100644 index 0000000000..7d70b27b2a --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/writecache/parsers.go @@ -0,0 +1,63 @@ +package writecache + +import ( + "bytes" + "errors" + "fmt" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/mr-tron/base58" +) + +var WritecacheParser = common.WithFallback( + DefaultBucketParser, + common.RawParser.ToFallbackParser(), +) + +func DefaultBucketParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, errors.New("not a bucket") + } + if !bytes.Equal(key, []byte{0}) { + return nil, nil, errors.New("invalid key") + } + return &DefaultBucket{}, DefaultRecordParser, nil +} + +func DefaultRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + parts := strings.Split(string(key), "/") + + if len(parts) != 2 { + return nil, nil, errors.New("invalid key, expected address string /") + } + + cnrRaw, err := base58.Decode(parts[0]) + if err != nil { + return nil, nil, errors.New("can't decode CID string") + } + objRaw, err := base58.Decode(parts[1]) + if err != nil { + return nil, nil, errors.New("can't decode OID string") + } + + cnr := cid.ID{} + if err := cnr.Decode(cnrRaw); err != nil { + return nil, nil, fmt.Errorf("can't decode CID: %w", err) + } + obj := oid.ID{} + if err := obj.Decode(objRaw); err != nil { + return nil, nil, fmt.Errorf("can't decode OID: %w", err) + } + + var r DefaultRecord + + r.addr.SetContainer(cnr) + r.addr.SetObject(obj) + + r.data = value[:] + + return &r, nil, nil +} diff --git a/cmd/frostfs-lens/internal/schema/writecache/types.go b/cmd/frostfs-lens/internal/schema/writecache/types.go new file mode 100644 index 0000000000..3f71c5366f --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/writecache/types.go @@ -0,0 +1,66 @@ +package writecache + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/davecgh/go-spew/spew" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +type ( + DefaultBucket struct{} + + DefaultRecord struct { + addr oid.Address + data []byte + } +) + +func (b *DefaultBucket) String() string { + return common.FormatSimple("0 Default", tcell.ColorLime) +} + +func (r *DefaultRecord) String() string { + return fmt.Sprintf( + "CID %s OID %s %c Data {...}", + common.FormatSimple(fmt.Sprintf("%-44s", r.addr.Container()), tcell.ColorAqua), + common.FormatSimple(fmt.Sprintf("%-44s", r.addr.Object()), tcell.ColorAqua), + tview.Borders.Vertical, + ) +} + +func (b *DefaultBucket) DetailedString() string { + return spew.Sdump(*b) +} + +func (r *DefaultRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (b *DefaultBucket) Filter(typ string, _ any) common.FilterResult { + switch typ { + case "cid": + return common.Maybe + case "oid": + return common.Maybe + default: + return common.No + } +} + +func (r *DefaultRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return common.IfThenElse(r.addr.Container().Equals(id), common.Yes, common.No) + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.addr.Object().Equals(id), common.Yes, common.No) + default: + return common.No + } +} From ed396448acbd3792da3ae0b756233e8c8fe67fee Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 11 Jul 2024 19:39:54 +0300 Subject: [PATCH 0780/1413] [#1223] lens/tui: Add TUI app to explore metabase Signed-off-by: Aleksey Savchuk --- cmd/frostfs-lens/internal/meta/root.go | 1 + cmd/frostfs-lens/internal/meta/tui.go | 82 ++++ cmd/frostfs-lens/internal/tui/buckets.go | 257 ++++++++++ cmd/frostfs-lens/internal/tui/db.go | 160 +++++++ cmd/frostfs-lens/internal/tui/detailed.go | 24 + cmd/frostfs-lens/internal/tui/filter.go | 44 ++ cmd/frostfs-lens/internal/tui/input.go | 77 +++ cmd/frostfs-lens/internal/tui/loading.go | 72 +++ cmd/frostfs-lens/internal/tui/records.go | 271 +++++++++++ cmd/frostfs-lens/internal/tui/types.go | 18 + cmd/frostfs-lens/internal/tui/ui.go | 548 ++++++++++++++++++++++ cmd/frostfs-lens/internal/tui/util.go | 97 ++++ go.mod | 3 +- go.sum | 6 +- 14 files changed, 1657 insertions(+), 3 deletions(-) create mode 100644 cmd/frostfs-lens/internal/meta/tui.go create mode 100644 cmd/frostfs-lens/internal/tui/buckets.go create mode 100644 cmd/frostfs-lens/internal/tui/db.go create mode 100644 cmd/frostfs-lens/internal/tui/detailed.go create mode 100644 cmd/frostfs-lens/internal/tui/filter.go create mode 100644 cmd/frostfs-lens/internal/tui/input.go create mode 100644 cmd/frostfs-lens/internal/tui/loading.go create mode 100644 cmd/frostfs-lens/internal/tui/records.go create mode 100644 cmd/frostfs-lens/internal/tui/types.go create mode 100644 cmd/frostfs-lens/internal/tui/ui.go create mode 100644 cmd/frostfs-lens/internal/tui/util.go diff --git a/cmd/frostfs-lens/internal/meta/root.go b/cmd/frostfs-lens/internal/meta/root.go index 6741abd0cd..351d1ce807 100644 --- a/cmd/frostfs-lens/internal/meta/root.go +++ b/cmd/frostfs-lens/internal/meta/root.go @@ -32,6 +32,7 @@ func init() { inspectCMD, listGraveyardCMD, listGarbageCMD, + tuiCMD, ) } diff --git a/cmd/frostfs-lens/internal/meta/tui.go b/cmd/frostfs-lens/internal/meta/tui.go new file mode 100644 index 0000000000..00e8bf1175 --- /dev/null +++ b/cmd/frostfs-lens/internal/meta/tui.go @@ -0,0 +1,82 @@ +package meta + +import ( + "context" + "fmt" + + common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" + schema "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/tui" + "github.com/rivo/tview" + "github.com/spf13/cobra" + "go.etcd.io/bbolt" +) + +var tuiCMD = &cobra.Command{ + Use: "explore", + Short: "Metabase exploration with a terminal UI", + Long: `Launch a terminal UI to explore metabase and search for data. + +Available search filters: +- cid CID +- oid OID +- addr CID/OID +- attr key[/value] +`, + Run: tuiFunc, +} + +var initialPrompt string + +func init() { + common.AddComponentPathFlag(tuiCMD, &vPath) + + tuiCMD.Flags().StringVar( + &initialPrompt, + "filter", + "", + "Filter prompt to start with, format 'tag:value [+ tag:value]...'", + ) +} + +func tuiFunc(cmd *cobra.Command, _ []string) { + common.ExitOnErr(cmd, runTUI(cmd)) +} + +func runTUI(cmd *cobra.Command) error { + db, err := openDB(false) + if err != nil { + return fmt.Errorf("couldn't open database: %w", err) + } + defer db.Close() + + // Need if app was stopped with Ctrl-C. + ctx, cancel := context.WithCancel(cmd.Context()) + defer cancel() + + app := tview.NewApplication() + ui := tui.NewUI(ctx, app, db, schema.MetabaseParser, nil) + + _ = ui.AddFilter("cid", tui.CIDParser, "CID") + _ = ui.AddFilter("oid", tui.OIDParser, "OID") + _ = ui.AddCompositeFilter("addr", tui.AddressParser, "CID/OID") + _ = ui.AddCompositeFilter("attr", tui.AttributeParser, "key[/value]") + + err = ui.WithPrompt(initialPrompt) + if err != nil { + return fmt.Errorf("invalid filter prompt: %w", err) + } + + app.SetRoot(ui, true).SetFocus(ui) + return app.Run() +} + +func openDB(writable bool) (*bbolt.DB, error) { + db, err := bbolt.Open(vPath, 0o600, &bbolt.Options{ + ReadOnly: !writable, + }) + if err != nil { + return nil, err + } + return db, nil +} diff --git a/cmd/frostfs-lens/internal/tui/buckets.go b/cmd/frostfs-lens/internal/tui/buckets.go new file mode 100644 index 0000000000..3f5088e7ab --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/buckets.go @@ -0,0 +1,257 @@ +package tui + +import ( + "context" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +type BucketsView struct { + *tview.Box + + mu sync.Mutex + + view *tview.TreeView + nodeToUpdate *tview.TreeNode + + ui *UI + filter *Filter +} + +type bucketNode struct { + bucket *Bucket + filter *Filter +} + +func NewBucketsView(ui *UI, filter *Filter) *BucketsView { + return &BucketsView{ + Box: tview.NewBox(), + view: tview.NewTreeView(), + ui: ui, + filter: filter, + } +} + +func (v *BucketsView) Mount(_ context.Context) error { + root := tview.NewTreeNode(".") + root.SetExpanded(false) + root.SetSelectable(false) + root.SetReference(&bucketNode{ + bucket: &Bucket{NextParser: v.ui.rootParser}, + filter: v.filter, + }) + + v.nodeToUpdate = root + + v.view.SetRoot(root) + v.view.SetCurrentNode(root) + + return nil +} + +func (v *BucketsView) Update(ctx context.Context) error { + if v.nodeToUpdate == nil { + return nil + } + defer func() { v.nodeToUpdate = nil }() + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + ready := make(chan struct{}) + errCh := make(chan error) + + tmp := tview.NewTreeNode(v.nodeToUpdate.GetText()) + tmp.SetReference(v.nodeToUpdate.GetReference()) + + node := v.nodeToUpdate.GetReference().(*bucketNode) + + go func() { + defer close(ready) + + hasBuckets, err := HasBuckets(ctx, v.ui.db, node.bucket.Path) + if err != nil { + errCh <- err + } + + // Show the selected bucket's records instead. + if !hasBuckets && node.bucket.NextParser != nil { + v.ui.moveNextPage(NewRecordsView(v.ui, node.bucket, node.filter)) + } + + if v.nodeToUpdate.IsExpanded() { + return + } + + err = v.loadNodeChildren(ctx, tmp, node.filter) + if err != nil { + errCh <- err + } + }() + + select { + case <-ctx.Done(): + case <-ready: + v.mu.Lock() + v.nodeToUpdate.SetChildren(tmp.GetChildren()) + v.nodeToUpdate.SetExpanded(!v.nodeToUpdate.IsExpanded()) + v.mu.Unlock() + case err := <-errCh: + return err + } + + return nil +} + +func (v *BucketsView) Unmount() { +} + +func (v *BucketsView) Draw(screen tcell.Screen) { + x, y, width, height := v.GetInnerRect() + v.view.SetRect(x, y, width, height) + + v.view.Draw(screen) +} + +func (v *BucketsView) loadNodeChildren( + ctx context.Context, node *tview.TreeNode, filter *Filter, +) error { + parentBucket := node.GetReference().(*bucketNode).bucket + + path := parentBucket.Path + parser := parentBucket.NextParser + + buffer, err := LoadBuckets(ctx, v.ui.db, path, v.ui.loadBufferSize) + if err != nil { + return err + } + + for item := range buffer { + if item.err != nil { + return item.err + } + bucket := item.val + + bucket.Entry, bucket.NextParser, err = parser(bucket.Name, nil) + if err != nil { + return err + } + + satisfies, err := v.bucketSatisfiesFilter(ctx, bucket, filter) + if err != nil { + return err + } + if !satisfies { + continue + } + + child := tview.NewTreeNode(bucket.Entry.String()). + SetSelectable(true). + SetExpanded(false). + SetReference(&bucketNode{ + bucket: bucket, + filter: filter.Apply(bucket.Entry), + }) + + node.AddChild(child) + } + + return nil +} + +func (v *BucketsView) bucketSatisfiesFilter( + ctx context.Context, bucket *Bucket, filter *Filter, +) (bool, error) { + // Does the current bucket satisfies the filter? + filter = filter.Apply(bucket.Entry) + + if filter.Result() == common.Yes { + return true, nil + } + + if filter.Result() == common.No { + return false, nil + } + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // Check the current bucket's nested buckets if exist + bucketsBuffer, err := LoadBuckets(ctx, v.ui.db, bucket.Path, v.ui.loadBufferSize) + if err != nil { + return false, err + } + + for item := range bucketsBuffer { + if item.err != nil { + return false, item.err + } + b := item.val + + b.Entry, b.NextParser, err = bucket.NextParser(b.Name, nil) + if err != nil { + return false, err + } + + satisfies, err := v.bucketSatisfiesFilter(ctx, b, filter) + if err != nil { + return false, err + } + if satisfies { + return true, nil + } + } + + // Check the current bucket's nested records if exist + recordsBuffer, err := LoadRecords(ctx, v.ui.db, bucket.Path, v.ui.loadBufferSize) + if err != nil { + return false, err + } + + for item := range recordsBuffer { + if item.err != nil { + return false, item.err + } + r := item.val + + r.Entry, _, err = bucket.NextParser(r.Key, r.Value) + if err != nil { + return false, err + } + + if filter.Apply(r.Entry).Result() == common.Yes { + return true, nil + } + } + + return false, nil +} + +func (v *BucketsView) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { + return v.WrapInputHandler(func(event *tcell.EventKey, _ func(tview.Primitive)) { + currentNode := v.view.GetCurrentNode() + if currentNode == nil { + return + } + + switch event.Key() { + case tcell.KeyEnter: + // Expand or collapse the selected bucket's nested buckets, + // otherwise, navigate to that bucket's records. + v.nodeToUpdate = currentNode + case tcell.KeyCtrlR: + // Navigate to the selected bucket's records. + bucketNode := currentNode.GetReference().(*bucketNode) + v.ui.moveNextPage(NewRecordsView(v.ui, bucketNode.bucket, bucketNode.filter)) + case tcell.KeyCtrlD: + // Navigate to the selected bucket's detailed view. + bucketNode := currentNode.GetReference().(*bucketNode) + v.ui.moveNextPage(NewDetailedView(bucketNode.bucket.Entry.DetailedString())) + default: + v.view.InputHandler()(event, func(tview.Primitive) {}) + } + }) +} diff --git a/cmd/frostfs-lens/internal/tui/db.go b/cmd/frostfs-lens/internal/tui/db.go new file mode 100644 index 0000000000..d0cf611d48 --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/db.go @@ -0,0 +1,160 @@ +package tui + +import ( + "context" + "errors" + "fmt" + + "go.etcd.io/bbolt" +) + +type Item[T any] struct { + val T + err error +} + +func resolvePath(tx *bbolt.Tx, path [][]byte) (*bbolt.Bucket, error) { + if len(path) == 0 { + return nil, errors.New("can't find bucket without path") + } + + name := path[0] + bucket := tx.Bucket(name) + if bucket == nil { + return nil, fmt.Errorf("no bucket with name %s", name) + } + for _, name := range path[1:] { + bucket = bucket.Bucket(name) + if bucket == nil { + return nil, fmt.Errorf("no bucket with name %s", name) + } + } + return bucket, nil +} + +func load[T any]( + ctx context.Context, db *bbolt.DB, path [][]byte, bufferSize int, + filter func(key, value []byte) bool, transform func(key, value []byte) T, +) (<-chan Item[T], error) { + buffer := make(chan Item[T], bufferSize) + + go func() { + defer close(buffer) + + err := db.View(func(tx *bbolt.Tx) error { + var cursor *bbolt.Cursor + if len(path) == 0 { + cursor = tx.Cursor() + } else { + bucket, err := resolvePath(tx, path) + if err != nil { + buffer <- Item[T]{err: fmt.Errorf("can't find bucket: %w", err)} + return nil + } + cursor = bucket.Cursor() + } + + key, value := cursor.First() + for { + if key == nil { + return nil + } + if filter != nil && !filter(key, value) { + key, value = cursor.Next() + continue + } + + select { + case <-ctx.Done(): + return nil + case buffer <- Item[T]{val: transform(key, value)}: + key, value = cursor.Next() + } + } + }) + if err != nil { + buffer <- Item[T]{err: err} + } + }() + + return buffer, nil +} + +func LoadBuckets( + ctx context.Context, db *bbolt.DB, path [][]byte, bufferSize int, +) (<-chan Item[*Bucket], error) { + buffer, err := load( + ctx, db, path, bufferSize, + func(_, value []byte) bool { + return value == nil + }, + func(key, _ []byte) *Bucket { + base := make([][]byte, 0, len(path)) + base = append(base, path...) + + return &Bucket{ + Name: key, + Path: append(base, key), + } + }, + ) + if err != nil { + return nil, fmt.Errorf("can't start iterating bucket: %w", err) + } + + return buffer, nil +} + +func LoadRecords( + ctx context.Context, db *bbolt.DB, path [][]byte, bufferSize int, +) (<-chan Item[*Record], error) { + buffer, err := load( + ctx, db, path, bufferSize, + func(_, value []byte) bool { + return value != nil + }, + func(key, value []byte) *Record { + base := make([][]byte, 0, len(path)) + base = append(base, path...) + + return &Record{ + Key: key, + Value: value, + Path: append(base, key), + } + }, + ) + if err != nil { + return nil, fmt.Errorf("can't start iterating bucket: %w", err) + } + + return buffer, nil +} + +// HasBuckets checks if a bucket has nested buckets. It relies on assumption +// that a bucket can have either nested buckets or records but not both. +func HasBuckets(ctx context.Context, db *bbolt.DB, path [][]byte) (bool, error) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + buffer, err := load( + ctx, db, path, 1, + nil, + func(_, value []byte) []byte { return value }, + ) + if err != nil { + return false, err + } + + x, ok := <-buffer + if !ok { + return false, nil + } + if x.err != nil { + return false, err + } + if x.val != nil { + return false, err + } + return true, nil +} diff --git a/cmd/frostfs-lens/internal/tui/detailed.go b/cmd/frostfs-lens/internal/tui/detailed.go new file mode 100644 index 0000000000..b2d897230a --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/detailed.go @@ -0,0 +1,24 @@ +package tui + +import ( + "context" + + "github.com/rivo/tview" +) + +type DetailedView struct { + *tview.TextView +} + +func NewDetailedView(detailed string) *DetailedView { + v := &DetailedView{ + TextView: tview.NewTextView(), + } + v.SetDynamicColors(true) + v.SetText(detailed) + return v +} + +func (v *DetailedView) Mount(_ context.Context) error { return nil } +func (v *DetailedView) Update(_ context.Context) error { return nil } +func (v *DetailedView) Unmount() {} diff --git a/cmd/frostfs-lens/internal/tui/filter.go b/cmd/frostfs-lens/internal/tui/filter.go new file mode 100644 index 0000000000..e7879eca71 --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/filter.go @@ -0,0 +1,44 @@ +package tui + +import ( + "maps" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" +) + +type Filter struct { + values map[string]any + results map[string]common.FilterResult +} + +func NewFilter(values map[string]any) *Filter { + f := &Filter{ + values: maps.Clone(values), + results: make(map[string]common.FilterResult), + } + for tag := range values { + f.results[tag] = common.No + } + return f +} + +func (f *Filter) Apply(e common.SchemaEntry) *Filter { + filter := &Filter{ + values: f.values, + results: maps.Clone(f.results), + } + + for tag, value := range filter.values { + filter.results[tag] = max(filter.results[tag], e.Filter(tag, value)) + } + + return filter +} + +func (f *Filter) Result() common.FilterResult { + current := common.Yes + for _, r := range f.results { + current = min(r, current) + } + return current +} diff --git a/cmd/frostfs-lens/internal/tui/input.go b/cmd/frostfs-lens/internal/tui/input.go new file mode 100644 index 0000000000..4fdf97119c --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/input.go @@ -0,0 +1,77 @@ +package tui + +import ( + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +type InputFieldWithHistory struct { + *tview.InputField + history []string + historyLimit int + historyPointer int + currentContent string +} + +func NewInputFieldWithHistory(historyLimit int) *InputFieldWithHistory { + return &InputFieldWithHistory{ + InputField: tview.NewInputField(), + historyLimit: historyLimit, + } +} + +func (f *InputFieldWithHistory) AddToHistory(s string) { + // Stop scrolling history on history change, need to start scrolling again. + defer func() { f.historyPointer = len(f.history) }() + + // Used history data for search prompt, so just make that data recent. + if f.historyPointer != len(f.history) && s == f.history[f.historyPointer] { + f.history = append(f.history[:f.historyPointer], f.history[f.historyPointer+1:]...) + f.history = append(f.history, s) + } + + if len(f.history) == f.historyLimit { + f.history = f.history[1:] + } + f.history = append(f.history, s) +} + +func (f *InputFieldWithHistory) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { + return f.WrapInputHandler(func(event *tcell.EventKey, _ func(tview.Primitive)) { + switch event.Key() { + case tcell.KeyDown: + if len(f.history) == 0 { + return + } + // Need to start iterating before. + if f.historyPointer == len(f.history) { + return + } + // Iterate to most recent prompts. + f.historyPointer++ + // Stop iterating over history. + if f.historyPointer == len(f.history) { + f.InputField.SetText(f.currentContent) + return + } + f.InputField.SetText(f.history[f.historyPointer]) + case tcell.KeyUp: + if len(f.history) == 0 { + return + } + // Start iterating over history. + if f.historyPointer == len(f.history) { + f.currentContent = f.InputField.GetText() + } + // End of history. + if f.historyPointer == 0 { + return + } + // Iterate to least recent prompts. + f.historyPointer-- + f.InputField.SetText(f.history[f.historyPointer]) + default: + f.InputField.InputHandler()(event, func(tview.Primitive) {}) + } + }) +} diff --git a/cmd/frostfs-lens/internal/tui/loading.go b/cmd/frostfs-lens/internal/tui/loading.go new file mode 100644 index 0000000000..4b9384ad45 --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/loading.go @@ -0,0 +1,72 @@ +package tui + +import ( + "context" + "fmt" + "sync/atomic" + "time" + + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +type LoadingBar struct { + *tview.Box + view *tview.TextView + secondsElapsed atomic.Int64 + needDrawFunc func() + reset func() +} + +func NewLoadingBar(needDrawFunc func()) *LoadingBar { + b := &LoadingBar{ + Box: tview.NewBox(), + view: tview.NewTextView(), + needDrawFunc: needDrawFunc, + } + b.view.SetBackgroundColor(tview.Styles.PrimaryTextColor) + b.view.SetTextColor(b.GetBackgroundColor()) + + return b +} + +func (b *LoadingBar) Start(ctx context.Context) { + ctx, b.reset = context.WithCancel(ctx) + + go func() { + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + b.secondsElapsed.Store(0) + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + b.secondsElapsed.Add(1) + b.needDrawFunc() + } + } + }() +} + +func (b *LoadingBar) Stop() { + b.reset() +} + +func (b *LoadingBar) Draw(screen tcell.Screen) { + seconds := b.secondsElapsed.Load() + + var time string + switch { + case seconds < 60: + time = fmt.Sprintf("%ds", seconds) + default: + time = fmt.Sprintf("%dm%ds", seconds/60, seconds%60) + } + b.view.SetText(fmt.Sprintf(" Loading... %s (press Escape to cancel) ", time)) + + x, y, width, _ := b.GetInnerRect() + b.view.SetRect(x, y, width, 1) + b.view.Draw(screen) +} diff --git a/cmd/frostfs-lens/internal/tui/records.go b/cmd/frostfs-lens/internal/tui/records.go new file mode 100644 index 0000000000..5f53ed287b --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/records.go @@ -0,0 +1,271 @@ +package tui + +import ( + "context" + "errors" + "fmt" + "math" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +type updateType int + +const ( + other updateType = iota + moveToPrevPage + moveToNextPage + moveUp + moveDown + moveHome + moveEnd +) + +type RecordsView struct { + *tview.Box + + mu sync.RWMutex + + onUnmount func() + + bucket *Bucket + records []*Record + + buffer chan *Record + + firstRecordIndex int + lastRecordIndex int + selectedRecordIndex int + + updateType updateType + + ui *UI + filter *Filter +} + +func NewRecordsView(ui *UI, bucket *Bucket, filter *Filter) *RecordsView { + return &RecordsView{ + Box: tview.NewBox(), + bucket: bucket, + ui: ui, + filter: filter, + } +} + +func (v *RecordsView) Mount(ctx context.Context) error { + if v.onUnmount != nil { + return errors.New("try to mount already mounted component") + } + + ctx, v.onUnmount = context.WithCancel(ctx) + + tempBuffer, err := LoadRecords(ctx, v.ui.db, v.bucket.Path, v.ui.loadBufferSize) + if err != nil { + return err + } + + v.buffer = make(chan *Record, v.ui.loadBufferSize) + go func() { + defer close(v.buffer) + + for item := range tempBuffer { + if item.err != nil { + v.ui.stopOnError(err) + break + } + record := item.val + + record.Entry, _, err = v.bucket.NextParser(record.Key, record.Value) + if err != nil { + v.ui.stopOnError(err) + break + } + + if v.filter.Apply(record.Entry).Result() != common.Yes { + continue + } + + v.buffer <- record + } + }() + + return nil +} + +func (v *RecordsView) Unmount() { + if v.onUnmount == nil { + panic("try to unmount not mounted component") + } + v.onUnmount() + v.onUnmount = nil +} + +func (v *RecordsView) Update(ctx context.Context) error { + _, _, _, recordsPerPage := v.GetInnerRect() + firstRecordIndex, lastRecordIndex, selectedRecordIndex := v.getNewIndexes() + +loop: + for len(v.records) < lastRecordIndex { + select { + case <-ctx.Done(): + return nil + case record, ok := <-v.buffer: + if !ok { + break loop + } + v.records = append(v.records, record) + } + } + + // Set the update type to its default value after some specific key event + // has been handled. + v.updateType = other + + firstRecordIndex = max(0, min(firstRecordIndex, len(v.records)-recordsPerPage)) + lastRecordIndex = min(firstRecordIndex+recordsPerPage, len(v.records)) + selectedRecordIndex = min(selectedRecordIndex, lastRecordIndex-1) + + v.mu.Lock() + v.firstRecordIndex = firstRecordIndex + v.lastRecordIndex = lastRecordIndex + v.selectedRecordIndex = selectedRecordIndex + v.mu.Unlock() + + return nil +} + +func (v *RecordsView) getNewIndexes() (int, int, int) { + v.mu.RLock() + firstRecordIndex := v.firstRecordIndex + lastRecordIndex := v.lastRecordIndex + selectedRecordIndex := v.selectedRecordIndex + v.mu.RUnlock() + + _, _, _, recordsPerPage := v.GetInnerRect() + + switch v.updateType { + case moveUp: + if selectedRecordIndex != firstRecordIndex { + selectedRecordIndex-- + break + } + firstRecordIndex = max(0, firstRecordIndex-1) + lastRecordIndex = min(firstRecordIndex+recordsPerPage, len(v.records)) + selectedRecordIndex = firstRecordIndex + case moveToPrevPage: + if selectedRecordIndex != firstRecordIndex { + selectedRecordIndex = firstRecordIndex + break + } + firstRecordIndex = max(0, firstRecordIndex-recordsPerPage) + lastRecordIndex = firstRecordIndex + recordsPerPage + selectedRecordIndex = firstRecordIndex + case moveDown: + if selectedRecordIndex != lastRecordIndex-1 { + selectedRecordIndex++ + break + } + firstRecordIndex++ + lastRecordIndex++ + selectedRecordIndex++ + case moveToNextPage: + if selectedRecordIndex != lastRecordIndex-1 { + selectedRecordIndex = lastRecordIndex - 1 + break + } + firstRecordIndex += recordsPerPage + lastRecordIndex = firstRecordIndex + recordsPerPage + selectedRecordIndex = lastRecordIndex - 1 + case moveHome: + firstRecordIndex = 0 + lastRecordIndex = firstRecordIndex + recordsPerPage + selectedRecordIndex = 0 + case moveEnd: + lastRecordIndex = math.MaxInt32 + firstRecordIndex = lastRecordIndex - recordsPerPage + selectedRecordIndex = lastRecordIndex - 1 + default: + lastRecordIndex = firstRecordIndex + recordsPerPage + } + + return firstRecordIndex, lastRecordIndex, selectedRecordIndex +} + +func (v *RecordsView) GetInnerRect() (int, int, int, int) { + x, y, width, height := v.Box.GetInnerRect() + + // Left padding. + x = min(x+3, x+width-1) + width = max(width-3, 0) + + return x, y, width, height +} + +func (v *RecordsView) Draw(screen tcell.Screen) { + v.mu.RLock() + firstRecordIndex := v.firstRecordIndex + lastRecordIndex := v.lastRecordIndex + selectedRecordIndex := v.selectedRecordIndex + records := v.records + v.mu.RUnlock() + + v.DrawForSubclass(screen, v) + + x, y, width, height := v.GetInnerRect() + if height == 0 { + return + } + + // No records in that bucket. + if firstRecordIndex == lastRecordIndex { + tview.Print( + screen, "Empty Bucket", x, y, width, tview.AlignCenter, tview.Styles.PrimaryTextColor, + ) + return + } + + for index := firstRecordIndex; index < lastRecordIndex; index++ { + result := records[index].Entry + text := result.String() + + if index == selectedRecordIndex { + text = fmt.Sprintf("[:white]%s[:-]", text) + tview.Print(screen, text, x, y, width, tview.AlignLeft, tview.Styles.PrimitiveBackgroundColor) + } else { + tview.Print(screen, text, x, y, width, tview.AlignLeft, tview.Styles.PrimaryTextColor) + } + + y++ + } +} + +func (v *RecordsView) InputHandler() func(event *tcell.EventKey, _ func(p tview.Primitive)) { + return v.WrapInputHandler(func(event *tcell.EventKey, _ func(p tview.Primitive)) { + switch m, k := event.Modifiers(), event.Key(); { + case m == 0 && k == tcell.KeyPgUp: + v.updateType = moveToPrevPage + case m == 0 && k == tcell.KeyPgDn: + v.updateType = moveToNextPage + case m == 0 && k == tcell.KeyUp: + v.updateType = moveUp + case m == 0 && k == tcell.KeyDown: + v.updateType = moveDown + case m == 0 && k == tcell.KeyHome: + v.updateType = moveHome + case m == 0 && k == tcell.KeyEnd: + v.updateType = moveEnd + case k == tcell.KeyEnter: + v.mu.RLock() + selectedRecordIndex := v.selectedRecordIndex + records := v.records + v.mu.RUnlock() + if len(records) != 0 { + current := records[selectedRecordIndex] + v.ui.moveNextPage(NewDetailedView(current.Entry.DetailedString())) + } + } + }) +} diff --git a/cmd/frostfs-lens/internal/tui/types.go b/cmd/frostfs-lens/internal/tui/types.go new file mode 100644 index 0000000000..4a227fe64a --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/types.go @@ -0,0 +1,18 @@ +package tui + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" +) + +type Bucket struct { + Name []byte + Path [][]byte + Entry common.SchemaEntry + NextParser common.Parser +} + +type Record struct { + Key, Value []byte + Path [][]byte + Entry common.SchemaEntry +} diff --git a/cmd/frostfs-lens/internal/tui/ui.go b/cmd/frostfs-lens/internal/tui/ui.go new file mode 100644 index 0000000000..701f2b3316 --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/ui.go @@ -0,0 +1,548 @@ +package tui + +import ( + "context" + "errors" + "fmt" + "strings" + "sync/atomic" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + "github.com/davecgh/go-spew/spew" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" + "go.etcd.io/bbolt" +) + +type Config struct { + LoadBufferSize int + SearchHistorySize int + LoadingIndicatorLag time.Duration +} + +var DefaultConfig = Config{ + LoadBufferSize: 100, + SearchHistorySize: 100, + LoadingIndicatorLag: 500 * time.Millisecond, +} + +type Primitive interface { + tview.Primitive + + Mount(ctx context.Context) error + Update(ctx context.Context) error + Unmount() +} + +type UI struct { + *tview.Box + + // Need to use context while updating pages those read data from a database. + // Context should be shared among all mount and updates. Current TUI library + // doesn't use contexts at all, so I do that feature by myself. + //nolint:containedctx + ctx context.Context + onStop func() + + app *tview.Application + db *bbolt.DB + + pageHistory []Primitive + mountedPage Primitive + + pageToMount Primitive + + pageStub tview.Primitive + + infoBar *tview.TextView + searchBar *InputFieldWithHistory + loadingBar *LoadingBar + helpBar *tview.TextView + + searchErrorBar *tview.TextView + + isSearching bool + isLoading atomic.Bool + isShowingError bool + isShowingHelp bool + + loadBufferSize int + + rootParser common.Parser + + loadingIndicatorLag time.Duration + + cancelLoading func() + + filters map[string]func(string) (any, error) + compositeFilters map[string]func(string) (map[string]any, error) + filterHints map[string]string +} + +func NewUI( + ctx context.Context, + app *tview.Application, + db *bbolt.DB, + rootParser common.Parser, + cfg *Config, +) *UI { + spew.Config.DisableMethods = true + + if cfg == nil { + cfg = &DefaultConfig + } + + ui := &UI{ + Box: tview.NewBox(), + + app: app, + db: db, + rootParser: rootParser, + + filters: make(map[string]func(string) (any, error)), + compositeFilters: make(map[string]func(string) (map[string]any, error)), + filterHints: make(map[string]string), + + loadBufferSize: cfg.LoadBufferSize, + loadingIndicatorLag: cfg.LoadingIndicatorLag, + } + + ui.ctx, ui.onStop = context.WithCancel(ctx) + + backgroundColor := ui.GetBackgroundColor() + textColor := tview.Styles.PrimaryTextColor + + inverseBackgroundColor := textColor + inverseTextColor := backgroundColor + + alertTextColor := tcell.ColorRed + + ui.pageStub = tview.NewBox() + + ui.infoBar = tview.NewTextView() + ui.infoBar.SetBackgroundColor(inverseBackgroundColor) + ui.infoBar.SetTextColor(inverseTextColor) + ui.infoBar.SetText( + fmt.Sprintf(" %s (press h for help, q to quit) ", db.Path()), + ) + + ui.searchBar = NewInputFieldWithHistory(cfg.SearchHistorySize) + ui.searchBar.SetFieldBackgroundColor(backgroundColor) + ui.searchBar.SetFieldTextColor(textColor) + ui.searchBar.SetLabelColor(textColor) + ui.searchBar.Focus(nil) + ui.searchBar.SetLabel("/") + + ui.searchErrorBar = tview.NewTextView() + ui.searchErrorBar.SetBackgroundColor(backgroundColor) + ui.searchErrorBar.SetTextColor(alertTextColor) + + ui.helpBar = tview.NewTextView() + ui.helpBar.SetBackgroundColor(inverseBackgroundColor) + ui.helpBar.SetTextColor(inverseTextColor) + ui.helpBar.SetText(" Press Enter for next page or Escape to exit help ") + + ui.loadingBar = NewLoadingBar(ui.triggerDraw) + + ui.pageToMount = NewBucketsView(ui, NewFilter(nil)) + + return ui +} + +func (ui *UI) checkFilterExists(typ string) bool { + if _, ok := ui.filters[typ]; ok { + return true + } + if _, ok := ui.compositeFilters[typ]; ok { + return true + } + return false +} + +func (ui *UI) AddFilter( + typ string, + parser func(string) (any, error), + helpHint string, +) error { + if ui.checkFilterExists(typ) { + return fmt.Errorf("filter %s already exists", typ) + } + ui.filters[typ] = parser + ui.filterHints[typ] = helpHint + return nil +} + +func (ui *UI) AddCompositeFilter( + typ string, + parser func(string) (map[string]any, error), + helpHint string, +) error { + if ui.checkFilterExists(typ) { + return fmt.Errorf("filter %s already exists", typ) + } + ui.compositeFilters[typ] = parser + ui.filterHints[typ] = helpHint + return nil +} + +func (ui *UI) stopOnError(err error) { + if err != nil { + ui.onStop() + ui.app.QueueEvent(tcell.NewEventError(err)) + } +} + +func (ui *UI) stop() { + ui.onStop() + ui.app.Stop() +} + +func (ui *UI) movePrevPage() { + if len(ui.pageHistory) != 0 { + ui.mountedPage.Unmount() + ui.mountedPage = ui.pageHistory[len(ui.pageHistory)-1] + ui.pageHistory = ui.pageHistory[:len(ui.pageHistory)-1] + ui.triggerDraw() + } +} + +func (ui *UI) moveNextPage(page Primitive) { + ui.pageToMount = page + ui.triggerDraw() +} + +func (ui *UI) triggerDraw() { + go ui.app.QueueUpdateDraw(func() {}) +} + +func (ui *UI) Draw(screen tcell.Screen) { + if ui.isLoading.Load() { + ui.draw(screen) + return + } + + ui.isLoading.Store(true) + + ctx, cancel := context.WithCancel(ui.ctx) + + ready := make(chan struct{}) + go func() { + ui.load(ctx) + + cancel() + close(ready) + ui.isLoading.Store(false) + }() + + select { + case <-ready: + case <-time.After(ui.loadingIndicatorLag): + ui.loadingBar.Start(ui.ctx) + ui.cancelLoading = cancel + + go func() { + <-ready + ui.loadingBar.Stop() + ui.triggerDraw() + }() + } + + ui.draw(screen) +} + +func (ui *UI) load(ctx context.Context) { + if ui.mountedPage == nil && ui.pageToMount == nil { + ui.stop() + return + } + + if ui.pageToMount != nil { + ui.mountAndUpdate(ctx) + } else { + ui.update(ctx) + } +} + +func (ui *UI) draw(screen tcell.Screen) { + ui.DrawForSubclass(screen, ui) + x, y, width, height := ui.GetInnerRect() + + var ( + pageToDraw tview.Primitive + barToDraw tview.Primitive + ) + + switch { + case ui.isShowingHelp: + pageToDraw = ui.pageStub + case ui.mountedPage != nil: + pageToDraw = ui.mountedPage + default: + pageToDraw = ui.pageStub + } + + pageToDraw.SetRect(x, y, width, height-1) + pageToDraw.Draw(screen) + + // Search bar uses cursor and we need to hide it when another bar is drawn. + screen.HideCursor() + + switch { + case ui.isLoading.Load(): + barToDraw = ui.loadingBar + case ui.isSearching: + barToDraw = ui.searchBar + case ui.isShowingError: + barToDraw = ui.searchErrorBar + case ui.isShowingHelp: + barToDraw = ui.helpBar + default: + barToDraw = ui.infoBar + } + + barToDraw.SetRect(x, y+height-1, width, 1) + barToDraw.Draw(screen) +} + +func (ui *UI) mountAndUpdate(ctx context.Context) { + defer func() { + // Operation succeeded or was canceled, either way reset page to mount. + ui.pageToMount = nil + }() + + // Mount should use app global context. + //nolint:contextcheck + err := ui.pageToMount.Mount(ui.ctx) + if err != nil { + ui.stopOnError(err) + return + } + + x, y, width, height := ui.GetInnerRect() + ui.pageToMount.SetRect(x, y, width, height-1) + + s := loadOp(ctx, ui.pageToMount.Update) + if s.err != nil { + ui.pageToMount.Unmount() + ui.stopOnError(s.err) + return + } + // Update was canceled. + if !s.done { + ui.pageToMount.Unmount() + return + } + + if ui.mountedPage != nil { + ui.pageHistory = append(ui.pageHistory, ui.mountedPage) + } + ui.mountedPage = ui.pageToMount +} + +func (ui *UI) update(ctx context.Context) { + x, y, width, height := ui.GetInnerRect() + ui.mountedPage.SetRect(x, y, width, height-1) + + s := loadOp(ctx, ui.mountedPage.Update) + if s.err != nil { + ui.stopOnError(s.err) + return + } +} + +type status struct { + done bool + err error +} + +func loadOp(ctx context.Context, op func(ctx context.Context) error) status { + errCh := make(chan error) + go func() { + errCh <- op(ctx) + }() + + select { + case <-ctx.Done(): + return status{done: false, err: nil} + case err := <-errCh: + return status{done: true, err: err} + } +} + +func (ui *UI) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { + return ui.WrapInputHandler(func(event *tcell.EventKey, _ func(tview.Primitive)) { + switch { + case ui.isLoading.Load(): + ui.handleInputOnLoading(event) + case ui.isShowingHelp: + ui.handleInputOnShowingHelp(event) + case ui.isShowingError: + ui.handleInputOnShowingError() + case ui.isSearching: + ui.handleInputOnSearching(event) + default: + ui.handleInput(event) + } + }) +} + +func (ui *UI) handleInput(event *tcell.EventKey) { + m, k, r := event.Modifiers(), event.Key(), event.Rune() + + switch { + case k == tcell.KeyEsc: + ui.movePrevPage() + case m == 0 && k == tcell.KeyRune && r == 'h': + ui.isShowingHelp = true + case m == 0 && k == tcell.KeyRune && r == '/': + ui.isSearching = true + case m == 0 && k == tcell.KeyRune && r == 'q': + ui.stop() + default: + if ui.mountedPage != nil { + ui.mountedPage.InputHandler()(event, func(tview.Primitive) {}) + } + } +} + +func (ui *UI) handleInputOnLoading(event *tcell.EventKey) { + switch k, r := event.Key(), event.Rune(); { + case k == tcell.KeyEsc: + ui.cancelLoading() + case k == tcell.KeyRune && r == 'q': + ui.stop() + } +} + +func (ui *UI) handleInputOnShowingError() { + ui.isShowingError = false + ui.isSearching = true +} + +func (ui *UI) handleInputOnShowingHelp(event *tcell.EventKey) { + k, r := event.Key(), event.Rune() + + switch { + case k == tcell.KeyEsc: + ui.isShowingHelp = false + case k == tcell.KeyRune && r == 'q': + ui.stop() + default: + } +} + +func (ui *UI) handleInputOnSearching(event *tcell.EventKey) { + m, k := event.Modifiers(), event.Key() + + switch { + case k == tcell.KeyEnter: + prompt := ui.searchBar.GetText() + + res, err := ui.processPrompt(prompt) + if err != nil { + ui.isShowingError = true + ui.isSearching = false + ui.searchErrorBar.SetText(err.Error() + " (press any key to continue)") + return + } + + switch ui.mountedPage.(type) { + case *BucketsView: + ui.moveNextPage(NewBucketsView(ui, res)) + case *RecordsView: + bucket := ui.mountedPage.(*RecordsView).bucket + ui.moveNextPage(NewRecordsView(ui, bucket, res)) + } + + if ui.searchBar.GetText() != "" { + ui.searchBar.AddToHistory(ui.searchBar.GetText()) + } + + ui.searchBar.SetText("") + ui.isSearching = false + case k == tcell.KeyEsc: + ui.isSearching = false + case (k == tcell.KeyBackspace2 || m&tcell.ModCtrl != 0 && k == tcell.KeyETB) && len(ui.searchBar.GetText()) == 0: + ui.isSearching = false + default: + ui.searchBar.InputHandler()(event, func(tview.Primitive) {}) + } + + ui.Box.MouseHandler() +} + +func (ui *UI) WithPrompt(prompt string) error { + filter, err := ui.processPrompt(prompt) + if err != nil { + return err + } + + ui.pageToMount = NewBucketsView(ui, filter) + + if prompt != "" { + ui.searchBar.AddToHistory(prompt) + } + + return nil +} + +func (ui *UI) processPrompt(prompt string) (filter *Filter, err error) { + if prompt == "" { + return NewFilter(nil), nil + } + + filterMap := make(map[string]any) + + for _, filterString := range strings.Split(prompt, "+") { + parts := strings.Split(filterString, ":") + if len(parts) != 2 { + return nil, errors.New("expected 'tag:value [+ tag:value]...'") + } + + filterTag := strings.TrimSpace(parts[0]) + filterValueString := strings.TrimSpace(parts[1]) + + if _, exists := filterMap[filterTag]; exists { + return nil, fmt.Errorf("duplicate filter tag '%s'", filterTag) + } + + parser, ok := ui.filters[filterTag] + if ok { + filterValue, err := parser(filterValueString) + if err != nil { + return nil, fmt.Errorf("can't parse '%s' filter value: %w", filterTag, err) + } + + filterMap[filterTag] = filterValue + continue + } + + compositeParser, ok := ui.compositeFilters[filterTag] + if ok { + compositeFilterValue, err := compositeParser(filterValueString) + if err != nil { + return nil, fmt.Errorf( + "can't parse '%s' filter value '%s': %w", + filterTag, filterValueString, err, + ) + } + + for tag, value := range compositeFilterValue { + if _, exists := filterMap[tag]; exists { + return nil, fmt.Errorf( + "found duplicate filter tag '%s' while processing composite filter with tag '%s'", + tag, filterTag, + ) + } + + filterMap[tag] = value + } + continue + } + + return nil, fmt.Errorf("unknown filter tag '%s'", filterTag) + } + + return NewFilter(filterMap), nil +} diff --git a/cmd/frostfs-lens/internal/tui/util.go b/cmd/frostfs-lens/internal/tui/util.go new file mode 100644 index 0000000000..d4e13b2a9b --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/util.go @@ -0,0 +1,97 @@ +package tui + +import ( + "errors" + "strings" + + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/mr-tron/base58" +) + +func CIDParser(s string) (any, error) { + data, err := base58.Decode(s) + if err != nil { + return nil, err + } + var id cid.ID + if err = id.Decode(data); err != nil { + return nil, err + } + return id, nil +} + +func OIDParser(s string) (any, error) { + data, err := base58.Decode(s) + if err != nil { + return nil, err + } + var id oid.ID + if err = id.Decode(data); err != nil { + return nil, err + } + return id, nil +} + +func AddressParser(s string) (map[string]any, error) { + m := make(map[string]any) + + parts := strings.Split(s, "/") + if len(parts) != 2 { + return nil, errors.New("expected /") + } + cnr, err := CIDParser(parts[0]) + if err != nil { + return nil, err + } + obj, err := OIDParser(parts[1]) + if err != nil { + return nil, err + } + + m["cid"] = cnr + m["oid"] = obj + + return m, nil +} + +func keyParser(s string) (any, error) { + if s == "" { + return nil, errors.New("empty attribute key") + } + return s, nil +} + +func valueParser(s string) (any, error) { + if s == "" { + return nil, errors.New("empty attribute value") + } + return s, nil +} + +func AttributeParser(s string) (map[string]any, error) { + m := make(map[string]any) + + parts := strings.Split(s, "/") + if len(parts) != 1 && len(parts) != 2 { + return nil, errors.New("expected or /") + } + + key, err := keyParser(parts[0]) + if err != nil { + return nil, err + } + m["key"] = key + + if len(parts) == 1 { + return m, nil + } + + value, err := valueParser(parts[1]) + if err != nil { + return nil, err + } + m["value"] = value + + return m, nil +} diff --git a/go.mod b/go.mod index be3c6e74df..93eef5b8c8 100644 --- a/go.mod +++ b/go.mod @@ -32,6 +32,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 github.com/prometheus/client_golang v1.19.0 + github.com/rivo/tview v0.0.0-20240625185742-b0a7293b8130 github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 @@ -106,7 +107,7 @@ require ( github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect - github.com/rivo/uniseg v0.4.4 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.11.0 // indirect diff --git a/go.sum b/go.sum index d0218a348b..102501484d 100644 --- a/go.sum +++ b/go.sum @@ -223,10 +223,12 @@ github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSz github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/rivo/tview v0.0.0-20240625185742-b0a7293b8130 h1:o1CYtoFOm6xJK3DvDAEG5wDJPLj+SoxUtUDFaQgt1iY= +github.com/rivo/tview v0.0.0-20240625185742-b0a7293b8130/go.mod h1:02iFIz7K/A9jGCvrizLPvoqr4cEIx7q54RH5Qudkrss= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= From e6553363905ef350b9faf12e7a42d52cf624815c Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 16 Aug 2024 17:27:35 +0300 Subject: [PATCH 0781/1413] [#1223] lens/tui: Add app help Signed-off-by: Aleksey Savchuk --- .../internal/tui/help-pages/hotkeys.txt | 38 +++++++ .../internal/tui/help-pages/searching.txt | 26 +++++ cmd/frostfs-lens/internal/tui/help.go | 101 ++++++++++++++++++ cmd/frostfs-lens/internal/tui/ui.go | 15 ++- 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 cmd/frostfs-lens/internal/tui/help-pages/hotkeys.txt create mode 100644 cmd/frostfs-lens/internal/tui/help-pages/searching.txt create mode 100644 cmd/frostfs-lens/internal/tui/help.go diff --git a/cmd/frostfs-lens/internal/tui/help-pages/hotkeys.txt b/cmd/frostfs-lens/internal/tui/help-pages/hotkeys.txt new file mode 100644 index 0000000000..c371b34e94 --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/help-pages/hotkeys.txt @@ -0,0 +1,38 @@ +[green::b]HOTKEYS[-::-] + + [green::b]Navigation[-::-] + + [yellow::b]Down Arrow[-::-] / [yellow::b]j[-::-] + Scroll down. + + [yellow::b]Up Arrow[-::-] / [yellow::b]k[-::-] + Scroll up. + + [yellow::b]Page Down[-::-] / [yellow::b]Ctrl-f[-::-] + Scroll down by a full page. + + [yellow::b]Page Up[-::-] / [yellow::b]Ctrl-b[-::-] + Scroll up by a full page. + + [green::b]Actions[-::-] + + [yellow::b]Enter[-::-] + Perform actions based on the current context: + - In Buckets View: + - Expand/collapse the selected bucket to show/hide its nested buckets. + - If no nested buckets exist, navigate to the selected bucket's records. + - In Records View: Open the detailed view of the selected record. + + [yellow::b]Escape[-::-] + Return to the previous page, opposite of [yellow::b]Enter[-::-]. + + Refer to the [green::b]SEARCHING[-::-] section for more specific actions. + + + [green::b]Alternative Action Hotkeys[-::-] + + [yellow::b]Ctrl-r[-::-] + Directly navigate to the selected bucket's records. + + [yellow::b]Ctrl-d[-::-] + Access the detailed view of the selected bucket. diff --git a/cmd/frostfs-lens/internal/tui/help-pages/searching.txt b/cmd/frostfs-lens/internal/tui/help-pages/searching.txt new file mode 100644 index 0000000000..bc2be512b1 --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/help-pages/searching.txt @@ -0,0 +1,26 @@ +[green::b]SEARCHING[-::-] + + [green::b]Hotkeys[-::-] + + [yellow::b]/[-::-] + Initiate the search prompt. + - The prompt follows this syntax: [yellow::b]tag:value [+ tag:value]...[-::-] + - Multiple filter can be combined with [yellow::b]+[-::-], the result is an intersection of those filters' result sets. + - Any leading and trailing whitespace will be ignored. + - An empty prompt will return all results with no filters applied. + - Refer to the [green::b]Available Search Filters[-::-] section below for a list of valid filter tags. + + [yellow::b]Enter[-::-] + Execute the search based on the entered prompt. + - If the prompt is invalid, an error message will be displayed. + + [yellow::b]Escape[-::-] + Exit the search prompt without performing a search. + + [yellow::b]Down Arrow[-::-], [yellow::b]Up Arrow[-::-] + Scroll through the search history. + + + [green::b]Available Search Filters[-::-] + +%s diff --git a/cmd/frostfs-lens/internal/tui/help.go b/cmd/frostfs-lens/internal/tui/help.go new file mode 100644 index 0000000000..3ab8fede02 --- /dev/null +++ b/cmd/frostfs-lens/internal/tui/help.go @@ -0,0 +1,101 @@ +package tui + +import ( + _ "embed" + "fmt" + "strings" + + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +var ( + //go:embed help-pages/hotkeys.txt + hotkeysHelpText string + + //go:embed help-pages/searching.txt + searchingHelpText string +) + +type HelpPage struct { + *tview.Box + pages []*tview.TextView + currentPage int + + filters []string + filterHints map[string]string +} + +func NewHelpPage(filters []string, hints map[string]string) *HelpPage { + hp := &HelpPage{ + Box: tview.NewBox(), + filters: filters, + filterHints: hints, + } + + page := tview.NewTextView(). + SetDynamicColors(true). + SetText(hotkeysHelpText) + hp.addPage(page) + + page = tview.NewTextView(). + SetDynamicColors(true). + SetText(fmt.Sprintf(searchingHelpText, hp.getFiltersText())) + hp.addPage(page) + + return hp +} + +func (hp *HelpPage) addPage(page *tview.TextView) { + hp.pages = append(hp.pages, page) +} + +func (hp *HelpPage) getFiltersText() string { + if len(hp.filters) == 0 { + return "\t\tNo filters defined.\n" + } + + filtersText := strings.Builder{} + gapSize := 4 + + tagMaxWidth := 3 + for _, filter := range hp.filters { + tagMaxWidth = max(tagMaxWidth, len(filter)) + } + filtersText.WriteString("\t\t[yellow::b]Tag") + filtersText.WriteString(strings.Repeat(" ", gapSize)) + filtersText.WriteString("\tValue[-::-]\n\n") + + for _, filter := range hp.filters { + filtersText.WriteString("\t\t") + filtersText.WriteString(filter) + filtersText.WriteString(strings.Repeat(" ", tagMaxWidth-len(filter)+gapSize)) + filtersText.WriteString(hp.filterHints[filter]) + filtersText.WriteRune('\n') + } + + return filtersText.String() +} + +func (hp *HelpPage) Draw(screen tcell.Screen) { + x, y, width, height := hp.GetInnerRect() + hp.pages[hp.currentPage].SetRect(x+1, y+1, width-2, height-2) + hp.pages[hp.currentPage].Draw(screen) +} + +func (hp *HelpPage) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) { + return hp.WrapInputHandler(func(event *tcell.EventKey, _ func(tview.Primitive)) { + if event.Key() == tcell.KeyEnter { + hp.currentPage++ + hp.currentPage %= len(hp.pages) + return + } + hp.pages[hp.currentPage].InputHandler()(event, func(tview.Primitive) {}) + }) +} + +func (hp *HelpPage) MouseHandler() func(action tview.MouseAction, event *tcell.EventMouse, setFocus func(p tview.Primitive)) (consumed bool, capture tview.Primitive) { + return hp.WrapMouseHandler(func(action tview.MouseAction, event *tcell.EventMouse, _ func(tview.Primitive)) (consumed bool, capture tview.Primitive) { + return hp.pages[hp.currentPage].MouseHandler()(action, event, func(tview.Primitive) {}) + }) +} diff --git a/cmd/frostfs-lens/internal/tui/ui.go b/cmd/frostfs-lens/internal/tui/ui.go index 701f2b3316..bcc082821c 100644 --- a/cmd/frostfs-lens/internal/tui/ui.go +++ b/cmd/frostfs-lens/internal/tui/ui.go @@ -60,6 +60,8 @@ type UI struct { loadingBar *LoadingBar helpBar *tview.TextView + helpPage *HelpPage + searchErrorBar *tview.TextView isSearching bool @@ -275,7 +277,17 @@ func (ui *UI) draw(screen tcell.Screen) { switch { case ui.isShowingHelp: - pageToDraw = ui.pageStub + if ui.helpPage == nil { + var filters []string + for f := range ui.filters { + filters = append(filters, f) + } + for f := range ui.compositeFilters { + filters = append(filters, f) + } + ui.helpPage = NewHelpPage(filters, ui.filterHints) + } + pageToDraw = ui.helpPage case ui.mountedPage != nil: pageToDraw = ui.mountedPage default: @@ -429,6 +441,7 @@ func (ui *UI) handleInputOnShowingHelp(event *tcell.EventKey) { case k == tcell.KeyRune && r == 'q': ui.stop() default: + ui.helpPage.InputHandler()(event, func(tview.Primitive) {}) } } From 371d97f61adc7cc74da815764a75a5438e865eda Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 19 Aug 2024 18:02:11 +0300 Subject: [PATCH 0782/1413] [#1223] lens/tui: Add TUI app for write cache Signed-off-by: Aleksey Savchuk --- cmd/frostfs-lens/internal/writecache/root.go | 2 +- cmd/frostfs-lens/internal/writecache/tui.go | 79 ++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 cmd/frostfs-lens/internal/writecache/tui.go diff --git a/cmd/frostfs-lens/internal/writecache/root.go b/cmd/frostfs-lens/internal/writecache/root.go index eb3b325b6c..d7d6db240f 100644 --- a/cmd/frostfs-lens/internal/writecache/root.go +++ b/cmd/frostfs-lens/internal/writecache/root.go @@ -17,5 +17,5 @@ var Root = &cobra.Command{ } func init() { - Root.AddCommand(listCMD, inspectCMD) + Root.AddCommand(listCMD, inspectCMD, tuiCMD) } diff --git a/cmd/frostfs-lens/internal/writecache/tui.go b/cmd/frostfs-lens/internal/writecache/tui.go new file mode 100644 index 0000000000..6b7532b08a --- /dev/null +++ b/cmd/frostfs-lens/internal/writecache/tui.go @@ -0,0 +1,79 @@ +package writecache + +import ( + "context" + "fmt" + + common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" + schema "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/writecache" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/tui" + "github.com/rivo/tview" + "github.com/spf13/cobra" + "go.etcd.io/bbolt" +) + +var tuiCMD = &cobra.Command{ + Use: "explore", + Short: "Write cache exploration with a terminal UI", + Long: `Launch a terminal UI to explore write cache and search for data. + +Available search filters: +- cid CID +- oid OID +- addr CID/OID +`, + Run: tuiFunc, +} + +var initialPrompt string + +func init() { + common.AddComponentPathFlag(tuiCMD, &vPath) + + tuiCMD.Flags().StringVar( + &initialPrompt, + "filter", + "", + "Filter prompt to start with, format 'tag:value [+ tag:value]...'", + ) +} + +func tuiFunc(cmd *cobra.Command, _ []string) { + common.ExitOnErr(cmd, runTUI(cmd)) +} + +func runTUI(cmd *cobra.Command) error { + db, err := openDB(false) + if err != nil { + return fmt.Errorf("couldn't open database: %w", err) + } + defer db.Close() + + ctx, cancel := context.WithCancel(cmd.Context()) + defer cancel() + + app := tview.NewApplication() + ui := tui.NewUI(ctx, app, db, schema.WritecacheParser, nil) + + _ = ui.AddFilter("cid", tui.CIDParser, "CID") + _ = ui.AddFilter("oid", tui.OIDParser, "OID") + _ = ui.AddCompositeFilter("addr", tui.AddressParser, "CID/OID") + + err = ui.WithPrompt(initialPrompt) + if err != nil { + return fmt.Errorf("invalid filter prompt: %w", err) + } + + app.SetRoot(ui, true).SetFocus(ui) + return app.Run() +} + +func openDB(writable bool) (*bbolt.DB, error) { + db, err := bbolt.Open(vPath, 0o600, &bbolt.Options{ + ReadOnly: !writable, + }) + if err != nil { + return nil, err + } + return db, nil +} From 7768a482b595e578570f6b3c705b6f7754705fab Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 22 Aug 2024 15:07:51 +0300 Subject: [PATCH 0783/1413] [#1223] lens/tui: Add TUI app for blobovnicza Signed-off-by: Aleksey Savchuk --- cmd/frostfs-lens/internal/blobovnicza/root.go | 2 +- cmd/frostfs-lens/internal/blobovnicza/tui.go | 79 ++++++++++++++ .../internal/schema/blobovnicza/parsers.go | 96 +++++++++++++++++ .../internal/schema/blobovnicza/types.go | 101 ++++++++++++++++++ 4 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 cmd/frostfs-lens/internal/blobovnicza/tui.go create mode 100644 cmd/frostfs-lens/internal/schema/blobovnicza/parsers.go create mode 100644 cmd/frostfs-lens/internal/schema/blobovnicza/types.go diff --git a/cmd/frostfs-lens/internal/blobovnicza/root.go b/cmd/frostfs-lens/internal/blobovnicza/root.go index 0a0cd955d8..9d8ef3dadc 100644 --- a/cmd/frostfs-lens/internal/blobovnicza/root.go +++ b/cmd/frostfs-lens/internal/blobovnicza/root.go @@ -19,7 +19,7 @@ var Root = &cobra.Command{ } func init() { - Root.AddCommand(listCMD, inspectCMD) + Root.AddCommand(listCMD, inspectCMD, tuiCMD) } func openBlobovnicza(cmd *cobra.Command) *blobovnicza.Blobovnicza { diff --git a/cmd/frostfs-lens/internal/blobovnicza/tui.go b/cmd/frostfs-lens/internal/blobovnicza/tui.go new file mode 100644 index 0000000000..eb4a5ff598 --- /dev/null +++ b/cmd/frostfs-lens/internal/blobovnicza/tui.go @@ -0,0 +1,79 @@ +package blobovnicza + +import ( + "context" + "fmt" + + common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" + schema "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/blobovnicza" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/tui" + "github.com/rivo/tview" + "github.com/spf13/cobra" + "go.etcd.io/bbolt" +) + +var tuiCMD = &cobra.Command{ + Use: "explore", + Short: "Blobovnicza exploration with a terminal UI", + Long: `Launch a terminal UI to explore blobovnicza and search for data. + +Available search filters: +- cid CID +- oid OID +- addr CID/OID +`, + Run: tuiFunc, +} + +var initialPrompt string + +func init() { + common.AddComponentPathFlag(tuiCMD, &vPath) + + tuiCMD.Flags().StringVar( + &initialPrompt, + "filter", + "", + "Filter prompt to start with, format 'tag:value [+ tag:value]...'", + ) +} + +func tuiFunc(cmd *cobra.Command, _ []string) { + common.ExitOnErr(cmd, runTUI(cmd)) +} + +func runTUI(cmd *cobra.Command) error { + db, err := openDB(false) + if err != nil { + return fmt.Errorf("couldn't open database: %w", err) + } + defer db.Close() + + ctx, cancel := context.WithCancel(cmd.Context()) + defer cancel() + + app := tview.NewApplication() + ui := tui.NewUI(ctx, app, db, schema.BlobovniczaParser, nil) + + _ = ui.AddFilter("cid", tui.CIDParser, "CID") + _ = ui.AddFilter("oid", tui.OIDParser, "OID") + _ = ui.AddCompositeFilter("addr", tui.AddressParser, "CID/OID") + + err = ui.WithPrompt(initialPrompt) + if err != nil { + return fmt.Errorf("invalid filter prompt: %w", err) + } + + app.SetRoot(ui, true).SetFocus(ui) + return app.Run() +} + +func openDB(writable bool) (*bbolt.DB, error) { + db, err := bbolt.Open(vPath, 0o600, &bbolt.Options{ + ReadOnly: !writable, + }) + if err != nil { + return nil, err + } + return db, nil +} diff --git a/cmd/frostfs-lens/internal/schema/blobovnicza/parsers.go b/cmd/frostfs-lens/internal/schema/blobovnicza/parsers.go new file mode 100644 index 0000000000..02b6cf4140 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/blobovnicza/parsers.go @@ -0,0 +1,96 @@ +package blobovnicza + +import ( + "encoding/binary" + "errors" + "fmt" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/mr-tron/base58" +) + +var BlobovniczaParser = common.WithFallback( + common.Any( + MetaBucketParser, + BucketParser, + ), + common.RawParser.ToFallbackParser(), +) + +func MetaBucketParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, errors.New("not a bucket") + } + + if string(key) != "META" { + return nil, nil, errors.New("invalid bucket name") + } + + return &MetaBucket{}, MetaRecordParser, nil +} + +func MetaRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + var r MetaRecord + + if len(key) == 0 { + return nil, nil, errors.New("invalid key") + } + + r.label = string(key) + r.count = binary.LittleEndian.Uint64(value) + + return &r, nil, nil +} + +func BucketParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if value != nil { + return nil, nil, errors.New("not a bucket") + } + + size, n := binary.Varint(key) + if n <= 0 { + return nil, nil, errors.New("invalid size") + } + + return &Bucket{size: size}, RecordParser, nil +} + +func RecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + parts := strings.Split(string(key), "/") + + if len(parts) != 2 { + return nil, nil, errors.New("invalid key, expected address string /") + } + + cnrRaw, err := base58.Decode(parts[0]) + if err != nil { + return nil, nil, errors.New("can't decode CID string") + } + objRaw, err := base58.Decode(parts[1]) + if err != nil { + return nil, nil, errors.New("can't decode OID string") + } + + cnr := cid.ID{} + if err := cnr.Decode(cnrRaw); err != nil { + return nil, nil, fmt.Errorf("can't decode CID: %w", err) + } + obj := oid.ID{} + if err := obj.Decode(objRaw); err != nil { + return nil, nil, fmt.Errorf("can't decode OID: %w", err) + } + + var r Record + + r.addr.SetContainer(cnr) + r.addr.SetObject(obj) + + if err := r.object.Unmarshal(value); err != nil { + return nil, nil, errors.New("can't unmarshal object") + } + + return &r, nil, nil +} diff --git a/cmd/frostfs-lens/internal/schema/blobovnicza/types.go b/cmd/frostfs-lens/internal/schema/blobovnicza/types.go new file mode 100644 index 0000000000..c7ed08cdd0 --- /dev/null +++ b/cmd/frostfs-lens/internal/schema/blobovnicza/types.go @@ -0,0 +1,101 @@ +package blobovnicza + +import ( + "fmt" + "strconv" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/davecgh/go-spew/spew" + "github.com/gdamore/tcell/v2" + "github.com/rivo/tview" +) + +type ( + MetaBucket struct{} + + MetaRecord struct { + label string + count uint64 + } + + Bucket struct { + size int64 + } + + Record struct { + addr oid.Address + object objectSDK.Object + } +) + +func (b *MetaBucket) String() string { + return common.FormatSimple("META", tcell.ColorLime) +} + +func (b *MetaBucket) DetailedString() string { + return spew.Sdump(*b) +} + +func (b *MetaBucket) Filter(string, any) common.FilterResult { + return common.No +} + +func (r *MetaRecord) String() string { + return fmt.Sprintf("%-11s %c %d", r.label, tview.Borders.Vertical, r.count) +} + +func (r *MetaRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *MetaRecord) Filter(string, any) common.FilterResult { + return common.No +} + +func (b *Bucket) String() string { + return common.FormatSimple(strconv.FormatInt(b.size, 10), tcell.ColorLime) +} + +func (b *Bucket) DetailedString() string { + return spew.Sdump(*b) +} + +func (b *Bucket) Filter(typ string, _ any) common.FilterResult { + switch typ { + case "cid": + return common.Maybe + case "oid": + return common.Maybe + default: + return common.No + } +} + +func (r *Record) String() string { + return fmt.Sprintf( + "CID %s OID %s %c Object {...}", + common.FormatSimple(fmt.Sprintf("%-44s", r.addr.Container()), tcell.ColorAqua), + common.FormatSimple(fmt.Sprintf("%-44s", r.addr.Object()), tcell.ColorAqua), + tview.Borders.Vertical, + ) +} + +func (r *Record) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *Record) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return common.IfThenElse(r.addr.Container().Equals(id), common.Yes, common.No) + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.addr.Object().Equals(id), common.Yes, common.No) + default: + return common.No + } +} From b3deb893ba26aa3ec9ce93213cef16243cc0f58d Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 30 Aug 2024 12:09:14 +0300 Subject: [PATCH 0784/1413] [#1310] object: Move target initialization to separate package * Split the logic of write target initialization to different packages; * Refactor patch and put services: since both service initialize the target themselves. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/cache.go | 6 +- cmd/frostfs-node/object.go | 17 +- .../object/{put => common/target}/builder.go | 2 +- .../object/{put => common/target}/pool.go | 2 +- pkg/services/object/common/target/target.go | 170 +++++++++++ .../{put => common/target}/validation.go | 2 +- .../object/{put => common/writer}/common.go | 42 +-- .../writer.go => common/writer/dispatcher.go} | 2 +- .../{put => common/writer}/distributed.go | 70 ++--- .../object/{put => common/writer}/ec.go | 104 +++---- .../object/{put => common/writer}/local.go | 14 +- .../object/{put => common/writer}/remote.go | 12 +- pkg/services/object/common/writer/writer.go | 183 +++++++++++ pkg/services/object/patch/service.go | 25 +- pkg/services/object/patch/streamer.go | 28 +- pkg/services/object/patch/util.go | 19 -- pkg/services/object/put/service.go | 114 ++----- pkg/services/object/put/single.go | 64 ++-- pkg/services/object/put/streamer.go | 289 ++---------------- pkg/services/object/put/v2/streamer.go | 9 +- pkg/services/replicator/process.go | 4 +- pkg/services/replicator/replicator.go | 6 +- 22 files changed, 599 insertions(+), 585 deletions(-) rename pkg/services/object/{put => common/target}/builder.go (98%) rename pkg/services/object/{put => common/target}/pool.go (96%) create mode 100644 pkg/services/object/common/target/target.go rename pkg/services/object/{put => common/target}/validation.go (99%) rename pkg/services/object/{put => common/writer}/common.go (65%) rename pkg/services/object/{put/writer.go => common/writer/dispatcher.go} (97%) rename pkg/services/object/{put => common/writer}/distributed.go (57%) rename pkg/services/object/{put => common/writer}/ec.go (69%) rename pkg/services/object/{put => common/writer}/local.go (81%) rename pkg/services/object/{put => common/writer}/remote.go (92%) create mode 100644 pkg/services/object/common/writer/writer.go diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index 81d552729f..57f65d8735 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -7,7 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -305,11 +305,11 @@ type ttlMaxObjectSizeCache struct { mtx sync.RWMutex lastUpdated time.Time lastSize uint64 - src putsvc.MaxSizeSource + src objectwriter.MaxSizeSource metrics cacheMetrics } -func newCachedMaxObjectSizeSource(src putsvc.MaxSizeSource) putsvc.MaxSizeSource { +func newCachedMaxObjectSizeSource(src objectwriter.MaxSizeSource) objectwriter.MaxSizeSource { return &ttlMaxObjectSizeCache{ src: src, metrics: metrics.NewCacheMetrics("max_object_size"), diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 467c5901b8..610e2c363c 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -24,6 +24,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl" v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" objectAPE "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/ape" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" deletesvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete" deletesvcV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete/v2" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" @@ -188,7 +189,7 @@ func initObjectService(c *cfg) { sDeleteV2 := createDeleteServiceV2(sDelete) - sPatch := createPatchSvc(sGet, sPut, keyStorage) + sPatch := createPatchSvc(sGet, sPut) // build service pipeline // grpc | audit | | signature | response | acl | ape | split @@ -326,7 +327,7 @@ func createReplicator(c *cfg, keyStorage *util.KeyStorage, cache *cache.ClientCa ), replicator.WithLocalStorage(ls), replicator.WithRemoteSender( - putsvc.NewRemoteSender(keyStorage, cache), + objectwriter.NewRemoteSender(keyStorage, cache), ), replicator.WithRemoteGetter( getsvc.NewRemoteGetter(c.clientCache, c.netMapSource, keyStorage), @@ -338,7 +339,7 @@ func createReplicator(c *cfg, keyStorage *util.KeyStorage, cache *cache.ClientCa func createPutSvc(c *cfg, keyStorage *util.KeyStorage, irFetcher *cachedIRFetcher) *putsvc.Service { ls := c.cfgObject.cfgLocalStorage.localStorage - var os putsvc.ObjectStorage = engineWithoutNotifications{ + var os objectwriter.ObjectStorage = engineWithoutNotifications{ engine: ls, } @@ -352,9 +353,9 @@ func createPutSvc(c *cfg, keyStorage *util.KeyStorage, irFetcher *cachedIRFetche c, c.cfgNetmap.state, irFetcher, - putsvc.WithWorkerPools(c.cfgObject.pool.putRemote, c.cfgObject.pool.putLocal), - putsvc.WithLogger(c.log), - putsvc.WithVerifySessionTokenIssuer(!c.cfgObject.skipSessionTokenIssuerVerification), + objectwriter.WithWorkerPools(c.cfgObject.pool.putRemote, c.cfgObject.pool.putLocal), + objectwriter.WithLogger(c.log), + objectwriter.WithVerifySessionTokenIssuer(!c.cfgObject.skipSessionTokenIssuerVerification), ) } @@ -362,8 +363,8 @@ func createPutSvcV2(sPut *putsvc.Service, keyStorage *util.KeyStorage) *putsvcV2 return putsvcV2.NewService(sPut, keyStorage) } -func createPatchSvc(sGet *getsvc.Service, sPut *putsvc.Service, keyStorage *util.KeyStorage) *patchsvc.Service { - return patchsvc.NewService(keyStorage, sGet, sPut) +func createPatchSvc(sGet *getsvc.Service, sPut *putsvc.Service) *patchsvc.Service { + return patchsvc.NewService(sPut.Config, sGet) } func createSearchSvc(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.TraverserGenerator, coreConstructor *cache.ClientCache) *searchsvc.Service { diff --git a/pkg/services/object/put/builder.go b/pkg/services/object/common/target/builder.go similarity index 98% rename from pkg/services/object/put/builder.go rename to pkg/services/object/common/target/builder.go index 64baf4e051..ea68365a75 100644 --- a/pkg/services/object/put/builder.go +++ b/pkg/services/object/common/target/builder.go @@ -1,4 +1,4 @@ -package putsvc +package target import ( "context" diff --git a/pkg/services/object/put/pool.go b/pkg/services/object/common/target/pool.go similarity index 96% rename from pkg/services/object/put/pool.go rename to pkg/services/object/common/target/pool.go index ebe214caf6..71da305adb 100644 --- a/pkg/services/object/put/pool.go +++ b/pkg/services/object/common/target/pool.go @@ -1,4 +1,4 @@ -package putsvc +package target import ( "sync" diff --git a/pkg/services/object/common/target/target.go b/pkg/services/object/common/target/target.go new file mode 100644 index 0000000000..00080ace69 --- /dev/null +++ b/pkg/services/object/common/target/target.go @@ -0,0 +1,170 @@ +package target + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" +) + +func New(prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { + // prepare needed put parameters + if err := preparePrm(prm); err != nil { + return nil, fmt.Errorf("could not prepare put parameters: %w", err) + } + + if prm.Header.Signature() != nil { + return newUntrustedTarget(prm) + } + return newTrustedTarget(prm) +} + +func newUntrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { + maxPayloadSz := prm.Config.MaxSizeSrc.MaxObjectSize() + if maxPayloadSz == 0 { + return nil, errors.New("could not obtain max object size parameter") + } + + if prm.SignRequestPrivateKey == nil { + nodeKey, err := prm.Config.KeyStorage.GetKey(nil) + if err != nil { + return nil, err + } + prm.SignRequestPrivateKey = nodeKey + } + + // prepare untrusted-Put object target + return &validatingPreparedTarget{ + nextTarget: newInMemoryObjectBuilder(objectwriter.New(prm)), + fmt: prm.Config.FormatValidator, + + maxPayloadSz: maxPayloadSz, + }, nil +} + +func newTrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { + maxPayloadSz := prm.Config.MaxSizeSrc.MaxObjectSize() + if maxPayloadSz == 0 { + return nil, errors.New("could not obtain max object size parameter") + } + + sToken := prm.Common.SessionToken() + + // prepare trusted-Put object target + + // get private token from local storage + var sessionInfo *util.SessionInfo + + if sToken != nil { + sessionInfo = &util.SessionInfo{ + ID: sToken.ID(), + Owner: sToken.Issuer(), + } + } + + key, err := prm.Config.KeyStorage.GetKey(sessionInfo) + if err != nil { + return nil, fmt.Errorf("could not receive session key: %w", err) + } + + // In case session token is missing, the line above returns the default key. + // If it isn't owner key, replication attempts will fail, thus this check. + ownerObj := prm.Header.OwnerID() + if ownerObj.IsEmpty() { + return nil, errors.New("missing object owner") + } + + if sToken == nil { + var ownerSession user.ID + user.IDFromKey(&ownerSession, key.PublicKey) + + if !ownerObj.Equals(ownerSession) { + return nil, errors.New("session token is missing but object owner id is different from the default key") + } + } else { + if !ownerObj.Equals(sessionInfo.Owner) { + return nil, fmt.Errorf("different token issuer and object owner identifiers %s/%s", sessionInfo.Owner, ownerObj) + } + } + + if prm.SignRequestPrivateKey == nil { + prm.SignRequestPrivateKey = key + } + + return &validatingTarget{ + fmt: prm.Config.FormatValidator, + nextTarget: transformer.NewPayloadSizeLimiter(transformer.Params{ + Key: key, + NextTargetInit: func() transformer.ObjectWriter { return objectwriter.New(prm) }, + NetworkState: prm.Config.NetworkState, + MaxSize: maxPayloadSz, + WithoutHomomorphicHash: containerSDK.IsHomomorphicHashingDisabled(prm.Container), + SessionToken: sToken, + }), + }, nil +} + +func preparePrm(prm *objectwriter.Params) error { + var err error + + // get latest network map + nm, err := netmap.GetLatestNetworkMap(prm.Config.NetmapSource) + if err != nil { + //return fmt.Errorf("(%T) could not get latest network map: %w", p, err) + return fmt.Errorf("could not get latest network map: %w", err) + } + + idCnr, ok := prm.Header.ContainerID() + if !ok { + return errors.New("missing container ID") + } + + // get container to store the object + cnrInfo, err := prm.Config.ContainerSource.Get(idCnr) + if err != nil { + //return fmt.Errorf("(%T) could not get container by ID: %w", p, err) + return fmt.Errorf("could not get container by ID: %w", err) + } + + prm.Container = cnrInfo.Value + + // add common options + prm.TraverseOpts = append(prm.TraverseOpts, + // set processing container + placement.ForContainer(prm.Container), + ) + + if ech := prm.Header.ECHeader(); ech != nil { + prm.TraverseOpts = append(prm.TraverseOpts, + // set identifier of the processing object + placement.ForObject(ech.Parent()), + ) + } else if id, ok := prm.Header.ID(); ok { + prm.TraverseOpts = append(prm.TraverseOpts, + // set identifier of the processing object + placement.ForObject(id), + ) + } + + // create placement builder from network map + builder := placement.NewNetworkMapBuilder(nm) + + if prm.Common.LocalOnly() { + // restrict success count to 1 stored copy (to local storage) + prm.TraverseOpts = append(prm.TraverseOpts, placement.SuccessAfter(1)) + + // use local-only placement builder + builder = util.NewLocalPlacement(builder, prm.Config.NetmapKeys) + } + + // set placement builder + prm.TraverseOpts = append(prm.TraverseOpts, placement.UseBuilder(builder)) + + return nil +} diff --git a/pkg/services/object/put/validation.go b/pkg/services/object/common/target/validation.go similarity index 99% rename from pkg/services/object/put/validation.go rename to pkg/services/object/common/target/validation.go index c2b078ef5a..b29721d01e 100644 --- a/pkg/services/object/put/validation.go +++ b/pkg/services/object/common/target/validation.go @@ -1,4 +1,4 @@ -package putsvc +package target import ( "bytes" diff --git a/pkg/services/object/put/common.go b/pkg/services/object/common/writer/common.go similarity index 65% rename from pkg/services/object/put/common.go rename to pkg/services/object/common/writer/common.go index cbb7f5f333..6689557ee8 100644 --- a/pkg/services/object/put/common.go +++ b/pkg/services/object/common/writer/common.go @@ -1,4 +1,4 @@ -package putsvc +package writer import ( "context" @@ -13,23 +13,23 @@ import ( "go.uber.org/zap" ) -type nodeIterator struct { - traversal - cfg *cfg +type NodeIterator struct { + Traversal + cfg *Config } -func (c *cfg) newNodeIterator(opts []placement.Option) *nodeIterator { - return &nodeIterator{ - traversal: traversal{ - opts: opts, - mExclude: make(map[string]*bool), +func (c *Config) NewNodeIterator(opts []placement.Option) *NodeIterator { + return &NodeIterator{ + Traversal: Traversal{ + Opts: opts, + Exclude: make(map[string]*bool), }, cfg: c, } } -func (n *nodeIterator) forEachNode(ctx context.Context, f func(context.Context, nodeDesc) error) error { - traverser, err := placement.NewTraverser(n.traversal.opts...) +func (n *NodeIterator) ForEachNode(ctx context.Context, f func(context.Context, NodeDescriptor) error) error { + traverser, err := placement.NewTraverser(n.Traversal.Opts...) if err != nil { return fmt.Errorf("could not create object placement traverser: %w", err) } @@ -56,10 +56,10 @@ func (n *nodeIterator) forEachNode(ctx context.Context, f func(context.Context, } // perform additional container broadcast if needed - if n.traversal.submitPrimaryPlacementFinish() { - err := n.forEachNode(ctx, f) + if n.Traversal.submitPrimaryPlacementFinish() { + err := n.ForEachNode(ctx, f) if err != nil { - n.cfg.log.Error(logs.PutAdditionalContainerBroadcastFailure, zap.Error(err)) + n.cfg.Logger.Error(logs.PutAdditionalContainerBroadcastFailure, zap.Error(err)) // we don't fail primary operation because of broadcast failure } } @@ -67,11 +67,11 @@ func (n *nodeIterator) forEachNode(ctx context.Context, f func(context.Context, return nil } -func (n *nodeIterator) forEachAddress(ctx context.Context, traverser *placement.Traverser, addrs []placement.Node, f func(context.Context, nodeDesc) error, resErr *atomic.Value) bool { +func (n *NodeIterator) forEachAddress(ctx context.Context, traverser *placement.Traverser, addrs []placement.Node, f func(context.Context, NodeDescriptor) error, resErr *atomic.Value) bool { var wg sync.WaitGroup for _, addr := range addrs { - if ok := n.mExclude[string(addr.PublicKey())]; ok != nil { + if ok := n.Exclude[string(addr.PublicKey())]; ok != nil { if *ok { traverser.SubmitSuccess() } @@ -86,10 +86,10 @@ func (n *nodeIterator) forEachAddress(ctx context.Context, traverser *placement. if err := workerPool.Submit(func() { defer wg.Done() - err := f(ctx, nodeDesc{local: isLocal, info: addr}) + err := f(ctx, NodeDescriptor{Local: isLocal, Info: addr}) if err != nil { resErr.Store(err) - svcutil.LogServiceError(n.cfg.log, "PUT", addr.Addresses(), err) + svcutil.LogServiceError(n.cfg.Logger, "PUT", addr.Addresses(), err) return } @@ -97,7 +97,7 @@ func (n *nodeIterator) forEachAddress(ctx context.Context, traverser *placement. *item = true }); err != nil { wg.Done() - svcutil.LogWorkerPoolError(n.cfg.log, "PUT", err) + svcutil.LogWorkerPoolError(n.cfg.Logger, "PUT", err) return true } @@ -105,7 +105,7 @@ func (n *nodeIterator) forEachAddress(ctx context.Context, traverser *placement. // in subsequent container broadcast. Note that we don't // process this node during broadcast if primary placement // on it failed. - n.traversal.submitProcessed(addr, item) + n.Traversal.submitProcessed(addr, item) } wg.Wait() @@ -113,6 +113,6 @@ func (n *nodeIterator) forEachAddress(ctx context.Context, traverser *placement. return false } -func needAdditionalBroadcast(obj *objectSDK.Object, localOnly bool) bool { +func NeedAdditionalBroadcast(obj *objectSDK.Object, localOnly bool) bool { return len(obj.Children()) > 0 || (!localOnly && (obj.Type() == objectSDK.TypeTombstone || obj.Type() == objectSDK.TypeLock)) } diff --git a/pkg/services/object/put/writer.go b/pkg/services/object/common/writer/dispatcher.go similarity index 97% rename from pkg/services/object/put/writer.go rename to pkg/services/object/common/writer/dispatcher.go index 53eee6006a..bb9a54ce9d 100644 --- a/pkg/services/object/put/writer.go +++ b/pkg/services/object/common/writer/dispatcher.go @@ -1,4 +1,4 @@ -package putsvc +package writer import ( "context" diff --git a/pkg/services/object/put/distributed.go b/pkg/services/object/common/writer/distributed.go similarity index 57% rename from pkg/services/object/put/distributed.go rename to pkg/services/object/common/writer/distributed.go index 5176f7a54b..f62934beda 100644 --- a/pkg/services/object/put/distributed.go +++ b/pkg/services/object/common/writer/distributed.go @@ -1,4 +1,4 @@ -package putsvc +package writer import ( "context" @@ -13,47 +13,47 @@ type preparedObjectTarget interface { WriteObject(context.Context, *objectSDK.Object, object.ContentMeta) error } -type distributedTarget struct { +type distributedWriter struct { + cfg *Config + placementOpts []placement.Option obj *objectSDK.Object objMeta object.ContentMeta - *cfg + nodeTargetInitializer func(NodeDescriptor) preparedObjectTarget - nodeTargetInitializer func(nodeDesc) preparedObjectTarget - - relay func(context.Context, nodeDesc) error + relay func(context.Context, NodeDescriptor) error resetSuccessAfterOnBroadcast bool } -// parameters and state of container traversal. -type traversal struct { - opts []placement.Option +// parameters and state of container Traversal. +type Traversal struct { + Opts []placement.Option // need of additional broadcast after the object is saved - extraBroadcastEnabled bool + ExtraBroadcastEnabled bool // container nodes which was processed during the primary object placement - mExclude map[string]*bool + Exclude map[string]*bool - resetSuccessAfterOnBroadcast bool + ResetSuccessAfterOnBroadcast bool } // updates traversal parameters after the primary placement finish and // returns true if additional container broadcast is needed. -func (x *traversal) submitPrimaryPlacementFinish() bool { - if x.extraBroadcastEnabled { +func (x *Traversal) submitPrimaryPlacementFinish() bool { + if x.ExtraBroadcastEnabled { // do not track success during container broadcast (best-effort) - x.opts = append(x.opts, placement.WithoutSuccessTracking()) + x.Opts = append(x.Opts, placement.WithoutSuccessTracking()) - if x.resetSuccessAfterOnBroadcast { - x.opts = append(x.opts, placement.ResetSuccessAfter()) + if x.ResetSuccessAfterOnBroadcast { + x.Opts = append(x.Opts, placement.ResetSuccessAfter()) } // avoid 2nd broadcast - x.extraBroadcastEnabled = false + x.ExtraBroadcastEnabled = false return true } @@ -62,22 +62,22 @@ func (x *traversal) submitPrimaryPlacementFinish() bool { } // marks the container node as processed during the primary object placement. -func (x *traversal) submitProcessed(n placement.Node, item *bool) { - if x.extraBroadcastEnabled { +func (x *Traversal) submitProcessed(n placement.Node, item *bool) { + if x.ExtraBroadcastEnabled { key := string(n.PublicKey()) - if x.mExclude == nil { - x.mExclude = make(map[string]*bool, 1) + if x.Exclude == nil { + x.Exclude = make(map[string]*bool, 1) } - x.mExclude[key] = item + x.Exclude[key] = item } } -type nodeDesc struct { - local bool +type NodeDescriptor struct { + Local bool - info placement.Node + Info placement.Node } // errIncompletePut is returned if processing on a container fails. @@ -96,19 +96,19 @@ func (x errIncompletePut) Error() string { } // WriteObject implements the transformer.ObjectWriter interface. -func (t *distributedTarget) WriteObject(ctx context.Context, obj *objectSDK.Object) error { +func (t *distributedWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error { t.obj = obj var err error - if t.objMeta, err = t.fmtValidator.ValidateContent(t.obj); err != nil { + if t.objMeta, err = t.cfg.FormatValidator.ValidateContent(t.obj); err != nil { return fmt.Errorf("(%T) could not validate payload content: %w", t, err) } return t.iteratePlacement(ctx) } -func (t *distributedTarget) sendObject(ctx context.Context, node nodeDesc) error { - if !node.local && t.relay != nil { +func (t *distributedWriter) sendObject(ctx context.Context, node NodeDescriptor) error { + if !node.Local && t.relay != nil { return t.relay(ctx, node) } @@ -121,11 +121,11 @@ func (t *distributedTarget) sendObject(ctx context.Context, node nodeDesc) error return nil } -func (t *distributedTarget) iteratePlacement(ctx context.Context) error { +func (t *distributedWriter) iteratePlacement(ctx context.Context) error { id, _ := t.obj.ID() - iter := t.cfg.newNodeIterator(append(t.placementOpts, placement.ForObject(id))) - iter.extraBroadcastEnabled = needAdditionalBroadcast(t.obj, false /* Distributed target is for cluster-wide PUT */) - iter.resetSuccessAfterOnBroadcast = t.resetSuccessAfterOnBroadcast - return iter.forEachNode(ctx, t.sendObject) + iter := t.cfg.NewNodeIterator(append(t.placementOpts, placement.ForObject(id))) + iter.ExtraBroadcastEnabled = NeedAdditionalBroadcast(t.obj, false /* Distributed target is for cluster-wide PUT */) + iter.ResetSuccessAfterOnBroadcast = t.resetSuccessAfterOnBroadcast + return iter.ForEachNode(ctx, t.sendObject) } diff --git a/pkg/services/object/put/ec.go b/pkg/services/object/common/writer/ec.go similarity index 69% rename from pkg/services/object/put/ec.go rename to pkg/services/object/common/writer/ec.go index 9980f6d617..fb0a8e4e53 100644 --- a/pkg/services/object/put/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -1,4 +1,4 @@ -package putsvc +package writer import ( "context" @@ -23,23 +23,23 @@ import ( "golang.org/x/sync/errgroup" ) -var _ transformer.ObjectWriter = (*ecWriter)(nil) +var _ transformer.ObjectWriter = (*ECWriter)(nil) var errUnsupportedECObject = errors.New("object is not supported for erasure coding") -type ecWriter struct { - cfg *cfg - placementOpts []placement.Option - container containerSDK.Container - key *ecdsa.PrivateKey - commonPrm *svcutil.CommonPrm - relay func(context.Context, client.NodeInfo, client.MultiAddressClient) error +type ECWriter struct { + Config *Config + PlacementOpts []placement.Option + Container containerSDK.Container + Key *ecdsa.PrivateKey + CommonPrm *svcutil.CommonPrm + Relay func(context.Context, client.NodeInfo, client.MultiAddressClient) error - objMeta object.ContentMeta - objMetaValid bool + ObjectMeta object.ContentMeta + ObjectMetaValid bool } -func (e *ecWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error { +func (e *ECWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error { relayed, err := e.relayIfNotContainerNode(ctx, obj) if err != nil { return err @@ -53,11 +53,11 @@ func (e *ecWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error return errUnsupportedECObject } - if !e.objMetaValid { - if e.objMeta, err = e.cfg.fmtValidator.ValidateContent(obj); err != nil { + if !e.ObjectMetaValid { + if e.ObjectMeta, err = e.Config.FormatValidator.ValidateContent(obj); err != nil { return fmt.Errorf("(%T) could not validate payload content: %w", e, err) } - e.objMetaValid = true + e.ObjectMetaValid = true } if obj.ECHeader() != nil { @@ -66,8 +66,8 @@ func (e *ecWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error return e.writeRawObject(ctx, obj) } -func (e *ecWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.Object) (bool, error) { - if e.relay == nil { +func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.Object) (bool, error) { + if e.Relay == nil { return false, nil } currentNodeIsContainerNode, err := e.currentNodeIsContainerNode() @@ -90,8 +90,8 @@ func (e *ecWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.O return true, nil } -func (e *ecWriter) currentNodeIsContainerNode() (bool, error) { - t, err := placement.NewTraverser(e.placementOpts...) +func (e *ECWriter) currentNodeIsContainerNode() (bool, error) { + t, err := placement.NewTraverser(e.PlacementOpts...) if err != nil { return false, err } @@ -101,7 +101,7 @@ func (e *ecWriter) currentNodeIsContainerNode() (bool, error) { break } for _, node := range nodes { - if e.cfg.netmapKeys.IsLocalKey(node.PublicKey()) { + if e.Config.NetmapKeys.IsLocalKey(node.PublicKey()) { return true, nil } } @@ -109,8 +109,8 @@ func (e *ecWriter) currentNodeIsContainerNode() (bool, error) { return false, nil } -func (e *ecWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index uint32) error { - t, err := placement.NewTraverser(append(e.placementOpts, placement.ForObject(objID))...) +func (e *ECWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index uint32) error { + t, err := placement.NewTraverser(append(e.PlacementOpts, placement.ForObject(objID))...) if err != nil { return err } @@ -126,18 +126,18 @@ func (e *ecWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index var info client.NodeInfo client.NodeInfoFromNetmapElement(&info, node) - c, err := e.cfg.clientConstructor.Get(info) + c, err := e.Config.ClientConstructor.Get(info) if err != nil { return fmt.Errorf("could not create SDK client %s: %w", info.AddressGroup(), err) } completed := make(chan interface{}) - if poolErr := e.cfg.remotePool.Submit(func() { + if poolErr := e.Config.RemotePool.Submit(func() { defer close(completed) - err = e.relay(ctx, info, c) + err = e.Relay(ctx, info, c) }); poolErr != nil { close(completed) - svcutil.LogWorkerPoolError(e.cfg.log, "PUT", poolErr) + svcutil.LogWorkerPoolError(e.Config.Logger, "PUT", poolErr) return poolErr } <-completed @@ -145,7 +145,7 @@ func (e *ecWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index if err == nil { return nil } - e.cfg.log.Logger.Warn(logs.ECFailedToSendToContainerNode, zap.Stringers("address_group", info.AddressGroup())) + e.Config.Logger.Logger.Warn(logs.ECFailedToSendToContainerNode, zap.Stringers("address_group", info.AddressGroup())) lastErr = err } } @@ -157,12 +157,12 @@ func (e *ecWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index } } -func (e *ecWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error { - if e.commonPrm.LocalOnly() { +func (e *ECWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error { + if e.CommonPrm.LocalOnly() { return e.writePartLocal(ctx, obj) } - t, err := placement.NewTraverser(append(e.placementOpts, placement.ForObject(obj.ECHeader().Parent()))...) + t, err := placement.NewTraverser(append(e.PlacementOpts, placement.ForObject(obj.ECHeader().Parent()))...) if err != nil { return err } @@ -187,18 +187,18 @@ func (e *ecWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error return nil } -func (e *ecWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) error { +func (e *ECWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) error { // now only single EC policy is supported - c, err := erasurecode.NewConstructor(policy.ECDataCount(e.container.PlacementPolicy()), policy.ECParityCount(e.container.PlacementPolicy())) + c, err := erasurecode.NewConstructor(policy.ECDataCount(e.Container.PlacementPolicy()), policy.ECParityCount(e.Container.PlacementPolicy())) if err != nil { return err } - parts, err := c.Split(obj, e.key) + parts, err := c.Split(obj, e.Key) if err != nil { return err } objID, _ := obj.ID() - t, err := placement.NewTraverser(append(e.placementOpts, placement.ForObject(objID))...) + t, err := placement.NewTraverser(append(e.PlacementOpts, placement.ForObject(objID))...) if err != nil { return err } @@ -230,7 +230,7 @@ func (e *ecWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er return nil } -func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx int, nodes []placement.Node, visited []atomic.Bool) error { +func (e *ECWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx int, nodes []placement.Node, visited []atomic.Bool) error { select { case <-ctx.Done(): return ctx.Err() @@ -243,7 +243,7 @@ func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx if err == nil { return nil } - e.cfg.log.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + e.Config.Logger.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) @@ -267,7 +267,7 @@ func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx if err == nil { return nil } - e.cfg.log.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + e.Config.Logger.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) @@ -291,7 +291,7 @@ func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx if err == nil { return nil } - e.cfg.log.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + e.Config.Logger.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) @@ -300,22 +300,22 @@ func (e *ecWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx return fmt.Errorf("failed to save EC chunk %s to any node", object.AddressOf(obj)) } -func (e *ecWriter) putECPartToNode(ctx context.Context, obj *objectSDK.Object, node placement.Node) error { - if e.cfg.netmapKeys.IsLocalKey(node.PublicKey()) { +func (e *ECWriter) putECPartToNode(ctx context.Context, obj *objectSDK.Object, node placement.Node) error { + if e.Config.NetmapKeys.IsLocalKey(node.PublicKey()) { return e.writePartLocal(ctx, obj) } return e.writePartRemote(ctx, obj, node) } -func (e *ecWriter) writePartLocal(ctx context.Context, obj *objectSDK.Object) error { +func (e *ECWriter) writePartLocal(ctx context.Context, obj *objectSDK.Object) error { var err error - localTarget := localTarget{ - storage: e.cfg.localStore, + localTarget := LocalTarget{ + Storage: e.Config.LocalStore, } completed := make(chan interface{}) - if poolErr := e.cfg.localPool.Submit(func() { + if poolErr := e.Config.LocalPool.Submit(func() { defer close(completed) - err = localTarget.WriteObject(ctx, obj, e.objMeta) + err = localTarget.WriteObject(ctx, obj, e.ObjectMeta) }); poolErr != nil { close(completed) return poolErr @@ -324,22 +324,22 @@ func (e *ecWriter) writePartLocal(ctx context.Context, obj *objectSDK.Object) er return err } -func (e *ecWriter) writePartRemote(ctx context.Context, obj *objectSDK.Object, node placement.Node) error { +func (e *ECWriter) writePartRemote(ctx context.Context, obj *objectSDK.Object, node placement.Node) error { var clientNodeInfo client.NodeInfo client.NodeInfoFromNetmapElement(&clientNodeInfo, node) - remoteTaget := remoteTarget{ - privateKey: e.key, - clientConstructor: e.cfg.clientConstructor, - commonPrm: e.commonPrm, + remoteTaget := remoteWriter{ + privateKey: e.Key, + clientConstructor: e.Config.ClientConstructor, + commonPrm: e.CommonPrm, nodeInfo: clientNodeInfo, } var err error completed := make(chan interface{}) - if poolErr := e.cfg.remotePool.Submit(func() { + if poolErr := e.Config.RemotePool.Submit(func() { defer close(completed) - err = remoteTaget.WriteObject(ctx, obj, e.objMeta) + err = remoteTaget.WriteObject(ctx, obj, e.ObjectMeta) }); poolErr != nil { close(completed) return poolErr diff --git a/pkg/services/object/put/local.go b/pkg/services/object/common/writer/local.go similarity index 81% rename from pkg/services/object/put/local.go rename to pkg/services/object/common/writer/local.go index 54649adc71..02fd25b9e7 100644 --- a/pkg/services/object/put/local.go +++ b/pkg/services/object/common/writer/local.go @@ -1,4 +1,4 @@ -package putsvc +package writer import ( "context" @@ -24,19 +24,19 @@ type ObjectStorage interface { IsLocked(context.Context, oid.Address) (bool, error) } -type localTarget struct { - storage ObjectStorage +type LocalTarget struct { + Storage ObjectStorage } -func (t localTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, meta objectCore.ContentMeta) error { +func (t LocalTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, meta objectCore.ContentMeta) error { switch meta.Type() { case objectSDK.TypeTombstone: - err := t.storage.Delete(ctx, objectCore.AddressOf(obj), meta.Objects()) + err := t.Storage.Delete(ctx, objectCore.AddressOf(obj), meta.Objects()) if err != nil { return fmt.Errorf("could not delete objects from tombstone locally: %w", err) } case objectSDK.TypeLock: - err := t.storage.Lock(ctx, objectCore.AddressOf(obj), meta.Objects()) + err := t.Storage.Lock(ctx, objectCore.AddressOf(obj), meta.Objects()) if err != nil { return fmt.Errorf("could not lock object from lock objects locally: %w", err) } @@ -44,7 +44,7 @@ func (t localTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, met // objects that do not change meta storage } - if err := t.storage.Put(ctx, obj); err != nil { + if err := t.Storage.Put(ctx, obj); err != nil { return fmt.Errorf("(%T) could not put object to local storage: %w", t, err) } return nil diff --git a/pkg/services/object/put/remote.go b/pkg/services/object/common/writer/remote.go similarity index 92% rename from pkg/services/object/put/remote.go rename to pkg/services/object/common/writer/remote.go index ee8d64e7a4..697613ff78 100644 --- a/pkg/services/object/put/remote.go +++ b/pkg/services/object/common/writer/remote.go @@ -1,4 +1,4 @@ -package putsvc +package writer import ( "context" @@ -16,7 +16,7 @@ import ( "google.golang.org/grpc/status" ) -type remoteTarget struct { +type remoteWriter struct { privateKey *ecdsa.PrivateKey commonPrm *util.CommonPrm @@ -41,7 +41,7 @@ type RemotePutPrm struct { obj *objectSDK.Object } -func (t *remoteTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, _ objectcore.ContentMeta) error { +func (t *remoteWriter) WriteObject(ctx context.Context, obj *objectSDK.Object, _ objectcore.ContentMeta) error { c, err := t.clientConstructor.Get(t.nodeInfo) if err != nil { return fmt.Errorf("(%T) could not create SDK client %s: %w", t, t.nodeInfo, err) @@ -64,7 +64,7 @@ func (t *remoteTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, _ return t.putStream(ctx, prm) } -func (t *remoteTarget) putStream(ctx context.Context, prm internalclient.PutObjectPrm) error { +func (t *remoteWriter) putStream(ctx context.Context, prm internalclient.PutObjectPrm) error { _, err := internalclient.PutObject(ctx, prm) if err != nil { return fmt.Errorf("(%T) could not put object to %s: %w", t, t.nodeInfo.AddressGroup(), err) @@ -72,7 +72,7 @@ func (t *remoteTarget) putStream(ctx context.Context, prm internalclient.PutObje return nil } -func (t *remoteTarget) putSingle(ctx context.Context, prm internalclient.PutObjectPrm) error { +func (t *remoteWriter) putSingle(ctx context.Context, prm internalclient.PutObjectPrm) error { _, err := internalclient.PutObjectSingle(ctx, prm) if err != nil { return fmt.Errorf("(%T) could not put single object to %s: %w", t, t.nodeInfo.AddressGroup(), err) @@ -113,7 +113,7 @@ func (s *RemoteSender) PutObject(ctx context.Context, p *RemotePutPrm) error { return err } - t := &remoteTarget{ + t := &remoteWriter{ privateKey: key, clientConstructor: s.clientConstructor, } diff --git a/pkg/services/object/common/writer/writer.go b/pkg/services/object/common/writer/writer.go new file mode 100644 index 0000000000..3d50da988a --- /dev/null +++ b/pkg/services/object/common/writer/writer.go @@ -0,0 +1,183 @@ +package writer + +import ( + "context" + "crypto/ecdsa" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" + objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" +) + +type MaxSizeSource interface { + // MaxObjectSize returns maximum payload size + // of physically stored object in system. + // + // Must return 0 if value can not be obtained. + MaxObjectSize() uint64 +} + +type ClientConstructor interface { + Get(client.NodeInfo) (client.MultiAddressClient, error) +} + +type InnerRing interface { + InnerRingKeys() ([][]byte, error) +} + +type FormatValidatorConfig interface { + VerifySessionTokenIssuer() bool +} + +// Config represents a set of static parameters that are established during +// the initialization phase of all services. +type Config struct { + KeyStorage *objutil.KeyStorage + + MaxSizeSrc MaxSizeSource + + LocalStore ObjectStorage + + ContainerSource container.Source + + NetmapSource netmap.Source + + RemotePool, LocalPool util.WorkerPool + + NetmapKeys netmap.AnnouncedKeys + + FormatValidator *object.FormatValidator + + NetworkState netmap.State + + ClientConstructor ClientConstructor + + Logger *logger.Logger + + VerifySessionTokenIssuer bool +} + +type Option func(*Config) + +func WithWorkerPools(remote, local util.WorkerPool) Option { + return func(c *Config) { + c.RemotePool, c.LocalPool = remote, local + } +} + +func WithLogger(l *logger.Logger) Option { + return func(c *Config) { + c.Logger = l + } +} + +func WithVerifySessionTokenIssuer(v bool) Option { + return func(c *Config) { + c.VerifySessionTokenIssuer = v + } +} + +func (c *Config) getWorkerPool(pub []byte) (util.WorkerPool, bool) { + if c.NetmapKeys.IsLocalKey(pub) { + return c.LocalPool, true + } + return c.RemotePool, false +} + +type Params struct { + Config *Config + + Common *objutil.CommonPrm + + Header *objectSDK.Object + + Container containerSDK.Container + + TraverseOpts []placement.Option + + Relay func(context.Context, client.NodeInfo, client.MultiAddressClient) error + + SignRequestPrivateKey *ecdsa.PrivateKey +} + +func New(prm *Params) transformer.ObjectWriter { + if container.IsECContainer(prm.Container) && object.IsECSupported(prm.Header) { + return newECWriter(prm) + } + return newDefaultObjectWriter(prm, false) +} + +func newDefaultObjectWriter(prm *Params, forECPlacement bool) transformer.ObjectWriter { + var relay func(context.Context, NodeDescriptor) error + if prm.Relay != nil { + relay = func(ctx context.Context, node NodeDescriptor) error { + var info client.NodeInfo + + client.NodeInfoFromNetmapElement(&info, node.Info) + + c, err := prm.Config.ClientConstructor.Get(info) + if err != nil { + return fmt.Errorf("could not create SDK client %s: %w", info.AddressGroup(), err) + } + + return prm.Relay(ctx, info, c) + } + } + + var resetSuccessAfterOnBroadcast bool + traverseOpts := prm.TraverseOpts + if forECPlacement && !prm.Common.LocalOnly() { + // save non-regular and linking object to EC container. + // EC 2.1 -> REP 2, EC 2.2 -> REP 3 etc. + traverseOpts = append(traverseOpts, placement.SuccessAfter(uint32(policy.ECParityCount(prm.Container.PlacementPolicy())+1))) + resetSuccessAfterOnBroadcast = true + } + + return &distributedWriter{ + cfg: prm.Config, + placementOpts: traverseOpts, + resetSuccessAfterOnBroadcast: resetSuccessAfterOnBroadcast, + nodeTargetInitializer: func(node NodeDescriptor) preparedObjectTarget { + if node.Local { + return LocalTarget{ + Storage: prm.Config.LocalStore, + } + } + + rt := &remoteWriter{ + privateKey: prm.SignRequestPrivateKey, + commonPrm: prm.Common, + clientConstructor: prm.Config.ClientConstructor, + } + + client.NodeInfoFromNetmapElement(&rt.nodeInfo, node.Info) + + return rt + }, + relay: relay, + } +} + +func newECWriter(prm *Params) transformer.ObjectWriter { + return &objectWriterDispatcher{ + ecWriter: &ECWriter{ + Config: prm.Config, + PlacementOpts: append(prm.TraverseOpts, placement.WithCopyNumbers(nil)), // copies number ignored for EC + Container: prm.Container, + Key: prm.SignRequestPrivateKey, + CommonPrm: prm.Common, + Relay: prm.Relay, + }, + repWriter: newDefaultObjectWriter(prm, true), + } +} diff --git a/pkg/services/object/patch/service.go b/pkg/services/object/patch/service.go index c4ab15abff..f1082dfff1 100644 --- a/pkg/services/object/patch/service.go +++ b/pkg/services/object/patch/service.go @@ -2,43 +2,40 @@ package patchsvc import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" - putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" ) // Service implements Put operation of Object service v2. type Service struct { - keyStorage *util.KeyStorage + *objectwriter.Config getSvc *getsvc.Service - - putSvc *putsvc.Service } // NewService constructs Service instance from provided options. -func NewService(ks *util.KeyStorage, getSvc *getsvc.Service, putSvc *putsvc.Service) *Service { +// +// Patch service can use the same objectwriter.Config initializied by Put service. +func NewService(cfg *objectwriter.Config, + getSvc *getsvc.Service, +) *Service { return &Service{ - keyStorage: ks, + Config: cfg, getSvc: getSvc, - - putSvc: putSvc, } } // Put calls internal service and returns v2 object streamer. func (s *Service) Patch() (object.PatchObjectStream, error) { - nodeKey, err := s.keyStorage.GetKey(nil) + nodeKey, err := s.Config.KeyStorage.GetKey(nil) if err != nil { return nil, err } return &Streamer{ - getSvc: s.getSvc, - - putSvc: s.putSvc, - + Config: s.Config, + getSvc: s.getSvc, localNodeKey: nodeKey, }, nil } diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index 84363530e1..85c28cda0d 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -9,8 +9,9 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/target" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" - putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -21,6 +22,8 @@ import ( // Streamer for the patch handler is a pipeline that merges two incoming streams of patches // and original object payload chunks. The merged result is fed to Put stream target. type Streamer struct { + *objectwriter.Config + // Patcher must be initialized at first Streamer.Send call. patcher patcher.PatchApplier @@ -28,8 +31,6 @@ type Streamer struct { getSvc *getsvc.Service - putSvc *putsvc.Service - localNodeKey *ecdsa.PrivateKey } @@ -78,11 +79,6 @@ func (s *Streamer) init(ctx context.Context, req *objectV2.PatchRequest) error { localNodeKey: s.localNodeKey, } - putstm, err := s.putSvc.Put() - if err != nil { - return err - } - hdr := hdrWithSig.GetHeader() oV2 := new(objectV2.Object) hV2 := new(objectV2.Header) @@ -97,14 +93,14 @@ func (s *Streamer) init(ctx context.Context, req *objectV2.PatchRequest) error { } oV2.GetHeader().SetOwnerID(ownerID) - prm, err := s.putInitPrm(req, oV2) + target, err := target.New(&objectwriter.Params{ + Config: s.Config, + Common: commonPrm, + Header: objectSDK.NewFromV2(oV2), + SignRequestPrivateKey: s.localNodeKey, + }) if err != nil { - return err - } - - err = putstm.Init(ctx, prm) - if err != nil { - return err + return fmt.Errorf("target creation: %w", err) } patcherPrm := patcher.Params{ @@ -112,7 +108,7 @@ func (s *Streamer) init(ctx context.Context, req *objectV2.PatchRequest) error { RangeProvider: rangeProvider, - ObjectWriter: putstm.Target(), + ObjectWriter: target, } s.patcher = patcher.New(patcherPrm) diff --git a/pkg/services/object/patch/util.go b/pkg/services/object/patch/util.go index 1218d66949..4f3c3ef172 100644 --- a/pkg/services/object/patch/util.go +++ b/pkg/services/object/patch/util.go @@ -6,31 +6,12 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) -// putInitPrm initializes put paramerer for Put stream. -func (s *Streamer) putInitPrm(req *objectV2.PatchRequest, obj *objectV2.Object) (*putsvc.PutInitPrm, error) { - commonPrm, err := util.CommonPrmFromV2(req) - if err != nil { - return nil, err - } - - prm := new(putsvc.PutInitPrm) - prm.WithObject(objectSDK.NewFromV2(obj)). - WithCommonPrm(commonPrm). - WithPrivateKey(s.localNodeKey) - - return prm, nil -} - func newOwnerID(vh *session.RequestVerificationHeader) (*refs.OwnerID, error) { for vh.GetOrigin() != nil { vh = vh.GetOrigin() diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index a93873738f..8cf4f0d623 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -1,132 +1,66 @@ package putsvc import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) -type MaxSizeSource interface { - // MaxObjectSize returns maximum payload size - // of physically stored object in system. - // - // Must return 0 if value can not be obtained. - MaxObjectSize() uint64 -} - type Service struct { - *cfg -} - -type Option func(*cfg) - -type ClientConstructor interface { - Get(client.NodeInfo) (client.MultiAddressClient, error) -} - -type InnerRing interface { - InnerRingKeys() ([][]byte, error) -} - -type FormatValidatorConfig interface { - VerifySessionTokenIssuer() bool -} - -type cfg struct { - keyStorage *objutil.KeyStorage - - maxSizeSrc MaxSizeSource - - localStore ObjectStorage - - cnrSrc container.Source - - netMapSrc netmap.Source - - remotePool, localPool util.WorkerPool - - netmapKeys netmap.AnnouncedKeys - - fmtValidator *object.FormatValidator - - networkState netmap.State - - clientConstructor ClientConstructor - - log *logger.Logger - - verifySessionTokenIssuer bool + *objectwriter.Config } func NewService(ks *objutil.KeyStorage, - cc ClientConstructor, - ms MaxSizeSource, - os ObjectStorage, + cc objectwriter.ClientConstructor, + ms objectwriter.MaxSizeSource, + os objectwriter.ObjectStorage, cs container.Source, ns netmap.Source, nk netmap.AnnouncedKeys, nst netmap.State, - ir InnerRing, - opts ...Option, + ir objectwriter.InnerRing, + opts ...objectwriter.Option, ) *Service { - c := &cfg{ - remotePool: util.NewPseudoWorkerPool(), - localPool: util.NewPseudoWorkerPool(), - log: &logger.Logger{Logger: zap.L()}, - keyStorage: ks, - clientConstructor: cc, - maxSizeSrc: ms, - localStore: os, - cnrSrc: cs, - netMapSrc: ns, - netmapKeys: nk, - networkState: nst, + c := &objectwriter.Config{ + RemotePool: util.NewPseudoWorkerPool(), + LocalPool: util.NewPseudoWorkerPool(), + Logger: &logger.Logger{Logger: zap.L()}, + KeyStorage: ks, + ClientConstructor: cc, + MaxSizeSrc: ms, + LocalStore: os, + ContainerSource: cs, + NetmapSource: ns, + NetmapKeys: nk, + NetworkState: nst, } for i := range opts { opts[i](c) } - c.fmtValidator = object.NewFormatValidator( + c.FormatValidator = object.NewFormatValidator( object.WithLockSource(os), object.WithNetState(nst), object.WithInnerRing(ir), object.WithNetmapSource(ns), object.WithContainersSource(cs), - object.WithVerifySessionTokenIssuer(c.verifySessionTokenIssuer), - object.WithLogger(c.log), + object.WithVerifySessionTokenIssuer(c.VerifySessionTokenIssuer), + object.WithLogger(c.Logger), ) return &Service{ - cfg: c, + Config: c, } } func (p *Service) Put() (*Streamer, error) { return &Streamer{ - cfg: p.cfg, + Config: p.Config, }, nil } - -func WithWorkerPools(remote, local util.WorkerPool) Option { - return func(c *cfg) { - c.remotePool, c.localPool = remote, local - } -} - -func WithLogger(l *logger.Logger) Option { - return func(c *cfg) { - c.log = l - } -} - -func WithVerifySessionTokenIssuer(v bool) Option { - return func(c *cfg) { - c.verifySessionTokenIssuer = v - } -} diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 3cc8518f5f..9b41632687 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -21,6 +21,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/target" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" @@ -97,12 +99,12 @@ func (s *Service) validatePutSingle(ctx context.Context, obj *objectSDK.Object) func (s *Service) validarePutSingleSize(obj *objectSDK.Object) error { if uint64(len(obj.Payload())) != obj.PayloadSize() { - return ErrWrongPayloadSize + return target.ErrWrongPayloadSize } - maxAllowedSize := s.maxSizeSrc.MaxObjectSize() + maxAllowedSize := s.Config.MaxSizeSrc.MaxObjectSize() if obj.PayloadSize() > maxAllowedSize { - return ErrExceedingMaxSize + return target.ErrExceedingMaxSize } return nil @@ -137,11 +139,11 @@ func (s *Service) validatePutSingleChecksum(obj *objectSDK.Object) error { } func (s *Service) validatePutSingleObject(ctx context.Context, obj *objectSDK.Object) (object.ContentMeta, error) { - if err := s.fmtValidator.Validate(ctx, obj, false); err != nil { + if err := s.FormatValidator.Validate(ctx, obj, false); err != nil { return object.ContentMeta{}, fmt.Errorf("coud not validate object format: %w", err) } - meta, err := s.fmtValidator.ValidateContent(obj) + meta, err := s.FormatValidator.ValidateContent(obj) if err != nil { return object.ContentMeta{}, fmt.Errorf("could not validate payload content: %w", err) } @@ -164,17 +166,17 @@ func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *o } func (s *Service) saveToREPReplicas(ctx context.Context, placement putSinglePlacement, obj *objectSDK.Object, localOnly bool, req *objectAPI.PutSingleRequest, meta object.ContentMeta) error { - iter := s.cfg.newNodeIterator(placement.placementOptions) - iter.extraBroadcastEnabled = needAdditionalBroadcast(obj, localOnly) - iter.resetSuccessAfterOnBroadcast = placement.resetSuccessAfterOnBroadcast + iter := s.Config.NewNodeIterator(placement.placementOptions) + iter.ExtraBroadcastEnabled = objectwriter.NeedAdditionalBroadcast(obj, localOnly) + iter.ResetSuccessAfterOnBroadcast = placement.resetSuccessAfterOnBroadcast signer := &putSingleRequestSigner{ req: req, - keyStorage: s.keyStorage, + keyStorage: s.Config.KeyStorage, signer: &sync.Once{}, } - return iter.forEachNode(ctx, func(ctx context.Context, nd nodeDesc) error { + return iter.ForEachNode(ctx, func(ctx context.Context, nd objectwriter.NodeDescriptor) error { return s.saveToPlacementNode(ctx, &nd, obj, signer, meta) }) } @@ -184,25 +186,25 @@ func (s *Service) saveToECReplicas(ctx context.Context, placement putSinglePlace if err != nil { return err } - key, err := s.cfg.keyStorage.GetKey(nil) + key, err := s.Config.KeyStorage.GetKey(nil) if err != nil { return err } signer := &putSingleRequestSigner{ req: req, - keyStorage: s.keyStorage, + keyStorage: s.Config.KeyStorage, signer: &sync.Once{}, } - w := ecWriter{ - cfg: s.cfg, - placementOpts: placement.placementOptions, - objMeta: meta, - objMetaValid: true, - commonPrm: commonPrm, - container: placement.container, - key: key, - relay: func(ctx context.Context, ni client.NodeInfo, mac client.MultiAddressClient) error { + w := objectwriter.ECWriter{ + Config: s.Config, + PlacementOpts: placement.placementOptions, + ObjectMeta: meta, + ObjectMetaValid: true, + CommonPrm: commonPrm, + Container: placement.container, + Key: key, + Relay: func(ctx context.Context, ni client.NodeInfo, mac client.MultiAddressClient) error { return s.redirectPutSingleRequest(ctx, signer, obj, ni, mac) }, } @@ -223,7 +225,7 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb if !ok { return result, errors.New("missing container ID") } - cnrInfo, err := s.cnrSrc.Get(cnrID) + cnrInfo, err := s.Config.ContainerSource.Get(cnrID) if err != nil { return result, fmt.Errorf("could not get container by ID: %w", err) } @@ -247,31 +249,31 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb } result.placementOptions = append(result.placementOptions, placement.ForObject(objID)) - latestNetmap, err := netmap.GetLatestNetworkMap(s.netMapSrc) + latestNetmap, err := netmap.GetLatestNetworkMap(s.Config.NetmapSource) if err != nil { return result, fmt.Errorf("could not get latest network map: %w", err) } builder := placement.NewNetworkMapBuilder(latestNetmap) if localOnly { result.placementOptions = append(result.placementOptions, placement.SuccessAfter(1)) - builder = svcutil.NewLocalPlacement(builder, s.netmapKeys) + builder = svcutil.NewLocalPlacement(builder, s.Config.NetmapKeys) } result.placementOptions = append(result.placementOptions, placement.UseBuilder(builder)) return result, nil } -func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *nodeDesc, obj *objectSDK.Object, +func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *objectwriter.NodeDescriptor, obj *objectSDK.Object, signer *putSingleRequestSigner, meta object.ContentMeta, ) error { - if nodeDesc.local { + if nodeDesc.Local { return s.saveLocal(ctx, obj, meta) } var info client.NodeInfo - client.NodeInfoFromNetmapElement(&info, nodeDesc.info) + client.NodeInfoFromNetmapElement(&info, nodeDesc.Info) - c, err := s.clientConstructor.Get(info) + c, err := s.Config.ClientConstructor.Get(info) if err != nil { return fmt.Errorf("could not create SDK client %s: %w", info.AddressGroup(), err) } @@ -280,8 +282,8 @@ func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *nodeDesc, o } func (s *Service) saveLocal(ctx context.Context, obj *objectSDK.Object, meta object.ContentMeta) error { - localTarget := &localTarget{ - storage: s.localStore, + localTarget := &objectwriter.LocalTarget{ + Storage: s.Config.LocalStore, } return localTarget.WriteObject(ctx, obj, meta) } @@ -314,7 +316,7 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, if err != nil { objID, _ := obj.ID() cnrID, _ := obj.ContainerID() - s.log.Warn(logs.PutSingleRedirectFailure, + s.Config.Logger.Warn(logs.PutSingleRedirectFailure, zap.Error(err), zap.Stringer("address", addr), zap.Stringer("object_id", objID), diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 6b396ec967..f3803d4338 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -2,33 +2,21 @@ package putsvc import ( "context" - "crypto/ecdsa" "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - pkgutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" - containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/target" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) type Streamer struct { - *cfg - - privateKey *ecdsa.PrivateKey + *objectwriter.Config target transformer.ChunkedObjectWriter relay func(context.Context, client.NodeInfo, client.MultiAddressClient) error - - maxPayloadSz uint64 // network config } var errNotInit = errors.New("stream not initialized") @@ -36,8 +24,23 @@ var errNotInit = errors.New("stream not initialized") var errInitRecall = errors.New("init recall") func (p *Streamer) Init(ctx context.Context, prm *PutInitPrm) error { + if p.target != nil { + return errInitRecall + } + // initialize destination target - if err := p.initTarget(prm); err != nil { + prmTarget := &objectwriter.Params{ + Config: p.Config, + Common: prm.common, + Header: prm.hdr, + Container: prm.cnr, + TraverseOpts: prm.traverseOpts, + Relay: p.relay, + } + + var err error + p.target, err = target.New(prmTarget) + if err != nil { return fmt.Errorf("(%T) could not initialize object target: %w", p, err) } @@ -47,253 +50,6 @@ func (p *Streamer) Init(ctx context.Context, prm *PutInitPrm) error { return nil } -// Target accesses underlying target chunked object writer. -func (p *Streamer) Target() transformer.ChunkedObjectWriter { - return p.target -} - -// MaxObjectSize returns maximum payload size for the streaming session. -// -// Must be called after the successful Init. -func (p *Streamer) MaxObjectSize() uint64 { - return p.maxPayloadSz -} - -func (p *Streamer) initTarget(prm *PutInitPrm) error { - // prevent re-calling - if p.target != nil { - return errInitRecall - } - - // prepare needed put parameters - if err := p.preparePrm(prm); err != nil { - return fmt.Errorf("(%T) could not prepare put parameters: %w", p, err) - } - - p.maxPayloadSz = p.maxSizeSrc.MaxObjectSize() - if p.maxPayloadSz == 0 { - return fmt.Errorf("(%T) could not obtain max object size parameter", p) - } - - if prm.hdr.Signature() != nil { - return p.initUntrustedTarget(prm) - } - return p.initTrustedTarget(prm) -} - -func (p *Streamer) initUntrustedTarget(prm *PutInitPrm) error { - p.relay = prm.relay - - if prm.privateKey != nil { - p.privateKey = prm.privateKey - } else { - nodeKey, err := p.cfg.keyStorage.GetKey(nil) - if err != nil { - return err - } - p.privateKey = nodeKey - } - - // prepare untrusted-Put object target - p.target = &validatingPreparedTarget{ - nextTarget: newInMemoryObjectBuilder(p.newObjectWriter(prm)), - fmt: p.fmtValidator, - - maxPayloadSz: p.maxPayloadSz, - } - - return nil -} - -func (p *Streamer) initTrustedTarget(prm *PutInitPrm) error { - sToken := prm.common.SessionToken() - - // prepare trusted-Put object target - - // get private token from local storage - var sessionInfo *util.SessionInfo - - if sToken != nil { - sessionInfo = &util.SessionInfo{ - ID: sToken.ID(), - Owner: sToken.Issuer(), - } - } - - key, err := p.keyStorage.GetKey(sessionInfo) - if err != nil { - return fmt.Errorf("(%T) could not receive session key: %w", p, err) - } - - // In case session token is missing, the line above returns the default key. - // If it isn't owner key, replication attempts will fail, thus this check. - ownerObj := prm.hdr.OwnerID() - if ownerObj.IsEmpty() { - return errors.New("missing object owner") - } - - if sToken == nil { - var ownerSession user.ID - user.IDFromKey(&ownerSession, key.PublicKey) - - if !ownerObj.Equals(ownerSession) { - return fmt.Errorf("(%T) session token is missing but object owner id is different from the default key", p) - } - } else { - if !ownerObj.Equals(sessionInfo.Owner) { - return fmt.Errorf("(%T) different token issuer and object owner identifiers %s/%s", p, sessionInfo.Owner, ownerObj) - } - } - - if prm.privateKey != nil { - p.privateKey = prm.privateKey - } else { - p.privateKey = key - } - p.target = &validatingTarget{ - fmt: p.fmtValidator, - nextTarget: transformer.NewPayloadSizeLimiter(transformer.Params{ - Key: key, - NextTargetInit: func() transformer.ObjectWriter { return p.newObjectWriter(prm) }, - NetworkState: p.networkState, - MaxSize: p.maxPayloadSz, - WithoutHomomorphicHash: containerSDK.IsHomomorphicHashingDisabled(prm.cnr), - SessionToken: sToken, - }), - } - - return nil -} - -func (p *Streamer) preparePrm(prm *PutInitPrm) error { - var err error - - // get latest network map - nm, err := netmap.GetLatestNetworkMap(p.netMapSrc) - if err != nil { - return fmt.Errorf("(%T) could not get latest network map: %w", p, err) - } - - idCnr, ok := prm.hdr.ContainerID() - if !ok { - return errors.New("missing container ID") - } - - // get container to store the object - cnrInfo, err := p.cnrSrc.Get(idCnr) - if err != nil { - return fmt.Errorf("(%T) could not get container by ID: %w", p, err) - } - - prm.cnr = cnrInfo.Value - - // add common options - prm.traverseOpts = append(prm.traverseOpts, - // set processing container - placement.ForContainer(prm.cnr), - ) - - if ech := prm.hdr.ECHeader(); ech != nil { - prm.traverseOpts = append(prm.traverseOpts, - // set identifier of the processing object - placement.ForObject(ech.Parent()), - ) - } else if id, ok := prm.hdr.ID(); ok { - prm.traverseOpts = append(prm.traverseOpts, - // set identifier of the processing object - placement.ForObject(id), - ) - } - - // create placement builder from network map - builder := placement.NewNetworkMapBuilder(nm) - - if prm.common.LocalOnly() { - // restrict success count to 1 stored copy (to local storage) - prm.traverseOpts = append(prm.traverseOpts, placement.SuccessAfter(1)) - - // use local-only placement builder - builder = util.NewLocalPlacement(builder, p.netmapKeys) - } - - // set placement builder - prm.traverseOpts = append(prm.traverseOpts, placement.UseBuilder(builder)) - - return nil -} - -func (p *Streamer) newObjectWriter(prm *PutInitPrm) transformer.ObjectWriter { - if container.IsECContainer(prm.cnr) && object.IsECSupported(prm.hdr) { - return p.newECWriter(prm) - } - return p.newDefaultObjectWriter(prm, false) -} - -func (p *Streamer) newDefaultObjectWriter(prm *PutInitPrm, forECPlacement bool) transformer.ObjectWriter { - var relay func(context.Context, nodeDesc) error - if p.relay != nil { - relay = func(ctx context.Context, node nodeDesc) error { - var info client.NodeInfo - - client.NodeInfoFromNetmapElement(&info, node.info) - - c, err := p.clientConstructor.Get(info) - if err != nil { - return fmt.Errorf("could not create SDK client %s: %w", info.AddressGroup(), err) - } - - return p.relay(ctx, info, c) - } - } - - var resetSuccessAfterOnBroadcast bool - traverseOpts := prm.traverseOpts - if forECPlacement && !prm.common.LocalOnly() { - // save non-regular and linking object to EC container. - // EC 2.1 -> REP 2, EC 2.2 -> REP 3 etc. - traverseOpts = append(traverseOpts, placement.SuccessAfter(uint32(policy.ECParityCount(prm.cnr.PlacementPolicy())+1))) - resetSuccessAfterOnBroadcast = true - } - - return &distributedTarget{ - cfg: p.cfg, - placementOpts: traverseOpts, - resetSuccessAfterOnBroadcast: resetSuccessAfterOnBroadcast, - nodeTargetInitializer: func(node nodeDesc) preparedObjectTarget { - if node.local { - return localTarget{ - storage: p.localStore, - } - } - - rt := &remoteTarget{ - privateKey: p.privateKey, - commonPrm: prm.common, - clientConstructor: p.clientConstructor, - } - - client.NodeInfoFromNetmapElement(&rt.nodeInfo, node.info) - - return rt - }, - relay: relay, - } -} - -func (p *Streamer) newECWriter(prm *PutInitPrm) transformer.ObjectWriter { - return &objectWriterDispatcher{ - ecWriter: &ecWriter{ - cfg: p.cfg, - placementOpts: append(prm.traverseOpts, placement.WithCopyNumbers(nil)), // copies number ignored for EC - container: prm.cnr, - key: p.privateKey, - commonPrm: prm.common, - relay: p.relay, - }, - repWriter: p.newDefaultObjectWriter(prm, true), - } -} - func (p *Streamer) SendChunk(ctx context.Context, prm *PutChunkPrm) error { if p.target == nil { return errNotInit @@ -327,10 +83,3 @@ func (p *Streamer) Close(ctx context.Context) (*PutResponse, error) { id: ids.SelfID, }, nil } - -func (c *cfg) getWorkerPool(pub []byte) (pkgutil.WorkerPool, bool) { - if c.netmapKeys.IsLocalKey(pub) { - return c.localPool, true - } - return c.remotePool, false -} diff --git a/pkg/services/object/put/v2/streamer.go b/pkg/services/object/put/v2/streamer.go index 9c6de4ca88..5bf15b4cdc 100644 --- a/pkg/services/object/put/v2/streamer.go +++ b/pkg/services/object/put/v2/streamer.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/target" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" @@ -55,7 +56,7 @@ func (s *streamer) Send(ctx context.Context, req *object.PutRequest) (err error) s.saveChunks = v.GetSignature() != nil if s.saveChunks { - maxSz := s.stream.MaxObjectSize() + maxSz := s.stream.MaxSizeSrc.MaxObjectSize() s.sizes = &sizes{ payloadSz: uint64(v.GetHeader().GetPayloadLength()), @@ -63,7 +64,7 @@ func (s *streamer) Send(ctx context.Context, req *object.PutRequest) (err error) // check payload size limit overflow if s.payloadSz > maxSz { - return putsvc.ErrExceedingMaxSize + return target.ErrExceedingMaxSize } s.init = req @@ -74,7 +75,7 @@ func (s *streamer) Send(ctx context.Context, req *object.PutRequest) (err error) // check payload size overflow if s.writtenPayload > s.payloadSz { - return putsvc.ErrWrongPayloadSize + return target.ErrWrongPayloadSize } } @@ -117,7 +118,7 @@ func (s *streamer) CloseAndRecv(ctx context.Context) (*object.PutResponse, error if s.saveChunks { // check payload size correctness if s.writtenPayload != s.payloadSz { - return nil, putsvc.ErrWrongPayloadSize + return nil, target.ErrWrongPayloadSize } } diff --git a/pkg/services/replicator/process.go b/pkg/services/replicator/process.go index 3d04b70841..7e5c6e0932 100644 --- a/pkg/services/replicator/process.go +++ b/pkg/services/replicator/process.go @@ -5,7 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" - putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -52,7 +52,7 @@ func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res T } } - prm := new(putsvc.RemotePutPrm). + prm := new(objectwriter.RemotePutPrm). WithObject(task.Obj) for i := 0; task.NumCopies > 0 && i < len(task.Nodes); i++ { diff --git a/pkg/services/replicator/replicator.go b/pkg/services/replicator/replicator.go index a67f2e766f..f2f86daf01 100644 --- a/pkg/services/replicator/replicator.go +++ b/pkg/services/replicator/replicator.go @@ -4,8 +4,8 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" - putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) @@ -24,7 +24,7 @@ type cfg struct { log *logger.Logger - remoteSender *putsvc.RemoteSender + remoteSender *objectwriter.RemoteSender remoteGetter *getsvc.RemoteGetter @@ -67,7 +67,7 @@ func WithLogger(v *logger.Logger) Option { } // WithRemoteSender returns option to set remote object sender of Replicator. -func WithRemoteSender(v *putsvc.RemoteSender) Option { +func WithRemoteSender(v *objectwriter.RemoteSender) Option { return func(c *cfg) { c.remoteSender = v } From 108e4e07be5d75f852fee90f8c0d9e17952be3b5 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 3 Sep 2024 12:18:10 +0300 Subject: [PATCH 0785/1413] [#1349] node: Evacuate objects without setting mode to `MAINTENANCE` Signed-off-by: Anton Nikiforov --- .../modules/control/shards_list.go | 18 ++++---- docs/evacuation.md | 6 +++ internal/metrics/engine.go | 8 ++++ pkg/local_object_storage/engine/evacuate.go | 10 +++++ .../engine/evacuate_test.go | 28 ++++++++++++ pkg/local_object_storage/engine/metrics.go | 1 + pkg/local_object_storage/engine/shards.go | 4 ++ pkg/local_object_storage/shard/exists.go | 4 ++ pkg/local_object_storage/shard/get.go | 14 +++++- pkg/local_object_storage/shard/head.go | 7 +++ pkg/local_object_storage/shard/info.go | 3 ++ .../shard/metrics_test.go | 3 ++ pkg/local_object_storage/shard/range.go | 4 ++ pkg/local_object_storage/shard/shard.go | 11 +++++ pkg/services/control/server/evacuate_async.go | 3 ++ pkg/services/control/server/list_shards.go | 1 + pkg/services/control/types.proto | 3 ++ pkg/services/control/types_frostfs.pb.go | 45 ++++++++++++++++--- 18 files changed, 156 insertions(+), 17 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/shards_list.go b/cmd/frostfs-cli/modules/control/shards_list.go index e9e49bb299..a81034a9e9 100644 --- a/cmd/frostfs-cli/modules/control/shards_list.go +++ b/cmd/frostfs-cli/modules/control/shards_list.go @@ -65,13 +65,14 @@ func prettyPrintShardsJSON(cmd *cobra.Command, ii []control.ShardInfo) { out := make([]map[string]any, 0, len(ii)) for _, i := range ii { out = append(out, map[string]any{ - "shard_id": base58.Encode(i.GetShard_ID()), - "mode": shardModeToString(i.GetMode()), - "metabase": i.GetMetabasePath(), - "blobstor": i.GetBlobstor(), - "writecache": i.GetWritecachePath(), - "pilorama": i.GetPiloramaPath(), - "error_count": i.GetErrorCount(), + "shard_id": base58.Encode(i.GetShard_ID()), + "mode": shardModeToString(i.GetMode()), + "metabase": i.GetMetabasePath(), + "blobstor": i.GetBlobstor(), + "writecache": i.GetWritecachePath(), + "pilorama": i.GetPiloramaPath(), + "error_count": i.GetErrorCount(), + "evacuation_in_progress": i.GetEvacuationInProgress(), }) } @@ -105,7 +106,8 @@ func prettyPrintShards(cmd *cobra.Command, ii []control.ShardInfo) { sb.String()+ pathPrinter("Write-cache", i.GetWritecachePath())+ pathPrinter("Pilorama", i.GetPiloramaPath())+ - fmt.Sprintf("Error count: %d\n", i.GetErrorCount()), + fmt.Sprintf("Error count: %d\n", i.GetErrorCount())+ + fmt.Sprintf("Evacuation in progress: %t\n", i.GetEvacuationInProgress()), base58.Encode(i.GetShard_ID()), shardModeToString(i.GetMode()), ) diff --git a/docs/evacuation.md b/docs/evacuation.md index 9db514a9e5..885ce169a7 100644 --- a/docs/evacuation.md +++ b/docs/evacuation.md @@ -10,6 +10,12 @@ First of all, by the evacuation the data is transferred to other shards of the s Only one running evacuation process is allowed on the node at a time. +It is not necessary to turn maintenance mode on storage node. + +Once evacuation from shard started, it is impossible to read data from it via public API, except the case when evacuation stopped manually or node restarted. + +Because it is necessary to prevent removing by policer objects with policy `REP 1 ...` from remote node during evacuation. + `frostfs-cli` utility is used to manage evacuation. ## Commands diff --git a/internal/metrics/engine.go b/internal/metrics/engine.go index e37777e409..1d01c95ed5 100644 --- a/internal/metrics/engine.go +++ b/internal/metrics/engine.go @@ -27,6 +27,7 @@ type EngineMetrics interface { IncRefillObjectsCount(shardID, path string, size int, success bool) SetRefillPercent(shardID, path string, percent uint32) SetRefillStatus(shardID, path, status string) + SetEvacuationInProgress(shardID string, value bool) WriteCache() WriteCacheMetrics GC() GCMetrics @@ -45,6 +46,7 @@ type engineMetrics struct { refillObjCounter *prometheus.GaugeVec refillPayloadCounter *prometheus.GaugeVec refillPercentCounter *prometheus.GaugeVec + evacuationInProgress *shardIDModeValue gc *gcMetrics writeCache *writeCacheMetrics @@ -72,6 +74,7 @@ func newEngineMetrics() *engineMetrics { refillObjCounter: newEngineGaugeVector("resync_metabase_objects_total", "Count of objects resynced from blobstore to metabase", []string{shardIDLabel, pathLabel, successLabel}), refillPayloadCounter: newEngineGaugeVector("resync_metabase_objects_size_bytes", "Size of objects resynced from blobstore to metabase", []string{shardIDLabel, pathLabel, successLabel}), refillPercentCounter: newEngineGaugeVector("resync_metabase_complete_percent", "Percent of resynced from blobstore to metabase completeness", []string{shardIDLabel, pathLabel}), + evacuationInProgress: newShardIDMode(engineSubsystem, "evacuation_in_progress", "Shard evacuation in progress"), } } @@ -124,6 +127,7 @@ func (m *engineMetrics) DeleteShardMetrics(shardID string) { m.refillPercentCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) m.mode.Delete(shardID) m.refillStatus.DeleteByShardID(shardID) + m.evacuationInProgress.Delete(shardID) } func (m *engineMetrics) AddToObjectCounter(shardID, objectType string, delta int) { @@ -213,3 +217,7 @@ func (m *engineMetrics) SetRefillPercent(shardID, path string, percent uint32) { func (m *engineMetrics) SetRefillStatus(shardID, path, status string) { m.refillStatus.SetMode(shardID, path, status) } + +func (m *engineMetrics) SetEvacuationInProgress(shardID string, value bool) { + m.evacuationInProgress.SetMode(shardID, strconv.FormatBool(value)) +} diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 04e427e490..7bef6edfbc 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -366,6 +366,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, shardID string listPrm.WithCount(defaultEvacuateBatchSize) sh := shardsToEvacuate[shardID] + sh.SetEvacuationInProgress(true) var c *meta.Cursor for { @@ -655,6 +656,7 @@ func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, to var getPrm shard.GetPrm getPrm.SetAddress(addr) + getPrm.SkipEvacCheck(true) getRes, err := sh.Get(ctx, getPrm) if err != nil { @@ -765,3 +767,11 @@ func (e *StorageEngine) ResetEvacuationStatus(ctx context.Context) error { return e.evacuateLimiter.ResetEvacuationStatus() } + +func (e *StorageEngine) ResetEvacuationStatusForShards() { + e.mtx.RLock() + defer e.mtx.RUnlock() + for _, sh := range e.shards { + sh.SetEvacuationInProgress(false) + } +} diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 8d25dad4a6..28529fab9b 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -125,6 +125,34 @@ func TestEvacuateShardObjects(t *testing.T) { // Second case ensures that all objects are indeed moved and available. checkHasObjects(t) + // Objects on evacuated shards should be logically unavailable, but persisted on disk. + // This is necessary to prevent removing it by policer in case of `REP 1` policy. + for _, obj := range objects[len(objects)-objPerShard:] { + var prmGet shard.GetPrm + prmGet.SetAddress(objectCore.AddressOf(obj)) + _, err = e.shards[evacuateShardID].Get(context.Background(), prmGet) + require.Error(t, err) + + prmGet.SkipEvacCheck(true) + _, err = e.shards[evacuateShardID].Get(context.Background(), prmGet) + require.NoError(t, err) + + var prmHead shard.HeadPrm + prmHead.SetAddress(objectCore.AddressOf(obj)) + _, err = e.shards[evacuateShardID].Head(context.Background(), prmHead) + require.Error(t, err) + + var existsPrm shard.ExistsPrm + existsPrm.Address = objectCore.AddressOf(obj) + _, err = e.shards[evacuateShardID].Exists(context.Background(), existsPrm) + require.Error(t, err) + + var rngPrm shard.RngPrm + rngPrm.SetAddress(objectCore.AddressOf(obj)) + _, err = e.shards[evacuateShardID].GetRange(context.Background(), rngPrm) + require.Error(t, err) + } + // Calling it again is OK, but all objects are already moved, so no new PUTs should be done. res, err = e.Evacuate(context.Background(), prm) require.NoError(t, err) diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index 72b5ae2528..1c088c7543 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -30,6 +30,7 @@ type MetricRegister interface { IncRefillObjectsCount(shardID, path string, size int, success bool) SetRefillPercent(shardID, path string, percent uint32) SetRefillStatus(shardID, path, status string) + SetEvacuationInProgress(shardID string, value bool) WriteCache() metrics.WriteCacheMetrics GC() metrics.GCMetrics diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 980b38a632..40584149ee 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -97,6 +97,10 @@ func (m *metricsWithID) SetRefillStatus(path string, status string) { m.mw.SetRefillStatus(m.id, path, status) } +func (m *metricsWithID) SetEvacuationInProgress(value bool) { + m.mw.SetEvacuationInProgress(m.id, value) +} + // AddShard adds a new shard to the storage engine. // // Returns any error encountered that did not allow adding a shard. diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index b5a9604b46..784bf293ae 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -5,7 +5,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -60,6 +62,8 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { if s.info.Mode.Disabled() { return ExistsRes{}, ErrShardDisabled + } else if s.info.EvacuationInProgress { + return ExistsRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) } else if s.info.Mode.NoMetabase() { var p common.ExistsPrm p.Address = prm.Address diff --git a/pkg/local_object_storage/shard/get.go b/pkg/local_object_storage/shard/get.go index 2e7c84bcd4..d1c3936132 100644 --- a/pkg/local_object_storage/shard/get.go +++ b/pkg/local_object_storage/shard/get.go @@ -27,8 +27,9 @@ type storFetcher = func(stor *blobstor.BlobStor, id []byte) (*objectSDK.Object, // GetPrm groups the parameters of Get operation. type GetPrm struct { - addr oid.Address - skipMeta bool + addr oid.Address + skipMeta bool + skipEvacCheck bool } // GetRes groups the resulting values of Get operation. @@ -50,6 +51,11 @@ func (p *GetPrm) SetIgnoreMeta(ignore bool) { p.skipMeta = ignore } +// SkipEvacCheck is a Get option which instruct to skip check is evacuation in progress. +func (p *GetPrm) SkipEvacCheck(val bool) { + p.skipEvacCheck = val +} + // Object returns the requested object. func (r GetRes) Object() *objectSDK.Object { return r.obj @@ -85,6 +91,10 @@ func (s *Shard) Get(ctx context.Context, prm GetPrm) (GetRes, error) { return GetRes{}, ErrShardDisabled } + if s.info.EvacuationInProgress && !prm.skipEvacCheck { + return GetRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) + } + cb := func(stor *blobstor.BlobStor, id []byte) (*objectSDK.Object, error) { var getPrm common.GetPrm getPrm.Address = prm.addr diff --git a/pkg/local_object_storage/shard/head.go b/pkg/local_object_storage/shard/head.go index 9d5d312608..ff57e3bf95 100644 --- a/pkg/local_object_storage/shard/head.go +++ b/pkg/local_object_storage/shard/head.go @@ -4,7 +4,9 @@ import ( "context" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" @@ -70,6 +72,11 @@ func (s *Shard) Head(ctx context.Context, prm HeadPrm) (HeadRes, error) { res, err = s.Get(ctx, getPrm) obj = res.Object() } else { + s.m.RLock() + defer s.m.RUnlock() + if s.info.EvacuationInProgress { + return HeadRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) + } var headParams meta.GetPrm headParams.SetAddress(prm.addr) headParams.SetRaw(prm.raw) diff --git a/pkg/local_object_storage/shard/info.go b/pkg/local_object_storage/shard/info.go index 1051ab3db3..f01796ec74 100644 --- a/pkg/local_object_storage/shard/info.go +++ b/pkg/local_object_storage/shard/info.go @@ -16,6 +16,9 @@ type Info struct { // Shard mode. Mode mode.Mode + // True when evacuation is in progress. + EvacuationInProgress bool + // Information about the metabase. MetaBaseInfo meta.Info diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 1ef849c02f..01a85da977 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -192,6 +192,9 @@ func (m *metricsStore) SetRefillStatus(_ string, status string) { m.refillStatus = status } +func (m *metricsStore) SetEvacuationInProgress(bool) { +} + func TestCounters(t *testing.T) { t.Parallel() diff --git a/pkg/local_object_storage/shard/range.go b/pkg/local_object_storage/shard/range.go index 9491543c4d..701268820d 100644 --- a/pkg/local_object_storage/shard/range.go +++ b/pkg/local_object_storage/shard/range.go @@ -87,6 +87,10 @@ func (s *Shard) GetRange(ctx context.Context, prm RngPrm) (RngRes, error) { s.m.RLock() defer s.m.RUnlock() + if s.info.EvacuationInProgress { + return RngRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) + } + if s.info.Mode.Disabled() { return RngRes{}, ErrShardDisabled } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index d11bcc36b8..ac389b5069 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -97,6 +97,8 @@ type MetricsWriter interface { SetRefillPercent(path string, percent uint32) // SetRefillStatus sets refill status. SetRefillStatus(path string, status string) + // SetEvacuationInProgress sets evacuation status + SetEvacuationInProgress(value bool) } type cfg struct { @@ -579,3 +581,12 @@ func (s *Shard) DeleteShardMetrics() { s.cfg.metricsWriter.DeleteShardMetrics() } } + +func (s *Shard) SetEvacuationInProgress(val bool) { + s.m.Lock() + defer s.m.Unlock() + s.info.EvacuationInProgress = val + if s.metricsWriter != nil { + s.metricsWriter.SetEvacuationInProgress(val) + } +} diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index b829573ec5..aacebe9e33 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -101,6 +101,9 @@ func (s *Server) StopShardEvacuation(ctx context.Context, req *control.StopShard if err != nil { return nil, status.Error(codes.Internal, err.Error()) } + + s.s.ResetEvacuationStatusForShards() + return resp, nil } diff --git a/pkg/services/control/server/list_shards.go b/pkg/services/control/server/list_shards.go index 56bd9fc1ff..efe2754eaa 100644 --- a/pkg/services/control/server/list_shards.go +++ b/pkg/services/control/server/list_shards.go @@ -53,6 +53,7 @@ func (s *Server) ListShards(_ context.Context, req *control.ListShardsRequest) ( si.SetMode(m) si.SetErrorCount(sh.ErrorCount) + si.SetEvacuationInProgress(sh.EvacuationInProgress) shardInfos = append(shardInfos, *si) } diff --git a/pkg/services/control/types.proto b/pkg/services/control/types.proto index 55636d88a5..d8135ed645 100644 --- a/pkg/services/control/types.proto +++ b/pkg/services/control/types.proto @@ -142,6 +142,9 @@ message ShardInfo { // Path to shard's pilorama storage. string pilorama_path = 7 [ json_name = "piloramaPath" ]; + + // Evacuation status. + bool evacuation_in_progress = 8 [ json_name = "evacuationInProgress" ]; } // Blobstor component description. diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index 42c1afa524..f921065896 100644 --- a/pkg/services/control/types_frostfs.pb.go +++ b/pkg/services/control/types_frostfs.pb.go @@ -954,13 +954,14 @@ func (x *Netmap) UnmarshalEasyJSON(in *jlexer.Lexer) { } type ShardInfo struct { - Shard_ID []byte `json:"shardID"` - MetabasePath string `json:"metabasePath"` - Blobstor []BlobstorInfo `json:"blobstor"` - WritecachePath string `json:"writecachePath"` - Mode ShardMode `json:"mode"` - ErrorCount uint32 `json:"errorCount"` - PiloramaPath string `json:"piloramaPath"` + Shard_ID []byte `json:"shardID"` + MetabasePath string `json:"metabasePath"` + Blobstor []BlobstorInfo `json:"blobstor"` + WritecachePath string `json:"writecachePath"` + Mode ShardMode `json:"mode"` + ErrorCount uint32 `json:"errorCount"` + PiloramaPath string `json:"piloramaPath"` + EvacuationInProgress bool `json:"evacuationInProgress"` } var ( @@ -986,6 +987,7 @@ func (x *ShardInfo) StableSize() (size int) { size += proto.EnumSize(5, int32(x.Mode)) size += proto.UInt32Size(6, x.ErrorCount) size += proto.StringSize(7, x.PiloramaPath) + size += proto.BoolSize(8, x.EvacuationInProgress) return size } @@ -1023,6 +1025,9 @@ func (x *ShardInfo) EmitProtobuf(mm *easyproto.MessageMarshaler) { if len(x.PiloramaPath) != 0 { mm.AppendString(7, x.PiloramaPath) } + if x.EvacuationInProgress { + mm.AppendBool(8, x.EvacuationInProgress) + } } // UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. @@ -1080,6 +1085,12 @@ func (x *ShardInfo) UnmarshalProtobuf(src []byte) (err error) { return fmt.Errorf("cannot unmarshal field %s", "PiloramaPath") } x.PiloramaPath = data + case 8: // EvacuationInProgress + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "EvacuationInProgress") + } + x.EvacuationInProgress = data } } return nil @@ -1147,6 +1158,15 @@ func (x *ShardInfo) GetPiloramaPath() string { func (x *ShardInfo) SetPiloramaPath(v string) { x.PiloramaPath = v } +func (x *ShardInfo) GetEvacuationInProgress() bool { + if x != nil { + return x.EvacuationInProgress + } + return false +} +func (x *ShardInfo) SetEvacuationInProgress(v bool) { + x.EvacuationInProgress = v +} // MarshalJSON implements the json.Marshaler interface. func (x *ShardInfo) MarshalJSON() ([]byte, error) { @@ -1202,6 +1222,11 @@ func (x *ShardInfo) MarshalEasyJSON(out *jwriter.Writer) { out.RawString(prefix) out.String(x.PiloramaPath) } + { + const prefix string = ",\"evacuationInProgress\":" + out.RawString(prefix) + out.Bool(x.EvacuationInProgress) + } out.RawByte('}') } @@ -1296,6 +1321,12 @@ func (x *ShardInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { f = in.String() x.PiloramaPath = f } + case "evacuationInProgress": + { + var f bool + f = in.Bool() + x.EvacuationInProgress = f + } } in.WantComma() } From 273980cfb99a29eef0dbe4bd013c7a0041b6db79 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 5 Sep 2024 16:40:32 +0300 Subject: [PATCH 0786/1413] [#1310] object: Remove irrelevant comments Signed-off-by: Airat Arifullin --- pkg/services/object/common/target/target.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/services/object/common/target/target.go b/pkg/services/object/common/target/target.go index 00080ace69..980c4c6bd0 100644 --- a/pkg/services/object/common/target/target.go +++ b/pkg/services/object/common/target/target.go @@ -116,7 +116,6 @@ func preparePrm(prm *objectwriter.Params) error { // get latest network map nm, err := netmap.GetLatestNetworkMap(prm.Config.NetmapSource) if err != nil { - //return fmt.Errorf("(%T) could not get latest network map: %w", p, err) return fmt.Errorf("could not get latest network map: %w", err) } @@ -128,7 +127,6 @@ func preparePrm(prm *objectwriter.Params) error { // get container to store the object cnrInfo, err := prm.Config.ContainerSource.Get(idCnr) if err != nil { - //return fmt.Errorf("(%T) could not get container by ID: %w", p, err) return fmt.Errorf("could not get container by ID: %w", err) } From f652518c241f405db22259c753be7f8685f39cc7 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 6 Sep 2024 13:09:58 +0300 Subject: [PATCH 0787/1413] [#1357] go: Fix panic caused by using range over slice len If slice is altered in `for` loop, we cannot use range over its length: it may cause panic if slice gets shorter. Signed-off-by: Ekaterina Lebedeva --- pkg/services/control/server/evacuate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go index 300cb9dc9d..ae34133735 100644 --- a/pkg/services/control/server/evacuate.go +++ b/pkg/services/control/server/evacuate.go @@ -169,7 +169,7 @@ func (s *Server) getContainerNodes(contID cid.ID) ([]netmap.NodeInfo, error) { nodes := placement.FlattenNodes(ns) bs := (*keys.PublicKey)(&s.key.PublicKey).Bytes() - for i := range len(nodes) { + for i := 0; i < len(nodes); i++ { // don't use range, slice mutates in body if bytes.Equal(nodes[i].PublicKey(), bs) { copy(nodes[i:], nodes[i+1:]) nodes = nodes[:len(nodes)-1] From 007827255ee65e9d7fd61c0f6bdd6bb59479bac1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 27 Aug 2024 15:51:55 +0300 Subject: [PATCH 0788/1413] [#1337] blobovniczatree: Add .rebuild temp files This allows to reduce open/close DBs to check incompleted rebuilds. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 + .../blobstor/blobovniczatree/blobovnicza.go | 2 +- .../blobstor/blobovniczatree/control.go | 6 +-- .../blobstor/blobovniczatree/iterate.go | 21 ++++++++-- .../blobstor/blobovniczatree/rebuild.go | 38 ++++++++++++++++++- .../blobovniczatree/rebuild_failover_test.go | 12 ++++++ 6 files changed, 71 insertions(+), 9 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 78bcd0c0ee..97b1895293 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -543,4 +543,5 @@ const ( WritecacheSealCompletedAsync = "writecache seal completed successfully" FailedToSealWritecacheAsync = "failed to seal writecache async" WritecacheShrinkSkippedNotEmpty = "writecache shrink skipped: database is not empty" + BlobovniczatreeFailedToRemoveRebuildTempFile = "failed to remove rebuild temp file" ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index 952203367a..c909113c74 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -135,7 +135,7 @@ func getBlobovniczaMaxIndex(directory string) (bool, uint64, error) { var hasDBs bool var maxIdx uint64 for _, e := range entries { - if e.IsDir() { + if e.IsDir() || strings.HasSuffix(e.Name(), rebuildSuffix) { continue } hasDBs = true diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index a31e9d6cbb..681cf876c8 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -2,6 +2,7 @@ package blobovniczatree import ( "context" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -41,10 +42,9 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { eg, egCtx := errgroup.WithContext(ctx) eg.SetLimit(b.blzInitWorkerCount) - visited := make(map[string]struct{}) - err = b.iterateExistingDBPaths(egCtx, func(p string) (bool, error) { - visited[p] = struct{}{} + err = b.iterateIncompletedRebuildDBPaths(egCtx, func(p string) (bool, error) { eg.Go(func() error { + p = strings.TrimSuffix(p, rebuildSuffix) shBlz := b.getBlobovniczaWithoutCaching(p) blz, err := shBlz.Open() if err != nil { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index af3d9e7206..f6acb46aa8 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -188,11 +188,11 @@ func (b *Blobovniczas) iterateExistingDBPaths(ctx context.Context, f func(string b.dbFilesGuard.RLock() defer b.dbFilesGuard.RUnlock() - _, err := b.iterateExistingDBPathsDFS(ctx, "", f) + _, err := b.iterateExistingPathsDFS(ctx, "", f, func(path string) bool { return !strings.HasSuffix(path, rebuildSuffix) }) return err } -func (b *Blobovniczas) iterateExistingDBPathsDFS(ctx context.Context, path string, f func(string) (bool, error)) (bool, error) { +func (b *Blobovniczas) iterateExistingPathsDFS(ctx context.Context, path string, f func(string) (bool, error), fileFilter func(path string) bool) (bool, error) { sysPath := filepath.Join(b.rootPath, path) entries, err := os.ReadDir(sysPath) if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode @@ -208,7 +208,7 @@ func (b *Blobovniczas) iterateExistingDBPathsDFS(ctx context.Context, path strin default: } if entry.IsDir() { - stop, err := b.iterateExistingDBPathsDFS(ctx, filepath.Join(path, entry.Name()), f) + stop, err := b.iterateExistingPathsDFS(ctx, filepath.Join(path, entry.Name()), f, fileFilter) if err != nil { return false, err } @@ -216,6 +216,9 @@ func (b *Blobovniczas) iterateExistingDBPathsDFS(ctx context.Context, path strin return true, nil } } else { + if !fileFilter(entry.Name()) { + continue + } stop, err := f(filepath.Join(path, entry.Name())) if err != nil { return false, err @@ -228,6 +231,15 @@ func (b *Blobovniczas) iterateExistingDBPathsDFS(ctx context.Context, path strin return false, nil } +// iterateIncompletedRebuildDBPaths iterates over the paths of Blobovniczas with incompleted rebuild files without any order. +func (b *Blobovniczas) iterateIncompletedRebuildDBPaths(ctx context.Context, f func(string) (bool, error)) error { + b.dbFilesGuard.RLock() + defer b.dbFilesGuard.RUnlock() + + _, err := b.iterateExistingPathsDFS(ctx, "", f, func(path string) bool { return strings.HasSuffix(path, rebuildSuffix) }) + return err +} + func (b *Blobovniczas) iterateSortedDBPaths(ctx context.Context, addr oid.Address, f func(string) (bool, error)) error { b.dbFilesGuard.RLock() defer b.dbFilesGuard.RUnlock() @@ -249,6 +261,9 @@ func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path st var dirIdxs []uint64 for _, entry := range entries { + if strings.HasSuffix(entry.Name(), rebuildSuffix) { + continue + } idx := u64FromHexString(entry.Name()) if entry.IsDir() { dirIdxs = append(dirIdxs, idx) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index cfc17cfaee..058fe1fb68 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -6,6 +6,7 @@ import ( "errors" "os" "path/filepath" + "strings" "sync" "sync/atomic" "time" @@ -19,6 +20,8 @@ import ( "golang.org/x/sync/errgroup" ) +const rebuildSuffix = ".rebuild" + var ( errRebuildInProgress = errors.New("rebuild is in progress, the operation cannot be performed") errBatchFull = errors.New("batch full") @@ -124,15 +127,36 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M } shDB.Close() }() - + dropTempFile, err := b.addRebuildTempFile(path) + if err != nil { + return 0, err + } migratedObjects, err := b.moveObjects(ctx, blz, shDB.SystemPath(), meta, limiter) if err != nil { return migratedObjects, err } shDBClosed, err = b.dropDB(ctx, path, shDB) + if err == nil { + // drop only on success to continue rebuild on error + dropTempFile() + } return migratedObjects, err } +func (b *Blobovniczas) addRebuildTempFile(path string) (func(), error) { + sysPath := filepath.Join(b.rootPath, path) + sysPath = sysPath + rebuildSuffix + _, err := os.OpenFile(sysPath, os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, b.perm) + if err != nil { + return nil, err + } + return func() { + if err := os.Remove(sysPath); err != nil { + b.log.Warn(logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) + } + }, nil +} + func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, blzPath string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) { var result atomic.Uint64 batch := make(map[oid.Address][]byte) @@ -256,7 +280,10 @@ func (b *Blobovniczas) dropDirectoryIfEmpty(path string) error { func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore common.MetaStorage) (uint64, error) { var count uint64 - return count, b.iterateExistingDBPaths(ctx, func(s string) (bool, error) { + var rebuildTempFilesToRemove []string + err := b.iterateIncompletedRebuildDBPaths(ctx, func(s string) (bool, error) { + rebuildTmpFilePath := s + s = strings.TrimSuffix(s, rebuildSuffix) shDB := b.getBlobovnicza(s) blz, err := shDB.Open() if err != nil { @@ -276,8 +303,15 @@ func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore co count++ } + rebuildTempFilesToRemove = append(rebuildTempFilesToRemove, rebuildTmpFilePath) return false, nil }) + for _, tmp := range rebuildTempFilesToRemove { + if err := os.Remove(filepath.Join(b.rootPath, tmp)); err != nil { + b.log.Warn(logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) + } + } + return count, err } func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blobovnicza, sourcePath string, diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index a6afed60c6..9fec795caf 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -3,6 +3,7 @@ package blobovniczatree import ( "bytes" "context" + "os" "path/filepath" "sync" "testing" @@ -53,6 +54,8 @@ func testRebuildFailoverOnlyMoveInfoSaved(t *testing.T) { })) require.NoError(t, blz.Close()) + _, err = os.OpenFile(filepath.Join(dir, "0", "0", "1.db.rebuild"), os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, defaultPerm) + require.NoError(t, err) testRebuildFailoverValidate(t, dir, obj, true) } @@ -82,6 +85,9 @@ func testRebuildFailoverObjectSavedToTarget(t *testing.T) { require.NoError(t, blz.Close()) + _, err = os.OpenFile(filepath.Join(dir, "0", "0", "1.db.rebuild"), os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, defaultPerm) + require.NoError(t, err) + blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) require.NoError(t, blz.Open()) require.NoError(t, blz.Init()) @@ -113,6 +119,9 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { require.NoError(t, blz.Close()) + _, err = os.OpenFile(filepath.Join(dir, "0", "0", "1.db.rebuild"), os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, defaultPerm) + require.NoError(t, err) + blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) require.NoError(t, blz.Open()) require.NoError(t, blz.Init()) @@ -194,4 +203,7 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object } require.NoError(t, blz.Close()) + + _, err = os.Stat(filepath.Join(dir, "0", "0", "1.db.rebuild")) + require.True(t, os.IsNotExist(err)) } From d508da8397026fac3fd2a5c77846f1a5ec61a665 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 29 Aug 2024 11:34:18 +0300 Subject: [PATCH 0789/1413] [#1337] blobovniczatree: Add rebuild by fill percent Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobovnicza/sizes.go | 4 + .../blobstor/blobovniczatree/rebuild.go | 93 ++++++++- .../blobstor/blobovniczatree/rebuild_test.go | 195 +++++++++++++++++- .../blobstor/common/rebuild.go | 8 + pkg/local_object_storage/blobstor/rebuild.go | 3 +- pkg/local_object_storage/shard/rebuild.go | 173 ++++++++++++++++ .../shard/rebuild_limiter.go | 13 -- pkg/local_object_storage/shard/rebuilder.go | 98 --------- pkg/local_object_storage/shard/shard.go | 2 +- 9 files changed, 470 insertions(+), 119 deletions(-) create mode 100644 pkg/local_object_storage/shard/rebuild.go delete mode 100644 pkg/local_object_storage/shard/rebuild_limiter.go delete mode 100644 pkg/local_object_storage/shard/rebuilder.go diff --git a/pkg/local_object_storage/blobovnicza/sizes.go b/pkg/local_object_storage/blobovnicza/sizes.go index 1dff75aede..9bbed0db58 100644 --- a/pkg/local_object_storage/blobovnicza/sizes.go +++ b/pkg/local_object_storage/blobovnicza/sizes.go @@ -57,3 +57,7 @@ func (b *Blobovnicza) itemDeleted(itemSize uint64) { func (b *Blobovnicza) IsFull() bool { return b.dataSize.Load() >= b.fullSizeLimit } + +func (b *Blobovnicza) FillPercent() int { + return int(100.0 * (float64(b.dataSize.Load()) / float64(b.fullSizeLimit))) +} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 058fe1fb68..b7f20822ef 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "fmt" "os" "path/filepath" "strings" @@ -59,7 +60,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm b.log.Debug(logs.BlobovniczaTreeCompletedPreviousRebuildSuccess) b.log.Debug(logs.BlobovniczaTreeCollectingDBToRebuild) - dbsToMigrate, err := b.getDBsToRebuild(ctx) + dbsToMigrate, err := b.getDBsToRebuild(ctx, prm.Action) if err != nil { b.log.Warn(logs.BlobovniczaTreeCollectingDBToRebuildFailed, zap.Error(err)) success = false @@ -93,7 +94,33 @@ func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common. return res, nil } -func (b *Blobovniczas) getDBsToRebuild(ctx context.Context) ([]string, error) { +func (b *Blobovniczas) getDBsToRebuild(ctx context.Context, action common.RebuildAction) ([]string, error) { + schemaChange := make(map[string]struct{}) + fillPercent := make(map[string]struct{}) + var err error + if action.SchemaChange { + schemaChange, err = b.selectDBsDoNotMatchSchema(ctx) + if err != nil { + return nil, err + } + } + if action.FillPercent { + fillPercent, err = b.selectDBsDoNotMatchFillPercent(ctx, action.FillPercentValue) + if err != nil { + return nil, err + } + } + for k := range fillPercent { + schemaChange[k] = struct{}{} + } + result := make([]string, 0, len(schemaChange)) + for db := range schemaChange { + result = append(result, db) + } + return result, nil +} + +func (b *Blobovniczas) selectDBsDoNotMatchSchema(ctx context.Context) (map[string]struct{}, error) { dbsToMigrate := make(map[string]struct{}) if err := b.iterateExistingDBPaths(ctx, func(s string) (bool, error) { dbsToMigrate[s] = struct{}{} @@ -107,13 +134,69 @@ func (b *Blobovniczas) getDBsToRebuild(ctx context.Context) ([]string, error) { }); err != nil { return nil, err } - result := make([]string, 0, len(dbsToMigrate)) - for db := range dbsToMigrate { - result = append(result, db) + return dbsToMigrate, nil +} + +func (b *Blobovniczas) selectDBsDoNotMatchFillPercent(ctx context.Context, target int) (map[string]struct{}, error) { + if target <= 0 || target > 100 { + return nil, fmt.Errorf("invalid fill percent value %d: must be (0; 100]", target) + } + result := make(map[string]struct{}) + if err := b.iterateDeepest(ctx, oid.Address{}, func(lvlPath string) (bool, error) { + dir := filepath.Join(b.rootPath, lvlPath) + entries, err := os.ReadDir(dir) + if os.IsNotExist(err) { // non initialized tree + return false, nil + } + if err != nil { + return false, err + } + hasDBs := false + // db with maxIdx could be an active, so it should not be rebuilded + var maxIdx uint64 + for _, e := range entries { + if e.IsDir() || strings.HasSuffix(e.Name(), rebuildSuffix) { + continue + } + hasDBs = true + maxIdx = max(u64FromHexString(e.Name()), maxIdx) + } + if !hasDBs { + return false, nil + } + for _, e := range entries { + if e.IsDir() || strings.HasSuffix(e.Name(), rebuildSuffix) { + continue + } + if u64FromHexString(e.Name()) == maxIdx { + continue + } + path := filepath.Join(lvlPath, e.Name()) + resettlementRequired, err := b.fillPercentIsLow(path, target) + if err != nil { + return false, err + } + if resettlementRequired { + result[path] = struct{}{} + } + } + return false, nil + }); err != nil { + return nil, err } return result, nil } +func (b *Blobovniczas) fillPercentIsLow(path string, target int) (bool, error) { + shDB := b.getBlobovnicza(path) + blz, err := shDB.Open() + if err != nil { + return false, err + } + defer shDB.Close() + return blz.FillPercent() < target, nil +} + func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) { shDB := b.getBlobovnicza(path) blz, err := shDB.Open() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 4a51fd86a7..62ae9ea904 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -15,7 +15,7 @@ import ( "golang.org/x/sync/errgroup" ) -func TestBlobovniczaTreeRebuild(t *testing.T) { +func TestBlobovniczaTreeSchemaRebuild(t *testing.T) { t.Parallel() t.Run("width increased", func(t *testing.T) { @@ -39,6 +39,197 @@ func TestBlobovniczaTreeRebuild(t *testing.T) { }) } +func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { + t.Parallel() + + t.Run("no rebuild by fill percent", func(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + b := NewBlobovniczaTree( + context.Background(), + WithLogger(test.NewLogger(t)), + WithObjectSizeLimit(64*1024), + WithBlobovniczaShallowWidth(1), // single directory + WithBlobovniczaShallowDepth(1), + WithRootPath(dir), + WithBlobovniczaSize(100*1024), // 100 KB limit for each blobovnicza + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) + require.NoError(t, b.Init()) + + storageIDs := make(map[oid.Address][]byte) + for i := 0; i < 100; i++ { + obj := blobstortest.NewObject(64 * 1024) // 64KB object + data, err := obj.Marshal() + require.NoError(t, err) + var prm common.PutPrm + prm.Address = object.AddressOf(obj) + prm.RawData = data + res, err := b.Put(context.Background(), prm) + require.NoError(t, err) + storageIDs[prm.Address] = res.StorageID + } + metaStub := &storageIDUpdateStub{ + storageIDs: storageIDs, + guard: &sync.Mutex{}, + } + rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ + MetaStorage: metaStub, + WorkerLimiter: &rebuildLimiterStub{}, + Action: common.RebuildAction{ + SchemaChange: false, + FillPercent: true, + FillPercentValue: 60, + }, + }) + require.NoError(t, err) + dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 + require.False(t, dataMigrated) + + for addr, storageID := range storageIDs { + var gPrm common.GetPrm + gPrm.Address = addr + gPrm.StorageID = storageID + _, err := b.Get(context.Background(), gPrm) + require.NoError(t, err) + } + + require.NoError(t, b.Close()) + }) + + t.Run("no rebuild single db", func(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + b := NewBlobovniczaTree( + context.Background(), + WithLogger(test.NewLogger(t)), + WithObjectSizeLimit(64*1024), + WithBlobovniczaShallowWidth(1), // single directory + WithBlobovniczaShallowDepth(1), + WithRootPath(dir), + WithBlobovniczaSize(100*1024), // 100 KB soft limit for each blobovnicza + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) + require.NoError(t, b.Init()) + + storageIDs := make(map[oid.Address][]byte) + obj := blobstortest.NewObject(64 * 1024) // 64KB object + data, err := obj.Marshal() + require.NoError(t, err) + var prm common.PutPrm + prm.Address = object.AddressOf(obj) + prm.RawData = data + res, err := b.Put(context.Background(), prm) + require.NoError(t, err) + storageIDs[prm.Address] = res.StorageID + metaStub := &storageIDUpdateStub{ + storageIDs: storageIDs, + guard: &sync.Mutex{}, + } + rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ + MetaStorage: metaStub, + WorkerLimiter: &rebuildLimiterStub{}, + Action: common.RebuildAction{ + SchemaChange: false, + FillPercent: true, + FillPercentValue: 90, // 64KB / 100KB = 64% + }, + }) + require.NoError(t, err) + dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 + require.False(t, dataMigrated) + + for addr, storageID := range storageIDs { + var gPrm common.GetPrm + gPrm.Address = addr + gPrm.StorageID = storageID + _, err := b.Get(context.Background(), gPrm) + require.NoError(t, err) + } + + require.NoError(t, b.Close()) + }) + + t.Run("rebuild by fill percent", func(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + b := NewBlobovniczaTree( + context.Background(), + WithLogger(test.NewLogger(t)), + WithObjectSizeLimit(64*1024), + WithBlobovniczaShallowWidth(1), // single directory + WithBlobovniczaShallowDepth(1), + WithRootPath(dir), + WithBlobovniczaSize(100*1024), // 100 KB limit for each blobovnicza + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) + require.NoError(t, b.Init()) + + storageIDs := make(map[oid.Address][]byte) + toDelete := make(map[oid.Address][]byte) + for i := 0; i < 100; i++ { // 2 objects for one blobovnicza, so 50 DBs total will be created + obj := blobstortest.NewObject(64 * 1024) + data, err := obj.Marshal() + require.NoError(t, err) + var prm common.PutPrm + prm.Address = object.AddressOf(obj) + prm.RawData = data + res, err := b.Put(context.Background(), prm) + require.NoError(t, err) + storageIDs[prm.Address] = res.StorageID + if i%2 == 1 { + toDelete[prm.Address] = res.StorageID + } + } + for addr, storageID := range toDelete { + var prm common.DeletePrm + prm.Address = addr + prm.StorageID = storageID + _, err := b.Delete(context.Background(), prm) + require.NoError(t, err) + } + metaStub := &storageIDUpdateStub{ + storageIDs: storageIDs, + guard: &sync.Mutex{}, + } + rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ + MetaStorage: metaStub, + WorkerLimiter: &rebuildLimiterStub{}, + Action: common.RebuildAction{ + SchemaChange: false, + FillPercent: true, + FillPercentValue: 80, + }, + }) + require.NoError(t, err) + require.Equal(t, uint64(49), rRes.FilesRemoved) + require.Equal(t, uint64(49), rRes.ObjectsMoved) // 49 DBs with 1 objects + require.Equal(t, uint64(49), metaStub.updatedCount) + + for addr, storageID := range storageIDs { + if _, found := toDelete[addr]; found { + continue + } + var gPrm common.GetPrm + gPrm.Address = addr + gPrm.StorageID = storageID + _, err := b.Get(context.Background(), gPrm) + require.NoError(t, err) + } + + require.NoError(t, b.Close()) + }) +} + func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { t.Parallel() @@ -92,6 +283,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub rPrm.WorkerLimiter = &rebuildLimiterStub{} + rPrm.Action = common.RebuildAction{SchemaChange: true} rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 @@ -180,6 +372,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub rPrm.WorkerLimiter = &rebuildLimiterStub{} + rPrm.Action = common.RebuildAction{SchemaChange: true} rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 diff --git a/pkg/local_object_storage/blobstor/common/rebuild.go b/pkg/local_object_storage/blobstor/common/rebuild.go index 9f629ef8cc..020d9d022c 100644 --- a/pkg/local_object_storage/blobstor/common/rebuild.go +++ b/pkg/local_object_storage/blobstor/common/rebuild.go @@ -11,9 +11,17 @@ type RebuildRes struct { FilesRemoved uint64 } +type RebuildAction struct { + SchemaChange bool + + FillPercent bool + FillPercentValue int +} + type RebuildPrm struct { MetaStorage MetaStorage WorkerLimiter ConcurrentWorkersLimiter + Action RebuildAction } type MetaStorage interface { diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go index 101c60752d..31bc2d1673 100644 --- a/pkg/local_object_storage/blobstor/rebuild.go +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -18,13 +18,14 @@ type ConcurrentWorkersLimiter interface { ReleaseWorkSlot() } -func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter ConcurrentWorkersLimiter) error { +func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter ConcurrentWorkersLimiter, action common.RebuildAction) error { var summary common.RebuildRes var rErr error for _, storage := range b.storage { res, err := storage.Storage.Rebuild(ctx, common.RebuildPrm{ MetaStorage: upd, WorkerLimiter: limiter, + Action: action, }) summary.FilesRemoved += res.FilesRemoved summary.ObjectsMoved += res.ObjectsMoved diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go new file mode 100644 index 0000000000..998fcf08b9 --- /dev/null +++ b/pkg/local_object_storage/shard/rebuild.go @@ -0,0 +1,173 @@ +package shard + +import ( + "context" + "errors" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.uber.org/zap" +) + +type RebuildWorkerLimiter interface { + AcquireWorkSlot(ctx context.Context) error + ReleaseWorkSlot() +} + +type rebuildLimiter struct { + semaphore chan struct{} +} + +func newRebuildLimiter(workersCount uint32) *rebuildLimiter { + return &rebuildLimiter{ + semaphore: make(chan struct{}, workersCount), + } +} + +func (l *rebuildLimiter) AcquireWorkSlot(ctx context.Context) error { + select { + case l.semaphore <- struct{}{}: + return nil + case <-ctx.Done(): + return ctx.Err() + } +} + +func (l *rebuildLimiter) ReleaseWorkSlot() { + <-l.semaphore +} + +type rebuildTask struct { + limiter RebuildWorkerLimiter + action common.RebuildAction +} + +type rebuilder struct { + mtx *sync.Mutex + wg *sync.WaitGroup + cancel func() + limiter RebuildWorkerLimiter + done chan struct{} + tasks chan rebuildTask +} + +func newRebuilder(l RebuildWorkerLimiter) *rebuilder { + return &rebuilder{ + mtx: &sync.Mutex{}, + wg: &sync.WaitGroup{}, + limiter: l, + tasks: make(chan rebuildTask, 10), + } +} + +func (r *rebuilder) Start(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *logger.Logger) { + r.mtx.Lock() + defer r.mtx.Unlock() + + if r.done != nil { + return // already started + } + ctx, cancel := context.WithCancel(ctx) + r.cancel = cancel + r.done = make(chan struct{}) + r.wg.Add(1) + go func() { + defer r.wg.Done() + for { + select { + case <-r.done: + return + case t, ok := <-r.tasks: + if !ok { + continue + } + runRebuild(ctx, bs, mb, log, t.action, t.limiter) + } + } + }() + select { + case <-ctx.Done(): + return + case r.tasks <- rebuildTask{ + limiter: r.limiter, + action: common.RebuildAction{ + SchemaChange: true, + }, + }: + return + } +} + +func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *logger.Logger, + action common.RebuildAction, limiter RebuildWorkerLimiter, +) { + select { + case <-ctx.Done(): + return + default: + } + log.Info(logs.BlobstoreRebuildStarted) + if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, limiter, action); err != nil { + log.Warn(logs.FailedToRebuildBlobstore, zap.Error(err)) + } else { + log.Info(logs.BlobstoreRebuildCompletedSuccessfully) + } +} + +func (r *rebuilder) ScheduleRebuild(ctx context.Context, limiter RebuildWorkerLimiter, action common.RebuildAction, +) error { + select { + case <-ctx.Done(): + return ctx.Err() + case r.tasks <- rebuildTask{ + limiter: limiter, + action: action, + }: + return nil + } +} + +func (r *rebuilder) Stop(log *logger.Logger) { + r.mtx.Lock() + defer r.mtx.Unlock() + + if r.done != nil { + close(r.done) + } + if r.cancel != nil { + r.cancel() + } + r.wg.Wait() + r.cancel = nil + r.done = nil + log.Info(logs.BlobstoreRebuildStopped) +} + +var errMBIsNotAvailable = errors.New("metabase is not available") + +type mbStorageIDUpdate struct { + mb *meta.DB +} + +func (u *mbStorageIDUpdate) UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if u.mb == nil { + return errMBIsNotAvailable + } + + var prm meta.UpdateStorageIDPrm + prm.SetAddress(addr) + prm.SetStorageID(storageID) + _, err := u.mb.UpdateStorageID(ctx, prm) + return err +} diff --git a/pkg/local_object_storage/shard/rebuild_limiter.go b/pkg/local_object_storage/shard/rebuild_limiter.go deleted file mode 100644 index efc21837c3..0000000000 --- a/pkg/local_object_storage/shard/rebuild_limiter.go +++ /dev/null @@ -1,13 +0,0 @@ -package shard - -import "context" - -type RebuildWorkerLimiter interface { - AcquireWorkSlot(ctx context.Context) error - ReleaseWorkSlot() -} - -type noopRebuildLimiter struct{} - -func (l *noopRebuildLimiter) AcquireWorkSlot(context.Context) error { return nil } -func (l *noopRebuildLimiter) ReleaseWorkSlot() {} diff --git a/pkg/local_object_storage/shard/rebuilder.go b/pkg/local_object_storage/shard/rebuilder.go deleted file mode 100644 index f18573c57c..0000000000 --- a/pkg/local_object_storage/shard/rebuilder.go +++ /dev/null @@ -1,98 +0,0 @@ -package shard - -import ( - "context" - "errors" - "sync" - - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" - meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.uber.org/zap" -) - -type rebuilder struct { - mtx *sync.Mutex - wg *sync.WaitGroup - cancel func() - limiter RebuildWorkerLimiter -} - -func newRebuilder(l RebuildWorkerLimiter) *rebuilder { - return &rebuilder{ - mtx: &sync.Mutex{}, - wg: &sync.WaitGroup{}, - cancel: nil, - limiter: l, - } -} - -func (r *rebuilder) Start(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *logger.Logger) { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.start(ctx, bs, mb, log) -} - -func (r *rebuilder) start(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *logger.Logger) { - if r.cancel != nil { - r.stop(log) - } - ctx, cancel := context.WithCancel(ctx) - r.cancel = cancel - r.wg.Add(1) - go func() { - defer r.wg.Done() - - log.Info(logs.BlobstoreRebuildStarted) - if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, r.limiter); err != nil { - log.Warn(logs.FailedToRebuildBlobstore, zap.Error(err)) - } else { - log.Info(logs.BlobstoreRebuildCompletedSuccessfully) - } - }() -} - -func (r *rebuilder) Stop(log *logger.Logger) { - r.mtx.Lock() - defer r.mtx.Unlock() - - r.stop(log) -} - -func (r *rebuilder) stop(log *logger.Logger) { - if r.cancel == nil { - return - } - - r.cancel() - r.wg.Wait() - r.cancel = nil - log.Info(logs.BlobstoreRebuildStopped) -} - -var errMBIsNotAvailable = errors.New("metabase is not available") - -type mbStorageIDUpdate struct { - mb *meta.DB -} - -func (u *mbStorageIDUpdate) UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - if u.mb == nil { - return errMBIsNotAvailable - } - - var prm meta.UpdateStorageIDPrm - prm.SetAddress(addr) - prm.SetStorageID(storageID) - _, err := u.mb.UpdateStorageID(ctx, prm) - return err -} diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index ac389b5069..1eaee8815b 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -151,7 +151,7 @@ func defaultCfg() *cfg { log: &logger.Logger{Logger: zap.L()}, gcCfg: defaultGCCfg(), reportErrorFunc: func(string, string, error) {}, - rebuildLimiter: &noopRebuildLimiter{}, + rebuildLimiter: newRebuildLimiter(1), zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, zeroCountContainersCallback: func(context.Context, []cid.ID) {}, } From 6b6eabe41cd5750257adc3041f6a1c28df8197c7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 29 Aug 2024 12:11:19 +0300 Subject: [PATCH 0790/1413] [#1337] cli: Add `control shards rebuild` command Signed-off-by: Dmitrii Stepanov --- .../modules/control/rebuild_shards.go | 88 ++ cmd/frostfs-cli/modules/control/shards.go | 1 + pkg/local_object_storage/engine/rebuild.go | 90 ++ pkg/local_object_storage/shard/rebuild.go | 33 + pkg/services/control/rpc.go | 14 + pkg/services/control/server/rebuild.go | 59 ++ pkg/services/control/service.proto | 29 + pkg/services/control/service_frostfs.pb.go | 918 ++++++++++++++++++ pkg/services/control/service_grpc.pb.go | 39 + 9 files changed, 1271 insertions(+) create mode 100644 cmd/frostfs-cli/modules/control/rebuild_shards.go create mode 100644 pkg/local_object_storage/engine/rebuild.go create mode 100644 pkg/services/control/server/rebuild.go diff --git a/cmd/frostfs-cli/modules/control/rebuild_shards.go b/cmd/frostfs-cli/modules/control/rebuild_shards.go new file mode 100644 index 0000000000..e2b4087124 --- /dev/null +++ b/cmd/frostfs-cli/modules/control/rebuild_shards.go @@ -0,0 +1,88 @@ +package control + +import ( + "fmt" + + rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "github.com/mr-tron/base58" + "github.com/spf13/cobra" +) + +const ( + fillPercentFlag = "fill_percent" +) + +var shardsRebuildCmd = &cobra.Command{ + Use: "rebuild", + Short: "Rebuild shards", + Long: "Rebuild reclaims storage occupied by dead objects and adjusts the storage structure according to the configuration (for blobovnicza only now)", + Run: shardsRebuild, +} + +func shardsRebuild(cmd *cobra.Command, _ []string) { + pk := key.Get(cmd) + + req := &control.StartShardRebuildRequest{ + Body: &control.StartShardRebuildRequest_Body{ + Shard_ID: getShardIDList(cmd), + TargetFillPercent: getFillPercentValue(cmd), + ConcurrencyLimit: getConcurrencyValue(cmd), + }, + } + + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var resp *control.StartShardRebuildResponse + var err error + err = cli.ExecRaw(func(client *rawclient.Client) error { + resp, err = control.StartShardRebuild(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + var success, failed uint + for _, res := range resp.GetBody().GetResults() { + if res.GetSuccess() { + success++ + cmd.Printf("Shard %s: OK\n", base58.Encode(res.GetShard_ID())) + } else { + failed++ + cmd.Printf("Shard %s: failed with error %q\n", base58.Encode(res.GetShard_ID()), res.GetError()) + } + } + cmd.Printf("Total: %d success, %d failed\n", success, failed) +} + +func getFillPercentValue(cmd *cobra.Command) uint32 { + v, _ := cmd.Flags().GetUint32(fillPercentFlag) + if v <= 0 || v > 100 { + commonCmd.ExitOnErr(cmd, "invalid fill_percent value", fmt.Errorf("fill_percent value must be (0, 100], current value: %d", v)) + } + return v +} + +func getConcurrencyValue(cmd *cobra.Command) uint32 { + v, _ := cmd.Flags().GetUint32(concurrencyFlag) + if v <= 0 || v > 10000 { + commonCmd.ExitOnErr(cmd, "invalid concurrency value", fmt.Errorf("concurrency value must be (0, 10 000], current value: %d", v)) + } + return v +} + +func initControlShardRebuildCmd() { + initControlFlags(shardsRebuildCmd) + + flags := shardsRebuildCmd.Flags() + flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") + flags.Bool(shardAllFlag, false, "Process all shards") + flags.Uint32(fillPercentFlag, 80, "Target fill percent to reclaim space") + flags.Uint32(concurrencyFlag, 20, "Maximum count of concurrently rebuilding files") + setShardModeCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag) +} diff --git a/cmd/frostfs-cli/modules/control/shards.go b/cmd/frostfs-cli/modules/control/shards.go index d8198c426f..d6c2a0b9ba 100644 --- a/cmd/frostfs-cli/modules/control/shards.go +++ b/cmd/frostfs-cli/modules/control/shards.go @@ -28,4 +28,5 @@ func initControlShardsCmd() { initControlDoctorCmd() initControlShardsWritecacheCmd() initControlShardsDetachCmd() + initControlShardRebuildCmd() } diff --git a/pkg/local_object_storage/engine/rebuild.go b/pkg/local_object_storage/engine/rebuild.go new file mode 100644 index 0000000000..3970aae89e --- /dev/null +++ b/pkg/local_object_storage/engine/rebuild.go @@ -0,0 +1,90 @@ +package engine + +import ( + "context" + "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" + "golang.org/x/sync/errgroup" +) + +type RebuildPrm struct { + ShardIDs []*shard.ID + ConcurrencyLimit uint32 + TargetFillPercent uint32 +} + +type ShardRebuildResult struct { + ShardID *shard.ID + Success bool + ErrorMsg string +} + +type RebuildRes struct { + ShardResults []ShardRebuildResult +} + +func (e *StorageEngine) Rebuild(ctx context.Context, prm RebuildPrm) (RebuildRes, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Rebuild", + trace.WithAttributes( + attribute.Int("shard_id_count", len(prm.ShardIDs)), + attribute.Int64("target_fill_percent", int64(prm.TargetFillPercent)), + attribute.Int64("concurrency_limit", int64(prm.ConcurrencyLimit)), + )) + defer span.End() + + res := RebuildRes{ + ShardResults: make([]ShardRebuildResult, 0, len(prm.ShardIDs)), + } + resGuard := &sync.Mutex{} + + limiter := newRebuildLimiter(prm.ConcurrencyLimit) + + eg, egCtx := errgroup.WithContext(ctx) + for _, shardID := range prm.ShardIDs { + eg.Go(func() error { + e.mtx.RLock() + sh, ok := e.shards[shardID.String()] + e.mtx.RUnlock() + + if !ok { + resGuard.Lock() + defer resGuard.Unlock() + res.ShardResults = append(res.ShardResults, ShardRebuildResult{ + ShardID: shardID, + ErrorMsg: errShardNotFound.Error(), + }) + return nil + } + + err := sh.ScheduleRebuild(egCtx, shard.RebuildPrm{ + ConcurrencyLimiter: limiter, + TargetFillPercent: prm.TargetFillPercent, + }) + + resGuard.Lock() + defer resGuard.Unlock() + + if err != nil { + res.ShardResults = append(res.ShardResults, ShardRebuildResult{ + ShardID: shardID, + ErrorMsg: err.Error(), + }) + } else { + res.ShardResults = append(res.ShardResults, ShardRebuildResult{ + ShardID: shardID, + Success: true, + }) + } + return nil + }) + } + + if err := eg.Wait(); err != nil { + return RebuildRes{}, err + } + return res, nil +} diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index 998fcf08b9..f8051999e9 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -10,7 +10,10 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "go.uber.org/zap" ) @@ -171,3 +174,33 @@ func (u *mbStorageIDUpdate) UpdateStorageID(ctx context.Context, addr oid.Addres _, err := u.mb.UpdateStorageID(ctx, prm) return err } + +type RebuildPrm struct { + ConcurrencyLimiter RebuildWorkerLimiter + TargetFillPercent uint32 +} + +func (s *Shard) ScheduleRebuild(ctx context.Context, p RebuildPrm) error { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.ScheduleRebuild", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.Int64("target_fill_percent", int64(p.TargetFillPercent)), + )) + defer span.End() + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.ReadOnly() { + return ErrReadOnlyMode + } + if s.info.Mode.NoMetabase() { + return ErrDegradedMode + } + + return s.rb.ScheduleRebuild(ctx, p.ConcurrencyLimiter, common.RebuildAction{ + SchemaChange: true, + FillPercent: true, + FillPercentValue: int(p.TargetFillPercent), + }) +} diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index a90e58a651..80aece0088 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -30,6 +30,7 @@ const ( rpcSealWriteCache = "SealWriteCache" rpcListTargetsLocalOverrides = "ListTargetsLocalOverrides" rpcDetachShards = "DetachShards" + rpcStartShardRebuild = "StartShardRebuild" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -361,3 +362,16 @@ func DetachShards( return wResp.message, nil } + +// StartShardRebuild executes ControlService.StartShardRebuild RPC. +func StartShardRebuild(cli *client.Client, req *StartShardRebuildRequest, opts ...client.CallOption) (*StartShardRebuildResponse, error) { + wResp := newResponseWrapper[StartShardRebuildResponse]() + wReq := &requestWrapper{m: req} + + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcStartShardRebuild), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.message, nil +} diff --git a/pkg/services/control/server/rebuild.go b/pkg/services/control/server/rebuild.go new file mode 100644 index 0000000000..6ddfb8bf4c --- /dev/null +++ b/pkg/services/control/server/rebuild.go @@ -0,0 +1,59 @@ +package control + +import ( + "context" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Server) StartShardRebuild(ctx context.Context, req *control.StartShardRebuildRequest) (*control.StartShardRebuildResponse, error) { + err := s.isValidRequest(req) + if err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + if req.GetBody().GetConcurrencyLimit() == 0 || req.GetBody().GetConcurrencyLimit() > 10000 { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("concurrency limit must be in range (0; 10 000], current value %d", req.GetBody().GetConcurrencyLimit())) + } + + if req.GetBody().GetTargetFillPercent() == 0 || req.GetBody().GetTargetFillPercent() > 100 { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("fill percent must be in range (0; 100], current value %d", req.GetBody().GetTargetFillPercent())) + } + + prm := engine.RebuildPrm{ + ShardIDs: s.getShardIDList(req.GetBody().GetShard_ID()), + ConcurrencyLimit: req.GetBody().GetConcurrencyLimit(), + TargetFillPercent: req.GetBody().GetTargetFillPercent(), + } + + res, err := s.s.Rebuild(ctx, prm) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + + resp := &control.StartShardRebuildResponse{Body: &control.StartShardRebuildResponse_Body{}} + for _, r := range res.ShardResults { + if r.Success { + resp.Body.Results = append(resp.GetBody().GetResults(), control.StartShardRebuildResponse_Body_Status{ + Shard_ID: *r.ShardID, + Success: true, + }) + } else { + resp.Body.Results = append(resp.GetBody().GetResults(), control.StartShardRebuildResponse_Body_Status{ + Shard_ID: *r.ShardID, + Error: r.ErrorMsg, + }) + } + } + + err = ctrlmessage.Sign(s.key, resp) + if err != nil { + return nil, err + } + return resp, nil +} diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index d6639cb489..04994328a7 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -91,6 +91,9 @@ service ControlService { // DetachShards detaches and closes shards. rpc DetachShards(DetachShardsRequest) returns (DetachShardsResponse); + + // StartShardRebuild starts shard rebuild process. + rpc StartShardRebuild(StartShardRebuildRequest) returns (StartShardRebuildResponse); } // Health check request. @@ -699,3 +702,29 @@ message DetachShardsResponse { Signature signature = 2; } + +message StartShardRebuildRequest { + message Body { + repeated bytes shard_ID = 1; + uint32 target_fill_percent = 2; + uint32 concurrency_limit = 3; + } + + Body body = 1; + Signature signature = 2; +} + +message StartShardRebuildResponse { + message Body { + message Status { + bytes shard_ID = 1; + bool success = 2; + string error = 3; + } + repeated Status results = 1; + } + + Body body = 1; + + Signature signature = 2; +} diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index eb0d95c64e..019cac290b 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -15023,3 +15023,921 @@ func (x *DetachShardsResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { in.Consumed() } } + +type StartShardRebuildRequest_Body struct { + Shard_ID [][]byte `json:"shardID"` + TargetFillPercent uint32 `json:"targetFillPercent"` + ConcurrencyLimit uint32 `json:"concurrencyLimit"` +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardRebuildRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardRebuildRequest_Body)(nil) + _ json.Marshaler = (*StartShardRebuildRequest_Body)(nil) + _ json.Unmarshaler = (*StartShardRebuildRequest_Body)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *StartShardRebuildRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.RepeatedBytesSize(1, x.Shard_ID) + size += proto.UInt32Size(2, x.TargetFillPercent) + size += proto.UInt32Size(3, x.ConcurrencyLimit) + return size +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardRebuildRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *StartShardRebuildRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Shard_ID { + mm.AppendBytes(1, x.Shard_ID[j]) + } + if x.TargetFillPercent != 0 { + mm.AppendUint32(2, x.TargetFillPercent) + } + if x.ConcurrencyLimit != 0 { + mm.AppendUint32(3, x.ConcurrencyLimit) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardRebuildRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardRebuildRequest_Body") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + case 2: // TargetFillPercent + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "TargetFillPercent") + } + x.TargetFillPercent = data + case 3: // ConcurrencyLimit + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ConcurrencyLimit") + } + x.ConcurrencyLimit = data + } + } + return nil +} +func (x *StartShardRebuildRequest_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *StartShardRebuildRequest_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} +func (x *StartShardRebuildRequest_Body) GetTargetFillPercent() uint32 { + if x != nil { + return x.TargetFillPercent + } + return 0 +} +func (x *StartShardRebuildRequest_Body) SetTargetFillPercent(v uint32) { + x.TargetFillPercent = v +} +func (x *StartShardRebuildRequest_Body) GetConcurrencyLimit() uint32 { + if x != nil { + return x.ConcurrencyLimit + } + return 0 +} +func (x *StartShardRebuildRequest_Body) SetConcurrencyLimit(v uint32) { + x.ConcurrencyLimit = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardRebuildRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardRebuildRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + out.Base64Bytes(x.Shard_ID[i]) + } + out.RawByte(']') + } + { + const prefix string = ",\"targetFillPercent\":" + out.RawString(prefix) + out.Uint32(x.TargetFillPercent) + } + { + const prefix string = ",\"concurrencyLimit\":" + out.RawString(prefix) + out.Uint32(x.ConcurrencyLimit) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardRebuildRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardRebuildRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + f = in.Bytes() + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + case "targetFillPercent": + { + var f uint32 + f = in.Uint32() + x.TargetFillPercent = f + } + case "concurrencyLimit": + { + var f uint32 + f = in.Uint32() + x.ConcurrencyLimit = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StartShardRebuildRequest struct { + Body *StartShardRebuildRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardRebuildRequest)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardRebuildRequest)(nil) + _ json.Marshaler = (*StartShardRebuildRequest)(nil) + _ json.Unmarshaler = (*StartShardRebuildRequest)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *StartShardRebuildRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *StartShardRebuildRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *StartShardRebuildRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().MarshalProtobuf(buf), nil +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardRebuildRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *StartShardRebuildRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardRebuildRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardRebuildRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(StartShardRebuildRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *StartShardRebuildRequest) GetBody() *StartShardRebuildRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *StartShardRebuildRequest) SetBody(v *StartShardRebuildRequest_Body) { + x.Body = v +} +func (x *StartShardRebuildRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *StartShardRebuildRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardRebuildRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardRebuildRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardRebuildRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardRebuildRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *StartShardRebuildRequest_Body + f = new(StartShardRebuildRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StartShardRebuildResponse_Body_Status struct { + Shard_ID []byte `json:"shardID"` + Success bool `json:"success"` + Error string `json:"error"` +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardRebuildResponse_Body_Status)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardRebuildResponse_Body_Status)(nil) + _ json.Marshaler = (*StartShardRebuildResponse_Body_Status)(nil) + _ json.Unmarshaler = (*StartShardRebuildResponse_Body_Status)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *StartShardRebuildResponse_Body_Status) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.BytesSize(1, x.Shard_ID) + size += proto.BoolSize(2, x.Success) + size += proto.StringSize(3, x.Error) + return size +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardRebuildResponse_Body_Status) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *StartShardRebuildResponse_Body_Status) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.Shard_ID) != 0 { + mm.AppendBytes(1, x.Shard_ID) + } + if x.Success { + mm.AppendBool(2, x.Success) + } + if len(x.Error) != 0 { + mm.AppendString(3, x.Error) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardRebuildResponse_Body_Status) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardRebuildResponse_Body_Status") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = data + case 2: // Success + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Success") + } + x.Success = data + case 3: // Error + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Error") + } + x.Error = data + } + } + return nil +} +func (x *StartShardRebuildResponse_Body_Status) GetShard_ID() []byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *StartShardRebuildResponse_Body_Status) SetShard_ID(v []byte) { + x.Shard_ID = v +} +func (x *StartShardRebuildResponse_Body_Status) GetSuccess() bool { + if x != nil { + return x.Success + } + return false +} +func (x *StartShardRebuildResponse_Body_Status) SetSuccess(v bool) { + x.Success = v +} +func (x *StartShardRebuildResponse_Body_Status) GetError() string { + if x != nil { + return x.Error + } + return "" +} +func (x *StartShardRebuildResponse_Body_Status) SetError(v string) { + x.Error = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardRebuildResponse_Body_Status) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardRebuildResponse_Body_Status) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"shardID\":" + out.RawString(prefix[1:]) + out.Base64Bytes(x.Shard_ID) + } + { + const prefix string = ",\"success\":" + out.RawString(prefix) + out.Bool(x.Success) + } + { + const prefix string = ",\"error\":" + out.RawString(prefix) + out.String(x.Error) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardRebuildResponse_Body_Status) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardRebuildResponse_Body_Status) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + f = in.Bytes() + x.Shard_ID = f + } + case "success": + { + var f bool + f = in.Bool() + x.Success = f + } + case "error": + { + var f string + f = in.String() + x.Error = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StartShardRebuildResponse_Body struct { + Results []StartShardRebuildResponse_Body_Status `json:"results"` +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardRebuildResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardRebuildResponse_Body)(nil) + _ json.Marshaler = (*StartShardRebuildResponse_Body)(nil) + _ json.Unmarshaler = (*StartShardRebuildResponse_Body)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *StartShardRebuildResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + for i := range x.Results { + size += proto.NestedStructureSizeUnchecked(1, &x.Results[i]) + } + return size +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardRebuildResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *StartShardRebuildResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for i := range x.Results { + x.Results[i].EmitProtobuf(mm.AppendMessage(1)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardRebuildResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardRebuildResponse_Body") + } + switch fc.FieldNum { + case 1: // Results + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Results") + } + x.Results = append(x.Results, StartShardRebuildResponse_Body_Status{}) + ff := &x.Results[len(x.Results)-1] + if err := ff.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *StartShardRebuildResponse_Body) GetResults() []StartShardRebuildResponse_Body_Status { + if x != nil { + return x.Results + } + return nil +} +func (x *StartShardRebuildResponse_Body) SetResults(v []StartShardRebuildResponse_Body_Status) { + x.Results = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardRebuildResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardRebuildResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"results\":" + out.RawString(prefix[1:]) + out.RawByte('[') + for i := range x.Results { + if i != 0 { + out.RawByte(',') + } + x.Results[i].MarshalEasyJSON(out) + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardRebuildResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardRebuildResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "results": + { + var f StartShardRebuildResponse_Body_Status + var list []StartShardRebuildResponse_Body_Status + in.Delim('[') + for !in.IsDelim(']') { + f = StartShardRebuildResponse_Body_Status{} + f.UnmarshalEasyJSON(in) + list = append(list, f) + in.WantComma() + } + x.Results = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type StartShardRebuildResponse struct { + Body *StartShardRebuildResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*StartShardRebuildResponse)(nil) + _ encoding.ProtoUnmarshaler = (*StartShardRebuildResponse)(nil) + _ json.Marshaler = (*StartShardRebuildResponse)(nil) + _ json.Unmarshaler = (*StartShardRebuildResponse)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *StartShardRebuildResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *StartShardRebuildResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *StartShardRebuildResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().MarshalProtobuf(buf), nil +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *StartShardRebuildResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *StartShardRebuildResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *StartShardRebuildResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "StartShardRebuildResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(StartShardRebuildResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *StartShardRebuildResponse) GetBody() *StartShardRebuildResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *StartShardRebuildResponse) SetBody(v *StartShardRebuildResponse_Body) { + x.Body = v +} +func (x *StartShardRebuildResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *StartShardRebuildResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *StartShardRebuildResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *StartShardRebuildResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + out.RawByte('{') + { + const prefix string = ",\"body\":" + out.RawString(prefix[1:]) + x.Body.MarshalEasyJSON(out) + } + { + const prefix string = ",\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *StartShardRebuildResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *StartShardRebuildResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *StartShardRebuildResponse_Body + f = new(StartShardRebuildResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index fa9de974a1..f5cfefa857 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -41,6 +41,7 @@ const ( ControlService_ListTargetsLocalOverrides_FullMethodName = "/control.ControlService/ListTargetsLocalOverrides" ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" ControlService_DetachShards_FullMethodName = "/control.ControlService/DetachShards" + ControlService_StartShardRebuild_FullMethodName = "/control.ControlService/StartShardRebuild" ) // ControlServiceClient is the client API for ControlService service. @@ -97,6 +98,8 @@ type ControlServiceClient interface { SealWriteCache(ctx context.Context, in *SealWriteCacheRequest, opts ...grpc.CallOption) (*SealWriteCacheResponse, error) // DetachShards detaches and closes shards. DetachShards(ctx context.Context, in *DetachShardsRequest, opts ...grpc.CallOption) (*DetachShardsResponse, error) + // StartShardRebuild starts shard rebuild process. + StartShardRebuild(ctx context.Context, in *StartShardRebuildRequest, opts ...grpc.CallOption) (*StartShardRebuildResponse, error) } type controlServiceClient struct { @@ -305,6 +308,15 @@ func (c *controlServiceClient) DetachShards(ctx context.Context, in *DetachShard return out, nil } +func (c *controlServiceClient) StartShardRebuild(ctx context.Context, in *StartShardRebuildRequest, opts ...grpc.CallOption) (*StartShardRebuildResponse, error) { + out := new(StartShardRebuildResponse) + err := c.cc.Invoke(ctx, ControlService_StartShardRebuild_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ControlServiceServer is the server API for ControlService service. // All implementations should embed UnimplementedControlServiceServer // for forward compatibility @@ -359,6 +371,8 @@ type ControlServiceServer interface { SealWriteCache(context.Context, *SealWriteCacheRequest) (*SealWriteCacheResponse, error) // DetachShards detaches and closes shards. DetachShards(context.Context, *DetachShardsRequest) (*DetachShardsResponse, error) + // StartShardRebuild starts shard rebuild process. + StartShardRebuild(context.Context, *StartShardRebuildRequest) (*StartShardRebuildResponse, error) } // UnimplementedControlServiceServer should be embedded to have forward compatible implementations. @@ -431,6 +445,9 @@ func (UnimplementedControlServiceServer) SealWriteCache(context.Context, *SealWr func (UnimplementedControlServiceServer) DetachShards(context.Context, *DetachShardsRequest) (*DetachShardsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DetachShards not implemented") } +func (UnimplementedControlServiceServer) StartShardRebuild(context.Context, *StartShardRebuildRequest) (*StartShardRebuildResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method StartShardRebuild not implemented") +} // UnsafeControlServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ControlServiceServer will @@ -839,6 +856,24 @@ func _ControlService_DetachShards_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _ControlService_StartShardRebuild_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StartShardRebuildRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).StartShardRebuild(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_StartShardRebuild_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).StartShardRebuild(ctx, req.(*StartShardRebuildRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ControlService_ServiceDesc is the grpc.ServiceDesc for ControlService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -934,6 +969,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DetachShards", Handler: _ControlService_DetachShards_Handler, }, + { + MethodName: "StartShardRebuild", + Handler: _ControlService_StartShardRebuild_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pkg/services/control/service.proto", From a61201a98753c4522a1169abe5b42f2631f639ad Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 29 Aug 2024 13:51:09 +0300 Subject: [PATCH 0791/1413] [#1337] config: Move `rebuild_worker_count` to shard section This makes it simple to limit performance degradation for every shard because of rebuild. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/control/shards.go | 1 + cmd/frostfs-node/config.go | 7 ++--- cmd/frostfs-node/config/engine/config.go | 11 -------- cmd/frostfs-node/config/engine/config_test.go | 4 +-- .../config/engine/shard/config.go | 15 +++++++++++ config/example/node.env | 2 +- config/example/node.json | 2 +- config/example/node.yaml | 2 +- docs/storage-node-configuration.md | 1 + pkg/local_object_storage/engine/engine.go | 16 ++---------- pkg/local_object_storage/engine/rebuild.go | 2 +- .../engine/rebuild_limiter.go | 26 ------------------- pkg/local_object_storage/engine/shards.go | 1 - pkg/local_object_storage/shard/control.go | 2 +- pkg/local_object_storage/shard/rebuild.go | 2 +- pkg/local_object_storage/shard/shard.go | 10 +++---- 16 files changed, 36 insertions(+), 68 deletions(-) delete mode 100644 pkg/local_object_storage/engine/rebuild_limiter.go diff --git a/cmd/frostfs-cli/modules/control/shards.go b/cmd/frostfs-cli/modules/control/shards.go index d6c2a0b9ba..329cb91006 100644 --- a/cmd/frostfs-cli/modules/control/shards.go +++ b/cmd/frostfs-cli/modules/control/shards.go @@ -19,6 +19,7 @@ func initControlShardsCmd() { shardsCmd.AddCommand(doctorCmd) shardsCmd.AddCommand(writecacheShardCmd) shardsCmd.AddCommand(shardsDetachCmd) + shardsCmd.AddCommand(shardsRebuildCmd) initControlShardsListCmd() initControlSetShardModeCmd() diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 1102814185..b59518d14a 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -109,7 +109,6 @@ type applicationConfiguration struct { shardPoolSize uint32 shards []shardCfg lowMem bool - rebuildWorkers uint32 } // if need to run node in compatibility with other versions mode @@ -127,6 +126,8 @@ type shardCfg struct { refillMetabaseWorkersCount int mode shardmode.Mode + rebuildWorkersCount uint32 + metaCfg struct { path string perm fs.FileMode @@ -230,7 +231,6 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { a.EngineCfg.errorThreshold = engineconfig.ShardErrorThreshold(c) a.EngineCfg.shardPoolSize = engineconfig.ShardPoolSize(c) a.EngineCfg.lowMem = engineconfig.EngineLowMemoryConsumption(c) - a.EngineCfg.rebuildWorkers = engineconfig.EngineRebuildWorkersCount(c) return engineconfig.IterateShards(c, false, func(sc *shardconfig.Config) error { return a.updateShardConfig(c, sc) }) } @@ -240,6 +240,7 @@ func (a *applicationConfiguration) updateShardConfig(c *config.Config, oldConfig newConfig.refillMetabase = oldConfig.RefillMetabase() newConfig.refillMetabaseWorkersCount = oldConfig.RefillMetabaseWorkersCount() + newConfig.rebuildWorkersCount = oldConfig.RebuildWorkerCount() newConfig.mode = oldConfig.Mode() newConfig.compress = oldConfig.Compress() newConfig.estimateCompressibility = oldConfig.EstimateCompressibility() @@ -835,7 +836,6 @@ func (c *cfg) engineOpts() []engine.Option { engine.WithErrorThreshold(c.EngineCfg.errorThreshold), engine.WithLogger(c.log), engine.WithLowMemoryConsumption(c.EngineCfg.lowMem), - engine.WithRebuildWorkersCount(c.EngineCfg.rebuildWorkers), ) if c.metricsCollector != nil { @@ -998,6 +998,7 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID shard.WithLogger(c.log), shard.WithRefillMetabase(shCfg.refillMetabase), shard.WithRefillMetabaseWorkersCount(shCfg.refillMetabaseWorkersCount), + shard.WithRebuildWorkersCount(shCfg.rebuildWorkersCount), shard.WithMode(shCfg.mode), shard.WithBlobStorOptions(blobstoreOpts...), shard.WithMetaBaseOptions(mbOptions...), diff --git a/cmd/frostfs-node/config/engine/config.go b/cmd/frostfs-node/config/engine/config.go index baa4e3c9d3..c944d1c58e 100644 --- a/cmd/frostfs-node/config/engine/config.go +++ b/cmd/frostfs-node/config/engine/config.go @@ -15,9 +15,6 @@ const ( // ShardPoolSizeDefault is a default value of routine pool size per-shard to // process object PUT operations in a storage engine. ShardPoolSizeDefault = 20 - // RebuildWorkersCountDefault is a default value of the workers count to - // process storage rebuild operations in a storage engine. - RebuildWorkersCountDefault = 100 ) // ErrNoShardConfigured is returned when at least 1 shard is required but none are found. @@ -91,11 +88,3 @@ func ShardErrorThreshold(c *config.Config) uint32 { func EngineLowMemoryConsumption(c *config.Config) bool { return config.BoolSafe(c.Sub(subsection), "low_mem") } - -// EngineRebuildWorkersCount returns value of "rebuild_workers_count" config parmeter from "storage" section. -func EngineRebuildWorkersCount(c *config.Config) uint32 { - if v := config.Uint32Safe(c.Sub(subsection), "rebuild_workers_count"); v > 0 { - return v - } - return RebuildWorkersCountDefault -} diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index d53207ccc0..464d725561 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -39,7 +39,6 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 0, engineconfig.ShardErrorThreshold(empty)) require.EqualValues(t, engineconfig.ShardPoolSizeDefault, engineconfig.ShardPoolSize(empty)) require.EqualValues(t, mode.ReadWrite, shardconfig.From(empty).Mode()) - require.EqualValues(t, engineconfig.RebuildWorkersCountDefault, engineconfig.EngineRebuildWorkersCount(empty)) }) const path = "../../../../config/example/node" @@ -49,7 +48,6 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 100, engineconfig.ShardErrorThreshold(c)) require.EqualValues(t, 15, engineconfig.ShardPoolSize(c)) - require.EqualValues(t, uint32(1000), engineconfig.EngineRebuildWorkersCount(c)) err := engineconfig.IterateShards(c, true, func(sc *shardconfig.Config) error { defer func() { @@ -121,6 +119,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, false, sc.RefillMetabase()) require.Equal(t, mode.ReadOnly, sc.Mode()) require.Equal(t, 100, sc.RefillMetabaseWorkersCount()) + require.Equal(t, uint32(1000), sc.RebuildWorkerCount()) case 1: require.Equal(t, "tmp/1/blob/pilorama.db", pl.Path()) require.Equal(t, fs.FileMode(0o644), pl.Perm()) @@ -176,6 +175,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, true, sc.RefillMetabase()) require.Equal(t, mode.ReadWrite, sc.Mode()) require.Equal(t, shardconfig.RefillMetabaseWorkersCountDefault, sc.RefillMetabaseWorkersCount()) + require.Equal(t, uint32(shardconfig.RebuildWorkersCountDefault), sc.RebuildWorkerCount()) } return nil }) diff --git a/cmd/frostfs-node/config/engine/shard/config.go b/cmd/frostfs-node/config/engine/shard/config.go index 0620c9f630..ec9df0e89e 100644 --- a/cmd/frostfs-node/config/engine/shard/config.go +++ b/cmd/frostfs-node/config/engine/shard/config.go @@ -19,6 +19,7 @@ const ( SmallSizeLimitDefault = 1 << 20 EstimateCompressibilityThresholdDefault = 0.1 RefillMetabaseWorkersCountDefault = 500 + RebuildWorkersCountDefault = 5 ) // From wraps config section into Config. @@ -149,6 +150,20 @@ func (x *Config) RefillMetabaseWorkersCount() int { return RefillMetabaseWorkersCountDefault } +// RebuildWorkersCount returns the value of "resync_metabase_worker_count" config parameter. +// +// Returns RebuildWorkersCountDefault if the value is not a positive number. +func (x *Config) RebuildWorkerCount() uint32 { + v := config.Uint32Safe( + (*config.Config)(x), + "rebuild_worker_count", + ) + if v > 0 { + return v + } + return RebuildWorkersCountDefault +} + // Mode return the value of "mode" config parameter. // // Panics if read the value is not one of predefined diff --git a/config/example/node.env b/config/example/node.env index b39423ffb8..1eccd8a5de 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -90,11 +90,11 @@ FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME=10 # Storage engine section FROSTFS_STORAGE_SHARD_POOL_SIZE=15 FROSTFS_STORAGE_SHARD_RO_ERROR_THRESHOLD=100 -FROSTFS_STORAGE_REBUILD_WORKERS_COUNT=1000 ## 0 shard ### Flag to refill Metabase from BlobStor FROSTFS_STORAGE_SHARD_0_RESYNC_METABASE=false FROSTFS_STORAGE_SHARD_0_RESYNC_METABASE_WORKER_COUNT=100 +FROSTFS_STORAGE_SHARD_0_REBUILD_WORKER_COUNT=1000 ### Flag to set shard mode FROSTFS_STORAGE_SHARD_0_MODE=read-only ### Write cache config diff --git a/config/example/node.json b/config/example/node.json index fe2de0e018..be7ced77a1 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -135,12 +135,12 @@ "storage": { "shard_pool_size": 15, "shard_ro_error_threshold": 100, - "rebuild_workers_count": 1000, "shard": { "0": { "mode": "read-only", "resync_metabase": false, "resync_metabase_worker_count": 100, + "rebuild_worker_count": 1000, "writecache": { "enabled": false, "no_sync": true, diff --git a/config/example/node.yaml b/config/example/node.yaml index cc339a427f..4b97206551 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -117,7 +117,6 @@ storage: # note: shard configuration can be omitted for relay node (see `node.relay`) shard_pool_size: 15 # size of per-shard worker pools used for PUT operations shard_ro_error_threshold: 100 # amount of errors to occur before shard is made read-only (default: 0, ignore errors) - rebuild_workers_count: 1000 # count of rebuild storage concurrent workers shard: default: # section with the default shard parameters @@ -165,6 +164,7 @@ storage: # disabled (do not work with the shard, allows to not remove it from the config) resync_metabase: false # sync metabase with blobstor on start, expensive, leave false until complete understanding resync_metabase_worker_count: 100 + rebuild_worker_count: 1000 # count of rebuild storage concurrent workers writecache: enabled: false diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 5bf35cd657..f390d84a44 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -189,6 +189,7 @@ The following table describes configuration for each shard. | `mode` | `string` | `read-write` | Shard Mode.
Possible values: `read-write`, `read-only`, `degraded`, `degraded-read-only`, `disabled` | | `resync_metabase` | `bool` | `false` | Flag to enable metabase resync on start. | | `resync_metabase_worker_count` | `int` | `1000` | Count of concurrent workers to resync metabase. | +| `rebuild_worker_count` | `int` | `5` | Count of concurrent workers to rebuild blobstore. | | `writecache` | [Writecache config](#writecache-subsection) | | Write-cache configuration. | | `metabase` | [Metabase config](#metabase-subsection) | | Metabase configuration. | | `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index b87d77e6c2..5e883a6419 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -40,7 +40,6 @@ type StorageEngine struct { err error } evacuateLimiter *evacuationLimiter - rebuildLimiter *rebuildLimiter } type shardWrapper struct { @@ -213,16 +212,13 @@ type cfg struct { lowMem bool - rebuildWorkersCount uint32 - containerSource atomic.Pointer[containerSource] } func defaultCfg() *cfg { res := &cfg{ - log: &logger.Logger{Logger: zap.L()}, - shardPoolSize: 20, - rebuildWorkersCount: 100, + log: &logger.Logger{Logger: zap.L()}, + shardPoolSize: 20, } res.containerSource.Store(&containerSource{}) return res @@ -243,7 +239,6 @@ func New(opts ...Option) *StorageEngine { closeCh: make(chan struct{}), setModeCh: make(chan setModeRequest), evacuateLimiter: &evacuationLimiter{}, - rebuildLimiter: newRebuildLimiter(c.rebuildWorkersCount), } } @@ -282,13 +277,6 @@ func WithLowMemoryConsumption(lowMemCons bool) Option { } } -// WithRebuildWorkersCount returns an option to set the count of concurrent rebuild workers. -func WithRebuildWorkersCount(count uint32) Option { - return func(c *cfg) { - c.rebuildWorkersCount = count - } -} - // SetContainerSource sets container source. func (e *StorageEngine) SetContainerSource(cs container.Source) { e.containerSource.Store(&containerSource{cs: cs}) diff --git a/pkg/local_object_storage/engine/rebuild.go b/pkg/local_object_storage/engine/rebuild.go index 3970aae89e..83c6a54ede 100644 --- a/pkg/local_object_storage/engine/rebuild.go +++ b/pkg/local_object_storage/engine/rebuild.go @@ -41,7 +41,7 @@ func (e *StorageEngine) Rebuild(ctx context.Context, prm RebuildPrm) (RebuildRes } resGuard := &sync.Mutex{} - limiter := newRebuildLimiter(prm.ConcurrencyLimit) + limiter := shard.NewRebuildLimiter(prm.ConcurrencyLimit) eg, egCtx := errgroup.WithContext(ctx) for _, shardID := range prm.ShardIDs { diff --git a/pkg/local_object_storage/engine/rebuild_limiter.go b/pkg/local_object_storage/engine/rebuild_limiter.go deleted file mode 100644 index 28b02b0a34..0000000000 --- a/pkg/local_object_storage/engine/rebuild_limiter.go +++ /dev/null @@ -1,26 +0,0 @@ -package engine - -import "context" - -type rebuildLimiter struct { - semaphore chan struct{} -} - -func newRebuildLimiter(workersCount uint32) *rebuildLimiter { - return &rebuildLimiter{ - semaphore: make(chan struct{}, workersCount), - } -} - -func (l *rebuildLimiter) AcquireWorkSlot(ctx context.Context) error { - select { - case l.semaphore <- struct{}{}: - return nil - case <-ctx.Done(): - return ctx.Err() - } -} - -func (l *rebuildLimiter) ReleaseWorkSlot() { - <-l.semaphore -} diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 40584149ee..2ad6859e4f 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -137,7 +137,6 @@ func (e *StorageEngine) createShard(_ context.Context, opts []shard.Option) (*sh shard.WithExpiredLocksCallback(e.processExpiredLocks), shard.WithDeletedLockCallback(e.processDeletedLocks), shard.WithReportErrorFunc(e.reportShardErrorBackground), - shard.WithRebuildWorkerLimiter(e.rebuildLimiter), shard.WithZeroSizeCallback(e.processZeroSizeContainers), shard.WithZeroCountCallback(e.processZeroCountContainers), )...) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 6efe4ec379..5e9639a7bf 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -129,7 +129,7 @@ func (s *Shard) Init(ctx context.Context) error { s.gc.init(ctx) - s.rb = newRebuilder(s.rebuildLimiter) + s.rb = newRebuilder(NewRebuildLimiter(s.rebuildWorkersCount)) if !m.NoMetabase() && !s.rebuildDisabled { s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) } diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index f8051999e9..2eef456be1 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -26,7 +26,7 @@ type rebuildLimiter struct { semaphore chan struct{} } -func newRebuildLimiter(workersCount uint32) *rebuildLimiter { +func NewRebuildLimiter(workersCount uint32) RebuildWorkerLimiter { return &rebuildLimiter{ semaphore: make(chan struct{}, workersCount), } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 1eaee8815b..1e2bb79000 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -140,7 +140,7 @@ type cfg struct { reportErrorFunc func(selfID string, message string, err error) - rebuildLimiter RebuildWorkerLimiter + rebuildWorkersCount uint32 rebuildDisabled bool } @@ -151,7 +151,7 @@ func defaultCfg() *cfg { log: &logger.Logger{Logger: zap.L()}, gcCfg: defaultGCCfg(), reportErrorFunc: func(string, string, error) {}, - rebuildLimiter: newRebuildLimiter(1), + rebuildWorkersCount: 1, zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, zeroCountContainersCallback: func(context.Context, []cid.ID) {}, } @@ -384,11 +384,11 @@ func WithExpiredCollectorWorkerCount(count int) Option { } } -// WithRebuildWorkerLimiter return option to set concurrent +// WithRebuildWorkersCount return option to set concurrent // workers count of storage rebuild operation. -func WithRebuildWorkerLimiter(l RebuildWorkerLimiter) Option { +func WithRebuildWorkersCount(count uint32) Option { return func(c *cfg) { - c.rebuildLimiter = l + c.rebuildWorkersCount = count } } From edb1747af7765fe685d9d4736626c409fbde7c79 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Sun, 1 Sep 2024 12:29:02 +0300 Subject: [PATCH 0792/1413] [#1337] blobovniczatree: Add rebuild by overflow Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/rebuild.go | 11 ++- .../blobstor/blobovniczatree/rebuild_test.go | 74 +++++++++++++++++++ 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index b7f20822ef..b7b1dfd4b2 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -172,7 +172,7 @@ func (b *Blobovniczas) selectDBsDoNotMatchFillPercent(ctx context.Context, targe continue } path := filepath.Join(lvlPath, e.Name()) - resettlementRequired, err := b.fillPercentIsLow(path, target) + resettlementRequired, err := b.rebuildBySize(path, target) if err != nil { return false, err } @@ -187,14 +187,19 @@ func (b *Blobovniczas) selectDBsDoNotMatchFillPercent(ctx context.Context, targe return result, nil } -func (b *Blobovniczas) fillPercentIsLow(path string, target int) (bool, error) { +func (b *Blobovniczas) rebuildBySize(path string, targetFillPercent int) (bool, error) { shDB := b.getBlobovnicza(path) blz, err := shDB.Open() if err != nil { return false, err } defer shDB.Close() - return blz.FillPercent() < target, nil + fp := blz.FillPercent() + // accepted fill percent defines as + // |----|+++++++++++++++++|+++++++++++++++++|--------------- + // 0% target 100% 100+(100 - target) + // where `+` - accepted fill percent, `-` - not accepted fill percent + return fp < targetFillPercent || fp > 100+(100-targetFillPercent), nil } func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 62ae9ea904..e6da1c553f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -228,6 +228,80 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, b.Close()) }) + + t.Run("rebuild by overflow", func(t *testing.T) { + t.Parallel() + + dir := t.TempDir() + b := NewBlobovniczaTree( + context.Background(), + WithLogger(test.NewLogger(t)), + WithObjectSizeLimit(64*1024), + WithBlobovniczaShallowWidth(1), // single directory + WithBlobovniczaShallowDepth(1), + WithRootPath(dir), + WithBlobovniczaSize(100*1024), // 100 KB limit for each blobovnicza + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) + require.NoError(t, b.Init()) + + storageIDs := make(map[oid.Address][]byte) + for i := 0; i < 100; i++ { // 2 objects for one blobovnicza, so 50 DBs total will be created + obj := blobstortest.NewObject(64 * 1024) + data, err := obj.Marshal() + require.NoError(t, err) + var prm common.PutPrm + prm.Address = object.AddressOf(obj) + prm.RawData = data + res, err := b.Put(context.Background(), prm) + require.NoError(t, err) + storageIDs[prm.Address] = res.StorageID + } + metaStub := &storageIDUpdateStub{ + storageIDs: storageIDs, + guard: &sync.Mutex{}, + } + require.NoError(t, b.Close()) + b = NewBlobovniczaTree( + context.Background(), + WithLogger(test.NewLogger(t)), + WithObjectSizeLimit(64*1024), + WithBlobovniczaShallowWidth(1), + WithBlobovniczaShallowDepth(1), + WithRootPath(dir), + WithBlobovniczaSize(50*1024), // 50 KB limit for each blobovnicza + WithWaitBeforeDropDB(0), + WithOpenedCacheSize(1000), + WithMoveBatchSize(3)) + require.NoError(t, b.Open(mode.ComponentReadWrite)) + require.NoError(t, b.Init()) + + rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ + MetaStorage: metaStub, + WorkerLimiter: &rebuildLimiterStub{}, + Action: common.RebuildAction{ + SchemaChange: false, + FillPercent: true, + FillPercentValue: 80, + }, + }) + require.NoError(t, err) + require.Equal(t, uint64(49), rRes.FilesRemoved) + require.Equal(t, uint64(98), rRes.ObjectsMoved) // 49 DBs with 2 objects + require.Equal(t, uint64(98), metaStub.updatedCount) + + for addr, storageID := range storageIDs { + var gPrm common.GetPrm + gPrm.Address = addr + gPrm.StorageID = storageID + _, err := b.Get(context.Background(), gPrm) + require.NoError(t, err) + } + + require.NoError(t, b.Close()) + }) } func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { From d3b209c8e19edfdeb13035e1d8f4b4815cf77f08 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 4 Sep 2024 09:30:56 +0300 Subject: [PATCH 0793/1413] [#1337] shard: Disable background rebuild Since `frostfs-cli control shards rebuild` command was added, there is no need for background rebuild now. For failover tests used used value 1 to rebuild only schema change. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 4 -- cmd/frostfs-node/config/engine/config_test.go | 2 - .../config/engine/shard/config.go | 15 ----- config/example/node.env | 1 - config/example/node.json | 1 - config/example/node.yaml | 1 - docs/storage-node-configuration.md | 1 - .../blobstor/blobovniczatree/rebuild.go | 31 ++++------ .../blobovniczatree/rebuild_failover_test.go | 3 +- .../blobstor/blobovniczatree/rebuild_test.go | 28 ++------- .../blobstor/common/rebuild.go | 9 +-- pkg/local_object_storage/blobstor/rebuild.go | 4 +- pkg/local_object_storage/shard/control.go | 6 +- pkg/local_object_storage/shard/gc_test.go | 2 +- pkg/local_object_storage/shard/rebuild.go | 58 +++++++------------ pkg/local_object_storage/shard/shard.go | 21 ------- 16 files changed, 49 insertions(+), 138 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index b59518d14a..16f49a0820 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -126,8 +126,6 @@ type shardCfg struct { refillMetabaseWorkersCount int mode shardmode.Mode - rebuildWorkersCount uint32 - metaCfg struct { path string perm fs.FileMode @@ -240,7 +238,6 @@ func (a *applicationConfiguration) updateShardConfig(c *config.Config, oldConfig newConfig.refillMetabase = oldConfig.RefillMetabase() newConfig.refillMetabaseWorkersCount = oldConfig.RefillMetabaseWorkersCount() - newConfig.rebuildWorkersCount = oldConfig.RebuildWorkerCount() newConfig.mode = oldConfig.Mode() newConfig.compress = oldConfig.Compress() newConfig.estimateCompressibility = oldConfig.EstimateCompressibility() @@ -998,7 +995,6 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID shard.WithLogger(c.log), shard.WithRefillMetabase(shCfg.refillMetabase), shard.WithRefillMetabaseWorkersCount(shCfg.refillMetabaseWorkersCount), - shard.WithRebuildWorkersCount(shCfg.rebuildWorkersCount), shard.WithMode(shCfg.mode), shard.WithBlobStorOptions(blobstoreOpts...), shard.WithMetaBaseOptions(mbOptions...), diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 464d725561..ef6bf7f743 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -119,7 +119,6 @@ func TestEngineSection(t *testing.T) { require.Equal(t, false, sc.RefillMetabase()) require.Equal(t, mode.ReadOnly, sc.Mode()) require.Equal(t, 100, sc.RefillMetabaseWorkersCount()) - require.Equal(t, uint32(1000), sc.RebuildWorkerCount()) case 1: require.Equal(t, "tmp/1/blob/pilorama.db", pl.Path()) require.Equal(t, fs.FileMode(0o644), pl.Perm()) @@ -175,7 +174,6 @@ func TestEngineSection(t *testing.T) { require.Equal(t, true, sc.RefillMetabase()) require.Equal(t, mode.ReadWrite, sc.Mode()) require.Equal(t, shardconfig.RefillMetabaseWorkersCountDefault, sc.RefillMetabaseWorkersCount()) - require.Equal(t, uint32(shardconfig.RebuildWorkersCountDefault), sc.RebuildWorkerCount()) } return nil }) diff --git a/cmd/frostfs-node/config/engine/shard/config.go b/cmd/frostfs-node/config/engine/shard/config.go index ec9df0e89e..0620c9f630 100644 --- a/cmd/frostfs-node/config/engine/shard/config.go +++ b/cmd/frostfs-node/config/engine/shard/config.go @@ -19,7 +19,6 @@ const ( SmallSizeLimitDefault = 1 << 20 EstimateCompressibilityThresholdDefault = 0.1 RefillMetabaseWorkersCountDefault = 500 - RebuildWorkersCountDefault = 5 ) // From wraps config section into Config. @@ -150,20 +149,6 @@ func (x *Config) RefillMetabaseWorkersCount() int { return RefillMetabaseWorkersCountDefault } -// RebuildWorkersCount returns the value of "resync_metabase_worker_count" config parameter. -// -// Returns RebuildWorkersCountDefault if the value is not a positive number. -func (x *Config) RebuildWorkerCount() uint32 { - v := config.Uint32Safe( - (*config.Config)(x), - "rebuild_worker_count", - ) - if v > 0 { - return v - } - return RebuildWorkersCountDefault -} - // Mode return the value of "mode" config parameter. // // Panics if read the value is not one of predefined diff --git a/config/example/node.env b/config/example/node.env index 1eccd8a5de..82553745e5 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -94,7 +94,6 @@ FROSTFS_STORAGE_SHARD_RO_ERROR_THRESHOLD=100 ### Flag to refill Metabase from BlobStor FROSTFS_STORAGE_SHARD_0_RESYNC_METABASE=false FROSTFS_STORAGE_SHARD_0_RESYNC_METABASE_WORKER_COUNT=100 -FROSTFS_STORAGE_SHARD_0_REBUILD_WORKER_COUNT=1000 ### Flag to set shard mode FROSTFS_STORAGE_SHARD_0_MODE=read-only ### Write cache config diff --git a/config/example/node.json b/config/example/node.json index be7ced77a1..da108c6927 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -140,7 +140,6 @@ "mode": "read-only", "resync_metabase": false, "resync_metabase_worker_count": 100, - "rebuild_worker_count": 1000, "writecache": { "enabled": false, "no_sync": true, diff --git a/config/example/node.yaml b/config/example/node.yaml index 4b97206551..a79f482265 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -164,7 +164,6 @@ storage: # disabled (do not work with the shard, allows to not remove it from the config) resync_metabase: false # sync metabase with blobstor on start, expensive, leave false until complete understanding resync_metabase_worker_count: 100 - rebuild_worker_count: 1000 # count of rebuild storage concurrent workers writecache: enabled: false diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index f390d84a44..5bf35cd657 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -189,7 +189,6 @@ The following table describes configuration for each shard. | `mode` | `string` | `read-write` | Shard Mode.
Possible values: `read-write`, `read-only`, `degraded`, `degraded-read-only`, `disabled` | | `resync_metabase` | `bool` | `false` | Flag to enable metabase resync on start. | | `resync_metabase_worker_count` | `int` | `1000` | Count of concurrent workers to resync metabase. | -| `rebuild_worker_count` | `int` | `5` | Count of concurrent workers to rebuild blobstore. | | `writecache` | [Writecache config](#writecache-subsection) | | Write-cache configuration. | | `metabase` | [Metabase config](#metabase-subsection) | | Metabase configuration. | | `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index b7b1dfd4b2..202d38cd7b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -60,7 +60,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm b.log.Debug(logs.BlobovniczaTreeCompletedPreviousRebuildSuccess) b.log.Debug(logs.BlobovniczaTreeCollectingDBToRebuild) - dbsToMigrate, err := b.getDBsToRebuild(ctx, prm.Action) + dbsToMigrate, err := b.getDBsToRebuild(ctx, prm.FillPercent) if err != nil { b.log.Warn(logs.BlobovniczaTreeCollectingDBToRebuildFailed, zap.Error(err)) success = false @@ -94,27 +94,20 @@ func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common. return res, nil } -func (b *Blobovniczas) getDBsToRebuild(ctx context.Context, action common.RebuildAction) ([]string, error) { - schemaChange := make(map[string]struct{}) - fillPercent := make(map[string]struct{}) - var err error - if action.SchemaChange { - schemaChange, err = b.selectDBsDoNotMatchSchema(ctx) - if err != nil { - return nil, err - } +func (b *Blobovniczas) getDBsToRebuild(ctx context.Context, fillPercent int) ([]string, error) { + withSchemaChange, err := b.selectDBsDoNotMatchSchema(ctx) + if err != nil { + return nil, err } - if action.FillPercent { - fillPercent, err = b.selectDBsDoNotMatchFillPercent(ctx, action.FillPercentValue) - if err != nil { - return nil, err - } + withFillPercent, err := b.selectDBsDoNotMatchFillPercent(ctx, fillPercent) + if err != nil { + return nil, err } - for k := range fillPercent { - schemaChange[k] = struct{}{} + for k := range withFillPercent { + withSchemaChange[k] = struct{}{} } - result := make([]string, 0, len(schemaChange)) - for db := range schemaChange { + result := make([]string, 0, len(withSchemaChange)) + for db := range withSchemaChange { result = append(result, db) } return result, nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index 9fec795caf..b177d20fcf 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -145,7 +145,7 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), WithRootPath(dir), - WithBlobovniczaSize(100*1024*1024), + WithBlobovniczaSize(10*1024), WithWaitBeforeDropDB(0), WithOpenedCacheSize(1000)) require.NoError(t, b.Open(mode.ComponentReadWrite)) @@ -164,6 +164,7 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, WorkerLimiter: &rebuildLimiterStub{}, + FillPercent: 1, }) require.NoError(t, err) require.Equal(t, uint64(1), rRes.ObjectsMoved) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index e6da1c553f..dfd928aaf8 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -79,11 +79,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, WorkerLimiter: &rebuildLimiterStub{}, - Action: common.RebuildAction{ - SchemaChange: false, - FillPercent: true, - FillPercentValue: 60, - }, + FillPercent: 60, }) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 @@ -135,11 +131,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, WorkerLimiter: &rebuildLimiterStub{}, - Action: common.RebuildAction{ - SchemaChange: false, - FillPercent: true, - FillPercentValue: 90, // 64KB / 100KB = 64% - }, + FillPercent: 90, // 64KB / 100KB = 64% }) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 @@ -204,11 +196,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, WorkerLimiter: &rebuildLimiterStub{}, - Action: common.RebuildAction{ - SchemaChange: false, - FillPercent: true, - FillPercentValue: 80, - }, + FillPercent: 80, }) require.NoError(t, err) require.Equal(t, uint64(49), rRes.FilesRemoved) @@ -281,11 +269,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, WorkerLimiter: &rebuildLimiterStub{}, - Action: common.RebuildAction{ - SchemaChange: false, - FillPercent: true, - FillPercentValue: 80, - }, + FillPercent: 80, }) require.NoError(t, err) require.Equal(t, uint64(49), rRes.FilesRemoved) @@ -357,7 +341,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub rPrm.WorkerLimiter = &rebuildLimiterStub{} - rPrm.Action = common.RebuildAction{SchemaChange: true} + rPrm.FillPercent = 1 rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 @@ -446,7 +430,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub rPrm.WorkerLimiter = &rebuildLimiterStub{} - rPrm.Action = common.RebuildAction{SchemaChange: true} + rPrm.FillPercent = 1 rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 diff --git a/pkg/local_object_storage/blobstor/common/rebuild.go b/pkg/local_object_storage/blobstor/common/rebuild.go index 020d9d022c..19e181ee70 100644 --- a/pkg/local_object_storage/blobstor/common/rebuild.go +++ b/pkg/local_object_storage/blobstor/common/rebuild.go @@ -11,17 +11,10 @@ type RebuildRes struct { FilesRemoved uint64 } -type RebuildAction struct { - SchemaChange bool - - FillPercent bool - FillPercentValue int -} - type RebuildPrm struct { MetaStorage MetaStorage WorkerLimiter ConcurrentWorkersLimiter - Action RebuildAction + FillPercent int } type MetaStorage interface { diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go index 31bc2d1673..7b2786ba26 100644 --- a/pkg/local_object_storage/blobstor/rebuild.go +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -18,14 +18,14 @@ type ConcurrentWorkersLimiter interface { ReleaseWorkSlot() } -func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter ConcurrentWorkersLimiter, action common.RebuildAction) error { +func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter ConcurrentWorkersLimiter, fillPercent int) error { var summary common.RebuildRes var rErr error for _, storage := range b.storage { res, err := storage.Storage.Rebuild(ctx, common.RebuildPrm{ MetaStorage: upd, WorkerLimiter: limiter, - Action: action, + FillPercent: fillPercent, }) summary.FilesRemoved += res.FilesRemoved summary.ObjectsMoved += res.ObjectsMoved diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 5e9639a7bf..de881654a3 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -129,8 +129,8 @@ func (s *Shard) Init(ctx context.Context) error { s.gc.init(ctx) - s.rb = newRebuilder(NewRebuildLimiter(s.rebuildWorkersCount)) - if !m.NoMetabase() && !s.rebuildDisabled { + s.rb = newRebuilder() + if !m.NoMetabase() { s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) } s.writecacheSealCancel.Store(dummyCancel) @@ -398,7 +398,7 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { defer unlock() s.rb.Stop(s.log) - if !s.info.Mode.NoMetabase() && !s.rebuildDisabled { + if !s.info.Mode.NoMetabase() { defer func() { s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) }() diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index 1c0ef1c2ea..90958cd355 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -187,7 +187,7 @@ func TestGCDropsObjectInhumedFromWritecache(t *testing.T) { func testGCDropsObjectInhumedFromWritecache(t *testing.T, flushbeforeInhume bool) { sh := newCustomShard(t, true, shardOptions{ - additionalShardOptions: []Option{WithDisabledGC(), WithDisabledRebuild()}, + additionalShardOptions: []Option{WithDisabledGC()}, wcOpts: []writecache.Option{writecache.WithDisableBackgroundFlush()}, }) defer func() { require.NoError(t, sh.Close()) }() diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index 2eef456be1..0d83caa0c3 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -17,6 +16,8 @@ import ( "go.uber.org/zap" ) +var ErrRebuildInProgress = errors.New("shard rebuild in progress") + type RebuildWorkerLimiter interface { AcquireWorkSlot(ctx context.Context) error ReleaseWorkSlot() @@ -46,25 +47,23 @@ func (l *rebuildLimiter) ReleaseWorkSlot() { } type rebuildTask struct { - limiter RebuildWorkerLimiter - action common.RebuildAction + limiter RebuildWorkerLimiter + fillPercent int } type rebuilder struct { - mtx *sync.Mutex - wg *sync.WaitGroup - cancel func() - limiter RebuildWorkerLimiter - done chan struct{} - tasks chan rebuildTask + mtx *sync.Mutex + wg *sync.WaitGroup + cancel func() + done chan struct{} + tasks chan rebuildTask } -func newRebuilder(l RebuildWorkerLimiter) *rebuilder { +func newRebuilder() *rebuilder { return &rebuilder{ - mtx: &sync.Mutex{}, - wg: &sync.WaitGroup{}, - limiter: l, - tasks: make(chan rebuildTask, 10), + mtx: &sync.Mutex{}, + wg: &sync.WaitGroup{}, + tasks: make(chan rebuildTask), } } @@ -89,25 +88,14 @@ func (r *rebuilder) Start(ctx context.Context, bs *blobstor.BlobStor, mb *meta.D if !ok { continue } - runRebuild(ctx, bs, mb, log, t.action, t.limiter) + runRebuild(ctx, bs, mb, log, t.fillPercent, t.limiter) } } }() - select { - case <-ctx.Done(): - return - case r.tasks <- rebuildTask{ - limiter: r.limiter, - action: common.RebuildAction{ - SchemaChange: true, - }, - }: - return - } } func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *logger.Logger, - action common.RebuildAction, limiter RebuildWorkerLimiter, + fillPercent int, limiter RebuildWorkerLimiter, ) { select { case <-ctx.Done(): @@ -115,23 +103,25 @@ func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *lo default: } log.Info(logs.BlobstoreRebuildStarted) - if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, limiter, action); err != nil { + if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, limiter, fillPercent); err != nil { log.Warn(logs.FailedToRebuildBlobstore, zap.Error(err)) } else { log.Info(logs.BlobstoreRebuildCompletedSuccessfully) } } -func (r *rebuilder) ScheduleRebuild(ctx context.Context, limiter RebuildWorkerLimiter, action common.RebuildAction, +func (r *rebuilder) ScheduleRebuild(ctx context.Context, limiter RebuildWorkerLimiter, fillPercent int, ) error { select { case <-ctx.Done(): return ctx.Err() case r.tasks <- rebuildTask{ - limiter: limiter, - action: action, + limiter: limiter, + fillPercent: fillPercent, }: return nil + default: + return ErrRebuildInProgress } } @@ -198,9 +188,5 @@ func (s *Shard) ScheduleRebuild(ctx context.Context, p RebuildPrm) error { return ErrDegradedMode } - return s.rb.ScheduleRebuild(ctx, p.ConcurrencyLimiter, common.RebuildAction{ - SchemaChange: true, - FillPercent: true, - FillPercentValue: int(p.TargetFillPercent), - }) + return s.rb.ScheduleRebuild(ctx, p.ConcurrencyLimiter, int(p.TargetFillPercent)) } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 1e2bb79000..7496fc3527 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -139,10 +139,6 @@ type cfg struct { metricsWriter MetricsWriter reportErrorFunc func(selfID string, message string, err error) - - rebuildWorkersCount uint32 - - rebuildDisabled bool } func defaultCfg() *cfg { @@ -151,7 +147,6 @@ func defaultCfg() *cfg { log: &logger.Logger{Logger: zap.L()}, gcCfg: defaultGCCfg(), reportErrorFunc: func(string, string, error) {}, - rebuildWorkersCount: 1, zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, zeroCountContainersCallback: func(context.Context, []cid.ID) {}, } @@ -384,14 +379,6 @@ func WithExpiredCollectorWorkerCount(count int) Option { } } -// WithRebuildWorkersCount return option to set concurrent -// workers count of storage rebuild operation. -func WithRebuildWorkersCount(count uint32) Option { - return func(c *cfg) { - c.rebuildWorkersCount = count - } -} - // WithDisabledGC disables GC. // For testing purposes only. func WithDisabledGC() Option { @@ -414,14 +401,6 @@ func WithZeroCountCallback(cb EmptyContainersCallback) Option { } } -// WithDisabledRebuild returns an option to disable a shard rebuild. -// For testing purposes only. -func WithDisabledRebuild() Option { - return func(c *cfg) { - c.rebuildDisabled = true - } -} - func (s *Shard) fillInfo() { s.cfg.info.MetaBaseInfo = s.metaBase.DumpInfo() s.cfg.info.BlobStorInfo = s.blobStor.DumpInfo() From 654d970fadfe7eb47a5ce566be81ad15119df6a0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 6 Sep 2024 11:16:12 +0300 Subject: [PATCH 0794/1413] [#1355] adm: Run `metabase upgrade` concurrently Signed-off-by: Dmitrii Stepanov --- .../internal/modules/metabase/upgrade.go | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go index 83e085df48..96cb62f106 100644 --- a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go +++ b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go @@ -3,6 +3,7 @@ package metabase import ( "errors" "fmt" + "sync" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" @@ -11,6 +12,7 @@ import ( shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" ) const ( @@ -57,17 +59,28 @@ func upgrade(cmd *cobra.Command, _ []string) error { cmd.Println(i+1, ":", path) } result := make(map[string]bool) + var resultGuard sync.Mutex + eg, ctx := errgroup.WithContext(cmd.Context()) for _, path := range paths { - cmd.Println("upgrading metabase", path, "...") - if err := meta.Upgrade(cmd.Context(), path, !noCompact, func(a ...any) { - cmd.Println(append([]any{time.Now().Format(time.RFC3339), ":", path, ":"}, a...)...) - }); err != nil { - result[path] = false - cmd.Println("error: failed to upgrade metabase", path, ":", err) - } else { - result[path] = true - cmd.Println("metabase", path, "upgraded successfully") - } + eg.Go(func() error { + var success bool + cmd.Println("upgrading metabase", path, "...") + if err := meta.Upgrade(ctx, path, !noCompact, func(a ...any) { + cmd.Println(append([]any{time.Now().Format(time.RFC3339), ":", path, ":"}, a...)...) + }); err != nil { + cmd.Println("error: failed to upgrade metabase", path, ":", err) + } else { + success = true + cmd.Println("metabase", path, "upgraded successfully") + } + resultGuard.Lock() + result[path] = success + resultGuard.Unlock() + return nil + }) + } + if err := eg.Wait(); err != nil { + return err } for mb, ok := range result { if ok { From 4668efc0bfdfac3750307d0863effb991baa1a4b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 6 Sep 2024 11:17:02 +0300 Subject: [PATCH 0795/1413] [#1355] metabase: Upgrade improvements Do not fail on same latest version to run compact on upgraded metabase. Use NoSync on compact. Log every batch on bucket delete stage. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/upgrade.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index e9abd746cb..f677dcf8eb 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -27,6 +27,10 @@ const ( var updates = map[uint64]func(ctx context.Context, db *bbolt.DB, log func(a ...any)) error{ 2: upgradeFromV2ToV3, + 3: func(_ context.Context, _ *bbolt.DB, log func(a ...any)) error { + log("metabase already upgraded") + return nil + }, } func Upgrade(ctx context.Context, path string, compact bool, log func(a ...any)) error { @@ -86,6 +90,7 @@ func compactDB(db *bbolt.DB) error { } dst, err := bbolt.Open(tmpFileName, f.Mode(), &bbolt.Options{ Timeout: 100 * time.Millisecond, + NoSync: true, }) if err != nil { return fmt.Errorf("can't open new metabase to compact: %w", err) @@ -93,6 +98,9 @@ func compactDB(db *bbolt.DB) error { if err := bbolt.Compact(dst, db, compactMaxTxSize); err != nil { return fmt.Errorf("compact metabase: %w", errors.Join(err, dst.Close(), os.Remove(tmpFileName))) } + if err := dst.Sync(); err != nil { + return fmt.Errorf("sync compacted metabase: %w", errors.Join(err, os.Remove(tmpFileName))) + } if err := dst.Close(); err != nil { return fmt.Errorf("close compacted metabase: %w", errors.Join(err, os.Remove(tmpFileName))) } @@ -369,8 +377,7 @@ func dropBucketsByPrefix(ctx context.Context, db *bbolt.DB, prefix []byte, log f log("deleting buckets completed with an error:", err) return err } - if count += uint64(len(keys)); count%upgradeLogFrequency == 0 { - log("deleted", count, "buckets") - } + count += uint64(len(keys)) + log("deleted", count, "buckets") } } From 92fe5d90f50a4d0f3c3b5265a32e0127848559e4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 9 Sep 2024 18:39:22 +0300 Subject: [PATCH 0796/1413] [#1359] writecache: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/writecache/cachebbolt.go | 8 -------- pkg/local_object_storage/writecache/put.go | 5 ----- 2 files changed, 13 deletions(-) diff --git a/pkg/local_object_storage/writecache/cachebbolt.go b/pkg/local_object_storage/writecache/cachebbolt.go index cdd4ed4423..f1e6a619ad 100644 --- a/pkg/local_object_storage/writecache/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cachebbolt.go @@ -18,16 +18,9 @@ import ( type cache struct { options - // mtx protects statistics, counters and compressFlags. - mtx sync.RWMutex - mode mode.Mode modeMtx sync.RWMutex - // compressFlags maps address of a big object to boolean value indicating - // whether object should be compressed. - compressFlags map[string]struct{} - // flushCh is a channel with objects to flush. flushCh chan objectInfo // cancel is cancel function, protected by modeMtx in Close. @@ -66,7 +59,6 @@ func New(opts ...Option) Cache { flushCh: make(chan objectInfo), mode: mode.Disabled, - compressFlags: make(map[string]struct{}), options: options{ log: &logger.Logger{Logger: zap.NewNop()}, maxObjectSize: defaultMaxObjectSize, diff --git a/pkg/local_object_storage/writecache/put.go b/pkg/local_object_storage/writecache/put.go index 150399de80..ae0e8b77a4 100644 --- a/pkg/local_object_storage/writecache/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -115,11 +115,6 @@ func (c *cache) putBig(ctx context.Context, addr string, prm common.PutPrm) erro return err } - if compressor := c.blobstor.Compressor(); compressor != nil && compressor.NeedsCompression(prm.Object) { - c.mtx.Lock() - c.compressFlags[addr] = struct{}{} - c.mtx.Unlock() - } storagelog.Write(c.log, storagelog.AddressField(addr), storagelog.StorageTypeField(wcStorageType), From a812932984531162648fdbfa985a6f496fdbd80e Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 10 Sep 2024 11:15:30 +0300 Subject: [PATCH 0797/1413] [#1362] ape: Move common APE check logic to separate package * Tree and object service have the same log for checking APE. So, this check should be moved to common package. Signed-off-by: Airat Arifullin --- pkg/services/common/ape/checker.go | 167 +++++++++++++++++++++++++++++ pkg/services/object/ape/checker.go | 139 +++++------------------- pkg/services/tree/ape.go | 116 ++------------------ pkg/services/tree/service.go | 5 + 4 files changed, 205 insertions(+), 222 deletions(-) create mode 100644 pkg/services/common/ape/checker.go diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go new file mode 100644 index 0000000000..f24d221245 --- /dev/null +++ b/pkg/services/common/ape/checker.go @@ -0,0 +1,167 @@ +package ape + +import ( + "crypto/ecdsa" + "errors" + "fmt" + + aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +var ( + errInvalidTargetType = errors.New("bearer token defines non-container target override") + errBearerExpired = errors.New("bearer token has expired") + errBearerInvalidSignature = errors.New("bearer token has invalid signature") + errBearerInvalidContainerID = errors.New("bearer token was created for another container") + errBearerNotSignedByOwner = errors.New("bearer token is not signed by the container owner") + errBearerInvalidOwner = errors.New("bearer token owner differs from the request sender") +) + +type CheckPrm struct { + // Request is an APE-request that is checked by policy engine. + Request aperequest.Request + + Namespace string + + Container cid.ID + + // An encoded container's owner user ID. + ContainerOwner user.ID + + // PublicKey is public key of the request sender. + PublicKey *keys.PublicKey + + // The request's bearer token. It is used in order to check APE overrides with the token. + BearerToken *bearer.Token + + // If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow. + SoftAPECheck bool +} + +// CheckCore provides methods to perform the common logic of APE check. +type CheckCore interface { + // CheckAPE performs the common policy-engine check logic on a prepared request. + CheckAPE(prm CheckPrm) error +} + +type checkerCoreImpl struct { + LocalOverrideStorage policyengine.LocalOverrideStorage + MorphChainStorage policyengine.MorphRuleChainStorageReader + FrostFSSubjectProvider frostfsidcore.SubjectProvider + State netmap.State +} + +func New(localOverrideStorage policyengine.LocalOverrideStorage, morphChainStorage policyengine.MorphRuleChainStorageReader, + frostFSSubjectProvider frostfsidcore.SubjectProvider, state netmap.State) CheckCore { + return &checkerCoreImpl{ + LocalOverrideStorage: localOverrideStorage, + MorphChainStorage: morphChainStorage, + FrostFSSubjectProvider: frostFSSubjectProvider, + State: state, + } +} + +// CheckAPE performs the common policy-engine check logic on a prepared request. +func (c *checkerCoreImpl) CheckAPE(prm CheckPrm) error { + var cr policyengine.ChainRouter + if prm.BearerToken != nil && !prm.BearerToken.Impersonate() { + var err error + if err = isValidBearer(prm.BearerToken, prm.ContainerOwner, prm.Container, prm.PublicKey, c.State); err != nil { + return fmt.Errorf("bearer validation error: %w", err) + } + cr, err = router.BearerChainFeedRouter(c.LocalOverrideStorage, c.MorphChainStorage, prm.BearerToken.APEOverride()) + if err != nil { + return fmt.Errorf("create chain router error: %w", err) + } + } else { + cr = policyengine.NewDefaultChainRouterWithLocalOverrides(c.MorphChainStorage, c.LocalOverrideStorage) + } + + groups, err := aperequest.Groups(c.FrostFSSubjectProvider, prm.PublicKey) + if err != nil { + return fmt.Errorf("failed to get group ids: %w", err) + } + + // Policy contract keeps group related chains as namespace-group pair. + for i := range groups { + groups[i] = fmt.Sprintf("%s:%s", prm.Namespace, groups[i]) + } + + rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, prm.PublicKey.Address()), groups) + status, found, err := cr.IsAllowed(apechain.Ingress, rt, prm.Request) + if err != nil { + return err + } + if !found && prm.SoftAPECheck || status == apechain.Allow { + return nil + } + err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", prm.Request.Operation(), status.String()) + return apeErr(err) +} + +func apeErr(err error) error { + errAccessDenied := &apistatus.ObjectAccessDenied{} + errAccessDenied.WriteReason(err.Error()) + return errAccessDenied +} + +// isValidBearer checks whether bearer token was correctly signed by authorized +// entity. This method might be defined on whole ACL service because it will +// require fetching current epoch to check lifetime. +func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKey *keys.PublicKey, st netmap.State) error { + if token == nil { + return nil + } + + // First check token lifetime. Simplest verification. + if token.InvalidAt(st.CurrentEpoch()) { + return errBearerExpired + } + + // Then check if bearer token is signed correctly. + if !token.VerifySignature() { + return errBearerInvalidSignature + } + + // Check for ape overrides defined in the bearer token. + apeOverride := token.APEOverride() + if len(apeOverride.Chains) > 0 && apeOverride.Target.TargetType != ape.TargetTypeContainer { + return fmt.Errorf("%w: %s", errInvalidTargetType, apeOverride.Target.TargetType.ToV2().String()) + } + + // Then check if container is either empty or equal to the container in the request. + var targetCnr cid.ID + err := targetCnr.DecodeString(apeOverride.Target.Name) + if err != nil { + return fmt.Errorf("invalid cid format: %s", apeOverride.Target.Name) + } + if !cntID.Equals(targetCnr) { + return errBearerInvalidContainerID + } + + // Then check if container owner signed this token. + if !bearer.ResolveIssuer(*token).Equals(ownerCnr) { + return errBearerNotSignedByOwner + } + + // Then check if request sender has rights to use this token. + var usrSender user.ID + user.IDFromKey(&usrSender, (ecdsa.PublicKey)(*publicKey)) + + if !token.AssertUser(usrSender) { + return errBearerInvalidOwner + } + + return nil +} diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index a1972292e3..3688638d03 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -2,49 +2,41 @@ package ape import ( "context" - "crypto/ecdsa" "errors" "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) type checkerImpl struct { - localOverrideStorage policyengine.LocalOverrideStorage - morphChainStorage policyengine.MorphRuleChainStorageReader - headerProvider HeaderProvider - frostFSIDClient frostfsidcore.SubjectProvider - nm netmap.Source - st netmap.State - cnrSource container.Source - nodePK []byte + checkerCore checkercore.CheckCore + frostFSIDClient frostfsidcore.SubjectProvider + headerProvider HeaderProvider + nm netmap.Source + cnrSource container.Source + nodePK []byte } func NewChecker(localOverrideStorage policyengine.LocalOverrideStorage, morphChainStorage policyengine.MorphRuleChainStorageReader, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider, nm netmap.Source, st netmap.State, cnrSource container.Source, nodePK []byte) Checker { return &checkerImpl{ - localOverrideStorage: localOverrideStorage, - morphChainStorage: morphChainStorage, - headerProvider: headerProvider, - frostFSIDClient: frostFSIDClient, - nm: nm, - st: st, - cnrSource: cnrSource, - nodePK: nodePK, + checkerCore: checkercore.New(localOverrideStorage, morphChainStorage, frostFSIDClient, st), + frostFSIDClient: frostFSIDClient, + headerProvider: headerProvider, + nm: nm, + cnrSource: cnrSource, + nodePK: nodePK, } } @@ -85,68 +77,9 @@ type Prm struct { XHeaders []session.XHeader } -var ( - errMissingOID = errors.New("object ID is not set") - errInvalidTargetType = errors.New("bearer token defines non-container target override") - errBearerExpired = errors.New("bearer token has expired") - errBearerInvalidSignature = errors.New("bearer token has invalid signature") - errBearerInvalidContainerID = errors.New("bearer token was created for another container") - errBearerNotSignedByOwner = errors.New("bearer token is not signed by the container owner") - errBearerInvalidOwner = errors.New("bearer token owner differs from the request sender") -) +var errMissingOID = errors.New("object ID is not set") -// isValidBearer checks whether bearer token was correctly signed by authorized -// entity. This method might be defined on whole ACL service because it will -// require fetching current epoch to check lifetime. -func isValidBearer(token *bearer.Token, ownerCnr user.ID, containerID cid.ID, publicKey *keys.PublicKey, st netmap.State) error { - if token == nil { - return nil - } - - // First check token lifetime. Simplest verification. - if token.InvalidAt(st.CurrentEpoch()) { - return errBearerExpired - } - - // Then check if bearer token is signed correctly. - if !token.VerifySignature() { - return errBearerInvalidSignature - } - - // Check for ape overrides defined in the bearer token. - apeOverride := token.APEOverride() - if len(apeOverride.Chains) > 0 && apeOverride.Target.TargetType != ape.TargetTypeContainer { - return fmt.Errorf("%w: %s", errInvalidTargetType, apeOverride.Target.TargetType.ToV2().String()) - } - - // Then check if container is either empty or equal to the container in the request. - var targetCnr cid.ID - err := targetCnr.DecodeString(apeOverride.Target.Name) - if err != nil { - return fmt.Errorf("invalid cid format: %s", apeOverride.Target.Name) - } - if !containerID.Equals(targetCnr) { - return errBearerInvalidContainerID - } - - // Then check if container owner signed this token. - if !bearer.ResolveIssuer(*token).Equals(ownerCnr) { - return errBearerNotSignedByOwner - } - - // Then check if request sender has rights to use this token. - var usrSender user.ID - user.IDFromKey(&usrSender, (ecdsa.PublicKey)(*publicKey)) - - if !token.AssertUser(usrSender) { - return errBearerInvalidOwner - } - - return nil -} - -// CheckAPE checks if a request or a response is permitted creating an ape request and passing -// it to chain router. +// CheckAPE prepares an APE-request and checks if it is permitted by policies. func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { // APE check is ignored for some inter-node requests. if prm.Role == nativeschema.PropertyValueContainerRoleContainer { @@ -171,38 +104,14 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { if err != nil { return err } - groups, err := aperequest.Groups(c.frostFSIDClient, pub) - if err != nil { - return fmt.Errorf("failed to get group ids: %w", err) - } - // Policy contract keeps group related chains as namespace-group pair. - for i := range groups { - groups[i] = fmt.Sprintf("%s:%s", prm.Namespace, groups[i]) - } - - var cr policyengine.ChainRouter - if prm.BearerToken != nil && !prm.BearerToken.Impersonate() { - if err := isValidBearer(prm.BearerToken, prm.ContainerOwner, prm.Container, pub, c.st); err != nil { - return fmt.Errorf("bearer token validation error: %w", err) - } - cr, err = router.BearerChainFeedRouter(c.localOverrideStorage, c.morphChainStorage, prm.BearerToken.APEOverride()) - if err != nil { - return fmt.Errorf("create chain router error: %w", err) - } - } else { - cr = policyengine.NewDefaultChainRouterWithLocalOverrides(c.morphChainStorage, c.localOverrideStorage) - } - - rt := policyengine.NewRequestTargetExtended(prm.Namespace, prm.Container.EncodeToString(), fmt.Sprintf("%s:%s", prm.Namespace, pub.Address()), groups) - status, ruleFound, err := cr.IsAllowed(apechain.Ingress, rt, r) - if err != nil { - return err - } - - if !ruleFound && prm.SoftAPECheck || status == apechain.Allow { - return nil - } - - return fmt.Errorf("method %s: %s", prm.Method, status) + return c.checkerCore.CheckAPE(checkercore.CheckPrm{ + Request: r, + PublicKey: pub, + Namespace: prm.Method, + Container: prm.Container, + ContainerOwner: prm.ContainerOwner, + BearerToken: prm.BearerToken, + SoftAPECheck: prm.SoftAPECheck, + }) } diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index ee4687911f..693b16e605 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -2,42 +2,25 @@ package tree import ( "context" - "crypto/ecdsa" "encoding/hex" - "errors" "fmt" "net" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/router" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" - "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "google.golang.org/grpc/peer" ) -var ( - errInvalidTargetType = errors.New("bearer token defines non-container target override") - errBearerExpired = errors.New("bearer token has expired") - errBearerInvalidSignature = errors.New("bearer token has invalid signature") - errBearerInvalidContainerID = errors.New("bearer token was created for another container") - errBearerNotSignedByOwner = errors.New("bearer token is not signed by the container owner") - errBearerInvalidOwner = errors.New("bearer token owner differs from the request sender") -) - func (s *Service) newAPERequest(ctx context.Context, namespace string, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey, ) (aperequest.Request, error) { @@ -77,56 +60,6 @@ func (s *Service) newAPERequest(ctx context.Context, namespace string, ), nil } -// isValidBearer checks whether bearer token was correctly signed by authorized -// entity. This method might be defined on whole ACL service because it will -// require fetching current epoch to check lifetime. -func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKey *keys.PublicKey, st netmap.State) error { - if token == nil { - return nil - } - - // First check token lifetime. Simplest verification. - if token.InvalidAt(st.CurrentEpoch()) { - return errBearerExpired - } - - // Then check if bearer token is signed correctly. - if !token.VerifySignature() { - return errBearerInvalidSignature - } - - // Check for ape overrides defined in the bearer token. - apeOverride := token.APEOverride() - if len(apeOverride.Chains) > 0 && apeOverride.Target.TargetType != ape.TargetTypeContainer { - return fmt.Errorf("%w: %s", errInvalidTargetType, apeOverride.Target.TargetType.ToV2().String()) - } - - // Then check if container is either empty or equal to the container in the request. - var targetCnr cid.ID - err := targetCnr.DecodeString(apeOverride.Target.Name) - if err != nil { - return fmt.Errorf("invalid cid format: %s", apeOverride.Target.Name) - } - if !cntID.Equals(targetCnr) { - return errBearerInvalidContainerID - } - - // Then check if container owner signed this token. - if !bearer.ResolveIssuer(*token).Equals(ownerCnr) { - return errBearerNotSignedByOwner - } - - // Then check if request sender has rights to use this token. - var usrSender user.ID - user.IDFromKey(&usrSender, (ecdsa.PublicKey)(*publicKey)) - - if !token.AssertUser(usrSender) { - return errBearerInvalidOwner - } - - return nil -} - func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey, ) error { @@ -141,45 +74,14 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, return fmt.Errorf("failed to create ape request: %w", err) } - var cr engine.ChainRouter - if bt != nil && !bt.Impersonate() { - if err := isValidBearer(bt, container.Value.Owner(), cid, publicKey, s.state); err != nil { - return fmt.Errorf("bearer validation error: %w", err) - } - cr, err = router.BearerChainFeedRouter(s.localOverrideStorage, s.morphChainStorage, bt.APEOverride()) - if err != nil { - return fmt.Errorf("create chain router error: %w", err) - } - } else { - cr = engine.NewDefaultChainRouterWithLocalOverrides(s.morphChainStorage, s.localOverrideStorage) - } - - groups, err := aperequest.Groups(s.frostfsidSubjectProvider, publicKey) - if err != nil { - return fmt.Errorf("failed to get group ids: %w", err) - } - - // Policy contract keeps group related chains as namespace-group pair. - for i := range groups { - groups[i] = fmt.Sprintf("%s:%s", namespace, groups[i]) - } - - rt := engine.NewRequestTargetExtended(namespace, cid.EncodeToString(), fmt.Sprintf("%s:%s", namespace, publicKey.Address()), groups) - status, found, err := cr.IsAllowed(apechain.Ingress, rt, request) - if err != nil { - return err - } - if found && status == apechain.Allow { - return nil - } - err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", request.Operation(), status.String()) - return apeErr(err) -} - -func apeErr(err error) error { - errAccessDenied := &apistatus.ObjectAccessDenied{} - errAccessDenied.WriteReason(err.Error()) - return errAccessDenied + return s.apeChecker.CheckAPE(checkercore.CheckPrm{ + Request: request, + Namespace: namespace, + Container: cid, + PublicKey: publicKey, + BearerToken: bt, + SoftAPECheck: false, + }) } // fillWithUserClaimTags fills ape request properties with user claim tags getting them from frostfsid contract by actor public key. diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 4da61617f7..875e47ecb0 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -10,6 +10,7 @@ import ( "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -37,6 +38,8 @@ type Service struct { initialSyncDone atomic.Bool + apeChecker checkercore.CheckCore + // cnrMap contains existing (used) container IDs. cnrMap map[cidSDK.ID]struct{} // cnrMapMtx protects cnrMap @@ -72,6 +75,8 @@ func New(opts ...Option) *Service { s.syncChan = make(chan struct{}) s.syncPool, _ = ants.NewPool(defaultSyncWorkerCount) + s.apeChecker = checkercore.New(s.localOverrideStorage, s.morphChainStorage, s.frostfsidSubjectProvider, s.state) + return &s } From 2220f6a8091d9b861fd6a86b7afc90320591e9b1 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 10 Sep 2024 16:45:15 +0300 Subject: [PATCH 0798/1413] [#1365] Makefile: Fix HUB_IMAGE Signed-off-by: Alexander Chuprov --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 71492ef171..2f29ac19c0 100755 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SHELL = bash REPO ?= $(shell go list -m) VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 2>/dev/null || cat VERSION 2>/dev/null || echo "develop") -HUB_IMAGE ?= truecloudlab/frostfs +HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.22 From 5fac4058e8cbc9ef8484b2ddaaf583574684dded Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 10 Sep 2024 12:14:46 +0300 Subject: [PATCH 0799/1413] [#1364] cmd/common: Add tests for CreateViper and ReloadViper Add tests for `CreateViper` and `ReloadViper` to ensure that no extra files, except *.yaml, *.yml, *.json, are loaded from config directory. Signed-off-by: Aleksey Savchuk --- cmd/internal/common/config/viper_test.go | 107 +++++++++++++++++++++++ pkg/util/config/test/generate.go | 58 ++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 cmd/internal/common/config/viper_test.go create mode 100644 pkg/util/config/test/generate.go diff --git a/cmd/internal/common/config/viper_test.go b/cmd/internal/common/config/viper_test.go new file mode 100644 index 0000000000..d533a15c2b --- /dev/null +++ b/cmd/internal/common/config/viper_test.go @@ -0,0 +1,107 @@ +package config_test + +import ( + "encoding/json" + "os" + "path" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/config" + configtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config/test" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v3" +) + +func TestCreateReloadViper(t *testing.T) { + type m = map[string]any + + dummyFileSize := 1 << 10 + + configPath := t.TempDir() + configFile := "000_a.yaml" + + configDirPath := path.Join(configPath, "conf.d") + require.NoError(t, os.Mkdir(configDirPath, 0o700)) + + configtest.PrepareConfigFiles(t, configPath, []configtest.ConfigFile{ + configtest.NewConfigFile(configFile, m{"a": "000"}, yaml.Marshal), + }) + + // Not valid configs, dummy files those appear lexicographically first. + configtest.PrepareDummyFiles(t, configDirPath, []configtest.DummyFile{ + configtest.NewDummyFile("000_file_1", dummyFileSize), + configtest.NewDummyFile("000_file_2", dummyFileSize), + configtest.NewDummyFile("000_file_3", dummyFileSize), + }) + + configtest.PrepareConfigFiles(t, configDirPath, []configtest.ConfigFile{ + // Valid configs with invalid extensions those appear lexicographically first. + configtest.NewConfigFile("001_a.yaml.un~", m{"a": "101"}, yaml.Marshal), + configtest.NewConfigFile("001_b.yml~", m{"b": m{"a": "102", "b": "103"}}, yaml.Marshal), + configtest.NewConfigFile("001_c.yaml.swp", m{"c": m{"a": "104", "b": "105"}}, yaml.Marshal), + configtest.NewConfigFile("001_d.json.swp", m{"d": m{"a": "106", "b": "107"}}, json.Marshal), + + // Valid configs with valid extensions those should be loaded. + configtest.NewConfigFile("010_a.yaml", m{"a": "1"}, yaml.Marshal), + configtest.NewConfigFile("020_b.yml", m{"b": m{"a": "2", "b": "3"}}, yaml.Marshal), + configtest.NewConfigFile("030_c.json", m{"c": m{"a": "4", "b": "5"}}, json.Marshal), + + // Valid configs with invalid extensions those appear lexicographically last. + configtest.NewConfigFile("099_a.yaml.un~", m{"a": "201"}, yaml.Marshal), + configtest.NewConfigFile("099_b.yml~", m{"b": m{"a": "202", "b": "203"}}, yaml.Marshal), + configtest.NewConfigFile("099_c.yaml.swp", m{"c": m{"a": "204", "b": "205"}}, yaml.Marshal), + configtest.NewConfigFile("099_c.json.swp", m{"d": m{"a": "206", "b": "207"}}, json.Marshal), + }) + + // Not valid configs, dummy files those appear lexicographically last. + configtest.PrepareDummyFiles(t, configDirPath, []configtest.DummyFile{ + configtest.NewDummyFile("999_file_1", dummyFileSize), + configtest.NewDummyFile("999_file_2", dummyFileSize), + configtest.NewDummyFile("999_file_3", dummyFileSize), + }) + + finalConfig := m{"a": "1", "b": m{"a": "2", "b": "3"}, "c": m{"a": "4", "b": "5"}} + + var ( + v *viper.Viper + err error + ) + + t.Run("create config with config dir only", func(t *testing.T) { + v, err = config.CreateViper( + config.WithConfigDir(configDirPath), + ) + require.NoError(t, err) + assert.Equal(t, finalConfig, v.AllSettings()) + }) + + t.Run("reload config with config dir only", func(t *testing.T) { + err = config.ReloadViper( + config.WithViper(v), + config.WithConfigDir(configDirPath), + ) + require.NoError(t, err) + assert.Equal(t, finalConfig, v.AllSettings()) + }) + + t.Run("create config with both config and config dir", func(t *testing.T) { + v, err = config.CreateViper( + config.WithConfigFile(path.Join(configPath, configFile)), + config.WithConfigDir(configDirPath), + ) + require.NoError(t, err) + assert.Equal(t, finalConfig, v.AllSettings()) + }) + + t.Run("reload config with both config and config dir", func(t *testing.T) { + err = config.ReloadViper( + config.WithViper(v), + config.WithConfigFile(path.Join(configPath, configFile)), + config.WithConfigDir(configDirPath), + ) + require.NoError(t, err) + assert.Equal(t, finalConfig, v.AllSettings()) + }) +} diff --git a/pkg/util/config/test/generate.go b/pkg/util/config/test/generate.go new file mode 100644 index 0000000000..63e2866151 --- /dev/null +++ b/pkg/util/config/test/generate.go @@ -0,0 +1,58 @@ +package configtest + +import ( + "crypto/rand" + "os" + "path" + "testing" + + "github.com/stretchr/testify/require" +) + +type MarshalFunc = func(any) ([]byte, error) + +type ConfigFile struct { + filename string + content map[string]any + marshal func(any) ([]byte, error) +} + +type DummyFile struct { + filename string + size int +} + +func NewConfigFile(filename string, content map[string]any, marshal MarshalFunc) ConfigFile { + return ConfigFile{ + filename: filename, + content: content, + marshal: marshal, + } +} + +func NewDummyFile(filename string, size int) DummyFile { + return DummyFile{ + filename: filename, + size: size, + } +} + +func PrepareConfigFiles(t *testing.T, dir string, files []ConfigFile) { + for _, file := range files { + data, err := file.marshal(file.content) + require.NoError(t, err) + + err = os.WriteFile(path.Join(dir, file.filename), data, 0o600) + require.NoError(t, err) + } +} + +func PrepareDummyFiles(t *testing.T, dir string, files []DummyFile) { + for _, file := range files { + data := make([]byte, file.size) + _, _ = rand.Read(data) + + err := os.WriteFile(path.Join(dir, file.filename), data, 0o600) + require.NoError(t, err) + } +} From dea6f031f97664259d407bff6a320b295dc4b3d0 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 9 Sep 2024 19:26:41 +0300 Subject: [PATCH 0800/1413] [#1331] cli/tree: Add order flag to `tree get-subtree` Added `--ordered` flag to sort output by ascending FileName. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/modules/tree/root.go | 1 + cmd/frostfs-cli/modules/tree/subtree.go | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/cmd/frostfs-cli/modules/tree/root.go b/cmd/frostfs-cli/modules/tree/root.go index efd1c08b52..5a53c50d6b 100644 --- a/cmd/frostfs-cli/modules/tree/root.go +++ b/cmd/frostfs-cli/modules/tree/root.go @@ -49,6 +49,7 @@ const ( heightFlagKey = "height" countFlagKey = "count" depthFlagKey = "depth" + orderFlagKey = "ordered" ) func initCTID(cmd *cobra.Command) { diff --git a/cmd/frostfs-cli/modules/tree/subtree.go b/cmd/frostfs-cli/modules/tree/subtree.go index e58a13fd66..e88ef79cbb 100644 --- a/cmd/frostfs-cli/modules/tree/subtree.go +++ b/cmd/frostfs-cli/modules/tree/subtree.go @@ -30,6 +30,7 @@ func initGetSubtreeCmd() { ff := getSubtreeCmd.Flags() ff.Uint64(rootIDFlagKey, 0, "Root ID to traverse from.") ff.Uint32(depthFlagKey, 10, "Traversal depth.") + ff.Bool(orderFlagKey, false, "Sort output by ascending FileName.") _ = getSubtreeCmd.MarkFlagRequired(commonflags.CIDFlag) _ = getSubtreeCmd.MarkFlagRequired(treeIDFlagKey) @@ -59,6 +60,13 @@ func getSubTree(cmd *cobra.Command, _ []string) { depth, _ := cmd.Flags().GetUint32(depthFlagKey) + order, _ := cmd.Flags().GetBool(orderFlagKey) + + bodyOrder := tree.GetSubTreeRequest_Body_Order_None + if order { + bodyOrder = tree.GetSubTreeRequest_Body_Order_Asc + } + var bt []byte if t := common.ReadBearerToken(cmd, bearerFlagKey); t != nil { bt = t.Marshal() @@ -71,6 +79,9 @@ func getSubTree(cmd *cobra.Command, _ []string) { RootId: []uint64{rid}, Depth: depth, BearerToken: bt, + OrderBy: &tree.GetSubTreeRequest_Body_Order{ + Direction: bodyOrder, + }, }, } From ec8da4056704d81107f514bcb998aa6f3dd7b07f Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Wed, 11 Sep 2024 12:40:04 +0300 Subject: [PATCH 0801/1413] [#1369] Update obsolete URLs Signed-off-by: Vitaliy Potyarkin --- README.md | 15 +++++++-------- cmd/frostfs-adm/docs/deploy.md | 4 ++-- config/testnet/README.md | 2 +- docs/release-instruction.md | 6 +++--- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8225f56c50..47d812b180 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,8 @@

--- -[![Report](https://goreportcard.com/badge/github.com/TrueCloudLab/frostfs-node)](https://goreportcard.com/report/github.com/TrueCloudLab/frostfs-node) -![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/TrueCloudLab/frostfs-node?sort=semver) -![License](https://img.shields.io/github/license/TrueCloudLab/frostfs-node.svg?style=popout) +[![Report](https://goreportcard.com/badge/git.frostfs.info/TrueCloudLab/frostfs-node)](https://goreportcard.com/report/git.frostfs.info/TrueCloudLab/frostfs-node) +![Release (latest)](https://git.frostfs.info/TrueCloudLab/frostfs-node/badges/release.svg) # Overview @@ -33,8 +32,8 @@ manipulate large amounts of data without paying a prohibitive price. FrostFS has a native [gRPC API](https://git.frostfs.info/TrueCloudLab/frostfs-api) and has protocol gateways for popular protocols such as [AWS -S3](https://github.com/TrueCloudLab/frostfs-s3-gw), -[HTTP](https://github.com/TrueCloudLab/frostfs-http-gw), +S3](https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw), +[HTTP](https://git.frostfs.info/TrueCloudLab/frostfs-http-gw), [FUSE](https://wikipedia.org/wiki/Filesystem_in_Userspace) and [sFTP](https://en.wikipedia.org/wiki/SSH_File_Transfer_Protocol) allowing developers to integrate applications without rewriting their code. @@ -45,7 +44,7 @@ Now, we only support GNU/Linux on amd64 CPUs with AVX/AVX2 instructions. More platforms will be officially supported after release `1.0`. The latest version of frostfs-node works with frostfs-contract -[v0.16.0](https://github.com/TrueCloudLab/frostfs-contract/releases/tag/v0.16.0). +[v0.19.2](https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/tag/v0.19.2). # Building @@ -71,7 +70,7 @@ make docker/bin/frostfs- # build a specific binary ## Docker images -To make docker images suitable for use in [frostfs-dev-env](https://github.com/TrueCloudLab/frostfs-dev-env/) use: +To make docker images suitable for use in [frostfs-dev-env](https://git.frostfs.info/TrueCloudLab/frostfs-dev-env/) use: ``` make images ``` @@ -125,7 +124,7 @@ the feature/topic you are going to implement. # Credits -FrostFS is maintained by [True Cloud Lab](https://github.com/TrueCloudLab/) with the help and +FrostFS is maintained by [True Cloud Lab](https://git.frostfs.info/TrueCloudLab/) with the help and contributions from community members. Please see [CREDITS](CREDITS.md) for details. diff --git a/cmd/frostfs-adm/docs/deploy.md b/cmd/frostfs-adm/docs/deploy.md index 87d2e47c1b..b4b1ed8e4e 100644 --- a/cmd/frostfs-adm/docs/deploy.md +++ b/cmd/frostfs-adm/docs/deploy.md @@ -9,8 +9,8 @@ related configuration details. To follow this guide you need: - latest released version of [neo-go](https://github.com/nspcc-dev/neo-go/releases) (v0.97.2 at the moment), -- latest released version of [frostfs-adm](https://github.com/TrueCloudLab/frostfs-node/releases) utility (v0.25.1 at the moment), -- latest released version of compiled [frostfs-contract](https://github.com/TrueCloudLab/frostfs-contract/releases) (v0.11.0 at the moment). +- latest released version of [frostfs-adm](https://git.frostfs.info/TrueCloudLab/frostfs-node/releases) utility (v0.42.9 at the moment), +- latest released version of compiled [frostfs-contract](https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases) (v0.19.2 at the moment). ## Step 1: Prepare network configuration diff --git a/config/testnet/README.md b/config/testnet/README.md index b5faf2b277..e2cda33eca 100644 --- a/config/testnet/README.md +++ b/config/testnet/README.md @@ -67,7 +67,7 @@ NEOFS_NODE_ATTRIBUTE_2=UN-LOCODE:RU LED ``` You can validate UN/LOCODE attribute in -[NeoFS LOCODE database](https://github.com/TrueCloudLab/frostfs-locode-db/releases/tag/v0.1.0) +[NeoFS LOCODE database](https://git.frostfs.info/TrueCloudLab/frostfs-locode-db/releases/tag/v0.4.0) with frostfs-cli. ``` diff --git a/docs/release-instruction.md b/docs/release-instruction.md index ec7b8cdf34..3aebc8e66f 100644 --- a/docs/release-instruction.md +++ b/docs/release-instruction.md @@ -9,7 +9,7 @@ These should run successfully: * `make lint` (should not change any files); * `make fmts` (should not change any files); * `go mod tidy` (should not change any files); -* integration tests in [frostfs-devenv](https://github.com/TrueCloudLab/frostfs-devenv). +* integration tests in [frostfs-devenv](https://git.frostfs.info/TrueCloudLab/frostfs-dev-env). ## Make release commit @@ -123,12 +123,12 @@ the release. Publish the release. ### Update FrostFS Developer Environment -Prepare pull-request in [frostfs-devenv](https://github.com/TrueCloudLab/frostfs-devenv) +Prepare pull-request in [frostfs-devenv](https://git.frostfs.info/TrueCloudLab/frostfs-dev-env) with new versions. ### Close GitHub milestone -Look up GitHub [milestones](https://github.com/TrueCloudLab/frostfs-node/milestones) and close the release one if exists. +Look up [milestones](https://git.frostfs.info/TrueCloudLab/frostfs-node/milestones) and close the release one if exists. ### Rebuild FrostFS LOCODE database From 99be4c83a7c8ab6717ef5242c80f9ccc51d470d7 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 12 Sep 2024 10:00:28 +0300 Subject: [PATCH 0802/1413] [#1368] *: Run gofumpt Signed-off-by: Aleksey Savchuk --- pkg/services/common/ape/checker.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index f24d221245..278f6da315 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -63,7 +63,8 @@ type checkerCoreImpl struct { } func New(localOverrideStorage policyengine.LocalOverrideStorage, morphChainStorage policyengine.MorphRuleChainStorageReader, - frostFSSubjectProvider frostfsidcore.SubjectProvider, state netmap.State) CheckCore { + frostFSSubjectProvider frostfsidcore.SubjectProvider, state netmap.State, +) CheckCore { return &checkerCoreImpl{ LocalOverrideStorage: localOverrideStorage, MorphChainStorage: morphChainStorage, From 66e17f4b8e968e1d58924ee9a38b720d0df7989c Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 12 Sep 2024 10:01:27 +0300 Subject: [PATCH 0803/1413] [#1368] cli/container: Use dedicated method to list user attributes Signed-off-by: Aleksey Savchuk --- cmd/frostfs-cli/modules/container/list.go | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index 6d0019ec4c..f01e4db4dc 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -1,9 +1,6 @@ package container import ( - "strings" - - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" @@ -84,12 +81,8 @@ var listContainersCmd = &cobra.Command{ cmd.Println(cnrID.String()) if flagVarListPrintAttr { - cnr.IterateAttributes(func(key, val string) { - if !strings.HasPrefix(key, container.SysAttributePrefix) && !strings.HasPrefix(key, container.SysAttributePrefixNeoFS) { - // FIXME(@cthulhu-rider): https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/issues/97 - // Use dedicated method to skip system attributes. - cmd.Printf(" %s: %s\n", key, val) - } + cnr.IterateUserAttributes(func(key, val string) { + cmd.Printf(" %s: %s\n", key, val) }) } } From 5f6c7cbdb102c51e4e994198f805a33084f3b9de Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 9 Sep 2024 18:37:06 +0300 Subject: [PATCH 0804/1413] [#1367] writecache: Drop bbolt DB Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 2 +- .../writecache/{cachebbolt.go => cache.go} | 15 +- pkg/local_object_storage/writecache/delete.go | 39 +--- pkg/local_object_storage/writecache/flush.go | 192 ++++-------------- .../writecache/flush_test.go | 28 +-- pkg/local_object_storage/writecache/get.go | 14 +- pkg/local_object_storage/writecache/mode.go | 39 ++-- .../writecache/mode_test.go | 8 +- .../writecache/options.go | 11 - pkg/local_object_storage/writecache/put.go | 53 +---- pkg/local_object_storage/writecache/state.go | 35 +--- .../writecache/storage.go | 61 ------ 12 files changed, 82 insertions(+), 415 deletions(-) rename pkg/local_object_storage/writecache/{cachebbolt.go => cache.go} (94%) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 97b1895293..87e4e0b43b 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -542,6 +542,6 @@ const ( StartedWritecacheSealAsync = "started writecache seal async" WritecacheSealCompletedAsync = "writecache seal completed successfully" FailedToSealWritecacheAsync = "failed to seal writecache async" - WritecacheShrinkSkippedNotEmpty = "writecache shrink skipped: database is not empty" + WritecacheShrinkSkippedNotEmpty = "writecache shrink skipped: not empty" BlobovniczatreeFailedToRemoveRebuildTempFile = "failed to remove rebuild temp file" ) diff --git a/pkg/local_object_storage/writecache/cachebbolt.go b/pkg/local_object_storage/writecache/cache.go similarity index 94% rename from pkg/local_object_storage/writecache/cachebbolt.go rename to pkg/local_object_storage/writecache/cache.go index f1e6a619ad..ff38de4079 100644 --- a/pkg/local_object_storage/writecache/cachebbolt.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -2,7 +2,7 @@ package writecache import ( "context" - "os" + "fmt" "sync" "sync/atomic" @@ -27,8 +27,6 @@ type cache struct { cancel atomic.Value // wg is a wait group for flush workers. wg sync.WaitGroup - // store contains underlying database. - store // fsTree contains big files stored directly on file-system. fsTree *fstree.FSTree } @@ -67,7 +65,6 @@ func New(opts ...Option) Cache { maxCacheSize: defaultMaxCacheSize, maxBatchSize: bbolt.DefaultMaxBatchSize, maxBatchDelay: bbolt.DefaultMaxBatchDelay, - openFile: os.OpenFile, metrics: DefaultMetrics(), }, } @@ -102,13 +99,15 @@ func (c *cache) Open(_ context.Context, mod mode.Mode) error { if err != nil { return metaerr.Wrap(err) } - return metaerr.Wrap(c.initCounters()) } // Init runs necessary services. func (c *cache) Init() error { c.metrics.SetMode(mode.ConvertToComponentModeDegraded(c.mode)) + if err := c.flushAndDropBBoltDB(context.Background()); err != nil { + return fmt.Errorf("flush previous version write-cache database: %w", err) + } ctx, cancel := context.WithCancel(context.Background()) c.cancel.Store(cancel) c.runFlushLoop(ctx) @@ -132,10 +131,10 @@ func (c *cache) Close() error { defer c.modeMtx.Unlock() var err error - if c.db != nil { - err = c.db.Close() + if c.fsTree != nil { + err = c.fsTree.Close() if err != nil { - c.db = nil + c.fsTree = nil } } c.metrics.Close() diff --git a/pkg/local_object_storage/writecache/delete.go b/pkg/local_object_storage/writecache/delete.go index b1a0511ee8..dda284439e 100644 --- a/pkg/local_object_storage/writecache/delete.go +++ b/pkg/local_object_storage/writecache/delete.go @@ -2,7 +2,6 @@ package writecache import ( "context" - "math" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" @@ -10,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) @@ -45,46 +43,11 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { return ErrDegraded } - saddr := addr.EncodeToString() - - var dataSize int - _ = c.db.View(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - dataSize = len(b.Get([]byte(saddr))) - return nil - }) - - if dataSize > 0 { - storageType = StorageTypeDB - var recordDeleted bool - err := c.db.Update(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - key := []byte(saddr) - recordDeleted = b.Get(key) != nil - err := b.Delete(key) - return err - }) - if err != nil { - return err - } - storagelog.Write(c.log, - storagelog.AddressField(saddr), - storagelog.StorageTypeField(wcStorageType), - storagelog.OpField("db DELETE"), - ) - if recordDeleted { - c.objCounters.cDB.Add(math.MaxUint64) - c.estimateCacheSize() - } - deleted = true - return nil - } - storageType = StorageTypeFSTree _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr}) if err == nil { storagelog.Write(c.log, - storagelog.AddressField(saddr), + storagelog.AddressField(addr.EncodeToString()), storagelog.StorageTypeField(wcStorageType), storagelog.OpField("fstree DELETE"), ) diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 930ac84312..074756e329 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -4,6 +4,9 @@ import ( "bytes" "context" "errors" + "fmt" + "os" + "path/filepath" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -16,7 +19,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/mr-tron/base58" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -24,10 +26,6 @@ import ( ) const ( - // flushBatchSize is amount of keys which will be read from cache to be flushed - // to the main storage. It is used to reduce contention between cache put - // and cache persist. - flushBatchSize = 512 // defaultFlushWorkersCount is number of workers for putting objects in main storage. defaultFlushWorkersCount = 20 // defaultFlushInterval is default time interval between successive flushes. @@ -41,112 +39,11 @@ func (c *cache) runFlushLoop(ctx context.Context) { if c.disableBackgroundFlush { return } - for range c.workersCount { - c.wg.Add(1) - go c.workerFlushSmall(ctx) - } - c.wg.Add(1) go func() { c.workerFlushBig(ctx) c.wg.Done() }() - - c.wg.Add(1) - go func() { - defer c.wg.Done() - - tt := time.NewTimer(defaultFlushInterval) - defer tt.Stop() - - for { - select { - case <-tt.C: - c.flushSmallObjects(ctx) - tt.Reset(defaultFlushInterval) - c.estimateCacheSize() - case <-ctx.Done(): - return - } - } - }() -} - -func (c *cache) flushSmallObjects(ctx context.Context) { - var lastKey []byte - for { - select { - case <-ctx.Done(): - return - default: - } - - var m []objectInfo - - c.modeMtx.RLock() - if c.readOnly() { - c.modeMtx.RUnlock() - time.Sleep(time.Second) - continue - } - - // We put objects in batches of fixed size to not interfere with main put cycle a lot. - _ = c.db.View(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - cs := b.Cursor() - - var k, v []byte - - if len(lastKey) == 0 { - k, v = cs.First() - } else { - k, v = cs.Seek(lastKey) - if bytes.Equal(k, lastKey) { - k, v = cs.Next() - } - } - - for ; k != nil && len(m) < flushBatchSize; k, v = cs.Next() { - if len(lastKey) == len(k) { - copy(lastKey, k) - } else { - lastKey = bytes.Clone(k) - } - - m = append(m, objectInfo{ - addr: string(k), - data: bytes.Clone(v), - }) - } - return nil - }) - - var count int - for i := range m { - obj := objectSDK.New() - if err := obj.Unmarshal(m[i].data); err != nil { - continue - } - m[i].obj = obj - - count++ - select { - case c.flushCh <- m[i]: - case <-ctx.Done(): - c.modeMtx.RUnlock() - return - } - } - - c.modeMtx.RUnlock() - if count == 0 { - break - } - - c.log.Debug(logs.WritecacheTriedToFlushItemsFromWritecache, - zap.Int("count", count), - zap.String("start", base58.Encode(lastKey))) - } } func (c *cache) workerFlushBig(ctx context.Context) { @@ -197,9 +94,6 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { err = c.flushObject(ctx, &obj, e.ObjectData, StorageTypeFSTree) if err != nil { - if ignoreErrors { - return nil - } return err } @@ -211,29 +105,6 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { return err } -// workerFlushSmall writes small objects to the main storage. -func (c *cache) workerFlushSmall(ctx context.Context) { - defer c.wg.Done() - - var objInfo objectInfo - for { - // Give priority to direct put. - select { - case objInfo = <-c.flushCh: - case <-ctx.Done(): - return - } - - err := c.flushObject(ctx, objInfo.obj, objInfo.data, StorageTypeDB) - if err != nil { - // Error is handled in flushObject. - continue - } - - c.deleteFromDB(objInfo.addr, true) - } -} - // flushObject is used to write object directly to the main storage. func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []byte, st StorageType) error { var err error @@ -300,13 +171,33 @@ func (c *cache) Flush(ctx context.Context, ignoreErrors, seal bool) error { } func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { - if err := c.flushFSTree(ctx, ignoreErrors); err != nil { - return err + return c.flushFSTree(ctx, ignoreErrors) +} + +type batchItem struct { + data []byte + address string +} + +func (c *cache) flushAndDropBBoltDB(ctx context.Context) error { + _, err := os.Stat(filepath.Join(c.path, dbName)) + if err != nil && os.IsNotExist(err) { + return nil } + if err != nil { + return fmt.Errorf("could not check write-cache database existence: %w", err) + } + db, err := OpenDB(c.path, true, os.OpenFile, c.pageSize) + if err != nil { + return fmt.Errorf("could not open write-cache database: %w", err) + } + defer func() { + _ = db.Close() + }() var last string for { - batch, err := c.readNextDBBatch(ignoreErrors, last) + batch, err := c.readNextDBBatch(db, last) if err != nil { return err } @@ -316,32 +207,27 @@ func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { for _, item := range batch { var obj objectSDK.Object if err := obj.Unmarshal(item.data); err != nil { - c.reportFlushError(logs.FSTreeCantDecodeDBObjectAddress, item.address, metaerr.Wrap(err)) - if ignoreErrors { - continue - } - return err + return fmt.Errorf("unmarshal object from database: %w", err) } - if err := c.flushObject(ctx, &obj, item.data, StorageTypeDB); err != nil { - return err + return fmt.Errorf("flush object from database: %w", err) } - c.deleteFromDB(item.address, false) } last = batch[len(batch)-1].address } + if err := db.Close(); err != nil { + return fmt.Errorf("close write-cache database: %w", err) + } + if err := os.Remove(filepath.Join(c.path, dbName)); err != nil { + return fmt.Errorf("remove write-cache database: %w", err) + } return nil } -type batchItem struct { - data []byte - address string -} - -func (c *cache) readNextDBBatch(ignoreErrors bool, last string) ([]batchItem, error) { +func (c *cache) readNextDBBatch(db *bbolt.DB, last string) ([]batchItem, error) { const batchSize = 100 var batch []batchItem - err := c.db.View(func(tx *bbolt.Tx) error { + err := db.View(func(tx *bbolt.Tx) error { var addr oid.Address b := tx.Bucket(defaultBucket) @@ -352,11 +238,7 @@ func (c *cache) readNextDBBatch(ignoreErrors bool, last string) ([]batchItem, er continue } if err := addr.DecodeString(sa); err != nil { - c.reportFlushError(logs.FSTreeCantDecodeDBObjectAddress, sa, metaerr.Wrap(err)) - if ignoreErrors { - continue - } - return err + return fmt.Errorf("decode address from database: %w", err) } batch = append(batch, batchItem{data: bytes.Clone(data), address: sa}) diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index a637da45d0..9c7e240e07 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -19,7 +19,6 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" - "go.etcd.io/bbolt" "go.uber.org/zap" ) @@ -47,31 +46,6 @@ func TestFlush(t *testing.T) { } failures := []TestFailureInjector[Option]{ - { - Desc: "db, invalid address", - InjectFn: func(t *testing.T, wc Cache) { - c := wc.(*cache) - obj := testutil.GenerateObject() - data, err := obj.Marshal() - require.NoError(t, err) - require.NoError(t, c.db.Batch(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - return b.Put([]byte{1, 2, 3}, data) - })) - }, - }, - { - Desc: "db, invalid object", - InjectFn: func(t *testing.T, wc Cache) { - c := wc.(*cache) - require.NoError(t, c.db.Batch(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - k := []byte(oidtest.Address().EncodeToString()) - v := []byte{1, 2, 3} - return b.Put(k, v) - })) - }, - }, { Desc: "fs, read error", InjectFn: func(t *testing.T, wc Cache) { @@ -263,7 +237,7 @@ func check(t *testing.T, mb *meta.DB, bs *blobstor.BlobStor, objects []objectPai prm.StorageID = mRes.StorageID() res, err := bs.Get(context.Background(), prm) - require.NoError(t, err) + require.NoError(t, err, objects[i].addr) require.Equal(t, objects[i].obj, res.Object) } } diff --git a/pkg/local_object_storage/writecache/get.go b/pkg/local_object_storage/writecache/get.go index bf26833bd8..c0847a65f3 100644 --- a/pkg/local_object_storage/writecache/get.go +++ b/pkg/local_object_storage/writecache/get.go @@ -37,11 +37,11 @@ func (c *cache) Get(ctx context.Context, addr oid.Address) (*objectSDK.Object, e return nil, ErrDegraded } - obj, err := c.getInternal(ctx, saddr, addr) + obj, err := c.getInternal(ctx, addr) return obj, metaerr.Wrap(err) } -func (c *cache) getInternal(ctx context.Context, saddr string, addr oid.Address) (*objectSDK.Object, error) { +func (c *cache) getInternal(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) { found := false storageType := StorageTypeUndefined startedAt := time.Now() @@ -49,14 +49,6 @@ func (c *cache) getInternal(ctx context.Context, saddr string, addr oid.Address) c.metrics.Get(time.Since(startedAt), found, storageType) }() - value, err := Get(c.db, []byte(saddr)) - if err == nil { - obj := objectSDK.New() - found = true - storageType = StorageTypeDB - return obj, obj.Unmarshal(value) - } - res, err := c.fsTree.Get(ctx, common.GetPrm{Address: addr}) if err != nil { return nil, logicerr.Wrap(new(apistatus.ObjectNotFound)) @@ -87,7 +79,7 @@ func (c *cache) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, return nil, ErrDegraded } - obj, err := c.getInternal(ctx, saddr, addr) + obj, err := c.getInternal(ctx, addr) if err != nil { return nil, metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index 44da9b36e1..d12dd603bc 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -5,13 +5,12 @@ import ( "errors" "fmt" "os" - "path/filepath" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) @@ -53,7 +52,7 @@ func (c *cache) setMode(ctx context.Context, m mode.Mode, prm setModePrm) error } } - if err := c.closeDB(prm.shrink); err != nil { + if err := c.closeStorage(ctx, prm.shrink); err != nil { return err } @@ -78,33 +77,37 @@ func (c *cache) setMode(ctx context.Context, m mode.Mode, prm setModePrm) error return nil } -func (c *cache) closeDB(shrink bool) error { - if c.db == nil { +func (c *cache) closeStorage(ctx context.Context, shrink bool) error { + if c.fsTree == nil { return nil } if !shrink { - if err := c.db.Close(); err != nil { - return fmt.Errorf("can't close write-cache database: %w", err) + if err := c.fsTree.Close(); err != nil { + return fmt.Errorf("can't close write-cache storage: %w", err) } return nil } - var empty bool - err := c.db.View(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - empty = b == nil || b.Stats().KeyN == 0 - return nil + empty := true + _, err := c.fsTree.Iterate(ctx, common.IteratePrm{ + Handler: func(common.IterationElement) error { + return errIterationCompleted + }, }) - if err != nil && !errors.Is(err, bbolt.ErrDatabaseNotOpen) { - return fmt.Errorf("failed to check DB items: %w", err) + if err != nil { + if errors.Is(err, errIterationCompleted) { + empty = false + } else { + return fmt.Errorf("failed to check write-cache items: %w", err) + } } - if err := c.db.Close(); err != nil { - return fmt.Errorf("can't close write-cache database: %w", err) + if err := c.fsTree.Close(); err != nil { + return fmt.Errorf("can't close write-cache storage: %w", err) } if empty { - err := os.Remove(filepath.Join(c.path, dbName)) + err := os.RemoveAll(c.path) if err != nil && !os.IsNotExist(err) { - return fmt.Errorf("failed to remove DB file: %w", err) + return fmt.Errorf("failed to remove write-cache files: %w", err) } } else { c.log.Info(logs.WritecacheShrinkSkippedNotEmpty) diff --git a/pkg/local_object_storage/writecache/mode_test.go b/pkg/local_object_storage/writecache/mode_test.go index f684c15bcf..70cfe83828 100644 --- a/pkg/local_object_storage/writecache/mode_test.go +++ b/pkg/local_object_storage/writecache/mode_test.go @@ -17,14 +17,14 @@ func TestMode(t *testing.T) { WithPath(t.TempDir())) require.NoError(t, wc.Open(context.Background(), mode.DegradedReadOnly)) - require.Nil(t, wc.(*cache).db) + require.Nil(t, wc.(*cache).fsTree) require.NoError(t, wc.Init()) - require.Nil(t, wc.(*cache).db) + require.Nil(t, wc.(*cache).fsTree) require.NoError(t, wc.Close()) require.NoError(t, wc.Open(context.Background(), mode.Degraded)) - require.Nil(t, wc.(*cache).db) + require.Nil(t, wc.(*cache).fsTree) require.NoError(t, wc.Init()) - require.Nil(t, wc.(*cache).db) + require.Nil(t, wc.(*cache).fsTree) require.NoError(t, wc.Close()) } diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index 980cf93037..7845c5da95 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -1,8 +1,6 @@ package writecache import ( - "io/fs" - "os" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" @@ -42,8 +40,6 @@ type options struct { noSync bool // reportError is the function called when encountering disk errors in background workers. reportError func(string, error) - // openFile is the function called internally by bbolt to open database files. Useful for hermetic testing. - openFile func(string, int, fs.FileMode) (*os.File, error) // metrics is metrics implementation metrics Metrics // disableBackgroundFlush is for testing purposes only. @@ -155,13 +151,6 @@ func WithReportErrorFunc(f func(string, error)) Option { } } -// WithOpenFile sets the OpenFile function to use internally by bolt. Useful for hermetic testing. -func WithOpenFile(f func(string, int, fs.FileMode) (*os.File, error)) Option { - return func(o *options) { - o.openFile = f - } -} - // WithMetrics sets metrics implementation. func WithMetrics(metrics Metrics) Option { return func(o *options) { diff --git a/pkg/local_object_storage/writecache/put.go b/pkg/local_object_storage/writecache/put.go index ae0e8b77a4..c53067beac 100644 --- a/pkg/local_object_storage/writecache/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -8,7 +8,6 @@ import ( storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) @@ -50,62 +49,16 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro return common.PutRes{}, ErrBigObject } - oi := objectInfo{ - addr: prm.Address.EncodeToString(), - obj: prm.Object, - data: prm.RawData, - } - - if sz <= c.smallObjectSize { - storageType = StorageTypeDB - err := c.putSmall(oi) - if err == nil { - added = true - } - return common.PutRes{}, err - } - storageType = StorageTypeFSTree - err := c.putBig(ctx, oi.addr, prm) + err := c.putBig(ctx, prm) if err == nil { added = true } return common.PutRes{}, metaerr.Wrap(err) } -// putSmall persists small objects to the write-cache database and -// pushes the to the flush workers queue. -func (c *cache) putSmall(obj objectInfo) error { - if !c.hasEnoughSpaceDB() { - return ErrOutOfSpace - } - - var newRecord bool - err := c.db.Batch(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - key := []byte(obj.addr) - newRecord = b.Get(key) == nil - if newRecord { - return b.Put(key, obj.data) - } - return nil - }) - if err == nil { - storagelog.Write(c.log, - storagelog.AddressField(obj.addr), - storagelog.StorageTypeField(wcStorageType), - storagelog.OpField("db PUT"), - ) - if newRecord { - c.objCounters.cDB.Add(1) - c.estimateCacheSize() - } - } - return err -} - // putBig writes object to FSTree and pushes it to the flush workers queue. -func (c *cache) putBig(ctx context.Context, addr string, prm common.PutPrm) error { +func (c *cache) putBig(ctx context.Context, prm common.PutPrm) error { if !c.hasEnoughSpaceFS() { return ErrOutOfSpace } @@ -116,7 +69,7 @@ func (c *cache) putBig(ctx context.Context, addr string, prm common.PutPrm) erro } storagelog.Write(c.log, - storagelog.AddressField(addr), + storagelog.AddressField(prm.Address.EncodeToString()), storagelog.StorageTypeField(wcStorageType), storagelog.OpField("fstree PUT"), ) diff --git a/pkg/local_object_storage/writecache/state.go b/pkg/local_object_storage/writecache/state.go index d03f4a63e3..e4e22f4042 100644 --- a/pkg/local_object_storage/writecache/state.go +++ b/pkg/local_object_storage/writecache/state.go @@ -1,29 +1,18 @@ package writecache import ( - "fmt" "math" "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" - "go.etcd.io/bbolt" ) func (c *cache) estimateCacheSize() (uint64, uint64) { - dbCount := c.objCounters.DB() fsCount := c.objCounters.FS() - if fsCount > 0 { - fsCount-- // db file - } - dbSize := dbCount * c.smallObjectSize fsSize := fsCount * c.maxObjectSize - c.metrics.SetEstimateSize(dbSize, fsSize) - c.metrics.SetActualCounters(dbCount, fsCount) - return dbCount + fsCount, dbSize + fsSize -} - -func (c *cache) hasEnoughSpaceDB() bool { - return c.hasEnoughSpace(c.smallObjectSize) + c.metrics.SetEstimateSize(0, fsSize) + c.metrics.SetActualCounters(0, fsCount) + return fsCount, fsSize } func (c *cache) hasEnoughSpaceFS() bool { @@ -41,11 +30,7 @@ func (c *cache) hasEnoughSpace(objectSize uint64) bool { var _ fstree.FileCounter = &counters{} type counters struct { - cDB, cFS atomic.Uint64 -} - -func (x *counters) DB() uint64 { - return x.cDB.Load() + cFS atomic.Uint64 } func (x *counters) FS() uint64 { @@ -68,18 +53,6 @@ func (x *counters) Dec() { } func (c *cache) initCounters() error { - var inDB uint64 - err := c.db.View(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - if b != nil { - inDB = uint64(b.Stats().KeyN) - } - return nil - }) - if err != nil { - return fmt.Errorf("could not read write-cache DB counter: %w", err) - } - c.objCounters.cDB.Store(inDB) c.estimateCacheSize() return nil } diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index 57021cc177..309bd2a66a 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -3,7 +3,6 @@ package writecache import ( "context" "fmt" - "math" "os" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -14,16 +13,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.etcd.io/bbolt" "go.uber.org/zap" ) -// store represents persistent storage with in-memory LRU cache -// for flushed items on top of it. -type store struct { - db *bbolt.DB -} - const dbName = "small.bolt" func (c *cache) openStore(mod mode.ComponentMode) error { @@ -32,24 +24,6 @@ func (c *cache) openStore(mod mode.ComponentMode) error { return err } - c.db, err = OpenDB(c.path, mod.ReadOnly(), c.openFile, c.pageSize) - if err != nil { - return fmt.Errorf("could not open database: %w", err) - } - - c.db.MaxBatchSize = c.maxBatchSize - c.db.MaxBatchDelay = c.maxBatchDelay - - if !mod.ReadOnly() { - err = c.db.Update(func(tx *bbolt.Tx) error { - _, err := tx.CreateBucketIfNotExists(defaultBucket) - return err - }) - if err != nil { - return fmt.Errorf("could not create default bucket: %w", err) - } - } - c.fsTree = fstree.New( fstree.WithPath(c.path), fstree.WithPerm(os.ModePerm), @@ -68,41 +42,6 @@ func (c *cache) openStore(mod mode.ComponentMode) error { return nil } -func (c *cache) deleteFromDB(key string, batched bool) { - var recordDeleted bool - var err error - if batched { - err = c.db.Batch(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - key := []byte(key) - recordDeleted = b.Get(key) != nil - return b.Delete(key) - }) - } else { - err = c.db.Update(func(tx *bbolt.Tx) error { - b := tx.Bucket(defaultBucket) - key := []byte(key) - recordDeleted = b.Get(key) != nil - return b.Delete(key) - }) - } - - if err == nil { - c.metrics.Evict(StorageTypeDB) - storagelog.Write(c.log, - storagelog.AddressField(key), - storagelog.StorageTypeField(wcStorageType), - storagelog.OpField("db DELETE"), - ) - if recordDeleted { - c.objCounters.cDB.Add(math.MaxUint64) - c.estimateCacheSize() - } - } else { - c.log.Error(logs.WritecacheCantRemoveObjectsFromTheDatabase, zap.Error(err)) - } -} - func (c *cache) deleteFromDisk(ctx context.Context, addr oid.Address) { _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr}) if err != nil && !client.IsErrObjectNotFound(err) { From b142b6f48e46210235a56840c79da358120cf0cc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Sep 2024 11:01:30 +0300 Subject: [PATCH 0805/1413] [#1367] fstree: Add size to file counter FSTree file counter used by writecache. As writecache has now only one storage, so it is required to use real object size to get writecache size more accurate than `count * max_object_size`. Signed-off-by: Dmitrii Stepanov --- .../blobstor/fstree/counter.go | 61 +++++++++++++++---- .../blobstor/fstree/fstree.go | 22 ++++--- .../blobstor/fstree/fstree_test.go | 15 +++-- .../blobstor/fstree/fstree_write_generic.go | 27 +++++--- .../blobstor/fstree/fstree_write_linux.go | 42 ++++++++++--- pkg/local_object_storage/writecache/cache.go | 3 + .../writecache/options.go | 2 - pkg/local_object_storage/writecache/state.go | 41 ++----------- .../writecache/storage.go | 2 +- 9 files changed, 130 insertions(+), 85 deletions(-) diff --git a/pkg/local_object_storage/blobstor/fstree/counter.go b/pkg/local_object_storage/blobstor/fstree/counter.go index 718104e2ea..b5dbc9e409 100644 --- a/pkg/local_object_storage/blobstor/fstree/counter.go +++ b/pkg/local_object_storage/blobstor/fstree/counter.go @@ -1,22 +1,21 @@ package fstree import ( - "math" - "sync/atomic" + "sync" ) // FileCounter used to count files in FSTree. The implementation must be thread-safe. type FileCounter interface { - Set(v uint64) - Inc() - Dec() + Set(count, size uint64) + Inc(size uint64) + Dec(size uint64) } type noopCounter struct{} -func (c *noopCounter) Set(uint64) {} -func (c *noopCounter) Inc() {} -func (c *noopCounter) Dec() {} +func (c *noopCounter) Set(uint64, uint64) {} +func (c *noopCounter) Inc(uint64) {} +func (c *noopCounter) Dec(uint64) {} func counterEnabled(c FileCounter) bool { _, noop := c.(*noopCounter) @@ -24,14 +23,50 @@ func counterEnabled(c FileCounter) bool { } type SimpleCounter struct { - v atomic.Uint64 + mtx sync.RWMutex + count uint64 + size uint64 } func NewSimpleCounter() *SimpleCounter { return &SimpleCounter{} } -func (c *SimpleCounter) Set(v uint64) { c.v.Store(v) } -func (c *SimpleCounter) Inc() { c.v.Add(1) } -func (c *SimpleCounter) Dec() { c.v.Add(math.MaxUint64) } -func (c *SimpleCounter) Value() uint64 { return c.v.Load() } +func (c *SimpleCounter) Set(count, size uint64) { + c.mtx.Lock() + defer c.mtx.Unlock() + + c.count = count + c.size = size +} + +func (c *SimpleCounter) Inc(size uint64) { + c.mtx.Lock() + defer c.mtx.Unlock() + + c.count++ + c.size += size +} + +func (c *SimpleCounter) Dec(size uint64) { + c.mtx.Lock() + defer c.mtx.Unlock() + + if c.count > 0 { + c.count-- + } else { + panic("fstree.SimpleCounter: invalid count") + } + if c.size >= size { + c.size -= size + } else { + panic("fstree.SimpleCounter: invalid size") + } +} + +func (c *SimpleCounter) CountSize() (uint64, uint64) { + c.mtx.RLock() + defer c.mtx.RUnlock() + + return c.count, c.size +} diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 02580dbfaa..bf6ba51e58 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -435,32 +435,38 @@ func (t *FSTree) initFileCounter() error { return nil } - counter, err := t.countFiles() + count, size, err := t.countFiles() if err != nil { return err } - t.fileCounter.Set(counter) + t.fileCounter.Set(count, size) return nil } -func (t *FSTree) countFiles() (uint64, error) { - var counter uint64 +func (t *FSTree) countFiles() (uint64, uint64, error) { + var count, size uint64 // it is simpler to just consider every file // that is not directory as an object err := filepath.WalkDir(t.RootPath, func(_ string, d fs.DirEntry, _ error) error { - if !d.IsDir() { - counter++ + if d.IsDir() { + return nil } + count++ + info, err := d.Info() + if err != nil { + return err + } + size += uint64(info.Size()) return nil }, ) if err != nil { - return 0, fmt.Errorf("could not walk through %s directory: %w", t.RootPath, err) + return 0, 0, fmt.Errorf("could not walk through %s directory: %w", t.RootPath, err) } - return counter, nil + return count, size, nil } func (t *FSTree) ObjectsCount(ctx context.Context) (uint64, error) { diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_test.go b/pkg/local_object_storage/blobstor/fstree/fstree_test.go index 5786dfd3b2..f39c7296ef 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_test.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_test.go @@ -47,8 +47,9 @@ func TestObjectCounter(t *testing.T) { require.NoError(t, fst.Open(mode.ComponentReadWrite)) require.NoError(t, fst.Init()) - counterValue := counter.Value() - require.Equal(t, uint64(0), counterValue) + count, size := counter.CountSize() + require.Equal(t, uint64(0), count) + require.Equal(t, uint64(0), size) defer func() { require.NoError(t, fst.Close()) @@ -64,9 +65,6 @@ func TestObjectCounter(t *testing.T) { putPrm.Address = addr putPrm.RawData, _ = obj.Marshal() - var getPrm common.GetPrm - getPrm.Address = putPrm.Address - var delPrm common.DeletePrm delPrm.Address = addr @@ -95,8 +93,9 @@ func TestObjectCounter(t *testing.T) { require.NoError(t, eg.Wait()) - counterValue = counter.Value() - realCount, err := fst.countFiles() + count, size = counter.CountSize() + realCount, realSize, err := fst.countFiles() require.NoError(t, err) - require.Equal(t, realCount, counterValue) + require.Equal(t, realCount, count, "real %d, actual %d", realCount, count) + require.Equal(t, realSize, size, "real %d, actual %d", realSize, size) } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 8b26228855..801fc4a22e 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -78,14 +78,14 @@ func (w *genericWriter) writeAndRename(tmpPath, p string, data []byte) error { } if w.fileCounterEnabled { - w.fileCounter.Inc() + w.fileCounter.Inc(uint64(len(data))) var targetFileExists bool if _, e := os.Stat(p); e == nil { targetFileExists = true } err = os.Rename(tmpPath, p) if err == nil && targetFileExists { - w.fileCounter.Dec() + w.fileCounter.Dec(uint64(len(data))) } } else { err = os.Rename(tmpPath, p) @@ -110,12 +110,7 @@ func (w *genericWriter) writeFile(p string, data []byte) error { func (w *genericWriter) removeFile(p string) error { var err error if w.fileCounterEnabled { - w.fileGuard.Lock(p) - err = os.Remove(p) - w.fileGuard.Unlock(p) - if err == nil { - w.fileCounter.Dec() - } + err = w.removeWithCounter(p) } else { err = os.Remove(p) } @@ -125,3 +120,19 @@ func (w *genericWriter) removeFile(p string) error { } return err } + +func (w *genericWriter) removeWithCounter(p string) error { + w.fileGuard.Lock(p) + defer w.fileGuard.Unlock(p) + + stat, err := os.Stat(p) + if err != nil { + return err + } + + if err := os.Remove(p); err != nil { + return err + } + w.fileCounter.Dec(uint64(stat.Size())) + return nil +} diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index efc5a3d3d4..3127579ac9 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "golang.org/x/sys/unix" ) @@ -18,7 +19,9 @@ type linuxWriter struct { perm uint32 flags int - counter FileCounter + fileGuard keyLock + fileCounter FileCounter + fileCounterEnabled bool } func newSpecificWriteData(c FileCounter, root string, perm fs.FileMode, noSync bool) writer { @@ -33,11 +36,18 @@ func newSpecificWriteData(c FileCounter, root string, perm fs.FileMode, noSync b return nil } _ = unix.Close(fd) // Don't care about error. + var fileGuard keyLock = &noopKeyLock{} + fileCounterEnabled := counterEnabled(c) + if fileCounterEnabled { + fileGuard = utilSync.NewKeyLocker[string]() + } w := &linuxWriter{ - root: root, - perm: uint32(perm), - flags: flags, - counter: c, + root: root, + perm: uint32(perm), + flags: flags, + fileGuard: fileGuard, + fileCounter: c, + fileCounterEnabled: fileCounterEnabled, } return w } @@ -51,6 +61,10 @@ func (w *linuxWriter) writeData(p string, data []byte) error { } func (w *linuxWriter) writeFile(p string, data []byte) error { + if w.fileCounterEnabled { + w.fileGuard.Lock(p) + defer w.fileGuard.Unlock(p) + } fd, err := unix.Open(w.root, w.flags, w.perm) if err != nil { return err @@ -61,7 +75,7 @@ func (w *linuxWriter) writeFile(p string, data []byte) error { if n == len(data) { err = unix.Linkat(unix.AT_FDCWD, tmpPath, unix.AT_FDCWD, p, unix.AT_SYMLINK_FOLLOW) if err == nil { - w.counter.Inc() + w.fileCounter.Inc(uint64(len(data))) } if errors.Is(err, unix.EEXIST) { err = nil @@ -78,12 +92,24 @@ func (w *linuxWriter) writeFile(p string, data []byte) error { } func (w *linuxWriter) removeFile(p string) error { - err := unix.Unlink(p) + if w.fileCounterEnabled { + w.fileGuard.Lock(p) + defer w.fileGuard.Unlock(p) + } + var stat unix.Stat_t + err := unix.Stat(p, &stat) + if err != nil { + if err == unix.ENOENT { + return logicerr.Wrap(new(apistatus.ObjectNotFound)) + } + return err + } + err = unix.Unlink(p) if err != nil && err == unix.ENOENT { return logicerr.Wrap(new(apistatus.ObjectNotFound)) } if err == nil { - w.counter.Dec() + w.fileCounter.Dec(uint64(stat.Size)) } return err } diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index ff38de4079..f2280f2f46 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -29,6 +29,8 @@ type cache struct { wg sync.WaitGroup // fsTree contains big files stored directly on file-system. fsTree *fstree.FSTree + // counter contains atomic counters for the number of objects stored in cache. + counter *fstree.SimpleCounter } // wcStorageType is used for write-cache operations logging. @@ -56,6 +58,7 @@ func New(opts ...Option) Cache { c := &cache{ flushCh: make(chan objectInfo), mode: mode.Disabled, + counter: fstree.NewSimpleCounter(), options: options{ log: &logger.Logger{Logger: zap.NewNop()}, diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index 7845c5da95..0643faac0b 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -30,8 +30,6 @@ type options struct { // maxCacheCount is the maximum total count of all object saved in cache. // 0 (no limit) by default. maxCacheCount uint64 - // objCounters contains atomic counters for the number of objects stored in cache. - objCounters counters // maxBatchSize is the maximum batch size for the small object database. maxBatchSize int // maxBatchDelay is the maximum batch wait time for the small object database. diff --git a/pkg/local_object_storage/writecache/state.go b/pkg/local_object_storage/writecache/state.go index e4e22f4042..748c78bcba 100644 --- a/pkg/local_object_storage/writecache/state.go +++ b/pkg/local_object_storage/writecache/state.go @@ -1,18 +1,10 @@ package writecache -import ( - "math" - "sync/atomic" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" -) - func (c *cache) estimateCacheSize() (uint64, uint64) { - fsCount := c.objCounters.FS() - fsSize := fsCount * c.maxObjectSize - c.metrics.SetEstimateSize(0, fsSize) - c.metrics.SetActualCounters(0, fsCount) - return fsCount, fsSize + count, size := c.counter.CountSize() + c.metrics.SetEstimateSize(0, size) + c.metrics.SetActualCounters(0, count) + return count, size } func (c *cache) hasEnoughSpaceFS() bool { @@ -27,31 +19,6 @@ func (c *cache) hasEnoughSpace(objectSize uint64) bool { return c.maxCacheSize >= size+objectSize } -var _ fstree.FileCounter = &counters{} - -type counters struct { - cFS atomic.Uint64 -} - -func (x *counters) FS() uint64 { - return x.cFS.Load() -} - -// Set implements fstree.ObjectCounter. -func (x *counters) Set(v uint64) { - x.cFS.Store(v) -} - -// Inc implements fstree.ObjectCounter. -func (x *counters) Inc() { - x.cFS.Add(1) -} - -// Dec implements fstree.ObjectCounter. -func (x *counters) Dec() { - x.cFS.Add(math.MaxUint64) -} - func (c *cache) initCounters() error { c.estimateCacheSize() return nil diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index 309bd2a66a..e708a529e1 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -30,7 +30,7 @@ func (c *cache) openStore(mod mode.ComponentMode) error { fstree.WithDepth(1), fstree.WithDirNameLen(1), fstree.WithNoSync(c.noSync), - fstree.WithFileCounter(&c.objCounters), + fstree.WithFileCounter(c.counter), ) if err := c.fsTree.Open(mod); err != nil { return fmt.Errorf("could not open FSTree: %w", err) From 2dd3a6f7a85800452f38ddb3127dea455b6366dc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Sep 2024 11:47:42 +0300 Subject: [PATCH 0806/1413] [#1367] fstree: Add IterateInfo method Signed-off-by: Dmitrii Stepanov --- .../blobstor/fstree/fstree.go | 75 +++++++++++++++++++ .../blobstor/fstree/metrics.go | 2 + pkg/local_object_storage/metrics/fstree.go | 4 + 3 files changed, 81 insertions(+) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index bf6ba51e58..1c60ec340f 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -222,6 +222,81 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr return nil } +type ObjectInfo struct { + Address oid.Address + DataSize uint64 +} +type IterateInfoHandler func(ObjectInfo) error + +func (t *FSTree) IterateInfo(ctx context.Context, handler IterateInfoHandler) error { + var ( + err error + startedAt = time.Now() + ) + defer func() { + t.metrics.IterateInfo(time.Since(startedAt), err == nil) + }() + _, span := tracing.StartSpanFromContext(ctx, "FSTree.IterateInfo") + defer span.End() + + return t.iterateInfo(ctx, 0, []string{t.RootPath}, handler) +} + +func (t *FSTree) iterateInfo(ctx context.Context, depth uint64, curPath []string, handler IterateInfoHandler) error { + curName := strings.Join(curPath[1:], "") + dirPath := filepath.Join(curPath...) + entries, err := os.ReadDir(dirPath) + if err != nil { + return fmt.Errorf("read fstree dir '%s': %w", dirPath, err) + } + + isLast := depth >= t.Depth + l := len(curPath) + curPath = append(curPath, "") + + for i := range entries { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + curPath[l] = entries[i].Name() + + if !isLast && entries[i].IsDir() { + err := t.iterateInfo(ctx, depth+1, curPath, handler) + if err != nil { + return err + } + } + + if depth != t.Depth { + continue + } + + addr, err := addressFromString(curName + entries[i].Name()) + if err != nil { + continue + } + info, err := entries[i].Info() + if err != nil { + if os.IsNotExist(err) { + continue + } + return err + } + + err = handler(ObjectInfo{ + Address: addr, + DataSize: uint64(info.Size()), + }) + if err != nil { + return err + } + } + + return nil +} + func (t *FSTree) treePath(addr oid.Address) string { sAddr := stringifyAddress(addr) diff --git a/pkg/local_object_storage/blobstor/fstree/metrics.go b/pkg/local_object_storage/blobstor/fstree/metrics.go index 10de935eb1..4241beec97 100644 --- a/pkg/local_object_storage/blobstor/fstree/metrics.go +++ b/pkg/local_object_storage/blobstor/fstree/metrics.go @@ -13,6 +13,7 @@ type Metrics interface { Close() Iterate(d time.Duration, success bool) + IterateInfo(d time.Duration, success bool) Delete(d time.Duration, success bool) Exists(d time.Duration, success bool) Put(d time.Duration, size int, success bool) @@ -27,6 +28,7 @@ func (m *noopMetrics) SetParentID(string) {} func (m *noopMetrics) SetMode(mode.ComponentMode) {} func (m *noopMetrics) Close() {} func (m *noopMetrics) Iterate(time.Duration, bool) {} +func (m *noopMetrics) IterateInfo(time.Duration, bool) {} func (m *noopMetrics) Delete(time.Duration, bool) {} func (m *noopMetrics) Exists(time.Duration, bool) {} func (m *noopMetrics) Put(time.Duration, int, bool) {} diff --git a/pkg/local_object_storage/metrics/fstree.go b/pkg/local_object_storage/metrics/fstree.go index 76822ac2c9..d93363fa3b 100644 --- a/pkg/local_object_storage/metrics/fstree.go +++ b/pkg/local_object_storage/metrics/fstree.go @@ -38,6 +38,10 @@ func (m *fstreeMetrics) Iterate(d time.Duration, success bool) { m.m.MethodDuration(m.shardID, m.path, "Iterate", d, success) } +func (m *fstreeMetrics) IterateInfo(d time.Duration, success bool) { + m.m.MethodDuration(m.shardID, m.path, "IterateInfo", d, success) +} + func (m *fstreeMetrics) Delete(d time.Duration, success bool) { m.m.MethodDuration(m.shardID, m.path, "Delete", d, success) } From 8a6e3025a07d9c4d80a6252f4ee8bb0e0aa2021d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Sep 2024 11:49:17 +0300 Subject: [PATCH 0807/1413] [#1367] writecache: Flush from FSTree concurrently Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 + pkg/local_object_storage/writecache/cache.go | 7 +-- pkg/local_object_storage/writecache/flush.go | 65 +++++++++++++++++--- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 87e4e0b43b..7aef6873ec 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -544,4 +544,5 @@ const ( FailedToSealWritecacheAsync = "failed to seal writecache async" WritecacheShrinkSkippedNotEmpty = "writecache shrink skipped: not empty" BlobovniczatreeFailedToRemoveRebuildTempFile = "failed to remove rebuild temp file" + WritecacheCantGetObject = "can't get an object from fstree" ) diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index f2280f2f46..b298f812a5 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -10,7 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.uber.org/zap" ) @@ -37,9 +37,8 @@ type cache struct { const wcStorageType = "write-cache" type objectInfo struct { - addr string - data []byte - obj *objectSDK.Object + addr oid.Address + size uint64 } const ( diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 074756e329..d06896ed56 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -13,10 +13,12 @@ import ( objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -29,7 +31,7 @@ const ( // defaultFlushWorkersCount is number of workers for putting objects in main storage. defaultFlushWorkersCount = 20 // defaultFlushInterval is default time interval between successive flushes. - defaultFlushInterval = time.Second + defaultFlushInterval = 10 * time.Second ) var errIterationCompleted = errors.New("iteration completed") @@ -41,23 +43,41 @@ func (c *cache) runFlushLoop(ctx context.Context) { } c.wg.Add(1) go func() { - c.workerFlushBig(ctx) - c.wg.Done() + defer c.wg.Done() + c.pushToFlushQueue(ctx) }() + + for range c.workersCount { + c.wg.Add(1) + go c.workerFlush(ctx) + } } -func (c *cache) workerFlushBig(ctx context.Context) { - tick := time.NewTicker(defaultFlushInterval * 10) +func (c *cache) pushToFlushQueue(ctx context.Context) { + tick := time.NewTicker(defaultFlushInterval) for { select { case <-tick.C: c.modeMtx.RLock() if c.readOnly() || c.noMetabase() { c.modeMtx.RUnlock() - break + continue } - _ = c.flushFSTree(ctx, true) + err := c.fsTree.IterateInfo(ctx, func(oi fstree.ObjectInfo) error { + select { + case c.flushCh <- objectInfo{ + addr: oi.Address, + size: oi.DataSize, + }: + return nil + case <-ctx.Done(): + return ctx.Err() + } + }) + if err != nil { + c.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, zap.Error(err)) + } c.modeMtx.RUnlock() case <-ctx.Done(): @@ -66,6 +86,37 @@ func (c *cache) workerFlushBig(ctx context.Context) { } } +func (c *cache) workerFlush(ctx context.Context) { + defer c.wg.Done() + + var objInfo objectInfo + for { + select { + case objInfo = <-c.flushCh: + case <-ctx.Done(): + return + } + + res, err := c.fsTree.Get(ctx, common.GetPrm{ + Address: objInfo.addr, + }) + if err != nil { + if !errors.As(err, new(*apistatus.ObjectNotFound)) { + c.reportFlushError(logs.WritecacheCantGetObject, objInfo.addr.EncodeToString(), metaerr.Wrap(err)) + } + continue + } + + err = c.flushObject(ctx, res.Object, res.RawData, StorageTypeFSTree) + if err != nil { + // Error is handled in flushObject. + continue + } + + c.deleteFromDisk(ctx, objInfo.addr) + } +} + func (c *cache) reportFlushError(msg string, addr string, err error) { if c.reportError != nil { c.reportError(msg, err) From e39378b1c36d0d00864c4f5e7fcab44975ce506d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Sep 2024 12:56:29 +0300 Subject: [PATCH 0808/1413] [#1367] writecache: Add background flushing objects limiter To limit memory usage by background flush. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 + cmd/frostfs-node/config/engine/config_test.go | 2 + .../config/engine/shard/writecache/config.go | 18 +++++ config/example/node.env | 1 + config/example/node.json | 3 +- config/example/node.yaml | 1 + docs/storage-node-configuration.md | 23 +++--- pkg/local_object_storage/writecache/cache.go | 1 + pkg/local_object_storage/writecache/flush.go | 61 ++++++++++------ .../writecache/limiter.go | 70 +++++++++++++++++++ .../writecache/limiter_test.go | 27 +++++++ .../writecache/options.go | 9 +++ 12 files changed, 184 insertions(+), 35 deletions(-) create mode 100644 pkg/local_object_storage/writecache/limiter.go create mode 100644 pkg/local_object_storage/writecache/limiter_test.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 16f49a0820..ef27528722 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -154,6 +154,7 @@ type shardCfg struct { countLimit uint64 noSync bool pageSize int + flushSizeLimit uint64 } piloramaCfg struct { @@ -278,6 +279,7 @@ func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, wc.sizeLimit = writeCacheCfg.SizeLimit() wc.countLimit = writeCacheCfg.CountLimit() wc.noSync = writeCacheCfg.NoSync() + wc.flushSizeLimit = writeCacheCfg.MaxFlushingObjectsSize() } } @@ -865,6 +867,7 @@ func (c *cfg) getWriteCacheOpts(shCfg shardCfg) []writecache.Option { writecache.WithMaxBatchSize(wcRead.maxBatchSize), writecache.WithMaxBatchDelay(wcRead.maxBatchDelay), writecache.WithPageSize(wcRead.pageSize), + writecache.WithFlushSizeLimit(wcRead.flushSizeLimit), writecache.WithMaxObjectSize(wcRead.maxObjSize), writecache.WithSmallObjectSize(wcRead.smallObjectSize), writecache.WithFlushWorkersCount(wcRead.flushWorkerCount), diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index ef6bf7f743..b952aca4c1 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -79,6 +79,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 3221225472, wc.SizeLimit()) require.EqualValues(t, 4096, wc.BoltDB().PageSize()) require.EqualValues(t, 49, wc.CountLimit()) + require.EqualValues(t, uint64(100), wc.MaxFlushingObjectsSize()) require.Equal(t, "tmp/0/meta", meta.Path()) require.Equal(t, fs.FileMode(0o644), meta.BoltDB().Perm()) @@ -136,6 +137,7 @@ func TestEngineSection(t *testing.T) { require.EqualValues(t, 4294967296, wc.SizeLimit()) require.EqualValues(t, 0, wc.BoltDB().PageSize()) require.EqualValues(t, writecacheconfig.CountLimitDefault, wc.CountLimit()) + require.EqualValues(t, writecacheconfig.MaxFlushingObjectsSizeDefault, wc.MaxFlushingObjectsSize()) require.Equal(t, "tmp/1/meta", meta.Path()) require.Equal(t, fs.FileMode(0o644), meta.BoltDB().Perm()) diff --git a/cmd/frostfs-node/config/engine/shard/writecache/config.go b/cmd/frostfs-node/config/engine/shard/writecache/config.go index bfe8144dfb..5a069e99f7 100644 --- a/cmd/frostfs-node/config/engine/shard/writecache/config.go +++ b/cmd/frostfs-node/config/engine/shard/writecache/config.go @@ -24,6 +24,8 @@ const ( // CountLimitDefault is a default write-cache count limit. CountLimitDefault = 0 + + MaxFlushingObjectsSizeDefault = 128 << 20 ) // From wraps config section into Config. @@ -145,3 +147,19 @@ func (x *Config) NoSync() bool { func (x *Config) BoltDB() *boltdbconfig.Config { return (*boltdbconfig.Config)(x) } + +// MaxFlushingObjectsSize returns the value of "max_flushing_objects_size" config parameter. +// +// Returns MaxFlushingObjectsSizeDefault if the value is not a positive number. +func (x *Config) MaxFlushingObjectsSize() uint64 { + s := config.SizeInBytesSafe( + (*config.Config)(x), + "max_flushing_objects_size", + ) + + if s > 0 { + return s + } + + return MaxFlushingObjectsSizeDefault +} diff --git a/config/example/node.env b/config/example/node.env index 82553745e5..c3fa85c138 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -106,6 +106,7 @@ FROSTFS_STORAGE_SHARD_0_WRITECACHE_FLUSH_WORKER_COUNT=30 FROSTFS_STORAGE_SHARD_0_WRITECACHE_CAPACITY=3221225472 FROSTFS_STORAGE_SHARD_0_WRITECACHE_PAGE_SIZE=4096 FROSTFS_STORAGE_SHARD_0_WRITECACHE_MAX_OBJECT_COUNT=49 +FROSTFS_STORAGE_SHARD_0_WRITECACHE_MAX_FLUSHING_OBJECTS_SIZE=100 ### Metabase config FROSTFS_STORAGE_SHARD_0_METABASE_PATH=tmp/0/meta FROSTFS_STORAGE_SHARD_0_METABASE_PERM=0644 diff --git a/config/example/node.json b/config/example/node.json index da108c6927..d7187250be 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -149,7 +149,8 @@ "flush_worker_count": 30, "capacity": 3221225472, "page_size": 4096, - "max_object_count": 49 + "max_object_count": 49, + "max_flushing_objects_size": 100 }, "metabase": { "path": "tmp/0/meta", diff --git a/config/example/node.yaml b/config/example/node.yaml index a79f482265..776b22bd08 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -172,6 +172,7 @@ storage: capacity: 3221225472 # approximate write-cache total size, bytes max_object_count: 49 page_size: 4k + max_flushing_objects_size: 100b metabase: path: tmp/0/meta # metabase path diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 5bf35cd657..c838289787 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -293,17 +293,18 @@ writecache: page_size: '4k' ``` -| Parameter | Type | Default value | Description | -|----------------------|------------|---------------|-------------------------------------------------------------------------------------------------------------------------------| -| `path` | `string` | | Path to the metabase file. | -| `capacity` | `size` | `1G` | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | -| `max_object_count` | `int` | unrestricted | Approximate maximum objects count in the writecache. If the writecache is full, objects are written to the blobstor directly. | -| `small_object_size` | `size` | `32K` | Maximum object size for "small" objects. This objects are stored in a key-value database instead of a file-system. | -| `max_object_size` | `size` | `64M` | Maximum object size allowed to be stored in the writecache. | -| `flush_worker_count` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | -| `max_batch_size` | `int` | `1000` | Maximum amount of small object `PUT` operations to perform in a single transaction. | -| `max_batch_delay` | `duration` | `10ms` | Maximum delay before a batch starts. | -| `page_size` | `size` | `0` | Page size overrides the default OS page size for small objects storage. Does not affect the existing storage. | +| Parameter | Type | Default value | Description | +| --------------------------- | ---------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `path` | `string` | | Path to the metabase file. | +| `capacity` | `size` | `1G` | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | +| `max_object_count` | `int` | unrestricted | Approximate maximum objects count in the writecache. If the writecache is full, objects are written to the blobstor directly. | +| `small_object_size` | `size` | `32K` | Maximum object size for "small" objects. This objects are stored in a key-value database instead of a file-system. | +| `max_object_size` | `size` | `64M` | Maximum object size allowed to be stored in the writecache. | +| `flush_worker_count` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | +| `max_flushing_objects_size` | `size` | `512M` | Max total size of background flushing objects. | +| `max_batch_size` | `int` | `1000` | Maximum amount of small object `PUT` operations to perform in a single transaction. | +| `max_batch_delay` | `duration` | `10ms` | Maximum delay before a batch starts. | +| `page_size` | `size` | `0` | Page size overrides the default OS page size for small objects storage. Does not affect the existing storage. | # `node` section diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index b298f812a5..f0f10d8b51 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -68,6 +68,7 @@ func New(opts ...Option) Cache { maxBatchSize: bbolt.DefaultMaxBatchSize, maxBatchDelay: bbolt.DefaultMaxBatchDelay, metrics: DefaultMetrics(), + flushSizeLimit: defaultFlushWorkersCount * defaultMaxObjectSize, }, } diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index d06896ed56..5d5fc13abf 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -18,7 +18,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -41,19 +41,25 @@ func (c *cache) runFlushLoop(ctx context.Context) { if c.disableBackgroundFlush { return } + fl := newFlushLimiter(c.flushSizeLimit) c.wg.Add(1) go func() { defer c.wg.Done() - c.pushToFlushQueue(ctx) + c.pushToFlushQueue(ctx, fl) }() for range c.workersCount { c.wg.Add(1) - go c.workerFlush(ctx) + go c.workerFlush(ctx, fl) } } -func (c *cache) pushToFlushQueue(ctx context.Context) { +func (c *cache) pushToFlushQueue(ctx context.Context, fl *flushLimiter) { + stopf := context.AfterFunc(ctx, func() { + fl.close() + }) + defer stopf() + tick := time.NewTicker(defaultFlushInterval) for { select { @@ -65,6 +71,9 @@ func (c *cache) pushToFlushQueue(ctx context.Context) { } err := c.fsTree.IterateInfo(ctx, func(oi fstree.ObjectInfo) error { + if err := fl.acquire(oi.DataSize); err != nil { + return err + } select { case c.flushCh <- objectInfo{ addr: oi.Address, @@ -72,6 +81,7 @@ func (c *cache) pushToFlushQueue(ctx context.Context) { }: return nil case <-ctx.Done(): + fl.release(oi.DataSize) return ctx.Err() } }) @@ -86,37 +96,42 @@ func (c *cache) pushToFlushQueue(ctx context.Context) { } } -func (c *cache) workerFlush(ctx context.Context) { +func (c *cache) workerFlush(ctx context.Context, fl *flushLimiter) { defer c.wg.Done() var objInfo objectInfo for { select { case objInfo = <-c.flushCh: + c.flushIfAnObjectExistsWorker(ctx, objInfo, fl) case <-ctx.Done(): return } - - res, err := c.fsTree.Get(ctx, common.GetPrm{ - Address: objInfo.addr, - }) - if err != nil { - if !errors.As(err, new(*apistatus.ObjectNotFound)) { - c.reportFlushError(logs.WritecacheCantGetObject, objInfo.addr.EncodeToString(), metaerr.Wrap(err)) - } - continue - } - - err = c.flushObject(ctx, res.Object, res.RawData, StorageTypeFSTree) - if err != nil { - // Error is handled in flushObject. - continue - } - - c.deleteFromDisk(ctx, objInfo.addr) } } +func (c *cache) flushIfAnObjectExistsWorker(ctx context.Context, objInfo objectInfo, fl *flushLimiter) { + defer fl.release(objInfo.size) + + res, err := c.fsTree.Get(ctx, common.GetPrm{ + Address: objInfo.addr, + }) + if err != nil { + if !client.IsErrObjectNotFound(err) { + c.reportFlushError(logs.WritecacheCantGetObject, objInfo.addr.EncodeToString(), metaerr.Wrap(err)) + } + return + } + + err = c.flushObject(ctx, res.Object, res.RawData, StorageTypeFSTree) + if err != nil { + // Error is handled in flushObject. + return + } + + c.deleteFromDisk(ctx, objInfo.addr) +} + func (c *cache) reportFlushError(msg string, addr string, err error) { if c.reportError != nil { c.reportError(msg, err) diff --git a/pkg/local_object_storage/writecache/limiter.go b/pkg/local_object_storage/writecache/limiter.go new file mode 100644 index 0000000000..ddc4101be1 --- /dev/null +++ b/pkg/local_object_storage/writecache/limiter.go @@ -0,0 +1,70 @@ +package writecache + +import ( + "errors" + "sync" +) + +var errLimiterClosed = errors.New("acquire failed: limiter closed") + +// flushLimiter is used to limit the total size of objects +// being flushed to blobstore at the same time. This is a necessary +// limitation so that the flushing process does not have +// a strong impact on user requests. +type flushLimiter struct { + count, size uint64 + maxSize uint64 + cond *sync.Cond + closed bool +} + +func newFlushLimiter(maxSize uint64) *flushLimiter { + return &flushLimiter{ + maxSize: maxSize, + cond: sync.NewCond(&sync.Mutex{}), + } +} + +func (l *flushLimiter) acquire(size uint64) error { + l.cond.L.Lock() + defer l.cond.L.Unlock() + + // it is allowed to overflow maxSize to allow flushing objects with size > maxSize + for l.count > 0 && l.size+size > l.maxSize && !l.closed { + l.cond.Wait() + if l.closed { + return errLimiterClosed + } + } + l.count++ + l.size += size + return nil +} + +func (l *flushLimiter) release(size uint64) { + l.cond.L.Lock() + defer l.cond.L.Unlock() + + if l.size >= size { + l.size -= size + } else { + panic("flushLimiter: invalid size") + } + + if l.count > 0 { + l.count-- + } else { + panic("flushLimiter: invalid count") + } + + l.cond.Broadcast() +} + +func (l *flushLimiter) close() { + l.cond.L.Lock() + defer l.cond.L.Unlock() + + l.closed = true + + l.cond.Broadcast() +} diff --git a/pkg/local_object_storage/writecache/limiter_test.go b/pkg/local_object_storage/writecache/limiter_test.go new file mode 100644 index 0000000000..db99b203a6 --- /dev/null +++ b/pkg/local_object_storage/writecache/limiter_test.go @@ -0,0 +1,27 @@ +package writecache + +import ( + "sync/atomic" + "testing" + + "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" +) + +func TestLimiter(t *testing.T) { + var maxSize uint64 = 10 + var single uint64 = 3 + l := newFlushLimiter(uint64(maxSize)) + var currSize atomic.Int64 + var eg errgroup.Group + for i := 0; i < 10_000; i++ { + eg.Go(func() error { + defer l.release(single) + defer currSize.Add(-1) + l.acquire(single) + require.True(t, currSize.Add(1) <= 3) + return nil + }) + } + require.NoError(t, eg.Wait()) +} diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index 0643faac0b..edbb3d4228 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -44,6 +44,8 @@ type options struct { disableBackgroundFlush bool // pageSize is bbolt's page size config value pageSize int + // flushSizeLimit is total size of flushing objects. + flushSizeLimit uint64 } // WithLogger sets logger. @@ -169,3 +171,10 @@ func WithPageSize(s int) Option { o.pageSize = s } } + +// WithFlushSizeLimit sets flush size limit. +func WithFlushSizeLimit(v uint64) Option { + return func(o *options) { + o.flushSizeLimit = v + } +} From 25d2ae8aaf22c12e9e625b0433f84a49f5f22b39 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Sep 2024 13:12:17 +0300 Subject: [PATCH 0809/1413] [#1367] writecache: Drop BBolt related config variables Signed-off-by: Dmitrii Stepanov --- .../internal/writecache/inspect.go | 2 +- cmd/frostfs-lens/internal/writecache/list.go | 2 +- cmd/frostfs-node/config.go | 12 ----- cmd/frostfs-node/config/engine/config_test.go | 4 -- .../config/engine/shard/writecache/config.go | 25 ----------- docs/storage-node-configuration.md | 6 --- .../writecache/benchmark/writecache_test.go | 1 - pkg/local_object_storage/writecache/cache.go | 21 ++++----- pkg/local_object_storage/writecache/flush.go | 2 +- .../writecache/flush_test.go | 13 +++--- .../writecache/options.go | 44 ------------------- pkg/local_object_storage/writecache/util.go | 3 +- 12 files changed, 17 insertions(+), 118 deletions(-) diff --git a/cmd/frostfs-lens/internal/writecache/inspect.go b/cmd/frostfs-lens/internal/writecache/inspect.go index 63c669a355..afc986c8b9 100644 --- a/cmd/frostfs-lens/internal/writecache/inspect.go +++ b/cmd/frostfs-lens/internal/writecache/inspect.go @@ -25,7 +25,7 @@ func init() { func inspectFunc(cmd *cobra.Command, _ []string) { var data []byte - db, err := writecache.OpenDB(vPath, true, os.OpenFile, 0) + db, err := writecache.OpenDB(vPath, true, os.OpenFile) common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) defer db.Close() diff --git a/cmd/frostfs-lens/internal/writecache/list.go b/cmd/frostfs-lens/internal/writecache/list.go index 9c8fa6138a..bcbae0ec9b 100644 --- a/cmd/frostfs-lens/internal/writecache/list.go +++ b/cmd/frostfs-lens/internal/writecache/list.go @@ -31,7 +31,7 @@ func listFunc(cmd *cobra.Command, _ []string) { return err } - db, err := writecache.OpenDB(vPath, true, os.OpenFile, 0) + db, err := writecache.OpenDB(vPath, true, os.OpenFile) common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) defer db.Close() diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index ef27528722..cdfabdebd3 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -145,15 +145,11 @@ type shardCfg struct { writecacheCfg struct { enabled bool path string - maxBatchSize int - maxBatchDelay time.Duration - smallObjectSize uint64 maxObjSize uint64 flushWorkerCount int sizeLimit uint64 countLimit uint64 noSync bool - pageSize int flushSizeLimit uint64 } @@ -270,11 +266,7 @@ func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, wc.enabled = true wc.path = writeCacheCfg.Path() - wc.maxBatchSize = writeCacheCfg.BoltDB().MaxBatchSize() - wc.maxBatchDelay = writeCacheCfg.BoltDB().MaxBatchDelay() - wc.pageSize = writeCacheCfg.BoltDB().PageSize() wc.maxObjSize = writeCacheCfg.MaxObjectSize() - wc.smallObjectSize = writeCacheCfg.SmallObjectSize() wc.flushWorkerCount = writeCacheCfg.WorkerCount() wc.sizeLimit = writeCacheCfg.SizeLimit() wc.countLimit = writeCacheCfg.CountLimit() @@ -864,12 +856,8 @@ func (c *cfg) getWriteCacheOpts(shCfg shardCfg) []writecache.Option { if wcRead := shCfg.writecacheCfg; wcRead.enabled { writeCacheOpts = append(writeCacheOpts, writecache.WithPath(wcRead.path), - writecache.WithMaxBatchSize(wcRead.maxBatchSize), - writecache.WithMaxBatchDelay(wcRead.maxBatchDelay), - writecache.WithPageSize(wcRead.pageSize), writecache.WithFlushSizeLimit(wcRead.flushSizeLimit), writecache.WithMaxObjectSize(wcRead.maxObjSize), - writecache.WithSmallObjectSize(wcRead.smallObjectSize), writecache.WithFlushWorkersCount(wcRead.flushWorkerCount), writecache.WithMaxCacheSize(wcRead.sizeLimit), writecache.WithMaxCacheCount(wcRead.countLimit), diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index b952aca4c1..19ad0e7ac0 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -73,11 +73,9 @@ func TestEngineSection(t *testing.T) { require.Equal(t, true, wc.NoSync()) require.Equal(t, "tmp/0/cache", wc.Path()) - require.EqualValues(t, 16384, wc.SmallObjectSize()) require.EqualValues(t, 134217728, wc.MaxObjectSize()) require.EqualValues(t, 30, wc.WorkerCount()) require.EqualValues(t, 3221225472, wc.SizeLimit()) - require.EqualValues(t, 4096, wc.BoltDB().PageSize()) require.EqualValues(t, 49, wc.CountLimit()) require.EqualValues(t, uint64(100), wc.MaxFlushingObjectsSize()) @@ -131,11 +129,9 @@ func TestEngineSection(t *testing.T) { require.Equal(t, false, wc.NoSync()) require.Equal(t, "tmp/1/cache", wc.Path()) - require.EqualValues(t, 16384, wc.SmallObjectSize()) require.EqualValues(t, 134217728, wc.MaxObjectSize()) require.EqualValues(t, 30, wc.WorkerCount()) require.EqualValues(t, 4294967296, wc.SizeLimit()) - require.EqualValues(t, 0, wc.BoltDB().PageSize()) require.EqualValues(t, writecacheconfig.CountLimitDefault, wc.CountLimit()) require.EqualValues(t, writecacheconfig.MaxFlushingObjectsSizeDefault, wc.MaxFlushingObjectsSize()) diff --git a/cmd/frostfs-node/config/engine/shard/writecache/config.go b/cmd/frostfs-node/config/engine/shard/writecache/config.go index 5a069e99f7..6fff0308bb 100644 --- a/cmd/frostfs-node/config/engine/shard/writecache/config.go +++ b/cmd/frostfs-node/config/engine/shard/writecache/config.go @@ -2,7 +2,6 @@ package writecacheconfig import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" - boltdbconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/boltdb" ) // Config is a wrapper over the config section @@ -10,9 +9,6 @@ import ( type Config config.Config const ( - // SmallSizeDefault is a default size of small objects. - SmallSizeDefault = 32 << 10 - // MaxSizeDefault is a default value of the object payload size limit. MaxSizeDefault = 64 << 20 @@ -56,22 +52,6 @@ func (x *Config) Path() string { return p } -// SmallObjectSize returns the value of "small_object_size" config parameter. -// -// Returns SmallSizeDefault if the value is not a positive number. -func (x *Config) SmallObjectSize() uint64 { - s := config.SizeInBytesSafe( - (*config.Config)(x), - "small_object_size", - ) - - if s > 0 { - return s - } - - return SmallSizeDefault -} - // MaxObjectSize returns the value of "max_object_size" config parameter. // // Returns MaxSizeDefault if the value is not a positive number. @@ -143,11 +123,6 @@ func (x *Config) NoSync() bool { return config.BoolSafe((*config.Config)(x), "no_sync") } -// BoltDB returns config instance for querying bolt db specific parameters. -func (x *Config) BoltDB() *boltdbconfig.Config { - return (*boltdbconfig.Config)(x) -} - // MaxFlushingObjectsSize returns the value of "max_flushing_objects_size" config parameter. // // Returns MaxFlushingObjectsSizeDefault if the value is not a positive number. diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index c838289787..c74695e2b6 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -287,10 +287,8 @@ writecache: enabled: true path: /path/to/writecache capacity: 4294967296 - small_object_size: 16384 max_object_size: 134217728 flush_worker_count: 30 - page_size: '4k' ``` | Parameter | Type | Default value | Description | @@ -298,13 +296,9 @@ writecache: | `path` | `string` | | Path to the metabase file. | | `capacity` | `size` | `1G` | Approximate maximum size of the writecache. If the writecache is full, objects are written to the blobstor directly. | | `max_object_count` | `int` | unrestricted | Approximate maximum objects count in the writecache. If the writecache is full, objects are written to the blobstor directly. | -| `small_object_size` | `size` | `32K` | Maximum object size for "small" objects. This objects are stored in a key-value database instead of a file-system. | | `max_object_size` | `size` | `64M` | Maximum object size allowed to be stored in the writecache. | | `flush_worker_count` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | | `max_flushing_objects_size` | `size` | `512M` | Max total size of background flushing objects. | -| `max_batch_size` | `int` | `1000` | Maximum amount of small object `PUT` operations to perform in a single transaction. | -| `max_batch_delay` | `duration` | `10ms` | Maximum delay before a batch starts. | -| `page_size` | `size` | `0` | Page size overrides the default OS page size for small objects storage. Does not affect the existing storage. | # `node` section diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index 4da9a26d76..79ab7d9c6b 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -118,6 +118,5 @@ func newCache(b *testing.B) writecache.Cache { writecache.WithBlobstor(bs), writecache.WithMetabase(testMetabase{}), writecache.WithMaxCacheSize(256<<30), - writecache.WithSmallObjectSize(128<<10), ) } diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index f0f10d8b51..341071dc63 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -11,7 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.etcd.io/bbolt" "go.uber.org/zap" ) @@ -42,9 +41,8 @@ type objectInfo struct { } const ( - defaultMaxObjectSize = 64 * 1024 * 1024 // 64 MiB - defaultSmallObjectSize = 32 * 1024 // 32 KiB - defaultMaxCacheSize = 1 << 30 // 1 GiB + defaultMaxObjectSize = 64 * 1024 * 1024 // 64 MiB + defaultMaxCacheSize = 1 << 30 // 1 GiB ) var ( @@ -60,15 +58,12 @@ func New(opts ...Option) Cache { counter: fstree.NewSimpleCounter(), options: options{ - log: &logger.Logger{Logger: zap.NewNop()}, - maxObjectSize: defaultMaxObjectSize, - smallObjectSize: defaultSmallObjectSize, - workersCount: defaultFlushWorkersCount, - maxCacheSize: defaultMaxCacheSize, - maxBatchSize: bbolt.DefaultMaxBatchSize, - maxBatchDelay: bbolt.DefaultMaxBatchDelay, - metrics: DefaultMetrics(), - flushSizeLimit: defaultFlushWorkersCount * defaultMaxObjectSize, + log: &logger.Logger{Logger: zap.NewNop()}, + maxObjectSize: defaultMaxObjectSize, + workersCount: defaultFlushWorkersCount, + maxCacheSize: defaultMaxCacheSize, + metrics: DefaultMetrics(), + flushSizeLimit: defaultFlushWorkersCount * defaultMaxObjectSize, }, } diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 5d5fc13abf..10e4d68f0b 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -253,7 +253,7 @@ func (c *cache) flushAndDropBBoltDB(ctx context.Context) error { if err != nil { return fmt.Errorf("could not check write-cache database existence: %w", err) } - db, err := OpenDB(c.path, true, os.OpenFile, c.pageSize) + db, err := OpenDB(c.path, true, os.OpenFile) if err != nil { return fmt.Errorf("could not open write-cache database: %w", err) } diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index 9c7e240e07..59a4e4895d 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -25,12 +25,11 @@ import ( func TestFlush(t *testing.T) { testlogger := test.NewLogger(t) - createCacheFn := func(t *testing.T, smallSize uint64, mb *meta.DB, bs MainStorage, opts ...Option) Cache { + createCacheFn := func(t *testing.T, mb *meta.DB, bs MainStorage, opts ...Option) Cache { return New( append([]Option{ WithLogger(testlogger), WithPath(filepath.Join(t.TempDir(), "writecache")), - WithSmallObjectSize(smallSize), WithMetabase(mb), WithBlobstor(bs), WithDisableBackgroundFlush(), @@ -92,7 +91,6 @@ const ( type CreateCacheFunc[Option any] func( t *testing.T, - smallSize uint64, meta *meta.DB, bs MainStorage, opts ...Option, @@ -115,7 +113,7 @@ func runFlushTest[Option any]( failures ...TestFailureInjector[Option], ) { t.Run("no errors", func(t *testing.T) { - wc, bs, mb := newCache(t, createCacheFn, smallSize) + wc, bs, mb := newCache(t, createCacheFn) defer func() { require.NoError(t, wc.Close()) }() objects := putObjects(t, wc) @@ -128,7 +126,7 @@ func runFlushTest[Option any]( }) t.Run("flush on moving to degraded mode", func(t *testing.T) { - wc, bs, mb := newCache(t, createCacheFn, smallSize) + wc, bs, mb := newCache(t, createCacheFn) defer func() { require.NoError(t, wc.Close()) }() objects := putObjects(t, wc) @@ -146,7 +144,7 @@ func runFlushTest[Option any]( for _, f := range failures { t.Run(f.Desc, func(t *testing.T) { errCountOpt, errCount := errCountOption() - wc, bs, mb := newCache(t, createCacheFn, smallSize, errCountOpt) + wc, bs, mb := newCache(t, createCacheFn, errCountOpt) defer func() { require.NoError(t, wc.Close()) }() objects := putObjects(t, wc) f.InjectFn(t, wc) @@ -168,7 +166,6 @@ func runFlushTest[Option any]( func newCache[Option any]( t *testing.T, createCacheFn CreateCacheFunc[Option], - smallSize uint64, opts ...Option, ) (Cache, *blobstor.BlobStor, *meta.DB) { dir := t.TempDir() @@ -189,7 +186,7 @@ func newCache[Option any]( require.NoError(t, bs.Open(context.Background(), mode.ReadWrite)) require.NoError(t, bs.Init()) - wc := createCacheFn(t, smallSize, mb, bs, opts...) + wc := createCacheFn(t, mb, bs, opts...) require.NoError(t, wc.Open(context.Background(), mode.ReadWrite)) require.NoError(t, wc.Init()) diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index edbb3d4228..66ac7805c8 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -1,8 +1,6 @@ package writecache import ( - "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) @@ -20,8 +18,6 @@ type options struct { metabase Metabase // maxObjectSize is the maximum size of the object stored in the write-cache. maxObjectSize uint64 - // smallObjectSize is the maximum size of the object stored in the database. - smallObjectSize uint64 // workersCount is the number of workers flushing objects in parallel. workersCount int // maxCacheSize is the maximum total size of all objects saved in cache (DB + FS). @@ -30,10 +26,6 @@ type options struct { // maxCacheCount is the maximum total count of all object saved in cache. // 0 (no limit) by default. maxCacheCount uint64 - // maxBatchSize is the maximum batch size for the small object database. - maxBatchSize int - // maxBatchDelay is the maximum batch wait time for the small object database. - maxBatchDelay time.Duration // noSync is true iff FSTree allows unsynchronized writes. noSync bool // reportError is the function called when encountering disk errors in background workers. @@ -42,8 +34,6 @@ type options struct { metrics Metrics // disableBackgroundFlush is for testing purposes only. disableBackgroundFlush bool - // pageSize is bbolt's page size config value - pageSize int // flushSizeLimit is total size of flushing objects. flushSizeLimit uint64 } @@ -85,15 +75,6 @@ func WithMaxObjectSize(sz uint64) Option { } } -// WithSmallObjectSize sets maximum object size to be stored in write-cache. -func WithSmallObjectSize(sz uint64) Option { - return func(o *options) { - if sz > 0 { - o.smallObjectSize = sz - } - } -} - func WithFlushWorkersCount(c int) Option { return func(o *options) { if c > 0 { @@ -116,24 +97,6 @@ func WithMaxCacheCount(v uint64) Option { } } -// WithMaxBatchSize sets max batch size for the small object database. -func WithMaxBatchSize(sz int) Option { - return func(o *options) { - if sz > 0 { - o.maxBatchSize = sz - } - } -} - -// WithMaxBatchDelay sets max batch delay for the small object database. -func WithMaxBatchDelay(d time.Duration) Option { - return func(o *options) { - if d > 0 { - o.maxBatchDelay = d - } - } -} - // WithNoSync sets an option to allow returning to caller on PUT before write is persisted. // Note, that we use this flag for FSTree only and DO NOT use it for a bolt DB because // we cannot yet properly handle the corrupted database during the startup. This SHOULD NOT @@ -165,13 +128,6 @@ func WithDisableBackgroundFlush() Option { } } -// WithPageSize sets bbolt's page size. -func WithPageSize(s int) Option { - return func(o *options) { - o.pageSize = s - } -} - // WithFlushSizeLimit sets flush size limit. func WithFlushSizeLimit(v uint64) Option { return func(o *options) { diff --git a/pkg/local_object_storage/writecache/util.go b/pkg/local_object_storage/writecache/util.go index ad3b443f33..0ed4a954e1 100644 --- a/pkg/local_object_storage/writecache/util.go +++ b/pkg/local_object_storage/writecache/util.go @@ -10,12 +10,11 @@ import ( ) // OpenDB opens BoltDB instance for write-cache. Opens in read-only mode if ro is true. -func OpenDB(p string, ro bool, openFile func(string, int, fs.FileMode) (*os.File, error), pageSize int) (*bbolt.DB, error) { +func OpenDB(p string, ro bool, openFile func(string, int, fs.FileMode) (*os.File, error)) (*bbolt.DB, error) { return bbolt.Open(filepath.Join(p, dbName), os.ModePerm, &bbolt.Options{ NoFreelistSync: true, ReadOnly: ro, Timeout: 100 * time.Millisecond, OpenFile: openFile, - PageSize: pageSize, }) } From 3b236160a61c8257aae5bd7078035838606650b7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 11 Sep 2024 09:55:08 +0300 Subject: [PATCH 0810/1413] [#1367] writecache: Drop DB label from metrics Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/writecache.go | 10 ++++------ pkg/local_object_storage/writecache/metrics.go | 8 ++++---- pkg/local_object_storage/writecache/state.go | 4 ++-- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/pkg/local_object_storage/engine/writecache.go b/pkg/local_object_storage/engine/writecache.go index 7710bc7f4c..e9ba3410f5 100644 --- a/pkg/local_object_storage/engine/writecache.go +++ b/pkg/local_object_storage/engine/writecache.go @@ -169,18 +169,16 @@ func (m *writeCacheMetrics) Put(d time.Duration, success bool, st writecache.Sto m.metrics.AddMethodDuration(m.shardID, m.path, st.String(), "Put", success, d) } -func (m *writeCacheMetrics) SetEstimateSize(db, fstree uint64) { - m.metrics.SetEstimateSize(m.shardID, m.path, writecache.StorageTypeDB.String(), db) - m.metrics.SetEstimateSize(m.shardID, m.path, writecache.StorageTypeFSTree.String(), fstree) +func (m *writeCacheMetrics) SetEstimateSize(size uint64) { + m.metrics.SetEstimateSize(m.shardID, m.path, writecache.StorageTypeFSTree.String(), size) } func (m *writeCacheMetrics) SetMode(mod mode.ComponentMode) { m.metrics.SetMode(m.shardID, mod.String()) } -func (m *writeCacheMetrics) SetActualCounters(db, fstree uint64) { - m.metrics.SetActualCount(m.shardID, m.path, writecache.StorageTypeDB.String(), db) - m.metrics.SetActualCount(m.shardID, m.path, writecache.StorageTypeFSTree.String(), fstree) +func (m *writeCacheMetrics) SetActualCounters(count uint64) { + m.metrics.SetActualCount(m.shardID, m.path, writecache.StorageTypeFSTree.String(), count) } func (m *writeCacheMetrics) Flush(success bool, st writecache.StorageType) { diff --git a/pkg/local_object_storage/writecache/metrics.go b/pkg/local_object_storage/writecache/metrics.go index e68b6d8bee..e3641f85e9 100644 --- a/pkg/local_object_storage/writecache/metrics.go +++ b/pkg/local_object_storage/writecache/metrics.go @@ -26,9 +26,9 @@ type Metrics interface { Flush(success bool, st StorageType) Evict(st StorageType) - SetEstimateSize(db, fstree uint64) + SetEstimateSize(uint64) SetMode(m mode.ComponentMode) - SetActualCounters(db, fstree uint64) + SetActualCounters(uint64) SetPath(path string) Close() } @@ -47,11 +47,11 @@ func (metricsStub) Delete(time.Duration, bool, StorageType) {} func (metricsStub) Put(time.Duration, bool, StorageType) {} -func (metricsStub) SetEstimateSize(uint64, uint64) {} +func (metricsStub) SetEstimateSize(uint64) {} func (metricsStub) SetMode(mode.ComponentMode) {} -func (metricsStub) SetActualCounters(uint64, uint64) {} +func (metricsStub) SetActualCounters(uint64) {} func (metricsStub) Flush(bool, StorageType) {} diff --git a/pkg/local_object_storage/writecache/state.go b/pkg/local_object_storage/writecache/state.go index 748c78bcba..835686fbbb 100644 --- a/pkg/local_object_storage/writecache/state.go +++ b/pkg/local_object_storage/writecache/state.go @@ -2,8 +2,8 @@ package writecache func (c *cache) estimateCacheSize() (uint64, uint64) { count, size := c.counter.CountSize() - c.metrics.SetEstimateSize(0, size) - c.metrics.SetActualCounters(0, count) + c.metrics.SetEstimateSize(size) + c.metrics.SetActualCounters(count) return count, size } From f345fe9a581762fcd5827719d1781e16ce133056 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 11 Sep 2024 17:08:52 +0300 Subject: [PATCH 0811/1413] [#1367] writecache: Move DB related code to upgrade.go This is done to drop this file in the future. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/writecache/cache.go | 5 +- pkg/local_object_storage/writecache/flush.go | 86 -------------- .../writecache/storage.go | 2 - .../writecache/upgrade.go | 110 ++++++++++++++++++ pkg/local_object_storage/writecache/util.go | 20 ---- 5 files changed, 111 insertions(+), 112 deletions(-) create mode 100644 pkg/local_object_storage/writecache/upgrade.go delete mode 100644 pkg/local_object_storage/writecache/util.go diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index 341071dc63..b97fc5856b 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -45,10 +45,7 @@ const ( defaultMaxCacheSize = 1 << 30 // 1 GiB ) -var ( - defaultBucket = []byte{0} - dummyCanceler context.CancelFunc = func() {} -) +var dummyCanceler context.CancelFunc = func() {} // New creates new writecache instance. func New(opts ...Option) Cache { diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 10e4d68f0b..83933375b6 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -1,12 +1,8 @@ package writecache import ( - "bytes" "context" "errors" - "fmt" - "os" - "path/filepath" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -20,8 +16,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" @@ -239,83 +233,3 @@ func (c *cache) Flush(ctx context.Context, ignoreErrors, seal bool) error { func (c *cache) flush(ctx context.Context, ignoreErrors bool) error { return c.flushFSTree(ctx, ignoreErrors) } - -type batchItem struct { - data []byte - address string -} - -func (c *cache) flushAndDropBBoltDB(ctx context.Context) error { - _, err := os.Stat(filepath.Join(c.path, dbName)) - if err != nil && os.IsNotExist(err) { - return nil - } - if err != nil { - return fmt.Errorf("could not check write-cache database existence: %w", err) - } - db, err := OpenDB(c.path, true, os.OpenFile) - if err != nil { - return fmt.Errorf("could not open write-cache database: %w", err) - } - defer func() { - _ = db.Close() - }() - - var last string - for { - batch, err := c.readNextDBBatch(db, last) - if err != nil { - return err - } - if len(batch) == 0 { - break - } - for _, item := range batch { - var obj objectSDK.Object - if err := obj.Unmarshal(item.data); err != nil { - return fmt.Errorf("unmarshal object from database: %w", err) - } - if err := c.flushObject(ctx, &obj, item.data, StorageTypeDB); err != nil { - return fmt.Errorf("flush object from database: %w", err) - } - } - last = batch[len(batch)-1].address - } - if err := db.Close(); err != nil { - return fmt.Errorf("close write-cache database: %w", err) - } - if err := os.Remove(filepath.Join(c.path, dbName)); err != nil { - return fmt.Errorf("remove write-cache database: %w", err) - } - return nil -} - -func (c *cache) readNextDBBatch(db *bbolt.DB, last string) ([]batchItem, error) { - const batchSize = 100 - var batch []batchItem - err := db.View(func(tx *bbolt.Tx) error { - var addr oid.Address - - b := tx.Bucket(defaultBucket) - cs := b.Cursor() - for k, data := cs.Seek([]byte(last)); k != nil; k, data = cs.Next() { - sa := string(k) - if sa == last { - continue - } - if err := addr.DecodeString(sa); err != nil { - return fmt.Errorf("decode address from database: %w", err) - } - - batch = append(batch, batchItem{data: bytes.Clone(data), address: sa}) - if len(batch) == batchSize { - return errIterationCompleted - } - } - return nil - }) - if err == nil || errors.Is(err, errIterationCompleted) { - return batch, nil - } - return nil, err -} diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index e708a529e1..6aface7a5f 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -16,8 +16,6 @@ import ( "go.uber.org/zap" ) -const dbName = "small.bolt" - func (c *cache) openStore(mod mode.ComponentMode) error { err := util.MkdirAllX(c.path, os.ModePerm) if err != nil { diff --git a/pkg/local_object_storage/writecache/upgrade.go b/pkg/local_object_storage/writecache/upgrade.go new file mode 100644 index 0000000000..3a100f1a31 --- /dev/null +++ b/pkg/local_object_storage/writecache/upgrade.go @@ -0,0 +1,110 @@ +package writecache + +import ( + "bytes" + "context" + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + "time" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.etcd.io/bbolt" +) + +const dbName = "small.bolt" + +var defaultBucket = []byte{0} + +func (c *cache) flushAndDropBBoltDB(ctx context.Context) error { + _, err := os.Stat(filepath.Join(c.path, dbName)) + if err != nil && os.IsNotExist(err) { + return nil + } + if err != nil { + return fmt.Errorf("could not check write-cache database existence: %w", err) + } + db, err := OpenDB(c.path, true, os.OpenFile) + if err != nil { + return fmt.Errorf("could not open write-cache database: %w", err) + } + defer func() { + _ = db.Close() + }() + + var last string + for { + batch, err := c.readNextDBBatch(db, last) + if err != nil { + return err + } + if len(batch) == 0 { + break + } + for _, item := range batch { + var obj objectSDK.Object + if err := obj.Unmarshal(item.data); err != nil { + return fmt.Errorf("unmarshal object from database: %w", err) + } + if err := c.flushObject(ctx, &obj, item.data, StorageTypeDB); err != nil { + return fmt.Errorf("flush object from database: %w", err) + } + } + last = batch[len(batch)-1].address + } + if err := db.Close(); err != nil { + return fmt.Errorf("close write-cache database: %w", err) + } + if err := os.Remove(filepath.Join(c.path, dbName)); err != nil { + return fmt.Errorf("remove write-cache database: %w", err) + } + return nil +} + +type batchItem struct { + data []byte + address string +} + +func (c *cache) readNextDBBatch(db *bbolt.DB, last string) ([]batchItem, error) { + const batchSize = 100 + var batch []batchItem + err := db.View(func(tx *bbolt.Tx) error { + var addr oid.Address + + b := tx.Bucket(defaultBucket) + cs := b.Cursor() + for k, data := cs.Seek([]byte(last)); k != nil; k, data = cs.Next() { + sa := string(k) + if sa == last { + continue + } + if err := addr.DecodeString(sa); err != nil { + return fmt.Errorf("decode address from database: %w", err) + } + + batch = append(batch, batchItem{data: bytes.Clone(data), address: sa}) + if len(batch) == batchSize { + return errIterationCompleted + } + } + return nil + }) + if err == nil || errors.Is(err, errIterationCompleted) { + return batch, nil + } + return nil, err +} + +// OpenDB opens BoltDB instance for write-cache. Opens in read-only mode if ro is true. +func OpenDB(p string, ro bool, openFile func(string, int, fs.FileMode) (*os.File, error)) (*bbolt.DB, error) { + return bbolt.Open(filepath.Join(p, dbName), os.ModePerm, &bbolt.Options{ + NoFreelistSync: true, + ReadOnly: ro, + Timeout: 100 * time.Millisecond, + OpenFile: openFile, + }) +} diff --git a/pkg/local_object_storage/writecache/util.go b/pkg/local_object_storage/writecache/util.go deleted file mode 100644 index 0ed4a954e1..0000000000 --- a/pkg/local_object_storage/writecache/util.go +++ /dev/null @@ -1,20 +0,0 @@ -package writecache - -import ( - "io/fs" - "os" - "path/filepath" - "time" - - "go.etcd.io/bbolt" -) - -// OpenDB opens BoltDB instance for write-cache. Opens in read-only mode if ro is true. -func OpenDB(p string, ro bool, openFile func(string, int, fs.FileMode) (*os.File, error)) (*bbolt.DB, error) { - return bbolt.Open(filepath.Join(p, dbName), os.ModePerm, &bbolt.Options{ - NoFreelistSync: true, - ReadOnly: ro, - Timeout: 100 * time.Millisecond, - OpenFile: openFile, - }) -} From b33559754df994c4e2e37f1b5b6c8f29ac8f97f1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 12 Sep 2024 12:33:12 +0300 Subject: [PATCH 0812/1413] [#1367] fstree: Add size hint for Delete This allow to not to call `os.Stat` if caller already knows data size. Signed-off-by: Dmitrii Stepanov --- .../blobstor/common/delete.go | 1 + .../blobstor/fstree/fstree.go | 2 +- .../blobstor/fstree/fstree_test.go | 84 +++++++++++++------ .../blobstor/fstree/fstree_write_generic.go | 19 +++-- .../blobstor/fstree/fstree_write_linux.go | 25 +++--- pkg/local_object_storage/writecache/flush.go | 4 +- .../writecache/storage.go | 4 +- 7 files changed, 92 insertions(+), 47 deletions(-) diff --git a/pkg/local_object_storage/blobstor/common/delete.go b/pkg/local_object_storage/blobstor/common/delete.go index 1b04eab1a1..c19e099cbd 100644 --- a/pkg/local_object_storage/blobstor/common/delete.go +++ b/pkg/local_object_storage/blobstor/common/delete.go @@ -8,6 +8,7 @@ import ( type DeletePrm struct { Address oid.Address StorageID []byte + Size uint64 } // DeleteRes groups the resulting values of Delete operation. diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 1c60ec340f..057796db24 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -338,7 +338,7 @@ func (t *FSTree) Delete(ctx context.Context, prm common.DeletePrm) (common.Delet } p := t.treePath(prm.Address) - err = t.writer.removeFile(p) + err = t.writer.removeFile(p, prm.Size) return common.DeleteRes{}, err } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_test.go b/pkg/local_object_storage/blobstor/fstree/fstree_test.go index f39c7296ef..eb2126b6c0 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_test.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_test.go @@ -68,34 +68,70 @@ func TestObjectCounter(t *testing.T) { var delPrm common.DeletePrm delPrm.Address = addr - eg, egCtx := errgroup.WithContext(context.Background()) + t.Run("without size hint", func(t *testing.T) { + eg, egCtx := errgroup.WithContext(context.Background()) - eg.Go(func() error { - for range 1_000 { - _, err := fst.Put(egCtx, putPrm) - if err != nil { - return err + eg.Go(func() error { + for range 1_000 { + _, err := fst.Put(egCtx, putPrm) + if err != nil { + return err + } } - } - return nil + return nil + }) + + eg.Go(func() error { + var le logicerr.Logical + for range 1_000 { + _, err := fst.Delete(egCtx, delPrm) + if err != nil && !errors.As(err, &le) { + return err + } + } + return nil + }) + + require.NoError(t, eg.Wait()) + + count, size = counter.CountSize() + realCount, realSize, err := fst.countFiles() + require.NoError(t, err) + require.Equal(t, realCount, count, "real %d, actual %d", realCount, count) + require.Equal(t, realSize, size, "real %d, actual %d", realSize, size) }) - eg.Go(func() error { - var le logicerr.Logical - for range 1_000 { - _, err := fst.Delete(egCtx, delPrm) - if err != nil && !errors.As(err, &le) { - return err + t.Run("with size hint", func(t *testing.T) { + delPrm.Size = uint64(len(putPrm.RawData)) + eg, egCtx := errgroup.WithContext(context.Background()) + + eg.Go(func() error { + for range 1_000 { + _, err := fst.Put(egCtx, putPrm) + if err != nil { + return err + } } - } - return nil + return nil + }) + + eg.Go(func() error { + var le logicerr.Logical + for range 1_000 { + _, err := fst.Delete(egCtx, delPrm) + if err != nil && !errors.As(err, &le) { + return err + } + } + return nil + }) + + require.NoError(t, eg.Wait()) + + count, size = counter.CountSize() + realCount, realSize, err := fst.countFiles() + require.NoError(t, err) + require.Equal(t, realCount, count, "real %d, actual %d", realCount, count) + require.Equal(t, realSize, size, "real %d, actual %d", realSize, size) }) - - require.NoError(t, eg.Wait()) - - count, size = counter.CountSize() - realCount, realSize, err := fst.countFiles() - require.NoError(t, err) - require.Equal(t, realCount, count, "real %d, actual %d", realCount, count) - require.Equal(t, realSize, size, "real %d, actual %d", realSize, size) } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 801fc4a22e..4110ba7d74 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -16,7 +16,7 @@ import ( type writer interface { writeData(string, []byte) error - removeFile(string) error + removeFile(string, uint64) error } type genericWriter struct { @@ -107,10 +107,10 @@ func (w *genericWriter) writeFile(p string, data []byte) error { return err } -func (w *genericWriter) removeFile(p string) error { +func (w *genericWriter) removeFile(p string, size uint64) error { var err error if w.fileCounterEnabled { - err = w.removeWithCounter(p) + err = w.removeWithCounter(p, size) } else { err = os.Remove(p) } @@ -121,18 +121,21 @@ func (w *genericWriter) removeFile(p string) error { return err } -func (w *genericWriter) removeWithCounter(p string) error { +func (w *genericWriter) removeWithCounter(p string, size uint64) error { w.fileGuard.Lock(p) defer w.fileGuard.Unlock(p) - stat, err := os.Stat(p) - if err != nil { - return err + if size == 0 { + stat, err := os.Stat(p) + if err != nil { + return err + } + size = uint64(stat.Size()) } if err := os.Remove(p); err != nil { return err } - w.fileCounter.Dec(uint64(stat.Size())) + w.fileCounter.Dec(uint64(size)) return nil } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index 3127579ac9..3561c616b8 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -91,25 +91,30 @@ func (w *linuxWriter) writeFile(p string, data []byte) error { return errClose } -func (w *linuxWriter) removeFile(p string) error { +func (w *linuxWriter) removeFile(p string, size uint64) error { if w.fileCounterEnabled { w.fileGuard.Lock(p) defer w.fileGuard.Unlock(p) - } - var stat unix.Stat_t - err := unix.Stat(p, &stat) - if err != nil { - if err == unix.ENOENT { - return logicerr.Wrap(new(apistatus.ObjectNotFound)) + + if size == 0 { + var stat unix.Stat_t + err := unix.Stat(p, &stat) + if err != nil { + if err == unix.ENOENT { + return logicerr.Wrap(new(apistatus.ObjectNotFound)) + } + return err + } + size = uint64(stat.Size) } - return err } - err = unix.Unlink(p) + + err := unix.Unlink(p) if err != nil && err == unix.ENOENT { return logicerr.Wrap(new(apistatus.ObjectNotFound)) } if err == nil { - w.fileCounter.Dec(uint64(stat.Size)) + w.fileCounter.Dec(uint64(size)) } return err } diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 83933375b6..bfa6aacb0f 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -123,7 +123,7 @@ func (c *cache) flushIfAnObjectExistsWorker(ctx context.Context, objInfo objectI return } - c.deleteFromDisk(ctx, objInfo.addr) + c.deleteFromDisk(ctx, objInfo.addr, uint64(len(res.RawData))) } func (c *cache) reportFlushError(msg string, addr string, err error) { @@ -157,7 +157,7 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { return err } - c.deleteFromDisk(ctx, e.Address) + c.deleteFromDisk(ctx, e.Address, uint64(len(e.ObjectData))) return nil } diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index 6aface7a5f..2e52e5b208 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -40,8 +40,8 @@ func (c *cache) openStore(mod mode.ComponentMode) error { return nil } -func (c *cache) deleteFromDisk(ctx context.Context, addr oid.Address) { - _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr}) +func (c *cache) deleteFromDisk(ctx context.Context, addr oid.Address, size uint64) { + _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr, Size: size}) if err != nil && !client.IsErrObjectNotFound(err) { c.log.Error(logs.WritecacheCantRemoveObjectFromWritecache, zap.Error(err)) } else if err == nil { From e3764c51df237289431eacd0051bb3754e7682cc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 12 Sep 2024 09:53:21 +0300 Subject: [PATCH 0813/1413] [#1347] metabase: Fix EC search For EC chunks need to return EC parent object ID as EC chunks don't have own attributes but inherit parent's. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/select.go | 21 +++++++++------ .../metabase/select_test.go | 27 +++++++++++++++++++ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 1863fc25e5..ed43fc41f9 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -150,7 +150,8 @@ func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters continue // ignore removed objects } - if !db.matchSlowFilters(tx, addr, group.slowFilters, currEpoch) { + addr, match := db.matchSlowFilters(tx, addr, group.slowFilters, currEpoch) + if !match { continue // ignore objects with unmatched slow filters } @@ -382,15 +383,16 @@ func (db *DB) selectObjectID( } // matchSlowFilters return true if object header is matched by all slow filters. -func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.SearchFilters, currEpoch uint64) bool { +func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.SearchFilters, currEpoch uint64) (oid.Address, bool) { + result := addr if len(f) == 0 { - return true + return result, true } buf := make([]byte, addressKeySize) obj, err := db.get(tx, addr, buf, true, false, currEpoch) if err != nil { - return false + return result, false } for i := range f { @@ -415,23 +417,26 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc default: // user attribute v, ok := attributeValue(obj, f[i].Header()) if ok { + if ech := obj.ECHeader(); ech != nil { + result.SetObject(ech.Parent()) + } data = []byte(v) } else { - return f[i].Operation() == objectSDK.MatchNotPresent + return result, f[i].Operation() == objectSDK.MatchNotPresent } } matchFunc, ok := db.matchers[f[i].Operation()] if !ok { - return false + return result, false } if !matchFunc.matchSlow(f[i].Header(), data, f[i].Value()) { - return false + return result, false } } - return true + return result, true } func attributeValue(obj *objectSDK.Object, attribute string) (string, bool) { diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 0fab3a1085..6469bbdbc0 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -70,6 +70,22 @@ func TestDB_SelectUserAttributes(t *testing.T) { err = putBig(db, raw6) require.NoError(t, err) + raw7 := testutil.GenerateObjectWithCID(cnr) + var attr objectSDK.Attribute + attr.SetKey("path") + attr.SetValue("test/3/4") + attrs := raw7.Attributes() + attrs = append(attrs, attr) + ech := objectSDK.NewECHeader(objectSDK.ECParentInfo{ + ID: oidtest.ID(), + Attributes: attrs, + }, 0, 3, []byte{}, 0) + raw7.SetECHeader(ech) + require.NoError(t, putBig(db, raw7)) + var raw7Parent oid.Address + raw7Parent.SetContainer(cnr) + raw7Parent.SetObject(ech.Parent()) + fs := objectSDK.SearchFilters{} fs.AddFilter("foo", "bar", objectSDK.MatchStringEqual) testSelect(t, db, cnr, fs, @@ -100,6 +116,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { object.AddressOf(raw4), object.AddressOf(raw5), object.AddressOf(raw6), + object.AddressOf(raw7), ) fs = objectSDK.SearchFilters{} @@ -110,6 +127,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { object.AddressOf(raw4), object.AddressOf(raw5), object.AddressOf(raw6), + object.AddressOf(raw7), ) fs = objectSDK.SearchFilters{} @@ -120,6 +138,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { object.AddressOf(raw4), object.AddressOf(raw5), object.AddressOf(raw6), + object.AddressOf(raw7), ) fs = objectSDK.SearchFilters{} @@ -131,6 +150,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { object.AddressOf(raw4), object.AddressOf(raw5), object.AddressOf(raw6), + object.AddressOf(raw7), ) fs = objectSDK.SearchFilters{} @@ -139,6 +159,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { object.AddressOf(raw4), object.AddressOf(raw5), object.AddressOf(raw6), + raw7Parent, ) fs = objectSDK.SearchFilters{} @@ -147,6 +168,12 @@ func TestDB_SelectUserAttributes(t *testing.T) { object.AddressOf(raw4), object.AddressOf(raw5), ) + + fs = objectSDK.SearchFilters{} + fs.AddFilter("path", "test/3/4", objectSDK.MatchStringEqual) + testSelect(t, db, cnr, fs, + raw7Parent, + ) } func TestDB_SelectRootPhyParent(t *testing.T) { From 546d09660f52d262c3c053b72457170f5c4b68e7 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 12 Sep 2024 17:05:14 +0300 Subject: [PATCH 0814/1413] [#1283] Clear systemd-notify status on exit Signed-off-by: Aleksey Savchuk --- cmd/frostfs-ir/main.go | 5 +++++ cmd/frostfs-node/config.go | 4 ++++ pkg/util/sdnotify/sdnotify.go | 5 +++++ 3 files changed, 14 insertions(+) diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 5b852c37ca..02936ae78c 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -13,6 +13,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" "github.com/spf13/viper" "go.uber.org/zap" ) @@ -124,4 +125,8 @@ func shutdown() { zap.String("error", err.Error()), ) } + + if err := sdnotify.ClearStatus(); err != nil { + log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) + } } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index cdfabdebd3..f98f1c1a31 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1398,4 +1398,8 @@ func (c *cfg) shutdown() { for i := range c.closers { c.closers[len(c.closers)-1-i].fn() } + + if err := sdnotify.ClearStatus(); err != nil { + c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) + } } diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go index 5235315cc9..e94ff77ad3 100644 --- a/pkg/util/sdnotify/sdnotify.go +++ b/pkg/util/sdnotify/sdnotify.go @@ -69,6 +69,11 @@ func Status(status string) error { return Send("STATUS=" + status) } +// ClearStatus resets the current service status previously set by Status. +func ClearStatus() error { + return Status("") +} + // Send state through the notify socket if any. // If the notify socket was not detected, it returns an error. func Send(state string) error { From bb448674918330ddd15df6462fbde860eca5bc64 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 13 Sep 2024 11:31:33 +0300 Subject: [PATCH 0815/1413] [#1374] go.mod: Upgrade grpc to v1.66.2 Signed-off-by: Dmitrii Stepanov --- go.mod | 14 +++++++------- go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 93eef5b8c8..78fefc9aee 100644 --- a/go.mod +++ b/go.mod @@ -46,9 +46,9 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/sync v0.7.0 golang.org/x/sys v0.22.0 - golang.org/x/term v0.18.0 - google.golang.org/grpc v1.63.2 - google.golang.org/protobuf v1.33.0 + golang.org/x/term v0.21.0 + google.golang.org/grpc v1.66.2 + google.golang.org/protobuf v1.34.1 gopkg.in/yaml.v3 v3.0.1 ) @@ -122,11 +122,11 @@ require ( go.opentelemetry.io/otel/sdk v1.22.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/net v0.23.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/net v0.26.0 // indirect golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 102501484d..2147f8988d 100644 --- a/go.sum +++ b/go.sum @@ -306,8 +306,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -327,8 +327,8 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -370,8 +370,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -393,12 +393,12 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= -google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -407,8 +407,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 944160427bad682df038f75b94cfad1e3e23aa41 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 13 Sep 2024 11:32:03 +0300 Subject: [PATCH 0816/1413] [#1374] cli: Drop deprecated grpc connection method For `frostfs-cli` it is ok to use grpc-client without blocking, as `frostfs-cli` will perform RPC call anyway. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/tree/add.go | 5 +++-- cmd/frostfs-cli/modules/tree/add_by_path.go | 5 +++-- cmd/frostfs-cli/modules/tree/client.go | 22 +++++++++++---------- cmd/frostfs-cli/modules/tree/get_by_path.go | 5 +++-- cmd/frostfs-cli/modules/tree/get_op_log.go | 5 +++-- cmd/frostfs-cli/modules/tree/healthcheck.go | 5 +++-- cmd/frostfs-cli/modules/tree/list.go | 5 +++-- cmd/frostfs-cli/modules/tree/move.go | 5 +++-- cmd/frostfs-cli/modules/tree/remove.go | 5 +++-- cmd/frostfs-cli/modules/tree/subtree.go | 5 +++-- 10 files changed, 39 insertions(+), 28 deletions(-) diff --git a/cmd/frostfs-cli/modules/tree/add.go b/cmd/frostfs-cli/modules/tree/add.go index 0b8dc292f2..019feb0ecc 100644 --- a/cmd/frostfs-cli/modules/tree/add.go +++ b/cmd/frostfs-cli/modules/tree/add.go @@ -47,9 +47,10 @@ func add(cmd *cobra.Command, _ []string) { meta, err := parseMeta(cmd) commonCmd.ExitOnErr(cmd, "meta data parsing: %w", err) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) diff --git a/cmd/frostfs-cli/modules/tree/add_by_path.go b/cmd/frostfs-cli/modules/tree/add_by_path.go index ea815dbfe4..5d5b00b7dd 100644 --- a/cmd/frostfs-cli/modules/tree/add_by_path.go +++ b/cmd/frostfs-cli/modules/tree/add_by_path.go @@ -50,9 +50,10 @@ func addByPath(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err) tid, _ := cmd.Flags().GetString(treeIDFlagKey) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) diff --git a/cmd/frostfs-cli/modules/tree/client.go b/cmd/frostfs-cli/modules/tree/client.go index 4f4f54657b..4e0099f027 100644 --- a/cmd/frostfs-cli/modules/tree/client.go +++ b/cmd/frostfs-cli/modules/tree/client.go @@ -3,13 +3,14 @@ package tree import ( "context" "strings" - "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + "github.com/spf13/cobra" "github.com/spf13/viper" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -17,7 +18,7 @@ import ( // _client returns grpc Tree service client. Should be removed // after making Tree API public. -func _client(ctx context.Context) (tree.TreeServiceClient, error) { +func _client() (tree.TreeServiceClient, error) { var netAddr network.Address err := netAddr.FromString(viper.GetString(commonflags.RPC)) if err != nil { @@ -25,7 +26,6 @@ func _client(ctx context.Context) (tree.TreeServiceClient, error) { } opts := []grpc.DialOption{ - grpc.WithBlock(), grpc.WithChainUnaryInterceptor( metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInteceptor(), @@ -40,12 +40,14 @@ func _client(ctx context.Context) (tree.TreeServiceClient, error) { opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } - // a default connection establishing timeout - const defaultClientConnectTimeout = time.Second * 2 - - ctx, cancel := context.WithTimeout(ctx, defaultClientConnectTimeout) - cc, err := grpc.DialContext(ctx, netAddr.URIAddr(), opts...) - cancel() - + cc, err := grpc.NewClient(netAddr.URIAddr(), opts...) return tree.NewTreeServiceClient(cc), err } + +func contextWithTimeout(cmd *cobra.Command) (context.Context, context.CancelFunc) { + if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 { + common.PrintVerbose(cmd, "Set request timeout to %s.", timeout) + return context.WithTimeout(cmd.Context(), timeout) + } + return context.WithTimeout(cmd.Context(), commonflags.TimeoutDefault) +} diff --git a/cmd/frostfs-cli/modules/tree/get_by_path.go b/cmd/frostfs-cli/modules/tree/get_by_path.go index f239066cd2..7061723fdf 100644 --- a/cmd/frostfs-cli/modules/tree/get_by_path.go +++ b/cmd/frostfs-cli/modules/tree/get_by_path.go @@ -50,9 +50,10 @@ func getByPath(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err) tid, _ := cmd.Flags().GetString(treeIDFlagKey) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) diff --git a/cmd/frostfs-cli/modules/tree/get_op_log.go b/cmd/frostfs-cli/modules/tree/get_op_log.go index b1b307f628..376aa8e8d6 100644 --- a/cmd/frostfs-cli/modules/tree/get_op_log.go +++ b/cmd/frostfs-cli/modules/tree/get_op_log.go @@ -44,9 +44,10 @@ func getOpLog(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err) tid, _ := cmd.Flags().GetString(treeIDFlagKey) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) diff --git a/cmd/frostfs-cli/modules/tree/healthcheck.go b/cmd/frostfs-cli/modules/tree/healthcheck.go index f0506467e9..b01bb2e771 100644 --- a/cmd/frostfs-cli/modules/tree/healthcheck.go +++ b/cmd/frostfs-cli/modules/tree/healthcheck.go @@ -26,9 +26,10 @@ func initHealthcheckCmd() { func healthcheck(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) req := &tree.HealthcheckRequest{ diff --git a/cmd/frostfs-cli/modules/tree/list.go b/cmd/frostfs-cli/modules/tree/list.go index a25d066d52..f8c0e490fd 100644 --- a/cmd/frostfs-cli/modules/tree/list.go +++ b/cmd/frostfs-cli/modules/tree/list.go @@ -38,9 +38,10 @@ func list(cmd *cobra.Command, _ []string) { err := cnr.DecodeString(cidString) commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) diff --git a/cmd/frostfs-cli/modules/tree/move.go b/cmd/frostfs-cli/modules/tree/move.go index 24abbd6505..dc807d7527 100644 --- a/cmd/frostfs-cli/modules/tree/move.go +++ b/cmd/frostfs-cli/modules/tree/move.go @@ -45,9 +45,10 @@ func move(cmd *cobra.Command, _ []string) { err := cnr.DecodeString(cidString) commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) diff --git a/cmd/frostfs-cli/modules/tree/remove.go b/cmd/frostfs-cli/modules/tree/remove.go index 74e9d9749a..d0b6fab2f6 100644 --- a/cmd/frostfs-cli/modules/tree/remove.go +++ b/cmd/frostfs-cli/modules/tree/remove.go @@ -41,9 +41,10 @@ func remove(cmd *cobra.Command, _ []string) { err := cnr.DecodeString(cidString) commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) diff --git a/cmd/frostfs-cli/modules/tree/subtree.go b/cmd/frostfs-cli/modules/tree/subtree.go index e88ef79cbb..83a8909b68 100644 --- a/cmd/frostfs-cli/modules/tree/subtree.go +++ b/cmd/frostfs-cli/modules/tree/subtree.go @@ -46,9 +46,10 @@ func getSubTree(cmd *cobra.Command, _ []string) { err := cnr.DecodeString(cidString) commonCmd.ExitOnErr(cmd, "decode container ID string: %w", err) - ctx := cmd.Context() + ctx, cancel := contextWithTimeout(cmd) + defer cancel() - cli, err := _client(ctx) + cli, err := _client() commonCmd.ExitOnErr(cmd, "failed to create client: %w", err) rawCID := make([]byte, sha256.Size) From 54fe8383a4f274da8f1fd553097f3268c9f2d13a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 13 Sep 2024 11:39:25 +0300 Subject: [PATCH 0817/1413] [#1374] tree: Use NewClient to create grpc connection for sync Created connection will be used to sync trees, so it is ok to defer dial to the first RPC call. Signed-off-by: Dmitrii Stepanov --- pkg/services/tree/sync.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index be22074a51..5bbc93978b 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -294,7 +294,7 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return false } - cc, err := s.dialCtx(egCtx, a) + cc, err := s.createConnection(a) if err != nil { s.log.Warn(logs.TreeFailedToConnectForTreeSynchronization, zap.Error(err), zap.String("address", addr)) return false @@ -332,8 +332,8 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return from } -func (*Service) dialCtx(egCtx context.Context, a network.Address) (*grpc.ClientConn, error) { - return grpc.DialContext(egCtx, a.URIAddr(), +func (*Service) createConnection(a network.Address) (*grpc.ClientConn, error) { + return grpc.NewClient(a.URIAddr(), grpc.WithChainUnaryInterceptor( metrics.NewUnaryClientInterceptor(), tracing_grpc.NewUnaryClientInteceptor(), From 89d0435b1d59257d5bf15c926465193e53c11922 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 13 Sep 2024 11:59:17 +0300 Subject: [PATCH 0818/1413] [#1374] tree: Use NewClient to create grpc connection in cache Created grpc connection should be established, so perform Healthcheck request to check connection is ok. Signed-off-by: Dmitrii Stepanov --- pkg/services/tree/cache.go | 33 +++++++++++++++++++++++++-------- pkg/services/tree/service.go | 2 +- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index 1be1c2f830..38501b8520 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -2,6 +2,7 @@ package tree import ( "context" + "crypto/ecdsa" "errors" "fmt" "sync" @@ -19,6 +20,7 @@ import ( type clientCache struct { sync.Mutex simplelru.LRU[string, cacheItem] + key *ecdsa.PrivateKey } type cacheItem struct { @@ -34,13 +36,14 @@ const ( var errRecentlyFailed = errors.New("client has recently failed") -func (c *clientCache) init() { +func (c *clientCache) init(pk *ecdsa.PrivateKey) { l, _ := simplelru.NewLRU(defaultClientCacheSize, func(_ string, value cacheItem) { if conn := value.cc; conn != nil { _ = conn.Close() } }) c.LRU = *l + c.key = pk } func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceClient, error) { @@ -63,7 +66,7 @@ func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceCl } } - cc, err := dialTreeService(ctx, netmapAddr) + cc, err := c.dialTreeService(ctx, netmapAddr) lastTry := time.Now() c.Lock() @@ -81,14 +84,13 @@ func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceCl return NewTreeServiceClient(cc), nil } -func dialTreeService(ctx context.Context, netmapAddr string) (*grpc.ClientConn, error) { +func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (*grpc.ClientConn, error) { var netAddr network.Address if err := netAddr.FromString(netmapAddr); err != nil { return nil, err } opts := []grpc.DialOption{ - grpc.WithBlock(), grpc.WithChainUnaryInterceptor( metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInteceptor(), @@ -103,9 +105,24 @@ func dialTreeService(ctx context.Context, netmapAddr string) (*grpc.ClientConn, opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } - ctx, cancel := context.WithTimeout(ctx, defaultClientConnectTimeout) - cc, err := grpc.DialContext(ctx, netAddr.URIAddr(), opts...) - cancel() + req := &HealthcheckRequest{ + Body: &HealthcheckRequest_Body{}, + } + if err := SignMessage(req, c.key); err != nil { + return nil, err + } - return cc, err + cc, err := grpc.NewClient(netAddr.URIAddr(), opts...) + if err != nil { + return nil, err + } + + ctx, cancel := context.WithTimeout(ctx, defaultClientConnectTimeout) + defer cancel() + // perform some request to check connection + if _, err := NewTreeServiceClient(cc).Healthcheck(ctx, req); err != nil { + _ = cc.Close() + return nil, err + } + return cc, nil } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 875e47ecb0..60bb1a6ad4 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -65,7 +65,7 @@ func New(opts ...Option) *Service { s.log = &logger.Logger{Logger: zap.NewNop()} } - s.cache.init() + s.cache.init(s.key) s.closeCh = make(chan struct{}) s.replicateCh = make(chan movePair, s.replicatorChannelCapacity) s.replicateLocalCh = make(chan applyOp) From 2be1aa781dbbc2462ca717f3b763053fb8cd2810 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 13 Sep 2024 15:44:23 +0300 Subject: [PATCH 0819/1413] [#1266] .forgejo: Make 'fumpt' job fail on changed files `gofumpt` always returns an exit code of 0, even when it finds misformatted files. To make `fumpt` action behave as expected we need to check if `gofumpt` changed any files. Signed-off-by: Ekaterina Lebedeva --- .forgejo/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index a908c62781..07ba5c268f 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -106,4 +106,6 @@ jobs: run: make fumpt-install - name: Run gofumpt - run: make fumpt + run: | + make fumpt + git diff --exit-code --quiet From 74a6a1da7fb6a895583d72f188f31b8f067ce513 Mon Sep 17 00:00:00 2001 From: Aleksey Savaitan Date: Thu, 12 Sep 2024 17:40:10 +0300 Subject: [PATCH 0820/1413] [#1361] add root ca cert for telemetry configuration Signed-off-by: Aleksey Savaitan --- cmd/frostfs-node/config.go | 6 ++- cmd/frostfs-node/config/tracing/config.go | 23 +++++++- cmd/frostfs-node/tracing.go | 10 ++-- config/example/node.env | 1 + config/example/node.json | 3 +- config/example/node.yaml | 1 + go.mod | 30 +++++------ go.sum | 64 +++++++++++------------ 8 files changed, 84 insertions(+), 54 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index f98f1c1a31..bb6580a401 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1299,7 +1299,11 @@ func (c *cfg) reloadConfig(ctx context.Context) { }}) components = append(components, dCmp{"pools", c.reloadPools}) components = append(components, dCmp{"tracing", func() error { - updated, err := tracing.Setup(ctx, *tracingconfig.ToTracingConfig(c.appCfg)) + traceConfig, err := tracingconfig.ToTracingConfig(c.appCfg) + if err != nil { + return err + } + updated, err := tracing.Setup(ctx, *traceConfig) if updated { c.log.Info(logs.FrostFSNodeTracingConfigationUpdated) } diff --git a/cmd/frostfs-node/config/tracing/config.go b/cmd/frostfs-node/config/tracing/config.go index e846be1586..8544c672c7 100644 --- a/cmd/frostfs-node/config/tracing/config.go +++ b/cmd/frostfs-node/config/tracing/config.go @@ -1,6 +1,11 @@ package tracing import ( + "crypto/x509" + "errors" + "fmt" + "os" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -11,8 +16,8 @@ const ( ) // ToTracingConfig extracts tracing config. -func ToTracingConfig(c *config.Config) *tracing.Config { - return &tracing.Config{ +func ToTracingConfig(c *config.Config) (*tracing.Config, error) { + conf := &tracing.Config{ Enabled: config.BoolSafe(c.Sub(subsection), "enabled"), Exporter: tracing.Exporter(config.StringSafe(c.Sub(subsection), "exporter")), Endpoint: config.StringSafe(c.Sub(subsection), "endpoint"), @@ -20,6 +25,20 @@ func ToTracingConfig(c *config.Config) *tracing.Config { InstanceID: getInstanceIDOrDefault(c), Version: misc.Version, } + + if trustedCa := config.StringSafe(c.Sub(subsection), "trusted_ca"); trustedCa != "" { + caBytes, err := os.ReadFile(trustedCa) + if err != nil { + return nil, fmt.Errorf("cannot read trusted ca cert by path: %w", err) + } + certPool := x509.NewCertPool() + ok := certPool.AppendCertsFromPEM(caBytes) + if !ok { + return nil, errors.New("can't fill cert pool by ca cert") + } + conf.ServerCaCertPool = certPool + } + return conf, nil } func getInstanceIDOrDefault(c *config.Config) string { diff --git a/cmd/frostfs-node/tracing.go b/cmd/frostfs-node/tracing.go index 675c31374f..f550dd8826 100644 --- a/cmd/frostfs-node/tracing.go +++ b/cmd/frostfs-node/tracing.go @@ -11,11 +11,15 @@ import ( ) func initTracing(ctx context.Context, c *cfg) { - conf := tracingconfig.ToTracingConfig(c.appCfg) - - _, err := tracing.Setup(ctx, *conf) + conf, err := tracingconfig.ToTracingConfig(c.appCfg) if err != nil { c.log.Error(logs.FrostFSNodeFailedInitTracing, zap.Error(err)) + return + } + _, err = tracing.Setup(ctx, *conf) + if err != nil { + c.log.Error(logs.FrostFSNodeFailedInitTracing, zap.Error(err)) + return } c.closers = append(c.closers, closer{ diff --git a/config/example/node.env b/config/example/node.env index c3fa85c138..030a79934b 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -199,6 +199,7 @@ FROSTFS_STORAGE_SHARD_1_GC_REMOVER_SLEEP_INTERVAL=5m FROSTFS_TRACING_ENABLED=true FROSTFS_TRACING_ENDPOINT="localhost" FROSTFS_TRACING_EXPORTER="otlp_grpc" +FROSTFS_TRACING_TRUSTED_CA="" FROSTFS_RUNTIME_SOFT_MEMORY_LIMIT=1073741824 diff --git a/config/example/node.json b/config/example/node.json index d7187250be..4e6d239fe4 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -255,7 +255,8 @@ "tracing": { "enabled": true, "endpoint": "localhost:9090", - "exporter": "otlp_grpc" + "exporter": "otlp_grpc", + "trusted_ca": "/etc/ssl/tracing.pem" }, "runtime": { "soft_memory_limit": 1073741824 diff --git a/config/example/node.yaml b/config/example/node.yaml index 776b22bd08..5a8e6a2a4b 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -231,6 +231,7 @@ tracing: enabled: true exporter: "otlp_grpc" endpoint: "localhost" + trusted_ca: "" runtime: soft_memory_limit: 1gb diff --git a/go.mod b/go.mod index 78fefc9aee..621d2e85df 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d - git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 + git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 @@ -40,15 +40,15 @@ require ( github.com/ssgreg/journald v1.0.0 github.com/stretchr/testify v1.9.0 go.etcd.io/bbolt v1.3.10 - go.opentelemetry.io/otel v1.24.0 - go.opentelemetry.io/otel/trace v1.24.0 + go.opentelemetry.io/otel v1.28.0 + go.opentelemetry.io/otel/trace v1.28.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/sync v0.7.0 golang.org/x/sys v0.22.0 golang.org/x/term v0.21.0 google.golang.org/grpc v1.66.2 - google.golang.org/protobuf v1.34.1 + google.golang.org/protobuf v1.34.2 gopkg.in/yaml.v3 v3.0.1 ) @@ -63,7 +63,7 @@ require ( github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect @@ -73,13 +73,13 @@ require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/go-fed/httpsig v1.1.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect @@ -115,18 +115,18 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/twmb/murmur3 v1.1.8 // indirect github.com/urfave/cli v1.22.14 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0 // indirect - go.opentelemetry.io/otel/metric v1.24.0 // indirect - go.opentelemetry.io/otel/sdk v1.22.0 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.24.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index 2147f8988d..4d21d9bca5 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 h1:PaZ8GpnUoXxUoNsc1qp36bT2u7FU+neU4Jn9cl8AWqI= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65/go.mod h1:6aAX80dvJ3r5fjN9CzzPglRptoiPgIC9KFGGsUA+1Hw= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 h1:6qCcm1oqFbmf9C5AauXzrL5OPGnTbI9HoB/jAtD9274= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad h1:cJGK/bXSF/0KMr6zkIy06qekQhQRU7eYzh+lWdQ0U8w= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad/go.mod h1:I4GzeEnftO++N2JHQn9QR88eV0rjQkGqlUCNMnCz1CY= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= @@ -33,8 +33,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= -github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= @@ -82,8 +82,8 @@ github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7 github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI= github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-pkgz/expirable-cache/v3 v3.0.0 h1:u3/gcu3sabLYiTCevoRKv+WzjIn5oo7P8XtiXBeRDLw= @@ -116,8 +116,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 h1:f4tg github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0/go.mod h1:hKAkSgNkL0FII46ZkJcpVEAai4KV+swlIWCKfekd1pA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -229,8 +229,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= @@ -278,22 +278,22 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= -go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0 h1:zr8ymM5OWWjjiWRzwTfZ67c905+2TMHYp2lMJ52QTyM= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.22.0/go.mod h1:sQs7FT2iLVJ+67vYngGJkPe1qr39IzaBzaj9IDNNY8k= -go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -393,10 +393,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= +google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -407,8 +407,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 96308a26c6ab73c416464e3da2f0e859915abc93 Mon Sep 17 00:00:00 2001 From: Aleksey Savaitan Date: Thu, 12 Sep 2024 17:42:20 +0300 Subject: [PATCH 0821/1413] [#1361] linter: fix funlen Signed-off-by: Aleksey Savaitan --- cmd/frostfs-node/config.go | 55 +++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index bb6580a401..c0019d36a3 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1278,7 +1278,6 @@ func (c *cfg) reloadConfig(ctx context.Context) { // all the components are expected to support // Logger's dynamic reconfiguration approach - var components []dCmp // Logger @@ -1288,6 +1287,36 @@ func (c *cfg) reloadConfig(ctx context.Context) { return } + components := c.getComponents(ctx, logPrm) + + // Storage Engine + + var rcfg engine.ReConfiguration + for _, optsWithID := range c.shardOpts(ctx) { + rcfg.AddShard(optsWithID.configID, append(optsWithID.shOpts, shard.WithTombstoneSource(c.createTombstoneSource()))) + } + + err = c.cfgObject.cfgLocalStorage.localStorage.Reload(ctx, rcfg) + if err != nil { + c.log.Error(logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err)) + return + } + + for _, component := range components { + err = component.reloadFunc() + if err != nil { + c.log.Error(logs.FrostFSNodeUpdatedConfigurationApplying, + zap.String("component", component.name), + zap.Error(err)) + } + } + + c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) +} + +func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { + var components []dCmp + components = append(components, dCmp{"logger", logPrm.Reload}) components = append(components, dCmp{"runtime", func() error { setRuntimeParameters(c) @@ -1321,29 +1350,7 @@ func (c *cfg) reloadConfig(ctx context.Context) { components = append(components, dCmp{cmp.name, func() error { return cmp.reload(ctx) }}) } - // Storage Engine - - var rcfg engine.ReConfiguration - for _, optsWithID := range c.shardOpts(ctx) { - rcfg.AddShard(optsWithID.configID, append(optsWithID.shOpts, shard.WithTombstoneSource(c.createTombstoneSource()))) - } - - err = c.cfgObject.cfgLocalStorage.localStorage.Reload(ctx, rcfg) - if err != nil { - c.log.Error(logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err)) - return - } - - for _, component := range components { - err = component.reloadFunc() - if err != nil { - c.log.Error(logs.FrostFSNodeUpdatedConfigurationApplying, - zap.String("component", component.name), - zap.Error(err)) - } - } - - c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) + return components } func (c *cfg) reloadPools() error { From ea48e928c8d6c54662c72bd650b57a8b897e7879 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 16 Sep 2024 10:45:26 +0300 Subject: [PATCH 0822/1413] [#1366] logger: Make timestamp prepending optional Signed-off-by: Aleksey Savchuk --- pkg/util/logger/logger.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index e67afb36b4..4b60f02de0 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -40,6 +40,9 @@ type Prm struct { // do not support runtime rereading dest string + + // PrependTimestamp specifies whether to prepend a timestamp in the log + PrependTimestamp bool } const ( @@ -116,11 +119,16 @@ func newConsoleLogger(prm *Prm) (*Logger, error) { c := zap.NewProductionConfig() c.Level = lvl c.Encoding = "console" - c.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder if prm.SamplingHook != nil { c.Sampling.Hook = prm.SamplingHook } + if prm.PrependTimestamp { + c.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + } else { + c.EncoderConfig.TimeKey = "" + } + lZap, err := c.Build( zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), ) @@ -140,11 +148,16 @@ func newJournaldLogger(prm *Prm) (*Logger, error) { c := zap.NewProductionConfig() c.Level = lvl c.Encoding = "console" - c.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder if prm.SamplingHook != nil { c.Sampling.Hook = prm.SamplingHook } + if prm.PrependTimestamp { + c.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + } else { + c.EncoderConfig.TimeKey = "" + } + encoder := zapjournald.NewPartialEncoder(zapcore.NewConsoleEncoder(c.EncoderConfig), zapjournald.SyslogFields) core := zapjournald.NewCore(lvl, encoder, &journald.Journal{}, zapjournald.SyslogFields) From d4bec24c9fa7ede0fcc4d5b879316f0a54c61bb9 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 16 Sep 2024 10:46:26 +0300 Subject: [PATCH 0823/1413] [#1366] node, ir: Support `timestamp` config option, update tests Signed-off-by: Aleksey Savchuk --- cmd/frostfs-ir/config.go | 2 ++ cmd/frostfs-ir/defaults.go | 1 + cmd/frostfs-ir/main.go | 2 ++ cmd/frostfs-node/config.go | 3 +++ cmd/frostfs-node/config/logger/config.go | 8 ++++++++ cmd/frostfs-node/config/logger/config_test.go | 2 ++ config/example/ir.env | 1 + config/example/ir.yaml | 1 + config/example/node.env | 1 + config/example/node.json | 3 ++- config/example/node.yaml | 1 + 11 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index 4eaac845cd..137e764ed3 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -41,6 +41,8 @@ func reloadConfig() error { if err != nil { return err } + logPrm.PrependTimestamp = cfg.GetBool("logger.timestamp") + return logPrm.Reload() } diff --git a/cmd/frostfs-ir/defaults.go b/cmd/frostfs-ir/defaults.go index e703301ae2..899918d226 100644 --- a/cmd/frostfs-ir/defaults.go +++ b/cmd/frostfs-ir/defaults.go @@ -9,6 +9,7 @@ import ( func defaultConfiguration(cfg *viper.Viper) { cfg.SetDefault("logger.level", "info") cfg.SetDefault("logger.destination", "stdout") + cfg.SetDefault("logger.timestamp", false) setPprofDefaults(cfg) diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 02936ae78c..4bc5923a0d 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -79,6 +79,8 @@ func main() { ) exitErr(err) logPrm.SamplingHook = metrics.LogMetrics().GetSamplingHook() + logPrm.PrependTimestamp = cfg.GetBool("logger.timestamp") + log, err = logger.NewLogger(logPrm) exitErr(err) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index c0019d36a3..ed3a65c25a 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -102,6 +102,7 @@ type applicationConfiguration struct { LoggerCfg struct { level string destination string + timestamp bool } EngineCfg struct { @@ -220,6 +221,7 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { a.LoggerCfg.level = loggerconfig.Level(c) a.LoggerCfg.destination = loggerconfig.Destination(c) + a.LoggerCfg.timestamp = loggerconfig.Timestamp(c) // Storage Engine @@ -1023,6 +1025,7 @@ func (c *cfg) loggerPrm() (*logger.Prm, error) { // not expected since validation should be performed before panic("incorrect log destination format: " + c.LoggerCfg.destination) } + c.dynamicConfiguration.logger.PrependTimestamp = c.LoggerCfg.timestamp return c.dynamicConfiguration.logger, nil } diff --git a/cmd/frostfs-node/config/logger/config.go b/cmd/frostfs-node/config/logger/config.go index 378b9d7939..ba9eeea2b3 100644 --- a/cmd/frostfs-node/config/logger/config.go +++ b/cmd/frostfs-node/config/logger/config.go @@ -52,6 +52,14 @@ func Destination(c *config.Config) string { return DestinationDefault } +// Timestamp returns the value of "timestamp" config parameter +// from "logger" section. +// +// Returns false if the value isn't specified. +func Timestamp(c *config.Config) bool { + return config.BoolSafe(c.Sub(subsection), "timestamp") +} + // ToLokiConfig extracts loki config. func ToLokiConfig(c *config.Config) loki.Config { hostname, _ := os.Hostname() diff --git a/cmd/frostfs-node/config/logger/config_test.go b/cmd/frostfs-node/config/logger/config_test.go index 3587a0ddb0..ffe8ac6932 100644 --- a/cmd/frostfs-node/config/logger/config_test.go +++ b/cmd/frostfs-node/config/logger/config_test.go @@ -13,6 +13,7 @@ func TestLoggerSection_Level(t *testing.T) { t.Run("defaults", func(t *testing.T) { require.Equal(t, loggerconfig.LevelDefault, loggerconfig.Level(configtest.EmptyConfig())) require.Equal(t, loggerconfig.DestinationDefault, loggerconfig.Destination(configtest.EmptyConfig())) + require.Equal(t, false, loggerconfig.Timestamp(configtest.EmptyConfig())) }) const path = "../../../../config/example/node" @@ -20,6 +21,7 @@ func TestLoggerSection_Level(t *testing.T) { fileConfigTest := func(c *config.Config) { require.Equal(t, "debug", loggerconfig.Level(c)) require.Equal(t, "journald", loggerconfig.Destination(c)) + require.Equal(t, true, loggerconfig.Timestamp(c)) } configtest.ForEachFileType(path, fileConfigTest) diff --git a/config/example/ir.env b/config/example/ir.env index 3f9530ab6f..7234a4b32c 100644 --- a/config/example/ir.env +++ b/config/example/ir.env @@ -1,4 +1,5 @@ FROSTFS_IR_LOGGER_LEVEL=info +FROSTFS_IR_LOGGER_TIMESTAMP=true FROSTFS_IR_WALLET_PATH=/path/to/wallet.json FROSTFS_IR_WALLET_ADDRESS=NUHtW3eM6a4mmFCgyyr4rj4wygsTKB88XX diff --git a/config/example/ir.yaml b/config/example/ir.yaml index 401328e721..4c64f088b6 100644 --- a/config/example/ir.yaml +++ b/config/example/ir.yaml @@ -2,6 +2,7 @@ logger: level: info # Logger level: one of "debug", "info" (default), "warn", "error", "dpanic", "panic", "fatal" + timestamp: true wallet: path: /path/to/wallet.json # Path to NEP-6 NEO wallet file diff --git a/config/example/node.env b/config/example/node.env index 030a79934b..6618a981aa 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -1,5 +1,6 @@ FROSTFS_LOGGER_LEVEL=debug FROSTFS_LOGGER_DESTINATION=journald +FROSTFS_LOGGER_TIMESTAMP=true FROSTFS_PPROF_ENABLED=true FROSTFS_PPROF_ADDRESS=localhost:6060 diff --git a/config/example/node.json b/config/example/node.json index 4e6d239fe4..0d100ed80f 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -1,7 +1,8 @@ { "logger": { "level": "debug", - "destination": "journald" + "destination": "journald", + "timestamp": true }, "pprof": { "enabled": true, diff --git a/config/example/node.yaml b/config/example/node.yaml index 5a8e6a2a4b..86be35ba85 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -1,6 +1,7 @@ logger: level: debug # logger level: one of "debug", "info" (default), "warn", "error", "dpanic", "panic", "fatal" destination: journald # logger destination: one of "stdout" (default), "journald" + timestamp: true systemdnotify: enabled: true From b807d8c40066a90accf7dbdb5d8f31f6069f551c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 18 Sep 2024 12:20:55 +0300 Subject: [PATCH 0824/1413] [#1382] go.mod: Upgrade sdk-go and api-go versions Signed-off-by: Dmitrii Stepanov --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 621d2e85df..78dce0131a 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,12 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240902111049-c11f50efeccb + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240916123151-6009d089fc69 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index 4d21d9bca5..dd0e310885 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240902111049-c11f50efeccb h1:p9ByDsw+H6p6LyYSx8LKFtAG/oPKQpDVMNfjPqdevTw= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240902111049-c11f50efeccb/go.mod h1:BDnEpkKMykCS8u1nLzR6SgNzCv6885RWlo5TnravQuI= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e h1:740ABnOBYx4o6jxULHdSSnVW2fYIO35ohg+Uz59sxd0= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 h1:6qCcm1oqFbmf9C5AauXzrL5OPGnTbI9HoB/jAtD9274= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad h1:cJGK/bXSF/0KMr6zkIy06qekQhQRU7eYzh+lWdQ0U8w= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240903093628-8f751d9dd0ad/go.mod h1:I4GzeEnftO++N2JHQn9QR88eV0rjQkGqlUCNMnCz1CY= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240916123151-6009d089fc69 h1:DJExzndXf6hztcQ8zHlBOJV/+FA6k2FpRGUcTDWqq2M= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240916123151-6009d089fc69/go.mod h1:GeNpo12HcEW4J412sH5yf8xFYapxlrt5fcYzRwg0Ino= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= From 1e7f9909dade3ed905c07930c9a9f1bd9a8323b4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 18 Sep 2024 12:21:53 +0300 Subject: [PATCH 0825/1413] [#1382] policer: Replace deprecated methods Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/check.go | 2 +- pkg/services/policer/ec.go | 2 +- pkg/services/policer/policer_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index bf67ec4d45..06282bd8de 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -110,7 +110,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe requirements.needLocalCopy = true shortage-- - } else if nodes[i].IsMaintenance() { + } else if nodes[i].Status().IsMaintenance() { shortage, uncheckedCopies = p.handleMaintenance(nodes[i], checkedNodes, shortage, uncheckedCopies) } else { if status := checkedNodes.processStatus(nodes[i]); status.Processed() { diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index 61a65fc21f..e822d1c091 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -106,7 +106,7 @@ func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, n validPlacement: true, } } - if requiredNode.IsMaintenance() { + if requiredNode.Status().IsMaintenance() { // consider maintenance mode has object, but do not drop local copy p.log.Debug(logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) return ecChunkProcessResult{} diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index e353ea4286..4e17e98a88 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -174,7 +174,7 @@ func TestProcessObject(t *testing.T) { nodes[i].SetPublicKey([]byte{byte(i)}) } for _, i := range ti.maintenanceNodes { - nodes[i].SetMaintenance() + nodes[i].SetStatus(netmap.Maintenance) } var policy netmap.PlacementPolicy From e5c8f7ff9f49b9e8d0f0a7ac4290aadeba356d6c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 18 Sep 2024 12:22:38 +0300 Subject: [PATCH 0826/1413] [#1382] controlSvc: Replace deprecated methods Signed-off-by: Dmitrii Stepanov --- pkg/services/control/ir/server/calls.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 2447a8a749..642932c913 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -91,7 +91,7 @@ func (s *Server) RemoveNode(_ context.Context, req *control.RemoveNodeRequest) ( if len(nodeInfo.PublicKey()) == 0 { return nil, status.Error(codes.NotFound, "no such node") } - if nodeInfo.IsOffline() { + if nodeInfo.Status().IsOffline() { return nil, status.Error(codes.FailedPrecondition, "node is already offline") } From d4be2f20d4a240dd5a46f09b07b432667ca52f24 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 18 Sep 2024 12:23:46 +0300 Subject: [PATCH 0827/1413] [#1382] morph: Replace deprecated methods Signed-off-by: Dmitrii Stepanov --- pkg/morph/client/netmap/netmap.go | 6 +++--- pkg/morph/client/netmap/netmap_test.go | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/morph/client/netmap/netmap.go b/pkg/morph/client/netmap/netmap.go index 61bbf5f171..f7b5c3ba45 100644 --- a/pkg/morph/client/netmap/netmap.go +++ b/pkg/morph/client/netmap/netmap.go @@ -136,11 +136,11 @@ func decodeNodeInfo(dst *netmap.NodeInfo, itemNode stackitem.Item) error { default: return fmt.Errorf("unsupported state %v", node.State) case netmapcontract.NodeStateOnline: - dst.SetOnline() + dst.SetStatus(netmap.Online) case netmapcontract.NodeStateOffline: - dst.SetOffline() + dst.SetStatus(netmap.Offline) case netmapcontract.NodeStateMaintenance: - dst.SetMaintenance() + dst.SetStatus(netmap.Maintenance) } return nil diff --git a/pkg/morph/client/netmap/netmap_test.go b/pkg/morph/client/netmap/netmap_test.go index a8a3061972..e686e271e2 100644 --- a/pkg/morph/client/netmap/netmap_test.go +++ b/pkg/morph/client/netmap/netmap_test.go @@ -20,11 +20,11 @@ func Test_stackItemsToNodeInfos(t *testing.T) { switch i % 3 { default: - expected[i].SetOffline() + expected[i].SetStatus(netmap.Offline) case int(netmapcontract.NodeStateOnline): - expected[i].SetOnline() + expected[i].SetStatus(netmap.Online) case int(netmapcontract.NodeStateMaintenance): - expected[i].SetMaintenance() + expected[i].SetStatus(netmap.Maintenance) } expected[i].SetPublicKey(pub) @@ -38,12 +38,12 @@ func Test_stackItemsToNodeInfos(t *testing.T) { var state int64 - switch { - case expected[i].IsOnline(): + switch expected[i].Status() { + case netmap.Online: state = int64(netmapcontract.NodeStateOnline) - case expected[i].IsOffline(): + case netmap.Offline: state = int64(netmapcontract.NodeStateOffline) - case expected[i].IsMaintenance(): + case netmap.Maintenance: state = int64(netmapcontract.NodeStateMaintenance) } From a603d14d080e2485fdedee4b92306b1ce4aee2b0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 18 Sep 2024 12:24:53 +0300 Subject: [PATCH 0828/1413] [#1382] ir: Replace deprecated methods Signed-off-by: Dmitrii Stepanov --- pkg/innerring/processors/netmap/cleanup_table.go | 2 +- pkg/innerring/processors/netmap/cleanup_table_test.go | 2 +- pkg/innerring/processors/netmap/handlers_test.go | 2 +- .../processors/netmap/nodevalidation/state/validator.go | 4 ++-- .../netmap/nodevalidation/state/validator_test.go | 8 ++++---- pkg/innerring/processors/netmap/process_peers.go | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/innerring/processors/netmap/cleanup_table.go b/pkg/innerring/processors/netmap/cleanup_table.go index c18611569e..abd5b089a5 100644 --- a/pkg/innerring/processors/netmap/cleanup_table.go +++ b/pkg/innerring/processors/netmap/cleanup_table.go @@ -60,7 +60,7 @@ func (c *cleanupTable) update(snapshot netmap.NetMap, now uint64) { } access.binNodeInfo = binNodeInfo - access.maintenance = nmNodes[i].IsMaintenance() + access.maintenance = nmNodes[i].Status().IsMaintenance() newMap[keyString] = access } diff --git a/pkg/innerring/processors/netmap/cleanup_table_test.go b/pkg/innerring/processors/netmap/cleanup_table_test.go index ae5620733e..208bd54960 100644 --- a/pkg/innerring/processors/netmap/cleanup_table_test.go +++ b/pkg/innerring/processors/netmap/cleanup_table_test.go @@ -127,7 +127,7 @@ func TestCleanupTable(t *testing.T) { t.Run("skip maintenance nodes", func(t *testing.T) { cnt := 0 - infos[1].SetMaintenance() + infos[1].SetStatus(netmap.Maintenance) key := netmap.StringifyPublicKey(infos[1]) c.update(networkMap, 5) diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index b34abb78cd..8875880bfc 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -146,7 +146,7 @@ func TestAddPeer(t *testing.T) { require.Nil(t, nc.notaryInvokes, "invalid notary invokes") - node.SetOnline() + node.SetStatus(netmap.Online) ev = netmapEvent.AddPeer{ NodeBytes: node.Marshal(), Request: &payload.P2PNotaryRequest{ diff --git a/pkg/innerring/processors/netmap/nodevalidation/state/validator.go b/pkg/innerring/processors/netmap/nodevalidation/state/validator.go index 4094e50a59..e5165f618c 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/state/validator.go +++ b/pkg/innerring/processors/netmap/nodevalidation/state/validator.go @@ -56,11 +56,11 @@ func (x *NetMapCandidateValidator) SetNetworkSettings(netSettings NetworkSetting // // See also netmap.NodeInfo.IsOnline/SetOnline and other similar methods. func (x *NetMapCandidateValidator) VerifyAndUpdate(node *netmap.NodeInfo) error { - if node.IsOnline() { + if node.Status().IsOnline() { return nil } - if node.IsMaintenance() { + if node.Status().IsMaintenance() { return x.netSettings.MaintenanceModeAllowed() } diff --git a/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go b/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go index a557628f08..b81d7243b1 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go +++ b/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go @@ -41,22 +41,22 @@ func TestValidator_VerifyAndUpdate(t *testing.T) { }, { name: "ONLINE", - preparer: (*netmap.NodeInfo).SetOnline, + preparer: func(ni *netmap.NodeInfo) { ni.SetStatus(netmap.Online) }, valid: true, }, { name: "OFFLINE", - preparer: (*netmap.NodeInfo).SetOffline, + preparer: func(ni *netmap.NodeInfo) { ni.SetStatus(netmap.Offline) }, valid: false, }, { name: "MAINTENANCE/allowed", - preparer: (*netmap.NodeInfo).SetMaintenance, + preparer: func(ni *netmap.NodeInfo) { ni.SetStatus(netmap.Maintenance) }, valid: true, }, { name: "MAINTENANCE/disallowed", - preparer: (*netmap.NodeInfo).SetMaintenance, + preparer: func(ni *netmap.NodeInfo) { ni.SetStatus(netmap.Maintenance) }, valid: false, validatorPreparer: func(v *state.NetMapCandidateValidator) { var s testNetworkSettings diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index 9e6e8c283a..c8c7928a34 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -62,7 +62,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { // But there is no guarantee that code will be executed in the same order. // That is why we need to perform `addPeerIR` only in case when node is online, // because in scope of this method, contract set state `ONLINE` for the node. - if updated && nodeInfo.IsOnline() { + if updated && nodeInfo.Status().IsOnline() { np.log.Info(logs.NetmapApprovingNetworkMapCandidate, zap.String("key", keyString)) From ac1eee091dfbb9193c407ac237cd53a26f4f83d9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 18 Sep 2024 12:27:10 +0300 Subject: [PATCH 0829/1413] [#1382] node: Replace deprecated methods Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 8 ++++++-- cmd/frostfs-node/netmap.go | 26 +++++++++++++++----------- cmd/internal/common/netmap.go | 8 ++++---- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index ed3a65c25a..63f410b897 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1182,7 +1182,9 @@ func (c *cfg) bootstrapWithState(stateSetter func(*netmap.NodeInfo)) error { // bootstrapOnline calls cfg.bootstrapWithState with "online" state. func bootstrapOnline(c *cfg) error { - return c.bootstrapWithState((*netmap.NodeInfo).SetOnline) + return c.bootstrapWithState(func(ni *netmap.NodeInfo) { + ni.SetStatus(netmap.Online) + }) } // bootstrap calls bootstrapWithState with: @@ -1193,7 +1195,9 @@ func (c *cfg) bootstrap() error { st := c.cfgNetmap.state.controlNetmapStatus() if st == control.NetmapStatus_MAINTENANCE { c.log.Info(logs.FrostFSNodeBootstrappingWithTheMaintenanceState) - return c.bootstrapWithState((*netmap.NodeInfo).SetMaintenance) + return c.bootstrapWithState(func(ni *netmap.NodeInfo) { + ni.SetStatus(netmap.Maintenance) + }) } c.log.Info(logs.FrostFSNodeBootstrappingWithOnlineState, diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 8104b1dc1f..c0b87492cf 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -61,13 +61,15 @@ func (s *networkState) setNodeInfo(ni *netmapSDK.NodeInfo) { if ni != nil { s.nodeInfo.Store(*ni) - switch { - case ni.IsOnline(): + switch ni.Status() { + case netmapSDK.Online: ctrlNetSt = control.NetmapStatus_ONLINE - case ni.IsOffline(): + case netmapSDK.Offline: ctrlNetSt = control.NetmapStatus_OFFLINE - case ni.IsMaintenance(): + case netmapSDK.Maintenance: ctrlNetSt = control.NetmapStatus_MAINTENANCE + case netmapSDK.UnspecifiedState: + ctrlNetSt = control.NetmapStatus_STATUS_UNDEFINED } } else { ctrlNetSt = control.NetmapStatus_OFFLINE @@ -78,7 +80,7 @@ func (s *networkState) setNodeInfo(ni *netmapSDK.NodeInfo) { // nil ni means that the node is not included // in the netmap - niOld.SetOffline() + niOld.SetStatus(netmapSDK.Offline) s.nodeInfo.Store(niOld) } @@ -139,7 +141,7 @@ func initNetmapService(ctx context.Context, c *cfg) { network.WriteToNodeInfo(c.localAddr, &c.cfgNodeInfo.localInfo) c.cfgNodeInfo.localInfo.SetPublicKey(c.key.PublicKey().Bytes()) parseAttributes(c) - c.cfgNodeInfo.localInfo.SetOffline() + c.cfgNodeInfo.localInfo.SetStatus(netmapSDK.Offline) if c.cfgMorph.client == nil { initMorphComponents(ctx, c) @@ -252,7 +254,7 @@ func initNetmapState(c *cfg) { zap.String("state", stateWord), ) - if ni != nil && ni.IsMaintenance() { + if ni != nil && ni.Status().IsMaintenance() { c.isMaintenance.Store(true) } @@ -263,13 +265,15 @@ func initNetmapState(c *cfg) { func nodeState(ni *netmapSDK.NodeInfo) string { if ni != nil { - switch { - case ni.IsOnline(): + switch ni.Status() { + case netmapSDK.Online: return "online" - case ni.IsOffline(): + case netmapSDK.Offline: return "offline" - case ni.IsMaintenance(): + case netmapSDK.Maintenance: return "maintenance" + case netmapSDK.UnspecifiedState: + return "undefined" } } return "undefined" diff --git a/cmd/internal/common/netmap.go b/cmd/internal/common/netmap.go index 79b03a7268..f550552d21 100644 --- a/cmd/internal/common/netmap.go +++ b/cmd/internal/common/netmap.go @@ -14,14 +14,14 @@ func PrettyPrintNodeInfo(cmd *cobra.Command, node netmap.NodeInfo, ) { var strState string - switch { + switch node.Status() { default: strState = "STATE_UNSUPPORTED" - case node.IsOnline(): + case netmap.Online: strState = "ONLINE" - case node.IsOffline(): + case netmap.Offline: strState = "OFFLINE" - case node.IsMaintenance(): + case netmap.Maintenance: strState = "MAINTENANCE" } From 3441fff05dd61647e7bd069db34f320e7e9efe9a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 18 Sep 2024 12:27:39 +0300 Subject: [PATCH 0830/1413] [#1382] cli: Replace deprecated methods Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/netmap/nodeinfo.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-cli/modules/netmap/nodeinfo.go b/cmd/frostfs-cli/modules/netmap/nodeinfo.go index b6ec48f354..ae4bb329a0 100644 --- a/cmd/frostfs-cli/modules/netmap/nodeinfo.go +++ b/cmd/frostfs-cli/modules/netmap/nodeinfo.go @@ -49,14 +49,14 @@ func prettyPrintNodeInfo(cmd *cobra.Command, i netmap.NodeInfo) { cmd.Println("key:", hex.EncodeToString(i.PublicKey())) var stateWord string - switch { + switch i.Status() { default: stateWord = "" - case i.IsOnline(): + case netmap.Online: stateWord = "online" - case i.IsOffline(): + case netmap.Offline: stateWord = "offline" - case i.IsMaintenance(): + case netmap.Maintenance: stateWord = "maintenance" } From 61d5e140e051f92222fa9152d6bd807d505ca1e8 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 18 Sep 2024 12:13:15 +0300 Subject: [PATCH 0831/1413] [#1383] object: Add restrictions for `Patch` method * `Patch` can't be applied for non-regular type object (tombstones, locks etc.) * Complex object parts can't be patched. So, if an object has EC/Split header, it won't be patched. Signed-off-by: Airat Arifullin --- pkg/services/object/patch/streamer.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index 85c28cda0d..73def8c7cc 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -57,12 +57,31 @@ func toFullObjectHeader(hdr *objectSDK.Object) objectV2.GetHeaderPart { return hs } +func isLinkObject(hdr *objectV2.HeaderWithSignature) bool { + split := hdr.GetHeader().GetSplit() + return len(split.GetChildren()) > 0 && split.GetParent() != nil +} + +func isComplexObjectPart(hdr *objectV2.HeaderWithSignature) bool { + return hdr.GetHeader().GetEC() != nil || hdr.GetHeader().GetSplit() != nil +} + func (s *Streamer) init(ctx context.Context, req *objectV2.PatchRequest) error { hdrWithSig, addr, err := s.readHeader(ctx, req) if err != nil { return err } + if hdrWithSig.GetHeader().GetObjectType() != objectV2.TypeRegular { + return errors.New("non-regular object can't be patched") + } + if isLinkObject(hdrWithSig) { + return errors.New("linking object can't be patched") + } + if isComplexObjectPart(hdrWithSig) { + return errors.New("complex object parts can't be patched") + } + commonPrm, err := util.CommonPrmFromV2(req) if err != nil { return err From 945b7c740b0deb4a2f16bb85f20efd8820762f53 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 18 Sep 2024 18:14:54 +0300 Subject: [PATCH 0832/1413] [#1372] adm/morph: Add delta flag to 'force-new-epoch' Signed-off-by: Alexander Chuprov --- cmd/frostfs-adm/internal/commonflags/flags.go | 1 + cmd/frostfs-adm/internal/modules/morph/helper/netmap.go | 8 ++++++-- cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go | 3 ++- cmd/frostfs-adm/internal/modules/morph/netmap/root.go | 2 ++ cmd/frostfs-adm/internal/modules/morph/node/remove.go | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-adm/internal/commonflags/flags.go b/cmd/frostfs-adm/internal/commonflags/flags.go index 81395edb0f..b51d2e1156 100644 --- a/cmd/frostfs-adm/internal/commonflags/flags.go +++ b/cmd/frostfs-adm/internal/commonflags/flags.go @@ -39,4 +39,5 @@ const ( CustomZoneFlag = "domain" AlphabetSizeFlag = "size" AllFlag = "all" + DeltaFlag = "delta" ) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go index 7a778f8c33..fb8f037838 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go @@ -72,13 +72,17 @@ func InvalidConfigValueErr(key string) error { return fmt.Errorf("invalid %s config value from netmap contract", key) } -func EmitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160) error { +func EmitNewEpochCall(bw *io.BufBinWriter, wCtx *InitializeContext, nmHash util.Uint160, countEpoch int64) error { + if countEpoch <= 0 { + return errors.New("number of epochs cannot be less than 1") + } + curr, err := unwrap.Int64(wCtx.ReadOnlyInvoker.Call(nmHash, "epoch")) if err != nil { return errors.New("can't fetch current epoch from the netmap contract") } - newEpoch := curr + 1 + newEpoch := curr + countEpoch wCtx.Command.Printf("Current epoch: %d, increase to %d.\n", curr, newEpoch) // In NeoFS this is done via Notary contract. Here, however, we can form the diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index df9a03fd1a..5e4e9c7259 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/io" @@ -30,7 +31,7 @@ func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { } bw := io.NewBufBinWriter() - if err := helper.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { + if err := helper.EmitNewEpochCall(bw, wCtx, nmHash, viper.GetInt64(commonflags.DeltaFlag)); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go index 31fda860ee..0288bcdc54 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go @@ -22,6 +22,7 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.DeltaFlag, cmd.Flags().Lookup(commonflags.DeltaFlag)) }, RunE: ForceNewEpochCmd, } @@ -35,6 +36,7 @@ func initForceNewEpochCmd() { ForceNewEpoch.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) ForceNewEpoch.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) ForceNewEpoch.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") + ForceNewEpoch.Flags().Int64(commonflags.DeltaFlag, 1, "Number of epochs to increase the current epoch") } func init() { diff --git a/cmd/frostfs-adm/internal/modules/morph/node/remove.go b/cmd/frostfs-adm/internal/modules/morph/node/remove.go index 0a19102ba5..e47451e0c0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/node/remove.go +++ b/cmd/frostfs-adm/internal/modules/morph/node/remove.go @@ -53,7 +53,7 @@ func RemoveNodesCmd(cmd *cobra.Command, args []string) error { int64(netmapcontract.NodeStateOffline), nodeKeys[i].Bytes()) } - if err := helper.EmitNewEpochCall(bw, wCtx, nmHash); err != nil { + if err := helper.EmitNewEpochCall(bw, wCtx, nmHash, 1); err != nil { return err } From 1361db91ee37d3da938dc5146cc3f15f9ee33517 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 16 Sep 2024 11:09:51 +0300 Subject: [PATCH 0833/1413] [#1301] adm/morph: Add flag -v to 'Tokens' Signed-off-by: Alexander Chuprov --- .../internal/modules/morph/nns/tokens.go | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go b/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go index 6e8ffb40a4..3c7136e9d5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go @@ -1,15 +1,25 @@ package nns import ( + "math/big" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + client "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/spf13/cobra" ) +const ( + verboseDesc = "Include additional information about CNAME record." +) + func initTokensCmd() { Cmd.AddCommand(tokensCmd) tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) tokensCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + tokensCmd.Flags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, verboseDesc) } func listTokens(cmd *cobra.Command, _ []string) { @@ -18,7 +28,39 @@ func listTokens(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "unable to get tokens: %w", err) for toks, err := it.Next(10); err == nil && len(toks) > 0; toks, err = it.Next(10) { for _, token := range toks { - cmd.Println(string(token)) + output := string(token) + if verbose, _ := cmd.Flags().GetBool(commonflags.Verbose); verbose { + cname, err := getCnameRecord(c, token) + commonCmd.ExitOnErr(cmd, "", err) + if cname != "" { + output += " (CNAME: " + cname + ")" + } + } + cmd.Println(output) } } } + +func getCnameRecord(c *client.Contract, token []byte) (string, error) { + items, err := c.GetRecords(string(token), big.NewInt(int64(nns.CNAME))) + + // GetRecords returns the error "not an array" if the domain does not contain records. + if err != nil && strings.Contains(err.Error(), "not an array") { + return "", nil + } + + if err != nil { + return "", err + } + + if len(items) == 0 { + return "", nil + } + + record, err := items[0].TryBytes() + if err != nil { + return "", err + } + + return string(record), nil +} From 5a53f9c4fd52243dd36c69e62d79f344342d4349 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 19 Sep 2024 14:19:16 +0300 Subject: [PATCH 0834/1413] [#1301] go.mod: Bump frostfs-contract Signed-off-by: Alexander Chuprov --- go.mod | 6 +++--- go.sum | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 78dce0131a..502761866b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e - git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e + git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 @@ -28,7 +28,7 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.12.1 - github.com/nspcc-dev/neo-go v0.106.2 + github.com/nspcc-dev/neo-go v0.106.3 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 github.com/prometheus/client_golang v1.19.0 @@ -100,7 +100,7 @@ require ( github.com/multiformats/go-multihash v0.2.3 // indirect github.com/multiformats/go-varint v0.0.7 // indirect github.com/nspcc-dev/go-ordered-json v0.0.0-20240301084351-0246b013f8b2 // indirect - github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d // indirect + github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240727093519-1a48f1ce43ec // indirect github.com/nspcc-dev/rfc6979 v0.2.1 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect diff --git a/go.sum b/go.sum index dd0e310885..85d9df443d 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e h1:740ABnOBYx4o6jxULHdSSnVW2fYIO35ohg+Uz59sxd0= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e h1:kcBqZBiFIUBATUqEuvVigtkJJWQ2Gug/eYXn967o3M4= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240621131249-49e5270f673e/go.mod h1:F/fe1OoIDKr5Bz99q4sriuHDuf3aZefZy9ZsCqEtgxc= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c h1:9JmXxWcqWaOXModBwtj/WlPYOfSk2jRSDoRsDRYvgnA= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c/go.mod h1:DVb1AqP323wiEwCtlfoJJTERF4Xji2L39X6T8kv26RE= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= @@ -188,8 +188,8 @@ github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/n 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/go.mod h1:U5VfmPNM88P4RORFb6KSUVBdJBDhlqggJZYGXGPxOcc= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d h1:Vcb7YkZuUSSIC+WF/xV3UDfHbAxZgyT2zGleJP3Ig5k= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240521091047-78685785716d/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240727093519-1a48f1ce43ec h1:vDrbVXF2+2uP0RlkZmem3QYATcXCu9BzzGGCNsNcK7Q= +github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20240727093519-1a48f1ce43ec/go.mod h1:/vrbWSHc7YS1KSYhVOyyeucXW/e+1DkVBOgnBEXUCeY= github.com/nspcc-dev/rfc6979 v0.2.1 h1:8wWxkamHWFmO790GsewSoKUSJjVnL1fmdRpokU/RgRM= github.com/nspcc-dev/rfc6979 v0.2.1/go.mod h1:Tk7h5kyUWkhjyO3zUgFFhy1v2vQv3BvQEntakdtqrWc= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= From 53a90634fc0a55be636a220b461be731f8a91b3f Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 19 Sep 2024 14:19:41 +0300 Subject: [PATCH 0835/1413] [#1301] adm/morph: Add 'delete' domains Signed-off-by: Alexander Chuprov --- .../morph/nns/{register.go => domains.go} | 20 +++++++++++++++++++ .../internal/modules/morph/nns/root.go | 10 ++++++++++ 2 files changed, 30 insertions(+) rename cmd/frostfs-adm/internal/modules/morph/nns/{register.go => domains.go} (73%) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/register.go b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go similarity index 73% rename from cmd/frostfs-adm/internal/modules/morph/nns/register.go rename to cmd/frostfs-adm/internal/modules/morph/nns/domains.go index d05d9f171a..3684db94ab 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/register.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go @@ -42,3 +42,23 @@ func registerDomain(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "register domain error: %w", err) cmd.Println("Domain registered successfully") } + +func initDeleteCmd() { + Cmd.AddCommand(deleteCmd) + deleteCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + deleteCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + deleteCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + + _ = cobra.MarkFlagRequired(deleteCmd.Flags(), nnsNameFlag) +} + +func deleteDomain(cmd *cobra.Command, _ []string) { + c, actor, _ := getRPCClient(cmd) + + name, _ := cmd.Flags().GetString(nnsNameFlag) + h, vub, err := c.DeleteDomain(name) + + _, err = actor.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "delete domain error: %w", err) + cmd.Println("Domain deleted successfully") +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/root.go b/cmd/frostfs-adm/internal/modules/morph/nns/root.go index e528e4b7b0..56774c2924 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/root.go @@ -42,6 +42,15 @@ var ( }, Run: registerDomain, } + deleteCmd = &cobra.Command{ + Use: "delete", + Short: "Delete a domain by name", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: deleteDomain, + } renewCmd = &cobra.Command{ Use: "renew", Short: "Increases domain expiration date", @@ -91,6 +100,7 @@ var ( func init() { initTokensCmd() initRegisterCmd() + initDeleteCmd() initRenewCmd() initUpdateCmd() initAddRecordCmd() From c290d079fd71ddc851cce8d06f496d27ceedc168 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 20 Sep 2024 10:53:02 +0300 Subject: [PATCH 0836/1413] [#1312] go.mod: Update sdk-go Signed-off-by: Aleksey Savchuk --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 502761866b..9817f85278 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240916123151-6009d089fc69 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240918095938-e580ee991d98 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index 85d9df443d..3c6dd9a99b 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 h1:6qCcm1oqFbmf9C5AauXzrL5OPGnTbI9HoB/jAtD9274= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240916123151-6009d089fc69 h1:DJExzndXf6hztcQ8zHlBOJV/+FA6k2FpRGUcTDWqq2M= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240916123151-6009d089fc69/go.mod h1:GeNpo12HcEW4J412sH5yf8xFYapxlrt5fcYzRwg0Ino= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240918095938-e580ee991d98 h1:ijUci3thz0EwWkuRJDocW5D1RkVAJlt9xNG4CYepC90= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240918095938-e580ee991d98/go.mod h1:GeNpo12HcEW4J412sH5yf8xFYapxlrt5fcYzRwg0Ino= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= From c34b8acedde282bbe81efccea772a923ee570a8f Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 20 Sep 2024 10:58:22 +0300 Subject: [PATCH 0837/1413] [#1312] Drop handling of system attributes with NeoFS prefix Signed-off-by: Aleksey Savchuk --- cmd/frostfs-cli/modules/container/list_objects.go | 13 ++----------- pkg/core/object/fmt.go | 2 +- pkg/local_object_storage/metabase/put.go | 4 ---- pkg/local_object_storage/metabase/upgrade.go | 2 +- pkg/services/object_manager/tombstone/checker.go | 2 +- 5 files changed, 5 insertions(+), 18 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/list_objects.go b/cmd/frostfs-cli/modules/container/list_objects.go index ff2f8cf458..d5850359d4 100644 --- a/cmd/frostfs-cli/modules/container/list_objects.go +++ b/cmd/frostfs-cli/modules/container/list_objects.go @@ -1,9 +1,6 @@ package container import ( - "strings" - - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" @@ -67,14 +64,8 @@ var listContainerObjectsCmd = &cobra.Command{ resHead, err := internalclient.HeadObject(cmd.Context(), prmHead) if err == nil { - attrs := resHead.Header().Attributes() - for i := range attrs { - attrKey := attrs[i].Key() - if !strings.HasPrefix(attrKey, v2object.SysAttributePrefix) && !strings.HasPrefix(attrKey, v2object.SysAttributePrefixNeoFS) { - // FIXME(@cthulhu-rider): https://git.frostfs.info/TrueCloudLab/frostfs-sdk-go/issues/97 - // Use dedicated method to skip system attributes. - cmd.Printf(" %s: %s\n", attrKey, attrs[i].Value()) - } + for _, attr := range resHead.Header().UserAttributes() { + cmd.Printf(" %s: %s\n", attr.Key(), attr.Value()) } } else { cmd.Printf(" failed to read attributes: %v\n", err) diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index 96f7218061..317d62cb0a 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -361,7 +361,7 @@ func (v *FormatValidator) checkIfExpired(ctx context.Context, obj *objectSDK.Obj func expirationEpochAttribute(obj *objectSDK.Object) (uint64, error) { for _, a := range obj.Attributes() { - if a.Key() != objectV2.SysAttributeExpEpoch && a.Key() != objectV2.SysAttributeExpEpochNeoFS { + if a.Key() != objectV2.SysAttributeExpEpoch { continue } diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index ff79a0387b..0875298953 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -387,10 +387,6 @@ func hasExpirationEpoch(obj *objectSDK.Object) (uint64, bool) { attributes = ech.ParentAttributes() } for _, attr := range attributes { - if attr.Key() == objectV2.SysAttributeExpEpochNeoFS { - expEpoch, err := strconv.ParseUint(attr.Value(), 10, 64) - return expEpoch, err == nil - } if attr.Key() == objectV2.SysAttributeExpEpoch { expEpoch, err := strconv.ParseUint(attr.Value(), 10, 64) return expEpoch, err == nil diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index f677dcf8eb..b5de430dcd 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -252,7 +252,7 @@ func getNextObjectsWithExpirationEpochBatch(ctx context.Context, db *bbolt.DB, i continue } attributeKey := string(attrKey[1+cidSize:]) - if attributeKey != objectV2.SysAttributeExpEpochNeoFS && attributeKey != objectV2.SysAttributeExpEpoch { + if attributeKey != objectV2.SysAttributeExpEpoch { continue } var containerID cid.ID diff --git a/pkg/services/object_manager/tombstone/checker.go b/pkg/services/object_manager/tombstone/checker.go index c3c8100017..48a08b6931 100644 --- a/pkg/services/object_manager/tombstone/checker.go +++ b/pkg/services/object_manager/tombstone/checker.go @@ -74,7 +74,7 @@ func (g *ExpirationChecker) IsTombstoneAvailable(ctx context.Context, a oid.Addr func (g *ExpirationChecker) handleTS(addr string, ts *objectSDK.Object, reqEpoch uint64) bool { for _, atr := range ts.Attributes() { - if atr.Key() == objectV2.SysAttributeExpEpoch || atr.Key() == objectV2.SysAttributeExpEpochNeoFS { + if atr.Key() == objectV2.SysAttributeExpEpoch { epoch, err := strconv.ParseUint(atr.Value(), 10, 64) if err != nil { g.log.Warn( From f71418b73cfb49306ec1a191621b954a75105b18 Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Fri, 20 Sep 2024 10:24:40 +0000 Subject: [PATCH 0838/1413] [#1386] frostfs-adm: Add info to error messages These error messages bubble up to human users - adding more context helps to find the cause of the issue faster. Signed-off-by: Vitaliy Potyarkin --- .../modules/morph/initialize/initialize_roles.go | 10 ++++++++-- .../morph/initialize/initialize_transfer.go | 15 ++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go index a6815ee13b..05bc83a8bb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_roles.go @@ -1,6 +1,8 @@ package initialize import ( + "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/io" @@ -29,10 +31,14 @@ func setNotaryAndAlphabetNodes(c *helper.InitializeContext) error { callflag.States|callflag.AllowNotify, int64(noderoles.NeoFSAlphabet), pubs) if err := c.SendCommitteeTx(w.Bytes(), false); err != nil { - return err + return fmt.Errorf("send committee transaction: %w", err) } - return c.AwaitTx() + err := c.AwaitTx() + if err != nil { + err = fmt.Errorf("await committee transaction: %w", err) + } + return err } func setRolesFinished(c *helper.InitializeContext) (bool, error) { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go index b7102fa139..d7b0ec86c5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go @@ -3,6 +3,7 @@ package initialize import ( "fmt" "math/big" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" @@ -144,5 +145,17 @@ func createNEP17MultiTransferTx(c helper.Client, acc *wallet.Account, recipients if err != nil { return nil, fmt.Errorf("can't create actor: %w", err) } - return act.MakeRun(w.Bytes()) + tx, err := act.MakeRun(w.Bytes()) + if err != nil { + sum := make(map[util.Uint160]int64) + for _, recipient := range recipients { + sum[recipient.Token] += recipient.Amount + } + detail := make([]string, 0, len(sum)) + for _, value := range sum { + detail = append(detail, fmt.Sprintf("amount=%v", value)) + } + err = fmt.Errorf("transfer failed: from=%s(%s) %s: %w", acc.Label, acc.Address, strings.Join(detail, " "), err) + } + return tx, err } From 0b87be804a63760fc7e43a51cc1b00c5aeedbb34 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 17 Sep 2024 11:24:48 +0300 Subject: [PATCH 0839/1413] [#1381] engine: Fix tests Drop not required `Eventually` calls. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/delete_test.go | 14 ++++------- pkg/local_object_storage/shard/get_test.go | 23 ++++--------------- pkg/local_object_storage/shard/head_test.go | 19 ++------------- pkg/local_object_storage/shard/inhume_test.go | 2 +- 4 files changed, 11 insertions(+), 47 deletions(-) diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index 9f205fa5dc..574250a939 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -3,7 +3,6 @@ package shard import ( "context" "testing" - "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" @@ -58,19 +57,14 @@ func testShard(t *testing.T, hasWriteCache bool, payloadSize int) { _, err := sh.Put(context.Background(), putPrm) require.NoError(t, err) - _, err = testGet(t, sh, getPrm, hasWriteCache) + _, err = sh.Get(context.Background(), getPrm) require.NoError(t, err) if hasWriteCache { - sh.FlushWriteCache(context.Background(), FlushWriteCachePrm{ignoreErrors: false}) - require.Eventually(t, func() bool { - _, err = sh.Delete(context.Background(), delPrm) - return err == nil - }, 30*time.Second, 10*time.Millisecond) - } else { - _, err = sh.Delete(context.Background(), delPrm) - require.NoError(t, err) + require.NoError(t, sh.FlushWriteCache(context.Background(), FlushWriteCachePrm{ignoreErrors: false})) } + _, err = sh.Delete(context.Background(), delPrm) + require.NoError(t, err) _, err = sh.Get(context.Background(), getPrm) require.True(t, client.IsErrObjectNotFound(err)) diff --git a/pkg/local_object_storage/shard/get_test.go b/pkg/local_object_storage/shard/get_test.go index 8a7c6972d0..d0eecf74e0 100644 --- a/pkg/local_object_storage/shard/get_test.go +++ b/pkg/local_object_storage/shard/get_test.go @@ -5,11 +5,9 @@ import ( "context" "errors" "testing" - "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -49,7 +47,7 @@ func testShardGet(t *testing.T, hasWriteCache bool) { getPrm.SetAddress(object.AddressOf(obj)) - res, err := testGet(t, sh, getPrm, hasWriteCache) + res, err := sh.Get(context.Background(), getPrm) require.NoError(t, err) require.Equal(t, obj, res.Object()) }) @@ -67,7 +65,7 @@ func testShardGet(t *testing.T, hasWriteCache bool) { getPrm.SetAddress(object.AddressOf(obj)) - res, err := testGet(t, sh, getPrm, hasWriteCache) + res, err := sh.Get(context.Background(), getPrm) require.NoError(t, err) require.Equal(t, obj, res.Object()) }) @@ -95,13 +93,13 @@ func testShardGet(t *testing.T, hasWriteCache bool) { getPrm.SetAddress(object.AddressOf(child)) - res, err := testGet(t, sh, getPrm, hasWriteCache) + res, err := sh.Get(context.Background(), getPrm) require.NoError(t, err) require.True(t, binaryEqual(child, res.Object())) getPrm.SetAddress(object.AddressOf(parent)) - _, err = testGet(t, sh, getPrm, hasWriteCache) + _, err = sh.Get(context.Background(), getPrm) var si *objectSDK.SplitInfoError require.True(t, errors.As(err, &si)) @@ -115,19 +113,6 @@ func testShardGet(t *testing.T, hasWriteCache bool) { }) } -func testGet(t *testing.T, sh *Shard, getPrm GetPrm, hasWriteCache bool) (GetRes, error) { - res, err := sh.Get(context.Background(), getPrm) - if hasWriteCache { - require.Eventually(t, func() bool { - if client.IsErrObjectNotFound(err) { - res, err = sh.Get(context.Background(), getPrm) - } - return !client.IsErrObjectNotFound(err) - }, time.Second, time.Millisecond*100) - } - return res, err -} - // binary equal is used when object contains empty lists in the structure and // requre.Equal fails on comparing and []{} lists. func binaryEqual(a, b *objectSDK.Object) bool { diff --git a/pkg/local_object_storage/shard/head_test.go b/pkg/local_object_storage/shard/head_test.go index 1f46319939..c65bbb1e3d 100644 --- a/pkg/local_object_storage/shard/head_test.go +++ b/pkg/local_object_storage/shard/head_test.go @@ -4,11 +4,9 @@ import ( "context" "errors" "testing" - "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" @@ -46,7 +44,7 @@ func testShardHead(t *testing.T, hasWriteCache bool) { headPrm.SetAddress(object.AddressOf(obj)) - res, err := testHead(t, sh, headPrm, hasWriteCache) + res, err := sh.Head(context.Background(), headPrm) require.NoError(t, err) require.Equal(t, obj.CutPayload(), res.Object()) }) @@ -74,7 +72,7 @@ func testShardHead(t *testing.T, hasWriteCache bool) { var siErr *objectSDK.SplitInfoError - _, err = testHead(t, sh, headPrm, hasWriteCache) + _, err = sh.Head(context.Background(), headPrm) require.True(t, errors.As(err, &siErr)) headPrm.SetAddress(object.AddressOf(parent)) @@ -85,16 +83,3 @@ func testShardHead(t *testing.T, hasWriteCache bool) { require.Equal(t, parent.CutPayload(), head.Object()) }) } - -func testHead(t *testing.T, sh *Shard, headPrm HeadPrm, hasWriteCache bool) (HeadRes, error) { - res, err := sh.Head(context.Background(), headPrm) - if hasWriteCache { - require.Eventually(t, func() bool { - if client.IsErrObjectNotFound(err) { - res, err = sh.Head(context.Background(), headPrm) - } - return !client.IsErrObjectNotFound(err) - }, time.Second, time.Millisecond*100) - } - return res, err -} diff --git a/pkg/local_object_storage/shard/inhume_test.go b/pkg/local_object_storage/shard/inhume_test.go index 82754568fd..1353d5d946 100644 --- a/pkg/local_object_storage/shard/inhume_test.go +++ b/pkg/local_object_storage/shard/inhume_test.go @@ -48,7 +48,7 @@ func testShardInhume(t *testing.T, hasWriteCache bool) { _, err := sh.Put(context.Background(), putPrm) require.NoError(t, err) - _, err = testGet(t, sh, getPrm, hasWriteCache) + _, err = sh.Get(context.Background(), getPrm) require.NoError(t, err) _, err = sh.Inhume(context.Background(), inhPrm) From d4493a6d082011cfa24df68b41d92c7b905fda27 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 15:07:10 +0300 Subject: [PATCH 0840/1413] [#1390] getSvc: Fix Head EC1.1 If local EC chunk found, but remote node is off, then `HEAD --raw` request returns object not found. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/container.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pkg/services/object/get/container.go b/pkg/services/object/get/container.go index d22b141928..034768c81b 100644 --- a/pkg/services/object/get/container.go +++ b/pkg/services/object/get/container.go @@ -26,8 +26,10 @@ func (r *request) executeOnContainer(ctx context.Context) { return } + localStatus := r.status + for { - if r.processCurrentEpoch(ctx) { + if r.processCurrentEpoch(ctx, localStatus) { break } @@ -43,7 +45,7 @@ func (r *request) executeOnContainer(ctx context.Context) { } } -func (r *request) processCurrentEpoch(ctx context.Context) bool { +func (r *request) processCurrentEpoch(ctx context.Context, localStatus int) bool { r.log.Debug(logs.ProcessEpoch, zap.Uint64("number", r.curProcEpoch), ) @@ -56,7 +58,11 @@ func (r *request) processCurrentEpoch(ctx context.Context) bool { ctx, cancel := context.WithCancel(ctx) defer cancel() - r.status = statusUndefined + if localStatus == statusEC { // possible only for raw == true and local == false + r.status = statusEC + } else { + r.status = statusUndefined + } for { addrs := traverser.Next() From 3bb65ba820274a2014b3abfe6e11a98047b2059f Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 24 Sep 2024 11:46:15 +0300 Subject: [PATCH 0841/1413] [#1392] object: Fix target initialization within put streamer * Remove `relay` field from put streamer as it's no longer used; * Fix initialization of `Relay` object writer parameter. Signed-off-by: Airat Arifullin --- pkg/services/object/put/streamer.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index f3803d4338..d08e7fafac 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/target" objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/transformer" @@ -15,8 +14,6 @@ type Streamer struct { *objectwriter.Config target transformer.ChunkedObjectWriter - - relay func(context.Context, client.NodeInfo, client.MultiAddressClient) error } var errNotInit = errors.New("stream not initialized") @@ -35,7 +32,7 @@ func (p *Streamer) Init(ctx context.Context, prm *PutInitPrm) error { Header: prm.hdr, Container: prm.cnr, TraverseOpts: prm.traverseOpts, - Relay: p.relay, + Relay: prm.relay, } var err error From 839dead226534887ffbb21b07327724e42cd2135 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 16 Sep 2024 12:38:45 +0300 Subject: [PATCH 0842/1413] [#1297] getSvc: Return AccessDenied instead of ObjectNotFound Do not replace the access denied error if it was received earlier. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/remote.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index 163767c432..f2639f8e67 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -41,7 +41,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { r.status = statusUndefined if errors.As(err, &errAccessDenied) { r.err = err - } else { + } else if r.err == nil || !errors.As(r.err, &errAccessDenied) { r.err = new(apistatus.ObjectNotFound) } } From bdf386366c4e268d9f151c38c4eb5c837a49ab25 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 16 Sep 2024 12:40:12 +0300 Subject: [PATCH 0843/1413] [#1297] dev: Bump neo-go version Signed-off-by: Dmitrii Stepanov --- dev/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index 9d026797cd..be1956e651 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -3,7 +3,7 @@ version: "2.4" services: neo-go: - image: nspccdev/neo-go:0.105.0 + image: nspccdev/neo-go:0.106.0 container_name: neo-go command: ["node", "--config-path", "/config", "--privnet", "--debug"] stop_signal: SIGKILL From 34e6a309c6b1cdd4e277f76b63a6b5d01b094115 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 18 Sep 2024 12:15:32 +0300 Subject: [PATCH 0844/1413] [#1356] engine: Evacuate object from shards concurrently Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/control/evacuation.go | 15 +- pkg/local_object_storage/engine/evacuate.go | 270 +++++++++++------- .../engine/evacuate_test.go | 41 ++- pkg/local_object_storage/metabase/list.go | 167 +++++++++++ pkg/local_object_storage/shard/list.go | 65 +++++ pkg/services/control/server/evacuate_async.go | 14 +- pkg/services/control/service.proto | 4 + pkg/services/control/service_frostfs.pb.go | 68 ++++- 8 files changed, 533 insertions(+), 111 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 6fa5ed75c6..04a67e5b57 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -21,6 +21,9 @@ const ( noProgressFlag = "no-progress" scopeFlag = "scope" + containerWorkerCountFlag = "container-worker-count" + objectWorkerCountFlag = "object-worker-count" + scopeAll = "all" scopeObjects = "objects" scopeTrees = "trees" @@ -64,12 +67,16 @@ func startEvacuateShard(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) ignoreErrors, _ := cmd.Flags().GetBool(ignoreErrorsFlag) + containerWorkerCount, _ := cmd.Flags().GetUint32(containerWorkerCountFlag) + objectWorkerCount, _ := cmd.Flags().GetUint32(objectWorkerCountFlag) req := &control.StartShardEvacuationRequest{ Body: &control.StartShardEvacuationRequest_Body{ - Shard_ID: getShardIDList(cmd), - IgnoreErrors: ignoreErrors, - Scope: getEvacuationScope(cmd), + Shard_ID: getShardIDList(cmd), + IgnoreErrors: ignoreErrors, + Scope: getEvacuationScope(cmd), + ContainerWorkerCount: containerWorkerCount, + ObjectWorkerCount: objectWorkerCount, }, } @@ -371,6 +378,8 @@ func initControlStartEvacuationShardCmd() { flags.String(scopeFlag, scopeAll, fmt.Sprintf("Evacuation scope; possible values: %s, %s, %s", scopeTrees, scopeObjects, scopeAll)) flags.Bool(awaitFlag, false, "Block execution until evacuation is completed") flags.Bool(noProgressFlag, false, fmt.Sprintf("Print progress if %s provided", awaitFlag)) + flags.Uint32(containerWorkerCountFlag, 0, "Count of concurrent container evacuation workers") + flags.Uint32(objectWorkerCountFlag, 0, "Count of concurrent object evacuation workers") startEvacuationShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag) } diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 7bef6edfbc..3db556a8fa 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -10,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" @@ -24,6 +23,16 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" + "golang.org/x/sync/errgroup" +) + +const ( + // containerWorkerCountDefault is a default value of the count of + // concurrent container evacuation workers. + containerWorkerCountDefault = 10 + // objectWorkerCountDefault is a default value of the count of + // concurrent object evacuation workers. + objectWorkerCountDefault = 10 ) var ( @@ -79,6 +88,9 @@ type EvacuateShardPrm struct { IgnoreErrors bool Async bool Scope EvacuateScope + + ContainerWorkerCount uint32 + ObjectWorkerCount uint32 } // EvacuateShardRes represents result of the EvacuateShard operation. @@ -189,8 +201,6 @@ func (p *EvacuateShardRes) DeepCopy() *EvacuateShardRes { return res } -const defaultEvacuateBatchSize = 100 - type pooledShard struct { hashedShard pool util.WorkerPool @@ -242,8 +252,16 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev return nil, err } + var mtx sync.RWMutex + copyShards := func() []pooledShard { + mtx.RLock() + defer mtx.RUnlock() + t := make([]pooledShard, len(shards)) + copy(t, shards) + return t + } eg.Go(func() error { - return e.evacuateShards(egCtx, shardIDs, prm, res, shards, shardsToEvacuate) + return e.evacuateShards(egCtx, shardIDs, prm, res, copyShards, shardsToEvacuate) }) if prm.Async { @@ -261,7 +279,7 @@ func ctxOrBackground(ctx context.Context, background bool) context.Context { } func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, + shards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { var err error ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShards", @@ -287,13 +305,39 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p return err } - for _, shardID := range shardIDs { - if err = e.evacuateShard(ctx, shardID, prm, res, shards, shardsToEvacuate); err != nil { - e.log.Error(logs.EngineFinishedWithErrorShardsEvacuation, zap.Error(err), zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) - return err + ctx, cancel, egShard, egContainer, egObject := e.createErrorGroupsForEvacuation(ctx, prm) + continueLoop := true + for i := 0; continueLoop && i < len(shardIDs); i++ { + select { + case <-ctx.Done(): + continueLoop = false + default: + egShard.Go(func() error { + err := e.evacuateShard(ctx, cancel, shardIDs[i], prm, res, shards, shardsToEvacuate, egContainer, egObject) + if err != nil { + cancel(err) + } + return err + }) } } + err = egShard.Wait() + if err != nil { + err = fmt.Errorf("shard error: %w", err) + } + errContainer := egContainer.Wait() + errObject := egObject.Wait() + if errContainer != nil { + err = errors.Join(err, fmt.Errorf("container error: %w", errContainer)) + } + if errObject != nil { + err = errors.Join(err, fmt.Errorf("object error: %w", errObject)) + } + if err != nil { + e.log.Error(logs.EngineFinishedWithErrorShardsEvacuation, zap.Error(err), zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) + return err + } e.log.Info(logs.EngineFinishedSuccessfullyShardsEvacuation, zap.Strings("shard_ids", shardIDs), @@ -309,6 +353,27 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p return nil } +func (e *StorageEngine) createErrorGroupsForEvacuation(ctx context.Context, prm EvacuateShardPrm) ( + context.Context, context.CancelCauseFunc, *errgroup.Group, *errgroup.Group, *errgroup.Group, +) { + operationCtx, cancel := context.WithCancelCause(ctx) + egObject, _ := errgroup.WithContext(operationCtx) + objectWorkerCount := prm.ObjectWorkerCount + if objectWorkerCount == 0 { + objectWorkerCount = objectWorkerCountDefault + } + egObject.SetLimit(int(objectWorkerCount)) + egContainer, _ := errgroup.WithContext(operationCtx) + containerWorkerCount := prm.ContainerWorkerCount + if containerWorkerCount == 0 { + containerWorkerCount = containerWorkerCountDefault + } + egContainer.SetLimit(int(containerWorkerCount)) + egShard, _ := errgroup.WithContext(operationCtx) + + return operationCtx, cancel, egShard, egContainer, egObject +} + func (e *StorageEngine) getTotals(ctx context.Context, prm EvacuateShardPrm, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.getTotals") defer span.End() @@ -335,8 +400,9 @@ func (e *StorageEngine) getTotals(ctx context.Context, prm EvacuateShardPrm, sha return nil } -func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, +func (e *StorageEngine) evacuateShard(ctx context.Context, cancel context.CancelCauseFunc, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, + shards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, + egContainer *errgroup.Group, egObject *errgroup.Group, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShard", trace.WithAttributes( @@ -345,11 +411,10 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm E defer span.End() if prm.Scope.WithObjects() { - if err := e.evacuateShardObjects(ctx, shardID, prm, res, shards, shardsToEvacuate); err != nil { + if err := e.evacuateShardObjects(ctx, cancel, shardID, prm, res, shards, shardsToEvacuate, egContainer, egObject); err != nil { return err } } - if prm.Scope.WithTrees() && shardsToEvacuate[shardID].PiloramaEnabled() { if err := e.evacuateShardTrees(ctx, shardID, prm, res, shards, shardsToEvacuate); err != nil { return err @@ -359,44 +424,60 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, shardID string, prm E return nil } -func (e *StorageEngine) evacuateShardObjects(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, +func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context.CancelCauseFunc, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, + shards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, + egContainer *errgroup.Group, egObject *errgroup.Group, ) error { - var listPrm shard.ListWithCursorPrm - listPrm.WithCount(defaultEvacuateBatchSize) - sh := shardsToEvacuate[shardID] - sh.SetEvacuationInProgress(true) - - var c *meta.Cursor - for { - listPrm.WithCursor(c) - - // TODO (@fyrchik): #1731 this approach doesn't work in degraded modes - // because ListWithCursor works only with the metabase. - listRes, err := sh.ListWithCursor(ctx, listPrm) - if err != nil { - if errors.Is(err, meta.ErrEndOfListing) || errors.Is(err, shard.ErrDegradedMode) { - break + var cntPrm shard.IterateOverContainersPrm + cntPrm.Handler = func(ctx context.Context, name []byte, _ cid.ID) error { + select { + case <-ctx.Done(): + return context.Cause(ctx) + default: + } + egContainer.Go(func() error { + var objPrm shard.IterateOverObjectsInContainerPrm + objPrm.BucketName = name + objPrm.Handler = func(ctx context.Context, objInfo *object.Info) error { + select { + case <-ctx.Done(): + return context.Cause(ctx) + default: + } + egObject.Go(func() error { + err := e.evacuateObject(ctx, shardID, objInfo, prm, res, shards, shardsToEvacuate) + if err != nil { + cancel(err) + } + return err + }) + return nil + } + err := sh.IterateOverObjectsInContainer(ctx, objPrm) + if err != nil { + cancel(err) } - e.log.Error(logs.EngineShardsEvacuationFailedToListObjects, zap.String("shard_id", shardID), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err - } - - if err = e.evacuateObjects(ctx, sh, listRes.AddressList(), prm, res, shards, shardsToEvacuate); err != nil { - return err - } - - c = listRes.Cursor() + }) + return nil } - return nil + + sh.SetEvacuationInProgress(true) + err := sh.IterateOverContainers(ctx, cntPrm) + if err != nil { + cancel(err) + e.log.Error(logs.EngineShardsEvacuationFailedToListObjects, zap.String("shard_id", shardID), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } + return err } func (e *StorageEngine) evacuateShardTrees(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, + getShards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { sh := shardsToEvacuate[shardID] + shards := getShards() var listPrm pilorama.TreeListTreesPrm first := true @@ -637,68 +718,65 @@ func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) return shards, nil } -func (e *StorageEngine) evacuateObjects(ctx context.Context, sh *shard.Shard, toEvacuate []object.Info, prm EvacuateShardPrm, res *EvacuateShardRes, - shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, +func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objInfo *object.Info, prm EvacuateShardPrm, res *EvacuateShardRes, + getShards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, ) error { - ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateObjects", - trace.WithAttributes( - attribute.Int("objects_count", len(toEvacuate)), - )) + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateObjects") defer span.End() - for i := range toEvacuate { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - addr := toEvacuate[i].Address + select { + case <-ctx.Done(): + return context.Cause(ctx) + default: + } - var getPrm shard.GetPrm - getPrm.SetAddress(addr) - getPrm.SkipEvacCheck(true) + shards := getShards() + addr := objInfo.Address - getRes, err := sh.Get(ctx, getPrm) - if err != nil { - if prm.IgnoreErrors { - res.objFailed.Add(1) - continue - } - e.log.Error(logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) - return err - } + var getPrm shard.GetPrm + getPrm.SetAddress(addr) + getPrm.SkipEvacCheck(true) - evacuatedLocal, err := e.tryEvacuateObjectLocal(ctx, addr, getRes.Object(), sh, shards, shardsToEvacuate, res) - if err != nil { - return err - } - - if evacuatedLocal { - continue - } - - if prm.ObjectsHandler == nil { - // Do not check ignoreErrors flag here because - // ignoring errors on put make this command kinda useless. - return fmt.Errorf("%w: %s", errPutShard, toEvacuate[i]) - } - - moved, err := prm.ObjectsHandler(ctx, addr, getRes.Object()) - if err != nil { - e.log.Error(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) - return err - } - if moved { - res.objEvacuated.Add(1) - } else if prm.IgnoreErrors { + getRes, err := shardsToEvacuate[shardID].Get(ctx, getPrm) + if err != nil { + if prm.IgnoreErrors { res.objFailed.Add(1) - e.log.Warn(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) - } else { - return fmt.Errorf("object %s was not replicated", addr) + return nil } + e.log.Error(logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + return err + } + + evacuatedLocal, err := e.tryEvacuateObjectLocal(ctx, addr, getRes.Object(), shardsToEvacuate[shardID], shards, shardsToEvacuate, res) + if err != nil { + return err + } + + if evacuatedLocal { + return nil + } + + if prm.ObjectsHandler == nil { + // Do not check ignoreErrors flag here because + // ignoring errors on put make this command kinda useless. + return fmt.Errorf("%w: %s", errPutShard, objInfo) + } + + moved, err := prm.ObjectsHandler(ctx, addr, getRes.Object()) + if err != nil { + e.log.Error(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + return err + } + if moved { + res.objEvacuated.Add(1) + } else if prm.IgnoreErrors { + res.objFailed.Add(1) + e.log.Warn(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } else { + return fmt.Errorf("object %s was not replicated", addr) } return nil } diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 28529fab9b..f723333999 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -6,6 +6,8 @@ import ( "fmt" "path/filepath" "strconv" + "sync" + "sync/atomic" "testing" "time" @@ -174,13 +176,13 @@ func TestEvacuateObjectsNetwork(t *testing.T) { errReplication := errors.New("handler error") acceptOneOf := func(objects []*objectSDK.Object, max uint64) func(context.Context, oid.Address, *objectSDK.Object) (bool, error) { - var n uint64 + var n atomic.Uint64 return func(_ context.Context, addr oid.Address, obj *objectSDK.Object) (bool, error) { - if n == max { + if n.Load() == max { return false, errReplication } - n++ + n.Add(1) for i := range objects { if addr == objectCore.AddressOf(objects[i]) { require.Equal(t, objects[i], obj) @@ -314,6 +316,36 @@ func TestEvacuateCancellation(t *testing.T) { require.Equal(t, uint64(0), res.ObjectsEvacuated()) } +func TestEvacuateCancellationByError(t *testing.T) { + t.Parallel() + e, ids, _ := newEngineEvacuate(t, 2, 10) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() + + require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + + var prm EvacuateShardPrm + prm.ShardID = ids[1:2] + var once atomic.Bool + prm.ObjectsHandler = func(ctx context.Context, a oid.Address, o *objectSDK.Object) (bool, error) { + var err error + flag := true + if once.CompareAndSwap(false, true) { + err = errors.New("test error") + flag = false + } + return flag, err + } + prm.Scope = EvacuateScopeObjects + prm.ObjectWorkerCount = 2 + prm.ContainerWorkerCount = 2 + + _, err := e.Evacuate(context.Background(), prm) + require.ErrorContains(t, err, "test error") +} + func TestEvacuateSingleProcess(t *testing.T) { e, ids, _ := newEngineEvacuate(t, 2, 3) defer func() { @@ -531,6 +563,7 @@ func TestEvacuateTreesRemote(t *testing.T) { require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + mutex := sync.Mutex{} evacuatedTreeOps := make(map[string][]*pilorama.Move) var prm EvacuateShardPrm prm.ShardID = ids @@ -545,7 +578,9 @@ func TestEvacuateTreesRemote(t *testing.T) { if op.Time == 0 { return true, "", nil } + mutex.Lock() evacuatedTreeOps[key] = append(evacuatedTreeOps[key], &op) + mutex.Unlock() height = op.Time + 1 } } diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index b4326a92c7..5943be7f4d 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -1,6 +1,7 @@ package meta import ( + "bytes" "context" "time" @@ -61,6 +62,20 @@ func (l ListRes) Cursor() *Cursor { return l.cursor } +// IterateOverContainersPrm contains parameters for IterateOverContainers operation. +type IterateOverContainersPrm struct { + // Handler function executed upon containers in db. + Handler func(context.Context, []byte, cid.ID) error +} + +// IterateOverObjectsInContainerPrm contains parameters for IterateOverObjectsInContainer operation. +type IterateOverObjectsInContainerPrm struct { + // BucketName container's bucket name. + BucketName []byte + // Handler function executed upon objects in db. + Handler func(context.Context, *objectcore.Info) error +} + // ListWithCursor lists physical objects available in metabase starting from // cursor. Includes objects of all types. Does not include inhumed objects. // Use cursor value from response for consecutive requests. @@ -259,3 +274,155 @@ func parseContainerIDWithPrefix(containerID *cid.ID, name []byte) ([]byte, byte) return rawID, name[0] } + +// IterateOverContainers lists physical containers available in metabase starting from first. +func (db *DB) IterateOverContainers(ctx context.Context, prm IterateOverContainersPrm) error { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("IterateOverContainers", time.Since(startedAt), success) + }() + _, span := tracing.StartSpanFromContext(ctx, "metabase.IterateOverContainers", + trace.WithAttributes( + attribute.Bool("has_handler", prm.Handler != nil), + )) + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return ErrDegradedMode + } + + err := db.boltDB.View(func(tx *bbolt.Tx) error { + return db.iterateOverContainers(ctx, tx, prm) + }) + success = err == nil + return metaerr.Wrap(err) +} + +func (db *DB) iterateOverContainers(ctx context.Context, tx *bbolt.Tx, prm IterateOverContainersPrm) error { + var containerID cid.ID + for _, prefix := range [][]byte{{byte(primaryPrefix)}, {byte(lockersPrefix)}, {byte(tombstonePrefix)}} { + c := tx.Cursor() + for name, _ := c.Seek(prefix); name != nil && bytes.HasPrefix(name, prefix); name, _ = c.Next() { + cidRaw, _ := parseContainerIDWithPrefix(&containerID, name) + if cidRaw == nil { + continue + } + + bktName := make([]byte, len(name)) + copy(bktName, name) + var cnt cid.ID + copy(cnt[:], containerID[:]) + err := prm.Handler(ctx, bktName, cnt) + if err != nil { + return err + } + } + } + + return nil +} + +// IterateOverObjectsInContainer iterate over physical objects available in metabase starting from first. +func (db *DB) IterateOverObjectsInContainer(ctx context.Context, prm IterateOverObjectsInContainerPrm) error { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("IterateOverObjectsInContainer", time.Since(startedAt), success) + }() + _, span := tracing.StartSpanFromContext(ctx, "metabase.IterateOverObjectsInContainer", + trace.WithAttributes( + attribute.Bool("has_handler", prm.Handler != nil), + )) + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return ErrDegradedMode + } + + var containerID cid.ID + cidRaw, prefix := parseContainerIDWithPrefix(&containerID, prm.BucketName) + if cidRaw == nil { + return nil + } + err := db.boltDB.View(func(tx *bbolt.Tx) error { + return db.iterateOverObjectsInContainer(ctx, tx, cidRaw, prefix, containerID, prm) + }) + success = err == nil + return metaerr.Wrap(err) +} + +func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, cidRaw []byte, prefix byte, + containerID cid.ID, prm IterateOverObjectsInContainerPrm, +) error { + bkt := tx.Bucket(prm.BucketName) + if bkt == nil { + return nil + } + graveyardBkt := tx.Bucket(graveyardBucketName) + garbageBkt := tx.Bucket(garbageBucketName) + c := bkt.Cursor() + k, v := c.First() + + var objType objectSDK.Type + + switch prefix { + case primaryPrefix: + objType = objectSDK.TypeRegular + case lockersPrefix: + objType = objectSDK.TypeLock + case tombstonePrefix: + objType = objectSDK.TypeTombstone + default: + return nil + } + + for ; k != nil; k, v = c.Next() { + var obj oid.ID + if err := obj.Decode(k); err != nil { + break + } + + if inGraveyardWithKey(append(cidRaw, k...), graveyardBkt, garbageBkt) > 0 { + continue + } + + var isLinkingObj bool + var ecInfo *objectcore.ECInfo + if objType == objectSDK.TypeRegular { + var o objectSDK.Object + if err := o.Unmarshal(v); err != nil { + return err + } + isLinkingObj = isLinkObject(&o) + ecHeader := o.ECHeader() + if ecHeader != nil { + ecInfo = &objectcore.ECInfo{ + ParentID: ecHeader.Parent(), + Index: ecHeader.Index(), + Total: ecHeader.Total(), + } + } + } + + var a oid.Address + a.SetContainer(containerID) + a.SetObject(obj) + objInfo := objectcore.Info{Address: a, Type: objType, IsLinkingObject: isLinkingObj, ECInfo: ecInfo} + err := prm.Handler(ctx, &objInfo) + if err != nil { + return err + } + } + return nil +} diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index 08ea81a0cf..9f56ec7509 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -34,6 +34,20 @@ func (r ListContainersRes) Containers() []cid.ID { return r.containers } +// IterateOverContainersPrm contains parameters for IterateOverContainers operation. +type IterateOverContainersPrm struct { + // Handler function executed upon containers in db. + Handler func(context.Context, []byte, cid.ID) error +} + +// IterateOverObjectsInContainerPrm contains parameters for IterateOverObjectsInContainer operation. +type IterateOverObjectsInContainerPrm struct { + // BucketName container's bucket name. + BucketName []byte + // Handler function executed upon containers in db. + Handler func(context.Context, *objectcore.Info) error +} + // ListWithCursorPrm contains parameters for ListWithCursor operation. type ListWithCursorPrm struct { count uint32 @@ -164,3 +178,54 @@ func (s *Shard) ListWithCursor(ctx context.Context, prm ListWithCursorPrm) (List cursor: res.Cursor(), }, nil } + +// IterateOverContainers lists physical containers presented in shard. +func (s *Shard) IterateOverContainers(ctx context.Context, prm IterateOverContainersPrm) error { + _, span := tracing.StartSpanFromContext(ctx, "shard.IterateOverContainers", + trace.WithAttributes( + attribute.Bool("has_handler", prm.Handler != nil), + )) + defer span.End() + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { + return ErrDegradedMode + } + + var metaPrm meta.IterateOverContainersPrm + metaPrm.Handler = prm.Handler + err := s.metaBase.IterateOverContainers(ctx, metaPrm) + if err != nil { + return fmt.Errorf("could not iterate over containers: %w", err) + } + + return nil +} + +// IterateOverObjectsInContainer lists physical objects presented in shard for provided container's bucket name. +func (s *Shard) IterateOverObjectsInContainer(ctx context.Context, prm IterateOverObjectsInContainerPrm) error { + _, span := tracing.StartSpanFromContext(ctx, "shard.IterateOverObjectsInContainer", + trace.WithAttributes( + attribute.Bool("has_handler", prm.Handler != nil), + )) + defer span.End() + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { + return ErrDegradedMode + } + + var metaPrm meta.IterateOverObjectsInContainerPrm + metaPrm.BucketName = prm.BucketName + metaPrm.Handler = prm.Handler + err := s.metaBase.IterateOverObjectsInContainer(ctx, metaPrm) + if err != nil { + return fmt.Errorf("could not iterate over objects: %w", err) + } + + return nil +} diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index aacebe9e33..bdc6f7c387 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -23,12 +23,14 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha } prm := engine.EvacuateShardPrm{ - ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), - IgnoreErrors: req.GetBody().GetIgnoreErrors(), - ObjectsHandler: s.replicateObject, - TreeHandler: s.replicateTree, - Async: true, - Scope: engine.EvacuateScope(req.GetBody().GetScope()), + ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), + IgnoreErrors: req.GetBody().GetIgnoreErrors(), + ObjectsHandler: s.replicateObject, + TreeHandler: s.replicateTree, + Async: true, + Scope: engine.EvacuateScope(req.GetBody().GetScope()), + ContainerWorkerCount: req.GetBody().GetContainerWorkerCount(), + ObjectWorkerCount: req.GetBody().GetObjectWorkerCount(), } _, err = s.s.Evacuate(ctx, prm) diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 04994328a7..88a06de229 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -394,6 +394,10 @@ message StartShardEvacuationRequest { bool ignore_errors = 2; // Evacuation scope. uint32 scope = 3; + // Count of concurrent container evacuation workers. + uint32 container_worker_count = 4; + // Count of concurrent object evacuation workers. + uint32 object_worker_count = 5; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 019cac290b..e92a8acd1f 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -6511,9 +6511,11 @@ func (x *StartShardEvacuationRequest_Body_Scope) FromString(s string) bool { } type StartShardEvacuationRequest_Body struct { - Shard_ID [][]byte `json:"shardID"` - IgnoreErrors bool `json:"ignoreErrors"` - Scope uint32 `json:"scope"` + Shard_ID [][]byte `json:"shardID"` + IgnoreErrors bool `json:"ignoreErrors"` + Scope uint32 `json:"scope"` + ContainerWorkerCount uint32 `json:"containerWorkerCount"` + ObjectWorkerCount uint32 `json:"objectWorkerCount"` } var ( @@ -6533,6 +6535,8 @@ func (x *StartShardEvacuationRequest_Body) StableSize() (size int) { size += proto.RepeatedBytesSize(1, x.Shard_ID) size += proto.BoolSize(2, x.IgnoreErrors) size += proto.UInt32Size(3, x.Scope) + size += proto.UInt32Size(4, x.ContainerWorkerCount) + size += proto.UInt32Size(5, x.ObjectWorkerCount) return size } @@ -6558,6 +6562,12 @@ func (x *StartShardEvacuationRequest_Body) EmitProtobuf(mm *easyproto.MessageMar if x.Scope != 0 { mm.AppendUint32(3, x.Scope) } + if x.ContainerWorkerCount != 0 { + mm.AppendUint32(4, x.ContainerWorkerCount) + } + if x.ObjectWorkerCount != 0 { + mm.AppendUint32(5, x.ObjectWorkerCount) + } } // UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. @@ -6587,6 +6597,18 @@ func (x *StartShardEvacuationRequest_Body) UnmarshalProtobuf(src []byte) (err er return fmt.Errorf("cannot unmarshal field %s", "Scope") } x.Scope = data + case 4: // ContainerWorkerCount + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerWorkerCount") + } + x.ContainerWorkerCount = data + case 5: // ObjectWorkerCount + data, ok := fc.Uint32() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ObjectWorkerCount") + } + x.ObjectWorkerCount = data } } return nil @@ -6618,6 +6640,24 @@ func (x *StartShardEvacuationRequest_Body) GetScope() uint32 { func (x *StartShardEvacuationRequest_Body) SetScope(v uint32) { x.Scope = v } +func (x *StartShardEvacuationRequest_Body) GetContainerWorkerCount() uint32 { + if x != nil { + return x.ContainerWorkerCount + } + return 0 +} +func (x *StartShardEvacuationRequest_Body) SetContainerWorkerCount(v uint32) { + x.ContainerWorkerCount = v +} +func (x *StartShardEvacuationRequest_Body) GetObjectWorkerCount() uint32 { + if x != nil { + return x.ObjectWorkerCount + } + return 0 +} +func (x *StartShardEvacuationRequest_Body) SetObjectWorkerCount(v uint32) { + x.ObjectWorkerCount = v +} // MarshalJSON implements the json.Marshaler interface. func (x *StartShardEvacuationRequest_Body) MarshalJSON() ([]byte, error) { @@ -6653,6 +6693,16 @@ func (x *StartShardEvacuationRequest_Body) MarshalEasyJSON(out *jwriter.Writer) out.RawString(prefix) out.Uint32(x.Scope) } + { + const prefix string = ",\"containerWorkerCount\":" + out.RawString(prefix) + out.Uint32(x.ContainerWorkerCount) + } + { + const prefix string = ",\"objectWorkerCount\":" + out.RawString(prefix) + out.Uint32(x.ObjectWorkerCount) + } out.RawByte('}') } @@ -6706,6 +6756,18 @@ func (x *StartShardEvacuationRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { f = in.Uint32() x.Scope = f } + case "containerWorkerCount": + { + var f uint32 + f = in.Uint32() + x.ContainerWorkerCount = f + } + case "objectWorkerCount": + { + var f uint32 + f = in.Uint32() + x.ObjectWorkerCount = f + } } in.WantComma() } From 8434f3dbfc850839c759430cea9640f3c87e5f95 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 19 Sep 2024 17:00:58 +0300 Subject: [PATCH 0845/1413] [#1385] metabase: Use `Batch` for delete-related operations Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/counter.go | 4 ++-- pkg/local_object_storage/metabase/delete.go | 2 +- pkg/local_object_storage/metabase/graveyard.go | 2 +- pkg/local_object_storage/metabase/inhume.go | 2 +- pkg/local_object_storage/metabase/lock.go | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index 275099ff2b..3ead0d9a0a 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -654,7 +654,7 @@ func (db *DB) DeleteContainerSize(ctx context.Context, id cid.ID) error { return ErrReadOnlyMode } - err := db.boltDB.Update(func(tx *bbolt.Tx) error { + err := db.boltDB.Batch(func(tx *bbolt.Tx) error { b := tx.Bucket(containerVolumeBucketName) key := make([]byte, cidSize) @@ -737,7 +737,7 @@ func (db *DB) DeleteContainerCount(ctx context.Context, id cid.ID) error { return ErrReadOnlyMode } - err := db.boltDB.Update(func(tx *bbolt.Tx) error { + err := db.boltDB.Batch(func(tx *bbolt.Tx) error { b := tx.Bucket(containerCounterBucketName) key := make([]byte, cidSize) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 00c8d06e04..e5e9840a0d 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -112,7 +112,7 @@ func (db *DB) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { var err error var res DeleteRes - err = db.boltDB.Update(func(tx *bbolt.Tx) error { + err = db.boltDB.Batch(func(tx *bbolt.Tx) error { res, err = db.deleteGroup(tx, prm.addrs) return err }) diff --git a/pkg/local_object_storage/metabase/graveyard.go b/pkg/local_object_storage/metabase/graveyard.go index 80d40fb780..31f95d6ed0 100644 --- a/pkg/local_object_storage/metabase/graveyard.go +++ b/pkg/local_object_storage/metabase/graveyard.go @@ -282,7 +282,7 @@ func (db *DB) DropGraves(ctx context.Context, tss []TombstonedObject) error { buf := make([]byte, addressKeySize) - return db.boltDB.Update(func(tx *bbolt.Tx) error { + return db.boltDB.Batch(func(tx *bbolt.Tx) error { bkt := tx.Bucket(graveyardBucketName) if bkt == nil { return nil diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index b62accc43e..3aae150614 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -181,7 +181,7 @@ func (db *DB) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { inhumedByCnrID: make(map[cid.ID]ObjectCounters), } currEpoch := db.epochState.CurrentEpoch() - err := db.boltDB.Update(func(tx *bbolt.Tx) error { + err := db.boltDB.Batch(func(tx *bbolt.Tx) error { return db.inhumeTx(tx, currEpoch, prm, &res) }) success = err == nil diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index 732ba426dd..6b78ef392d 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -78,7 +78,7 @@ func (db *DB) lockInternal(locked []oid.ID, cnr cid.ID, locker oid.ID) error { } key := make([]byte, cidSize) - return metaerr.Wrap(db.boltDB.Update(func(tx *bbolt.Tx) error { + return metaerr.Wrap(db.boltDB.Batch(func(tx *bbolt.Tx) error { if firstIrregularObjectType(tx, cnr, bucketKeysLocked...) != objectSDK.TypeRegular { return logicerr.Wrap(new(apistatus.LockNonRegularObject)) } @@ -143,7 +143,7 @@ func (db *DB) FreeLockedBy(lockers []oid.Address) ([]oid.Address, error) { var unlockedObjects []oid.Address - if err := db.boltDB.Update(func(tx *bbolt.Tx) error { + if err := db.boltDB.Batch(func(tx *bbolt.Tx) error { for i := range lockers { unlocked, err := freePotentialLocks(tx, lockers[i].Container(), lockers[i].Object()) if err != nil { From 76268e3ea2a73072119ea1963f914646c029e08a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 20 Sep 2024 13:28:21 +0300 Subject: [PATCH 0846/1413] [#1385] metabase: Validate that tombstone and target have the same container ID Target container ID is taken from tombstone: cmd/frostfs-node/object.go:507 Also object of type `TOMBSTONE` contains objectID, so tombstone and tombstoned object must have the same containerID. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/lock_test.go | 8 +++-- .../metabase/containers_test.go | 4 +-- .../metabase/control_test.go | 2 +- .../metabase/counter_test.go | 30 ++++++++++++------- .../metabase/delete_test.go | 6 ++-- .../metabase/exists_test.go | 2 +- pkg/local_object_storage/metabase/get_test.go | 3 +- .../metabase/graveyard_test.go | 27 ++++++++++------- pkg/local_object_storage/metabase/inhume.go | 18 +++++++++++ .../metabase/inhume_test.go | 21 +++++++++---- .../metabase/iterators_test.go | 6 ++++ .../metabase/list_test.go | 2 +- .../metabase/lock_test.go | 10 +++++-- .../metabase/select_test.go | 6 +--- .../metabase/storage_id_test.go | 2 +- .../shard/metrics_test.go | 13 ++++---- 16 files changed, 108 insertions(+), 52 deletions(-) diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 7fa7c27ef2..9e6758fb47 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -199,7 +199,9 @@ func TestLockExpiration(t *testing.T) { require.NoError(t, err) var inhumePrm InhumePrm - inhumePrm.WithTarget(oidtest.Address(), objectcore.AddressOf(obj)) + tombAddr := oidtest.Address() + tombAddr.SetContainer(cnr) + inhumePrm.WithTarget(tombAddr, objectcore.AddressOf(obj)) var objLockedErr *apistatus.ObjectLocked _, err = e.Inhume(context.Background(), inhumePrm) @@ -209,7 +211,9 @@ func TestLockExpiration(t *testing.T) { e.HandleNewEpoch(context.Background(), lockerExpiresAfter+1) // 4. - inhumePrm.WithTarget(oidtest.Address(), objectcore.AddressOf(obj)) + tombAddr = oidtest.Address() + tombAddr.SetContainer(cnr) + inhumePrm.WithTarget(tombAddr, objectcore.AddressOf(obj)) require.Eventually(t, func() bool { _, err = e.Inhume(context.Background(), inhumePrm) diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index 8b18744585..110be68ad1 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -67,7 +67,7 @@ func TestDB_Containers(t *testing.T) { assertContains(cnrs, cnr) - require.NoError(t, metaInhume(db, object.AddressOf(obj), oidtest.Address())) + require.NoError(t, metaInhume(db, object.AddressOf(obj), oidtest.ID())) cnrs, err = db.Containers(context.Background()) require.NoError(t, err) @@ -164,7 +164,7 @@ func TestDB_ContainerSize(t *testing.T) { require.NoError(t, metaInhume( db, object.AddressOf(obj), - oidtest.Address(), + oidtest.ID(), )) volume -= int(obj.PayloadSize()) diff --git a/pkg/local_object_storage/metabase/control_test.go b/pkg/local_object_storage/metabase/control_test.go index 0354a5eb6e..2a64881cbb 100644 --- a/pkg/local_object_storage/metabase/control_test.go +++ b/pkg/local_object_storage/metabase/control_test.go @@ -41,7 +41,7 @@ func TestReset(t *testing.T) { err = putBig(db, obj) require.NoError(t, err) - err = metaInhume(db, addrToInhume, oidtest.Address()) + err = metaInhume(db, addrToInhume, oidtest.ID()) require.NoError(t, err) assertExists(addr, true, nil) diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index d1f808a633..dccccd456b 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -156,13 +156,18 @@ func TestCounters(t *testing.T) { } var prm meta.InhumePrm - prm.SetTombstoneAddress(oidtest.Address()) - prm.SetAddresses(inhumedObjs...) + for _, o := range inhumedObjs { + tombAddr := oidtest.Address() + tombAddr.SetContainer(o.Container()) - res, err := db.Inhume(context.Background(), prm) - require.NoError(t, err) - require.Equal(t, uint64(len(inhumedObjs)), res.LogicInhumed()) - require.Equal(t, uint64(len(inhumedObjs)), res.UserInhumed()) + prm.SetTombstoneAddress(tombAddr) + prm.SetAddresses(o) + + res, err := db.Inhume(context.Background(), prm) + require.NoError(t, err) + require.Equal(t, uint64(1), res.LogicInhumed()) + require.Equal(t, uint64(1), res.UserInhumed()) + } c, err := db.ObjectCounters() require.NoError(t, err) @@ -296,11 +301,16 @@ func TestCounters(t *testing.T) { } var prm meta.InhumePrm - prm.SetTombstoneAddress(oidtest.Address()) - prm.SetAddresses(inhumedObjs...) + for _, o := range inhumedObjs { + tombAddr := oidtest.Address() + tombAddr.SetContainer(o.Container()) - _, err := db.Inhume(context.Background(), prm) - require.NoError(t, err) + prm.SetTombstoneAddress(tombAddr) + prm.SetAddresses(o) + + _, err := db.Inhume(context.Background(), prm) + require.NoError(t, err) + } c, err := db.ObjectCounters() require.NoError(t, err) diff --git a/pkg/local_object_storage/metabase/delete_test.go b/pkg/local_object_storage/metabase/delete_test.go index cb85157e78..fe5f7833b9 100644 --- a/pkg/local_object_storage/metabase/delete_test.go +++ b/pkg/local_object_storage/metabase/delete_test.go @@ -40,12 +40,12 @@ func TestDB_Delete(t *testing.T) { // inhume parent and child so they will be on graveyard ts := testutil.GenerateObjectWithCID(cnr) - err = metaInhume(db, object.AddressOf(child), object.AddressOf(ts)) + err = metaInhume(db, object.AddressOf(child), object.AddressOf(ts).Object()) require.NoError(t, err) ts = testutil.GenerateObjectWithCID(cnr) - err = metaInhume(db, object.AddressOf(parent), object.AddressOf(ts)) + err = metaInhume(db, object.AddressOf(parent), object.AddressOf(ts).Object()) require.NoError(t, err) // delete object @@ -108,7 +108,7 @@ func TestGraveOnlyDelete(t *testing.T) { addr := oidtest.Address() // inhume non-existent object by address - require.NoError(t, metaInhume(db, addr, oidtest.Address())) + require.NoError(t, metaInhume(db, addr, oidtest.ID())) // delete the object data require.NoError(t, metaDelete(db, addr)) diff --git a/pkg/local_object_storage/metabase/exists_test.go b/pkg/local_object_storage/metabase/exists_test.go index 0087c1e31d..1e4148eba0 100644 --- a/pkg/local_object_storage/metabase/exists_test.go +++ b/pkg/local_object_storage/metabase/exists_test.go @@ -37,7 +37,7 @@ func TestDB_Exists(t *testing.T) { require.True(t, exists) t.Run("removed object", func(t *testing.T) { - err := metaInhume(db, object.AddressOf(regular), oidtest.Address()) + err := metaInhume(db, object.AddressOf(regular), oidtest.ID()) require.NoError(t, err) exists, err := metaExists(db, object.AddressOf(regular)) diff --git a/pkg/local_object_storage/metabase/get_test.go b/pkg/local_object_storage/metabase/get_test.go index 7654d2cd88..f0caaea705 100644 --- a/pkg/local_object_storage/metabase/get_test.go +++ b/pkg/local_object_storage/metabase/get_test.go @@ -150,9 +150,8 @@ func TestDB_Get(t *testing.T) { t.Run("get removed object", func(t *testing.T) { obj := oidtest.Address() - ts := oidtest.Address() - require.NoError(t, metaInhume(db, obj, ts)) + require.NoError(t, metaInhume(db, obj, oidtest.ID())) _, err := metaGet(db, obj, false) require.True(t, client.IsErrObjectAlreadyRemoved(err)) diff --git a/pkg/local_object_storage/metabase/graveyard_test.go b/pkg/local_object_storage/metabase/graveyard_test.go index 75c7e28524..b9c6ce28ce 100644 --- a/pkg/local_object_storage/metabase/graveyard_test.go +++ b/pkg/local_object_storage/metabase/graveyard_test.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" @@ -114,11 +115,12 @@ func TestDB_IterateDeletedObjects(t *testing.T) { db := newDB(t) defer func() { require.NoError(t, db.Close()) }() + cnr := cidtest.ID() // generate and put 4 objects - obj1 := testutil.GenerateObject() - obj2 := testutil.GenerateObject() - obj3 := testutil.GenerateObject() - obj4 := testutil.GenerateObject() + obj1 := testutil.GenerateObjectWithCID(cnr) + obj2 := testutil.GenerateObjectWithCID(cnr) + obj3 := testutil.GenerateObjectWithCID(cnr) + obj4 := testutil.GenerateObjectWithCID(cnr) var err error @@ -138,6 +140,7 @@ func TestDB_IterateDeletedObjects(t *testing.T) { // inhume with tombstone addrTombstone := oidtest.Address() + addrTombstone.SetContainer(cnr) inhumePrm.SetAddresses(object.AddressOf(obj1), object.AddressOf(obj2)) inhumePrm.SetTombstoneAddress(addrTombstone) @@ -201,11 +204,12 @@ func TestDB_IterateOverGraveyard_Offset(t *testing.T) { db := newDB(t) defer func() { require.NoError(t, db.Close()) }() + cnr := cidtest.ID() // generate and put 4 objects - obj1 := testutil.GenerateObject() - obj2 := testutil.GenerateObject() - obj3 := testutil.GenerateObject() - obj4 := testutil.GenerateObject() + obj1 := testutil.GenerateObjectWithCID(cnr) + obj2 := testutil.GenerateObjectWithCID(cnr) + obj3 := testutil.GenerateObjectWithCID(cnr) + obj4 := testutil.GenerateObjectWithCID(cnr) var err error @@ -223,6 +227,7 @@ func TestDB_IterateOverGraveyard_Offset(t *testing.T) { // inhume with tombstone addrTombstone := oidtest.Address() + addrTombstone.SetContainer(cnr) var inhumePrm meta.InhumePrm inhumePrm.SetAddresses( @@ -392,9 +397,10 @@ func TestDB_DropGraves(t *testing.T) { db := newDB(t) defer func() { require.NoError(t, db.Close()) }() + cnr := cidtest.ID() // generate and put 2 objects - obj1 := testutil.GenerateObject() - obj2 := testutil.GenerateObject() + obj1 := testutil.GenerateObjectWithCID(cnr) + obj2 := testutil.GenerateObjectWithCID(cnr) var err error @@ -406,6 +412,7 @@ func TestDB_DropGraves(t *testing.T) { // inhume with tombstone addrTombstone := oidtest.Address() + addrTombstone.SetContainer(cnr) var inhumePrm meta.InhumePrm inhumePrm.SetAddresses(object.AddressOf(obj1), object.AddressOf(obj2)) diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 3aae150614..77bb84af13 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -143,6 +143,20 @@ func (p *InhumePrm) SetForceGCMark() { p.forceRemoval = true } +func (p *InhumePrm) validate() error { + if p == nil { + return nil + } + if p.tomb != nil { + for _, addr := range p.target { + if addr.Container() != p.tomb.Container() { + return fmt.Errorf("object %s and tombstone %s have different container ID", addr, p.tomb) + } + } + } + return nil +} + var errBreakBucketForEach = errors.New("bucket ForEach break") // ErrLockObjectRemoval is returned when inhume operation is being @@ -171,6 +185,10 @@ func (db *DB) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { db.modeMtx.RLock() defer db.modeMtx.RUnlock() + if err := prm.validate(); err != nil { + return InhumeRes{}, err + } + if db.mode.NoMetabase() { return InhumeRes{}, ErrDegradedMode } else if db.mode.ReadOnly() { diff --git a/pkg/local_object_storage/metabase/inhume_test.go b/pkg/local_object_storage/metabase/inhume_test.go index 163fbec2ab..277316f7bd 100644 --- a/pkg/local_object_storage/metabase/inhume_test.go +++ b/pkg/local_object_storage/metabase/inhume_test.go @@ -9,6 +9,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" @@ -21,12 +22,10 @@ func TestDB_Inhume(t *testing.T) { raw := testutil.GenerateObject() testutil.AddAttribute(raw, "foo", "bar") - tombstoneID := oidtest.Address() - err := putBig(db, raw) require.NoError(t, err) - err = metaInhume(db, object.AddressOf(raw), tombstoneID) + err = metaInhume(db, object.AddressOf(raw), oidtest.ID()) require.NoError(t, err) _, err = metaExists(db, object.AddressOf(raw)) @@ -43,13 +42,20 @@ func TestInhumeTombOnTomb(t *testing.T) { var ( err error + cnr = cidtest.ID() addr1 = oidtest.Address() addr2 = oidtest.Address() addr3 = oidtest.Address() + addr4 = oidtest.Address() inhumePrm meta.InhumePrm existsPrm meta.ExistsPrm ) + addr1.SetContainer(cnr) + addr2.SetContainer(cnr) + addr3.SetContainer(cnr) + addr4.SetContainer(cnr) + inhumePrm.SetAddresses(addr1) inhumePrm.SetTombstoneAddress(addr2) @@ -84,7 +90,7 @@ func TestInhumeTombOnTomb(t *testing.T) { require.True(t, client.IsErrObjectAlreadyRemoved(err)) inhumePrm.SetAddresses(addr1) - inhumePrm.SetTombstoneAddress(oidtest.Address()) + inhumePrm.SetTombstoneAddress(addr4) // try to inhume addr1 (which is already a tombstone in graveyard) _, err = db.Inhume(context.Background(), inhumePrm) @@ -117,10 +123,13 @@ func TestInhumeLocked(t *testing.T) { require.ErrorAs(t, err, &e) } -func metaInhume(db *meta.DB, target, tomb oid.Address) error { +func metaInhume(db *meta.DB, target oid.Address, tomb oid.ID) error { var inhumePrm meta.InhumePrm inhumePrm.SetAddresses(target) - inhumePrm.SetTombstoneAddress(tomb) + var tombAddr oid.Address + tombAddr.SetContainer(target.Container()) + tombAddr.SetObject(tomb) + inhumePrm.SetTombstoneAddress(tombAddr) _, err := db.Inhume(context.Background(), inhumePrm) return err diff --git a/pkg/local_object_storage/metabase/iterators_test.go b/pkg/local_object_storage/metabase/iterators_test.go index 54d56d9231..777a94a6f6 100644 --- a/pkg/local_object_storage/metabase/iterators_test.go +++ b/pkg/local_object_storage/metabase/iterators_test.go @@ -9,6 +9,7 @@ import ( object2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -71,11 +72,16 @@ func TestDB_IterateCoveredByTombstones(t *testing.T) { db := newDB(t) defer func() { require.NoError(t, db.Close()) }() + cnr := cidtest.ID() ts := oidtest.Address() protected1 := oidtest.Address() protected2 := oidtest.Address() protectedLocked := oidtest.Address() garbage := oidtest.Address() + ts.SetContainer(cnr) + protected1.SetContainer(cnr) + protected2.SetContainer(cnr) + protectedLocked.SetContainer(cnr) var prm meta.InhumePrm var err error diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 6207497b1a..bc1726bd6b 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -110,7 +110,7 @@ func TestLisObjectsWithCursor(t *testing.T) { err = putBig(db, obj) require.NoError(t, err) ts := testutil.GenerateObjectWithCID(containerID) - err = metaInhume(db, object.AddressOf(obj), object.AddressOf(ts)) + err = metaInhume(db, object.AddressOf(obj), object.AddressOf(ts).Object()) require.NoError(t, err) // add one child object (do not include parent into expected) diff --git a/pkg/local_object_storage/metabase/lock_test.go b/pkg/local_object_storage/metabase/lock_test.go index 62a109b023..9601cb2bea 100644 --- a/pkg/local_object_storage/metabase/lock_test.go +++ b/pkg/local_object_storage/metabase/lock_test.go @@ -73,7 +73,9 @@ func TestDB_Lock(t *testing.T) { _, err := db.Inhume(context.Background(), inhumePrm) require.ErrorAs(t, err, &objLockedErr) - inhumePrm.SetTombstoneAddress(oidtest.Address()) + tombAddr := oidtest.Address() + tombAddr.SetContainer(objAddr.Container()) + inhumePrm.SetTombstoneAddress(tombAddr) _, err = db.Inhume(context.Background(), inhumePrm) require.ErrorAs(t, err, &objLockedErr) @@ -89,7 +91,9 @@ func TestDB_Lock(t *testing.T) { _, err = db.Inhume(context.Background(), inhumePrm) require.ErrorAs(t, err, &objLockedErr) - inhumePrm.SetTombstoneAddress(oidtest.Address()) + tombAddr = oidtest.Address() + tombAddr.SetContainer(objAddr.Container()) + inhumePrm.SetTombstoneAddress(tombAddr) _, err = db.Inhume(context.Background(), inhumePrm) require.ErrorAs(t, err, &objLockedErr) }) @@ -103,7 +107,7 @@ func TestDB_Lock(t *testing.T) { var objLockedErr *apistatus.ObjectLocked // try to inhume locked object using tombstone - err := metaInhume(db, objAddr, lockAddr) + err := metaInhume(db, objAddr, lockAddr.Object()) require.ErrorAs(t, err, &objLockedErr) // free locked object diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 6469bbdbc0..fcd5d3a90c 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -352,11 +352,7 @@ func TestDB_SelectInhume(t *testing.T) { object.AddressOf(raw2), ) - var tombstone oid.Address - tombstone.SetContainer(cnr) - tombstone.SetObject(oidtest.ID()) - - err = metaInhume(db, object.AddressOf(raw2), tombstone) + err = metaInhume(db, object.AddressOf(raw2), oidtest.ID()) require.NoError(t, err) fs = objectSDK.SearchFilters{} diff --git a/pkg/local_object_storage/metabase/storage_id_test.go b/pkg/local_object_storage/metabase/storage_id_test.go index aaf6480ab7..a86e42bd25 100644 --- a/pkg/local_object_storage/metabase/storage_id_test.go +++ b/pkg/local_object_storage/metabase/storage_id_test.go @@ -43,7 +43,7 @@ func TestDB_StorageID(t *testing.T) { cnrID, ok := deleted.ContainerID() require.True(t, ok) ts := testutil.GenerateObjectWithCID(cnrID) - require.NoError(t, metaInhume(db, object.AddressOf(deleted), object.AddressOf(ts))) + require.NoError(t, metaInhume(db, object.AddressOf(deleted), object.AddressOf(ts).Object())) // check StorageID for object without storageID fetchedStorageID, err = metaStorageID(db, object.AddressOf(raw2)) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 01a85da977..56622326a5 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -17,6 +17,7 @@ import ( cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) @@ -308,17 +309,19 @@ func TestCounters(t *testing.T) { t.Run("inhume_TS", func(t *testing.T) { var prm InhumePrm - ts := objectcore.AddressOf(testutil.GenerateObject()) phy := mm.getObjectCounter(physical) logic := mm.getObjectCounter(logical) custom := mm.getObjectCounter(user) inhumedNumber := int(phy / 4) - prm.SetTarget(ts, addrFromObjs(oo[:inhumedNumber])...) - - _, err := sh.Inhume(context.Background(), prm) - require.NoError(t, err) + for _, o := range addrFromObjs(oo[:inhumedNumber]) { + ts := oidtest.Address() + ts.SetContainer(o.Container()) + prm.SetTarget(ts, o) + _, err := sh.Inhume(context.Background(), prm) + require.NoError(t, err) + } for i := range inhumedNumber { cid, ok := oo[i].ContainerID() From fd18aa363b7b33f8b662f9b4bffaf9f3099216a6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 20 Sep 2024 13:32:05 +0300 Subject: [PATCH 0847/1413] [#1385] metabase: Optimize `isTomb` check As tombstone and target must have the same containerID, do not iterate other containers. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/inhume.go | 29 ++++++++------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 77bb84af13..12f27d3302 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -377,11 +377,8 @@ func (db *DB) getInhumeTargetBucketAndValue(garbageBKT, graveyardBKT *bbolt.Buck return targetBucket, value, nil } -func (db *DB) markAsGC(graveyardBKT, garbageBKT *bbolt.Bucket, key []byte) (bool, error) { - targetIsTomb, err := isTomb(graveyardBKT, key) - if err != nil { - return false, err - } +func (db *DB) markAsGC(graveyardBKT, garbageBKT *bbolt.Bucket, addressKey []byte) (bool, error) { + targetIsTomb := isTomb(graveyardBKT, addressKey) // do not add grave if target is a tombstone if targetIsTomb { @@ -390,7 +387,7 @@ func (db *DB) markAsGC(graveyardBKT, garbageBKT *bbolt.Bucket, key []byte) (bool // if tombstone appears object must be // additionally marked with GC - return false, garbageBKT.Put(key, zeroValue) + return false, garbageBKT.Put(addressKey, zeroValue) } func (db *DB) updateDeleteInfo(tx *bbolt.Tx, garbageBKT, graveyardBKT *bbolt.Bucket, targetKey []byte, cnr cid.ID, obj *objectSDK.Object, res *InhumeRes) error { @@ -410,25 +407,21 @@ func (db *DB) updateDeleteInfo(tx *bbolt.Tx, garbageBKT, graveyardBKT *bbolt.Buc return nil } -func isTomb(graveyardBucket *bbolt.Bucket, key []byte) (bool, error) { +func isTomb(graveyardBucket *bbolt.Bucket, addressKey []byte) bool { targetIsTomb := false // iterate over graveyard and check if target address // is the address of tombstone in graveyard. - err := graveyardBucket.ForEach(func(_, v []byte) error { + // tombstone must have the same container ID as key. + c := graveyardBucket.Cursor() + containerPrefix := addressKey[:cidSize] + for k, v := c.Seek(containerPrefix); k != nil && bytes.HasPrefix(k, containerPrefix); k, v = c.Next() { // check if graveyard has record with key corresponding // to tombstone address (at least one) - targetIsTomb = bytes.Equal(v, key) - + targetIsTomb = bytes.Equal(v, addressKey) if targetIsTomb { - // break bucket iterator - return errBreakBucketForEach + break } - - return nil - }) - if err != nil && !errors.Is(err, errBreakBucketForEach) { - return false, err } - return targetIsTomb, nil + return targetIsTomb } From 95597d34371db6555739c4e92640cd8f8862ee7e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 08:56:02 +0300 Subject: [PATCH 0848/1413] [#1388] golangci: Make `unused` linter stricker Add aditional checks. The most important false positive - structs used as map keys. Signed-off-by: Dmitrii Stepanov --- .golangci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 971f0d0e79..33cf88d8a4 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -38,6 +38,10 @@ linters-settings: alias: pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object alias: objectSDK + unused: + field-writes-are-uses: false + exported-fields-are-used: false + local-variables-are-used: false custom: truecloudlab-linters: path: bin/linters/external_linters.so From 2bd560e52846b77d2902370cfaa80d54fcd77c46 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 08:57:18 +0300 Subject: [PATCH 0849/1413] [#1388] cli: Drop unused flag/parameter Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/internal/client/client.go | 7 ------- cmd/frostfs-cli/modules/object/head.go | 3 --- 2 files changed, 10 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 03a987a57d..dcd67f0d9d 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -565,13 +565,6 @@ type HeadObjectPrm struct { commonObjectPrm objectAddressPrm rawPrm - - mainOnly bool -} - -// SetMainOnlyFlag sets flag to get only main fields of an object header in terms of FrostFS API. -func (x *HeadObjectPrm) SetMainOnlyFlag(v bool) { - x.mainOnly = v } // HeadObjectRes groups the resulting values of HeadObject operation. diff --git a/cmd/frostfs-cli/modules/object/head.go b/cmd/frostfs-cli/modules/object/head.go index 14797dc414..cf2e2d5e66 100644 --- a/cmd/frostfs-cli/modules/object/head.go +++ b/cmd/frostfs-cli/modules/object/head.go @@ -38,7 +38,6 @@ func initObjectHeadCmd() { _ = objectHeadCmd.MarkFlagRequired(commonflags.OIDFlag) flags.String(fileFlag, "", "File to write header to. Default: stdout.") - flags.Bool("main-only", false, "Return only main fields") flags.Bool(commonflags.JSON, false, "Marshal output in JSON") flags.Bool("proto", false, "Marshal output in Protobuf") flags.Bool(rawFlag, false, rawFlagDesc) @@ -49,7 +48,6 @@ func getObjectHeader(cmd *cobra.Command, _ []string) { var obj oid.ID objAddr := readObjectAddress(cmd, &cnr, &obj) - mainOnly, _ := cmd.Flags().GetBool("main-only") pk := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) @@ -62,7 +60,6 @@ func getObjectHeader(cmd *cobra.Command, _ []string) { raw, _ := cmd.Flags().GetBool(rawFlag) prm.SetRawFlag(raw) prm.SetAddress(objAddr) - prm.SetMainOnlyFlag(mainOnly) res, err := internalclient.HeadObject(cmd.Context(), prm) if err != nil { From b69e07da7af2c8167e02585a723008fa2753f848 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:02:00 +0300 Subject: [PATCH 0850/1413] [#1388] metrics: Mark nolint:unused metrics Although these fields could be deleted, I annotated them so that all the metrics used would be defined in one place. Signed-off-by: Dmitrii Stepanov --- internal/metrics/innerring.go | 3 ++- internal/metrics/node.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/metrics/innerring.go b/internal/metrics/innerring.go index f6b14a6320..f3f529d05b 100644 --- a/internal/metrics/innerring.go +++ b/internal/metrics/innerring.go @@ -17,7 +17,8 @@ type InnerRingServiceMetrics struct { eventDuration *prometheus.HistogramVec morphCacheMetrics *morphCacheMetrics logMetrics logger.LogMetrics - appInfo *ApplicationInfo + // nolint: unused + appInfo *ApplicationInfo } // NewInnerRingMetrics returns new instance of metrics collectors for inner ring. diff --git a/internal/metrics/node.go b/internal/metrics/node.go index d9e4014467..7113878757 100644 --- a/internal/metrics/node.go +++ b/internal/metrics/node.go @@ -25,7 +25,8 @@ type NodeMetrics struct { morphClient *morphClientMetrics morphCache *morphCacheMetrics log logger.LogMetrics - appInfo *ApplicationInfo + // nolint: unused + appInfo *ApplicationInfo } func NewNodeMetrics() *NodeMetrics { From aedb55f913d151669885aa6bc8ea5e83269a60b0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:06:19 +0300 Subject: [PATCH 0851/1413] [#1388] governance: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/innerring/initialization.go | 1 - .../processors/governance/handlers_test.go | 21 ------------------- .../processors/governance/processor.go | 3 --- 3 files changed, 25 deletions(-) diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index 7da0a9794e..c4aaeda560 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -163,7 +163,6 @@ func (s *Server) createAlphaSync(cfg *viper.Viper, frostfsCli *frostfsClient.Cli Log: s.log, Metrics: s.irMetrics, FrostFSClient: frostfsCli, - NetmapClient: s.netmapClient, AlphabetState: s, EpochState: s, Voter: s, diff --git a/pkg/innerring/processors/governance/handlers_test.go b/pkg/innerring/processors/governance/handlers_test.go index b73e24318c..87040bdef8 100644 --- a/pkg/innerring/processors/governance/handlers_test.go +++ b/pkg/innerring/processors/governance/handlers_test.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" frostfscontract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs" - nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/rolemanagement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" @@ -38,7 +37,6 @@ func TestHandleAlphabetSyncEvent(t *testing.T) { alphabetKeys: testKeys.mainnetKeys, } f := &testFrostFSClient{} - nm := &testNetmapClient{} proc, err := New( &Params{ @@ -50,7 +48,6 @@ func TestHandleAlphabetSyncEvent(t *testing.T) { MorphClient: m, MainnetClient: mn, FrostFSClient: f, - NetmapClient: nm, }, ) @@ -73,10 +70,6 @@ func TestHandleAlphabetSyncEvent(t *testing.T) { }, }, v.votes, "invalid vote calls") - var irUpdateExp []nmClient.UpdateIRPrm - - require.EqualValues(t, irUpdateExp, nm.updates, "invalid IR updates") - var expAlphabetUpdate client.UpdateAlphabetListPrm expAlphabetUpdate.SetHash(ev.txHash) expAlphabetUpdate.SetList(testKeys.newInnerRingExp) @@ -119,7 +112,6 @@ func TestHandleAlphabetDesignateEvent(t *testing.T) { alphabetKeys: testKeys.mainnetKeys, } f := &testFrostFSClient{} - nm := &testNetmapClient{} proc, err := New( &Params{ @@ -131,7 +123,6 @@ func TestHandleAlphabetDesignateEvent(t *testing.T) { MorphClient: m, MainnetClient: mn, FrostFSClient: f, - NetmapClient: nm, }, ) @@ -155,9 +146,6 @@ func TestHandleAlphabetDesignateEvent(t *testing.T) { }, }, v.votes, "invalid vote calls") - var irUpdatesExp []nmClient.UpdateIRPrm - require.EqualValues(t, irUpdatesExp, nm.updates, "invalid IR updates") - var alpabetUpdExp client.UpdateAlphabetListPrm alpabetUpdExp.SetList(testKeys.newInnerRingExp) alpabetUpdExp.SetHash(ev.TxHash) @@ -293,12 +281,3 @@ func (c *testFrostFSClient) AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) c.updates = append(c.updates, p) return nil } - -type testNetmapClient struct { - updates []nmClient.UpdateIRPrm -} - -func (c *testNetmapClient) UpdateInnerRing(p nmClient.UpdateIRPrm) error { - c.updates = append(c.updates, p) - return nil -} diff --git a/pkg/innerring/processors/governance/processor.go b/pkg/innerring/processors/governance/processor.go index fa267eaded..6daea417e6 100644 --- a/pkg/innerring/processors/governance/processor.go +++ b/pkg/innerring/processors/governance/processor.go @@ -79,7 +79,6 @@ type ( metrics metrics.Register pool *ants.Pool frostfsClient FrostFSClient - netmapClient NetmapClient alphabetState AlphabetState epochState EpochState @@ -105,7 +104,6 @@ type ( MorphClient MorphClient MainnetClient MainnetClient FrostFSClient FrostFSClient - NetmapClient NetmapClient } ) @@ -146,7 +144,6 @@ func New(p *Params) (*Processor, error) { metrics: metricsRegister, pool: pool, frostfsClient: p.FrostFSClient, - netmapClient: p.NetmapClient, alphabetState: p.AlphabetState, epochState: p.EpochState, voter: p.Voter, From e319bf403e7ddd24d9527829a9d5863643635ff8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:08:11 +0300 Subject: [PATCH 0852/1413] [#1388] apeSvc: Drop unused and make annotations Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 - cmd/frostfs-node/object.go | 1 - cmd/frostfs-node/policy_engine.go | 4 +++- pkg/ape/chainbase/option.go | 10 ---------- pkg/services/object/ape/service.go | 6 +----- 5 files changed, 4 insertions(+), 18 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 63f410b897..0ffa8c45bd 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1082,7 +1082,6 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) { localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase() } else { localOverrideDB = chainbase.NewBoltLocalOverrideDatabase( - chainbase.WithLogger(c.log), chainbase.WithPath(nodeconfig.PersistentPolicyRules(c.appCfg).Path()), chainbase.WithPerm(nodeconfig.PersistentPolicyRules(c.appCfg).Perm()), chainbase.WithNoSync(nodeconfig.PersistentPolicyRules(c.appCfg).NoSync()), diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 610e2c363c..9d4e35ca8c 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -473,7 +473,6 @@ func createACLServiceV2(c *cfg, apeSvc *objectAPE.Service, irFetcher *cachedIRFe func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *objectAPE.Service { return objectAPE.NewService( - c.log, objectAPE.NewChecker( c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage(), c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage(), diff --git a/cmd/frostfs-node/policy_engine.go b/cmd/frostfs-node/policy_engine.go index 22fda2b4cc..55f76cc767 100644 --- a/cmd/frostfs-node/policy_engine.go +++ b/cmd/frostfs-node/policy_engine.go @@ -21,7 +21,9 @@ type accessPolicyEngine struct { var _ engine.MorphRuleChainStorageReader = (*morphAPEChainCache)(nil) type morphAPEChainCacheKey struct { - name chain.Name + // nolint:unused + name chain.Name + // nolint:unused target engine.Target } diff --git a/pkg/ape/chainbase/option.go b/pkg/ape/chainbase/option.go index e547701fb0..590b7a885c 100644 --- a/pkg/ape/chainbase/option.go +++ b/pkg/ape/chainbase/option.go @@ -5,9 +5,7 @@ import ( "os" "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.etcd.io/bbolt" - "go.uber.org/zap" ) type Option func(*cfg) @@ -18,7 +16,6 @@ type cfg struct { noSync bool maxBatchDelay time.Duration maxBatchSize int - log *logger.Logger } func defaultCfg() *cfg { @@ -26,7 +23,6 @@ func defaultCfg() *cfg { perm: os.ModePerm, maxBatchDelay: bbolt.DefaultMaxBatchDelay, maxBatchSize: bbolt.DefaultMaxBatchSize, - log: &logger.Logger{Logger: zap.L()}, } } @@ -59,9 +55,3 @@ func WithMaxBatchSize(maxBatchSize int) Option { c.maxBatchSize = maxBatchSize } } - -func WithLogger(l *logger.Logger) Option { - return func(c *cfg) { - c.log = l - } -} diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index a1634e7c5e..6eedaf99e8 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -12,7 +12,6 @@ import ( objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -24,8 +23,6 @@ import ( var errFailedToCastToRequestContext = errors.New("failed cast to RequestContext") type Service struct { - log *logger.Logger - apeChecker Checker next objectSvc.ServiceServer @@ -67,9 +64,8 @@ func NewStorageEngineHeaderProvider(e *engine.StorageEngine, s *getsvc.Service) } } -func NewService(log *logger.Logger, apeChecker Checker, next objectSvc.ServiceServer) *Service { +func NewService(apeChecker Checker, next objectSvc.ServiceServer) *Service { return &Service{ - log: log, apeChecker: apeChecker, next: next, } From 580cd551807cea0ad2b9dfe9fbd21da0b55d6282 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:10:03 +0300 Subject: [PATCH 0853/1413] [#1388] getSvc: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/assembleec.go | 2 +- pkg/services/object/get/assemblerec.go | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/services/object/get/assembleec.go b/pkg/services/object/get/assembleec.go index a58602bf76..03f913bbf1 100644 --- a/pkg/services/object/get/assembleec.go +++ b/pkg/services/object/get/assembleec.go @@ -43,7 +43,7 @@ func (r *request) assembleEC(ctx context.Context) { } r.prm.common = r.prm.common.WithLocalOnly(false) - assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.localStorage, r.containerSource, r.log, r.headOnly(), r.traverserGenerator, r.curProcEpoch) + assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.localStorage, r.log, r.headOnly(), r.traverserGenerator, r.curProcEpoch) r.log.Debug(logs.GetAssemblingECObject, zap.Uint64("range_offset", r.ctxRange().GetOffset()), diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index dde0d7dada..44d9af3a2d 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -34,7 +34,6 @@ type assemblerec struct { rng *objectSDK.Range remoteStorage ecRemoteStorage localStorage localStorage - cs container.Source log *logger.Logger head bool traverserGenerator traverserGenerator @@ -47,7 +46,6 @@ func newAssemblerEC( rng *objectSDK.Range, remoteStorage ecRemoteStorage, localStorage localStorage, - cs container.Source, log *logger.Logger, head bool, tg traverserGenerator, @@ -59,7 +57,6 @@ func newAssemblerEC( ecInfo: ecInfo, remoteStorage: remoteStorage, localStorage: localStorage, - cs: cs, log: log, head: head, traverserGenerator: tg, From 63a567a1de8d40b87c5e0cfcb99235eb4079f059 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:10:38 +0300 Subject: [PATCH 0854/1413] [#1388] engine: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/control.go | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index 4778cf539b..80fb3f9ed8 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -249,23 +249,9 @@ func (e *StorageEngine) ResumeExecution() error { } type ReConfiguration struct { - errorsThreshold uint32 - shardPoolSize uint32 - shards map[string][]shard.Option // meta path -> shard opts } -// SetErrorsThreshold sets a size amount of errors after which -// shard is moved to read-only mode. -func (rCfg *ReConfiguration) SetErrorsThreshold(errorsThreshold uint32) { - rCfg.errorsThreshold = errorsThreshold -} - -// SetShardPoolSize sets a size of worker pool for each shard. -func (rCfg *ReConfiguration) SetShardPoolSize(shardPoolSize uint32) { - rCfg.shardPoolSize = shardPoolSize -} - // AddShard adds a shard for the reconfiguration. // Shard identifier is calculated from paths used in blobstor. func (rCfg *ReConfiguration) AddShard(id string, opts []shard.Option) { From 004ff9e9bf68174fbb64df6cbc81f98ced8755d3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:11:15 +0300 Subject: [PATCH 0855/1413] [#1388] blobstor: Drop unused Signed-off-by: Dmitrii Stepanov --- .../blobstor/memstore/control.go | 16 ++++++++-------- .../blobstor/memstore/memstore_test.go | 2 -- .../blobstor/memstore/option.go | 15 +-------------- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/pkg/local_object_storage/blobstor/memstore/control.go b/pkg/local_object_storage/blobstor/memstore/control.go index 449d4352ae..83da52eb75 100644 --- a/pkg/local_object_storage/blobstor/memstore/control.go +++ b/pkg/local_object_storage/blobstor/memstore/control.go @@ -10,11 +10,11 @@ func (s *memstoreImpl) Open(mod mode.ComponentMode) error { return nil } -func (s *memstoreImpl) Init() error { return nil } -func (s *memstoreImpl) Close() error { return nil } -func (s *memstoreImpl) Type() string { return Type } -func (s *memstoreImpl) Path() string { return s.rootPath } -func (s *memstoreImpl) SetCompressor(cc *compression.Config) { s.compression = cc } -func (s *memstoreImpl) Compressor() *compression.Config { return s.compression } -func (s *memstoreImpl) SetReportErrorFunc(f func(string, error)) { s.reportError = f } -func (s *memstoreImpl) SetParentID(string) {} +func (s *memstoreImpl) Init() error { return nil } +func (s *memstoreImpl) Close() error { return nil } +func (s *memstoreImpl) Type() string { return Type } +func (s *memstoreImpl) Path() string { return s.rootPath } +func (s *memstoreImpl) SetCompressor(cc *compression.Config) { s.compression = cc } +func (s *memstoreImpl) Compressor() *compression.Config { return s.compression } +func (s *memstoreImpl) SetReportErrorFunc(func(string, error)) {} +func (s *memstoreImpl) SetParentID(string) {} diff --git a/pkg/local_object_storage/blobstor/memstore/memstore_test.go b/pkg/local_object_storage/blobstor/memstore/memstore_test.go index 8d1480dff4..dd130e5f96 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore_test.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore_test.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/internal/blobstortest" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/stretchr/testify/require" ) @@ -16,7 +15,6 @@ import ( func TestSimpleLifecycle(t *testing.T) { s := New( WithRootPath("memstore"), - WithLogger(test.NewLogger(t)), ) defer func() { require.NoError(t, s.Close()) }() require.NoError(t, s.Open(mode.ComponentReadWrite)) diff --git a/pkg/local_object_storage/blobstor/memstore/option.go b/pkg/local_object_storage/blobstor/memstore/option.go index 3d67b1e9cd..97a03993d5 100644 --- a/pkg/local_object_storage/blobstor/memstore/option.go +++ b/pkg/local_object_storage/blobstor/memstore/option.go @@ -2,33 +2,20 @@ package memstore import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" ) type cfg struct { - log *logger.Logger rootPath string readOnly bool compression *compression.Config - reportError func(string, error) } func defaultConfig() *cfg { - return &cfg{ - log: &logger.Logger{Logger: zap.L()}, - reportError: func(string, error) {}, - } + return &cfg{} } type Option func(*cfg) -func WithLogger(l *logger.Logger) Option { - return func(c *cfg) { - c.log = l - } -} - func WithRootPath(p string) Option { return func(c *cfg) { c.rootPath = p From 401c398704f15c1d516fbcc04f842d9d3fb8c2d3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:12:01 +0300 Subject: [PATCH 0856/1413] [#1388] metabase: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index e5e9840a0d..4ad11164f0 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -77,8 +77,6 @@ func (p *DeletePrm) SetAddresses(addrs ...oid.Address) { type referenceNumber struct { all, cur int - addr oid.Address - obj *objectSDK.Object } @@ -295,9 +293,8 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter nRef, ok := refCounter[k] if !ok { nRef = &referenceNumber{ - all: parentLength(tx, parAddr), - addr: parAddr, - obj: parent, + all: parentLength(tx, parAddr), + obj: parent, } refCounter[k] = nRef From d1d6e3471c2e902c29480a091545f09c4daaf335 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:12:32 +0300 Subject: [PATCH 0857/1413] [#1388] signSvc: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/services/object/sign.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 35367aafe2..f5ae97b625 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -10,8 +10,6 @@ import ( ) type SignService struct { - key *ecdsa.PrivateKey - sigSvc *util.SignService svc ServiceServer @@ -48,7 +46,6 @@ type getRangeStreamSigner struct { func NewSignService(key *ecdsa.PrivateKey, svc ServiceServer) *SignService { return &SignService{ - key: key, sigSvc: util.NewUnarySignService(key), svc: svc, } From bdd57c8b6b03f78ed74c31db41f5bbd0f3c84beb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:12:54 +0300 Subject: [PATCH 0858/1413] [#1388] sessionSvc: Add nolint annotations Used as map key. Signed-off-by: Dmitrii Stepanov --- pkg/services/session/storage/temporary/storage.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/services/session/storage/temporary/storage.go b/pkg/services/session/storage/temporary/storage.go index ee93dee71a..9ae9db9dc9 100644 --- a/pkg/services/session/storage/temporary/storage.go +++ b/pkg/services/session/storage/temporary/storage.go @@ -9,7 +9,9 @@ import ( ) type key struct { + // nolint:unused tokenID string + // nolint:unused ownerID string } From a2ab6d4942046c3bca59addd2b73ce3b58251b84 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 09:13:27 +0300 Subject: [PATCH 0859/1413] [#1388] node: Drop unused Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 - cmd/frostfs-node/container.go | 6 ------ cmd/frostfs-node/netmap.go | 1 - 3 files changed, 8 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 0ffa8c45bd..c625b575fb 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -602,7 +602,6 @@ type cfgNetmap struct { needBootstrap bool reBoostrapTurnedOff *atomic.Bool // managed by control service in runtime - startEpoch uint64 // epoch number when application is started } type cfgNodeInfo struct { diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 5a29aac769..6733140d21 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -128,9 +128,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c cnrRdr.lister = client cnrRdr.eacl = c.cfgObject.eaclSource cnrRdr.src = c.cfgObject.cnrSource - - cnrWrt.cacheEnabled = true - cnrWrt.eacls = cachedEACLStorage } return cnrRdr, cnrWrt @@ -247,9 +244,6 @@ func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) { type morphContainerWriter struct { neoClient *cntClient.Client - - cacheEnabled bool - eacls ttlEACLStorage } func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error) { diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index c0b87492cf..5e4585f854 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -259,7 +259,6 @@ func initNetmapState(c *cfg) { } c.cfgNetmap.state.setCurrentEpoch(epoch) - c.cfgNetmap.startEpoch = epoch c.setContractNodeInfo(ni) } From 29e4cf7ba1c88552172bdbb19dade34ea9ff5ba2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 23 Sep 2024 10:51:05 +0300 Subject: [PATCH 0860/1413] [#1388] ir: Annotate cmode as nolint Signed-off-by: Dmitrii Stepanov --- pkg/innerring/innerring.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 50a37845b3..53a07e36cd 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -103,6 +103,8 @@ type ( // to the application. runners []func(chan<- error) error + // cmode used for upgrade scenario. + // nolint:unused cmode *atomic.Bool } From 4fbfffd44c4e0f4aa7bc88052eff8400a0421f7c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 24 Sep 2024 12:13:11 +0300 Subject: [PATCH 0861/1413] [#1388] putSvc: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/services/object/put/prm.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pkg/services/object/put/prm.go b/pkg/services/object/put/prm.go index 0c8f12b45e..52a7c102c3 100644 --- a/pkg/services/object/put/prm.go +++ b/pkg/services/object/put/prm.go @@ -2,7 +2,6 @@ package putsvc import ( "context" - "crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -21,8 +20,6 @@ type PutInitPrm struct { traverseOpts []placement.Option relay func(context.Context, client.NodeInfo, client.MultiAddressClient) error - - privateKey *ecdsa.PrivateKey } type PutChunkPrm struct { @@ -68,11 +65,3 @@ func (p *PutChunkPrm) WithChunk(v []byte) *PutChunkPrm { return p } - -func (p *PutInitPrm) WithPrivateKey(v *ecdsa.PrivateKey) *PutInitPrm { - if p != nil { - p.privateKey = v - } - - return p -} From 772b471aab53774e1d2cf11ae7db28166a47ec45 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 24 Sep 2024 15:58:52 +0300 Subject: [PATCH 0862/1413] [#1388] lens: Add nolint annotations Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-lens/internal/schema/common/raw.go | 2 ++ cmd/frostfs-lens/internal/schema/writecache/types.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/cmd/frostfs-lens/internal/schema/common/raw.go b/cmd/frostfs-lens/internal/schema/common/raw.go index 0990e24c34..55051554c2 100644 --- a/cmd/frostfs-lens/internal/schema/common/raw.go +++ b/cmd/frostfs-lens/internal/schema/common/raw.go @@ -7,6 +7,8 @@ import ( ) type RawEntry struct { + // key and value used for record dump. + // nolint:unused key, value []byte } diff --git a/cmd/frostfs-lens/internal/schema/writecache/types.go b/cmd/frostfs-lens/internal/schema/writecache/types.go index 3f71c5366f..11e6f3fcd9 100644 --- a/cmd/frostfs-lens/internal/schema/writecache/types.go +++ b/cmd/frostfs-lens/internal/schema/writecache/types.go @@ -16,6 +16,8 @@ type ( DefaultRecord struct { addr oid.Address + // data used for record dump. + // nolint:unused data []byte } ) From a5e1aa22c963fe612d6d2d3316ee7ca0482f0d09 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 25 Sep 2024 17:15:03 +0300 Subject: [PATCH 0863/1413] [#1394] putSvc: Fix relay Signed-off-by: Dmitrii Stepanov --- pkg/services/object/common/target/target.go | 9 +++++---- pkg/services/object/patch/streamer.go | 2 +- pkg/services/object/put/streamer.go | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/services/object/common/target/target.go b/pkg/services/object/common/target/target.go index 980c4c6bd0..a2d6b4d39f 100644 --- a/pkg/services/object/common/target/target.go +++ b/pkg/services/object/common/target/target.go @@ -13,16 +13,16 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) -func New(prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { +func New(prm objectwriter.Params) (transformer.ChunkedObjectWriter, error) { // prepare needed put parameters - if err := preparePrm(prm); err != nil { + if err := preparePrm(&prm); err != nil { return nil, fmt.Errorf("could not prepare put parameters: %w", err) } if prm.Header.Signature() != nil { - return newUntrustedTarget(prm) + return newUntrustedTarget(&prm) } - return newTrustedTarget(prm) + return newTrustedTarget(&prm) } func newUntrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { @@ -49,6 +49,7 @@ func newUntrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWrit } func newTrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { + prm.Relay = nil // do not relay request without signature maxPayloadSz := prm.Config.MaxSizeSrc.MaxObjectSize() if maxPayloadSz == 0 { return nil, errors.New("could not obtain max object size parameter") diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index 73def8c7cc..c8ed6fdbfe 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -112,7 +112,7 @@ func (s *Streamer) init(ctx context.Context, req *objectV2.PatchRequest) error { } oV2.GetHeader().SetOwnerID(ownerID) - target, err := target.New(&objectwriter.Params{ + target, err := target.New(objectwriter.Params{ Config: s.Config, Common: commonPrm, Header: objectSDK.NewFromV2(oV2), diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index d08e7fafac..f71309d31f 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -26,7 +26,7 @@ func (p *Streamer) Init(ctx context.Context, prm *PutInitPrm) error { } // initialize destination target - prmTarget := &objectwriter.Params{ + prmTarget := objectwriter.Params{ Config: p.Config, Common: prm.common, Header: prm.hdr, From 5f22ba6f380fd9d41be070f000b10cc4432981b9 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 27 Sep 2024 13:45:57 +0300 Subject: [PATCH 0864/1413] [#1397] object: Correctly set namespace before APE check Signed-off-by: Airat Arifullin --- pkg/services/object/ape/checker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 3688638d03..3f6cc7c201 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -108,7 +108,7 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { return c.checkerCore.CheckAPE(checkercore.CheckPrm{ Request: r, PublicKey: pub, - Namespace: prm.Method, + Namespace: prm.Namespace, Container: prm.Container, ContainerOwner: prm.ContainerOwner, BearerToken: prm.BearerToken, From d0ed29b3c73626f6bf881090f86bdc834d81acc1 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 3 Sep 2024 15:42:38 +0300 Subject: [PATCH 0865/1413] [#1350] node: Add ability to evacuate objects from `REP 1` only Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/control/evacuation.go | 4 + docs/evacuation.md | 7 +- pkg/local_object_storage/engine/evacuate.go | 39 +++- .../engine/evacuate_test.go | 181 +++++++++++++++++- pkg/local_object_storage/metabase/list.go | 51 +++++ pkg/local_object_storage/shard/list.go | 30 ++- pkg/services/control/server/evacuate_async.go | 1 + pkg/services/control/service.proto | 2 + pkg/services/control/service_frostfs.pb.go | 31 +++ 9 files changed, 340 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 04a67e5b57..fffc5e33e8 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -20,6 +20,7 @@ const ( awaitFlag = "await" noProgressFlag = "no-progress" scopeFlag = "scope" + repOneOnlyFlag = "rep-one-only" containerWorkerCountFlag = "container-worker-count" objectWorkerCountFlag = "object-worker-count" @@ -69,6 +70,7 @@ func startEvacuateShard(cmd *cobra.Command, _ []string) { ignoreErrors, _ := cmd.Flags().GetBool(ignoreErrorsFlag) containerWorkerCount, _ := cmd.Flags().GetUint32(containerWorkerCountFlag) objectWorkerCount, _ := cmd.Flags().GetUint32(objectWorkerCountFlag) + repOneOnly, _ := cmd.Flags().GetBool(repOneOnlyFlag) req := &control.StartShardEvacuationRequest{ Body: &control.StartShardEvacuationRequest_Body{ @@ -77,6 +79,7 @@ func startEvacuateShard(cmd *cobra.Command, _ []string) { Scope: getEvacuationScope(cmd), ContainerWorkerCount: containerWorkerCount, ObjectWorkerCount: objectWorkerCount, + RepOneOnly: repOneOnly, }, } @@ -380,6 +383,7 @@ func initControlStartEvacuationShardCmd() { flags.Bool(noProgressFlag, false, fmt.Sprintf("Print progress if %s provided", awaitFlag)) flags.Uint32(containerWorkerCountFlag, 0, "Count of concurrent container evacuation workers") flags.Uint32(objectWorkerCountFlag, 0, "Count of concurrent object evacuation workers") + flags.Bool(repOneOnlyFlag, false, "Evacuate objects only from containers with policy 'REP 1 ...'") startEvacuationShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag) } diff --git a/docs/evacuation.md b/docs/evacuation.md index 885ce169a7..d47d56d150 100644 --- a/docs/evacuation.md +++ b/docs/evacuation.md @@ -20,7 +20,12 @@ Because it is necessary to prevent removing by policer objects with policy `REP ## Commands -`frostfs-cli control shards evacuation start` starts evacuation process for shards specified. To start evacuating all node shards, use the `--all` flag. By default, objects and trees are evacuated. To limit the evacuation scope, use `--scope` flag (possible values are `all`, `trees`, `objects`). +`frostfs-cli control shards evacuation start` starts evacuation process for shards specified. To start evacuating all node shards, use the `--all` flag. +By default, objects and trees are evacuated. To limit the evacuation scope, use `--scope` flag (possible values are `all`, `trees`, `objects`). +To evacuate objects only from containers with policy `REP 1` use option `--rep-one-only`. +To adjust resource consumption required for evacuation use options: + - `--container-worker-count` count of concurrent container evacuation workers + - `--object-worker-count` count of concurrent object evacuation workers `frostfs-cli control shards evacuation stop` stops running evacuation process. diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 3db556a8fa..a618ff2740 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -9,6 +9,7 @@ import ( "sync/atomic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" @@ -16,6 +17,7 @@ import ( tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -88,6 +90,7 @@ type EvacuateShardPrm struct { IgnoreErrors bool Async bool Scope EvacuateScope + RepOneOnly bool ContainerWorkerCount uint32 ObjectWorkerCount uint32 @@ -288,6 +291,7 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p attribute.Bool("async", prm.Async), attribute.Bool("ignoreErrors", prm.IgnoreErrors), attribute.Stringer("scope", prm.Scope), + attribute.Bool("repOneOnly", prm.RepOneOnly), )) defer func() { @@ -430,13 +434,34 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context ) error { sh := shardsToEvacuate[shardID] var cntPrm shard.IterateOverContainersPrm - cntPrm.Handler = func(ctx context.Context, name []byte, _ cid.ID) error { + cntPrm.Handler = func(ctx context.Context, name []byte, cnt cid.ID) error { select { case <-ctx.Done(): return context.Cause(ctx) default: } egContainer.Go(func() error { + var skip bool + c, err := e.containerSource.Load().cs.Get(cnt) + if err != nil { + if client.IsErrContainerNotFound(err) { + skip = true + } else { + return err + } + } + if !skip && prm.RepOneOnly { + skip = e.isNotRepOne(c) + } + if skip { + countPrm := shard.CountAliveObjectsInBucketPrm{BucketName: name} + count, err := sh.CountAliveObjectsInBucket(ctx, countPrm) + if err != nil { + return err + } + res.objSkipped.Add(count) + return nil + } var objPrm shard.IterateOverObjectsInContainerPrm objPrm.BucketName = name objPrm.Handler = func(ctx context.Context, objInfo *object.Info) error { @@ -454,7 +479,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context }) return nil } - err := sh.IterateOverObjectsInContainer(ctx, objPrm) + err = sh.IterateOverObjectsInContainer(ctx, objPrm) if err != nil { cancel(err) } @@ -781,6 +806,16 @@ func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objI return nil } +func (e *StorageEngine) isNotRepOne(c *container.Container) bool { + p := c.Value.PlacementPolicy() + for i := range p.NumberOfReplicas() { + if p.ReplicaDescriptor(i).NumberOfObjects() > 1 { + return true + } + } + return false +} + func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Address, object *objectSDK.Object, sh *shard.Shard, shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes, ) (bool, error) { diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index f723333999..8498c92455 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + coreContainer "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" @@ -20,14 +21,38 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" ) +type containerStorage struct { + cntmap map[cid.ID]*container.Container + latency time.Duration +} + +func (cs *containerStorage) Get(id cid.ID) (*coreContainer.Container, error) { + time.Sleep(cs.latency) + v, ok := cs.cntmap[id] + if !ok { + return nil, new(apistatus.ContainerNotFound) + } + coreCnt := coreContainer.Container{ + Value: *v, + } + return &coreCnt, nil +} + +func (cs *containerStorage) DeletionInfo(cid.ID) (*coreContainer.DelInfo, error) { + return nil, nil +} + func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEngine, []*shard.ID, []*objectSDK.Object) { dir := t.TempDir() @@ -61,10 +86,15 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng {Key: pilorama.AttributeVersion, Value: []byte("XXX")}, {Key: pilorama.AttributeFilename, Value: []byte("file.txt")}, } - + cnrMap := make(map[cid.ID]*container.Container) for _, sh := range ids { - for range objPerShard { + for i := range objPerShard { + // Create dummy container + cnr1 := container.Container{} + cnr1.SetAttribute("cnr", "cnr"+strconv.Itoa(i)) contID := cidtest.ID() + cnrMap[contID] = &cnr1 + obj := testutil.GenerateObjectWithCID(contID) objects = append(objects, obj) @@ -78,6 +108,7 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng require.NoError(t, err) } } + e.SetContainerSource(&containerStorage{cntmap: cnrMap}) return e, ids, objects } @@ -177,7 +208,10 @@ func TestEvacuateObjectsNetwork(t *testing.T) { acceptOneOf := func(objects []*objectSDK.Object, max uint64) func(context.Context, oid.Address, *objectSDK.Object) (bool, error) { var n atomic.Uint64 + var mtx sync.Mutex return func(_ context.Context, addr oid.Address, obj *objectSDK.Object) (bool, error) { + mtx.Lock() + defer mtx.Unlock() if n.Load() == max { return false, errReplication } @@ -640,3 +674,146 @@ func TestEvacuateTreesRemote(t *testing.T) { require.Equal(t, expectedTreeOps, evacuatedTreeOps) } + +func TestEvacuateShardObjectsRepOneOnly(t *testing.T) { + e, ids, _ := newEngineEvacuate(t, 2, 0) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() + + // Create container with policy REP 2 + cnr1 := container.Container{} + p1 := netmap.PlacementPolicy{} + p1.SetContainerBackupFactor(1) + x1 := netmap.ReplicaDescriptor{} + x1.SetNumberOfObjects(2) + p1.AddReplicas(x1) + x1 = netmap.ReplicaDescriptor{} + x1.SetNumberOfObjects(1) + p1.AddReplicas(x1) + cnr1.SetPlacementPolicy(p1) + cnr1.SetAttribute("cnr", "cnr1") + + var idCnr1 cid.ID + container.CalculateID(&idCnr1, cnr1) + + cnrmap := make(map[cid.ID]*container.Container) + var cids []cid.ID + cnrmap[idCnr1] = &cnr1 + cids = append(cids, idCnr1) + + // Create container with policy REP 1 + cnr2 := container.Container{} + p2 := netmap.PlacementPolicy{} + p2.SetContainerBackupFactor(1) + x2 := netmap.ReplicaDescriptor{} + x2.SetNumberOfObjects(1) + p2.AddReplicas(x2) + x2 = netmap.ReplicaDescriptor{} + x2.SetNumberOfObjects(1) + p2.AddReplicas(x2) + cnr2.SetPlacementPolicy(p2) + cnr2.SetAttribute("cnr", "cnr2") + + var idCnr2 cid.ID + container.CalculateID(&idCnr2, cnr2) + cnrmap[idCnr2] = &cnr2 + cids = append(cids, idCnr2) + + // Create container for simulate removing + cnr3 := container.Container{} + p3 := netmap.PlacementPolicy{} + p3.SetContainerBackupFactor(1) + x3 := netmap.ReplicaDescriptor{} + x3.SetNumberOfObjects(1) + p3.AddReplicas(x3) + cnr3.SetPlacementPolicy(p3) + cnr3.SetAttribute("cnr", "cnr3") + + var idCnr3 cid.ID + container.CalculateID(&idCnr3, cnr3) + cids = append(cids, idCnr3) + + e.SetContainerSource(&containerStorage{cntmap: cnrmap}) + + for _, sh := range ids { + for j := range 3 { + for range 4 { + obj := testutil.GenerateObjectWithCID(cids[j]) + var putPrm shard.PutPrm + putPrm.SetObject(obj) + _, err := e.shards[sh.String()].Put(context.Background(), putPrm) + require.NoError(t, err) + } + } + } + + var prm EvacuateShardPrm + prm.ShardID = ids[0:1] + prm.Scope = EvacuateScopeObjects + prm.RepOneOnly = true + + require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) + + res, err := e.Evacuate(context.Background(), prm) + require.NoError(t, err) + require.Equal(t, uint64(4), res.ObjectsEvacuated()) + require.Equal(t, uint64(8), res.ObjectsSkipped()) + require.Equal(t, uint64(0), res.ObjectsFailed()) +} + +func TestEvacuateShardObjectsRepOneOnlyBench(t *testing.T) { + t.Skip() + e, ids, _ := newEngineEvacuate(t, 2, 0) + defer func() { + require.NoError(t, e.Close(context.Background())) + }() + + cnrmap := make(map[cid.ID]*container.Container) + var cids []cid.ID + // Create containers with policy REP 1 + for i := range 10_000 { + cnr1 := container.Container{} + p1 := netmap.PlacementPolicy{} + p1.SetContainerBackupFactor(1) + x1 := netmap.ReplicaDescriptor{} + x1.SetNumberOfObjects(2) + p1.AddReplicas(x1) + cnr1.SetPlacementPolicy(p1) + cnr1.SetAttribute("i", strconv.Itoa(i)) + + var idCnr1 cid.ID + container.CalculateID(&idCnr1, cnr1) + + cnrmap[idCnr1] = &cnr1 + cids = append(cids, idCnr1) + } + + e.SetContainerSource(&containerStorage{ + cntmap: cnrmap, + latency: time.Millisecond * 100, + }) + + for _, cnt := range cids { + for range 1 { + obj := testutil.GenerateObjectWithCID(cnt) + var putPrm shard.PutPrm + putPrm.SetObject(obj) + _, err := e.shards[ids[0].String()].Put(context.Background(), putPrm) + require.NoError(t, err) + } + } + + var prm EvacuateShardPrm + prm.ShardID = ids[0:1] + prm.Scope = EvacuateScopeObjects + prm.RepOneOnly = true + prm.ContainerWorkerCount = 10 + + require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) + + start := time.Now() + _, err := e.Evacuate(context.Background(), prm) + t.Logf("evacuate took %v\n", time.Since(start)) + require.NoError(t, err) +} diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 5943be7f4d..44f25246e6 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -76,6 +76,12 @@ type IterateOverObjectsInContainerPrm struct { Handler func(context.Context, *objectcore.Info) error } +// CountAliveObjectsInBucketPrm contains parameters for IterateOverObjectsInContainer operation. +type CountAliveObjectsInBucketPrm struct { + // BucketName container's bucket name. + BucketName []byte +} + // ListWithCursor lists physical objects available in metabase starting from // cursor. Includes objects of all types. Does not include inhumed objects. // Use cursor value from response for consecutive requests. @@ -426,3 +432,48 @@ func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, c } return nil } + +// CountAliveObjectsInBucket count objects in bucket which aren't in graveyard or garbage. +func (db *DB) CountAliveObjectsInBucket(ctx context.Context, prm CountAliveObjectsInBucketPrm) (uint64, error) { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + db.metrics.AddMethodDuration("CountAliveObjectsInBucket", time.Since(startedAt), success) + }() + _, span := tracing.StartSpanFromContext(ctx, "metabase.CountAliveObjectsInBucket") + defer span.End() + + db.modeMtx.RLock() + defer db.modeMtx.RUnlock() + + if db.mode.NoMetabase() { + return 0, ErrDegradedMode + } + + cidRaw := prm.BucketName[1:bucketKeySize] + if cidRaw == nil { + return 0, nil + } + var count uint64 + err := db.boltDB.View(func(tx *bbolt.Tx) error { + bkt := tx.Bucket(prm.BucketName) + if bkt == nil { + return nil + } + graveyardBkt := tx.Bucket(graveyardBucketName) + garbageBkt := tx.Bucket(garbageBucketName) + c := bkt.Cursor() + k, _ := c.First() + for ; k != nil; k, _ = c.Next() { + if inGraveyardWithKey(append(cidRaw, k...), graveyardBkt, garbageBkt) > 0 { + continue + } + count++ + } + return nil + }) + success = err == nil + return count, metaerr.Wrap(err) +} diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index 9f56ec7509..f5d633b775 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -44,10 +44,16 @@ type IterateOverContainersPrm struct { type IterateOverObjectsInContainerPrm struct { // BucketName container's bucket name. BucketName []byte - // Handler function executed upon containers in db. + // Handler function executed upon objects in db. Handler func(context.Context, *objectcore.Info) error } +// CountAliveObjectsInBucketPrm contains parameters for CountAliveObjectsInBucket operation. +type CountAliveObjectsInBucketPrm struct { + // BucketName container's bucket name. + BucketName []byte +} + // ListWithCursorPrm contains parameters for ListWithCursor operation. type ListWithCursorPrm struct { count uint32 @@ -229,3 +235,25 @@ func (s *Shard) IterateOverObjectsInContainer(ctx context.Context, prm IterateOv return nil } + +// CountAliveObjectsInBucket count objects in bucket which aren't in graveyard or garbage. +func (s *Shard) CountAliveObjectsInBucket(ctx context.Context, prm CountAliveObjectsInBucketPrm) (uint64, error) { + _, span := tracing.StartSpanFromContext(ctx, "shard.CountAliveObjectsInBucket") + defer span.End() + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { + return 0, ErrDegradedMode + } + + var metaPrm meta.CountAliveObjectsInBucketPrm + metaPrm.BucketName = prm.BucketName + count, err := s.metaBase.CountAliveObjectsInBucket(ctx, metaPrm) + if err != nil { + return 0, fmt.Errorf("could not count alive objects in bucket: %w", err) + } + + return count, nil +} diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index bdc6f7c387..146ac7e16e 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -31,6 +31,7 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha Scope: engine.EvacuateScope(req.GetBody().GetScope()), ContainerWorkerCount: req.GetBody().GetContainerWorkerCount(), ObjectWorkerCount: req.GetBody().GetObjectWorkerCount(), + RepOneOnly: req.GetBody().GetRepOneOnly(), } _, err = s.s.Evacuate(ctx, prm) diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 88a06de229..ae1939e137 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -398,6 +398,8 @@ message StartShardEvacuationRequest { uint32 container_worker_count = 4; // Count of concurrent object evacuation workers. uint32 object_worker_count = 5; + // Choose for evacuation objects in `REP 1` containers only. + bool rep_one_only = 6; } Body body = 1; diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index e92a8acd1f..e16f082b13 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -6516,6 +6516,7 @@ type StartShardEvacuationRequest_Body struct { Scope uint32 `json:"scope"` ContainerWorkerCount uint32 `json:"containerWorkerCount"` ObjectWorkerCount uint32 `json:"objectWorkerCount"` + RepOneOnly bool `json:"repOneOnly"` } var ( @@ -6537,6 +6538,7 @@ func (x *StartShardEvacuationRequest_Body) StableSize() (size int) { size += proto.UInt32Size(3, x.Scope) size += proto.UInt32Size(4, x.ContainerWorkerCount) size += proto.UInt32Size(5, x.ObjectWorkerCount) + size += proto.BoolSize(6, x.RepOneOnly) return size } @@ -6568,6 +6570,9 @@ func (x *StartShardEvacuationRequest_Body) EmitProtobuf(mm *easyproto.MessageMar if x.ObjectWorkerCount != 0 { mm.AppendUint32(5, x.ObjectWorkerCount) } + if x.RepOneOnly { + mm.AppendBool(6, x.RepOneOnly) + } } // UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. @@ -6609,6 +6614,12 @@ func (x *StartShardEvacuationRequest_Body) UnmarshalProtobuf(src []byte) (err er return fmt.Errorf("cannot unmarshal field %s", "ObjectWorkerCount") } x.ObjectWorkerCount = data + case 6: // RepOneOnly + data, ok := fc.Bool() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "RepOneOnly") + } + x.RepOneOnly = data } } return nil @@ -6658,6 +6669,15 @@ func (x *StartShardEvacuationRequest_Body) GetObjectWorkerCount() uint32 { func (x *StartShardEvacuationRequest_Body) SetObjectWorkerCount(v uint32) { x.ObjectWorkerCount = v } +func (x *StartShardEvacuationRequest_Body) GetRepOneOnly() bool { + if x != nil { + return x.RepOneOnly + } + return false +} +func (x *StartShardEvacuationRequest_Body) SetRepOneOnly(v bool) { + x.RepOneOnly = v +} // MarshalJSON implements the json.Marshaler interface. func (x *StartShardEvacuationRequest_Body) MarshalJSON() ([]byte, error) { @@ -6703,6 +6723,11 @@ func (x *StartShardEvacuationRequest_Body) MarshalEasyJSON(out *jwriter.Writer) out.RawString(prefix) out.Uint32(x.ObjectWorkerCount) } + { + const prefix string = ",\"repOneOnly\":" + out.RawString(prefix) + out.Bool(x.RepOneOnly) + } out.RawByte('}') } @@ -6768,6 +6793,12 @@ func (x *StartShardEvacuationRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { f = in.Uint32() x.ObjectWorkerCount = f } + case "repOneOnly": + { + var f bool + f = in.Bool() + x.RepOneOnly = f + } } in.WantComma() } From 7f8a1dcf8e238a08af84a1ef9e180541f783b71f Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 30 Sep 2024 14:15:13 +0300 Subject: [PATCH 0866/1413] [#1400] adm: Support flag `alphabet-wallets` for commands `proxy-add/remove-account` Signed-off-by: Anton Nikiforov --- cmd/frostfs-adm/internal/modules/morph/proxy/root.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go index 082bc57d1b..1854c8d2b9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go @@ -30,11 +30,13 @@ var ( func initProxyAddAccount() { AddAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) AddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") + AddAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initProxyRemoveAccount() { RemoveAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) RemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") + RemoveAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func init() { From a13219808a42f30839fe87ba3ea88a8fdd54f0ac Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 27 Sep 2024 12:39:43 +0300 Subject: [PATCH 0867/1413] [#1375] node: Configure of the container cache size Signed-off-by: Alexander Chuprov --- cmd/frostfs-node/cache.go | 8 ++-- cmd/frostfs-node/config.go | 2 + cmd/frostfs-node/config/morph/config.go | 15 ++++++ cmd/frostfs-node/container.go | 63 +++++++++++++------------ cmd/frostfs-node/morph.go | 1 + config/example/node.yaml | 1 + 6 files changed, 55 insertions(+), 35 deletions(-) diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index 57f65d8735..06142a46ce 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -165,13 +165,11 @@ type ttlContainerStorage struct { delInfoCache *ttlNetCache[cid.ID, *container.DelInfo] } -func newCachedContainerStorage(v container.Source, ttl time.Duration) ttlContainerStorage { - const containerCacheSize = 100 - - lruCnrCache := newNetworkTTLCache(containerCacheSize, ttl, func(id cid.ID) (*container.Container, error) { +func newCachedContainerStorage(v container.Source, ttl time.Duration, containerCacheSize uint32) ttlContainerStorage { + lruCnrCache := newNetworkTTLCache(int(containerCacheSize), ttl, func(id cid.ID) (*container.Container, error) { return v.Get(id) }, metrics.NewCacheMetrics("container")) - lruDelInfoCache := newNetworkTTLCache(containerCacheSize, ttl, func(id cid.ID) (*container.DelInfo, error) { + lruDelInfoCache := newNetworkTTLCache(int(containerCacheSize), ttl, func(id cid.ID) (*container.DelInfo, error) { return v.DeletionInfo(id) }, metrics.NewCacheMetrics("container_deletion_info")) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index c625b575fb..58a96879f3 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -570,6 +570,8 @@ type cfgMorph struct { // TTL of Sidechain cached values. Non-positive value disables caching. cacheTTL time.Duration + containerCacheSize uint32 + proxyScriptHash neogoutil.Uint160 } diff --git a/cmd/frostfs-node/config/morph/config.go b/cmd/frostfs-node/config/morph/config.go index 1c536a0e26..d089870eae 100644 --- a/cmd/frostfs-node/config/morph/config.go +++ b/cmd/frostfs-node/config/morph/config.go @@ -30,6 +30,9 @@ const ( // FrostfsIDCacheSizeDefault is a default value of APE chain cache. FrostfsIDCacheSizeDefault = 10_000 + + // ContainerCacheSizeDefault represents the default size for the container cache. + ContainerCacheSizeDefault = 100 ) var errNoMorphEndpoints = errors.New("no morph chain RPC endpoints, see `morph.rpc_endpoint` section") @@ -103,6 +106,18 @@ func CacheTTL(c *config.Config) time.Duration { return CacheTTLDefault } +// ContainerCacheSize returns the value of "container_cache_size" config parameter +// from "morph" section. +// +// Returns 0 if the value is not positive integer. +// Returns ContainerCacheSizeDefault if the value is missing. +func ContainerCacheSize(c *config.Config) uint32 { + if c.Sub(subsection).Value("container_cache_size") == nil { + return ContainerCacheSizeDefault + } + return config.Uint32Safe(c.Sub(subsection), "container_cache_size") +} + // SwitchInterval returns the value of "switch_interval" config parameter // from "morph" section. // diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 6733140d21..729fcb8afa 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -87,43 +87,46 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c cnrRdr.lister = client } else { // use RPC node as source of Container contract items (with caching) - cachedContainerStorage := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL) - cachedEACLStorage := newCachedEACLStorage(eACLFetcher, c.cfgMorph.cacheTTL) + c.cfgObject.cnrSource = cnrSrc + if c.cfgMorph.containerCacheSize > 0 { + containerCache := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL, c.cfgMorph.containerCacheSize) - subscribeToContainerCreation(c, func(e event.Event) { - ev := e.(containerEvent.PutSuccess) + subscribeToContainerCreation(c, func(e event.Event) { + ev := e.(containerEvent.PutSuccess) - // read owner of the created container in order to update the reading cache. - // TODO: use owner directly from the event after neofs-contract#256 will become resolved - // but don't forget about the profit of reading the new container and caching it: - // creation success are most commonly tracked by polling GET op. - cnr, err := cnrSrc.Get(ev.ID) - if err == nil { - cachedContainerStorage.containerCache.set(ev.ID, cnr, nil) - } else { - // unlike removal, we expect successful receive of the container - // after successful creation, so logging can be useful - c.log.Error(logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification, + // read owner of the created container in order to update the reading cache. + // TODO: use owner directly from the event after neofs-contract#256 will become resolved + // but don't forget about the profit of reading the new container and caching it: + // creation success are most commonly tracked by polling GET op. + cnr, err := cnrSrc.Get(ev.ID) + if err == nil { + containerCache.containerCache.set(ev.ID, cnr, nil) + } else { + // unlike removal, we expect successful receive of the container + // after successful creation, so logging can be useful + c.log.Error(logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification, + zap.Stringer("id", ev.ID), + zap.Error(err), + ) + } + + c.log.Debug(logs.FrostFSNodeContainerCreationEventsReceipt, zap.Stringer("id", ev.ID), - zap.Error(err), ) - } + }) - c.log.Debug(logs.FrostFSNodeContainerCreationEventsReceipt, - zap.Stringer("id", ev.ID), - ) - }) - - subscribeToContainerRemoval(c, func(e event.Event) { - ev := e.(containerEvent.DeleteSuccess) - cachedContainerStorage.handleRemoval(ev.ID) - c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt, - zap.Stringer("id", ev.ID), - ) - }) + subscribeToContainerRemoval(c, func(e event.Event) { + ev := e.(containerEvent.DeleteSuccess) + containerCache.handleRemoval(ev.ID) + c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt, + zap.Stringer("id", ev.ID), + ) + }) + c.cfgObject.cnrSource = containerCache + } + cachedEACLStorage := newCachedEACLStorage(eACLFetcher, c.cfgMorph.cacheTTL) c.cfgObject.eaclSource = cachedEACLStorage - c.cfgObject.cnrSource = cachedContainerStorage cnrRdr.lister = client cnrRdr.eacl = c.cfgObject.eaclSource diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 7178cd97d7..1bfcb8ac9a 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -90,6 +90,7 @@ func initMorphComponents(ctx context.Context, c *cfg) { var netmapSource netmap.Source + c.cfgMorph.containerCacheSize = morphconfig.ContainerCacheSize(c.appCfg) c.cfgMorph.cacheTTL = morphconfig.CacheTTL(c.appCfg) if c.cfgMorph.cacheTTL == 0 { diff --git a/config/example/node.yaml b/config/example/node.yaml index 86be35ba85..2a80fba182 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -81,6 +81,7 @@ morph: cache_ttl: 15s # Sidechain cache TTL value (min interval between similar calls). Negative value disables caching. # Default value: block time. It is recommended to have this value less or equal to block time. # Cached entities: containers, container lists, eACL tables. + container_cache_size: 100 # container_cache_size is is the maximum number of containers in the cache. switch_interval: 3m # interval b/w RPC switch attempts if the node is connected not to the highest priority node rpc_endpoint: # side chain NEO RPC endpoints; are shuffled and used one by one until the first success - address: wss://rpc1.morph.frostfs.info:40341/ws From 54eb0058229965b7ddd704fe4da2e24f41c20f3f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 1 Oct 2024 14:39:36 +0300 Subject: [PATCH 0868/1413] [#1404] go.mod: Update api-go Fix #1398 Fix #1399 Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9817f85278..1023948bc1 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241001111852-d9a604fbc16f git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d diff --git a/go.sum b/go.sum index 3c6dd9a99b..5d719a0274 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e h1:740ABnOBYx4o6jxULHdSSnVW2fYIO35ohg+Uz59sxd0= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240916093537-13fa0da3741e/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241001111852-d9a604fbc16f h1:FZvX6CLzTQqMyMvOerIKMvIEJQbOImDjSooZx3AVRyE= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241001111852-d9a604fbc16f/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c h1:9JmXxWcqWaOXModBwtj/WlPYOfSk2jRSDoRsDRYvgnA= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c/go.mod h1:DVb1AqP323wiEwCtlfoJJTERF4Xji2L39X6T8kv26RE= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= From 9c5ddc4dfeb6447ae7d9cc0d74db551271ac6eb1 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 2 Oct 2024 10:09:10 +0300 Subject: [PATCH 0869/1413] [#1407] tree: Set `ContainerOwner` in parameter for `CheckAPE` Signed-off-by: Airat Arifullin --- pkg/services/tree/ape.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 693b16e605..69cf594056 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -75,12 +75,13 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, } return s.apeChecker.CheckAPE(checkercore.CheckPrm{ - Request: request, - Namespace: namespace, - Container: cid, - PublicKey: publicKey, - BearerToken: bt, - SoftAPECheck: false, + Request: request, + Namespace: namespace, + Container: cid, + ContainerOwner: container.Value.Owner(), + PublicKey: publicKey, + BearerToken: bt, + SoftAPECheck: false, }) } From 57c31e9802ad19b8d64388315cd53a05515e353e Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 1 Oct 2024 16:09:05 +0300 Subject: [PATCH 0870/1413] [#1306] node: Allow tombstone_lifetime config to be loaded on the fly Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-node/config.go | 17 +++++++++++++++-- cmd/frostfs-node/object.go | 6 ++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 58a96879f3..4ad9ec6c62 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -105,6 +105,10 @@ type applicationConfiguration struct { timestamp bool } + ObjectCfg struct { + tombstoneLifetime uint64 + } + EngineCfg struct { errorThreshold uint32 shardPoolSize uint32 @@ -223,6 +227,10 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { a.LoggerCfg.destination = loggerconfig.Destination(c) a.LoggerCfg.timestamp = loggerconfig.Timestamp(c) + // Object + + a.ObjectCfg.tombstoneLifetime = objectconfig.TombstoneLifetime(c) + // Storage Engine a.EngineCfg.errorThreshold = engineconfig.ShardErrorThreshold(c) @@ -624,7 +632,7 @@ type cfgObject struct { cfgLocalStorage cfgLocalStorage - tombstoneLifetime uint64 + tombstoneLifetime *atomic.Uint64 skipSessionTokenIssuerVerification bool } @@ -815,9 +823,11 @@ func initCfgGRPC() cfgGRPC { } func initCfgObject(appCfg *config.Config) cfgObject { + var tsLifetime atomic.Uint64 + tsLifetime.Store(objectconfig.TombstoneLifetime(appCfg)) return cfgObject{ pool: initObjectPool(appCfg), - tombstoneLifetime: objectconfig.TombstoneLifetime(appCfg), + tombstoneLifetime: &tsLifetime, skipSessionTokenIssuerVerification: objectconfig.Put(appCfg).SkipSessionTokenIssuerVerification(), } } @@ -1296,6 +1306,9 @@ func (c *cfg) reloadConfig(ctx context.Context) { components := c.getComponents(ctx, logPrm) + // Object + c.cfgObject.tombstoneLifetime.Store(c.ObjectCfg.tombstoneLifetime) + // Storage Engine var rcfg engine.ReConfiguration diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 9d4e35ca8c..47649c88ba 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -109,13 +109,12 @@ func (s *objectSvc) GetRangeHash(ctx context.Context, req *object.GetRangeHashRe type delNetInfo struct { netmap.State - tsLifetime uint64 cfg *cfg } func (i *delNetInfo) TombstoneLifetime() (uint64, error) { - return i.tsLifetime, nil + return i.cfg.cfgObject.tombstoneLifetime.Load(), nil } // returns node owner ID calculated from configured private key. @@ -424,8 +423,7 @@ func createDeleteService(c *cfg, keyStorage *util.KeyStorage, sGet *getsvc.Servi sSearch, sPut, &delNetInfo{ - State: c.cfgNetmap.state, - tsLifetime: c.cfgObject.tombstoneLifetime, + State: c.cfgNetmap.state, cfg: c, }, From f45e75e3eb781662abbbc4f6820076c492fc1f0d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 2 Oct 2024 11:18:35 +0300 Subject: [PATCH 0871/1413] [#1409] adm: Do not bind DeltaFlag to viper We bind flag that could be specified in config. This is not a config flag, just a command option. Also fix TestInitialize failures: ``` Error: Received unexpected error: number of epochs cannot be less than 1 Test: TestInitialize/16_nodes/force-new-epoch ``` Refs #1372 (945b7c740b0deb4) Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go | 3 ++- cmd/frostfs-adm/internal/modules/morph/netmap/root.go | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index 5e4e9c7259..5c5fa99881 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -31,7 +31,8 @@ func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { } bw := io.NewBufBinWriter() - if err := helper.EmitNewEpochCall(bw, wCtx, nmHash, viper.GetInt64(commonflags.DeltaFlag)); err != nil { + delta, _ := cmd.Flags().GetInt64(commonflags.DeltaFlag) + if err := helper.EmitNewEpochCall(bw, wCtx, nmHash, delta); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go index 0288bcdc54..3300db36aa 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go @@ -22,7 +22,6 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) - _ = viper.BindPFlag(commonflags.DeltaFlag, cmd.Flags().Lookup(commonflags.DeltaFlag)) }, RunE: ForceNewEpochCmd, } From 62028cd7ee0b5d825b71cfa11d1d87369b1da23d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 2 Oct 2024 11:20:09 +0300 Subject: [PATCH 0872/1413] [#1409] adm: Uncommonize DeltaFlag It is used only in `force-new-epoch`, it is not _common_ between multiple commands. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/commonflags/flags.go | 1 - cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go | 5 +++-- cmd/frostfs-adm/internal/modules/morph/netmap/root.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-adm/internal/commonflags/flags.go b/cmd/frostfs-adm/internal/commonflags/flags.go index b51d2e1156..81395edb0f 100644 --- a/cmd/frostfs-adm/internal/commonflags/flags.go +++ b/cmd/frostfs-adm/internal/commonflags/flags.go @@ -39,5 +39,4 @@ const ( CustomZoneFlag = "domain" AlphabetSizeFlag = "size" AllFlag = "all" - DeltaFlag = "delta" ) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go index 5c5fa99881..94223dbd09 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/epoch.go @@ -4,7 +4,6 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "github.com/nspcc-dev/neo-go/pkg/io" @@ -13,6 +12,8 @@ import ( "github.com/spf13/viper" ) +const deltaFlag = "delta" + func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { @@ -31,7 +32,7 @@ func ForceNewEpochCmd(cmd *cobra.Command, _ []string) error { } bw := io.NewBufBinWriter() - delta, _ := cmd.Flags().GetInt64(commonflags.DeltaFlag) + delta, _ := cmd.Flags().GetInt64(deltaFlag) if err := helper.EmitNewEpochCall(bw, wCtx, nmHash, delta); err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go index 3300db36aa..55b7e64f02 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go @@ -35,7 +35,7 @@ func initForceNewEpochCmd() { ForceNewEpoch.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) ForceNewEpoch.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) ForceNewEpoch.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") - ForceNewEpoch.Flags().Int64(commonflags.DeltaFlag, 1, "Number of epochs to increase the current epoch") + ForceNewEpoch.Flags().Int64(deltaFlag, 1, "Number of epochs to increase the current epoch") } func init() { From f83f7feb8caa0ef5ab9a952a6a6d3e2f12a63486 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 2 Oct 2024 11:01:22 +0300 Subject: [PATCH 0873/1413] [#1391] adm: Properly check whether transfers were made Signed-off-by: Evgenii Stratonikov --- .../morph/initialize/initialize_transfer.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go index d7b0ec86c5..7f1bfee2b0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go @@ -27,12 +27,12 @@ const ( initialAlphabetGASAmount = 10_000 * native.GASFactor // initialProxyGASAmount represents the amount of GAS given to a proxy contract. initialProxyGASAmount = 50_000 * native.GASFactor - // alphabetGasRatio is a coefficient that defines the threshold below which - // the balance of the alphabet node is considered not replenished. The value - // of this coefficient is determined empirically. - alphabetGasRatio = 5 ) +func initialCommitteeGASAmount(c *helper.InitializeContext) int64 { + return (gasInitialTotalSupply - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2 +} + func transferFunds(c *helper.InitializeContext) error { ok, err := transferFundsFinished(c) if ok || err != nil { @@ -59,7 +59,7 @@ func transferFunds(c *helper.InitializeContext) error { transferTarget{ Token: gas.Hash, Address: c.CommitteeAcc.Contract.ScriptHash(), - Amount: (gasInitialTotalSupply - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2, + Amount: initialCommitteeGASAmount(c), }, transferTarget{ Token: neo.Hash, @@ -80,12 +80,19 @@ func transferFunds(c *helper.InitializeContext) error { return c.AwaitTx() } +// transferFundsFinished checks balances of accounts we transfer GAS to. +// The stage is considered finished if the balance is greater than the half of what we need to transfer. func transferFundsFinished(c *helper.InitializeContext) (bool, error) { acc := c.Accounts[0] r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) res, err := r.BalanceOf(acc.Contract.ScriptHash()) - return res.Cmp(big.NewInt(alphabetGasRatio*native.GASFactor)) == 1, err + if err != nil || res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) != 1 { + return false, err + } + + res, err = r.BalanceOf(c.CommitteeAcc.ScriptHash()) + return res != nil && res.Cmp(big.NewInt(initialCommitteeGASAmount(c)/2)) == 1, err } func transferGASToProxy(c *helper.InitializeContext) error { From 434048e8d959b29375c0d63a112b8eb8df8792d8 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 2 Oct 2024 11:28:00 +0300 Subject: [PATCH 0874/1413] [#1408] metabase: Fix EC search with slow and fast filters Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/select.go | 35 ++++++++++++- .../metabase/select_test.go | 50 +++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index ed43fc41f9..85d1b08ba0 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -389,8 +389,7 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc return result, true } - buf := make([]byte, addressKeySize) - obj, err := db.get(tx, addr, buf, true, false, currEpoch) + obj, isECChunk, err := db.getObjectForSlowFilters(tx, addr, currEpoch) if err != nil { return result, false } @@ -401,17 +400,26 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc case v2object.FilterHeaderVersion: data = []byte(obj.Version().String()) case v2object.FilterHeaderHomomorphicHash: + if isECChunk { + return result, false // EC chunk and EC parent hashes are incomparable + } cs, _ := obj.PayloadHomomorphicHash() data = cs.Value() case v2object.FilterHeaderCreationEpoch: data = make([]byte, 8) binary.LittleEndian.PutUint64(data, obj.CreationEpoch()) case v2object.FilterHeaderPayloadLength: + if isECChunk { + return result, false // EC chunk and EC parent payload lengths are incomparable + } data = make([]byte, 8) binary.LittleEndian.PutUint64(data, obj.PayloadSize()) case v2object.FilterHeaderOwnerID: data = []byte(obj.OwnerID().EncodeToString()) case v2object.FilterHeaderPayloadHash: + if isECChunk { + return result, false // EC chunk and EC parent payload hashes are incomparable + } cs, _ := obj.PayloadChecksum() data = cs.Value() default: // user attribute @@ -439,6 +447,29 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc return result, true } +func (db *DB) getObjectForSlowFilters(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (*objectSDK.Object, bool, error) { + buf := make([]byte, addressKeySize) + obj, err := db.get(tx, addr, buf, true, false, currEpoch) + if err != nil { + var ecInfoError *objectSDK.ECInfoError + if errors.As(err, &ecInfoError) { + for _, chunk := range ecInfoError.ECInfo().Chunks { + var objID oid.ID + if err = objID.ReadFromV2(chunk.ID); err != nil { + continue + } + addr.SetObject(objID) + obj, err = db.get(tx, addr, buf, true, false, currEpoch) + if err == nil { + return obj, true, nil + } + } + } + return nil, false, err + } + return obj, false, nil +} + func attributeValue(obj *objectSDK.Object, attribute string) (string, bool) { objectAttributes := obj.Attributes() if ech := obj.ECHeader(); ech != nil { diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index fcd5d3a90c..0c6ebc8631 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -762,6 +762,56 @@ func TestDB_SelectOwnerID(t *testing.T) { }) } +func TestDB_SelectECWithFastAndSlowFilters(t *testing.T) { + t.Parallel() + + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + ecChunk1 := oidtest.ID() + ecChunk2 := oidtest.ID() + ecParent := oidtest.ID() + var ecParentAddr oid.Address + ecParentAddr.SetContainer(cnr) + ecParentAddr.SetObject(ecParent) + var ecParentAttr []objectSDK.Attribute + var attr objectSDK.Attribute + attr.SetKey(objectSDK.AttributeFilePath) + attr.SetValue("/1/2/3") + ecParentAttr = append(ecParentAttr, attr) + + chunkObj := testutil.GenerateObjectWithCID(cnr) + chunkObj.SetContainerID(cnr) + chunkObj.SetID(ecChunk1) + chunkObj.SetPayload([]byte{0, 1, 2, 3, 4}) + chunkObj.SetPayloadSize(uint64(5)) + chunkObj.SetECHeader(objectSDK.NewECHeader(objectSDK.ECParentInfo{ID: ecParent, Attributes: ecParentAttr}, 0, 3, []byte{}, 0)) + + chunkObj2 := testutil.GenerateObjectWithCID(cnr) + chunkObj2.SetContainerID(cnr) + chunkObj2.SetID(ecChunk2) + chunkObj2.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) + chunkObj2.SetPayloadSize(uint64(10)) + chunkObj2.SetECHeader(objectSDK.NewECHeader(objectSDK.ECParentInfo{ID: ecParent, Attributes: ecParentAttr}, 1, 3, []byte{}, 0)) + + // put object with EC + + var prm meta.PutPrm + prm.SetObject(chunkObj) + _, err := db.Put(context.Background(), prm) + require.NoError(t, err) + + prm.SetObject(chunkObj2) + _, err = db.Put(context.Background(), prm) + require.NoError(t, err) + + fs := objectSDK.SearchFilters{} + fs.AddRootFilter() + fs.AddFilter(objectSDK.AttributeFilePath, "/1/2/3", objectSDK.MatchCommonPrefix) + testSelect(t, db, cnr, fs, ecParentAddr) +} + type testTarget struct { objects []*objectSDK.Object } From 01e3944b31e7daed8ca855244b833302daabe9cc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 2 Oct 2024 14:36:10 +0300 Subject: [PATCH 0875/1413] [#1408] metabase: Fix tests No need to specify container ID for objects created with `testutil.GenerateObjectWithCID`. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete_ec_test.go | 1 - pkg/local_object_storage/metabase/inhume_ec_test.go | 2 -- pkg/local_object_storage/metabase/select_test.go | 2 -- 3 files changed, 5 deletions(-) diff --git a/pkg/local_object_storage/metabase/delete_ec_test.go b/pkg/local_object_storage/metabase/delete_ec_test.go index 66c79ecd7c..a256279904 100644 --- a/pkg/local_object_storage/metabase/delete_ec_test.go +++ b/pkg/local_object_storage/metabase/delete_ec_test.go @@ -39,7 +39,6 @@ func TestDeleteECObject_WithoutSplit(t *testing.T) { tombstoneID := oidtest.ID() chunkObj := testutil.GenerateObjectWithCID(cnr) - chunkObj.SetContainerID(cnr) chunkObj.SetID(ecChunk) chunkObj.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) chunkObj.SetPayloadSize(uint64(10)) diff --git a/pkg/local_object_storage/metabase/inhume_ec_test.go b/pkg/local_object_storage/metabase/inhume_ec_test.go index c3b1e72da2..32e412c795 100644 --- a/pkg/local_object_storage/metabase/inhume_ec_test.go +++ b/pkg/local_object_storage/metabase/inhume_ec_test.go @@ -35,14 +35,12 @@ func TestInhumeECObject(t *testing.T) { tombstoneID := oidtest.ID() chunkObj := testutil.GenerateObjectWithCID(cnr) - chunkObj.SetContainerID(cnr) chunkObj.SetID(ecChunk) chunkObj.SetPayload([]byte{0, 1, 2, 3, 4}) chunkObj.SetPayloadSize(uint64(5)) chunkObj.SetECHeader(objectSDK.NewECHeader(objectSDK.ECParentInfo{ID: ecParent}, 0, 3, []byte{}, 0)) chunkObj2 := testutil.GenerateObjectWithCID(cnr) - chunkObj2.SetContainerID(cnr) chunkObj2.SetID(ecChunk2) chunkObj2.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) chunkObj2.SetPayloadSize(uint64(10)) diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 0c6ebc8631..bee778e2b4 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -782,14 +782,12 @@ func TestDB_SelectECWithFastAndSlowFilters(t *testing.T) { ecParentAttr = append(ecParentAttr, attr) chunkObj := testutil.GenerateObjectWithCID(cnr) - chunkObj.SetContainerID(cnr) chunkObj.SetID(ecChunk1) chunkObj.SetPayload([]byte{0, 1, 2, 3, 4}) chunkObj.SetPayloadSize(uint64(5)) chunkObj.SetECHeader(objectSDK.NewECHeader(objectSDK.ECParentInfo{ID: ecParent, Attributes: ecParentAttr}, 0, 3, []byte{}, 0)) chunkObj2 := testutil.GenerateObjectWithCID(cnr) - chunkObj2.SetContainerID(cnr) chunkObj2.SetID(ecChunk2) chunkObj2.SetPayload([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) chunkObj2.SetPayloadSize(uint64(10)) From 6c46044c9cba5f2e20e105b3efa7abe166fbf577 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 3 Oct 2024 10:19:26 +0300 Subject: [PATCH 0876/1413] [#1410] shard: Move MetricsWriter interface to a separate file Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/metrics.go | 47 +++++++++++++++++++++++ pkg/local_object_storage/shard/shard.go | 44 --------------------- 2 files changed, 47 insertions(+), 44 deletions(-) create mode 100644 pkg/local_object_storage/shard/metrics.go diff --git a/pkg/local_object_storage/shard/metrics.go b/pkg/local_object_storage/shard/metrics.go new file mode 100644 index 0000000000..568c0de5e7 --- /dev/null +++ b/pkg/local_object_storage/shard/metrics.go @@ -0,0 +1,47 @@ +package shard + +import "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + +// MetricsWriter is an interface that must store shard's metrics. +type MetricsWriter interface { + // SetObjectCounter must set object counter taking into account object type. + SetObjectCounter(objectType string, v uint64) + // AddToObjectCounter must update object counter taking into account object + // type. + // Negative parameter must decrease the counter. + AddToObjectCounter(objectType string, delta int) + // AddToContainerSize must add a value to the container size. + // Value can be negative. + AddToContainerSize(cnr string, value int64) + // AddToPayloadSize must add a value to the payload size. + // Value can be negative. + AddToPayloadSize(value int64) + // IncObjectCounter must increment shard's object counter taking into account + // object type. + IncObjectCounter(objectType string) + // SetShardID must set (update) the shard identifier that will be used in + // metrics. + SetShardID(id string) + // SetReadonly must set shard mode. + SetMode(mode mode.Mode) + // IncErrorCounter increment error counter. + IncErrorCounter() + // ClearErrorCounter clear error counter. + ClearErrorCounter() + // DeleteShardMetrics deletes shard metrics from registry. + DeleteShardMetrics() + // SetContainerObjectsCount sets container object count. + SetContainerObjectsCount(cnrID string, objectType string, value uint64) + // IncContainerObjectsCount increments container object count. + IncContainerObjectsCount(cnrID string, objectType string) + // SubContainerObjectsCount subtracts container object count. + SubContainerObjectsCount(cnrID string, objectType string, value uint64) + // IncRefillObjectsCount increments refill objects count. + IncRefillObjectsCount(path string, size int, success bool) + // SetRefillPercent sets refill percent. + SetRefillPercent(path string, percent uint32) + // SetRefillStatus sets refill status. + SetRefillStatus(path string, status string) + // SetEvacuationInProgress sets evacuation status + SetEvacuationInProgress(value bool) +} diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 7496fc3527..f5317b16ce 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -57,50 +57,6 @@ type DeletedLockCallback func(context.Context, []oid.Address) // EmptyContainersCallback is a callback hanfling list of zero-size and zero-count containers. type EmptyContainersCallback func(context.Context, []cid.ID) -// MetricsWriter is an interface that must store shard's metrics. -type MetricsWriter interface { - // SetObjectCounter must set object counter taking into account object type. - SetObjectCounter(objectType string, v uint64) - // AddToObjectCounter must update object counter taking into account object - // type. - // Negative parameter must decrease the counter. - AddToObjectCounter(objectType string, delta int) - // AddToContainerSize must add a value to the container size. - // Value can be negative. - AddToContainerSize(cnr string, value int64) - // AddToPayloadSize must add a value to the payload size. - // Value can be negative. - AddToPayloadSize(value int64) - // IncObjectCounter must increment shard's object counter taking into account - // object type. - IncObjectCounter(objectType string) - // SetShardID must set (update) the shard identifier that will be used in - // metrics. - SetShardID(id string) - // SetReadonly must set shard mode. - SetMode(mode mode.Mode) - // IncErrorCounter increment error counter. - IncErrorCounter() - // ClearErrorCounter clear error counter. - ClearErrorCounter() - // DeleteShardMetrics deletes shard metrics from registry. - DeleteShardMetrics() - // SetContainerObjectsCount sets container object count. - SetContainerObjectsCount(cnrID string, objectType string, value uint64) - // IncContainerObjectsCount increments container object count. - IncContainerObjectsCount(cnrID string, objectType string) - // SubContainerObjectsCount subtracts container object count. - SubContainerObjectsCount(cnrID string, objectType string, value uint64) - // IncRefillObjectsCount increments refill objects count. - IncRefillObjectsCount(path string, size int, success bool) - // SetRefillPercent sets refill percent. - SetRefillPercent(path string, percent uint32) - // SetRefillStatus sets refill status. - SetRefillStatus(path string, status string) - // SetEvacuationInProgress sets evacuation status - SetEvacuationInProgress(value bool) -} - type cfg struct { m sync.RWMutex From 9206ce5cd2ea973feef6a53ae0453736efacbe11 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 3 Oct 2024 10:23:59 +0300 Subject: [PATCH 0877/1413] [#1410] shard: Provide the default implementation for MetricsWriter Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/id.go | 4 +- pkg/local_object_storage/shard/metrics.go | 22 ++++++++++ pkg/local_object_storage/shard/mode.go | 4 +- pkg/local_object_storage/shard/shard.go | 49 +++++++++-------------- 4 files changed, 42 insertions(+), 37 deletions(-) diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index 2fe68d2705..a723134989 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -45,9 +45,7 @@ func (s *Shard) UpdateID() (err error) { } shardID := s.info.ID.String() - if s.cfg.metricsWriter != nil { - s.cfg.metricsWriter.SetShardID(shardID) - } + s.cfg.metricsWriter.SetShardID(shardID) if s.writeCache != nil && s.writeCache.GetMetrics() != nil { s.writeCache.GetMetrics().SetShardID(shardID) } diff --git a/pkg/local_object_storage/shard/metrics.go b/pkg/local_object_storage/shard/metrics.go index 568c0de5e7..6bf198048d 100644 --- a/pkg/local_object_storage/shard/metrics.go +++ b/pkg/local_object_storage/shard/metrics.go @@ -45,3 +45,25 @@ type MetricsWriter interface { // SetEvacuationInProgress sets evacuation status SetEvacuationInProgress(value bool) } + +type noopMetrics struct{} + +var _ MetricsWriter = noopMetrics{} + +func (noopMetrics) SetObjectCounter(string, uint64) {} +func (noopMetrics) AddToObjectCounter(string, int) {} +func (noopMetrics) AddToContainerSize(string, int64) {} +func (noopMetrics) AddToPayloadSize(int64) {} +func (noopMetrics) IncObjectCounter(string) {} +func (noopMetrics) SetShardID(string) {} +func (noopMetrics) SetMode(mode.Mode) {} +func (noopMetrics) IncErrorCounter() {} +func (noopMetrics) ClearErrorCounter() {} +func (noopMetrics) DeleteShardMetrics() {} +func (noopMetrics) SetContainerObjectsCount(string, string, uint64) {} +func (noopMetrics) IncContainerObjectsCount(string, string) {} +func (noopMetrics) SubContainerObjectsCount(string, string, uint64) {} +func (noopMetrics) IncRefillObjectsCount(string, int, bool) {} +func (noopMetrics) SetRefillPercent(string, uint32) {} +func (noopMetrics) SetRefillStatus(string, string) {} +func (noopMetrics) SetEvacuationInProgress(bool) {} diff --git a/pkg/local_object_storage/shard/mode.go b/pkg/local_object_storage/shard/mode.go index 1bab574482..d90a5f4b69 100644 --- a/pkg/local_object_storage/shard/mode.go +++ b/pkg/local_object_storage/shard/mode.go @@ -65,9 +65,7 @@ func (s *Shard) setMode(m mode.Mode) error { } s.info.Mode = m - if s.metricsWriter != nil { - s.metricsWriter.SetMode(s.info.Mode) - } + s.metricsWriter.SetMode(s.info.Mode) s.log.Info(logs.ShardShardModeSetSuccessfully, zap.Stringer("mode", s.info.Mode)) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index f5317b16ce..a57b548be4 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -105,6 +105,7 @@ func defaultCfg() *cfg { reportErrorFunc: func(string, string, error) {}, zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, zeroCountContainersCallback: func(context.Context, []cid.ID) {}, + metricsWriter: noopMetrics{}, } } @@ -384,7 +385,7 @@ const ( ) func (s *Shard) updateMetrics(ctx context.Context) { - if s.cfg.metricsWriter == nil || s.GetMode().NoMetabase() { + if s.GetMode().NoMetabase() { return } @@ -439,35 +440,29 @@ func (s *Shard) updateMetrics(ctx context.Context) { // incObjectCounter increment both physical and logical object // counters. func (s *Shard) incObjectCounter(cnrID cid.ID, isUser bool) { - if s.cfg.metricsWriter != nil { - s.cfg.metricsWriter.IncObjectCounter(physical) - s.cfg.metricsWriter.IncObjectCounter(logical) - s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), physical) - s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), logical) - if isUser { - s.cfg.metricsWriter.IncObjectCounter(user) - s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), user) - } + s.cfg.metricsWriter.IncObjectCounter(physical) + s.cfg.metricsWriter.IncObjectCounter(logical) + s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), physical) + s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), logical) + if isUser { + s.cfg.metricsWriter.IncObjectCounter(user) + s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), user) } } func (s *Shard) decObjectCounterBy(typ string, v uint64) { - if s.cfg.metricsWriter != nil && v > 0 { + if v > 0 { s.cfg.metricsWriter.AddToObjectCounter(typ, -int(v)) } } func (s *Shard) setObjectCounterBy(typ string, v uint64) { - if s.cfg.metricsWriter != nil && v > 0 { + if v > 0 { s.cfg.metricsWriter.SetObjectCounter(typ, v) } } func (s *Shard) decContainerObjectCounter(byCnr map[cid.ID]meta.ObjectCounters) { - if s.cfg.metricsWriter == nil { - return - } - for cnrID, count := range byCnr { if count.Phy > 0 { s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy) @@ -482,46 +477,38 @@ func (s *Shard) decContainerObjectCounter(byCnr map[cid.ID]meta.ObjectCounters) } func (s *Shard) addToContainerSize(cnr string, size int64) { - if s.cfg.metricsWriter != nil && size != 0 { + if size != 0 { s.cfg.metricsWriter.AddToContainerSize(cnr, size) } } func (s *Shard) addToPayloadSize(size int64) { - if s.cfg.metricsWriter != nil && size != 0 { + if size != 0 { s.cfg.metricsWriter.AddToPayloadSize(size) } } func (s *Shard) setContainerObjectsCount(cnr string, typ string, v uint64) { - if s.cfg.metricsWriter != nil && v > 0 { + if v > 0 { s.metricsWriter.SetContainerObjectsCount(cnr, typ, v) } } func (s *Shard) IncErrorCounter() { - if s.cfg.metricsWriter != nil { - s.cfg.metricsWriter.IncErrorCounter() - } + s.cfg.metricsWriter.IncErrorCounter() } func (s *Shard) ClearErrorCounter() { - if s.cfg.metricsWriter != nil { - s.cfg.metricsWriter.ClearErrorCounter() - } + s.cfg.metricsWriter.ClearErrorCounter() } func (s *Shard) DeleteShardMetrics() { - if s.cfg.metricsWriter != nil { - s.cfg.metricsWriter.DeleteShardMetrics() - } + s.cfg.metricsWriter.DeleteShardMetrics() } func (s *Shard) SetEvacuationInProgress(val bool) { s.m.Lock() defer s.m.Unlock() s.info.EvacuationInProgress = val - if s.metricsWriter != nil { - s.metricsWriter.SetEvacuationInProgress(val) - } + s.metricsWriter.SetEvacuationInProgress(val) } From 9a87acb87ad243fcdd932e764a3f5f8d9c5c6657 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 3 Oct 2024 10:40:56 +0300 Subject: [PATCH 0878/1413] [#1410] engine: Provide the default implementation to MetricsRegister Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/container.go | 8 +--- pkg/local_object_storage/engine/delete.go | 4 +- pkg/local_object_storage/engine/engine.go | 1 + pkg/local_object_storage/engine/get.go | 4 +- pkg/local_object_storage/engine/head.go | 4 +- pkg/local_object_storage/engine/inhume.go | 4 +- pkg/local_object_storage/engine/metrics.go | 45 +++++++++++++++++++ pkg/local_object_storage/engine/put.go | 4 +- pkg/local_object_storage/engine/range.go | 4 +- pkg/local_object_storage/engine/select.go | 8 +--- pkg/local_object_storage/engine/shards.go | 46 +++++++++----------- 11 files changed, 77 insertions(+), 55 deletions(-) diff --git a/pkg/local_object_storage/engine/container.go b/pkg/local_object_storage/engine/container.go index e45f502ac1..6def02f12f 100644 --- a/pkg/local_object_storage/engine/container.go +++ b/pkg/local_object_storage/engine/container.go @@ -68,9 +68,7 @@ func ContainerSize(e *StorageEngine, id cid.ID) (uint64, error) { } func (e *StorageEngine) containerSize(prm ContainerSizePrm) (res ContainerSizeRes, err error) { - if e.metrics != nil { - defer elapsed("EstimateContainerSize", e.metrics.AddMethodDuration)() - } + defer elapsed("EstimateContainerSize", e.metrics.AddMethodDuration)() e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { var csPrm shard.ContainerSizePrm @@ -116,9 +114,7 @@ func ListContainers(ctx context.Context, e *StorageEngine) ([]cid.ID, error) { } func (e *StorageEngine) listContainers(ctx context.Context) (ListContainersRes, error) { - if e.metrics != nil { - defer elapsed("ListContainers", e.metrics.AddMethodDuration)() - } + defer elapsed("ListContainers", e.metrics.AddMethodDuration)() uniqueIDs := make(map[string]cid.ID) diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 318f938fb3..61cb6832d2 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -68,9 +68,7 @@ func (e *StorageEngine) Delete(ctx context.Context, prm DeletePrm) (res DeleteRe } func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { - if e.metrics != nil { - defer elapsed("Delete", e.metrics.AddMethodDuration)() - } + defer elapsed("Delete", e.metrics.AddMethodDuration)() var locked struct { is bool diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 5e883a6419..13efdcb840 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -219,6 +219,7 @@ func defaultCfg() *cfg { res := &cfg{ log: &logger.Logger{Logger: zap.L()}, shardPoolSize: 20, + metrics: noopMetrics{}, } res.containerSource.Store(&containerSource{}) return res diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index 253256c342..4a9199be70 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -66,9 +66,7 @@ func (e *StorageEngine) Get(ctx context.Context, prm GetPrm) (res GetRes, err er } func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { - if e.metrics != nil { - defer elapsed("Get", e.metrics.AddMethodDuration)() - } + defer elapsed("Get", e.metrics.AddMethodDuration)() errNotFound := new(apistatus.ObjectNotFound) diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index 6857a36319..d2e3cfd99f 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -68,9 +68,7 @@ func (e *StorageEngine) Head(ctx context.Context, prm HeadPrm) (res HeadRes, err func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.head") defer span.End() - if e.metrics != nil { - defer elapsed("Head", e.metrics.AddMethodDuration)() - } + defer elapsed("Head", e.metrics.AddMethodDuration)() var ( head *objectSDK.Object diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 683713f943..35ce50f653 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -80,9 +80,7 @@ func (e *StorageEngine) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRe } func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { - if e.metrics != nil { - defer elapsed("Inhume", e.metrics.AddMethodDuration)() - } + defer elapsed("Inhume", e.metrics.AddMethodDuration)() var shPrm shard.InhumePrm if prm.forceRemoval { diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index 1c088c7543..75936206df 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -68,3 +68,48 @@ func (m *gcMetrics) AddExpiredObjectCollectionDuration(d time.Duration, success func (m *gcMetrics) AddInhumedObjectCount(count uint64, objectType string) { m.storage.AddInhumedObjectCount(m.shardID, count, objectType) } + +type ( + noopMetrics struct{} + noopWriteCacheMetrics struct{} + noopGCMetrics struct{} +) + +var ( + _ MetricRegister = noopMetrics{} + _ metrics.WriteCacheMetrics = noopWriteCacheMetrics{} + _ metrics.GCMetrics = noopGCMetrics{} +) + +func (noopMetrics) AddMethodDuration(string, time.Duration) {} +func (noopMetrics) SetObjectCounter(string, string, uint64) {} +func (noopMetrics) AddToObjectCounter(string, string, int) {} +func (noopMetrics) SetMode(string, mode.Mode) {} +func (noopMetrics) AddToContainerSize(string, int64) {} +func (noopMetrics) DeleteContainerSize(string) {} +func (noopMetrics) DeleteContainerCount(string) {} +func (noopMetrics) AddToPayloadCounter(string, int64) {} +func (noopMetrics) IncErrorCounter(string) {} +func (noopMetrics) ClearErrorCounter(string) {} +func (noopMetrics) DeleteShardMetrics(string) {} +func (noopMetrics) SetContainerObjectCounter(string, string, string, uint64) {} +func (noopMetrics) IncContainerObjectCounter(string, string, string) {} +func (noopMetrics) SubContainerObjectCounter(string, string, string, uint64) {} +func (noopMetrics) IncRefillObjectsCount(string, string, int, bool) {} +func (noopMetrics) SetRefillPercent(string, string, uint32) {} +func (noopMetrics) SetRefillStatus(string, string, string) {} +func (noopMetrics) SetEvacuationInProgress(string, bool) {} +func (noopMetrics) WriteCache() metrics.WriteCacheMetrics { return noopWriteCacheMetrics{} } +func (noopMetrics) GC() metrics.GCMetrics { return noopGCMetrics{} } + +func (noopWriteCacheMetrics) AddMethodDuration(string, string, string, string, bool, time.Duration) {} +func (noopWriteCacheMetrics) SetActualCount(string, string, string, uint64) {} +func (noopWriteCacheMetrics) SetEstimateSize(string, string, string, uint64) {} +func (noopWriteCacheMetrics) SetMode(string, string) {} +func (noopWriteCacheMetrics) IncOperationCounter(string, string, string, string, metrics.NullBool) {} +func (noopWriteCacheMetrics) Close(string, string) {} + +func (noopGCMetrics) AddRunDuration(string, time.Duration, bool) {} +func (noopGCMetrics) AddDeletedCount(string, uint64, uint64) {} +func (noopGCMetrics) AddExpiredObjectCollectionDuration(string, time.Duration, bool, string) {} +func (noopGCMetrics) AddInhumedObjectCount(string, uint64, string) {} diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index f92d837454..bf86402a7c 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -72,9 +72,7 @@ func (e *StorageEngine) Put(ctx context.Context, prm PutPrm) (err error) { } func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { - if e.metrics != nil { - defer elapsed("Put", e.metrics.AddMethodDuration)() - } + defer elapsed("Put", e.metrics.AddMethodDuration)() addr := object.AddressOf(prm.obj) diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index cbf26ff4e8..498674fd26 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -82,9 +82,7 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error )) defer span.End() - if e.metrics != nil { - defer elapsed("GetRange", e.metrics.AddMethodDuration)() - } + defer elapsed("GetRange", e.metrics.AddMethodDuration)() var shPrm shard.RngPrm shPrm.SetAddress(prm.addr) diff --git a/pkg/local_object_storage/engine/select.go b/pkg/local_object_storage/engine/select.go index 6a8c9fab91..972a4f52a2 100644 --- a/pkg/local_object_storage/engine/select.go +++ b/pkg/local_object_storage/engine/select.go @@ -59,9 +59,7 @@ func (e *StorageEngine) Select(ctx context.Context, prm SelectPrm) (res SelectRe } func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, error) { - if e.metrics != nil { - defer elapsed("Search", e.metrics.AddMethodDuration)() - } + defer elapsed("Search", e.metrics.AddMethodDuration)() addrList := make([]oid.Address, 0) uniqueMap := make(map[string]struct{}) @@ -108,9 +106,7 @@ func (e *StorageEngine) List(ctx context.Context, limit uint64) (res SelectRes, } func (e *StorageEngine) list(ctx context.Context, limit uint64) (SelectRes, error) { - if e.metrics != nil { - defer elapsed("ListObjects", e.metrics.AddMethodDuration)() - } + defer elapsed("ListObjects", e.metrics.AddMethodDuration)() addrList := make([]oid.Address, 0, limit) uniqueMap := make(map[string]struct{}) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 2ad6859e4f..96f54369b6 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -116,9 +116,7 @@ func (e *StorageEngine) AddShard(ctx context.Context, opts ...shard.Option) (*sh return nil, fmt.Errorf("could not add %s shard: %w", sh.ID().String(), err) } - if e.cfg.metrics != nil { - e.cfg.metrics.SetMode(sh.ID().String(), sh.GetMode()) - } + e.cfg.metrics.SetMode(sh.ID().String(), sh.GetMode()) return sh.ID(), nil } @@ -152,28 +150,26 @@ func (e *StorageEngine) appendMetrics(id *shard.ID, opts []shard.Option) []shard e.mtx.RLock() defer e.mtx.RUnlock() - if e.metrics != nil { - opts = append(opts, - shard.WithMetricsWriter( - &metricsWithID{ - id: id.String(), - mw: e.metrics, - }, - ), - shard.WithWriteCacheMetrics( - &writeCacheMetrics{ - shardID: id.String(), - metrics: e.metrics.WriteCache(), - }, - ), - shard.WithGCMetrics( - &gcMetrics{ - storage: e.metrics.GC(), - shardID: id.String(), - }, - ), - ) - } + opts = append(opts, + shard.WithMetricsWriter( + &metricsWithID{ + id: id.String(), + mw: e.metrics, + }, + ), + shard.WithWriteCacheMetrics( + &writeCacheMetrics{ + shardID: id.String(), + metrics: e.metrics.WriteCache(), + }, + ), + shard.WithGCMetrics( + &gcMetrics{ + storage: e.metrics.GC(), + shardID: id.String(), + }, + ), + ) return opts } From 963faa615ab0a70964821b3a3725c27ed5d7f60e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 4 Oct 2024 14:58:45 +0300 Subject: [PATCH 0879/1413] [#1413] engine: Cleanup shard error reporting - `reportShardErrorBackground()` no longer differs from `reportShardError()`, reflect this in its name; - reuse common pieces of code to make it simpler. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/engine.go | 28 ++++------------------- pkg/local_object_storage/engine/shards.go | 2 +- 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 13efdcb840..f40c9cc04f 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -115,10 +115,8 @@ func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32, isMeta log.Info(logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) } -// reportShardErrorBackground increases shard error counter and logs an error. -// It is intended to be used from background workers and -// doesn't change shard mode because of possible deadlocks. -func (e *StorageEngine) reportShardErrorBackground(id string, msg string, err error) { +// reportShardErrorByID increases shard error counter and logs an error. +func (e *StorageEngine) reportShardErrorByID(id string, msg string, err error) { e.mtx.RLock() sh, ok := e.shards[id] e.mtx.RUnlock() @@ -127,16 +125,7 @@ func (e *StorageEngine) reportShardErrorBackground(id string, msg string, err er return } - if isLogical(err) { - e.log.Warn(msg, - zap.Stringer("shard_id", sh.ID()), - zap.String("error", err.Error())) - return - } - - errCount := sh.errorCount.Add(1) - sh.Shard.IncErrorCounter() - e.reportShardErrorWithFlags(sh.Shard, errCount, msg, err) + e.reportShardError(sh, msg, err) } // reportShardError checks that the amount of errors doesn't exceed the configured threshold. @@ -156,16 +145,7 @@ func (e *StorageEngine) reportShardError( errCount := sh.errorCount.Add(1) sh.Shard.IncErrorCounter() - e.reportShardErrorWithFlags(sh.Shard, errCount, msg, err, fields...) -} -func (e *StorageEngine) reportShardErrorWithFlags( - sh *shard.Shard, - errCount uint32, - msg string, - err error, - fields ...zap.Field, -) { sid := sh.ID() e.log.Warn(msg, append([]zap.Field{ zap.Stringer("shard_id", sid), @@ -179,7 +159,7 @@ func (e *StorageEngine) reportShardErrorWithFlags( req := setModeRequest{ errorCount: errCount, - sh: sh, + sh: sh.Shard, isMeta: errors.As(err, new(metaerr.Error)), } diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 96f54369b6..c3ccb52762 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -134,7 +134,7 @@ func (e *StorageEngine) createShard(_ context.Context, opts []shard.Option) (*sh shard.WithExpiredTombstonesCallback(e.processExpiredTombstones), shard.WithExpiredLocksCallback(e.processExpiredLocks), shard.WithDeletedLockCallback(e.processDeletedLocks), - shard.WithReportErrorFunc(e.reportShardErrorBackground), + shard.WithReportErrorFunc(e.reportShardErrorByID), shard.WithZeroSizeCallback(e.processZeroSizeContainers), shard.WithZeroCountCallback(e.processZeroCountContainers), )...) From 4dc9a1b300b2f22dbd9628713917347bc0d3a6ee Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 4 Oct 2024 15:07:20 +0300 Subject: [PATCH 0880/1413] [#1413] engine: Remove error counting methods from Shard All error counting and hangling logic is present on the engine level. Currently, we pass engine metrics with shard ID metric to shard, then export 3 methods to manipulate these metrics. In this commits all methods are removed and error counter is tracked on the engine level exlusively. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/engine.go | 2 +- pkg/local_object_storage/engine/shards.go | 6 +++--- pkg/local_object_storage/shard/metrics.go | 9 --------- pkg/local_object_storage/shard/shard.go | 12 ------------ 4 files changed, 4 insertions(+), 25 deletions(-) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index f40c9cc04f..3183d61374 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -144,7 +144,7 @@ func (e *StorageEngine) reportShardError( } errCount := sh.errorCount.Add(1) - sh.Shard.IncErrorCounter() + e.metrics.IncErrorCounter(sh.ID().String()) sid := sh.ID() e.log.Warn(msg, append([]zap.Field{ diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index c3ccb52762..aab2c423c6 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -217,7 +217,7 @@ func (e *StorageEngine) removeShards(ids ...string) { continue } - sh.DeleteShardMetrics() + e.metrics.DeleteShardMetrics(id) ss = append(ss, sh) delete(e.shards, id) @@ -318,7 +318,7 @@ func (e *StorageEngine) SetShardMode(id *shard.ID, m mode.Mode, resetErrorCounte if id.String() == shID { if resetErrorCounter { sh.errorCount.Store(0) - sh.Shard.ClearErrorCounter() + e.metrics.ClearErrorCounter(shID) } return sh.SetMode(m) } @@ -422,7 +422,7 @@ func (e *StorageEngine) deleteShards(ids []*shard.ID) ([]hashedShard, error) { for _, sh := range ss { idStr := sh.ID().String() - sh.DeleteShardMetrics() + e.metrics.DeleteShardMetrics(idStr) delete(e.shards, idStr) diff --git a/pkg/local_object_storage/shard/metrics.go b/pkg/local_object_storage/shard/metrics.go index 6bf198048d..91bf8d0aef 100644 --- a/pkg/local_object_storage/shard/metrics.go +++ b/pkg/local_object_storage/shard/metrics.go @@ -24,12 +24,6 @@ type MetricsWriter interface { SetShardID(id string) // SetReadonly must set shard mode. SetMode(mode mode.Mode) - // IncErrorCounter increment error counter. - IncErrorCounter() - // ClearErrorCounter clear error counter. - ClearErrorCounter() - // DeleteShardMetrics deletes shard metrics from registry. - DeleteShardMetrics() // SetContainerObjectsCount sets container object count. SetContainerObjectsCount(cnrID string, objectType string, value uint64) // IncContainerObjectsCount increments container object count. @@ -57,9 +51,6 @@ func (noopMetrics) AddToPayloadSize(int64) {} func (noopMetrics) IncObjectCounter(string) {} func (noopMetrics) SetShardID(string) {} func (noopMetrics) SetMode(mode.Mode) {} -func (noopMetrics) IncErrorCounter() {} -func (noopMetrics) ClearErrorCounter() {} -func (noopMetrics) DeleteShardMetrics() {} func (noopMetrics) SetContainerObjectsCount(string, string, uint64) {} func (noopMetrics) IncContainerObjectsCount(string, string) {} func (noopMetrics) SubContainerObjectsCount(string, string, uint64) {} diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index a57b548be4..d7e7237339 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -494,18 +494,6 @@ func (s *Shard) setContainerObjectsCount(cnr string, typ string, v uint64) { } } -func (s *Shard) IncErrorCounter() { - s.cfg.metricsWriter.IncErrorCounter() -} - -func (s *Shard) ClearErrorCounter() { - s.cfg.metricsWriter.ClearErrorCounter() -} - -func (s *Shard) DeleteShardMetrics() { - s.cfg.metricsWriter.DeleteShardMetrics() -} - func (s *Shard) SetEvacuationInProgress(val bool) { s.m.Lock() defer s.m.Unlock() From 2f710d8f945f90c5d65e4c9a0c53f0dfdcc4f291 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 4 Oct 2024 15:23:22 +0300 Subject: [PATCH 0881/1413] [#1414] metabase: Check parameter for `CountAliveObjectsInBucket` Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/metabase/list.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 44f25246e6..74a5298098 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -452,10 +452,11 @@ func (db *DB) CountAliveObjectsInBucket(ctx context.Context, prm CountAliveObjec return 0, ErrDegradedMode } - cidRaw := prm.BucketName[1:bucketKeySize] - if cidRaw == nil { + if len(prm.BucketName) != bucketKeySize { return 0, nil } + + cidRaw := prm.BucketName[1:bucketKeySize] var count uint64 err := db.boltDB.View(func(tx *bbolt.Tx) error { bkt := tx.Bucket(prm.BucketName) From fc032838c037c7c649f80181ca71d8c9f6847e7d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 7 Oct 2024 11:50:47 +0300 Subject: [PATCH 0882/1413] [#1215] blobstor/test: Cover iteration behaviour Signed-off-by: Evgenii Stratonikov --- .../blobstor/iterate_test.go | 172 ++++++------------ 1 file changed, 59 insertions(+), 113 deletions(-) diff --git a/pkg/local_object_storage/blobstor/iterate_test.go b/pkg/local_object_storage/blobstor/iterate_test.go index 0797283804..195d0bd31d 100644 --- a/pkg/local_object_storage/blobstor/iterate_test.go +++ b/pkg/local_object_storage/blobstor/iterate_test.go @@ -3,10 +3,13 @@ package blobstor import ( "context" "encoding/binary" + "errors" "os" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/memstore" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -90,117 +93,60 @@ func TestIterateObjects(t *testing.T) { } func TestIterate_IgnoreErrors(t *testing.T) { - t.Skip() - // dir := t.TempDir() - // - // const ( - // smallSize = 512 - // objCount = 5 - // ) - // bsOpts := []Option{ - // WithCompressObjects(true), - // WithRootPath(dir), - // WithSmallSizeLimit(smallSize * 2), // + header - // WithBlobovniczaOpenedCacheSize(1), - // WithBlobovniczaShallowWidth(1), - // WithBlobovniczaShallowDepth(1)} - // bs := New(bsOpts...) - // require.NoError(t, bs.Open(false)) - // require.NoError(t, bs.Init()) - // - // addrs := make([]oid.Address, objCount) - // for i := range addrs { - // addrs[i] = oidtest.Address() - // - // obj := object.New() - // obj.SetContainerID(addrs[i].Container()) - // obj.SetID(addrs[i].Object()) - // obj.SetPayload(make([]byte, smallSize<<(i%2))) - // - // objData, err := obj.Marshal() - // require.NoError(t, err) - // - // _, err = bs.PutRaw(addrs[i], objData, true) - // require.NoError(t, err) - // } - // - // // Construct corrupted compressed object. - // buf := bytes.NewBuffer(nil) - // badObject := make([]byte, smallSize/2+1) - // enc, err := zstd.NewWriter(buf) - // require.NoError(t, err) - // rawData := enc.EncodeAll(badObject, nil) - // for i := 4; /* magic size */ i < len(rawData); i += 2 { - // rawData[i] ^= 0xFF - // } - // // Will be put uncompressed but fetched as compressed because of magic. - // _, err = bs.PutRaw(oidtest.Address(), rawData, false) - // require.NoError(t, err) - // require.NoError(t, bs.fsTree.Put(oidtest.Address(), rawData)) - // - // require.NoError(t, bs.Close()) - // - // // Increase width to have blobovnicza which is definitely empty. - // b := New(append(bsOpts, WithBlobovniczaShallowWidth(2))...) - // require.NoError(t, b.Open(false)) - // require.NoError(t, b.Init()) - // - // var p string - // for i := 0; i < 2; i++ { - // bp := filepath.Join(bs.rootPath, "1", strconv.FormatUint(uint64(i), 10)) - // if _, ok := bs.blobovniczas.opened.Get(bp); !ok { - // p = bp - // break - // } - // } - // require.NotEqual(t, "", p, "expected to not have at least 1 blobovnicza in cache") - // require.NoError(t, os.Chmod(p, 0)) - // - // require.NoError(t, b.Close()) - // require.NoError(t, bs.Open(false)) - // require.NoError(t, bs.Init()) - // - // var prm IteratePrm - // prm.SetIterationHandler(func(e IterationElement) error { - // return nil - // }) - // _, err = bs.Iterate(prm) - // require.Error(t, err) - // - // prm.IgnoreErrors() - // - // t.Run("skip invalid objects", func(t *testing.T) { - // actual := make([]oid.Address, 0, len(addrs)) - // prm.SetIterationHandler(func(e IterationElement) error { - // obj := object.New() - // err := obj.Unmarshal(e.data) - // if err != nil { - // return err - // } - // - // var addr oid.Address - // cnr, _ := obj.ContainerID() - // addr.SetContainer(cnr) - // id, _ := obj.ID() - // addr.SetObject(id) - // actual = append(actual, addr) - // return nil - // }) - // - // _, err := bs.Iterate(prm) - // require.NoError(t, err) - // require.ElementsMatch(t, addrs, actual) - // }) - // t.Run("return errors from handler", func(t *testing.T) { - // n := 0 - // expectedErr := errors.New("expected error") - // prm.SetIterationHandler(func(e IterationElement) error { - // if n++; n == objCount/2 { - // return expectedErr - // } - // return nil - // }) - // _, err := bs.Iterate(prm) - // require.ErrorIs(t, err, expectedErr) - // }) + ctx := context.Background() + + myErr := errors.New("unique error") + nopIter := func(common.IteratePrm) (common.IterateRes, error) { return common.IterateRes{}, nil } + panicIter := func(common.IteratePrm) (common.IterateRes, error) { panic("unreachable") } + errIter := func(common.IteratePrm) (common.IterateRes, error) { return common.IterateRes{}, myErr } + + var s1iter, s2iter func(common.IteratePrm) (common.IterateRes, error) + st1 := teststore.New( + teststore.WithSubstorage(memstore.New()), + teststore.WithIterate(func(prm common.IteratePrm) (common.IterateRes, error) { + return s1iter(prm) + })) + st2 := teststore.New( + teststore.WithSubstorage(memstore.New()), + teststore.WithIterate(func(prm common.IteratePrm) (common.IterateRes, error) { + return s2iter(prm) + })) + + bsOpts := []Option{WithStorages([]SubStorage{ + {Storage: st1}, + {Storage: st2}, + })} + bs := New(bsOpts...) + require.NoError(t, bs.Open(ctx, mode.ReadWrite)) + require.NoError(t, bs.Init()) + + nopHandler := func(e common.IterationElement) error { + return nil + } + + t.Run("no errors", func(t *testing.T) { + s1iter = nopIter + s2iter = nopIter + _, err := bs.Iterate(ctx, common.IteratePrm{Handler: nopHandler}) + require.NoError(t, err) + }) + t.Run("error in the first sub storage, the second one is not iterated over", func(t *testing.T) { + s1iter = errIter + s2iter = panicIter + _, err := bs.Iterate(ctx, common.IteratePrm{Handler: nopHandler}) + require.ErrorIs(t, err, myErr) + }) + + t.Run("ignore errors, storage 1", func(t *testing.T) { + s1iter = errIter + s2iter = nopIter + _, err := bs.Iterate(ctx, common.IteratePrm{IgnoreErrors: true, Handler: nopHandler}) + require.NoError(t, err) + }) + t.Run("ignore errors, storage 2", func(t *testing.T) { + s1iter = nopIter + s2iter = errIter + _, err := bs.Iterate(ctx, common.IteratePrm{IgnoreErrors: true, Handler: nopHandler}) + require.NoError(t, err) + }) } From a5de74a2492deb9e969c1d722c82bb8b050130df Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 7 Oct 2024 15:13:44 +0300 Subject: [PATCH 0883/1413] [#1418] go.mod: Update api-go Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1023948bc1..f81ba9cf77 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241001111852-d9a604fbc16f + git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3 git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d diff --git a/go.sum b/go.sum index 5d719a0274..8aa087de41 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241001111852-d9a604fbc16f h1:FZvX6CLzTQqMyMvOerIKMvIEJQbOImDjSooZx3AVRyE= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241001111852-d9a604fbc16f/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3 h1:6QXNnfBgYx81UZsBdpPnQY+ZMSKGFbFc29wV7DJ/UG4= +git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c h1:9JmXxWcqWaOXModBwtj/WlPYOfSk2jRSDoRsDRYvgnA= git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c/go.mod h1:DVb1AqP323wiEwCtlfoJJTERF4Xji2L39X6T8kv26RE= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= From 5fbb2657ca9ca9bbc3aa2ca9239fbb55ea47cdc3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 8 Oct 2024 10:02:14 +0300 Subject: [PATCH 0884/1413] [#1419] mod: Bump sdk-go version Signed-off-by: Dmitrii Stepanov --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index f81ba9cf77..91cc55a364 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240918095938-e580ee991d98 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241007135805-4c310ae1c7fa git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 @@ -60,7 +60,7 @@ require ( require ( git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect - github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect diff --git a/go.sum b/go.sum index 8aa087de41..728592ea5e 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 h1:6qCcm1oqFbmf9C5AauXzrL5OPGnTbI9HoB/jAtD9274= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240918095938-e580ee991d98 h1:ijUci3thz0EwWkuRJDocW5D1RkVAJlt9xNG4CYepC90= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240918095938-e580ee991d98/go.mod h1:GeNpo12HcEW4J412sH5yf8xFYapxlrt5fcYzRwg0Ino= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241007135805-4c310ae1c7fa h1:Jr8hXNNFECLhC7S45HuyQms4U/gim1xILoU3g4ZZnHg= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241007135805-4c310ae1c7fa/go.mod h1:jmb7yxzZota9jWbC10p+7YR+6wwJPBj7J/Fl5VDkXys= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= @@ -27,8 +27,8 @@ git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02/go. github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/VictoriaMetrics/easyproto v0.1.4 h1:r8cNvo8o6sR4QShBXQd1bKw/VVLSQma/V2KhTBPf+Sc= github.com/VictoriaMetrics/easyproto v0.1.4/go.mod h1:QlGlzaJnDfFd8Lk6Ci/fuLxfTo3/GThPs2KH23mv710= -github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= -github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= +github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= From 0c49bca19c82d574c9a93681bda77362edd5b88c Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 7 Oct 2024 18:32:26 +0300 Subject: [PATCH 0885/1413] [#1415] lens/explorer: Add timeout for opening database Signed-off-by: Aleksey Savchuk --- cmd/frostfs-lens/internal/blobovnicza/tui.go | 13 +------------ cmd/frostfs-lens/internal/meta/tui.go | 13 +------------ cmd/frostfs-lens/internal/tui/util.go | 13 +++++++++++++ cmd/frostfs-lens/internal/writecache/tui.go | 13 +------------ 4 files changed, 16 insertions(+), 36 deletions(-) diff --git a/cmd/frostfs-lens/internal/blobovnicza/tui.go b/cmd/frostfs-lens/internal/blobovnicza/tui.go index eb4a5ff598..4aa281616c 100644 --- a/cmd/frostfs-lens/internal/blobovnicza/tui.go +++ b/cmd/frostfs-lens/internal/blobovnicza/tui.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/tui" "github.com/rivo/tview" "github.com/spf13/cobra" - "go.etcd.io/bbolt" ) var tuiCMD = &cobra.Command{ @@ -43,7 +42,7 @@ func tuiFunc(cmd *cobra.Command, _ []string) { } func runTUI(cmd *cobra.Command) error { - db, err := openDB(false) + db, err := tui.OpenDB(vPath, false) if err != nil { return fmt.Errorf("couldn't open database: %w", err) } @@ -67,13 +66,3 @@ func runTUI(cmd *cobra.Command) error { app.SetRoot(ui, true).SetFocus(ui) return app.Run() } - -func openDB(writable bool) (*bbolt.DB, error) { - db, err := bbolt.Open(vPath, 0o600, &bbolt.Options{ - ReadOnly: !writable, - }) - if err != nil { - return nil, err - } - return db, nil -} diff --git a/cmd/frostfs-lens/internal/meta/tui.go b/cmd/frostfs-lens/internal/meta/tui.go index 00e8bf1175..5a41f945c0 100644 --- a/cmd/frostfs-lens/internal/meta/tui.go +++ b/cmd/frostfs-lens/internal/meta/tui.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/tui" "github.com/rivo/tview" "github.com/spf13/cobra" - "go.etcd.io/bbolt" ) var tuiCMD = &cobra.Command{ @@ -44,7 +43,7 @@ func tuiFunc(cmd *cobra.Command, _ []string) { } func runTUI(cmd *cobra.Command) error { - db, err := openDB(false) + db, err := tui.OpenDB(vPath, false) if err != nil { return fmt.Errorf("couldn't open database: %w", err) } @@ -70,13 +69,3 @@ func runTUI(cmd *cobra.Command) error { app.SetRoot(ui, true).SetFocus(ui) return app.Run() } - -func openDB(writable bool) (*bbolt.DB, error) { - db, err := bbolt.Open(vPath, 0o600, &bbolt.Options{ - ReadOnly: !writable, - }) - if err != nil { - return nil, err - } - return db, nil -} diff --git a/cmd/frostfs-lens/internal/tui/util.go b/cmd/frostfs-lens/internal/tui/util.go index d4e13b2a9b..2d1ab3e33f 100644 --- a/cmd/frostfs-lens/internal/tui/util.go +++ b/cmd/frostfs-lens/internal/tui/util.go @@ -3,12 +3,25 @@ package tui import ( "errors" "strings" + "time" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/mr-tron/base58" + "go.etcd.io/bbolt" ) +func OpenDB(path string, writable bool) (*bbolt.DB, error) { + db, err := bbolt.Open(path, 0o600, &bbolt.Options{ + ReadOnly: !writable, + Timeout: 100 * time.Millisecond, + }) + if err != nil { + return nil, err + } + return db, nil +} + func CIDParser(s string) (any, error) { data, err := base58.Decode(s) if err != nil { diff --git a/cmd/frostfs-lens/internal/writecache/tui.go b/cmd/frostfs-lens/internal/writecache/tui.go index 6b7532b08a..b7e4d7c966 100644 --- a/cmd/frostfs-lens/internal/writecache/tui.go +++ b/cmd/frostfs-lens/internal/writecache/tui.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/tui" "github.com/rivo/tview" "github.com/spf13/cobra" - "go.etcd.io/bbolt" ) var tuiCMD = &cobra.Command{ @@ -43,7 +42,7 @@ func tuiFunc(cmd *cobra.Command, _ []string) { } func runTUI(cmd *cobra.Command) error { - db, err := openDB(false) + db, err := tui.OpenDB(vPath, false) if err != nil { return fmt.Errorf("couldn't open database: %w", err) } @@ -67,13 +66,3 @@ func runTUI(cmd *cobra.Command) error { app.SetRoot(ui, true).SetFocus(ui) return app.Run() } - -func openDB(writable bool) (*bbolt.DB, error) { - db, err := bbolt.Open(vPath, 0o600, &bbolt.Options{ - ReadOnly: !writable, - }) - if err != nil { - return nil, err - } - return db, nil -} From 899cd55c277b04b974e67df29b81146528d5c293 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 1 Oct 2024 13:28:46 +0300 Subject: [PATCH 0886/1413] [#1412] engine: PutPrm refactoring Use fields instead of methods. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/list_test.go | 6 +---- pkg/local_object_storage/engine/put.go | 24 ++++++-------------- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index 11a6c7841b..d683b5475a 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -82,11 +82,7 @@ func TestListWithCursor(t *testing.T) { for range tt.objectNum { containerID := cidtest.ID() obj := testutil.GenerateObjectWithCIDWithPayload(containerID, []byte{'a'}) - - var prm PutPrm - prm.WithObject(obj) - - err := e.Put(context.Background(), prm) + err := e.Put(context.Background(), PutPrm{Object: obj}) require.NoError(t, err) expected = append(expected, object.Info{Type: objectSDK.TypeRegular, Address: object.AddressOf(obj)}) } diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index bf86402a7c..9ce31e791e 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -22,7 +22,7 @@ import ( // PutPrm groups the parameters of Put operation. type PutPrm struct { - obj *objectSDK.Object + Object *objectSDK.Object } var errPutShard = errors.New("could not put object to any shard") @@ -41,13 +41,6 @@ type putToShardRes struct { err error } -// WithObject is a Put option to set object to save. -// -// Option is required. -func (p *PutPrm) WithObject(obj *objectSDK.Object) { - p.obj = obj -} - // Put saves the object to local storage. // // Returns any error encountered that @@ -59,7 +52,7 @@ func (p *PutPrm) WithObject(obj *objectSDK.Object) { func (e *StorageEngine) Put(ctx context.Context, prm PutPrm) (err error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Put", trace.WithAttributes( - attribute.String("address", object.AddressOf(prm.obj).EncodeToString()), + attribute.String("address", object.AddressOf(prm.Object).EncodeToString()), )) defer span.End() @@ -74,13 +67,13 @@ func (e *StorageEngine) Put(ctx context.Context, prm PutPrm) (err error) { func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { defer elapsed("Put", e.metrics.AddMethodDuration)() - addr := object.AddressOf(prm.obj) + addr := object.AddressOf(prm.Object) // In #1146 this check was parallelized, however, it became // much slower on fast machines for 4 shards. var parent oid.Address - if prm.obj.ECHeader() != nil { - parent.SetObject(prm.obj.ECHeader().Parent()) + if prm.Object.ECHeader() != nil { + parent.SetObject(prm.Object.ECHeader().Parent()) parent.SetContainer(addr.Container()) } var shPrm shard.ExistsPrm @@ -113,7 +106,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // Shard was concurrently removed, skip. return false } - shRes = e.putToShard(ctx, sh, pool, addr, prm.obj) + shRes = e.putToShard(ctx, sh, pool, addr, prm.Object) return shRes.status != putToShardUnknown }) switch shRes.status { @@ -202,8 +195,5 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti // Put writes provided object to local storage. func Put(ctx context.Context, storage *StorageEngine, obj *objectSDK.Object) error { - var putPrm PutPrm - putPrm.WithObject(obj) - - return storage.Put(ctx, putPrm) + return storage.Put(ctx, PutPrm{Object: obj}) } From 1b520f79733e3628af5d47b597b5baff60f3f36a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 1 Oct 2024 15:27:06 +0300 Subject: [PATCH 0887/1413] [#1412] engine: Add `IsIndexedContainer` flag Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 4 +- pkg/core/container/info.go | 103 ++++++++++++++++++ pkg/core/container/util.go | 12 ++ .../engine/control_test.go | 2 +- .../engine/delete_test.go | 8 +- .../engine/engine_test.go | 2 +- .../engine/inhume_test.go | 2 +- pkg/local_object_storage/engine/lock_test.go | 14 +-- pkg/local_object_storage/engine/put.go | 7 +- pkg/local_object_storage/engine/tree_test.go | 2 +- pkg/services/object/common/writer/ec.go | 3 +- pkg/services/object/common/writer/local.go | 9 +- pkg/services/object/common/writer/writer.go | 3 +- pkg/services/object/put/single.go | 11 +- pkg/services/policer/check.go | 2 +- pkg/services/policer/ec.go | 39 ++++--- pkg/services/replicator/pull.go | 3 +- pkg/services/replicator/put.go | 3 +- pkg/services/replicator/task.go | 3 + 19 files changed, 182 insertions(+), 50 deletions(-) create mode 100644 pkg/core/container/info.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 47649c88ba..5c322886bb 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -535,6 +535,6 @@ func (e engineWithoutNotifications) Lock(ctx context.Context, locker oid.Address return e.engine.Lock(ctx, locker.Container(), locker.Object(), toLock) } -func (e engineWithoutNotifications) Put(ctx context.Context, o *objectSDK.Object) error { - return engine.Put(ctx, e.engine, o) +func (e engineWithoutNotifications) Put(ctx context.Context, o *objectSDK.Object, indexableContainer bool) error { + return engine.Put(ctx, e.engine, o, indexableContainer) } diff --git a/pkg/core/container/info.go b/pkg/core/container/info.go new file mode 100644 index 0000000000..62cc215536 --- /dev/null +++ b/pkg/core/container/info.go @@ -0,0 +1,103 @@ +package container + +import ( + "sync" + + utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" +) + +type Info struct { + Indexed bool + Removed bool +} + +type infoValue struct { + info Info + err error +} + +type InfoProvider interface { + Info(id cid.ID) (Info, error) +} + +type infoProvider struct { + mtx *sync.RWMutex + cache map[cid.ID]infoValue + kl *utilSync.KeyLocker[cid.ID] + + source Source + sourceErr error + sourceOnce *sync.Once + sourceFactory func() (Source, error) +} + +func NewInfoProvider(sourceFactory func() (Source, error)) InfoProvider { + return &infoProvider{ + mtx: &sync.RWMutex{}, + cache: make(map[cid.ID]infoValue), + sourceOnce: &sync.Once{}, + kl: utilSync.NewKeyLocker[cid.ID](), + sourceFactory: sourceFactory, + } +} + +func (r *infoProvider) Info(id cid.ID) (Info, error) { + v, found := r.tryGetFromCache(id) + if found { + return v.info, v.err + } + + return r.getFromSource(id) +} + +func (r *infoProvider) tryGetFromCache(id cid.ID) (infoValue, bool) { + r.mtx.RLock() + defer r.mtx.RUnlock() + + value, found := r.cache[id] + return value, found +} + +func (r *infoProvider) getFromSource(id cid.ID) (Info, error) { + r.kl.Lock(id) + defer r.kl.Unlock(id) + + if v, ok := r.tryGetFromCache(id); ok { + return v.info, v.err + } + + r.sourceOnce.Do(func() { + r.source, r.sourceErr = r.sourceFactory() + }) + if r.sourceErr != nil { + return Info{}, r.sourceErr + } + + cnr, err := r.source.Get(id) + var civ infoValue + if err != nil { + if client.IsErrContainerNotFound(err) { + removed, err := WasRemoved(r.source, id) + if err != nil { + civ.err = err + } else { + civ.info.Removed = removed + } + } else { + civ.err = err + } + } else { + civ.info.Indexed = IsIndexedContainer(cnr.Value) + } + r.putToCache(id, civ) + return civ.info, civ.err +} + +func (r *infoProvider) putToCache(id cid.ID, ct infoValue) { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.cache[id] = ct +} diff --git a/pkg/core/container/util.go b/pkg/core/container/util.go index 98919284ee..d275568078 100644 --- a/pkg/core/container/util.go +++ b/pkg/core/container/util.go @@ -4,6 +4,7 @@ import ( "errors" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" ) @@ -20,3 +21,14 @@ func WasRemoved(s Source, cid cid.ID) (bool, error) { } return false, err } + +// IsIndexedContainer returns True if container attributes should be indexed. +func IsIndexedContainer(cnr containerSDK.Container) bool { + var isS3Container bool + cnr.IterateAttributes(func(key, _ string) { + if key == ".s3-location-constraint" { + isS3Container = true + } + }) + return !isS3Container +} diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 2de92ae844..83babeca33 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -171,7 +171,7 @@ func TestExecBlocks(t *testing.T) { addr := object.AddressOf(obj) - require.NoError(t, Put(context.Background(), e, obj)) + require.NoError(t, Put(context.Background(), e, obj, false)) // block executions errBlock := errors.New("block exec err") diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 4a6758012d..0904c98204 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -58,9 +58,9 @@ func TestDeleteBigObject(t *testing.T) { defer e.Close(context.Background()) for i := range children { - require.NoError(t, Put(context.Background(), e, children[i])) + require.NoError(t, Put(context.Background(), e, children[i], false)) } - require.NoError(t, Put(context.Background(), e, link)) + require.NoError(t, Put(context.Background(), e, link, false)) addrParent := object.AddressOf(parent) checkGetError[*objectSDK.SplitInfoError](t, e, addrParent, true) @@ -126,9 +126,9 @@ func TestDeleteBigObjectWithoutGC(t *testing.T) { defer e.Close(context.Background()) for i := range children { - require.NoError(t, Put(context.Background(), e, children[i])) + require.NoError(t, Put(context.Background(), e, children[i], false)) } - require.NoError(t, Put(context.Background(), e, link)) + require.NoError(t, Put(context.Background(), e, link, false)) addrParent := object.AddressOf(parent) checkGetError[*objectSDK.SplitInfoError](t, e, addrParent, true) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 525e17f341..88c523b765 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -54,7 +54,7 @@ func benchmarkExists(b *testing.B, shardNum int) { addr := oidtest.Address() for range 100 { obj := testutil.GenerateObjectWithCID(cidtest.ID()) - err := Put(context.Background(), e, obj) + err := Put(context.Background(), e, obj, false) if err != nil { b.Fatal(err) } diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 9daa113f8e..f87679253a 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -40,7 +40,7 @@ func TestStorageEngine_Inhume(t *testing.T) { e := testNewEngine(t).setShardsNum(t, 1).engine defer e.Close(context.Background()) - err := Put(context.Background(), e, parent) + err := Put(context.Background(), e, parent, false) require.NoError(t, err) var inhumePrm InhumePrm diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 9e6758fb47..3702f567f5 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -97,7 +97,7 @@ func TestLockUserScenario(t *testing.T) { id, _ := obj.ID() objAddr.SetObject(id) - err = Put(context.Background(), e, obj) + err = Put(context.Background(), e, obj, false) require.NoError(t, err) // 2. @@ -105,7 +105,7 @@ func TestLockUserScenario(t *testing.T) { locker.WriteMembers([]oid.ID{id}) objectSDK.WriteLock(lockerObj, locker) - err = Put(context.Background(), e, lockerObj) + err = Put(context.Background(), e, lockerObj, false) require.NoError(t, err) err = e.Lock(context.Background(), cnr, lockerID, []oid.ID{id}) @@ -124,7 +124,7 @@ func TestLockUserScenario(t *testing.T) { tombObj.SetID(tombForLockID) tombObj.SetAttributes(a) - err = Put(context.Background(), e, tombObj) + err = Put(context.Background(), e, tombObj, false) require.NoError(t, err) inhumePrm.WithTarget(tombForLockAddr, lockerAddr) @@ -177,7 +177,7 @@ func TestLockExpiration(t *testing.T) { // 1. obj := testutil.GenerateObjectWithCID(cnr) - err = Put(context.Background(), e, obj) + err = Put(context.Background(), e, obj, false) require.NoError(t, err) // 2. @@ -189,7 +189,7 @@ func TestLockExpiration(t *testing.T) { lock.SetType(objectSDK.TypeLock) lock.SetAttributes(a) - err = Put(context.Background(), e, lock) + err = Put(context.Background(), e, lock, false) require.NoError(t, err) id, _ := obj.ID() @@ -254,14 +254,14 @@ func TestLockForceRemoval(t *testing.T) { // 1. obj := testutil.GenerateObjectWithCID(cnr) - err = Put(context.Background(), e, obj) + err = Put(context.Background(), e, obj, false) require.NoError(t, err) // 2. lock := testutil.GenerateObjectWithCID(cnr) lock.SetType(objectSDK.TypeLock) - err = Put(context.Background(), e, lock) + err = Put(context.Background(), e, lock, false) require.NoError(t, err) id, _ := obj.ID() diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 9ce31e791e..41e5665608 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -22,7 +22,8 @@ import ( // PutPrm groups the parameters of Put operation. type PutPrm struct { - Object *objectSDK.Object + Object *objectSDK.Object + IsIndexedContainer bool } var errPutShard = errors.New("could not put object to any shard") @@ -194,6 +195,6 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti } // Put writes provided object to local storage. -func Put(ctx context.Context, storage *StorageEngine, obj *objectSDK.Object) error { - return storage.Put(ctx, PutPrm{Object: obj}) +func Put(ctx context.Context, storage *StorageEngine, obj *objectSDK.Object, indexedContainer bool) error { + return storage.Put(ctx, PutPrm{Object: obj, IsIndexedContainer: indexedContainer}) } diff --git a/pkg/local_object_storage/engine/tree_test.go b/pkg/local_object_storage/engine/tree_test.go index 6f694f0821..21fcce4153 100644 --- a/pkg/local_object_storage/engine/tree_test.go +++ b/pkg/local_object_storage/engine/tree_test.go @@ -37,7 +37,7 @@ func benchmarkTreeVsSearch(b *testing.B, objCount int) { for i := range objCount { obj := testutil.GenerateObjectWithCID(cid) testutil.AddAttribute(obj, pilorama.AttributeFilename, strconv.Itoa(i)) - err := Put(context.Background(), te.ng, obj) + err := Put(context.Background(), te.ng, obj, false) if err != nil { b.Fatal(err) } diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index fb0a8e4e53..6b6a14cc0a 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -310,7 +310,8 @@ func (e *ECWriter) putECPartToNode(ctx context.Context, obj *objectSDK.Object, n func (e *ECWriter) writePartLocal(ctx context.Context, obj *objectSDK.Object) error { var err error localTarget := LocalTarget{ - Storage: e.Config.LocalStore, + Storage: e.Config.LocalStore, + Container: e.Container, } completed := make(chan interface{}) if poolErr := e.Config.LocalPool.Submit(func() { diff --git a/pkg/services/object/common/writer/local.go b/pkg/services/object/common/writer/local.go index 02fd25b9e7..e219b44ddf 100644 --- a/pkg/services/object/common/writer/local.go +++ b/pkg/services/object/common/writer/local.go @@ -4,7 +4,9 @@ import ( "context" "fmt" + containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) @@ -13,7 +15,7 @@ import ( type ObjectStorage interface { // Put must save passed object // and return any appeared error. - Put(context.Context, *objectSDK.Object) error + Put(context.Context, *objectSDK.Object, bool) error // Delete must delete passed objects // and return any appeared error. Delete(ctx context.Context, tombstone oid.Address, toDelete []oid.ID) error @@ -25,7 +27,8 @@ type ObjectStorage interface { } type LocalTarget struct { - Storage ObjectStorage + Storage ObjectStorage + Container containerSDK.Container } func (t LocalTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, meta objectCore.ContentMeta) error { @@ -44,7 +47,7 @@ func (t LocalTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, met // objects that do not change meta storage } - if err := t.Storage.Put(ctx, obj); err != nil { + if err := t.Storage.Put(ctx, obj, containerCore.IsIndexedContainer(t.Container)); err != nil { return fmt.Errorf("(%T) could not put object to local storage: %w", t, err) } return nil diff --git a/pkg/services/object/common/writer/writer.go b/pkg/services/object/common/writer/writer.go index 3d50da988a..0e4c4d9c62 100644 --- a/pkg/services/object/common/writer/writer.go +++ b/pkg/services/object/common/writer/writer.go @@ -150,7 +150,8 @@ func newDefaultObjectWriter(prm *Params, forECPlacement bool) transformer.Object nodeTargetInitializer: func(node NodeDescriptor) preparedObjectTarget { if node.Local { return LocalTarget{ - Storage: prm.Config.LocalStore, + Storage: prm.Config.LocalStore, + Container: prm.Container, } } diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 9b41632687..5f9b5d110e 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -177,7 +177,7 @@ func (s *Service) saveToREPReplicas(ctx context.Context, placement putSinglePlac } return iter.ForEachNode(ctx, func(ctx context.Context, nd objectwriter.NodeDescriptor) error { - return s.saveToPlacementNode(ctx, &nd, obj, signer, meta) + return s.saveToPlacementNode(ctx, &nd, obj, signer, meta, placement.container) }) } @@ -263,10 +263,10 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb } func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *objectwriter.NodeDescriptor, obj *objectSDK.Object, - signer *putSingleRequestSigner, meta object.ContentMeta, + signer *putSingleRequestSigner, meta object.ContentMeta, container containerSDK.Container, ) error { if nodeDesc.Local { - return s.saveLocal(ctx, obj, meta) + return s.saveLocal(ctx, obj, meta, container) } var info client.NodeInfo @@ -281,9 +281,10 @@ func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *objectwrite return s.redirectPutSingleRequest(ctx, signer, obj, info, c) } -func (s *Service) saveLocal(ctx context.Context, obj *objectSDK.Object, meta object.ContentMeta) error { +func (s *Service) saveLocal(ctx context.Context, obj *objectSDK.Object, meta object.ContentMeta, container containerSDK.Container) error { localTarget := &objectwriter.LocalTarget{ - Storage: s.Config.LocalStore, + Storage: s.Config.LocalStore, + Container: container, } return localTarget.WriteObject(ctx, obj, meta) } diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 06282bd8de..401977f663 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -37,7 +37,7 @@ func (p *Policer) processObject(ctx context.Context, objInfo objectcore.Info) er policy := cnr.Value.PlacementPolicy() if policycore.IsECPlacement(policy) { - return p.processECContainerObject(ctx, objInfo, policy) + return p.processECContainerObject(ctx, objInfo, cnr.Value) } return p.processRepContainerObject(ctx, objInfo, policy) } diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index e822d1c091..6d2c153c9c 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -10,6 +10,7 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" @@ -27,11 +28,11 @@ type ecChunkProcessResult struct { var errInvalidECPlacement = errors.New("invalid EC placement: EC placement must have one placement vector with at least one node") -func (p *Policer) processECContainerObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { +func (p *Policer) processECContainerObject(ctx context.Context, objInfo objectcore.Info, cnr containerSDK.Container) error { if objInfo.ECInfo == nil { - return p.processECContainerRepObject(ctx, objInfo, policy) + return p.processECContainerRepObject(ctx, objInfo, cnr.PlacementPolicy()) } - return p.processECContainerECObject(ctx, objInfo, policy) + return p.processECContainerECObject(ctx, objInfo, cnr) } // processECContainerRepObject processes non erasure coded objects in EC container: tombstones, locks and linking objects. @@ -67,8 +68,8 @@ func (p *Policer) processECContainerRepObject(ctx context.Context, objInfo objec return nil } -func (p *Policer) processECContainerECObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { - nn, err := p.placementBuilder.BuildPlacement(objInfo.Address.Container(), &objInfo.ECInfo.ParentID, policy) +func (p *Policer) processECContainerECObject(ctx context.Context, objInfo objectcore.Info, cnr containerSDK.Container) error { + nn, err := p.placementBuilder.BuildPlacement(objInfo.Address.Container(), &objInfo.ECInfo.ParentID, cnr.PlacementPolicy()) if err != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) } @@ -85,9 +86,9 @@ func (p *Policer) processECContainerECObject(ctx context.Context, objInfo object res := p.processECChunk(ctx, objInfo, nn[0]) if !res.validPlacement { // drop local chunk only if all required chunks are in place - res.removeLocal = res.removeLocal && p.pullRequiredECChunks(ctx, objInfo, nn[0]) + res.removeLocal = res.removeLocal && p.pullRequiredECChunks(ctx, objInfo, nn[0], cnr) } - p.adjustECPlacement(ctx, objInfo, nn[0], policy) + p.adjustECPlacement(ctx, objInfo, nn[0], cnr) if res.removeLocal { p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address)) @@ -138,7 +139,7 @@ func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, n } } -func (p *Policer) pullRequiredECChunks(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) bool { +func (p *Policer) pullRequiredECChunks(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo, cnr containerSDK.Container) bool { var parentAddress oid.Address parentAddress.SetContainer(objInfo.Address.Container()) parentAddress.SetObject(objInfo.ECInfo.ParentID) @@ -169,8 +170,9 @@ func (p *Policer) pullRequiredECChunks(ctx context.Context, objInfo objectcore.I addr.SetContainer(objInfo.Address.Container()) addr.SetObject(indexToObjectID[index]) p.replicator.HandlePullTask(ctx, replicator.Task{ - Addr: addr, - Nodes: candidates, + Addr: addr, + Nodes: candidates, + Container: cnr, }) } // there was some missing chunks, it's not ok @@ -245,7 +247,7 @@ func (p *Policer) resolveRemoteECChunks(ctx context.Context, parentAddress oid.A return true } -func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo, policy netmap.PlacementPolicy) { +func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo, cnr containerSDK.Container) { var parentAddress oid.Address parentAddress.SetContainer(objInfo.Address.Container()) parentAddress.SetObject(objInfo.ECInfo.ParentID) @@ -292,7 +294,7 @@ func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info if !restore || uint32(len(resolved)) == objInfo.ECInfo.Total { return } - if objInfo.ECInfo.Total-uint32(len(resolved)) > policy.ReplicaDescriptor(0).GetECParityCount() { + if objInfo.ECInfo.Total-uint32(len(resolved)) > cnr.PlacementPolicy().ReplicaDescriptor(0).GetECParityCount() { var found []uint32 for i := range resolved { found = append(found, i) @@ -300,11 +302,13 @@ func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info p.log.Error(logs.PolicerCouldNotRestoreObjectNotEnoughChunks, zap.Stringer("object", parentAddress), zap.Uint32s("found_chunks", found)) return } - p.restoreECObject(ctx, objInfo, parentAddress, nodes, resolved, chunkIDs, policy) + p.restoreECObject(ctx, objInfo, parentAddress, nodes, resolved, chunkIDs, cnr) } -func (p *Policer) restoreECObject(ctx context.Context, objInfo objectcore.Info, parentAddress oid.Address, nodes []netmap.NodeInfo, existedChunks map[uint32][]netmap.NodeInfo, chunkIDs map[uint32]oid.ID, policy netmap.PlacementPolicy) { - c, err := erasurecode.NewConstructor(int(policy.ReplicaDescriptor(0).GetECDataCount()), int(policy.ReplicaDescriptor(0).GetECParityCount())) +func (p *Policer) restoreECObject(ctx context.Context, objInfo objectcore.Info, parentAddress oid.Address, nodes []netmap.NodeInfo, existedChunks map[uint32][]netmap.NodeInfo, chunkIDs map[uint32]oid.ID, + cnr containerSDK.Container, +) { + c, err := erasurecode.NewConstructor(int(cnr.PlacementPolicy().ReplicaDescriptor(0).GetECDataCount()), int(cnr.PlacementPolicy().ReplicaDescriptor(0).GetECParityCount())) if err != nil { p.log.Error(logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) return @@ -339,8 +343,9 @@ func (p *Policer) restoreECObject(ctx context.Context, objInfo objectcore.Info, targetNode := nodes[idx%len(nodes)] if p.cfg.netmapKeys.IsLocalKey(targetNode.PublicKey()) { p.replicator.HandleLocalPutTask(ctx, replicator.Task{ - Addr: addr, - Obj: part, + Addr: addr, + Obj: part, + Container: cnr, }) } else { p.replicator.HandleReplicationTask(ctx, replicator.Task{ diff --git a/pkg/services/replicator/pull.go b/pkg/services/replicator/pull.go index d178700f67..7e70902379 100644 --- a/pkg/services/replicator/pull.go +++ b/pkg/services/replicator/pull.go @@ -5,6 +5,7 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" @@ -62,7 +63,7 @@ func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { return } - err := engine.Put(ctx, p.localStorage, obj) + err := engine.Put(ctx, p.localStorage, obj, containerCore.IsIndexedContainer(task.Container)) if err != nil { p.log.Error(logs.ReplicatorCouldNotPutObjectToLocalStorage, zap.Stringer("object", task.Addr), diff --git a/pkg/services/replicator/put.go b/pkg/services/replicator/put.go index c06ec3f659..5378335165 100644 --- a/pkg/services/replicator/put.go +++ b/pkg/services/replicator/put.go @@ -5,6 +5,7 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -37,7 +38,7 @@ func (p *Replicator) HandleLocalPutTask(ctx context.Context, task Task) { return } - err := engine.Put(ctx, p.localStorage, task.Obj) + err := engine.Put(ctx, p.localStorage, task.Obj, containerCore.IsIndexedContainer(task.Container)) if err != nil { p.log.Error(logs.ReplicatorCouldNotPutObjectToLocalStorage, zap.Stringer("object", task.Addr), diff --git a/pkg/services/replicator/task.go b/pkg/services/replicator/task.go index d2b5b25062..a03f8dcaa4 100644 --- a/pkg/services/replicator/task.go +++ b/pkg/services/replicator/task.go @@ -1,6 +1,7 @@ package replicator import ( + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -16,4 +17,6 @@ type Task struct { Obj *objectSDK.Object // Nodes is a list of potential object holders. Nodes []netmap.NodeInfo + + Container containerSDK.Container } From be744ae3e6eadb5b02952cbb110ef59f33f799bc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 1 Oct 2024 18:19:12 +0300 Subject: [PATCH 0888/1413] [#1412] metabase: Index attributes for indexed containers Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 4 +- pkg/local_object_storage/engine/evacuate.go | 11 +-- pkg/local_object_storage/engine/put.go | 5 +- pkg/local_object_storage/metabase/delete.go | 45 ++++++++++ .../metabase/delete_meta_test.go | 85 +++++++++++++++++++ pkg/local_object_storage/metabase/put.go | 80 ++++++++++++++++- pkg/local_object_storage/metabase/util.go | 8 +- pkg/local_object_storage/shard/put.go | 8 +- 8 files changed, 231 insertions(+), 15 deletions(-) create mode 100644 pkg/local_object_storage/metabase/delete_meta_test.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 5c322886bb..f2c4bff1db 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -535,6 +535,6 @@ func (e engineWithoutNotifications) Lock(ctx context.Context, locker oid.Address return e.engine.Lock(ctx, locker.Container(), locker.Object(), toLock) } -func (e engineWithoutNotifications) Put(ctx context.Context, o *objectSDK.Object, indexableContainer bool) error { - return engine.Put(ctx, e.engine, o, indexableContainer) +func (e engineWithoutNotifications) Put(ctx context.Context, o *objectSDK.Object, indexedContainer bool) error { + return engine.Put(ctx, e.engine, o, indexedContainer) } diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index a618ff2740..1baf237f91 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -18,6 +18,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -471,7 +472,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context default: } egObject.Go(func() error { - err := e.evacuateObject(ctx, shardID, objInfo, prm, res, shards, shardsToEvacuate) + err := e.evacuateObject(ctx, shardID, objInfo, prm, res, shards, shardsToEvacuate, c.Value) if err != nil { cancel(err) } @@ -744,7 +745,7 @@ func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) } func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objInfo *object.Info, prm EvacuateShardPrm, res *EvacuateShardRes, - getShards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, + getShards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, cnr containerSDK.Container, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateObjects") defer span.End() @@ -773,7 +774,7 @@ func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objI return err } - evacuatedLocal, err := e.tryEvacuateObjectLocal(ctx, addr, getRes.Object(), shardsToEvacuate[shardID], shards, shardsToEvacuate, res) + evacuatedLocal, err := e.tryEvacuateObjectLocal(ctx, addr, getRes.Object(), shardsToEvacuate[shardID], shards, shardsToEvacuate, res, cnr) if err != nil { return err } @@ -817,7 +818,7 @@ func (e *StorageEngine) isNotRepOne(c *container.Container) bool { } func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Address, object *objectSDK.Object, sh *shard.Shard, - shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes, + shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes, cnr containerSDK.Container, ) (bool, error) { hrw.SortHasherSliceByValue(shards, hrw.StringHash(addr.EncodeToString())) for j := range shards { @@ -830,7 +831,7 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add if _, ok := shardsToEvacuate[shards[j].ID().String()]; ok { continue } - switch e.putToShard(ctx, shards[j].hashedShard, shards[j].pool, addr, object).status { + switch e.putToShard(ctx, shards[j].hashedShard, shards[j].pool, addr, object, container.IsIndexedContainer(cnr)).status { case putToShardSuccess: res.objEvacuated.Add(1) e.log.Debug(logs.EngineObjectIsMovedToAnotherShard, diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 41e5665608..a50d80b75d 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -107,7 +107,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // Shard was concurrently removed, skip. return false } - shRes = e.putToShard(ctx, sh, pool, addr, prm.Object) + shRes = e.putToShard(ctx, sh, pool, addr, prm.Object, prm.IsIndexedContainer) return shRes.status != putToShardUnknown }) switch shRes.status { @@ -125,7 +125,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // putToShard puts object to sh. // Return putToShardStatus and error if it is necessary to propagate an error upper. func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool util.WorkerPool, - addr oid.Address, obj *objectSDK.Object, + addr oid.Address, obj *objectSDK.Object, isIndexedContainer bool, ) (res putToShardRes) { exitCh := make(chan struct{}) @@ -158,6 +158,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti var putPrm shard.PutPrm putPrm.SetObject(obj) + putPrm.SetIndexAttributes(isIndexedContainer) _, err = sh.Put(ctx, putPrm) if err != nil { diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 4ad11164f0..3add1f268e 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -338,6 +338,11 @@ func (db *DB) deleteObject( return fmt.Errorf("can't remove list indexes: %w", err) } + err = updateFKBTIndexes(tx, obj, delFKBTIndexItem) + if err != nil { + return fmt.Errorf("can't remove fake bucket tree indexes: %w", err) + } + if isParent { // remove record from the garbage bucket, because regular object deletion does nothing for virtual object garbageBKT := tx.Bucket(garbageBucketName) @@ -415,6 +420,46 @@ func delListIndexItem(tx *bbolt.Tx, item namedBucketItem) error { return nil } +func delFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { + bkt := tx.Bucket(item.name) + if bkt == nil { + return nil + } + + fkbtRoot := bkt.Bucket(item.key) + if fkbtRoot == nil { + return nil + } + + if err := fkbtRoot.Delete(item.val); err != nil { + return err + } + + if hasAnyItem(fkbtRoot) { + return nil + } + + if err := bkt.DeleteBucket(item.key); err != nil { + return err + } + + if hasAnyItem(bkt) { + return nil + } + + return tx.DeleteBucket(item.name) +} + +func hasAnyItem(b *bbolt.Bucket) bool { + var hasAnyItem bool + c := b.Cursor() + for k, _ := c.First(); k != nil; k, _ = c.Next() { + hasAnyItem = true + break + } + return hasAnyItem +} + func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error { addr := object.AddressOf(obj) diff --git a/pkg/local_object_storage/metabase/delete_meta_test.go b/pkg/local_object_storage/metabase/delete_meta_test.go new file mode 100644 index 0000000000..cdfe2a2031 --- /dev/null +++ b/pkg/local_object_storage/metabase/delete_meta_test.go @@ -0,0 +1,85 @@ +package meta + +import ( + "bytes" + "context" + "path/filepath" + "testing" + + objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "github.com/stretchr/testify/require" + "go.etcd.io/bbolt" +) + +func TestPutDeleteIndexAttributes(t *testing.T) { + db := New([]Option{ + WithPath(filepath.Join(t.TempDir(), "metabase")), + WithPermissions(0o600), + WithEpochState(epochState{}), + }...) + + require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) + require.NoError(t, db.Init()) + defer func() { require.NoError(t, db.Close()) }() + + cnr := cidtest.ID() + obj1 := testutil.GenerateObjectWithCID(cnr) + testutil.AddAttribute(obj1, "S3-Access-Box-CRDT-Name", "CRDT-Name") + testutil.AddAttribute(obj1, objectSDK.AttributeFilePath, "/path/to/object") + + var putPrm PutPrm + putPrm.SetObject(obj1) + + _, err := db.Put(context.Background(), putPrm) + require.NoError(t, err) + + require.NoError(t, db.boltDB.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(attributeBucketName(cnr, "S3-Access-Box-CRDT-Name", make([]byte, bucketKeySize))) + require.Nil(t, b) + b = tx.Bucket(attributeBucketName(cnr, objectSDK.AttributeFilePath, make([]byte, bucketKeySize))) + require.Nil(t, b) + return nil + })) + + obj2 := testutil.GenerateObjectWithCID(cnr) + testutil.AddAttribute(obj2, "S3-Access-Box-CRDT-Name", "CRDT-Name") + testutil.AddAttribute(obj2, objectSDK.AttributeFilePath, "/path/to/object") + + putPrm.SetObject(obj2) + putPrm.SetIndexAttributes(true) + + _, err = db.Put(context.Background(), putPrm) + require.NoError(t, err) + + objKey := objectKey(objectCore.AddressOf(obj2).Object(), make([]byte, objectKeySize)) + require.NoError(t, db.boltDB.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(attributeBucketName(cnr, "S3-Access-Box-CRDT-Name", make([]byte, bucketKeySize))) + require.NotNil(t, b) + b = b.Bucket([]byte("CRDT-Name")) + require.NotNil(t, b) + require.True(t, bytes.Equal(zeroValue, b.Get(objKey))) + b = tx.Bucket(attributeBucketName(cnr, objectSDK.AttributeFilePath, make([]byte, bucketKeySize))) + require.NotNil(t, b) + b = b.Bucket([]byte("/path/to/object")) + require.NotNil(t, b) + require.True(t, bytes.Equal(zeroValue, b.Get(objKey))) + return nil + })) + + var dPrm DeletePrm + dPrm.SetAddresses(objectCore.AddressOf(obj1), objectCore.AddressOf(obj2)) + _, err = db.Delete(context.Background(), dPrm) + require.NoError(t, err) + + require.NoError(t, db.boltDB.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(attributeBucketName(cnr, "S3-Access-Box-CRDT-Name", make([]byte, bucketKeySize))) + require.Nil(t, b) + b = tx.Bucket(attributeBucketName(cnr, objectSDK.AttributeFilePath, make([]byte, bucketKeySize))) + require.Nil(t, b) + return nil + })) +} diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 0875298953..0c14196b7c 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -35,6 +35,8 @@ type PutPrm struct { obj *objectSDK.Object id []byte + + indexAttributes bool } // PutRes groups the resulting values of Put operation. @@ -52,6 +54,10 @@ func (p *PutPrm) SetStorageID(id []byte) { p.id = id } +func (p *PutPrm) SetIndexAttributes(v bool) { + p.indexAttributes = v +} + var ( ErrUnknownObjectType = errors.New("unknown object type") ErrIncorrectSplitInfoUpdate = errors.New("updating split info on object without it") @@ -90,7 +96,7 @@ func (db *DB) Put(ctx context.Context, prm PutPrm) (res PutRes, err error) { err = db.boltDB.Batch(func(tx *bbolt.Tx) error { var e error - res, e = db.put(tx, prm.obj, prm.id, nil, currEpoch) + res, e = db.put(tx, prm.obj, prm.id, nil, currEpoch, prm.indexAttributes) return e }) if err == nil { @@ -108,6 +114,7 @@ func (db *DB) put(tx *bbolt.Tx, id []byte, si *objectSDK.SplitInfo, currEpoch uint64, + indexAttributes bool, ) (PutRes, error) { cnr, ok := obj.ContainerID() if !ok { @@ -129,7 +136,7 @@ func (db *DB) put(tx *bbolt.Tx, return PutRes{}, db.updateObj(tx, obj, id, si, isParent) } - return PutRes{Inserted: true}, db.insertObject(tx, obj, id, si, isParent, cnr, currEpoch) + return PutRes{Inserted: true}, db.insertObject(tx, obj, id, si, isParent, cnr, currEpoch, indexAttributes) } func (db *DB) updateObj(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *objectSDK.SplitInfo, isParent bool) error { @@ -152,14 +159,14 @@ func (db *DB) updateObj(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *obje return nil } -func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *objectSDK.SplitInfo, isParent bool, cnr cid.ID, currEpoch uint64) error { +func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *objectSDK.SplitInfo, isParent bool, cnr cid.ID, currEpoch uint64, indexAttributes bool) error { if par := obj.Parent(); par != nil && !isParent { // limit depth by two parentSI, err := splitInfoFromObject(obj) if err != nil { return err } - _, err = db.put(tx, par, id, parentSI, currEpoch) + _, err = db.put(tx, par, id, parentSI, currEpoch, indexAttributes) if err != nil { return err } @@ -175,6 +182,13 @@ func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *o return fmt.Errorf("can't put list indexes: %w", err) } + if indexAttributes { + err = updateFKBTIndexes(tx, obj, putFKBTIndexItem) + if err != nil { + return fmt.Errorf("can't put fake bucket tree indexes: %w", err) + } + } + // update container volume size estimation if obj.Type() == objectSDK.TypeRegular && !isParent { err = changeContainerSize(tx, cnr, obj.PayloadSize(), true) @@ -381,6 +395,50 @@ func updateListIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFun return nil } +var indexedAttributes = map[string]struct{}{ + "S3-Access-Box-CRDT-Name": {}, + objectSDK.AttributeFilePath: {}, +} + +// IsAtrributeIndexed returns True if attribute is indexed by metabase. +func IsAtrributeIndexed(attr string) bool { + _, found := indexedAttributes[attr] + return found +} + +func updateFKBTIndexes(tx *bbolt.Tx, obj *objectSDK.Object, f updateIndexItemFunc) error { + id, _ := obj.ID() + cnr, _ := obj.ContainerID() + objKey := objectKey(id, make([]byte, objectKeySize)) + + key := make([]byte, bucketKeySize) + var attrs []objectSDK.Attribute + if obj.ECHeader() != nil { + attrs = obj.ECHeader().ParentAttributes() + objKey = objectKey(obj.ECHeader().Parent(), make([]byte, objectKeySize)) + } else { + attrs = obj.Attributes() + } + + // user specified attributes + for i := range attrs { + if !IsAtrributeIndexed(attrs[i].Key()) { + continue + } + key = attributeBucketName(cnr, attrs[i].Key(), key) + err := f(tx, namedBucketItem{ + name: key, + key: []byte(attrs[i].Value()), + val: objKey, + }) + if err != nil { + return err + } + } + + return nil +} + func hasExpirationEpoch(obj *objectSDK.Object) (uint64, bool) { attributes := obj.Attributes() if ech := obj.ECHeader(); ech != nil { @@ -425,6 +483,20 @@ func putUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) error { return updateUniqueIndexItem(tx, item, func(_, val []byte) ([]byte, error) { return val, nil }) } +func putFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { + bkt, err := createBucketLikelyExists(tx, item.name) + if err != nil { + return fmt.Errorf("can't create index %v: %w", item.name, err) + } + + fkbtRoot, err := createBucketLikelyExists(bkt, item.key) + if err != nil { + return fmt.Errorf("can't create fake bucket tree index %v: %w", item.key, err) + } + + return fkbtRoot.Put(item.val, zeroValue) +} + func putListIndexItem(tx *bbolt.Tx, item namedBucketItem) error { bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index eef7210dc2..4679de332e 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -99,7 +99,6 @@ const ( // userAttributePrefix was used for prefixing FKBT index buckets containing objects. // Key: attribute value // Value: bucket containing object IDs as keys - // removed in version 3 userAttributePrefix // ==================== @@ -170,6 +169,13 @@ func smallBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, smallPrefix, key) } +// attributeBucketName returns _. +func attributeBucketName(cnr cid.ID, attributeKey string, key []byte) []byte { + key[0] = userAttributePrefix + cnr.Encode(key[1:]) + return append(key[:bucketKeySize], attributeKey...) +} + // rootBucketName returns _root. func rootBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, rootPrefix, key) diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index d7a9e70126..24cc751547 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -17,7 +17,8 @@ import ( // PutPrm groups the parameters of Put operation. type PutPrm struct { - obj *objectSDK.Object + obj *objectSDK.Object + indexAttributes bool } // PutRes groups the resulting values of Put operation. @@ -28,6 +29,10 @@ func (p *PutPrm) SetObject(obj *objectSDK.Object) { p.obj = obj } +func (p *PutPrm) SetIndexAttributes(v bool) { + p.indexAttributes = v +} + // Put saves the object in shard. // // Returns any error encountered that @@ -84,6 +89,7 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { var pPrm meta.PutPrm pPrm.SetObject(prm.obj) pPrm.SetStorageID(res.StorageID) + pPrm.SetIndexAttributes(prm.indexAttributes) res, err := s.metaBase.Put(ctx, pPrm) if err != nil { // may we need to handle this case in a special way From 1efa64ee72851e53ca5eb2bf643e74141b41ca46 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 2 Oct 2024 13:04:29 +0300 Subject: [PATCH 0889/1413] [#1412] metabase: Add search by indexed attributes Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/db_test.go | 12 +- pkg/local_object_storage/metabase/select.go | 115 ++++++++++++++++-- .../metabase/select_test.go | 81 +++++++----- 3 files changed, 169 insertions(+), 39 deletions(-) diff --git a/pkg/local_object_storage/metabase/db_test.go b/pkg/local_object_storage/metabase/db_test.go index 01e1ed2bc1..0abb5ea892 100644 --- a/pkg/local_object_storage/metabase/db_test.go +++ b/pkg/local_object_storage/metabase/db_test.go @@ -32,7 +32,17 @@ func putBig(db *meta.DB, obj *objectSDK.Object) error { } func testSelect(t *testing.T, db *meta.DB, cnr cid.ID, fs objectSDK.SearchFilters, exp ...oid.Address) { - res, err := metaSelect(db, cnr, fs) + res, err := metaSelect(db, cnr, fs, false) + require.NoError(t, err) + require.Len(t, res, len(exp)) + + for i := range exp { + require.Contains(t, res, exp[i]) + } +} + +func testSelect2(t *testing.T, db *meta.DB, cnr cid.ID, fs objectSDK.SearchFilters, useAttrIndex bool, exp ...oid.Address) { + res, err := metaSelect(db, cnr, fs, useAttrIndex) require.NoError(t, err) require.Len(t, res, len(exp)) diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 85d1b08ba0..88ef7d5a40 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -37,8 +37,9 @@ type ( // SelectPrm groups the parameters of Select operation. type SelectPrm struct { - cnr cid.ID - filters objectSDK.SearchFilters + cnr cid.ID + filters objectSDK.SearchFilters + useAttributeIndex bool } // SelectRes groups the resulting values of Select operation. @@ -56,6 +57,10 @@ func (p *SelectPrm) SetFilters(fs objectSDK.SearchFilters) { p.filters = fs } +func (p *SelectPrm) SetUseAttributeIndex(v bool) { + p.useAttributeIndex = v +} + // AddressList returns list of addresses of the selected objects. func (r SelectRes) AddressList() []oid.Address { return r.addrList @@ -92,14 +97,14 @@ func (db *DB) Select(ctx context.Context, prm SelectPrm) (res SelectRes, err err currEpoch := db.epochState.CurrentEpoch() return res, metaerr.Wrap(db.boltDB.View(func(tx *bbolt.Tx) error { - res.addrList, err = db.selectObjects(tx, prm.cnr, prm.filters, currEpoch) + res.addrList, err = db.selectObjects(tx, prm.cnr, prm.filters, currEpoch, prm.useAttributeIndex) success = err == nil return err })) } -func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters, currEpoch uint64) ([]oid.Address, error) { - group, err := groupFilters(fs) +func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters, currEpoch uint64, useAttributeIndex bool) ([]oid.Address, error) { + group, err := groupFilters(fs, useAttributeIndex) if err != nil { return nil, err } @@ -218,7 +223,13 @@ func (db *DB) selectFastFilter( selectAllFromBucket(tx, primaryBucketName(cnr, bucketName), to, fNum) selectAllFromBucket(tx, tombstoneBucketName(cnr, bucketName), to, fNum) selectAllFromBucket(tx, bucketNameLockers(cnr, bucketName), to, fNum) - default: + default: // user attribute + bucketName := attributeBucketName(cnr, f.Header(), bucketName) + if f.Operation() == objectSDK.MatchNotPresent { + selectOutsideFKBT(tx, allBucketNames(cnr), bucketName, to, fNum) + } else { + db.selectFromFKBT(tx, bucketName, f, to, fNum) + } } } @@ -228,6 +239,15 @@ var mBucketNaming = map[string][]func(cid.ID, []byte) []byte{ v2object.TypeLock.String(): {bucketNameLockers}, } +func allBucketNames(cnr cid.ID) (names [][]byte) { + for _, fns := range mBucketNaming { + for _, fn := range fns { + names = append(names, fn(cnr, make([]byte, bucketKeySize))) + } + } + return +} + func bucketNamesForType(cnr cid.ID, mType objectSDK.SearchMatchType, typeVal string) (names [][]byte) { appendNames := func(key string) { fns, ok := mBucketNaming[key] @@ -259,6 +279,81 @@ func bucketNamesForType(cnr cid.ID, mType objectSDK.SearchMatchType, typeVal str return } +func (db *DB) selectFromFKBT( + tx *bbolt.Tx, + name []byte, // fkbt root bucket name + f objectSDK.SearchFilter, // filter for operation and value + to map[string]int, // resulting cache + fNum int, // index of filter +) { // + matchFunc, ok := db.matchers[f.Operation()] + if !ok { + db.log.Debug(logs.MetabaseMissingMatcher, zap.Stringer("operation", f.Operation())) + + return + } + + fkbtRoot := tx.Bucket(name) + if fkbtRoot == nil { + return + } + + err := matchFunc.matchBucket(fkbtRoot, f.Header(), f.Value(), func(k, _ []byte) error { + fkbtLeaf := fkbtRoot.Bucket(k) + if fkbtLeaf == nil { + return nil + } + + return fkbtLeaf.ForEach(func(k, _ []byte) error { + markAddressInCache(to, fNum, string(k)) + + return nil + }) + }) + if err != nil { + db.log.Debug(logs.MetabaseErrorInFKBTSelection, zap.String("error", err.Error())) + } +} + +// selectOutsideFKBT looks into all incl buckets to find list of addresses outside to add in +// resulting cache. +func selectOutsideFKBT( + tx *bbolt.Tx, + incl [][]byte, // buckets + name []byte, // fkbt root bucket name + to map[string]int, // resulting cache + fNum int, // index of filter +) { + mExcl := make(map[string]struct{}) + + bktExcl := tx.Bucket(name) + if bktExcl != nil { + _ = bktExcl.ForEachBucket(func(k []byte) error { + exclBktLeaf := bktExcl.Bucket(k) + return exclBktLeaf.ForEach(func(k, _ []byte) error { + mExcl[string(k)] = struct{}{} + + return nil + }) + }) + } + + for i := range incl { + bktIncl := tx.Bucket(incl[i]) + if bktIncl == nil { + continue + } + + _ = bktIncl.ForEach(func(k, _ []byte) error { + if _, ok := mExcl[string(k)]; !ok { + markAddressInCache(to, fNum, string(k)) + } + + return nil + }) + } +} + // selectFromList looks into index to find list of addresses to add in // resulting cache. func (db *DB) selectFromList( @@ -486,7 +581,7 @@ func attributeValue(obj *objectSDK.Object, attribute string) (string, bool) { // groupFilters divides filters in two groups: fast and slow. Fast filters // processed by indexes and slow filters processed after by unmarshaling // object headers. -func groupFilters(filters objectSDK.SearchFilters) (filterGroup, error) { +func groupFilters(filters objectSDK.SearchFilters, useAttributeIndex bool) (filterGroup, error) { res := filterGroup{ fastFilters: make(objectSDK.SearchFilters, 0, len(filters)), slowFilters: make(objectSDK.SearchFilters, 0, len(filters)), @@ -511,7 +606,11 @@ func groupFilters(filters objectSDK.SearchFilters) (filterGroup, error) { v2object.FilterPropertyPhy: res.fastFilters = append(res.fastFilters, filters[i]) default: - res.slowFilters = append(res.slowFilters, filters[i]) + if useAttributeIndex && IsAtrributeIndexed(filters[i].Header()) { + res.fastFilters = append(res.fastFilters, filters[i]) + } else { + res.slowFilters = append(res.slowFilters, filters[i]) + } } } diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index bee778e2b4..5cc25a9f6b 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -26,6 +26,16 @@ import ( func TestDB_SelectUserAttributes(t *testing.T) { t.Parallel() + t.Run("with_index", func(t *testing.T) { + testSelectUserAttributes(t, true) + }) + t.Run("without_index", func(t *testing.T) { + testSelectUserAttributes(t, false) + }) +} + +func testSelectUserAttributes(t *testing.T, index bool) { + t.Parallel() db := newDB(t) defer func() { require.NoError(t, db.Close()) }() @@ -36,44 +46,52 @@ func TestDB_SelectUserAttributes(t *testing.T) { testutil.AddAttribute(raw1, "foo", "bar") testutil.AddAttribute(raw1, "x", "y") - err := putBig(db, raw1) + var putPrm meta.PutPrm + putPrm.SetIndexAttributes(index) + putPrm.SetObject(raw1) + _, err := db.Put(context.Background(), putPrm) require.NoError(t, err) raw2 := testutil.GenerateObjectWithCID(cnr) testutil.AddAttribute(raw2, "foo", "bar") testutil.AddAttribute(raw2, "x", "z") - err = putBig(db, raw2) + putPrm.SetObject(raw2) + _, err = db.Put(context.Background(), putPrm) require.NoError(t, err) raw3 := testutil.GenerateObjectWithCID(cnr) testutil.AddAttribute(raw3, "a", "b") - err = putBig(db, raw3) + putPrm.SetObject(raw3) + _, err = db.Put(context.Background(), putPrm) require.NoError(t, err) raw4 := testutil.GenerateObjectWithCID(cnr) - testutil.AddAttribute(raw4, "path", "test/1/2") + testutil.AddAttribute(raw4, objectSDK.AttributeFilePath, "/test/1/2") - err = putBig(db, raw4) + putPrm.SetObject(raw4) + _, err = db.Put(context.Background(), putPrm) require.NoError(t, err) raw5 := testutil.GenerateObjectWithCID(cnr) - testutil.AddAttribute(raw5, "path", "test/1/3") + testutil.AddAttribute(raw5, objectSDK.AttributeFilePath, "/test/1/3") - err = putBig(db, raw5) + putPrm.SetObject(raw5) + _, err = db.Put(context.Background(), putPrm) require.NoError(t, err) raw6 := testutil.GenerateObjectWithCID(cnr) - testutil.AddAttribute(raw6, "path", "test/2/3") + testutil.AddAttribute(raw6, objectSDK.AttributeFilePath, "/test/2/3") - err = putBig(db, raw6) + putPrm.SetObject(raw6) + _, err = db.Put(context.Background(), putPrm) require.NoError(t, err) raw7 := testutil.GenerateObjectWithCID(cnr) var attr objectSDK.Attribute - attr.SetKey("path") - attr.SetValue("test/3/4") + attr.SetKey(objectSDK.AttributeFilePath) + attr.SetValue("/test/3/4") attrs := raw7.Attributes() attrs = append(attrs, attr) ech := objectSDK.NewECHeader(objectSDK.ECParentInfo{ @@ -81,37 +99,39 @@ func TestDB_SelectUserAttributes(t *testing.T) { Attributes: attrs, }, 0, 3, []byte{}, 0) raw7.SetECHeader(ech) - require.NoError(t, putBig(db, raw7)) + putPrm.SetObject(raw7) + _, err = db.Put(context.Background(), putPrm) + require.NoError(t, err) var raw7Parent oid.Address raw7Parent.SetContainer(cnr) raw7Parent.SetObject(ech.Parent()) fs := objectSDK.SearchFilters{} fs.AddFilter("foo", "bar", objectSDK.MatchStringEqual) - testSelect(t, db, cnr, fs, + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw1), object.AddressOf(raw2), ) fs = objectSDK.SearchFilters{} fs.AddFilter("x", "y", objectSDK.MatchStringEqual) - testSelect(t, db, cnr, fs, object.AddressOf(raw1)) + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw1)) fs = objectSDK.SearchFilters{} fs.AddFilter("x", "y", objectSDK.MatchStringNotEqual) - testSelect(t, db, cnr, fs, object.AddressOf(raw2)) + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw2)) fs = objectSDK.SearchFilters{} fs.AddFilter("a", "b", objectSDK.MatchStringEqual) - testSelect(t, db, cnr, fs, object.AddressOf(raw3)) + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw3)) fs = objectSDK.SearchFilters{} fs.AddFilter("c", "d", objectSDK.MatchStringEqual) - testSelect(t, db, cnr, fs) + testSelect2(t, db, cnr, fs, index) fs = objectSDK.SearchFilters{} fs.AddFilter("foo", "", objectSDK.MatchNotPresent) - testSelect(t, db, cnr, fs, + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw3), object.AddressOf(raw4), object.AddressOf(raw5), @@ -121,7 +141,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { fs = objectSDK.SearchFilters{} fs.AddFilter("a", "", objectSDK.MatchNotPresent) - testSelect(t, db, cnr, fs, + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw1), object.AddressOf(raw2), object.AddressOf(raw4), @@ -131,7 +151,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { ) fs = objectSDK.SearchFilters{} - testSelect(t, db, cnr, fs, + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw1), object.AddressOf(raw2), object.AddressOf(raw3), @@ -143,7 +163,7 @@ func TestDB_SelectUserAttributes(t *testing.T) { fs = objectSDK.SearchFilters{} fs.AddFilter("key", "", objectSDK.MatchNotPresent) - testSelect(t, db, cnr, fs, + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw1), object.AddressOf(raw2), object.AddressOf(raw3), @@ -154,8 +174,8 @@ func TestDB_SelectUserAttributes(t *testing.T) { ) fs = objectSDK.SearchFilters{} - fs.AddFilter("path", "test", objectSDK.MatchCommonPrefix) - testSelect(t, db, cnr, fs, + fs.AddFilter(objectSDK.AttributeFilePath, "/test", objectSDK.MatchCommonPrefix) + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw4), object.AddressOf(raw5), object.AddressOf(raw6), @@ -163,15 +183,15 @@ func TestDB_SelectUserAttributes(t *testing.T) { ) fs = objectSDK.SearchFilters{} - fs.AddFilter("path", "test/1", objectSDK.MatchCommonPrefix) - testSelect(t, db, cnr, fs, + fs.AddFilter(objectSDK.AttributeFilePath, "/test/1", objectSDK.MatchCommonPrefix) + testSelect2(t, db, cnr, fs, index, object.AddressOf(raw4), object.AddressOf(raw5), ) fs = objectSDK.SearchFilters{} - fs.AddFilter("path", "test/3/4", objectSDK.MatchStringEqual) - testSelect(t, db, cnr, fs, + fs.AddFilter(objectSDK.AttributeFilePath, "/test/3/4", objectSDK.MatchStringEqual) + testSelect2(t, db, cnr, fs, index, raw7Parent, ) } @@ -1185,11 +1205,11 @@ func TestExpiredObjects(t *testing.T) { cidExp, _ := exp.ContainerID() cidNonExp, _ := nonExp.ContainerID() - objs, err := metaSelect(db, cidExp, objectSDK.SearchFilters{}) + objs, err := metaSelect(db, cidExp, objectSDK.SearchFilters{}, false) require.NoError(t, err) require.Empty(t, objs) // expired object should not be returned - objs, err = metaSelect(db, cidNonExp, objectSDK.SearchFilters{}) + objs, err = metaSelect(db, cidNonExp, objectSDK.SearchFilters{}, false) require.NoError(t, err) require.NotEmpty(t, objs) }) @@ -1211,10 +1231,11 @@ func benchmarkSelect(b *testing.B, db *meta.DB, cid cidSDK.ID, fs objectSDK.Sear } } -func metaSelect(db *meta.DB, cnr cidSDK.ID, fs objectSDK.SearchFilters) ([]oid.Address, error) { +func metaSelect(db *meta.DB, cnr cidSDK.ID, fs objectSDK.SearchFilters, useAttributeIndex bool) ([]oid.Address, error) { var prm meta.SelectPrm prm.SetFilters(fs) prm.SetContainerID(cnr) + prm.SetUseAttributeIndex(useAttributeIndex) res, err := db.Select(context.Background(), prm) return res.AddressList(), err From 4572fa487493f21cc5ebffcdc526270452a36e6a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 2 Oct 2024 14:52:54 +0300 Subject: [PATCH 0890/1413] [#1412] searchSvc: Check container is indexed For non S3 containers it is expected to use attributes index for some attributes. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 5 +++-- pkg/local_object_storage/engine/delete.go | 2 +- pkg/local_object_storage/engine/inhume_test.go | 4 ++-- pkg/local_object_storage/engine/select.go | 14 ++++++++------ pkg/local_object_storage/engine/tree_test.go | 2 +- pkg/local_object_storage/shard/select.go | 9 ++++++--- pkg/services/object/search/container.go | 10 ++++++++++ pkg/services/object/search/service.go | 4 ++++ pkg/services/object/search/util.go | 7 ++++++- 9 files changed, 41 insertions(+), 16 deletions(-) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index f2c4bff1db..68acb05d34 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -174,7 +174,7 @@ func initObjectService(c *cfg) { sPutV2 := createPutSvcV2(sPut, keyStorage) - sSearch := createSearchSvc(c, keyStorage, traverseGen, c.clientCache) + sSearch := createSearchSvc(c, keyStorage, traverseGen, c.clientCache, c.cfgObject.cnrSource) sSearchV2 := createSearchSvcV2(sSearch, keyStorage) @@ -366,7 +366,7 @@ func createPatchSvc(sGet *getsvc.Service, sPut *putsvc.Service) *patchsvc.Servic return patchsvc.NewService(sPut.Config, sGet) } -func createSearchSvc(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.TraverserGenerator, coreConstructor *cache.ClientCache) *searchsvc.Service { +func createSearchSvc(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.TraverserGenerator, coreConstructor *cache.ClientCache, containerSource containercore.Source) *searchsvc.Service { ls := c.cfgObject.cfgLocalStorage.localStorage return searchsvc.New( @@ -377,6 +377,7 @@ func createSearchSvc(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.Trav ), c.netMapSource, keyStorage, + containerSource, searchsvc.WithLogger(c.log), ) } diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 61cb6832d2..3ec3f8f9b5 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -143,7 +143,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo var selectPrm shard.SelectPrm selectPrm.SetFilters(fs) - selectPrm.SetContainerID(addr.Container()) + selectPrm.SetContainerID(addr.Container(), false) // doesn't matter for search by splitID var inhumePrm shard.InhumePrm if force { diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index f87679253a..b4fbbd8100 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -49,7 +49,7 @@ func TestStorageEngine_Inhume(t *testing.T) { _, err = e.Inhume(context.Background(), inhumePrm) require.NoError(t, err) - addrs, err := Select(context.Background(), e, cnr, fs) + addrs, err := Select(context.Background(), e, cnr, false, fs) require.NoError(t, err) require.Empty(t, addrs) }) @@ -78,7 +78,7 @@ func TestStorageEngine_Inhume(t *testing.T) { _, err = e.Inhume(context.Background(), inhumePrm) require.NoError(t, err) - addrs, err := Select(context.Background(), e, cnr, fs) + addrs, err := Select(context.Background(), e, cnr, false, fs) require.NoError(t, err) require.Empty(t, addrs) }) diff --git a/pkg/local_object_storage/engine/select.go b/pkg/local_object_storage/engine/select.go index 972a4f52a2..a85891f0c5 100644 --- a/pkg/local_object_storage/engine/select.go +++ b/pkg/local_object_storage/engine/select.go @@ -14,8 +14,9 @@ import ( // SelectPrm groups the parameters of Select operation. type SelectPrm struct { - cnr cid.ID - filters objectSDK.SearchFilters + cnr cid.ID + filters objectSDK.SearchFilters + indexedContainer bool } // SelectRes groups the resulting values of Select operation. @@ -24,8 +25,9 @@ type SelectRes struct { } // WithContainerID is a Select option to set the container id to search in. -func (p *SelectPrm) WithContainerID(cnr cid.ID) { +func (p *SelectPrm) WithContainerID(cnr cid.ID, indexedContainer bool) { p.cnr = cnr + p.indexedContainer = indexedContainer } // WithFilters is a Select option to set the object filters. @@ -67,7 +69,7 @@ func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, var outError error var shPrm shard.SelectPrm - shPrm.SetContainerID(prm.cnr) + shPrm.SetContainerID(prm.cnr, prm.indexedContainer) shPrm.SetFilters(prm.filters) e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { @@ -140,9 +142,9 @@ func (e *StorageEngine) list(ctx context.Context, limit uint64) (SelectRes, erro } // Select selects objects from local storage using provided filters. -func Select(ctx context.Context, storage *StorageEngine, cnr cid.ID, fs objectSDK.SearchFilters) ([]oid.Address, error) { +func Select(ctx context.Context, storage *StorageEngine, cnr cid.ID, isIndexedContainer bool, fs objectSDK.SearchFilters) ([]oid.Address, error) { var selectPrm SelectPrm - selectPrm.WithContainerID(cnr) + selectPrm.WithContainerID(cnr, isIndexedContainer) selectPrm.WithFilters(fs) res, err := storage.Select(ctx, selectPrm) diff --git a/pkg/local_object_storage/engine/tree_test.go b/pkg/local_object_storage/engine/tree_test.go index 21fcce4153..ea0a9e74ea 100644 --- a/pkg/local_object_storage/engine/tree_test.go +++ b/pkg/local_object_storage/engine/tree_test.go @@ -50,7 +50,7 @@ func benchmarkTreeVsSearch(b *testing.B, objCount int) { b.Run("search", func(b *testing.B) { var prm SelectPrm - prm.WithContainerID(cid) + prm.WithContainerID(cid, true) var fs objectSDK.SearchFilters fs.AddFilter(pilorama.AttributeFilename, strconv.Itoa(objCount/2), objectSDK.MatchStringEqual) diff --git a/pkg/local_object_storage/shard/select.go b/pkg/local_object_storage/shard/select.go index 1615f5fbe5..184ca9b712 100644 --- a/pkg/local_object_storage/shard/select.go +++ b/pkg/local_object_storage/shard/select.go @@ -15,8 +15,9 @@ import ( // SelectPrm groups the parameters of Select operation. type SelectPrm struct { - cnr cid.ID - filters objectSDK.SearchFilters + cnr cid.ID + filters objectSDK.SearchFilters + isIndexedContainer bool } // SelectRes groups the resulting values of Select operation. @@ -25,8 +26,9 @@ type SelectRes struct { } // SetContainerID is a Select option to set the container id to search in. -func (p *SelectPrm) SetContainerID(cnr cid.ID) { +func (p *SelectPrm) SetContainerID(cnr cid.ID, isIndexedContainer bool) { p.cnr = cnr + p.isIndexedContainer = isIndexedContainer } // SetFilters is a Select option to set the object filters. @@ -61,6 +63,7 @@ func (s *Shard) Select(ctx context.Context, prm SelectPrm) (SelectRes, error) { var selectPrm meta.SelectPrm selectPrm.SetFilters(prm.filters) selectPrm.SetContainerID(prm.cnr) + selectPrm.SetUseAttributeIndex(prm.isIndexedContainer) mRes, err := s.metaBase.Select(ctx, selectPrm) if err != nil { diff --git a/pkg/services/object/search/container.go b/pkg/services/object/search/container.go index d705741568..39259b0cac 100644 --- a/pkg/services/object/search/container.go +++ b/pkg/services/object/search/container.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "go.uber.org/zap" ) @@ -112,3 +113,12 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { return nil } + +func (exec *execCtx) getContainer() (containerSDK.Container, error) { + cnrID := exec.containerID() + cnr, err := exec.svc.containerSource.Get(cnrID) + if err != nil { + return containerSDK.Container{}, err + } + return cnr.Value, nil +} diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index cc388c1b21..7700f78d87 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -54,6 +54,8 @@ type cfg struct { } keyStore *util.KeyStorage + + containerSource container.Source } // New creates, initializes and returns utility serving @@ -63,6 +65,7 @@ func New(e *engine.StorageEngine, tg *util.TraverserGenerator, ns netmap.Source, ks *util.KeyStorage, + cs container.Source, opts ...Option, ) *Service { c := &cfg{ @@ -76,6 +79,7 @@ func New(e *engine.StorageEngine, traverserGenerator: tg, currentEpochReceiver: ns, keyStore: ks, + containerSource: cs, } for i := range opts { diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index 67b6c0d016..910384a0bc 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -5,6 +5,7 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" @@ -112,9 +113,13 @@ func (c *clientWrapper) searchObjects(ctx context.Context, exec *execCtx, info c } func (e *storageEngineWrapper) search(ctx context.Context, exec *execCtx) ([]oid.ID, error) { + cnr, err := exec.getContainer() + if err != nil { + return nil, err + } var selectPrm engine.SelectPrm selectPrm.WithFilters(exec.searchFilters()) - selectPrm.WithContainerID(exec.containerID()) + selectPrm.WithContainerID(exec.containerID(), container.IsIndexedContainer(cnr)) r, err := e.storage.Select(ctx, selectPrm) if err != nil { From 3da168f8cf96cb342c4cfe753e38c8a0bd7ad0a4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 2 Oct 2024 16:46:39 +0300 Subject: [PATCH 0891/1413] [#1412] shard: Resolve container is indexed on metabase resync Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 23 +++++++++++++++++++++-- internal/logs/logs.go | 1 + pkg/local_object_storage/shard/control.go | 17 +++++++++++++++++ pkg/local_object_storage/shard/shard.go | 10 ++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 4ad9ec6c62..3c7e310b41 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1058,7 +1058,9 @@ func initLocalStorage(ctx context.Context, c *cfg) { var shardsAttached int for _, optsWithMeta := range c.shardOpts(ctx) { - id, err := ls.AddShard(ctx, append(optsWithMeta.shOpts, shard.WithTombstoneSource(c.createTombstoneSource()))...) + id, err := ls.AddShard(ctx, append(optsWithMeta.shOpts, + shard.WithTombstoneSource(c.createTombstoneSource()), + shard.WithContainerInfoProvider(c.createContainerInfoProvider(ctx)))...) if err != nil { c.log.Error(logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err)) } else { @@ -1313,7 +1315,10 @@ func (c *cfg) reloadConfig(ctx context.Context) { var rcfg engine.ReConfiguration for _, optsWithID := range c.shardOpts(ctx) { - rcfg.AddShard(optsWithID.configID, append(optsWithID.shOpts, shard.WithTombstoneSource(c.createTombstoneSource()))) + rcfg.AddShard(optsWithID.configID, append(optsWithID.shOpts, + shard.WithTombstoneSource(c.createTombstoneSource()), + shard.WithContainerInfoProvider(c.createContainerInfoProvider(ctx)), + )) } err = c.cfgObject.cfgLocalStorage.localStorage.Reload(ctx, rcfg) @@ -1414,6 +1419,20 @@ func (c *cfg) createTombstoneSource() *tombstone.ExpirationChecker { return tombstoneSource } +func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoProvider { + return container.NewInfoProvider(func() (container.Source, error) { + // threadsafe: called on init or on sighup when morph initialized + if c.cfgMorph.client == nil { + initMorphComponents(ctx, c) + } + cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, containerClient.TryNotary()) + if err != nil { + return nil, err + } + return containerClient.AsContainerSource(cc), nil + }) +} + func (c *cfg) shutdown() { old := c.swapHealthStatus(control.HealthStatus_SHUTTING_DOWN) if old == control.HealthStatus_SHUTTING_DOWN { diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 7aef6873ec..1ae4f0d3f7 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -249,6 +249,7 @@ const ( ShardMetabaseFailureSwitchingMode = "metabase failure, switching mode" ShardCantMoveShardToReadonlySwitchMode = "can't move shard to readonly, switch mode" ShardCouldNotUnmarshalObject = "could not unmarshal object" + ShardSkipObjectFromResyncContainerDeleted = "object skipped from metabase resync: container deleted" ShardCouldNotCloseShardComponent = "could not close shard component" ShardCantOpenMetabaseMoveToADegradedMode = "can't open metabase, move to a degraded mode" ShardCantInitializeMetabaseMoveToADegradedreadonlyMode = "can't initialize metabase, move to a degraded-read-only mode" diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index de881654a3..4f9f256086 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "slices" "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -275,6 +276,21 @@ func (s *Shard) refillObject(ctx context.Context, data []byte, addr oid.Address, return nil } + hasIndexedAttribute := slices.IndexFunc(obj.Attributes(), func(attr objectSDK.Attribute) bool { return meta.IsAtrributeIndexed(attr.Key()) }) > 0 + + var isIndexedContainer bool + if hasIndexedAttribute { + info, err := s.containerInfo.Info(addr.Container()) + if err != nil { + return err + } + if info.Removed { + s.log.Debug(logs.ShardSkipObjectFromResyncContainerDeleted, zap.Stringer("address", addr)) + return nil + } + isIndexedContainer = info.Indexed + } + var err error switch obj.Type() { case objectSDK.TypeTombstone: @@ -290,6 +306,7 @@ func (s *Shard) refillObject(ctx context.Context, data []byte, addr oid.Address, var mPrm meta.PutPrm mPrm.SetObject(obj) mPrm.SetStorageID(descriptor) + mPrm.SetIndexAttributes(hasIndexedAttribute && isIndexedContainer) _, err = s.metaBase.Put(ctx, mPrm) if err != nil && !client.IsErrObjectAlreadyRemoved(err) && !errors.Is(err, meta.ErrObjectIsExpired) { diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index d7e7237339..413bfd2f71 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -7,6 +7,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" @@ -95,6 +96,8 @@ type cfg struct { metricsWriter MetricsWriter reportErrorFunc func(selfID string, message string, err error) + + containerInfo container.InfoProvider } func defaultCfg() *cfg { @@ -358,6 +361,13 @@ func WithZeroCountCallback(cb EmptyContainersCallback) Option { } } +// WithContainerInfoProvider returns option to set container info provider. +func WithContainerInfoProvider(containerInfo container.InfoProvider) Option { + return func(c *cfg) { + c.containerInfo = containerInfo + } +} + func (s *Shard) fillInfo() { s.cfg.info.MetaBaseInfo = s.metaBase.DumpInfo() s.cfg.info.BlobStorInfo = s.blobStor.DumpInfo() From 8093e145b316762977aff5b2c8babda64ae7283b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 3 Oct 2024 11:06:31 +0300 Subject: [PATCH 0892/1413] [#1412] adm: Resolve container type by metabase upgrade Signed-off-by: Dmitrii Stepanov --- .../internal/modules/metabase/upgrade.go | 83 +++++++++++++---- pkg/local_object_storage/metabase/upgrade.go | 93 +++++++++++++++++-- .../metabase/upgrade_test.go | 21 +++-- pkg/local_object_storage/metabase/util.go | 15 +++ 4 files changed, 179 insertions(+), 33 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go index 96cb62f106..00b30c9b2a 100644 --- a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go +++ b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go @@ -1,6 +1,7 @@ package metabase import ( + "context" "errors" "fmt" "sync" @@ -10,19 +11,24 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" engineconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine" shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard" + morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" + nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + morphcontainer "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "github.com/spf13/cobra" "golang.org/x/sync/errgroup" ) const ( - pathFlag = "path" noCompactFlag = "no-compact" ) -var errNoPathsFound = errors.New("no metabase paths found") - -var path string +var ( + errNoPathsFound = errors.New("no metabase paths found") + errNoMorphEndpointsFound = errors.New("no morph endpoints found") +) var UpgradeCmd = &cobra.Command{ Use: "upgrade", @@ -39,17 +45,10 @@ func upgrade(cmd *cobra.Command, _ []string) error { if err != nil { return err } - noCompact, _ := cmd.Flags().GetBool(noCompactFlag) - var paths []string - if path != "" { - paths = append(paths, path) - } appCfg := config.New(configFile, configDir, config.EnvPrefix) - if err := engineconfig.IterateShards(appCfg, false, func(sc *shardconfig.Config) error { - paths = append(paths, sc.Metabase().Path()) - return nil - }); err != nil { - return fmt.Errorf("failed to get metabase paths: %w", err) + paths, err := getMetabasePaths(appCfg) + if err != nil { + return err } if len(paths) == 0 { return errNoPathsFound @@ -58,6 +57,16 @@ func upgrade(cmd *cobra.Command, _ []string) error { for i, path := range paths { cmd.Println(i+1, ":", path) } + mc, err := createMorphClient(cmd.Context(), appCfg) + if err != nil { + return err + } + defer mc.Close() + civ, err := createContainerInfoProvider(mc) + if err != nil { + return err + } + noCompact, _ := cmd.Flags().GetBool(noCompactFlag) result := make(map[string]bool) var resultGuard sync.Mutex eg, ctx := errgroup.WithContext(cmd.Context()) @@ -65,7 +74,7 @@ func upgrade(cmd *cobra.Command, _ []string) error { eg.Go(func() error { var success bool cmd.Println("upgrading metabase", path, "...") - if err := meta.Upgrade(ctx, path, !noCompact, func(a ...any) { + if err := meta.Upgrade(ctx, path, !noCompact, civ, func(a ...any) { cmd.Println(append([]any{time.Now().Format(time.RFC3339), ":", path, ":"}, a...)...) }); err != nil { cmd.Println("error: failed to upgrade metabase", path, ":", err) @@ -92,8 +101,50 @@ func upgrade(cmd *cobra.Command, _ []string) error { return nil } +func getMetabasePaths(appCfg *config.Config) ([]string, error) { + var paths []string + if err := engineconfig.IterateShards(appCfg, false, func(sc *shardconfig.Config) error { + paths = append(paths, sc.Metabase().Path()) + return nil + }); err != nil { + return nil, fmt.Errorf("get metabase paths: %w", err) + } + return paths, nil +} + +func createMorphClient(ctx context.Context, appCfg *config.Config) (*client.Client, error) { + addresses := morphconfig.RPCEndpoint(appCfg) + if len(addresses) == 0 { + return nil, errNoMorphEndpointsFound + } + key := nodeconfig.Key(appCfg) + cli, err := client.New(ctx, + key, + client.WithDialTimeout(morphconfig.DialTimeout(appCfg)), + client.WithEndpoints(addresses...), + client.WithSwitchInterval(morphconfig.SwitchInterval(appCfg)), + ) + if err != nil { + return nil, fmt.Errorf("create morph client:%w", err) + } + return cli, nil +} + +func createContainerInfoProvider(cli *client.Client) (container.InfoProvider, error) { + sh, err := cli.NNSContractAddress(client.NNSContainerContractName) + if err != nil { + return nil, fmt.Errorf("resolve container contract hash: %w", err) + } + cc, err := morphcontainer.NewFromMorph(cli, sh, 0, morphcontainer.TryNotary()) + if err != nil { + return nil, fmt.Errorf("create morph container client: %w", err) + } + return container.NewInfoProvider(func() (container.Source, error) { + return morphcontainer.AsContainerSource(cc), nil + }), nil +} + func initUpgradeCommand() { flags := UpgradeCmd.Flags() - flags.StringVar(&path, pathFlag, "", "Path to metabase file") flags.Bool(noCompactFlag, false, "Do not compact upgraded metabase file") } diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index b5de430dcd..f2a0107a19 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/binary" + "encoding/hex" "errors" "fmt" "os" @@ -12,6 +13,7 @@ import ( "time" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" @@ -25,15 +27,15 @@ const ( upgradeTimeout = 1 * time.Second ) -var updates = map[uint64]func(ctx context.Context, db *bbolt.DB, log func(a ...any)) error{ +var updates = map[uint64]func(ctx context.Context, db *bbolt.DB, cs container.InfoProvider, log func(a ...any)) error{ 2: upgradeFromV2ToV3, - 3: func(_ context.Context, _ *bbolt.DB, log func(a ...any)) error { + 3: func(_ context.Context, _ *bbolt.DB, _ container.InfoProvider, log func(a ...any)) error { log("metabase already upgraded") return nil }, } -func Upgrade(ctx context.Context, path string, compact bool, log func(a ...any)) error { +func Upgrade(ctx context.Context, path string, compact bool, cs container.InfoProvider, log func(a ...any)) error { if _, err := os.Stat(path); err != nil { return fmt.Errorf("check metabase existence: %w", err) } @@ -61,7 +63,7 @@ func Upgrade(ctx context.Context, path string, compact bool, log func(a ...any)) }); err != nil { return fmt.Errorf("set upgrade key %w", err) } - if err := updater(ctx, db, log); err != nil { + if err := updater(ctx, db, cs, log); err != nil { return fmt.Errorf("update metabase schema: %w", err) } if err := db.Update(func(tx *bbolt.Tx) error { @@ -113,11 +115,11 @@ func compactDB(db *bbolt.DB) error { return nil } -func upgradeFromV2ToV3(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { +func upgradeFromV2ToV3(ctx context.Context, db *bbolt.DB, cs container.InfoProvider, log func(a ...any)) error { if err := createExpirationEpochBuckets(ctx, db, log); err != nil { return err } - if err := dropUserAttributes(ctx, db, log); err != nil { + if err := dropUserAttributes(ctx, db, cs, log); err != nil { return err } if err := dropOwnerIDIndex(ctx, db, log); err != nil { @@ -323,10 +325,81 @@ func iterateExpirationAttributeKeyBucket(ctx context.Context, b *bbolt.Bucket, i return nil } -func dropUserAttributes(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { - return dropBucketsByPrefix(ctx, db, []byte{userAttributePrefix}, func(a ...any) { - log(append([]any{"user attributes:"}, a...)...) - }) +func dropUserAttributes(ctx context.Context, db *bbolt.DB, cs container.InfoProvider, log func(a ...any)) error { + log("deleting user attribute buckets...") + const batch = 1000 + prefix := []byte{userAttributePrefix} + last := prefix + var count uint64 + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + var keys [][]byte + if err := db.View(func(tx *bbolt.Tx) error { + c := tx.Cursor() + for k, _ := c.Seek(last); k != nil && bytes.HasPrefix(k, prefix) && len(keys) < batch; k, _ = c.Next() { + if bytes.Equal(last, k) { + continue + } + keys = append(keys, bytes.Clone(k)) + } + return nil + }); err != nil { + log("deleting user attribute buckets completed with an error:", err) + return err + } + if len(keys) == 0 { + log("deleting user attribute buckets completed successfully, deleted", count, "buckets") + return nil + } + last = keys[len(keys)-1] + keysToDrop, err := selectUserAttributeKeysToDrop(keys, cs) + if err != nil { + return err + } + if err := db.Update(func(tx *bbolt.Tx) error { + for _, k := range keysToDrop { + if err := tx.DeleteBucket(k); err != nil { + return err + } + } + return nil + }); err != nil { + log("deleting buckets completed with an error:", err) + return err + } + count += uint64(len(keysToDrop)) + log("deleted", count, "buckets") + } +} + +func selectUserAttributeKeysToDrop(keys [][]byte, cs container.InfoProvider) ([][]byte, error) { + var keysToDrop [][]byte + for _, key := range keys { + attr, ok := attributeFromAttributeBucket(key) + if !ok { + return nil, fmt.Errorf("failed to parse attribute key from user attribute bucket key %s", hex.EncodeToString(key)) + } + if !IsAtrributeIndexed(attr) { + keysToDrop = append(keysToDrop, key) + continue + } + contID, ok := cidFromAttributeBucket(key) + if !ok { + return nil, fmt.Errorf("failed to parse container ID from user attribute bucket key %s", hex.EncodeToString(key)) + } + info, err := cs.Info(contID) + if err != nil { + return nil, err + } + if info.Removed || !info.Indexed { + keysToDrop = append(keysToDrop, key) + } + } + return keysToDrop, nil } func dropOwnerIDIndex(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { diff --git a/pkg/local_object_storage/metabase/upgrade_test.go b/pkg/local_object_storage/metabase/upgrade_test.go index 3797de0a45..9c525291a4 100644 --- a/pkg/local_object_storage/metabase/upgrade_test.go +++ b/pkg/local_object_storage/metabase/upgrade_test.go @@ -12,6 +12,7 @@ import ( "time" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -35,13 +36,19 @@ func TestUpgradeV2ToV3(t *testing.T) { require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.ErrorIs(t, db.Init(), ErrOutdatedVersion) require.NoError(t, db.Close()) - require.NoError(t, Upgrade(context.Background(), path, true, t.Log)) + require.NoError(t, Upgrade(context.Background(), path, true, &testContainerInfoProvider{}, t.Log)) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.Init()) require.NoError(t, db.Close()) fmt.Println() } +type testContainerInfoProvider struct{} + +func (p *testContainerInfoProvider) Info(id cid.ID) (container.Info, error) { + return container.Info{}, nil +} + func createTempCopy(t *testing.T, path string) string { src, err := os.Open(path) require.NoError(t, err) @@ -95,7 +102,7 @@ func TestGenerateMetabaseFile(t *testing.T) { i := i eg.Go(func() error { obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) - testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(obj, objectSDK.AttributeFilePath, strconv.FormatInt(int64(i%maxFilename), 10)) testutil.AddAttribute(obj, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10)) _, err := db.Put(ctx, PutPrm{ obj: obj, @@ -118,8 +125,8 @@ func TestGenerateMetabaseFile(t *testing.T) { child.SetParent(parent) idParent, _ := parent.ID() child.SetParentID(idParent) - testutil.AddAttribute(child, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) - testutil.AddAttribute(parent, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(child, objectSDK.AttributeFilePath, strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(parent, objectSDK.AttributeFilePath, strconv.FormatInt(int64(i%maxFilename), 10)) testutil.AddAttribute(child, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10)) testutil.AddAttribute(parent, objectV2.SysAttributeExpEpoch, strconv.FormatUint(uint64(i%minEpoch+minEpoch), 10)) _, err := db.Put(ctx, PutPrm{ @@ -138,7 +145,7 @@ func TestGenerateMetabaseFile(t *testing.T) { i := i eg.Go(func() error { obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) - testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(obj, objectSDK.AttributeFilePath, strconv.FormatInt(int64(i%maxFilename), 10)) _, err := db.Put(ctx, PutPrm{ obj: obj, id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), @@ -160,7 +167,7 @@ func TestGenerateMetabaseFile(t *testing.T) { i := i eg.Go(func() error { obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) - testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(obj, objectSDK.AttributeFilePath, strconv.FormatInt(int64(i%maxFilename), 10)) _, err := db.Put(ctx, PutPrm{ obj: obj, id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), @@ -190,7 +197,7 @@ func TestGenerateMetabaseFile(t *testing.T) { i := i eg.Go(func() error { obj := testutil.GenerateObjectWithCID(containers[i%len(containers)]) - testutil.AddAttribute(obj, "FileName", strconv.FormatInt(int64(i%maxFilename), 10)) + testutil.AddAttribute(obj, objectSDK.AttributeFilePath, strconv.FormatInt(int64(i%maxFilename), 10)) _, err := db.Put(ctx, PutPrm{ obj: obj, id: []byte(strconv.FormatInt(int64(i%maxStorageID), 10) + "/" + strconv.FormatInt(int64(i%maxStorageID), 10)), diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index 4679de332e..0a2f91a476 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -176,6 +176,21 @@ func attributeBucketName(cnr cid.ID, attributeKey string, key []byte) []byte { return append(key[:bucketKeySize], attributeKey...) } +func cidFromAttributeBucket(bucketName []byte) (cid.ID, bool) { + if len(bucketName) < bucketKeySize || bucketName[0] != userAttributePrefix { + return cid.ID{}, false + } + var result cid.ID + return result, result.Decode(bucketName[1:bucketKeySize]) == nil +} + +func attributeFromAttributeBucket(bucketName []byte) (string, bool) { + if len(bucketName) < bucketKeySize || bucketName[0] != userAttributePrefix { + return "", false + } + return string(bucketName[bucketKeySize:]), true +} + // rootBucketName returns _root. func rootBucketName(cnr cid.ID, key []byte) []byte { return bucketName(cnr, rootPrefix, key) From 87f4b934d1cca9a671dc93fcc4cdb5861be35915 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 3 Oct 2024 17:57:21 +0300 Subject: [PATCH 0893/1413] [#1412] metabase: Run bucket drop steps on upgrade concurrently Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/upgrade.go | 22 ++++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index f2a0107a19..a997b90a00 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -119,13 +119,17 @@ func upgradeFromV2ToV3(ctx context.Context, db *bbolt.DB, cs container.InfoProvi if err := createExpirationEpochBuckets(ctx, db, log); err != nil { return err } - if err := dropUserAttributes(ctx, db, cs, log); err != nil { - return err - } - if err := dropOwnerIDIndex(ctx, db, log); err != nil { - return err - } - if err := dropPayloadChecksumIndex(ctx, db, log); err != nil { + eg, ctx := errgroup.WithContext(ctx) + eg.Go(func() error { + return dropUserAttributes(ctx, db, cs, log) + }) + eg.Go(func() error { + return dropOwnerIDIndex(ctx, db, log) + }) + eg.Go(func() error { + return dropPayloadChecksumIndex(ctx, db, log) + }) + if err := eg.Wait(); err != nil { return err } return db.Update(func(tx *bbolt.Tx) error { @@ -360,7 +364,7 @@ func dropUserAttributes(ctx context.Context, db *bbolt.DB, cs container.InfoProv if err != nil { return err } - if err := db.Update(func(tx *bbolt.Tx) error { + if err := db.Batch(func(tx *bbolt.Tx) error { for _, k := range keysToDrop { if err := tx.DeleteBucket(k); err != nil { return err @@ -439,7 +443,7 @@ func dropBucketsByPrefix(ctx context.Context, db *bbolt.DB, prefix []byte, log f log("deleting buckets completed successfully, deleted", count, "buckets") return nil } - if err := db.Update(func(tx *bbolt.Tx) error { + if err := db.Batch(func(tx *bbolt.Tx) error { for _, k := range keys { if err := tx.DeleteBucket(k); err != nil { return err From fe9f664b577f1b51797e375ef736977ed61d9757 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 4 Oct 2024 10:49:39 +0300 Subject: [PATCH 0894/1413] [#1412] metabase: Drop empty user attribute buckets on upgrade Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/upgrade.go | 166 +++++++++++++++++-- 1 file changed, 154 insertions(+), 12 deletions(-) diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index a997b90a00..1f2c7956bf 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -360,26 +360,40 @@ func dropUserAttributes(ctx context.Context, db *bbolt.DB, cs container.InfoProv return nil } last = keys[len(keys)-1] - keysToDrop, err := selectUserAttributeKeysToDrop(keys, cs) + cnt, err := dropNonIndexedUserAttributeBuckets(db, cs, keys) if err != nil { + log("deleting user attribute buckets completed with an error:", err) return err } - if err := db.Batch(func(tx *bbolt.Tx) error { - for _, k := range keysToDrop { - if err := tx.DeleteBucket(k); err != nil { - return err - } - } - return nil - }); err != nil { - log("deleting buckets completed with an error:", err) + count += cnt + cnt, err = dropEmptyUserAttributeBuckets(ctx, db, keys) + if err != nil { + log("deleting user attribute buckets completed with an error:", err) return err } - count += uint64(len(keysToDrop)) - log("deleted", count, "buckets") + count += cnt + log("deleted", count, "user attribute buckets") } } +func dropNonIndexedUserAttributeBuckets(db *bbolt.DB, cs container.InfoProvider, keys [][]byte) (uint64, error) { + keysToDrop, err := selectUserAttributeKeysToDrop(keys, cs) + if err != nil { + return 0, fmt.Errorf("select non indexed user attributes: %w", err) + } + if err := db.Batch(func(tx *bbolt.Tx) error { + for _, k := range keysToDrop { + if err := tx.DeleteBucket(k); err != nil { + return err + } + } + return nil + }); err != nil { + return 0, fmt.Errorf("drop non indexed user attributes: %w", err) + } + return uint64(len(keysToDrop)), nil +} + func selectUserAttributeKeysToDrop(keys [][]byte, cs container.InfoProvider) ([][]byte, error) { var keysToDrop [][]byte for _, key := range keys { @@ -406,6 +420,134 @@ func selectUserAttributeKeysToDrop(keys [][]byte, cs container.InfoProvider) ([] return keysToDrop, nil } +func dropEmptyUserAttributeBuckets(ctx context.Context, db *bbolt.DB, keys [][]byte) (uint64, error) { + var dropBuckets [][]byte + for _, key := range keys { + select { + case <-ctx.Done(): + return 0, ctx.Err() + default: + } + + if err := dropEmptyNestedBuckets(ctx, db, key); err != nil { + return 0, err + } + + empty, exists, err := bucketIsEmpty(db, key) + if err != nil { + return 0, err + } + if empty && exists { + dropBuckets = append(dropBuckets, key) + } + } + if len(dropBuckets) == 0 { + return 0, nil + } + if err := db.Batch(func(tx *bbolt.Tx) error { + for _, key := range dropBuckets { + if err := tx.DeleteBucket(key); err != nil { + return err + } + } + return nil + }); err != nil { + return 0, fmt.Errorf("drop empty user attributes buckets: %w", err) + } + return uint64(len(dropBuckets)), nil +} + +func bucketIsEmpty(db *bbolt.DB, bucketKey []byte) (bool, bool, error) { + var empty bool + var exists bool + if err := db.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(bucketKey) + if b == nil { + return nil + } + exists = true + empty = !hasAnyItem(b) + return nil + }); err != nil { + return false, false, fmt.Errorf("bucket empty check: %w", err) + } + return empty, exists, nil +} + +func dropEmptyNestedBuckets(ctx context.Context, db *bbolt.DB, rootBucketKey []byte) error { + var last []byte + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + var dropBuckets [][]byte + var err error + dropBuckets, last, err = selectEmptyNestedBuckets(ctx, db, rootBucketKey, last) + if err != nil { + return fmt.Errorf("select empty nested buckets: %w", err) + } + if len(dropBuckets) == 0 { + return nil + } + + if err := db.Batch(func(tx *bbolt.Tx) error { + rootBucket := tx.Bucket(rootBucketKey) + if rootBucket == nil { + return nil + } + for _, sb := range dropBuckets { + if err := rootBucket.DeleteBucket(sb); err != nil { + return err + } + } + return nil + }); err != nil { + return fmt.Errorf("drop empty nested buckets: %w", err) + } + } +} + +func selectEmptyNestedBuckets(ctx context.Context, db *bbolt.DB, rootBucketKey, last []byte) ([][]byte, []byte, error) { + const batchSize = 1000 + var result [][]byte + if err := db.View(func(tx *bbolt.Tx) error { + rootBucket := tx.Bucket(rootBucketKey) + if rootBucket == nil { + return nil + } + c := rootBucket.Cursor() + for k, v := c.Seek(last); k != nil && len(result) < batchSize; k, v = c.Next() { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + if bytes.Equal(last, k) { + continue + } + last = bytes.Clone(k) + if v != nil { // record + continue + } + nestedBucket := rootBucket.Bucket(k) + if nestedBucket == nil { + continue + } + if !hasAnyItem(nestedBucket) { + result = append(result, bytes.Clone(k)) + } + } + return nil + }); err != nil { + return nil, nil, err + } + return result, last, nil +} + func dropOwnerIDIndex(ctx context.Context, db *bbolt.DB, log func(a ...any)) error { return dropBucketsByPrefix(ctx, db, []byte{ownerPrefix}, func(a ...any) { log(append([]any{"owner ID index:"}, a...)...) From c065d55ca31c18fa48c8d8a173237095179be732 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 7 Oct 2024 17:19:04 +0300 Subject: [PATCH 0895/1413] [#1412] metabase: Drop logging inside transaction This could lead to hang the db. Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 6 ---- pkg/local_object_storage/metabase/select.go | 31 ++------------------- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 1ae4f0d3f7..84bd023f15 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -226,12 +226,6 @@ const ( EngineFinishedSuccessfullyShardsEvacuation = "shards evacuation finished successfully" EngineFinishedWithErrorShardsEvacuation = "shards evacuation finished with error" EngineObjectIsMovedToAnotherShard = "object is moved to another shard" - MetabaseMissingMatcher = "missing matcher" - MetabaseErrorInFKBTSelection = "error in FKBT selection" - MetabaseCantDecodeListBucketLeaf = "can't decode list bucket leaf" - MetabaseUnknownOperation = "unknown operation" - MetabaseCantIterateOverTheBucket = "can't iterate over the bucket" - MetabaseCouldNotIterateOverTheBuckets = "could not iterate over the buckets" MetabaseCreatedDirectoryForMetabase = "created directory for Metabase" MetabaseOpenedBoltDBInstanceForMetabase = "opened boltDB instance for Metabase" MetabaseCheckingMetabaseVersion = "checking metabase version" diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 88ef7d5a40..41f05b7569 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -9,7 +9,6 @@ import ( "time" v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -18,7 +17,6 @@ import ( "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" - "go.uber.org/zap" ) type ( @@ -288,8 +286,6 @@ func (db *DB) selectFromFKBT( ) { // matchFunc, ok := db.matchers[f.Operation()] if !ok { - db.log.Debug(logs.MetabaseMissingMatcher, zap.Stringer("operation", f.Operation())) - return } @@ -298,7 +294,7 @@ func (db *DB) selectFromFKBT( return } - err := matchFunc.matchBucket(fkbtRoot, f.Header(), f.Value(), func(k, _ []byte) error { + _ = matchFunc.matchBucket(fkbtRoot, f.Header(), f.Value(), func(k, _ []byte) error { fkbtLeaf := fkbtRoot.Bucket(k) if fkbtLeaf == nil { return nil @@ -310,9 +306,6 @@ func (db *DB) selectFromFKBT( return nil }) }) - if err != nil { - db.log.Debug(logs.MetabaseErrorInFKBTSelection, zap.String("error", err.Error())) - } } // selectOutsideFKBT looks into all incl buckets to find list of addresses outside to add in @@ -377,24 +370,17 @@ func (db *DB) selectFromList( case objectSDK.MatchStringEqual: lst, err = decodeList(bkt.Get(bucketKeyHelper(f.Header(), f.Value()))) if err != nil { - db.log.Debug(logs.MetabaseCantDecodeListBucketLeaf, zap.String("error", err.Error())) return } default: fMatch, ok := db.matchers[op] if !ok { - db.log.Debug(logs.MetabaseUnknownOperation, zap.Uint32("operation", uint32(op))) - return } if err = fMatch.matchBucket(bkt, f.Header(), f.Value(), func(_, val []byte) error { l, err := decodeList(val) if err != nil { - db.log.Debug(logs.MetabaseCantDecodeListBucketLeaf, - zap.String("error", err.Error()), - ) - return err } @@ -402,10 +388,6 @@ func (db *DB) selectFromList( return nil }); err != nil { - db.log.Debug(logs.MetabaseCantIterateOverTheBucket, - zap.String("error", err.Error()), - ) - return } } @@ -447,10 +429,6 @@ func (db *DB) selectObjectID( default: fMatch, ok := db.matchers[op] if !ok { - db.log.Debug(logs.MetabaseUnknownOperation, - zap.Uint32("operation", uint32(f.Operation())), - ) - return } @@ -461,18 +439,13 @@ func (db *DB) selectObjectID( return } - err := fMatch.matchBucket(bkt, f.Header(), f.Value(), func(k, _ []byte) error { + _ = fMatch.matchBucket(bkt, f.Header(), f.Value(), func(k, _ []byte) error { var id oid.ID if err := id.Decode(k); err == nil { appendOID(id) } return nil }) - if err != nil { - db.log.Debug(logs.MetabaseCouldNotIterateOverTheBuckets, - zap.String("error", err.Error()), - ) - } } } } From 936ebbb8e5c1b1967e6fd0ec5ec50bd282c1f8bc Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 8 Oct 2024 18:39:52 +0300 Subject: [PATCH 0896/1413] [#1423] metabase: Hide `BucketName` form upper levels Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/engine/evacuate.go | 12 +- pkg/local_object_storage/metabase/list.go | 104 ++++++++++-------- .../metabase/list_test.go | 57 ++++++++++ pkg/local_object_storage/shard/list.go | 32 +++--- 4 files changed, 143 insertions(+), 62 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 1baf237f91..c1b9276f35 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -435,7 +435,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context ) error { sh := shardsToEvacuate[shardID] var cntPrm shard.IterateOverContainersPrm - cntPrm.Handler = func(ctx context.Context, name []byte, cnt cid.ID) error { + cntPrm.Handler = func(ctx context.Context, objType objectSDK.Type, cnt cid.ID) error { select { case <-ctx.Done(): return context.Cause(ctx) @@ -455,8 +455,11 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context skip = e.isNotRepOne(c) } if skip { - countPrm := shard.CountAliveObjectsInBucketPrm{BucketName: name} - count, err := sh.CountAliveObjectsInBucket(ctx, countPrm) + countPrm := shard.CountAliveObjectsInContainerPrm{ + ObjectType: objType, + ContainerID: cnt, + } + count, err := sh.CountAliveObjectsInContainer(ctx, countPrm) if err != nil { return err } @@ -464,7 +467,8 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context return nil } var objPrm shard.IterateOverObjectsInContainerPrm - objPrm.BucketName = name + objPrm.ObjectType = objType + objPrm.ContainerID = cnt objPrm.Handler = func(ctx context.Context, objInfo *object.Info) error { select { case <-ctx.Done(): diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 74a5298098..b007ef0dad 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -65,21 +65,25 @@ func (l ListRes) Cursor() *Cursor { // IterateOverContainersPrm contains parameters for IterateOverContainers operation. type IterateOverContainersPrm struct { // Handler function executed upon containers in db. - Handler func(context.Context, []byte, cid.ID) error + Handler func(context.Context, objectSDK.Type, cid.ID) error } // IterateOverObjectsInContainerPrm contains parameters for IterateOverObjectsInContainer operation. type IterateOverObjectsInContainerPrm struct { - // BucketName container's bucket name. - BucketName []byte + // ObjectType type of objects to iterate over. + ObjectType objectSDK.Type + // ContainerID container for objects to iterate over. + ContainerID cid.ID // Handler function executed upon objects in db. Handler func(context.Context, *objectcore.Info) error } -// CountAliveObjectsInBucketPrm contains parameters for IterateOverObjectsInContainer operation. -type CountAliveObjectsInBucketPrm struct { - // BucketName container's bucket name. - BucketName []byte +// CountAliveObjectsInContainerPrm contains parameters for IterateOverObjectsInContainer operation. +type CountAliveObjectsInContainerPrm struct { + // ObjectType type of objects to iterate over. + ObjectType objectSDK.Type + // ContainerID container for objects to iterate over. + ContainerID cid.ID } // ListWithCursor lists physical objects available in metabase starting from @@ -319,12 +323,20 @@ func (db *DB) iterateOverContainers(ctx context.Context, tx *bbolt.Tx, prm Itera if cidRaw == nil { continue } - - bktName := make([]byte, len(name)) - copy(bktName, name) var cnt cid.ID copy(cnt[:], containerID[:]) - err := prm.Handler(ctx, bktName, cnt) + var objType objectSDK.Type + switch prefix[0] { + case primaryPrefix: + objType = objectSDK.TypeRegular + case lockersPrefix: + objType = objectSDK.TypeLock + case tombstonePrefix: + objType = objectSDK.TypeTombstone + default: + continue + } + err := prm.Handler(ctx, objType, cnt) if err != nil { return err } @@ -356,22 +368,29 @@ func (db *DB) IterateOverObjectsInContainer(ctx context.Context, prm IterateOver return ErrDegradedMode } - var containerID cid.ID - cidRaw, prefix := parseContainerIDWithPrefix(&containerID, prm.BucketName) - if cidRaw == nil { - return nil - } err := db.boltDB.View(func(tx *bbolt.Tx) error { - return db.iterateOverObjectsInContainer(ctx, tx, cidRaw, prefix, containerID, prm) + return db.iterateOverObjectsInContainer(ctx, tx, prm) }) success = err == nil return metaerr.Wrap(err) } -func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, cidRaw []byte, prefix byte, - containerID cid.ID, prm IterateOverObjectsInContainerPrm, -) error { - bkt := tx.Bucket(prm.BucketName) +func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, prm IterateOverObjectsInContainerPrm) error { + var prefix byte + switch prm.ObjectType { + case objectSDK.TypeRegular: + prefix = primaryPrefix + case objectSDK.TypeLock: + prefix = lockersPrefix + case objectSDK.TypeTombstone: + prefix = tombstonePrefix + default: + return nil + } + bucketName := []byte{prefix} + bucketName = append(bucketName, prm.ContainerID[:]...) + + bkt := tx.Bucket(bucketName) if bkt == nil { return nil } @@ -380,32 +399,19 @@ func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, c c := bkt.Cursor() k, v := c.First() - var objType objectSDK.Type - - switch prefix { - case primaryPrefix: - objType = objectSDK.TypeRegular - case lockersPrefix: - objType = objectSDK.TypeLock - case tombstonePrefix: - objType = objectSDK.TypeTombstone - default: - return nil - } - for ; k != nil; k, v = c.Next() { var obj oid.ID if err := obj.Decode(k); err != nil { break } - if inGraveyardWithKey(append(cidRaw, k...), graveyardBkt, garbageBkt) > 0 { + if inGraveyardWithKey(append(prm.ContainerID[:], k...), graveyardBkt, garbageBkt) > 0 { continue } var isLinkingObj bool var ecInfo *objectcore.ECInfo - if objType == objectSDK.TypeRegular { + if prm.ObjectType == objectSDK.TypeRegular { var o objectSDK.Object if err := o.Unmarshal(v); err != nil { return err @@ -422,9 +428,9 @@ func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, c } var a oid.Address - a.SetContainer(containerID) + a.SetContainer(prm.ContainerID) a.SetObject(obj) - objInfo := objectcore.Info{Address: a, Type: objType, IsLinkingObject: isLinkingObj, ECInfo: ecInfo} + objInfo := objectcore.Info{Address: a, Type: prm.ObjectType, IsLinkingObject: isLinkingObj, ECInfo: ecInfo} err := prm.Handler(ctx, &objInfo) if err != nil { return err @@ -433,8 +439,8 @@ func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, c return nil } -// CountAliveObjectsInBucket count objects in bucket which aren't in graveyard or garbage. -func (db *DB) CountAliveObjectsInBucket(ctx context.Context, prm CountAliveObjectsInBucketPrm) (uint64, error) { +// CountAliveObjectsInContainer count objects in bucket which aren't in graveyard or garbage. +func (db *DB) CountAliveObjectsInContainer(ctx context.Context, prm CountAliveObjectsInContainerPrm) (uint64, error) { var ( startedAt = time.Now() success = false @@ -452,14 +458,22 @@ func (db *DB) CountAliveObjectsInBucket(ctx context.Context, prm CountAliveObjec return 0, ErrDegradedMode } - if len(prm.BucketName) != bucketKeySize { + var prefix byte + switch prm.ObjectType { + case objectSDK.TypeRegular: + prefix = primaryPrefix + case objectSDK.TypeLock: + prefix = lockersPrefix + case objectSDK.TypeTombstone: + prefix = tombstonePrefix + default: return 0, nil } - - cidRaw := prm.BucketName[1:bucketKeySize] + bucketName := []byte{prefix} + bucketName = append(bucketName, prm.ContainerID[:]...) var count uint64 err := db.boltDB.View(func(tx *bbolt.Tx) error { - bkt := tx.Bucket(prm.BucketName) + bkt := tx.Bucket(bucketName) if bkt == nil { return nil } @@ -468,7 +482,7 @@ func (db *DB) CountAliveObjectsInBucket(ctx context.Context, prm CountAliveObjec c := bkt.Cursor() k, _ := c.First() for ; k != nil; k, _ = c.Next() { - if inGraveyardWithKey(append(cidRaw, k...), graveyardBkt, garbageBkt) > 0 { + if inGraveyardWithKey(append(prm.ContainerID[:], k...), graveyardBkt, garbageBkt) > 0 { continue } count++ diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index bc1726bd6b..203802ec0b 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -219,3 +220,59 @@ func metaListWithCursor(db *meta.DB, count uint32, cursor *meta.Cursor) ([]objec r, err := db.ListWithCursor(context.Background(), listPrm) return r.AddressList(), r.Cursor(), err } + +func TestIterateOver(t *testing.T) { + t.Parallel() + + db := newDB(t) + defer func() { require.NoError(t, db.Close()) }() + + const total uint64 = 5 + for _, typ := range []objectSDK.Type{objectSDK.TypeRegular, objectSDK.TypeTombstone, objectSDK.TypeLock} { + var expected []*objectSDK.Object + // fill metabase with objects + cid := cidtest.ID() + for range total { + obj := testutil.GenerateObjectWithCID(cid) + obj.SetType(typ) + err := metaPut(db, obj, nil) + require.NoError(t, err) + expected = append(expected, obj) + } + + var metaIter meta.IterateOverObjectsInContainerPrm + var count uint64 + metaIter.Handler = func(context.Context, *object.Info) error { + count++ + return nil + } + metaIter.ContainerID = cid + metaIter.ObjectType = typ + err := db.IterateOverObjectsInContainer(context.Background(), metaIter) + require.NoError(t, err) + require.Equal(t, total, count) + + var metaCount meta.CountAliveObjectsInContainerPrm + metaCount.ContainerID = cid + metaCount.ObjectType = typ + res, err := db.CountAliveObjectsInContainer(context.Background(), metaCount) + require.NoError(t, err) + require.Equal(t, res, total) + + err = metaDelete(db, object.AddressOf(expected[0]), object.AddressOf(expected[1])) + require.NoError(t, err) + + res, err = db.CountAliveObjectsInContainer(context.Background(), metaCount) + require.NoError(t, err) + require.Equal(t, uint64(3), res) + } + var count int + var metaPrm meta.IterateOverContainersPrm + metaPrm.Handler = func(context.Context, objectSDK.Type, cidSDK.ID) error { + count++ + return nil + } + err := db.IterateOverContainers(context.Background(), metaPrm) + require.NoError(t, err) + require.Equal(t, 3, count) +} diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index f5d633b775..8d09974b8e 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -37,21 +37,25 @@ func (r ListContainersRes) Containers() []cid.ID { // IterateOverContainersPrm contains parameters for IterateOverContainers operation. type IterateOverContainersPrm struct { // Handler function executed upon containers in db. - Handler func(context.Context, []byte, cid.ID) error + Handler func(context.Context, objectSDK.Type, cid.ID) error } // IterateOverObjectsInContainerPrm contains parameters for IterateOverObjectsInContainer operation. type IterateOverObjectsInContainerPrm struct { - // BucketName container's bucket name. - BucketName []byte + // ObjectType type of objects to iterate over. + ObjectType objectSDK.Type + // ContainerID container for objects to iterate over. + ContainerID cid.ID // Handler function executed upon objects in db. Handler func(context.Context, *objectcore.Info) error } -// CountAliveObjectsInBucketPrm contains parameters for CountAliveObjectsInBucket operation. -type CountAliveObjectsInBucketPrm struct { - // BucketName container's bucket name. - BucketName []byte +// CountAliveObjectsInContainerPrm contains parameters for CountAliveObjectsInContainer operation. +type CountAliveObjectsInContainerPrm struct { + // ObjectType type of objects to iterate over. + ObjectType objectSDK.Type + // ContainerID container for objects to iterate over. + ContainerID cid.ID } // ListWithCursorPrm contains parameters for ListWithCursor operation. @@ -226,7 +230,8 @@ func (s *Shard) IterateOverObjectsInContainer(ctx context.Context, prm IterateOv } var metaPrm meta.IterateOverObjectsInContainerPrm - metaPrm.BucketName = prm.BucketName + metaPrm.ContainerID = prm.ContainerID + metaPrm.ObjectType = prm.ObjectType metaPrm.Handler = prm.Handler err := s.metaBase.IterateOverObjectsInContainer(ctx, metaPrm) if err != nil { @@ -236,8 +241,8 @@ func (s *Shard) IterateOverObjectsInContainer(ctx context.Context, prm IterateOv return nil } -// CountAliveObjectsInBucket count objects in bucket which aren't in graveyard or garbage. -func (s *Shard) CountAliveObjectsInBucket(ctx context.Context, prm CountAliveObjectsInBucketPrm) (uint64, error) { +// CountAliveObjectsInContainer count objects in bucket which aren't in graveyard or garbage. +func (s *Shard) CountAliveObjectsInContainer(ctx context.Context, prm CountAliveObjectsInContainerPrm) (uint64, error) { _, span := tracing.StartSpanFromContext(ctx, "shard.CountAliveObjectsInBucket") defer span.End() @@ -248,9 +253,10 @@ func (s *Shard) CountAliveObjectsInBucket(ctx context.Context, prm CountAliveObj return 0, ErrDegradedMode } - var metaPrm meta.CountAliveObjectsInBucketPrm - metaPrm.BucketName = prm.BucketName - count, err := s.metaBase.CountAliveObjectsInBucket(ctx, metaPrm) + var metaPrm meta.CountAliveObjectsInContainerPrm + metaPrm.ObjectType = prm.ObjectType + metaPrm.ContainerID = prm.ContainerID + count, err := s.metaBase.CountAliveObjectsInContainer(ctx, metaPrm) if err != nil { return 0, fmt.Errorf("could not count alive objects in bucket: %w", err) } From 4190fba86d575ba6c05aeb919ae5bc30572ecbd2 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 8 Oct 2024 16:44:34 +0300 Subject: [PATCH 0897/1413] [#1425] Remove SetEACL-related code Signed-off-by: Evgenii Stratonikov --- .../modules/morph/container/container.go | 8 -- internal/logs/logs.go | 3 - .../processors/container/handlers.go | 4 - .../processors/container/processor.go | 10 --- pkg/morph/client/container/client.go | 1 - pkg/morph/event/container/eacl.go | 51 ------------- pkg/morph/event/container/eacl_notary.go | 75 ------------------- pkg/services/container/morph/executor_test.go | 4 - 8 files changed, 156 deletions(-) delete mode 100644 pkg/morph/event/container/eacl.go delete mode 100644 pkg/morph/event/container/eacl_notary.go diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index a664389753..e280bc6346 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -159,9 +159,6 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo if err != nil { return nil, fmt.Errorf("%w: %v", errInvalidContainerResponse, err) } - if len(ea.Value) != 0 { - cnt.EACL = ea - } return cnt, nil } @@ -258,10 +255,6 @@ func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd func putContainer(bw *io.BufBinWriter, ch util.Uint160, cnt Container) { emit.AppCall(bw.BinWriter, ch, "put", callflag.All, cnt.Value, cnt.Signature, cnt.PublicKey, cnt.Token) - if ea := cnt.EACL; ea != nil { - emit.AppCall(bw.BinWriter, ch, "setEACL", callflag.All, - ea.Value, ea.Signature, ea.PublicKey, ea.Token) - } } func isContainerRestored(cmd *cobra.Command, wCtx *helper.InitializeContext, containerHash util.Uint160, bw *io.BufBinWriter, hashValue util.Uint256) (bool, error) { @@ -322,7 +315,6 @@ type Container struct { Signature []byte `json:"signature"` PublicKey []byte `json:"public_key"` Token []byte `json:"token"` - EACL *EACL `json:"eacl"` } // EACL represents extended ACL struct in contract storage. diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 84bd023f15..ca783a39d3 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -308,9 +308,6 @@ const ( ContainerNonAlphabetModeIgnoreContainerDelete = "non alphabet mode, ignore container delete" ContainerDeleteContainerCheckFailed = "delete container check failed" ContainerCouldNotApproveDeleteContainer = "could not approve delete container" - ContainerNonAlphabetModeIgnoreSetEACL = "non alphabet mode, ignore set EACL" - ContainerSetEACLCheckFailed = "set EACL check failed" - ContainerCouldNotApproveSetEACL = "could not approve set EACL" FrostFSNonAlphabetModeIgnoreConfig = "non alphabet mode, ignore config" FrostFSCantRelaySetConfigEvent = "can't relay set config event" FrostFSFrostfsWorkerPool = "frostfs worker pool" diff --git a/pkg/innerring/processors/container/handlers.go b/pkg/innerring/processors/container/handlers.go index 8bb89abe2d..a54f3c7724 100644 --- a/pkg/innerring/processors/container/handlers.go +++ b/pkg/innerring/processors/container/handlers.go @@ -48,7 +48,3 @@ func (cp *Processor) handleDelete(ev event.Event) { zap.Int("capacity", cp.pool.Cap())) } } - -func (cp *Processor) handleSetEACL(_ event.Event) { - cp.log.Warn(logs.SkipDeprecatedNotification, zap.String("type", "set EACL")) -} diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index 8fd9edfb8e..a6fbdc707d 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -157,11 +157,6 @@ func (cp *Processor) ListenerNotaryParsers() []event.NotaryParserInfo { p.SetParser(containerEvent.ParseDeleteNotary) pp = append(pp, p) - // set EACL - p.SetRequestType(containerEvent.SetEACLNotaryEvent) - p.SetParser(containerEvent.ParseSetEACLNotary) - pp = append(pp, p) - return pp } @@ -190,10 +185,5 @@ func (cp *Processor) ListenerNotaryHandlers() []event.NotaryHandlerInfo { h.SetHandler(cp.handleDelete) hh = append(hh, h) - // set eACL - h.SetRequestType(containerEvent.SetEACLNotaryEvent) - h.SetHandler(cp.handleSetEACL) - hh = append(hh, h) - return hh } diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index 9dd3a337be..fc892aafb2 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -28,7 +28,6 @@ const ( listMethod = "list" containersOfMethod = "containersOf" eaclMethod = "eACL" - setEACLMethod = "setEACL" deletionInfoMethod = "deletionInfo" startEstimationMethod = "startContainerEstimation" diff --git a/pkg/morph/event/container/eacl.go b/pkg/morph/event/container/eacl.go deleted file mode 100644 index 4168d88428..0000000000 --- a/pkg/morph/event/container/eacl.go +++ /dev/null @@ -1,51 +0,0 @@ -package container - -import ( - "github.com/nspcc-dev/neo-go/pkg/network/payload" -) - -// SetEACL represents structure of notification about -// modified eACL table coming from FrostFS Container contract. -type SetEACL struct { - TableValue []byte - SignatureValue []byte - PublicKeyValue []byte - TokenValue []byte - - // For notary notifications only. - // Contains raw transactions of notary request. - NotaryRequestValue *payload.P2PNotaryRequest -} - -// MorphEvent implements Neo:Morph Event interface. -func (SetEACL) MorphEvent() {} - -// Table returns returns eACL table in a binary FrostFS API format. -func (x SetEACL) Table() []byte { - return x.TableValue -} - -// Signature returns signature of the binary table. -func (x SetEACL) Signature() []byte { - return x.SignatureValue -} - -// PublicKey returns public keys of container -// owner in a binary format. -func (x SetEACL) PublicKey() []byte { - return x.PublicKeyValue -} - -// SessionToken returns binary token of the session -// within which the eACL was set. -func (x SetEACL) SessionToken() []byte { - return x.TokenValue -} - -// NotaryRequest returns raw notary request if notification -// was received via notary service. Otherwise, returns nil. -func (x SetEACL) NotaryRequest() *payload.P2PNotaryRequest { - return x.NotaryRequestValue -} - -const expectedItemNumEACL = 4 diff --git a/pkg/morph/event/container/eacl_notary.go b/pkg/morph/event/container/eacl_notary.go deleted file mode 100644 index a4fe7c9669..0000000000 --- a/pkg/morph/event/container/eacl_notary.go +++ /dev/null @@ -1,75 +0,0 @@ -package container - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/vm/opcode" -) - -func (x *SetEACL) setTable(v []byte) { - if v != nil { - x.TableValue = v - } -} - -func (x *SetEACL) setSignature(v []byte) { - if v != nil { - x.SignatureValue = v - } -} - -func (x *SetEACL) setPublicKey(v []byte) { - if v != nil { - x.PublicKeyValue = v - } -} - -func (x *SetEACL) setToken(v []byte) { - if v != nil { - x.TokenValue = v - } -} - -var setEACLFieldSetters = []func(*SetEACL, []byte){ - // order on stack is reversed - (*SetEACL).setToken, - (*SetEACL).setPublicKey, - (*SetEACL).setSignature, - (*SetEACL).setTable, -} - -const ( - // SetEACLNotaryEvent is method name for container EACL operations - // in `Container` contract. Is used as identificator for notary - // EACL changing requests. - SetEACLNotaryEvent = "setEACL" -) - -// ParseSetEACLNotary from NotaryEvent into container event structure. -func ParseSetEACLNotary(ne event.NotaryEvent) (event.Event, error) { - var ( - ev SetEACL - currentOp opcode.Opcode - ) - - fieldNum := 0 - - for _, op := range ne.Params() { - currentOp = op.Code() - - switch { - case opcode.PUSHDATA1 <= currentOp && currentOp <= opcode.PUSHDATA4: - if fieldNum == expectedItemNumEACL { - return nil, event.UnexpectedArgNumErr(SetEACLNotaryEvent) - } - - setEACLFieldSetters[fieldNum](&ev, op.Param()) - fieldNum++ - default: - return nil, event.UnexpectedOpcode(SetEACLNotaryEvent, op.Code()) - } - } - - ev.NotaryRequestValue = ne.Raw() - - return ev, nil -} diff --git a/pkg/services/container/morph/executor_test.go b/pkg/services/container/morph/executor_test.go index 560c69232b..c64310eb32 100644 --- a/pkg/services/container/morph/executor_test.go +++ b/pkg/services/container/morph/executor_test.go @@ -32,10 +32,6 @@ func (m mock) Delete(_ containerCore.RemovalWitness) error { return nil } -func (m mock) PutEACL(_ containerCore.EACL) error { - return nil -} - func TestInvalidToken(t *testing.T) { m := mock{} e := containerSvcMorph.NewExecutor(m, m) From cc5360a57851e27dd51d72cf0ff5fa6ac44aba2f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 8 Oct 2024 16:46:41 +0300 Subject: [PATCH 0898/1413] [#1425] morph/event: Rename eacl_test.go Signed-off-by: Evgenii Stratonikov --- pkg/morph/event/container/{eacl_test.go => util_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkg/morph/event/container/{eacl_test.go => util_test.go} (100%) diff --git a/pkg/morph/event/container/eacl_test.go b/pkg/morph/event/container/util_test.go similarity index 100% rename from pkg/morph/event/container/eacl_test.go rename to pkg/morph/event/container/util_test.go From 94302235d03ad147c9d42791de39f75aaa7fe7f9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 9 Oct 2024 10:03:58 +0300 Subject: [PATCH 0899/1413] [#1425] adm: Remove eACL fetching from dump-containers Signed-off-by: Evgenii Stratonikov --- .../modules/morph/container/container.go | 62 +------------------ 1 file changed, 2 insertions(+), 60 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index e280bc6346..6f08d1655a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -139,13 +139,12 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invoker, id []byte) (*Container, error) { bw.Reset() emit.AppCall(bw.BinWriter, ch, "get", callflag.All, id) - emit.AppCall(bw.BinWriter, ch, "eACL", callflag.All, id) res, err := inv.Run(bw.Bytes()) if err != nil { return nil, fmt.Errorf("can't get container info: %w", err) } - if len(res.Stack) != 2 { - return nil, fmt.Errorf("%w: expected 2 items on stack", errInvalidContainerResponse) + if len(res.Stack) != 1 { + return nil, fmt.Errorf("%w: expected 1 items on stack", errInvalidContainerResponse) } cnt := new(Container) @@ -154,11 +153,6 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo return nil, fmt.Errorf("%w: %v", errInvalidContainerResponse, err) } - ea := new(EACL) - err = ea.FromStackItem(res.Stack[1]) - if err != nil { - return nil, fmt.Errorf("%w: %v", errInvalidContainerResponse, err) - } return cnt, nil } @@ -317,14 +311,6 @@ type Container struct { Token []byte `json:"token"` } -// EACL represents extended ACL struct in contract storage. -type EACL struct { - Value []byte `json:"value"` - Signature []byte `json:"signature"` - PublicKey []byte `json:"public_key"` - Token []byte `json:"token"` -} - // ToStackItem implements stackitem.Convertible. func (c *Container) ToStackItem() (stackitem.Item, error) { return stackitem.NewStruct([]stackitem.Item{ @@ -369,50 +355,6 @@ func (c *Container) FromStackItem(item stackitem.Item) error { return nil } -// ToStackItem implements stackitem.Convertible. -func (c *EACL) ToStackItem() (stackitem.Item, error) { - return stackitem.NewStruct([]stackitem.Item{ - stackitem.NewByteArray(c.Value), - stackitem.NewByteArray(c.Signature), - stackitem.NewByteArray(c.PublicKey), - stackitem.NewByteArray(c.Token), - }), nil -} - -// FromStackItem implements stackitem.Convertible. -func (c *EACL) FromStackItem(item stackitem.Item) error { - arr, ok := item.Value().([]stackitem.Item) - if !ok || len(arr) != 4 { - return errors.New("invalid stack item type") - } - - value, err := arr[0].TryBytes() - if err != nil { - return errors.New("invalid eACL value") - } - - sig, err := arr[1].TryBytes() - if err != nil { - return errors.New("invalid eACL signature") - } - - pub, err := arr[2].TryBytes() - if err != nil { - return errors.New("invalid eACL public key") - } - - tok, err := arr[3].TryBytes() - if err != nil { - return errors.New("invalid eACL token") - } - - c.Value = value - c.Signature = sig - c.PublicKey = pub - c.Token = tok - return nil -} - // getCIDFilterFunc returns filtering function for container IDs. // Raw byte slices are used because it works with structures returned // from contract. From 02bb7159a54a9522ad0bc97d1a5456f5cfc425e4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 9 Oct 2024 10:50:30 +0300 Subject: [PATCH 0900/1413] [#1425] services/tree: Remove eACL processing Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/tree.go | 1 - pkg/services/tree/options.go | 9 -- pkg/services/tree/signature.go | 137 +------------------------ pkg/services/tree/signature_test.go | 151 ++++++++++++++++++---------- 4 files changed, 100 insertions(+), 198 deletions(-) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index d22e510ded..192f084713 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -54,7 +54,6 @@ func initTreeService(c *cfg) { cli: c.shared.cnrClient, }), tree.WithFrostfsidSubjectProvider(c.shared.frostfsidClient), - tree.WithEACLSource(c.cfgObject.eaclSource), tree.WithNetmapSource(c.netMapSource), tree.WithPrivateKey(&c.key.PrivateKey), tree.WithLogger(c.log), diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index 6a20fe5cc1..1db5607f66 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -33,7 +33,6 @@ type cfg struct { nmSource netmap.Source cnrSource ContainerSource frostfsidSubjectProvider frostfsidcore.SubjectProvider - eaclSource container.EACLSource forest pilorama.Forest // replication-related parameters replicatorChannelCapacity int @@ -65,14 +64,6 @@ func WithFrostfsidSubjectProvider(provider frostfsidcore.SubjectProvider) Option } } -// WithEACLSource sets a eACL table source for a tree service. -// This option is required. -func WithEACLSource(src container.EACLSource) Option { - return func(c *cfg) { - c.eaclSource = src - } -} - // WithNetmapSource sets a netmap source for a tree service. // This option is required. func WithNetmapSource(src netmap.Source) Option { diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 58cab659fc..305adf2d7f 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -9,10 +9,8 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" @@ -20,7 +18,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "go.uber.org/zap" ) type message interface { @@ -30,16 +27,11 @@ type message interface { SetSignature(*Signature) } -func basicACLErr(op acl.Op) error { - return fmt.Errorf("access to operation %s is denied by basic ACL check", op) -} - func eACLErr(op eacl.Operation, err error) error { return fmt.Errorf("access to operation %s is denied by extended ACL check: %w", op, err) } var ( - errBearerWrongOwner = errors.New("bearer token must be signed by the container owner") errBearerWrongContainer = errors.New("bearer token is created for another container") errBearerSignature = errors.New("invalid bearer token signature") ) @@ -77,56 +69,7 @@ func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, return fmt.Errorf("can't get request role: %w", err) } - basicACL := cnr.Value.BasicACL() - // Basic ACL mask can be unset, if a container operations are performed - // with strict APE checks only. - // - // FIXME(@aarifullin): tree service temporiraly performs APE checks on - // object verbs, because tree verbs have not been introduced yet. - if basicACL == 0x0 { - return s.checkAPE(ctx, bt, cnr, cid, op, role, pubKey) - } - - if !basicACL.IsOpAllowed(op, role) { - return basicACLErr(op) - } - - if !basicACL.Extendable() { - return nil - } - - var useBearer bool - if len(rawBearer) != 0 { - if !basicACL.AllowedBearerRules(op) { - s.log.Debug(logs.TreeBearerPresentedButNotAllowedByACL, - zap.String("cid", cid.EncodeToString()), - zap.Stringer("op", op), - ) - } else { - useBearer = true - } - } - - var tb eacl.Table - signer := req.GetSignature().GetKey() - if useBearer && !bt.Impersonate() { - if !bearer.ResolveIssuer(*bt).Equals(cnr.Value.Owner()) { - return eACLErr(eaclOp, errBearerWrongOwner) - } - tb = bt.EACLTable() - } else { - tbCore, err := s.eaclSource.GetEACL(cid) - if err != nil { - return handleGetEACLError(err) - } - tb = *tbCore.Value - - if useBearer && bt.Impersonate() { - signer = bt.SigningKeyBytes() - } - } - - return checkEACL(tb, signer, eACLRole(role), eaclOp) + return s.checkAPE(ctx, bt, cnr, cid, op, role, pubKey) } // Returns true iff the operation is read-only and request was signed @@ -168,14 +111,6 @@ func parseBearer(rawBearer []byte, cid cidSDK.ID, eaclOp eacl.Operation) (*beare return bt, nil } -func handleGetEACLError(err error) error { - if client.IsErrEACLNotFound(err) { - return nil - } - - return fmt.Errorf("get eACL table: %w", err) -} - func verifyMessage(m message) error { binBody, err := m.ReadSignedData(nil) if err != nil { @@ -260,73 +195,3 @@ func eACLOp(op acl.Op) eacl.Operation { panic(fmt.Sprintf("unexpected tree service ACL operation: %s", op)) } } - -func eACLRole(role acl.Role) eacl.Role { - switch role { - case acl.RoleOwner: - return eacl.RoleUser - case acl.RoleOthers: - return eacl.RoleOthers - default: - panic(fmt.Sprintf("unexpected tree service ACL role: %s", role)) - } -} - -var ( - errDENY = errors.New("DENY eACL rule") - errNoAllowRules = errors.New("not found allowing rules for the request") -) - -// checkEACL searches for the eACL rules that could be applied to the request -// (a tuple of a signer key, his FrostFS role and a request operation). -// It does not filter the request by the filters of the eACL table since tree -// requests do not contain any "object" information that could be filtered and, -// therefore, filtering leads to unexpected results. -// The code was copied with the minor updates from the SDK repo: -// https://github.com/nspcc-dev/frostfs-sdk-go/blob/43a57d42dd50dc60465bfd3482f7f12bcfcf3411/eacl/validator.go#L28. -func checkEACL(tb eacl.Table, signer []byte, role eacl.Role, op eacl.Operation) error { - for _, record := range tb.Records() { - // check type of operation - if record.Operation() != op { - continue - } - - // check target - if !targetMatches(record, role, signer) { - continue - } - - switch a := record.Action(); a { - case eacl.ActionAllow: - return nil - case eacl.ActionDeny: - return eACLErr(op, errDENY) - default: - return eACLErr(op, fmt.Errorf("unexpected action: %s", a)) - } - } - - return eACLErr(op, errNoAllowRules) -} - -func targetMatches(rec eacl.Record, role eacl.Role, signer []byte) bool { - for _, target := range rec.Targets() { - // check public key match - if pubs := target.BinaryKeys(); len(pubs) != 0 { - for _, key := range pubs { - if bytes.Equal(key, signer) { - return true - } - } - - continue - } - - // check target group match - if role == target.Role() { - return true - } - } - - return false -} diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 3c3ebfe892..939ff170d8 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -4,22 +4,30 @@ import ( "context" "crypto/ecdsa" "crypto/sha256" + "encoding/hex" "errors" "testing" aclV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/stretchr/testify/require" ) @@ -27,6 +35,34 @@ type dummyNetmapSource struct { netmap.Source } +type dummySubjectProvider struct { + subjects map[util.Uint160]client.SubjectExtended +} + +func (s dummySubjectProvider) GetSubject(addr util.Uint160) (*client.Subject, error) { + res := s.subjects[addr] + return &client.Subject{ + PrimaryKey: res.PrimaryKey, + AdditionalKeys: res.AdditionalKeys, + Namespace: res.Namespace, + Name: res.Name, + KV: res.KV, + }, nil +} + +func (s dummySubjectProvider) GetSubjectExtended(addr util.Uint160) (*client.SubjectExtended, error) { + res := s.subjects[addr] + return &res, nil +} + +type dummyEpochSource struct { + epoch uint64 +} + +func (s dummyEpochSource) CurrentEpoch() uint64 { + return s.epoch +} + type dummyContainerSource map[string]*containercore.Container func (s dummyContainerSource) List() ([]cid.ID, error) { @@ -57,16 +93,6 @@ func (s dummyContainerSource) DeletionInfo(id cid.ID) (*containercore.DelInfo, e return &containercore.DelInfo{}, nil } -type dummyEACLSource map[string]*containercore.EACL - -func (s dummyEACLSource) GetEACL(id cid.ID) (*containercore.EACL, error) { - cntEACL, ok := s[id.String()] - if !ok { - return nil, errors.New("container not found") - } - return cntEACL, nil -} - func testContainer(owner user.ID) container.Container { var r netmapSDK.ReplicaDescriptor r.SetNumberOfObjects(1) @@ -81,6 +107,8 @@ func testContainer(owner user.ID) container.Container { return cnt } +const currentEpoch = 123 + func TestMessageSign(t *testing.T) { privs := make([]*keys.PrivateKey, 4) for i := range privs { @@ -99,6 +127,15 @@ func TestMessageSign(t *testing.T) { Value: testContainer(ownerID), } + e := inmemory.NewInMemoryLocalOverrides() + e.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.Target{ + Type: engine.Container, + Name: cid1.EncodeToString(), + }, testChain(privs[0].PublicKey(), privs[1].PublicKey())) + frostfsidProvider := dummySubjectProvider{ + subjects: make(map[util.Uint160]client.SubjectExtended), + } + s := &Service{ cfg: cfg{ log: test.NewLogger(t), @@ -107,12 +144,10 @@ func TestMessageSign(t *testing.T) { cnrSource: dummyContainerSource{ cid1.String(): cnr, }, - eaclSource: dummyEACLSource{ - cid1.String(): &containercore.EACL{ - Value: testTable(cid1, privs[0].PublicKey(), privs[1].PublicKey()), - }, - }, + frostfsidSubjectProvider: frostfsidProvider, + state: dummyEpochSource{epoch: currentEpoch}, }, + apeChecker: checkercore.New(e.LocalStorage(), e.MorphRuleChainStorage(), frostfsidProvider, dummyEpochSource{}), } rawCID1 := make([]byte, sha256.Size) @@ -235,46 +270,58 @@ func TestMessageSign(t *testing.T) { func testBearerToken(cid cid.ID, forPutGet, forGet *keys.PublicKey) bearer.Token { var b bearer.Token - b.SetEACLTable(*testTable(cid, forPutGet, forGet)) + b.SetExp(currentEpoch + 1) + b.SetAPEOverride(bearer.APEOverride{ + Target: ape.ChainTarget{ + TargetType: ape.TargetTypeContainer, + Name: cid.EncodeToString(), + }, + Chains: []ape.Chain{{Raw: testChain(forPutGet, forGet).Bytes()}}, + }) return b } -func testTable(cid cid.ID, forPutGet, forGet *keys.PublicKey) *eaclSDK.Table { - tgtGet := eaclSDK.NewTarget() - tgtGet.SetRole(eaclSDK.RoleUnknown) - tgtGet.SetBinaryKeys([][]byte{forPutGet.Bytes(), forGet.Bytes()}) - - rGet := eaclSDK.NewRecord() - rGet.SetAction(eaclSDK.ActionAllow) - rGet.SetOperation(eaclSDK.OperationGet) - rGet.SetTargets(*tgtGet) - - tgtPut := eaclSDK.NewTarget() - tgtPut.SetRole(eaclSDK.RoleUnknown) - tgtPut.SetBinaryKeys([][]byte{forPutGet.Bytes()}) - - rPut := eaclSDK.NewRecord() - rPut.SetAction(eaclSDK.ActionAllow) - rPut.SetOperation(eaclSDK.OperationPut) - rPut.SetTargets(*tgtPut) - - tb := eaclSDK.NewTable() - tb.AddRecord(rGet) - tb.AddRecord(rPut) - - tgt := eaclSDK.NewTarget() - tgt.SetRole(eaclSDK.RoleOthers) - - for _, op := range []eaclSDK.Operation{eaclSDK.OperationGet, eaclSDK.OperationPut} { - r := eaclSDK.NewRecord() - r.SetAction(eaclSDK.ActionDeny) - r.SetTargets(*tgt) - r.SetOperation(op) - tb.AddRecord(r) +func testChain(forPutGet, forGet *keys.PublicKey) *chain.Chain { + ruleGet := chain.Rule{ + Status: chain.Allow, + Resources: chain.Resources{Names: []string{native.ResourceFormatAllObjects}}, + Actions: chain.Actions{Names: []string{native.MethodGetObject}}, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Kind: chain.KindRequest, + Key: native.PropertyKeyActorPublicKey, + Value: hex.EncodeToString(forPutGet.Bytes()), + }, + { + Op: chain.CondStringEquals, + Kind: chain.KindRequest, + Key: native.PropertyKeyActorPublicKey, + Value: hex.EncodeToString(forGet.Bytes()), + }, + }, + } + rulePut := chain.Rule{ + Status: chain.Allow, + Resources: chain.Resources{Names: []string{native.ResourceFormatAllObjects}}, + Actions: chain.Actions{Names: []string{native.MethodPutObject}}, + Any: true, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Kind: chain.KindRequest, + Key: native.PropertyKeyActorPublicKey, + Value: hex.EncodeToString(forPutGet.Bytes()), + }, + }, } - tb.SetCID(cid) - - return tb + return &chain.Chain{ + Rules: []chain.Rule{ + ruleGet, + rulePut, + }, + } } From 11347602719a764179a74382076de4430936d7ad Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 9 Oct 2024 10:55:48 +0300 Subject: [PATCH 0901/1413] [#1425] services/tree: Remove eACL mentions from bearer token parsing errors Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/signature.go | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 305adf2d7f..20a629fccc 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -15,7 +15,6 @@ import ( cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) @@ -27,10 +26,6 @@ type message interface { SetSignature(*Signature) } -func eACLErr(op eacl.Operation, err error) error { - return fmt.Errorf("access to operation %s is denied by extended ACL check: %w", op, err) -} - var ( errBearerWrongContainer = errors.New("bearer token is created for another container") errBearerSignature = errors.New("invalid bearer token signature") @@ -57,11 +52,9 @@ func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, return fmt.Errorf("can't get container %s: %w", cid, err) } - eaclOp := eACLOp(op) - - bt, err := parseBearer(rawBearer, cid, eaclOp) + bt, err := parseBearer(rawBearer, cid) if err != nil { - return err + return fmt.Errorf("access to operation %s is denied: %w", op, err) } role, pubKey, err := roleAndPubKeyFromReq(cnr, req, bt) @@ -93,20 +86,20 @@ func (s *Service) isAuthorized(req message, op acl.Op) (bool, error) { return false, nil } -func parseBearer(rawBearer []byte, cid cidSDK.ID, eaclOp eacl.Operation) (*bearer.Token, error) { +func parseBearer(rawBearer []byte, cid cidSDK.ID) (*bearer.Token, error) { if len(rawBearer) == 0 { return nil, nil } bt := new(bearer.Token) if err := bt.Unmarshal(rawBearer); err != nil { - return nil, eACLErr(eaclOp, fmt.Errorf("invalid bearer token: %w", err)) + return nil, fmt.Errorf("invalid bearer token: %w", err) } if !bt.AssertContainer(cid) { - return nil, eACLErr(eaclOp, errBearerWrongContainer) + return nil, errBearerWrongContainer } if !bt.VerifySignature() { - return nil, eACLErr(eaclOp, errBearerSignature) + return nil, errBearerSignature } return bt, nil } @@ -184,14 +177,3 @@ func roleAndPubKeyFromReq(cnr *core.Container, req message, bt *bearer.Token) (a return role, pub, nil } - -func eACLOp(op acl.Op) eacl.Operation { - switch op { - case acl.OpObjectGet: - return eacl.OperationGet - case acl.OpObjectPut: - return eacl.OperationPut - default: - panic(fmt.Sprintf("unexpected tree service ACL operation: %s", op)) - } -} From dfb00083d07499a0e3d89076cc3f08729c00cb71 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 10 Oct 2024 14:57:39 +0300 Subject: [PATCH 0902/1413] [#1426] go.mod: Update sdk-go Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 91cc55a364..9a64f0e81f 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241007135805-4c310ae1c7fa + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 diff --git a/go.sum b/go.sum index 728592ea5e..777d9b3ab8 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 h1:6qCcm1oqFbmf9C5AauXzrL5OPGnTbI9HoB/jAtD9274= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241007135805-4c310ae1c7fa h1:Jr8hXNNFECLhC7S45HuyQms4U/gim1xILoU3g4ZZnHg= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241007135805-4c310ae1c7fa/go.mod h1:jmb7yxzZota9jWbC10p+7YR+6wwJPBj7J/Fl5VDkXys= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509 h1:5gtEq4bjVgAbTOrbEquspyM3s+qsMtkpGC5m9FtfImk= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509/go.mod h1:jmb7yxzZota9jWbC10p+7YR+6wwJPBj7J/Fl5VDkXys= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= From 5992ee901ae574d536a82bd7f1504852e17fb086 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 11 Oct 2024 11:33:36 +0300 Subject: [PATCH 0903/1413] [#1411] go.mod: Bump frostfs-contract to v0.20.0 Signed-off-by: Alexander Chuprov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9a64f0e81f..1468c12b22 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c + git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 diff --git a/go.sum b/go.sum index 777d9b3ab8..5ce81807ad 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3 h1:6QXNnfBgYx81UZsBdpPnQY+ZMSKGFbFc29wV7DJ/UG4= git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c h1:9JmXxWcqWaOXModBwtj/WlPYOfSk2jRSDoRsDRYvgnA= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240909072709-3e221b973a3c/go.mod h1:DVb1AqP323wiEwCtlfoJJTERF4Xji2L39X6T8kv26RE= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0 h1:8Z5iPhieCrbcdhxBuY/Bajh6V5fki7Whh0b4S2zYJYU= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0/go.mod h1:Y2Xorxc8SBO4phoek7n3XxaPZz5rIrFgDsU4TOjmlGA= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= From 42bf03e5cc04f2b6d67465608b842693171344ba Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 11 Oct 2024 11:33:56 +0300 Subject: [PATCH 0904/1413] [#1411] adm/nns: Add 'delRecord' Signed-off-by: Alexander Chuprov --- .../internal/modules/morph/nns/record.go | 29 +++++++++++++++++++ .../internal/modules/morph/nns/root.go | 10 +++++++ 2 files changed, 39 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/record.go b/cmd/frostfs-adm/internal/modules/morph/nns/record.go index 0e217eb616..66bb1b94fb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/record.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/record.go @@ -47,6 +47,19 @@ func initDelRecordsCmd() { _ = cobra.MarkFlagRequired(delRecordsCmd.Flags(), nnsRecordTypeFlag) } +func initDelRecordCmd() { + Cmd.AddCommand(delRecordCmd) + delRecordCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + delRecordCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + delRecordCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + delRecordCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) + delRecordCmd.Flags().String(nnsRecordDataFlag, "", nnsRecordDataFlagDesc) + + _ = cobra.MarkFlagRequired(delRecordCmd.Flags(), nnsNameFlag) + _ = cobra.MarkFlagRequired(delRecordCmd.Flags(), nnsRecordTypeFlag) + _ = cobra.MarkFlagRequired(delRecordCmd.Flags(), nnsRecordDataFlag) +} + func addRecord(cmd *cobra.Command, _ []string) { c, actor, _ := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) @@ -115,6 +128,22 @@ func delRecords(cmd *cobra.Command, _ []string) { cmd.Println("Records removed successfully") } +func delRecord(cmd *cobra.Command, _ []string) { + c, actor, _ := getRPCClient(cmd) + name, _ := cmd.Flags().GetString(nnsNameFlag) + data, _ := cmd.Flags().GetString(nnsRecordDataFlag) + recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) + typ, err := getRecordType(recordType) + commonCmd.ExitOnErr(cmd, "unable to parse record type: %w", err) + h, vub, err := c.DeleteRecord(name, typ, data) + commonCmd.ExitOnErr(cmd, "unable to delete record: %w", err) + + cmd.Println("Waiting for transaction to persist...") + _, err = actor.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "delete records error: %w", err) + cmd.Println("Record removed successfully") +} + func getRecordType(recordType string) (*big.Int, error) { switch strings.ToUpper(recordType) { case "A": diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/root.go b/cmd/frostfs-adm/internal/modules/morph/nns/root.go index 56774c2924..9bdeaccd90 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/root.go @@ -95,6 +95,15 @@ var ( }, Run: delRecords, } + delRecordCmd = &cobra.Command{ + Use: "delete-record", + Short: "Removes domain record with the specified type and data", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + }, + Run: delRecord, + } ) func init() { @@ -106,4 +115,5 @@ func init() { initAddRecordCmd() initGetRecordsCmd() initDelRecordsCmd() + initDelRecordCmd() } From acd6eb18151d7e2fec413d97e273b13076a9b4bb Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 11 Oct 2024 15:40:01 +0300 Subject: [PATCH 0905/1413] [#1427] object: Fix `Put` for `EC` object when node unavailable There might be situation when context canceled earlier than traverser move to another part of the nodes. To avoid this, need to wait for the result from concurrent put at each traverser iteration. Signed-off-by: Anton Nikiforov --- pkg/services/object/common/writer/ec.go | 20 +- pkg/services/object/common/writer/ec_test.go | 191 +++++++++++++++++++ 2 files changed, 205 insertions(+), 6 deletions(-) create mode 100644 pkg/services/object/common/writer/ec_test.go diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index 6b6a14cc0a..dffe52a6de 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -197,14 +197,15 @@ func (e *ECWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er if err != nil { return err } + partsProcessed := make([]atomic.Bool, len(parts)) objID, _ := obj.ID() t, err := placement.NewTraverser(append(e.PlacementOpts, placement.ForObject(objID))...) if err != nil { return err } - eg, egCtx := errgroup.WithContext(ctx) for { + eg, egCtx := errgroup.WithContext(ctx) nodes := t.Next() if len(nodes) == 0 { break @@ -216,13 +217,20 @@ func (e *ECWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er } for idx := range parts { - eg.Go(func() error { - return e.writePart(egCtx, parts[idx], idx, nodes, visited) - }) - t.SubmitSuccess() + if !partsProcessed[idx].Load() { + eg.Go(func() error { + err := e.writePart(egCtx, parts[idx], idx, nodes, visited) + if err == nil { + partsProcessed[idx].Store(true) + t.SubmitSuccess() + } + return err + }) + } } + err = eg.Wait() } - if err := eg.Wait(); err != nil { + if err != nil { return errIncompletePut{ singleErr: err, } diff --git a/pkg/services/object/common/writer/ec_test.go b/pkg/services/object/common/writer/ec_test.go new file mode 100644 index 0000000000..32863d6787 --- /dev/null +++ b/pkg/services/object/common/writer/ec_test.go @@ -0,0 +1,191 @@ +package writer + +import ( + "bytes" + "context" + "crypto/rand" + "crypto/sha256" + "errors" + "fmt" + "strconv" + "testing" + + rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" + apiclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" + "git.frostfs.info/TrueCloudLab/tzhash/tz" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/panjf2000/ants/v2" + "github.com/stretchr/testify/require" +) + +type testPlacementBuilder struct { + vectors [][]netmap.NodeInfo +} + +func (p *testPlacementBuilder) BuildPlacement(_ cid.ID, _ *oid.ID, _ netmap.PlacementPolicy) ( + [][]netmap.NodeInfo, error, +) { + arr := make([]netmap.NodeInfo, len(p.vectors[0])) + copy(arr, p.vectors[0]) + return [][]netmap.NodeInfo{arr}, nil +} + +type nmKeys struct{} + +func (nmKeys) IsLocalKey(_ []byte) bool { + return false +} + +type clientConstructor struct { + vectors [][]netmap.NodeInfo +} + +func (c clientConstructor) Get(info client.NodeInfo) (client.MultiAddressClient, error) { + if bytes.Equal(info.PublicKey(), c.vectors[0][0].PublicKey()) || + bytes.Equal(info.PublicKey(), c.vectors[0][1].PublicKey()) { + return multiAddressClient{err: errors.New("node unavailable")}, nil + } + return multiAddressClient{}, nil +} + +type multiAddressClient struct { + client.MultiAddressClient + err error +} + +func (c multiAddressClient) ObjectPutSingle(_ context.Context, _ apiclient.PrmObjectPutSingle) (*apiclient.ResObjectPutSingle, error) { + if c.err != nil { + return nil, c.err + } + return &apiclient.ResObjectPutSingle{}, nil +} + +func (c multiAddressClient) ReportError(error) { +} + +func (multiAddressClient) RawForAddress(context.Context, network.Address, func(cli *rawclient.Client) error) error { + return nil +} + +func TestECWriter(t *testing.T) { + // Create container with policy EC 1.1 + cnr := container.Container{} + p1 := netmap.PlacementPolicy{} + p1.SetContainerBackupFactor(1) + x1 := netmap.ReplicaDescriptor{} + x1.SetECDataCount(1) + x1.SetECParityCount(1) + p1.AddReplicas(x1) + cnr.SetPlacementPolicy(p1) + cnr.SetAttribute("cnr", "cnr1") + + cid := cidtest.ID() + + // Create 4 nodes, 2 nodes for chunks, + // 2 nodes for the case when the first two will fail. + ns, _ := testNodeMatrix(t, []int{4}) + + data := make([]byte, 100) + _, _ = rand.Read(data) + ver := version.Current() + + var csum checksum.Checksum + csum.SetSHA256(sha256.Sum256(data)) + + var csumTZ checksum.Checksum + csumTZ.SetTillichZemor(tz.Sum(csum.Value())) + + obj := objectSDK.New() + obj.SetID(oidtest.ID()) + obj.SetOwnerID(usertest.ID()) + obj.SetContainerID(cid) + obj.SetVersion(&ver) + obj.SetPayload(data) + obj.SetPayloadSize(uint64(len(data))) + obj.SetPayloadChecksum(csum) + obj.SetPayloadHomomorphicHash(csumTZ) + + // Builder return nodes without sort by hrw + builder := &testPlacementBuilder{ + vectors: ns, + } + + ownerKey, err := keys.NewPrivateKey() + require.NoError(t, err) + + pool, err := ants.NewPool(4, ants.WithNonblocking(true)) + require.NoError(t, err) + + log, err := logger.NewLogger(nil) + require.NoError(t, err) + + var n nmKeys + ecw := ECWriter{ + Config: &Config{ + NetmapKeys: n, + RemotePool: pool, + Logger: log, + ClientConstructor: clientConstructor{vectors: ns}, + }, + PlacementOpts: append( + []placement.Option{placement.UseBuilder(builder), placement.ForContainer(cnr)}, + placement.WithCopyNumbers(nil)), // copies number ignored for EC + Container: cnr, + Key: &ownerKey.PrivateKey, + Relay: nil, + ObjectMetaValid: true, + } + + err = ecw.WriteObject(context.Background(), obj) + require.NoError(t, err) +} + +func testNodeMatrix(t testing.TB, dim []int) ([][]netmap.NodeInfo, [][]string) { + mNodes := make([][]netmap.NodeInfo, len(dim)) + mAddr := make([][]string, len(dim)) + + for i := range dim { + ns := make([]netmap.NodeInfo, dim[i]) + as := make([]string, dim[i]) + + for j := range dim[i] { + a := fmt.Sprintf("/ip4/192.168.0.%s/tcp/%s", + strconv.Itoa(i), + strconv.Itoa(60000+j), + ) + + var ni netmap.NodeInfo + ni.SetNetworkEndpoints(a) + ni.SetPublicKey([]byte(a)) + + var na network.AddressGroup + + err := na.FromIterator(netmapcore.Node(ni)) + require.NoError(t, err) + + as[j] = network.StringifyGroup(na) + + ns[j] = ni + } + + mNodes[i] = ns + mAddr[i] = as + } + + return mNodes, mAddr +} From d2a59b2de8572952df34e2b66c3bf51d03ce13d9 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 14 Oct 2024 15:51:37 +0300 Subject: [PATCH 0906/1413] [#1429] lens/explorer: Fix locked object records display text Display texts for a locked object and a list of it lockers were mistakenly swapped. Signed-off-by: Aleksey Savchuk --- cmd/frostfs-lens/internal/schema/metabase/records/string.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/string.go b/cmd/frostfs-lens/internal/schema/metabase/records/string.go index a6c70d537d..ec0ab8e1a4 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/records/string.go +++ b/cmd/frostfs-lens/internal/schema/metabase/records/string.go @@ -38,7 +38,7 @@ func (r *ContainerVolumeRecord) String() string { func (r *LockedRecord) String() string { return fmt.Sprintf( - "Locker OID %s %c Locked [%d]OID {...}", + "Object OID %s %c Lockers [%d]OID {...}", common.FormatSimple(fmt.Sprintf("%-44s", r.id), tcell.ColorAqua), tview.Borders.Vertical, len(r.ids), From 714ff784fa460767e82527b71fd520932b0256ed Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Mon, 14 Oct 2024 17:31:26 +0300 Subject: [PATCH 0907/1413] [#1431] objsvc: Use specific values in message about address mismatch This makes troubleshooting failed operations much easier Signed-off-by: Vitaliy Potyarkin --- pkg/services/object/common/target/target.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/common/target/target.go b/pkg/services/object/common/target/target.go index a2d6b4d39f..9e0f492972 100644 --- a/pkg/services/object/common/target/target.go +++ b/pkg/services/object/common/target/target.go @@ -86,7 +86,7 @@ func newTrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWriter user.IDFromKey(&ownerSession, key.PublicKey) if !ownerObj.Equals(ownerSession) { - return nil, errors.New("session token is missing but object owner id is different from the default key") + return nil, fmt.Errorf("session token is missing but object owner id (%s) is different from the default key (%s)", ownerObj, ownerSession) } } else { if !ownerObj.Equals(sessionInfo.Owner) { From 3012286452e8b2bb04a6ad9b70e364b00b29919f Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 14 Oct 2024 17:10:03 +0300 Subject: [PATCH 0908/1413] [#1431] metabase: Fix unreachable code Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/metabase/delete.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 3add1f268e..b5ac220179 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -453,7 +453,7 @@ func delFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { func hasAnyItem(b *bbolt.Bucket) bool { var hasAnyItem bool c := b.Cursor() - for k, _ := c.First(); k != nil; k, _ = c.Next() { + for k, _ := c.First(); k != nil; { hasAnyItem = true break } From d53732f663ce46ff29196782b5d836a37c1f6c7d Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 14 Oct 2024 17:17:00 +0300 Subject: [PATCH 0909/1413] [#1431] engine: Delete always false condition Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/engine/evacuate.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index c1b9276f35..940e303234 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -56,9 +56,6 @@ func (s EvacuateScope) String() string { var sb strings.Builder first := true if s&EvacuateScopeObjects == EvacuateScopeObjects { - if !first { - sb.WriteString(";") - } sb.WriteString("objects") first = false } From 63466d71b22d8b23eff4d0fc1eea5a16d36a138b Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 14 Oct 2024 17:20:14 +0300 Subject: [PATCH 0910/1413] [#1431] engine: Delete unused constants Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/modules/ape_manager/add_chain.go | 9 ++++----- internal/logs/logs.go | 14 -------------- pkg/morph/client/container/client.go | 1 - 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-cli/modules/ape_manager/add_chain.go b/cmd/frostfs-cli/modules/ape_manager/add_chain.go index c6622da255..a85f3c93e4 100644 --- a/cmd/frostfs-cli/modules/ape_manager/add_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/add_chain.go @@ -31,11 +31,10 @@ const ( ) const ( - defaultNamespace = "" - namespaceTarget = "namespace" - containerTarget = "container" - userTarget = "user" - groupTarget = "group" + namespaceTarget = "namespace" + containerTarget = "container" + userTarget = "user" + groupTarget = "group" ) var errUnknownTargetType = errors.New("unknown target type") diff --git a/internal/logs/logs.go b/internal/logs/logs.go index ca783a39d3..b4bc31b0c0 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -14,8 +14,6 @@ const ( InterruptPlacementIterationByContext = "interrupt placement iteration by context" Notification = "notification" - - SkipDeprecatedNotification = "skip deprecated notification" ) const ( @@ -41,8 +39,6 @@ const ( InnerringCantUpdatePersistentState = "can't update persistent state" InnerringCloserError = "closer error" InnerringReadConfigFromBlockchain = "read config from blockchain" - NotificatorNotificatorStartProcessingObjectNotifications = "notificator: start processing object notifications" - NotificatorNotificatorProcessingObjectNotification = "notificator: processing object notification" PolicerCouldNotGetContainer = "could not get container" PolicerCouldNotConfirmContainerRemoval = "could not confirm container removal" PolicerCouldNotInhumeObjectWithMissingContainer = "could not inhume object with missing container" @@ -61,7 +57,6 @@ const ( ReplicatorCouldNotReplicateObject = "could not replicate object" ReplicatorObjectSuccessfullyReplicated = "object successfully replicated" TreeRedirectingTreeServiceQuery = "redirecting tree service query" - TreeBearerPresentedButNotAllowedByACL = "bearer presented but not allowed by ACL" TreeCouldNotGetLastSynchronizedHeightForATree = "could not get last synchronized height for a tree" TreeCouldNotUpdateLastSynchronizedHeightForATree = "could not update last synchronized height for a tree" TreeSynchronizeTree = "synchronize tree" @@ -107,7 +102,6 @@ const ( GetUnableToGetAllPartsECObject = "unable to get all parts, continue to reconstruct with existed" GetUnableToGetPartECObject = "unable to get part of the erasure-encoded object" GetUnableToHeadPartECObject = "unable to head part of the erasure-encoded object" - GetUnableToGetECObjectContainer = "unable to get container for erasure-coded object" GetUnableToHeadPartsECObject = "unable to head parts of the erasure-encoded object" GetAssemblingSplittedObjectCompleted = "assembling splitted object completed" GetAssemblingECObjectCompleted = "assembling erasure-coded object completed" @@ -271,9 +265,7 @@ const ( ShardFailureToMarkLockersAsGarbage = "failure to mark lockers as garbage" ShardFailureToGetExpiredUnlockedObjects = "failure to get expired unlocked objects" ShardCouldNotMarkObjectToDeleteInMetabase = "could not mark object to delete in metabase" - WritecacheTriedToFlushItemsFromWritecache = "tried to flush items from write-cache" WritecacheWaitingForChannelsToFlush = "waiting for channels to flush" - WritecacheCantRemoveObjectsFromTheDatabase = "can't remove objects from the database" WritecacheCantRemoveObjectFromWritecache = "can't remove object from write-cache" BlobovniczatreeCouldNotGetObjectFromLevel = "could not get object from level" BlobovniczatreeCouldNotCloseBlobovnicza = "could not close Blobovnicza" @@ -413,11 +405,6 @@ const ( FrostFSNodeReadNewlyCreatedContainerAfterTheNotification = "read newly created container after the notification" FrostFSNodeContainerCreationEventsReceipt = "container creation event's receipt" FrostFSNodeContainerRemovalEventsReceipt = "container removal event's receipt" - FrostFSNodeNotificatorCouldNotListContainers = "notificator: could not list containers" - FrostFSNodeNotificatorCouldNotSelectObjectsFromContainer = "notificator: could not select objects from container" - FrostFSNodeNotificatorCouldNotProcessObject = "notificator: could not process object" - FrostFSNodeNotificatorFinishedProcessingObjectNotifications = "notificator: finished processing object notifications" - FrostFSNodeCouldNotWriteObjectNotification = "could not write object notification" FrostFSNodeCouldNotGetMaxObjectSizeValue = "could not get max object size value" FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage = "could not inhume mark redundant copy as garbage" FrostFSNodeFailedInitTracing = "failed init tracing" @@ -461,7 +448,6 @@ const ( FSTreeCantUnmarshalObject = "can't unmarshal an object" FSTreeCantFushObjectBlobstor = "can't flush an object to blobstor" FSTreeCantUpdateID = "can't update object storage ID" - FSTreeCantDecodeDBObjectAddress = "can't decode object address from the DB" PutSingleRedirectFailure = "failed to redirect PutSingle request" StorageIDRetrievalFailure = "can't get storage ID from metabase" ObjectRemovalFailureBlobStor = "can't remove object from blobStor" diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index fc892aafb2..f735a5ff71 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -33,7 +33,6 @@ const ( startEstimationMethod = "startContainerEstimation" stopEstimationMethod = "stopContainerEstimation" - putSizeMethod = "putContainerSize" listSizesMethod = "listContainerSizes" getSizeMethod = "getContainerSize" From 00b1cecfb7486aac93e8806caa6563fe75eabc1b Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 14 Oct 2024 17:25:00 +0300 Subject: [PATCH 0911/1413] [#1431] obj_storage/shard: Fix visibility of 'newMetricStore' Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/shard/control_test.go | 4 ++-- pkg/local_object_storage/shard/metrics_test.go | 4 ++-- pkg/local_object_storage/shard/reload_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 44fee16360..6b9eaa5507 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -126,7 +126,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) { }), } - mm := NewMetricStore() + mm := newMetricStore() sh := New( WithID(NewIDFromBytes([]byte{})), @@ -190,7 +190,7 @@ func TestRefillMetabase(t *testing.T) { }), } - mm := NewMetricStore() + mm := newMetricStore() sh := New( WithID(NewIDFromBytes([]byte{})), diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index 56622326a5..cec5a12adc 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -35,7 +35,7 @@ type metricsStore struct { refillStatus string } -func NewMetricStore() *metricsStore { +func newMetricStore() *metricsStore { return &metricsStore{ objCounters: map[string]uint64{ "phy": 0, @@ -404,7 +404,7 @@ func shardWithMetrics(t *testing.T, path string) (*Shard, *metricsStore) { }), } - mm := NewMetricStore() + mm := newMetricStore() sh := New( WithID(NewIDFromBytes([]byte{})), diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index 7dacbfa6c8..7dd7189bba 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -51,7 +51,7 @@ func TestShardReload(t *testing.T) { WithMetaBaseOptions(metaOpts...), WithPiloramaOptions( pilorama.WithPath(filepath.Join(p, "pilorama"))), - WithMetricsWriter(NewMetricStore()), + WithMetricsWriter(newMetricStore()), } sh := New(opts...) From f6582081a4ee67e97773f655b8f18148946c5a0c Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 14 Oct 2024 17:31:15 +0300 Subject: [PATCH 0912/1413] [#1431] obj_storage/metabase: Delete unused variable Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/metabase/put.go | 5 ++--- pkg/services/object/remote_reader.go | 3 --- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 0c14196b7c..b329e80327 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -59,9 +59,8 @@ func (p *PutPrm) SetIndexAttributes(v bool) { } var ( - ErrUnknownObjectType = errors.New("unknown object type") - ErrIncorrectSplitInfoUpdate = errors.New("updating split info on object without it") - ErrIncorrectRootObject = errors.New("invalid root object") + ErrUnknownObjectType = errors.New("unknown object type") + ErrIncorrectRootObject = errors.New("invalid root object") ) // Put saves object header in metabase. Object payload expected to be cut. diff --git a/pkg/services/object/remote_reader.go b/pkg/services/object/remote_reader.go index 18b6107cfa..bc6ffd1601 100644 --- a/pkg/services/object/remote_reader.go +++ b/pkg/services/object/remote_reader.go @@ -2,7 +2,6 @@ package object import ( "context" - "errors" "fmt" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" @@ -35,8 +34,6 @@ type RemoteRequestPrm struct { const remoteOpTTL = 1 -var ErrNotFound = errors.New("object header not found") - // NewRemoteReader creates, initializes and returns new RemoteHeader instance. func NewRemoteReader(keyStorage *util.KeyStorage, cache ClientConstructor) *RemoteReader { return &RemoteReader{ From d83879d4b859f016a9bfef808b19324ce593814e Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 14 Oct 2024 18:05:55 +0300 Subject: [PATCH 0913/1413] [#1431] node: Fix comment format Signed-off-by: Alexander Chuprov --- cmd/frostfs-node/config/profiler/config.go | 2 +- cmd/frostfs-node/object.go | 2 +- pkg/core/netmap/keys.go | 2 +- .../netmap/nodevalidation/locode/deps.go | 16 ++++++++-------- pkg/innerring/processors/netmap/processor.go | 2 +- pkg/local_object_storage/shard/metrics.go | 2 +- pkg/morph/client/actor.go | 2 +- pkg/morph/event/container/put_notary.go | 2 +- pkg/network/group.go | 4 ++-- pkg/services/control/ir/server/deps.go | 2 +- pkg/services/control/rpc.go | 2 +- pkg/services/control/server/server.go | 4 ++-- pkg/services/netmap/executor.go | 4 ++-- pkg/services/object/common/writer/distributed.go | 2 +- pkg/services/object/delete/service.go | 4 ++-- pkg/services/object/patch/service.go | 2 +- pkg/services/policer/option.go | 2 +- pkg/util/rand/rand.go | 2 +- pkg/util/sdnotify/sdnotify.go | 2 +- 19 files changed, 30 insertions(+), 30 deletions(-) diff --git a/cmd/frostfs-node/config/profiler/config.go b/cmd/frostfs-node/config/profiler/config.go index 1916949701..6c3e8adabd 100644 --- a/cmd/frostfs-node/config/profiler/config.go +++ b/cmd/frostfs-node/config/profiler/config.go @@ -52,7 +52,7 @@ func Address(c *config.Config) string { return AddressDefault } -// BlockRates returns the value of "block_rate" config parameter +// BlockRate returns the value of "block_rate" config parameter // from "pprof" section. func BlockRate(c *config.Config) int { s := c.Sub(subsection) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 68acb05d34..c484c5d8ca 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -117,7 +117,7 @@ func (i *delNetInfo) TombstoneLifetime() (uint64, error) { return i.cfg.cfgObject.tombstoneLifetime.Load(), nil } -// returns node owner ID calculated from configured private key. +// LocalNodeID returns node owner ID calculated from configured private key. // // Implements method needed for Object.Delete service. func (i *delNetInfo) LocalNodeID() user.ID { diff --git a/pkg/core/netmap/keys.go b/pkg/core/netmap/keys.go index 29cb2dc943..0c64bb7984 100644 --- a/pkg/core/netmap/keys.go +++ b/pkg/core/netmap/keys.go @@ -2,6 +2,6 @@ package netmap // AnnouncedKeys is an interface of utility for working with the announced public keys of the storage nodes. type AnnouncedKeys interface { - // Checks if the key was announced by a local node. + // IsLocalKey checks if the key was announced by a local node. IsLocalKey(key []byte) bool } diff --git a/pkg/innerring/processors/netmap/nodevalidation/locode/deps.go b/pkg/innerring/processors/netmap/nodevalidation/locode/deps.go index 8f66679339..ba5db9205f 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/locode/deps.go +++ b/pkg/innerring/processors/netmap/nodevalidation/locode/deps.go @@ -8,38 +8,38 @@ import ( // Record is an interface of read-only // FrostFS LOCODE database single entry. type Record interface { - // Must return ISO 3166-1 alpha-2 + // CountryCode must return ISO 3166-1 alpha-2 // country code. // // Must not return nil. CountryCode() *locodedb.CountryCode - // Must return English short country name + // CountryName must return English short country name // officially used by the ISO 3166 // Maintenance Agency (ISO 3166/MA). CountryName() string - // Must return UN/LOCODE 3-character code + // LocationCode must return UN/LOCODE 3-character code // for the location (numerals 2-9 may also // be used). // // Must not return nil. LocationCode() *locodedb.LocationCode - // Must return name of the location which + // LocationName must return name of the location which // have been allocated a UN/LOCODE without // diacritic sign. LocationName() string - // Must return ISO 1-3 character alphabetic + // SubDivCode Must return ISO 1-3 character alphabetic // and/or numeric code for the administrative // division of the country concerned. SubDivCode() string - // Must return subdivision name. + // SubDivName must return subdivision name. SubDivName() string - // Must return existing continent where is + // Continent must return existing continent where is // the location. // // Must not return nil. @@ -49,7 +49,7 @@ type Record interface { // DB is an interface of read-only // FrostFS LOCODE database. type DB interface { - // Must find the record that corresponds to + // Get must find the record that corresponds to // LOCODE and provides the Record interface. // // Must return an error if Record is nil. diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index e8fb8721be..4cecda59c2 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -43,7 +43,7 @@ type ( // of information about the node and its finalization for adding // to the network map. NodeValidator interface { - // Must verify and optionally update NodeInfo structure. + // VerifyAndUpdate must verify and optionally update NodeInfo structure. // // Must return an error if NodeInfo input is invalid. // Must return an error if it is not possible to correctly diff --git a/pkg/local_object_storage/shard/metrics.go b/pkg/local_object_storage/shard/metrics.go index 91bf8d0aef..087ba42efa 100644 --- a/pkg/local_object_storage/shard/metrics.go +++ b/pkg/local_object_storage/shard/metrics.go @@ -22,7 +22,7 @@ type MetricsWriter interface { // SetShardID must set (update) the shard identifier that will be used in // metrics. SetShardID(id string) - // SetReadonly must set shard mode. + // SetMode set mode of shard. SetMode(mode mode.Mode) // SetContainerObjectsCount sets container object count. SetContainerObjectsCount(cnrID string, objectType string, value uint64) diff --git a/pkg/morph/client/actor.go b/pkg/morph/client/actor.go index b6718dea5a..2849f3052b 100644 --- a/pkg/morph/client/actor.go +++ b/pkg/morph/client/actor.go @@ -16,7 +16,7 @@ type actorProvider interface { GetRPCActor() actor.RPCActor } -// Client switches an established connection with neo-go if it is broken. +// SwitchRPCGuardedActor switches an established connection with neo-go if it is broken. // This leads to an invalidation of an rpc actor within Client. That means the // components that are initilized with the rpc actor may unintentionally use // it when it is already invalidated. SwitchRPCGuardedActor is used to prevent diff --git a/pkg/morph/event/container/put_notary.go b/pkg/morph/event/container/put_notary.go index f5779ced65..6b2ee7b0ac 100644 --- a/pkg/morph/event/container/put_notary.go +++ b/pkg/morph/event/container/put_notary.go @@ -46,7 +46,7 @@ const ( // put container requests. PutNotaryEvent = "put" - // PutNotaryEvent is an ID of notary "put named container" notification. + // PutNamedNotaryEvent is an ID of notary "put named container" notification. PutNamedNotaryEvent = "putNamed" ) diff --git a/pkg/network/group.go b/pkg/network/group.go index a6de0653e2..9843b14d4d 100644 --- a/pkg/network/group.go +++ b/pkg/network/group.go @@ -67,11 +67,11 @@ func (x AddressGroup) Swap(i, j int) { // MultiAddressIterator is an interface of network address group. type MultiAddressIterator interface { - // Must iterate over network addresses and pass each one + // IterateAddresses must iterate over network addresses and pass each one // to the handler until it returns true. IterateAddresses(func(string) bool) - // Must return number of addresses in group. + // NumberOfAddresses must return number of addresses in group. NumberOfAddresses() int } diff --git a/pkg/services/control/ir/server/deps.go b/pkg/services/control/ir/server/deps.go index 0c2de53006..9d5cfefc8e 100644 --- a/pkg/services/control/ir/server/deps.go +++ b/pkg/services/control/ir/server/deps.go @@ -5,7 +5,7 @@ import control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ // HealthChecker is component interface for calculating // the current health status of a node. type HealthChecker interface { - // Must calculate and return current health status of the IR application. + // HealthStatus must calculate and return current health status of the IR application. // // If status can not be calculated for any reason, // control.HealthStatus_HEALTH_STATUS_UNDEFINED should be returned. diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 80aece0088..04524a68ce 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -292,7 +292,7 @@ func ListTargetsLocalOverrides(cli *client.Client, req *ListTargetsLocalOverride return wResp.message, nil } -// RemoveChainLocalOverride executes ControlService.RemoveChainLocalOverride RPC. +// GetChainLocalOverride executes ControlService.RemoveChainLocalOverride RPC. func GetChainLocalOverride(cli *client.Client, req *GetChainLocalOverrideRequest, opts ...client.CallOption) (*GetChainLocalOverrideResponse, error) { wResp := newResponseWrapper[GetChainLocalOverrideResponse]() wReq := &requestWrapper{m: req} diff --git a/pkg/services/control/server/server.go b/pkg/services/control/server/server.go index f3fe56a46c..b6fdcb246a 100644 --- a/pkg/services/control/server/server.go +++ b/pkg/services/control/server/server.go @@ -26,13 +26,13 @@ type Server struct { // HealthChecker is component interface for calculating // the current health status of a node. type HealthChecker interface { - // Must calculate and return current status of the node in FrostFS network map. + // NetmapStatus must calculate and return current status of the node in FrostFS network map. // // If status can not be calculated for any reason, // control.netmapStatus_STATUS_UNDEFINED should be returned. NetmapStatus() control.NetmapStatus - // Must calculate and return current health status of the node application. + // HealthStatus must calculate and return current health status of the node application. // // If status can not be calculated for any reason, // control.HealthStatus_HEALTH_STATUS_UNDEFINED should be returned. diff --git a/pkg/services/netmap/executor.go b/pkg/services/netmap/executor.go index 496b07a981..ae2044246f 100644 --- a/pkg/services/netmap/executor.go +++ b/pkg/services/netmap/executor.go @@ -26,7 +26,7 @@ type executorSvc struct { // NodeState encapsulates information // about current node state. type NodeState interface { - // Must return current node state + // LocalNodeInfo must return current node state // in FrostFS API v2 NodeInfo structure. LocalNodeInfo() (*netmap.NodeInfo, error) @@ -39,7 +39,7 @@ type NodeState interface { // NetworkInfo encapsulates source of the // recent information about the FrostFS network. type NetworkInfo interface { - // Must return recent network information in FrostFS API v2 NetworkInfo structure. + // Dump must return recent network information in FrostFS API v2 NetworkInfo structure. // // If protocol version is <=2.9, MillisecondsPerBlock and network config should be unset. Dump(versionsdk.Version) (*netmapSDK.NetworkInfo, error) diff --git a/pkg/services/object/common/writer/distributed.go b/pkg/services/object/common/writer/distributed.go index f62934beda..f7486eae72 100644 --- a/pkg/services/object/common/writer/distributed.go +++ b/pkg/services/object/common/writer/distributed.go @@ -28,7 +28,7 @@ type distributedWriter struct { resetSuccessAfterOnBroadcast bool } -// parameters and state of container Traversal. +// Traversal parameters and state of container. type Traversal struct { Opts []placement.Option diff --git a/pkg/services/object/delete/service.go b/pkg/services/object/delete/service.go index 0ba21eee38..e4f7a8c502 100644 --- a/pkg/services/object/delete/service.go +++ b/pkg/services/object/delete/service.go @@ -27,11 +27,11 @@ type Option func(*cfg) type NetworkInfo interface { netmap.State - // Must return the lifespan of the tombstones + // TombstoneLifetime must return the lifespan of the tombstones // in the FrostFS epochs. TombstoneLifetime() (uint64, error) - // Returns user ID of the local storage node. Result must not be nil. + // LocalNodeID returns user ID of the local storage node. Result must not be nil. // New tombstone objects will have the result as an owner ID if removal is executed w/o a session. LocalNodeID() user.ID } diff --git a/pkg/services/object/patch/service.go b/pkg/services/object/patch/service.go index f1082dfff1..953f82b483 100644 --- a/pkg/services/object/patch/service.go +++ b/pkg/services/object/patch/service.go @@ -26,7 +26,7 @@ func NewService(cfg *objectwriter.Config, } } -// Put calls internal service and returns v2 object streamer. +// Patch calls internal service and returns v2 object streamer. func (s *Service) Patch() (object.PatchObjectStream, error) { nodeKey, err := s.Config.KeyStorage.GetKey(nil) if err != nil { diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 9dbfd8b9ff..336f7a0abb 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -143,7 +143,7 @@ func WithPlacementBuilder(v placement.Builder) Option { } } -// WithRemoteObjectHeader returns option to set remote object header receiver of Policer. +// WithRemoteObjectHeaderFunc returns option to set remote object header receiver of Policer. func WithRemoteObjectHeaderFunc(v RemoteObjectHeaderFunc) Option { return func(c *cfg) { c.remoteHeader = v diff --git a/pkg/util/rand/rand.go b/pkg/util/rand/rand.go index 97508f82af..a06296a07f 100644 --- a/pkg/util/rand/rand.go +++ b/pkg/util/rand/rand.go @@ -13,7 +13,7 @@ func Uint64() uint64 { return source.Uint64() } -// Uint64 returns a random uint32 value. +// Uint32 returns a random uint32 value. func Uint32() uint32 { return source.Uint32() } diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go index e94ff77ad3..22549bc963 100644 --- a/pkg/util/sdnotify/sdnotify.go +++ b/pkg/util/sdnotify/sdnotify.go @@ -24,7 +24,7 @@ var ( errSocketIsNotInitialized = errors.New("socket is not initialized") ) -// Initializes socket with provided name of +// InitSocket initializes socket with provided name of // environment variable. func InitSocket() error { notifySocket := os.Getenv("NOTIFY_SOCKET") From 41038b2ec0fab0d9488f15330e8777f053a28c03 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 14 Oct 2024 18:16:59 +0300 Subject: [PATCH 0914/1413] [#1431] node: Fix 'empty slice declaration using a literal' Signed-off-by: Alexander Chuprov --- pkg/innerring/processors/alphabet/handlers_test.go | 6 +++--- pkg/local_object_storage/shard/control.go | 2 +- pkg/morph/event/notary_preparator_test.go | 2 +- scripts/populate-metabase/internal/generate.go | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index dfda374727..c7a004b54f 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -95,7 +95,7 @@ func TestProcessorEmitsGasToNetmapIfNoParsedWallets(t *testing.T) { t.Parallel() var emission uint64 = 100_000 var index int = 5 - var parsedWallets []util.Uint160 = []util.Uint160{} + var parsedWallets []util.Uint160 alphabetContracts := innerring.NewAlphabetContracts() for i := range index + 1 { @@ -167,7 +167,7 @@ func TestProcessorDoesntEmitGasIfNoNetmapOrParsedWallets(t *testing.T) { t.Parallel() var emission uint64 = 100_000 var index int = 5 - var parsedWallets []util.Uint160 = []util.Uint160{} + var parsedWallets []util.Uint160 alphabetContracts := innerring.NewAlphabetContracts() for i := range index + 1 { @@ -176,7 +176,7 @@ func TestProcessorDoesntEmitGasIfNoNetmapOrParsedWallets(t *testing.T) { morphClient := &testMorphClient{} - nodes := []netmap.NodeInfo{} + var nodes []netmap.NodeInfo network := &netmap.NetMap{} network.SetNodes(nodes) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 4f9f256086..62800dbd03 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -368,7 +368,7 @@ func (s *Shard) Close() error { if s.rb != nil { s.rb.Stop(s.log) } - components := []interface{ Close() error }{} + var components []interface{ Close() error } if s.pilorama != nil { components = append(components, s.pilorama) diff --git a/pkg/morph/event/notary_preparator_test.go b/pkg/morph/event/notary_preparator_test.go index 4c269bcbdb..60ddb46010 100644 --- a/pkg/morph/event/notary_preparator_test.go +++ b/pkg/morph/event/notary_preparator_test.go @@ -25,7 +25,7 @@ var ( alphaKeys keys.PublicKeys wrongAlphaKeys keys.PublicKeys - dummyAlphabetInvocationScript = []byte{} // expected to be empty if generated by Notary Actor, as requester can't fill it in + dummyAlphabetInvocationScript []byte dummyAlphabetInvocationScriptOld = append([]byte{byte(opcode.PUSHDATA1), 64}, make([]byte, 64)...) // expected to be dummy if generated manually wrongDummyInvocationScript = append([]byte{byte(opcode.PUSHDATA1), 64, 1}, make([]byte, 63)...) diff --git a/scripts/populate-metabase/internal/generate.go b/scripts/populate-metabase/internal/generate.go index d2004b6734..8a96dcaaa8 100644 --- a/scripts/populate-metabase/internal/generate.go +++ b/scripts/populate-metabase/internal/generate.go @@ -18,7 +18,7 @@ import ( ) func GeneratePayloadPool(count uint, size uint) [][]byte { - pool := [][]byte{} + var pool [][]byte for i := uint(0); i < count; i++ { payload := make([]byte, size) _, _ = rand.Read(payload) @@ -29,7 +29,7 @@ func GeneratePayloadPool(count uint, size uint) [][]byte { } func GenerateAttributePool(count uint) []objectSDK.Attribute { - pool := []objectSDK.Attribute{} + var pool []objectSDK.Attribute for i := uint(0); i < count; i++ { for j := uint(0); j < count; j++ { attr := *objectSDK.NewAttribute() @@ -42,7 +42,7 @@ func GenerateAttributePool(count uint) []objectSDK.Attribute { } func GenerateOwnerPool(count uint) []user.ID { - pool := []user.ID{} + var pool []user.ID for i := uint(0); i < count; i++ { pool = append(pool, usertest.ID()) } @@ -117,7 +117,7 @@ func WithPayloadFromPool(pool [][]byte) ObjectOption { func WithAttributesFromPool(pool []objectSDK.Attribute, count uint) ObjectOption { return func(obj *objectSDK.Object) { - attrs := []objectSDK.Attribute{} + var attrs []objectSDK.Attribute for i := uint(0); i < count; i++ { attrs = append(attrs, pool[rand.Intn(len(pool))]) } From 07ce40e1196a44d305390dcea8e1e0040f6a16d2 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 15 Oct 2024 12:28:58 +0300 Subject: [PATCH 0915/1413] [#1430] adm/morph: Add NNS address display in 'deploy' Signed-off-by: Alexander Chuprov --- cmd/frostfs-adm/internal/modules/morph/helper/contract.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/contract.go b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go index 2011301d17..eea3b040e6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/contract.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go @@ -166,5 +166,6 @@ func DeployNNS(c *InitializeContext, method string) error { return fmt.Errorf("can't send deploy transaction: %w", err) } + c.Command.Println("NNS hash:", invokeHash.StringLE()) return c.AwaitTx() } From 90f36693995e1b411094686e4419bb7d11831f35 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 14 Oct 2024 16:07:38 +0300 Subject: [PATCH 0916/1413] [#1342] network/cache: Add node address to error multiClient Signed-off-by: Alexander Chuprov --- pkg/network/cache/multi.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 9305c143b8..b83cbb217b 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -169,15 +169,16 @@ func (x *multiClient) iterateClients(ctx context.Context, f func(clientcore.Clie var siErr *objectSDK.SplitInfoError var eiErr *objectSDK.ECInfoError + if err != nil { + err = fmt.Errorf("client connection error at %v: %w", addr, err) + x.ReportError(err) + } + success := err == nil || errors.Is(err, context.Canceled) || errors.As(err, &siErr) || errors.As(err, &eiErr) if success || firstErr == nil || errors.Is(firstErr, errRecentlyFailed) { firstErr = err } - if err != nil { - x.ReportError(err) - } - return success }) From b0c5def2d934ed5b79f54fb37160560f576785f4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Oct 2024 14:16:03 +0300 Subject: [PATCH 0917/1413] [#1433] shard/test: Use WithDisabledGC() option where possible Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc_internal_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 3993593ad7..11db5e54eb 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -73,10 +73,10 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { return pool }), WithGCRemoverSleepInterval(1 * time.Second), + WithDisabledGC(), } sh = New(opts...) - sh.gcCfg.testHookRemover = func(context.Context) gcRunResult { return gcRunResult{} } require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) defer func() { require.NoError(t, sh.Close()) }() From b42bcdc6fa6cca2cf8e5a5fbaf2c8cf82f957b37 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Oct 2024 14:37:26 +0300 Subject: [PATCH 0918/1413] [#1433] services/object: Put object before auxiliary info Consider the following operations ordering: 1. Inhume(with tombstone A) --> add tombstone mark for an object 2. --> new epoch arives 3. --> GCMark is added for a tombstone A, because it is unavailable 4. Put(A) --> return error, because the object already has a GCMark It is possible, and I have successfully reproduced it with a test on the shard level. However, the error is related to the specific _ordering_ of operations with engine. And triggering race-conditions like this is only possible on a shard level currently, so no tests are written. Signed-off-by: Evgenii Stratonikov --- pkg/services/object/common/writer/local.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/services/object/common/writer/local.go b/pkg/services/object/common/writer/local.go index e219b44ddf..cf3d032756 100644 --- a/pkg/services/object/common/writer/local.go +++ b/pkg/services/object/common/writer/local.go @@ -32,6 +32,10 @@ type LocalTarget struct { } func (t LocalTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, meta objectCore.ContentMeta) error { + if err := t.Storage.Put(ctx, obj, containerCore.IsIndexedContainer(t.Container)); err != nil { + return fmt.Errorf("(%T) could not put object to local storage: %w", t, err) + } + switch meta.Type() { case objectSDK.TypeTombstone: err := t.Storage.Delete(ctx, objectCore.AddressOf(obj), meta.Objects()) @@ -47,8 +51,5 @@ func (t LocalTarget) WriteObject(ctx context.Context, obj *objectSDK.Object, met // objects that do not change meta storage } - if err := t.Storage.Put(ctx, obj, containerCore.IsIndexedContainer(t.Container)); err != nil { - return fmt.Errorf("(%T) could not put object to local storage: %w", t, err) - } return nil } From 3304afa9d1f9893ad72bcd9445751798b6558c16 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 8 Oct 2024 15:24:01 +0300 Subject: [PATCH 0919/1413] [#1422] config: Add multinet config Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config/multinet/config.go | 62 +++++++++++++++++++ .../config/multinet/config_test.go | 52 ++++++++++++++++ config/example/ir.env | 9 +++ config/example/ir.yaml | 15 +++++ config/example/node.env | 10 +++ config/example/node.json | 22 +++++++ config/example/node.yaml | 15 +++++ docs/storage-node-configuration.md | 39 ++++++++++-- 8 files changed, 219 insertions(+), 5 deletions(-) create mode 100644 cmd/frostfs-node/config/multinet/config.go create mode 100644 cmd/frostfs-node/config/multinet/config_test.go diff --git a/cmd/frostfs-node/config/multinet/config.go b/cmd/frostfs-node/config/multinet/config.go new file mode 100644 index 0000000000..f598efc513 --- /dev/null +++ b/cmd/frostfs-node/config/multinet/config.go @@ -0,0 +1,62 @@ +package multinet + +import ( + "strconv" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" +) + +const ( + subsection = "multinet" + + FallbackDelayDefault = 300 * time.Millisecond +) + +// Enabled returns the value of "enabled" config parameter from "multinet" section. +func Enabled(c *config.Config) bool { + return config.BoolSafe(c.Sub(subsection), "enabled") +} + +type Subnet struct { + Mask string + SourceIPs []string +} + +// Subnets returns the value of "subnets" config parameter from "multinet" section. +func Subnets(c *config.Config) []Subnet { + var result []Subnet + sub := c.Sub(subsection).Sub("subnets") + for i := 0; ; i++ { + s := sub.Sub(strconv.FormatInt(int64(i), 10)) + mask := config.StringSafe(s, "mask") + if mask == "" { + break + } + sourceIPs := config.StringSliceSafe(s, "source_ips") + result = append(result, Subnet{ + Mask: mask, + SourceIPs: sourceIPs, + }) + } + return result +} + +// Balancer returns the value of "balancer" config parameter from "multinet" section. +func Balancer(c *config.Config) string { + return config.StringSafe(c.Sub(subsection), "balancer") +} + +// Restrict returns the value of "restrict" config parameter from "multinet" section. +func Restrict(c *config.Config) bool { + return config.BoolSafe(c.Sub(subsection), "restrict") +} + +// FallbackDelay returns the value of "fallback_delay" config parameter from "multinet" section. +func FallbackDelay(c *config.Config) time.Duration { + fd := config.DurationSafe(c.Sub(subsection), "fallback_delay") + if fd != 0 { // negative value means no fallback + return fd + } + return FallbackDelayDefault +} diff --git a/cmd/frostfs-node/config/multinet/config_test.go b/cmd/frostfs-node/config/multinet/config_test.go new file mode 100644 index 0000000000..5f7dc6d532 --- /dev/null +++ b/cmd/frostfs-node/config/multinet/config_test.go @@ -0,0 +1,52 @@ +package multinet + +import ( + "testing" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" + "github.com/stretchr/testify/require" +) + +func TestMultinetSection(t *testing.T) { + t.Run("defaults", func(t *testing.T) { + empty := configtest.EmptyConfig() + require.Equal(t, false, Enabled(empty)) + require.Equal(t, ([]Subnet)(nil), Subnets(empty)) + require.Equal(t, "", Balancer(empty)) + require.Equal(t, false, Restrict(empty)) + require.Equal(t, FallbackDelayDefault, FallbackDelay(empty)) + }) + + const path = "../../../../config/example/node" + + fileConfigTest := func(c *config.Config) { + require.Equal(t, true, Enabled(c)) + require.Equal(t, []Subnet{ + { + Mask: "192.168.219.174/24", + SourceIPs: []string{ + "192.168.218.185", + "192.168.219.185", + }, + }, + { + Mask: "10.78.70.74/24", + SourceIPs: []string{ + "10.78.70.185", + "10.78.71.185", + }, + }, + }, Subnets(c)) + require.Equal(t, "roundrobin", Balancer(c)) + require.Equal(t, false, Restrict(c)) + require.Equal(t, 350*time.Millisecond, FallbackDelay(c)) + } + + configtest.ForEachFileType(path, fileConfigTest) + + t.Run("ENV", func(t *testing.T) { + configtest.ForEnvFileType(t, path, fileConfigTest) + }) +} diff --git a/config/example/ir.env b/config/example/ir.env index 7234a4b32c..ebd91c243e 100644 --- a/config/example/ir.env +++ b/config/example/ir.env @@ -80,3 +80,12 @@ FROSTFS_IR_PPROF_MUTEX_RATE=10000 FROSTFS_IR_PROMETHEUS_ENABLED=true FROSTFS_IR_PROMETHEUS_ADDRESS=localhost:9090 FROSTFS_IR_PROMETHEUS_SHUTDOWN_TIMEOUT=30s + +FROSTFS_MULTINET_ENABLED=true +FROSTFS_MULTINET_SUBNETS_0_MASK="192.168.219.174/24" +FROSTFS_MULTINET_SUBNETS_0_SOURCE_IPS="192.168.218.185 192.168.219.185" +FROSTFS_MULTINET_SUBNETS_1_MASK="10.78.70.74/24" +FROSTFS_MULTINET_SUBNETS_1_SOURCE_IPS="10.78.70.185 10.78.71.185" +FROSTFS_MULTINET_BALANCER=roundrobin +FROSTFS_MULTINET_RESTRICT=false +FROSTFS_MULTINET_FALLBACK_DELAY=350ms diff --git a/config/example/ir.yaml b/config/example/ir.yaml index 4c64f088b6..49f9fd324c 100644 --- a/config/example/ir.yaml +++ b/config/example/ir.yaml @@ -123,3 +123,18 @@ prometheus: systemdnotify: enabled: true + +multinet: + enabled: true + subnets: + - mask: 192.168.219.174/24 + source_ips: + - 192.168.218.185 + - 192.168.219.185 + - mask: 10.78.70.74/24 + source_ips: + - 10.78.70.185 + - 10.78.71.185 + balancer: roundrobin + restrict: false + fallback_delay: 350ms diff --git a/config/example/node.env b/config/example/node.env index 6618a981aa..580d343fbb 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -206,3 +206,13 @@ FROSTFS_RUNTIME_SOFT_MEMORY_LIMIT=1073741824 # AUDIT section FROSTFS_AUDIT_ENABLED=true + +# MULTINET section +FROSTFS_MULTINET_ENABLED=true +FROSTFS_MULTINET_SUBNETS_0_MASK="192.168.219.174/24" +FROSTFS_MULTINET_SUBNETS_0_SOURCE_IPS="192.168.218.185 192.168.219.185" +FROSTFS_MULTINET_SUBNETS_1_MASK="10.78.70.74/24" +FROSTFS_MULTINET_SUBNETS_1_SOURCE_IPS="10.78.70.185 10.78.71.185" +FROSTFS_MULTINET_BALANCER=roundrobin +FROSTFS_MULTINET_RESTRICT=false +FROSTFS_MULTINET_FALLBACK_DELAY=350ms diff --git a/config/example/node.json b/config/example/node.json index 0d100ed80f..3470d2d124 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -264,5 +264,27 @@ }, "audit": { "enabled": true + }, + "multinet": { + "enabled": true, + "subnets": [ + { + "mask": "192.168.219.174/24", + "source_ips": [ + "192.168.218.185", + "192.168.219.185" + ] + }, + { + "mask": "10.78.70.74/24", + "source_ips":[ + "10.78.70.185", + "10.78.71.185" + ] + } + ], + "balancer": "roundrobin", + "restrict": false, + "fallback_delay": "350ms" } } diff --git a/config/example/node.yaml b/config/example/node.yaml index 2a80fba182..2a963fc0f3 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -240,3 +240,18 @@ runtime: audit: enabled: true + +multinet: + enabled: true + subnets: + - mask: 192.168.219.174/24 + source_ips: + - 192.168.218.185 + - 192.168.219.185 + - mask: 10.78.70.74/24 + source_ips: + - 10.78.70.185 + - 10.78.71.185 + balancer: roundrobin + restrict: false + fallback_delay: 350ms diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index c74695e2b6..2b94400dfe 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -25,8 +25,8 @@ There are some custom types used for brevity: | `replicator` | [Replicator service configuration](#replicator-section) | | `storage` | [Storage engine configuration](#storage-section) | | `runtime` | [Runtime configuration](#runtime-section) | -| `audit` | [Audit configuration](#audit-section) | - +| `audit` | [Audit configuration](#audit-section) | +| `multinet` | [Multinet configuration](#multinet-section) | # `control` section ```yaml @@ -435,6 +435,35 @@ audit: enabled: true ``` -| Parameter | Type | Default value | Description | -|---------------------|--------|---------------|---------------------------------------------------| -| `soft_memory_limit` | `bool` | false | If `true` then audit event logs will be recorded. | +| Parameter | Type | Default value | Description | +|-----------|--------|---------------|---------------------------------------------------| +| `enabled` | `bool` | false | If `true` then audit event logs will be recorded. | + + +# `multinet` section +Contains multinet parameters. + +```yaml +multinet: + enabled: true + subnets: + - mask: 192.168.219.174/24 + source_ips: + - 192.168.218.185 + - 192.168.219.185 + - mask: 10.78.70.74/24 + source_ips: + - 10.78.70.185 + - 10.78.71.185 + balancer: roundrobin + restrict: false + fallback_delay: 350ms +``` + +| Parameter | Type | Default value | Description | +| ---------------- | ---------- | ------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `enabled` | `bool` | false | If `true` then source-based routing is enabled. | +| `subnets` | `subnet` | empty | Resulting subnets. | +| `balancer` | `string` | "" | Balancer to select network interfaces, allowed values are "" (no balancing, use first suitable interface) or "roundrobin". | +| `restrict` | `bool` | false | If `true` then any requests that do not match `subnets` will fail. | +| `fallback_delay` | `duration` | 350ms | Delay before fallback to secondary IP addresses in case of hostname resolve. | From 74db7352653b67e67e9345e0659fd37047fec710 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 8 Oct 2024 17:25:37 +0300 Subject: [PATCH 0920/1413] [#1422] node: Add dialer source to config Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 30 +++++++++++++++ go.mod | 1 + go.sum | 2 + internal/logs/logs.go | 1 + internal/net/config.go | 66 +++++++++++++++++++++++++++++++++ internal/net/dial_target.go | 54 +++++++++++++++++++++++++++ internal/net/dialer.go | 35 ++++++++++++++++++ internal/net/dialer_source.go | 69 +++++++++++++++++++++++++++++++++++ 8 files changed, 258 insertions(+) create mode 100644 internal/net/config.go create mode 100644 internal/net/dial_target.go create mode 100644 internal/net/dialer.go create mode 100644 internal/net/dialer_source.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 3c7e310b41..dc1bad485f 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -26,12 +26,14 @@ import ( fstreeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/fstree" loggerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/logger" morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/multinet" nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" objectconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/object" replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" + internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" @@ -436,6 +438,8 @@ type shared struct { metricsCollector *metrics.NodeMetrics metricsSvc *objectService.MetricCollector + + dialerSource *internalNet.DialerSource } // dynamicConfiguration stores parameters of the @@ -760,6 +764,9 @@ func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkSt persistate, err := state.NewPersistentStorage(nodeconfig.PersistentState(appCfg).Path()) fatalOnErr(err) + ds, err := internalNet.NewDialerSource(internalNetConfig(appCfg)) + fatalOnErr(err) + cacheOpts := cache.ClientCacheOpts{ DialTimeout: apiclientconfig.DialTimeout(appCfg), StreamTimeout: apiclientconfig.StreamTimeout(appCfg), @@ -778,9 +785,27 @@ func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkSt putClientCache: cache.NewSDKClientCache(cacheOpts), persistate: persistate, metricsCollector: metrics.NewNodeMetrics(), + dialerSource: ds, } } +func internalNetConfig(appCfg *config.Config) internalNet.Config { + result := internalNet.Config{ + Enabled: multinet.Enabled(appCfg), + Balancer: multinet.Balancer(appCfg), + Restrict: multinet.Restrict(appCfg), + FallbackDelay: multinet.FallbackDelay(appCfg), + } + sn := multinet.Subnets(appCfg) + for _, s := range sn { + result.Subnets = append(result.Subnets, internalNet.Subnet{ + Prefix: s.Mask, + SourceIPs: s.SourceIPs, + }) + } + return result +} + func initNetmap(appCfg *config.Config, netState *networkState, relayOnly bool) cfgNetmap { netmapWorkerPool, err := ants.NewPool(notificationHandlerPoolSize) fatalOnErr(err) @@ -1336,6 +1361,11 @@ func (c *cfg) reloadConfig(ctx context.Context) { } } + if err := c.dialerSource.Update(internalNetConfig(c.appCfg)); err != nil { + c.log.Error(logs.FailedToUpdateMultinetConfiguration, zap.Error(err)) + return + } + c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) } diff --git a/go.mod b/go.mod index 1468c12b22..a84d3122a1 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509 git.frostfs.info/TrueCloudLab/hrw v1.2.1 + git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 diff --git a/go.sum b/go.sum index 5ce81807ad..43d53aa404 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509/go.mod h1:jmb7yxzZota9jWbC10p+7YR+6wwJPBj7J/Fl5VDkXys= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= +git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= +git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972/go.mod h1:2hM42MBrlhvN6XToaW6OWNk5ZLcu1FhaukGgxtfpDDI= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 h1:vgbfkcnIexZUm3vREBBSa/Gv1Whjd1SFCUd0A+IaGPQ= diff --git a/internal/logs/logs.go b/internal/logs/logs.go index b4bc31b0c0..0e9d58f320 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -523,4 +523,5 @@ const ( WritecacheShrinkSkippedNotEmpty = "writecache shrink skipped: not empty" BlobovniczatreeFailedToRemoveRebuildTempFile = "failed to remove rebuild temp file" WritecacheCantGetObject = "can't get an object from fstree" + FailedToUpdateMultinetConfiguration = "failed to update multinet configuration" ) diff --git a/internal/net/config.go b/internal/net/config.go new file mode 100644 index 0000000000..10450db23c --- /dev/null +++ b/internal/net/config.go @@ -0,0 +1,66 @@ +package net + +import ( + "errors" + "fmt" + "net/netip" + "slices" + "time" + + "git.frostfs.info/TrueCloudLab/multinet" +) + +var errEmptySourceIPList = errors.New("empty source IP list") + +type Subnet struct { + Prefix string + SourceIPs []string +} + +type Config struct { + Enabled bool + Subnets []Subnet + Balancer string + Restrict bool + FallbackDelay time.Duration +} + +func (c Config) toMultinetConfig() (multinet.Config, error) { + var subnets []multinet.Subnet + for _, s := range c.Subnets { + var ms multinet.Subnet + p, err := netip.ParsePrefix(s.Prefix) + if err != nil { + return multinet.Config{}, fmt.Errorf("parse IP prefix '%s': %w", s.Prefix, err) + } + ms.Prefix = p + for _, ip := range s.SourceIPs { + addr, err := netip.ParseAddr(ip) + if err != nil { + return multinet.Config{}, fmt.Errorf("parse IP address '%s': %w", ip, err) + } + ms.SourceIPs = append(ms.SourceIPs, addr) + } + if len(ms.SourceIPs) == 0 { + return multinet.Config{}, errEmptySourceIPList + } + subnets = append(subnets, ms) + } + return multinet.Config{ + Subnets: subnets, + Balancer: multinet.BalancerType(c.Balancer), + Restrict: c.Restrict, + FallbackDelay: c.FallbackDelay, + Dialer: newDefaulDialer(), + }, nil +} + +func (c Config) equals(other Config) bool { + return c.Enabled == other.Enabled && + slices.EqualFunc(c.Subnets, other.Subnets, func(lhs, rhs Subnet) bool { + return lhs.Prefix == rhs.Prefix && slices.Equal(lhs.SourceIPs, rhs.SourceIPs) + }) && + c.Balancer == other.Balancer && + c.Restrict == other.Restrict && + c.FallbackDelay == other.FallbackDelay +} diff --git a/internal/net/dial_target.go b/internal/net/dial_target.go new file mode 100644 index 0000000000..6265f18606 --- /dev/null +++ b/internal/net/dial_target.go @@ -0,0 +1,54 @@ +// NOTE: code is taken from https://github.com/grpc/grpc-go/blob/v1.68.x/internal/transport/http_util.go + +/* + * + * Copyright 2014 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package net + +import ( + "net/url" + "strings" +) + +// parseDialTarget returns the network and address to pass to dialer. +func parseDialTarget(target string) (string, string) { + net := "tcp" + m1 := strings.Index(target, ":") + m2 := strings.Index(target, ":/") + // handle unix:addr which will fail with url.Parse + if m1 >= 0 && m2 < 0 { + if n := target[0:m1]; n == "unix" { + return n, target[m1+1:] + } + } + if m2 >= 0 { + t, err := url.Parse(target) + if err != nil { + return net, target + } + scheme := t.Scheme + addr := t.Path + if scheme == "unix" { + if addr == "" { + addr = t.Host + } + return scheme, addr + } + } + return net, target +} diff --git a/internal/net/dialer.go b/internal/net/dialer.go new file mode 100644 index 0000000000..4537490f66 --- /dev/null +++ b/internal/net/dialer.go @@ -0,0 +1,35 @@ +package net + +import ( + "context" + "net" + "syscall" + "time" + + "golang.org/x/sys/unix" +) + +type Dialer interface { + DialContext(ctx context.Context, network, address string) (net.Conn, error) +} + +func newDefaulDialer() net.Dialer { + // From `grpc.WithContextDialer` comment: + // + // Note: All supported releases of Go (as of December 2023) override the OS + // defaults for TCP keepalive time and interval to 15s. To enable TCP keepalive + // with OS defaults for keepalive time and interval, use a net.Dialer that sets + // the KeepAlive field to a negative value, and sets the SO_KEEPALIVE socket + // option to true from the Control field. For a concrete example of how to do + // this, see internal.NetDialerWithTCPKeepalive(). + // + // https://github.com/grpc/grpc-go/blob/830135e6c5a351abf75f0c9cfdf978e5df8daeba/dialoptions.go#L432 + return net.Dialer{ + KeepAlive: time.Duration(-1), + Control: func(_, _ string, c syscall.RawConn) error { + return c.Control(func(fd uintptr) { + unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1) + }) + }, + } +} diff --git a/internal/net/dialer_source.go b/internal/net/dialer_source.go new file mode 100644 index 0000000000..e6a142a082 --- /dev/null +++ b/internal/net/dialer_source.go @@ -0,0 +1,69 @@ +package net + +import ( + "context" + "net" + "sync" + + "git.frostfs.info/TrueCloudLab/multinet" +) + +type DialerSource struct { + guard sync.RWMutex + + c Config + + md multinet.Dialer +} + +func NewDialerSource(c Config) (*DialerSource, error) { + result := &DialerSource{} + if err := result.build(c); err != nil { + return nil, err + } + return result, nil +} + +func (s *DialerSource) build(c Config) error { + if c.Enabled { + mc, err := c.toMultinetConfig() + if err != nil { + return err + } + md, err := multinet.NewDialer(mc) + if err != nil { + return err + } + s.md = md + s.c = c + return nil + } + s.md = nil + s.c = c + return nil +} + +// GrpcContextDialer returns grpc.WithContextDialer func. +// Returns nil if multinet disabled. +func (s *DialerSource) GrpcContextDialer() func(context.Context, string) (net.Conn, error) { + s.guard.RLock() + defer s.guard.RUnlock() + + if s.c.Enabled { + return func(ctx context.Context, address string) (net.Conn, error) { + network, address := parseDialTarget(address) + return s.md.DialContext(ctx, network, address) + } + } + return nil +} + +func (s *DialerSource) Update(c Config) error { + s.guard.Lock() + defer s.guard.Unlock() + + if s.c.equals(c) { + return nil + } + return s.build(c) +} From 6c96cc2af6eb9cb64e747c5b758fbec4d90c7287 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Oct 2024 11:11:44 +0300 Subject: [PATCH 0921/1413] [#1422] node: Use dialer source for SDK cache Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 + internal/net/dialer.go | 6 +++++- pkg/network/cache/client.go | 2 ++ pkg/network/cache/multi.go | 25 ++++++++++++++----------- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index dc1bad485f..d44597857e 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -773,6 +773,7 @@ func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkSt Key: &key.PrivateKey, AllowExternal: apiclientconfig.AllowExternal(appCfg), ReconnectTimeout: apiclientconfig.ReconnectTimeout(appCfg), + DialerSource: ds, } return shared{ diff --git a/internal/net/dialer.go b/internal/net/dialer.go index 4537490f66..daf0f815fa 100644 --- a/internal/net/dialer.go +++ b/internal/net/dialer.go @@ -13,6 +13,10 @@ type Dialer interface { DialContext(ctx context.Context, network, address string) (net.Conn, error) } +func DialContextTCP(ctx context.Context, address string, d Dialer) (net.Conn, error) { + return d.DialContext(ctx, "tcp", address) +} + func newDefaulDialer() net.Dialer { // From `grpc.WithContextDialer` comment: // @@ -28,7 +32,7 @@ func newDefaulDialer() net.Dialer { KeepAlive: time.Duration(-1), Control: func(_, _ string, c syscall.RawConn) error { return c.Control(func(fd uintptr) { - unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1) + _ = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1) }) }, } diff --git a/pkg/network/cache/client.go b/pkg/network/cache/client.go index 371d3c76f3..63ae0bfdbf 100644 --- a/pkg/network/cache/client.go +++ b/pkg/network/cache/client.go @@ -5,6 +5,7 @@ import ( "sync" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" ) @@ -25,6 +26,7 @@ type ( Key *ecdsa.PrivateKey ResponseCallback func(client.ResponseMetaInfo) error AllowExternal bool + DialerSource *net.DialerSource } ) diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index b83cbb217b..e936ead651 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -60,18 +60,21 @@ func (x *multiClient) createForAddress(ctx context.Context, addr network.Address prmInit.Key = *x.opts.Key } + grpcOpts := []grpc.DialOption{ + grpc.WithChainUnaryInterceptor( + metrics.NewUnaryClientInterceptor(), + tracing.NewUnaryClientInteceptor(), + ), + grpc.WithChainStreamInterceptor( + metrics.NewStreamClientInterceptor(), + tracing.NewStreamClientInterceptor(), + ), + grpc.WithContextDialer(x.opts.DialerSource.GrpcContextDialer()), + } + prmDial := client.PrmDial{ - Endpoint: addr.URIAddr(), - GRPCDialOptions: []grpc.DialOption{ - grpc.WithChainUnaryInterceptor( - metrics.NewUnaryClientInterceptor(), - tracing.NewUnaryClientInteceptor(), - ), - grpc.WithChainStreamInterceptor( - metrics.NewStreamClientInterceptor(), - tracing.NewStreamClientInterceptor(), - ), - }, + Endpoint: addr.URIAddr(), + GRPCDialOptions: grpcOpts, } if x.opts.DialTimeout > 0 { prmDial.DialTimeout = x.opts.DialTimeout From e314f328c4806bf1b34b6e3c31abdc4afdfaaac4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Oct 2024 11:18:24 +0300 Subject: [PATCH 0922/1413] [#1422] tree: Use dialer source for tree service connections Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/tree.go | 1 + pkg/services/tree/cache.go | 6 +++++- pkg/services/tree/options.go | 8 ++++++++ pkg/services/tree/service.go | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index 192f084713..f188e2fbcf 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -67,6 +67,7 @@ func initTreeService(c *cfg) { tree.WithAPELocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage()), tree.WithAPEMorphRuleStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage()), tree.WithNetmapState(c.cfgNetmap.state), + tree.WithDialerSource(c.dialerSource), ) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index 38501b8520..e490cb8559 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -8,6 +8,7 @@ import ( "sync" "time" + internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" @@ -21,6 +22,7 @@ type clientCache struct { sync.Mutex simplelru.LRU[string, cacheItem] key *ecdsa.PrivateKey + ds *internalNet.DialerSource } type cacheItem struct { @@ -36,7 +38,7 @@ const ( var errRecentlyFailed = errors.New("client has recently failed") -func (c *clientCache) init(pk *ecdsa.PrivateKey) { +func (c *clientCache) init(pk *ecdsa.PrivateKey, ds *internalNet.DialerSource) { l, _ := simplelru.NewLRU(defaultClientCacheSize, func(_ string, value cacheItem) { if conn := value.cc; conn != nil { _ = conn.Close() @@ -44,6 +46,7 @@ func (c *clientCache) init(pk *ecdsa.PrivateKey) { }) c.LRU = *l c.key = pk + c.ds = ds } func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceClient, error) { @@ -99,6 +102,7 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* metrics.NewStreamClientInterceptor(), tracing.NewStreamClientInterceptor(), ), + grpc.WithContextDialer(c.ds.GrpcContextDialer()), } if !netAddr.IsTLSEnabled() { diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index 1db5607f66..1633ae5579 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -4,6 +4,7 @@ import ( "crypto/ecdsa" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" @@ -45,6 +46,7 @@ type cfg struct { morphChainStorage policyengine.MorphRuleChainStorageReader metrics MetricsRegister + ds *net.DialerSource } // Option represents configuration option for a tree service. @@ -161,3 +163,9 @@ func WithNetmapState(state netmap.State) Option { c.state = state } } + +func WithDialerSource(ds *net.DialerSource) Option { + return func(c *cfg) { + c.ds = ds + } +} diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 60bb1a6ad4..2cb2af294d 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -65,7 +65,7 @@ func New(opts ...Option) *Service { s.log = &logger.Logger{Logger: zap.NewNop()} } - s.cache.init(s.key) + s.cache.init(s.key, s.ds) s.closeCh = make(chan struct{}) s.replicateCh = make(chan movePair, s.replicatorChannelCapacity) s.replicateLocalCh = make(chan applyOp) From 5b653aa65fd65759ee733fd552d17870c6660b13 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Oct 2024 11:34:36 +0300 Subject: [PATCH 0923/1413] [#1422] morph: Drop single client as not used Signed-off-by: Dmitrii Stepanov --- pkg/morph/client/constructor.go | 59 +++++++++------------------------ 1 file changed, 15 insertions(+), 44 deletions(-) diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index 78cb3e82f5..60b5b4b971 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -41,8 +41,6 @@ type cfg struct { endpoints []Endpoint - singleCli *rpcclient.WSClient // neo-go client for single client mode - inactiveModeCb Callback switchInterval time.Duration @@ -124,40 +122,24 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er var err error var act *actor.Actor - if cfg.singleCli != nil { - // return client in single RPC node mode that uses - // predefined WS client - // - // in case of the closing web socket connection: - // if extra endpoints were provided via options, - // they will be used in switch process, otherwise - // inactive mode will be enabled - cli.client = cfg.singleCli - - act, err = newActor(cfg.singleCli, acc, *cfg) + var endpoint Endpoint + for cli.endpoints.curr, endpoint = range cli.endpoints.list { + cli.client, act, err = cli.newCli(ctx, endpoint) if err != nil { - return nil, fmt.Errorf("could not create RPC actor: %w", err) - } - } else { - var endpoint Endpoint - for cli.endpoints.curr, endpoint = range cli.endpoints.list { - cli.client, act, err = cli.newCli(ctx, endpoint) - if err != nil { - cli.logger.Warn(logs.FrostFSIRCouldntCreateRPCClientForEndpoint, - zap.Error(err), zap.String("endpoint", endpoint.Address)) - } else { - cli.logger.Info(logs.FrostFSIRCreatedRPCClientForEndpoint, - zap.String("endpoint", endpoint.Address)) - if cli.endpoints.curr > 0 && cli.cfg.switchInterval != 0 { - cli.switchIsActive.Store(true) - go cli.switchToMostPrioritized(ctx) - } - break + cli.logger.Warn(logs.FrostFSIRCouldntCreateRPCClientForEndpoint, + zap.Error(err), zap.String("endpoint", endpoint.Address)) + } else { + cli.logger.Info(logs.FrostFSIRCreatedRPCClientForEndpoint, + zap.String("endpoint", endpoint.Address)) + if cli.endpoints.curr > 0 && cli.cfg.switchInterval != 0 { + cli.switchIsActive.Store(true) + go cli.switchToMostPrioritized(ctx) } + break } - if cli.client == nil { - return nil, ErrNoHealthyEndpoint - } + } + if cli.client == nil { + return nil, ErrNoHealthyEndpoint } cli.setActor(act) @@ -285,17 +267,6 @@ func WithEndpoints(endpoints ...Endpoint) Option { } } -// WithSingleClient returns a client constructor option -// that specifies single neo-go client and forces Client -// to use it for requests. -// -// Passed client must already be initialized. -func WithSingleClient(cli *rpcclient.WSClient) Option { - return func(c *cfg) { - c.singleCli = cli - } -} - // WithConnLostCallback return a client constructor option // that specifies a callback that is called when Client // unsuccessfully tried to connect to all the specified From 67798bb50e57ecf77a6797a3a02751f54a2e02ee Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Oct 2024 11:48:16 +0300 Subject: [PATCH 0924/1413] [#1422] mod: Bump neoneo-go version Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a84d3122a1..aefe2889ab 100644 --- a/go.mod +++ b/go.mod @@ -133,4 +133,4 @@ require ( rsc.io/tmplfunc v0.0.3 // indirect ) -replace github.com/nspcc-dev/neo-go => git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 +replace github.com/nspcc-dev/neo-go => git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07 diff --git a/go.sum b/go.sum index 43d53aa404..4d44079d4a 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8l git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972/go.mod h1:2hM42MBrlhvN6XToaW6OWNk5ZLcu1FhaukGgxtfpDDI= -git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928 h1:LK3mCkNZkY48eBA9jnk1N0eQZLsZhOG+XYw4EBoKUjM= -git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20240726093631-5481339d6928/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= +git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07 h1:gPaqGsk6gSWQyNVjaStydfUz6Z/loHc9XyvGrJ5qSPY= +git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 h1:vgbfkcnIexZUm3vREBBSa/Gv1Whjd1SFCUd0A+IaGPQ= git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= From fbdfd503e4c2475b01728dbfc21c269a443c93f2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Oct 2024 11:48:59 +0300 Subject: [PATCH 0925/1413] [#1422] morph: Add dialer source support Signed-off-by: Dmitrii Stepanov --- internal/net/dialer_source.go | 14 ++++++++++++++ pkg/morph/client/constructor.go | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/internal/net/dialer_source.go b/internal/net/dialer_source.go index e6a142a082..3d94dedc74 100644 --- a/internal/net/dialer_source.go +++ b/internal/net/dialer_source.go @@ -58,6 +58,20 @@ func (s *DialerSource) GrpcContextDialer() func(context.Context, string) (net.Co return nil } +// NetContextDialer returns net.DialContext dial function. +// Returns nil if multinet disabled. +func (s *DialerSource) NetContextDialer() func(context.Context, string, string) (net.Conn, error) { + s.guard.RLock() + defer s.guard.RUnlock() + + if s.c.Enabled { + return func(ctx context.Context, network, address string) (net.Conn, error) { + return s.md.DialContext(ctx, network, address) + } + } + return nil +} + func (s *DialerSource) Update(c Config) error { s.guard.Lock() defer s.guard.Unlock() diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index 60b5b4b971..2313222f04 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -4,10 +4,12 @@ import ( "context" "errors" "fmt" + "net" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" + internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" lru "github.com/hashicorp/golang-lru/v2" @@ -46,6 +48,8 @@ type cfg struct { switchInterval time.Duration morphCacheMetrics metrics.MorphCacheMetrics + + dialerSource *internalNet.DialerSource } const ( @@ -153,10 +157,15 @@ func (c *Client) newCli(ctx context.Context, endpoint Endpoint) (*rpcclient.WSCl if err != nil { return nil, nil, fmt.Errorf("read mtls certificates: %w", err) } + var netDialContext func(ctx context.Context, network, addr string) (net.Conn, error) + if c.cfg.dialerSource != nil { // TODO fix after IR + netDialContext = c.cfg.dialerSource.NetContextDialer() + } cli, err := rpcclient.NewWS(ctx, endpoint.Address, rpcclient.WSOptions{ Options: rpcclient.Options{ DialTimeout: c.cfg.dialTimeout, TLSClientConfig: cfg, + NetDialContext: netDialContext, }, }) if err != nil { @@ -291,3 +300,9 @@ func WithMorphCacheMetrics(morphCacheMetrics metrics.MorphCacheMetrics) Option { c.morphCacheMetrics = morphCacheMetrics } } + +func WithDialerSource(ds *internalNet.DialerSource) Option { + return func(c *cfg) { + c.dialerSource = ds + } +} From f7caef355bee787ac34f2cd44a4f9c4eb32177a3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Oct 2024 11:49:23 +0300 Subject: [PATCH 0926/1413] [#1422] node: Use dialer source for morph Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/morph.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 1bfcb8ac9a..f93f233ebc 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -48,6 +48,7 @@ func initMorphComponents(ctx context.Context, c *cfg) { }), client.WithSwitchInterval(morphconfig.SwitchInterval(c.appCfg)), client.WithMorphCacheMetrics(c.metricsCollector.MorphCacheMetrics()), + client.WithDialerSource(c.dialerSource), ) if err != nil { c.log.Info(logs.FrostFSNodeFailedToCreateNeoRPCClient, From ef38420623c64e12aa00b7d4072bdf6b08dec247 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 14 Oct 2024 13:51:21 +0300 Subject: [PATCH 0927/1413] [#1422] ir: Add dialer source Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-ir/defaults.go | 10 ++++++++++ pkg/innerring/innerring.go | 29 +++++++++++++++++++++++++++++ pkg/morph/client/constructor.go | 7 +------ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-ir/defaults.go b/cmd/frostfs-ir/defaults.go index 899918d226..9b775252f7 100644 --- a/cmd/frostfs-ir/defaults.go +++ b/cmd/frostfs-ir/defaults.go @@ -48,6 +48,8 @@ func defaultConfiguration(cfg *viper.Viper) { cfg.SetDefault("node.kludge_compatibility_mode", false) cfg.SetDefault("audit.enabled", false) + + setMultinetDefaults(cfg) } func setControlDefaults(cfg *viper.Viper) { @@ -131,3 +133,11 @@ func setMorphDefaults(cfg *viper.Viper) { cfg.SetDefault("morph.validators", []string{}) cfg.SetDefault("morph.switch_interval", 2*time.Minute) } + +func setMultinetDefaults(cfg *viper.Viper) { + cfg.SetDefault("multinet.enabled", false) + cfg.SetDefault("multinet.balancer", "") + cfg.SetDefault("multinet.restrict", false) + cfg.SetDefault("multinet.fallback_delay", "0s") + cfg.SetDefault("multinet.subnets", "") +} diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 53a07e36cd..a4a52edecd 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" + internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" @@ -486,6 +487,12 @@ func createClient(ctx context.Context, p *chainParams, errChan chan<- error) (*c return nil, fmt.Errorf("%s chain client endpoints not provided", p.name) } + nc := parseMultinetConfig(p.cfg) + ds, err := internalNet.NewDialerSource(nc) + if err != nil { + return nil, fmt.Errorf("dialer source: %w", err) + } + return client.New( ctx, p.key, @@ -498,6 +505,7 @@ func createClient(ctx context.Context, p *chainParams, errChan chan<- error) (*c }), client.WithSwitchInterval(p.cfg.GetDuration(p.name+".switch_interval")), client.WithMorphCacheMetrics(p.morphCacheMetric), + client.WithDialerSource(ds), ) } @@ -542,6 +550,27 @@ func parseWalletAddressesFromStrings(wallets []string) ([]util.Uint160, error) { return extraWallets, nil } +func parseMultinetConfig(cfg *viper.Viper) internalNet.Config { + nc := internalNet.Config{ + Enabled: cfg.GetBool("multinet.enabled"), + Balancer: cfg.GetString("multinet.balancer"), + Restrict: cfg.GetBool("multinet.restrict"), + FallbackDelay: cfg.GetDuration("multinet.fallback_delay"), + } + for i := 0; ; i++ { + mask := cfg.GetString(fmt.Sprintf("multinet.subnets.%d.mask", i)) + if mask == "" { + break + } + sourceIPs := cfg.GetStringSlice(fmt.Sprintf("multinet.subnets.%d.source_ips", i)) + nc.Subnets = append(nc.Subnets, internalNet.Subnet{ + Prefix: mask, + SourceIPs: sourceIPs, + }) + } + return nc +} + func (s *Server) initConfigFromBlockchain() error { // get current epoch epoch, err := s.netmapClient.Epoch() diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index 2313222f04..a8efa76e72 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "net" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -157,15 +156,11 @@ func (c *Client) newCli(ctx context.Context, endpoint Endpoint) (*rpcclient.WSCl if err != nil { return nil, nil, fmt.Errorf("read mtls certificates: %w", err) } - var netDialContext func(ctx context.Context, network, addr string) (net.Conn, error) - if c.cfg.dialerSource != nil { // TODO fix after IR - netDialContext = c.cfg.dialerSource.NetContextDialer() - } cli, err := rpcclient.NewWS(ctx, endpoint.Address, rpcclient.WSOptions{ Options: rpcclient.Options{ DialTimeout: c.cfg.dialTimeout, TLSClientConfig: cfg, - NetDialContext: netDialContext, + NetDialContext: c.cfg.dialerSource.NetContextDialer(), }, }) if err != nil { From 2d064d0bd87c9627aaeacb9c160cfe2bb029c56a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 14 Oct 2024 14:22:27 +0300 Subject: [PATCH 0928/1413] [#1422] morph: Resolve funlen linter Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/morph.go | 84 ++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index f93f233ebc..197e503712 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -29,6 +29,50 @@ const ( ) func initMorphComponents(ctx context.Context, c *cfg) { + initMorphClient(ctx, c) + + lookupScriptHashesInNNS(c) // smart contract auto negotiation + + if c.cfgMorph.notaryEnabled { + err := c.cfgMorph.client.EnableNotarySupport( + client.WithProxyContract( + c.cfgMorph.proxyScriptHash, + ), + ) + fatalOnErr(err) + } + + c.log.Info(logs.FrostFSNodeNotarySupport, + zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled), + ) + + wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0, nmClient.TryNotary()) + fatalOnErr(err) + + var netmapSource netmap.Source + + c.cfgMorph.containerCacheSize = morphconfig.ContainerCacheSize(c.appCfg) + c.cfgMorph.cacheTTL = morphconfig.CacheTTL(c.appCfg) + + if c.cfgMorph.cacheTTL == 0 { + msPerBlock, err := c.cfgMorph.client.MsPerBlock() + fatalOnErr(err) + c.cfgMorph.cacheTTL = time.Duration(msPerBlock) * time.Millisecond + c.log.Debug(logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL)) + } + + if c.cfgMorph.cacheTTL < 0 { + netmapSource = wrap + } else { + // use RPC node as source of netmap (with caching) + netmapSource = newCachedNetmapStorage(c.cfgNetmap.state, wrap) + } + + c.netMapSource = netmapSource + c.cfgNetmap.wrapper = wrap +} + +func initMorphClient(ctx context.Context, c *cfg) { addresses := morphconfig.RPCEndpoint(c.appCfg) // Morph client stable-sorts endpoints by priority. Shuffle here to randomize @@ -70,46 +114,6 @@ func initMorphComponents(ctx context.Context, c *cfg) { c.cfgMorph.client = cli c.cfgMorph.notaryEnabled = cli.ProbeNotary() - - lookupScriptHashesInNNS(c) // smart contract auto negotiation - - if c.cfgMorph.notaryEnabled { - err = c.cfgMorph.client.EnableNotarySupport( - client.WithProxyContract( - c.cfgMorph.proxyScriptHash, - ), - ) - fatalOnErr(err) - } - - c.log.Info(logs.FrostFSNodeNotarySupport, - zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled), - ) - - wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0, nmClient.TryNotary()) - fatalOnErr(err) - - var netmapSource netmap.Source - - c.cfgMorph.containerCacheSize = morphconfig.ContainerCacheSize(c.appCfg) - c.cfgMorph.cacheTTL = morphconfig.CacheTTL(c.appCfg) - - if c.cfgMorph.cacheTTL == 0 { - msPerBlock, err := c.cfgMorph.client.MsPerBlock() - fatalOnErr(err) - c.cfgMorph.cacheTTL = time.Duration(msPerBlock) * time.Millisecond - c.log.Debug(logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL)) - } - - if c.cfgMorph.cacheTTL < 0 { - netmapSource = wrap - } else { - // use RPC node as source of netmap (with caching) - netmapSource = newCachedNetmapStorage(c.cfgNetmap.state, wrap) - } - - c.netMapSource = netmapSource - c.cfgNetmap.wrapper = wrap } func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { From c0a2f20eee5e6279e71cfc3d83f8bb89d0a2ef75 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 15 Oct 2024 14:46:00 +0300 Subject: [PATCH 0929/1413] [#1422] multinet: Add metrics Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 11 +++++++---- internal/metrics/consts.go | 2 ++ internal/metrics/innerring.go | 6 ++++++ internal/metrics/multinet.go | 35 +++++++++++++++++++++++++++++++++ internal/metrics/node.go | 6 ++++++ internal/net/config.go | 3 +++ internal/net/event_handler.go | 29 +++++++++++++++++++++++++++ pkg/innerring/initialization.go | 1 + pkg/innerring/innerring.go | 6 ++++-- 9 files changed, 93 insertions(+), 6 deletions(-) create mode 100644 internal/metrics/multinet.go create mode 100644 internal/net/event_handler.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index d44597857e..9d2b772106 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -764,7 +764,9 @@ func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkSt persistate, err := state.NewPersistentStorage(nodeconfig.PersistentState(appCfg).Path()) fatalOnErr(err) - ds, err := internalNet.NewDialerSource(internalNetConfig(appCfg)) + nodeMetrics := metrics.NewNodeMetrics() + + ds, err := internalNet.NewDialerSource(internalNetConfig(appCfg, nodeMetrics.MultinetMetrics())) fatalOnErr(err) cacheOpts := cache.ClientCacheOpts{ @@ -785,17 +787,18 @@ func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkSt bgClientCache: cache.NewSDKClientCache(cacheOpts), putClientCache: cache.NewSDKClientCache(cacheOpts), persistate: persistate, - metricsCollector: metrics.NewNodeMetrics(), + metricsCollector: nodeMetrics, dialerSource: ds, } } -func internalNetConfig(appCfg *config.Config) internalNet.Config { +func internalNetConfig(appCfg *config.Config, m metrics.MultinetMetrics) internalNet.Config { result := internalNet.Config{ Enabled: multinet.Enabled(appCfg), Balancer: multinet.Balancer(appCfg), Restrict: multinet.Restrict(appCfg), FallbackDelay: multinet.FallbackDelay(appCfg), + Metrics: m, } sn := multinet.Subnets(appCfg) for _, s := range sn { @@ -1362,7 +1365,7 @@ func (c *cfg) reloadConfig(ctx context.Context) { } } - if err := c.dialerSource.Update(internalNetConfig(c.appCfg)); err != nil { + if err := c.dialerSource.Update(internalNetConfig(c.appCfg, c.metricsCollector.MultinetMetrics())); err != nil { c.log.Error(logs.FailedToUpdateMultinetConfiguration, zap.Error(err)) return } diff --git a/internal/metrics/consts.go b/internal/metrics/consts.go index 3aa51c0f01..cb165de69c 100644 --- a/internal/metrics/consts.go +++ b/internal/metrics/consts.go @@ -22,6 +22,7 @@ const ( grpcServerSubsystem = "grpc_server" policerSubsystem = "policer" commonCacheSubsystem = "common_cache" + multinetSubsystem = "multinet" successLabel = "success" shardIDLabel = "shard_id" @@ -41,6 +42,7 @@ const ( endpointLabel = "endpoint" hitLabel = "hit" cacheLabel = "cache" + sourceIPLabel = "source_ip" readWriteMode = "READ_WRITE" readOnlyMode = "READ_ONLY" diff --git a/internal/metrics/innerring.go b/internal/metrics/innerring.go index f3f529d05b..d0cb8131ff 100644 --- a/internal/metrics/innerring.go +++ b/internal/metrics/innerring.go @@ -17,6 +17,7 @@ type InnerRingServiceMetrics struct { eventDuration *prometheus.HistogramVec morphCacheMetrics *morphCacheMetrics logMetrics logger.LogMetrics + multinet *multinetMetrics // nolint: unused appInfo *ApplicationInfo } @@ -51,6 +52,7 @@ func NewInnerRingMetrics() *InnerRingServiceMetrics { morphCacheMetrics: newMorphCacheMetrics(innerRingNamespace), appInfo: NewApplicationInfo(misc.Version), logMetrics: logger.NewLogMetrics(innerRingNamespace), + multinet: newMultinetMetrics(innerRingNamespace), } } @@ -78,3 +80,7 @@ func (m *InnerRingServiceMetrics) MorphCacheMetrics() MorphCacheMetrics { func (m *InnerRingServiceMetrics) LogMetrics() logger.LogMetrics { return m.logMetrics } + +func (m *InnerRingServiceMetrics) Multinet() MultinetMetrics { + return m.multinet +} diff --git a/internal/metrics/multinet.go b/internal/metrics/multinet.go new file mode 100644 index 0000000000..6b1f99d46a --- /dev/null +++ b/internal/metrics/multinet.go @@ -0,0 +1,35 @@ +package metrics + +import ( + "strconv" + + "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +type multinetMetrics struct { + dials *prometheus.GaugeVec +} + +type MultinetMetrics interface { + Dial(sourceIP string, success bool) +} + +func newMultinetMetrics(ns string) *multinetMetrics { + return &multinetMetrics{ + dials: metrics.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: ns, + Subsystem: multinetSubsystem, + Name: "dial_count", + Help: "Dials count performed by multinet", + }, []string{sourceIPLabel, successLabel}), + } +} + +func (m *multinetMetrics) Dial(sourceIP string, success bool) { + m.dials.With(prometheus.Labels{ + sourceIPLabel: sourceIP, + successLabel: strconv.FormatBool(success), + }).Inc() +} diff --git a/internal/metrics/node.go b/internal/metrics/node.go index 7113878757..4ea3c7c24d 100644 --- a/internal/metrics/node.go +++ b/internal/metrics/node.go @@ -25,6 +25,7 @@ type NodeMetrics struct { morphClient *morphClientMetrics morphCache *morphCacheMetrics log logger.LogMetrics + multinet *multinetMetrics // nolint: unused appInfo *ApplicationInfo } @@ -53,6 +54,7 @@ func NewNodeMetrics() *NodeMetrics { morphCache: newMorphCacheMetrics(namespace), log: logger.NewLogMetrics(namespace), appInfo: NewApplicationInfo(misc.Version), + multinet: newMultinetMetrics(namespace), } } @@ -120,3 +122,7 @@ func (m *NodeMetrics) MorphCacheMetrics() MorphCacheMetrics { func (m *NodeMetrics) LogMetrics() logger.LogMetrics { return m.log } + +func (m *NodeMetrics) MultinetMetrics() MultinetMetrics { + return m.multinet +} diff --git a/internal/net/config.go b/internal/net/config.go index 10450db23c..b84ac3b350 100644 --- a/internal/net/config.go +++ b/internal/net/config.go @@ -7,6 +7,7 @@ import ( "slices" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/multinet" ) @@ -23,6 +24,7 @@ type Config struct { Balancer string Restrict bool FallbackDelay time.Duration + Metrics metrics.MultinetMetrics } func (c Config) toMultinetConfig() (multinet.Config, error) { @@ -52,6 +54,7 @@ func (c Config) toMultinetConfig() (multinet.Config, error) { Restrict: c.Restrict, FallbackDelay: c.FallbackDelay, Dialer: newDefaulDialer(), + EventHandler: newEventHandler(c.Metrics), }, nil } diff --git a/internal/net/event_handler.go b/internal/net/event_handler.go new file mode 100644 index 0000000000..024e5cf7ca --- /dev/null +++ b/internal/net/event_handler.go @@ -0,0 +1,29 @@ +package net + +import ( + "net" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" + "git.frostfs.info/TrueCloudLab/multinet" +) + +var _ multinet.EventHandler = (*metricsEventHandler)(nil) + +type metricsEventHandler struct { + m metrics.MultinetMetrics +} + +func (m *metricsEventHandler) DialPerformed(sourceIP net.Addr, _ string, _ string, err error) { + sourceIPString := "undefined" + if sourceIP != nil { + sourceIPString = sourceIP.Network() + "://" + sourceIP.String() + } + m.m.Dial(sourceIPString, err == nil) +} + +func newEventHandler(m metrics.MultinetMetrics) multinet.EventHandler { + if m == nil { + return nil + } + return &metricsEventHandler{m: m} +} diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index c4aaeda560..cb0654b6e5 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -463,6 +463,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<- name: morphPrefix, from: fromSideChainBlock, morphCacheMetric: s.irMetrics.MorphCacheMetrics(), + multinetMetrics: s.irMetrics.Multinet(), } // create morph client diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index a4a52edecd..b943126450 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -117,6 +117,7 @@ type ( sgn *transaction.Signer from uint32 // block height morphCacheMetric metrics.MorphCacheMetrics + multinetMetrics metrics.MultinetMetrics } ) @@ -487,7 +488,7 @@ func createClient(ctx context.Context, p *chainParams, errChan chan<- error) (*c return nil, fmt.Errorf("%s chain client endpoints not provided", p.name) } - nc := parseMultinetConfig(p.cfg) + nc := parseMultinetConfig(p.cfg, p.multinetMetrics) ds, err := internalNet.NewDialerSource(nc) if err != nil { return nil, fmt.Errorf("dialer source: %w", err) @@ -550,12 +551,13 @@ func parseWalletAddressesFromStrings(wallets []string) ([]util.Uint160, error) { return extraWallets, nil } -func parseMultinetConfig(cfg *viper.Viper) internalNet.Config { +func parseMultinetConfig(cfg *viper.Viper, m metrics.MultinetMetrics) internalNet.Config { nc := internalNet.Config{ Enabled: cfg.GetBool("multinet.enabled"), Balancer: cfg.GetString("multinet.balancer"), Restrict: cfg.GetBool("multinet.restrict"), FallbackDelay: cfg.GetDuration("multinet.fallback_delay"), + Metrics: m, } for i := 0; ; i++ { mask := cfg.GetString(fmt.Sprintf("multinet.subnets.%d.mask", i)) From 5afea62ec0c29b8b3422412e4cd8a5452785e6fd Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 18 Oct 2024 15:15:19 +0300 Subject: [PATCH 0930/1413] [#1438] debian: Remove package scripts Signed-off-by: Evgenii Stratonikov --- Makefile | 21 +------------ debian/changelog | 5 --- debian/clean | 2 -- debian/control | 39 ----------------------- debian/copyright | 23 -------------- debian/frostfs-cli.docs | 4 --- debian/frostfs-cli.install | 3 -- debian/frostfs-cli.manpages | 1 - debian/frostfs-ir.dirs | 2 -- debian/frostfs-ir.docs | 3 -- debian/frostfs-ir.install | 1 - debian/frostfs-ir.postinst | 51 ------------------------------ debian/frostfs-ir.postrm | 40 ------------------------ debian/frostfs-ir.preinst | 34 -------------------- debian/frostfs-ir.prerm | 37 ---------------------- debian/frostfs-ir.service | 17 ---------- debian/frostfs-storage.dirs | 3 -- debian/frostfs-storage.docs | 4 --- debian/frostfs-storage.install | 1 - debian/frostfs-storage.postinst | 55 --------------------------------- debian/frostfs-storage.postrm | 40 ------------------------ debian/frostfs-storage.preinst | 34 -------------------- debian/frostfs-storage.prerm | 37 ---------------------- debian/frostfs-storage.service | 17 ---------- debian/rules | 40 ------------------------ debian/source/format | 1 - docs/building-deb-package.md | 46 --------------------------- docs/release-instruction.md | 5 --- 28 files changed, 1 insertion(+), 565 deletions(-) delete mode 100644 debian/changelog delete mode 100644 debian/clean delete mode 100644 debian/control delete mode 100644 debian/copyright delete mode 100644 debian/frostfs-cli.docs delete mode 100644 debian/frostfs-cli.install delete mode 100644 debian/frostfs-cli.manpages delete mode 100644 debian/frostfs-ir.dirs delete mode 100644 debian/frostfs-ir.docs delete mode 100644 debian/frostfs-ir.install delete mode 100755 debian/frostfs-ir.postinst delete mode 100755 debian/frostfs-ir.postrm delete mode 100755 debian/frostfs-ir.preinst delete mode 100755 debian/frostfs-ir.prerm delete mode 100644 debian/frostfs-ir.service delete mode 100644 debian/frostfs-storage.dirs delete mode 100644 debian/frostfs-storage.docs delete mode 100644 debian/frostfs-storage.install delete mode 100755 debian/frostfs-storage.postinst delete mode 100755 debian/frostfs-storage.postrm delete mode 100755 debian/frostfs-storage.preinst delete mode 100755 debian/frostfs-storage.prerm delete mode 100644 debian/frostfs-storage.service delete mode 100755 debian/rules delete mode 100644 debian/source/format delete mode 100644 docs/building-deb-package.md diff --git a/Makefile b/Makefile index 2f29ac19c0..d92844bb50 100755 --- a/Makefile +++ b/Makefile @@ -27,12 +27,6 @@ DIRS = $(BIN) $(RELEASE) CMDS = $(notdir $(basename $(wildcard cmd/frostfs-*))) BINS = $(addprefix $(BIN)/, $(CMDS)) -# .deb package versioning -OS_RELEASE = $(shell lsb_release -cs) -PKG_VERSION ?= $(shell echo $(VERSION) | sed "s/^v//" | \ - sed -E "s/(.*)-(g[a-fA-F0-9]{6,8})(.*)/\1\3~\2/" | \ - sed "s/-/~/")-${OS_RELEASE} - OUTPUT_LINT_DIR ?= $(abspath $(BIN))/linters LINT_DIR = $(OUTPUT_LINT_DIR)/golangci-lint-$(LINT_VERSION)-v$(TRUECLOUDLAB_LINT_VERSION) TMP_DIR := .cache @@ -58,7 +52,7 @@ LOCODE_DB_PATH=$(abspath ./.cache/locode_db) LOCODE_DB_VERSION=v0.4.0 .PHONY: help all images dep clean fmts fumpt imports test lint docker/lint - prepare-release debpackage pre-commit unpre-commit + prepare-release pre-commit unpre-commit # To build a specific binary, use it's name prefix with bin/ as a target # For example `make bin/frostfs-node` will build only storage node binary @@ -263,19 +257,6 @@ clean: rm -rf $(BIN) rm -rf $(RELEASE) -# Package for Debian -debpackage: - dch -b --package frostfs-node \ - --controlmaint \ - --newversion $(PKG_VERSION) \ - --distribution $(OS_RELEASE) \ - "Please see CHANGELOG.md for code changes for $(VERSION)" - dpkg-buildpackage --no-sign -b - -# Cleanup deb package build directories -debclean: - dh clean - # Download locode database locode-download: mkdir -p $(TMP_DIR) diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 47328c4190..0000000000 --- a/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -frostfs-node (0.0.1) stable; urgency=medium - - * Initial package build - - -- TrueCloudLab Tue, 25 Oct 2022 21:10:49 +0300 diff --git a/debian/clean b/debian/clean deleted file mode 100644 index 44dc05e0af..0000000000 --- a/debian/clean +++ /dev/null @@ -1,2 +0,0 @@ -man/ -debian/*.bash-completion diff --git a/debian/control b/debian/control deleted file mode 100644 index f3f214bcaf..0000000000 --- a/debian/control +++ /dev/null @@ -1,39 +0,0 @@ -Source: frostfs-node -Section: misc -Priority: optional -Maintainer: TrueCloudLab -Build-Depends: debhelper-compat (= 13), dh-sequence-bash-completion, devscripts -Standards-Version: 4.5.1 -Homepage: https://fs.neo.org/ -Vcs-Git: https://git.frostfs.info/TrueCloudLab/frostfs-node.git -Vcs-Browser: https://git.frostfs.info/TrueCloudLab/frostfs-node - -Package: frostfs-storage -Architecture: any -Depends: ${misc:Depends} -Description: FrostFS Storage node - FrostFS is a decentralized distributed object storage integrated with the NEO - Blockchain. FrostFS Nodes are organized in a peer-to-peer network that takes care - of storing and distributing user's data. Any Neo user may participate in the - network and get paid for providing storage resources to other users or store - their data in FrostFS and pay a competitive price for it. - -Package: frostfs-ir -Architecture: any -Depends: ${misc:Depends}, frostfs-locode-db -Description: FrostFS InnerRing node - FrostFS is a decentralized distributed object storage integrated with the NEO - Blockchain. FrostFS Nodes are organized in a peer-to-peer network that takes care - of storing and distributing user's data. Any Neo user may participate in the - network and get paid for providing storage resources to other users or store - their data in FrostFS and pay a competitive price for it. - -Package: frostfs-cli -Architecture: any -Depends: ${misc:Depends} -Description: CLI tools for FrostFS - FrostFS is a decentralized distributed object storage integrated with the NEO - Blockchain. FrostFS Nodes are organized in a peer-to-peer network that takes care - of storing and distributing user's data. Any Neo user may participate in the - network and get paid for providing storage resources to other users or store - their data in FrostFS and pay a competitive price for it. diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index 61dab665d1..0000000000 --- a/debian/copyright +++ /dev/null @@ -1,23 +0,0 @@ -Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: frostfs-node -Upstream-Contact: tech@frostfs.info -Source: https://git.frostfs.info/TrueCloudLab/frostfs-node - -Files: * -Copyright: 2022-2023 TrueCloudLab (@TrueCloudLab), contributors of FrostFS project - 2018-2022 NeoSPCC (@nspcc-dev), contributors of NeoFS project - (https://git.frostfs.info/TrueCloudLab/frostfs-node/src/branch/master/CREDITS.md) - -License: GPL-3 - This program is free software: you can redistribute it and/or modify it - under the terms of the GNU General Public License as published - by the Free Software Foundation; version 3. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program or at /usr/share/common-licenses/GPL-3 - If not, see . diff --git a/debian/frostfs-cli.docs b/debian/frostfs-cli.docs deleted file mode 100644 index 58d4559cc9..0000000000 --- a/debian/frostfs-cli.docs +++ /dev/null @@ -1,4 +0,0 @@ -CONTRIBUTING.md -CREDITS.md -README.md -cmd/frostfs-adm/docs diff --git a/debian/frostfs-cli.install b/debian/frostfs-cli.install deleted file mode 100644 index 93025187b2..0000000000 --- a/debian/frostfs-cli.install +++ /dev/null @@ -1,3 +0,0 @@ -bin/frostfs-adm usr/bin -bin/frostfs-cli usr/bin -bin/frostfs-lens usr/bin diff --git a/debian/frostfs-cli.manpages b/debian/frostfs-cli.manpages deleted file mode 100644 index 85c5e001d0..0000000000 --- a/debian/frostfs-cli.manpages +++ /dev/null @@ -1 +0,0 @@ -man/* diff --git a/debian/frostfs-ir.dirs b/debian/frostfs-ir.dirs deleted file mode 100644 index 90da8fd278..0000000000 --- a/debian/frostfs-ir.dirs +++ /dev/null @@ -1,2 +0,0 @@ -/etc/frostfs/ir -/var/lib/frostfs/ir diff --git a/debian/frostfs-ir.docs b/debian/frostfs-ir.docs deleted file mode 100644 index 38b0cef260..0000000000 --- a/debian/frostfs-ir.docs +++ /dev/null @@ -1,3 +0,0 @@ -CONTRIBUTING.md -CREDITS.md -README.md diff --git a/debian/frostfs-ir.install b/debian/frostfs-ir.install deleted file mode 100644 index e052f5434c..0000000000 --- a/debian/frostfs-ir.install +++ /dev/null @@ -1 +0,0 @@ -bin/frostfs-ir usr/bin diff --git a/debian/frostfs-ir.postinst b/debian/frostfs-ir.postinst deleted file mode 100755 index eb9d381c99..0000000000 --- a/debian/frostfs-ir.postinst +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `configure' -# * `abort-upgrade' -# * `abort-remove' `in-favour' -# -# * `abort-remove' -# * `abort-deconfigure' `in-favour' -# `removing' -# -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - -case "$1" in - configure) - USERNAME=ir - id -u frostfs-ir >/dev/null 2>&1 || useradd -s /usr/sbin/nologin -d /var/lib/frostfs/ir --system -M -U -c "FrostFS InnerRing node" frostfs-ir - if ! dpkg-statoverride --list /etc/frostfs/$USERNAME >/dev/null; then - chown -f root:frostfs-$USERNAME /etc/frostfs/$USERNAME - chmod -f 0750 /etc/frostfs/$USERNAME - chown -f root:frostfs-$USERNAME /etc/frostfs/$USERNAME/config.yml - chown -f root:frostfs-$USERNAME /etc/frostfs/$USERNAME/control.yml - chmod -f 0640 /etc/frostfs/$USERNAME/config.yml || true - chmod -f 0640 /etc/frostfs/$USERNAME/control.yml || true - fi - USERDIR="$(getent passwd frostfs-$USERNAME | cut -d: -f6)" - if ! dpkg-statoverride --list frostfs-"$USERDIR" >/dev/null; then - chown -f frostfs-$USERNAME: "$USERDIR" - fi - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/frostfs-ir.postrm b/debian/frostfs-ir.postrm deleted file mode 100755 index cbb7db2f2f..0000000000 --- a/debian/frostfs-ir.postrm +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `purge' -# * `upgrade' -# * `failed-upgrade' -# * `abort-install' -# * `abort-install' -# * `abort-upgrade' -# * `disappear' -# -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - purge) - rm -rf /var/lib/frostfs/ir/* - ;; - - remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/frostfs-ir.preinst b/debian/frostfs-ir.preinst deleted file mode 100755 index 37f9525378..0000000000 --- a/debian/frostfs-ir.preinst +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `install' -# * `install' -# * `upgrade' -# * `abort-upgrade' -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - install|upgrade) - ;; - - abort-upgrade) - ;; - - *) - echo "preinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/frostfs-ir.prerm b/debian/frostfs-ir.prerm deleted file mode 100755 index 0da369d751..0000000000 --- a/debian/frostfs-ir.prerm +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `upgrade' -# * `failed-upgrade' -# * `remove' `in-favour' -# * `deconfigure' `in-favour' -# `removing' -# -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - remove|upgrade|deconfigure) - ;; - - failed-upgrade) - ;; - - *) - echo "prerm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/frostfs-ir.service b/debian/frostfs-ir.service deleted file mode 100644 index 304017f683..0000000000 --- a/debian/frostfs-ir.service +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=FrostFS InnerRing node -Requires=network.target - -[Service] -Type=notify -NotifyAccess=all -ExecStart=/usr/bin/frostfs-ir --config /etc/frostfs/ir/config.yml -User=frostfs-ir -Group=frostfs-ir -WorkingDirectory=/var/lib/frostfs/ir -Restart=always -RestartSec=5 -PrivateTmp=true - -[Install] -WantedBy=multi-user.target diff --git a/debian/frostfs-storage.dirs b/debian/frostfs-storage.dirs deleted file mode 100644 index 4142145ee4..0000000000 --- a/debian/frostfs-storage.dirs +++ /dev/null @@ -1,3 +0,0 @@ -/etc/frostfs/storage -/srv/frostfs -/var/lib/frostfs/storage diff --git a/debian/frostfs-storage.docs b/debian/frostfs-storage.docs deleted file mode 100644 index cd1f5f23f0..0000000000 --- a/debian/frostfs-storage.docs +++ /dev/null @@ -1,4 +0,0 @@ -docs/storage-node-configuration.md -CONTRIBUTING.md -CREDITS.md -README.md diff --git a/debian/frostfs-storage.install b/debian/frostfs-storage.install deleted file mode 100644 index 670935e7bd..0000000000 --- a/debian/frostfs-storage.install +++ /dev/null @@ -1 +0,0 @@ -bin/frostfs-node usr/bin diff --git a/debian/frostfs-storage.postinst b/debian/frostfs-storage.postinst deleted file mode 100755 index 88fa53be5d..0000000000 --- a/debian/frostfs-storage.postinst +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `configure' -# * `abort-upgrade' -# * `abort-remove' `in-favour' -# -# * `abort-remove' -# * `abort-deconfigure' `in-favour' -# `removing' -# -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - -case "$1" in - configure) - USERNAME=storage - id -u frostfs-$USERNAME >/dev/null 2>&1 || useradd -s /usr/sbin/nologin -d /var/lib/frostfs/$USERNAME --system -M -U -c "FrostFS Storage node" frostfs-$USERNAME - if ! dpkg-statoverride --list /etc/frostfs/$USERNAME >/dev/null; then - chown -f root:frostfs-$USERNAME /etc/frostfs/$USERNAME - chmod -f 0750 /etc/frostfs/$USERNAME - chown -f root:frostfs-$USERNAME /etc/frostfs/$USERNAME/config.yml - chown -f root:frostfs-$USERNAME /etc/frostfs/$USERNAME/control.yml - chmod -f 0640 /etc/frostfs/$USERNAME/config.yml || true - chmod -f 0640 /etc/frostfs/$USERNAME/control.yml || true - fi - USERDIR=$(getent passwd frostfs-$USERNAME | cut -d: -f6) - if ! dpkg-statoverride --list frostfs-"$USERDIR" >/dev/null; then - chown -f frostfs-$USERNAME: "$USERDIR" - fi - USERDIR=/srv/frostfs - if ! dpkg-statoverride --list frostfs-$USERDIR >/dev/null; then - chown -f frostfs-$USERNAME: $USERDIR - fi - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/frostfs-storage.postrm b/debian/frostfs-storage.postrm deleted file mode 100755 index d9c8c9656a..0000000000 --- a/debian/frostfs-storage.postrm +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `purge' -# * `upgrade' -# * `failed-upgrade' -# * `abort-install' -# * `abort-install' -# * `abort-upgrade' -# * `disappear' -# -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - purge) - rm -rf /var/lib/frostfs/storage/* - ;; - - remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) - ;; - - *) - echo "postrm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/frostfs-storage.preinst b/debian/frostfs-storage.preinst deleted file mode 100755 index 37f9525378..0000000000 --- a/debian/frostfs-storage.preinst +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `install' -# * `install' -# * `upgrade' -# * `abort-upgrade' -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - install|upgrade) - ;; - - abort-upgrade) - ;; - - *) - echo "preinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/frostfs-storage.prerm b/debian/frostfs-storage.prerm deleted file mode 100755 index 0da369d751..0000000000 --- a/debian/frostfs-storage.prerm +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `remove' -# * `upgrade' -# * `failed-upgrade' -# * `remove' `in-favour' -# * `deconfigure' `in-favour' -# `removing' -# -# for details, see https://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - remove|upgrade|deconfigure) - ;; - - failed-upgrade) - ;; - - *) - echo "prerm called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 diff --git a/debian/frostfs-storage.service b/debian/frostfs-storage.service deleted file mode 100644 index 5739617568..0000000000 --- a/debian/frostfs-storage.service +++ /dev/null @@ -1,17 +0,0 @@ -[Unit] -Description=FrostFS Storage node -Requires=network.target - -[Service] -Type=notify -NotifyAccess=all -ExecStart=/usr/bin/frostfs-node --config /etc/frostfs/storage/config.yml -User=frostfs-storage -Group=frostfs-storage -WorkingDirectory=/srv/frostfs -Restart=always -RestartSec=5 -PrivateTmp=true - -[Install] -WantedBy=multi-user.target diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 0dd8ee3994..0000000000 --- a/debian/rules +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/make -f - -# Do not try to strip Go binaries -export DEB_BUILD_OPTIONS := nostrip - -%: - dh $@ --with bash-completion - -override_dh_auto_test: - -override_dh_auto_install: - echo $(DEB_BUILD_OPTIONS) - dh_auto_install - - bin/frostfs-adm gendoc --type man man/ - bin/frostfs-cli gendoc --type man man/ - - bin/frostfs-adm completion bash > debian/frostfs-adm.bash-completion - bin/frostfs-cli completion bash > debian/frostfs-cli.bash-completion - install -m 0755 -d debian/frostfs-cli/usr/share/fish/completions/ - install -m 0755 -d debian/frostfs-cli/usr/share/zsh/vendor-completions/ - bin/frostfs-adm completion fish > debian/frostfs-cli/usr/share/fish/completions/frostfs-adm.fish - bin/frostfs-adm completion zsh > debian/frostfs-cli/usr/share/zsh/vendor-completions/_frostfs-adm - bin/frostfs-cli completion fish > debian/frostfs-cli/usr/share/fish/completions/frostfs-cli.fish - bin/frostfs-cli completion zsh > debian/frostfs-cli/usr/share/zsh/vendor-completions/_frostfs-cli - - install -T -m 0640 config/example/ir.yaml debian/frostfs-ir/etc/frostfs/ir/config.yml - install -T -m 0640 config/example/ir-control.yaml debian/frostfs-ir/etc/frostfs/ir/control.yml - install -T -m 0640 config/example/node.yaml debian/frostfs-storage/etc/frostfs/storage/config.yml - install -T -m 0640 config/example/node-control.yaml debian/frostfs-storage/etc/frostfs/storage/control.yml - -override_dh_installsystemd: - dh_installsystemd --no-enable --no-start --name=frostfs-ir - dh_installsystemd --no-enable --no-start --name=frostfs-storage - -override_dh_installchangelogs: - dh_installchangelogs -k CHANGELOG.md - -override_dh_installdocs: - dh_installdocs diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 163aaf8d82..0000000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/docs/building-deb-package.md b/docs/building-deb-package.md deleted file mode 100644 index 26a77a27ff..0000000000 --- a/docs/building-deb-package.md +++ /dev/null @@ -1,46 +0,0 @@ -# Building Debian package on host - -## Prerequisites - -For now, we're assuming building for Debian 11 (stable) x86_64. - -Go version 18.4 or later should already be installed, i.e. this runs -successfully: - -* `make all` - -## Installing packaging dependencies - -```shell -$ sudo apt install debhelper-compat dh-sequence-bash-completion devscripts -``` - -Warining: number of package installed is pretty large considering dependecies. - -## Package building - -```shell -$ make debpackage -``` - -## Leftovers cleaning - -```shell -$ make debclean -``` -or -```shell -$ dh clean -``` - -# Package versioning - -By default, package version is based on product version and may also contain git -tags and hashes. - -Package version could be overwritten by setting `PKG_VERSION` variable before -build, Debian package versioning rules should be respected. - -```shell -$ PKG_VERSION=0.32.0 make debpackge -``` diff --git a/docs/release-instruction.md b/docs/release-instruction.md index 3aebc8e66f..d000f10d08 100644 --- a/docs/release-instruction.md +++ b/docs/release-instruction.md @@ -43,11 +43,6 @@ Write new revision number into the root `VERSION` file: $ echo ${FROSTFS_TAG_PREFIX}${FROSTFS_REVISION} > VERSION ``` -Update version in Debian package changelog file -``` -$ cat debian/changelog -``` - Update the supported version of `TrueCloudLab/frostfs-contract` module in root `README.md` if needed. From ed13387c0e1406040898fc91f36c6d9370f58413 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 18 Oct 2024 15:19:29 +0300 Subject: [PATCH 0931/1413] [#1438] .docker: Use go1.23 for builders Signed-off-by: Evgenii Stratonikov --- .docker/Dockerfile.adm | 2 +- .docker/Dockerfile.ci | 2 +- .docker/Dockerfile.cli | 2 +- .docker/Dockerfile.ir | 2 +- .docker/Dockerfile.storage | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.docker/Dockerfile.adm b/.docker/Dockerfile.adm index 5d67a1d04c..42aeebc482 100644 --- a/.docker/Dockerfile.adm +++ b/.docker/Dockerfile.adm @@ -1,4 +1,4 @@ -FROM golang:1.22 AS builder +FROM golang:1.23 AS builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ci b/.docker/Dockerfile.ci index e9077c8313..9ddd8de593 100644 --- a/.docker/Dockerfile.ci +++ b/.docker/Dockerfile.ci @@ -1,4 +1,4 @@ -FROM golang:1.22 +FROM golang:1.23 WORKDIR /tmp diff --git a/.docker/Dockerfile.cli b/.docker/Dockerfile.cli index 16f643b614..16f1300562 100644 --- a/.docker/Dockerfile.cli +++ b/.docker/Dockerfile.cli @@ -1,4 +1,4 @@ -FROM golang:1.22 AS builder +FROM golang:1.23 AS builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.ir b/.docker/Dockerfile.ir index f2cb764e53..c119f8127a 100644 --- a/.docker/Dockerfile.ir +++ b/.docker/Dockerfile.ir @@ -1,4 +1,4 @@ -FROM golang:1.22 AS builder +FROM golang:1.23 AS builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository diff --git a/.docker/Dockerfile.storage b/.docker/Dockerfile.storage index cf7f977480..854f7adeab 100644 --- a/.docker/Dockerfile.storage +++ b/.docker/Dockerfile.storage @@ -1,4 +1,4 @@ -FROM golang:1.22 AS builder +FROM golang:1.23 AS builder ARG BUILD=now ARG VERSION=dev ARG REPO=repository From 8b6ec57c6147e5b784d78bc891144dd55493503d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 21 Oct 2024 14:12:02 +0300 Subject: [PATCH 0932/1413] [#1440] sdnotify: Fix status for `RELOADING` Before: ``` RELOADING=1 MONOTONIC_USEC=17951246687 STATUS=RELOADING=1 MONOTONIC_USEC=17951246687 ``` After: ``` RELOADING=1 MONOTONIC_USEC=17951246687 STATUS=RELOADING ``` Signed-off-by: Anton Nikiforov --- pkg/util/sdnotify/sdnotify.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/util/sdnotify/sdnotify.go b/pkg/util/sdnotify/sdnotify.go index 22549bc963..bd15d0e8f4 100644 --- a/pkg/util/sdnotify/sdnotify.go +++ b/pkg/util/sdnotify/sdnotify.go @@ -59,6 +59,8 @@ func FlagAndStatus(status string) error { return fmt.Errorf("clock_gettime: %w", err) } status += "\nMONOTONIC_USEC=" + strconv.FormatInt(ts.Nano()/1000, 10) + status += "\nSTATUS=RELOADING" + return Send(status) } status += "\nSTATUS=" + strings.TrimSuffix(status, "=1") return Send(status) From e515dd458267b8cbaa05d09b0cf55ec07f8dcf5b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 23 Oct 2024 10:39:19 +0300 Subject: [PATCH 0933/1413] [#1444] config: Fix data race on morph component init It could be called for every shard on metabase resync concurrently and it is possible to get state with initialized client but not initialized contract hashes. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/accounting.go | 4 +--- cmd/frostfs-node/config.go | 8 ++++---- cmd/frostfs-node/morph.go | 8 +++++++- cmd/frostfs-node/netmap.go | 4 +--- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/cmd/frostfs-node/accounting.go b/cmd/frostfs-node/accounting.go index ec737f8a01..1d065c2272 100644 --- a/cmd/frostfs-node/accounting.go +++ b/cmd/frostfs-node/accounting.go @@ -13,9 +13,7 @@ import ( ) func initAccountingService(ctx context.Context, c *cfg) { - if c.cfgMorph.client == nil { - initMorphComponents(ctx, c) - } + c.initMorphComponents(ctx) balanceMorphWrapper, err := balance.NewFromMorph(c.cfgMorph.client, c.cfgAccounting.scriptHash, 0) fatalOnErr(err) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 9d2b772106..cf7e0da7e3 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -575,6 +575,9 @@ func (c *cfgGRPC) dropConnection(endpoint string) { } type cfgMorph struct { + initialized bool + guard sync.Mutex + client *client.Client notaryEnabled bool @@ -1455,10 +1458,7 @@ func (c *cfg) createTombstoneSource() *tombstone.ExpirationChecker { func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoProvider { return container.NewInfoProvider(func() (container.Source, error) { - // threadsafe: called on init or on sighup when morph initialized - if c.cfgMorph.client == nil { - initMorphComponents(ctx, c) - } + c.initMorphComponents(ctx) cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, containerClient.TryNotary()) if err != nil { return nil, err diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 197e503712..e852090599 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -28,7 +28,12 @@ const ( notaryDepositRetriesAmount = 300 ) -func initMorphComponents(ctx context.Context, c *cfg) { +func (c *cfg) initMorphComponents(ctx context.Context) { + c.cfgMorph.guard.Lock() + defer c.cfgMorph.guard.Unlock() + if c.cfgMorph.initialized { + return + } initMorphClient(ctx, c) lookupScriptHashesInNNS(c) // smart contract auto negotiation @@ -70,6 +75,7 @@ func initMorphComponents(ctx context.Context, c *cfg) { c.netMapSource = netmapSource c.cfgNetmap.wrapper = wrap + c.cfgMorph.initialized = true } func initMorphClient(ctx context.Context, c *cfg) { diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 5e4585f854..0e05717603 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -143,9 +143,7 @@ func initNetmapService(ctx context.Context, c *cfg) { parseAttributes(c) c.cfgNodeInfo.localInfo.SetStatus(netmapSDK.Offline) - if c.cfgMorph.client == nil { - initMorphComponents(ctx, c) - } + c.initMorphComponents(ctx) initNetmapState(c) From 6f798b9c4b4e244a0161e50dd5ee2e647835a949 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 22 Oct 2024 10:18:01 +0300 Subject: [PATCH 0934/1413] [#1441] cli: Use `grpc.WaitForReady` while initializing SDK client Before, when the target RPC server was unavailable, requests made by CLI didn't wait for a timeout specified by the `--timeout` option if the timeout was more than 20 seconds. It's because of the gRPC default backoff strategy. Adding this option fixes that behavior. Signed-off-by: Aleksey Savchuk --- cmd/frostfs-cli/internal/client/sdk.go | 1 + cmd/frostfs-cli/modules/tree/client.go | 1 + 2 files changed, 2 insertions(+) diff --git a/cmd/frostfs-cli/internal/client/sdk.go b/cmd/frostfs-cli/internal/client/sdk.go index f7c48b8718..2d9c45cbd9 100644 --- a/cmd/frostfs-cli/internal/client/sdk.go +++ b/cmd/frostfs-cli/internal/client/sdk.go @@ -58,6 +58,7 @@ func GetSDKClient(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey GRPCDialOptions: []grpc.DialOption{ grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor()), grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor()), + grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), }, } if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 { diff --git a/cmd/frostfs-cli/modules/tree/client.go b/cmd/frostfs-cli/modules/tree/client.go index 4e0099f027..6891e711c5 100644 --- a/cmd/frostfs-cli/modules/tree/client.go +++ b/cmd/frostfs-cli/modules/tree/client.go @@ -34,6 +34,7 @@ func _client() (tree.TreeServiceClient, error) { metrics.NewStreamClientInterceptor(), tracing.NewStreamClientInterceptor(), ), + grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), } if !strings.HasPrefix(netAddr.URIAddr(), "grpcs:") { From 9a260c2e64abd5309cce7e3e7fde93b131b3ffc0 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 23 Oct 2024 14:02:31 +0300 Subject: [PATCH 0935/1413] [#1441] network/cache: Use `grpc.WaitForReady` option when creating client Signed-off-by: Aleksey Savchuk --- pkg/network/cache/multi.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index e936ead651..2ecce3a010 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -70,6 +70,7 @@ func (x *multiClient) createForAddress(ctx context.Context, addr network.Address tracing.NewStreamClientInterceptor(), ), grpc.WithContextDialer(x.opts.DialerSource.GrpcContextDialer()), + grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), } prmDial := client.PrmDial{ From 65a4320c7539f4915e799f652475c739b7ad58b7 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 23 Oct 2024 14:04:37 +0300 Subject: [PATCH 0936/1413] [#1441] services/tree: Use `grpc.WaitForReady` option when creating client Signed-off-by: Aleksey Savchuk --- pkg/services/tree/cache.go | 1 + pkg/services/tree/sync.go | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index e490cb8559..ac80d0e4c4 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -103,6 +103,7 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* tracing.NewStreamClientInterceptor(), ), grpc.WithContextDialer(c.ds.GrpcContextDialer()), + grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), } if !netAddr.IsTLSEnabled() { diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 5bbc93978b..ce1e72104b 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -342,7 +342,9 @@ func (*Service) createConnection(a network.Address) (*grpc.ClientConn, error) { metrics.NewStreamClientInterceptor(), tracing_grpc.NewStreamClientInterceptor(), ), - grpc.WithTransportCredentials(insecure.NewCredentials())) + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), + ) } // ErrAlreadySyncing is returned when a service synchronization has already From b9284604d9a19ba4151e664439c6300894c14905 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 23 Oct 2024 15:36:49 +0300 Subject: [PATCH 0937/1413] [#1442] cli/tree: Allow to specify `rpc-endpoint` with config file We have several ways to specify the `rpc-endpoint`: with a flag, with a single config file or multiple files. Before, the `rpc-endpoint` flag was marked as required. Because `cobra` checked the required flag presence first, it prevented specifying `rpc-endpoint` with a config file. Signed-off-by: Aleksey Savchuk --- cmd/frostfs-cli/modules/tree/add.go | 2 -- cmd/frostfs-cli/modules/tree/add_by_path.go | 1 - cmd/frostfs-cli/modules/tree/get_by_path.go | 2 -- cmd/frostfs-cli/modules/tree/get_op_log.go | 2 -- cmd/frostfs-cli/modules/tree/healthcheck.go | 2 -- cmd/frostfs-cli/modules/tree/list.go | 2 -- cmd/frostfs-cli/modules/tree/move.go | 2 -- cmd/frostfs-cli/modules/tree/remove.go | 2 -- cmd/frostfs-cli/modules/tree/subtree.go | 2 -- 9 files changed, 17 deletions(-) diff --git a/cmd/frostfs-cli/modules/tree/add.go b/cmd/frostfs-cli/modules/tree/add.go index 019feb0ecc..e2c05d4868 100644 --- a/cmd/frostfs-cli/modules/tree/add.go +++ b/cmd/frostfs-cli/modules/tree/add.go @@ -30,8 +30,6 @@ func initAddCmd() { ff := addCmd.Flags() ff.StringSlice(metaFlagKey, nil, "Meta pairs in the form of Key1=[0x]Value1,Key2=[0x]Value2") ff.Uint64(parentIDFlagKey, 0, "Parent node ID") - - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func add(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-cli/modules/tree/add_by_path.go b/cmd/frostfs-cli/modules/tree/add_by_path.go index 5d5b00b7dd..7263bcd0d6 100644 --- a/cmd/frostfs-cli/modules/tree/add_by_path.go +++ b/cmd/frostfs-cli/modules/tree/add_by_path.go @@ -36,7 +36,6 @@ func initAddByPathCmd() { ff.String(pathFlagKey, "", "Path to a node") ff.StringSlice(metaFlagKey, nil, "Meta pairs in the form of Key1=[0x]Value1,Key2=[0x]Value2") - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) _ = cobra.MarkFlagRequired(ff, pathFlagKey) } diff --git a/cmd/frostfs-cli/modules/tree/get_by_path.go b/cmd/frostfs-cli/modules/tree/get_by_path.go index 7061723fdf..210630e60a 100644 --- a/cmd/frostfs-cli/modules/tree/get_by_path.go +++ b/cmd/frostfs-cli/modules/tree/get_by_path.go @@ -36,8 +36,6 @@ func initGetByPathCmd() { ff.String(pathFlagKey, "", "Path to a node") ff.Bool(latestOnlyFlagKey, false, "Look only for the latest version of a node") - - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func getByPath(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-cli/modules/tree/get_op_log.go b/cmd/frostfs-cli/modules/tree/get_op_log.go index 376aa8e8d6..9d767ab3e8 100644 --- a/cmd/frostfs-cli/modules/tree/get_op_log.go +++ b/cmd/frostfs-cli/modules/tree/get_op_log.go @@ -30,8 +30,6 @@ func initGetOpLogCmd() { ff := getOpLogCmd.Flags() ff.Uint64(heightFlagKey, 0, "Height to start with") ff.Uint64(countFlagKey, 10, "Logged operations count") - - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func getOpLog(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-cli/modules/tree/healthcheck.go b/cmd/frostfs-cli/modules/tree/healthcheck.go index b01bb2e771..c581b8e26b 100644 --- a/cmd/frostfs-cli/modules/tree/healthcheck.go +++ b/cmd/frostfs-cli/modules/tree/healthcheck.go @@ -20,8 +20,6 @@ var healthcheckCmd = &cobra.Command{ func initHealthcheckCmd() { commonflags.Init(healthcheckCmd) - ff := healthcheckCmd.Flags() - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func healthcheck(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-cli/modules/tree/list.go b/cmd/frostfs-cli/modules/tree/list.go index f8c0e490fd..ee1db2a79a 100644 --- a/cmd/frostfs-cli/modules/tree/list.go +++ b/cmd/frostfs-cli/modules/tree/list.go @@ -26,8 +26,6 @@ func initListCmd() { ff := listCmd.Flags() ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) _ = listCmd.MarkFlagRequired(commonflags.CIDFlag) - - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func list(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-cli/modules/tree/move.go b/cmd/frostfs-cli/modules/tree/move.go index dc807d7527..7a369bd027 100644 --- a/cmd/frostfs-cli/modules/tree/move.go +++ b/cmd/frostfs-cli/modules/tree/move.go @@ -33,8 +33,6 @@ func initMoveCmd() { _ = getSubtreeCmd.MarkFlagRequired(nodeIDFlagKey) _ = getSubtreeCmd.MarkFlagRequired(parentIDFlagKey) - - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func move(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-cli/modules/tree/remove.go b/cmd/frostfs-cli/modules/tree/remove.go index d0b6fab2f6..3c532fe261 100644 --- a/cmd/frostfs-cli/modules/tree/remove.go +++ b/cmd/frostfs-cli/modules/tree/remove.go @@ -29,8 +29,6 @@ func initRemoveCmd() { ff.Uint64(nodeIDFlagKey, 0, "Node ID.") _ = getSubtreeCmd.MarkFlagRequired(nodeIDFlagKey) - - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func remove(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-cli/modules/tree/subtree.go b/cmd/frostfs-cli/modules/tree/subtree.go index 83a8909b68..c5f7ad401d 100644 --- a/cmd/frostfs-cli/modules/tree/subtree.go +++ b/cmd/frostfs-cli/modules/tree/subtree.go @@ -34,8 +34,6 @@ func initGetSubtreeCmd() { _ = getSubtreeCmd.MarkFlagRequired(commonflags.CIDFlag) _ = getSubtreeCmd.MarkFlagRequired(treeIDFlagKey) - - _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func getSubTree(cmd *cobra.Command, _ []string) { From 29708b78d705958067a6f0d25b4e63572bf7e93d Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 23 Oct 2024 15:37:50 +0300 Subject: [PATCH 0938/1413] [#1442] cli/tree: Enchance error message if `rpc-endpoint` isn't defined Signed-off-by: Aleksey Savchuk --- cmd/frostfs-cli/modules/tree/client.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/modules/tree/client.go b/cmd/frostfs-cli/modules/tree/client.go index 6891e711c5..a70624ac8d 100644 --- a/cmd/frostfs-cli/modules/tree/client.go +++ b/cmd/frostfs-cli/modules/tree/client.go @@ -2,6 +2,7 @@ package tree import ( "context" + "fmt" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" @@ -20,7 +21,13 @@ import ( // after making Tree API public. func _client() (tree.TreeServiceClient, error) { var netAddr network.Address - err := netAddr.FromString(viper.GetString(commonflags.RPC)) + + rpcEndpoint := viper.GetString(commonflags.RPC) + if rpcEndpoint == "" { + return nil, fmt.Errorf("%s is not defined", commonflags.RPC) + } + + err := netAddr.FromString(rpcEndpoint) if err != nil { return nil, err } From bc8d79ddf949cb88546bc214d688a03f5ab9740e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 24 Oct 2024 09:45:57 +0300 Subject: [PATCH 0939/1413] [#1447] services/tree: Move relaying code to a separate function Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/redirect.go | 14 ++++++++ pkg/services/tree/service.go | 66 ++++------------------------------- 2 files changed, 20 insertions(+), 60 deletions(-) diff --git a/pkg/services/tree/redirect.go b/pkg/services/tree/redirect.go index ec41a60d47..5bde3ae381 100644 --- a/pkg/services/tree/redirect.go +++ b/pkg/services/tree/redirect.go @@ -12,10 +12,24 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" + "google.golang.org/grpc" ) var errNoSuitableNode = errors.New("no node was found to execute the request") +func relayUnary[Req any, Resp any](ctx context.Context, s *Service, ns []netmapSDK.NodeInfo, req *Req, callback func(TreeServiceClient, context.Context, *Req, ...grpc.CallOption) (*Resp, error)) (*Resp, error) { + var resp *Resp + var outErr error + err := s.forEachNode(ctx, ns, func(c TreeServiceClient) bool { + resp, outErr = callback(c, ctx, req) + return true + }) + if err != nil { + return nil, err + } + return resp, outErr +} + // forEachNode executes callback for each node in the container until true is returned. // Returns errNoSuitableNode if there was no successful attempt to dial any node. func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo, f func(c TreeServiceClient) bool) error { diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 2cb2af294d..acc2775e64 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -122,16 +122,7 @@ func (s *Service) Add(ctx context.Context, req *AddRequest) (*AddResponse, error return nil, err } if pos < 0 { - var resp *AddResponse - var outErr error - err = s.forEachNode(ctx, ns, func(c TreeServiceClient) bool { - resp, outErr = c.Add(ctx, req) - return true - }) - if err != nil { - return nil, err - } - return resp, outErr + return relayUnary(ctx, s, ns, req, (TreeServiceClient).Add) } d := pilorama.CIDDescriptor{CID: cid, Position: pos, Size: len(ns)} @@ -174,16 +165,7 @@ func (s *Service) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByP return nil, err } if pos < 0 { - var resp *AddByPathResponse - var outErr error - err = s.forEachNode(ctx, ns, func(c TreeServiceClient) bool { - resp, outErr = c.AddByPath(ctx, req) - return true - }) - if err != nil { - return nil, err - } - return resp, outErr + return relayUnary(ctx, s, ns, req, (TreeServiceClient).AddByPath) } meta := protoToMeta(b.GetMeta()) @@ -238,16 +220,7 @@ func (s *Service) Remove(ctx context.Context, req *RemoveRequest) (*RemoveRespon return nil, err } if pos < 0 { - var resp *RemoveResponse - var outErr error - err = s.forEachNode(ctx, ns, func(c TreeServiceClient) bool { - resp, outErr = c.Remove(ctx, req) - return true - }) - if err != nil { - return nil, err - } - return resp, outErr + return relayUnary(ctx, s, ns, req, (TreeServiceClient).Remove) } if b.GetNodeId() == pilorama.RootID { @@ -291,16 +264,7 @@ func (s *Service) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, er return nil, err } if pos < 0 { - var resp *MoveResponse - var outErr error - err = s.forEachNode(ctx, ns, func(c TreeServiceClient) bool { - resp, outErr = c.Move(ctx, req) - return true - }) - if err != nil { - return nil, err - } - return resp, outErr + return relayUnary(ctx, s, ns, req, (TreeServiceClient).Move) } if b.GetNodeId() == pilorama.RootID { @@ -343,16 +307,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) return nil, err } if pos < 0 { - var resp *GetNodeByPathResponse - var outErr error - err = s.forEachNode(ctx, ns, func(c TreeServiceClient) bool { - resp, outErr = c.GetNodeByPath(ctx, req) - return true - }) - if err != nil { - return nil, err - } - return resp, outErr + return relayUnary(ctx, s, ns, req, (TreeServiceClient).GetNodeByPath) } attr := b.GetPathAttribute() @@ -763,16 +718,7 @@ func (s *Service) TreeList(ctx context.Context, req *TreeListRequest) (*TreeList return nil, err } if pos < 0 { - var resp *TreeListResponse - var outErr error - err = s.forEachNode(ctx, ns, func(c TreeServiceClient) bool { - resp, outErr = c.TreeList(ctx, req) - return outErr == nil - }) - if err != nil { - return nil, err - } - return resp, outErr + return relayUnary(ctx, s, ns, req, (TreeServiceClient).TreeList) } ids, err := s.forest.TreeList(ctx, cid) From eb5336d5ff53f764edee4fcbd10e738db506a0e6 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 22 Oct 2024 15:47:15 +0300 Subject: [PATCH 0940/1413] [#1406] tree: Use delete verb instead put for Remove Signed-off-by: Airat Arifullin --- pkg/services/tree/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index acc2775e64..10c3b6ccc4 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -210,7 +210,7 @@ func (s *Service) Remove(ctx context.Context, req *RemoveRequest) (*RemoveRespon return nil, err } - err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut) + err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectDelete) if err != nil { return nil, err } From 012af5cc38597d6bbd28b723a5d4190ece8c7cbb Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 28 Oct 2024 13:07:28 +0300 Subject: [PATCH 0941/1413] [#1406] tree: Add unit-tests for ape check Signed-off-by: Airat Arifullin --- pkg/services/tree/ape_test.go | 207 ++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 pkg/services/tree/ape_test.go diff --git a/pkg/services/tree/ape_test.go b/pkg/services/tree/ape_test.go new file mode 100644 index 0000000000..3f94925b57 --- /dev/null +++ b/pkg/services/tree/ape_test.go @@ -0,0 +1,207 @@ +package tree + +import ( + "context" + "encoding/hex" + "fmt" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" + checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" + containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine/inmemory" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/stretchr/testify/require" +) + +var ( + containerID = "73tQMTYyUkTgmvPR1HWib6pndbhSoBovbnMF7Pws8Rcy" + + senderPrivateKey, _ = keys.NewPrivateKey() + + senderKey = hex.EncodeToString(senderPrivateKey.PublicKey().Bytes()) + + rootCnr = &core.Container{Value: containerSDK.Container{}} +) + +type frostfsIDProviderMock struct { + subjects map[util.Uint160]*client.Subject + subjectsExtended map[util.Uint160]*client.SubjectExtended +} + +func (f *frostfsIDProviderMock) GetSubject(key util.Uint160) (*client.Subject, error) { + v, ok := f.subjects[key] + if !ok { + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) + } + return v, nil +} + +func (f *frostfsIDProviderMock) GetSubjectExtended(key util.Uint160) (*client.SubjectExtended, error) { + v, ok := f.subjectsExtended[key] + if !ok { + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) + } + return v, nil +} + +var _ frostfsidcore.SubjectProvider = (*frostfsIDProviderMock)(nil) + +func newFrostfsIDProviderMock(t *testing.T) *frostfsIDProviderMock { + return &frostfsIDProviderMock{ + subjects: map[util.Uint160]*client.Subject{ + scriptHashFromSenderKey(t, senderKey): { + Namespace: "testnamespace", + Name: "test", + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + }, + }, + subjectsExtended: map[util.Uint160]*client.SubjectExtended{ + scriptHashFromSenderKey(t, senderKey): { + Namespace: "testnamespace", + Name: "test", + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 1, + Name: "test", + Namespace: "testnamespace", + KV: map[string]string{ + "attr1": "value1", + "attr2": "value2", + }, + }, + }, + }, + }, + } +} + +func scriptHashFromSenderKey(t *testing.T, senderKey string) util.Uint160 { + pk, err := keys.NewPublicKeyFromString(senderKey) + require.NoError(t, err) + return pk.GetScriptHash() +} + +type stMock struct{} + +func (m *stMock) CurrentEpoch() uint64 { + return 8 +} + +func TestCheckAPE(t *testing.T) { + cid := cid.ID{} + _ = cid.DecodeString(containerID) + + t.Run("put non-tombstone rule won't affect tree remove", func(t *testing.T) { + los := inmemory.NewInmemoryLocalStorage() + mcs := inmemory.NewInmemoryMorphRuleChainStorage() + fid := newFrostfsIDProviderMock(t) + s := Service{ + cfg: cfg{ + frostfsidSubjectProvider: fid, + }, + apeChecker: checkercore.New(los, mcs, fid, &stMock{}), + } + + los.AddOverride(chain.Ingress, engine.ContainerTarget(containerID), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + Condition: []chain.Condition{ + { + Op: chain.CondStringNotEquals, + Kind: chain.KindResource, + Key: nativeschema.PropertyKeyObjectType, + Value: "TOMBSTONE", + }, + }, + }, + }, + MatchType: chain.MatchTypeFirstMatch, + }) + + mcs.AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(containerID), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{Names: []string{nativeschema.MethodDeleteObject}}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + }, + }, + MatchType: chain.MatchTypeFirstMatch, + }) + + err := s.checkAPE(context.Background(), nil, rootCnr, cid, acl.OpObjectDelete, acl.RoleOwner, senderPrivateKey.PublicKey()) + require.NoError(t, err) + }) + + t.Run("delete rule won't affect tree add", func(t *testing.T) { + los := inmemory.NewInmemoryLocalStorage() + mcs := inmemory.NewInmemoryMorphRuleChainStorage() + fid := newFrostfsIDProviderMock(t) + s := Service{ + cfg: cfg{ + frostfsidSubjectProvider: fid, + }, + apeChecker: checkercore.New(los, mcs, fid, &stMock{}), + } + + los.AddOverride(chain.Ingress, engine.ContainerTarget(containerID), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{Names: []string{nativeschema.MethodDeleteObject}}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + }, + }, + MatchType: chain.MatchTypeFirstMatch, + }) + + mcs.AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(containerID), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{Names: []string{nativeschema.MethodPutObject}}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + Condition: []chain.Condition{ + { + Op: chain.CondStringNotEquals, + Kind: chain.KindResource, + Key: nativeschema.PropertyKeyObjectType, + Value: "TOMBSTONE", + }, + }, + }, + }, + MatchType: chain.MatchTypeFirstMatch, + }) + + err := s.checkAPE(context.Background(), nil, rootCnr, cid, acl.OpObjectPut, acl.RoleOwner, senderPrivateKey.PublicKey()) + require.NoError(t, err) + }) +} From 3cd7d23f1095d2efe99e66a4dfe73ec4e5ff62d5 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 22 Oct 2024 10:04:34 +0300 Subject: [PATCH 0942/1413] [#1439] node: Reduce usage of `netmapAPI.NodeInfo` Remove outdated code from `netmap` service. Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/config.go | 12 +++++------ pkg/services/netmap/executor.go | 36 ++++++--------------------------- 2 files changed, 11 insertions(+), 37 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index cf7e0da7e3..b2dcafbd77 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1179,17 +1179,15 @@ func initObjectPool(cfg *config.Config) (pool cfgObjectRoutines) { return pool } -func (c *cfg) LocalNodeInfo() (*netmapV2.NodeInfo, error) { - var res netmapV2.NodeInfo - +func (c *cfg) LocalNodeInfo() *netmap.NodeInfo { + var res netmap.NodeInfo ni, ok := c.cfgNetmap.state.getNodeInfo() if ok { - ni.WriteToV2(&res) + res = ni } else { - c.cfgNodeInfo.localInfo.WriteToV2(&res) + res = c.cfgNodeInfo.localInfo } - - return &res, nil + return &res } // setContractNodeInfo rewrites local node info from the FrostFS network map. diff --git a/pkg/services/netmap/executor.go b/pkg/services/netmap/executor.go index ae2044246f..f48357915c 100644 --- a/pkg/services/netmap/executor.go +++ b/pkg/services/netmap/executor.go @@ -28,7 +28,7 @@ type executorSvc struct { type NodeState interface { // LocalNodeInfo must return current node state // in FrostFS API v2 NodeInfo structure. - LocalNodeInfo() (*netmap.NodeInfo, error) + LocalNodeInfo() *netmapSDK.NodeInfo // ReadCurrentNetMap reads current local network map of the storage node // into the given parameter. Returns any error encountered which prevented @@ -64,39 +64,15 @@ func NewExecutionService(s NodeState, v versionsdk.Version, netInfo NetworkInfo, func (s *executorSvc) LocalNodeInfo( _ context.Context, - req *netmap.LocalNodeInfoRequest, + _ *netmap.LocalNodeInfoRequest, ) (*netmap.LocalNodeInfoResponse, error) { - verV2 := req.GetMetaHeader().GetVersion() - if verV2 == nil { - return nil, errors.New("missing version") - } - - var ver versionsdk.Version - if err := ver.ReadFromV2(*verV2); err != nil { - return nil, fmt.Errorf("can't read version: %w", err) - } - - ni, err := s.state.LocalNodeInfo() - if err != nil { - return nil, err - } - - if addrNum := ni.NumberOfAddresses(); addrNum > 0 && ver.Minor() <= 7 { - ni2 := new(netmap.NodeInfo) - ni2.SetPublicKey(ni.GetPublicKey()) - ni2.SetState(ni.GetState()) - ni2.SetAttributes(ni.GetAttributes()) - ni.IterateAddresses(func(s string) bool { - ni2.SetAddresses(s) - return true - }) - - ni = ni2 - } + ni := s.state.LocalNodeInfo() + var nodeInfo netmap.NodeInfo + ni.WriteToV2(&nodeInfo) body := new(netmap.LocalNodeInfoResponseBody) body.SetVersion(&s.version) - body.SetNodeInfo(ni) + body.SetNodeInfo(&nodeInfo) resp := new(netmap.LocalNodeInfoResponse) resp.SetBody(body) From 81f4cdbb91589ddab47ecde57992ef8de10e9ec0 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 22 Oct 2024 10:06:16 +0300 Subject: [PATCH 0943/1413] [#1439] object: Sort nodes by priority metrics to compute GET request Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/config.go | 11 + cmd/frostfs-node/config/object/config.go | 20 ++ cmd/frostfs-node/object.go | 6 +- config/example/node.env | 1 + config/example/node.json | 3 + config/example/node.yaml | 4 + docs/storage-node-configuration.md | 14 +- .../object_manager/placement/metrics.go | 43 +++ .../object_manager/placement/traverser.go | 70 ++++- .../placement/traverser_test.go | 288 +++++++++++++++++- 10 files changed, 449 insertions(+), 11 deletions(-) create mode 100644 pkg/services/object_manager/placement/metrics.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index b2dcafbd77..800c491273 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -58,6 +58,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/tombstone" tsourse "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/tombstone/source" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" @@ -109,6 +110,7 @@ type applicationConfiguration struct { ObjectCfg struct { tombstoneLifetime uint64 + priorityMetrics []placement.Metric } EngineCfg struct { @@ -232,6 +234,15 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { // Object a.ObjectCfg.tombstoneLifetime = objectconfig.TombstoneLifetime(c) + var pm []placement.Metric + for _, raw := range objectconfig.Get(c).Priority() { + m, err := placement.ParseMetric(raw) + if err != nil { + return err + } + pm = append(pm, m) + } + a.ObjectCfg.priorityMetrics = pm // Storage Engine diff --git a/cmd/frostfs-node/config/object/config.go b/cmd/frostfs-node/config/object/config.go index 876dc3ef12..6ff1fe2aba 100644 --- a/cmd/frostfs-node/config/object/config.go +++ b/cmd/frostfs-node/config/object/config.go @@ -10,10 +10,17 @@ type PutConfig struct { cfg *config.Config } +// GetConfig is a wrapper over "get" config section which provides access +// to object get pipeline configuration of object service. +type GetConfig struct { + cfg *config.Config +} + const ( subsection = "object" putSubsection = "put" + getSubsection = "get" // PutPoolSizeDefault is a default value of routine pool size to // process object.Put requests in object service. @@ -56,3 +63,16 @@ func (g PutConfig) PoolSizeLocal() int { func (g PutConfig) SkipSessionTokenIssuerVerification() bool { return config.BoolSafe(g.cfg, "skip_session_token_issuer_verification") } + +// Get returns structure that provides access to "get" subsection of +// "object" section. +func Get(c *config.Config) GetConfig { + return GetConfig{ + c.Sub(subsection).Sub(getSubsection), + } +} + +// Priority returns the value of "priority" config parameter. +func (g GetConfig) Priority() []string { + return config.StringSliceSafe(g.cfg, "priority") +} diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index c484c5d8ca..c6bde2cff6 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -178,7 +178,8 @@ func initObjectService(c *cfg) { sSearchV2 := createSearchSvcV2(sSearch, keyStorage) - sGet := createGetService(c, keyStorage, traverseGen, c.clientCache, c.cfgObject.cnrSource) + sGet := createGetService(c, keyStorage, traverseGen, c.clientCache, c.cfgObject.cnrSource, + c.ObjectCfg.priorityMetrics) *c.cfgObject.getSvc = *sGet // need smth better @@ -389,6 +390,7 @@ func createSearchSvcV2(sSearch *searchsvc.Service, keyStorage *util.KeyStorage) func createGetService(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.TraverserGenerator, coreConstructor *cache.ClientCache, containerSource containercore.Source, + priorityMetrics []placement.Metric, ) *getsvc.Service { ls := c.cfgObject.cfgLocalStorage.localStorage @@ -398,6 +400,8 @@ func createGetService(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.Tra ls, traverseGen.WithTraverseOptions( placement.SuccessAfter(1), + placement.WithPriorityMetrics(priorityMetrics), + placement.WithNodeState(c), ), coreConstructor, containerSource, diff --git a/config/example/node.env b/config/example/node.env index 580d343fbb..3979eb18fc 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -87,6 +87,7 @@ FROSTFS_OBJECT_PUT_REMOTE_POOL_SIZE=100 FROSTFS_OBJECT_PUT_LOCAL_POOL_SIZE=200 FROSTFS_OBJECT_PUT_SKIP_SESSION_TOKEN_ISSUER_VERIFICATION=true FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME=10 +FROSTFS_OBJECT_GET_PRIORITY="$attribute:ClusterName $attribute:UN-LOCODE" # Storage engine section FROSTFS_STORAGE_SHARD_POOL_SIZE=15 diff --git a/config/example/node.json b/config/example/node.json index 3470d2d124..1ea28de6cd 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -131,6 +131,9 @@ "remote_pool_size": 100, "local_pool_size": 200, "skip_session_token_issuer_verification": true + }, + "get": { + "priority": ["$attribute:ClusterName", "$attribute:UN-LOCODE"] } }, "storage": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 2a963fc0f3..4a418dfcbc 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -114,6 +114,10 @@ object: remote_pool_size: 100 # number of async workers for remote PUT operations local_pool_size: 200 # number of async workers for local PUT operations skip_session_token_issuer_verification: true # session token issuer verification will be skipped if true + get: + priority: # list of metrics of nodes for prioritization + - $attribute:ClusterName + - $attribute:UN-LOCODE storage: # note: shard configuration can be omitted for relay node (see `node.relay`) diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 2b94400dfe..3635204815 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -407,13 +407,17 @@ Contains object-service related parameters. object: put: remote_pool_size: 100 + get: + priority: + - $attribute:ClusterName ``` -| Parameter | Type | Default value | Description | -|-----------------------------|-------|---------------|------------------------------------------------------------------------------------------------| -| `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. | -| `put.remote_pool_size` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. | -| `put.local_pool_size` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. | +| Parameter | Type | Default value | Description | +|-----------------------------|------------|---------------|------------------------------------------------------------------------------------------------------| +| `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. | +| `put.remote_pool_size` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. | +| `put.local_pool_size` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. | +| `get.priority` | `[]string` | | List of metrics of nodes for prioritization. Used for computing response on GET and SEARCH requests. | # `runtime` section Contains runtime parameters. diff --git a/pkg/services/object_manager/placement/metrics.go b/pkg/services/object_manager/placement/metrics.go new file mode 100644 index 0000000000..45e6df3397 --- /dev/null +++ b/pkg/services/object_manager/placement/metrics.go @@ -0,0 +1,43 @@ +package placement + +import ( + "errors" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" +) + +const ( + attrPrefix = "$attribute:" +) + +type Metric interface { + CalculateValue(*netmap.NodeInfo, *netmap.NodeInfo) int +} + +func ParseMetric(raw string) (Metric, error) { + if attr, found := strings.CutPrefix(raw, attrPrefix); found { + return NewAttributeMetric(attr), nil + } + return nil, errors.New("unsupported priority metric") +} + +// attributeMetric describes priority metric based on attribute. +type attributeMetric struct { + attribute string +} + +// CalculateValue return [0] if from and to contains attribute attributeMetric.attribute and +// the value of attribute is the same. In other case return [1]. +func (am *attributeMetric) CalculateValue(from *netmap.NodeInfo, to *netmap.NodeInfo) int { + fromAttr := from.Attribute(am.attribute) + toAttr := to.Attribute(am.attribute) + if len(fromAttr) > 0 && len(toAttr) > 0 && fromAttr == toAttr { + return 0 + } + return 1 +} + +func NewAttributeMetric(attr string) Metric { + return &attributeMetric{attribute: attr} +} diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 4e790628fa..6440f187db 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -3,6 +3,7 @@ package placement import ( "errors" "fmt" + "slices" "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" @@ -23,6 +24,11 @@ type Builder interface { BuildPlacement(cid.ID, *oid.ID, netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) } +type NodeState interface { + // LocalNodeInfo return current node state in FrostFS API v2 NodeInfo structure. + LocalNodeInfo() *netmap.NodeInfo +} + // Option represents placement traverser option. type Option func(*cfg) @@ -50,6 +56,10 @@ type cfg struct { policy netmap.PlacementPolicy builder Builder + + metrics []Metric + + nodeState NodeState } const invalidOptsMsg = "invalid traverser options" @@ -99,7 +109,22 @@ func NewTraverser(opts ...Option) (*Traverser, error) { } var rem []int - if cfg.flatSuccess != nil { + if len(cfg.metrics) > 0 && cfg.nodeState != nil { + rem = defaultCopiesVector(cfg.policy) + var unsortedVector []netmap.NodeInfo + var regularVector []netmap.NodeInfo + for i := range rem { + unsortedVector = append(unsortedVector, ns[i][:rem[i]]...) + regularVector = append(regularVector, ns[i][rem[i]:]...) + } + rem = []int{-1, -1} + + sortedVector, err := sortVector(cfg, unsortedVector) + if err != nil { + return nil, err + } + ns = [][]netmap.NodeInfo{sortedVector, regularVector} + } else if cfg.flatSuccess != nil { ns = flatNodes(ns) rem = []int{int(*cfg.flatSuccess)} } else { @@ -157,6 +182,35 @@ func flatNodes(ns [][]netmap.NodeInfo) [][]netmap.NodeInfo { return [][]netmap.NodeInfo{flat} } +type nodeMetrics struct { + index int + metrics []int +} + +func sortVector(cfg *cfg, unsortedVector []netmap.NodeInfo) ([]netmap.NodeInfo, error) { + nm := make([]nodeMetrics, len(unsortedVector)) + node := cfg.nodeState.LocalNodeInfo() + + for i := range unsortedVector { + m := make([]int, len(cfg.metrics)) + for j, pm := range cfg.metrics { + m[j] = pm.CalculateValue(node, &unsortedVector[i]) + } + nm[i] = nodeMetrics{ + index: i, + metrics: m, + } + } + slices.SortFunc(nm, func(a, b nodeMetrics) int { + return slices.Compare(a.metrics, b.metrics) + }) + sortedVector := make([]netmap.NodeInfo, len(unsortedVector)) + for i := range unsortedVector { + sortedVector[i] = unsortedVector[nm[i].index] + } + return sortedVector, nil +} + // Node is a descriptor of storage node with information required for intra-container communication. type Node struct { addresses network.AddressGroup @@ -322,3 +376,17 @@ func WithCopyNumbers(v []uint32) Option { c.copyNumbers = v } } + +// WithPriorityMetrics use provided priority metrics to sort nodes. +func WithPriorityMetrics(m []Metric) Option { + return func(c *cfg) { + c.metrics = m + } +} + +// WithNodeState provide state of the current node. +func WithNodeState(s NodeState) Option { + return func(c *cfg) { + c.nodeState = s + } +} diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index b3b57677d9..38f62aa076 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -22,7 +22,9 @@ func (b testBuilder) BuildPlacement(cid.ID, *oid.ID, netmap.PlacementPolicy) ([] } func testNode(v uint32) (n netmap.NodeInfo) { - n.SetNetworkEndpoints("/ip4/0.0.0.0/tcp/" + strconv.Itoa(int(v))) + ip := "/ip4/0.0.0.0/tcp/" + strconv.Itoa(int(v)) + n.SetNetworkEndpoints(ip) + n.SetPublicKey([]byte(ip)) return n } @@ -40,7 +42,15 @@ func copyVectors(v [][]netmap.NodeInfo) [][]netmap.NodeInfo { return vc } -func testPlacement(ss, rs []int) ([][]netmap.NodeInfo, container.Container) { +func testPlacement(ss []int, rs []int) ([][]netmap.NodeInfo, container.Container) { + return placement(ss, rs, nil) +} + +func testECPlacement(ss []int, ec [][]int) ([][]netmap.NodeInfo, container.Container) { + return placement(ss, nil, ec) +} + +func placement(ss []int, rs []int, ec [][]int) ([][]netmap.NodeInfo, container.Container) { nodes := make([][]netmap.NodeInfo, 0, len(rs)) replicas := make([]netmap.ReplicaDescriptor, 0, len(rs)) num := uint32(0) @@ -56,7 +66,12 @@ func testPlacement(ss, rs []int) ([][]netmap.NodeInfo, container.Container) { nodes = append(nodes, ns) var rd netmap.ReplicaDescriptor - rd.SetNumberOfObjects(uint32(rs[i])) + if len(rs) > 0 { + rd.SetNumberOfObjects(uint32(rs[i])) + } else { + rd.SetECDataCount(uint32(ec[i][0])) + rd.SetECParityCount(uint32(ec[i][1])) + } replicas = append(replicas, rd) } @@ -134,7 +149,7 @@ func TestTraverserObjectScenarios(t *testing.T) { err = n.FromIterator(netmapcore.Node(nodes[1][0])) require.NoError(t, err) - require.Equal(t, []Node{{addresses: n}}, tr.Next()) + require.Equal(t, []Node{{addresses: n, key: []byte("/ip4/0.0.0.0/tcp/5")}}, tr.Next()) }) t.Run("put scenario", func(t *testing.T) { @@ -275,3 +290,268 @@ func TestTraverserRemValues(t *testing.T) { }) } } + +type nodeState struct { + node *netmap.NodeInfo +} + +func (n *nodeState) LocalNodeInfo() *netmap.NodeInfo { + return n.node +} + +func TestTraverserPriorityMetrics(t *testing.T) { + t.Run("one rep one metric", func(t *testing.T) { + selectors := []int{4} + replicas := []int{3} + + nodes, cnr := testPlacement(selectors, replicas) + + // Node_0, PK - ip4/0.0.0.0/tcp/0 + nodes[0][0].SetAttribute("ClusterName", "A") + // Node_1, PK - ip4/0.0.0.0/tcp/1 + nodes[0][1].SetAttribute("ClusterName", "A") + // Node_2, PK - ip4/0.0.0.0/tcp/2 + nodes[0][2].SetAttribute("ClusterName", "B") + // Node_3, PK - ip4/0.0.0.0/tcp/3 + nodes[0][3].SetAttribute("ClusterName", "B") + + sdkNode := testNode(5) + sdkNode.SetAttribute("ClusterName", "B") + + nodesCopy := copyVectors(nodes) + + m := []Metric{NewAttributeMetric("ClusterName")} + + tr, err := NewTraverser( + ForContainer(cnr), + UseBuilder(&testBuilder{ + vectors: nodesCopy, + }), + WithoutSuccessTracking(), + WithPriorityMetrics(m), + WithNodeState(&nodeState{ + node: &sdkNode, + }), + ) + require.NoError(t, err) + + // Without priority metric `ClusterName` the order will be: + // [ {Node_0 A}, {Node_1 A}, {Node_2 B}, {Node_3 B}] + // With priority metric `ClusterName` and current node in cluster B + // the order should be: + // [ {Node_2 B}, {Node_0 A}, {Node_1 A}, {Node_3 B}] + next := tr.Next() + require.NotNil(t, next) + require.Equal(t, 3, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/2", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/0", string(next[1].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/1", string(next[2].PublicKey())) + + next = tr.Next() + // The last node is + require.Equal(t, 1, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/3", string(next[0].PublicKey())) + + next = tr.Next() + require.Nil(t, next) + }) + + t.Run("two reps two metrics", func(t *testing.T) { + selectors := []int{3, 3} + replicas := []int{2, 2} + + nodes, cnr := testPlacement(selectors, replicas) + + // REPLICA #1 + // Node_0, PK - ip4/0.0.0.0/tcp/0 + nodes[0][0].SetAttribute("ClusterName", "A") + nodes[0][0].SetAttribute("UN-LOCODE", "RU LED") + + // Node_1, PK - ip4/0.0.0.0/tcp/1 + nodes[0][1].SetAttribute("ClusterName", "A") + nodes[0][1].SetAttribute("UN-LOCODE", "FI HEL") + + // Node_2, PK - ip4/0.0.0.0/tcp/2 + nodes[0][2].SetAttribute("ClusterName", "A") + nodes[0][2].SetAttribute("UN-LOCODE", "RU LED") + + // REPLICA #2 + // Node_3 ip4/0.0.0.0/tcp/3 + nodes[1][0].SetAttribute("ClusterName", "B") + nodes[1][0].SetAttribute("UN-LOCODE", "RU MOW") + + // Node_4, PK - ip4/0.0.0.0/tcp/4 + nodes[1][1].SetAttribute("ClusterName", "B") + nodes[1][1].SetAttribute("UN-LOCODE", "RU DME") + + // Node_5, PK - ip4/0.0.0.0/tcp/5 + nodes[1][2].SetAttribute("ClusterName", "B") + nodes[1][2].SetAttribute("UN-LOCODE", "RU MOW") + + sdkNode := testNode(9) + sdkNode.SetAttribute("ClusterName", "B") + sdkNode.SetAttribute("UN-LOCODE", "RU DME") + + nodesCopy := copyVectors(nodes) + + m := []Metric{ + NewAttributeMetric("ClusterName"), + NewAttributeMetric("UN-LOCODE"), + } + + tr, err := NewTraverser( + ForContainer(cnr), + UseBuilder(&testBuilder{ + vectors: nodesCopy, + }), + WithoutSuccessTracking(), + WithPriorityMetrics(m), + WithNodeState(&nodeState{ + node: &sdkNode, + }), + ) + require.NoError(t, err) + + // Check that nodes in the same cluster and + // in the same location should be the first in slice. + // Nodes which are follow criteria but stay outside the replica + // should be in the next slice. + + next := tr.Next() + require.Equal(t, 4, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/4", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/3", string(next[1].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/0", string(next[2].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/1", string(next[3].PublicKey())) + + next = tr.Next() + require.Equal(t, 2, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/2", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/5", string(next[1].PublicKey())) + + next = tr.Next() + require.Nil(t, next) + + sdkNode.SetAttribute("ClusterName", "B") + sdkNode.SetAttribute("UN-LOCODE", "RU MOW") + + nodesCopy = copyVectors(nodes) + + tr, err = NewTraverser( + ForContainer(cnr), + UseBuilder(&testBuilder{ + vectors: nodesCopy, + }), + WithoutSuccessTracking(), + WithPriorityMetrics(m), + WithNodeState(&nodeState{ + node: &sdkNode, + }), + ) + require.NoError(t, err) + + next = tr.Next() + require.Equal(t, 4, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/3", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/4", string(next[1].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/0", string(next[2].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/1", string(next[3].PublicKey())) + + next = tr.Next() + require.Equal(t, 2, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/2", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/5", string(next[1].PublicKey())) + + next = tr.Next() + require.Nil(t, next) + + sdkNode.SetAttribute("ClusterName", "A") + sdkNode.SetAttribute("UN-LOCODE", "RU LED") + + nodesCopy = copyVectors(nodes) + + tr, err = NewTraverser( + ForContainer(cnr), + UseBuilder(&testBuilder{ + vectors: nodesCopy, + }), + WithoutSuccessTracking(), + WithPriorityMetrics(m), + WithNodeState(&nodeState{ + node: &sdkNode, + }), + ) + require.NoError(t, err) + + next = tr.Next() + require.Equal(t, 4, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/0", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/1", string(next[1].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/3", string(next[2].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/4", string(next[3].PublicKey())) + + next = tr.Next() + require.Equal(t, 2, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/2", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/5", string(next[1].PublicKey())) + + next = tr.Next() + require.Nil(t, next) + }) + + t.Run("ec container", func(t *testing.T) { + selectors := []int{4} + ec := [][]int{{2, 1}} + + nodes, cnr := testECPlacement(selectors, ec) + + // Node_0, PK - ip4/0.0.0.0/tcp/0 + nodes[0][0].SetAttribute("ClusterName", "A") + // Node_1, PK - ip4/0.0.0.0/tcp/1 + nodes[0][1].SetAttribute("ClusterName", "A") + // Node_2, PK - ip4/0.0.0.0/tcp/2 + nodes[0][2].SetAttribute("ClusterName", "B") + // Node_3, PK - ip4/0.0.0.0/tcp/3 + nodes[0][3].SetAttribute("ClusterName", "B") + + sdkNode := testNode(5) + sdkNode.SetAttribute("ClusterName", "B") + + nodesCopy := copyVectors(nodes) + + m := []Metric{NewAttributeMetric("ClusterName")} + + tr, err := NewTraverser( + ForContainer(cnr), + UseBuilder(&testBuilder{ + vectors: nodesCopy, + }), + WithoutSuccessTracking(), + WithPriorityMetrics(m), + WithNodeState(&nodeState{ + node: &sdkNode, + }), + ) + require.NoError(t, err) + + // Without priority metric `ClusterName` the order will be: + // [ {Node_0 A}, {Node_1 A}, {Node_2 B}, {Node_3 B}] + // With priority metric `ClusterName` and current node in cluster B + // the order should be: + // [ {Node_2 B}, {Node_0 A}, {Node_1 A}, {Node_3 B}] + next := tr.Next() + require.NotNil(t, next) + require.Equal(t, 3, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/2", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/0", string(next[1].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/1", string(next[2].PublicKey())) + + next = tr.Next() + // The last node is + require.Equal(t, 1, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/3", string(next[0].PublicKey())) + + next = tr.Next() + require.Nil(t, next) + }) +} From 433aab12bb170832a8b6607e372d09dafdd6ba84 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 29 Oct 2024 16:14:40 +0300 Subject: [PATCH 0944/1413] [#1455] cli: Handle missing home directory go-homedir library incorrectly handles some of the errors that could occur. It is archived, so no PR, but let's fix it on our side. The scenario in case: executing command in an empty environment. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/root.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/root.go b/cmd/frostfs-cli/modules/root.go index 21c367d29d..c0282586ab 100644 --- a/cmd/frostfs-cli/modules/root.go +++ b/cmd/frostfs-cli/modules/root.go @@ -114,12 +114,14 @@ func initConfig() { } else { // Find home directory. home, err := homedir.Dir() - commonCmd.ExitOnErr(rootCmd, "", err) - - // Search config in `$HOME/.config/frostfs-cli/` with name "config.yaml" - viper.AddConfigPath(filepath.Join(home, ".config", "frostfs-cli")) - viper.SetConfigName("config") - viper.SetConfigType("yaml") + if err != nil { + common.PrintVerbose(rootCmd, "Get homedir: %s", err) + } else { + // Search config in `$HOME/.config/frostfs-cli/` with name "config.yaml" + viper.AddConfigPath(filepath.Join(home, ".config", "frostfs-cli")) + viper.SetConfigName("config") + viper.SetConfigType("yaml") + } } viper.SetEnvPrefix(envPrefix) From d5ee6d30390497b1c60245dc4cae782cad619995 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 29 Oct 2024 17:17:04 +0300 Subject: [PATCH 0945/1413] [#1456] morph: Use DialerSource interface instead of internal struct Signed-off-by: Dmitrii Stepanov --- pkg/morph/client/constructor.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index a8efa76e72..08d16deb45 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -4,11 +4,11 @@ import ( "context" "errors" "fmt" + "net" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" - internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" lru "github.com/hashicorp/golang-lru/v2" @@ -48,7 +48,7 @@ type cfg struct { morphCacheMetrics metrics.MorphCacheMetrics - dialerSource *internalNet.DialerSource + dialerSource DialerSource } const ( @@ -68,6 +68,7 @@ func defaultConfig() *cfg { Scopes: transaction.Global, }, morphCacheMetrics: &morphmetrics.NoopMorphCacheMetrics{}, + dialerSource: &noopDialerSource{}, } } @@ -296,7 +297,17 @@ func WithMorphCacheMetrics(morphCacheMetrics metrics.MorphCacheMetrics) Option { } } -func WithDialerSource(ds *internalNet.DialerSource) Option { +type DialerSource interface { + NetContextDialer() func(context.Context, string, string) (net.Conn, error) +} + +type noopDialerSource struct{} + +func (ds *noopDialerSource) NetContextDialer() func(context.Context, string, string) (net.Conn, error) { + return nil +} + +func WithDialerSource(ds DialerSource) Option { return func(c *cfg) { c.dialerSource = ds } From 87ac3c52797d65f1c46e255c937ffd30b8441d35 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 29 Oct 2024 17:16:21 +0300 Subject: [PATCH 0946/1413] [#1458] object: Make patch not set key before target construction * `SignRequestPrivateKey` field should be initialized either within `newUntrustedTarget` or within `newTrustedTarget`. Otherwise, all requests are signed by local node key that makes impossible to perform patch on non-container node. Signed-off-by: Airat Arifullin --- pkg/services/object/patch/streamer.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index c8ed6fdbfe..677c6610fe 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -113,10 +113,9 @@ func (s *Streamer) init(ctx context.Context, req *objectV2.PatchRequest) error { oV2.GetHeader().SetOwnerID(ownerID) target, err := target.New(objectwriter.Params{ - Config: s.Config, - Common: commonPrm, - Header: objectSDK.NewFromV2(oV2), - SignRequestPrivateKey: s.localNodeKey, + Config: s.Config, + Common: commonPrm, + Header: objectSDK.NewFromV2(oV2), }) if err != nil { return fmt.Errorf("target creation: %w", err) From d28a5d2d7a48084a45b154183c450f219969db69 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 29 Oct 2024 15:47:19 +0300 Subject: [PATCH 0947/1413] [#1448] container/ape: Ignore an error when getting a role When getting a role in the APE checker for the container services, an error may be returned if network maps of the previous two epochs don't have enough nodes to fulfil a container placement policy. It's a logical error, so we should ignore it. Signed-off-by: Aleksey Savchuk --- pkg/services/container/ape.go | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index d92ecf58b1..dd4878331e 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -537,10 +537,7 @@ func (ac *apeChecker) isContainerKey(pk []byte, cnrID cid.ID, cont *containercor return false, err } - in, err := isContainerNode(nm, pk, binCnrID, cont) - if err != nil { - return false, err - } else if in { + if isContainerNode(nm, pk, binCnrID, cont) { return true, nil } @@ -551,24 +548,24 @@ func (ac *apeChecker) isContainerKey(pk []byte, cnrID cid.ID, cont *containercor return false, err } - return isContainerNode(nm, pk, binCnrID, cont) + return isContainerNode(nm, pk, binCnrID, cont), nil } -func isContainerNode(nm *netmapSDK.NetMap, pk, binCnrID []byte, cont *containercore.Container) (bool, error) { - cnrVectors, err := nm.ContainerNodes(cont.Value.PlacementPolicy(), binCnrID) - if err != nil { - return false, err - } +func isContainerNode(nm *netmapSDK.NetMap, pk, binCnrID []byte, cont *containercore.Container) bool { + // It could an error only if the network map doesn't have enough nodes to + // fulfil the policy. It's a logical error that doesn't affect an actor role + // determining, so we ignore it + cnrVectors, _ := nm.ContainerNodes(cont.Value.PlacementPolicy(), binCnrID) for i := range cnrVectors { for j := range cnrVectors[i] { if bytes.Equal(cnrVectors[i][j].PublicKey(), pk) { - return true, nil + return true } } } - return false, nil + return false } func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { From 7ac08523647c7450366a9aa350f05eafecad8c7d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 30 Oct 2024 14:42:09 +0300 Subject: [PATCH 0948/1413] [#1459] .golangci.yml: Add intrange linter, fix issues Signed-off-by: Evgenii Stratonikov --- .golangci.yml | 1 + cmd/frostfs-adm/internal/modules/config/config.go | 2 +- .../internal/modules/morph/generate/generate_test.go | 2 +- .../internal/schema/metabase/records/util.go | 2 +- .../blobstor/blobovniczatree/rebuild_test.go | 6 +++--- pkg/local_object_storage/blobstor/iterate_test.go | 2 +- pkg/local_object_storage/engine/error_test.go | 2 +- pkg/local_object_storage/pilorama/forest_test.go | 2 +- pkg/local_object_storage/shard/control_test.go | 2 +- pkg/local_object_storage/writecache/limiter_test.go | 2 +- pkg/morph/timer/block_test.go | 2 +- pkg/services/object/acl/v2/util_test.go | 2 +- scripts/populate-metabase/internal/generate.go | 10 +++++----- scripts/populate-metabase/internal/populate.go | 8 ++++---- scripts/populate-metabase/main.go | 2 +- 15 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 33cf88d8a4..1235c62b46 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -87,5 +87,6 @@ linters: - perfsprint - testifylint - protogetter + - intrange disable-all: true fast: false diff --git a/cmd/frostfs-adm/internal/modules/config/config.go b/cmd/frostfs-adm/internal/modules/config/config.go index a98245d010..69153f0d78 100644 --- a/cmd/frostfs-adm/internal/modules/config/config.go +++ b/cmd/frostfs-adm/internal/modules/config/config.go @@ -128,7 +128,7 @@ func generateConfigExample(appDir string, credSize int) (string, error) { tmpl.AlphabetDir = filepath.Join(appDir, "alphabet-wallets") var i innerring.GlagoliticLetter - for i = 0; i < innerring.GlagoliticLetter(credSize); i++ { + for i = range innerring.GlagoliticLetter(credSize) { tmpl.Glagolitics = append(tmpl.Glagolitics, i.String()) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go index 1dd6420eba..15af5637bc 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate_test.go @@ -63,7 +63,7 @@ func TestGenerateAlphabet(t *testing.T) { buf.Reset() v.Set(commonflags.AlphabetWalletsFlag, walletDir) require.NoError(t, GenerateAlphabetCmd.Flags().Set(commonflags.AlphabetSizeFlag, strconv.FormatUint(size, 10))) - for i := uint64(0); i < size; i++ { + for i := range uint64(size) { buf.WriteString(strconv.FormatUint(i, 10) + "\r") } diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/util.go b/cmd/frostfs-lens/internal/schema/metabase/records/util.go index f50ebe9513..d15d691462 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/records/util.go +++ b/cmd/frostfs-lens/internal/schema/metabase/records/util.go @@ -11,7 +11,7 @@ func DecodeOIDs(data []byte) ([]oid.ID, error) { size := r.ReadVarUint() oids := make([]oid.ID, size) - for i := uint64(0); i < size; i++ { + for i := range size { if err := oids[i].Decode(r.ReadVarBytes()); err != nil { return nil, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index dfd928aaf8..dff4e9024f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -61,7 +61,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, b.Init()) storageIDs := make(map[oid.Address][]byte) - for i := 0; i < 100; i++ { + for range 100 { obj := blobstortest.NewObject(64 * 1024) // 64KB object data, err := obj.Marshal() require.NoError(t, err) @@ -168,7 +168,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { storageIDs := make(map[oid.Address][]byte) toDelete := make(map[oid.Address][]byte) - for i := 0; i < 100; i++ { // 2 objects for one blobovnicza, so 50 DBs total will be created + for i := range 100 { // 2 objects for one blobovnicza, so 50 DBs total will be created obj := blobstortest.NewObject(64 * 1024) data, err := obj.Marshal() require.NoError(t, err) @@ -236,7 +236,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, b.Init()) storageIDs := make(map[oid.Address][]byte) - for i := 0; i < 100; i++ { // 2 objects for one blobovnicza, so 50 DBs total will be created + for range 100 { // 2 objects for one blobovnicza, so 50 DBs total will be created obj := blobstortest.NewObject(64 * 1024) data, err := obj.Marshal() require.NoError(t, err) diff --git a/pkg/local_object_storage/blobstor/iterate_test.go b/pkg/local_object_storage/blobstor/iterate_test.go index 195d0bd31d..3c9457db2d 100644 --- a/pkg/local_object_storage/blobstor/iterate_test.go +++ b/pkg/local_object_storage/blobstor/iterate_test.go @@ -47,7 +47,7 @@ func TestIterateObjects(t *testing.T) { mObjs := make(map[string]addrData) - for i := uint64(0); i < objNum; i++ { + for i := range uint64(objNum) { sz := smalSz big := i < objNum/2 diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 535435ceb5..1619003a15 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -151,7 +151,7 @@ func TestErrorReporting(t *testing.T) { checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) } - for i := uint32(0); i < 2; i++ { + for i := range uint32(2) { _, err = te.ng.Get(context.Background(), GetPrm{addr: object.AddressOf(obj)}) require.Error(t, err) checkShardState(t, te.ng, te.shards[0].id, errThreshold+i, mode.ReadOnly) diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index 854fe0aadc..fbcc53fb30 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -1081,7 +1081,7 @@ func prepareRandomTree(nodeCount, opCount int) []Move { } func compareForests(t *testing.T, expected, actual Forest, cid cidSDK.ID, treeID string, nodeCount int) { - for i := uint64(0); i < uint64(nodeCount); i++ { + for i := range uint64(nodeCount) { expectedMeta, expectedParent, err := expected.TreeGetMeta(context.Background(), cid, treeID, i) require.NoError(t, err) actualMeta, actualParent, err := actual.TreeGetMeta(context.Background(), cid, treeID, i) diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index 6b9eaa5507..b8f1d44175 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -216,7 +216,7 @@ func TestRefillMetabase(t *testing.T) { locked := make([]oid.ID, 1, 2) locked[0] = oidtest.ID() cnrLocked := cidtest.ID() - for i := uint64(0); i < objNum; i++ { + for range objNum { obj := objecttest.Object() obj.SetType(objectSDK.TypeRegular) diff --git a/pkg/local_object_storage/writecache/limiter_test.go b/pkg/local_object_storage/writecache/limiter_test.go index db99b203a6..1ca3e1156c 100644 --- a/pkg/local_object_storage/writecache/limiter_test.go +++ b/pkg/local_object_storage/writecache/limiter_test.go @@ -14,7 +14,7 @@ func TestLimiter(t *testing.T) { l := newFlushLimiter(uint64(maxSize)) var currSize atomic.Int64 var eg errgroup.Group - for i := 0; i < 10_000; i++ { + for range 10_000 { eg.Go(func() error { defer l.release(single) defer currSize.Add(-1) diff --git a/pkg/morph/timer/block_test.go b/pkg/morph/timer/block_test.go index 7929754c12..ee6091845f 100644 --- a/pkg/morph/timer/block_test.go +++ b/pkg/morph/timer/block_test.go @@ -8,7 +8,7 @@ import ( ) func tickN(t *timer.BlockTimer, n uint32) { - for i := uint32(0); i < n; i++ { + for range n { t.Tick(0) } } diff --git a/pkg/services/object/acl/v2/util_test.go b/pkg/services/object/acl/v2/util_test.go index 4353396830..8c6d01ae9f 100644 --- a/pkg/services/object/acl/v2/util_test.go +++ b/pkg/services/object/acl/v2/util_test.go @@ -50,7 +50,7 @@ func testGenerateMetaHeader(depth uint32, b *acl.BearerToken, s *session.Token) metaHeader.SetBearerToken(b) metaHeader.SetSessionToken(s) - for i := uint32(0); i < depth; i++ { + for range depth { link := metaHeader metaHeader = new(session.RequestMetaHeader) metaHeader.SetOrigin(link) diff --git a/scripts/populate-metabase/internal/generate.go b/scripts/populate-metabase/internal/generate.go index 8a96dcaaa8..f2f8881cfd 100644 --- a/scripts/populate-metabase/internal/generate.go +++ b/scripts/populate-metabase/internal/generate.go @@ -19,7 +19,7 @@ import ( func GeneratePayloadPool(count uint, size uint) [][]byte { var pool [][]byte - for i := uint(0); i < count; i++ { + for range count { payload := make([]byte, size) _, _ = rand.Read(payload) @@ -30,8 +30,8 @@ func GeneratePayloadPool(count uint, size uint) [][]byte { func GenerateAttributePool(count uint) []objectSDK.Attribute { var pool []objectSDK.Attribute - for i := uint(0); i < count; i++ { - for j := uint(0); j < count; j++ { + for i := range count { + for j := range count { attr := *objectSDK.NewAttribute() attr.SetKey(fmt.Sprintf("key%d", i)) attr.SetValue(fmt.Sprintf("value%d", j)) @@ -43,7 +43,7 @@ func GenerateAttributePool(count uint) []objectSDK.Attribute { func GenerateOwnerPool(count uint) []user.ID { var pool []user.ID - for i := uint(0); i < count; i++ { + for range count { pool = append(pool, usertest.ID()) } return pool @@ -118,7 +118,7 @@ func WithPayloadFromPool(pool [][]byte) ObjectOption { func WithAttributesFromPool(pool []objectSDK.Attribute, count uint) ObjectOption { return func(obj *objectSDK.Object) { var attrs []objectSDK.Attribute - for i := uint(0); i < count; i++ { + for range count { attrs = append(attrs, pool[rand.Intn(len(pool))]) } obj.SetAttributes(attrs...) diff --git a/scripts/populate-metabase/internal/populate.go b/scripts/populate-metabase/internal/populate.go index 390c1cdc07..4da23a295d 100644 --- a/scripts/populate-metabase/internal/populate.go +++ b/scripts/populate-metabase/internal/populate.go @@ -29,7 +29,7 @@ func PopulateWithObjects( ) { digits := "0123456789" - for i := uint(0); i < count; i++ { + for range count { obj := factory() id := []byte(fmt.Sprintf( @@ -59,7 +59,7 @@ func PopulateWithBigObjects( count uint, factory func() *objectSDK.Object, ) { - for i := uint(0); i < count; i++ { + for range count { group.Go(func() error { if err := populateWithBigObject(ctx, db, factory); err != nil { return fmt.Errorf("couldn't put a big object: %w", err) @@ -154,7 +154,7 @@ func PopulateGraveyard( wg := &sync.WaitGroup{} wg.Add(int(count)) - for i := uint(0); i < count; i++ { + for range count { obj := factory() prm := meta.PutPrm{} @@ -226,7 +226,7 @@ func PopulateLocked( wg := &sync.WaitGroup{} wg.Add(int(count)) - for i := uint(0); i < count; i++ { + for range count { defer wg.Done() obj := factory() diff --git a/scripts/populate-metabase/main.go b/scripts/populate-metabase/main.go index 2bc7a5553f..6f6b233cf4 100644 --- a/scripts/populate-metabase/main.go +++ b/scripts/populate-metabase/main.go @@ -116,7 +116,7 @@ func populate() (err error) { eg, ctx := errgroup.WithContext(ctx) eg.SetLimit(int(jobs)) - for i := uint(0); i < numContainers; i++ { + for range numContainers { cid := cidtest.ID() for _, typ := range types { From 89892d9754988fce2d826edee7a7c6af949ced64 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 30 Oct 2024 15:13:45 +0300 Subject: [PATCH 0949/1413] [#1459] cli: Simplify slice append Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/internal/client/client.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index dcd67f0d9d..ed9817b86e 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -659,9 +659,7 @@ func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes for { n, ok = rdr.Read(buf) - for i := range n { - list = append(list, buf[i]) - } + list = append(list, buf[:n]...) if !ok { break } From 48862e0e63f0306cbe9556abc8e20bb7da27d399 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 30 Oct 2024 15:33:10 +0300 Subject: [PATCH 0950/1413] [#1459] .golanci.yml: Add tenv linter, fix issues Refs #1309 Signed-off-by: Evgenii Stratonikov --- .golangci.yml | 1 + cmd/frostfs-node/config/calls_test.go | 4 +--- cmd/frostfs-node/config/test/config.go | 14 +------------- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 1235c62b46..57e3b44941 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -88,5 +88,6 @@ linters: - testifylint - protogetter - intrange + - tenv disable-all: true fast: false diff --git a/cmd/frostfs-node/config/calls_test.go b/cmd/frostfs-node/config/calls_test.go index 68bf1c6794..bc149eb7d6 100644 --- a/cmd/frostfs-node/config/calls_test.go +++ b/cmd/frostfs-node/config/calls_test.go @@ -1,7 +1,6 @@ package config_test import ( - "os" "strings" "testing" @@ -38,8 +37,7 @@ func TestConfigEnv(t *testing.T) { envName := strings.ToUpper( strings.Join([]string{config.EnvPrefix, section, name}, configViper.EnvSeparator)) - err := os.Setenv(envName, value) - require.NoError(t, err) + t.Setenv(envName, value) c := configtest.EmptyConfig() diff --git a/cmd/frostfs-node/config/test/config.go b/cmd/frostfs-node/config/test/config.go index a93d7e6489..e98c032f00 100644 --- a/cmd/frostfs-node/config/test/config.go +++ b/cmd/frostfs-node/config/test/config.go @@ -11,8 +11,6 @@ import ( ) func fromFile(path string) *config.Config { - os.Clearenv() // ENVs have priority over config files, so we do this in tests - return config.New(path, "", "") } @@ -40,15 +38,6 @@ func ForEachFileType(pref string, f func(*config.Config)) { // ForEnvFileType creates config from `.env` file. func ForEnvFileType(t testing.TB, pref string, f func(*config.Config)) { - envs := os.Environ() - t.Cleanup(func() { - os.Clearenv() - for _, env := range envs { - keyValue := strings.Split(env, "=") - os.Setenv(keyValue[0], keyValue[1]) - } - }) - f(fromEnvFile(t, pref+".env")) } @@ -73,7 +62,6 @@ func loadEnv(t testing.TB, path string) { v = strings.Trim(v, `"`) - err = os.Setenv(k, v) - require.NoError(t, err, "can't set environment variable") + t.Setenv(k, v) } } From e74d05c03f6806cea12e69ce00d84bd69eab5fb7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 30 Oct 2024 17:43:54 +0300 Subject: [PATCH 0951/1413] [#1464] frostfsid: Add cache metrics Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/container.go | 3 ++- cmd/frostfs-node/frostfsid.go | 24 +++++++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 729fcb8afa..f95f671cd4 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -8,6 +8,7 @@ import ( containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" @@ -42,7 +43,7 @@ func initContainerService(_ context.Context, c *cfg) { cacheSize := morphconfig.FrostfsIDCacheSize(c.appCfg) if cacheSize > 0 { - frostfsIDSubjectProvider = newMorphFrostfsIDCache(frostfsIDSubjectProvider, int(cacheSize), c.cfgMorph.cacheTTL) + frostfsIDSubjectProvider = newMorphFrostfsIDCache(frostfsIDSubjectProvider, int(cacheSize), c.cfgMorph.cacheTTL, metrics.NewCacheMetrics("frostfs_id")) } c.shared.frostfsidClient = frostfsIDSubjectProvider diff --git a/cmd/frostfs-node/frostfsid.go b/cmd/frostfs-node/frostfsid.go index fb55a60190..9039915f58 100644 --- a/cmd/frostfs-node/frostfsid.go +++ b/cmd/frostfs-node/frostfsid.go @@ -14,22 +14,29 @@ type morphFrostfsIDCache struct { subjCache *expirable.LRU[util.Uint160, *client.Subject] - subjExtCache *expirable.LRU[util.Uint160, *client.SubjectExtended] + metrics cacheMetrics } -func newMorphFrostfsIDCache(subjProvider frostfsidcore.SubjectProvider, size int, ttl time.Duration) frostfsidcore.SubjectProvider { +func newMorphFrostfsIDCache(subjProvider frostfsidcore.SubjectProvider, size int, ttl time.Duration, metrics cacheMetrics) frostfsidcore.SubjectProvider { return &morphFrostfsIDCache{ subjProvider: subjProvider, subjCache: expirable.NewLRU(size, func(util.Uint160, *client.Subject) {}, ttl), - subjExtCache: expirable.NewLRU(size, func(util.Uint160, *client.SubjectExtended) {}, ttl), + metrics: metrics, } } func (m *morphFrostfsIDCache) GetSubject(addr util.Uint160) (*client.Subject, error) { + hit := false + startedAt := time.Now() + defer func() { + m.metrics.AddMethodDuration("GetSubject", time.Since(startedAt), hit) + }() + result, found := m.subjCache.Get(addr) if found { + hit = true return result, nil } @@ -43,9 +50,16 @@ func (m *morphFrostfsIDCache) GetSubject(addr util.Uint160) (*client.Subject, er } func (m *morphFrostfsIDCache) GetSubjectExtended(addr util.Uint160) (*client.SubjectExtended, error) { - subjExt, found := m.subjExtCache.Get(addr) + hit := false + startedAt := time.Now() + defer func() { + m.metrics.AddMethodDuration("GetSubjectExtended", time.Since(startedAt), hit) + }() + + result, found := m.subjExtCache.Get(addr) if found { - return subjExt, nil + hit = true + return result, nil } var err error From 2285cfc36f1d815e722fb7ef246801a9029efb63 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 30 Oct 2024 17:44:31 +0300 Subject: [PATCH 0952/1413] [#1464] frostfsid: Cache `subject not found` error Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/frostfsid.go | 53 +++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/cmd/frostfs-node/frostfsid.go b/cmd/frostfs-node/frostfsid.go index 9039915f58..3cca091059 100644 --- a/cmd/frostfs-node/frostfsid.go +++ b/cmd/frostfs-node/frostfsid.go @@ -1,6 +1,7 @@ package main import ( + "strings" "time" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" @@ -9,10 +10,22 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" ) +type subjectWithError struct { + subject *client.Subject + err error +} + +type subjectExtWithError struct { + subject *client.SubjectExtended + err error +} + type morphFrostfsIDCache struct { subjProvider frostfsidcore.SubjectProvider - subjCache *expirable.LRU[util.Uint160, *client.Subject] + subjCache *expirable.LRU[util.Uint160, subjectWithError] + + subjExtCache *expirable.LRU[util.Uint160, subjectExtWithError] metrics cacheMetrics } @@ -21,7 +34,9 @@ func newMorphFrostfsIDCache(subjProvider frostfsidcore.SubjectProvider, size int return &morphFrostfsIDCache{ subjProvider: subjProvider, - subjCache: expirable.NewLRU(size, func(util.Uint160, *client.Subject) {}, ttl), + subjCache: expirable.NewLRU(size, func(util.Uint160, subjectWithError) {}, ttl), + + subjExtCache: expirable.NewLRU(size, func(util.Uint160, subjectExtWithError) {}, ttl), metrics: metrics, } @@ -37,16 +52,21 @@ func (m *morphFrostfsIDCache) GetSubject(addr util.Uint160) (*client.Subject, er result, found := m.subjCache.Get(addr) if found { hit = true - return result, nil + return result.subject, result.err } - result, err := m.subjProvider.GetSubject(addr) + subj, err := m.subjProvider.GetSubject(addr) if err != nil { + if m.isCacheableError(err) { + m.subjCache.Add(addr, subjectWithError{ + err: err, + }) + } return nil, err } - m.subjCache.Add(addr, result) - return result, nil + m.subjCache.Add(addr, subjectWithError{subject: subj}) + return subj, nil } func (m *morphFrostfsIDCache) GetSubjectExtended(addr util.Uint160) (*client.SubjectExtended, error) { @@ -59,21 +79,32 @@ func (m *morphFrostfsIDCache) GetSubjectExtended(addr util.Uint160) (*client.Sub result, found := m.subjExtCache.Get(addr) if found { hit = true - return result, nil + return result.subject, result.err } - var err error - subjExt, err = m.subjProvider.GetSubjectExtended(addr) + subjExt, err := m.subjProvider.GetSubjectExtended(addr) if err != nil { + if m.isCacheableError(err) { + m.subjExtCache.Add(addr, subjectExtWithError{ + err: err, + }) + m.subjCache.Add(addr, subjectWithError{ + err: err, + }) + } return nil, err } - m.subjExtCache.Add(addr, subjExt) - m.subjCache.Add(addr, subjectFromSubjectExtended(subjExt)) + m.subjExtCache.Add(addr, subjectExtWithError{subject: subjExt}) + m.subjCache.Add(addr, subjectWithError{subject: subjectFromSubjectExtended(subjExt)}) return subjExt, nil } +func (m *morphFrostfsIDCache) isCacheableError(err error) bool { + return strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) +} + func subjectFromSubjectExtended(subjExt *client.SubjectExtended) *client.Subject { return &client.Subject{ PrimaryKey: subjExt.PrimaryKey, From c2effcc61c5bcb10f58e9d039b12ea0b22a17bba Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 31 Oct 2024 09:13:50 +0300 Subject: [PATCH 0953/1413] [#1465] Makefile: Update golangci-lint, fix warnings Signed-off-by: Evgenii Stratonikov --- Makefile | 2 +- cmd/frostfs-cli/modules/object/nodes.go | 2 +- pkg/local_object_storage/pilorama/boltdb.go | 2 +- pkg/services/object/common/writer/ec.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index d92844bb50..94b1542d57 100755 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.22 -LINT_VERSION ?= 1.60.3 +LINT_VERSION ?= 1.61.0 TRUECLOUDLAB_LINT_VERSION ?= 0.0.7 PROTOC_VERSION ?= 25.0 PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 0eac4e6d26..e6918dfc92 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -195,7 +195,7 @@ func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, member prmHead.SetRawFlag(true) // to get an error instead of whole object eg, egCtx := errgroup.WithContext(cmd.Context()) - for idx := range len(members) { + for idx := range members { partObjID := members[idx] eg.Go(func() error { diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index e2d69cafa4..09f2e1919c 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -705,7 +705,7 @@ func (t *boltForest) applyOperation(logBucket, treeBucket *bbolt.Bucket, ms []*M key, value = c.Prev() } - for i := range len(ms) { + for i := range ms { // Loop invariant: key represents the next stored timestamp after ms[i].Time. // 2. Insert the operation. diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index dffe52a6de..ee0681349d 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -284,7 +284,7 @@ func (e *ECWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx } // try to save to any node not visited by current part - for i := range len(nodes) { + for i := range nodes { select { case <-ctx.Done(): return ctx.Err() From 5bcf81d1cc20408a925c27a9f069bbba6e0a2993 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 31 Oct 2024 10:06:51 +0300 Subject: [PATCH 0954/1413] [#1466] Remove woodpecker CI We use forgejo actions now. Signed-off-by: Evgenii Stratonikov --- .woodpecker/pre-commit.yml | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 .woodpecker/pre-commit.yml diff --git a/.woodpecker/pre-commit.yml b/.woodpecker/pre-commit.yml deleted file mode 100644 index bdf3402de4..0000000000 --- a/.woodpecker/pre-commit.yml +++ /dev/null @@ -1,11 +0,0 @@ -pipeline: - # Kludge for non-root containers under WoodPecker - fix-ownership: - image: alpine:latest - commands: chown -R 1234:1234 . - - pre-commit: - image: git.frostfs.info/truecloudlab/frostfs-ci:v0.36 - commands: - - export HOME="$(getent passwd $(id -u) | cut '-d:' -f6)" - - pre-commit run --hook-stage manual From d19ab43500c24795b9511f0644b706a010983a5a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 30 Oct 2024 16:42:09 +0300 Subject: [PATCH 0955/1413] [#1462] node: Add off-cpu profiler Signed-off-by: Dmitrii Stepanov --- go.mod | 2 ++ go.sum | 14 ++++++++++++++ pkg/util/http/pprof.go | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/go.mod b/go.mod index aefe2889ab..ba9ec375ca 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/cheggaaa/pb v1.0.29 github.com/chzyer/readline v1.5.1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc + github.com/felixge/fgprof v0.9.5 github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/gdamore/tcell/v2 v2.7.4 github.com/go-pkgz/expirable-cache/v3 v3.0.0 @@ -77,6 +78,7 @@ require ( github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect diff --git a/go.sum b/go.sum index 4d44079d4a..a037a99afb 100644 --- a/go.sum +++ b/go.sum @@ -41,6 +41,9 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -68,6 +71,8 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/felixge/fgprof v0.9.5 h1:8+vR6yu2vvSKn08urWyEuxx75NWPEvybbkBirEpsbVY= +github.com/felixge/fgprof v0.9.5/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -91,6 +96,9 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-pkgz/expirable-cache/v3 v3.0.0 h1:u3/gcu3sabLYiTCevoRKv+WzjIn5oo7P8XtiXBeRDLw= github.com/go-pkgz/expirable-cache/v3 v3.0.0/go.mod h1:2OQiDyEGQalYecLWmXprm3maPXeVb5/6/X7yRPYTzec= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -109,6 +117,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q= +github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -130,6 +140,7 @@ github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU 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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= @@ -148,6 +159,7 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= @@ -210,6 +222,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo= github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= @@ -361,6 +374,7 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/pkg/util/http/pprof.go b/pkg/util/http/pprof.go index 7a04130001..f85fd2ea9b 100644 --- a/pkg/util/http/pprof.go +++ b/pkg/util/http/pprof.go @@ -3,8 +3,14 @@ package httputil import ( "net/http" "net/http/pprof" + + "github.com/felixge/fgprof" ) +func init() { + http.DefaultServeMux.Handle("/debug/fgprof", fgprof.Handler()) +} + // initializes pprof package in order to // register Prometheus handlers on http.DefaultServeMux. var _ = pprof.Handler("") From 6c45a17af66843ac5757fcd4b8f8e6acd0bca087 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 31 Oct 2024 13:13:03 +0300 Subject: [PATCH 0956/1413] [#1467] node: Break notary deposit wait after VUB Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/morph.go | 70 ++++++++++++++++++++++---------------- cmd/frostfs-node/netmap.go | 2 +- internal/logs/logs.go | 1 - pkg/innerring/notary.go | 5 +-- pkg/morph/client/client.go | 23 +++++++++++++ pkg/morph/client/notary.go | 17 ++++----- 6 files changed, 77 insertions(+), 41 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index e852090599..0969f55794 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -17,15 +17,16 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/state" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "go.uber.org/zap" ) const ( newEpochNotification = "NewEpoch" - - // amount of tries(blocks) before notary deposit timeout. - notaryDepositRetriesAmount = 300 ) func (c *cfg) initMorphComponents(ctx context.Context) { @@ -128,7 +129,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { return } - tx, err := makeNotaryDeposit(c) + tx, vub, err := makeNotaryDeposit(c) fatalOnErr(err) if tx.Equals(util.Uint256{}) { @@ -139,11 +140,11 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { return } - err = waitNotaryDeposit(ctx, c, tx) + err = waitNotaryDeposit(ctx, c, tx, vub) fatalOnErr(err) } -func makeNotaryDeposit(c *cfg) (util.Uint256, error) { +func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) { const ( // gasMultiplier defines how many times more the notary // balance must be compared to the GAS balance of the node: @@ -157,7 +158,7 @@ func makeNotaryDeposit(c *cfg) (util.Uint256, error) { depositAmount, err := client.CalculateNotaryDepositAmount(c.cfgMorph.client, gasMultiplier, gasDivisor) if err != nil { - return util.Uint256{}, fmt.Errorf("could not calculate notary deposit: %w", err) + return util.Uint256{}, 0, fmt.Errorf("could not calculate notary deposit: %w", err) } return c.cfgMorph.client.DepositEndlessNotary(depositAmount) @@ -168,32 +169,43 @@ var ( errNotaryDepositTimeout = errors.New("notary deposit tx has not appeared in the network") ) -func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256) error { - for range notaryDepositRetriesAmount { - c.log.Debug(logs.ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted) - select { - case <-ctx.Done(): - return ctx.Err() - default: - } +type waiterClient struct { + c *client.Client +} - ok, err := c.cfgMorph.client.TxHalt(tx) - if err == nil { - if ok { - c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) - return nil - } +func (w *waiterClient) Context() context.Context { + return context.Background() +} - return errNotaryDepositFail - } +func (w *waiterClient) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { + return w.c.GetApplicationLog(hash, trig) +} - err = c.cfgMorph.client.Wait(ctx, 1) - if err != nil { - return fmt.Errorf("could not wait for one block in chain: %w", err) - } +func (w *waiterClient) GetBlockCount() (uint32, error) { + return w.c.BlockCount() +} + +func (w *waiterClient) GetVersion() (*result.Version, error) { + return w.c.GetVersion() +} + +func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error { + w, err := waiter.NewPollingBased(&waiterClient{c: c.cfgMorph.client}) + if err != nil { + return fmt.Errorf("could not create notary deposit waiter: %w", err) } - - return errNotaryDepositTimeout + res, err := w.WaitAny(ctx, vub, tx) + if err != nil { + if errors.Is(err, waiter.ErrTxNotAccepted) { + return errNotaryDepositTimeout + } + return fmt.Errorf("could not wait for notary deposit persists in chain: %w", err) + } + if res.Execution.VMState.HasFlag(vmstate.Halt) { + c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) + return nil + } + return errNotaryDepositFail } func listenMorphNotifications(ctx context.Context, c *cfg) { diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 0e05717603..6e2a7c44a7 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -192,7 +192,7 @@ func addNewEpochNotificationHandlers(c *cfg) { if c.cfgMorph.notaryEnabled { addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { - _, err := makeNotaryDeposit(c) + _, _, err := makeNotaryDeposit(c) if err != nil { c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit, zap.String("error", err.Error()), diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 0e9d58f320..e4bac4930f 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -142,7 +142,6 @@ const ( ClientNotaryRequestWithPreparedMainTXInvoked = "notary request with prepared main TX invoked" ClientNotaryRequestInvoked = "notary request invoked" ClientNotaryDepositTransactionWasSuccessfullyPersisted = "notary deposit transaction was successfully persisted" - ClientAttemptToWaitForNotaryDepositTransactionToGetPersisted = "attempt to wait for notary deposit transaction to get persisted" ClientNeoClientInvoke = "neo client invoke" ClientNativeGasTransferInvoke = "native gas transfer invoke" ClientBatchGasTransferInvoke = "batch gas transfer invoke" diff --git a/pkg/innerring/notary.go b/pkg/innerring/notary.go index e6f2b1de4c..5cdbb971c6 100644 --- a/pkg/innerring/notary.go +++ b/pkg/innerring/notary.go @@ -40,13 +40,14 @@ func (s *Server) depositMainNotary() (tx util.Uint256, err error) { ) } -func (s *Server) depositSideNotary() (tx util.Uint256, err error) { +func (s *Server) depositSideNotary() (util.Uint256, error) { depositAmount, err := client.CalculateNotaryDepositAmount(s.morphClient, gasMultiplier, gasDivisor) if err != nil { return util.Uint256{}, fmt.Errorf("could not calculate side notary deposit amount: %w", err) } - return s.morphClient.DepositEndlessNotary(depositAmount) + tx, _, err := s.morphClient.DepositEndlessNotary(depositAmount) + return tx, err } func (s *Server) notaryHandler(_ event.Event) { diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index df521f56bc..933f1039f0 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -19,6 +19,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" @@ -461,6 +462,28 @@ func (c *Client) TxHalt(h util.Uint256) (res bool, err error) { return len(aer.Executions) > 0 && aer.Executions[0].VMState.HasFlag(vmstate.Halt), nil } +func (c *Client) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { + c.switchLock.RLock() + defer c.switchLock.RUnlock() + + if c.inactive { + return nil, ErrConnectionLost + } + + return c.client.GetApplicationLog(hash, trig) +} + +func (c *Client) GetVersion() (*result.Version, error) { + c.switchLock.RLock() + defer c.switchLock.RUnlock() + + if c.inactive { + return nil, ErrConnectionLost + } + + return c.client.GetVersion() +} + // TxHeight returns true if transaction has been successfully executed and persisted. func (c *Client) TxHeight(h util.Uint256) (res uint32, err error) { c.switchLock.RLock() diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 616b3b5c3e..2a500b31b1 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -140,7 +140,7 @@ func (c *Client) ProbeNotary() (res bool) { // use this function. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uint256, err error) { +func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (util.Uint256, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -163,7 +163,8 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin } till := max(int64(bc+delta), currentTill) - return c.depositNotary(amount, till) + res, _, err := c.depositNotary(amount, till) + return res, err } // DepositEndlessNotary calls notary deposit method. Unlike `DepositNotary`, @@ -171,12 +172,12 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (res util.Uin // This allows to avoid ValidAfterDeposit failures. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) DepositEndlessNotary(amount fixedn.Fixed8) (res util.Uint256, err error) { +func (c *Client) DepositEndlessNotary(amount fixedn.Fixed8) (util.Uint256, uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() if c.inactive { - return util.Uint256{}, ErrConnectionLost + return util.Uint256{}, 0, ErrConnectionLost } if c.notary == nil { @@ -187,7 +188,7 @@ func (c *Client) DepositEndlessNotary(amount fixedn.Fixed8) (res util.Uint256, e return c.depositNotary(amount, math.MaxUint32) } -func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (res util.Uint256, err error) { +func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (util.Uint256, uint32, error) { txHash, vub, err := c.gasToken.Transfer( c.accAddr, c.notary.notary, @@ -195,7 +196,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (res util.Uint2 []any{c.acc.PrivateKey().GetScriptHash(), till}) if err != nil { if !errors.Is(err, neorpc.ErrAlreadyExists) { - return util.Uint256{}, fmt.Errorf("can't make notary deposit: %w", err) + return util.Uint256{}, 0, fmt.Errorf("can't make notary deposit: %w", err) } // Transaction is already in mempool waiting to be processed. @@ -205,7 +206,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (res util.Uint2 zap.Int64("expire_at", till), zap.Uint32("vub", vub), zap.Error(err)) - return util.Uint256{}, nil + return util.Uint256{}, 0, nil } c.logger.Info(logs.ClientNotaryDepositInvoke, @@ -214,7 +215,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (res util.Uint2 zap.Uint32("vub", vub), zap.Stringer("tx_hash", txHash.Reverse())) - return txHash, nil + return txHash, vub, nil } // GetNotaryDeposit returns deposit of client's account in notary contract. From 17ec84151b4f9f3d2ff593ecdad41b8c0c860e02 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 5 Nov 2024 16:15:59 +0300 Subject: [PATCH 0957/1413] [#532] cli: Respect XDG base directory spec XDG base directory specification defines where various files should be looked by an application. Hopefully, this makes `frostfs-cli` more predictable and pleasant to work with. Luckily for us, golang already has everything we need in the stdlib. This commit also gets rid of `github.com/mitchellh/go-homedir` dependency. Close #532 Refs #1455 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/root.go | 11 +++++------ go.mod | 1 - go.sum | 2 -- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-cli/modules/root.go b/cmd/frostfs-cli/modules/root.go index c0282586ab..88acab3410 100644 --- a/cmd/frostfs-cli/modules/root.go +++ b/cmd/frostfs-cli/modules/root.go @@ -21,7 +21,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/gendoc" - "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -112,13 +111,13 @@ func initConfig() { // Use config file from the flag. viper.SetConfigFile(cfgFile) } else { - // Find home directory. - home, err := homedir.Dir() + // Find config directory. + configDir, err := os.UserConfigDir() if err != nil { - common.PrintVerbose(rootCmd, "Get homedir: %s", err) + common.PrintVerbose(rootCmd, "Get config dir: %s", err) } else { - // Search config in `$HOME/.config/frostfs-cli/` with name "config.yaml" - viper.AddConfigPath(filepath.Join(home, ".config", "frostfs-cli")) + // Search config in `$XDG_CONFIG_HOME/frostfs-cli/` with name "config.yaml" + viper.AddConfigPath(filepath.Join(configDir, "frostfs-cli")) viper.SetConfigName("config") viper.SetConfigType("yaml") } diff --git a/go.mod b/go.mod index ba9ec375ca..886fa958ff 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,6 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/klauspost/compress v1.17.4 github.com/mailru/easyjson v0.7.7 - github.com/mitchellh/go-homedir v1.1.0 github.com/mr-tron/base58 v1.2.0 github.com/multiformats/go-multiaddr v0.12.1 github.com/nspcc-dev/neo-go v0.106.3 diff --git a/go.sum b/go.sum index a037a99afb..6ed130cdbe 100644 --- a/go.sum +++ b/go.sum @@ -179,8 +179,6 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= From 15102e6dfd3eddca34d83e2264c79d05d665939f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Nov 2024 10:34:16 +0300 Subject: [PATCH 0958/1413] [#1471] Replace sort.Slice in some places MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `slices.SortFunc` doesn't use reflection and is a bit faster. I have done some micro-benchmarks for `[]NodeInfo`: ``` $ benchstat -col "/func" out goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ sort.Slice │ slices.SortFunc │ │ sec/op │ sec/op vs base │ Sort-8 2.130µ ± 2% 1.253µ ± 2% -41.20% (p=0.000 n=10) ``` Haven't included them, though, as they I don't see them being used a lot. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/internal/client/client.go | 5 ++--- cmd/frostfs-cli/internal/common/tracing.go | 10 +++------- pkg/local_object_storage/pilorama/batch.go | 6 +++--- pkg/local_object_storage/pilorama/boltdb.go | 12 ++++++++---- pkg/local_object_storage/pilorama/forest.go | 5 +---- pkg/local_object_storage/pilorama/inmemory.go | 13 ++++++++----- pkg/services/tree/service.go | 9 ++++----- 7 files changed, 29 insertions(+), 31 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index ed9817b86e..948d61f369 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -670,9 +670,8 @@ func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes return nil, fmt.Errorf("read object list: %w", err) } - sort.Slice(list, func(i, j int) bool { - lhs, rhs := list[i].EncodeToString(), list[j].EncodeToString() - return strings.Compare(lhs, rhs) < 0 + slices.SortFunc(list, func(a, b oid.ID) int { + return strings.Compare(a.EncodeToString(), b.EncodeToString()) }) return &SearchObjectsRes{ diff --git a/cmd/frostfs-cli/internal/common/tracing.go b/cmd/frostfs-cli/internal/common/tracing.go index 30c2f2b1a2..10863ed1e1 100644 --- a/cmd/frostfs-cli/internal/common/tracing.go +++ b/cmd/frostfs-cli/internal/common/tracing.go @@ -2,7 +2,7 @@ package common import ( "context" - "sort" + "slices" "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" @@ -45,15 +45,11 @@ func StartClientCommandSpan(cmd *cobra.Command) { }) commonCmd.ExitOnErr(cmd, "init tracing: %w", err) - var components sort.StringSlice + var components []string for c := cmd; c != nil; c = c.Parent() { components = append(components, c.Name()) } - for i, j := 0, len(components)-1; i < j; { - components.Swap(i, j) - i++ - j-- - } + slices.Reverse(components) operation := strings.Join(components, ".") ctx, span := tracing.StartSpanFromContext(cmd.Context(), operation) diff --git a/pkg/local_object_storage/pilorama/batch.go b/pkg/local_object_storage/pilorama/batch.go index 520c6dfb48..4c5238921b 100644 --- a/pkg/local_object_storage/pilorama/batch.go +++ b/pkg/local_object_storage/pilorama/batch.go @@ -1,9 +1,9 @@ package pilorama import ( + "cmp" "encoding/binary" "slices" - "sort" "sync" "time" @@ -48,8 +48,8 @@ func (b *batch) run() { // Sorting without a mutex is ok, because we append to this slice only if timer is non-nil. // See (*boltForest).addBatch for details. - sort.Slice(b.operations, func(i, j int) bool { - return b.operations[i].Time < b.operations[j].Time + slices.SortFunc(b.operations, func(mi, mj *Move) int { + return cmp.Compare(mi.Time, mj.Time) }) b.operations = slices.CompactFunc(b.operations, func(x, y *Move) bool { return x.Time == y.Time }) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 09f2e1919c..7bce1f3405 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -10,7 +10,6 @@ import ( "os" "path/filepath" "slices" - "sort" "strconv" "sync" "time" @@ -1093,14 +1092,19 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr return res, last, metaerr.Wrap(err) } +func sortByFilename(nodes []NodeInfo) { + slices.SortFunc(nodes, func(a, b NodeInfo) int { + return bytes.Compare(a.Meta.GetAttr(AttributeFilename), b.Meta.GetAttr(AttributeFilename)) + }) +} + func sortAndCut(result []NodeInfo, last *string) []NodeInfo { var lastBytes []byte if last != nil { lastBytes = []byte(*last) } - sort.Slice(result, func(i, j int) bool { - return bytes.Compare(result[i].Meta.GetAttr(AttributeFilename), result[j].Meta.GetAttr(AttributeFilename)) == -1 - }) + sortByFilename(result) + for i := range result { if lastBytes == nil || bytes.Compare(lastBytes, result[i].Meta.GetAttr(AttributeFilename)) == -1 { return result[i:] diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index 78503bada6..bb5c22e511 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -1,7 +1,6 @@ package pilorama import ( - "bytes" "context" "errors" "fmt" @@ -192,9 +191,7 @@ func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeI return nil, start, nil } - sort.Slice(res, func(i, j int) bool { - return bytes.Compare(res[i].Meta.GetAttr(AttributeFilename), res[j].Meta.GetAttr(AttributeFilename)) == -1 - }) + sortByFilename(res) r := mergeNodeInfos(res) for i := range r { diff --git a/pkg/local_object_storage/pilorama/inmemory.go b/pkg/local_object_storage/pilorama/inmemory.go index c9f5df3b70..ce7b3db1e9 100644 --- a/pkg/local_object_storage/pilorama/inmemory.go +++ b/pkg/local_object_storage/pilorama/inmemory.go @@ -1,6 +1,9 @@ package pilorama -import "sort" +import ( + "cmp" + "slices" +) // nodeInfo couples parent and metadata. type nodeInfo struct { @@ -131,10 +134,10 @@ func (t tree) getChildren(parent Node) []Node { } } - sort.Slice(children, func(i, j int) bool { - a := t.infoMap[children[i]] - b := t.infoMap[children[j]] - return a.Meta.Time < b.Meta.Time + slices.SortFunc(children, func(ci, cj uint64) int { + a := t.infoMap[ci] + b := t.infoMap[cj] + return cmp.Compare(a.Meta.Time, b.Meta.Time) }) return children } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 10c3b6ccc4..8097d545c6 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -5,7 +5,7 @@ import ( "context" "errors" "fmt" - "sort" + "slices" "sync" "sync/atomic" @@ -575,10 +575,9 @@ func sortByFilename(nodes []pilorama.NodeInfo, d GetSubTreeRequest_Body_Order_Di if len(nodes) == 0 { return nodes, nil } - less := func(i, j int) bool { - return bytes.Compare(nodes[i].Meta.GetAttr(pilorama.AttributeFilename), nodes[j].Meta.GetAttr(pilorama.AttributeFilename)) < 0 - } - sort.Slice(nodes, less) + slices.SortFunc(nodes, func(a, b pilorama.NodeInfo) int { + return bytes.Compare(a.Meta.GetAttr(pilorama.AttributeFilename), b.Meta.GetAttr(pilorama.AttributeFilename)) + }) return nodes, nil default: return nil, fmt.Errorf("unsupported order direction: %s", d.String()) From 33ad753302754c102247424b03ec4d1d8b9042c3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 6 Nov 2024 10:57:01 +0300 Subject: [PATCH 0959/1413] [#1473] policer: Add tracing span To filter HEAD requests from policer. Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/check.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 401977f663..dbc9ea53c8 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -9,14 +9,25 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" policycore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" "go.uber.org/zap" ) func (p *Policer) processObject(ctx context.Context, objInfo objectcore.Info) error { + ctx, span := tracing.StartSpanFromContext(ctx, "Policer.ProcessObject", trace.WithAttributes( + attribute.String("address", objInfo.Address.String()), + attribute.Bool("is_linking_object", objInfo.IsLinkingObject), + attribute.Bool("is_ec_part", objInfo.ECInfo != nil), + attribute.String("type", objInfo.Type.String()), + )) + defer span.End() + cnr, err := p.cnrSrc.Get(objInfo.Address.Container()) if err != nil { if client.IsErrContainerNotFound(err) { From 9902965ff49094c83b755e2f81bd386f2a74c347 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 28 Oct 2024 15:44:47 +0300 Subject: [PATCH 0960/1413] [#1451] writer: Sign EC parts with node's private key As EC put request may be processed only by container node, so sign requests with current node private to not to perform APE checks. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/common/writer/ec.go | 34 ++++++++++++++------ pkg/services/object/common/writer/ec_test.go | 4 +++ pkg/services/object/util/prm.go | 9 +++++- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index ee0681349d..3f7d4d49c7 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -37,10 +37,12 @@ type ECWriter struct { ObjectMeta object.ContentMeta ObjectMetaValid bool + + remoteRequestSignKey *ecdsa.PrivateKey } func (e *ECWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error { - relayed, err := e.relayIfNotContainerNode(ctx, obj) + relayed, isContainerNode, err := e.relayIfNotContainerNode(ctx, obj) if err != nil { return err } @@ -60,23 +62,35 @@ func (e *ECWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error e.ObjectMetaValid = true } + if isContainerNode { + restoreTokens := e.CommonPrm.ForgetTokens() + defer restoreTokens() + // As request executed on container node, so sign request with container key. + e.remoteRequestSignKey, err = e.Config.KeyStorage.GetKey(nil) + if err != nil { + return err + } + } else { + e.remoteRequestSignKey = e.Key + } + if obj.ECHeader() != nil { return e.writeECPart(ctx, obj) } return e.writeRawObject(ctx, obj) } -func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.Object) (bool, error) { - if e.Relay == nil { - return false, nil - } +func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.Object) (bool, bool, error) { currentNodeIsContainerNode, err := e.currentNodeIsContainerNode() if err != nil { - return false, err + return false, false, err } if currentNodeIsContainerNode { // object can be splitted or saved local - return false, nil + return false, true, nil + } + if e.Relay == nil { + return false, currentNodeIsContainerNode, nil } objID := object.AddressOf(obj).Object() var index uint32 @@ -85,9 +99,9 @@ func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.O index = obj.ECHeader().Index() } if err := e.relayToContainerNode(ctx, objID, index); err != nil { - return false, err + return false, false, err } - return true, nil + return true, currentNodeIsContainerNode, nil } func (e *ECWriter) currentNodeIsContainerNode() (bool, error) { @@ -338,7 +352,7 @@ func (e *ECWriter) writePartRemote(ctx context.Context, obj *objectSDK.Object, n client.NodeInfoFromNetmapElement(&clientNodeInfo, node) remoteTaget := remoteWriter{ - privateKey: e.Key, + privateKey: e.remoteRequestSignKey, clientConstructor: e.Config.ClientConstructor, commonPrm: e.CommonPrm, nodeInfo: clientNodeInfo, diff --git a/pkg/services/object/common/writer/ec_test.go b/pkg/services/object/common/writer/ec_test.go index 32863d6787..c828c79ba3 100644 --- a/pkg/services/object/common/writer/ec_test.go +++ b/pkg/services/object/common/writer/ec_test.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" @@ -127,6 +128,8 @@ func TestECWriter(t *testing.T) { ownerKey, err := keys.NewPrivateKey() require.NoError(t, err) + nodeKey, err := keys.NewPrivateKey() + require.NoError(t, err) pool, err := ants.NewPool(4, ants.WithNonblocking(true)) require.NoError(t, err) @@ -141,6 +144,7 @@ func TestECWriter(t *testing.T) { RemotePool: pool, Logger: log, ClientConstructor: clientConstructor{vectors: ns}, + KeyStorage: util.NewKeyStorage(&nodeKey.PrivateKey, nil, nil), }, PlacementOpts: append( []placement.Option{placement.UseBuilder(builder), placement.ForContainer(cnr)}, diff --git a/pkg/services/object/util/prm.go b/pkg/services/object/util/prm.go index 022b9fe5b1..80c0db39ea 100644 --- a/pkg/services/object/util/prm.go +++ b/pkg/services/object/util/prm.go @@ -100,11 +100,18 @@ func (p *CommonPrm) SetNetmapLookupDepth(v uint64) { // ForgetTokens forgets all the tokens read from the request's // meta information before. -func (p *CommonPrm) ForgetTokens() { +func (p *CommonPrm) ForgetTokens() func() { if p != nil { + tk := p.token + br := p.bearer p.token = nil p.bearer = nil + return func() { + p.token = tk + p.bearer = br + } } + return func() {} } func CommonPrmFromV2(req interface { From 5b1ba8e23dfbeae687deb19aaebce316cc266ad9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 28 Oct 2024 15:46:38 +0300 Subject: [PATCH 0961/1413] [#1451] ape: Perform strict APE checks for EC parts Signed-off-by: Dmitrii Stepanov --- pkg/services/object/ape/checker_test.go | 1 + pkg/services/object/ape/request.go | 44 ++++++++++++++++--------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 090f6a83ca..7ebd147f3b 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -695,6 +695,7 @@ func TestPutECChunk(t *testing.T) { nm := &netmapStub{ currentEpoch: 100, netmaps: map[uint64]*netmapSDK.NetMap{ + 99: netmap, 100: netmap, }, } diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index da5307ca7b..d07e590675 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -3,6 +3,7 @@ package ape import ( "context" "crypto/sha256" + "errors" "fmt" "net" "strconv" @@ -11,6 +12,7 @@ import ( aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -24,6 +26,8 @@ import ( var defaultRequest = aperequest.Request{} +var errECMissingParentObjectID = errors.New("missing EC parent object ID") + func nativeSchemaRole(role acl.Role) string { switch role { case acl.RoleOwner: @@ -122,7 +126,10 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re header = headerObjSDK.ToV2().GetHeader() } } - header = c.fillHeaderWithECParent(ctx, prm, header) + header, err := c.fillHeaderWithECParent(ctx, prm, header) + if err != nil { + return defaultRequest, fmt.Errorf("get EC parent header: %w", err) + } reqProps := map[string]string{ nativeschema.PropertyKeyActorPublicKey: prm.SenderKey, nativeschema.PropertyKeyActorRole: prm.Role, @@ -133,7 +140,6 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re reqProps[xheadKey] = xhead.GetValue() } - var err error reqProps, err = c.fillWithUserClaimTags(reqProps, prm) if err != nil { return defaultRequest, err @@ -155,35 +161,43 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re ), nil } -func (c *checkerImpl) fillHeaderWithECParent(ctx context.Context, prm Prm, header *objectV2.Header) *objectV2.Header { +func (c *checkerImpl) fillHeaderWithECParent(ctx context.Context, prm Prm, header *objectV2.Header) (*objectV2.Header, error) { if header == nil { - return header + return header, nil } if header.GetEC() == nil { - return header - } - if prm.Role == nativeschema.PropertyValueContainerRoleContainer || - prm.Role == nativeschema.PropertyValueContainerRoleIR { - return header + return header, nil } parentObjRefID := header.GetEC().Parent if parentObjRefID == nil { - return header + return nil, errECMissingParentObjectID } var parentObjID oid.ID if err := parentObjID.ReadFromV2(*parentObjRefID); err != nil { - return header + return nil, fmt.Errorf("EC parent object ID format error: %w", err) } // only container node have access to collect parent object contNode, err := c.currentNodeIsContainerNode(prm.Container) - if err != nil || !contNode { - return header + if err != nil { + return nil, fmt.Errorf("check container node status: %w", err) + } + if !contNode { + return header, nil } parentObj, err := c.headerProvider.GetHeader(ctx, prm.Container, parentObjID, false) if err != nil { - return header + if isLogicalError(err) { + return header, nil + } + return nil, fmt.Errorf("EC parent header request: %w", err) } - return parentObj.ToV2().GetHeader() + return parentObj.ToV2().GetHeader(), nil +} + +func isLogicalError(err error) bool { + var errObjRemoved *apistatus.ObjectAlreadyRemoved + var errObjNotFound *apistatus.ObjectNotFound + return errors.As(err, &errObjRemoved) || errors.As(err, &errObjNotFound) } func (c *checkerImpl) currentNodeIsContainerNode(cnrID cid.ID) (bool, error) { From 9a77527f46f2db09628bef5b4567ae77cbdb3f69 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 28 Oct 2024 16:18:28 +0300 Subject: [PATCH 0962/1413] [#1451] ape: Drop unused Signed-off-by: Dmitrii Stepanov --- pkg/services/object/ape/checker.go | 3 --- pkg/services/object/ape/request.go | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 3f6cc7c201..8ce1b429d9 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -67,9 +67,6 @@ type Prm struct { // If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow. SoftAPECheck bool - // If true, object headers will not retrieved from storage engine. - WithoutHeaderRequest bool - // The request's bearer token. It is used in order to check APE overrides with the token. BearerToken *bearer.Token diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index d07e590675..e12fccb5e7 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -120,7 +120,7 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re var header *objectV2.Header if prm.Header != nil { header = prm.Header - } else if prm.Object != nil && !prm.WithoutHeaderRequest { + } else if prm.Object != nil { headerObjSDK, err := c.headerProvider.GetHeader(ctx, prm.Container, *prm.Object, true) if err == nil { header = headerObjSDK.ToV2().GetHeader() From 3cf6ea745da38fe2dede263c88275fd4e96576e0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 29 Oct 2024 12:25:59 +0300 Subject: [PATCH 0963/1413] [#1451] ec: Check all parts are saved Signed-off-by: Dmitrii Stepanov --- pkg/services/object/common/writer/ec.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index 3f7d4d49c7..571bae7bbe 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -25,7 +25,10 @@ import ( var _ transformer.ObjectWriter = (*ECWriter)(nil) -var errUnsupportedECObject = errors.New("object is not supported for erasure coding") +var ( + errUnsupportedECObject = errors.New("object is not supported for erasure coding") + errFailedToSaveAllECParts = errors.New("failed to save all EC parts") +) type ECWriter struct { Config *Config @@ -249,6 +252,13 @@ func (e *ECWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er singleErr: err, } } + for idx := range partsProcessed { + if !partsProcessed[idx].Load() { + return errIncompletePut{ + singleErr: errFailedToSaveAllECParts, + } + } + } return nil } From 7edec9193cf7fd3d3f68a7cae3def81247b525eb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 29 Oct 2024 12:39:50 +0300 Subject: [PATCH 0964/1413] [#1451] placement: Return copy of slice from container nodes cache Nodes from cache could be changed by traverser, if no objectID specified. So it is required to return copy of cache's slice. Signed-off-by: Dmitrii Stepanov --- pkg/services/object_manager/placement/cache.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/services/object_manager/placement/cache.go b/pkg/services/object_manager/placement/cache.go index 217261877a..2a8460ca59 100644 --- a/pkg/services/object_manager/placement/cache.go +++ b/pkg/services/object_manager/placement/cache.go @@ -3,6 +3,7 @@ package placement import ( "crypto/sha256" "fmt" + "slices" "sync" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -44,7 +45,7 @@ func (c *ContainerNodesCache) ContainerNodes(nm *netmapSDK.NetMap, cnr cid.ID, p raw, ok := c.containerCache.Get(cnr) c.mtx.Unlock() if ok { - return raw, nil + return c.cloneResult(raw), nil } } else { c.lastEpoch = nm.Epoch() @@ -65,5 +66,13 @@ func (c *ContainerNodesCache) ContainerNodes(nm *netmapSDK.NetMap, cnr cid.ID, p c.containerCache.Add(cnr, cn) } c.mtx.Unlock() - return cn, nil + return c.cloneResult(cn), nil +} + +func (c *ContainerNodesCache) cloneResult(nodes [][]netmapSDK.NodeInfo) [][]netmapSDK.NodeInfo { + result := make([][]netmapSDK.NodeInfo, len(nodes)) + for repIdx := range nodes { + result[repIdx] = slices.Clone(nodes[repIdx]) + } + return result } From c8fb154151c4a944c87bea373fe9828ac267f2ea Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 6 Nov 2024 15:25:02 +0300 Subject: [PATCH 0965/1413] [#1475] Remove container estimation code Signed-off-by: Evgenii Stratonikov --- internal/logs/logs.go | 3 - pkg/innerring/blocktimer.go | 53 +------ pkg/innerring/blocktimer_test.go | 42 +----- pkg/innerring/initialization.go | 15 +- pkg/innerring/innerring.go | 2 +- .../processors/netmap/handlers_test.go | 19 --- .../processors/netmap/process_epoch.go | 15 -- pkg/innerring/processors/netmap/processor.go | 10 -- pkg/morph/client/container/client.go | 6 - pkg/morph/client/container/estimations.go | 54 -------- pkg/morph/client/container/load.go | 131 ------------------ pkg/morph/event/container/estimates.go | 78 ----------- pkg/morph/event/container/estimates_test.go | 80 ----------- 13 files changed, 9 insertions(+), 499 deletions(-) delete mode 100644 pkg/morph/client/container/estimations.go delete mode 100644 pkg/morph/client/container/load.go delete mode 100644 pkg/morph/event/container/estimates.go delete mode 100644 pkg/morph/event/container/estimates_test.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index e4bac4930f..d0bac4d110 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -17,8 +17,6 @@ const ( ) const ( - InnerringNonalphabetModeDoNotStopContainerEstimations = "non-alphabet mode, do not stop container estimations" - InnerringCantStopEpochEstimation = "can't stop epoch estimation" InnerringCantMakeNotaryDepositInMainChain = "can't make notary deposit in main chain" InnerringCantMakeNotaryDepositInSideChain = "can't make notary deposit in side chain" InnerringNotaryDepositHasAlreadyBeenMade = "notary deposit has already been made" @@ -343,7 +341,6 @@ const ( NetmapCantGetTransactionHeight = "can't get transaction height" NetmapCantResetEpochTimer = "can't reset epoch timer" NetmapCantGetNetmapSnapshotToPerformCleanup = "can't get netmap snapshot to perform cleanup" - NetmapCantStartContainerSizeEstimation = "can't start container size estimation" NetmapNonAlphabetModeIgnoreNewEpochTick = "non alphabet mode, ignore new epoch tick" NetmapNextEpoch = "next epoch" NetmapCantInvokeNetmapNewEpoch = "can't invoke netmap.NewEpoch" diff --git a/pkg/innerring/blocktimer.go b/pkg/innerring/blocktimer.go index ad69f207b1..3db5043683 100644 --- a/pkg/innerring/blocktimer.go +++ b/pkg/innerring/blocktimer.go @@ -3,14 +3,10 @@ package innerring import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet" timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/nspcc-dev/neo-go/pkg/util" - "go.uber.org/zap" ) type ( @@ -19,28 +15,12 @@ type ( EpochDuration() uint64 } - alphaState interface { - IsAlphabet() bool - } - newEpochHandler func() - containerEstimationStopper interface { - StopEstimation(p container.StopEstimationPrm) error - } - epochTimerArgs struct { - l *logger.Logger - - alphabetState alphaState - newEpochHandlers []newEpochHandler - cnrWrapper containerEstimationStopper // to invoke stop container estimation - epoch epochState // to specify which epoch to stop, and epoch duration - - stopEstimationDMul uint32 // X: X/Y of epoch in blocks - stopEstimationDDiv uint32 // Y: X/Y of epoch in blocks + epoch epochState // to specify which epoch to stop, and epoch duration } emitTimerArgs struct { @@ -74,7 +54,7 @@ func (s *Server) tickTimers(h uint32) { } func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer { - epochTimer := timer.NewBlockTimer( + return timer.NewBlockTimer( func() (uint32, error) { return uint32(args.epoch.EpochDuration()), nil }, @@ -84,35 +64,6 @@ func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer { } }, ) - - // sub-timer for epoch timer to tick stop container estimation events at - // some block in epoch - epochTimer.OnDelta( - args.stopEstimationDMul, - args.stopEstimationDDiv, - func() { - if !args.alphabetState.IsAlphabet() { - args.l.Debug(logs.InnerringNonalphabetModeDoNotStopContainerEstimations) - return - } - - epochN := args.epoch.EpochCounter() - if epochN == 0 { // estimates are invalid in genesis epoch - return - } - - prm := container.StopEstimationPrm{} - prm.SetEpoch(epochN - 1) - - err := args.cnrWrapper.StopEstimation(prm) - if err != nil { - args.l.Warn(logs.InnerringCantStopEpochEstimation, - zap.Uint64("epoch", epochN), - zap.String("error", err.Error())) - } - }) - - return epochTimer } func newEmissionTimer(args *emitTimerArgs) *timer.BlockTimer { diff --git a/pkg/innerring/blocktimer_test.go b/pkg/innerring/blocktimer_test.go index 242c0903b3..4cbe7e3948 100644 --- a/pkg/innerring/blocktimer_test.go +++ b/pkg/innerring/blocktimer_test.go @@ -3,29 +3,20 @@ package innerring import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "github.com/stretchr/testify/require" ) func TestEpochTimer(t *testing.T) { t.Parallel() - alphaState := &testAlphabetState{isAlphabet: true} neh := &testNewEpochHandler{} - cnrStopper := &testContainerEstStopper{} epochState := &testEpochState{ counter: 99, duration: 10, } args := &epochTimerArgs{ - l: test.NewLogger(t), - alphabetState: alphaState, - newEpochHandlers: []newEpochHandler{neh.Handle}, - cnrWrapper: cnrStopper, - epoch: epochState, - stopEstimationDMul: 2, - stopEstimationDDiv: 10, + newEpochHandlers: []newEpochHandler{neh.Handle}, + epoch: epochState, } et := newEpochTimer(args) err := et.Reset() @@ -33,63 +24,43 @@ func TestEpochTimer(t *testing.T) { et.Tick(100) require.Equal(t, 0, neh.called, "invalid new epoch handler calls") - require.Equal(t, 0, cnrStopper.called, "invalid container stop handler calls") et.Tick(101) require.Equal(t, 0, neh.called, "invalid new epoch handler calls") - require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls") et.Tick(102) require.Equal(t, 0, neh.called, "invalid new epoch handler calls") - require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls") et.Tick(103) require.Equal(t, 0, neh.called, "invalid new epoch handler calls") - require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls") var h uint32 for h = 104; h < 109; h++ { et.Tick(h) require.Equal(t, 0, neh.called, "invalid new epoch handler calls") - require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls") } et.Tick(109) require.Equal(t, 1, neh.called, "invalid new epoch handler calls") - require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls") et.Tick(110) require.Equal(t, 1, neh.called, "invalid new epoch handler calls") - require.Equal(t, 1, cnrStopper.called, "invalid container stop handler calls") et.Tick(111) require.Equal(t, 1, neh.called, "invalid new epoch handler calls") - require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls") et.Tick(112) require.Equal(t, 1, neh.called, "invalid new epoch handler calls") - require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls") et.Tick(113) require.Equal(t, 1, neh.called, "invalid new epoch handler calls") - require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls") for h = 114; h < 119; h++ { et.Tick(h) require.Equal(t, 1, neh.called, "invalid new epoch handler calls") - require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls") } et.Tick(120) require.Equal(t, 2, neh.called, "invalid new epoch handler calls") - require.Equal(t, 2, cnrStopper.called, "invalid container stop handler calls") -} - -type testAlphabetState struct { - isAlphabet bool -} - -func (s *testAlphabetState) IsAlphabet() bool { - return s.isAlphabet } type testNewEpochHandler struct { @@ -100,15 +71,6 @@ func (h *testNewEpochHandler) Handle() { h.called++ } -type testContainerEstStopper struct { - called int -} - -func (s *testContainerEstStopper) StopEstimation(_ container.StopEstimationPrm) error { - s.called++ - return nil -} - type testEpochState struct { counter uint64 duration uint64 diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index cb0654b6e5..d6b474c32a 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -36,7 +36,6 @@ import ( ) func (s *Server) initNetmapProcessor(cfg *viper.Viper, - cnrClient *container.Client, alphaSync event.Handler, ) error { locodeValidator, err := s.newLocodeValidator(cfg) @@ -59,7 +58,6 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper, AlphabetState: s, CleanupEnabled: cfg.GetBool("netmap_cleaner.enabled"), CleanupThreshold: cfg.GetUint64("netmap_cleaner.threshold"), - ContainerWrapper: cnrClient, NotaryDepositHandler: s.onlyAlphabetEventHandler( s.notaryHandler, ), @@ -198,15 +196,10 @@ func (s *Server) createIRFetcher() irFetcher { return irf } -func (s *Server) initTimers(cfg *viper.Viper, morphClients *serverMorphClients) { +func (s *Server) initTimers(cfg *viper.Viper) { s.epochTimer = newEpochTimer(&epochTimerArgs{ - l: s.log, - alphabetState: s, - newEpochHandlers: s.newEpochTickHandlers(), - cnrWrapper: morphClients.CnrClient, - epoch: s, - stopEstimationDMul: cfg.GetUint32("timers.stop_estimation.mul"), - stopEstimationDDiv: cfg.GetUint32("timers.stop_estimation.div"), + newEpochHandlers: s.newEpochTickHandlers(), + epoch: s, }) s.addBlockTimer(s.epochTimer) @@ -425,7 +418,7 @@ func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClien return err } - err = s.initNetmapProcessor(cfg, morphClients.CnrClient, alphaSync) + err = s.initNetmapProcessor(cfg, alphaSync) if err != nil { return err } diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index b943126450..5fae302c41 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -405,7 +405,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan return nil, err } - server.initTimers(cfg, morphClients) + server.initTimers(cfg) err = server.initGRPCServer(cfg, log, audit) if err != nil { diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index 8875880bfc..35f4469b16 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -9,7 +9,6 @@ import ( netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" - cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" @@ -68,7 +67,6 @@ func TestNewEpoch(t *testing.T) { duration: 10, } r := &testEpochResetter{} - cc := &testContainerClient{} nc := &testNetmapClient{ epochDuration: 20, txHeights: map[util.Uint256]uint32{ @@ -82,7 +80,6 @@ func TestNewEpoch(t *testing.T) { p.NotaryDepositHandler = eh.Handle p.AlphabetSyncHandler = eh.Handle p.NetmapClient = nc - p.ContainerWrapper = cc p.EpochTimer = r p.EpochState = es }) @@ -103,11 +100,6 @@ func TestNewEpoch(t *testing.T) { require.Equal(t, ev.Num, es.counter, "invalid epoch counter") require.EqualValues(t, []uint32{nc.txHeights[ev.Hash]}, r.timers, "invalid epoch timer resets") - var expEstimation cntClient.StartEstimationPrm - expEstimation.SetEpoch(ev.Num - 1) - expEstimation.SetHash(ev.Hash) - require.EqualValues(t, []cntClient.StartEstimationPrm{expEstimation}, cc.estimations, "invalid estimations") - require.EqualValues(t, []event.Event{ governance.NewSyncEvent(ev.TxHash()), ev, @@ -274,7 +266,6 @@ func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) { as := &testAlphabetState{ isAlphabet: true, } - cc := &testContainerClient{} nc := &testNetmapClient{} eh := &testEventHandler{} @@ -288,7 +279,6 @@ func newTestProc(t *testing.T, nonDefault func(p *Params)) (*Processor, error) { EpochState: es, EpochTimer: r, AlphabetState: as, - ContainerWrapper: cc, NetmapClient: nc, NotaryDepositHandler: eh.Handle, AlphabetSyncHandler: eh.Handle, @@ -354,15 +344,6 @@ func (s *testAlphabetState) IsAlphabet() bool { return s.isAlphabet } -type testContainerClient struct { - estimations []cntClient.StartEstimationPrm -} - -func (c *testContainerClient) StartEstimation(p cntClient.StartEstimationPrm) error { - c.estimations = append(c.estimations, p) - return nil -} - type notaryInvoke struct { contract util.Uint160 fee fixedn.Fixed8 diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index 4dfa3997b4..9522df26c5 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -3,7 +3,6 @@ package netmap import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" - cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" "go.uber.org/zap" ) @@ -44,20 +43,6 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool { return false } - prm := cntClient.StartEstimationPrm{} - - prm.SetEpoch(epoch - 1) - prm.SetHash(ev.TxHash()) - - if epoch > 0 && np.alphabetState.IsAlphabet() { // estimates are invalid in genesis epoch - err = np.containerWrp.StartEstimation(prm) - if err != nil { - np.log.Warn(logs.NetmapCantStartContainerSizeEstimation, - zap.Uint64("epoch", epoch), - zap.String("error", err.Error())) - } - } - np.netmapSnapshot.update(*networkMap, epoch) np.handleCleanupTick(netmapCleanupTick{epoch: epoch, txHash: ev.TxHash()}) np.handleAlphabetSync(governance.NewSyncEvent(ev.TxHash())) diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index 4cecda59c2..f5a91dee2f 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state" - cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" @@ -65,10 +64,6 @@ type ( MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error } - ContainerClient interface { - StartEstimation(p cntClient.StartEstimationPrm) error - } - // Processor of events produced by network map contract // and new epoch ticker, because it is related to contract. Processor struct { @@ -80,7 +75,6 @@ type ( alphabetState AlphabetState netmapClient Client - containerWrp ContainerClient netmapSnapshot cleanupTable @@ -103,7 +97,6 @@ type ( AlphabetState AlphabetState CleanupEnabled bool CleanupThreshold uint64 // in epochs - ContainerWrapper ContainerClient AlphabetSyncHandler event.Handler NotaryDepositHandler event.Handler @@ -133,8 +126,6 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/netmap: alphabet sync handler is not set") case p.NotaryDepositHandler == nil: return nil, errors.New("ir/netmap: notary deposit handler is not set") - case p.ContainerWrapper == nil: - return nil, errors.New("ir/netmap: container contract wrapper is not set") case p.NodeValidator == nil: return nil, errors.New("ir/netmap: node validator is not set") case p.NodeStateSettings == nil: @@ -161,7 +152,6 @@ func New(p *Params) (*Processor, error) { epochState: p.EpochState, alphabetState: p.AlphabetState, netmapClient: p.NetmapClient, - containerWrp: p.ContainerWrapper, netmapSnapshot: newCleanupTable(p.CleanupEnabled, p.CleanupThreshold), handleAlphabetSync: p.AlphabetSyncHandler, diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index f735a5ff71..b512a6594b 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -30,12 +30,6 @@ const ( eaclMethod = "eACL" deletionInfoMethod = "deletionInfo" - startEstimationMethod = "startContainerEstimation" - stopEstimationMethod = "stopContainerEstimation" - - listSizesMethod = "listContainerSizes" - getSizeMethod = "getContainerSize" - // putNamedMethod is method name for container put with an alias. It is exported to provide custom fee. putNamedMethod = "putNamed" ) diff --git a/pkg/morph/client/container/estimations.go b/pkg/morph/client/container/estimations.go deleted file mode 100644 index f288c63cf5..0000000000 --- a/pkg/morph/client/container/estimations.go +++ /dev/null @@ -1,54 +0,0 @@ -package container - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" -) - -// StartEstimationPrm groups parameters of StartEstimation operation. -type StartEstimationPrm struct { - commonEstimationPrm -} - -// StopEstimationPrm groups parameters of StopEstimation operation. -type StopEstimationPrm struct { - commonEstimationPrm -} - -type commonEstimationPrm struct { - epoch uint64 - - client.InvokePrmOptional -} - -// SetEpoch sets epoch. -func (p *commonEstimationPrm) SetEpoch(epoch uint64) { - p.epoch = epoch -} - -// StartEstimation votes to produce start estimation notification. -func (c *Client) StartEstimation(p StartEstimationPrm) error { - prm := client.InvokePrm{} - prm.SetMethod(startEstimationMethod) - prm.SetArgs(p.epoch) - prm.InvokePrmOptional = p.InvokePrmOptional - - if _, err := c.client.Invoke(prm); err != nil { - return fmt.Errorf("could not invoke method (%s): %w", startEstimationMethod, err) - } - return nil -} - -// StopEstimation votes to produce stop estimation notification. -func (c *Client) StopEstimation(p StopEstimationPrm) error { - prm := client.InvokePrm{} - prm.SetMethod(stopEstimationMethod) - prm.SetArgs(p.epoch) - prm.InvokePrmOptional = p.InvokePrmOptional - - if _, err := c.client.Invoke(prm); err != nil { - return fmt.Errorf("could not invoke method (%s): %w", stopEstimationMethod, err) - } - return nil -} diff --git a/pkg/morph/client/container/load.go b/pkg/morph/client/container/load.go deleted file mode 100644 index 5e2c3c2c3d..0000000000 --- a/pkg/morph/client/container/load.go +++ /dev/null @@ -1,131 +0,0 @@ -package container - -import ( - "fmt" - - v2refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" -) - -// EstimationID is an identity of container load estimation inside Container contract. -type EstimationID []byte - -// ListLoadEstimationsByEpoch returns a list of container load estimations for to the specified epoch. -// The list is composed through Container contract call. -func (c *Client) ListLoadEstimationsByEpoch(epoch uint64) ([]EstimationID, error) { - invokePrm := client.TestInvokePrm{} - invokePrm.SetMethod(listSizesMethod) - invokePrm.SetArgs(epoch) - - prms, err := c.client.TestInvoke(invokePrm) - if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", listSizesMethod, err) - } else if ln := len(prms); ln != 1 { - return nil, fmt.Errorf("unexpected stack item count (%s): %d", listSizesMethod, ln) - } - - prms, err = client.ArrayFromStackItem(prms[0]) - if err != nil { - return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listSizesMethod, err) - } - - res := make([]EstimationID, 0, len(prms)) - for i := range prms { - id, err := client.BytesFromStackItem(prms[i]) - if err != nil { - return nil, fmt.Errorf("could not get ID byte array from stack item (%s): %w", listSizesMethod, err) - } - - res = append(res, id) - } - - return res, nil -} - -// Estimation is a structure of single container load estimation -// reported by storage node. -type Estimation struct { - Size uint64 - - Reporter []byte -} - -// Estimations is a structure of grouped container load estimation inside Container contract. -type Estimations struct { - ContainerID cid.ID - - Values []Estimation -} - -// GetUsedSpaceEstimations returns a list of container load estimations by ID. -// The list is composed through Container contract call. -func (c *Client) GetUsedSpaceEstimations(id EstimationID) (*Estimations, error) { - prm := client.TestInvokePrm{} - prm.SetMethod(getSizeMethod) - prm.SetArgs([]byte(id)) - - prms, err := c.client.TestInvoke(prm) - if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", getSizeMethod, err) - } else if ln := len(prms); ln != 1 { - return nil, fmt.Errorf("unexpected stack item count (%s): %d", getSizeMethod, ln) - } - - prms, err = client.ArrayFromStackItem(prms[0]) - if err != nil { - return nil, fmt.Errorf("could not get stack items of estimation fields from stack item (%s): %w", getSizeMethod, err) - } else if ln := len(prms); ln != 2 { - return nil, fmt.Errorf("unexpected stack item count of estimations fields (%s)", getSizeMethod) - } - - rawCnr, err := client.BytesFromStackItem(prms[0]) - if err != nil { - return nil, fmt.Errorf("could not get container ID byte array from stack item (%s): %w", getSizeMethod, err) - } - - prms, err = client.ArrayFromStackItem(prms[1]) - if err != nil { - return nil, fmt.Errorf("could not get estimation list array from stack item (%s): %w", getSizeMethod, err) - } - - var cnr cid.ID - - err = cnr.Decode(rawCnr) - if err != nil { - return nil, fmt.Errorf("decode container ID: %w", err) - } - - v2 := new(v2refs.ContainerID) - v2.SetValue(rawCnr) - res := &Estimations{ - ContainerID: cnr, - Values: make([]Estimation, 0, len(prms)), - } - - for i := range prms { - arr, err := client.ArrayFromStackItem(prms[i]) - if err != nil { - return nil, fmt.Errorf("could not get estimation struct from stack item (%s): %w", getSizeMethod, err) - } else if ln := len(arr); ln != 2 { - return nil, fmt.Errorf("unexpected stack item count of estimation fields (%s)", getSizeMethod) - } - - reporter, err := client.BytesFromStackItem(arr[0]) - if err != nil { - return nil, fmt.Errorf("could not get reporter byte array from stack item (%s): %w", getSizeMethod, err) - } - - sz, err := client.IntFromStackItem(arr[1]) - if err != nil { - return nil, fmt.Errorf("could not get estimation size from stack item (%s): %w", getSizeMethod, err) - } - - res.Values = append(res.Values, Estimation{ - Reporter: reporter, - Size: uint64(sz), - }) - } - - return res, nil -} diff --git a/pkg/morph/event/container/estimates.go b/pkg/morph/event/container/estimates.go deleted file mode 100644 index 9fd21e2b51..0000000000 --- a/pkg/morph/event/container/estimates.go +++ /dev/null @@ -1,78 +0,0 @@ -package container - -import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" -) - -// StartEstimation structure of container.StartEstimation notification from -// morph chain. -type StartEstimation struct { - epoch uint64 -} - -// StopEstimation structure of container.StopEstimation notification from -// morph chain. -type StopEstimation struct { - epoch uint64 -} - -// MorphEvent implements Neo:Morph Event interface. -func (StartEstimation) MorphEvent() {} - -// MorphEvent implements Neo:Morph Event interface. -func (StopEstimation) MorphEvent() {} - -// Epoch returns epoch value for which to start container size estimation. -func (s StartEstimation) Epoch() uint64 { return s.epoch } - -// Epoch returns epoch value for which to stop container size estimation. -func (s StopEstimation) Epoch() uint64 { return s.epoch } - -// ParseStartEstimation from notification into container event structure. -func ParseStartEstimation(e *state.ContainedNotificationEvent) (event.Event, error) { - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) - } - - epoch, err := parseEstimation(params) - if err != nil { - return nil, err - } - - return StartEstimation{epoch: epoch}, nil -} - -// ParseStopEstimation from notification into container event structure. -func ParseStopEstimation(e *state.ContainedNotificationEvent) (event.Event, error) { - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) - } - - epoch, err := parseEstimation(params) - if err != nil { - return nil, err - } - - return StopEstimation{epoch: epoch}, nil -} - -func parseEstimation(params []stackitem.Item) (uint64, error) { - if ln := len(params); ln != 1 { - return 0, event.WrongNumberOfParameters(1, ln) - } - - // parse container - epoch, err := client.IntFromStackItem(params[0]) - if err != nil { - return 0, fmt.Errorf("could not get estimation epoch: %w", err) - } - - return uint64(epoch), nil -} diff --git a/pkg/morph/event/container/estimates_test.go b/pkg/morph/event/container/estimates_test.go deleted file mode 100644 index be46e62c4e..0000000000 --- a/pkg/morph/event/container/estimates_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package container - -import ( - "math/big" - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/stretchr/testify/require" -) - -func TestStartEstimation(t *testing.T) { - var epochNum uint64 = 100 - epochItem := stackitem.NewBigInteger(new(big.Int).SetUint64(epochNum)) - - t.Run("wrong number of parameters", func(t *testing.T) { - prms := []stackitem.Item{ - stackitem.NewMap(), - stackitem.NewMap(), - } - - _, err := ParseStartEstimation(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error()) - }) - - t.Run("wrong estimation parameter", func(t *testing.T) { - _, err := ParseStartEstimation(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewMap(), - })) - - require.Error(t, err) - }) - - t.Run("correct behavior", func(t *testing.T) { - ev, err := ParseStartEstimation(createNotifyEventFromItems([]stackitem.Item{ - epochItem, - })) - - require.NoError(t, err) - - require.Equal(t, StartEstimation{ - epochNum, - }, ev) - }) -} - -func TestStopEstimation(t *testing.T) { - var epochNum uint64 = 100 - epochItem := stackitem.NewBigInteger(new(big.Int).SetUint64(epochNum)) - - t.Run("wrong number of parameters", func(t *testing.T) { - prms := []stackitem.Item{ - stackitem.NewMap(), - stackitem.NewMap(), - } - - _, err := ParseStopEstimation(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error()) - }) - - t.Run("wrong estimation parameter", func(t *testing.T) { - _, err := ParseStopEstimation(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewMap(), - })) - - require.Error(t, err) - }) - - t.Run("correct behavior", func(t *testing.T) { - ev, err := ParseStopEstimation(createNotifyEventFromItems([]stackitem.Item{ - epochItem, - })) - - require.NoError(t, err) - - require.Equal(t, StopEstimation{ - epochNum, - }, ev) - }) -} From ef64930feff929fb613e2e90ce16c9fdc7f232ce Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 7 Nov 2024 16:00:20 +0300 Subject: [PATCH 0966/1413] [#1477] ape: Fix EC chunk test Initially, this test was a check that only the container node can assemble an EC object. But the implementation of this test was wrong. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/ape/checker_test.go | 56 +++++++++++++++---------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 7ebd147f3b..66f0822e45 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -652,7 +652,7 @@ func (s *testContainerSource) DeletionInfo(cid.ID) (*container.DelInfo, error) { return nil, nil } -func TestPutECChunk(t *testing.T) { +func TestGetECChunk(t *testing.T) { headerProvider := newHeaderProviderMock() frostfsidProvider := newFrostfsIDProviderMock(t) @@ -666,11 +666,10 @@ func TestPutECChunk(t *testing.T) { Rules: []chain.Rule{ { Status: chain.AccessDenied, - Actions: chain.Actions{Names: methodsOptionalOID}, + Actions: chain.Actions{Names: methodsRequiredOID}, Resources: chain.Resources{ Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, }, - Any: true, Condition: []chain.Condition{ { Op: chain.CondStringEquals, @@ -680,17 +679,27 @@ func TestPutECChunk(t *testing.T) { }, }, }, + { + Status: chain.Allow, + Actions: chain.Actions{Names: methodsRequiredOID}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + }, }, - MatchType: chain.MatchTypeFirstMatch, }) node1Key, err := keys.NewPrivateKey() require.NoError(t, err) node1 := netmapSDK.NodeInfo{} node1.SetPublicKey(node1Key.PublicKey().Bytes()) + node2Key, err := keys.NewPrivateKey() + require.NoError(t, err) + node2 := netmapSDK.NodeInfo{} + node2.SetPublicKey(node1Key.PublicKey().Bytes()) netmap := &netmapSDK.NetMap{} netmap.SetEpoch(100) - netmap.SetNodes([]netmapSDK.NodeInfo{node1}) + netmap.SetNodes([]netmapSDK.NodeInfo{node1, node2}) nm := &netmapStub{ currentEpoch: 100, @@ -703,7 +712,7 @@ func TestPutECChunk(t *testing.T) { cont := containerSDK.Container{} cont.Init() pp := netmapSDK.PlacementPolicy{} - require.NoError(t, pp.DecodeString("REP 1")) + require.NoError(t, pp.DecodeString("EC 1.1")) cont.SetPlacementPolicy(pp) cs := &testContainerSource{ containers: map[cid.ID]*container.Container{ @@ -719,7 +728,7 @@ func TestPutECChunk(t *testing.T) { chunkHeader := newHeaderObjectSDK(cnr, obj, nil).ToV2().GetHeader() ecHeader := object.ECHeader{ Index: 1, - Total: 5, + Total: 2, Parent: &refs.ObjectID{}, } chunkHeader.SetEC(&ecHeader) @@ -738,32 +747,33 @@ func TestPutECChunk(t *testing.T) { }) headerProvider.addHeader(cnr, ecParentID, parentHeader) - t.Run("access denied for container node", func(t *testing.T) { + // container node requests EC parent headers, so container node denies access by matching attribute key/value + t.Run("access denied on container node", func(t *testing.T) { prm := Prm{ - Method: nativeschema.MethodPutObject, - Container: cnr, - Object: obj, - Role: role, - SenderKey: senderKey, - Header: chunkHeader, - SoftAPECheck: true, + Method: nativeschema.MethodGetObject, + Container: cnr, + Object: obj, + Role: role, + SenderKey: hex.EncodeToString(node2Key.PublicKey().Bytes()), + Header: chunkHeader, } err = checker.CheckAPE(context.Background(), prm) require.Error(t, err) }) - t.Run("access allowed for non container node", func(t *testing.T) { + + // non container node has no access rights to collect EC parent header, so it uses EC chunk headers + t.Run("access allowed on non container node", func(t *testing.T) { otherKey, err := keys.NewPrivateKey() require.NoError(t, err) checker = NewChecker(ls, ms, headerProvider, frostfsidProvider, nm, &stMock{}, cs, otherKey.PublicKey().Bytes()) prm := Prm{ - Method: nativeschema.MethodPutObject, - Container: cnr, - Object: obj, - Role: nativeschema.PropertyValueContainerRoleOthers, - SenderKey: senderKey, - Header: chunkHeader, - SoftAPECheck: true, + Method: nativeschema.MethodGetObject, + Container: cnr, + Object: obj, + Role: nativeschema.PropertyValueContainerRoleOthers, + SenderKey: senderKey, + Header: chunkHeader, } err = checker.CheckAPE(context.Background(), prm) From 9b13a18aacf6591a6d165ac9b0d070a7940ba45f Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 7 Nov 2024 17:32:10 +0300 Subject: [PATCH 0967/1413] [#1479] go.mod: Bump frostfs-sdk-go version * Update version within go.mod; * Fix deprecated frostfs-api-go/v2 package and use frostfs-sdk-go/api instead. Signed-off-by: Airat Arifullin --- Makefile | 4 ++-- cmd/frostfs-cli/modules/container/create.go | 2 +- cmd/frostfs-cli/modules/control/add_rule.go | 2 +- cmd/frostfs-cli/modules/control/detach_shards.go | 2 +- cmd/frostfs-cli/modules/control/doctor.go | 2 +- cmd/frostfs-cli/modules/control/drop_objects.go | 2 +- cmd/frostfs-cli/modules/control/evacuate_shard.go | 2 +- cmd/frostfs-cli/modules/control/evacuation.go | 2 +- cmd/frostfs-cli/modules/control/flush_cache.go | 2 +- cmd/frostfs-cli/modules/control/get_rule.go | 2 +- cmd/frostfs-cli/modules/control/healthcheck.go | 2 +- cmd/frostfs-cli/modules/control/ir_healthcheck.go | 2 +- .../modules/control/ir_remove_container.go | 4 ++-- cmd/frostfs-cli/modules/control/ir_remove_node.go | 2 +- cmd/frostfs-cli/modules/control/ir_tick_epoch.go | 2 +- cmd/frostfs-cli/modules/control/list_rules.go | 2 +- cmd/frostfs-cli/modules/control/list_targets.go | 2 +- cmd/frostfs-cli/modules/control/rebuild_shards.go | 2 +- cmd/frostfs-cli/modules/control/remove_rule.go | 2 +- cmd/frostfs-cli/modules/control/set_netmap_status.go | 2 +- cmd/frostfs-cli/modules/control/shards_list.go | 2 +- cmd/frostfs-cli/modules/control/shards_set_mode.go | 2 +- cmd/frostfs-cli/modules/control/synchronize_tree.go | 2 +- cmd/frostfs-cli/modules/control/util.go | 2 +- cmd/frostfs-cli/modules/control/writecache.go | 2 +- cmd/frostfs-cli/modules/object/head.go | 2 +- cmd/frostfs-cli/modules/object/lock.go | 2 +- cmd/frostfs-cli/modules/object/put.go | 2 +- cmd/frostfs-node/accounting.go | 2 +- cmd/frostfs-node/apemanager.go | 2 +- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/container.go | 2 +- cmd/frostfs-node/netmap.go | 2 +- cmd/frostfs-node/object.go | 4 ++-- cmd/frostfs-node/session.go | 4 ++-- go.mod | 3 +-- go.sum | 6 ++---- internal/ape/converter.go | 2 +- internal/audit/request.go | 2 +- internal/audit/target.go | 2 +- pkg/core/client/client.go | 2 +- pkg/core/container/delete.go | 2 +- pkg/core/object/fmt.go | 4 ++-- pkg/core/object/fmt_test.go | 2 +- pkg/innerring/processors/netmap/handlers_test.go | 2 +- pkg/innerring/processors/netmap/process_cleanup.go | 2 +- pkg/local_object_storage/engine/lock_test.go | 2 +- pkg/local_object_storage/metabase/db.go | 2 +- pkg/local_object_storage/metabase/db_test.go | 2 +- pkg/local_object_storage/metabase/iterators_test.go | 2 +- pkg/local_object_storage/metabase/put.go | 2 +- pkg/local_object_storage/metabase/select.go | 2 +- pkg/local_object_storage/metabase/select_test.go | 2 +- pkg/local_object_storage/metabase/upgrade.go | 2 +- pkg/local_object_storage/metabase/upgrade_test.go | 2 +- pkg/local_object_storage/shard/gc_test.go | 2 +- pkg/morph/client/container/eacl.go | 2 +- pkg/morph/client/container/get.go | 2 +- pkg/morph/client/container/put.go | 2 +- pkg/network/address.go | 2 +- pkg/network/cache/multi.go | 2 +- pkg/network/transport/accounting/grpc/service.go | 4 ++-- pkg/network/transport/apemanager/grpc/service.go | 4 ++-- pkg/network/transport/container/grpc/service.go | 4 ++-- pkg/network/transport/netmap/grpc/service.go | 4 ++-- pkg/network/transport/object/grpc/get.go | 4 ++-- pkg/network/transport/object/grpc/range.go | 4 ++-- pkg/network/transport/object/grpc/search.go | 4 ++-- pkg/network/transport/object/grpc/service.go | 4 ++-- pkg/network/transport/session/grpc/service.go | 4 ++-- pkg/services/accounting/executor.go | 2 +- pkg/services/accounting/morph/executor.go | 2 +- pkg/services/accounting/server.go | 2 +- pkg/services/accounting/sign.go | 2 +- pkg/services/apemanager/audit.go | 4 ++-- pkg/services/apemanager/executor.go | 8 ++++---- pkg/services/apemanager/server.go | 2 +- pkg/services/apemanager/sign.go | 2 +- pkg/services/container/ape.go | 6 +++--- pkg/services/container/ape_test.go | 8 ++++---- pkg/services/container/audit.go | 4 ++-- pkg/services/container/executor.go | 4 ++-- pkg/services/container/morph/executor.go | 6 +++--- pkg/services/container/morph/executor_test.go | 6 +++--- pkg/services/container/server.go | 2 +- pkg/services/container/sign.go | 2 +- pkg/services/control/convert.go | 4 ++-- pkg/services/control/ir/convert.go | 4 ++-- pkg/services/control/ir/rpc.go | 6 +++--- pkg/services/control/ir/server/audit.go | 2 +- pkg/services/control/ir/server/calls.go | 2 +- pkg/services/control/ir/server/sign.go | 2 +- pkg/services/control/ir/service_frostfs.pb.go | 6 +++--- pkg/services/control/ir/types_frostfs.pb.go | 6 +++--- pkg/services/control/rpc.go | 4 ++-- pkg/services/control/server/ctrlmessage/sign.go | 2 +- pkg/services/control/server/sign.go | 2 +- pkg/services/control/service_frostfs.pb.go | 6 +++--- pkg/services/control/types_frostfs.pb.go | 6 +++--- pkg/services/netmap/executor.go | 4 ++-- pkg/services/netmap/server.go | 2 +- pkg/services/netmap/sign.go | 2 +- pkg/services/object/acl/eacl/v2/eacl_test.go | 6 +++--- pkg/services/object/acl/eacl/v2/headers.go | 8 ++++---- pkg/services/object/acl/eacl/v2/object.go | 2 +- pkg/services/object/acl/eacl/v2/xheader.go | 2 +- pkg/services/object/acl/v2/request.go | 2 +- pkg/services/object/acl/v2/request_test.go | 6 +++--- pkg/services/object/acl/v2/service.go | 4 ++-- pkg/services/object/acl/v2/util.go | 6 +++--- pkg/services/object/acl/v2/util_test.go | 4 ++-- pkg/services/object/ape/checker.go | 4 ++-- pkg/services/object/ape/checker_test.go | 6 +++--- pkg/services/object/ape/request.go | 2 +- pkg/services/object/ape/request_test.go | 2 +- pkg/services/object/ape/service.go | 4 ++-- pkg/services/object/audit.go | 6 +++--- pkg/services/object/common.go | 2 +- pkg/services/object/common/writer/ec_test.go | 2 +- pkg/services/object/delete/exec.go | 2 +- pkg/services/object/delete/v2/service.go | 2 +- pkg/services/object/delete/v2/util.go | 4 ++-- pkg/services/object/get/getrangeec_test.go | 2 +- pkg/services/object/get/v2/errors.go | 4 ++-- pkg/services/object/get/v2/get_forwarder.go | 10 +++++----- pkg/services/object/get/v2/get_range_forwarder.go | 10 +++++----- pkg/services/object/get/v2/get_range_hash.go | 10 +++++----- pkg/services/object/get/v2/head_forwarder.go | 12 ++++++------ pkg/services/object/get/v2/service.go | 2 +- pkg/services/object/get/v2/streamer.go | 2 +- pkg/services/object/get/v2/util.go | 10 +++++----- pkg/services/object/internal/key.go | 2 +- pkg/services/object/metrics.go | 2 +- pkg/services/object/patch/streamer.go | 4 ++-- pkg/services/object/patch/util.go | 4 ++-- pkg/services/object/put/single.go | 10 +++++----- pkg/services/object/put/v2/service.go | 2 +- pkg/services/object/put/v2/streamer.go | 10 +++++----- pkg/services/object/put/v2/util.go | 4 ++-- pkg/services/object/response.go | 2 +- pkg/services/object/search/search_test.go | 2 +- pkg/services/object/search/v2/request_forwarder.go | 10 +++++----- pkg/services/object/search/v2/service.go | 2 +- pkg/services/object/search/v2/streamer.go | 4 ++-- pkg/services/object/search/v2/util.go | 2 +- pkg/services/object/server.go | 2 +- pkg/services/object/sign.go | 2 +- pkg/services/object/transport_splitter.go | 2 +- pkg/services/object/util/key_test.go | 4 ++-- pkg/services/object/util/prm.go | 2 +- pkg/services/object_manager/tombstone/checker.go | 2 +- pkg/services/session/executor.go | 2 +- pkg/services/session/server.go | 2 +- pkg/services/session/sign.go | 2 +- pkg/services/session/storage/persistent/executor.go | 2 +- .../session/storage/persistent/executor_test.go | 4 ++-- pkg/services/session/storage/temporary/executor.go | 2 +- pkg/services/tree/service_frostfs.pb.go | 6 +++--- pkg/services/tree/signature.go | 2 +- pkg/services/tree/signature_test.go | 2 +- pkg/services/tree/types_frostfs.pb.go | 6 +++--- pkg/services/util/response/service.go | 4 ++-- pkg/services/util/sign.go | 4 ++-- 163 files changed, 271 insertions(+), 274 deletions(-) diff --git a/Makefile b/Makefile index 94b1542d57..68a31febe7 100755 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ GO_VERSION ?= 1.22 LINT_VERSION ?= 1.61.0 TRUECLOUDLAB_LINT_VERSION ?= 0.0.7 PROTOC_VERSION ?= 25.0 -PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-api-go/v2) +PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go) PROTOC_OS_VERSION=osx-x86_64 ifeq ($(shell uname), Linux) PROTOC_OS_VERSION=linux-x86_64 @@ -121,7 +121,7 @@ protoc-install: @unzip -q -o $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip -d $(PROTOC_DIR) @rm $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip @echo "⇒ Instaling protogen FrostFS plugin..." - @GOBIN=$(PROTOGEN_FROSTFS_DIR) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/protogen@$(PROTOGEN_FROSTFS_VERSION) + @GOBIN=$(PROTOGEN_FROSTFS_DIR) go install -mod=mod -v git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/protogen@$(PROTOGEN_FROSTFS_VERSION) # Build FrostFS component's docker image image-%: diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index f37b169ce8..017f4b5ce3 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -7,12 +7,12 @@ import ( "strings" "time" - containerApi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + containerApi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index a22d0525df..c648377bd0 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -4,11 +4,11 @@ import ( "encoding/hex" "errors" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/detach_shards.go b/cmd/frostfs-cli/modules/control/detach_shards.go index 5e5b60c3de..025a6e5613 100644 --- a/cmd/frostfs-cli/modules/control/detach_shards.go +++ b/cmd/frostfs-cli/modules/control/detach_shards.go @@ -1,10 +1,10 @@ package control import ( - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/doctor.go b/cmd/frostfs-cli/modules/control/doctor.go index 13bb81a0aa..632cdd6a73 100644 --- a/cmd/frostfs-cli/modules/control/doctor.go +++ b/cmd/frostfs-cli/modules/control/doctor.go @@ -1,10 +1,10 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/drop_objects.go b/cmd/frostfs-cli/modules/control/drop_objects.go index 8c0bb23324..dcc1c12296 100644 --- a/cmd/frostfs-cli/modules/control/drop_objects.go +++ b/cmd/frostfs-cli/modules/control/drop_objects.go @@ -1,10 +1,10 @@ package control import ( - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/evacuate_shard.go b/cmd/frostfs-cli/modules/control/evacuate_shard.go index 458e4cc0b2..1e48c1df42 100644 --- a/cmd/frostfs-cli/modules/control/evacuate_shard.go +++ b/cmd/frostfs-cli/modules/control/evacuate_shard.go @@ -1,10 +1,10 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index fffc5e33e8..73700e56de 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -7,11 +7,11 @@ import ( "sync/atomic" "time" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/flush_cache.go b/cmd/frostfs-cli/modules/control/flush_cache.go index 5419619037..280aacfad4 100644 --- a/cmd/frostfs-cli/modules/control/flush_cache.go +++ b/cmd/frostfs-cli/modules/control/flush_cache.go @@ -1,10 +1,10 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 050cf165c0..4b4d6eef57 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -3,11 +3,11 @@ package control import ( "encoding/hex" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/healthcheck.go b/cmd/frostfs-cli/modules/control/healthcheck.go index 2241a403fb..1d4441f1ed 100644 --- a/cmd/frostfs-cli/modules/control/healthcheck.go +++ b/cmd/frostfs-cli/modules/control/healthcheck.go @@ -3,11 +3,11 @@ package control import ( "os" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/ir_healthcheck.go b/cmd/frostfs-cli/modules/control/ir_healthcheck.go index 4f272c1b4f..373f21c308 100644 --- a/cmd/frostfs-cli/modules/control/ir_healthcheck.go +++ b/cmd/frostfs-cli/modules/control/ir_healthcheck.go @@ -3,12 +3,12 @@ package control import ( "os" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/ir_remove_container.go b/cmd/frostfs-cli/modules/control/ir_remove_container.go index a66d7e06df..460e299e56 100644 --- a/cmd/frostfs-cli/modules/control/ir_remove_container.go +++ b/cmd/frostfs-cli/modules/control/ir_remove_container.go @@ -1,13 +1,13 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/ir_remove_node.go b/cmd/frostfs-cli/modules/control/ir_remove_node.go index 412dc79342..2fe686d639 100644 --- a/cmd/frostfs-cli/modules/control/ir_remove_node.go +++ b/cmd/frostfs-cli/modules/control/ir_remove_node.go @@ -4,11 +4,11 @@ import ( "encoding/hex" "errors" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/ir_tick_epoch.go b/cmd/frostfs-cli/modules/control/ir_tick_epoch.go index 6965b5dcad..5f09e92c13 100644 --- a/cmd/frostfs-cli/modules/control/ir_tick_epoch.go +++ b/cmd/frostfs-cli/modules/control/ir_tick_epoch.go @@ -1,11 +1,11 @@ package control import ( - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" ircontrol "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" ircontrolsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index f5fc27bda1..7162df5e0b 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -5,11 +5,11 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/nspcc-dev/neo-go/cli/input" diff --git a/cmd/frostfs-cli/modules/control/list_targets.go b/cmd/frostfs-cli/modules/control/list_targets.go index 6a988c355e..7c401eb179 100644 --- a/cmd/frostfs-cli/modules/control/list_targets.go +++ b/cmd/frostfs-cli/modules/control/list_targets.go @@ -7,10 +7,10 @@ import ( "strconv" "text/tabwriter" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" "google.golang.org/grpc/codes" diff --git a/cmd/frostfs-cli/modules/control/rebuild_shards.go b/cmd/frostfs-cli/modules/control/rebuild_shards.go index e2b4087124..3df12a15da 100644 --- a/cmd/frostfs-cli/modules/control/rebuild_shards.go +++ b/cmd/frostfs-cli/modules/control/rebuild_shards.go @@ -3,10 +3,10 @@ package control import ( "fmt" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/mr-tron/base58" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index 4189ea76b2..a996156a5e 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -4,10 +4,10 @@ import ( "encoding/hex" "errors" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/set_netmap_status.go b/cmd/frostfs-cli/modules/control/set_netmap_status.go index a107b2b531..87c4f3b3d8 100644 --- a/cmd/frostfs-cli/modules/control/set_netmap_status.go +++ b/cmd/frostfs-cli/modules/control/set_netmap_status.go @@ -6,12 +6,12 @@ import ( "fmt" "time" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/shards_list.go b/cmd/frostfs-cli/modules/control/shards_list.go index a81034a9e9..40d6628ee5 100644 --- a/cmd/frostfs-cli/modules/control/shards_list.go +++ b/cmd/frostfs-cli/modules/control/shards_list.go @@ -7,11 +7,11 @@ import ( "sort" "strings" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/mr-tron/base58" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/shards_set_mode.go b/cmd/frostfs-cli/modules/control/shards_set_mode.go index dd0d77748b..8fe01ba305 100644 --- a/cmd/frostfs-cli/modules/control/shards_set_mode.go +++ b/cmd/frostfs-cli/modules/control/shards_set_mode.go @@ -6,10 +6,10 @@ import ( "slices" "strings" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/mr-tron/base58" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/synchronize_tree.go b/cmd/frostfs-cli/modules/control/synchronize_tree.go index 5f2e4da965..1e4575f49d 100644 --- a/cmd/frostfs-cli/modules/control/synchronize_tree.go +++ b/cmd/frostfs-cli/modules/control/synchronize_tree.go @@ -4,12 +4,12 @@ import ( "crypto/sha256" "errors" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/util.go b/cmd/frostfs-cli/modules/control/util.go index ef547681f3..41d9dbf8a3 100644 --- a/cmd/frostfs-cli/modules/control/util.go +++ b/cmd/frostfs-cli/modules/control/util.go @@ -4,11 +4,11 @@ import ( "crypto/ecdsa" "errors" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" "github.com/spf13/cobra" diff --git a/cmd/frostfs-cli/modules/control/writecache.go b/cmd/frostfs-cli/modules/control/writecache.go index ffe9009ab4..80e4a0c87c 100644 --- a/cmd/frostfs-cli/modules/control/writecache.go +++ b/cmd/frostfs-cli/modules/control/writecache.go @@ -1,10 +1,10 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/mr-tron/base58" "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/object/head.go b/cmd/frostfs-cli/modules/object/head.go index cf2e2d5e66..70c2734433 100644 --- a/cmd/frostfs-cli/modules/object/head.go +++ b/cmd/frostfs-cli/modules/object/head.go @@ -6,12 +6,12 @@ import ( "fmt" "os" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/cmd/frostfs-cli/modules/object/lock.go b/cmd/frostfs-cli/modules/object/lock.go index d2e9af24cf..53dd01868a 100644 --- a/cmd/frostfs-cli/modules/object/lock.go +++ b/cmd/frostfs-cli/modules/object/lock.go @@ -7,12 +7,12 @@ import ( "strconv" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/cmd/frostfs-cli/modules/object/put.go b/cmd/frostfs-cli/modules/object/put.go index 45e02edb34..affe9bbba5 100644 --- a/cmd/frostfs-cli/modules/object/put.go +++ b/cmd/frostfs-cli/modules/object/put.go @@ -10,11 +10,11 @@ import ( "strings" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" diff --git a/cmd/frostfs-node/accounting.go b/cmd/frostfs-node/accounting.go index 1d065c2272..72a6e5331c 100644 --- a/cmd/frostfs-node/accounting.go +++ b/cmd/frostfs-node/accounting.go @@ -4,11 +4,11 @@ import ( "context" "net" - accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" accountingTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/accounting/grpc" accountingService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting" accounting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting/morph" + accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/grpc" "google.golang.org/grpc" ) diff --git a/cmd/frostfs-node/apemanager.go b/cmd/frostfs-node/apemanager.go index 79c45c2546..c4d7725f53 100644 --- a/cmd/frostfs-node/apemanager.go +++ b/cmd/frostfs-node/apemanager.go @@ -3,11 +3,11 @@ package main import ( "net" - apemanager_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc" ape_contract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/contract_storage" morph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" apemanager_transport "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/apemanager/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/apemanager" + apemanager_grpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/grpc" "google.golang.org/grpc" ) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 800c491273..40af238414 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -15,7 +15,6 @@ import ( "syscall" "time" - netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" apiclientconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/apiclient" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/audit" @@ -70,6 +69,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/state" "git.frostfs.info/TrueCloudLab/frostfs-observability/logging/lokicore" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index f95f671cd4..9c35059221 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -5,7 +5,6 @@ import ( "context" "net" - containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" @@ -18,6 +17,7 @@ import ( containerTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/container/grpc" containerService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" containerMorph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/morph" + containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 6e2a7c44a7..58e066fc97 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -8,7 +8,6 @@ import ( "net" "sync/atomic" - netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" @@ -19,6 +18,7 @@ import ( netmapTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/netmap/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" netmapService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/netmap" + netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "go.uber.org/zap" diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index c6bde2cff6..7f26393a77 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -6,8 +6,6 @@ import ( "fmt" "net" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" metricsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/metrics" policerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/policer" replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" @@ -38,6 +36,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/policer" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index ee21ec230c..20d2d318fb 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -6,8 +6,6 @@ import ( "net" "time" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc" nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" @@ -16,6 +14,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/persistent" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/temporary" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "google.golang.org/grpc" ) diff --git a/go.mod b/go.mod index 886fa958ff..8a70c38199 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,11 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3 git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 diff --git a/go.sum b/go.sum index 6ed130cdbe..9778f91e21 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3 h1:6QXNnfBgYx81UZsBdpPnQY+ZMSKGFbFc29wV7DJ/UG4= -git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20241007120543-29c522d5d8a3/go.mod h1:F5GS7hRb62PUy5sTYDC4ajVdeffoAfjHSSHTKUJEaYU= git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0 h1:8Z5iPhieCrbcdhxBuY/Bajh6V5fki7Whh0b4S2zYJYU= git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0/go.mod h1:Y2Xorxc8SBO4phoek7n3XxaPZz5rIrFgDsU4TOjmlGA= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= @@ -10,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 h1:6qCcm1oqFbmf9C5AauXzrL5OPGnTbI9HoB/jAtD9274= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509 h1:5gtEq4bjVgAbTOrbEquspyM3s+qsMtkpGC5m9FtfImk= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241010110344-99c5c5836509/go.mod h1:jmb7yxzZota9jWbC10p+7YR+6wwJPBj7J/Fl5VDkXys= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823 h1:sepm9FeuoInmygH1K/+3L+Yp5bJhGiVi/oGCH6Emp2c= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823/go.mod h1:eoK7+KZQ9GJxbzIs6vTnoUJqFDppavInLRHaN4MYgZg= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= diff --git a/internal/ape/converter.go b/internal/ape/converter.go index eb80e7ded1..c706cf0526 100644 --- a/internal/ape/converter.go +++ b/internal/ape/converter.go @@ -4,7 +4,7 @@ import ( "encoding/hex" "fmt" - v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + v2acl "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" diff --git a/internal/audit/request.go b/internal/audit/request.go index cf07973004..3355087f1a 100644 --- a/internal/audit/request.go +++ b/internal/audit/request.go @@ -1,10 +1,10 @@ package audit import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.uber.org/zap" ) diff --git a/internal/audit/target.go b/internal/audit/target.go index 8bc87ee8e6..2d6881e299 100644 --- a/internal/audit/target.go +++ b/internal/audit/target.go @@ -3,7 +3,7 @@ package audit import ( "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) diff --git a/pkg/core/client/client.go b/pkg/core/client/client.go index 854fbc49fe..98bdf99e78 100644 --- a/pkg/core/client/client.go +++ b/pkg/core/client/client.go @@ -3,8 +3,8 @@ package client import ( "context" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" ) diff --git a/pkg/core/container/delete.go b/pkg/core/container/delete.go index 8e0aaebb97..8c14bdf5e4 100644 --- a/pkg/core/container/delete.go +++ b/pkg/core/container/delete.go @@ -1,7 +1,7 @@ package container import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" ) diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index 317d62cb0a..5bc5c8bea4 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -8,11 +8,11 @@ import ( "fmt" "strconv" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index 77afbfc459..b428b56da7 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -7,9 +7,9 @@ import ( "strconv" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index 35f4469b16..a534581794 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -5,7 +5,6 @@ import ( "testing" "time" - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" netmapContract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" timerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" @@ -13,6 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" diff --git a/pkg/innerring/processors/netmap/process_cleanup.go b/pkg/innerring/processors/netmap/process_cleanup.go index 170c39e2ca..269e79c5e4 100644 --- a/pkg/innerring/processors/netmap/process_cleanup.go +++ b/pkg/innerring/processors/netmap/process_cleanup.go @@ -1,8 +1,8 @@ package netmap import ( - v2netmap "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.uber.org/zap" ) diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 3702f567f5..7e15c76f5d 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -6,12 +6,12 @@ import ( "testing" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/local_object_storage/metabase/db.go b/pkg/local_object_storage/metabase/db.go index 1f444a3ef8..2cd990814c 100644 --- a/pkg/local_object_storage/metabase/db.go +++ b/pkg/local_object_storage/metabase/db.go @@ -11,9 +11,9 @@ import ( "sync" "time" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/mr-tron/base58" "go.etcd.io/bbolt" diff --git a/pkg/local_object_storage/metabase/db_test.go b/pkg/local_object_storage/metabase/db_test.go index 0abb5ea892..c61d762bc3 100644 --- a/pkg/local_object_storage/metabase/db_test.go +++ b/pkg/local_object_storage/metabase/db_test.go @@ -6,10 +6,10 @@ import ( "strconv" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/local_object_storage/metabase/iterators_test.go b/pkg/local_object_storage/metabase/iterators_test.go index 777a94a6f6..646dc196ce 100644 --- a/pkg/local_object_storage/metabase/iterators_test.go +++ b/pkg/local_object_storage/metabase/iterators_test.go @@ -5,10 +5,10 @@ import ( "strconv" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" object2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index b329e80327..09c5e04ad3 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -9,12 +9,12 @@ import ( "strconv" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 41f05b7569..f802036be3 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -8,9 +8,9 @@ import ( "strings" "time" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 5cc25a9f6b..6f48607be9 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -7,10 +7,10 @@ import ( "strconv" "testing" - v2object "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + v2object "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index 1f2c7956bf..bcf72f4400 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -12,8 +12,8 @@ import ( "sync/atomic" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" diff --git a/pkg/local_object_storage/metabase/upgrade_test.go b/pkg/local_object_storage/metabase/upgrade_test.go index 9c525291a4..aeb14aeb6c 100644 --- a/pkg/local_object_storage/metabase/upgrade_test.go +++ b/pkg/local_object_storage/metabase/upgrade_test.go @@ -11,12 +11,12 @@ import ( "testing" "time" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index 90958cd355..2b97111e73 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -5,13 +5,13 @@ import ( "errors" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" diff --git a/pkg/morph/client/container/eacl.go b/pkg/morph/client/container/eacl.go index 8e94550501..9e604e0912 100644 --- a/pkg/morph/client/container/eacl.go +++ b/pkg/morph/client/container/eacl.go @@ -4,9 +4,9 @@ import ( "crypto/sha256" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" diff --git a/pkg/morph/client/container/get.go b/pkg/morph/client/container/get.go index 6715f870f4..ea57a3a957 100644 --- a/pkg/morph/client/container/get.go +++ b/pkg/morph/client/container/get.go @@ -5,10 +5,10 @@ import ( "fmt" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" containerContract "git.frostfs.info/TrueCloudLab/frostfs-contract/container" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" diff --git a/pkg/morph/client/container/put.go b/pkg/morph/client/container/put.go index ee323af008..777ae2d4e4 100644 --- a/pkg/morph/client/container/put.go +++ b/pkg/morph/client/container/put.go @@ -3,9 +3,9 @@ package container import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" ) diff --git a/pkg/network/address.go b/pkg/network/address.go index 88f4a571d8..cb83a813d6 100644 --- a/pkg/network/address.go +++ b/pkg/network/address.go @@ -7,7 +7,7 @@ import ( "net/url" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" ) diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 2ecce3a010..481d1ea4ad 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -7,11 +7,11 @@ import ( "sync" "time" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "google.golang.org/grpc" diff --git a/pkg/network/transport/accounting/grpc/service.go b/pkg/network/transport/accounting/grpc/service.go index 2144a3001e..78129bfbe0 100644 --- a/pkg/network/transport/accounting/grpc/service.go +++ b/pkg/network/transport/accounting/grpc/service.go @@ -3,9 +3,9 @@ package accounting import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" - accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc" accountingsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" + accountingGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting/grpc" ) // Server wraps FrostFS API Accounting service and diff --git a/pkg/network/transport/apemanager/grpc/service.go b/pkg/network/transport/apemanager/grpc/service.go index 59783cfc09..850d38a651 100644 --- a/pkg/network/transport/apemanager/grpc/service.go +++ b/pkg/network/transport/apemanager/grpc/service.go @@ -3,9 +3,9 @@ package apemanager import ( "context" - apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" - apemanager_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc" apemanager_svc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/apemanager" + apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + apemanager_grpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/grpc" ) type Server struct { diff --git a/pkg/network/transport/container/grpc/service.go b/pkg/network/transport/container/grpc/service.go index 9fae22b45a..49d083a906 100644 --- a/pkg/network/transport/container/grpc/service.go +++ b/pkg/network/transport/container/grpc/service.go @@ -3,9 +3,9 @@ package container import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" containersvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + containerGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc" ) // Server wraps FrostFS API Container service and diff --git a/pkg/network/transport/netmap/grpc/service.go b/pkg/network/transport/netmap/grpc/service.go index 406c77e58c..4bc3a42f81 100644 --- a/pkg/network/transport/netmap/grpc/service.go +++ b/pkg/network/transport/netmap/grpc/service.go @@ -3,9 +3,9 @@ package grpc import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc" netmapsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap/grpc" ) // Server wraps FrostFS API Netmap service and diff --git a/pkg/network/transport/object/grpc/get.go b/pkg/network/transport/object/grpc/get.go index e1655c183e..655b1f9fb1 100644 --- a/pkg/network/transport/object/grpc/get.go +++ b/pkg/network/transport/object/grpc/get.go @@ -1,8 +1,8 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" ) type getStreamerV2 struct { diff --git a/pkg/network/transport/object/grpc/range.go b/pkg/network/transport/object/grpc/range.go index 391536e8ef..7d7ce0e4cf 100644 --- a/pkg/network/transport/object/grpc/range.go +++ b/pkg/network/transport/object/grpc/range.go @@ -1,8 +1,8 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" ) type getRangeStreamerV2 struct { diff --git a/pkg/network/transport/object/grpc/search.go b/pkg/network/transport/object/grpc/search.go index a151ced096..8432707f7b 100644 --- a/pkg/network/transport/object/grpc/search.go +++ b/pkg/network/transport/object/grpc/search.go @@ -1,8 +1,8 @@ package object import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" ) type searchStreamerV2 struct { diff --git a/pkg/network/transport/object/grpc/service.go b/pkg/network/transport/object/grpc/service.go index d55e3d87f9..fa62521183 100644 --- a/pkg/network/transport/object/grpc/service.go +++ b/pkg/network/transport/object/grpc/service.go @@ -5,10 +5,10 @@ import ( "errors" "io" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" ) // Server wraps FrostFS API Object service and diff --git a/pkg/network/transport/session/grpc/service.go b/pkg/network/transport/session/grpc/service.go index e0dc749426..6fce397f35 100644 --- a/pkg/network/transport/session/grpc/service.go +++ b/pkg/network/transport/session/grpc/service.go @@ -3,9 +3,9 @@ package session import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc" sessionsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" ) // Server wraps FrostFS API Session service and diff --git a/pkg/services/accounting/executor.go b/pkg/services/accounting/executor.go index b0722cf8a0..93e44c52b8 100644 --- a/pkg/services/accounting/executor.go +++ b/pkg/services/accounting/executor.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" ) type ServiceExecutor interface { diff --git a/pkg/services/accounting/morph/executor.go b/pkg/services/accounting/morph/executor.go index ac836b71d3..b77d3e3e6c 100644 --- a/pkg/services/accounting/morph/executor.go +++ b/pkg/services/accounting/morph/executor.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" accountingSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) diff --git a/pkg/services/accounting/server.go b/pkg/services/accounting/server.go index 72833c46cd..a280416fb9 100644 --- a/pkg/services/accounting/server.go +++ b/pkg/services/accounting/server.go @@ -3,7 +3,7 @@ package accounting import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" ) // Server is an interface of the FrostFS API Accounting service server. diff --git a/pkg/services/accounting/sign.go b/pkg/services/accounting/sign.go index cd6ff0307b..d8feb76bd5 100644 --- a/pkg/services/accounting/sign.go +++ b/pkg/services/accounting/sign.go @@ -4,8 +4,8 @@ import ( "context" "crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/accounting" ) type signService struct { diff --git a/pkg/services/apemanager/audit.go b/pkg/services/apemanager/audit.go index d132ae7dbf..b9bea07fbb 100644 --- a/pkg/services/apemanager/audit.go +++ b/pkg/services/apemanager/audit.go @@ -4,10 +4,10 @@ import ( "context" "sync/atomic" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" - ape_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + ape_grpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager/grpc" ) var _ Server = (*auditService)(nil) diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go index 25f43486a1..86f9cb8935 100644 --- a/pkg/services/apemanager/executor.go +++ b/pkg/services/apemanager/executor.go @@ -8,14 +8,14 @@ import ( "errors" "fmt" - apeV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/ape" - apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" ape_contract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/contract_storage" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" apemanager_errors "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/apemanager/errors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + apeV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/ape" + apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" diff --git a/pkg/services/apemanager/server.go b/pkg/services/apemanager/server.go index 90b2d92aec..e624177ac8 100644 --- a/pkg/services/apemanager/server.go +++ b/pkg/services/apemanager/server.go @@ -3,7 +3,7 @@ package apemanager import ( "context" - apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" + apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" ) type Server interface { diff --git a/pkg/services/apemanager/sign.go b/pkg/services/apemanager/sign.go index eda2a7342f..a172624fff 100644 --- a/pkg/services/apemanager/sign.go +++ b/pkg/services/apemanager/sign.go @@ -4,8 +4,8 @@ import ( "context" "crypto/ecdsa" - apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + apemanager_v2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/apemanager" ) type signService struct { diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index dd4878331e..2cdb30b459 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -12,14 +12,14 @@ import ( "net" "strings" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index d6f9b75ef2..b6b42a559d 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -9,13 +9,13 @@ import ( "net" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + session "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/pkg/services/container/audit.go b/pkg/services/container/audit.go index b257272f52..03d3dc13d4 100644 --- a/pkg/services/container/audit.go +++ b/pkg/services/container/audit.go @@ -4,10 +4,10 @@ import ( "context" "sync/atomic" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - container_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + container_grpc "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container/grpc" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) diff --git a/pkg/services/container/executor.go b/pkg/services/container/executor.go index 0917e3bd08..70234d3de1 100644 --- a/pkg/services/container/executor.go +++ b/pkg/services/container/executor.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" ) type ServiceExecutor interface { diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index 05d8749cf8..adb808af38 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -5,11 +5,11 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" diff --git a/pkg/services/container/morph/executor_test.go b/pkg/services/container/morph/executor_test.go index c64310eb32..87d3073852 100644 --- a/pkg/services/container/morph/executor_test.go +++ b/pkg/services/container/morph/executor_test.go @@ -4,12 +4,12 @@ import ( "context" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container" containerSvcMorph "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container/morph" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" containertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/test" diff --git a/pkg/services/container/server.go b/pkg/services/container/server.go index a19d83c565..78fd3d34ce 100644 --- a/pkg/services/container/server.go +++ b/pkg/services/container/server.go @@ -3,7 +3,7 @@ package container import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" ) // Server is an interface of the FrostFS API Container service server. diff --git a/pkg/services/container/sign.go b/pkg/services/container/sign.go index f7f5d6486e..c478c0e1c9 100644 --- a/pkg/services/container/sign.go +++ b/pkg/services/container/sign.go @@ -4,8 +4,8 @@ import ( "context" "crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" ) type signService struct { diff --git a/pkg/services/control/convert.go b/pkg/services/control/convert.go index fd6f020d1c..37daf67be5 100644 --- a/pkg/services/control/convert.go +++ b/pkg/services/control/convert.go @@ -1,8 +1,8 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" ) type requestWrapper struct { diff --git a/pkg/services/control/ir/convert.go b/pkg/services/control/ir/convert.go index c892c5b6c1..024676b87a 100644 --- a/pkg/services/control/ir/convert.go +++ b/pkg/services/control/ir/convert.go @@ -1,8 +1,8 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/message" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/message" ) type requestWrapper struct { diff --git a/pkg/services/control/ir/rpc.go b/pkg/services/control/ir/rpc.go index 0c9400f6ce..62f800d999 100644 --- a/pkg/services/control/ir/rpc.go +++ b/pkg/services/control/ir/rpc.go @@ -1,9 +1,9 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/common" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/grpc" ) const serviceName = "ircontrol.ControlService" diff --git a/pkg/services/control/ir/server/audit.go b/pkg/services/control/ir/server/audit.go index 9f7a8b8799..e54fa9824c 100644 --- a/pkg/services/control/ir/server/audit.go +++ b/pkg/services/control/ir/server/audit.go @@ -6,10 +6,10 @@ import ( "strings" "sync/atomic" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 642932c913..63be224115 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -5,10 +5,10 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "google.golang.org/grpc/codes" diff --git a/pkg/services/control/ir/server/sign.go b/pkg/services/control/ir/server/sign.go index f72d51f9ec..d39f6d5f95 100644 --- a/pkg/services/control/ir/server/sign.go +++ b/pkg/services/control/ir/server/sign.go @@ -6,8 +6,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" ) diff --git a/pkg/services/control/ir/service_frostfs.pb.go b/pkg/services/control/ir/service_frostfs.pb.go index 66d1966170..ff4ce7245d 100644 --- a/pkg/services/control/ir/service_frostfs.pb.go +++ b/pkg/services/control/ir/service_frostfs.pb.go @@ -5,9 +5,9 @@ package control import ( json "encoding/json" fmt "fmt" - pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" - proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" - encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + pool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/encoding" easyproto "github.com/VictoriaMetrics/easyproto" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" diff --git a/pkg/services/control/ir/types_frostfs.pb.go b/pkg/services/control/ir/types_frostfs.pb.go index b230726a93..32bf457a1d 100644 --- a/pkg/services/control/ir/types_frostfs.pb.go +++ b/pkg/services/control/ir/types_frostfs.pb.go @@ -5,9 +5,9 @@ package control import ( json "encoding/json" fmt "fmt" - pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" - proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" - encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + pool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/encoding" easyproto "github.com/VictoriaMetrics/easyproto" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 04524a68ce..514061db4e 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -1,8 +1,8 @@ package control import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/common" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" ) const serviceName = "control.ControlService" diff --git a/pkg/services/control/server/ctrlmessage/sign.go b/pkg/services/control/server/ctrlmessage/sign.go index 31425b337a..d9d5c5f5ee 100644 --- a/pkg/services/control/server/ctrlmessage/sign.go +++ b/pkg/services/control/server/ctrlmessage/sign.go @@ -4,8 +4,8 @@ import ( "crypto/ecdsa" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" ) diff --git a/pkg/services/control/server/sign.go b/pkg/services/control/server/sign.go index 514af273f2..0e8e24b6e9 100644 --- a/pkg/services/control/server/sign.go +++ b/pkg/services/control/server/sign.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" ) diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index e16f082b13..96b8964781 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -5,9 +5,9 @@ package control import ( json "encoding/json" fmt "fmt" - pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" - proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" - encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + pool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/encoding" easyproto "github.com/VictoriaMetrics/easyproto" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index f921065896..50984f15ad 100644 --- a/pkg/services/control/types_frostfs.pb.go +++ b/pkg/services/control/types_frostfs.pb.go @@ -5,9 +5,9 @@ package control import ( json "encoding/json" fmt "fmt" - pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" - proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" - encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + pool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/encoding" easyproto "github.com/VictoriaMetrics/easyproto" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" diff --git a/pkg/services/netmap/executor.go b/pkg/services/netmap/executor.go index f48357915c..5223047dfb 100644 --- a/pkg/services/netmap/executor.go +++ b/pkg/services/netmap/executor.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" versionsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) diff --git a/pkg/services/netmap/server.go b/pkg/services/netmap/server.go index 0a09c9f44f..eff880dbee 100644 --- a/pkg/services/netmap/server.go +++ b/pkg/services/netmap/server.go @@ -3,7 +3,7 @@ package netmap import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" ) // Server is an interface of the FrostFS API Netmap service server. diff --git a/pkg/services/netmap/sign.go b/pkg/services/netmap/sign.go index 9a16ad8f1f..5f184d5c0f 100644 --- a/pkg/services/netmap/sign.go +++ b/pkg/services/netmap/sign.go @@ -4,8 +4,8 @@ import ( "context" "crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" ) type signService struct { diff --git a/pkg/services/object/acl/eacl/v2/eacl_test.go b/pkg/services/object/acl/eacl/v2/eacl_test.go index 023b992398..94e015abec 100644 --- a/pkg/services/object/acl/eacl/v2/eacl_test.go +++ b/pkg/services/object/acl/eacl/v2/eacl_test.go @@ -6,9 +6,9 @@ import ( "errors" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go index 34975e1e66..ecb793df82 100644 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ b/pkg/services/object/acl/eacl/v2/headers.go @@ -5,10 +5,10 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/services/object/acl/eacl/v2/object.go b/pkg/services/object/acl/eacl/v2/object.go index 72bd4c2d23..92570a3c58 100644 --- a/pkg/services/object/acl/eacl/v2/object.go +++ b/pkg/services/object/acl/eacl/v2/object.go @@ -3,7 +3,7 @@ package v2 import ( "strconv" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/services/object/acl/eacl/v2/xheader.go b/pkg/services/object/acl/eacl/v2/xheader.go index c1fdea9d8c..ce380c117a 100644 --- a/pkg/services/object/acl/eacl/v2/xheader.go +++ b/pkg/services/object/acl/eacl/v2/xheader.go @@ -1,7 +1,7 @@ package v2 import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" ) diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go index 74279e4530..e35cd2e116 100644 --- a/pkg/services/object/acl/v2/request.go +++ b/pkg/services/object/acl/v2/request.go @@ -4,7 +4,7 @@ import ( "crypto/ecdsa" "fmt" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/pkg/services/object/acl/v2/request_test.go b/pkg/services/object/acl/v2/request_test.go index 980d1a2e59..618af3469b 100644 --- a/pkg/services/object/acl/v2/request_test.go +++ b/pkg/services/object/acl/v2/request_test.go @@ -3,9 +3,9 @@ package v2 import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - sigutilV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + sigutilV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 5a8e8b0655..e02a3be36e 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -6,13 +6,13 @@ import ( "fmt" "strings" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" diff --git a/pkg/services/object/acl/v2/util.go b/pkg/services/object/acl/v2/util.go index c5225e8c40..e02f707716 100644 --- a/pkg/services/object/acl/v2/util.go +++ b/pkg/services/object/acl/v2/util.go @@ -6,9 +6,9 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/pkg/services/object/acl/v2/util_test.go b/pkg/services/object/acl/v2/util_test.go index 8c6d01ae9f..4b19cecfef 100644 --- a/pkg/services/object/acl/v2/util_test.go +++ b/pkg/services/object/acl/v2/util_test.go @@ -6,8 +6,8 @@ import ( "crypto/rand" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test" aclsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 8ce1b429d9..abcd2f4bbd 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -5,12 +5,12 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 66f0822e45..e03b5750c2 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -8,13 +8,13 @@ import ( "fmt" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index e12fccb5e7..cb9bbf1b8a 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -8,10 +8,10 @@ import ( "net" "strconv" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index 9dad69d17c..787785b608 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -6,8 +6,8 @@ import ( "net" "testing" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 6eedaf99e8..c114f02f64 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -6,12 +6,12 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/services/object/audit.go b/pkg/services/object/audit.go index 39e1f9f2d5..b420846344 100644 --- a/pkg/services/object/audit.go +++ b/pkg/services/object/audit.go @@ -5,12 +5,12 @@ import ( "errors" "sync/atomic" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) diff --git a/pkg/services/object/common.go b/pkg/services/object/common.go index f48cc5b3d0..758156607b 100644 --- a/pkg/services/object/common.go +++ b/pkg/services/object/common.go @@ -3,7 +3,7 @@ package object import ( "context" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) diff --git a/pkg/services/object/common/writer/ec_test.go b/pkg/services/object/common/writer/ec_test.go index c828c79ba3..8b2599e5fa 100644 --- a/pkg/services/object/common/writer/ec_test.go +++ b/pkg/services/object/common/writer/ec_test.go @@ -10,13 +10,13 @@ import ( "strconv" "testing" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" apiclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index c2f92950fb..ec771320e6 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -6,10 +6,10 @@ import ( "fmt" "strconv" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" apiclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/services/object/delete/v2/service.go b/pkg/services/object/delete/v2/service.go index 10dcd0e874..7146f0361a 100644 --- a/pkg/services/object/delete/v2/service.go +++ b/pkg/services/object/delete/v2/service.go @@ -3,8 +3,8 @@ package deletesvc import ( "context" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" deletesvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) // Service implements Delete operation of Object service v2. diff --git a/pkg/services/object/delete/v2/util.go b/pkg/services/object/delete/v2/util.go index d0db1f543d..c57d4562a8 100644 --- a/pkg/services/object/delete/v2/util.go +++ b/pkg/services/object/delete/v2/util.go @@ -4,10 +4,10 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" deletesvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) diff --git a/pkg/services/object/get/getrangeec_test.go b/pkg/services/object/get/getrangeec_test.go index a6882d4a88..599a6f176f 100644 --- a/pkg/services/object/get/getrangeec_test.go +++ b/pkg/services/object/get/getrangeec_test.go @@ -6,12 +6,12 @@ import ( "fmt" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" coreContainer "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" diff --git a/pkg/services/object/get/v2/errors.go b/pkg/services/object/get/v2/errors.go index 213455e10e..aaa09b891f 100644 --- a/pkg/services/object/get/v2/errors.go +++ b/pkg/services/object/get/v2/errors.go @@ -4,8 +4,8 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refs "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + refs "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" ) var ( diff --git a/pkg/services/object/get/v2/get_forwarder.go b/pkg/services/object/get/v2/get_forwarder.go index 18194c740c..60fcd7fbfc 100644 --- a/pkg/services/object/get/v2/get_forwarder.go +++ b/pkg/services/object/get/v2/get_forwarder.go @@ -7,16 +7,16 @@ import ( "io" "sync" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/services/object/get/v2/get_range_forwarder.go b/pkg/services/object/get/v2/get_range_forwarder.go index 10ecfc4a37..a44616fc9d 100644 --- a/pkg/services/object/get/v2/get_range_forwarder.go +++ b/pkg/services/object/get/v2/get_range_forwarder.go @@ -7,15 +7,15 @@ import ( "io" "sync" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/pkg/services/object/get/v2/get_range_hash.go b/pkg/services/object/get/v2/get_range_hash.go index e97b60f668..e8e82ddd9f 100644 --- a/pkg/services/object/get/v2/get_range_hash.go +++ b/pkg/services/object/get/v2/get_range_hash.go @@ -5,15 +5,15 @@ import ( "encoding/hex" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" clientCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/services/object/get/v2/head_forwarder.go b/pkg/services/object/get/v2/head_forwarder.go index 5e16008b8f..56056398db 100644 --- a/pkg/services/object/get/v2/head_forwarder.go +++ b/pkg/services/object/get/v2/head_forwarder.go @@ -5,15 +5,15 @@ import ( "crypto/ecdsa" "sync" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index edd19b441d..24b2f0099f 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -4,7 +4,6 @@ import ( "context" "errors" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" @@ -12,6 +11,7 @@ import ( getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.uber.org/zap" ) diff --git a/pkg/services/object/get/v2/streamer.go b/pkg/services/object/get/v2/streamer.go index ce9a5c7673..98207336c4 100644 --- a/pkg/services/object/get/v2/streamer.go +++ b/pkg/services/object/get/v2/streamer.go @@ -3,8 +3,8 @@ package getsvc import ( "context" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" ) diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index 852c2aec39..bfa7fd619f 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -5,17 +5,17 @@ import ( "crypto/sha256" "hash" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/status" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/status" clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/services/object/internal/key.go b/pkg/services/object/internal/key.go index eba7169769..1e0a7ef903 100644 --- a/pkg/services/object/internal/key.go +++ b/pkg/services/object/internal/key.go @@ -3,8 +3,8 @@ package internal import ( "bytes" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" ) // VerifyResponseKeyV2 checks if response is signed with expected key. Returns client.ErrWrongPublicKey if not. diff --git a/pkg/services/object/metrics.go b/pkg/services/object/metrics.go index 61aed50035..377350fddb 100644 --- a/pkg/services/object/metrics.go +++ b/pkg/services/object/metrics.go @@ -4,8 +4,8 @@ import ( "context" "time" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) type ( diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index 677c6610fe..91b4efdc10 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -7,13 +7,13 @@ import ( "fmt" "io" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/target" objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/patcher" diff --git a/pkg/services/object/patch/util.go b/pkg/services/object/patch/util.go index 4f3c3ef172..b9416789ce 100644 --- a/pkg/services/object/patch/util.go +++ b/pkg/services/object/patch/util.go @@ -6,8 +6,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 5f9b5d110e..3a0b3901f7 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -9,11 +9,6 @@ import ( "hash" "sync" - objectAPI "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" @@ -28,6 +23,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + objectAPI "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" diff --git a/pkg/services/object/put/v2/service.go b/pkg/services/object/put/v2/service.go index db902ae59b..78d4c711d7 100644 --- a/pkg/services/object/put/v2/service.go +++ b/pkg/services/object/put/v2/service.go @@ -4,10 +4,10 @@ import ( "context" "fmt" - objectAPI "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectAPI "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) // Service implements Put operation of Object service v2. diff --git a/pkg/services/object/put/v2/streamer.go b/pkg/services/object/put/v2/streamer.go index 5bf15b4cdc..36b514fbcb 100644 --- a/pkg/services/object/put/v2/streamer.go +++ b/pkg/services/object/put/v2/streamer.go @@ -4,11 +4,6 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rawclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/target" @@ -17,6 +12,11 @@ import ( putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) diff --git a/pkg/services/object/put/v2/util.go b/pkg/services/object/put/v2/util.go index a157a95423..5ec9ebe107 100644 --- a/pkg/services/object/put/v2/util.go +++ b/pkg/services/object/put/v2/util.go @@ -1,10 +1,10 @@ package putsvc import ( - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" putsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/put" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" ) diff --git a/pkg/services/object/response.go b/pkg/services/object/response.go index d7ba9f8433..3787b41684 100644 --- a/pkg/services/object/response.go +++ b/pkg/services/object/response.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) type ResponseService struct { diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 44abcfe5b5..0a40025e1c 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -9,7 +9,6 @@ import ( "strconv" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" @@ -17,6 +16,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" diff --git a/pkg/services/object/search/v2/request_forwarder.go b/pkg/services/object/search/v2/request_forwarder.go index 5a2e9b936d..7bb6e4d3c8 100644 --- a/pkg/services/object/search/v2/request_forwarder.go +++ b/pkg/services/object/search/v2/request_forwarder.go @@ -8,14 +8,14 @@ import ( "io" "sync" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc" - rpcclient "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" + rpcclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) diff --git a/pkg/services/object/search/v2/service.go b/pkg/services/object/search/v2/service.go index 78b72ac790..856cd9f041 100644 --- a/pkg/services/object/search/v2/service.go +++ b/pkg/services/object/search/v2/service.go @@ -1,10 +1,10 @@ package searchsvc import ( - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" searchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search" objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) // Service implements Search operation of Object service v2. diff --git a/pkg/services/object/search/v2/streamer.go b/pkg/services/object/search/v2/streamer.go index 15e2d53d5a..93b2813436 100644 --- a/pkg/services/object/search/v2/streamer.go +++ b/pkg/services/object/search/v2/streamer.go @@ -1,9 +1,9 @@ package searchsvc import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" ) diff --git a/pkg/services/object/search/v2/util.go b/pkg/services/object/search/v2/util.go index e971fa8e5d..48ae989582 100644 --- a/pkg/services/object/search/v2/util.go +++ b/pkg/services/object/search/v2/util.go @@ -5,12 +5,12 @@ import ( "errors" "fmt" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" searchsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" diff --git a/pkg/services/object/server.go b/pkg/services/object/server.go index da98ce245c..c570e9d8e9 100644 --- a/pkg/services/object/server.go +++ b/pkg/services/object/server.go @@ -3,8 +3,8 @@ package object import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) // GetObjectStream is an interface of FrostFS API v2 compatible object streamer. diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index f5ae97b625..2c5e794e95 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -5,8 +5,8 @@ import ( "crypto/ecdsa" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) type SignService struct { diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index e560d6d8c1..1438a0ea23 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -4,8 +4,8 @@ import ( "bytes" "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) type ( diff --git a/pkg/services/object/util/key_test.go b/pkg/services/object/util/key_test.go index cb7ddfde53..1753a26f75 100644 --- a/pkg/services/object/util/key_test.go +++ b/pkg/services/object/util/key_test.go @@ -5,10 +5,10 @@ import ( "crypto/elliptic" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" tokenStorage "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/temporary" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" diff --git a/pkg/services/object/util/prm.go b/pkg/services/object/util/prm.go index 80c0db39ea..34d8ec7047 100644 --- a/pkg/services/object/util/prm.go +++ b/pkg/services/object/util/prm.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" sessionsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" ) diff --git a/pkg/services/object_manager/tombstone/checker.go b/pkg/services/object_manager/tombstone/checker.go index 48a08b6931..7476dbd48d 100644 --- a/pkg/services/object_manager/tombstone/checker.go +++ b/pkg/services/object_manager/tombstone/checker.go @@ -4,9 +4,9 @@ import ( "context" "strconv" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" lru "github.com/hashicorp/golang-lru/v2" diff --git a/pkg/services/session/executor.go b/pkg/services/session/executor.go index 76c220fab5..e914119b43 100644 --- a/pkg/services/session/executor.go +++ b/pkg/services/session/executor.go @@ -4,10 +4,10 @@ import ( "context" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "go.uber.org/zap" ) diff --git a/pkg/services/session/server.go b/pkg/services/session/server.go index 9e44ae6676..e8555a7c94 100644 --- a/pkg/services/session/server.go +++ b/pkg/services/session/server.go @@ -3,7 +3,7 @@ package session import ( "context" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" ) // Server is an interface of the FrostFS API Session service server. diff --git a/pkg/services/session/sign.go b/pkg/services/session/sign.go index 690fff896f..3664c14035 100644 --- a/pkg/services/session/sign.go +++ b/pkg/services/session/sign.go @@ -4,8 +4,8 @@ import ( "context" "crypto/ecdsa" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" ) type signService struct { diff --git a/pkg/services/session/storage/persistent/executor.go b/pkg/services/session/storage/persistent/executor.go index 21f55a7d14..ea0233f9a4 100644 --- a/pkg/services/session/storage/persistent/executor.go +++ b/pkg/services/session/storage/persistent/executor.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "go.etcd.io/bbolt" diff --git a/pkg/services/session/storage/persistent/executor_test.go b/pkg/services/session/storage/persistent/executor_test.go index 124d36930b..f80ecb591a 100644 --- a/pkg/services/session/storage/persistent/executor_test.go +++ b/pkg/services/session/storage/persistent/executor_test.go @@ -8,8 +8,8 @@ import ( "path/filepath" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/stretchr/testify/require" diff --git a/pkg/services/session/storage/temporary/executor.go b/pkg/services/session/storage/temporary/executor.go index cd498709c2..d531b25cb6 100644 --- a/pkg/services/session/storage/temporary/executor.go +++ b/pkg/services/session/storage/temporary/executor.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/mr-tron/base58" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" diff --git a/pkg/services/tree/service_frostfs.pb.go b/pkg/services/tree/service_frostfs.pb.go index 7b6abb1dd7..05076ee03c 100644 --- a/pkg/services/tree/service_frostfs.pb.go +++ b/pkg/services/tree/service_frostfs.pb.go @@ -5,9 +5,9 @@ package tree import ( json "encoding/json" fmt "fmt" - pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" - proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" - encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + pool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/encoding" easyproto "github.com/VictoriaMetrics/easyproto" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 20a629fccc..4fd4a7e1e2 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -8,8 +8,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 939ff170d8..7bc5002dc8 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -8,13 +8,13 @@ import ( "errors" "testing" - aclV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" + aclV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" diff --git a/pkg/services/tree/types_frostfs.pb.go b/pkg/services/tree/types_frostfs.pb.go index 4399f8a8b1..13f1a43be8 100644 --- a/pkg/services/tree/types_frostfs.pb.go +++ b/pkg/services/tree/types_frostfs.pb.go @@ -5,9 +5,9 @@ package tree import ( json "encoding/json" fmt "fmt" - pool "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" - proto "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto" - encoding "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/proto/encoding" + pool "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/pool" + proto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto" + encoding "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/proto/encoding" easyproto "github.com/VictoriaMetrics/easyproto" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" diff --git a/pkg/services/util/response/service.go b/pkg/services/util/response/service.go index 005a643e56..5152a8ece8 100644 --- a/pkg/services/util/response/service.go +++ b/pkg/services/util/response/service.go @@ -1,10 +1,10 @@ package response import ( - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" ) diff --git a/pkg/services/util/sign.go b/pkg/services/util/sign.go index bce43d6e81..348a45a942 100644 --- a/pkg/services/util/sign.go +++ b/pkg/services/util/sign.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) From 755cae3f19801437fd60dcbbbc2cda64969006ab Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 7 Nov 2024 17:50:14 +0300 Subject: [PATCH 0968/1413] [#1479] control: Regenerate protobufs for service Signed-off-by: Airat Arifullin --- pkg/services/control/ir/service_frostfs.pb.go | 340 ++- pkg/services/control/ir/types_frostfs.pb.go | 45 +- pkg/services/control/service_frostfs.pb.go | 1897 ++++++++++++++--- pkg/services/control/types_frostfs.pb.go | 283 ++- 4 files changed, 2144 insertions(+), 421 deletions(-) diff --git a/pkg/services/control/ir/service_frostfs.pb.go b/pkg/services/control/ir/service_frostfs.pb.go index ff4ce7245d..d277462634 100644 --- a/pkg/services/control/ir/service_frostfs.pb.go +++ b/pkg/services/control/ir/service_frostfs.pb.go @@ -233,14 +233,25 @@ func (x *HealthCheckRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -375,11 +386,22 @@ func (x *HealthCheckResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"healthStatus\":" - out.RawString(prefix[1:]) - out.Int32(int32(x.HealthStatus)) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"healthStatus\":" + out.RawString(prefix) + v := int32(x.HealthStatus) + if vv, ok := HealthStatus_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } out.RawByte('}') } @@ -564,14 +586,25 @@ func (x *HealthCheckResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -706,10 +739,16 @@ func (x *TickEpochRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"vub\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"vub\":" + out.RawString(prefix) out.Uint32(x.Vub) } out.RawByte('}') @@ -743,7 +782,15 @@ func (x *TickEpochRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "vub": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Vub = f } } @@ -879,14 +926,25 @@ func (x *TickEpochRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -1021,10 +1079,16 @@ func (x *TickEpochResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"vub\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"vub\":" + out.RawString(prefix) out.Uint32(x.Vub) } out.RawByte('}') @@ -1058,7 +1122,15 @@ func (x *TickEpochResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "vub": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Vub = f } } @@ -1194,14 +1266,25 @@ func (x *TickEpochResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -1356,14 +1439,29 @@ func (x *RemoveNodeRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"key\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.Key) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"key\":" + out.RawString(prefix) + if x.Key != nil { + out.Base64Bytes(x.Key) + } else { + out.String("") + } } { - const prefix string = ",\"vub\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"vub\":" out.RawString(prefix) out.Uint32(x.Vub) } @@ -1398,13 +1496,27 @@ func (x *RemoveNodeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "key": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Key = f } case "vub": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Vub = f } } @@ -1540,14 +1652,25 @@ func (x *RemoveNodeRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -1682,10 +1805,16 @@ func (x *RemoveNodeResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"vub\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"vub\":" + out.RawString(prefix) out.Uint32(x.Vub) } out.RawByte('}') @@ -1719,7 +1848,15 @@ func (x *RemoveNodeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "vub": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Vub = f } } @@ -1855,14 +1992,25 @@ func (x *RemoveNodeResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -2037,19 +2185,43 @@ func (x *RemoveContainerRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) - } - { - const prefix string = ",\"owner\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" out.RawString(prefix) - out.Base64Bytes(x.Owner) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"vub\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"owner\":" + out.RawString(prefix) + if x.Owner != nil { + out.Base64Bytes(x.Owner) + } else { + out.String("") + } + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"vub\":" out.RawString(prefix) out.Uint32(x.Vub) } @@ -2084,19 +2256,39 @@ func (x *RemoveContainerRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "owner": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Owner = f } case "vub": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Vub = f } } @@ -2232,14 +2424,25 @@ func (x *RemoveContainerRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -2374,10 +2577,16 @@ func (x *RemoveContainerResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"vub\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"vub\":" + out.RawString(prefix) out.Uint32(x.Vub) } out.RawByte('}') @@ -2411,7 +2620,15 @@ func (x *RemoveContainerResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "vub": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Vub = f } } @@ -2547,14 +2764,25 @@ func (x *RemoveContainerResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } diff --git a/pkg/services/control/ir/types_frostfs.pb.go b/pkg/services/control/ir/types_frostfs.pb.go index 32bf457a1d..407eec6ad8 100644 --- a/pkg/services/control/ir/types_frostfs.pb.go +++ b/pkg/services/control/ir/types_frostfs.pb.go @@ -155,16 +155,35 @@ func (x *Signature) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"key\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.Key) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"key\":" + out.RawString(prefix) + if x.Key != nil { + out.Base64Bytes(x.Key) + } else { + out.String("") + } } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) - out.Base64Bytes(x.Sign) + if x.Sign != nil { + out.Base64Bytes(x.Sign) + } else { + out.String("") + } } out.RawByte('}') } @@ -197,13 +216,25 @@ func (x *Signature) UnmarshalEasyJSON(in *jlexer.Lexer) { case "key": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Key = f } case "signature": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Sign = f } } diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 96b8964781..0b4e3cf32a 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -233,14 +233,25 @@ func (x *HealthCheckRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -395,16 +406,37 @@ func (x *HealthCheckResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"netmapStatus\":" - out.RawString(prefix[1:]) - out.Int32(int32(x.NetmapStatus)) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"netmapStatus\":" + out.RawString(prefix) + v := int32(x.NetmapStatus) + if vv, ok := NetmapStatus_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } { - const prefix string = ",\"healthStatus\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"healthStatus\":" out.RawString(prefix) - out.Int32(int32(x.HealthStatus)) + v := int32(x.HealthStatus) + if vv, ok := HealthStatus_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } out.RawByte('}') } @@ -611,14 +643,25 @@ func (x *HealthCheckResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -773,14 +816,30 @@ func (x *SetNetmapStatusRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"status\":" - out.RawString(prefix[1:]) - out.Int32(int32(x.Status)) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"status\":" + out.RawString(prefix) + v := int32(x.Status) + if vv, ok := NetmapStatus_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } { - const prefix string = ",\"forceMaintenance\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"forceMaintenance\":" out.RawString(prefix) out.Bool(x.ForceMaintenance) } @@ -973,14 +1032,25 @@ func (x *SetNetmapStatusRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -1254,14 +1324,25 @@ func (x *SetNetmapStatusResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -1535,14 +1616,25 @@ func (x *GetNetmapStatusRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -1697,16 +1789,34 @@ func (x *GetNetmapStatusResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"status\":" - out.RawString(prefix[1:]) - out.Int32(int32(x.Status)) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"status\":" + out.RawString(prefix) + v := int32(x.Status) + if vv, ok := NetmapStatus_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } { - const prefix string = ",\"epoch\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"epoch\":" out.RawString(prefix) - out.Uint64(x.Epoch) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.Epoch, 10) + out.RawByte('"') } out.RawByte('}') } @@ -1761,7 +1871,15 @@ func (x *GetNetmapStatusResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "epoch": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.Epoch = f } } @@ -1897,14 +2015,25 @@ func (x *GetNetmapStatusResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -2039,16 +2168,26 @@ func (x *DropObjectsRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"addressList\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"addressList\":" + out.RawString(prefix) out.RawByte('[') for i := range x.AddressList { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.AddressList[i]) + if x.AddressList[i] != nil { + out.Base64Bytes(x.AddressList[i]) + } else { + out.String("") + } } out.RawByte(']') } @@ -2086,7 +2225,13 @@ func (x *DropObjectsRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -2226,14 +2371,25 @@ func (x *DropObjectsRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -2507,14 +2663,25 @@ func (x *DropObjectsResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -2788,14 +2955,25 @@ func (x *ListShardsRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -2936,10 +3114,16 @@ func (x *ListShardsResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shards\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shards\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Shards { if i != 0 { @@ -3124,14 +3308,25 @@ func (x *ListShardsResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -3306,26 +3501,51 @@ func (x *SetShardModeRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Shard_ID { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Shard_ID[i]) + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } } out.RawByte(']') } { - const prefix string = ",\"mode\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"mode\":" out.RawString(prefix) - out.Int32(int32(x.Mode)) + v := int32(x.Mode) + if vv, ok := ShardMode_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } { - const prefix string = ",\"resetErrorCounter\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"resetErrorCounter\":" out.RawString(prefix) out.Bool(x.ResetErrorCounter) } @@ -3363,7 +3583,13 @@ func (x *SetShardModeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -3531,14 +3757,25 @@ func (x *SetShardModeRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -3812,14 +4049,25 @@ func (x *SetShardModeResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -3994,21 +4242,43 @@ func (x *SynchronizeTreeRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"height\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"height\":" out.RawString(prefix) - out.Uint64(x.Height) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.Height, 10) + out.RawByte('"') } out.RawByte('}') } @@ -4041,7 +4311,13 @@ func (x *SynchronizeTreeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -4053,7 +4329,15 @@ func (x *SynchronizeTreeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "height": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.Height = f } } @@ -4189,14 +4473,25 @@ func (x *SynchronizeTreeRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -4470,14 +4765,25 @@ func (x *SynchronizeTreeResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -4632,21 +4938,36 @@ func (x *EvacuateShardRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Shard_ID { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Shard_ID[i]) + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } } out.RawByte(']') } { - const prefix string = ",\"ignoreErrors\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"ignoreErrors\":" out.RawString(prefix) out.Bool(x.IgnoreErrors) } @@ -4684,7 +5005,13 @@ func (x *EvacuateShardRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -4830,14 +5157,25 @@ func (x *EvacuateShardRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -4972,10 +5310,16 @@ func (x *EvacuateShardResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"count\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"count\":" + out.RawString(prefix) out.Uint32(x.Count) } out.RawByte('}') @@ -5009,7 +5353,15 @@ func (x *EvacuateShardResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "count": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Count = f } } @@ -5145,14 +5497,25 @@ func (x *EvacuateShardResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -5307,21 +5670,36 @@ func (x *FlushCacheRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Shard_ID { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Shard_ID[i]) + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } } out.RawByte(']') } { - const prefix string = ",\"seal\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"seal\":" out.RawString(prefix) out.Bool(x.Seal) } @@ -5359,7 +5737,13 @@ func (x *FlushCacheRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -5505,14 +5889,25 @@ func (x *FlushCacheRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -5786,14 +6181,25 @@ func (x *FlushCacheResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -5948,14 +6354,25 @@ func (x *DoctorRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"concurrency\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"concurrency\":" + out.RawString(prefix) out.Uint32(x.Concurrency) } { - const prefix string = ",\"removeDuplicates\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"removeDuplicates\":" out.RawString(prefix) out.Bool(x.RemoveDuplicates) } @@ -5990,7 +6407,15 @@ func (x *DoctorRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "concurrency": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Concurrency = f } case "removeDuplicates": @@ -6132,14 +6557,25 @@ func (x *DoctorRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -6413,14 +6849,25 @@ func (x *DoctorResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -6690,41 +7137,76 @@ func (x *StartShardEvacuationRequest_Body) MarshalEasyJSON(out *jwriter.Writer) out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Shard_ID { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Shard_ID[i]) + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } } out.RawByte(']') } { - const prefix string = ",\"ignoreErrors\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"ignoreErrors\":" out.RawString(prefix) out.Bool(x.IgnoreErrors) } { - const prefix string = ",\"scope\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"scope\":" out.RawString(prefix) out.Uint32(x.Scope) } { - const prefix string = ",\"containerWorkerCount\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerWorkerCount\":" out.RawString(prefix) out.Uint32(x.ContainerWorkerCount) } { - const prefix string = ",\"objectWorkerCount\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"objectWorkerCount\":" out.RawString(prefix) out.Uint32(x.ObjectWorkerCount) } { - const prefix string = ",\"repOneOnly\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"repOneOnly\":" out.RawString(prefix) out.Bool(x.RepOneOnly) } @@ -6762,7 +7244,13 @@ func (x *StartShardEvacuationRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -6778,19 +7266,43 @@ func (x *StartShardEvacuationRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "scope": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Scope = f } case "containerWorkerCount": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.ContainerWorkerCount = f } case "objectWorkerCount": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.ObjectWorkerCount = f } case "repOneOnly": @@ -6932,14 +7444,25 @@ func (x *StartShardEvacuationRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -7213,14 +7736,25 @@ func (x *StartShardEvacuationResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -7494,14 +8028,25 @@ func (x *GetShardEvacuationStatusRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -7671,11 +8216,19 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) MarshalEasyJSON(ou out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"value\":" - out.RawString(prefix[1:]) - out.Int64(x.Value) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"value\":" + out.RawString(prefix) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendInt(out.Buffer.Buf, x.Value, 10) + out.RawByte('"') } out.RawByte('}') } @@ -7708,7 +8261,15 @@ func (x *GetShardEvacuationStatusResponse_Body_UnixTimestamp) UnmarshalEasyJSON( case "value": { var f int64 - f = in.Int64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseInt(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := int64(v) + f = pv x.Value = f } } @@ -7800,11 +8361,19 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) MarshalEasyJSON(out *jw out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"seconds\":" - out.RawString(prefix[1:]) - out.Int64(x.Seconds) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"seconds\":" + out.RawString(prefix) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendInt(out.Buffer.Buf, x.Seconds, 10) + out.RawByte('"') } out.RawByte('}') } @@ -7837,7 +8406,15 @@ func (x *GetShardEvacuationStatusResponse_Body_Duration) UnmarshalEasyJSON(in *j case "seconds": { var f int64 - f = in.Int64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseInt(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := int64(v) + f = pv x.Seconds = f } } @@ -8155,73 +8732,157 @@ func (x *GetShardEvacuationStatusResponse_Body) MarshalEasyJSON(out *jwriter.Wri out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"totalObjects\":" - out.RawString(prefix[1:]) - out.Uint64(x.TotalObjects) - } - { - const prefix string = ",\"evacuatedObjects\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"totalObjects\":" out.RawString(prefix) - out.Uint64(x.EvacuatedObjects) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.TotalObjects, 10) + out.RawByte('"') } { - const prefix string = ",\"failedObjects\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"evacuatedObjects\":" out.RawString(prefix) - out.Uint64(x.FailedObjects) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.EvacuatedObjects, 10) + out.RawByte('"') } { - const prefix string = ",\"shardID\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"failedObjects\":" + out.RawString(prefix) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.FailedObjects, 10) + out.RawByte('"') + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" out.RawString(prefix) out.RawByte('[') for i := range x.Shard_ID { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Shard_ID[i]) + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } } out.RawByte(']') } { - const prefix string = ",\"status\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"status\":" out.RawString(prefix) - out.Int32(int32(x.Status)) + v := int32(x.Status) + if vv, ok := GetShardEvacuationStatusResponse_Body_Status_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } { - const prefix string = ",\"duration\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"duration\":" out.RawString(prefix) x.Duration.MarshalEasyJSON(out) } { - const prefix string = ",\"startedAt\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"startedAt\":" out.RawString(prefix) x.StartedAt.MarshalEasyJSON(out) } { - const prefix string = ",\"errorMessage\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"errorMessage\":" out.RawString(prefix) out.String(x.ErrorMessage) } { - const prefix string = ",\"skippedObjects\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"skippedObjects\":" out.RawString(prefix) - out.Uint64(x.SkippedObjects) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.SkippedObjects, 10) + out.RawByte('"') } { - const prefix string = ",\"totalTrees\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"totalTrees\":" out.RawString(prefix) - out.Uint64(x.TotalTrees) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.TotalTrees, 10) + out.RawByte('"') } { - const prefix string = ",\"evacuatedTrees\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"evacuatedTrees\":" out.RawString(prefix) - out.Uint64(x.EvacuatedTrees) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.EvacuatedTrees, 10) + out.RawByte('"') } { - const prefix string = ",\"failedTrees\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"failedTrees\":" out.RawString(prefix) - out.Uint64(x.FailedTrees) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.FailedTrees, 10) + out.RawByte('"') } out.RawByte('}') } @@ -8254,19 +8915,43 @@ func (x *GetShardEvacuationStatusResponse_Body) UnmarshalEasyJSON(in *jlexer.Lex case "totalObjects": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.TotalObjects = f } case "evacuatedObjects": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.EvacuatedObjects = f } case "failedObjects": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.FailedObjects = f } case "shardID": @@ -8275,7 +8960,13 @@ func (x *GetShardEvacuationStatusResponse_Body) UnmarshalEasyJSON(in *jlexer.Lex var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -8327,25 +9018,57 @@ func (x *GetShardEvacuationStatusResponse_Body) UnmarshalEasyJSON(in *jlexer.Lex case "skippedObjects": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.SkippedObjects = f } case "totalTrees": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.TotalTrees = f } case "evacuatedTrees": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.EvacuatedTrees = f } case "failedTrees": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.FailedTrees = f } } @@ -8481,14 +9204,25 @@ func (x *GetShardEvacuationStatusResponse) MarshalEasyJSON(out *jwriter.Writer) out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -8762,14 +9496,25 @@ func (x *ResetShardEvacuationStatusRequest) MarshalEasyJSON(out *jwriter.Writer) out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -9043,14 +9788,25 @@ func (x *ResetShardEvacuationStatusResponse) MarshalEasyJSON(out *jwriter.Writer out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -9324,14 +10080,25 @@ func (x *StopShardEvacuationRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -9605,14 +10372,25 @@ func (x *StopShardEvacuationResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -9770,16 +10548,31 @@ func (x *AddChainLocalOverrideRequest_Body) MarshalEasyJSON(out *jwriter.Writer) out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"target\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"target\":" + out.RawString(prefix) x.Target.MarshalEasyJSON(out) } { - const prefix string = ",\"chain\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"chain\":" out.RawString(prefix) - out.Base64Bytes(x.Chain) + if x.Chain != nil { + out.Base64Bytes(x.Chain) + } else { + out.String("") + } } out.RawByte('}') } @@ -9819,7 +10612,13 @@ func (x *AddChainLocalOverrideRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) case "chain": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Chain = f } } @@ -9955,14 +10754,25 @@ func (x *AddChainLocalOverrideRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -10097,11 +10907,21 @@ func (x *AddChainLocalOverrideResponse_Body) MarshalEasyJSON(out *jwriter.Writer out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"chainId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ChainId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"chainId\":" + out.RawString(prefix) + if x.ChainId != nil { + out.Base64Bytes(x.ChainId) + } else { + out.String("") + } } out.RawByte('}') } @@ -10134,7 +10954,13 @@ func (x *AddChainLocalOverrideResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) case "chainId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ChainId = f } } @@ -10270,14 +11096,25 @@ func (x *AddChainLocalOverrideResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -10435,16 +11272,31 @@ func (x *GetChainLocalOverrideRequest_Body) MarshalEasyJSON(out *jwriter.Writer) out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"target\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"target\":" + out.RawString(prefix) x.Target.MarshalEasyJSON(out) } { - const prefix string = ",\"chainId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"chainId\":" out.RawString(prefix) - out.Base64Bytes(x.ChainId) + if x.ChainId != nil { + out.Base64Bytes(x.ChainId) + } else { + out.String("") + } } out.RawByte('}') } @@ -10484,7 +11336,13 @@ func (x *GetChainLocalOverrideRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) case "chainId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ChainId = f } } @@ -10620,14 +11478,25 @@ func (x *GetChainLocalOverrideRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -10762,11 +11631,21 @@ func (x *GetChainLocalOverrideResponse_Body) MarshalEasyJSON(out *jwriter.Writer out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"chain\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.Chain) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"chain\":" + out.RawString(prefix) + if x.Chain != nil { + out.Base64Bytes(x.Chain) + } else { + out.String("") + } } out.RawByte('}') } @@ -10799,7 +11678,13 @@ func (x *GetChainLocalOverrideResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) case "chain": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Chain = f } } @@ -10935,14 +11820,25 @@ func (x *GetChainLocalOverrideResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -11080,10 +11976,16 @@ func (x *ListChainLocalOverridesRequest_Body) MarshalEasyJSON(out *jwriter.Write out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"target\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"target\":" + out.RawString(prefix) x.Target.MarshalEasyJSON(out) } out.RawByte('}') @@ -11254,14 +12156,25 @@ func (x *ListChainLocalOverridesRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -11396,16 +12309,26 @@ func (x *ListChainLocalOverridesResponse_Body) MarshalEasyJSON(out *jwriter.Writ out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"chains\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"chains\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Chains { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Chains[i]) + if x.Chains[i] != nil { + out.Base64Bytes(x.Chains[i]) + } else { + out.String("") + } } out.RawByte(']') } @@ -11443,7 +12366,13 @@ func (x *ListChainLocalOverridesResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexe var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -11583,14 +12512,25 @@ func (x *ListChainLocalOverridesResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -11725,10 +12665,16 @@ func (x *ListTargetsLocalOverridesRequest_Body) MarshalEasyJSON(out *jwriter.Wri out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"chainName\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"chainName\":" + out.RawString(prefix) out.String(x.ChainName) } out.RawByte('}') @@ -11898,14 +12844,25 @@ func (x *ListTargetsLocalOverridesRequest) MarshalEasyJSON(out *jwriter.Writer) out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -12046,10 +13003,16 @@ func (x *ListTargetsLocalOverridesResponse_Body) MarshalEasyJSON(out *jwriter.Wr out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"targets\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"targets\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Targets { if i != 0 { @@ -12234,14 +13197,25 @@ func (x *ListTargetsLocalOverridesResponse) MarshalEasyJSON(out *jwriter.Writer) out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -12399,16 +13373,31 @@ func (x *RemoveChainLocalOverrideRequest_Body) MarshalEasyJSON(out *jwriter.Writ out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"target\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"target\":" + out.RawString(prefix) x.Target.MarshalEasyJSON(out) } { - const prefix string = ",\"chainId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"chainId\":" out.RawString(prefix) - out.Base64Bytes(x.ChainId) + if x.ChainId != nil { + out.Base64Bytes(x.ChainId) + } else { + out.String("") + } } out.RawByte('}') } @@ -12448,7 +13437,13 @@ func (x *RemoveChainLocalOverrideRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexe case "chainId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ChainId = f } } @@ -12584,14 +13579,25 @@ func (x *RemoveChainLocalOverrideRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -12865,14 +13871,25 @@ func (x *RemoveChainLocalOverrideResponse) MarshalEasyJSON(out *jwriter.Writer) out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -13010,10 +14027,16 @@ func (x *RemoveChainLocalOverridesByTargetRequest_Body) MarshalEasyJSON(out *jwr out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"target\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"target\":" + out.RawString(prefix) x.Target.MarshalEasyJSON(out) } out.RawByte('}') @@ -13184,14 +14207,25 @@ func (x *RemoveChainLocalOverridesByTargetRequest) MarshalEasyJSON(out *jwriter. out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -13465,14 +14499,25 @@ func (x *RemoveChainLocalOverridesByTargetResponse) MarshalEasyJSON(out *jwriter out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -13687,36 +14732,66 @@ func (x *SealWriteCacheRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Shard_ID { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Shard_ID[i]) + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } } out.RawByte(']') } { - const prefix string = ",\"ignoreErrors\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"ignoreErrors\":" out.RawString(prefix) out.Bool(x.IgnoreErrors) } { - const prefix string = ",\"async\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"async\":" out.RawString(prefix) out.Bool(x.Async) } { - const prefix string = ",\"restoreMode\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"restoreMode\":" out.RawString(prefix) out.Bool(x.RestoreMode) } { - const prefix string = ",\"shrink\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shrink\":" out.RawString(prefix) out.Bool(x.Shrink) } @@ -13754,7 +14829,13 @@ func (x *SealWriteCacheRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -13918,14 +14999,25 @@ func (x *SealWriteCacheRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -14100,19 +15192,39 @@ func (x *SealWriteCacheResponse_Body_Status) MarshalEasyJSON(out *jwriter.Writer out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.Shard_ID) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) + if x.Shard_ID != nil { + out.Base64Bytes(x.Shard_ID) + } else { + out.String("") + } } { - const prefix string = ",\"success\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"success\":" out.RawString(prefix) out.Bool(x.Success) } { - const prefix string = ",\"error\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"error\":" out.RawString(prefix) out.String(x.Error) } @@ -14147,7 +15259,13 @@ func (x *SealWriteCacheResponse_Body_Status) UnmarshalEasyJSON(in *jlexer.Lexer) case "shardID": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Shard_ID = f } case "success": @@ -14257,10 +15375,16 @@ func (x *SealWriteCacheResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"results\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"results\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Results { if i != 0 { @@ -14445,14 +15569,25 @@ func (x *SealWriteCacheResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -14587,16 +15722,26 @@ func (x *DetachShardsRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Shard_ID { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Shard_ID[i]) + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } } out.RawByte(']') } @@ -14634,7 +15779,13 @@ func (x *DetachShardsRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -14774,14 +15925,25 @@ func (x *DetachShardsRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -15055,14 +16217,25 @@ func (x *DetachShardsResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -15237,26 +16410,46 @@ func (x *StartShardRebuildRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Shard_ID { if i != 0 { out.RawByte(',') } - out.Base64Bytes(x.Shard_ID[i]) + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } } out.RawByte(']') } { - const prefix string = ",\"targetFillPercent\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"targetFillPercent\":" out.RawString(prefix) out.Uint32(x.TargetFillPercent) } { - const prefix string = ",\"concurrencyLimit\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"concurrencyLimit\":" out.RawString(prefix) out.Uint32(x.ConcurrencyLimit) } @@ -15294,7 +16487,13 @@ func (x *StartShardRebuildRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list [][]byte in.Delim('[') for !in.IsDelim(']') { - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } list = append(list, f) in.WantComma() } @@ -15304,13 +16503,29 @@ func (x *StartShardRebuildRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "targetFillPercent": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.TargetFillPercent = f } case "concurrencyLimit": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.ConcurrencyLimit = f } } @@ -15446,14 +16661,25 @@ func (x *StartShardRebuildRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -15628,19 +16854,39 @@ func (x *StartShardRebuildResponse_Body_Status) MarshalEasyJSON(out *jwriter.Wri out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.Shard_ID) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) + if x.Shard_ID != nil { + out.Base64Bytes(x.Shard_ID) + } else { + out.String("") + } } { - const prefix string = ",\"success\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"success\":" out.RawString(prefix) out.Bool(x.Success) } { - const prefix string = ",\"error\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"error\":" out.RawString(prefix) out.String(x.Error) } @@ -15675,7 +16921,13 @@ func (x *StartShardRebuildResponse_Body_Status) UnmarshalEasyJSON(in *jlexer.Lex case "shardID": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Shard_ID = f } case "success": @@ -15785,10 +17037,16 @@ func (x *StartShardRebuildResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"results\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"results\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Results { if i != 0 { @@ -15973,14 +17231,25 @@ func (x *StartShardRebuildResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } diff --git a/pkg/services/control/types_frostfs.pb.go b/pkg/services/control/types_frostfs.pb.go index 50984f15ad..69d87292d4 100644 --- a/pkg/services/control/types_frostfs.pb.go +++ b/pkg/services/control/types_frostfs.pb.go @@ -234,16 +234,35 @@ func (x *Signature) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"key\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.Key) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"key\":" + out.RawString(prefix) + if x.Key != nil { + out.Base64Bytes(x.Key) + } else { + out.String("") + } } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) - out.Base64Bytes(x.Sign) + if x.Sign != nil { + out.Base64Bytes(x.Sign) + } else { + out.String("") + } } out.RawByte('}') } @@ -276,13 +295,25 @@ func (x *Signature) UnmarshalEasyJSON(in *jlexer.Lexer) { case "key": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Key = f } case "signature": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Sign = f } } @@ -414,19 +445,35 @@ func (x *NodeInfo_Attribute) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"key\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"key\":" + out.RawString(prefix) out.String(x.Key) } { - const prefix string = ",\"value\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"value\":" out.RawString(prefix) out.String(x.Value) } { - const prefix string = ",\"parents\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"parents\":" out.RawString(prefix) out.RawByte('[') for i := range x.Parents { @@ -645,14 +692,29 @@ func (x *NodeInfo) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"publicKey\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.PublicKey) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"publicKey\":" + out.RawString(prefix) + if x.PublicKey != nil { + out.Base64Bytes(x.PublicKey) + } else { + out.String("") + } } { - const prefix string = ",\"addresses\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"addresses\":" out.RawString(prefix) out.RawByte('[') for i := range x.Addresses { @@ -664,7 +726,12 @@ func (x *NodeInfo) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"attributes\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"attributes\":" out.RawString(prefix) out.RawByte('[') for i := range x.Attributes { @@ -676,9 +743,19 @@ func (x *NodeInfo) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"state\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"state\":" out.RawString(prefix) - out.Int32(int32(x.State)) + v := int32(x.State) + if vv, ok := NetmapStatus_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } out.RawByte('}') } @@ -711,7 +788,13 @@ func (x *NodeInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { case "publicKey": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.PublicKey = f } case "addresses": @@ -878,14 +961,27 @@ func (x *Netmap) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"epoch\":" - out.RawString(prefix[1:]) - out.Uint64(x.Epoch) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"epoch\":" + out.RawString(prefix) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.Epoch, 10) + out.RawByte('"') } { - const prefix string = ",\"nodes\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"nodes\":" out.RawString(prefix) out.RawByte('[') for i := range x.Nodes { @@ -927,7 +1023,15 @@ func (x *Netmap) UnmarshalEasyJSON(in *jlexer.Lexer) { case "epoch": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.Epoch = f } case "nodes": @@ -1179,19 +1283,39 @@ func (x *ShardInfo) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"shardID\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.Shard_ID) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) + if x.Shard_ID != nil { + out.Base64Bytes(x.Shard_ID) + } else { + out.String("") + } } { - const prefix string = ",\"metabasePath\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"metabasePath\":" out.RawString(prefix) out.String(x.MetabasePath) } { - const prefix string = ",\"blobstor\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"blobstor\":" out.RawString(prefix) out.RawByte('[') for i := range x.Blobstor { @@ -1203,27 +1327,57 @@ func (x *ShardInfo) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"writecachePath\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"writecachePath\":" out.RawString(prefix) out.String(x.WritecachePath) } { - const prefix string = ",\"mode\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"mode\":" out.RawString(prefix) - out.Int32(int32(x.Mode)) + v := int32(x.Mode) + if vv, ok := ShardMode_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } { - const prefix string = ",\"errorCount\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"errorCount\":" out.RawString(prefix) out.Uint32(x.ErrorCount) } { - const prefix string = ",\"piloramaPath\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"piloramaPath\":" out.RawString(prefix) out.String(x.PiloramaPath) } { - const prefix string = ",\"evacuationInProgress\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"evacuationInProgress\":" out.RawString(prefix) out.Bool(x.EvacuationInProgress) } @@ -1258,7 +1412,13 @@ func (x *ShardInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { case "shardID": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Shard_ID = f } case "metabasePath": @@ -1312,7 +1472,15 @@ func (x *ShardInfo) UnmarshalEasyJSON(in *jlexer.Lexer) { case "errorCount": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.ErrorCount = f } case "piloramaPath": @@ -1436,14 +1604,25 @@ func (x *BlobstorInfo) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"path\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"path\":" + out.RawString(prefix) out.String(x.Path) } { - const prefix string = ",\"type\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"type\":" out.RawString(prefix) out.String(x.Type) } @@ -1637,14 +1816,30 @@ func (x *ChainTarget) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"type\":" - out.RawString(prefix[1:]) - out.Int32(int32(x.Type)) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"type\":" + out.RawString(prefix) + v := int32(x.Type) + if vv, ok := ChainTarget_TargetType_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } { - const prefix string = ",\"Name\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"Name\":" out.RawString(prefix) out.String(x.Name) } From 764450d04a38bedc3d1b38a098a7546983fcdf93 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 7 Nov 2024 17:51:33 +0300 Subject: [PATCH 0969/1413] [#1479] tree: Regenerate service protobufs Signed-off-by: Airat Arifullin --- pkg/services/tree/service_frostfs.pb.go | 1252 +++++++++++++++++++---- pkg/services/tree/types_frostfs.pb.go | 143 ++- 2 files changed, 1172 insertions(+), 223 deletions(-) diff --git a/pkg/services/tree/service_frostfs.pb.go b/pkg/services/tree/service_frostfs.pb.go index 05076ee03c..88d0026217 100644 --- a/pkg/services/tree/service_frostfs.pb.go +++ b/pkg/services/tree/service_frostfs.pb.go @@ -181,24 +181,51 @@ func (x *AddRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"parentId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"parentId\":" out.RawString(prefix) - out.Uint64(x.ParentId) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.ParentId, 10) + out.RawByte('"') } { - const prefix string = ",\"meta\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"meta\":" out.RawString(prefix) out.RawByte('[') for i := range x.Meta { @@ -210,9 +237,18 @@ func (x *AddRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"bearerToken\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"bearerToken\":" out.RawString(prefix) - out.Base64Bytes(x.BearerToken) + if x.BearerToken != nil { + out.Base64Bytes(x.BearerToken) + } else { + out.String("") + } } out.RawByte('}') } @@ -245,7 +281,13 @@ func (x *AddRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -257,7 +299,15 @@ func (x *AddRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "parentId": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.ParentId = f } case "meta": @@ -277,7 +327,13 @@ func (x *AddRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "bearerToken": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.BearerToken = f } } @@ -413,14 +469,25 @@ func (x *AddRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -555,11 +622,19 @@ func (x *AddResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"nodeId\":" - out.RawString(prefix[1:]) - out.Uint64(x.NodeId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"nodeId\":" + out.RawString(prefix) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.NodeId, 10) + out.RawByte('"') } out.RawByte('}') } @@ -592,7 +667,15 @@ func (x *AddResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "nodeId": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.NodeId = f } } @@ -728,14 +811,25 @@ func (x *AddResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -976,24 +1070,49 @@ func (x *AddByPathRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"pathAttribute\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"pathAttribute\":" out.RawString(prefix) out.String(x.PathAttribute) } { - const prefix string = ",\"path\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"path\":" out.RawString(prefix) out.RawByte('[') for i := range x.Path { @@ -1005,7 +1124,12 @@ func (x *AddByPathRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"meta\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"meta\":" out.RawString(prefix) out.RawByte('[') for i := range x.Meta { @@ -1017,9 +1141,18 @@ func (x *AddByPathRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"bearerToken\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"bearerToken\":" out.RawString(prefix) - out.Base64Bytes(x.BearerToken) + if x.BearerToken != nil { + out.Base64Bytes(x.BearerToken) + } else { + out.String("") + } } out.RawByte('}') } @@ -1052,7 +1185,13 @@ func (x *AddByPathRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -1097,7 +1236,13 @@ func (x *AddByPathRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "bearerToken": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.BearerToken = f } } @@ -1233,14 +1378,25 @@ func (x *AddByPathRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -1397,23 +1553,38 @@ func (x *AddByPathResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"nodes\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"nodes\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Nodes { if i != 0 { out.RawByte(',') } - out.Uint64(x.Nodes[i]) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.Nodes[i], 10) + out.RawByte('"') } out.RawByte(']') } { - const prefix string = ",\"parentId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"parentId\":" out.RawString(prefix) - out.Uint64(x.ParentId) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.ParentId, 10) + out.RawByte('"') } out.RawByte('}') } @@ -1449,7 +1620,15 @@ func (x *AddByPathResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list []uint64 in.Delim('[') for !in.IsDelim(']') { - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv list = append(list, f) in.WantComma() } @@ -1459,7 +1638,15 @@ func (x *AddByPathResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "parentId": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.ParentId = f } } @@ -1595,14 +1782,25 @@ func (x *AddByPathResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -1797,26 +1995,57 @@ func (x *RemoveRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"nodeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"nodeId\":" out.RawString(prefix) - out.Uint64(x.NodeId) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.NodeId, 10) + out.RawByte('"') } { - const prefix string = ",\"bearerToken\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"bearerToken\":" out.RawString(prefix) - out.Base64Bytes(x.BearerToken) + if x.BearerToken != nil { + out.Base64Bytes(x.BearerToken) + } else { + out.String("") + } } out.RawByte('}') } @@ -1849,7 +2078,13 @@ func (x *RemoveRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -1861,13 +2096,27 @@ func (x *RemoveRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "nodeId": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.NodeId = f } case "bearerToken": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.BearerToken = f } } @@ -2003,14 +2252,25 @@ func (x *RemoveRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -2284,14 +2544,25 @@ func (x *RemoveResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -2532,29 +2803,63 @@ func (x *MoveRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"parentId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"parentId\":" out.RawString(prefix) - out.Uint64(x.ParentId) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.ParentId, 10) + out.RawByte('"') } { - const prefix string = ",\"nodeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"nodeId\":" out.RawString(prefix) - out.Uint64(x.NodeId) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.NodeId, 10) + out.RawByte('"') } { - const prefix string = ",\"meta\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"meta\":" out.RawString(prefix) out.RawByte('[') for i := range x.Meta { @@ -2566,9 +2871,18 @@ func (x *MoveRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"bearerToken\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"bearerToken\":" out.RawString(prefix) - out.Base64Bytes(x.BearerToken) + if x.BearerToken != nil { + out.Base64Bytes(x.BearerToken) + } else { + out.String("") + } } out.RawByte('}') } @@ -2601,7 +2915,13 @@ func (x *MoveRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -2613,13 +2933,29 @@ func (x *MoveRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "parentId": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.ParentId = f } case "nodeId": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.NodeId = f } case "meta": @@ -2639,7 +2975,13 @@ func (x *MoveRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "bearerToken": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.BearerToken = f } } @@ -2775,14 +3117,25 @@ func (x *MoveRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -3056,14 +3409,25 @@ func (x *MoveResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -3338,24 +3702,49 @@ func (x *GetNodeByPathRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"pathAttribute\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"pathAttribute\":" out.RawString(prefix) out.String(x.PathAttribute) } { - const prefix string = ",\"path\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"path\":" out.RawString(prefix) out.RawByte('[') for i := range x.Path { @@ -3367,7 +3756,12 @@ func (x *GetNodeByPathRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"attributes\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"attributes\":" out.RawString(prefix) out.RawByte('[') for i := range x.Attributes { @@ -3379,19 +3773,38 @@ func (x *GetNodeByPathRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"latestOnly\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"latestOnly\":" out.RawString(prefix) out.Bool(x.LatestOnly) } { - const prefix string = ",\"allAttributes\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"allAttributes\":" out.RawString(prefix) out.Bool(x.AllAttributes) } { - const prefix string = ",\"bearerToken\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"bearerToken\":" out.RawString(prefix) - out.Base64Bytes(x.BearerToken) + if x.BearerToken != nil { + out.Base64Bytes(x.BearerToken) + } else { + out.String("") + } } out.RawByte('}') } @@ -3424,7 +3837,13 @@ func (x *GetNodeByPathRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -3480,7 +3899,13 @@ func (x *GetNodeByPathRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "bearerToken": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.BearerToken = f } } @@ -3616,14 +4041,25 @@ func (x *GetNodeByPathRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -3824,19 +4260,39 @@ func (x *GetNodeByPathResponse_Info) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"nodeId\":" - out.RawString(prefix[1:]) - out.Uint64(x.NodeId) - } - { - const prefix string = ",\"timestamp\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"nodeId\":" out.RawString(prefix) - out.Uint64(x.Timestamp) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.NodeId, 10) + out.RawByte('"') } { - const prefix string = ",\"meta\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"timestamp\":" + out.RawString(prefix) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.Timestamp, 10) + out.RawByte('"') + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"meta\":" out.RawString(prefix) out.RawByte('[') for i := range x.Meta { @@ -3848,9 +4304,16 @@ func (x *GetNodeByPathResponse_Info) MarshalEasyJSON(out *jwriter.Writer) { out.RawByte(']') } { - const prefix string = ",\"parentId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"parentId\":" out.RawString(prefix) - out.Uint64(x.ParentId) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.ParentId, 10) + out.RawByte('"') } out.RawByte('}') } @@ -3883,13 +4346,29 @@ func (x *GetNodeByPathResponse_Info) UnmarshalEasyJSON(in *jlexer.Lexer) { case "nodeId": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.NodeId = f } case "timestamp": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.Timestamp = f } case "meta": @@ -3909,7 +4388,15 @@ func (x *GetNodeByPathResponse_Info) UnmarshalEasyJSON(in *jlexer.Lexer) { case "parentId": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.ParentId = f } } @@ -4007,10 +4494,16 @@ func (x *GetNodeByPathResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"nodes\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"nodes\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Nodes { if i != 0 { @@ -4195,14 +4688,25 @@ func (x *GetNodeByPathResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -4369,11 +4873,22 @@ func (x *GetSubTreeRequest_Body_Order) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"direction\":" - out.RawString(prefix[1:]) - out.Int32(int32(x.Direction)) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"direction\":" + out.RawString(prefix) + v := int32(x.Direction) + if vv, ok := GetSubTreeRequest_Body_Order_Direction_name[v]; ok { + out.String(vv) + } else { + out.Int32(v) + } } out.RawByte('}') } @@ -4619,41 +5134,82 @@ func (x *GetSubTreeRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"rootId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"rootId\":" out.RawString(prefix) out.RawByte('[') for i := range x.RootId { if i != 0 { out.RawByte(',') } - out.Uint64(x.RootId[i]) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.RootId[i], 10) + out.RawByte('"') } out.RawByte(']') } { - const prefix string = ",\"depth\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"depth\":" out.RawString(prefix) out.Uint32(x.Depth) } { - const prefix string = ",\"bearerToken\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"bearerToken\":" out.RawString(prefix) - out.Base64Bytes(x.BearerToken) + if x.BearerToken != nil { + out.Base64Bytes(x.BearerToken) + } else { + out.String("") + } } { - const prefix string = ",\"orderBy\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"orderBy\":" out.RawString(prefix) x.OrderBy.MarshalEasyJSON(out) } @@ -4688,7 +5244,13 @@ func (x *GetSubTreeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -4703,7 +5265,15 @@ func (x *GetSubTreeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list []uint64 in.Delim('[') for !in.IsDelim(']') { - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv list = append(list, f) in.WantComma() } @@ -4713,13 +5283,27 @@ func (x *GetSubTreeRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "depth": { var f uint32 - f = in.Uint32() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 32) + if err != nil { + in.AddError(err) + return + } + pv := uint32(v) + f = pv x.Depth = f } case "bearerToken": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.BearerToken = f } case "orderBy": @@ -4862,14 +5446,25 @@ func (x *GetSubTreeRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -5076,45 +5671,72 @@ func (x *GetSubTreeResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"nodeId\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"nodeId\":" + out.RawString(prefix) out.RawByte('[') for i := range x.NodeId { if i != 0 { out.RawByte(',') } - out.Uint64(x.NodeId[i]) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.NodeId[i], 10) + out.RawByte('"') } out.RawByte(']') } { - const prefix string = ",\"parentId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"parentId\":" out.RawString(prefix) out.RawByte('[') for i := range x.ParentId { if i != 0 { out.RawByte(',') } - out.Uint64(x.ParentId[i]) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.ParentId[i], 10) + out.RawByte('"') } out.RawByte(']') } { - const prefix string = ",\"timestamp\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"timestamp\":" out.RawString(prefix) out.RawByte('[') for i := range x.Timestamp { if i != 0 { out.RawByte(',') } - out.Uint64(x.Timestamp[i]) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.Timestamp[i], 10) + out.RawByte('"') } out.RawByte(']') } { - const prefix string = ",\"meta\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"meta\":" out.RawString(prefix) out.RawByte('[') for i := range x.Meta { @@ -5159,7 +5781,15 @@ func (x *GetSubTreeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list []uint64 in.Delim('[') for !in.IsDelim(']') { - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv list = append(list, f) in.WantComma() } @@ -5172,7 +5802,15 @@ func (x *GetSubTreeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list []uint64 in.Delim('[') for !in.IsDelim(']') { - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv list = append(list, f) in.WantComma() } @@ -5185,7 +5823,15 @@ func (x *GetSubTreeResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { var list []uint64 in.Delim('[') for !in.IsDelim(']') { - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv list = append(list, f) in.WantComma() } @@ -5339,14 +5985,25 @@ func (x *GetSubTreeResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -5481,11 +6138,21 @@ func (x *TreeListRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } out.RawByte('}') } @@ -5518,7 +6185,13 @@ func (x *TreeListRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } } @@ -5654,14 +6327,25 @@ func (x *TreeListRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -5796,10 +6480,16 @@ func (x *TreeListResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"ids\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"ids\":" + out.RawString(prefix) out.RawByte('[') for i := range x.Ids { if i != 0 { @@ -5983,14 +6673,25 @@ func (x *TreeListResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -6168,19 +6869,39 @@ func (x *ApplyRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"operation\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"operation\":" out.RawString(prefix) x.Operation.MarshalEasyJSON(out) } @@ -6215,7 +6936,13 @@ func (x *ApplyRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -6364,14 +7091,25 @@ func (x *ApplyRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -6645,14 +7383,25 @@ func (x *ApplyResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -6847,26 +7596,55 @@ func (x *GetOpLogRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"containerId\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.ContainerId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + if x.ContainerId != nil { + out.Base64Bytes(x.ContainerId) + } else { + out.String("") + } } { - const prefix string = ",\"treeId\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"treeId\":" out.RawString(prefix) out.String(x.TreeId) } { - const prefix string = ",\"height\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"height\":" out.RawString(prefix) - out.Uint64(x.Height) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.Height, 10) + out.RawByte('"') } { - const prefix string = ",\"count\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"count\":" out.RawString(prefix) - out.Uint64(x.Count) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.Count, 10) + out.RawByte('"') } out.RawByte('}') } @@ -6899,7 +7677,13 @@ func (x *GetOpLogRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "containerId": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.ContainerId = f } case "treeId": @@ -6911,13 +7695,29 @@ func (x *GetOpLogRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { case "height": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.Height = f } case "count": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.Count = f } } @@ -7053,14 +7853,25 @@ func (x *GetOpLogRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -7198,10 +8009,16 @@ func (x *GetOpLogResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"operation\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"operation\":" + out.RawString(prefix) x.Operation.MarshalEasyJSON(out) } out.RawByte('}') @@ -7372,14 +8189,25 @@ func (x *GetOpLogResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -7653,14 +8481,25 @@ func (x *HealthcheckResponse) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } @@ -7934,14 +8773,25 @@ func (x *HealthcheckRequest) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"body\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) x.Body.MarshalEasyJSON(out) } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) x.Signature.MarshalEasyJSON(out) } diff --git a/pkg/services/tree/types_frostfs.pb.go b/pkg/services/tree/types_frostfs.pb.go index 13f1a43be8..2827b10a94 100644 --- a/pkg/services/tree/types_frostfs.pb.go +++ b/pkg/services/tree/types_frostfs.pb.go @@ -11,6 +11,7 @@ import ( easyproto "github.com/VictoriaMetrics/easyproto" jlexer "github.com/mailru/easyjson/jlexer" jwriter "github.com/mailru/easyjson/jwriter" + strconv "strconv" ) type KeyValue struct { @@ -113,16 +114,31 @@ func (x *KeyValue) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"key\":" - out.RawString(prefix[1:]) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"key\":" + out.RawString(prefix) out.String(x.Key) } { - const prefix string = ",\"value\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"value\":" out.RawString(prefix) - out.Base64Bytes(x.Value) + if x.Value != nil { + out.Base64Bytes(x.Value) + } else { + out.String("") + } } out.RawByte('}') } @@ -161,7 +177,13 @@ func (x *KeyValue) UnmarshalEasyJSON(in *jlexer.Lexer) { case "value": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Value = f } } @@ -293,21 +315,45 @@ func (x *LogMove) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"parentID\":" - out.RawString(prefix[1:]) - out.Uint64(x.ParentId) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"parentID\":" + out.RawString(prefix) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.ParentId, 10) + out.RawByte('"') } { - const prefix string = ",\"meta\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"meta\":" out.RawString(prefix) - out.Base64Bytes(x.Meta) + if x.Meta != nil { + out.Base64Bytes(x.Meta) + } else { + out.String("") + } } { - const prefix string = ",\"childID\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"childID\":" out.RawString(prefix) - out.Uint64(x.ChildId) + out.RawByte('"') + out.Buffer.Buf = strconv.AppendUint(out.Buffer.Buf, x.ChildId, 10) + out.RawByte('"') } out.RawByte('}') } @@ -340,19 +386,41 @@ func (x *LogMove) UnmarshalEasyJSON(in *jlexer.Lexer) { case "parentID": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.ParentId = f } case "meta": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Meta = f } case "childID": { var f uint64 - f = in.Uint64() + r := in.JsonNumber() + n := r.String() + v, err := strconv.ParseUint(n, 10, 64) + if err != nil { + in.AddError(err) + return + } + pv := uint64(v) + f = pv x.ChildId = f } } @@ -464,16 +532,35 @@ func (x *Signature) MarshalEasyJSON(out *jwriter.Writer) { out.RawString("null") return } + first := true out.RawByte('{') { - const prefix string = ",\"key\":" - out.RawString(prefix[1:]) - out.Base64Bytes(x.Key) + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"key\":" + out.RawString(prefix) + if x.Key != nil { + out.Base64Bytes(x.Key) + } else { + out.String("") + } } { - const prefix string = ",\"signature\":" + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" out.RawString(prefix) - out.Base64Bytes(x.Sign) + if x.Sign != nil { + out.Base64Bytes(x.Sign) + } else { + out.String("") + } } out.RawByte('}') } @@ -506,13 +593,25 @@ func (x *Signature) UnmarshalEasyJSON(in *jlexer.Lexer) { case "key": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Key = f } case "signature": { var f []byte - f = in.Bytes() + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } x.Sign = f } } From b1a31281e4901e73d93a5690ccb9ac6ae3e2aa4f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 8 Nov 2024 09:51:14 +0300 Subject: [PATCH 0970/1413] [#1480] ape: Remove SoftAPECheck flag Previous release was EACL-compatible. Starting from now all EACL should've been migrated to APE chains. Signed-off-by: Evgenii Stratonikov --- pkg/services/common/ape/checker.go | 5 +- pkg/services/object/acl/acl.go | 48 ------------ pkg/services/object/acl/acl_test.go | 89 ----------------------- pkg/services/object/acl/v2/errors.go | 7 -- pkg/services/object/acl/v2/errors_test.go | 10 --- pkg/services/object/acl/v2/request.go | 7 -- pkg/services/object/acl/v2/service.go | 67 ----------------- pkg/services/object/acl/v2/types.go | 11 --- pkg/services/object/ape/checker.go | 4 - pkg/services/object/ape/service.go | 12 --- pkg/services/object/request_context.go | 2 - pkg/services/tree/ape.go | 1 - 12 files changed, 1 insertion(+), 262 deletions(-) delete mode 100644 pkg/services/object/acl/acl_test.go diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index 278f6da315..eb4fd03c73 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -44,9 +44,6 @@ type CheckPrm struct { // The request's bearer token. It is used in order to check APE overrides with the token. BearerToken *bearer.Token - - // If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow. - SoftAPECheck bool } // CheckCore provides methods to perform the common logic of APE check. @@ -104,7 +101,7 @@ func (c *checkerCoreImpl) CheckAPE(prm CheckPrm) error { if err != nil { return err } - if !found && prm.SoftAPECheck || status == apechain.Allow { + if found && status == apechain.Allow { return nil } err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", prm.Request.Operation(), status.String()) diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go index 921545c8ba..53ba652e18 100644 --- a/pkg/services/object/acl/acl.go +++ b/pkg/services/object/acl/acl.go @@ -3,7 +3,6 @@ package acl import ( "context" "crypto/ecdsa" - "crypto/elliptic" "errors" "fmt" "io" @@ -22,7 +21,6 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) // Checker implements v2.ACLChecker interfaces and provides @@ -72,33 +70,6 @@ func NewChecker( } } -// CheckBasicACL is a main check function for basic ACL. -func (c *Checker) CheckBasicACL(info v2.RequestInfo) bool { - // check basic ACL permissions - return info.BasicACL().IsOpAllowed(info.Operation(), info.RequestRole()) -} - -// StickyBitCheck validates owner field in the request if sticky bit is enabled. -func (c *Checker) StickyBitCheck(info v2.RequestInfo, owner user.ID) bool { - // According to FrostFS specification sticky bit has no effect on system nodes - // for correct intra-container work with objects (in particular, replication). - if info.RequestRole() == acl.RoleContainer { - return true - } - - if !info.BasicACL().Sticky() { - return true - } - - if len(info.SenderKey()) == 0 { - return false - } - - requestSenderKey := unmarshalPublicKey(info.SenderKey()) - - return isOwnerFromKey(owner, requestSenderKey) -} - // CheckEACL is a main check function for extended ACL. func (c *Checker) CheckEACL(msg any, reqInfo v2.RequestInfo) error { basicACL := reqInfo.BasicACL() @@ -241,22 +212,3 @@ func isValidBearer(reqInfo v2.RequestInfo, st netmap.State) error { return nil } - -func isOwnerFromKey(id user.ID, key *keys.PublicKey) bool { - if key == nil { - return false - } - - var id2 user.ID - user.IDFromKey(&id2, (ecdsa.PublicKey)(*key)) - - return id.Equals(id2) -} - -func unmarshalPublicKey(bs []byte) *keys.PublicKey { - pub, err := keys.NewPublicKeyFromBytes(bs, elliptic.P256()) - if err != nil { - return nil - } - return pub -} diff --git a/pkg/services/object/acl/acl_test.go b/pkg/services/object/acl/acl_test.go deleted file mode 100644 index d63cb12856..0000000000 --- a/pkg/services/object/acl/acl_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package acl - -import ( - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" - v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" - "github.com/stretchr/testify/require" -) - -type emptyEACLSource struct{} - -func (e emptyEACLSource) GetEACL(_ cid.ID) (*container.EACL, error) { - return nil, nil -} - -type emptyNetmapState struct{} - -func (e emptyNetmapState) CurrentEpoch() uint64 { - return 0 -} - -func TestStickyCheck(t *testing.T) { - checker := NewChecker( - emptyNetmapState{}, - emptyEACLSource{}, - eaclSDK.NewValidator(), - &engine.StorageEngine{}) - - t.Run("system role", func(t *testing.T) { - var info v2.RequestInfo - - info.SetSenderKey(make([]byte, 33)) // any non-empty key - info.SetRequestRole(acl.RoleContainer) - - require.True(t, checker.StickyBitCheck(info, usertest.ID())) - - var basicACL acl.Basic - basicACL.MakeSticky() - - info.SetBasicACL(basicACL) - - require.True(t, checker.StickyBitCheck(info, usertest.ID())) - }) - - t.Run("owner ID and/or public key emptiness", func(t *testing.T) { - var info v2.RequestInfo - - info.SetRequestRole(acl.RoleOthers) // should be non-system role - - assertFn := func(isSticky, withKey, withOwner, expected bool) { - info := info - if isSticky { - var basicACL acl.Basic - basicACL.MakeSticky() - - info.SetBasicACL(basicACL) - } - - if withKey { - info.SetSenderKey(make([]byte, 33)) - } else { - info.SetSenderKey(nil) - } - - var ownerID user.ID - - if withOwner { - ownerID = usertest.ID() - } - - require.Equal(t, expected, checker.StickyBitCheck(info, ownerID)) - } - - assertFn(true, false, false, false) - assertFn(true, true, false, false) - assertFn(true, false, true, false) - assertFn(false, false, false, true) - assertFn(false, true, false, true) - assertFn(false, false, true, true) - assertFn(false, true, true, true) - }) -} diff --git a/pkg/services/object/acl/v2/errors.go b/pkg/services/object/acl/v2/errors.go index 11b9e6e5fb..e969d37fa0 100644 --- a/pkg/services/object/acl/v2/errors.go +++ b/pkg/services/object/acl/v2/errors.go @@ -26,13 +26,6 @@ const ( accessDeniedEACLReasonFmt = "access to operation %s is denied by extended ACL check: %v" ) -func basicACLErr(info RequestInfo) error { - errAccessDenied := &apistatus.ObjectAccessDenied{} - errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedACLReasonFmt, info.operation)) - - return errAccessDenied -} - func eACLErr(info RequestInfo, err error) error { errAccessDenied := &apistatus.ObjectAccessDenied{} errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedEACLReasonFmt, info.operation, err)) diff --git a/pkg/services/object/acl/v2/errors_test.go b/pkg/services/object/acl/v2/errors_test.go index 2d2b7bc8db..3cc74e6aad 100644 --- a/pkg/services/object/acl/v2/errors_test.go +++ b/pkg/services/object/acl/v2/errors_test.go @@ -8,16 +8,6 @@ import ( "github.com/stretchr/testify/require" ) -func TestBasicACLErr(t *testing.T) { - var reqInfo RequestInfo - err := basicACLErr(reqInfo) - - var errAccessDenied *apistatus.ObjectAccessDenied - - require.ErrorAs(t, err, &errAccessDenied, - "basicACLErr must be able to be casted to apistatus.ObjectAccessDenied") -} - func TestEACLErr(t *testing.T) { var reqInfo RequestInfo testErr := errors.New("test-eacl") diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go index e35cd2e116..8bd34ccb36 100644 --- a/pkg/services/object/acl/v2/request.go +++ b/pkg/services/object/acl/v2/request.go @@ -104,13 +104,6 @@ func (r RequestInfo) RequestRole() acl.Role { return r.requestRole } -// IsSoftAPECheck states if APE should perform soft checks. -// Soft APE check allows a request if CheckAPE returns NoRuleFound for it, -// otherwise it denies the request. -func (r RequestInfo) IsSoftAPECheck() bool { - return r.BasicACL().Bits() != 0 -} - // MetaWithToken groups session and bearer tokens, // verification header and raw API request. type MetaWithToken struct { diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index e02a3be36e..9f5ac5a27b 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -123,7 +123,6 @@ func (w *wrappedGetObjectStream) Context() context.Context { ContainerOwner: w.requestInfo.ContainerOwner(), SenderKey: w.requestInfo.SenderKey(), Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), BearerToken: w.requestInfo.Bearer(), }) } @@ -149,7 +148,6 @@ func (w *wrappedRangeStream) Context() context.Context { ContainerOwner: w.requestInfo.ContainerOwner(), SenderKey: w.requestInfo.SenderKey(), Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), BearerToken: w.requestInfo.Bearer(), }) } @@ -175,7 +173,6 @@ func (w *wrappedSearchStream) Context() context.Context { ContainerOwner: w.requestInfo.ContainerOwner(), SenderKey: w.requestInfo.SenderKey(), Role: w.requestInfo.RequestRole(), - SoftAPECheck: w.requestInfo.IsSoftAPECheck(), BearerToken: w.requestInfo.Bearer(), }) } @@ -231,14 +228,6 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream reqInfo.obj = obj - if reqInfo.IsSoftAPECheck() { - if !b.checker.CheckBasicACL(reqInfo) { - return basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return eACLErr(reqInfo, err) - } - } - return b.next.Get(request, &getStreamBasicChecker{ GetObjectStream: newWrappedGetObjectStreamStream(stream, reqInfo), info: reqInfo, @@ -309,14 +298,6 @@ func (b Service) Head( reqInfo.obj = obj - if reqInfo.IsSoftAPECheck() { - if !b.checker.CheckBasicACL(reqInfo) { - return nil, basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) - } - } - resp, err := b.next.Head(requestContext(ctx, reqInfo), request) if err == nil { if err = b.checker.CheckEACL(resp, reqInfo); err != nil { @@ -362,14 +343,6 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr return err } - if reqInfo.IsSoftAPECheck() { - if !b.checker.CheckBasicACL(reqInfo) { - return basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return eACLErr(reqInfo, err) - } - } - return b.next.Search(request, &searchStreamBasicChecker{ checker: b.checker, SearchStream: newWrappedSearchStream(stream, reqInfo), @@ -422,14 +395,6 @@ func (b Service) Delete( reqInfo.obj = obj - if reqInfo.IsSoftAPECheck() { - if !b.checker.CheckBasicACL(reqInfo) { - return nil, basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) - } - } - return b.next.Delete(requestContext(ctx, reqInfo), request) } @@ -475,14 +440,6 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb reqInfo.obj = obj - if reqInfo.IsSoftAPECheck() { - if !b.checker.CheckBasicACL(reqInfo) { - return basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return eACLErr(reqInfo, err) - } - } - return b.next.GetRange(request, &rangeStreamBasicChecker{ checker: b.checker, GetObjectRangeStream: newWrappedRangeStream(stream, reqInfo), @@ -496,7 +453,6 @@ func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { ContainerOwner: reqInfo.ContainerOwner(), SenderKey: reqInfo.SenderKey(), Role: reqInfo.RequestRole(), - SoftAPECheck: reqInfo.IsSoftAPECheck(), BearerToken: reqInfo.Bearer(), }) } @@ -546,14 +502,6 @@ func (b Service) GetRangeHash( reqInfo.obj = obj - if reqInfo.IsSoftAPECheck() { - if !b.checker.CheckBasicACL(reqInfo) { - return nil, basicACLErr(reqInfo) - } else if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) - } - } - return b.next.GetRangeHash(requestContext(ctx, reqInfo), request) } @@ -605,15 +553,6 @@ func (b Service) PutSingle(ctx context.Context, request *objectV2.PutSingleReque reqInfo.obj = obj - if reqInfo.IsSoftAPECheck() { - if !b.checker.CheckBasicACL(reqInfo) || !b.checker.StickyBitCheck(reqInfo, idOwner) { - return nil, basicACLErr(reqInfo) - } - if err := b.checker.CheckEACL(request, reqInfo); err != nil { - return nil, eACLErr(reqInfo, err) - } - } - return b.next.PutSingle(requestContext(ctx, reqInfo), request) } @@ -679,12 +618,6 @@ func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRe reqInfo.obj = obj - if reqInfo.IsSoftAPECheck() { - if !p.source.checker.CheckBasicACL(reqInfo) || !p.source.checker.StickyBitCheck(reqInfo, idOwner) { - return basicACLErr(reqInfo) - } - } - ctx = requestContext(ctx, reqInfo) } diff --git a/pkg/services/object/acl/v2/types.go b/pkg/services/object/acl/v2/types.go index 061cd26b62..6ae80e9c2d 100644 --- a/pkg/services/object/acl/v2/types.go +++ b/pkg/services/object/acl/v2/types.go @@ -1,22 +1,11 @@ package v2 -import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" -) - // ACLChecker is an interface that must provide // ACL related checks. type ACLChecker interface { - // CheckBasicACL must return true only if request - // passes basic ACL validation. - CheckBasicACL(RequestInfo) bool // CheckEACL must return non-nil error if request // doesn't pass extended ACL validation. CheckEACL(any, RequestInfo) error - // StickyBitCheck must return true only if sticky bit - // is disabled or enabled but request contains correct - // owner field. - StickyBitCheck(RequestInfo, user.ID) bool } // InnerRingFetcher is an interface that must provide diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index abcd2f4bbd..4a3b5ba5ee 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -64,9 +64,6 @@ type Prm struct { // An encoded container's owner user ID. ContainerOwner user.ID - // If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow. - SoftAPECheck bool - // The request's bearer token. It is used in order to check APE overrides with the token. BearerToken *bearer.Token @@ -109,6 +106,5 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { Container: prm.Container, ContainerOwner: prm.ContainerOwner, BearerToken: prm.BearerToken, - SoftAPECheck: prm.SoftAPECheck, }) } diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index c114f02f64..558c48da8e 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -84,8 +84,6 @@ type getStreamBasicChecker struct { role string - softAPECheck bool - bearerToken *bearer.Token } @@ -105,7 +103,6 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { SenderKey: hex.EncodeToString(g.senderKey), ContainerOwner: g.containerOwner, Role: g.role, - SoftAPECheck: g.softAPECheck, BearerToken: g.bearerToken, XHeaders: resp.GetMetaHeader().GetXHeaders(), } @@ -142,7 +139,6 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt senderKey: reqCtx.SenderKey, containerOwner: reqCtx.ContainerOwner, role: nativeSchemaRole(reqCtx.Role), - softAPECheck: reqCtx.SoftAPECheck, bearerToken: reqCtx.BearerToken, }) } @@ -174,7 +170,6 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, Role: nativeSchemaRole(reqCtx.Role), - SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, XHeaders: request.GetMetaHeader().GetXHeaders(), } @@ -230,7 +225,6 @@ func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.Pa SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, Role: nativeSchemaRole(reqCtx.Role), - SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, XHeaders: request.GetMetaHeader().GetXHeaders(), } @@ -300,7 +294,6 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj Role: nativeSchemaRole(reqCtx.Role), SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, XHeaders: request.GetMetaHeader().GetXHeaders(), }) @@ -330,7 +323,6 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc Role: nativeSchemaRole(reqCtx.Role), SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, XHeaders: request.GetMetaHeader().GetXHeaders(), }) @@ -360,7 +352,6 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( Role: nativeSchemaRole(reqCtx.Role), SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, XHeaders: request.GetMetaHeader().GetXHeaders(), }) @@ -395,7 +386,6 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G Role: nativeSchemaRole(reqCtx.Role), SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, XHeaders: request.GetMetaHeader().GetXHeaders(), }) @@ -425,7 +415,6 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa Role: nativeSchemaRole(reqCtx.Role), SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, XHeaders: request.GetMetaHeader().GetXHeaders(), } @@ -461,7 +450,6 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ Role: nativeSchemaRole(reqCtx.Role), SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, - SoftAPECheck: reqCtx.SoftAPECheck, BearerToken: reqCtx.BearerToken, XHeaders: request.GetMetaHeader().GetXHeaders(), } diff --git a/pkg/services/object/request_context.go b/pkg/services/object/request_context.go index 95d4c9d935..eb4041f808 100644 --- a/pkg/services/object/request_context.go +++ b/pkg/services/object/request_context.go @@ -20,7 +20,5 @@ type RequestContext struct { Role acl.Role - SoftAPECheck bool - BearerToken *bearer.Token } diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 69cf594056..606044f8ed 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -81,7 +81,6 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, ContainerOwner: container.Value.Owner(), PublicKey: publicKey, BearerToken: bt, - SoftAPECheck: false, }) } From f666898e5d19e34a571848ecd0a78dbbea3a1b34 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 8 Nov 2024 10:05:37 +0300 Subject: [PATCH 0971/1413] [#1480] objsvc: Remove EACL checks Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/object.go | 9 - pkg/services/object/acl/acl.go | 214 ---------------------- pkg/services/object/acl/v2/errors.go | 14 -- pkg/services/object/acl/v2/errors_test.go | 20 -- pkg/services/object/acl/v2/service.go | 45 +---- pkg/services/object/acl/v2/types.go | 8 - 6 files changed, 1 insertion(+), 309 deletions(-) delete mode 100644 pkg/services/object/acl/acl.go delete mode 100644 pkg/services/object/acl/v2/errors_test.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 7f26393a77..629f79207b 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -19,7 +19,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache" objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc" objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl" v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" objectAPE "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/ape" objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" @@ -39,7 +38,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -458,17 +456,10 @@ func createSplitService(c *cfg, sPutV2 *putsvcV2.Service, sGetV2 *getsvcV2.Servi } func createACLServiceV2(c *cfg, apeSvc *objectAPE.Service, irFetcher *cachedIRFetcher) v2.Service { - ls := c.cfgObject.cfgLocalStorage.localStorage - return v2.New( apeSvc, c.netMapSource, irFetcher, - acl.NewChecker( - c.cfgNetmap.state, - c.cfgObject.eaclSource, - eaclSDK.NewValidator(), - ls), c.cfgObject.cnrSource, v2.WithLogger(c.log), ) diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go deleted file mode 100644 index 53ba652e18..0000000000 --- a/pkg/services/object/acl/acl.go +++ /dev/null @@ -1,214 +0,0 @@ -package acl - -import ( - "context" - "crypto/ecdsa" - "errors" - "fmt" - "io" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" - eaclV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/eacl/v2" - v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" - bearerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" -) - -// Checker implements v2.ACLChecker interfaces and provides -// ACL/eACL validation functionality. -type Checker struct { - eaclSrc container.EACLSource - validator *eaclSDK.Validator - localStorage *engine.StorageEngine - state netmap.State -} - -type localStorage struct { - ls *engine.StorageEngine -} - -func (s *localStorage) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) { - if s.ls == nil { - return nil, io.ErrUnexpectedEOF - } - - return engine.Head(ctx, s.ls, addr) -} - -// Various EACL check errors. -var ( - errEACLDeniedByRule = errors.New("denied by rule") - errBearerExpired = errors.New("bearer token has expired") - errBearerInvalidSignature = errors.New("bearer token has invalid signature") - errBearerInvalidContainerID = errors.New("bearer token was created for another container") - errBearerNotSignedByOwner = errors.New("bearer token is not signed by the container owner") - errBearerInvalidOwner = errors.New("bearer token owner differs from the request sender") -) - -// NewChecker creates Checker. -// Panics if at least one of the parameter is nil. -func NewChecker( - state netmap.State, - eaclSrc container.EACLSource, - validator *eaclSDK.Validator, - localStorage *engine.StorageEngine, -) *Checker { - return &Checker{ - eaclSrc: eaclSrc, - validator: validator, - localStorage: localStorage, - state: state, - } -} - -// CheckEACL is a main check function for extended ACL. -func (c *Checker) CheckEACL(msg any, reqInfo v2.RequestInfo) error { - basicACL := reqInfo.BasicACL() - if !basicACL.Extendable() { - return nil - } - - bearerTok := reqInfo.Bearer() - impersonate := bearerTok != nil && bearerTok.Impersonate() - - // if bearer token is not allowed, then ignore it - if impersonate || !basicACL.AllowedBearerRules(reqInfo.Operation()) { - reqInfo.CleanBearer() - } - - var table eaclSDK.Table - cnr := reqInfo.ContainerID() - - if bearerTok == nil { - eaclInfo, err := c.eaclSrc.GetEACL(cnr) - if err != nil { - if client.IsErrEACLNotFound(err) { - return nil - } - return err - } - - table = *eaclInfo.Value - } else { - table = bearerTok.EACLTable() - } - - // if bearer token is not present, isValidBearer returns true - if err := isValidBearer(reqInfo, c.state); err != nil { - return err - } - - hdrSrc, err := c.getHeaderSource(cnr, msg, reqInfo) - if err != nil { - return err - } - - eaclRole := getRole(reqInfo) - - action, _ := c.validator.CalculateAction(new(eaclSDK.ValidationUnit). - WithRole(eaclRole). - WithOperation(eaclSDK.Operation(reqInfo.Operation())). - WithContainerID(&cnr). - WithSenderKey(reqInfo.SenderKey()). - WithHeaderSource(hdrSrc). - WithEACLTable(&table), - ) - - if action != eaclSDK.ActionAllow { - return errEACLDeniedByRule - } - return nil -} - -func getRole(reqInfo v2.RequestInfo) eaclSDK.Role { - var eaclRole eaclSDK.Role - switch op := reqInfo.RequestRole(); op { - default: - eaclRole = eaclSDK.Role(op) - case acl.RoleOwner: - eaclRole = eaclSDK.RoleUser - case acl.RoleInnerRing, acl.RoleContainer: - eaclRole = eaclSDK.RoleSystem - case acl.RoleOthers: - eaclRole = eaclSDK.RoleOthers - } - return eaclRole -} - -func (c *Checker) getHeaderSource(cnr cid.ID, msg any, reqInfo v2.RequestInfo) (eaclSDK.TypedHeaderSource, error) { - var xHeaderSource eaclV2.XHeaderSource - if req, ok := msg.(eaclV2.Request); ok { - xHeaderSource = eaclV2.NewRequestXHeaderSource(req) - } else { - xHeaderSource = eaclV2.NewResponseXHeaderSource(msg.(eaclV2.Response), reqInfo.Request().(eaclV2.Request)) - } - - hdrSrc, err := eaclV2.NewMessageHeaderSource(&localStorage{ls: c.localStorage}, xHeaderSource, cnr, eaclV2.WithOID(reqInfo.ObjectID())) - if err != nil { - return nil, fmt.Errorf("can't parse headers: %w", err) - } - return hdrSrc, nil -} - -// isValidBearer checks whether bearer token was correctly signed by authorized -// entity. This method might be defined on whole ACL service because it will -// require fetching current epoch to check lifetime. -func isValidBearer(reqInfo v2.RequestInfo, st netmap.State) error { - ownerCnr := reqInfo.ContainerOwner() - - token := reqInfo.Bearer() - - // 0. Check if bearer token is present in reqInfo. - if token == nil { - return nil - } - - // 1. First check token lifetime. Simplest verification. - if token.InvalidAt(st.CurrentEpoch()) { - return errBearerExpired - } - - // 2. Then check if bearer token is signed correctly. - if !token.VerifySignature() { - return errBearerInvalidSignature - } - - // 3. Then check if container is either empty or equal to the container in the request. - cnr, isSet := token.EACLTable().CID() - if isSet && !cnr.Equals(reqInfo.ContainerID()) { - return errBearerInvalidContainerID - } - - // 4. Then check if container owner signed this token. - if !bearerSDK.ResolveIssuer(*token).Equals(ownerCnr) { - // TODO: #767 in this case we can issue all owner keys from frostfs.id and check once again - return errBearerNotSignedByOwner - } - - // 5. Then check if request sender has rights to use this token. - var keySender frostfsecdsa.PublicKey - - err := keySender.Decode(reqInfo.SenderKey()) - if err != nil { - return fmt.Errorf("decode sender public key: %w", err) - } - - var usrSender user.ID - user.IDFromKey(&usrSender, ecdsa.PublicKey(keySender)) - - if !token.AssertUser(usrSender) { - // TODO: #767 in this case we can issue all owner keys from frostfs.id and check once again - return errBearerInvalidOwner - } - - return nil -} diff --git a/pkg/services/object/acl/v2/errors.go b/pkg/services/object/acl/v2/errors.go index e969d37fa0..cd2de174ae 100644 --- a/pkg/services/object/acl/v2/errors.go +++ b/pkg/services/object/acl/v2/errors.go @@ -2,8 +2,6 @@ package v2 import ( "fmt" - - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) const invalidRequestMessage = "malformed request" @@ -20,15 +18,3 @@ var ( errInvalidSessionOwner = malformedRequestError("invalid session token owner") errInvalidVerb = malformedRequestError("session token verb is invalid") ) - -const ( - accessDeniedACLReasonFmt = "access to operation %s is denied by basic ACL check" - accessDeniedEACLReasonFmt = "access to operation %s is denied by extended ACL check: %v" -) - -func eACLErr(info RequestInfo, err error) error { - errAccessDenied := &apistatus.ObjectAccessDenied{} - errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedEACLReasonFmt, info.operation, err)) - - return errAccessDenied -} diff --git a/pkg/services/object/acl/v2/errors_test.go b/pkg/services/object/acl/v2/errors_test.go deleted file mode 100644 index 3cc74e6aad..0000000000 --- a/pkg/services/object/acl/v2/errors_test.go +++ /dev/null @@ -1,20 +0,0 @@ -package v2 - -import ( - "errors" - "testing" - - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - "github.com/stretchr/testify/require" -) - -func TestEACLErr(t *testing.T) { - var reqInfo RequestInfo - testErr := errors.New("test-eacl") - err := eACLErr(reqInfo, testErr) - - var errAccessDenied *apistatus.ObjectAccessDenied - - require.ErrorAs(t, err, &errAccessDenied, - "eACLErr must be able to be casted to apistatus.ObjectAccessDenied") -} diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 9f5ac5a27b..69406e5b02 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -42,27 +42,15 @@ type patchStreamBasicChecker struct { } type getStreamBasicChecker struct { - checker ACLChecker - object.GetObjectStream - - info RequestInfo } type rangeStreamBasicChecker struct { - checker ACLChecker - object.GetObjectRangeStream - - info RequestInfo } type searchStreamBasicChecker struct { - checker ACLChecker - object.SearchStream - - info RequestInfo } // Option represents Service constructor option. @@ -73,8 +61,6 @@ type cfg struct { containers container.Source - checker ACLChecker - irFetcher InnerRingFetcher nm netmap.Source @@ -86,7 +72,6 @@ type cfg struct { func New(next object.ServiceServer, nm netmap.Source, irf InnerRingFetcher, - acl ACLChecker, cs container.Source, opts ...Option, ) Service { @@ -95,7 +80,6 @@ func New(next object.ServiceServer, next: next, nm: nm, irFetcher: irf, - checker: acl, containers: cs, } @@ -230,8 +214,6 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream return b.next.Get(request, &getStreamBasicChecker{ GetObjectStream: newWrappedGetObjectStreamStream(stream, reqInfo), - info: reqInfo, - checker: b.checker, }) } @@ -298,14 +280,7 @@ func (b Service) Head( reqInfo.obj = obj - resp, err := b.next.Head(requestContext(ctx, reqInfo), request) - if err == nil { - if err = b.checker.CheckEACL(resp, reqInfo); err != nil { - err = eACLErr(reqInfo, err) - } - } - - return resp, err + return b.next.Head(requestContext(ctx, reqInfo), request) } func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStream) error { @@ -344,9 +319,7 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr } return b.next.Search(request, &searchStreamBasicChecker{ - checker: b.checker, SearchStream: newWrappedSearchStream(stream, reqInfo), - info: reqInfo, }) } @@ -441,9 +414,7 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb reqInfo.obj = obj return b.next.GetRange(request, &rangeStreamBasicChecker{ - checker: b.checker, GetObjectRangeStream: newWrappedRangeStream(stream, reqInfo), - info: reqInfo, }) } @@ -657,28 +628,14 @@ func (p putStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PutR } func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { - if _, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok { - if err := g.checker.CheckEACL(resp, g.info); err != nil { - return eACLErr(g.info, err) - } - } - return g.GetObjectStream.Send(resp) } func (g *rangeStreamBasicChecker) Send(resp *objectV2.GetRangeResponse) error { - if err := g.checker.CheckEACL(resp, g.info); err != nil { - return eACLErr(g.info, err) - } - return g.GetObjectRangeStream.Send(resp) } func (g *searchStreamBasicChecker) Send(resp *objectV2.SearchResponse) error { - if err := g.checker.CheckEACL(resp, g.info); err != nil { - return eACLErr(g.info, err) - } - return g.SearchStream.Send(resp) } diff --git a/pkg/services/object/acl/v2/types.go b/pkg/services/object/acl/v2/types.go index 6ae80e9c2d..b03261b90f 100644 --- a/pkg/services/object/acl/v2/types.go +++ b/pkg/services/object/acl/v2/types.go @@ -1,13 +1,5 @@ package v2 -// ACLChecker is an interface that must provide -// ACL related checks. -type ACLChecker interface { - // CheckEACL must return non-nil error if request - // doesn't pass extended ACL validation. - CheckEACL(any, RequestInfo) error -} - // InnerRingFetcher is an interface that must provide // Inner Ring information. type InnerRingFetcher interface { From c82c753e9f67c70dfa99f98a34623fae3dfa5fce Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 8 Nov 2024 10:10:06 +0300 Subject: [PATCH 0972/1413] [#1480] objsvc: Remove useless stream wrappers Signed-off-by: Evgenii Stratonikov --- pkg/services/object/acl/v2/service.go | 36 +++------------------------ 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 69406e5b02..56748b08c5 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -41,18 +41,6 @@ type patchStreamBasicChecker struct { nonFirstSend bool } -type getStreamBasicChecker struct { - object.GetObjectStream -} - -type rangeStreamBasicChecker struct { - object.GetObjectRangeStream -} - -type searchStreamBasicChecker struct { - object.SearchStream -} - // Option represents Service constructor option. type Option func(*cfg) @@ -212,9 +200,7 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream reqInfo.obj = obj - return b.next.Get(request, &getStreamBasicChecker{ - GetObjectStream: newWrappedGetObjectStreamStream(stream, reqInfo), - }) + return b.next.Get(request, newWrappedGetObjectStreamStream(stream, reqInfo)) } func (b Service) Put() (object.PutObjectStream, error) { @@ -318,9 +304,7 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr return err } - return b.next.Search(request, &searchStreamBasicChecker{ - SearchStream: newWrappedSearchStream(stream, reqInfo), - }) + return b.next.Search(request, newWrappedSearchStream(stream, reqInfo)) } func (b Service) Delete( @@ -413,9 +397,7 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb reqInfo.obj = obj - return b.next.GetRange(request, &rangeStreamBasicChecker{ - GetObjectRangeStream: newWrappedRangeStream(stream, reqInfo), - }) + return b.next.GetRange(request, newWrappedRangeStream(stream, reqInfo)) } func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { @@ -627,18 +609,6 @@ func (p putStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PutR return p.next.CloseAndRecv(ctx) } -func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { - return g.GetObjectStream.Send(resp) -} - -func (g *rangeStreamBasicChecker) Send(resp *objectV2.GetRangeResponse) error { - return g.GetObjectRangeStream.Send(resp) -} - -func (g *searchStreamBasicChecker) Send(resp *objectV2.SearchResponse) error { - return g.SearchStream.Send(resp) -} - func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { body := request.GetBody() if body == nil { From d336f2d487abd5fd102d24d130749a6a6ddeb8c4 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 30 Oct 2024 17:39:02 +0300 Subject: [PATCH 0973/1413] [#1393] adm: Make `NewLocalActor` receive accout name * Some RPC-clients for contracts require different wallet account types. Since, `Policy` contract gets `consensus` accounts while `NNS` gets `committee` accounts. Signed-off-by: Airat Arifullin --- .../internal/modules/morph/ape/ape_util.go | 2 +- .../internal/modules/morph/helper/actor.go | 11 +++++++---- cmd/frostfs-adm/internal/modules/morph/nns/helper.go | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index d4aedda2ec..f4373c5354 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -139,7 +139,7 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *he c, err := helper.GetN3Client(viper.GetViper()) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - ac, err := helper.NewLocalActor(cmd, c) + ac, err := helper.NewLocalActor(cmd, c, constants.ConsensusAccountName) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) var ch util.Uint160 diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go index 1ca246f9f8..ff0421335c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go @@ -5,7 +5,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -31,7 +30,11 @@ type LocalActor struct { // NewLocalActor create LocalActor with accounts form provided wallets. // In case of empty wallets provided created actor with dummy account only for read operation. -func NewLocalActor(cmd *cobra.Command, c actor.RPCActor) (*LocalActor, error) { +// +// If wallets are provided, the contract client will use accounts with accName name from these wallets. +// To determine which account name should be used in a contract client, refer to how the contract +// verifies the transaction signature. +func NewLocalActor(cmd *cobra.Command, c actor.RPCActor, accName string) (*LocalActor, error) { walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) var act *actor.Actor var accounts []*wallet.Account @@ -53,8 +56,8 @@ func NewLocalActor(cmd *cobra.Command, c actor.RPCActor) (*LocalActor, error) { commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) for _, w := range wallets { - acc, err := GetWalletAccount(w, constants.CommitteeAccountName) - commonCmd.ExitOnErr(cmd, "can't find committee account: %w", err) + acc, err := GetWalletAccount(w, accName) + commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err) accounts = append(accounts, acc) } act, err = actor.New(c, []actor.SignerAccount{{ diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index 0eaa5ac58e..de439acd1d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -2,6 +2,7 @@ package nns import ( client "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" @@ -15,7 +16,7 @@ func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, uti c, err := helper.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - ac, err := helper.NewLocalActor(cmd, c) + ac, err := helper.NewLocalActor(cmd, c, constants.CommitteeAccountName) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) r := management.NewReader(ac.Invoker) From ad01fb958afd2c48e2efba03e5d22acdf8be7849 Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Wed, 6 Nov 2024 13:39:46 +0300 Subject: [PATCH 0974/1413] [#1474] Stop using obsolete .github directory This commit is a part of multi-repo cleanup effort: https://git.frostfs.info/TrueCloudLab/frostfs-infra/issues/136 Signed-off-by: Vitaliy Potyarkin --- {.github => .forgejo}/ISSUE_TEMPLATE/bug_report.md | 0 {.github => .forgejo}/ISSUE_TEMPLATE/config.yml | 0 {.github => .forgejo}/ISSUE_TEMPLATE/feature_request.md | 0 {.github => .forgejo}/logo.svg | 0 README.md | 2 +- docs/release-instruction.md | 8 ++++---- docs/update-go-instruction.md | 2 +- 7 files changed, 6 insertions(+), 6 deletions(-) rename {.github => .forgejo}/ISSUE_TEMPLATE/bug_report.md (100%) rename {.github => .forgejo}/ISSUE_TEMPLATE/config.yml (100%) rename {.github => .forgejo}/ISSUE_TEMPLATE/feature_request.md (100%) rename {.github => .forgejo}/logo.svg (100%) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.forgejo/ISSUE_TEMPLATE/bug_report.md similarity index 100% rename from .github/ISSUE_TEMPLATE/bug_report.md rename to .forgejo/ISSUE_TEMPLATE/bug_report.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.forgejo/ISSUE_TEMPLATE/config.yml similarity index 100% rename from .github/ISSUE_TEMPLATE/config.yml rename to .forgejo/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.forgejo/ISSUE_TEMPLATE/feature_request.md similarity index 100% rename from .github/ISSUE_TEMPLATE/feature_request.md rename to .forgejo/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/logo.svg b/.forgejo/logo.svg similarity index 100% rename from .github/logo.svg rename to .forgejo/logo.svg diff --git a/README.md b/README.md index 47d812b180..6998b6726b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- FrostFS + FrostFS

diff --git a/docs/release-instruction.md b/docs/release-instruction.md index d000f10d08..18659c699a 100644 --- a/docs/release-instruction.md +++ b/docs/release-instruction.md @@ -55,7 +55,7 @@ Add an entry to the `CHANGELOG.md` following the style established there. * update `Unreleased...new` and `new...old` diff-links at the bottom of the file * add optional codename and release date in the heading * remove all empty sections such as `Added`, `Removed`, etc. -* make sure all changes have references to GitHub issues in `#123` format (if possible) +* make sure all changes have references to relevant issues in `#123` format (if possible) * clean up all `Unreleased` sections and leave them empty ### Make release commit @@ -110,9 +110,9 @@ $ docker push truecloudlab/frostfs-cli:${FROSTFS_REVISION} $ docker push truecloudlab/frostfs-adm:${FROSTFS_REVISION} ``` -### Make a proper GitHub release (if not automated) +### Make a proper release (if not automated) -Edit an automatically-created release on GitHub, copy things from `CHANGELOG.md`. +Edit an automatically-created release on git.frostfs.info, copy things from `CHANGELOG.md`. Build and tar release binaries with `make prepare-release`, attach them to the release. Publish the release. @@ -121,7 +121,7 @@ the release. Publish the release. Prepare pull-request in [frostfs-devenv](https://git.frostfs.info/TrueCloudLab/frostfs-dev-env) with new versions. -### Close GitHub milestone +### Close milestone Look up [milestones](https://git.frostfs.info/TrueCloudLab/frostfs-node/milestones) and close the release one if exists. diff --git a/docs/update-go-instruction.md b/docs/update-go-instruction.md index f992250463..195e0c6b3e 100644 --- a/docs/update-go-instruction.md +++ b/docs/update-go-instruction.md @@ -7,7 +7,7 @@ ## Update CI Change Golang versions for unit test in CI. -There is `go` section in `.github/workflows/go.yaml` file: +There is `go` section in `.forgejo/workflows/*.yml` files: ```yaml jobs: test: From 8a57c78f5f5e2098ec1b0085c709a2473d40adbb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Nov 2024 12:46:55 +0300 Subject: [PATCH 0975/1413] [#1484] engine: Fix engine metrics 1. Add forgotten metrics for client requests 2. Include execIfNotBlocked into metrics Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/container.go | 8 ++++---- pkg/local_object_storage/engine/delete.go | 3 +-- pkg/local_object_storage/engine/get.go | 3 +-- pkg/local_object_storage/engine/inhume.go | 3 +-- pkg/local_object_storage/engine/list.go | 5 +++++ pkg/local_object_storage/engine/lock.go | 1 + pkg/local_object_storage/engine/put.go | 3 +-- pkg/local_object_storage/engine/range.go | 19 +++++++++---------- pkg/local_object_storage/engine/select.go | 6 ++---- 9 files changed, 25 insertions(+), 26 deletions(-) diff --git a/pkg/local_object_storage/engine/container.go b/pkg/local_object_storage/engine/container.go index 6def02f12f..a52436175d 100644 --- a/pkg/local_object_storage/engine/container.go +++ b/pkg/local_object_storage/engine/container.go @@ -45,6 +45,8 @@ func (r ListContainersRes) Containers() []cid.ID { // // Returns an error if executions are blocked (see BlockExecution). func (e *StorageEngine) ContainerSize(prm ContainerSizePrm) (res ContainerSizeRes, err error) { + defer elapsed("ContainerSize", e.metrics.AddMethodDuration)() + err = e.execIfNotBlocked(func() error { res, err = e.containerSize(prm) return err @@ -68,8 +70,6 @@ func ContainerSize(e *StorageEngine, id cid.ID) (uint64, error) { } func (e *StorageEngine) containerSize(prm ContainerSizePrm) (res ContainerSizeRes, err error) { - defer elapsed("EstimateContainerSize", e.metrics.AddMethodDuration)() - e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { var csPrm shard.ContainerSizePrm csPrm.SetContainerID(prm.cnr) @@ -93,6 +93,8 @@ func (e *StorageEngine) containerSize(prm ContainerSizePrm) (res ContainerSizeRe // // Returns an error if executions are blocked (see BlockExecution). func (e *StorageEngine) ListContainers(ctx context.Context, _ ListContainersPrm) (res ListContainersRes, err error) { + defer elapsed("ListContainers", e.metrics.AddMethodDuration)() + err = e.execIfNotBlocked(func() error { res, err = e.listContainers(ctx) return err @@ -114,8 +116,6 @@ func ListContainers(ctx context.Context, e *StorageEngine) ([]cid.ID, error) { } func (e *StorageEngine) listContainers(ctx context.Context) (ListContainersRes, error) { - defer elapsed("ListContainers", e.metrics.AddMethodDuration)() - uniqueIDs := make(map[string]cid.ID) e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 3ec3f8f9b5..9ca3a7ceec 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -58,6 +58,7 @@ func (e *StorageEngine) Delete(ctx context.Context, prm DeletePrm) (res DeleteRe attribute.Bool("force_removal", prm.forceRemoval), )) defer span.End() + defer elapsed("Delete", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { res, err = e.delete(ctx, prm) @@ -68,8 +69,6 @@ func (e *StorageEngine) Delete(ctx context.Context, prm DeletePrm) (res DeleteRe } func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { - defer elapsed("Delete", e.metrics.AddMethodDuration)() - var locked struct { is bool } diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index 4a9199be70..a1fe8a0101 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -56,6 +56,7 @@ func (e *StorageEngine) Get(ctx context.Context, prm GetPrm) (res GetRes, err er attribute.String("address", prm.addr.EncodeToString()), )) defer span.End() + defer elapsed("Get", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { res, err = e.get(ctx, prm) @@ -66,8 +67,6 @@ func (e *StorageEngine) Get(ctx context.Context, prm GetPrm) (res GetRes, err er } func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { - defer elapsed("Get", e.metrics.AddMethodDuration)() - errNotFound := new(apistatus.ObjectNotFound) var shPrm shard.GetPrm diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 35ce50f653..b8959b5340 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -70,6 +70,7 @@ var errInhumeFailure = errors.New("inhume operation failed") func (e *StorageEngine) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRes, err error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Inhume") defer span.End() + defer elapsed("Inhume", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { res, err = e.inhume(ctx, prm) @@ -80,8 +81,6 @@ func (e *StorageEngine) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRe } func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { - defer elapsed("Inhume", e.metrics.AddMethodDuration)() - var shPrm shard.InhumePrm if prm.forceRemoval { shPrm.ForceRemoval() diff --git a/pkg/local_object_storage/engine/list.go b/pkg/local_object_storage/engine/list.go index cb3830b7c7..073248862b 100644 --- a/pkg/local_object_storage/engine/list.go +++ b/pkg/local_object_storage/engine/list.go @@ -7,6 +7,7 @@ import ( objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" ) // ErrEndOfListing is returned from an object listing with cursor @@ -98,6 +99,10 @@ func (l ListWithCursorRes) Cursor() *Cursor { // Returns ErrEndOfListing if there are no more objects to return or count // parameter set to zero. func (e *StorageEngine) ListWithCursor(ctx context.Context, prm ListWithCursorPrm) (ListWithCursorRes, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.ListWithCursor") + defer span.End() + defer elapsed("ListWithCursor", e.metrics.AddMethodDuration)() + result := make([]objectcore.Info, 0, prm.count) // Set initial cursors diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index ac8fa9c6fc..bbab59bfab 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -32,6 +32,7 @@ func (e *StorageEngine) Lock(ctx context.Context, idCnr cid.ID, locker oid.ID, l attribute.Int("locked_count", len(locked)), )) defer span.End() + defer elapsed("Lock", e.metrics.AddMethodDuration)() return e.execIfNotBlocked(func() error { return e.lock(ctx, idCnr, locker, locked) diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index a50d80b75d..56d3ef4901 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -56,6 +56,7 @@ func (e *StorageEngine) Put(ctx context.Context, prm PutPrm) (err error) { attribute.String("address", object.AddressOf(prm.Object).EncodeToString()), )) defer span.End() + defer elapsed("Put", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { err = e.put(ctx, prm) @@ -66,8 +67,6 @@ func (e *StorageEngine) Put(ctx context.Context, prm PutPrm) (err error) { } func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { - defer elapsed("Put", e.metrics.AddMethodDuration)() - addr := object.AddressOf(prm.Object) // In #1146 this check was parallelized, however, it became diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index 498674fd26..fde6052ae9 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -65,6 +65,15 @@ func (r RngRes) Object() *objectSDK.Object { // // Returns an error if executions are blocked (see BlockExecution). func (e *StorageEngine) GetRange(ctx context.Context, prm RngPrm) (res RngRes, err error) { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.getRange", + trace.WithAttributes( + attribute.String("address", prm.addr.EncodeToString()), + attribute.String("offset", strconv.FormatUint(prm.off, 10)), + attribute.String("length", strconv.FormatUint(prm.ln, 10)), + )) + defer span.End() + defer elapsed("GetRange", e.metrics.AddMethodDuration)() + err = e.execIfNotBlocked(func() error { res, err = e.getRange(ctx, prm) return err @@ -74,16 +83,6 @@ func (e *StorageEngine) GetRange(ctx context.Context, prm RngPrm) (res RngRes, e } func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error) { - ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.getRange", - trace.WithAttributes( - attribute.String("address", prm.addr.EncodeToString()), - attribute.String("offset", strconv.FormatUint(prm.off, 10)), - attribute.String("length", strconv.FormatUint(prm.ln, 10)), - )) - defer span.End() - - defer elapsed("GetRange", e.metrics.AddMethodDuration)() - var shPrm shard.RngPrm shPrm.SetAddress(prm.addr) shPrm.SetRange(prm.off, prm.ln) diff --git a/pkg/local_object_storage/engine/select.go b/pkg/local_object_storage/engine/select.go index a85891f0c5..0f1341f856 100644 --- a/pkg/local_object_storage/engine/select.go +++ b/pkg/local_object_storage/engine/select.go @@ -51,6 +51,7 @@ func (e *StorageEngine) Select(ctx context.Context, prm SelectPrm) (res SelectRe attribute.String("container_id", prm.cnr.EncodeToString()), )) defer span.End() + defer elapsed("Select", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { res, err = e._select(ctx, prm) @@ -61,8 +62,6 @@ func (e *StorageEngine) Select(ctx context.Context, prm SelectPrm) (res SelectRe } func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, error) { - defer elapsed("Search", e.metrics.AddMethodDuration)() - addrList := make([]oid.Address, 0) uniqueMap := make(map[string]struct{}) @@ -99,6 +98,7 @@ func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, // // Returns an error if executions are blocked (see BlockExecution). func (e *StorageEngine) List(ctx context.Context, limit uint64) (res SelectRes, err error) { + defer elapsed("List", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { res, err = e.list(ctx, limit) return err @@ -108,8 +108,6 @@ func (e *StorageEngine) List(ctx context.Context, limit uint64) (res SelectRes, } func (e *StorageEngine) list(ctx context.Context, limit uint64) (SelectRes, error) { - defer elapsed("ListObjects", e.metrics.AddMethodDuration)() - addrList := make([]oid.Address, 0, limit) uniqueMap := make(map[string]struct{}) ln := uint64(0) From 2f3bc6eb8421eb742d1304371d077015a74e218c Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 12 Nov 2024 11:07:48 +0300 Subject: [PATCH 0976/1413] [#1396] cli/playground: Improve terminal control key handling Signed-off-by: Alexander Chuprov --- .../modules/container/policy_playground.go | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 095ab64381..6885d35f27 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -1,11 +1,10 @@ package container import ( - "bufio" "encoding/hex" "encoding/json" + "errors" "fmt" - "io" "os" "strings" @@ -14,6 +13,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "github.com/chzyer/readline" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -163,6 +163,16 @@ func (repl *policyPlaygroundREPL) netMap() netmap.NetMap { return nm } +var policyPlaygroundCompleter = readline.NewPrefixCompleter( + readline.PcItem("list"), + readline.PcItem("ls"), + readline.PcItem("add"), + readline.PcItem("load"), + readline.PcItem("remove"), + readline.PcItem("rm"), + readline.PcItem("eval"), +) + func (repl *policyPlaygroundREPL) run() error { if len(viper.GetString(commonflags.RPC)) > 0 { key := key.GetOrGenerate(repl.cmd) @@ -189,15 +199,32 @@ func (repl *policyPlaygroundREPL) run() error { "rm": repl.handleRemove, "eval": repl.handleEval, } - for reader := bufio.NewReader(os.Stdin); ; { - fmt.Print("> ") - line, err := reader.ReadString('\n') + + rl, err := readline.NewEx(&readline.Config{ + Prompt: "> ", + InterruptPrompt: "^C", + AutoComplete: policyPlaygroundCompleter, + }) + if err != nil { + return fmt.Errorf("error initializing readline: %w", err) + } + defer rl.Close() + + var exit bool + for { + line, err := rl.Readline() if err != nil { - if err == io.EOF { - return nil + if errors.Is(err, readline.ErrInterrupt) { + if exit { + return nil + } + exit = true + continue } return fmt.Errorf("reading line: %v", err) } + exit = false + parts := strings.Fields(line) if len(parts) == 0 { continue From 80f8a8fd3abd0cf9a605c4002cbaced6f2fd9b8c Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 12 Nov 2024 11:09:27 +0300 Subject: [PATCH 0977/1413] [#1396] cli/playground: Refactor Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/modules/container/policy_playground.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 6885d35f27..40bd4110ba 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -221,7 +221,7 @@ func (repl *policyPlaygroundREPL) run() error { exit = true continue } - return fmt.Errorf("reading line: %v", err) + return fmt.Errorf("reading line: %w", err) } exit = false @@ -230,8 +230,7 @@ func (repl *policyPlaygroundREPL) run() error { continue } cmd := parts[0] - handler, exists := cmdHandlers[cmd] - if exists { + if handler, exists := cmdHandlers[cmd]; exists { if err := handler(parts[1:]); err != nil { fmt.Printf("error: %v\n", err) } From b543569c3f0ae2feab378ad3568bab27528d1035 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 11 Nov 2024 18:54:07 +0300 Subject: [PATCH 0978/1413] [#1486] node: Introduce dual service support * Register GRPC services for both neo.fs.v2 and frost.fs namespaces * Use this temporary solution until all nodes are updated Signed-off-by: Airat Arifullin --- cmd/frostfs-node/accounting.go | 23 +++++++++++++++++++++++ cmd/frostfs-node/apemanager.go | 3 +++ cmd/frostfs-node/container.go | 3 +++ cmd/frostfs-node/netmap.go | 3 +++ cmd/frostfs-node/object.go | 3 +++ cmd/frostfs-node/session.go | 3 +++ 6 files changed, 38 insertions(+) diff --git a/cmd/frostfs-node/accounting.go b/cmd/frostfs-node/accounting.go index 72a6e5331c..2d52e0c56f 100644 --- a/cmd/frostfs-node/accounting.go +++ b/cmd/frostfs-node/accounting.go @@ -3,6 +3,7 @@ package main import ( "context" "net" + "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" accountingTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/accounting/grpc" @@ -30,5 +31,27 @@ func initAccountingService(ctx context.Context, c *cfg) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { accountingGRPC.RegisterAccountingServiceServer(s, server) + + // TODO(@aarifullin): #1487 remove the dual service support. + s.RegisterService(frostFSServiceDesc(accountingGRPC.AccountingService_ServiceDesc), server) }) } + +// frostFSServiceDesc creates a service descriptor with the new namespace for dual service support. +func frostFSServiceDesc(sd grpc.ServiceDesc) *grpc.ServiceDesc { + sdLegacy := new(grpc.ServiceDesc) + *sdLegacy = sd + + const ( + legacyNamespace = "neo.fs.v2" + apemanagerLegacyNamespace = "frostfs.v2" + newNamespace = "frost.fs" + ) + + if strings.HasPrefix(sd.ServiceName, legacyNamespace) { + sdLegacy.ServiceName = strings.ReplaceAll(sd.ServiceName, legacyNamespace, newNamespace) + } else if strings.HasPrefix(sd.ServiceName, apemanagerLegacyNamespace) { + sdLegacy.ServiceName = strings.ReplaceAll(sd.ServiceName, apemanagerLegacyNamespace, newNamespace) + } + return sdLegacy +} diff --git a/cmd/frostfs-node/apemanager.go b/cmd/frostfs-node/apemanager.go index c4d7725f53..de3aed660b 100644 --- a/cmd/frostfs-node/apemanager.go +++ b/cmd/frostfs-node/apemanager.go @@ -26,5 +26,8 @@ func initAPEManagerService(c *cfg) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { apemanager_grpc.RegisterAPEManagerServiceServer(s, server) + + // TODO(@aarifullin): #1487 remove the dual service support. + s.RegisterService(frostFSServiceDesc(apemanager_grpc.APEManagerService_ServiceDesc), server) }) } diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 9c35059221..de840ec802 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -64,6 +64,9 @@ func initContainerService(_ context.Context, c *cfg) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { containerGRPC.RegisterContainerServiceServer(s, server) + + // TODO(@aarifullin): #1487 remove the dual service support. + s.RegisterService(frostFSServiceDesc(containerGRPC.ContainerService_ServiceDesc), server) }) c.cfgObject.cfgLocalStorage.localStorage.SetContainerSource(cnrRdr) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 58e066fc97..73871bfc9d 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -166,6 +166,9 @@ func initNetmapService(ctx context.Context, c *cfg) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { netmapGRPC.RegisterNetmapServiceServer(s, server) + + // TODO(@aarifullin): #1487 remove the dual service support. + s.RegisterService(frostFSServiceDesc(netmapGRPC.NetmapService_ServiceDesc), server) }) addNewEpochNotificationHandlers(c) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 629f79207b..ec521ab018 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -218,6 +218,9 @@ func initObjectService(c *cfg) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { objectGRPC.RegisterObjectServiceServer(s, server) + + // TODO(@aarifullin): #1487 remove the dual service support. + s.RegisterService(frostFSServiceDesc(objectGRPC.ObjectService_ServiceDesc), server) }) } diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index 20d2d318fb..a35d4e4702 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -61,5 +61,8 @@ func initSessionService(c *cfg) { c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { sessionGRPC.RegisterSessionServiceServer(s, server) + + // TODO(@aarifullin): #1487 remove the dual service support. + s.RegisterService(frostFSServiceDesc(sessionGRPC.SessionService_ServiceDesc), server) }) } From be2753de0032c2eb4c0abb5b00096c7e6697413f Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 12 Nov 2024 13:31:13 +0300 Subject: [PATCH 0979/1413] [#1490] docs: Update description for `object.get.priority` Signed-off-by: Anton Nikiforov --- docs/storage-node-configuration.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 3635204815..98d72cb692 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -412,12 +412,12 @@ object: - $attribute:ClusterName ``` -| Parameter | Type | Default value | Description | -|-----------------------------|------------|---------------|------------------------------------------------------------------------------------------------------| -| `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. | -| `put.remote_pool_size` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. | -| `put.local_pool_size` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. | -| `get.priority` | `[]string` | | List of metrics of nodes for prioritization. Used for computing response on GET and SEARCH requests. | +| Parameter | Type | Default value | Description | +|-----------------------------|------------|---------------|------------------------------------------------------------------------------------------------| +| `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. | +| `put.remote_pool_size` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. | +| `put.local_pool_size` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. | +| `get.priority` | `[]string` | | List of metrics of nodes for prioritization. Used for computing response on GET requests. | # `runtime` section Contains runtime parameters. From a69229853366e192296e2a287c49adc66c647bb3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 11 Nov 2024 09:24:09 +0300 Subject: [PATCH 0980/1413] [#1483] node: Remove eACL cache Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/cache.go | 25 ----------------------- cmd/frostfs-node/config.go | 2 -- cmd/frostfs-node/container.go | 16 --------------- cmd/frostfs-node/object.go | 26 ------------------------ pkg/core/container/storage.go | 13 ------------ pkg/services/container/morph/executor.go | 1 - 6 files changed, 83 deletions(-) diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index 06142a46ce..b906417994 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -196,31 +196,6 @@ func (s ttlContainerStorage) DeletionInfo(cnr cid.ID) (*container.DelInfo, error return s.delInfoCache.get(cnr) } -type ttlEACLStorage struct { - *ttlNetCache[cid.ID, *container.EACL] -} - -func newCachedEACLStorage(v container.EACLSource, ttl time.Duration) ttlEACLStorage { - const eaclCacheSize = 100 - - lruCnrCache := newNetworkTTLCache(eaclCacheSize, ttl, func(id cid.ID) (*container.EACL, error) { - return v.GetEACL(id) - }, metrics.NewCacheMetrics("eacl")) - - return ttlEACLStorage{lruCnrCache} -} - -// GetEACL returns eACL value from the cache. If value is missing in the cache -// or expired, then it returns value from side chain and updates cache. -func (s ttlEACLStorage) GetEACL(cnr cid.ID) (*container.EACL, error) { - return s.get(cnr) -} - -// InvalidateEACL removes cached eACL value. -func (s ttlEACLStorage) InvalidateEACL(cnr cid.ID) { - s.remove(cnr) -} - type lruNetmapSource struct { netState netmap.State diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 40af238414..902187560d 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -642,8 +642,6 @@ type cfgObject struct { cnrSource container.Source - eaclSource container.EACLSource - cfgAccessPolicyEngine cfgAccessPolicyEngine pool cfgObjectRoutines diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index de840ec802..cc38876ee1 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -73,10 +73,6 @@ func initContainerService(_ context.Context, c *cfg) { } func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc containerCore.Source) (*morphContainerReader, *morphContainerWriter) { - eACLFetcher := &morphEACLFetcher{ - w: client, - } - cnrRdr := new(morphContainerReader) cnrWrt := &morphContainerWriter{ @@ -84,8 +80,6 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c } if c.cfgMorph.cacheTTL <= 0 { - c.cfgObject.eaclSource = eACLFetcher - cnrRdr.eacl = eACLFetcher c.cfgObject.cnrSource = cnrSrc cnrRdr.src = cnrSrc cnrRdr.lister = client @@ -129,11 +123,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c c.cfgObject.cnrSource = containerCache } - cachedEACLStorage := newCachedEACLStorage(eACLFetcher, c.cfgMorph.cacheTTL) - c.cfgObject.eaclSource = cachedEACLStorage - cnrRdr.lister = client - cnrRdr.eacl = c.cfgObject.eaclSource cnrRdr.src = c.cfgObject.cnrSource } @@ -224,8 +214,6 @@ func (c *cfg) ExternalAddresses() []string { // implements interface required by container service provided by morph executor. type morphContainerReader struct { - eacl containerCore.EACLSource - src containerCore.Source lister interface { @@ -241,10 +229,6 @@ func (x *morphContainerReader) DeletionInfo(id cid.ID) (*containerCore.DelInfo, return x.src.DeletionInfo(id) } -func (x *morphContainerReader) GetEACL(id cid.ID) (*containerCore.EACL, error) { - return x.eacl.GetEACL(id) -} - func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) { return x.lister.ContainersOf(id) } diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index ec521ab018..aeab1d6cb1 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -2,7 +2,6 @@ package main import ( "context" - "errors" "fmt" "net" @@ -14,7 +13,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache" objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc" @@ -37,7 +35,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -484,29 +481,6 @@ func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *object ) } -type morphEACLFetcher struct { - w *cntClient.Client -} - -func (s *morphEACLFetcher) GetEACL(cnr cid.ID) (*containercore.EACL, error) { - eaclInfo, err := s.w.GetEACL(cnr) - if err != nil { - return nil, err - } - - binTable, err := eaclInfo.Value.Marshal() - if err != nil { - return nil, fmt.Errorf("marshal eACL table: %w", err) - } - - if !eaclInfo.Signature.Verify(binTable) { - // TODO(@cthulhu-rider): #468 use "const" error - return nil, errors.New("invalid signature of the eACL table") - } - - return eaclInfo, nil -} - type engineWithoutNotifications struct { engine *engine.StorageEngine } diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index 69854f4951..ba44045462 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -58,16 +58,3 @@ type EACL struct { // Session within which Value was set. Nil means session absence. Session *session.Container } - -// EACLSource is the interface that wraps -// basic methods of extended ACL table source. -type EACLSource interface { - // GetEACL reads the table from the source by identifier. - // It returns any error encountered. - // - // GetEACL must return exactly one non-nil value. - // - // Must return apistatus.ErrEACLNotFound if requested - // eACL table is not in source. - GetEACL(cid.ID) (*EACL, error) -} diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index adb808af38..eb43eab70a 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -25,7 +25,6 @@ type morphExecutor struct { // Reader is an interface of read-only container storage. type Reader interface { containercore.Source - containercore.EACLSource // ContainersOf returns a list of container identifiers belonging // to the specified user of FrostFS system. Returns the identifiers From 3324c26fd8f8b68ca7feea07263bfc91b8587817 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 11 Nov 2024 09:26:00 +0300 Subject: [PATCH 0981/1413] [#1483] morph: Remove container.GetEACL() Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/container/client.go | 1 - pkg/morph/client/container/eacl.go | 95 ---------------------------- 2 files changed, 96 deletions(-) delete mode 100644 pkg/morph/client/container/eacl.go diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index b512a6594b..bdbcce9178 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -27,7 +27,6 @@ const ( getMethod = "get" listMethod = "list" containersOfMethod = "containersOf" - eaclMethod = "eACL" deletionInfoMethod = "deletionInfo" // putNamedMethod is method name for container put with an alias. It is exported to provide custom fee. diff --git a/pkg/morph/client/container/eacl.go b/pkg/morph/client/container/eacl.go deleted file mode 100644 index 9e604e0912..0000000000 --- a/pkg/morph/client/container/eacl.go +++ /dev/null @@ -1,95 +0,0 @@ -package container - -import ( - "crypto/sha256" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" -) - -// GetEACL reads the extended ACL table from FrostFS system -// through Container contract call. -// -// Returns apistatus.EACLNotFound if eACL table is missing in the contract. -func (c *Client) GetEACL(cnr cid.ID) (*container.EACL, error) { - binCnr := make([]byte, sha256.Size) - cnr.Encode(binCnr) - - prm := client.TestInvokePrm{} - prm.SetMethod(eaclMethod) - prm.SetArgs(binCnr) - - prms, err := c.client.TestInvoke(prm) - if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", eaclMethod, err) - } else if ln := len(prms); ln != 1 { - return nil, fmt.Errorf("unexpected stack item count (%s): %d", eaclMethod, ln) - } - - arr, err := client.ArrayFromStackItem(prms[0]) - if err != nil { - return nil, fmt.Errorf("could not get item array of eACL (%s): %w", eaclMethod, err) - } - - if len(arr) != 4 { - return nil, fmt.Errorf("unexpected eacl stack item count (%s): %d", eaclMethod, len(arr)) - } - - rawEACL, err := client.BytesFromStackItem(arr[0]) - if err != nil { - return nil, fmt.Errorf("could not get byte array of eACL (%s): %w", eaclMethod, err) - } - - sig, err := client.BytesFromStackItem(arr[1]) - if err != nil { - return nil, fmt.Errorf("could not get byte array of eACL signature (%s): %w", eaclMethod, err) - } - - // Client may not return errors if the table is missing, so check this case additionally. - // The absence of a signature in the response can be taken as an eACL absence criterion, - // since unsigned table cannot be approved in the storage by design. - if len(sig) == 0 { - return nil, new(apistatus.EACLNotFound) - } - - pub, err := client.BytesFromStackItem(arr[2]) - if err != nil { - return nil, fmt.Errorf("could not get byte array of eACL public key (%s): %w", eaclMethod, err) - } - - binToken, err := client.BytesFromStackItem(arr[3]) - if err != nil { - return nil, fmt.Errorf("could not get byte array of eACL session token (%s): %w", eaclMethod, err) - } - - var res container.EACL - - res.Value = eacl.NewTable() - if err = res.Value.Unmarshal(rawEACL); err != nil { - return nil, err - } - - if len(binToken) > 0 { - res.Session = new(session.Container) - - err = res.Session.Unmarshal(binToken) - if err != nil { - return nil, fmt.Errorf("could not unmarshal session token: %w", err) - } - } - - // TODO(@cthulhu-rider): #468 implement and use another approach to avoid conversion - var sigV2 refs.Signature - sigV2.SetKey(pub) - sigV2.SetSign(sig) - sigV2.SetScheme(refs.ECDSA_RFC6979_SHA256) - - err = res.Signature.ReadFromV2(sigV2) - return &res, err -} From 1cf51a80799b93cc679be7ea1d1f4022ae019ade Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 11 Nov 2024 09:37:30 +0300 Subject: [PATCH 0982/1413] [#1483] cli/docs: Remove set-eacl mention Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/docs/sessions.md | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/frostfs-cli/docs/sessions.md b/cmd/frostfs-cli/docs/sessions.md index 04563b7af0..52c0e9b9b3 100644 --- a/cmd/frostfs-cli/docs/sessions.md +++ b/cmd/frostfs-cli/docs/sessions.md @@ -72,4 +72,3 @@ All other `object` sub-commands support only static sessions (2). List of commands supporting sessions (static only): - `create` - `delete` -- `set-eacl` From 16830033f82cfa2936a721b22ab65469896ea240 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 11 Nov 2024 09:41:55 +0300 Subject: [PATCH 0983/1413] [#1483] cli: Remove --basic-acl flag Signed-off-by: Evgenii Stratonikov --- README.md | 2 +- cmd/frostfs-cli/modules/container/create.go | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/README.md b/README.md index 6998b6726b..0109ed0e5b 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ See `frostfs-contract`'s README.md for build instructions. 4. To create container and put object into it run (container and object IDs will be different): ``` -./bin/frostfs-cli container create -r 127.0.0.1:8080 --wallet ./dev/wallet.json --policy "REP 1 IN X CBF 1 SELECT 1 FROM * AS X" --basic-acl public-read-write --await +./bin/frostfs-cli container create -r 127.0.0.1:8080 --wallet ./dev/wallet.json --policy "REP 1 IN X CBF 1 SELECT 1 FROM * AS X" --await Enter password > <- press ENTER, the is no password for wallet CID: CfPhEuHQ2PRvM4gfBQDC4dWZY3NccovyfcnEdiq2ixju diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index 017f4b5ce3..30f9951807 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -15,14 +15,12 @@ import ( containerApi "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/spf13/cobra" ) var ( - containerACL string containerPolicy string containerAttributes []string containerAwait bool @@ -89,9 +87,6 @@ It will be stored in sidechain when inner ring will accepts it.`, err = parseAttributes(&cnr, containerAttributes) commonCmd.ExitOnErr(cmd, "", err) - var basicACL acl.Basic - commonCmd.ExitOnErr(cmd, "decode basic ACL string: %w", basicACL.DecodeString(containerACL)) - tok := getSession(cmd) if tok != nil { @@ -105,7 +100,6 @@ It will be stored in sidechain when inner ring will accepts it.`, } cnr.SetPlacementPolicy(*placementPolicy) - cnr.SetBasicACL(basicACL) var syncContainerPrm internalclient.SyncContainerPrm syncContainerPrm.SetClient(cli) @@ -163,10 +157,6 @@ func initContainerCreateCmd() { flags.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage) flags.StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, commonflags.WalletPathDefault, commonflags.WalletPathUsage) flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage) - - flags.StringVar(&containerACL, "basic-acl", acl.NamePrivate, fmt.Sprintf("HEX encoded basic ACL value or keywords like '%s', '%s', '%s'", - acl.NamePublicRW, acl.NamePrivate, acl.NamePublicROExtended, - )) flags.StringVarP(&containerPolicy, "policy", "p", "", "QL-encoded or JSON-encoded placement policy or path to file with it") flags.StringSliceVarP(&containerAttributes, "attributes", "a", nil, "Comma separated pairs of container attributes in form of Key1=Value1,Key2=Value2") flags.BoolVar(&containerAwait, "await", false, "Block execution until container is persisted") From 9bd05e94c8e1dee1a63d343938abf77cc40eb51d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 30 Oct 2024 11:02:52 +0300 Subject: [PATCH 0984/1413] [#1449] tree: Add ApplyBatch method Concurrent Apply can lead to child node applies before parent, so undo/redo operations will perform. This leads to performance degradation in case of tree with many sublevels. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config/tree/config.go | 13 ++++ cmd/frostfs-node/config/tree/config_test.go | 1 + cmd/frostfs-node/tree.go | 1 + config/example/node.env | 1 + config/example/node.json | 1 + config/example/node.yaml | 1 + pkg/local_object_storage/engine/tree.go | 28 +++++++ pkg/local_object_storage/pilorama/boltdb.go | 74 +++++++++++++++++++ pkg/local_object_storage/pilorama/forest.go | 9 +++ .../pilorama/interface.go | 2 + pkg/local_object_storage/shard/tree.go | 27 +++++++ pkg/services/tree/options.go | 7 ++ pkg/services/tree/replicator.go | 1 + pkg/services/tree/service.go | 1 + pkg/services/tree/sync.go | 34 ++++----- 15 files changed, 180 insertions(+), 21 deletions(-) diff --git a/cmd/frostfs-node/config/tree/config.go b/cmd/frostfs-node/config/tree/config.go index 8a8919999f..da877791e4 100644 --- a/cmd/frostfs-node/config/tree/config.go +++ b/cmd/frostfs-node/config/tree/config.go @@ -10,6 +10,8 @@ import ( const ( subsection = "tree" + + SyncBatchSizeDefault = 1000 ) // TreeConfig is a wrapper over "tree" config section @@ -74,6 +76,17 @@ func (c TreeConfig) SyncInterval() time.Duration { return config.DurationSafe(c.cfg, "sync_interval") } +// SyncBatchSize returns the value of "sync_batch_size" +// config parameter from the "tree" section. +// +// Returns `SyncBatchSizeDefault` if config value is not specified. +func (c TreeConfig) SyncBatchSize() int { + if v := config.IntSafe(c.cfg, "sync_batch_size"); v > 0 { + return int(v) + } + return SyncBatchSizeDefault +} + // AuthorizedKeys parses and returns an array of "authorized_keys" config // parameter from "tree" section. // diff --git a/cmd/frostfs-node/config/tree/config_test.go b/cmd/frostfs-node/config/tree/config_test.go index 285ea07253..6628b88785 100644 --- a/cmd/frostfs-node/config/tree/config_test.go +++ b/cmd/frostfs-node/config/tree/config_test.go @@ -44,6 +44,7 @@ func TestTreeSection(t *testing.T) { require.Equal(t, 32, treeSec.ReplicationWorkerCount()) require.Equal(t, 5*time.Second, treeSec.ReplicationTimeout()) require.Equal(t, time.Hour, treeSec.SyncInterval()) + require.Equal(t, 2000, treeSec.SyncBatchSize()) require.Equal(t, expectedKeys, treeSec.AuthorizedKeys()) } diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index f188e2fbcf..a92979daf3 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -62,6 +62,7 @@ func initTreeService(c *cfg) { tree.WithReplicationTimeout(treeConfig.ReplicationTimeout()), tree.WithReplicationChannelCapacity(treeConfig.ReplicationChannelCapacity()), tree.WithReplicationWorkerCount(treeConfig.ReplicationWorkerCount()), + tree.WithSyncBatchSize(treeConfig.SyncBatchSize()), tree.WithAuthorizedKeys(treeConfig.AuthorizedKeys()), tree.WithMetrics(c.metricsCollector.TreeService()), tree.WithAPELocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage()), diff --git a/config/example/node.env b/config/example/node.env index 3979eb18fc..e21328b60c 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -31,6 +31,7 @@ FROSTFS_TREE_REPLICATION_CHANNEL_CAPACITY=32 FROSTFS_TREE_REPLICATION_WORKER_COUNT=32 FROSTFS_TREE_REPLICATION_TIMEOUT=5s FROSTFS_TREE_SYNC_INTERVAL=1h +FROSTFS_TREE_SYNC_BATCH_SIZE=2000 FROSTFS_TREE_AUTHORIZED_KEYS="0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0 02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56" # gRPC section diff --git a/config/example/node.json b/config/example/node.json index 1ea28de6cd..ac7125949b 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -69,6 +69,7 @@ "replication_worker_count": 32, "replication_timeout": "5s", "sync_interval": "1h", + "sync_batch_size": 2000, "authorized_keys": [ "0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0", "02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56" diff --git a/config/example/node.yaml b/config/example/node.yaml index 4a418dfcbc..d547f5cee3 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -59,6 +59,7 @@ tree: replication_channel_capacity: 32 replication_timeout: 5s sync_interval: 1h + sync_batch_size: 2000 authorized_keys: # list of hex-encoded public keys that have rights to use the Tree Service with frostfs-cli - 0397d207ea77909f7d66fa6f36d08daae22ace672be7ea4f53513484dde8a142a0 - 02053819235c20d784132deba10bb3061629e3a5c819a039ef091841d9d35dad56 diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index 39122628f2..6bb5e3a41a 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -110,6 +110,34 @@ func (e *StorageEngine) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID str return nil } +// TreeApplyBatch implements the pilorama.Forest interface. +func (e *StorageEngine) TreeApplyBatch(ctx context.Context, cnr cidSDK.ID, treeID string, m []*pilorama.Move) error { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.TreeApplyBatch", + trace.WithAttributes( + attribute.String("container_id", cnr.EncodeToString()), + attribute.String("tree_id", treeID), + ), + ) + defer span.End() + + index, lst, err := e.getTreeShard(ctx, cnr, treeID) + if err != nil && !errors.Is(err, pilorama.ErrTreeNotFound) { + return err + } + + err = lst[index].TreeApplyBatch(ctx, cnr, treeID, m) + if err != nil { + if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { + e.reportShardError(lst[index], "can't perform `TreeApplyBatch`", err, + zap.Stringer("cid", cnr), + zap.String("tree", treeID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + } + return err + } + return nil +} + // TreeGetByPath implements the pilorama.Forest interface. func (e *StorageEngine) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID string, attr string, path []string, latest bool) ([]pilorama.Node, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.TreeGetByPath", diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 7bce1f3405..a778434dd2 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -558,6 +558,80 @@ func (t *boltForest) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID string return metaerr.Wrap(err) } +func (t *boltForest) TreeApplyBatch(ctx context.Context, cnr cidSDK.ID, treeID string, m []*Move) error { + var ( + startedAt = time.Now() + success = false + ) + defer func() { + t.metrics.AddMethodDuration("TreeApplyBatch", time.Since(startedAt), success) + }() + + _, span := tracing.StartSpanFromContext(ctx, "boltForest.TreeApplyBatch", + trace.WithAttributes( + attribute.String("container_id", cnr.EncodeToString()), + attribute.String("tree_id", treeID), + ), + ) + defer span.End() + + m, err := t.filterSeen(cnr, treeID, m) + if err != nil { + return err + } + if len(m) == 0 { + success = true + return nil + } + + ch := make(chan error) + b := &batch{ + forest: t, + cid: cnr, + treeID: treeID, + results: []chan<- error{ch}, + operations: m, + } + go func() { + b.run() + }() + err = <-ch + success = err == nil + return metaerr.Wrap(err) +} + +func (t *boltForest) filterSeen(cnr cidSDK.ID, treeID string, m []*Move) ([]*Move, error) { + t.modeMtx.RLock() + defer t.modeMtx.RUnlock() + + if t.mode.NoMetabase() { + return nil, ErrDegradedMode + } + + ops := make([]*Move, 0, len(m)) + err := t.db.View(func(tx *bbolt.Tx) error { + treeRoot := tx.Bucket(bucketName(cnr, treeID)) + if treeRoot == nil { + ops = m + return nil + } + b := treeRoot.Bucket(logBucket) + for _, op := range m { + var logKey [8]byte + binary.BigEndian.PutUint64(logKey[:], op.Time) + seen := b.Get(logKey[:]) != nil + if !seen { + ops = append(ops, op) + } + } + return nil + }) + if err != nil { + return nil, metaerr.Wrap(err) + } + return ops, nil +} + // TreeApplyStream should be used with caution: this method locks other write transactions while `source` is not closed. func (t *boltForest) TreeApplyStream(ctx context.Context, cnr cidSDK.ID, treeID string, source <-chan *Move) error { var ( diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index bb5c22e511..3749437457 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -111,6 +111,15 @@ func (f *memoryForest) TreeApply(_ context.Context, cnr cid.ID, treeID string, o return s.Apply(op) } +func (f *memoryForest) TreeApplyBatch(ctx context.Context, cnr cid.ID, treeID string, ops []*Move) error { + for _, op := range ops { + if err := f.TreeApply(ctx, cnr, treeID, op, true); err != nil { + return err + } + } + return nil +} + func (f *memoryForest) Init() error { return nil } diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index 61a3849bf6..b6ca246f2e 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -21,6 +21,8 @@ type Forest interface { // TreeApply applies replicated operation from another node. // If background is true, TreeApply will first check whether an operation exists. TreeApply(ctx context.Context, cnr cidSDK.ID, treeID string, m *Move, backgroundSync bool) error + // TreeApplyBatch applies replicated operations from another node. + TreeApplyBatch(ctx context.Context, cnr cidSDK.ID, treeID string, m []*Move) error // TreeGetByPath returns all nodes corresponding to the path. // The path is constructed by descending from the root using the values of the // AttributeFilename in meta. diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index 26dc8ec1eb..01a014cecc 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -106,6 +106,33 @@ func (s *Shard) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID string, m * return s.pilorama.TreeApply(ctx, cnr, treeID, m, backgroundSync) } +// TreeApplyBatch implements the pilorama.Forest interface. +func (s *Shard) TreeApplyBatch(ctx context.Context, cnr cidSDK.ID, treeID string, m []*pilorama.Move) error { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeApplyBatch", + trace.WithAttributes( + attribute.String("shard_id", s.ID().String()), + attribute.String("container_id", cnr.EncodeToString()), + attribute.String("tree_id", treeID), + ), + ) + defer span.End() + + if s.pilorama == nil { + return ErrPiloramaDisabled + } + + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.ReadOnly() { + return ErrReadOnlyMode + } + if s.info.Mode.NoMetabase() { + return ErrDegradedMode + } + return s.pilorama.TreeApplyBatch(ctx, cnr, treeID, m) +} + // TreeGetByPath implements the pilorama.Forest interface. func (s *Shard) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID string, attr string, path []string, latest bool) ([]pilorama.Node, error) { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeGetByPath", diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index 1633ae5579..a3f4880098 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -41,6 +41,7 @@ type cfg struct { replicatorTimeout time.Duration containerCacheSize int authorizedKeys [][]byte + syncBatchSize int localOverrideStorage policyengine.LocalOverrideStorage morphChainStorage policyengine.MorphRuleChainStorageReader @@ -113,6 +114,12 @@ func WithReplicationWorkerCount(n int) Option { } } +func WithSyncBatchSize(n int) Option { + return func(c *cfg) { + c.syncBatchSize = n + } +} + func WithContainerCacheSize(n int) Option { return func(c *cfg) { if n > 0 { diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 95c8f80134..84e376cf74 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -40,6 +40,7 @@ const ( defaultReplicatorCapacity = 64 defaultReplicatorWorkerCount = 64 defaultReplicatorSendTimeout = time.Second * 5 + defaultSyncBatchSize = 1000 ) func (s *Service) localReplicationWorker(ctx context.Context) { diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 8097d545c6..b63338d259 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -55,6 +55,7 @@ func New(opts ...Option) *Service { s.replicatorChannelCapacity = defaultReplicatorCapacity s.replicatorWorkerCount = defaultReplicatorWorkerCount s.replicatorTimeout = defaultReplicatorSendTimeout + s.syncBatchSize = defaultSyncBatchSize s.metrics = defaultMetricsRegister{} for i := range opts { diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index ce1e72104b..b93410616a 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -177,37 +177,29 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID string, operationStream <-chan *pilorama.Move, ) uint64 { - errGroup, _ := errgroup.WithContext(ctx) - const workersCount = 1024 - errGroup.SetLimit(workersCount) - - // We run TreeApply concurrently for the operation batch. Let's consider two operations - // in the batch m1 and m2 such that m1.Time < m2.Time. The engine may apply m2 and fail - // on m1. That means the service must start sync from m1.Time in the next iteration and - // this height is stored in unappliedOperationHeight. - var unappliedOperationHeight uint64 = math.MaxUint64 - var heightMtx sync.Mutex - var prev *pilorama.Move + var batch []*pilorama.Move for m := range operationStream { // skip already applied op if prev != nil && prev.Time == m.Time { continue } prev = m + batch = append(batch, m) - errGroup.Go(func() error { - if err := s.forest.TreeApply(ctx, cid, treeID, m, true); err != nil { - heightMtx.Lock() - unappliedOperationHeight = min(unappliedOperationHeight, m.Time) - heightMtx.Unlock() - return err + if len(batch) == s.syncBatchSize { + if err := s.forest.TreeApplyBatch(ctx, cid, treeID, batch); err != nil { + return batch[0].Time } - return nil - }) + batch = batch[:0] + } } - _ = errGroup.Wait() - return unappliedOperationHeight + if len(batch) > 0 { + if err := s.forest.TreeApplyBatch(ctx, cid, treeID, batch); err != nil { + return batch[0].Time + } + } + return math.MaxUint64 } func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, From 46fef276b474ba5c5ee66d0dee2a7595d47bc4f0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 11 Nov 2024 12:12:45 +0300 Subject: [PATCH 0985/1413] [#1449] tree: Log tree sync with Info level Signed-off-by: Dmitrii Stepanov --- pkg/services/tree/sync.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index b93410616a..2c6deeb787 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -376,7 +376,7 @@ func (s *Service) syncLoop(ctx context.Context) { return case <-s.syncChan: ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.sync") - s.log.Debug(logs.TreeSyncingTrees) + s.log.Info(logs.TreeSyncingTrees) start := time.Now() @@ -394,7 +394,7 @@ func (s *Service) syncLoop(ctx context.Context) { s.removeContainers(ctx, newMap) - s.log.Debug(logs.TreeTreesHaveBeenSynchronized) + s.log.Info(logs.TreeTreesHaveBeenSynchronized) s.metrics.AddSyncDuration(time.Since(start), true) span.End() From c00f4bab18854b88f8c87d5b3dfff859d7505a26 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 12 Nov 2024 11:32:33 +0300 Subject: [PATCH 0986/1413] [#1488] go.mod: Bump observability version Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8a70c38199..84f9f9a668 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d - git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 + git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 diff --git a/go.sum b/go.sum index 9778f91e21..d93e9b74e0 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573 h1:6qCcm1oqFbmf9C5AauXzrL5OPGnTbI9HoB/jAtD9274= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20240909114314-666d326cc573/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823 h1:sepm9FeuoInmygH1K/+3L+Yp5bJhGiVi/oGCH6Emp2c= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823/go.mod h1:eoK7+KZQ9GJxbzIs6vTnoUJqFDppavInLRHaN4MYgZg= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= From e2658c75194fb8b04b0ec763dda92bfa94967e55 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 12 Nov 2024 11:33:23 +0300 Subject: [PATCH 0987/1413] [#1488] tracing: KV attributes for spans from config Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config/tracing/config.go | 23 +++++++++- .../config/tracing/config_test.go | 46 +++++++++++++++++++ config/example/node.env | 4 ++ config/example/node.json | 14 +++++- config/example/node.yaml | 5 ++ 5 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 cmd/frostfs-node/config/tracing/config_test.go diff --git a/cmd/frostfs-node/config/tracing/config.go b/cmd/frostfs-node/config/tracing/config.go index 8544c672c7..91ef669ee8 100644 --- a/cmd/frostfs-node/config/tracing/config.go +++ b/cmd/frostfs-node/config/tracing/config.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" @@ -24,6 +25,7 @@ func ToTracingConfig(c *config.Config) (*tracing.Config, error) { Service: "frostfs-node", InstanceID: getInstanceIDOrDefault(c), Version: misc.Version, + Attributes: make(map[string]string), } if trustedCa := config.StringSafe(c.Sub(subsection), "trusted_ca"); trustedCa != "" { @@ -38,11 +40,30 @@ func ToTracingConfig(c *config.Config) (*tracing.Config, error) { } conf.ServerCaCertPool = certPool } + + i := uint64(0) + for ; ; i++ { + si := strconv.FormatUint(i, 10) + ac := c.Sub(subsection).Sub("attributes").Sub(si) + k := config.StringSafe(ac, "key") + if k == "" { + break + } + v := config.StringSafe(ac, "value") + if v == "" { + return nil, fmt.Errorf("empty tracing attribute value for key %s", k) + } + if _, ok := conf.Attributes[k]; ok { + return nil, fmt.Errorf("tracing attribute key %s defined more than once", k) + } + conf.Attributes[k] = v + } + return conf, nil } func getInstanceIDOrDefault(c *config.Config) string { - s := config.StringSlice(c.Sub("node"), "addresses") + s := config.StringSliceSafe(c.Sub("node"), "addresses") if len(s) > 0 { return s[0] } diff --git a/cmd/frostfs-node/config/tracing/config_test.go b/cmd/frostfs-node/config/tracing/config_test.go new file mode 100644 index 0000000000..8e485ca6e8 --- /dev/null +++ b/cmd/frostfs-node/config/tracing/config_test.go @@ -0,0 +1,46 @@ +package tracing + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "github.com/stretchr/testify/require" +) + +func TestTracingSection(t *testing.T) { + t.Run("defaults", func(t *testing.T) { + tc, err := ToTracingConfig(configtest.EmptyConfig()) + require.NoError(t, err) + require.Equal(t, false, tc.Enabled) + require.Equal(t, tracing.Exporter(""), tc.Exporter) + require.Equal(t, "", tc.Endpoint) + require.Equal(t, "frostfs-node", tc.Service) + require.Equal(t, "", tc.InstanceID) + require.Nil(t, tc.ServerCaCertPool) + require.Empty(t, tc.Attributes) + }) + + const path = "../../../../config/example/node" + + fileConfigTest := func(c *config.Config) { + tc, err := ToTracingConfig(c) + require.NoError(t, err) + require.Equal(t, true, tc.Enabled) + require.Equal(t, tracing.OTLPgRPCExporter, tc.Exporter) + require.Equal(t, "localhost", tc.Endpoint) + require.Equal(t, "frostfs-node", tc.Service) + require.Nil(t, tc.ServerCaCertPool) + require.EqualValues(t, map[string]string{ + "key0": "value", + "key1": "value", + }, tc.Attributes) + } + + configtest.ForEachFileType(path, fileConfigTest) + + t.Run("ENV", func(t *testing.T) { + configtest.ForEnvFileType(t, path, fileConfigTest) + }) +} diff --git a/config/example/node.env b/config/example/node.env index e21328b60c..f470acf3e0 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -203,6 +203,10 @@ FROSTFS_TRACING_ENABLED=true FROSTFS_TRACING_ENDPOINT="localhost" FROSTFS_TRACING_EXPORTER="otlp_grpc" FROSTFS_TRACING_TRUSTED_CA="" +FROSTFS_TRACING_ATTRIBUTES_0_KEY=key0 +FROSTFS_TRACING_ATTRIBUTES_0_VALUE=value +FROSTFS_TRACING_ATTRIBUTES_1_KEY=key1 +FROSTFS_TRACING_ATTRIBUTES_1_VALUE=value FROSTFS_RUNTIME_SOFT_MEMORY_LIMIT=1073741824 diff --git a/config/example/node.json b/config/example/node.json index ac7125949b..dba3bad8b0 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -259,9 +259,19 @@ }, "tracing": { "enabled": true, - "endpoint": "localhost:9090", + "endpoint": "localhost", "exporter": "otlp_grpc", - "trusted_ca": "/etc/ssl/tracing.pem" + "trusted_ca": "", + "attributes":[ + { + "key": "key0", + "value": "value" + }, + { + "key": "key1", + "value": "value" + } + ] }, "runtime": { "soft_memory_limit": 1073741824 diff --git a/config/example/node.yaml b/config/example/node.yaml index d547f5cee3..8f9300b4a5 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -239,6 +239,11 @@ tracing: exporter: "otlp_grpc" endpoint: "localhost" trusted_ca: "" + attributes: + - key: key0 + value: value + - key: key1 + value: value runtime: soft_memory_limit: 1gb From e122ff6013f63898471ecb95c06073d925f50698 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 12 Nov 2024 11:34:58 +0300 Subject: [PATCH 0988/1413] [#1488] dev: Add Jaeger image and enable tracing on debug Signed-off-by: Dmitrii Stepanov --- dev/.vscode-example/launch.json | 28 ++++++++++++++++++++++++---- dev/docker-compose.yml | 12 ++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/dev/.vscode-example/launch.json b/dev/.vscode-example/launch.json index 990fd42a82..6abf5ecdcf 100644 --- a/dev/.vscode-example/launch.json +++ b/dev/.vscode-example/launch.json @@ -78,7 +78,12 @@ "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s1/pilorama1", "FROSTFS_PROMETHEUS_ENABLED":"true", "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9090", - "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" + "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s", + "FROSTFS_TRACING_ENABLED":"true", + "FROSTFS_TRACING_EXPORTER":"otlp_grpc", + "FROSTFS_TRACING_ENDPOINT":"127.0.0.1:4317", + "FROSTFS_TRACING_ATTRIBUTES_0_KEY":"host.ip", + "FROSTFS_TRACING_ATTRIBUTES_0_VALUE":"127.0.0.1:8080" }, "postDebugTask": "env-down" }, @@ -129,7 +134,12 @@ "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s2/pilorama1", "FROSTFS_PROMETHEUS_ENABLED":"true", "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9091", - "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" + "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s", + "FROSTFS_TRACING_ENABLED":"true", + "FROSTFS_TRACING_EXPORTER":"otlp_grpc", + "FROSTFS_TRACING_ENDPOINT":"127.0.0.1:4317", + "FROSTFS_TRACING_ATTRIBUTES_0_KEY":"host.ip", + "FROSTFS_TRACING_ATTRIBUTES_0_VALUE":"127.0.0.1:8082" }, "postDebugTask": "env-down" }, @@ -180,7 +190,12 @@ "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s3/pilorama1", "FROSTFS_PROMETHEUS_ENABLED":"true", "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9092", - "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" + "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s", + "FROSTFS_TRACING_ENABLED":"true", + "FROSTFS_TRACING_EXPORTER":"otlp_grpc", + "FROSTFS_TRACING_ENDPOINT":"127.0.0.1:4317", + "FROSTFS_TRACING_ATTRIBUTES_0_KEY":"host.ip", + "FROSTFS_TRACING_ATTRIBUTES_0_VALUE":"127.0.0.1:8084" }, "postDebugTask": "env-down" }, @@ -231,7 +246,12 @@ "FROSTFS_STORAGE_SHARD_1_PILORAMA_PATH":"${workspaceFolder}/.cache/storage/s4/pilorama1", "FROSTFS_PROMETHEUS_ENABLED":"true", "FROSTFS_PROMETHEUS_ADDRESS":"127.0.0.1:9093", - "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s" + "FROSTFS_PROMETHEUS_SHUTDOWN_TIMEOUT":"15s", + "FROSTFS_TRACING_ENABLED":"true", + "FROSTFS_TRACING_EXPORTER":"otlp_grpc", + "FROSTFS_TRACING_ENDPOINT":"127.0.0.1:4317", + "FROSTFS_TRACING_ATTRIBUTES_0_KEY":"host.ip", + "FROSTFS_TRACING_ATTRIBUTES_0_VALUE":"127.0.0.1:8086" }, "postDebugTask": "env-down" } diff --git a/dev/docker-compose.yml b/dev/docker-compose.yml index be1956e651..40ed35aeb5 100644 --- a/dev/docker-compose.yml +++ b/dev/docker-compose.yml @@ -14,3 +14,15 @@ services: - ./neo-go/node-wallet.json:/wallets/node-wallet.json - ./neo-go/config.yml:/wallets/config.yml - ./neo-go/wallet.json:/wallets/wallet.json + jaeger: + image: jaegertracing/all-in-one:latest + container_name: jaeger + ports: + - '4317:4317' #OTLP over gRPC + - '4318:4318' #OTLP over HTTP + - '16686:16686' #frontend + stop_signal: SIGKILL + environment: + - COLLECTOR_OTLP_ENABLED=true + - SPAN_STORAGE_TYPE=badger + - BADGER_EPHEMERAL=true From f1556e3c42764499c2a7f4f9c75f8b13a7d643d7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 12 Nov 2024 11:35:20 +0300 Subject: [PATCH 0989/1413] [#1488] Makefile: Drop all containers created on env-up Signed-off-by: Dmitrii Stepanov --- Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 68a31febe7..c54601c73c 100755 --- a/Makefile +++ b/Makefile @@ -282,7 +282,6 @@ env-up: all # Shutdown dev environment env-down: - docker compose -f dev/docker-compose.yml down - docker volume rm -f frostfs-node_neo-go + docker compose -f dev/docker-compose.yml down -v rm -rf ./$(TMP_DIR)/state rm -rf ./$(TMP_DIR)/storage From b451de94c81a7a40f2afa712dd56f9c84f5be1c1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 13 Nov 2024 10:02:38 +0300 Subject: [PATCH 0990/1413] [#1492] metabase: Fix typo in objData Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/get.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index 776f5d27c3..6a35d47f36 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -216,10 +216,10 @@ func getECInfoError(tx *bbolt.Tx, cnr cid.ID, data []byte) error { ecInfo := objectSDK.NewECInfo() for _, key := range keys { // check in primary index - ojbData := getFromBucket(tx, primaryBucketName(cnr, make([]byte, bucketKeySize)), key) - if len(ojbData) != 0 { + objData := getFromBucket(tx, primaryBucketName(cnr, make([]byte, bucketKeySize)), key) + if len(objData) != 0 { obj := objectSDK.New() - if err := obj.Unmarshal(ojbData); err != nil { + if err := obj.Unmarshal(objData); err != nil { return err } chunk := objectSDK.ECChunk{} From 8ed7a676d50e24489e2abeb5269d6eb3332df1f8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 13 Nov 2024 10:07:32 +0300 Subject: [PATCH 0991/1413] [#1492] metabase: Ensure Unmarshal() is called on a cloned slice The slice returned from bucket.Get() is only valid during the tx lifetime. Cloning it is not necessary everywhere, but better safe than sorry. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/exists.go | 3 ++- pkg/local_object_storage/metabase/get.go | 4 ++-- pkg/local_object_storage/metabase/iterators.go | 3 ++- pkg/local_object_storage/metabase/list.go | 4 ++-- pkg/local_object_storage/metabase/put.go | 3 ++- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index 2e1b1dce87..0294dd3bab 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -1,6 +1,7 @@ package meta import ( + "bytes" "context" "fmt" "time" @@ -215,7 +216,7 @@ func getSplitInfo(tx *bbolt.Tx, cnr cid.ID, key []byte) (*objectSDK.SplitInfo, e splitInfo := objectSDK.NewSplitInfo() - err := splitInfo.Unmarshal(rawSplitInfo) + err := splitInfo.Unmarshal(bytes.Clone(rawSplitInfo)) if err != nil { return nil, fmt.Errorf("can't unmarshal split info from root index: %w", err) } diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index 6a35d47f36..1cbf78ab2e 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -185,7 +185,7 @@ func getVirtualObject(tx *bbolt.Tx, cnr cid.ID, key []byte, raw bool) (*objectSD child := objectSDK.New() - err = child.Unmarshal(data) + err = child.Unmarshal(bytes.Clone(data)) if err != nil { return nil, fmt.Errorf("can't unmarshal child with parent: %w", err) } @@ -219,7 +219,7 @@ func getECInfoError(tx *bbolt.Tx, cnr cid.ID, data []byte) error { objData := getFromBucket(tx, primaryBucketName(cnr, make([]byte, bucketKeySize)), key) if len(objData) != 0 { obj := objectSDK.New() - if err := obj.Unmarshal(objData); err != nil { + if err := obj.Unmarshal(bytes.Clone(objData)); err != nil { return err } chunk := objectSDK.ECChunk{} diff --git a/pkg/local_object_storage/metabase/iterators.go b/pkg/local_object_storage/metabase/iterators.go index d44c51fb29..1809bfd2d5 100644 --- a/pkg/local_object_storage/metabase/iterators.go +++ b/pkg/local_object_storage/metabase/iterators.go @@ -1,6 +1,7 @@ package meta import ( + "bytes" "context" "errors" "fmt" @@ -195,7 +196,7 @@ func iteratePhyObjects(tx *bbolt.Tx, f func(cid.ID, oid.ID, *objectSDK.Object) e } return b.ForEach(func(k, v []byte) error { - if oid.Decode(k) == nil && obj.Unmarshal(v) == nil { + if oid.Decode(k) == nil && obj.Unmarshal(bytes.Clone(v)) == nil { return f(cid, oid, obj) } diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index b007ef0dad..a7ff2222fe 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -247,7 +247,7 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket var ecInfo *objectcore.ECInfo if objType == objectSDK.TypeRegular { var o objectSDK.Object - if err := o.Unmarshal(v); err != nil { + if err := o.Unmarshal(bytes.Clone(v)); err != nil { return nil, nil, nil, err } isLinkingObj = isLinkObject(&o) @@ -413,7 +413,7 @@ func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, p var ecInfo *objectcore.ECInfo if prm.ObjectType == objectSDK.TypeRegular { var o objectSDK.Object - if err := o.Unmarshal(v); err != nil { + if err := o.Unmarshal(bytes.Clone(v)); err != nil { return err } isLinkingObj = isLinkObject(&o) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 09c5e04ad3..2d94e7ae18 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -1,6 +1,7 @@ package meta import ( + "bytes" "context" "encoding/binary" "errors" @@ -313,7 +314,7 @@ func updateSplitInfoIndex(tx *bbolt.Tx, objKey []byte, cnr cid.ID, bucketName [] return si.Marshal() default: oldSI := objectSDK.NewSplitInfo() - if err := oldSI.Unmarshal(old); err != nil { + if err := oldSI.Unmarshal(bytes.Clone(old)); err != nil { return nil, err } si = util.MergeSplitInfo(si, oldSI) From fd004add00fd35924e70dd450221dc74bc285cb9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 13 Nov 2024 10:08:17 +0300 Subject: [PATCH 0992/1413] [#1492] metabase: Fix import formatting Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/iterators.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/iterators.go b/pkg/local_object_storage/metabase/iterators.go index 1809bfd2d5..5d42e41250 100644 --- a/pkg/local_object_storage/metabase/iterators.go +++ b/pkg/local_object_storage/metabase/iterators.go @@ -13,7 +13,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" "go.opentelemetry.io/otel/attribute" From c16dae8b4d76c55037a56d9382d359fa91dc27f6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 18 Oct 2024 13:31:53 +0300 Subject: [PATCH 0993/1413] [#1437] logger: Use context to log trace id Signed-off-by: Dmitrii Stepanov --- pkg/util/logger/log.go | 40 ++++++++++++++++++++++++++++++++++ pkg/util/logger/logger.go | 16 +++++++++++--- pkg/util/logger/test/logger.go | 11 +++++----- 3 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 pkg/util/logger/log.go diff --git a/pkg/util/logger/log.go b/pkg/util/logger/log.go new file mode 100644 index 0000000000..269e07d906 --- /dev/null +++ b/pkg/util/logger/log.go @@ -0,0 +1,40 @@ +package logger + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" + "go.uber.org/zap" +) + +func (l *Logger) Debug(ctx context.Context, msg string, fields ...zap.Field) { + if traceID := tracing.GetTraceID(ctx); traceID != "" { + l.z.Debug(msg, append(fields, zap.String("trace_id", traceID))...) + return + } + l.z.Debug(msg, fields...) +} + +func (l *Logger) Info(ctx context.Context, msg string, fields ...zap.Field) { + if traceID := tracing.GetTraceID(ctx); traceID != "" { + l.z.Info(msg, append(fields, zap.String("trace_id", traceID))...) + return + } + l.z.Info(msg, fields...) +} + +func (l *Logger) Warn(ctx context.Context, msg string, fields ...zap.Field) { + if traceID := tracing.GetTraceID(ctx); traceID != "" { + l.z.Warn(msg, append(fields, zap.String("trace_id", traceID))...) + return + } + l.z.Warn(msg, fields...) +} + +func (l *Logger) Error(ctx context.Context, msg string, fields ...zap.Field) { + if traceID := tracing.GetTraceID(ctx); traceID != "" { + l.z.Error(msg, append(fields, zap.String("trace_id", traceID))...) + return + } + l.z.Error(msg, fields...) +} diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index 4b60f02de0..d4ac2ab027 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -12,7 +12,7 @@ import ( // Logger represents a component // for writing messages to log. type Logger struct { - *zap.Logger + z *zap.Logger lvl zap.AtomicLevel } @@ -136,7 +136,7 @@ func newConsoleLogger(prm *Prm) (*Logger, error) { return nil, err } - l := &Logger{Logger: lZap, lvl: lvl} + l := &Logger{z: lZap, lvl: lvl} prm._log = l return l, nil @@ -169,7 +169,7 @@ func newJournaldLogger(prm *Prm) (*Logger, error) { lZap := zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel))) - l := &Logger{Logger: lZap, lvl: lvl} + l := &Logger{z: lZap, lvl: lvl} prm._log = l return l, nil @@ -179,3 +179,13 @@ func (l *Logger) reload(prm Prm) error { l.lvl.SetLevel(prm.level) return nil } + +func (l *Logger) WithOptions(options ...zap.Option) { + l.z = l.z.WithOptions(options...) +} + +func NewLoggerWrapper(z *zap.Logger) *Logger { + return &Logger{ + z: z, + } +} diff --git a/pkg/util/logger/test/logger.go b/pkg/util/logger/test/logger.go index f93756d17e..b5b0a31eb2 100644 --- a/pkg/util/logger/test/logger.go +++ b/pkg/util/logger/test/logger.go @@ -11,9 +11,10 @@ import ( // NewLogger creates a new logger. func NewLogger(t testing.TB) *logger.Logger { - var l logger.Logger - l.Logger = zaptest.NewLogger(t, - zaptest.Level(zapcore.DebugLevel), - zaptest.WrapOptions(zap.Development(), zap.AddCaller())) - return &l + return logger.NewLoggerWrapper( + zaptest.NewLogger(t, + zaptest.Level(zapcore.DebugLevel), + zaptest.WrapOptions(zap.Development(), zap.AddCaller()), + ), + ) } From 6db46257c0d30ddba71138de248aa86c18611730 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 21 Oct 2024 10:22:54 +0300 Subject: [PATCH 0994/1413] [#1437] node: Use ctx for logging Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-ir/config.go | 25 +++---- cmd/frostfs-ir/httpcomponent.go | 15 ++-- cmd/frostfs-ir/main.go | 12 ++-- cmd/frostfs-ir/pprof.go | 7 +- cmd/frostfs-node/config.go | 68 +++++++++--------- cmd/frostfs-node/container.go | 6 +- cmd/frostfs-node/control.go | 6 +- cmd/frostfs-node/grpc.go | 29 ++++---- cmd/frostfs-node/httpcomponent.go | 4 +- cmd/frostfs-node/main.go | 20 +++--- cmd/frostfs-node/morph.go | 22 +++--- cmd/frostfs-node/netmap.go | 10 +-- cmd/frostfs-node/object.go | 6 +- cmd/frostfs-node/runtime.go | 5 +- cmd/frostfs-node/tracing.go | 6 +- cmd/frostfs-node/tree.go | 10 +-- internal/audit/request.go | 4 +- pkg/core/object/fmt_test.go | 12 ++-- pkg/core/object/sender_classifier.go | 5 +- pkg/innerring/initialization.go | 12 ++-- pkg/innerring/innerring.go | 14 ++-- pkg/innerring/notary.go | 8 +-- pkg/innerring/processors/alphabet/handlers.go | 6 +- .../processors/alphabet/process_emit.go | 19 ++--- .../processors/alphabet/processor.go | 3 +- pkg/innerring/processors/balance/handlers.go | 5 +- .../processors/balance/process_assets.go | 6 +- pkg/innerring/processors/balance/processor.go | 3 +- .../processors/container/handlers.go | 9 +-- .../processors/container/process_container.go | 13 ++-- .../processors/container/processor.go | 3 +- pkg/innerring/processors/frostfs/handlers.go | 17 ++--- .../processors/frostfs/process_assets.go | 24 ++++--- .../processors/frostfs/process_config.go | 6 +- pkg/innerring/processors/frostfs/processor.go | 3 +- .../processors/governance/handlers.go | 6 +- .../processors/governance/process_update.go | 29 ++++---- pkg/innerring/processors/netmap/handlers.go | 23 +++--- .../processors/netmap/process_cleanup.go | 12 ++-- .../processors/netmap/process_epoch.go | 16 +++-- .../processors/netmap/process_peers.go | 19 ++--- pkg/innerring/processors/netmap/processor.go | 3 +- pkg/innerring/state.go | 15 ++-- .../blobovnicza/blobovnicza.go | 4 +- .../blobovnicza/control.go | 19 ++--- .../blobovnicza/delete.go | 2 +- .../blobstor/blobovniczatree/control.go | 6 +- .../blobstor/blobovniczatree/delete.go | 2 +- .../blobstor/blobovniczatree/exists.go | 2 +- .../blobstor/blobovniczatree/get.go | 2 +- .../blobstor/blobovniczatree/get_range.go | 2 +- .../blobstor/blobovniczatree/iterate.go | 4 +- .../blobstor/blobovniczatree/manager.go | 7 +- .../blobstor/blobovniczatree/option.go | 2 +- .../blobstor/blobovniczatree/put.go | 6 +- .../blobstor/blobovniczatree/rebuild.go | 50 ++++++------- pkg/local_object_storage/blobstor/blobstor.go | 4 +- pkg/local_object_storage/blobstor/control.go | 8 +-- pkg/local_object_storage/blobstor/delete.go | 4 +- pkg/local_object_storage/blobstor/exists.go | 2 +- .../blobstor/fstree/fstree.go | 6 +- .../blobstor/fstree/option.go | 2 +- pkg/local_object_storage/blobstor/iterate.go | 2 +- pkg/local_object_storage/blobstor/logger.go | 6 +- pkg/local_object_storage/blobstor/put.go | 2 +- pkg/local_object_storage/blobstor/rebuild.go | 4 +- pkg/local_object_storage/engine/control.go | 14 ++-- pkg/local_object_storage/engine/delete.go | 6 +- pkg/local_object_storage/engine/engine.go | 20 +++--- pkg/local_object_storage/engine/evacuate.go | 28 ++++---- pkg/local_object_storage/engine/get.go | 2 +- pkg/local_object_storage/engine/inhume.go | 24 +++---- pkg/local_object_storage/engine/put.go | 8 +-- pkg/local_object_storage/engine/range.go | 2 +- .../engine/remove_copies.go | 8 +-- pkg/local_object_storage/engine/shards.go | 16 ++--- pkg/local_object_storage/internal/log/log.go | 6 +- pkg/local_object_storage/metabase/control.go | 6 +- pkg/local_object_storage/metabase/db.go | 2 +- pkg/local_object_storage/metabase/delete.go | 2 +- pkg/local_object_storage/metabase/inhume.go | 2 +- pkg/local_object_storage/metabase/put.go | 2 +- .../metabase/upgrade_test.go | 10 +-- pkg/local_object_storage/shard/control.go | 16 ++--- pkg/local_object_storage/shard/delete.go | 6 +- pkg/local_object_storage/shard/gc.go | 70 +++++++++---------- pkg/local_object_storage/shard/get.go | 6 +- pkg/local_object_storage/shard/id.go | 3 +- pkg/local_object_storage/shard/inhume.go | 2 +- pkg/local_object_storage/shard/list.go | 2 +- pkg/local_object_storage/shard/lock_test.go | 2 +- pkg/local_object_storage/shard/mode.go | 6 +- pkg/local_object_storage/shard/put.go | 2 +- pkg/local_object_storage/shard/rebuild.go | 8 +-- pkg/local_object_storage/shard/shard.go | 10 +-- pkg/local_object_storage/shard/writecache.go | 6 +- pkg/local_object_storage/writecache/cache.go | 2 +- pkg/local_object_storage/writecache/delete.go | 2 +- pkg/local_object_storage/writecache/flush.go | 4 +- .../writecache/flush_test.go | 2 +- pkg/local_object_storage/writecache/mode.go | 4 +- .../writecache/options.go | 2 +- pkg/local_object_storage/writecache/put.go | 2 +- .../writecache/storage.go | 4 +- pkg/morph/client/client.go | 10 +-- pkg/morph/client/constructor.go | 6 +- pkg/morph/client/multi.go | 8 +-- pkg/morph/client/notary.go | 9 +-- pkg/morph/event/listener.go | 70 +++++++++---------- pkg/morph/event/utils.go | 3 +- pkg/morph/subscriber/subscriber.go | 10 +-- pkg/services/apemanager/executor.go | 2 +- pkg/services/object/acl/v2/service.go | 2 +- pkg/services/object/common/writer/common.go | 2 +- pkg/services/object/common/writer/ec.go | 8 +-- pkg/services/object/delete/delete.go | 6 +- pkg/services/object/delete/exec.go | 18 ++--- pkg/services/object/delete/local.go | 6 +- pkg/services/object/delete/service.go | 4 +- pkg/services/object/get/assemble.go | 10 +-- pkg/services/object/get/assembleec.go | 10 +-- pkg/services/object/get/assemblerec.go | 18 ++--- pkg/services/object/get/container.go | 12 ++-- pkg/services/object/get/get.go | 14 ++-- pkg/services/object/get/local.go | 2 +- pkg/services/object/get/remote.go | 4 +- pkg/services/object/get/request.go | 14 ++-- pkg/services/object/get/service.go | 4 +- pkg/services/object/get/v2/get_range_hash.go | 8 +-- pkg/services/object/get/v2/service.go | 4 +- pkg/services/object/put/service.go | 2 +- pkg/services/object/put/single.go | 2 +- pkg/services/object/search/container.go | 16 ++--- pkg/services/object/search/exec.go | 4 +- pkg/services/object/search/local.go | 2 +- pkg/services/object/search/search.go | 8 +-- pkg/services/object/search/service.go | 4 +- pkg/services/object/util/log.go | 6 +- .../object_manager/tombstone/checker.go | 4 +- .../object_manager/tombstone/constructor.go | 2 +- pkg/services/policer/check.go | 10 +-- pkg/services/policer/ec.go | 40 +++++------ pkg/services/policer/option.go | 2 +- pkg/services/policer/policer.go | 3 +- pkg/services/policer/process.go | 8 +-- pkg/services/replicator/process.go | 8 +-- pkg/services/replicator/pull.go | 8 +-- pkg/services/replicator/put.go | 6 +- pkg/services/replicator/replicator.go | 2 +- pkg/services/session/executor.go | 2 +- .../session/storage/persistent/options.go | 2 +- .../session/storage/persistent/storage.go | 7 +- pkg/services/tree/redirect.go | 2 +- pkg/services/tree/replicator.go | 8 +-- pkg/services/tree/service.go | 2 +- pkg/services/tree/sync.go | 36 +++++----- pkg/util/logger/logger.go | 4 ++ 157 files changed, 764 insertions(+), 713 deletions(-) diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index 137e764ed3..34d9d55950 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -1,6 +1,7 @@ package main import ( + "context" "os" "os/signal" "syscall" @@ -58,13 +59,13 @@ func watchForSignal(cancel func()) { // signals causing application to shut down should have priority over // reconfiguration signal case <-ch: - log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + log.Info(context.Background(), logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) cancel() shutdown() - log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) + log.Info(context.Background(), logs.FrostFSNodeTerminationSignalProcessingIsComplete) return case err := <-intErr: // internal application error - log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error())) + log.Info(context.Background(), logs.FrostFSIRInternalError, zap.String("msg", err.Error())) cancel() shutdown() return @@ -72,35 +73,35 @@ func watchForSignal(cancel func()) { // block until any signal is receieved select { case <-ch: - log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + log.Info(context.Background(), logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) cancel() shutdown() - log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) + log.Info(context.Background(), logs.FrostFSNodeTerminationSignalProcessingIsComplete) return case err := <-intErr: // internal application error - log.Info(logs.FrostFSIRInternalError, zap.String("msg", err.Error())) + log.Info(context.Background(), logs.FrostFSIRInternalError, zap.String("msg", err.Error())) cancel() shutdown() return case <-sighupCh: - log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) + log.Info(context.Background(), logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) if !innerRing.CompareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { - log.Info(logs.FrostFSNodeSIGHUPSkip) + log.Info(context.Background(), logs.FrostFSNodeSIGHUPSkip) break } err := reloadConfig() if err != nil { - log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) + log.Error(context.Background(), logs.FrostFSNodeConfigurationReading, zap.Error(err)) } pprofCmp.reload() metricsCmp.reload() - log.Info(logs.FrostFSIRReloadExtraWallets) + log.Info(context.Background(), logs.FrostFSIRReloadExtraWallets) err = innerRing.SetExtraWallets(cfg) if err != nil { - log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) + log.Error(context.Background(), logs.FrostFSNodeConfigurationReading, zap.Error(err)) } innerRing.CompareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) - log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) + log.Info(context.Background(), logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) } } } diff --git a/cmd/frostfs-ir/httpcomponent.go b/cmd/frostfs-ir/httpcomponent.go index 2792c35486..685ef61add 100644 --- a/cmd/frostfs-ir/httpcomponent.go +++ b/cmd/frostfs-ir/httpcomponent.go @@ -1,6 +1,7 @@ package main import ( + "context" "net/http" "time" @@ -25,7 +26,7 @@ const ( ) func (c *httpComponent) init() { - log.Info("init " + c.name) + log.Info(context.Background(), "init "+c.name) c.enabled = cfg.GetBool(c.name + enabledKeyPostfix) c.address = cfg.GetString(c.name + addressKeyPostfix) c.shutdownDur = cfg.GetDuration(c.name + shutdownTimeoutKeyPostfix) @@ -39,14 +40,14 @@ func (c *httpComponent) init() { httputil.WithShutdownTimeout(c.shutdownDur), ) } else { - log.Info(c.name + " is disabled, skip") + log.Info(context.Background(), c.name+" is disabled, skip") c.srv = nil } } func (c *httpComponent) start() { if c.srv != nil { - log.Info("start " + c.name) + log.Info(context.Background(), "start "+c.name) wg.Add(1) go func() { defer wg.Done() @@ -57,7 +58,7 @@ func (c *httpComponent) start() { func (c *httpComponent) shutdown() error { if c.srv != nil { - log.Info("shutdown " + c.name) + log.Info(context.Background(), "shutdown "+c.name) return c.srv.Shutdown() } return nil @@ -71,11 +72,11 @@ func (c *httpComponent) needReload() bool { } func (c *httpComponent) reload() { - log.Info("reload " + c.name) + log.Info(context.Background(), "reload "+c.name) if c.needReload() { - log.Info(c.name + " config updated") + log.Info(context.Background(), c.name+" config updated") if err := c.shutdown(); err != nil { - log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, + log.Debug(context.Background(), logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } else { diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 4bc5923a0d..55a8ce00dd 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -103,32 +103,32 @@ func main() { err = innerRing.Start(ctx, intErr) exitErr(err) - log.Info(logs.CommonApplicationStarted, + log.Info(ctx, logs.CommonApplicationStarted, zap.String("version", misc.Version)) watchForSignal(cancel) <-ctx.Done() // graceful shutdown - log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop) + log.Debug(ctx, logs.FrostFSNodeWaitingForAllProcessesToStop) wg.Wait() - log.Info(logs.FrostFSIRApplicationStopped) + log.Info(ctx, logs.FrostFSIRApplicationStopped) } func shutdown() { innerRing.Stop() if err := metricsCmp.shutdown(); err != nil { - log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, + log.Debug(context.Background(), logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } if err := pprofCmp.shutdown(); err != nil { - log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, + log.Debug(context.Background(), logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } if err := sdnotify.ClearStatus(); err != nil { - log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) + log.Error(context.Background(), logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/cmd/frostfs-ir/pprof.go b/cmd/frostfs-ir/pprof.go index ff5642008d..e95fd117f7 100644 --- a/cmd/frostfs-ir/pprof.go +++ b/cmd/frostfs-ir/pprof.go @@ -1,6 +1,7 @@ package main import ( + "context" "runtime" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -52,11 +53,11 @@ func (c *pprofComponent) needReload() bool { } func (c *pprofComponent) reload() { - log.Info("reload " + c.name) + log.Info(context.Background(), "reload "+c.name) if c.needReload() { - log.Info(c.name + " config updated") + log.Info(context.Background(), c.name+" config updated") if err := c.shutdown(); err != nil { - log.Debug(logs.FrostFSIRCouldNotShutdownHTTPServer, + log.Debug(context.Background(), logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error())) return } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 902187560d..bd1b99095c 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -400,13 +400,13 @@ type internals struct { func (c *cfg) startMaintenance() { c.isMaintenance.Store(true) c.cfgNetmap.state.setControlNetmapStatus(control.NetmapStatus_MAINTENANCE) - c.log.Info(logs.FrostFSNodeStartedLocalNodesMaintenance) + c.log.Info(context.Background(), logs.FrostFSNodeStartedLocalNodesMaintenance) } // stops node's maintenance. func (c *internals) stopMaintenance() { if c.isMaintenance.CompareAndSwap(true, false) { - c.log.Info(logs.FrostFSNodeStoppedLocalNodesMaintenance) + c.log.Info(context.Background(), logs.FrostFSNodeStoppedLocalNodesMaintenance) } } @@ -705,7 +705,7 @@ func initCfg(appCfg *config.Config) *cfg { log, err := logger.NewLogger(logPrm) fatalOnErr(err) if loggerconfig.ToLokiConfig(appCfg).Enabled { - log.Logger = log.Logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { + log.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { lokiCore := lokicore.New(core, loggerconfig.ToLokiConfig(appCfg)) return lokiCore })) @@ -1103,10 +1103,10 @@ func initLocalStorage(ctx context.Context, c *cfg) { shard.WithTombstoneSource(c.createTombstoneSource()), shard.WithContainerInfoProvider(c.createContainerInfoProvider(ctx)))...) if err != nil { - c.log.Error(logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeFailedToAttachShardToEngine, zap.Error(err)) } else { shardsAttached++ - c.log.Info(logs.FrostFSNodeShardAttachedToEngine, zap.Stringer("id", id)) + c.log.Info(ctx, logs.FrostFSNodeShardAttachedToEngine, zap.Stringer("id", id)) } } if shardsAttached == 0 { @@ -1116,15 +1116,15 @@ func initLocalStorage(ctx context.Context, c *cfg) { c.cfgObject.cfgLocalStorage.localStorage = ls c.onShutdown(func() { - c.log.Info(logs.FrostFSNodeClosingComponentsOfTheStorageEngine) + c.log.Info(ctx, logs.FrostFSNodeClosingComponentsOfTheStorageEngine) err := ls.Close(context.WithoutCancel(ctx)) if err != nil { - c.log.Info(logs.FrostFSNodeStorageEngineClosingFailure, + c.log.Info(ctx, logs.FrostFSNodeStorageEngineClosingFailure, zap.String("error", err.Error()), ) } else { - c.log.Info(logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully) + c.log.Info(ctx, logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully) } }) } @@ -1132,7 +1132,7 @@ func initLocalStorage(ctx context.Context, c *cfg) { func initAccessPolicyEngine(_ context.Context, c *cfg) { var localOverrideDB chainbase.LocalOverrideDatabase if nodeconfig.PersistentPolicyRules(c.appCfg).Path() == "" { - c.log.Warn(logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed) + c.log.Warn(context.Background(), logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed) localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase() } else { localOverrideDB = chainbase.NewBoltLocalOverrideDatabase( @@ -1157,7 +1157,7 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) { c.onShutdown(func() { if err := ape.LocalOverrideDatabaseCore().Close(); err != nil { - c.log.Warn(logs.FrostFSNodeAccessPolicyEngineClosingFailure, + c.log.Warn(context.Background(), logs.FrostFSNodeAccessPolicyEngineClosingFailure, zap.Error(err), ) } @@ -1209,7 +1209,7 @@ func (c *cfg) setContractNodeInfo(ni *netmap.NodeInfo) { func (c *cfg) updateContractNodeInfo(epoch uint64) { ni, err := c.netmapLocalNodeState(epoch) if err != nil { - c.log.Error(logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, + c.log.Error(context.Background(), logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, zap.Uint64("epoch", epoch), zap.String("error", err.Error())) return @@ -1245,13 +1245,13 @@ func (c *cfg) bootstrap() error { // switch to online except when under maintenance st := c.cfgNetmap.state.controlNetmapStatus() if st == control.NetmapStatus_MAINTENANCE { - c.log.Info(logs.FrostFSNodeBootstrappingWithTheMaintenanceState) + c.log.Info(context.Background(), logs.FrostFSNodeBootstrappingWithTheMaintenanceState) return c.bootstrapWithState(func(ni *netmap.NodeInfo) { ni.SetStatus(netmap.Maintenance) }) } - c.log.Info(logs.FrostFSNodeBootstrappingWithOnlineState, + c.log.Info(context.Background(), logs.FrostFSNodeBootstrappingWithOnlineState, zap.Stringer("previous", st), ) @@ -1280,19 +1280,19 @@ func (c *cfg) signalWatcher(ctx context.Context) { // signals causing application to shut down should have priority over // reconfiguration signal case <-ch: - c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) c.shutdown() - c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) + c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) return case err := <-c.internalErr: // internal application error - c.log.Warn(logs.FrostFSNodeInternalApplicationError, + c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError, zap.String("message", err.Error())) c.shutdown() - c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete) + c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete) return default: // block until any signal is receieved @@ -1300,19 +1300,19 @@ func (c *cfg) signalWatcher(ctx context.Context) { case <-sighupCh: c.reloadConfig(ctx) case <-ch: - c.log.Info(logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) c.shutdown() - c.log.Info(logs.FrostFSNodeTerminationSignalProcessingIsComplete) + c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) return case err := <-c.internalErr: // internal application error - c.log.Warn(logs.FrostFSNodeInternalApplicationError, + c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError, zap.String("message", err.Error())) c.shutdown() - c.log.Info(logs.FrostFSNodeInternalErrorProcessingIsComplete) + c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete) return } } @@ -1320,17 +1320,17 @@ func (c *cfg) signalWatcher(ctx context.Context) { } func (c *cfg) reloadConfig(ctx context.Context) { - c.log.Info(logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) + c.log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) if !c.compareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { - c.log.Info(logs.FrostFSNodeSIGHUPSkip) + c.log.Info(ctx, logs.FrostFSNodeSIGHUPSkip) return } defer c.compareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) err := c.reloadAppConfig() if err != nil { - c.log.Error(logs.FrostFSNodeConfigurationReading, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err)) return } @@ -1341,7 +1341,7 @@ func (c *cfg) reloadConfig(ctx context.Context) { logPrm, err := c.loggerPrm() if err != nil { - c.log.Error(logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err)) return } @@ -1362,25 +1362,25 @@ func (c *cfg) reloadConfig(ctx context.Context) { err = c.cfgObject.cfgLocalStorage.localStorage.Reload(ctx, rcfg) if err != nil { - c.log.Error(logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeStorageEngineConfigurationUpdate, zap.Error(err)) return } for _, component := range components { err = component.reloadFunc() if err != nil { - c.log.Error(logs.FrostFSNodeUpdatedConfigurationApplying, + c.log.Error(ctx, logs.FrostFSNodeUpdatedConfigurationApplying, zap.String("component", component.name), zap.Error(err)) } } if err := c.dialerSource.Update(internalNetConfig(c.appCfg, c.metricsCollector.MultinetMetrics())); err != nil { - c.log.Error(logs.FailedToUpdateMultinetConfiguration, zap.Error(err)) + c.log.Error(ctx, logs.FailedToUpdateMultinetConfiguration, zap.Error(err)) return } - c.log.Info(logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) + c.log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) } func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { @@ -1403,7 +1403,7 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { } updated, err := tracing.Setup(ctx, *traceConfig) if updated { - c.log.Info(logs.FrostFSNodeTracingConfigationUpdated) + c.log.Info(ctx, logs.FrostFSNodeTracingConfigationUpdated) } return err }}) @@ -1438,7 +1438,7 @@ func (c *cfg) reloadPools() error { func (c *cfg) reloadPool(p *ants.Pool, newSize int, name string) { oldSize := p.Cap() if oldSize != newSize { - c.log.Info(logs.FrostFSNodePoolConfigurationUpdate, zap.String("field", name), + c.log.Info(context.Background(), logs.FrostFSNodePoolConfigurationUpdate, zap.String("field", name), zap.Int("old", oldSize), zap.Int("new", newSize)) p.Tune(newSize) } @@ -1477,11 +1477,11 @@ func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoPro func (c *cfg) shutdown() { old := c.swapHealthStatus(control.HealthStatus_SHUTTING_DOWN) if old == control.HealthStatus_SHUTTING_DOWN { - c.log.Info(logs.FrostFSNodeShutdownSkip) + c.log.Info(context.Background(), logs.FrostFSNodeShutdownSkip) return } if old == control.HealthStatus_STARTING { - c.log.Warn(logs.FrostFSNodeShutdownWhenNotReady) + c.log.Warn(context.Background(), logs.FrostFSNodeShutdownWhenNotReady) } c.ctxCancel() @@ -1491,6 +1491,6 @@ func (c *cfg) shutdown() { } if err := sdnotify.ClearStatus(); err != nil { - c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) + c.log.Error(context.Background(), logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index cc38876ee1..1a54f9ffc2 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -102,13 +102,13 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c } else { // unlike removal, we expect successful receive of the container // after successful creation, so logging can be useful - c.log.Error(logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification, + c.log.Error(context.Background(), logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification, zap.Stringer("id", ev.ID), zap.Error(err), ) } - c.log.Debug(logs.FrostFSNodeContainerCreationEventsReceipt, + c.log.Debug(context.Background(), logs.FrostFSNodeContainerCreationEventsReceipt, zap.Stringer("id", ev.ID), ) }) @@ -116,7 +116,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c subscribeToContainerRemoval(c, func(e event.Event) { ev := e.(containerEvent.DeleteSuccess) containerCache.handleRemoval(ev.ID) - c.log.Debug(logs.FrostFSNodeContainerRemovalEventsReceipt, + c.log.Debug(context.Background(), logs.FrostFSNodeContainerRemovalEventsReceipt, zap.Stringer("id", ev.ID), ) }) diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index e1e6e3ac9e..ffac23eec3 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -46,7 +46,7 @@ func initControlService(c *cfg) { lis, err := net.Listen("tcp", endpoint) if err != nil { - c.log.Error(logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err)) + c.log.Error(context.Background(), logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err)) return } @@ -60,7 +60,7 @@ func initControlService(c *cfg) { c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { runAndLog(ctx, c, serviceNameControl, false, func(context.Context, *cfg) { - c.log.Info(logs.FrostFSNodeStartListeningEndpoint, + c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint, zap.String("service", serviceNameControl), zap.String("endpoint", endpoint)) fatalOnErr(c.cfgControlService.server.Serve(lis)) @@ -113,6 +113,6 @@ func (c *cfg) notifySystemd(st control.HealthStatus) { err = sdnotify.Status(fmt.Sprintf("%v", st)) } if err != nil { - c.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) + c.log.Error(context.Background(), logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index 3a38b2cca2..271810ee6b 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -1,6 +1,7 @@ package main import ( + "context" "crypto/tls" "errors" "net" @@ -30,7 +31,7 @@ func initGRPC(c *cfg) { lis, err := net.Listen("tcp", sc.Endpoint()) if err != nil { c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint()) - c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) + c.log.Error(context.Background(), logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) endpointsToReconnect = append(endpointsToReconnect, sc.Endpoint()) return } @@ -76,19 +77,19 @@ func scheduleReconnect(endpoint string, c *cfg) { } func tryReconnect(endpoint string, c *cfg) bool { - c.log.Info(logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint)) + c.log.Info(context.Background(), logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint)) serverOpts, found := getGRPCEndpointOpts(endpoint, c) if !found { - c.log.Warn(logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint)) + c.log.Warn(context.Background(), logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint)) return true } lis, err := net.Listen("tcp", endpoint) if err != nil { c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(endpoint) - c.log.Error(logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) - c.log.Warn(logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout)) + c.log.Error(context.Background(), logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) + c.log.Warn(context.Background(), logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout)) return false } c.metricsCollector.GrpcServerMetrics().MarkHealthy(endpoint) @@ -101,7 +102,7 @@ func tryReconnect(endpoint string, c *cfg) bool { c.cfgGRPC.appendAndHandle(endpoint, lis, srv) - c.log.Info(logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint)) + c.log.Info(context.Background(), logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint)) return true } @@ -143,7 +144,7 @@ func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool if tlsCfg != nil { cert, err := tls.LoadX509KeyPair(tlsCfg.CertificateFile(), tlsCfg.KeyFile()) if err != nil { - c.log.Error(logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err)) + c.log.Error(context.Background(), logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err)) return nil, false } @@ -180,21 +181,21 @@ func serveGRPC(c *cfg) { go func() { defer func() { - c.log.Info(logs.FrostFSNodeStopListeningGRPCEndpoint, + c.log.Info(context.Background(), logs.FrostFSNodeStopListeningGRPCEndpoint, zap.Stringer("endpoint", l.Addr()), ) c.wg.Done() }() - c.log.Info(logs.FrostFSNodeStartListeningEndpoint, + c.log.Info(context.Background(), logs.FrostFSNodeStartListeningEndpoint, zap.String("service", "gRPC"), zap.Stringer("endpoint", l.Addr()), ) if err := s.Serve(l); err != nil { c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(e) - c.log.Error(logs.FrostFSNodeGRPCServerError, zap.Error(err)) + c.log.Error(context.Background(), logs.FrostFSNodeGRPCServerError, zap.Error(err)) c.cfgGRPC.dropConnection(e) scheduleReconnect(e, c) } @@ -203,9 +204,9 @@ func serveGRPC(c *cfg) { } func stopGRPC(name string, s *grpc.Server, l *logger.Logger) { - l = &logger.Logger{Logger: l.With(zap.String("name", name))} + l = l.With(zap.String("name", name)) - l.Info(logs.FrostFSNodeStoppingGRPCServer) + l.Info(context.Background(), logs.FrostFSNodeStoppingGRPCServer) // GracefulStop() may freeze forever, see #1270 done := make(chan struct{}) @@ -217,9 +218,9 @@ func stopGRPC(name string, s *grpc.Server, l *logger.Logger) { select { case <-done: case <-time.After(1 * time.Minute): - l.Info(logs.FrostFSNodeGRPCCannotShutdownGracefullyForcingStop) + l.Info(context.Background(), logs.FrostFSNodeGRPCCannotShutdownGracefullyForcingStop) s.Stop() } - l.Info(logs.FrostFSNodeGRPCServerStoppedSuccessfully) + l.Info(context.Background(), logs.FrostFSNodeGRPCServerStoppedSuccessfully) } diff --git a/cmd/frostfs-node/httpcomponent.go b/cmd/frostfs-node/httpcomponent.go index 2ec20d848a..a699a72a1f 100644 --- a/cmd/frostfs-node/httpcomponent.go +++ b/cmd/frostfs-node/httpcomponent.go @@ -22,7 +22,7 @@ type httpComponent struct { func (cmp *httpComponent) init(c *cfg) { if !cmp.enabled { - c.log.Info(cmp.name + " is disabled") + c.log.Info(context.Background(), cmp.name+" is disabled") return } // Init server with parameters @@ -39,7 +39,7 @@ func (cmp *httpComponent) init(c *cfg) { go func() { defer c.wg.Done() - c.log.Info(logs.FrostFSNodeStartListeningEndpoint, + c.log.Info(context.Background(), logs.FrostFSNodeStartListeningEndpoint, zap.String("service", cmp.name), zap.String("endpoint", cmp.address)) fatalOnErr(srv.Serve()) diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index e4f0a434c2..cd42d5f1df 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -73,9 +73,9 @@ func main() { } func initAndLog(c *cfg, name string, initializer func(*cfg)) { - c.log.Info(fmt.Sprintf("initializing %s service...", name)) + c.log.Info(context.Background(), fmt.Sprintf("initializing %s service...", name)) initializer(c) - c.log.Info(name + " service has been successfully initialized") + c.log.Info(context.Background(), name+" service has been successfully initialized") } func initApp(ctx context.Context, c *cfg) { @@ -120,25 +120,25 @@ func initApp(ctx context.Context, c *cfg) { } func runAndLog(ctx context.Context, c *cfg, name string, logSuccess bool, starter func(context.Context, *cfg)) { - c.log.Info(fmt.Sprintf("starting %s service...", name)) + c.log.Info(ctx, fmt.Sprintf("starting %s service...", name)) starter(ctx, c) if logSuccess { - c.log.Info(name + " service started successfully") + c.log.Info(ctx, name+" service started successfully") } } func stopAndLog(c *cfg, name string, stopper func() error) { - c.log.Debug(fmt.Sprintf("shutting down %s service", name)) + c.log.Debug(context.Background(), fmt.Sprintf("shutting down %s service", name)) err := stopper() if err != nil { - c.log.Debug(fmt.Sprintf("could not shutdown %s server", name), + c.log.Debug(context.Background(), fmt.Sprintf("could not shutdown %s server", name), zap.String("error", err.Error()), ) } - c.log.Debug(name + " service has been stopped") + c.log.Debug(context.Background(), name+" service has been stopped") } func bootUp(ctx context.Context, c *cfg) { @@ -150,7 +150,7 @@ func bootUp(ctx context.Context, c *cfg) { } func wait(c *cfg) { - c.log.Info(logs.CommonApplicationStarted, + c.log.Info(context.Background(), logs.CommonApplicationStarted, zap.String("version", misc.Version)) <-c.done // graceful shutdown @@ -160,12 +160,12 @@ func wait(c *cfg) { go func() { defer drain.Done() for err := range c.internalErr { - c.log.Warn(logs.FrostFSNodeInternalApplicationError, + c.log.Warn(context.Background(), logs.FrostFSNodeInternalApplicationError, zap.String("message", err.Error())) } }() - c.log.Debug(logs.FrostFSNodeWaitingForAllProcessesToStop) + c.log.Debug(context.Background(), logs.FrostFSNodeWaitingForAllProcessesToStop) c.wg.Wait() diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 0969f55794..3e010b181b 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -48,7 +48,7 @@ func (c *cfg) initMorphComponents(ctx context.Context) { fatalOnErr(err) } - c.log.Info(logs.FrostFSNodeNotarySupport, + c.log.Info(ctx, logs.FrostFSNodeNotarySupport, zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled), ) @@ -64,7 +64,7 @@ func (c *cfg) initMorphComponents(ctx context.Context) { msPerBlock, err := c.cfgMorph.client.MsPerBlock() fatalOnErr(err) c.cfgMorph.cacheTTL = time.Duration(msPerBlock) * time.Millisecond - c.log.Debug(logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL)) + c.log.Debug(ctx, logs.FrostFSNodeMorphcacheTTLFetchedFromNetwork, zap.Duration("value", c.cfgMorph.cacheTTL)) } if c.cfgMorph.cacheTTL < 0 { @@ -102,7 +102,7 @@ func initMorphClient(ctx context.Context, c *cfg) { client.WithDialerSource(c.dialerSource), ) if err != nil { - c.log.Info(logs.FrostFSNodeFailedToCreateNeoRPCClient, + c.log.Info(ctx, logs.FrostFSNodeFailedToCreateNeoRPCClient, zap.Any("endpoints", addresses), zap.String("error", err.Error()), ) @@ -111,12 +111,12 @@ func initMorphClient(ctx context.Context, c *cfg) { } c.onShutdown(func() { - c.log.Info(logs.FrostFSNodeClosingMorphComponents) + c.log.Info(ctx, logs.FrostFSNodeClosingMorphComponents) cli.Close() }) if err := cli.SetGroupSignerScope(); err != nil { - c.log.Info(logs.FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal, zap.Error(err)) + c.log.Info(ctx, logs.FrostFSNodeFailedToSetGroupSignerScopeContinueWithGlobal, zap.Error(err)) } c.cfgMorph.client = cli @@ -136,7 +136,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { // non-error deposit with an empty TX hash means // that the deposit has already been made; no // need to wait it. - c.log.Info(logs.FrostFSNodeNotaryDepositHasAlreadyBeenMade) + c.log.Info(ctx, logs.FrostFSNodeNotaryDepositHasAlreadyBeenMade) return } @@ -202,7 +202,7 @@ func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) return fmt.Errorf("could not wait for notary deposit persists in chain: %w", err) } if res.Execution.VMState.HasFlag(vmstate.Halt) { - c.log.Info(logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) + c.log.Info(ctx, logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) return nil } return errNotaryDepositFail @@ -217,7 +217,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { fromSideChainBlock, err := c.persistate.UInt32(persistateSideChainLastBlockKey) if err != nil { fromSideChainBlock = 0 - c.log.Warn(logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) + c.log.Warn(ctx, logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) } subs, err = subscriber.New(ctx, &subscriber.Params{ @@ -246,7 +246,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { setNetmapNotificationParser(c, newEpochNotification, func(src *state.ContainedNotificationEvent) (event.Event, error) { res, err := netmapEvent.ParseNewEpoch(src) if err == nil { - c.log.Info(logs.FrostFSNodeNewEpochEventFromSidechain, + c.log.Info(ctx, logs.FrostFSNodeNewEpochEventFromSidechain, zap.Uint64("number", res.(netmapEvent.NewEpoch).EpochNumber()), ) } @@ -257,11 +257,11 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { registerNotificationHandlers(c.cfgContainer.scriptHash, lis, c.cfgContainer.parsers, c.cfgContainer.subscribers) registerBlockHandler(lis, func(block *block.Block) { - c.log.Debug(logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index)) + c.log.Debug(ctx, logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index)) err = c.persistate.SetUInt32(persistateSideChainLastBlockKey, block.Index) if err != nil { - c.log.Warn(logs.FrostFSNodeCantUpdatePersistentState, + c.log.Warn(ctx, logs.FrostFSNodeCantUpdatePersistentState, zap.String("chain", "side"), zap.Uint32("block_index", block.Index)) } diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 73871bfc9d..18667e6361 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -189,7 +189,7 @@ func addNewEpochNotificationHandlers(c *cfg) { } if err := c.bootstrap(); err != nil { - c.log.Warn(logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) + c.log.Warn(context.Background(), logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) } }) @@ -197,7 +197,7 @@ func addNewEpochNotificationHandlers(c *cfg) { addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { _, _, err := makeNotaryDeposit(c) if err != nil { - c.log.Error(logs.FrostFSNodeCouldNotMakeNotaryDeposit, + c.log.Error(context.Background(), logs.FrostFSNodeCouldNotMakeNotaryDeposit, zap.String("error", err.Error()), ) } @@ -210,7 +210,7 @@ func addNewEpochNotificationHandlers(c *cfg) { func bootstrapNode(c *cfg) { if c.needBootstrap() { if c.IsMaintenance() { - c.log.Info(logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) + c.log.Info(context.Background(), logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) return } err := c.bootstrap() @@ -250,7 +250,7 @@ func initNetmapState(c *cfg) { stateWord := nodeState(ni) - c.log.Info(logs.FrostFSNodeInitialNetworkState, + c.log.Info(context.Background(), logs.FrostFSNodeInitialNetworkState, zap.Uint64("epoch", epoch), zap.String("state", stateWord), ) @@ -307,7 +307,7 @@ func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error if nmState != candidateState { // This happens when the node was switched to maintenance without epoch tick. // We expect it to continue staying in maintenance. - c.log.Info(logs.CandidateStatusPriority, + c.log.Info(context.Background(), logs.CandidateStatusPriority, zap.String("netmap", nmState), zap.String("candidate", candidateState)) } diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index aeab1d6cb1..cad6d5ee36 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -58,7 +58,7 @@ type objectSvc struct { func (c *cfg) MaxObjectSize() uint64 { sz, err := c.cfgNetmap.wrapper.MaxObjectSize() if err != nil { - c.log.Error(logs.FrostFSNodeCouldNotGetMaxObjectSizeValue, + c.log.Error(context.Background(), logs.FrostFSNodeCouldNotGetMaxObjectSizeValue, zap.String("error", err.Error()), ) } @@ -223,7 +223,7 @@ func initObjectService(c *cfg) { func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.ClientCache) { if policerconfig.UnsafeDisable(c.appCfg) { - c.log.Warn(logs.FrostFSNodePolicerIsDisabled) + c.log.Warn(context.Background(), logs.FrostFSNodePolicerIsDisabled) return } @@ -287,7 +287,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl _, err := ls.Inhume(ctx, inhumePrm) if err != nil { - c.log.Warn(logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage, + c.log.Warn(ctx, logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage, zap.String("error", err.Error()), ) } diff --git a/cmd/frostfs-node/runtime.go b/cmd/frostfs-node/runtime.go index d858ba4901..0b1000e705 100644 --- a/cmd/frostfs-node/runtime.go +++ b/cmd/frostfs-node/runtime.go @@ -1,6 +1,7 @@ package main import ( + "context" "os" "runtime/debug" @@ -12,14 +13,14 @@ import ( func setRuntimeParameters(c *cfg) { if len(os.Getenv("GOMEMLIMIT")) != 0 { // default limit < yaml limit < app env limit < GOMEMLIMIT - c.log.Warn(logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT) + c.log.Warn(context.Background(), logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT) return } memLimitBytes := runtime.GCMemoryLimitBytes(c.appCfg) previous := debug.SetMemoryLimit(memLimitBytes) if memLimitBytes != previous { - c.log.Info(logs.RuntimeSoftMemoryLimitUpdated, + c.log.Info(context.Background(), logs.RuntimeSoftMemoryLimitUpdated, zap.Int64("new_value", memLimitBytes), zap.Int64("old_value", previous)) } diff --git a/cmd/frostfs-node/tracing.go b/cmd/frostfs-node/tracing.go index f550dd8826..65f5aec159 100644 --- a/cmd/frostfs-node/tracing.go +++ b/cmd/frostfs-node/tracing.go @@ -13,12 +13,12 @@ import ( func initTracing(ctx context.Context, c *cfg) { conf, err := tracingconfig.ToTracingConfig(c.appCfg) if err != nil { - c.log.Error(logs.FrostFSNodeFailedInitTracing, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeFailedInitTracing, zap.Error(err)) return } _, err = tracing.Setup(ctx, *conf) if err != nil { - c.log.Error(logs.FrostFSNodeFailedInitTracing, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeFailedInitTracing, zap.Error(err)) return } @@ -29,7 +29,7 @@ func initTracing(ctx context.Context, c *cfg) { defer cancel() err := tracing.Shutdown(ctx) // cfg context cancels before close if err != nil { - c.log.Error(logs.FrostFSNodeFailedShutdownTracing, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeFailedShutdownTracing, zap.Error(err)) } }, }) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index a92979daf3..59923ee2f9 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -44,7 +44,7 @@ func (c cnrSource) List() ([]cid.ID, error) { func initTreeService(c *cfg) { treeConfig := treeconfig.Tree(c.appCfg) if !treeConfig.Enabled() { - c.log.Info(logs.FrostFSNodeTreeServiceIsNotEnabledSkipInitialization) + c.log.Info(context.Background(), logs.FrostFSNodeTreeServiceIsNotEnabledSkipInitialization) return } @@ -83,7 +83,7 @@ func initTreeService(c *cfg) { addNewEpochNotificationHandler(c, func(_ event.Event) { err := c.treeService.SynchronizeAll() if err != nil { - c.log.Error(logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) + c.log.Error(context.Background(), logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) } }) } else { @@ -94,7 +94,7 @@ func initTreeService(c *cfg) { for range tick.C { err := c.treeService.SynchronizeAll() if err != nil { - c.log.Error(logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) + c.log.Error(context.Background(), logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) if errors.Is(err, tree.ErrShuttingDown) { return } @@ -107,11 +107,11 @@ func initTreeService(c *cfg) { ev := e.(containerEvent.DeleteSuccess) // This is executed asynchronously, so we don't care about the operation taking some time. - c.log.Debug(logs.FrostFSNodeRemovingAllTreesForContainer, zap.Stringer("cid", ev.ID)) + c.log.Debug(context.Background(), logs.FrostFSNodeRemovingAllTreesForContainer, zap.Stringer("cid", ev.ID)) err := c.treeService.DropTree(context.Background(), ev.ID, "") if err != nil && !errors.Is(err, pilorama.ErrTreeNotFound) { // Ignore pilorama.ErrTreeNotFound but other errors, including shard.ErrReadOnly, should be logged. - c.log.Error(logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved, + c.log.Error(context.Background(), logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved, zap.Stringer("cid", ev.ID), zap.String("error", err.Error())) } diff --git a/internal/audit/request.go b/internal/audit/request.go index 3355087f1a..15a4a79603 100644 --- a/internal/audit/request.go +++ b/internal/audit/request.go @@ -1,6 +1,8 @@ package audit import ( + "context" + crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" @@ -37,7 +39,7 @@ func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target object = target.String() } - log.Info(logs.AuditEventLogRecord, + log.Info(context.Background(), logs.AuditEventLogRecord, zap.String("operation", operation), zap.String("object", object), zap.String("subject", subject), diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index b428b56da7..20560cf3a4 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -65,7 +65,7 @@ func TestFormatValidator_Validate(t *testing.T) { epoch: curEpoch, }), WithLockSource(ls), - WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), + WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), ) ownerKey, err := keys.NewPrivateKey() @@ -290,7 +290,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { }), WithLockSource(ls), WithVerifySessionTokenIssuer(false), - WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), + WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), ) tok := sessiontest.Object() @@ -339,7 +339,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { }, }, ), - WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), + WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), ) tok := sessiontest.Object() @@ -417,7 +417,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { currentEpoch: curEpoch, }, ), - WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), + WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), ) require.NoError(t, v.Validate(context.Background(), obj, false)) @@ -491,7 +491,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { currentEpoch: curEpoch, }, ), - WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), + WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), ) require.NoError(t, v.Validate(context.Background(), obj, false)) @@ -567,7 +567,7 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { currentEpoch: curEpoch, }, ), - WithLogger(&logger.Logger{Logger: zaptest.NewLogger(t)}), + WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), ) require.Error(t, v.Validate(context.Background(), obj, false)) diff --git a/pkg/core/object/sender_classifier.go b/pkg/core/object/sender_classifier.go index 13d0ebfb1c..ed438c0b95 100644 --- a/pkg/core/object/sender_classifier.go +++ b/pkg/core/object/sender_classifier.go @@ -2,6 +2,7 @@ package object import ( "bytes" + "context" "crypto/sha256" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -64,7 +65,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ownerKeyInBytes []byte, idC isInnerRingNode, err := c.isInnerRingKey(ownerKeyInBytes) if err != nil { // do not throw error, try best case matching - c.log.Debug(logs.V2CantCheckIfRequestFromInnerRing, + c.log.Debug(context.Background(), logs.V2CantCheckIfRequestFromInnerRing, zap.String("error", err.Error())) } else if isInnerRingNode { return &ClassifyResult{ @@ -81,7 +82,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ownerKeyInBytes []byte, idC // error might happen if request has `RoleOther` key and placement // is not possible for previous epoch, so // do not throw error, try best case matching - c.log.Debug(logs.V2CantCheckIfRequestFromContainerNode, + c.log.Debug(context.Background(), logs.V2CantCheckIfRequestFromContainerNode, zap.String("error", err.Error())) } else if isContainerNode { return &ClassifyResult{ diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index d6b474c32a..b8812819e2 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -97,7 +97,7 @@ func (s *Server) initMainnet(ctx context.Context, cfg *viper.Viper, morphChain * fromMainChainBlock, err := s.persistate.UInt32(persistateMainChainLastBlockKey) if err != nil { fromMainChainBlock = 0 - s.log.Warn(logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.String("error", err.Error())) + s.log.Warn(ctx, logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.String("error", err.Error())) } mainnetChain.from = fromMainChainBlock @@ -142,7 +142,7 @@ func (s *Server) initNotaryConfig() { !s.withoutMainNet && s.mainnetClient.ProbeNotary(), // if mainnet disabled then notary flag must be disabled too ) - s.log.Info(logs.InnerringNotarySupport, + s.log.Info(context.Background(), logs.InnerringNotarySupport, zap.Bool("sidechain_enabled", true), zap.Bool("mainchain_enabled", !s.mainNotaryConfig.disabled), ) @@ -153,7 +153,7 @@ func (s *Server) createAlphaSync(cfg *viper.Viper, frostfsCli *frostfsClient.Cli if s.withoutMainNet || cfg.GetBool("governance.disable") { alphaSync = func(event.Event) { - s.log.Debug(logs.InnerringAlphabetKeysSyncIsDisabled) + s.log.Debug(context.Background(), logs.InnerringAlphabetKeysSyncIsDisabled) } } else { // create governance processor @@ -307,7 +307,7 @@ func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error { func (s *Server) initGRPCServer(cfg *viper.Viper, log *logger.Logger, audit *atomic.Bool) error { controlSvcEndpoint := cfg.GetString("control.grpc.endpoint") if controlSvcEndpoint == "" { - s.log.Info(logs.InnerringNoControlServerEndpointSpecified) + s.log.Info(context.Background(), logs.InnerringNoControlServerEndpointSpecified) return nil } @@ -446,7 +446,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<- fromSideChainBlock, err := s.persistate.UInt32(persistateSideChainLastBlockKey) if err != nil { fromSideChainBlock = 0 - s.log.Warn(logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) + s.log.Warn(ctx, logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) } morphChain := &chainParams{ @@ -471,7 +471,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<- return nil, err } if err := s.morphClient.SetGroupSignerScope(); err != nil { - morphChain.log.Info(logs.InnerringFailedToSetGroupSignerScope, zap.Error(err)) + morphChain.log.Info(ctx, logs.InnerringFailedToSetGroupSignerScope, zap.Error(err)) } return morphChain, nil diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 5fae302c41..63a4cb1cb9 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -176,7 +176,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { err = s.voteForSidechainValidator(prm) if err != nil { // we don't stop inner ring execution on this error - s.log.Warn(logs.InnerringCantVoteForPreparedValidators, + s.log.Warn(ctx, logs.InnerringCantVoteForPreparedValidators, zap.String("error", err.Error())) } @@ -218,13 +218,13 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { func (s *Server) registerMorphNewBlockEventHandler() { s.morphListener.RegisterBlockHandler(func(b *block.Block) { - s.log.Debug(logs.InnerringNewBlock, + s.log.Debug(context.Background(), logs.InnerringNewBlock, zap.Uint32("index", b.Index), ) err := s.persistate.SetUInt32(persistateSideChainLastBlockKey, b.Index) if err != nil { - s.log.Warn(logs.InnerringCantUpdatePersistentState, + s.log.Warn(context.Background(), logs.InnerringCantUpdatePersistentState, zap.String("chain", "side"), zap.Uint32("block_index", b.Index)) } @@ -238,7 +238,7 @@ func (s *Server) registerMainnetNewBlockEventHandler() { s.mainnetListener.RegisterBlockHandler(func(b *block.Block) { err := s.persistate.SetUInt32(persistateMainChainLastBlockKey, b.Index) if err != nil { - s.log.Warn(logs.InnerringCantUpdatePersistentState, + s.log.Warn(context.Background(), logs.InnerringCantUpdatePersistentState, zap.String("chain", "main"), zap.Uint32("block_index", b.Index)) } @@ -307,7 +307,7 @@ func (s *Server) Stop() { for _, c := range s.closers { if err := c(); err != nil { - s.log.Warn(logs.InnerringCloserError, + s.log.Warn(context.Background(), logs.InnerringCloserError, zap.String("error", err.Error()), ) } @@ -438,7 +438,7 @@ func createListener(ctx context.Context, cli *client.Client, p *chainParams) (ev } listener, err := event.NewListener(event.ListenerParams{ - Logger: &logger.Logger{Logger: p.log.With(zap.String("chain", p.name))}, + Logger: p.log.With(zap.String("chain", p.name)), Subscriber: sub, }) if err != nil { @@ -602,7 +602,7 @@ func (s *Server) initConfigFromBlockchain() error { return err } - s.log.Debug(logs.InnerringReadConfigFromBlockchain, + s.log.Debug(context.Background(), logs.InnerringReadConfigFromBlockchain, zap.Bool("active", s.IsActive()), zap.Bool("alphabet", s.IsAlphabet()), zap.Uint64("epoch", epoch), diff --git a/pkg/innerring/notary.go b/pkg/innerring/notary.go index 5cdbb971c6..902a4c30ae 100644 --- a/pkg/innerring/notary.go +++ b/pkg/innerring/notary.go @@ -54,12 +54,12 @@ func (s *Server) notaryHandler(_ event.Event) { if !s.mainNotaryConfig.disabled { _, err := s.depositMainNotary() if err != nil { - s.log.Error(logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err)) + s.log.Error(context.Background(), logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err)) } } if _, err := s.depositSideNotary(); err != nil { - s.log.Error(logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err)) + s.log.Error(context.Background(), logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err)) } } @@ -81,11 +81,11 @@ func (s *Server) initNotary(ctx context.Context, deposit depositor, await awaite // non-error deposit with an empty TX hash means // that the deposit has already been made; no // need to wait it. - s.log.Info(logs.InnerringNotaryDepositHasAlreadyBeenMade) + s.log.Info(ctx, logs.InnerringNotaryDepositHasAlreadyBeenMade) return nil } - s.log.Info(msg) + s.log.Info(ctx, msg) return await(ctx, tx) } diff --git a/pkg/innerring/processors/alphabet/handlers.go b/pkg/innerring/processors/alphabet/handlers.go index 9de075f17e..0cc2a5f395 100644 --- a/pkg/innerring/processors/alphabet/handlers.go +++ b/pkg/innerring/processors/alphabet/handlers.go @@ -1,6 +1,8 @@ package alphabet import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" @@ -10,14 +12,14 @@ import ( func (ap *Processor) HandleGasEmission(ev event.Event) { _ = ev.(timers.NewAlphabetEmitTick) - ap.log.Info(logs.AlphabetTick, zap.String("type", "alphabet gas emit")) + ap.log.Info(context.Background(), logs.AlphabetTick, zap.String("type", "alphabet gas emit")) // send event to the worker pool err := processors.SubmitEvent(ap.pool, ap.metrics, "alphabet_emit_gas", ap.processEmit) if err != nil { // there system can be moved into controlled degradation stage - ap.log.Warn(logs.AlphabetAlphabetProcessorWorkerPoolDrained, + ap.log.Warn(context.Background(), logs.AlphabetAlphabetProcessorWorkerPoolDrained, zap.Int("capacity", ap.pool.Cap())) } } diff --git a/pkg/innerring/processors/alphabet/process_emit.go b/pkg/innerring/processors/alphabet/process_emit.go index 2317f3e98d..142409631d 100644 --- a/pkg/innerring/processors/alphabet/process_emit.go +++ b/pkg/innerring/processors/alphabet/process_emit.go @@ -1,6 +1,7 @@ package alphabet import ( + "context" "crypto/elliptic" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -16,14 +17,14 @@ const emitMethod = "emit" func (ap *Processor) processEmit() bool { index := ap.irList.AlphabetIndex() if index < 0 { - ap.log.Info(logs.AlphabetNonAlphabetModeIgnoreGasEmissionEvent) + ap.log.Info(context.Background(), logs.AlphabetNonAlphabetModeIgnoreGasEmissionEvent) return true } contract, ok := ap.alphabetContracts.GetByIndex(index) if !ok { - ap.log.Debug(logs.AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent, + ap.log.Debug(context.Background(), logs.AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent, zap.Int("index", index)) return false @@ -32,20 +33,20 @@ func (ap *Processor) processEmit() bool { // there is no signature collecting, so we don't need extra fee _, err := ap.morphClient.Invoke(contract, 0, emitMethod) if err != nil { - ap.log.Warn(logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) + ap.log.Warn(context.Background(), logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) return false } if ap.storageEmission == 0 { - ap.log.Info(logs.AlphabetStorageNodeEmissionIsOff) + ap.log.Info(context.Background(), logs.AlphabetStorageNodeEmissionIsOff) return true } networkMap, err := ap.netmapClient.NetMap() if err != nil { - ap.log.Warn(logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, + ap.log.Warn(context.Background(), logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, zap.String("error", err.Error())) return false @@ -58,7 +59,7 @@ func (ap *Processor) processEmit() bool { ap.pwLock.RUnlock() extraLen := len(pw) - ap.log.Debug(logs.AlphabetGasEmission, + ap.log.Debug(context.Background(), logs.AlphabetGasEmission, zap.Int("network_map", nmLen), zap.Int("extra_wallets", extraLen)) @@ -81,7 +82,7 @@ func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerN key, err := keys.NewPublicKeyFromBytes(keyBytes, elliptic.P256()) if err != nil { - ap.log.Warn(logs.AlphabetCantParseNodePublicKey, + ap.log.Warn(context.Background(), logs.AlphabetCantParseNodePublicKey, zap.String("error", err.Error())) continue @@ -89,7 +90,7 @@ func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerN err = ap.morphClient.TransferGas(key.GetScriptHash(), gasPerNode) if err != nil { - ap.log.Warn(logs.AlphabetCantTransferGas, + ap.log.Warn(context.Background(), logs.AlphabetCantTransferGas, zap.String("receiver", key.Address()), zap.Int64("amount", int64(gasPerNode)), zap.String("error", err.Error()), @@ -106,7 +107,7 @@ func (ap *Processor) transferGasToExtraNodes(pw []util.Uint160, gasPerNode fixed for i, addr := range pw { receiversLog[i] = addr.StringLE() } - ap.log.Warn(logs.AlphabetCantTransferGasToWallet, + ap.log.Warn(context.Background(), logs.AlphabetCantTransferGasToWallet, zap.Strings("receivers", receiversLog), zap.Int64("amount", int64(gasPerNode)), zap.String("error", err.Error()), diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index ce66799693..8dbef1e209 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -1,6 +1,7 @@ package alphabet import ( + "context" "errors" "fmt" "sync" @@ -85,7 +86,7 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/alphabet: global state is not set") } - p.Log.Debug(logs.AlphabetAlphabetWorkerPool, zap.Int("size", p.PoolSize)) + p.Log.Debug(context.Background(), logs.AlphabetAlphabetWorkerPool, zap.Int("size", p.PoolSize)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { diff --git a/pkg/innerring/processors/balance/handlers.go b/pkg/innerring/processors/balance/handlers.go index e39f3abbd0..3792fc2af1 100644 --- a/pkg/innerring/processors/balance/handlers.go +++ b/pkg/innerring/processors/balance/handlers.go @@ -1,6 +1,7 @@ package balance import ( + "context" "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -12,7 +13,7 @@ import ( func (bp *Processor) handleLock(ev event.Event) { lock := ev.(balanceEvent.Lock) - bp.log.Info(logs.Notification, + bp.log.Info(context.Background(), logs.Notification, zap.String("type", "lock"), zap.String("value", hex.EncodeToString(lock.ID()))) @@ -23,7 +24,7 @@ func (bp *Processor) handleLock(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - bp.log.Warn(logs.BalanceBalanceWorkerPoolDrained, + bp.log.Warn(context.Background(), logs.BalanceBalanceWorkerPoolDrained, zap.Int("capacity", bp.pool.Cap())) } } diff --git a/pkg/innerring/processors/balance/process_assets.go b/pkg/innerring/processors/balance/process_assets.go index 1d94fa454e..ac6a1e4933 100644 --- a/pkg/innerring/processors/balance/process_assets.go +++ b/pkg/innerring/processors/balance/process_assets.go @@ -1,6 +1,8 @@ package balance import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" frostfsContract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs" balanceEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/balance" @@ -11,7 +13,7 @@ import ( // back to the withdraw issuer. func (bp *Processor) processLock(lock *balanceEvent.Lock) bool { if !bp.alphabetState.IsAlphabet() { - bp.log.Info(logs.BalanceNonAlphabetModeIgnoreBalanceLock) + bp.log.Info(context.Background(), logs.BalanceNonAlphabetModeIgnoreBalanceLock) return true } @@ -25,7 +27,7 @@ func (bp *Processor) processLock(lock *balanceEvent.Lock) bool { err := bp.frostfsClient.Cheque(prm) if err != nil { - bp.log.Error(logs.BalanceCantSendLockAssetTx, zap.Error(err)) + bp.log.Error(context.Background(), logs.BalanceCantSendLockAssetTx, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/balance/processor.go b/pkg/innerring/processors/balance/processor.go index 5cc849b5c3..c4078461e6 100644 --- a/pkg/innerring/processors/balance/processor.go +++ b/pkg/innerring/processors/balance/processor.go @@ -1,6 +1,7 @@ package balance import ( + "context" "errors" "fmt" @@ -68,7 +69,7 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/balance: balance precision converter is not set") } - p.Log.Debug(logs.BalanceBalanceWorkerPool, zap.Int("size", p.PoolSize)) + p.Log.Debug(context.Background(), logs.BalanceBalanceWorkerPool, zap.Int("size", p.PoolSize)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { diff --git a/pkg/innerring/processors/container/handlers.go b/pkg/innerring/processors/container/handlers.go index a54f3c7724..b3d50d9d02 100644 --- a/pkg/innerring/processors/container/handlers.go +++ b/pkg/innerring/processors/container/handlers.go @@ -1,6 +1,7 @@ package container import ( + "context" "crypto/sha256" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -15,7 +16,7 @@ func (cp *Processor) handlePut(ev event.Event) { put := ev.(putEvent) id := sha256.Sum256(put.Container()) - cp.log.Info(logs.Notification, + cp.log.Info(context.Background(), logs.Notification, zap.String("type", "container put"), zap.String("id", base58.Encode(id[:]))) @@ -26,14 +27,14 @@ func (cp *Processor) handlePut(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - cp.log.Warn(logs.ContainerContainerProcessorWorkerPoolDrained, + cp.log.Warn(context.Background(), logs.ContainerContainerProcessorWorkerPoolDrained, zap.Int("capacity", cp.pool.Cap())) } } func (cp *Processor) handleDelete(ev event.Event) { del := ev.(containerEvent.Delete) - cp.log.Info(logs.Notification, + cp.log.Info(context.Background(), logs.Notification, zap.String("type", "container delete"), zap.String("id", base58.Encode(del.ContainerID()))) @@ -44,7 +45,7 @@ func (cp *Processor) handleDelete(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - cp.log.Warn(logs.ContainerContainerProcessorWorkerPoolDrained, + cp.log.Warn(context.Background(), logs.ContainerContainerProcessorWorkerPoolDrained, zap.Int("capacity", cp.pool.Cap())) } } diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index d89b63e82f..2b9c5995c1 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -1,6 +1,7 @@ package container import ( + "context" "errors" "fmt" "strings" @@ -38,7 +39,7 @@ var errContainerAndOwnerNamespaceDontMatch = errors.New("container and owner nam // and sending approve tx back to the morph. func (cp *Processor) processContainerPut(put putEvent) bool { if !cp.alphabetState.IsAlphabet() { - cp.log.Info(logs.ContainerNonAlphabetModeIgnoreContainerPut) + cp.log.Info(context.Background(), logs.ContainerNonAlphabetModeIgnoreContainerPut) return true } @@ -48,7 +49,7 @@ func (cp *Processor) processContainerPut(put putEvent) bool { err := cp.checkPutContainer(ctx) if err != nil { - cp.log.Error(logs.ContainerPutContainerCheckFailed, + cp.log.Error(context.Background(), logs.ContainerPutContainerCheckFailed, zap.String("error", err.Error()), ) @@ -56,7 +57,7 @@ func (cp *Processor) processContainerPut(put putEvent) bool { } if err := cp.morphClient.NotarySignAndInvokeTX(ctx.e.NotaryRequest().MainTransaction); err != nil { - cp.log.Error(logs.ContainerCouldNotApprovePutContainer, + cp.log.Error(context.Background(), logs.ContainerCouldNotApprovePutContainer, zap.String("error", err.Error()), ) return false @@ -105,13 +106,13 @@ func (cp *Processor) checkPutContainer(ctx *putContainerContext) error { // and sending approve tx back to morph. func (cp *Processor) processContainerDelete(e containerEvent.Delete) bool { if !cp.alphabetState.IsAlphabet() { - cp.log.Info(logs.ContainerNonAlphabetModeIgnoreContainerDelete) + cp.log.Info(context.Background(), logs.ContainerNonAlphabetModeIgnoreContainerDelete) return true } err := cp.checkDeleteContainer(e) if err != nil { - cp.log.Error(logs.ContainerDeleteContainerCheckFailed, + cp.log.Error(context.Background(), logs.ContainerDeleteContainerCheckFailed, zap.String("error", err.Error()), ) @@ -119,7 +120,7 @@ func (cp *Processor) processContainerDelete(e containerEvent.Delete) bool { } if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil { - cp.log.Error(logs.ContainerCouldNotApproveDeleteContainer, + cp.log.Error(context.Background(), logs.ContainerCouldNotApproveDeleteContainer, zap.String("error", err.Error()), ) diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index a6fbdc707d..7a50ca7733 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -1,6 +1,7 @@ package container import ( + "context" "errors" "fmt" @@ -97,7 +98,7 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/container: FrostFSID client is not set") } - p.Log.Debug(logs.ContainerContainerWorkerPool, zap.Int("size", p.PoolSize)) + p.Log.Debug(context.Background(), logs.ContainerContainerWorkerPool, zap.Int("size", p.PoolSize)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { diff --git a/pkg/innerring/processors/frostfs/handlers.go b/pkg/innerring/processors/frostfs/handlers.go index c80f9fdc51..02dfbaf609 100644 --- a/pkg/innerring/processors/frostfs/handlers.go +++ b/pkg/innerring/processors/frostfs/handlers.go @@ -2,6 +2,7 @@ package frostfs import ( "bytes" + "context" "encoding/hex" "slices" @@ -16,7 +17,7 @@ func (np *Processor) handleDeposit(ev event.Event) { deposit := ev.(frostfsEvent.Deposit) depositIDBin := bytes.Clone(deposit.ID()) slices.Reverse(depositIDBin) - np.log.Info(logs.Notification, + np.log.Info(context.Background(), logs.Notification, zap.String("type", "deposit"), zap.String("id", hex.EncodeToString(depositIDBin))) @@ -27,7 +28,7 @@ func (np *Processor) handleDeposit(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained, + np.log.Warn(context.Background(), logs.FrostFSFrostfsProcessorWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } @@ -36,7 +37,7 @@ func (np *Processor) handleWithdraw(ev event.Event) { withdraw := ev.(frostfsEvent.Withdraw) withdrawBin := bytes.Clone(withdraw.ID()) slices.Reverse(withdrawBin) - np.log.Info(logs.Notification, + np.log.Info(context.Background(), logs.Notification, zap.String("type", "withdraw"), zap.String("id", hex.EncodeToString(withdrawBin))) @@ -47,14 +48,14 @@ func (np *Processor) handleWithdraw(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained, + np.log.Warn(context.Background(), logs.FrostFSFrostfsProcessorWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } func (np *Processor) handleCheque(ev event.Event) { cheque := ev.(frostfsEvent.Cheque) - np.log.Info(logs.Notification, + np.log.Info(context.Background(), logs.Notification, zap.String("type", "cheque"), zap.String("id", hex.EncodeToString(cheque.ID()))) @@ -65,14 +66,14 @@ func (np *Processor) handleCheque(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained, + np.log.Warn(context.Background(), logs.FrostFSFrostfsProcessorWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } func (np *Processor) handleConfig(ev event.Event) { cfg := ev.(frostfsEvent.Config) - np.log.Info(logs.Notification, + np.log.Info(context.Background(), logs.Notification, zap.String("type", "set config"), zap.String("key", hex.EncodeToString(cfg.Key())), zap.String("value", hex.EncodeToString(cfg.Value()))) @@ -84,7 +85,7 @@ func (np *Processor) handleConfig(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.FrostFSFrostfsProcessorWorkerPoolDrained, + np.log.Warn(context.Background(), logs.FrostFSFrostfsProcessorWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } diff --git a/pkg/innerring/processors/frostfs/process_assets.go b/pkg/innerring/processors/frostfs/process_assets.go index c72aeceee9..3bee6ed96b 100644 --- a/pkg/innerring/processors/frostfs/process_assets.go +++ b/pkg/innerring/processors/frostfs/process_assets.go @@ -1,6 +1,8 @@ package frostfs import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" @@ -17,7 +19,7 @@ const ( // gas in the sidechain. func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.FrostFSNonAlphabetModeIgnoreDeposit) + np.log.Info(context.Background(), logs.FrostFSNonAlphabetModeIgnoreDeposit) return true } @@ -30,7 +32,7 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { // send transferX to a balance contract err := np.balanceClient.Mint(prm) if err != nil { - np.log.Error(logs.FrostFSCantTransferAssetsToBalanceContract, zap.Error(err)) + np.log.Error(context.Background(), logs.FrostFSCantTransferAssetsToBalanceContract, zap.Error(err)) } curEpoch := np.epochState.EpochCounter() @@ -44,7 +46,7 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { val, ok := np.mintEmitCache.Get(receiver.String()) if ok && val+np.mintEmitThreshold >= curEpoch { - np.log.Warn(logs.FrostFSDoubleMintEmissionDeclined, + np.log.Warn(context.Background(), logs.FrostFSDoubleMintEmissionDeclined, zap.Stringer("receiver", receiver), zap.Uint64("last_emission", val), zap.Uint64("current_epoch", curEpoch)) @@ -56,12 +58,12 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { // before gas transfer check if the balance is greater than the threshold balance, err := np.morphClient.GasBalance() if err != nil { - np.log.Error(logs.FrostFSCantGetGasBalanceOfTheNode, zap.Error(err)) + np.log.Error(context.Background(), logs.FrostFSCantGetGasBalanceOfTheNode, zap.Error(err)) return false } if balance < np.gasBalanceThreshold { - np.log.Warn(logs.FrostFSGasBalanceThresholdHasBeenReached, + np.log.Warn(context.Background(), logs.FrostFSGasBalanceThresholdHasBeenReached, zap.Int64("balance", balance), zap.Int64("threshold", np.gasBalanceThreshold)) @@ -70,7 +72,7 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { err = np.morphClient.TransferGas(receiver, np.mintEmitValue) if err != nil { - np.log.Error(logs.FrostFSCantTransferNativeGasToReceiver, + np.log.Error(context.Background(), logs.FrostFSCantTransferNativeGasToReceiver, zap.String("error", err.Error())) return false @@ -84,14 +86,14 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { // Process withdraw event by locking assets in the balance account. func (np *Processor) processWithdraw(withdraw frostfsEvent.Withdraw) bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.FrostFSNonAlphabetModeIgnoreWithdraw) + np.log.Info(context.Background(), logs.FrostFSNonAlphabetModeIgnoreWithdraw) return true } // create lock account lock, err := util.Uint160DecodeBytesBE(withdraw.ID()[:util.Uint160Size]) if err != nil { - np.log.Error(logs.FrostFSCantCreateLockAccount, zap.Error(err)) + np.log.Error(context.Background(), logs.FrostFSCantCreateLockAccount, zap.Error(err)) return false } @@ -107,7 +109,7 @@ func (np *Processor) processWithdraw(withdraw frostfsEvent.Withdraw) bool { err = np.balanceClient.Lock(prm) if err != nil { - np.log.Error(logs.FrostFSCantLockAssetsForWithdraw, zap.Error(err)) + np.log.Error(context.Background(), logs.FrostFSCantLockAssetsForWithdraw, zap.Error(err)) return false } @@ -118,7 +120,7 @@ func (np *Processor) processWithdraw(withdraw frostfsEvent.Withdraw) bool { // the reserve account. func (np *Processor) processCheque(cheque frostfsEvent.Cheque) bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.FrostFSNonAlphabetModeIgnoreCheque) + np.log.Info(context.Background(), logs.FrostFSNonAlphabetModeIgnoreCheque) return true } @@ -130,7 +132,7 @@ func (np *Processor) processCheque(cheque frostfsEvent.Cheque) bool { err := np.balanceClient.Burn(prm) if err != nil { - np.log.Error(logs.FrostFSCantTransferAssetsToFedContract, zap.Error(err)) + np.log.Error(context.Background(), logs.FrostFSCantTransferAssetsToFedContract, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/frostfs/process_config.go b/pkg/innerring/processors/frostfs/process_config.go index 2ae3e6cedd..814dd40b4f 100644 --- a/pkg/innerring/processors/frostfs/process_config.go +++ b/pkg/innerring/processors/frostfs/process_config.go @@ -1,6 +1,8 @@ package frostfs import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" frostfsEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/frostfs" @@ -11,7 +13,7 @@ import ( // the sidechain. func (np *Processor) processConfig(config frostfsEvent.Config) bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.FrostFSNonAlphabetModeIgnoreConfig) + np.log.Info(context.Background(), logs.FrostFSNonAlphabetModeIgnoreConfig) return true } @@ -24,7 +26,7 @@ func (np *Processor) processConfig(config frostfsEvent.Config) bool { err := np.netmapClient.SetConfig(prm) if err != nil { - np.log.Error(logs.FrostFSCantRelaySetConfigEvent, zap.Error(err)) + np.log.Error(context.Background(), logs.FrostFSCantRelaySetConfigEvent, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/frostfs/processor.go b/pkg/innerring/processors/frostfs/processor.go index 2019857ac6..fdc31d82e5 100644 --- a/pkg/innerring/processors/frostfs/processor.go +++ b/pkg/innerring/processors/frostfs/processor.go @@ -1,6 +1,7 @@ package frostfs import ( + "context" "errors" "fmt" "sync" @@ -110,7 +111,7 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/frostfs: balance precision converter is not set") } - p.Log.Debug(logs.FrostFSFrostfsWorkerPool, zap.Int("size", p.PoolSize)) + p.Log.Debug(context.Background(), logs.FrostFSFrostfsWorkerPool, zap.Int("size", p.PoolSize)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { diff --git a/pkg/innerring/processors/governance/handlers.go b/pkg/innerring/processors/governance/handlers.go index fd7f539c3b..dee8c13e2e 100644 --- a/pkg/innerring/processors/governance/handlers.go +++ b/pkg/innerring/processors/governance/handlers.go @@ -1,6 +1,8 @@ package governance import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" @@ -32,7 +34,7 @@ func (gp *Processor) HandleAlphabetSync(e event.Event) { return } - gp.log.Info(logs.GovernanceNewEvent, zap.String("type", typ)) + gp.log.Info(context.Background(), logs.GovernanceNewEvent, zap.String("type", typ)) // send event to the worker pool @@ -41,7 +43,7 @@ func (gp *Processor) HandleAlphabetSync(e event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - gp.log.Warn(logs.GovernanceGovernanceWorkerPoolDrained, + gp.log.Warn(context.Background(), logs.GovernanceGovernanceWorkerPoolDrained, zap.Int("capacity", gp.pool.Cap())) } } diff --git a/pkg/innerring/processors/governance/process_update.go b/pkg/innerring/processors/governance/process_update.go index 50ba58e77e..faca22f67b 100644 --- a/pkg/innerring/processors/governance/process_update.go +++ b/pkg/innerring/processors/governance/process_update.go @@ -1,6 +1,7 @@ package governance import ( + "context" "encoding/binary" "encoding/hex" "sort" @@ -20,37 +21,37 @@ const ( func (gp *Processor) processAlphabetSync(txHash util.Uint256) bool { if !gp.alphabetState.IsAlphabet() { - gp.log.Info(logs.GovernanceNonAlphabetModeIgnoreAlphabetSync) + gp.log.Info(context.Background(), logs.GovernanceNonAlphabetModeIgnoreAlphabetSync) return true } mainnetAlphabet, err := gp.mainnetClient.NeoFSAlphabetList() if err != nil { - gp.log.Error(logs.GovernanceCantFetchAlphabetListFromMainNet, + gp.log.Error(context.Background(), logs.GovernanceCantFetchAlphabetListFromMainNet, zap.String("error", err.Error())) return false } sidechainAlphabet, err := gp.morphClient.Committee() if err != nil { - gp.log.Error(logs.GovernanceCantFetchAlphabetListFromSideChain, + gp.log.Error(context.Background(), logs.GovernanceCantFetchAlphabetListFromSideChain, zap.String("error", err.Error())) return false } newAlphabet, err := newAlphabetList(sidechainAlphabet, mainnetAlphabet) if err != nil { - gp.log.Error(logs.GovernanceCantMergeAlphabetListsFromMainNetAndSideChain, + gp.log.Error(context.Background(), logs.GovernanceCantMergeAlphabetListsFromMainNetAndSideChain, zap.String("error", err.Error())) return false } if newAlphabet == nil { - gp.log.Info(logs.GovernanceNoGovernanceUpdateAlphabetListHasNotBeenChanged) + gp.log.Info(context.Background(), logs.GovernanceNoGovernanceUpdateAlphabetListHasNotBeenChanged) return true } - gp.log.Info(logs.GovernanceAlphabetListHasBeenChangedStartingUpdate, + gp.log.Info(context.Background(), logs.GovernanceAlphabetListHasBeenChangedStartingUpdate, zap.String("side_chain_alphabet", prettyKeys(sidechainAlphabet)), zap.String("new_alphabet", prettyKeys(newAlphabet)), ) @@ -63,7 +64,7 @@ func (gp *Processor) processAlphabetSync(txHash util.Uint256) bool { // 1. Vote to sidechain committee via alphabet contracts. err = gp.voter.VoteForSidechainValidator(votePrm) if err != nil { - gp.log.Error(logs.GovernanceCantVoteForSideChainCommittee, + gp.log.Error(context.Background(), logs.GovernanceCantVoteForSideChainCommittee, zap.String("error", err.Error())) } @@ -76,7 +77,7 @@ func (gp *Processor) processAlphabetSync(txHash util.Uint256) bool { // 4. Update FrostFS contract in the mainnet. gp.updateFrostFSContractInMainnet(newAlphabet) - gp.log.Info(logs.GovernanceFinishedAlphabetListUpdate) + gp.log.Info(context.Background(), logs.GovernanceFinishedAlphabetListUpdate) return true } @@ -96,21 +97,21 @@ func prettyKeys(keys keys.PublicKeys) string { func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(sidechainAlphabet, newAlphabet keys.PublicKeys, txHash util.Uint256) { innerRing, err := gp.irFetcher.InnerRingKeys() if err != nil { - gp.log.Error(logs.GovernanceCantFetchInnerRingListFromSideChain, + gp.log.Error(context.Background(), logs.GovernanceCantFetchInnerRingListFromSideChain, zap.String("error", err.Error())) return } newInnerRing, err := updateInnerRing(innerRing, sidechainAlphabet, newAlphabet) if err != nil { - gp.log.Error(logs.GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys, + gp.log.Error(context.Background(), logs.GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys, zap.String("error", err.Error())) return } sort.Sort(newInnerRing) - gp.log.Info(logs.GovernanceUpdateOfTheInnerRingList, + gp.log.Info(context.Background(), logs.GovernanceUpdateOfTheInnerRingList, zap.String("before", prettyKeys(innerRing)), zap.String("after", prettyKeys(newInnerRing)), ) @@ -120,7 +121,7 @@ func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(sidechainAlphabet, newAl updPrm.SetHash(txHash) if err = gp.morphClient.UpdateNeoFSAlphabetList(updPrm); err != nil { - gp.log.Error(logs.GovernanceCantUpdateInnerRingListWithNewAlphabetKeys, + gp.log.Error(context.Background(), logs.GovernanceCantUpdateInnerRingListWithNewAlphabetKeys, zap.String("error", err.Error())) } } @@ -133,7 +134,7 @@ func (gp *Processor) updateNotaryRoleInSidechain(newAlphabet keys.PublicKeys, tx err := gp.morphClient.UpdateNotaryList(updPrm) if err != nil { - gp.log.Error(logs.GovernanceCantUpdateListOfNotaryNodesInSideChain, + gp.log.Error(context.Background(), logs.GovernanceCantUpdateListOfNotaryNodesInSideChain, zap.String("error", err.Error())) } } @@ -153,7 +154,7 @@ func (gp *Processor) updateFrostFSContractInMainnet(newAlphabet keys.PublicKeys) err := gp.frostfsClient.AlphabetUpdate(prm) if err != nil { - gp.log.Error(logs.GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract, + gp.log.Error(context.Background(), logs.GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract, zap.String("error", err.Error())) } } diff --git a/pkg/innerring/processors/netmap/handlers.go b/pkg/innerring/processors/netmap/handlers.go index c6053e281e..478ab5eab1 100644 --- a/pkg/innerring/processors/netmap/handlers.go +++ b/pkg/innerring/processors/netmap/handlers.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -13,21 +14,21 @@ import ( func (np *Processor) HandleNewEpochTick(ev event.Event) { _ = ev.(timerEvent.NewEpochTick) - np.log.Info(logs.NetmapTick, zap.String("type", "epoch")) + np.log.Info(context.Background(), logs.NetmapTick, zap.String("type", "epoch")) // send an event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch_tick", np.processNewEpochTick) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } func (np *Processor) handleNewEpoch(ev event.Event) { epochEvent := ev.(netmapEvent.NewEpoch) - np.log.Info(logs.Notification, + np.log.Info(context.Background(), logs.Notification, zap.String("type", "new epoch"), zap.Uint64("value", epochEvent.EpochNumber())) @@ -38,7 +39,7 @@ func (np *Processor) handleNewEpoch(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } @@ -46,7 +47,7 @@ func (np *Processor) handleNewEpoch(ev event.Event) { func (np *Processor) handleAddPeer(ev event.Event) { newPeer := ev.(netmapEvent.AddPeer) - np.log.Info(logs.Notification, + np.log.Info(context.Background(), logs.Notification, zap.String("type", "add peer"), ) @@ -57,14 +58,14 @@ func (np *Processor) handleAddPeer(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } func (np *Processor) handleUpdateState(ev event.Event) { updPeer := ev.(netmapEvent.UpdatePeer) - np.log.Info(logs.Notification, + np.log.Info(context.Background(), logs.Notification, zap.String("type", "update peer state"), zap.String("key", hex.EncodeToString(updPeer.PublicKey().Bytes()))) @@ -75,21 +76,21 @@ func (np *Processor) handleUpdateState(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } func (np *Processor) handleCleanupTick(ev event.Event) { if !np.netmapSnapshot.enabled { - np.log.Debug(logs.NetmapNetmapCleanUpRoutineIsDisabled518) + np.log.Debug(context.Background(), logs.NetmapNetmapCleanUpRoutineIsDisabled518) return } cleanup := ev.(netmapCleanupTick) - np.log.Info(logs.NetmapTick, zap.String("type", "netmap cleaner")) + np.log.Info(context.Background(), logs.NetmapTick, zap.String("type", "netmap cleaner")) // send event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "netmap_cleanup_tick", func() bool { @@ -97,7 +98,7 @@ func (np *Processor) handleCleanupTick(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } diff --git a/pkg/innerring/processors/netmap/process_cleanup.go b/pkg/innerring/processors/netmap/process_cleanup.go index 269e79c5e4..9529d3a0ce 100644 --- a/pkg/innerring/processors/netmap/process_cleanup.go +++ b/pkg/innerring/processors/netmap/process_cleanup.go @@ -1,6 +1,8 @@ package netmap import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" v2netmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -9,7 +11,7 @@ import ( func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.NetmapNonAlphabetModeIgnoreNewNetmapCleanupTick) + np.log.Info(context.Background(), logs.NetmapNonAlphabetModeIgnoreNewNetmapCleanupTick) return true } @@ -17,13 +19,13 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) bool { err := np.netmapSnapshot.forEachRemoveCandidate(ev.epoch, func(s string) error { key, err := keys.NewPublicKeyFromString(s) if err != nil { - np.log.Warn(logs.NetmapCantDecodePublicKeyOfNetmapNode, + np.log.Warn(context.Background(), logs.NetmapCantDecodePublicKeyOfNetmapNode, zap.String("key", s)) return nil } - np.log.Info(logs.NetmapVoteToRemoveNodeFromNetmap, zap.String("key", s)) + np.log.Info(context.Background(), logs.NetmapVoteToRemoveNodeFromNetmap, zap.String("key", s)) // In notary environments we call UpdateStateIR method instead of UpdateState. // It differs from UpdateState only by name, so we can do this in the same form. @@ -39,13 +41,13 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) bool { int64(v2netmap.Offline), key.Bytes(), ) if err != nil { - np.log.Error(logs.NetmapCantInvokeNetmapUpdateState, zap.Error(err)) + np.log.Error(context.Background(), logs.NetmapCantInvokeNetmapUpdateState, zap.Error(err)) } return nil }) if err != nil { - np.log.Warn(logs.NetmapCantIterateOnNetmapCleanerCache, + np.log.Warn(context.Background(), logs.NetmapCantIterateOnNetmapCleanerCache, zap.String("error", err.Error())) return false } diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index 9522df26c5..8ad295a741 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -1,6 +1,8 @@ package netmap import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/governance" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" @@ -14,7 +16,7 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool { epochDuration, err := np.netmapClient.EpochDuration() if err != nil { - np.log.Warn(logs.NetmapCantGetEpochDuration, + np.log.Warn(context.Background(), logs.NetmapCantGetEpochDuration, zap.String("error", err.Error())) } else { np.epochState.SetEpochDuration(epochDuration) @@ -24,20 +26,20 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool { h, err := np.netmapClient.MorphTxHeight(ev.TxHash()) if err != nil { - np.log.Warn(logs.NetmapCantGetTransactionHeight, + np.log.Warn(context.Background(), logs.NetmapCantGetTransactionHeight, zap.String("hash", ev.TxHash().StringLE()), zap.String("error", err.Error())) } if err := np.epochTimer.ResetEpochTimer(h); err != nil { - np.log.Warn(logs.NetmapCantResetEpochTimer, + np.log.Warn(context.Background(), logs.NetmapCantResetEpochTimer, zap.String("error", err.Error())) } // get new netmap snapshot networkMap, err := np.netmapClient.NetMap() if err != nil { - np.log.Warn(logs.NetmapCantGetNetmapSnapshotToPerformCleanup, + np.log.Warn(context.Background(), logs.NetmapCantGetNetmapSnapshotToPerformCleanup, zap.String("error", err.Error())) return false @@ -54,16 +56,16 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool { // Process new epoch tick by invoking new epoch method in network map contract. func (np *Processor) processNewEpochTick() bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.NetmapNonAlphabetModeIgnoreNewEpochTick) + np.log.Info(context.Background(), logs.NetmapNonAlphabetModeIgnoreNewEpochTick) return true } nextEpoch := np.epochState.EpochCounter() + 1 - np.log.Debug(logs.NetmapNextEpoch, zap.Uint64("value", nextEpoch)) + np.log.Debug(context.Background(), logs.NetmapNextEpoch, zap.Uint64("value", nextEpoch)) err := np.netmapClient.NewEpoch(nextEpoch) if err != nil { - np.log.Error(logs.NetmapCantInvokeNetmapNewEpoch, zap.Error(err)) + np.log.Error(context.Background(), logs.NetmapCantInvokeNetmapNewEpoch, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index c8c7928a34..42d1b5ec6f 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -14,7 +15,7 @@ import ( // local epoch timer. func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.NetmapNonAlphabetModeIgnoreNewPeerNotification) + np.log.Info(context.Background(), logs.NetmapNonAlphabetModeIgnoreNewPeerNotification) return true } @@ -22,7 +23,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { tx := ev.NotaryRequest().MainTransaction ok, err := np.netmapClient.MorphIsValidScript(tx.Script, tx.Signers) if err != nil || !ok { - np.log.Warn(logs.NetmapNonhaltNotaryTransaction, + np.log.Warn(context.Background(), logs.NetmapNonhaltNotaryTransaction, zap.String("method", "netmap.AddPeer"), zap.String("hash", tx.Hash().StringLE()), zap.Error(err)) @@ -33,14 +34,14 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { var nodeInfo netmap.NodeInfo if err := nodeInfo.Unmarshal(ev.Node()); err != nil { // it will be nice to have tx id at event structure to log it - np.log.Warn(logs.NetmapCantParseNetworkMapCandidate) + np.log.Warn(context.Background(), logs.NetmapCantParseNetworkMapCandidate) return false } // validate and update node info err = np.nodeValidator.VerifyAndUpdate(&nodeInfo) if err != nil { - np.log.Warn(logs.NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate, + np.log.Warn(context.Background(), logs.NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate, zap.String("error", err.Error()), ) @@ -63,7 +64,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { // That is why we need to perform `addPeerIR` only in case when node is online, // because in scope of this method, contract set state `ONLINE` for the node. if updated && nodeInfo.Status().IsOnline() { - np.log.Info(logs.NetmapApprovingNetworkMapCandidate, + np.log.Info(context.Background(), logs.NetmapApprovingNetworkMapCandidate, zap.String("key", keyString)) prm := netmapclient.AddPeerPrm{} @@ -84,7 +85,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { nodeInfoBinary, ) if err != nil { - np.log.Error(logs.NetmapCantInvokeNetmapAddPeer, zap.Error(err)) + np.log.Error(context.Background(), logs.NetmapCantInvokeNetmapAddPeer, zap.Error(err)) return false } } @@ -95,7 +96,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { // Process update peer notification by sending approval tx to the smart contract. func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(logs.NetmapNonAlphabetModeIgnoreUpdatePeerNotification) + np.log.Info(context.Background(), logs.NetmapNonAlphabetModeIgnoreUpdatePeerNotification) return true } @@ -108,7 +109,7 @@ func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) bool { if ev.Maintenance() { err = np.nodeStateSettings.MaintenanceModeAllowed() if err != nil { - np.log.Info(logs.NetmapPreventSwitchingNodeToMaintenanceState, + np.log.Info(context.Background(), logs.NetmapPreventSwitchingNodeToMaintenanceState, zap.Error(err), ) @@ -117,7 +118,7 @@ func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) bool { } if err = np.netmapClient.MorphNotarySignAndInvokeTX(ev.NotaryRequest().MainTransaction); err != nil { - np.log.Error(logs.NetmapCantInvokeNetmapUpdatePeer, zap.Error(err)) + np.log.Error(context.Background(), logs.NetmapCantInvokeNetmapUpdatePeer, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index f5a91dee2f..bbd60c1e19 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "errors" "fmt" @@ -132,7 +133,7 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/netmap: node state settings is not set") } - p.Log.Debug(logs.NetmapNetmapWorkerPool, zap.Int("size", p.PoolSize)) + p.Log.Debug(context.Background(), logs.NetmapNetmapWorkerPool, zap.Int("size", p.PoolSize)) pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index d3071faadc..250f41e5f3 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -1,6 +1,7 @@ package innerring import ( + "context" "fmt" "sort" @@ -61,7 +62,7 @@ func (s *Server) IsAlphabet() bool { func (s *Server) InnerRingIndex() int { index, err := s.statusIndex.InnerRingIndex() if err != nil { - s.log.Error(logs.InnerringCantGetInnerRingIndex, zap.String("error", err.Error())) + s.log.Error(context.Background(), logs.InnerringCantGetInnerRingIndex, zap.String("error", err.Error())) return -1 } @@ -73,7 +74,7 @@ func (s *Server) InnerRingIndex() int { func (s *Server) InnerRingSize() int { size, err := s.statusIndex.InnerRingSize() if err != nil { - s.log.Error(logs.InnerringCantGetInnerRingSize, zap.String("error", err.Error())) + s.log.Error(context.Background(), logs.InnerringCantGetInnerRingSize, zap.String("error", err.Error())) return 0 } @@ -85,7 +86,7 @@ func (s *Server) InnerRingSize() int { func (s *Server) AlphabetIndex() int { index, err := s.statusIndex.AlphabetIndex() if err != nil { - s.log.Error(logs.InnerringCantGetAlphabetIndex, zap.String("error", err.Error())) + s.log.Error(context.Background(), logs.InnerringCantGetAlphabetIndex, zap.String("error", err.Error())) return -1 } @@ -97,13 +98,13 @@ func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) erro index := s.InnerRingIndex() if s.contracts.alphabet.indexOutOfRange(index) { - s.log.Info(logs.InnerringIgnoreValidatorVoteNodeNotInAlphabetRange) + s.log.Info(context.Background(), logs.InnerringIgnoreValidatorVoteNodeNotInAlphabetRange) return nil } if len(validators) == 0 { - s.log.Info(logs.InnerringIgnoreValidatorVoteEmptyValidatorsList) + s.log.Info(context.Background(), logs.InnerringIgnoreValidatorVoteEmptyValidatorsList) return nil } @@ -128,7 +129,7 @@ func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) erro s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) { _, err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators) if err != nil { - s.log.Warn(logs.InnerringCantInvokeVoteMethodInAlphabetContract, + s.log.Warn(context.Background(), logs.InnerringCantInvokeVoteMethodInAlphabetContract, zap.Int8("alphabet_index", int8(letter)), zap.Uint64("epoch", epoch), zap.String("error", err.Error())) @@ -202,6 +203,6 @@ func (s *Server) notifySystemd(st control.HealthStatus) { err = sdnotify.Status(fmt.Sprintf("%v", st)) } if err != nil { - s.log.Error(logs.FailedToReportStatusToSystemd, zap.Error(err)) + s.log.Error(context.Background(), logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza.go b/pkg/local_object_storage/blobovnicza/blobovnicza.go index c787f9d5e8..08ef8b86cd 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza.go @@ -58,7 +58,7 @@ func defaultCfg(c *cfg) { }, fullSizeLimit: 1 << 30, // 1GB objSizeLimit: 1 << 20, // 1MB - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), metrics: &NoopMetrics{}, } } @@ -110,7 +110,7 @@ func WithFullSizeLimit(lim uint64) Option { // WithLogger returns an option to specify Blobovnicza's logger. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = &logger.Logger{Logger: l.With(zap.String("component", "Blobovnicza"))} + c.log = l.With(zap.String("component", "Blobovnicza")) } } diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index aeaa4e1d5c..5d71357414 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -1,6 +1,7 @@ package blobovnicza import ( + "context" "errors" "fmt" "path/filepath" @@ -23,7 +24,7 @@ func (b *Blobovnicza) Open() error { return nil } - b.log.Debug(logs.BlobovniczaCreatingDirectoryForBoltDB, + b.log.Debug(context.Background(), logs.BlobovniczaCreatingDirectoryForBoltDB, zap.String("path", b.path), zap.Bool("ro", b.boltOptions.ReadOnly), ) @@ -37,7 +38,7 @@ func (b *Blobovnicza) Open() error { } } - b.log.Debug(logs.BlobovniczaOpeningBoltDB, + b.log.Debug(context.Background(), logs.BlobovniczaOpeningBoltDB, zap.String("path", b.path), zap.Stringer("permissions", b.perm), ) @@ -63,7 +64,7 @@ func (b *Blobovnicza) Init() error { return errors.New("blobovnicza is not open") } - b.log.Debug(logs.BlobovniczaInitializing, + b.log.Debug(context.Background(), logs.BlobovniczaInitializing, zap.Uint64("object size limit", b.objSizeLimit), zap.Uint64("storage size limit", b.fullSizeLimit), ) @@ -71,7 +72,7 @@ func (b *Blobovnicza) Init() error { size := b.dataSize.Load() items := b.itemsCount.Load() if size != 0 || items != 0 { - b.log.Debug(logs.BlobovniczaAlreadyInitialized, zap.Uint64("size", size), zap.Uint64("items", items)) + b.log.Debug(context.Background(), logs.BlobovniczaAlreadyInitialized, zap.Uint64("size", size), zap.Uint64("items", items)) return nil } @@ -81,7 +82,7 @@ func (b *Blobovnicza) Init() error { // create size range bucket rangeStr := stringifyBounds(lower, upper) - b.log.Debug(logs.BlobovniczaCreatingBucketForSizeRange, + b.log.Debug(context.Background(), logs.BlobovniczaCreatingBucketForSizeRange, zap.String("range", rangeStr)) _, err := tx.CreateBucketIfNotExists(key) @@ -131,17 +132,17 @@ func (b *Blobovnicza) initializeCounters() error { return fmt.Errorf("can't determine DB size: %w", err) } if (!sizeExists || !itemsCountExists) && !b.boltOptions.ReadOnly { - b.log.Debug(logs.BlobovniczaSavingCountersToMeta, zap.Uint64("size", size), zap.Uint64("items", items)) + b.log.Debug(context.Background(), logs.BlobovniczaSavingCountersToMeta, zap.Uint64("size", size), zap.Uint64("items", items)) if err := b.boltDB.Update(func(tx *bbolt.Tx) error { if err := saveDataSize(tx, size); err != nil { return err } return saveItemsCount(tx, items) }); err != nil { - b.log.Debug(logs.BlobovniczaSavingCountersToMetaFailed, zap.Uint64("size", size), zap.Uint64("items", items)) + b.log.Debug(context.Background(), logs.BlobovniczaSavingCountersToMetaFailed, zap.Uint64("size", size), zap.Uint64("items", items)) return fmt.Errorf("can't save blobovnicza's size and items count: %w", err) } - b.log.Debug(logs.BlobovniczaSavingCountersToMetaSuccess, zap.Uint64("size", size), zap.Uint64("items", items)) + b.log.Debug(context.Background(), logs.BlobovniczaSavingCountersToMetaSuccess, zap.Uint64("size", size), zap.Uint64("items", items)) } b.dataSize.Store(size) @@ -162,7 +163,7 @@ func (b *Blobovnicza) Close() error { return nil } - b.log.Debug(logs.BlobovniczaClosingBoltDB, + b.log.Debug(context.Background(), logs.BlobovniczaClosingBoltDB, zap.String("path", b.path), ) diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index 5d6787897e..d821b29910 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -91,7 +91,7 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err } if err == nil && found { - b.log.Debug(logs.BlobovniczaObjectWasRemovedFromBucket, + b.log.Debug(ctx, logs.BlobovniczaObjectWasRemovedFromBucket, zap.String("binary size", stringifyByteSize(dataSize)), zap.String("range", stringifyBounds(sizeLowerBound, sizeUpperBound)), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 681cf876c8..55c9d6630f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -24,10 +24,10 @@ func (b *Blobovniczas) Open(mode mode.ComponentMode) error { // // Should be called exactly once. func (b *Blobovniczas) Init() error { - b.log.Debug(logs.BlobovniczatreeInitializingBlobovniczas) + b.log.Debug(context.Background(), logs.BlobovniczatreeInitializingBlobovniczas) if b.readOnly { - b.log.Debug(logs.BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization) + b.log.Debug(context.Background(), logs.BlobovniczatreeReadonlyModeSkipBlobovniczasInitialization) return nil } @@ -60,7 +60,7 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { b.deleteProtectedObjects.Add(move.Address) } - b.log.Debug(logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) + b.log.Debug(egCtx, logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) return nil }) return false, nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 298de3ad65..dd52580426 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -80,7 +80,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co res, err = b.deleteObjectFromLevel(ctx, bPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotRemoveObjectFromLevel, + b.log.Debug(ctx, logs.BlobovniczatreeCouldNotRemoveObjectFromLevel, zap.String("level", p), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index a64b2bbb1b..2149b17c01 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -55,7 +55,7 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common _, err := b.getObjectFromLevel(ctx, gPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromLevel, + b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 08cacda8ac..e79480095b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -67,7 +67,7 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G res, err = b.getObjectFromLevel(ctx, bPrm, p) if err != nil { if !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromLevel, + b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index d237ae439d..20f2be2bad 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -69,7 +69,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re if err != nil { outOfBounds := isErrOutOfRange(err) if !outOfBounds && !client.IsErrObjectNotFound(err) { - b.log.Debug(logs.BlobovniczatreeCouldNotGetObjectFromLevel, + b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index f6acb46aa8..7f04534104 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -42,7 +42,7 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm data, err := b.compression.Decompress(elem.ObjectData()) if err != nil { if prm.IgnoreErrors { - b.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.Stringer("address", elem.Address()), zap.String("err", err.Error()), zap.String("storage_id", p), @@ -76,7 +76,7 @@ func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors boo blz, err := shBlz.Open() if err != nil { if ignoreErrors { - b.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.String("err", err.Error()), zap.String("storage_id", p), zap.String("root_path", b.rootPath)) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index 4fdde15a92..235c9f65d2 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -1,6 +1,7 @@ package blobovniczatree import ( + "context" "errors" "fmt" "os" @@ -86,7 +87,7 @@ func (b *sharedDB) Close() { defer b.cond.L.Unlock() if b.refCount == 0 { - b.log.Error(logs.AttemtToCloseAlreadyClosedBlobovnicza, zap.String("id", b.path)) + b.log.Error(context.Background(), logs.AttemtToCloseAlreadyClosedBlobovnicza, zap.String("id", b.path)) b.cond.Broadcast() return } @@ -94,7 +95,7 @@ func (b *sharedDB) Close() { if b.refCount == 1 { b.refCount = 0 if err := b.blcza.Close(); err != nil { - b.log.Error(logs.BlobovniczatreeCouldNotCloseBlobovnicza, + b.log.Error(context.Background(), logs.BlobovniczatreeCouldNotCloseBlobovnicza, zap.String("id", b.path), zap.String("error", err.Error()), ) @@ -122,7 +123,7 @@ func (b *sharedDB) CloseAndRemoveFile() error { } if err := b.blcza.Close(); err != nil { - b.log.Error(logs.BlobovniczatreeCouldNotCloseBlobovnicza, + b.log.Error(context.Background(), logs.BlobovniczatreeCouldNotCloseBlobovnicza, zap.String("id", b.path), zap.String("error", err.Error()), ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index 008be95436..b562517721 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -47,7 +47,7 @@ const ( func initConfig(c *cfg) { *c = cfg{ - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), perm: defaultPerm, openedCacheSize: defaultOpenedCacheSize, openedCacheTTL: defaultOpenedCacheTTL, diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 76c4953e4f..844b431518 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -82,7 +82,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) } else { - i.B.log.Debug(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, + i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } @@ -91,7 +91,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) } if active == nil { - i.B.log.Debug(logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath), + i.B.log.Debug(ctx, logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return false, nil } @@ -104,7 +104,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) } else { - i.B.log.Debug(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, + i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", active.SystemPath()), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 202d38cd7b..fee67a0a84 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -49,25 +49,25 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm var res common.RebuildRes - b.log.Debug(logs.BlobovniczaTreeCompletingPreviousRebuild) + b.log.Debug(ctx, logs.BlobovniczaTreeCompletingPreviousRebuild) completedPreviosMoves, err := b.completeIncompletedMove(ctx, prm.MetaStorage) res.ObjectsMoved += completedPreviosMoves if err != nil { - b.log.Warn(logs.BlobovniczaTreeCompletedPreviousRebuildFailed, zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczaTreeCompletedPreviousRebuildFailed, zap.Error(err)) success = false return res, err } - b.log.Debug(logs.BlobovniczaTreeCompletedPreviousRebuildSuccess) + b.log.Debug(ctx, logs.BlobovniczaTreeCompletedPreviousRebuildSuccess) - b.log.Debug(logs.BlobovniczaTreeCollectingDBToRebuild) + b.log.Debug(ctx, logs.BlobovniczaTreeCollectingDBToRebuild) dbsToMigrate, err := b.getDBsToRebuild(ctx, prm.FillPercent) if err != nil { - b.log.Warn(logs.BlobovniczaTreeCollectingDBToRebuildFailed, zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczaTreeCollectingDBToRebuildFailed, zap.Error(err)) success = false return res, err } - b.log.Info(logs.BlobovniczaTreeCollectingDBToRebuildSuccess, zap.Int("blobovniczas_to_rebuild", len(dbsToMigrate))) + b.log.Info(ctx, logs.BlobovniczaTreeCollectingDBToRebuildSuccess, zap.Int("blobovniczas_to_rebuild", len(dbsToMigrate))) res, err = b.migrateDBs(ctx, dbsToMigrate, prm, res) if err != nil { success = false @@ -78,14 +78,14 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common.RebuildPrm, res common.RebuildRes) (common.RebuildRes, error) { var completedDBCount uint32 for _, db := range dbs { - b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) + b.log.Debug(ctx, logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage, prm.WorkerLimiter) res.ObjectsMoved += movedObjects if err != nil { - b.log.Warn(logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) return res, err } - b.log.Debug(logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) + b.log.Debug(ctx, logs.BlobovniczaTreeRebuildingBlobovniczaSuccess, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects)) res.FilesRemoved++ completedDBCount++ b.metrics.SetRebuildPercent((100 * completedDBCount) / uint32(len(dbs))) @@ -233,7 +233,7 @@ func (b *Blobovniczas) addRebuildTempFile(path string) (func(), error) { } return func() { if err := os.Remove(sysPath); err != nil { - b.log.Warn(logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) + b.log.Warn(context.Background(), logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) } }, nil } @@ -389,7 +389,7 @@ func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore co }) for _, tmp := range rebuildTempFilesToRemove { if err := os.Remove(filepath.Join(b.rootPath, tmp)); err != nil { - b.log.Warn(logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) } } return count, err @@ -413,14 +413,14 @@ func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blob if client.IsErrObjectNotFound(err) { existsInSource = false } else { - b.log.Warn(logs.BlobovniczatreeCouldNotCheckExistenceInTargetDB, zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczatreeCouldNotCheckExistenceInTargetDB, zap.Error(err)) return err } } if !existsInSource { // object was deleted by Rebuild, need to delete move info if err = source.DropMoveInfo(ctx, move.Address); err != nil { - b.log.Warn(logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", sourcePath), zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", sourcePath), zap.Error(err)) return err } b.deleteProtectedObjects.Delete(move.Address) @@ -429,7 +429,7 @@ func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blob existsInTarget, err := target.Exists(ctx, move.Address) if err != nil { - b.log.Warn(logs.BlobovniczatreeCouldNotCheckExistenceInTargetDB, zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczatreeCouldNotCheckExistenceInTargetDB, zap.Error(err)) return err } @@ -439,25 +439,25 @@ func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blob putPrm.SetMarshaledObject(gRes.Object()) _, err = target.Put(ctx, putPrm) if err != nil { - b.log.Warn(logs.BlobovniczatreeCouldNotPutObjectToTargetDB, zap.String("path", targetDB.SystemPath()), zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczatreeCouldNotPutObjectToTargetDB, zap.String("path", targetDB.SystemPath()), zap.Error(err)) return err } } if err = metaStore.UpdateStorageID(ctx, move.Address, move.TargetStorageID); err != nil { - b.log.Warn(logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err), zap.Stringer("address", move.Address)) + b.log.Warn(ctx, logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err), zap.Stringer("address", move.Address)) return err } var deletePrm blobovnicza.DeletePrm deletePrm.SetAddress(move.Address) if _, err = source.Delete(ctx, deletePrm); err != nil { - b.log.Warn(logs.BlobovniczatreeCouldNotDeleteFromSource, zap.String("path", sourcePath), zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczatreeCouldNotDeleteFromSource, zap.String("path", sourcePath), zap.Error(err)) return err } if err = source.DropMoveInfo(ctx, move.Address); err != nil { - b.log.Warn(logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", sourcePath), zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", sourcePath), zap.Error(err)) return err } @@ -482,13 +482,13 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) } else { - i.B.log.Warn(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, zap.Error(err)) + i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, zap.Error(err)) } return false, nil } if target == nil { - i.B.log.Warn(logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath)) + i.B.log.Warn(ctx, logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath)) return false, nil } defer target.Close() @@ -505,7 +505,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza, err) } else { - i.B.log.Warn(logs.BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza, zap.String("path", i.SourceSysPath), zap.Error(err)) + i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza, zap.String("path", i.SourceSysPath), zap.Error(err)) } return true, nil } @@ -521,13 +521,13 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) } else { - i.B.log.Warn(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", target.SystemPath()), zap.Error(err)) + i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", target.SystemPath()), zap.Error(err)) } return true, nil } if err = i.MetaStore.UpdateStorageID(ctx, i.Address, targetStorageID.Bytes()); err != nil { - i.B.log.Warn(logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err), zap.Stringer("address", i.Address)) + i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotUpdateStorageID, zap.Error(err), zap.Stringer("address", i.Address)) return true, nil } @@ -537,7 +537,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotDeleteFromSource, err) } else { - i.B.log.Warn(logs.BlobovniczatreeCouldNotDeleteFromSource, zap.String("path", i.SourceSysPath), zap.Error(err)) + i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotDeleteFromSource, zap.String("path", i.SourceSysPath), zap.Error(err)) } return true, nil } @@ -546,7 +546,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotDropMoveInfo, err) } else { - i.B.log.Warn(logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", i.SourceSysPath), zap.Error(err)) + i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", i.SourceSysPath), zap.Error(err)) } return true, nil } diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index 6f579a8ca9..41c6cf1612 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -47,7 +47,7 @@ type cfg struct { } func initConfig(c *cfg) { - c.log = &logger.Logger{Logger: zap.L()} + c.log = logger.NewLoggerWrapper(zap.L()) c.metrics = &noopMetrics{} } @@ -90,7 +90,7 @@ func WithStorages(st []SubStorage) Option { // WithLogger returns option to specify BlobStor's logger. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = &logger.Logger{Logger: l.With(zap.String("component", "BlobStor"))} + c.log = l.With(zap.String("component", "BlobStor")) } } diff --git a/pkg/local_object_storage/blobstor/control.go b/pkg/local_object_storage/blobstor/control.go index 9b414a9be7..43436b4eb6 100644 --- a/pkg/local_object_storage/blobstor/control.go +++ b/pkg/local_object_storage/blobstor/control.go @@ -12,7 +12,7 @@ import ( // Open opens BlobStor. func (b *BlobStor) Open(ctx context.Context, mode mode.Mode) error { - b.log.Debug(logs.BlobstorOpening) + b.log.Debug(ctx, logs.BlobstorOpening) b.modeMtx.Lock() defer b.modeMtx.Unlock() @@ -51,7 +51,7 @@ var ErrInitBlobovniczas = errors.New("failure on blobovnicza initialization stag // // Returns wrapped ErrInitBlobovniczas on blobovnicza tree's initializaiton failure. func (b *BlobStor) Init() error { - b.log.Debug(logs.BlobstorInitializing) + b.log.Debug(context.Background(), logs.BlobstorInitializing) if err := b.compression.Init(); err != nil { return err @@ -68,13 +68,13 @@ func (b *BlobStor) Init() error { // Close releases all internal resources of BlobStor. func (b *BlobStor) Close() error { - b.log.Debug(logs.BlobstorClosing) + b.log.Debug(context.Background(), logs.BlobstorClosing) var firstErr error for i := range b.storage { err := b.storage[i].Storage.Close() if err != nil { - b.log.Info(logs.BlobstorCouldntCloseStorage, zap.String("error", err.Error())) + b.log.Info(context.Background(), logs.BlobstorCouldntCloseStorage, zap.String("error", err.Error())) if firstErr == nil { firstErr = err } diff --git a/pkg/local_object_storage/blobstor/delete.go b/pkg/local_object_storage/blobstor/delete.go index c91508e6d2..86d8f15e34 100644 --- a/pkg/local_object_storage/blobstor/delete.go +++ b/pkg/local_object_storage/blobstor/delete.go @@ -39,7 +39,7 @@ func (b *BlobStor) Delete(ctx context.Context, prm common.DeletePrm) (common.Del if err == nil || !client.IsErrObjectNotFound(err) { if err == nil { success = true - logOp(b.log, deleteOp, prm.Address, b.storage[i].Storage.Type(), prm.StorageID) + logOp(ctx, b.log, deleteOp, prm.Address, b.storage[i].Storage.Type(), prm.StorageID) } return res, err } @@ -58,7 +58,7 @@ func (b *BlobStor) Delete(ctx context.Context, prm common.DeletePrm) (common.Del res, err := st.Delete(ctx, prm) if err == nil { success = true - logOp(b.log, deleteOp, prm.Address, st.Type(), prm.StorageID) + logOp(ctx, b.log, deleteOp, prm.Address, st.Type(), prm.StorageID) } return res, err diff --git a/pkg/local_object_storage/blobstor/exists.go b/pkg/local_object_storage/blobstor/exists.go index 43feec7c91..556f53e12c 100644 --- a/pkg/local_object_storage/blobstor/exists.go +++ b/pkg/local_object_storage/blobstor/exists.go @@ -73,7 +73,7 @@ func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exi } for _, err := range errors[:len(errors)-1] { - b.log.Warn(logs.BlobstorErrorOccurredDuringObjectExistenceChecking, + b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringObjectExistenceChecking, zap.Stringer("address", prm.Address), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 057796db24..7f52762a7a 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -87,7 +87,7 @@ func New(opts ...Option) *FSTree { DirNameLen: DirNameLen, metrics: &noopMetrics{}, fileCounter: &noopCounter{}, - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), } for i := range opts { opts[i](f) @@ -152,7 +152,7 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr des, err := os.ReadDir(dirPath) if err != nil { if prm.IgnoreErrors { - t.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + t.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.String("err", err.Error()), zap.String("directory_path", dirPath)) return nil @@ -200,7 +200,7 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr } if err != nil { if prm.IgnoreErrors { - t.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + t.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.Stringer("address", addr), zap.String("err", err.Error()), zap.String("path", path)) diff --git a/pkg/local_object_storage/blobstor/fstree/option.go b/pkg/local_object_storage/blobstor/fstree/option.go index 4d1f8fc22d..7155ddcbb6 100644 --- a/pkg/local_object_storage/blobstor/fstree/option.go +++ b/pkg/local_object_storage/blobstor/fstree/option.go @@ -53,6 +53,6 @@ func WithFileCounter(c FileCounter) Option { func WithLogger(l *logger.Logger) Option { return func(f *FSTree) { - f.log = &logger.Logger{Logger: l.With(zap.String("component", "FSTree"))} + f.log = l.With(zap.String("component", "FSTree")) } } diff --git a/pkg/local_object_storage/blobstor/iterate.go b/pkg/local_object_storage/blobstor/iterate.go index f213d75474..1ba835a95c 100644 --- a/pkg/local_object_storage/blobstor/iterate.go +++ b/pkg/local_object_storage/blobstor/iterate.go @@ -42,7 +42,7 @@ func (b *BlobStor) Iterate(ctx context.Context, prm common.IteratePrm) (common.I _, err := b.storage[i].Storage.Iterate(ctx, prm) if err != nil { if prm.IgnoreErrors { - b.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, + b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.String("storage_path", b.storage[i].Storage.Path()), zap.String("storage_type", b.storage[i].Storage.Type()), zap.String("err", err.Error())) diff --git a/pkg/local_object_storage/blobstor/logger.go b/pkg/local_object_storage/blobstor/logger.go index 7e057a0e32..070b1eac9d 100644 --- a/pkg/local_object_storage/blobstor/logger.go +++ b/pkg/local_object_storage/blobstor/logger.go @@ -1,6 +1,8 @@ package blobstor import ( + "context" + storagelog "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/log" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -11,8 +13,8 @@ const ( putOp = "PUT" ) -func logOp(l *logger.Logger, op string, addr oid.Address, typ string, sID []byte) { - storagelog.Write(l, +func logOp(ctx context.Context, l *logger.Logger, op string, addr oid.Address, typ string, sID []byte) { + storagelog.Write(ctx, l, storagelog.AddressField(addr), storagelog.OpField(op), storagelog.StorageTypeField(typ), diff --git a/pkg/local_object_storage/blobstor/put.go b/pkg/local_object_storage/blobstor/put.go index 1adae303d5..342da28bfb 100644 --- a/pkg/local_object_storage/blobstor/put.go +++ b/pkg/local_object_storage/blobstor/put.go @@ -63,7 +63,7 @@ func (b *BlobStor) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, e res, err := b.storage[i].Storage.Put(ctx, prm) if err == nil { success = true - logOp(b.log, putOp, prm.Address, b.storage[i].Storage.Type(), res.StorageID) + logOp(ctx, b.log, putOp, prm.Address, b.storage[i].Storage.Type(), res.StorageID) } return res, err } diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go index 7b2786ba26..2a6b947895 100644 --- a/pkg/local_object_storage/blobstor/rebuild.go +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -30,7 +30,7 @@ func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter Con summary.FilesRemoved += res.FilesRemoved summary.ObjectsMoved += res.ObjectsMoved if err != nil { - b.log.Error(logs.BlobstorRebuildFailedToRebuildStorages, + b.log.Error(ctx, logs.BlobstorRebuildFailedToRebuildStorages, zap.String("failed_storage_path", storage.Storage.Path()), zap.String("failed_storage_type", storage.Storage.Type()), zap.Error(err)) @@ -38,7 +38,7 @@ func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter Con break } } - b.log.Info(logs.BlobstorRebuildRebuildStoragesCompleted, + b.log.Info(ctx, logs.BlobstorRebuildRebuildStoragesCompleted, zap.Bool("success", rErr == nil), zap.Uint64("total_files_removed", summary.FilesRemoved), zap.Uint64("total_objects_moved", summary.ObjectsMoved)) diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index 80fb3f9ed8..98ec73ae96 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -49,7 +49,7 @@ func (e *StorageEngine) open(ctx context.Context) error { for res := range errCh { if res.err != nil { - e.log.Error(logs.EngineCouldNotOpenShardClosingAndSkipping, + e.log.Error(ctx, logs.EngineCouldNotOpenShardClosingAndSkipping, zap.String("id", res.id), zap.Error(res.err)) @@ -58,7 +58,7 @@ func (e *StorageEngine) open(ctx context.Context) error { err := sh.Close() if err != nil { - e.log.Error(logs.EngineCouldNotClosePartiallyInitializedShard, + e.log.Error(ctx, logs.EngineCouldNotClosePartiallyInitializedShard, zap.String("id", res.id), zap.Error(res.err)) } @@ -101,7 +101,7 @@ func (e *StorageEngine) Init(ctx context.Context) error { for res := range errCh { if res.err != nil { if errors.Is(res.err, blobstor.ErrInitBlobovniczas) { - e.log.Error(logs.EngineCouldNotInitializeShardClosingAndSkipping, + e.log.Error(ctx, logs.EngineCouldNotInitializeShardClosingAndSkipping, zap.String("id", res.id), zap.Error(res.err)) @@ -110,7 +110,7 @@ func (e *StorageEngine) Init(ctx context.Context) error { err := sh.Close() if err != nil { - e.log.Error(logs.EngineCouldNotClosePartiallyInitializedShard, + e.log.Error(ctx, logs.EngineCouldNotClosePartiallyInitializedShard, zap.String("id", res.id), zap.Error(res.err)) } @@ -165,7 +165,7 @@ func (e *StorageEngine) close(releasePools bool) error { for id, sh := range e.shards { if err := sh.Close(); err != nil { - e.log.Debug(logs.EngineCouldNotCloseShard, + e.log.Debug(context.Background(), logs.EngineCouldNotCloseShard, zap.String("id", id), zap.String("error", err.Error()), ) @@ -311,7 +311,7 @@ loop: for _, p := range shardsToReload { err := p.sh.Reload(ctx, p.opts...) if err != nil { - e.log.Error(logs.EngineCouldNotReloadAShard, + e.log.Error(ctx, logs.EngineCouldNotReloadAShard, zap.Stringer("shard id", p.sh.ID()), zap.Error(err)) } @@ -340,7 +340,7 @@ loop: return fmt.Errorf("could not add %s shard: %w", idStr, err) } - e.log.Info(logs.EngineAddedNewShard, zap.String("id", idStr)) + e.log.Info(ctx, logs.EngineAddedNewShard, zap.String("id", idStr)) } return nil diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 9ca3a7ceec..2e957eb046 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -152,7 +152,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { res, err := sh.Select(ctx, selectPrm) if err != nil { - e.log.Warn(logs.EngineErrorDuringSearchingForObjectChildren, + e.log.Warn(ctx, logs.EngineErrorDuringSearchingForObjectChildren, zap.Stringer("addr", addr), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -164,7 +164,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo _, err = sh.Inhume(ctx, inhumePrm) if err != nil { - e.log.Debug(logs.EngineCouldNotInhumeObjectInShard, + e.log.Debug(ctx, logs.EngineCouldNotInhumeObjectInShard, zap.Stringer("addr", addr), zap.String("err", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -194,7 +194,7 @@ func (e *StorageEngine) deleteChunks( inhumePrm.MarkAsGarbage(addr) _, err = sh.Inhume(ctx, inhumePrm) if err != nil { - e.log.Debug(logs.EngineCouldNotInhumeObjectInShard, + e.log.Debug(ctx, logs.EngineCouldNotInhumeObjectInShard, zap.Stringer("addr", addr), zap.String("err", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 3183d61374..8963ec0991 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -99,20 +99,20 @@ func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32, isMeta if isMeta { err := sh.SetMode(mode.DegradedReadOnly) if err == nil { - log.Info(logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) + log.Info(context.Background(), logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) return } - log.Error(logs.EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly, + log.Error(context.Background(), logs.EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly, zap.Error(err)) } err := sh.SetMode(mode.ReadOnly) if err != nil { - log.Error(logs.EngineFailedToMoveShardInReadonlyMode, zap.Error(err)) + log.Error(context.Background(), logs.EngineFailedToMoveShardInReadonlyMode, zap.Error(err)) return } - log.Info(logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) + log.Info(context.Background(), logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) } // reportShardErrorByID increases shard error counter and logs an error. @@ -137,7 +137,7 @@ func (e *StorageEngine) reportShardError( fields ...zap.Field, ) { if isLogical(err) { - e.log.Warn(msg, + e.log.Warn(context.Background(), msg, zap.Stringer("shard_id", sh.ID()), zap.String("error", err.Error())) return @@ -147,7 +147,7 @@ func (e *StorageEngine) reportShardError( e.metrics.IncErrorCounter(sh.ID().String()) sid := sh.ID() - e.log.Warn(msg, append([]zap.Field{ + e.log.Warn(context.Background(), msg, append([]zap.Field{ zap.Stringer("shard_id", sid), zap.Uint32("error count", errCount), zap.String("error", err.Error()), @@ -168,7 +168,7 @@ func (e *StorageEngine) reportShardError( default: // For background workers we can have a lot of such errors, // thus logging is done with DEBUG level. - e.log.Debug(logs.EngineModeChangeIsInProgressIgnoringSetmodeRequest, + e.log.Debug(context.Background(), logs.EngineModeChangeIsInProgressIgnoringSetmodeRequest, zap.Stringer("shard_id", sid), zap.Uint32("error_count", errCount)) } @@ -197,7 +197,7 @@ type cfg struct { func defaultCfg() *cfg { res := &cfg{ - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), shardPoolSize: 20, metrics: noopMetrics{}, } @@ -269,8 +269,8 @@ type containerSource struct { func (s *containerSource) IsContainerAvailable(ctx context.Context, id cid.ID) (bool, error) { select { - case <-ctx.Done(): - return false, ctx.Err() + case <-context.Background().Done(): + return false, context.Background().Err() default: } diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 940e303234..b88c249b1c 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -297,12 +297,12 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p e.evacuateLimiter.Complete(err) }() - e.log.Info(logs.EngineStartedShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, + e.log.Info(ctx, logs.EngineStartedShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) err = e.getTotals(ctx, prm, shardsToEvacuate, res) if err != nil { - e.log.Error(logs.EngineShardsEvacuationFailedToCount, zap.Strings("shard_ids", shardIDs), zap.Error(err), evacuationOperationLogField, + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToCount, zap.Strings("shard_ids", shardIDs), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) return err } @@ -336,12 +336,12 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p err = errors.Join(err, fmt.Errorf("object error: %w", errObject)) } if err != nil { - e.log.Error(logs.EngineFinishedWithErrorShardsEvacuation, zap.Error(err), zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, + e.log.Error(ctx, logs.EngineFinishedWithErrorShardsEvacuation, zap.Error(err), zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) return err } - e.log.Info(logs.EngineFinishedSuccessfullyShardsEvacuation, + e.log.Info(ctx, logs.EngineFinishedSuccessfullyShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, zap.Uint64("total_objects", res.ObjectsTotal()), @@ -494,7 +494,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context err := sh.IterateOverContainers(ctx, cntPrm) if err != nil { cancel(err) - e.log.Error(logs.EngineShardsEvacuationFailedToListObjects, zap.String("shard_id", shardID), zap.Error(err), evacuationOperationLogField, + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToListObjects, zap.String("shard_id", shardID), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } return err @@ -551,7 +551,7 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree return err } if success { - e.log.Debug(logs.EngineShardsEvacuationTreeEvacuatedLocal, + e.log.Debug(ctx, logs.EngineShardsEvacuationTreeEvacuatedLocal, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), zap.String("from_shard_id", sh.ID().String()), zap.String("to_shard_id", shardID), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -561,26 +561,26 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree moved, nodePK, err := e.evacuateTreeToOtherNode(ctx, sh, contTree, prm) if err != nil { - e.log.Error(logs.EngineShardsEvacuationFailedToMoveTree, + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToMoveTree, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } if moved { - e.log.Debug(logs.EngineShardsEvacuationTreeEvacuatedRemote, + e.log.Debug(ctx, logs.EngineShardsEvacuationTreeEvacuatedRemote, zap.String("cid", contTree.CID.EncodeToString()), zap.String("treeID", contTree.TreeID), zap.String("from_shardID", sh.ID().String()), zap.String("to_node", nodePK), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) res.trEvacuated.Add(1) } else if prm.IgnoreErrors { res.trFailed.Add(1) - e.log.Warn(logs.EngineShardsEvacuationFailedToMoveTree, + e.log.Warn(ctx, logs.EngineShardsEvacuationFailedToMoveTree, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } else { - e.log.Error(logs.EngineShardsEvacuationFailedToMoveTree, + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToMoveTree, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -770,7 +770,7 @@ func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objI res.objFailed.Add(1) return nil } - e.log.Error(logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } @@ -792,7 +792,7 @@ func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objI moved, err := prm.ObjectsHandler(ctx, addr, getRes.Object()) if err != nil { - e.log.Error(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } @@ -800,7 +800,7 @@ func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objI res.objEvacuated.Add(1) } else if prm.IgnoreErrors { res.objFailed.Add(1) - e.log.Warn(logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, + e.log.Warn(ctx, logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } else { return fmt.Errorf("object %s was not replicated", addr) @@ -835,7 +835,7 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add switch e.putToShard(ctx, shards[j].hashedShard, shards[j].pool, addr, object, container.IsIndexedContainer(cnr)).status { case putToShardSuccess: res.objEvacuated.Add(1) - e.log.Debug(logs.EngineObjectIsMovedToAnotherShard, + e.log.Debug(ctx, logs.EngineObjectIsMovedToAnotherShard, zap.Stringer("from", sh.ID()), zap.Stringer("to", shards[j].ID()), zap.Stringer("addr", addr), diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index a1fe8a0101..d6827e6c34 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -104,7 +104,7 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { return GetRes{}, it.OutError } if it.ShardWithMeta.Shard != nil && it.MetaError != nil { - e.log.Warn(logs.ShardMetaInfoPresentButObjectNotFound, + e.log.Warn(ctx, logs.ShardMetaInfoPresentButObjectNotFound, zap.Stringer("shard_id", it.ShardWithMeta.ID()), zap.String("error", it.MetaError.Error()), zap.Stringer("address", prm.addr), diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index b8959b5340..1dc64c1744 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -90,7 +90,7 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, e if !prm.forceRemoval { locked, err := e.IsLocked(ctx, prm.addrs[i]) if err != nil { - e.log.Warn(logs.EngineRemovingAnObjectWithoutFullLockingCheck, + e.log.Warn(ctx, logs.EngineRemovingAnObjectWithoutFullLockingCheck, zap.Error(err), zap.Stringer("addr", prm.addrs[i]), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -264,7 +264,7 @@ func (e *StorageEngine) processExpiredLocks(ctx context.Context, epoch uint64, l select { case <-ctx.Done(): - e.log.Info(logs.EngineInterruptProcessingTheExpiredLocks, zap.Error(ctx.Err())) + e.log.Info(ctx, logs.EngineInterruptProcessingTheExpiredLocks, zap.Error(ctx.Err())) return true default: return false @@ -278,7 +278,7 @@ func (e *StorageEngine) processDeletedLocks(ctx context.Context, lockers []oid.A select { case <-ctx.Done(): - e.log.Info(logs.EngineInterruptProcessingTheDeletedLocks, zap.Error(ctx.Err())) + e.log.Info(ctx, logs.EngineInterruptProcessingTheDeletedLocks, zap.Error(ctx.Err())) return true default: return false @@ -305,7 +305,7 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid e.iterateOverUnsortedShards(func(sh hashedShard) bool { select { case <-ctx.Done(): - e.log.Info(logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(ctx.Err())) + e.log.Info(ctx, logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(ctx.Err())) failed = true return true default: @@ -316,7 +316,7 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid prm.SetContainerID(id) s, err := sh.ContainerSize(prm) if err != nil { - e.log.Warn(logs.EngineFailedToGetContainerSize, zap.Stringer("container_id", id), zap.Error(err)) + e.log.Warn(ctx, logs.EngineFailedToGetContainerSize, zap.Stringer("container_id", id), zap.Error(err)) failed = true return true } @@ -338,7 +338,7 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid e.iterateOverUnsortedShards(func(sh hashedShard) bool { select { case <-ctx.Done(): - e.log.Info(logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(ctx.Err())) + e.log.Info(ctx, logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(ctx.Err())) failed = true return true default: @@ -346,7 +346,7 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid for id := range idMap { if err := sh.DeleteContainerSize(ctx, id); err != nil { - e.log.Warn(logs.EngineFailedToDeleteContainerSize, zap.Stringer("container_id", id), zap.Error(err)) + e.log.Warn(ctx, logs.EngineFailedToDeleteContainerSize, zap.Stringer("container_id", id), zap.Error(err)) failed = true return true } @@ -383,7 +383,7 @@ func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []ci e.iterateOverUnsortedShards(func(sh hashedShard) bool { select { case <-ctx.Done(): - e.log.Info(logs.EngineInterruptProcessingZeroCountContainers, zap.Error(ctx.Err())) + e.log.Info(ctx, logs.EngineInterruptProcessingZeroCountContainers, zap.Error(ctx.Err())) failed = true return true default: @@ -394,7 +394,7 @@ func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []ci prm.ContainerID = id s, err := sh.ContainerCount(ctx, prm) if err != nil { - e.log.Warn(logs.EngineFailedToGetContainerCounters, zap.Stringer("container_id", id), zap.Error(err)) + e.log.Warn(ctx, logs.EngineFailedToGetContainerCounters, zap.Stringer("container_id", id), zap.Error(err)) failed = true return true } @@ -416,7 +416,7 @@ func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []ci e.iterateOverUnsortedShards(func(sh hashedShard) bool { select { case <-ctx.Done(): - e.log.Info(logs.EngineInterruptProcessingZeroCountContainers, zap.Error(ctx.Err())) + e.log.Info(ctx, logs.EngineInterruptProcessingZeroCountContainers, zap.Error(ctx.Err())) failed = true return true default: @@ -424,7 +424,7 @@ func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []ci for id := range idMap { if err := sh.DeleteContainerCount(ctx, id); err != nil { - e.log.Warn(logs.EngineFailedToDeleteContainerSize, zap.Stringer("container_id", id), zap.Error(err)) + e.log.Warn(ctx, logs.EngineFailedToDeleteContainerSize, zap.Stringer("container_id", id), zap.Error(err)) failed = true return true } @@ -449,7 +449,7 @@ func (e *StorageEngine) selectNonExistentIDs(ctx context.Context, ids []cid.ID) for _, id := range ids { isAvailable, err := cs.IsContainerAvailable(ctx, id) if err != nil { - e.log.Warn(logs.EngineFailedToCheckContainerAvailability, zap.Stringer("container_id", id), zap.Error(err)) + e.log.Warn(ctx, logs.EngineFailedToCheckContainerAvailability, zap.Stringer("container_id", id), zap.Error(err)) return nil, err } if isAvailable { diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 56d3ef4901..635f0e3023 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -141,7 +141,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti // expired => do nothing with it res.status = putToShardExists } else { - e.log.Warn(logs.EngineCouldNotCheckObjectExistence, + e.log.Warn(ctx, logs.EngineCouldNotCheckObjectExistence, zap.Stringer("shard_id", sh.ID()), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -163,14 +163,14 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti if err != nil { if errors.Is(err, shard.ErrReadOnlyMode) || errors.Is(err, blobstor.ErrNoPlaceFound) || errors.Is(err, common.ErrReadOnly) || errors.Is(err, common.ErrNoSpace) { - e.log.Warn(logs.EngineCouldNotPutObjectToShard, + e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, zap.Stringer("shard_id", sh.ID()), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return } if client.IsErrObjectAlreadyRemoved(err) { - e.log.Warn(logs.EngineCouldNotPutObjectToShard, + e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, zap.Stringer("shard_id", sh.ID()), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -185,7 +185,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti res.status = putToShardSuccess }); err != nil { - e.log.Warn(logs.EngineCouldNotPutObjectToShard, zap.Error(err)) + e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, zap.Error(err)) close(exitCh) } diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index fde6052ae9..c5c94eef7e 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -116,7 +116,7 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error return RngRes{}, it.OutError } if it.ShardWithMeta.Shard != nil && it.MetaError != nil { - e.log.Warn(logs.ShardMetaInfoPresentButObjectNotFound, + e.log.Warn(ctx, logs.ShardMetaInfoPresentButObjectNotFound, zap.Stringer("shard_id", it.ShardWithMeta.ID()), zap.String("error", it.MetaError.Error()), zap.Stringer("address", prm.addr), diff --git a/pkg/local_object_storage/engine/remove_copies.go b/pkg/local_object_storage/engine/remove_copies.go index 5e1ced56a3..8ab3c5217f 100644 --- a/pkg/local_object_storage/engine/remove_copies.go +++ b/pkg/local_object_storage/engine/remove_copies.go @@ -43,7 +43,7 @@ func (e *StorageEngine) RemoveDuplicates(ctx context.Context, prm RemoveDuplicat prm.Concurrency = defaultRemoveDuplicatesConcurrency } - e.log.Info(logs.EngineStartingRemovalOfLocallyredundantCopies, + e.log.Info(ctx, logs.EngineStartingRemovalOfLocallyredundantCopies, zap.Int("concurrency", prm.Concurrency)) // The mutext must be taken for the whole duration to avoid target shard being removed @@ -55,7 +55,7 @@ func (e *StorageEngine) RemoveDuplicates(ctx context.Context, prm RemoveDuplicat // This is not currently the case, because `FreeSpace` metric used by weight sorting is always 0. // However we could change weights in future and easily forget this function. for _, sh := range e.shards { - e.log.Debug(logs.EngineStartedDuplicatesRemovalRoutine, zap.Stringer("shard_id", sh.ID())) + e.log.Debug(ctx, logs.EngineStartedDuplicatesRemovalRoutine, zap.Stringer("shard_id", sh.ID())) ch := make(chan oid.Address) errG, ctx := errgroup.WithContext(ctx) @@ -93,12 +93,12 @@ func (e *StorageEngine) RemoveDuplicates(ctx context.Context, prm RemoveDuplicat }) } if err := errG.Wait(); err != nil { - e.log.Error(logs.EngineFinishedRemovalOfLocallyredundantCopies, zap.Error(err)) + e.log.Error(ctx, logs.EngineFinishedRemovalOfLocallyredundantCopies, zap.Error(err)) return err } } - e.log.Info(logs.EngineFinishedRemovalOfLocallyredundantCopies) + e.log.Info(ctx, logs.EngineFinishedRemovalOfLocallyredundantCopies) return nil } diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index aab2c423c6..e172706e3a 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -140,7 +140,7 @@ func (e *StorageEngine) createShard(_ context.Context, opts []shard.Option) (*sh )...) if err := sh.UpdateID(); err != nil { - e.log.Warn(logs.FailedToUpdateShardID, zap.Stringer("shard_id", sh.ID()), zap.String("metabase_path", sh.DumpInfo().MetaBaseInfo.Path), zap.Error(err)) + e.log.Warn(context.Background(), logs.FailedToUpdateShardID, zap.Stringer("shard_id", sh.ID()), zap.String("metabase_path", sh.DumpInfo().MetaBaseInfo.Path), zap.Error(err)) } return sh, nil @@ -228,7 +228,7 @@ func (e *StorageEngine) removeShards(ids ...string) { delete(e.shardPools, id) } - e.log.Info(logs.EngineShardHasBeenRemoved, + e.log.Info(context.Background(), logs.EngineShardHasBeenRemoved, zap.String("id", id)) } e.mtx.Unlock() @@ -236,14 +236,14 @@ func (e *StorageEngine) removeShards(ids ...string) { for _, sh := range ss { err := sh.SetMode(mode.Disabled) if err != nil { - e.log.Error(logs.EngineCouldNotChangeShardModeToDisabled, + e.log.Error(context.Background(), logs.EngineCouldNotChangeShardModeToDisabled, zap.Stringer("id", sh.ID()), zap.Error(err), ) } err = sh.Close() if err != nil { - e.log.Error(logs.EngineCouldNotCloseRemovedShard, + e.log.Error(context.Background(), logs.EngineCouldNotCloseRemovedShard, zap.Stringer("id", sh.ID()), zap.Error(err), ) @@ -340,7 +340,7 @@ func (e *StorageEngine) HandleNewEpoch(ctx context.Context, epoch uint64) { return case sh.NotificationChannel() <- ev: default: - e.log.Debug(logs.ShardEventProcessingInProgress, + e.log.Debug(ctx, logs.ShardEventProcessingInProgress, zap.Uint64("epoch", epoch), zap.Stringer("shard", sh.ID())) } } @@ -369,7 +369,7 @@ func (e *StorageEngine) closeShards(deletedShards []hashedShard) error { eg.Go(func() error { err := sh.SetMode(mode.Disabled) if err != nil { - e.log.Error(logs.EngineCouldNotChangeShardModeToDisabled, + e.log.Error(context.Background(), logs.EngineCouldNotChangeShardModeToDisabled, zap.Stringer("id", sh.ID()), zap.Error(err), ) @@ -380,7 +380,7 @@ func (e *StorageEngine) closeShards(deletedShards []hashedShard) error { err = sh.Close() if err != nil { - e.log.Error(logs.EngineCouldNotCloseRemovedShard, + e.log.Error(context.Background(), logs.EngineCouldNotCloseRemovedShard, zap.Stringer("id", sh.ID()), zap.Error(err), ) @@ -432,7 +432,7 @@ func (e *StorageEngine) deleteShards(ids []*shard.ID) ([]hashedShard, error) { delete(e.shardPools, idStr) } - e.log.Info(logs.EngineShardHasBeenRemoved, + e.log.Info(context.Background(), logs.EngineShardHasBeenRemoved, zap.String("id", idStr)) } diff --git a/pkg/local_object_storage/internal/log/log.go b/pkg/local_object_storage/internal/log/log.go index 23740868d7..6b101fa605 100644 --- a/pkg/local_object_storage/internal/log/log.go +++ b/pkg/local_object_storage/internal/log/log.go @@ -1,14 +1,16 @@ package storagelog import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) // Write writes message about storage engine's operation to logger. -func Write(logger *logger.Logger, fields ...zap.Field) { - logger.Debug(logs.StorageOperation, fields...) +func Write(ctx context.Context, logger *logger.Logger, fields ...zap.Field) { + logger.Debug(ctx, logs.StorageOperation, fields...) } // AddressField returns logger's field for object address. diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index d6546d922c..68e065a0ad 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -57,7 +57,7 @@ func (db *DB) openDB(mode mode.Mode) error { return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err) } - db.log.Debug(logs.MetabaseCreatedDirectoryForMetabase, zap.String("path", db.info.Path)) + db.log.Debug(context.Background(), logs.MetabaseCreatedDirectoryForMetabase, zap.String("path", db.info.Path)) if db.boltOptions == nil { opts := *bbolt.DefaultOptions @@ -78,9 +78,9 @@ func (db *DB) openBolt() error { db.boltDB.MaxBatchDelay = db.boltBatchDelay db.boltDB.MaxBatchSize = db.boltBatchSize - db.log.Debug(logs.MetabaseOpenedBoltDBInstanceForMetabase) + db.log.Debug(context.Background(), logs.MetabaseOpenedBoltDBInstanceForMetabase) - db.log.Debug(logs.MetabaseCheckingMetabaseVersion) + db.log.Debug(context.Background(), logs.MetabaseCheckingMetabaseVersion) return db.boltDB.View(func(tx *bbolt.Tx) error { // The safest way to check if the metabase is fresh is to check if it has no buckets. // However, shard info can be present. So here we check that the number of buckets is diff --git a/pkg/local_object_storage/metabase/db.go b/pkg/local_object_storage/metabase/db.go index 2cd990814c..4474aa2291 100644 --- a/pkg/local_object_storage/metabase/db.go +++ b/pkg/local_object_storage/metabase/db.go @@ -70,7 +70,7 @@ func defaultCfg() *cfg { }, boltBatchDelay: bbolt.DefaultMaxBatchDelay, boltBatchSize: bbolt.DefaultMaxBatchSize, - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), metrics: &noopMetrics{}, } } diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index b5ac220179..62ab1056d9 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -117,7 +117,7 @@ func (db *DB) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { if err == nil { deleted = true for i := range prm.addrs { - storagelog.Write(db.log, + storagelog.Write(ctx, db.log, storagelog.AddressField(prm.addrs[i]), storagelog.OpField("metabase DELETE")) } diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 12f27d3302..8d1e18729a 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -205,7 +205,7 @@ func (db *DB) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { success = err == nil if success { for _, addr := range prm.target { - storagelog.Write(db.log, + storagelog.Write(ctx, db.log, storagelog.AddressField(addr), storagelog.OpField("metabase INHUME")) } diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 2d94e7ae18..d7675869fa 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -101,7 +101,7 @@ func (db *DB) Put(ctx context.Context, prm PutPrm) (res PutRes, err error) { }) if err == nil { success = true - storagelog.Write(db.log, + storagelog.Write(ctx, db.log, storagelog.AddressField(objectCore.AddressOf(prm.obj)), storagelog.OpField("metabase PUT")) } diff --git a/pkg/local_object_storage/metabase/upgrade_test.go b/pkg/local_object_storage/metabase/upgrade_test.go index aeb14aeb6c..e2eee86b07 100644 --- a/pkg/local_object_storage/metabase/upgrade_test.go +++ b/pkg/local_object_storage/metabase/upgrade_test.go @@ -113,7 +113,7 @@ func TestGenerateMetabaseFile(t *testing.T) { }) } require.NoError(t, eg.Wait()) - db.log.Info("simple objects generated") + db.log.Info(ctx, "simple objects generated") eg, ctx = errgroup.WithContext(context.Background()) eg.SetLimit(generateWorkersCount) // complex objects @@ -137,7 +137,7 @@ func TestGenerateMetabaseFile(t *testing.T) { }) } require.NoError(t, eg.Wait()) - db.log.Info("complex objects generated") + db.log.Info(ctx, "complex objects generated") eg, ctx = errgroup.WithContext(context.Background()) eg.SetLimit(generateWorkersCount) // simple objects deleted by gc marks @@ -159,7 +159,7 @@ func TestGenerateMetabaseFile(t *testing.T) { }) } require.NoError(t, eg.Wait()) - db.log.Info("simple objects deleted by gc marks generated") + db.log.Info(ctx, "simple objects deleted by gc marks generated") eg, ctx = errgroup.WithContext(context.Background()) eg.SetLimit(10000) // simple objects deleted by tombstones @@ -189,7 +189,7 @@ func TestGenerateMetabaseFile(t *testing.T) { }) } require.NoError(t, eg.Wait()) - db.log.Info("simple objects deleted by tombstones generated") + db.log.Info(ctx, "simple objects deleted by tombstones generated") eg, ctx = errgroup.WithContext(context.Background()) eg.SetLimit(generateWorkersCount) // simple objects locked by locks @@ -216,7 +216,7 @@ func TestGenerateMetabaseFile(t *testing.T) { }) } require.NoError(t, eg.Wait()) - db.log.Info("simple objects locked by locks generated") + db.log.Info(ctx, "simple objects locked by locks generated") require.NoError(t, db.boltDB.Sync()) require.NoError(t, db.Close()) } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 62800dbd03..eb3aa61c07 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -21,7 +21,7 @@ import ( ) func (s *Shard) handleMetabaseFailure(stage string, err error) error { - s.log.Error(logs.ShardMetabaseFailureSwitchingMode, + s.log.Error(context.Background(), logs.ShardMetabaseFailureSwitchingMode, zap.String("stage", stage), zap.Stringer("mode", mode.ReadOnly), zap.Error(err)) @@ -31,7 +31,7 @@ func (s *Shard) handleMetabaseFailure(stage string, err error) error { return nil } - s.log.Error(logs.ShardCantMoveShardToReadonlySwitchMode, + s.log.Error(context.Background(), logs.ShardCantMoveShardToReadonlySwitchMode, zap.String("stage", stage), zap.Stringer("mode", mode.DegradedReadOnly), zap.Error(err)) @@ -211,7 +211,7 @@ func (s *Shard) refillMetabase(ctx context.Context) error { withCount := true totalObjects, err := s.blobStor.ObjectsCount(ctx) if err != nil { - s.log.Warn(logs.EngineRefillFailedToGetObjectsCount, zap.Error(err)) + s.log.Warn(ctx, logs.EngineRefillFailedToGetObjectsCount, zap.Error(err)) withCount = false } @@ -270,7 +270,7 @@ func (s *Shard) refillMetabase(ctx context.Context) error { func (s *Shard) refillObject(ctx context.Context, data []byte, addr oid.Address, descriptor []byte) error { obj := objectSDK.New() if err := obj.Unmarshal(data); err != nil { - s.log.Warn(logs.ShardCouldNotUnmarshalObject, + s.log.Warn(ctx, logs.ShardCouldNotUnmarshalObject, zap.Stringer("address", addr), zap.String("err", err.Error())) return nil @@ -285,7 +285,7 @@ func (s *Shard) refillObject(ctx context.Context, data []byte, addr oid.Address, return err } if info.Removed { - s.log.Debug(logs.ShardSkipObjectFromResyncContainerDeleted, zap.Stringer("address", addr)) + s.log.Debug(ctx, logs.ShardSkipObjectFromResyncContainerDeleted, zap.Stringer("address", addr)) return nil } isIndexedContainer = info.Indexed @@ -386,7 +386,7 @@ func (s *Shard) Close() error { for _, component := range components { if err := component.Close(); err != nil { lastErr = err - s.log.Error(logs.ShardCouldNotCloseShardComponent, zap.Error(err)) + s.log.Error(context.Background(), logs.ShardCouldNotCloseShardComponent, zap.Error(err)) } } @@ -424,7 +424,7 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { ok, err := s.metaBase.Reload(c.metaOpts...) if err != nil { if errors.Is(err, meta.ErrDegradedMode) { - s.log.Error(logs.ShardCantOpenMetabaseMoveToADegradedMode, zap.Error(err)) + s.log.Error(ctx, logs.ShardCantOpenMetabaseMoveToADegradedMode, zap.Error(err)) _ = s.setMode(mode.DegradedReadOnly) } return err @@ -440,7 +440,7 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { err = s.metaBase.Init() } if err != nil { - s.log.Error(logs.ShardCantInitializeMetabaseMoveToADegradedreadonlyMode, zap.Error(err)) + s.log.Error(ctx, logs.ShardCantInitializeMetabaseMoveToADegradedreadonlyMode, zap.Error(err)) _ = s.setMode(mode.DegradedReadOnly) return err } diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index c898fdf41b..f62cecd56b 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -95,7 +95,7 @@ func (s *Shard) validateWritecacheDoesntContainObject(ctx context.Context, addr } _, err := s.writeCache.Head(ctx, addr) if err == nil { - s.log.Warn(logs.ObjectRemovalFailureExistsInWritecache, zap.Stringer("object_address", addr)) + s.log.Warn(ctx, logs.ObjectRemovalFailureExistsInWritecache, zap.Stringer("object_address", addr)) return fmt.Errorf("object %s must be flushed from writecache", addr) } if client.IsErrObjectNotFound(err) { @@ -110,7 +110,7 @@ func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error res, err := s.metaBase.StorageID(ctx, sPrm) if err != nil { - s.log.Debug(logs.StorageIDRetrievalFailure, + s.log.Debug(ctx, logs.StorageIDRetrievalFailure, zap.Stringer("object", addr), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -130,7 +130,7 @@ func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error _, err = s.blobStor.Delete(ctx, delPrm) if err != nil && !client.IsErrObjectNotFound(err) { - s.log.Debug(logs.ObjectRemovalFailureBlobStor, + s.log.Debug(ctx, logs.ObjectRemovalFailureBlobStor, zap.Stringer("object_address", addr), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index d605746e84..6fabf7103e 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -131,7 +131,7 @@ type gcCfg struct { func defaultGCCfg() gcCfg { return gcCfg{ removerInterval: 10 * time.Second, - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), workerPoolInit: func(int) util.WorkerPool { return nil }, @@ -161,14 +161,14 @@ func (gc *gc) listenEvents(ctx context.Context) { for { select { case <-gc.stopChannel: - gc.log.Warn(logs.ShardStopEventListenerByClosedStopChannel) + gc.log.Warn(ctx, logs.ShardStopEventListenerByClosedStopChannel) return case <-ctx.Done(): - gc.log.Warn(logs.ShardStopEventListenerByContext) + gc.log.Warn(ctx, logs.ShardStopEventListenerByContext) return case event, ok := <-gc.eventChan: if !ok { - gc.log.Warn(logs.ShardStopEventListenerByClosedEventChannel) + gc.log.Warn(ctx, logs.ShardStopEventListenerByClosedEventChannel) return } @@ -204,7 +204,7 @@ func (gc *gc) handleEvent(ctx context.Context, event Event) { h(runCtx, event) }) if err != nil { - gc.log.Warn(logs.ShardCouldNotSubmitGCJobToWorkerPool, + gc.log.Warn(ctx, logs.ShardCouldNotSubmitGCJobToWorkerPool, zap.String("error", err.Error()), ) @@ -222,7 +222,7 @@ func (gc *gc) releaseResources() { // because it is possible that we are close it earlier than stop writing. // It is ok to keep it opened. - gc.log.Debug(logs.ShardGCIsStopped) + gc.log.Debug(context.Background(), logs.ShardGCIsStopped) } func (gc *gc) tickRemover(ctx context.Context) { @@ -263,7 +263,7 @@ func (gc *gc) stop() { close(gc.stopChannel) }) - gc.log.Info(logs.ShardWaitingForGCWorkersToStop) + gc.log.Info(context.Background(), logs.ShardWaitingForGCWorkersToStop) gc.wg.Wait() } @@ -286,8 +286,8 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { return } - s.log.Debug(logs.ShardGCRemoveGarbageStarted) - defer s.log.Debug(logs.ShardGCRemoveGarbageCompleted) + s.log.Debug(ctx, logs.ShardGCRemoveGarbageStarted) + defer s.log.Debug(ctx, logs.ShardGCRemoveGarbageCompleted) buf := make([]oid.Address, 0, s.rmBatchSize) @@ -312,7 +312,7 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { // (no more than s.rmBatchSize objects) err := s.metaBase.IterateOverGarbage(ctx, iterPrm) if err != nil { - s.log.Warn(logs.ShardIteratorOverMetabaseGraveyardFailed, + s.log.Warn(ctx, logs.ShardIteratorOverMetabaseGraveyardFailed, zap.String("error", err.Error()), ) @@ -333,7 +333,7 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { result.success = true if err != nil { - s.log.Warn(logs.ShardCouldNotDeleteTheObjects, + s.log.Warn(ctx, logs.ShardCouldNotDeleteTheObjects, zap.String("error", err.Error()), ) result.success = false @@ -356,8 +356,8 @@ func (s *Shard) collectExpiredObjects(ctx context.Context, e Event) { s.gc.metrics.AddExpiredObjectCollectionDuration(time.Since(startedAt), err == nil, objectTypeRegular) }() - s.log.Debug(logs.ShardGCCollectingExpiredObjectsStarted, zap.Uint64("epoch", e.(newEpoch).epoch)) - defer s.log.Debug(logs.ShardGCCollectingExpiredObjectsCompleted, zap.Uint64("epoch", e.(newEpoch).epoch)) + s.log.Debug(ctx, logs.ShardGCCollectingExpiredObjectsStarted, zap.Uint64("epoch", e.(newEpoch).epoch)) + defer s.log.Debug(ctx, logs.ShardGCCollectingExpiredObjectsCompleted, zap.Uint64("epoch", e.(newEpoch).epoch)) workersCount, batchSize := s.getExpiredObjectsParameters() @@ -396,7 +396,7 @@ func (s *Shard) collectExpiredObjects(ctx context.Context, e Event) { }) if err = errGroup.Wait(); err != nil { - s.log.Warn(logs.ShardIteratorOverExpiredObjectsFailed, zap.String("error", err.Error())) + s.log.Warn(ctx, logs.ShardIteratorOverExpiredObjectsFailed, zap.String("error", err.Error())) } } @@ -416,7 +416,7 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) expired, err := s.getExpiredWithLinked(ctx, expired) if err != nil { - s.log.Warn(logs.ShardGCFailedToGetExpiredWithLinked, zap.Error(err)) + s.log.Warn(ctx, logs.ShardGCFailedToGetExpiredWithLinked, zap.Error(err)) return } @@ -428,7 +428,7 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) // inhume the collected objects res, err := s.metaBase.Inhume(ctx, inhumePrm) if err != nil { - s.log.Warn(logs.ShardCouldNotInhumeTheObjects, + s.log.Warn(ctx, logs.ShardCouldNotInhumeTheObjects, zap.String("error", err.Error()), ) @@ -473,8 +473,8 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { epoch := e.(newEpoch).epoch log := s.log.With(zap.Uint64("epoch", epoch)) - log.Debug(logs.ShardStartedExpiredTombstonesHandling) - defer log.Debug(logs.ShardFinishedExpiredTombstonesHandling) + log.Debug(ctx, logs.ShardStartedExpiredTombstonesHandling) + defer log.Debug(ctx, logs.ShardFinishedExpiredTombstonesHandling) const tssDeleteBatch = 50 tss := make([]meta.TombstonedObject, 0, tssDeleteBatch) @@ -492,12 +492,12 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { }) for { - log.Debug(logs.ShardIteratingTombstones) + log.Debug(ctx, logs.ShardIteratingTombstones) s.m.RLock() if s.info.Mode.NoMetabase() { - s.log.Debug(logs.ShardShardIsInADegradedModeSkipCollectingExpiredTombstones) + s.log.Debug(ctx, logs.ShardShardIsInADegradedModeSkipCollectingExpiredTombstones) s.m.RUnlock() return @@ -505,7 +505,7 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { err = s.metaBase.IterateOverGraveyard(ctx, iterPrm) if err != nil { - log.Error(logs.ShardIteratorOverGraveyardFailed, zap.Error(err)) + log.Error(ctx, logs.ShardIteratorOverGraveyardFailed, zap.Error(err)) s.m.RUnlock() return @@ -524,7 +524,7 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { } } - log.Debug(logs.ShardHandlingExpiredTombstonesBatch, zap.Int("number", len(tssExp))) + log.Debug(ctx, logs.ShardHandlingExpiredTombstonesBatch, zap.Int("number", len(tssExp))) if len(tssExp) > 0 { s.expiredTombstonesCallback(ctx, tssExp) } @@ -543,8 +543,8 @@ func (s *Shard) collectExpiredLocks(ctx context.Context, e Event) { s.gc.metrics.AddExpiredObjectCollectionDuration(time.Since(startedAt), err == nil, objectTypeLock) }() - s.log.Debug(logs.ShardGCCollectingExpiredLocksStarted, zap.Uint64("epoch", e.(newEpoch).epoch)) - defer s.log.Debug(logs.ShardGCCollectingExpiredLocksCompleted, zap.Uint64("epoch", e.(newEpoch).epoch)) + s.log.Debug(ctx, logs.ShardGCCollectingExpiredLocksStarted, zap.Uint64("epoch", e.(newEpoch).epoch)) + defer s.log.Debug(ctx, logs.ShardGCCollectingExpiredLocksCompleted, zap.Uint64("epoch", e.(newEpoch).epoch)) workersCount, batchSize := s.getExpiredObjectsParameters() @@ -584,7 +584,7 @@ func (s *Shard) collectExpiredLocks(ctx context.Context, e Event) { }) if err = errGroup.Wait(); err != nil { - s.log.Warn(logs.ShardIteratorOverExpiredLocksFailed, zap.String("error", err.Error())) + s.log.Warn(ctx, logs.ShardIteratorOverExpiredLocksFailed, zap.String("error", err.Error())) } } @@ -645,7 +645,7 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston // inhume tombstones res, err := s.metaBase.Inhume(ctx, pInhume) if err != nil { - s.log.Warn(logs.ShardCouldNotMarkTombstonesAsGarbage, + s.log.Warn(ctx, logs.ShardCouldNotMarkTombstonesAsGarbage, zap.String("error", err.Error()), ) @@ -668,7 +668,7 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston // from graveyard err = s.metaBase.DropGraves(ctx, tss) if err != nil { - s.log.Warn(logs.ShardCouldNotDropExpiredGraveRecords, zap.Error(err)) + s.log.Warn(ctx, logs.ShardCouldNotDropExpiredGraveRecords, zap.Error(err)) } } @@ -680,7 +680,7 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] } unlocked, err := s.metaBase.FreeLockedBy(lockers) if err != nil { - s.log.Warn(logs.ShardFailureToUnlockObjects, + s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, zap.String("error", err.Error()), ) @@ -693,7 +693,7 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] res, err := s.metaBase.Inhume(ctx, pInhume) if err != nil { - s.log.Warn(logs.ShardFailureToMarkLockersAsGarbage, + s.log.Warn(ctx, logs.ShardFailureToMarkLockersAsGarbage, zap.String("error", err.Error()), ) @@ -718,7 +718,7 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] func (s *Shard) inhumeUnlockedIfExpired(ctx context.Context, epoch uint64, unlocked []oid.Address) { expiredUnlocked, err := s.selectExpired(ctx, epoch, unlocked) if err != nil { - s.log.Warn(logs.ShardFailureToGetExpiredUnlockedObjects, zap.Error(err)) + s.log.Warn(ctx, logs.ShardFailureToGetExpiredUnlockedObjects, zap.Error(err)) return } @@ -737,7 +737,7 @@ func (s *Shard) HandleDeletedLocks(lockers []oid.Address) { _, err := s.metaBase.FreeLockedBy(lockers) if err != nil { - s.log.Warn(logs.ShardFailureToUnlockObjects, + s.log.Warn(context.Background(), logs.ShardFailureToUnlockObjects, zap.String("error", err.Error()), ) @@ -756,8 +756,8 @@ func (s *Shard) collectExpiredMetrics(ctx context.Context, e Event) { epoch := e.(newEpoch).epoch - s.log.Debug(logs.ShardGCCollectingExpiredMetricsStarted, zap.Uint64("epoch", epoch)) - defer s.log.Debug(logs.ShardGCCollectingExpiredMetricsCompleted, zap.Uint64("epoch", epoch)) + s.log.Debug(ctx, logs.ShardGCCollectingExpiredMetricsStarted, zap.Uint64("epoch", epoch)) + defer s.log.Debug(ctx, logs.ShardGCCollectingExpiredMetricsCompleted, zap.Uint64("epoch", epoch)) s.collectExpiredContainerSizeMetrics(ctx, epoch) s.collectExpiredContainerCountMetrics(ctx, epoch) @@ -766,7 +766,7 @@ func (s *Shard) collectExpiredMetrics(ctx context.Context, e Event) { func (s *Shard) collectExpiredContainerSizeMetrics(ctx context.Context, epoch uint64) { ids, err := s.metaBase.ZeroSizeContainers(ctx) if err != nil { - s.log.Warn(logs.ShardGCFailedToCollectZeroSizeContainers, zap.Uint64("epoch", epoch), zap.Error(err)) + s.log.Warn(ctx, logs.ShardGCFailedToCollectZeroSizeContainers, zap.Uint64("epoch", epoch), zap.Error(err)) return } if len(ids) == 0 { @@ -778,7 +778,7 @@ func (s *Shard) collectExpiredContainerSizeMetrics(ctx context.Context, epoch ui func (s *Shard) collectExpiredContainerCountMetrics(ctx context.Context, epoch uint64) { ids, err := s.metaBase.ZeroCountContainers(ctx) if err != nil { - s.log.Warn(logs.ShardGCFailedToCollectZeroCountContainers, zap.Uint64("epoch", epoch), zap.Error(err)) + s.log.Warn(ctx, logs.ShardGCFailedToCollectZeroCountContainers, zap.Uint64("epoch", epoch), zap.Error(err)) return } if len(ids) == 0 { diff --git a/pkg/local_object_storage/shard/get.go b/pkg/local_object_storage/shard/get.go index d1c3936132..7a31a705ef 100644 --- a/pkg/local_object_storage/shard/get.go +++ b/pkg/local_object_storage/shard/get.go @@ -144,7 +144,7 @@ func (s *Shard) fetchObjectData(ctx context.Context, addr oid.Address, skipMeta return nil, false, logicerr.Wrap(new(apistatus.ObjectNotFound)) } } else { - s.log.Warn(logs.ShardFetchingObjectWithoutMeta, zap.Stringer("addr", addr)) + s.log.Warn(ctx, logs.ShardFetchingObjectWithoutMeta, zap.Stringer("addr", addr)) } if s.hasWriteCache() { @@ -153,12 +153,12 @@ func (s *Shard) fetchObjectData(ctx context.Context, addr oid.Address, skipMeta return res, false, err } if client.IsErrObjectNotFound(err) { - s.log.Debug(logs.ShardObjectIsMissingInWritecache, + s.log.Debug(ctx, logs.ShardObjectIsMissingInWritecache, zap.Stringer("addr", addr), zap.Bool("skip_meta", skipMeta), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } else { - s.log.Error(logs.ShardFailedToFetchObjectFromWritecache, + s.log.Error(ctx, logs.ShardFailedToFetchObjectFromWritecache, zap.Error(err), zap.Stringer("addr", addr), zap.Bool("skip_meta", skipMeta), diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index a723134989..e27dc07334 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -5,7 +5,6 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/mr-tron/base58" "go.uber.org/zap" ) @@ -50,7 +49,7 @@ func (s *Shard) UpdateID() (err error) { s.writeCache.GetMetrics().SetShardID(shardID) } - s.log = &logger.Logger{Logger: s.log.With(zap.Stringer("shard_id", s.info.ID))} + s.log = s.log.With(zap.Stringer("shard_id", s.info.ID)) s.metaBase.SetLogger(s.log) s.blobStor.SetLogger(s.log) if s.hasWriteCache() { diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index 746177c3a4..984c54fbce 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -109,7 +109,7 @@ func (s *Shard) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { return InhumeRes{}, ErrLockObjectRemoval } - s.log.Debug(logs.ShardCouldNotMarkObjectToDeleteInMetabase, + s.log.Debug(ctx, logs.ShardCouldNotMarkObjectToDeleteInMetabase, zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index 8d09974b8e..7b267d2e46 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -122,7 +122,7 @@ func (s *Shard) List(ctx context.Context) (res SelectRes, err error) { sRes, err := s.metaBase.Select(ctx, sPrm) // consider making List in metabase if err != nil { - s.log.Debug(logs.ShardCantSelectAllObjects, + s.log.Debug(ctx, logs.ShardCantSelectAllObjects, zap.Stringer("cid", lst[i]), zap.String("error", err.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index 9ce95feb13..595afb60ef 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -30,7 +30,7 @@ func TestShard_Lock(t *testing.T) { rootPath := t.TempDir() opts := []Option{ WithID(NewIDFromBytes([]byte{})), - WithLogger(&logger.Logger{Logger: zap.NewNop()}), + WithLogger(logger.NewLoggerWrapper(zap.NewNop())), WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{ { diff --git a/pkg/local_object_storage/shard/mode.go b/pkg/local_object_storage/shard/mode.go index d90a5f4b69..98b4c37b2e 100644 --- a/pkg/local_object_storage/shard/mode.go +++ b/pkg/local_object_storage/shard/mode.go @@ -1,6 +1,8 @@ package shard import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" @@ -26,7 +28,7 @@ func (s *Shard) SetMode(m mode.Mode) error { } func (s *Shard) setMode(m mode.Mode) error { - s.log.Info(logs.ShardSettingShardMode, + s.log.Info(context.Background(), logs.ShardSettingShardMode, zap.Stringer("old_mode", s.info.Mode), zap.Stringer("new_mode", m)) @@ -67,7 +69,7 @@ func (s *Shard) setMode(m mode.Mode) error { s.info.Mode = m s.metricsWriter.SetMode(s.info.Mode) - s.log.Info(logs.ShardShardModeSetSuccessfully, + s.log.Info(context.Background(), logs.ShardShardModeSetSuccessfully, zap.Stringer("mode", s.info.Mode)) return nil } diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index 24cc751547..50125a88d3 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -75,7 +75,7 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { } if err != nil || !tryCache { if err != nil { - s.log.Debug(logs.ShardCantPutObjectToTheWritecacheTryingBlobstor, + s.log.Debug(ctx, logs.ShardCantPutObjectToTheWritecacheTryingBlobstor, zap.String("err", err.Error())) } diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index 0d83caa0c3..124b72a5cb 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -102,11 +102,11 @@ func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *lo return default: } - log.Info(logs.BlobstoreRebuildStarted) + log.Info(ctx, logs.BlobstoreRebuildStarted) if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, limiter, fillPercent); err != nil { - log.Warn(logs.FailedToRebuildBlobstore, zap.Error(err)) + log.Warn(ctx, logs.FailedToRebuildBlobstore, zap.Error(err)) } else { - log.Info(logs.BlobstoreRebuildCompletedSuccessfully) + log.Info(ctx, logs.BlobstoreRebuildCompletedSuccessfully) } } @@ -138,7 +138,7 @@ func (r *rebuilder) Stop(log *logger.Logger) { r.wg.Wait() r.cancel = nil r.done = nil - log.Info(logs.BlobstoreRebuildStopped) + log.Info(context.Background(), logs.BlobstoreRebuildStopped) } var errMBIsNotAvailable = errors.New("metabase is not available") diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 413bfd2f71..3a06fe8a7a 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -103,7 +103,7 @@ type cfg struct { func defaultCfg() *cfg { return &cfg{ rmBatchSize: 100, - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), gcCfg: defaultGCCfg(), reportErrorFunc: func(string, string, error) {}, zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, @@ -401,7 +401,7 @@ func (s *Shard) updateMetrics(ctx context.Context) { cc, err := s.metaBase.ObjectCounters() if err != nil { - s.log.Warn(logs.ShardMetaObjectCounterRead, + s.log.Warn(ctx, logs.ShardMetaObjectCounterRead, zap.Error(err), ) @@ -414,7 +414,7 @@ func (s *Shard) updateMetrics(ctx context.Context) { cnrList, err := s.metaBase.Containers(ctx) if err != nil { - s.log.Warn(logs.ShardMetaCantReadContainerList, zap.Error(err)) + s.log.Warn(ctx, logs.ShardMetaCantReadContainerList, zap.Error(err)) return } @@ -423,7 +423,7 @@ func (s *Shard) updateMetrics(ctx context.Context) { for i := range cnrList { size, err := s.metaBase.ContainerSize(cnrList[i]) if err != nil { - s.log.Warn(logs.ShardMetaCantReadContainerSize, + s.log.Warn(ctx, logs.ShardMetaCantReadContainerSize, zap.String("cid", cnrList[i].EncodeToString()), zap.Error(err)) continue @@ -436,7 +436,7 @@ func (s *Shard) updateMetrics(ctx context.Context) { contCount, err := s.metaBase.ContainerCounters(ctx) if err != nil { - s.log.Warn(logs.FailedToGetContainerCounters, zap.Error(err)) + s.log.Warn(ctx, logs.FailedToGetContainerCounters, zap.Error(err)) return } for contID, count := range contCount.Counts { diff --git a/pkg/local_object_storage/shard/writecache.go b/pkg/local_object_storage/shard/writecache.go index a6de07f033..f655e477a9 100644 --- a/pkg/local_object_storage/shard/writecache.go +++ b/pkg/local_object_storage/shard/writecache.go @@ -124,12 +124,12 @@ func (s *Shard) SealWriteCache(ctx context.Context, p SealWriteCachePrm) error { close(started) defer cleanup() - s.log.Info(logs.StartedWritecacheSealAsync) + s.log.Info(ctx, logs.StartedWritecacheSealAsync) if err := s.writeCache.Seal(ctx, prm); err != nil { - s.log.Warn(logs.FailedToSealWritecacheAsync, zap.Error(err)) + s.log.Warn(ctx, logs.FailedToSealWritecacheAsync, zap.Error(err)) return } - s.log.Info(logs.WritecacheSealCompletedAsync) + s.log.Info(ctx, logs.WritecacheSealCompletedAsync) }() select { case <-ctx.Done(): diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index b97fc5856b..098872e08a 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -55,7 +55,7 @@ func New(opts ...Option) Cache { counter: fstree.NewSimpleCounter(), options: options{ - log: &logger.Logger{Logger: zap.NewNop()}, + log: logger.NewLoggerWrapper(zap.NewNop()), maxObjectSize: defaultMaxObjectSize, workersCount: defaultFlushWorkersCount, maxCacheSize: defaultMaxCacheSize, diff --git a/pkg/local_object_storage/writecache/delete.go b/pkg/local_object_storage/writecache/delete.go index dda284439e..94a0a40db9 100644 --- a/pkg/local_object_storage/writecache/delete.go +++ b/pkg/local_object_storage/writecache/delete.go @@ -46,7 +46,7 @@ func (c *cache) Delete(ctx context.Context, addr oid.Address) error { storageType = StorageTypeFSTree _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr}) if err == nil { - storagelog.Write(c.log, + storagelog.Write(ctx, c.log, storagelog.AddressField(addr.EncodeToString()), storagelog.StorageTypeField(wcStorageType), storagelog.OpField("fstree DELETE"), diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index bfa6aacb0f..123eb4abc6 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -80,7 +80,7 @@ func (c *cache) pushToFlushQueue(ctx context.Context, fl *flushLimiter) { } }) if err != nil { - c.log.Warn(logs.BlobstorErrorOccurredDuringTheIteration, zap.Error(err)) + c.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.Error(err)) } c.modeMtx.RUnlock() @@ -130,7 +130,7 @@ func (c *cache) reportFlushError(msg string, addr string, err error) { if c.reportError != nil { c.reportError(msg, err) } else { - c.log.Error(msg, + c.log.Error(context.Background(), msg, zap.String("address", addr), zap.Error(err)) } diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index 59a4e4895d..26f47e82ef 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -40,7 +40,7 @@ func TestFlush(t *testing.T) { cnt := &atomic.Uint32{} return WithReportErrorFunc(func(msg string, err error) { cnt.Add(1) - testlogger.Warn(msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) + testlogger.Warn(context.Background(), msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) }), cnt } diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index d12dd603bc..26658e9b8c 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -60,7 +60,7 @@ func (c *cache) setMode(ctx context.Context, m mode.Mode, prm setModePrm) error // flushCh is populated by `flush` with `modeMtx` taken, thus waiting until it is empty // guarantees that there are no in-fly operations. for len(c.flushCh) != 0 { - c.log.Info(logs.WritecacheWaitingForChannelsToFlush) + c.log.Info(ctx, logs.WritecacheWaitingForChannelsToFlush) time.Sleep(time.Second) } @@ -110,7 +110,7 @@ func (c *cache) closeStorage(ctx context.Context, shrink bool) error { return fmt.Errorf("failed to remove write-cache files: %w", err) } } else { - c.log.Info(logs.WritecacheShrinkSkippedNotEmpty) + c.log.Info(ctx, logs.WritecacheShrinkSkippedNotEmpty) } return nil } diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index 66ac7805c8..25c1694a8b 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -41,7 +41,7 @@ type options struct { // WithLogger sets logger. func WithLogger(log *logger.Logger) Option { return func(o *options) { - o.log = &logger.Logger{Logger: log.With(zap.String("component", "WriteCache"))} + o.log = log.With(zap.String("component", "WriteCache")) } } diff --git a/pkg/local_object_storage/writecache/put.go b/pkg/local_object_storage/writecache/put.go index c53067beac..7da5c4d3a0 100644 --- a/pkg/local_object_storage/writecache/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -68,7 +68,7 @@ func (c *cache) putBig(ctx context.Context, prm common.PutPrm) error { return err } - storagelog.Write(c.log, + storagelog.Write(ctx, c.log, storagelog.AddressField(prm.Address.EncodeToString()), storagelog.StorageTypeField(wcStorageType), storagelog.OpField("fstree PUT"), diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index 2e52e5b208..a0e236cb73 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -43,9 +43,9 @@ func (c *cache) openStore(mod mode.ComponentMode) error { func (c *cache) deleteFromDisk(ctx context.Context, addr oid.Address, size uint64) { _, err := c.fsTree.Delete(ctx, common.DeletePrm{Address: addr, Size: size}) if err != nil && !client.IsErrObjectNotFound(err) { - c.log.Error(logs.WritecacheCantRemoveObjectFromWritecache, zap.Error(err)) + c.log.Error(ctx, logs.WritecacheCantRemoveObjectFromWritecache, zap.Error(err)) } else if err == nil { - storagelog.Write(c.log, + storagelog.Write(ctx, c.log, storagelog.AddressField(addr.EncodeToString()), storagelog.StorageTypeField(wcStorageType), storagelog.OpField("fstree DELETE"), diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 933f1039f0..12c0e08421 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -199,7 +199,7 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, return 0, fmt.Errorf("could not invoke %s: %w", method, err) } - c.logger.Debug(logs.ClientNeoClientInvoke, + c.logger.Debug(context.Background(), logs.ClientNeoClientInvoke, zap.String("method", method), zap.Uint32("vub", vub), zap.Stringer("tx_hash", txHash.Reverse())) @@ -328,7 +328,7 @@ func (c *Client) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error return err } - c.logger.Debug(logs.ClientNativeGasTransferInvoke, + c.logger.Debug(context.Background(), logs.ClientNativeGasTransferInvoke, zap.String("to", receiver.StringLE()), zap.Stringer("tx_hash", txHash.Reverse()), zap.Uint32("vub", vub)) @@ -362,7 +362,7 @@ func (c *Client) BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8 return err } - c.logger.Debug(logs.ClientBatchGasTransferInvoke, + c.logger.Debug(context.Background(), logs.ClientBatchGasTransferInvoke, zap.Strings("to", receiversLog), zap.Stringer("tx_hash", txHash.Reverse()), zap.Uint32("vub", vub)) @@ -389,7 +389,7 @@ func (c *Client) Wait(ctx context.Context, n uint32) error { height, err = c.rpcActor.GetBlockCount() if err != nil { - c.logger.Error(logs.ClientCantGetBlockchainHeight, + c.logger.Error(context.Background(), logs.ClientCantGetBlockchainHeight, zap.String("error", err.Error())) return nil } @@ -403,7 +403,7 @@ func (c *Client) Wait(ctx context.Context, n uint32) error { newHeight, err = c.rpcActor.GetBlockCount() if err != nil { - c.logger.Error(logs.ClientCantGetBlockchainHeight243, + c.logger.Error(context.Background(), logs.ClientCantGetBlockchainHeight243, zap.String("error", err.Error())) return nil } diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index 08d16deb45..d061747bb5 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -61,7 +61,7 @@ var ErrNoHealthyEndpoint = errors.New("no healthy endpoint") func defaultConfig() *cfg { return &cfg{ dialTimeout: defaultDialTimeout, - logger: &logger.Logger{Logger: zap.L()}, + logger: logger.NewLoggerWrapper(zap.L()), metrics: morphmetrics.NoopRegister{}, waitInterval: defaultWaitInterval, signer: &transaction.Signer{ @@ -130,10 +130,10 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er for cli.endpoints.curr, endpoint = range cli.endpoints.list { cli.client, act, err = cli.newCli(ctx, endpoint) if err != nil { - cli.logger.Warn(logs.FrostFSIRCouldntCreateRPCClientForEndpoint, + cli.logger.Warn(ctx, logs.FrostFSIRCouldntCreateRPCClientForEndpoint, zap.Error(err), zap.String("endpoint", endpoint.Address)) } else { - cli.logger.Info(logs.FrostFSIRCreatedRPCClientForEndpoint, + cli.logger.Info(ctx, logs.FrostFSIRCreatedRPCClientForEndpoint, zap.String("endpoint", endpoint.Address)) if cli.endpoints.curr > 0 && cli.cfg.switchInterval != 0 { cli.switchIsActive.Store(true) diff --git a/pkg/morph/client/multi.go b/pkg/morph/client/multi.go index 10ed215826..708d3b39f9 100644 --- a/pkg/morph/client/multi.go +++ b/pkg/morph/client/multi.go @@ -42,7 +42,7 @@ func (c *Client) SwitchRPC(ctx context.Context) bool { newEndpoint := c.endpoints.list[c.endpoints.curr] cli, act, err := c.newCli(ctx, newEndpoint) if err != nil { - c.logger.Warn(logs.ClientCouldNotEstablishConnectionToTheSwitchedRPCNode, + c.logger.Warn(ctx, logs.ClientCouldNotEstablishConnectionToTheSwitchedRPCNode, zap.String("endpoint", newEndpoint.Address), zap.Error(err), ) @@ -52,7 +52,7 @@ func (c *Client) SwitchRPC(ctx context.Context) bool { c.cache.invalidate() - c.logger.Info(logs.ClientConnectionToTheNewRPCNodeHasBeenEstablished, + c.logger.Info(ctx, logs.ClientConnectionToTheNewRPCNodeHasBeenEstablished, zap.String("endpoint", newEndpoint.Address)) c.client = cli @@ -122,7 +122,7 @@ mainLoop: cli, act, err := c.newCli(ctx, e) if err != nil { - c.logger.Warn(logs.ClientCouldNotCreateClientToTheHigherPriorityNode, + c.logger.Warn(ctx, logs.ClientCouldNotCreateClientToTheHigherPriorityNode, zap.String("endpoint", tryE), zap.Error(err), ) @@ -147,7 +147,7 @@ mainLoop: c.switchLock.Unlock() - c.logger.Info(logs.ClientSwitchedToTheHigherPriorityRPC, + c.logger.Info(ctx, logs.ClientSwitchedToTheHigherPriorityRPC, zap.String("endpoint", tryE)) return diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 2a500b31b1..58c417fb1a 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -1,6 +1,7 @@ package client import ( + "context" "crypto/elliptic" "encoding/binary" "errors" @@ -201,7 +202,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (util.Uint256, // Transaction is already in mempool waiting to be processed. // This is an expected situation if we restart the service. - c.logger.Info(logs.ClientNotaryDepositHasAlreadyBeenMade, + c.logger.Info(context.Background(), logs.ClientNotaryDepositHasAlreadyBeenMade, zap.Int64("amount", int64(amount)), zap.Int64("expire_at", till), zap.Uint32("vub", vub), @@ -209,7 +210,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (util.Uint256, return util.Uint256{}, 0, nil } - c.logger.Info(logs.ClientNotaryDepositInvoke, + c.logger.Info(context.Background(), logs.ClientNotaryDepositInvoke, zap.Int64("amount", int64(amount)), zap.Int64("expire_at", till), zap.Uint32("vub", vub), @@ -429,7 +430,7 @@ func (c *Client) NotarySignAndInvokeTX(mainTx *transaction.Transaction) error { return err } - c.logger.Debug(logs.ClientNotaryRequestWithPreparedMainTXInvoked, + c.logger.Debug(context.Background(), logs.ClientNotaryRequestWithPreparedMainTXInvoked, zap.String("tx_hash", mainH.StringLE()), zap.Uint32("valid_until_block", untilActual), zap.String("fallback_hash", fbH.StringLE())) @@ -485,7 +486,7 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint return 0, err } - c.logger.Debug(logs.ClientNotaryRequestInvoked, + c.logger.Debug(context.Background(), logs.ClientNotaryRequestInvoked, zap.String("method", method), zap.Uint32("valid_until_block", untilActual), zap.String("tx_hash", mainH.StringLE()), diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index dd3c7d2164..03bba8ab90 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -144,7 +144,7 @@ func (l *listener) Listen(ctx context.Context) { l.wg.Add(1) defer l.wg.Done() if err := l.listen(ctx, nil); err != nil { - l.log.Error(logs.EventCouldNotStartListenToEvents, + l.log.Error(ctx, logs.EventCouldNotStartListenToEvents, zap.String("error", err.Error()), ) } @@ -162,7 +162,7 @@ func (l *listener) ListenWithError(ctx context.Context, intError chan<- error) { l.wg.Add(1) defer l.wg.Done() if err := l.listen(ctx, intError); err != nil { - l.log.Error(logs.EventCouldNotStartListenToEvents, + l.log.Error(ctx, logs.EventCouldNotStartListenToEvents, zap.String("error", err.Error()), ) l.sendError(ctx, intError, err) @@ -234,7 +234,7 @@ func (l *listener) sendError(ctx context.Context, intErr chan<- error, err error // in the same routine when shutting down node. select { case <-ctx.Done(): - l.log.Info(logs.EventStopEventListenerByContext, + l.log.Info(ctx, logs.EventStopEventListenerByContext, zap.String("reason", ctx.Err().Error()), ) return false @@ -251,43 +251,43 @@ loop: select { case err := <-subErrCh: if !l.sendError(ctx, intErr, err) { - l.log.Error(logs.EventStopEventListenerByError, zap.Error(err)) + l.log.Error(ctx, logs.EventStopEventListenerByError, zap.Error(err)) } break loop case <-ctx.Done(): - l.log.Info(logs.EventStopEventListenerByContext, + l.log.Info(ctx, logs.EventStopEventListenerByContext, zap.String("reason", ctx.Err().Error()), ) break loop case notifyEvent, ok := <-chs.NotificationsCh: if !ok { - l.log.Warn(logs.EventStopEventListenerByNotificationChannel) + l.log.Warn(ctx, logs.EventStopEventListenerByNotificationChannel) l.sendError(ctx, intErr, errNotificationSubscrConnectionTerminated) break loop } else if notifyEvent == nil { - l.log.Warn(logs.EventNilNotificationEventWasCaught) + l.log.Warn(ctx, logs.EventNilNotificationEventWasCaught) continue loop } l.handleNotifyEvent(notifyEvent) case notaryEvent, ok := <-chs.NotaryRequestsCh: if !ok { - l.log.Warn(logs.EventStopEventListenerByNotaryChannel) + l.log.Warn(ctx, logs.EventStopEventListenerByNotaryChannel) l.sendError(ctx, intErr, errNotarySubscrConnectionTerminated) break loop } else if notaryEvent == nil { - l.log.Warn(logs.EventNilNotaryEventWasCaught) + l.log.Warn(ctx, logs.EventNilNotaryEventWasCaught) continue loop } l.handleNotaryEvent(notaryEvent) case b, ok := <-chs.BlockCh: if !ok { - l.log.Warn(logs.EventStopEventListenerByBlockChannel) + l.log.Warn(ctx, logs.EventStopEventListenerByBlockChannel) l.sendError(ctx, intErr, errBlockNotificationChannelClosed) break loop } else if b == nil { - l.log.Warn(logs.EventNilBlockWasCaught) + l.log.Warn(ctx, logs.EventNilBlockWasCaught) continue loop } @@ -302,7 +302,7 @@ func (l *listener) handleBlockEvent(b *block.Block) { l.blockHandlers[i](b) } }); err != nil { - l.log.Warn(logs.EventListenerWorkerPoolDrained, + l.log.Warn(context.Background(), logs.EventListenerWorkerPoolDrained, zap.Int("capacity", l.pool.Cap())) } } @@ -311,7 +311,7 @@ func (l *listener) handleNotaryEvent(notaryEvent *result.NotaryRequestEvent) { if err := l.pool.Submit(func() { l.parseAndHandleNotary(notaryEvent) }); err != nil { - l.log.Warn(logs.EventListenerWorkerPoolDrained, + l.log.Warn(context.Background(), logs.EventListenerWorkerPoolDrained, zap.Int("capacity", l.pool.Cap())) } } @@ -320,7 +320,7 @@ func (l *listener) handleNotifyEvent(notifyEvent *state.ContainedNotificationEve if err := l.pool.Submit(func() { l.parseAndHandleNotification(notifyEvent) }); err != nil { - l.log.Warn(logs.EventListenerWorkerPoolDrained, + l.log.Warn(context.Background(), logs.EventListenerWorkerPoolDrained, zap.Int("capacity", l.pool.Cap())) } } @@ -347,7 +347,7 @@ func (l *listener) parseAndHandleNotification(notifyEvent *state.ContainedNotifi l.mtx.RUnlock() if !ok { - log.Debug(logs.EventEventParserNotSet) + log.Debug(context.Background(), logs.EventEventParserNotSet) return } @@ -355,7 +355,7 @@ func (l *listener) parseAndHandleNotification(notifyEvent *state.ContainedNotifi // parse the notification event event, err := parser(notifyEvent) if err != nil { - log.Warn(logs.EventCouldNotParseNotificationEvent, + log.Warn(context.Background(), logs.EventCouldNotParseNotificationEvent, zap.String("error", err.Error()), ) @@ -368,7 +368,7 @@ func (l *listener) parseAndHandleNotification(notifyEvent *state.ContainedNotifi l.mtx.RUnlock() if len(handlers) == 0 { - log.Info(logs.EventNotificationHandlersForParsedNotificationEventWereNotRegistered, + log.Info(context.Background(), logs.EventNotificationHandlersForParsedNotificationEventWereNotRegistered, zap.Any("event", event), ) @@ -388,13 +388,13 @@ func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { switch { case errors.Is(err, ErrTXAlreadyHandled): case errors.As(err, &expErr): - l.log.Warn(logs.EventSkipExpiredMainTXNotaryEvent, + l.log.Warn(context.Background(), logs.EventSkipExpiredMainTXNotaryEvent, zap.String("error", err.Error()), zap.Uint32("current_block_height", expErr.CurrentBlockHeight), zap.Uint32("fallback_tx_not_valid_before_height", expErr.FallbackTXNotValidBeforeHeight), ) default: - l.log.Warn(logs.EventCouldNotPrepareAndValidateNotaryEvent, + l.log.Warn(context.Background(), logs.EventCouldNotPrepareAndValidateNotaryEvent, zap.String("error", err.Error()), ) } @@ -418,7 +418,7 @@ func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { l.mtx.RUnlock() if !ok { - log.Debug(logs.EventNotaryParserNotSet) + log.Debug(context.Background(), logs.EventNotaryParserNotSet) return } @@ -426,7 +426,7 @@ func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { // parse the notary event event, err := parser(notaryEvent) if err != nil { - log.Warn(logs.EventCouldNotParseNotaryEvent, + log.Warn(context.Background(), logs.EventCouldNotParseNotaryEvent, zap.String("error", err.Error()), ) @@ -439,7 +439,7 @@ func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { l.mtx.RUnlock() if !ok { - log.Info(logs.EventNotaryHandlersForParsedNotificationEventWereNotRegistered, + log.Info(context.Background(), logs.EventNotaryHandlersForParsedNotificationEventWereNotRegistered, zap.Any("event", event), ) @@ -461,7 +461,7 @@ func (l *listener) SetNotificationParser(pi NotificationParserInfo) { parser := pi.parser() if parser == nil { - log.Info(logs.EventIgnoreNilEventParser) + log.Info(context.Background(), logs.EventIgnoreNilEventParser) return } @@ -470,7 +470,7 @@ func (l *listener) SetNotificationParser(pi NotificationParserInfo) { // check if the listener was started if l.started { - log.Warn(logs.EventListenerHasBeenAlreadyStartedIgnoreParser) + log.Warn(context.Background(), logs.EventListenerHasBeenAlreadyStartedIgnoreParser) return } @@ -479,7 +479,7 @@ func (l *listener) SetNotificationParser(pi NotificationParserInfo) { l.notificationParsers[pi.scriptHashWithType] = pi.parser() } - log.Debug(logs.EventRegisteredNewEventParser) + log.Debug(context.Background(), logs.EventRegisteredNewEventParser) } // RegisterNotificationHandler registers the handler for particular notification event of contract. @@ -494,7 +494,7 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) { handler := hi.Handler() if handler == nil { - log.Warn(logs.EventIgnoreNilEventHandler) + log.Warn(context.Background(), logs.EventIgnoreNilEventHandler) return } @@ -504,7 +504,7 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) { l.mtx.RUnlock() if !ok { - log.Warn(logs.EventIgnoreHandlerOfEventWoParser) + log.Warn(context.Background(), logs.EventIgnoreHandlerOfEventWoParser) return } @@ -516,7 +516,7 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) { ) l.mtx.Unlock() - log.Debug(logs.EventRegisteredNewEventHandler) + log.Debug(context.Background(), logs.EventRegisteredNewEventHandler) } // EnableNotarySupport enables notary request listening. Passed hash is @@ -557,7 +557,7 @@ func (l *listener) SetNotaryParser(pi NotaryParserInfo) { parser := pi.parser() if parser == nil { - log.Info(logs.EventIgnoreNilNotaryEventParser) + log.Info(context.Background(), logs.EventIgnoreNilNotaryEventParser) return } @@ -566,7 +566,7 @@ func (l *listener) SetNotaryParser(pi NotaryParserInfo) { // check if the listener was started if l.started { - log.Warn(logs.EventListenerHasBeenAlreadyStartedIgnoreNotaryParser) + log.Warn(context.Background(), logs.EventListenerHasBeenAlreadyStartedIgnoreNotaryParser) return } @@ -575,7 +575,7 @@ func (l *listener) SetNotaryParser(pi NotaryParserInfo) { l.notaryParsers[pi.notaryRequestTypes] = pi.parser() } - log.Info(logs.EventRegisteredNewEventParser) + log.Info(context.Background(), logs.EventRegisteredNewEventParser) } // RegisterNotaryHandler registers the handler for particular notification notary request event. @@ -595,7 +595,7 @@ func (l *listener) RegisterNotaryHandler(hi NotaryHandlerInfo) { handler := hi.Handler() if handler == nil { - log.Warn(logs.EventIgnoreNilNotaryEventHandler) + log.Warn(context.Background(), logs.EventIgnoreNilNotaryEventHandler) return } @@ -605,7 +605,7 @@ func (l *listener) RegisterNotaryHandler(hi NotaryHandlerInfo) { l.mtx.RUnlock() if !ok { - log.Warn(logs.EventIgnoreHandlerOfNotaryEventWoParser) + log.Warn(context.Background(), logs.EventIgnoreHandlerOfNotaryEventWoParser) return } @@ -614,7 +614,7 @@ func (l *listener) RegisterNotaryHandler(hi NotaryHandlerInfo) { l.notaryHandlers[hi.notaryRequestTypes] = hi.Handler() l.mtx.Unlock() - log.Info(logs.EventRegisteredNewEventHandler) + log.Info(context.Background(), logs.EventRegisteredNewEventHandler) } // Stop closes subscription channel with remote neo node. @@ -628,7 +628,7 @@ func (l *listener) Stop() { func (l *listener) RegisterBlockHandler(handler BlockHandler) { if handler == nil { - l.log.Warn(logs.EventIgnoreNilBlockHandler) + l.log.Warn(context.Background(), logs.EventIgnoreNilBlockHandler) return } diff --git a/pkg/morph/event/utils.go b/pkg/morph/event/utils.go index f3b6443fbf..31bbf4432e 100644 --- a/pkg/morph/event/utils.go +++ b/pkg/morph/event/utils.go @@ -1,6 +1,7 @@ package event import ( + "context" "errors" "fmt" @@ -89,7 +90,7 @@ func WorkerPoolHandler(w util2.WorkerPool, h Handler, log *logger.Logger) Handle h(e) }) if err != nil { - log.Warn(logs.EventCouldNotSubmitHandlerToWorkerPool, + log.Warn(context.Background(), logs.EventCouldNotSubmitHandlerToWorkerPool, zap.String("error", err.Error()), ) } diff --git a/pkg/morph/subscriber/subscriber.go b/pkg/morph/subscriber/subscriber.go index ee5466a7de..3a2da67573 100644 --- a/pkg/morph/subscriber/subscriber.go +++ b/pkg/morph/subscriber/subscriber.go @@ -245,9 +245,9 @@ routeloop: } func (s *subscriber) switchEndpoint(ctx context.Context, finishCh chan<- bool) bool { - s.log.Info(logs.RPConnectionLost) + s.log.Info(ctx, logs.RPConnectionLost) if !s.client.SwitchRPC(ctx) { - s.log.Error(logs.RPCNodeSwitchFailure) + s.log.Error(ctx, logs.RPCNodeSwitchFailure) return false } @@ -304,7 +304,7 @@ func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotific if s.subscribedToNewBlocks { _, err = s.client.ReceiveBlocks(blCh) if err != nil { - s.log.Error(logs.ClientCouldNotRestoreBlockSubscriptionAfterRPCSwitch, zap.Error(err)) + s.log.Error(context.Background(), logs.ClientCouldNotRestoreBlockSubscriptionAfterRPCSwitch, zap.Error(err)) return false } } @@ -313,7 +313,7 @@ func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotific for contract := range s.subscribedEvents { _, err = s.client.ReceiveExecutionNotifications(contract, notifCh) if err != nil { - s.log.Error(logs.ClientCouldNotRestoreNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) + s.log.Error(context.Background(), logs.ClientCouldNotRestoreNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) return false } } @@ -322,7 +322,7 @@ func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotific for signer := range s.subscribedNotaryEvents { _, err = s.client.ReceiveNotaryRequests(signer, notaryCh) if err != nil { - s.log.Error(logs.ClientCouldNotRestoreNotaryNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) + s.log.Error(context.Background(), logs.ClientCouldNotRestoreNotaryNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) return false } } diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go index 86f9cb8935..cc792e23d2 100644 --- a/pkg/services/apemanager/executor.go +++ b/pkg/services/apemanager/executor.go @@ -53,7 +53,7 @@ func New(cnrSrc containercore.Source, contractStorage ape_contract.ProxyAdaptedC } if s.log == nil { - s.log = &logger.Logger{Logger: zap.NewNop()} + s.log = logger.NewLoggerWrapper(zap.NewNop()) } return s diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 56748b08c5..93ad3dc460 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -64,7 +64,7 @@ func New(next object.ServiceServer, opts ...Option, ) Service { cfg := &cfg{ - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), next: next, nm: nm, irFetcher: irf, diff --git a/pkg/services/object/common/writer/common.go b/pkg/services/object/common/writer/common.go index 6689557ee8..8b92d34edf 100644 --- a/pkg/services/object/common/writer/common.go +++ b/pkg/services/object/common/writer/common.go @@ -59,7 +59,7 @@ func (n *NodeIterator) ForEachNode(ctx context.Context, f func(context.Context, if n.Traversal.submitPrimaryPlacementFinish() { err := n.ForEachNode(ctx, f) if err != nil { - n.cfg.Logger.Error(logs.PutAdditionalContainerBroadcastFailure, zap.Error(err)) + n.cfg.Logger.Error(ctx, logs.PutAdditionalContainerBroadcastFailure, zap.Error(err)) // we don't fail primary operation because of broadcast failure } } diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index 571bae7bbe..64115b86b2 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -162,7 +162,7 @@ func (e *ECWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index if err == nil { return nil } - e.Config.Logger.Logger.Warn(logs.ECFailedToSendToContainerNode, zap.Stringers("address_group", info.AddressGroup())) + e.Config.Logger.Warn(ctx, logs.ECFailedToSendToContainerNode, zap.Stringers("address_group", info.AddressGroup())) lastErr = err } } @@ -275,7 +275,7 @@ func (e *ECWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx if err == nil { return nil } - e.Config.Logger.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + e.Config.Logger.Warn(ctx, logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) @@ -299,7 +299,7 @@ func (e *ECWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx if err == nil { return nil } - e.Config.Logger.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + e.Config.Logger.Warn(ctx, logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) @@ -323,7 +323,7 @@ func (e *ECWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx if err == nil { return nil } - e.Config.Logger.Warn(logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), + e.Config.Logger.Warn(ctx, logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) diff --git a/pkg/services/object/delete/delete.go b/pkg/services/object/delete/delete.go index 88454625de..8aaff670c3 100644 --- a/pkg/services/object/delete/delete.go +++ b/pkg/services/object/delete/delete.go @@ -33,13 +33,13 @@ func (s *Service) Delete(ctx context.Context, prm Prm) error { } func (exec *execCtx) execute(ctx context.Context) error { - exec.log.Debug(logs.ServingRequest) + exec.log.Debug(ctx, logs.ServingRequest) if err := exec.executeLocal(ctx); err != nil { - exec.log.Debug(logs.OperationFinishedWithError, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.OperationFinishedWithError, zap.String("error", err.Error())) return err } - exec.log.Debug(logs.OperationFinishedSuccessfully) + exec.log.Debug(ctx, logs.OperationFinishedSuccessfully) return nil } diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index ec771320e6..36a17bde2c 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -34,13 +34,13 @@ type execCtx struct { } func (exec *execCtx) setLogger(l *logger.Logger) { - exec.log = &logger.Logger{Logger: l.With( + exec.log = l.With( zap.String("request", "DELETE"), zap.Stringer("address", exec.address()), zap.Bool("local", exec.isLocal()), zap.Bool("with session", exec.prm.common.SessionToken() != nil), zap.Bool("with bearer", exec.prm.common.BearerToken() != nil), - )} + ) } func (exec *execCtx) isLocal() bool { @@ -83,16 +83,16 @@ func (exec *execCtx) formExtendedInfo(ctx context.Context) error { exec.splitInfo = errSplitInfo.SplitInfo() exec.tombstone.SetSplitID(exec.splitInfo.SplitID()) - exec.log.Debug(logs.DeleteSplitInfoSuccessfullyFormedCollectingMembers) + exec.log.Debug(ctx, logs.DeleteSplitInfoSuccessfullyFormedCollectingMembers) if err := exec.collectMembers(ctx); err != nil { return err } - exec.log.Debug(logs.DeleteMembersSuccessfullyCollected) + exec.log.Debug(ctx, logs.DeleteMembersSuccessfullyCollected) return nil case errors.As(err, &errECInfo): - exec.log.Debug(logs.DeleteECObjectReceived) + exec.log.Debug(ctx, logs.DeleteECObjectReceived) return nil } @@ -108,7 +108,7 @@ func (exec *execCtx) formExtendedInfo(ctx context.Context) error { func (exec *execCtx) collectMembers(ctx context.Context) error { if exec.splitInfo == nil { - exec.log.Debug(logs.DeleteNoSplitInfoObjectIsPHY) + exec.log.Debug(ctx, logs.DeleteNoSplitInfoObjectIsPHY) return nil } @@ -131,7 +131,7 @@ func (exec *execCtx) collectMembers(ctx context.Context) error { func (exec *execCtx) collectChain(ctx context.Context) error { var chain []oid.ID - exec.log.Debug(logs.DeleteAssemblingChain) + exec.log.Debug(ctx, logs.DeleteAssemblingChain) for prev, withPrev := exec.splitInfo.LastPart(); withPrev; { chain = append(chain, prev) @@ -152,7 +152,7 @@ func (exec *execCtx) collectChain(ctx context.Context) error { } func (exec *execCtx) collectChildren(ctx context.Context) error { - exec.log.Debug(logs.DeleteCollectingChildren) + exec.log.Debug(ctx, logs.DeleteCollectingChildren) children, err := exec.svc.header.children(ctx, exec) if err != nil { @@ -165,7 +165,7 @@ func (exec *execCtx) collectChildren(ctx context.Context) error { } func (exec *execCtx) supplementBySplitID(ctx context.Context) error { - exec.log.Debug(logs.DeleteSupplementBySplitID) + exec.log.Debug(ctx, logs.DeleteSupplementBySplitID) chain, err := exec.svc.searcher.splitMembers(ctx, exec) if err != nil { diff --git a/pkg/services/object/delete/local.go b/pkg/services/object/delete/local.go index 2c3c47f491..01b2d9b3f2 100644 --- a/pkg/services/object/delete/local.go +++ b/pkg/services/object/delete/local.go @@ -10,13 +10,13 @@ import ( ) func (exec *execCtx) executeLocal(ctx context.Context) error { - exec.log.Debug(logs.DeleteFormingTombstoneStructure) + exec.log.Debug(ctx, logs.DeleteFormingTombstoneStructure) if err := exec.formTombstone(ctx); err != nil { return err } - exec.log.Debug(logs.DeleteTombstoneStructureSuccessfullyFormedSaving) + exec.log.Debug(ctx, logs.DeleteTombstoneStructureSuccessfullyFormedSaving) return exec.saveTombstone(ctx) } @@ -33,7 +33,7 @@ func (exec *execCtx) formTombstone(ctx context.Context) error { ) exec.addMembers([]oid.ID{exec.address().Object()}) - exec.log.Debug(logs.DeleteFormingSplitInfo) + exec.log.Debug(ctx, logs.DeleteFormingSplitInfo) if err := exec.formExtendedInfo(ctx); err != nil { return fmt.Errorf("form extended info: %w", err) diff --git a/pkg/services/object/delete/service.go b/pkg/services/object/delete/service.go index e4f7a8c502..867d3f4ef3 100644 --- a/pkg/services/object/delete/service.go +++ b/pkg/services/object/delete/service.go @@ -72,7 +72,7 @@ func New(gs *getsvc.Service, opts ...Option, ) *Service { c := &cfg{ - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), header: &headSvcWrapper{s: gs}, searcher: &searchSvcWrapper{s: ss}, placer: &putSvcWrapper{s: ps}, @@ -92,6 +92,6 @@ func New(gs *getsvc.Service, // WithLogger returns option to specify Delete service's logger. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = &logger.Logger{Logger: l.With(zap.String("component", "objectSDK.Delete service"))} + c.log = l.With(zap.String("component", "objectSDK.Delete service")) } } diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index 9f17f1e4c3..e164627d2b 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -13,7 +13,7 @@ import ( func (r *request) assemble(ctx context.Context) { if !r.canAssembleComplexObject() { - r.log.Debug(logs.GetCanNotAssembleTheObject) + r.log.Debug(ctx, logs.GetCanNotAssembleTheObject) return } @@ -35,23 +35,23 @@ func (r *request) assemble(ctx context.Context) { // `execCtx` so it should be disabled there. r.disableForwarding() - r.log.Debug(logs.GetTryingToAssembleTheObject) + r.log.Debug(ctx, logs.GetTryingToAssembleTheObject) r.prm.common = r.prm.common.WithLocalOnly(false) assembler := newAssembler(r.address(), r.splitInfo(), r.ctxRange(), r, r.headOnly()) - r.log.Debug(logs.GetAssemblingSplittedObject, + r.log.Debug(ctx, logs.GetAssemblingSplittedObject, zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) - defer r.log.Debug(logs.GetAssemblingSplittedObjectCompleted, + defer r.log.Debug(ctx, logs.GetAssemblingSplittedObjectCompleted, zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) obj, err := assembler.Assemble(ctx, r.prm.objWriter) if err != nil { - r.log.Warn(logs.GetFailedToAssembleSplittedObject, + r.log.Warn(ctx, logs.GetFailedToAssembleSplittedObject, zap.Error(err), zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), diff --git a/pkg/services/object/get/assembleec.go b/pkg/services/object/get/assembleec.go index 03f913bbf1..8ab423c878 100644 --- a/pkg/services/object/get/assembleec.go +++ b/pkg/services/object/get/assembleec.go @@ -12,7 +12,7 @@ import ( func (r *request) assembleEC(ctx context.Context) { if r.isRaw() { - r.log.Debug(logs.GetCanNotAssembleTheObject) + r.log.Debug(ctx, logs.GetCanNotAssembleTheObject) return } @@ -34,7 +34,7 @@ func (r *request) assembleEC(ctx context.Context) { // `execCtx` so it should be disabled there. r.disableForwarding() - r.log.Debug(logs.GetTryingToAssembleTheECObject) + r.log.Debug(ctx, logs.GetTryingToAssembleTheECObject) // initialize epoch number ok := r.initEpoch() @@ -45,18 +45,18 @@ func (r *request) assembleEC(ctx context.Context) { r.prm.common = r.prm.common.WithLocalOnly(false) assembler := newAssemblerEC(r.address(), r.infoEC, r.ctxRange(), r, r.localStorage, r.log, r.headOnly(), r.traverserGenerator, r.curProcEpoch) - r.log.Debug(logs.GetAssemblingECObject, + r.log.Debug(ctx, logs.GetAssemblingECObject, zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) - defer r.log.Debug(logs.GetAssemblingECObjectCompleted, + defer r.log.Debug(ctx, logs.GetAssemblingECObjectCompleted, zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), ) obj, err := assembler.Assemble(ctx, r.prm.objWriter) if err != nil && !errors.As(err, new(*objectSDK.ECInfoError)) { - r.log.Warn(logs.GetFailedToAssembleECObject, + r.log.Warn(ctx, logs.GetFailedToAssembleECObject, zap.Error(err), zap.Uint64("range_offset", r.ctxRange().GetOffset()), zap.Uint64("range_length", r.ctxRange().GetLength()), diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index 44d9af3a2d..b0895e13ec 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -155,7 +155,7 @@ func (a *assemblerec) retrieveParts(ctx context.Context, trav *placement.Travers parts, err := a.processECNodesRequests(ctx, remoteNodes, dataCount, parityCount) if err != nil { - a.log.Debug(logs.GetUnableToGetAllPartsECObject, zap.Error(err)) + a.log.Debug(ctx, logs.GetUnableToGetAllPartsECObject, zap.Error(err)) } return parts } @@ -229,7 +229,7 @@ func (a *assemblerec) tryGetChunkFromLocalStorage(ctx context.Context, ch object var objID oid.ID err := objID.ReadFromV2(ch.ID) if err != nil { - a.log.Error(logs.GetUnableToHeadPartECObject, zap.String("node", "local"), zap.Uint32("part_index", ch.Index), zap.Error(fmt.Errorf("invalid object ID: %w", err))) + a.log.Error(ctx, logs.GetUnableToHeadPartECObject, zap.String("node", "local"), zap.Uint32("part_index", ch.Index), zap.Error(fmt.Errorf("invalid object ID: %w", err))) return nil } var addr oid.Address @@ -239,13 +239,13 @@ func (a *assemblerec) tryGetChunkFromLocalStorage(ctx context.Context, ch object if a.head { object, err = a.localStorage.Head(ctx, addr, false) if err != nil { - a.log.Warn(logs.GetUnableToHeadPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) + a.log.Warn(ctx, logs.GetUnableToHeadPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) return nil } } else { object, err = a.localStorage.Get(ctx, addr) if err != nil { - a.log.Warn(logs.GetUnableToGetPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) + a.log.Warn(ctx, logs.GetUnableToGetPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) return nil } } @@ -259,11 +259,11 @@ func (a *assemblerec) tryGetChunkListFromNode(ctx context.Context, node client.N var errECInfo *objectSDK.ECInfoError _, err := a.remoteStorage.headObjectFromNode(ctx, a.addr, node, true) if err == nil { - a.log.Error(logs.GetUnexpectedECObject, zap.String("node", hex.EncodeToString(node.PublicKey()))) + a.log.Error(ctx, logs.GetUnexpectedECObject, zap.String("node", hex.EncodeToString(node.PublicKey()))) return nil } if !errors.As(err, &errECInfo) { - a.log.Warn(logs.GetUnableToHeadPartsECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) + a.log.Warn(ctx, logs.GetUnableToHeadPartsECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Error(err)) return nil } result := make([]objectSDK.ECChunk, 0, len(errECInfo.ECInfo().Chunks)) @@ -277,7 +277,7 @@ func (a *assemblerec) tryGetChunkFromRemoteStorage(ctx context.Context, node cli var objID oid.ID err := objID.ReadFromV2(ch.ID) if err != nil { - a.log.Error(logs.GetUnableToHeadPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Uint32("part_index", ch.Index), zap.Error(fmt.Errorf("invalid object ID: %w", err))) + a.log.Error(ctx, logs.GetUnableToHeadPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Uint32("part_index", ch.Index), zap.Error(fmt.Errorf("invalid object ID: %w", err))) return nil } var addr oid.Address @@ -287,13 +287,13 @@ func (a *assemblerec) tryGetChunkFromRemoteStorage(ctx context.Context, node cli if a.head { object, err = a.remoteStorage.headObjectFromNode(ctx, addr, node, false) if err != nil { - a.log.Warn(logs.GetUnableToHeadPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) + a.log.Warn(ctx, logs.GetUnableToHeadPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) return nil } } else { object, err = a.remoteStorage.getObjectFromNode(ctx, addr, node) if err != nil { - a.log.Warn(logs.GetUnableToGetPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) + a.log.Warn(ctx, logs.GetUnableToGetPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) return nil } } diff --git a/pkg/services/object/get/container.go b/pkg/services/object/get/container.go index 034768c81b..2b84c5b32f 100644 --- a/pkg/services/object/get/container.go +++ b/pkg/services/object/get/container.go @@ -10,13 +10,13 @@ import ( func (r *request) executeOnContainer(ctx context.Context) { if r.isLocal() { - r.log.Debug(logs.GetReturnResultDirectly) + r.log.Debug(ctx, logs.GetReturnResultDirectly) return } lookupDepth := r.netmapLookupDepth() - r.log.Debug(logs.TryingToExecuteInContainer, + r.log.Debug(ctx, logs.TryingToExecuteInContainer, zap.Uint64("netmap lookup depth", lookupDepth), ) @@ -46,7 +46,7 @@ func (r *request) executeOnContainer(ctx context.Context) { } func (r *request) processCurrentEpoch(ctx context.Context, localStatus int) bool { - r.log.Debug(logs.ProcessEpoch, + r.log.Debug(ctx, logs.ProcessEpoch, zap.Uint64("number", r.curProcEpoch), ) @@ -67,7 +67,7 @@ func (r *request) processCurrentEpoch(ctx context.Context, localStatus int) bool for { addrs := traverser.Next() if len(addrs) == 0 { - r.log.Debug(logs.NoMoreNodesAbortPlacementIteration) + r.log.Debug(ctx, logs.NoMoreNodesAbortPlacementIteration) return false } @@ -75,7 +75,7 @@ func (r *request) processCurrentEpoch(ctx context.Context, localStatus int) bool for i := range addrs { select { case <-ctx.Done(): - r.log.Debug(logs.InterruptPlacementIterationByContext, + r.log.Debug(ctx, logs.InterruptPlacementIterationByContext, zap.Error(ctx.Err()), ) @@ -91,7 +91,7 @@ func (r *request) processCurrentEpoch(ctx context.Context, localStatus int) bool client.NodeInfoFromNetmapElement(&info, addrs[i]) if r.processNode(ctx, info) { - r.log.Debug(logs.GetCompletingTheOperation) + r.log.Debug(ctx, logs.GetCompletingTheOperation) return true } } diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 03b7f8bf2f..557e9a0285 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -91,7 +91,7 @@ func (s *Service) get(ctx context.Context, prm RequestParameters) error { } func (exec *request) execute(ctx context.Context) { - exec.log.Debug(logs.ServingRequest) + exec.log.Debug(ctx, logs.ServingRequest) // perform local operation exec.executeLocal(ctx) @@ -103,23 +103,23 @@ func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) { // analyze local result switch exec.status { case statusOK: - exec.log.Debug(logs.OperationFinishedSuccessfully) + exec.log.Debug(ctx, logs.OperationFinishedSuccessfully) case statusINHUMED: - exec.log.Debug(logs.GetRequestedObjectWasMarkedAsRemoved) + exec.log.Debug(ctx, logs.GetRequestedObjectWasMarkedAsRemoved) case statusVIRTUAL: - exec.log.Debug(logs.GetRequestedObjectIsVirtual) + exec.log.Debug(ctx, logs.GetRequestedObjectIsVirtual) exec.assemble(ctx) case statusOutOfRange: - exec.log.Debug(logs.GetRequestedRangeIsOutOfObjectBounds) + exec.log.Debug(ctx, logs.GetRequestedRangeIsOutOfObjectBounds) case statusEC: - exec.log.Debug(logs.GetRequestedObjectIsEC) + exec.log.Debug(ctx, logs.GetRequestedObjectIsEC) if exec.isRaw() && execCnr { exec.executeOnContainer(ctx) exec.analyzeStatus(ctx, false) } exec.assembleEC(ctx) default: - exec.log.Debug(logs.OperationFinishedWithError, + exec.log.Debug(ctx, logs.OperationFinishedWithError, zap.Error(exec.err), ) var errAccessDenied *apistatus.ObjectAccessDenied diff --git a/pkg/services/object/get/local.go b/pkg/services/object/get/local.go index 1cd5e549c7..cfabb082f2 100644 --- a/pkg/services/object/get/local.go +++ b/pkg/services/object/get/local.go @@ -31,7 +31,7 @@ func (r *request) executeLocal(ctx context.Context) { r.status = statusUndefined r.err = err - r.log.Debug(logs.GetLocalGetFailed, zap.Error(err)) + r.log.Debug(ctx, logs.GetLocalGetFailed, zap.Error(err)) case err == nil: r.status = statusOK r.err = nil diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index f2639f8e67..b6a83fd0cf 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -18,7 +18,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { ctx, span := tracing.StartSpanFromContext(ctx, "getService.processNode") defer span.End() - r.log.Debug(logs.ProcessingNode, zap.String("node_key", hex.EncodeToString(info.PublicKey()))) + r.log.Debug(ctx, logs.ProcessingNode, zap.String("node_key", hex.EncodeToString(info.PublicKey()))) rs, ok := r.getRemoteStorage(info) if !ok { @@ -35,7 +35,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { switch { default: - r.log.Debug(logs.GetRemoteCallFailed, zap.Error(err)) + r.log.Debug(ctx, logs.GetRemoteCallFailed, zap.Error(err)) if r.status != statusEC { // for raw requests, continue to collect other parts r.status = statusUndefined diff --git a/pkg/services/object/get/request.go b/pkg/services/object/get/request.go index 1a7a43a351..bba767d2d8 100644 --- a/pkg/services/object/get/request.go +++ b/pkg/services/object/get/request.go @@ -47,14 +47,14 @@ func (r *request) setLogger(l *logger.Logger) { req = "GET_RANGE" } - r.log = &logger.Logger{Logger: l.With( + r.log = l.With( zap.String("request", req), zap.Stringer("address", r.address()), zap.Bool("raw", r.isRaw()), zap.Bool("local", r.isLocal()), zap.Bool("with session", r.prm.common.SessionToken() != nil), zap.Bool("with bearer", r.prm.common.BearerToken() != nil), - )} + ) } func (r *request) isLocal() bool { @@ -129,7 +129,7 @@ func (r *request) initEpoch() bool { r.status = statusUndefined r.err = err - r.log.Debug(logs.CouldNotGetCurrentEpochNumber, zap.Error(err)) + r.log.Debug(context.Background(), logs.CouldNotGetCurrentEpochNumber, zap.Error(err)) return false case err == nil: @@ -148,7 +148,7 @@ func (r *request) generateTraverser(addr oid.Address) (*placement.Traverser, boo r.status = statusUndefined r.err = err - r.log.Debug(logs.GetCouldNotGenerateContainerTraverser, zap.Error(err)) + r.log.Debug(context.Background(), logs.GetCouldNotGenerateContainerTraverser, zap.Error(err)) return nil, false case err == nil: @@ -162,7 +162,7 @@ func (r *request) getRemoteStorage(info clientcore.NodeInfo) (remoteStorage, boo r.status = statusUndefined r.err = err - r.log.Debug(logs.GetCouldNotConstructRemoteNodeClient) + r.log.Debug(context.Background(), logs.GetCouldNotConstructRemoteNodeClient) return nil, false } @@ -185,7 +185,7 @@ func (r *request) writeCollectedHeader(ctx context.Context) bool { r.status = statusUndefined r.err = err - r.log.Debug(logs.GetCouldNotWriteHeader, zap.Error(err)) + r.log.Debug(ctx, logs.GetCouldNotWriteHeader, zap.Error(err)) case err == nil: r.status = statusOK r.err = nil @@ -206,7 +206,7 @@ func (r *request) writeObjectPayload(ctx context.Context, obj *objectSDK.Object) r.status = statusUndefined r.err = err - r.log.Debug(logs.GetCouldNotWritePayloadChunk, zap.Error(err)) + r.log.Debug(ctx, logs.GetCouldNotWritePayloadChunk, zap.Error(err)) case err == nil: r.status = statusOK r.err = nil diff --git a/pkg/services/object/get/service.go b/pkg/services/object/get/service.go index 3413abeb7d..9ec10b5f27 100644 --- a/pkg/services/object/get/service.go +++ b/pkg/services/object/get/service.go @@ -34,7 +34,7 @@ func New( result := &Service{ keyStore: ks, epochSource: es, - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), localStorage: &engineLocalStorage{ engine: e, }, @@ -53,6 +53,6 @@ func New( // WithLogger returns option to specify Get service's logger. func WithLogger(l *logger.Logger) Option { return func(s *Service) { - s.log = &logger.Logger{Logger: l.With(zap.String("component", "Object.Get service"))} + s.log = l.With(zap.String("component", "Object.Get service")) } } diff --git a/pkg/services/object/get/v2/get_range_hash.go b/pkg/services/object/get/v2/get_range_hash.go index e8e82ddd9f..7d26a38c32 100644 --- a/pkg/services/object/get/v2/get_range_hash.go +++ b/pkg/services/object/get/v2/get_range_hash.go @@ -125,14 +125,14 @@ func (s *Service) forwardGetRangeHashRequest(ctx context.Context, req *objectV2. var addrGr network.AddressGroup if err := addrGr.FromIterator(network.NodeEndpointsIterator(node)); err != nil { - s.log.Warn(logs.GetSvcV2FailedToParseNodeEndpoints, zap.String("node_public_key", hex.EncodeToString(node.PublicKey()))) + s.log.Warn(ctx, logs.GetSvcV2FailedToParseNodeEndpoints, zap.String("node_public_key", hex.EncodeToString(node.PublicKey()))) continue } var extAddr network.AddressGroup if len(node.ExternalAddresses()) > 0 { if err := extAddr.FromStringSlice(node.ExternalAddresses()); err != nil { - s.log.Warn(logs.GetSvcV2FailedToParseNodeExternalAddresses, zap.String("node_public_key", hex.EncodeToString(node.PublicKey()))) + s.log.Warn(ctx, logs.GetSvcV2FailedToParseNodeExternalAddresses, zap.String("node_public_key", hex.EncodeToString(node.PublicKey()))) continue } } @@ -150,12 +150,12 @@ func (s *Service) forwardGetRangeHashRequest(ctx context.Context, req *objectV2. if firstErr == nil { firstErr = err } - s.log.Debug(logs.GetSvcV2FailedToGetRangeHashFromNode, + s.log.Debug(ctx, logs.GetSvcV2FailedToGetRangeHashFromNode, zap.String("node_public_key", hex.EncodeToString(node.PublicKey())), zap.Stringer("address", params.address), zap.Error(err)) } - s.log.Debug(logs.GetSvcV2FailedToGetRangeHashFromAllOfContainerNodes, zap.Stringer("address", params.address), zap.Error(firstErr)) + s.log.Debug(ctx, logs.GetSvcV2FailedToGetRangeHashFromAllOfContainerNodes, zap.Stringer("address", params.address), zap.Error(firstErr)) if firstErr != nil { return nil, firstErr } diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index 24b2f0099f..fc483b74b9 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -60,7 +60,7 @@ func NewService(svc *getsvc.Service, netmapSource: netmapSource, announcedKeys: announcedKeys, contSource: contSource, - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), } for i := range opts { @@ -145,6 +145,6 @@ func (s *Service) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = &logger.Logger{Logger: l.With(zap.String("component", "Object.Get V2 service"))} + c.log = l.With(zap.String("component", "Object.Get V2 service")) } } diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index 8cf4f0d623..5cc0a57225 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -29,7 +29,7 @@ func NewService(ks *objutil.KeyStorage, c := &objectwriter.Config{ RemotePool: util.NewPseudoWorkerPool(), LocalPool: util.NewPseudoWorkerPool(), - Logger: &logger.Logger{Logger: zap.L()}, + Logger: logger.NewLoggerWrapper(zap.L()), KeyStorage: ks, ClientConstructor: cc, MaxSizeSrc: ms, diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 3a0b3901f7..36b0bd54c7 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -317,7 +317,7 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, if err != nil { objID, _ := obj.ID() cnrID, _ := obj.ContainerID() - s.Config.Logger.Warn(logs.PutSingleRedirectFailure, + s.Config.Logger.Warn(ctx, logs.PutSingleRedirectFailure, zap.Error(err), zap.Stringer("address", addr), zap.Stringer("object_id", objID), diff --git a/pkg/services/object/search/container.go b/pkg/services/object/search/container.go index 39259b0cac..999a3cc9e2 100644 --- a/pkg/services/object/search/container.go +++ b/pkg/services/object/search/container.go @@ -15,7 +15,7 @@ import ( func (exec *execCtx) executeOnContainer(ctx context.Context) error { lookupDepth := exec.netmapLookupDepth() - exec.log.Debug(logs.TryingToExecuteInContainer, + exec.log.Debug(ctx, logs.TryingToExecuteInContainer, zap.Uint64("netmap lookup depth", lookupDepth), ) @@ -44,7 +44,7 @@ func (exec *execCtx) executeOnContainer(ctx context.Context) error { } func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { - exec.log.Debug(logs.ProcessEpoch, + exec.log.Debug(ctx, logs.ProcessEpoch, zap.Uint64("number", exec.curProcEpoch), ) @@ -59,7 +59,7 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { for { addrs := traverser.Next() if len(addrs) == 0 { - exec.log.Debug(logs.NoMoreNodesAbortPlacementIteration) + exec.log.Debug(ctx, logs.NoMoreNodesAbortPlacementIteration) break } @@ -72,7 +72,7 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { defer wg.Done() select { case <-ctx.Done(): - exec.log.Debug(logs.InterruptPlacementIterationByContext, + exec.log.Debug(ctx, logs.InterruptPlacementIterationByContext, zap.String("error", ctx.Err().Error())) return default: @@ -82,17 +82,17 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { client.NodeInfoFromNetmapElement(&info, addrs[i]) - exec.log.Debug(logs.ProcessingNode, zap.String("key", hex.EncodeToString(addrs[i].PublicKey()))) + exec.log.Debug(ctx, logs.ProcessingNode, zap.String("key", hex.EncodeToString(addrs[i].PublicKey()))) c, err := exec.svc.clientConstructor.get(info) if err != nil { - exec.log.Debug(logs.SearchCouldNotConstructRemoteNodeClient, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.SearchCouldNotConstructRemoteNodeClient, zap.String("error", err.Error())) return } ids, err := c.searchObjects(ctx, exec, info) if err != nil { - exec.log.Debug(logs.SearchRemoteOperationFailed, + exec.log.Debug(ctx, logs.SearchRemoteOperationFailed, zap.String("error", err.Error())) return @@ -102,7 +102,7 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { err = exec.writeIDList(ids) mtx.Unlock() if err != nil { - exec.log.Debug(logs.SearchCouldNotWriteObjectIdentifiers, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.SearchCouldNotWriteObjectIdentifiers, zap.String("error", err.Error())) return } }(i) diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index 4a2c04ecd6..eb9635f147 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -19,13 +19,13 @@ type execCtx struct { } func (exec *execCtx) setLogger(l *logger.Logger) { - exec.log = &logger.Logger{Logger: l.With( + exec.log = l.With( zap.String("request", "SEARCH"), zap.Stringer("container", exec.containerID()), zap.Bool("local", exec.isLocal()), zap.Bool("with session", exec.prm.common.SessionToken() != nil), zap.Bool("with bearer", exec.prm.common.BearerToken() != nil), - )} + ) } func (exec *execCtx) isLocal() bool { diff --git a/pkg/services/object/search/local.go b/pkg/services/object/search/local.go index cfaed13b8c..bc59d03945 100644 --- a/pkg/services/object/search/local.go +++ b/pkg/services/object/search/local.go @@ -11,7 +11,7 @@ import ( func (exec *execCtx) executeLocal(ctx context.Context) error { ids, err := exec.svc.localStorage.search(ctx, exec) if err != nil { - exec.log.Debug(logs.SearchLocalOperationFailed, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.SearchLocalOperationFailed, zap.String("error", err.Error())) return err } diff --git a/pkg/services/object/search/search.go b/pkg/services/object/search/search.go index 4a5c414d5e..bb5c720ffb 100644 --- a/pkg/services/object/search/search.go +++ b/pkg/services/object/search/search.go @@ -20,13 +20,13 @@ func (s *Service) Search(ctx context.Context, prm Prm) error { } func (exec *execCtx) execute(ctx context.Context) error { - exec.log.Debug(logs.ServingRequest) + exec.log.Debug(ctx, logs.ServingRequest) err := exec.executeLocal(ctx) exec.logResult(err) if exec.isLocal() { - exec.log.Debug(logs.SearchReturnResultDirectly) + exec.log.Debug(ctx, logs.SearchReturnResultDirectly) return err } @@ -38,8 +38,8 @@ func (exec *execCtx) execute(ctx context.Context) error { func (exec *execCtx) logResult(err error) { switch { default: - exec.log.Debug(logs.OperationFinishedWithError, zap.String("error", err.Error())) + exec.log.Debug(context.Background(), logs.OperationFinishedWithError, zap.String("error", err.Error())) case err == nil: - exec.log.Debug(logs.OperationFinishedSuccessfully) + exec.log.Debug(context.Background(), logs.OperationFinishedSuccessfully) } } diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index 7700f78d87..77d25357a5 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -69,7 +69,7 @@ func New(e *engine.StorageEngine, opts ...Option, ) *Service { c := &cfg{ - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), clientConstructor: &clientConstructorWrapper{ constructor: cc, }, @@ -94,6 +94,6 @@ func New(e *engine.StorageEngine, // WithLogger returns option to specify Get service's logger. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = &logger.Logger{Logger: l.With(zap.String("component", "Object.Search service"))} + c.log = l.With(zap.String("component", "Object.Search service")) } } diff --git a/pkg/services/object/util/log.go b/pkg/services/object/util/log.go index 92beedaa75..5075344a4f 100644 --- a/pkg/services/object/util/log.go +++ b/pkg/services/object/util/log.go @@ -1,6 +1,8 @@ package util import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" @@ -9,7 +11,7 @@ import ( // LogServiceError writes error message of object service to provided logger. func LogServiceError(l *logger.Logger, req string, node network.AddressGroup, err error) { - l.Error(logs.UtilObjectServiceError, + l.Error(context.Background(), logs.UtilObjectServiceError, zap.String("node", network.StringifyGroup(node)), zap.String("request", req), zap.String("error", err.Error()), @@ -18,7 +20,7 @@ func LogServiceError(l *logger.Logger, req string, node network.AddressGroup, er // LogWorkerPoolError writes debug error message of object worker pool to provided logger. func LogWorkerPoolError(l *logger.Logger, req string, err error) { - l.Error(logs.UtilCouldNotPushTaskToWorkerPool, + l.Error(context.Background(), logs.UtilCouldNotPushTaskToWorkerPool, zap.String("request", req), zap.String("error", err.Error()), ) diff --git a/pkg/services/object_manager/tombstone/checker.go b/pkg/services/object_manager/tombstone/checker.go index 7476dbd48d..6a9706b9e5 100644 --- a/pkg/services/object_manager/tombstone/checker.go +++ b/pkg/services/object_manager/tombstone/checker.go @@ -57,7 +57,7 @@ func (g *ExpirationChecker) IsTombstoneAvailable(ctx context.Context, a oid.Addr ts, err := g.tsSource.Tombstone(ctx, a, epoch) if err != nil { - log.Warn( + log.Warn(ctx, logs.TombstoneCouldNotGetTheTombstoneTheSource, zap.Error(err), ) @@ -77,7 +77,7 @@ func (g *ExpirationChecker) handleTS(addr string, ts *objectSDK.Object, reqEpoch if atr.Key() == objectV2.SysAttributeExpEpoch { epoch, err := strconv.ParseUint(atr.Value(), 10, 64) if err != nil { - g.log.Warn( + g.log.Warn(context.Background(), logs.TombstoneExpirationParseFailure, zap.Error(err), ) diff --git a/pkg/services/object_manager/tombstone/constructor.go b/pkg/services/object_manager/tombstone/constructor.go index 9d33e8179b..67ddf316f2 100644 --- a/pkg/services/object_manager/tombstone/constructor.go +++ b/pkg/services/object_manager/tombstone/constructor.go @@ -23,7 +23,7 @@ type Option func(*cfg) func defaultCfg() *cfg { return &cfg{ - log: &logger.Logger{Logger: zap.NewNop()}, + log: logger.NewLoggerWrapper(zap.NewNop()), cacheSize: defaultLRUCacheSize, } } diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index dbc9ea53c8..c82680a1e3 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -86,7 +86,7 @@ func (p *Policer) processRepContainerObject(ctx context.Context, objInfo objectc } if !c.needLocalCopy && c.removeLocalCopy { - p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, + p.log.Info(ctx, logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address), ) @@ -151,7 +151,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe } else if client.IsErrNodeUnderMaintenance(err) { shortage, uncheckedCopies = p.handleMaintenance(nodes[i], checkedNodes, shortage, uncheckedCopies) } else { - p.log.Error(logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, + p.log.Error(ctx, logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", addr), zap.String("error", err.Error()), ) @@ -178,7 +178,7 @@ func (p *Policer) handleMaintenance(node netmap.NodeInfo, checkedNodes nodeCache shortage-- uncheckedCopies++ - p.log.Debug(logs.PolicerConsiderNodeUnderMaintenanceAsOK, + p.log.Debug(context.Background(), logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(node)), ) return shortage, uncheckedCopies @@ -189,7 +189,7 @@ func (p *Policer) handleProcessNodesResult(ctx context.Context, addr oid.Address ) { switch { case shortage > 0: - p.log.Debug(logs.PolicerShortageOfObjectCopiesDetected, + p.log.Debug(ctx, logs.PolicerShortageOfObjectCopiesDetected, zap.Stringer("object", addr), zap.Uint32("shortage", shortage), ) @@ -205,7 +205,7 @@ func (p *Policer) handleProcessNodesResult(ctx context.Context, addr oid.Address case uncheckedCopies > 0: // If we have more copies than needed, but some of them are from the maintenance nodes, // save the local copy. - p.log.Debug(logs.PolicerSomeOfTheCopiesAreStoredOnNodesUnderMaintenance, + p.log.Debug(ctx, logs.PolicerSomeOfTheCopiesAreStoredOnNodesUnderMaintenance, zap.Int("count", uncheckedCopies)) case uncheckedCopies == 0: diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index 6d2c153c9c..cb583f1d3b 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -59,7 +59,7 @@ func (p *Policer) processECContainerRepObject(ctx context.Context, objInfo objec p.processRepNodes(ctx, c, objInfo, nn[0], uint32(len(nn[0])), checkedNodes) if !c.needLocalCopy && c.removeLocalCopy { - p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, + p.log.Info(ctx, logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address), ) @@ -91,7 +91,7 @@ func (p *Policer) processECContainerECObject(ctx context.Context, objInfo object p.adjustECPlacement(ctx, objInfo, nn[0], cnr) if res.removeLocal { - p.log.Info(logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address)) + p.log.Info(ctx, logs.PolicerRedundantLocalObjectCopyDetected, zap.Stringer("object", objInfo.Address)) p.cbRedundantCopy(ctx, objInfo.Address) } return nil @@ -109,7 +109,7 @@ func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, n } if requiredNode.Status().IsMaintenance() { // consider maintenance mode has object, but do not drop local copy - p.log.Debug(logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) + p.log.Debug(ctx, logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) return ecChunkProcessResult{} } @@ -120,7 +120,7 @@ func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, n if err == nil { removeLocalChunk = true } else if client.IsErrObjectNotFound(err) { - p.log.Debug(logs.PolicerShortageOfObjectCopiesDetected, zap.Stringer("object", objInfo.Address), zap.Uint32("shortage", 1)) + p.log.Debug(ctx, logs.PolicerShortageOfObjectCopiesDetected, zap.Stringer("object", objInfo.Address), zap.Uint32("shortage", 1)) task := replicator.Task{ NumCopies: 1, Addr: objInfo.Address, @@ -129,9 +129,9 @@ func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, n p.replicator.HandleReplicationTask(ctx, task, newNodeCache()) } else if client.IsErrNodeUnderMaintenance(err) { // consider maintenance mode has object, but do not drop local copy - p.log.Debug(logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) + p.log.Debug(ctx, logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) } else { - p.log.Error(logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", objInfo.Address), zap.String("error", err.Error())) + p.log.Error(ctx, logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", objInfo.Address), zap.String("error", err.Error())) } return ecChunkProcessResult{ @@ -146,13 +146,13 @@ func (p *Policer) pullRequiredECChunks(ctx context.Context, objInfo objectcore.I requiredChunkIndexes := p.collectRequiredECChunks(nodes, objInfo) if len(requiredChunkIndexes) == 0 { - p.log.Info(logs.PolicerNodeIsNotECObjectNode, zap.Stringer("object", objInfo.ECInfo.ParentID)) + p.log.Info(ctx, logs.PolicerNodeIsNotECObjectNode, zap.Stringer("object", objInfo.ECInfo.ParentID)) return true } err := p.resolveLocalECChunks(ctx, parentAddress, requiredChunkIndexes) if err != nil { - p.log.Error(logs.PolicerFailedToGetLocalECChunks, zap.Error(err), zap.Stringer("object", parentAddress)) + p.log.Error(ctx, logs.PolicerFailedToGetLocalECChunks, zap.Error(err), zap.Stringer("object", parentAddress)) return false } if len(requiredChunkIndexes) == 0 { @@ -224,11 +224,11 @@ func (p *Policer) resolveRemoteECChunks(ctx context.Context, parentAddress oid.A var chunkID oid.ID if err := chunkID.ReadFromV2(ch.ID); err != nil { - p.log.Error(logs.PolicerFailedToDecodeECChunkID, zap.Error(err), zap.Stringer("object", parentAddress)) + p.log.Error(ctx, logs.PolicerFailedToDecodeECChunkID, zap.Error(err), zap.Stringer("object", parentAddress)) return false } if existed, ok := indexToObjectID[ch.Index]; ok && existed != chunkID { - p.log.Error(logs.PolicerDifferentObjectIDForTheSameECChunk, zap.Stringer("first", existed), + p.log.Error(ctx, logs.PolicerDifferentObjectIDForTheSameECChunk, zap.Stringer("first", existed), zap.Stringer("second", chunkID), zap.Stringer("object", parentAddress), zap.Uint32("index", ch.Index)) return false } @@ -239,7 +239,7 @@ func (p *Policer) resolveRemoteECChunks(ctx context.Context, parentAddress oid.A for index, candidates := range required { if len(candidates) == 0 { - p.log.Error(logs.PolicerMissingECChunk, zap.Stringer("object", parentAddress), zap.Uint32("index", index)) + p.log.Error(ctx, logs.PolicerMissingECChunk, zap.Stringer("object", parentAddress), zap.Uint32("index", index)) return false } } @@ -271,18 +271,18 @@ func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info resolved[ch.Index] = append(resolved[ch.Index], n) var ecInfoChunkID oid.ID if err := ecInfoChunkID.ReadFromV2(ch.ID); err != nil { - p.log.Error(logs.PolicerFailedToDecodeECChunkID, zap.Error(err), zap.Stringer("object", parentAddress)) + p.log.Error(ctx, logs.PolicerFailedToDecodeECChunkID, zap.Error(err), zap.Stringer("object", parentAddress)) return } if chunkID, exist := chunkIDs[ch.Index]; exist && chunkID != ecInfoChunkID { - p.log.Error(logs.PolicerDifferentObjectIDForTheSameECChunk, zap.Stringer("first", chunkID), + p.log.Error(ctx, logs.PolicerDifferentObjectIDForTheSameECChunk, zap.Stringer("first", chunkID), zap.Stringer("second", ecInfoChunkID), zap.Stringer("object", parentAddress), zap.Uint32("index", ch.Index)) return } chunkIDs[ch.Index] = ecInfoChunkID } } else if !p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) && uint32(idx) < objInfo.ECInfo.Total { - p.log.Warn(logs.PolicerCouldNotGetObjectFromNodeMoving, zap.String("node", hex.EncodeToString(n.PublicKey())), zap.Stringer("object", parentAddress), zap.Error(err)) + p.log.Warn(ctx, logs.PolicerCouldNotGetObjectFromNodeMoving, zap.String("node", hex.EncodeToString(n.PublicKey())), zap.Stringer("object", parentAddress), zap.Error(err)) p.replicator.HandleReplicationTask(ctx, replicator.Task{ NumCopies: 1, Addr: objInfo.Address, @@ -299,7 +299,7 @@ func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info for i := range resolved { found = append(found, i) } - p.log.Error(logs.PolicerCouldNotRestoreObjectNotEnoughChunks, zap.Stringer("object", parentAddress), zap.Uint32s("found_chunks", found)) + p.log.Error(ctx, logs.PolicerCouldNotRestoreObjectNotEnoughChunks, zap.Stringer("object", parentAddress), zap.Uint32s("found_chunks", found)) return } p.restoreECObject(ctx, objInfo, parentAddress, nodes, resolved, chunkIDs, cnr) @@ -310,7 +310,7 @@ func (p *Policer) restoreECObject(ctx context.Context, objInfo objectcore.Info, ) { c, err := erasurecode.NewConstructor(int(cnr.PlacementPolicy().ReplicaDescriptor(0).GetECDataCount()), int(cnr.PlacementPolicy().ReplicaDescriptor(0).GetECParityCount())) if err != nil { - p.log.Error(logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) + p.log.Error(ctx, logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) return } parts := p.collectExistedChunks(ctx, objInfo, existedChunks, parentAddress, chunkIDs) @@ -319,7 +319,7 @@ func (p *Policer) restoreECObject(ctx context.Context, objInfo objectcore.Info, } key, err := p.keyStorage.GetKey(nil) if err != nil { - p.log.Error(logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) + p.log.Error(ctx, logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) return } required := make([]bool, len(parts)) @@ -329,7 +329,7 @@ func (p *Policer) restoreECObject(ctx context.Context, objInfo objectcore.Info, } } if err := c.ReconstructParts(parts, required, key); err != nil { - p.log.Error(logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) + p.log.Error(ctx, logs.PolicerFailedToRestoreObject, zap.Stringer("object", parentAddress), zap.Error(err)) return } for idx, part := range parts { @@ -377,7 +377,7 @@ func (p *Policer) collectExistedChunks(ctx context.Context, objInfo objectcore.I if err == nil { break } - p.log.Warn(logs.PolicerCouldNotGetChunk, zap.Stringer("object", parentAddress), zap.Stringer("chunkID", objID), zap.Error(err), zap.String("node", hex.EncodeToString(node.PublicKey()))) + p.log.Warn(ctx, logs.PolicerCouldNotGetChunk, zap.Stringer("object", parentAddress), zap.Stringer("chunkID", objID), zap.Error(err), zap.String("node", hex.EncodeToString(node.PublicKey()))) } if obj != nil { parts[idx] = obj @@ -386,7 +386,7 @@ func (p *Policer) collectExistedChunks(ctx context.Context, objInfo objectcore.I }) } if err := errGroup.Wait(); err != nil { - p.log.Error(logs.PolicerCouldNotGetChunks, zap.Stringer("object", parentAddress), zap.Error(err)) + p.log.Error(ctx, logs.PolicerCouldNotGetChunks, zap.Stringer("object", parentAddress), zap.Error(err)) return nil } return parts diff --git a/pkg/services/policer/option.go b/pkg/services/policer/option.go index 336f7a0abb..5d59604c20 100644 --- a/pkg/services/policer/option.go +++ b/pkg/services/policer/option.go @@ -91,7 +91,7 @@ type cfg struct { func defaultCfg() *cfg { return &cfg{ - log: &logger.Logger{Logger: zap.L()}, + log: logger.NewLoggerWrapper(zap.L()), batchSize: 10, cacheSize: 1024, // 1024 * address size = 1024 * 64 = 64 MiB sleepDuration: 1 * time.Second, diff --git a/pkg/services/policer/policer.go b/pkg/services/policer/policer.go index 363c0b922c..4e8bacfec1 100644 --- a/pkg/services/policer/policer.go +++ b/pkg/services/policer/policer.go @@ -4,7 +4,6 @@ import ( "sync" "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" lru "github.com/hashicorp/golang-lru/v2" "go.uber.org/zap" @@ -55,7 +54,7 @@ func New(opts ...Option) *Policer { opts[i](c) } - c.log = &logger.Logger{Logger: c.log.With(zap.String("component", "Object Policer"))} + c.log = c.log.With(zap.String("component", "Object Policer")) cache, err := lru.New[oid.Address, time.Time](int(c.cacheSize)) if err != nil { diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index a5ebb00101..80a87ade9c 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -14,7 +14,7 @@ import ( func (p *Policer) Run(ctx context.Context) { p.shardPolicyWorker(ctx) - p.log.Info(logs.PolicerRoutineStopped) + p.log.Info(ctx, logs.PolicerRoutineStopped) } func (p *Policer) shardPolicyWorker(ctx context.Context) { @@ -33,7 +33,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { time.Sleep(p.sleepDuration) // finished whole cycle, sleep a bit continue } - p.log.Warn(logs.PolicerFailureAtObjectSelectForReplication, zap.Error(err)) + p.log.Warn(ctx, logs.PolicerFailureAtObjectSelectForReplication, zap.Error(err)) } skipMap := newSkipMap() @@ -59,7 +59,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { if p.objsInWork.add(addr.Address) { err := p.processObject(ctx, addr) if err != nil && !skipMap.addSeenError(addr.Address.Container(), err) { - p.log.Error(logs.PolicerUnableToProcessObj, + p.log.Error(ctx, logs.PolicerUnableToProcessObj, zap.Stringer("object", addr.Address), zap.String("error", err.Error())) } @@ -69,7 +69,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { } }) if err != nil { - p.log.Warn(logs.PolicerPoolSubmission, zap.Error(err)) + p.log.Warn(ctx, logs.PolicerPoolSubmission, zap.Error(err)) } } } diff --git a/pkg/services/replicator/process.go b/pkg/services/replicator/process.go index 7e5c6e0932..2120312f6e 100644 --- a/pkg/services/replicator/process.go +++ b/pkg/services/replicator/process.go @@ -27,7 +27,7 @@ func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res T p.metrics.IncInFlightRequest() defer p.metrics.DecInFlightRequest() defer func() { - p.log.Debug(logs.ReplicatorFinishWork, + p.log.Debug(ctx, logs.ReplicatorFinishWork, zap.Uint32("amount of unfinished replicas", task.NumCopies), ) }() @@ -43,7 +43,7 @@ func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res T var err error task.Obj, err = engine.Get(ctx, p.localStorage, task.Addr) if err != nil { - p.log.Error(logs.ReplicatorCouldNotGetObjectFromLocalStorage, + p.log.Error(ctx, logs.ReplicatorCouldNotGetObjectFromLocalStorage, zap.Stringer("object", task.Addr), zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -75,11 +75,11 @@ func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res T cancel() if err != nil { - log.Error(logs.ReplicatorCouldNotReplicateObject, + log.Error(ctx, logs.ReplicatorCouldNotReplicateObject, zap.String("error", err.Error()), ) } else { - log.Debug(logs.ReplicatorObjectSuccessfullyReplicated) + log.Debug(ctx, logs.ReplicatorObjectSuccessfullyReplicated) task.NumCopies-- diff --git a/pkg/services/replicator/pull.go b/pkg/services/replicator/pull.go index 7e70902379..5ce9293425 100644 --- a/pkg/services/replicator/pull.go +++ b/pkg/services/replicator/pull.go @@ -22,7 +22,7 @@ func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { p.metrics.IncInFlightRequest() defer p.metrics.DecInFlightRequest() defer func() { - p.log.Debug(logs.ReplicatorFinishWork, zap.String("type", "pull")) + p.log.Debug(ctx, logs.ReplicatorFinishWork, zap.String("type", "pull")) }() ctx, span := tracing.StartSpanFromContext(ctx, "Replicator.HandlePullTask", @@ -48,7 +48,7 @@ func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { endpoints = append(endpoints, s) return false }) - p.log.Error(logs.ReplicatorCouldNotGetObjectFromRemoteStorage, + p.log.Error(ctx, logs.ReplicatorCouldNotGetObjectFromRemoteStorage, zap.Stringer("object", task.Addr), zap.Error(err), zap.Strings("endpoints", endpoints), @@ -56,7 +56,7 @@ func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { } if obj == nil { - p.log.Error(logs.ReplicatorCouldNotGetObjectFromRemoteStorage, + p.log.Error(ctx, logs.ReplicatorCouldNotGetObjectFromRemoteStorage, zap.Stringer("object", task.Addr), zap.Error(errFailedToGetObjectFromAnyNode), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -65,7 +65,7 @@ func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { err := engine.Put(ctx, p.localStorage, obj, containerCore.IsIndexedContainer(task.Container)) if err != nil { - p.log.Error(logs.ReplicatorCouldNotPutObjectToLocalStorage, + p.log.Error(ctx, logs.ReplicatorCouldNotPutObjectToLocalStorage, zap.Stringer("object", task.Addr), zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/services/replicator/put.go b/pkg/services/replicator/put.go index 5378335165..489f66ae56 100644 --- a/pkg/services/replicator/put.go +++ b/pkg/services/replicator/put.go @@ -20,7 +20,7 @@ func (p *Replicator) HandleLocalPutTask(ctx context.Context, task Task) { p.metrics.IncInFlightRequest() defer p.metrics.DecInFlightRequest() defer func() { - p.log.Debug(logs.ReplicatorFinishWork, zap.String("type", "pull")) + p.log.Debug(ctx, logs.ReplicatorFinishWork, zap.String("type", "pull")) }() ctx, span := tracing.StartSpanFromContext(ctx, "Replicator.HandleLocalPutTask", @@ -31,7 +31,7 @@ func (p *Replicator) HandleLocalPutTask(ctx context.Context, task Task) { defer span.End() if task.Obj == nil { - p.log.Error(logs.ReplicatorCouldNotPutObjectToLocalStorage, + p.log.Error(ctx, logs.ReplicatorCouldNotPutObjectToLocalStorage, zap.Stringer("object", task.Addr), zap.Error(errObjectNotDefined), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -40,7 +40,7 @@ func (p *Replicator) HandleLocalPutTask(ctx context.Context, task Task) { err := engine.Put(ctx, p.localStorage, task.Obj, containerCore.IsIndexedContainer(task.Container)) if err != nil { - p.log.Error(logs.ReplicatorCouldNotPutObjectToLocalStorage, + p.log.Error(ctx, logs.ReplicatorCouldNotPutObjectToLocalStorage, zap.Stringer("object", task.Addr), zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/services/replicator/replicator.go b/pkg/services/replicator/replicator.go index f2f86daf01..6910fa5af5 100644 --- a/pkg/services/replicator/replicator.go +++ b/pkg/services/replicator/replicator.go @@ -45,7 +45,7 @@ func New(opts ...Option) *Replicator { opts[i](c) } - c.log = &logger.Logger{Logger: c.log.With(zap.String("component", "Object Replicator"))} + c.log = c.log.With(zap.String("component", "Object Replicator")) return &Replicator{ cfg: c, diff --git a/pkg/services/session/executor.go b/pkg/services/session/executor.go index e914119b43..12b2216132 100644 --- a/pkg/services/session/executor.go +++ b/pkg/services/session/executor.go @@ -33,7 +33,7 @@ func NewExecutionService(exec ServiceExecutor, respSvc *response.Service, l *log } func (s *executorSvc) Create(ctx context.Context, req *session.CreateRequest) (*session.CreateResponse, error) { - s.log.Debug(logs.ServingRequest, + s.log.Debug(ctx, logs.ServingRequest, zap.String("component", "SessionService"), zap.String("request", "Create"), ) diff --git a/pkg/services/session/storage/persistent/options.go b/pkg/services/session/storage/persistent/options.go index 411734ea18..60db97f901 100644 --- a/pkg/services/session/storage/persistent/options.go +++ b/pkg/services/session/storage/persistent/options.go @@ -19,7 +19,7 @@ type Option func(*cfg) func defaultCfg() *cfg { return &cfg{ - l: &logger.Logger{Logger: zap.L()}, + l: logger.NewLoggerWrapper(zap.L()), timeout: 100 * time.Millisecond, } } diff --git a/pkg/services/session/storage/persistent/storage.go b/pkg/services/session/storage/persistent/storage.go index 71711e3715..d312ea0ea7 100644 --- a/pkg/services/session/storage/persistent/storage.go +++ b/pkg/services/session/storage/persistent/storage.go @@ -1,6 +1,7 @@ package persistent import ( + "context" "crypto/aes" "crypto/cipher" "encoding/hex" @@ -105,7 +106,7 @@ func (s *TokenStore) Get(ownerID user.ID, tokenID []byte) (t *storage.PrivateTok return err }) if err != nil { - s.l.Error(logs.PersistentCouldNotGetSessionFromPersistentStorage, + s.l.Error(context.Background(), logs.PersistentCouldNotGetSessionFromPersistentStorage, zap.Error(err), zap.Stringer("ownerID", ownerID), zap.String("tokenID", hex.EncodeToString(tokenID)), @@ -130,7 +131,7 @@ func (s *TokenStore) RemoveOld(epoch uint64) { if epochFromToken(v) <= epoch { err = c.Delete() if err != nil { - s.l.Error(logs.PersistentCouldNotDeleteSToken, + s.l.Error(context.Background(), logs.PersistentCouldNotDeleteSToken, zap.String("token_id", hex.EncodeToString(k)), ) } @@ -141,7 +142,7 @@ func (s *TokenStore) RemoveOld(epoch uint64) { }) }) if err != nil { - s.l.Error(logs.PersistentCouldNotCleanUpExpiredTokens, + s.l.Error(context.Background(), logs.PersistentCouldNotCleanUpExpiredTokens, zap.Uint64("epoch", epoch), ) } diff --git a/pkg/services/tree/redirect.go b/pkg/services/tree/redirect.go index 5bde3ae381..416a0fafeb 100644 --- a/pkg/services/tree/redirect.go +++ b/pkg/services/tree/redirect.go @@ -54,7 +54,7 @@ func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo return false } - s.log.Debug(logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint), + s.log.Debug(ctx, logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) called = true diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 84e376cf74..0c5bde0781 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -58,7 +58,7 @@ func (s *Service) localReplicationWorker(ctx context.Context) { err := s.forest.TreeApply(ctx, op.cid, op.treeID, &op.Move, false) if err != nil { - s.log.Error(logs.TreeFailedToApplyReplicatedOperation, + s.log.Error(ctx, logs.TreeFailedToApplyReplicatedOperation, zap.String("err", err.Error())) } span.End() @@ -116,11 +116,11 @@ func (s *Service) ReplicateTreeOp(ctx context.Context, n netmapSDK.NodeInfo, req if lastErr != nil { if errors.Is(lastErr, errRecentlyFailed) { - s.log.Debug(logs.TreeDoNotSendUpdateToTheNode, + s.log.Debug(ctx, logs.TreeDoNotSendUpdateToTheNode, zap.String("last_error", lastErr.Error()), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } else { - s.log.Warn(logs.TreeFailedToSentUpdateToTheNode, + s.log.Warn(ctx, logs.TreeFailedToSentUpdateToTheNode, zap.String("last_error", lastErr.Error()), zap.String("address", lastAddr), zap.String("key", hex.EncodeToString(n.PublicKey())), @@ -154,7 +154,7 @@ func (s *Service) replicateLoop(ctx context.Context) { start := time.Now() err := s.replicate(op) if err != nil { - s.log.Error(logs.TreeErrorDuringReplication, + s.log.Error(ctx, logs.TreeErrorDuringReplication, zap.String("err", err.Error()), zap.Stringer("cid", op.cid), zap.String("treeID", op.treeID)) diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index b63338d259..2df3c08e65 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -63,7 +63,7 @@ func New(opts ...Option) *Service { } if s.log == nil { - s.log = &logger.Logger{Logger: zap.NewNop()} + s.log = logger.NewLoggerWrapper(zap.NewNop()) } s.cache.init(s.key, s.ds) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 2c6deeb787..e2249c9fb8 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -92,7 +92,7 @@ func (s *Service) synchronizeAllTrees(ctx context.Context, cid cid.ID) error { for _, tid := range treesToSync { h, err := s.forest.TreeLastSyncHeight(ctx, cid, tid) if err != nil && !errors.Is(err, pilorama.ErrTreeNotFound) { - s.log.Warn(logs.TreeCouldNotGetLastSynchronizedHeightForATree, + s.log.Warn(ctx, logs.TreeCouldNotGetLastSynchronizedHeightForATree, zap.Stringer("cid", cid), zap.String("tree", tid)) continue @@ -100,7 +100,7 @@ func (s *Service) synchronizeAllTrees(ctx context.Context, cid cid.ID) error { newHeight := s.synchronizeTree(ctx, cid, h, tid, nodes) if h < newHeight { if err := s.forest.TreeUpdateLastSyncHeight(ctx, cid, tid, newHeight); err != nil { - s.log.Warn(logs.TreeCouldNotUpdateLastSynchronizedHeightForATree, + s.log.Warn(ctx, logs.TreeCouldNotUpdateLastSynchronizedHeightForATree, zap.Stringer("cid", cid), zap.String("tree", tid)) } @@ -251,7 +251,7 @@ func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, treeID string, nodes []netmapSDK.NodeInfo, ) uint64 { - s.log.Debug(logs.TreeSynchronizeTree, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.Uint64("from", from)) + s.log.Debug(ctx, logs.TreeSynchronizeTree, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.Uint64("from", from)) errGroup, egCtx := errgroup.WithContext(ctx) const workersCount = 1024 @@ -282,20 +282,20 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, n.IterateNetworkEndpoints(func(addr string) bool { var a network.Address if err := a.FromString(addr); err != nil { - s.log.Warn(logs.TreeFailedToParseAddressForTreeSynchronization, zap.Error(err), zap.String("address", addr)) + s.log.Warn(ctx, logs.TreeFailedToParseAddressForTreeSynchronization, zap.Error(err), zap.String("address", addr)) return false } cc, err := s.createConnection(a) if err != nil { - s.log.Warn(logs.TreeFailedToConnectForTreeSynchronization, zap.Error(err), zap.String("address", addr)) + s.log.Warn(ctx, logs.TreeFailedToConnectForTreeSynchronization, zap.Error(err), zap.String("address", addr)) return false } defer cc.Close() err = s.startStream(egCtx, cid, treeID, from, cc, nodeOperationStreams[i]) if err != nil { - s.log.Warn(logs.TreeFailedToRunTreeSynchronizationForSpecificNode, zap.Error(err), zap.String("address", addr)) + s.log.Warn(ctx, logs.TreeFailedToRunTreeSynchronizationForSpecificNode, zap.Error(err), zap.String("address", addr)) } nodeSynced = err == nil return true @@ -309,7 +309,7 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, } if err := errGroup.Wait(); err != nil { allNodesSynced.Store(false) - s.log.Warn(logs.TreeFailedToRunTreeSynchronizationOverAllNodes, zap.Error(err)) + s.log.Warn(ctx, logs.TreeFailedToRunTreeSynchronizationOverAllNodes, zap.Error(err)) } newHeight := minStreamedLastHeight @@ -376,13 +376,13 @@ func (s *Service) syncLoop(ctx context.Context) { return case <-s.syncChan: ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.sync") - s.log.Info(logs.TreeSyncingTrees) + s.log.Info(ctx, logs.TreeSyncingTrees) start := time.Now() cnrs, err := s.cfg.cnrSource.List() if err != nil { - s.log.Error(logs.TreeCouldNotFetchContainers, zap.Error(err)) + s.log.Error(ctx, logs.TreeCouldNotFetchContainers, zap.Error(err)) s.metrics.AddSyncDuration(time.Since(start), false) span.End() break @@ -394,7 +394,7 @@ func (s *Service) syncLoop(ctx context.Context) { s.removeContainers(ctx, newMap) - s.log.Info(logs.TreeTreesHaveBeenSynchronized) + s.log.Info(ctx, logs.TreeTreesHaveBeenSynchronized) s.metrics.AddSyncDuration(time.Since(start), true) span.End() @@ -414,19 +414,19 @@ func (s *Service) syncContainers(ctx context.Context, cnrs []cid.ID) { err := s.syncPool.Submit(func() { defer wg.Done() - s.log.Debug(logs.TreeSyncingContainerTrees, zap.Stringer("cid", cnr)) + s.log.Debug(ctx, logs.TreeSyncingContainerTrees, zap.Stringer("cid", cnr)) err := s.synchronizeAllTrees(ctx, cnr) if err != nil { - s.log.Error(logs.TreeCouldNotSyncTrees, zap.Stringer("cid", cnr), zap.Error(err)) + s.log.Error(ctx, logs.TreeCouldNotSyncTrees, zap.Stringer("cid", cnr), zap.Error(err)) return } - s.log.Debug(logs.TreeContainerTreesHaveBeenSynced, zap.Stringer("cid", cnr)) + s.log.Debug(ctx, logs.TreeContainerTreesHaveBeenSynced, zap.Stringer("cid", cnr)) }) if err != nil { wg.Done() - s.log.Error(logs.TreeCouldNotQueryTreesForSynchronization, + s.log.Error(ctx, logs.TreeCouldNotQueryTreesForSynchronization, zap.Stringer("cid", cnr), zap.Error(err)) if errors.Is(err, ants.ErrPoolClosed) { @@ -452,7 +452,7 @@ func (s *Service) removeContainers(ctx context.Context, newContainers map[cid.ID existed, err := containerCore.WasRemoved(s.cnrSource, cnr) if err != nil { - s.log.Error(logs.TreeCouldNotCheckIfContainerExisted, + s.log.Error(ctx, logs.TreeCouldNotCheckIfContainerExisted, zap.Stringer("cid", cnr), zap.Error(err)) } else if existed { @@ -464,11 +464,11 @@ func (s *Service) removeContainers(ctx context.Context, newContainers map[cid.ID } for _, cnr := range removed { - s.log.Debug(logs.TreeRemovingRedundantTrees, zap.Stringer("cid", cnr)) + s.log.Debug(ctx, logs.TreeRemovingRedundantTrees, zap.Stringer("cid", cnr)) err := s.DropTree(ctx, cnr, "") if err != nil { - s.log.Error(logs.TreeCouldNotRemoveRedundantTree, + s.log.Error(ctx, logs.TreeCouldNotRemoveRedundantTree, zap.Stringer("cid", cnr), zap.Error(err)) } @@ -482,7 +482,7 @@ func (s *Service) containersToSync(cnrs []cid.ID) (map[cid.ID]struct{}, []cid.ID for _, cnr := range cnrs { _, pos, err := s.getContainerNodes(cnr) if err != nil { - s.log.Error(logs.TreeCouldNotCalculateContainerNodes, + s.log.Error(context.Background(), logs.TreeCouldNotCalculateContainerNodes, zap.Stringer("cid", cnr), zap.Error(err)) continue diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index d4ac2ab027..b3a1b9b943 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -184,6 +184,10 @@ func (l *Logger) WithOptions(options ...zap.Option) { l.z = l.z.WithOptions(options...) } +func (l *Logger) With(fields ...zap.Field) *Logger { + return &Logger{z: l.z.With(fields...)} +} + func NewLoggerWrapper(z *zap.Logger) *Logger { return &Logger{ z: z, From 62b5181618f194f024ede60070e240bcd8fe7a31 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 21 Oct 2024 11:20:17 +0300 Subject: [PATCH 0995/1413] [#1437] blobovnicza: Fix contextcheck linter Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-lens/internal/blobovnicza/root.go | 2 +- .../blobovnicza/blobovnicza_test.go | 2 +- .../blobovnicza/control.go | 6 ++--- .../blobovnicza/get_test.go | 2 +- .../blobovnicza/iterate_test.go | 2 +- .../blobstor/blobovniczatree/active.go | 23 ++++++++++--------- .../blobstor/blobovniczatree/cache.go | 8 +++---- .../blobstor/blobovniczatree/control.go | 6 ++--- .../blobstor/blobovniczatree/count.go | 4 ++-- .../blobstor/blobovniczatree/delete.go | 8 +++---- .../blobstor/blobovniczatree/exists.go | 4 ++-- .../blobstor/blobovniczatree/get.go | 8 +++---- .../blobstor/blobovniczatree/get_range.go | 8 +++---- .../blobstor/blobovniczatree/iterate.go | 4 ++-- .../blobstor/blobovniczatree/manager.go | 4 ++-- .../blobstor/blobovniczatree/put.go | 2 +- .../blobstor/blobovniczatree/rebuild.go | 22 +++++++++--------- .../blobovniczatree/rebuild_failover_test.go | 14 +++++------ pkg/local_object_storage/engine/engine.go | 4 ++-- pkg/morph/client/client.go | 4 ++-- pkg/morph/event/listener.go | 16 ++++++------- pkg/morph/subscriber/subscriber.go | 10 ++++---- 22 files changed, 82 insertions(+), 81 deletions(-) diff --git a/cmd/frostfs-lens/internal/blobovnicza/root.go b/cmd/frostfs-lens/internal/blobovnicza/root.go index 9d8ef3dadc..2819981d61 100644 --- a/cmd/frostfs-lens/internal/blobovnicza/root.go +++ b/cmd/frostfs-lens/internal/blobovnicza/root.go @@ -27,7 +27,7 @@ func openBlobovnicza(cmd *cobra.Command) *blobovnicza.Blobovnicza { blobovnicza.WithPath(vPath), blobovnicza.WithReadOnly(true), ) - common.ExitOnErr(cmd, blz.Open()) + common.ExitOnErr(cmd, blz.Open(cmd.Context())) return blz } diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go index caee770e85..10cb6f368c 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go @@ -69,7 +69,7 @@ func TestBlobovnicza(t *testing.T) { defer os.Remove(p) // open Blobovnicza - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) // initialize Blobovnicza require.NoError(t, blz.Init()) diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index 5d71357414..a317279a45 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -16,7 +16,7 @@ import ( // // If the database file does not exist, it will be created automatically. // If blobovnicza is already open, does nothing. -func (b *Blobovnicza) Open() error { +func (b *Blobovnicza) Open(ctx context.Context) error { b.controlMtx.Lock() defer b.controlMtx.Unlock() @@ -24,7 +24,7 @@ func (b *Blobovnicza) Open() error { return nil } - b.log.Debug(context.Background(), logs.BlobovniczaCreatingDirectoryForBoltDB, + b.log.Debug(ctx, logs.BlobovniczaCreatingDirectoryForBoltDB, zap.String("path", b.path), zap.Bool("ro", b.boltOptions.ReadOnly), ) @@ -38,7 +38,7 @@ func (b *Blobovnicza) Open() error { } } - b.log.Debug(context.Background(), logs.BlobovniczaOpeningBoltDB, + b.log.Debug(ctx, logs.BlobovniczaOpeningBoltDB, zap.String("path", b.path), zap.Stringer("permissions", b.perm), ) diff --git a/pkg/local_object_storage/blobovnicza/get_test.go b/pkg/local_object_storage/blobovnicza/get_test.go index c464abc877..8c435af897 100644 --- a/pkg/local_object_storage/blobovnicza/get_test.go +++ b/pkg/local_object_storage/blobovnicza/get_test.go @@ -26,7 +26,7 @@ func TestBlobovnicza_Get(t *testing.T) { WithObjectSizeLimit(szLimit), ) - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) require.NoError(t, blz.Init()) } diff --git a/pkg/local_object_storage/blobovnicza/iterate_test.go b/pkg/local_object_storage/blobovnicza/iterate_test.go index 5db1e4165b..bec23bb96a 100644 --- a/pkg/local_object_storage/blobovnicza/iterate_test.go +++ b/pkg/local_object_storage/blobovnicza/iterate_test.go @@ -15,7 +15,7 @@ import ( func TestBlobovniczaIterate(t *testing.T) { filename := filepath.Join(t.TempDir(), "blob") b := New(WithPath(filename)) - require.NoError(t, b.Open()) + require.NoError(t, b.Open(context.Background())) require.NoError(t, b.Init()) data := [][]byte{{0, 1, 2, 3}, {5, 6, 7, 8}} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/active.go b/pkg/local_object_storage/blobstor/blobovniczatree/active.go index 603c6abe3c..0ac15df827 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/active.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/active.go @@ -1,6 +1,7 @@ package blobovniczatree import ( + "context" "path/filepath" "sync" @@ -53,8 +54,8 @@ func newActiveDBManager(dbManager *dbManager, rootPath string) *activeDBManager // GetOpenedActiveDBForLevel returns active DB for level. // DB must be closed after use. -func (m *activeDBManager) GetOpenedActiveDBForLevel(lvlPath string) (*activeDB, error) { - activeDB, err := m.getCurrentActiveIfOk(lvlPath) +func (m *activeDBManager) GetOpenedActiveDBForLevel(ctx context.Context, lvlPath string) (*activeDB, error) { + activeDB, err := m.getCurrentActiveIfOk(ctx, lvlPath) if err != nil { return nil, err } @@ -62,7 +63,7 @@ func (m *activeDBManager) GetOpenedActiveDBForLevel(lvlPath string) (*activeDB, return activeDB, nil } - return m.updateAndGetActive(lvlPath) + return m.updateAndGetActive(ctx, lvlPath) } func (m *activeDBManager) Open() { @@ -83,7 +84,7 @@ func (m *activeDBManager) Close() { m.closed = true } -func (m *activeDBManager) getCurrentActiveIfOk(lvlPath string) (*activeDB, error) { +func (m *activeDBManager) getCurrentActiveIfOk(ctx context.Context, lvlPath string) (*activeDB, error) { m.levelToActiveDBGuard.RLock() defer m.levelToActiveDBGuard.RUnlock() @@ -96,7 +97,7 @@ func (m *activeDBManager) getCurrentActiveIfOk(lvlPath string) (*activeDB, error return nil, nil } - blz, err := db.Open() // open db for usage, will be closed on activeDB.Close() + blz, err := db.Open(ctx) // open db for usage, will be closed on activeDB.Close() if err != nil { return nil, err } @@ -112,11 +113,11 @@ func (m *activeDBManager) getCurrentActiveIfOk(lvlPath string) (*activeDB, error }, nil } -func (m *activeDBManager) updateAndGetActive(lvlPath string) (*activeDB, error) { +func (m *activeDBManager) updateAndGetActive(ctx context.Context, lvlPath string) (*activeDB, error) { m.levelLock.Lock(lvlPath) defer m.levelLock.Unlock(lvlPath) - current, err := m.getCurrentActiveIfOk(lvlPath) + current, err := m.getCurrentActiveIfOk(ctx, lvlPath) if err != nil { return nil, err } @@ -124,7 +125,7 @@ func (m *activeDBManager) updateAndGetActive(lvlPath string) (*activeDB, error) return current, nil } - nextShDB, err := m.getNextSharedDB(lvlPath) + nextShDB, err := m.getNextSharedDB(ctx, lvlPath) if err != nil { return nil, err } @@ -133,7 +134,7 @@ func (m *activeDBManager) updateAndGetActive(lvlPath string) (*activeDB, error) return nil, nil } - blz, err := nextShDB.Open() // open db for client, client must call Close() after usage + blz, err := nextShDB.Open(ctx) // open db for client, client must call Close() after usage if err != nil { return nil, err } @@ -143,7 +144,7 @@ func (m *activeDBManager) updateAndGetActive(lvlPath string) (*activeDB, error) }, nil } -func (m *activeDBManager) getNextSharedDB(lvlPath string) (*sharedDB, error) { +func (m *activeDBManager) getNextSharedDB(ctx context.Context, lvlPath string) (*sharedDB, error) { var nextActiveDBIdx uint64 hasActive, currentIdx := m.hasActiveDB(lvlPath) if hasActive { @@ -160,7 +161,7 @@ func (m *activeDBManager) getNextSharedDB(lvlPath string) (*sharedDB, error) { path := filepath.Join(lvlPath, u64ToHexStringExt(nextActiveDBIdx)) next := m.dbManager.GetByPath(path) - _, err := next.Open() // open db to hold active DB open, will be closed if db is full, after m.replace or by activeDBManager.Close() + _, err := next.Open(ctx) // open db to hold active DB open, will be closed if db is full, after m.replace or by activeDBManager.Close() if err != nil { return nil, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index 5c103c1bb3..e8016781ab 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -81,12 +81,12 @@ func (c *dbCache) Close() { c.closed = true } -func (c *dbCache) GetOrCreate(path string) *sharedDB { +func (c *dbCache) GetOrCreate(ctx context.Context, path string) *sharedDB { value := c.getExisted(path) if value != nil { return value } - return c.create(path) + return c.create(ctx, path) } func (c *dbCache) EvictAndMarkNonCached(path string) { @@ -122,7 +122,7 @@ func (c *dbCache) getExisted(path string) *sharedDB { return nil } -func (c *dbCache) create(path string) *sharedDB { +func (c *dbCache) create(ctx context.Context, path string) *sharedDB { c.pathLock.Lock(path) defer c.pathLock.Unlock(path) @@ -133,7 +133,7 @@ func (c *dbCache) create(path string) *sharedDB { value = c.dbManager.GetByPath(path) - _, err := value.Open() // open db to hold reference, closed by evictedDB.Close() or if cache closed + _, err := value.Open(ctx) // open db to hold reference, closed by evictedDB.Close() or if cache closed if err != nil { return value } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 55c9d6630f..7c0a9edd61 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -46,7 +46,7 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { eg.Go(func() error { p = strings.TrimSuffix(p, rebuildSuffix) shBlz := b.getBlobovniczaWithoutCaching(p) - blz, err := shBlz.Open() + blz, err := shBlz.Open(egCtx) if err != nil { return err } @@ -91,8 +91,8 @@ func (b *Blobovniczas) Close() error { // returns blobovnicza with path p // // If blobovnicza is already cached, instance from cache is returned w/o changes. -func (b *Blobovniczas) getBlobovnicza(p string) *sharedDB { - return b.dbCache.GetOrCreate(p) +func (b *Blobovniczas) getBlobovnicza(ctx context.Context, p string) *sharedDB { + return b.dbCache.GetOrCreate(ctx, p) } func (b *Blobovniczas) getBlobovniczaWithoutCaching(p string) *sharedDB { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/count.go b/pkg/local_object_storage/blobstor/blobovniczatree/count.go index cf91637d70..1137b9eb2e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/count.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/count.go @@ -16,13 +16,13 @@ func (b *Blobovniczas) ObjectsCount(ctx context.Context) (uint64, error) { b.metrics.ObjectsCount(time.Since(startedAt), success) }() - _, span := tracing.StartSpanFromContext(ctx, "Blobovniczas.ObjectsCount") + ctx, span := tracing.StartSpanFromContext(ctx, "Blobovniczas.ObjectsCount") defer span.End() var result uint64 err := b.iterateExistingDBPaths(ctx, func(p string) (bool, error) { shDB := b.getBlobovniczaWithoutCaching(p) - blz, err := shDB.Open() + blz, err := shDB.Open(ctx) if err != nil { return true, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index dd52580426..b26e44144c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -61,8 +61,8 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co if prm.StorageID != nil { id := NewIDFromBytes(prm.StorageID) - shBlz := b.getBlobovnicza(id.Path()) - blz, err := shBlz.Open() + shBlz := b.getBlobovnicza(ctx, id.Path()) + blz, err := shBlz.Open(ctx) if err != nil { return res, err } @@ -109,8 +109,8 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co // // returns no error if object was removed from some blobovnicza of the same level. func (b *Blobovniczas) deleteObjectFromLevel(ctx context.Context, prm blobovnicza.DeletePrm, blzPath string) (common.DeleteRes, error) { - shBlz := b.getBlobovnicza(blzPath) - blz, err := shBlz.Open() + shBlz := b.getBlobovnicza(ctx, blzPath) + blz, err := shBlz.Open(ctx) if err != nil { return common.DeleteRes{}, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index 2149b17c01..528dbfed71 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -37,8 +37,8 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common if prm.StorageID != nil { id := NewIDFromBytes(prm.StorageID) - shBlz := b.getBlobovnicza(id.Path()) - blz, err := shBlz.Open() + shBlz := b.getBlobovnicza(ctx, id.Path()) + blz, err := shBlz.Open(ctx) if err != nil { return common.ExistsRes{}, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index e79480095b..fc017f22d3 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -48,8 +48,8 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G if prm.StorageID != nil { id := NewIDFromBytes(prm.StorageID) - shBlz := b.getBlobovnicza(id.Path()) - blz, err := shBlz.Open() + shBlz := b.getBlobovnicza(ctx, id.Path()) + blz, err := shBlz.Open(ctx) if err != nil { return res, err } @@ -95,8 +95,8 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G // returns error if object could not be read from any blobovnicza of the same level. func (b *Blobovniczas) getObjectFromLevel(ctx context.Context, prm blobovnicza.GetPrm, blzPath string) (common.GetRes, error) { // open blobovnicza (cached inside) - shBlz := b.getBlobovnicza(blzPath) - blz, err := shBlz.Open() + shBlz := b.getBlobovnicza(ctx, blzPath) + blz, err := shBlz.Open(ctx) if err != nil { return common.GetRes{}, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 20f2be2bad..384544d7b7 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -47,8 +47,8 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re if prm.StorageID != nil { id := NewIDFromBytes(prm.StorageID) - shBlz := b.getBlobovnicza(id.Path()) - blz, err := shBlz.Open() + shBlz := b.getBlobovnicza(ctx, id.Path()) + blz, err := shBlz.Open(ctx) if err != nil { return common.GetRangeRes{}, err } @@ -103,8 +103,8 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re // returns error if object could not be read from any blobovnicza of the same level. func (b *Blobovniczas) getRangeFromLevel(ctx context.Context, prm common.GetRangePrm, blzPath string) (common.GetRangeRes, error) { // open blobovnicza (cached inside) - shBlz := b.getBlobovnicza(blzPath) - blz, err := shBlz.Open() + shBlz := b.getBlobovnicza(ctx, blzPath) + blz, err := shBlz.Open(ctx) if err != nil { return common.GetRangeRes{}, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 7f04534104..049a61d721 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -72,8 +72,8 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm // iterator over all Blobovniczas in unsorted order. Break on f's error return. func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors bool, f func(string, *blobovnicza.Blobovnicza) error) error { return b.iterateExistingDBPaths(ctx, func(p string) (bool, error) { - shBlz := b.getBlobovnicza(p) - blz, err := shBlz.Open() + shBlz := b.getBlobovnicza(ctx, p) + blz, err := shBlz.Open(ctx) if err != nil { if ignoreErrors { b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index 235c9f65d2..502202d689 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -49,7 +49,7 @@ func newSharedDB(options []blobovnicza.Option, path string, readOnly bool, } } -func (b *sharedDB) Open() (*blobovnicza.Blobovnicza, error) { +func (b *sharedDB) Open(ctx context.Context) (*blobovnicza.Blobovnicza, error) { if b.closedFlag.Load() { return nil, errClosed } @@ -68,7 +68,7 @@ func (b *sharedDB) Open() (*blobovnicza.Blobovnicza, error) { blobovnicza.WithMetrics(b.metrics), )...) - if err := blz.Open(); err != nil { + if err := blz.Open(ctx); err != nil { return nil, fmt.Errorf("could not open blobovnicza %s: %w", b.path, err) } if err := blz.Init(); err != nil { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 844b431518..8dff436d3b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -77,7 +77,7 @@ type putIterator struct { } func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) { - active, err := i.B.activeDBManager.GetOpenedActiveDBForLevel(lvlPath) + active, err := i.B.activeDBManager.GetOpenedActiveDBForLevel(ctx, lvlPath) if err != nil { if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index fee67a0a84..e137bdd994 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -165,7 +165,7 @@ func (b *Blobovniczas) selectDBsDoNotMatchFillPercent(ctx context.Context, targe continue } path := filepath.Join(lvlPath, e.Name()) - resettlementRequired, err := b.rebuildBySize(path, target) + resettlementRequired, err := b.rebuildBySize(ctx, path, target) if err != nil { return false, err } @@ -180,9 +180,9 @@ func (b *Blobovniczas) selectDBsDoNotMatchFillPercent(ctx context.Context, targe return result, nil } -func (b *Blobovniczas) rebuildBySize(path string, targetFillPercent int) (bool, error) { - shDB := b.getBlobovnicza(path) - blz, err := shDB.Open() +func (b *Blobovniczas) rebuildBySize(ctx context.Context, path string, targetFillPercent int) (bool, error) { + shDB := b.getBlobovnicza(ctx, path) + blz, err := shDB.Open(ctx) if err != nil { return false, err } @@ -196,8 +196,8 @@ func (b *Blobovniczas) rebuildBySize(path string, targetFillPercent int) (bool, } func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) { - shDB := b.getBlobovnicza(path) - blz, err := shDB.Open() + shDB := b.getBlobovnicza(ctx, path) + blz, err := shDB.Open(ctx) if err != nil { return 0, err } @@ -365,8 +365,8 @@ func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore co err := b.iterateIncompletedRebuildDBPaths(ctx, func(s string) (bool, error) { rebuildTmpFilePath := s s = strings.TrimSuffix(s, rebuildSuffix) - shDB := b.getBlobovnicza(s) - blz, err := shDB.Open() + shDB := b.getBlobovnicza(ctx, s) + blz, err := shDB.Open(ctx) if err != nil { return true, err } @@ -398,8 +398,8 @@ func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore co func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blobovnicza, sourcePath string, move blobovnicza.MoveInfo, metaStore common.MetaStorage, ) error { - targetDB := b.getBlobovnicza(NewIDFromBytes(move.TargetStorageID).Path()) - target, err := targetDB.Open() + targetDB := b.getBlobovnicza(ctx, NewIDFromBytes(move.TargetStorageID).Path()) + target, err := targetDB.Open(ctx) if err != nil { return err } @@ -477,7 +477,7 @@ type moveIterator struct { } func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, error) { - target, err := i.B.activeDBManager.GetOpenedActiveDBForLevel(lvlPath) + target, err := i.B.activeDBManager.GetOpenedActiveDBForLevel(ctx, lvlPath) if err != nil { if !isLogical(err) { i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index b177d20fcf..bfea97afe6 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -35,7 +35,7 @@ func testRebuildFailoverOnlyMoveInfoSaved(t *testing.T) { dir := t.TempDir() blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) require.NoError(t, blz.Init()) obj := blobstortest.NewObject(1024) @@ -65,7 +65,7 @@ func testRebuildFailoverObjectSavedToTarget(t *testing.T) { dir := t.TempDir() blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) require.NoError(t, blz.Init()) obj := blobstortest.NewObject(1024) @@ -89,7 +89,7 @@ func testRebuildFailoverObjectSavedToTarget(t *testing.T) { require.NoError(t, err) blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) require.NoError(t, blz.Init()) _, err = blz.Put(context.Background(), pPrm) @@ -105,7 +105,7 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { dir := t.TempDir() blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) require.NoError(t, blz.Init()) obj := blobstortest.NewObject(1024) @@ -123,7 +123,7 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { require.NoError(t, err) blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) require.NoError(t, blz.Init()) var pPrm blobovnicza.PutPrm @@ -173,7 +173,7 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object require.NoError(t, b.Close()) blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) require.NoError(t, blz.Init()) moveInfo, err := blz.ListMoveInfo(context.Background()) @@ -188,7 +188,7 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object require.NoError(t, blz.Close()) blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) - require.NoError(t, blz.Open()) + require.NoError(t, blz.Open(context.Background())) require.NoError(t, blz.Init()) moveInfo, err = blz.ListMoveInfo(context.Background()) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 8963ec0991..a8caa215a5 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -269,8 +269,8 @@ type containerSource struct { func (s *containerSource) IsContainerAvailable(ctx context.Context, id cid.ID) (bool, error) { select { - case <-context.Background().Done(): - return false, context.Background().Err() + case <-ctx.Done(): + return false, ctx.Err() default: } diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 12c0e08421..ef6a009e4a 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -389,7 +389,7 @@ func (c *Client) Wait(ctx context.Context, n uint32) error { height, err = c.rpcActor.GetBlockCount() if err != nil { - c.logger.Error(context.Background(), logs.ClientCantGetBlockchainHeight, + c.logger.Error(ctx, logs.ClientCantGetBlockchainHeight, zap.String("error", err.Error())) return nil } @@ -403,7 +403,7 @@ func (c *Client) Wait(ctx context.Context, n uint32) error { newHeight, err = c.rpcActor.GetBlockCount() if err != nil { - c.logger.Error(context.Background(), logs.ClientCantGetBlockchainHeight243, + c.logger.Error(ctx, logs.ClientCantGetBlockchainHeight243, zap.String("error", err.Error())) return nil } diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 03bba8ab90..3d3d806a4e 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -269,7 +269,7 @@ loop: continue loop } - l.handleNotifyEvent(notifyEvent) + l.handleNotifyEvent(ctx, notifyEvent) case notaryEvent, ok := <-chs.NotaryRequestsCh: if !ok { l.log.Warn(ctx, logs.EventStopEventListenerByNotaryChannel) @@ -316,16 +316,16 @@ func (l *listener) handleNotaryEvent(notaryEvent *result.NotaryRequestEvent) { } } -func (l *listener) handleNotifyEvent(notifyEvent *state.ContainedNotificationEvent) { +func (l *listener) handleNotifyEvent(ctx context.Context, notifyEvent *state.ContainedNotificationEvent) { if err := l.pool.Submit(func() { - l.parseAndHandleNotification(notifyEvent) + l.parseAndHandleNotification(ctx, notifyEvent) }); err != nil { - l.log.Warn(context.Background(), logs.EventListenerWorkerPoolDrained, + l.log.Warn(ctx, logs.EventListenerWorkerPoolDrained, zap.Int("capacity", l.pool.Cap())) } } -func (l *listener) parseAndHandleNotification(notifyEvent *state.ContainedNotificationEvent) { +func (l *listener) parseAndHandleNotification(ctx context.Context, notifyEvent *state.ContainedNotificationEvent) { log := l.log.With( zap.String("script hash LE", notifyEvent.ScriptHash.StringLE()), ) @@ -347,7 +347,7 @@ func (l *listener) parseAndHandleNotification(notifyEvent *state.ContainedNotifi l.mtx.RUnlock() if !ok { - log.Debug(context.Background(), logs.EventEventParserNotSet) + log.Debug(ctx, logs.EventEventParserNotSet) return } @@ -355,7 +355,7 @@ func (l *listener) parseAndHandleNotification(notifyEvent *state.ContainedNotifi // parse the notification event event, err := parser(notifyEvent) if err != nil { - log.Warn(context.Background(), logs.EventCouldNotParseNotificationEvent, + log.Warn(ctx, logs.EventCouldNotParseNotificationEvent, zap.String("error", err.Error()), ) @@ -368,7 +368,7 @@ func (l *listener) parseAndHandleNotification(notifyEvent *state.ContainedNotifi l.mtx.RUnlock() if len(handlers) == 0 { - log.Info(context.Background(), logs.EventNotificationHandlersForParsedNotificationEventWereNotRegistered, + log.Info(ctx, logs.EventNotificationHandlersForParsedNotificationEventWereNotRegistered, zap.Any("event", event), ) diff --git a/pkg/morph/subscriber/subscriber.go b/pkg/morph/subscriber/subscriber.go index 3a2da67573..4ef59ed6ad 100644 --- a/pkg/morph/subscriber/subscriber.go +++ b/pkg/morph/subscriber/subscriber.go @@ -254,7 +254,7 @@ func (s *subscriber) switchEndpoint(ctx context.Context, finishCh chan<- bool) b s.Lock() chs := newSubChannels() go func() { - finishCh <- s.restoreSubscriptions(chs.NotifyChan, chs.BlockChan, chs.NotaryChan) + finishCh <- s.restoreSubscriptions(ctx, chs.NotifyChan, chs.BlockChan, chs.NotaryChan) }() s.current = chs s.Unlock() @@ -295,7 +295,7 @@ drainloop: // restoreSubscriptions restores subscriptions according to // cached information about them. -func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotificationEvent, +func (s *subscriber) restoreSubscriptions(ctx context.Context, notifCh chan<- *state.ContainedNotificationEvent, blCh chan<- *block.Block, notaryCh chan<- *result.NotaryRequestEvent, ) bool { var err error @@ -304,7 +304,7 @@ func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotific if s.subscribedToNewBlocks { _, err = s.client.ReceiveBlocks(blCh) if err != nil { - s.log.Error(context.Background(), logs.ClientCouldNotRestoreBlockSubscriptionAfterRPCSwitch, zap.Error(err)) + s.log.Error(ctx, logs.ClientCouldNotRestoreBlockSubscriptionAfterRPCSwitch, zap.Error(err)) return false } } @@ -313,7 +313,7 @@ func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotific for contract := range s.subscribedEvents { _, err = s.client.ReceiveExecutionNotifications(contract, notifCh) if err != nil { - s.log.Error(context.Background(), logs.ClientCouldNotRestoreNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) + s.log.Error(ctx, logs.ClientCouldNotRestoreNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) return false } } @@ -322,7 +322,7 @@ func (s *subscriber) restoreSubscriptions(notifCh chan<- *state.ContainedNotific for signer := range s.subscribedNotaryEvents { _, err = s.client.ReceiveNotaryRequests(signer, notaryCh) if err != nil { - s.log.Error(context.Background(), logs.ClientCouldNotRestoreNotaryNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) + s.log.Error(ctx, logs.ClientCouldNotRestoreNotaryNotificationSubscriptionAfterRPCSwitch, zap.Error(err)) return false } } From c139892117c3ebd6405ea1362cd7576edda1ac00 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 21 Oct 2024 11:30:31 +0300 Subject: [PATCH 0996/1413] [#1437] ir: Fix contextcheck linter Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-ir/config.go | 38 ++++++++++++++++++------------------- cmd/frostfs-ir/main.go | 12 ++++++------ pkg/innerring/innerring.go | 12 ++++++------ pkg/innerring/state.go | 12 ++++++------ pkg/innerring/state_test.go | 3 ++- 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index 34d9d55950..7415e8e701 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -47,7 +47,7 @@ func reloadConfig() error { return logPrm.Reload() } -func watchForSignal(cancel func()) { +func watchForSignal(ctx context.Context, cancel func()) { ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) @@ -59,49 +59,49 @@ func watchForSignal(cancel func()) { // signals causing application to shut down should have priority over // reconfiguration signal case <-ch: - log.Info(context.Background(), logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) cancel() - shutdown() - log.Info(context.Background(), logs.FrostFSNodeTerminationSignalProcessingIsComplete) + shutdown(ctx) + log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) return case err := <-intErr: // internal application error - log.Info(context.Background(), logs.FrostFSIRInternalError, zap.String("msg", err.Error())) + log.Info(ctx, logs.FrostFSIRInternalError, zap.String("msg", err.Error())) cancel() - shutdown() + shutdown(ctx) return default: // block until any signal is receieved select { case <-ch: - log.Info(context.Background(), logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) + log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) cancel() - shutdown() - log.Info(context.Background(), logs.FrostFSNodeTerminationSignalProcessingIsComplete) + shutdown(ctx) + log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) return case err := <-intErr: // internal application error - log.Info(context.Background(), logs.FrostFSIRInternalError, zap.String("msg", err.Error())) + log.Info(ctx, logs.FrostFSIRInternalError, zap.String("msg", err.Error())) cancel() - shutdown() + shutdown(ctx) return case <-sighupCh: - log.Info(context.Background(), logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) - if !innerRing.CompareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { - log.Info(context.Background(), logs.FrostFSNodeSIGHUPSkip) + log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) + if !innerRing.CompareAndSwapHealthStatus(ctx, control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { + log.Info(ctx, logs.FrostFSNodeSIGHUPSkip) break } err := reloadConfig() if err != nil { - log.Error(context.Background(), logs.FrostFSNodeConfigurationReading, zap.Error(err)) + log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err)) } pprofCmp.reload() metricsCmp.reload() - log.Info(context.Background(), logs.FrostFSIRReloadExtraWallets) + log.Info(ctx, logs.FrostFSIRReloadExtraWallets) err = innerRing.SetExtraWallets(cfg) if err != nil { - log.Error(context.Background(), logs.FrostFSNodeConfigurationReading, zap.Error(err)) + log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err)) } - innerRing.CompareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) - log.Info(context.Background(), logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) + innerRing.CompareAndSwapHealthStatus(ctx, control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) + log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) } } } diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 55a8ce00dd..bcb2c5dd88 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -106,7 +106,7 @@ func main() { log.Info(ctx, logs.CommonApplicationStarted, zap.String("version", misc.Version)) - watchForSignal(cancel) + watchForSignal(ctx, cancel) <-ctx.Done() // graceful shutdown log.Debug(ctx, logs.FrostFSNodeWaitingForAllProcessesToStop) @@ -115,20 +115,20 @@ func main() { log.Info(ctx, logs.FrostFSIRApplicationStopped) } -func shutdown() { - innerRing.Stop() +func shutdown(ctx context.Context) { + innerRing.Stop(ctx) if err := metricsCmp.shutdown(); err != nil { - log.Debug(context.Background(), logs.FrostFSIRCouldNotShutdownHTTPServer, + log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } if err := pprofCmp.shutdown(); err != nil { - log.Debug(context.Background(), logs.FrostFSIRCouldNotShutdownHTTPServer, + log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } if err := sdnotify.ClearStatus(); err != nil { - log.Error(context.Background(), logs.FailedToReportStatusToSystemd, zap.Error(err)) + log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 63a4cb1cb9..67927c10cc 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -140,10 +140,10 @@ var ( // Start runs all event providers. func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { - s.setHealthStatus(control.HealthStatus_STARTING) + s.setHealthStatus(ctx, control.HealthStatus_STARTING) defer func() { if err == nil { - s.setHealthStatus(control.HealthStatus_READY) + s.setHealthStatus(ctx, control.HealthStatus_READY) } }() @@ -299,15 +299,15 @@ func (s *Server) startWorkers(ctx context.Context) { } // Stop closes all subscription channels. -func (s *Server) Stop() { - s.setHealthStatus(control.HealthStatus_SHUTTING_DOWN) +func (s *Server) Stop(ctx context.Context) { + s.setHealthStatus(ctx, control.HealthStatus_SHUTTING_DOWN) go s.morphListener.Stop() go s.mainnetListener.Stop() for _, c := range s.closers { if err := c(); err != nil { - s.log.Warn(context.Background(), logs.InnerringCloserError, + s.log.Warn(ctx, logs.InnerringCloserError, zap.String("error", err.Error()), ) } @@ -349,7 +349,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan return nil, err } - server.setHealthStatus(control.HealthStatus_HEALTH_STATUS_UNDEFINED) + server.setHealthStatus(ctx, control.HealthStatus_HEALTH_STATUS_UNDEFINED) // parse notary support server.feeConfig = config.NewFeeConfig(cfg) diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index 250f41e5f3..2dbcd74945 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -154,17 +154,17 @@ func (s *Server) ResetEpochTimer(h uint32) error { return s.epochTimer.Reset() } -func (s *Server) setHealthStatus(hs control.HealthStatus) { +func (s *Server) setHealthStatus(ctx context.Context, hs control.HealthStatus) { s.healthStatus.Store(int32(hs)) - s.notifySystemd(hs) + s.notifySystemd(ctx, hs) if s.irMetrics != nil { s.irMetrics.SetHealth(int32(hs)) } } -func (s *Server) CompareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swapped bool) { +func (s *Server) CompareAndSwapHealthStatus(ctx context.Context, oldSt, newSt control.HealthStatus) (swapped bool) { if swapped = s.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped { - s.notifySystemd(newSt) + s.notifySystemd(ctx, newSt) if s.irMetrics != nil { s.irMetrics.SetHealth(int32(newSt)) } @@ -187,7 +187,7 @@ func initPersistentStateStorage(cfg *viper.Viper) (*state.PersistentStorage, err return persistStorage, nil } -func (s *Server) notifySystemd(st control.HealthStatus) { +func (s *Server) notifySystemd(ctx context.Context, st control.HealthStatus) { if !s.sdNotify { return } @@ -203,6 +203,6 @@ func (s *Server) notifySystemd(st control.HealthStatus) { err = sdnotify.Status(fmt.Sprintf("%v", st)) } if err != nil { - s.log.Error(context.Background(), logs.FailedToReportStatusToSystemd, zap.Error(err)) + s.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/pkg/innerring/state_test.go b/pkg/innerring/state_test.go index fe09f8f2d3..9313edf780 100644 --- a/pkg/innerring/state_test.go +++ b/pkg/innerring/state_test.go @@ -1,6 +1,7 @@ package innerring import ( + "context" "testing" "time" @@ -42,7 +43,7 @@ func TestServerState(t *testing.T) { require.Equal(t, epochDuration, srv.EpochDuration(), "invalid epoch duration") var healthStatus control.HealthStatus = control.HealthStatus_READY - srv.setHealthStatus(healthStatus) + srv.setHealthStatus(context.Background(), healthStatus) require.Equal(t, healthStatus, srv.HealthStatus(), "invalid health status") require.True(t, srv.IsActive(), "invalid IsActive result") From 16598553d9603cdf7d5b349db250041a80f9ec14 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 21 Oct 2024 11:56:38 +0300 Subject: [PATCH 0997/1413] [#1437] shard: Fix contextcheck linter Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobstor/mode.go | 4 +-- pkg/local_object_storage/engine/control.go | 20 +++++------ pkg/local_object_storage/engine/engine.go | 10 +++--- pkg/local_object_storage/engine/error_test.go | 4 +-- .../engine/evacuate_test.go | 36 +++++++++---------- pkg/local_object_storage/engine/shards.go | 36 +++++++++---------- .../engine/shards_test.go | 10 +++--- .../internal/storagetest/storage.go | 12 +++---- pkg/local_object_storage/metabase/control.go | 14 ++++---- pkg/local_object_storage/metabase/mode.go | 5 +-- pkg/local_object_storage/metabase/shard_id.go | 9 ++--- .../metabase/version_test.go | 2 +- pkg/local_object_storage/pilorama/boltdb.go | 2 +- pkg/local_object_storage/pilorama/forest.go | 2 +- .../pilorama/interface.go | 2 +- pkg/local_object_storage/shard/control.go | 34 +++++++++--------- .../shard/control_test.go | 16 ++++----- pkg/local_object_storage/shard/delete_test.go | 2 +- .../shard/gc_internal_test.go | 2 +- pkg/local_object_storage/shard/gc_test.go | 8 ++--- pkg/local_object_storage/shard/get_test.go | 2 +- pkg/local_object_storage/shard/head_test.go | 2 +- pkg/local_object_storage/shard/id.go | 7 ++-- pkg/local_object_storage/shard/inhume_test.go | 2 +- pkg/local_object_storage/shard/list_test.go | 4 +-- pkg/local_object_storage/shard/lock_test.go | 4 +-- .../shard/metrics_test.go | 6 ++-- pkg/local_object_storage/shard/mode.go | 16 +++++---- pkg/local_object_storage/shard/range_test.go | 2 +- pkg/local_object_storage/shard/rebuild.go | 4 +-- pkg/local_object_storage/shard/refill_test.go | 6 ++-- pkg/local_object_storage/shard/reload_test.go | 2 +- .../shard/shutdown_test.go | 4 +-- .../writecache/flush_test.go | 20 +++++------ pkg/local_object_storage/writecache/mode.go | 4 +-- .../writecache/writecache.go | 2 +- pkg/services/control/server/detach_shards.go | 4 +-- pkg/services/control/server/set_shard_mode.go | 4 +-- 38 files changed, 165 insertions(+), 160 deletions(-) diff --git a/pkg/local_object_storage/blobstor/mode.go b/pkg/local_object_storage/blobstor/mode.go index a579a6f929..f081ff6451 100644 --- a/pkg/local_object_storage/blobstor/mode.go +++ b/pkg/local_object_storage/blobstor/mode.go @@ -8,7 +8,7 @@ import ( ) // SetMode sets the blobstor mode of operation. -func (b *BlobStor) SetMode(m mode.Mode) error { +func (b *BlobStor) SetMode(ctx context.Context, m mode.Mode) error { b.modeMtx.Lock() defer b.modeMtx.Unlock() @@ -22,7 +22,7 @@ func (b *BlobStor) SetMode(m mode.Mode) error { err := b.Close() if err == nil { - if err = b.openBlobStor(context.TODO(), m); err == nil { + if err = b.openBlobStor(ctx, m); err == nil { err = b.Init() } } diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index 98ec73ae96..a5c53dcadb 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -56,7 +56,7 @@ func (e *StorageEngine) open(ctx context.Context) error { sh := e.shards[res.id] delete(e.shards, res.id) - err := sh.Close() + err := sh.Close(ctx) if err != nil { e.log.Error(ctx, logs.EngineCouldNotClosePartiallyInitializedShard, zap.String("id", res.id), @@ -108,7 +108,7 @@ func (e *StorageEngine) Init(ctx context.Context) error { sh := e.shards[res.id] delete(e.shards, res.id) - err := sh.Close() + err := sh.Close(ctx) if err != nil { e.log.Error(ctx, logs.EngineCouldNotClosePartiallyInitializedShard, zap.String("id", res.id), @@ -126,7 +126,7 @@ func (e *StorageEngine) Init(ctx context.Context) error { } e.wg.Add(1) - go e.setModeLoop() + go e.setModeLoop(ctx) return nil } @@ -153,7 +153,7 @@ func (e *StorageEngine) Close(ctx context.Context) error { } // closes all shards. Never returns an error, shard errors are logged. -func (e *StorageEngine) close(releasePools bool) error { +func (e *StorageEngine) close(ctx context.Context, releasePools bool) error { e.mtx.RLock() defer e.mtx.RUnlock() @@ -164,8 +164,8 @@ func (e *StorageEngine) close(releasePools bool) error { } for id, sh := range e.shards { - if err := sh.Close(); err != nil { - e.log.Debug(context.Background(), logs.EngineCouldNotCloseShard, + if err := sh.Close(ctx); err != nil { + e.log.Debug(ctx, logs.EngineCouldNotCloseShard, zap.String("id", id), zap.String("error", err.Error()), ) @@ -213,7 +213,7 @@ func (e *StorageEngine) setBlockExecErr(ctx context.Context, err error) error { return e.open(ctx) } } else if prevErr == nil { // ok -> block - return e.close(errors.Is(err, errClosed)) + return e.close(ctx, errors.Is(err, errClosed)) } // otherwise do nothing @@ -306,7 +306,7 @@ loop: e.mtx.RUnlock() - e.removeShards(shardsToRemove...) + e.removeShards(ctx, shardsToRemove...) for _, p := range shardsToReload { err := p.sh.Reload(ctx, p.opts...) @@ -330,13 +330,13 @@ loop: err = sh.Init(ctx) } if err != nil { - _ = sh.Close() + _ = sh.Close(ctx) return fmt.Errorf("could not init %s shard: %w", idStr, err) } err = e.addShard(sh) if err != nil { - _ = sh.Close() + _ = sh.Close(ctx) return fmt.Errorf("could not add %s shard: %w", idStr, err) } diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index a8caa215a5..6e30ee9de7 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -55,7 +55,7 @@ type setModeRequest struct { // setModeLoop listens setModeCh to perform degraded mode transition of a single shard. // Instead of creating a worker per single shard we use a single goroutine. -func (e *StorageEngine) setModeLoop() { +func (e *StorageEngine) setModeLoop(ctx context.Context) { defer e.wg.Done() var ( @@ -75,7 +75,7 @@ func (e *StorageEngine) setModeLoop() { if !ok { inProgress[sid] = struct{}{} go func() { - e.moveToDegraded(r.sh, r.errorCount, r.isMeta) + e.moveToDegraded(ctx, r.sh, r.errorCount, r.isMeta) mtx.Lock() delete(inProgress, sid) @@ -87,7 +87,7 @@ func (e *StorageEngine) setModeLoop() { } } -func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32, isMeta bool) { +func (e *StorageEngine) moveToDegraded(ctx context.Context, sh *shard.Shard, errCount uint32, isMeta bool) { sid := sh.ID() log := e.log.With( zap.Stringer("shard_id", sid), @@ -97,7 +97,7 @@ func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32, isMeta defer e.mtx.RUnlock() if isMeta { - err := sh.SetMode(mode.DegradedReadOnly) + err := sh.SetMode(ctx, mode.DegradedReadOnly) if err == nil { log.Info(context.Background(), logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) return @@ -106,7 +106,7 @@ func (e *StorageEngine) moveToDegraded(sh *shard.Shard, errCount uint32, isMeta zap.Error(err)) } - err := sh.SetMode(mode.ReadOnly) + err := sh.SetMode(ctx, mode.ReadOnly) if err != nil { log.Error(context.Background(), logs.EngineFailedToMoveShardInReadonlyMode, zap.Error(err)) return diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 1619003a15..57c423764a 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -158,10 +158,10 @@ func TestErrorReporting(t *testing.T) { checkShardState(t, te.ng, te.shards[1].id, 0, mode.ReadWrite) } - require.NoError(t, te.ng.SetShardMode(te.shards[0].id, mode.ReadWrite, false)) + require.NoError(t, te.ng.SetShardMode(context.Background(), te.shards[0].id, mode.ReadWrite, false)) checkShardState(t, te.ng, te.shards[0].id, errThreshold+1, mode.ReadWrite) - require.NoError(t, te.ng.SetShardMode(te.shards[0].id, mode.ReadWrite, true)) + require.NoError(t, te.ng.SetShardMode(context.Background(), te.shards[0].id, mode.ReadWrite, true)) checkShardState(t, te.ng, te.shards[0].id, 0, mode.ReadWrite) require.NoError(t, te.ng.Close(context.Background())) }) diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 8498c92455..54eacc3f28 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -146,7 +146,7 @@ func TestEvacuateShardObjects(t *testing.T) { require.Equal(t, uint64(0), res.ObjectsEvacuated()) }) - require.NoError(t, e.shards[evacuateShardID].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[evacuateShardID].SetMode(context.Background(), mode.ReadOnly)) res, err := e.Evacuate(context.Background(), prm) require.NoError(t, err) @@ -237,7 +237,7 @@ func TestEvacuateObjectsNetwork(t *testing.T) { evacuateShardID := ids[0].String() - require.NoError(t, e.shards[evacuateShardID].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[evacuateShardID].SetMode(context.Background(), mode.ReadOnly)) var prm EvacuateShardPrm prm.ShardID = ids[0:1] @@ -260,8 +260,8 @@ func TestEvacuateObjectsNetwork(t *testing.T) { require.NoError(t, e.Close(context.Background())) }() - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) - require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) + require.NoError(t, e.shards[ids[1].String()].SetMode(context.Background(), mode.ReadOnly)) var prm EvacuateShardPrm prm.ShardID = ids[1:2] @@ -298,7 +298,7 @@ func TestEvacuateObjectsNetwork(t *testing.T) { } for i := range ids { - require.NoError(t, e.shards[ids[i].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[i].String()].SetMode(context.Background(), mode.ReadOnly)) } var prm EvacuateShardPrm @@ -327,8 +327,8 @@ func TestEvacuateCancellation(t *testing.T) { require.NoError(t, e.Close(context.Background())) }() - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) - require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) + require.NoError(t, e.shards[ids[1].String()].SetMode(context.Background(), mode.ReadOnly)) var prm EvacuateShardPrm prm.ShardID = ids[1:2] @@ -357,8 +357,8 @@ func TestEvacuateCancellationByError(t *testing.T) { require.NoError(t, e.Close(context.Background())) }() - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) - require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) + require.NoError(t, e.shards[ids[1].String()].SetMode(context.Background(), mode.ReadOnly)) var prm EvacuateShardPrm prm.ShardID = ids[1:2] @@ -386,8 +386,8 @@ func TestEvacuateSingleProcess(t *testing.T) { require.NoError(t, e.Close(context.Background())) }() - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) - require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) + require.NoError(t, e.shards[ids[1].String()].SetMode(context.Background(), mode.ReadOnly)) blocker := make(chan interface{}) running := make(chan interface{}) @@ -429,8 +429,8 @@ func TestEvacuateObjectsAsync(t *testing.T) { require.NoError(t, e.Close(context.Background())) }() - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) - require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) + require.NoError(t, e.shards[ids[1].String()].SetMode(context.Background(), mode.ReadOnly)) blocker := make(chan interface{}) running := make(chan interface{}) @@ -515,7 +515,7 @@ func TestEvacuateTreesLocal(t *testing.T) { require.NoError(t, e.Close(context.Background())) }() - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) var prm EvacuateShardPrm prm.ShardID = ids[0:1] @@ -594,8 +594,8 @@ func TestEvacuateTreesRemote(t *testing.T) { require.NoError(t, e.Close(context.Background())) }() - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) - require.NoError(t, e.shards[ids[1].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) + require.NoError(t, e.shards[ids[1].String()].SetMode(context.Background(), mode.ReadOnly)) mutex := sync.Mutex{} evacuatedTreeOps := make(map[string][]*pilorama.Move) @@ -753,7 +753,7 @@ func TestEvacuateShardObjectsRepOneOnly(t *testing.T) { prm.Scope = EvacuateScopeObjects prm.RepOneOnly = true - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) res, err := e.Evacuate(context.Background(), prm) require.NoError(t, err) @@ -810,7 +810,7 @@ func TestEvacuateShardObjectsRepOneOnlyBench(t *testing.T) { prm.RepOneOnly = true prm.ContainerWorkerCount = 10 - require.NoError(t, e.shards[ids[0].String()].SetMode(mode.ReadOnly)) + require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) start := time.Now() _, err := e.Evacuate(context.Background(), prm) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index e172706e3a..2b94103e99 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -121,7 +121,7 @@ func (e *StorageEngine) AddShard(ctx context.Context, opts ...shard.Option) (*sh return sh.ID(), nil } -func (e *StorageEngine) createShard(_ context.Context, opts []shard.Option) (*shard.Shard, error) { +func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (*shard.Shard, error) { id, err := generateShardID() if err != nil { return nil, fmt.Errorf("could not generate shard ID: %w", err) @@ -139,8 +139,8 @@ func (e *StorageEngine) createShard(_ context.Context, opts []shard.Option) (*sh shard.WithZeroCountCallback(e.processZeroCountContainers), )...) - if err := sh.UpdateID(); err != nil { - e.log.Warn(context.Background(), logs.FailedToUpdateShardID, zap.Stringer("shard_id", sh.ID()), zap.String("metabase_path", sh.DumpInfo().MetaBaseInfo.Path), zap.Error(err)) + if err := sh.UpdateID(ctx); err != nil { + e.log.Warn(ctx, logs.FailedToUpdateShardID, zap.Stringer("shard_id", sh.ID()), zap.String("metabase_path", sh.DumpInfo().MetaBaseInfo.Path), zap.Error(err)) } return sh, nil @@ -203,7 +203,7 @@ func (e *StorageEngine) addShard(sh *shard.Shard) error { // removeShards removes specified shards. Skips non-existent shards. // Logs errors about shards that it could not Close after the removal. -func (e *StorageEngine) removeShards(ids ...string) { +func (e *StorageEngine) removeShards(ctx context.Context, ids ...string) { if len(ids) == 0 { return } @@ -228,22 +228,22 @@ func (e *StorageEngine) removeShards(ids ...string) { delete(e.shardPools, id) } - e.log.Info(context.Background(), logs.EngineShardHasBeenRemoved, + e.log.Info(ctx, logs.EngineShardHasBeenRemoved, zap.String("id", id)) } e.mtx.Unlock() for _, sh := range ss { - err := sh.SetMode(mode.Disabled) + err := sh.SetMode(ctx, mode.Disabled) if err != nil { - e.log.Error(context.Background(), logs.EngineCouldNotChangeShardModeToDisabled, + e.log.Error(ctx, logs.EngineCouldNotChangeShardModeToDisabled, zap.Stringer("id", sh.ID()), zap.Error(err), ) } - err = sh.Close() + err = sh.Close(ctx) if err != nil { - e.log.Error(context.Background(), logs.EngineCouldNotCloseRemovedShard, + e.log.Error(ctx, logs.EngineCouldNotCloseRemovedShard, zap.Stringer("id", sh.ID()), zap.Error(err), ) @@ -310,7 +310,7 @@ func (e *StorageEngine) iterateOverUnsortedShards(handler func(hashedShard) (sto // SetShardMode sets mode of the shard with provided identifier. // // Returns an error if shard mode was not set, or shard was not found in storage engine. -func (e *StorageEngine) SetShardMode(id *shard.ID, m mode.Mode, resetErrorCounter bool) error { +func (e *StorageEngine) SetShardMode(ctx context.Context, id *shard.ID, m mode.Mode, resetErrorCounter bool) error { e.mtx.RLock() defer e.mtx.RUnlock() @@ -320,7 +320,7 @@ func (e *StorageEngine) SetShardMode(id *shard.ID, m mode.Mode, resetErrorCounte sh.errorCount.Store(0) e.metrics.ClearErrorCounter(shID) } - return sh.SetMode(m) + return sh.SetMode(ctx, m) } } @@ -346,7 +346,7 @@ func (e *StorageEngine) HandleNewEpoch(ctx context.Context, epoch uint64) { } } -func (e *StorageEngine) DetachShards(ids []*shard.ID) error { +func (e *StorageEngine) DetachShards(ctx context.Context, ids []*shard.ID) error { if len(ids) == 0 { return logicerr.New("ids must be non-empty") } @@ -356,20 +356,20 @@ func (e *StorageEngine) DetachShards(ids []*shard.ID) error { return err } - return e.closeShards(deletedShards) + return e.closeShards(ctx, deletedShards) } // closeShards closes deleted shards. Tries to close all shards. // Returns single error with joined shard errors. -func (e *StorageEngine) closeShards(deletedShards []hashedShard) error { +func (e *StorageEngine) closeShards(ctx context.Context, deletedShards []hashedShard) error { var multiErr error var multiErrGuard sync.Mutex var eg errgroup.Group for _, sh := range deletedShards { eg.Go(func() error { - err := sh.SetMode(mode.Disabled) + err := sh.SetMode(ctx, mode.Disabled) if err != nil { - e.log.Error(context.Background(), logs.EngineCouldNotChangeShardModeToDisabled, + e.log.Error(ctx, logs.EngineCouldNotChangeShardModeToDisabled, zap.Stringer("id", sh.ID()), zap.Error(err), ) @@ -378,9 +378,9 @@ func (e *StorageEngine) closeShards(deletedShards []hashedShard) error { multiErrGuard.Unlock() } - err = sh.Close() + err = sh.Close(ctx) if err != nil { - e.log.Error(context.Background(), logs.EngineCouldNotCloseRemovedShard, + e.log.Error(ctx, logs.EngineCouldNotCloseRemovedShard, zap.Stringer("id", sh.ID()), zap.Error(err), ) diff --git a/pkg/local_object_storage/engine/shards_test.go b/pkg/local_object_storage/engine/shards_test.go index 3347d58f19..207491bd4e 100644 --- a/pkg/local_object_storage/engine/shards_test.go +++ b/pkg/local_object_storage/engine/shards_test.go @@ -33,7 +33,7 @@ func TestRemoveShard(t *testing.T) { for id, remove := range mSh { if remove { - e.removeShards(id) + e.removeShards(context.Background(), id) } } @@ -55,11 +55,11 @@ func TestDisableShards(t *testing.T) { e, ids := te.engine, te.shardIDs defer func() { require.NoError(t, e.Close(context.Background())) }() - require.ErrorAs(t, e.DetachShards(ids), new(logicerr.Logical)) - require.ErrorAs(t, e.DetachShards(nil), new(logicerr.Logical)) - require.ErrorAs(t, e.DetachShards([]*shard.ID{}), new(logicerr.Logical)) + require.ErrorAs(t, e.DetachShards(context.Background(), ids), new(logicerr.Logical)) + require.ErrorAs(t, e.DetachShards(context.Background(), nil), new(logicerr.Logical)) + require.ErrorAs(t, e.DetachShards(context.Background(), []*shard.ID{}), new(logicerr.Logical)) - require.NoError(t, e.DetachShards([]*shard.ID{ids[0]})) + require.NoError(t, e.DetachShards(context.Background(), []*shard.ID{ids[0]})) require.Equal(t, 1, len(e.shards)) } diff --git a/pkg/local_object_storage/internal/storagetest/storage.go b/pkg/local_object_storage/internal/storagetest/storage.go index 586b3dcc65..d8ac106dd6 100644 --- a/pkg/local_object_storage/internal/storagetest/storage.go +++ b/pkg/local_object_storage/internal/storagetest/storage.go @@ -11,7 +11,7 @@ import ( // Component represents single storage component. type Component interface { Open(context.Context, mode.Mode) error - SetMode(mode.Mode) error + SetMode(context.Context, mode.Mode) error Init() error Close() error } @@ -91,12 +91,12 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { // call `SetMode` on all not-yet-initialized components. s := cons(t) require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, s.SetMode(m)) + require.NoError(t, s.SetMode(context.Background(), m)) t.Run("after open in RO", func(t *testing.T) { require.NoError(t, s.Close()) require.NoError(t, s.Open(context.Background(), mode.ReadOnly)) - require.NoError(t, s.SetMode(m)) + require.NoError(t, s.SetMode(context.Background(), m)) }) require.NoError(t, s.Close()) @@ -106,7 +106,7 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { // Use-case: notmal node operation. require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) require.NoError(t, s.Init()) - require.NoError(t, s.SetMode(m)) + require.NoError(t, s.SetMode(context.Background(), m)) require.NoError(t, s.Close()) }) } @@ -116,7 +116,7 @@ func TestModeTransition(t *testing.T, cons Constructor, from, to mode.Mode) { s := cons(t) require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) require.NoError(t, s.Init()) - require.NoError(t, s.SetMode(from)) - require.NoError(t, s.SetMode(to)) + require.NoError(t, s.SetMode(context.Background(), from)) + require.NoError(t, s.SetMode(context.Background(), to)) require.NoError(t, s.Close()) } diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 68e065a0ad..54bea42046 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -39,7 +39,7 @@ var ( ) // Open boltDB instance for metabase. -func (db *DB) Open(_ context.Context, m mode.Mode) error { +func (db *DB) Open(ctx context.Context, m mode.Mode) error { db.modeMtx.Lock() defer db.modeMtx.Unlock() db.mode = m @@ -48,10 +48,10 @@ func (db *DB) Open(_ context.Context, m mode.Mode) error { if m.NoMetabase() { return nil } - return db.openDB(m) + return db.openDB(ctx, m) } -func (db *DB) openDB(mode mode.Mode) error { +func (db *DB) openDB(ctx context.Context, mode mode.Mode) error { err := util.MkdirAllX(filepath.Dir(db.info.Path), db.info.Permission) if err != nil { return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err) @@ -65,10 +65,10 @@ func (db *DB) openDB(mode mode.Mode) error { } db.boltOptions.ReadOnly = mode.ReadOnly() - return metaerr.Wrap(db.openBolt()) + return metaerr.Wrap(db.openBolt(ctx)) } -func (db *DB) openBolt() error { +func (db *DB) openBolt(ctx context.Context) error { var err error db.boltDB, err = bbolt.Open(db.info.Path, db.info.Permission, db.boltOptions) @@ -226,7 +226,7 @@ func (db *DB) close() error { // If there was a problem with applying new configuration, an error is returned. // // If a metabase was couldn't be reopened because of an error, ErrDegradedMode is returned. -func (db *DB) Reload(opts ...Option) (bool, error) { +func (db *DB) Reload(ctx context.Context, opts ...Option) (bool, error) { var c cfg for i := range opts { opts[i](&c) @@ -243,7 +243,7 @@ func (db *DB) Reload(opts ...Option) (bool, error) { db.mode = mode.Disabled db.metrics.SetMode(mode.ComponentDisabled) db.info.Path = c.info.Path - if err := db.openBolt(); err != nil { + if err := db.openBolt(ctx); err != nil { return false, metaerr.Wrap(fmt.Errorf("%w: %v", ErrDegradedMode, err)) } diff --git a/pkg/local_object_storage/metabase/mode.go b/pkg/local_object_storage/metabase/mode.go index 2032ed6b20..f99262be47 100644 --- a/pkg/local_object_storage/metabase/mode.go +++ b/pkg/local_object_storage/metabase/mode.go @@ -1,6 +1,7 @@ package meta import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -8,7 +9,7 @@ import ( // SetMode sets the metabase mode of operation. // If the mode assumes no operation metabase, the database is closed. -func (db *DB) SetMode(m mode.Mode) error { +func (db *DB) SetMode(ctx context.Context, m mode.Mode) error { db.modeMtx.Lock() defer db.modeMtx.Unlock() @@ -25,7 +26,7 @@ func (db *DB) SetMode(m mode.Mode) error { if m.NoMetabase() { db.boltDB = nil } else { - err := db.openDB(m) + err := db.openDB(ctx, m) if err == nil && !m.ReadOnly() { err = db.Init() } diff --git a/pkg/local_object_storage/metabase/shard_id.go b/pkg/local_object_storage/metabase/shard_id.go index 88446494ee..e58115bc82 100644 --- a/pkg/local_object_storage/metabase/shard_id.go +++ b/pkg/local_object_storage/metabase/shard_id.go @@ -2,6 +2,7 @@ package meta import ( "bytes" + "context" "errors" "fmt" "os" @@ -21,7 +22,7 @@ var ( // If id is missing, returns nil, nil. // // GetShardID does not report any metrics. -func (db *DB) GetShardID(mode metamode.Mode) ([]byte, error) { +func (db *DB) GetShardID(ctx context.Context, mode metamode.Mode) ([]byte, error) { db.modeMtx.Lock() defer db.modeMtx.Unlock() db.mode = mode @@ -30,7 +31,7 @@ func (db *DB) GetShardID(mode metamode.Mode) ([]byte, error) { return nil, nil } - if err := db.openDB(mode); err != nil { + if err := db.openDB(ctx, mode); err != nil { return nil, fmt.Errorf("failed to open metabase: %w", err) } @@ -59,7 +60,7 @@ func (db *DB) readShardID() ([]byte, error) { // SetShardID sets metabase operation mode // and writes shard id to db. -func (db *DB) SetShardID(id []byte, mode metamode.Mode) error { +func (db *DB) SetShardID(ctx context.Context, id []byte, mode metamode.Mode) error { db.modeMtx.Lock() defer db.modeMtx.Unlock() db.mode = mode @@ -68,7 +69,7 @@ func (db *DB) SetShardID(id []byte, mode metamode.Mode) error { return ErrReadOnlyMode } - if err := db.openDB(mode); err != nil { + if err := db.openDB(ctx, mode); err != nil { return fmt.Errorf("failed to open metabase: %w", err) } diff --git a/pkg/local_object_storage/metabase/version_test.go b/pkg/local_object_storage/metabase/version_test.go index 75229a1b44..509e72479e 100644 --- a/pkg/local_object_storage/metabase/version_test.go +++ b/pkg/local_object_storage/metabase/version_test.go @@ -58,7 +58,7 @@ func TestVersion(t *testing.T) { }) t.Run("old data", func(t *testing.T) { db := newDB(t) - require.NoError(t, db.SetShardID([]byte{1, 2, 3, 4}, mode.ReadWrite)) + require.NoError(t, db.SetShardID(context.Background(), []byte{1, 2, 3, 4}, mode.ReadWrite)) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.Init()) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index a778434dd2..9ffcf1e83a 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -91,7 +91,7 @@ func NewBoltForest(opts ...Option) ForestStorage { return &b } -func (t *boltForest) SetMode(m mode.Mode) error { +func (t *boltForest) SetMode(_ context.Context, m mode.Mode) error { t.modeMtx.Lock() defer t.modeMtx.Unlock() diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index 3749437457..76da1c0c24 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -128,7 +128,7 @@ func (f *memoryForest) Open(context.Context, mode.Mode) error { return nil } -func (f *memoryForest) SetMode(mode.Mode) error { +func (f *memoryForest) SetMode(context.Context, mode.Mode) error { return nil } diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index b6ca246f2e..9717b2401e 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -65,7 +65,7 @@ type ForestStorage interface { Init() error Open(context.Context, mode.Mode) error Close() error - SetMode(m mode.Mode) error + SetMode(context.Context, mode.Mode) error SetParentID(id string) Forest diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index eb3aa61c07..056737a9d9 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -20,23 +20,23 @@ import ( "golang.org/x/sync/errgroup" ) -func (s *Shard) handleMetabaseFailure(stage string, err error) error { - s.log.Error(context.Background(), logs.ShardMetabaseFailureSwitchingMode, +func (s *Shard) handleMetabaseFailure(ctx context.Context, stage string, err error) error { + s.log.Error(ctx, logs.ShardMetabaseFailureSwitchingMode, zap.String("stage", stage), zap.Stringer("mode", mode.ReadOnly), zap.Error(err)) - err = s.SetMode(mode.ReadOnly) + err = s.SetMode(ctx, mode.ReadOnly) if err == nil { return nil } - s.log.Error(context.Background(), logs.ShardCantMoveShardToReadonlySwitchMode, + s.log.Error(ctx, logs.ShardCantMoveShardToReadonlySwitchMode, zap.String("stage", stage), zap.Stringer("mode", mode.DegradedReadOnly), zap.Error(err)) - err = s.SetMode(mode.DegradedReadOnly) + err = s.SetMode(ctx, mode.DegradedReadOnly) if err != nil { return fmt.Errorf("could not switch to mode %s", mode.Mode(mode.DegradedReadOnly)) } @@ -75,7 +75,7 @@ func (s *Shard) Open(ctx context.Context) error { return fmt.Errorf("could not open %T: %w", components[j], err) } } - err = s.handleMetabaseFailure("open", err) + err = s.handleMetabaseFailure(ctx, "open", err) if err != nil { return err } @@ -101,7 +101,7 @@ func (x *metabaseSynchronizer) Init() error { // Init initializes all Shard's components. func (s *Shard) Init(ctx context.Context) error { m := s.GetMode() - if err := s.initializeComponents(m); err != nil { + if err := s.initializeComponents(ctx, m); err != nil { return err } @@ -138,7 +138,7 @@ func (s *Shard) Init(ctx context.Context) error { return nil } -func (s *Shard) initializeComponents(m mode.Mode) error { +func (s *Shard) initializeComponents(ctx context.Context, m mode.Mode) error { type initializer interface { Init() error } @@ -176,7 +176,7 @@ func (s *Shard) initializeComponents(m mode.Mode) error { return fmt.Errorf("metabase initialization: %w", err) } - err = s.handleMetabaseFailure("init", err) + err = s.handleMetabaseFailure(ctx, "init", err) if err != nil { return err } @@ -364,9 +364,9 @@ func (s *Shard) refillTombstoneObject(ctx context.Context, obj *objectSDK.Object } // Close releases all Shard's components. -func (s *Shard) Close() error { +func (s *Shard) Close(ctx context.Context) error { if s.rb != nil { - s.rb.Stop(s.log) + s.rb.Stop(ctx, s.log) } var components []interface{ Close() error } @@ -386,7 +386,7 @@ func (s *Shard) Close() error { for _, component := range components { if err := component.Close(); err != nil { lastErr = err - s.log.Error(context.Background(), logs.ShardCouldNotCloseShardComponent, zap.Error(err)) + s.log.Error(ctx, logs.ShardCouldNotCloseShardComponent, zap.Error(err)) } } @@ -414,18 +414,18 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { unlock := s.lockExclusive() defer unlock() - s.rb.Stop(s.log) + s.rb.Stop(ctx, s.log) if !s.info.Mode.NoMetabase() { defer func() { s.rb.Start(ctx, s.blobStor, s.metaBase, s.log) }() } - ok, err := s.metaBase.Reload(c.metaOpts...) + ok, err := s.metaBase.Reload(ctx, c.metaOpts...) if err != nil { if errors.Is(err, meta.ErrDegradedMode) { s.log.Error(ctx, logs.ShardCantOpenMetabaseMoveToADegradedMode, zap.Error(err)) - _ = s.setMode(mode.DegradedReadOnly) + _ = s.setMode(ctx, mode.DegradedReadOnly) } return err } @@ -441,11 +441,11 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { } if err != nil { s.log.Error(ctx, logs.ShardCantInitializeMetabaseMoveToADegradedreadonlyMode, zap.Error(err)) - _ = s.setMode(mode.DegradedReadOnly) + _ = s.setMode(ctx, mode.DegradedReadOnly) return err } } - return s.setMode(c.info.Mode) + return s.setMode(ctx, c.info.Mode) } func (s *Shard) lockExclusive() func() { diff --git a/pkg/local_object_storage/shard/control_test.go b/pkg/local_object_storage/shard/control_test.go index b8f1d44175..6d2cd71370 100644 --- a/pkg/local_object_storage/shard/control_test.go +++ b/pkg/local_object_storage/shard/control_test.go @@ -86,7 +86,7 @@ func TestShardOpen(t *testing.T) { require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) require.Equal(t, mode.ReadWrite, sh.GetMode()) - require.NoError(t, sh.Close()) + require.NoError(t, sh.Close(context.Background())) // Metabase can be opened in read-only => start in ReadOnly mode. allowedMode.Store(int64(os.O_RDONLY)) @@ -95,9 +95,9 @@ func TestShardOpen(t *testing.T) { require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) require.Equal(t, mode.ReadOnly, sh.GetMode()) - require.Error(t, sh.SetMode(mode.ReadWrite)) + require.Error(t, sh.SetMode(context.Background(), mode.ReadWrite)) require.Equal(t, mode.ReadOnly, sh.GetMode()) - require.NoError(t, sh.Close()) + require.NoError(t, sh.Close(context.Background())) // Metabase is corrupted => start in DegradedReadOnly mode. allowedMode.Store(math.MaxInt64) @@ -106,7 +106,7 @@ func TestShardOpen(t *testing.T) { require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) require.Equal(t, mode.DegradedReadOnly, sh.GetMode()) - require.NoError(t, sh.Close()) + require.NoError(t, sh.Close(context.Background())) } func TestRefillMetabaseCorrupted(t *testing.T) { @@ -146,7 +146,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) { putPrm.SetObject(obj) _, err := sh.Put(context.Background(), putPrm) require.NoError(t, err) - require.NoError(t, sh.Close()) + require.NoError(t, sh.Close(context.Background())) addr := object.AddressOf(obj) // This is copied from `fstree.treePath()` to avoid exporting function just for tests. @@ -170,7 +170,7 @@ func TestRefillMetabaseCorrupted(t *testing.T) { getPrm.SetAddress(addr) _, err = sh.Get(context.Background(), getPrm) require.True(t, client.IsErrObjectNotFound(err)) - require.NoError(t, sh.Close()) + require.NoError(t, sh.Close(context.Background())) } func TestRefillMetabase(t *testing.T) { @@ -358,7 +358,7 @@ func TestRefillMetabase(t *testing.T) { phyBefore := c.Phy logicalBefore := c.Logic - err = sh.Close() + err = sh.Close(context.Background()) require.NoError(t, err) sh = New( @@ -379,7 +379,7 @@ func TestRefillMetabase(t *testing.T) { // initialize Blobstor require.NoError(t, sh.Init(context.Background())) - defer sh.Close() + defer sh.Close(context.Background()) checkAllObjs(false) checkObj(object.AddressOf(tombObj), nil) diff --git a/pkg/local_object_storage/shard/delete_test.go b/pkg/local_object_storage/shard/delete_test.go index 574250a939..c9ce93bc59 100644 --- a/pkg/local_object_storage/shard/delete_test.go +++ b/pkg/local_object_storage/shard/delete_test.go @@ -37,7 +37,7 @@ func TestShard_Delete_BigObject(t *testing.T) { func testShard(t *testing.T, hasWriteCache bool, payloadSize int) { sh := newShard(t, hasWriteCache) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() cnr := cidtest.ID() diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 11db5e54eb..39073a529a 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -79,7 +79,7 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { sh = New(opts...) require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() cnr := cidtest.ID() obj := testutil.GenerateObjectWithCID(cnr) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index 2b97111e73..e3670b441b 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -34,7 +34,7 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { return util.NewPseudoWorkerPool() // synchronous event processing })}, }) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() cnr := cidtest.ID() @@ -131,7 +131,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { return util.NewPseudoWorkerPool() // synchronous event processing })}, }) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() lock := testutil.GenerateObjectWithCID(cnr) lock.SetType(objectSDK.TypeLock) @@ -190,7 +190,7 @@ func testGCDropsObjectInhumedFromWritecache(t *testing.T, flushbeforeInhume bool additionalShardOptions: []Option{WithDisabledGC()}, wcOpts: []writecache.Option{writecache.WithDisableBackgroundFlush()}, }) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() obj := testutil.GenerateObjectWithSize(1024) @@ -254,7 +254,7 @@ func TestGCDontDeleteObjectFromWritecache(t *testing.T) { additionalShardOptions: []Option{WithDisabledGC()}, wcOpts: []writecache.Option{writecache.WithDisableBackgroundFlush()}, }) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() obj := testutil.GenerateObjectWithSize(1024) diff --git a/pkg/local_object_storage/shard/get_test.go b/pkg/local_object_storage/shard/get_test.go index d0eecf74e0..837991b734 100644 --- a/pkg/local_object_storage/shard/get_test.go +++ b/pkg/local_object_storage/shard/get_test.go @@ -30,7 +30,7 @@ func TestShard_Get(t *testing.T) { func testShardGet(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() var putPrm PutPrm var getPrm GetPrm diff --git a/pkg/local_object_storage/shard/head_test.go b/pkg/local_object_storage/shard/head_test.go index c65bbb1e3d..deb3019df0 100644 --- a/pkg/local_object_storage/shard/head_test.go +++ b/pkg/local_object_storage/shard/head_test.go @@ -28,7 +28,7 @@ func TestShard_Head(t *testing.T) { func testShardHead(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() var putPrm PutPrm var headPrm HeadPrm diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index e27dc07334..6ccae3f535 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -1,6 +1,7 @@ package shard import ( + "context" "errors" "fmt" @@ -30,11 +31,11 @@ func (s *Shard) ID() *ID { } // UpdateID reads shard ID saved in the metabase and updates it if it is missing. -func (s *Shard) UpdateID() (err error) { +func (s *Shard) UpdateID(ctx context.Context) (err error) { var idFromMetabase []byte modeDegraded := s.GetMode().NoMetabase() if !modeDegraded { - if idFromMetabase, err = s.metaBase.GetShardID(mode.ReadOnly); err != nil { + if idFromMetabase, err = s.metaBase.GetShardID(ctx, mode.ReadOnly); err != nil { err = fmt.Errorf("failed to read shard id from metabase: %w", err) } } @@ -62,7 +63,7 @@ func (s *Shard) UpdateID() (err error) { } if len(idFromMetabase) == 0 && !modeDegraded { - if setErr := s.metaBase.SetShardID(*s.info.ID, s.GetMode()); setErr != nil { + if setErr := s.metaBase.SetShardID(ctx, *s.info.ID, s.GetMode()); setErr != nil { err = errors.Join(err, fmt.Errorf("failed to write shard id to metabase: %w", setErr)) } } diff --git a/pkg/local_object_storage/shard/inhume_test.go b/pkg/local_object_storage/shard/inhume_test.go index 1353d5d946..1421f0e188 100644 --- a/pkg/local_object_storage/shard/inhume_test.go +++ b/pkg/local_object_storage/shard/inhume_test.go @@ -27,7 +27,7 @@ func TestShard_Inhume(t *testing.T) { func testShardInhume(t *testing.T, hasWriteCache bool) { sh := newShard(t, hasWriteCache) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() cnr := cidtest.ID() diff --git a/pkg/local_object_storage/shard/list_test.go b/pkg/local_object_storage/shard/list_test.go index 3414dc76a6..139b2e3166 100644 --- a/pkg/local_object_storage/shard/list_test.go +++ b/pkg/local_object_storage/shard/list_test.go @@ -18,14 +18,14 @@ func TestShard_List(t *testing.T) { t.Run("without write cache", func(t *testing.T) { t.Parallel() sh := newShard(t, false) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() testShardList(t, sh) }) t.Run("with write cache", func(t *testing.T) { t.Parallel() shWC := newShard(t, true) - defer func() { require.NoError(t, shWC.Close()) }() + defer func() { require.NoError(t, shWC.Close(context.Background())) }() testShardList(t, shWC) }) } diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index 595afb60ef..7da8b8c284 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -62,7 +62,7 @@ func TestShard_Lock(t *testing.T) { require.NoError(t, sh.Open(context.Background())) require.NoError(t, sh.Init(context.Background())) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() cnr := cidtest.ID() obj := testutil.GenerateObjectWithCID(cnr) @@ -148,7 +148,7 @@ func TestShard_Lock(t *testing.T) { func TestShard_IsLocked(t *testing.T) { sh := newShard(t, false) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() cnr := cidtest.ID() obj := testutil.GenerateObjectWithCID(cnr) diff --git a/pkg/local_object_storage/shard/metrics_test.go b/pkg/local_object_storage/shard/metrics_test.go index cec5a12adc..5230dcad0b 100644 --- a/pkg/local_object_storage/shard/metrics_test.go +++ b/pkg/local_object_storage/shard/metrics_test.go @@ -201,11 +201,11 @@ func TestCounters(t *testing.T) { dir := t.TempDir() sh, mm := shardWithMetrics(t, dir) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() - sh.SetMode(mode.ReadOnly) + sh.SetMode(context.Background(), mode.ReadOnly) require.Equal(t, mode.ReadOnly, mm.mode) - sh.SetMode(mode.ReadWrite) + sh.SetMode(context.Background(), mode.ReadWrite) require.Equal(t, mode.ReadWrite, mm.mode) const objNumber = 10 diff --git a/pkg/local_object_storage/shard/mode.go b/pkg/local_object_storage/shard/mode.go index 98b4c37b2e..901528976d 100644 --- a/pkg/local_object_storage/shard/mode.go +++ b/pkg/local_object_storage/shard/mode.go @@ -20,19 +20,21 @@ var ErrDegradedMode = logicerr.New("shard is in degraded mode") // // Returns any error encountered that did not allow // setting shard mode. -func (s *Shard) SetMode(m mode.Mode) error { +func (s *Shard) SetMode(ctx context.Context, m mode.Mode) error { unlock := s.lockExclusive() defer unlock() - return s.setMode(m) + return s.setMode(ctx, m) } -func (s *Shard) setMode(m mode.Mode) error { - s.log.Info(context.Background(), logs.ShardSettingShardMode, +func (s *Shard) setMode(ctx context.Context, m mode.Mode) error { + s.log.Info(ctx, logs.ShardSettingShardMode, zap.Stringer("old_mode", s.info.Mode), zap.Stringer("new_mode", m)) - components := []interface{ SetMode(mode.Mode) error }{ + components := []interface { + SetMode(context.Context, mode.Mode) error + }{ s.metaBase, s.blobStor, } @@ -60,7 +62,7 @@ func (s *Shard) setMode(m mode.Mode) error { if !m.Disabled() { for i := range components { - if err := components[i].SetMode(m); err != nil { + if err := components[i].SetMode(ctx, m); err != nil { return err } } @@ -69,7 +71,7 @@ func (s *Shard) setMode(m mode.Mode) error { s.info.Mode = m s.metricsWriter.SetMode(s.info.Mode) - s.log.Info(context.Background(), logs.ShardShardModeSetSuccessfully, + s.log.Info(ctx, logs.ShardShardModeSetSuccessfully, zap.Stringer("mode", s.info.Mode)) return nil } diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index cc73db3168..146e834cc1 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -94,7 +94,7 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { }), }, }) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index 124b72a5cb..10eb51a283 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -125,7 +125,7 @@ func (r *rebuilder) ScheduleRebuild(ctx context.Context, limiter RebuildWorkerLi } } -func (r *rebuilder) Stop(log *logger.Logger) { +func (r *rebuilder) Stop(ctx context.Context, log *logger.Logger) { r.mtx.Lock() defer r.mtx.Unlock() @@ -138,7 +138,7 @@ func (r *rebuilder) Stop(log *logger.Logger) { r.wg.Wait() r.cancel = nil r.done = nil - log.Info(context.Background(), logs.BlobstoreRebuildStopped) + log.Info(ctx, logs.BlobstoreRebuildStopped) } var errMBIsNotAvailable = errors.New("metabase is not available") diff --git a/pkg/local_object_storage/shard/refill_test.go b/pkg/local_object_storage/shard/refill_test.go index 0025bb45ae..d90343265c 100644 --- a/pkg/local_object_storage/shard/refill_test.go +++ b/pkg/local_object_storage/shard/refill_test.go @@ -34,7 +34,7 @@ func benchRefillMetabase(b *testing.B, objectsCount int) { additionalShardOptions: []Option{WithRefillMetabaseWorkersCount(shardconfig.RefillMetabaseWorkersCountDefault)}, }) - defer func() { require.NoError(b, sh.Close()) }() + defer func() { require.NoError(b, sh.Close(context.Background())) }() var putPrm PutPrm @@ -61,7 +61,7 @@ func benchRefillMetabase(b *testing.B, objectsCount int) { require.NoError(b, err) } - require.NoError(b, sh.Close()) + require.NoError(b, sh.Close(context.Background())) require.NoError(b, os.Remove(sh.metaBase.DumpInfo().Path)) require.NoError(b, sh.Open(context.Background())) @@ -72,5 +72,5 @@ func benchRefillMetabase(b *testing.B, objectsCount int) { require.NoError(b, sh.Init(context.Background())) - require.NoError(b, sh.Close()) + require.NoError(b, sh.Close(context.Background())) } diff --git a/pkg/local_object_storage/shard/reload_test.go b/pkg/local_object_storage/shard/reload_test.go index 7dd7189bba..e563f390b7 100644 --- a/pkg/local_object_storage/shard/reload_test.go +++ b/pkg/local_object_storage/shard/reload_test.go @@ -59,7 +59,7 @@ func TestShardReload(t *testing.T) { require.NoError(t, sh.Init(context.Background())) defer func() { - require.NoError(t, sh.Close()) + require.NoError(t, sh.Close(context.Background())) }() objects := make([]objAddr, 5) diff --git a/pkg/local_object_storage/shard/shutdown_test.go b/pkg/local_object_storage/shard/shutdown_test.go index de00eabd11..b1232707f1 100644 --- a/pkg/local_object_storage/shard/shutdown_test.go +++ b/pkg/local_object_storage/shard/shutdown_test.go @@ -52,10 +52,10 @@ func TestWriteCacheObjectLoss(t *testing.T) { }) } require.NoError(t, errG.Wait()) - require.NoError(t, sh.Close()) + require.NoError(t, sh.Close(context.Background())) sh = newCustomShard(t, true, shardOptions{rootPath: dir, wcOpts: wcOpts}) - defer func() { require.NoError(t, sh.Close()) }() + defer func() { require.NoError(t, sh.Close(context.Background())) }() var getPrm GetPrm diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index 26f47e82ef..92fb493e0b 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -117,8 +117,8 @@ func runFlushTest[Option any]( defer func() { require.NoError(t, wc.Close()) }() objects := putObjects(t, wc) - require.NoError(t, bs.SetMode(mode.ReadWrite)) - require.NoError(t, mb.SetMode(mode.ReadWrite)) + require.NoError(t, bs.SetMode(context.Background(), mode.ReadWrite)) + require.NoError(t, mb.SetMode(context.Background(), mode.ReadWrite)) require.NoError(t, wc.Flush(context.Background(), false, false)) @@ -131,11 +131,11 @@ func runFlushTest[Option any]( objects := putObjects(t, wc) // Blobstor is read-only, so we expect en error from `flush` here. - require.Error(t, wc.SetMode(mode.Degraded)) + require.Error(t, wc.SetMode(context.Background(), mode.Degraded)) - require.NoError(t, bs.SetMode(mode.ReadWrite)) - require.NoError(t, mb.SetMode(mode.ReadWrite)) - require.NoError(t, wc.SetMode(mode.Degraded)) + require.NoError(t, bs.SetMode(context.Background(), mode.ReadWrite)) + require.NoError(t, mb.SetMode(context.Background(), mode.ReadWrite)) + require.NoError(t, wc.SetMode(context.Background(), mode.Degraded)) check(t, mb, bs, objects) }) @@ -149,8 +149,8 @@ func runFlushTest[Option any]( objects := putObjects(t, wc) f.InjectFn(t, wc) - require.NoError(t, bs.SetMode(mode.ReadWrite)) - require.NoError(t, mb.SetMode(mode.ReadWrite)) + require.NoError(t, bs.SetMode(context.Background(), mode.ReadWrite)) + require.NoError(t, mb.SetMode(context.Background(), mode.ReadWrite)) require.Equal(t, uint32(0), errCount.Load()) require.Error(t, wc.Flush(context.Background(), false, false)) @@ -191,8 +191,8 @@ func newCache[Option any]( require.NoError(t, wc.Init()) // First set mode for metabase and blobstor to prevent background flushes. - require.NoError(t, mb.SetMode(mode.ReadOnly)) - require.NoError(t, bs.SetMode(mode.ReadOnly)) + require.NoError(t, mb.SetMode(context.Background(), mode.ReadOnly)) + require.NoError(t, bs.SetMode(context.Background(), mode.ReadOnly)) return wc, bs, mb } diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index 26658e9b8c..db789d994d 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -23,8 +23,8 @@ type setModePrm struct { // SetMode sets write-cache mode of operation. // When shard is put in read-only mode all objects in memory are flushed to disk // and all background jobs are suspended. -func (c *cache) SetMode(m mode.Mode) error { - ctx, span := tracing.StartSpanFromContext(context.TODO(), "writecache.SetMode", +func (c *cache) SetMode(ctx context.Context, m mode.Mode) error { + ctx, span := tracing.StartSpanFromContext(ctx, "writecache.SetMode", trace.WithAttributes( attribute.String("mode", m.String()), )) diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index a973df604e..d07220b68f 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -38,7 +38,7 @@ type Cache interface { // Returns ErrReadOnly if the Cache is currently in the read-only mode. Delete(context.Context, oid.Address) error Put(context.Context, common.PutPrm) (common.PutRes, error) - SetMode(mode.Mode) error + SetMode(context.Context, mode.Mode) error SetLogger(*logger.Logger) DumpInfo() Info Flush(context.Context, bool, bool) error diff --git a/pkg/services/control/server/detach_shards.go b/pkg/services/control/server/detach_shards.go index a4111bddb3..ffd36962ba 100644 --- a/pkg/services/control/server/detach_shards.go +++ b/pkg/services/control/server/detach_shards.go @@ -11,7 +11,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Server) DetachShards(_ context.Context, req *control.DetachShardsRequest) (*control.DetachShardsResponse, error) { +func (s *Server) DetachShards(ctx context.Context, req *control.DetachShardsRequest) (*control.DetachShardsResponse, error) { err := s.isValidRequest(req) if err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) @@ -19,7 +19,7 @@ func (s *Server) DetachShards(_ context.Context, req *control.DetachShardsReques shardIDs := s.getShardIDList(req.GetBody().GetShard_ID()) - if err := s.s.DetachShards(shardIDs); err != nil { + if err := s.s.DetachShards(ctx, shardIDs); err != nil { if errors.As(err, new(logicerr.Logical)) { return nil, status.Error(codes.InvalidArgument, err.Error()) } diff --git a/pkg/services/control/server/set_shard_mode.go b/pkg/services/control/server/set_shard_mode.go index 52835c41d1..4f87962636 100644 --- a/pkg/services/control/server/set_shard_mode.go +++ b/pkg/services/control/server/set_shard_mode.go @@ -11,7 +11,7 @@ import ( "google.golang.org/grpc/status" ) -func (s *Server) SetShardMode(_ context.Context, req *control.SetShardModeRequest) (*control.SetShardModeResponse, error) { +func (s *Server) SetShardMode(ctx context.Context, req *control.SetShardModeRequest) (*control.SetShardModeResponse, error) { // verify request err := s.isValidRequest(req) if err != nil { @@ -38,7 +38,7 @@ func (s *Server) SetShardMode(_ context.Context, req *control.SetShardModeReques } for _, shardID := range s.getShardIDList(req.GetBody().GetShard_ID()) { - err = s.s.SetShardMode(shardID, m, req.GetBody().GetResetErrorCounter()) + err = s.s.SetShardMode(ctx, shardID, m, req.GetBody().GetResetErrorCounter()) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } From 6921a890619cc23a2eb2d9e5b4e92cc1bc45ee41 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 21 Oct 2024 12:21:01 +0300 Subject: [PATCH 0998/1413] [#1437] ir: Fix contextcheck linters Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/container.go | 10 +++--- cmd/frostfs-node/netmap.go | 10 +++--- cmd/frostfs-node/session.go | 2 +- cmd/frostfs-node/tree.go | 12 +++---- pkg/innerring/initialization.go | 12 +++---- pkg/innerring/innerring.go | 28 ++++++++-------- pkg/innerring/notary.go | 6 ++-- pkg/innerring/processors/balance/handlers.go | 6 ++-- .../processors/balance/handlers_test.go | 5 +-- .../processors/container/handlers.go | 12 +++---- .../processors/container/handlers_test.go | 5 +-- pkg/innerring/processors/frostfs/handlers.go | 24 +++++++------- .../processors/frostfs/handlers_test.go | 11 ++++--- .../processors/governance/handlers.go | 8 ++--- .../processors/governance/handlers_test.go | 7 ++-- .../processors/governance/process_update.go | 20 ++++++------ .../processors/governance/processor.go | 3 +- pkg/innerring/processors/netmap/handlers.go | 32 +++++++++---------- .../processors/netmap/handlers_test.go | 15 +++++---- .../processors/netmap/process_epoch.go | 24 +++++++------- pkg/innerring/state.go | 26 +++++++-------- pkg/innerring/state_test.go | 6 ++-- pkg/morph/event/handlers.go | 4 ++- pkg/morph/event/listener.go | 24 +++++++------- pkg/morph/event/listener_test.go | 2 +- pkg/morph/event/utils.go | 6 ++-- 27 files changed, 165 insertions(+), 157 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index bd1b99095c..aa92e5ec5d 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1089,7 +1089,7 @@ func (c *cfg) LocalAddress() network.AddressGroup { func initLocalStorage(ctx context.Context, c *cfg) { ls := engine.New(c.engineOpts()...) - addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { + addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) { ls.HandleNewEpoch(ctx, ev.(netmap2.NewEpoch).EpochNumber()) }) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 1a54f9ffc2..3f75be2356 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -89,7 +89,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c if c.cfgMorph.containerCacheSize > 0 { containerCache := newCachedContainerStorage(cnrSrc, c.cfgMorph.cacheTTL, c.cfgMorph.containerCacheSize) - subscribeToContainerCreation(c, func(e event.Event) { + subscribeToContainerCreation(c, func(ctx context.Context, e event.Event) { ev := e.(containerEvent.PutSuccess) // read owner of the created container in order to update the reading cache. @@ -102,21 +102,21 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c } else { // unlike removal, we expect successful receive of the container // after successful creation, so logging can be useful - c.log.Error(context.Background(), logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification, + c.log.Error(ctx, logs.FrostFSNodeReadNewlyCreatedContainerAfterTheNotification, zap.Stringer("id", ev.ID), zap.Error(err), ) } - c.log.Debug(context.Background(), logs.FrostFSNodeContainerCreationEventsReceipt, + c.log.Debug(ctx, logs.FrostFSNodeContainerCreationEventsReceipt, zap.Stringer("id", ev.ID), ) }) - subscribeToContainerRemoval(c, func(e event.Event) { + subscribeToContainerRemoval(c, func(ctx context.Context, e event.Event) { ev := e.(containerEvent.DeleteSuccess) containerCache.handleRemoval(ev.ID) - c.log.Debug(context.Background(), logs.FrostFSNodeContainerRemovalEventsReceipt, + c.log.Debug(ctx, logs.FrostFSNodeContainerRemovalEventsReceipt, zap.Stringer("id", ev.ID), ) }) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 18667e6361..35ab4d575f 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -175,11 +175,11 @@ func initNetmapService(ctx context.Context, c *cfg) { } func addNewEpochNotificationHandlers(c *cfg) { - addNewEpochNotificationHandler(c, func(ev event.Event) { + addNewEpochNotificationHandler(c, func(_ context.Context, ev event.Event) { c.cfgNetmap.state.setCurrentEpoch(ev.(netmapEvent.NewEpoch).EpochNumber()) }) - addNewEpochAsyncNotificationHandler(c, func(ev event.Event) { + addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) { e := ev.(netmapEvent.NewEpoch).EpochNumber() c.updateContractNodeInfo(e) @@ -189,15 +189,15 @@ func addNewEpochNotificationHandlers(c *cfg) { } if err := c.bootstrap(); err != nil { - c.log.Warn(context.Background(), logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) + c.log.Warn(ctx, logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) } }) if c.cfgMorph.notaryEnabled { - addNewEpochAsyncNotificationHandler(c, func(_ event.Event) { + addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) { _, _, err := makeNotaryDeposit(c) if err != nil { - c.log.Error(context.Background(), logs.FrostFSNodeCouldNotMakeNotaryDeposit, + c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit, zap.String("error", err.Error()), ) } diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index a35d4e4702..2f3c9cbfea 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -48,7 +48,7 @@ func initSessionService(c *cfg) { _ = c.privateTokenStore.Close() }) - addNewEpochNotificationHandler(c, func(ev event.Event) { + addNewEpochNotificationHandler(c, func(_ context.Context, ev event.Event) { c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber()) }) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index 59923ee2f9..c423c0660c 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -80,10 +80,10 @@ func initTreeService(c *cfg) { })) if d := treeConfig.SyncInterval(); d == 0 { - addNewEpochNotificationHandler(c, func(_ event.Event) { + addNewEpochNotificationHandler(c, func(ctx context.Context, _ event.Event) { err := c.treeService.SynchronizeAll() if err != nil { - c.log.Error(context.Background(), logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeCouldNotSynchronizeTreeService, zap.Error(err)) } }) } else { @@ -103,15 +103,15 @@ func initTreeService(c *cfg) { }() } - subscribeToContainerRemoval(c, func(e event.Event) { + subscribeToContainerRemoval(c, func(ctx context.Context, e event.Event) { ev := e.(containerEvent.DeleteSuccess) // This is executed asynchronously, so we don't care about the operation taking some time. - c.log.Debug(context.Background(), logs.FrostFSNodeRemovingAllTreesForContainer, zap.Stringer("cid", ev.ID)) - err := c.treeService.DropTree(context.Background(), ev.ID, "") + c.log.Debug(ctx, logs.FrostFSNodeRemovingAllTreesForContainer, zap.Stringer("cid", ev.ID)) + err := c.treeService.DropTree(ctx, ev.ID, "") if err != nil && !errors.Is(err, pilorama.ErrTreeNotFound) { // Ignore pilorama.ErrTreeNotFound but other errors, including shard.ErrReadOnly, should be logged. - c.log.Error(context.Background(), logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved, + c.log.Error(ctx, logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved, zap.Stringer("cid", ev.ID), zap.String("error", err.Error())) } diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index b8812819e2..e08a613c3f 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -137,12 +137,12 @@ func (s *Server) enableNotarySupport() error { return nil } -func (s *Server) initNotaryConfig() { +func (s *Server) initNotaryConfig(ctx context.Context) { s.mainNotaryConfig = notaryConfigs( !s.withoutMainNet && s.mainnetClient.ProbeNotary(), // if mainnet disabled then notary flag must be disabled too ) - s.log.Info(context.Background(), logs.InnerringNotarySupport, + s.log.Info(ctx, logs.InnerringNotarySupport, zap.Bool("sidechain_enabled", true), zap.Bool("mainchain_enabled", !s.mainNotaryConfig.disabled), ) @@ -152,8 +152,8 @@ func (s *Server) createAlphaSync(cfg *viper.Viper, frostfsCli *frostfsClient.Cli var alphaSync event.Handler if s.withoutMainNet || cfg.GetBool("governance.disable") { - alphaSync = func(event.Event) { - s.log.Debug(context.Background(), logs.InnerringAlphabetKeysSyncIsDisabled) + alphaSync = func(ctx context.Context, _ event.Event) { + s.log.Debug(ctx, logs.InnerringAlphabetKeysSyncIsDisabled) } } else { // create governance processor @@ -196,9 +196,9 @@ func (s *Server) createIRFetcher() irFetcher { return irf } -func (s *Server) initTimers(cfg *viper.Viper) { +func (s *Server) initTimers(ctx context.Context, cfg *viper.Viper) { s.epochTimer = newEpochTimer(&epochTimerArgs{ - newEpochHandlers: s.newEpochTickHandlers(), + newEpochHandlers: s.newEpochTickHandlers(ctx), epoch: s, }) diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 67927c10cc..e81ec6bca6 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -152,7 +152,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { return err } - err = s.initConfigFromBlockchain() + err = s.initConfigFromBlockchain(ctx) if err != nil { return err } @@ -173,14 +173,14 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { prm.Validators = s.predefinedValidators // vote for sidechain validator if it is prepared in config - err = s.voteForSidechainValidator(prm) + err = s.voteForSidechainValidator(ctx, prm) if err != nil { // we don't stop inner ring execution on this error s.log.Warn(ctx, logs.InnerringCantVoteForPreparedValidators, zap.String("error", err.Error())) } - s.tickInitialExpoch() + s.tickInitialExpoch(ctx) morphErr := make(chan error) mainnnetErr := make(chan error) @@ -283,11 +283,11 @@ func (s *Server) initSideNotary(ctx context.Context) error { ) } -func (s *Server) tickInitialExpoch() { +func (s *Server) tickInitialExpoch(ctx context.Context) { initialEpochTicker := timer.NewOneTickTimer( timer.StaticBlockMeter(s.initialEpochTickDelta), func() { - s.netmapProcessor.HandleNewEpochTick(timerEvent.NewEpochTick{}) + s.netmapProcessor.HandleNewEpochTick(ctx, timerEvent.NewEpochTick{}) }) s.addBlockTimer(initialEpochTicker) } @@ -376,7 +376,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan return nil, err } - server.initNotaryConfig() + server.initNotaryConfig(ctx) err = server.initContracts(cfg) if err != nil { @@ -405,7 +405,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan return nil, err } - server.initTimers(cfg) + server.initTimers(ctx, cfg) err = server.initGRPCServer(cfg, log, audit) if err != nil { @@ -573,7 +573,7 @@ func parseMultinetConfig(cfg *viper.Viper, m metrics.MultinetMetrics) internalNe return nc } -func (s *Server) initConfigFromBlockchain() error { +func (s *Server) initConfigFromBlockchain(ctx context.Context) error { // get current epoch epoch, err := s.netmapClient.Epoch() if err != nil { @@ -602,8 +602,8 @@ func (s *Server) initConfigFromBlockchain() error { return err } - s.log.Debug(context.Background(), logs.InnerringReadConfigFromBlockchain, - zap.Bool("active", s.IsActive()), + s.log.Debug(ctx, logs.InnerringReadConfigFromBlockchain, + zap.Bool("active", s.IsActive(ctx)), zap.Bool("alphabet", s.IsAlphabet()), zap.Uint64("epoch", epoch), zap.Uint32("precision", balancePrecision), @@ -635,17 +635,17 @@ func (s *Server) nextEpochBlockDelta() (uint32, error) { // onlyAlphabet wrapper around event handler that executes it // only if inner ring node is alphabet node. func (s *Server) onlyAlphabetEventHandler(f event.Handler) event.Handler { - return func(ev event.Event) { + return func(ctx context.Context, ev event.Event) { if s.IsAlphabet() { - f(ev) + f(ctx, ev) } } } -func (s *Server) newEpochTickHandlers() []newEpochHandler { +func (s *Server) newEpochTickHandlers(ctx context.Context) []newEpochHandler { newEpochHandlers := []newEpochHandler{ func() { - s.netmapProcessor.HandleNewEpochTick(timerEvent.NewEpochTick{}) + s.netmapProcessor.HandleNewEpochTick(ctx, timerEvent.NewEpochTick{}) }, } diff --git a/pkg/innerring/notary.go b/pkg/innerring/notary.go index 902a4c30ae..dd3afa2c23 100644 --- a/pkg/innerring/notary.go +++ b/pkg/innerring/notary.go @@ -50,16 +50,16 @@ func (s *Server) depositSideNotary() (util.Uint256, error) { return tx, err } -func (s *Server) notaryHandler(_ event.Event) { +func (s *Server) notaryHandler(ctx context.Context, _ event.Event) { if !s.mainNotaryConfig.disabled { _, err := s.depositMainNotary() if err != nil { - s.log.Error(context.Background(), logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err)) + s.log.Error(ctx, logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err)) } } if _, err := s.depositSideNotary(); err != nil { - s.log.Error(context.Background(), logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err)) + s.log.Error(ctx, logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err)) } } diff --git a/pkg/innerring/processors/balance/handlers.go b/pkg/innerring/processors/balance/handlers.go index 3792fc2af1..5a89e6f7ce 100644 --- a/pkg/innerring/processors/balance/handlers.go +++ b/pkg/innerring/processors/balance/handlers.go @@ -11,9 +11,9 @@ import ( "go.uber.org/zap" ) -func (bp *Processor) handleLock(ev event.Event) { +func (bp *Processor) handleLock(ctx context.Context, ev event.Event) { lock := ev.(balanceEvent.Lock) - bp.log.Info(context.Background(), logs.Notification, + bp.log.Info(ctx, logs.Notification, zap.String("type", "lock"), zap.String("value", hex.EncodeToString(lock.ID()))) @@ -24,7 +24,7 @@ func (bp *Processor) handleLock(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - bp.log.Warn(context.Background(), logs.BalanceBalanceWorkerPoolDrained, + bp.log.Warn(ctx, logs.BalanceBalanceWorkerPoolDrained, zap.Int("capacity", bp.pool.Cap())) } } diff --git a/pkg/innerring/processors/balance/handlers_test.go b/pkg/innerring/processors/balance/handlers_test.go index 86a9e15d04..3ef4959cc8 100644 --- a/pkg/innerring/processors/balance/handlers_test.go +++ b/pkg/innerring/processors/balance/handlers_test.go @@ -1,6 +1,7 @@ package balance import ( + "context" "testing" "time" @@ -30,7 +31,7 @@ func TestProcessorCallsFrostFSContractForLockEvent(t *testing.T) { }) require.NoError(t, err, "failed to create processor") - processor.handleLock(balanceEvent.Lock{}) + processor.handleLock(context.Background(), balanceEvent.Lock{}) for processor.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -56,7 +57,7 @@ func TestProcessorDoesntCallFrostFSContractIfNotAlphabet(t *testing.T) { }) require.NoError(t, err, "failed to create processor") - processor.handleLock(balanceEvent.Lock{}) + processor.handleLock(context.Background(), balanceEvent.Lock{}) for processor.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) diff --git a/pkg/innerring/processors/container/handlers.go b/pkg/innerring/processors/container/handlers.go index b3d50d9d02..45cac513ad 100644 --- a/pkg/innerring/processors/container/handlers.go +++ b/pkg/innerring/processors/container/handlers.go @@ -12,11 +12,11 @@ import ( "go.uber.org/zap" ) -func (cp *Processor) handlePut(ev event.Event) { +func (cp *Processor) handlePut(ctx context.Context, ev event.Event) { put := ev.(putEvent) id := sha256.Sum256(put.Container()) - cp.log.Info(context.Background(), logs.Notification, + cp.log.Info(ctx, logs.Notification, zap.String("type", "container put"), zap.String("id", base58.Encode(id[:]))) @@ -27,14 +27,14 @@ func (cp *Processor) handlePut(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - cp.log.Warn(context.Background(), logs.ContainerContainerProcessorWorkerPoolDrained, + cp.log.Warn(ctx, logs.ContainerContainerProcessorWorkerPoolDrained, zap.Int("capacity", cp.pool.Cap())) } } -func (cp *Processor) handleDelete(ev event.Event) { +func (cp *Processor) handleDelete(ctx context.Context, ev event.Event) { del := ev.(containerEvent.Delete) - cp.log.Info(context.Background(), logs.Notification, + cp.log.Info(ctx, logs.Notification, zap.String("type", "container delete"), zap.String("id", base58.Encode(del.ContainerID()))) @@ -45,7 +45,7 @@ func (cp *Processor) handleDelete(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - cp.log.Warn(context.Background(), logs.ContainerContainerProcessorWorkerPoolDrained, + cp.log.Warn(ctx, logs.ContainerContainerProcessorWorkerPoolDrained, zap.Int("capacity", cp.pool.Cap())) } } diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index dc1e919bbd..a2fe50fa8d 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -1,6 +1,7 @@ package container import ( + "context" "crypto/ecdsa" "encoding/hex" "testing" @@ -71,7 +72,7 @@ func TestPutEvent(t *testing.T) { nr: nr, } - proc.handlePut(event) + proc.handlePut(context.Background(), event) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -143,7 +144,7 @@ func TestDeleteEvent(t *testing.T) { Signature: signature, } - proc.handleDelete(ev) + proc.handleDelete(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) diff --git a/pkg/innerring/processors/frostfs/handlers.go b/pkg/innerring/processors/frostfs/handlers.go index 02dfbaf609..d11ad0f5c7 100644 --- a/pkg/innerring/processors/frostfs/handlers.go +++ b/pkg/innerring/processors/frostfs/handlers.go @@ -13,11 +13,11 @@ import ( "go.uber.org/zap" ) -func (np *Processor) handleDeposit(ev event.Event) { +func (np *Processor) handleDeposit(ctx context.Context, ev event.Event) { deposit := ev.(frostfsEvent.Deposit) depositIDBin := bytes.Clone(deposit.ID()) slices.Reverse(depositIDBin) - np.log.Info(context.Background(), logs.Notification, + np.log.Info(ctx, logs.Notification, zap.String("type", "deposit"), zap.String("id", hex.EncodeToString(depositIDBin))) @@ -28,16 +28,16 @@ func (np *Processor) handleDeposit(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.FrostFSFrostfsProcessorWorkerPoolDrained, + np.log.Warn(ctx, logs.FrostFSFrostfsProcessorWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } -func (np *Processor) handleWithdraw(ev event.Event) { +func (np *Processor) handleWithdraw(ctx context.Context, ev event.Event) { withdraw := ev.(frostfsEvent.Withdraw) withdrawBin := bytes.Clone(withdraw.ID()) slices.Reverse(withdrawBin) - np.log.Info(context.Background(), logs.Notification, + np.log.Info(ctx, logs.Notification, zap.String("type", "withdraw"), zap.String("id", hex.EncodeToString(withdrawBin))) @@ -48,14 +48,14 @@ func (np *Processor) handleWithdraw(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.FrostFSFrostfsProcessorWorkerPoolDrained, + np.log.Warn(ctx, logs.FrostFSFrostfsProcessorWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } -func (np *Processor) handleCheque(ev event.Event) { +func (np *Processor) handleCheque(ctx context.Context, ev event.Event) { cheque := ev.(frostfsEvent.Cheque) - np.log.Info(context.Background(), logs.Notification, + np.log.Info(ctx, logs.Notification, zap.String("type", "cheque"), zap.String("id", hex.EncodeToString(cheque.ID()))) @@ -66,14 +66,14 @@ func (np *Processor) handleCheque(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.FrostFSFrostfsProcessorWorkerPoolDrained, + np.log.Warn(ctx, logs.FrostFSFrostfsProcessorWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } -func (np *Processor) handleConfig(ev event.Event) { +func (np *Processor) handleConfig(ctx context.Context, ev event.Event) { cfg := ev.(frostfsEvent.Config) - np.log.Info(context.Background(), logs.Notification, + np.log.Info(ctx, logs.Notification, zap.String("type", "set config"), zap.String("key", hex.EncodeToString(cfg.Key())), zap.String("value", hex.EncodeToString(cfg.Value()))) @@ -85,7 +85,7 @@ func (np *Processor) handleConfig(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.FrostFSFrostfsProcessorWorkerPoolDrained, + np.log.Warn(ctx, logs.FrostFSFrostfsProcessorWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } diff --git a/pkg/innerring/processors/frostfs/handlers_test.go b/pkg/innerring/processors/frostfs/handlers_test.go index 6425172bd1..c1541ca40b 100644 --- a/pkg/innerring/processors/frostfs/handlers_test.go +++ b/pkg/innerring/processors/frostfs/handlers_test.go @@ -1,6 +1,7 @@ package frostfs import ( + "context" "testing" "time" @@ -36,7 +37,7 @@ func TestHandleDeposit(t *testing.T) { AmountValue: 1000, } - proc.handleDeposit(ev) + proc.handleDeposit(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -57,7 +58,7 @@ func TestHandleDeposit(t *testing.T) { es.epochCounter = 109 - proc.handleDeposit(ev) + proc.handleDeposit(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -98,7 +99,7 @@ func TestHandleWithdraw(t *testing.T) { AmountValue: 1000, } - proc.handleWithdraw(ev) + proc.handleWithdraw(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -139,7 +140,7 @@ func TestHandleCheque(t *testing.T) { LockValue: util.Uint160{200}, } - proc.handleCheque(ev) + proc.handleCheque(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -176,7 +177,7 @@ func TestHandleConfig(t *testing.T) { TxHashValue: util.Uint256{100}, } - proc.handleConfig(ev) + proc.handleConfig(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) diff --git a/pkg/innerring/processors/governance/handlers.go b/pkg/innerring/processors/governance/handlers.go index dee8c13e2e..7e8ab629d0 100644 --- a/pkg/innerring/processors/governance/handlers.go +++ b/pkg/innerring/processors/governance/handlers.go @@ -13,7 +13,7 @@ import ( "go.uber.org/zap" ) -func (gp *Processor) HandleAlphabetSync(e event.Event) { +func (gp *Processor) HandleAlphabetSync(ctx context.Context, e event.Event) { var ( typ string hash util.Uint256 @@ -34,16 +34,16 @@ func (gp *Processor) HandleAlphabetSync(e event.Event) { return } - gp.log.Info(context.Background(), logs.GovernanceNewEvent, zap.String("type", typ)) + gp.log.Info(ctx, logs.GovernanceNewEvent, zap.String("type", typ)) // send event to the worker pool err := processors.SubmitEvent(gp.pool, gp.metrics, "alphabet_sync", func() bool { - return gp.processAlphabetSync(hash) + return gp.processAlphabetSync(ctx, hash) }) if err != nil { // there system can be moved into controlled degradation stage - gp.log.Warn(context.Background(), logs.GovernanceGovernanceWorkerPoolDrained, + gp.log.Warn(ctx, logs.GovernanceGovernanceWorkerPoolDrained, zap.Int("capacity", gp.pool.Cap())) } } diff --git a/pkg/innerring/processors/governance/handlers_test.go b/pkg/innerring/processors/governance/handlers_test.go index 87040bdef8..286935129b 100644 --- a/pkg/innerring/processors/governance/handlers_test.go +++ b/pkg/innerring/processors/governance/handlers_test.go @@ -1,6 +1,7 @@ package governance import ( + "context" "encoding/binary" "sort" "testing" @@ -57,7 +58,7 @@ func TestHandleAlphabetSyncEvent(t *testing.T) { txHash: util.Uint256{100}, } - proc.HandleAlphabetSync(ev) + proc.HandleAlphabetSync(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -133,7 +134,7 @@ func TestHandleAlphabetDesignateEvent(t *testing.T) { Role: noderoles.NeoFSAlphabet, } - proc.HandleAlphabetSync(ev) + proc.HandleAlphabetSync(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -226,7 +227,7 @@ type testVoter struct { votes []VoteValidatorPrm } -func (v *testVoter) VoteForSidechainValidator(prm VoteValidatorPrm) error { +func (v *testVoter) VoteForSidechainValidator(_ context.Context, prm VoteValidatorPrm) error { v.votes = append(v.votes, prm) return nil } diff --git a/pkg/innerring/processors/governance/process_update.go b/pkg/innerring/processors/governance/process_update.go index faca22f67b..fdfdfa4791 100644 --- a/pkg/innerring/processors/governance/process_update.go +++ b/pkg/innerring/processors/governance/process_update.go @@ -19,39 +19,39 @@ const ( alphabetUpdateIDPrefix = "AlphabetUpdate" ) -func (gp *Processor) processAlphabetSync(txHash util.Uint256) bool { +func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint256) bool { if !gp.alphabetState.IsAlphabet() { - gp.log.Info(context.Background(), logs.GovernanceNonAlphabetModeIgnoreAlphabetSync) + gp.log.Info(ctx, logs.GovernanceNonAlphabetModeIgnoreAlphabetSync) return true } mainnetAlphabet, err := gp.mainnetClient.NeoFSAlphabetList() if err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantFetchAlphabetListFromMainNet, + gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromMainNet, zap.String("error", err.Error())) return false } sidechainAlphabet, err := gp.morphClient.Committee() if err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantFetchAlphabetListFromSideChain, + gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromSideChain, zap.String("error", err.Error())) return false } newAlphabet, err := newAlphabetList(sidechainAlphabet, mainnetAlphabet) if err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantMergeAlphabetListsFromMainNetAndSideChain, + gp.log.Error(ctx, logs.GovernanceCantMergeAlphabetListsFromMainNetAndSideChain, zap.String("error", err.Error())) return false } if newAlphabet == nil { - gp.log.Info(context.Background(), logs.GovernanceNoGovernanceUpdateAlphabetListHasNotBeenChanged) + gp.log.Info(ctx, logs.GovernanceNoGovernanceUpdateAlphabetListHasNotBeenChanged) return true } - gp.log.Info(context.Background(), logs.GovernanceAlphabetListHasBeenChangedStartingUpdate, + gp.log.Info(ctx, logs.GovernanceAlphabetListHasBeenChangedStartingUpdate, zap.String("side_chain_alphabet", prettyKeys(sidechainAlphabet)), zap.String("new_alphabet", prettyKeys(newAlphabet)), ) @@ -62,9 +62,9 @@ func (gp *Processor) processAlphabetSync(txHash util.Uint256) bool { } // 1. Vote to sidechain committee via alphabet contracts. - err = gp.voter.VoteForSidechainValidator(votePrm) + err = gp.voter.VoteForSidechainValidator(ctx, votePrm) if err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantVoteForSideChainCommittee, + gp.log.Error(ctx, logs.GovernanceCantVoteForSideChainCommittee, zap.String("error", err.Error())) } @@ -77,7 +77,7 @@ func (gp *Processor) processAlphabetSync(txHash util.Uint256) bool { // 4. Update FrostFS contract in the mainnet. gp.updateFrostFSContractInMainnet(newAlphabet) - gp.log.Info(context.Background(), logs.GovernanceFinishedAlphabetListUpdate) + gp.log.Info(ctx, logs.GovernanceFinishedAlphabetListUpdate) return true } diff --git a/pkg/innerring/processors/governance/processor.go b/pkg/innerring/processors/governance/processor.go index 6daea417e6..eaadfdb4fd 100644 --- a/pkg/innerring/processors/governance/processor.go +++ b/pkg/innerring/processors/governance/processor.go @@ -1,6 +1,7 @@ package governance import ( + "context" "errors" "fmt" @@ -38,7 +39,7 @@ type VoteValidatorPrm struct { // Voter is a callback interface for alphabet contract voting. type Voter interface { - VoteForSidechainValidator(VoteValidatorPrm) error + VoteForSidechainValidator(context.Context, VoteValidatorPrm) error } type ( diff --git a/pkg/innerring/processors/netmap/handlers.go b/pkg/innerring/processors/netmap/handlers.go index 478ab5eab1..61547e0bad 100644 --- a/pkg/innerring/processors/netmap/handlers.go +++ b/pkg/innerring/processors/netmap/handlers.go @@ -12,13 +12,13 @@ import ( "go.uber.org/zap" ) -func (np *Processor) HandleNewEpochTick(ev event.Event) { +func (np *Processor) HandleNewEpochTick(ctx context.Context, ev event.Event) { _ = ev.(timerEvent.NewEpochTick) np.log.Info(context.Background(), logs.NetmapTick, zap.String("type", "epoch")) // send an event to the worker pool - err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch_tick", np.processNewEpochTick) + err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch_tick", func() bool { return np.processNewEpochTick(ctx) }) if err != nil { // there system can be moved into controlled degradation stage np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, @@ -26,28 +26,28 @@ func (np *Processor) HandleNewEpochTick(ev event.Event) { } } -func (np *Processor) handleNewEpoch(ev event.Event) { +func (np *Processor) handleNewEpoch(ctx context.Context, ev event.Event) { epochEvent := ev.(netmapEvent.NewEpoch) - np.log.Info(context.Background(), logs.Notification, + np.log.Info(ctx, logs.Notification, zap.String("type", "new epoch"), zap.Uint64("value", epochEvent.EpochNumber())) // send an event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch", func() bool { - return np.processNewEpoch(epochEvent) + return np.processNewEpoch(ctx, epochEvent) }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } -func (np *Processor) handleAddPeer(ev event.Event) { +func (np *Processor) handleAddPeer(ctx context.Context, ev event.Event) { newPeer := ev.(netmapEvent.AddPeer) - np.log.Info(context.Background(), logs.Notification, + np.log.Info(ctx, logs.Notification, zap.String("type", "add peer"), ) @@ -58,14 +58,14 @@ func (np *Processor) handleAddPeer(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } -func (np *Processor) handleUpdateState(ev event.Event) { +func (np *Processor) handleUpdateState(ctx context.Context, ev event.Event) { updPeer := ev.(netmapEvent.UpdatePeer) - np.log.Info(context.Background(), logs.Notification, + np.log.Info(ctx, logs.Notification, zap.String("type", "update peer state"), zap.String("key", hex.EncodeToString(updPeer.PublicKey().Bytes()))) @@ -76,21 +76,21 @@ func (np *Processor) handleUpdateState(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } -func (np *Processor) handleCleanupTick(ev event.Event) { +func (np *Processor) handleCleanupTick(ctx context.Context, ev event.Event) { if !np.netmapSnapshot.enabled { - np.log.Debug(context.Background(), logs.NetmapNetmapCleanUpRoutineIsDisabled518) + np.log.Debug(ctx, logs.NetmapNetmapCleanUpRoutineIsDisabled518) return } cleanup := ev.(netmapCleanupTick) - np.log.Info(context.Background(), logs.NetmapTick, zap.String("type", "netmap cleaner")) + np.log.Info(ctx, logs.NetmapTick, zap.String("type", "netmap cleaner")) // send event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "netmap_cleanup_tick", func() bool { @@ -98,7 +98,7 @@ func (np *Processor) handleCleanupTick(ev event.Event) { }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index a534581794..1e8be40950 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "fmt" "testing" "time" @@ -38,7 +39,7 @@ func TestNewEpochTick(t *testing.T) { require.NoError(t, err, "failed to create processor") ev := timerEvent.NewEpochTick{} - proc.HandleNewEpochTick(ev) + proc.HandleNewEpochTick(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -90,7 +91,7 @@ func TestNewEpoch(t *testing.T) { Num: 101, Hash: util.Uint256{101}, } - proc.handleNewEpoch(ev) + proc.handleNewEpoch(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -130,7 +131,7 @@ func TestAddPeer(t *testing.T) { MainTransaction: &transaction.Transaction{}, }, } - proc.handleAddPeer(ev) + proc.handleAddPeer(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -145,7 +146,7 @@ func TestAddPeer(t *testing.T) { MainTransaction: &transaction.Transaction{}, }, } - proc.handleAddPeer(ev) + proc.handleAddPeer(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -188,7 +189,7 @@ func TestUpdateState(t *testing.T) { MainTransaction: &transaction.Transaction{}, }, } - proc.handleUpdateState(ev) + proc.handleUpdateState(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -232,7 +233,7 @@ func TestCleanupTick(t *testing.T) { txHash: util.Uint256{123}, } - proc.handleCleanupTick(ev) + proc.handleCleanupTick(context.Background(), ev) for proc.pool.Running() > 0 { time.Sleep(10 * time.Millisecond) @@ -413,6 +414,6 @@ type testEventHandler struct { handledEvents []event.Event } -func (h *testEventHandler) Handle(e event.Event) { +func (h *testEventHandler) Handle(_ context.Context, e event.Event) { h.handledEvents = append(h.handledEvents, e) } diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index 8ad295a741..e401ef4f2b 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -11,12 +11,12 @@ import ( // Process new epoch notification by setting global epoch value and resetting // local epoch timer. -func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool { +func (np *Processor) processNewEpoch(ctx context.Context, ev netmapEvent.NewEpoch) bool { epoch := ev.EpochNumber() epochDuration, err := np.netmapClient.EpochDuration() if err != nil { - np.log.Warn(context.Background(), logs.NetmapCantGetEpochDuration, + np.log.Warn(ctx, logs.NetmapCantGetEpochDuration, zap.String("error", err.Error())) } else { np.epochState.SetEpochDuration(epochDuration) @@ -26,46 +26,46 @@ func (np *Processor) processNewEpoch(ev netmapEvent.NewEpoch) bool { h, err := np.netmapClient.MorphTxHeight(ev.TxHash()) if err != nil { - np.log.Warn(context.Background(), logs.NetmapCantGetTransactionHeight, + np.log.Warn(ctx, logs.NetmapCantGetTransactionHeight, zap.String("hash", ev.TxHash().StringLE()), zap.String("error", err.Error())) } if err := np.epochTimer.ResetEpochTimer(h); err != nil { - np.log.Warn(context.Background(), logs.NetmapCantResetEpochTimer, + np.log.Warn(ctx, logs.NetmapCantResetEpochTimer, zap.String("error", err.Error())) } // get new netmap snapshot networkMap, err := np.netmapClient.NetMap() if err != nil { - np.log.Warn(context.Background(), logs.NetmapCantGetNetmapSnapshotToPerformCleanup, + np.log.Warn(ctx, logs.NetmapCantGetNetmapSnapshotToPerformCleanup, zap.String("error", err.Error())) return false } np.netmapSnapshot.update(*networkMap, epoch) - np.handleCleanupTick(netmapCleanupTick{epoch: epoch, txHash: ev.TxHash()}) - np.handleAlphabetSync(governance.NewSyncEvent(ev.TxHash())) - np.handleNotaryDeposit(ev) + np.handleCleanupTick(ctx, netmapCleanupTick{epoch: epoch, txHash: ev.TxHash()}) + np.handleAlphabetSync(ctx, governance.NewSyncEvent(ev.TxHash())) + np.handleNotaryDeposit(ctx, ev) return true } // Process new epoch tick by invoking new epoch method in network map contract. -func (np *Processor) processNewEpochTick() bool { +func (np *Processor) processNewEpochTick(ctx context.Context) bool { if !np.alphabetState.IsAlphabet() { - np.log.Info(context.Background(), logs.NetmapNonAlphabetModeIgnoreNewEpochTick) + np.log.Info(ctx, logs.NetmapNonAlphabetModeIgnoreNewEpochTick) return true } nextEpoch := np.epochState.EpochCounter() + 1 - np.log.Debug(context.Background(), logs.NetmapNextEpoch, zap.Uint64("value", nextEpoch)) + np.log.Debug(ctx, logs.NetmapNextEpoch, zap.Uint64("value", nextEpoch)) err := np.netmapClient.NewEpoch(nextEpoch) if err != nil { - np.log.Error(context.Background(), logs.NetmapCantInvokeNetmapNewEpoch, zap.Error(err)) + np.log.Error(ctx, logs.NetmapCantInvokeNetmapNewEpoch, zap.Error(err)) return false } diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index 2dbcd74945..85f332fb64 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -48,8 +48,8 @@ func (s *Server) SetEpochDuration(val uint64) { } // IsActive is a getter for a global active flag state. -func (s *Server) IsActive() bool { - return s.InnerRingIndex() >= 0 +func (s *Server) IsActive(ctx context.Context) bool { + return s.InnerRingIndex(ctx) >= 0 } // IsAlphabet is a getter for a global alphabet flag state. @@ -59,10 +59,10 @@ func (s *Server) IsAlphabet() bool { // InnerRingIndex is a getter for a global index of node in inner ring list. Negative // index means that node is not in the inner ring list. -func (s *Server) InnerRingIndex() int { +func (s *Server) InnerRingIndex(ctx context.Context) int { index, err := s.statusIndex.InnerRingIndex() if err != nil { - s.log.Error(context.Background(), logs.InnerringCantGetInnerRingIndex, zap.String("error", err.Error())) + s.log.Error(ctx, logs.InnerringCantGetInnerRingIndex, zap.String("error", err.Error())) return -1 } @@ -71,10 +71,10 @@ func (s *Server) InnerRingIndex() int { // InnerRingSize is a getter for a global size of inner ring list. This value // paired with inner ring index. -func (s *Server) InnerRingSize() int { +func (s *Server) InnerRingSize(ctx context.Context) int { size, err := s.statusIndex.InnerRingSize() if err != nil { - s.log.Error(context.Background(), logs.InnerringCantGetInnerRingSize, zap.String("error", err.Error())) + s.log.Error(ctx, logs.InnerringCantGetInnerRingSize, zap.String("error", err.Error())) return 0 } @@ -93,18 +93,18 @@ func (s *Server) AlphabetIndex() int { return int(index) } -func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) error { +func (s *Server) voteForSidechainValidator(ctx context.Context, prm governance.VoteValidatorPrm) error { validators := prm.Validators - index := s.InnerRingIndex() + index := s.InnerRingIndex(ctx) if s.contracts.alphabet.indexOutOfRange(index) { - s.log.Info(context.Background(), logs.InnerringIgnoreValidatorVoteNodeNotInAlphabetRange) + s.log.Info(ctx, logs.InnerringIgnoreValidatorVoteNodeNotInAlphabetRange) return nil } if len(validators) == 0 { - s.log.Info(context.Background(), logs.InnerringIgnoreValidatorVoteEmptyValidatorsList) + s.log.Info(ctx, logs.InnerringIgnoreValidatorVoteEmptyValidatorsList) return nil } @@ -129,7 +129,7 @@ func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) erro s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) { _, err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators) if err != nil { - s.log.Warn(context.Background(), logs.InnerringCantInvokeVoteMethodInAlphabetContract, + s.log.Warn(ctx, logs.InnerringCantInvokeVoteMethodInAlphabetContract, zap.Int8("alphabet_index", int8(letter)), zap.Uint64("epoch", epoch), zap.String("error", err.Error())) @@ -141,9 +141,9 @@ func (s *Server) voteForSidechainValidator(prm governance.VoteValidatorPrm) erro // VoteForSidechainValidator calls vote method on alphabet contracts with // the provided list of keys. -func (s *Server) VoteForSidechainValidator(prm governance.VoteValidatorPrm) error { +func (s *Server) VoteForSidechainValidator(ctx context.Context, prm governance.VoteValidatorPrm) error { sort.Sort(prm.Validators) - return s.voteForSidechainValidator(prm) + return s.voteForSidechainValidator(ctx, prm) } // ResetEpochTimer resets the block timer that produces events to update epoch diff --git a/pkg/innerring/state_test.go b/pkg/innerring/state_test.go index 9313edf780..17ab995af7 100644 --- a/pkg/innerring/state_test.go +++ b/pkg/innerring/state_test.go @@ -46,9 +46,9 @@ func TestServerState(t *testing.T) { srv.setHealthStatus(context.Background(), healthStatus) require.Equal(t, healthStatus, srv.HealthStatus(), "invalid health status") - require.True(t, srv.IsActive(), "invalid IsActive result") + require.True(t, srv.IsActive(context.Background()), "invalid IsActive result") require.True(t, srv.IsAlphabet(), "invalid IsAlphabet result") - require.Equal(t, 0, srv.InnerRingIndex(), "invalid IR index") - require.Equal(t, 1, srv.InnerRingSize(), "invalid IR index") + require.Equal(t, 0, srv.InnerRingIndex(context.Background()), "invalid IR index") + require.Equal(t, 1, srv.InnerRingSize(context.Background()), "invalid IR index") require.Equal(t, 0, srv.AlphabetIndex(), "invalid alphabet index") } diff --git a/pkg/morph/event/handlers.go b/pkg/morph/event/handlers.go index 182b4667e9..bda83ba542 100644 --- a/pkg/morph/event/handlers.go +++ b/pkg/morph/event/handlers.go @@ -1,11 +1,13 @@ package event import ( + "context" + "github.com/nspcc-dev/neo-go/pkg/core/block" ) // Handler is an Event processing function. -type Handler func(Event) +type Handler func(context.Context, Event) // BlockHandler is a chain block processing function. type BlockHandler func(*block.Block) diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 3d3d806a4e..eeec46540f 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -280,7 +280,7 @@ loop: continue loop } - l.handleNotaryEvent(notaryEvent) + l.handleNotaryEvent(ctx, notaryEvent) case b, ok := <-chs.BlockCh: if !ok { l.log.Warn(ctx, logs.EventStopEventListenerByBlockChannel) @@ -307,11 +307,11 @@ func (l *listener) handleBlockEvent(b *block.Block) { } } -func (l *listener) handleNotaryEvent(notaryEvent *result.NotaryRequestEvent) { +func (l *listener) handleNotaryEvent(ctx context.Context, notaryEvent *result.NotaryRequestEvent) { if err := l.pool.Submit(func() { - l.parseAndHandleNotary(notaryEvent) + l.parseAndHandleNotary(ctx, notaryEvent) }); err != nil { - l.log.Warn(context.Background(), logs.EventListenerWorkerPoolDrained, + l.log.Warn(ctx, logs.EventListenerWorkerPoolDrained, zap.Int("capacity", l.pool.Cap())) } } @@ -376,11 +376,11 @@ func (l *listener) parseAndHandleNotification(ctx context.Context, notifyEvent * } for _, handler := range handlers { - handler(event) + handler(ctx, event) } } -func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { +func (l *listener) parseAndHandleNotary(ctx context.Context, nr *result.NotaryRequestEvent) { // prepare the notary event notaryEvent, err := l.notaryEventsPreparator.Prepare(nr.NotaryRequest) if err != nil { @@ -388,13 +388,13 @@ func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { switch { case errors.Is(err, ErrTXAlreadyHandled): case errors.As(err, &expErr): - l.log.Warn(context.Background(), logs.EventSkipExpiredMainTXNotaryEvent, + l.log.Warn(ctx, logs.EventSkipExpiredMainTXNotaryEvent, zap.String("error", err.Error()), zap.Uint32("current_block_height", expErr.CurrentBlockHeight), zap.Uint32("fallback_tx_not_valid_before_height", expErr.FallbackTXNotValidBeforeHeight), ) default: - l.log.Warn(context.Background(), logs.EventCouldNotPrepareAndValidateNotaryEvent, + l.log.Warn(ctx, logs.EventCouldNotPrepareAndValidateNotaryEvent, zap.String("error", err.Error()), ) } @@ -418,7 +418,7 @@ func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { l.mtx.RUnlock() if !ok { - log.Debug(context.Background(), logs.EventNotaryParserNotSet) + log.Debug(ctx, logs.EventNotaryParserNotSet) return } @@ -426,7 +426,7 @@ func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { // parse the notary event event, err := parser(notaryEvent) if err != nil { - log.Warn(context.Background(), logs.EventCouldNotParseNotaryEvent, + log.Warn(ctx, logs.EventCouldNotParseNotaryEvent, zap.String("error", err.Error()), ) @@ -439,14 +439,14 @@ func (l *listener) parseAndHandleNotary(nr *result.NotaryRequestEvent) { l.mtx.RUnlock() if !ok { - log.Info(context.Background(), logs.EventNotaryHandlersForParsedNotificationEventWereNotRegistered, + log.Info(ctx, logs.EventNotaryHandlersForParsedNotificationEventWereNotRegistered, zap.Any("event", event), ) return } - handler(event) + handler(ctx, event) } // SetNotificationParser sets the parser of particular contract event. diff --git a/pkg/morph/event/listener_test.go b/pkg/morph/event/listener_test.go index 5f7cf9f436..214daf694a 100644 --- a/pkg/morph/event/listener_test.go +++ b/pkg/morph/event/listener_test.go @@ -59,7 +59,7 @@ func TestEventHandling(t *testing.T) { handledNotifications := make([]Event, 0) l.RegisterNotificationHandler(NotificationHandlerInfo{ scriptHashWithType: key, - h: func(e Event) { + h: func(_ context.Context, e Event) { handledNotifications = append(handledNotifications, e) notificationHandled <- true }, diff --git a/pkg/morph/event/utils.go b/pkg/morph/event/utils.go index 31bbf4432e..99ea9a7f0b 100644 --- a/pkg/morph/event/utils.go +++ b/pkg/morph/event/utils.go @@ -85,12 +85,12 @@ func (s typeValue) GetType() Type { // WorkerPoolHandler sets closure over worker pool w with passed handler h. func WorkerPoolHandler(w util2.WorkerPool, h Handler, log *logger.Logger) Handler { - return func(e Event) { + return func(ctx context.Context, e Event) { err := w.Submit(func() { - h(e) + h(ctx, e) }) if err != nil { - log.Warn(context.Background(), logs.EventCouldNotSubmitHandlerToWorkerPool, + log.Warn(ctx, logs.EventCouldNotSubmitHandlerToWorkerPool, zap.String("error", err.Error()), ) } From 74295532665e32efc80fcdcde639b2d9bc872a88 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 21 Oct 2024 16:27:28 +0300 Subject: [PATCH 0999/1413] [#1437] node: Fix contextcheck linter Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-ir/config.go | 4 +- cmd/frostfs-ir/httpcomponent.go | 30 +++++----- cmd/frostfs-ir/main.go | 12 ++-- cmd/frostfs-ir/pprof.go | 18 +++--- .../internal/blobovnicza/inspect.go | 2 +- cmd/frostfs-lens/internal/blobovnicza/list.go | 2 +- cmd/frostfs-lens/internal/meta/inspect.go | 2 +- .../internal/meta/list-garbage.go | 2 +- .../internal/meta/list-graveyard.go | 2 +- cmd/frostfs-node/config.go | 60 +++++++++---------- cmd/frostfs-node/container.go | 8 +-- cmd/frostfs-node/control.go | 22 +++---- cmd/frostfs-node/grpc.go | 56 ++++++++--------- cmd/frostfs-node/httpcomponent.go | 10 ++-- cmd/frostfs-node/main.go | 56 ++++++++--------- cmd/frostfs-node/morph.go | 8 +-- cmd/frostfs-node/netmap.go | 48 +++++++-------- cmd/frostfs-node/object.go | 4 +- cmd/frostfs-node/pprof.go | 5 +- cmd/frostfs-node/runtime.go | 6 +- internal/audit/request.go | 8 +-- pkg/core/object/fmt.go | 12 ++-- pkg/core/object/sender_classifier.go | 9 +-- pkg/innerring/blocktimer.go | 6 +- pkg/innerring/initialization.go | 49 +++++++++------ pkg/innerring/innerring.go | 20 +++---- pkg/innerring/notary.go | 13 ++-- pkg/innerring/processors/alphabet/handlers.go | 8 +-- .../processors/alphabet/handlers_test.go | 11 ++-- .../processors/alphabet/process_emit.go | 32 +++++----- .../processors/alphabet/processor.go | 8 +-- pkg/innerring/processors/balance/handlers.go | 2 +- .../processors/balance/handlers_test.go | 4 +- .../processors/balance/process_assets.go | 10 ++-- pkg/innerring/processors/balance/processor.go | 8 +-- .../processors/container/handlers.go | 4 +- .../processors/container/handlers_test.go | 2 +- .../processors/container/process_container.go | 26 ++++---- .../processors/container/processor.go | 6 +- pkg/innerring/processors/frostfs/handlers.go | 8 +-- .../processors/frostfs/handlers_test.go | 10 ++-- .../processors/frostfs/process_assets.go | 40 ++++++------- .../processors/frostfs/process_config.go | 10 ++-- pkg/innerring/processors/frostfs/processor.go | 14 ++--- .../processors/governance/handlers_test.go | 8 +-- .../processors/governance/process_update.go | 32 +++++----- .../processors/governance/processor.go | 8 +-- pkg/innerring/processors/netmap/handlers.go | 10 ++-- .../processors/netmap/handlers_test.go | 6 +- .../processors/netmap/process_cleanup.go | 15 ++--- .../processors/netmap/process_epoch.go | 4 +- .../processors/netmap/process_peers.go | 27 +++++---- pkg/innerring/processors/netmap/processor.go | 10 +--- pkg/innerring/processors/netmap/wrappers.go | 18 +++--- pkg/innerring/state.go | 10 ++-- pkg/innerring/state_test.go | 4 +- .../blobovnicza/blobovnicza_test.go | 4 +- .../blobovnicza/control.go | 22 +++---- .../blobovnicza/get_test.go | 6 +- .../blobovnicza/iterate_test.go | 2 +- .../blobstor/blobovniczatree/active.go | 14 ++--- .../blobstor/blobovniczatree/blobovnicza.go | 2 +- .../blobstor/blobovniczatree/cache.go | 4 +- .../blobovniczatree/concurrency_test.go | 2 +- .../blobstor/blobovniczatree/control.go | 6 +- .../blobstor/blobovniczatree/control_test.go | 6 +- .../blobstor/blobovniczatree/count.go | 2 +- .../blobstor/blobovniczatree/delete.go | 4 +- .../blobstor/blobovniczatree/exists.go | 2 +- .../blobstor/blobovniczatree/exists_test.go | 2 +- .../blobstor/blobovniczatree/get.go | 4 +- .../blobstor/blobovniczatree/get_range.go | 4 +- .../blobstor/blobovniczatree/iterate.go | 2 +- .../blobstor/blobovniczatree/manager.go | 16 ++--- .../blobstor/blobovniczatree/option.go | 5 +- .../blobstor/blobovniczatree/put.go | 6 +- .../blobstor/blobovniczatree/rebuild.go | 28 ++++----- .../blobovniczatree/rebuild_failover_test.go | 30 +++++----- .../blobstor/blobovniczatree/rebuild_test.go | 18 +++--- pkg/local_object_storage/blobstor/blobstor.go | 3 +- .../blobstor/blobstor_test.go | 14 ++--- .../blobstor/common/storage.go | 4 +- pkg/local_object_storage/blobstor/control.go | 12 ++-- .../blobstor/exists_test.go | 2 +- .../blobstor/fstree/control.go | 4 +- .../blobstor/fstree/fstree.go | 2 +- .../blobstor/fstree/fstree_test.go | 2 +- .../blobstor/internal/blobstortest/control.go | 2 +- .../blobstor/internal/blobstortest/delete.go | 2 +- .../blobstor/internal/blobstortest/exists.go | 2 +- .../blobstor/internal/blobstortest/get.go | 2 +- .../internal/blobstortest/get_range.go | 2 +- .../blobstor/internal/blobstortest/iterate.go | 2 +- .../blobstor/iterate_test.go | 6 +- .../blobstor/memstore/control.go | 18 +++--- .../blobstor/memstore/memstore_test.go | 2 +- pkg/local_object_storage/blobstor/mode.go | 4 +- .../blobstor/perf_test.go | 6 +- .../blobstor/teststore/option.go | 6 +- .../blobstor/teststore/teststore.go | 6 +- pkg/local_object_storage/engine/container.go | 14 ++--- pkg/local_object_storage/engine/delete.go | 6 +- pkg/local_object_storage/engine/engine.go | 19 +++--- pkg/local_object_storage/engine/exists.go | 2 +- pkg/local_object_storage/engine/get.go | 2 +- pkg/local_object_storage/engine/head.go | 2 +- pkg/local_object_storage/engine/inhume.go | 10 ++-- pkg/local_object_storage/engine/lock.go | 8 +-- pkg/local_object_storage/engine/put.go | 2 +- pkg/local_object_storage/engine/range.go | 2 +- pkg/local_object_storage/engine/select.go | 4 +- pkg/local_object_storage/engine/shards.go | 6 +- pkg/local_object_storage/engine/tree.go | 26 ++++---- .../internal/storagetest/storage.go | 30 +++++----- .../metabase/containers_test.go | 6 +- pkg/local_object_storage/metabase/control.go | 12 ++-- .../metabase/control_test.go | 2 +- .../metabase/counter_test.go | 18 +++--- pkg/local_object_storage/metabase/db_test.go | 2 +- .../metabase/delete_ec_test.go | 8 +-- .../metabase/delete_meta_test.go | 4 +- .../metabase/delete_test.go | 12 ++-- .../metabase/exists_test.go | 3 +- .../metabase/expired_test.go | 2 +- pkg/local_object_storage/metabase/get_test.go | 6 +- .../metabase/graveyard_test.go | 12 ++-- .../metabase/inhume_ec_test.go | 4 +- .../metabase/inhume_test.go | 6 +- .../metabase/iterators_test.go | 4 +- .../metabase/list_test.go | 8 +-- .../metabase/lock_test.go | 6 +- pkg/local_object_storage/metabase/mode.go | 4 +- .../metabase/mode_test.go | 8 +-- pkg/local_object_storage/metabase/put_test.go | 6 +- .../metabase/reset_test.go | 4 +- .../metabase/select_test.go | 34 +++++------ .../metabase/storage_id_test.go | 4 +- .../metabase/upgrade_test.go | 12 ++-- .../metabase/version_test.go | 32 +++++----- .../pilorama/bench_test.go | 4 +- pkg/local_object_storage/pilorama/boltdb.go | 10 ++-- pkg/local_object_storage/pilorama/forest.go | 4 +- .../pilorama/forest_test.go | 54 ++++++++--------- .../pilorama/interface.go | 4 +- .../pilorama/mode_test.go | 8 +-- pkg/local_object_storage/shard/control.go | 16 ++--- pkg/local_object_storage/shard/gc.go | 16 ++--- .../shard/gc_internal_test.go | 4 +- pkg/local_object_storage/shard/lock_test.go | 4 +- pkg/local_object_storage/shard/shard.go | 10 ++-- pkg/local_object_storage/shard/shard_test.go | 4 +- .../writecache/benchmark/writecache_test.go | 8 +-- pkg/local_object_storage/writecache/cache.go | 10 ++-- pkg/local_object_storage/writecache/flush.go | 14 ++--- .../writecache/flush_test.go | 16 ++--- pkg/local_object_storage/writecache/mode.go | 4 +- .../writecache/mode_test.go | 8 +-- .../writecache/options.go | 6 +- .../writecache/writecache.go | 4 +- pkg/morph/client/balance/burn.go | 6 +- pkg/morph/client/balance/lock.go | 6 +- pkg/morph/client/balance/mint.go | 6 +- pkg/morph/client/balance/transfer.go | 5 +- pkg/morph/client/client.go | 4 +- pkg/morph/client/container/delete.go | 9 +-- pkg/morph/client/container/put.go | 9 +-- pkg/morph/client/frostfs/cheque.go | 10 ++-- pkg/morph/client/netmap/config.go | 5 +- pkg/morph/client/netmap/innerring.go | 5 +- pkg/morph/client/netmap/new_epoch.go | 9 +-- pkg/morph/client/netmap/peer.go | 9 +-- pkg/morph/client/netmap/update_state.go | 5 +- pkg/morph/client/notary.go | 40 +++++++------ pkg/morph/client/static.go | 8 ++- pkg/morph/event/handlers.go | 2 +- pkg/morph/event/listener.go | 8 +-- pkg/morph/event/listener_test.go | 4 +- pkg/network/transport/object/grpc/service.go | 4 +- pkg/services/apemanager/audit.go | 6 +- pkg/services/container/audit.go | 8 +-- pkg/services/container/morph/executor.go | 12 ++-- pkg/services/container/morph/executor_test.go | 4 +- pkg/services/control/ir/server/audit.go | 8 +-- pkg/services/control/ir/server/calls.go | 18 +++--- pkg/services/control/server/server.go | 5 +- .../control/server/set_netmap_status.go | 6 +- pkg/services/object/acl/v2/service.go | 34 +++++------ pkg/services/object/ape/service.go | 8 +-- pkg/services/object/audit.go | 34 +++++------ pkg/services/object/common.go | 8 +-- pkg/services/object/common/writer/common.go | 4 +- pkg/services/object/common/writer/ec.go | 2 +- pkg/services/object/get/assembleec.go | 2 +- pkg/services/object/get/container.go | 4 +- pkg/services/object/get/remote.go | 2 +- pkg/services/object/get/request.go | 12 ++-- pkg/services/object/metrics.go | 12 ++-- pkg/services/object/response.go | 8 +-- pkg/services/object/search/search.go | 10 ++-- pkg/services/object/server.go | 4 +- pkg/services/object/sign.go | 8 +-- pkg/services/object/transport_splitter.go | 8 +-- pkg/services/object/util/log.go | 8 +-- .../object_manager/tombstone/checker.go | 6 +- pkg/services/policer/check.go | 8 +-- pkg/services/tree/getsubtree_test.go | 2 +- pkg/services/tree/sync.go | 6 +- pkg/util/http/calls.go | 4 +- scripts/populate-metabase/main.go | 6 +- 209 files changed, 1068 insertions(+), 1036 deletions(-) diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index 7415e8e701..09af085254 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -93,8 +93,8 @@ func watchForSignal(ctx context.Context, cancel func()) { if err != nil { log.Error(ctx, logs.FrostFSNodeConfigurationReading, zap.Error(err)) } - pprofCmp.reload() - metricsCmp.reload() + pprofCmp.reload(ctx) + metricsCmp.reload(ctx) log.Info(ctx, logs.FrostFSIRReloadExtraWallets) err = innerRing.SetExtraWallets(cfg) if err != nil { diff --git a/cmd/frostfs-ir/httpcomponent.go b/cmd/frostfs-ir/httpcomponent.go index 685ef61add..a8eef60100 100644 --- a/cmd/frostfs-ir/httpcomponent.go +++ b/cmd/frostfs-ir/httpcomponent.go @@ -25,8 +25,8 @@ const ( shutdownTimeoutKeyPostfix = ".shutdown_timeout" ) -func (c *httpComponent) init() { - log.Info(context.Background(), "init "+c.name) +func (c *httpComponent) init(ctx context.Context) { + log.Info(ctx, "init "+c.name) c.enabled = cfg.GetBool(c.name + enabledKeyPostfix) c.address = cfg.GetString(c.name + addressKeyPostfix) c.shutdownDur = cfg.GetDuration(c.name + shutdownTimeoutKeyPostfix) @@ -40,14 +40,14 @@ func (c *httpComponent) init() { httputil.WithShutdownTimeout(c.shutdownDur), ) } else { - log.Info(context.Background(), c.name+" is disabled, skip") + log.Info(ctx, c.name+" is disabled, skip") c.srv = nil } } -func (c *httpComponent) start() { +func (c *httpComponent) start(ctx context.Context) { if c.srv != nil { - log.Info(context.Background(), "start "+c.name) + log.Info(ctx, "start "+c.name) wg.Add(1) go func() { defer wg.Done() @@ -56,10 +56,10 @@ func (c *httpComponent) start() { } } -func (c *httpComponent) shutdown() error { +func (c *httpComponent) shutdown(ctx context.Context) error { if c.srv != nil { - log.Info(context.Background(), "shutdown "+c.name) - return c.srv.Shutdown() + log.Info(ctx, "shutdown "+c.name) + return c.srv.Shutdown(ctx) } return nil } @@ -71,17 +71,17 @@ func (c *httpComponent) needReload() bool { return enabled != c.enabled || enabled && (address != c.address || dur != c.shutdownDur) } -func (c *httpComponent) reload() { - log.Info(context.Background(), "reload "+c.name) +func (c *httpComponent) reload(ctx context.Context) { + log.Info(ctx, "reload "+c.name) if c.needReload() { - log.Info(context.Background(), c.name+" config updated") - if err := c.shutdown(); err != nil { - log.Debug(context.Background(), logs.FrostFSIRCouldNotShutdownHTTPServer, + log.Info(ctx, c.name+" config updated") + if err := c.shutdown(ctx); err != nil { + log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } else { - c.init() - c.start() + c.init(ctx) + c.start(ctx) } } } diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index bcb2c5dd88..e86c04b9ed 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -87,17 +87,17 @@ func main() { ctx, cancel := context.WithCancel(context.Background()) pprofCmp = newPprofComponent() - pprofCmp.init() + pprofCmp.init(ctx) metricsCmp = newMetricsComponent() - metricsCmp.init() + metricsCmp.init(ctx) audit.Store(cfg.GetBool("audit.enabled")) innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode, audit) exitErr(err) - pprofCmp.start() - metricsCmp.start() + pprofCmp.start(ctx) + metricsCmp.start(ctx) // start inner ring err = innerRing.Start(ctx, intErr) @@ -117,12 +117,12 @@ func main() { func shutdown(ctx context.Context) { innerRing.Stop(ctx) - if err := metricsCmp.shutdown(); err != nil { + if err := metricsCmp.shutdown(ctx); err != nil { log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) } - if err := pprofCmp.shutdown(); err != nil { + if err := pprofCmp.shutdown(ctx); err != nil { log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error()), ) diff --git a/cmd/frostfs-ir/pprof.go b/cmd/frostfs-ir/pprof.go index e95fd117f7..8e81d8b85e 100644 --- a/cmd/frostfs-ir/pprof.go +++ b/cmd/frostfs-ir/pprof.go @@ -29,8 +29,8 @@ func newPprofComponent() *pprofComponent { } } -func (c *pprofComponent) init() { - c.httpComponent.init() +func (c *pprofComponent) init(ctx context.Context) { + c.httpComponent.init(ctx) if c.enabled { c.blockRate = cfg.GetInt(pprofBlockRateKey) @@ -52,17 +52,17 @@ func (c *pprofComponent) needReload() bool { c.enabled && (c.blockRate != blockRate || c.mutexRate != mutexRate) } -func (c *pprofComponent) reload() { - log.Info(context.Background(), "reload "+c.name) +func (c *pprofComponent) reload(ctx context.Context) { + log.Info(ctx, "reload "+c.name) if c.needReload() { - log.Info(context.Background(), c.name+" config updated") - if err := c.shutdown(); err != nil { - log.Debug(context.Background(), logs.FrostFSIRCouldNotShutdownHTTPServer, + log.Info(ctx, c.name+" config updated") + if err := c.shutdown(ctx); err != nil { + log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, zap.String("error", err.Error())) return } - c.init() - c.start() + c.init(ctx) + c.start(ctx) } } diff --git a/cmd/frostfs-lens/internal/blobovnicza/inspect.go b/cmd/frostfs-lens/internal/blobovnicza/inspect.go index b1a6e3fd28..e7e2c07699 100644 --- a/cmd/frostfs-lens/internal/blobovnicza/inspect.go +++ b/cmd/frostfs-lens/internal/blobovnicza/inspect.go @@ -28,7 +28,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) { common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) blz := openBlobovnicza(cmd) - defer blz.Close() + defer blz.Close(cmd.Context()) var prm blobovnicza.GetPrm prm.SetAddress(addr) diff --git a/cmd/frostfs-lens/internal/blobovnicza/list.go b/cmd/frostfs-lens/internal/blobovnicza/list.go index d327dbc416..d41a15bcfe 100644 --- a/cmd/frostfs-lens/internal/blobovnicza/list.go +++ b/cmd/frostfs-lens/internal/blobovnicza/list.go @@ -32,7 +32,7 @@ func listFunc(cmd *cobra.Command, _ []string) { } blz := openBlobovnicza(cmd) - defer blz.Close() + defer blz.Close(cmd.Context()) err := blobovnicza.IterateAddresses(context.Background(), blz, wAddr) common.ExitOnErr(cmd, common.Errf("blobovnicza iterator failure: %w", err)) diff --git a/cmd/frostfs-lens/internal/meta/inspect.go b/cmd/frostfs-lens/internal/meta/inspect.go index 9eb60f9669..f436343c71 100644 --- a/cmd/frostfs-lens/internal/meta/inspect.go +++ b/cmd/frostfs-lens/internal/meta/inspect.go @@ -31,7 +31,7 @@ func inspectFunc(cmd *cobra.Command, _ []string) { common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) db := openMeta(cmd) - defer db.Close() + defer db.Close(cmd.Context()) storageID := meta.StorageIDPrm{} storageID.SetAddress(addr) diff --git a/cmd/frostfs-lens/internal/meta/list-garbage.go b/cmd/frostfs-lens/internal/meta/list-garbage.go index 61b10ca1f7..6b27a232f4 100644 --- a/cmd/frostfs-lens/internal/meta/list-garbage.go +++ b/cmd/frostfs-lens/internal/meta/list-garbage.go @@ -19,7 +19,7 @@ func init() { func listGarbageFunc(cmd *cobra.Command, _ []string) { db := openMeta(cmd) - defer db.Close() + defer db.Close(cmd.Context()) var garbPrm meta.GarbageIterationPrm garbPrm.SetHandler( diff --git a/cmd/frostfs-lens/internal/meta/list-graveyard.go b/cmd/frostfs-lens/internal/meta/list-graveyard.go index 19a93691c2..45642e74be 100644 --- a/cmd/frostfs-lens/internal/meta/list-graveyard.go +++ b/cmd/frostfs-lens/internal/meta/list-graveyard.go @@ -19,7 +19,7 @@ func init() { func listGraveyardFunc(cmd *cobra.Command, _ []string) { db := openMeta(cmd) - defer db.Close() + defer db.Close(cmd.Context()) var gravePrm meta.GraveyardIterationPrm gravePrm.SetHandler( diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index aa92e5ec5d..5af37865f7 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -397,16 +397,16 @@ type internals struct { } // starts node's maintenance. -func (c *cfg) startMaintenance() { +func (c *cfg) startMaintenance(ctx context.Context) { c.isMaintenance.Store(true) c.cfgNetmap.state.setControlNetmapStatus(control.NetmapStatus_MAINTENANCE) - c.log.Info(context.Background(), logs.FrostFSNodeStartedLocalNodesMaintenance) + c.log.Info(ctx, logs.FrostFSNodeStartedLocalNodesMaintenance) } // stops node's maintenance. -func (c *internals) stopMaintenance() { +func (c *internals) stopMaintenance(ctx context.Context) { if c.isMaintenance.CompareAndSwap(true, false) { - c.log.Info(context.Background(), logs.FrostFSNodeStoppedLocalNodesMaintenance) + c.log.Info(ctx, logs.FrostFSNodeStoppedLocalNodesMaintenance) } } @@ -1129,10 +1129,10 @@ func initLocalStorage(ctx context.Context, c *cfg) { }) } -func initAccessPolicyEngine(_ context.Context, c *cfg) { +func initAccessPolicyEngine(ctx context.Context, c *cfg) { var localOverrideDB chainbase.LocalOverrideDatabase if nodeconfig.PersistentPolicyRules(c.appCfg).Path() == "" { - c.log.Warn(context.Background(), logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed) + c.log.Warn(ctx, logs.FrostFSNodePersistentRuleStorageDBPathIsNotSetInmemoryWillBeUsed) localOverrideDB = chainbase.NewInmemoryLocalOverrideDatabase() } else { localOverrideDB = chainbase.NewBoltLocalOverrideDatabase( @@ -1157,7 +1157,7 @@ func initAccessPolicyEngine(_ context.Context, c *cfg) { c.onShutdown(func() { if err := ape.LocalOverrideDatabaseCore().Close(); err != nil { - c.log.Warn(context.Background(), logs.FrostFSNodeAccessPolicyEngineClosingFailure, + c.log.Warn(ctx, logs.FrostFSNodeAccessPolicyEngineClosingFailure, zap.Error(err), ) } @@ -1206,10 +1206,10 @@ func (c *cfg) setContractNodeInfo(ni *netmap.NodeInfo) { c.cfgNetmap.state.setNodeInfo(ni) } -func (c *cfg) updateContractNodeInfo(epoch uint64) { +func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) { ni, err := c.netmapLocalNodeState(epoch) if err != nil { - c.log.Error(context.Background(), logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, + c.log.Error(ctx, logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, zap.Uint64("epoch", epoch), zap.String("error", err.Error())) return @@ -1221,19 +1221,19 @@ func (c *cfg) updateContractNodeInfo(epoch uint64) { // bootstrapWithState calls "addPeer" method of the Sidechain Netmap contract // with the binary-encoded information from the current node's configuration. // The state is set using the provided setter which MUST NOT be nil. -func (c *cfg) bootstrapWithState(stateSetter func(*netmap.NodeInfo)) error { +func (c *cfg) bootstrapWithState(ctx context.Context, stateSetter func(*netmap.NodeInfo)) error { ni := c.cfgNodeInfo.localInfo stateSetter(&ni) prm := nmClient.AddPeerPrm{} prm.SetNodeInfo(ni) - return c.cfgNetmap.wrapper.AddPeer(prm) + return c.cfgNetmap.wrapper.AddPeer(ctx, prm) } // bootstrapOnline calls cfg.bootstrapWithState with "online" state. -func bootstrapOnline(c *cfg) error { - return c.bootstrapWithState(func(ni *netmap.NodeInfo) { +func bootstrapOnline(ctx context.Context, c *cfg) error { + return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) { ni.SetStatus(netmap.Online) }) } @@ -1241,21 +1241,21 @@ func bootstrapOnline(c *cfg) error { // bootstrap calls bootstrapWithState with: // - "maintenance" state if maintenance is in progress on the current node // - "online", otherwise -func (c *cfg) bootstrap() error { +func (c *cfg) bootstrap(ctx context.Context) error { // switch to online except when under maintenance st := c.cfgNetmap.state.controlNetmapStatus() if st == control.NetmapStatus_MAINTENANCE { - c.log.Info(context.Background(), logs.FrostFSNodeBootstrappingWithTheMaintenanceState) - return c.bootstrapWithState(func(ni *netmap.NodeInfo) { + c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithTheMaintenanceState) + return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) { ni.SetStatus(netmap.Maintenance) }) } - c.log.Info(context.Background(), logs.FrostFSNodeBootstrappingWithOnlineState, + c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithOnlineState, zap.Stringer("previous", st), ) - return bootstrapOnline(c) + return bootstrapOnline(ctx, c) } // needBootstrap checks if local node should be registered in network on bootup. @@ -1282,7 +1282,7 @@ func (c *cfg) signalWatcher(ctx context.Context) { case <-ch: c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) - c.shutdown() + c.shutdown(ctx) c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) return @@ -1290,7 +1290,7 @@ func (c *cfg) signalWatcher(ctx context.Context) { c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError, zap.String("message", err.Error())) - c.shutdown() + c.shutdown(ctx) c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete) return @@ -1302,7 +1302,7 @@ func (c *cfg) signalWatcher(ctx context.Context) { case <-ch: c.log.Info(ctx, logs.FrostFSNodeTerminationSignalHasBeenReceivedStopping) - c.shutdown() + c.shutdown(ctx) c.log.Info(ctx, logs.FrostFSNodeTerminationSignalProcessingIsComplete) return @@ -1310,7 +1310,7 @@ func (c *cfg) signalWatcher(ctx context.Context) { c.log.Warn(ctx, logs.FrostFSNodeInternalApplicationError, zap.String("message", err.Error())) - c.shutdown() + c.shutdown(ctx) c.log.Info(ctx, logs.FrostFSNodeInternalErrorProcessingIsComplete) return @@ -1322,11 +1322,11 @@ func (c *cfg) signalWatcher(ctx context.Context) { func (c *cfg) reloadConfig(ctx context.Context) { c.log.Info(ctx, logs.FrostFSNodeSIGHUPHasBeenReceivedRereadingConfiguration) - if !c.compareAndSwapHealthStatus(control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { + if !c.compareAndSwapHealthStatus(ctx, control.HealthStatus_READY, control.HealthStatus_RECONFIGURING) { c.log.Info(ctx, logs.FrostFSNodeSIGHUPSkip) return } - defer c.compareAndSwapHealthStatus(control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) + defer c.compareAndSwapHealthStatus(ctx, control.HealthStatus_RECONFIGURING, control.HealthStatus_READY) err := c.reloadAppConfig() if err != nil { @@ -1388,7 +1388,7 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { components = append(components, dCmp{"logger", logPrm.Reload}) components = append(components, dCmp{"runtime", func() error { - setRuntimeParameters(c) + setRuntimeParameters(ctx, c) return nil }}) components = append(components, dCmp{"audit", func() error { @@ -1474,14 +1474,14 @@ func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoPro }) } -func (c *cfg) shutdown() { - old := c.swapHealthStatus(control.HealthStatus_SHUTTING_DOWN) +func (c *cfg) shutdown(ctx context.Context) { + old := c.swapHealthStatus(ctx, control.HealthStatus_SHUTTING_DOWN) if old == control.HealthStatus_SHUTTING_DOWN { - c.log.Info(context.Background(), logs.FrostFSNodeShutdownSkip) + c.log.Info(ctx, logs.FrostFSNodeShutdownSkip) return } if old == control.HealthStatus_STARTING { - c.log.Warn(context.Background(), logs.FrostFSNodeShutdownWhenNotReady) + c.log.Warn(ctx, logs.FrostFSNodeShutdownWhenNotReady) } c.ctxCancel() @@ -1491,6 +1491,6 @@ func (c *cfg) shutdown() { } if err := sdnotify.ClearStatus(); err != nil { - c.log.Error(context.Background(), logs.FailedToReportStatusToSystemd, zap.Error(err)) + c.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 3f75be2356..d3e1b27661 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -237,10 +237,10 @@ type morphContainerWriter struct { neoClient *cntClient.Client } -func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error) { - return cntClient.Put(m.neoClient, cnr) +func (m morphContainerWriter) Put(ctx context.Context, cnr containerCore.Container) (*cid.ID, error) { + return cntClient.Put(ctx, m.neoClient, cnr) } -func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error { - return cntClient.Delete(m.neoClient, witness) +func (m morphContainerWriter) Delete(ctx context.Context, witness containerCore.RemovalWitness) error { + return cntClient.Delete(ctx, m.neoClient, witness) } diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index ffac23eec3..ecd82bba51 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -16,7 +16,7 @@ import ( const serviceNameControl = "control" -func initControlService(c *cfg) { +func initControlService(ctx context.Context, c *cfg) { endpoint := controlconfig.GRPC(c.appCfg).Endpoint() if endpoint == controlconfig.GRPCEndpointDefault { return @@ -46,14 +46,14 @@ func initControlService(c *cfg) { lis, err := net.Listen("tcp", endpoint) if err != nil { - c.log.Error(context.Background(), logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpointControl, zap.Error(err)) return } c.cfgControlService.server = grpc.NewServer() c.onShutdown(func() { - stopGRPC("FrostFS Control API", c.cfgControlService.server, c.log) + stopGRPC(ctx, "FrostFS Control API", c.cfgControlService.server, c.log) }) control.RegisterControlServiceServer(c.cfgControlService.server, ctlSvc) @@ -72,23 +72,23 @@ func (c *cfg) NetmapStatus() control.NetmapStatus { return c.cfgNetmap.state.controlNetmapStatus() } -func (c *cfg) setHealthStatus(st control.HealthStatus) { - c.notifySystemd(st) +func (c *cfg) setHealthStatus(ctx context.Context, st control.HealthStatus) { + c.notifySystemd(ctx, st) c.healthStatus.Store(int32(st)) c.metricsCollector.State().SetHealth(int32(st)) } -func (c *cfg) compareAndSwapHealthStatus(oldSt, newSt control.HealthStatus) (swapped bool) { +func (c *cfg) compareAndSwapHealthStatus(ctx context.Context, oldSt, newSt control.HealthStatus) (swapped bool) { if swapped = c.healthStatus.CompareAndSwap(int32(oldSt), int32(newSt)); swapped { - c.notifySystemd(newSt) + c.notifySystemd(ctx, newSt) c.metricsCollector.State().SetHealth(int32(newSt)) } return } -func (c *cfg) swapHealthStatus(st control.HealthStatus) (old control.HealthStatus) { +func (c *cfg) swapHealthStatus(ctx context.Context, st control.HealthStatus) (old control.HealthStatus) { old = control.HealthStatus(c.healthStatus.Swap(int32(st))) - c.notifySystemd(st) + c.notifySystemd(ctx, st) c.metricsCollector.State().SetHealth(int32(st)) return } @@ -97,7 +97,7 @@ func (c *cfg) HealthStatus() control.HealthStatus { return control.HealthStatus(c.healthStatus.Load()) } -func (c *cfg) notifySystemd(st control.HealthStatus) { +func (c *cfg) notifySystemd(ctx context.Context, st control.HealthStatus) { if !c.sdNotify { return } @@ -113,6 +113,6 @@ func (c *cfg) notifySystemd(st control.HealthStatus) { err = sdnotify.Status(fmt.Sprintf("%v", st)) } if err != nil { - c.log.Error(context.Background(), logs.FailedToReportStatusToSystemd, zap.Error(err)) + c.log.Error(ctx, logs.FailedToReportStatusToSystemd, zap.Error(err)) } } diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index 271810ee6b..6105be8611 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -19,11 +19,11 @@ import ( const maxRecvMsgSize = 256 << 20 -func initGRPC(c *cfg) { +func initGRPC(ctx context.Context, c *cfg) { var endpointsToReconnect []string var successCount int grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) { - serverOpts, ok := getGrpcServerOpts(c, sc) + serverOpts, ok := getGrpcServerOpts(ctx, c, sc) if !ok { return } @@ -31,7 +31,7 @@ func initGRPC(c *cfg) { lis, err := net.Listen("tcp", sc.Endpoint()) if err != nil { c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(sc.Endpoint()) - c.log.Error(context.Background(), logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) endpointsToReconnect = append(endpointsToReconnect, sc.Endpoint()) return } @@ -40,7 +40,7 @@ func initGRPC(c *cfg) { srv := grpc.NewServer(serverOpts...) c.onShutdown(func() { - stopGRPC("FrostFS Public API", srv, c.log) + stopGRPC(ctx, "FrostFS Public API", srv, c.log) }) c.cfgGRPC.append(sc.Endpoint(), lis, srv) @@ -53,11 +53,11 @@ func initGRPC(c *cfg) { c.cfgGRPC.reconnectTimeout = grpcconfig.ReconnectTimeout(c.appCfg) for _, endpoint := range endpointsToReconnect { - scheduleReconnect(endpoint, c) + scheduleReconnect(ctx, endpoint, c) } } -func scheduleReconnect(endpoint string, c *cfg) { +func scheduleReconnect(ctx context.Context, endpoint string, c *cfg) { c.wg.Add(1) go func() { defer c.wg.Done() @@ -66,7 +66,7 @@ func scheduleReconnect(endpoint string, c *cfg) { for { select { case <-t.C: - if tryReconnect(endpoint, c) { + if tryReconnect(ctx, endpoint, c) { return } case <-c.done: @@ -76,20 +76,20 @@ func scheduleReconnect(endpoint string, c *cfg) { }() } -func tryReconnect(endpoint string, c *cfg) bool { - c.log.Info(context.Background(), logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint)) +func tryReconnect(ctx context.Context, endpoint string, c *cfg) bool { + c.log.Info(ctx, logs.FrostFSNodeGRPCReconnecting, zap.String("endpoint", endpoint)) - serverOpts, found := getGRPCEndpointOpts(endpoint, c) + serverOpts, found := getGRPCEndpointOpts(ctx, endpoint, c) if !found { - c.log.Warn(context.Background(), logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint)) + c.log.Warn(ctx, logs.FrostFSNodeGRPCServerConfigNotFound, zap.String("endpoint", endpoint)) return true } lis, err := net.Listen("tcp", endpoint) if err != nil { c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(endpoint) - c.log.Error(context.Background(), logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) - c.log.Warn(context.Background(), logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout)) + c.log.Error(ctx, logs.FrostFSNodeCantListenGRPCEndpoint, zap.Error(err)) + c.log.Warn(ctx, logs.FrostFSNodeGRPCReconnectFailed, zap.Duration("next_try_in", c.cfgGRPC.reconnectTimeout)) return false } c.metricsCollector.GrpcServerMetrics().MarkHealthy(endpoint) @@ -97,16 +97,16 @@ func tryReconnect(endpoint string, c *cfg) bool { srv := grpc.NewServer(serverOpts...) c.onShutdown(func() { - stopGRPC("FrostFS Public API", srv, c.log) + stopGRPC(ctx, "FrostFS Public API", srv, c.log) }) c.cfgGRPC.appendAndHandle(endpoint, lis, srv) - c.log.Info(context.Background(), logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint)) + c.log.Info(ctx, logs.FrostFSNodeGRPCReconnectedSuccessfully, zap.String("endpoint", endpoint)) return true } -func getGRPCEndpointOpts(endpoint string, c *cfg) (result []grpc.ServerOption, found bool) { +func getGRPCEndpointOpts(ctx context.Context, endpoint string, c *cfg) (result []grpc.ServerOption, found bool) { unlock := c.LockAppConfigShared() defer unlock() grpcconfig.IterateEndpoints(c.appCfg, func(sc *grpcconfig.Config) { @@ -117,7 +117,7 @@ func getGRPCEndpointOpts(endpoint string, c *cfg) (result []grpc.ServerOption, f return } var ok bool - result, ok = getGrpcServerOpts(c, sc) + result, ok = getGrpcServerOpts(ctx, c, sc) if !ok { return } @@ -126,7 +126,7 @@ func getGRPCEndpointOpts(endpoint string, c *cfg) (result []grpc.ServerOption, f return } -func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool) { +func getGrpcServerOpts(ctx context.Context, c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool) { serverOpts := []grpc.ServerOption{ grpc.MaxRecvMsgSize(maxRecvMsgSize), grpc.ChainUnaryInterceptor( @@ -144,7 +144,7 @@ func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool if tlsCfg != nil { cert, err := tls.LoadX509KeyPair(tlsCfg.CertificateFile(), tlsCfg.KeyFile()) if err != nil { - c.log.Error(context.Background(), logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeCouldNotReadCertificateFromFile, zap.Error(err)) return nil, false } @@ -175,38 +175,38 @@ func getGrpcServerOpts(c *cfg, sc *grpcconfig.Config) ([]grpc.ServerOption, bool return serverOpts, true } -func serveGRPC(c *cfg) { +func serveGRPC(ctx context.Context, c *cfg) { c.cfgGRPC.performAndSave(func(e string, l net.Listener, s *grpc.Server) { c.wg.Add(1) go func() { defer func() { - c.log.Info(context.Background(), logs.FrostFSNodeStopListeningGRPCEndpoint, + c.log.Info(ctx, logs.FrostFSNodeStopListeningGRPCEndpoint, zap.Stringer("endpoint", l.Addr()), ) c.wg.Done() }() - c.log.Info(context.Background(), logs.FrostFSNodeStartListeningEndpoint, + c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint, zap.String("service", "gRPC"), zap.Stringer("endpoint", l.Addr()), ) if err := s.Serve(l); err != nil { c.metricsCollector.GrpcServerMetrics().MarkUnhealthy(e) - c.log.Error(context.Background(), logs.FrostFSNodeGRPCServerError, zap.Error(err)) + c.log.Error(ctx, logs.FrostFSNodeGRPCServerError, zap.Error(err)) c.cfgGRPC.dropConnection(e) - scheduleReconnect(e, c) + scheduleReconnect(ctx, e, c) } }() }) } -func stopGRPC(name string, s *grpc.Server, l *logger.Logger) { +func stopGRPC(ctx context.Context, name string, s *grpc.Server, l *logger.Logger) { l = l.With(zap.String("name", name)) - l.Info(context.Background(), logs.FrostFSNodeStoppingGRPCServer) + l.Info(ctx, logs.FrostFSNodeStoppingGRPCServer) // GracefulStop() may freeze forever, see #1270 done := make(chan struct{}) @@ -218,9 +218,9 @@ func stopGRPC(name string, s *grpc.Server, l *logger.Logger) { select { case <-done: case <-time.After(1 * time.Minute): - l.Info(context.Background(), logs.FrostFSNodeGRPCCannotShutdownGracefullyForcingStop) + l.Info(ctx, logs.FrostFSNodeGRPCCannotShutdownGracefullyForcingStop) s.Stop() } - l.Info(context.Background(), logs.FrostFSNodeGRPCServerStoppedSuccessfully) + l.Info(ctx, logs.FrostFSNodeGRPCServerStoppedSuccessfully) } diff --git a/cmd/frostfs-node/httpcomponent.go b/cmd/frostfs-node/httpcomponent.go index a699a72a1f..7346206ef8 100644 --- a/cmd/frostfs-node/httpcomponent.go +++ b/cmd/frostfs-node/httpcomponent.go @@ -20,9 +20,9 @@ type httpComponent struct { preReload func(c *cfg) } -func (cmp *httpComponent) init(c *cfg) { +func (cmp *httpComponent) init(ctx context.Context, c *cfg) { if !cmp.enabled { - c.log.Info(context.Background(), cmp.name+" is disabled") + c.log.Info(ctx, cmp.name+" is disabled") return } // Init server with parameters @@ -39,14 +39,14 @@ func (cmp *httpComponent) init(c *cfg) { go func() { defer c.wg.Done() - c.log.Info(context.Background(), logs.FrostFSNodeStartListeningEndpoint, + c.log.Info(ctx, logs.FrostFSNodeStartListeningEndpoint, zap.String("service", cmp.name), zap.String("endpoint", cmp.address)) fatalOnErr(srv.Serve()) }() c.closers = append(c.closers, closer{ cmp.name, - func() { stopAndLog(c, cmp.name, srv.Shutdown) }, + func() { stopAndLog(ctx, c, cmp.name, srv.Shutdown) }, }) } @@ -62,7 +62,7 @@ func (cmp *httpComponent) reload(ctx context.Context) error { // Cleanup delCloser(cmp.cfg, cmp.name) // Init server with new parameters - cmp.init(cmp.cfg) + cmp.init(ctx, cmp.cfg) // Start worker if cmp.enabled { startWorker(ctx, cmp.cfg, *getWorker(cmp.cfg, cmp.name)) diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index cd42d5f1df..f8854ab3cf 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -61,21 +61,21 @@ func main() { var ctx context.Context ctx, c.ctxCancel = context.WithCancel(context.Background()) - c.setHealthStatus(control.HealthStatus_STARTING) + c.setHealthStatus(ctx, control.HealthStatus_STARTING) initApp(ctx, c) bootUp(ctx, c) - c.compareAndSwapHealthStatus(control.HealthStatus_STARTING, control.HealthStatus_READY) + c.compareAndSwapHealthStatus(ctx, control.HealthStatus_STARTING, control.HealthStatus_READY) wait(c) } -func initAndLog(c *cfg, name string, initializer func(*cfg)) { - c.log.Info(context.Background(), fmt.Sprintf("initializing %s service...", name)) +func initAndLog(ctx context.Context, c *cfg, name string, initializer func(*cfg)) { + c.log.Info(ctx, fmt.Sprintf("initializing %s service...", name)) initializer(c) - c.log.Info(context.Background(), name+" service has been successfully initialized") + c.log.Info(ctx, name+" service has been successfully initialized") } func initApp(ctx context.Context, c *cfg) { @@ -85,38 +85,38 @@ func initApp(ctx context.Context, c *cfg) { c.wg.Done() }() - setRuntimeParameters(c) + setRuntimeParameters(ctx, c) metrics, _ := metricsComponent(c) - initAndLog(c, "profiler", initProfilerService) - initAndLog(c, metrics.name, metrics.init) + initAndLog(ctx, c, "profiler", func(c *cfg) { initProfilerService(ctx, c) }) + initAndLog(ctx, c, metrics.name, func(c *cfg) { metrics.init(ctx, c) }) - initAndLog(c, "tracing", func(c *cfg) { initTracing(ctx, c) }) + initAndLog(ctx, c, "tracing", func(c *cfg) { initTracing(ctx, c) }) initLocalStorage(ctx, c) - initAndLog(c, "storage engine", func(c *cfg) { + initAndLog(ctx, c, "storage engine", func(c *cfg) { fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Open(ctx)) fatalOnErr(c.cfgObject.cfgLocalStorage.localStorage.Init(ctx)) }) - initAndLog(c, "gRPC", initGRPC) - initAndLog(c, "netmap", func(c *cfg) { initNetmapService(ctx, c) }) + initAndLog(ctx, c, "gRPC", func(c *cfg) { initGRPC(ctx, c) }) + initAndLog(ctx, c, "netmap", func(c *cfg) { initNetmapService(ctx, c) }) initAccessPolicyEngine(ctx, c) - initAndLog(c, "access policy engine", func(c *cfg) { + initAndLog(ctx, c, "access policy engine", func(c *cfg) { fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Open(ctx)) fatalOnErr(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalOverrideDatabaseCore().Init()) }) - initAndLog(c, "accounting", func(c *cfg) { initAccountingService(ctx, c) }) - initAndLog(c, "container", func(c *cfg) { initContainerService(ctx, c) }) - initAndLog(c, "session", initSessionService) - initAndLog(c, "object", initObjectService) - initAndLog(c, "tree", initTreeService) - initAndLog(c, "apemanager", initAPEManagerService) - initAndLog(c, "control", initControlService) + initAndLog(ctx, c, "accounting", func(c *cfg) { initAccountingService(ctx, c) }) + initAndLog(ctx, c, "container", func(c *cfg) { initContainerService(ctx, c) }) + initAndLog(ctx, c, "session", initSessionService) + initAndLog(ctx, c, "object", initObjectService) + initAndLog(ctx, c, "tree", initTreeService) + initAndLog(ctx, c, "apemanager", initAPEManagerService) + initAndLog(ctx, c, "control", func(c *cfg) { initControlService(ctx, c) }) - initAndLog(c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) }) + initAndLog(ctx, c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) }) } func runAndLog(ctx context.Context, c *cfg, name string, logSuccess bool, starter func(context.Context, *cfg)) { @@ -128,24 +128,24 @@ func runAndLog(ctx context.Context, c *cfg, name string, logSuccess bool, starte } } -func stopAndLog(c *cfg, name string, stopper func() error) { - c.log.Debug(context.Background(), fmt.Sprintf("shutting down %s service", name)) +func stopAndLog(ctx context.Context, c *cfg, name string, stopper func(context.Context) error) { + c.log.Debug(ctx, fmt.Sprintf("shutting down %s service", name)) - err := stopper() + err := stopper(ctx) if err != nil { - c.log.Debug(context.Background(), fmt.Sprintf("could not shutdown %s server", name), + c.log.Debug(ctx, fmt.Sprintf("could not shutdown %s server", name), zap.String("error", err.Error()), ) } - c.log.Debug(context.Background(), name+" service has been stopped") + c.log.Debug(ctx, name+" service has been stopped") } func bootUp(ctx context.Context, c *cfg) { - runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(c) }) + runAndLog(ctx, c, "gRPC", false, func(_ context.Context, c *cfg) { serveGRPC(ctx, c) }) runAndLog(ctx, c, "notary", true, makeAndWaitNotaryDeposit) - bootstrapNode(c) + bootstrapNode(ctx, c) startWorkers(ctx, c) } diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 3e010b181b..ca9f4fe3e4 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -129,7 +129,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { return } - tx, vub, err := makeNotaryDeposit(c) + tx, vub, err := makeNotaryDeposit(ctx, c) fatalOnErr(err) if tx.Equals(util.Uint256{}) { @@ -144,7 +144,7 @@ func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { fatalOnErr(err) } -func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) { +func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error) { const ( // gasMultiplier defines how many times more the notary // balance must be compared to the GAS balance of the node: @@ -161,7 +161,7 @@ func makeNotaryDeposit(c *cfg) (util.Uint256, uint32, error) { return util.Uint256{}, 0, fmt.Errorf("could not calculate notary deposit: %w", err) } - return c.cfgMorph.client.DepositEndlessNotary(depositAmount) + return c.cfgMorph.client.DepositEndlessNotary(ctx, depositAmount) } var ( @@ -256,7 +256,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { registerNotificationHandlers(c.cfgNetmap.scriptHash, lis, c.cfgNetmap.parsers, c.cfgNetmap.subscribers) registerNotificationHandlers(c.cfgContainer.scriptHash, lis, c.cfgContainer.parsers, c.cfgContainer.subscribers) - registerBlockHandler(lis, func(block *block.Block) { + registerBlockHandler(lis, func(ctx context.Context, block *block.Block) { c.log.Debug(ctx, logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index)) err = c.persistate.SetUInt32(persistateSideChainLastBlockKey, block.Index) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 35ab4d575f..6df9479543 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -145,7 +145,7 @@ func initNetmapService(ctx context.Context, c *cfg) { c.initMorphComponents(ctx) - initNetmapState(c) + initNetmapState(ctx, c) server := netmapTransportGRPC.New( netmapService.NewSignService( @@ -182,20 +182,20 @@ func addNewEpochNotificationHandlers(c *cfg) { addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, ev event.Event) { e := ev.(netmapEvent.NewEpoch).EpochNumber() - c.updateContractNodeInfo(e) + c.updateContractNodeInfo(ctx, e) if !c.needBootstrap() || c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470 return } - if err := c.bootstrap(); err != nil { + if err := c.bootstrap(ctx); err != nil { c.log.Warn(ctx, logs.FrostFSNodeCantSendRebootstrapTx, zap.Error(err)) } }) if c.cfgMorph.notaryEnabled { addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) { - _, _, err := makeNotaryDeposit(c) + _, _, err := makeNotaryDeposit(ctx, c) if err != nil { c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit, zap.String("error", err.Error()), @@ -207,13 +207,13 @@ func addNewEpochNotificationHandlers(c *cfg) { // bootstrapNode adds current node to the Network map. // Must be called after initNetmapService. -func bootstrapNode(c *cfg) { +func bootstrapNode(ctx context.Context, c *cfg) { if c.needBootstrap() { if c.IsMaintenance() { - c.log.Info(context.Background(), logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) + c.log.Info(ctx, logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) return } - err := c.bootstrap() + err := c.bootstrap(ctx) fatalOnErrDetails("bootstrap error", err) } } @@ -240,17 +240,17 @@ func setNetmapNotificationParser(c *cfg, sTyp string, p event.NotificationParser // initNetmapState inits current Network map state. // Must be called after Morph components initialization. -func initNetmapState(c *cfg) { +func initNetmapState(ctx context.Context, c *cfg) { epoch, err := c.cfgNetmap.wrapper.Epoch() fatalOnErrDetails("could not initialize current epoch number", err) var ni *netmapSDK.NodeInfo - ni, err = c.netmapInitLocalNodeState(epoch) + ni, err = c.netmapInitLocalNodeState(ctx, epoch) fatalOnErrDetails("could not init network state", err) stateWord := nodeState(ni) - c.log.Info(context.Background(), logs.FrostFSNodeInitialNetworkState, + c.log.Info(ctx, logs.FrostFSNodeInitialNetworkState, zap.Uint64("epoch", epoch), zap.String("state", stateWord), ) @@ -279,7 +279,7 @@ func nodeState(ni *netmapSDK.NodeInfo) string { return "undefined" } -func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error) { +func (c *cfg) netmapInitLocalNodeState(ctx context.Context, epoch uint64) (*netmapSDK.NodeInfo, error) { nmNodes, err := c.cfgNetmap.wrapper.GetCandidates() if err != nil { return nil, err @@ -307,7 +307,7 @@ func (c *cfg) netmapInitLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error if nmState != candidateState { // This happens when the node was switched to maintenance without epoch tick. // We expect it to continue staying in maintenance. - c.log.Info(context.Background(), logs.CandidateStatusPriority, + c.log.Info(ctx, logs.CandidateStatusPriority, zap.String("netmap", nmState), zap.String("candidate", candidateState)) } @@ -353,16 +353,16 @@ func addNewEpochAsyncNotificationHandler(c *cfg, h event.Handler) { var errRelayBootstrap = errors.New("setting netmap status is forbidden in relay mode") -func (c *cfg) SetNetmapStatus(st control.NetmapStatus) error { +func (c *cfg) SetNetmapStatus(ctx context.Context, st control.NetmapStatus) error { switch st { default: return fmt.Errorf("unsupported status %v", st) case control.NetmapStatus_MAINTENANCE: - return c.setMaintenanceStatus(false) + return c.setMaintenanceStatus(ctx, false) case control.NetmapStatus_ONLINE, control.NetmapStatus_OFFLINE: } - c.stopMaintenance() + c.stopMaintenance(ctx) if !c.needBootstrap() { return errRelayBootstrap @@ -370,12 +370,12 @@ func (c *cfg) SetNetmapStatus(st control.NetmapStatus) error { if st == control.NetmapStatus_ONLINE { c.cfgNetmap.reBoostrapTurnedOff.Store(false) - return bootstrapOnline(c) + return bootstrapOnline(ctx, c) } c.cfgNetmap.reBoostrapTurnedOff.Store(true) - return c.updateNetMapState(func(*nmClient.UpdatePeerPrm) {}) + return c.updateNetMapState(ctx, func(*nmClient.UpdatePeerPrm) {}) } func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) { @@ -387,11 +387,11 @@ func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) { return st, epoch, nil } -func (c *cfg) ForceMaintenance() error { - return c.setMaintenanceStatus(true) +func (c *cfg) ForceMaintenance(ctx context.Context) error { + return c.setMaintenanceStatus(ctx, true) } -func (c *cfg) setMaintenanceStatus(force bool) error { +func (c *cfg) setMaintenanceStatus(ctx context.Context, force bool) error { netSettings, err := c.cfgNetmap.wrapper.ReadNetworkConfiguration() if err != nil { err = fmt.Errorf("read network settings to check maintenance allowance: %w", err) @@ -400,10 +400,10 @@ func (c *cfg) setMaintenanceStatus(force bool) error { } if err == nil || force { - c.startMaintenance() + c.startMaintenance(ctx) if err == nil { - err = c.updateNetMapState((*nmClient.UpdatePeerPrm).SetMaintenance) + err = c.updateNetMapState(ctx, (*nmClient.UpdatePeerPrm).SetMaintenance) } if err != nil { @@ -416,12 +416,12 @@ func (c *cfg) setMaintenanceStatus(force bool) error { // calls UpdatePeerState operation of Netmap contract's client for the local node. // State setter is used to specify node state to switch to. -func (c *cfg) updateNetMapState(stateSetter func(*nmClient.UpdatePeerPrm)) error { +func (c *cfg) updateNetMapState(ctx context.Context, stateSetter func(*nmClient.UpdatePeerPrm)) error { var prm nmClient.UpdatePeerPrm prm.SetKey(c.key.PublicKey().Bytes()) stateSetter(&prm) - _, err := c.cfgNetmap.wrapper.UpdatePeerState(prm) + _, err := c.cfgNetmap.wrapper.UpdatePeerState(ctx, prm) return err } diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index cad6d5ee36..c4205a620c 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -66,11 +66,11 @@ func (c *cfg) MaxObjectSize() uint64 { return sz } -func (s *objectSvc) Put() (objectService.PutObjectStream, error) { +func (s *objectSvc) Put(_ context.Context) (objectService.PutObjectStream, error) { return s.put.Put() } -func (s *objectSvc) Patch() (objectService.PatchObjectStream, error) { +func (s *objectSvc) Patch(_ context.Context) (objectService.PatchObjectStream, error) { return s.patch.Patch() } diff --git a/cmd/frostfs-node/pprof.go b/cmd/frostfs-node/pprof.go index dcd320146d..5b40c8a88a 100644 --- a/cmd/frostfs-node/pprof.go +++ b/cmd/frostfs-node/pprof.go @@ -1,17 +1,18 @@ package main import ( + "context" "runtime" profilerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/profiler" httputil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/http" ) -func initProfilerService(c *cfg) { +func initProfilerService(ctx context.Context, c *cfg) { tuneProfilers(c) pprof, _ := pprofComponent(c) - pprof.init(c) + pprof.init(ctx, c) } func pprofComponent(c *cfg) (*httpComponent, bool) { diff --git a/cmd/frostfs-node/runtime.go b/cmd/frostfs-node/runtime.go index 0b1000e705..f6d398574b 100644 --- a/cmd/frostfs-node/runtime.go +++ b/cmd/frostfs-node/runtime.go @@ -10,17 +10,17 @@ import ( "go.uber.org/zap" ) -func setRuntimeParameters(c *cfg) { +func setRuntimeParameters(ctx context.Context, c *cfg) { if len(os.Getenv("GOMEMLIMIT")) != 0 { // default limit < yaml limit < app env limit < GOMEMLIMIT - c.log.Warn(context.Background(), logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT) + c.log.Warn(ctx, logs.RuntimeSoftMemoryDefinedWithGOMEMLIMIT) return } memLimitBytes := runtime.GCMemoryLimitBytes(c.appCfg) previous := debug.SetMemoryLimit(memLimitBytes) if memLimitBytes != previous { - c.log.Info(context.Background(), logs.RuntimeSoftMemoryLimitUpdated, + c.log.Info(ctx, logs.RuntimeSoftMemoryLimitUpdated, zap.Int64("new_value", memLimitBytes), zap.Int64("old_value", previous)) } diff --git a/internal/audit/request.go b/internal/audit/request.go index 15a4a79603..17666ab4b9 100644 --- a/internal/audit/request.go +++ b/internal/audit/request.go @@ -19,15 +19,15 @@ type Target interface { String() string } -func LogRequest(log *logger.Logger, operation string, req Request, target Target, status bool) { +func LogRequest(ctx context.Context, log *logger.Logger, operation string, req Request, target Target, status bool) { var key []byte if req != nil { key = req.GetVerificationHeader().GetBodySignature().GetKey() } - LogRequestWithKey(log, operation, key, target, status) + LogRequestWithKey(ctx, log, operation, key, target, status) } -func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target Target, status bool) { +func LogRequestWithKey(ctx context.Context, log *logger.Logger, operation string, key []byte, target Target, status bool) { object, subject := NotDefined, NotDefined publicKey := crypto.UnmarshalPublicKey(key) @@ -39,7 +39,7 @@ func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target object = target.String() } - log.Info(context.Background(), logs.AuditEventLogRecord, + log.Info(ctx, logs.AuditEventLogRecord, zap.String("operation", operation), zap.String("object", object), zap.String("subject", subject), diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index 5bc5c8bea4..19b5d34e46 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -117,7 +117,7 @@ func (v *FormatValidator) Validate(ctx context.Context, obj *objectSDK.Object, u } if !unprepared { - if err := v.validateSignatureKey(obj); err != nil { + if err := v.validateSignatureKey(ctx, obj); err != nil { return fmt.Errorf("(%T) could not validate signature key: %w", v, err) } @@ -134,7 +134,7 @@ func (v *FormatValidator) Validate(ctx context.Context, obj *objectSDK.Object, u return nil } -func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { +func (v *FormatValidator) validateSignatureKey(ctx context.Context, obj *objectSDK.Object) error { sig := obj.Signature() if sig == nil { return errMissingSignature @@ -156,7 +156,7 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { ownerID := obj.OwnerID() if token == nil && obj.ECHeader() != nil { - role, err := v.isIROrContainerNode(obj, binKey) + role, err := v.isIROrContainerNode(ctx, obj, binKey) if err != nil { return err } @@ -172,7 +172,7 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { } if v.verifyTokenIssuer { - role, err := v.isIROrContainerNode(obj, binKey) + role, err := v.isIROrContainerNode(ctx, obj, binKey) if err != nil { return err } @@ -190,7 +190,7 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error { return nil } -func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey []byte) (acl.Role, error) { +func (v *FormatValidator) isIROrContainerNode(ctx context.Context, obj *objectSDK.Object, signerKey []byte) (acl.Role, error) { cnrID, containerIDSet := obj.ContainerID() if !containerIDSet { return acl.RoleOthers, errNilCID @@ -204,7 +204,7 @@ func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey [ return acl.RoleOthers, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err) } - res, err := v.senderClassifier.IsInnerRingOrContainerNode(signerKey, cnrID, cnr.Value) + res, err := v.senderClassifier.IsInnerRingOrContainerNode(ctx, signerKey, cnrID, cnr.Value) if err != nil { return acl.RoleOthers, err } diff --git a/pkg/core/object/sender_classifier.go b/pkg/core/object/sender_classifier.go index ed438c0b95..3b3650134c 100644 --- a/pkg/core/object/sender_classifier.go +++ b/pkg/core/object/sender_classifier.go @@ -41,6 +41,7 @@ type ClassifyResult struct { } func (c SenderClassifier) Classify( + ctx context.Context, ownerID *user.ID, ownerKey *keys.PublicKey, idCnr cid.ID, @@ -58,14 +59,14 @@ func (c SenderClassifier) Classify( }, nil } - return c.IsInnerRingOrContainerNode(ownerKeyInBytes, idCnr, cnr) + return c.IsInnerRingOrContainerNode(ctx, ownerKeyInBytes, idCnr, cnr) } -func (c SenderClassifier) IsInnerRingOrContainerNode(ownerKeyInBytes []byte, idCnr cid.ID, cnr container.Container) (*ClassifyResult, error) { +func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerKeyInBytes []byte, idCnr cid.ID, cnr container.Container) (*ClassifyResult, error) { isInnerRingNode, err := c.isInnerRingKey(ownerKeyInBytes) if err != nil { // do not throw error, try best case matching - c.log.Debug(context.Background(), logs.V2CantCheckIfRequestFromInnerRing, + c.log.Debug(ctx, logs.V2CantCheckIfRequestFromInnerRing, zap.String("error", err.Error())) } else if isInnerRingNode { return &ClassifyResult{ @@ -82,7 +83,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ownerKeyInBytes []byte, idC // error might happen if request has `RoleOther` key and placement // is not possible for previous epoch, so // do not throw error, try best case matching - c.log.Debug(context.Background(), logs.V2CantCheckIfRequestFromContainerNode, + c.log.Debug(ctx, logs.V2CantCheckIfRequestFromContainerNode, zap.String("error", err.Error())) } else if isContainerNode { return &ClassifyResult{ diff --git a/pkg/innerring/blocktimer.go b/pkg/innerring/blocktimer.go index 3db5043683..3f9d8df5ff 100644 --- a/pkg/innerring/blocktimer.go +++ b/pkg/innerring/blocktimer.go @@ -29,7 +29,7 @@ type ( emitDuration uint32 // in blocks } - depositor func() (util.Uint256, error) + depositor func(context.Context) (util.Uint256, error) awaiter func(context.Context, util.Uint256) error ) @@ -66,11 +66,11 @@ func newEpochTimer(args *epochTimerArgs) *timer.BlockTimer { ) } -func newEmissionTimer(args *emitTimerArgs) *timer.BlockTimer { +func newEmissionTimer(ctx context.Context, args *emitTimerArgs) *timer.BlockTimer { return timer.NewBlockTimer( timer.StaticBlockMeter(args.emitDuration), func() { - args.ap.HandleGasEmission(timerEvent.NewAlphabetEmitTick{}) + args.ap.HandleGasEmission(ctx, timerEvent.NewAlphabetEmitTick{}) }, ) } diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index e08a613c3f..25f4ff0347 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -35,7 +35,7 @@ import ( "google.golang.org/grpc" ) -func (s *Server) initNetmapProcessor(cfg *viper.Viper, +func (s *Server) initNetmapProcessor(ctx context.Context, cfg *viper.Viper, alphaSync event.Handler, ) error { locodeValidator, err := s.newLocodeValidator(cfg) @@ -48,10 +48,13 @@ func (s *Server) initNetmapProcessor(cfg *viper.Viper, var netMapCandidateStateValidator statevalidation.NetMapCandidateValidator netMapCandidateStateValidator.SetNetworkSettings(netSettings) + poolSize := cfg.GetInt("workers.netmap") + s.log.Debug(ctx, logs.NetmapNetmapWorkerPool, zap.Int("size", poolSize)) + s.netmapProcessor, err = netmap.New(&netmap.Params{ Log: s.log, Metrics: s.irMetrics, - PoolSize: cfg.GetInt("workers.netmap"), + PoolSize: poolSize, NetmapClient: netmap.NewNetmapClient(s.netmapClient), EpochTimer: s, EpochState: s, @@ -205,7 +208,7 @@ func (s *Server) initTimers(ctx context.Context, cfg *viper.Viper) { s.addBlockTimer(s.epochTimer) // initialize emission timer - emissionTimer := newEmissionTimer(&emitTimerArgs{ + emissionTimer := newEmissionTimer(ctx, &emitTimerArgs{ ap: s.alphabetProcessor, emitDuration: cfg.GetUint32("timers.emit"), }) @@ -213,18 +216,20 @@ func (s *Server) initTimers(ctx context.Context, cfg *viper.Viper) { s.addBlockTimer(emissionTimer) } -func (s *Server) initAlphabetProcessor(cfg *viper.Viper) error { +func (s *Server) initAlphabetProcessor(ctx context.Context, cfg *viper.Viper) error { parsedWallets, err := parseWalletAddressesFromStrings(cfg.GetStringSlice("emit.extra_wallets")) if err != nil { return err } + poolSize := cfg.GetInt("workers.alphabet") + s.log.Debug(ctx, logs.AlphabetAlphabetWorkerPool, zap.Int("size", poolSize)) // create alphabet processor s.alphabetProcessor, err = alphabet.New(&alphabet.Params{ ParsedWallets: parsedWallets, Log: s.log, Metrics: s.irMetrics, - PoolSize: cfg.GetInt("workers.alphabet"), + PoolSize: poolSize, AlphabetContracts: s.contracts.alphabet, NetmapClient: s.netmapClient, MorphClient: s.morphClient, @@ -239,12 +244,14 @@ func (s *Server) initAlphabetProcessor(cfg *viper.Viper) error { return err } -func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.Client, frostfsIDClient *frostfsid.Client) error { +func (s *Server) initContainerProcessor(ctx context.Context, cfg *viper.Viper, cnrClient *container.Client, frostfsIDClient *frostfsid.Client) error { + poolSize := cfg.GetInt("workers.container") + s.log.Debug(ctx, logs.ContainerContainerWorkerPool, zap.Int("size", poolSize)) // container processor containerProcessor, err := cont.New(&cont.Params{ Log: s.log, Metrics: s.irMetrics, - PoolSize: cfg.GetInt("workers.container"), + PoolSize: poolSize, AlphabetState: s, ContainerClient: cnrClient, MorphClient: cnrClient.Morph(), @@ -258,12 +265,14 @@ func (s *Server) initContainerProcessor(cfg *viper.Viper, cnrClient *container.C return bindMorphProcessor(containerProcessor, s) } -func (s *Server) initBalanceProcessor(cfg *viper.Viper, frostfsCli *frostfsClient.Client) error { +func (s *Server) initBalanceProcessor(ctx context.Context, cfg *viper.Viper, frostfsCli *frostfsClient.Client) error { + poolSize := cfg.GetInt("workers.balance") + s.log.Debug(ctx, logs.BalanceBalanceWorkerPool, zap.Int("size", poolSize)) // create balance processor balanceProcessor, err := balance.New(&balance.Params{ Log: s.log, Metrics: s.irMetrics, - PoolSize: cfg.GetInt("workers.balance"), + PoolSize: poolSize, FrostFSClient: frostfsCli, BalanceSC: s.contracts.balance, AlphabetState: s, @@ -276,15 +285,17 @@ func (s *Server) initBalanceProcessor(cfg *viper.Viper, frostfsCli *frostfsClien return bindMorphProcessor(balanceProcessor, s) } -func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error { +func (s *Server) initFrostFSMainnetProcessor(ctx context.Context, cfg *viper.Viper) error { if s.withoutMainNet { return nil } + poolSize := cfg.GetInt("workers.frostfs") + s.log.Debug(ctx, logs.FrostFSFrostfsWorkerPool, zap.Int("size", poolSize)) frostfsProcessor, err := frostfs.New(&frostfs.Params{ Log: s.log, Metrics: s.irMetrics, - PoolSize: cfg.GetInt("workers.frostfs"), + PoolSize: poolSize, FrostFSContract: s.contracts.frostfs, BalanceClient: s.balanceClient, NetmapClient: s.netmapClient, @@ -304,10 +315,10 @@ func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error { return bindMainnetProcessor(frostfsProcessor, s) } -func (s *Server) initGRPCServer(cfg *viper.Viper, log *logger.Logger, audit *atomic.Bool) error { +func (s *Server) initGRPCServer(ctx context.Context, cfg *viper.Viper, log *logger.Logger, audit *atomic.Bool) error { controlSvcEndpoint := cfg.GetString("control.grpc.endpoint") if controlSvcEndpoint == "" { - s.log.Info(context.Background(), logs.InnerringNoControlServerEndpointSpecified) + s.log.Info(ctx, logs.InnerringNoControlServerEndpointSpecified) return nil } @@ -403,7 +414,7 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) { return result, nil } -func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClients) error { +func (s *Server) initProcessors(ctx context.Context, cfg *viper.Viper, morphClients *serverMorphClients) error { irf := s.createIRFetcher() s.statusIndex = newInnerRingIndexer( @@ -418,27 +429,27 @@ func (s *Server) initProcessors(cfg *viper.Viper, morphClients *serverMorphClien return err } - err = s.initNetmapProcessor(cfg, alphaSync) + err = s.initNetmapProcessor(ctx, cfg, alphaSync) if err != nil { return err } - err = s.initContainerProcessor(cfg, morphClients.CnrClient, morphClients.FrostFSIDClient) + err = s.initContainerProcessor(ctx, cfg, morphClients.CnrClient, morphClients.FrostFSIDClient) if err != nil { return err } - err = s.initBalanceProcessor(cfg, morphClients.FrostFSClient) + err = s.initBalanceProcessor(ctx, cfg, morphClients.FrostFSClient) if err != nil { return err } - err = s.initFrostFSMainnetProcessor(cfg) + err = s.initFrostFSMainnetProcessor(ctx, cfg) if err != nil { return err } - err = s.initAlphabetProcessor(cfg) + err = s.initAlphabetProcessor(ctx, cfg) return err } diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index e81ec6bca6..4fe9cc0847 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -157,7 +157,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { return err } - if s.IsAlphabet() { + if s.IsAlphabet(ctx) { err = s.initMainNotary(ctx) if err != nil { return err @@ -217,14 +217,14 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { } func (s *Server) registerMorphNewBlockEventHandler() { - s.morphListener.RegisterBlockHandler(func(b *block.Block) { - s.log.Debug(context.Background(), logs.InnerringNewBlock, + s.morphListener.RegisterBlockHandler(func(ctx context.Context, b *block.Block) { + s.log.Debug(ctx, logs.InnerringNewBlock, zap.Uint32("index", b.Index), ) err := s.persistate.SetUInt32(persistateSideChainLastBlockKey, b.Index) if err != nil { - s.log.Warn(context.Background(), logs.InnerringCantUpdatePersistentState, + s.log.Warn(ctx, logs.InnerringCantUpdatePersistentState, zap.String("chain", "side"), zap.Uint32("block_index", b.Index)) } @@ -235,10 +235,10 @@ func (s *Server) registerMorphNewBlockEventHandler() { func (s *Server) registerMainnetNewBlockEventHandler() { if !s.withoutMainNet { - s.mainnetListener.RegisterBlockHandler(func(b *block.Block) { + s.mainnetListener.RegisterBlockHandler(func(ctx context.Context, b *block.Block) { err := s.persistate.SetUInt32(persistateMainChainLastBlockKey, b.Index) if err != nil { - s.log.Warn(context.Background(), logs.InnerringCantUpdatePersistentState, + s.log.Warn(ctx, logs.InnerringCantUpdatePersistentState, zap.String("chain", "main"), zap.Uint32("block_index", b.Index)) } @@ -400,14 +400,14 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan return nil, err } - err = server.initProcessors(cfg, morphClients) + err = server.initProcessors(ctx, cfg, morphClients) if err != nil { return nil, err } server.initTimers(ctx, cfg) - err = server.initGRPCServer(cfg, log, audit) + err = server.initGRPCServer(ctx, cfg, log, audit) if err != nil { return nil, err } @@ -604,7 +604,7 @@ func (s *Server) initConfigFromBlockchain(ctx context.Context) error { s.log.Debug(ctx, logs.InnerringReadConfigFromBlockchain, zap.Bool("active", s.IsActive(ctx)), - zap.Bool("alphabet", s.IsAlphabet()), + zap.Bool("alphabet", s.IsAlphabet(ctx)), zap.Uint64("epoch", epoch), zap.Uint32("precision", balancePrecision), zap.Uint32("init_epoch_tick_delta", s.initialEpochTickDelta), @@ -636,7 +636,7 @@ func (s *Server) nextEpochBlockDelta() (uint32, error) { // only if inner ring node is alphabet node. func (s *Server) onlyAlphabetEventHandler(f event.Handler) event.Handler { return func(ctx context.Context, ev event.Event) { - if s.IsAlphabet() { + if s.IsAlphabet(ctx) { f(ctx, ev) } } diff --git a/pkg/innerring/notary.go b/pkg/innerring/notary.go index dd3afa2c23..c8a69962f9 100644 --- a/pkg/innerring/notary.go +++ b/pkg/innerring/notary.go @@ -28,37 +28,38 @@ const ( gasDivisor = 2 ) -func (s *Server) depositMainNotary() (tx util.Uint256, err error) { +func (s *Server) depositMainNotary(ctx context.Context) (tx util.Uint256, err error) { depositAmount, err := client.CalculateNotaryDepositAmount(s.mainnetClient, gasMultiplier, gasDivisor) if err != nil { return util.Uint256{}, fmt.Errorf("could not calculate main notary deposit amount: %w", err) } return s.mainnetClient.DepositNotary( + ctx, depositAmount, uint32(s.epochDuration.Load())+notaryExtraBlocks, ) } -func (s *Server) depositSideNotary() (util.Uint256, error) { +func (s *Server) depositSideNotary(ctx context.Context) (util.Uint256, error) { depositAmount, err := client.CalculateNotaryDepositAmount(s.morphClient, gasMultiplier, gasDivisor) if err != nil { return util.Uint256{}, fmt.Errorf("could not calculate side notary deposit amount: %w", err) } - tx, _, err := s.morphClient.DepositEndlessNotary(depositAmount) + tx, _, err := s.morphClient.DepositEndlessNotary(ctx, depositAmount) return tx, err } func (s *Server) notaryHandler(ctx context.Context, _ event.Event) { if !s.mainNotaryConfig.disabled { - _, err := s.depositMainNotary() + _, err := s.depositMainNotary(ctx) if err != nil { s.log.Error(ctx, logs.InnerringCantMakeNotaryDepositInMainChain, zap.Error(err)) } } - if _, err := s.depositSideNotary(); err != nil { + if _, err := s.depositSideNotary(ctx); err != nil { s.log.Error(ctx, logs.InnerringCantMakeNotaryDepositInSideChain, zap.Error(err)) } } @@ -72,7 +73,7 @@ func (s *Server) awaitSideNotaryDeposit(ctx context.Context, tx util.Uint256) er } func (s *Server) initNotary(ctx context.Context, deposit depositor, await awaiter, msg string) error { - tx, err := deposit() + tx, err := deposit(ctx) if err != nil { return err } diff --git a/pkg/innerring/processors/alphabet/handlers.go b/pkg/innerring/processors/alphabet/handlers.go index 0cc2a5f395..d6b6532827 100644 --- a/pkg/innerring/processors/alphabet/handlers.go +++ b/pkg/innerring/processors/alphabet/handlers.go @@ -10,16 +10,16 @@ import ( "go.uber.org/zap" ) -func (ap *Processor) HandleGasEmission(ev event.Event) { +func (ap *Processor) HandleGasEmission(ctx context.Context, ev event.Event) { _ = ev.(timers.NewAlphabetEmitTick) - ap.log.Info(context.Background(), logs.AlphabetTick, zap.String("type", "alphabet gas emit")) + ap.log.Info(ctx, logs.AlphabetTick, zap.String("type", "alphabet gas emit")) // send event to the worker pool - err := processors.SubmitEvent(ap.pool, ap.metrics, "alphabet_emit_gas", ap.processEmit) + err := processors.SubmitEvent(ap.pool, ap.metrics, "alphabet_emit_gas", func() bool { return ap.processEmit(ctx) }) if err != nil { // there system can be moved into controlled degradation stage - ap.log.Warn(context.Background(), logs.AlphabetAlphabetProcessorWorkerPoolDrained, + ap.log.Warn(ctx, logs.AlphabetAlphabetProcessorWorkerPoolDrained, zap.Int("capacity", ap.pool.Cap())) } } diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index c7a004b54f..036b8055cf 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -1,6 +1,7 @@ package alphabet_test import ( + "context" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" @@ -60,7 +61,7 @@ func TestProcessorEmitsGasToNetmapAndAlphabet(t *testing.T) { processor, err := alphabet.New(params) require.NoError(t, err, "failed to create processor instance") - processor.HandleGasEmission(timers.NewAlphabetEmitTick{}) + processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{}) processor.WaitPoolRunning() @@ -137,7 +138,7 @@ func TestProcessorEmitsGasToNetmapIfNoParsedWallets(t *testing.T) { processor, err := alphabet.New(params) require.NoError(t, err, "failed to create processor instance") - processor.HandleGasEmission(timers.NewAlphabetEmitTick{}) + processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{}) processor.WaitPoolRunning() @@ -198,7 +199,7 @@ func TestProcessorDoesntEmitGasIfNoNetmapOrParsedWallets(t *testing.T) { processor, err := alphabet.New(params) require.NoError(t, err, "failed to create processor instance") - processor.HandleGasEmission(timers.NewAlphabetEmitTick{}) + processor.HandleGasEmission(context.Background(), timers.NewAlphabetEmitTick{}) processor.WaitPoolRunning() @@ -219,7 +220,7 @@ type testIndexer struct { index int } -func (i *testIndexer) AlphabetIndex() int { +func (i *testIndexer) AlphabetIndex(context.Context) int { return i.index } @@ -246,7 +247,7 @@ type testMorphClient struct { batchTransferedGas []batchTransferGas } -func (c *testMorphClient) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { +func (c *testMorphClient) Invoke(_ context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { c.invokedMethods = append(c.invokedMethods, invokedMethod{ contract: contract, diff --git a/pkg/innerring/processors/alphabet/process_emit.go b/pkg/innerring/processors/alphabet/process_emit.go index 142409631d..2292612508 100644 --- a/pkg/innerring/processors/alphabet/process_emit.go +++ b/pkg/innerring/processors/alphabet/process_emit.go @@ -14,39 +14,39 @@ import ( const emitMethod = "emit" -func (ap *Processor) processEmit() bool { - index := ap.irList.AlphabetIndex() +func (ap *Processor) processEmit(ctx context.Context) bool { + index := ap.irList.AlphabetIndex(ctx) if index < 0 { - ap.log.Info(context.Background(), logs.AlphabetNonAlphabetModeIgnoreGasEmissionEvent) + ap.log.Info(ctx, logs.AlphabetNonAlphabetModeIgnoreGasEmissionEvent) return true } contract, ok := ap.alphabetContracts.GetByIndex(index) if !ok { - ap.log.Debug(context.Background(), logs.AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent, + ap.log.Debug(ctx, logs.AlphabetNodeIsOutOfAlphabetRangeIgnoreGasEmissionEvent, zap.Int("index", index)) return false } // there is no signature collecting, so we don't need extra fee - _, err := ap.morphClient.Invoke(contract, 0, emitMethod) + _, err := ap.morphClient.Invoke(ctx, contract, 0, emitMethod) if err != nil { - ap.log.Warn(context.Background(), logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) + ap.log.Warn(ctx, logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) return false } if ap.storageEmission == 0 { - ap.log.Info(context.Background(), logs.AlphabetStorageNodeEmissionIsOff) + ap.log.Info(ctx, logs.AlphabetStorageNodeEmissionIsOff) return true } networkMap, err := ap.netmapClient.NetMap() if err != nil { - ap.log.Warn(context.Background(), logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, + ap.log.Warn(ctx, logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, zap.String("error", err.Error())) return false @@ -59,7 +59,7 @@ func (ap *Processor) processEmit() bool { ap.pwLock.RUnlock() extraLen := len(pw) - ap.log.Debug(context.Background(), logs.AlphabetGasEmission, + ap.log.Debug(ctx, logs.AlphabetGasEmission, zap.Int("network_map", nmLen), zap.Int("extra_wallets", extraLen)) @@ -69,20 +69,20 @@ func (ap *Processor) processEmit() bool { gasPerNode := fixedn.Fixed8(ap.storageEmission / uint64(nmLen+extraLen)) - ap.transferGasToNetmapNodes(nmNodes, gasPerNode) + ap.transferGasToNetmapNodes(ctx, nmNodes, gasPerNode) - ap.transferGasToExtraNodes(pw, gasPerNode) + ap.transferGasToExtraNodes(ctx, pw, gasPerNode) return true } -func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerNode fixedn.Fixed8) { +func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []netmap.NodeInfo, gasPerNode fixedn.Fixed8) { for i := range nmNodes { keyBytes := nmNodes[i].PublicKey() key, err := keys.NewPublicKeyFromBytes(keyBytes, elliptic.P256()) if err != nil { - ap.log.Warn(context.Background(), logs.AlphabetCantParseNodePublicKey, + ap.log.Warn(ctx, logs.AlphabetCantParseNodePublicKey, zap.String("error", err.Error())) continue @@ -90,7 +90,7 @@ func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerN err = ap.morphClient.TransferGas(key.GetScriptHash(), gasPerNode) if err != nil { - ap.log.Warn(context.Background(), logs.AlphabetCantTransferGas, + ap.log.Warn(ctx, logs.AlphabetCantTransferGas, zap.String("receiver", key.Address()), zap.Int64("amount", int64(gasPerNode)), zap.String("error", err.Error()), @@ -99,7 +99,7 @@ func (ap *Processor) transferGasToNetmapNodes(nmNodes []netmap.NodeInfo, gasPerN } } -func (ap *Processor) transferGasToExtraNodes(pw []util.Uint160, gasPerNode fixedn.Fixed8) { +func (ap *Processor) transferGasToExtraNodes(ctx context.Context, pw []util.Uint160, gasPerNode fixedn.Fixed8) { if len(pw) > 0 { err := ap.morphClient.BatchTransferGas(pw, gasPerNode) if err != nil { @@ -107,7 +107,7 @@ func (ap *Processor) transferGasToExtraNodes(pw []util.Uint160, gasPerNode fixed for i, addr := range pw { receiversLog[i] = addr.StringLE() } - ap.log.Warn(context.Background(), logs.AlphabetCantTransferGasToWallet, + ap.log.Warn(ctx, logs.AlphabetCantTransferGasToWallet, zap.Strings("receivers", receiversLog), zap.Int64("amount", int64(gasPerNode)), zap.String("error", err.Error()), diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index 8dbef1e209..bf74834ed9 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -7,7 +7,6 @@ import ( "sync" "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" @@ -15,13 +14,12 @@ import ( "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" - "go.uber.org/zap" ) type ( // Indexer is a callback interface for inner ring global state. Indexer interface { - AlphabetIndex() int + AlphabetIndex(context.Context) int } // Contracts is an interface of the storage @@ -41,7 +39,7 @@ type ( } morphClient interface { - Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) + Invoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8) error } @@ -86,8 +84,6 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/alphabet: global state is not set") } - p.Log.Debug(context.Background(), logs.AlphabetAlphabetWorkerPool, zap.Int("size", p.PoolSize)) - pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { return nil, fmt.Errorf("ir/frostfs: can't create worker pool: %w", err) diff --git a/pkg/innerring/processors/balance/handlers.go b/pkg/innerring/processors/balance/handlers.go index 5a89e6f7ce..b5d05a02e7 100644 --- a/pkg/innerring/processors/balance/handlers.go +++ b/pkg/innerring/processors/balance/handlers.go @@ -20,7 +20,7 @@ func (bp *Processor) handleLock(ctx context.Context, ev event.Event) { // send an event to the worker pool err := processors.SubmitEvent(bp.pool, bp.metrics, "lock", func() bool { - return bp.processLock(&lock) + return bp.processLock(ctx, &lock) }) if err != nil { // there system can be moved into controlled degradation stage diff --git a/pkg/innerring/processors/balance/handlers_test.go b/pkg/innerring/processors/balance/handlers_test.go index 3ef4959cc8..0fd23d8abd 100644 --- a/pkg/innerring/processors/balance/handlers_test.go +++ b/pkg/innerring/processors/balance/handlers_test.go @@ -70,7 +70,7 @@ type testAlphabetState struct { isAlphabet bool } -func (s *testAlphabetState) IsAlphabet() bool { +func (s *testAlphabetState) IsAlphabet(context.Context) bool { return s.isAlphabet } @@ -84,7 +84,7 @@ type testFrostFSContractClient struct { chequeCalls int } -func (c *testFrostFSContractClient) Cheque(p frostfscontract.ChequePrm) error { +func (c *testFrostFSContractClient) Cheque(_ context.Context, p frostfscontract.ChequePrm) error { c.chequeCalls++ return nil } diff --git a/pkg/innerring/processors/balance/process_assets.go b/pkg/innerring/processors/balance/process_assets.go index ac6a1e4933..60475908ce 100644 --- a/pkg/innerring/processors/balance/process_assets.go +++ b/pkg/innerring/processors/balance/process_assets.go @@ -11,9 +11,9 @@ import ( // Process lock event by invoking Cheque method in main net to send assets // back to the withdraw issuer. -func (bp *Processor) processLock(lock *balanceEvent.Lock) bool { - if !bp.alphabetState.IsAlphabet() { - bp.log.Info(context.Background(), logs.BalanceNonAlphabetModeIgnoreBalanceLock) +func (bp *Processor) processLock(ctx context.Context, lock *balanceEvent.Lock) bool { + if !bp.alphabetState.IsAlphabet(ctx) { + bp.log.Info(ctx, logs.BalanceNonAlphabetModeIgnoreBalanceLock) return true } @@ -25,9 +25,9 @@ func (bp *Processor) processLock(lock *balanceEvent.Lock) bool { prm.SetLock(lock.LockAccount()) prm.SetHash(lock.TxHash()) - err := bp.frostfsClient.Cheque(prm) + err := bp.frostfsClient.Cheque(ctx, prm) if err != nil { - bp.log.Error(context.Background(), logs.BalanceCantSendLockAssetTx, zap.Error(err)) + bp.log.Error(ctx, logs.BalanceCantSendLockAssetTx, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/balance/processor.go b/pkg/innerring/processors/balance/processor.go index c4078461e6..e2f649600f 100644 --- a/pkg/innerring/processors/balance/processor.go +++ b/pkg/innerring/processors/balance/processor.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" frostfscontract "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/frostfs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" @@ -13,13 +12,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" - "go.uber.org/zap" ) type ( // AlphabetState is a callback interface for inner ring global state. AlphabetState interface { - IsAlphabet() bool + IsAlphabet(context.Context) bool } // PrecisionConverter converts balance amount values. @@ -28,7 +26,7 @@ type ( } FrostFSClient interface { - Cheque(p frostfscontract.ChequePrm) error + Cheque(ctx context.Context, p frostfscontract.ChequePrm) error } // Processor of events produced by balance contract in the morphchain. @@ -69,8 +67,6 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/balance: balance precision converter is not set") } - p.Log.Debug(context.Background(), logs.BalanceBalanceWorkerPool, zap.Int("size", p.PoolSize)) - pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { return nil, fmt.Errorf("ir/balance: can't create worker pool: %w", err) diff --git a/pkg/innerring/processors/container/handlers.go b/pkg/innerring/processors/container/handlers.go index 45cac513ad..bb038a3cbf 100644 --- a/pkg/innerring/processors/container/handlers.go +++ b/pkg/innerring/processors/container/handlers.go @@ -23,7 +23,7 @@ func (cp *Processor) handlePut(ctx context.Context, ev event.Event) { // send an event to the worker pool err := processors.SubmitEvent(cp.pool, cp.metrics, "container_put", func() bool { - return cp.processContainerPut(put) + return cp.processContainerPut(ctx, put) }) if err != nil { // there system can be moved into controlled degradation stage @@ -41,7 +41,7 @@ func (cp *Processor) handleDelete(ctx context.Context, ev event.Event) { // send an event to the worker pool err := processors.SubmitEvent(cp.pool, cp.metrics, "container_delete", func() bool { - return cp.processContainerDelete(del) + return cp.processContainerDelete(ctx, del) }) if err != nil { // there system can be moved into controlled degradation stage diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index a2fe50fa8d..f28e5372a8 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -161,7 +161,7 @@ type testAlphabetState struct { isAlphabet bool } -func (s *testAlphabetState) IsAlphabet() bool { +func (s *testAlphabetState) IsAlphabet(context.Context) bool { return s.isAlphabet } diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index 2b9c5995c1..16c450166b 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -37,27 +37,27 @@ var errContainerAndOwnerNamespaceDontMatch = errors.New("container and owner nam // Process a new container from the user by checking the container sanity // and sending approve tx back to the morph. -func (cp *Processor) processContainerPut(put putEvent) bool { - if !cp.alphabetState.IsAlphabet() { - cp.log.Info(context.Background(), logs.ContainerNonAlphabetModeIgnoreContainerPut) +func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool { + if !cp.alphabetState.IsAlphabet(ctx) { + cp.log.Info(ctx, logs.ContainerNonAlphabetModeIgnoreContainerPut) return true } - ctx := &putContainerContext{ + pctx := &putContainerContext{ e: put, } - err := cp.checkPutContainer(ctx) + err := cp.checkPutContainer(pctx) if err != nil { - cp.log.Error(context.Background(), logs.ContainerPutContainerCheckFailed, + cp.log.Error(ctx, logs.ContainerPutContainerCheckFailed, zap.String("error", err.Error()), ) return false } - if err := cp.morphClient.NotarySignAndInvokeTX(ctx.e.NotaryRequest().MainTransaction); err != nil { - cp.log.Error(context.Background(), logs.ContainerCouldNotApprovePutContainer, + if err := cp.morphClient.NotarySignAndInvokeTX(pctx.e.NotaryRequest().MainTransaction); err != nil { + cp.log.Error(ctx, logs.ContainerCouldNotApprovePutContainer, zap.String("error", err.Error()), ) return false @@ -104,15 +104,15 @@ func (cp *Processor) checkPutContainer(ctx *putContainerContext) error { // Process delete container operation from the user by checking container sanity // and sending approve tx back to morph. -func (cp *Processor) processContainerDelete(e containerEvent.Delete) bool { - if !cp.alphabetState.IsAlphabet() { - cp.log.Info(context.Background(), logs.ContainerNonAlphabetModeIgnoreContainerDelete) +func (cp *Processor) processContainerDelete(ctx context.Context, e containerEvent.Delete) bool { + if !cp.alphabetState.IsAlphabet(ctx) { + cp.log.Info(ctx, logs.ContainerNonAlphabetModeIgnoreContainerDelete) return true } err := cp.checkDeleteContainer(e) if err != nil { - cp.log.Error(context.Background(), logs.ContainerDeleteContainerCheckFailed, + cp.log.Error(ctx, logs.ContainerDeleteContainerCheckFailed, zap.String("error", err.Error()), ) @@ -120,7 +120,7 @@ func (cp *Processor) processContainerDelete(e containerEvent.Delete) bool { } if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil { - cp.log.Error(context.Background(), logs.ContainerCouldNotApproveDeleteContainer, + cp.log.Error(ctx, logs.ContainerCouldNotApproveDeleteContainer, zap.String("error", err.Error()), ) diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index 7a50ca7733..58b90457c7 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -6,7 +6,6 @@ import ( "fmt" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" @@ -16,13 +15,12 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" - "go.uber.org/zap" ) type ( // AlphabetState is a callback interface for inner ring global state. AlphabetState interface { - IsAlphabet() bool + IsAlphabet(context.Context) bool } ContClient interface { @@ -98,8 +96,6 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/container: FrostFSID client is not set") } - p.Log.Debug(context.Background(), logs.ContainerContainerWorkerPool, zap.Int("size", p.PoolSize)) - pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { return nil, fmt.Errorf("ir/container: can't create worker pool: %w", err) diff --git a/pkg/innerring/processors/frostfs/handlers.go b/pkg/innerring/processors/frostfs/handlers.go index d11ad0f5c7..936de2e774 100644 --- a/pkg/innerring/processors/frostfs/handlers.go +++ b/pkg/innerring/processors/frostfs/handlers.go @@ -24,7 +24,7 @@ func (np *Processor) handleDeposit(ctx context.Context, ev event.Event) { // send event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_deposit", func() bool { - return np.processDeposit(deposit) + return np.processDeposit(ctx, deposit) }) if err != nil { // there system can be moved into controlled degradation stage @@ -44,7 +44,7 @@ func (np *Processor) handleWithdraw(ctx context.Context, ev event.Event) { // send event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_withdraw", func() bool { - return np.processWithdraw(withdraw) + return np.processWithdraw(ctx, withdraw) }) if err != nil { // there system can be moved into controlled degradation stage @@ -62,7 +62,7 @@ func (np *Processor) handleCheque(ctx context.Context, ev event.Event) { // send event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_cheque", func() bool { - return np.processCheque(cheque) + return np.processCheque(ctx, cheque) }) if err != nil { // there system can be moved into controlled degradation stage @@ -81,7 +81,7 @@ func (np *Processor) handleConfig(ctx context.Context, ev event.Event) { // send event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "frostfs_config", func() bool { - return np.processConfig(cfg) + return np.processConfig(ctx, cfg) }) if err != nil { // there system can be moved into controlled degradation stage diff --git a/pkg/innerring/processors/frostfs/handlers_test.go b/pkg/innerring/processors/frostfs/handlers_test.go index c1541ca40b..72310f6f9e 100644 --- a/pkg/innerring/processors/frostfs/handlers_test.go +++ b/pkg/innerring/processors/frostfs/handlers_test.go @@ -226,7 +226,7 @@ type testAlphabetState struct { isAlphabet bool } -func (s *testAlphabetState) IsAlphabet() bool { +func (s *testAlphabetState) IsAlphabet(context.Context) bool { return s.isAlphabet } @@ -242,17 +242,17 @@ type testBalaceClient struct { burn []balance.BurnPrm } -func (c *testBalaceClient) Mint(p balance.MintPrm) error { +func (c *testBalaceClient) Mint(_ context.Context, p balance.MintPrm) error { c.mint = append(c.mint, p) return nil } -func (c *testBalaceClient) Lock(p balance.LockPrm) error { +func (c *testBalaceClient) Lock(_ context.Context, p balance.LockPrm) error { c.lock = append(c.lock, p) return nil } -func (c *testBalaceClient) Burn(p balance.BurnPrm) error { +func (c *testBalaceClient) Burn(_ context.Context, p balance.BurnPrm) error { c.burn = append(c.burn, p) return nil } @@ -261,7 +261,7 @@ type testNetmapClient struct { config []nmClient.SetConfigPrm } -func (c *testNetmapClient) SetConfig(p nmClient.SetConfigPrm) error { +func (c *testNetmapClient) SetConfig(_ context.Context, p nmClient.SetConfigPrm) error { c.config = append(c.config, p) return nil } diff --git a/pkg/innerring/processors/frostfs/process_assets.go b/pkg/innerring/processors/frostfs/process_assets.go index 3bee6ed96b..ee824ea317 100644 --- a/pkg/innerring/processors/frostfs/process_assets.go +++ b/pkg/innerring/processors/frostfs/process_assets.go @@ -17,9 +17,9 @@ const ( // Process deposit event by invoking a balance contract and sending native // gas in the sidechain. -func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { - if !np.alphabetState.IsAlphabet() { - np.log.Info(context.Background(), logs.FrostFSNonAlphabetModeIgnoreDeposit) +func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.Deposit) bool { + if !np.alphabetState.IsAlphabet(ctx) { + np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreDeposit) return true } @@ -30,9 +30,9 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { prm.SetID(deposit.ID()) // send transferX to a balance contract - err := np.balanceClient.Mint(prm) + err := np.balanceClient.Mint(ctx, prm) if err != nil { - np.log.Error(context.Background(), logs.FrostFSCantTransferAssetsToBalanceContract, zap.Error(err)) + np.log.Error(ctx, logs.FrostFSCantTransferAssetsToBalanceContract, zap.Error(err)) } curEpoch := np.epochState.EpochCounter() @@ -46,7 +46,7 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { val, ok := np.mintEmitCache.Get(receiver.String()) if ok && val+np.mintEmitThreshold >= curEpoch { - np.log.Warn(context.Background(), logs.FrostFSDoubleMintEmissionDeclined, + np.log.Warn(ctx, logs.FrostFSDoubleMintEmissionDeclined, zap.Stringer("receiver", receiver), zap.Uint64("last_emission", val), zap.Uint64("current_epoch", curEpoch)) @@ -58,12 +58,12 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { // before gas transfer check if the balance is greater than the threshold balance, err := np.morphClient.GasBalance() if err != nil { - np.log.Error(context.Background(), logs.FrostFSCantGetGasBalanceOfTheNode, zap.Error(err)) + np.log.Error(ctx, logs.FrostFSCantGetGasBalanceOfTheNode, zap.Error(err)) return false } if balance < np.gasBalanceThreshold { - np.log.Warn(context.Background(), logs.FrostFSGasBalanceThresholdHasBeenReached, + np.log.Warn(ctx, logs.FrostFSGasBalanceThresholdHasBeenReached, zap.Int64("balance", balance), zap.Int64("threshold", np.gasBalanceThreshold)) @@ -72,7 +72,7 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { err = np.morphClient.TransferGas(receiver, np.mintEmitValue) if err != nil { - np.log.Error(context.Background(), logs.FrostFSCantTransferNativeGasToReceiver, + np.log.Error(ctx, logs.FrostFSCantTransferNativeGasToReceiver, zap.String("error", err.Error())) return false @@ -84,16 +84,16 @@ func (np *Processor) processDeposit(deposit frostfsEvent.Deposit) bool { } // Process withdraw event by locking assets in the balance account. -func (np *Processor) processWithdraw(withdraw frostfsEvent.Withdraw) bool { - if !np.alphabetState.IsAlphabet() { - np.log.Info(context.Background(), logs.FrostFSNonAlphabetModeIgnoreWithdraw) +func (np *Processor) processWithdraw(ctx context.Context, withdraw frostfsEvent.Withdraw) bool { + if !np.alphabetState.IsAlphabet(ctx) { + np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreWithdraw) return true } // create lock account lock, err := util.Uint160DecodeBytesBE(withdraw.ID()[:util.Uint160Size]) if err != nil { - np.log.Error(context.Background(), logs.FrostFSCantCreateLockAccount, zap.Error(err)) + np.log.Error(ctx, logs.FrostFSCantCreateLockAccount, zap.Error(err)) return false } @@ -107,9 +107,9 @@ func (np *Processor) processWithdraw(withdraw frostfsEvent.Withdraw) bool { prm.SetAmount(np.converter.ToBalancePrecision(withdraw.Amount())) prm.SetDueEpoch(int64(curEpoch + lockAccountLifetime)) - err = np.balanceClient.Lock(prm) + err = np.balanceClient.Lock(ctx, prm) if err != nil { - np.log.Error(context.Background(), logs.FrostFSCantLockAssetsForWithdraw, zap.Error(err)) + np.log.Error(ctx, logs.FrostFSCantLockAssetsForWithdraw, zap.Error(err)) return false } @@ -118,9 +118,9 @@ func (np *Processor) processWithdraw(withdraw frostfsEvent.Withdraw) bool { // Process cheque event by transferring assets from the lock account back to // the reserve account. -func (np *Processor) processCheque(cheque frostfsEvent.Cheque) bool { - if !np.alphabetState.IsAlphabet() { - np.log.Info(context.Background(), logs.FrostFSNonAlphabetModeIgnoreCheque) +func (np *Processor) processCheque(ctx context.Context, cheque frostfsEvent.Cheque) bool { + if !np.alphabetState.IsAlphabet(ctx) { + np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreCheque) return true } @@ -130,9 +130,9 @@ func (np *Processor) processCheque(cheque frostfsEvent.Cheque) bool { prm.SetAmount(np.converter.ToBalancePrecision(cheque.Amount())) prm.SetID(cheque.ID()) - err := np.balanceClient.Burn(prm) + err := np.balanceClient.Burn(ctx, prm) if err != nil { - np.log.Error(context.Background(), logs.FrostFSCantTransferAssetsToFedContract, zap.Error(err)) + np.log.Error(ctx, logs.FrostFSCantTransferAssetsToFedContract, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/frostfs/process_config.go b/pkg/innerring/processors/frostfs/process_config.go index 814dd40b4f..dc579f6bb5 100644 --- a/pkg/innerring/processors/frostfs/process_config.go +++ b/pkg/innerring/processors/frostfs/process_config.go @@ -11,9 +11,9 @@ import ( // Process config event by setting configuration value from the mainchain in // the sidechain. -func (np *Processor) processConfig(config frostfsEvent.Config) bool { - if !np.alphabetState.IsAlphabet() { - np.log.Info(context.Background(), logs.FrostFSNonAlphabetModeIgnoreConfig) +func (np *Processor) processConfig(ctx context.Context, config frostfsEvent.Config) bool { + if !np.alphabetState.IsAlphabet(ctx) { + np.log.Info(ctx, logs.FrostFSNonAlphabetModeIgnoreConfig) return true } @@ -24,9 +24,9 @@ func (np *Processor) processConfig(config frostfsEvent.Config) bool { prm.SetValue(config.Value()) prm.SetHash(config.TxHash()) - err := np.netmapClient.SetConfig(prm) + err := np.netmapClient.SetConfig(ctx, prm) if err != nil { - np.log.Error(context.Background(), logs.FrostFSCantRelaySetConfigEvent, zap.Error(err)) + np.log.Error(ctx, logs.FrostFSCantRelaySetConfigEvent, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/frostfs/processor.go b/pkg/innerring/processors/frostfs/processor.go index fdc31d82e5..6c29d330d9 100644 --- a/pkg/innerring/processors/frostfs/processor.go +++ b/pkg/innerring/processors/frostfs/processor.go @@ -6,7 +6,6 @@ import ( "fmt" "sync" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/balance" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" @@ -17,7 +16,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" - "go.uber.org/zap" ) type ( @@ -28,7 +26,7 @@ type ( // AlphabetState is a callback interface for inner ring global state. AlphabetState interface { - IsAlphabet() bool + IsAlphabet(context.Context) bool } // PrecisionConverter converts balance amount values. @@ -37,13 +35,13 @@ type ( } BalanceClient interface { - Mint(p balance.MintPrm) error - Lock(p balance.LockPrm) error - Burn(p balance.BurnPrm) error + Mint(ctx context.Context, p balance.MintPrm) error + Lock(ctx context.Context, p balance.LockPrm) error + Burn(ctx context.Context, p balance.BurnPrm) error } NetmapClient interface { - SetConfig(p nmClient.SetConfigPrm) error + SetConfig(ctx context.Context, p nmClient.SetConfigPrm) error } MorphClient interface { @@ -111,8 +109,6 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/frostfs: balance precision converter is not set") } - p.Log.Debug(context.Background(), logs.FrostFSFrostfsWorkerPool, zap.Int("size", p.PoolSize)) - pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { return nil, fmt.Errorf("ir/frostfs: can't create worker pool: %w", err) diff --git a/pkg/innerring/processors/governance/handlers_test.go b/pkg/innerring/processors/governance/handlers_test.go index 286935129b..5a6126249d 100644 --- a/pkg/innerring/processors/governance/handlers_test.go +++ b/pkg/innerring/processors/governance/handlers_test.go @@ -219,7 +219,7 @@ type testAlphabetState struct { isAlphabet bool } -func (s *testAlphabetState) IsAlphabet() bool { +func (s *testAlphabetState) IsAlphabet(context.Context) bool { return s.isAlphabet } @@ -251,12 +251,12 @@ func (c *testMorphClient) Committee() (res keys.PublicKeys, err error) { return c.commiteeKeys, nil } -func (c *testMorphClient) UpdateNeoFSAlphabetList(prm client.UpdateAlphabetListPrm) error { +func (c *testMorphClient) UpdateNeoFSAlphabetList(_ context.Context, prm client.UpdateAlphabetListPrm) error { c.alphabetUpdates = append(c.alphabetUpdates, prm) return nil } -func (c *testMorphClient) UpdateNotaryList(prm client.UpdateNotaryListPrm) error { +func (c *testMorphClient) UpdateNotaryList(_ context.Context, prm client.UpdateNotaryListPrm) error { c.notaryUpdates = append(c.notaryUpdates, prm) return nil } @@ -278,7 +278,7 @@ type testFrostFSClient struct { updates []frostfscontract.AlphabetUpdatePrm } -func (c *testFrostFSClient) AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) error { +func (c *testFrostFSClient) AlphabetUpdate(_ context.Context, p frostfscontract.AlphabetUpdatePrm) error { c.updates = append(c.updates, p) return nil } diff --git a/pkg/innerring/processors/governance/process_update.go b/pkg/innerring/processors/governance/process_update.go index fdfdfa4791..73d21a7d28 100644 --- a/pkg/innerring/processors/governance/process_update.go +++ b/pkg/innerring/processors/governance/process_update.go @@ -20,7 +20,7 @@ const ( ) func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint256) bool { - if !gp.alphabetState.IsAlphabet() { + if !gp.alphabetState.IsAlphabet(ctx) { gp.log.Info(ctx, logs.GovernanceNonAlphabetModeIgnoreAlphabetSync) return true } @@ -69,13 +69,13 @@ func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint25 } // 2. Update NeoFSAlphabet role in the sidechain. - gp.updateNeoFSAlphabetRoleInSidechain(sidechainAlphabet, newAlphabet, txHash) + gp.updateNeoFSAlphabetRoleInSidechain(ctx, sidechainAlphabet, newAlphabet, txHash) // 3. Update notary role in the sidechain. - gp.updateNotaryRoleInSidechain(newAlphabet, txHash) + gp.updateNotaryRoleInSidechain(ctx, newAlphabet, txHash) // 4. Update FrostFS contract in the mainnet. - gp.updateFrostFSContractInMainnet(newAlphabet) + gp.updateFrostFSContractInMainnet(ctx, newAlphabet) gp.log.Info(ctx, logs.GovernanceFinishedAlphabetListUpdate) @@ -94,24 +94,24 @@ func prettyKeys(keys keys.PublicKeys) string { return strings.TrimRight(sb.String(), delimiter) } -func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(sidechainAlphabet, newAlphabet keys.PublicKeys, txHash util.Uint256) { +func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(ctx context.Context, sidechainAlphabet, newAlphabet keys.PublicKeys, txHash util.Uint256) { innerRing, err := gp.irFetcher.InnerRingKeys() if err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantFetchInnerRingListFromSideChain, + gp.log.Error(ctx, logs.GovernanceCantFetchInnerRingListFromSideChain, zap.String("error", err.Error())) return } newInnerRing, err := updateInnerRing(innerRing, sidechainAlphabet, newAlphabet) if err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys, + gp.log.Error(ctx, logs.GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys, zap.String("error", err.Error())) return } sort.Sort(newInnerRing) - gp.log.Info(context.Background(), logs.GovernanceUpdateOfTheInnerRingList, + gp.log.Info(ctx, logs.GovernanceUpdateOfTheInnerRingList, zap.String("before", prettyKeys(innerRing)), zap.String("after", prettyKeys(newInnerRing)), ) @@ -120,26 +120,26 @@ func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(sidechainAlphabet, newAl updPrm.SetList(newInnerRing) updPrm.SetHash(txHash) - if err = gp.morphClient.UpdateNeoFSAlphabetList(updPrm); err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantUpdateInnerRingListWithNewAlphabetKeys, + if err = gp.morphClient.UpdateNeoFSAlphabetList(ctx, updPrm); err != nil { + gp.log.Error(ctx, logs.GovernanceCantUpdateInnerRingListWithNewAlphabetKeys, zap.String("error", err.Error())) } } -func (gp *Processor) updateNotaryRoleInSidechain(newAlphabet keys.PublicKeys, txHash util.Uint256) { +func (gp *Processor) updateNotaryRoleInSidechain(ctx context.Context, newAlphabet keys.PublicKeys, txHash util.Uint256) { updPrm := client.UpdateNotaryListPrm{} updPrm.SetList(newAlphabet) updPrm.SetHash(txHash) - err := gp.morphClient.UpdateNotaryList(updPrm) + err := gp.morphClient.UpdateNotaryList(ctx, updPrm) if err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantUpdateListOfNotaryNodesInSideChain, + gp.log.Error(ctx, logs.GovernanceCantUpdateListOfNotaryNodesInSideChain, zap.String("error", err.Error())) } } -func (gp *Processor) updateFrostFSContractInMainnet(newAlphabet keys.PublicKeys) { +func (gp *Processor) updateFrostFSContractInMainnet(ctx context.Context, newAlphabet keys.PublicKeys) { epoch := gp.epochState.EpochCounter() buf := make([]byte, 8) @@ -152,9 +152,9 @@ func (gp *Processor) updateFrostFSContractInMainnet(newAlphabet keys.PublicKeys) prm.SetID(id) prm.SetPubs(newAlphabet) - err := gp.frostfsClient.AlphabetUpdate(prm) + err := gp.frostfsClient.AlphabetUpdate(ctx, prm) if err != nil { - gp.log.Error(context.Background(), logs.GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract, + gp.log.Error(ctx, logs.GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract, zap.String("error", err.Error())) } } diff --git a/pkg/innerring/processors/governance/processor.go b/pkg/innerring/processors/governance/processor.go index eaadfdb4fd..565f4c27d8 100644 --- a/pkg/innerring/processors/governance/processor.go +++ b/pkg/innerring/processors/governance/processor.go @@ -26,7 +26,7 @@ const ProcessorPoolSize = 1 type ( // AlphabetState is a callback interface for innerring global state. AlphabetState interface { - IsAlphabet() bool + IsAlphabet(context.Context) bool } ) @@ -56,7 +56,7 @@ type ( } FrostFSClient interface { - AlphabetUpdate(p frostfscontract.AlphabetUpdatePrm) error + AlphabetUpdate(ctx context.Context, p frostfscontract.AlphabetUpdatePrm) error } NetmapClient interface { @@ -70,8 +70,8 @@ type ( MorphClient interface { Committee() (res keys.PublicKeys, err error) - UpdateNeoFSAlphabetList(prm client.UpdateAlphabetListPrm) error - UpdateNotaryList(prm client.UpdateNotaryListPrm) error + UpdateNeoFSAlphabetList(ctx context.Context, prm client.UpdateAlphabetListPrm) error + UpdateNotaryList(ctx context.Context, prm client.UpdateNotaryListPrm) error } // Processor of events related to governance in the network. diff --git a/pkg/innerring/processors/netmap/handlers.go b/pkg/innerring/processors/netmap/handlers.go index 61547e0bad..4c7199a49f 100644 --- a/pkg/innerring/processors/netmap/handlers.go +++ b/pkg/innerring/processors/netmap/handlers.go @@ -14,14 +14,14 @@ import ( func (np *Processor) HandleNewEpochTick(ctx context.Context, ev event.Event) { _ = ev.(timerEvent.NewEpochTick) - np.log.Info(context.Background(), logs.NetmapTick, zap.String("type", "epoch")) + np.log.Info(ctx, logs.NetmapTick, zap.String("type", "epoch")) // send an event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "netmap_new_epoch_tick", func() bool { return np.processNewEpochTick(ctx) }) if err != nil { // there system can be moved into controlled degradation stage - np.log.Warn(context.Background(), logs.NetmapNetmapWorkerPoolDrained, + np.log.Warn(ctx, logs.NetmapNetmapWorkerPoolDrained, zap.Int("capacity", np.pool.Cap())) } } @@ -54,7 +54,7 @@ func (np *Processor) handleAddPeer(ctx context.Context, ev event.Event) { // send an event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "netmap_add_peer", func() bool { - return np.processAddPeer(newPeer) + return np.processAddPeer(ctx, newPeer) }) if err != nil { // there system can be moved into controlled degradation stage @@ -72,7 +72,7 @@ func (np *Processor) handleUpdateState(ctx context.Context, ev event.Event) { // send event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "netmap_update_peer", func() bool { - return np.processUpdatePeer(updPeer) + return np.processUpdatePeer(ctx, updPeer) }) if err != nil { // there system can be moved into controlled degradation stage @@ -94,7 +94,7 @@ func (np *Processor) handleCleanupTick(ctx context.Context, ev event.Event) { // send event to the worker pool err := processors.SubmitEvent(np.pool, np.metrics, "netmap_cleanup_tick", func() bool { - return np.processNetmapCleanupTick(cleanup) + return np.processNetmapCleanupTick(ctx, cleanup) }) if err != nil { // there system can be moved into controlled degradation stage diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index 1e8be40950..5a5adfb2dc 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -341,7 +341,7 @@ type testAlphabetState struct { isAlphabet bool } -func (s *testAlphabetState) IsAlphabet() bool { +func (s *testAlphabetState) IsAlphabet(context.Context) bool { return s.isAlphabet } @@ -365,7 +365,7 @@ type testNetmapClient struct { invokedTxs []*transaction.Transaction } -func (c *testNetmapClient) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { +func (c *testNetmapClient) MorphNotaryInvoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { c.notaryInvokes = append(c.notaryInvokes, notaryInvoke{ contract: contract, fee: fee, @@ -396,7 +396,7 @@ func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) { return c.netmap, nil } -func (c *testNetmapClient) NewEpoch(epoch uint64) error { +func (c *testNetmapClient) NewEpoch(_ context.Context, epoch uint64) error { c.newEpochs = append(c.newEpochs, epoch) return nil } diff --git a/pkg/innerring/processors/netmap/process_cleanup.go b/pkg/innerring/processors/netmap/process_cleanup.go index 9529d3a0ce..a43005ffbe 100644 --- a/pkg/innerring/processors/netmap/process_cleanup.go +++ b/pkg/innerring/processors/netmap/process_cleanup.go @@ -9,9 +9,9 @@ import ( "go.uber.org/zap" ) -func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) bool { - if !np.alphabetState.IsAlphabet() { - np.log.Info(context.Background(), logs.NetmapNonAlphabetModeIgnoreNewNetmapCleanupTick) +func (np *Processor) processNetmapCleanupTick(ctx context.Context, ev netmapCleanupTick) bool { + if !np.alphabetState.IsAlphabet(ctx) { + np.log.Info(ctx, logs.NetmapNonAlphabetModeIgnoreNewNetmapCleanupTick) return true } @@ -19,13 +19,13 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) bool { err := np.netmapSnapshot.forEachRemoveCandidate(ev.epoch, func(s string) error { key, err := keys.NewPublicKeyFromString(s) if err != nil { - np.log.Warn(context.Background(), logs.NetmapCantDecodePublicKeyOfNetmapNode, + np.log.Warn(ctx, logs.NetmapCantDecodePublicKeyOfNetmapNode, zap.String("key", s)) return nil } - np.log.Info(context.Background(), logs.NetmapVoteToRemoveNodeFromNetmap, zap.String("key", s)) + np.log.Info(ctx, logs.NetmapVoteToRemoveNodeFromNetmap, zap.String("key", s)) // In notary environments we call UpdateStateIR method instead of UpdateState. // It differs from UpdateState only by name, so we can do this in the same form. @@ -33,6 +33,7 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) bool { const methodUpdateStateNotary = "updateStateIR" err = np.netmapClient.MorphNotaryInvoke( + ctx, np.netmapClient.ContractAddress(), 0, uint32(ev.epoch), @@ -41,13 +42,13 @@ func (np *Processor) processNetmapCleanupTick(ev netmapCleanupTick) bool { int64(v2netmap.Offline), key.Bytes(), ) if err != nil { - np.log.Error(context.Background(), logs.NetmapCantInvokeNetmapUpdateState, zap.Error(err)) + np.log.Error(ctx, logs.NetmapCantInvokeNetmapUpdateState, zap.Error(err)) } return nil }) if err != nil { - np.log.Warn(context.Background(), logs.NetmapCantIterateOnNetmapCleanerCache, + np.log.Warn(ctx, logs.NetmapCantIterateOnNetmapCleanerCache, zap.String("error", err.Error())) return false } diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index e401ef4f2b..237c4e512a 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -55,7 +55,7 @@ func (np *Processor) processNewEpoch(ctx context.Context, ev netmapEvent.NewEpoc // Process new epoch tick by invoking new epoch method in network map contract. func (np *Processor) processNewEpochTick(ctx context.Context) bool { - if !np.alphabetState.IsAlphabet() { + if !np.alphabetState.IsAlphabet(ctx) { np.log.Info(ctx, logs.NetmapNonAlphabetModeIgnoreNewEpochTick) return true } @@ -63,7 +63,7 @@ func (np *Processor) processNewEpochTick(ctx context.Context) bool { nextEpoch := np.epochState.EpochCounter() + 1 np.log.Debug(ctx, logs.NetmapNextEpoch, zap.Uint64("value", nextEpoch)) - err := np.netmapClient.NewEpoch(nextEpoch) + err := np.netmapClient.NewEpoch(ctx, nextEpoch) if err != nil { np.log.Error(ctx, logs.NetmapCantInvokeNetmapNewEpoch, zap.Error(err)) return false diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index 42d1b5ec6f..72aa08f768 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -13,9 +13,9 @@ import ( // Process add peer notification by sanity check of new node // local epoch timer. -func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { - if !np.alphabetState.IsAlphabet() { - np.log.Info(context.Background(), logs.NetmapNonAlphabetModeIgnoreNewPeerNotification) +func (np *Processor) processAddPeer(ctx context.Context, ev netmapEvent.AddPeer) bool { + if !np.alphabetState.IsAlphabet(ctx) { + np.log.Info(ctx, logs.NetmapNonAlphabetModeIgnoreNewPeerNotification) return true } @@ -23,7 +23,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { tx := ev.NotaryRequest().MainTransaction ok, err := np.netmapClient.MorphIsValidScript(tx.Script, tx.Signers) if err != nil || !ok { - np.log.Warn(context.Background(), logs.NetmapNonhaltNotaryTransaction, + np.log.Warn(ctx, logs.NetmapNonhaltNotaryTransaction, zap.String("method", "netmap.AddPeer"), zap.String("hash", tx.Hash().StringLE()), zap.Error(err)) @@ -34,14 +34,14 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { var nodeInfo netmap.NodeInfo if err := nodeInfo.Unmarshal(ev.Node()); err != nil { // it will be nice to have tx id at event structure to log it - np.log.Warn(context.Background(), logs.NetmapCantParseNetworkMapCandidate) + np.log.Warn(ctx, logs.NetmapCantParseNetworkMapCandidate) return false } // validate and update node info err = np.nodeValidator.VerifyAndUpdate(&nodeInfo) if err != nil { - np.log.Warn(context.Background(), logs.NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate, + np.log.Warn(ctx, logs.NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate, zap.String("error", err.Error()), ) @@ -64,7 +64,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { // That is why we need to perform `addPeerIR` only in case when node is online, // because in scope of this method, contract set state `ONLINE` for the node. if updated && nodeInfo.Status().IsOnline() { - np.log.Info(context.Background(), logs.NetmapApprovingNetworkMapCandidate, + np.log.Info(ctx, logs.NetmapApprovingNetworkMapCandidate, zap.String("key", keyString)) prm := netmapclient.AddPeerPrm{} @@ -77,6 +77,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { // create new notary request with the original nonce err = np.netmapClient.MorphNotaryInvoke( + ctx, np.netmapClient.ContractAddress(), 0, ev.NotaryRequest().MainTransaction.Nonce, @@ -85,7 +86,7 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { nodeInfoBinary, ) if err != nil { - np.log.Error(context.Background(), logs.NetmapCantInvokeNetmapAddPeer, zap.Error(err)) + np.log.Error(ctx, logs.NetmapCantInvokeNetmapAddPeer, zap.Error(err)) return false } } @@ -94,9 +95,9 @@ func (np *Processor) processAddPeer(ev netmapEvent.AddPeer) bool { } // Process update peer notification by sending approval tx to the smart contract. -func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) bool { - if !np.alphabetState.IsAlphabet() { - np.log.Info(context.Background(), logs.NetmapNonAlphabetModeIgnoreUpdatePeerNotification) +func (np *Processor) processUpdatePeer(ctx context.Context, ev netmapEvent.UpdatePeer) bool { + if !np.alphabetState.IsAlphabet(ctx) { + np.log.Info(ctx, logs.NetmapNonAlphabetModeIgnoreUpdatePeerNotification) return true } @@ -109,7 +110,7 @@ func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) bool { if ev.Maintenance() { err = np.nodeStateSettings.MaintenanceModeAllowed() if err != nil { - np.log.Info(context.Background(), logs.NetmapPreventSwitchingNodeToMaintenanceState, + np.log.Info(ctx, logs.NetmapPreventSwitchingNodeToMaintenanceState, zap.Error(err), ) @@ -118,7 +119,7 @@ func (np *Processor) processUpdatePeer(ev netmapEvent.UpdatePeer) bool { } if err = np.netmapClient.MorphNotarySignAndInvokeTX(ev.NotaryRequest().MainTransaction); err != nil { - np.log.Error(context.Background(), logs.NetmapCantInvokeNetmapUpdatePeer, zap.Error(err)) + np.log.Error(ctx, logs.NetmapCantInvokeNetmapUpdatePeer, zap.Error(err)) return false } diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index bbd60c1e19..b3d57e85bd 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" @@ -17,7 +16,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/panjf2000/ants/v2" - "go.uber.org/zap" ) type ( @@ -36,7 +34,7 @@ type ( // AlphabetState is a callback interface for inner ring global state. AlphabetState interface { - IsAlphabet() bool + IsAlphabet(context.Context) bool } // NodeValidator wraps basic method of checking the correctness @@ -55,12 +53,12 @@ type ( } Client interface { - MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error + MorphNotaryInvoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error ContractAddress() util.Uint160 EpochDuration() (uint64, error) MorphTxHeight(h util.Uint256) (res uint32, err error) NetMap() (*netmap.NetMap, error) - NewEpoch(epoch uint64) error + NewEpoch(ctx context.Context, epoch uint64) error MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error } @@ -133,8 +131,6 @@ func New(p *Params) (*Processor, error) { return nil, errors.New("ir/netmap: node state settings is not set") } - p.Log.Debug(context.Background(), logs.NetmapNetmapWorkerPool, zap.Int("size", p.PoolSize)) - pool, err := ants.NewPool(p.PoolSize, ants.WithNonblocking(true)) if err != nil { return nil, fmt.Errorf("ir/netmap: can't create worker pool: %w", err) diff --git a/pkg/innerring/processors/netmap/wrappers.go b/pkg/innerring/processors/netmap/wrappers.go index e75fdaf403..9cd71ae487 100644 --- a/pkg/innerring/processors/netmap/wrappers.go +++ b/pkg/innerring/processors/netmap/wrappers.go @@ -1,6 +1,8 @@ package netmap import ( + "context" + netmapclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -18,13 +20,13 @@ type netmapClientWrapper struct { netmapClient *netmapclient.Client } -func (w *netmapClientWrapper) UpdatePeerState(p netmapclient.UpdatePeerPrm) error { - _, err := w.netmapClient.UpdatePeerState(p) +func (w *netmapClientWrapper) UpdatePeerState(ctx context.Context, p netmapclient.UpdatePeerPrm) error { + _, err := w.netmapClient.UpdatePeerState(ctx, p) return err } -func (w *netmapClientWrapper) MorphNotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { - _, err := w.netmapClient.Morph().NotaryInvoke(contract, fee, nonce, vub, method, args...) +func (w *netmapClientWrapper) MorphNotaryInvoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error { + _, err := w.netmapClient.Morph().NotaryInvoke(ctx, contract, fee, nonce, vub, method, args...) return err } @@ -44,16 +46,16 @@ func (w *netmapClientWrapper) NetMap() (*netmap.NetMap, error) { return w.netmapClient.NetMap() } -func (w *netmapClientWrapper) NewEpoch(epoch uint64) error { - return w.netmapClient.NewEpoch(epoch) +func (w *netmapClientWrapper) NewEpoch(ctx context.Context, epoch uint64) error { + return w.netmapClient.NewEpoch(ctx, epoch) } func (w *netmapClientWrapper) MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) { return w.netmapClient.Morph().IsValidScript(script, signers) } -func (w *netmapClientWrapper) AddPeer(p netmapclient.AddPeerPrm) error { - return w.netmapClient.AddPeer(p) +func (w *netmapClientWrapper) AddPeer(ctx context.Context, p netmapclient.AddPeerPrm) error { + return w.netmapClient.AddPeer(ctx, p) } func (w *netmapClientWrapper) MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error { diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index 85f332fb64..77c2af2ce3 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -53,8 +53,8 @@ func (s *Server) IsActive(ctx context.Context) bool { } // IsAlphabet is a getter for a global alphabet flag state. -func (s *Server) IsAlphabet() bool { - return s.AlphabetIndex() >= 0 +func (s *Server) IsAlphabet(ctx context.Context) bool { + return s.AlphabetIndex(ctx) >= 0 } // InnerRingIndex is a getter for a global index of node in inner ring list. Negative @@ -83,10 +83,10 @@ func (s *Server) InnerRingSize(ctx context.Context) int { // AlphabetIndex is a getter for a global index of node in alphabet list. // Negative index means that node is not in the alphabet list. -func (s *Server) AlphabetIndex() int { +func (s *Server) AlphabetIndex(ctx context.Context) int { index, err := s.statusIndex.AlphabetIndex() if err != nil { - s.log.Error(context.Background(), logs.InnerringCantGetAlphabetIndex, zap.String("error", err.Error())) + s.log.Error(ctx, logs.InnerringCantGetAlphabetIndex, zap.String("error", err.Error())) return -1 } @@ -127,7 +127,7 @@ func (s *Server) voteForSidechainValidator(ctx context.Context, prm governance.V } s.contracts.alphabet.iterate(func(letter GlagoliticLetter, contract util.Uint160) { - _, err := s.morphClient.NotaryInvoke(contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators) + _, err := s.morphClient.NotaryInvoke(ctx, contract, s.feeConfig.SideChainFee(), nonce, vubP, voteMethod, epoch, validators) if err != nil { s.log.Warn(ctx, logs.InnerringCantInvokeVoteMethodInAlphabetContract, zap.Int8("alphabet_index", int8(letter)), diff --git a/pkg/innerring/state_test.go b/pkg/innerring/state_test.go index 17ab995af7..f60ca87c45 100644 --- a/pkg/innerring/state_test.go +++ b/pkg/innerring/state_test.go @@ -47,8 +47,8 @@ func TestServerState(t *testing.T) { require.Equal(t, healthStatus, srv.HealthStatus(), "invalid health status") require.True(t, srv.IsActive(context.Background()), "invalid IsActive result") - require.True(t, srv.IsAlphabet(), "invalid IsAlphabet result") + require.True(t, srv.IsAlphabet(context.Background()), "invalid IsAlphabet result") require.Equal(t, 0, srv.InnerRingIndex(context.Background()), "invalid IR index") require.Equal(t, 1, srv.InnerRingSize(context.Background()), "invalid IR index") - require.Equal(t, 0, srv.AlphabetIndex(), "invalid alphabet index") + require.Equal(t, 0, srv.AlphabetIndex(context.Background()), "invalid alphabet index") } diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go index 10cb6f368c..95fdd844b4 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza_test.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza_test.go @@ -72,7 +72,7 @@ func TestBlobovnicza(t *testing.T) { require.NoError(t, blz.Open(context.Background())) // initialize Blobovnicza - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) // try to read non-existent address testGet(t, blz, oidtest.Address(), nil, client.IsErrObjectNotFound) @@ -102,5 +102,5 @@ func TestBlobovnicza(t *testing.T) { return err == nil }, nil) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) } diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index a317279a45..d0e71a8768 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -56,7 +56,7 @@ func (b *Blobovnicza) Open(ctx context.Context) error { // // If Blobovnicza is already initialized, no action is taken. // Blobovnicza must be open, otherwise an error will return. -func (b *Blobovnicza) Init() error { +func (b *Blobovnicza) Init(ctx context.Context) error { b.controlMtx.Lock() defer b.controlMtx.Unlock() @@ -64,7 +64,7 @@ func (b *Blobovnicza) Init() error { return errors.New("blobovnicza is not open") } - b.log.Debug(context.Background(), logs.BlobovniczaInitializing, + b.log.Debug(ctx, logs.BlobovniczaInitializing, zap.Uint64("object size limit", b.objSizeLimit), zap.Uint64("storage size limit", b.fullSizeLimit), ) @@ -72,7 +72,7 @@ func (b *Blobovnicza) Init() error { size := b.dataSize.Load() items := b.itemsCount.Load() if size != 0 || items != 0 { - b.log.Debug(context.Background(), logs.BlobovniczaAlreadyInitialized, zap.Uint64("size", size), zap.Uint64("items", items)) + b.log.Debug(ctx, logs.BlobovniczaAlreadyInitialized, zap.Uint64("size", size), zap.Uint64("items", items)) return nil } @@ -82,7 +82,7 @@ func (b *Blobovnicza) Init() error { // create size range bucket rangeStr := stringifyBounds(lower, upper) - b.log.Debug(context.Background(), logs.BlobovniczaCreatingBucketForSizeRange, + b.log.Debug(ctx, logs.BlobovniczaCreatingBucketForSizeRange, zap.String("range", rangeStr)) _, err := tx.CreateBucketIfNotExists(key) @@ -99,14 +99,14 @@ func (b *Blobovnicza) Init() error { } } - return b.initializeCounters() + return b.initializeCounters(ctx) } func (b *Blobovnicza) ObjectsCount() uint64 { return b.itemsCount.Load() } -func (b *Blobovnicza) initializeCounters() error { +func (b *Blobovnicza) initializeCounters(ctx context.Context) error { var size uint64 var items uint64 var sizeExists bool @@ -132,17 +132,17 @@ func (b *Blobovnicza) initializeCounters() error { return fmt.Errorf("can't determine DB size: %w", err) } if (!sizeExists || !itemsCountExists) && !b.boltOptions.ReadOnly { - b.log.Debug(context.Background(), logs.BlobovniczaSavingCountersToMeta, zap.Uint64("size", size), zap.Uint64("items", items)) + b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMeta, zap.Uint64("size", size), zap.Uint64("items", items)) if err := b.boltDB.Update(func(tx *bbolt.Tx) error { if err := saveDataSize(tx, size); err != nil { return err } return saveItemsCount(tx, items) }); err != nil { - b.log.Debug(context.Background(), logs.BlobovniczaSavingCountersToMetaFailed, zap.Uint64("size", size), zap.Uint64("items", items)) + b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMetaFailed, zap.Uint64("size", size), zap.Uint64("items", items)) return fmt.Errorf("can't save blobovnicza's size and items count: %w", err) } - b.log.Debug(context.Background(), logs.BlobovniczaSavingCountersToMetaSuccess, zap.Uint64("size", size), zap.Uint64("items", items)) + b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMetaSuccess, zap.Uint64("size", size), zap.Uint64("items", items)) } b.dataSize.Store(size) @@ -155,7 +155,7 @@ func (b *Blobovnicza) initializeCounters() error { // Close releases all internal database resources. // // If blobovnicza is already closed, does nothing. -func (b *Blobovnicza) Close() error { +func (b *Blobovnicza) Close(ctx context.Context) error { b.controlMtx.Lock() defer b.controlMtx.Unlock() @@ -163,7 +163,7 @@ func (b *Blobovnicza) Close() error { return nil } - b.log.Debug(context.Background(), logs.BlobovniczaClosingBoltDB, + b.log.Debug(ctx, logs.BlobovniczaClosingBoltDB, zap.String("path", b.path), ) diff --git a/pkg/local_object_storage/blobovnicza/get_test.go b/pkg/local_object_storage/blobovnicza/get_test.go index 8c435af897..5a382c1590 100644 --- a/pkg/local_object_storage/blobovnicza/get_test.go +++ b/pkg/local_object_storage/blobovnicza/get_test.go @@ -14,11 +14,11 @@ func TestBlobovnicza_Get(t *testing.T) { filename := filepath.Join(t.TempDir(), "blob") var blz *Blobovnicza - defer func() { require.NoError(t, blz.Close()) }() + defer func() { require.NoError(t, blz.Close(context.Background())) }() fnInit := func(szLimit uint64) { if blz != nil { - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) } blz = New( @@ -27,7 +27,7 @@ func TestBlobovnicza_Get(t *testing.T) { ) require.NoError(t, blz.Open(context.Background())) - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) } // initial distribution: [0:32K] (32K:64K] diff --git a/pkg/local_object_storage/blobovnicza/iterate_test.go b/pkg/local_object_storage/blobovnicza/iterate_test.go index bec23bb96a..7172747816 100644 --- a/pkg/local_object_storage/blobovnicza/iterate_test.go +++ b/pkg/local_object_storage/blobovnicza/iterate_test.go @@ -16,7 +16,7 @@ func TestBlobovniczaIterate(t *testing.T) { filename := filepath.Join(t.TempDir(), "blob") b := New(WithPath(filename)) require.NoError(t, b.Open(context.Background())) - require.NoError(t, b.Init()) + require.NoError(t, b.Init(context.Background())) data := [][]byte{{0, 1, 2, 3}, {5, 6, 7, 8}} addr := oidtest.Address() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/active.go b/pkg/local_object_storage/blobstor/blobovniczatree/active.go index 0ac15df827..dbaa7387a1 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/active.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/active.go @@ -18,8 +18,8 @@ func (db *activeDB) Blobovnicza() *blobovnicza.Blobovnicza { return db.blz } -func (db *activeDB) Close() { - db.shDB.Close() +func (db *activeDB) Close(ctx context.Context) { + db.shDB.Close(ctx) } func (db *activeDB) SystemPath() string { @@ -73,12 +73,12 @@ func (m *activeDBManager) Open() { m.closed = false } -func (m *activeDBManager) Close() { +func (m *activeDBManager) Close(ctx context.Context) { m.levelToActiveDBGuard.Lock() defer m.levelToActiveDBGuard.Unlock() for _, db := range m.levelToActiveDB { - db.Close() + db.Close(ctx) } m.levelToActiveDB = make(map[string]*sharedDB) m.closed = true @@ -103,7 +103,7 @@ func (m *activeDBManager) getCurrentActiveIfOk(ctx context.Context, lvlPath stri } if blz.IsFull() { - db.Close() + db.Close(ctx) return nil, nil } @@ -168,10 +168,10 @@ func (m *activeDBManager) getNextSharedDB(ctx context.Context, lvlPath string) ( previous, updated := m.replace(lvlPath, next) if !updated && next != nil { - next.Close() // manager is closed, so don't hold active DB open + next.Close(ctx) // manager is closed, so don't hold active DB open } if updated && previous != nil { - previous.Close() + previous.Close(ctx) } return next, nil } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index c909113c74..d9e99d0d13 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -167,7 +167,7 @@ func (b *Blobovniczas) Compressor() *compression.Config { } // SetReportErrorFunc implements common.Storage. -func (b *Blobovniczas) SetReportErrorFunc(f func(string, error)) { +func (b *Blobovniczas) SetReportErrorFunc(f func(context.Context, string, error)) { b.reportError = f } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go index e8016781ab..04ff5120c2 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/cache.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/cache.go @@ -32,7 +32,7 @@ func newDBCache(parentCtx context.Context, size int, ch := cache.NewCache[string, *sharedDB](). WithTTL(ttl).WithLRU().WithMaxKeys(size). WithOnEvicted(func(_ string, db *sharedDB) { - db.Close() + db.Close(parentCtx) }) ctx, cancel := context.WithCancel(parentCtx) res := &dbCache{ @@ -138,7 +138,7 @@ func (c *dbCache) create(ctx context.Context, path string) *sharedDB { return value } if added := c.put(path, value); !added { - value.Close() + value.Close(ctx) } return value } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go index cc8a52d036..ec9743b57b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -27,7 +27,7 @@ func TestBlobovniczaTree_Concurrency(t *testing.T) { require.NoError(t, st.Open(mode.ComponentReadWrite)) require.NoError(t, st.Init()) defer func() { - require.NoError(t, st.Close()) + require.NoError(t, st.Close(context.Background())) }() objGen := &testutil.SeqObjGenerator{ObjSize: 1} diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index 7c0a9edd61..c77df63bf6 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -50,7 +50,7 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { if err != nil { return err } - defer shBlz.Close() + defer shBlz.Close(egCtx) moveInfo, err := blz.ListMoveInfo(egCtx) if err != nil { @@ -80,9 +80,9 @@ func (b *Blobovniczas) openManagers() { } // Close implements common.Storage. -func (b *Blobovniczas) Close() error { +func (b *Blobovniczas) Close(ctx context.Context) error { b.dbCache.Close() // order important - b.activeDBManager.Close() + b.activeDBManager.Close(ctx) b.commondbManager.Close() return nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go index f0a32ded14..b26323bd0d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go @@ -51,7 +51,7 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { require.NoError(t, err) require.EqualValues(t, obj35, gRes.Object) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) // change depth and width blz = NewBlobovniczaTree( @@ -89,7 +89,7 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { }) require.NoError(t, err) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) // change depth and width back blz = NewBlobovniczaTree( @@ -127,5 +127,5 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { require.NoError(t, err) require.EqualValues(t, obj52, gRes.Object) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/count.go b/pkg/local_object_storage/blobstor/blobovniczatree/count.go index 1137b9eb2e..b83849c775 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/count.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/count.go @@ -26,7 +26,7 @@ func (b *Blobovniczas) ObjectsCount(ctx context.Context) (uint64, error) { if err != nil { return true, err } - defer shDB.Close() + defer shDB.Close(ctx) result += blz.ObjectsCount() return false, nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index b26e44144c..8c2d7aa67f 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -66,7 +66,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co if err != nil { return res, err } - defer shBlz.Close() + defer shBlz.Close(ctx) if res, err = b.deleteObject(ctx, blz, bPrm); err == nil { success = true @@ -114,7 +114,7 @@ func (b *Blobovniczas) deleteObjectFromLevel(ctx context.Context, prm blobovnicz if err != nil { return common.DeleteRes{}, err } - defer shBlz.Close() + defer shBlz.Close(ctx) return b.deleteObject(ctx, blz, prm) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index 528dbfed71..63d2f21e12 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -42,7 +42,7 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common if err != nil { return common.ExistsRes{}, err } - defer shBlz.Close() + defer shBlz.Close(ctx) exists, err := blz.Exists(ctx, prm.Address) return common.ExistsRes{Exists: exists}, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index d6ffd8bcee..5414140f05 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -27,7 +27,7 @@ func TestExistsInvalidStorageID(t *testing.T) { WithBlobovniczaSize(1<<20)) require.NoError(t, b.Open(mode.ComponentReadWrite)) require.NoError(t, b.Init()) - defer func() { require.NoError(t, b.Close()) }() + defer func() { require.NoError(t, b.Close(context.Background())) }() obj := blobstortest.NewObject(1024) addr := object.AddressOf(obj) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index fc017f22d3..b7ef8d8a59 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -53,7 +53,7 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G if err != nil { return res, err } - defer shBlz.Close() + defer shBlz.Close(ctx) res, err = b.getObject(ctx, blz, bPrm) if err == nil { @@ -100,7 +100,7 @@ func (b *Blobovniczas) getObjectFromLevel(ctx context.Context, prm blobovnicza.G if err != nil { return common.GetRes{}, err } - defer shBlz.Close() + defer shBlz.Close(ctx) return b.getObject(ctx, blz, prm) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 384544d7b7..b24f1b8819 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -52,7 +52,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re if err != nil { return common.GetRangeRes{}, err } - defer shBlz.Close() + defer shBlz.Close(ctx) res, err := b.getObjectRange(ctx, blz, prm) if err == nil { @@ -108,7 +108,7 @@ func (b *Blobovniczas) getRangeFromLevel(ctx context.Context, prm common.GetRang if err != nil { return common.GetRangeRes{}, err } - defer shBlz.Close() + defer shBlz.Close(ctx) return b.getObjectRange(ctx, blz, prm) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 049a61d721..b120c22f77 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -84,7 +84,7 @@ func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors boo } return false, fmt.Errorf("could not open blobovnicza %s: %w", p, err) } - defer shBlz.Close() + defer shBlz.Close(ctx) err = f(p, blz) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index 502202d689..b35e052cf9 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -71,7 +71,7 @@ func (b *sharedDB) Open(ctx context.Context) (*blobovnicza.Blobovnicza, error) { if err := blz.Open(ctx); err != nil { return nil, fmt.Errorf("could not open blobovnicza %s: %w", b.path, err) } - if err := blz.Init(); err != nil { + if err := blz.Init(ctx); err != nil { return nil, fmt.Errorf("could not init blobovnicza %s: %w", b.path, err) } @@ -82,20 +82,20 @@ func (b *sharedDB) Open(ctx context.Context) (*blobovnicza.Blobovnicza, error) { return blz, nil } -func (b *sharedDB) Close() { +func (b *sharedDB) Close(ctx context.Context) { b.cond.L.Lock() defer b.cond.L.Unlock() if b.refCount == 0 { - b.log.Error(context.Background(), logs.AttemtToCloseAlreadyClosedBlobovnicza, zap.String("id", b.path)) + b.log.Error(ctx, logs.AttemtToCloseAlreadyClosedBlobovnicza, zap.String("id", b.path)) b.cond.Broadcast() return } if b.refCount == 1 { b.refCount = 0 - if err := b.blcza.Close(); err != nil { - b.log.Error(context.Background(), logs.BlobovniczatreeCouldNotCloseBlobovnicza, + if err := b.blcza.Close(ctx); err != nil { + b.log.Error(ctx, logs.BlobovniczatreeCouldNotCloseBlobovnicza, zap.String("id", b.path), zap.String("error", err.Error()), ) @@ -111,7 +111,7 @@ func (b *sharedDB) Close() { } } -func (b *sharedDB) CloseAndRemoveFile() error { +func (b *sharedDB) CloseAndRemoveFile(ctx context.Context) error { b.cond.L.Lock() if b.refCount > 1 { b.cond.Wait() @@ -122,8 +122,8 @@ func (b *sharedDB) CloseAndRemoveFile() error { return errClosingClosedBlobovnicza } - if err := b.blcza.Close(); err != nil { - b.log.Error(context.Background(), logs.BlobovniczatreeCouldNotCloseBlobovnicza, + if err := b.blcza.Close(ctx); err != nil { + b.log.Error(ctx, logs.BlobovniczatreeCouldNotCloseBlobovnicza, zap.String("id", b.path), zap.String("error", err.Error()), ) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index b562517721..0e1b2022e9 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -1,6 +1,7 @@ package blobovniczatree import ( + "context" "io/fs" "time" @@ -20,7 +21,7 @@ type cfg struct { blzShallowWidth uint64 compression *compression.Config blzOpts []blobovnicza.Option - reportError func(string, error) // reportError is the function called when encountering disk errors. + reportError func(context.Context, string, error) // reportError is the function called when encountering disk errors. metrics Metrics waitBeforeDropDB time.Duration blzInitWorkerCount int @@ -54,7 +55,7 @@ func initConfig(c *cfg) { openedCacheExpInterval: defaultOpenedCacheInterval, blzShallowDepth: defaultBlzShallowDepth, blzShallowWidth: defaultBlzShallowWidth, - reportError: func(string, error) {}, + reportError: func(context.Context, string, error) {}, metrics: &noopMetrics{}, waitBeforeDropDB: defaultWaitBeforeDropDB, blzInitWorkerCount: defaultBlzInitWorkerCount, diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 8dff436d3b..1678e578c8 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -80,7 +80,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) active, err := i.B.activeDBManager.GetOpenedActiveDBForLevel(ctx, lvlPath) if err != nil { if !isLogical(err) { - i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) + i.B.reportError(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) } else { i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, zap.String("error", err.Error()), @@ -95,14 +95,14 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return false, nil } - defer active.Close() + defer active.Close(ctx) i.AllFull = false _, err = active.Blobovnicza().Put(ctx, i.PutPrm) if err != nil { if !isLogical(err) { - i.B.reportError(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) + i.B.reportError(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) } else { i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", active.SystemPath()), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index e137bdd994..16ef2b1805 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -186,7 +186,7 @@ func (b *Blobovniczas) rebuildBySize(ctx context.Context, path string, targetFil if err != nil { return false, err } - defer shDB.Close() + defer shDB.Close(ctx) fp := blz.FillPercent() // accepted fill percent defines as // |----|+++++++++++++++++|+++++++++++++++++|--------------- @@ -206,9 +206,9 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M if shDBClosed { return } - shDB.Close() + shDB.Close(ctx) }() - dropTempFile, err := b.addRebuildTempFile(path) + dropTempFile, err := b.addRebuildTempFile(ctx, path) if err != nil { return 0, err } @@ -224,7 +224,7 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M return migratedObjects, err } -func (b *Blobovniczas) addRebuildTempFile(path string) (func(), error) { +func (b *Blobovniczas) addRebuildTempFile(ctx context.Context, path string) (func(), error) { sysPath := filepath.Join(b.rootPath, path) sysPath = sysPath + rebuildSuffix _, err := os.OpenFile(sysPath, os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, b.perm) @@ -233,7 +233,7 @@ func (b *Blobovniczas) addRebuildTempFile(path string) (func(), error) { } return func() { if err := os.Remove(sysPath); err != nil { - b.log.Warn(context.Background(), logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) + b.log.Warn(ctx, logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) } }, nil } @@ -330,7 +330,7 @@ func (b *Blobovniczas) dropDB(ctx context.Context, path string, shDb *sharedDB) b.dbFilesGuard.Lock() defer b.dbFilesGuard.Unlock() - if err := shDb.CloseAndRemoveFile(); err != nil { + if err := shDb.CloseAndRemoveFile(ctx); err != nil { return false, err } b.commondbManager.CleanResources(path) @@ -370,7 +370,7 @@ func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore co if err != nil { return true, err } - defer shDB.Close() + defer shDB.Close(ctx) incompletedMoves, err := blz.ListMoveInfo(ctx) if err != nil { @@ -403,7 +403,7 @@ func (b *Blobovniczas) performMove(ctx context.Context, source *blobovnicza.Blob if err != nil { return err } - defer targetDB.Close() + defer targetDB.Close(ctx) existsInSource := true var gPrm blobovnicza.GetPrm @@ -480,7 +480,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, target, err := i.B.activeDBManager.GetOpenedActiveDBForLevel(ctx, lvlPath) if err != nil { if !isLogical(err) { - i.B.reportError(logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) + i.B.reportError(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) } else { i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, zap.Error(err)) } @@ -491,7 +491,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, i.B.log.Warn(ctx, logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath)) return false, nil } - defer target.Close() + defer target.Close(ctx) i.AllFull = false @@ -503,7 +503,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, TargetStorageID: targetStorageID.Bytes(), }); err != nil { if !isLogical(err) { - i.B.reportError(logs.BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza, err) + i.B.reportError(ctx, logs.BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza, err) } else { i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotPutMoveInfoToSourceBlobovnicza, zap.String("path", i.SourceSysPath), zap.Error(err)) } @@ -519,7 +519,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, _, err = target.Blobovnicza().Put(ctx, putPrm) if err != nil { if !isLogical(err) { - i.B.reportError(logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) + i.B.reportError(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, err) } else { i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", target.SystemPath()), zap.Error(err)) } @@ -535,7 +535,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, deletePrm.SetAddress(i.Address) if _, err = i.Source.Delete(ctx, deletePrm); err != nil { if !isLogical(err) { - i.B.reportError(logs.BlobovniczatreeCouldNotDeleteFromSource, err) + i.B.reportError(ctx, logs.BlobovniczatreeCouldNotDeleteFromSource, err) } else { i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotDeleteFromSource, zap.String("path", i.SourceSysPath), zap.Error(err)) } @@ -544,7 +544,7 @@ func (i *moveIterator) tryMoveToLvl(ctx context.Context, lvlPath string) (bool, if err = i.Source.DropMoveInfo(ctx, i.Address); err != nil { if !isLogical(err) { - i.B.reportError(logs.BlobovniczatreeCouldNotDropMoveInfo, err) + i.B.reportError(ctx, logs.BlobovniczatreeCouldNotDropMoveInfo, err) } else { i.B.log.Warn(ctx, logs.BlobovniczatreeCouldNotDropMoveInfo, zap.String("path", i.SourceSysPath), zap.Error(err)) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index bfea97afe6..2f58624aae 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -36,7 +36,7 @@ func testRebuildFailoverOnlyMoveInfoSaved(t *testing.T) { blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) require.NoError(t, blz.Open(context.Background())) - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) obj := blobstortest.NewObject(1024) data, err := obj.Marshal() @@ -53,7 +53,7 @@ func testRebuildFailoverOnlyMoveInfoSaved(t *testing.T) { TargetStorageID: []byte("0/0/0"), })) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) _, err = os.OpenFile(filepath.Join(dir, "0", "0", "1.db.rebuild"), os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, defaultPerm) require.NoError(t, err) @@ -66,7 +66,7 @@ func testRebuildFailoverObjectSavedToTarget(t *testing.T) { blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) require.NoError(t, blz.Open(context.Background())) - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) obj := blobstortest.NewObject(1024) data, err := obj.Marshal() @@ -83,19 +83,19 @@ func testRebuildFailoverObjectSavedToTarget(t *testing.T) { TargetStorageID: []byte("0/0/0"), })) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) _, err = os.OpenFile(filepath.Join(dir, "0", "0", "1.db.rebuild"), os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, defaultPerm) require.NoError(t, err) blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) require.NoError(t, blz.Open(context.Background())) - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) _, err = blz.Put(context.Background(), pPrm) require.NoError(t, err) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) testRebuildFailoverValidate(t, dir, obj, true) } @@ -106,7 +106,7 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) require.NoError(t, blz.Open(context.Background())) - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) obj := blobstortest.NewObject(1024) data, err := obj.Marshal() @@ -117,14 +117,14 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { TargetStorageID: []byte("0/0/0"), })) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) _, err = os.OpenFile(filepath.Join(dir, "0", "0", "1.db.rebuild"), os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, defaultPerm) require.NoError(t, err) blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) require.NoError(t, blz.Open(context.Background())) - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) var pPrm blobovnicza.PutPrm pPrm.SetAddress(object.AddressOf(obj)) @@ -132,7 +132,7 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { _, err = blz.Put(context.Background(), pPrm) require.NoError(t, err) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) testRebuildFailoverValidate(t, dir, obj, false) } @@ -170,11 +170,11 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object require.Equal(t, uint64(1), rRes.ObjectsMoved) require.Equal(t, uint64(0), rRes.FilesRemoved) - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) require.NoError(t, blz.Open(context.Background())) - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) moveInfo, err := blz.ListMoveInfo(context.Background()) require.NoError(t, err) @@ -185,11 +185,11 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object _, err = blz.Get(context.Background(), gPrm) require.True(t, client.IsErrObjectNotFound(err)) - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) blz = blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "0.db"))) require.NoError(t, blz.Open(context.Background())) - require.NoError(t, blz.Init()) + require.NoError(t, blz.Init(context.Background())) moveInfo, err = blz.ListMoveInfo(context.Background()) require.NoError(t, err) @@ -203,7 +203,7 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object require.True(t, bytes.Equal([]byte("0/0/0"), metaStub.storageIDs[object.AddressOf(obj)])) } - require.NoError(t, blz.Close()) + require.NoError(t, blz.Close(context.Background())) _, err = os.Stat(filepath.Join(dir, "0", "0", "1.db.rebuild")) require.True(t, os.IsNotExist(err)) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index dff4e9024f..aae72b5fff 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -93,7 +93,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, err) } - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) }) t.Run("no rebuild single db", func(t *testing.T) { @@ -145,7 +145,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, err) } - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) }) t.Run("rebuild by fill percent", func(t *testing.T) { @@ -214,7 +214,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, err) } - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) }) t.Run("rebuild by overflow", func(t *testing.T) { @@ -251,7 +251,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { storageIDs: storageIDs, guard: &sync.Mutex{}, } - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) b = NewBlobovniczaTree( context.Background(), WithLogger(test.NewLogger(t)), @@ -284,7 +284,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, err) } - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) }) } @@ -318,7 +318,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { storageIDs := make(map[oid.Address][]byte) storageIDs[prm.Address] = res.StorageID - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) b = NewBlobovniczaTree( context.Background(), @@ -355,7 +355,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { require.NoError(t, err) } - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) } func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, targetDepth, targetWidth uint64, shouldMigrate bool) { @@ -399,7 +399,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta } require.NoError(t, eg.Wait()) - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) b = NewBlobovniczaTree( context.Background(), @@ -444,7 +444,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta require.NoError(t, err) } - require.NoError(t, b.Close()) + require.NoError(t, b.Close(context.Background())) } type storageIDUpdateStub struct { diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index 41c6cf1612..f850f48b40 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -1,6 +1,7 @@ package blobstor import ( + "context" "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" @@ -139,7 +140,7 @@ func WithUncompressableContentTypes(values []string) Option { // SetReportErrorFunc allows to provide a function to be called on disk errors. // This function MUST be called before Open. -func (b *BlobStor) SetReportErrorFunc(f func(string, error)) { +func (b *BlobStor) SetReportErrorFunc(f func(context.Context, string, error)) { for i := range b.storage { b.storage[i].Storage.SetReportErrorFunc(f) } diff --git a/pkg/local_object_storage/blobstor/blobstor_test.go b/pkg/local_object_storage/blobstor/blobstor_test.go index bed5e0eb96..6cc56fa3b2 100644 --- a/pkg/local_object_storage/blobstor/blobstor_test.go +++ b/pkg/local_object_storage/blobstor/blobstor_test.go @@ -54,7 +54,7 @@ func TestCompression(t *testing.T) { WithCompressObjects(compress), WithStorages(defaultStorages(dir, smallSizeLimit))) require.NoError(t, bs.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, bs.Init()) + require.NoError(t, bs.Init(context.Background())) return bs } @@ -91,20 +91,20 @@ func TestCompression(t *testing.T) { blobStor := newBlobStor(t, false) testPut(t, blobStor, 0) testGet(t, blobStor, 0) - require.NoError(t, blobStor.Close()) + require.NoError(t, blobStor.Close(context.Background())) blobStor = newBlobStor(t, true) testGet(t, blobStor, 0) // get uncompressed object with compress enabled testPut(t, blobStor, 1) testGet(t, blobStor, 1) - require.NoError(t, blobStor.Close()) + require.NoError(t, blobStor.Close(context.Background())) blobStor = newBlobStor(t, false) testGet(t, blobStor, 0) // get old uncompressed object testGet(t, blobStor, 1) // get compressed object with compression disabled testPut(t, blobStor, 2) testGet(t, blobStor, 2) - require.NoError(t, blobStor.Close()) + require.NoError(t, blobStor.Close(context.Background())) } func TestBlobstor_needsCompression(t *testing.T) { @@ -130,7 +130,7 @@ func TestBlobstor_needsCompression(t *testing.T) { }, })) require.NoError(t, bs.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, bs.Init()) + require.NoError(t, bs.Init(context.Background())) return bs } @@ -192,7 +192,7 @@ func TestConcurrentPut(t *testing.T) { blobStor := New( WithStorages(defaultStorages(dir, smallSizeLimit))) require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, blobStor.Init()) + require.NoError(t, blobStor.Init(context.Background())) testGet := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) { res, err := b.Get(context.Background(), common.GetPrm{Address: object.AddressOf(obj)}) @@ -272,7 +272,7 @@ func TestConcurrentDelete(t *testing.T) { blobStor := New( WithStorages(defaultStorages(dir, smallSizeLimit))) require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, blobStor.Init()) + require.NoError(t, blobStor.Init(context.Background())) testPut := func(t *testing.T, b *BlobStor, obj *objectSDK.Object) { var prm common.PutPrm diff --git a/pkg/local_object_storage/blobstor/common/storage.go b/pkg/local_object_storage/blobstor/common/storage.go index 4f3a209937..6ecef48cdc 100644 --- a/pkg/local_object_storage/blobstor/common/storage.go +++ b/pkg/local_object_storage/blobstor/common/storage.go @@ -12,7 +12,7 @@ import ( type Storage interface { Open(mode mode.ComponentMode) error Init() error - Close() error + Close(context.Context) error Type() string Path() string @@ -23,7 +23,7 @@ type Storage interface { // SetReportErrorFunc allows to provide a function to be called on disk errors. // This function MUST be called before Open. - SetReportErrorFunc(f func(string, error)) + SetReportErrorFunc(f func(context.Context, string, error)) SetParentID(parentID string) Get(context.Context, GetPrm) (GetRes, error) diff --git a/pkg/local_object_storage/blobstor/control.go b/pkg/local_object_storage/blobstor/control.go index 43436b4eb6..44685524f2 100644 --- a/pkg/local_object_storage/blobstor/control.go +++ b/pkg/local_object_storage/blobstor/control.go @@ -50,8 +50,8 @@ var ErrInitBlobovniczas = errors.New("failure on blobovnicza initialization stag // If BlobStor is already initialized, no action is taken. // // Returns wrapped ErrInitBlobovniczas on blobovnicza tree's initializaiton failure. -func (b *BlobStor) Init() error { - b.log.Debug(context.Background(), logs.BlobstorInitializing) +func (b *BlobStor) Init(ctx context.Context) error { + b.log.Debug(ctx, logs.BlobstorInitializing) if err := b.compression.Init(); err != nil { return err @@ -67,14 +67,14 @@ func (b *BlobStor) Init() error { } // Close releases all internal resources of BlobStor. -func (b *BlobStor) Close() error { - b.log.Debug(context.Background(), logs.BlobstorClosing) +func (b *BlobStor) Close(ctx context.Context) error { + b.log.Debug(ctx, logs.BlobstorClosing) var firstErr error for i := range b.storage { - err := b.storage[i].Storage.Close() + err := b.storage[i].Storage.Close(ctx) if err != nil { - b.log.Info(context.Background(), logs.BlobstorCouldntCloseStorage, zap.String("error", err.Error())) + b.log.Info(ctx, logs.BlobstorCouldntCloseStorage, zap.String("error", err.Error())) if firstErr == nil { firstErr = err } diff --git a/pkg/local_object_storage/blobstor/exists_test.go b/pkg/local_object_storage/blobstor/exists_test.go index 783c198b2c..7eb7d49bf4 100644 --- a/pkg/local_object_storage/blobstor/exists_test.go +++ b/pkg/local_object_storage/blobstor/exists_test.go @@ -22,7 +22,7 @@ func TestExists(t *testing.T) { b := New(WithStorages(storages)) require.NoError(t, b.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, b.Init()) + require.NoError(t, b.Init(context.Background())) objects := []*objectSDK.Object{ testObject(smallSizeLimit / 2), diff --git a/pkg/local_object_storage/blobstor/fstree/control.go b/pkg/local_object_storage/blobstor/fstree/control.go index c21d79f09c..2544729f73 100644 --- a/pkg/local_object_storage/blobstor/fstree/control.go +++ b/pkg/local_object_storage/blobstor/fstree/control.go @@ -1,6 +1,8 @@ package fstree import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" ) @@ -28,7 +30,7 @@ func (t *FSTree) Init() error { } // Close implements common.Storage. -func (t *FSTree) Close() error { +func (t *FSTree) Close(_ context.Context) error { t.metrics.Close() return nil } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 7f52762a7a..53eb0395a3 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -606,7 +606,7 @@ func (t *FSTree) Compressor() *compression.Config { } // SetReportErrorFunc implements common.Storage. -func (t *FSTree) SetReportErrorFunc(_ func(string, error)) { +func (t *FSTree) SetReportErrorFunc(_ func(context.Context, string, error)) { // Do nothing, FSTree can encounter only one error which is returned. } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_test.go b/pkg/local_object_storage/blobstor/fstree/fstree_test.go index eb2126b6c0..50dae46a74 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_test.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_test.go @@ -52,7 +52,7 @@ func TestObjectCounter(t *testing.T) { require.Equal(t, uint64(0), size) defer func() { - require.NoError(t, fst.Close()) + require.NoError(t, fst.Close(context.Background())) }() addr := oidtest.Address() diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/control.go b/pkg/local_object_storage/blobstor/internal/blobstortest/control.go index 21c80b0898..b8e88f84a0 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/control.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/control.go @@ -19,7 +19,7 @@ func TestControl(t *testing.T, cons Constructor, minSize, maxSize uint64) { require.NoError(t, s.Init()) objects := prepare(t, 10, s, minSize, maxSize) - require.NoError(t, s.Close()) + require.NoError(t, s.Close(context.Background())) require.NoError(t, s.Open(mode.ComponentReadOnly)) for i := range objects { diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go index cf4e765132..3a163f6b17 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/delete.go @@ -15,7 +15,7 @@ func TestDelete(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() objects := prepare(t, 4, s, minSize, maxSize) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go index 08465ed5ea..f34fe5f97e 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/exists.go @@ -14,7 +14,7 @@ func TestExists(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() objects := prepare(t, 1, s, minSize, maxSize) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go index d1f709b0cd..af0f4b45dd 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get.go @@ -15,7 +15,7 @@ func TestGet(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() objects := prepare(t, 2, s, minSize, maxSize) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go index fcbeddac74..13032048c9 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/get_range.go @@ -17,7 +17,7 @@ func TestGetRange(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() objects := prepare(t, 1, s, minSize, maxSize) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index 3a6c8b699d..36b2c33f88 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -14,7 +14,7 @@ func TestIterate(t *testing.T, cons Constructor, minSize, maxSize uint64) { s := cons(t) require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() objects := prepare(t, 10, s, minSize, maxSize) diff --git a/pkg/local_object_storage/blobstor/iterate_test.go b/pkg/local_object_storage/blobstor/iterate_test.go index 3c9457db2d..ccfa510fe4 100644 --- a/pkg/local_object_storage/blobstor/iterate_test.go +++ b/pkg/local_object_storage/blobstor/iterate_test.go @@ -33,9 +33,9 @@ func TestIterateObjects(t *testing.T) { require.NoError(t, blobStor.Open(context.Background(), mode.ReadWrite)) // initialize Blobstor - require.NoError(t, blobStor.Init()) + require.NoError(t, blobStor.Init(context.Background())) - defer blobStor.Close() + defer blobStor.Close(context.Background()) const objNum = 5 @@ -118,7 +118,7 @@ func TestIterate_IgnoreErrors(t *testing.T) { })} bs := New(bsOpts...) require.NoError(t, bs.Open(ctx, mode.ReadWrite)) - require.NoError(t, bs.Init()) + require.NoError(t, bs.Init(ctx)) nopHandler := func(e common.IterationElement) error { return nil diff --git a/pkg/local_object_storage/blobstor/memstore/control.go b/pkg/local_object_storage/blobstor/memstore/control.go index 83da52eb75..95a916662d 100644 --- a/pkg/local_object_storage/blobstor/memstore/control.go +++ b/pkg/local_object_storage/blobstor/memstore/control.go @@ -1,6 +1,8 @@ package memstore import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" ) @@ -10,11 +12,11 @@ func (s *memstoreImpl) Open(mod mode.ComponentMode) error { return nil } -func (s *memstoreImpl) Init() error { return nil } -func (s *memstoreImpl) Close() error { return nil } -func (s *memstoreImpl) Type() string { return Type } -func (s *memstoreImpl) Path() string { return s.rootPath } -func (s *memstoreImpl) SetCompressor(cc *compression.Config) { s.compression = cc } -func (s *memstoreImpl) Compressor() *compression.Config { return s.compression } -func (s *memstoreImpl) SetReportErrorFunc(func(string, error)) {} -func (s *memstoreImpl) SetParentID(string) {} +func (s *memstoreImpl) Init() error { return nil } +func (s *memstoreImpl) Close(context.Context) error { return nil } +func (s *memstoreImpl) Type() string { return Type } +func (s *memstoreImpl) Path() string { return s.rootPath } +func (s *memstoreImpl) SetCompressor(cc *compression.Config) { s.compression = cc } +func (s *memstoreImpl) Compressor() *compression.Config { return s.compression } +func (s *memstoreImpl) SetReportErrorFunc(func(context.Context, string, error)) {} +func (s *memstoreImpl) SetParentID(string) {} diff --git a/pkg/local_object_storage/blobstor/memstore/memstore_test.go b/pkg/local_object_storage/blobstor/memstore/memstore_test.go index dd130e5f96..f904d42323 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore_test.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore_test.go @@ -16,7 +16,7 @@ func TestSimpleLifecycle(t *testing.T) { s := New( WithRootPath("memstore"), ) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() require.NoError(t, s.Open(mode.ComponentReadWrite)) require.NoError(t, s.Init()) diff --git a/pkg/local_object_storage/blobstor/mode.go b/pkg/local_object_storage/blobstor/mode.go index f081ff6451..af19e398ee 100644 --- a/pkg/local_object_storage/blobstor/mode.go +++ b/pkg/local_object_storage/blobstor/mode.go @@ -20,10 +20,10 @@ func (b *BlobStor) SetMode(ctx context.Context, m mode.Mode) error { return nil } - err := b.Close() + err := b.Close(ctx) if err == nil { if err = b.openBlobStor(ctx, m); err == nil { - err = b.Init() + err = b.Init(ctx) } } if err != nil { diff --git a/pkg/local_object_storage/blobstor/perf_test.go b/pkg/local_object_storage/blobstor/perf_test.go index 1ac769e367..64e3c8da12 100644 --- a/pkg/local_object_storage/blobstor/perf_test.go +++ b/pkg/local_object_storage/blobstor/perf_test.go @@ -106,7 +106,7 @@ func BenchmarkSubstorageReadPerf(b *testing.B) { b.Run(fmt.Sprintf("%s-%s", stEntry.desc, tt.desc), func(b *testing.B) { objGen := tt.objGen() st := stEntry.open(b) - defer func() { require.NoError(b, st.Close()) }() + defer func() { require.NoError(b, st.Close(context.Background())) }() // Fill database var errG errgroup.Group @@ -161,7 +161,7 @@ func BenchmarkSubstorageWritePerf(b *testing.B) { b.Run(fmt.Sprintf("%s-%s", stEntry.desc, genEntry.desc), func(b *testing.B) { gen := genEntry.create() st := stEntry.open(b) - defer func() { require.NoError(b, st.Close()) }() + defer func() { require.NoError(b, st.Close(context.Background())) }() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { @@ -200,7 +200,7 @@ func BenchmarkSubstorageIteratePerf(b *testing.B) { b.Run(fmt.Sprintf("%s-%s", stEntry.desc, tt.desc), func(b *testing.B) { objGen := tt.objGen() st := stEntry.open(b) - defer func() { require.NoError(b, st.Close()) }() + defer func() { require.NoError(b, st.Close(context.Background())) }() // Fill database for range tt.size { diff --git a/pkg/local_object_storage/blobstor/teststore/option.go b/pkg/local_object_storage/blobstor/teststore/option.go index bc0bed49d6..fb11887517 100644 --- a/pkg/local_object_storage/blobstor/teststore/option.go +++ b/pkg/local_object_storage/blobstor/teststore/option.go @@ -1,6 +1,8 @@ package teststore import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -17,7 +19,7 @@ type cfg struct { Path func() string SetCompressor func(cc *compression.Config) Compressor func() *compression.Config - SetReportErrorFunc func(f func(string, error)) + SetReportErrorFunc func(f func(context.Context, string, error)) Get func(common.GetPrm) (common.GetRes, error) GetRange func(common.GetRangePrm) (common.GetRangeRes, error) @@ -51,7 +53,7 @@ func WithCompressor(f func() *compression.Config) Option { return func(c *cfg) { c.overrides.Compressor = f } } -func WithReportErrorFunc(f func(func(string, error))) Option { +func WithReportErrorFunc(f func(func(context.Context, string, error))) Option { return func(c *cfg) { c.overrides.SetReportErrorFunc = f } } diff --git a/pkg/local_object_storage/blobstor/teststore/teststore.go b/pkg/local_object_storage/blobstor/teststore/teststore.go index fea4a2d49b..626ba00231 100644 --- a/pkg/local_object_storage/blobstor/teststore/teststore.go +++ b/pkg/local_object_storage/blobstor/teststore/teststore.go @@ -77,14 +77,14 @@ func (s *TestStore) Init() error { } } -func (s *TestStore) Close() error { +func (s *TestStore) Close(ctx context.Context) error { s.mu.RLock() defer s.mu.RUnlock() switch { case s.overrides.Close != nil: return s.overrides.Close() case s.st != nil: - return s.st.Close() + return s.st.Close(ctx) default: panic("unexpected storage call: Close()") } @@ -142,7 +142,7 @@ func (s *TestStore) Compressor() *compression.Config { } } -func (s *TestStore) SetReportErrorFunc(f func(string, error)) { +func (s *TestStore) SetReportErrorFunc(f func(context.Context, string, error)) { s.mu.RLock() defer s.mu.RUnlock() switch { diff --git a/pkg/local_object_storage/engine/container.go b/pkg/local_object_storage/engine/container.go index a52436175d..24059a3f90 100644 --- a/pkg/local_object_storage/engine/container.go +++ b/pkg/local_object_storage/engine/container.go @@ -44,11 +44,11 @@ func (r ListContainersRes) Containers() []cid.ID { // ContainerSize returns the sum of estimation container sizes among all shards. // // Returns an error if executions are blocked (see BlockExecution). -func (e *StorageEngine) ContainerSize(prm ContainerSizePrm) (res ContainerSizeRes, err error) { +func (e *StorageEngine) ContainerSize(ctx context.Context, prm ContainerSizePrm) (res ContainerSizeRes, err error) { defer elapsed("ContainerSize", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res, err = e.containerSize(prm) + res, err = e.containerSize(ctx, prm) return err }) @@ -56,12 +56,12 @@ func (e *StorageEngine) ContainerSize(prm ContainerSizePrm) (res ContainerSizeRe } // ContainerSize calls ContainerSize method on engine to calculate sum of estimation container sizes among all shards. -func ContainerSize(e *StorageEngine, id cid.ID) (uint64, error) { +func ContainerSize(ctx context.Context, e *StorageEngine, id cid.ID) (uint64, error) { var prm ContainerSizePrm prm.SetContainerID(id) - res, err := e.ContainerSize(prm) + res, err := e.ContainerSize(ctx, prm) if err != nil { return 0, err } @@ -69,14 +69,14 @@ func ContainerSize(e *StorageEngine, id cid.ID) (uint64, error) { return res.Size(), nil } -func (e *StorageEngine) containerSize(prm ContainerSizePrm) (res ContainerSizeRes, err error) { +func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) (res ContainerSizeRes, err error) { e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { var csPrm shard.ContainerSizePrm csPrm.SetContainerID(prm.cnr) csRes, err := sh.Shard.ContainerSize(csPrm) if err != nil { - e.reportShardError(sh, "can't get container size", err, + e.reportShardError(ctx, sh, "can't get container size", err, zap.Stringer("container_id", prm.cnr)) return false } @@ -121,7 +121,7 @@ func (e *StorageEngine) listContainers(ctx context.Context) (ListContainersRes, e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { res, err := sh.Shard.ListContainers(ctx, shard.ListContainersPrm{}) if err != nil { - e.reportShardError(sh, "can't get list of containers", err) + e.reportShardError(ctx, sh, "can't get list of containers", err) return false } diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 2e957eb046..7164ff21f2 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -97,7 +97,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e return false } else { if !client.IsErrObjectNotFound(err) { - e.reportShardError(sh, "could not check object existence", err, zap.Stringer("address", prm.addr)) + e.reportShardError(ctx, sh, "could not check object existence", err, zap.Stringer("address", prm.addr)) } return false } @@ -113,7 +113,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e _, err = sh.Inhume(ctx, shPrm) if err != nil { - e.reportShardError(sh, "could not inhume object in shard", err, zap.Stringer("address", prm.addr)) + e.reportShardError(ctx, sh, "could not inhume object in shard", err, zap.Stringer("address", prm.addr)) var target *apistatus.ObjectLocked locked.is = errors.As(err, &target) @@ -188,7 +188,7 @@ func (e *StorageEngine) deleteChunks( var objID oid.ID err := objID.ReadFromV2(chunk.ID) if err != nil { - e.reportShardError(sh, "could not delete EC chunk", err, zap.Stringer("address", prm.addr)) + e.reportShardError(ctx, sh, "could not delete EC chunk", err, zap.Stringer("address", prm.addr)) } addr.SetObject(objID) inhumePrm.MarkAsGarbage(addr) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 6e30ee9de7..0299040463 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -99,24 +99,24 @@ func (e *StorageEngine) moveToDegraded(ctx context.Context, sh *shard.Shard, err if isMeta { err := sh.SetMode(ctx, mode.DegradedReadOnly) if err == nil { - log.Info(context.Background(), logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) + log.Info(ctx, logs.EngineShardIsMovedInDegradedModeDueToErrorThreshold) return } - log.Error(context.Background(), logs.EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly, + log.Error(ctx, logs.EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly, zap.Error(err)) } err := sh.SetMode(ctx, mode.ReadOnly) if err != nil { - log.Error(context.Background(), logs.EngineFailedToMoveShardInReadonlyMode, zap.Error(err)) + log.Error(ctx, logs.EngineFailedToMoveShardInReadonlyMode, zap.Error(err)) return } - log.Info(context.Background(), logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) + log.Info(ctx, logs.EngineShardIsMovedInReadonlyModeDueToErrorThreshold) } // reportShardErrorByID increases shard error counter and logs an error. -func (e *StorageEngine) reportShardErrorByID(id string, msg string, err error) { +func (e *StorageEngine) reportShardErrorByID(ctx context.Context, id string, msg string, err error) { e.mtx.RLock() sh, ok := e.shards[id] e.mtx.RUnlock() @@ -125,19 +125,20 @@ func (e *StorageEngine) reportShardErrorByID(id string, msg string, err error) { return } - e.reportShardError(sh, msg, err) + e.reportShardError(ctx, sh, msg, err) } // reportShardError checks that the amount of errors doesn't exceed the configured threshold. // If it does, shard is set to read-only mode. func (e *StorageEngine) reportShardError( + ctx context.Context, sh hashedShard, msg string, err error, fields ...zap.Field, ) { if isLogical(err) { - e.log.Warn(context.Background(), msg, + e.log.Warn(ctx, msg, zap.Stringer("shard_id", sh.ID()), zap.String("error", err.Error())) return @@ -147,7 +148,7 @@ func (e *StorageEngine) reportShardError( e.metrics.IncErrorCounter(sh.ID().String()) sid := sh.ID() - e.log.Warn(context.Background(), msg, append([]zap.Field{ + e.log.Warn(ctx, msg, append([]zap.Field{ zap.Stringer("shard_id", sid), zap.Uint32("error count", errCount), zap.String("error", err.Error()), @@ -168,7 +169,7 @@ func (e *StorageEngine) reportShardError( default: // For background workers we can have a lot of such errors, // thus logging is done with DEBUG level. - e.log.Debug(context.Background(), logs.EngineModeChangeIsInProgressIgnoringSetmodeRequest, + e.log.Debug(ctx, logs.EngineModeChangeIsInProgressIgnoringSetmodeRequest, zap.Stringer("shard_id", sid), zap.Uint32("error_count", errCount)) } diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index d981013064..9d2b1c1b78 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -37,7 +37,7 @@ func (e *StorageEngine) exists(ctx context.Context, shPrm shard.ExistsPrm) (bool } if !client.IsErrObjectNotFound(err) { - e.reportShardError(sh, "could not check existence of object in shard", err, zap.Stringer("address", shPrm.Address)) + e.reportShardError(ctx, sh, "could not check existence of object in shard", err, zap.Stringer("address", shPrm.Address)) } return false } diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index d6827e6c34..c7145889b1 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -183,7 +183,7 @@ func (i *getShardIterator) tryGetWithMeta(ctx context.Context) { i.ObjectExpired = true return true default: - i.Engine.reportShardError(sh, "could not get object from shard", err, zap.Stringer("address", i.Address)) + i.Engine.reportShardError(ctx, sh, "could not get object from shard", err, zap.Stringer("address", i.Address)) return false } }) diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index d2e3cfd99f..d6892f1291 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -117,7 +117,7 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) outError = new(apistatus.ObjectNotFound) return true default: - e.reportShardError(sh, "could not head object from shard", err, zap.Stringer("address", prm.addr)) + e.reportShardError(ctx, sh, "could not head object from shard", err, zap.Stringer("address", prm.addr)) return false } } diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 1dc64c1744..e89a8d0484 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -151,7 +151,7 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh var siErr *objectSDK.SplitInfoError var ecErr *objectSDK.ECInfoError if !(errors.As(err, &siErr) || errors.As(err, &ecErr)) { - e.reportShardError(sh, "could not check for presents in shard", err, zap.Stringer("address", addr)) + e.reportShardError(ctx, sh, "could not check for presents in shard", err, zap.Stringer("address", addr)) return } @@ -176,7 +176,7 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh return true } - e.reportShardError(sh, "could not inhume object in shard", err, zap.Stringer("address", addr)) + e.reportShardError(ctx, sh, "could not inhume object in shard", err, zap.Stringer("address", addr)) return false } @@ -202,7 +202,7 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { locked, err = h.Shard.IsLocked(ctx, addr) if err != nil { - e.reportShardError(h, "can't check object's lockers", err, zap.Stringer("address", addr), + e.reportShardError(ctx, h, "can't check object's lockers", err, zap.Stringer("address", addr), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) outErr = err return false @@ -232,7 +232,7 @@ func (e *StorageEngine) GetLocked(ctx context.Context, addr oid.Address) ([]oid. e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { ld, err := h.Shard.GetLocked(ctx, addr) if err != nil { - e.reportShardError(h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr), + e.reportShardError(ctx, h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) outErr = err } @@ -274,7 +274,7 @@ func (e *StorageEngine) processExpiredLocks(ctx context.Context, epoch uint64, l func (e *StorageEngine) processDeletedLocks(ctx context.Context, lockers []oid.Address) { e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { - sh.HandleDeletedLocks(lockers) + sh.HandleDeletedLocks(ctx, lockers) select { case <-ctx.Done(): diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index bbab59bfab..5d43e59df1 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -89,7 +89,7 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo var objID oid.ID err = objID.ReadFromV2(chunk.ID) if err != nil { - e.reportShardError(sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), + e.reportShardError(ctx, sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) return false } @@ -97,7 +97,7 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo } err = sh.Lock(ctx, idCnr, locker, eclocked) if err != nil { - e.reportShardError(sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), + e.reportShardError(ctx, sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) return false } @@ -109,7 +109,7 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo // do not lock it return true } - e.reportShardError(sh, "could not check locked object for presence in shard", err, zap.Stringer("container_id", idCnr), + e.reportShardError(ctx, sh, "could not check locked object for presence in shard", err, zap.Stringer("container_id", idCnr), zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) return } @@ -122,7 +122,7 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo err := sh.Lock(ctx, idCnr, locker, []oid.ID{locked}) if err != nil { - e.reportShardError(sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), + e.reportShardError(ctx, sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) var errIrregular *apistatus.LockNonRegularObject diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 635f0e3023..e080191ae4 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -179,7 +179,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti return } - e.reportShardError(sh, "could not put object to shard", err, zap.Stringer("address", addr)) + e.reportShardError(ctx, sh, "could not put object to shard", err, zap.Stringer("address", addr)) return } diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index c5c94eef7e..0c9cea9036 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -205,7 +205,7 @@ func (i *getRangeShardIterator) tryGetWithMeta(ctx context.Context) { return true // stop, return it back default: - i.Engine.reportShardError(sh, "could not get object from shard", err, zap.Stringer("address", i.Address)) + i.Engine.reportShardError(ctx, sh, "could not get object from shard", err, zap.Stringer("address", i.Address)) return false } }) diff --git a/pkg/local_object_storage/engine/select.go b/pkg/local_object_storage/engine/select.go index 0f1341f856..02149b4c8b 100644 --- a/pkg/local_object_storage/engine/select.go +++ b/pkg/local_object_storage/engine/select.go @@ -74,7 +74,7 @@ func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { res, err := sh.Select(ctx, shPrm) if err != nil { - e.reportShardError(sh, "could not select objects from shard", err) + e.reportShardError(ctx, sh, "could not select objects from shard", err) return false } @@ -116,7 +116,7 @@ func (e *StorageEngine) list(ctx context.Context, limit uint64) (SelectRes, erro e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { res, err := sh.List(ctx) // consider limit result of shard iterator if err != nil { - e.reportShardError(sh, "could not select objects from shard", err) + e.reportShardError(ctx, sh, "could not select objects from shard", err) } else { for _, addr := range res.AddressList() { // save only unique values if _, ok := uniqueMap[addr.EncodeToString()]; !ok { diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 2b94103e99..898f685ecf 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -351,7 +351,7 @@ func (e *StorageEngine) DetachShards(ctx context.Context, ids []*shard.ID) error return logicerr.New("ids must be non-empty") } - deletedShards, err := e.deleteShards(ids) + deletedShards, err := e.deleteShards(ctx, ids) if err != nil { return err } @@ -400,7 +400,7 @@ func (e *StorageEngine) closeShards(ctx context.Context, deletedShards []hashedS // deleteShards deletes shards with specified ids from engine shard list // and releases all engine resources associated with shards. // Returns deleted shards or error if some shard could not be deleted. -func (e *StorageEngine) deleteShards(ids []*shard.ID) ([]hashedShard, error) { +func (e *StorageEngine) deleteShards(ctx context.Context, ids []*shard.ID) ([]hashedShard, error) { ss := make([]hashedShard, 0, len(ids)) e.mtx.Lock() @@ -432,7 +432,7 @@ func (e *StorageEngine) deleteShards(ids []*shard.ID) ([]hashedShard, error) { delete(e.shardPools, idStr) } - e.log.Info(context.Background(), logs.EngineShardHasBeenRemoved, + e.log.Info(ctx, logs.EngineShardHasBeenRemoved, zap.String("id", idStr)) } diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index 6bb5e3a41a..268b4adfaa 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -37,7 +37,7 @@ func (e *StorageEngine) TreeMove(ctx context.Context, d pilorama.CIDDescriptor, lm, err := lst[index].TreeMove(ctx, d, treeID, m) if err != nil { if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { - e.reportShardError(lst[index], "can't perform `TreeMove`", err, + e.reportShardError(ctx, lst[index], "can't perform `TreeMove`", err, zap.Stringer("cid", d.CID), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -71,7 +71,7 @@ func (e *StorageEngine) TreeAddByPath(ctx context.Context, d pilorama.CIDDescrip lm, err := lst[index].TreeAddByPath(ctx, d, treeID, attr, path, m) if err != nil { if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { - e.reportShardError(lst[index], "can't perform `TreeAddByPath`", err, + e.reportShardError(ctx, lst[index], "can't perform `TreeAddByPath`", err, zap.Stringer("cid", d.CID), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -100,7 +100,7 @@ func (e *StorageEngine) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID str err = lst[index].TreeApply(ctx, cnr, treeID, m, backgroundSync) if err != nil { if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { - e.reportShardError(lst[index], "can't perform `TreeApply`", err, + e.reportShardError(ctx, lst[index], "can't perform `TreeApply`", err, zap.Stringer("cid", cnr), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -128,7 +128,7 @@ func (e *StorageEngine) TreeApplyBatch(ctx context.Context, cnr cidSDK.ID, treeI err = lst[index].TreeApplyBatch(ctx, cnr, treeID, m) if err != nil { if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { - e.reportShardError(lst[index], "can't perform `TreeApplyBatch`", err, + e.reportShardError(ctx, lst[index], "can't perform `TreeApplyBatch`", err, zap.Stringer("cid", cnr), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -160,7 +160,7 @@ func (e *StorageEngine) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID break } if !errors.Is(err, pilorama.ErrTreeNotFound) { - e.reportShardError(sh, "can't perform `TreeGetByPath`", err, + e.reportShardError(ctx, sh, "can't perform `TreeGetByPath`", err, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -193,7 +193,7 @@ func (e *StorageEngine) TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID s break } if !errors.Is(err, pilorama.ErrTreeNotFound) { - e.reportShardError(sh, "can't perform `TreeGetMeta`", err, + e.reportShardError(ctx, sh, "can't perform `TreeGetMeta`", err, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -225,7 +225,7 @@ func (e *StorageEngine) TreeGetChildren(ctx context.Context, cid cidSDK.ID, tree break } if !errors.Is(err, pilorama.ErrTreeNotFound) { - e.reportShardError(sh, "can't perform `TreeGetChildren`", err, + e.reportShardError(ctx, sh, "can't perform `TreeGetChildren`", err, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -257,7 +257,7 @@ func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, break } if !errors.Is(err, pilorama.ErrTreeNotFound) { - e.reportShardError(sh, "can't perform `TreeSortedByFilename`", err, + e.reportShardError(ctx, sh, "can't perform `TreeSortedByFilename`", err, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -289,7 +289,7 @@ func (e *StorageEngine) TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID break } if !errors.Is(err, pilorama.ErrTreeNotFound) { - e.reportShardError(sh, "can't perform `TreeGetOpLog`", err, + e.reportShardError(ctx, sh, "can't perform `TreeGetOpLog`", err, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -319,7 +319,7 @@ func (e *StorageEngine) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID stri break } if !errors.Is(err, pilorama.ErrTreeNotFound) && !errors.Is(err, shard.ErrReadOnlyMode) { - e.reportShardError(sh, "can't perform `TreeDrop`", err, + e.reportShardError(ctx, sh, "can't perform `TreeDrop`", err, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -349,7 +349,7 @@ func (e *StorageEngine) TreeList(ctx context.Context, cid cidSDK.ID) ([]string, return nil, err } - e.reportShardError(sh, "can't perform `TreeList`", err, + e.reportShardError(ctx, sh, "can't perform `TreeList`", err, zap.Stringer("cid", cid), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -415,7 +415,7 @@ func (e *StorageEngine) TreeUpdateLastSyncHeight(ctx context.Context, cid cidSDK err = lst[index].TreeUpdateLastSyncHeight(ctx, cid, treeID, height) if err != nil && !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { - e.reportShardError(lst[index], "can't update tree synchronization height", err, + e.reportShardError(ctx, lst[index], "can't update tree synchronization height", err, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) @@ -442,7 +442,7 @@ func (e *StorageEngine) TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, t break } if !errors.Is(err, pilorama.ErrTreeNotFound) { - e.reportShardError(sh, "can't read tree synchronization height", err, + e.reportShardError(ctx, sh, "can't read tree synchronization height", err, zap.Stringer("cid", cid), zap.String("tree", treeID), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/internal/storagetest/storage.go b/pkg/local_object_storage/internal/storagetest/storage.go index d8ac106dd6..d46365296b 100644 --- a/pkg/local_object_storage/internal/storagetest/storage.go +++ b/pkg/local_object_storage/internal/storagetest/storage.go @@ -12,8 +12,8 @@ import ( type Component interface { Open(context.Context, mode.Mode) error SetMode(context.Context, mode.Mode) error - Init() error - Close() error + Init(context.Context) error + Close(context.Context) error } // Constructor constructs storage component. @@ -59,18 +59,18 @@ func TestCloseAfterOpen(t *testing.T, cons Constructor) { // Use-case: irrecoverable error on some components, close everything. s := cons(t) require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, s.Close()) + require.NoError(t, s.Close(context.Background())) }) t.Run("RO", func(t *testing.T) { // Use-case: irrecoverable error on some components, close everything. // Open in read-only must be done after the db is here. s := cons(t) require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, s.Init()) - require.NoError(t, s.Close()) + require.NoError(t, s.Init(context.Background())) + require.NoError(t, s.Close(context.Background())) require.NoError(t, s.Open(context.Background(), mode.ReadOnly)) - require.NoError(t, s.Close()) + require.NoError(t, s.Close(context.Background())) }) } @@ -79,9 +79,9 @@ func TestCloseTwice(t *testing.T, cons Constructor) { // Use-case: move to maintenance mode twice, first time failed. s := cons(t) require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, s.Init()) - require.NoError(t, s.Close()) - require.NoError(t, s.Close()) // already closed, no-op + require.NoError(t, s.Init(context.Background())) + require.NoError(t, s.Close(context.Background())) + require.NoError(t, s.Close(context.Background())) // already closed, no-op } // TestSetMode checks that any mode transition can be done safely. @@ -94,20 +94,20 @@ func TestSetMode(t *testing.T, cons Constructor, m mode.Mode) { require.NoError(t, s.SetMode(context.Background(), m)) t.Run("after open in RO", func(t *testing.T) { - require.NoError(t, s.Close()) + require.NoError(t, s.Close(context.Background())) require.NoError(t, s.Open(context.Background(), mode.ReadOnly)) require.NoError(t, s.SetMode(context.Background(), m)) }) - require.NoError(t, s.Close()) + require.NoError(t, s.Close(context.Background())) }) t.Run("after init", func(t *testing.T) { s := cons(t) // Use-case: notmal node operation. require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, s.Init()) + require.NoError(t, s.Init(context.Background())) require.NoError(t, s.SetMode(context.Background(), m)) - require.NoError(t, s.Close()) + require.NoError(t, s.Close(context.Background())) }) } @@ -115,8 +115,8 @@ func TestModeTransition(t *testing.T, cons Constructor, from, to mode.Mode) { // Use-case: normal node operation. s := cons(t) require.NoError(t, s.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, s.Init()) + require.NoError(t, s.Init(context.Background())) require.NoError(t, s.SetMode(context.Background(), from)) require.NoError(t, s.SetMode(context.Background(), to)) - require.NoError(t, s.Close()) + require.NoError(t, s.Close(context.Background())) } diff --git a/pkg/local_object_storage/metabase/containers_test.go b/pkg/local_object_storage/metabase/containers_test.go index 110be68ad1..8d8d91dc74 100644 --- a/pkg/local_object_storage/metabase/containers_test.go +++ b/pkg/local_object_storage/metabase/containers_test.go @@ -18,7 +18,7 @@ func TestDB_Containers(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() const N = 10 @@ -79,7 +79,7 @@ func TestDB_ContainersCount(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() const R, T, SG, L = 10, 11, 12, 13 // amount of object per type @@ -116,7 +116,7 @@ func TestDB_ContainerSize(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() const ( C = 3 diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 54bea42046..07fa7e9cf6 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -57,7 +57,7 @@ func (db *DB) openDB(ctx context.Context, mode mode.Mode) error { return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err) } - db.log.Debug(context.Background(), logs.MetabaseCreatedDirectoryForMetabase, zap.String("path", db.info.Path)) + db.log.Debug(ctx, logs.MetabaseCreatedDirectoryForMetabase, zap.String("path", db.info.Path)) if db.boltOptions == nil { opts := *bbolt.DefaultOptions @@ -78,9 +78,9 @@ func (db *DB) openBolt(ctx context.Context) error { db.boltDB.MaxBatchDelay = db.boltBatchDelay db.boltDB.MaxBatchSize = db.boltBatchSize - db.log.Debug(context.Background(), logs.MetabaseOpenedBoltDBInstanceForMetabase) + db.log.Debug(ctx, logs.MetabaseOpenedBoltDBInstanceForMetabase) - db.log.Debug(context.Background(), logs.MetabaseCheckingMetabaseVersion) + db.log.Debug(ctx, logs.MetabaseCheckingMetabaseVersion) return db.boltDB.View(func(tx *bbolt.Tx) error { // The safest way to check if the metabase is fresh is to check if it has no buckets. // However, shard info can be present. So here we check that the number of buckets is @@ -109,7 +109,7 @@ func (db *DB) openBolt(ctx context.Context) error { // // Does nothing if metabase has already been initialized and filled. To roll back the database to its initial state, // use Reset. -func (db *DB) Init() error { +func (db *DB) Init(_ context.Context) error { return metaerr.Wrap(db.init(false)) } @@ -205,7 +205,7 @@ func (db *DB) SyncCounters() error { // Close closes boltDB instance // and reports metabase metric. -func (db *DB) Close() error { +func (db *DB) Close(context.Context) error { var err error if db.boltDB != nil { err = db.close() @@ -236,7 +236,7 @@ func (db *DB) Reload(ctx context.Context, opts ...Option) (bool, error) { defer db.modeMtx.Unlock() if db.mode.NoMetabase() || c.info.Path != "" && filepath.Clean(db.info.Path) != filepath.Clean(c.info.Path) { - if err := db.Close(); err != nil { + if err := db.Close(ctx); err != nil { return false, err } diff --git a/pkg/local_object_storage/metabase/control_test.go b/pkg/local_object_storage/metabase/control_test.go index 2a64881cbb..d264026757 100644 --- a/pkg/local_object_storage/metabase/control_test.go +++ b/pkg/local_object_storage/metabase/control_test.go @@ -15,7 +15,7 @@ import ( func TestReset(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() err := db.Reset() require.NoError(t, err) diff --git a/pkg/local_object_storage/metabase/counter_test.go b/pkg/local_object_storage/metabase/counter_test.go index dccccd456b..950385a297 100644 --- a/pkg/local_object_storage/metabase/counter_test.go +++ b/pkg/local_object_storage/metabase/counter_test.go @@ -22,7 +22,7 @@ func TestCounters(t *testing.T) { t.Run("defaults", func(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() c, err := db.ObjectCounters() require.NoError(t, err) require.Zero(t, c.Phy) @@ -37,7 +37,7 @@ func TestCounters(t *testing.T) { t.Run("put", func(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() oo := make([]*objectSDK.Object, 0, objCount) for range objCount { oo = append(oo, testutil.GenerateObject()) @@ -75,7 +75,7 @@ func TestCounters(t *testing.T) { t.Run("delete", func(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() oo := putObjs(t, db, objCount, false) exp := make(map[cid.ID]meta.ObjectCounters) @@ -120,7 +120,7 @@ func TestCounters(t *testing.T) { t.Run("inhume", func(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() oo := putObjs(t, db, objCount, false) exp := make(map[cid.ID]meta.ObjectCounters) @@ -185,7 +185,7 @@ func TestCounters(t *testing.T) { t.Run("put_split", func(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() parObj := testutil.GenerateObject() exp := make(map[cid.ID]meta.ObjectCounters) @@ -223,7 +223,7 @@ func TestCounters(t *testing.T) { t.Run("delete_split", func(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() oo := putObjs(t, db, objCount, true) exp := make(map[cid.ID]meta.ObjectCounters) @@ -265,7 +265,7 @@ func TestCounters(t *testing.T) { t.Run("inhume_split", func(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() oo := putObjs(t, db, objCount, true) exp := make(map[cid.ID]meta.ObjectCounters) @@ -329,7 +329,7 @@ func TestCounters(t *testing.T) { func TestDoublePut(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() obj := testutil.GenerateObject() exp := make(map[cid.ID]meta.ObjectCounters) @@ -387,7 +387,7 @@ func TestCounters_Expired(t *testing.T) { es := &epochState{epoch} db := newDB(t, meta.WithEpochState(es)) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() oo := make([]oid.Address, objCount) for i := range oo { diff --git a/pkg/local_object_storage/metabase/db_test.go b/pkg/local_object_storage/metabase/db_test.go index c61d762bc3..edaeb13c5c 100644 --- a/pkg/local_object_storage/metabase/db_test.go +++ b/pkg/local_object_storage/metabase/db_test.go @@ -61,7 +61,7 @@ func newDB(t testing.TB, opts ...meta.Option) *meta.DB { ) require.NoError(t, bdb.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, bdb.Init()) + require.NoError(t, bdb.Init(context.Background())) return bdb } diff --git a/pkg/local_object_storage/metabase/delete_ec_test.go b/pkg/local_object_storage/metabase/delete_ec_test.go index a256279904..9f1f91e144 100644 --- a/pkg/local_object_storage/metabase/delete_ec_test.go +++ b/pkg/local_object_storage/metabase/delete_ec_test.go @@ -30,8 +30,8 @@ func TestDeleteECObject_WithoutSplit(t *testing.T) { ) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) - defer func() { require.NoError(t, db.Close()) }() + require.NoError(t, db.Init(context.Background())) + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() ecChunk := oidtest.ID() @@ -194,8 +194,8 @@ func testDeleteECObjectWithSplit(t *testing.T, chunksCount int, withLinking bool ) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) - defer func() { require.NoError(t, db.Close()) }() + require.NoError(t, db.Init(context.Background())) + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() ecChunks := make([]oid.ID, chunksCount) diff --git a/pkg/local_object_storage/metabase/delete_meta_test.go b/pkg/local_object_storage/metabase/delete_meta_test.go index cdfe2a2031..0329e3a73a 100644 --- a/pkg/local_object_storage/metabase/delete_meta_test.go +++ b/pkg/local_object_storage/metabase/delete_meta_test.go @@ -23,8 +23,8 @@ func TestPutDeleteIndexAttributes(t *testing.T) { }...) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) - defer func() { require.NoError(t, db.Close()) }() + require.NoError(t, db.Init(context.Background())) + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() obj1 := testutil.GenerateObjectWithCID(cnr) diff --git a/pkg/local_object_storage/metabase/delete_test.go b/pkg/local_object_storage/metabase/delete_test.go index fe5f7833b9..c0762a377c 100644 --- a/pkg/local_object_storage/metabase/delete_test.go +++ b/pkg/local_object_storage/metabase/delete_test.go @@ -18,7 +18,7 @@ import ( func TestDB_Delete(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() parent := testutil.GenerateObjectWithCID(cnr) @@ -65,7 +65,7 @@ func TestDB_Delete(t *testing.T) { func TestDeleteAllChildren(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -103,7 +103,7 @@ func TestDeleteAllChildren(t *testing.T) { func TestGraveOnlyDelete(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() addr := oidtest.Address() @@ -116,7 +116,7 @@ func TestGraveOnlyDelete(t *testing.T) { func TestExpiredObject(t *testing.T) { db := newDB(t, meta.WithEpochState(epochState{currEpoch})) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() checkExpiredObjects(t, db, func(exp, nonExp *objectSDK.Object) { // removing expired object should be error-free @@ -128,7 +128,7 @@ func TestExpiredObject(t *testing.T) { func TestDelete(t *testing.T) { db := newDB(t, meta.WithEpochState(epochState{currEpoch})) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() for range 10 { @@ -170,7 +170,7 @@ func TestDelete(t *testing.T) { func TestDeleteDropsGCMarkIfObjectNotFound(t *testing.T) { db := newDB(t, meta.WithEpochState(epochState{currEpoch})) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() addr := oidtest.Address() diff --git a/pkg/local_object_storage/metabase/exists_test.go b/pkg/local_object_storage/metabase/exists_test.go index 1e4148eba0..3045e17f1b 100644 --- a/pkg/local_object_storage/metabase/exists_test.go +++ b/pkg/local_object_storage/metabase/exists_test.go @@ -1,6 +1,7 @@ package meta_test import ( + "context" "errors" "testing" @@ -18,7 +19,7 @@ const currEpoch = 1000 func TestDB_Exists(t *testing.T) { db := newDB(t, meta.WithEpochState(epochState{currEpoch})) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() t.Run("no object", func(t *testing.T) { nonExist := testutil.GenerateObject() diff --git a/pkg/local_object_storage/metabase/expired_test.go b/pkg/local_object_storage/metabase/expired_test.go index bb98745ee0..495c1eee76 100644 --- a/pkg/local_object_storage/metabase/expired_test.go +++ b/pkg/local_object_storage/metabase/expired_test.go @@ -13,7 +13,7 @@ import ( func TestDB_SelectExpired(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() containerID1 := cidtest.ID() diff --git a/pkg/local_object_storage/metabase/get_test.go b/pkg/local_object_storage/metabase/get_test.go index f0caaea705..c93d2c992b 100644 --- a/pkg/local_object_storage/metabase/get_test.go +++ b/pkg/local_object_storage/metabase/get_test.go @@ -25,7 +25,7 @@ import ( func TestDB_Get(t *testing.T) { db := newDB(t, meta.WithEpochState(epochState{currEpoch})) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() raw := testutil.GenerateObject() @@ -219,7 +219,7 @@ func benchmarkGet(b *testing.B, numOfObj int) { meta.WithMaxBatchSize(batchSize), meta.WithMaxBatchDelay(10*time.Millisecond), ) - defer func() { require.NoError(b, db.Close()) }() + defer func() { require.NoError(b, db.Close(context.Background())) }() addrs := make([]oid.Address, 0, numOfObj) for range numOfObj { @@ -253,7 +253,7 @@ func benchmarkGet(b *testing.B, numOfObj int) { }) }) - require.NoError(b, db.Close()) + require.NoError(b, db.Close(context.Background())) require.NoError(b, os.RemoveAll(b.Name())) db, addrs = prepareDb(1) diff --git a/pkg/local_object_storage/metabase/graveyard_test.go b/pkg/local_object_storage/metabase/graveyard_test.go index b9c6ce28ce..99794e609f 100644 --- a/pkg/local_object_storage/metabase/graveyard_test.go +++ b/pkg/local_object_storage/metabase/graveyard_test.go @@ -15,7 +15,7 @@ import ( func TestDB_IterateDeletedObjects_EmptyDB(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() var counter int var iterGravePRM meta.GraveyardIterationPrm @@ -42,7 +42,7 @@ func TestDB_IterateDeletedObjects_EmptyDB(t *testing.T) { func TestDB_Iterate_OffsetNotFound(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() obj1 := testutil.GenerateObject() obj2 := testutil.GenerateObject() @@ -113,7 +113,7 @@ func TestDB_Iterate_OffsetNotFound(t *testing.T) { func TestDB_IterateDeletedObjects(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() // generate and put 4 objects @@ -202,7 +202,7 @@ func TestDB_IterateDeletedObjects(t *testing.T) { func TestDB_IterateOverGraveyard_Offset(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() // generate and put 4 objects @@ -303,7 +303,7 @@ func TestDB_IterateOverGraveyard_Offset(t *testing.T) { func TestDB_IterateOverGarbage_Offset(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() // generate and put 4 objects obj1 := testutil.GenerateObject() @@ -395,7 +395,7 @@ func TestDB_IterateOverGarbage_Offset(t *testing.T) { func TestDB_DropGraves(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() // generate and put 2 objects diff --git a/pkg/local_object_storage/metabase/inhume_ec_test.go b/pkg/local_object_storage/metabase/inhume_ec_test.go index 32e412c795..1807132870 100644 --- a/pkg/local_object_storage/metabase/inhume_ec_test.go +++ b/pkg/local_object_storage/metabase/inhume_ec_test.go @@ -25,8 +25,8 @@ func TestInhumeECObject(t *testing.T) { ) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) - defer func() { require.NoError(t, db.Close()) }() + require.NoError(t, db.Init(context.Background())) + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() ecChunk := oidtest.ID() diff --git a/pkg/local_object_storage/metabase/inhume_test.go b/pkg/local_object_storage/metabase/inhume_test.go index 277316f7bd..786d10396b 100644 --- a/pkg/local_object_storage/metabase/inhume_test.go +++ b/pkg/local_object_storage/metabase/inhume_test.go @@ -17,7 +17,7 @@ import ( func TestDB_Inhume(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() raw := testutil.GenerateObject() testutil.AddAttribute(raw, "foo", "bar") @@ -37,7 +37,7 @@ func TestDB_Inhume(t *testing.T) { func TestInhumeTombOnTomb(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() var ( err error @@ -107,7 +107,7 @@ func TestInhumeTombOnTomb(t *testing.T) { func TestInhumeLocked(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() locked := oidtest.Address() diff --git a/pkg/local_object_storage/metabase/iterators_test.go b/pkg/local_object_storage/metabase/iterators_test.go index 646dc196ce..7eed32c55f 100644 --- a/pkg/local_object_storage/metabase/iterators_test.go +++ b/pkg/local_object_storage/metabase/iterators_test.go @@ -18,7 +18,7 @@ import ( func TestDB_IterateExpired(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() const epoch = 13 @@ -70,7 +70,7 @@ func putWithExpiration(t *testing.T, db *meta.DB, typ objectSDK.Type, expiresAt func TestDB_IterateCoveredByTombstones(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() ts := oidtest.Address() diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 203802ec0b..6f64630719 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -33,7 +33,7 @@ func listWithCursorPrepareDB(b *testing.B) *meta.DB { db := newDB(b, meta.WithMaxBatchSize(1), meta.WithBoltDBOptions(&bbolt.Options{ NoSync: true, })) // faster single-thread generation - defer func() { require.NoError(b, db.Close()) }() + defer func() { require.NoError(b, db.Close(context.Background())) }() obj := testutil.GenerateObject() for i := range 100_000 { // should be a multiple of all batch sizes @@ -71,7 +71,7 @@ func TestLisObjectsWithCursor(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() const ( containers = 5 @@ -163,7 +163,7 @@ func TestAddObjectDuringListingWithCursor(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() const total = 5 @@ -225,7 +225,7 @@ func TestIterateOver(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() const total uint64 = 5 for _, typ := range []objectSDK.Type{objectSDK.TypeRegular, objectSDK.TypeTombstone, objectSDK.TypeLock} { diff --git a/pkg/local_object_storage/metabase/lock_test.go b/pkg/local_object_storage/metabase/lock_test.go index 9601cb2bea..341ff9ad18 100644 --- a/pkg/local_object_storage/metabase/lock_test.go +++ b/pkg/local_object_storage/metabase/lock_test.go @@ -21,7 +21,7 @@ func TestDB_Lock(t *testing.T) { cnr := cidtest.ID() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() t.Run("empty locked list", func(t *testing.T) { require.Panics(t, func() { _ = db.Lock(context.Background(), cnr, oid.ID{}, nil) }) @@ -187,7 +187,7 @@ func TestDB_Lock_Expired(t *testing.T) { es := &epochState{e: 123} db := newDB(t, meta.WithEpochState(es)) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() // put an object addr := putWithExpiration(t, db, objectSDK.TypeRegular, 124) @@ -209,7 +209,7 @@ func TestDB_IsLocked(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() // existing and locked objs diff --git a/pkg/local_object_storage/metabase/mode.go b/pkg/local_object_storage/metabase/mode.go index f99262be47..ce6ae10047 100644 --- a/pkg/local_object_storage/metabase/mode.go +++ b/pkg/local_object_storage/metabase/mode.go @@ -18,7 +18,7 @@ func (db *DB) SetMode(ctx context.Context, m mode.Mode) error { } if !db.mode.NoMetabase() { - if err := db.Close(); err != nil { + if err := db.Close(ctx); err != nil { return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err) } } @@ -28,7 +28,7 @@ func (db *DB) SetMode(ctx context.Context, m mode.Mode) error { } else { err := db.openDB(ctx, m) if err == nil && !m.ReadOnly() { - err = db.Init() + err = db.Init(ctx) } if err != nil { return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err) diff --git a/pkg/local_object_storage/metabase/mode_test.go b/pkg/local_object_storage/metabase/mode_test.go index 1b9f60055d..28b42283f9 100644 --- a/pkg/local_object_storage/metabase/mode_test.go +++ b/pkg/local_object_storage/metabase/mode_test.go @@ -25,13 +25,13 @@ func Test_Mode(t *testing.T) { require.NoError(t, bdb.Open(context.Background(), mode.DegradedReadOnly)) require.Nil(t, bdb.boltDB) - require.NoError(t, bdb.Init()) + require.NoError(t, bdb.Init(context.Background())) require.Nil(t, bdb.boltDB) - require.NoError(t, bdb.Close()) + require.NoError(t, bdb.Close(context.Background())) require.NoError(t, bdb.Open(context.Background(), mode.Degraded)) require.Nil(t, bdb.boltDB) - require.NoError(t, bdb.Init()) + require.NoError(t, bdb.Init(context.Background())) require.Nil(t, bdb.boltDB) - require.NoError(t, bdb.Close()) + require.NoError(t, bdb.Close(context.Background())) } diff --git a/pkg/local_object_storage/metabase/put_test.go b/pkg/local_object_storage/metabase/put_test.go index 914f5ef065..f37ed4cf2f 100644 --- a/pkg/local_object_storage/metabase/put_test.go +++ b/pkg/local_object_storage/metabase/put_test.go @@ -46,7 +46,7 @@ func BenchmarkPut(b *testing.B) { db := newDB(b, meta.WithMaxBatchDelay(time.Millisecond*10), meta.WithMaxBatchSize(runtime.NumCPU())) - defer func() { require.NoError(b, db.Close()) }() + defer func() { require.NoError(b, db.Close(context.Background())) }() // Ensure the benchmark is bound by CPU and not waiting batch-delay time. b.SetParallelism(1) @@ -68,7 +68,7 @@ func BenchmarkPut(b *testing.B) { db := newDB(b, meta.WithMaxBatchDelay(time.Millisecond*10), meta.WithMaxBatchSize(1)) - defer func() { require.NoError(b, db.Close()) }() + defer func() { require.NoError(b, db.Close(context.Background())) }() var index atomic.Int64 index.Store(-1) objs := prepareObjects(b.N) @@ -84,7 +84,7 @@ func BenchmarkPut(b *testing.B) { func TestDB_PutBlobovniczaUpdate(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() raw1 := testutil.GenerateObject() storageID := []byte{1, 2, 3, 4} diff --git a/pkg/local_object_storage/metabase/reset_test.go b/pkg/local_object_storage/metabase/reset_test.go index 993079dcec..45faecc13f 100644 --- a/pkg/local_object_storage/metabase/reset_test.go +++ b/pkg/local_object_storage/metabase/reset_test.go @@ -30,9 +30,9 @@ func TestResetDropsContainerBuckets(t *testing.T) { ) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) + require.NoError(t, db.Init(context.Background())) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() for idx := range 100 { var putPrm PutPrm diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 6f48607be9..5cc9983117 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -38,7 +38,7 @@ func testSelectUserAttributes(t *testing.T, index bool) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -200,7 +200,7 @@ func TestDB_SelectRootPhyParent(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -354,7 +354,7 @@ func TestDB_SelectInhume(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -385,7 +385,7 @@ func TestDB_SelectPayloadHash(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -456,7 +456,7 @@ func TestDB_SelectWithSlowFilters(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -564,7 +564,7 @@ func TestDB_SelectObjectID(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -680,7 +680,7 @@ func TestDB_SelectOwnerID(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -786,7 +786,7 @@ func TestDB_SelectECWithFastAndSlowFilters(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() ecChunk1 := oidtest.ID() @@ -865,7 +865,7 @@ func TestDB_RawHead_SplitInfo(t *testing.T) { ) db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -906,7 +906,7 @@ func testGetRawSplitInfo(t *testing.T, cnr cidSDK.ID, ids *transformer.AccessIde t.Run("first last, then linking", func(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() require.NoError(t, metaPut(db, lastPart, nil)) require.NoError(t, metaPut(db, linking, nil)) @@ -930,7 +930,7 @@ func testGetRawSplitInfo(t *testing.T, cnr cidSDK.ID, ids *transformer.AccessIde }) t.Run("first linking, then last", func(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() require.NoError(t, metaPut(db, linking, nil)) require.NoError(t, metaPut(db, lastPart, nil)) @@ -954,7 +954,7 @@ func testGetRawSplitInfo(t *testing.T, cnr cidSDK.ID, ids *transformer.AccessIde }) t.Run("only last part", func(t *testing.T) { db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() require.NoError(t, metaPut(db, lastPart, nil)) @@ -984,7 +984,7 @@ func TestDB_SelectSplitID_EC(t *testing.T) { ) db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -1052,7 +1052,7 @@ func TestDB_SelectSplitID(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -1109,7 +1109,7 @@ func TestDB_SelectContainerID(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() cnr := cidtest.ID() @@ -1157,7 +1157,7 @@ func TestDB_SelectContainerID(t *testing.T) { func BenchmarkSelect(b *testing.B) { const objCount = 1000 db := newDB(b) - defer func() { require.NoError(b, db.Close()) }() + defer func() { require.NoError(b, db.Close(context.Background())) }() cid := cidtest.ID() @@ -1199,7 +1199,7 @@ func TestExpiredObjects(t *testing.T) { t.Parallel() db := newDB(t, meta.WithEpochState(epochState{currEpoch})) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() checkExpiredObjects(t, db, func(exp, nonExp *objectSDK.Object) { cidExp, _ := exp.ContainerID() diff --git a/pkg/local_object_storage/metabase/storage_id_test.go b/pkg/local_object_storage/metabase/storage_id_test.go index a86e42bd25..fef680159a 100644 --- a/pkg/local_object_storage/metabase/storage_id_test.go +++ b/pkg/local_object_storage/metabase/storage_id_test.go @@ -15,7 +15,7 @@ func TestDB_StorageID(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() raw1 := testutil.GenerateObject() raw2 := testutil.GenerateObject() @@ -79,7 +79,7 @@ func TestPutWritecacheDataRace(t *testing.T) { t.Parallel() db := newDB(t) - defer func() { require.NoError(t, db.Close()) }() + defer func() { require.NoError(t, db.Close(context.Background())) }() putStorageID := []byte{1, 2, 3} wcStorageID := []byte{1, 2, 3, 4, 5} diff --git a/pkg/local_object_storage/metabase/upgrade_test.go b/pkg/local_object_storage/metabase/upgrade_test.go index e2eee86b07..5444264be4 100644 --- a/pkg/local_object_storage/metabase/upgrade_test.go +++ b/pkg/local_object_storage/metabase/upgrade_test.go @@ -34,12 +34,12 @@ func TestUpgradeV2ToV3(t *testing.T) { }() db := New(WithPath(path), WithEpochState(epochState{e: 1000}), WithLogger(test.NewLogger(t))) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.ErrorIs(t, db.Init(), ErrOutdatedVersion) - require.NoError(t, db.Close()) + require.ErrorIs(t, db.Init(context.Background()), ErrOutdatedVersion) + require.NoError(t, db.Close(context.Background())) require.NoError(t, Upgrade(context.Background(), path, true, &testContainerInfoProvider{}, t.Log)) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) - require.NoError(t, db.Close()) + require.NoError(t, db.Init(context.Background())) + require.NoError(t, db.Close(context.Background())) fmt.Println() } @@ -87,7 +87,7 @@ func TestGenerateMetabaseFile(t *testing.T) { require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) db.boltDB.AllocSize = allocSize db.boltDB.NoSync = true - require.NoError(t, db.Init()) + require.NoError(t, db.Init(context.Background())) containers := make([]cid.ID, containersCount) for i := range containers { containers[i] = cidtest.ID() @@ -218,5 +218,5 @@ func TestGenerateMetabaseFile(t *testing.T) { require.NoError(t, eg.Wait()) db.log.Info(ctx, "simple objects locked by locks generated") require.NoError(t, db.boltDB.Sync()) - require.NoError(t, db.Close()) + require.NoError(t, db.Close(context.Background())) } diff --git a/pkg/local_object_storage/metabase/version_test.go b/pkg/local_object_storage/metabase/version_test.go index 509e72479e..b373fb32ed 100644 --- a/pkg/local_object_storage/metabase/version_test.go +++ b/pkg/local_object_storage/metabase/version_test.go @@ -45,15 +45,15 @@ func TestVersion(t *testing.T) { t.Run("simple", func(t *testing.T) { db := newDB(t) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) + require.NoError(t, db.Init(context.Background())) check(t, db) - require.NoError(t, db.Close()) + require.NoError(t, db.Close(context.Background())) t.Run("reopen", func(t *testing.T) { require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) + require.NoError(t, db.Init(context.Background())) check(t, db) - require.NoError(t, db.Close()) + require.NoError(t, db.Close(context.Background())) }) }) t.Run("old data", func(t *testing.T) { @@ -61,9 +61,9 @@ func TestVersion(t *testing.T) { require.NoError(t, db.SetShardID(context.Background(), []byte{1, 2, 3, 4}, mode.ReadWrite)) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) + require.NoError(t, db.Init(context.Background())) check(t, db) - require.NoError(t, db.Close()) + require.NoError(t, db.Close(context.Background())) }) t.Run("invalid version", func(t *testing.T) { db := newDB(t) @@ -71,37 +71,37 @@ func TestVersion(t *testing.T) { require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error { return updateVersion(tx, version+1) })) - require.NoError(t, db.Close()) + require.NoError(t, db.Close(context.Background())) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.Error(t, db.Init()) - require.NoError(t, db.Close()) + require.Error(t, db.Init(context.Background())) + require.NoError(t, db.Close(context.Background())) t.Run("reset", func(t *testing.T) { require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.Reset()) check(t, db) - require.NoError(t, db.Close()) + require.NoError(t, db.Close(context.Background())) }) }) t.Run("incompleted upgrade", func(t *testing.T) { db := newDB(t) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, db.Init()) - require.NoError(t, db.Close()) + require.NoError(t, db.Init(context.Background())) + require.NoError(t, db.Close(context.Background())) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error { return tx.Bucket(shardInfoBucket).Put(upgradeKey, zeroValue) })) - require.ErrorIs(t, db.Init(), ErrIncompletedUpgrade) - require.NoError(t, db.Close()) + require.ErrorIs(t, db.Init(context.Background()), ErrIncompletedUpgrade) + require.NoError(t, db.Close(context.Background())) require.NoError(t, db.Open(context.Background(), mode.ReadWrite)) require.NoError(t, db.boltDB.Update(func(tx *bbolt.Tx) error { return tx.Bucket(shardInfoBucket).Delete(upgradeKey) })) - require.NoError(t, db.Init()) - require.NoError(t, db.Close()) + require.NoError(t, db.Init(context.Background())) + require.NoError(t, db.Close(context.Background())) }) } diff --git a/pkg/local_object_storage/pilorama/bench_test.go b/pkg/local_object_storage/pilorama/bench_test.go index 22b951a410..3156751f2c 100644 --- a/pkg/local_object_storage/pilorama/bench_test.go +++ b/pkg/local_object_storage/pilorama/bench_test.go @@ -28,8 +28,8 @@ func BenchmarkCreate(b *testing.B) { WithPath(filepath.Join(tmpDir, "test.db")), WithMaxBatchSize(runtime.GOMAXPROCS(0))) require.NoError(b, f.Open(context.Background(), mode.ReadWrite)) - require.NoError(b, f.Init()) - defer func() { require.NoError(b, f.Close()) }() + require.NoError(b, f.Init(context.Background())) + defer func() { require.NoError(b, f.Close(context.Background())) }() b.Cleanup(func() { require.NoError(b, os.RemoveAll(tmpDir)) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 9ffcf1e83a..c62d728b1f 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -91,7 +91,7 @@ func NewBoltForest(opts ...Option) ForestStorage { return &b } -func (t *boltForest) SetMode(_ context.Context, m mode.Mode) error { +func (t *boltForest) SetMode(ctx context.Context, m mode.Mode) error { t.modeMtx.Lock() defer t.modeMtx.Unlock() @@ -99,10 +99,10 @@ func (t *boltForest) SetMode(_ context.Context, m mode.Mode) error { return nil } - err := t.Close() + err := t.Close(ctx) if err == nil && !m.NoMetabase() { if err = t.openBolt(m); err == nil { - err = t.Init() + err = t.Init(ctx) } } if err != nil { @@ -148,7 +148,7 @@ func (t *boltForest) openBolt(m mode.Mode) error { return nil } -func (t *boltForest) Init() error { +func (t *boltForest) Init(context.Context) error { if t.mode.NoMetabase() || t.db.IsReadOnly() { return nil } @@ -162,7 +162,7 @@ func (t *boltForest) Init() error { }) } -func (t *boltForest) Close() error { +func (t *boltForest) Close(context.Context) error { var err error if t.db != nil { err = t.db.Close() diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index 76da1c0c24..f31504e2b1 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -120,7 +120,7 @@ func (f *memoryForest) TreeApplyBatch(ctx context.Context, cnr cid.ID, treeID st return nil } -func (f *memoryForest) Init() error { +func (f *memoryForest) Init(context.Context) error { return nil } @@ -132,7 +132,7 @@ func (f *memoryForest) SetMode(context.Context, mode.Mode) error { return nil } -func (f *memoryForest) Close() error { +func (f *memoryForest) Close(context.Context) error { return nil } func (f *memoryForest) SetParentID(string) {} diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index fbcc53fb30..de56fc82be 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -30,7 +30,7 @@ var providers = []struct { {"inmemory", func(t testing.TB, _ ...Option) ForestStorage { f := NewMemoryForest() require.NoError(t, f.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, f.Init()) + require.NoError(t, f.Init(context.Background())) return f }}, {"bbolt", func(t testing.TB, opts ...Option) ForestStorage { @@ -40,7 +40,7 @@ var providers = []struct { WithMaxBatchSize(1), }, opts...)...) require.NoError(t, f.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, f.Init()) + require.NoError(t, f.Init(context.Background())) return f }}, } @@ -61,7 +61,7 @@ func TestForest_TreeMove(t *testing.T) { } func testForestTreeMove(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} @@ -125,7 +125,7 @@ func TestMemoryForest_TreeGetChildren(t *testing.T) { } func testForestTreeGetChildren(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} @@ -247,7 +247,7 @@ func TestForest_TreeSortedIterationBugWithSkip(t *testing.T) { } func testForestTreeSortedIterationBugWithSkip(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} @@ -302,7 +302,7 @@ func TestForest_TreeSortedIteration(t *testing.T) { } func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} @@ -361,7 +361,7 @@ func TestForest_TreeSortedFilename(t *testing.T) { } func testForestTreeSortedByFilename(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() const controlAttr = "control_attr" cid := cidtest.ID() @@ -453,7 +453,7 @@ func TestForest_TreeDrop(t *testing.T) { } func testForestTreeDrop(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() const cidsSize = 3 var cids [cidsSize]cidSDK.ID @@ -523,7 +523,7 @@ func TestForest_TreeAdd(t *testing.T) { } func testForestTreeAdd(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} @@ -571,7 +571,7 @@ func TestForest_TreeAddByPath(t *testing.T) { } func testForestTreeAddByPath(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() cid := cidtest.ID() d := CIDDescriptor{cid, 0, 1} @@ -709,7 +709,7 @@ func testForestTreeApply(t *testing.T, constructor func(t testing.TB, _ ...Optio t.Run("add a child, then insert a parent removal", func(t *testing.T) { s := constructor(t) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() testApply(t, s, 10, 0, Meta{Time: 1, Items: []KeyValue{{"grand", []byte{1}}}}) @@ -722,7 +722,7 @@ func testForestTreeApply(t *testing.T, constructor func(t testing.TB, _ ...Optio }) t.Run("add a child to non-existent parent, then add a parent", func(t *testing.T) { s := constructor(t) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() meta := Meta{Time: 1, Items: []KeyValue{{"child", []byte{3}}}} testApply(t, s, 11, 10, meta) @@ -792,7 +792,7 @@ func testForestApplySameOperation(t *testing.T, constructor func(t testing.TB, _ t.Run("expected", func(t *testing.T) { s := constructor(t) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() for i := range logs { require.NoError(t, s.TreeApply(ctx, cid, treeID, &logs[i], false)) @@ -801,7 +801,7 @@ func testForestApplySameOperation(t *testing.T, constructor func(t testing.TB, _ }) s := constructor(t, WithMaxBatchSize(batchSize)) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() require.NoError(t, s.TreeApply(ctx, cid, treeID, &logs[0], false)) for range batchSize { @@ -842,7 +842,7 @@ func testForestTreeGetOpLog(t *testing.T, constructor func(t testing.TB, _ ...Op } s := constructor(t) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() t.Run("empty log, no panic", func(t *testing.T) { _, err := s.TreeGetOpLog(context.Background(), cid, treeID, 0) @@ -883,7 +883,7 @@ func TestForest_TreeExists(t *testing.T) { func testForestTreeExists(t *testing.T, constructor func(t testing.TB, opts ...Option) ForestStorage) { s := constructor(t) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() checkExists := func(t *testing.T, expected bool, cid cidSDK.ID, treeID string) { actual, err := s.TreeExists(context.Background(), cid, treeID) @@ -942,7 +942,7 @@ func TestApplyTricky1(t *testing.T) { for i := range providers { t.Run(providers[i].name, func(t *testing.T) { s := providers[i].construct(t) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() for i := range ops { require.NoError(t, s.TreeApply(context.Background(), cid, treeID, &ops[i], false)) @@ -1005,7 +1005,7 @@ func TestApplyTricky2(t *testing.T) { for i := range providers { t.Run(providers[i].name, func(t *testing.T) { s := providers[i].construct(t) - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() for i := range ops { require.NoError(t, s.TreeApply(context.Background(), cid, treeID, &ops[i], false)) @@ -1115,7 +1115,7 @@ func testForestTreeParallelApply(t *testing.T, constructor func(t testing.TB, _ treeID := "version" expected := constructor(t, WithNoSync(true)) - defer func() { require.NoError(t, expected.Close()) }() + defer func() { require.NoError(t, expected.Close(context.Background())) }() for i := range ops { require.NoError(t, expected.TreeApply(context.Background(), cid, treeID, &ops[i], false)) @@ -1145,7 +1145,7 @@ func testForestTreeParallelApply(t *testing.T, constructor func(t testing.TB, _ wg.Wait() compareForests(t, expected, actual, cid, treeID, nodeCount) - require.NoError(t, actual.Close()) + require.NoError(t, actual.Close(context.Background())) } } @@ -1163,7 +1163,7 @@ func testForestTreeApplyRandom(t *testing.T, constructor func(t testing.TB, _ .. treeID := "version" expected := constructor(t, WithNoSync(true)) - defer func() { require.NoError(t, expected.Close()) }() + defer func() { require.NoError(t, expected.Close(context.Background())) }() for i := range ops { require.NoError(t, expected.TreeApply(context.Background(), cid, treeID, &ops[i], false)) @@ -1179,7 +1179,7 @@ func testForestTreeApplyRandom(t *testing.T, constructor func(t testing.TB, _ .. require.NoError(t, actual.TreeApply(context.Background(), cid, treeID, &ops[i], false)) } compareForests(t, expected, actual, cid, treeID, nodeCount) - require.NoError(t, actual.Close()) + require.NoError(t, actual.Close(context.Background())) } } @@ -1197,7 +1197,7 @@ func BenchmarkApplySequential(b *testing.B) { b.Run("batchsize="+strconv.Itoa(bs), func(b *testing.B) { r := mrand.New(mrand.NewSource(time.Now().Unix())) s := providers[i].construct(b, WithMaxBatchSize(bs)) - defer func() { require.NoError(b, s.Close()) }() + defer func() { require.NoError(b, s.Close(context.Background())) }() benchmarkApply(b, s, func(opCount int) []Move { ops := make([]Move, opCount) @@ -1233,7 +1233,7 @@ func BenchmarkApplyReorderLast(b *testing.B) { b.Run("batchsize="+strconv.Itoa(bs), func(b *testing.B) { r := mrand.New(mrand.NewSource(time.Now().Unix())) s := providers[i].construct(b, WithMaxBatchSize(bs)) - defer func() { require.NoError(b, s.Close()) }() + defer func() { require.NoError(b, s.Close(context.Background())) }() benchmarkApply(b, s, func(opCount int) []Move { ops := make([]Move, opCount) @@ -1290,7 +1290,7 @@ func TestTreeGetByPath(t *testing.T) { } func testTreeGetByPath(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() cid := cidtest.ID() treeID := "version" @@ -1369,7 +1369,7 @@ func TestGetTrees(t *testing.T) { } func testTreeGetTrees(t *testing.T, s ForestStorage) { - defer func() { require.NoError(t, s.Close()) }() + defer func() { require.NoError(t, s.Close(context.Background())) }() cids := []cidSDK.ID{cidtest.ID(), cidtest.ID()} d := CIDDescriptor{Position: 0, Size: 1} @@ -1415,7 +1415,7 @@ func TestTreeLastSyncHeight(t *testing.T) { } func testTreeLastSyncHeight(t *testing.T, f ForestStorage) { - defer func() { require.NoError(t, f.Close()) }() + defer func() { require.NoError(t, f.Close(context.Background())) }() cnr := cidtest.ID() treeID := "someTree" diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index 9717b2401e..1f7e742a21 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -62,9 +62,9 @@ type Forest interface { type ForestStorage interface { // DumpInfo returns information about the pilorama. DumpInfo() Info - Init() error + Init(context.Context) error Open(context.Context, mode.Mode) error - Close() error + Close(context.Context) error SetMode(context.Context, mode.Mode) error SetParentID(id string) Forest diff --git a/pkg/local_object_storage/pilorama/mode_test.go b/pkg/local_object_storage/pilorama/mode_test.go index 01d3da9f0b..0c042aa562 100644 --- a/pkg/local_object_storage/pilorama/mode_test.go +++ b/pkg/local_object_storage/pilorama/mode_test.go @@ -19,13 +19,13 @@ func Test_Mode(t *testing.T) { require.NoError(t, f.Open(context.Background(), mode.DegradedReadOnly)) require.Nil(t, f.(*boltForest).db) - require.NoError(t, f.Init()) + require.NoError(t, f.Init(context.Background())) require.Nil(t, f.(*boltForest).db) - require.NoError(t, f.Close()) + require.NoError(t, f.Close(context.Background())) require.NoError(t, f.Open(context.Background(), mode.Degraded)) require.Nil(t, f.(*boltForest).db) - require.NoError(t, f.Init()) + require.NoError(t, f.Init(context.Background())) require.Nil(t, f.(*boltForest).db) - require.NoError(t, f.Close()) + require.NoError(t, f.Close(context.Background())) } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 056737a9d9..5a9e261551 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -91,8 +91,8 @@ func (s *Shard) Open(ctx context.Context) error { type metabaseSynchronizer Shard -func (x *metabaseSynchronizer) Init() error { - ctx, span := tracing.StartSpanFromContext(context.TODO(), "metabaseSynchronizer.Init") +func (x *metabaseSynchronizer) Init(ctx context.Context) error { + ctx, span := tracing.StartSpanFromContext(ctx, "metabaseSynchronizer.Init") defer span.End() return (*Shard)(x).refillMetabase(ctx) @@ -140,7 +140,7 @@ func (s *Shard) Init(ctx context.Context) error { func (s *Shard) initializeComponents(ctx context.Context, m mode.Mode) error { type initializer interface { - Init() error + Init(context.Context) error } var components []initializer @@ -170,7 +170,7 @@ func (s *Shard) initializeComponents(ctx context.Context, m mode.Mode) error { } for _, component := range components { - if err := component.Init(); err != nil { + if err := component.Init(ctx); err != nil { if component == s.metaBase { if errors.Is(err, meta.ErrOutdatedVersion) || errors.Is(err, meta.ErrIncompletedUpgrade) { return fmt.Errorf("metabase initialization: %w", err) @@ -368,7 +368,7 @@ func (s *Shard) Close(ctx context.Context) error { if s.rb != nil { s.rb.Stop(ctx, s.log) } - var components []interface{ Close() error } + var components []interface{ Close(context.Context) error } if s.pilorama != nil { components = append(components, s.pilorama) @@ -384,7 +384,7 @@ func (s *Shard) Close(ctx context.Context) error { var lastErr error for _, component := range components { - if err := component.Close(); err != nil { + if err := component.Close(ctx); err != nil { lastErr = err s.log.Error(ctx, logs.ShardCouldNotCloseShardComponent, zap.Error(err)) } @@ -392,7 +392,7 @@ func (s *Shard) Close(ctx context.Context) error { // If Init/Open was unsuccessful gc can be nil. if s.gc != nil { - s.gc.stop() + s.gc.stop(ctx) } return lastErr @@ -437,7 +437,7 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { // config after the node was updated. err = s.refillMetabase(ctx) } else { - err = s.metaBase.Init() + err = s.metaBase.Init(ctx) } if err != nil { s.log.Error(ctx, logs.ShardCantInitializeMetabaseMoveToADegradedreadonlyMode, zap.Error(err)) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 6fabf7103e..a987d3d14d 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -213,7 +213,7 @@ func (gc *gc) handleEvent(ctx context.Context, event Event) { } } -func (gc *gc) releaseResources() { +func (gc *gc) releaseResources(ctx context.Context) { if gc.workerPool != nil { gc.workerPool.Release() } @@ -222,7 +222,7 @@ func (gc *gc) releaseResources() { // because it is possible that we are close it earlier than stop writing. // It is ok to keep it opened. - gc.log.Debug(context.Background(), logs.ShardGCIsStopped) + gc.log.Debug(ctx, logs.ShardGCIsStopped) } func (gc *gc) tickRemover(ctx context.Context) { @@ -236,10 +236,10 @@ func (gc *gc) tickRemover(ctx context.Context) { case <-ctx.Done(): // Context canceled earlier than we start to close shards. // It make sense to stop collecting garbage by context too. - gc.releaseResources() + gc.releaseResources(ctx) return case <-gc.stopChannel: - gc.releaseResources() + gc.releaseResources(ctx) return case <-timer.C: startedAt := time.Now() @@ -258,12 +258,12 @@ func (gc *gc) tickRemover(ctx context.Context) { } } -func (gc *gc) stop() { +func (gc *gc) stop(ctx context.Context) { gc.onceStop.Do(func() { close(gc.stopChannel) }) - gc.log.Info(context.Background(), logs.ShardWaitingForGCWorkersToStop) + gc.log.Info(ctx, logs.ShardWaitingForGCWorkersToStop) gc.wg.Wait() } @@ -730,14 +730,14 @@ func (s *Shard) inhumeUnlockedIfExpired(ctx context.Context, epoch uint64, unloc } // HandleDeletedLocks unlocks all objects which were locked by lockers. -func (s *Shard) HandleDeletedLocks(lockers []oid.Address) { +func (s *Shard) HandleDeletedLocks(ctx context.Context, lockers []oid.Address) { if s.GetMode().NoMetabase() { return } _, err := s.metaBase.FreeLockedBy(lockers) if err != nil { - s.log.Warn(context.Background(), logs.ShardFailureToUnlockObjects, + s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, zap.String("error", err.Error()), ) diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 39073a529a..9998bbae2d 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -61,8 +61,8 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { meta.WithEpochState(epochState{}), ), WithPiloramaOptions(pilorama.WithPath(filepath.Join(rootPath, "pilorama"))), - WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { - sh.HandleDeletedLocks(addresses) + WithDeletedLockCallback(func(ctx context.Context, addresses []oid.Address) { + sh.HandleDeletedLocks(ctx, addresses) }), WithExpiredLocksCallback(func(ctx context.Context, epoch uint64, a []oid.Address) { sh.HandleExpiredLocks(ctx, epoch, a) diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index 7da8b8c284..5caf3641ff 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -53,8 +53,8 @@ func TestShard_Lock(t *testing.T) { meta.WithPath(filepath.Join(rootPath, "meta")), meta.WithEpochState(epochState{}), ), - WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { - sh.HandleDeletedLocks(addresses) + WithDeletedLockCallback(func(ctx context.Context, addresses []oid.Address) { + sh.HandleDeletedLocks(ctx, addresses) }), } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 3a06fe8a7a..1eb7f14d02 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -95,7 +95,7 @@ type cfg struct { metricsWriter MetricsWriter - reportErrorFunc func(selfID string, message string, err error) + reportErrorFunc func(ctx context.Context, selfID string, message string, err error) containerInfo container.InfoProvider } @@ -105,7 +105,7 @@ func defaultCfg() *cfg { rmBatchSize: 100, log: logger.NewLoggerWrapper(zap.L()), gcCfg: defaultGCCfg(), - reportErrorFunc: func(string, string, error) {}, + reportErrorFunc: func(context.Context, string, string, error) {}, zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, zeroCountContainersCallback: func(context.Context, []cid.ID) {}, metricsWriter: noopMetrics{}, @@ -130,8 +130,8 @@ func New(opts ...Option) *Shard { tsSource: c.tsSource, } - reportFunc := func(msg string, err error) { - s.reportErrorFunc(s.ID().String(), msg, err) + reportFunc := func(ctx context.Context, msg string, err error) { + s.reportErrorFunc(ctx, s.ID().String(), msg, err) } s.blobStor.SetReportErrorFunc(reportFunc) @@ -317,7 +317,7 @@ func WithGCMetrics(v GCMectrics) Option { // WithReportErrorFunc returns option to specify callback for handling storage-related errors // in the background workers. -func WithReportErrorFunc(f func(selfID string, message string, err error)) Option { +func WithReportErrorFunc(f func(ctx context.Context, selfID string, message string, err error)) Option { return func(c *cfg) { c.reportErrorFunc = f } diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index 73ba2e82b1..f9ee34488b 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -89,8 +89,8 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard WithPiloramaOptions(pilorama.WithPath(filepath.Join(o.rootPath, "pilorama"))), WithWriteCache(enableWriteCache), WithWriteCacheOptions(o.wcOpts), - WithDeletedLockCallback(func(_ context.Context, addresses []oid.Address) { - sh.HandleDeletedLocks(addresses) + WithDeletedLockCallback(func(ctx context.Context, addresses []oid.Address) { + sh.HandleDeletedLocks(ctx, addresses) }), WithExpiredLocksCallback(func(ctx context.Context, epoch uint64, a []oid.Address) { sh.HandleExpiredLocks(ctx, epoch, a) diff --git a/pkg/local_object_storage/writecache/benchmark/writecache_test.go b/pkg/local_object_storage/writecache/benchmark/writecache_test.go index 79ab7d9c6b..fd85b4501a 100644 --- a/pkg/local_object_storage/writecache/benchmark/writecache_test.go +++ b/pkg/local_object_storage/writecache/benchmark/writecache_test.go @@ -43,12 +43,12 @@ func BenchmarkWriteAfterDelete(b *testing.B) { b.SetParallelism(parallel) benchmarkRunPar(b, cache, payloadSize) }) - require.NoError(b, cache.Close()) + require.NoError(b, cache.Close(context.Background())) } func benchmarkPutSeq(b *testing.B, cache writecache.Cache, size uint64) { benchmarkPutPrepare(b, cache) - defer func() { require.NoError(b, cache.Close()) }() + defer func() { require.NoError(b, cache.Close(context.Background())) }() ctx := context.Background() objGen := testutil.RandObjGenerator{ObjSize: size} @@ -71,7 +71,7 @@ func benchmarkPutSeq(b *testing.B, cache writecache.Cache, size uint64) { func benchmarkPutPar(b *testing.B, cache writecache.Cache, size uint64) { benchmarkPutPrepare(b, cache) - defer func() { require.NoError(b, cache.Close()) }() + defer func() { require.NoError(b, cache.Close(context.Background())) }() benchmarkRunPar(b, cache, size) } @@ -100,7 +100,7 @@ func benchmarkRunPar(b *testing.B, cache writecache.Cache, size uint64) { func benchmarkPutPrepare(b *testing.B, cache writecache.Cache) { require.NoError(b, cache.Open(context.Background(), mode.ReadWrite), "opening") - require.NoError(b, cache.Init(), "initializing") + require.NoError(b, cache.Init(context.Background()), "initializing") } type testMetabase struct{} diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index 098872e08a..e829d013cc 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -98,19 +98,19 @@ func (c *cache) Open(_ context.Context, mod mode.Mode) error { } // Init runs necessary services. -func (c *cache) Init() error { +func (c *cache) Init(ctx context.Context) error { c.metrics.SetMode(mode.ConvertToComponentModeDegraded(c.mode)) - if err := c.flushAndDropBBoltDB(context.Background()); err != nil { + if err := c.flushAndDropBBoltDB(ctx); err != nil { return fmt.Errorf("flush previous version write-cache database: %w", err) } - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancel(context.WithoutCancel(ctx)) // canceling performed by cache c.cancel.Store(cancel) c.runFlushLoop(ctx) return nil } // Close closes db connection and stops services. Executes ObjectCounters.FlushAndClose op. -func (c *cache) Close() error { +func (c *cache) Close(ctx context.Context) error { if cancelValue := c.cancel.Swap(dummyCanceler); cancelValue != nil { cancelValue.(context.CancelFunc)() } @@ -127,7 +127,7 @@ func (c *cache) Close() error { var err error if c.fsTree != nil { - err = c.fsTree.Close() + err = c.fsTree.Close(ctx) if err != nil { c.fsTree = nil } diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 123eb4abc6..d9e34ceab2 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -112,7 +112,7 @@ func (c *cache) flushIfAnObjectExistsWorker(ctx context.Context, objInfo objectI }) if err != nil { if !client.IsErrObjectNotFound(err) { - c.reportFlushError(logs.WritecacheCantGetObject, objInfo.addr.EncodeToString(), metaerr.Wrap(err)) + c.reportFlushError(ctx, logs.WritecacheCantGetObject, objInfo.addr.EncodeToString(), metaerr.Wrap(err)) } return } @@ -126,11 +126,11 @@ func (c *cache) flushIfAnObjectExistsWorker(ctx context.Context, objInfo objectI c.deleteFromDisk(ctx, objInfo.addr, uint64(len(res.RawData))) } -func (c *cache) reportFlushError(msg string, addr string, err error) { +func (c *cache) reportFlushError(ctx context.Context, msg string, addr string, err error) { if c.reportError != nil { - c.reportError(msg, err) + c.reportError(ctx, msg, err) } else { - c.log.Error(context.Background(), msg, + c.log.Error(ctx, msg, zap.String("address", addr), zap.Error(err)) } @@ -145,7 +145,7 @@ func (c *cache) flushFSTree(ctx context.Context, ignoreErrors bool) error { var obj objectSDK.Object err := obj.Unmarshal(e.ObjectData) if err != nil { - c.reportFlushError(logs.FSTreeCantUnmarshalObject, sAddr, metaerr.Wrap(err)) + c.reportFlushError(ctx, logs.FSTreeCantUnmarshalObject, sAddr, metaerr.Wrap(err)) if ignoreErrors { return nil } @@ -183,7 +183,7 @@ func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []b if err != nil { if !errors.Is(err, common.ErrNoSpace) && !errors.Is(err, common.ErrReadOnly) && !errors.Is(err, blobstor.ErrNoPlaceFound) { - c.reportFlushError(logs.FSTreeCantFushObjectBlobstor, + c.reportFlushError(ctx, logs.FSTreeCantFushObjectBlobstor, addr.EncodeToString(), err) } return err @@ -195,7 +195,7 @@ func (c *cache) flushObject(ctx context.Context, obj *objectSDK.Object, data []b _, err = c.metabase.UpdateStorageID(ctx, updPrm) if err != nil { - c.reportFlushError(logs.FSTreeCantUpdateID, + c.reportFlushError(ctx, logs.FSTreeCantUpdateID, addr.EncodeToString(), err) } return err diff --git a/pkg/local_object_storage/writecache/flush_test.go b/pkg/local_object_storage/writecache/flush_test.go index 92fb493e0b..7fc84657c0 100644 --- a/pkg/local_object_storage/writecache/flush_test.go +++ b/pkg/local_object_storage/writecache/flush_test.go @@ -38,9 +38,9 @@ func TestFlush(t *testing.T) { errCountOpt := func() (Option, *atomic.Uint32) { cnt := &atomic.Uint32{} - return WithReportErrorFunc(func(msg string, err error) { + return WithReportErrorFunc(func(ctx context.Context, msg string, err error) { cnt.Add(1) - testlogger.Warn(context.Background(), msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) + testlogger.Warn(ctx, msg, zap.Uint32("error_count", cnt.Load()), zap.Error(err)) }), cnt } @@ -114,7 +114,7 @@ func runFlushTest[Option any]( ) { t.Run("no errors", func(t *testing.T) { wc, bs, mb := newCache(t, createCacheFn) - defer func() { require.NoError(t, wc.Close()) }() + defer func() { require.NoError(t, wc.Close(context.Background())) }() objects := putObjects(t, wc) require.NoError(t, bs.SetMode(context.Background(), mode.ReadWrite)) @@ -127,7 +127,7 @@ func runFlushTest[Option any]( t.Run("flush on moving to degraded mode", func(t *testing.T) { wc, bs, mb := newCache(t, createCacheFn) - defer func() { require.NoError(t, wc.Close()) }() + defer func() { require.NoError(t, wc.Close(context.Background())) }() objects := putObjects(t, wc) // Blobstor is read-only, so we expect en error from `flush` here. @@ -145,7 +145,7 @@ func runFlushTest[Option any]( t.Run(f.Desc, func(t *testing.T) { errCountOpt, errCount := errCountOption() wc, bs, mb := newCache(t, createCacheFn, errCountOpt) - defer func() { require.NoError(t, wc.Close()) }() + defer func() { require.NoError(t, wc.Close(context.Background())) }() objects := putObjects(t, wc) f.InjectFn(t, wc) @@ -173,7 +173,7 @@ func newCache[Option any]( meta.WithPath(filepath.Join(dir, "meta")), meta.WithEpochState(dummyEpoch{})) require.NoError(t, mb.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, mb.Init()) + require.NoError(t, mb.Init(context.Background())) bs := blobstor.New(blobstor.WithStorages([]blobstor.SubStorage{ { @@ -184,11 +184,11 @@ func newCache[Option any]( }, })) require.NoError(t, bs.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, bs.Init()) + require.NoError(t, bs.Init(context.Background())) wc := createCacheFn(t, mb, bs, opts...) require.NoError(t, wc.Open(context.Background(), mode.ReadWrite)) - require.NoError(t, wc.Init()) + require.NoError(t, wc.Init(context.Background())) // First set mode for metabase and blobstor to prevent background flushes. require.NoError(t, mb.SetMode(context.Background(), mode.ReadOnly)) diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index db789d994d..73d12fd33f 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -82,7 +82,7 @@ func (c *cache) closeStorage(ctx context.Context, shrink bool) error { return nil } if !shrink { - if err := c.fsTree.Close(); err != nil { + if err := c.fsTree.Close(ctx); err != nil { return fmt.Errorf("can't close write-cache storage: %w", err) } return nil @@ -101,7 +101,7 @@ func (c *cache) closeStorage(ctx context.Context, shrink bool) error { return fmt.Errorf("failed to check write-cache items: %w", err) } } - if err := c.fsTree.Close(); err != nil { + if err := c.fsTree.Close(ctx); err != nil { return fmt.Errorf("can't close write-cache storage: %w", err) } if empty { diff --git a/pkg/local_object_storage/writecache/mode_test.go b/pkg/local_object_storage/writecache/mode_test.go index 70cfe83828..4fbadbc641 100644 --- a/pkg/local_object_storage/writecache/mode_test.go +++ b/pkg/local_object_storage/writecache/mode_test.go @@ -18,13 +18,13 @@ func TestMode(t *testing.T) { require.NoError(t, wc.Open(context.Background(), mode.DegradedReadOnly)) require.Nil(t, wc.(*cache).fsTree) - require.NoError(t, wc.Init()) + require.NoError(t, wc.Init(context.Background())) require.Nil(t, wc.(*cache).fsTree) - require.NoError(t, wc.Close()) + require.NoError(t, wc.Close(context.Background())) require.NoError(t, wc.Open(context.Background(), mode.Degraded)) require.Nil(t, wc.(*cache).fsTree) - require.NoError(t, wc.Init()) + require.NoError(t, wc.Init(context.Background())) require.Nil(t, wc.(*cache).fsTree) - require.NoError(t, wc.Close()) + require.NoError(t, wc.Close(context.Background())) } diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index 25c1694a8b..f2957fe980 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -1,6 +1,8 @@ package writecache import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) @@ -29,7 +31,7 @@ type options struct { // noSync is true iff FSTree allows unsynchronized writes. noSync bool // reportError is the function called when encountering disk errors in background workers. - reportError func(string, error) + reportError func(context.Context, string, error) // metrics is metrics implementation metrics Metrics // disableBackgroundFlush is for testing purposes only. @@ -108,7 +110,7 @@ func WithNoSync(noSync bool) Option { } // WithReportErrorFunc sets error reporting function. -func WithReportErrorFunc(f func(string, error)) Option { +func WithReportErrorFunc(f func(context.Context, string, error)) Option { return func(o *options) { o.reportError = f } diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index d07220b68f..70b17eb8e6 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -44,9 +44,9 @@ type Cache interface { Flush(context.Context, bool, bool) error Seal(context.Context, SealPrm) error - Init() error + Init(context.Context) error Open(ctx context.Context, mode mode.Mode) error - Close() error + Close(context.Context) error GetMetrics() Metrics } diff --git a/pkg/morph/client/balance/burn.go b/pkg/morph/client/balance/burn.go index 4befbef45f..f4685b0ab6 100644 --- a/pkg/morph/client/balance/burn.go +++ b/pkg/morph/client/balance/burn.go @@ -1,6 +1,8 @@ package balance import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -30,12 +32,12 @@ func (b *BurnPrm) SetID(id []byte) { } // Burn destroys funds from the account. -func (c *Client) Burn(p BurnPrm) error { +func (c *Client) Burn(ctx context.Context, p BurnPrm) error { prm := client.InvokePrm{} prm.SetMethod(burnMethod) prm.SetArgs(p.to, p.amount, p.id) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := c.client.Invoke(prm) + _, err := c.client.Invoke(ctx, prm) return err } diff --git a/pkg/morph/client/balance/lock.go b/pkg/morph/client/balance/lock.go index a5b2067995..83e8b05868 100644 --- a/pkg/morph/client/balance/lock.go +++ b/pkg/morph/client/balance/lock.go @@ -1,6 +1,8 @@ package balance import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -42,12 +44,12 @@ func (l *LockPrm) SetDueEpoch(dueEpoch int64) { } // Lock locks fund on the user account. -func (c *Client) Lock(p LockPrm) error { +func (c *Client) Lock(ctx context.Context, p LockPrm) error { prm := client.InvokePrm{} prm.SetMethod(lockMethod) prm.SetArgs(p.id, p.user, p.lock, p.amount, p.dueEpoch) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := c.client.Invoke(prm) + _, err := c.client.Invoke(ctx, prm) return err } diff --git a/pkg/morph/client/balance/mint.go b/pkg/morph/client/balance/mint.go index 73448da315..082ade85e5 100644 --- a/pkg/morph/client/balance/mint.go +++ b/pkg/morph/client/balance/mint.go @@ -1,6 +1,8 @@ package balance import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -30,12 +32,12 @@ func (m *MintPrm) SetID(id []byte) { } // Mint sends funds to the account. -func (c *Client) Mint(p MintPrm) error { +func (c *Client) Mint(ctx context.Context, p MintPrm) error { prm := client.InvokePrm{} prm.SetMethod(mintMethod) prm.SetArgs(p.to, p.amount, p.id) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := c.client.Invoke(prm) + _, err := c.client.Invoke(ctx, prm) return err } diff --git a/pkg/morph/client/balance/transfer.go b/pkg/morph/client/balance/transfer.go index 08fb05289a..65a0b70a6b 100644 --- a/pkg/morph/client/balance/transfer.go +++ b/pkg/morph/client/balance/transfer.go @@ -1,6 +1,7 @@ package balance import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -23,7 +24,7 @@ type TransferPrm struct { // with details p.Details through direct smart contract call. // // If TryNotary is provided, calls notary contract. -func (c *Client) TransferX(p TransferPrm) error { +func (c *Client) TransferX(ctx context.Context, p TransferPrm) error { from, err := address.StringToUint160(p.From.EncodeToString()) if err != nil { return err @@ -39,7 +40,7 @@ func (c *Client) TransferX(p TransferPrm) error { prm.SetArgs(from, to, p.Amount, p.Details) prm.InvokePrmOptional = p.InvokePrmOptional - _, err = c.client.Invoke(prm) + _, err = c.client.Invoke(ctx, prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", transferXMethod, err) } diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index ef6a009e4a..f61c6e9f9b 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -180,7 +180,7 @@ func wrapFrostFSError(err error) error { // Invoke invokes contract method by sending transaction into blockchain. // Returns valid until block value. // Supported args types: int64, string, util.Uint160, []byte and bool. -func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { +func (c *Client) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { start := time.Now() success := false defer func() { @@ -199,7 +199,7 @@ func (c *Client) Invoke(contract util.Uint160, fee fixedn.Fixed8, method string, return 0, fmt.Errorf("could not invoke %s: %w", method, err) } - c.logger.Debug(context.Background(), logs.ClientNeoClientInvoke, + c.logger.Debug(ctx, logs.ClientNeoClientInvoke, zap.String("method", method), zap.Uint32("vub", vub), zap.Stringer("tx_hash", txHash.Reverse())) diff --git a/pkg/morph/client/container/delete.go b/pkg/morph/client/container/delete.go index 20351b5707..5696645b2f 100644 --- a/pkg/morph/client/container/delete.go +++ b/pkg/morph/client/container/delete.go @@ -1,6 +1,7 @@ package container import ( + "context" "crypto/sha256" "fmt" @@ -12,7 +13,7 @@ import ( // along with signature and session token. // // Returns error if container ID is nil. -func Delete(c *Client, witness core.RemovalWitness) error { +func Delete(ctx context.Context, c *Client, witness core.RemovalWitness) error { binCnr := make([]byte, sha256.Size) witness.ContainerID.Encode(binCnr) @@ -26,7 +27,7 @@ func Delete(c *Client, witness core.RemovalWitness) error { prm.SetToken(tok.Marshal()) } - _, err := c.Delete(prm) + _, err := c.Delete(ctx, prm) return err } @@ -67,7 +68,7 @@ func (d *DeletePrm) SetKey(key []byte) { // the removal to interrupt. // // If TryNotary is provided, calls notary contract. -func (c *Client) Delete(p DeletePrm) (uint32, error) { +func (c *Client) Delete(ctx context.Context, p DeletePrm) (uint32, error) { if len(p.signature) == 0 && !p.IsControl() { return 0, errNilArgument } @@ -77,7 +78,7 @@ func (c *Client) Delete(p DeletePrm) (uint32, error) { prm.SetArgs(p.cnr, p.signature, p.key, p.token) prm.InvokePrmOptional = p.InvokePrmOptional - res, err := c.client.Invoke(prm) + res, err := c.client.Invoke(ctx, prm) if err != nil { return 0, fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err) } diff --git a/pkg/morph/client/container/put.go b/pkg/morph/client/container/put.go index 777ae2d4e4..74d9f6da80 100644 --- a/pkg/morph/client/container/put.go +++ b/pkg/morph/client/container/put.go @@ -1,6 +1,7 @@ package container import ( + "context" "fmt" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" @@ -14,7 +15,7 @@ import ( // along with sig.Key() and sig.Sign(). // // Returns error if container is nil. -func Put(c *Client, cnr containercore.Container) (*cid.ID, error) { +func Put(ctx context.Context, c *Client, cnr containercore.Container) (*cid.ID, error) { data := cnr.Value.Marshal() d := container.ReadDomain(cnr.Value) @@ -35,7 +36,7 @@ func Put(c *Client, cnr containercore.Container) (*cid.ID, error) { prm.SetKey(sigV2.GetKey()) prm.SetSignature(sigV2.GetSign()) - err := c.Put(prm) + err := c.Put(ctx, prm) if err != nil { return nil, err } @@ -95,7 +96,7 @@ func (p *PutPrm) SetZone(zone string) { // encountered that caused the saving to interrupt. // // If TryNotary is provided, calls notary contract. -func (c *Client) Put(p PutPrm) error { +func (c *Client) Put(ctx context.Context, p PutPrm) error { if len(p.sig) == 0 || len(p.key) == 0 { return errNilArgument } @@ -116,7 +117,7 @@ func (c *Client) Put(p PutPrm) error { prm.SetMethod(method) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := c.client.Invoke(prm) + _, err := c.client.Invoke(ctx, prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", method, err) } diff --git a/pkg/morph/client/frostfs/cheque.go b/pkg/morph/client/frostfs/cheque.go index 016b56f8fe..d3eba76392 100644 --- a/pkg/morph/client/frostfs/cheque.go +++ b/pkg/morph/client/frostfs/cheque.go @@ -1,6 +1,8 @@ package frostfscontract import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" @@ -37,13 +39,13 @@ func (c *ChequePrm) SetLock(lock util.Uint160) { } // Cheque invokes `cheque` method of FrostFS contract. -func (x *Client) Cheque(p ChequePrm) error { +func (x *Client) Cheque(ctx context.Context, p ChequePrm) error { prm := client.InvokePrm{} prm.SetMethod(chequeMethod) prm.SetArgs(p.id, p.user, p.amount, p.lock) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := x.client.Invoke(prm) + _, err := x.client.Invoke(ctx, prm) return err } @@ -66,12 +68,12 @@ func (a *AlphabetUpdatePrm) SetPubs(pubs keys.PublicKeys) { } // AlphabetUpdate update list of alphabet nodes. -func (x *Client) AlphabetUpdate(p AlphabetUpdatePrm) error { +func (x *Client) AlphabetUpdate(ctx context.Context, p AlphabetUpdatePrm) error { prm := client.InvokePrm{} prm.SetMethod(alphabetUpdateMethod) prm.SetArgs(p.id, p.pubs) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := x.client.Invoke(prm) + _, err := x.client.Invoke(ctx, prm) return err } diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index 2d19a8193c..0a3c351dbe 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "errors" "fmt" @@ -155,13 +156,13 @@ func (s *SetConfigPrm) SetValue(value any) { } // SetConfig sets config field. -func (c *Client) SetConfig(p SetConfigPrm) error { +func (c *Client) SetConfig(ctx context.Context, p SetConfigPrm) error { prm := client.InvokePrm{} prm.SetMethod(setConfigMethod) prm.SetArgs(p.id, p.key, p.value) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := c.client.Invoke(prm) + _, err := c.client.Invoke(ctx, prm) return err } diff --git a/pkg/morph/client/netmap/innerring.go b/pkg/morph/client/netmap/innerring.go index d6f8c56b2c..c9dc7d2fcb 100644 --- a/pkg/morph/client/netmap/innerring.go +++ b/pkg/morph/client/netmap/innerring.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "crypto/elliptic" "fmt" @@ -23,7 +24,7 @@ func (u *UpdateIRPrm) SetKeys(keys keys.PublicKeys) { } // UpdateInnerRing updates inner ring keys. -func (c *Client) UpdateInnerRing(p UpdateIRPrm) error { +func (c *Client) UpdateInnerRing(ctx context.Context, p UpdateIRPrm) error { args := make([][]byte, len(p.keys)) for i := range args { args[i] = p.keys[i].Bytes() @@ -34,7 +35,7 @@ func (c *Client) UpdateInnerRing(p UpdateIRPrm) error { prm.SetArgs(args) prm.InvokePrmOptional = p.InvokePrmOptional - _, err := c.client.Invoke(prm) + _, err := c.client.Invoke(ctx, prm) return err } diff --git a/pkg/morph/client/netmap/new_epoch.go b/pkg/morph/client/netmap/new_epoch.go index ded386c868..efcdfd7b60 100644 --- a/pkg/morph/client/netmap/new_epoch.go +++ b/pkg/morph/client/netmap/new_epoch.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -8,12 +9,12 @@ import ( // NewEpoch updates FrostFS epoch number through // Netmap contract call. -func (c *Client) NewEpoch(epoch uint64) error { +func (c *Client) NewEpoch(ctx context.Context, epoch uint64) error { prm := client.InvokePrm{} prm.SetMethod(newEpochMethod) prm.SetArgs(epoch) - _, err := c.client.Invoke(prm) + _, err := c.client.Invoke(ctx, prm) if err != nil { return fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) } @@ -24,14 +25,14 @@ func (c *Client) NewEpoch(epoch uint64) error { // control notary transaction internally to ensure all // nodes produce the same transaction with high probability. // If vub > 0, vub will be used as valid until block value. -func (c *Client) NewEpochControl(epoch uint64, vub uint32) (uint32, error) { +func (c *Client) NewEpochControl(ctx context.Context, epoch uint64, vub uint32) (uint32, error) { prm := client.InvokePrm{} prm.SetMethod(newEpochMethod) prm.SetArgs(epoch) prm.SetControlTX(true) prm.SetVUB(vub) - res, err := c.client.Invoke(prm) + res, err := c.client.Invoke(ctx, prm) if err != nil { return 0, fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) } diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 764bbc899b..9617d018c3 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "errors" "fmt" @@ -24,7 +25,7 @@ func (a *AddPeerPrm) SetNodeInfo(nodeInfo netmap.NodeInfo) { // AddPeer registers peer in FrostFS network through // Netmap contract call. -func (c *Client) AddPeer(p AddPeerPrm) error { +func (c *Client) AddPeer(ctx context.Context, p AddPeerPrm) error { method := addPeerMethod if c.client.WithNotary() && c.client.IsAlpha() { @@ -39,7 +40,7 @@ func (c *Client) AddPeer(p AddPeerPrm) error { prm.SetArgs(p.nodeInfo.Marshal()) prm.InvokePrmOptional = p.InvokePrmOptional - if _, err := c.client.Invoke(prm); err != nil { + if _, err := c.client.Invoke(ctx, prm); err != nil { return fmt.Errorf("could not invoke method (%s): %w", method, err) } return nil @@ -47,7 +48,7 @@ func (c *Client) AddPeer(p AddPeerPrm) error { // ForceRemovePeer marks the given peer as offline via a notary control transaction. // If vub > 0, vub will be used as valid until block value. -func (c *Client) ForceRemovePeer(nodeInfo netmap.NodeInfo, vub uint32) (uint32, error) { +func (c *Client) ForceRemovePeer(ctx context.Context, nodeInfo netmap.NodeInfo, vub uint32) (uint32, error) { if !c.client.WithNotary() { return 0, errFailedToRemovePeerWithoutNotary } @@ -57,7 +58,7 @@ func (c *Client) ForceRemovePeer(nodeInfo netmap.NodeInfo, vub uint32) (uint32, prm.SetControlTX(true) prm.SetVUB(vub) - vub, err := c.UpdatePeerState(prm) + vub, err := c.UpdatePeerState(ctx, prm) if err != nil { return 0, fmt.Errorf("updating peer state: %v", err) } diff --git a/pkg/morph/client/netmap/update_state.go b/pkg/morph/client/netmap/update_state.go index 7c3a4e8cd2..971a55d33b 100644 --- a/pkg/morph/client/netmap/update_state.go +++ b/pkg/morph/client/netmap/update_state.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" @@ -36,7 +37,7 @@ func (u *UpdatePeerPrm) SetMaintenance() { } // UpdatePeerState changes peer status through Netmap contract call. -func (c *Client) UpdatePeerState(p UpdatePeerPrm) (uint32, error) { +func (c *Client) UpdatePeerState(ctx context.Context, p UpdatePeerPrm) (uint32, error) { method := updateStateMethod if c.client.WithNotary() && c.client.IsAlpha() { @@ -55,7 +56,7 @@ func (c *Client) UpdatePeerState(p UpdatePeerPrm) (uint32, error) { prm.SetArgs(int64(p.state), p.key) prm.InvokePrmOptional = p.InvokePrmOptional - res, err := c.client.Invoke(prm) + res, err := c.client.Invoke(ctx, prm) if err != nil { return 0, fmt.Errorf("could not invoke smart contract: %w", err) } diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 58c417fb1a..65a5e77a69 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -141,7 +141,7 @@ func (c *Client) ProbeNotary() (res bool) { // use this function. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (util.Uint256, error) { +func (c *Client) DepositNotary(ctx context.Context, amount fixedn.Fixed8, delta uint32) (util.Uint256, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -164,7 +164,7 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (util.Uint256 } till := max(int64(bc+delta), currentTill) - res, _, err := c.depositNotary(amount, till) + res, _, err := c.depositNotary(ctx, amount, till) return res, err } @@ -173,7 +173,7 @@ func (c *Client) DepositNotary(amount fixedn.Fixed8, delta uint32) (util.Uint256 // This allows to avoid ValidAfterDeposit failures. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) DepositEndlessNotary(amount fixedn.Fixed8) (util.Uint256, uint32, error) { +func (c *Client) DepositEndlessNotary(ctx context.Context, amount fixedn.Fixed8) (util.Uint256, uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -186,10 +186,10 @@ func (c *Client) DepositEndlessNotary(amount fixedn.Fixed8) (util.Uint256, uint3 } // till value refers to a block height and it is uint32 value in neo-go - return c.depositNotary(amount, math.MaxUint32) + return c.depositNotary(ctx, amount, math.MaxUint32) } -func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (util.Uint256, uint32, error) { +func (c *Client) depositNotary(ctx context.Context, amount fixedn.Fixed8, till int64) (util.Uint256, uint32, error) { txHash, vub, err := c.gasToken.Transfer( c.accAddr, c.notary.notary, @@ -202,7 +202,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (util.Uint256, // Transaction is already in mempool waiting to be processed. // This is an expected situation if we restart the service. - c.logger.Info(context.Background(), logs.ClientNotaryDepositHasAlreadyBeenMade, + c.logger.Info(ctx, logs.ClientNotaryDepositHasAlreadyBeenMade, zap.Int64("amount", int64(amount)), zap.Int64("expire_at", till), zap.Uint32("vub", vub), @@ -210,7 +210,7 @@ func (c *Client) depositNotary(amount fixedn.Fixed8, till int64) (util.Uint256, return util.Uint256{}, 0, nil } - c.logger.Info(context.Background(), logs.ClientNotaryDepositInvoke, + c.logger.Info(ctx, logs.ClientNotaryDepositInvoke, zap.Int64("amount", int64(amount)), zap.Int64("expire_at", till), zap.Uint32("vub", vub), @@ -275,7 +275,7 @@ func (u *UpdateNotaryListPrm) SetHash(hash util.Uint256) { // committee multi signature. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) UpdateNotaryList(prm UpdateNotaryListPrm) error { +func (c *Client) UpdateNotaryList(ctx context.Context, prm UpdateNotaryListPrm) error { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -293,6 +293,7 @@ func (c *Client) UpdateNotaryList(prm UpdateNotaryListPrm) error { } return c.notaryInvokeAsCommittee( + ctx, setDesignateMethod, nonce, vub, @@ -323,7 +324,7 @@ func (u *UpdateAlphabetListPrm) SetHash(hash util.Uint256) { // Requires committee multi signature. // // This function must be invoked with notary enabled otherwise it throws panic. -func (c *Client) UpdateNeoFSAlphabetList(prm UpdateAlphabetListPrm) error { +func (c *Client) UpdateNeoFSAlphabetList(ctx context.Context, prm UpdateAlphabetListPrm) error { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -341,6 +342,7 @@ func (c *Client) UpdateNeoFSAlphabetList(prm UpdateAlphabetListPrm) error { } return c.notaryInvokeAsCommittee( + ctx, setDesignateMethod, nonce, vub, @@ -356,7 +358,7 @@ func (c *Client) UpdateNeoFSAlphabetList(prm UpdateAlphabetListPrm) error { // Returns valid until block value. // // `nonce` and `vub` are used only if notary is enabled. -func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { +func (c *Client) NotaryInvoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -365,10 +367,10 @@ func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce ui } if c.notary == nil { - return c.Invoke(contract, fee, method, args...) + return c.Invoke(ctx, contract, fee, method, args...) } - return c.notaryInvoke(false, true, contract, nonce, vub, method, args...) + return c.notaryInvoke(ctx, false, true, contract, nonce, vub, method, args...) } // NotaryInvokeNotAlpha does the same as NotaryInvoke but does not use client's @@ -376,7 +378,7 @@ func (c *Client) NotaryInvoke(contract util.Uint160, fee fixedn.Fixed8, nonce ui // not expected to be signed by the current node. // // Considered to be used by non-IR nodes. -func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, vubP *uint32, method string, args ...any) (uint32, error) { +func (c *Client) NotaryInvokeNotAlpha(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, vubP *uint32, method string, args ...any) (uint32, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() @@ -385,10 +387,10 @@ func (c *Client) NotaryInvokeNotAlpha(contract util.Uint160, fee fixedn.Fixed8, } if c.notary == nil { - return c.Invoke(contract, fee, method, args...) + return c.Invoke(ctx, contract, fee, method, args...) } - return c.notaryInvoke(false, false, contract, rand.Uint32(), vubP, method, args...) + return c.notaryInvoke(ctx, false, false, contract, rand.Uint32(), vubP, method, args...) } // NotarySignAndInvokeTX signs and sends notary request that was received from @@ -438,13 +440,13 @@ func (c *Client) NotarySignAndInvokeTX(mainTx *transaction.Transaction) error { return nil } -func (c *Client) notaryInvokeAsCommittee(method string, nonce, vub uint32, args ...any) error { +func (c *Client) notaryInvokeAsCommittee(ctx context.Context, method string, nonce, vub uint32, args ...any) error { designate := c.GetDesignateHash() - _, err := c.notaryInvoke(true, true, designate, nonce, &vub, method, args...) + _, err := c.notaryInvoke(ctx, true, true, designate, nonce, &vub, method, args...) return err } -func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { +func (c *Client) notaryInvoke(ctx context.Context, committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { start := time.Now() success := false defer func() { @@ -486,7 +488,7 @@ func (c *Client) notaryInvoke(committee, invokedByAlpha bool, contract util.Uint return 0, err } - c.logger.Debug(context.Background(), logs.ClientNotaryRequestInvoked, + c.logger.Debug(ctx, logs.ClientNotaryRequestInvoked, zap.String("method", method), zap.Uint32("valid_until_block", untilActual), zap.String("tx_hash", mainH.StringLE()), diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index dfcf62b834..1e091936f0 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -1,6 +1,7 @@ package client import ( + "context" "fmt" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" @@ -140,7 +141,7 @@ type InvokeRes struct { // // If fee for the operation executed using specified method is customized, then StaticClient uses it. // Otherwise, default fee is used. -func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) { +func (s StaticClient) Invoke(ctx context.Context, prm InvokePrm) (InvokeRes, error) { var res InvokeRes var err error var vubP *uint32 @@ -169,7 +170,7 @@ func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) { vubP = &prm.vub } - res.VUB, err = s.client.NotaryInvoke(s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) + res.VUB, err = s.client.NotaryInvoke(ctx, s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) return res, err } @@ -177,11 +178,12 @@ func (s StaticClient) Invoke(prm InvokePrm) (InvokeRes, error) { vubP = &prm.vub } - res.VUB, err = s.client.NotaryInvokeNotAlpha(s.scScriptHash, s.fee, vubP, prm.method, prm.args...) + res.VUB, err = s.client.NotaryInvokeNotAlpha(ctx, s.scScriptHash, s.fee, vubP, prm.method, prm.args...) return res, err } res.VUB, err = s.client.Invoke( + ctx, s.scScriptHash, s.fee, prm.method, diff --git a/pkg/morph/event/handlers.go b/pkg/morph/event/handlers.go index bda83ba542..8223353296 100644 --- a/pkg/morph/event/handlers.go +++ b/pkg/morph/event/handlers.go @@ -10,7 +10,7 @@ import ( type Handler func(context.Context, Event) // BlockHandler is a chain block processing function. -type BlockHandler func(*block.Block) +type BlockHandler func(context.Context, *block.Block) // NotificationHandlerInfo is a structure that groups // the parameters of the handler of particular diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index eeec46540f..6e6184e775 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -291,18 +291,18 @@ loop: continue loop } - l.handleBlockEvent(b) + l.handleBlockEvent(ctx, b) } } } -func (l *listener) handleBlockEvent(b *block.Block) { +func (l *listener) handleBlockEvent(ctx context.Context, b *block.Block) { if err := l.pool.Submit(func() { for i := range l.blockHandlers { - l.blockHandlers[i](b) + l.blockHandlers[i](ctx, b) } }); err != nil { - l.log.Warn(context.Background(), logs.EventListenerWorkerPoolDrained, + l.log.Warn(ctx, logs.EventListenerWorkerPoolDrained, zap.Int("capacity", l.pool.Cap())) } } diff --git a/pkg/morph/event/listener_test.go b/pkg/morph/event/listener_test.go index 214daf694a..c0f9722d7a 100644 --- a/pkg/morph/event/listener_test.go +++ b/pkg/morph/event/listener_test.go @@ -34,7 +34,7 @@ func TestEventHandling(t *testing.T) { blockHandled := make(chan bool) handledBlocks := make([]*block.Block, 0) - l.RegisterBlockHandler(func(b *block.Block) { + l.RegisterBlockHandler(func(_ context.Context, b *block.Block) { handledBlocks = append(handledBlocks, b) blockHandled <- true }) @@ -137,7 +137,7 @@ func TestErrorPassing(t *testing.T) { WorkerPoolCapacity: 10, }) require.NoError(t, err, "failed to create listener") - l.RegisterBlockHandler(func(b *block.Block) {}) + l.RegisterBlockHandler(func(context.Context, *block.Block) {}) errCh := make(chan error) diff --git a/pkg/network/transport/object/grpc/service.go b/pkg/network/transport/object/grpc/service.go index fa62521183..15dacd5539 100644 --- a/pkg/network/transport/object/grpc/service.go +++ b/pkg/network/transport/object/grpc/service.go @@ -26,7 +26,7 @@ func New(c objectSvc.ServiceServer) *Server { // Patch opens internal Object patch stream and feeds it by the data read from gRPC stream. func (s *Server) Patch(gStream objectGRPC.ObjectService_PatchServer) error { - stream, err := s.srv.Patch() + stream, err := s.srv.Patch(gStream.Context()) if err != nil { return err } @@ -68,7 +68,7 @@ func (s *Server) Patch(gStream objectGRPC.ObjectService_PatchServer) error { // Put opens internal Object service Put stream and overtakes data from gRPC stream to it. func (s *Server) Put(gStream objectGRPC.ObjectService_PutServer) error { - stream, err := s.srv.Put() + stream, err := s.srv.Put(gStream.Context()) if err != nil { return err } diff --git a/pkg/services/apemanager/audit.go b/pkg/services/apemanager/audit.go index b9bea07fbb..61fb025b89 100644 --- a/pkg/services/apemanager/audit.go +++ b/pkg/services/apemanager/audit.go @@ -33,7 +33,7 @@ func (a *auditService) AddChain(ctx context.Context, req *apemanager.AddChainReq return res, err } - audit.LogRequest(a.log, ape_grpc.APEManagerService_AddChain_FullMethodName, req, + audit.LogRequest(ctx, a.log, ape_grpc.APEManagerService_AddChain_FullMethodName, req, audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(), req.GetBody().GetTarget().GetName(), res.GetBody().GetChainID()), @@ -49,7 +49,7 @@ func (a *auditService) ListChains(ctx context.Context, req *apemanager.ListChain return res, err } - audit.LogRequest(a.log, ape_grpc.APEManagerService_ListChains_FullMethodName, req, + audit.LogRequest(ctx, a.log, ape_grpc.APEManagerService_ListChains_FullMethodName, req, audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(), req.GetBody().GetTarget().GetName(), nil), @@ -65,7 +65,7 @@ func (a *auditService) RemoveChain(ctx context.Context, req *apemanager.RemoveCh return res, err } - audit.LogRequest(a.log, ape_grpc.APEManagerService_RemoveChain_FullMethodName, req, + audit.LogRequest(ctx, a.log, ape_grpc.APEManagerService_RemoveChain_FullMethodName, req, audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(), req.GetBody().GetTarget().GetName(), req.GetBody().GetChainID()), diff --git a/pkg/services/container/audit.go b/pkg/services/container/audit.go index 03d3dc13d4..411eb48630 100644 --- a/pkg/services/container/audit.go +++ b/pkg/services/container/audit.go @@ -35,7 +35,7 @@ func (a *auditService) Delete(ctx context.Context, req *container.DeleteRequest) return res, err } - audit.LogRequest(a.log, container_grpc.ContainerService_Delete_FullMethodName, req, + audit.LogRequest(ctx, a.log, container_grpc.ContainerService_Delete_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil) return res, err @@ -47,7 +47,7 @@ func (a *auditService) Get(ctx context.Context, req *container.GetRequest) (*con if !a.enabled.Load() { return res, err } - audit.LogRequest(a.log, container_grpc.ContainerService_Get_FullMethodName, req, + audit.LogRequest(ctx, a.log, container_grpc.ContainerService_Get_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil) return res, err } @@ -58,7 +58,7 @@ func (a *auditService) List(ctx context.Context, req *container.ListRequest) (*c if !a.enabled.Load() { return res, err } - audit.LogRequest(a.log, container_grpc.ContainerService_List_FullMethodName, req, + audit.LogRequest(ctx, a.log, container_grpc.ContainerService_List_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil) return res, err } @@ -69,7 +69,7 @@ func (a *auditService) Put(ctx context.Context, req *container.PutRequest) (*con if !a.enabled.Load() { return res, err } - audit.LogRequest(a.log, container_grpc.ContainerService_Put_FullMethodName, req, + audit.LogRequest(ctx, a.log, container_grpc.ContainerService_Put_FullMethodName, req, audit.TargetFromRef(res.GetBody().GetContainerID(), &cid.ID{}), err == nil) return res, err } diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index eb43eab70a..211f469f32 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -35,9 +35,9 @@ type Reader interface { // Writer is an interface of container storage updater. type Writer interface { // Put stores specified container in the side chain. - Put(containercore.Container) (*cid.ID, error) + Put(context.Context, containercore.Container) (*cid.ID, error) // Delete removes specified container from the side chain. - Delete(containercore.RemovalWitness) error + Delete(context.Context, containercore.RemovalWitness) error } func NewExecutor(rdr Reader, wrt Writer) containerSvc.ServiceExecutor { @@ -47,7 +47,7 @@ func NewExecutor(rdr Reader, wrt Writer) containerSvc.ServiceExecutor { } } -func (s *morphExecutor) Put(_ context.Context, tokV2 *sessionV2.Token, body *container.PutRequestBody) (*container.PutResponseBody, error) { +func (s *morphExecutor) Put(ctx context.Context, tokV2 *sessionV2.Token, body *container.PutRequestBody) (*container.PutResponseBody, error) { sigV2 := body.GetSignature() if sigV2 == nil { // TODO(@cthulhu-rider): #468 use "const" error @@ -80,7 +80,7 @@ func (s *morphExecutor) Put(_ context.Context, tokV2 *sessionV2.Token, body *con } } - idCnr, err := s.wrt.Put(cnr) + idCnr, err := s.wrt.Put(ctx, cnr) if err != nil { return nil, err } @@ -94,7 +94,7 @@ func (s *morphExecutor) Put(_ context.Context, tokV2 *sessionV2.Token, body *con return res, nil } -func (s *morphExecutor) Delete(_ context.Context, tokV2 *sessionV2.Token, body *container.DeleteRequestBody) (*container.DeleteResponseBody, error) { +func (s *morphExecutor) Delete(ctx context.Context, tokV2 *sessionV2.Token, body *container.DeleteRequestBody) (*container.DeleteResponseBody, error) { idV2 := body.GetContainerID() if idV2 == nil { return nil, errors.New("missing container ID") @@ -124,7 +124,7 @@ func (s *morphExecutor) Delete(_ context.Context, tokV2 *sessionV2.Token, body * rmWitness.Signature = body.GetSignature() rmWitness.SessionToken = tok - err = s.wrt.Delete(rmWitness) + err = s.wrt.Delete(ctx, rmWitness) if err != nil { return nil, err } diff --git a/pkg/services/container/morph/executor_test.go b/pkg/services/container/morph/executor_test.go index 87d3073852..1f6fdb0bec 100644 --- a/pkg/services/container/morph/executor_test.go +++ b/pkg/services/container/morph/executor_test.go @@ -24,11 +24,11 @@ type mock struct { containerSvcMorph.Reader } -func (m mock) Put(_ containerCore.Container) (*cid.ID, error) { +func (m mock) Put(_ context.Context, _ containerCore.Container) (*cid.ID, error) { return new(cid.ID), nil } -func (m mock) Delete(_ containerCore.RemovalWitness) error { +func (m mock) Delete(_ context.Context, _ containerCore.RemovalWitness) error { return nil } diff --git a/pkg/services/control/ir/server/audit.go b/pkg/services/control/ir/server/audit.go index e54fa9824c..d9f65a2fc1 100644 --- a/pkg/services/control/ir/server/audit.go +++ b/pkg/services/control/ir/server/audit.go @@ -36,7 +36,7 @@ func (a *auditService) HealthCheck(ctx context.Context, req *control.HealthCheck if !a.enabled.Load() { return res, err } - audit.LogRequestWithKey(a.log, control.ControlService_HealthCheck_FullMethodName, req.GetSignature().GetKey(), nil, err == nil) + audit.LogRequestWithKey(ctx, a.log, control.ControlService_HealthCheck_FullMethodName, req.GetSignature().GetKey(), nil, err == nil) return res, err } @@ -79,7 +79,7 @@ func (a *auditService) RemoveContainer(ctx context.Context, req *control.RemoveC } } - audit.LogRequestWithKey(a.log, control.ControlService_RemoveContainer_FullMethodName, req.GetSignature().GetKey(), sb, err == nil) + audit.LogRequestWithKey(ctx, a.log, control.ControlService_RemoveContainer_FullMethodName, req.GetSignature().GetKey(), sb, err == nil) return res, err } @@ -90,7 +90,7 @@ func (a *auditService) RemoveNode(ctx context.Context, req *control.RemoveNodeRe return res, err } - audit.LogRequestWithKey(a.log, control.ControlService_RemoveNode_FullMethodName, req.GetSignature().GetKey(), + audit.LogRequestWithKey(ctx, a.log, control.ControlService_RemoveNode_FullMethodName, req.GetSignature().GetKey(), audit.TargetFromString(hex.EncodeToString(req.GetBody().GetKey())), err == nil) return res, err } @@ -102,7 +102,7 @@ func (a *auditService) TickEpoch(ctx context.Context, req *control.TickEpochRequ return res, err } - audit.LogRequestWithKey(a.log, control.ControlService_TickEpoch_FullMethodName, req.GetSignature().GetKey(), + audit.LogRequestWithKey(ctx, a.log, control.ControlService_TickEpoch_FullMethodName, req.GetSignature().GetKey(), nil, err == nil) return res, err } diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index 63be224115..e2c385c6ad 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -40,7 +40,7 @@ func (s *Server) HealthCheck(_ context.Context, req *control.HealthCheckRequest) // TickEpoch forces a new epoch. // // If request is not signed with a key from white list, permission error returns. -func (s *Server) TickEpoch(_ context.Context, req *control.TickEpochRequest) (*control.TickEpochResponse, error) { +func (s *Server) TickEpoch(ctx context.Context, req *control.TickEpochRequest) (*control.TickEpochResponse, error) { if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) } @@ -53,7 +53,7 @@ func (s *Server) TickEpoch(_ context.Context, req *control.TickEpochRequest) (*c return nil, fmt.Errorf("getting current epoch: %w", err) } - vub, err := s.netmapClient.NewEpochControl(epoch+1, req.GetBody().GetVub()) + vub, err := s.netmapClient.NewEpochControl(ctx, epoch+1, req.GetBody().GetVub()) if err != nil { return nil, fmt.Errorf("forcing new epoch: %w", err) } @@ -69,7 +69,7 @@ func (s *Server) TickEpoch(_ context.Context, req *control.TickEpochRequest) (*c // RemoveNode forces a node removal. // // If request is not signed with a key from white list, permission error returns. -func (s *Server) RemoveNode(_ context.Context, req *control.RemoveNodeRequest) (*control.RemoveNodeResponse, error) { +func (s *Server) RemoveNode(ctx context.Context, req *control.RemoveNodeRequest) (*control.RemoveNodeResponse, error) { if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) } @@ -95,7 +95,7 @@ func (s *Server) RemoveNode(_ context.Context, req *control.RemoveNodeRequest) ( return nil, status.Error(codes.FailedPrecondition, "node is already offline") } - vub, err := s.netmapClient.ForceRemovePeer(nodeInfo, req.GetBody().GetVub()) + vub, err := s.netmapClient.ForceRemovePeer(ctx, nodeInfo, req.GetBody().GetVub()) if err != nil { return nil, fmt.Errorf("forcing node removal: %w", err) } @@ -109,7 +109,7 @@ func (s *Server) RemoveNode(_ context.Context, req *control.RemoveNodeRequest) ( } // RemoveContainer forces a container removal. -func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainerRequest) (*control.RemoveContainerResponse, error) { +func (s *Server) RemoveContainer(ctx context.Context, req *control.RemoveContainerRequest) (*control.RemoveContainerResponse, error) { if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) } @@ -124,7 +124,7 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer return nil, status.Error(codes.InvalidArgument, "failed to parse container ID: "+err.Error()) } var err error - vub, err = s.removeContainer(containerID, req.GetBody().GetVub()) + vub, err = s.removeContainer(ctx, containerID, req.GetBody().GetVub()) if err != nil { return nil, err } @@ -144,7 +144,7 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer } for _, containerID := range cids { - vub, err = s.removeContainer(containerID, req.GetBody().GetVub()) + vub, err = s.removeContainer(ctx, containerID, req.GetBody().GetVub()) if err != nil { return nil, err } @@ -162,13 +162,13 @@ func (s *Server) RemoveContainer(_ context.Context, req *control.RemoveContainer return resp, nil } -func (s *Server) removeContainer(containerID cid.ID, vub uint32) (uint32, error) { +func (s *Server) removeContainer(ctx context.Context, containerID cid.ID, vub uint32) (uint32, error) { var prm container.DeletePrm prm.SetCID(containerID[:]) prm.SetControlTX(true) prm.SetVUB(vub) - vub, err := s.containerClient.Delete(prm) + vub, err := s.containerClient.Delete(ctx, prm) if err != nil { return 0, fmt.Errorf("forcing container removal: %w", err) } diff --git a/pkg/services/control/server/server.go b/pkg/services/control/server/server.go index b6fdcb246a..94aa1ff5b0 100644 --- a/pkg/services/control/server/server.go +++ b/pkg/services/control/server/server.go @@ -1,6 +1,7 @@ package control import ( + "context" "crypto/ecdsa" "sync/atomic" @@ -45,11 +46,11 @@ type NodeState interface { // // If status is control.NetmapStatus_MAINTENANCE and maintenance is allowed // in the network settings, the node additionally starts local maintenance. - SetNetmapStatus(st control.NetmapStatus) error + SetNetmapStatus(ctx context.Context, st control.NetmapStatus) error // ForceMaintenance works like SetNetmapStatus(control.NetmapStatus_MAINTENANCE) // but starts local maintenance regardless of the network settings. - ForceMaintenance() error + ForceMaintenance(ctx context.Context) error GetNetmapStatus() (control.NetmapStatus, uint64, error) } diff --git a/pkg/services/control/server/set_netmap_status.go b/pkg/services/control/server/set_netmap_status.go index 3fd69df12f..529041dcad 100644 --- a/pkg/services/control/server/set_netmap_status.go +++ b/pkg/services/control/server/set_netmap_status.go @@ -12,7 +12,7 @@ import ( // SetNetmapStatus sets node status in FrostFS network. // // If request is unsigned or signed by disallowed key, permission error returns. -func (s *Server) SetNetmapStatus(_ context.Context, req *control.SetNetmapStatusRequest) (*control.SetNetmapStatusResponse, error) { +func (s *Server) SetNetmapStatus(ctx context.Context, req *control.SetNetmapStatusRequest) (*control.SetNetmapStatusResponse, error) { // verify request if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) @@ -29,9 +29,9 @@ func (s *Server) SetNetmapStatus(_ context.Context, req *control.SetNetmapStatus "force_maintenance MUST be set for %s status only", control.NetmapStatus_MAINTENANCE) } - err = s.nodeState.ForceMaintenance() + err = s.nodeState.ForceMaintenance(ctx) } else { - err = s.nodeState.SetNetmapStatus(st) + err = s.nodeState.SetNetmapStatus(ctx, st) } if err != nil { diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 93ad3dc460..db0f13ee73 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -193,7 +193,7 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream src: request, } - reqInfo, err := b.findRequestInfo(req, cnr, acl.OpObjectGet) + reqInfo, err := b.findRequestInfo(stream.Context(), req, cnr, acl.OpObjectGet) if err != nil { return err } @@ -203,8 +203,8 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream return b.next.Get(request, newWrappedGetObjectStreamStream(stream, reqInfo)) } -func (b Service) Put() (object.PutObjectStream, error) { - streamer, err := b.next.Put() +func (b Service) Put(ctx context.Context) (object.PutObjectStream, error) { + streamer, err := b.next.Put(ctx) return putStreamBasicChecker{ source: &b, @@ -212,8 +212,8 @@ func (b Service) Put() (object.PutObjectStream, error) { }, err } -func (b Service) Patch() (object.PatchObjectStream, error) { - streamer, err := b.next.Patch() +func (b Service) Patch(ctx context.Context) (object.PatchObjectStream, error) { + streamer, err := b.next.Patch(ctx) return &patchStreamBasicChecker{ source: &b, @@ -259,7 +259,7 @@ func (b Service) Head( src: request, } - reqInfo, err := b.findRequestInfo(req, cnr, acl.OpObjectHead) + reqInfo, err := b.findRequestInfo(ctx, req, cnr, acl.OpObjectHead) if err != nil { return nil, err } @@ -299,7 +299,7 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr src: request, } - reqInfo, err := b.findRequestInfo(req, id, acl.OpObjectSearch) + reqInfo, err := b.findRequestInfo(stream.Context(), req, id, acl.OpObjectSearch) if err != nil { return err } @@ -345,7 +345,7 @@ func (b Service) Delete( src: request, } - reqInfo, err := b.findRequestInfo(req, cnr, acl.OpObjectDelete) + reqInfo, err := b.findRequestInfo(ctx, req, cnr, acl.OpObjectDelete) if err != nil { return nil, err } @@ -390,7 +390,7 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb src: request, } - reqInfo, err := b.findRequestInfo(req, cnr, acl.OpObjectRange) + reqInfo, err := b.findRequestInfo(stream.Context(), req, cnr, acl.OpObjectRange) if err != nil { return err } @@ -448,7 +448,7 @@ func (b Service) GetRangeHash( src: request, } - reqInfo, err := b.findRequestInfo(req, cnr, acl.OpObjectHash) + reqInfo, err := b.findRequestInfo(ctx, req, cnr, acl.OpObjectHash) if err != nil { return nil, err } @@ -499,7 +499,7 @@ func (b Service) PutSingle(ctx context.Context, request *objectV2.PutSingleReque src: request, } - reqInfo, err := b.findRequestInfo(req, cnr, acl.OpObjectPut) + reqInfo, err := b.findRequestInfo(ctx, req, cnr, acl.OpObjectPut) if err != nil { return nil, err } @@ -564,7 +564,7 @@ func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRe src: request, } - reqInfo, err := p.source.findRequestInfo(req, cnr, acl.OpObjectPut) + reqInfo, err := p.source.findRequestInfo(ctx, req, cnr, acl.OpObjectPut) if err != nil { return err } @@ -651,7 +651,7 @@ func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.Pa src: request, } - reqInfo, err := p.source.findRequestInfoWithoutACLOperationAssert(req, cnr) + reqInfo, err := p.source.findRequestInfoWithoutACLOperationAssert(ctx, req, cnr) if err != nil { return err } @@ -668,7 +668,7 @@ func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.Pa return p.next.CloseAndRecv(ctx) } -func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (info RequestInfo, err error) { +func (b Service) findRequestInfo(ctx context.Context, req MetaWithToken, idCnr cid.ID, op acl.Op) (info RequestInfo, err error) { cnr, err := b.containers.Get(idCnr) // fetch actual container if err != nil { return info, err @@ -697,7 +697,7 @@ func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (in if err != nil { return info, err } - res, err := b.c.Classify(ownerID, ownerKey, idCnr, cnr.Value) + res, err := b.c.Classify(ctx, ownerID, ownerKey, idCnr, cnr.Value) if err != nil { return info, err } @@ -726,7 +726,7 @@ func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (in } // findRequestInfoWithoutACLOperationAssert is findRequestInfo without session token verb assert. -func (b Service) findRequestInfoWithoutACLOperationAssert(req MetaWithToken, idCnr cid.ID) (info RequestInfo, err error) { +func (b Service) findRequestInfoWithoutACLOperationAssert(ctx context.Context, req MetaWithToken, idCnr cid.ID) (info RequestInfo, err error) { cnr, err := b.containers.Get(idCnr) // fetch actual container if err != nil { return info, err @@ -751,7 +751,7 @@ func (b Service) findRequestInfoWithoutACLOperationAssert(req MetaWithToken, idC if err != nil { return info, err } - res, err := b.c.Classify(ownerID, ownerKey, idCnr, cnr.Value) + res, err := b.c.Classify(ctx, ownerID, ownerKey, idCnr, cnr.Value) if err != nil { return info, err } diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index 558c48da8e..c6d152e0f0 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -186,8 +186,8 @@ func (p putStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PutR return p.next.CloseAndRecv(ctx) } -func (c *Service) Put() (objectSvc.PutObjectStream, error) { - streamer, err := c.next.Put() +func (c *Service) Put(ctx context.Context) (objectSvc.PutObjectStream, error) { + streamer, err := c.next.Put(ctx) return &putStreamBasicChecker{ apeChecker: c.apeChecker, @@ -241,8 +241,8 @@ func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.Pa return p.next.CloseAndRecv(ctx) } -func (c *Service) Patch() (objectSvc.PatchObjectStream, error) { - streamer, err := c.next.Patch() +func (c *Service) Patch(ctx context.Context) (objectSvc.PatchObjectStream, error) { + streamer, err := c.next.Patch(ctx) return &patchStreamBasicChecker{ apeChecker: c.apeChecker, diff --git a/pkg/services/object/audit.go b/pkg/services/object/audit.go index b420846344..dde9f8fc05 100644 --- a/pkg/services/object/audit.go +++ b/pkg/services/object/audit.go @@ -37,7 +37,7 @@ func (a *auditService) Delete(ctx context.Context, req *object.DeleteRequest) (* if !a.enabled.Load() { return res, err } - audit.LogRequest(a.log, objectGRPC.ObjectService_Delete_FullMethodName, req, + audit.LogRequest(ctx, a.log, objectGRPC.ObjectService_Delete_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) return res, err } @@ -48,7 +48,7 @@ func (a *auditService) Get(req *object.GetRequest, stream GetObjectStream) error if !a.enabled.Load() { return err } - audit.LogRequest(a.log, objectGRPC.ObjectService_Get_FullMethodName, req, + audit.LogRequest(stream.Context(), a.log, objectGRPC.ObjectService_Get_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) return err } @@ -59,7 +59,7 @@ func (a *auditService) GetRange(req *object.GetRangeRequest, stream GetObjectRan if !a.enabled.Load() { return err } - audit.LogRequest(a.log, objectGRPC.ObjectService_GetRange_FullMethodName, req, + audit.LogRequest(stream.Context(), a.log, objectGRPC.ObjectService_GetRange_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) return err } @@ -70,7 +70,7 @@ func (a *auditService) GetRangeHash(ctx context.Context, req *object.GetRangeHas if !a.enabled.Load() { return resp, err } - audit.LogRequest(a.log, objectGRPC.ObjectService_GetRangeHash_FullMethodName, req, + audit.LogRequest(ctx, a.log, objectGRPC.ObjectService_GetRangeHash_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) return resp, err } @@ -81,19 +81,19 @@ func (a *auditService) Head(ctx context.Context, req *object.HeadRequest) (*obje if !a.enabled.Load() { return resp, err } - audit.LogRequest(a.log, objectGRPC.ObjectService_Head_FullMethodName, req, + audit.LogRequest(ctx, a.log, objectGRPC.ObjectService_Head_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil) return resp, err } // Put implements ServiceServer. -func (a *auditService) Put() (PutObjectStream, error) { - res, err := a.next.Put() +func (a *auditService) Put(ctx context.Context) (PutObjectStream, error) { + res, err := a.next.Put(ctx) if !a.enabled.Load() { return res, err } if err != nil { - audit.LogRequest(a.log, objectGRPC.ObjectService_Put_FullMethodName, nil, nil, false) + audit.LogRequest(ctx, a.log, objectGRPC.ObjectService_Put_FullMethodName, nil, nil, false) return res, err } return &auditPutStream{ @@ -108,7 +108,7 @@ func (a *auditService) PutSingle(ctx context.Context, req *object.PutSingleReque if !a.enabled.Load() { return resp, err } - audit.LogRequest(a.log, objectGRPC.ObjectService_PutSingle_FullMethodName, req, + audit.LogRequest(ctx, a.log, objectGRPC.ObjectService_PutSingle_FullMethodName, req, audit.TargetFromContainerIDObjectID(req.GetBody().GetObject().GetHeader().GetContainerID(), req.GetBody().GetObject().GetObjectID()), err == nil) @@ -121,7 +121,7 @@ func (a *auditService) Search(req *object.SearchRequest, stream SearchStream) er if !a.enabled.Load() { return err } - audit.LogRequest(a.log, objectGRPC.ObjectService_Search_FullMethodName, req, + audit.LogRequest(stream.Context(), a.log, objectGRPC.ObjectService_Search_FullMethodName, req, audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil) return err } @@ -145,7 +145,7 @@ func (a *auditPutStream) CloseAndRecv(ctx context.Context) (*object.PutResponse, a.failed = true } a.objectID = resp.GetBody().GetObjectID() - audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key, + audit.LogRequestWithKey(ctx, a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key, audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), !a.failed) return resp, err @@ -164,7 +164,7 @@ func (a *auditPutStream) Send(ctx context.Context, req *object.PutRequest) error a.failed = true } if !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here - audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key, + audit.LogRequestWithKey(ctx, a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key, audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), !a.failed) } @@ -183,13 +183,13 @@ type auditPatchStream struct { nonFirstSend bool } -func (a *auditService) Patch() (PatchObjectStream, error) { - res, err := a.next.Patch() +func (a *auditService) Patch(ctx context.Context) (PatchObjectStream, error) { + res, err := a.next.Patch(ctx) if !a.enabled.Load() { return res, err } if err != nil { - audit.LogRequest(a.log, objectGRPC.ObjectService_Patch_FullMethodName, nil, nil, false) + audit.LogRequest(ctx, a.log, objectGRPC.ObjectService_Patch_FullMethodName, nil, nil, false) return res, err } return &auditPatchStream{ @@ -205,7 +205,7 @@ func (a *auditPatchStream) CloseAndRecv(ctx context.Context) (*object.PatchRespo a.failed = true } a.objectID = resp.GetBody().GetObjectID() - audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Patch_FullMethodName, a.key, + audit.LogRequestWithKey(ctx, a.log, objectGRPC.ObjectService_Patch_FullMethodName, a.key, audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), !a.failed) return resp, err @@ -225,7 +225,7 @@ func (a *auditPatchStream) Send(ctx context.Context, req *object.PatchRequest) e a.failed = true } if !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here - audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Patch_FullMethodName, a.key, + audit.LogRequestWithKey(ctx, a.log, objectGRPC.ObjectService_Patch_FullMethodName, a.key, audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), !a.failed) } diff --git a/pkg/services/object/common.go b/pkg/services/object/common.go index 758156607b..ef65e78bc6 100644 --- a/pkg/services/object/common.go +++ b/pkg/services/object/common.go @@ -40,20 +40,20 @@ func (x *Common) Get(req *objectV2.GetRequest, stream GetObjectStream) error { return x.nextHandler.Get(req, stream) } -func (x *Common) Put() (PutObjectStream, error) { +func (x *Common) Put(ctx context.Context) (PutObjectStream, error) { if x.state.IsMaintenance() { return nil, new(apistatus.NodeUnderMaintenance) } - return x.nextHandler.Put() + return x.nextHandler.Put(ctx) } -func (x *Common) Patch() (PatchObjectStream, error) { +func (x *Common) Patch(ctx context.Context) (PatchObjectStream, error) { if x.state.IsMaintenance() { return nil, new(apistatus.NodeUnderMaintenance) } - return x.nextHandler.Patch() + return x.nextHandler.Patch(ctx) } func (x *Common) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { diff --git a/pkg/services/object/common/writer/common.go b/pkg/services/object/common/writer/common.go index 8b92d34edf..3b68efab41 100644 --- a/pkg/services/object/common/writer/common.go +++ b/pkg/services/object/common/writer/common.go @@ -89,7 +89,7 @@ func (n *NodeIterator) forEachAddress(ctx context.Context, traverser *placement. err := f(ctx, NodeDescriptor{Local: isLocal, Info: addr}) if err != nil { resErr.Store(err) - svcutil.LogServiceError(n.cfg.Logger, "PUT", addr.Addresses(), err) + svcutil.LogServiceError(ctx, n.cfg.Logger, "PUT", addr.Addresses(), err) return } @@ -97,7 +97,7 @@ func (n *NodeIterator) forEachAddress(ctx context.Context, traverser *placement. *item = true }); err != nil { wg.Done() - svcutil.LogWorkerPoolError(n.cfg.Logger, "PUT", err) + svcutil.LogWorkerPoolError(ctx, n.cfg.Logger, "PUT", err) return true } diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index 64115b86b2..fdaa569da2 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -154,7 +154,7 @@ func (e *ECWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index err = e.Relay(ctx, info, c) }); poolErr != nil { close(completed) - svcutil.LogWorkerPoolError(e.Config.Logger, "PUT", poolErr) + svcutil.LogWorkerPoolError(ctx, e.Config.Logger, "PUT", poolErr) return poolErr } <-completed diff --git a/pkg/services/object/get/assembleec.go b/pkg/services/object/get/assembleec.go index 8ab423c878..59dd7fd93e 100644 --- a/pkg/services/object/get/assembleec.go +++ b/pkg/services/object/get/assembleec.go @@ -37,7 +37,7 @@ func (r *request) assembleEC(ctx context.Context) { r.log.Debug(ctx, logs.GetTryingToAssembleTheECObject) // initialize epoch number - ok := r.initEpoch() + ok := r.initEpoch(ctx) if !ok { return } diff --git a/pkg/services/object/get/container.go b/pkg/services/object/get/container.go index 2b84c5b32f..0ee8aed537 100644 --- a/pkg/services/object/get/container.go +++ b/pkg/services/object/get/container.go @@ -21,7 +21,7 @@ func (r *request) executeOnContainer(ctx context.Context) { ) // initialize epoch number - ok := r.initEpoch() + ok := r.initEpoch(ctx) if !ok { return } @@ -50,7 +50,7 @@ func (r *request) processCurrentEpoch(ctx context.Context, localStatus int) bool zap.Uint64("number", r.curProcEpoch), ) - traverser, ok := r.generateTraverser(r.address()) + traverser, ok := r.generateTraverser(ctx, r.address()) if !ok { return true } diff --git a/pkg/services/object/get/remote.go b/pkg/services/object/get/remote.go index b6a83fd0cf..78ca5b5e35 100644 --- a/pkg/services/object/get/remote.go +++ b/pkg/services/object/get/remote.go @@ -20,7 +20,7 @@ func (r *request) processNode(ctx context.Context, info client.NodeInfo) bool { r.log.Debug(ctx, logs.ProcessingNode, zap.String("node_key", hex.EncodeToString(info.PublicKey()))) - rs, ok := r.getRemoteStorage(info) + rs, ok := r.getRemoteStorage(ctx, info) if !ok { return true } diff --git a/pkg/services/object/get/request.go b/pkg/services/object/get/request.go index bba767d2d8..be0950c60a 100644 --- a/pkg/services/object/get/request.go +++ b/pkg/services/object/get/request.go @@ -116,7 +116,7 @@ func (r *request) netmapLookupDepth() uint64 { return r.prm.common.NetmapLookupDepth() } -func (r *request) initEpoch() bool { +func (r *request) initEpoch(ctx context.Context) bool { r.curProcEpoch = r.netmapEpoch() if r.curProcEpoch > 0 { return true @@ -129,7 +129,7 @@ func (r *request) initEpoch() bool { r.status = statusUndefined r.err = err - r.log.Debug(context.Background(), logs.CouldNotGetCurrentEpochNumber, zap.Error(err)) + r.log.Debug(ctx, logs.CouldNotGetCurrentEpochNumber, zap.Error(err)) return false case err == nil: @@ -138,7 +138,7 @@ func (r *request) initEpoch() bool { } } -func (r *request) generateTraverser(addr oid.Address) (*placement.Traverser, bool) { +func (r *request) generateTraverser(ctx context.Context, addr oid.Address) (*placement.Traverser, bool) { obj := addr.Object() t, _, err := r.traverserGenerator.GenerateTraverser(addr.Container(), &obj, r.curProcEpoch) @@ -148,7 +148,7 @@ func (r *request) generateTraverser(addr oid.Address) (*placement.Traverser, boo r.status = statusUndefined r.err = err - r.log.Debug(context.Background(), logs.GetCouldNotGenerateContainerTraverser, zap.Error(err)) + r.log.Debug(ctx, logs.GetCouldNotGenerateContainerTraverser, zap.Error(err)) return nil, false case err == nil: @@ -156,13 +156,13 @@ func (r *request) generateTraverser(addr oid.Address) (*placement.Traverser, boo } } -func (r *request) getRemoteStorage(info clientcore.NodeInfo) (remoteStorage, bool) { +func (r *request) getRemoteStorage(ctx context.Context, info clientcore.NodeInfo) (remoteStorage, bool) { rs, err := r.remoteStorageConstructor.Get(info) if err != nil { r.status = statusUndefined r.err = err - r.log.Debug(context.Background(), logs.GetCouldNotConstructRemoteNodeClient) + r.log.Debug(ctx, logs.GetCouldNotConstructRemoteNodeClient) return nil, false } diff --git a/pkg/services/object/metrics.go b/pkg/services/object/metrics.go index 377350fddb..19748e9383 100644 --- a/pkg/services/object/metrics.go +++ b/pkg/services/object/metrics.go @@ -64,11 +64,11 @@ func (m MetricCollector) Get(req *object.GetRequest, stream GetObjectStream) (er return } -func (m MetricCollector) Put() (PutObjectStream, error) { +func (m MetricCollector) Put(ctx context.Context) (PutObjectStream, error) { if m.enabled { t := time.Now() - stream, err := m.next.Put() + stream, err := m.next.Put(ctx) if err != nil { return nil, err } @@ -79,14 +79,14 @@ func (m MetricCollector) Put() (PutObjectStream, error) { start: t, }, nil } - return m.next.Put() + return m.next.Put(ctx) } -func (m MetricCollector) Patch() (PatchObjectStream, error) { +func (m MetricCollector) Patch(ctx context.Context) (PatchObjectStream, error) { if m.enabled { t := time.Now() - stream, err := m.next.Patch() + stream, err := m.next.Patch(ctx) if err != nil { return nil, err } @@ -97,7 +97,7 @@ func (m MetricCollector) Patch() (PatchObjectStream, error) { start: t, }, nil } - return m.next.Patch() + return m.next.Patch(ctx) } func (m MetricCollector) PutSingle(ctx context.Context, request *object.PutSingleRequest) (*object.PutSingleResponse, error) { diff --git a/pkg/services/object/response.go b/pkg/services/object/response.go index 3787b41684..80c971e8f7 100644 --- a/pkg/services/object/response.go +++ b/pkg/services/object/response.go @@ -80,8 +80,8 @@ func (s *putStreamResponser) CloseAndRecv(ctx context.Context) (*object.PutRespo return r, nil } -func (s *ResponseService) Put() (PutObjectStream, error) { - stream, err := s.svc.Put() +func (s *ResponseService) Put(ctx context.Context) (PutObjectStream, error) { + stream, err := s.svc.Put(ctx) if err != nil { return nil, fmt.Errorf("could not create Put object streamer: %w", err) } @@ -109,8 +109,8 @@ func (s *patchStreamResponser) CloseAndRecv(ctx context.Context) (*object.PatchR return r, nil } -func (s *ResponseService) Patch() (PatchObjectStream, error) { - stream, err := s.svc.Patch() +func (s *ResponseService) Patch(ctx context.Context) (PatchObjectStream, error) { + stream, err := s.svc.Patch(ctx) if err != nil { return nil, fmt.Errorf("could not create Put object streamer: %w", err) } diff --git a/pkg/services/object/search/search.go b/pkg/services/object/search/search.go index bb5c720ffb..e24da975de 100644 --- a/pkg/services/object/search/search.go +++ b/pkg/services/object/search/search.go @@ -23,7 +23,7 @@ func (exec *execCtx) execute(ctx context.Context) error { exec.log.Debug(ctx, logs.ServingRequest) err := exec.executeLocal(ctx) - exec.logResult(err) + exec.logResult(ctx, err) if exec.isLocal() { exec.log.Debug(ctx, logs.SearchReturnResultDirectly) @@ -31,15 +31,15 @@ func (exec *execCtx) execute(ctx context.Context) error { } err = exec.executeOnContainer(ctx) - exec.logResult(err) + exec.logResult(ctx, err) return err } -func (exec *execCtx) logResult(err error) { +func (exec *execCtx) logResult(ctx context.Context, err error) { switch { default: - exec.log.Debug(context.Background(), logs.OperationFinishedWithError, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.OperationFinishedWithError, zap.String("error", err.Error())) case err == nil: - exec.log.Debug(context.Background(), logs.OperationFinishedSuccessfully) + exec.log.Debug(ctx, logs.OperationFinishedSuccessfully) } } diff --git a/pkg/services/object/server.go b/pkg/services/object/server.go index c570e9d8e9..e652939770 100644 --- a/pkg/services/object/server.go +++ b/pkg/services/object/server.go @@ -41,8 +41,8 @@ type PatchObjectStream interface { // serving v2 Object service. type ServiceServer interface { Get(*object.GetRequest, GetObjectStream) error - Put() (PutObjectStream, error) - Patch() (PatchObjectStream, error) + Put(context.Context) (PutObjectStream, error) + Patch(context.Context) (PatchObjectStream, error) Head(context.Context, *object.HeadRequest) (*object.HeadResponse, error) Search(*object.SearchRequest, SearchStream) error Delete(context.Context, *object.DeleteRequest) (*object.DeleteResponse, error) diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 2c5e794e95..2b44227a52 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -103,8 +103,8 @@ func (s *putStreamSigner) CloseAndRecv(ctx context.Context) (resp *object.PutRes return resp, s.sigSvc.SignResponse(resp, err) } -func (s *SignService) Put() (PutObjectStream, error) { - stream, err := s.svc.Put() +func (s *SignService) Put(ctx context.Context) (PutObjectStream, error) { + stream, err := s.svc.Put(ctx) if err != nil { return nil, fmt.Errorf("could not create Put object streamer: %w", err) } @@ -139,8 +139,8 @@ func (s *patchStreamSigner) CloseAndRecv(ctx context.Context) (resp *object.Patc return resp, s.sigSvc.SignResponse(resp, err) } -func (s *SignService) Patch() (PatchObjectStream, error) { - stream, err := s.svc.Patch() +func (s *SignService) Patch(ctx context.Context) (PatchObjectStream, error) { + stream, err := s.svc.Patch(ctx) if err != nil { return nil, fmt.Errorf("could not create Put object streamer: %w", err) } diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index 1438a0ea23..0b3676edb5 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -87,12 +87,12 @@ func (c *TransportSplitter) Get(req *object.GetRequest, stream GetObjectStream) }) } -func (c TransportSplitter) Put() (PutObjectStream, error) { - return c.next.Put() +func (c TransportSplitter) Put(ctx context.Context) (PutObjectStream, error) { + return c.next.Put(ctx) } -func (c TransportSplitter) Patch() (PatchObjectStream, error) { - return c.next.Patch() +func (c TransportSplitter) Patch(ctx context.Context) (PatchObjectStream, error) { + return c.next.Patch(ctx) } func (c TransportSplitter) Head(ctx context.Context, request *object.HeadRequest) (*object.HeadResponse, error) { diff --git a/pkg/services/object/util/log.go b/pkg/services/object/util/log.go index 5075344a4f..a9f875d8dd 100644 --- a/pkg/services/object/util/log.go +++ b/pkg/services/object/util/log.go @@ -10,8 +10,8 @@ import ( ) // LogServiceError writes error message of object service to provided logger. -func LogServiceError(l *logger.Logger, req string, node network.AddressGroup, err error) { - l.Error(context.Background(), logs.UtilObjectServiceError, +func LogServiceError(ctx context.Context, l *logger.Logger, req string, node network.AddressGroup, err error) { + l.Error(ctx, logs.UtilObjectServiceError, zap.String("node", network.StringifyGroup(node)), zap.String("request", req), zap.String("error", err.Error()), @@ -19,8 +19,8 @@ func LogServiceError(l *logger.Logger, req string, node network.AddressGroup, er } // LogWorkerPoolError writes debug error message of object worker pool to provided logger. -func LogWorkerPoolError(l *logger.Logger, req string, err error) { - l.Error(context.Background(), logs.UtilCouldNotPushTaskToWorkerPool, +func LogWorkerPoolError(ctx context.Context, l *logger.Logger, req string, err error) { + l.Error(ctx, logs.UtilCouldNotPushTaskToWorkerPool, zap.String("request", req), zap.String("error", err.Error()), ) diff --git a/pkg/services/object_manager/tombstone/checker.go b/pkg/services/object_manager/tombstone/checker.go index 6a9706b9e5..a4e36c2dc6 100644 --- a/pkg/services/object_manager/tombstone/checker.go +++ b/pkg/services/object_manager/tombstone/checker.go @@ -63,7 +63,7 @@ func (g *ExpirationChecker) IsTombstoneAvailable(ctx context.Context, a oid.Addr ) } else { if ts != nil { - return g.handleTS(addrStr, ts, epoch) + return g.handleTS(ctx, addrStr, ts, epoch) } } @@ -72,12 +72,12 @@ func (g *ExpirationChecker) IsTombstoneAvailable(ctx context.Context, a oid.Addr return false } -func (g *ExpirationChecker) handleTS(addr string, ts *objectSDK.Object, reqEpoch uint64) bool { +func (g *ExpirationChecker) handleTS(ctx context.Context, addr string, ts *objectSDK.Object, reqEpoch uint64) bool { for _, atr := range ts.Attributes() { if atr.Key() == objectV2.SysAttributeExpEpoch { epoch, err := strconv.ParseUint(atr.Value(), 10, 64) if err != nil { - g.log.Warn(context.Background(), + g.log.Warn(ctx, logs.TombstoneExpirationParseFailure, zap.Error(err), ) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index c82680a1e3..2e5e54dfd8 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -122,7 +122,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe shortage-- } else if nodes[i].Status().IsMaintenance() { - shortage, uncheckedCopies = p.handleMaintenance(nodes[i], checkedNodes, shortage, uncheckedCopies) + shortage, uncheckedCopies = p.handleMaintenance(ctx, nodes[i], checkedNodes, shortage, uncheckedCopies) } else { if status := checkedNodes.processStatus(nodes[i]); status.Processed() { if status == nodeHoldsObject { @@ -149,7 +149,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe checkedNodes.submitReplicaCandidate(nodes[i]) continue } else if client.IsErrNodeUnderMaintenance(err) { - shortage, uncheckedCopies = p.handleMaintenance(nodes[i], checkedNodes, shortage, uncheckedCopies) + shortage, uncheckedCopies = p.handleMaintenance(ctx, nodes[i], checkedNodes, shortage, uncheckedCopies) } else { p.log.Error(ctx, logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", addr), @@ -173,12 +173,12 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe // prevent spam with new replicas. // However, additional copies should not be removed in this case, // because we can remove the only copy this way. -func (p *Policer) handleMaintenance(node netmap.NodeInfo, checkedNodes nodeCache, shortage uint32, uncheckedCopies int) (uint32, int) { +func (p *Policer) handleMaintenance(ctx context.Context, node netmap.NodeInfo, checkedNodes nodeCache, shortage uint32, uncheckedCopies int) (uint32, int) { checkedNodes.submitReplicaHolder(node) shortage-- uncheckedCopies++ - p.log.Debug(context.Background(), logs.PolicerConsiderNodeUnderMaintenanceAsOK, + p.log.Debug(ctx, logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(node)), ) return shortage, uncheckedCopies diff --git a/pkg/services/tree/getsubtree_test.go b/pkg/services/tree/getsubtree_test.go index 95bdda34b7..e7a13827ec 100644 --- a/pkg/services/tree/getsubtree_test.go +++ b/pkg/services/tree/getsubtree_test.go @@ -131,7 +131,7 @@ func TestGetSubTreeOrderAsc(t *testing.T) { t.Run("boltdb forest", func(t *testing.T) { p := pilorama.NewBoltForest(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))) require.NoError(t, p.Open(context.Background(), 0o644)) - require.NoError(t, p.Init()) + require.NoError(t, p.Init(context.Background())) testGetSubTreeOrderAsc(t, p) }) } diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index e2249c9fb8..c48a312fb6 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -388,7 +388,7 @@ func (s *Service) syncLoop(ctx context.Context) { break } - newMap, cnrsToSync := s.containersToSync(cnrs) + newMap, cnrsToSync := s.containersToSync(ctx, cnrs) s.syncContainers(ctx, cnrsToSync) @@ -475,14 +475,14 @@ func (s *Service) removeContainers(ctx context.Context, newContainers map[cid.ID } } -func (s *Service) containersToSync(cnrs []cid.ID) (map[cid.ID]struct{}, []cid.ID) { +func (s *Service) containersToSync(ctx context.Context, cnrs []cid.ID) (map[cid.ID]struct{}, []cid.ID) { newMap := make(map[cid.ID]struct{}, len(s.cnrMap)) cnrsToSync := make([]cid.ID, 0, len(cnrs)) for _, cnr := range cnrs { _, pos, err := s.getContainerNodes(cnr) if err != nil { - s.log.Error(context.Background(), logs.TreeCouldNotCalculateContainerNodes, + s.log.Error(ctx, logs.TreeCouldNotCalculateContainerNodes, zap.Stringer("cid", cnr), zap.Error(err)) continue diff --git a/pkg/util/http/calls.go b/pkg/util/http/calls.go index a9877e007f..8569ec7341 100644 --- a/pkg/util/http/calls.go +++ b/pkg/util/http/calls.go @@ -32,8 +32,8 @@ func (x *Server) Serve() error { // // Once Shutdown has been called on a server, it may not be reused; // future calls to Serve method will have no effect. -func (x *Server) Shutdown() error { - ctx, cancel := context.WithTimeout(context.Background(), x.shutdownTimeout) +func (x *Server) Shutdown(ctx context.Context) error { + ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), x.shutdownTimeout) err := x.srv.Shutdown(ctx) diff --git a/scripts/populate-metabase/main.go b/scripts/populate-metabase/main.go index 6f6b233cf4..8c4ea41ada 100644 --- a/scripts/populate-metabase/main.go +++ b/scripts/populate-metabase/main.go @@ -91,15 +91,15 @@ func populate() (err error) { return fmt.Errorf("couldn't open the metabase: %w", err) } defer func() { - if errOnClose := db.Close(); errOnClose != nil { + if errOnClose := db.Close(ctx); errOnClose != nil { err = errors.Join( err, - fmt.Errorf("couldn't close the metabase: %w", db.Close()), + fmt.Errorf("couldn't close the metabase: %w", db.Close(ctx)), ) } }() - if err = db.Init(); err != nil { + if err = db.Init(ctx); err != nil { return fmt.Errorf("couldn't init the metabase: %w", err) } From 612b34d5708c23f888f75f6b6b1e5e87efdeede1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 7 Nov 2024 14:37:42 +0300 Subject: [PATCH 1000/1413] [#1437] logger: Add caller skip to log original caller position Signed-off-by: Dmitrii Stepanov --- pkg/util/logger/logger.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index b3a1b9b943..19d3f1ed10 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -131,6 +131,7 @@ func newConsoleLogger(prm *Prm) (*Logger, error) { lZap, err := c.Build( zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), + zap.AddCallerSkip(1), ) if err != nil { return nil, err @@ -167,7 +168,7 @@ func newJournaldLogger(prm *Prm) (*Logger, error) { zapjournald.SyslogPid(), }) - lZap := zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel))) + lZap := zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), zap.AddCallerSkip(1)) l := &Logger{z: lZap, lvl: lvl} prm._log = l @@ -190,6 +191,6 @@ func (l *Logger) With(fields ...zap.Field) *Logger { func NewLoggerWrapper(z *zap.Logger) *Logger { return &Logger{ - z: z, + z: z.WithOptions(zap.AddCallerSkip(1)), } } From c6066d6ee4da0e1ac193ad986ca2b8c470f070f7 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 12 Nov 2024 17:15:23 +0300 Subject: [PATCH 1001/1413] [#1491] engine/test: Use more suitable testing utils here and there Use `setShardsNum` instead of `setInitializedShards` wherever possible. Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/delete_test.go | 6 +----- pkg/local_object_storage/engine/engine_test.go | 7 +------ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 0904c98204..e095e4bbdb 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -49,11 +49,7 @@ func TestDeleteBigObject(t *testing.T) { link.SetSplitID(splitID) link.SetChildren(childIDs...) - s1 := testNewShard(t) - s2 := testNewShard(t) - s3 := testNewShard(t) - - e := testNewEngine(t).setInitializedShards(t, s1, s2, s3).engine + e := testNewEngine(t).setShardsNum(t, 3).engine e.log = test.NewLogger(t) defer e.Close(context.Background()) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 88c523b765..44bda2cbc9 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -43,12 +43,7 @@ func BenchmarkExists(b *testing.B) { } func benchmarkExists(b *testing.B, shardNum int) { - shards := make([]*shard.Shard, shardNum) - for i := range shardNum { - shards[i] = testNewShard(b) - } - - e := testNewEngine(b).setInitializedShards(b, shards...).engine + e := testNewEngine(b).setShardsNum(b, shardNum).engine defer func() { require.NoError(b, e.Close(context.Background())) }() addr := oidtest.Address() From 7ef36749d0c17d7c4f1da0e684f3db7e7ab69e61 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 13 Nov 2024 11:59:42 +0300 Subject: [PATCH 1002/1413] [#1491] engine/test: Move `BenchmarkExists` to `exists_test.go` Move `BenchmarkExists` from `engine_test.go` to `exists_test.go` for better organization and clarity. Signed-off-by: Aleksey Savchuk --- .../engine/engine_test.go | 44 ---------------- .../engine/exists_test.go | 51 +++++++++++++++++++ 2 files changed, 51 insertions(+), 44 deletions(-) create mode 100644 pkg/local_object_storage/engine/exists_test.go diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 44bda2cbc9..bac35917c2 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -10,17 +10,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - "git.frostfs.info/TrueCloudLab/hrw" - "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) @@ -30,44 +24,6 @@ func (s epochState) CurrentEpoch() uint64 { return 0 } -func BenchmarkExists(b *testing.B) { - b.Run("2 shards", func(b *testing.B) { - benchmarkExists(b, 2) - }) - b.Run("4 shards", func(b *testing.B) { - benchmarkExists(b, 4) - }) - b.Run("8 shards", func(b *testing.B) { - benchmarkExists(b, 8) - }) -} - -func benchmarkExists(b *testing.B, shardNum int) { - e := testNewEngine(b).setShardsNum(b, shardNum).engine - defer func() { require.NoError(b, e.Close(context.Background())) }() - - addr := oidtest.Address() - for range 100 { - obj := testutil.GenerateObjectWithCID(cidtest.ID()) - err := Put(context.Background(), e, obj, false) - if err != nil { - b.Fatal(err) - } - } - - b.ReportAllocs() - b.ResetTimer() - for range b.N { - var shPrm shard.ExistsPrm - shPrm.Address = addr - shPrm.ParentAddress = oid.Address{} - ok, _, err := e.exists(context.Background(), shPrm) - if err != nil || ok { - b.Fatalf("%t %v", ok, err) - } - } -} - type testEngineWrapper struct { engine *StorageEngine shardIDs []*shard.ID diff --git a/pkg/local_object_storage/engine/exists_test.go b/pkg/local_object_storage/engine/exists_test.go new file mode 100644 index 0000000000..e2e5ff13e4 --- /dev/null +++ b/pkg/local_object_storage/engine/exists_test.go @@ -0,0 +1,51 @@ +package engine + +import ( + "context" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + "github.com/stretchr/testify/require" +) + +func BenchmarkExists(b *testing.B) { + b.Run("2 shards", func(b *testing.B) { + benchmarkExists(b, 2) + }) + b.Run("4 shards", func(b *testing.B) { + benchmarkExists(b, 4) + }) + b.Run("8 shards", func(b *testing.B) { + benchmarkExists(b, 8) + }) +} + +func benchmarkExists(b *testing.B, shardNum int) { + e := testNewEngine(b).setShardsNum(b, shardNum).engine + defer func() { require.NoError(b, e.Close(context.Background())) }() + + addr := oidtest.Address() + for range 100 { + obj := testutil.GenerateObjectWithCID(cidtest.ID()) + err := Put(context.Background(), e, obj, false) + if err != nil { + b.Fatal(err) + } + } + + b.ReportAllocs() + b.ResetTimer() + for range b.N { + var shPrm shard.ExistsPrm + shPrm.Address = addr + shPrm.ParentAddress = oid.Address{} + ok, _, err := e.exists(context.Background(), shPrm) + if err != nil || ok { + b.Fatalf("%t %v", ok, err) + } + } +} From 7fc6101bec418f6a5540a1ecf3626be8251d2696 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 13 Nov 2024 13:30:16 +0300 Subject: [PATCH 1003/1413] [#1491] engine/test: Rework engine test utils - Remove `testNewShard` and `setInitializedShards` because they violated the default engine workflow. The correct workflow is: first use `New()`, followed by `Open()`, and then `Init()`. As a result, adding new logic to `(*StorageEngine).Init` caused several tests to fail with a panic when attempting to access uninitialized resources. Now, all engines created with the test utils must be initialized manually. The new helper method `prepare` can be used for that purpose. - Additionally, `setInitializedShards` hardcoded the shard worker pool size, which prevented it from being configured in tests and benchmarks. This has been fixed as well. - Ensure engine initialization is done wherever it was missing. - Refactor `setShardsNumOpts`, `setShardsNumAdditionalOpts`, and `setShardsNum`. Make them all depend on `setShardsNumOpts`. Signed-off-by: Aleksey Savchuk --- .../engine/control_test.go | 8 +- .../engine/delete_test.go | 16 +-- .../engine/engine_test.go | 129 +++++++----------- pkg/local_object_storage/engine/error_test.go | 4 +- .../engine/evacuate_test.go | 5 +- .../engine/exists_test.go | 2 +- pkg/local_object_storage/engine/head_test.go | 8 +- .../engine/inhume_test.go | 13 +- pkg/local_object_storage/engine/list_test.go | 5 +- pkg/local_object_storage/engine/lock_test.go | 17 +-- .../engine/shards_test.go | 4 +- 11 files changed, 88 insertions(+), 123 deletions(-) diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index 83babeca33..c9efc312ca 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -164,7 +164,7 @@ func testEngineFailInitAndReload(t *testing.T, degradedMode bool, opts []shard.O } func TestExecBlocks(t *testing.T) { - e := testNewEngine(t).setShardsNum(t, 2).engine // number doesn't matter in this test, 2 is several but not many + e := testNewEngine(t).setShardsNum(t, 2).prepare(t).engine // number doesn't matter in this test, 2 is several but not many // put some object obj := testutil.GenerateObjectWithCID(cidtest.ID()) @@ -302,7 +302,8 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str meta.WithEpochState(epochState{}), ), } - }) + }). + prepare(t) e, ids := te.engine, te.shardIDs for _, id := range ids { @@ -312,8 +313,5 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str require.Equal(t, num, len(e.shards)) require.Equal(t, num, len(e.shardPools)) - require.NoError(t, e.Open(context.Background())) - require.NoError(t, e.Init(context.Background())) - return e, currShards } diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index e095e4bbdb..0dd2e94bb4 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -49,9 +48,8 @@ func TestDeleteBigObject(t *testing.T) { link.SetSplitID(splitID) link.SetChildren(childIDs...) - e := testNewEngine(t).setShardsNum(t, 3).engine - e.log = test.NewLogger(t) - defer e.Close(context.Background()) + e := testNewEngine(t).setShardsNum(t, 3).prepare(t).engine + defer func() { require.NoError(t, e.Close(context.Background())) }() for i := range children { require.NoError(t, Put(context.Background(), e, children[i], false)) @@ -115,11 +113,13 @@ func TestDeleteBigObjectWithoutGC(t *testing.T) { link.SetSplitID(splitID) link.SetChildren(childIDs...) - s1 := testNewShard(t, shard.WithDisabledGC()) + te := testNewEngine(t).setShardsNumAdditionalOpts(t, 1, func(_ int) []shard.Option { + return []shard.Option{shard.WithDisabledGC()} + }).prepare(t) + e := te.engine + defer func() { require.NoError(t, e.Close(context.Background())) }() - e := testNewEngine(t).setInitializedShards(t, s1).engine - e.log = test.NewLogger(t) - defer e.Close(context.Background()) + s1 := te.shards[0] for i := range children { require.NoError(t, Put(context.Background(), e, children[i], false)) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index bac35917c2..a7cb90bae6 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -3,7 +3,6 @@ package engine import ( "context" "path/filepath" - "sync/atomic" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" @@ -26,68 +25,77 @@ func (s epochState) CurrentEpoch() uint64 { type testEngineWrapper struct { engine *StorageEngine + shards []*shard.Shard shardIDs []*shard.ID } func testNewEngine(t testing.TB, opts ...Option) *testEngineWrapper { - engine := New(WithLogger(test.NewLogger(t))) - for _, opt := range opts { - opt(engine.cfg) - } - return &testEngineWrapper{ - engine: engine, - } -} - -func (te *testEngineWrapper) setInitializedShards(t testing.TB, shards ...*shard.Shard) *testEngineWrapper { - for _, s := range shards { - pool, err := ants.NewPool(10, ants.WithNonblocking(true)) - require.NoError(t, err) - - te.engine.shards[s.ID().String()] = hashedShard{ - shardWrapper: shardWrapper{ - errorCount: new(atomic.Uint32), - Shard: s, - }, - hash: hrw.StringHash(s.ID().String()), - } - te.engine.shardPools[s.ID().String()] = pool - te.shardIDs = append(te.shardIDs, s.ID()) - } - return te + opts = append(testGetDefaultEngineOptions(t), opts...) + return &testEngineWrapper{engine: New(opts...)} } func (te *testEngineWrapper) setShardsNum(t testing.TB, num int) *testEngineWrapper { - shards := make([]*shard.Shard, 0, num) - - for range num { - shards = append(shards, testNewShard(t)) - } - - return te.setInitializedShards(t, shards...) + return te.setShardsNumOpts(t, num, func(_ int) []shard.Option { + return testGetDefaultShardOptions(t) + }) } -func (te *testEngineWrapper) setShardsNumOpts(t testing.TB, num int, shardOpts func(id int) []shard.Option) *testEngineWrapper { +func (te *testEngineWrapper) setShardsNumOpts( + t testing.TB, num int, shardOpts func(id int) []shard.Option, +) *testEngineWrapper { + te.shards = make([]*shard.Shard, num) + te.shardIDs = make([]*shard.ID, num) for i := range num { - opts := shardOpts(i) - id, err := te.engine.AddShard(context.Background(), opts...) + shard, err := te.engine.createShard(context.Background(), shardOpts(i)) require.NoError(t, err) - te.shardIDs = append(te.shardIDs, id) + require.NoError(t, te.engine.addShard(shard)) + te.shards[i] = shard + te.shardIDs[i] = shard.ID() } + require.Len(t, te.engine.shards, num) + require.Len(t, te.engine.shardPools, num) return te } -func (te *testEngineWrapper) setShardsNumAdditionalOpts(t testing.TB, num int, shardOpts func(id int) []shard.Option) *testEngineWrapper { - for i := range num { - defaultOpts := testDefaultShardOptions(t) - opts := append(defaultOpts, shardOpts(i)...) - id, err := te.engine.AddShard(context.Background(), opts...) - require.NoError(t, err) - te.shardIDs = append(te.shardIDs, id) - } +func (te *testEngineWrapper) setShardsNumAdditionalOpts( + t testing.TB, num int, shardOpts func(id int) []shard.Option, +) *testEngineWrapper { + return te.setShardsNumOpts(t, num, func(id int) []shard.Option { + return append(testGetDefaultShardOptions(t), shardOpts(id)...) + }) +} + +// prepare calls Open and Init on the created engine. +func (te *testEngineWrapper) prepare(t testing.TB) *testEngineWrapper { + require.NoError(t, te.engine.Open(context.Background())) + require.NoError(t, te.engine.Init(context.Background())) return te } +func testGetDefaultEngineOptions(t testing.TB) []Option { + return []Option{ + WithLogger(test.NewLogger(t)), + } +} + +func testGetDefaultShardOptions(t testing.TB) []shard.Option { + return []shard.Option{ + shard.WithLogger(test.NewLogger(t)), + shard.WithBlobStorOptions( + blobstor.WithStorages( + newStorages(t, t.TempDir(), 1<<20)), + blobstor.WithLogger(test.NewLogger(t)), + ), + shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), + shard.WithMetaBaseOptions( + meta.WithPath(filepath.Join(t.TempDir(), "metabase")), + meta.WithPermissions(0o700), + meta.WithEpochState(epochState{}), + meta.WithLogger(test.NewLogger(t)), + ), + } +} + func newStorages(t testing.TB, root string, smallSize uint64) []blobstor.SubStorage { return []blobstor.SubStorage{ { @@ -137,34 +145,3 @@ func newTestStorages(root string, smallSize uint64) ([]blobstor.SubStorage, *tes }, }, smallFileStorage, largeFileStorage } - -func testNewShard(t testing.TB, opts ...shard.Option) *shard.Shard { - sid, err := generateShardID() - require.NoError(t, err) - - shardOpts := append([]shard.Option{shard.WithID(sid)}, testDefaultShardOptions(t)...) - s := shard.New(append(shardOpts, opts...)...) - - require.NoError(t, s.Open(context.Background())) - require.NoError(t, s.Init(context.Background())) - - return s -} - -func testDefaultShardOptions(t testing.TB) []shard.Option { - return []shard.Option{ - shard.WithLogger(test.NewLogger(t)), - shard.WithBlobStorOptions( - blobstor.WithStorages( - newStorages(t, t.TempDir(), 1<<20)), - blobstor.WithLogger(test.NewLogger(t)), - ), - shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), - shard.WithMetaBaseOptions( - meta.WithPath(filepath.Join(t.TempDir(), "metabase")), - meta.WithPermissions(0o700), - meta.WithEpochState(epochState{}), - meta.WithLogger(test.NewLogger(t)), - ), - } -} diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index 57c423764a..d68a7e826b 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -67,10 +67,8 @@ func newEngineWithErrorThreshold(t testing.TB, dir string, errThreshold uint32) pilorama.WithPath(filepath.Join(dir, fmt.Sprintf("%d.pilorama", id))), pilorama.WithPerm(0o700)), } - }) + }).prepare(t) e := te.engine - require.NoError(t, e.Open(context.Background())) - require.NoError(t, e.Init(context.Background())) for i, id := range te.shardIDs { testShards[i].id = id diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 54eacc3f28..beab8384e3 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -75,10 +75,9 @@ func newEngineEvacuate(t *testing.T, shardNum int, objPerShard int) (*StorageEng pilorama.WithPerm(0o700), ), } - }) + }). + prepare(t) e, ids := te.engine, te.shardIDs - require.NoError(t, e.Open(context.Background())) - require.NoError(t, e.Init(context.Background())) objects := make([]*objectSDK.Object, 0, objPerShard*len(ids)) treeID := "version" diff --git a/pkg/local_object_storage/engine/exists_test.go b/pkg/local_object_storage/engine/exists_test.go index e2e5ff13e4..1b51c10dc9 100644 --- a/pkg/local_object_storage/engine/exists_test.go +++ b/pkg/local_object_storage/engine/exists_test.go @@ -25,7 +25,7 @@ func BenchmarkExists(b *testing.B) { } func benchmarkExists(b *testing.B, shardNum int) { - e := testNewEngine(b).setShardsNum(b, shardNum).engine + e := testNewEngine(b).setShardsNum(b, shardNum).prepare(b).engine defer func() { require.NoError(b, e.Close(context.Background())) }() addr := oidtest.Address() diff --git a/pkg/local_object_storage/engine/head_test.go b/pkg/local_object_storage/engine/head_test.go index 5afc50f078..f9db81f169 100644 --- a/pkg/local_object_storage/engine/head_test.go +++ b/pkg/local_object_storage/engine/head_test.go @@ -39,11 +39,11 @@ func TestHeadRaw(t *testing.T) { link.SetSplitID(splitID) t.Run("virtual object split in different shards", func(t *testing.T) { - s1 := testNewShard(t) - s2 := testNewShard(t) + te := testNewEngine(t).setShardsNum(t, 2).prepare(t) + e := te.engine + defer func() { require.NoError(t, e.Close(context.Background())) }() - e := testNewEngine(t).setInitializedShards(t, s1, s2).engine - defer e.Close(context.Background()) + s1, s2 := te.shards[0], te.shards[1] var putPrmLeft shard.PutPrm putPrmLeft.SetObject(child) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index b4fbbd8100..6980afb07e 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -37,8 +37,8 @@ func TestStorageEngine_Inhume(t *testing.T) { t.Run("delete small object", func(t *testing.T) { t.Parallel() - e := testNewEngine(t).setShardsNum(t, 1).engine - defer e.Close(context.Background()) + e := testNewEngine(t).setShardsNum(t, 1).prepare(t).engine + defer func() { require.NoError(t, e.Close(context.Background())) }() err := Put(context.Background(), e, parent, false) require.NoError(t, err) @@ -56,11 +56,12 @@ func TestStorageEngine_Inhume(t *testing.T) { t.Run("delete big object", func(t *testing.T) { t.Parallel() - s1 := testNewShard(t) - s2 := testNewShard(t) - e := testNewEngine(t).setInitializedShards(t, s1, s2).engine - defer e.Close(context.Background()) + te := testNewEngine(t).setShardsNum(t, 2).prepare(t) + e := te.engine + defer func() { require.NoError(t, e.Close(context.Background())) }() + + s1, s2 := te.shards[0], te.shards[1] var putChild shard.PutPrm putChild.SetObject(child) diff --git a/pkg/local_object_storage/engine/list_test.go b/pkg/local_object_storage/engine/list_test.go index d683b5475a..6cfa546f8e 100644 --- a/pkg/local_object_storage/engine/list_test.go +++ b/pkg/local_object_storage/engine/list_test.go @@ -68,10 +68,7 @@ func TestListWithCursor(t *testing.T) { meta.WithEpochState(epochState{}), ), } - }).engine - require.NoError(t, e.Open(context.Background())) - require.NoError(t, e.Init(context.Background())) - + }).prepare(t).engine defer func() { require.NoError(t, e.Close(context.Background())) }() diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 7e15c76f5d..feca9cb69d 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -57,11 +57,9 @@ func TestLockUserScenario(t *testing.T) { }), shard.WithTombstoneSource(tss{lockerExpiresAfter}), } - }) + }). + prepare(t) e := testEngine.engine - require.NoError(t, e.Open(context.Background())) - require.NoError(t, e.Init(context.Background())) - defer func() { require.NoError(t, e.Close(context.Background())) }() lockerID := oidtest.ID() @@ -162,11 +160,9 @@ func TestLockExpiration(t *testing.T) { return pool }), } - }) + }). + prepare(t) e := testEngine.engine - require.NoError(t, e.Open(context.Background())) - require.NoError(t, e.Init(context.Background())) - defer func() { require.NoError(t, e.Close(context.Background())) }() const lockerExpiresAfter = 13 @@ -243,9 +239,8 @@ func TestLockForceRemoval(t *testing.T) { }), shard.WithDeletedLockCallback(e.processDeletedLocks), } - }).engine - require.NoError(t, e.Open(context.Background())) - require.NoError(t, e.Init(context.Background())) + }). + prepare(t).engine defer func() { require.NoError(t, e.Close(context.Background())) }() cnr := cidtest.ID() diff --git a/pkg/local_object_storage/engine/shards_test.go b/pkg/local_object_storage/engine/shards_test.go index 207491bd4e..0bbc7563c3 100644 --- a/pkg/local_object_storage/engine/shards_test.go +++ b/pkg/local_object_storage/engine/shards_test.go @@ -13,7 +13,7 @@ import ( func TestRemoveShard(t *testing.T) { const numOfShards = 6 - te := testNewEngine(t).setShardsNum(t, numOfShards) + te := testNewEngine(t).setShardsNum(t, numOfShards).prepare(t) e, ids := te.engine, te.shardIDs defer func() { require.NoError(t, e.Close(context.Background())) }() @@ -51,7 +51,7 @@ func TestDisableShards(t *testing.T) { const numOfShards = 2 - te := testNewEngine(t).setShardsNum(t, numOfShards) + te := testNewEngine(t).setShardsNum(t, numOfShards).prepare(t) e, ids := te.engine, te.shardIDs defer func() { require.NoError(t, e.Close(context.Background())) }() From f7cb6b4d87ec9869d371e569b49cdf418d26a756 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 13 Nov 2024 16:26:40 +0300 Subject: [PATCH 1004/1413] [#1482] Makefile: Update golangci-lint Signed-off-by: Alexander Chuprov --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c54601c73c..ecac760e97 100755 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.22 -LINT_VERSION ?= 1.61.0 -TRUECLOUDLAB_LINT_VERSION ?= 0.0.7 +LINT_VERSION ?= 1.62.0 +TRUECLOUDLAB_LINT_VERSION ?= 0.0.8 PROTOC_VERSION ?= 25.0 PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go) PROTOC_OS_VERSION=osx-x86_64 From 6dc0dc66919a19e08b6542cbdb5569b78f432121 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 18 Oct 2024 13:45:06 +0300 Subject: [PATCH 1005/1413] [#1493] shard: Take mode mutex in HandleExpiredTombstones() Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/shard/gc.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index a987d3d14d..57c21459cf 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -627,7 +627,10 @@ func (s *Shard) selectExpired(ctx context.Context, epoch uint64, addresses []oid // // Does not modify tss. func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.TombstonedObject) { - if s.GetMode().NoMetabase() { + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { return } From 1e6f132b4e59bfc7c341e44a4612de6b2924a555 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 18 Oct 2024 13:57:16 +0300 Subject: [PATCH 1006/1413] [#1493] metabase: Pass InhumePrm by value Unify with the other code, no functional changes. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/inhume.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 8d1e18729a..915de52626 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -217,7 +217,7 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes garbageBKT := tx.Bucket(garbageBucketName) graveyardBKT := tx.Bucket(graveyardBucketName) - bkt, value, err := db.getInhumeTargetBucketAndValue(garbageBKT, graveyardBKT, &prm) + bkt, value, err := db.getInhumeTargetBucketAndValue(garbageBKT, graveyardBKT, prm) if err != nil { return err } @@ -354,7 +354,7 @@ func (db *DB) applyInhumeResToCounters(tx *bbolt.Tx, res *InhumeRes) error { // 1. tombstone address if Inhume was called with // a Tombstone // 2. zeroValue if Inhume was called with a GC mark -func (db *DB) getInhumeTargetBucketAndValue(garbageBKT, graveyardBKT *bbolt.Bucket, prm *InhumePrm) (targetBucket *bbolt.Bucket, value []byte, err error) { +func (db *DB) getInhumeTargetBucketAndValue(garbageBKT, graveyardBKT *bbolt.Bucket, prm InhumePrm) (targetBucket *bbolt.Bucket, value []byte, err error) { if prm.tomb != nil { targetBucket = graveyardBKT tombKey := addressKey(*prm.tomb, make([]byte, addressKeySize)) From 44df67492f8f933c2f923e7660d9a58949e21a57 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 18 Oct 2024 14:08:57 +0300 Subject: [PATCH 1007/1413] [#1493] metabase: Split inhumeTx() into 2 functions No functional changes. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/inhume.go | 138 +++++++++++--------- 1 file changed, 73 insertions(+), 65 deletions(-) diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 915de52626..5ac0c0be5a 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -224,78 +224,86 @@ func (db *DB) inhumeTx(tx *bbolt.Tx, epoch uint64, prm InhumePrm, res *InhumeRes buf := make([]byte, addressKeySize) for i := range prm.target { - id := prm.target[i].Object() - cnr := prm.target[i].Container() - - // prevent locked objects to be inhumed - if !prm.forceRemoval && objectLocked(tx, cnr, id) { - return new(apistatus.ObjectLocked) - } - - var lockWasChecked bool - - // prevent lock objects to be inhumed - // if `Inhume` was called not with the - // `WithForceGCMark` option - if !prm.forceRemoval { - if isLockObject(tx, cnr, id) { - return ErrLockObjectRemoval - } - - lockWasChecked = true - } - - obj, err := db.get(tx, prm.target[i], buf, false, true, epoch) - targetKey := addressKey(prm.target[i], buf) - var ecErr *objectSDK.ECInfoError - if err == nil { - err = db.updateDeleteInfo(tx, garbageBKT, graveyardBKT, targetKey, cnr, obj, res) - if err != nil { - return err - } - } else if errors.As(err, &ecErr) { - err = db.inhumeECInfo(tx, epoch, prm.tomb, res, garbageBKT, graveyardBKT, ecErr.ECInfo(), cnr, bkt, value) - if err != nil { - return err - } - } - - if prm.tomb != nil { - var isTomb bool - isTomb, err = db.markAsGC(graveyardBKT, garbageBKT, targetKey) - if err != nil { - return err - } - - if isTomb { - continue - } - } - - // consider checking if target is already in graveyard? - err = bkt.Put(targetKey, value) - if err != nil { + if err := db.inhumeTxSingle(bkt, value, graveyardBKT, garbageBKT, prm.target[i], buf, epoch, prm, res); err != nil { return err } - - if prm.lockObjectHandling { - // do not perform lock check if - // it was already called - if lockWasChecked { - // inhumed object is not of - // the LOCK type - continue - } - - if isLockObject(tx, cnr, id) { - res.deletedLockObj = append(res.deletedLockObj, prm.target[i]) - } - } } return db.applyInhumeResToCounters(tx, res) } +func (db *DB) inhumeTxSingle(bkt *bbolt.Bucket, value []byte, graveyardBKT, garbageBKT *bbolt.Bucket, addr oid.Address, buf []byte, epoch uint64, prm InhumePrm, res *InhumeRes) error { + id := addr.Object() + cnr := addr.Container() + tx := bkt.Tx() + + // prevent locked objects to be inhumed + if !prm.forceRemoval && objectLocked(tx, cnr, id) { + return new(apistatus.ObjectLocked) + } + + var lockWasChecked bool + + // prevent lock objects to be inhumed + // if `Inhume` was called not with the + // `WithForceGCMark` option + if !prm.forceRemoval { + if isLockObject(tx, cnr, id) { + return ErrLockObjectRemoval + } + + lockWasChecked = true + } + + obj, err := db.get(tx, addr, buf, false, true, epoch) + targetKey := addressKey(addr, buf) + var ecErr *objectSDK.ECInfoError + if err == nil { + err = db.updateDeleteInfo(tx, garbageBKT, graveyardBKT, targetKey, cnr, obj, res) + if err != nil { + return err + } + } else if errors.As(err, &ecErr) { + err = db.inhumeECInfo(tx, epoch, prm.tomb, res, garbageBKT, graveyardBKT, ecErr.ECInfo(), cnr, bkt, value) + if err != nil { + return err + } + } + + if prm.tomb != nil { + var isTomb bool + isTomb, err = db.markAsGC(graveyardBKT, garbageBKT, targetKey) + if err != nil { + return err + } + + if isTomb { + return nil + } + } + + // consider checking if target is already in graveyard? + err = bkt.Put(targetKey, value) + if err != nil { + return err + } + + if prm.lockObjectHandling { + // do not perform lock check if + // it was already called + if lockWasChecked { + // inhumed object is not of + // the LOCK type + return nil + } + + if isLockObject(tx, cnr, id) { + res.deletedLockObj = append(res.deletedLockObj, addr) + } + } + return nil +} + func (db *DB) inhumeECInfo(tx *bbolt.Tx, epoch uint64, tomb *oid.Address, res *InhumeRes, garbageBKT *bbolt.Bucket, graveyardBKT *bbolt.Bucket, ecInfo *objectSDK.ECInfo, cnr cid.ID, targetBucket *bbolt.Bucket, value []byte, From d77a218f7c1a449369eb6d63e00ae1906984aed4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 13 Nov 2024 15:56:16 +0300 Subject: [PATCH 1008/1413] [#1493] metabase: Merge Inhume() and DropGraves() for tombstones DropGraves() is only used to drop gravemarks after a tombstone removal. Thus, it makes sense to do Inhume() and DropGraves() in one transaction. It has less overhead and no unexpected problems in case of sudden power failure. Signed-off-by: Evgenii Stratonikov --- .../metabase/delete_ec_test.go | 20 +--------- .../metabase/graveyard.go | 39 ++++++++++++------- .../metabase/graveyard_test.go | 26 ++++++++++--- pkg/local_object_storage/shard/gc.go | 21 +--------- 4 files changed, 50 insertions(+), 56 deletions(-) diff --git a/pkg/local_object_storage/metabase/delete_ec_test.go b/pkg/local_object_storage/metabase/delete_ec_test.go index 9f1f91e144..884da23ff5 100644 --- a/pkg/local_object_storage/metabase/delete_ec_test.go +++ b/pkg/local_object_storage/metabase/delete_ec_test.go @@ -130,17 +130,9 @@ func TestDeleteECObject_WithoutSplit(t *testing.T) { require.NoError(t, db.IterateOverGraveyard(context.Background(), graveyardIterationPrm)) require.Equal(t, 2, len(tombstonedObjects)) - var tombstones []oid.Address - for _, tss := range tombstonedObjects { - tombstones = append(tombstones, tss.tomb) - } - inhumePrm.SetAddresses(tombstones...) - inhumePrm.SetGCMark() - _, err = db.Inhume(context.Background(), inhumePrm) + _, err = db.InhumeTombstones(context.Background(), tombstonedObjects) require.NoError(t, err) - require.NoError(t, db.DropGraves(context.Background(), tombstonedObjects)) - // GC finds tombstone as garbage and deletes it garbageAddresses = nil @@ -374,17 +366,9 @@ func testDeleteECObjectWithSplit(t *testing.T, chunksCount int, withLinking bool require.NoError(t, db.IterateOverGraveyard(context.Background(), graveyardIterationPrm)) require.True(t, len(tombstonedObjects) == parentCount+chunksCount) - var tombstones []oid.Address - for _, tss := range tombstonedObjects { - tombstones = append(tombstones, tss.tomb) - } - inhumePrm.SetAddresses(tombstones...) - inhumePrm.SetGCMark() - _, err = db.Inhume(context.Background(), inhumePrm) + _, err = db.InhumeTombstones(context.Background(), tombstonedObjects) require.NoError(t, err) - require.NoError(t, db.DropGraves(context.Background(), tombstonedObjects)) - // GC finds tombstone as garbage and deletes it garbageAddresses = nil diff --git a/pkg/local_object_storage/metabase/graveyard.go b/pkg/local_object_storage/metabase/graveyard.go index 31f95d6ed0..b0db952b27 100644 --- a/pkg/local_object_storage/metabase/graveyard.go +++ b/pkg/local_object_storage/metabase/graveyard.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.etcd.io/bbolt" ) @@ -255,46 +256,58 @@ func graveFromKV(k, v []byte) (res TombstonedObject, err error) { return } -// DropGraves deletes tombstoned objects from the +// InhumeTombstones deletes tombstoned objects from the // graveyard bucket. // // Returns any error appeared during deletion process. -func (db *DB) DropGraves(ctx context.Context, tss []TombstonedObject) error { +func (db *DB) InhumeTombstones(ctx context.Context, tss []TombstonedObject) (InhumeRes, error) { var ( startedAt = time.Now() success = false ) defer func() { - db.metrics.AddMethodDuration("DropGraves", time.Since(startedAt), success) + db.metrics.AddMethodDuration("InhumeTombstones", time.Since(startedAt), success) }() - _, span := tracing.StartSpanFromContext(ctx, "metabase.DropGraves") + _, span := tracing.StartSpanFromContext(ctx, "metabase.InhumeTombstones") defer span.End() db.modeMtx.RLock() defer db.modeMtx.RUnlock() if db.mode.NoMetabase() { - return ErrDegradedMode + return InhumeRes{}, ErrDegradedMode } else if db.mode.ReadOnly() { - return ErrReadOnlyMode + return InhumeRes{}, ErrReadOnlyMode } buf := make([]byte, addressKeySize) + prm := InhumePrm{forceRemoval: true} + currEpoch := db.epochState.CurrentEpoch() - return db.boltDB.Batch(func(tx *bbolt.Tx) error { - bkt := tx.Bucket(graveyardBucketName) - if bkt == nil { - return nil + var res InhumeRes + + err := db.boltDB.Batch(func(tx *bbolt.Tx) error { + res = InhumeRes{inhumedByCnrID: make(map[cid.ID]ObjectCounters)} + + garbageBKT := tx.Bucket(garbageBucketName) + graveyardBKT := tx.Bucket(graveyardBucketName) + + bkt, value, err := db.getInhumeTargetBucketAndValue(garbageBKT, graveyardBKT, prm) + if err != nil { + return err } - for _, ts := range tss { - err := bkt.Delete(addressKey(ts.Address(), buf)) - if err != nil { + for i := range tss { + if err := db.inhumeTxSingle(bkt, value, graveyardBKT, garbageBKT, tss[i].Tombstone(), buf, currEpoch, prm, &res); err != nil { + return err + } + if err := graveyardBKT.Delete(addressKey(tss[i].Address(), buf)); err != nil { return err } } return nil }) + return res, err } diff --git a/pkg/local_object_storage/metabase/graveyard_test.go b/pkg/local_object_storage/metabase/graveyard_test.go index 99794e609f..ebadecc044 100644 --- a/pkg/local_object_storage/metabase/graveyard_test.go +++ b/pkg/local_object_storage/metabase/graveyard_test.go @@ -7,7 +7,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" @@ -393,7 +395,7 @@ func TestDB_IterateOverGarbage_Offset(t *testing.T) { require.False(t, iWasCalled) } -func TestDB_DropGraves(t *testing.T) { +func TestDB_InhumeTombstones(t *testing.T) { db := newDB(t) defer func() { require.NoError(t, db.Close(context.Background())) }() @@ -410,9 +412,20 @@ func TestDB_DropGraves(t *testing.T) { err = putBig(db, obj2) require.NoError(t, err) - // inhume with tombstone - addrTombstone := oidtest.Address() - addrTombstone.SetContainer(cnr) + id1, _ := obj1.ID() + id2, _ := obj2.ID() + ts := objectSDK.NewTombstone() + ts.SetMembers([]oid.ID{id1, id2}) + objTs := objectSDK.New() + objTs.SetContainerID(cnr) + objTs.SetType(objectSDK.TypeTombstone) + + data, _ := ts.Marshal() + objTs.SetPayload(data) + require.NoError(t, objectSDK.CalculateAndSetID(objTs)) + require.NoError(t, putBig(db, objTs)) + + addrTombstone := object.AddressOf(objTs) var inhumePrm meta.InhumePrm inhumePrm.SetAddresses(object.AddressOf(obj1), object.AddressOf(obj2)) @@ -435,8 +448,11 @@ func TestDB_DropGraves(t *testing.T) { require.NoError(t, err) require.Equal(t, 2, counter) - err = db.DropGraves(context.Background(), buriedTS) + res, err := db.InhumeTombstones(context.Background(), buriedTS) require.NoError(t, err) + require.EqualValues(t, 1, res.LogicInhumed()) + require.EqualValues(t, 0, res.UserInhumed()) + require.EqualValues(t, map[cid.ID]meta.ObjectCounters{cnr: {Logic: 1}}, res.InhumedByCnrID()) counter = 0 iterGravePRM.SetHandler(func(_ meta.TombstonedObject) error { diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 57c21459cf..c212f8c361 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -634,19 +634,7 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston return } - // Mark tombstones as garbage. - var pInhume meta.InhumePrm - - tsAddrs := make([]oid.Address, 0, len(tss)) - for _, ts := range tss { - tsAddrs = append(tsAddrs, ts.Tombstone()) - } - - pInhume.SetGCMark() - pInhume.SetAddresses(tsAddrs...) - - // inhume tombstones - res, err := s.metaBase.Inhume(ctx, pInhume) + res, err := s.metaBase.InhumeTombstones(ctx, tss) if err != nil { s.log.Warn(ctx, logs.ShardCouldNotMarkTombstonesAsGarbage, zap.String("error", err.Error()), @@ -666,13 +654,6 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston s.addToContainerSize(delInfo.CID.EncodeToString(), -int64(delInfo.Size)) i++ } - - // drop just processed expired tombstones - // from graveyard - err = s.metaBase.DropGraves(ctx, tss) - if err != nil { - s.log.Warn(ctx, logs.ShardCouldNotDropExpiredGraveRecords, zap.Error(err)) - } } // HandleExpiredLocks unlocks all objects which were locked by lockers. From 69c63006da57d182618eb1ef498e3aaac9888783 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 14 Nov 2024 09:52:35 +0300 Subject: [PATCH 1009/1413] [#1496] morph: Move tx waiter to morph package Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/morph.go | 49 ++++---------------------------- pkg/morph/client/waiter.go | 57 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 44 deletions(-) create mode 100644 pkg/morph/client/waiter.go diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index ca9f4fe3e4..4e33ad6e20 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -17,11 +17,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "go.uber.org/zap" ) @@ -164,48 +160,13 @@ func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error return c.cfgMorph.client.DepositEndlessNotary(ctx, depositAmount) } -var ( - errNotaryDepositFail = errors.New("notary deposit tx has faulted") - errNotaryDepositTimeout = errors.New("notary deposit tx has not appeared in the network") -) - -type waiterClient struct { - c *client.Client -} - -func (w *waiterClient) Context() context.Context { - return context.Background() -} - -func (w *waiterClient) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { - return w.c.GetApplicationLog(hash, trig) -} - -func (w *waiterClient) GetBlockCount() (uint32, error) { - return w.c.BlockCount() -} - -func (w *waiterClient) GetVersion() (*result.Version, error) { - return w.c.GetVersion() -} - func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error { - w, err := waiter.NewPollingBased(&waiterClient{c: c.cfgMorph.client}) - if err != nil { - return fmt.Errorf("could not create notary deposit waiter: %w", err) + if err := c.cfgMorph.client.WaitTxHalt(ctx, client.WaitParams{Hash: tx, ValidUntilBlock: vub}); err != nil { + return err } - res, err := w.WaitAny(ctx, vub, tx) - if err != nil { - if errors.Is(err, waiter.ErrTxNotAccepted) { - return errNotaryDepositTimeout - } - return fmt.Errorf("could not wait for notary deposit persists in chain: %w", err) - } - if res.Execution.VMState.HasFlag(vmstate.Halt) { - c.log.Info(ctx, logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) - return nil - } - return errNotaryDepositFail + + c.log.Info(ctx, logs.ClientNotaryDepositTransactionWasSuccessfullyPersisted) + return nil } func listenMorphNotifications(ctx context.Context, c *cfg) { diff --git a/pkg/morph/client/waiter.go b/pkg/morph/client/waiter.go new file mode 100644 index 0000000000..8211deac45 --- /dev/null +++ b/pkg/morph/client/waiter.go @@ -0,0 +1,57 @@ +package client + +import ( + "context" + "fmt" + + "github.com/nspcc-dev/neo-go/pkg/neorpc/result" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/waiter" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" +) + +// WaitParams represents transaction to wait for. +type WaitParams struct { + Hash util.Uint256 + ValidUntilBlock uint32 +} + +type waiterClient struct { + c *Client +} + +func (w *waiterClient) Context() context.Context { + return context.Background() +} + +func (w *waiterClient) GetApplicationLog(hash util.Uint256, trig *trigger.Type) (*result.ApplicationLog, error) { + return w.c.GetApplicationLog(hash, trig) +} + +func (w *waiterClient) GetBlockCount() (uint32, error) { + return w.c.BlockCount() +} + +func (w *waiterClient) GetVersion() (*result.Version, error) { + return w.c.GetVersion() +} + +// WaitTxHalt waits until transaction with the specified hash persists on the blockchain. +// It also checks execution result to finish in HALT state. +func (c *Client) WaitTxHalt(ctx context.Context, p WaitParams) error { + w, err := waiter.NewPollingBased(&waiterClient{c: c}) + if err != nil { + return fmt.Errorf("create tx waiter: %w", err) + } + + res, err := w.WaitAny(ctx, p.ValidUntilBlock, p.Hash) + if err != nil { + return fmt.Errorf("wait until tx persists: %w", err) + } + + if res.VMState.HasFlag(vmstate.Halt) { + return nil + } + return wrapFrostFSError(¬HaltStateError{state: res.VMState.String(), exception: res.FaultException}) +} From b65874d1c35fe194a20d25bf19c8d82c633a04b6 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 14 Nov 2024 10:01:59 +0300 Subject: [PATCH 1010/1413] [#1496] morph: Return `InvokeRes` from all invoke*() methods Signed-off-by: Evgenii Stratonikov --- .../processors/alphabet/handlers_test.go | 5 +++-- .../processors/alphabet/processor.go | 3 ++- pkg/morph/client/client.go | 8 +++---- pkg/morph/client/notary.go | 22 +++++++++---------- pkg/morph/client/static.go | 14 +++++------- 5 files changed, 25 insertions(+), 27 deletions(-) diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index 036b8055cf..ac3e2a14d5 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/timers" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -247,7 +248,7 @@ type testMorphClient struct { batchTransferedGas []batchTransferGas } -func (c *testMorphClient) Invoke(_ context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { +func (c *testMorphClient) Invoke(_ context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (client.InvokeRes, error) { c.invokedMethods = append(c.invokedMethods, invokedMethod{ contract: contract, @@ -255,7 +256,7 @@ func (c *testMorphClient) Invoke(_ context.Context, contract util.Uint160, fee f method: method, args: args, }) - return 0, nil + return client.InvokeRes{}, nil } func (c *testMorphClient) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error { diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index bf74834ed9..3992e00f34 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -8,6 +8,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/metrics" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -39,7 +40,7 @@ type ( } morphClient interface { - Invoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) + Invoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (client.InvokeRes, error) TransferGas(receiver util.Uint160, amount fixedn.Fixed8) error BatchTransferGas(receivers []util.Uint160, amount fixedn.Fixed8) error } diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index f61c6e9f9b..a0c29141bd 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -180,7 +180,7 @@ func wrapFrostFSError(err error) error { // Invoke invokes contract method by sending transaction into blockchain. // Returns valid until block value. // Supported args types: int64, string, util.Uint160, []byte and bool. -func (c *Client) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (uint32, error) { +func (c *Client) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, method string, args ...any) (InvokeRes, error) { start := time.Now() success := false defer func() { @@ -191,12 +191,12 @@ func (c *Client) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.F defer c.switchLock.RUnlock() if c.inactive { - return 0, ErrConnectionLost + return InvokeRes{}, ErrConnectionLost } txHash, vub, err := c.rpcActor.SendTunedCall(contract, method, nil, addFeeCheckerModifier(int64(fee)), args...) if err != nil { - return 0, fmt.Errorf("could not invoke %s: %w", method, err) + return InvokeRes{}, fmt.Errorf("could not invoke %s: %w", method, err) } c.logger.Debug(ctx, logs.ClientNeoClientInvoke, @@ -205,7 +205,7 @@ func (c *Client) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.F zap.Stringer("tx_hash", txHash.Reverse())) success = true - return vub, nil + return InvokeRes{Hash: txHash, VUB: vub}, nil } // TestInvokeIterator invokes contract method returning an iterator and executes cb on each element. diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 65a5e77a69..71232cb33f 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -358,12 +358,12 @@ func (c *Client) UpdateNeoFSAlphabetList(ctx context.Context, prm UpdateAlphabet // Returns valid until block value. // // `nonce` and `vub` are used only if notary is enabled. -func (c *Client) NotaryInvoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { +func (c *Client) NotaryInvoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) (InvokeRes, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() if c.inactive { - return 0, ErrConnectionLost + return InvokeRes{}, ErrConnectionLost } if c.notary == nil { @@ -378,12 +378,12 @@ func (c *Client) NotaryInvoke(ctx context.Context, contract util.Uint160, fee fi // not expected to be signed by the current node. // // Considered to be used by non-IR nodes. -func (c *Client) NotaryInvokeNotAlpha(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, vubP *uint32, method string, args ...any) (uint32, error) { +func (c *Client) NotaryInvokeNotAlpha(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, vubP *uint32, method string, args ...any) (InvokeRes, error) { c.switchLock.RLock() defer c.switchLock.RUnlock() if c.inactive { - return 0, ErrConnectionLost + return InvokeRes{}, ErrConnectionLost } if c.notary == nil { @@ -446,7 +446,7 @@ func (c *Client) notaryInvokeAsCommittee(ctx context.Context, method string, non return err } -func (c *Client) notaryInvoke(ctx context.Context, committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, vub *uint32, method string, args ...any) (uint32, error) { +func (c *Client) notaryInvoke(ctx context.Context, committee, invokedByAlpha bool, contract util.Uint160, nonce uint32, vub *uint32, method string, args ...any) (InvokeRes, error) { start := time.Now() success := false defer func() { @@ -455,22 +455,22 @@ func (c *Client) notaryInvoke(ctx context.Context, committee, invokedByAlpha boo alphabetList, err := c.notary.alphabetSource() if err != nil { - return 0, err + return InvokeRes{}, err } until, err := c.getUntilValue(vub) if err != nil { - return 0, err + return InvokeRes{}, err } cosigners, err := c.notaryCosigners(invokedByAlpha, alphabetList, committee) if err != nil { - return 0, err + return InvokeRes{}, err } nAct, err := notary.NewActor(c.client, cosigners, c.acc) if err != nil { - return 0, err + return InvokeRes{}, err } mainH, fbH, untilActual, err := nAct.Notarize(nAct.MakeTunedCall(contract, method, nil, func(r *result.Invoke, t *transaction.Transaction) error { @@ -485,7 +485,7 @@ func (c *Client) notaryInvoke(ctx context.Context, committee, invokedByAlpha boo }, args...)) if err != nil && !alreadyOnChainError(err) { - return 0, err + return InvokeRes{}, err } c.logger.Debug(ctx, logs.ClientNotaryRequestInvoked, @@ -495,7 +495,7 @@ func (c *Client) notaryInvoke(ctx context.Context, committee, invokedByAlpha boo zap.String("fallback_hash", fbH.StringLE())) success = true - return until, nil + return InvokeRes{Hash: mainH, VUB: until}, nil } func (c *Client) notaryCosignersFromTx(mainTx *transaction.Transaction, alphabetList keys.PublicKeys) ([]actor.SignerAccount, error) { diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index 1e091936f0..be4c091825 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -129,7 +129,8 @@ func (i *InvokePrmOptional) SetVUB(v uint32) { } type InvokeRes struct { - VUB uint32 + Hash util.Uint256 + VUB uint32 } // Invoke calls Invoke method of Client with static internal script hash and fee. @@ -142,8 +143,6 @@ type InvokeRes struct { // If fee for the operation executed using specified method is customized, then StaticClient uses it. // Otherwise, default fee is used. func (s StaticClient) Invoke(ctx context.Context, prm InvokePrm) (InvokeRes, error) { - var res InvokeRes - var err error var vubP *uint32 if s.tryNotary { if s.alpha { @@ -170,26 +169,23 @@ func (s StaticClient) Invoke(ctx context.Context, prm InvokePrm) (InvokeRes, err vubP = &prm.vub } - res.VUB, err = s.client.NotaryInvoke(ctx, s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) - return res, err + return s.client.NotaryInvoke(ctx, s.scScriptHash, s.fee, nonce, vubP, prm.method, prm.args...) } if prm.vub > 0 { vubP = &prm.vub } - res.VUB, err = s.client.NotaryInvokeNotAlpha(ctx, s.scScriptHash, s.fee, vubP, prm.method, prm.args...) - return res, err + return s.client.NotaryInvokeNotAlpha(ctx, s.scScriptHash, s.fee, vubP, prm.method, prm.args...) } - res.VUB, err = s.client.Invoke( + return s.client.Invoke( ctx, s.scScriptHash, s.fee, prm.method, prm.args..., ) - return res, err } // TestInvokePrm groups parameters of the TestInvoke operation. From acd5babd86ec98f227a30573497af0cdcd53df87 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 14 Nov 2024 10:04:02 +0300 Subject: [PATCH 1011/1413] [#1496] morph: Merge `InvokeRes` and `WaitParams` Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/morph.go | 2 +- pkg/morph/client/waiter.go | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 4e33ad6e20..67d2d1c064 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -161,7 +161,7 @@ func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error } func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error { - if err := c.cfgMorph.client.WaitTxHalt(ctx, client.WaitParams{Hash: tx, ValidUntilBlock: vub}); err != nil { + if err := c.cfgMorph.client.WaitTxHalt(ctx, client.InvokeRes{Hash: tx, VUB: vub}); err != nil { return err } diff --git a/pkg/morph/client/waiter.go b/pkg/morph/client/waiter.go index 8211deac45..962ec1bc2a 100644 --- a/pkg/morph/client/waiter.go +++ b/pkg/morph/client/waiter.go @@ -11,12 +11,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) -// WaitParams represents transaction to wait for. -type WaitParams struct { - Hash util.Uint256 - ValidUntilBlock uint32 -} - type waiterClient struct { c *Client } @@ -39,13 +33,13 @@ func (w *waiterClient) GetVersion() (*result.Version, error) { // WaitTxHalt waits until transaction with the specified hash persists on the blockchain. // It also checks execution result to finish in HALT state. -func (c *Client) WaitTxHalt(ctx context.Context, p WaitParams) error { +func (c *Client) WaitTxHalt(ctx context.Context, p InvokeRes) error { w, err := waiter.NewPollingBased(&waiterClient{c: c}) if err != nil { return fmt.Errorf("create tx waiter: %w", err) } - res, err := w.WaitAny(ctx, p.ValidUntilBlock, p.Hash) + res, err := w.WaitAny(ctx, p.VUB, p.Hash) if err != nil { return fmt.Errorf("wait until tx persists: %w", err) } From d82f0d192691f33eb63e2d71beac433a4232b163 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 14 Nov 2024 15:09:42 +0300 Subject: [PATCH 1012/1413] [#1496] node/control: Await until SetNetmapStatus() persists Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/netmap.go | 7 +++++-- pkg/morph/client/netmap/peer.go | 4 ++-- pkg/morph/client/netmap/update_state.go | 9 ++------- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 6df9479543..9127d11232 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -421,8 +421,11 @@ func (c *cfg) updateNetMapState(ctx context.Context, stateSetter func(*nmClient. prm.SetKey(c.key.PublicKey().Bytes()) stateSetter(&prm) - _, err := c.cfgNetmap.wrapper.UpdatePeerState(ctx, prm) - return err + res, err := c.cfgNetmap.wrapper.UpdatePeerState(ctx, prm) + if err != nil { + return err + } + return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res) } type netInfo struct { diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 9617d018c3..949e8cb63a 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -58,9 +58,9 @@ func (c *Client) ForceRemovePeer(ctx context.Context, nodeInfo netmap.NodeInfo, prm.SetControlTX(true) prm.SetVUB(vub) - vub, err := c.UpdatePeerState(ctx, prm) + res, err := c.UpdatePeerState(ctx, prm) if err != nil { return 0, fmt.Errorf("updating peer state: %v", err) } - return vub, nil + return res.VUB, nil } diff --git a/pkg/morph/client/netmap/update_state.go b/pkg/morph/client/netmap/update_state.go index 971a55d33b..f9f639c199 100644 --- a/pkg/morph/client/netmap/update_state.go +++ b/pkg/morph/client/netmap/update_state.go @@ -2,7 +2,6 @@ package netmap import ( "context" - "fmt" "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -37,7 +36,7 @@ func (u *UpdatePeerPrm) SetMaintenance() { } // UpdatePeerState changes peer status through Netmap contract call. -func (c *Client) UpdatePeerState(ctx context.Context, p UpdatePeerPrm) (uint32, error) { +func (c *Client) UpdatePeerState(ctx context.Context, p UpdatePeerPrm) (client.InvokeRes, error) { method := updateStateMethod if c.client.WithNotary() && c.client.IsAlpha() { @@ -56,9 +55,5 @@ func (c *Client) UpdatePeerState(ctx context.Context, p UpdatePeerPrm) (uint32, prm.SetArgs(int64(p.state), p.key) prm.InvokePrmOptional = p.InvokePrmOptional - res, err := c.client.Invoke(ctx, prm) - if err != nil { - return 0, fmt.Errorf("could not invoke smart contract: %w", err) - } - return res.VUB, nil + return c.client.Invoke(ctx, prm) } From 9f4ce600ac98bd34bb097b73d45b148ec4f75b26 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 19 Nov 2024 16:25:16 +0300 Subject: [PATCH 1013/1413] [#1505] adm: Allow to manage additional keys in frostfsid Signed-off-by: Evgenii Stratonikov --- .../morph/frostfsid/additional_keys.go | 83 +++++++++++++++++++ .../internal/modules/morph/frostfsid/root.go | 2 + 2 files changed, 85 insertions(+) create mode 100644 cmd/frostfs-adm/internal/modules/morph/frostfsid/additional_keys.go diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/additional_keys.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/additional_keys.go new file mode 100644 index 0000000000..4046e85e3a --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/additional_keys.go @@ -0,0 +1,83 @@ +package frostfsid + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + frostfsidAddSubjectKeyCmd = &cobra.Command{ + Use: "add-subject-key", + Short: "Add a public key to the subject in frostfsid contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + }, + Run: frostfsidAddSubjectKey, + } + frostfsidRemoveSubjectKeyCmd = &cobra.Command{ + Use: "remove-subject-key", + Short: "Remove a public key from the subject in frostfsid contract", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + }, + Run: frostfsidRemoveSubjectKey, + } +) + +func initFrostfsIDAddSubjectKeyCmd() { + Cmd.AddCommand(frostfsidAddSubjectKeyCmd) + + ff := frostfsidAddSubjectKeyCmd.Flags() + ff.StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + ff.String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + + ff.String(subjectAddressFlag, "", "Subject address") + _ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectAddressFlag) + + ff.String(subjectKeyFlag, "", "Public key to add") + _ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectKeyFlag) +} + +func initFrostfsIDRemoveSubjectKeyCmd() { + Cmd.AddCommand(frostfsidRemoveSubjectKeyCmd) + + ff := frostfsidRemoveSubjectKeyCmd.Flags() + ff.StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + ff.String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + + ff.String(subjectAddressFlag, "", "Subject address") + _ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectAddressFlag) + + ff.String(subjectKeyFlag, "", "Public key to remove") + _ = frostfsidAddSubjectKeyCmd.MarkFlagRequired(subjectKeyFlag) +} + +func frostfsidAddSubjectKey(cmd *cobra.Command, _ []string) { + addr := getFrostfsIDSubjectAddress(cmd) + pub := getFrostfsIDSubjectKey(cmd) + + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + ffsid.addCall(ffsid.roCli.AddSubjectKeyCall(addr, pub)) + + err = ffsid.sendWait() + commonCmd.ExitOnErr(cmd, "add subject key: %w", err) +} + +func frostfsidRemoveSubjectKey(cmd *cobra.Command, _ []string) { + addr := getFrostfsIDSubjectAddress(cmd) + pub := getFrostfsIDSubjectKey(cmd) + + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + ffsid.addCall(ffsid.roCli.RemoveSubjectKeyCall(addr, pub)) + + err = ffsid.sendWait() + commonCmd.ExitOnErr(cmd, "remove subject key: %w", err) +} diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go index 8504747945..6ffcaa4871 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go @@ -12,4 +12,6 @@ func init() { initFrostfsIDAddSubjectToGroupCmd() initFrostfsIDRemoveSubjectFromGroupCmd() initFrostfsIDListGroupSubjectsCmd() + initFrostfsIDAddSubjectKeyCmd() + initFrostfsIDRemoveSubjectKeyCmd() } From e2cb0640f1236ea1874daeb18472ed77da30df90 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 18 Nov 2024 12:19:13 +0300 Subject: [PATCH 1014/1413] [#1501] util: Move eACL-to-APE converter to `pkg/util` * `ConvertEACLToAPE` is useful method which couldn't be imported out of frostfs-node so far as it has been in `internal` * Since `ConvertEACLToAPE` and related structures and unit-tests are placed in `pkg/util` Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/util/convert_eacl.go | 2 +- {internal => pkg/util}/ape/converter.go | 0 {internal => pkg/util}/ape/converter_test.go | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename {internal => pkg/util}/ape/converter.go (100%) rename {internal => pkg/util}/ape/converter_test.go (100%) diff --git a/cmd/frostfs-cli/modules/util/convert_eacl.go b/cmd/frostfs-cli/modules/util/convert_eacl.go index d588ba35d6..caa6dfcfe4 100644 --- a/cmd/frostfs-cli/modules/util/convert_eacl.go +++ b/cmd/frostfs-cli/modules/util/convert_eacl.go @@ -6,7 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" + apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) diff --git a/internal/ape/converter.go b/pkg/util/ape/converter.go similarity index 100% rename from internal/ape/converter.go rename to pkg/util/ape/converter.go diff --git a/internal/ape/converter_test.go b/pkg/util/ape/converter_test.go similarity index 100% rename from internal/ape/converter_test.go rename to pkg/util/ape/converter_test.go From ae31ef36029e0f8d6e7934faa5ccfd9a32d2a42a Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 18 Nov 2024 12:37:55 +0300 Subject: [PATCH 1015/1413] [#1501] cli: Move `PrintHumanReadableAPEChain` to a common package * Both `frostfs-cli` and `frostfs-adm` APE-related subcommands use `PrintHumanReadableAPEChain` to print a parsed APE-chain. So, it's more correct to have it in a common package over `frostfs-cli` and `frostfs-adm` folders. Signed-off-by: Airat Arifullin --- .../internal/modules/morph/ape/ape.go | 4 +- .../internal/modules/morph/ape/ape_util.go | 3 +- .../modules/ape_manager/add_chain.go | 3 +- .../modules/ape_manager/list_chain.go | 4 +- .../modules/bearer/generate_override.go | 3 +- cmd/frostfs-cli/modules/control/add_rule.go | 3 +- cmd/frostfs-cli/modules/control/get_rule.go | 4 +- cmd/frostfs-cli/modules/control/list_rules.go | 4 +- cmd/frostfs-cli/modules/util/ape.go | 34 --------------- cmd/internal/common/ape/commands.go | 41 +++++++++++++++++++ 10 files changed, 57 insertions(+), 46 deletions(-) create mode 100644 cmd/internal/common/ape/commands.go diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index 077e037375..fb363f9037 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -5,8 +5,8 @@ import ( "encoding/json" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" - parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/cobra" @@ -210,7 +210,7 @@ func listRuleChains(cmd *cobra.Command, _ []string) { prettyJSONFormat(cmd, chains) } else { for _, c := range chains { - parseutil.PrintHumanReadableAPEChain(cmd, c) + apeCmd.PrintHumanReadableAPEChain(cmd, c) } } } diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index f4373c5354..df358ff69d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" @@ -90,7 +91,7 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { chain.ID = parseChainID(cmd) cmd.Println("Parsed chain:") - parseutil.PrintHumanReadableAPEChain(cmd, chain) + apeCmd.PrintHumanReadableAPEChain(cmd, chain) return chain } diff --git a/cmd/frostfs-cli/modules/ape_manager/add_chain.go b/cmd/frostfs-cli/modules/ape_manager/add_chain.go index a85f3c93e4..d9cfc304c8 100644 --- a/cmd/frostfs-cli/modules/ape_manager/add_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/add_chain.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -95,7 +96,7 @@ func parseChain(cmd *cobra.Command) apeSDK.Chain { } cmd.Println("Parsed chain:") - util.PrintHumanReadableAPEChain(cmd, chain) + apeCmd.PrintHumanReadableAPEChain(cmd, chain) serialized := chain.Bytes() return apeSDK.Chain{ diff --git a/cmd/frostfs-cli/modules/ape_manager/list_chain.go b/cmd/frostfs-cli/modules/ape_manager/list_chain.go index a5dd446147..9955c8c035 100644 --- a/cmd/frostfs-cli/modules/ape_manager/list_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/list_chain.go @@ -4,8 +4,8 @@ import ( internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" - apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" @@ -35,7 +35,7 @@ func list(cmd *cobra.Command, _ []string) { for _, respChain := range resp.Chains { var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(respChain.Raw)) - apeutil.PrintHumanReadableAPEChain(cmd, &chain) + apeCmd.PrintHumanReadableAPEChain(cmd, &chain) } } diff --git a/cmd/frostfs-cli/modules/bearer/generate_override.go b/cmd/frostfs-cli/modules/bearer/generate_override.go index 482c0027e1..31dbdbdbdf 100644 --- a/cmd/frostfs-cli/modules/bearer/generate_override.go +++ b/cmd/frostfs-cli/modules/bearer/generate_override.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -109,7 +110,7 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { chain.ID = parseChainID(cmd) cmd.Println("Parsed chain:") - parseutil.PrintHumanReadableAPEChain(cmd, chain) + apeCmd.PrintHumanReadableAPEChain(cmd, chain) return chain } diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index c648377bd0..88291f0acf 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -55,7 +56,7 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { } cmd.Println("Parsed chain:") - util.PrintHumanReadableAPEChain(cmd, chain) + apeCmd.PrintHumanReadableAPEChain(cmd, chain) return chain } diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 4b4d6eef57..9bbbb02f74 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -4,8 +4,8 @@ import ( "encoding/hex" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -56,7 +56,7 @@ func getRule(cmd *cobra.Command, _ []string) { var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain())) - util.PrintHumanReadableAPEChain(cmd, &chain) + apeCmd.PrintHumanReadableAPEChain(cmd, &chain) } func initControGetRuleCmd() { diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index 7162df5e0b..a7b9f9ef54 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -6,8 +6,8 @@ import ( "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -117,7 +117,7 @@ func listRules(cmd *cobra.Command, _ []string) { for _, c := range chains { var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(c)) - util.PrintHumanReadableAPEChain(cmd, &chain) + apeCmd.PrintHumanReadableAPEChain(cmd, &chain) } } diff --git a/cmd/frostfs-cli/modules/util/ape.go b/cmd/frostfs-cli/modules/util/ape.go index 73c3685103..0e963c0a35 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/cmd/frostfs-cli/modules/util/ape.go @@ -4,13 +4,11 @@ import ( "errors" "fmt" "os" - "strconv" "strings" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/flynn-archive/go-shlex" - "github.com/spf13/cobra" ) var ( @@ -27,38 +25,6 @@ var ( errFailedToParseAllAny = errors.New("any/all is not parsed") ) -// PrintHumanReadableAPEChain print APE chain rules. -func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) { - cmd.Println("Chain ID: " + string(chain.ID)) - cmd.Printf(" HEX: %x\n", chain.ID) - cmd.Println("Rules:") - for _, rule := range chain.Rules { - cmd.Println("\n\tStatus: " + rule.Status.String()) - cmd.Println("\tAny: " + strconv.FormatBool(rule.Any)) - cmd.Println("\tConditions:") - for _, c := range rule.Condition { - var ot string - switch c.Kind { - case apechain.KindResource: - ot = "Resource" - case apechain.KindRequest: - ot = "Request" - default: - panic("unknown object type") - } - cmd.Println(fmt.Sprintf("\t\t%s %s %s %s", ot, c.Key, c.Op, c.Value)) - } - cmd.Println("\tActions:\tInverted:" + strconv.FormatBool(rule.Actions.Inverted)) - for _, name := range rule.Actions.Names { - cmd.Println("\t\t" + name) - } - cmd.Println("\tResources:\tInverted:" + strconv.FormatBool(rule.Resources.Inverted)) - for _, name := range rule.Resources.Names { - cmd.Println("\t\t" + name) - } - } -} - func ParseAPEChainBinaryOrJSON(chain *apechain.Chain, path string) error { data, err := os.ReadFile(path) if err != nil { diff --git a/cmd/internal/common/ape/commands.go b/cmd/internal/common/ape/commands.go new file mode 100644 index 0000000000..a8f50b29e8 --- /dev/null +++ b/cmd/internal/common/ape/commands.go @@ -0,0 +1,41 @@ +package ape + +import ( + "fmt" + "strconv" + + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "github.com/spf13/cobra" +) + +// PrintHumanReadableAPEChain print APE chain rules. +func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) { + cmd.Println("Chain ID: " + string(chain.ID)) + cmd.Printf(" HEX: %x\n", chain.ID) + cmd.Println("Rules:") + for _, rule := range chain.Rules { + cmd.Println("\n\tStatus: " + rule.Status.String()) + cmd.Println("\tAny: " + strconv.FormatBool(rule.Any)) + cmd.Println("\tConditions:") + for _, c := range rule.Condition { + var ot string + switch c.Kind { + case apechain.KindResource: + ot = "Resource" + case apechain.KindRequest: + ot = "Request" + default: + panic("unknown object type") + } + cmd.Println(fmt.Sprintf("\t\t%s %s %s %s", ot, c.Key, c.Op, c.Value)) + } + cmd.Println("\tActions:\tInverted:" + strconv.FormatBool(rule.Actions.Inverted)) + for _, name := range rule.Actions.Names { + cmd.Println("\t\t" + name) + } + cmd.Println("\tResources:\tInverted:" + strconv.FormatBool(rule.Resources.Inverted)) + for _, name := range rule.Resources.Names { + cmd.Println("\t\t" + name) + } + } +} From ffe9906266044ca3d8a1f2baf6256490a787cada Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 18 Nov 2024 12:54:02 +0300 Subject: [PATCH 1016/1413] [#1501] cli: Move APE-chain parser methods to `pkg/util` Signed-off-by: Airat Arifullin --- cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go | 2 +- cmd/frostfs-cli/modules/ape_manager/add_chain.go | 6 +++--- cmd/frostfs-cli/modules/bearer/generate_override.go | 2 +- cmd/frostfs-cli/modules/control/add_rule.go | 6 +++--- .../modules/util/ape.go => pkg/util/ape/parser.go | 2 +- .../modules/util/ape_test.go => pkg/util/ape/parser_test.go | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) rename cmd/frostfs-cli/modules/util/ape.go => pkg/util/ape/parser.go (99%) rename cmd/frostfs-cli/modules/util/ape_test.go => pkg/util/ape/parser_test.go (99%) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index df358ff69d..1a70dd4a21 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -6,9 +6,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" - parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" + parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" diff --git a/cmd/frostfs-cli/modules/ape_manager/add_chain.go b/cmd/frostfs-cli/modules/ape_manager/add_chain.go index d9cfc304c8..7a49dee683 100644 --- a/cmd/frostfs-cli/modules/ape_manager/add_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/add_chain.go @@ -7,9 +7,9 @@ import ( internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" + parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -88,9 +88,9 @@ func parseChain(cmd *cobra.Command) apeSDK.Chain { chain.ID = apechain.ID(chainIDRaw) if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { - commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules)) + commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules)) } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { - commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath)) + commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) } else { commonCmd.ExitOnErr(cmd, "parser error: %w", errors.New("rule is not passed")) } diff --git a/cmd/frostfs-cli/modules/bearer/generate_override.go b/cmd/frostfs-cli/modules/bearer/generate_override.go index 31dbdbdbdf..c3df0294eb 100644 --- a/cmd/frostfs-cli/modules/bearer/generate_override.go +++ b/cmd/frostfs-cli/modules/bearer/generate_override.go @@ -6,9 +6,9 @@ import ( "os" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" - parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" + parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 88291f0acf..25960f4398 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -5,10 +5,10 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/util" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" @@ -48,9 +48,9 @@ func parseChain(cmd *cobra.Command) *apechain.Chain { chain.ID = apechain.ID(chainIDRaw) if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { - commonCmd.ExitOnErr(cmd, "parser error: %w", util.ParseAPEChain(chain, rules)) + commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules)) } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { - commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", util.ParseAPEChainBinaryOrJSON(chain, encPath)) + commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) } else { commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed")) } diff --git a/cmd/frostfs-cli/modules/util/ape.go b/pkg/util/ape/parser.go similarity index 99% rename from cmd/frostfs-cli/modules/util/ape.go rename to pkg/util/ape/parser.go index 0e963c0a35..b4a31fd8d8 100644 --- a/cmd/frostfs-cli/modules/util/ape.go +++ b/pkg/util/ape/parser.go @@ -1,4 +1,4 @@ -package util +package ape import ( "errors" diff --git a/cmd/frostfs-cli/modules/util/ape_test.go b/pkg/util/ape/parser_test.go similarity index 99% rename from cmd/frostfs-cli/modules/util/ape_test.go rename to pkg/util/ape/parser_test.go index b275803dff..21649fd24d 100644 --- a/cmd/frostfs-cli/modules/util/ape_test.go +++ b/pkg/util/ape/parser_test.go @@ -1,4 +1,4 @@ -package util +package ape import ( "fmt" From 7a7ee71a4d076325306e1bae754bdb8c40f5f026 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 18 Nov 2024 13:12:22 +0300 Subject: [PATCH 1017/1413] [#1501] cmd: Introduce common APE-chain parser commands * Introduce common parsing commands to use them in `frostfs-cli` and `frostfs-adm` APE-related subcommands * Introduce common flags for these parsing commands Signed-off-by: Airat Arifullin --- cmd/internal/common/ape/commands.go | 125 ++++++++++++++++++++++++++++ cmd/internal/common/ape/flags.go | 19 +++++ 2 files changed, 144 insertions(+) create mode 100644 cmd/internal/common/ape/flags.go diff --git a/cmd/internal/common/ape/commands.go b/cmd/internal/common/ape/commands.go index a8f50b29e8..3547473305 100644 --- a/cmd/internal/common/ape/commands.go +++ b/cmd/internal/common/ape/commands.go @@ -1,13 +1,43 @@ package ape import ( + "encoding/hex" + "errors" "fmt" "strconv" + "strings" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" + "github.com/nspcc-dev/neo-go/cli/input" "github.com/spf13/cobra" ) +const ( + defaultNamespace = "root" + namespaceTarget = "namespace" + containerTarget = "container" + userTarget = "user" + groupTarget = "group" + + Ingress = "ingress" + S3 = "s3" +) + +var mChainName = map[string]apechain.Name{ + Ingress: apechain.Ingress, + S3: apechain.S3, +} + +var ( + errSettingDefaultValueWasDeclined = errors.New("setting default value was declined") + errUnknownTargetType = errors.New("unknown target type") + errUnsupportedChainName = errors.New("unsupported chain name") +) + // PrintHumanReadableAPEChain print APE chain rules. func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) { cmd.Println("Chain ID: " + string(chain.ID)) @@ -39,3 +69,98 @@ func PrintHumanReadableAPEChain(cmd *cobra.Command, chain *apechain.Chain) { } } } + +// ParseTarget handles target parsing of an APE chain. +func ParseTarget(cmd *cobra.Command) engine.Target { + typ := ParseTargetType(cmd) + name, _ := cmd.Flags().GetString(TargetNameFlag) + switch typ { + case engine.Namespace: + if name == "" { + ln, err := input.ReadLine(fmt.Sprintf("Target name is not set. Confirm to use %s namespace (n|Y)> ", defaultNamespace)) + commonCmd.ExitOnErr(cmd, "read line error: %w", err) + ln = strings.ToLower(ln) + if len(ln) > 0 && (ln[0] == 'n') { + commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined) + } + name = defaultNamespace + } + return engine.NamespaceTarget(name) + case engine.Container: + var cnr cid.ID + commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name)) + return engine.ContainerTarget(name) + case engine.User: + return engine.UserTarget(name) + case engine.Group: + return engine.GroupTarget(name) + default: + commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) + } + return engine.Target{} +} + +// ParseTargetType handles target type parsing of an APE chain. +func ParseTargetType(cmd *cobra.Command) engine.TargetType { + typ, _ := cmd.Flags().GetString(TargetTypeFlag) + switch typ { + case namespaceTarget: + return engine.Namespace + case containerTarget: + return engine.Container + case userTarget: + return engine.User + case groupTarget: + return engine.Group + } + commonCmd.ExitOnErr(cmd, "parse target type error: %w", errUnknownTargetType) + return engine.TargetType(0) +} + +// ParseChainID handles the parsing of APE-chain identifier. +// For some subcommands, chain ID is optional as an input parameter and should be generated by +// the service instead. +func ParseChainID(cmd *cobra.Command) (id apechain.ID) { + chainID, _ := cmd.Flags().GetString(ChainIDFlag) + id = apechain.ID(chainID) + + hexEncoded, _ := cmd.Flags().GetBool(ChainIDHexFlag) + if !hexEncoded { + return + } + + chainIDRaw, err := hex.DecodeString(chainID) + commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) + id = apechain.ID(chainIDRaw) + return +} + +// ParseChain parses an APE chain which can be provided either as a rule statement +// or loaded from a binary/JSON file path. +func ParseChain(cmd *cobra.Command) *apechain.Chain { + chain := new(apechain.Chain) + chain.ID = ParseChainID(cmd) + + if rules, _ := cmd.Flags().GetStringArray(RuleFlag); len(rules) > 0 { + commonCmd.ExitOnErr(cmd, "parser error: %w", apeutil.ParseAPEChain(chain, rules)) + } else if encPath, _ := cmd.Flags().GetString(PathFlag); encPath != "" { + commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", apeutil.ParseAPEChainBinaryOrJSON(chain, encPath)) + } else { + commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed")) + } + + cmd.Println("Parsed chain:") + PrintHumanReadableAPEChain(cmd, chain) + + return chain +} + +// ParseChainName parses chain name: the place in the request lifecycle where policy is applied. +func ParseChainName(cmd *cobra.Command) apechain.Name { + chainName, _ := cmd.Flags().GetString(ChainNameFlag) + apeChainName, ok := mChainName[strings.ToLower(chainName)] + if !ok { + commonCmd.ExitOnErr(cmd, "", errUnsupportedChainName) + } + return apeChainName +} diff --git a/cmd/internal/common/ape/flags.go b/cmd/internal/common/ape/flags.go new file mode 100644 index 0000000000..c5e2a3a999 --- /dev/null +++ b/cmd/internal/common/ape/flags.go @@ -0,0 +1,19 @@ +package ape + +const ( + RuleFlag = "rule" + RuleFlagDesc = "Rule statement" + PathFlag = "path" + PathFlagDesc = "Path to encoded chain in JSON or binary format" + TargetNameFlag = "target-name" + TargetNameFlagDesc = "Resource name in APE resource name format" + TargetTypeFlag = "target-type" + TargetTypeFlagDesc = "Resource type(container/namespace)" + ChainIDFlag = "chain-id" + ChainIDFlagDesc = "Chain id" + ChainIDHexFlag = "chain-id-hex" + ChainIDHexFlagDesc = "Flag to parse chain ID as hex" + ChainNameFlag = "chain-name" + ChainNameFlagDesc = "Chain name(ingress|s3)" + AllFlag = "all" +) From daff77b2737cdf2c5257cac608794e87c67ebb60 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 18 Nov 2024 13:33:47 +0300 Subject: [PATCH 1018/1413] [#1501] cli: Refactor local override managing subcommands * Refactor local override managing subcommands * Use `cmd/internal/common/ape` parser commands within local override subcommands * Use flag names from `cmd/internal/common/ape` Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/control/add_rule.go | 57 ++----------- cmd/frostfs-cli/modules/control/get_rule.go | 18 ++-- cmd/frostfs-cli/modules/control/list_rules.go | 82 +++++-------------- .../modules/control/list_targets.go | 20 ++--- .../modules/control/remove_rule.go | 27 +++--- 5 files changed, 54 insertions(+), 150 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/add_rule.go b/cmd/frostfs-cli/modules/control/add_rule.go index 25960f4398..42f229ad9b 100644 --- a/cmd/frostfs-cli/modules/control/add_rule.go +++ b/cmd/frostfs-cli/modules/control/add_rule.go @@ -1,24 +1,14 @@ package control import ( - "encoding/hex" - "errors" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" - apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) -const ( - ruleFlag = "rule" - pathFlag = "path" -) - var addRuleCmd = &cobra.Command{ Use: "add-rule", Short: "Add local override", @@ -32,41 +22,12 @@ control add-rule --endpoint ... -w ... --address ... --chain-id ChainID --cid .. Run: addRule, } -func parseChain(cmd *cobra.Command) *apechain.Chain { - chainID, _ := cmd.Flags().GetString(chainIDFlag) - hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) - - chainIDRaw := []byte(chainID) - - if hexEncoded { - var err error - chainIDRaw, err = hex.DecodeString(chainID) - commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) - } - - chain := new(apechain.Chain) - chain.ID = apechain.ID(chainIDRaw) - - if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { - commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules)) - } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { - commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) - } else { - commonCmd.ExitOnErr(cmd, "parser error", errors.New("rule is not passed")) - } - - cmd.Println("Parsed chain:") - apeCmd.PrintHumanReadableAPEChain(cmd, chain) - - return chain -} - func addRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) target := parseTarget(cmd) - parsed := parseChain(cmd) + parsed := apeCmd.ParseChain(cmd) req := &control.AddChainLocalOverrideRequest{ Body: &control.AddChainLocalOverrideRequest_Body{ @@ -95,13 +56,13 @@ func initControlAddRuleCmd() { initControlFlags(addRuleCmd) ff := addRuleCmd.Flags() - ff.StringArray(ruleFlag, []string{}, "Rule statement") - ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") - ff.String(chainIDFlag, "", "Assign ID to the parsed chain") - ff.String(targetNameFlag, "", targetNameDesc) - ff.String(targetTypeFlag, "", targetTypeDesc) - _ = addRuleCmd.MarkFlagRequired(targetTypeFlag) - ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement") + ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format") + ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain") + ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) + ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) + _ = addRuleCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) + ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex") - addRuleCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag) + addRuleCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.RuleFlag) } diff --git a/cmd/frostfs-cli/modules/control/get_rule.go b/cmd/frostfs-cli/modules/control/get_rule.go index 9bbbb02f74..4da903a9ab 100644 --- a/cmd/frostfs-cli/modules/control/get_rule.go +++ b/cmd/frostfs-cli/modules/control/get_rule.go @@ -5,7 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" + apecmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -24,8 +24,8 @@ func getRule(cmd *cobra.Command, _ []string) { target := parseTarget(cmd) - chainID, _ := cmd.Flags().GetString(chainIDFlag) - hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) + chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag) + hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag) if hexEncoded { chainIDBytes, err := hex.DecodeString(chainID) @@ -56,16 +56,16 @@ func getRule(cmd *cobra.Command, _ []string) { var chain apechain.Chain commonCmd.ExitOnErr(cmd, "decode error: %w", chain.DecodeBytes(resp.GetBody().GetChain())) - apeCmd.PrintHumanReadableAPEChain(cmd, &chain) + apecmd.PrintHumanReadableAPEChain(cmd, &chain) } func initControGetRuleCmd() { initControlFlags(getRuleCmd) ff := getRuleCmd.Flags() - ff.String(targetNameFlag, "", targetNameDesc) - ff.String(targetTypeFlag, "", targetTypeDesc) - _ = getRuleCmd.MarkFlagRequired(targetTypeFlag) - ff.String(chainIDFlag, "", "Chain id") - ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc) + ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc) + _ = getRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag) + ff.String(apecmd.ChainIDFlag, "", "Chain id") + ff.Bool(apecmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex") } diff --git a/cmd/frostfs-cli/modules/control/list_rules.go b/cmd/frostfs-cli/modules/control/list_rules.go index a7b9f9ef54..a6c65d0833 100644 --- a/cmd/frostfs-cli/modules/control/list_rules.go +++ b/cmd/frostfs-cli/modules/control/list_rules.go @@ -1,7 +1,6 @@ package control import ( - "errors" "fmt" "strings" @@ -10,9 +9,8 @@ import ( apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" - "github.com/nspcc-dev/neo-go/cli/input" + policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/spf13/cobra" ) @@ -23,65 +21,25 @@ var listRulesCmd = &cobra.Command{ Run: listRules, } -const ( - defaultNamespace = "root" - namespaceTarget = "namespace" - containerTarget = "container" - userTarget = "user" - groupTarget = "group" -) - -const ( - targetNameFlag = "target-name" - targetNameDesc = "Resource name in APE resource name format" - targetTypeFlag = "target-type" - targetTypeDesc = "Resource type(container/namespace)" -) - -var ( - errSettingDefaultValueWasDeclined = errors.New("setting default value was declined") - errUnknownTargetType = errors.New("unknown target type") -) +var engineToControlSvcType = map[policyengine.TargetType]control.ChainTarget_TargetType{ + policyengine.Namespace: control.ChainTarget_NAMESPACE, + policyengine.Container: control.ChainTarget_CONTAINER, + policyengine.User: control.ChainTarget_USER, + policyengine.Group: control.ChainTarget_GROUP, +} func parseTarget(cmd *cobra.Command) *control.ChainTarget { - typ, _ := cmd.Flags().GetString(targetTypeFlag) - name, _ := cmd.Flags().GetString(targetNameFlag) - switch typ { - case namespaceTarget: - if name == "" { - ln, err := input.ReadLine(fmt.Sprintf("Target name is not set. Confirm to use %s namespace (n|Y)> ", defaultNamespace)) - commonCmd.ExitOnErr(cmd, "read line error: %w", err) - ln = strings.ToLower(ln) - if len(ln) > 0 && (ln[0] == 'n') { - commonCmd.ExitOnErr(cmd, "read namespace error: %w", errSettingDefaultValueWasDeclined) - } - name = defaultNamespace - } - return &control.ChainTarget{ - Name: name, - Type: control.ChainTarget_NAMESPACE, - } - case containerTarget: - var cnr cid.ID - commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name)) - return &control.ChainTarget{ - Name: name, - Type: control.ChainTarget_CONTAINER, - } - case userTarget: - return &control.ChainTarget{ - Name: name, - Type: control.ChainTarget_USER, - } - case groupTarget: - return &control.ChainTarget{ - Name: name, - Type: control.ChainTarget_GROUP, - } - default: - commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) + target := apeCmd.ParseTarget(cmd) + + typ, ok := engineToControlSvcType[target.Type] + if !ok { + commonCmd.ExitOnErr(cmd, "%w", fmt.Errorf("unknown type '%c", target.Type)) + } + + return &control.ChainTarget{ + Name: target.Name, + Type: typ, } - return nil } func listRules(cmd *cobra.Command, _ []string) { @@ -125,7 +83,7 @@ func initControlListRulesCmd() { initControlFlags(listRulesCmd) ff := listRulesCmd.Flags() - ff.String(targetNameFlag, "", targetNameDesc) - ff.String(targetTypeFlag, "", targetTypeDesc) - _ = listRulesCmd.MarkFlagRequired(targetTypeFlag) + ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) + ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) + _ = listRulesCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) } diff --git a/cmd/frostfs-cli/modules/control/list_targets.go b/cmd/frostfs-cli/modules/control/list_targets.go index 7c401eb179..8bd2dc9cde 100644 --- a/cmd/frostfs-cli/modules/control/list_targets.go +++ b/cmd/frostfs-cli/modules/control/list_targets.go @@ -2,26 +2,20 @@ package control import ( "bytes" - "crypto/sha256" "fmt" "strconv" "text/tabwriter" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/spf13/cobra" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) -const ( - chainNameFlag = "chain-name" - chainNameFlagUsage = "Chain name(ingress|s3)" -) - var listTargetsCmd = &cobra.Command{ Use: "list-targets", Short: "List local targets", @@ -32,15 +26,11 @@ var listTargetsCmd = &cobra.Command{ func listTargets(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) - var cnr cid.ID - chainName, _ := cmd.Flags().GetString(chainNameFlag) - - rawCID := make([]byte, sha256.Size) - cnr.Encode(rawCID) + chainName := apeCmd.ParseChainName(cmd) req := &control.ListTargetsLocalOverridesRequest{ Body: &control.ListTargetsLocalOverridesRequest_Body{ - ChainName: chainName, + ChainName: string(chainName), }, } @@ -82,7 +72,7 @@ func initControlListTargetsCmd() { initControlFlags(listTargetsCmd) ff := listTargetsCmd.Flags() - ff.String(chainNameFlag, "", chainNameFlagUsage) + ff.String(apeCmd.ChainNameFlag, "", apeCmd.ChainNameFlagDesc) - _ = cobra.MarkFlagRequired(ff, chainNameFlag) + _ = cobra.MarkFlagRequired(ff, apeCmd.ChainNameFlag) } diff --git a/cmd/frostfs-cli/modules/control/remove_rule.go b/cmd/frostfs-cli/modules/control/remove_rule.go index a996156a5e..036317bcbd 100644 --- a/cmd/frostfs-cli/modules/control/remove_rule.go +++ b/cmd/frostfs-cli/modules/control/remove_rule.go @@ -6,17 +6,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apecmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" ) -const ( - chainIDFlag = "chain-id" - chainIDHexFlag = "chain-id-hex" - allFlag = "all" -) - var ( errEmptyChainID = errors.New("chain id cannot be empty") @@ -30,8 +25,8 @@ var ( func removeRule(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) - hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) - removeAll, _ := cmd.Flags().GetBool(allFlag) + hexEncoded, _ := cmd.Flags().GetBool(apecmd.ChainIDHexFlag) + removeAll, _ := cmd.Flags().GetBool(apecmd.AllFlag) if removeAll { req := &control.RemoveChainLocalOverridesByTargetRequest{ Body: &control.RemoveChainLocalOverridesByTargetRequest_Body{ @@ -52,7 +47,7 @@ func removeRule(cmd *cobra.Command, _ []string) { return } - chainID, _ := cmd.Flags().GetString(chainIDFlag) + chainID, _ := cmd.Flags().GetString(apecmd.ChainIDFlag) if chainID == "" { commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID) } @@ -92,11 +87,11 @@ func initControlRemoveRuleCmd() { initControlFlags(removeRuleCmd) ff := removeRuleCmd.Flags() - ff.String(targetNameFlag, "", targetNameDesc) - ff.String(targetTypeFlag, "", targetTypeDesc) - _ = removeRuleCmd.MarkFlagRequired(targetTypeFlag) - ff.String(chainIDFlag, "", "Chain id") - ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") - ff.Bool(allFlag, false, "Remove all chains") - removeRuleCmd.MarkFlagsMutuallyExclusive(allFlag, chainIDFlag) + ff.String(apecmd.TargetNameFlag, "", apecmd.TargetNameFlagDesc) + ff.String(apecmd.TargetTypeFlag, "", apecmd.TargetTypeFlagDesc) + _ = removeRuleCmd.MarkFlagRequired(apecmd.TargetTypeFlag) + ff.String(apecmd.ChainIDFlag, "", apecmd.ChainIDFlagDesc) + ff.Bool(apecmd.ChainIDHexFlag, false, apecmd.ChainIDHexFlagDesc) + ff.Bool(apecmd.AllFlag, false, "Remove all chains") + removeRuleCmd.MarkFlagsMutuallyExclusive(apecmd.AllFlag, apecmd.ChainIDFlag) } From 3b1364e4cf9276b944b9a48610a11989e74aa75b Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 18 Nov 2024 14:01:27 +0300 Subject: [PATCH 1019/1413] [#1501] cli: Refactor ape-manager subcommands * Refactor ape-manager subcommands * Use `cmd/internal/common/ape` parser commands within ape-manager subcommands * Use flag names from `cmd/internal/common/ape` Signed-off-by: Airat Arifullin --- .../modules/ape_manager/add_chain.go | 93 ++++--------------- .../modules/ape_manager/list_chain.go | 6 +- .../modules/ape_manager/remove_chain.go | 47 ++++------ 3 files changed, 39 insertions(+), 107 deletions(-) diff --git a/cmd/frostfs-cli/modules/ape_manager/add_chain.go b/cmd/frostfs-cli/modules/ape_manager/add_chain.go index 7a49dee683..f4039283f9 100644 --- a/cmd/frostfs-cli/modules/ape_manager/add_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/add_chain.go @@ -1,45 +1,19 @@ package apemanager import ( - "encoding/hex" - "errors" + "fmt" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" - parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/spf13/cobra" ) -const ( - chainIDFlag = "chain-id" - chainIDHexFlag = "chain-id-hex" - ruleFlag = "rule" - pathFlag = "path" -) - -const ( - targetNameFlag = "target-name" - targetNameDesc = "Resource name in APE resource name format" - targetTypeFlag = "target-type" - targetTypeDesc = "Resource type(container/namespace)" -) - -const ( - namespaceTarget = "namespace" - containerTarget = "container" - userTarget = "user" - groupTarget = "group" -) - -var errUnknownTargetType = errors.New("unknown target type") - var addCmd = &cobra.Command{ Use: "add", Short: "Add rule chain for a target", @@ -50,55 +24,28 @@ var addCmd = &cobra.Command{ } func parseTarget(cmd *cobra.Command) (ct apeSDK.ChainTarget) { - typ, _ := cmd.Flags().GetString(targetTypeFlag) - name, _ := cmd.Flags().GetString(targetNameFlag) + t := apeCmd.ParseTarget(cmd) - ct.Name = name + ct.Name = t.Name - switch typ { - case namespaceTarget: + switch t.Type { + case engine.Namespace: ct.TargetType = apeSDK.TargetTypeNamespace - case containerTarget: - var cnr cid.ID - commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name)) + case engine.Container: ct.TargetType = apeSDK.TargetTypeContainer - case userTarget: + case engine.User: ct.TargetType = apeSDK.TargetTypeUser - case groupTarget: + case engine.Group: ct.TargetType = apeSDK.TargetTypeGroup default: - commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) + commonCmd.ExitOnErr(cmd, "conversion error: %w", fmt.Errorf("unknown type '%c'", t.Type)) } return ct } func parseChain(cmd *cobra.Command) apeSDK.Chain { - chainID, _ := cmd.Flags().GetString(chainIDFlag) - hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) - - chainIDRaw := []byte(chainID) - - if hexEncoded { - var err error - chainIDRaw, err = hex.DecodeString(chainID) - commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) - } - - chain := new(apechain.Chain) - chain.ID = apechain.ID(chainIDRaw) - - if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { - commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules)) - } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { - commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) - } else { - commonCmd.ExitOnErr(cmd, "parser error: %w", errors.New("rule is not passed")) - } - - cmd.Println("Parsed chain:") - apeCmd.PrintHumanReadableAPEChain(cmd, chain) - - serialized := chain.Bytes() + c := apeCmd.ParseChain(cmd) + serialized := c.Bytes() return apeSDK.Chain{ Raw: serialized, } @@ -127,13 +74,13 @@ func initAddCmd() { commonflags.Init(addCmd) ff := addCmd.Flags() - ff.StringArray(ruleFlag, []string{}, "Rule statement") - ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") - ff.String(chainIDFlag, "", "Assign ID to the parsed chain") - ff.String(targetNameFlag, "", targetNameDesc) - ff.String(targetTypeFlag, "", targetTypeDesc) - _ = addCmd.MarkFlagRequired(targetTypeFlag) - ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + ff.StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc) + ff.String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc) + ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc) + ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) + ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) + _ = addCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) + ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc) - addCmd.MarkFlagsMutuallyExclusive(pathFlag, ruleFlag) + addCmd.MarkFlagsMutuallyExclusive(apeCmd.PathFlag, apeCmd.RuleFlag) } diff --git a/cmd/frostfs-cli/modules/ape_manager/list_chain.go b/cmd/frostfs-cli/modules/ape_manager/list_chain.go index 9955c8c035..b07ecc52fa 100644 --- a/cmd/frostfs-cli/modules/ape_manager/list_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/list_chain.go @@ -43,7 +43,7 @@ func initListCmd() { commonflags.Init(listCmd) ff := listCmd.Flags() - ff.String(targetNameFlag, "", targetNameDesc) - ff.String(targetTypeFlag, "", targetTypeDesc) - _ = listCmd.MarkFlagRequired(targetTypeFlag) + ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) + ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) + _ = listCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) } diff --git a/cmd/frostfs-cli/modules/ape_manager/remove_chain.go b/cmd/frostfs-cli/modules/ape_manager/remove_chain.go index 179bd5c9e7..136ca81c36 100644 --- a/cmd/frostfs-cli/modules/ape_manager/remove_chain.go +++ b/cmd/frostfs-cli/modules/ape_manager/remove_chain.go @@ -1,29 +1,23 @@ package apemanager import ( - "encoding/hex" - "errors" - internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" client_sdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "github.com/spf13/cobra" ) -var ( - errEmptyChainID = errors.New("chain id cannot be empty") - - removeCmd = &cobra.Command{ - Use: "remove", - Short: "Remove rule chain for a target", - Run: remove, - PersistentPreRun: func(cmd *cobra.Command, _ []string) { - commonflags.Bind(cmd) - }, - } -) +var removeCmd = &cobra.Command{ + Use: "remove", + Short: "Remove rule chain for a target", + Run: remove, + PersistentPreRun: func(cmd *cobra.Command, _ []string) { + commonflags.Bind(cmd) + }, +} func remove(cmd *cobra.Command, _ []string) { target := parseTarget(cmd) @@ -31,19 +25,9 @@ func remove(cmd *cobra.Command, _ []string) { key := key.Get(cmd) cli := internalclient.GetSDKClientByFlag(cmd, key, commonflags.RPC) - chainID, _ := cmd.Flags().GetString(chainIDFlag) - if chainID == "" { - commonCmd.ExitOnErr(cmd, "read chain id error: %w", errEmptyChainID) - } + chainID := apeCmd.ParseChainID(cmd) chainIDRaw := []byte(chainID) - hexEncoded, _ := cmd.Flags().GetBool(chainIDHexFlag) - if hexEncoded { - var err error - chainIDRaw, err = hex.DecodeString(chainID) - commonCmd.ExitOnErr(cmd, "can't decode chain ID as hex: %w", err) - } - _, err := cli.APEManagerRemoveChain(cmd.Context(), client_sdk.PrmAPEManagerRemoveChain{ ChainTarget: target, ChainID: chainIDRaw, @@ -58,9 +42,10 @@ func initRemoveCmd() { commonflags.Init(removeCmd) ff := removeCmd.Flags() - ff.String(targetNameFlag, "", targetNameDesc) - ff.String(targetTypeFlag, "", targetTypeDesc) - _ = removeCmd.MarkFlagRequired(targetTypeFlag) - ff.String(chainIDFlag, "", "Chain id") - ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + ff.String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) + ff.String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) + _ = removeCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) + ff.String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc) + _ = removeCmd.MarkFlagRequired(apeCmd.ChainIDFlag) + ff.Bool(apeCmd.ChainIDHexFlag, false, apeCmd.ChainIDHexFlagDesc) } From 4ab4ed6f96e3538a25110e1eb5229e90e438de49 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 18 Nov 2024 14:07:14 +0300 Subject: [PATCH 1020/1413] [#1501] cli: Refactor bearer subcommand * Use `cmd/internal/common/ape` parser commands within `generate-ape-override` subcommand * Use flag names from `cmd/internal/common/ape` Signed-off-by: Airat Arifullin --- .../modules/bearer/generate_override.go | 52 +++---------------- 1 file changed, 6 insertions(+), 46 deletions(-) diff --git a/cmd/frostfs-cli/modules/bearer/generate_override.go b/cmd/frostfs-cli/modules/bearer/generate_override.go index c3df0294eb..13fe079959 100644 --- a/cmd/frostfs-cli/modules/bearer/generate_override.go +++ b/cmd/frostfs-cli/modules/bearer/generate_override.go @@ -1,32 +1,20 @@ package bearer import ( - "errors" "fmt" "os" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" - parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "github.com/spf13/cobra" ) -var ( - errChainIDCannotBeEmpty = errors.New("chain id cannot be empty") - errRuleIsNotParsed = errors.New("rule is not passed") -) - const ( - chainIDFlag = "chain-id" - chainIDHexFlag = "chain-id-hex" - ruleFlag = "rule" - pathFlag = "path" - outputFlag = "output" + outputFlag = "output" ) var generateAPEOverrideCmd = &cobra.Command{ @@ -41,7 +29,7 @@ Generated APE override can be dumped to a file in JSON format that is passed to } func genereateAPEOverride(cmd *cobra.Command, _ []string) { - c := parseChain(cmd) + c := apeCmd.ParseChain(cmd) targetCID, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cid cidSDK.ID @@ -78,39 +66,11 @@ func init() { ff.StringP(commonflags.CIDFlag, "", "", "Target container ID.") _ = cobra.MarkFlagRequired(createCmd.Flags(), commonflags.CIDFlag) - ff.StringArray(ruleFlag, []string{}, "Rule statement") - ff.String(pathFlag, "", "Path to encoded chain in JSON or binary format") - ff.String(chainIDFlag, "", "Assign ID to the parsed chain") - ff.Bool(chainIDHexFlag, false, "Flag to parse chain ID as hex") + ff.StringArray(apeCmd.RuleFlag, []string{}, "Rule statement") + ff.String(apeCmd.PathFlag, "", "Path to encoded chain in JSON or binary format") + ff.String(apeCmd.ChainIDFlag, "", "Assign ID to the parsed chain") + ff.Bool(apeCmd.ChainIDHexFlag, false, "Flag to parse chain ID as hex") ff.String(outputFlag, "", "Output path to dump result JSON-encoded APE override") _ = cobra.MarkFlagFilename(createCmd.Flags(), outputFlag) } - -func parseChainID(cmd *cobra.Command) apechain.ID { - chainID, _ := cmd.Flags().GetString(chainIDFlag) - if chainID == "" { - commonCmd.ExitOnErr(cmd, "read chain id error: %w", - errChainIDCannotBeEmpty) - } - return apechain.ID(chainID) -} - -func parseChain(cmd *cobra.Command) *apechain.Chain { - chain := new(apechain.Chain) - - if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { - commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules)) - } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { - commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) - } else { - commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed) - } - - chain.ID = parseChainID(cmd) - - cmd.Println("Parsed chain:") - apeCmd.PrintHumanReadableAPEChain(cmd, chain) - - return chain -} From a339b52a6038f0746a54acd8f668ea57a8541fd5 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 18 Nov 2024 14:11:21 +0300 Subject: [PATCH 1021/1413] [#1501] adm: Refactor APE-chains managing subcommands * Use `cmd/internal/common/ape` parser commands within `ape` subcommands * Use flag names from `cmd/internal/common/ape Signed-off-by: Airat Arifullin --- .../internal/modules/morph/ape/ape.go | 86 ++++++--------- .../internal/modules/morph/ape/ape_util.go | 103 ++++-------------- cmd/internal/common/ape/commands.go | 7 +- 3 files changed, 58 insertions(+), 138 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index fb363f9037..8fcd4a441c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -14,26 +14,10 @@ import ( ) const ( - namespaceTarget = "namespace" - containerTarget = "container" - userTarget = "user" - groupTarget = "group" - jsonFlag = "json" - jsonFlagDesc = "Output rule chains in JSON format" - chainIDFlag = "chain-id" - chainIDDesc = "Rule chain ID" - ruleFlag = "rule" - ruleFlagDesc = "Rule chain in text format" - pathFlag = "path" - pathFlagDesc = "path to encoded chain in JSON or binary format" - targetNameFlag = "target-name" - targetNameDesc = "Resource name in APE resource name format" - targetTypeFlag = "target-type" - targetTypeDesc = "Resource type(container/namespace)" - addrAdminFlag = "addr" - addrAdminDesc = "The address of the admins wallet" - chainNameFlag = "chain-name" - chainNameFlagDesc = "Chain name(ingress|s3)" + jsonFlag = "json" + jsonFlagDesc = "Output rule chains in JSON format" + addrAdminFlag = "addr" + addrAdminDesc = "The address of the admins wallet" ) var ( @@ -101,17 +85,17 @@ func initAddRuleChainCmd() { addRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) addRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) - addRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) - _ = addRuleChainCmd.MarkFlagRequired(targetTypeFlag) - addRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc) - _ = addRuleChainCmd.MarkFlagRequired(targetNameFlag) + addRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) + _ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) + addRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetTypeFlagDesc) + _ = addRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag) - addRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) - _ = addRuleChainCmd.MarkFlagRequired(chainIDFlag) - addRuleChainCmd.Flags().StringArray(ruleFlag, []string{}, ruleFlagDesc) - addRuleChainCmd.Flags().String(pathFlag, "", pathFlagDesc) - addRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) - addRuleChainCmd.MarkFlagsMutuallyExclusive(ruleFlag, pathFlag) + addRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc) + _ = addRuleChainCmd.MarkFlagRequired(apeCmd.ChainIDFlag) + addRuleChainCmd.Flags().StringArray(apeCmd.RuleFlag, []string{}, apeCmd.RuleFlagDesc) + addRuleChainCmd.Flags().String(apeCmd.PathFlag, "", apeCmd.PathFlagDesc) + addRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc) + addRuleChainCmd.MarkFlagsMutuallyExclusive(apeCmd.RuleFlag, apeCmd.PathFlag) } func initRemoveRuleChainCmd() { @@ -120,26 +104,25 @@ func initRemoveRuleChainCmd() { removeRuleChainCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) removeRuleChainCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) - removeRuleChainCmd.Flags().String(targetTypeFlag, "", targetTypeDesc) - _ = removeRuleChainCmd.MarkFlagRequired(targetTypeFlag) - removeRuleChainCmd.Flags().String(targetNameFlag, "", targetNameDesc) - _ = removeRuleChainCmd.MarkFlagRequired(targetNameFlag) - removeRuleChainCmd.Flags().String(chainIDFlag, "", chainIDDesc) - removeRuleChainCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) + removeRuleChainCmd.Flags().String(apeCmd.TargetTypeFlag, "", apeCmd.TargetTypeFlagDesc) + _ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) + removeRuleChainCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) + _ = removeRuleChainCmd.MarkFlagRequired(apeCmd.TargetNameFlag) + removeRuleChainCmd.Flags().String(apeCmd.ChainIDFlag, "", apeCmd.ChainIDFlagDesc) + removeRuleChainCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc) removeRuleChainCmd.Flags().Bool(commonflags.AllFlag, false, "Remove all chains for target") - removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, chainIDFlag) + removeRuleChainCmd.MarkFlagsMutuallyExclusive(commonflags.AllFlag, apeCmd.ChainIDFlag) } func initListRuleChainsCmd() { Cmd.AddCommand(listRuleChainsCmd) listRuleChainsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - listRuleChainsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) - _ = listRuleChainsCmd.MarkFlagRequired(targetTypeFlag) - listRuleChainsCmd.Flags().String(targetNameFlag, "", targetNameDesc) - _ = listRuleChainsCmd.MarkFlagRequired(targetNameFlag) + listRuleChainsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc) + _ = listRuleChainsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) + listRuleChainsCmd.Flags().String(apeCmd.TargetNameFlag, "", apeCmd.TargetNameFlagDesc) listRuleChainsCmd.Flags().Bool(jsonFlag, false, jsonFlagDesc) - listRuleChainsCmd.Flags().String(chainNameFlag, ingress, chainNameFlagDesc) + listRuleChainsCmd.Flags().String(apeCmd.ChainNameFlag, apeCmd.Ingress, apeCmd.ChainNameFlagDesc) } func initSetAdminCmd() { @@ -161,15 +144,15 @@ func initListTargetsCmd() { Cmd.AddCommand(listTargetsCmd) listTargetsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - listTargetsCmd.Flags().StringP(targetTypeFlag, "t", "", targetTypeDesc) - _ = listTargetsCmd.MarkFlagRequired(targetTypeFlag) + listTargetsCmd.Flags().StringP(apeCmd.TargetTypeFlag, "t", "", apeCmd.TargetTypeFlagDesc) + _ = listTargetsCmd.MarkFlagRequired(apeCmd.TargetTypeFlag) } func addRuleChain(cmd *cobra.Command, _ []string) { - chain := parseChain(cmd) + chain := apeCmd.ParseChain(cmd) target := parseTarget(cmd) pci, ac := newPolicyContractInterface(cmd) - h, vub, err := pci.AddMorphRuleChain(parseChainName(cmd), target, chain) + h, vub, err := pci.AddMorphRuleChain(apeCmd.ParseChainName(cmd), target, chain) cmd.Println("Waiting for transaction to persist...") _, err = ac.Wait(h, vub, err) commonCmd.ExitOnErr(cmd, "add rule chain error: %w", err) @@ -181,14 +164,14 @@ func removeRuleChain(cmd *cobra.Command, _ []string) { pci, ac := newPolicyContractInterface(cmd) removeAll, _ := cmd.Flags().GetBool(commonflags.AllFlag) if removeAll { - h, vub, err := pci.RemoveMorphRuleChainsByTarget(parseChainName(cmd), target) + h, vub, err := pci.RemoveMorphRuleChainsByTarget(apeCmd.ParseChainName(cmd), target) cmd.Println("Waiting for transaction to persist...") _, err = ac.Wait(h, vub, err) commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) cmd.Println("All chains for target removed successfully") } else { - chainID := parseChainID(cmd) - h, vub, err := pci.RemoveMorphRuleChain(parseChainName(cmd), target, chainID) + chainID := apeCmd.ParseChainID(cmd) + h, vub, err := pci.RemoveMorphRuleChain(apeCmd.ParseChainName(cmd), target, chainID) cmd.Println("Waiting for transaction to persist...") _, err = ac.Wait(h, vub, err) commonCmd.ExitOnErr(cmd, "remove rule chain error: %w", err) @@ -199,7 +182,7 @@ func removeRuleChain(cmd *cobra.Command, _ []string) { func listRuleChains(cmd *cobra.Command, _ []string) { target := parseTarget(cmd) pci, _ := newPolicyContractReaderInterface(cmd) - chains, err := pci.ListMorphRuleChains(parseChainName(cmd), target) + chains, err := pci.ListMorphRuleChains(apeCmd.ParseChainName(cmd), target) commonCmd.ExitOnErr(cmd, "list rule chains error: %w", err) if len(chains) == 0 { return @@ -235,8 +218,7 @@ func getAdmin(cmd *cobra.Command, _ []string) { } func listTargets(cmd *cobra.Command, _ []string) { - typ, err := parseTargetType(cmd) - commonCmd.ExitOnErr(cmd, "parse target type error: %w", err) + typ := apeCmd.ParseTargetType(cmd) pci, inv := newPolicyContractReaderInterface(cmd) sid, it, err := pci.ListTargetsIterator(typ) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 1a70dd4a21..6780e6dd34 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -2,14 +2,12 @@ package ape import ( "errors" - "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" - parseutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/ape" - apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" morph "git.frostfs.info/TrueCloudLab/policy-engine/pkg/morph/policy" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -19,90 +17,29 @@ import ( "github.com/spf13/viper" ) -const ( - ingress = "ingress" - s3 = "s3" -) - -var mChainName = map[string]apechain.Name{ - ingress: apechain.Ingress, - s3: apechain.S3, -} - -var ( - errUnknownTargetType = errors.New("unknown target type") - errChainIDCannotBeEmpty = errors.New("chain id cannot be empty") - errRuleIsNotParsed = errors.New("rule is not passed") - errUnsupportedChainName = errors.New("unsupported chain name") -) +var errUnknownTargetType = errors.New("unknown target type") func parseTarget(cmd *cobra.Command) policyengine.Target { - name, _ := cmd.Flags().GetString(targetNameFlag) - typ, err := parseTargetType(cmd) - - // interpret "root" namespace as empty - if typ == policyengine.Namespace && name == "root" { - name = "" - } - - commonCmd.ExitOnErr(cmd, "read target type error: %w", err) - - return policyengine.Target{ - Name: name, - Type: typ, - } -} - -func parseTargetType(cmd *cobra.Command) (policyengine.TargetType, error) { - typ, _ := cmd.Flags().GetString(targetTypeFlag) + typ := apeCmd.ParseTargetType(cmd) + name, _ := cmd.Flags().GetString(apeCmd.TargetNameFlag) switch typ { - case namespaceTarget: - return policyengine.Namespace, nil - case containerTarget: - return policyengine.Container, nil - case userTarget: - return policyengine.User, nil - case groupTarget: - return policyengine.Group, nil + case policyengine.Namespace: + if name == "root" { + name = "" + } + return policyengine.NamespaceTarget(name) + case policyengine.Container: + var cnr cid.ID + commonCmd.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(name)) + return policyengine.ContainerTarget(name) + case policyengine.User: + return policyengine.UserTarget(name) + case policyengine.Group: + return policyengine.GroupTarget(name) + default: + commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) } - return -1, errUnknownTargetType -} - -func parseChainID(cmd *cobra.Command) apechain.ID { - chainID, _ := cmd.Flags().GetString(chainIDFlag) - if chainID == "" { - commonCmd.ExitOnErr(cmd, "read chain id error: %w", - errChainIDCannotBeEmpty) - } - return apechain.ID(chainID) -} - -func parseChain(cmd *cobra.Command) *apechain.Chain { - chain := new(apechain.Chain) - - if rules, _ := cmd.Flags().GetStringArray(ruleFlag); len(rules) > 0 { - commonCmd.ExitOnErr(cmd, "parser error: %w", parseutil.ParseAPEChain(chain, rules)) - } else if encPath, _ := cmd.Flags().GetString(pathFlag); encPath != "" { - commonCmd.ExitOnErr(cmd, "decode binary or json error: %w", parseutil.ParseAPEChainBinaryOrJSON(chain, encPath)) - } else { - commonCmd.ExitOnErr(cmd, "parser error: %w", errRuleIsNotParsed) - } - - chain.ID = parseChainID(cmd) - - cmd.Println("Parsed chain:") - apeCmd.PrintHumanReadableAPEChain(cmd, chain) - - return chain -} - -func parseChainName(cmd *cobra.Command) apechain.Name { - chainName, _ := cmd.Flags().GetString(chainNameFlag) - apeChainName, ok := mChainName[strings.ToLower(chainName)] - if !ok { - commonCmd.ExitOnErr(cmd, "", errUnsupportedChainName) - } - return apeChainName + panic("unreachable") } // invokerAdapter adapats invoker.Invoker to ContractStorageInvoker interface. diff --git a/cmd/internal/common/ape/commands.go b/cmd/internal/common/ape/commands.go index 3547473305..e5a35ab711 100644 --- a/cmd/internal/common/ape/commands.go +++ b/cmd/internal/common/ape/commands.go @@ -97,7 +97,7 @@ func ParseTarget(cmd *cobra.Command) engine.Target { default: commonCmd.ExitOnErr(cmd, "read target type error: %w", errUnknownTargetType) } - return engine.Target{} + panic("unreachable") } // ParseTargetType handles target type parsing of an APE chain. @@ -112,9 +112,10 @@ func ParseTargetType(cmd *cobra.Command) engine.TargetType { return engine.User case groupTarget: return engine.Group + default: + commonCmd.ExitOnErr(cmd, "parse target type error: %w", errUnknownTargetType) } - commonCmd.ExitOnErr(cmd, "parse target type error: %w", errUnknownTargetType) - return engine.TargetType(0) + panic("unreachable") } // ParseChainID handles the parsing of APE-chain identifier. From 3042490340fcfe223fa8069006876f84e1721082 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 20 Nov 2024 10:43:38 +0300 Subject: [PATCH 1022/1413] [#1507] timer: Remove unused OnDelta() method Signed-off-by: Evgenii Stratonikov --- pkg/morph/timer/block.go | 73 +---------------- pkg/morph/timer/block_test.go | 142 ++++------------------------------ 2 files changed, 17 insertions(+), 198 deletions(-) diff --git a/pkg/morph/timer/block.go b/pkg/morph/timer/block.go index be20d35713..974be1120a 100644 --- a/pkg/morph/timer/block.go +++ b/pkg/morph/timer/block.go @@ -15,41 +15,19 @@ type BlockTickHandler func() // It can tick the blocks and perform certain actions // on block time intervals. type BlockTimer struct { - rolledBack bool - mtx sync.Mutex dur BlockMeter baseDur uint32 - mul, div uint32 - cur, tgt uint32 last uint32 h BlockTickHandler - ps []BlockTimer - once bool - - deltaCfg -} - -// DeltaOption is an option of delta-interval handler. -type DeltaOption func(*deltaCfg) - -type deltaCfg struct { - pulse bool -} - -// WithPulse returns option to call delta-interval handler multiple times. -func WithPulse() DeltaOption { - return func(c *deltaCfg) { - c.pulse = true - } } // StaticBlockMeter returns BlockMeters that always returns (d, nil). @@ -65,52 +43,19 @@ func StaticBlockMeter(d uint32) BlockMeter { func NewBlockTimer(dur BlockMeter, h BlockTickHandler) *BlockTimer { return &BlockTimer{ dur: dur, - mul: 1, - div: 1, h: h, - deltaCfg: deltaCfg{ - pulse: true, - }, } } // NewOneTickTimer creates a new BlockTimer that ticks only once. -// -// Do not use delta handlers with pulse in this timer. func NewOneTickTimer(dur BlockMeter, h BlockTickHandler) *BlockTimer { return &BlockTimer{ dur: dur, - mul: 1, - div: 1, h: h, once: true, } } -// OnDelta registers handler which is executed on (mul / div * BlockMeter()) block -// after basic interval reset. -// -// If WithPulse option is provided, handler is executed (mul / div * BlockMeter()) block -// during base interval. -func (t *BlockTimer) OnDelta(mul, div uint32, h BlockTickHandler, opts ...DeltaOption) { - c := deltaCfg{ - pulse: false, - } - - for i := range opts { - opts[i](&c) - } - - t.ps = append(t.ps, BlockTimer{ - mul: mul, - div: div, - h: h, - once: t.once, - - deltaCfg: c, - }) -} - // Reset resets previous ticks of the BlockTimer. // // Returns BlockMeter's error upon occurrence. @@ -124,29 +69,18 @@ func (t *BlockTimer) Reset() error { t.resetWithBaseInterval(d) - for i := range t.ps { - t.ps[i].resetWithBaseInterval(d) - } - t.mtx.Unlock() return nil } func (t *BlockTimer) resetWithBaseInterval(d uint32) { - t.rolledBack = false t.baseDur = d t.reset() } func (t *BlockTimer) reset() { - mul, div := t.mul, t.div - - if !t.pulse && t.rolledBack && mul < div { - mul, div = 1, 1 - } - - delta := mul * t.baseDur / div + delta := t.baseDur if delta == 0 { delta = 1 } @@ -180,12 +114,7 @@ func (t *BlockTimer) tick(h uint32) { if !t.once { t.cur = 0 - t.rolledBack = true t.reset() } } - - for i := range t.ps { - t.ps[i].tick(h) - } } diff --git a/pkg/morph/timer/block_test.go b/pkg/morph/timer/block_test.go index ee6091845f..c0af6c5c3d 100644 --- a/pkg/morph/timer/block_test.go +++ b/pkg/morph/timer/block_test.go @@ -63,85 +63,6 @@ func TestBlockTimer(t *testing.T) { tickN(bt, intervalNum*blockDur) require.Equal(t, intervalNum, uint32(baseCallCounter)) - - // add half-interval handler - halfCallCounter := uint32(0) - - bt.OnDelta(1, 2, func() { - halfCallCounter++ - }) - - // add double interval handler - doubleCallCounter := uint32(0) - - bt.OnDelta(2, 1, func() { - doubleCallCounter++ - }) - - require.NoError(t, bt.Reset()) - - baseCallCounter = 0 - intervalNum = 20 - - tickN(bt, intervalNum*blockDur) - - require.Equal(t, intervalNum, uint32(halfCallCounter)) - require.Equal(t, intervalNum, uint32(baseCallCounter)) - require.Equal(t, intervalNum/2, uint32(doubleCallCounter)) -} - -func TestDeltaPulse(t *testing.T) { - blockDur := uint32(9) - baseCallCounter := uint32(0) - - bt := timer.NewBlockTimer(timer.StaticBlockMeter(blockDur), func() { - baseCallCounter++ - }) - - deltaCallCounter := uint32(0) - - div := uint32(3) - - bt.OnDelta(1, div, func() { - deltaCallCounter++ - }, timer.WithPulse()) - - require.NoError(t, bt.Reset()) - - intervalNum := uint32(7) - - tickN(bt, intervalNum*blockDur) - - require.Equal(t, intervalNum, uint32(baseCallCounter)) - require.Equal(t, intervalNum*div, uint32(deltaCallCounter)) -} - -func TestDeltaReset(t *testing.T) { - blockDur := uint32(6) - baseCallCounter := 0 - - bt := timer.NewBlockTimer(timer.StaticBlockMeter(blockDur), func() { - baseCallCounter++ - }) - - detlaCallCounter := 0 - - bt.OnDelta(1, 3, func() { - detlaCallCounter++ - }) - - require.NoError(t, bt.Reset()) - - tickN(bt, 6) - - require.Equal(t, 1, baseCallCounter) - require.Equal(t, 1, detlaCallCounter) - - require.NoError(t, bt.Reset()) - - tickN(bt, 3) - - require.Equal(t, 2, detlaCallCounter) } func TestNewOneTickTimer(t *testing.T) { @@ -168,82 +89,51 @@ func TestNewOneTickTimer(t *testing.T) { tickN(bt, 10) require.Equal(t, 1, baseCallCounter) }) - - t.Run("delta without pulse", func(t *testing.T) { - blockDur = uint32(10) - baseCallCounter = 0 - - bt = timer.NewOneTickTimer(timer.StaticBlockMeter(blockDur), func() { - baseCallCounter++ - }) - - detlaCallCounter := 0 - - bt.OnDelta(1, 10, func() { - detlaCallCounter++ - }) - - require.NoError(t, bt.Reset()) - - tickN(bt, 10) - require.Equal(t, 1, baseCallCounter) - require.Equal(t, 1, detlaCallCounter) - - tickN(bt, 10) // 10 more ticks must not affect counters - require.Equal(t, 1, baseCallCounter) - require.Equal(t, 1, detlaCallCounter) - }) } func TestBlockTimer_TickSameHeight(t *testing.T) { - var baseCounter, deltaCounter int + var baseCounter int blockDur := uint32(2) bt := timer.NewBlockTimer( func() (uint32, error) { return blockDur, nil }, func() { baseCounter++ }) - bt.OnDelta(2, 1, func() { - deltaCounter++ - }) require.NoError(t, bt.Reset()) - check := func(t *testing.T, h uint32, base, delta int) { + check := func(t *testing.T, h uint32, base int) { for range 2 * int(blockDur) { bt.Tick(h) require.Equal(t, base, baseCounter) - require.Equal(t, delta, deltaCounter) } } - check(t, 1, 0, 0) - check(t, 2, 1, 0) - check(t, 3, 1, 0) - check(t, 4, 2, 1) + check(t, 1, 0) + check(t, 2, 1) + check(t, 3, 1) + check(t, 4, 2) t.Run("works the same way after `Reset()`", func(t *testing.T) { t.Run("same block duration", func(t *testing.T) { require.NoError(t, bt.Reset()) baseCounter = 0 - deltaCounter = 0 - check(t, 1, 0, 0) - check(t, 2, 1, 0) - check(t, 3, 1, 0) - check(t, 4, 2, 1) + check(t, 1, 0) + check(t, 2, 1) + check(t, 3, 1) + check(t, 4, 2) }) t.Run("different block duration", func(t *testing.T) { blockDur = 3 require.NoError(t, bt.Reset()) baseCounter = 0 - deltaCounter = 0 - check(t, 1, 0, 0) - check(t, 2, 0, 0) - check(t, 3, 1, 0) - check(t, 4, 1, 0) - check(t, 5, 1, 0) - check(t, 6, 2, 1) + check(t, 1, 0) + check(t, 2, 0) + check(t, 3, 1) + check(t, 4, 1) + check(t, 5, 1) + check(t, 6, 2) }) }) } From 2e974f734c38161c251e6556daacbc8fbf4fbfd3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 20 Nov 2024 10:53:33 +0300 Subject: [PATCH 1023/1413] [#1507] timer/test: Improve test coverage Signed-off-by: Evgenii Stratonikov --- pkg/morph/timer/block_test.go | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/pkg/morph/timer/block_test.go b/pkg/morph/timer/block_test.go index c0af6c5c3d..615631dcb8 100644 --- a/pkg/morph/timer/block_test.go +++ b/pkg/morph/timer/block_test.go @@ -1,6 +1,7 @@ package timer_test import ( + "errors" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/timer" @@ -48,6 +49,38 @@ func TestIRBlockTimer_Reset(t *testing.T) { require.Equal(t, baseCounter[0], baseCounter[1]) } +func TestBlockTimer_ResetChangeDuration(t *testing.T) { + var dur uint32 = 2 + var err error + var counter int + + bt := timer.NewBlockTimer( + func() (uint32, error) { return dur, err }, + func() { counter++ }) + + require.NoError(t, bt.Reset()) + + tickN(bt, 2) + require.Equal(t, 1, counter) + + t.Run("return error", func(t *testing.T) { + dur = 5 + err = errors.New("my awesome error") + require.ErrorIs(t, bt.Reset(), err) + + tickN(bt, 2) + require.Equal(t, 2, counter) + }) + t.Run("change duration", func(t *testing.T) { + dur = 5 + err = nil + require.NoError(t, bt.Reset()) + + tickN(bt, 5) + require.Equal(t, 3, counter) + }) +} + func TestBlockTimer(t *testing.T) { blockDur := uint32(10) baseCallCounter := uint32(0) From 49a4e727fd864da271c72ee6a53f1b315a959efd Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 20 Nov 2024 10:55:24 +0300 Subject: [PATCH 1024/1413] [#1507] timer/test: Use const for constants Make it easy to see what the test is about. Signed-off-by: Evgenii Stratonikov --- pkg/morph/timer/block_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/morph/timer/block_test.go b/pkg/morph/timer/block_test.go index 615631dcb8..a144b3db66 100644 --- a/pkg/morph/timer/block_test.go +++ b/pkg/morph/timer/block_test.go @@ -18,7 +18,7 @@ func tickN(t *timer.BlockTimer, n uint32) { // "resetting" consists of ticking the current height as well and invoking `Reset`. func TestIRBlockTimer_Reset(t *testing.T) { var baseCounter [2]int - blockDur := uint32(3) + const blockDur = uint32(3) bt1 := timer.NewBlockTimer( func() (uint32, error) { return blockDur, nil }, @@ -82,7 +82,7 @@ func TestBlockTimer_ResetChangeDuration(t *testing.T) { } func TestBlockTimer(t *testing.T) { - blockDur := uint32(10) + const blockDur = uint32(10) baseCallCounter := uint32(0) bt := timer.NewBlockTimer(timer.StaticBlockMeter(blockDur), func() { From 6ae8667fb4a7c00fc5d3a72ff181a8da54a0eba3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 20 Nov 2024 11:40:13 +0300 Subject: [PATCH 1025/1413] [#1509] .forgejo: Run actions on push to master Signed-off-by: Evgenii Stratonikov --- .forgejo/workflows/build.yml | 6 +++++- .forgejo/workflows/pre-commit.yml | 7 ++++++- .forgejo/workflows/tests.yml | 7 ++++++- .forgejo/workflows/vulncheck.yml | 7 ++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index ce2d64dd99..9129d136ed 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -1,6 +1,10 @@ name: Build -on: [pull_request] +on: + pull_request: + push: + branches: + - master jobs: build: diff --git a/.forgejo/workflows/pre-commit.yml b/.forgejo/workflows/pre-commit.yml index 8b06a2fdfb..b27e7a39a8 100644 --- a/.forgejo/workflows/pre-commit.yml +++ b/.forgejo/workflows/pre-commit.yml @@ -1,5 +1,10 @@ name: Pre-commit hooks -on: [pull_request] + +on: + pull_request: + push: + branches: + - master jobs: precommit: diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index 07ba5c268f..4f1bebe61f 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -1,5 +1,10 @@ name: Tests and linters -on: [pull_request] + +on: + pull_request: + push: + branches: + - master jobs: lint: diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index 2951a80595..cf15005b10 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -1,5 +1,10 @@ name: Vulncheck -on: [pull_request] + +on: + pull_request: + push: + branches: + - master jobs: vulncheck: From 2e2c62147db434c3834be92e7ebcc3ed80a44a57 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 20 Nov 2024 14:16:17 +0300 Subject: [PATCH 1026/1413] [#1513] adm: Move ProtoConfigPath from `constants` to `commonflags` package Refs #932 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/commonflags/flags.go | 1 + cmd/frostfs-adm/internal/modules/morph/constants/const.go | 1 - .../internal/modules/morph/helper/local_client.go | 3 ++- .../internal/modules/morph/initialize/initialize_test.go | 2 +- cmd/frostfs-adm/internal/modules/morph/initialize/root.go | 5 ++--- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-adm/internal/commonflags/flags.go b/cmd/frostfs-adm/internal/commonflags/flags.go index 81395edb0f..87692d0136 100644 --- a/cmd/frostfs-adm/internal/commonflags/flags.go +++ b/cmd/frostfs-adm/internal/commonflags/flags.go @@ -20,6 +20,7 @@ const ( AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" LocalDumpFlag = "local-dump" + ProtoConfigPath = "protocol" ContractsInitFlag = "contracts" ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" ContractsURLFlag = "contracts-url" diff --git a/cmd/frostfs-adm/internal/modules/morph/constants/const.go b/cmd/frostfs-adm/internal/modules/morph/constants/const.go index a3b4f129a5..be4041a860 100644 --- a/cmd/frostfs-adm/internal/modules/morph/constants/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/constants/const.go @@ -4,7 +4,6 @@ import "time" const ( ConsensusAccountName = "consensus" - ProtoConfigPath = "protocol" // MaxAlphabetNodes is the maximum number of candidates allowed, which is currently limited by the size // of the invocation script. diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index 375fa84d74..ed028fb7c9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -8,6 +8,7 @@ import ( "sort" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/config" @@ -47,7 +48,7 @@ type LocalClient struct { } func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet, dumpPath string) (*LocalClient, error) { - cfg, err := config.LoadFile(v.GetString(constants.ProtoConfigPath)) + cfg, err := config.LoadFile(v.GetString(commonflags.ProtoConfigPath)) if err != nil { return nil, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go index 74f5d3e888..9bc51c055c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_test.go @@ -62,7 +62,7 @@ func testInitialize(t *testing.T, committeeSize int) { v := viper.GetViper() require.NoError(t, generateTestData(testdataDir, committeeSize)) - v.Set(constants.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) + v.Set(commonflags.ProtoConfigPath, filepath.Join(testdataDir, protoFileName)) // Set to the path or remove the next statement to download from the network. require.NoError(t, Cmd.Flags().Set(commonflags.ContractsInitFlag, contractsPath)) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go index b7885c5124..50f14e7282 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/root.go @@ -2,7 +2,6 @@ package initialize import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -32,7 +31,7 @@ var Cmd = &cobra.Command{ _ = viper.BindPFlag(commonflags.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) _ = viper.BindPFlag(commonflags.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) _ = viper.BindPFlag(commonflags.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) - _ = viper.BindPFlag(constants.ProtoConfigPath, cmd.Flags().Lookup(constants.ProtoConfigPath)) + _ = viper.BindPFlag(commonflags.ProtoConfigPath, cmd.Flags().Lookup(commonflags.ProtoConfigPath)) }, RunE: initializeSideChainCmd, } @@ -48,7 +47,7 @@ func initInitCmd() { // Defaults are taken from neo-preodolenie. Cmd.Flags().Uint64(containerFeeCLIFlag, 1000, "Container registration fee") Cmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") - Cmd.Flags().String(constants.ProtoConfigPath, "", "Path to the consensus node configuration") + Cmd.Flags().String(commonflags.ProtoConfigPath, "", "Path to the consensus node configuration") Cmd.Flags().String(commonflags.LocalDumpFlag, "", "Path to the blocks dump file") Cmd.MarkFlagsMutuallyExclusive(commonflags.ContractsInitFlag, commonflags.ContractsURLFlag) } From f12f04199e8437a9a6f440cac7ef5dfdd4454efc Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 21 Nov 2024 13:17:16 +0300 Subject: [PATCH 1027/1413] [#1516] traverser: Check for placement vector out of range Placement vector may contain fewer nodes count than it required by policy due to the outage of the one of the node. Signed-off-by: Anton Nikiforov --- .../object_manager/placement/traverser.go | 5 +- .../placement/traverser_test.go | 46 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 6440f187db..7c720b204a 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -114,8 +114,9 @@ func NewTraverser(opts ...Option) (*Traverser, error) { var unsortedVector []netmap.NodeInfo var regularVector []netmap.NodeInfo for i := range rem { - unsortedVector = append(unsortedVector, ns[i][:rem[i]]...) - regularVector = append(regularVector, ns[i][rem[i]:]...) + pivot := min(len(ns[i]), rem[i]) + unsortedVector = append(unsortedVector, ns[i][:pivot]...) + regularVector = append(regularVector, ns[i][pivot:]...) } rem = []int{-1, -1} diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index 38f62aa076..f96e5c8a7e 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -356,6 +356,52 @@ func TestTraverserPriorityMetrics(t *testing.T) { require.Nil(t, next) }) + t.Run("one rep one metric fewer nodes", func(t *testing.T) { + selectors := []int{2} + replicas := []int{3} + + nodes, cnr := testPlacement(selectors, replicas) + + // Node_0, PK - ip4/0.0.0.0/tcp/0 + nodes[0][0].SetAttribute("ClusterName", "A") + // Node_1, PK - ip4/0.0.0.0/tcp/1 + nodes[0][1].SetAttribute("ClusterName", "B") + + sdkNode := testNode(5) + sdkNode.SetAttribute("ClusterName", "B") + + nodesCopy := copyVectors(nodes) + + m := []Metric{NewAttributeMetric("ClusterName")} + + tr, err := NewTraverser( + ForContainer(cnr), + UseBuilder(&testBuilder{ + vectors: nodesCopy, + }), + WithoutSuccessTracking(), + WithPriorityMetrics(m), + WithNodeState(&nodeState{ + node: &sdkNode, + }), + ) + require.NoError(t, err) + + // Without priority metric `ClusterName` the order will be: + // [ {Node_0 A}, {Node_1 A} ] + // With priority metric `ClusterName` and current node in cluster B + // the order should be: + // [ {Node_1 B}, {Node_0 A} ] + next := tr.Next() + require.NotNil(t, next) + require.Equal(t, 2, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/1", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/0", string(next[1].PublicKey())) + + next = tr.Next() + require.Nil(t, next) + }) + t.Run("two reps two metrics", func(t *testing.T) { selectors := []int{3, 3} replicas := []int{2, 2} From efa4ce00b8eef3b896d94f0119edcdf7cbbc24b8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 21 Nov 2024 10:10:56 +0300 Subject: [PATCH 1028/1413] [#1514] go.mod: Update frostfs-contract to v0.21.0-rc.3 Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 84f9f9a668..c538a31789 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 diff --git a/go.sum b/go.sum index d93e9b74e0..064f3274e4 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0 h1:8Z5iPhieCrbcdhxBuY/Bajh6V5fki7Whh0b4S2zYJYU= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.20.0/go.mod h1:Y2Xorxc8SBO4phoek7n3XxaPZz5rIrFgDsU4TOjmlGA= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4 h1:o3iqVmbvFsfe8kpB2Hvuix6Q/tAhbiPLP91xK4lmoBQ= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4/go.mod h1:5fSm/l5xSjGWqsPUffSdboiGFUHa7y/1S0fvxzQowN8= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= @@ -267,6 +267,7 @@ github.com/ssgreg/journald v1.0.0/go.mod h1:RUckwmTM8ghGWPslq2+ZBZzbb9/2KgjzYZ4J github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= From 2771fdb8c7916c39dc855a0ee1a8eae97bb10205 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 21 Nov 2024 10:39:04 +0300 Subject: [PATCH 1029/1413] [#1514] adm/nns: Use nns.GetAllRecords() wrapper It was not possible previously, because GetAllRecords() was not declared safe in frostfs-contract. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/nns/record.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/record.go b/cmd/frostfs-adm/internal/modules/morph/nns/record.go index 66bb1b94fb..32c88481f5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/record.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/record.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/spf13/cobra" ) @@ -77,11 +76,11 @@ func addRecord(cmd *cobra.Command, _ []string) { } func getRecords(cmd *cobra.Command, _ []string) { - c, act, hash := getRPCClient(cmd) + c, act, _ := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) if recordType == "" { - sid, r, err := unwrap.SessionIterator(act.Invoker.Call(hash, "getAllRecords", name)) + sid, r, err := c.GetAllRecords(name) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) defer func() { _ = act.Invoker.TerminateSession(sid) From 9073e555db7f0f5e0a389ad3ac9c23885c2df67f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 21 Nov 2024 10:43:53 +0300 Subject: [PATCH 1030/1413] [#1514] adm/nns: Do not create actor for readonly commands `nns get-records` and `nns tokens` command do not need to sign anything, so remove useless actor and use invoker directly. `NewLocalActor()` is only used in `ape` and `nns` packages. `ape` package seem to use it correctly, only when alphabet wallets are provided, so no changes there. Also, remove --alphabet-wallets flag from commands that do not need it. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/actor.go | 48 +++++++------------ .../internal/modules/morph/nns/helper.go | 13 +++++ .../internal/modules/morph/nns/record.go | 9 ++-- .../internal/modules/morph/nns/tokens.go | 5 +- 4 files changed, 36 insertions(+), 39 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go index ff0421335c..eb04444089 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go @@ -38,38 +38,24 @@ func NewLocalActor(cmd *cobra.Command, c actor.RPCActor, accName string) (*Local walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) var act *actor.Actor var accounts []*wallet.Account - if walletDir == "" { - account, err := wallet.NewAccount() - commonCmd.ExitOnErr(cmd, "unable to create dummy account: %w", err) - act, err = actor.New(c, []actor.SignerAccount{{ - Signer: transaction.Signer{ - Account: account.Contract.ScriptHash(), - Scopes: transaction.Global, - }, - Account: account, - }}) - if err != nil { - return nil, err - } - } else { - wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir) - commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) - for _, w := range wallets { - acc, err := GetWalletAccount(w, accName) - commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err) - accounts = append(accounts, acc) - } - act, err = actor.New(c, []actor.SignerAccount{{ - Signer: transaction.Signer{ - Account: accounts[0].Contract.ScriptHash(), - Scopes: transaction.Global, - }, - Account: accounts[0], - }}) - if err != nil { - return nil, err - } + wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir) + commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) + + for _, w := range wallets { + acc, err := GetWalletAccount(w, accName) + commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err) + accounts = append(accounts, acc) + } + act, err = actor.New(c, []actor.SignerAccount{{ + Signer: transaction.Signer{ + Account: accounts[0].Contract.ScriptHash(), + Scopes: transaction.Global, + }, + Account: accounts[0], + }}) + if err != nil { + return nil, err } return &LocalActor{ neoActor: act, diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index de439acd1d..68a629c3c3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/cobra" @@ -24,3 +25,15 @@ func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, uti commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) return client.New(ac, nnsCs.Hash), ac, nnsCs.Hash } + +func nnsReader(cmd *cobra.Command) (*client.ContractReader, *invoker.Invoker) { + c, err := helper.GetN3Client(viper.GetViper()) + commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) + + inv := invoker.New(c, nil) + r := management.NewReader(inv) + nnsCs, err := helper.GetContractByID(r, 1) + commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) + + return client.NewReader(inv, nnsCs.Hash), inv +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/record.go b/cmd/frostfs-adm/internal/modules/morph/nns/record.go index 32c88481f5..5a6db6e720 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/record.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/record.go @@ -28,7 +28,6 @@ func initAddRecordCmd() { func initGetRecordsCmd() { Cmd.AddCommand(getRecordsCmd) getRecordsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - getRecordsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) getRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) getRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) @@ -76,16 +75,16 @@ func addRecord(cmd *cobra.Command, _ []string) { } func getRecords(cmd *cobra.Command, _ []string) { - c, act, _ := getRPCClient(cmd) + c, inv := nnsReader(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) if recordType == "" { sid, r, err := c.GetAllRecords(name) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) defer func() { - _ = act.Invoker.TerminateSession(sid) + _ = inv.TerminateSession(sid) }() - items, err := act.Invoker.TraverseIterator(sid, &r, 0) + items, err := inv.TraverseIterator(sid, &r, 0) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) for len(items) != 0 { for j := range items { @@ -96,7 +95,7 @@ func getRecords(cmd *cobra.Command, _ []string) { recordTypeToString(nns.RecordType(rs[1].Value().(*big.Int).Int64())), string(bs)) } - items, err = act.Invoker.TraverseIterator(sid, &r, 0) + items, err = inv.TraverseIterator(sid, &r, 0) commonCmd.ExitOnErr(cmd, "unable to get records: %w", err) } } else { diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go b/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go index 3c7136e9d5..4ccbb1677a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/tokens.go @@ -18,12 +18,11 @@ const ( func initTokensCmd() { Cmd.AddCommand(tokensCmd) tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - tokensCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) tokensCmd.Flags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, verboseDesc) } func listTokens(cmd *cobra.Command, _ []string) { - c, _, _ := getRPCClient(cmd) + c, _ := nnsReader(cmd) it, err := c.Tokens() commonCmd.ExitOnErr(cmd, "unable to get tokens: %w", err) for toks, err := it.Next(10); err == nil && len(toks) > 0; toks, err = it.Next(10) { @@ -41,7 +40,7 @@ func listTokens(cmd *cobra.Command, _ []string) { } } -func getCnameRecord(c *client.Contract, token []byte) (string, error) { +func getCnameRecord(c *client.ContractReader, token []byte) (string, error) { items, err := c.GetRecords(string(token), big.NewInt(int64(nns.CNAME))) // GetRecords returns the error "not an array" if the domain does not contain records. From e5ea95c045fa5de03a699204102943cdb4bd7e1e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 21 Nov 2024 10:51:38 +0300 Subject: [PATCH 1031/1413] [#1514] adm/nns: Do not return hash from getRPCClient() It was unused and we employ better abstractions now. gopatch: ``` @@ var a, b expression @@ -a, b, _ := getRPCClient(...) +a, b := getRPCClient(...) ``` Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/nns/domains.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/nns/helper.go | 5 ++--- cmd/frostfs-adm/internal/modules/morph/nns/record.go | 6 +++--- cmd/frostfs-adm/internal/modules/morph/nns/renew.go | 2 +- cmd/frostfs-adm/internal/modules/morph/nns/update.go | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/domains.go b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go index 3684db94ab..c111545955 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/domains.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go @@ -24,7 +24,7 @@ func initRegisterCmd() { } func registerDomain(cmd *cobra.Command, _ []string) { - c, actor, _ := getRPCClient(cmd) + c, actor := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) email, _ := cmd.Flags().GetString(nnsEmailFlag) @@ -53,7 +53,7 @@ func initDeleteCmd() { } func deleteDomain(cmd *cobra.Command, _ []string) { - c, actor, _ := getRPCClient(cmd) + c, actor := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) h, vub, err := c.DeleteDomain(name) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index 68a629c3c3..4b7ae46645 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -7,12 +7,11 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" - "github.com/nspcc-dev/neo-go/pkg/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) -func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, util.Uint160) { +func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { v := viper.GetViper() c, err := helper.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) @@ -23,7 +22,7 @@ func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor, uti r := management.NewReader(ac.Invoker) nnsCs, err := helper.GetContractByID(r, 1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - return client.New(ac, nnsCs.Hash), ac, nnsCs.Hash + return client.New(ac, nnsCs.Hash), ac } func nnsReader(cmd *cobra.Command) (*client.ContractReader, *invoker.Invoker) { diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/record.go b/cmd/frostfs-adm/internal/modules/morph/nns/record.go index 5a6db6e720..cb6c5e0947 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/record.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/record.go @@ -59,7 +59,7 @@ func initDelRecordCmd() { } func addRecord(cmd *cobra.Command, _ []string) { - c, actor, _ := getRPCClient(cmd) + c, actor := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) data, _ := cmd.Flags().GetString(nnsRecordDataFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) @@ -112,7 +112,7 @@ func getRecords(cmd *cobra.Command, _ []string) { } func delRecords(cmd *cobra.Command, _ []string) { - c, actor, _ := getRPCClient(cmd) + c, actor := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) typ, err := getRecordType(recordType) @@ -127,7 +127,7 @@ func delRecords(cmd *cobra.Command, _ []string) { } func delRecord(cmd *cobra.Command, _ []string) { - c, actor, _ := getRPCClient(cmd) + c, actor := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) data, _ := cmd.Flags().GetString(nnsRecordDataFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/renew.go b/cmd/frostfs-adm/internal/modules/morph/nns/renew.go index b13092240e..80105ded2b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/renew.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/renew.go @@ -14,7 +14,7 @@ func initRenewCmd() { } func renewDomain(cmd *cobra.Command, _ []string) { - c, actor, _ := getRPCClient(cmd) + c, actor := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) h, vub, err := c.Renew(name) commonCmd.ExitOnErr(cmd, "unable to renew domain: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/update.go b/cmd/frostfs-adm/internal/modules/morph/nns/update.go index 3437316e36..dc8dcb3a38 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/update.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/update.go @@ -30,7 +30,7 @@ func initUpdateCmd() { } func updateSOA(cmd *cobra.Command, _ []string) { - c, actor, _ := getRPCClient(cmd) + c, actor := getRPCClient(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) email, _ := cmd.Flags().GetString(nnsEmailFlag) From 256f96e252f52b9dafd7b14d1608498d622df350 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 21 Nov 2024 10:54:14 +0300 Subject: [PATCH 1032/1413] [#1514] adm/nns: Rename getRPCClient() to nnsWriter() Make it more specific and similar to nnsReader(). Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/nns/domains.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/nns/helper.go | 2 +- cmd/frostfs-adm/internal/modules/morph/nns/record.go | 6 +++--- cmd/frostfs-adm/internal/modules/morph/nns/renew.go | 2 +- cmd/frostfs-adm/internal/modules/morph/nns/update.go | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/domains.go b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go index c111545955..1668bb327a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/domains.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go @@ -24,7 +24,7 @@ func initRegisterCmd() { } func registerDomain(cmd *cobra.Command, _ []string) { - c, actor := getRPCClient(cmd) + c, actor := nnsWriter(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) email, _ := cmd.Flags().GetString(nnsEmailFlag) @@ -53,7 +53,7 @@ func initDeleteCmd() { } func deleteDomain(cmd *cobra.Command, _ []string) { - c, actor := getRPCClient(cmd) + c, actor := nnsWriter(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) h, vub, err := c.DeleteDomain(name) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index 4b7ae46645..29b0a24ae0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -11,7 +11,7 @@ import ( "github.com/spf13/viper" ) -func getRPCClient(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { +func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { v := viper.GetViper() c, err := helper.GetN3Client(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/record.go b/cmd/frostfs-adm/internal/modules/morph/nns/record.go index cb6c5e0947..09ed92ab35 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/record.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/record.go @@ -59,7 +59,7 @@ func initDelRecordCmd() { } func addRecord(cmd *cobra.Command, _ []string) { - c, actor := getRPCClient(cmd) + c, actor := nnsWriter(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) data, _ := cmd.Flags().GetString(nnsRecordDataFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) @@ -112,7 +112,7 @@ func getRecords(cmd *cobra.Command, _ []string) { } func delRecords(cmd *cobra.Command, _ []string) { - c, actor := getRPCClient(cmd) + c, actor := nnsWriter(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) typ, err := getRecordType(recordType) @@ -127,7 +127,7 @@ func delRecords(cmd *cobra.Command, _ []string) { } func delRecord(cmd *cobra.Command, _ []string) { - c, actor := getRPCClient(cmd) + c, actor := nnsWriter(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) data, _ := cmd.Flags().GetString(nnsRecordDataFlag) recordType, _ := cmd.Flags().GetString(nnsRecordTypeFlag) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/renew.go b/cmd/frostfs-adm/internal/modules/morph/nns/renew.go index 80105ded2b..53bd943f0a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/renew.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/renew.go @@ -14,7 +14,7 @@ func initRenewCmd() { } func renewDomain(cmd *cobra.Command, _ []string) { - c, actor := getRPCClient(cmd) + c, actor := nnsWriter(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) h, vub, err := c.Renew(name) commonCmd.ExitOnErr(cmd, "unable to renew domain: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/update.go b/cmd/frostfs-adm/internal/modules/morph/nns/update.go index dc8dcb3a38..c6d77ead6a 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/update.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/update.go @@ -30,7 +30,7 @@ func initUpdateCmd() { } func updateSOA(cmd *cobra.Command, _ []string) { - c, actor := getRPCClient(cmd) + c, actor := nnsWriter(cmd) name, _ := cmd.Flags().GetString(nnsNameFlag) email, _ := cmd.Flags().GetString(nnsEmailFlag) From 99f9e59de974e1219ad78befd89331826f3712f3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 21 Nov 2024 11:52:50 +0300 Subject: [PATCH 1033/1413] [#1514] adm: Remove --alphabet-wallets flag from readonly commands Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/frostfsid/frostfsid.go | 8 -------- cmd/frostfs-adm/internal/modules/morph/netmap/root.go | 1 - 2 files changed, 9 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 091d6634ad..74da52a8f2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -61,7 +61,6 @@ var ( Use: "list-namespaces", Short: "List all namespaces in frostfsid", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidListNamespaces, @@ -91,7 +90,6 @@ var ( Use: "list-subjects", Short: "List subjects in namespace", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidListSubjects, @@ -121,7 +119,6 @@ var ( Use: "list-groups", Short: "List groups in namespace", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidListGroups, @@ -151,7 +148,6 @@ var ( Use: "list-group-subjects", Short: "List subjects in group", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) }, Run: frostfsidListGroupSubjects, @@ -169,7 +165,6 @@ func initFrostfsIDCreateNamespaceCmd() { func initFrostfsIDListNamespacesCmd() { Cmd.AddCommand(frostfsidListNamespacesCmd) frostfsidListNamespacesCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - frostfsidListNamespacesCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDCreateSubjectCmd() { @@ -193,7 +188,6 @@ func initFrostfsIDListSubjectsCmd() { frostfsidListSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") - frostfsidListSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDCreateGroupCmd() { @@ -217,7 +211,6 @@ func initFrostfsIDListGroupsCmd() { Cmd.AddCommand(frostfsidListGroupsCmd) frostfsidListGroupsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListGroupsCmd.Flags().String(namespaceFlag, "", "Namespace to list groups") - frostfsidListGroupsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initFrostfsIDAddSubjectToGroupCmd() { @@ -242,7 +235,6 @@ func initFrostfsIDListGroupSubjectsCmd() { frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") - frostfsidListGroupSubjectsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go index 55b7e64f02..291482e0f3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/root.go @@ -12,7 +12,6 @@ var ( Short: "List netmap candidates nodes", PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) - _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) }, Run: listNetmapCandidatesNodes, } From 1ed7ab75fbb62f293e17ecd6afc62b76c543206e Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 22 Nov 2024 15:19:51 +0300 Subject: [PATCH 1034/1413] [#1517] cli: Print the reason of ape manager error Signed-off-by: Airat Arifullin --- cmd/internal/common/exit.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/internal/common/exit.go b/cmd/internal/common/exit.go index 9e4fa30982..b8acf0143a 100644 --- a/cmd/internal/common/exit.go +++ b/cmd/internal/common/exit.go @@ -26,13 +26,15 @@ func ExitOnErr(cmd *cobra.Command, errFmt string, err error) { _ = iota internal aclDenied + apemanagerDenied ) var ( code int - internalErr = new(sdkstatus.ServerInternal) - accessErr = new(sdkstatus.ObjectAccessDenied) + internalErr = new(sdkstatus.ServerInternal) + accessErr = new(sdkstatus.ObjectAccessDenied) + apemanagerErr = new(sdkstatus.APEManagerAccessDenied) ) switch { @@ -41,6 +43,9 @@ func ExitOnErr(cmd *cobra.Command, errFmt string, err error) { case errors.As(err, &accessErr): code = aclDenied err = fmt.Errorf("%w: %s", err, accessErr.Reason()) + case errors.As(err, &apemanagerErr): + code = apemanagerDenied + err = fmt.Errorf("%w: %s", err, apemanagerErr.Reason()) default: code = internal } From 3ebd560f4225b96788ca12cc6662245486d54d88 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 22 Nov 2024 15:50:47 +0300 Subject: [PATCH 1035/1413] [#1519] cli: Make descriptive help for`--rule` option Signed-off-by: Airat Arifullin --- cmd/internal/common/ape/flags.go | 62 +++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/cmd/internal/common/ape/flags.go b/cmd/internal/common/ape/flags.go index c5e2a3a999..d8b2e88a21 100644 --- a/cmd/internal/common/ape/flags.go +++ b/cmd/internal/common/ape/flags.go @@ -2,7 +2,6 @@ package ape const ( RuleFlag = "rule" - RuleFlagDesc = "Rule statement" PathFlag = "path" PathFlagDesc = "Path to encoded chain in JSON or binary format" TargetNameFlag = "target-name" @@ -17,3 +16,64 @@ const ( ChainNameFlagDesc = "Chain name(ingress|s3)" AllFlag = "all" ) + +const RuleFlagDesc = `Defines an Access Policy Engine (APE) rule in the format: + [:status_detail] ... ... ... + +Status: + - allow Permits specified actions + - deny Prohibits specified actions + - deny:QuotaLimitReached Denies access due to quota limits + +Actions: + Object operations: + - Object.Put, Object.Get, etc. + - Object.* (all object operations) + Container operations: + - Container.Put, Container.Get, etc. + - Container.* (all container operations) + +Conditions: + ResourceCondition: + Format: ResourceCondition:"key"=value, "key"!=value + Reserved properties (use '\' before '$'): + - $Object:version + - $Object:objectID + - $Object:containerID + - $Object:ownerID + - $Object:creationEpoch + - $Object:payloadLength + - $Object:payloadHash + - $Object:objectType + - $Object:homomorphicHash + +RequestCondition: + Format: RequestCondition:"key"=value, "key"!=value + Reserved properties (use '\' before '$'): + - $Actor:publicKey + - $Actor:role + + Example: + ResourceCondition:"check_key"!="check_value" RequestCondition:"$Actor:role"=others + +Resources: + For objects: + - namespace/cid/oid (specific object) + - namespace/cid/* (all objects in container) + - namespace/* (all objects in namespace) + - * (all objects) + - /* (all objects in root namespace) + - /cid/* (all objects in root container) + - /cid/oid (specific object in root container) + + For containers: + - namespace/cid (specific container) + - namespace/* (all containers in namespace) + - * (all containers) + - /cid (root container) + - /* (all root containers) + +Notes: + - Cannot mix object and container operations in one rule + - Default behavior is Any=false unless 'any' is specified + - Use 'all' keyword to explicitly set Any=false` From 0e5524dac75b3e8a287ba0b820dc4f8fccdecfb4 Mon Sep 17 00:00:00 2001 From: George Bartolomey Date: Sat, 23 Nov 2024 15:08:50 +0300 Subject: [PATCH 1036/1413] [#1515] adm: Print address in base58 format in morph ape get-admin Signed-off-by: George Bartolomey --- cmd/frostfs-adm/internal/modules/morph/ape/ape.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go index 8fcd4a441c..1960faab45 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape.go @@ -8,7 +8,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" apeCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/ape" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" - "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -200,7 +200,7 @@ func listRuleChains(cmd *cobra.Command, _ []string) { func setAdmin(cmd *cobra.Command, _ []string) { s, _ := cmd.Flags().GetString(addrAdminFlag) - addr, err := util.Uint160DecodeStringLE(s) + addr, err := address.StringToUint160(s) commonCmd.ExitOnErr(cmd, "can't decode admin addr: %w", err) pci, ac := newPolicyContractInterface(cmd) h, vub, err := pci.SetAdmin(addr) @@ -214,7 +214,7 @@ func getAdmin(cmd *cobra.Command, _ []string) { pci, _ := newPolicyContractReaderInterface(cmd) addr, err := pci.GetAdmin() commonCmd.ExitOnErr(cmd, "unable to get admin: %w", err) - cmd.Println(addr.StringLE()) + cmd.Println(address.Uint160ToString(addr)) } func listTargets(cmd *cobra.Command, _ []string) { From 7eac5fb18bd1d234b65a311bacdf1326d256e283 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 25 Nov 2024 13:55:14 +0300 Subject: [PATCH 1037/1413] Release v0.44.0 Signed-off-by: Evgenii Stratonikov --- CHANGELOG.md | 24 ++++++++++++++++++++++++ VERSION | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4ba6a5d60..92c84ab167 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,30 @@ Changelog for FrostFS Node ### Removed ### Updated +## [v0.44.0] - 2024-25-11 - Rongbuk + +### Added +- Allow to prioritize nodes during GET traversal via attributes (#1439) +- Add metrics for the frostfsid cache (#1464) +- Customize constant attributes attached to every tracing span (#1488) +- Manage additional keys in the `frostfsid` contract (#1505) +- Describe `--rule` flag in detail for `frostfs-cli ape-manager` subcommands (#1519) + +### Changed +- Support richer interaction with the console in `frostfs-cli container policy-playground` (#1396) +- Print address in base58 format in `frostfs-adm morph policy set-admin` (#1515) + +### Fixed +- Fix EC object search (#1408) +- Fix EC object put when one of the nodes is unavailable (#1427) + +### Removed +- Drop most of the eACL-related code (#1425) +- Remove `--basic-acl` flag from `frostfs-cli container create` (#1483) + +### Upgrading from v0.43.0 +The metabase schema has changed completely, resync is required. + ## [v0.42.0] ### Added diff --git a/VERSION b/VERSION index 01efe7f3aa..9052dab968 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.42.0 +v0.44.0 From caa4253249a5713d201d262939343a28df70a620 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 09:59:43 +0300 Subject: [PATCH 1038/1413] [#1522] adm: Remove unnecessary variable declaration It is better to have small scope. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 6780e6dd34..0d28383a27 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -57,12 +57,11 @@ func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorag commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) inv := invoker.New(c, nil) - var ch util.Uint160 r := management.NewReader(inv) nnsCs, err := helper.GetContractByID(r, 1) commonCmd.ExitOnErr(cmd, "can't get NNS contract state: %w", err) - ch, err = helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) + ch, err := helper.NNSResolveHash(inv, nnsCs.Hash, helper.DomainOf(constants.PolicyContract)) commonCmd.ExitOnErr(cmd, "unable to resolve policy contract hash: %w", err) invokerAdapter := &invokerAdapter{ From b1766e47c766ed2591e8f8a6b97dbfc13ad6976c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 10:12:54 +0300 Subject: [PATCH 1039/1413] [#1522] adm/helper: Remove unused GetCommittee() method from the Client interface Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/local_client.go | 5 ----- cmd/frostfs-adm/internal/modules/morph/helper/n3client.go | 2 -- 2 files changed, 7 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index ed028fb7c9..17bee78585 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -128,11 +128,6 @@ func (l *LocalClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*resul return &a, nil } -func (l *LocalClient) GetCommittee() (keys.PublicKeys, error) { - // not used by `morph init` command - panic("unexpected call") -} - // InvokeFunction is implemented via `InvokeScript`. func (l *LocalClient) InvokeFunction(h util.Uint160, method string, sPrm []smartcontract.Parameter, ss []transaction.Signer) (*result.Invoke, error) { var err error diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index e62a21b3f8..5563b1fd99 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -10,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" @@ -32,7 +31,6 @@ type Client interface { GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error) GetVersion() (*result.Version, error) SendRawTransaction(*transaction.Transaction) (util.Uint256, error) - GetCommittee() (keys.PublicKeys, error) CalculateNetworkFee(tx *transaction.Transaction) (int64, error) } From 16053916286fd9cc3e7badc068514cb4d267c03f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 10:14:00 +0300 Subject: [PATCH 1040/1413] [#1522] adm/helper: Simplify Client interface Just reuse `actor.RPCActor`. No functional changes. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/helper/n3client.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index 5563b1fd99..066ce01fc6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -24,14 +24,10 @@ import ( // Client represents N3 client interface capable of test-invoking scripts // and sending signed transactions to chain. type Client interface { - invoker.RPCInvoke + actor.RPCActor - GetBlockCount() (uint32, error) GetNativeContracts() ([]state.Contract, error) GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error) - GetVersion() (*result.Version, error) - SendRawTransaction(*transaction.Transaction) (util.Uint256, error) - CalculateNetworkFee(tx *transaction.Transaction) (int64, error) } type HashVUBPair struct { From b10c9543772b9ac4b00abf06a28b9da62f0ef022 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 10:22:54 +0300 Subject: [PATCH 1041/1413] [#1522] adm: Split NewLocalClient() into functions No functional changes. Signed-off-by: Evgenii Stratonikov --- .../modules/morph/helper/local_client.go | 87 +++++++++++-------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index 17bee78585..34ce5938a5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -58,17 +58,59 @@ func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet return nil, err } - m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ProtocolConfiguration.ValidatorsCount)) - accounts := make([]*wallet.Account, len(wallets)) - for i := range accounts { - accounts[i], err = GetWalletAccount(wallets[i], constants.ConsensusAccountName) - if err != nil { - return nil, err + go bc.Run() + + accounts, err := getBlockSigningAccounts(cfg.ProtocolConfiguration, wallets) + if err != nil { + return nil, err + } + + if cmd.Name() != "init" { + if err := restoreDump(bc, dumpPath); err != nil { + return nil, fmt.Errorf("restore dump: %w", err) } } + return &LocalClient{ + bc: bc, + dumpPath: dumpPath, + accounts: accounts, + }, nil +} + +func restoreDump(bc *core.Blockchain, dumpPath string) error { + f, err := os.OpenFile(dumpPath, os.O_RDONLY, 0o600) + if err != nil { + return fmt.Errorf("can't open local dump: %w", err) + } + defer f.Close() + + r := io.NewBinReaderFromIO(f) + + var skip uint32 + if bc.BlockHeight() != 0 { + skip = bc.BlockHeight() + 1 + } + + count := r.ReadU32LE() - skip + if err := chaindump.Restore(bc, r, skip, count, nil); err != nil { + return err + } + return nil +} + +func getBlockSigningAccounts(cfg config.ProtocolConfiguration, wallets []*wallet.Wallet) ([]*wallet.Account, error) { + accounts := make([]*wallet.Account, len(wallets)) + for i := range accounts { + acc, err := GetWalletAccount(wallets[i], constants.ConsensusAccountName) + if err != nil { + return nil, err + } + accounts[i] = acc + } + indexMap := make(map[string]int) - for i, pub := range cfg.ProtocolConfiguration.StandbyCommittee { + for i, pub := range cfg.StandbyCommittee { indexMap[pub] = i } @@ -77,37 +119,12 @@ func NewLocalClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet pj := accounts[j].PrivateKey().PublicKey().Bytes() return indexMap[string(pi)] < indexMap[string(pj)] }) - sort.Slice(accounts[:cfg.ProtocolConfiguration.ValidatorsCount], func(i, j int) bool { + sort.Slice(accounts[:cfg.ValidatorsCount], func(i, j int) bool { return accounts[i].PublicKey().Cmp(accounts[j].PublicKey()) == -1 }) - go bc.Run() - - if cmd.Name() != "init" { - f, err := os.OpenFile(dumpPath, os.O_RDONLY, 0o600) - if err != nil { - return nil, fmt.Errorf("can't open local dump: %w", err) - } - defer f.Close() - - r := io.NewBinReaderFromIO(f) - - var skip uint32 - if bc.BlockHeight() != 0 { - skip = bc.BlockHeight() + 1 - } - - count := r.ReadU32LE() - skip - if err := chaindump.Restore(bc, r, skip, count, nil); err != nil { - return nil, fmt.Errorf("can't restore local dump: %w", err) - } - } - - return &LocalClient{ - bc: bc, - dumpPath: dumpPath, - accounts: accounts[:m], - }, nil + m := smartcontract.GetDefaultHonestNodeCount(int(cfg.ValidatorsCount)) + return accounts[:m], nil } func (l *LocalClient) GetBlockCount() (uint32, error) { From 61ee1b56103bd77ea3318f23dceebb1928b846a3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 10:33:24 +0300 Subject: [PATCH 1042/1413] [#1522] adm: Simplify LocalClient.SendRawTransaction() The old code was there before Copy() method was introduced. It was also supposed to check errors, however, they are already checked server-side. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/local_client.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index 34ce5938a5..d0a05d5c74 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -308,13 +308,7 @@ func (l *LocalClient) InvokeScript(script []byte, signers []transaction.Signer) } func (l *LocalClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) { - // We need to test that transaction was formed correctly to catch as many errors as we can. - bs := tx.Bytes() - _, err := transaction.NewTransactionFromBytes(bs) - if err != nil { - return tx.Hash(), fmt.Errorf("invalid transaction: %w", err) - } - + tx = tx.Copy() l.transactions = append(l.transactions, tx) return tx.Hash(), nil } From 49959c4166d92cd46df04d352c7928f92fbf1aa9 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 10:45:47 +0300 Subject: [PATCH 1043/1413] [#1522] adm/helper: Unexport GetFrostfsIDAdmin() It is used in `helper` package only, besides unit-tests. Move unit-tests to the same package, where they belong. Signed-off-by: Evgenii Stratonikov --- .../morph/frostfsid/frostfsid_util_test.go | 47 ---------------- .../internal/modules/morph/helper/contract.go | 2 +- .../modules/morph/helper/frostfsid.go | 2 +- .../modules/morph/helper/frostfsid_test.go | 53 +++++++++++++++++++ 4 files changed, 55 insertions(+), 49 deletions(-) create mode 100644 cmd/frostfs-adm/internal/modules/morph/helper/frostfsid_test.go diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go index cce859d2fd..1d0bc84411 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid_util_test.go @@ -1,59 +1,12 @@ package frostfsid import ( - "encoding/hex" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/spf13/viper" "github.com/stretchr/testify/require" ) -func TestFrostfsIDConfig(t *testing.T) { - pks := make([]*keys.PrivateKey, 4) - for i := range pks { - pk, err := keys.NewPrivateKey() - require.NoError(t, err) - pks[i] = pk - } - - fmts := []string{ - pks[0].GetScriptHash().StringLE(), - address.Uint160ToString(pks[1].GetScriptHash()), - hex.EncodeToString(pks[2].PublicKey().UncompressedBytes()), - hex.EncodeToString(pks[3].PublicKey().Bytes()), - } - - for i := range fmts { - v := viper.New() - v.Set("frostfsid.admin", fmts[i]) - - actual, found, err := helper.GetFrostfsIDAdmin(v) - require.NoError(t, err) - require.True(t, found) - require.Equal(t, pks[i].GetScriptHash(), actual) - } - - t.Run("bad key", func(t *testing.T) { - v := viper.New() - v.Set("frostfsid.admin", "abc") - - _, found, err := helper.GetFrostfsIDAdmin(v) - require.Error(t, err) - require.True(t, found) - }) - t.Run("missing key", func(t *testing.T) { - v := viper.New() - - _, found, err := helper.GetFrostfsIDAdmin(v) - require.NoError(t, err) - require.False(t, found) - }) -} - func TestNamespaceRegexp(t *testing.T) { for _, tc := range []struct { name string diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/contract.go b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go index eea3b040e6..64d1c63931 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/contract.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/contract.go @@ -82,7 +82,7 @@ func GetContractDeployData(c *InitializeContext, ctrName string, keysParam []any h, found, err = getFrostfsIDAdminFromContract(c.ReadOnlyInvoker) } if method != constants.UpdateMethodName || err == nil && !found { - h, found, err = GetFrostfsIDAdmin(viper.GetViper()) + h, found, err = getFrostfsIDAdmin(viper.GetViper()) } if err != nil { return nil, err diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid.go index f29042b828..fce2dfb741 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid.go @@ -11,7 +11,7 @@ import ( const frostfsIDAdminConfigKey = "frostfsid.admin" -func GetFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { +func getFrostfsIDAdmin(v *viper.Viper) (util.Uint160, bool, error) { admin := v.GetString(frostfsIDAdminConfigKey) if admin == "" { return util.Uint160{}, false, nil diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid_test.go b/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid_test.go new file mode 100644 index 0000000000..38991e9629 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/helper/frostfsid_test.go @@ -0,0 +1,53 @@ +package helper + +import ( + "encoding/hex" + "testing" + + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/spf13/viper" + "github.com/stretchr/testify/require" +) + +func TestFrostfsIDConfig(t *testing.T) { + pks := make([]*keys.PrivateKey, 4) + for i := range pks { + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + pks[i] = pk + } + + fmts := []string{ + pks[0].GetScriptHash().StringLE(), + address.Uint160ToString(pks[1].GetScriptHash()), + hex.EncodeToString(pks[2].PublicKey().UncompressedBytes()), + hex.EncodeToString(pks[3].PublicKey().Bytes()), + } + + for i := range fmts { + v := viper.New() + v.Set("frostfsid.admin", fmts[i]) + + actual, found, err := getFrostfsIDAdmin(v) + require.NoError(t, err) + require.True(t, found) + require.Equal(t, pks[i].GetScriptHash(), actual) + } + + t.Run("bad key", func(t *testing.T) { + v := viper.New() + v.Set("frostfsid.admin", "abc") + + _, found, err := getFrostfsIDAdmin(v) + require.Error(t, err) + require.True(t, found) + }) + t.Run("missing key", func(t *testing.T) { + v := viper.New() + + _, found, err := getFrostfsIDAdmin(v) + require.NoError(t, err) + require.False(t, found) + }) +} From a6ef4ab52437802432d0ce022d42ad7fbafd844b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 10:53:09 +0300 Subject: [PATCH 1044/1413] [#1522] adm/helper: Rename GetN3Client() -> NewRemoteClient() Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/balance/balance.go | 2 +- cmd/frostfs-adm/internal/modules/morph/config/config.go | 2 +- cmd/frostfs-adm/internal/modules/morph/container/container.go | 4 ++-- .../internal/modules/morph/contract/dump_hashes.go | 2 +- cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go | 2 +- .../internal/modules/morph/helper/initialize_ctx.go | 2 +- cmd/frostfs-adm/internal/modules/morph/helper/n3client.go | 2 +- .../internal/modules/morph/netmap/netmap_candidates.go | 2 +- cmd/frostfs-adm/internal/modules/morph/nns/helper.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/notary/notary.go | 2 +- cmd/frostfs-adm/internal/modules/morph/policy/policy.go | 2 +- 12 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 0d28383a27..9146826476 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -53,7 +53,7 @@ func (n *invokerAdapter) GetRPCInvoker() invoker.RPCInvoke { } func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorageReader, *invoker.Invoker) { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) inv := invoker.New(c, nil) @@ -73,7 +73,7 @@ func newPolicyContractReaderInterface(cmd *cobra.Command) (*morph.ContractStorag } func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *helper.LocalActor) { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) ac, err := helper.NewLocalActor(cmd, c, constants.ConsensusAccountName) diff --git a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go index 5519705d46..be42f2aa5f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go @@ -51,7 +51,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error { nmHash util.Uint160 ) - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index 3a7f84acb9..65ccc9f9f9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -26,7 +26,7 @@ import ( const forceConfigSet = "force" func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index 6f08d1655a..e72dc15e9c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -76,7 +76,7 @@ func dumpContainers(cmd *cobra.Command, _ []string) error { return fmt.Errorf("invalid filename: %w", err) } - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } @@ -157,7 +157,7 @@ func dumpSingleContainer(bw *io.BufBinWriter, ch util.Uint160, inv *invoker.Invo } func listContainers(cmd *cobra.Command, _ []string) error { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index be2134b775..437e2480dd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -36,7 +36,7 @@ type contractDumpInfo struct { } func dumpContractHashes(cmd *cobra.Command, _ []string) error { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) if err != nil { return fmt.Errorf("can't create N3 client: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 74da52a8f2..c3a232710b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -514,7 +514,7 @@ func readIterator(inv *invoker.Invoker, iter *result.Iterator, batchSize int, se } func initInvoker(cmd *cobra.Command) (*invoker.Invoker, *state.Contract, util.Uint160) { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err) inv := invoker.New(c, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go index b5b6adf05c..335ec5ac93 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go @@ -191,7 +191,7 @@ func createClient(cmd *cobra.Command, v *viper.Viper, wallets []*wallet.Wallet) } c, err = NewLocalClient(cmd, v, wallets, ldf.Value.String()) } else { - c, err = GetN3Client(v) + c, err = NewRemoteClient(v) } if err != nil { return nil, fmt.Errorf("can't create N3 client: %w", err) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index 066ce01fc6..25160305d7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -42,7 +42,7 @@ type ClientContext struct { SentTxs []HashVUBPair } -func GetN3Client(v *viper.Viper) (Client, error) { +func NewRemoteClient(v *viper.Viper) (Client, error) { // number of opened connections // by neo-go client per one host const ( diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go index d8471bb9aa..a689e0ec12 100644 --- a/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go +++ b/cmd/frostfs-adm/internal/modules/morph/netmap/netmap_candidates.go @@ -13,7 +13,7 @@ import ( ) func listNetmapCandidatesNodes(cmd *cobra.Command, _ []string) { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client: %w", err) inv := invoker.New(c, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index 29b0a24ae0..b13cbc8a15 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -13,7 +13,7 @@ import ( func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { v := viper.GetViper() - c, err := helper.GetN3Client(v) + c, err := helper.NewRemoteClient(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) ac, err := helper.NewLocalActor(cmd, c, constants.CommitteeAccountName) @@ -26,7 +26,7 @@ func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { } func nnsReader(cmd *cobra.Command) (*client.ContractReader, *invoker.Invoker) { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) inv := invoker.New(c, nil) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go index 9b213da4e9..fd42d5a4a9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go @@ -89,7 +89,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error { } func transferGas(cmd *cobra.Command, acc *wallet.Account, accHash util.Uint160, gasAmount fixedn.Fixed8, till int64) error { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go index 36547e22c0..686a244f0e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go @@ -62,7 +62,7 @@ func SetPolicyCmd(cmd *cobra.Command, args []string) error { } func dumpPolicyCmd(cmd *cobra.Command, _ []string) error { - c, err := helper.GetN3Client(viper.GetViper()) + c, err := helper.NewRemoteClient(viper.GetViper()) commonCmd.ExitOnErr(cmd, "can't create N3 client:", err) inv := invoker.New(c, nil) From 2469e0c6831604b70e11b4418b42ddf8f1fc2593 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 10:55:51 +0300 Subject: [PATCH 1045/1413] [#1522] adm/helper: Remove NewActor() helper It is used once, it is used only internally and it is single-statement. I see no justification in having it as a separate function. It introduces confusion, because we also have NewLocalActor(). Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/n3client.go | 8 +++++++- .../internal/modules/morph/helper/util.go | 12 ------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index 25160305d7..03009ebe3f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -83,7 +83,13 @@ func NewRemoteClient(v *viper.Viper) (Client, error) { } func DefaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) { - commAct, err := NewActor(c, committeeAcc) + commAct, err := actor.New(c, []actor.SignerAccount{{ + Signer: transaction.Signer{ + Account: committeeAcc.Contract.ScriptHash(), + Scopes: transaction.Global, + }, + Account: committeeAcc, + }}) if err != nil { return nil, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/util.go b/cmd/frostfs-adm/internal/modules/morph/helper/util.go index 8c6b905394..c26aa447b3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/util.go @@ -15,10 +15,8 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/viper" @@ -87,16 +85,6 @@ func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, er return wallets, nil } -func NewActor(c actor.RPCActor, committeeAcc *wallet.Account) (*actor.Actor, error) { - return actor.New(c, []actor.SignerAccount{{ - Signer: transaction.Signer{ - Account: committeeAcc.Contract.ScriptHash(), - Scopes: transaction.Global, - }, - Account: committeeAcc, - }}) -} - func ReadContract(ctrPath, ctrName string) (*ContractState, error) { rawNef, err := os.ReadFile(filepath.Join(ctrPath, ctrName+"_contract.nef")) if err != nil { From 9e275d44c8bb9c32134c4dabeb2757580da7ea75 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 13:11:43 +0300 Subject: [PATCH 1046/1413] [#1522] adm/helper: Unexport DefaultClientContext() Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go | 2 +- cmd/frostfs-adm/internal/modules/morph/helper/n3client.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go index 335ec5ac93..08a87b999c 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go @@ -139,7 +139,7 @@ func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContex return nil, err } - cliCtx, err := DefaultClientContext(c, committeeAcc) + cliCtx, err := defaultClientContext(c, committeeAcc) if err != nil { return nil, fmt.Errorf("client context: %w", err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index 03009ebe3f..3f3a66cb68 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -82,7 +82,7 @@ func NewRemoteClient(v *viper.Viper) (Client, error) { return c, nil } -func DefaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) { +func defaultClientContext(c Client, committeeAcc *wallet.Account) (*ClientContext, error) { commAct, err := actor.New(c, []actor.SignerAccount{{ Signer: transaction.Signer{ Account: committeeAcc.Contract.ScriptHash(), From 11703707533e085d37cd7d77be41801da5def702 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 13:14:02 +0300 Subject: [PATCH 1047/1413] [#1522] adm/helper: Rename createSingleAccounts() -> getSingleAccounts() It doesn't create any accounts, purely finds them in the wallet. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/initialize_ctx.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go index 08a87b999c..8e5615baa6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go @@ -134,7 +134,7 @@ func NewInitializeContext(cmd *cobra.Command, v *viper.Viper) (*InitializeContex return nil, err } - accounts, err := createWalletAccounts(wallets) + accounts, err := getSingleAccounts(wallets) if err != nil { return nil, err } @@ -211,7 +211,7 @@ func getContractsPath(cmd *cobra.Command, needContracts bool) (string, error) { return ctrPath, nil } -func createWalletAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { +func getSingleAccounts(wallets []*wallet.Wallet) ([]*wallet.Account, error) { accounts := make([]*wallet.Account, len(wallets)) for i, w := range wallets { acc, err := GetWalletAccount(w, constants.SingleAccountName) From aac65001e524b789c6e8f1d55c70bca6f47293d1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 22 Nov 2024 13:19:58 +0300 Subject: [PATCH 1048/1413] [#1522] adm/frostfsid: Remove unreachable condition SendConsensusTx() modifies SendTxs field, if it is not the case, there is a bug in code. Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/frostfsid/frostfsid.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index c3a232710b..db98bb8ad4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -1,7 +1,6 @@ package frostfsid import ( - "errors" "fmt" "math/big" "sort" @@ -489,10 +488,6 @@ func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) { } f.bw.Reset() - if len(f.wCtx.SentTxs) == 0 { - return nil, errors.New("no transactions to wait") - } - f.wCtx.Command.Println("Waiting for transactions to persist...") return f.roCli.Wait(f.wCtx.SentTxs[0].Hash, f.wCtx.SentTxs[0].Vub, nil) } From 01acec708fa8f0c536ebc79e8f03ee2420ef3731 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 28 Nov 2024 09:15:29 +0300 Subject: [PATCH 1049/1413] [#1525] pilorama: Use AppendUint* helpers from stdlib gopatch: ``` @@ var slice, e expression @@ +import "encoding/binary" -append(slice, byte(e), byte(e >> 8)) +binary.LittleEndian.AppendUint16(slice, e) ``` Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/boltdb.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index c62d728b1f..6e68e9986a 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1240,7 +1240,7 @@ func (t *boltForest) fillSortedChildren(b *bbolt.Bucket, nodeIDs MultiNode, h *f nodes = nil length = actualLength + 1 count = 0 - c.Seek(append(prefix, byte(length), byte(length>>8))) + c.Seek(binary.LittleEndian.AppendUint16(prefix, length)) c.Prev() // c.Next() will be performed by for loop } } @@ -1664,7 +1664,7 @@ func internalKeyPrefix(key []byte, k string) []byte { key = append(key, 'i') l := len(k) - key = append(key, byte(l), byte(l>>8)) + key = binary.LittleEndian.AppendUint16(key, uint16(l)) key = append(key, k...) return key } @@ -1679,14 +1679,10 @@ func internalKey(key []byte, k, v string, parent, node Node) []byte { key = internalKeyPrefix(key, k) l := len(v) - key = append(key, byte(l), byte(l>>8)) + key = binary.LittleEndian.AppendUint16(key, uint16(l)) key = append(key, v...) - var raw [8]byte - binary.LittleEndian.PutUint64(raw[:], parent) - key = append(key, raw[:]...) - - binary.LittleEndian.PutUint64(raw[:], node) - key = append(key, raw[:]...) + key = binary.LittleEndian.AppendUint64(key, parent) + key = binary.LittleEndian.AppendUint64(key, node) return key } From bba1892fa13d0c8aa904dc6b6e992a6407f57b64 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 27 Nov 2024 15:48:16 +0300 Subject: [PATCH 1050/1413] [#1524] ape: Make APE checker return error without status Signed-off-by: Airat Arifullin --- pkg/services/common/ape/checker.go | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index eb4fd03c73..30580da122 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -11,7 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" @@ -104,14 +103,7 @@ func (c *checkerCoreImpl) CheckAPE(prm CheckPrm) error { if found && status == apechain.Allow { return nil } - err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", prm.Request.Operation(), status.String()) - return apeErr(err) -} - -func apeErr(err error) error { - errAccessDenied := &apistatus.ObjectAccessDenied{} - errAccessDenied.WriteReason(err.Error()) - return errAccessDenied + return fmt.Errorf("access to operation %s is denied by access policy engine: %s", prm.Request.Operation(), status.String()) } // isValidBearer checks whether bearer token was correctly signed by authorized From 00c608c05e3c6574b5258f9c63b5ed8bfca264a7 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 27 Nov 2024 15:52:23 +0300 Subject: [PATCH 1051/1413] [#1524] tree: Make check APE error get wrapped to api status Signed-off-by: Airat Arifullin --- pkg/services/tree/signature.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 4fd4a7e1e2..80f5b35905 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -11,6 +11,7 @@ import ( core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" @@ -62,7 +63,16 @@ func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, return fmt.Errorf("can't get request role: %w", err) } - return s.checkAPE(ctx, bt, cnr, cid, op, role, pubKey) + if err = s.checkAPE(ctx, bt, cnr, cid, op, role, pubKey); err != nil { + return apeErr(err) + } + return nil +} + +func apeErr(err error) error { + errAccessDenied := &apistatus.ObjectAccessDenied{} + errAccessDenied.WriteReason(err.Error()) + return errAccessDenied } // Returns true iff the operation is read-only and request was signed From e0ac3a583f9207684d0cbfa12ecd59f5c4b83642 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 28 Nov 2024 10:41:59 +0300 Subject: [PATCH 1052/1413] [#1523] metabase: Remove `(*DB).IterateCoveredByTombstones` Remove this method because it isn't used anywhere since 7799f8e4c. Signed-off-by: Aleksey Savchuk --- .../metabase/iterators.go | 65 ------------------- .../metabase/iterators_test.go | 63 ------------------ 2 files changed, 128 deletions(-) diff --git a/pkg/local_object_storage/metabase/iterators.go b/pkg/local_object_storage/metabase/iterators.go index 5d42e41250..0d438e1023 100644 --- a/pkg/local_object_storage/metabase/iterators.go +++ b/pkg/local_object_storage/metabase/iterators.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "errors" - "fmt" "strconv" "time" @@ -111,70 +110,6 @@ func (db *DB) iterateExpired(tx *bbolt.Tx, epoch uint64, h ExpiredObjectHandler) return nil } -// IterateCoveredByTombstones iterates over all objects in DB which are covered -// by tombstone with string address from tss. Locked objects are not included -// (do not confuse with objects of type LOCK). -// -// If h returns ErrInterruptIterator, nil returns immediately. -// Returns other errors of h directly. -// -// Does not modify tss. -func (db *DB) IterateCoveredByTombstones(ctx context.Context, tss map[string]oid.Address, h func(oid.Address) error) error { - var ( - startedAt = time.Now() - success = false - ) - defer func() { - db.metrics.AddMethodDuration("IterateCoveredByTombstones", time.Since(startedAt), success) - }() - _, span := tracing.StartSpanFromContext(ctx, "metabase.IterateCoveredByTombstones") - defer span.End() - - db.modeMtx.RLock() - defer db.modeMtx.RUnlock() - - if db.mode.NoMetabase() { - return ErrDegradedMode - } - - return db.boltDB.View(func(tx *bbolt.Tx) error { - return db.iterateCoveredByTombstones(tx, tss, h) - }) -} - -func (db *DB) iterateCoveredByTombstones(tx *bbolt.Tx, tss map[string]oid.Address, h func(oid.Address) error) error { - bktGraveyard := tx.Bucket(graveyardBucketName) - - err := bktGraveyard.ForEach(func(k, v []byte) error { - var addr oid.Address - if err := decodeAddressFromKey(&addr, v); err != nil { - return err - } - if _, ok := tss[addr.EncodeToString()]; ok { - var addr oid.Address - - err := decodeAddressFromKey(&addr, k) - if err != nil { - return fmt.Errorf("could not parse address of the object under tombstone: %w", err) - } - - if objectLocked(tx, addr.Container(), addr.Object()) { - return nil - } - - return h(addr) - } - - return nil - }) - - if errors.Is(err, ErrInterruptIterator) { - err = nil - } - - return err -} - func iteratePhyObjects(tx *bbolt.Tx, f func(cid.ID, oid.ID, *objectSDK.Object) error) error { var cid cid.ID var oid oid.ID diff --git a/pkg/local_object_storage/metabase/iterators_test.go b/pkg/local_object_storage/metabase/iterators_test.go index 7eed32c55f..4c9579965e 100644 --- a/pkg/local_object_storage/metabase/iterators_test.go +++ b/pkg/local_object_storage/metabase/iterators_test.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" @@ -67,65 +66,3 @@ func putWithExpiration(t *testing.T, db *meta.DB, typ objectSDK.Type, expiresAt return object2.AddressOf(obj) } - -func TestDB_IterateCoveredByTombstones(t *testing.T) { - db := newDB(t) - defer func() { require.NoError(t, db.Close(context.Background())) }() - - cnr := cidtest.ID() - ts := oidtest.Address() - protected1 := oidtest.Address() - protected2 := oidtest.Address() - protectedLocked := oidtest.Address() - garbage := oidtest.Address() - ts.SetContainer(cnr) - protected1.SetContainer(cnr) - protected2.SetContainer(cnr) - protectedLocked.SetContainer(cnr) - - var prm meta.InhumePrm - var err error - - prm.SetAddresses(protected1, protected2, protectedLocked) - prm.SetTombstoneAddress(ts) - - _, err = db.Inhume(context.Background(), prm) - require.NoError(t, err) - - prm.SetAddresses(garbage) - prm.SetGCMark() - - _, err = db.Inhume(context.Background(), prm) - require.NoError(t, err) - - var handled []oid.Address - - tss := map[string]oid.Address{ - ts.EncodeToString(): ts, - } - - err = db.IterateCoveredByTombstones(context.Background(), tss, func(addr oid.Address) error { - handled = append(handled, addr) - return nil - }) - require.NoError(t, err) - - require.Len(t, handled, 3) - require.Contains(t, handled, protected1) - require.Contains(t, handled, protected2) - require.Contains(t, handled, protectedLocked) - - err = db.Lock(context.Background(), protectedLocked.Container(), oidtest.ID(), []oid.ID{protectedLocked.Object()}) - require.NoError(t, err) - - handled = handled[:0] - - err = db.IterateCoveredByTombstones(context.Background(), tss, func(addr oid.Address) error { - handled = append(handled, addr) - return nil - }) - require.NoError(t, err) - - require.Len(t, handled, 2) - require.NotContains(t, handled, protectedLocked) -} From edfa3f4825ecefd40f9dbda0dfa0356c062a4fa7 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 2 Dec 2024 13:31:32 +0300 Subject: [PATCH 1053/1413] [#1528] node: Keep order for equal elements when sort priority metrics Signed-off-by: Anton Nikiforov --- pkg/services/object_manager/placement/traverser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 7c720b204a..6a949e9388 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -202,7 +202,7 @@ func sortVector(cfg *cfg, unsortedVector []netmap.NodeInfo) ([]netmap.NodeInfo, metrics: m, } } - slices.SortFunc(nm, func(a, b nodeMetrics) int { + slices.SortStableFunc(nm, func(a, b nodeMetrics) int { return slices.Compare(a.metrics, b.metrics) }) sortedVector := make([]netmap.NodeInfo, len(unsortedVector)) From 635a292ae49a9e6bfdb82575cd8c1421c03c4e37 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 2 Dec 2024 13:35:59 +0300 Subject: [PATCH 1054/1413] [#1528] cli: Keep order for required nodes in the result of `object nodes` Signed-off-by: Anton Nikiforov --- cmd/frostfs-cli/modules/object/nodes.go | 32 ------------------------- 1 file changed, 32 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index e6918dfc92..31682c0e18 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -1,15 +1,12 @@ package object import ( - "bytes" - "cmp" "context" "crypto/ecdsa" "encoding/hex" "encoding/json" "errors" "fmt" - "slices" "sync" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" @@ -507,7 +504,6 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID, } func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) { - normilizeObjectNodesResult(objects, result) if json, _ := cmd.Flags().GetBool(commonflags.JSON); json { printObjectNodesAsJSON(cmd, objID, objects, result) } else { @@ -515,34 +511,6 @@ func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, resul } } -func normilizeObjectNodesResult(objects []phyObject, result *objectNodesResult) { - slices.SortFunc(objects, func(lhs, rhs phyObject) int { - if lhs.ecHeader == nil && rhs.ecHeader == nil { - return bytes.Compare(lhs.objectID[:], rhs.objectID[:]) - } - if lhs.ecHeader == nil { - return -1 - } - if rhs.ecHeader == nil { - return 1 - } - if lhs.ecHeader.parent == rhs.ecHeader.parent { - return cmp.Compare(lhs.ecHeader.index, rhs.ecHeader.index) - } - return bytes.Compare(lhs.ecHeader.parent[:], rhs.ecHeader.parent[:]) - }) - for _, obj := range objects { - op := result.placements[obj.objectID] - slices.SortFunc(op.confirmedNodes, func(lhs, rhs netmapSDK.NodeInfo) int { - return bytes.Compare(lhs.PublicKey(), rhs.PublicKey()) - }) - slices.SortFunc(op.requiredNodes, func(lhs, rhs netmapSDK.NodeInfo) int { - return bytes.Compare(lhs.PublicKey(), rhs.PublicKey()) - }) - result.placements[obj.objectID] = op - } -} - func printObjectNodesAsText(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) { fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects:\n", objID.EncodeToString(), len(objects)) From 60feed3b5f71f58e8694873721cb1c115bcf6bfd Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 2 Dec 2024 15:37:25 +0300 Subject: [PATCH 1055/1413] [#1527] engine/test: Allow to specify current epoch in `epochState` Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/engine_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index a7cb90bae6..9a3eaadc0d 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -17,10 +17,12 @@ import ( "github.com/stretchr/testify/require" ) -type epochState struct{} +type epochState struct { + currEpoch uint64 +} func (s epochState) CurrentEpoch() uint64 { - return 0 + return s.currEpoch } type testEngineWrapper struct { From 9cabca9dfe73999b4b68f19ef9422d1fafc0b23a Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 2 Dec 2024 16:12:12 +0300 Subject: [PATCH 1056/1413] [#1527] engine/test: Move default metabase options to separate function Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/engine_test.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 9a3eaadc0d..926ff43f3c 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -89,12 +89,16 @@ func testGetDefaultShardOptions(t testing.TB) []shard.Option { blobstor.WithLogger(test.NewLogger(t)), ), shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), - shard.WithMetaBaseOptions( - meta.WithPath(filepath.Join(t.TempDir(), "metabase")), - meta.WithPermissions(0o700), - meta.WithEpochState(epochState{}), - meta.WithLogger(test.NewLogger(t)), - ), + shard.WithMetaBaseOptions(testGetDefaultMetabaseOptions(t)...), + } +} + +func testGetDefaultMetabaseOptions(t testing.TB) []meta.Option { + return []meta.Option{ + meta.WithPath(filepath.Join(t.TempDir(), "metabase")), + meta.WithPermissions(0o700), + meta.WithEpochState(epochState{}), + meta.WithLogger(test.NewLogger(t)), } } From 432042c534ec3f8774b2d75e4236e3419f466482 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 2 Dec 2024 16:16:50 +0300 Subject: [PATCH 1057/1413] [#1527] engine: Add tests for handling expired objects on inhume and lock Currently, it's allowed to inhume or lock an expired object. Consider the following scenario: 1) An user inhumes or locks an object 2) The object expires 3) GC hasn't yet deleted the object 4) The node loses the associated tombstone or lock 5) Another node replicates tombstone or lock to the first node In this case, the second node succeeds, which is the desired behavior. Signed-off-by: Aleksey Savchuk --- .../engine/inhume_test.go | 53 +++++++++++++++++++ pkg/local_object_storage/engine/lock_test.go | 53 +++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 6980afb07e..b89cf09a8b 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -2,13 +2,17 @@ package engine import ( "context" + "strconv" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" + meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" ) @@ -84,3 +88,52 @@ func TestStorageEngine_Inhume(t *testing.T) { require.Empty(t, addrs) }) } + +func TestInhumeExpiredRegularObject(t *testing.T) { + t.Parallel() + + const currEpoch = 42 + const objectExpiresAfter = currEpoch - 1 + + engine := testNewEngine(t).setShardsNumAdditionalOpts(t, 1, func(_ int) []shard.Option { + return []shard.Option{ + shard.WithDisabledGC(), + shard.WithMetaBaseOptions(append( + testGetDefaultMetabaseOptions(t), + meta.WithEpochState(epochState{currEpoch}), + )...), + } + }).prepare(t).engine + + cnr := cidtest.ID() + + generateAndPutObject := func() *objectSDK.Object { + obj := testutil.GenerateObjectWithCID(cnr) + testutil.AddAttribute(obj, objectV2.SysAttributeExpEpoch, strconv.Itoa(objectExpiresAfter)) + + var putPrm PutPrm + putPrm.Object = obj + require.NoError(t, engine.Put(context.Background(), putPrm)) + return obj + } + + t.Run("inhume with tombstone", func(t *testing.T) { + obj := generateAndPutObject() + ts := oidtest.Address() + ts.SetContainer(cnr) + + var prm InhumePrm + prm.WithTarget(ts, object.AddressOf(obj)) + _, err := engine.Inhume(context.Background(), prm) + require.NoError(t, err) + }) + + t.Run("inhume without tombstone", func(t *testing.T) { + obj := generateAndPutObject() + + var prm InhumePrm + prm.MarkAsGarbage(object.AddressOf(obj)) + _, err := engine.Inhume(context.Background(), prm) + require.NoError(t, err) + }) +} diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index feca9cb69d..7bb9e39348 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -292,3 +292,56 @@ func TestLockForceRemoval(t *testing.T) { _, err = e.Inhume(context.Background(), inhumePrm) require.NoError(t, err) } + +func TestLockExpiredRegularObject(t *testing.T) { + const currEpoch = 42 + const objectExpiresAfter = currEpoch - 1 + + engine := testNewEngine(t).setShardsNumAdditionalOpts(t, 1, func(_ int) []shard.Option { + return []shard.Option{ + shard.WithDisabledGC(), + shard.WithMetaBaseOptions(append( + testGetDefaultMetabaseOptions(t), + meta.WithEpochState(epochState{currEpoch}), + )...), + } + }).prepare(t).engine + + cnr := cidtest.ID() + + object := testutil.GenerateObjectWithCID(cnr) + testutil.AddAttribute(object, objectV2.SysAttributeExpEpoch, strconv.Itoa(objectExpiresAfter)) + + address := objectcore.AddressOf(object) + + var putPrm PutPrm + putPrm.Object = object + require.NoError(t, engine.Put(context.Background(), putPrm)) + + var getPrm GetPrm + var errNotFound *apistatus.ObjectNotFound + + getPrm.WithAddress(address) + _, err := engine.Get(context.Background(), getPrm) + require.ErrorAs(t, err, &errNotFound) + + t.Run("lock expired regular object", func(t *testing.T) { + engine.Lock(context.Background(), + address.Container(), + oidtest.ID(), + []oid.ID{address.Object()}, + ) + + res, err := engine.IsLocked(context.Background(), objectcore.AddressOf(object)) + require.NoError(t, err) + require.True(t, res) + }) + + t.Run("get expired and locked regular object", func(t *testing.T) { + getPrm.WithAddress(objectcore.AddressOf(object)) + + res, err := engine.Get(context.Background(), getPrm) + require.NoError(t, err) + require.Equal(t, res.Object(), object) + }) +} From 47dfd8840c14fc47ebc621aea1980d8fe002fce6 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 3 Dec 2024 15:34:26 +0300 Subject: [PATCH 1058/1413] [#1532] node: Allow to omit metabase.path if shard is disabled Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config/engine/config.go | 8 ++++---- cmd/frostfs-node/config/engine/config_test.go | 16 ++++++++++++++++ .../config/engine/testdata/shards.env | 3 +++ .../config/engine/testdata/shards.json | 13 +++++++++++++ .../config/engine/testdata/shards.yaml | 7 +++++++ 5 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 cmd/frostfs-node/config/engine/testdata/shards.env create mode 100644 cmd/frostfs-node/config/engine/testdata/shards.json create mode 100644 cmd/frostfs-node/config/engine/testdata/shards.yaml diff --git a/cmd/frostfs-node/config/engine/config.go b/cmd/frostfs-node/config/engine/config.go index c944d1c58e..e5735e88be 100644 --- a/cmd/frostfs-node/config/engine/config.go +++ b/cmd/frostfs-node/config/engine/config.go @@ -41,6 +41,10 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config) c.Sub(si), ) + if sc.Mode() == mode.Disabled { + continue + } + // Path for the blobstor can't be present in the default section, because different shards // must have different paths, so if it is missing, the shard is not here. // At the same time checking for "blobstor" section doesn't work proper @@ -50,10 +54,6 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config) } (*config.Config)(sc).SetDefault(def) - if sc.Mode() == mode.Disabled { - continue - } - if err := f(sc); err != nil { return err } diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 19ad0e7ac0..ef6380a620 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -18,6 +18,22 @@ import ( "github.com/stretchr/testify/require" ) +func TestIterateShards(t *testing.T) { + fileConfigTest := func(c *config.Config) { + var res []string + require.NoError(t, + engineconfig.IterateShards(c, false, func(sc *shardconfig.Config) error { + res = append(res, sc.Metabase().Path()) + return nil + })) + require.Equal(t, []string{"abc", "xyz"}, res) + } + + const cfgDir = "./testdata/shards" + configtest.ForEachFileType(cfgDir, fileConfigTest) + configtest.ForEnvFileType(t, cfgDir, fileConfigTest) +} + func TestEngineSection(t *testing.T) { t.Run("defaults", func(t *testing.T) { empty := configtest.EmptyConfig() diff --git a/cmd/frostfs-node/config/engine/testdata/shards.env b/cmd/frostfs-node/config/engine/testdata/shards.env new file mode 100644 index 0000000000..079789b0fa --- /dev/null +++ b/cmd/frostfs-node/config/engine/testdata/shards.env @@ -0,0 +1,3 @@ +FROSTFS_STORAGE_SHARD_0_METABASE_PATH=abc +FROSTFS_STORAGE_SHARD_1_MODE=disabled +FROSTFS_STORAGE_SHARD_2_METABASE_PATH=xyz diff --git a/cmd/frostfs-node/config/engine/testdata/shards.json b/cmd/frostfs-node/config/engine/testdata/shards.json new file mode 100644 index 0000000000..b3d6abe857 --- /dev/null +++ b/cmd/frostfs-node/config/engine/testdata/shards.json @@ -0,0 +1,13 @@ +{ + "storage.shard": { + "0": { + "metabase.path": "abc" + }, + "1": { + "mode": "disabled" + }, + "2": { + "metabase.path": "xyz" + } + } +} diff --git a/cmd/frostfs-node/config/engine/testdata/shards.yaml b/cmd/frostfs-node/config/engine/testdata/shards.yaml new file mode 100644 index 0000000000..bbbba3af84 --- /dev/null +++ b/cmd/frostfs-node/config/engine/testdata/shards.yaml @@ -0,0 +1,7 @@ +storage.shard: + 0: + metabase.path: abc + 1: + mode: disabled + 2: + metabase.path: xyz From 748edd19993e6cc70329f5eeb782f850e2cef87b Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 2 Dec 2024 15:15:50 +0300 Subject: [PATCH 1059/1413] [#1450] engine: Return shard-level error if object is expired on inhume Since we have errors defined on the shard-level, it looks strage that we check an error againt the shard-level error `ErrLockObjectRemoval`, but then return the metabase-level error. Let's return the same shard-level error instead. Since we have errors defined on the shard-level Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/inhume.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index e89a8d0484..74e5b56605 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -169,7 +169,7 @@ func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm sh retErr = new(apistatus.ObjectLocked) return true case errors.Is(err, shard.ErrLockObjectRemoval): - retErr = meta.ErrLockObjectRemoval + retErr = shard.ErrLockObjectRemoval return true case errors.Is(err, shard.ErrReadOnlyMode) || errors.Is(err, shard.ErrDegradedMode): retErr = err From b348b20289e6bc08fc923a8882d7dc24409ee0d6 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 4 Dec 2024 10:08:34 +0300 Subject: [PATCH 1060/1413] [#1450] engine: Add benchmark for `Inhume` operation Signed-off-by: Aleksey Savchuk --- .../engine/inhume_test.go | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index b89cf09a8b..9d7196d946 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -2,6 +2,7 @@ package engine import ( "context" + "fmt" "strconv" "testing" @@ -12,8 +13,11 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + objecttest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/test" "github.com/stretchr/testify/require" + "golang.org/x/sync/errgroup" ) func TestStorageEngine_Inhume(t *testing.T) { @@ -137,3 +141,59 @@ func TestInhumeExpiredRegularObject(t *testing.T) { require.NoError(t, err) }) } + +func BenchmarkInhumeMultipart(b *testing.B) { + // The benchmark result insignificantly depends on the number of shards, + // so do not use it as a benchmark parameter, just set it big enough. + numShards := 100 + + for numObjects := 1; numObjects <= 10000; numObjects *= 10 { + b.Run( + fmt.Sprintf("objects=%d", numObjects), + func(b *testing.B) { + benchmarkInhumeMultipart(b, numShards, numObjects) + }, + ) + } +} + +func benchmarkInhumeMultipart(b *testing.B, numShards, numObjects int) { + b.StopTimer() + + engine := testNewEngine(b, WithShardPoolSize(uint32(numObjects))). + setShardsNum(b, numShards).prepare(b).engine + defer func() { require.NoError(b, engine.Close(context.Background())) }() + + cnt := cidtest.ID() + eg := errgroup.Group{} + + for range b.N { + addrs := make([]oid.Address, numObjects) + + for i := range numObjects { + prm := PutPrm{} + + prm.Object = objecttest.Object().Parent() + prm.Object.SetContainerID(cnt) + prm.Object.SetType(objectSDK.TypeRegular) + + addrs[i] = object.AddressOf(prm.Object) + + eg.Go(func() error { + return engine.Put(context.Background(), prm) + }) + } + require.NoError(b, eg.Wait()) + + ts := oidtest.Address() + ts.SetContainer(cnt) + + prm := InhumePrm{} + prm.WithTarget(ts, addrs...) + + b.StartTimer() + _, err := engine.Inhume(context.Background(), prm) + require.NoError(b, err) + b.StopTimer() + } +} From 281d65435e05c6b6b37224c46c755a939b486f99 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 18 Nov 2024 14:40:10 +0300 Subject: [PATCH 1061/1413] [#1450] engine: Group object by shard before `Inhume` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine cpu: 12th Gen Intel(R) Core(TM) i5-1235U │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ InhumeMultipart/objects=1-12 11.42m ± 1% 10.71m ± 0% -6.27% (p=0.000 n=10) InhumeMultipart/objects=10-12 113.5m ± 0% 100.9m ± 3% -11.08% (p=0.000 n=10) InhumeMultipart/objects=100-12 1135.4m ± 1% 681.3m ± 2% -40.00% (p=0.000 n=10) InhumeMultipart/objects=1000-12 11.358 ± 0% 1.089 ± 1% -90.41% (p=0.000 n=10) InhumeMultipart/objects=10000-12 113.251 ± 0% 1.645 ± 1% -98.55% (p=0.000 n=10) geomean 1.136 265.5m -76.63% ``` Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/inhume.go | 184 +++++++++++++--------- 1 file changed, 110 insertions(+), 74 deletions(-) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 74e5b56605..80c77af54a 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -81,110 +81,146 @@ func (e *StorageEngine) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRe } func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { + addrsPerShard, err := e.groupObjectsByShard(ctx, prm.addrs, !prm.forceRemoval) + if err != nil { + return InhumeRes{}, err + } + var shPrm shard.InhumePrm if prm.forceRemoval { shPrm.ForceRemoval() } - for i := range prm.addrs { - if !prm.forceRemoval { - locked, err := e.IsLocked(ctx, prm.addrs[i]) - if err != nil { - e.log.Warn(ctx, logs.EngineRemovingAnObjectWithoutFullLockingCheck, - zap.Error(err), - zap.Stringer("addr", prm.addrs[i]), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) - } else if locked { - return InhumeRes{}, new(apistatus.ObjectLocked) - } - } + var errLocked *apistatus.ObjectLocked + for shardID, addrs := range addrsPerShard { if prm.tombstone != nil { - shPrm.SetTarget(*prm.tombstone, prm.addrs[i]) + shPrm.SetTarget(*prm.tombstone, addrs...) } else { - shPrm.MarkAsGarbage(prm.addrs[i]) + shPrm.MarkAsGarbage(addrs...) } - ok, err := e.inhumeAddr(ctx, prm.addrs[i], shPrm, true) - if err != nil { - return InhumeRes{}, err + sh, exists := e.shards[shardID] + if !exists { + e.log.Warn(ctx, logs.EngineCouldNotInhumeObjectInShard, + zap.Error(errors.New("this shard was expected to exist")), + zap.String("shard_id", shardID), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), + ) + return InhumeRes{}, errInhumeFailure } - if !ok { - ok, err := e.inhumeAddr(ctx, prm.addrs[i], shPrm, false) - if err != nil { - return InhumeRes{}, err - } else if !ok { - return InhumeRes{}, errInhumeFailure + + if _, err := sh.Inhume(ctx, shPrm); err != nil { + switch { + case errors.As(err, &errLocked): + case errors.Is(err, shard.ErrLockObjectRemoval): + case errors.Is(err, shard.ErrReadOnlyMode): + case errors.Is(err, shard.ErrDegradedMode): + default: + e.reportShardError(ctx, sh, "couldn't inhume object in shard", err) } + return InhumeRes{}, err } } return InhumeRes{}, nil } -// Returns ok if object was inhumed during this invocation or before. -func (e *StorageEngine) inhumeAddr(ctx context.Context, addr oid.Address, prm shard.InhumePrm, checkExists bool) (bool, error) { - root := false - var existPrm shard.ExistsPrm - var retErr error - var ok bool +// groupObjectsByShard groups objects based on the shard(s) they are stored on. +// +// If checkLocked is set, [apistatus.ObjectLocked] will be returned if any of +// the objects are locked. +func (e *StorageEngine) groupObjectsByShard(ctx context.Context, addrs []oid.Address, checkLocked bool) (map[string][]oid.Address, error) { + groups := make(map[string][]oid.Address) + + for _, addr := range addrs { + ids, err := e.findShards(ctx, addr, checkLocked) + if err != nil { + return nil, err + } + for _, id := range ids { + groups[id] = append(groups[id], addr) + } + } + + return groups, nil +} + +// findShards determines the shard(s) where the object is stored. +// +// If the object is a root object, multiple shards will be returned. +// +// If checkLocked is set, [apistatus.ObjectLocked] will be returned if any of +// the objects are locked. +func (e *StorageEngine) findShards(ctx context.Context, addr oid.Address, checkLocked bool) ([]string, error) { + var ( + ids []string + retErr error + + prm shard.ExistsPrm + + siErr *objectSDK.SplitInfoError + ecErr *objectSDK.ECInfoError + + isRootObject bool + objectExists bool + ) e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { - defer func() { - // if object is root we continue since information about it - // can be presented in other shards - if checkExists && root { - stop = false - } - }() + objectExists = false - if checkExists { - existPrm.Address = addr - exRes, err := sh.Exists(ctx, existPrm) - if err != nil { - if client.IsErrObjectAlreadyRemoved(err) || shard.IsErrObjectExpired(err) { - // inhumed once - no need to be inhumed again - ok = true - return true - } - - var siErr *objectSDK.SplitInfoError - var ecErr *objectSDK.ECInfoError - if !(errors.As(err, &siErr) || errors.As(err, &ecErr)) { - e.reportShardError(ctx, sh, "could not check for presents in shard", err, zap.Stringer("address", addr)) - return - } - - root = true - } else if !exRes.Exists() { - return - } + prm.Address = addr + switch res, err := sh.Exists(ctx, prm); { + case client.IsErrObjectAlreadyRemoved(err) || shard.IsErrObjectExpired(err): + // NOTE(@a-savchuk): there were some considerations that we can stop + // immediately if the object is already removed or expired. However, + // the previous method behavior was: + // - keep iterating if it's a root object and already removed, + // - stop iterating if it's not a root object and removed. + // + // Since my task was only improving method speed, let's keep the + // previous method behavior. Continue if it's a root object. + return !isRootObject + case errors.As(err, &siErr) || errors.As(err, &ecErr): + isRootObject = true + objectExists = true + case err != nil: + e.reportShardError( + ctx, sh, "couldn't check for presence in shard", + err, zap.Stringer("address", addr), + ) + case res.Exists(): + objectExists = true + default: } - _, err := sh.Inhume(ctx, prm) - if err != nil { - var errLocked *apistatus.ObjectLocked - switch { - case errors.As(err, &errLocked): + if !objectExists { + return + } + + if checkLocked { + if isLocked, err := sh.IsLocked(ctx, addr); err != nil { + e.log.Warn(ctx, logs.EngineRemovingAnObjectWithoutFullLockingCheck, + zap.Error(err), + zap.Stringer("address", addr), + zap.String("trace_id", tracingPkg.GetTraceID(ctx)), + ) + } else if isLocked { retErr = new(apistatus.ObjectLocked) return true - case errors.Is(err, shard.ErrLockObjectRemoval): - retErr = shard.ErrLockObjectRemoval - return true - case errors.Is(err, shard.ErrReadOnlyMode) || errors.Is(err, shard.ErrDegradedMode): - retErr = err - return true } - - e.reportShardError(ctx, sh, "could not inhume object in shard", err, zap.Stringer("address", addr)) - return false } - ok = true - return true + ids = append(ids, sh.ID().String()) + + // Continue if it's a root object. + return !isRootObject }) - return ok, retErr + if retErr != nil { + return nil, retErr + } + return ids, nil } // IsLocked checks whether an object is locked according to StorageEngine's state. From 6c679d15350e8d28b25ede822d682c3354b06ebe Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 4 Dec 2024 11:03:42 +0300 Subject: [PATCH 1062/1413] [#1535] morph: Unify client creation error messages Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/balance/client.go | 2 +- pkg/morph/client/container/client.go | 2 +- pkg/morph/client/frostfs/client.go | 2 +- pkg/morph/client/frostfsid/client.go | 2 +- pkg/morph/client/netmap/client.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/morph/client/balance/client.go b/pkg/morph/client/balance/client.go index b05c526dc7..d229e59008 100644 --- a/pkg/morph/client/balance/client.go +++ b/pkg/morph/client/balance/client.go @@ -39,7 +39,7 @@ func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, staticClient, err := client.NewStatic(cli, contract, fee, ([]client.StaticClientOption)(*o)...) if err != nil { - return nil, fmt.Errorf("could not create static client of Balance contract: %w", err) + return nil, fmt.Errorf("create 'balance' contract client: %w", err) } return &Client{ diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index bdbcce9178..b95b1ea06c 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -48,7 +48,7 @@ func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, sc, err := client.NewStatic(cli, contract, fee, o.staticOpts...) if err != nil { - return nil, fmt.Errorf("can't create container static client: %w", err) + return nil, fmt.Errorf("create 'container' contract client: %w", err) } return &Client{client: sc}, nil diff --git a/pkg/morph/client/frostfs/client.go b/pkg/morph/client/frostfs/client.go index 571915c273..cd6a9849ec 100644 --- a/pkg/morph/client/frostfs/client.go +++ b/pkg/morph/client/frostfs/client.go @@ -35,7 +35,7 @@ func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, sc, err := client.NewStatic(cli, contract, fee, ([]client.StaticClientOption)(*o)...) if err != nil { - return nil, fmt.Errorf("could not create client of FrostFS contract: %w", err) + return nil, fmt.Errorf("create 'frostfs' contract client: %w", err) } return &Client{client: sc}, nil diff --git a/pkg/morph/client/frostfsid/client.go b/pkg/morph/client/frostfsid/client.go index 4c31f42de9..61eb03f099 100644 --- a/pkg/morph/client/frostfsid/client.go +++ b/pkg/morph/client/frostfsid/client.go @@ -27,7 +27,7 @@ var _ frostfsidcore.SubjectProvider = (*Client)(nil) func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8) (*Client, error) { sc, err := client.NewStatic(cli, contract, fee, client.TryNotary(), client.AsAlphabet()) if err != nil { - return nil, fmt.Errorf("could not create client of FrostFS ID contract: %w", err) + return nil, fmt.Errorf("create 'frostfsid' contract client: %w", err) } return &Client{client: sc}, nil diff --git a/pkg/morph/client/netmap/client.go b/pkg/morph/client/netmap/client.go index eafa097e9e..da7eb07190 100644 --- a/pkg/morph/client/netmap/client.go +++ b/pkg/morph/client/netmap/client.go @@ -52,7 +52,7 @@ func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, sc, err := client.NewStatic(cli, contract, fee, ([]client.StaticClientOption)(*o)...) if err != nil { - return nil, fmt.Errorf("can't create netmap static client: %w", err) + return nil, fmt.Errorf("create 'netmap' contract client: %w", err) } return &Client{client: sc}, nil From e37dcdf88bfb6e159b1e2812b43774227e7d3366 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 4 Dec 2024 11:07:43 +0300 Subject: [PATCH 1063/1413] [#1535] morph/netmap: Unify error messages for config retrieval Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/netmap/config.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index 0a3c351dbe..29bd1517d6 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -28,7 +28,7 @@ const ( func (c *Client) MaxObjectSize() (uint64, error) { objectSize, err := c.readUInt64Config(MaxObjectSizeConfig) if err != nil { - return 0, fmt.Errorf("(%T) could not get epoch number: %w", c, err) + return 0, err } return objectSize, nil @@ -38,7 +38,7 @@ func (c *Client) MaxObjectSize() (uint64, error) { func (c *Client) EpochDuration() (uint64, error) { epochDuration, err := c.readUInt64Config(EpochDurationConfig) if err != nil { - return 0, fmt.Errorf("(%T) could not get epoch duration: %w", c, err) + return 0, err } return epochDuration, nil @@ -49,7 +49,7 @@ func (c *Client) EpochDuration() (uint64, error) { func (c *Client) ContainerFee() (uint64, error) { fee, err := c.readUInt64Config(ContainerFeeConfig) if err != nil { - return 0, fmt.Errorf("(%T) could not get container fee: %w", c, err) + return 0, err } return fee, nil @@ -60,7 +60,7 @@ func (c *Client) ContainerFee() (uint64, error) { func (c *Client) ContainerAliasFee() (uint64, error) { fee, err := c.readUInt64Config(ContainerAliasFeeConfig) if err != nil { - return 0, fmt.Errorf("(%T) could not get container alias fee: %w", c, err) + return 0, err } return fee, nil @@ -79,7 +79,7 @@ func (c *Client) HomomorphicHashDisabled() (bool, error) { func (c *Client) InnerRingCandidateFee() (uint64, error) { fee, err := c.readUInt64Config(IrCandidateFeeConfig) if err != nil { - return 0, fmt.Errorf("(%T) could not get inner ring candidate fee: %w", c, err) + return 0, err } return fee, nil @@ -90,7 +90,7 @@ func (c *Client) InnerRingCandidateFee() (uint64, error) { func (c *Client) WithdrawFee() (uint64, error) { fee, err := c.readUInt64Config(WithdrawFeeConfig) if err != nil { - return 0, fmt.Errorf("(%T) could not get withdraw fee: %w", c, err) + return 0, err } return fee, nil @@ -108,7 +108,7 @@ func (c *Client) MaintenanceModeAllowed() (bool, error) { func (c *Client) readUInt64Config(key string) (uint64, error) { v, err := c.config([]byte(key), IntegerAssert) if err != nil { - return 0, err + return 0, fmt.Errorf("read netconfig value '%s': %w", key, err) } // IntegerAssert is guaranteed to return int64 if the error is nil. @@ -124,7 +124,7 @@ func (c *Client) readBoolConfig(key string) (bool, error) { return false, nil } - return false, fmt.Errorf("read boolean configuration value %s from the Sidechain: %w", key, err) + return false, fmt.Errorf("read netconfig value '%s': %w", key, err) } // BoolAssert is guaranteed to return bool if the error is nil. From e3487d5af5d513115659294a1699bde18269887f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 4 Dec 2024 11:17:13 +0300 Subject: [PATCH 1064/1413] [#1535] morph: Unify test invoke error messages Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/balance/balanceOf.go | 2 +- pkg/morph/client/balance/decimals.go | 2 +- pkg/morph/client/container/deletion_info.go | 2 +- pkg/morph/client/container/get.go | 2 +- pkg/morph/client/container/list.go | 2 +- pkg/morph/client/frostfsid/subject.go | 4 ++-- pkg/morph/client/netmap/config.go | 4 ++-- pkg/morph/client/netmap/epoch.go | 4 ++-- pkg/morph/client/netmap/innerring.go | 2 +- pkg/morph/client/netmap/netmap.go | 6 +++--- pkg/morph/client/netmap/snapshot.go | 4 +++- pkg/morph/client/notary.go | 4 ++-- 12 files changed, 20 insertions(+), 18 deletions(-) diff --git a/pkg/morph/client/balance/balanceOf.go b/pkg/morph/client/balance/balanceOf.go index aae245acd2..73aab17361 100644 --- a/pkg/morph/client/balance/balanceOf.go +++ b/pkg/morph/client/balance/balanceOf.go @@ -23,7 +23,7 @@ func (c *Client) BalanceOf(id user.ID) (*big.Int, error) { prms, err := c.client.TestInvoke(invokePrm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", balanceOfMethod, err) + return nil, fmt.Errorf("test invoke (%s): %w", balanceOfMethod, err) } else if ln := len(prms); ln != 1 { return nil, fmt.Errorf("unexpected stack item count (%s): %d", balanceOfMethod, ln) } diff --git a/pkg/morph/client/balance/decimals.go b/pkg/morph/client/balance/decimals.go index 39e4b28e57..28329ee6e0 100644 --- a/pkg/morph/client/balance/decimals.go +++ b/pkg/morph/client/balance/decimals.go @@ -14,7 +14,7 @@ func (c *Client) Decimals() (uint32, error) { prms, err := c.client.TestInvoke(invokePrm) if err != nil { - return 0, fmt.Errorf("could not perform test invocation (%s): %w", decimalsMethod, err) + return 0, fmt.Errorf("test invoke (%s): %w", decimalsMethod, err) } else if ln := len(prms); ln != 1 { return 0, fmt.Errorf("unexpected stack item count (%s): %d", decimalsMethod, ln) } diff --git a/pkg/morph/client/container/deletion_info.go b/pkg/morph/client/container/deletion_info.go index dda6bf98cc..436ca3c016 100644 --- a/pkg/morph/client/container/deletion_info.go +++ b/pkg/morph/client/container/deletion_info.go @@ -39,7 +39,7 @@ func (c *Client) DeletionInfo(cid []byte) (*containercore.DelInfo, error) { if strings.Contains(err.Error(), containerContract.NotFoundError) { return nil, new(apistatus.ContainerNotFound) } - return nil, fmt.Errorf("could not perform test invocation (%s): %w", deletionInfoMethod, err) + return nil, fmt.Errorf("test invoke (%s): %w", deletionInfoMethod, err) } else if ln := len(res); ln != 1 { return nil, fmt.Errorf("unexpected stack item count (%s): %d", deletionInfoMethod, ln) } diff --git a/pkg/morph/client/container/get.go b/pkg/morph/client/container/get.go index ea57a3a957..1d84e9109e 100644 --- a/pkg/morph/client/container/get.go +++ b/pkg/morph/client/container/get.go @@ -53,7 +53,7 @@ func (c *Client) Get(cid []byte) (*containercore.Container, error) { if strings.Contains(err.Error(), containerContract.NotFoundError) { return nil, new(apistatus.ContainerNotFound) } - return nil, fmt.Errorf("could not perform test invocation (%s): %w", getMethod, err) + return nil, fmt.Errorf("test invoke (%s): %w", getMethod, err) } else if ln := len(res); ln != 1 { return nil, fmt.Errorf("unexpected stack item count (%s): %d", getMethod, ln) } diff --git a/pkg/morph/client/container/list.go b/pkg/morph/client/container/list.go index 6fed46c1ad..55317375a6 100644 --- a/pkg/morph/client/container/list.go +++ b/pkg/morph/client/container/list.go @@ -27,7 +27,7 @@ func (c *Client) list(idUser *user.ID) ([]cid.ID, error) { res, err := c.client.TestInvoke(prm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", listMethod, err) + return nil, fmt.Errorf("test invoke (%s): %w", listMethod, err) } else if ln := len(res); ln != 1 { return nil, fmt.Errorf("unexpected stack item count (%s): %d", listMethod, ln) } diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index 0852f536cf..7c93f49222 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -21,7 +21,7 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) res, err := c.client.TestInvoke(prm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubject, err) + return nil, fmt.Errorf("test invoke (%s): %w", methodGetSubject, err) } structArr, err := checkStackItem(res) @@ -44,7 +44,7 @@ func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.Subject res, err := c.client.TestInvoke(prm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", methodGetSubjectExtended, err) + return nil, fmt.Errorf("test invoke (%s): %w", methodGetSubjectExtended, err) } structArr, err := checkStackItem(res) diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index 29bd1517d6..2b87df6f78 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -206,7 +206,7 @@ func (c *Client) ReadNetworkConfiguration() (NetworkConfiguration, error) { items, err := c.client.TestInvoke(prm) if err != nil { - return res, fmt.Errorf("could not perform test invocation (%s): %w", + return res, fmt.Errorf("test invoke (%s): %w", configListMethod, err) } @@ -292,7 +292,7 @@ func (c *Client) config(key []byte, assert func(stackitem.Item) (any, error)) (a items, err := c.client.TestInvoke(prm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", + return nil, fmt.Errorf("test invoke (%s): %w", configMethod, err) } diff --git a/pkg/morph/client/netmap/epoch.go b/pkg/morph/client/netmap/epoch.go index 92d569ae2c..6d909a7a17 100644 --- a/pkg/morph/client/netmap/epoch.go +++ b/pkg/morph/client/netmap/epoch.go @@ -14,7 +14,7 @@ func (c *Client) Epoch() (uint64, error) { items, err := c.client.TestInvoke(prm) if err != nil { - return 0, fmt.Errorf("could not perform test invocation (%s): %w", + return 0, fmt.Errorf("test invoke (%s): %w", epochMethod, err) } @@ -38,7 +38,7 @@ func (c *Client) LastEpochBlock() (uint32, error) { items, err := c.client.TestInvoke(prm) if err != nil { - return 0, fmt.Errorf("could not perform test invocation (%s): %w", + return 0, fmt.Errorf("test invoke (%s): %w", lastEpochBlockMethod, err) } diff --git a/pkg/morph/client/netmap/innerring.go b/pkg/morph/client/netmap/innerring.go index c9dc7d2fcb..824827d6fb 100644 --- a/pkg/morph/client/netmap/innerring.go +++ b/pkg/morph/client/netmap/innerring.go @@ -46,7 +46,7 @@ func (c *Client) GetInnerRingList() (keys.PublicKeys, error) { prms, err := c.client.TestInvoke(invokePrm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", innerRingListMethod, err) + return nil, fmt.Errorf("test invoke (%s): %w", innerRingListMethod, err) } return irKeysFromStackItem(prms, innerRingListMethod) diff --git a/pkg/morph/client/netmap/netmap.go b/pkg/morph/client/netmap/netmap.go index f7b5c3ba45..a0009ea734 100644 --- a/pkg/morph/client/netmap/netmap.go +++ b/pkg/morph/client/netmap/netmap.go @@ -18,7 +18,7 @@ func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { res, err := c.client.TestInvoke(invokePrm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", + return nil, fmt.Errorf("test invoke (%s): %w", epochSnapshotMethod, err) } @@ -40,7 +40,7 @@ func (c *Client) GetCandidates() ([]netmap.NodeInfo, error) { res, err := c.client.TestInvoke(invokePrm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", netMapCandidatesMethod, err) + return nil, fmt.Errorf("test invoke (%s): %w", netMapCandidatesMethod, err) } if len(res) > 0 { @@ -57,7 +57,7 @@ func (c *Client) NetMap() (*netmap.NetMap, error) { res, err := c.client.TestInvoke(invokePrm) if err != nil { - return nil, fmt.Errorf("could not perform test invocation (%s): %w", + return nil, fmt.Errorf("test invoke (%s): %w", netMapMethod, err) } diff --git a/pkg/morph/client/netmap/snapshot.go b/pkg/morph/client/netmap/snapshot.go index ba2c26af78..a5134bcef7 100644 --- a/pkg/morph/client/netmap/snapshot.go +++ b/pkg/morph/client/netmap/snapshot.go @@ -1,6 +1,8 @@ package netmap import ( + "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" ) @@ -13,7 +15,7 @@ func (c *Client) GetNetMap(diff uint64) (*netmap.NetMap, error) { res, err := c.client.TestInvoke(prm) if err != nil { - return nil, err + return nil, fmt.Errorf("test invoke (%s): %w", snapshotMethod, err) } return DecodeNetMap(res) diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 71232cb33f..8516c89a97 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -239,7 +239,7 @@ func (c *Client) GetNotaryDeposit() (res int64, err error) { items, err := c.TestInvoke(c.notary.notary, notaryBalanceOfMethod, sh) if err != nil { - return 0, fmt.Errorf("%v: %w", notaryBalanceErrMsg, err) + return 0, fmt.Errorf("test invoke (%s): %w", notaryBalanceOfMethod, err) } if len(items) != 1 { @@ -654,7 +654,7 @@ func (c *Client) notaryTxValidationLimit() (uint32, error) { func (c *Client) depositExpirationOf() (int64, error) { expirationRes, err := c.TestInvoke(c.notary.notary, notaryExpirationOfMethod, c.acc.PrivateKey().GetScriptHash()) if err != nil { - return 0, fmt.Errorf("can't invoke method: %w", err) + return 0, fmt.Errorf("test invoke (%s): %w", notaryExpirationOfMethod, err) } if len(expirationRes) != 1 { From 2d5d4093be45cd26660ddcd9ea28d7b625a6e203 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 4 Dec 2024 13:19:37 +0300 Subject: [PATCH 1065/1413] [#1537] morph: Use `(user.ID).ScriptHash()` where possible Pick up changes from TrueCloudLab/frostfs-sdk-go#198. gopatch: ``` @@ var user expression @@ -address.StringToUint160(user.EncodeToString()) +user.ScriptHash() ``` Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/balance/balanceOf.go | 3 +-- pkg/morph/client/balance/transfer.go | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/morph/client/balance/balanceOf.go b/pkg/morph/client/balance/balanceOf.go index 73aab17361..12a499ffbe 100644 --- a/pkg/morph/client/balance/balanceOf.go +++ b/pkg/morph/client/balance/balanceOf.go @@ -6,13 +6,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" ) // BalanceOf receives the amount of funds in the client's account // through the Balance contract call, and returns it. func (c *Client) BalanceOf(id user.ID) (*big.Int, error) { - h, err := address.StringToUint160(id.EncodeToString()) + h, err := id.ScriptHash() if err != nil { return nil, err } diff --git a/pkg/morph/client/balance/transfer.go b/pkg/morph/client/balance/transfer.go index 65a0b70a6b..9638b5c455 100644 --- a/pkg/morph/client/balance/transfer.go +++ b/pkg/morph/client/balance/transfer.go @@ -6,7 +6,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" ) // TransferPrm groups parameters of TransferX method. @@ -25,12 +24,12 @@ type TransferPrm struct { // // If TryNotary is provided, calls notary contract. func (c *Client) TransferX(ctx context.Context, p TransferPrm) error { - from, err := address.StringToUint160(p.From.EncodeToString()) + from, err := p.From.ScriptHash() if err != nil { return err } - to, err := address.StringToUint160(p.To.EncodeToString()) + to, err := p.To.ScriptHash() if err != nil { return err } From 5c3b2d95ba860327963fce069553f5ec953982a1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 4 Dec 2024 15:17:50 +0300 Subject: [PATCH 1066/1413] [#1538] node: Assume notary is enabled Notaryless environments are not tested at all since a while. We use neo-go only and it has notary contract enabled. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 2 -- cmd/frostfs-node/morph.go | 28 +++++++--------------------- cmd/frostfs-node/netmap.go | 18 ++++++++---------- cmd/frostfs-node/object.go | 28 ++-------------------------- 4 files changed, 17 insertions(+), 59 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 5af37865f7..e63786b7d3 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -591,8 +591,6 @@ type cfgMorph struct { client *client.Client - notaryEnabled bool - // TTL of Sidechain cached values. Non-positive value disables caching. cacheTTL time.Duration diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 67d2d1c064..3b9175981b 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -35,18 +35,14 @@ func (c *cfg) initMorphComponents(ctx context.Context) { lookupScriptHashesInNNS(c) // smart contract auto negotiation - if c.cfgMorph.notaryEnabled { - err := c.cfgMorph.client.EnableNotarySupport( - client.WithProxyContract( - c.cfgMorph.proxyScriptHash, - ), - ) - fatalOnErr(err) - } - - c.log.Info(ctx, logs.FrostFSNodeNotarySupport, - zap.Bool("sidechain_enabled", c.cfgMorph.notaryEnabled), + err := c.cfgMorph.client.EnableNotarySupport( + client.WithProxyContract( + c.cfgMorph.proxyScriptHash, + ), ) + fatalOnErr(err) + + c.log.Info(ctx, logs.FrostFSNodeNotarySupport) wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0, nmClient.TryNotary()) fatalOnErr(err) @@ -116,15 +112,9 @@ func initMorphClient(ctx context.Context, c *cfg) { } c.cfgMorph.client = cli - c.cfgMorph.notaryEnabled = cli.ProbeNotary() } func makeAndWaitNotaryDeposit(ctx context.Context, c *cfg) { - // skip notary deposit in non-notary environments - if !c.cfgMorph.notaryEnabled { - return - } - tx, vub, err := makeNotaryDeposit(ctx, c) fatalOnErr(err) @@ -282,10 +272,6 @@ func lookupScriptHashesInNNS(c *cfg) { ) for _, t := range targets { - if t.nnsName == client.NNSProxyContractName && !c.cfgMorph.notaryEnabled { - continue // ignore proxy contract if notary disabled - } - if emptyHash.Equals(*t.h) { *t.h, err = c.cfgMorph.client.NNSContractAddress(t.nnsName) fatalOnErrDetails(fmt.Sprintf("can't resolve %s in NNS", t.nnsName), err) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 9127d11232..e94428fcb7 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -193,16 +193,14 @@ func addNewEpochNotificationHandlers(c *cfg) { } }) - if c.cfgMorph.notaryEnabled { - addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) { - _, _, err := makeNotaryDeposit(ctx, c) - if err != nil { - c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit, - zap.String("error", err.Error()), - ) - } - }) - } + addNewEpochAsyncNotificationHandler(c, func(ctx context.Context, _ event.Event) { + _, _, err := makeNotaryDeposit(ctx, c) + if err != nil { + c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit, + zap.String("error", err.Error()), + ) + } + }) } // bootstrapNode adds current node to the Network map. diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index c4205a620c..6804aae592 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -13,7 +13,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache" objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc" objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" @@ -137,24 +136,6 @@ func (fn *innerRingFetcherWithNotary) InnerRingKeys() ([][]byte, error) { return result, nil } -type innerRingFetcherWithoutNotary struct { - nm *nmClient.Client -} - -func (f *innerRingFetcherWithoutNotary) InnerRingKeys() ([][]byte, error) { - keys, err := f.nm.GetInnerRingList() - if err != nil { - return nil, fmt.Errorf("can't get inner ring keys from netmap contract: %w", err) - } - - result := make([][]byte, 0, len(keys)) - for i := range keys { - result = append(result, keys[i].Bytes()) - } - - return result, nil -} - func initObjectService(c *cfg) { keyStorage := util.NewKeyStorage(&c.key.PrivateKey, c.privateTokenStore, c.cfgNetmap.state) @@ -305,13 +286,8 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl } func createInnerRingFetcher(c *cfg) v2.InnerRingFetcher { - if c.cfgMorph.client.ProbeNotary() { - return &innerRingFetcherWithNotary{ - sidechain: c.cfgMorph.client, - } - } - return &innerRingFetcherWithoutNotary{ - nm: c.cfgNetmap.wrapper, + return &innerRingFetcherWithNotary{ + sidechain: c.cfgMorph.client, } } From 6a51086030bc9ae8f6403928579313d629549110 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 4 Dec 2024 15:25:36 +0300 Subject: [PATCH 1067/1413] [#1538] morph/client: Remove TryNotary() option from side-chain contracts The notary is always enabled and this option does always work. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/metabase/upgrade.go | 2 +- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/container.go | 2 +- cmd/frostfs-node/morph.go | 2 +- pkg/innerring/initialization.go | 5 ++--- pkg/morph/client/balance/client.go | 10 +--------- pkg/morph/client/balance/transfer.go | 2 -- pkg/morph/client/container/client.go | 10 +--------- pkg/morph/client/container/delete.go | 2 -- pkg/morph/client/container/put.go | 2 -- pkg/morph/client/netmap/client.go | 10 +--------- 11 files changed, 9 insertions(+), 40 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go index 00b30c9b2a..beced0d7a4 100644 --- a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go +++ b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go @@ -135,7 +135,7 @@ func createContainerInfoProvider(cli *client.Client) (container.InfoProvider, er if err != nil { return nil, fmt.Errorf("resolve container contract hash: %w", err) } - cc, err := morphcontainer.NewFromMorph(cli, sh, 0, morphcontainer.TryNotary()) + cc, err := morphcontainer.NewFromMorph(cli, sh, 0) if err != nil { return nil, fmt.Errorf("create morph container client: %w", err) } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e63786b7d3..9b727e41ad 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1464,7 +1464,7 @@ func (c *cfg) createTombstoneSource() *tombstone.ExpirationChecker { func (c *cfg) createContainerInfoProvider(ctx context.Context) container.InfoProvider { return container.NewInfoProvider(func() (container.Source, error) { c.initMorphComponents(ctx) - cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, containerClient.TryNotary()) + cc, err := containerClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0) if err != nil { return nil, err } diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index d3e1b27661..7d558dacb6 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -28,7 +28,7 @@ import ( func initContainerService(_ context.Context, c *cfg) { // container wrapper that tries to invoke notary // requests if chain is configured so - wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0, cntClient.TryNotary()) + wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0) fatalOnErr(err) c.shared.cnrClient = wrap diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 3b9175981b..81579c7fc8 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -44,7 +44,7 @@ func (c *cfg) initMorphComponents(ctx context.Context) { c.log.Info(ctx, logs.FrostFSNodeNotarySupport) - wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0, nmClient.TryNotary()) + wrap, err := nmClient.NewFromMorph(c.cfgMorph.client, c.cfgNetmap.scriptHash, 0) fatalOnErr(err) var netmapSource netmap.Source diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index 25f4ff0347..5481354e15 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -380,7 +380,6 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) { // form morph container client's options morphCnrOpts := make([]container.Option, 0, 3) morphCnrOpts = append(morphCnrOpts, - container.TryNotary(), container.AsAlphabet(), ) @@ -390,12 +389,12 @@ func (s *Server) initClientsFromMorph() (*serverMorphClients, error) { } s.containerClient = result.CnrClient - s.netmapClient, err = nmClient.NewFromMorph(s.morphClient, s.contracts.netmap, fee, nmClient.TryNotary(), nmClient.AsAlphabet()) + s.netmapClient, err = nmClient.NewFromMorph(s.morphClient, s.contracts.netmap, fee, nmClient.AsAlphabet()) if err != nil { return nil, err } - s.balanceClient, err = balanceClient.NewFromMorph(s.morphClient, s.contracts.balance, fee, balanceClient.TryNotary(), balanceClient.AsAlphabet()) + s.balanceClient, err = balanceClient.NewFromMorph(s.morphClient, s.contracts.balance, fee, balanceClient.AsAlphabet()) if err != nil { return nil, err } diff --git a/pkg/morph/client/balance/client.go b/pkg/morph/client/balance/client.go index d229e59008..1dacb9574c 100644 --- a/pkg/morph/client/balance/client.go +++ b/pkg/morph/client/balance/client.go @@ -54,15 +54,7 @@ type Option func(*opts) type opts []client.StaticClientOption func defaultOpts() *opts { - return new(opts) -} - -// TryNotary returns option to enable -// notary invocation tries. -func TryNotary() Option { - return func(o *opts) { - *o = append(*o, client.TryNotary()) - } + return &opts{client.TryNotary()} } // AsAlphabet returns option to sign main TX diff --git a/pkg/morph/client/balance/transfer.go b/pkg/morph/client/balance/transfer.go index 9638b5c455..16c8f39820 100644 --- a/pkg/morph/client/balance/transfer.go +++ b/pkg/morph/client/balance/transfer.go @@ -21,8 +21,6 @@ type TransferPrm struct { // TransferX transfers p.Amount of GASe-12 from p.From to p.To // with details p.Details through direct smart contract call. -// -// If TryNotary is provided, calls notary contract. func (c *Client) TransferX(ctx context.Context, p TransferPrm) error { from, err := p.From.ScriptHash() if err != nil { diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index b95b1ea06c..51aa1a93a4 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -73,15 +73,7 @@ type opts struct { } func defaultOpts() *opts { - return new(opts) -} - -// TryNotary returns option to enable -// notary invocation tries. -func TryNotary() Option { - return func(o *opts) { - o.staticOpts = append(o.staticOpts, client.TryNotary()) - } + return &opts{staticOpts: []client.StaticClientOption{client.TryNotary()}} } // AsAlphabet returns option to sign main TX diff --git a/pkg/morph/client/container/delete.go b/pkg/morph/client/container/delete.go index 5696645b2f..ef5cc8c384 100644 --- a/pkg/morph/client/container/delete.go +++ b/pkg/morph/client/container/delete.go @@ -66,8 +66,6 @@ func (d *DeletePrm) SetKey(key []byte) { // // Returns valid until block and any error encountered that caused // the removal to interrupt. -// -// If TryNotary is provided, calls notary contract. func (c *Client) Delete(ctx context.Context, p DeletePrm) (uint32, error) { if len(p.signature) == 0 && !p.IsControl() { return 0, errNilArgument diff --git a/pkg/morph/client/container/put.go b/pkg/morph/client/container/put.go index 74d9f6da80..1eb03694f4 100644 --- a/pkg/morph/client/container/put.go +++ b/pkg/morph/client/container/put.go @@ -94,8 +94,6 @@ func (p *PutPrm) SetZone(zone string) { // // Returns calculated container identifier and any error // encountered that caused the saving to interrupt. -// -// If TryNotary is provided, calls notary contract. func (c *Client) Put(ctx context.Context, p PutPrm) error { if len(p.sig) == 0 || len(p.key) == 0 { return errNilArgument diff --git a/pkg/morph/client/netmap/client.go b/pkg/morph/client/netmap/client.go index da7eb07190..de8afbfb52 100644 --- a/pkg/morph/client/netmap/client.go +++ b/pkg/morph/client/netmap/client.go @@ -65,15 +65,7 @@ type Option func(*opts) type opts []client.StaticClientOption func defaultOpts() *opts { - return new(opts) -} - -// TryNotary returns option to enable -// notary invocation tries. -func TryNotary() Option { - return func(o *opts) { - *o = append(*o, client.TryNotary()) - } + return &opts{client.TryNotary()} } // AsAlphabet returns option to sign main TX From 84b4051b4da05e3a0433793c6de89fcb5b5e2e9c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 4 Dec 2024 15:28:33 +0300 Subject: [PATCH 1068/1413] [#1538] morph/container: Make opts struct similar to that of other contracts Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/container/client.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/morph/client/container/client.go b/pkg/morph/client/container/client.go index 51aa1a93a4..be684619b9 100644 --- a/pkg/morph/client/container/client.go +++ b/pkg/morph/client/container/client.go @@ -46,7 +46,7 @@ func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8, opts[i](o) } - sc, err := client.NewStatic(cli, contract, fee, o.staticOpts...) + sc, err := client.NewStatic(cli, contract, fee, *o...) if err != nil { return nil, fmt.Errorf("create 'container' contract client: %w", err) } @@ -68,12 +68,10 @@ func (c Client) ContractAddress() util.Uint160 { // parameter of Wrapper. type Option func(*opts) -type opts struct { - staticOpts []client.StaticClientOption -} +type opts []client.StaticClientOption func defaultOpts() *opts { - return &opts{staticOpts: []client.StaticClientOption{client.TryNotary()}} + return &opts{client.TryNotary()} } // AsAlphabet returns option to sign main TX @@ -83,6 +81,6 @@ func defaultOpts() *opts { // Considered to be used by IR nodes only. func AsAlphabet() Option { return func(o *opts) { - o.staticOpts = append(o.staticOpts, client.AsAlphabet()) + *o = append(*o, client.AsAlphabet()) } } From 5fe78e51d1c4cc19d53e2106de4c7577f6d4f272 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 5 Dec 2024 10:32:20 +0300 Subject: [PATCH 1069/1413] [#1540] getSvc: Do not log context canceled errors during EC assemble Those errors are fired when it is enough chunks retrieved and error group cancels other requests. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/assemblerec.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index b0895e13ec..127be2b52c 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -238,13 +238,13 @@ func (a *assemblerec) tryGetChunkFromLocalStorage(ctx context.Context, ch object var object *objectSDK.Object if a.head { object, err = a.localStorage.Head(ctx, addr, false) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { a.log.Warn(ctx, logs.GetUnableToHeadPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) return nil } } else { object, err = a.localStorage.Get(ctx, addr) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { a.log.Warn(ctx, logs.GetUnableToGetPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) return nil } @@ -286,13 +286,13 @@ func (a *assemblerec) tryGetChunkFromRemoteStorage(ctx context.Context, node cli var object *objectSDK.Object if a.head { object, err = a.remoteStorage.headObjectFromNode(ctx, addr, node, false) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { a.log.Warn(ctx, logs.GetUnableToHeadPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) return nil } } else { object, err = a.remoteStorage.getObjectFromNode(ctx, addr, node) - if err != nil { + if err != nil && !errors.Is(err, context.Canceled) { a.log.Warn(ctx, logs.GetUnableToGetPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) return nil } From 7df3520d486555a0211f7e37ee3e0fa9a96cf92c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 5 Dec 2024 10:32:30 +0300 Subject: [PATCH 1070/1413] [#1540] getSvc: Drop redundant returns Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/assemblerec.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index 127be2b52c..a53299480e 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -240,13 +240,11 @@ func (a *assemblerec) tryGetChunkFromLocalStorage(ctx context.Context, ch object object, err = a.localStorage.Head(ctx, addr, false) if err != nil && !errors.Is(err, context.Canceled) { a.log.Warn(ctx, logs.GetUnableToHeadPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) - return nil } } else { object, err = a.localStorage.Get(ctx, addr) if err != nil && !errors.Is(err, context.Canceled) { a.log.Warn(ctx, logs.GetUnableToGetPartECObject, zap.String("node", "local"), zap.Stringer("part_id", objID), zap.Error(err)) - return nil } } return object @@ -288,13 +286,11 @@ func (a *assemblerec) tryGetChunkFromRemoteStorage(ctx context.Context, node cli object, err = a.remoteStorage.headObjectFromNode(ctx, addr, node, false) if err != nil && !errors.Is(err, context.Canceled) { a.log.Warn(ctx, logs.GetUnableToHeadPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) - return nil } } else { object, err = a.remoteStorage.getObjectFromNode(ctx, addr, node) if err != nil && !errors.Is(err, context.Canceled) { a.log.Warn(ctx, logs.GetUnableToGetPartECObject, zap.String("node", hex.EncodeToString(node.PublicKey())), zap.Stringer("part_id", objID), zap.Error(err)) - return nil } } return object From d5d5ce2074d1a5ef60ebe04465c35f047dfdca15 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 5 Dec 2024 11:17:12 +0300 Subject: [PATCH 1071/1413] [#1541] morph/event: Simplify balance contract event parsing Signed-off-by: Evgenii Stratonikov --- pkg/morph/event/balance/lock.go | 68 +++++----------------------- pkg/morph/event/balance/lock_test.go | 3 +- 2 files changed, 13 insertions(+), 58 deletions(-) diff --git a/pkg/morph/event/balance/lock.go b/pkg/morph/event/balance/lock.go index 062a2a8864..99f80584aa 100644 --- a/pkg/morph/event/balance/lock.go +++ b/pkg/morph/event/balance/lock.go @@ -3,7 +3,7 @@ package balance import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/balance" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" @@ -47,61 +47,17 @@ func (l Lock) TxHash() util.Uint256 { return l.txHash } // ParseLock from notification into lock structure. func ParseLock(e *state.ContainedNotificationEvent) (event.Event, error) { - var ( - ev Lock - err error - ) - - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) + var le balance.LockEvent + if err := le.FromStackItem(e.Item); err != nil { + return nil, fmt.Errorf("parse balance.LockEvent: %w", err) } - if ln := len(params); ln != 5 { - return nil, event.WrongNumberOfParameters(5, ln) - } - - // parse id - ev.id, err = client.BytesFromStackItem(params[0]) - if err != nil { - return nil, fmt.Errorf("could not get lock id: %w", err) - } - - // parse user - user, err := client.BytesFromStackItem(params[1]) - if err != nil { - return nil, fmt.Errorf("could not get lock user value: %w", err) - } - - ev.user, err = util.Uint160DecodeBytesBE(user) - if err != nil { - return nil, fmt.Errorf("could not convert lock user value to uint160: %w", err) - } - - // parse lock account - lock, err := client.BytesFromStackItem(params[2]) - if err != nil { - return nil, fmt.Errorf("could not get lock account value: %w", err) - } - - ev.lock, err = util.Uint160DecodeBytesBE(lock) - if err != nil { - return nil, fmt.Errorf("could not convert lock account value to uint160: %w", err) - } - - // parse amount - ev.amount, err = client.IntFromStackItem(params[3]) - if err != nil { - return nil, fmt.Errorf("could not get lock amount: %w", err) - } - - // parse until deadline - ev.until, err = client.IntFromStackItem(params[4]) - if err != nil { - return nil, fmt.Errorf("could not get lock deadline: %w", err) - } - - ev.txHash = e.Container - - return ev, nil + return Lock{ + id: le.TxID, + user: le.From, + lock: le.To, + amount: le.Amount.Int64(), + until: le.Until.Int64(), + txHash: e.Container, + }, nil } diff --git a/pkg/morph/event/balance/lock_test.go b/pkg/morph/event/balance/lock_test.go index 9199bcd552..87b91aede4 100644 --- a/pkg/morph/event/balance/lock_test.go +++ b/pkg/morph/event/balance/lock_test.go @@ -4,7 +4,6 @@ import ( "math/big" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" @@ -28,7 +27,7 @@ func TestParseLock(t *testing.T) { } _, err := ParseLock(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(5, len(prms)).Error()) + require.Error(t, err) }) t.Run("wrong id parameter", func(t *testing.T) { From d5c46d812a641a93e299d468b0daa49aa2f9e323 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 5 Dec 2024 11:43:24 +0300 Subject: [PATCH 1072/1413] [#1541] go.mod: Update frostfs-contract New version contains more idiomatic types in the auto-generated code. Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c538a31789..7e7fa584e4 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1-0.20241205083807-762d7f9f9f08 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 diff --git a/go.sum b/go.sum index 064f3274e4..dec34ff6ec 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4 h1:o3iqVmbvFsfe8kpB2Hvuix6Q/tAhbiPLP91xK4lmoBQ= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.0-rc.4/go.mod h1:5fSm/l5xSjGWqsPUffSdboiGFUHa7y/1S0fvxzQowN8= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1-0.20241205083807-762d7f9f9f08 h1:tl1TT+zNk1lF/J5EaD3syDrTaYbQwvJKVOVENM4oQ+k= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1-0.20241205083807-762d7f9f9f08/go.mod h1:5fSm/l5xSjGWqsPUffSdboiGFUHa7y/1S0fvxzQowN8= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= From a353d45742e9ac48260a9d2f32b81c4b3c7c769c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 5 Dec 2024 11:52:30 +0300 Subject: [PATCH 1073/1413] [#1541] morph/event: Simplify container contract event parsing Signed-off-by: Evgenii Stratonikov --- pkg/morph/event/container/delete.go | 32 ++++++-------------- pkg/morph/event/container/delete_test.go | 3 +- pkg/morph/event/container/put.go | 37 ++++++------------------ pkg/morph/event/container/put_test.go | 28 +++++++++++++----- 4 files changed, 39 insertions(+), 61 deletions(-) diff --git a/pkg/morph/event/container/delete.go b/pkg/morph/event/container/delete.go index a206307f88..d28f6d5211 100644 --- a/pkg/morph/event/container/delete.go +++ b/pkg/morph/event/container/delete.go @@ -3,7 +3,7 @@ package container import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -58,28 +58,14 @@ func (DeleteSuccess) MorphEvent() {} // ParseDeleteSuccess decodes notification event thrown by Container contract into // DeleteSuccess and returns it as event.Event. func ParseDeleteSuccess(e *state.ContainedNotificationEvent) (event.Event, error) { - items, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("parse stack array from raw notification event: %w", err) + var dse container.DeleteSuccessEvent + if err := dse.FromStackItem(e.Item); err != nil { + return nil, fmt.Errorf("parse container.DeleteSuccessEvent: %w", err) } - const expectedItemNumDeleteSuccess = 1 - - if ln := len(items); ln != expectedItemNumDeleteSuccess { - return nil, event.WrongNumberOfParameters(expectedItemNumDeleteSuccess, ln) - } - - binID, err := client.BytesFromStackItem(items[0]) - if err != nil { - return nil, fmt.Errorf("parse container ID item: %w", err) - } - - var res DeleteSuccess - - err = res.ID.Decode(binID) - if err != nil { - return nil, fmt.Errorf("decode container ID: %w", err) - } - - return res, nil + var cnr cid.ID + cnr.SetSHA256(dse.ContainerID) + return DeleteSuccess{ + ID: cnr, + }, nil } diff --git a/pkg/morph/event/container/delete_test.go b/pkg/morph/event/container/delete_test.go index 627c5fcf56..62e7d7277c 100644 --- a/pkg/morph/event/container/delete_test.go +++ b/pkg/morph/event/container/delete_test.go @@ -4,7 +4,6 @@ import ( "crypto/sha256" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" @@ -18,7 +17,7 @@ func TestParseDeleteSuccess(t *testing.T) { } _, err := ParseDeleteSuccess(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error()) + require.Error(t, err) }) t.Run("wrong container parameter", func(t *testing.T) { diff --git a/pkg/morph/event/container/put.go b/pkg/morph/event/container/put.go index 335034bf35..b09394ba4c 100644 --- a/pkg/morph/event/container/put.go +++ b/pkg/morph/event/container/put.go @@ -3,7 +3,7 @@ package container import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -78,33 +78,14 @@ func (PutSuccess) MorphEvent() {} // ParsePutSuccess decodes notification event thrown by Container contract into // PutSuccess and returns it as event.Event. func ParsePutSuccess(e *state.ContainedNotificationEvent) (event.Event, error) { - items, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("parse stack array from raw notification event: %w", err) + var pse container.PutSuccessEvent + if err := pse.FromStackItem(e.Item); err != nil { + return nil, fmt.Errorf("parse container.PutSuccessEvent: %w", err) } - const expectedItemNumPutSuccess = 2 - - if ln := len(items); ln != expectedItemNumPutSuccess { - return nil, event.WrongNumberOfParameters(expectedItemNumPutSuccess, ln) - } - - binID, err := client.BytesFromStackItem(items[0]) - if err != nil { - return nil, fmt.Errorf("parse container ID item: %w", err) - } - - _, err = client.BytesFromStackItem(items[1]) - if err != nil { - return nil, fmt.Errorf("parse public key item: %w", err) - } - - var res PutSuccess - - err = res.ID.Decode(binID) - if err != nil { - return nil, fmt.Errorf("decode container ID: %w", err) - } - - return res, nil + var cnr cid.ID + cnr.SetSHA256(pse.ContainerID) + return PutSuccess{ + ID: cnr, + }, nil } diff --git a/pkg/morph/event/container/put_test.go b/pkg/morph/event/container/put_test.go index 3622f99430..dd5c7ea937 100644 --- a/pkg/morph/event/container/put_test.go +++ b/pkg/morph/event/container/put_test.go @@ -4,8 +4,8 @@ import ( "crypto/sha256" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) @@ -17,7 +17,7 @@ func TestParsePutSuccess(t *testing.T) { } _, err := ParsePutSuccess(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(2, len(prms)).Error()) + require.Error(t, err) }) t.Run("wrong container ID parameter", func(t *testing.T) { @@ -35,18 +35,30 @@ func TestParsePutSuccess(t *testing.T) { id.Encode(binID) t.Run("wrong public key parameter", func(t *testing.T) { - _, err := ParsePutSuccess(createNotifyEventFromItems([]stackitem.Item{ - stackitem.NewByteArray(binID), - stackitem.NewMap(), - })) + t.Run("wrong type", func(t *testing.T) { + _, err := ParsePutSuccess(createNotifyEventFromItems([]stackitem.Item{ + stackitem.NewByteArray(binID), + stackitem.NewMap(), + })) - require.Error(t, err) + require.Error(t, err) + }) + t.Run("garbage data", func(t *testing.T) { + _, err := ParsePutSuccess(createNotifyEventFromItems([]stackitem.Item{ + stackitem.NewByteArray(binID), + stackitem.NewByteArray([]byte("key")), + })) + require.Error(t, err) + }) }) t.Run("correct behavior", func(t *testing.T) { + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + ev, err := ParsePutSuccess(createNotifyEventFromItems([]stackitem.Item{ stackitem.NewByteArray(binID), - stackitem.NewByteArray([]byte("key")), + stackitem.NewByteArray(pk.PublicKey().Bytes()), })) require.NoError(t, err) From 1c12f23b841511b95efac32b62470a7b1e316fb3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 5 Dec 2024 11:58:38 +0300 Subject: [PATCH 1074/1413] [#1541] morph/event: Simplify netmap contract event parsing Signed-off-by: Evgenii Stratonikov --- pkg/morph/event/netmap/epoch.go | 21 +++++---------------- pkg/morph/event/netmap/epoch_test.go | 3 +-- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/pkg/morph/event/netmap/epoch.go b/pkg/morph/event/netmap/epoch.go index e454e2a6a8..4dcc0d0350 100644 --- a/pkg/morph/event/netmap/epoch.go +++ b/pkg/morph/event/netmap/epoch.go @@ -1,9 +1,7 @@ package netmap import ( - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" @@ -37,22 +35,13 @@ func (s NewEpoch) TxHash() util.Uint256 { // // Result is type of NewEpoch. func ParseNewEpoch(e *state.ContainedNotificationEvent) (event.Event, error) { - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) - } - - if ln := len(params); ln != 1 { - return nil, event.WrongNumberOfParameters(1, ln) - } - - prmEpochNum, err := client.IntFromStackItem(params[0]) - if err != nil { - return nil, fmt.Errorf("could not get integer epoch number: %w", err) + var nee netmap.NewEpochEvent + if err := nee.FromStackItem(e.Item); err != nil { + return nil, err } return NewEpoch{ - Num: uint64(prmEpochNum), + Num: uint64(nee.Epoch.Uint64()), Hash: e.Container, }, nil } diff --git a/pkg/morph/event/netmap/epoch_test.go b/pkg/morph/event/netmap/epoch_test.go index bc267ecb64..6ff6923272 100644 --- a/pkg/morph/event/netmap/epoch_test.go +++ b/pkg/morph/event/netmap/epoch_test.go @@ -4,7 +4,6 @@ import ( "math/big" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) @@ -17,7 +16,7 @@ func TestParseNewEpoch(t *testing.T) { } _, err := ParseNewEpoch(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error()) + require.Error(t, err) }) t.Run("wrong first parameter type", func(t *testing.T) { From d1bc4351c3d2904bedfad970d13c9bcde55e3d31 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 6 Dec 2024 13:59:15 +0300 Subject: [PATCH 1075/1413] [#1545] morph/event: Simplify frostfs contract event parsing Signed-off-by: Evgenii Stratonikov --- pkg/morph/event/frostfs/cheque.go | 59 ++++++------------------ pkg/morph/event/frostfs/cheque_test.go | 3 +- pkg/morph/event/frostfs/config.go | 44 ++++-------------- pkg/morph/event/frostfs/config_test.go | 3 +- pkg/morph/event/frostfs/deposit.go | 55 ++++------------------ pkg/morph/event/frostfs/deposit_test.go | 9 ++-- pkg/morph/event/frostfs/withdraw.go | 43 ++++------------- pkg/morph/event/frostfs/withdraw_test.go | 9 ++-- 8 files changed, 52 insertions(+), 173 deletions(-) diff --git a/pkg/morph/event/frostfs/cheque.go b/pkg/morph/event/frostfs/cheque.go index eae2a23f57..cf56464b80 100644 --- a/pkg/morph/event/frostfs/cheque.go +++ b/pkg/morph/event/frostfs/cheque.go @@ -3,7 +3,7 @@ package frostfs import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/frostfs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" @@ -34,53 +34,20 @@ func (c Cheque) LockAccount() util.Uint160 { return c.LockValue } // ParseCheque from notification into cheque structure. func ParseCheque(e *state.ContainedNotificationEvent) (event.Event, error) { - var ( - ev Cheque - err error - ) + var ce frostfs.ChequeEvent + if err := ce.FromStackItem(e.Item); err != nil { + return nil, fmt.Errorf("parse frostfs.ChequeEvent: %w", err) + } - params, err := event.ParseStackArray(e) + lock, err := util.Uint160DecodeBytesBE(ce.LockAccount) if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) + return nil, fmt.Errorf("parse frostfs.ChequeEvent: field LockAccount: %w", err) } - if ln := len(params); ln != 4 { - return nil, event.WrongNumberOfParameters(4, ln) - } - - // parse id - ev.IDValue, err = client.BytesFromStackItem(params[0]) - if err != nil { - return nil, fmt.Errorf("could not get cheque id: %w", err) - } - - // parse user - user, err := client.BytesFromStackItem(params[1]) - if err != nil { - return nil, fmt.Errorf("could not get cheque user: %w", err) - } - - ev.UserValue, err = util.Uint160DecodeBytesBE(user) - if err != nil { - return nil, fmt.Errorf("could not convert cheque user to uint160: %w", err) - } - - // parse amount - ev.AmountValue, err = client.IntFromStackItem(params[2]) - if err != nil { - return nil, fmt.Errorf("could not get cheque amount: %w", err) - } - - // parse lock account - lock, err := client.BytesFromStackItem(params[3]) - if err != nil { - return nil, fmt.Errorf("could not get cheque lock account: %w", err) - } - - ev.LockValue, err = util.Uint160DecodeBytesBE(lock) - if err != nil { - return nil, fmt.Errorf("could not convert cheque lock account to uint160: %w", err) - } - - return ev, nil + return Cheque{ + IDValue: ce.Id, + AmountValue: ce.Amount.Int64(), + UserValue: ce.User, + LockValue: lock, + }, nil } diff --git a/pkg/morph/event/frostfs/cheque_test.go b/pkg/morph/event/frostfs/cheque_test.go index ab177757f1..d92b7922b3 100644 --- a/pkg/morph/event/frostfs/cheque_test.go +++ b/pkg/morph/event/frostfs/cheque_test.go @@ -4,7 +4,6 @@ import ( "math/big" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" @@ -27,7 +26,7 @@ func TestParseCheque(t *testing.T) { } _, err := ParseCheque(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(4, len(prms)).Error()) + require.Error(t, err) }) t.Run("wrong id parameter", func(t *testing.T) { diff --git a/pkg/morph/event/frostfs/config.go b/pkg/morph/event/frostfs/config.go index 4c87634c22..805e80f3c9 100644 --- a/pkg/morph/event/frostfs/config.go +++ b/pkg/morph/event/frostfs/config.go @@ -3,7 +3,7 @@ package frostfs import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/frostfs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" @@ -36,39 +36,15 @@ func (u Config) Key() []byte { return u.KeyValue } func (u Config) Value() []byte { return u.ValueValue } func ParseConfig(e *state.ContainedNotificationEvent) (event.Event, error) { - var ( - ev Config - err error - ) - - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) + var sce frostfs.SetConfigEvent + if err := sce.FromStackItem(e.Item); err != nil { + return nil, fmt.Errorf("parse frostfs.SetConfigEvent: %w", err) } - if ln := len(params); ln != 3 { - return nil, event.WrongNumberOfParameters(3, ln) - } - - // parse id - ev.IDValue, err = client.BytesFromStackItem(params[0]) - if err != nil { - return nil, fmt.Errorf("could not get config update id: %w", err) - } - - // parse key - ev.KeyValue, err = client.BytesFromStackItem(params[1]) - if err != nil { - return nil, fmt.Errorf("could not get config key: %w", err) - } - - // parse value - ev.ValueValue, err = client.BytesFromStackItem(params[2]) - if err != nil { - return nil, fmt.Errorf("could not get config value: %w", err) - } - - ev.TxHashValue = e.Container - - return ev, nil + return Config{ + KeyValue: sce.Key, + ValueValue: sce.Value, + IDValue: sce.Id, + TxHashValue: e.Container, + }, nil } diff --git a/pkg/morph/event/frostfs/config_test.go b/pkg/morph/event/frostfs/config_test.go index dcd4201e45..8acc8c15ce 100644 --- a/pkg/morph/event/frostfs/config_test.go +++ b/pkg/morph/event/frostfs/config_test.go @@ -3,7 +3,6 @@ package frostfs import ( "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" ) @@ -21,7 +20,7 @@ func TestParseConfig(t *testing.T) { } _, err := ParseConfig(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(3, len(prms)).Error()) + require.Error(t, err) }) t.Run("wrong first parameter", func(t *testing.T) { diff --git a/pkg/morph/event/frostfs/deposit.go b/pkg/morph/event/frostfs/deposit.go index d8a3b82f03..fcb01577ed 100644 --- a/pkg/morph/event/frostfs/deposit.go +++ b/pkg/morph/event/frostfs/deposit.go @@ -3,7 +3,7 @@ package frostfs import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/frostfs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" @@ -34,50 +34,15 @@ func (d Deposit) Amount() int64 { return d.AmountValue } // ParseDeposit notification into deposit structure. func ParseDeposit(e *state.ContainedNotificationEvent) (event.Event, error) { - var ev Deposit - - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) + var de frostfs.DepositEvent + if err := de.FromStackItem(e.Item); err != nil { + return nil, fmt.Errorf("parse frostfs.DepositEvent: %w", err) } - if ln := len(params); ln != 4 { - return nil, event.WrongNumberOfParameters(4, ln) - } - - // parse from - from, err := client.BytesFromStackItem(params[0]) - if err != nil { - return nil, fmt.Errorf("could not get deposit sender: %w", err) - } - - ev.FromValue, err = util.Uint160DecodeBytesBE(from) - if err != nil { - return nil, fmt.Errorf("could not convert deposit sender to uint160: %w", err) - } - - // parse amount - ev.AmountValue, err = client.IntFromStackItem(params[1]) - if err != nil { - return nil, fmt.Errorf("could not get deposit amount: %w", err) - } - - // parse to - to, err := client.BytesFromStackItem(params[2]) - if err != nil { - return nil, fmt.Errorf("could not get deposit receiver: %w", err) - } - - ev.ToValue, err = util.Uint160DecodeBytesBE(to) - if err != nil { - return nil, fmt.Errorf("could not convert deposit receiver to uint160: %w", err) - } - - // parse id - ev.IDValue, err = client.BytesFromStackItem(params[3]) - if err != nil { - return nil, fmt.Errorf("could not get deposit id: %w", err) - } - - return ev, nil + return Deposit{ + IDValue: de.TxHash[:], + AmountValue: de.Amount.Int64(), + FromValue: de.From, + ToValue: de.Receiver, + }, nil } diff --git a/pkg/morph/event/frostfs/deposit_test.go b/pkg/morph/event/frostfs/deposit_test.go index f279a7f9c9..38d3e61f6a 100644 --- a/pkg/morph/event/frostfs/deposit_test.go +++ b/pkg/morph/event/frostfs/deposit_test.go @@ -4,7 +4,6 @@ import ( "math/big" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" @@ -12,7 +11,7 @@ import ( func TestParseDeposit(t *testing.T) { var ( - id = []byte("Hello World") + id = util.Uint256{0, 1, 2, 3} from = util.Uint160{0x1, 0x2, 0x3} to = util.Uint160{0x3, 0x2, 0x1} @@ -26,7 +25,7 @@ func TestParseDeposit(t *testing.T) { } _, err := ParseDeposit(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(4, len(prms)).Error()) + require.Error(t, err) }) t.Run("wrong from parameter", func(t *testing.T) { @@ -72,12 +71,12 @@ func TestParseDeposit(t *testing.T) { stackitem.NewByteArray(from.BytesBE()), stackitem.NewBigInteger(new(big.Int).SetInt64(amount)), stackitem.NewByteArray(to.BytesBE()), - stackitem.NewByteArray(id), + stackitem.NewByteArray(id[:]), })) require.NoError(t, err) require.Equal(t, Deposit{ - IDValue: id, + IDValue: id[:], AmountValue: amount, FromValue: from, ToValue: to, diff --git a/pkg/morph/event/frostfs/withdraw.go b/pkg/morph/event/frostfs/withdraw.go index f48067f864..2568b65127 100644 --- a/pkg/morph/event/frostfs/withdraw.go +++ b/pkg/morph/event/frostfs/withdraw.go @@ -3,7 +3,7 @@ package frostfs import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/frostfs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/util" @@ -30,39 +30,14 @@ func (w Withdraw) Amount() int64 { return w.AmountValue } // ParseWithdraw notification into withdraw structure. func ParseWithdraw(e *state.ContainedNotificationEvent) (event.Event, error) { - var ev Withdraw - - params, err := event.ParseStackArray(e) - if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) + var we frostfs.WithdrawEvent + if err := we.FromStackItem(e.Item); err != nil { + return nil, fmt.Errorf("parse frostfs.WithdrawEvent: %w", err) } - if ln := len(params); ln != 3 { - return nil, event.WrongNumberOfParameters(3, ln) - } - - // parse user - user, err := client.BytesFromStackItem(params[0]) - if err != nil { - return nil, fmt.Errorf("could not get withdraw user: %w", err) - } - - ev.UserValue, err = util.Uint160DecodeBytesBE(user) - if err != nil { - return nil, fmt.Errorf("could not convert withdraw user to uint160: %w", err) - } - - // parse amount - ev.AmountValue, err = client.IntFromStackItem(params[1]) - if err != nil { - return nil, fmt.Errorf("could not get withdraw amount: %w", err) - } - - // parse id - ev.IDValue, err = client.BytesFromStackItem(params[2]) - if err != nil { - return nil, fmt.Errorf("could not get withdraw id: %w", err) - } - - return ev, nil + return Withdraw{ + IDValue: we.TxHash[:], + AmountValue: we.Amount.Int64(), + UserValue: we.User, + }, nil } diff --git a/pkg/morph/event/frostfs/withdraw_test.go b/pkg/morph/event/frostfs/withdraw_test.go index 33435d19a5..e382305e61 100644 --- a/pkg/morph/event/frostfs/withdraw_test.go +++ b/pkg/morph/event/frostfs/withdraw_test.go @@ -4,7 +4,6 @@ import ( "math/big" "testing" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" @@ -12,7 +11,7 @@ import ( func TestParseWithdraw(t *testing.T) { var ( - id = []byte("Hello World") + id = util.Uint256{1, 2, 3} user = util.Uint160{0x1, 0x2, 0x3} amount int64 = 10 @@ -25,7 +24,7 @@ func TestParseWithdraw(t *testing.T) { } _, err := ParseWithdraw(createNotifyEventFromItems(prms)) - require.EqualError(t, err, event.WrongNumberOfParameters(3, len(prms)).Error()) + require.Error(t, err) }) t.Run("wrong user parameter", func(t *testing.T) { @@ -59,12 +58,12 @@ func TestParseWithdraw(t *testing.T) { ev, err := ParseWithdraw(createNotifyEventFromItems([]stackitem.Item{ stackitem.NewByteArray(user.BytesBE()), stackitem.NewBigInteger(new(big.Int).SetInt64(amount)), - stackitem.NewByteArray(id), + stackitem.NewByteArray(id[:]), })) require.NoError(t, err) require.Equal(t, Withdraw{ - IDValue: id, + IDValue: id[:], AmountValue: amount, UserValue: user, }, ev) From 7e542906ef9085a792e5ec5f7185bfdd9acecedb Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 6 Dec 2024 14:48:44 +0300 Subject: [PATCH 1076/1413] [#1539] go.mod: Bump `frostfs-sdk-go` version * Also fix placement unit-test in object manager Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- pkg/services/object_manager/placement/cache_test.go | 5 ++++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 7e7fa584e4..6ac37d3433 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241206094944-81c423e7094d git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 diff --git a/go.sum b/go.sum index dec34ff6ec..e084c2445a 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823 h1:sepm9FeuoInmygH1K/+3L+Yp5bJhGiVi/oGCH6Emp2c= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241107121119-cb813e27a823/go.mod h1:eoK7+KZQ9GJxbzIs6vTnoUJqFDppavInLRHaN4MYgZg= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241206094944-81c423e7094d h1:FpXI+mOrmJk3t2MKQFZuhLjCHDyDeo5rtP1WXl7gUWc= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241206094944-81c423e7094d/go.mod h1:eoK7+KZQ9GJxbzIs6vTnoUJqFDppavInLRHaN4MYgZg= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= diff --git a/pkg/services/object_manager/placement/cache_test.go b/pkg/services/object_manager/placement/cache_test.go index a890d53577..7242970b5a 100644 --- a/pkg/services/object_manager/placement/cache_test.go +++ b/pkg/services/object_manager/placement/cache_test.go @@ -85,7 +85,10 @@ func TestContainerNodesCache(t *testing.T) { }) t.Run("the error is propagated", func(t *testing.T) { var pp netmapSDK.PlacementPolicy - require.NoError(t, pp.DecodeString("REP 1 SELECT 1 FROM X FILTER ATTR EQ 42 AS X")) + r := netmapSDK.ReplicaDescriptor{} + r.SetNumberOfObjects(1) + r.SetSelectorName("Missing") + pp.AddReplicas(r) c := placement.NewContainerNodesCache(size) _, err := c.ContainerNodes(nm(1, nodes[0:1]), cidtest.ID(), pp) From ac0511d21423df1d191539f8272f962c23dfb62b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Dec 2024 16:52:46 +0300 Subject: [PATCH 1077/1413] [#1549] controlSvc: Drop deprecated EvacuateShard rpc Signed-off-by: Dmitrii Stepanov --- .../modules/control/evacuate_shard.go | 56 ------ cmd/frostfs-cli/modules/control/evacuation.go | 9 +- cmd/frostfs-cli/modules/control/shards.go | 2 - pkg/services/control/rpc.go | 14 -- pkg/services/control/server/evacuate.go | 188 ------------------ pkg/services/control/server/evacuate_async.go | 148 +++++++++++++- pkg/services/control/service.proto | 5 - pkg/services/control/service_grpc.pb.go | 43 ---- 8 files changed, 151 insertions(+), 314 deletions(-) delete mode 100644 cmd/frostfs-cli/modules/control/evacuate_shard.go delete mode 100644 pkg/services/control/server/evacuate.go diff --git a/cmd/frostfs-cli/modules/control/evacuate_shard.go b/cmd/frostfs-cli/modules/control/evacuate_shard.go deleted file mode 100644 index 1e48c1df42..0000000000 --- a/cmd/frostfs-cli/modules/control/evacuate_shard.go +++ /dev/null @@ -1,56 +0,0 @@ -package control - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" - commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" - "github.com/spf13/cobra" -) - -const ignoreErrorsFlag = "no-errors" - -var evacuateShardCmd = &cobra.Command{ - Use: "evacuate", - Short: "Evacuate objects from shard", - Long: "Evacuate objects from shard to other shards", - Run: evacuateShard, - Deprecated: "use frostfs-cli control shards evacuation start", -} - -func evacuateShard(cmd *cobra.Command, _ []string) { - pk := key.Get(cmd) - - req := &control.EvacuateShardRequest{Body: new(control.EvacuateShardRequest_Body)} - req.Body.Shard_ID = getShardIDList(cmd) - req.Body.IgnoreErrors, _ = cmd.Flags().GetBool(ignoreErrorsFlag) - - signRequest(cmd, pk, req) - - cli := getClient(cmd, pk) - - var resp *control.EvacuateShardResponse - var err error - err = cli.ExecRaw(func(client *client.Client) error { - resp, err = control.EvacuateShard(client, req) - return err - }) - commonCmd.ExitOnErr(cmd, "rpc error: %w", err) - - cmd.Printf("Objects moved: %d\n", resp.GetBody().GetCount()) - - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) - - cmd.Println("Shard has successfully been evacuated.") -} - -func initControlEvacuateShardCmd() { - initControlFlags(evacuateShardCmd) - - flags := evacuateShardCmd.Flags() - flags.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding") - flags.Bool(shardAllFlag, false, "Process all shards") - flags.Bool(ignoreErrorsFlag, false, "Skip invalid/unreadable objects") - - evacuateShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag) -} diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 73700e56de..8032bf09a9 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -17,10 +17,11 @@ import ( ) const ( - awaitFlag = "await" - noProgressFlag = "no-progress" - scopeFlag = "scope" - repOneOnlyFlag = "rep-one-only" + awaitFlag = "await" + noProgressFlag = "no-progress" + scopeFlag = "scope" + repOneOnlyFlag = "rep-one-only" + ignoreErrorsFlag = "no-errors" containerWorkerCountFlag = "container-worker-count" objectWorkerCountFlag = "object-worker-count" diff --git a/cmd/frostfs-cli/modules/control/shards.go b/cmd/frostfs-cli/modules/control/shards.go index 329cb91006..3483f5d62d 100644 --- a/cmd/frostfs-cli/modules/control/shards.go +++ b/cmd/frostfs-cli/modules/control/shards.go @@ -13,7 +13,6 @@ var shardsCmd = &cobra.Command{ func initControlShardsCmd() { shardsCmd.AddCommand(listShardsCmd) shardsCmd.AddCommand(setShardModeCmd) - shardsCmd.AddCommand(evacuateShardCmd) shardsCmd.AddCommand(evacuationShardCmd) shardsCmd.AddCommand(flushCacheCmd) shardsCmd.AddCommand(doctorCmd) @@ -23,7 +22,6 @@ func initControlShardsCmd() { initControlShardsListCmd() initControlSetShardModeCmd() - initControlEvacuateShardCmd() initControlEvacuationShardCmd() initControlFlushCacheCmd() initControlDoctorCmd() diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 514061db4e..6982d780db 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -15,7 +15,6 @@ const ( rpcListShards = "ListShards" rpcSetShardMode = "SetShardMode" rpcSynchronizeTree = "SynchronizeTree" - rpcEvacuateShard = "EvacuateShard" rpcStartShardEvacuation = "StartShardEvacuation" rpcGetShardEvacuationStatus = "GetShardEvacuationStatus" rpcResetShardEvacuationStatus = "ResetShardEvacuationStatus" @@ -162,19 +161,6 @@ func SynchronizeTree(cli *client.Client, req *SynchronizeTreeRequest, opts ...cl return wResp.message, nil } -// EvacuateShard executes ControlService.EvacuateShard RPC. -func EvacuateShard(cli *client.Client, req *EvacuateShardRequest, opts ...client.CallOption) (*EvacuateShardResponse, error) { - wResp := newResponseWrapper[EvacuateShardResponse]() - wReq := &requestWrapper{m: req} - - err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcEvacuateShard), wReq, wResp, opts...) - if err != nil { - return nil, err - } - - return wResp.message, nil -} - // StartShardEvacuation executes ControlService.StartShardEvacuation RPC. func StartShardEvacuation(cli *client.Client, req *StartShardEvacuationRequest, opts ...client.CallOption) (*StartShardEvacuationResponse, error) { wResp := newResponseWrapper[StartShardEvacuationResponse]() diff --git a/pkg/services/control/server/evacuate.go b/pkg/services/control/server/evacuate.go deleted file mode 100644 index ae34133735..0000000000 --- a/pkg/services/control/server/evacuate.go +++ /dev/null @@ -1,188 +0,0 @@ -package control - -import ( - "bytes" - "context" - "crypto/sha256" - "encoding/hex" - "errors" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -var errFailedToBuildListOfContainerNodes = errors.New("can't build a list of container nodes") - -func (s *Server) EvacuateShard(ctx context.Context, req *control.EvacuateShardRequest) (*control.EvacuateShardResponse, error) { - err := s.isValidRequest(req) - if err != nil { - return nil, status.Error(codes.PermissionDenied, err.Error()) - } - - prm := engine.EvacuateShardPrm{ - ShardID: s.getShardIDList(req.GetBody().GetShard_ID()), - IgnoreErrors: req.GetBody().GetIgnoreErrors(), - ObjectsHandler: s.replicateObject, - Scope: engine.EvacuateScopeObjects, - } - - res, err := s.s.Evacuate(ctx, prm) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - - resp := &control.EvacuateShardResponse{ - Body: &control.EvacuateShardResponse_Body{ - Count: uint32(res.ObjectsEvacuated()), - }, - } - - err = ctrlmessage.Sign(s.key, resp) - if err != nil { - return nil, status.Error(codes.Internal, err.Error()) - } - return resp, nil -} - -func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *objectSDK.Object) (bool, error) { - cid, ok := obj.ContainerID() - if !ok { - // Return nil to prevent situations where a shard can't be evacuated - // because of a single bad/corrupted object. - return false, nil - } - - nodes, err := s.getContainerNodes(cid) - if err != nil { - return false, err - } - - if len(nodes) == 0 { - return false, nil - } - - var res replicatorResult - task := replicator.Task{ - NumCopies: 1, - Addr: addr, - Obj: obj, - Nodes: nodes, - } - s.replicator.HandleReplicationTask(ctx, task, &res) - - if res.count == 0 { - return false, errors.New("object was not replicated") - } - return true, nil -} - -func (s *Server) replicateTree(ctx context.Context, contID cid.ID, treeID string, forest pilorama.Forest) (bool, string, error) { - nodes, err := s.getContainerNodes(contID) - if err != nil { - return false, "", err - } - if len(nodes) == 0 { - return false, "", nil - } - - for _, node := range nodes { - err = s.replicateTreeToNode(ctx, forest, contID, treeID, node) - if err == nil { - return true, hex.EncodeToString(node.PublicKey()), nil - } - } - return false, "", err -} - -func (s *Server) replicateTreeToNode(ctx context.Context, forest pilorama.Forest, contID cid.ID, treeID string, node netmap.NodeInfo) error { - rawCID := make([]byte, sha256.Size) - contID.Encode(rawCID) - - var height uint64 - for { - op, err := forest.TreeGetOpLog(ctx, contID, treeID, height) - if err != nil { - return err - } - - if op.Time == 0 { - return nil - } - - req := &tree.ApplyRequest{ - Body: &tree.ApplyRequest_Body{ - ContainerId: rawCID, - TreeId: treeID, - Operation: &tree.LogMove{ - ParentId: op.Parent, - Meta: op.Meta.Bytes(), - ChildId: op.Child, - }, - }, - } - - err = tree.SignMessage(req, s.key) - if err != nil { - return fmt.Errorf("can't message apply request: %w", err) - } - - err = s.treeService.ReplicateTreeOp(ctx, node, req) - if err != nil { - return err - } - - height = op.Time + 1 - } -} - -func (s *Server) getContainerNodes(contID cid.ID) ([]netmap.NodeInfo, error) { - nm, err := s.netMapSrc.GetNetMap(0) - if err != nil { - return nil, err - } - - c, err := s.cnrSrc.Get(contID) - if err != nil { - return nil, err - } - - binCnr := make([]byte, sha256.Size) - contID.Encode(binCnr) - - ns, err := nm.ContainerNodes(c.Value.PlacementPolicy(), binCnr) - if err != nil { - return nil, errFailedToBuildListOfContainerNodes - } - - nodes := placement.FlattenNodes(ns) - bs := (*keys.PublicKey)(&s.key.PublicKey).Bytes() - for i := 0; i < len(nodes); i++ { // don't use range, slice mutates in body - if bytes.Equal(nodes[i].PublicKey(), bs) { - copy(nodes[i:], nodes[i+1:]) - nodes = nodes[:len(nodes)-1] - } - } - return nodes, nil -} - -type replicatorResult struct { - count int -} - -// SubmitSuccessfulReplication implements the replicator.TaskResult interface. -func (r *replicatorResult) SubmitSuccessfulReplication(_ netmap.NodeInfo) { - r.count++ -} diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index 146ac7e16e..04465eb266 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -1,17 +1,32 @@ package control import ( + "bytes" "context" + "crypto/sha256" + "encoding/hex" "errors" + "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) +var errFailedToBuildListOfContainerNodes = errors.New("can't build a list of container nodes") + func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartShardEvacuationRequest) (*control.StartShardEvacuationResponse, error) { err := s.isValidRequest(req) if err != nil { @@ -34,8 +49,7 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha RepOneOnly: req.GetBody().GetRepOneOnly(), } - _, err = s.s.Evacuate(ctx, prm) - if err != nil { + if err = s.s.Evacuate(ctx, prm); err != nil { var logicalErr logicerr.Logical if errors.As(err, &logicalErr) { return nil, status.Error(codes.Aborted, err.Error()) @@ -135,3 +149,133 @@ func (s *Server) ResetShardEvacuationStatus(ctx context.Context, req *control.Re } return resp, nil } + +func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *objectSDK.Object) (bool, error) { + cid, ok := obj.ContainerID() + if !ok { + // Return nil to prevent situations where a shard can't be evacuated + // because of a single bad/corrupted object. + return false, nil + } + + nodes, err := s.getContainerNodes(cid) + if err != nil { + return false, err + } + + if len(nodes) == 0 { + return false, nil + } + + var res replicatorResult + task := replicator.Task{ + NumCopies: 1, + Addr: addr, + Obj: obj, + Nodes: nodes, + } + s.replicator.HandleReplicationTask(ctx, task, &res) + + if res.count == 0 { + return false, errors.New("object was not replicated") + } + return true, nil +} + +func (s *Server) replicateTree(ctx context.Context, contID cid.ID, treeID string, forest pilorama.Forest) (bool, string, error) { + nodes, err := s.getContainerNodes(contID) + if err != nil { + return false, "", err + } + if len(nodes) == 0 { + return false, "", nil + } + + for _, node := range nodes { + err = s.replicateTreeToNode(ctx, forest, contID, treeID, node) + if err == nil { + return true, hex.EncodeToString(node.PublicKey()), nil + } + } + return false, "", err +} + +func (s *Server) replicateTreeToNode(ctx context.Context, forest pilorama.Forest, contID cid.ID, treeID string, node netmap.NodeInfo) error { + rawCID := make([]byte, sha256.Size) + contID.Encode(rawCID) + + var height uint64 + for { + op, err := forest.TreeGetOpLog(ctx, contID, treeID, height) + if err != nil { + return err + } + + if op.Time == 0 { + return nil + } + + req := &tree.ApplyRequest{ + Body: &tree.ApplyRequest_Body{ + ContainerId: rawCID, + TreeId: treeID, + Operation: &tree.LogMove{ + ParentId: op.Parent, + Meta: op.Meta.Bytes(), + ChildId: op.Child, + }, + }, + } + + err = tree.SignMessage(req, s.key) + if err != nil { + return fmt.Errorf("can't message apply request: %w", err) + } + + err = s.treeService.ReplicateTreeOp(ctx, node, req) + if err != nil { + return err + } + + height = op.Time + 1 + } +} + +func (s *Server) getContainerNodes(contID cid.ID) ([]netmap.NodeInfo, error) { + nm, err := s.netMapSrc.GetNetMap(0) + if err != nil { + return nil, err + } + + c, err := s.cnrSrc.Get(contID) + if err != nil { + return nil, err + } + + binCnr := make([]byte, sha256.Size) + contID.Encode(binCnr) + + ns, err := nm.ContainerNodes(c.Value.PlacementPolicy(), binCnr) + if err != nil { + return nil, errFailedToBuildListOfContainerNodes + } + + nodes := placement.FlattenNodes(ns) + bs := (*keys.PublicKey)(&s.key.PublicKey).Bytes() + for i := 0; i < len(nodes); i++ { // don't use range, slice mutates in body + if bytes.Equal(nodes[i].PublicKey(), bs) { + copy(nodes[i:], nodes[i+1:]) + nodes = nodes[:len(nodes)-1] + } + } + return nodes, nil +} + +type replicatorResult struct { + count int +} + +// SubmitSuccessfulReplication implements the replicator.TaskResult interface. +func (r *replicatorResult) SubmitSuccessfulReplication(_ netmap.NodeInfo) { + r.count++ +} diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index ae1939e137..97ecf9a8cd 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -30,11 +30,6 @@ service ControlService { // Synchronizes all log operations for the specified tree. rpc SynchronizeTree(SynchronizeTreeRequest) returns (SynchronizeTreeResponse); - // EvacuateShard moves all data from one shard to the others. - // Deprecated: Use - // StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation - rpc EvacuateShard(EvacuateShardRequest) returns (EvacuateShardResponse); - // StartShardEvacuation starts moving all data from one shard to the others. rpc StartShardEvacuation(StartShardEvacuationRequest) returns (StartShardEvacuationResponse); diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index f5cfefa857..987e08c59e 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -26,7 +26,6 @@ const ( ControlService_ListShards_FullMethodName = "/control.ControlService/ListShards" ControlService_SetShardMode_FullMethodName = "/control.ControlService/SetShardMode" ControlService_SynchronizeTree_FullMethodName = "/control.ControlService/SynchronizeTree" - ControlService_EvacuateShard_FullMethodName = "/control.ControlService/EvacuateShard" ControlService_StartShardEvacuation_FullMethodName = "/control.ControlService/StartShardEvacuation" ControlService_GetShardEvacuationStatus_FullMethodName = "/control.ControlService/GetShardEvacuationStatus" ControlService_ResetShardEvacuationStatus_FullMethodName = "/control.ControlService/ResetShardEvacuationStatus" @@ -62,10 +61,6 @@ type ControlServiceClient interface { SetShardMode(ctx context.Context, in *SetShardModeRequest, opts ...grpc.CallOption) (*SetShardModeResponse, error) // Synchronizes all log operations for the specified tree. SynchronizeTree(ctx context.Context, in *SynchronizeTreeRequest, opts ...grpc.CallOption) (*SynchronizeTreeResponse, error) - // EvacuateShard moves all data from one shard to the others. - // Deprecated: Use - // StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation - EvacuateShard(ctx context.Context, in *EvacuateShardRequest, opts ...grpc.CallOption) (*EvacuateShardResponse, error) // StartShardEvacuation starts moving all data from one shard to the others. StartShardEvacuation(ctx context.Context, in *StartShardEvacuationRequest, opts ...grpc.CallOption) (*StartShardEvacuationResponse, error) // GetShardEvacuationStatus returns evacuation status. @@ -173,15 +168,6 @@ func (c *controlServiceClient) SynchronizeTree(ctx context.Context, in *Synchron return out, nil } -func (c *controlServiceClient) EvacuateShard(ctx context.Context, in *EvacuateShardRequest, opts ...grpc.CallOption) (*EvacuateShardResponse, error) { - out := new(EvacuateShardResponse) - err := c.cc.Invoke(ctx, ControlService_EvacuateShard_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *controlServiceClient) StartShardEvacuation(ctx context.Context, in *StartShardEvacuationRequest, opts ...grpc.CallOption) (*StartShardEvacuationResponse, error) { out := new(StartShardEvacuationResponse) err := c.cc.Invoke(ctx, ControlService_StartShardEvacuation_FullMethodName, in, out, opts...) @@ -335,10 +321,6 @@ type ControlServiceServer interface { SetShardMode(context.Context, *SetShardModeRequest) (*SetShardModeResponse, error) // Synchronizes all log operations for the specified tree. SynchronizeTree(context.Context, *SynchronizeTreeRequest) (*SynchronizeTreeResponse, error) - // EvacuateShard moves all data from one shard to the others. - // Deprecated: Use - // StartShardEvacuation/GetShardEvacuationStatus/StopShardEvacuation - EvacuateShard(context.Context, *EvacuateShardRequest) (*EvacuateShardResponse, error) // StartShardEvacuation starts moving all data from one shard to the others. StartShardEvacuation(context.Context, *StartShardEvacuationRequest) (*StartShardEvacuationResponse, error) // GetShardEvacuationStatus returns evacuation status. @@ -400,9 +382,6 @@ func (UnimplementedControlServiceServer) SetShardMode(context.Context, *SetShard func (UnimplementedControlServiceServer) SynchronizeTree(context.Context, *SynchronizeTreeRequest) (*SynchronizeTreeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SynchronizeTree not implemented") } -func (UnimplementedControlServiceServer) EvacuateShard(context.Context, *EvacuateShardRequest) (*EvacuateShardResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method EvacuateShard not implemented") -} func (UnimplementedControlServiceServer) StartShardEvacuation(context.Context, *StartShardEvacuationRequest) (*StartShardEvacuationResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method StartShardEvacuation not implemented") } @@ -586,24 +565,6 @@ func _ControlService_SynchronizeTree_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } -func _ControlService_EvacuateShard_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(EvacuateShardRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(ControlServiceServer).EvacuateShard(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: ControlService_EvacuateShard_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ControlServiceServer).EvacuateShard(ctx, req.(*EvacuateShardRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _ControlService_StartShardEvacuation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(StartShardEvacuationRequest) if err := dec(in); err != nil { @@ -909,10 +870,6 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "SynchronizeTree", Handler: _ControlService_SynchronizeTree_Handler, }, - { - MethodName: "EvacuateShard", - Handler: _ControlService_EvacuateShard_Handler, - }, { MethodName: "StartShardEvacuation", Handler: _ControlService_StartShardEvacuation_Handler, From 41da27dad51b2906b15157c0e3dc4e87c991da02 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Dec 2024 16:53:19 +0300 Subject: [PATCH 1078/1413] [#1549] engine: Drop Async flag from evacuation parameters Now it is only async evacuation. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate.go | 30 ++-- .../engine/evacuate_test.go | 130 +++++++++--------- pkg/services/control/server/evacuate_async.go | 1 - 3 files changed, 74 insertions(+), 87 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index b88c249b1c..2e0344bfbc 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -86,7 +86,6 @@ type EvacuateShardPrm struct { ObjectsHandler func(context.Context, oid.Address, *objectSDK.Object) (bool, error) TreeHandler func(context.Context, cid.ID, string, pilorama.Forest) (bool, string, error) IgnoreErrors bool - Async bool Scope EvacuateScope RepOneOnly bool @@ -211,10 +210,10 @@ var errMustHaveTwoShards = errors.New("must have at least 1 spare shard") // Evacuate moves data from one shard to the others. // The shard being moved must be in read-only mode. -func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*EvacuateShardRes, error) { +func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) error { select { case <-ctx.Done(): - return nil, ctx.Err() + return ctx.Err() default: } @@ -226,7 +225,6 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Evacuate", trace.WithAttributes( attribute.StringSlice("shardIDs", shardIDs), - attribute.Bool("async", prm.Async), attribute.Bool("ignoreErrors", prm.IgnoreErrors), attribute.Stringer("scope", prm.Scope), )) @@ -234,7 +232,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev shards, err := e.getActualShards(shardIDs, prm) if err != nil { - return nil, err + return err } shardsToEvacuate := make(map[string]*shard.Shard) @@ -247,10 +245,10 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev } res := NewEvacuateShardRes() - ctx = ctxOrBackground(ctx, prm.Async) - eg, egCtx, err := e.evacuateLimiter.TryStart(ctx, shardIDs, res) + ctx = context.WithoutCancel(ctx) + eg, ctx, err := e.evacuateLimiter.TryStart(ctx, shardIDs, res) if err != nil { - return nil, err + return err } var mtx sync.RWMutex @@ -262,21 +260,10 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) (*Ev return t } eg.Go(func() error { - return e.evacuateShards(egCtx, shardIDs, prm, res, copyShards, shardsToEvacuate) + return e.evacuateShards(ctx, shardIDs, prm, res, copyShards, shardsToEvacuate) }) - if prm.Async { - return nil, nil - } - - return res, eg.Wait() -} - -func ctxOrBackground(ctx context.Context, background bool) context.Context { - if background { - return context.Background() - } - return ctx + return nil } func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, prm EvacuateShardPrm, res *EvacuateShardRes, @@ -286,7 +273,6 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShards", trace.WithAttributes( attribute.StringSlice("shardIDs", shardIDs), - attribute.Bool("async", prm.Async), attribute.Bool("ignoreErrors", prm.IgnoreErrors), attribute.Stringer("scope", prm.Scope), attribute.Bool("repOneOnly", prm.RepOneOnly), diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index beab8384e3..248c391556 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -140,16 +140,17 @@ func TestEvacuateShardObjects(t *testing.T) { prm.Scope = EvacuateScopeObjects t.Run("must be read-only", func(t *testing.T) { - res, err := e.Evacuate(context.Background(), prm) + err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, ErrMustBeReadOnly) - require.Equal(t, uint64(0), res.ObjectsEvacuated()) }) require.NoError(t, e.shards[evacuateShardID].SetMode(context.Background(), mode.ReadOnly)) - res, err := e.Evacuate(context.Background(), prm) + err := e.Evacuate(context.Background(), prm) require.NoError(t, err) - require.Equal(t, uint64(objPerShard), res.ObjectsEvacuated()) + st := testWaitForEvacuationCompleted(t, e) + require.Equal(t, st.ErrorMessage(), "") + require.Equal(t, uint64(objPerShard), st.ObjectsEvacuated()) // We check that all objects are available both before and after shard removal. // First case is a real-world use-case. It ensures that an object can be put in presense @@ -186,9 +187,10 @@ func TestEvacuateShardObjects(t *testing.T) { } // Calling it again is OK, but all objects are already moved, so no new PUTs should be done. - res, err = e.Evacuate(context.Background(), prm) - require.NoError(t, err) - require.Equal(t, uint64(0), res.ObjectsEvacuated()) + require.NoError(t, e.Evacuate(context.Background(), prm)) + st = testWaitForEvacuationCompleted(t, e) + require.Equal(t, st.ErrorMessage(), "") + require.Equal(t, uint64(0), st.ObjectsEvacuated()) checkHasObjects(t) @@ -200,6 +202,17 @@ func TestEvacuateShardObjects(t *testing.T) { checkHasObjects(t) } +func testWaitForEvacuationCompleted(t *testing.T, e *StorageEngine) *EvacuationState { + var st *EvacuationState + var err error + require.Eventually(t, func() bool { + st, err = e.GetEvacuationState(context.Background()) + require.NoError(t, err) + return st.ProcessingStatus() == EvacuateProcessStateCompleted + }, 3*time.Second, 10*time.Millisecond) + return st +} + func TestEvacuateObjectsNetwork(t *testing.T) { t.Parallel() @@ -242,15 +255,15 @@ func TestEvacuateObjectsNetwork(t *testing.T) { prm.ShardID = ids[0:1] prm.Scope = EvacuateScopeObjects - res, err := e.Evacuate(context.Background(), prm) + err := e.Evacuate(context.Background(), prm) require.ErrorIs(t, err, errMustHaveTwoShards) - require.Equal(t, uint64(0), res.ObjectsEvacuated()) prm.ObjectsHandler = acceptOneOf(objects, 2) - res, err = e.Evacuate(context.Background(), prm) - require.ErrorIs(t, err, errReplication) - require.Equal(t, uint64(2), res.ObjectsEvacuated()) + require.NoError(t, e.Evacuate(context.Background(), prm)) + st := testWaitForEvacuationCompleted(t, e) + require.Contains(t, st.ErrorMessage(), errReplication.Error()) + require.Equal(t, uint64(2), st.ObjectsEvacuated()) }) t.Run("multiple shards, evacuate one", func(t *testing.T) { t.Parallel() @@ -267,16 +280,18 @@ func TestEvacuateObjectsNetwork(t *testing.T) { prm.ObjectsHandler = acceptOneOf(objects, 2) prm.Scope = EvacuateScopeObjects - res, err := e.Evacuate(context.Background(), prm) - require.ErrorIs(t, err, errReplication) - require.Equal(t, uint64(2), res.ObjectsEvacuated()) + require.NoError(t, e.Evacuate(context.Background(), prm)) + st := testWaitForEvacuationCompleted(t, e) + require.Contains(t, st.ErrorMessage(), errReplication.Error()) + require.Equal(t, uint64(2), st.ObjectsEvacuated()) t.Run("no errors", func(t *testing.T) { prm.ObjectsHandler = acceptOneOf(objects, 3) - res, err := e.Evacuate(context.Background(), prm) - require.NoError(t, err) - require.Equal(t, uint64(3), res.ObjectsEvacuated()) + require.NoError(t, e.Evacuate(context.Background(), prm)) + st := testWaitForEvacuationCompleted(t, e) + require.Equal(t, st.ErrorMessage(), "") + require.Equal(t, uint64(3), st.ObjectsEvacuated()) }) }) t.Run("multiple shards, evacuate many", func(t *testing.T) { @@ -305,16 +320,18 @@ func TestEvacuateObjectsNetwork(t *testing.T) { prm.ObjectsHandler = acceptOneOf(objects, totalCount-1) prm.Scope = EvacuateScopeObjects - res, err := e.Evacuate(context.Background(), prm) - require.ErrorIs(t, err, errReplication) - require.Equal(t, totalCount-1, res.ObjectsEvacuated()) + require.NoError(t, e.Evacuate(context.Background(), prm)) + st := testWaitForEvacuationCompleted(t, e) + require.Contains(t, st.ErrorMessage(), errReplication.Error()) + require.Equal(t, totalCount-1, st.ObjectsEvacuated()) t.Run("no errors", func(t *testing.T) { prm.ObjectsHandler = acceptOneOf(objects, totalCount) - res, err := e.Evacuate(context.Background(), prm) - require.NoError(t, err) - require.Equal(t, totalCount, res.ObjectsEvacuated()) + require.NoError(t, e.Evacuate(context.Background(), prm)) + st := testWaitForEvacuationCompleted(t, e) + require.Equal(t, st.ErrorMessage(), "") + require.Equal(t, totalCount, st.ObjectsEvacuated()) }) }) } @@ -344,9 +361,8 @@ func TestEvacuateCancellation(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) cancel() - res, err := e.Evacuate(ctx, prm) + err := e.Evacuate(ctx, prm) require.ErrorContains(t, err, "context canceled") - require.Equal(t, uint64(0), res.ObjectsEvacuated()) } func TestEvacuateCancellationByError(t *testing.T) { @@ -375,8 +391,9 @@ func TestEvacuateCancellationByError(t *testing.T) { prm.ObjectWorkerCount = 2 prm.ContainerWorkerCount = 2 - _, err := e.Evacuate(context.Background(), prm) - require.ErrorContains(t, err, "test error") + require.NoError(t, e.Evacuate(context.Background(), prm)) + st := testWaitForEvacuationCompleted(t, e) + require.Contains(t, st.ErrorMessage(), "test error") } func TestEvacuateSingleProcess(t *testing.T) { @@ -406,20 +423,19 @@ func TestEvacuateSingleProcess(t *testing.T) { eg, egCtx := errgroup.WithContext(context.Background()) eg.Go(func() error { - res, err := e.Evacuate(egCtx, prm) - require.NoError(t, err, "first evacuation failed") - require.Equal(t, uint64(3), res.ObjectsEvacuated()) + require.NoError(t, e.Evacuate(egCtx, prm), "first evacuation failed") return nil }) eg.Go(func() error { <-running - res, err := e.Evacuate(egCtx, prm) - require.ErrorContains(t, err, "evacuate is already running for shard ids", "second evacuation not failed") - require.Equal(t, uint64(0), res.ObjectsEvacuated()) + require.ErrorContains(t, e.Evacuate(egCtx, prm), "evacuate is already running for shard ids", "second evacuation not failed") close(blocker) return nil }) require.NoError(t, eg.Wait()) + st := testWaitForEvacuationCompleted(t, e) + require.Equal(t, uint64(3), st.ObjectsEvacuated()) + require.Equal(t, st.ErrorMessage(), "") } func TestEvacuateObjectsAsync(t *testing.T) { @@ -458,9 +474,9 @@ func TestEvacuateObjectsAsync(t *testing.T) { eg, egCtx := errgroup.WithContext(context.Background()) eg.Go(func() error { - res, err := e.Evacuate(egCtx, prm) - require.NoError(t, err, "first evacuation failed") - require.Equal(t, uint64(3), res.ObjectsEvacuated()) + require.NoError(t, e.Evacuate(egCtx, prm), "first evacuation failed") + st = testWaitForEvacuationCompleted(t, e) + require.Equal(t, uint64(3), st.ObjectsEvacuated(), "invalid final count") return nil }) @@ -483,12 +499,7 @@ func TestEvacuateObjectsAsync(t *testing.T) { close(blocker) - require.Eventually(t, func() bool { - st, err = e.GetEvacuationState(context.Background()) - return st.ProcessingStatus() == EvacuateProcessStateCompleted - }, 3*time.Second, 10*time.Millisecond, "invalid final state") - - require.NoError(t, err, "get final state failed") + st = testWaitForEvacuationCompleted(t, e) require.Equal(t, uint64(3), st.ObjectsEvacuated(), "invalid final count") require.NotNil(t, st.StartedAt(), "invalid final started at") require.NotNil(t, st.FinishedAt(), "invalid final finished at") @@ -534,14 +545,9 @@ func TestEvacuateTreesLocal(t *testing.T) { require.ElementsMatch(t, []string{}, st.ShardIDs(), "invalid init shard ids") require.Equal(t, "", st.ErrorMessage(), "invalid init error message") - res, err := e.Evacuate(context.Background(), prm) - require.NotNil(t, res, "sync evacuation result must be not nil") - require.NoError(t, err, "evacuation failed") - - st, err = e.GetEvacuationState(context.Background()) - require.NoError(t, err, "get evacuation state failed") - require.Equal(t, EvacuateProcessStateCompleted, st.ProcessingStatus()) + require.NoError(t, e.Evacuate(context.Background(), prm), "evacuation failed") + st = testWaitForEvacuationCompleted(t, e) require.Equal(t, uint64(3), st.TreesTotal(), "invalid trees total count") require.Equal(t, uint64(3), st.TreesEvacuated(), "invalid trees evacuated count") require.Equal(t, uint64(0), st.TreesFailed(), "invalid trees failed count") @@ -632,15 +638,9 @@ func TestEvacuateTreesRemote(t *testing.T) { require.ElementsMatch(t, []string{}, st.ShardIDs(), "invalid init shard ids") require.Equal(t, "", st.ErrorMessage(), "invalid init error message") - res, err := e.Evacuate(context.Background(), prm) - require.NotNil(t, res, "sync evacuation must return not nil") - require.NoError(t, err, "evacuation failed") + require.NoError(t, e.Evacuate(context.Background(), prm), "evacuation failed") + st = testWaitForEvacuationCompleted(t, e) - st, err = e.GetEvacuationState(context.Background()) - require.NoError(t, err, "get evacuation state failed") - require.Equal(t, EvacuateProcessStateCompleted, st.ProcessingStatus()) - - require.NoError(t, err, "get final state failed") require.Equal(t, uint64(6), st.TreesTotal(), "invalid trees total count") require.Equal(t, uint64(6), st.TreesEvacuated(), "invalid trees evacuated count") require.Equal(t, uint64(0), st.TreesFailed(), "invalid trees failed count") @@ -754,11 +754,12 @@ func TestEvacuateShardObjectsRepOneOnly(t *testing.T) { require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) - res, err := e.Evacuate(context.Background(), prm) - require.NoError(t, err) - require.Equal(t, uint64(4), res.ObjectsEvacuated()) - require.Equal(t, uint64(8), res.ObjectsSkipped()) - require.Equal(t, uint64(0), res.ObjectsFailed()) + require.NoError(t, e.Evacuate(context.Background(), prm)) + st := testWaitForEvacuationCompleted(t, e) + require.Equal(t, "", st.ErrorMessage()) + require.Equal(t, uint64(4), st.ObjectsEvacuated()) + require.Equal(t, uint64(8), st.ObjectsSkipped()) + require.Equal(t, uint64(0), st.ObjectsFailed()) } func TestEvacuateShardObjectsRepOneOnlyBench(t *testing.T) { @@ -812,7 +813,8 @@ func TestEvacuateShardObjectsRepOneOnlyBench(t *testing.T) { require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) start := time.Now() - _, err := e.Evacuate(context.Background(), prm) + err := e.Evacuate(context.Background(), prm) + testWaitForEvacuationCompleted(t, e) t.Logf("evacuate took %v\n", time.Since(start)) require.NoError(t, err) } diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index 04465eb266..da54015157 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -42,7 +42,6 @@ func (s *Server) StartShardEvacuation(ctx context.Context, req *control.StartSha IgnoreErrors: req.GetBody().GetIgnoreErrors(), ObjectsHandler: s.replicateObject, TreeHandler: s.replicateTree, - Async: true, Scope: engine.EvacuateScope(req.GetBody().GetScope()), ContainerWorkerCount: req.GetBody().GetContainerWorkerCount(), ObjectWorkerCount: req.GetBody().GetObjectWorkerCount(), From 15139d80c9e78ca5a9023eb3f6466d31d40942f3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Dec 2024 12:47:20 +0300 Subject: [PATCH 1079/1413] [#1548] policer: Do not replicate EC chunk if object already removed Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/ec.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index cb583f1d3b..db640e3233 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -281,6 +281,8 @@ func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info } chunkIDs[ch.Index] = ecInfoChunkID } + } else if client.IsErrObjectAlreadyRemoved(err) { + restore = false } else if !p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) && uint32(idx) < objInfo.ECInfo.Total { p.log.Warn(ctx, logs.PolicerCouldNotGetObjectFromNodeMoving, zap.String("node", hex.EncodeToString(n.PublicKey())), zap.Stringer("object", parentAddress), zap.Error(err)) p.replicator.HandleReplicationTask(ctx, replicator.Task{ From 386a12eea45d5af072dfbba307e5a079ee9ebdb4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Dec 2024 12:52:26 +0300 Subject: [PATCH 1080/1413] [#1548] engine: Rename parent -> ecParent Parent could mean split parent or EC parent. In this case it is EC parent only. Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/exists_test.go | 2 +- pkg/local_object_storage/engine/put.go | 10 +++++----- pkg/local_object_storage/metabase/exists.go | 18 +++++++++--------- pkg/local_object_storage/shard/exists.go | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pkg/local_object_storage/engine/exists_test.go b/pkg/local_object_storage/engine/exists_test.go index 1b51c10dc9..9b3c0833f9 100644 --- a/pkg/local_object_storage/engine/exists_test.go +++ b/pkg/local_object_storage/engine/exists_test.go @@ -42,7 +42,7 @@ func benchmarkExists(b *testing.B, shardNum int) { for range b.N { var shPrm shard.ExistsPrm shPrm.Address = addr - shPrm.ParentAddress = oid.Address{} + shPrm.ECParentAddress = oid.Address{} ok, _, err := e.exists(context.Background(), shPrm) if err != nil || ok { b.Fatalf("%t %v", ok, err) diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index e080191ae4..ba4a144d1a 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -71,21 +71,21 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // In #1146 this check was parallelized, however, it became // much slower on fast machines for 4 shards. - var parent oid.Address + var ecParent oid.Address if prm.Object.ECHeader() != nil { - parent.SetObject(prm.Object.ECHeader().Parent()) - parent.SetContainer(addr.Container()) + ecParent.SetObject(prm.Object.ECHeader().Parent()) + ecParent.SetContainer(addr.Container()) } var shPrm shard.ExistsPrm shPrm.Address = addr - shPrm.ParentAddress = parent + shPrm.ECParentAddress = ecParent existed, locked, err := e.exists(ctx, shPrm) if err != nil { return err } if !existed && locked { - lockers, err := e.GetLocked(ctx, parent) + lockers, err := e.GetLocked(ctx, ecParent) if err != nil { return err } diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index 0294dd3bab..f6596e8302 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -20,8 +20,8 @@ import ( // ExistsPrm groups the parameters of Exists operation. type ExistsPrm struct { - addr oid.Address - paddr oid.Address + addr oid.Address + ecParentAddr oid.Address } // ExistsRes groups the resulting values of Exists operation. @@ -37,9 +37,9 @@ func (p *ExistsPrm) SetAddress(addr oid.Address) { p.addr = addr } -// SetParent is an Exists option to set objects parent. -func (p *ExistsPrm) SetParent(addr oid.Address) { - p.paddr = addr +// SetECParent is an Exists option to set objects parent. +func (p *ExistsPrm) SetECParent(addr oid.Address) { + p.ecParentAddr = addr } // Exists returns the fact that the object is in the metabase. @@ -82,7 +82,7 @@ func (db *DB) Exists(ctx context.Context, prm ExistsPrm) (res ExistsRes, err err currEpoch := db.epochState.CurrentEpoch() err = db.boltDB.View(func(tx *bbolt.Tx) error { - res.exists, res.locked, err = db.exists(tx, prm.addr, prm.paddr, currEpoch) + res.exists, res.locked, err = db.exists(tx, prm.addr, prm.ecParentAddr, currEpoch) return err }) @@ -90,10 +90,10 @@ func (db *DB) Exists(ctx context.Context, prm ExistsPrm) (res ExistsRes, err err return res, metaerr.Wrap(err) } -func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, parent oid.Address, currEpoch uint64) (bool, bool, error) { +func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, ecParent oid.Address, currEpoch uint64) (bool, bool, error) { var locked bool - if !parent.Equals(oid.Address{}) { - locked = objectLocked(tx, parent.Container(), parent.Object()) + if !ecParent.Equals(oid.Address{}) { + locked = objectLocked(tx, ecParent.Container(), ecParent.Object()) } // check graveyard and object expiration first st, err := objectStatus(tx, addr, currEpoch) diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index 784bf293ae..82ce48dde7 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -18,7 +18,7 @@ type ExistsPrm struct { // Exists option to set object checked for existence. Address oid.Address // Exists option to set parent object checked for existence. - ParentAddress oid.Address + ECParentAddress oid.Address } // ExistsRes groups the resulting values of Exists operation. @@ -74,7 +74,7 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { } else { var existsPrm meta.ExistsPrm existsPrm.SetAddress(prm.Address) - existsPrm.SetParent(prm.ParentAddress) + existsPrm.SetECParent(prm.ECParentAddress) var res meta.ExistsRes res, err = s.metaBase.Exists(ctx, existsPrm) From 1f6cf57e308eab9b2659989eb31f1bee1a56ef9b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 10 Dec 2024 12:53:54 +0300 Subject: [PATCH 1081/1413] [#1548] metabase: Check if EC parent is removed or expired Signed-off-by: Dmitrii Stepanov --- .../engine/inhume_test.go | 45 +++++++++++++++++++ pkg/local_object_storage/metabase/exists.go | 11 +++++ pkg/local_object_storage/metabase/put.go | 8 +++- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 9d7196d946..2d083a58cf 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -11,6 +11,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -93,6 +94,50 @@ func TestStorageEngine_Inhume(t *testing.T) { }) } +func TestStorageEngine_ECInhume(t *testing.T) { + parentObjectAddress := oidtest.Address() + containerID := parentObjectAddress.Container() + + chunkObject0 := testutil.GenerateObjectWithCID(containerID) + chunkObject0.SetECHeader(objectSDK.NewECHeader( + objectSDK.ECParentInfo{ + ID: parentObjectAddress.Object(), + }, 0, 4, []byte{}, 0)) + + chunkObject1 := testutil.GenerateObjectWithCID(containerID) + chunkObject1.SetECHeader(objectSDK.NewECHeader( + objectSDK.ECParentInfo{ + ID: parentObjectAddress.Object(), + }, 1, 4, []byte{}, 0)) + + tombstone := objectSDK.NewTombstone() + tombstone.SetMembers([]oid.ID{parentObjectAddress.Object()}) + payload, err := tombstone.Marshal() + require.NoError(t, err) + tombstoneObject := testutil.GenerateObjectWithCID(containerID) + tombstoneObject.SetType(objectSDK.TypeTombstone) + tombstoneObject.SetPayload(payload) + tombstoneObjectAddress := object.AddressOf(tombstoneObject) + + e := testNewEngine(t).setShardsNum(t, 5).prepare(t).engine + defer func() { require.NoError(t, e.Close(context.Background())) }() + + require.NoError(t, Put(context.Background(), e, chunkObject0, false)) + + require.NoError(t, Put(context.Background(), e, tombstoneObject, false)) + + var inhumePrm InhumePrm + inhumePrm.WithTarget(tombstoneObjectAddress, parentObjectAddress) + _, err = e.Inhume(context.Background(), inhumePrm) + require.NoError(t, err) + + var alreadyRemoved *apistatus.ObjectAlreadyRemoved + + require.ErrorAs(t, Put(context.Background(), e, chunkObject0, false), &alreadyRemoved) + + require.ErrorAs(t, Put(context.Background(), e, chunkObject1, false), &alreadyRemoved) +} + func TestInhumeExpiredRegularObject(t *testing.T) { t.Parallel() diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index f6596e8302..411beb6b39 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -93,6 +93,17 @@ func (db *DB) Exists(ctx context.Context, prm ExistsPrm) (res ExistsRes, err err func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, ecParent oid.Address, currEpoch uint64) (bool, bool, error) { var locked bool if !ecParent.Equals(oid.Address{}) { + st, err := objectStatus(tx, ecParent, currEpoch) + if err != nil { + return false, false, err + } + switch st { + case 2: + return false, locked, logicerr.Wrap(new(apistatus.ObjectAlreadyRemoved)) + case 3: + return false, locked, ErrObjectIsExpired + } + locked = objectLocked(tx, ecParent.Container(), ecParent.Object()) } // check graveyard and object expiration first diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index d7675869fa..6f9dc1bf04 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -121,9 +121,15 @@ func (db *DB) put(tx *bbolt.Tx, return PutRes{}, errors.New("missing container in object") } + var ecParentAddress oid.Address + if ecHeader := obj.ECHeader(); ecHeader != nil { + ecParentAddress.SetContainer(cnr) + ecParentAddress.SetObject(ecHeader.Parent()) + } + isParent := si != nil - exists, _, err := db.exists(tx, objectCore.AddressOf(obj), oid.Address{}, currEpoch) + exists, _, err := db.exists(tx, objectCore.AddressOf(obj), ecParentAddress, currEpoch) var splitInfoError *objectSDK.SplitInfoError if errors.As(err, &splitInfoError) { From 670305a7216bf3a5304b6256eed8dc1efe285f9f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 6 Dec 2024 15:50:57 +0300 Subject: [PATCH 1082/1413] [#1546] morph/event: Remove nil checks from event handler registrar This codepath hides possible bugs in code. We would rather panic then silently fail. Signed-off-by: Evgenii Stratonikov --- internal/logs/logs.go | 5 ----- pkg/morph/event/listener.go | 29 ----------------------------- 2 files changed, 34 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index d0bac4d110..893be7006b 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -164,17 +164,12 @@ const ( EventNotaryParserNotSet = "notary parser not set" EventCouldNotParseNotaryEvent = "could not parse notary event" EventNotaryHandlersForParsedNotificationEventWereNotRegistered = "notary handlers for parsed notification event were not registered" - EventIgnoreNilEventParser = "ignore nil event parser" EventListenerHasBeenAlreadyStartedIgnoreParser = "listener has been already started, ignore parser" EventRegisteredNewEventParser = "registered new event parser" - EventIgnoreNilEventHandler = "ignore nil event handler" EventIgnoreHandlerOfEventWoParser = "ignore handler of event w/o parser" EventRegisteredNewEventHandler = "registered new event handler" - EventIgnoreNilNotaryEventParser = "ignore nil notary event parser" EventListenerHasBeenAlreadyStartedIgnoreNotaryParser = "listener has been already started, ignore notary parser" - EventIgnoreNilNotaryEventHandler = "ignore nil notary event handler" EventIgnoreHandlerOfNotaryEventWoParser = "ignore handler of notary event w/o parser" - EventIgnoreNilBlockHandler = "ignore nil block handler" StorageOperation = "local object storage operation" BlobovniczaCreatingDirectoryForBoltDB = "creating directory for BoltDB" BlobovniczaOpeningBoltDB = "opening BoltDB" diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 6e6184e775..b67546804f 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -459,12 +459,6 @@ func (l *listener) SetNotificationParser(pi NotificationParserInfo) { zap.Stringer("event_type", pi.getType()), ) - parser := pi.parser() - if parser == nil { - log.Info(context.Background(), logs.EventIgnoreNilEventParser) - return - } - l.mtx.Lock() defer l.mtx.Unlock() @@ -492,12 +486,6 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) { zap.Stringer("event_type", hi.GetType()), ) - handler := hi.Handler() - if handler == nil { - log.Warn(context.Background(), logs.EventIgnoreNilEventHandler) - return - } - // check if parser was set l.mtx.RLock() _, ok := l.notificationParsers[hi.scriptHashWithType] @@ -555,12 +543,6 @@ func (l *listener) SetNotaryParser(pi NotaryParserInfo) { zap.Stringer("notary_type", pi.RequestType()), ) - parser := pi.parser() - if parser == nil { - log.Info(context.Background(), logs.EventIgnoreNilNotaryEventParser) - return - } - l.mtx.Lock() defer l.mtx.Unlock() @@ -593,12 +575,6 @@ func (l *listener) RegisterNotaryHandler(hi NotaryHandlerInfo) { zap.Stringer("notary type", hi.RequestType()), ) - handler := hi.Handler() - if handler == nil { - log.Warn(context.Background(), logs.EventIgnoreNilNotaryEventHandler) - return - } - // check if parser was set l.mtx.RLock() _, ok := l.notaryParsers[hi.notaryRequestTypes] @@ -627,11 +603,6 @@ func (l *listener) Stop() { } func (l *listener) RegisterBlockHandler(handler BlockHandler) { - if handler == nil { - l.log.Warn(context.Background(), logs.EventIgnoreNilBlockHandler) - return - } - l.blockHandlers = append(l.blockHandlers, handler) } From dfa51048a852aa9a8c88a67b6914d671137dc3f7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 6 Dec 2024 15:56:41 +0300 Subject: [PATCH 1083/1413] [#1546] morph/event: Remove "is started" checks from event handler registrar This codepath hides possible bugs in code. All initialization function should run before init stage. Signed-off-by: Evgenii Stratonikov --- internal/logs/logs.go | 2 -- pkg/morph/event/listener.go | 17 ----------------- 2 files changed, 19 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 893be7006b..535802a20e 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -164,11 +164,9 @@ const ( EventNotaryParserNotSet = "notary parser not set" EventCouldNotParseNotaryEvent = "could not parse notary event" EventNotaryHandlersForParsedNotificationEventWereNotRegistered = "notary handlers for parsed notification event were not registered" - EventListenerHasBeenAlreadyStartedIgnoreParser = "listener has been already started, ignore parser" EventRegisteredNewEventParser = "registered new event parser" EventIgnoreHandlerOfEventWoParser = "ignore handler of event w/o parser" EventRegisteredNewEventHandler = "registered new event handler" - EventListenerHasBeenAlreadyStartedIgnoreNotaryParser = "listener has been already started, ignore notary parser" EventIgnoreHandlerOfNotaryEventWoParser = "ignore handler of notary event w/o parser" StorageOperation = "local object storage operation" BlobovniczaCreatingDirectoryForBoltDB = "creating directory for BoltDB" diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index b67546804f..64ff205be2 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -100,8 +100,6 @@ type listener struct { startOnce, stopOnce sync.Once - started bool - notificationParsers map[scriptHashWithType]NotificationParser notificationHandlers map[scriptHashWithType][]Handler @@ -171,9 +169,6 @@ func (l *listener) ListenWithError(ctx context.Context, intError chan<- error) { } func (l *listener) listen(ctx context.Context, intError chan<- error) error { - // mark listener as started - l.started = true - subErrCh := make(chan error) go l.subscribe(subErrCh) @@ -462,12 +457,6 @@ func (l *listener) SetNotificationParser(pi NotificationParserInfo) { l.mtx.Lock() defer l.mtx.Unlock() - // check if the listener was started - if l.started { - log.Warn(context.Background(), logs.EventListenerHasBeenAlreadyStartedIgnoreParser) - return - } - // add event parser if _, ok := l.notificationParsers[pi.scriptHashWithType]; !ok { l.notificationParsers[pi.scriptHashWithType] = pi.parser() @@ -546,12 +535,6 @@ func (l *listener) SetNotaryParser(pi NotaryParserInfo) { l.mtx.Lock() defer l.mtx.Unlock() - // check if the listener was started - if l.started { - log.Warn(context.Background(), logs.EventListenerHasBeenAlreadyStartedIgnoreNotaryParser) - return - } - // add event parser if _, ok := l.notaryParsers[pi.notaryRequestTypes]; !ok { l.notaryParsers[pi.notaryRequestTypes] = pi.parser() From d0ce835fbf75658271613a40741443405b86f7eb Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 6 Dec 2024 16:01:16 +0300 Subject: [PATCH 1084/1413] [#1546] morph/event: Merge notification parser and handlers They are decoupled, but it is an error to have a handler without a corresponding parser. Register them together on the code level and get rid of unreachable code. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/morph.go | 18 +++----- internal/logs/logs.go | 1 - pkg/innerring/bindings.go | 6 --- .../processors/alphabet/processor.go | 5 --- pkg/innerring/processors/balance/processor.go | 17 +------ .../processors/container/processor.go | 5 --- pkg/innerring/processors/frostfs/processor.go | 45 ++++--------------- .../processors/governance/processor.go | 12 +---- pkg/innerring/processors/netmap/processor.go | 19 +------- pkg/morph/event/handlers.go | 18 +++++--- pkg/morph/event/listener.go | 44 ++---------------- pkg/morph/event/listener_test.go | 18 ++++---- pkg/morph/event/parsers.go | 27 ----------- 13 files changed, 44 insertions(+), 191 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 81579c7fc8..e80dda80e5 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -223,27 +223,21 @@ func registerNotificationHandlers(scHash util.Uint160, lis event.Listener, parse subs map[event.Type][]event.Handler, ) { for typ, handlers := range subs { - pi := event.NotificationParserInfo{} - pi.SetType(typ) - pi.SetScriptHash(scHash) + hi := event.NotificationHandlerInfo{} + hi.SetType(typ) + hi.SetScriptHash(scHash) p, ok := parsers[typ] if !ok { panic(fmt.Sprintf("missing parser for event %s", typ)) } - pi.SetParser(p) - - lis.SetNotificationParser(pi) + hi.SetParser(p) for _, h := range handlers { - hi := event.NotificationHandlerInfo{} - hi.SetType(typ) - hi.SetScriptHash(scHash) - hi.SetHandler(h) - - lis.RegisterNotificationHandler(hi) + hi.AddHandler(h) } + lis.RegisterNotificationHandler(hi) } } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 535802a20e..b24f3593dd 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -165,7 +165,6 @@ const ( EventCouldNotParseNotaryEvent = "could not parse notary event" EventNotaryHandlersForParsedNotificationEventWereNotRegistered = "notary handlers for parsed notification event were not registered" EventRegisteredNewEventParser = "registered new event parser" - EventIgnoreHandlerOfEventWoParser = "ignore handler of event w/o parser" EventRegisteredNewEventHandler = "registered new event handler" EventIgnoreHandlerOfNotaryEventWoParser = "ignore handler of notary event w/o parser" StorageOperation = "local object storage operation" diff --git a/pkg/innerring/bindings.go b/pkg/innerring/bindings.go index c4de07a5fc..dfada764aa 100644 --- a/pkg/innerring/bindings.go +++ b/pkg/innerring/bindings.go @@ -8,7 +8,6 @@ type ( // ContractProcessor interface defines functions for binding event producers // such as event.Listener and Timers with contract processor. ContractProcessor interface { - ListenerNotificationParsers() []event.NotificationParserInfo ListenerNotificationHandlers() []event.NotificationHandlerInfo ListenerNotaryParsers() []event.NotaryParserInfo ListenerNotaryHandlers() []event.NotaryHandlerInfo @@ -16,11 +15,6 @@ type ( ) func connectListenerWithProcessor(l event.Listener, p ContractProcessor) { - // register notification parsers - for _, parser := range p.ListenerNotificationParsers() { - l.SetNotificationParser(parser) - } - // register notification handlers for _, handler := range p.ListenerNotificationHandlers() { l.RegisterNotificationHandler(handler) diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index 3992e00f34..2c4654e7c3 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -114,11 +114,6 @@ func (ap *Processor) SetParsedWallets(parsedWallets []util.Uint160) { ap.pwLock.Unlock() } -// ListenerNotificationParsers for the 'event.Listener' event producer. -func (ap *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { - return nil -} - // ListenerNotificationHandlers for the 'event.Listener' event producer. func (ap *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { return nil diff --git a/pkg/innerring/processors/balance/processor.go b/pkg/innerring/processors/balance/processor.go index e2f649600f..d323238c76 100644 --- a/pkg/innerring/processors/balance/processor.go +++ b/pkg/innerring/processors/balance/processor.go @@ -88,20 +88,6 @@ func New(p *Params) (*Processor, error) { }, nil } -// ListenerNotificationParsers for the 'event.Listener' event producer. -func (bp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { - var parsers []event.NotificationParserInfo - - // new lock event - lock := event.NotificationParserInfo{} - lock.SetType(lockNotification) - lock.SetScriptHash(bp.balanceSC) - lock.SetParser(balanceEvent.ParseLock) - parsers = append(parsers, lock) - - return parsers -} - // ListenerNotificationHandlers for the 'event.Listener' event producer. func (bp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { var handlers []event.NotificationHandlerInfo @@ -110,7 +96,8 @@ func (bp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI lock := event.NotificationHandlerInfo{} lock.SetType(lockNotification) lock.SetScriptHash(bp.balanceSC) - lock.SetHandler(bp.handleLock) + lock.SetParser(balanceEvent.ParseLock) + lock.AddHandler(bp.handleLock) handlers = append(handlers, lock) return handlers diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index 58b90457c7..a0b7491e1c 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -118,11 +118,6 @@ func New(p *Params) (*Processor, error) { }, nil } -// ListenerNotificationParsers for the 'event.Listener' event producer. -func (cp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { - return nil -} - // ListenerNotificationHandlers for the 'event.Listener' event producer. func (cp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { return nil diff --git a/pkg/innerring/processors/frostfs/processor.go b/pkg/innerring/processors/frostfs/processor.go index 6c29d330d9..64b171f7ff 100644 --- a/pkg/innerring/processors/frostfs/processor.go +++ b/pkg/innerring/processors/frostfs/processor.go @@ -142,39 +142,6 @@ func New(p *Params) (*Processor, error) { }, nil } -// ListenerNotificationParsers for the 'event.Listener' event producer. -func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { - var ( - parsers = make([]event.NotificationParserInfo, 0, 6) - - p event.NotificationParserInfo - ) - - p.SetScriptHash(np.frostfsContract) - - // deposit event - p.SetType(event.TypeFromString(depositNotification)) - p.SetParser(frostfsEvent.ParseDeposit) - parsers = append(parsers, p) - - // withdraw event - p.SetType(event.TypeFromString(withdrawNotification)) - p.SetParser(frostfsEvent.ParseWithdraw) - parsers = append(parsers, p) - - // cheque event - p.SetType(event.TypeFromString(chequeNotification)) - p.SetParser(frostfsEvent.ParseCheque) - parsers = append(parsers, p) - - // config event - p.SetType(event.TypeFromString(configNotification)) - p.SetParser(frostfsEvent.ParseConfig) - parsers = append(parsers, p) - - return parsers -} - // ListenerNotificationHandlers for the 'event.Listener' event producer. func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { var ( @@ -187,22 +154,26 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI // deposit handler h.SetType(event.TypeFromString(depositNotification)) - h.SetHandler(np.handleDeposit) + h.SetParser(frostfsEvent.ParseDeposit) + h.AddHandler(np.handleDeposit) handlers = append(handlers, h) // withdraw handler h.SetType(event.TypeFromString(withdrawNotification)) - h.SetHandler(np.handleWithdraw) + h.SetParser(frostfsEvent.ParseWithdraw) + h.AddHandler(np.handleWithdraw) handlers = append(handlers, h) // cheque handler h.SetType(event.TypeFromString(chequeNotification)) - h.SetHandler(np.handleCheque) + h.SetParser(frostfsEvent.ParseCheque) + h.AddHandler(np.handleCheque) handlers = append(handlers, h) // config handler h.SetType(event.TypeFromString(configNotification)) - h.SetHandler(np.handleConfig) + h.SetParser(frostfsEvent.ParseConfig) + h.AddHandler(np.handleConfig) handlers = append(handlers, h) return handlers diff --git a/pkg/innerring/processors/governance/processor.go b/pkg/innerring/processors/governance/processor.go index 565f4c27d8..313a0baea7 100644 --- a/pkg/innerring/processors/governance/processor.go +++ b/pkg/innerring/processors/governance/processor.go @@ -155,21 +155,13 @@ func New(p *Params) (*Processor, error) { }, nil } -// ListenerNotificationParsers for the 'event.Listener' event producer. -func (gp *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { - var pi event.NotificationParserInfo - pi.SetScriptHash(gp.designate) - pi.SetType(event.TypeFromString(native.DesignationEventName)) - pi.SetParser(rolemanagement.ParseDesignate) - return []event.NotificationParserInfo{pi} -} - // ListenerNotificationHandlers for the 'event.Listener' event producer. func (gp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { var hi event.NotificationHandlerInfo hi.SetScriptHash(gp.designate) hi.SetType(event.TypeFromString(native.DesignationEventName)) - hi.SetHandler(gp.HandleAlphabetSync) + hi.SetParser(rolemanagement.ParseDesignate) + hi.AddHandler(gp.HandleAlphabetSync) return []event.NotificationHandlerInfo{hi} } diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index b3d57e85bd..c726df9551 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -161,22 +161,6 @@ func New(p *Params) (*Processor, error) { }, nil } -// ListenerNotificationParsers for the 'event.Listener' event producer. -func (np *Processor) ListenerNotificationParsers() []event.NotificationParserInfo { - parsers := make([]event.NotificationParserInfo, 0, 3) - - var p event.NotificationParserInfo - - p.SetScriptHash(np.netmapClient.ContractAddress()) - - // new epoch event - p.SetType(newEpochNotification) - p.SetParser(netmapEvent.ParseNewEpoch) - parsers = append(parsers, p) - - return parsers -} - // ListenerNotificationHandlers for the 'event.Listener' event producer. func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { handlers := make([]event.NotificationHandlerInfo, 0, 3) @@ -187,7 +171,8 @@ func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerI // new epoch handler i.SetType(newEpochNotification) - i.SetHandler(np.handleNewEpoch) + i.SetParser(netmapEvent.ParseNewEpoch) + i.AddHandler(np.handleNewEpoch) handlers = append(handlers, i) return handlers diff --git a/pkg/morph/event/handlers.go b/pkg/morph/event/handlers.go index 8223353296..e96abb846c 100644 --- a/pkg/morph/event/handlers.go +++ b/pkg/morph/event/handlers.go @@ -18,17 +18,23 @@ type BlockHandler func(context.Context, *block.Block) type NotificationHandlerInfo struct { scriptHashWithType - h Handler + parser NotificationParser + handlers []Handler } -// SetHandler is an event handler setter. -func (s *NotificationHandlerInfo) SetHandler(v Handler) { - s.h = v +// SetParser is an event handler setter. +func (s *NotificationHandlerInfo) SetParser(p NotificationParser) { + s.parser = p +} + +// AddHandler adds an event handler. +func (s *NotificationHandlerInfo) AddHandler(v Handler) { + s.handlers = append(s.handlers, v) } // Handler returns an event handler. -func (s NotificationHandlerInfo) Handler() Handler { - return s.h +func (s NotificationHandlerInfo) Handlers() []Handler { + return s.handlers } // NotaryHandlerInfo is a structure that groups diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 64ff205be2..8fe95cf497 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -33,13 +33,6 @@ type Listener interface { // it could not be started. ListenWithError(context.Context, chan<- error) - // SetNotificationParser must set the parser of particular contract event. - // - // Parser of each event must be set once. All parsers must be set before Listen call. - // - // Must ignore nil parsers and all calls after listener has been started. - SetNotificationParser(NotificationParserInfo) - // RegisterNotificationHandler must register the event handler for particular notification event of contract. // // The specified handler must be called after each capture and parsing of the event. @@ -444,27 +437,6 @@ func (l *listener) parseAndHandleNotary(ctx context.Context, nr *result.NotaryRe handler(ctx, event) } -// SetNotificationParser sets the parser of particular contract event. -// -// Ignores nil and already set parsers. -// Ignores the parser if listener is started. -func (l *listener) SetNotificationParser(pi NotificationParserInfo) { - log := l.log.With( - zap.String("contract", pi.ScriptHash().StringLE()), - zap.Stringer("event_type", pi.getType()), - ) - - l.mtx.Lock() - defer l.mtx.Unlock() - - // add event parser - if _, ok := l.notificationParsers[pi.scriptHashWithType]; !ok { - l.notificationParsers[pi.scriptHashWithType] = pi.parser() - } - - log.Debug(context.Background(), logs.EventRegisteredNewEventParser) -} - // RegisterNotificationHandler registers the handler for particular notification event of contract. // // Ignores nil handlers. @@ -476,22 +448,14 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) { ) // check if parser was set - l.mtx.RLock() - _, ok := l.notificationParsers[hi.scriptHashWithType] - l.mtx.RUnlock() - - if !ok { - log.Warn(context.Background(), logs.EventIgnoreHandlerOfEventWoParser) - return - } - - // add event handler l.mtx.Lock() + defer l.mtx.Unlock() + + l.notificationParsers[hi.scriptHashWithType] = hi.parser l.notificationHandlers[hi.scriptHashWithType] = append( l.notificationHandlers[hi.scriptHashWithType], - hi.Handler(), + hi.handlers..., ) - l.mtx.Unlock() log.Debug(context.Background(), logs.EventRegisteredNewEventHandler) } diff --git a/pkg/morph/event/listener_test.go b/pkg/morph/event/listener_test.go index c0f9722d7a..02dad2fd39 100644 --- a/pkg/morph/event/listener_test.go +++ b/pkg/morph/event/listener_test.go @@ -48,20 +48,18 @@ func TestEventHandling(t *testing.T) { }, } - l.SetNotificationParser(NotificationParserInfo{ - scriptHashWithType: key, - p: func(cne *state.ContainedNotificationEvent) (Event, error) { - return testNotificationEvent{source: cne}, nil - }, - }) - notificationHandled := make(chan bool) handledNotifications := make([]Event, 0) l.RegisterNotificationHandler(NotificationHandlerInfo{ scriptHashWithType: key, - h: func(_ context.Context, e Event) { - handledNotifications = append(handledNotifications, e) - notificationHandled <- true + parser: func(cne *state.ContainedNotificationEvent) (Event, error) { + return testNotificationEvent{source: cne}, nil + }, + handlers: []Handler{ + func(_ context.Context, e Event) { + handledNotifications = append(handledNotifications, e) + notificationHandled <- true + }, }, }) diff --git a/pkg/morph/event/parsers.go b/pkg/morph/event/parsers.go index 90eff0bd22..5adeb4b30f 100644 --- a/pkg/morph/event/parsers.go +++ b/pkg/morph/event/parsers.go @@ -11,15 +11,6 @@ import ( // from the StackItem list. type NotificationParser func(*state.ContainedNotificationEvent) (Event, error) -// NotificationParserInfo is a structure that groups -// the parameters of particular contract -// notification event parser. -type NotificationParserInfo struct { - scriptHashWithType - - p NotificationParser -} - // NotaryPreparator constructs NotaryEvent // from the NotaryRequest event. type NotaryPreparator interface { @@ -47,24 +38,6 @@ func (n *NotaryParserInfo) SetParser(p NotaryParser) { n.p = p } -// SetParser is an event parser setter. -func (s *NotificationParserInfo) SetParser(v NotificationParser) { - s.p = v -} - -func (s NotificationParserInfo) parser() NotificationParser { - return s.p -} - -// SetType is an event type setter. -func (s *NotificationParserInfo) SetType(v Type) { - s.typ = v -} - -func (s NotificationParserInfo) getType() Type { - return s.typ -} - type wrongPrmNumber struct { exp, act int } From b1614a284d42521dfb1d5b7b46dd7e45acad4f7b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 6 Dec 2024 16:12:47 +0300 Subject: [PATCH 1085/1413] [#1546] morph/event: Export NotificationHandlerInfo fields Hiding them achieves nothing, as the struct has no methods and is not used concurrently. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/morph.go | 16 ++--- pkg/innerring/processors/balance/processor.go | 19 +++--- pkg/innerring/processors/frostfs/processor.go | 59 ++++++++----------- .../processors/governance/processor.go | 14 +++-- pkg/innerring/processors/netmap/processor.go | 21 +++---- pkg/morph/event/handlers.go | 24 ++------ pkg/morph/event/listener.go | 16 +++-- pkg/morph/event/listener_test.go | 16 ++--- 8 files changed, 75 insertions(+), 110 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index e80dda80e5..0d4e8a1be2 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -223,21 +223,17 @@ func registerNotificationHandlers(scHash util.Uint160, lis event.Listener, parse subs map[event.Type][]event.Handler, ) { for typ, handlers := range subs { - hi := event.NotificationHandlerInfo{} - hi.SetType(typ) - hi.SetScriptHash(scHash) - p, ok := parsers[typ] if !ok { panic(fmt.Sprintf("missing parser for event %s", typ)) } - hi.SetParser(p) - - for _, h := range handlers { - hi.AddHandler(h) - } - lis.RegisterNotificationHandler(hi) + lis.RegisterNotificationHandler(event.NotificationHandlerInfo{ + Contract: scHash, + Type: typ, + Parser: p, + Handlers: handlers, + }) } } diff --git a/pkg/innerring/processors/balance/processor.go b/pkg/innerring/processors/balance/processor.go index d323238c76..34203b74fb 100644 --- a/pkg/innerring/processors/balance/processor.go +++ b/pkg/innerring/processors/balance/processor.go @@ -90,17 +90,14 @@ func New(p *Params) (*Processor, error) { // ListenerNotificationHandlers for the 'event.Listener' event producer. func (bp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { - var handlers []event.NotificationHandlerInfo - - // lock handler - lock := event.NotificationHandlerInfo{} - lock.SetType(lockNotification) - lock.SetScriptHash(bp.balanceSC) - lock.SetParser(balanceEvent.ParseLock) - lock.AddHandler(bp.handleLock) - handlers = append(handlers, lock) - - return handlers + return []event.NotificationHandlerInfo{ + { + Contract: bp.balanceSC, + Type: lockNotification, + Parser: balanceEvent.ParseLock, + Handlers: []event.Handler{bp.handleLock}, + }, + } } // ListenerNotaryParsers for the 'event.Listener' event producer. diff --git a/pkg/innerring/processors/frostfs/processor.go b/pkg/innerring/processors/frostfs/processor.go index 64b171f7ff..9d3bf65cd3 100644 --- a/pkg/innerring/processors/frostfs/processor.go +++ b/pkg/innerring/processors/frostfs/processor.go @@ -144,39 +144,32 @@ func New(p *Params) (*Processor, error) { // ListenerNotificationHandlers for the 'event.Listener' event producer. func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { - var ( - handlers = make([]event.NotificationHandlerInfo, 0, 6) - - h event.NotificationHandlerInfo - ) - - h.SetScriptHash(np.frostfsContract) - - // deposit handler - h.SetType(event.TypeFromString(depositNotification)) - h.SetParser(frostfsEvent.ParseDeposit) - h.AddHandler(np.handleDeposit) - handlers = append(handlers, h) - - // withdraw handler - h.SetType(event.TypeFromString(withdrawNotification)) - h.SetParser(frostfsEvent.ParseWithdraw) - h.AddHandler(np.handleWithdraw) - handlers = append(handlers, h) - - // cheque handler - h.SetType(event.TypeFromString(chequeNotification)) - h.SetParser(frostfsEvent.ParseCheque) - h.AddHandler(np.handleCheque) - handlers = append(handlers, h) - - // config handler - h.SetType(event.TypeFromString(configNotification)) - h.SetParser(frostfsEvent.ParseConfig) - h.AddHandler(np.handleConfig) - handlers = append(handlers, h) - - return handlers + return []event.NotificationHandlerInfo{ + { + Contract: np.frostfsContract, + Type: event.TypeFromString(depositNotification), + Parser: frostfsEvent.ParseDeposit, + Handlers: []event.Handler{np.handleDeposit}, + }, + { + Contract: np.frostfsContract, + Type: event.TypeFromString(withdrawNotification), + Parser: frostfsEvent.ParseWithdraw, + Handlers: []event.Handler{np.handleWithdraw}, + }, + { + Contract: np.frostfsContract, + Type: event.TypeFromString(chequeNotification), + Parser: frostfsEvent.ParseCheque, + Handlers: []event.Handler{np.handleCheque}, + }, + { + Contract: np.frostfsContract, + Type: event.TypeFromString(configNotification), + Parser: frostfsEvent.ParseConfig, + Handlers: []event.Handler{np.handleConfig}, + }, + } } // ListenerNotaryParsers for the 'event.Listener' event producer. diff --git a/pkg/innerring/processors/governance/processor.go b/pkg/innerring/processors/governance/processor.go index 313a0baea7..7859ebee14 100644 --- a/pkg/innerring/processors/governance/processor.go +++ b/pkg/innerring/processors/governance/processor.go @@ -157,12 +157,14 @@ func New(p *Params) (*Processor, error) { // ListenerNotificationHandlers for the 'event.Listener' event producer. func (gp *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { - var hi event.NotificationHandlerInfo - hi.SetScriptHash(gp.designate) - hi.SetType(event.TypeFromString(native.DesignationEventName)) - hi.SetParser(rolemanagement.ParseDesignate) - hi.AddHandler(gp.HandleAlphabetSync) - return []event.NotificationHandlerInfo{hi} + return []event.NotificationHandlerInfo{ + { + Contract: gp.designate, + Type: event.TypeFromString(native.DesignationEventName), + Parser: rolemanagement.ParseDesignate, + Handlers: []event.Handler{gp.HandleAlphabetSync}, + }, + } } // ListenerNotaryParsers for the 'event.Listener' event producer. diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index c726df9551..36df57afe4 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -163,19 +163,14 @@ func New(p *Params) (*Processor, error) { // ListenerNotificationHandlers for the 'event.Listener' event producer. func (np *Processor) ListenerNotificationHandlers() []event.NotificationHandlerInfo { - handlers := make([]event.NotificationHandlerInfo, 0, 3) - - var i event.NotificationHandlerInfo - - i.SetScriptHash(np.netmapClient.ContractAddress()) - - // new epoch handler - i.SetType(newEpochNotification) - i.SetParser(netmapEvent.ParseNewEpoch) - i.AddHandler(np.handleNewEpoch) - handlers = append(handlers, i) - - return handlers + return []event.NotificationHandlerInfo{ + { + Contract: np.netmapClient.ContractAddress(), + Type: newEpochNotification, + Parser: netmapEvent.ParseNewEpoch, + Handlers: []event.Handler{np.handleNewEpoch}, + }, + } } // ListenerNotaryParsers for the 'event.Listener' event producer. diff --git a/pkg/morph/event/handlers.go b/pkg/morph/event/handlers.go index e96abb846c..55a514ff16 100644 --- a/pkg/morph/event/handlers.go +++ b/pkg/morph/event/handlers.go @@ -4,6 +4,7 @@ import ( "context" "github.com/nspcc-dev/neo-go/pkg/core/block" + "github.com/nspcc-dev/neo-go/pkg/util" ) // Handler is an Event processing function. @@ -16,25 +17,10 @@ type BlockHandler func(context.Context, *block.Block) // the parameters of the handler of particular // contract event. type NotificationHandlerInfo struct { - scriptHashWithType - - parser NotificationParser - handlers []Handler -} - -// SetParser is an event handler setter. -func (s *NotificationHandlerInfo) SetParser(p NotificationParser) { - s.parser = p -} - -// AddHandler adds an event handler. -func (s *NotificationHandlerInfo) AddHandler(v Handler) { - s.handlers = append(s.handlers, v) -} - -// Handler returns an event handler. -func (s NotificationHandlerInfo) Handlers() []Handler { - return s.handlers + Contract util.Uint160 + Type Type + Parser NotificationParser + Handlers []Handler } // NotaryHandlerInfo is a structure that groups diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 8fe95cf497..9852a3d620 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -443,18 +443,22 @@ func (l *listener) parseAndHandleNotary(ctx context.Context, nr *result.NotaryRe // Ignores handlers of event without parser. func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) { log := l.log.With( - zap.String("contract", hi.ScriptHash().StringLE()), - zap.Stringer("event_type", hi.GetType()), + zap.String("contract", hi.Contract.StringLE()), + zap.Stringer("event_type", hi.Type), ) // check if parser was set l.mtx.Lock() defer l.mtx.Unlock() - l.notificationParsers[hi.scriptHashWithType] = hi.parser - l.notificationHandlers[hi.scriptHashWithType] = append( - l.notificationHandlers[hi.scriptHashWithType], - hi.handlers..., + var k scriptHashWithType + k.hash = hi.Contract + k.typ = hi.Type + + l.notificationParsers[k] = hi.Parser + l.notificationHandlers[k] = append( + l.notificationHandlers[k], + hi.Handlers..., ) log.Debug(context.Background(), logs.EventRegisteredNewEventHandler) diff --git a/pkg/morph/event/listener_test.go b/pkg/morph/event/listener_test.go index 02dad2fd39..87f37305ff 100644 --- a/pkg/morph/event/listener_test.go +++ b/pkg/morph/event/listener_test.go @@ -39,23 +39,15 @@ func TestEventHandling(t *testing.T) { blockHandled <- true }) - key := scriptHashWithType{ - scriptHashValue: scriptHashValue{ - hash: util.Uint160{100}, - }, - typeValue: typeValue{ - typ: TypeFromString("notification type"), - }, - } - notificationHandled := make(chan bool) handledNotifications := make([]Event, 0) l.RegisterNotificationHandler(NotificationHandlerInfo{ - scriptHashWithType: key, - parser: func(cne *state.ContainedNotificationEvent) (Event, error) { + Contract: util.Uint160{100}, + Type: TypeFromString("notification type"), + Parser: func(cne *state.ContainedNotificationEvent) (Event, error) { return testNotificationEvent{source: cne}, nil }, - handlers: []Handler{ + Handlers: []Handler{ func(_ context.Context, e Event) { handledNotifications = append(handledNotifications, e) notificationHandled <- true From a641c91594dcf48c567ae312a7b7db8ccabf121c Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Tue, 10 Dec 2024 18:04:22 +0300 Subject: [PATCH 1086/1413] [#1550] Add CODEOWNERS Signed-off-by: Vitaliy Potyarkin --- CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000000..d19c96a5cd --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,3 @@ +.* @TrueCloudLab/storage-core-committers @TrueCloudLab/storage-core-developers +.forgejo/.* @potyarkin +Makefile @potyarkin From e9837bbcf9b02ed9218f7ebdb088f0099fd04b86 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 11 Dec 2024 14:39:53 +0300 Subject: [PATCH 1087/1413] [#1554] morph/event: Remove unused AlphabetUpdate event Refs TrueCloudLab/frostfs-contract#138. Signed-off-by: Evgenii Stratonikov --- pkg/morph/event/frostfs/ir_update.go | 54 --------------------- pkg/morph/event/frostfs/ir_update_test.go | 57 ----------------------- 2 files changed, 111 deletions(-) delete mode 100644 pkg/morph/event/frostfs/ir_update.go delete mode 100644 pkg/morph/event/frostfs/ir_update_test.go diff --git a/pkg/morph/event/frostfs/ir_update.go b/pkg/morph/event/frostfs/ir_update.go deleted file mode 100644 index 62203540f0..0000000000 --- a/pkg/morph/event/frostfs/ir_update.go +++ /dev/null @@ -1,54 +0,0 @@ -package frostfs - -import ( - "crypto/elliptic" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" -) - -type UpdateInnerRing struct { - keys []*keys.PublicKey -} - -// MorphEvent implements Neo:Morph Event interface. -func (UpdateInnerRing) MorphEvent() {} - -func (u UpdateInnerRing) Keys() []*keys.PublicKey { return u.keys } - -func ParseUpdateInnerRing(params []stackitem.Item) (event.Event, error) { - var ( - ev UpdateInnerRing - err error - ) - - if ln := len(params); ln != 1 { - return nil, event.WrongNumberOfParameters(1, ln) - } - - // parse keys - irKeys, err := client.ArrayFromStackItem(params[0]) - if err != nil { - return nil, fmt.Errorf("could not get updated inner ring keys: %w", err) - } - - ev.keys = make([]*keys.PublicKey, 0, len(irKeys)) - for i := range irKeys { - rawKey, err := client.BytesFromStackItem(irKeys[i]) - if err != nil { - return nil, fmt.Errorf("could not get updated inner ring public key: %w", err) - } - - key, err := keys.NewPublicKeyFromBytes(rawKey, elliptic.P256()) - if err != nil { - return nil, fmt.Errorf("could not parse updated inner ring public key: %w", err) - } - - ev.keys = append(ev.keys, key) - } - - return ev, nil -} diff --git a/pkg/morph/event/frostfs/ir_update_test.go b/pkg/morph/event/frostfs/ir_update_test.go deleted file mode 100644 index fae87e5f94..0000000000 --- a/pkg/morph/event/frostfs/ir_update_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package frostfs - -import ( - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/stretchr/testify/require" -) - -func genKey(t *testing.T) *keys.PrivateKey { - priv, err := keys.NewPrivateKey() - require.NoError(t, err) - return priv -} - -func TestParseUpdateInnerRing(t *testing.T) { - publicKeys := []*keys.PublicKey{ - genKey(t).PublicKey(), - genKey(t).PublicKey(), - genKey(t).PublicKey(), - } - - t.Run("wrong number of parameters", func(t *testing.T) { - prms := []stackitem.Item{ - stackitem.NewMap(), - stackitem.NewMap(), - } - - _, err := ParseUpdateInnerRing(prms) - require.EqualError(t, err, event.WrongNumberOfParameters(1, len(prms)).Error()) - }) - - t.Run("wrong first parameter", func(t *testing.T) { - _, err := ParseUpdateInnerRing([]stackitem.Item{ - stackitem.NewMap(), - }) - - require.Error(t, err) - }) - - t.Run("correct", func(t *testing.T) { - ev, err := ParseUpdateInnerRing([]stackitem.Item{ - stackitem.NewArray([]stackitem.Item{ - stackitem.NewByteArray(publicKeys[0].Bytes()), - stackitem.NewByteArray(publicKeys[1].Bytes()), - stackitem.NewByteArray(publicKeys[2].Bytes()), - }), - }) - require.NoError(t, err) - - require.Equal(t, UpdateInnerRing{ - keys: publicKeys, - }, ev) - }) -} From 72470d6b4884780978768add9c3496768cb6ee9c Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 11 Dec 2024 14:43:36 +0300 Subject: [PATCH 1088/1413] [#1555] local_object_storage: Rename method `GetLocked` -> `GetLocks` Renamed to better reflect the method's purpose of returning locks for the specified object. Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/inhume.go | 8 ++++---- pkg/local_object_storage/engine/put.go | 2 +- pkg/local_object_storage/metabase/lock.go | 12 ++++++------ pkg/local_object_storage/shard/lock.go | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 80c77af54a..0eb9d05c95 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -254,9 +254,9 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e return locked, outErr } -// GetLocked return lock id's if object is locked according to StorageEngine's state. -func (e *StorageEngine) GetLocked(ctx context.Context, addr oid.Address) ([]oid.ID, error) { - ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.GetLocked", +// GetLocks return lock id's if object is locked according to StorageEngine's state. +func (e *StorageEngine) GetLocks(ctx context.Context, addr oid.Address) ([]oid.ID, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.GetLocks", trace.WithAttributes( attribute.String("address", addr.EncodeToString()), )) @@ -266,7 +266,7 @@ func (e *StorageEngine) GetLocked(ctx context.Context, addr oid.Address) ([]oid. var outErr error e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { - ld, err := h.Shard.GetLocked(ctx, addr) + ld, err := h.Shard.GetLocks(ctx, addr) if err != nil { e.reportShardError(ctx, h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index ba4a144d1a..62671f4331 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -85,7 +85,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { } if !existed && locked { - lockers, err := e.GetLocked(ctx, ecParent) + lockers, err := e.GetLocks(ctx, ecParent) if err != nil { return err } diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index 6b78ef392d..b930a01413 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -176,7 +176,7 @@ func objectLocked(tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) bool { } // return `LOCK` id's if specified object is locked in the specified container. -func getLocked(tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) ([]oid.ID, error) { +func getLocks(tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) ([]oid.ID, error) { var lockers []oid.ID bucketLocked := tx.Bucket(bucketNameLocked) if bucketLocked != nil { @@ -351,20 +351,20 @@ func (db *DB) IsLocked(ctx context.Context, prm IsLockedPrm) (res IsLockedRes, e return res, err } -// GetLocked return `LOCK` id's if provided object is locked by any `LOCK`. Not found +// GetLocks return `LOCK` id's if provided object is locked by any `LOCK`. Not found // object is considered as non-locked. // // Returns only non-logical errors related to underlying database. -func (db *DB) GetLocked(ctx context.Context, addr oid.Address) (res []oid.ID, err error) { +func (db *DB) GetLocks(ctx context.Context, addr oid.Address) (res []oid.ID, err error) { var ( startedAt = time.Now() success = false ) defer func() { - db.metrics.AddMethodDuration("GetLocked", time.Since(startedAt), success) + db.metrics.AddMethodDuration("GetLocks", time.Since(startedAt), success) }() - _, span := tracing.StartSpanFromContext(ctx, "metabase.GetLocked", + _, span := tracing.StartSpanFromContext(ctx, "metabase.GetLocks", trace.WithAttributes( attribute.String("address", addr.EncodeToString()), )) @@ -377,7 +377,7 @@ func (db *DB) GetLocked(ctx context.Context, addr oid.Address) (res []oid.ID, er return res, ErrDegradedMode } err = metaerr.Wrap(db.boltDB.View(func(tx *bbolt.Tx) error { - res, err = getLocked(tx, addr.Container(), addr.Object()) + res, err = getLocks(tx, addr.Container(), addr.Object()) return nil })) success = err == nil diff --git a/pkg/local_object_storage/shard/lock.go b/pkg/local_object_storage/shard/lock.go index 4a8d89d630..31ca16aa17 100644 --- a/pkg/local_object_storage/shard/lock.go +++ b/pkg/local_object_storage/shard/lock.go @@ -72,10 +72,10 @@ func (s *Shard) IsLocked(ctx context.Context, addr oid.Address) (bool, error) { return res.Locked(), nil } -// GetLocked return lock id's of the provided object. Not found object is +// GetLocks return lock id's of the provided object. Not found object is // considered as not locked. Requires healthy metabase, returns ErrDegradedMode otherwise. -func (s *Shard) GetLocked(ctx context.Context, addr oid.Address) ([]oid.ID, error) { - ctx, span := tracing.StartSpanFromContext(ctx, "Shard.GetLocked", +func (s *Shard) GetLocks(ctx context.Context, addr oid.Address) ([]oid.ID, error) { + ctx, span := tracing.StartSpanFromContext(ctx, "Shard.GetLocks", trace.WithAttributes( attribute.String("shard_id", s.ID().String()), attribute.String("address", addr.EncodeToString()), @@ -86,5 +86,5 @@ func (s *Shard) GetLocked(ctx context.Context, addr oid.Address) ([]oid.ID, erro if m.NoMetabase() { return nil, ErrDegradedMode } - return s.metaBase.GetLocked(ctx, addr) + return s.metaBase.GetLocks(ctx, addr) } From 3821645085986c116b2f19c721775e6921ad76a0 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 11 Dec 2024 14:47:18 +0300 Subject: [PATCH 1089/1413] [#1555] engine: Refactor `(*StorageEngine).GetLocks` Refactored after renaming the method to replace the confusing `locked` variable with `locks`. Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/inhume.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 0eb9d05c95..bae7840646 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -262,23 +262,23 @@ func (e *StorageEngine) GetLocks(ctx context.Context, addr oid.Address) ([]oid.I )) defer span.End() - var locked []oid.ID + var allLocks []oid.ID var outErr error e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { - ld, err := h.Shard.GetLocks(ctx, addr) + locks, err := h.Shard.GetLocks(ctx, addr) if err != nil { e.reportShardError(ctx, h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) outErr = err } - locked = append(locked, ld...) + allLocks = append(allLocks, locks...) return false }) - if len(locked) > 0 { - return locked, nil + if len(allLocks) > 0 { + return allLocks, nil } - return locked, outErr + return allLocks, outErr } func (e *StorageEngine) processExpiredTombstones(ctx context.Context, addrs []meta.TombstonedObject) { From 7853dbc315a7a9d7d450d92e4342b59c155a514c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 11 Dec 2024 15:20:59 +0300 Subject: [PATCH 1090/1413] [#1557] morph/event: Remove embedded structs from scriptHashWithValue Also, make them public, because otherwise `unused` linter complains. ``` pkg/morph/event/utils.go:25:2 unused field `typ` is unused ``` This complain is wrong, though: we _use_ `typ` field because the whole struct is used as a map key. Signed-off-by: Evgenii Stratonikov --- pkg/morph/event/listener.go | 12 ++++-------- pkg/morph/event/utils.go | 18 ++---------------- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 9852a3d620..7a16eb991e 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -180,7 +180,7 @@ func (l *listener) subscribe(errCh chan error) { // fill the list with the contracts with set event parsers. l.mtx.RLock() for hashType := range l.notificationParsers { - scHash := hashType.ScriptHash() + scHash := hashType.Hash // prevent repetitions for _, hash := range hashes { @@ -189,7 +189,7 @@ func (l *listener) subscribe(errCh chan error) { } } - hashes = append(hashes, hashType.ScriptHash()) + hashes = append(hashes, hashType.Hash) } l.mtx.RUnlock() @@ -326,9 +326,7 @@ func (l *listener) parseAndHandleNotification(ctx context.Context, notifyEvent * ) // get the event parser - keyEvent := scriptHashWithType{} - keyEvent.SetScriptHash(notifyEvent.ScriptHash) - keyEvent.SetType(typEvent) + keyEvent := scriptHashWithType{Hash: notifyEvent.ScriptHash, Type: typEvent} l.mtx.RLock() parser, ok := l.notificationParsers[keyEvent] @@ -451,9 +449,7 @@ func (l *listener) RegisterNotificationHandler(hi NotificationHandlerInfo) { l.mtx.Lock() defer l.mtx.Unlock() - var k scriptHashWithType - k.hash = hi.Contract - k.typ = hi.Type + k := scriptHashWithType{Hash: hi.Contract, Type: hi.Type} l.notificationParsers[k] = hi.Parser l.notificationHandlers[k] = append( diff --git a/pkg/morph/event/utils.go b/pkg/morph/event/utils.go index 99ea9a7f0b..058959c634 100644 --- a/pkg/morph/event/utils.go +++ b/pkg/morph/event/utils.go @@ -20,13 +20,9 @@ type scriptHashValue struct { hash util.Uint160 } -type typeValue struct { - typ Type -} - type scriptHashWithType struct { - scriptHashValue - typeValue + Hash util.Uint160 + Type Type } type notaryRequestTypes struct { @@ -73,16 +69,6 @@ func (s scriptHashValue) ScriptHash() util.Uint160 { return s.hash } -// SetType is an event type setter. -func (s *typeValue) SetType(v Type) { - s.typ = v -} - -// GetType is an event type getter. -func (s typeValue) GetType() Type { - return s.typ -} - // WorkerPoolHandler sets closure over worker pool w with passed handler h. func WorkerPoolHandler(w util2.WorkerPool, h Handler, log *logger.Logger) Handler { return func(ctx context.Context, e Event) { From 91d9dc2676fa7739ae5ba6763995ae92fab81d29 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 12 Dec 2024 14:59:49 +0300 Subject: [PATCH 1091/1413] [#1558] morph/event: Remove "could not" from error messages Signed-off-by: Evgenii Stratonikov --- pkg/morph/event/listener.go | 10 +++++----- pkg/morph/event/netmap/update_peer_notary.go | 4 ++-- pkg/morph/event/notary_preparator.go | 18 +++++++++--------- pkg/morph/event/rolemanagement/designate.go | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 7a16eb991e..ed77352ec7 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -111,7 +111,7 @@ type listener struct { pool *ants.Pool } -const newListenerFailMsg = "could not instantiate Listener" +const newListenerFailMsg = "instantiate Listener" var ( errNilLogger = errors.New("nil logger") @@ -195,20 +195,20 @@ func (l *listener) subscribe(errCh chan error) { err := l.subscriber.SubscribeForNotification(hashes...) if err != nil { - errCh <- fmt.Errorf("could not subscribe for notifications: %w", err) + errCh <- fmt.Errorf("subscribe for notifications: %w", err) return } if len(l.blockHandlers) > 0 { if err = l.subscriber.BlockNotifications(); err != nil { - errCh <- fmt.Errorf("could not subscribe for blocks: %w", err) + errCh <- fmt.Errorf("subscribe for blocks: %w", err) return } } if l.listenNotary { if err = l.subscriber.SubscribeForNotaryRequests(l.notaryMainTXSigner); err != nil { - errCh <- fmt.Errorf("could not subscribe for notary requests: %w", err) + errCh <- fmt.Errorf("subscribe for notary requests: %w", err) return } } @@ -566,7 +566,7 @@ func NewListener(p ListenerParams) (Listener, error) { // The default capacity is 0, which means "infinite". pool, err := ants.NewPool(p.WorkerPoolCapacity) if err != nil { - return nil, fmt.Errorf("could not init worker pool: %w", err) + return nil, fmt.Errorf("init worker pool: %w", err) } return &listener{ diff --git a/pkg/morph/event/netmap/update_peer_notary.go b/pkg/morph/event/netmap/update_peer_notary.go index 0260810b83..993182ab49 100644 --- a/pkg/morph/event/netmap/update_peer_notary.go +++ b/pkg/morph/event/netmap/update_peer_notary.go @@ -10,7 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/opcode" ) -var errNilPubKey = errors.New("could not parse public key: public key is nil") +var errNilPubKey = errors.New("public key is nil") func (s *UpdatePeer) setPublicKey(v []byte) (err error) { if v == nil { @@ -19,7 +19,7 @@ func (s *UpdatePeer) setPublicKey(v []byte) (err error) { s.PubKey, err = keys.NewPublicKeyFromBytes(v, elliptic.P256()) if err != nil { - return fmt.Errorf("could not parse public key: %w", err) + return fmt.Errorf("parse public key: %w", err) } return diff --git a/pkg/morph/event/notary_preparator.go b/pkg/morph/event/notary_preparator.go index 37091f768c..40f5984a97 100644 --- a/pkg/morph/event/notary_preparator.go +++ b/pkg/morph/event/notary_preparator.go @@ -127,7 +127,7 @@ func (p Preparator) Prepare(nr *payload.P2PNotaryRequest) (NotaryEvent, error) { for { opCode, param, err = ctx.Next() if err != nil { - return nil, fmt.Errorf("could not get next opcode in script: %w", err) + return nil, fmt.Errorf("get next opcode in script: %w", err) } if opCode == opcode.RET { @@ -147,7 +147,7 @@ func (p Preparator) Prepare(nr *payload.P2PNotaryRequest) (NotaryEvent, error) { // retrieve contract's script hash contractHash, err := util.Uint160DecodeBytesBE(ops[opsLen-2].param) if err != nil { - return nil, fmt.Errorf("could not decode contract hash: %w", err) + return nil, fmt.Errorf("decode contract hash: %w", err) } // retrieve contract's method @@ -164,7 +164,7 @@ func (p Preparator) Prepare(nr *payload.P2PNotaryRequest) (NotaryEvent, error) { if len(args) != 0 { err = p.validateParameterOpcodes(args) if err != nil { - return nil, fmt.Errorf("could not validate arguments: %w", err) + return nil, fmt.Errorf("validate arguments: %w", err) } // without args packing opcodes @@ -206,7 +206,7 @@ func (p Preparator) validateNotaryRequest(nr *payload.P2PNotaryRequest) error { currentAlphabet, err := p.alphaKeys() if err != nil { - return fmt.Errorf("could not fetch Alphabet public keys: %w", err) + return fmt.Errorf("fetch Alphabet public keys: %w", err) } err = p.validateCosigners(ln, nr.MainTransaction.Signers, currentAlphabet) @@ -239,7 +239,7 @@ func (p Preparator) validateParameterOpcodes(ops []Op) error { argsLen, err := IntFromOpcode(ops[l-2]) if err != nil { - return fmt.Errorf("could not parse argument len: %w", err) + return fmt.Errorf("parse argument len: %w", err) } err = validateNestedArgs(argsLen, ops[:l-2]) @@ -273,7 +273,7 @@ func validateNestedArgs(expArgLen int64, ops []Op) error { argsLen, err := IntFromOpcode(ops[i-1]) if err != nil { - return fmt.Errorf("could not parse argument len: %w", err) + return fmt.Errorf("parse argument len: %w", err) } expArgLen += argsLen + 1 @@ -307,7 +307,7 @@ func (p Preparator) validateExpiration(fbTX *transaction.Transaction) error { currBlock, err := p.blockCounter.BlockCount() if err != nil { - return fmt.Errorf("could not fetch current chain height: %w", err) + return fmt.Errorf("fetch current chain height: %w", err) } if currBlock >= nvb.Height { @@ -327,7 +327,7 @@ func (p Preparator) validateCosigners(expected int, s []transaction.Signer, alph alphaVerificationScript, err := smartcontract.CreateMultiSigRedeemScript(len(alphaKeys)*2/3+1, alphaKeys) if err != nil { - return fmt.Errorf("could not get Alphabet verification script: %w", err) + return fmt.Errorf("get Alphabet verification script: %w", err) } if !s[1].Account.Equals(hash.Hash160(alphaVerificationScript)) { @@ -346,7 +346,7 @@ func (p Preparator) validateWitnesses(w []transaction.Witness, alphaKeys keys.Pu alphaVerificationScript, err := smartcontract.CreateMultiSigRedeemScript(len(alphaKeys)*2/3+1, alphaKeys) if err != nil { - return fmt.Errorf("could not get Alphabet verification script: %w", err) + return fmt.Errorf("get Alphabet verification script: %w", err) } // the second one must be witness of the current diff --git a/pkg/morph/event/rolemanagement/designate.go b/pkg/morph/event/rolemanagement/designate.go index 28c9680462..b384e436b6 100644 --- a/pkg/morph/event/rolemanagement/designate.go +++ b/pkg/morph/event/rolemanagement/designate.go @@ -26,7 +26,7 @@ func (Designate) MorphEvent() {} func ParseDesignate(e *state.ContainedNotificationEvent) (event.Event, error) { params, err := event.ParseStackArray(e) if err != nil { - return nil, fmt.Errorf("could not parse stack items from notify event: %w", err) + return nil, fmt.Errorf("parse stack items from notify event: %w", err) } if len(params) != 2 { From 7151c71d51615648233acda1479feb7f4ab86ce6 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 12 Dec 2024 15:06:20 +0300 Subject: [PATCH 1092/1413] [#1558] morph/client: Remove "could not"/"can't"/"failed to" from error messages Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/balance/balanceOf.go | 2 +- pkg/morph/client/balance/decimals.go | 2 +- pkg/morph/client/balance/transfer.go | 2 +- pkg/morph/client/client.go | 6 ++-- pkg/morph/client/container/containers_of.go | 2 +- pkg/morph/client/container/delete.go | 2 +- pkg/morph/client/container/deletion_info.go | 8 ++--- pkg/morph/client/container/get.go | 14 ++++---- pkg/morph/client/container/list.go | 4 +-- pkg/morph/client/container/put.go | 2 +- pkg/morph/client/frostfsid/subject.go | 6 ++-- pkg/morph/client/netmap/epoch.go | 4 +-- pkg/morph/client/netmap/innerring.go | 6 ++-- pkg/morph/client/netmap/new_epoch.go | 4 +-- pkg/morph/client/netmap/peer.go | 2 +- pkg/morph/client/nns.go | 2 +- pkg/morph/client/notary.go | 38 ++++++++++----------- pkg/morph/client/static.go | 2 +- pkg/morph/client/util.go | 2 +- 19 files changed, 55 insertions(+), 55 deletions(-) diff --git a/pkg/morph/client/balance/balanceOf.go b/pkg/morph/client/balance/balanceOf.go index 12a499ffbe..a5fb8e82ac 100644 --- a/pkg/morph/client/balance/balanceOf.go +++ b/pkg/morph/client/balance/balanceOf.go @@ -29,7 +29,7 @@ func (c *Client) BalanceOf(id user.ID) (*big.Int, error) { amount, err := client.BigIntFromStackItem(prms[0]) if err != nil { - return nil, fmt.Errorf("could not get integer stack item from stack item (%s): %w", balanceOfMethod, err) + return nil, fmt.Errorf("get integer stack item from stack item (%s): %w", balanceOfMethod, err) } return amount, nil } diff --git a/pkg/morph/client/balance/decimals.go b/pkg/morph/client/balance/decimals.go index 28329ee6e0..c2a66ddedd 100644 --- a/pkg/morph/client/balance/decimals.go +++ b/pkg/morph/client/balance/decimals.go @@ -21,7 +21,7 @@ func (c *Client) Decimals() (uint32, error) { decimals, err := client.IntFromStackItem(prms[0]) if err != nil { - return 0, fmt.Errorf("could not get integer stack item from stack item (%s): %w", decimalsMethod, err) + return 0, fmt.Errorf("get integer stack item from stack item (%s): %w", decimalsMethod, err) } return uint32(decimals), nil } diff --git a/pkg/morph/client/balance/transfer.go b/pkg/morph/client/balance/transfer.go index 16c8f39820..52d69dccb8 100644 --- a/pkg/morph/client/balance/transfer.go +++ b/pkg/morph/client/balance/transfer.go @@ -39,7 +39,7 @@ func (c *Client) TransferX(ctx context.Context, p TransferPrm) error { _, err = c.client.Invoke(ctx, prm) if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", transferXMethod, err) + return fmt.Errorf("invoke method (%s): %w", transferXMethod, err) } return nil } diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index a0c29141bd..5a5d24900d 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -196,7 +196,7 @@ func (c *Client) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.F txHash, vub, err := c.rpcActor.SendTunedCall(contract, method, nil, addFeeCheckerModifier(int64(fee)), args...) if err != nil { - return InvokeRes{}, fmt.Errorf("could not invoke %s: %w", method, err) + return InvokeRes{}, fmt.Errorf("invoke %s: %w", method, err) } c.logger.Debug(ctx, logs.ClientNeoClientInvoke, @@ -509,7 +509,7 @@ func (c *Client) NeoFSAlphabetList() (res keys.PublicKeys, err error) { list, err := c.roleList(noderoles.NeoFSAlphabet) if err != nil { - return nil, fmt.Errorf("can't get alphabet nodes role list: %w", err) + return nil, fmt.Errorf("get alphabet nodes role list: %w", err) } return list, nil @@ -523,7 +523,7 @@ func (c *Client) GetDesignateHash() util.Uint160 { func (c *Client) roleList(r noderoles.Role) (keys.PublicKeys, error) { height, err := c.rpcActor.GetBlockCount() if err != nil { - return nil, fmt.Errorf("can't get chain height: %w", err) + return nil, fmt.Errorf("get chain height: %w", err) } return c.rolemgmt.GetDesignatedByRole(r, height) diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go index c4db0fe6e8..5fe15be0d9 100644 --- a/pkg/morph/client/container/containers_of.go +++ b/pkg/morph/client/container/containers_of.go @@ -26,7 +26,7 @@ func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { cb := func(item stackitem.Item) error { rawID, err := client.BytesFromStackItem(item) if err != nil { - return fmt.Errorf("could not get byte array from stack item (%s): %w", containersOfMethod, err) + return fmt.Errorf("get byte array from stack item (%s): %w", containersOfMethod, err) } var id cid.ID diff --git a/pkg/morph/client/container/delete.go b/pkg/morph/client/container/delete.go index ef5cc8c384..09912efa52 100644 --- a/pkg/morph/client/container/delete.go +++ b/pkg/morph/client/container/delete.go @@ -78,7 +78,7 @@ func (c *Client) Delete(ctx context.Context, p DeletePrm) (uint32, error) { res, err := c.client.Invoke(ctx, prm) if err != nil { - return 0, fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err) + return 0, fmt.Errorf("invoke method (%s): %w", deleteMethod, err) } return res.VUB, nil } diff --git a/pkg/morph/client/container/deletion_info.go b/pkg/morph/client/container/deletion_info.go index 436ca3c016..b86e0ce9c0 100644 --- a/pkg/morph/client/container/deletion_info.go +++ b/pkg/morph/client/container/deletion_info.go @@ -46,7 +46,7 @@ func (c *Client) DeletionInfo(cid []byte) (*containercore.DelInfo, error) { arr, err := client.ArrayFromStackItem(res[0]) if err != nil { - return nil, fmt.Errorf("could not get item array of container (%s): %w", deletionInfoMethod, err) + return nil, fmt.Errorf("get item array of container (%s): %w", deletionInfoMethod, err) } if len(arr) != 2 { @@ -55,17 +55,17 @@ func (c *Client) DeletionInfo(cid []byte) (*containercore.DelInfo, error) { rawOwner, err := client.BytesFromStackItem(arr[0]) if err != nil { - return nil, fmt.Errorf("could not get byte array of container (%s): %w", deletionInfoMethod, err) + return nil, fmt.Errorf("get byte array of container (%s): %w", deletionInfoMethod, err) } var owner user.ID if err := owner.DecodeString(base58.Encode(rawOwner)); err != nil { - return nil, fmt.Errorf("could not decode container owner id (%s): %w", deletionInfoMethod, err) + return nil, fmt.Errorf("decode container owner id (%s): %w", deletionInfoMethod, err) } epoch, err := client.BigIntFromStackItem(arr[1]) if err != nil { - return nil, fmt.Errorf("could not get byte array of container signature (%s): %w", deletionInfoMethod, err) + return nil, fmt.Errorf("get byte array of container signature (%s): %w", deletionInfoMethod, err) } return &containercore.DelInfo{ diff --git a/pkg/morph/client/container/get.go b/pkg/morph/client/container/get.go index 1d84e9109e..2ab58bf017 100644 --- a/pkg/morph/client/container/get.go +++ b/pkg/morph/client/container/get.go @@ -60,7 +60,7 @@ func (c *Client) Get(cid []byte) (*containercore.Container, error) { arr, err := client.ArrayFromStackItem(res[0]) if err != nil { - return nil, fmt.Errorf("could not get item array of container (%s): %w", getMethod, err) + return nil, fmt.Errorf("get item array of container (%s): %w", getMethod, err) } if len(arr) != 4 { @@ -69,29 +69,29 @@ func (c *Client) Get(cid []byte) (*containercore.Container, error) { cnrBytes, err := client.BytesFromStackItem(arr[0]) if err != nil { - return nil, fmt.Errorf("could not get byte array of container (%s): %w", getMethod, err) + return nil, fmt.Errorf("get byte array of container (%s): %w", getMethod, err) } sigBytes, err := client.BytesFromStackItem(arr[1]) if err != nil { - return nil, fmt.Errorf("could not get byte array of container signature (%s): %w", getMethod, err) + return nil, fmt.Errorf("get byte array of container signature (%s): %w", getMethod, err) } pub, err := client.BytesFromStackItem(arr[2]) if err != nil { - return nil, fmt.Errorf("could not get byte array of public key (%s): %w", getMethod, err) + return nil, fmt.Errorf("get byte array of public key (%s): %w", getMethod, err) } tokBytes, err := client.BytesFromStackItem(arr[3]) if err != nil { - return nil, fmt.Errorf("could not get byte array of session token (%s): %w", getMethod, err) + return nil, fmt.Errorf("get byte array of session token (%s): %w", getMethod, err) } var cnr containercore.Container if err := cnr.Value.Unmarshal(cnrBytes); err != nil { // use other major version if there any - return nil, fmt.Errorf("can't unmarshal container: %w", err) + return nil, fmt.Errorf("unmarshal container: %w", err) } if len(tokBytes) > 0 { @@ -99,7 +99,7 @@ func (c *Client) Get(cid []byte) (*containercore.Container, error) { err = cnr.Session.Unmarshal(tokBytes) if err != nil { - return nil, fmt.Errorf("could not unmarshal session token: %w", err) + return nil, fmt.Errorf("unmarshal session token: %w", err) } } diff --git a/pkg/morph/client/container/list.go b/pkg/morph/client/container/list.go index 55317375a6..d9719aedd2 100644 --- a/pkg/morph/client/container/list.go +++ b/pkg/morph/client/container/list.go @@ -34,14 +34,14 @@ func (c *Client) list(idUser *user.ID) ([]cid.ID, error) { res, err = client.ArrayFromStackItem(res[0]) if err != nil { - return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", listMethod, err) + return nil, fmt.Errorf("get stack item array from stack item (%s): %w", listMethod, err) } cidList := make([]cid.ID, 0, len(res)) for i := range res { rawID, err := client.BytesFromStackItem(res[i]) if err != nil { - return nil, fmt.Errorf("could not get byte array from stack item (%s): %w", listMethod, err) + return nil, fmt.Errorf("get byte array from stack item (%s): %w", listMethod, err) } var id cid.ID diff --git a/pkg/morph/client/container/put.go b/pkg/morph/client/container/put.go index 1eb03694f4..3bb84eb87c 100644 --- a/pkg/morph/client/container/put.go +++ b/pkg/morph/client/container/put.go @@ -117,7 +117,7 @@ func (c *Client) Put(ctx context.Context, p PutPrm) error { _, err := c.client.Invoke(ctx, prm) if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", method, err) + return fmt.Errorf("invoke method (%s): %w", method, err) } return nil } diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index 7c93f49222..305f3ce098 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -31,7 +31,7 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) subj, err := frostfsidclient.ParseSubject(structArr) if err != nil { - return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) + return nil, fmt.Errorf("parse test invocation result (%s): %w", methodGetSubject, err) } return subj, nil @@ -54,7 +54,7 @@ func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.Subject subj, err := frostfsidclient.ParseSubjectExtended(structArr) if err != nil { - return nil, fmt.Errorf("could not parse test invocation result (%s): %w", methodGetSubject, err) + return nil, fmt.Errorf("parse test invocation result (%s): %w", methodGetSubject, err) } return subj, nil @@ -67,7 +67,7 @@ func checkStackItem(res []stackitem.Item) (structArr []stackitem.Item, err error structArr, err = client.ArrayFromStackItem(res[0]) if err != nil { - return nil, fmt.Errorf("could not get item array of container (%s): %w", methodGetSubject, err) + return nil, fmt.Errorf("get item array of container (%s): %w", methodGetSubject, err) } return } diff --git a/pkg/morph/client/netmap/epoch.go b/pkg/morph/client/netmap/epoch.go index 6d909a7a17..6d73949984 100644 --- a/pkg/morph/client/netmap/epoch.go +++ b/pkg/morph/client/netmap/epoch.go @@ -25,7 +25,7 @@ func (c *Client) Epoch() (uint64, error) { num, err := client.IntFromStackItem(items[0]) if err != nil { - return 0, fmt.Errorf("could not get number from stack item (%s): %w", epochMethod, err) + return 0, fmt.Errorf("get number from stack item (%s): %w", epochMethod, err) } return uint64(num), nil } @@ -49,7 +49,7 @@ func (c *Client) LastEpochBlock() (uint32, error) { block, err := client.IntFromStackItem(items[0]) if err != nil { - return 0, fmt.Errorf("could not get number from stack item (%s): %w", + return 0, fmt.Errorf("get number from stack item (%s): %w", lastEpochBlockMethod, err) } return uint32(block), nil diff --git a/pkg/morph/client/netmap/innerring.go b/pkg/morph/client/netmap/innerring.go index 824827d6fb..0cfad4c82c 100644 --- a/pkg/morph/client/netmap/innerring.go +++ b/pkg/morph/client/netmap/innerring.go @@ -59,7 +59,7 @@ func irKeysFromStackItem(stack []stackitem.Item, method string) (keys.PublicKeys irs, err := client.ArrayFromStackItem(stack[0]) if err != nil { - return nil, fmt.Errorf("could not get stack item array from stack item (%s): %w", method, err) + return nil, fmt.Errorf("get stack item array from stack item (%s): %w", method, err) } irKeys := make(keys.PublicKeys, len(irs)) @@ -79,7 +79,7 @@ const irNodeFixedPrmNumber = 1 func irKeyFromStackItem(prm stackitem.Item) (*keys.PublicKey, error) { prms, err := client.ArrayFromStackItem(prm) if err != nil { - return nil, fmt.Errorf("could not get stack item array (IRNode): %w", err) + return nil, fmt.Errorf("get stack item array (IRNode): %w", err) } else if ln := len(prms); ln != irNodeFixedPrmNumber { return nil, fmt.Errorf( "unexpected stack item count (IRNode): expected %d, has %d", @@ -90,7 +90,7 @@ func irKeyFromStackItem(prm stackitem.Item) (*keys.PublicKey, error) { byteKey, err := client.BytesFromStackItem(prms[0]) if err != nil { - return nil, fmt.Errorf("could not parse bytes from stack item (IRNode): %w", err) + return nil, fmt.Errorf("parse bytes from stack item (IRNode): %w", err) } return keys.NewPublicKeyFromBytes(byteKey, elliptic.P256()) diff --git a/pkg/morph/client/netmap/new_epoch.go b/pkg/morph/client/netmap/new_epoch.go index efcdfd7b60..341b20935d 100644 --- a/pkg/morph/client/netmap/new_epoch.go +++ b/pkg/morph/client/netmap/new_epoch.go @@ -16,7 +16,7 @@ func (c *Client) NewEpoch(ctx context.Context, epoch uint64) error { _, err := c.client.Invoke(ctx, prm) if err != nil { - return fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) + return fmt.Errorf("invoke method (%s): %w", newEpochMethod, err) } return nil } @@ -34,7 +34,7 @@ func (c *Client) NewEpochControl(ctx context.Context, epoch uint64, vub uint32) res, err := c.client.Invoke(ctx, prm) if err != nil { - return 0, fmt.Errorf("could not invoke method (%s): %w", newEpochMethod, err) + return 0, fmt.Errorf("invoke method (%s): %w", newEpochMethod, err) } return res.VUB, nil } diff --git a/pkg/morph/client/netmap/peer.go b/pkg/morph/client/netmap/peer.go index 949e8cb63a..e83acde390 100644 --- a/pkg/morph/client/netmap/peer.go +++ b/pkg/morph/client/netmap/peer.go @@ -41,7 +41,7 @@ func (c *Client) AddPeer(ctx context.Context, p AddPeerPrm) error { prm.InvokePrmOptional = p.InvokePrmOptional if _, err := c.client.Invoke(ctx, prm); err != nil { - return fmt.Errorf("could not invoke method (%s): %w", method, err) + return fmt.Errorf("invoke method (%s): %w", method, err) } return nil } diff --git a/pkg/morph/client/nns.go b/pkg/morph/client/nns.go index 218f7ad8e2..f292dccf1a 100644 --- a/pkg/morph/client/nns.go +++ b/pkg/morph/client/nns.go @@ -107,7 +107,7 @@ func (c *Client) NNSHash() (util.Uint160, error) { func nnsResolveItem(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (stackitem.Item, error) { found, err := exists(c, nnsHash, domain) if err != nil { - return nil, fmt.Errorf("could not check presence in NNS contract for %s: %w", domain, err) + return nil, fmt.Errorf("check presence in NNS contract for %s: %w", domain, err) } if !found { diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 8516c89a97..1e80be9211 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -62,7 +62,7 @@ const ( notaryExpirationOfMethod = "expirationOf" setDesignateMethod = "designateAsRole" - notaryBalanceErrMsg = "can't fetch notary balance" + notaryBalanceErrMsg = "fetch notary balance" notaryNotEnabledPanicMsg = "notary support was not enabled on this client" ) @@ -155,12 +155,12 @@ func (c *Client) DepositNotary(ctx context.Context, amount fixedn.Fixed8, delta bc, err := c.rpcActor.GetBlockCount() if err != nil { - return util.Uint256{}, fmt.Errorf("can't get blockchain height: %w", err) + return util.Uint256{}, fmt.Errorf("get blockchain height: %w", err) } currentTill, err := c.depositExpirationOf() if err != nil { - return util.Uint256{}, fmt.Errorf("can't get previous expiration value: %w", err) + return util.Uint256{}, fmt.Errorf("get previous expiration value: %w", err) } till := max(int64(bc+delta), currentTill) @@ -197,7 +197,7 @@ func (c *Client) depositNotary(ctx context.Context, amount fixedn.Fixed8, till i []any{c.acc.PrivateKey().GetScriptHash(), till}) if err != nil { if !errors.Is(err, neorpc.ErrAlreadyExists) { - return util.Uint256{}, 0, fmt.Errorf("can't make notary deposit: %w", err) + return util.Uint256{}, 0, fmt.Errorf("make notary deposit: %w", err) } // Transaction is already in mempool waiting to be processed. @@ -289,7 +289,7 @@ func (c *Client) UpdateNotaryList(ctx context.Context, prm UpdateNotaryListPrm) nonce, vub, err := c.CalculateNonceAndVUB(&prm.hash) if err != nil { - return fmt.Errorf("could not calculate nonce and `valicUntilBlock` values: %w", err) + return fmt.Errorf("calculate nonce and `valicUntilBlock` values: %w", err) } return c.notaryInvokeAsCommittee( @@ -338,7 +338,7 @@ func (c *Client) UpdateNeoFSAlphabetList(ctx context.Context, prm UpdateAlphabet nonce, vub, err := c.CalculateNonceAndVUB(&prm.hash) if err != nil { - return fmt.Errorf("could not calculate nonce and `valicUntilBlock` values: %w", err) + return fmt.Errorf("calculate nonce and `valicUntilBlock` values: %w", err) } return c.notaryInvokeAsCommittee( @@ -407,7 +407,7 @@ func (c *Client) NotarySignAndInvokeTX(mainTx *transaction.Transaction) error { alphabetList, err := c.notary.alphabetSource() if err != nil { - return fmt.Errorf("could not fetch current alphabet keys: %w", err) + return fmt.Errorf("fetch current alphabet keys: %w", err) } cosigners, err := c.notaryCosignersFromTx(mainTx, alphabetList) @@ -529,24 +529,24 @@ func (c *Client) notaryCosignersFromTx(mainTx *transaction.Transaction, alphabet if ok { pub, err := keys.NewPublicKeyFromBytes(pubBytes, elliptic.P256()) if err != nil { - return nil, fmt.Errorf("failed to parse verification script of signer #2: invalid public key: %w", err) + return nil, fmt.Errorf("parse verification script of signer #2: invalid public key: %w", err) } acc = notary.FakeSimpleAccount(pub) } else { m, pubsBytes, ok := vm.ParseMultiSigContract(script) if !ok { - return nil, errors.New("failed to parse verification script of signer #2: unknown witness type") + return nil, errors.New("parse verification script of signer #2: unknown witness type") } pubs := make(keys.PublicKeys, len(pubsBytes)) for i := range pubs { pubs[i], err = keys.NewPublicKeyFromBytes(pubsBytes[i], elliptic.P256()) if err != nil { - return nil, fmt.Errorf("failed to parse verification script of signer #2: invalid public key #%d: %w", i, err) + return nil, fmt.Errorf("parse verification script of signer #2: invalid public key #%d: %w", i, err) } } acc, err = notary.FakeMultisigAccount(m, pubs) if err != nil { - return nil, fmt.Errorf("failed to create fake account for signer #2: %w", err) + return nil, fmt.Errorf("create fake account for signer #2: %w", err) } } } @@ -623,7 +623,7 @@ func (c *Client) notaryMultisigAccount(ir []*keys.PublicKey, committee, invokedB err := multisigAccount.ConvertMultisig(m, ir) if err != nil { // wrap error as FrostFS-specific since the call is not related to any client - return nil, wrapFrostFSError(fmt.Errorf("can't convert account to inner ring multisig wallet: %w", err)) + return nil, wrapFrostFSError(fmt.Errorf("convert account to inner ring multisig wallet: %w", err)) } } else { // alphabet multisig redeem script is @@ -632,7 +632,7 @@ func (c *Client) notaryMultisigAccount(ir []*keys.PublicKey, committee, invokedB multisigAccount, err = notary.FakeMultisigAccount(m, ir) if err != nil { // wrap error as FrostFS-specific since the call is not related to any client - return nil, wrapFrostFSError(fmt.Errorf("can't make inner ring multisig wallet: %w", err)) + return nil, wrapFrostFSError(fmt.Errorf("make inner ring multisig wallet: %w", err)) } } @@ -642,7 +642,7 @@ func (c *Client) notaryMultisigAccount(ir []*keys.PublicKey, committee, invokedB func (c *Client) notaryTxValidationLimit() (uint32, error) { bc, err := c.rpcActor.GetBlockCount() if err != nil { - return 0, fmt.Errorf("can't get current blockchain height: %w", err) + return 0, fmt.Errorf("get current blockchain height: %w", err) } minTime := bc + c.notary.txValidTime @@ -663,7 +663,7 @@ func (c *Client) depositExpirationOf() (int64, error) { currentTillBig, err := expirationRes[0].TryInteger() if err != nil { - return 0, fmt.Errorf("can't parse deposit till value: %w", err) + return 0, fmt.Errorf("parse deposit till value: %w", err) } return currentTillBig.Int64(), nil @@ -742,12 +742,12 @@ func alreadyOnChainError(err error) bool { func CalculateNotaryDepositAmount(c *Client, gasMul, gasDiv int64) (fixedn.Fixed8, error) { notaryBalance, err := c.GetNotaryDeposit() if err != nil { - return 0, fmt.Errorf("could not get notary balance: %w", err) + return 0, fmt.Errorf("get notary balance: %w", err) } gasBalance, err := c.GasBalance() if err != nil { - return 0, fmt.Errorf("could not get GAS balance: %w", err) + return 0, fmt.Errorf("get GAS balance: %w", err) } if gasBalance == 0 { @@ -796,12 +796,12 @@ func (c *Client) calculateNonceAndVUB(hash *util.Uint256, roundBlockHeight bool) if hash != nil { height, err = c.getTransactionHeight(*hash) if err != nil { - return 0, 0, fmt.Errorf("could not get transaction height: %w", err) + return 0, 0, fmt.Errorf("get transaction height: %w", err) } } else { height, err = c.rpcActor.GetBlockCount() if err != nil { - return 0, 0, fmt.Errorf("could not get chain height: %w", err) + return 0, 0, fmt.Errorf("get chain height: %w", err) } } diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index be4c091825..21adebd9e2 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -159,7 +159,7 @@ func (s StaticClient) Invoke(ctx context.Context, prm InvokePrm) (InvokeRes, err nonce, vub, err = s.client.CalculateNonceAndVUB(prm.hash) } if err != nil { - return InvokeRes{}, fmt.Errorf("could not calculate nonce and VUB for notary alphabet invoke: %w", err) + return InvokeRes{}, fmt.Errorf("calculate nonce and VUB for notary alphabet invoke: %w", err) } vubP = &vub diff --git a/pkg/morph/client/util.go b/pkg/morph/client/util.go index cd55d6bd2b..f68d39beba 100644 --- a/pkg/morph/client/util.go +++ b/pkg/morph/client/util.go @@ -53,7 +53,7 @@ func BytesFromStackItem(param stackitem.Item) ([]byte, error) { case stackitem.IntegerT: n, err := param.TryInteger() if err != nil { - return nil, fmt.Errorf("can't parse integer bytes: %w", err) + return nil, fmt.Errorf("parse integer bytes: %w", err) } return n.Bytes(), nil From d165ac042cf9f34a54117ea002d789fae0b0905b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 12 Dec 2024 15:27:17 +0300 Subject: [PATCH 1093/1413] [#1558] morph/client: Reuse notary rpcclient wrapper Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/notary.go | 44 ++++++-------------------------------- 1 file changed, 7 insertions(+), 37 deletions(-) diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 1e80be9211..dbd58a53ac 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -58,16 +58,11 @@ const ( defaultNotaryValidTime = 50 defaultNotaryRoundTime = 100 - notaryBalanceOfMethod = "balanceOf" - notaryExpirationOfMethod = "expirationOf" - setDesignateMethod = "designateAsRole" + setDesignateMethod = "designateAsRole" - notaryBalanceErrMsg = "fetch notary balance" notaryNotEnabledPanicMsg = "notary support was not enabled on this client" ) -var errUnexpectedItems = errors.New("invalid number of NEO VM arguments on stack") - func defaultNotaryConfig(c *Client) *notaryCfg { return ¬aryCfg{ txValidTime: defaultNotaryValidTime, @@ -158,12 +153,13 @@ func (c *Client) DepositNotary(ctx context.Context, amount fixedn.Fixed8, delta return util.Uint256{}, fmt.Errorf("get blockchain height: %w", err) } - currentTill, err := c.depositExpirationOf() + r := notary.NewReader(c.rpcActor) + currentTill, err := r.ExpirationOf(c.acc.PrivateKey().GetScriptHash()) if err != nil { return util.Uint256{}, fmt.Errorf("get previous expiration value: %w", err) } - till := max(int64(bc+delta), currentTill) + till := max(int64(bc+delta), int64(currentTill)) res, _, err := c.depositNotary(ctx, amount, till) return res, err } @@ -237,18 +233,10 @@ func (c *Client) GetNotaryDeposit() (res int64, err error) { sh := c.acc.PrivateKey().PublicKey().GetScriptHash() - items, err := c.TestInvoke(c.notary.notary, notaryBalanceOfMethod, sh) + r := notary.NewReader(c.rpcActor) + bigIntDeposit, err := r.BalanceOf(sh) if err != nil { - return 0, fmt.Errorf("test invoke (%s): %w", notaryBalanceOfMethod, err) - } - - if len(items) != 1 { - return 0, wrapFrostFSError(fmt.Errorf("%v: %w", notaryBalanceErrMsg, errUnexpectedItems)) - } - - bigIntDeposit, err := items[0].TryInteger() - if err != nil { - return 0, wrapFrostFSError(fmt.Errorf("%v: %w", notaryBalanceErrMsg, err)) + return 0, fmt.Errorf("get notary deposit: %w", err) } return bigIntDeposit.Int64(), nil @@ -651,24 +639,6 @@ func (c *Client) notaryTxValidationLimit() (uint32, error) { return rounded, nil } -func (c *Client) depositExpirationOf() (int64, error) { - expirationRes, err := c.TestInvoke(c.notary.notary, notaryExpirationOfMethod, c.acc.PrivateKey().GetScriptHash()) - if err != nil { - return 0, fmt.Errorf("test invoke (%s): %w", notaryExpirationOfMethod, err) - } - - if len(expirationRes) != 1 { - return 0, fmt.Errorf("method returned unexpected item count: %d", len(expirationRes)) - } - - currentTillBig, err := expirationRes[0].TryInteger() - if err != nil { - return 0, fmt.Errorf("parse deposit till value: %w", err) - } - - return currentTillBig.Int64(), nil -} - // sigCount returns the number of required signature. // For FrostFS Alphabet M is a 2/3+1 of it (like in dBFT). // If committee is true, returns M as N/2+1. From 2af3409d39f173e749fb6b1396cc2f4c03d1b179 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 13 Dec 2024 12:59:35 +0300 Subject: [PATCH 1094/1413] [#1510] metabase/test: Fix `BenchmarkGet` Fix misplaced `(*DB).Close` (broken after 47dcfa20f3) Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/metabase/get_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/get_test.go b/pkg/local_object_storage/metabase/get_test.go index c93d2c992b..98c4284105 100644 --- a/pkg/local_object_storage/metabase/get_test.go +++ b/pkg/local_object_storage/metabase/get_test.go @@ -219,7 +219,6 @@ func benchmarkGet(b *testing.B, numOfObj int) { meta.WithMaxBatchSize(batchSize), meta.WithMaxBatchDelay(10*time.Millisecond), ) - defer func() { require.NoError(b, db.Close(context.Background())) }() addrs := make([]oid.Address, 0, numOfObj) for range numOfObj { @@ -234,6 +233,7 @@ func benchmarkGet(b *testing.B, numOfObj int) { } db, addrs := prepareDb(runtime.NumCPU()) + defer func() { require.NoError(b, db.Close(context.Background())) }() b.Run("parallel", func(b *testing.B) { b.ReportAllocs() From 8ba9f31fca82ca8c0ccabdbb7254b2ad67a2f6fe Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 13 Dec 2024 13:04:12 +0300 Subject: [PATCH 1095/1413] [#1510] metabase/test: Fix `BenchmarkListWithCursor` - Fix misplaced `(*DB).Close` (broken after 47dcfa20f3) - Use `errors.Is` for error checking (broken after fcdbf5e509) Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/metabase/list_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 6f64630719..1d8beb1758 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -18,6 +18,8 @@ import ( func BenchmarkListWithCursor(b *testing.B) { db := listWithCursorPrepareDB(b) + defer func() { require.NoError(b, db.Close(context.Background())) }() + b.Run("1 item", func(b *testing.B) { benchmarkListWithCursor(b, db, 1) }) @@ -33,7 +35,6 @@ func listWithCursorPrepareDB(b *testing.B) *meta.DB { db := newDB(b, meta.WithMaxBatchSize(1), meta.WithBoltDBOptions(&bbolt.Options{ NoSync: true, })) // faster single-thread generation - defer func() { require.NoError(b, db.Close(context.Background())) }() obj := testutil.GenerateObject() for i := range 100_000 { // should be a multiple of all batch sizes @@ -55,7 +56,7 @@ func benchmarkListWithCursor(b *testing.B, db *meta.DB, batchSize int) { for range b.N { res, err := db.ListWithCursor(context.Background(), prm) if err != nil { - if err != meta.ErrEndOfListing { + if errors.Is(err, meta.ErrEndOfListing) { b.Fatalf("error: %v", err) } prm.SetCursor(nil) From f0c43c8d80e79b12111e8e8d1574e847f5162ac1 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 13 Dec 2024 11:44:56 +0300 Subject: [PATCH 1096/1413] [#1502] Use `zap.Error` for logging errors Use `zap.Error` instead of `zap.String` for logging errors: change all expressions like `zap.String("error", err.Error())` or `zap.String("err", err.Error())` to `zap.Error(err)`. Leave similar expressions with other messages unchanged, for example, `zap.String("last_error", lastErr.Error())` or `zap.String("reason", ctx.Err().Error())`. This change was made by applying the following patch: ```diff @@ var err expression @@ -zap.String("error", err.Error()) +zap.Error(err) @@ var err expression @@ -zap.String("err", err.Error()) +zap.Error(err) ``` Signed-off-by: Aleksey Savchuk --- cmd/frostfs-ir/httpcomponent.go | 2 +- cmd/frostfs-ir/main.go | 4 ++-- cmd/frostfs-ir/pprof.go | 2 +- cmd/frostfs-node/config.go | 4 ++-- cmd/frostfs-node/main.go | 2 +- cmd/frostfs-node/morph.go | 4 ++-- cmd/frostfs-node/netmap.go | 2 +- cmd/frostfs-node/object.go | 4 ++-- cmd/frostfs-node/tree.go | 2 +- pkg/core/object/sender_classifier.go | 4 ++-- pkg/innerring/initialization.go | 4 ++-- pkg/innerring/innerring.go | 4 ++-- .../processors/alphabet/process_emit.go | 10 +++++----- .../processors/container/process_container.go | 8 ++++---- .../processors/frostfs/process_assets.go | 2 +- .../processors/governance/process_update.go | 18 ++++++++--------- .../processors/netmap/process_cleanup.go | 2 +- .../processors/netmap/process_epoch.go | 8 ++++---- .../processors/netmap/process_peers.go | 2 +- pkg/innerring/state.go | 8 ++++---- .../blobstor/blobovniczatree/delete.go | 2 +- .../blobstor/blobovniczatree/exists.go | 2 +- .../blobstor/blobovniczatree/get.go | 2 +- .../blobstor/blobovniczatree/get_range.go | 2 +- .../blobstor/blobovniczatree/iterate.go | 4 ++-- .../blobstor/blobovniczatree/manager.go | 4 ++-- .../blobstor/blobovniczatree/put.go | 4 ++-- pkg/local_object_storage/blobstor/control.go | 2 +- pkg/local_object_storage/blobstor/exists.go | 2 +- .../blobstor/fstree/fstree.go | 4 ++-- pkg/local_object_storage/blobstor/iterate.go | 2 +- pkg/local_object_storage/engine/control.go | 2 +- pkg/local_object_storage/engine/delete.go | 6 +++--- pkg/local_object_storage/engine/engine.go | 4 ++-- pkg/local_object_storage/engine/get.go | 2 +- pkg/local_object_storage/engine/put.go | 6 +++--- pkg/local_object_storage/engine/range.go | 2 +- pkg/local_object_storage/shard/control.go | 2 +- pkg/local_object_storage/shard/delete.go | 4 ++-- pkg/local_object_storage/shard/gc.go | 20 +++++++++---------- pkg/local_object_storage/shard/inhume.go | 2 +- pkg/local_object_storage/shard/list.go | 2 +- pkg/local_object_storage/shard/put.go | 2 +- pkg/morph/client/client.go | 4 ++-- pkg/morph/event/listener.go | 12 +++++------ pkg/morph/event/utils.go | 2 +- pkg/services/object/delete/delete.go | 2 +- pkg/services/object/search/container.go | 8 ++++---- pkg/services/object/search/local.go | 2 +- pkg/services/object/search/search.go | 2 +- pkg/services/object/util/log.go | 4 ++-- pkg/services/policer/check.go | 2 +- pkg/services/policer/ec.go | 2 +- pkg/services/policer/process.go | 2 +- pkg/services/replicator/process.go | 2 +- pkg/services/tree/replicator.go | 4 ++-- 56 files changed, 114 insertions(+), 114 deletions(-) diff --git a/cmd/frostfs-ir/httpcomponent.go b/cmd/frostfs-ir/httpcomponent.go index a8eef60100..dd70fc91c3 100644 --- a/cmd/frostfs-ir/httpcomponent.go +++ b/cmd/frostfs-ir/httpcomponent.go @@ -77,7 +77,7 @@ func (c *httpComponent) reload(ctx context.Context) { log.Info(ctx, c.name+" config updated") if err := c.shutdown(ctx); err != nil { log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, - zap.String("error", err.Error()), + zap.Error(err), ) } else { c.init(ctx) diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index e86c04b9ed..ade64ba84e 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -119,12 +119,12 @@ func shutdown(ctx context.Context) { innerRing.Stop(ctx) if err := metricsCmp.shutdown(ctx); err != nil { log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, - zap.String("error", err.Error()), + zap.Error(err), ) } if err := pprofCmp.shutdown(ctx); err != nil { log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, - zap.String("error", err.Error()), + zap.Error(err), ) } diff --git a/cmd/frostfs-ir/pprof.go b/cmd/frostfs-ir/pprof.go index 8e81d8b85e..2aebcde7f0 100644 --- a/cmd/frostfs-ir/pprof.go +++ b/cmd/frostfs-ir/pprof.go @@ -58,7 +58,7 @@ func (c *pprofComponent) reload(ctx context.Context) { log.Info(ctx, c.name+" config updated") if err := c.shutdown(ctx); err != nil { log.Debug(ctx, logs.FrostFSIRCouldNotShutdownHTTPServer, - zap.String("error", err.Error())) + zap.Error(err)) return } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 9b727e41ad..6950c9e24b 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1119,7 +1119,7 @@ func initLocalStorage(ctx context.Context, c *cfg) { err := ls.Close(context.WithoutCancel(ctx)) if err != nil { c.log.Info(ctx, logs.FrostFSNodeStorageEngineClosingFailure, - zap.String("error", err.Error()), + zap.Error(err), ) } else { c.log.Info(ctx, logs.FrostFSNodeAllComponentsOfTheStorageEngineClosedSuccessfully) @@ -1209,7 +1209,7 @@ func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) { if err != nil { c.log.Error(ctx, logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, zap.Uint64("epoch", epoch), - zap.String("error", err.Error())) + zap.Error(err)) return } diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index f8854ab3cf..3c15dc4396 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -134,7 +134,7 @@ func stopAndLog(ctx context.Context, c *cfg, name string, stopper func(context.C err := stopper(ctx) if err != nil { c.log.Debug(ctx, fmt.Sprintf("could not shutdown %s server", name), - zap.String("error", err.Error()), + zap.Error(err), ) } diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 0d4e8a1be2..5415da12a4 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -96,7 +96,7 @@ func initMorphClient(ctx context.Context, c *cfg) { if err != nil { c.log.Info(ctx, logs.FrostFSNodeFailedToCreateNeoRPCClient, zap.Any("endpoints", addresses), - zap.String("error", err.Error()), + zap.Error(err), ) fatalOnErr(err) @@ -168,7 +168,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { fromSideChainBlock, err := c.persistate.UInt32(persistateSideChainLastBlockKey) if err != nil { fromSideChainBlock = 0 - c.log.Warn(ctx, logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) + c.log.Warn(ctx, logs.FrostFSNodeCantGetLastProcessedSideChainBlockNumber, zap.Error(err)) } subs, err = subscriber.New(ctx, &subscriber.Params{ diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index e94428fcb7..2eb4cd132c 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -197,7 +197,7 @@ func addNewEpochNotificationHandlers(c *cfg) { _, _, err := makeNotaryDeposit(ctx, c) if err != nil { c.log.Error(ctx, logs.FrostFSNodeCouldNotMakeNotaryDeposit, - zap.String("error", err.Error()), + zap.Error(err), ) } }) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 6804aae592..f82a8e5330 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -58,7 +58,7 @@ func (c *cfg) MaxObjectSize() uint64 { sz, err := c.cfgNetmap.wrapper.MaxObjectSize() if err != nil { c.log.Error(context.Background(), logs.FrostFSNodeCouldNotGetMaxObjectSizeValue, - zap.String("error", err.Error()), + zap.Error(err), ) } @@ -269,7 +269,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl _, err := ls.Inhume(ctx, inhumePrm) if err != nil { c.log.Warn(ctx, logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage, - zap.String("error", err.Error()), + zap.Error(err), ) } }), diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index c423c0660c..f3ddc8cbeb 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -113,7 +113,7 @@ func initTreeService(c *cfg) { // Ignore pilorama.ErrTreeNotFound but other errors, including shard.ErrReadOnly, should be logged. c.log.Error(ctx, logs.FrostFSNodeContainerRemovalEventReceivedButTreesWerentRemoved, zap.Stringer("cid", ev.ID), - zap.String("error", err.Error())) + zap.Error(err)) } }) diff --git a/pkg/core/object/sender_classifier.go b/pkg/core/object/sender_classifier.go index 3b3650134c..a1a5fcac17 100644 --- a/pkg/core/object/sender_classifier.go +++ b/pkg/core/object/sender_classifier.go @@ -67,7 +67,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerK if err != nil { // do not throw error, try best case matching c.log.Debug(ctx, logs.V2CantCheckIfRequestFromInnerRing, - zap.String("error", err.Error())) + zap.Error(err)) } else if isInnerRingNode { return &ClassifyResult{ Role: acl.RoleInnerRing, @@ -84,7 +84,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerK // is not possible for previous epoch, so // do not throw error, try best case matching c.log.Debug(ctx, logs.V2CantCheckIfRequestFromContainerNode, - zap.String("error", err.Error())) + zap.Error(err)) } else if isContainerNode { return &ClassifyResult{ Role: acl.RoleContainer, diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index 5481354e15..ecaf8ae866 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -100,7 +100,7 @@ func (s *Server) initMainnet(ctx context.Context, cfg *viper.Viper, morphChain * fromMainChainBlock, err := s.persistate.UInt32(persistateMainChainLastBlockKey) if err != nil { fromMainChainBlock = 0 - s.log.Warn(ctx, logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.String("error", err.Error())) + s.log.Warn(ctx, logs.InnerringCantGetLastProcessedMainChainBlockNumber, zap.Error(err)) } mainnetChain.from = fromMainChainBlock @@ -456,7 +456,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<- fromSideChainBlock, err := s.persistate.UInt32(persistateSideChainLastBlockKey) if err != nil { fromSideChainBlock = 0 - s.log.Warn(ctx, logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.String("error", err.Error())) + s.log.Warn(ctx, logs.InnerringCantGetLastProcessedSideChainBlockNumber, zap.Error(err)) } morphChain := &chainParams{ diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 4fe9cc0847..0b9e834438 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -177,7 +177,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) { if err != nil { // we don't stop inner ring execution on this error s.log.Warn(ctx, logs.InnerringCantVoteForPreparedValidators, - zap.String("error", err.Error())) + zap.Error(err)) } s.tickInitialExpoch(ctx) @@ -308,7 +308,7 @@ func (s *Server) Stop(ctx context.Context) { for _, c := range s.closers { if err := c(); err != nil { s.log.Warn(ctx, logs.InnerringCloserError, - zap.String("error", err.Error()), + zap.Error(err), ) } } diff --git a/pkg/innerring/processors/alphabet/process_emit.go b/pkg/innerring/processors/alphabet/process_emit.go index 2292612508..8e11d2d61d 100644 --- a/pkg/innerring/processors/alphabet/process_emit.go +++ b/pkg/innerring/processors/alphabet/process_emit.go @@ -33,7 +33,7 @@ func (ap *Processor) processEmit(ctx context.Context) bool { // there is no signature collecting, so we don't need extra fee _, err := ap.morphClient.Invoke(ctx, contract, 0, emitMethod) if err != nil { - ap.log.Warn(ctx, logs.AlphabetCantInvokeAlphabetEmitMethod, zap.String("error", err.Error())) + ap.log.Warn(ctx, logs.AlphabetCantInvokeAlphabetEmitMethod, zap.Error(err)) return false } @@ -47,7 +47,7 @@ func (ap *Processor) processEmit(ctx context.Context) bool { networkMap, err := ap.netmapClient.NetMap() if err != nil { ap.log.Warn(ctx, logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, - zap.String("error", err.Error())) + zap.Error(err)) return false } @@ -83,7 +83,7 @@ func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []net key, err := keys.NewPublicKeyFromBytes(keyBytes, elliptic.P256()) if err != nil { ap.log.Warn(ctx, logs.AlphabetCantParseNodePublicKey, - zap.String("error", err.Error())) + zap.Error(err)) continue } @@ -93,7 +93,7 @@ func (ap *Processor) transferGasToNetmapNodes(ctx context.Context, nmNodes []net ap.log.Warn(ctx, logs.AlphabetCantTransferGas, zap.String("receiver", key.Address()), zap.Int64("amount", int64(gasPerNode)), - zap.String("error", err.Error()), + zap.Error(err), ) } } @@ -110,7 +110,7 @@ func (ap *Processor) transferGasToExtraNodes(ctx context.Context, pw []util.Uint ap.log.Warn(ctx, logs.AlphabetCantTransferGasToWallet, zap.Strings("receivers", receiversLog), zap.Int64("amount", int64(gasPerNode)), - zap.String("error", err.Error()), + zap.Error(err), ) } } diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index 16c450166b..ffaea653a0 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -50,7 +50,7 @@ func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool err := cp.checkPutContainer(pctx) if err != nil { cp.log.Error(ctx, logs.ContainerPutContainerCheckFailed, - zap.String("error", err.Error()), + zap.Error(err), ) return false @@ -58,7 +58,7 @@ func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool if err := cp.morphClient.NotarySignAndInvokeTX(pctx.e.NotaryRequest().MainTransaction); err != nil { cp.log.Error(ctx, logs.ContainerCouldNotApprovePutContainer, - zap.String("error", err.Error()), + zap.Error(err), ) return false } @@ -113,7 +113,7 @@ func (cp *Processor) processContainerDelete(ctx context.Context, e containerEven err := cp.checkDeleteContainer(e) if err != nil { cp.log.Error(ctx, logs.ContainerDeleteContainerCheckFailed, - zap.String("error", err.Error()), + zap.Error(err), ) return false @@ -121,7 +121,7 @@ func (cp *Processor) processContainerDelete(ctx context.Context, e containerEven if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil { cp.log.Error(ctx, logs.ContainerCouldNotApproveDeleteContainer, - zap.String("error", err.Error()), + zap.Error(err), ) return false diff --git a/pkg/innerring/processors/frostfs/process_assets.go b/pkg/innerring/processors/frostfs/process_assets.go index ee824ea317..d10eb96603 100644 --- a/pkg/innerring/processors/frostfs/process_assets.go +++ b/pkg/innerring/processors/frostfs/process_assets.go @@ -73,7 +73,7 @@ func (np *Processor) processDeposit(ctx context.Context, deposit frostfsEvent.De err = np.morphClient.TransferGas(receiver, np.mintEmitValue) if err != nil { np.log.Error(ctx, logs.FrostFSCantTransferNativeGasToReceiver, - zap.String("error", err.Error())) + zap.Error(err)) return false } diff --git a/pkg/innerring/processors/governance/process_update.go b/pkg/innerring/processors/governance/process_update.go index 73d21a7d28..2456796567 100644 --- a/pkg/innerring/processors/governance/process_update.go +++ b/pkg/innerring/processors/governance/process_update.go @@ -28,21 +28,21 @@ func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint25 mainnetAlphabet, err := gp.mainnetClient.NeoFSAlphabetList() if err != nil { gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromMainNet, - zap.String("error", err.Error())) + zap.Error(err)) return false } sidechainAlphabet, err := gp.morphClient.Committee() if err != nil { gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromSideChain, - zap.String("error", err.Error())) + zap.Error(err)) return false } newAlphabet, err := newAlphabetList(sidechainAlphabet, mainnetAlphabet) if err != nil { gp.log.Error(ctx, logs.GovernanceCantMergeAlphabetListsFromMainNetAndSideChain, - zap.String("error", err.Error())) + zap.Error(err)) return false } @@ -65,7 +65,7 @@ func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint25 err = gp.voter.VoteForSidechainValidator(ctx, votePrm) if err != nil { gp.log.Error(ctx, logs.GovernanceCantVoteForSideChainCommittee, - zap.String("error", err.Error())) + zap.Error(err)) } // 2. Update NeoFSAlphabet role in the sidechain. @@ -98,14 +98,14 @@ func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(ctx context.Context, sid innerRing, err := gp.irFetcher.InnerRingKeys() if err != nil { gp.log.Error(ctx, logs.GovernanceCantFetchInnerRingListFromSideChain, - zap.String("error", err.Error())) + zap.Error(err)) return } newInnerRing, err := updateInnerRing(innerRing, sidechainAlphabet, newAlphabet) if err != nil { gp.log.Error(ctx, logs.GovernanceCantCreateNewInnerRingListWithNewAlphabetKeys, - zap.String("error", err.Error())) + zap.Error(err)) return } @@ -122,7 +122,7 @@ func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(ctx context.Context, sid if err = gp.morphClient.UpdateNeoFSAlphabetList(ctx, updPrm); err != nil { gp.log.Error(ctx, logs.GovernanceCantUpdateInnerRingListWithNewAlphabetKeys, - zap.String("error", err.Error())) + zap.Error(err)) } } @@ -135,7 +135,7 @@ func (gp *Processor) updateNotaryRoleInSidechain(ctx context.Context, newAlphabe err := gp.morphClient.UpdateNotaryList(ctx, updPrm) if err != nil { gp.log.Error(ctx, logs.GovernanceCantUpdateListOfNotaryNodesInSideChain, - zap.String("error", err.Error())) + zap.Error(err)) } } @@ -155,6 +155,6 @@ func (gp *Processor) updateFrostFSContractInMainnet(ctx context.Context, newAlph err := gp.frostfsClient.AlphabetUpdate(ctx, prm) if err != nil { gp.log.Error(ctx, logs.GovernanceCantUpdateListOfAlphabetNodesInFrostfsContract, - zap.String("error", err.Error())) + zap.Error(err)) } } diff --git a/pkg/innerring/processors/netmap/process_cleanup.go b/pkg/innerring/processors/netmap/process_cleanup.go index a43005ffbe..8f8cc17ff3 100644 --- a/pkg/innerring/processors/netmap/process_cleanup.go +++ b/pkg/innerring/processors/netmap/process_cleanup.go @@ -49,7 +49,7 @@ func (np *Processor) processNetmapCleanupTick(ctx context.Context, ev netmapClea }) if err != nil { np.log.Warn(ctx, logs.NetmapCantIterateOnNetmapCleanerCache, - zap.String("error", err.Error())) + zap.Error(err)) return false } diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index 237c4e512a..93e00bbaa1 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -17,7 +17,7 @@ func (np *Processor) processNewEpoch(ctx context.Context, ev netmapEvent.NewEpoc epochDuration, err := np.netmapClient.EpochDuration() if err != nil { np.log.Warn(ctx, logs.NetmapCantGetEpochDuration, - zap.String("error", err.Error())) + zap.Error(err)) } else { np.epochState.SetEpochDuration(epochDuration) } @@ -28,19 +28,19 @@ func (np *Processor) processNewEpoch(ctx context.Context, ev netmapEvent.NewEpoc if err != nil { np.log.Warn(ctx, logs.NetmapCantGetTransactionHeight, zap.String("hash", ev.TxHash().StringLE()), - zap.String("error", err.Error())) + zap.Error(err)) } if err := np.epochTimer.ResetEpochTimer(h); err != nil { np.log.Warn(ctx, logs.NetmapCantResetEpochTimer, - zap.String("error", err.Error())) + zap.Error(err)) } // get new netmap snapshot networkMap, err := np.netmapClient.NetMap() if err != nil { np.log.Warn(ctx, logs.NetmapCantGetNetmapSnapshotToPerformCleanup, - zap.String("error", err.Error())) + zap.Error(err)) return false } diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index 72aa08f768..5b565ffd19 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -42,7 +42,7 @@ func (np *Processor) processAddPeer(ctx context.Context, ev netmapEvent.AddPeer) err = np.nodeValidator.VerifyAndUpdate(&nodeInfo) if err != nil { np.log.Warn(ctx, logs.NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate, - zap.String("error", err.Error()), + zap.Error(err), ) return false diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index 77c2af2ce3..3e9880e70c 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -62,7 +62,7 @@ func (s *Server) IsAlphabet(ctx context.Context) bool { func (s *Server) InnerRingIndex(ctx context.Context) int { index, err := s.statusIndex.InnerRingIndex() if err != nil { - s.log.Error(ctx, logs.InnerringCantGetInnerRingIndex, zap.String("error", err.Error())) + s.log.Error(ctx, logs.InnerringCantGetInnerRingIndex, zap.Error(err)) return -1 } @@ -74,7 +74,7 @@ func (s *Server) InnerRingIndex(ctx context.Context) int { func (s *Server) InnerRingSize(ctx context.Context) int { size, err := s.statusIndex.InnerRingSize() if err != nil { - s.log.Error(ctx, logs.InnerringCantGetInnerRingSize, zap.String("error", err.Error())) + s.log.Error(ctx, logs.InnerringCantGetInnerRingSize, zap.Error(err)) return 0 } @@ -86,7 +86,7 @@ func (s *Server) InnerRingSize(ctx context.Context) int { func (s *Server) AlphabetIndex(ctx context.Context) int { index, err := s.statusIndex.AlphabetIndex() if err != nil { - s.log.Error(ctx, logs.InnerringCantGetAlphabetIndex, zap.String("error", err.Error())) + s.log.Error(ctx, logs.InnerringCantGetAlphabetIndex, zap.Error(err)) return -1 } @@ -132,7 +132,7 @@ func (s *Server) voteForSidechainValidator(ctx context.Context, prm governance.V s.log.Warn(ctx, logs.InnerringCantInvokeVoteMethodInAlphabetContract, zap.Int8("alphabet_index", int8(letter)), zap.Uint64("epoch", epoch), - zap.String("error", err.Error())) + zap.Error(err)) } }) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 8c2d7aa67f..47e12bafbc 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -82,7 +82,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co if !client.IsErrObjectNotFound(err) { b.log.Debug(ctx, logs.BlobovniczatreeCouldNotRemoveObjectFromLevel, zap.String("level", p), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index 63d2f21e12..d2c99945f6 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -57,7 +57,7 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common if !client.IsErrObjectNotFound(err) { b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index b7ef8d8a59..1a4f11c29a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -69,7 +69,7 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G if !client.IsErrObjectNotFound(err) { b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index b24f1b8819..6d06b8e6f9 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -71,7 +71,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re if !outOfBounds && !client.IsErrObjectNotFound(err) { b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } if outOfBounds { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index b120c22f77..a710cf988a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -44,7 +44,7 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm if prm.IgnoreErrors { b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.Stringer("address", elem.Address()), - zap.String("err", err.Error()), + zap.Error(err), zap.String("storage_id", p), zap.String("root_path", b.rootPath)) return nil @@ -77,7 +77,7 @@ func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors boo if err != nil { if ignoreErrors { b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, - zap.String("err", err.Error()), + zap.Error(err), zap.String("storage_id", p), zap.String("root_path", b.rootPath)) return false, nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index b35e052cf9..7d44aa5c6c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -97,7 +97,7 @@ func (b *sharedDB) Close(ctx context.Context) { if err := b.blcza.Close(ctx); err != nil { b.log.Error(ctx, logs.BlobovniczatreeCouldNotCloseBlobovnicza, zap.String("id", b.path), - zap.String("error", err.Error()), + zap.Error(err), ) } b.blcza = nil @@ -125,7 +125,7 @@ func (b *sharedDB) CloseAndRemoveFile(ctx context.Context) error { if err := b.blcza.Close(ctx); err != nil { b.log.Error(ctx, logs.BlobovniczatreeCouldNotCloseBlobovnicza, zap.String("id", b.path), - zap.String("error", err.Error()), + zap.Error(err), ) return fmt.Errorf("failed to close blobovnicza (path = %s): %w", b.path, err) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 1678e578c8..8276a25ef9 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -83,7 +83,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) i.B.reportError(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) } else { i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } @@ -106,7 +106,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) } else { i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", active.SystemPath()), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } if errors.Is(err, blobovnicza.ErrNoSpace) { diff --git a/pkg/local_object_storage/blobstor/control.go b/pkg/local_object_storage/blobstor/control.go index 44685524f2..93316be026 100644 --- a/pkg/local_object_storage/blobstor/control.go +++ b/pkg/local_object_storage/blobstor/control.go @@ -74,7 +74,7 @@ func (b *BlobStor) Close(ctx context.Context) error { for i := range b.storage { err := b.storage[i].Storage.Close(ctx) if err != nil { - b.log.Info(ctx, logs.BlobstorCouldntCloseStorage, zap.String("error", err.Error())) + b.log.Info(ctx, logs.BlobstorCouldntCloseStorage, zap.Error(err)) if firstErr == nil { firstErr = err } diff --git a/pkg/local_object_storage/blobstor/exists.go b/pkg/local_object_storage/blobstor/exists.go index 556f53e12c..f1e45fe10b 100644 --- a/pkg/local_object_storage/blobstor/exists.go +++ b/pkg/local_object_storage/blobstor/exists.go @@ -75,7 +75,7 @@ func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exi for _, err := range errors[:len(errors)-1] { b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringObjectExistenceChecking, zap.Stringer("address", prm.Address), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 53eb0395a3..a77ad2f93c 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -153,7 +153,7 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr if err != nil { if prm.IgnoreErrors { t.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, - zap.String("err", err.Error()), + zap.Error(err), zap.String("directory_path", dirPath)) return nil } @@ -202,7 +202,7 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr if prm.IgnoreErrors { t.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.Stringer("address", addr), - zap.String("err", err.Error()), + zap.Error(err), zap.String("path", path)) continue } diff --git a/pkg/local_object_storage/blobstor/iterate.go b/pkg/local_object_storage/blobstor/iterate.go index 1ba835a95c..ff1aa9d640 100644 --- a/pkg/local_object_storage/blobstor/iterate.go +++ b/pkg/local_object_storage/blobstor/iterate.go @@ -45,7 +45,7 @@ func (b *BlobStor) Iterate(ctx context.Context, prm common.IteratePrm) (common.I b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.String("storage_path", b.storage[i].Storage.Path()), zap.String("storage_type", b.storage[i].Storage.Type()), - zap.String("err", err.Error())) + zap.Error(err)) continue } return common.IterateRes{}, fmt.Errorf("blobstor iterator failure: %w", err) diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index a5c53dcadb..bd9eb1021b 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -167,7 +167,7 @@ func (e *StorageEngine) close(ctx context.Context, releasePools bool) error { if err := sh.Close(ctx); err != nil { e.log.Debug(ctx, logs.EngineCouldNotCloseShard, zap.String("id", id), - zap.String("error", err.Error()), + zap.Error(err), ) } } diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 7164ff21f2..65ccbdb9ec 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -154,7 +154,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo if err != nil { e.log.Warn(ctx, logs.EngineErrorDuringSearchingForObjectChildren, zap.Stringer("addr", addr), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return false } @@ -166,7 +166,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo if err != nil { e.log.Debug(ctx, logs.EngineCouldNotInhumeObjectInShard, zap.Stringer("addr", addr), - zap.String("err", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) continue } @@ -196,7 +196,7 @@ func (e *StorageEngine) deleteChunks( if err != nil { e.log.Debug(ctx, logs.EngineCouldNotInhumeObjectInShard, zap.Stringer("addr", addr), - zap.String("err", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) continue } diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 0299040463..f82268d1d9 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -140,7 +140,7 @@ func (e *StorageEngine) reportShardError( if isLogical(err) { e.log.Warn(ctx, msg, zap.Stringer("shard_id", sh.ID()), - zap.String("error", err.Error())) + zap.Error(err)) return } @@ -151,7 +151,7 @@ func (e *StorageEngine) reportShardError( e.log.Warn(ctx, msg, append([]zap.Field{ zap.Stringer("shard_id", sid), zap.Uint32("error count", errCount), - zap.String("error", err.Error()), + zap.Error(err), }, fields...)...) if e.errorsThreshold == 0 || errCount < e.errorsThreshold { diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index c7145889b1..81b027c269 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -106,7 +106,7 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { if it.ShardWithMeta.Shard != nil && it.MetaError != nil { e.log.Warn(ctx, logs.ShardMetaInfoPresentButObjectNotFound, zap.Stringer("shard_id", it.ShardWithMeta.ID()), - zap.String("error", it.MetaError.Error()), + zap.Error(it.MetaError), zap.Stringer("address", prm.addr), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 62671f4331..c79b6e2519 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -143,7 +143,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti } else { e.log.Warn(ctx, logs.EngineCouldNotCheckObjectExistence, zap.Stringer("shard_id", sh.ID()), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } @@ -165,14 +165,14 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti errors.Is(err, common.ErrReadOnly) || errors.Is(err, common.ErrNoSpace) { e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, zap.Stringer("shard_id", sh.ID()), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return } if client.IsErrObjectAlreadyRemoved(err) { e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, zap.Stringer("shard_id", sh.ID()), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) res.status = putToShardRemoved res.err = err diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index 0c9cea9036..600e7266c9 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -118,7 +118,7 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error if it.ShardWithMeta.Shard != nil && it.MetaError != nil { e.log.Warn(ctx, logs.ShardMetaInfoPresentButObjectNotFound, zap.Stringer("shard_id", it.ShardWithMeta.ID()), - zap.String("error", it.MetaError.Error()), + zap.Error(it.MetaError), zap.Stringer("address", prm.addr), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 5a9e261551..78ce241fec 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -272,7 +272,7 @@ func (s *Shard) refillObject(ctx context.Context, data []byte, addr oid.Address, if err := obj.Unmarshal(data); err != nil { s.log.Warn(ctx, logs.ShardCouldNotUnmarshalObject, zap.Stringer("address", addr), - zap.String("err", err.Error())) + zap.Error(err)) return nil } diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index f62cecd56b..fb6769b51c 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -112,7 +112,7 @@ func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error if err != nil { s.log.Debug(ctx, logs.StorageIDRetrievalFailure, zap.Stringer("object", addr), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } @@ -132,7 +132,7 @@ func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error if err != nil && !client.IsErrObjectNotFound(err) { s.log.Debug(ctx, logs.ObjectRemovalFailureBlobStor, zap.Stringer("object_address", addr), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) return err } diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index c212f8c361..1b218a372d 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -205,7 +205,7 @@ func (gc *gc) handleEvent(ctx context.Context, event Event) { }) if err != nil { gc.log.Warn(ctx, logs.ShardCouldNotSubmitGCJobToWorkerPool, - zap.String("error", err.Error()), + zap.Error(err), ) v.prevGroup.Done() @@ -313,7 +313,7 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { err := s.metaBase.IterateOverGarbage(ctx, iterPrm) if err != nil { s.log.Warn(ctx, logs.ShardIteratorOverMetabaseGraveyardFailed, - zap.String("error", err.Error()), + zap.Error(err), ) return @@ -334,7 +334,7 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { if err != nil { s.log.Warn(ctx, logs.ShardCouldNotDeleteTheObjects, - zap.String("error", err.Error()), + zap.Error(err), ) result.success = false } @@ -396,7 +396,7 @@ func (s *Shard) collectExpiredObjects(ctx context.Context, e Event) { }) if err = errGroup.Wait(); err != nil { - s.log.Warn(ctx, logs.ShardIteratorOverExpiredObjectsFailed, zap.String("error", err.Error())) + s.log.Warn(ctx, logs.ShardIteratorOverExpiredObjectsFailed, zap.Error(err)) } } @@ -429,7 +429,7 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) res, err := s.metaBase.Inhume(ctx, inhumePrm) if err != nil { s.log.Warn(ctx, logs.ShardCouldNotInhumeTheObjects, - zap.String("error", err.Error()), + zap.Error(err), ) return @@ -584,7 +584,7 @@ func (s *Shard) collectExpiredLocks(ctx context.Context, e Event) { }) if err = errGroup.Wait(); err != nil { - s.log.Warn(ctx, logs.ShardIteratorOverExpiredLocksFailed, zap.String("error", err.Error())) + s.log.Warn(ctx, logs.ShardIteratorOverExpiredLocksFailed, zap.Error(err)) } } @@ -637,7 +637,7 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston res, err := s.metaBase.InhumeTombstones(ctx, tss) if err != nil { s.log.Warn(ctx, logs.ShardCouldNotMarkTombstonesAsGarbage, - zap.String("error", err.Error()), + zap.Error(err), ) return @@ -665,7 +665,7 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] unlocked, err := s.metaBase.FreeLockedBy(lockers) if err != nil { s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, - zap.String("error", err.Error()), + zap.Error(err), ) return @@ -678,7 +678,7 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] res, err := s.metaBase.Inhume(ctx, pInhume) if err != nil { s.log.Warn(ctx, logs.ShardFailureToMarkLockersAsGarbage, - zap.String("error", err.Error()), + zap.Error(err), ) return @@ -722,7 +722,7 @@ func (s *Shard) HandleDeletedLocks(ctx context.Context, lockers []oid.Address) { _, err := s.metaBase.FreeLockedBy(lockers) if err != nil { s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, - zap.String("error", err.Error()), + zap.Error(err), ) return diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index 984c54fbce..d464008692 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -110,7 +110,7 @@ func (s *Shard) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { } s.log.Debug(ctx, logs.ShardCouldNotMarkObjectToDeleteInMetabase, - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index 7b267d2e46..f583ef5d93 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -124,7 +124,7 @@ func (s *Shard) List(ctx context.Context) (res SelectRes, err error) { if err != nil { s.log.Debug(ctx, logs.ShardCantSelectAllObjects, zap.Stringer("cid", lst[i]), - zap.String("error", err.Error()), + zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) continue diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index 50125a88d3..1e4643db53 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -76,7 +76,7 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { if err != nil || !tryCache { if err != nil { s.log.Debug(ctx, logs.ShardCantPutObjectToTheWritecacheTryingBlobstor, - zap.String("err", err.Error())) + zap.Error(err)) } res, err = s.blobStor.Put(ctx, putPrm) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 5a5d24900d..37599e6961 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -390,7 +390,7 @@ func (c *Client) Wait(ctx context.Context, n uint32) error { height, err = c.rpcActor.GetBlockCount() if err != nil { c.logger.Error(ctx, logs.ClientCantGetBlockchainHeight, - zap.String("error", err.Error())) + zap.Error(err)) return nil } @@ -404,7 +404,7 @@ func (c *Client) Wait(ctx context.Context, n uint32) error { newHeight, err = c.rpcActor.GetBlockCount() if err != nil { c.logger.Error(ctx, logs.ClientCantGetBlockchainHeight243, - zap.String("error", err.Error())) + zap.Error(err)) return nil } diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index ed77352ec7..83f8bee078 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -136,7 +136,7 @@ func (l *listener) Listen(ctx context.Context) { defer l.wg.Done() if err := l.listen(ctx, nil); err != nil { l.log.Error(ctx, logs.EventCouldNotStartListenToEvents, - zap.String("error", err.Error()), + zap.Error(err), ) } }) @@ -154,7 +154,7 @@ func (l *listener) ListenWithError(ctx context.Context, intError chan<- error) { defer l.wg.Done() if err := l.listen(ctx, intError); err != nil { l.log.Error(ctx, logs.EventCouldNotStartListenToEvents, - zap.String("error", err.Error()), + zap.Error(err), ) l.sendError(ctx, intError, err) } @@ -342,7 +342,7 @@ func (l *listener) parseAndHandleNotification(ctx context.Context, notifyEvent * event, err := parser(notifyEvent) if err != nil { log.Warn(ctx, logs.EventCouldNotParseNotificationEvent, - zap.String("error", err.Error()), + zap.Error(err), ) return @@ -375,13 +375,13 @@ func (l *listener) parseAndHandleNotary(ctx context.Context, nr *result.NotaryRe case errors.Is(err, ErrTXAlreadyHandled): case errors.As(err, &expErr): l.log.Warn(ctx, logs.EventSkipExpiredMainTXNotaryEvent, - zap.String("error", err.Error()), + zap.Error(err), zap.Uint32("current_block_height", expErr.CurrentBlockHeight), zap.Uint32("fallback_tx_not_valid_before_height", expErr.FallbackTXNotValidBeforeHeight), ) default: l.log.Warn(ctx, logs.EventCouldNotPrepareAndValidateNotaryEvent, - zap.String("error", err.Error()), + zap.Error(err), ) } @@ -413,7 +413,7 @@ func (l *listener) parseAndHandleNotary(ctx context.Context, nr *result.NotaryRe event, err := parser(notaryEvent) if err != nil { log.Warn(ctx, logs.EventCouldNotParseNotaryEvent, - zap.String("error", err.Error()), + zap.Error(err), ) return diff --git a/pkg/morph/event/utils.go b/pkg/morph/event/utils.go index 058959c634..0088be4001 100644 --- a/pkg/morph/event/utils.go +++ b/pkg/morph/event/utils.go @@ -77,7 +77,7 @@ func WorkerPoolHandler(w util2.WorkerPool, h Handler, log *logger.Logger) Handle }) if err != nil { log.Warn(ctx, logs.EventCouldNotSubmitHandlerToWorkerPool, - zap.String("error", err.Error()), + zap.Error(err), ) } } diff --git a/pkg/services/object/delete/delete.go b/pkg/services/object/delete/delete.go index 8aaff670c3..57e33fde7a 100644 --- a/pkg/services/object/delete/delete.go +++ b/pkg/services/object/delete/delete.go @@ -36,7 +36,7 @@ func (exec *execCtx) execute(ctx context.Context) error { exec.log.Debug(ctx, logs.ServingRequest) if err := exec.executeLocal(ctx); err != nil { - exec.log.Debug(ctx, logs.OperationFinishedWithError, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.OperationFinishedWithError, zap.Error(err)) return err } diff --git a/pkg/services/object/search/container.go b/pkg/services/object/search/container.go index 999a3cc9e2..e82f999cf1 100644 --- a/pkg/services/object/search/container.go +++ b/pkg/services/object/search/container.go @@ -73,7 +73,7 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { select { case <-ctx.Done(): exec.log.Debug(ctx, logs.InterruptPlacementIterationByContext, - zap.String("error", ctx.Err().Error())) + zap.Error(ctx.Err())) return default: } @@ -86,14 +86,14 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { c, err := exec.svc.clientConstructor.get(info) if err != nil { - exec.log.Debug(ctx, logs.SearchCouldNotConstructRemoteNodeClient, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.SearchCouldNotConstructRemoteNodeClient, zap.Error(err)) return } ids, err := c.searchObjects(ctx, exec, info) if err != nil { exec.log.Debug(ctx, logs.SearchRemoteOperationFailed, - zap.String("error", err.Error())) + zap.Error(err)) return } @@ -102,7 +102,7 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { err = exec.writeIDList(ids) mtx.Unlock() if err != nil { - exec.log.Debug(ctx, logs.SearchCouldNotWriteObjectIdentifiers, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.SearchCouldNotWriteObjectIdentifiers, zap.Error(err)) return } }(i) diff --git a/pkg/services/object/search/local.go b/pkg/services/object/search/local.go index bc59d03945..ec65ab06a2 100644 --- a/pkg/services/object/search/local.go +++ b/pkg/services/object/search/local.go @@ -11,7 +11,7 @@ import ( func (exec *execCtx) executeLocal(ctx context.Context) error { ids, err := exec.svc.localStorage.search(ctx, exec) if err != nil { - exec.log.Debug(ctx, logs.SearchLocalOperationFailed, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.SearchLocalOperationFailed, zap.Error(err)) return err } diff --git a/pkg/services/object/search/search.go b/pkg/services/object/search/search.go index e24da975de..76c091f85a 100644 --- a/pkg/services/object/search/search.go +++ b/pkg/services/object/search/search.go @@ -38,7 +38,7 @@ func (exec *execCtx) execute(ctx context.Context) error { func (exec *execCtx) logResult(ctx context.Context, err error) { switch { default: - exec.log.Debug(ctx, logs.OperationFinishedWithError, zap.String("error", err.Error())) + exec.log.Debug(ctx, logs.OperationFinishedWithError, zap.Error(err)) case err == nil: exec.log.Debug(ctx, logs.OperationFinishedSuccessfully) } diff --git a/pkg/services/object/util/log.go b/pkg/services/object/util/log.go index a9f875d8dd..2c1e053ac2 100644 --- a/pkg/services/object/util/log.go +++ b/pkg/services/object/util/log.go @@ -14,7 +14,7 @@ func LogServiceError(ctx context.Context, l *logger.Logger, req string, node net l.Error(ctx, logs.UtilObjectServiceError, zap.String("node", network.StringifyGroup(node)), zap.String("request", req), - zap.String("error", err.Error()), + zap.Error(err), ) } @@ -22,6 +22,6 @@ func LogServiceError(ctx context.Context, l *logger.Logger, req string, node net func LogWorkerPoolError(ctx context.Context, l *logger.Logger, req string, err error) { l.Error(ctx, logs.UtilCouldNotPushTaskToWorkerPool, zap.String("request", req), - zap.String("error", err.Error()), + zap.Error(err), ) } diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 2e5e54dfd8..bdfc4344bf 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -153,7 +153,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe } else { p.log.Error(ctx, logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", addr), - zap.String("error", err.Error()), + zap.Error(err), ) } } diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index db640e3233..f6d3b9ea14 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -131,7 +131,7 @@ func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, n // consider maintenance mode has object, but do not drop local copy p.log.Debug(ctx, logs.PolicerConsiderNodeUnderMaintenanceAsOK, zap.String("node", netmap.StringifyPublicKey(requiredNode))) } else { - p.log.Error(ctx, logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", objInfo.Address), zap.String("error", err.Error())) + p.log.Error(ctx, logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, zap.Stringer("object", objInfo.Address), zap.Error(err)) } return ecChunkProcessResult{ diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index 80a87ade9c..bd830d04ee 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -61,7 +61,7 @@ func (p *Policer) shardPolicyWorker(ctx context.Context) { if err != nil && !skipMap.addSeenError(addr.Address.Container(), err) { p.log.Error(ctx, logs.PolicerUnableToProcessObj, zap.Stringer("object", addr.Address), - zap.String("error", err.Error())) + zap.Error(err)) } p.cache.Add(addr.Address, time.Now()) p.objsInWork.remove(addr.Address) diff --git a/pkg/services/replicator/process.go b/pkg/services/replicator/process.go index 2120312f6e..69395bb021 100644 --- a/pkg/services/replicator/process.go +++ b/pkg/services/replicator/process.go @@ -76,7 +76,7 @@ func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res T if err != nil { log.Error(ctx, logs.ReplicatorCouldNotReplicateObject, - zap.String("error", err.Error()), + zap.Error(err), ) } else { log.Debug(ctx, logs.ReplicatorObjectSuccessfullyReplicated) diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 0c5bde0781..e0085d73af 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -59,7 +59,7 @@ func (s *Service) localReplicationWorker(ctx context.Context) { err := s.forest.TreeApply(ctx, op.cid, op.treeID, &op.Move, false) if err != nil { s.log.Error(ctx, logs.TreeFailedToApplyReplicatedOperation, - zap.String("err", err.Error())) + zap.Error(err)) } span.End() } @@ -155,7 +155,7 @@ func (s *Service) replicateLoop(ctx context.Context) { err := s.replicate(op) if err != nil { s.log.Error(ctx, logs.TreeErrorDuringReplication, - zap.String("err", err.Error()), + zap.Error(err), zap.Stringer("cid", op.cid), zap.String("treeID", op.treeID)) } From 7ac354271462ec6ec59d5d02f2e4cfad0c693572 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 16 Dec 2024 13:59:08 +0300 Subject: [PATCH 1097/1413] [#1563] ape: Introduce `ChainRouterError` error type Signed-off-by: Airat Arifullin --- pkg/services/common/ape/checker.go | 2 +- pkg/services/common/ape/error.go | 33 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 pkg/services/common/ape/error.go diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index 30580da122..86021c3db6 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -103,7 +103,7 @@ func (c *checkerCoreImpl) CheckAPE(prm CheckPrm) error { if found && status == apechain.Allow { return nil } - return fmt.Errorf("access to operation %s is denied by access policy engine: %s", prm.Request.Operation(), status.String()) + return newChainRouterError(prm.Request.Operation(), status) } // isValidBearer checks whether bearer token was correctly signed by authorized diff --git a/pkg/services/common/ape/error.go b/pkg/services/common/ape/error.go new file mode 100644 index 0000000000..d3c381de7b --- /dev/null +++ b/pkg/services/common/ape/error.go @@ -0,0 +1,33 @@ +package ape + +import ( + "fmt" + + apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" +) + +// ChainRouterError is returned when chain router validation prevents +// the APE request from being processed (no rule found, access denied, etc.). +type ChainRouterError struct { + operation string + status apechain.Status +} + +func (e *ChainRouterError) Error() string { + return fmt.Sprintf("access to operation %s is denied by access policy engine: %s", e.Operation(), e.Status()) +} + +func (e *ChainRouterError) Operation() string { + return e.operation +} + +func (e *ChainRouterError) Status() apechain.Status { + return e.status +} + +func newChainRouterError(operation string, status apechain.Status) *ChainRouterError { + return &ChainRouterError{ + operation: operation, + status: status, + } +} From 1a091ea7bbc2c1f01bd3026b7be338261338a4d9 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 16 Dec 2024 14:10:18 +0300 Subject: [PATCH 1098/1413] [#1563] object: Wrap only `ChainRouterError` erros with `ObjectAccessDenied` * Such wrapping helps to differentiate logical check errors and server internal errors. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/errors.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pkg/services/object/ape/errors.go b/pkg/services/object/ape/errors.go index 1b2024ed5c..6e458b3849 100644 --- a/pkg/services/object/ape/errors.go +++ b/pkg/services/object/ape/errors.go @@ -1,10 +1,19 @@ package ape import ( + "errors" + + checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) func toStatusErr(err error) error { + var chRouterErr *checkercore.ChainRouterError + if !errors.As(err, &chRouterErr) { + errServerInternal := &apistatus.ServerInternal{} + apistatus.WriteInternalServerErr(errServerInternal, err) + return errServerInternal + } errAccessDenied := &apistatus.ObjectAccessDenied{} errAccessDenied.WriteReason("ape denied request: " + err.Error()) return errAccessDenied From 6e82661c3556fa64ee11310258c7b980870a649e Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 16 Dec 2024 14:17:37 +0300 Subject: [PATCH 1099/1413] [#1563] tree: Wrap only `ChainRouterError` erros with `ObjectAccessDenied` * Such wrapping helps to differentiate logical check errors and server internal errors. Signed-off-by: Airat Arifullin --- pkg/services/tree/signature.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 80f5b35905..b0f00615ae 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -9,6 +9,7 @@ import ( "fmt" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -70,6 +71,12 @@ func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, } func apeErr(err error) error { + var chRouterErr *checkercore.ChainRouterError + if !errors.As(err, &chRouterErr) { + errServerInternal := &apistatus.ServerInternal{} + apistatus.WriteInternalServerErr(errServerInternal, err) + return errServerInternal + } errAccessDenied := &apistatus.ObjectAccessDenied{} errAccessDenied.WriteReason(err.Error()) return errAccessDenied From b6c8ebf4930174367a08ff546fb2354162fc6d4f Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Thu, 12 Dec 2024 17:46:30 +0300 Subject: [PATCH 1100/1413] [#1453] container: Replace `sort.Slice` with `slices.SortFunc` * Replaced `sort.Slice` with `slices.SortFunc` in `ListContainersRes.SortedIDList()` as it is a bit faster, according to 15102e6dfd. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/internal/client/client.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 948d61f369..851cf5ccc5 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -9,7 +9,6 @@ import ( "io" "os" "slices" - "sort" "strings" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting" @@ -78,9 +77,8 @@ func ListContainers(ctx context.Context, prm ListContainersPrm) (res ListContain // SortedIDList returns sorted list of identifiers of user's containers. func (x ListContainersRes) SortedIDList() []cid.ID { list := x.cliRes.Containers() - sort.Slice(list, func(i, j int) bool { - lhs, rhs := list[i].EncodeToString(), list[j].EncodeToString() - return strings.Compare(lhs, rhs) < 0 + slices.SortFunc(list, func(lhs, rhs cid.ID) int { + return strings.Compare(lhs.EncodeToString(), rhs.EncodeToString()) }) return list } From df05057ed46632e7746fcaa26731987a9070b2e5 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 28 Oct 2024 18:10:07 +0300 Subject: [PATCH 1101/1413] [#1452] container: Add ListStream method * Added new method for listing containers to container service. It opens stream and sends containers in batches. * Added TransportSplitter wrapper around ExecutionService to split container ID list read from contract in parts that are smaller than grpc max message size. Batch size can be changed in node configuration file (as in example config file). * Changed `container list` implementaion in cli: now ListStream is called by default. Old List is called only if ListStream is not implemented. * Changed `internalclient.ListContainersPrm`.`Account` to `OwnerID` since `client.PrmContainerList`.`Account` was renamed to `OwnerID` in sdk. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/internal/client/client.go | 19 ++++ cmd/frostfs-cli/modules/container/list.go | 77 ++++++++++------ cmd/frostfs-node/config.go | 7 +- .../config/container/container.go | 27 ++++++ .../config/container/container_test.go | 27 ++++++ cmd/frostfs-node/container.go | 6 +- config/example/node.env | 3 + config/example/node.json | 5 + config/example/node.yaml | 4 + go.mod | 2 +- go.sum | 4 +- .../transport/container/grpc/service.go | 23 +++++ pkg/services/container/ape.go | 73 +++++++++++++++ pkg/services/container/ape_test.go | 5 + pkg/services/container/audit.go | 11 +++ pkg/services/container/executor.go | 9 ++ pkg/services/container/morph/executor.go | 32 +++++++ pkg/services/container/server.go | 8 ++ pkg/services/container/sign.go | 37 ++++++++ pkg/services/container/transport_splitter.go | 92 +++++++++++++++++++ 20 files changed, 435 insertions(+), 36 deletions(-) create mode 100644 cmd/frostfs-node/config/container/container.go create mode 100644 cmd/frostfs-node/config/container/container_test.go create mode 100644 pkg/services/container/transport_splitter.go diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 851cf5ccc5..ceae36ae7d 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -83,6 +83,25 @@ func (x ListContainersRes) SortedIDList() []cid.ID { return list } +func ListContainersStream(ctx context.Context, prm ListContainersPrm, processCnr func(id cid.ID) bool) (err error) { + cliPrm := &client.PrmContainerListStream{ + XHeaders: prm.XHeaders, + OwnerID: prm.OwnerID, + Session: prm.Session, + } + rdr, err := prm.cli.ContainerListInit(ctx, *cliPrm) + if err != nil { + return fmt.Errorf("init container list: %w", err) + } + + err = rdr.Iterate(processCnr) + if err != nil { + return fmt.Errorf("read container list: %w", err) + } + + return +} + // PutContainerPrm groups parameters of PutContainer operation. type PutContainerPrm struct { Client *client.Client diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index f01e4db4dc..bbb8da8401 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -6,8 +6,11 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/spf13/cobra" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) // flags of list command. @@ -51,44 +54,60 @@ var listContainersCmd = &cobra.Command{ var prm internalclient.ListContainersPrm prm.SetClient(cli) - prm.Account = idUser - - res, err := internalclient.ListContainers(cmd.Context(), prm) - commonCmd.ExitOnErr(cmd, "rpc error: %w", err) - + prm.OwnerID = idUser prmGet := internalclient.GetContainerPrm{ Client: cli, } + var containerIDs []cid.ID + + err := internalclient.ListContainersStream(cmd.Context(), prm, func(id cid.ID) bool { + printContainer(cmd, prmGet, id) + return false + }) + if err == nil { + return + } + + if e, ok := status.FromError(err); ok && e.Code() == codes.Unimplemented { + res, err := internalclient.ListContainers(cmd.Context(), prm) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + containerIDs = res.SortedIDList() + } else { + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + } - containerIDs := res.SortedIDList() for _, cnrID := range containerIDs { - if flagVarListName == "" && !flagVarListPrintAttr { - cmd.Println(cnrID.String()) - continue - } - - prmGet.ClientParams.ContainerID = &cnrID - res, err := internalclient.GetContainer(cmd.Context(), prmGet) - if err != nil { - cmd.Printf(" failed to read attributes: %v\n", err) - continue - } - - cnr := res.Container() - if cnrName := containerSDK.Name(cnr); flagVarListName != "" && cnrName != flagVarListName { - continue - } - cmd.Println(cnrID.String()) - - if flagVarListPrintAttr { - cnr.IterateUserAttributes(func(key, val string) { - cmd.Printf(" %s: %s\n", key, val) - }) - } + printContainer(cmd, prmGet, cnrID) } }, } +func printContainer(cmd *cobra.Command, prmGet internalclient.GetContainerPrm, id cid.ID) { + if flagVarListName == "" && !flagVarListPrintAttr { + cmd.Println(id.String()) + return + } + + prmGet.ClientParams.ContainerID = &id + res, err := internalclient.GetContainer(cmd.Context(), prmGet) + if err != nil { + cmd.Printf(" failed to read attributes: %v\n", err) + return + } + + cnr := res.Container() + if cnrName := containerSDK.Name(cnr); flagVarListName != "" && cnrName != flagVarListName { + return + } + cmd.Println(id.String()) + + if flagVarListPrintAttr { + cnr.IterateUserAttributes(func(key, val string) { + cmd.Printf(" %s: %s\n", key, val) + }) + } +} + func initContainerListContainersCmd() { commonflags.Init(listContainersCmd) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 6950c9e24b..40be8f45fc 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -606,9 +606,10 @@ type cfgAccounting struct { type cfgContainer struct { scriptHash neogoutil.Uint160 - parsers map[event.Type]event.NotificationParser - subscribers map[event.Type][]event.Handler - workerPool util.WorkerPool // pool for asynchronous handlers + parsers map[event.Type]event.NotificationParser + subscribers map[event.Type][]event.Handler + workerPool util.WorkerPool // pool for asynchronous handlers + containerBatchSize uint32 } type cfgFrostfsID struct { diff --git a/cmd/frostfs-node/config/container/container.go b/cmd/frostfs-node/config/container/container.go new file mode 100644 index 0000000000..b0b8043d62 --- /dev/null +++ b/cmd/frostfs-node/config/container/container.go @@ -0,0 +1,27 @@ +package containerconfig + +import "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + +const ( + subsection = "container" + listStreamSubsection = "list_stream" + + // ContainerBatchSizeDefault represents he maximum amount of containers to send via stream at once. + ContainerBatchSizeDefault = 1000 +) + +// ContainerBatchSize returns the value of "batch_size" config parameter +// from "list_stream" subsection of "container" section. +// +// Returns ContainerBatchSizeDefault if the value is missing or if +// the value is not positive integer. +func ContainerBatchSize(c *config.Config) uint32 { + if c.Sub(subsection).Sub(listStreamSubsection).Value("batch_size") == nil { + return ContainerBatchSizeDefault + } + size := config.Uint32Safe(c.Sub(subsection).Sub(listStreamSubsection), "batch_size") + if size == 0 { + return ContainerBatchSizeDefault + } + return size +} diff --git a/cmd/frostfs-node/config/container/container_test.go b/cmd/frostfs-node/config/container/container_test.go new file mode 100644 index 0000000000..744cd32950 --- /dev/null +++ b/cmd/frostfs-node/config/container/container_test.go @@ -0,0 +1,27 @@ +package containerconfig_test + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + containerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/container" + configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" + "github.com/stretchr/testify/require" +) + +func TestContainerSection(t *testing.T) { + t.Run("defaults", func(t *testing.T) { + empty := configtest.EmptyConfig() + require.Equal(t, uint32(containerconfig.ContainerBatchSizeDefault), containerconfig.ContainerBatchSize(empty)) + }) + + const path = "../../../../config/example/node" + fileConfigTest := func(c *config.Config) { + require.Equal(t, uint32(500), containerconfig.ContainerBatchSize(c)) + } + + configtest.ForEachFileType(path, fileConfigTest) + t.Run("ENV", func(t *testing.T) { + configtest.ForEnvFileType(t, path, fileConfigTest) + }) +} diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 7d558dacb6..fb2550a03b 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -5,6 +5,7 @@ import ( "context" "net" + containerconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/container" morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" @@ -47,6 +48,7 @@ func initContainerService(_ context.Context, c *cfg) { } c.shared.frostfsidClient = frostfsIDSubjectProvider + c.cfgContainer.containerBatchSize = containerconfig.ContainerBatchSize(c.appCfg) defaultChainRouter := engine.NewDefaultChainRouterWithLocalOverrides( c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage(), @@ -56,7 +58,9 @@ func initContainerService(_ context.Context, c *cfg) { &c.key.PrivateKey, containerService.NewAPEServer(defaultChainRouter, cnrRdr, newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient, - containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc), + containerService.NewSplitterService( + c.cfgContainer.containerBatchSize, c.respSvc, + containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc)), ), ) service = containerService.NewAuditService(service, c.log, c.audit) diff --git a/config/example/node.env b/config/example/node.env index f470acf3e0..b2a0633a98 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -83,6 +83,9 @@ FROSTFS_POLICER_HEAD_TIMEOUT=15s FROSTFS_REPLICATOR_PUT_TIMEOUT=15s FROSTFS_REPLICATOR_POOL_SIZE=10 +# Container service section +FROSTFS_CONTAINER_LIST_STREAM_BATCH_SIZE=500 + # Object service section FROSTFS_OBJECT_PUT_REMOTE_POOL_SIZE=100 FROSTFS_OBJECT_PUT_LOCAL_POOL_SIZE=200 diff --git a/config/example/node.json b/config/example/node.json index dba3bad8b0..f3192ac2f0 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -124,6 +124,11 @@ "pool_size": 10, "put_timeout": "15s" }, + "container": { + "list_stream": { + "batch_size": "500" + } + }, "object": { "delete": { "tombstone_lifetime": 10 diff --git a/config/example/node.yaml b/config/example/node.yaml index 8f9300b4a5..a179b47048 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -108,6 +108,10 @@ replicator: put_timeout: 15s # timeout for the Replicator PUT remote operation pool_size: 10 # maximum amount of concurrent replications +container: + list_stream: + batch_size: 500 # container_batch_size is the maximum amount of containers to send via stream at once + object: delete: tombstone_lifetime: 10 # tombstone "local" lifetime in epochs diff --git a/go.mod b/go.mod index 6ac37d3433..8f40538726 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241206094944-81c423e7094d + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241210104938-c4463df8d467 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 diff --git a/go.sum b/go.sum index e084c2445a..d633962020 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241206094944-81c423e7094d h1:FpXI+mOrmJk3t2MKQFZuhLjCHDyDeo5rtP1WXl7gUWc= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241206094944-81c423e7094d/go.mod h1:eoK7+KZQ9GJxbzIs6vTnoUJqFDppavInLRHaN4MYgZg= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241210104938-c4463df8d467 h1:MH9uHZFZNyUCL+YChiDcVeXPjhTDcFDeoGr8Mc8NY9M= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241210104938-c4463df8d467/go.mod h1:eoK7+KZQ9GJxbzIs6vTnoUJqFDppavInLRHaN4MYgZg= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= diff --git a/pkg/network/transport/container/grpc/service.go b/pkg/network/transport/container/grpc/service.go index 49d083a906..8cbf8d9c38 100644 --- a/pkg/network/transport/container/grpc/service.go +++ b/pkg/network/transport/container/grpc/service.go @@ -80,3 +80,26 @@ func (s *Server) List(ctx context.Context, req *containerGRPC.ListRequest) (*con return resp.ToGRPCMessage().(*containerGRPC.ListResponse), nil } + +type containerStreamerV2 struct { + containerGRPC.ContainerService_ListStreamServer +} + +func (s *containerStreamerV2) Send(resp *container.ListStreamResponse) error { + return s.ContainerService_ListStreamServer.Send( + resp.ToGRPCMessage().(*containerGRPC.ListStreamResponse), + ) +} + +// ListStream converts gRPC ListRequest message and server-side stream and overtakes its data +// to gRPC stream. +func (s *Server) ListStream(req *containerGRPC.ListStreamRequest, gStream containerGRPC.ContainerService_ListStreamServer) error { + listReq := new(container.ListStreamRequest) + if err := listReq.FromGRPCMessage(req); err != nil { + return err + } + + return s.srv.ListStream(listReq, &containerStreamerV2{ + ContainerService_ListStreamServer: gStream, + }) +} diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 2cdb30b459..493452fa6c 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -175,6 +175,79 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co return nil, apeErr(nativeschema.MethodListContainers, s) } +func (ac *apeChecker) ListStream(req *container.ListStreamRequest, stream ListStream) error { + ctx, span := tracing.StartSpanFromContext(stream.Context(), "apeChecker.ListStream") + defer span.End() + + role, pk, err := ac.getRoleWithoutContainerID(req.GetBody().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) + if err != nil { + return err + } + + reqProps := map[string]string{ + nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(pk.Bytes()), + nativeschema.PropertyKeyActorRole: role, + } + + reqProps, err = ac.fillWithUserClaimTags(reqProps, pk) + if err != nil { + return err + } + if p, ok := peer.FromContext(ctx); ok { + if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok { + reqProps[commonschema.PropertyKeyFrostFSSourceIP] = tcpAddr.IP.String() + } + } + + namespace, err := ac.namespaceByOwner(req.GetBody().GetOwnerID()) + if err != nil { + return fmt.Errorf("could not get owner namespace: %w", err) + } + if err := ac.validateNamespaceByPublicKey(pk, namespace); err != nil { + return err + } + + request := aperequest.NewRequest( + nativeschema.MethodListContainers, + aperequest.NewResource( + resourceName(namespace, ""), + make(map[string]string), + ), + reqProps, + ) + + groups, err := aperequest.Groups(ac.frostFSIDClient, pk) + if err != nil { + return fmt.Errorf("failed to get group ids: %w", err) + } + + // Policy contract keeps group related chains as namespace-group pair. + for i := range groups { + groups[i] = fmt.Sprintf("%s:%s", namespace, groups[i]) + } + + rt := policyengine.NewRequestTargetWithNamespace(namespace) + rt.User = &policyengine.Target{ + Type: policyengine.User, + Name: fmt.Sprintf("%s:%s", namespace, pk.Address()), + } + rt.Groups = make([]policyengine.Target, len(groups)) + for i := range groups { + rt.Groups[i] = policyengine.GroupTarget(groups[i]) + } + + s, found, err := ac.router.IsAllowed(apechain.Ingress, rt, request) + if err != nil { + return err + } + + if found && s == apechain.Allow { + return ac.next.ListStream(req, stream) + } + + return apeErr(nativeschema.MethodListContainers, s) +} + func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) { ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Put") defer span.End() diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index b6b42a559d..513ffff023 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -1079,6 +1079,11 @@ func (s *srvStub) List(context.Context, *container.ListRequest) (*container.List return &container.ListResponse{}, nil } +func (s *srvStub) ListStream(*container.ListStreamRequest, ListStream) error { + s.calls["ListStream"]++ + return nil +} + func (s *srvStub) Put(context.Context, *container.PutRequest) (*container.PutResponse, error) { s.calls["Put"]++ return &container.PutResponse{}, nil diff --git a/pkg/services/container/audit.go b/pkg/services/container/audit.go index 411eb48630..b235efa3c5 100644 --- a/pkg/services/container/audit.go +++ b/pkg/services/container/audit.go @@ -63,6 +63,17 @@ func (a *auditService) List(ctx context.Context, req *container.ListRequest) (*c return res, err } +// ListStream implements Server. +func (a *auditService) ListStream(req *container.ListStreamRequest, stream ListStream) error { + err := a.next.ListStream(req, stream) + if !a.enabled.Load() { + return err + } + audit.LogRequest(stream.Context(), a.log, container_grpc.ContainerService_ListStream_FullMethodName, req, + audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil) + return err +} + // Put implements Server. func (a *auditService) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) { res, err := a.next.Put(ctx, req) diff --git a/pkg/services/container/executor.go b/pkg/services/container/executor.go index 70234d3de1..cdd0d25142 100644 --- a/pkg/services/container/executor.go +++ b/pkg/services/container/executor.go @@ -14,6 +14,7 @@ type ServiceExecutor interface { Delete(context.Context, *session.Token, *container.DeleteRequestBody) (*container.DeleteResponseBody, error) Get(context.Context, *container.GetRequestBody) (*container.GetResponseBody, error) List(context.Context, *container.ListRequestBody) (*container.ListResponseBody, error) + ListStream(context.Context, *container.ListStreamRequest, ListStream) error } type executorSvc struct { @@ -93,3 +94,11 @@ func (s *executorSvc) List(ctx context.Context, req *container.ListRequest) (*co s.respSvc.SetMeta(resp) return resp, nil } + +func (s *executorSvc) ListStream(req *container.ListStreamRequest, stream ListStream) error { + err := s.exec.ListStream(stream.Context(), req, stream) + if err != nil { + return fmt.Errorf("could not execute ListStream request: %w", err) + } + return nil +} diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index 211f469f32..e9d1606f19 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -200,3 +200,35 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) return res, nil } + +func (s *morphExecutor) ListStream(_ context.Context, req *container.ListStreamRequest, stream containerSvc.ListStream) error { + body := req.GetBody() + idV2 := body.GetOwnerID() + if idV2 == nil { + return errMissingUserID + } + + var id user.ID + + err := id.ReadFromV2(*idV2) + if err != nil { + return fmt.Errorf("invalid user ID: %w", err) + } + + cnrs, err := s.rdr.ContainersOf(&id) + if err != nil { + return err + } + + cidList := make([]refs.ContainerID, len(cnrs)) + for i := range cnrs { + cnrs[i].WriteToV2(&cidList[i]) + } + + resBody := new(container.ListStreamResponseBody) + resBody.SetContainerIDs(cidList) + r := new(container.ListStreamResponse) + r.SetBody(resBody) + + return stream.Send(r) +} diff --git a/pkg/services/container/server.go b/pkg/services/container/server.go index 78fd3d34ce..d9208077d1 100644 --- a/pkg/services/container/server.go +++ b/pkg/services/container/server.go @@ -3,6 +3,7 @@ package container import ( "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" ) @@ -12,4 +13,11 @@ type Server interface { Get(context.Context, *container.GetRequest) (*container.GetResponse, error) Delete(context.Context, *container.DeleteRequest) (*container.DeleteResponse, error) List(context.Context, *container.ListRequest) (*container.ListResponse, error) + ListStream(*container.ListStreamRequest, ListStream) error +} + +// ListStream is an interface of FrostFS API v2 compatible search streamer. +type ListStream interface { + util.ServerStream + Send(*container.ListStreamResponse) error } diff --git a/pkg/services/container/sign.go b/pkg/services/container/sign.go index c478c0e1c9..85fe7ae873 100644 --- a/pkg/services/container/sign.go +++ b/pkg/services/container/sign.go @@ -56,3 +56,40 @@ func (s *signService) List(ctx context.Context, req *container.ListRequest) (*co resp, err := util.EnsureNonNilResponse(s.svc.List(ctx, req)) return resp, s.sigSvc.SignResponse(resp, err) } + +func (s *signService) ListStream(req *container.ListStreamRequest, stream ListStream) error { + if err := s.sigSvc.VerifyRequest(req); err != nil { + resp := new(container.ListStreamResponse) + _ = s.sigSvc.SignResponse(resp, err) + return stream.Send(resp) + } + + ss := &listStreamSigner{ + ListStream: stream, + sigSvc: s.sigSvc, + } + err := s.svc.ListStream(req, ss) + if err != nil || !ss.nonEmptyResp { + return ss.send(new(container.ListStreamResponse), err) + } + return nil +} + +type listStreamSigner struct { + ListStream + sigSvc *util.SignService + + nonEmptyResp bool // set on first Send call +} + +func (s *listStreamSigner) Send(resp *container.ListStreamResponse) error { + s.nonEmptyResp = true + return s.send(resp, nil) +} + +func (s *listStreamSigner) send(resp *container.ListStreamResponse, err error) error { + if err := s.sigSvc.SignResponse(resp, err); err != nil { + return err + } + return s.ListStream.Send(resp) +} diff --git a/pkg/services/container/transport_splitter.go b/pkg/services/container/transport_splitter.go new file mode 100644 index 0000000000..4f8708da7e --- /dev/null +++ b/pkg/services/container/transport_splitter.go @@ -0,0 +1,92 @@ +package container + +import ( + "context" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" +) + +type ( + TransportSplitter struct { + next Server + + respSvc *response.Service + cnrAmount uint32 + } + + listStreamMsgSizeCtrl struct { + util.ServerStream + stream ListStream + respSvc *response.Service + cnrAmount uint32 + } +) + +func NewSplitterService(cnrAmount uint32, respSvc *response.Service, next Server) Server { + return &TransportSplitter{ + next: next, + respSvc: respSvc, + cnrAmount: cnrAmount, + } +} + +func (s *TransportSplitter) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) { + return s.next.Put(ctx, req) +} + +func (s *TransportSplitter) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) { + return s.next.Delete(ctx, req) +} + +func (s *TransportSplitter) Get(ctx context.Context, req *container.GetRequest) (*container.GetResponse, error) { + return s.next.Get(ctx, req) +} + +func (s *TransportSplitter) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) { + return s.next.List(ctx, req) +} + +func (s *TransportSplitter) ListStream(req *container.ListStreamRequest, stream ListStream) error { + return s.next.ListStream(req, &listStreamMsgSizeCtrl{ + ServerStream: stream, + stream: stream, + respSvc: s.respSvc, + cnrAmount: s.cnrAmount, + }) +} + +func (s *listStreamMsgSizeCtrl) Send(resp *container.ListStreamResponse) error { + s.respSvc.SetMeta(resp) + body := resp.GetBody() + ids := body.GetContainerIDs() + + var newResp *container.ListStreamResponse + + for { + if newResp == nil { + newResp = new(container.ListStreamResponse) + newResp.SetBody(body) + } + + cut := min(s.cnrAmount, uint32(len(ids))) + + body.SetContainerIDs(ids[:cut]) + newResp.SetMetaHeader(resp.GetMetaHeader()) + newResp.SetVerificationHeader(resp.GetVerificationHeader()) + + if err := s.stream.Send(newResp); err != nil { + return fmt.Errorf("TransportSplitter: %w", err) + } + + ids = ids[cut:] + + if len(ids) == 0 { + break + } + } + + return nil +} From bed49e6ace1b975e0c0d4a53d82540ad35e90bf3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 18 Dec 2024 10:01:19 +0300 Subject: [PATCH 1102/1413] [#1569] cli: Make `--range` flag required in `object hash` Previously, `object head` was used if no range was provided. This is wrong on multiple levels: 1. We print an error if the checksum is missing in header, even though taking hash is possible. 2. We silently ignore --salt parameter. 3. `--range` is required for Object.RANGEHASH RPC, custom logic for one specific usecase has no value. So we make it required and make CLI command follow more closely the FrostFS API. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/object/hash.go | 31 ++------------------------ 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/hash.go b/cmd/frostfs-cli/modules/object/hash.go index 26243e7e7b..b18fab5e0a 100644 --- a/cmd/frostfs-cli/modules/object/hash.go +++ b/cmd/frostfs-cli/modules/object/hash.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/spf13/cobra" @@ -43,6 +42,8 @@ func initObjectHashCmd() { _ = objectHashCmd.MarkFlagRequired(commonflags.OIDFlag) flags.String("range", "", "Range to take hash from in the form offset1:length1,...") + _ = objectHashCmd.MarkFlagRequired("range") + flags.String("type", hashSha256, "Hash type. Either 'sha256' or 'tz'") flags.String(getRangeHashSaltFlag, "", "Salt in hex format") } @@ -67,34 +68,6 @@ func getObjectHash(cmd *cobra.Command, _ []string) { cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) tz := typ == hashTz - fullHash := len(ranges) == 0 - if fullHash { - var headPrm internalclient.HeadObjectPrm - headPrm.SetClient(cli) - Prepare(cmd, &headPrm) - headPrm.SetAddress(objAddr) - - // get hash of full payload through HEAD (may be user can do it through dedicated command?) - res, err := internalclient.HeadObject(cmd.Context(), headPrm) - commonCmd.ExitOnErr(cmd, "rpc error: %w", err) - - var cs checksum.Checksum - var csSet bool - - if tz { - cs, csSet = res.Header().PayloadHomomorphicHash() - } else { - cs, csSet = res.Header().PayloadChecksum() - } - - if csSet { - cmd.Println(hex.EncodeToString(cs.Value())) - } else { - cmd.Println("Missing checksum in object header.") - } - - return - } var hashPrm internalclient.HashPayloadRangesPrm hashPrm.SetClient(cli) From e44b84c18c428a691b36ec100a41cfa100e4ad8a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 18 Dec 2024 10:07:22 +0300 Subject: [PATCH 1103/1413] [#1569] cli: Remove unnecessary variable after refactoring Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/object/hash.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/hash.go b/cmd/frostfs-cli/modules/object/hash.go index b18fab5e0a..461c35f30c 100644 --- a/cmd/frostfs-cli/modules/object/hash.go +++ b/cmd/frostfs-cli/modules/object/hash.go @@ -67,8 +67,6 @@ func getObjectHash(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) - tz := typ == hashTz - var hashPrm internalclient.HashPayloadRangesPrm hashPrm.SetClient(cli) Prepare(cmd, &hashPrm) @@ -77,7 +75,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) { hashPrm.SetSalt(salt) hashPrm.SetRanges(ranges) - if tz { + if typ == hashTz { hashPrm.TZ() } From bd0197eaa8579ac4aa54bc2ebc7b38a610a38aa2 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 18 Dec 2024 09:38:14 +0300 Subject: [PATCH 1104/1413] [#1568] storage: Remove "could not/can't/failed to" from error messages Signed-off-by: Evgenii Stratonikov --- .../blobovnicza/control.go | 4 ++-- .../blobovnicza/iterate.go | 2 +- .../blobstor/blobovniczatree/get.go | 4 ++-- .../blobstor/blobovniczatree/get_range.go | 4 ++-- .../blobstor/blobovniczatree/iterate.go | 4 ++-- .../blobstor/blobovniczatree/manager.go | 6 ++--- .../blobstor/fstree/fstree.go | 4 ++-- .../blobstor/memstore/memstore.go | 4 ++-- pkg/local_object_storage/blobstor/mode.go | 2 +- pkg/local_object_storage/blobstor/put.go | 2 +- pkg/local_object_storage/engine/control.go | 10 ++++---- pkg/local_object_storage/engine/evacuate.go | 2 +- pkg/local_object_storage/engine/shards.go | 12 +++++----- pkg/local_object_storage/metabase/control.go | 12 +++++----- pkg/local_object_storage/metabase/counter.go | 22 ++++++++--------- pkg/local_object_storage/metabase/delete.go | 24 +++++++++---------- pkg/local_object_storage/metabase/exists.go | 2 +- pkg/local_object_storage/metabase/get.go | 2 +- .../metabase/graveyard.go | 6 ++--- pkg/local_object_storage/metabase/inhume.go | 2 +- pkg/local_object_storage/metabase/mode.go | 4 ++-- pkg/local_object_storage/metabase/put.go | 20 ++++++++-------- pkg/local_object_storage/metabase/select.go | 2 +- pkg/local_object_storage/metabase/shard_id.go | 8 +++---- pkg/local_object_storage/metabase/upgrade.go | 8 +++---- pkg/local_object_storage/metabase/util.go | 4 ++-- pkg/local_object_storage/metabase/version.go | 2 +- pkg/local_object_storage/pilorama/boltdb.go | 10 ++++---- pkg/local_object_storage/shard/container.go | 4 ++-- pkg/local_object_storage/shard/control.go | 22 ++++++++--------- pkg/local_object_storage/shard/get.go | 2 +- pkg/local_object_storage/shard/id.go | 4 ++-- pkg/local_object_storage/shard/list.go | 12 +++++----- pkg/local_object_storage/shard/put.go | 4 ++-- pkg/local_object_storage/shard/select.go | 2 +- .../writecache/iterate.go | 2 +- pkg/local_object_storage/writecache/mode.go | 8 +++---- .../writecache/storage.go | 4 ++-- .../writecache/upgrade.go | 4 ++-- 39 files changed, 128 insertions(+), 128 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/control.go b/pkg/local_object_storage/blobovnicza/control.go index d0e71a8768..4947512cc7 100644 --- a/pkg/local_object_storage/blobovnicza/control.go +++ b/pkg/local_object_storage/blobovnicza/control.go @@ -129,7 +129,7 @@ func (b *Blobovnicza) initializeCounters(ctx context.Context) error { }) }) if err != nil { - return fmt.Errorf("can't determine DB size: %w", err) + return fmt.Errorf("determine DB size: %w", err) } if (!sizeExists || !itemsCountExists) && !b.boltOptions.ReadOnly { b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMeta, zap.Uint64("size", size), zap.Uint64("items", items)) @@ -140,7 +140,7 @@ func (b *Blobovnicza) initializeCounters(ctx context.Context) error { return saveItemsCount(tx, items) }); err != nil { b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMetaFailed, zap.Uint64("size", size), zap.Uint64("items", items)) - return fmt.Errorf("can't save blobovnicza's size and items count: %w", err) + return fmt.Errorf("save blobovnicza's size and items count: %w", err) } b.log.Debug(ctx, logs.BlobovniczaSavingCountersToMetaSuccess, zap.Uint64("size", size), zap.Uint64("items", items)) } diff --git a/pkg/local_object_storage/blobovnicza/iterate.go b/pkg/local_object_storage/blobovnicza/iterate.go index 01e5529dae..cd33b263c4 100644 --- a/pkg/local_object_storage/blobovnicza/iterate.go +++ b/pkg/local_object_storage/blobovnicza/iterate.go @@ -146,7 +146,7 @@ func (b *Blobovnicza) Iterate(ctx context.Context, prm IteratePrm) (IterateRes, if prm.ignoreErrors { return nil } - return fmt.Errorf("could not decode address key: %w", err) + return fmt.Errorf("decode address key: %w", err) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 1a4f11c29a..5d158644e9 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -115,13 +115,13 @@ func (b *Blobovniczas) getObject(ctx context.Context, blz *blobovnicza.Blobovnic // decompress the data data, err := b.compression.Decompress(res.Object()) if err != nil { - return common.GetRes{}, fmt.Errorf("could not decompress object data: %w", err) + return common.GetRes{}, fmt.Errorf("decompress object data: %w", err) } // unmarshal the object obj := objectSDK.New() if err := obj.Unmarshal(data); err != nil { - return common.GetRes{}, fmt.Errorf("could not unmarshal the object: %w", err) + return common.GetRes{}, fmt.Errorf("unmarshal the object: %w", err) } return common.GetRes{Object: obj, RawData: data}, nil diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 6d06b8e6f9..84b9bc55fb 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -130,13 +130,13 @@ func (b *Blobovniczas) getObjectRange(ctx context.Context, blz *blobovnicza.Blob // decompress the data data, err := b.compression.Decompress(res.Object()) if err != nil { - return common.GetRangeRes{}, fmt.Errorf("could not decompress object data: %w", err) + return common.GetRangeRes{}, fmt.Errorf("decompress object data: %w", err) } // unmarshal the object obj := objectSDK.New() if err := obj.Unmarshal(data); err != nil { - return common.GetRangeRes{}, fmt.Errorf("could not unmarshal the object: %w", err) + return common.GetRangeRes{}, fmt.Errorf("unmarshal the object: %w", err) } from := prm.Range.GetOffset() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index a710cf988a..5c2d58ca15 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -49,7 +49,7 @@ func (b *Blobovniczas) Iterate(ctx context.Context, prm common.IteratePrm) (comm zap.String("root_path", b.rootPath)) return nil } - return fmt.Errorf("could not decompress object data: %w", err) + return fmt.Errorf("decompress object data: %w", err) } if prm.Handler != nil { @@ -82,7 +82,7 @@ func (b *Blobovniczas) iterateBlobovniczas(ctx context.Context, ignoreErrors boo zap.String("root_path", b.rootPath)) return false, nil } - return false, fmt.Errorf("could not open blobovnicza %s: %w", p, err) + return false, fmt.Errorf("open blobovnicza %s: %w", p, err) } defer shBlz.Close(ctx) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index 7d44aa5c6c..f2f9509adb 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -69,10 +69,10 @@ func (b *sharedDB) Open(ctx context.Context) (*blobovnicza.Blobovnicza, error) { )...) if err := blz.Open(ctx); err != nil { - return nil, fmt.Errorf("could not open blobovnicza %s: %w", b.path, err) + return nil, fmt.Errorf("open blobovnicza %s: %w", b.path, err) } if err := blz.Init(ctx); err != nil { - return nil, fmt.Errorf("could not init blobovnicza %s: %w", b.path, err) + return nil, fmt.Errorf("init blobovnicza %s: %w", b.path, err) } b.refCount++ @@ -127,7 +127,7 @@ func (b *sharedDB) CloseAndRemoveFile(ctx context.Context) error { zap.String("id", b.path), zap.Error(err), ) - return fmt.Errorf("failed to close blobovnicza (path = %s): %w", b.path, err) + return fmt.Errorf("close blobovnicza (path = %s): %w", b.path, err) } b.refCount = 0 diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index a77ad2f93c..031b385b2d 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -538,7 +538,7 @@ func (t *FSTree) countFiles() (uint64, uint64, error) { }, ) if err != nil { - return 0, 0, fmt.Errorf("could not walk through %s directory: %w", t.RootPath, err) + return 0, 0, fmt.Errorf("walk through %s directory: %w", t.RootPath, err) } return count, size, nil @@ -577,7 +577,7 @@ func (t *FSTree) ObjectsCount(ctx context.Context) (uint64, error) { }, ) if err != nil { - return 0, fmt.Errorf("could not walk through %s directory: %w", t.RootPath, err) + return 0, fmt.Errorf("walk through %s directory: %w", t.RootPath, err) } success = true return result, nil diff --git a/pkg/local_object_storage/blobstor/memstore/memstore.go b/pkg/local_object_storage/blobstor/memstore/memstore.go index 0252c79835..3afef7d186 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore.go @@ -47,13 +47,13 @@ func (s *memstoreImpl) Get(_ context.Context, req common.GetPrm) (common.GetRes, // Decompress the data. var err error if data, err = s.compression.Decompress(data); err != nil { - return common.GetRes{}, fmt.Errorf("could not decompress object data: %w", err) + return common.GetRes{}, fmt.Errorf("decompress object data: %w", err) } // Unmarshal the SDK object. obj := objectSDK.New() if err := obj.Unmarshal(data); err != nil { - return common.GetRes{}, fmt.Errorf("could not unmarshal the object: %w", err) + return common.GetRes{}, fmt.Errorf("unmarshal the object: %w", err) } return common.GetRes{Object: obj, RawData: data}, nil diff --git a/pkg/local_object_storage/blobstor/mode.go b/pkg/local_object_storage/blobstor/mode.go index af19e398ee..80268fa7af 100644 --- a/pkg/local_object_storage/blobstor/mode.go +++ b/pkg/local_object_storage/blobstor/mode.go @@ -27,7 +27,7 @@ func (b *BlobStor) SetMode(ctx context.Context, m mode.Mode) error { } } if err != nil { - return fmt.Errorf("can't set blobstor mode (old=%s, new=%s): %w", b.mode, m, err) + return fmt.Errorf("set blobstor mode (old=%s, new=%s): %w", b.mode, m, err) } b.mode = m diff --git a/pkg/local_object_storage/blobstor/put.go b/pkg/local_object_storage/blobstor/put.go index 342da28bfb..fe9c109dd1 100644 --- a/pkg/local_object_storage/blobstor/put.go +++ b/pkg/local_object_storage/blobstor/put.go @@ -52,7 +52,7 @@ func (b *BlobStor) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, e // marshal object data, err := prm.Object.Marshal() if err != nil { - return common.PutRes{}, fmt.Errorf("could not marshal the object: %w", err) + return common.PutRes{}, fmt.Errorf("marshal the object: %w", err) } prm.RawData = data } diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index bd9eb1021b..6a416cfd94 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -95,7 +95,7 @@ func (e *StorageEngine) Init(ctx context.Context) error { err := eg.Wait() close(errCh) if err != nil { - return fmt.Errorf("failed to initialize shards: %w", err) + return fmt.Errorf("initialize shards: %w", err) } for res := range errCh { @@ -117,7 +117,7 @@ func (e *StorageEngine) Init(ctx context.Context) error { continue } - return fmt.Errorf("could not initialize shard %s: %w", res.id, res.err) + return fmt.Errorf("initialize shard %s: %w", res.id, res.err) } } @@ -320,7 +320,7 @@ loop: for _, newID := range shardsToAdd { sh, err := e.createShard(ctx, rcfg.shards[newID]) if err != nil { - return fmt.Errorf("could not add new shard with '%s' metabase path: %w", newID, err) + return fmt.Errorf("add new shard with '%s' metabase path: %w", newID, err) } idStr := sh.ID().String() @@ -331,13 +331,13 @@ loop: } if err != nil { _ = sh.Close(ctx) - return fmt.Errorf("could not init %s shard: %w", idStr, err) + return fmt.Errorf("init %s shard: %w", idStr, err) } err = e.addShard(sh) if err != nil { _ = sh.Close(ctx) - return fmt.Errorf("could not add %s shard: %w", idStr, err) + return fmt.Errorf("add %s shard: %w", idStr, err) } e.log.Info(ctx, logs.EngineAddedNewShard, zap.String("id", idStr)) diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 2e0344bfbc..623f5c9416 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -578,7 +578,7 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree func (e *StorageEngine) evacuateTreeToOtherNode(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, prm EvacuateShardPrm) (bool, string, error) { if prm.TreeHandler == nil { - return false, "", fmt.Errorf("failed to evacuate tree '%s' for container %s from shard %s: local evacuation failed, but no remote evacuation available", tree.TreeID, tree.CID, sh.ID()) + return false, "", fmt.Errorf("evacuate tree '%s' for container %s from shard %s: local evacuation failed, but no remote evacuation available", tree.TreeID, tree.CID, sh.ID()) } return prm.TreeHandler(ctx, tree.CID, tree.TreeID, sh) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 898f685ecf..6d4844b75a 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -108,12 +108,12 @@ func (m *metricsWithID) SetEvacuationInProgress(value bool) { func (e *StorageEngine) AddShard(ctx context.Context, opts ...shard.Option) (*shard.ID, error) { sh, err := e.createShard(ctx, opts) if err != nil { - return nil, fmt.Errorf("could not create a shard: %w", err) + return nil, fmt.Errorf("create a shard: %w", err) } err = e.addShard(sh) if err != nil { - return nil, fmt.Errorf("could not add %s shard: %w", sh.ID().String(), err) + return nil, fmt.Errorf("add %s shard: %w", sh.ID().String(), err) } e.cfg.metrics.SetMode(sh.ID().String(), sh.GetMode()) @@ -124,7 +124,7 @@ func (e *StorageEngine) AddShard(ctx context.Context, opts ...shard.Option) (*sh func (e *StorageEngine) createShard(ctx context.Context, opts []shard.Option) (*shard.Shard, error) { id, err := generateShardID() if err != nil { - return nil, fmt.Errorf("could not generate shard ID: %w", err) + return nil, fmt.Errorf("generate shard ID: %w", err) } opts = e.appendMetrics(id, opts) @@ -180,7 +180,7 @@ func (e *StorageEngine) addShard(sh *shard.Shard) error { pool, err := ants.NewPool(int(e.shardPoolSize), ants.WithNonblocking(true)) if err != nil { - return fmt.Errorf("could not create pool: %w", err) + return fmt.Errorf("create pool: %w", err) } strID := sh.ID().String() @@ -374,7 +374,7 @@ func (e *StorageEngine) closeShards(ctx context.Context, deletedShards []hashedS zap.Error(err), ) multiErrGuard.Lock() - multiErr = errors.Join(multiErr, fmt.Errorf("could not change shard (id:%s) mode to disabled: %w", sh.ID(), err)) + multiErr = errors.Join(multiErr, fmt.Errorf("change shard (id:%s) mode to disabled: %w", sh.ID(), err)) multiErrGuard.Unlock() } @@ -385,7 +385,7 @@ func (e *StorageEngine) closeShards(ctx context.Context, deletedShards []hashedS zap.Error(err), ) multiErrGuard.Lock() - multiErr = errors.Join(multiErr, fmt.Errorf("could not close removed shard (id:%s): %w", sh.ID(), err)) + multiErr = errors.Join(multiErr, fmt.Errorf("close removed shard (id:%s): %w", sh.ID(), err)) multiErrGuard.Unlock() } return nil diff --git a/pkg/local_object_storage/metabase/control.go b/pkg/local_object_storage/metabase/control.go index 07fa7e9cf6..c19c65224a 100644 --- a/pkg/local_object_storage/metabase/control.go +++ b/pkg/local_object_storage/metabase/control.go @@ -54,7 +54,7 @@ func (db *DB) Open(ctx context.Context, m mode.Mode) error { func (db *DB) openDB(ctx context.Context, mode mode.Mode) error { err := util.MkdirAllX(filepath.Dir(db.info.Path), db.info.Permission) if err != nil { - return fmt.Errorf("can't create dir %s for metabase: %w", db.info.Path, err) + return fmt.Errorf("create dir %s for metabase: %w", db.info.Path, err) } db.log.Debug(ctx, logs.MetabaseCreatedDirectoryForMetabase, zap.String("path", db.info.Path)) @@ -73,7 +73,7 @@ func (db *DB) openBolt(ctx context.Context) error { db.boltDB, err = bbolt.Open(db.info.Path, db.info.Permission, db.boltOptions) if err != nil { - return fmt.Errorf("can't open boltDB database: %w", err) + return fmt.Errorf("open boltDB database: %w", err) } db.boltDB.MaxBatchDelay = db.boltBatchDelay db.boltDB.MaxBatchSize = db.boltBatchSize @@ -145,27 +145,27 @@ func (db *DB) init(reset bool) error { if reset { err := tx.DeleteBucket(name) if err != nil && !errors.Is(err, bbolt.ErrBucketNotFound) { - return fmt.Errorf("could not delete static bucket %s: %w", k, err) + return fmt.Errorf("delete static bucket %s: %w", k, err) } } _, err := tx.CreateBucketIfNotExists(name) if err != nil { - return fmt.Errorf("could not create static bucket %s: %w", k, err) + return fmt.Errorf("create static bucket %s: %w", k, err) } } for _, b := range deprecatedBuckets { err := tx.DeleteBucket(b) if err != nil && !errors.Is(err, bbolt.ErrBucketNotFound) { - return fmt.Errorf("could not delete deprecated bucket %s: %w", string(b), err) + return fmt.Errorf("delete deprecated bucket %s: %w", string(b), err) } } if !reset { // counters will be recalculated by refill metabase err = syncCounter(tx, false) if err != nil { - return fmt.Errorf("could not sync object counter: %w", err) + return fmt.Errorf("sync object counter: %w", err) } return nil diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index 3ead0d9a0a..f29dafe77c 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -238,14 +238,14 @@ func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID, isUserObject bool) error { } if err := db.updateShardObjectCounterBucket(b, phy, 1, true); err != nil { - return fmt.Errorf("could not increase phy object counter: %w", err) + return fmt.Errorf("increase phy object counter: %w", err) } if err := db.updateShardObjectCounterBucket(b, logical, 1, true); err != nil { - return fmt.Errorf("could not increase logical object counter: %w", err) + return fmt.Errorf("increase logical object counter: %w", err) } if isUserObject { if err := db.updateShardObjectCounterBucket(b, user, 1, true); err != nil { - return fmt.Errorf("could not increase user object counter: %w", err) + return fmt.Errorf("increase user object counter: %w", err) } } return db.incContainerObjectCounter(tx, cnrID, isUserObject) @@ -362,7 +362,7 @@ func (db *DB) incContainerObjectCounter(tx *bbolt.Tx, cnrID cid.ID, isUserObject func syncCounter(tx *bbolt.Tx, force bool) error { shardInfoB, err := createBucketLikelyExists(tx, shardInfoBucket) if err != nil { - return fmt.Errorf("could not get shard info bucket: %w", err) + return fmt.Errorf("get shard info bucket: %w", err) } shardObjectCounterInitialized := len(shardInfoB.Get(objectPhyCounterKey)) == 8 && len(shardInfoB.Get(objectLogicCounterKey)) == 8 && @@ -375,7 +375,7 @@ func syncCounter(tx *bbolt.Tx, force bool) error { containerCounterB, err := createBucketLikelyExists(tx, containerCounterBucketName) if err != nil { - return fmt.Errorf("could not get container counter bucket: %w", err) + return fmt.Errorf("get container counter bucket: %w", err) } var addr oid.Address @@ -428,7 +428,7 @@ func syncCounter(tx *bbolt.Tx, force bool) error { return nil }) if err != nil { - return fmt.Errorf("could not iterate objects: %w", err) + return fmt.Errorf("iterate objects: %w", err) } return setObjectCounters(counters, shardInfoB, containerCounterB) @@ -448,7 +448,7 @@ func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, container value := containerCounterValue(count) err := containerCounterB.Put(key, value) if err != nil { - return fmt.Errorf("could not update phy container object counter: %w", err) + return fmt.Errorf("update phy container object counter: %w", err) } } phyData := make([]byte, 8) @@ -456,7 +456,7 @@ func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, container err := shardInfoB.Put(objectPhyCounterKey, phyData) if err != nil { - return fmt.Errorf("could not update phy object counter: %w", err) + return fmt.Errorf("update phy object counter: %w", err) } logData := make([]byte, 8) @@ -464,7 +464,7 @@ func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, container err = shardInfoB.Put(objectLogicCounterKey, logData) if err != nil { - return fmt.Errorf("could not update logic object counter: %w", err) + return fmt.Errorf("update logic object counter: %w", err) } userData := make([]byte, 8) @@ -472,7 +472,7 @@ func setObjectCounters(counters map[cid.ID]ObjectCounters, shardInfoB, container err = shardInfoB.Put(objectUserCounterKey, userData) if err != nil { - return fmt.Errorf("could not update user object counter: %w", err) + return fmt.Errorf("update user object counter: %w", err) } return nil @@ -492,7 +492,7 @@ func parseContainerCounterKey(buf []byte) (cid.ID, error) { } var cnrID cid.ID if err := cnrID.Decode(buf); err != nil { - return cid.ID{}, fmt.Errorf("failed to decode container ID: %w", err) + return cid.ID{}, fmt.Errorf("decode container ID: %w", err) } return cnrID, nil } diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 62ab1056d9..00ee2baa36 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -163,26 +163,26 @@ func (db *DB) updateCountersDelete(tx *bbolt.Tx, res DeleteRes) error { if res.phyCount > 0 { err := db.updateShardObjectCounter(tx, phy, res.phyCount, false) if err != nil { - return fmt.Errorf("could not decrease phy object counter: %w", err) + return fmt.Errorf("decrease phy object counter: %w", err) } } if res.logicCount > 0 { err := db.updateShardObjectCounter(tx, logical, res.logicCount, false) if err != nil { - return fmt.Errorf("could not decrease logical object counter: %w", err) + return fmt.Errorf("decrease logical object counter: %w", err) } } if res.userCount > 0 { err := db.updateShardObjectCounter(tx, user, res.userCount, false) if err != nil { - return fmt.Errorf("could not decrease user object counter: %w", err) + return fmt.Errorf("decrease user object counter: %w", err) } } if err := db.updateContainerCounter(tx, res.removedByCnrID, false); err != nil { - return fmt.Errorf("could not decrease container object counter: %w", err) + return fmt.Errorf("decrease container object counter: %w", err) } return nil } @@ -259,7 +259,7 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter if garbageBKT != nil { err := garbageBKT.Delete(addrKey) if err != nil { - return deleteSingleResult{}, fmt.Errorf("could not remove from garbage bucket: %w", err) + return deleteSingleResult{}, fmt.Errorf("remove from garbage bucket: %w", err) } } return deleteSingleResult{}, nil @@ -280,7 +280,7 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter if garbageBKT != nil { err := garbageBKT.Delete(addrKey) if err != nil { - return deleteSingleResult{}, fmt.Errorf("could not remove from garbage bucket: %w", err) + return deleteSingleResult{}, fmt.Errorf("remove from garbage bucket: %w", err) } } @@ -308,7 +308,7 @@ func (db *DB) delete(tx *bbolt.Tx, addr oid.Address, refCounter referenceCounter // remove object err = db.deleteObject(tx, obj, false) if err != nil { - return deleteSingleResult{}, fmt.Errorf("could not remove object: %w", err) + return deleteSingleResult{}, fmt.Errorf("remove object: %w", err) } if err := deleteECRelatedInfo(tx, garbageBKT, obj, addr.Container(), refCounter); err != nil { @@ -335,12 +335,12 @@ func (db *DB) deleteObject( err = updateListIndexes(tx, obj, delListIndexItem) if err != nil { - return fmt.Errorf("can't remove list indexes: %w", err) + return fmt.Errorf("remove list indexes: %w", err) } err = updateFKBTIndexes(tx, obj, delFKBTIndexItem) if err != nil { - return fmt.Errorf("can't remove fake bucket tree indexes: %w", err) + return fmt.Errorf("remove fake bucket tree indexes: %w", err) } if isParent { @@ -351,7 +351,7 @@ func (db *DB) deleteObject( addrKey := addressKey(object.AddressOf(obj), key) err := garbageBKT.Delete(addrKey) if err != nil { - return fmt.Errorf("could not remove from garbage bucket: %w", err) + return fmt.Errorf("remove from garbage bucket: %w", err) } } } @@ -529,7 +529,7 @@ func deleteECRelatedInfo(tx *bbolt.Tx, garbageBKT *bbolt.Bucket, obj *objectSDK. addrKey := addressKey(ecParentAddress, make([]byte, addressKeySize)) err := garbageBKT.Delete(addrKey) if err != nil { - return fmt.Errorf("could not remove EC parent from garbage bucket: %w", err) + return fmt.Errorf("remove EC parent from garbage bucket: %w", err) } } @@ -567,7 +567,7 @@ func deleteECRelatedInfo(tx *bbolt.Tx, garbageBKT *bbolt.Bucket, obj *objectSDK. addrKey := addressKey(splitParentAddress, make([]byte, addressKeySize)) err := garbageBKT.Delete(addrKey) if err != nil { - return fmt.Errorf("could not remove EC parent from garbage bucket: %w", err) + return fmt.Errorf("remove EC parent from garbage bucket: %w", err) } } diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index 411beb6b39..3133c5480a 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -229,7 +229,7 @@ func getSplitInfo(tx *bbolt.Tx, cnr cid.ID, key []byte) (*objectSDK.SplitInfo, e err := splitInfo.Unmarshal(bytes.Clone(rawSplitInfo)) if err != nil { - return nil, fmt.Errorf("can't unmarshal split info from root index: %w", err) + return nil, fmt.Errorf("unmarshal split info from root index: %w", err) } return splitInfo, nil diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index 1cbf78ab2e..af274b245f 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -187,7 +187,7 @@ func getVirtualObject(tx *bbolt.Tx, cnr cid.ID, key []byte, raw bool) (*objectSD err = child.Unmarshal(bytes.Clone(data)) if err != nil { - return nil, fmt.Errorf("can't unmarshal child with parent: %w", err) + return nil, fmt.Errorf("unmarshal child with parent: %w", err) } par := child.Parent() diff --git a/pkg/local_object_storage/metabase/graveyard.go b/pkg/local_object_storage/metabase/graveyard.go index b0db952b27..2f23d424c8 100644 --- a/pkg/local_object_storage/metabase/graveyard.go +++ b/pkg/local_object_storage/metabase/graveyard.go @@ -177,7 +177,7 @@ type gcHandler struct { func (g gcHandler) handleKV(k, _ []byte) error { o, err := garbageFromKV(k) if err != nil { - return fmt.Errorf("could not parse garbage object: %w", err) + return fmt.Errorf("parse garbage object: %w", err) } return g.h(o) @@ -190,7 +190,7 @@ type graveyardHandler struct { func (g graveyardHandler) handleKV(k, v []byte) error { o, err := graveFromKV(k, v) if err != nil { - return fmt.Errorf("could not parse grave: %w", err) + return fmt.Errorf("parse grave: %w", err) } return g.h(o) @@ -240,7 +240,7 @@ func (db *DB) iterateDeletedObj(tx *bbolt.Tx, h kvHandler, offset *oid.Address) func garbageFromKV(k []byte) (res GarbageObject, err error) { err = decodeAddressFromKey(&res.addr, k) if err != nil { - err = fmt.Errorf("could not parse address: %w", err) + err = fmt.Errorf("parse address: %w", err) } return diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 5ac0c0be5a..99fdec3102 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -373,7 +373,7 @@ func (db *DB) getInhumeTargetBucketAndValue(garbageBKT, graveyardBKT *bbolt.Buck if data != nil { err := targetBucket.Delete(tombKey) if err != nil { - return nil, nil, fmt.Errorf("could not remove grave with tombstone key: %w", err) + return nil, nil, fmt.Errorf("remove grave with tombstone key: %w", err) } } diff --git a/pkg/local_object_storage/metabase/mode.go b/pkg/local_object_storage/metabase/mode.go index ce6ae10047..7edb963841 100644 --- a/pkg/local_object_storage/metabase/mode.go +++ b/pkg/local_object_storage/metabase/mode.go @@ -19,7 +19,7 @@ func (db *DB) SetMode(ctx context.Context, m mode.Mode) error { if !db.mode.NoMetabase() { if err := db.Close(ctx); err != nil { - return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err) + return fmt.Errorf("set metabase mode (old=%s, new=%s): %w", db.mode, m, err) } } @@ -31,7 +31,7 @@ func (db *DB) SetMode(ctx context.Context, m mode.Mode) error { err = db.Init(ctx) } if err != nil { - return fmt.Errorf("can't set metabase mode (old=%s, new=%s): %w", db.mode, m, err) + return fmt.Errorf("set metabase mode (old=%s, new=%s): %w", db.mode, m, err) } } diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 6f9dc1bf04..16918c4d93 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -180,18 +180,18 @@ func (db *DB) insertObject(tx *bbolt.Tx, obj *objectSDK.Object, id []byte, si *o err := putUniqueIndexes(tx, obj, si, id) if err != nil { - return fmt.Errorf("can't put unique indexes: %w", err) + return fmt.Errorf("put unique indexes: %w", err) } err = updateListIndexes(tx, obj, putListIndexItem) if err != nil { - return fmt.Errorf("can't put list indexes: %w", err) + return fmt.Errorf("put list indexes: %w", err) } if indexAttributes { err = updateFKBTIndexes(tx, obj, putFKBTIndexItem) if err != nil { - return fmt.Errorf("can't put fake bucket tree indexes: %w", err) + return fmt.Errorf("put fake bucket tree indexes: %w", err) } } @@ -250,7 +250,7 @@ func putRawObjectData(tx *bbolt.Tx, obj *objectSDK.Object, bucketName []byte, ad } rawObject, err := obj.CutPayload().Marshal() if err != nil { - return fmt.Errorf("can't marshal object header: %w", err) + return fmt.Errorf("marshal object header: %w", err) } return putUniqueIndexItem(tx, namedBucketItem{ name: bucketName, @@ -475,7 +475,7 @@ func createBucketLikelyExists[T bucketContainer](tx T, name []byte) (*bbolt.Buck func updateUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem, update func(oldData, newData []byte) ([]byte, error)) error { bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { - return fmt.Errorf("can't create index %v: %w", item.name, err) + return fmt.Errorf("create index %v: %w", item.name, err) } data, err := update(bkt.Get(item.key), item.val) @@ -492,12 +492,12 @@ func putUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) error { func putFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { - return fmt.Errorf("can't create index %v: %w", item.name, err) + return fmt.Errorf("create index %v: %w", item.name, err) } fkbtRoot, err := createBucketLikelyExists(bkt, item.key) if err != nil { - return fmt.Errorf("can't create fake bucket tree index %v: %w", item.key, err) + return fmt.Errorf("create fake bucket tree index %v: %w", item.key, err) } return fkbtRoot.Put(item.val, zeroValue) @@ -506,19 +506,19 @@ func putFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { func putListIndexItem(tx *bbolt.Tx, item namedBucketItem) error { bkt, err := createBucketLikelyExists(tx, item.name) if err != nil { - return fmt.Errorf("can't create index %v: %w", item.name, err) + return fmt.Errorf("create index %v: %w", item.name, err) } lst, err := decodeList(bkt.Get(item.key)) if err != nil { - return fmt.Errorf("can't decode leaf list %v: %w", item.key, err) + return fmt.Errorf("decode leaf list %v: %w", item.key, err) } lst = append(lst, item.val) encodedLst, err := encodeList(lst) if err != nil { - return fmt.Errorf("can't encode leaf list %v: %w", item.key, err) + return fmt.Errorf("encode leaf list %v: %w", item.key, err) } return bkt.Put(item.key, encodedLst) diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index f802036be3..9f1b8b0601 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -565,7 +565,7 @@ func groupFilters(filters objectSDK.SearchFilters, useAttributeIndex bool) (filt case v2object.FilterHeaderContainerID: // support deprecated field err := res.cnr.DecodeString(filters[i].Value()) if err != nil { - return filterGroup{}, fmt.Errorf("can't parse container id: %w", err) + return filterGroup{}, fmt.Errorf("parse container id: %w", err) } res.withCnrFilter = true diff --git a/pkg/local_object_storage/metabase/shard_id.go b/pkg/local_object_storage/metabase/shard_id.go index e58115bc82..72618b1a0c 100644 --- a/pkg/local_object_storage/metabase/shard_id.go +++ b/pkg/local_object_storage/metabase/shard_id.go @@ -32,13 +32,13 @@ func (db *DB) GetShardID(ctx context.Context, mode metamode.Mode) ([]byte, error } if err := db.openDB(ctx, mode); err != nil { - return nil, fmt.Errorf("failed to open metabase: %w", err) + return nil, fmt.Errorf("open metabase: %w", err) } id, err := db.readShardID() if cErr := db.close(); cErr != nil { - err = errors.Join(err, fmt.Errorf("failed to close metabase: %w", cErr)) + err = errors.Join(err, fmt.Errorf("close metabase: %w", cErr)) } return id, metaerr.Wrap(err) @@ -70,7 +70,7 @@ func (db *DB) SetShardID(ctx context.Context, id []byte, mode metamode.Mode) err } if err := db.openDB(ctx, mode); err != nil { - return fmt.Errorf("failed to open metabase: %w", err) + return fmt.Errorf("open metabase: %w", err) } err := db.writeShardID(id) @@ -79,7 +79,7 @@ func (db *DB) SetShardID(ctx context.Context, id []byte, mode metamode.Mode) err } if cErr := db.close(); cErr != nil { - err = errors.Join(err, fmt.Errorf("failed to close metabase: %w", cErr)) + err = errors.Join(err, fmt.Errorf("close metabase: %w", cErr)) } return metaerr.Wrap(err) diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index bcf72f4400..6eba58c69f 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -95,7 +95,7 @@ func compactDB(db *bbolt.DB) error { NoSync: true, }) if err != nil { - return fmt.Errorf("can't open new metabase to compact: %w", err) + return fmt.Errorf("open new metabase to compact: %w", err) } if err := bbolt.Compact(dst, db, compactMaxTxSize); err != nil { return fmt.Errorf("compact metabase: %w", errors.Join(err, dst.Close(), os.Remove(tmpFileName))) @@ -292,7 +292,7 @@ func iterateExpirationAttributeKeyBucket(ctx context.Context, b *bbolt.Bucket, i } expirationEpoch, err := strconv.ParseUint(string(attrValue), 10, 64) if err != nil { - return fmt.Errorf("could not parse expiration epoch: %w", err) + return fmt.Errorf("parse expiration epoch: %w", err) } expirationEpochBucket := b.Bucket(attrValue) attrKeyValueC := expirationEpochBucket.Cursor() @@ -399,7 +399,7 @@ func selectUserAttributeKeysToDrop(keys [][]byte, cs container.InfoProvider) ([] for _, key := range keys { attr, ok := attributeFromAttributeBucket(key) if !ok { - return nil, fmt.Errorf("failed to parse attribute key from user attribute bucket key %s", hex.EncodeToString(key)) + return nil, fmt.Errorf("parse attribute key from user attribute bucket key %s", hex.EncodeToString(key)) } if !IsAtrributeIndexed(attr) { keysToDrop = append(keysToDrop, key) @@ -407,7 +407,7 @@ func selectUserAttributeKeysToDrop(keys [][]byte, cs container.InfoProvider) ([] } contID, ok := cidFromAttributeBucket(key) if !ok { - return nil, fmt.Errorf("failed to parse container ID from user attribute bucket key %s", hex.EncodeToString(key)) + return nil, fmt.Errorf("parse container ID from user attribute bucket key %s", hex.EncodeToString(key)) } info, err := cs.Info(contID) if err != nil { diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index 0a2f91a476..80851f1c43 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -231,11 +231,11 @@ func parseExpirationEpochKey(key []byte) (uint64, cid.ID, oid.ID, error) { epoch := binary.BigEndian.Uint64(key) var cnr cid.ID if err := cnr.Decode(key[epochSize : epochSize+cidSize]); err != nil { - return 0, cid.ID{}, oid.ID{}, fmt.Errorf("failed to decode expiration epoch to object key (container ID): %w", err) + return 0, cid.ID{}, oid.ID{}, fmt.Errorf("decode expiration epoch to object key (container ID): %w", err) } var obj oid.ID if err := obj.Decode(key[epochSize+cidSize:]); err != nil { - return 0, cid.ID{}, oid.ID{}, fmt.Errorf("failed to decode expiration epoch to object key (object ID): %w", err) + return 0, cid.ID{}, oid.ID{}, fmt.Errorf("decode expiration epoch to object key (object ID): %w", err) } return epoch, cnr, obj, nil } diff --git a/pkg/local_object_storage/metabase/version.go b/pkg/local_object_storage/metabase/version.go index 048bb9af64..fbc0f1ad9d 100644 --- a/pkg/local_object_storage/metabase/version.go +++ b/pkg/local_object_storage/metabase/version.go @@ -67,7 +67,7 @@ func updateVersion(tx *bbolt.Tx, version uint64) error { b, err := tx.CreateBucketIfNotExists(shardInfoBucket) if err != nil { - return fmt.Errorf("can't create auxiliary bucket: %w", err) + return fmt.Errorf("create auxiliary bucket: %w", err) } return b.Put(versionKey, data) } diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 6e68e9986a..fecf96f664 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -106,7 +106,7 @@ func (t *boltForest) SetMode(ctx context.Context, m mode.Mode) error { } } if err != nil { - return fmt.Errorf("can't set pilorama mode (old=%s, new=%s): %w", t.mode, m, err) + return fmt.Errorf("set pilorama mode (old=%s, new=%s): %w", t.mode, m, err) } t.mode = m @@ -128,7 +128,7 @@ func (t *boltForest) openBolt(m mode.Mode) error { readOnly := m.ReadOnly() err := util.MkdirAllX(filepath.Dir(t.path), t.perm) if err != nil { - return metaerr.Wrap(fmt.Errorf("can't create dir %s for the pilorama: %w", t.path, err)) + return metaerr.Wrap(fmt.Errorf("create dir %s for the pilorama: %w", t.path, err)) } opts := *bbolt.DefaultOptions @@ -139,7 +139,7 @@ func (t *boltForest) openBolt(m mode.Mode) error { t.db, err = bbolt.Open(t.path, t.perm, &opts) if err != nil { - return metaerr.Wrap(fmt.Errorf("can't open the pilorama DB: %w", err)) + return metaerr.Wrap(fmt.Errorf("open the pilorama DB: %w", err)) } t.db.MaxBatchSize = t.maxBatchSize @@ -1360,7 +1360,7 @@ func (t *boltForest) TreeList(ctx context.Context, cid cidSDK.ID) ([]string, err return nil }) if err != nil { - return nil, metaerr.Wrap(fmt.Errorf("could not list trees: %w", err)) + return nil, metaerr.Wrap(fmt.Errorf("list trees: %w", err)) } success = true return ids, nil @@ -1504,7 +1504,7 @@ func (t *boltForest) TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (* var contID cidSDK.ID if err := contID.Decode(k[:32]); err != nil { - return fmt.Errorf("failed to decode containerID: %w", err) + return fmt.Errorf("decode containerID: %w", err) } res.Items = append(res.Items, ContainerIDTreeID{ CID: contID, diff --git a/pkg/local_object_storage/shard/container.go b/pkg/local_object_storage/shard/container.go index 364649b50c..0309f0c81b 100644 --- a/pkg/local_object_storage/shard/container.go +++ b/pkg/local_object_storage/shard/container.go @@ -36,7 +36,7 @@ func (s *Shard) ContainerSize(prm ContainerSizePrm) (ContainerSizeRes, error) { size, err := s.metaBase.ContainerSize(prm.cnr) if err != nil { - return ContainerSizeRes{}, fmt.Errorf("could not get container size: %w", err) + return ContainerSizeRes{}, fmt.Errorf("get container size: %w", err) } return ContainerSizeRes{ @@ -71,7 +71,7 @@ func (s *Shard) ContainerCount(ctx context.Context, prm ContainerCountPrm) (Cont counters, err := s.metaBase.ContainerCount(ctx, prm.ContainerID) if err != nil { - return ContainerCountRes{}, fmt.Errorf("could not get container counters: %w", err) + return ContainerCountRes{}, fmt.Errorf("get container counters: %w", err) } return ContainerCountRes{ diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 78ce241fec..1c1933af53 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -38,7 +38,7 @@ func (s *Shard) handleMetabaseFailure(ctx context.Context, stage string, err err err = s.SetMode(ctx, mode.DegradedReadOnly) if err != nil { - return fmt.Errorf("could not switch to mode %s", mode.Mode(mode.DegradedReadOnly)) + return fmt.Errorf("switch to mode %s", mode.Mode(mode.DegradedReadOnly)) } return nil } @@ -72,7 +72,7 @@ func (s *Shard) Open(ctx context.Context) error { for j := i + 1; j < len(components); j++ { if err := components[j].Open(ctx, m); err != nil { // Other components must be opened, fail. - return fmt.Errorf("could not open %T: %w", components[j], err) + return fmt.Errorf("open %T: %w", components[j], err) } } err = s.handleMetabaseFailure(ctx, "open", err) @@ -83,7 +83,7 @@ func (s *Shard) Open(ctx context.Context) error { break } - return fmt.Errorf("could not open %T: %w", component, err) + return fmt.Errorf("open %T: %w", component, err) } } return nil @@ -184,7 +184,7 @@ func (s *Shard) initializeComponents(ctx context.Context, m mode.Mode) error { break } - return fmt.Errorf("could not initialize %T: %w", component, err) + return fmt.Errorf("initialize %T: %w", component, err) } } return nil @@ -205,7 +205,7 @@ func (s *Shard) refillMetabase(ctx context.Context) error { err := s.metaBase.Reset() if err != nil { - return fmt.Errorf("could not reset metabase: %w", err) + return fmt.Errorf("reset metabase: %w", err) } withCount := true @@ -254,12 +254,12 @@ func (s *Shard) refillMetabase(ctx context.Context) error { err = errors.Join(egErr, itErr) if err != nil { - return fmt.Errorf("could not put objects to the meta: %w", err) + return fmt.Errorf("put objects to the meta: %w", err) } err = s.metaBase.SyncCounters() if err != nil { - return fmt.Errorf("could not sync object counters: %w", err) + return fmt.Errorf("sync object counters: %w", err) } success = true @@ -318,7 +318,7 @@ func (s *Shard) refillObject(ctx context.Context, data []byte, addr oid.Address, func (s *Shard) refillLockObject(ctx context.Context, obj *objectSDK.Object) error { var lock objectSDK.Lock if err := lock.Unmarshal(obj.Payload()); err != nil { - return fmt.Errorf("could not unmarshal lock content: %w", err) + return fmt.Errorf("unmarshal lock content: %w", err) } locked := make([]oid.ID, lock.NumberOfMembers()) @@ -328,7 +328,7 @@ func (s *Shard) refillLockObject(ctx context.Context, obj *objectSDK.Object) err id, _ := obj.ID() err := s.metaBase.Lock(ctx, cnr, id, locked) if err != nil { - return fmt.Errorf("could not lock objects: %w", err) + return fmt.Errorf("lock objects: %w", err) } return nil } @@ -337,7 +337,7 @@ func (s *Shard) refillTombstoneObject(ctx context.Context, obj *objectSDK.Object tombstone := objectSDK.NewTombstone() if err := tombstone.Unmarshal(obj.Payload()); err != nil { - return fmt.Errorf("could not unmarshal tombstone content: %w", err) + return fmt.Errorf("unmarshal tombstone content: %w", err) } tombAddr := object.AddressOf(obj) @@ -358,7 +358,7 @@ func (s *Shard) refillTombstoneObject(ctx context.Context, obj *objectSDK.Object _, err := s.metaBase.Inhume(ctx, inhumePrm) if err != nil { - return fmt.Errorf("could not inhume objects: %w", err) + return fmt.Errorf("inhume objects: %w", err) } return nil } diff --git a/pkg/local_object_storage/shard/get.go b/pkg/local_object_storage/shard/get.go index 7a31a705ef..15d1eb6bac 100644 --- a/pkg/local_object_storage/shard/get.go +++ b/pkg/local_object_storage/shard/get.go @@ -175,7 +175,7 @@ func (s *Shard) fetchObjectData(ctx context.Context, addr oid.Address, skipMeta mExRes, err := s.metaBase.StorageID(ctx, mPrm) if err != nil { - return nil, true, fmt.Errorf("can't fetch blobovnicza id from metabase: %w", err) + return nil, true, fmt.Errorf("fetch blobovnicza id from metabase: %w", err) } storageID := mExRes.StorageID() diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index 6ccae3f535..26492cf01e 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -36,7 +36,7 @@ func (s *Shard) UpdateID(ctx context.Context) (err error) { modeDegraded := s.GetMode().NoMetabase() if !modeDegraded { if idFromMetabase, err = s.metaBase.GetShardID(ctx, mode.ReadOnly); err != nil { - err = fmt.Errorf("failed to read shard id from metabase: %w", err) + err = fmt.Errorf("read shard id from metabase: %w", err) } } @@ -64,7 +64,7 @@ func (s *Shard) UpdateID(ctx context.Context) (err error) { if len(idFromMetabase) == 0 && !modeDegraded { if setErr := s.metaBase.SetShardID(ctx, *s.info.ID, s.GetMode()); setErr != nil { - err = errors.Join(err, fmt.Errorf("failed to write shard id to metabase: %w", setErr)) + err = errors.Join(err, fmt.Errorf("write shard id to metabase: %w", setErr)) } } return diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index f583ef5d93..c5275dafd9 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -109,7 +109,7 @@ func (s *Shard) List(ctx context.Context) (res SelectRes, err error) { lst, err := s.metaBase.Containers(ctx) if err != nil { - return res, fmt.Errorf("can't list stored containers: %w", err) + return res, fmt.Errorf("list stored containers: %w", err) } filters := objectSDK.NewSearchFilters() @@ -149,7 +149,7 @@ func (s *Shard) ListContainers(ctx context.Context, _ ListContainersPrm) (ListCo containers, err := s.metaBase.Containers(ctx) if err != nil { - return ListContainersRes{}, fmt.Errorf("could not get list of containers: %w", err) + return ListContainersRes{}, fmt.Errorf("get list of containers: %w", err) } return ListContainersRes{ @@ -180,7 +180,7 @@ func (s *Shard) ListWithCursor(ctx context.Context, prm ListWithCursorPrm) (List metaPrm.SetCursor(prm.cursor) res, err := s.metaBase.ListWithCursor(ctx, metaPrm) if err != nil { - return ListWithCursorRes{}, fmt.Errorf("could not get list of objects: %w", err) + return ListWithCursorRes{}, fmt.Errorf("get list of objects: %w", err) } return ListWithCursorRes{ @@ -208,7 +208,7 @@ func (s *Shard) IterateOverContainers(ctx context.Context, prm IterateOverContai metaPrm.Handler = prm.Handler err := s.metaBase.IterateOverContainers(ctx, metaPrm) if err != nil { - return fmt.Errorf("could not iterate over containers: %w", err) + return fmt.Errorf("iterate over containers: %w", err) } return nil @@ -235,7 +235,7 @@ func (s *Shard) IterateOverObjectsInContainer(ctx context.Context, prm IterateOv metaPrm.Handler = prm.Handler err := s.metaBase.IterateOverObjectsInContainer(ctx, metaPrm) if err != nil { - return fmt.Errorf("could not iterate over objects: %w", err) + return fmt.Errorf("iterate over objects: %w", err) } return nil @@ -258,7 +258,7 @@ func (s *Shard) CountAliveObjectsInContainer(ctx context.Context, prm CountAlive metaPrm.ContainerID = prm.ContainerID count, err := s.metaBase.CountAliveObjectsInContainer(ctx, metaPrm) if err != nil { - return 0, fmt.Errorf("could not count alive objects in bucket: %w", err) + return 0, fmt.Errorf("count alive objects in bucket: %w", err) } return count, nil diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index 1e4643db53..3f23111aff 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -81,7 +81,7 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { res, err = s.blobStor.Put(ctx, putPrm) if err != nil { - return PutRes{}, fmt.Errorf("could not put object to BLOB storage: %w", err) + return PutRes{}, fmt.Errorf("put object to BLOB storage: %w", err) } } @@ -94,7 +94,7 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { if err != nil { // may we need to handle this case in a special way // since the object has been successfully written to BlobStor - return PutRes{}, fmt.Errorf("could not put object to metabase: %w", err) + return PutRes{}, fmt.Errorf("put object to metabase: %w", err) } if res.Inserted { diff --git a/pkg/local_object_storage/shard/select.go b/pkg/local_object_storage/shard/select.go index 184ca9b712..c7c7e11c2e 100644 --- a/pkg/local_object_storage/shard/select.go +++ b/pkg/local_object_storage/shard/select.go @@ -67,7 +67,7 @@ func (s *Shard) Select(ctx context.Context, prm SelectPrm) (SelectRes, error) { mRes, err := s.metaBase.Select(ctx, selectPrm) if err != nil { - return SelectRes{}, fmt.Errorf("could not select objects from metabase: %w", err) + return SelectRes{}, fmt.Errorf("select objects from metabase: %w", err) } return SelectRes{ diff --git a/pkg/local_object_storage/writecache/iterate.go b/pkg/local_object_storage/writecache/iterate.go index 9ec039f914..e369fbd505 100644 --- a/pkg/local_object_storage/writecache/iterate.go +++ b/pkg/local_object_storage/writecache/iterate.go @@ -30,7 +30,7 @@ func IterateDB(db *bbolt.DB, f func(oid.Address) error) error { return b.ForEach(func(k, _ []byte) error { err := addr.DecodeString(string(k)) if err != nil { - return fmt.Errorf("could not parse object address: %w", err) + return fmt.Errorf("parse object address: %w", err) } return f(addr) diff --git a/pkg/local_object_storage/writecache/mode.go b/pkg/local_object_storage/writecache/mode.go index 73d12fd33f..c491be60b1 100644 --- a/pkg/local_object_storage/writecache/mode.go +++ b/pkg/local_object_storage/writecache/mode.go @@ -83,7 +83,7 @@ func (c *cache) closeStorage(ctx context.Context, shrink bool) error { } if !shrink { if err := c.fsTree.Close(ctx); err != nil { - return fmt.Errorf("can't close write-cache storage: %w", err) + return fmt.Errorf("close write-cache storage: %w", err) } return nil } @@ -98,16 +98,16 @@ func (c *cache) closeStorage(ctx context.Context, shrink bool) error { if errors.Is(err, errIterationCompleted) { empty = false } else { - return fmt.Errorf("failed to check write-cache items: %w", err) + return fmt.Errorf("check write-cache items: %w", err) } } if err := c.fsTree.Close(ctx); err != nil { - return fmt.Errorf("can't close write-cache storage: %w", err) + return fmt.Errorf("close write-cache storage: %w", err) } if empty { err := os.RemoveAll(c.path) if err != nil && !os.IsNotExist(err) { - return fmt.Errorf("failed to remove write-cache files: %w", err) + return fmt.Errorf("remove write-cache files: %w", err) } } else { c.log.Info(ctx, logs.WritecacheShrinkSkippedNotEmpty) diff --git a/pkg/local_object_storage/writecache/storage.go b/pkg/local_object_storage/writecache/storage.go index a0e236cb73..e88566cdfc 100644 --- a/pkg/local_object_storage/writecache/storage.go +++ b/pkg/local_object_storage/writecache/storage.go @@ -31,10 +31,10 @@ func (c *cache) openStore(mod mode.ComponentMode) error { fstree.WithFileCounter(c.counter), ) if err := c.fsTree.Open(mod); err != nil { - return fmt.Errorf("could not open FSTree: %w", err) + return fmt.Errorf("open FSTree: %w", err) } if err := c.fsTree.Init(); err != nil { - return fmt.Errorf("could not init FSTree: %w", err) + return fmt.Errorf("init FSTree: %w", err) } return nil diff --git a/pkg/local_object_storage/writecache/upgrade.go b/pkg/local_object_storage/writecache/upgrade.go index 3a100f1a31..5eb341ba45 100644 --- a/pkg/local_object_storage/writecache/upgrade.go +++ b/pkg/local_object_storage/writecache/upgrade.go @@ -25,11 +25,11 @@ func (c *cache) flushAndDropBBoltDB(ctx context.Context) error { return nil } if err != nil { - return fmt.Errorf("could not check write-cache database existence: %w", err) + return fmt.Errorf("check write-cache database existence: %w", err) } db, err := OpenDB(c.path, true, os.OpenFile) if err != nil { - return fmt.Errorf("could not open write-cache database: %w", err) + return fmt.Errorf("open write-cache database: %w", err) } defer func() { _ = db.Close() From 226dd25dd0f464f440248d0d4c7180db0ca4be56 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 18 Dec 2024 09:40:19 +0300 Subject: [PATCH 1105/1413] [#1568] pilorama: Replace "containerID" with "container ID" in the error message It is "container ID" in every other place. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/boltdb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index fecf96f664..86b19e3afe 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1504,7 +1504,7 @@ func (t *boltForest) TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (* var contID cidSDK.ID if err := contID.Decode(k[:32]); err != nil { - return fmt.Errorf("decode containerID: %w", err) + return fmt.Errorf("decode container ID: %w", err) } res.Items = append(res.Items, ContainerIDTreeID{ CID: contID, From 51ee132ea311b6227d1f0642ab736b5b8e21a0f7 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 18 Dec 2024 19:27:14 +0300 Subject: [PATCH 1106/1413] [#1342] network/cache: Add node address to error multiClient Signed-off-by: Alexander Chuprov --- pkg/network/cache/multi.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 481d1ea4ad..1bcb832590 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -155,7 +155,7 @@ func (x *multiClient) iterateClients(ctx context.Context, f func(clientcore.Clie group.IterateAddresses(func(addr network.Address) bool { select { case <-ctx.Done(): - firstErr = context.Canceled + firstErr = fmt.Errorf("try %v: %w", addr, context.Canceled) return true default: } From 148d68933bb1f3fda17db2c7f4fe073336554f67 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 19 Dec 2024 16:07:22 +0300 Subject: [PATCH 1107/1413] [#1573] node: Simplify bootstrapWithState() After #1382 we have no need to use lambdas. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config.go | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 40be8f45fc..18d3e24541 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1220,9 +1220,9 @@ func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) { // bootstrapWithState calls "addPeer" method of the Sidechain Netmap contract // with the binary-encoded information from the current node's configuration. // The state is set using the provided setter which MUST NOT be nil. -func (c *cfg) bootstrapWithState(ctx context.Context, stateSetter func(*netmap.NodeInfo)) error { +func (c *cfg) bootstrapWithState(ctx context.Context, state netmap.NodeState) error { ni := c.cfgNodeInfo.localInfo - stateSetter(&ni) + ni.SetStatus(state) prm := nmClient.AddPeerPrm{} prm.SetNodeInfo(ni) @@ -1232,9 +1232,7 @@ func (c *cfg) bootstrapWithState(ctx context.Context, stateSetter func(*netmap.N // bootstrapOnline calls cfg.bootstrapWithState with "online" state. func bootstrapOnline(ctx context.Context, c *cfg) error { - return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) { - ni.SetStatus(netmap.Online) - }) + return c.bootstrapWithState(ctx, netmap.Online) } // bootstrap calls bootstrapWithState with: @@ -1245,9 +1243,7 @@ func (c *cfg) bootstrap(ctx context.Context) error { st := c.cfgNetmap.state.controlNetmapStatus() if st == control.NetmapStatus_MAINTENANCE { c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithTheMaintenanceState) - return c.bootstrapWithState(ctx, func(ni *netmap.NodeInfo) { - ni.SetStatus(netmap.Maintenance) - }) + return c.bootstrapWithState(ctx, netmap.Maintenance) } c.log.Info(ctx, logs.FrostFSNodeBootstrappingWithOnlineState, From db03742d332681ab3d4626d50e85f5da6c482629 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 20 Dec 2024 15:04:17 +0300 Subject: [PATCH 1108/1413] [#1578] adm: Reword help message for `morph refill-gas` Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/generate/generate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go index 7af7767975..37c5d4a4a6 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -159,7 +159,7 @@ func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error } } else { if storageWalletPath == "" { - return fmt.Errorf("missing wallet path (use '--%s ')", commonflags.StorageWalletFlag) + return fmt.Errorf("missing wallet path (use '--%s ')", commonflags.StorageWalletFlag) } var w *wallet.Wallet From bb9ba1bce2101e44999aeae10815688aec8d7a01 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 23 Dec 2024 09:55:09 +0300 Subject: [PATCH 1109/1413] [#1578] adm: Remove bool flag from refillGas() Signed-off-by: Evgenii Stratonikov --- .../modules/morph/generate/generate.go | 74 ++++++------------- .../internal/modules/morph/generate/root.go | 32 +++++++- 2 files changed, 52 insertions(+), 54 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go index 37c5d4a4a6..388d5c0605 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -12,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -141,60 +140,29 @@ func addMultisigAccount(w *wallet.Wallet, m int, name, password string, pubs key } func generateStorageCreds(cmd *cobra.Command, _ []string) error { - return refillGas(cmd, storageGasConfigFlag, true) -} - -func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) (err error) { - // storage wallet path is not part of the config - storageWalletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag) - // wallet address is not part of the config - walletAddress, _ := cmd.Flags().GetString(walletAddressFlag) - - var gasReceiver util.Uint160 - - if len(walletAddress) != 0 { - gasReceiver, err = address.StringToUint160(walletAddress) - if err != nil { - return fmt.Errorf("invalid wallet address %s: %w", walletAddress, err) - } - } else { - if storageWalletPath == "" { - return fmt.Errorf("missing wallet path (use '--%s ')", commonflags.StorageWalletFlag) - } - - var w *wallet.Wallet - - if createWallet { - w, err = wallet.NewWallet(storageWalletPath) - } else { - w, err = wallet.NewWalletFromFile(storageWalletPath) - } - - if err != nil { - return fmt.Errorf("can't create wallet: %w", err) - } - - if createWallet { - var password string - - label, _ := cmd.Flags().GetString(storageWalletLabelFlag) - password, err := config.GetStoragePassword(viper.GetViper(), label) - if err != nil { - return fmt.Errorf("can't fetch password: %w", err) - } - - if label == "" { - label = constants.SingleAccountName - } - - if err := w.CreateAccount(label, password); err != nil { - return fmt.Errorf("can't create account: %w", err) - } - } - - gasReceiver = w.Accounts[0].Contract.ScriptHash() + walletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag) + w, err := wallet.NewWallet(walletPath) + if err != nil { + return fmt.Errorf("create wallet: %w", err) } + label, _ := cmd.Flags().GetString(storageWalletLabelFlag) + password, err := config.GetStoragePassword(viper.GetViper(), label) + if err != nil { + return fmt.Errorf("can't fetch password: %w", err) + } + + if label == "" { + label = constants.SingleAccountName + } + + if err := w.CreateAccount(label, password); err != nil { + return fmt.Errorf("can't create account: %w", err) + } + return refillGas(cmd, storageGasConfigFlag, w.Accounts[0].ScriptHash()) +} + +func refillGas(cmd *cobra.Command, gasFlag string, gasReceiver util.Uint160) (err error) { gasStr := viper.GetString(gasFlag) gasAmount, err := helper.ParseGASAmount(gasStr) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/root.go b/cmd/frostfs-adm/internal/modules/morph/generate/root.go index 3633d9a8ee..da9665d227 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/root.go @@ -1,7 +1,12 @@ package generate import ( + "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "github.com/nspcc-dev/neo-go/pkg/encoding/address" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -33,7 +38,32 @@ var ( _ = viper.BindPFlag(commonflags.RefillGasAmountFlag, cmd.Flags().Lookup(commonflags.RefillGasAmountFlag)) }, RunE: func(cmd *cobra.Command, _ []string) error { - return refillGas(cmd, commonflags.RefillGasAmountFlag, false) + // storage wallet path is not part of the config + storageWalletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag) + // wallet address is not part of the config + walletAddress, _ := cmd.Flags().GetString(walletAddressFlag) + + var gasReceiver util.Uint160 + + if len(walletAddress) != 0 { + var err error + gasReceiver, err = address.StringToUint160(walletAddress) + if err != nil { + return fmt.Errorf("invalid wallet address %s: %w", walletAddress, err) + } + } else { + if storageWalletPath == "" { + return fmt.Errorf("missing wallet path (use '--%s ')", commonflags.StorageWalletFlag) + } + + w, err := wallet.NewWalletFromFile(storageWalletPath) + if err != nil { + return fmt.Errorf("can't create wallet: %w", err) + } + + gasReceiver = w.Accounts[0].Contract.ScriptHash() + } + return refillGas(cmd, commonflags.RefillGasAmountFlag, gasReceiver) }, } GenerateAlphabetCmd = &cobra.Command{ From 303cd35a019f110f1f47d264ac30827977643b91 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 23 Dec 2024 09:55:54 +0300 Subject: [PATCH 1110/1413] [#1578] adm: Remove unnecessary comments in RefillGasCmd Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/generate/root.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/root.go b/cmd/frostfs-adm/internal/modules/morph/generate/root.go index da9665d227..bdf4dc3d82 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/root.go @@ -38,9 +38,7 @@ var ( _ = viper.BindPFlag(commonflags.RefillGasAmountFlag, cmd.Flags().Lookup(commonflags.RefillGasAmountFlag)) }, RunE: func(cmd *cobra.Command, _ []string) error { - // storage wallet path is not part of the config storageWalletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag) - // wallet address is not part of the config walletAddress, _ := cmd.Flags().GetString(walletAddressFlag) var gasReceiver util.Uint160 From e64871c3fdcd1180b673ac7eb96e2ff6dffe6b87 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 23 Dec 2024 10:20:26 +0300 Subject: [PATCH 1111/1413] [#1578] adm: Allow to transfer GAS to multiple recepients Signed-off-by: Evgenii Stratonikov --- .../modules/morph/generate/generate.go | 10 ++++--- .../internal/modules/morph/generate/root.go | 29 +++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go index 388d5c0605..78f8617f13 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/generate.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/generate.go @@ -162,7 +162,7 @@ func generateStorageCreds(cmd *cobra.Command, _ []string) error { return refillGas(cmd, storageGasConfigFlag, w.Accounts[0].ScriptHash()) } -func refillGas(cmd *cobra.Command, gasFlag string, gasReceiver util.Uint160) (err error) { +func refillGas(cmd *cobra.Command, gasFlag string, gasReceivers ...util.Uint160) (err error) { gasStr := viper.GetString(gasFlag) gasAmount, err := helper.ParseGASAmount(gasStr) @@ -176,9 +176,11 @@ func refillGas(cmd *cobra.Command, gasFlag string, gasReceiver util.Uint160) (er } bw := io.NewBufBinWriter() - emit.AppCall(bw.BinWriter, gas.Hash, "transfer", callflag.All, - wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil) - emit.Opcodes(bw.BinWriter, opcode.ASSERT) + for _, gasReceiver := range gasReceivers { + emit.AppCall(bw.BinWriter, gas.Hash, "transfer", callflag.All, + wCtx.CommitteeAcc.Contract.ScriptHash(), gasReceiver, int64(gasAmount), nil) + emit.Opcodes(bw.BinWriter, opcode.ASSERT) + } if bw.Err != nil { return fmt.Errorf("BUG: invalid transfer arguments: %w", bw.Err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/generate/root.go b/cmd/frostfs-adm/internal/modules/morph/generate/root.go index bdf4dc3d82..73c9867133 100644 --- a/cmd/frostfs-adm/internal/modules/morph/generate/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/generate/root.go @@ -38,30 +38,27 @@ var ( _ = viper.BindPFlag(commonflags.RefillGasAmountFlag, cmd.Flags().Lookup(commonflags.RefillGasAmountFlag)) }, RunE: func(cmd *cobra.Command, _ []string) error { - storageWalletPath, _ := cmd.Flags().GetString(commonflags.StorageWalletFlag) - walletAddress, _ := cmd.Flags().GetString(walletAddressFlag) + storageWalletPaths, _ := cmd.Flags().GetStringArray(commonflags.StorageWalletFlag) + walletAddresses, _ := cmd.Flags().GetStringArray(walletAddressFlag) - var gasReceiver util.Uint160 - - if len(walletAddress) != 0 { - var err error - gasReceiver, err = address.StringToUint160(walletAddress) + var gasReceivers []util.Uint160 + for _, walletAddress := range walletAddresses { + addr, err := address.StringToUint160(walletAddress) if err != nil { return fmt.Errorf("invalid wallet address %s: %w", walletAddress, err) } - } else { - if storageWalletPath == "" { - return fmt.Errorf("missing wallet path (use '--%s ')", commonflags.StorageWalletFlag) - } + gasReceivers = append(gasReceivers, addr) + } + for _, storageWalletPath := range storageWalletPaths { w, err := wallet.NewWalletFromFile(storageWalletPath) if err != nil { return fmt.Errorf("can't create wallet: %w", err) } - gasReceiver = w.Accounts[0].Contract.ScriptHash() + gasReceivers = append(gasReceivers, w.Accounts[0].Contract.ScriptHash()) } - return refillGas(cmd, commonflags.RefillGasAmountFlag, gasReceiver) + return refillGas(cmd, commonflags.RefillGasAmountFlag, gasReceivers...) }, } GenerateAlphabetCmd = &cobra.Command{ @@ -78,10 +75,10 @@ var ( func initRefillGasCmd() { RefillGasCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) RefillGasCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - RefillGasCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet") - RefillGasCmd.Flags().String(walletAddressFlag, "", "Address of wallet") + RefillGasCmd.Flags().StringArray(commonflags.StorageWalletFlag, nil, "Path to storage node wallet") + RefillGasCmd.Flags().StringArray(walletAddressFlag, nil, "Address of wallet") RefillGasCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Additional amount of GAS to transfer") - RefillGasCmd.MarkFlagsMutuallyExclusive(walletAddressFlag, commonflags.StorageWalletFlag) + RefillGasCmd.MarkFlagsOneRequired(walletAddressFlag, commonflags.StorageWalletFlag) } func initGenerateStorageCmd() { From 7c3bcb0f44cca381ae9c430d032f685265ed6938 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 23 Dec 2024 10:22:09 +0300 Subject: [PATCH 1112/1413] [#1578] Makefile: Refill GAS with a single command in env-up Signed-off-by: Evgenii Stratonikov --- Makefile | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index ecac760e97..f0cdc273c3 100755 --- a/Makefile +++ b/Makefile @@ -270,10 +270,12 @@ env-up: all echo "Frostfs contracts not found"; exit 1; \ fi ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph init --contracts ${FROSTFS_CONTRACTS_PATH} - ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet01.json --gas 10.0 - ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet02.json --gas 10.0 - ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet03.json --gas 10.0 - ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --storage-wallet ./dev/storage/wallet04.json --gas 10.0 + ${BIN}/frostfs-adm --config ./dev/adm/frostfs-adm.yml morph refill-gas --gas 10.0 \ + --storage-wallet ./dev/storage/wallet01.json \ + --storage-wallet ./dev/storage/wallet02.json \ + --storage-wallet ./dev/storage/wallet03.json \ + --storage-wallet ./dev/storage/wallet04.json + @if [ ! -f "$(LOCODE_DB_PATH)" ]; then \ make locode-download; \ fi From 2832f4443750fb11ee827be5491f34f749c9122a Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 20 Dec 2024 12:30:06 +0300 Subject: [PATCH 1113/1413] [#1531] metrics: Rename `app_info` metric Signed-off-by: Ekaterina Lebedeva --- internal/metrics/application.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/metrics/application.go b/internal/metrics/application.go index 8bc408ab65..53acf9b7f7 100644 --- a/internal/metrics/application.go +++ b/internal/metrics/application.go @@ -12,8 +12,9 @@ type ApplicationInfo struct { func NewApplicationInfo(version string) *ApplicationInfo { appInfo := &ApplicationInfo{ versionValue: metrics.NewGaugeVec(prometheus.GaugeOpts{ - Name: "app_info", - Help: "General information about the application.", + Namespace: namespace, + Name: "app_info", + Help: "General information about the application.", }, []string{"version"}), } appInfo.versionValue.With(prometheus.Labels{"version": version}) From b5b4f78b4925f71e6a774a4b0b7753a6c3833cbe Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Dec 2024 14:14:57 +0300 Subject: [PATCH 1114/1413] [#1582] adm: Allow using the default account in `deposit-notary` It has never worked, actually. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/notary/notary.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go index fd42d5a4a9..6e159f11e5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go @@ -41,7 +41,8 @@ func depositNotary(cmd *cobra.Command, _ []string) error { } accHash := w.GetChangeAddress() - if addr, err := cmd.Flags().GetString(walletAccountFlag); err == nil { + addr, _ := cmd.Flags().GetString(walletAccountFlag) + if addr != "" { accHash, err = address.StringToUint160(addr) if err != nil { return fmt.Errorf("invalid address: %s", addr) From 31d3d299bfd03b9de5b3d3f7e973ea6e3718f98a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Dec 2024 14:17:28 +0300 Subject: [PATCH 1115/1413] [#1582] adm: Unify promps for reading a password Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/notary/notary.go | 2 +- cmd/frostfs-adm/internal/modules/storagecfg/root.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go index 6e159f11e5..7058818c03 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go @@ -54,7 +54,7 @@ func depositNotary(cmd *cobra.Command, _ []string) error { return fmt.Errorf("can't find account for %s", accHash) } - prompt := fmt.Sprintf("Enter password for %s >", address.Uint160ToString(accHash)) + prompt := fmt.Sprintf("Enter password for %s > ", address.Uint160ToString(accHash)) pass, err := input.ReadPassword(prompt) if err != nil { return fmt.Errorf("can't get password: %v", err) diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/root.go b/cmd/frostfs-adm/internal/modules/storagecfg/root.go index 127272da59..8e6a8354eb 100644 --- a/cmd/frostfs-adm/internal/modules/storagecfg/root.go +++ b/cmd/frostfs-adm/internal/modules/storagecfg/root.go @@ -105,7 +105,7 @@ func storageConfig(cmd *cobra.Command, args []string) { fatalOnErr(errors.New("can't find account in wallet")) } - c.Wallet.Password, err = input.ReadPassword(fmt.Sprintf("Account password for %s: ", c.Wallet.Account)) + c.Wallet.Password, err = input.ReadPassword(fmt.Sprintf("Enter password for %s > ", c.Wallet.Account)) fatalOnErr(err) err = acc.Decrypt(c.Wallet.Password, keys.NEP2ScryptParams()) From ea868e09f84e0be28acb6c403006900f68ad8bf0 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Dec 2024 14:21:36 +0300 Subject: [PATCH 1116/1413] [#1582] adm: Use int64 type and the default value for `--till` flag Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/notary/notary.go | 14 +++----------- .../internal/modules/morph/notary/root.go | 2 +- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go index 7058818c03..3435926c00 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/notary.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/notary.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "math/big" - "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" @@ -74,16 +73,9 @@ func depositNotary(cmd *cobra.Command, _ []string) error { return err } - till := int64(defaultNotaryDepositLifetime) - tillStr, err := cmd.Flags().GetString(notaryDepositTillFlag) - if err != nil { - return err - } - if tillStr != "" { - till, err = strconv.ParseInt(tillStr, 10, 64) - if err != nil || till <= 0 { - return errInvalidNotaryDepositLifetime - } + till, _ := cmd.Flags().GetInt64(notaryDepositTillFlag) + if till <= 0 { + return errInvalidNotaryDepositLifetime } return transferGas(cmd, acc, accHash, gasAmount, till) diff --git a/cmd/frostfs-adm/internal/modules/morph/notary/root.go b/cmd/frostfs-adm/internal/modules/morph/notary/root.go index 497ff8ea1d..d7be2e5038 100644 --- a/cmd/frostfs-adm/internal/modules/morph/notary/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/notary/root.go @@ -20,7 +20,7 @@ func initDepositoryNotaryCmd() { DepositCmd.Flags().String(commonflags.StorageWalletFlag, "", "Path to storage node wallet") DepositCmd.Flags().String(walletAccountFlag, "", "Wallet account address") DepositCmd.Flags().String(commonflags.RefillGasAmountFlag, "", "Amount of GAS to deposit") - DepositCmd.Flags().String(notaryDepositTillFlag, "", "Notary deposit duration in blocks") + DepositCmd.Flags().Int64(notaryDepositTillFlag, defaultNotaryDepositLifetime, "Notary deposit duration in blocks") } func init() { From f6c5222952ebce32569b4ff3801943895b56258f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Dec 2024 12:15:56 +0300 Subject: [PATCH 1117/1413] [#1581] services/session: Use user.ID.EncodeToString() where possible gopatch: ``` @@ var id expression @@ -base58.Encode(id.WalletBytes()) +id.EncodeToString() ``` Signed-off-by: Evgenii Stratonikov --- pkg/services/session/storage/temporary/executor.go | 2 +- pkg/services/session/storage/temporary/storage.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/services/session/storage/temporary/executor.go b/pkg/services/session/storage/temporary/executor.go index d531b25cb6..423e579d7e 100644 --- a/pkg/services/session/storage/temporary/executor.go +++ b/pkg/services/session/storage/temporary/executor.go @@ -38,7 +38,7 @@ func (s *TokenStore) Create(_ context.Context, body *session.CreateRequestBody) s.mtx.Lock() s.tokens[key{ tokenID: base58.Encode(uidBytes), - ownerID: base58.Encode(id.WalletBytes()), + ownerID: id.EncodeToString(), }] = storage.NewPrivateToken(&sk.PrivateKey, body.GetExpiration()) s.mtx.Unlock() diff --git a/pkg/services/session/storage/temporary/storage.go b/pkg/services/session/storage/temporary/storage.go index 9ae9db9dc9..c9da6b842f 100644 --- a/pkg/services/session/storage/temporary/storage.go +++ b/pkg/services/session/storage/temporary/storage.go @@ -41,7 +41,7 @@ func (s *TokenStore) Get(ownerID user.ID, tokenID []byte) *storage.PrivateToken s.mtx.RLock() t := s.tokens[key{ tokenID: base58.Encode(tokenID), - ownerID: base58.Encode(ownerID.WalletBytes()), + ownerID: ownerID.EncodeToString(), }] s.mtx.RUnlock() From ca0a33ea0febe0a44f5ca70a61c92a23b6cbd4d5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 25 Dec 2024 12:04:08 +0300 Subject: [PATCH 1118/1413] [#465] objsvc: Set NETMAP_EPOCH xheader for auxiliary requests Signed-off-by: Evgenii Stratonikov --- pkg/services/object/internal/client/client.go | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/pkg/services/object/internal/client/client.go b/pkg/services/object/internal/client/client.go index 2c405070d0..3e88326401 100644 --- a/pkg/services/object/internal/client/client.go +++ b/pkg/services/object/internal/client/client.go @@ -7,9 +7,11 @@ import ( "errors" "fmt" "io" + "strconv" coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + sessionAPI "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -31,6 +33,8 @@ type commonPrm struct { local bool xHeaders []string + + netmapEpoch uint64 } // SetClient sets base client for ForstFS API communication. @@ -73,6 +77,14 @@ func (x *commonPrm) SetXHeaders(hs []string) { x.xHeaders = hs } +func (x *commonPrm) calculateXHeaders() []string { + hs := x.xHeaders + if x.netmapEpoch != 0 { + hs = append(hs, sessionAPI.XHeaderNetmapEpoch, strconv.FormatUint(x.netmapEpoch, 10)) + } + return hs +} + type readPrmCommon struct { commonPrm } @@ -80,8 +92,8 @@ type readPrmCommon struct { // SetNetmapEpoch sets the epoch number to be used to locate the objectSDK. // // By default current epoch on the server will be used. -func (x *readPrmCommon) SetNetmapEpoch(_ uint64) { - // FIXME(@fyrchik): https://git.frostfs.info/TrueCloudLab/frostfs-node/issues/465 +func (x *readPrmCommon) SetNetmapEpoch(epoch uint64) { + x.netmapEpoch = epoch } // GetObjectPrm groups parameters of GetObject operation. @@ -139,7 +151,7 @@ func GetObject(ctx context.Context, prm GetObjectPrm) (*GetObjectRes, error) { prm.ClientParams.Session = prm.tokenSession } - prm.ClientParams.XHeaders = prm.xHeaders + prm.ClientParams.XHeaders = prm.calculateXHeaders() prm.ClientParams.BearerToken = prm.tokenBearer prm.ClientParams.Local = prm.local prm.ClientParams.Key = prm.key @@ -233,7 +245,7 @@ func HeadObject(ctx context.Context, prm HeadObjectPrm) (*HeadObjectRes, error) prm.ClientParams.BearerToken = prm.tokenBearer prm.ClientParams.Local = prm.local - prm.ClientParams.XHeaders = prm.xHeaders + prm.ClientParams.XHeaders = prm.calculateXHeaders() cliRes, err := prm.cli.ObjectHead(ctx, prm.ClientParams) if err == nil { @@ -326,7 +338,7 @@ func PayloadRange(ctx context.Context, prm PayloadRangePrm) (*PayloadRangeRes, e prm.ClientParams.Session = prm.tokenSession } - prm.ClientParams.XHeaders = prm.xHeaders + prm.ClientParams.XHeaders = prm.calculateXHeaders() prm.ClientParams.BearerToken = prm.tokenBearer prm.ClientParams.Local = prm.local prm.ClientParams.Length = prm.ln @@ -390,7 +402,7 @@ func PutObject(ctx context.Context, prm PutObjectPrm) (*PutObjectRes, error) { defer span.End() prmCli := client.PrmObjectPutInit{ - XHeaders: prm.xHeaders, + XHeaders: prm.calculateXHeaders(), BearerToken: prm.tokenBearer, Session: prm.tokenSession, Local: true, @@ -437,7 +449,7 @@ func PutObjectSingle(ctx context.Context, prm PutObjectPrm) (*PutObjectRes, erro } prmCli := client.PrmObjectPutSingle{ - XHeaders: prm.xHeaders, + XHeaders: prm.calculateXHeaders(), BearerToken: prm.tokenBearer, Session: prm.tokenSession, Local: true, @@ -496,7 +508,7 @@ func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes prm.cliPrm.Local = prm.local prm.cliPrm.Session = prm.tokenSession prm.cliPrm.BearerToken = prm.tokenBearer - prm.cliPrm.XHeaders = prm.xHeaders + prm.cliPrm.XHeaders = prm.calculateXHeaders() prm.cliPrm.Key = prm.key rdr, err := prm.cli.ObjectSearchInit(ctx, prm.cliPrm) From 9cd1bcef06b1c116910f6d9d2e4895332a628b92 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 23 Dec 2024 14:53:04 +0300 Subject: [PATCH 1119/1413] [#1512] object: Make raw `PutSingle` check status within response Signed-off-by: Airat Arifullin --- pkg/services/object/put/single.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 36b0bd54c7..19d025ff81 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -29,6 +29,7 @@ import ( sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/tzhash/tz" @@ -353,6 +354,9 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, err = fmt.Errorf("response verification failed: %w", err) } + st := apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus()) + err = apistatus.ErrFromStatus(st) + return }) From e44782473a737daac7f05b0b491dc756de31391d Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 24 Dec 2024 21:27:45 +0300 Subject: [PATCH 1120/1413] [#1512] object: Fix `writePart` for EC-container * Immediatly return after `ObjectAlreadyRemoved` error. Signed-off-by: Airat Arifullin --- pkg/services/object/common/writer/ec.go | 3 +++ pkg/services/object/put/single.go | 1 + 2 files changed, 4 insertions(+) diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index fdaa569da2..94bcf6a32c 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" + clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/erasurecode" @@ -274,6 +275,8 @@ func (e *ECWriter) writePart(ctx context.Context, obj *objectSDK.Object, partIdx err := e.putECPartToNode(ctx, obj, node) if err == nil { return nil + } else if clientSDK.IsErrObjectAlreadyRemoved(err) { + return err } e.Config.Logger.Warn(ctx, logs.ECFailedToSaveECPart, zap.Stringer("part_address", object.AddressOf(obj)), zap.Stringer("parent_address", obj.ECHeader().Parent()), zap.Int("part_index", partIdx), diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 19d025ff81..5219e64d56 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -352,6 +352,7 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, err = signature.VerifyServiceMessage(resp) if err != nil { err = fmt.Errorf("response verification failed: %w", err) + return } st := apistatus.FromStatusV2(resp.GetMetaHeader().GetStatus()) From 0da998ef50472d8de4589bfd9105ce1892636c94 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 25 Dec 2024 22:12:41 +0300 Subject: [PATCH 1121/1413] [#1583] metabase: Skip expired objects in `ListWithCursor` Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/metabase/list.go | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index a7ff2222fe..375d1cb1a8 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -87,7 +87,8 @@ type CountAliveObjectsInContainerPrm struct { } // ListWithCursor lists physical objects available in metabase starting from -// cursor. Includes objects of all types. Does not include inhumed objects. +// cursor. Includes objects of all types. Does not include inhumed and expired +// objects. // Use cursor value from response for consecutive requests. // // Returns ErrEndOfListing if there are no more objects to return or count @@ -143,6 +144,8 @@ func (db *DB) listWithCursor(tx *bbolt.Tx, result []objectcore.Info, count int, rawAddr := make([]byte, cidSize, addressKeySize) + currEpoch := db.epochState.CurrentEpoch() + loop: for ; name != nil; name, _ = c.Next() { cidRaw, prefix := parseContainerIDWithPrefix(&containerID, name) @@ -167,7 +170,7 @@ loop: if bkt != nil { copy(rawAddr, cidRaw) result, offset, cursor, err = selectNFromBucket(bkt, objType, graveyardBkt, garbageBkt, rawAddr, containerID, - result, count, cursor, threshold) + result, count, cursor, threshold, currEpoch) if err != nil { return nil, nil, err } @@ -212,6 +215,7 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket limit int, // stop listing at `limit` items in result cursor *Cursor, // start from cursor object threshold bool, // ignore cursor and start immediately + currEpoch uint64, ) ([]objectcore.Info, []byte, *Cursor, error) { if cursor == nil { cursor = new(Cursor) @@ -243,13 +247,19 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket continue } + var o objectSDK.Object + if err := o.Unmarshal(bytes.Clone(v)); err != nil { + return nil, nil, nil, err + } + + expEpoch, hasExpEpoch := hasExpirationEpoch(&o) + if !objectLocked(bkt.Tx(), cnt, obj) && hasExpEpoch && expEpoch < currEpoch { + continue + } + var isLinkingObj bool var ecInfo *objectcore.ECInfo if objType == objectSDK.TypeRegular { - var o objectSDK.Object - if err := o.Unmarshal(bytes.Clone(v)); err != nil { - return nil, nil, nil, err - } isLinkingObj = isLinkObject(&o) ecHeader := o.ECHeader() if ecHeader != nil { From fa08bfa553ee013b65076c38146f83134ae2f06c Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 25 Dec 2024 22:16:11 +0300 Subject: [PATCH 1122/1413] [#1583] metabase/test: Update `TestLisObjectsWithCursor` Update this test following recent changes to ensure that `(*DB).ListWithCursor` skips expired objects. Signed-off-by: Aleksey Savchuk --- .../metabase/list_test.go | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 1d8beb1758..817b220105 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -3,14 +3,17 @@ package meta_test import ( "context" "errors" + "strconv" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" @@ -71,14 +74,16 @@ func benchmarkListWithCursor(b *testing.B, db *meta.DB, batchSize int) { func TestLisObjectsWithCursor(t *testing.T) { t.Parallel() - db := newDB(t) - defer func() { require.NoError(t, db.Close(context.Background())) }() - const ( + currEpoch = 100 + expEpoch = currEpoch - 1 containers = 5 - total = containers * 4 // regular + ts + child + lock + total = containers * 6 // regular + ts + child + lock + non-expired regular + locked expired ) + db := newDB(t, meta.WithEpochState(epochState{currEpoch})) + defer func() { require.NoError(t, db.Close(context.Background())) }() + expected := make([]object.Info, 0, total) // fill metabase with objects @@ -127,6 +132,26 @@ func TestLisObjectsWithCursor(t *testing.T) { err = putBig(db, child) require.NoError(t, err) expected = append(expected, object.Info{Address: object.AddressOf(child), Type: objectSDK.TypeRegular}) + + // add expired object (do not include into expected) + obj = testutil.GenerateObjectWithCID(containerID) + testutil.AddAttribute(obj, objectV2.SysAttributeExpEpoch, strconv.Itoa(expEpoch)) + require.NoError(t, metaPut(db, obj, nil)) + + // add non-expired object (include into expected) + obj = testutil.GenerateObjectWithCID(containerID) + testutil.AddAttribute(obj, objectV2.SysAttributeExpEpoch, strconv.Itoa(currEpoch)) + require.NoError(t, metaPut(db, obj, nil)) + expected = append(expected, object.Info{Address: object.AddressOf(obj), Type: objectSDK.TypeRegular}) + + // add locked expired object (include into expected) + obj = testutil.GenerateObjectWithCID(containerID) + objID := oidtest.ID() + obj.SetID(objID) + testutil.AddAttribute(obj, objectV2.SysAttributeExpEpoch, strconv.Itoa(expEpoch)) + require.NoError(t, metaPut(db, obj, nil)) + require.NoError(t, db.Lock(context.Background(), containerID, oidtest.ID(), []oid.ID{objID})) + expected = append(expected, object.Info{Address: object.AddressOf(obj), Type: objectSDK.TypeRegular}) } t.Run("success with various count", func(t *testing.T) { From 6fe34d266a2cd8ff35929053610cb36851263cb4 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Wed, 25 Dec 2024 15:32:24 +0300 Subject: [PATCH 1123/1413] [#1577] morph: Fix typo Signed-off-by: Ekaterina Lebedeva --- pkg/morph/client/client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 37599e6961..01fcc98e58 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -210,7 +210,7 @@ func (c *Client) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.F // TestInvokeIterator invokes contract method returning an iterator and executes cb on each element. // If cb returns an error, the session is closed and this error is returned as-is. -// If the remove neo-go node does not support sessions, `unwrap.ErrNoSessionID` is returned. +// If the remote neo-go node does not support sessions, `unwrap.ErrNoSessionID` is returned. // batchSize is the number of items to prefetch: if the number of items in the iterator is less than batchSize, no session will be created. // The default batchSize is 100, the default limit from neo-go. func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int, contract util.Uint160, method string, args ...interface{}) error { From 242f0095d08e54124807f14b30f5ee3adfe9eb6b Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Wed, 25 Dec 2024 14:25:29 +0300 Subject: [PATCH 1124/1413] [#1577] container: Reduce iterations through container list * Separated iteration through container ids from `ContainersOf()` so that it could be reused. * When listing containers we used to iterate through the the whole list of containers twice: first when reading from a contract, then when sending them. Now we can send batches of containers when reading from the contract. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-node/container.go | 5 +++ pkg/morph/client/container/containers_of.go | 50 +++++++++++---------- pkg/morph/client/container/list.go | 44 +++++++++++------- pkg/services/container/morph/executor.go | 48 ++++++++++++++------ 4 files changed, 94 insertions(+), 53 deletions(-) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index fb2550a03b..be0acf7389 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -222,6 +222,7 @@ type morphContainerReader struct { lister interface { ContainersOf(*user.ID) ([]cid.ID, error) + IterateContainersOf(*user.ID, func(cid.ID) error) error } } @@ -237,6 +238,10 @@ func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) { return x.lister.ContainersOf(id) } +func (x *morphContainerReader) IterateContainersOf(id *user.ID, processCID func(cid.ID) error) error { + return x.lister.IterateContainersOf(id, processCID) +} + type morphContainerWriter struct { neoClient *cntClient.Client } diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go index 5fe15be0d9..6381a14c09 100644 --- a/pkg/morph/client/container/containers_of.go +++ b/pkg/morph/client/container/containers_of.go @@ -2,9 +2,7 @@ package container import ( "errors" - "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" @@ -16,27 +14,37 @@ import ( // // If remote RPC does not support neo-go session API, fallback to List() method. func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { - var rawID []byte + var cidList []cid.ID + var err error + cb := func(id cid.ID) error { + cidList = append(cidList, id) + return nil + } + if err = c.IterateContainersOf(idUser, cb); err != nil { + return nil, err + } + return cidList, nil +} + +// iterateContainers iterates over a list of container identifiers +// belonging to the specified user of FrostFS system and executes +// `cb` on each element. If idUser is nil, calls it on the list of all containers. +func (c *Client) IterateContainersOf(idUser *user.ID, cb func(item cid.ID) error) error { + var rawID []byte if idUser != nil { rawID = idUser.WalletBytes() } - var cidList []cid.ID - cb := func(item stackitem.Item) error { - rawID, err := client.BytesFromStackItem(item) + cnrHash := c.client.ContractAddress() + itemCb := func(item stackitem.Item) error { + id, err := getCIDfromStackItem(item) if err != nil { - return fmt.Errorf("get byte array from stack item (%s): %w", containersOfMethod, err) + return err } - - var id cid.ID - - err = id.Decode(rawID) - if err != nil { - return fmt.Errorf("decode container ID: %w", err) + if err = cb(id); err != nil { + return err } - - cidList = append(cidList, id) return nil } @@ -49,14 +57,10 @@ func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { // 512 is big enough value and it is beautiful. const batchSize = 512 - cnrHash := c.client.ContractAddress() - err := c.client.Morph().TestInvokeIterator(cb, batchSize, cnrHash, containersOfMethod, rawID) - if err != nil { - if errors.Is(err, unwrap.ErrNoSessionID) { - return c.list(idUser) - } - return nil, err + err := c.client.Morph().TestInvokeIterator(itemCb, batchSize, cnrHash, containersOfMethod, rawID) + if err != nil && errors.Is(err, unwrap.ErrNoSessionID) { + return c.iterate(idUser, cb) } - return cidList, nil + return err } diff --git a/pkg/morph/client/container/list.go b/pkg/morph/client/container/list.go index d9719aedd2..78ea8278f5 100644 --- a/pkg/morph/client/container/list.go +++ b/pkg/morph/client/container/list.go @@ -6,15 +6,16 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) -// list returns a list of container identifiers belonging +// iterate iterates through a list of container identifiers belonging // to the specified user of FrostFS system. The list is composed // through Container contract call. // -// Returns the identifiers of all FrostFS containers if pointer +// Iterates through the identifiers of all FrostFS containers if pointer // to user identifier is nil. -func (c *Client) list(idUser *user.ID) ([]cid.ID, error) { +func (c *Client) iterate(idUser *user.ID, cb func(cid.ID) error) error { var rawID []byte if idUser != nil { @@ -27,32 +28,41 @@ func (c *Client) list(idUser *user.ID) ([]cid.ID, error) { res, err := c.client.TestInvoke(prm) if err != nil { - return nil, fmt.Errorf("test invoke (%s): %w", listMethod, err) + return fmt.Errorf("test invoke (%s): %w", listMethod, err) } else if ln := len(res); ln != 1 { - return nil, fmt.Errorf("unexpected stack item count (%s): %d", listMethod, ln) + return fmt.Errorf("unexpected stack item count (%s): %d", listMethod, ln) } res, err = client.ArrayFromStackItem(res[0]) if err != nil { - return nil, fmt.Errorf("get stack item array from stack item (%s): %w", listMethod, err) + return fmt.Errorf("get stack item array from stack item (%s): %w", listMethod, err) } - cidList := make([]cid.ID, 0, len(res)) for i := range res { - rawID, err := client.BytesFromStackItem(res[i]) + id, err := getCIDfromStackItem(res[i]) if err != nil { - return nil, fmt.Errorf("get byte array from stack item (%s): %w", listMethod, err) + return err } - var id cid.ID - - err = id.Decode(rawID) - if err != nil { - return nil, fmt.Errorf("decode container ID: %w", err) + if err = cb(id); err != nil { + return err } - - cidList = append(cidList, id) } - return cidList, nil + return nil +} + +func getCIDfromStackItem(item stackitem.Item) (cid.ID, error) { + rawID, err := client.BytesFromStackItem(item) + if err != nil { + return cid.ID{}, fmt.Errorf("get byte array from stack item (%s): %w", listMethod, err) + } + + var id cid.ID + + err = id.Decode(rawID) + if err != nil { + return cid.ID{}, fmt.Errorf("decode container ID: %w", err) + } + return id, nil } diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index e9d1606f19..cadf92e193 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -30,6 +30,7 @@ type Reader interface { // to the specified user of FrostFS system. Returns the identifiers // of all FrostFS containers if pointer to owner identifier is nil. ContainersOf(*user.ID) ([]cid.ID, error) + IterateContainersOf(*user.ID, func(cid.ID) error) error } // Writer is an interface of container storage updater. @@ -201,7 +202,7 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) return res, nil } -func (s *morphExecutor) ListStream(_ context.Context, req *container.ListStreamRequest, stream containerSvc.ListStream) error { +func (s *morphExecutor) ListStream(ctx context.Context, req *container.ListStreamRequest, stream containerSvc.ListStream) error { body := req.GetBody() idV2 := body.GetOwnerID() if idV2 == nil { @@ -215,20 +216,41 @@ func (s *morphExecutor) ListStream(_ context.Context, req *container.ListStreamR return fmt.Errorf("invalid user ID: %w", err) } - cnrs, err := s.rdr.ContainersOf(&id) - if err != nil { - return err - } - - cidList := make([]refs.ContainerID, len(cnrs)) - for i := range cnrs { - cnrs[i].WriteToV2(&cidList[i]) - } - resBody := new(container.ListStreamResponseBody) - resBody.SetContainerIDs(cidList) r := new(container.ListStreamResponse) r.SetBody(resBody) - return stream.Send(r) + var cidList []refs.ContainerID + + // Amount of containers to send at once. + const batchSize = 1000 + + processCID := func(id cid.ID) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + var refID refs.ContainerID + id.WriteToV2(&refID) + cidList = append(cidList, refID) + if len(cidList) == batchSize { + r.GetBody().SetContainerIDs(cidList) + cidList = cidList[:0] + return stream.Send(r) + } + return nil + } + + if err = s.rdr.IterateContainersOf(&id, processCID); err != nil { + return err + } + + if len(cidList) > 0 { + r.GetBody().SetContainerIDs(cidList) + return stream.Send(r) + } + + return nil } From c0221d76e6534a7c264c24a7b1c6af73dad2b5ed Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 27 Dec 2024 15:31:06 +0300 Subject: [PATCH 1125/1413] [#1577] node/container: Fix typo Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-node/config/container/container.go | 2 +- pkg/morph/client/container/containers_of.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-node/config/container/container.go b/cmd/frostfs-node/config/container/container.go index b0b8043d62..1cd64a6f80 100644 --- a/cmd/frostfs-node/config/container/container.go +++ b/cmd/frostfs-node/config/container/container.go @@ -6,7 +6,7 @@ const ( subsection = "container" listStreamSubsection = "list_stream" - // ContainerBatchSizeDefault represents he maximum amount of containers to send via stream at once. + // ContainerBatchSizeDefault represents the maximum amount of containers to send via stream at once. ContainerBatchSizeDefault = 1000 ) diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go index 6381a14c09..074a586beb 100644 --- a/pkg/morph/client/container/containers_of.go +++ b/pkg/morph/client/container/containers_of.go @@ -36,7 +36,6 @@ func (c *Client) IterateContainersOf(idUser *user.ID, cb func(item cid.ID) error rawID = idUser.WalletBytes() } - cnrHash := c.client.ContractAddress() itemCb := func(item stackitem.Item) error { id, err := getCIDfromStackItem(item) if err != nil { @@ -57,6 +56,7 @@ func (c *Client) IterateContainersOf(idUser *user.ID, cb func(item cid.ID) error // 512 is big enough value and it is beautiful. const batchSize = 512 + cnrHash := c.client.ContractAddress() err := c.client.Morph().TestInvokeIterator(itemCb, batchSize, cnrHash, containersOfMethod, rawID) if err != nil && errors.Is(err, unwrap.ErrNoSessionID) { return c.iterate(idUser, cb) From d7fcc5ce304c0c8e971c4edccf778cf6b8693d52 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 28 Dec 2024 09:03:07 +0300 Subject: [PATCH 1126/1413] [#1586] objsvc: Allow to send search response in multiple messages Previously, `ln` was only set once, so search has really worked for small number of objects. Fix panic: ``` panic: runtime error: slice bounds out of range [:43690] with capacity 21238 goroutine 6859775 [running]: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object.(*searchStreamMsgSizeCtrl).Send(0xc001eec8d0, 0xc005734000) git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/transport_splitter.go:173 +0x1f0 git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/v2.(*streamWriter).WriteIDs(0xc000520320, {0xc00eb1a000, 0x4fd9c, 0x7fd6475a9a68?}) git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/v2/streamer.go:28 +0x155 git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search.(*uniqueIDWriter).WriteIDs(0xc001386420, {0xc00eb1a000?, 0xc0013ea9c0?, 0x113eef3?}) git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/util.go:62 +0x202 git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search.(*execCtx).writeIDList(0xc00011aa38?, {0xc00eb1a000?, 0xc001eec9f0?, 0xc0008f4380?}) git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/exec.go:68 +0x91 git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search.(*execCtx).executeLocal(0xc0008f4380, {0x176c538, 0xc001eec9f0}) git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/search/local.go:18 +0x16b ``` Signed-off-by: Evgenii Stratonikov --- pkg/services/object/transport_splitter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/services/object/transport_splitter.go b/pkg/services/object/transport_splitter.go index 0b3676edb5..b446d36056 100644 --- a/pkg/services/object/transport_splitter.go +++ b/pkg/services/object/transport_splitter.go @@ -162,13 +162,13 @@ func (s *searchStreamMsgSizeCtrl) Send(resp *object.SearchResponse) error { var newResp *object.SearchResponse - for ln := uint64(len(ids)); ; { + for { if newResp == nil { newResp = new(object.SearchResponse) newResp.SetBody(body) } - cut := min(s.addrAmount, ln) + cut := min(s.addrAmount, uint64(len(ids))) body.SetIDList(ids[:cut]) newResp.SetMetaHeader(resp.GetMetaHeader()) From cddcd73f04cbb1c1894e45dab62dc2070f3931d5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 28 Dec 2024 14:36:18 +0300 Subject: [PATCH 1127/1413] [#1590] adm: Make `--account` flag required in `proxy-*` commands Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/proxy/root.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go index 1854c8d2b9..5f07e58620 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go @@ -30,12 +30,14 @@ var ( func initProxyAddAccount() { AddAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) AddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") + _ = AddAccountCmd.MarkFlagRequired(accountAddressFlag) AddAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initProxyRemoveAccount() { RemoveAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) RemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") + _ = AddAccountCmd.MarkFlagRequired(accountAddressFlag) RemoveAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } From dc410fca901dc0f4628fb3d64d83be32525414bd Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 28 Dec 2024 14:37:35 +0300 Subject: [PATCH 1128/1413] [#1590] adm: Accept many accounts in `proxy-*` commands Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/proxy/proxy.go | 31 +++++++++++++------ .../internal/modules/morph/proxy/root.go | 4 +-- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go index cb575b657b..24cda45a61 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/proxy.go @@ -20,23 +20,32 @@ const ( accountAddressFlag = "account" ) +func parseAddresses(cmd *cobra.Command) []util.Uint160 { + var addrs []util.Uint160 + + accs, _ := cmd.Flags().GetStringArray(accountAddressFlag) + for _, acc := range accs { + addr, err := address.StringToUint160(acc) + commonCmd.ExitOnErr(cmd, "invalid account: %w", err) + + addrs = append(addrs, addr) + } + return addrs +} + func addProxyAccount(cmd *cobra.Command, _ []string) { - acc, _ := cmd.Flags().GetString(accountAddressFlag) - addr, err := address.StringToUint160(acc) - commonCmd.ExitOnErr(cmd, "invalid account: %w", err) - err = processAccount(cmd, addr, "addAccount") + addrs := parseAddresses(cmd) + err := processAccount(cmd, addrs, "addAccount") commonCmd.ExitOnErr(cmd, "processing error: %w", err) } func removeProxyAccount(cmd *cobra.Command, _ []string) { - acc, _ := cmd.Flags().GetString(accountAddressFlag) - addr, err := address.StringToUint160(acc) - commonCmd.ExitOnErr(cmd, "invalid account: %w", err) - err = processAccount(cmd, addr, "removeAccount") + addrs := parseAddresses(cmd) + err := processAccount(cmd, addrs, "removeAccount") commonCmd.ExitOnErr(cmd, "processing error: %w", err) } -func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error { +func processAccount(cmd *cobra.Command, addrs []util.Uint160, method string) error { wCtx, err := helper.NewInitializeContext(cmd, viper.GetViper()) if err != nil { return fmt.Errorf("can't initialize context: %w", err) @@ -54,7 +63,9 @@ func processAccount(cmd *cobra.Command, addr util.Uint160, method string) error } bw := io.NewBufBinWriter() - emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr) + for _, addr := range addrs { + emit.AppCall(bw.BinWriter, proxyHash, method, callflag.All, addr) + } if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil { return err diff --git a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go index 5f07e58620..ad89af2b52 100644 --- a/cmd/frostfs-adm/internal/modules/morph/proxy/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/proxy/root.go @@ -29,14 +29,14 @@ var ( func initProxyAddAccount() { AddAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - AddAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") + AddAccountCmd.Flags().StringArray(accountAddressFlag, nil, "Wallet address string") _ = AddAccountCmd.MarkFlagRequired(accountAddressFlag) AddAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } func initProxyRemoveAccount() { RemoveAccountCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) - RemoveAccountCmd.Flags().String(accountAddressFlag, "", "Wallet address string") + RemoveAccountCmd.Flags().StringArray(accountAddressFlag, nil, "Wallet address string") _ = AddAccountCmd.MarkFlagRequired(accountAddressFlag) RemoveAccountCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) } From 5ccb3394b49c29ea0e9186849bfc9a909e74f5b8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 9 Jan 2025 14:30:17 +0300 Subject: [PATCH 1129/1413] [#1592] go.mod: Update sdk-go Signed-off-by: Evgenii Stratonikov --- go.mod | 32 +++++++++++++-------------- go.sum | 68 +++++++++++++++++++++++++++++++--------------------------- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/go.mod b/go.mod index 8f40538726..267e411fba 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241210104938-c4463df8d467 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250109084609-328d214d2d76 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 @@ -27,7 +27,7 @@ require ( github.com/klauspost/compress v1.17.4 github.com/mailru/easyjson v0.7.7 github.com/mr-tron/base58 v1.2.0 - github.com/multiformats/go-multiaddr v0.12.1 + github.com/multiformats/go-multiaddr v0.14.0 github.com/nspcc-dev/neo-go v0.106.3 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 @@ -40,15 +40,15 @@ require ( github.com/ssgreg/journald v1.0.0 github.com/stretchr/testify v1.9.0 go.etcd.io/bbolt v1.3.10 - go.opentelemetry.io/otel v1.28.0 - go.opentelemetry.io/otel/trace v1.28.0 + go.opentelemetry.io/otel v1.31.0 + go.opentelemetry.io/otel/trace v1.31.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/sync v0.7.0 - golang.org/x/sys v0.22.0 - golang.org/x/term v0.21.0 - google.golang.org/grpc v1.66.2 - google.golang.org/protobuf v1.34.2 + golang.org/x/sync v0.10.0 + golang.org/x/sys v0.28.0 + golang.org/x/term v0.27.0 + google.golang.org/grpc v1.69.2 + google.golang.org/protobuf v1.36.1 gopkg.in/yaml.v3 v3.0.1 ) @@ -119,15 +119,15 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 // indirect - go.opentelemetry.io/otel/metric v1.28.0 // indirect - go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/net v0.26.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + golang.org/x/crypto v0.31.0 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/text v0.21.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect gopkg.in/ini.v1 v1.67.0 // indirect lukechampine.com/blake3 v1.2.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/go.sum b/go.sum index d633962020..935d3c56a7 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241210104938-c4463df8d467 h1:MH9uHZFZNyUCL+YChiDcVeXPjhTDcFDeoGr8Mc8NY9M= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20241210104938-c4463df8d467/go.mod h1:eoK7+KZQ9GJxbzIs6vTnoUJqFDppavInLRHaN4MYgZg= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250109084609-328d214d2d76 h1:wzvSJIiS+p9qKfl3eg1oH6qlrjaEWiqTc/iMDKG3Ml4= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250109084609-328d214d2d76/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= @@ -106,6 +106,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -188,8 +190,8 @@ github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aG github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= 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-multiaddr v0.12.1 h1:vm+BA/WZA8QZDp1pF1FWhi5CT3g1tbi5GJmqpb6wnlk= -github.com/multiformats/go-multiaddr v0.12.1/go.mod h1:7mPkiBMmLeFipt+nNSq9pHZUeJSt8lHBgH6yhj0YQzE= +github.com/multiformats/go-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= +github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= 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-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= @@ -290,20 +292,22 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0= go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ= -go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= -go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= +go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0 h1:EVSnY9JbEEW92bEkIYOVMw4q1WJxIAGoFTrtYOzWuRQ= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.28.0/go.mod h1:Ea1N1QQryNXpCD0I1fdLibBAIpQuBkznMmkdKrapk1Y= -go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= -go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= -go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= -go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= -go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= +go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= +go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc= +go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8= +go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= +go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -318,8 +322,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -339,16 +343,16 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= -golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +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/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -375,16 +379,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -392,8 +396,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -406,12 +410,12 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0= -google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= -google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= -google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 h1:fVoAXEKA4+yufmbdVYv+SE73+cPZbbbe8paLsHfkK+U= +google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU= +google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -420,8 +424,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= From 3900b92927bb0343cf7282bf91e817f8cd44f827 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 26 Dec 2024 14:12:35 +0300 Subject: [PATCH 1130/1413] Revert "[#1492] metabase: Ensure Unmarshal() is called on a cloned slice" This reverts commit 8ed7a676d50e24489e2abeb5269d6eb3332df1f8. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/exists.go | 3 +-- pkg/local_object_storage/metabase/get.go | 11 +++++------ pkg/local_object_storage/metabase/iterators.go | 3 +-- pkg/local_object_storage/metabase/list.go | 4 ++-- pkg/local_object_storage/metabase/put.go | 3 +-- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index 3133c5480a..962108a761 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -1,7 +1,6 @@ package meta import ( - "bytes" "context" "fmt" "time" @@ -227,7 +226,7 @@ func getSplitInfo(tx *bbolt.Tx, cnr cid.ID, key []byte) (*objectSDK.SplitInfo, e splitInfo := objectSDK.NewSplitInfo() - err := splitInfo.Unmarshal(bytes.Clone(rawSplitInfo)) + err := splitInfo.Unmarshal(rawSplitInfo) if err != nil { return nil, fmt.Errorf("unmarshal split info from root index: %w", err) } diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index af274b245f..615add1af1 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -1,7 +1,6 @@ package meta import ( - "bytes" "context" "fmt" "time" @@ -112,7 +111,7 @@ func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw b // check in primary index data := getFromBucket(tx, primaryBucketName(cnr, bucketName), key) if len(data) != 0 { - return obj, obj.Unmarshal(bytes.Clone(data)) + return obj, obj.Unmarshal(data) } data = getFromBucket(tx, ecInfoBucketName(cnr, bucketName), key) @@ -123,13 +122,13 @@ func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw b // if not found then check in tombstone index data = getFromBucket(tx, tombstoneBucketName(cnr, bucketName), key) if len(data) != 0 { - return obj, obj.Unmarshal(bytes.Clone(data)) + return obj, obj.Unmarshal(data) } // if not found then check in locker index data = getFromBucket(tx, bucketNameLockers(cnr, bucketName), key) if len(data) != 0 { - return obj, obj.Unmarshal(bytes.Clone(data)) + return obj, obj.Unmarshal(data) } // if not found then check if object is a virtual @@ -185,7 +184,7 @@ func getVirtualObject(tx *bbolt.Tx, cnr cid.ID, key []byte, raw bool) (*objectSD child := objectSDK.New() - err = child.Unmarshal(bytes.Clone(data)) + err = child.Unmarshal(data) if err != nil { return nil, fmt.Errorf("unmarshal child with parent: %w", err) } @@ -219,7 +218,7 @@ func getECInfoError(tx *bbolt.Tx, cnr cid.ID, data []byte) error { objData := getFromBucket(tx, primaryBucketName(cnr, make([]byte, bucketKeySize)), key) if len(objData) != 0 { obj := objectSDK.New() - if err := obj.Unmarshal(bytes.Clone(objData)); err != nil { + if err := obj.Unmarshal(objData); err != nil { return err } chunk := objectSDK.ECChunk{} diff --git a/pkg/local_object_storage/metabase/iterators.go b/pkg/local_object_storage/metabase/iterators.go index 0d438e1023..9cccd7dad5 100644 --- a/pkg/local_object_storage/metabase/iterators.go +++ b/pkg/local_object_storage/metabase/iterators.go @@ -1,7 +1,6 @@ package meta import ( - "bytes" "context" "errors" "strconv" @@ -130,7 +129,7 @@ func iteratePhyObjects(tx *bbolt.Tx, f func(cid.ID, oid.ID, *objectSDK.Object) e } return b.ForEach(func(k, v []byte) error { - if oid.Decode(k) == nil && obj.Unmarshal(bytes.Clone(v)) == nil { + if oid.Decode(k) == nil && obj.Unmarshal(v) == nil { return f(cid, oid, obj) } diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 375d1cb1a8..f488c3ced3 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -248,7 +248,7 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket } var o objectSDK.Object - if err := o.Unmarshal(bytes.Clone(v)); err != nil { + if err := o.Unmarshal(v); err != nil { return nil, nil, nil, err } @@ -423,7 +423,7 @@ func (db *DB) iterateOverObjectsInContainer(ctx context.Context, tx *bbolt.Tx, p var ecInfo *objectcore.ECInfo if prm.ObjectType == objectSDK.TypeRegular { var o objectSDK.Object - if err := o.Unmarshal(bytes.Clone(v)); err != nil { + if err := o.Unmarshal(v); err != nil { return err } isLinkingObj = isLinkObject(&o) diff --git a/pkg/local_object_storage/metabase/put.go b/pkg/local_object_storage/metabase/put.go index 16918c4d93..5e1bbfe9e9 100644 --- a/pkg/local_object_storage/metabase/put.go +++ b/pkg/local_object_storage/metabase/put.go @@ -1,7 +1,6 @@ package meta import ( - "bytes" "context" "encoding/binary" "errors" @@ -320,7 +319,7 @@ func updateSplitInfoIndex(tx *bbolt.Tx, objKey []byte, cnr cid.ID, bucketName [] return si.Marshal() default: oldSI := objectSDK.NewSplitInfo() - if err := oldSI.Unmarshal(bytes.Clone(old)); err != nil { + if err := oldSI.Unmarshal(old); err != nil { return nil, err } si = util.MergeSplitInfo(si, oldSI) From 8a658de0b28835fcf55a7c611eed497dd1e253ee Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 20 Dec 2024 11:40:34 +0300 Subject: [PATCH 1131/1413] [#1506] ape: Do not create cosigners slice on each contract invocation Signed-off-by: Evgenii Stratonikov --- pkg/ape/contract_storage/proxy.go | 47 +++++++++++++------------------ 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/pkg/ape/contract_storage/proxy.go b/pkg/ape/contract_storage/proxy.go index 953b91a796..8ae3f52036 100644 --- a/pkg/ape/contract_storage/proxy.go +++ b/pkg/ape/contract_storage/proxy.go @@ -31,9 +31,7 @@ type RPCActorProvider interface { type ProxyVerificationContractStorage struct { rpcActorProvider RPCActorProvider - acc *wallet.Account - - proxyScriptHash util.Uint160 + cosigners []actor.SignerAccount policyScriptHash util.Uint160 } @@ -41,12 +39,27 @@ type ProxyVerificationContractStorage struct { var _ ProxyAdaptedContractStorage = (*ProxyVerificationContractStorage)(nil) func NewProxyVerificationContractStorage(rpcActorProvider RPCActorProvider, key *keys.PrivateKey, proxyScriptHash, policyScriptHash util.Uint160) *ProxyVerificationContractStorage { + acc := wallet.NewAccountFromPrivateKey(key) return &ProxyVerificationContractStorage{ rpcActorProvider: rpcActorProvider, - acc: wallet.NewAccountFromPrivateKey(key), - - proxyScriptHash: proxyScriptHash, + cosigners: []actor.SignerAccount{ + { + Signer: transaction.Signer{ + Account: proxyScriptHash, + Scopes: transaction.CustomContracts, + AllowedContracts: []util.Uint160{policyScriptHash}, + }, + Account: notary.FakeContractAccount(proxyScriptHash), + }, + { + Signer: transaction.Signer{ + Account: acc.Contract.ScriptHash(), + Scopes: transaction.CalledByEntry, + }, + Account: acc, + }, + }, policyScriptHash: policyScriptHash, } @@ -64,7 +77,7 @@ func (n *contractStorageActorAdapter) GetRPCInvoker() invoker.RPCInvoke { func (contractStorage *ProxyVerificationContractStorage) newContractStorageActor() (policy_morph.ContractStorageActor, error) { rpcActor := contractStorage.rpcActorProvider.GetRPCActor() - act, err := actor.New(rpcActor, cosigners(contractStorage.acc, contractStorage.proxyScriptHash, contractStorage.policyScriptHash)) + act, err := actor.New(rpcActor, contractStorage.cosigners) if err != nil { return nil, err } @@ -106,23 +119,3 @@ func (contractStorage *ProxyVerificationContractStorage) ListMorphRuleChains(nam } return policy_morph.NewContractStorage(contractStorageActor, contractStorage.policyScriptHash).ListMorphRuleChains(name, target) } - -func cosigners(acc *wallet.Account, proxyScriptHash, policyScriptHash util.Uint160) []actor.SignerAccount { - return []actor.SignerAccount{ - { - Signer: transaction.Signer{ - Account: proxyScriptHash, - Scopes: transaction.CustomContracts, - AllowedContracts: []util.Uint160{policyScriptHash}, - }, - Account: notary.FakeContractAccount(proxyScriptHash), - }, - { - Signer: transaction.Signer{ - Account: acc.Contract.ScriptHash(), - Scopes: transaction.CalledByEntry, - }, - Account: acc, - }, - } -} From 85af6bcd5c31f43672d88345f730e7edb2b1de2a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 20 Dec 2024 11:47:28 +0300 Subject: [PATCH 1132/1413] [#1506] ape: Use contract reader in ListMorphRuleChains() Signed-off-by: Evgenii Stratonikov --- pkg/ape/contract_storage/proxy.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pkg/ape/contract_storage/proxy.go b/pkg/ape/contract_storage/proxy.go index 8ae3f52036..8cbb1cce98 100644 --- a/pkg/ape/contract_storage/proxy.go +++ b/pkg/ape/contract_storage/proxy.go @@ -111,11 +111,16 @@ func (contractStorage *ProxyVerificationContractStorage) RemoveMorphRuleChain(na // ListMorphRuleChains lists morph rule chains from Policy contract using both Proxy contract and storage account as consigners. func (contractStorage *ProxyVerificationContractStorage) ListMorphRuleChains(name chain.Name, target engine.Target) ([]*chain.Chain, error) { - // contractStorageActor is reconstructed per each method invocation because RPCActor's (that is, basically, WSClient) connection may get invalidated, but - // ProxyVerificationContractStorage does not manage reconnections. - contractStorageActor, err := contractStorage.newContractStorageActor() - if err != nil { - return nil, err - } - return policy_morph.NewContractStorage(contractStorageActor, contractStorage.policyScriptHash).ListMorphRuleChains(name, target) + rpcActor := contractStorage.rpcActorProvider.GetRPCActor() + inv := &invokerAdapter{Invoker: invoker.New(rpcActor, nil), rpcInvoker: rpcActor} + return policy_morph.NewContractStorageReader(inv, contractStorage.policyScriptHash).ListMorphRuleChains(name, target) +} + +type invokerAdapter struct { + *invoker.Invoker + rpcInvoker invoker.RPCInvoke +} + +func (n *invokerAdapter) GetRPCInvoker() invoker.RPCInvoke { + return n.rpcInvoker } From 198aaebc94495b992a2eb143f501b14fde4ca641 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 28 Dec 2024 10:20:53 +0300 Subject: [PATCH 1133/1413] [#1506] morph: Simplify WaitTxHalt() signature Avoid dependency on `morph/client` package because of `InvokeRes`. Make signature resemble `WaitAny()` method of `waiter.Waiter` from neo-go. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/morph.go | 2 +- cmd/frostfs-node/netmap.go | 2 +- pkg/morph/client/waiter.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 5415da12a4..657e22389c 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -151,7 +151,7 @@ func makeNotaryDeposit(ctx context.Context, c *cfg) (util.Uint256, uint32, error } func waitNotaryDeposit(ctx context.Context, c *cfg, tx util.Uint256, vub uint32) error { - if err := c.cfgMorph.client.WaitTxHalt(ctx, client.InvokeRes{Hash: tx, VUB: vub}); err != nil { + if err := c.cfgMorph.client.WaitTxHalt(ctx, vub, tx); err != nil { return err } diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 2eb4cd132c..a26fdd7989 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -423,7 +423,7 @@ func (c *cfg) updateNetMapState(ctx context.Context, stateSetter func(*nmClient. if err != nil { return err } - return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res) + return c.cfgNetmap.wrapper.Morph().WaitTxHalt(ctx, res.VUB, res.Hash) } type netInfo struct { diff --git a/pkg/morph/client/waiter.go b/pkg/morph/client/waiter.go index 962ec1bc2a..5b9d2cbe0f 100644 --- a/pkg/morph/client/waiter.go +++ b/pkg/morph/client/waiter.go @@ -33,13 +33,13 @@ func (w *waiterClient) GetVersion() (*result.Version, error) { // WaitTxHalt waits until transaction with the specified hash persists on the blockchain. // It also checks execution result to finish in HALT state. -func (c *Client) WaitTxHalt(ctx context.Context, p InvokeRes) error { +func (c *Client) WaitTxHalt(ctx context.Context, vub uint32, h util.Uint256) error { w, err := waiter.NewPollingBased(&waiterClient{c: c}) if err != nil { return fmt.Errorf("create tx waiter: %w", err) } - res, err := w.WaitAny(ctx, p.VUB, p.Hash) + res, err := w.WaitAny(ctx, vub, h) if err != nil { return fmt.Errorf("wait until tx persists: %w", err) } From f7e75b13b0b3796852d061c06a4d40cc6f5501d7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 20 Dec 2024 15:01:44 +0300 Subject: [PATCH 1134/1413] [#1506] ape_manager: Await tx persist before returning response Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/apemanager.go | 1 + pkg/services/apemanager/executor.go | 27 ++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-node/apemanager.go b/cmd/frostfs-node/apemanager.go index de3aed660b..e761a1b14c 100644 --- a/cmd/frostfs-node/apemanager.go +++ b/cmd/frostfs-node/apemanager.go @@ -19,6 +19,7 @@ func initAPEManagerService(c *cfg) { c.cfgObject.cfgAccessPolicyEngine.policyContractHash) execsvc := apemanager.New(c.cfgObject.cnrSource, contractStorage, + c.cfgMorph.client, apemanager.WithLogger(c.log)) sigsvc := apemanager.NewSignService(&c.key.PrivateKey, execsvc) auditSvc := apemanager.NewAuditService(sigsvc, c.log, c.audit) diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go index cc792e23d2..9d8f665afd 100644 --- a/pkg/services/apemanager/executor.go +++ b/pkg/services/apemanager/executor.go @@ -22,6 +22,7 @@ import ( policy_engine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/mr-tron/base58/base58" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" "go.uber.org/zap" ) @@ -34,6 +35,8 @@ type cfg struct { type Service struct { cfg + waiter Waiter + cnrSrc containercore.Source contractStorage ape_contract.ProxyAdaptedContractStorage @@ -41,11 +44,17 @@ type Service struct { type Option func(*cfg) -func New(cnrSrc containercore.Source, contractStorage ape_contract.ProxyAdaptedContractStorage, opts ...Option) *Service { +type Waiter interface { + WaitTxHalt(context.Context, uint32, util.Uint256) error +} + +func New(cnrSrc containercore.Source, contractStorage ape_contract.ProxyAdaptedContractStorage, waiter Waiter, opts ...Option) *Service { s := &Service{ cnrSrc: cnrSrc, contractStorage: contractStorage, + + waiter: waiter, } for i := range opts { @@ -84,7 +93,7 @@ func (s *Service) validateContainerTargetRequest(cid string, pubKey *keys.Public return nil } -func (s *Service) AddChain(_ context.Context, req *apemanagerV2.AddChainRequest) (*apemanagerV2.AddChainResponse, error) { +func (s *Service) AddChain(ctx context.Context, req *apemanagerV2.AddChainRequest) (*apemanagerV2.AddChainResponse, error) { pub, err := getSignaturePublicKey(req.GetVerificationHeader()) if err != nil { return nil, err @@ -116,7 +125,11 @@ func (s *Service) AddChain(_ context.Context, req *apemanagerV2.AddChainRequest) return nil, fmt.Errorf("unsupported target type: %s", targetType) } - if _, _, err = s.contractStorage.AddMorphRuleChain(apechain.Ingress, target, &chain); err != nil { + txHash, vub, err := s.contractStorage.AddMorphRuleChain(apechain.Ingress, target, &chain) + if err != nil { + return nil, err + } + if err := s.waiter.WaitTxHalt(ctx, vub, txHash); err != nil { return nil, err } @@ -129,7 +142,7 @@ func (s *Service) AddChain(_ context.Context, req *apemanagerV2.AddChainRequest) return resp, nil } -func (s *Service) RemoveChain(_ context.Context, req *apemanagerV2.RemoveChainRequest) (*apemanagerV2.RemoveChainResponse, error) { +func (s *Service) RemoveChain(ctx context.Context, req *apemanagerV2.RemoveChainRequest) (*apemanagerV2.RemoveChainResponse, error) { pub, err := getSignaturePublicKey(req.GetVerificationHeader()) if err != nil { return nil, err @@ -148,7 +161,11 @@ func (s *Service) RemoveChain(_ context.Context, req *apemanagerV2.RemoveChainRe return nil, fmt.Errorf("unsupported target type: %s", targetType) } - if _, _, err = s.contractStorage.RemoveMorphRuleChain(apechain.Ingress, target, req.GetBody().GetChainID()); err != nil { + txHash, vub, err := s.contractStorage.RemoveMorphRuleChain(apechain.Ingress, target, req.GetBody().GetChainID()) + if err != nil { + return nil, err + } + if err := s.waiter.WaitTxHalt(ctx, vub, txHash); err != nil { return nil, err } From ceac1c870915898770603208de2c1cb2d9a23db0 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 9 Jan 2025 20:52:24 +0300 Subject: [PATCH 1135/1413] [#1594] dev: Remove unused parameter 'FROSTFS_MORPH_INACTIVITY_TIMEOUT' Signed-off-by: Alexander Chuprov --- dev/.vscode-example/launch.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/dev/.vscode-example/launch.json b/dev/.vscode-example/launch.json index 6abf5ecdcf..b68ce4fa32 100644 --- a/dev/.vscode-example/launch.json +++ b/dev/.vscode-example/launch.json @@ -42,7 +42,6 @@ "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", - "FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s", "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet01.json", "FROSTFS_NODE_WALLET_PASSWORD":"", "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8080", @@ -98,7 +97,6 @@ "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", - "FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s", "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet02.json", "FROSTFS_NODE_WALLET_PASSWORD":"", "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8082", @@ -154,7 +152,6 @@ "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", - "FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s", "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet03.json", "FROSTFS_NODE_WALLET_PASSWORD":"", "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8084", @@ -210,7 +207,6 @@ "FROSTFS_MORPH_DIAL_TIMEOUT":"30s", "FROSTFS_MORPH_RPC_ENDPOINT_0_ADDRESS":"ws://127.0.0.1:30333/ws", "FROSTFS_MORPH_RPC_ENDPOINT_0_PRIORITY":"0", - "FROSTFS_MORPH_INACTIVITY_TIMEOUT":"60s", "FROSTFS_NODE_WALLET_PATH":"${workspaceFolder}/dev/storage/wallet04.json", "FROSTFS_NODE_WALLET_PASSWORD":"", "FROSTFS_NODE_ADDRESSES":"127.0.0.1:8086", From 09faca034c089b99da140519ef723e03f2c2238b Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 10 Jan 2025 14:53:10 +0300 Subject: [PATCH 1136/1413] [#1593] node: Fix initialization of frostfsid cache Signed-off-by: Alexander Chuprov --- cmd/frostfs-node/container.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index be0acf7389..98fea9f415 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -43,7 +43,7 @@ func initContainerService(_ context.Context, c *cfg) { fatalOnErr(err) cacheSize := morphconfig.FrostfsIDCacheSize(c.appCfg) - if cacheSize > 0 { + if cacheSize > 0 && c.cfgMorph.cacheTTL > 0 { frostfsIDSubjectProvider = newMorphFrostfsIDCache(frostfsIDSubjectProvider, int(cacheSize), c.cfgMorph.cacheTTL, metrics.NewCacheMetrics("frostfs_id")) } From a2485637bb91fcf976ce21cfa09af95f12c27c94 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Fri, 10 Jan 2025 15:13:10 +0300 Subject: [PATCH 1137/1413] [#1593] node/config_example: Add description of morph/cache_ttl=0 behavior Signed-off-by: Alexander Chuprov --- config/example/node.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/example/node.yaml b/config/example/node.yaml index a179b47048..c5acf53860 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -79,7 +79,8 @@ contracts: # side chain NEOFS contract script hashes; optional, override values morph: dial_timeout: 30s # timeout for side chain NEO RPC client connection - cache_ttl: 15s # Sidechain cache TTL value (min interval between similar calls). Negative value disables caching. + cache_ttl: 15s # Sidechain cache TTL value (min interval between similar calls). + # Negative value disables caching. A zero value sets the default value. # Default value: block time. It is recommended to have this value less or equal to block time. # Cached entities: containers, container lists, eACL tables. container_cache_size: 100 # container_cache_size is is the maximum number of containers in the cache. From 6c51f48aab6932b035a42f1982a531eed8251174 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 13 Jan 2025 12:52:02 +0300 Subject: [PATCH 1138/1413] [#1596] metrics: Create public aliases for internal `engine` metrics Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/engine/metrics.go | 44 ++++++---------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/pkg/local_object_storage/engine/metrics.go b/pkg/local_object_storage/engine/metrics.go index 75936206df..963292d835 100644 --- a/pkg/local_object_storage/engine/metrics.go +++ b/pkg/local_object_storage/engine/metrics.go @@ -7,34 +7,12 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" ) -type MetricRegister interface { - AddMethodDuration(method string, d time.Duration) - - SetObjectCounter(shardID, objectType string, v uint64) - AddToObjectCounter(shardID, objectType string, delta int) - - SetMode(shardID string, mode mode.Mode) - - AddToContainerSize(cnrID string, size int64) - DeleteContainerSize(cnrID string) - DeleteContainerCount(cnrID string) - AddToPayloadCounter(shardID string, size int64) - IncErrorCounter(shardID string) - ClearErrorCounter(shardID string) - DeleteShardMetrics(shardID string) - - SetContainerObjectCounter(shardID, contID, objectType string, v uint64) - IncContainerObjectCounter(shardID, contID, objectType string) - SubContainerObjectCounter(shardID, contID, objectType string, v uint64) - - IncRefillObjectsCount(shardID, path string, size int, success bool) - SetRefillPercent(shardID, path string, percent uint32) - SetRefillStatus(shardID, path, status string) - SetEvacuationInProgress(shardID string, value bool) - - WriteCache() metrics.WriteCacheMetrics - GC() metrics.GCMetrics -} +type ( + MetricRegister = metrics.EngineMetrics + GCMetrics = metrics.GCMetrics + WriteCacheMetrics = metrics.WriteCacheMetrics + NullBool = metrics.NullBool +) func elapsed(method string, addFunc func(method string, d time.Duration)) func() { t := time.Now() @@ -76,9 +54,9 @@ type ( ) var ( - _ MetricRegister = noopMetrics{} - _ metrics.WriteCacheMetrics = noopWriteCacheMetrics{} - _ metrics.GCMetrics = noopGCMetrics{} + _ MetricRegister = noopMetrics{} + _ WriteCacheMetrics = noopWriteCacheMetrics{} + _ GCMetrics = noopGCMetrics{} ) func (noopMetrics) AddMethodDuration(string, time.Duration) {} @@ -99,8 +77,8 @@ func (noopMetrics) IncRefillObjectsCount(string, string, int, bool) {} func (noopMetrics) SetRefillPercent(string, string, uint32) {} func (noopMetrics) SetRefillStatus(string, string, string) {} func (noopMetrics) SetEvacuationInProgress(string, bool) {} -func (noopMetrics) WriteCache() metrics.WriteCacheMetrics { return noopWriteCacheMetrics{} } -func (noopMetrics) GC() metrics.GCMetrics { return noopGCMetrics{} } +func (noopMetrics) WriteCache() WriteCacheMetrics { return noopWriteCacheMetrics{} } +func (noopMetrics) GC() GCMetrics { return noopGCMetrics{} } func (noopWriteCacheMetrics) AddMethodDuration(string, string, string, string, bool, time.Duration) {} func (noopWriteCacheMetrics) SetActualCount(string, string, string, uint64) {} From a9f27e074bbf085016f82e1b4802c87ede452283 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 10 Jan 2025 16:27:08 +0300 Subject: [PATCH 1139/1413] [#1243] object: Look for X-Headers within origin before APE check * X-Headers can be found in `origin` field of `MetaHeader` if the request has been forwarded from non-container node. Signed-off-by: Airat Arifullin --- pkg/services/object/ape/service.go | 56 +++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index c6d152e0f0..d9594a3fc8 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -150,6 +150,11 @@ type putStreamBasicChecker struct { } func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRequest) error { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin + } + if partInit, ok := request.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok { reqCtx, err := requestContext(ctx) if err != nil { @@ -171,7 +176,7 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR ContainerOwner: reqCtx.ContainerOwner, Role: nativeSchemaRole(reqCtx.Role), BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), + XHeaders: meta.GetXHeaders(), } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -204,6 +209,11 @@ type patchStreamBasicChecker struct { } func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin + } + if !p.nonFirstSend { p.nonFirstSend = true @@ -226,7 +236,7 @@ func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.Pa ContainerOwner: reqCtx.ContainerOwner, Role: nativeSchemaRole(reqCtx.Role), BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), + XHeaders: meta.GetXHeaders(), } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -251,6 +261,11 @@ func (c *Service) Patch(ctx context.Context) (objectSvc.PatchObjectStream, error } func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin + } + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { return nil, err @@ -295,7 +310,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), + XHeaders: meta.GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -304,6 +319,11 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.SearchStream) error { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin + } + var cnrID cid.ID if cnrV2 := request.GetBody().GetContainerID(); cnrV2 != nil { if err := cnrID.ReadFromV2(*cnrV2); err != nil { @@ -324,7 +344,7 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), + XHeaders: meta.GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -334,6 +354,11 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc } func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) (*objectV2.DeleteResponse, error) { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin + } + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { return nil, err @@ -353,7 +378,7 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), + XHeaders: meta.GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -368,6 +393,11 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( } func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.GetObjectRangeStream) error { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin + } + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { return toStatusErr(err) @@ -387,7 +417,7 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), + XHeaders: meta.GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -397,6 +427,11 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G } func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin + } + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { return nil, err @@ -416,7 +451,7 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), + XHeaders: meta.GetXHeaders(), } resp, err := c.next.GetRangeHash(ctx, request) @@ -431,6 +466,11 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa } func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequest) (*objectV2.PutSingleResponse, error) { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin + } + cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetObject().GetHeader().GetContainerID(), request.GetBody().GetObject().GetObjectID()) if err != nil { return nil, err @@ -451,7 +491,7 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ SenderKey: hex.EncodeToString(reqCtx.SenderKey), ContainerOwner: reqCtx.ContainerOwner, BearerToken: reqCtx.BearerToken, - XHeaders: request.GetMetaHeader().GetXHeaders(), + XHeaders: meta.GetXHeaders(), } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { From 4d5ae59a52e7ab0ce89e2c5cc1f9c6c88a193de2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 13 Jan 2025 16:55:43 +0300 Subject: [PATCH 1140/1413] [#1598] golangci: Enable unconvert linters To drop unnecessary conversions. Signed-off-by: Dmitrii Stepanov --- .golangci.yml | 1 + cmd/frostfs-cli/modules/bearer/generate_override.go | 2 +- cmd/frostfs-node/config.go | 4 ++-- cmd/frostfs-node/config/node/config.go | 4 ++-- cmd/frostfs-node/netmap.go | 2 +- .../blobstor/fstree/fstree_write_generic.go | 2 +- .../blobstor/fstree/fstree_write_linux.go | 2 +- pkg/local_object_storage/blobstor/memstore/memstore.go | 4 ++-- pkg/local_object_storage/engine/evacuate.go | 2 +- pkg/local_object_storage/engine/shards.go | 4 ++-- pkg/local_object_storage/shard/control.go | 2 +- pkg/morph/event/netmap/epoch.go | 2 +- pkg/services/object/put/v2/streamer.go | 2 +- 13 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 57e3b44941..d0e45aa75f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -89,5 +89,6 @@ linters: - protogetter - intrange - tenv + - unconvert disable-all: true fast: false diff --git a/cmd/frostfs-cli/modules/bearer/generate_override.go b/cmd/frostfs-cli/modules/bearer/generate_override.go index 13fe079959..9632061f1e 100644 --- a/cmd/frostfs-cli/modules/bearer/generate_override.go +++ b/cmd/frostfs-cli/modules/bearer/generate_override.go @@ -52,7 +52,7 @@ func genereateAPEOverride(cmd *cobra.Command, _ []string) { outputPath, _ := cmd.Flags().GetString(outputFlag) if outputPath != "" { - err := os.WriteFile(outputPath, []byte(overrideMarshalled), 0o644) + err := os.WriteFile(outputPath, overrideMarshalled, 0o644) commonCmd.ExitOnErr(cmd, "dump error: %w", err) } else { fmt.Print("\n") diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 18d3e24541..3392589bf0 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -853,8 +853,8 @@ func initFrostfsID(appCfg *config.Config) cfgFrostfsID { } func initCfgGRPC() cfgGRPC { - maxChunkSize := uint64(maxMsgSize) * 3 / 4 // 25% to meta, 75% to payload - maxAddrAmount := uint64(maxChunkSize) / addressSize // each address is about 72 bytes + maxChunkSize := uint64(maxMsgSize) * 3 / 4 // 25% to meta, 75% to payload + maxAddrAmount := maxChunkSize / addressSize // each address is about 72 bytes return cfgGRPC{ maxChunkSize: maxChunkSize, diff --git a/cmd/frostfs-node/config/node/config.go b/cmd/frostfs-node/config/node/config.go index 4d063245b2..969d773964 100644 --- a/cmd/frostfs-node/config/node/config.go +++ b/cmd/frostfs-node/config/node/config.go @@ -198,7 +198,7 @@ func (l PersistentPolicyRulesConfig) Path() string { // // Returns PermDefault if the value is not a positive number. func (l PersistentPolicyRulesConfig) Perm() fs.FileMode { - p := config.UintSafe((*config.Config)(l.cfg), "perm") + p := config.UintSafe(l.cfg, "perm") if p == 0 { p = PermDefault } @@ -210,7 +210,7 @@ func (l PersistentPolicyRulesConfig) Perm() fs.FileMode { // // Returns false if the value is not a boolean. func (l PersistentPolicyRulesConfig) NoSync() bool { - return config.BoolSafe((*config.Config)(l.cfg), "no_sync") + return config.BoolSafe(l.cfg, "no_sync") } // CompatibilityMode returns true if need to run node in compatibility with previous versions mode. diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index a26fdd7989..34cd00ac8a 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -86,7 +86,7 @@ func (s *networkState) setNodeInfo(ni *netmapSDK.NodeInfo) { } } - s.setControlNetmapStatus(control.NetmapStatus(ctrlNetSt)) + s.setControlNetmapStatus(ctrlNetSt) } // sets the current node state to the given value. Subsequent cfg.bootstrap diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 4110ba7d74..07a618b0ac 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -136,6 +136,6 @@ func (w *genericWriter) removeWithCounter(p string, size uint64) error { if err := os.Remove(p); err != nil { return err } - w.fileCounter.Dec(uint64(size)) + w.fileCounter.Dec(size) return nil } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index 3561c616b8..c62654028e 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -114,7 +114,7 @@ func (w *linuxWriter) removeFile(p string, size uint64) error { return logicerr.Wrap(new(apistatus.ObjectNotFound)) } if err == nil { - w.fileCounter.Dec(uint64(size)) + w.fileCounter.Dec(size) } return err } diff --git a/pkg/local_object_storage/blobstor/memstore/memstore.go b/pkg/local_object_storage/blobstor/memstore/memstore.go index 3afef7d186..7ef7e37a40 100644 --- a/pkg/local_object_storage/blobstor/memstore/memstore.go +++ b/pkg/local_object_storage/blobstor/memstore/memstore.go @@ -133,11 +133,11 @@ func (s *memstoreImpl) Iterate(_ context.Context, req common.IteratePrm) (common elem := common.IterationElement{ ObjectData: v, } - if err := elem.Address.DecodeString(string(k)); err != nil { + if err := elem.Address.DecodeString(k); err != nil { if req.IgnoreErrors { continue } - return common.IterateRes{}, logicerr.Wrap(fmt.Errorf("(%T) decoding address string %q: %v", s, string(k), err)) + return common.IterateRes{}, logicerr.Wrap(fmt.Errorf("(%T) decoding address string %q: %v", s, k, err)) } var err error if elem.ObjectData, err = s.compression.Decompress(elem.ObjectData); err != nil { diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 623f5c9416..682f23dff3 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -724,7 +724,7 @@ func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) shards := make([]pooledShard, 0, len(e.shards)) for id := range e.shards { shards = append(shards, pooledShard{ - hashedShard: hashedShard(e.shards[id]), + hashedShard: e.shards[id], pool: e.shardPools[id], }) } diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 6d4844b75a..8e191f72c4 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -272,7 +272,7 @@ func (e *StorageEngine) sortShards(objAddr interface{ EncodeToString() string }) h := hrw.StringHash(objAddr.EncodeToString()) shards := make([]hashedShard, 0, len(e.shards)) for _, sh := range e.shards { - shards = append(shards, hashedShard(sh)) + shards = append(shards, sh) } hrw.SortHasherSliceByValue(shards, h) return shards @@ -285,7 +285,7 @@ func (e *StorageEngine) unsortedShards() []hashedShard { shards := make([]hashedShard, 0, len(e.shards)) for _, sh := range e.shards { - shards = append(shards, hashedShard(sh)) + shards = append(shards, sh) } return shards diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 1c1933af53..3136ddfcc8 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -38,7 +38,7 @@ func (s *Shard) handleMetabaseFailure(ctx context.Context, stage string, err err err = s.SetMode(ctx, mode.DegradedReadOnly) if err != nil { - return fmt.Errorf("switch to mode %s", mode.Mode(mode.DegradedReadOnly)) + return fmt.Errorf("switch to mode %s", mode.DegradedReadOnly) } return nil } diff --git a/pkg/morph/event/netmap/epoch.go b/pkg/morph/event/netmap/epoch.go index 4dcc0d0350..39c8f62371 100644 --- a/pkg/morph/event/netmap/epoch.go +++ b/pkg/morph/event/netmap/epoch.go @@ -41,7 +41,7 @@ func ParseNewEpoch(e *state.ContainedNotificationEvent) (event.Event, error) { } return NewEpoch{ - Num: uint64(nee.Epoch.Uint64()), + Num: nee.Epoch.Uint64(), Hash: e.Container, }, nil } diff --git a/pkg/services/object/put/v2/streamer.go b/pkg/services/object/put/v2/streamer.go index 36b514fbcb..1cd10cd7f6 100644 --- a/pkg/services/object/put/v2/streamer.go +++ b/pkg/services/object/put/v2/streamer.go @@ -59,7 +59,7 @@ func (s *streamer) Send(ctx context.Context, req *object.PutRequest) (err error) maxSz := s.stream.MaxSizeSrc.MaxObjectSize() s.sizes = &sizes{ - payloadSz: uint64(v.GetHeader().GetPayloadLength()), + payloadSz: v.GetHeader().GetPayloadLength(), } // check payload size limit overflow From fb928616ccade3c704dd98dccd7f2e521d27e5c5 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 13 Jan 2025 17:43:39 +0300 Subject: [PATCH 1141/1413] [#1598] golangci: Enable unparam linter To drop unnecessary parameters and return values. Signed-off-by: Dmitrii Stepanov --- .golangci.yml | 1 + .../modules/morph/frostfsid/frostfsid.go | 16 +++++----- .../modules/container/policy_playground.go | 7 ++--- cmd/frostfs-lens/internal/tui/buckets.go | 18 ++++------- cmd/frostfs-lens/internal/tui/db.go | 31 +++++++------------ cmd/frostfs-lens/internal/tui/records.go | 8 ++--- cmd/frostfs-node/config.go | 13 +++----- internal/logs/logs.go | 2 -- pkg/innerring/initialization.go | 6 ++-- pkg/innerring/locode.go | 4 +-- .../blobstor/blobovniczatree/delete.go | 17 +++++----- .../blobstor/blobovniczatree/iterate.go | 6 ++++ pkg/local_object_storage/engine/container.go | 14 ++++----- pkg/local_object_storage/engine/delete.go | 6 ++-- pkg/local_object_storage/engine/inhume.go | 10 +++--- pkg/local_object_storage/engine/select.go | 18 +++++------ .../metabase/containers.go | 13 ++++---- pkg/local_object_storage/metabase/counter.go | 4 +-- pkg/local_object_storage/metabase/delete.go | 6 ++-- pkg/local_object_storage/metabase/inhume.go | 4 +-- .../metabase/storage_id.go | 18 +++++------ pkg/local_object_storage/pilorama/boltdb.go | 22 +++++-------- pkg/local_object_storage/writecache/cache.go | 3 +- pkg/local_object_storage/writecache/state.go | 3 +- pkg/morph/event/listener.go | 19 +++--------- .../object_manager/placement/traverser.go | 9 ++---- 26 files changed, 123 insertions(+), 155 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d0e45aa75f..d83f36de8c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -90,5 +90,6 @@ linters: - intrange - tenv - unconvert + - unparam disable-all: true fast: false diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index db98bb8ad4..b229d04368 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -253,7 +253,7 @@ func frostfsidListNamespaces(cmd *cobra.Command, _ []string) { reader := frostfsidrpclient.NewReader(inv, hash) sessionID, it, err := reader.ListNamespaces() commonCmd.ExitOnErr(cmd, "can't get namespace: %w", err) - items, err := readIterator(inv, &it, iteratorBatchSize, sessionID) + items, err := readIterator(inv, &it, sessionID) commonCmd.ExitOnErr(cmd, "can't read iterator: %w", err) namespaces, err := frostfsidclient.ParseNamespaces(items) @@ -305,7 +305,7 @@ func frostfsidListSubjects(cmd *cobra.Command, _ []string) { sessionID, it, err := reader.ListNamespaceSubjects(ns) commonCmd.ExitOnErr(cmd, "can't get namespace: %w", err) - subAddresses, err := frostfsidclient.UnwrapArrayOfUint160(readIterator(inv, &it, iteratorBatchSize, sessionID)) + subAddresses, err := frostfsidclient.UnwrapArrayOfUint160(readIterator(inv, &it, sessionID)) commonCmd.ExitOnErr(cmd, "can't unwrap: %w", err) sort.Slice(subAddresses, func(i, j int) bool { return subAddresses[i].Less(subAddresses[j]) }) @@ -319,7 +319,7 @@ func frostfsidListSubjects(cmd *cobra.Command, _ []string) { sessionID, it, err := reader.ListSubjects() commonCmd.ExitOnErr(cmd, "can't get subject: %w", err) - items, err := readIterator(inv, &it, iteratorBatchSize, sessionID) + items, err := readIterator(inv, &it, sessionID) commonCmd.ExitOnErr(cmd, "can't read iterator: %w", err) subj, err := frostfsidclient.ParseSubject(items) @@ -365,7 +365,7 @@ func frostfsidListGroups(cmd *cobra.Command, _ []string) { sessionID, it, err := reader.ListGroups(ns) commonCmd.ExitOnErr(cmd, "can't get namespace: %w", err) - items, err := readIterator(inv, &it, iteratorBatchSize, sessionID) + items, err := readIterator(inv, &it, sessionID) commonCmd.ExitOnErr(cmd, "can't list groups: %w", err) groups, err := frostfsidclient.ParseGroups(items) commonCmd.ExitOnErr(cmd, "can't parse groups: %w", err) @@ -415,7 +415,7 @@ func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { sessionID, it, err := reader.ListGroupSubjects(ns, big.NewInt(groupID)) commonCmd.ExitOnErr(cmd, "can't list groups: %w", err) - items, err := readIterator(inv, &it, iteratorBatchSize, sessionID) + items, err := readIterator(inv, &it, sessionID) commonCmd.ExitOnErr(cmd, "can't read iterator: %w", err) subjects, err := frostfsidclient.UnwrapArrayOfUint160(items, err) @@ -492,17 +492,17 @@ func (f *frostfsidClient) sendWaitRes() (*state.AppExecResult, error) { return f.roCli.Wait(f.wCtx.SentTxs[0].Hash, f.wCtx.SentTxs[0].Vub, nil) } -func readIterator(inv *invoker.Invoker, iter *result.Iterator, batchSize int, sessionID uuid.UUID) ([]stackitem.Item, error) { +func readIterator(inv *invoker.Invoker, iter *result.Iterator, sessionID uuid.UUID) ([]stackitem.Item, error) { var shouldStop bool res := make([]stackitem.Item, 0) for !shouldStop { - items, err := inv.TraverseIterator(sessionID, iter, batchSize) + items, err := inv.TraverseIterator(sessionID, iter, iteratorBatchSize) if err != nil { return nil, err } res = append(res, items...) - shouldStop = len(items) < batchSize + shouldStop = len(items) < iteratorBatchSize } return res, nil diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 40bd4110ba..dcd755510d 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -23,11 +23,11 @@ type policyPlaygroundREPL struct { nodes map[string]netmap.NodeInfo } -func newPolicyPlaygroundREPL(cmd *cobra.Command) (*policyPlaygroundREPL, error) { +func newPolicyPlaygroundREPL(cmd *cobra.Command) *policyPlaygroundREPL { return &policyPlaygroundREPL{ cmd: cmd, nodes: map[string]netmap.NodeInfo{}, - }, nil + } } func (repl *policyPlaygroundREPL) handleLs(args []string) error { @@ -246,8 +246,7 @@ var policyPlaygroundCmd = &cobra.Command{ Long: `A REPL for testing placement policies. If a wallet and endpoint is provided, the initial netmap data will be loaded from the snapshot of the node. Otherwise, an empty playground is created.`, Run: func(cmd *cobra.Command, _ []string) { - repl, err := newPolicyPlaygroundREPL(cmd) - commonCmd.ExitOnErr(cmd, "could not create policy playground: %w", err) + repl := newPolicyPlaygroundREPL(cmd) commonCmd.ExitOnErr(cmd, "policy playground failed: %w", repl.run()) }, } diff --git a/cmd/frostfs-lens/internal/tui/buckets.go b/cmd/frostfs-lens/internal/tui/buckets.go index 3f5088e7ab..2d3b207926 100644 --- a/cmd/frostfs-lens/internal/tui/buckets.go +++ b/cmd/frostfs-lens/internal/tui/buckets.go @@ -124,10 +124,7 @@ func (v *BucketsView) loadNodeChildren( path := parentBucket.Path parser := parentBucket.NextParser - buffer, err := LoadBuckets(ctx, v.ui.db, path, v.ui.loadBufferSize) - if err != nil { - return err - } + buffer := LoadBuckets(ctx, v.ui.db, path, v.ui.loadBufferSize) for item := range buffer { if item.err != nil { @@ -135,6 +132,7 @@ func (v *BucketsView) loadNodeChildren( } bucket := item.val + var err error bucket.Entry, bucket.NextParser, err = parser(bucket.Name, nil) if err != nil { return err @@ -180,10 +178,7 @@ func (v *BucketsView) bucketSatisfiesFilter( defer cancel() // Check the current bucket's nested buckets if exist - bucketsBuffer, err := LoadBuckets(ctx, v.ui.db, bucket.Path, v.ui.loadBufferSize) - if err != nil { - return false, err - } + bucketsBuffer := LoadBuckets(ctx, v.ui.db, bucket.Path, v.ui.loadBufferSize) for item := range bucketsBuffer { if item.err != nil { @@ -191,6 +186,7 @@ func (v *BucketsView) bucketSatisfiesFilter( } b := item.val + var err error b.Entry, b.NextParser, err = bucket.NextParser(b.Name, nil) if err != nil { return false, err @@ -206,10 +202,7 @@ func (v *BucketsView) bucketSatisfiesFilter( } // Check the current bucket's nested records if exist - recordsBuffer, err := LoadRecords(ctx, v.ui.db, bucket.Path, v.ui.loadBufferSize) - if err != nil { - return false, err - } + recordsBuffer := LoadRecords(ctx, v.ui.db, bucket.Path, v.ui.loadBufferSize) for item := range recordsBuffer { if item.err != nil { @@ -217,6 +210,7 @@ func (v *BucketsView) bucketSatisfiesFilter( } r := item.val + var err error r.Entry, _, err = bucket.NextParser(r.Key, r.Value) if err != nil { return false, err diff --git a/cmd/frostfs-lens/internal/tui/db.go b/cmd/frostfs-lens/internal/tui/db.go index d0cf611d48..94fa87f982 100644 --- a/cmd/frostfs-lens/internal/tui/db.go +++ b/cmd/frostfs-lens/internal/tui/db.go @@ -35,7 +35,7 @@ func resolvePath(tx *bbolt.Tx, path [][]byte) (*bbolt.Bucket, error) { func load[T any]( ctx context.Context, db *bbolt.DB, path [][]byte, bufferSize int, filter func(key, value []byte) bool, transform func(key, value []byte) T, -) (<-chan Item[T], error) { +) <-chan Item[T] { buffer := make(chan Item[T], bufferSize) go func() { @@ -77,13 +77,13 @@ func load[T any]( } }() - return buffer, nil + return buffer } func LoadBuckets( ctx context.Context, db *bbolt.DB, path [][]byte, bufferSize int, -) (<-chan Item[*Bucket], error) { - buffer, err := load( +) <-chan Item[*Bucket] { + buffer := load( ctx, db, path, bufferSize, func(_, value []byte) bool { return value == nil @@ -98,17 +98,14 @@ func LoadBuckets( } }, ) - if err != nil { - return nil, fmt.Errorf("can't start iterating bucket: %w", err) - } - return buffer, nil + return buffer } func LoadRecords( ctx context.Context, db *bbolt.DB, path [][]byte, bufferSize int, -) (<-chan Item[*Record], error) { - buffer, err := load( +) <-chan Item[*Record] { + buffer := load( ctx, db, path, bufferSize, func(_, value []byte) bool { return value != nil @@ -124,11 +121,8 @@ func LoadRecords( } }, ) - if err != nil { - return nil, fmt.Errorf("can't start iterating bucket: %w", err) - } - return buffer, nil + return buffer } // HasBuckets checks if a bucket has nested buckets. It relies on assumption @@ -137,24 +131,21 @@ func HasBuckets(ctx context.Context, db *bbolt.DB, path [][]byte) (bool, error) ctx, cancel := context.WithCancel(ctx) defer cancel() - buffer, err := load( + buffer := load( ctx, db, path, 1, nil, func(_, value []byte) []byte { return value }, ) - if err != nil { - return false, err - } x, ok := <-buffer if !ok { return false, nil } if x.err != nil { - return false, err + return false, x.err } if x.val != nil { - return false, err + return false, nil } return true, nil } diff --git a/cmd/frostfs-lens/internal/tui/records.go b/cmd/frostfs-lens/internal/tui/records.go index 5f53ed287b..5f61df8841 100644 --- a/cmd/frostfs-lens/internal/tui/records.go +++ b/cmd/frostfs-lens/internal/tui/records.go @@ -62,10 +62,7 @@ func (v *RecordsView) Mount(ctx context.Context) error { ctx, v.onUnmount = context.WithCancel(ctx) - tempBuffer, err := LoadRecords(ctx, v.ui.db, v.bucket.Path, v.ui.loadBufferSize) - if err != nil { - return err - } + tempBuffer := LoadRecords(ctx, v.ui.db, v.bucket.Path, v.ui.loadBufferSize) v.buffer = make(chan *Record, v.ui.loadBufferSize) go func() { @@ -73,11 +70,12 @@ func (v *RecordsView) Mount(ctx context.Context) error { for item := range tempBuffer { if item.err != nil { - v.ui.stopOnError(err) + v.ui.stopOnError(item.err) break } record := item.val + var err error record.Entry, _, err = v.bucket.NextParser(record.Key, record.Value) if err != nil { v.ui.stopOnError(err) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 3392589bf0..9931d0dc8c 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -698,8 +698,7 @@ func initCfg(appCfg *config.Config) *cfg { netState.metrics = c.metricsCollector - logPrm, err := c.loggerPrm() - fatalOnErr(err) + logPrm := c.loggerPrm() logPrm.SamplingHook = c.metricsCollector.LogMetrics().GetSamplingHook() log, err := logger.NewLogger(logPrm) fatalOnErr(err) @@ -1059,7 +1058,7 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID return sh } -func (c *cfg) loggerPrm() (*logger.Prm, error) { +func (c *cfg) loggerPrm() *logger.Prm { // check if it has been inited before if c.dynamicConfiguration.logger == nil { c.dynamicConfiguration.logger = new(logger.Prm) @@ -1078,7 +1077,7 @@ func (c *cfg) loggerPrm() (*logger.Prm, error) { } c.dynamicConfiguration.logger.PrependTimestamp = c.LoggerCfg.timestamp - return c.dynamicConfiguration.logger, nil + return c.dynamicConfiguration.logger } func (c *cfg) LocalAddress() network.AddressGroup { @@ -1334,11 +1333,7 @@ func (c *cfg) reloadConfig(ctx context.Context) { // Logger - logPrm, err := c.loggerPrm() - if err != nil { - c.log.Error(ctx, logs.FrostFSNodeLoggerConfigurationPreparation, zap.Error(err)) - return - } + logPrm := c.loggerPrm() components := c.getComponents(ctx, logPrm) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index b24f3593dd..0610dc1751 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -146,7 +146,6 @@ const ( ClientCantGetBlockchainHeight = "can't get blockchain height" ClientCantGetBlockchainHeight243 = "can't get blockchain height" EventCouldNotSubmitHandlerToWorkerPool = "could not Submit handler to worker pool" - EventCouldNotStartListenToEvents = "could not start listen to events" EventStopEventListenerByError = "stop event listener by error" EventStopEventListenerByContext = "stop event listener by context" EventStopEventListenerByNotificationChannel = "stop event listener by notification channel" @@ -384,7 +383,6 @@ const ( FrostFSNodeShutdownSkip = "node is already shutting down, skipped shutdown" FrostFSNodeShutdownWhenNotReady = "node is going to shut down when subsystems are still initializing" FrostFSNodeConfigurationReading = "configuration reading" - FrostFSNodeLoggerConfigurationPreparation = "logger configuration preparation" FrostFSNodeTracingConfigationUpdated = "tracing configation updated" FrostFSNodeStorageEngineConfigurationUpdate = "storage engine configuration update" FrostFSNodePoolConfigurationUpdate = "adjust pool configuration" diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index ecaf8ae866..f7b71dbe6f 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -38,10 +38,7 @@ import ( func (s *Server) initNetmapProcessor(ctx context.Context, cfg *viper.Viper, alphaSync event.Handler, ) error { - locodeValidator, err := s.newLocodeValidator(cfg) - if err != nil { - return err - } + locodeValidator := s.newLocodeValidator(cfg) netSettings := (*networkSettings)(s.netmapClient) @@ -51,6 +48,7 @@ func (s *Server) initNetmapProcessor(ctx context.Context, cfg *viper.Viper, poolSize := cfg.GetInt("workers.netmap") s.log.Debug(ctx, logs.NetmapNetmapWorkerPool, zap.Int("size", poolSize)) + var err error s.netmapProcessor, err = netmap.New(&netmap.Params{ Log: s.log, Metrics: s.irMetrics, diff --git a/pkg/innerring/locode.go b/pkg/innerring/locode.go index a0c3ea7518..ae4c851681 100644 --- a/pkg/innerring/locode.go +++ b/pkg/innerring/locode.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/viper" ) -func (s *Server) newLocodeValidator(cfg *viper.Viper) (netmap.NodeValidator, error) { +func (s *Server) newLocodeValidator(cfg *viper.Viper) netmap.NodeValidator { locodeDB := locodebolt.New(locodebolt.Prm{ Path: cfg.GetString("locode.db.path"), }, @@ -21,7 +21,7 @@ func (s *Server) newLocodeValidator(cfg *viper.Viper) (netmap.NodeValidator, err return irlocode.New(irlocode.Prm{ DB: (*locodeBoltDBWrapper)(locodeDB), - }), nil + }) } type locodeBoltEntryWrapper struct { diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 47e12bafbc..8d17fc4b0e 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -19,7 +19,10 @@ import ( "go.uber.org/zap" ) -var errObjectIsDeleteProtected = errors.New("object is delete protected") +var ( + errObjectIsDeleteProtected = errors.New("object is delete protected") + deleteRes = common.DeleteRes{} +) // Delete deletes object from blobovnicza tree. // @@ -43,17 +46,17 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co defer span.End() if b.readOnly { - return common.DeleteRes{}, common.ErrReadOnly + return deleteRes, common.ErrReadOnly } if b.rebuildGuard.TryRLock() { defer b.rebuildGuard.RUnlock() } else { - return common.DeleteRes{}, errRebuildInProgress + return deleteRes, errRebuildInProgress } if b.deleteProtectedObjects.Contains(prm.Address) { - return common.DeleteRes{}, errObjectIsDeleteProtected + return deleteRes, errObjectIsDeleteProtected } var bPrm blobovnicza.DeletePrm @@ -98,7 +101,7 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co if err == nil && !objectFound { // not found in any blobovnicza - return common.DeleteRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) + return deleteRes, logicerr.Wrap(new(apistatus.ObjectNotFound)) } success = err == nil @@ -112,7 +115,7 @@ func (b *Blobovniczas) deleteObjectFromLevel(ctx context.Context, prm blobovnicz shBlz := b.getBlobovnicza(ctx, blzPath) blz, err := shBlz.Open(ctx) if err != nil { - return common.DeleteRes{}, err + return deleteRes, err } defer shBlz.Close(ctx) @@ -122,5 +125,5 @@ func (b *Blobovniczas) deleteObjectFromLevel(ctx context.Context, prm blobovnicz // removes object from blobovnicza and returns common.DeleteRes. func (b *Blobovniczas) deleteObject(ctx context.Context, blz *blobovnicza.Blobovnicza, prm blobovnicza.DeletePrm) (common.DeleteRes, error) { _, err := blz.Delete(ctx, prm) - return common.DeleteRes{}, err + return deleteRes, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go index 5c2d58ca15..ceb8fb7e3b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/iterate.go @@ -249,6 +249,12 @@ func (b *Blobovniczas) iterateSortedDBPaths(ctx context.Context, addr oid.Addres } func (b *Blobovniczas) iterateSordedDBPathsInternal(ctx context.Context, path string, addr oid.Address, f func(string) (bool, error)) (bool, error) { + select { + case <-ctx.Done(): + return false, ctx.Err() + default: + } + sysPath := filepath.Join(b.rootPath, path) entries, err := os.ReadDir(sysPath) if os.IsNotExist(err) && b.readOnly && path == "" { // non initialized tree in read only mode diff --git a/pkg/local_object_storage/engine/container.go b/pkg/local_object_storage/engine/container.go index 24059a3f90..b2d7a1037a 100644 --- a/pkg/local_object_storage/engine/container.go +++ b/pkg/local_object_storage/engine/container.go @@ -48,8 +48,8 @@ func (e *StorageEngine) ContainerSize(ctx context.Context, prm ContainerSizePrm) defer elapsed("ContainerSize", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res, err = e.containerSize(ctx, prm) - return err + res = e.containerSize(ctx, prm) + return nil }) return @@ -69,7 +69,7 @@ func ContainerSize(ctx context.Context, e *StorageEngine, id cid.ID) (uint64, er return res.Size(), nil } -func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) (res ContainerSizeRes, err error) { +func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) (res ContainerSizeRes) { e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { var csPrm shard.ContainerSizePrm csPrm.SetContainerID(prm.cnr) @@ -96,8 +96,8 @@ func (e *StorageEngine) ListContainers(ctx context.Context, _ ListContainersPrm) defer elapsed("ListContainers", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res, err = e.listContainers(ctx) - return err + res = e.listContainers(ctx) + return nil }) return @@ -115,7 +115,7 @@ func ListContainers(ctx context.Context, e *StorageEngine) ([]cid.ID, error) { return res.Containers(), nil } -func (e *StorageEngine) listContainers(ctx context.Context) (ListContainersRes, error) { +func (e *StorageEngine) listContainers(ctx context.Context) ListContainersRes { uniqueIDs := make(map[string]cid.ID) e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { @@ -142,5 +142,5 @@ func (e *StorageEngine) listContainers(ctx context.Context) (ListContainersRes, return ListContainersRes{ containers: result, - }, nil + } } diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 65ccbdb9ec..c735cc41dc 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -27,6 +27,8 @@ type DeletePrm struct { // DeleteRes groups the resulting values of Delete operation. type DeleteRes struct{} +var deleteRes = DeleteRes{} + // WithAddress is a Delete option to set the addresses of the objects to delete. // // Option is required. @@ -126,14 +128,14 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e }) if locked.is { - return DeleteRes{}, new(apistatus.ObjectLocked) + return deleteRes, new(apistatus.ObjectLocked) } if splitInfo != nil { e.deleteChildren(ctx, prm.addr, prm.forceRemoval, splitInfo.SplitID()) } - return DeleteRes{}, nil + return deleteRes, nil } func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, force bool, splitID *objectSDK.SplitID) { diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index bae7840646..a0c38cd5d8 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -30,6 +30,8 @@ type InhumePrm struct { // InhumeRes encapsulates results of inhume operation. type InhumeRes struct{} +var inhumeRes = InhumeRes{} + // WithTarget sets a list of objects that should be inhumed and tombstone address // as the reason for inhume operation. // @@ -83,7 +85,7 @@ func (e *StorageEngine) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRe func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { addrsPerShard, err := e.groupObjectsByShard(ctx, prm.addrs, !prm.forceRemoval) if err != nil { - return InhumeRes{}, err + return inhumeRes, err } var shPrm shard.InhumePrm @@ -107,7 +109,7 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, e zap.String("shard_id", shardID), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) - return InhumeRes{}, errInhumeFailure + return inhumeRes, errInhumeFailure } if _, err := sh.Inhume(ctx, shPrm); err != nil { @@ -119,11 +121,11 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, e default: e.reportShardError(ctx, sh, "couldn't inhume object in shard", err) } - return InhumeRes{}, err + return inhumeRes, err } } - return InhumeRes{}, nil + return inhumeRes, nil } // groupObjectsByShard groups objects based on the shard(s) they are stored on. diff --git a/pkg/local_object_storage/engine/select.go b/pkg/local_object_storage/engine/select.go index 02149b4c8b..fc8b4a9a72 100644 --- a/pkg/local_object_storage/engine/select.go +++ b/pkg/local_object_storage/engine/select.go @@ -54,19 +54,17 @@ func (e *StorageEngine) Select(ctx context.Context, prm SelectPrm) (res SelectRe defer elapsed("Select", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res, err = e._select(ctx, prm) - return err + res = e._select(ctx, prm) + return nil }) return } -func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, error) { +func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) SelectRes { addrList := make([]oid.Address, 0) uniqueMap := make(map[string]struct{}) - var outError error - var shPrm shard.SelectPrm shPrm.SetContainerID(prm.cnr, prm.indexedContainer) shPrm.SetFilters(prm.filters) @@ -90,7 +88,7 @@ func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, return SelectRes{ addrList: addrList, - }, outError + } } // List returns `limit` available physically storage object addresses in engine. @@ -100,14 +98,14 @@ func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, func (e *StorageEngine) List(ctx context.Context, limit uint64) (res SelectRes, err error) { defer elapsed("List", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res, err = e.list(ctx, limit) - return err + res = e.list(ctx, limit) + return nil }) return } -func (e *StorageEngine) list(ctx context.Context, limit uint64) (SelectRes, error) { +func (e *StorageEngine) list(ctx context.Context, limit uint64) SelectRes { addrList := make([]oid.Address, 0, limit) uniqueMap := make(map[string]struct{}) ln := uint64(0) @@ -136,7 +134,7 @@ func (e *StorageEngine) list(ctx context.Context, limit uint64) (SelectRes, erro return SelectRes{ addrList: addrList, - }, nil + } } // Select selects objects from local storage using provided filters. diff --git a/pkg/local_object_storage/metabase/containers.go b/pkg/local_object_storage/metabase/containers.go index 472b2affc1..da27e6085a 100644 --- a/pkg/local_object_storage/metabase/containers.go +++ b/pkg/local_object_storage/metabase/containers.go @@ -56,7 +56,7 @@ func (db *DB) containers(tx *bbolt.Tx) ([]cid.ID, error) { return result, err } -func (db *DB) ContainerSize(id cid.ID) (size uint64, err error) { +func (db *DB) ContainerSize(id cid.ID) (uint64, error) { db.modeMtx.RLock() defer db.modeMtx.RUnlock() @@ -64,21 +64,22 @@ func (db *DB) ContainerSize(id cid.ID) (size uint64, err error) { return 0, ErrDegradedMode } - err = db.boltDB.View(func(tx *bbolt.Tx) error { - size, err = db.containerSize(tx, id) + var size uint64 + err := db.boltDB.View(func(tx *bbolt.Tx) error { + size = db.containerSize(tx, id) - return err + return nil }) return size, metaerr.Wrap(err) } -func (db *DB) containerSize(tx *bbolt.Tx, id cid.ID) (uint64, error) { +func (db *DB) containerSize(tx *bbolt.Tx, id cid.ID) uint64 { containerVolume := tx.Bucket(containerVolumeBucketName) key := make([]byte, cidSize) id.Encode(key) - return parseContainerSize(containerVolume.Get(key)), nil + return parseContainerSize(containerVolume.Get(key)) } func parseContainerID(dst *cid.ID, name []byte, ignore map[string]struct{}) bool { diff --git a/pkg/local_object_storage/metabase/counter.go b/pkg/local_object_storage/metabase/counter.go index f29dafe77c..732f99519e 100644 --- a/pkg/local_object_storage/metabase/counter.go +++ b/pkg/local_object_storage/metabase/counter.go @@ -251,13 +251,13 @@ func (db *DB) incCounters(tx *bbolt.Tx, cnrID cid.ID, isUserObject bool) error { return db.incContainerObjectCounter(tx, cnrID, isUserObject) } -func (db *DB) updateShardObjectCounter(tx *bbolt.Tx, typ objectType, delta uint64, inc bool) error { +func (db *DB) decShardObjectCounter(tx *bbolt.Tx, typ objectType, delta uint64) error { b := tx.Bucket(shardInfoBucket) if b == nil { return nil } - return db.updateShardObjectCounterBucket(b, typ, delta, inc) + return db.updateShardObjectCounterBucket(b, typ, delta, false) } func (*DB) updateShardObjectCounterBucket(b *bbolt.Bucket, typ objectType, delta uint64, inc bool) error { diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index 00ee2baa36..d338e228ff 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -161,21 +161,21 @@ func (db *DB) deleteGroup(tx *bbolt.Tx, addrs []oid.Address) (DeleteRes, error) func (db *DB) updateCountersDelete(tx *bbolt.Tx, res DeleteRes) error { if res.phyCount > 0 { - err := db.updateShardObjectCounter(tx, phy, res.phyCount, false) + err := db.decShardObjectCounter(tx, phy, res.phyCount) if err != nil { return fmt.Errorf("decrease phy object counter: %w", err) } } if res.logicCount > 0 { - err := db.updateShardObjectCounter(tx, logical, res.logicCount, false) + err := db.decShardObjectCounter(tx, logical, res.logicCount) if err != nil { return fmt.Errorf("decrease logical object counter: %w", err) } } if res.userCount > 0 { - err := db.updateShardObjectCounter(tx, user, res.userCount, false) + err := db.decShardObjectCounter(tx, user, res.userCount) if err != nil { return fmt.Errorf("decrease user object counter: %w", err) } diff --git a/pkg/local_object_storage/metabase/inhume.go b/pkg/local_object_storage/metabase/inhume.go index 99fdec3102..76018fb611 100644 --- a/pkg/local_object_storage/metabase/inhume.go +++ b/pkg/local_object_storage/metabase/inhume.go @@ -342,10 +342,10 @@ func (db *DB) inhumeECInfo(tx *bbolt.Tx, epoch uint64, tomb *oid.Address, res *I } func (db *DB) applyInhumeResToCounters(tx *bbolt.Tx, res *InhumeRes) error { - if err := db.updateShardObjectCounter(tx, logical, res.LogicInhumed(), false); err != nil { + if err := db.decShardObjectCounter(tx, logical, res.LogicInhumed()); err != nil { return err } - if err := db.updateShardObjectCounter(tx, user, res.UserInhumed(), false); err != nil { + if err := db.decShardObjectCounter(tx, user, res.UserInhumed()); err != nil { return err } diff --git a/pkg/local_object_storage/metabase/storage_id.go b/pkg/local_object_storage/metabase/storage_id.go index 6d620b41a2..8f23765031 100644 --- a/pkg/local_object_storage/metabase/storage_id.go +++ b/pkg/local_object_storage/metabase/storage_id.go @@ -35,7 +35,7 @@ func (r StorageIDRes) StorageID() []byte { // StorageID returns storage descriptor for objects from the blobstor. // It is put together with the object can makes get/delete operation faster. -func (db *DB) StorageID(ctx context.Context, prm StorageIDPrm) (res StorageIDRes, err error) { +func (db *DB) StorageID(ctx context.Context, prm StorageIDPrm) (StorageIDRes, error) { var ( startedAt = time.Now() success = false @@ -53,32 +53,32 @@ func (db *DB) StorageID(ctx context.Context, prm StorageIDPrm) (res StorageIDRes db.modeMtx.RLock() defer db.modeMtx.RUnlock() + var res StorageIDRes if db.mode.NoMetabase() { return res, ErrDegradedMode } - err = db.boltDB.View(func(tx *bbolt.Tx) error { - res.id, err = db.storageID(tx, prm.addr) - - return err + err := db.boltDB.View(func(tx *bbolt.Tx) error { + res.id = db.storageID(tx, prm.addr) + return nil }) success = err == nil return res, metaerr.Wrap(err) } -func (db *DB) storageID(tx *bbolt.Tx, addr oid.Address) ([]byte, error) { +func (db *DB) storageID(tx *bbolt.Tx, addr oid.Address) []byte { key := make([]byte, bucketKeySize) smallBucket := tx.Bucket(smallBucketName(addr.Container(), key)) if smallBucket == nil { - return nil, nil + return nil } storageID := smallBucket.Get(objectKey(addr.Object(), key)) if storageID == nil { - return nil, nil + return nil } - return bytes.Clone(storageID), nil + return bytes.Clone(storageID) } // UpdateStorageIDPrm groups the parameters of UpdateStorageID operation. diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 86b19e3afe..1d55d1c139 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -419,10 +419,7 @@ func (t *boltForest) addByPathInternal(d CIDDescriptor, attr string, treeID stri return err } - i, node, err := t.getPathPrefix(bTree, attr, path) - if err != nil { - return err - } + i, node := t.getPathPrefix(bTree, attr, path) ts := t.getLatestTimestamp(bLog, d.Position, d.Size) lm = make([]Move, len(path)-i+1) @@ -980,10 +977,7 @@ func (t *boltForest) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID st b := treeRoot.Bucket(dataBucket) - i, curNodes, err := t.getPathPrefixMultiTraversal(b, attr, path[:len(path)-1]) - if err != nil { - return err - } + i, curNodes := t.getPathPrefixMultiTraversal(b, attr, path[:len(path)-1]) if i < len(path)-1 { return nil } @@ -1526,7 +1520,7 @@ func (t *boltForest) TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (* return &res, nil } -func (t *boltForest) getPathPrefixMultiTraversal(bTree *bbolt.Bucket, attr string, path []string) (int, []Node, error) { +func (t *boltForest) getPathPrefixMultiTraversal(bTree *bbolt.Bucket, attr string, path []string) (int, []Node) { c := bTree.Cursor() var curNodes []Node @@ -1549,14 +1543,14 @@ func (t *boltForest) getPathPrefixMultiTraversal(bTree *bbolt.Bucket, attr strin } if len(nextNodes) == 0 { - return i, curNodes, nil + return i, curNodes } } - return len(path), nextNodes, nil + return len(path), nextNodes } -func (t *boltForest) getPathPrefix(bTree *bbolt.Bucket, attr string, path []string) (int, Node, error) { +func (t *boltForest) getPathPrefix(bTree *bbolt.Bucket, attr string, path []string) (int, Node) { c := bTree.Cursor() var curNode Node @@ -1576,10 +1570,10 @@ loop: childKey, value = c.Next() } - return i, curNode, nil + return i, curNode } - return len(path), curNode, nil + return len(path), curNode } func (t *boltForest) moveFromBytes(m *Move, data []byte) error { diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index e829d013cc..b99d73d3a8 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -94,7 +94,8 @@ func (c *cache) Open(_ context.Context, mod mode.Mode) error { if err != nil { return metaerr.Wrap(err) } - return metaerr.Wrap(c.initCounters()) + c.initCounters() + return nil } // Init runs necessary services. diff --git a/pkg/local_object_storage/writecache/state.go b/pkg/local_object_storage/writecache/state.go index 835686fbbb..44caa26033 100644 --- a/pkg/local_object_storage/writecache/state.go +++ b/pkg/local_object_storage/writecache/state.go @@ -19,7 +19,6 @@ func (c *cache) hasEnoughSpace(objectSize uint64) bool { return c.maxCacheSize >= size+objectSize } -func (c *cache) initCounters() error { +func (c *cache) initCounters() { c.estimateCacheSize() - return nil } diff --git a/pkg/morph/event/listener.go b/pkg/morph/event/listener.go index 83f8bee078..e5cdfeef76 100644 --- a/pkg/morph/event/listener.go +++ b/pkg/morph/event/listener.go @@ -134,11 +134,8 @@ func (l *listener) Listen(ctx context.Context) { l.startOnce.Do(func() { l.wg.Add(1) defer l.wg.Done() - if err := l.listen(ctx, nil); err != nil { - l.log.Error(ctx, logs.EventCouldNotStartListenToEvents, - zap.Error(err), - ) - } + + l.listen(ctx, nil) }) } @@ -152,23 +149,17 @@ func (l *listener) ListenWithError(ctx context.Context, intError chan<- error) { l.startOnce.Do(func() { l.wg.Add(1) defer l.wg.Done() - if err := l.listen(ctx, intError); err != nil { - l.log.Error(ctx, logs.EventCouldNotStartListenToEvents, - zap.Error(err), - ) - l.sendError(ctx, intError, err) - } + + l.listen(ctx, intError) }) } -func (l *listener) listen(ctx context.Context, intError chan<- error) error { +func (l *listener) listen(ctx context.Context, intError chan<- error) { subErrCh := make(chan error) go l.subscribe(subErrCh) l.listenLoop(ctx, intError, subErrCh) - - return nil } func (l *listener) subscribe(errCh chan error) { diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 6a949e9388..8daf382174 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -120,10 +120,7 @@ func NewTraverser(opts ...Option) (*Traverser, error) { } rem = []int{-1, -1} - sortedVector, err := sortVector(cfg, unsortedVector) - if err != nil { - return nil, err - } + sortedVector := sortVector(cfg, unsortedVector) ns = [][]netmap.NodeInfo{sortedVector, regularVector} } else if cfg.flatSuccess != nil { ns = flatNodes(ns) @@ -188,7 +185,7 @@ type nodeMetrics struct { metrics []int } -func sortVector(cfg *cfg, unsortedVector []netmap.NodeInfo) ([]netmap.NodeInfo, error) { +func sortVector(cfg *cfg, unsortedVector []netmap.NodeInfo) []netmap.NodeInfo { nm := make([]nodeMetrics, len(unsortedVector)) node := cfg.nodeState.LocalNodeInfo() @@ -209,7 +206,7 @@ func sortVector(cfg *cfg, unsortedVector []netmap.NodeInfo) ([]netmap.NodeInfo, for i := range unsortedVector { sortedVector[i] = unsortedVector[nm[i].index] } - return sortedVector, nil + return sortedVector } // Node is a descriptor of storage node with information required for intra-container communication. From eff95bd632dc11435b8356555bfbdebe35b6d1d6 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 14 Jan 2025 11:15:21 +0300 Subject: [PATCH 1142/1413] [#1598] engine: Drop unnecessary result structs Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 9 +++---- pkg/local_object_storage/engine/delete.go | 20 +++++----------- .../engine/delete_test.go | 8 +++---- pkg/local_object_storage/engine/inhume.go | 24 +++++++------------ .../engine/inhume_test.go | 12 +++++----- pkg/local_object_storage/engine/lock_test.go | 19 +++++++-------- pkg/services/control/server/gc.go | 3 +-- 7 files changed, 36 insertions(+), 59 deletions(-) diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index f82a8e5330..9392411686 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -215,8 +215,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl prm.MarkAsGarbage(addr) prm.WithForceRemoval() - _, err := ls.Inhume(ctx, prm) - return err + return ls.Inhume(ctx, prm) } remoteReader := objectService.NewRemoteReader(keyStorage, clientConstructor) @@ -266,8 +265,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl var inhumePrm engine.InhumePrm inhumePrm.MarkAsGarbage(addr) - _, err := ls.Inhume(ctx, inhumePrm) - if err != nil { + if err := ls.Inhume(ctx, inhumePrm); err != nil { c.log.Warn(ctx, logs.FrostFSNodeCouldNotInhumeMarkRedundantCopyAsGarbage, zap.Error(err), ) @@ -476,8 +474,7 @@ func (e engineWithoutNotifications) Delete(ctx context.Context, tombstone oid.Ad prm.WithTarget(tombstone, addrs...) - _, err := e.engine.Inhume(ctx, prm) - return err + return e.engine.Inhume(ctx, prm) } func (e engineWithoutNotifications) Lock(ctx context.Context, locker oid.Address, toLock []oid.ID) error { diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index c735cc41dc..20c915da67 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -24,11 +24,6 @@ type DeletePrm struct { forceRemoval bool } -// DeleteRes groups the resulting values of Delete operation. -type DeleteRes struct{} - -var deleteRes = DeleteRes{} - // WithAddress is a Delete option to set the addresses of the objects to delete. // // Option is required. @@ -53,7 +48,7 @@ func (p *DeletePrm) WithForceRemoval() { // NOTE: Marks any object to be deleted (despite any prohibitions // on operations with that object) if WithForceRemoval option has // been provided. -func (e *StorageEngine) Delete(ctx context.Context, prm DeletePrm) (res DeleteRes, err error) { +func (e *StorageEngine) Delete(ctx context.Context, prm DeletePrm) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Delete", trace.WithAttributes( attribute.String("address", prm.addr.EncodeToString()), @@ -62,15 +57,12 @@ func (e *StorageEngine) Delete(ctx context.Context, prm DeletePrm) (res DeleteRe defer span.End() defer elapsed("Delete", e.metrics.AddMethodDuration)() - err = e.execIfNotBlocked(func() error { - res, err = e.delete(ctx, prm) - return err + return e.execIfNotBlocked(func() error { + return e.delete(ctx, prm) }) - - return } -func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, error) { +func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) error { var locked struct { is bool } @@ -128,14 +120,14 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) (DeleteRes, e }) if locked.is { - return deleteRes, new(apistatus.ObjectLocked) + return new(apistatus.ObjectLocked) } if splitInfo != nil { e.deleteChildren(ctx, prm.addr, prm.forceRemoval, splitInfo.SplitID()) } - return deleteRes, nil + return nil } func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, force bool, splitID *objectSDK.SplitID) { diff --git a/pkg/local_object_storage/engine/delete_test.go b/pkg/local_object_storage/engine/delete_test.go index 0dd2e94bb4..a56598c09d 100644 --- a/pkg/local_object_storage/engine/delete_test.go +++ b/pkg/local_object_storage/engine/delete_test.go @@ -70,8 +70,7 @@ func TestDeleteBigObject(t *testing.T) { deletePrm.WithForceRemoval() deletePrm.WithAddress(addrParent) - _, err := e.Delete(context.Background(), deletePrm) - require.NoError(t, err) + require.NoError(t, e.Delete(context.Background(), deletePrm)) checkGetError[*apistatus.ObjectNotFound](t, e, addrParent, true) checkGetError[*apistatus.ObjectNotFound](t, e, addrLink, true) @@ -141,8 +140,7 @@ func TestDeleteBigObjectWithoutGC(t *testing.T) { deletePrm.WithForceRemoval() deletePrm.WithAddress(addrParent) - _, err := e.Delete(context.Background(), deletePrm) - require.NoError(t, err) + require.NoError(t, e.Delete(context.Background(), deletePrm)) checkGetError[*apistatus.ObjectNotFound](t, e, addrParent, true) checkGetError[*apistatus.ObjectNotFound](t, e, addrLink, true) @@ -153,7 +151,7 @@ func TestDeleteBigObjectWithoutGC(t *testing.T) { // delete physical var delPrm shard.DeletePrm delPrm.SetAddresses(addrParent) - _, err = s1.Delete(context.Background(), delPrm) + _, err := s1.Delete(context.Background(), delPrm) require.NoError(t, err) delPrm.SetAddresses(addrLink) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index a0c38cd5d8..75bd15c8bd 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -27,11 +27,6 @@ type InhumePrm struct { forceRemoval bool } -// InhumeRes encapsulates results of inhume operation. -type InhumeRes struct{} - -var inhumeRes = InhumeRes{} - // WithTarget sets a list of objects that should be inhumed and tombstone address // as the reason for inhume operation. // @@ -69,23 +64,20 @@ var errInhumeFailure = errors.New("inhume operation failed") // with that object) if WithForceRemoval option has been provided. // // Returns an error if executions are blocked (see BlockExecution). -func (e *StorageEngine) Inhume(ctx context.Context, prm InhumePrm) (res InhumeRes, err error) { +func (e *StorageEngine) Inhume(ctx context.Context, prm InhumePrm) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.Inhume") defer span.End() defer elapsed("Inhume", e.metrics.AddMethodDuration)() - err = e.execIfNotBlocked(func() error { - res, err = e.inhume(ctx, prm) - return err + return e.execIfNotBlocked(func() error { + return e.inhume(ctx, prm) }) - - return } -func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { +func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) error { addrsPerShard, err := e.groupObjectsByShard(ctx, prm.addrs, !prm.forceRemoval) if err != nil { - return inhumeRes, err + return err } var shPrm shard.InhumePrm @@ -109,7 +101,7 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, e zap.String("shard_id", shardID), zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) - return inhumeRes, errInhumeFailure + return errInhumeFailure } if _, err := sh.Inhume(ctx, shPrm); err != nil { @@ -121,11 +113,11 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) (InhumeRes, e default: e.reportShardError(ctx, sh, "couldn't inhume object in shard", err) } - return inhumeRes, err + return err } } - return inhumeRes, nil + return nil } // groupObjectsByShard groups objects based on the shard(s) they are stored on. diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 2d083a58cf..8c5d28b154 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -55,7 +55,7 @@ func TestStorageEngine_Inhume(t *testing.T) { var inhumePrm InhumePrm inhumePrm.WithTarget(tombstoneID, object.AddressOf(parent)) - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.NoError(t, err) addrs, err := Select(context.Background(), e, cnr, false, fs) @@ -85,7 +85,7 @@ func TestStorageEngine_Inhume(t *testing.T) { var inhumePrm InhumePrm inhumePrm.WithTarget(tombstoneID, object.AddressOf(parent)) - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.NoError(t, err) addrs, err := Select(context.Background(), e, cnr, false, fs) @@ -128,7 +128,7 @@ func TestStorageEngine_ECInhume(t *testing.T) { var inhumePrm InhumePrm inhumePrm.WithTarget(tombstoneObjectAddress, parentObjectAddress) - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.NoError(t, err) var alreadyRemoved *apistatus.ObjectAlreadyRemoved @@ -173,7 +173,7 @@ func TestInhumeExpiredRegularObject(t *testing.T) { var prm InhumePrm prm.WithTarget(ts, object.AddressOf(obj)) - _, err := engine.Inhume(context.Background(), prm) + err := engine.Inhume(context.Background(), prm) require.NoError(t, err) }) @@ -182,7 +182,7 @@ func TestInhumeExpiredRegularObject(t *testing.T) { var prm InhumePrm prm.MarkAsGarbage(object.AddressOf(obj)) - _, err := engine.Inhume(context.Background(), prm) + err := engine.Inhume(context.Background(), prm) require.NoError(t, err) }) } @@ -237,7 +237,7 @@ func benchmarkInhumeMultipart(b *testing.B, numShards, numObjects int) { prm.WithTarget(ts, addrs...) b.StartTimer() - _, err := engine.Inhume(context.Background(), prm) + err := engine.Inhume(context.Background(), prm) require.NoError(b, err) b.StopTimer() } diff --git a/pkg/local_object_storage/engine/lock_test.go b/pkg/local_object_storage/engine/lock_test.go index 7bb9e39348..b8c9d6b1d6 100644 --- a/pkg/local_object_storage/engine/lock_test.go +++ b/pkg/local_object_storage/engine/lock_test.go @@ -114,7 +114,7 @@ func TestLockUserScenario(t *testing.T) { inhumePrm.WithTarget(tombAddr, objAddr) var objLockedErr *apistatus.ObjectLocked - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.ErrorAs(t, err, &objLockedErr) // 4. @@ -127,7 +127,7 @@ func TestLockUserScenario(t *testing.T) { inhumePrm.WithTarget(tombForLockAddr, lockerAddr) - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.ErrorIs(t, err, meta.ErrLockObjectRemoval) // 5. @@ -136,7 +136,7 @@ func TestLockUserScenario(t *testing.T) { inhumePrm.WithTarget(tombAddr, objAddr) require.Eventually(t, func() bool { - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) return err == nil }, 30*time.Second, time.Second) } @@ -200,7 +200,7 @@ func TestLockExpiration(t *testing.T) { inhumePrm.WithTarget(tombAddr, objectcore.AddressOf(obj)) var objLockedErr *apistatus.ObjectLocked - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.ErrorAs(t, err, &objLockedErr) // 3. @@ -212,7 +212,7 @@ func TestLockExpiration(t *testing.T) { inhumePrm.WithTarget(tombAddr, objectcore.AddressOf(obj)) require.Eventually(t, func() bool { - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) return err == nil }, 30*time.Second, time.Second) } @@ -270,12 +270,12 @@ func TestLockForceRemoval(t *testing.T) { inhumePrm.MarkAsGarbage(objectcore.AddressOf(obj)) var objLockedErr *apistatus.ObjectLocked - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.ErrorAs(t, err, &objLockedErr) inhumePrm.WithTarget(oidtest.Address(), objectcore.AddressOf(obj)) - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.ErrorAs(t, err, &objLockedErr) // 4. @@ -283,13 +283,12 @@ func TestLockForceRemoval(t *testing.T) { deletePrm.WithAddress(objectcore.AddressOf(lock)) deletePrm.WithForceRemoval() - _, err = e.Delete(context.Background(), deletePrm) - require.NoError(t, err) + require.NoError(t, e.Delete(context.Background(), deletePrm)) // 5. inhumePrm.MarkAsGarbage(objectcore.AddressOf(obj)) - _, err = e.Inhume(context.Background(), inhumePrm) + err = e.Inhume(context.Background(), inhumePrm) require.NoError(t, err) } diff --git a/pkg/services/control/server/gc.go b/pkg/services/control/server/gc.go index d9fefc38e6..a8ef7809ea 100644 --- a/pkg/services/control/server/gc.go +++ b/pkg/services/control/server/gc.go @@ -42,8 +42,7 @@ func (s *Server) DropObjects(ctx context.Context, req *control.DropObjectsReques prm.WithForceRemoval() prm.WithAddress(addrList[i]) - _, err := s.s.Delete(ctx, prm) - if err != nil && firstErr == nil { + if err := s.s.Delete(ctx, prm); err != nil && firstErr == nil { firstErr = err } } From 05fd999162f30042a0021f14a250aa3305b79f29 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 14 Jan 2025 10:54:53 +0300 Subject: [PATCH 1143/1413] [#1600] fstree: Handle incomplete writes Signed-off-by: Evgenii Stratonikov --- .../blobstor/fstree/fstree_write_linux.go | 25 +++++++++-- .../fstree/fstree_write_linux_test.go | 42 +++++++++++++++++++ 2 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 pkg/local_object_storage/blobstor/fstree/fstree_write_linux_test.go diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go index c62654028e..49cbda344b 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux.go @@ -69,10 +69,13 @@ func (w *linuxWriter) writeFile(p string, data []byte) error { if err != nil { return err } + written := 0 tmpPath := "/proc/self/fd/" + strconv.FormatUint(uint64(fd), 10) n, err := unix.Write(fd, data) - if err == nil { - if n == len(data) { + for err == nil { + written += n + + if written == len(data) { err = unix.Linkat(unix.AT_FDCWD, tmpPath, unix.AT_FDCWD, p, unix.AT_SYMLINK_FOLLOW) if err == nil { w.fileCounter.Inc(uint64(len(data))) @@ -80,9 +83,23 @@ func (w *linuxWriter) writeFile(p string, data []byte) error { if errors.Is(err, unix.EEXIST) { err = nil } - } else { - err = errors.New("incomplete write") + break } + + // From man 2 write: + // https://www.man7.org/linux/man-pages/man2/write.2.html + // + // Note that a successful write() may transfer fewer than count + // bytes. Such partial writes can occur for various reasons; for + // example, because there was insufficient space on the disk device + // to write all of the requested bytes, or because a blocked write() + // to a socket, pipe, or similar was interrupted by a signal handler + // after it had transferred some, but before it had transferred all + // of the requested bytes. In the event of a partial write, the + // caller can make another write() call to transfer the remaining + // bytes. The subsequent call will either transfer further bytes or + // may result in an error (e.g., if the disk is now full). + n, err = unix.Write(fd, data[written:]) } errClose := unix.Close(fd) if err != nil { diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_linux_test.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux_test.go new file mode 100644 index 0000000000..7fae2e6951 --- /dev/null +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_linux_test.go @@ -0,0 +1,42 @@ +//go:build linux && integration + +package fstree + +import ( + "context" + "errors" + "os" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + "github.com/stretchr/testify/require" + "golang.org/x/sys/unix" +) + +func TestENOSPC(t *testing.T) { + dir, err := os.MkdirTemp(t.TempDir(), "ramdisk") + require.NoError(t, err) + + f, err := os.CreateTemp(t.TempDir(), "ramdisk_*") + require.NoError(t, err) + + err = unix.Mount(f.Name(), dir, "tmpfs", 0, "size=1M") + if errors.Is(err, unix.EPERM) { + t.Skipf("skip size tests: no permission to mount: %v", err) + return + } + require.NoError(t, err) + defer func() { + require.NoError(t, unix.Unmount(dir, 0)) + }() + + fst := New(WithPath(dir), WithDepth(1)) + require.NoError(t, fst.Open(mode.ComponentReadWrite)) + require.NoError(t, fst.Init()) + + _, err = fst.Put(context.Background(), common.PutPrm{ + RawData: make([]byte, 10<<20), + }) + require.ErrorIs(t, err, common.ErrNoSpace) +} From c3c034eccac1297a15645d1ff7995855cc45fc74 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 15 Jan 2025 14:19:56 +0300 Subject: [PATCH 1144/1413] [#1601] util: Correctly parse 'root' name for container resources * Convert `root/*` to `//`; * Add unit-test case for parses to check parsing correctness. Signed-off-by: Airat Arifullin --- pkg/util/ape/parser.go | 2 +- pkg/util/ape/parser_test.go | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pkg/util/ape/parser.go b/pkg/util/ape/parser.go index b4a31fd8d8..a34a17f6f9 100644 --- a/pkg/util/ape/parser.go +++ b/pkg/util/ape/parser.go @@ -261,7 +261,7 @@ func parseResource(lexeme string, isObj bool) (string, error) { } else { if lexeme == "*" { return nativeschema.ResourceFormatAllContainers, nil - } else if lexeme == "/*" { + } else if lexeme == "/*" || lexeme == "root/*" { return nativeschema.ResourceFormatRootContainers, nil } else if strings.HasPrefix(lexeme, "/") && len(lexeme) > 1 { lexeme = lexeme[1:] diff --git a/pkg/util/ape/parser_test.go b/pkg/util/ape/parser_test.go index 21649fd24d..c236c46037 100644 --- a/pkg/util/ape/parser_test.go +++ b/pkg/util/ape/parser_test.go @@ -43,6 +43,15 @@ func TestParseAPERule(t *testing.T) { Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootObjects}}, }, }, + { + name: "Valid rule for all containers in explicit root namespace", + rule: "allow Container.Put root/*", + expectRule: policyengine.Rule{ + Status: policyengine.Allow, + Actions: policyengine.Actions{Names: []string{nativeschema.MethodPutContainer}}, + Resources: policyengine.Resources{Names: []string{nativeschema.ResourceFormatRootContainers}}, + }, + }, { name: "Valid rule for all objects in root namespace and container", rule: "allow Object.Put /cid/*", From 436d65d784876248585edb94be9cf397a874caba Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Thu, 9 Jan 2025 12:07:17 +0300 Subject: [PATCH 1145/1413] [#1591] Build and host OCI images on our own infra Similar to https://git.frostfs.info/TrueCloudLab/frostfs-s3-gw/issues/587 this PR introduces a CI pipeline that builds Docker images and pushes them to our selfhosted registry. Signed-off-by: Vitaliy Potyarkin --- .forgejo/workflows/oci-image.yml | 28 ++++++++++++++++++++++++++++ Makefile | 9 +++++++++ docs/release-instruction.md | 12 ++++-------- 3 files changed, 41 insertions(+), 8 deletions(-) create mode 100644 .forgejo/workflows/oci-image.yml diff --git a/.forgejo/workflows/oci-image.yml b/.forgejo/workflows/oci-image.yml new file mode 100644 index 0000000000..fe91d65f9b --- /dev/null +++ b/.forgejo/workflows/oci-image.yml @@ -0,0 +1,28 @@ +name: OCI image + +on: + push: + workflow_dispatch: + +jobs: + image: + name: Build container images + runs-on: docker + container: git.frostfs.info/truecloudlab/env:oci-image-builder-bookworm + steps: + - name: Clone git repo + uses: actions/checkout@v3 + + - name: Build OCI image + run: make images + + - name: Push image to OCI registry + run: | + echo "$REGISTRY_PASSWORD" \ + | docker login --username truecloudlab --password-stdin git.frostfs.info + make push-images + if: >- + startsWith(github.ref, 'refs/tags/v') && + (github.event_name == 'workflow_dispatch' || github.event_name == 'push') + env: + REGISTRY_PASSWORD: ${{secrets.FORGEJO_OCI_REGISTRY_PUSH_TOKEN}} diff --git a/Makefile b/Makefile index f0cdc273c3..e9601a87ee 100755 --- a/Makefile +++ b/Makefile @@ -139,6 +139,15 @@ images: image-storage image-ir image-cli image-adm # Build dirty local Docker images dirty-images: image-dirty-storage image-dirty-ir image-dirty-cli image-dirty-adm +# Push FrostFS components' docker image to the registry +push-image-%: + @echo "⇒ Publish FrostFS $* docker image " + @docker push $(HUB_IMAGE)-$*:$(HUB_TAG) + +# Push all Docker images to the registry +.PHONY: push-images +push-images: push-image-storage push-image-ir push-image-cli push-image-adm + # Run `make %` in Golang container docker/%: docker run --rm -t \ diff --git a/docs/release-instruction.md b/docs/release-instruction.md index 18659c699a..aa867e83cc 100644 --- a/docs/release-instruction.md +++ b/docs/release-instruction.md @@ -95,19 +95,15 @@ $ git push origin ${FROSTFS_TAG_PREFIX}${FROSTFS_REVISION} ## Post-release -### Prepare and push images to a Docker Hub (if not automated) +### Prepare and push images to a Docker registry (automated) -Create Docker images for all applications and push them into Docker Hub -(requires [organization](https://hub.docker.com/u/truecloudlab) privileges) +Create Docker images for all applications and push them into container registry +(executed automatically in Forgejo Actions upon pushing a release tag): ```shell $ git checkout ${FROSTFS_TAG_PREFIX}${FROSTFS_REVISION} $ make images -$ docker push truecloudlab/frostfs-storage:${FROSTFS_REVISION} -$ docker push truecloudlab/frostfs-storage-testnet:${FROSTFS_REVISION} -$ docker push truecloudlab/frostfs-ir:${FROSTFS_REVISION} -$ docker push truecloudlab/frostfs-cli:${FROSTFS_REVISION} -$ docker push truecloudlab/frostfs-adm:${FROSTFS_REVISION} +$ make push-images ``` ### Make a proper release (if not automated) From 5a270e2e61fc245130c5fc663e035a574ec6bc5e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 16 Jan 2025 15:08:35 +0300 Subject: [PATCH 1146/1413] [#1604] policer: Use status instead of bool value in node cache Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/nodecache.go | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/pkg/services/policer/nodecache.go b/pkg/services/policer/nodecache.go index cd47cb0fcf..410ef7d86d 100644 --- a/pkg/services/policer/nodecache.go +++ b/pkg/services/policer/nodecache.go @@ -15,37 +15,30 @@ func (st nodeProcessStatus) Processed() bool { } // nodeCache tracks Policer's check progress. -type nodeCache map[uint64]bool +type nodeCache map[uint64]nodeProcessStatus func newNodeCache() nodeCache { - return make(map[uint64]bool) + return make(map[uint64]nodeProcessStatus) } -func (n nodeCache) set(node netmap.NodeInfo, val bool) { +func (n nodeCache) set(node netmap.NodeInfo, val nodeProcessStatus) { n[node.Hash()] = val } // submits storage node as a candidate to store the object replica in case of // shortage. func (n nodeCache) submitReplicaCandidate(node netmap.NodeInfo) { - n.set(node, false) + n.set(node, nodeDoesNotHoldObject) } // submits storage node as a current object replica holder. func (n nodeCache) submitReplicaHolder(node netmap.NodeInfo) { - n.set(node, true) + n.set(node, nodeHoldsObject) } // processStatus returns current processing status of the storage node. func (n nodeCache) processStatus(node netmap.NodeInfo) nodeProcessStatus { - switch val, ok := n[node.Hash()]; { - case !ok: - return nodeNotProcessed - case val: - return nodeHoldsObject - default: - return nodeDoesNotHoldObject - } + return n[node.Hash()] } // SubmitSuccessfulReplication marks given storage node as a current object From 84e1599997c3d4674c418556dccbeaeb1d2414ed Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 16 Jan 2025 15:52:21 +0300 Subject: [PATCH 1147/1413] [#1604] policer: Remove one-line helpers Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/check.go | 6 +++--- pkg/services/policer/check_test.go | 4 ++-- pkg/services/policer/nodecache.go | 13 +------------ 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index bdfc4344bf..9335a75d8a 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -143,10 +143,10 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe if err == nil { shortage-- - checkedNodes.submitReplicaHolder(nodes[i]) + checkedNodes.set(nodes[i], nodeHoldsObject) } else { if client.IsErrObjectNotFound(err) { - checkedNodes.submitReplicaCandidate(nodes[i]) + checkedNodes.set(nodes[i], nodeDoesNotHoldObject) continue } else if client.IsErrNodeUnderMaintenance(err) { shortage, uncheckedCopies = p.handleMaintenance(ctx, nodes[i], checkedNodes, shortage, uncheckedCopies) @@ -174,7 +174,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe // However, additional copies should not be removed in this case, // because we can remove the only copy this way. func (p *Policer) handleMaintenance(ctx context.Context, node netmap.NodeInfo, checkedNodes nodeCache, shortage uint32, uncheckedCopies int) (uint32, int) { - checkedNodes.submitReplicaHolder(node) + checkedNodes.set(node, nodeHoldsObject) shortage-- uncheckedCopies++ diff --git a/pkg/services/policer/check_test.go b/pkg/services/policer/check_test.go index d4c7ccbf98..69879c439f 100644 --- a/pkg/services/policer/check_test.go +++ b/pkg/services/policer/check_test.go @@ -16,9 +16,9 @@ func TestNodeCache(t *testing.T) { cache.SubmitSuccessfulReplication(node) require.Equal(t, cache.processStatus(node), nodeHoldsObject) - cache.submitReplicaCandidate(node) + cache.set(node, nodeDoesNotHoldObject) require.Equal(t, cache.processStatus(node), nodeDoesNotHoldObject) - cache.submitReplicaHolder(node) + cache.set(node, nodeHoldsObject) require.Equal(t, cache.processStatus(node), nodeHoldsObject) } diff --git a/pkg/services/policer/nodecache.go b/pkg/services/policer/nodecache.go index 410ef7d86d..7a82178586 100644 --- a/pkg/services/policer/nodecache.go +++ b/pkg/services/policer/nodecache.go @@ -25,17 +25,6 @@ func (n nodeCache) set(node netmap.NodeInfo, val nodeProcessStatus) { n[node.Hash()] = val } -// submits storage node as a candidate to store the object replica in case of -// shortage. -func (n nodeCache) submitReplicaCandidate(node netmap.NodeInfo) { - n.set(node, nodeDoesNotHoldObject) -} - -// submits storage node as a current object replica holder. -func (n nodeCache) submitReplicaHolder(node netmap.NodeInfo) { - n.set(node, nodeHoldsObject) -} - // processStatus returns current processing status of the storage node. func (n nodeCache) processStatus(node netmap.NodeInfo) nodeProcessStatus { return n[node.Hash()] @@ -46,5 +35,5 @@ func (n nodeCache) processStatus(node netmap.NodeInfo) nodeProcessStatus { // // SubmitSuccessfulReplication implements replicator.TaskResult. func (n nodeCache) SubmitSuccessfulReplication(node netmap.NodeInfo) { - n.submitReplicaHolder(node) + n.set(node, nodeHoldsObject) } From 4538ccb12a4769eeb397417f0b755dc1bc7bd712 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 16 Jan 2025 15:59:17 +0300 Subject: [PATCH 1148/1413] [#1604] policer: Do not process the same node twice Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/check.go | 6 +++--- pkg/services/policer/nodecache.go | 1 + pkg/services/policer/policer_test.go | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 9335a75d8a..f79ffbece3 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -126,12 +126,11 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe } else { if status := checkedNodes.processStatus(nodes[i]); status.Processed() { if status == nodeHoldsObject { - // node already contains replica, no need to replicate - nodes = append(nodes[:i], nodes[i+1:]...) - i-- shortage-- } + nodes = append(nodes[:i], nodes[i+1:]...) + i-- continue } @@ -155,6 +154,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe zap.Stringer("object", addr), zap.Error(err), ) + checkedNodes.set(nodes[i], nodeStatusUnknown) } } } diff --git a/pkg/services/policer/nodecache.go b/pkg/services/policer/nodecache.go index 7a82178586..84a3332788 100644 --- a/pkg/services/policer/nodecache.go +++ b/pkg/services/policer/nodecache.go @@ -8,6 +8,7 @@ const ( nodeNotProcessed nodeProcessStatus = iota nodeDoesNotHoldObject nodeHoldsObject + nodeStatusUnknown ) func (st nodeProcessStatus) Processed() bool { diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 4e17e98a88..2ed71c4046 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -127,7 +127,7 @@ func TestProcessObject(t *testing.T) { nodeCount: 2, policy: `REP 2 REP 2`, placement: [][]int{{0, 1}, {0, 1}}, - wantReplicateTo: []int{1, 1}, // is this actually good? + wantReplicateTo: []int{1}, }, { desc: "lock object must be replicated to all nodes", From 26e0c82fb8ad0d74782e2c96cbf4d7bcdd76e428 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 16 Jan 2025 16:22:37 +0300 Subject: [PATCH 1149/1413] [#1604] policer/test: Add test for MAINTENANCE runtime status The node can have MAINTENANCE status in the network map, but can also be ONLINE while responding with MAINTENANCE. These are 2 different code paths, let's test them separately. Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/policer_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 2ed71c4046..ca6bff944a 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -78,6 +78,7 @@ func TestProcessObject(t *testing.T) { maintenanceNodes []int wantRemoveRedundant bool wantReplicateTo []int + headResult map[int]error ecInfo *objectcore.ECInfo }{ { @@ -145,6 +146,14 @@ func TestProcessObject(t *testing.T) { objHolders: []int{1}, maintenanceNodes: []int{2}, }, + { + desc: "preserve local copy when node response with MAINTENANCE", + nodeCount: 3, + policy: `REP 2`, + placement: [][]int{{1, 2}}, + objHolders: []int{1}, + headResult: map[int]error{2: new(apistatus.NodeUnderMaintenance)}, + }, { desc: "lock object must be replicated to all EC nodes", objType: objectSDK.TypeLock, @@ -204,6 +213,11 @@ func TestProcessObject(t *testing.T) { t.Errorf("unexpected remote object head: node=%+v addr=%v", ni, a) return nil, errors.New("unexpected object head") } + if ti.headResult != nil { + if err, ok := ti.headResult[index]; ok { + return nil, err + } + } for _, i := range ti.objHolders { if index == i { return nil, nil From 57efa0bc8eebbc7b26ef9d0c14b4dbbdb7b59de7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 16 Jan 2025 16:04:40 +0300 Subject: [PATCH 1150/1413] [#1604] policer: Properly handle maintenance nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consider `REP 1 REP 1` placement (selects/filters are omitted). The placement is `[1, 2], [1, 0]`. We are the 0-th node. Node 1 is under maintenance, so we do not replicate object on the node 2. In the second replication group node 1 is under maintenance, but current caching logic considers it as "replica holder" and removes local copy. Voilà, we have DL if the object is missing from the node 1. Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/check.go | 6 +++++- pkg/services/policer/nodecache.go | 1 + pkg/services/policer/policer_test.go | 8 ++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index f79ffbece3..7ac5fc9e0f 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -128,6 +128,10 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe if status == nodeHoldsObject { shortage-- } + if status == nodeIsUnderMaintenance { + shortage-- + uncheckedCopies++ + } nodes = append(nodes[:i], nodes[i+1:]...) i-- @@ -174,7 +178,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe // However, additional copies should not be removed in this case, // because we can remove the only copy this way. func (p *Policer) handleMaintenance(ctx context.Context, node netmap.NodeInfo, checkedNodes nodeCache, shortage uint32, uncheckedCopies int) (uint32, int) { - checkedNodes.set(node, nodeHoldsObject) + checkedNodes.set(node, nodeIsUnderMaintenance) shortage-- uncheckedCopies++ diff --git a/pkg/services/policer/nodecache.go b/pkg/services/policer/nodecache.go index 84a3332788..53b64d3fa9 100644 --- a/pkg/services/policer/nodecache.go +++ b/pkg/services/policer/nodecache.go @@ -9,6 +9,7 @@ const ( nodeDoesNotHoldObject nodeHoldsObject nodeStatusUnknown + nodeIsUnderMaintenance ) func (st nodeProcessStatus) Processed() bool { diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index ca6bff944a..9b9ab99ace 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -170,6 +170,14 @@ func TestProcessObject(t *testing.T) { placement: [][]int{{0, 1, 2}}, wantReplicateTo: []int{1, 2}, }, + { + desc: "do not remove local copy when MAINTENANCE status is cached", + objType: objectSDK.TypeRegular, + nodeCount: 3, + policy: `REP 1 REP 1`, + placement: [][]int{{1, 2}, {1, 0}}, + headResult: map[int]error{1: new(apistatus.NodeUnderMaintenance)}, + }, } for i := range tests { From 80de5d70bfd5bca16b9c891b8fdef25165e0bba1 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 16 Jan 2025 15:25:05 +0300 Subject: [PATCH 1151/1413] [#1593] node: Fix initialization of ape_chain cache Signed-off-by: Alexander Chuprov --- cmd/frostfs-node/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 9931d0dc8c..3e9cd4e111 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1146,7 +1146,7 @@ func initAccessPolicyEngine(ctx context.Context, c *cfg) { c.cfgObject.cfgAccessPolicyEngine.policyContractHash) cacheSize := morphconfig.APEChainCacheSize(c.appCfg) - if cacheSize > 0 { + if cacheSize > 0 && c.cfgMorph.cacheTTL > 0 { morphRuleStorage = newMorphCache(morphRuleStorage, int(cacheSize), c.cfgMorph.cacheTTL) } From c98357606b4e387f7a8063331438dccfb24d255e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 17 Jan 2025 13:51:18 +0300 Subject: [PATCH 1152/1413] [#1606] Use slices.Clone()/bytes.Clone() where possible gopatch: ``` @@ var from, to expression @@ +import "bytes" -to := make([]byte, len(from)) -copy(to, from) +to := bytes.Clone(from) @@ var from, to expression @@ +import "bytes" -to = make([]byte, len(from)) -copy(to, from) +to = bytes.Clone(from) @@ var from, to, typ expression @@ +import "slices" -to := make([]typ, len(from)) -copy(to, from) +to := slices.Clone(from) @@ var from, to, typ expression @@ +import "slices" -to = make([]typ, len(from)) -copy(to, from) +to = slices.Clone(from) ``` Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/storagecfg/root.go | 4 ++-- cmd/frostfs-node/config/calls.go | 4 ++-- pkg/local_object_storage/engine/evacuate.go | 4 ++-- pkg/local_object_storage/engine/evacuate_limiter.go | 4 ++-- pkg/local_object_storage/metabase/list.go | 6 ++---- pkg/local_object_storage/pilorama/boltdb.go | 3 +-- pkg/local_object_storage/pilorama/forest.go | 4 ++-- pkg/morph/client/multi.go | 4 ++-- pkg/services/object/common/writer/ec_test.go | 4 ++-- pkg/services/object/search/search_test.go | 4 ++-- pkg/services/object_manager/placement/traverser_test.go | 4 ++-- 11 files changed, 21 insertions(+), 24 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/root.go b/cmd/frostfs-adm/internal/modules/storagecfg/root.go index 8e6a8354eb..8acbc45795 100644 --- a/cmd/frostfs-adm/internal/modules/storagecfg/root.go +++ b/cmd/frostfs-adm/internal/modules/storagecfg/root.go @@ -11,6 +11,7 @@ import ( "net/url" "os" "path/filepath" + "slices" "strconv" "strings" "text/template" @@ -410,8 +411,7 @@ func initClient(rpc []string) *rpcclient.Client { var c *rpcclient.Client var err error - shuffled := make([]string, len(rpc)) - copy(shuffled, rpc) + shuffled := slices.Clone(rpc) rand.Shuffle(len(shuffled), func(i, j int) { shuffled[i], shuffled[j] = shuffled[j], shuffled[i] }) for _, endpoint := range shuffled { diff --git a/cmd/frostfs-node/config/calls.go b/cmd/frostfs-node/config/calls.go index 36e53ea7c9..c40bf36201 100644 --- a/cmd/frostfs-node/config/calls.go +++ b/cmd/frostfs-node/config/calls.go @@ -1,6 +1,7 @@ package config import ( + "slices" "strings" configViper "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/config" @@ -52,6 +53,5 @@ func (x *Config) Value(name string) any { // It supports only one level of nesting and is intended to be used // to provide default values. func (x *Config) SetDefault(from *Config) { - x.defaultPath = make([]string, len(from.path)) - copy(x.defaultPath, from.path) + x.defaultPath = slices.Clone(from.path) } diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 682f23dff3..b37f6b68e8 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "slices" "strings" "sync" "sync/atomic" @@ -255,8 +256,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) erro copyShards := func() []pooledShard { mtx.RLock() defer mtx.RUnlock() - t := make([]pooledShard, len(shards)) - copy(t, shards) + t := slices.Clone(shards) return t } eg.Go(func() error { diff --git a/pkg/local_object_storage/engine/evacuate_limiter.go b/pkg/local_object_storage/engine/evacuate_limiter.go index 1e6b9ccb1f..c74134500f 100644 --- a/pkg/local_object_storage/engine/evacuate_limiter.go +++ b/pkg/local_object_storage/engine/evacuate_limiter.go @@ -3,6 +3,7 @@ package engine import ( "context" "fmt" + "slices" "sync" "time" @@ -123,8 +124,7 @@ func (s *EvacuationState) DeepCopy() *EvacuationState { if s == nil { return nil } - shardIDs := make([]string, len(s.shardIDs)) - copy(shardIDs, s.shardIDs) + shardIDs := slices.Clone(s.shardIDs) return &EvacuationState{ shardIDs: shardIDs, diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index f488c3ced3..eaef3b9ba7 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -188,8 +188,7 @@ loop: if offset != nil { // new slice is much faster but less memory efficient // we need to copy, because offset exists during bbolt tx - cursor.inBucketOffset = make([]byte, len(offset)) - copy(cursor.inBucketOffset, offset) + cursor.inBucketOffset = bytes.Clone(offset) } if len(result) == 0 { @@ -198,8 +197,7 @@ loop: // new slice is much faster but less memory efficient // we need to copy, because bucketName exists during bbolt tx - cursor.bucketName = make([]byte, len(bucketName)) - copy(cursor.bucketName, bucketName) + cursor.bucketName = bytes.Clone(bucketName) return result, cursor, nil } diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 1d55d1c139..9d71d9fdae 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1506,8 +1506,7 @@ func (t *boltForest) TreeListTrees(ctx context.Context, prm TreeListTreesPrm) (* }) if len(res.Items) == batchSize { - res.NextPageToken = make([]byte, len(k)) - copy(res.NextPageToken, k) + res.NextPageToken = bytes.Clone(k) break } } diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index f31504e2b1..92183716c3 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "slices" "sort" "strings" @@ -84,8 +85,7 @@ func (f *memoryForest) TreeAddByPath(_ context.Context, d CIDDescriptor, treeID s.operations = append(s.operations, op) } - mCopy := make([]KeyValue, len(m)) - copy(mCopy, m) + mCopy := slices.Clone(m) op := s.do(&Move{ Parent: node, Meta: Meta{ diff --git a/pkg/morph/client/multi.go b/pkg/morph/client/multi.go index 708d3b39f9..b9e39c25e1 100644 --- a/pkg/morph/client/multi.go +++ b/pkg/morph/client/multi.go @@ -2,6 +2,7 @@ package client import ( "context" + "slices" "sort" "time" @@ -99,8 +100,7 @@ mainLoop: case <-t.C: c.switchLock.RLock() - endpointsCopy := make([]Endpoint, len(c.endpoints.list)) - copy(endpointsCopy, c.endpoints.list) + endpointsCopy := slices.Clone(c.endpoints.list) currPriority := c.endpoints.list[c.endpoints.curr].Priority highestPriority := c.endpoints.list[0].Priority diff --git a/pkg/services/object/common/writer/ec_test.go b/pkg/services/object/common/writer/ec_test.go index 8b2599e5fa..8ad7e641a5 100644 --- a/pkg/services/object/common/writer/ec_test.go +++ b/pkg/services/object/common/writer/ec_test.go @@ -7,6 +7,7 @@ import ( "crypto/sha256" "errors" "fmt" + "slices" "strconv" "testing" @@ -41,8 +42,7 @@ type testPlacementBuilder struct { func (p *testPlacementBuilder) BuildPlacement(_ cid.ID, _ *oid.ID, _ netmap.PlacementPolicy) ( [][]netmap.NodeInfo, error, ) { - arr := make([]netmap.NodeInfo, len(p.vectors[0])) - copy(arr, p.vectors[0]) + arr := slices.Clone(p.vectors[0]) return [][]netmap.NodeInfo{arr}, nil } diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 0a40025e1c..05643eb2b3 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "errors" "fmt" + "slices" "strconv" "testing" @@ -103,8 +104,7 @@ func (p *testPlacementBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, _ netmap. return nil, errors.New("vectors for address not found") } - res := make([][]netmap.NodeInfo, len(vs)) - copy(res, vs) + res := slices.Clone(vs) return res, nil } diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index f96e5c8a7e..624efb007a 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -1,6 +1,7 @@ package placement import ( + "slices" "strconv" "testing" @@ -33,8 +34,7 @@ func copyVectors(v [][]netmap.NodeInfo) [][]netmap.NodeInfo { vc := make([][]netmap.NodeInfo, 0, len(v)) for i := range v { - ns := make([]netmap.NodeInfo, len(v[i])) - copy(ns, v[i]) + ns := slices.Clone(v[i]) vc = append(vc, ns) } From 0bcbeb26b2b79d210d4b99360e1ad58ae809faab Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 17 Jan 2025 12:38:44 +0300 Subject: [PATCH 1153/1413] [#1605] policer: Simplify processRepNodes() checks Current flow is hard to reason about, #1601 is a notorious example of accidental complexity. 1. Remove multiple nested ifs, use depth=1. 2. Process each status exactly once, hopefully preventing bugs like #1601. Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/check.go | 106 ++++++++++++++---------------- pkg/services/policer/nodecache.go | 1 + 2 files changed, 52 insertions(+), 55 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 7ac5fc9e0f..3e536f1059 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -117,50 +117,40 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe default: } - if p.netmapKeys.IsLocalKey(nodes[i].PublicKey()) { + var err error + st := checkedNodes.processStatus(nodes[i]) + if !st.Processed() { + st, err = p.checkStatus(ctx, addr, nodes[i]) + checkedNodes.set(nodes[i], st) + if st == nodeDoesNotHoldObject { + // 1. This is the first time the node is encountered (`!st.Processed()`). + // 2. The node does not hold object (`st == nodeDoesNotHoldObject`). + // So we leave the node in the list and skip its removal + // at the end of the loop body. + continue + } + } + + switch st { + case nodeIsLocal: requirements.needLocalCopy = true shortage-- - } else if nodes[i].Status().IsMaintenance() { - shortage, uncheckedCopies = p.handleMaintenance(ctx, nodes[i], checkedNodes, shortage, uncheckedCopies) - } else { - if status := checkedNodes.processStatus(nodes[i]); status.Processed() { - if status == nodeHoldsObject { - shortage-- - } - if status == nodeIsUnderMaintenance { - shortage-- - uncheckedCopies++ - } + case nodeIsUnderMaintenance: + shortage-- + uncheckedCopies++ - nodes = append(nodes[:i], nodes[i+1:]...) - i-- - continue - } - - callCtx, cancel := context.WithTimeout(ctx, p.headTimeout) - - _, err := p.remoteHeader(callCtx, nodes[i], addr, false) - - cancel() - - if err == nil { - shortage-- - checkedNodes.set(nodes[i], nodeHoldsObject) - } else { - if client.IsErrObjectNotFound(err) { - checkedNodes.set(nodes[i], nodeDoesNotHoldObject) - continue - } else if client.IsErrNodeUnderMaintenance(err) { - shortage, uncheckedCopies = p.handleMaintenance(ctx, nodes[i], checkedNodes, shortage, uncheckedCopies) - } else { - p.log.Error(ctx, logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, - zap.Stringer("object", addr), - zap.Error(err), - ) - checkedNodes.set(nodes[i], nodeStatusUnknown) - } - } + p.log.Debug(ctx, logs.PolicerConsiderNodeUnderMaintenanceAsOK, + zap.String("node", netmap.StringifyPublicKey(nodes[i]))) + case nodeHoldsObject: + shortage-- + case nodeDoesNotHoldObject: + case nodeStatusUnknown: + p.log.Error(ctx, logs.PolicerReceiveObjectHeaderToCheckPolicyCompliance, + zap.Stringer("object", addr), + zap.Error(err)) + default: + panic("unreachable") } nodes = append(nodes[:i], nodes[i+1:]...) @@ -170,22 +160,28 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe p.handleProcessNodesResult(ctx, addr, requirements, nodes, checkedNodes, shortage, uncheckedCopies) } -// handleMaintenance handles node in maintenance mode and returns new shortage and uncheckedCopies values -// -// consider remote nodes under maintenance as problem OK. Such -// nodes MAY not respond with object, however, this is how we -// prevent spam with new replicas. -// However, additional copies should not be removed in this case, -// because we can remove the only copy this way. -func (p *Policer) handleMaintenance(ctx context.Context, node netmap.NodeInfo, checkedNodes nodeCache, shortage uint32, uncheckedCopies int) (uint32, int) { - checkedNodes.set(node, nodeIsUnderMaintenance) - shortage-- - uncheckedCopies++ +func (p *Policer) checkStatus(ctx context.Context, addr oid.Address, node netmap.NodeInfo) (nodeProcessStatus, error) { + if p.netmapKeys.IsLocalKey(node.PublicKey()) { + return nodeIsLocal, nil + } + if node.Status().IsMaintenance() { + return nodeIsUnderMaintenance, nil + } - p.log.Debug(ctx, logs.PolicerConsiderNodeUnderMaintenanceAsOK, - zap.String("node", netmap.StringifyPublicKey(node)), - ) - return shortage, uncheckedCopies + callCtx, cancel := context.WithTimeout(ctx, p.headTimeout) + _, err := p.remoteHeader(callCtx, node, addr, false) + cancel() + + if err == nil { + return nodeHoldsObject, nil + } + if client.IsErrObjectNotFound(err) { + return nodeDoesNotHoldObject, nil + } + if client.IsErrNodeUnderMaintenance(err) { + return nodeIsUnderMaintenance, nil + } + return nodeStatusUnknown, err } func (p *Policer) handleProcessNodesResult(ctx context.Context, addr oid.Address, requirements *placementRequirements, diff --git a/pkg/services/policer/nodecache.go b/pkg/services/policer/nodecache.go index 53b64d3fa9..c2157de5d5 100644 --- a/pkg/services/policer/nodecache.go +++ b/pkg/services/policer/nodecache.go @@ -10,6 +10,7 @@ const ( nodeHoldsObject nodeStatusUnknown nodeIsUnderMaintenance + nodeIsLocal ) func (st nodeProcessStatus) Processed() bool { From 951a7ee1c7fa9ffa96041e77731e3bacea16242b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 20 Jan 2025 16:09:35 +0300 Subject: [PATCH 1154/1413] [#1605] policer: Do not mutate slice under iteration Nothing wrong with it, besides being difficult to read. Signed-off-by: Evgenii Stratonikov --- pkg/services/policer/check.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 3e536f1059..7df3724764 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -110,6 +110,7 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe // Number of copies that are stored on maintenance nodes. var uncheckedCopies int + var candidates []netmap.NodeInfo for i := 0; shortage > 0 && i < len(nodes); i++ { select { case <-ctx.Done(): @@ -125,8 +126,8 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe if st == nodeDoesNotHoldObject { // 1. This is the first time the node is encountered (`!st.Processed()`). // 2. The node does not hold object (`st == nodeDoesNotHoldObject`). - // So we leave the node in the list and skip its removal - // at the end of the loop body. + // So we need to try to put an object to it. + candidates = append(candidates, nodes[i]) continue } } @@ -152,12 +153,9 @@ func (p *Policer) processRepNodes(ctx context.Context, requirements *placementRe default: panic("unreachable") } - - nodes = append(nodes[:i], nodes[i+1:]...) - i-- } - p.handleProcessNodesResult(ctx, addr, requirements, nodes, checkedNodes, shortage, uncheckedCopies) + p.handleProcessNodesResult(ctx, addr, requirements, candidates, checkedNodes, shortage, uncheckedCopies) } func (p *Policer) checkStatus(ctx context.Context, addr oid.Address, node netmap.NodeInfo) (nodeProcessStatus, error) { From 30e14d50ef97e04758b5fb529fb24a5f912d247b Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 23 Jan 2025 17:56:52 +0300 Subject: [PATCH 1155/1413] [#1612] Makefile: Update golangci-lint Signed-off-by: Alexander Chuprov --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e9601a87ee..497dce1156 100755 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.22 -LINT_VERSION ?= 1.62.0 +LINT_VERSION ?= 1.62.2 TRUECLOUDLAB_LINT_VERSION ?= 0.0.8 PROTOC_VERSION ?= 25.0 PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go) From 603015d029ba15dcc9f84e19b14eea1e38e55309 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 24 Jan 2025 16:33:32 +0300 Subject: [PATCH 1156/1413] [#1570] cli: Use array type for --range parameter to object hash Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/modules/object/hash.go | 2 +- cmd/frostfs-cli/modules/object/range.go | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/hash.go b/cmd/frostfs-cli/modules/object/hash.go index 461c35f30c..d8ea449eb1 100644 --- a/cmd/frostfs-cli/modules/object/hash.go +++ b/cmd/frostfs-cli/modules/object/hash.go @@ -41,7 +41,7 @@ func initObjectHashCmd() { flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) _ = objectHashCmd.MarkFlagRequired(commonflags.OIDFlag) - flags.String("range", "", "Range to take hash from in the form offset1:length1,...") + flags.StringSlice("range", nil, "Range to take hash from in the form offset1:length1,...") _ = objectHashCmd.MarkFlagRequired("range") flags.String("type", hashSha256, "Hash type. Either 'sha256' or 'tz'") diff --git a/cmd/frostfs-cli/modules/object/range.go b/cmd/frostfs-cli/modules/object/range.go index ad4bc3d598..8f59906ca7 100644 --- a/cmd/frostfs-cli/modules/object/range.go +++ b/cmd/frostfs-cli/modules/object/range.go @@ -38,7 +38,7 @@ func initObjectRangeCmd() { flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) _ = objectRangeCmd.MarkFlagRequired(commonflags.OIDFlag) - flags.String("range", "", "Range to take data from in the form offset:length") + flags.StringSlice("range", nil, "Range to take data from in the form offset:length") flags.String(fileFlag, "", "File to write object payload to. Default: stdout.") flags.Bool(rawFlag, false, rawFlagDesc) } @@ -195,11 +195,10 @@ func marshalECInfo(cmd *cobra.Command, info *objectSDK.ECInfo) ([]byte, error) { } func getRangeList(cmd *cobra.Command) ([]objectSDK.Range, error) { - v := cmd.Flag("range").Value.String() - if len(v) == 0 { - return nil, nil + vs, err := cmd.Flags().GetStringSlice("range") + if len(vs) == 0 || err != nil { + return nil, err } - vs := strings.Split(v, ",") rs := make([]objectSDK.Range, len(vs)) for i := range vs { before, after, found := strings.Cut(vs[i], rangeSep) From a788d4477342b92f7fa9c3bc9c34be8a9c9b45df Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 24 Jan 2025 16:54:27 +0300 Subject: [PATCH 1157/1413] [#1570] cli: Use array type for attributes parameters Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/modules/object/patch.go | 10 ++++------ cmd/frostfs-cli/modules/object/put.go | 10 ++++------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/patch.go b/cmd/frostfs-cli/modules/object/patch.go index 8f03885ab8..ebc415b2f5 100644 --- a/cmd/frostfs-cli/modules/object/patch.go +++ b/cmd/frostfs-cli/modules/object/patch.go @@ -46,7 +46,7 @@ func initObjectPatchCmd() { flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) _ = objectRangeCmd.MarkFlagRequired(commonflags.OIDFlag) - flags.String(newAttrsFlagName, "", "New object attributes in form of Key1=Value1,Key2=Value2") + flags.StringSlice(newAttrsFlagName, nil, "New object attributes in form of Key1=Value1,Key2=Value2") flags.Bool(replaceAttrsFlagName, false, "Replace object attributes by new ones.") flags.StringSlice(rangeFlagName, []string{}, "Range to which patch payload is applied. Format: offset:length") flags.StringSlice(payloadFlagName, []string{}, "Path to file with patch payload.") @@ -99,11 +99,9 @@ func patch(cmd *cobra.Command, _ []string) { } func parseNewObjectAttrs(cmd *cobra.Command) ([]objectSDK.Attribute, error) { - var rawAttrs []string - - raw := cmd.Flag(newAttrsFlagName).Value.String() - if len(raw) != 0 { - rawAttrs = strings.Split(raw, ",") + rawAttrs, err := cmd.Flags().GetStringSlice(newAttrsFlagName) + if err != nil { + return nil, err } attrs := make([]objectSDK.Attribute, len(rawAttrs), len(rawAttrs)+2) // name + timestamp attributes diff --git a/cmd/frostfs-cli/modules/object/put.go b/cmd/frostfs-cli/modules/object/put.go index affe9bbba5..9e8a7cc6f1 100644 --- a/cmd/frostfs-cli/modules/object/put.go +++ b/cmd/frostfs-cli/modules/object/put.go @@ -50,7 +50,7 @@ func initObjectPutCmd() { flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) - flags.String("attributes", "", "User attributes in form of Key1=Value1,Key2=Value2") + flags.StringSlice("attributes", nil, "User attributes in form of Key1=Value1,Key2=Value2") flags.Bool("disable-filename", false, "Do not set well-known filename attribute") flags.Bool("disable-timestamp", false, "Do not set well-known timestamp attribute") flags.Uint64VarP(&putExpiredOn, commonflags.ExpireAt, "e", 0, "The last active epoch in the life of the object") @@ -214,11 +214,9 @@ func getAllObjectAttributes(cmd *cobra.Command) []objectSDK.Attribute { } func parseObjectAttrs(cmd *cobra.Command) ([]objectSDK.Attribute, error) { - var rawAttrs []string - - raw := cmd.Flag("attributes").Value.String() - if len(raw) != 0 { - rawAttrs = strings.Split(raw, ",") + rawAttrs, err := cmd.Flags().GetStringSlice("attributes") + if err != nil { + return nil, err } attrs := make([]objectSDK.Attribute, len(rawAttrs), len(rawAttrs)+2) // name + timestamp attributes From abfd9657f97f2d7b8e9227befeadf08b3fc75f03 Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Tue, 28 Jan 2025 17:43:14 +0300 Subject: [PATCH 1158/1413] [#1617] govulncheck: Use patch release with security fixes https://go.dev/doc/devel/release#go1.23.minor Signed-off-by: Vitaliy Potyarkin --- .forgejo/workflows/vulncheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index cf15005b10..8a5a818aa0 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.23' + go-version: '1.23.5' - name: Install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest From e1a984e9d8bb0cedd5597f6176b865dea5e2f3b5 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 16:09:53 +0300 Subject: [PATCH 1159/1413] [#1620] logs: Drop redundant trace_id fields `trace_id` is taken from context. Signed-off-by: Dmitrii Stepanov --- .../blobovnicza/delete.go | 2 - .../blobstor/blobovniczatree/delete.go | 2 - .../blobstor/blobovniczatree/exists.go | 4 +- .../blobstor/blobovniczatree/get.go | 2 - .../blobstor/blobovniczatree/get_range.go | 4 +- .../blobstor/blobovniczatree/put.go | 10 ++--- pkg/local_object_storage/blobstor/exists.go | 4 +- pkg/local_object_storage/engine/delete.go | 10 ++--- pkg/local_object_storage/engine/evacuate.go | 32 ++++++--------- pkg/local_object_storage/engine/get.go | 4 +- pkg/local_object_storage/engine/inhume.go | 9 +---- pkg/local_object_storage/engine/put.go | 10 ++--- pkg/local_object_storage/engine/range.go | 4 +- pkg/local_object_storage/engine/tree.go | 40 ++++++------------- pkg/local_object_storage/shard/delete.go | 7 +--- pkg/local_object_storage/shard/get.go | 7 +--- pkg/local_object_storage/shard/inhume.go | 2 - pkg/local_object_storage/shard/list.go | 4 +- pkg/services/object/put/single.go | 2 - pkg/services/replicator/process.go | 5 +-- pkg/services/replicator/pull.go | 10 ++--- pkg/services/replicator/put.go | 7 +--- pkg/services/tree/redirect.go | 4 +- pkg/services/tree/replicator.go | 7 +--- 24 files changed, 56 insertions(+), 136 deletions(-) diff --git a/pkg/local_object_storage/blobovnicza/delete.go b/pkg/local_object_storage/blobovnicza/delete.go index d821b29910..8f24b56756 100644 --- a/pkg/local_object_storage/blobovnicza/delete.go +++ b/pkg/local_object_storage/blobovnicza/delete.go @@ -6,7 +6,6 @@ import ( "syscall" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -94,7 +93,6 @@ func (b *Blobovnicza) Delete(ctx context.Context, prm DeletePrm) (DeleteRes, err b.log.Debug(ctx, logs.BlobovniczaObjectWasRemovedFromBucket, zap.String("binary size", stringifyByteSize(dataSize)), zap.String("range", stringifyBounds(sizeLowerBound, sizeUpperBound)), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) b.itemDeleted(recordSize) } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go index 8d17fc4b0e..d096791c3a 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/delete.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/delete.go @@ -10,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -86,7 +85,6 @@ func (b *Blobovniczas) Delete(ctx context.Context, prm common.DeletePrm) (res co b.log.Debug(ctx, logs.BlobovniczatreeCouldNotRemoveObjectFromLevel, zap.String("level", p), zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go index d2c99945f6..0c5e48821b 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "go.opentelemetry.io/otel/attribute" @@ -57,8 +56,7 @@ func (b *Blobovniczas) Exists(ctx context.Context, prm common.ExistsPrm) (common if !client.IsErrObjectNotFound(err) { b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get.go b/pkg/local_object_storage/blobstor/blobovniczatree/get.go index 5d158644e9..e5c83e5f2c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get.go @@ -10,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -70,7 +69,6 @@ func (b *Blobovniczas) Get(ctx context.Context, prm common.GetPrm) (res common.G b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go index 84b9bc55fb..27d13f4f30 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/get_range.go @@ -11,7 +11,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -71,8 +70,7 @@ func (b *Blobovniczas) GetRange(ctx context.Context, prm common.GetRangePrm) (re if !outOfBounds && !client.IsErrObjectNotFound(err) { b.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetObjectFromLevel, zap.String("level", p), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } if outOfBounds { return true, err diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/put.go b/pkg/local_object_storage/blobstor/blobovniczatree/put.go index 8276a25ef9..37c49d7419 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/put.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/put.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobovnicza" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -83,16 +82,14 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) i.B.reportError(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, err) } else { i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotGetActiveBlobovnicza, - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } return false, nil } if active == nil { - i.B.log.Debug(ctx, logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + i.B.log.Debug(ctx, logs.BlobovniczatreeBlobovniczaOverflowed, zap.String("level", lvlPath)) return false, nil } defer active.Close(ctx) @@ -106,8 +103,7 @@ func (i *putIterator) iterate(ctx context.Context, lvlPath string) (bool, error) } else { i.B.log.Debug(ctx, logs.BlobovniczatreeCouldNotPutObjectToActiveBlobovnicza, zap.String("path", active.SystemPath()), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } if errors.Is(err, blobovnicza.ErrNoSpace) { i.AllFull = true diff --git a/pkg/local_object_storage/blobstor/exists.go b/pkg/local_object_storage/blobstor/exists.go index f1e45fe10b..c155e15b82 100644 --- a/pkg/local_object_storage/blobstor/exists.go +++ b/pkg/local_object_storage/blobstor/exists.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -75,8 +74,7 @@ func (b *BlobStor) Exists(ctx context.Context, prm common.ExistsPrm) (common.Exi for _, err := range errors[:len(errors)-1] { b.log.Warn(ctx, logs.BlobstorErrorOccurredDuringObjectExistenceChecking, zap.Stringer("address", prm.Address), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } return common.ExistsRes{}, errors[len(errors)-1] diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 20c915da67..5e5f65fa2f 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -6,7 +6,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -148,8 +147,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo if err != nil { e.log.Warn(ctx, logs.EngineErrorDuringSearchingForObjectChildren, zap.Stringer("addr", addr), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) return false } @@ -160,8 +158,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo if err != nil { e.log.Debug(ctx, logs.EngineCouldNotInhumeObjectInShard, zap.Stringer("addr", addr), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) continue } } @@ -190,8 +187,7 @@ func (e *StorageEngine) deleteChunks( if err != nil { e.log.Debug(ctx, logs.EngineCouldNotInhumeObjectInShard, zap.Stringer("addr", addr), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) continue } } diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index b37f6b68e8..fd1530f536 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -15,7 +15,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" @@ -284,12 +283,12 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p }() e.log.Info(ctx, logs.EngineStartedShardsEvacuation, zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) + zap.Stringer("scope", prm.Scope)) err = e.getTotals(ctx, prm, shardsToEvacuate, res) if err != nil { e.log.Error(ctx, logs.EngineShardsEvacuationFailedToCount, zap.Strings("shard_ids", shardIDs), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) + zap.Stringer("scope", prm.Scope)) return err } @@ -323,7 +322,7 @@ func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, p } if err != nil { e.log.Error(ctx, logs.EngineFinishedWithErrorShardsEvacuation, zap.Error(err), zap.Strings("shard_ids", shardIDs), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), zap.Stringer("scope", prm.Scope)) + zap.Stringer("scope", prm.Scope)) return err } @@ -480,8 +479,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context err := sh.IterateOverContainers(ctx, cntPrm) if err != nil { cancel(err) - e.log.Error(ctx, logs.EngineShardsEvacuationFailedToListObjects, zap.String("shard_id", shardID), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToListObjects, zap.String("shard_id", shardID), zap.Error(err), evacuationOperationLogField) } return err } @@ -540,7 +538,7 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree e.log.Debug(ctx, logs.EngineShardsEvacuationTreeEvacuatedLocal, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), zap.String("from_shard_id", sh.ID().String()), zap.String("to_shard_id", shardID), - evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + evacuationOperationLogField) res.trEvacuated.Add(1) continue } @@ -550,26 +548,26 @@ func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, tree e.log.Error(ctx, logs.EngineShardsEvacuationFailedToMoveTree, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, - zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) return err } if moved { e.log.Debug(ctx, logs.EngineShardsEvacuationTreeEvacuatedRemote, zap.String("cid", contTree.CID.EncodeToString()), zap.String("treeID", contTree.TreeID), zap.String("from_shardID", sh.ID().String()), zap.String("to_node", nodePK), - evacuationOperationLogField, zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + evacuationOperationLogField) res.trEvacuated.Add(1) } else if prm.IgnoreErrors { res.trFailed.Add(1) e.log.Warn(ctx, logs.EngineShardsEvacuationFailedToMoveTree, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, - zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } else { e.log.Error(ctx, logs.EngineShardsEvacuationFailedToMoveTree, zap.String("cid", contTree.CID.EncodeToString()), zap.String("tree_id", contTree.TreeID), zap.String("from_shard_id", sh.ID().String()), evacuationOperationLogField, - zap.Error(err), zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) return fmt.Errorf("no remote nodes available to replicate tree '%s' of container %s", contTree.TreeID, contTree.CID) } } @@ -756,8 +754,7 @@ func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objI res.objFailed.Add(1) return nil } - e.log.Error(ctx, logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToReadObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField) return err } @@ -778,16 +775,14 @@ func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objI moved, err := prm.ObjectsHandler(ctx, addr, getRes.Object()) if err != nil { - e.log.Error(ctx, logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + e.log.Error(ctx, logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField) return err } if moved { res.objEvacuated.Add(1) } else if prm.IgnoreErrors { res.objFailed.Add(1) - e.log.Warn(ctx, logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + e.log.Warn(ctx, logs.EngineShardsEvacuationFailedToMoveObject, zap.String("address", addr.EncodeToString()), zap.Error(err), evacuationOperationLogField) } else { return fmt.Errorf("object %s was not replicated", addr) } @@ -825,8 +820,7 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add zap.Stringer("from", sh.ID()), zap.Stringer("to", shards[j].ID()), zap.Stringer("addr", addr), - evacuationOperationLogField, - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + evacuationOperationLogField) return true, nil case putToShardExists, putToShardRemoved: res.objSkipped.Add(1) diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index 81b027c269..74c64bbb60 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -107,8 +106,7 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { e.log.Warn(ctx, logs.ShardMetaInfoPresentButObjectNotFound, zap.Stringer("shard_id", it.ShardWithMeta.ID()), zap.Error(it.MetaError), - zap.Stringer("address", prm.addr), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Stringer("address", prm.addr)) } } diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 75bd15c8bd..fb802ef2ab 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -99,7 +98,6 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) error { e.log.Warn(ctx, logs.EngineCouldNotInhumeObjectInShard, zap.Error(errors.New("this shard was expected to exist")), zap.String("shard_id", shardID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) return errInhumeFailure } @@ -197,7 +195,6 @@ func (e *StorageEngine) findShards(ctx context.Context, addr oid.Address, checkL e.log.Warn(ctx, logs.EngineRemovingAnObjectWithoutFullLockingCheck, zap.Error(err), zap.Stringer("address", addr), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } else if isLocked { retErr = new(apistatus.ObjectLocked) @@ -232,8 +229,7 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { locked, err = h.Shard.IsLocked(ctx, addr) if err != nil { - e.reportShardError(ctx, h, "can't check object's lockers", err, zap.Stringer("address", addr), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + e.reportShardError(ctx, h, "can't check object's lockers", err, zap.Stringer("address", addr)) outErr = err return false } @@ -262,8 +258,7 @@ func (e *StorageEngine) GetLocks(ctx context.Context, addr oid.Address) ([]oid.I e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { locks, err := h.Shard.GetLocks(ctx, addr) if err != nil { - e.reportShardError(ctx, h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + e.reportShardError(ctx, h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr)) outErr = err } allLocks = append(allLocks, locks...) diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index c79b6e2519..64288a5118 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" @@ -143,8 +142,7 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti } else { e.log.Warn(ctx, logs.EngineCouldNotCheckObjectExistence, zap.Stringer("shard_id", sh.ID()), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } return // this is not ErrAlreadyRemoved error so we can go to the next shard @@ -165,15 +163,13 @@ func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool uti errors.Is(err, common.ErrReadOnly) || errors.Is(err, common.ErrNoSpace) { e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, zap.Stringer("shard_id", sh.ID()), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) return } if client.IsErrObjectAlreadyRemoved(err) { e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, zap.Stringer("shard_id", sh.ID()), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) res.status = putToShardRemoved res.err = err return diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index 600e7266c9..a468cf5944 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -119,8 +118,7 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error e.log.Warn(ctx, logs.ShardMetaInfoPresentButObjectNotFound, zap.Stringer("shard_id", it.ShardWithMeta.ID()), zap.Error(it.MetaError), - zap.Stringer("address", prm.addr), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Stringer("address", prm.addr)) } } diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index 268b4adfaa..7f70d36f74 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.opentelemetry.io/otel/attribute" @@ -39,8 +38,7 @@ func (e *StorageEngine) TreeMove(ctx context.Context, d pilorama.CIDDescriptor, if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(ctx, lst[index], "can't perform `TreeMove`", err, zap.Stringer("cid", d.CID), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } return nil, err @@ -73,8 +71,7 @@ func (e *StorageEngine) TreeAddByPath(ctx context.Context, d pilorama.CIDDescrip if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(ctx, lst[index], "can't perform `TreeAddByPath`", err, zap.Stringer("cid", d.CID), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } return nil, err } @@ -102,8 +99,7 @@ func (e *StorageEngine) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID str if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(ctx, lst[index], "can't perform `TreeApply`", err, zap.Stringer("cid", cnr), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } return err } @@ -130,8 +126,7 @@ func (e *StorageEngine) TreeApplyBatch(ctx context.Context, cnr cidSDK.ID, treeI if !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(ctx, lst[index], "can't perform `TreeApplyBatch`", err, zap.Stringer("cid", cnr), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } return err } @@ -162,8 +157,7 @@ func (e *StorageEngine) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(ctx, sh, "can't perform `TreeGetByPath`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } continue } @@ -195,8 +189,7 @@ func (e *StorageEngine) TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID s if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(ctx, sh, "can't perform `TreeGetMeta`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } continue } @@ -227,8 +220,7 @@ func (e *StorageEngine) TreeGetChildren(ctx context.Context, cid cidSDK.ID, tree if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(ctx, sh, "can't perform `TreeGetChildren`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } continue } @@ -259,8 +251,7 @@ func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(ctx, sh, "can't perform `TreeSortedByFilename`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } continue } @@ -291,8 +282,7 @@ func (e *StorageEngine) TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(ctx, sh, "can't perform `TreeGetOpLog`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } continue } @@ -321,8 +311,7 @@ func (e *StorageEngine) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID stri if !errors.Is(err, pilorama.ErrTreeNotFound) && !errors.Is(err, shard.ErrReadOnlyMode) { e.reportShardError(ctx, sh, "can't perform `TreeDrop`", err, zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } continue } @@ -350,8 +339,7 @@ func (e *StorageEngine) TreeList(ctx context.Context, cid cidSDK.ID) ([]string, } e.reportShardError(ctx, sh, "can't perform `TreeList`", err, - zap.Stringer("cid", cid), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Stringer("cid", cid)) // returns as much info about // trees as possible @@ -417,8 +405,7 @@ func (e *StorageEngine) TreeUpdateLastSyncHeight(ctx context.Context, cid cidSDK if err != nil && !errors.Is(err, shard.ErrReadOnlyMode) && err != shard.ErrPiloramaDisabled { e.reportShardError(ctx, lst[index], "can't update tree synchronization height", err, zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } return err } @@ -444,8 +431,7 @@ func (e *StorageEngine) TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, t if !errors.Is(err, pilorama.ErrTreeNotFound) { e.reportShardError(ctx, sh, "can't read tree synchronization height", err, zap.Stringer("cid", cid), - zap.String("tree", treeID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("tree", treeID)) } continue } diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index fb6769b51c..55231b0322 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -112,8 +111,7 @@ func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error if err != nil { s.log.Debug(ctx, logs.StorageIDRetrievalFailure, zap.Stringer("object", addr), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) return err } storageID := res.StorageID() @@ -132,8 +130,7 @@ func (s *Shard) deleteFromBlobstor(ctx context.Context, addr oid.Address) error if err != nil && !client.IsErrObjectNotFound(err) { s.log.Debug(ctx, logs.ObjectRemovalFailureBlobStor, zap.Stringer("object_address", addr), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) return err } return nil diff --git a/pkg/local_object_storage/shard/get.go b/pkg/local_object_storage/shard/get.go index 15d1eb6bac..05823c62bd 100644 --- a/pkg/local_object_storage/shard/get.go +++ b/pkg/local_object_storage/shard/get.go @@ -10,7 +10,6 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -155,14 +154,12 @@ func (s *Shard) fetchObjectData(ctx context.Context, addr oid.Address, skipMeta if client.IsErrObjectNotFound(err) { s.log.Debug(ctx, logs.ShardObjectIsMissingInWritecache, zap.Stringer("addr", addr), - zap.Bool("skip_meta", skipMeta), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Bool("skip_meta", skipMeta)) } else { s.log.Error(ctx, logs.ShardFailedToFetchObjectFromWritecache, zap.Error(err), zap.Stringer("addr", addr), - zap.Bool("skip_meta", skipMeta), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Bool("skip_meta", skipMeta)) } } if skipMeta || mErr != nil { diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index d464008692..9d5f660637 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" @@ -111,7 +110,6 @@ func (s *Shard) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { s.log.Debug(ctx, logs.ShardCouldNotMarkObjectToDeleteInMetabase, zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) s.m.RUnlock() diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index c5275dafd9..7bc5ead1d7 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -124,8 +123,7 @@ func (s *Shard) List(ctx context.Context) (res SelectRes, err error) { if err != nil { s.log.Debug(ctx, logs.ShardCantSelectAllObjects, zap.Stringer("cid", lst[i]), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) continue } diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index 5219e64d56..fec50b1d95 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -21,7 +21,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal" svcutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectAPI "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc" @@ -323,7 +322,6 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, zap.Stringer("address", addr), zap.Stringer("object_id", objID), zap.Stringer("container_id", cnrID), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) } diff --git a/pkg/services/replicator/process.go b/pkg/services/replicator/process.go index 69395bb021..8c6f0df060 100644 --- a/pkg/services/replicator/process.go +++ b/pkg/services/replicator/process.go @@ -6,7 +6,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "go.opentelemetry.io/otel/attribute" @@ -45,8 +44,7 @@ func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res T if err != nil { p.log.Error(ctx, logs.ReplicatorCouldNotGetObjectFromLocalStorage, zap.Stringer("object", task.Addr), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) return } @@ -65,7 +63,6 @@ func (p *Replicator) HandleReplicationTask(ctx context.Context, task Task, res T log := p.log.With( zap.String("node", netmap.StringifyPublicKey(task.Nodes[i])), zap.Stringer("object", task.Addr), - zap.String("trace_id", tracingPkg.GetTraceID(ctx)), ) callCtx, cancel := context.WithTimeout(ctx, p.putTimeout) diff --git a/pkg/services/replicator/pull.go b/pkg/services/replicator/pull.go index 5ce9293425..bb38c72ad6 100644 --- a/pkg/services/replicator/pull.go +++ b/pkg/services/replicator/pull.go @@ -8,7 +8,6 @@ import ( containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" @@ -51,15 +50,13 @@ func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { p.log.Error(ctx, logs.ReplicatorCouldNotGetObjectFromRemoteStorage, zap.Stringer("object", task.Addr), zap.Error(err), - zap.Strings("endpoints", endpoints), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Strings("endpoints", endpoints)) } if obj == nil { p.log.Error(ctx, logs.ReplicatorCouldNotGetObjectFromRemoteStorage, zap.Stringer("object", task.Addr), - zap.Error(errFailedToGetObjectFromAnyNode), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(errFailedToGetObjectFromAnyNode)) return } @@ -67,7 +64,6 @@ func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { if err != nil { p.log.Error(ctx, logs.ReplicatorCouldNotPutObjectToLocalStorage, zap.Stringer("object", task.Addr), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } } diff --git a/pkg/services/replicator/put.go b/pkg/services/replicator/put.go index 489f66ae56..bcad8471da 100644 --- a/pkg/services/replicator/put.go +++ b/pkg/services/replicator/put.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -33,8 +32,7 @@ func (p *Replicator) HandleLocalPutTask(ctx context.Context, task Task) { if task.Obj == nil { p.log.Error(ctx, logs.ReplicatorCouldNotPutObjectToLocalStorage, zap.Stringer("object", task.Addr), - zap.Error(errObjectNotDefined), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(errObjectNotDefined)) return } @@ -42,7 +40,6 @@ func (p *Replicator) HandleLocalPutTask(ctx context.Context, task Task) { if err != nil { p.log.Error(ctx, logs.ReplicatorCouldNotPutObjectToLocalStorage, zap.Stringer("object", task.Addr), - zap.Error(err), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.Error(err)) } } diff --git a/pkg/services/tree/redirect.go b/pkg/services/tree/redirect.go index 416a0fafeb..d92c749a82 100644 --- a/pkg/services/tree/redirect.go +++ b/pkg/services/tree/redirect.go @@ -6,7 +6,6 @@ import ( "errors" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "go.opentelemetry.io/otel/attribute" @@ -54,8 +53,7 @@ func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo return false } - s.log.Debug(ctx, logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + s.log.Debug(ctx, logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint)) called = true stop = f(c) diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index e0085d73af..bcbb73589e 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -10,7 +10,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" - tracingPkg "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -117,14 +116,12 @@ func (s *Service) ReplicateTreeOp(ctx context.Context, n netmapSDK.NodeInfo, req if lastErr != nil { if errors.Is(lastErr, errRecentlyFailed) { s.log.Debug(ctx, logs.TreeDoNotSendUpdateToTheNode, - zap.String("last_error", lastErr.Error()), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("last_error", lastErr.Error())) } else { s.log.Warn(ctx, logs.TreeFailedToSentUpdateToTheNode, zap.String("last_error", lastErr.Error()), zap.String("address", lastAddr), - zap.String("key", hex.EncodeToString(n.PublicKey())), - zap.String("trace_id", tracingPkg.GetTraceID(ctx))) + zap.String("key", hex.EncodeToString(n.PublicKey()))) } s.metrics.AddReplicateTaskDuration(time.Since(start), false) return lastErr From c0a341a7f6f02cc5e5a419287fab841251f4f4cc Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 27 Jan 2025 14:17:58 +0300 Subject: [PATCH 1160/1413] [#1616] getsvc: Move head assembling to a separate file Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/assembler.go | 37 ------------------- pkg/services/object/get/assembler_head.go | 45 +++++++++++++++++++++++ 2 files changed, 45 insertions(+), 37 deletions(-) create mode 100644 pkg/services/object/get/assembler_head.go diff --git a/pkg/services/object/get/assembler.go b/pkg/services/object/get/assembler.go index ff3f90bf2d..23fc187f58 100644 --- a/pkg/services/object/get/assembler.go +++ b/pkg/services/object/get/assembler.go @@ -71,43 +71,6 @@ func (a *assembler) Assemble(ctx context.Context, writer ObjectWriter) (*objectS return a.parentObject, nil } -func (a *assembler) assembleHeader(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { - var sourceObjectIDs []oid.ID - sourceObjectID, ok := a.splitInfo.Link() - if ok { - sourceObjectIDs = append(sourceObjectIDs, sourceObjectID) - } - sourceObjectID, ok = a.splitInfo.LastPart() - if ok { - sourceObjectIDs = append(sourceObjectIDs, sourceObjectID) - } - if len(sourceObjectIDs) == 0 { - return nil, objectSDK.NewSplitInfoError(a.splitInfo) - } - for _, sourceObjectID = range sourceObjectIDs { - obj, err := a.getParent(ctx, sourceObjectID, writer) - if err == nil { - return obj, nil - } - } - return nil, objectSDK.NewSplitInfoError(a.splitInfo) -} - -func (a *assembler) getParent(ctx context.Context, sourceObjectID oid.ID, writer ObjectWriter) (*objectSDK.Object, error) { - obj, err := a.objGetter.HeadObject(ctx, sourceObjectID) - if err != nil { - return nil, err - } - parent := obj.Parent() - if parent == nil { - return nil, objectSDK.NewSplitInfoError(a.splitInfo) - } - if err := writer.WriteHeader(ctx, parent); err != nil { - return nil, err - } - return obj, nil -} - func (a *assembler) getLastPartOrLinkObjectID() (oid.ID, bool) { sourceObjectID, ok := a.splitInfo.Link() if ok { diff --git a/pkg/services/object/get/assembler_head.go b/pkg/services/object/get/assembler_head.go new file mode 100644 index 0000000000..ff213cb821 --- /dev/null +++ b/pkg/services/object/get/assembler_head.go @@ -0,0 +1,45 @@ +package getsvc + +import ( + "context" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +) + +func (a *assembler) assembleHeader(ctx context.Context, writer ObjectWriter) (*objectSDK.Object, error) { + var sourceObjectIDs []oid.ID + sourceObjectID, ok := a.splitInfo.Link() + if ok { + sourceObjectIDs = append(sourceObjectIDs, sourceObjectID) + } + sourceObjectID, ok = a.splitInfo.LastPart() + if ok { + sourceObjectIDs = append(sourceObjectIDs, sourceObjectID) + } + if len(sourceObjectIDs) == 0 { + return nil, objectSDK.NewSplitInfoError(a.splitInfo) + } + for _, sourceObjectID = range sourceObjectIDs { + obj, err := a.getParent(ctx, sourceObjectID, writer) + if err == nil { + return obj, nil + } + } + return nil, objectSDK.NewSplitInfoError(a.splitInfo) +} + +func (a *assembler) getParent(ctx context.Context, sourceObjectID oid.ID, writer ObjectWriter) (*objectSDK.Object, error) { + obj, err := a.objGetter.HeadObject(ctx, sourceObjectID) + if err != nil { + return nil, err + } + parent := obj.Parent() + if parent == nil { + return nil, objectSDK.NewSplitInfoError(a.splitInfo) + } + if err := writer.WriteHeader(ctx, parent); err != nil { + return nil, err + } + return obj, nil +} From 6410542d1933fa35b765f4cf324b60e1f6584714 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 27 Jan 2025 14:22:46 +0300 Subject: [PATCH 1161/1413] [#1616] getsvc: Move range assembling to a separate file Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/assembler.go | 102 ++++++-------------- pkg/services/object/get/assembler_range.go | 103 +++++++++++++++++++++ 2 files changed, 129 insertions(+), 76 deletions(-) create mode 100644 pkg/services/object/get/assembler_range.go diff --git a/pkg/services/object/get/assembler.go b/pkg/services/object/get/assembler.go index 23fc187f58..886f0aabb7 100644 --- a/pkg/services/object/get/assembler.go +++ b/pkg/services/object/get/assembler.go @@ -59,15 +59,23 @@ func (a *assembler) Assemble(ctx context.Context, writer ObjectWriter) (*objectS if previousID == nil && len(childrenIDs) == 0 { return nil, objectSDK.NewSplitInfoError(a.splitInfo) } + if len(childrenIDs) > 0 { - if err := a.assembleObjectByChildrenList(ctx, childrenIDs, writer); err != nil { - return nil, err + if a.rng != nil { + err = a.assembleObjectByChildrenListRange(ctx, childrenIDs, writer) + } else { + err = a.assembleObjectByChildrenList(ctx, childrenIDs, writer) } } else { - if err := a.assemleObjectByPreviousIDInReverse(ctx, *previousID, writer); err != nil { - return nil, err + if a.rng != nil { + err = a.assemleObjectByPreviousIDInReverseRange(ctx, *previousID, writer) + } else { + err = a.assemleObjectByPreviousIDInReverse(ctx, *previousID, writer) } } + if err != nil { + return nil, err + } return a.parentObject, nil } @@ -153,26 +161,16 @@ func (a *assembler) getChildObject(ctx context.Context, id oid.ID, rng *objectSD } func (a *assembler) assembleObjectByChildrenList(ctx context.Context, childrenIDs []oid.ID, writer ObjectWriter) error { - if a.rng == nil { - if err := writer.WriteHeader(ctx, a.parentObject.CutPayload()); err != nil { - return err - } - return a.assemblePayloadByObjectIDs(ctx, writer, childrenIDs, nil, true) - } - - if err := a.assemblePayloadInReverse(ctx, writer, childrenIDs[len(childrenIDs)-1]); err != nil { + if err := writer.WriteHeader(ctx, a.parentObject.CutPayload()); err != nil { return err } - return writer.WriteChunk(ctx, a.parentObject.Payload()) + return a.assemblePayloadByObjectIDs(ctx, writer, childrenIDs, true) } func (a *assembler) assemleObjectByPreviousIDInReverse(ctx context.Context, prevID oid.ID, writer ObjectWriter) error { - if a.rng == nil { - if err := writer.WriteHeader(ctx, a.parentObject.CutPayload()); err != nil { - return err - } + if err := writer.WriteHeader(ctx, a.parentObject.CutPayload()); err != nil { + return err } - if err := a.assemblePayloadInReverse(ctx, writer, prevID); err != nil { return err } @@ -182,16 +180,9 @@ func (a *assembler) assemleObjectByPreviousIDInReverse(ctx context.Context, prev return nil } -func (a *assembler) assemblePayloadByObjectIDs(ctx context.Context, writer ObjectWriter, partIDs []oid.ID, partRanges []objectSDK.Range, verifyIsChild bool) error { - withRng := len(partRanges) > 0 && a.rng != nil - +func (a *assembler) assemblePayloadByObjectIDs(ctx context.Context, writer ObjectWriter, partIDs []oid.ID, verifyIsChild bool) error { for i := range partIDs { - var r *objectSDK.Range - if withRng { - r = &partRanges[i] - } - - _, err := a.getChildObject(ctx, partIDs[i], r, verifyIsChild, writer) + _, err := a.getChildObject(ctx, partIDs[i], nil, verifyIsChild, writer) if err != nil { return err } @@ -200,22 +191,16 @@ func (a *assembler) assemblePayloadByObjectIDs(ctx context.Context, writer Objec } func (a *assembler) assemblePayloadInReverse(ctx context.Context, writer ObjectWriter, prevID oid.ID) error { - chain, rngs, err := a.buildChain(ctx, prevID) + chain, err := a.buildChain(ctx, prevID) if err != nil { return err } - reverseRngs := len(rngs) > 0 - for left, right := 0, len(chain)-1; left < right; left, right = left+1, right-1 { chain[left], chain[right] = chain[right], chain[left] - - if reverseRngs { - rngs[left], rngs[right] = rngs[right], rngs[left] - } } - return a.assemblePayloadByObjectIDs(ctx, writer, chain, rngs, false) + return a.assemblePayloadByObjectIDs(ctx, writer, chain, false) } func (a *assembler) isChild(obj *objectSDK.Object) bool { @@ -223,63 +208,28 @@ func (a *assembler) isChild(obj *objectSDK.Object) bool { return parent == nil || equalAddresses(a.addr, object.AddressOf(parent)) } -func (a *assembler) buildChain(ctx context.Context, prevID oid.ID) ([]oid.ID, []objectSDK.Range, error) { +func (a *assembler) buildChain(ctx context.Context, prevID oid.ID) ([]oid.ID, error) { var ( chain []oid.ID - rngs []objectSDK.Range - from = a.rng.GetOffset() - to = from + a.rng.GetLength() hasPrev = true ) // fill the chain end-to-start for hasPrev { - // check that only for "range" requests, - // for `GET` it stops via the false `withPrev` - if a.rng != nil && a.currentOffset <= from { - break - } - head, err := a.objGetter.HeadObject(ctx, prevID) if err != nil { - return nil, nil, err + return nil, err } if !a.isChild(head) { - return nil, nil, errParentAddressDiffers + return nil, errParentAddressDiffers } - if a.rng != nil { - sz := head.PayloadSize() - - a.currentOffset -= sz - - if a.currentOffset < to { - off := uint64(0) - if from > a.currentOffset { - off = from - a.currentOffset - sz -= from - a.currentOffset - } - - if to < a.currentOffset+off+sz { - sz = to - off - a.currentOffset - } - - index := len(rngs) - rngs = append(rngs, objectSDK.Range{}) - rngs[index].SetOffset(off) - rngs[index].SetLength(sz) - - id, _ := head.ID() - chain = append(chain, id) - } - } else { - id, _ := head.ID() - chain = append(chain, id) - } + id, _ := head.ID() + chain = append(chain, id) prevID, hasPrev = head.PreviousID() } - return chain, rngs, nil + return chain, nil } diff --git a/pkg/services/object/get/assembler_range.go b/pkg/services/object/get/assembler_range.go new file mode 100644 index 0000000000..638db0c762 --- /dev/null +++ b/pkg/services/object/get/assembler_range.go @@ -0,0 +1,103 @@ +package getsvc + +import ( + "context" + + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" +) + +func (a *assembler) assembleObjectByChildrenListRange(ctx context.Context, childrenIDs []oid.ID, writer ObjectWriter) error { + if err := a.assemblePayloadInReverseRange(ctx, writer, childrenIDs[len(childrenIDs)-1]); err != nil { + return err + } + return writer.WriteChunk(ctx, a.parentObject.Payload()) +} + +func (a *assembler) assemleObjectByPreviousIDInReverseRange(ctx context.Context, prevID oid.ID, writer ObjectWriter) error { + if err := a.assemblePayloadInReverseRange(ctx, writer, prevID); err != nil { + return err + } + if err := writer.WriteChunk(ctx, a.parentObject.Payload()); err != nil { // last part + return err + } + return nil +} + +func (a *assembler) assemblePayloadByObjectIDsRange(ctx context.Context, writer ObjectWriter, partIDs []oid.ID, partRanges []objectSDK.Range) error { + for i := range partIDs { + _, err := a.getChildObject(ctx, partIDs[i], &partRanges[i], false, writer) + if err != nil { + return err + } + } + return nil +} + +func (a *assembler) assemblePayloadInReverseRange(ctx context.Context, writer ObjectWriter, prevID oid.ID) error { + chain, rngs, err := a.buildChainRange(ctx, prevID) + if err != nil { + return err + } + + for left, right := 0, len(chain)-1; left < right; left, right = left+1, right-1 { + chain[left], chain[right] = chain[right], chain[left] + rngs[left], rngs[right] = rngs[right], rngs[left] + } + + return a.assemblePayloadByObjectIDsRange(ctx, writer, chain, rngs) +} + +func (a *assembler) buildChainRange(ctx context.Context, prevID oid.ID) ([]oid.ID, []objectSDK.Range, error) { + var ( + chain []oid.ID + rngs []objectSDK.Range + from = a.rng.GetOffset() + to = from + a.rng.GetLength() + + hasPrev = true + ) + + // fill the chain end-to-start + for hasPrev { + if a.currentOffset <= from { + break + } + + head, err := a.objGetter.HeadObject(ctx, prevID) + if err != nil { + return nil, nil, err + } + if !a.isChild(head) { + return nil, nil, errParentAddressDiffers + } + + sz := head.PayloadSize() + + a.currentOffset -= sz + + if a.currentOffset < to { + off := uint64(0) + if from > a.currentOffset { + off = from - a.currentOffset + sz -= from - a.currentOffset + } + + if to < a.currentOffset+off+sz { + sz = to - off - a.currentOffset + } + + index := len(rngs) + rngs = append(rngs, objectSDK.Range{}) + rngs[index].SetOffset(off) + rngs[index].SetLength(sz) + + id, _ := head.ID() + chain = append(chain, id) + } + + prevID, hasPrev = head.PreviousID() + } + + return chain, rngs, nil +} From c8acdf40bbd18970fb39130f78ea64959f072f4b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Mon, 27 Jan 2025 14:24:06 +0300 Subject: [PATCH 1162/1413] [#1616] getsvc: Use slices.Reverse() where possible Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/assembler.go | 6 ++---- pkg/services/object/get/assembler_range.go | 8 +++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/pkg/services/object/get/assembler.go b/pkg/services/object/get/assembler.go index 886f0aabb7..b24c9417ba 100644 --- a/pkg/services/object/get/assembler.go +++ b/pkg/services/object/get/assembler.go @@ -2,6 +2,7 @@ package getsvc import ( "context" + "slices" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -196,10 +197,7 @@ func (a *assembler) assemblePayloadInReverse(ctx context.Context, writer ObjectW return err } - for left, right := 0, len(chain)-1; left < right; left, right = left+1, right-1 { - chain[left], chain[right] = chain[right], chain[left] - } - + slices.Reverse(chain) return a.assemblePayloadByObjectIDs(ctx, writer, chain, false) } diff --git a/pkg/services/object/get/assembler_range.go b/pkg/services/object/get/assembler_range.go index 638db0c762..748a499ef5 100644 --- a/pkg/services/object/get/assembler_range.go +++ b/pkg/services/object/get/assembler_range.go @@ -2,6 +2,7 @@ package getsvc import ( "context" + "slices" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -40,11 +41,8 @@ func (a *assembler) assemblePayloadInReverseRange(ctx context.Context, writer Ob return err } - for left, right := 0, len(chain)-1; left < right; left, right = left+1, right-1 { - chain[left], chain[right] = chain[right], chain[left] - rngs[left], rngs[right] = rngs[right], rngs[left] - } - + slices.Reverse(chain) + slices.Reverse(rngs) return a.assemblePayloadByObjectIDsRange(ctx, writer, chain, rngs) } From b309b34bfc77db01c77a6b98b6143aefc1673fcc Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 28 Jan 2025 15:01:02 +0300 Subject: [PATCH 1163/1413] [#1616] getsvc: Simplify buildChainRange() Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/assembler_range.go | 24 +++++++--------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/pkg/services/object/get/assembler_range.go b/pkg/services/object/get/assembler_range.go index 748a499ef5..844a471a6c 100644 --- a/pkg/services/object/get/assembler_range.go +++ b/pkg/services/object/get/assembler_range.go @@ -70,30 +70,20 @@ func (a *assembler) buildChainRange(ctx context.Context, prevID oid.ID) ([]oid.I return nil, nil, errParentAddressDiffers } - sz := head.PayloadSize() - - a.currentOffset -= sz - - if a.currentOffset < to { - off := uint64(0) - if from > a.currentOffset { - off = from - a.currentOffset - sz -= from - a.currentOffset - } - - if to < a.currentOffset+off+sz { - sz = to - off - a.currentOffset - } - + nextOffset := a.currentOffset - head.PayloadSize() + clampedFrom := max(from, nextOffset) + clampedTo := min(to, a.currentOffset) + if clampedFrom < clampedTo { index := len(rngs) rngs = append(rngs, objectSDK.Range{}) - rngs[index].SetOffset(off) - rngs[index].SetLength(sz) + rngs[index].SetOffset(clampedFrom - nextOffset) + rngs[index].SetLength(clampedTo - clampedFrom) id, _ := head.ID() chain = append(chain, id) } + a.currentOffset = nextOffset prevID, hasPrev = head.PreviousID() } From 57dc0a8e9e69567213f87616d0080a6c12182019 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 29 Jan 2025 12:23:05 +0300 Subject: [PATCH 1164/1413] [#1616] getsvc: Move break condition from body to the loop condition Signed-off-by: Evgenii Stratonikov --- pkg/services/object/get/assembler_range.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/services/object/get/assembler_range.go b/pkg/services/object/get/assembler_range.go index 844a471a6c..780693c409 100644 --- a/pkg/services/object/get/assembler_range.go +++ b/pkg/services/object/get/assembler_range.go @@ -57,11 +57,7 @@ func (a *assembler) buildChainRange(ctx context.Context, prevID oid.ID) ([]oid.I ) // fill the chain end-to-start - for hasPrev { - if a.currentOffset <= from { - break - } - + for hasPrev && from < a.currentOffset { head, err := a.objGetter.HeadObject(ctx, prevID) if err != nil { return nil, nil, err From 78bfd1222908d4ff4e8163f3e045fa2d7e478fcb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 30 Jan 2025 15:29:38 +0300 Subject: [PATCH 1165/1413] [#1622] adm: Return non zero return code if metabase upgrade failed Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-adm/internal/modules/metabase/upgrade.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go index beced0d7a4..c0c290c5ed 100644 --- a/cmd/frostfs-adm/internal/modules/metabase/upgrade.go +++ b/cmd/frostfs-adm/internal/modules/metabase/upgrade.go @@ -28,6 +28,7 @@ const ( var ( errNoPathsFound = errors.New("no metabase paths found") errNoMorphEndpointsFound = errors.New("no morph endpoints found") + errUpgradeFailed = errors.New("upgrade failed") ) var UpgradeCmd = &cobra.Command{ @@ -91,14 +92,19 @@ func upgrade(cmd *cobra.Command, _ []string) error { if err := eg.Wait(); err != nil { return err } + allSuccess := true for mb, ok := range result { if ok { cmd.Println(mb, ": success") } else { cmd.Println(mb, ": failed") + allSuccess = false } } - return nil + if allSuccess { + return nil + } + return errUpgradeFailed } func getMetabasePaths(appCfg *config.Config) ([]string, error) { From 9ee3dd4e91bea626eedee35f751fddaedf9c9621 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 28 Jan 2025 18:32:14 +0300 Subject: [PATCH 1166/1413] [#1618] ape: Fix object service request tests Constant string `testOwnerID` for these tests has an invalid format. It has 11 bytes instead of required 25 for `user.ID`. It worked because: 1. `user.ID` was a byte slice and didn't check length and format of byte slices decoded from strings. 2. in these tests `testOwnerID` was used only to decode container owner id and to compare it with owner id encoded back to string. Since `user.ID implementation has changed`, the problem arised. Now `testOwnerID` is valid. Signed-off-by: Ekaterina Lebedeva --- pkg/services/object/ape/request_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index 787785b608..f270bf97db 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -19,7 +19,7 @@ import ( ) const ( - testOwnerID = "FPPtmAi9TCX329" + testOwnerID = "NURFM8PWbLA2aLt2vrD8q4FyfAdgESwM8y" incomingIP = "192.92.33.1" ) From 24054cf6f4c9b2cae443ea5b9741602eaca57a22 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 28 Jan 2025 18:49:45 +0300 Subject: [PATCH 1167/1413] [#1618] pkg: Refactor `user.ID.ScriptHash()` usage `user.ID.ScriptHash()` does not return an error anymore. Signed-off-by: Ekaterina Lebedeva --- go.mod | 2 +- go.sum | 4 ++-- pkg/morph/client/balance/balanceOf.go | 5 +---- pkg/morph/client/balance/transfer.go | 13 +++---------- pkg/services/container/ape.go | 10 ++-------- pkg/services/container/ape_test.go | 22 ++++++++-------------- 6 files changed, 17 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index 267e411fba..95efa584e1 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250109084609-328d214d2d76 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250129133430-d195cb510401 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 diff --git a/go.sum b/go.sum index 935d3c56a7..3be3f22462 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250109084609-328d214d2d76 h1:wzvSJIiS+p9qKfl3eg1oH6qlrjaEWiqTc/iMDKG3Ml4= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250109084609-328d214d2d76/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250129133430-d195cb510401 h1:5EN6YsbF5u2BffTKo5kVwe+Aqcy6CRTTVKcwZOI+Ym0= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250129133430-d195cb510401/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= diff --git a/pkg/morph/client/balance/balanceOf.go b/pkg/morph/client/balance/balanceOf.go index a5fb8e82ac..449d49e5a3 100644 --- a/pkg/morph/client/balance/balanceOf.go +++ b/pkg/morph/client/balance/balanceOf.go @@ -11,10 +11,7 @@ import ( // BalanceOf receives the amount of funds in the client's account // through the Balance contract call, and returns it. func (c *Client) BalanceOf(id user.ID) (*big.Int, error) { - h, err := id.ScriptHash() - if err != nil { - return nil, err - } + h := id.ScriptHash() invokePrm := client.TestInvokePrm{} invokePrm.SetMethod(balanceOfMethod) diff --git a/pkg/morph/client/balance/transfer.go b/pkg/morph/client/balance/transfer.go index 52d69dccb8..870bed1661 100644 --- a/pkg/morph/client/balance/transfer.go +++ b/pkg/morph/client/balance/transfer.go @@ -22,22 +22,15 @@ type TransferPrm struct { // TransferX transfers p.Amount of GASe-12 from p.From to p.To // with details p.Details through direct smart contract call. func (c *Client) TransferX(ctx context.Context, p TransferPrm) error { - from, err := p.From.ScriptHash() - if err != nil { - return err - } - - to, err := p.To.ScriptHash() - if err != nil { - return err - } + from := p.From.ScriptHash() + to := p.To.ScriptHash() prm := client.InvokePrm{} prm.SetMethod(transferXMethod) prm.SetArgs(from, to, p.Amount, p.Details) prm.InvokePrmOptional = p.InvokePrmOptional - _, err = c.client.Invoke(ctx, prm) + _, err := c.client.Invoke(ctx, prm) if err != nil { return fmt.Errorf("invoke method (%s): %w", transferXMethod, err) } diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 493452fa6c..2c240412b8 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -649,10 +649,7 @@ func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { if err := ownerSDK.ReadFromV2(*owner); err != nil { return "", err } - addr, err := ownerSDK.ScriptHash() - if err != nil { - return "", err - } + addr := ownerSDK.ScriptHash() namespace := "" subject, err := ac.frostFSIDClient.GetSubject(addr) @@ -674,10 +671,7 @@ func (ac *apeChecker) namespaceByKnownOwner(owner *refs.OwnerID) (string, error) if err := ownerSDK.ReadFromV2(*owner); err != nil { return "", err } - addr, err := ownerSDK.ScriptHash() - if err != nil { - return "", err - } + addr := ownerSDK.ScriptHash() subject, err := ac.frostFSIDClient.GetSubject(addr) if err != nil { return "", fmt.Errorf("get subject error: %w", err) diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 513ffff023..38b240d944 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -678,8 +678,7 @@ func testDenyPutContainerForOthersSessionToken(t *testing.T) { testContainer := containertest.Container() owner := testContainer.Owner() - ownerAddr, err := owner.ScriptHash() - require.NoError(t, err) + ownerAddr := owner.ScriptHash() frostfsIDSubjectReader := &frostfsidStub{ subjects: map[util.Uint160]*client.Subject{ ownerAddr: {}, @@ -690,7 +689,7 @@ func testDenyPutContainerForOthersSessionToken(t *testing.T) { nm.currentEpoch = 100 nm.netmaps = map[uint64]*netmap.NetMap{} - _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{ + _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{ Rules: []chain.Rule{ { Status: chain.AccessDenied, @@ -773,7 +772,7 @@ func testDenyPutContainerReadNamespaceFromFrostfsID(t *testing.T) { require.NoError(t, err) req := initPutRequest(t, testContainer) - ownerScriptHash := initOwnerIDScriptHash(t, testContainer) + ownerScriptHash := initOwnerIDScriptHash(testContainer) frostfsIDSubjectReader := &frostfsidStub{ subjects: map[util.Uint160]*client.Subject{ @@ -857,7 +856,7 @@ func testDenyPutContainerInvalidNamespace(t *testing.T) { require.NoError(t, err) req := initPutRequest(t, testContainer) - ownerScriptHash := initOwnerIDScriptHash(t, testContainer) + ownerScriptHash := initOwnerIDScriptHash(testContainer) frostfsIDSubjectReader := &frostfsidStub{ subjects: map[util.Uint160]*client.Subject{ @@ -1532,26 +1531,21 @@ func initPutRequest(t *testing.T, testContainer cnrSDK.Container) *container.Put return req } -func initOwnerIDScriptHash(t *testing.T, testContainer cnrSDK.Container) util.Uint160 { +func initOwnerIDScriptHash(testContainer cnrSDK.Container) util.Uint160 { var ownerSDK *user.ID owner := testContainer.Owner() ownerSDK = &owner - sc, err := ownerSDK.ScriptHash() - require.NoError(t, err) - return sc + return ownerSDK.ScriptHash() } func initActorOwnerScriptHashes(t *testing.T, actorPK *keys.PrivateKey, ownerPK *keys.PrivateKey) (actorScriptHash util.Uint160, ownerScriptHash util.Uint160) { var actorUserID user.ID user.IDFromKey(&actorUserID, ecdsa.PublicKey(*actorPK.PublicKey())) - var err error - actorScriptHash, err = actorUserID.ScriptHash() - require.NoError(t, err) + actorScriptHash = actorUserID.ScriptHash() var ownerUserID user.ID user.IDFromKey(&ownerUserID, ecdsa.PublicKey(*ownerPK.PublicKey())) - ownerScriptHash, err = ownerUserID.ScriptHash() - require.NoError(t, err) + ownerScriptHash = ownerUserID.ScriptHash() require.NotEqual(t, ownerScriptHash.String(), actorScriptHash.String()) return } From 6a580db55effc5d824d3f6f53b2c3bab07781f93 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 30 Jan 2025 16:06:14 +0300 Subject: [PATCH 1168/1413] [#1626] go.mod: Bump frostfs-sdk-go Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 95efa584e1..e3f44569e1 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250129133430-d195cb510401 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250130095343-593dd77d841a git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 diff --git a/go.sum b/go.sum index 3be3f22462..e0aacb4541 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250129133430-d195cb510401 h1:5EN6YsbF5u2BffTKo5kVwe+Aqcy6CRTTVKcwZOI+Ym0= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250129133430-d195cb510401/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250130095343-593dd77d841a h1:Ud+3zz4WP9HPxEQxDPJZPpiPdm30nDNSKucsWP9L54M= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250130095343-593dd77d841a/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= From 1df64c5caba97eb0b03a4a2220517cd8c649dac1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 30 Jan 2025 10:23:30 +0300 Subject: [PATCH 1169/1413] [#1621] treesvc: Move variable initialization to top in mergeOperationStreams() Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/sync.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index c48a312fb6..4f32621139 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -134,11 +134,6 @@ func (s *Service) SynchronizeTree(ctx context.Context, cid cid.ID, treeID string func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *pilorama.Move) uint64 { defer close(merged) - ms := make([]*pilorama.Move, len(streams)) - for i := range streams { - ms[i] = <-streams[i] - } - // Merging different node streams shuffles incoming operations like that: // // x - operation from the stream A @@ -150,6 +145,11 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram // operation height from the stream B. This height is stored in minStreamedLastHeight. var minStreamedLastHeight uint64 = math.MaxUint64 + ms := make([]*pilorama.Move, len(streams)) + for i := range streams { + ms[i] = <-streams[i] + } + for { var minTimeMoveTime uint64 = math.MaxUint64 minTimeMoveIndex := -1 From 6fcae9f75ab822a67a7a0462cfe3cedaac155b92 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 30 Jan 2025 10:36:02 +0300 Subject: [PATCH 1170/1413] [#1621] treesvc: Cancel background sync on failure If applyOperationStream() exits prematurely, other goroutines will block on send and errgroup will never finish waiting. In this commit we also check whether context is cancelled. Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/sync.go | 35 +++++++++++++++++++++++----------- pkg/services/tree/sync_test.go | 3 ++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 4f32621139..1a455def97 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -131,7 +131,7 @@ func (s *Service) SynchronizeTree(ctx context.Context, cid cid.ID, treeID string } // mergeOperationStreams performs merge sort for node operation streams to one stream. -func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *pilorama.Move) uint64 { +func mergeOperationStreams(ctx context.Context, streams []chan *pilorama.Move, merged chan<- *pilorama.Move) uint64 { defer close(merged) // Merging different node streams shuffles incoming operations like that: @@ -147,7 +147,11 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram ms := make([]*pilorama.Move, len(streams)) for i := range streams { - ms[i] = <-streams[i] + select { + case ms[i] = <-streams[i]: + case <-ctx.Done(): + return minStreamedLastHeight + } } for { @@ -164,7 +168,11 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram break } - merged <- ms[minTimeMoveIndex] + select { + case merged <- ms[minTimeMoveIndex]: + case <-ctx.Done(): + return minStreamedLastHeight + } height := ms[minTimeMoveIndex].Time if ms[minTimeMoveIndex] = <-streams[minTimeMoveIndex]; ms[minTimeMoveIndex] == nil { minStreamedLastHeight = min(minStreamedLastHeight, height) @@ -176,7 +184,7 @@ func mergeOperationStreams(streams []chan *pilorama.Move, merged chan<- *piloram func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID string, operationStream <-chan *pilorama.Move, -) uint64 { +) (uint64, error) { var prev *pilorama.Move var batch []*pilorama.Move for m := range operationStream { @@ -189,17 +197,17 @@ func (s *Service) applyOperationStream(ctx context.Context, cid cid.ID, treeID s if len(batch) == s.syncBatchSize { if err := s.forest.TreeApplyBatch(ctx, cid, treeID, batch); err != nil { - return batch[0].Time + return batch[0].Time, err } batch = batch[:0] } } if len(batch) > 0 { if err := s.forest.TreeApplyBatch(ctx, cid, treeID, batch); err != nil { - return batch[0].Time + return batch[0].Time, err } } - return math.MaxUint64 + return math.MaxUint64, nil } func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, @@ -235,7 +243,11 @@ func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, if err := m.Meta.FromBytes(lm.GetMeta()); err != nil { return err } - opsCh <- m + select { + case opsCh <- m: + case <-ctx.Done(): + return ctx.Err() + } } if !errors.Is(err, io.EOF) { return err @@ -264,13 +276,14 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, merged := make(chan *pilorama.Move) var minStreamedLastHeight uint64 errGroup.Go(func() error { - minStreamedLastHeight = mergeOperationStreams(nodeOperationStreams, merged) + minStreamedLastHeight = mergeOperationStreams(egCtx, nodeOperationStreams, merged) return nil }) var minUnappliedHeight uint64 errGroup.Go(func() error { - minUnappliedHeight = s.applyOperationStream(ctx, cid, treeID, merged) - return nil + var err error + minUnappliedHeight, err = s.applyOperationStream(egCtx, cid, treeID, merged) + return err }) var allNodesSynced atomic.Bool diff --git a/pkg/services/tree/sync_test.go b/pkg/services/tree/sync_test.go index 497d90554e..87d419408f 100644 --- a/pkg/services/tree/sync_test.go +++ b/pkg/services/tree/sync_test.go @@ -1,6 +1,7 @@ package tree import ( + "context" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" @@ -64,7 +65,7 @@ func Test_mergeOperationStreams(t *testing.T) { merged := make(chan *pilorama.Move, 1) min := make(chan uint64) go func() { - min <- mergeOperationStreams(nodeOpChans, merged) + min <- mergeOperationStreams(context.Background(), nodeOpChans, merged) }() var res []uint64 From 9c4c5a52625180ae8491cee184d2f8583f541e75 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 14 Jan 2025 16:37:48 +0300 Subject: [PATCH 1171/1413] [#1602] go.mod: Update sdk-go Signed-off-by: Aleksey Savchuk --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e3f44569e1..cc6b0a2028 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250130095343-593dd77d841a + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 diff --git a/go.sum b/go.sum index e0aacb4541..eae467b310 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250130095343-593dd77d841a h1:Ud+3zz4WP9HPxEQxDPJZPpiPdm30nDNSKucsWP9L54M= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250130095343-593dd77d841a/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421 h1:pP19IawSdsLCKFv7HMNfWAeH6E3uSnntKZkwka+/2+4= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= From 4de5fca547359398cd4b6bbf801f15d0bd603b83 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 3 Feb 2025 17:36:21 +0300 Subject: [PATCH 1172/1413] [#1624] blobovniczatree: Return source error from Init() As it was before: when the database was opened, an error returned, but along with the original error, the `context cancelled`` error returned, because `iterateIncompletedRebuildDBPaths` method has `ctx.Done()` check and egCtx passed to `iterateIncompletedRebuildDBPaths` method. Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/control.go | 53 +++++++++---------- .../blobstor/blobovniczatree/control_test.go | 34 ++++++++++++ 2 files changed, 60 insertions(+), 27 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control.go b/pkg/local_object_storage/blobstor/blobovniczatree/control.go index c77df63bf6..a6c1ce3685 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control.go @@ -41,35 +41,34 @@ func (b *Blobovniczas) initializeDBs(ctx context.Context) error { } eg, egCtx := errgroup.WithContext(ctx) - eg.SetLimit(b.blzInitWorkerCount) - err = b.iterateIncompletedRebuildDBPaths(egCtx, func(p string) (bool, error) { - eg.Go(func() error { - p = strings.TrimSuffix(p, rebuildSuffix) - shBlz := b.getBlobovniczaWithoutCaching(p) - blz, err := shBlz.Open(egCtx) - if err != nil { - return err - } - defer shBlz.Close(egCtx) - - moveInfo, err := blz.ListMoveInfo(egCtx) - if err != nil { - return err - } - for _, move := range moveInfo { - b.deleteProtectedObjects.Add(move.Address) - } - - b.log.Debug(egCtx, logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) - return nil - }) - return false, nil - }) - if err != nil { - _ = eg.Wait() - return err + if b.blzInitWorkerCount > 0 { + eg.SetLimit(b.blzInitWorkerCount + 1) } + eg.Go(func() error { + return b.iterateIncompletedRebuildDBPaths(egCtx, func(p string) (bool, error) { + eg.Go(func() error { + p = strings.TrimSuffix(p, rebuildSuffix) + shBlz := b.getBlobovniczaWithoutCaching(p) + blz, err := shBlz.Open(egCtx) + if err != nil { + return err + } + defer shBlz.Close(egCtx) + moveInfo, err := blz.ListMoveInfo(egCtx) + if err != nil { + return err + } + for _, move := range moveInfo { + b.deleteProtectedObjects.Add(move.Address) + } + + b.log.Debug(egCtx, logs.BlobovniczatreeBlobovniczaSuccessfullyInitializedClosing, zap.String("id", p)) + return nil + }) + return false, nil + }) + }) return eg.Wait() } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go index b26323bd0d..7db1891f96 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/control_test.go @@ -2,6 +2,9 @@ package blobovniczatree import ( "context" + "os" + "path" + "strconv" "testing" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -129,3 +132,34 @@ func TestObjectsAvailableAfterDepthAndWidthEdit(t *testing.T) { require.NoError(t, blz.Close(context.Background())) } + +func TestInitBlobovniczasInitErrorType(t *testing.T) { + t.Parallel() + + rootDir := t.TempDir() + + for idx := 0; idx < 10; idx++ { + f, err := os.Create(path.Join(rootDir, strconv.FormatInt(int64(idx), 10)+".db")) + require.NoError(t, err) + _, err = f.Write([]byte("invalid db")) + require.NoError(t, err) + require.NoError(t, f.Close()) + + f, err = os.Create(path.Join(rootDir, strconv.FormatInt(int64(idx), 10)+".db"+rebuildSuffix)) + require.NoError(t, err) + require.NoError(t, f.Close()) + } + + blz := NewBlobovniczaTree( + context.Background(), + WithBlobovniczaShallowDepth(1), + WithBlobovniczaShallowWidth(1), + WithRootPath(rootDir), + ) + + require.NoError(t, blz.Open(mode.ComponentReadWrite)) + err := blz.Init() + require.Contains(t, err.Error(), "open blobovnicza") + require.Contains(t, err.Error(), "invalid database") + require.NoError(t, blz.Close(context.Background())) +} From 9b113c315668fd26a9d43f8b29c9139fcf3fbb5e Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 5 Feb 2025 16:37:11 +0300 Subject: [PATCH 1173/1413] [#1613] morph: Add tracing for morph queries to neo-go Signed-off-by: Alexander Chuprov --- .../modules/control/set_netmap_status.go | 2 +- cmd/frostfs-cli/modules/object/nodes.go | 4 +- cmd/frostfs-node/cache.go | 62 ++++++++------- cmd/frostfs-node/cache_test.go | 11 +-- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/container.go | 22 +++--- cmd/frostfs-node/frostfsid.go | 9 ++- cmd/frostfs-node/netmap.go | 20 ++--- cmd/frostfs-node/object.go | 10 +-- cmd/frostfs-node/tree.go | 12 +-- pkg/ape/request/frostfsid.go | 9 ++- pkg/core/container/info.go | 13 ++-- pkg/core/container/storage.go | 6 +- pkg/core/container/util.go | 5 +- pkg/core/frostfsid/subject_provider.go | 6 +- pkg/core/netmap/storage.go | 16 ++-- pkg/core/object/fmt.go | 2 +- pkg/core/object/fmt_test.go | 14 ++-- pkg/core/object/sender_classifier.go | 15 ++-- pkg/innerring/fetcher.go | 10 ++- pkg/innerring/indexer.go | 19 ++--- pkg/innerring/indexer_test.go | 47 ++++++------ pkg/innerring/innerring.go | 12 +-- pkg/innerring/netmap.go | 5 +- .../processors/alphabet/handlers_test.go | 2 +- .../processors/alphabet/process_emit.go | 2 +- .../processors/alphabet/processor.go | 2 +- pkg/innerring/processors/container/common.go | 13 ++-- .../processors/container/handlers_test.go | 8 +- .../processors/container/process_container.go | 48 ++++++------ .../processors/container/processor.go | 8 +- .../processors/governance/handlers_test.go | 4 +- .../processors/governance/process_update.go | 4 +- .../processors/governance/processor.go | 4 +- .../processors/netmap/handlers_test.go | 8 +- .../netmap/nodevalidation/locode/calls.go | 3 +- .../nodevalidation/locode/calls_test.go | 9 ++- .../netmap/nodevalidation/maddress/calls.go | 3 +- .../netmap/nodevalidation/state/validator.go | 7 +- .../nodevalidation/state/validator_test.go | 5 +- .../netmap/nodevalidation/validator.go | 6 +- .../processors/netmap/process_epoch.go | 4 +- .../processors/netmap/process_peers.go | 4 +- pkg/innerring/processors/netmap/processor.go | 6 +- pkg/innerring/processors/netmap/wrappers.go | 8 +- pkg/innerring/state.go | 6 +- pkg/local_object_storage/engine/engine.go | 2 +- pkg/local_object_storage/engine/evacuate.go | 2 +- .../engine/evacuate_test.go | 4 +- pkg/local_object_storage/metabase/upgrade.go | 10 +-- pkg/local_object_storage/shard/control.go | 2 +- pkg/morph/client/balance/balanceOf.go | 5 +- pkg/morph/client/balance/decimals.go | 5 +- pkg/morph/client/client.go | 2 +- pkg/morph/client/container/containers_of.go | 9 ++- pkg/morph/client/container/deletion_info.go | 15 ++-- pkg/morph/client/container/get.go | 15 ++-- pkg/morph/client/container/list.go | 5 +- pkg/morph/client/frostfsid/subject.go | 9 ++- pkg/morph/client/netmap/config.go | 48 ++++++------ pkg/morph/client/netmap/epoch.go | 9 ++- pkg/morph/client/netmap/innerring.go | 4 +- pkg/morph/client/netmap/netmap.go | 13 ++-- pkg/morph/client/netmap/snapshot.go | 5 +- pkg/morph/client/static.go | 5 +- pkg/services/accounting/morph/executor.go | 6 +- pkg/services/apemanager/executor.go | 16 ++-- pkg/services/common/ape/checker.go | 7 +- pkg/services/container/ape.go | 76 +++++++++---------- pkg/services/container/ape_test.go | 16 ++-- pkg/services/container/morph/executor.go | 14 ++-- pkg/services/control/ir/server/calls.go | 6 +- pkg/services/control/rpc.go | 3 + pkg/services/control/server/evacuate_async.go | 10 +-- .../control/server/get_netmap_status.go | 4 +- pkg/services/control/server/server.go | 2 +- pkg/services/netmap/executor.go | 6 +- pkg/services/object/acl/v2/service.go | 8 +- pkg/services/object/acl/v2/types.go | 4 +- pkg/services/object/ape/checker.go | 2 +- pkg/services/object/ape/checker_test.go | 16 ++-- pkg/services/object/ape/request.go | 16 ++-- pkg/services/object/common/target/target.go | 23 +++--- pkg/services/object/common/writer/common.go | 2 +- pkg/services/object/common/writer/ec.go | 12 +-- pkg/services/object/common/writer/ec_test.go | 2 +- pkg/services/object/common/writer/writer.go | 4 +- pkg/services/object/get/assemblerec.go | 2 +- pkg/services/object/get/get_test.go | 8 +- pkg/services/object/get/getrangeec_test.go | 4 +- pkg/services/object/get/remote_getter.go | 2 +- pkg/services/object/get/request.go | 4 +- pkg/services/object/get/types.go | 4 +- pkg/services/object/get/v2/get_range_hash.go | 12 +-- pkg/services/object/patch/streamer.go | 2 +- pkg/services/object/put/single.go | 14 ++-- pkg/services/object/put/streamer.go | 2 +- pkg/services/object/put/v2/streamer.go | 2 +- pkg/services/object/search/container.go | 8 +- pkg/services/object/search/exec.go | 6 +- pkg/services/object/search/search_test.go | 8 +- pkg/services/object/search/service.go | 4 +- pkg/services/object/search/util.go | 2 +- pkg/services/object/util/placement.go | 17 +++-- .../object_manager/placement/netmap.go | 7 +- .../object_manager/placement/traverser.go | 7 +- .../placement/traverser_test.go | 25 +++--- pkg/services/policer/check.go | 6 +- pkg/services/policer/ec.go | 4 +- pkg/services/policer/ec_test.go | 8 +- pkg/services/policer/policer_test.go | 30 ++++---- pkg/services/tree/ape.go | 8 +- pkg/services/tree/ape_test.go | 4 +- pkg/services/tree/container.go | 7 +- pkg/services/tree/options.go | 5 +- pkg/services/tree/replicator.go | 6 +- pkg/services/tree/service.go | 24 +++--- pkg/services/tree/signature.go | 2 +- pkg/services/tree/signature_test.go | 10 +-- pkg/services/tree/sync.go | 10 +-- 120 files changed, 623 insertions(+), 562 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/set_netmap_status.go b/cmd/frostfs-cli/modules/control/set_netmap_status.go index 87c4f3b3d8..26a1ba883d 100644 --- a/cmd/frostfs-cli/modules/control/set_netmap_status.go +++ b/cmd/frostfs-cli/modules/control/set_netmap_status.go @@ -127,7 +127,7 @@ func awaitSetNetmapStatus(cmd *cobra.Command, pk *ecdsa.PrivateKey, cli *client. var resp *control.GetNetmapStatusResponse var err error err = cli.ExecRaw(func(client *rawclient.Client) error { - resp, err = control.GetNetmapStatus(client, req) + resp, err = control.GetNetmapStatus(cmd.Context(), client, req) return err }) commonCmd.ExitOnErr(cmd, "failed to get current netmap status: %w", err) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 31682c0e18..1500830a2e 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -320,7 +320,7 @@ func getReplicaRequiredPlacement(cmd *cobra.Command, objects []phyObject, placem } placementBuilder := placement.NewNetworkMapBuilder(netmap) for _, object := range objects { - placement, err := placementBuilder.BuildPlacement(object.containerID, &object.objectID, placementPolicy) + placement, err := placementBuilder.BuildPlacement(cmd.Context(), object.containerID, &object.objectID, placementPolicy) commonCmd.ExitOnErr(cmd, "failed to get required placement for object: %w", err) for repIdx, rep := range placement { numOfReplicas := placementPolicy.ReplicaDescriptor(repIdx).NumberOfObjects() @@ -358,7 +358,7 @@ func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placem placementObjectID = object.ecHeader.parent } placementBuilder := placement.NewNetworkMapBuilder(netmap) - placement, err := placementBuilder.BuildPlacement(object.containerID, &placementObjectID, placementPolicy) + placement, err := placementBuilder.BuildPlacement(cmd.Context(), object.containerID, &placementObjectID, placementPolicy) commonCmd.ExitOnErr(cmd, "failed to get required placement: %w", err) for _, vector := range placement { diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index b906417994..0fe56d2b08 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -1,6 +1,7 @@ package main import ( + "context" "sync" "time" @@ -16,7 +17,7 @@ import ( "github.com/hashicorp/golang-lru/v2/expirable" ) -type netValueReader[K any, V any] func(K) (V, error) +type netValueReader[K any, V any] func(ctx context.Context, cid K) (V, error) type valueWithError[V any] struct { v V @@ -49,7 +50,7 @@ func newNetworkTTLCache[K comparable, V any](sz int, ttl time.Duration, netRdr n // updates the value from the network on cache miss or by TTL. // // returned value should not be modified. -func (c *ttlNetCache[K, V]) get(key K) (V, error) { +func (c *ttlNetCache[K, V]) get(ctx context.Context, key K) (V, error) { hit := false startedAt := time.Now() defer func() { @@ -71,7 +72,7 @@ func (c *ttlNetCache[K, V]) get(key K) (V, error) { return val.v, val.e } - v, err := c.netRdr(key) + v, err := c.netRdr(ctx, key) c.cache.Add(key, &valueWithError[V]{ v: v, @@ -135,7 +136,7 @@ func newNetworkLRUCache(sz int, netRdr netValueReader[uint64, *netmapSDK.NetMap] // updates the value from the network on cache miss. // // returned value should not be modified. -func (c *lruNetCache) get(key uint64) (*netmapSDK.NetMap, error) { +func (c *lruNetCache) get(ctx context.Context, key uint64) (*netmapSDK.NetMap, error) { hit := false startedAt := time.Now() defer func() { @@ -148,7 +149,7 @@ func (c *lruNetCache) get(key uint64) (*netmapSDK.NetMap, error) { return val, nil } - val, err := c.netRdr(key) + val, err := c.netRdr(ctx, key) if err != nil { return nil, err } @@ -166,11 +167,11 @@ type ttlContainerStorage struct { } func newCachedContainerStorage(v container.Source, ttl time.Duration, containerCacheSize uint32) ttlContainerStorage { - lruCnrCache := newNetworkTTLCache(int(containerCacheSize), ttl, func(id cid.ID) (*container.Container, error) { - return v.Get(id) + lruCnrCache := newNetworkTTLCache(int(containerCacheSize), ttl, func(ctx context.Context, id cid.ID) (*container.Container, error) { + return v.Get(ctx, id) }, metrics.NewCacheMetrics("container")) - lruDelInfoCache := newNetworkTTLCache(int(containerCacheSize), ttl, func(id cid.ID) (*container.DelInfo, error) { - return v.DeletionInfo(id) + lruDelInfoCache := newNetworkTTLCache(int(containerCacheSize), ttl, func(ctx context.Context, id cid.ID) (*container.DelInfo, error) { + return v.DeletionInfo(ctx, id) }, metrics.NewCacheMetrics("container_deletion_info")) return ttlContainerStorage{ @@ -188,12 +189,12 @@ func (s ttlContainerStorage) handleRemoval(cnr cid.ID) { // Get returns container value from the cache. If value is missing in the cache // or expired, then it returns value from side chain and updates the cache. -func (s ttlContainerStorage) Get(cnr cid.ID) (*container.Container, error) { - return s.containerCache.get(cnr) +func (s ttlContainerStorage) Get(ctx context.Context, cnr cid.ID) (*container.Container, error) { + return s.containerCache.get(ctx, cnr) } -func (s ttlContainerStorage) DeletionInfo(cnr cid.ID) (*container.DelInfo, error) { - return s.delInfoCache.get(cnr) +func (s ttlContainerStorage) DeletionInfo(ctx context.Context, cnr cid.ID) (*container.DelInfo, error) { + return s.delInfoCache.get(ctx, cnr) } type lruNetmapSource struct { @@ -205,8 +206,8 @@ type lruNetmapSource struct { func newCachedNetmapStorage(s netmap.State, v netmap.Source) netmap.Source { const netmapCacheSize = 10 - lruNetmapCache := newNetworkLRUCache(netmapCacheSize, func(key uint64) (*netmapSDK.NetMap, error) { - return v.GetNetMapByEpoch(key) + lruNetmapCache := newNetworkLRUCache(netmapCacheSize, func(ctx context.Context, key uint64) (*netmapSDK.NetMap, error) { + return v.GetNetMapByEpoch(ctx, key) }, metrics.NewCacheMetrics("netmap")) return &lruNetmapSource{ @@ -215,16 +216,16 @@ func newCachedNetmapStorage(s netmap.State, v netmap.Source) netmap.Source { } } -func (s *lruNetmapSource) GetNetMap(diff uint64) (*netmapSDK.NetMap, error) { - return s.getNetMapByEpoch(s.netState.CurrentEpoch() - diff) +func (s *lruNetmapSource) GetNetMap(ctx context.Context, diff uint64) (*netmapSDK.NetMap, error) { + return s.getNetMapByEpoch(ctx, s.netState.CurrentEpoch()-diff) } -func (s *lruNetmapSource) GetNetMapByEpoch(epoch uint64) (*netmapSDK.NetMap, error) { - return s.getNetMapByEpoch(epoch) +func (s *lruNetmapSource) GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmapSDK.NetMap, error) { + return s.getNetMapByEpoch(ctx, epoch) } -func (s *lruNetmapSource) getNetMapByEpoch(epoch uint64) (*netmapSDK.NetMap, error) { - val, err := s.cache.get(epoch) +func (s *lruNetmapSource) getNetMapByEpoch(ctx context.Context, epoch uint64) (*netmapSDK.NetMap, error) { + val, err := s.cache.get(ctx, epoch) if err != nil { return nil, err } @@ -232,7 +233,7 @@ func (s *lruNetmapSource) getNetMapByEpoch(epoch uint64) (*netmapSDK.NetMap, err return val, nil } -func (s *lruNetmapSource) Epoch() (uint64, error) { +func (s *lruNetmapSource) Epoch(_ context.Context) (uint64, error) { return s.netState.CurrentEpoch(), nil } @@ -240,7 +241,10 @@ type cachedIRFetcher struct { *ttlNetCache[struct{}, [][]byte] } -func newCachedIRFetcher(f interface{ InnerRingKeys() ([][]byte, error) }) cachedIRFetcher { +func newCachedIRFetcher(f interface { + InnerRingKeys(ctx context.Context) ([][]byte, error) +}, +) cachedIRFetcher { const ( irFetcherCacheSize = 1 // we intend to store only one value @@ -254,8 +258,8 @@ func newCachedIRFetcher(f interface{ InnerRingKeys() ([][]byte, error) }) cached ) irFetcherCache := newNetworkTTLCache(irFetcherCacheSize, irFetcherCacheTTL, - func(_ struct{}) ([][]byte, error) { - return f.InnerRingKeys() + func(ctx context.Context, _ struct{}) ([][]byte, error) { + return f.InnerRingKeys(ctx) }, metrics.NewCacheMetrics("ir_keys"), ) @@ -265,8 +269,8 @@ func newCachedIRFetcher(f interface{ InnerRingKeys() ([][]byte, error) }) cached // InnerRingKeys returns cached list of Inner Ring keys. If keys are missing in // the cache or expired, then it returns keys from side chain and updates // the cache. -func (f cachedIRFetcher) InnerRingKeys() ([][]byte, error) { - val, err := f.get(struct{}{}) +func (f cachedIRFetcher) InnerRingKeys(ctx context.Context) ([][]byte, error) { + val, err := f.get(ctx, struct{}{}) if err != nil { return nil, err } @@ -289,7 +293,7 @@ func newCachedMaxObjectSizeSource(src objectwriter.MaxSizeSource) objectwriter.M } } -func (c *ttlMaxObjectSizeCache) MaxObjectSize() uint64 { +func (c *ttlMaxObjectSizeCache) MaxObjectSize(ctx context.Context) uint64 { const ttl = time.Second * 30 hit := false @@ -311,7 +315,7 @@ func (c *ttlMaxObjectSizeCache) MaxObjectSize() uint64 { c.mtx.Lock() size = c.lastSize if !c.lastUpdated.After(prevUpdated) { - size = c.src.MaxObjectSize() + size = c.src.MaxObjectSize(ctx) c.lastSize = size c.lastUpdated = time.Now() } diff --git a/cmd/frostfs-node/cache_test.go b/cmd/frostfs-node/cache_test.go index f8c324a2f5..b1601aa677 100644 --- a/cmd/frostfs-node/cache_test.go +++ b/cmd/frostfs-node/cache_test.go @@ -1,6 +1,7 @@ package main import ( + "context" "errors" "testing" "time" @@ -17,7 +18,7 @@ func TestTTLNetCache(t *testing.T) { t.Run("Test Add and Get", func(t *testing.T) { ti := time.Now() cache.set(key, ti, nil) - val, err := cache.get(key) + val, err := cache.get(context.Background(), key) require.NoError(t, err) require.Equal(t, ti, val) }) @@ -26,7 +27,7 @@ func TestTTLNetCache(t *testing.T) { ti := time.Now() cache.set(key, ti, nil) time.Sleep(2 * ttlDuration) - val, err := cache.get(key) + val, err := cache.get(context.Background(), key) require.NoError(t, err) require.NotEqual(t, val, ti) }) @@ -35,20 +36,20 @@ func TestTTLNetCache(t *testing.T) { ti := time.Now() cache.set(key, ti, nil) cache.remove(key) - val, err := cache.get(key) + val, err := cache.get(context.Background(), key) require.NoError(t, err) require.NotEqual(t, val, ti) }) t.Run("Test Cache Error", func(t *testing.T) { cache.set("error", time.Now(), errors.New("mock error")) - _, err := cache.get("error") + _, err := cache.get(context.Background(), "error") require.Error(t, err) require.Equal(t, "mock error", err.Error()) }) } -func testNetValueReader(key string) (time.Time, error) { +func testNetValueReader(_ context.Context, key string) (time.Time, error) { if key == "error" { return time.Now(), errors.New("mock error") } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 3e9cd4e111..75d6f6dec0 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1205,7 +1205,7 @@ func (c *cfg) setContractNodeInfo(ni *netmap.NodeInfo) { } func (c *cfg) updateContractNodeInfo(ctx context.Context, epoch uint64) { - ni, err := c.netmapLocalNodeState(epoch) + ni, err := c.netmapLocalNodeState(ctx, epoch) if err != nil { c.log.Error(ctx, logs.FrostFSNodeCouldNotUpdateNodeStateOnNewEpoch, zap.Uint64("epoch", epoch), diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 98fea9f415..0120122972 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -100,7 +100,7 @@ func configureEACLAndContainerSources(c *cfg, client *cntClient.Client, cnrSrc c // TODO: use owner directly from the event after neofs-contract#256 will become resolved // but don't forget about the profit of reading the new container and caching it: // creation success are most commonly tracked by polling GET op. - cnr, err := cnrSrc.Get(ev.ID) + cnr, err := cnrSrc.Get(ctx, ev.ID) if err == nil { containerCache.containerCache.set(ev.ID, cnr, nil) } else { @@ -221,25 +221,25 @@ type morphContainerReader struct { src containerCore.Source lister interface { - ContainersOf(*user.ID) ([]cid.ID, error) - IterateContainersOf(*user.ID, func(cid.ID) error) error + ContainersOf(context.Context, *user.ID) ([]cid.ID, error) + IterateContainersOf(context.Context, *user.ID, func(cid.ID) error) error } } -func (x *morphContainerReader) Get(id cid.ID) (*containerCore.Container, error) { - return x.src.Get(id) +func (x *morphContainerReader) Get(ctx context.Context, id cid.ID) (*containerCore.Container, error) { + return x.src.Get(ctx, id) } -func (x *morphContainerReader) DeletionInfo(id cid.ID) (*containerCore.DelInfo, error) { - return x.src.DeletionInfo(id) +func (x *morphContainerReader) DeletionInfo(ctx context.Context, id cid.ID) (*containerCore.DelInfo, error) { + return x.src.DeletionInfo(ctx, id) } -func (x *morphContainerReader) ContainersOf(id *user.ID) ([]cid.ID, error) { - return x.lister.ContainersOf(id) +func (x *morphContainerReader) ContainersOf(ctx context.Context, id *user.ID) ([]cid.ID, error) { + return x.lister.ContainersOf(ctx, id) } -func (x *morphContainerReader) IterateContainersOf(id *user.ID, processCID func(cid.ID) error) error { - return x.lister.IterateContainersOf(id, processCID) +func (x *morphContainerReader) IterateContainersOf(ctx context.Context, id *user.ID, processCID func(cid.ID) error) error { + return x.lister.IterateContainersOf(ctx, id, processCID) } type morphContainerWriter struct { diff --git a/cmd/frostfs-node/frostfsid.go b/cmd/frostfs-node/frostfsid.go index 3cca091059..d2d4e97858 100644 --- a/cmd/frostfs-node/frostfsid.go +++ b/cmd/frostfs-node/frostfsid.go @@ -1,6 +1,7 @@ package main import ( + "context" "strings" "time" @@ -42,7 +43,7 @@ func newMorphFrostfsIDCache(subjProvider frostfsidcore.SubjectProvider, size int } } -func (m *morphFrostfsIDCache) GetSubject(addr util.Uint160) (*client.Subject, error) { +func (m *morphFrostfsIDCache) GetSubject(ctx context.Context, addr util.Uint160) (*client.Subject, error) { hit := false startedAt := time.Now() defer func() { @@ -55,7 +56,7 @@ func (m *morphFrostfsIDCache) GetSubject(addr util.Uint160) (*client.Subject, er return result.subject, result.err } - subj, err := m.subjProvider.GetSubject(addr) + subj, err := m.subjProvider.GetSubject(ctx, addr) if err != nil { if m.isCacheableError(err) { m.subjCache.Add(addr, subjectWithError{ @@ -69,7 +70,7 @@ func (m *morphFrostfsIDCache) GetSubject(addr util.Uint160) (*client.Subject, er return subj, nil } -func (m *morphFrostfsIDCache) GetSubjectExtended(addr util.Uint160) (*client.SubjectExtended, error) { +func (m *morphFrostfsIDCache) GetSubjectExtended(ctx context.Context, addr util.Uint160) (*client.SubjectExtended, error) { hit := false startedAt := time.Now() defer func() { @@ -82,7 +83,7 @@ func (m *morphFrostfsIDCache) GetSubjectExtended(addr util.Uint160) (*client.Sub return result.subject, result.err } - subjExt, err := m.subjProvider.GetSubjectExtended(addr) + subjExt, err := m.subjProvider.GetSubjectExtended(ctx, addr) if err != nil { if m.isCacheableError(err) { m.subjExtCache.Add(addr, subjectExtWithError{ diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 34cd00ac8a..0e90e77075 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -239,7 +239,7 @@ func setNetmapNotificationParser(c *cfg, sTyp string, p event.NotificationParser // initNetmapState inits current Network map state. // Must be called after Morph components initialization. func initNetmapState(ctx context.Context, c *cfg) { - epoch, err := c.cfgNetmap.wrapper.Epoch() + epoch, err := c.cfgNetmap.wrapper.Epoch(ctx) fatalOnErrDetails("could not initialize current epoch number", err) var ni *netmapSDK.NodeInfo @@ -278,7 +278,7 @@ func nodeState(ni *netmapSDK.NodeInfo) string { } func (c *cfg) netmapInitLocalNodeState(ctx context.Context, epoch uint64) (*netmapSDK.NodeInfo, error) { - nmNodes, err := c.cfgNetmap.wrapper.GetCandidates() + nmNodes, err := c.cfgNetmap.wrapper.GetCandidates(ctx) if err != nil { return nil, err } @@ -291,7 +291,7 @@ func (c *cfg) netmapInitLocalNodeState(ctx context.Context, epoch uint64) (*netm } } - node, err := c.netmapLocalNodeState(epoch) + node, err := c.netmapLocalNodeState(ctx, epoch) if err != nil { return nil, err } @@ -312,9 +312,9 @@ func (c *cfg) netmapInitLocalNodeState(ctx context.Context, epoch uint64) (*netm return candidate, nil } -func (c *cfg) netmapLocalNodeState(epoch uint64) (*netmapSDK.NodeInfo, error) { +func (c *cfg) netmapLocalNodeState(ctx context.Context, epoch uint64) (*netmapSDK.NodeInfo, error) { // calculate current network state - nm, err := c.cfgNetmap.wrapper.GetNetMapByEpoch(epoch) + nm, err := c.cfgNetmap.wrapper.GetNetMapByEpoch(ctx, epoch) if err != nil { return nil, err } @@ -376,8 +376,8 @@ func (c *cfg) SetNetmapStatus(ctx context.Context, st control.NetmapStatus) erro return c.updateNetMapState(ctx, func(*nmClient.UpdatePeerPrm) {}) } -func (c *cfg) GetNetmapStatus() (control.NetmapStatus, uint64, error) { - epoch, err := c.netMapSource.Epoch() +func (c *cfg) GetNetmapStatus(ctx context.Context) (control.NetmapStatus, uint64, error) { + epoch, err := c.netMapSource.Epoch(ctx) if err != nil { return control.NetmapStatus_STATUS_UNDEFINED, 0, fmt.Errorf("failed to get current epoch: %w", err) } @@ -390,7 +390,7 @@ func (c *cfg) ForceMaintenance(ctx context.Context) error { } func (c *cfg) setMaintenanceStatus(ctx context.Context, force bool) error { - netSettings, err := c.cfgNetmap.wrapper.ReadNetworkConfiguration() + netSettings, err := c.cfgNetmap.wrapper.ReadNetworkConfiguration(ctx) if err != nil { err = fmt.Errorf("read network settings to check maintenance allowance: %w", err) } else if !netSettings.MaintenanceModeAllowed { @@ -438,7 +438,7 @@ type netInfo struct { msPerBlockRdr func() (int64, error) } -func (n *netInfo) Dump(ver version.Version) (*netmapSDK.NetworkInfo, error) { +func (n *netInfo) Dump(ctx context.Context, ver version.Version) (*netmapSDK.NetworkInfo, error) { magic, err := n.magic.MagicNumber() if err != nil { return nil, err @@ -448,7 +448,7 @@ func (n *netInfo) Dump(ver version.Version) (*netmapSDK.NetworkInfo, error) { ni.SetCurrentEpoch(n.netState.CurrentEpoch()) ni.SetMagicNumber(magic) - netInfoMorph, err := n.morphClientNetMap.ReadNetworkConfiguration() + netInfoMorph, err := n.morphClientNetMap.ReadNetworkConfiguration(ctx) if err != nil { return nil, fmt.Errorf("read network configuration using netmap contract client: %w", err) } diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 9392411686..77446b81ce 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -54,10 +54,10 @@ type objectSvc struct { patch *patchsvc.Service } -func (c *cfg) MaxObjectSize() uint64 { - sz, err := c.cfgNetmap.wrapper.MaxObjectSize() +func (c *cfg) MaxObjectSize(ctx context.Context) uint64 { + sz, err := c.cfgNetmap.wrapper.MaxObjectSize(ctx) if err != nil { - c.log.Error(context.Background(), logs.FrostFSNodeCouldNotGetMaxObjectSizeValue, + c.log.Error(ctx, logs.FrostFSNodeCouldNotGetMaxObjectSizeValue, zap.Error(err), ) } @@ -122,8 +122,8 @@ type innerRingFetcherWithNotary struct { sidechain *morphClient.Client } -func (fn *innerRingFetcherWithNotary) InnerRingKeys() ([][]byte, error) { - keys, err := fn.sidechain.NeoFSAlphabetList() +func (fn *innerRingFetcherWithNotary) InnerRingKeys(ctx context.Context) ([][]byte, error) { + keys, err := fn.sidechain.NeoFSAlphabetList(ctx) if err != nil { return nil, fmt.Errorf("can't get inner ring keys from alphabet role: %w", err) } diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index f3ddc8cbeb..f8330a25ea 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -29,16 +29,16 @@ type cnrSource struct { cli *containerClient.Client } -func (c cnrSource) Get(id cid.ID) (*container.Container, error) { - return c.src.Get(id) +func (c cnrSource) Get(ctx context.Context, id cid.ID) (*container.Container, error) { + return c.src.Get(ctx, id) } -func (c cnrSource) DeletionInfo(cid cid.ID) (*container.DelInfo, error) { - return c.src.DeletionInfo(cid) +func (c cnrSource) DeletionInfo(ctx context.Context, cid cid.ID) (*container.DelInfo, error) { + return c.src.DeletionInfo(ctx, cid) } -func (c cnrSource) List() ([]cid.ID, error) { - return c.cli.ContainersOf(nil) +func (c cnrSource) List(ctx context.Context) ([]cid.ID, error) { + return c.cli.ContainersOf(ctx, nil) } func initTreeService(c *cfg) { diff --git a/pkg/ape/request/frostfsid.go b/pkg/ape/request/frostfsid.go index c0413678d0..d32bd4a07e 100644 --- a/pkg/ape/request/frostfsid.go +++ b/pkg/ape/request/frostfsid.go @@ -1,6 +1,7 @@ package request import ( + "context" "fmt" "strconv" "strings" @@ -12,9 +13,9 @@ import ( ) // FormFrostfsIDRequestProperties forms frostfsid specific request properties like user-claim tags and group ID. -func FormFrostfsIDRequestProperties(frostFSIDClient frostfsidcore.SubjectProvider, pk *keys.PublicKey) (map[string]string, error) { +func FormFrostfsIDRequestProperties(ctx context.Context, frostFSIDClient frostfsidcore.SubjectProvider, pk *keys.PublicKey) (map[string]string, error) { reqProps := make(map[string]string) - subj, err := frostFSIDClient.GetSubjectExtended(pk.GetScriptHash()) + subj, err := frostFSIDClient.GetSubjectExtended(ctx, pk.GetScriptHash()) if err != nil { if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return nil, fmt.Errorf("get subject error: %w", err) @@ -36,8 +37,8 @@ func FormFrostfsIDRequestProperties(frostFSIDClient frostfsidcore.SubjectProvide } // Groups return the actor's group ids from frostfsid contract. -func Groups(frostFSIDClient frostfsidcore.SubjectProvider, pk *keys.PublicKey) ([]string, error) { - subj, err := frostFSIDClient.GetSubjectExtended(pk.GetScriptHash()) +func Groups(ctx context.Context, frostFSIDClient frostfsidcore.SubjectProvider, pk *keys.PublicKey) ([]string, error) { + subj, err := frostFSIDClient.GetSubjectExtended(ctx, pk.GetScriptHash()) if err != nil { if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return nil, fmt.Errorf("get subject error: %w", err) diff --git a/pkg/core/container/info.go b/pkg/core/container/info.go index 62cc215536..1c52d93e74 100644 --- a/pkg/core/container/info.go +++ b/pkg/core/container/info.go @@ -1,6 +1,7 @@ package container import ( + "context" "sync" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" @@ -19,7 +20,7 @@ type infoValue struct { } type InfoProvider interface { - Info(id cid.ID) (Info, error) + Info(ctx context.Context, id cid.ID) (Info, error) } type infoProvider struct { @@ -43,13 +44,13 @@ func NewInfoProvider(sourceFactory func() (Source, error)) InfoProvider { } } -func (r *infoProvider) Info(id cid.ID) (Info, error) { +func (r *infoProvider) Info(ctx context.Context, id cid.ID) (Info, error) { v, found := r.tryGetFromCache(id) if found { return v.info, v.err } - return r.getFromSource(id) + return r.getFromSource(ctx, id) } func (r *infoProvider) tryGetFromCache(id cid.ID) (infoValue, bool) { @@ -60,7 +61,7 @@ func (r *infoProvider) tryGetFromCache(id cid.ID) (infoValue, bool) { return value, found } -func (r *infoProvider) getFromSource(id cid.ID) (Info, error) { +func (r *infoProvider) getFromSource(ctx context.Context, id cid.ID) (Info, error) { r.kl.Lock(id) defer r.kl.Unlock(id) @@ -75,11 +76,11 @@ func (r *infoProvider) getFromSource(id cid.ID) (Info, error) { return Info{}, r.sourceErr } - cnr, err := r.source.Get(id) + cnr, err := r.source.Get(ctx, id) var civ infoValue if err != nil { if client.IsErrContainerNotFound(err) { - removed, err := WasRemoved(r.source, id) + removed, err := WasRemoved(ctx, r.source, id) if err != nil { civ.err = err } else { diff --git a/pkg/core/container/storage.go b/pkg/core/container/storage.go index ba44045462..4eb14e53c5 100644 --- a/pkg/core/container/storage.go +++ b/pkg/core/container/storage.go @@ -1,6 +1,8 @@ package container import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto" @@ -41,9 +43,9 @@ type Source interface { // // Implementations must not retain the container pointer and modify // the container through it. - Get(cid.ID) (*Container, error) + Get(ctx context.Context, cid cid.ID) (*Container, error) - DeletionInfo(cid.ID) (*DelInfo, error) + DeletionInfo(ctx context.Context, cid cid.ID) (*DelInfo, error) } // EACL groups information about the FrostFS container's extended ACL stored in diff --git a/pkg/core/container/util.go b/pkg/core/container/util.go index d275568078..a24b369449 100644 --- a/pkg/core/container/util.go +++ b/pkg/core/container/util.go @@ -1,6 +1,7 @@ package container import ( + "context" "errors" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -10,8 +11,8 @@ import ( // WasRemoved checks whether the container ever existed or // it just has not been created yet at the current epoch. -func WasRemoved(s Source, cid cid.ID) (bool, error) { - _, err := s.DeletionInfo(cid) +func WasRemoved(ctx context.Context, s Source, cid cid.ID) (bool, error) { + _, err := s.DeletionInfo(ctx, cid) if err == nil { return true, nil } diff --git a/pkg/core/frostfsid/subject_provider.go b/pkg/core/frostfsid/subject_provider.go index ecfd0eb157..e752043d3d 100644 --- a/pkg/core/frostfsid/subject_provider.go +++ b/pkg/core/frostfsid/subject_provider.go @@ -1,6 +1,8 @@ package frostfsid import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -11,6 +13,6 @@ const ( // SubjectProvider interface provides methods to get subject from FrostfsID contract. type SubjectProvider interface { - GetSubject(util.Uint160) (*client.Subject, error) - GetSubjectExtended(util.Uint160) (*client.SubjectExtended, error) + GetSubject(ctx context.Context, addr util.Uint160) (*client.Subject, error) + GetSubjectExtended(ctx context.Context, addr util.Uint160) (*client.SubjectExtended, error) } diff --git a/pkg/core/netmap/storage.go b/pkg/core/netmap/storage.go index 7770c61c76..97313da841 100644 --- a/pkg/core/netmap/storage.go +++ b/pkg/core/netmap/storage.go @@ -1,6 +1,8 @@ package netmap import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" ) @@ -16,7 +18,7 @@ type Source interface { // // Implementations must not retain the network map pointer and modify // the network map through it. - GetNetMap(diff uint64) (*netmap.NetMap, error) + GetNetMap(ctx context.Context, diff uint64) (*netmap.NetMap, error) // GetNetMapByEpoch reads network map by the epoch number from the storage. // It returns the pointer to the requested network map and any error encountered. @@ -25,21 +27,21 @@ type Source interface { // // Implementations must not retain the network map pointer and modify // the network map through it. - GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) + GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmap.NetMap, error) // Epoch reads the current epoch from the storage. // It returns thw number of the current epoch and any error encountered. // // Must return exactly one non-default value. - Epoch() (uint64, error) + Epoch(ctx context.Context) (uint64, error) } // GetLatestNetworkMap requests and returns the latest network map from the storage. -func GetLatestNetworkMap(src Source) (*netmap.NetMap, error) { - return src.GetNetMap(0) +func GetLatestNetworkMap(ctx context.Context, src Source) (*netmap.NetMap, error) { + return src.GetNetMap(ctx, 0) } // GetPreviousNetworkMap requests and returns previous from the latest network map from the storage. -func GetPreviousNetworkMap(src Source) (*netmap.NetMap, error) { - return src.GetNetMap(1) +func GetPreviousNetworkMap(ctx context.Context, src Source) (*netmap.NetMap, error) { + return src.GetNetMap(ctx, 1) } diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index 19b5d34e46..cf090eb375 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -199,7 +199,7 @@ func (v *FormatValidator) isIROrContainerNode(ctx context.Context, obj *objectSD cnrIDBin := make([]byte, sha256.Size) cnrID.Encode(cnrIDBin) - cnr, err := v.containers.Get(cnrID) + cnr, err := v.containers.Get(ctx, cnrID) if err != nil { return acl.RoleOthers, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err) } diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index 20560cf3a4..239a9f389d 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -578,7 +578,7 @@ type testIRSource struct { irNodes [][]byte } -func (s *testIRSource) InnerRingKeys() ([][]byte, error) { +func (s *testIRSource) InnerRingKeys(_ context.Context) ([][]byte, error) { return s.irNodes, nil } @@ -586,14 +586,14 @@ type testContainerSource struct { containers map[cid.ID]*container.Container } -func (s *testContainerSource) Get(cnrID cid.ID) (*container.Container, error) { +func (s *testContainerSource) Get(ctx context.Context, cnrID cid.ID) (*container.Container, error) { if cnr, found := s.containers[cnrID]; found { return cnr, nil } return nil, fmt.Errorf("container not found") } -func (s *testContainerSource) DeletionInfo(cid.ID) (*container.DelInfo, error) { +func (s *testContainerSource) DeletionInfo(context.Context, cid.ID) (*container.DelInfo, error) { return nil, nil } @@ -602,20 +602,20 @@ type testNetmapSource struct { currentEpoch uint64 } -func (s *testNetmapSource) GetNetMap(diff uint64) (*netmap.NetMap, error) { +func (s *testNetmapSource) GetNetMap(ctx context.Context, diff uint64) (*netmap.NetMap, error) { if diff >= s.currentEpoch { return nil, fmt.Errorf("invalid diff") } - return s.GetNetMapByEpoch(s.currentEpoch - diff) + return s.GetNetMapByEpoch(ctx, s.currentEpoch-diff) } -func (s *testNetmapSource) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { +func (s *testNetmapSource) GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmap.NetMap, error) { if nm, found := s.netmaps[epoch]; found { return nm, nil } return nil, fmt.Errorf("netmap not found") } -func (s *testNetmapSource) Epoch() (uint64, error) { +func (s *testNetmapSource) Epoch(ctx context.Context) (uint64, error) { return s.currentEpoch, nil } diff --git a/pkg/core/object/sender_classifier.go b/pkg/core/object/sender_classifier.go index a1a5fcac17..3733ed5078 100644 --- a/pkg/core/object/sender_classifier.go +++ b/pkg/core/object/sender_classifier.go @@ -18,7 +18,7 @@ import ( ) type InnerRing interface { - InnerRingKeys() ([][]byte, error) + InnerRingKeys(ctx context.Context) ([][]byte, error) } type SenderClassifier struct { @@ -63,7 +63,7 @@ func (c SenderClassifier) Classify( } func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerKeyInBytes []byte, idCnr cid.ID, cnr container.Container) (*ClassifyResult, error) { - isInnerRingNode, err := c.isInnerRingKey(ownerKeyInBytes) + isInnerRingNode, err := c.isInnerRingKey(ctx, ownerKeyInBytes) if err != nil { // do not throw error, try best case matching c.log.Debug(ctx, logs.V2CantCheckIfRequestFromInnerRing, @@ -78,7 +78,7 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerK binCnr := make([]byte, sha256.Size) idCnr.Encode(binCnr) - isContainerNode, err := c.isContainerKey(ownerKeyInBytes, binCnr, cnr) + isContainerNode, err := c.isContainerKey(ctx, ownerKeyInBytes, binCnr, cnr) if err != nil { // error might happen if request has `RoleOther` key and placement // is not possible for previous epoch, so @@ -99,8 +99,8 @@ func (c SenderClassifier) IsInnerRingOrContainerNode(ctx context.Context, ownerK }, nil } -func (c SenderClassifier) isInnerRingKey(owner []byte) (bool, error) { - innerRingKeys, err := c.innerRing.InnerRingKeys() +func (c SenderClassifier) isInnerRingKey(ctx context.Context, owner []byte) (bool, error) { + innerRingKeys, err := c.innerRing.InnerRingKeys(ctx) if err != nil { return false, err } @@ -116,10 +116,11 @@ func (c SenderClassifier) isInnerRingKey(owner []byte) (bool, error) { } func (c SenderClassifier) isContainerKey( + ctx context.Context, owner, idCnr []byte, cnr container.Container, ) (bool, error) { - nm, err := core.GetLatestNetworkMap(c.netmap) // first check current netmap + nm, err := core.GetLatestNetworkMap(ctx, c.netmap) // first check current netmap if err != nil { return false, err } @@ -133,7 +134,7 @@ func (c SenderClassifier) isContainerKey( // then check previous netmap, this can happen in-between epoch change // when node migrates data from last epoch container - nm, err = core.GetPreviousNetworkMap(c.netmap) + nm, err = core.GetPreviousNetworkMap(ctx, c.netmap) if err != nil { return false, err } diff --git a/pkg/innerring/fetcher.go b/pkg/innerring/fetcher.go index 4a80ebf3bf..7deec3f317 100644 --- a/pkg/innerring/fetcher.go +++ b/pkg/innerring/fetcher.go @@ -1,6 +1,8 @@ package innerring import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" nmClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -47,12 +49,12 @@ type IrFetcherWithoutNotary struct { // InnerRingKeys fetches list of innerring keys from NeoFSAlphabet // role in the sidechain. -func (fN IrFetcherWithNotary) InnerRingKeys() (keys.PublicKeys, error) { - return fN.cli.NeoFSAlphabetList() +func (fN IrFetcherWithNotary) InnerRingKeys(ctx context.Context) (keys.PublicKeys, error) { + return fN.cli.NeoFSAlphabetList(ctx) } // InnerRingKeys fetches list of innerring keys from netmap contract // in the sidechain. -func (f IrFetcherWithoutNotary) InnerRingKeys() (keys.PublicKeys, error) { - return f.nm.GetInnerRingList() +func (f IrFetcherWithoutNotary) InnerRingKeys(ctx context.Context) (keys.PublicKeys, error) { + return f.nm.GetInnerRingList(ctx) } diff --git a/pkg/innerring/indexer.go b/pkg/innerring/indexer.go index 45135a57b3..439400baca 100644 --- a/pkg/innerring/indexer.go +++ b/pkg/innerring/indexer.go @@ -1,6 +1,7 @@ package innerring import ( + "context" "fmt" "sync" "time" @@ -10,7 +11,7 @@ import ( type ( irFetcher interface { - InnerRingKeys() (keys.PublicKeys, error) + InnerRingKeys(ctx context.Context) (keys.PublicKeys, error) } committeeFetcher interface { @@ -45,7 +46,7 @@ func newInnerRingIndexer(comf committeeFetcher, irf irFetcher, key *keys.PublicK } } -func (s *innerRingIndexer) update() (ind indexes, err error) { +func (s *innerRingIndexer) update(ctx context.Context) (ind indexes, err error) { s.RLock() if time.Since(s.lastAccess) < s.timeout { @@ -62,7 +63,7 @@ func (s *innerRingIndexer) update() (ind indexes, err error) { return s.ind, nil } - innerRing, err := s.irFetcher.InnerRingKeys() + innerRing, err := s.irFetcher.InnerRingKeys(ctx) if err != nil { return indexes{}, err } @@ -81,8 +82,8 @@ func (s *innerRingIndexer) update() (ind indexes, err error) { return s.ind, nil } -func (s *innerRingIndexer) InnerRingIndex() (int32, error) { - ind, err := s.update() +func (s *innerRingIndexer) InnerRingIndex(ctx context.Context) (int32, error) { + ind, err := s.update(ctx) if err != nil { return 0, fmt.Errorf("can't update index state: %w", err) } @@ -90,8 +91,8 @@ func (s *innerRingIndexer) InnerRingIndex() (int32, error) { return ind.innerRingIndex, nil } -func (s *innerRingIndexer) InnerRingSize() (int32, error) { - ind, err := s.update() +func (s *innerRingIndexer) InnerRingSize(ctx context.Context) (int32, error) { + ind, err := s.update(ctx) if err != nil { return 0, fmt.Errorf("can't update index state: %w", err) } @@ -99,8 +100,8 @@ func (s *innerRingIndexer) InnerRingSize() (int32, error) { return ind.innerRingSize, nil } -func (s *innerRingIndexer) AlphabetIndex() (int32, error) { - ind, err := s.update() +func (s *innerRingIndexer) AlphabetIndex(ctx context.Context) (int32, error) { + ind, err := s.update(ctx) if err != nil { return 0, fmt.Errorf("can't update index state: %w", err) } diff --git a/pkg/innerring/indexer_test.go b/pkg/innerring/indexer_test.go index c8a819b5be..f8201b7df4 100644 --- a/pkg/innerring/indexer_test.go +++ b/pkg/innerring/indexer_test.go @@ -1,6 +1,7 @@ package innerring import ( + "context" "fmt" "sync/atomic" "testing" @@ -37,15 +38,15 @@ func TestIndexerReturnsIndexes(t *testing.T) { indexer := newInnerRingIndexer(cf, irf, key, time.Second) - idx, err := indexer.AlphabetIndex() + idx, err := indexer.AlphabetIndex(context.Background()) require.NoError(t, err, "failed to get alphabet index") require.Equal(t, int32(1), idx, "invalid alphabet index") - idx, err = indexer.InnerRingIndex() + idx, err = indexer.InnerRingIndex(context.Background()) require.NoError(t, err, "failed to get IR index") require.Equal(t, int32(2), idx, "invalid IR index") - size, err := indexer.InnerRingSize() + size, err := indexer.InnerRingSize(context.Background()) require.NoError(t, err, "failed to get IR size") require.Equal(t, int32(3), size, "invalid IR size") }) @@ -56,11 +57,11 @@ func TestIndexerReturnsIndexes(t *testing.T) { indexer := newInnerRingIndexer(cf, irf, key, time.Second) - idx, err := indexer.AlphabetIndex() + idx, err := indexer.AlphabetIndex(context.Background()) require.NoError(t, err, "failed to get alphabet index") require.Equal(t, int32(-1), idx, "invalid alphabet index") - idx, err = indexer.InnerRingIndex() + idx, err = indexer.InnerRingIndex(context.Background()) require.NoError(t, err, "failed to get IR index") require.Equal(t, int32(0), idx, "invalid IR index") }) @@ -71,11 +72,11 @@ func TestIndexerReturnsIndexes(t *testing.T) { indexer := newInnerRingIndexer(cf, irf, key, time.Second) - idx, err := indexer.AlphabetIndex() + idx, err := indexer.AlphabetIndex(context.Background()) require.NoError(t, err, "failed to get alphabet index") require.Equal(t, int32(0), idx, "invalid alphabet index") - idx, err = indexer.InnerRingIndex() + idx, err = indexer.InnerRingIndex(context.Background()) require.NoError(t, err, "failed to get IR index") require.Equal(t, int32(-1), idx, "invalid IR index") }) @@ -100,30 +101,30 @@ func TestIndexerCachesIndexes(t *testing.T) { indexer := newInnerRingIndexer(cf, irf, key, time.Second) - idx, err := indexer.AlphabetIndex() + idx, err := indexer.AlphabetIndex(context.Background()) require.NoError(t, err, "failed to get alphabet index") require.Equal(t, int32(-1), idx, "invalid alphabet index") - idx, err = indexer.InnerRingIndex() + idx, err = indexer.InnerRingIndex(context.Background()) require.NoError(t, err, "failed to get IR index") require.Equal(t, int32(-1), idx, "invalid IR index") - size, err := indexer.InnerRingSize() + size, err := indexer.InnerRingSize(context.Background()) require.NoError(t, err, "failed to get IR size") require.Equal(t, int32(0), size, "invalid IR size") require.Equal(t, int32(1), cf.calls.Load(), "invalid commitee calls count") require.Equal(t, int32(1), irf.calls.Load(), "invalid IR calls count") - idx, err = indexer.AlphabetIndex() + idx, err = indexer.AlphabetIndex(context.Background()) require.NoError(t, err, "failed to get alphabet index") require.Equal(t, int32(-1), idx, "invalid alphabet index") - idx, err = indexer.InnerRingIndex() + idx, err = indexer.InnerRingIndex(context.Background()) require.NoError(t, err, "failed to get IR index") require.Equal(t, int32(-1), idx, "invalid IR index") - size, err = indexer.InnerRingSize() + size, err = indexer.InnerRingSize(context.Background()) require.NoError(t, err, "failed to get IR size") require.Equal(t, int32(0), size, "invalid IR size") @@ -132,15 +133,15 @@ func TestIndexerCachesIndexes(t *testing.T) { time.Sleep(2 * time.Second) - idx, err = indexer.AlphabetIndex() + idx, err = indexer.AlphabetIndex(context.Background()) require.NoError(t, err, "failed to get alphabet index") require.Equal(t, int32(-1), idx, "invalid alphabet index") - idx, err = indexer.InnerRingIndex() + idx, err = indexer.InnerRingIndex(context.Background()) require.NoError(t, err, "failed to get IR index") require.Equal(t, int32(-1), idx, "invalid IR index") - size, err = indexer.InnerRingSize() + size, err = indexer.InnerRingSize(context.Background()) require.NoError(t, err, "failed to get IR size") require.Equal(t, int32(0), size, "invalid IR size") @@ -165,15 +166,15 @@ func TestIndexerThrowsErrors(t *testing.T) { indexer := newInnerRingIndexer(cf, irf, key, time.Second) - idx, err := indexer.AlphabetIndex() + idx, err := indexer.AlphabetIndex(context.Background()) require.ErrorContains(t, err, "test commitee error", "error from commitee not throwed") require.Equal(t, int32(0), idx, "invalid alphabet index") - idx, err = indexer.InnerRingIndex() + idx, err = indexer.InnerRingIndex(context.Background()) require.ErrorContains(t, err, "test commitee error", "error from IR not throwed") require.Equal(t, int32(0), idx, "invalid IR index") - size, err := indexer.InnerRingSize() + size, err := indexer.InnerRingSize(context.Background()) require.ErrorContains(t, err, "test commitee error", "error from IR not throwed") require.Equal(t, int32(0), size, "invalid IR size") @@ -189,15 +190,15 @@ func TestIndexerThrowsErrors(t *testing.T) { indexer = newInnerRingIndexer(cf, irf, key, time.Second) - idx, err = indexer.AlphabetIndex() + idx, err = indexer.AlphabetIndex(context.Background()) require.ErrorContains(t, err, "test IR error", "error from commitee not throwed") require.Equal(t, int32(0), idx, "invalid alphabet index") - idx, err = indexer.InnerRingIndex() + idx, err = indexer.InnerRingIndex(context.Background()) require.ErrorContains(t, err, "test IR error", "error from IR not throwed") require.Equal(t, int32(0), idx, "invalid IR index") - size, err = indexer.InnerRingSize() + size, err = indexer.InnerRingSize(context.Background()) require.ErrorContains(t, err, "test IR error", "error from IR not throwed") require.Equal(t, int32(0), size, "invalid IR size") } @@ -219,7 +220,7 @@ type testIRFetcher struct { calls atomic.Int32 } -func (f *testIRFetcher) InnerRingKeys() (keys.PublicKeys, error) { +func (f *testIRFetcher) InnerRingKeys(context.Context) (keys.PublicKeys, error) { f.calls.Add(1) return f.keys, f.err } diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index 0b9e834438..ae5661905c 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -575,19 +575,19 @@ func parseMultinetConfig(cfg *viper.Viper, m metrics.MultinetMetrics) internalNe func (s *Server) initConfigFromBlockchain(ctx context.Context) error { // get current epoch - epoch, err := s.netmapClient.Epoch() + epoch, err := s.netmapClient.Epoch(ctx) if err != nil { return fmt.Errorf("can't read epoch number: %w", err) } // get current epoch duration - epochDuration, err := s.netmapClient.EpochDuration() + epochDuration, err := s.netmapClient.EpochDuration(ctx) if err != nil { return fmt.Errorf("can't read epoch duration: %w", err) } // get balance precision - balancePrecision, err := s.balanceClient.Decimals() + balancePrecision, err := s.balanceClient.Decimals(ctx) if err != nil { return fmt.Errorf("can't read balance contract precision: %w", err) } @@ -597,7 +597,7 @@ func (s *Server) initConfigFromBlockchain(ctx context.Context) error { s.precision.SetBalancePrecision(balancePrecision) // get next epoch delta tick - s.initialEpochTickDelta, err = s.nextEpochBlockDelta() + s.initialEpochTickDelta, err = s.nextEpochBlockDelta(ctx) if err != nil { return err } @@ -613,8 +613,8 @@ func (s *Server) initConfigFromBlockchain(ctx context.Context) error { return nil } -func (s *Server) nextEpochBlockDelta() (uint32, error) { - epochBlock, err := s.netmapClient.LastEpochBlock() +func (s *Server) nextEpochBlockDelta(ctx context.Context) (uint32, error) { + epochBlock, err := s.netmapClient.LastEpochBlock(ctx) if err != nil { return 0, fmt.Errorf("can't read last epoch block: %w", err) } diff --git a/pkg/innerring/netmap.go b/pkg/innerring/netmap.go index 9961710caf..fb11e94269 100644 --- a/pkg/innerring/netmap.go +++ b/pkg/innerring/netmap.go @@ -1,6 +1,7 @@ package innerring import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state" @@ -17,8 +18,8 @@ type networkSettings netmapclient.Client // MaintenanceModeAllowed requests network configuration from the Sidechain // and check allowance of storage node's maintenance mode according to it. // Always returns state.ErrMaintenanceModeDisallowed. -func (s *networkSettings) MaintenanceModeAllowed() error { - allowed, err := (*netmapclient.Client)(s).MaintenanceModeAllowed() +func (s *networkSettings) MaintenanceModeAllowed(ctx context.Context) error { + allowed, err := (*netmapclient.Client)(s).MaintenanceModeAllowed(ctx) if err != nil { return fmt.Errorf("read maintenance mode's allowance from the Sidechain: %w", err) } else if allowed { diff --git a/pkg/innerring/processors/alphabet/handlers_test.go b/pkg/innerring/processors/alphabet/handlers_test.go index ac3e2a14d5..1da3c401de 100644 --- a/pkg/innerring/processors/alphabet/handlers_test.go +++ b/pkg/innerring/processors/alphabet/handlers_test.go @@ -279,6 +279,6 @@ type testNetmapClient struct { netmap *netmap.NetMap } -func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) { +func (c *testNetmapClient) NetMap(context.Context) (*netmap.NetMap, error) { return c.netmap, nil } diff --git a/pkg/innerring/processors/alphabet/process_emit.go b/pkg/innerring/processors/alphabet/process_emit.go index 8e11d2d61d..d3d0f83f2c 100644 --- a/pkg/innerring/processors/alphabet/process_emit.go +++ b/pkg/innerring/processors/alphabet/process_emit.go @@ -44,7 +44,7 @@ func (ap *Processor) processEmit(ctx context.Context) bool { return true } - networkMap, err := ap.netmapClient.NetMap() + networkMap, err := ap.netmapClient.NetMap(ctx) if err != nil { ap.log.Warn(ctx, logs.AlphabetCantGetNetmapSnapshotToEmitGasToStorageNodes, zap.Error(err)) diff --git a/pkg/innerring/processors/alphabet/processor.go b/pkg/innerring/processors/alphabet/processor.go index 2c4654e7c3..0aea740031 100644 --- a/pkg/innerring/processors/alphabet/processor.go +++ b/pkg/innerring/processors/alphabet/processor.go @@ -36,7 +36,7 @@ type ( } netmapClient interface { - NetMap() (*netmap.NetMap, error) + NetMap(ctx context.Context) (*netmap.NetMap, error) } morphClient interface { diff --git a/pkg/innerring/processors/container/common.go b/pkg/innerring/processors/container/common.go index ba12ebb377..5334b9a1fe 100644 --- a/pkg/innerring/processors/container/common.go +++ b/pkg/innerring/processors/container/common.go @@ -1,6 +1,7 @@ package container import ( + "context" "crypto/ecdsa" "errors" "fmt" @@ -45,7 +46,7 @@ type signatureVerificationData struct { // - v.binPublicKey is a public session key // - session context corresponds to the container and verb in v // - session is "alive" -func (cp *Processor) verifySignature(v signatureVerificationData) error { +func (cp *Processor) verifySignature(ctx context.Context, v signatureVerificationData) error { var err error var key frostfsecdsa.PublicKeyRFC6979 keyProvided := v.binPublicKey != nil @@ -58,7 +59,7 @@ func (cp *Processor) verifySignature(v signatureVerificationData) error { } if len(v.binTokenSession) > 0 { - return cp.verifyByTokenSession(v, &key, keyProvided) + return cp.verifyByTokenSession(ctx, v, &key, keyProvided) } if keyProvided { @@ -77,8 +78,8 @@ func (cp *Processor) verifySignature(v signatureVerificationData) error { return errors.New("signature is invalid or calculated with the key not bound to the container owner") } -func (cp *Processor) checkTokenLifetime(token session.Container) error { - curEpoch, err := cp.netState.Epoch() +func (cp *Processor) checkTokenLifetime(ctx context.Context, token session.Container) error { + curEpoch, err := cp.netState.Epoch(ctx) if err != nil { return fmt.Errorf("could not read current epoch: %w", err) } @@ -90,7 +91,7 @@ func (cp *Processor) checkTokenLifetime(token session.Container) error { return nil } -func (cp *Processor) verifyByTokenSession(v signatureVerificationData, key *frostfsecdsa.PublicKeyRFC6979, keyProvided bool) error { +func (cp *Processor) verifyByTokenSession(ctx context.Context, v signatureVerificationData, key *frostfsecdsa.PublicKeyRFC6979, keyProvided bool) error { var tok session.Container err := tok.Unmarshal(v.binTokenSession) @@ -118,7 +119,7 @@ func (cp *Processor) verifyByTokenSession(v signatureVerificationData, key *fros return errors.New("owner differs with token owner") } - err = cp.checkTokenLifetime(tok) + err = cp.checkTokenLifetime(ctx, tok) if err != nil { return fmt.Errorf("check session lifetime: %w", err) } diff --git a/pkg/innerring/processors/container/handlers_test.go b/pkg/innerring/processors/container/handlers_test.go index f28e5372a8..1b3842eb07 100644 --- a/pkg/innerring/processors/container/handlers_test.go +++ b/pkg/innerring/processors/container/handlers_test.go @@ -170,11 +170,11 @@ type testNetworkState struct { epoch uint64 } -func (s *testNetworkState) HomomorphicHashDisabled() (bool, error) { +func (s *testNetworkState) HomomorphicHashDisabled(context.Context) (bool, error) { return s.homHashDisabled, nil } -func (s *testNetworkState) Epoch() (uint64, error) { +func (s *testNetworkState) Epoch(context.Context) (uint64, error) { return s.epoch, nil } @@ -187,7 +187,7 @@ func (c *testContainerClient) ContractAddress() util.Uint160 { return c.contractAddress } -func (c *testContainerClient) Get(cid []byte) (*containercore.Container, error) { +func (c *testContainerClient) Get(ctx context.Context, cid []byte) (*containercore.Container, error) { key := hex.EncodeToString(cid) if cont, found := c.get[key]; found { return cont, nil @@ -237,6 +237,6 @@ func (c *testMorphClient) NotarySignAndInvokeTX(mainTx *transaction.Transaction) type testFrostFSIDClient struct{} -func (c *testFrostFSIDClient) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) { +func (c *testFrostFSIDClient) GetSubject(ctx context.Context, addr util.Uint160) (*frostfsidclient.Subject, error) { return &frostfsidclient.Subject{}, nil } diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index ffaea653a0..854e2c7792 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -47,7 +47,7 @@ func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool e: put, } - err := cp.checkPutContainer(pctx) + err := cp.checkPutContainer(ctx, pctx) if err != nil { cp.log.Error(ctx, logs.ContainerPutContainerCheckFailed, zap.Error(err), @@ -66,8 +66,8 @@ func (cp *Processor) processContainerPut(ctx context.Context, put putEvent) bool return true } -func (cp *Processor) checkPutContainer(ctx *putContainerContext) error { - binCnr := ctx.e.Container() +func (cp *Processor) checkPutContainer(ctx context.Context, pctx *putContainerContext) error { + binCnr := pctx.e.Container() var cnr containerSDK.Container err := cnr.Unmarshal(binCnr) @@ -75,12 +75,12 @@ func (cp *Processor) checkPutContainer(ctx *putContainerContext) error { return fmt.Errorf("invalid binary container: %w", err) } - err = cp.verifySignature(signatureVerificationData{ + err = cp.verifySignature(ctx, signatureVerificationData{ ownerContainer: cnr.Owner(), verb: session.VerbContainerPut, - binTokenSession: ctx.e.SessionToken(), - binPublicKey: ctx.e.PublicKey(), - signature: ctx.e.Signature(), + binTokenSession: pctx.e.SessionToken(), + binPublicKey: pctx.e.PublicKey(), + signature: pctx.e.Signature(), signedData: binCnr, }) if err != nil { @@ -88,13 +88,13 @@ func (cp *Processor) checkPutContainer(ctx *putContainerContext) error { } // check homomorphic hashing setting - err = checkHomomorphicHashing(cp.netState, cnr) + err = checkHomomorphicHashing(ctx, cp.netState, cnr) if err != nil { return fmt.Errorf("incorrect homomorphic hashing setting: %w", err) } // check native name and zone - err = cp.checkNNS(ctx, cnr) + err = cp.checkNNS(ctx, pctx, cnr) if err != nil { return fmt.Errorf("NNS: %w", err) } @@ -110,7 +110,7 @@ func (cp *Processor) processContainerDelete(ctx context.Context, e containerEven return true } - err := cp.checkDeleteContainer(e) + err := cp.checkDeleteContainer(ctx, e) if err != nil { cp.log.Error(ctx, logs.ContainerDeleteContainerCheckFailed, zap.Error(err), @@ -130,7 +130,7 @@ func (cp *Processor) processContainerDelete(ctx context.Context, e containerEven return true } -func (cp *Processor) checkDeleteContainer(e containerEvent.Delete) error { +func (cp *Processor) checkDeleteContainer(ctx context.Context, e containerEvent.Delete) error { binCnr := e.ContainerID() var idCnr cid.ID @@ -141,12 +141,12 @@ func (cp *Processor) checkDeleteContainer(e containerEvent.Delete) error { } // receive owner of the related container - cnr, err := cp.cnrClient.Get(binCnr) + cnr, err := cp.cnrClient.Get(ctx, binCnr) if err != nil { return fmt.Errorf("could not receive the container: %w", err) } - err = cp.verifySignature(signatureVerificationData{ + err = cp.verifySignature(ctx, signatureVerificationData{ ownerContainer: cnr.Value.Owner(), verb: session.VerbContainerDelete, idContainerSet: true, @@ -163,21 +163,21 @@ func (cp *Processor) checkDeleteContainer(e containerEvent.Delete) error { return nil } -func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Container) error { +func (cp *Processor) checkNNS(ctx context.Context, pctx *putContainerContext, cnr containerSDK.Container) error { // fetch domain info - ctx.d = containerSDK.ReadDomain(cnr) + pctx.d = containerSDK.ReadDomain(cnr) // if PutNamed event => check if values in container correspond to args - if named, ok := ctx.e.(interface { + if named, ok := pctx.e.(interface { Name() string Zone() string }); ok { - if name := named.Name(); name != ctx.d.Name() { - return fmt.Errorf("names differ %s/%s", name, ctx.d.Name()) + if name := named.Name(); name != pctx.d.Name() { + return fmt.Errorf("names differ %s/%s", name, pctx.d.Name()) } - if zone := named.Zone(); zone != ctx.d.Zone() { - return fmt.Errorf("zones differ %s/%s", zone, ctx.d.Zone()) + if zone := named.Zone(); zone != pctx.d.Zone() { + return fmt.Errorf("zones differ %s/%s", zone, pctx.d.Zone()) } } @@ -186,12 +186,12 @@ func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Contain return fmt.Errorf("could not get container owner address: %w", err) } - subject, err := cp.frostFSIDClient.GetSubject(addr) + subject, err := cp.frostFSIDClient.GetSubject(ctx, addr) if err != nil { return fmt.Errorf("could not get subject from FrostfsID contract: %w", err) } - namespace, hasNamespace := strings.CutSuffix(ctx.d.Zone(), ".ns") + namespace, hasNamespace := strings.CutSuffix(pctx.d.Zone(), ".ns") if !hasNamespace { return nil } @@ -203,8 +203,8 @@ func (cp *Processor) checkNNS(ctx *putContainerContext, cnr containerSDK.Contain return nil } -func checkHomomorphicHashing(ns NetworkState, cnr containerSDK.Container) error { - netSetting, err := ns.HomomorphicHashDisabled() +func checkHomomorphicHashing(ctx context.Context, ns NetworkState, cnr containerSDK.Container) error { + netSetting, err := ns.HomomorphicHashDisabled(ctx) if err != nil { return fmt.Errorf("could not get setting in contract: %w", err) } diff --git a/pkg/innerring/processors/container/processor.go b/pkg/innerring/processors/container/processor.go index a0b7491e1c..9be93baa4b 100644 --- a/pkg/innerring/processors/container/processor.go +++ b/pkg/innerring/processors/container/processor.go @@ -25,7 +25,7 @@ type ( ContClient interface { ContractAddress() util.Uint160 - Get(cid []byte) (*containercore.Container, error) + Get(ctx context.Context, cid []byte) (*containercore.Container, error) } MorphClient interface { @@ -33,7 +33,7 @@ type ( } FrostFSIDClient interface { - GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) + GetSubject(ctx context.Context, addr util.Uint160) (*frostfsidclient.Subject, error) } // Processor of events produced by container contract in the sidechain. @@ -68,7 +68,7 @@ type NetworkState interface { // // Must return any error encountered // which did not allow reading the value. - Epoch() (uint64, error) + Epoch(ctx context.Context) (uint64, error) // HomomorphicHashDisabled must return boolean that // represents homomorphic network state: @@ -76,7 +76,7 @@ type NetworkState interface { // * false if hashing is enabled. // // which did not allow reading the value. - HomomorphicHashDisabled() (bool, error) + HomomorphicHashDisabled(ctx context.Context) (bool, error) } // New creates a container contract processor instance. diff --git a/pkg/innerring/processors/governance/handlers_test.go b/pkg/innerring/processors/governance/handlers_test.go index 5a6126249d..864c5da673 100644 --- a/pkg/innerring/processors/governance/handlers_test.go +++ b/pkg/innerring/processors/governance/handlers_test.go @@ -236,7 +236,7 @@ type testIRFetcher struct { publicKeys keys.PublicKeys } -func (f *testIRFetcher) InnerRingKeys() (keys.PublicKeys, error) { +func (f *testIRFetcher) InnerRingKeys(context.Context) (keys.PublicKeys, error) { return f.publicKeys, nil } @@ -266,7 +266,7 @@ type testMainnetClient struct { designateHash util.Uint160 } -func (c *testMainnetClient) NeoFSAlphabetList() (res keys.PublicKeys, err error) { +func (c *testMainnetClient) NeoFSAlphabetList(context.Context) (res keys.PublicKeys, err error) { return c.alphabetKeys, nil } diff --git a/pkg/innerring/processors/governance/process_update.go b/pkg/innerring/processors/governance/process_update.go index 2456796567..6e22abb3c0 100644 --- a/pkg/innerring/processors/governance/process_update.go +++ b/pkg/innerring/processors/governance/process_update.go @@ -25,7 +25,7 @@ func (gp *Processor) processAlphabetSync(ctx context.Context, txHash util.Uint25 return true } - mainnetAlphabet, err := gp.mainnetClient.NeoFSAlphabetList() + mainnetAlphabet, err := gp.mainnetClient.NeoFSAlphabetList(ctx) if err != nil { gp.log.Error(ctx, logs.GovernanceCantFetchAlphabetListFromMainNet, zap.Error(err)) @@ -95,7 +95,7 @@ func prettyKeys(keys keys.PublicKeys) string { } func (gp *Processor) updateNeoFSAlphabetRoleInSidechain(ctx context.Context, sidechainAlphabet, newAlphabet keys.PublicKeys, txHash util.Uint256) { - innerRing, err := gp.irFetcher.InnerRingKeys() + innerRing, err := gp.irFetcher.InnerRingKeys(ctx) if err != nil { gp.log.Error(ctx, logs.GovernanceCantFetchInnerRingListFromSideChain, zap.Error(err)) diff --git a/pkg/innerring/processors/governance/processor.go b/pkg/innerring/processors/governance/processor.go index 7859ebee14..2d131eddab 100644 --- a/pkg/innerring/processors/governance/processor.go +++ b/pkg/innerring/processors/governance/processor.go @@ -52,7 +52,7 @@ type ( // Implementation must take into account availability of // the notary contract. IRFetcher interface { - InnerRingKeys() (keys.PublicKeys, error) + InnerRingKeys(ctx context.Context) (keys.PublicKeys, error) } FrostFSClient interface { @@ -64,7 +64,7 @@ type ( } MainnetClient interface { - NeoFSAlphabetList() (res keys.PublicKeys, err error) + NeoFSAlphabetList(context.Context) (res keys.PublicKeys, err error) GetDesignateHash() util.Uint160 } diff --git a/pkg/innerring/processors/netmap/handlers_test.go b/pkg/innerring/processors/netmap/handlers_test.go index 5a5adfb2dc..934c3790d7 100644 --- a/pkg/innerring/processors/netmap/handlers_test.go +++ b/pkg/innerring/processors/netmap/handlers_test.go @@ -294,7 +294,7 @@ type testNodeStateSettings struct { maintAllowed bool } -func (s *testNodeStateSettings) MaintenanceModeAllowed() error { +func (s *testNodeStateSettings) MaintenanceModeAllowed(context.Context) error { if s.maintAllowed { return nil } @@ -303,7 +303,7 @@ func (s *testNodeStateSettings) MaintenanceModeAllowed() error { type testValidator struct{} -func (v *testValidator) VerifyAndUpdate(*netmap.NodeInfo) error { +func (v *testValidator) VerifyAndUpdate(context.Context, *netmap.NodeInfo) error { return nil } @@ -381,7 +381,7 @@ func (c *testNetmapClient) ContractAddress() util.Uint160 { return c.contractAddress } -func (c *testNetmapClient) EpochDuration() (uint64, error) { +func (c *testNetmapClient) EpochDuration(context.Context) (uint64, error) { return c.epochDuration, nil } @@ -392,7 +392,7 @@ func (c *testNetmapClient) MorphTxHeight(h util.Uint256) (uint32, error) { return 0, fmt.Errorf("not found") } -func (c *testNetmapClient) NetMap() (*netmap.NetMap, error) { +func (c *testNetmapClient) NetMap(context.Context) (*netmap.NetMap, error) { return c.netmap, nil } diff --git a/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go b/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go index 5e0558344f..b81dc9989a 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go +++ b/pkg/innerring/processors/netmap/nodevalidation/locode/calls.go @@ -1,6 +1,7 @@ package locode import ( + "context" "errors" "fmt" @@ -29,7 +30,7 @@ var errMissingRequiredAttr = errors.New("missing required attribute in DB record // - Continent: R.Continent().String(). // // UN-LOCODE attribute remains untouched. -func (v *Validator) VerifyAndUpdate(n *netmap.NodeInfo) error { +func (v *Validator) VerifyAndUpdate(_ context.Context, n *netmap.NodeInfo) error { attrLocode := n.LOCODE() if attrLocode == "" { return nil diff --git a/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go b/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go index 8ab174dfda..fa2dd1ac1d 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go +++ b/pkg/innerring/processors/netmap/nodevalidation/locode/calls_test.go @@ -1,6 +1,7 @@ package locode_test import ( + "context" "errors" "fmt" "testing" @@ -92,7 +93,7 @@ func TestValidator_VerifyAndUpdate(t *testing.T) { t.Run("w/o locode", func(t *testing.T) { n := nodeInfoWithSomeAttrs() - err := validator.VerifyAndUpdate(n) + err := validator.VerifyAndUpdate(context.Background(), n) require.NoError(t, err) }) @@ -102,7 +103,7 @@ func TestValidator_VerifyAndUpdate(t *testing.T) { addLocodeAttrValue(n, "WRONG LOCODE") - err := validator.VerifyAndUpdate(n) + err := validator.VerifyAndUpdate(context.Background(), n) require.Error(t, err) }) @@ -111,7 +112,7 @@ func TestValidator_VerifyAndUpdate(t *testing.T) { addLocodeAttr(n, locodestd.LOCODE{"RU", "SPB"}) - err := validator.VerifyAndUpdate(n) + err := validator.VerifyAndUpdate(context.Background(), n) require.Error(t, err) }) @@ -119,7 +120,7 @@ func TestValidator_VerifyAndUpdate(t *testing.T) { addLocodeAttr(n, r.LOCODE) - err := validator.VerifyAndUpdate(n) + err := validator.VerifyAndUpdate(context.Background(), n) require.NoError(t, err) require.Equal(t, rec.CountryCode().String(), n.Attribute("CountryCode")) diff --git a/pkg/innerring/processors/netmap/nodevalidation/maddress/calls.go b/pkg/innerring/processors/netmap/nodevalidation/maddress/calls.go index 126f365827..0e4628ac76 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/maddress/calls.go +++ b/pkg/innerring/processors/netmap/nodevalidation/maddress/calls.go @@ -1,6 +1,7 @@ package maddress import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" @@ -8,7 +9,7 @@ import ( ) // VerifyAndUpdate calls network.VerifyAddress. -func (v *Validator) VerifyAndUpdate(n *netmap.NodeInfo) error { +func (v *Validator) VerifyAndUpdate(_ context.Context, n *netmap.NodeInfo) error { err := network.VerifyMultiAddress(*n) if err != nil { return fmt.Errorf("could not verify multiaddress: %w", err) diff --git a/pkg/innerring/processors/netmap/nodevalidation/state/validator.go b/pkg/innerring/processors/netmap/nodevalidation/state/validator.go index e5165f618c..03c41a4517 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/state/validator.go +++ b/pkg/innerring/processors/netmap/nodevalidation/state/validator.go @@ -7,6 +7,7 @@ map candidates. package state import ( + "context" "errors" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -23,7 +24,7 @@ type NetworkSettings interface { // no error if allowed; // ErrMaintenanceModeDisallowed if disallowed; // other error if there are any problems with the check. - MaintenanceModeAllowed() error + MaintenanceModeAllowed(ctx context.Context) error } // NetMapCandidateValidator represents tool which checks state of nodes which @@ -55,13 +56,13 @@ func (x *NetMapCandidateValidator) SetNetworkSettings(netSettings NetworkSetting // MUST NOT be called before SetNetworkSettings. // // See also netmap.NodeInfo.IsOnline/SetOnline and other similar methods. -func (x *NetMapCandidateValidator) VerifyAndUpdate(node *netmap.NodeInfo) error { +func (x *NetMapCandidateValidator) VerifyAndUpdate(ctx context.Context, node *netmap.NodeInfo) error { if node.Status().IsOnline() { return nil } if node.Status().IsMaintenance() { - return x.netSettings.MaintenanceModeAllowed() + return x.netSettings.MaintenanceModeAllowed(ctx) } return errors.New("invalid status: MUST be either ONLINE or MAINTENANCE") diff --git a/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go b/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go index b81d7243b1..cbf48a7101 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go +++ b/pkg/innerring/processors/netmap/nodevalidation/state/validator_test.go @@ -1,6 +1,7 @@ package state_test import ( + "context" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap/nodevalidation/state" @@ -13,7 +14,7 @@ type testNetworkSettings struct { disallowed bool } -func (x testNetworkSettings) MaintenanceModeAllowed() error { +func (x testNetworkSettings) MaintenanceModeAllowed(context.Context) error { if x.disallowed { return state.ErrMaintenanceModeDisallowed } @@ -81,7 +82,7 @@ func TestValidator_VerifyAndUpdate(t *testing.T) { testCase.validatorPreparer(&v) } - err := v.VerifyAndUpdate(&node) + err := v.VerifyAndUpdate(context.Background(), &node) if testCase.valid { require.NoError(t, err, testCase.name) diff --git a/pkg/innerring/processors/netmap/nodevalidation/validator.go b/pkg/innerring/processors/netmap/nodevalidation/validator.go index e9b24e0247..3dbe98a8dd 100644 --- a/pkg/innerring/processors/netmap/nodevalidation/validator.go +++ b/pkg/innerring/processors/netmap/nodevalidation/validator.go @@ -1,6 +1,8 @@ package nodevalidation import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/netmap" apinetmap "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" ) @@ -26,9 +28,9 @@ func New(validators ...netmap.NodeValidator) *CompositeValidator { // VerifyAndUpdate passes apinetmap.NodeInfo to wrapped validators. // // If error appears, returns it immediately. -func (c *CompositeValidator) VerifyAndUpdate(ni *apinetmap.NodeInfo) error { +func (c *CompositeValidator) VerifyAndUpdate(ctx context.Context, ni *apinetmap.NodeInfo) error { for _, v := range c.validators { - if err := v.VerifyAndUpdate(ni); err != nil { + if err := v.VerifyAndUpdate(ctx, ni); err != nil { return err } } diff --git a/pkg/innerring/processors/netmap/process_epoch.go b/pkg/innerring/processors/netmap/process_epoch.go index 93e00bbaa1..7c78d24a5f 100644 --- a/pkg/innerring/processors/netmap/process_epoch.go +++ b/pkg/innerring/processors/netmap/process_epoch.go @@ -14,7 +14,7 @@ import ( func (np *Processor) processNewEpoch(ctx context.Context, ev netmapEvent.NewEpoch) bool { epoch := ev.EpochNumber() - epochDuration, err := np.netmapClient.EpochDuration() + epochDuration, err := np.netmapClient.EpochDuration(ctx) if err != nil { np.log.Warn(ctx, logs.NetmapCantGetEpochDuration, zap.Error(err)) @@ -37,7 +37,7 @@ func (np *Processor) processNewEpoch(ctx context.Context, ev netmapEvent.NewEpoc } // get new netmap snapshot - networkMap, err := np.netmapClient.NetMap() + networkMap, err := np.netmapClient.NetMap(ctx) if err != nil { np.log.Warn(ctx, logs.NetmapCantGetNetmapSnapshotToPerformCleanup, zap.Error(err)) diff --git a/pkg/innerring/processors/netmap/process_peers.go b/pkg/innerring/processors/netmap/process_peers.go index 5b565ffd19..b5c727cc7c 100644 --- a/pkg/innerring/processors/netmap/process_peers.go +++ b/pkg/innerring/processors/netmap/process_peers.go @@ -39,7 +39,7 @@ func (np *Processor) processAddPeer(ctx context.Context, ev netmapEvent.AddPeer) } // validate and update node info - err = np.nodeValidator.VerifyAndUpdate(&nodeInfo) + err = np.nodeValidator.VerifyAndUpdate(ctx, &nodeInfo) if err != nil { np.log.Warn(ctx, logs.NetmapCouldNotVerifyAndUpdateInformationAboutNetworkMapCandidate, zap.Error(err), @@ -108,7 +108,7 @@ func (np *Processor) processUpdatePeer(ctx context.Context, ev netmapEvent.Updat var err error if ev.Maintenance() { - err = np.nodeStateSettings.MaintenanceModeAllowed() + err = np.nodeStateSettings.MaintenanceModeAllowed(ctx) if err != nil { np.log.Info(ctx, logs.NetmapPreventSwitchingNodeToMaintenanceState, zap.Error(err), diff --git a/pkg/innerring/processors/netmap/processor.go b/pkg/innerring/processors/netmap/processor.go index 36df57afe4..277bca1c33 100644 --- a/pkg/innerring/processors/netmap/processor.go +++ b/pkg/innerring/processors/netmap/processor.go @@ -49,15 +49,15 @@ type ( // // If no error occurs, the parameter must point to the // ready-made NodeInfo structure. - VerifyAndUpdate(*netmap.NodeInfo) error + VerifyAndUpdate(context.Context, *netmap.NodeInfo) error } Client interface { MorphNotaryInvoke(ctx context.Context, contract util.Uint160, fee fixedn.Fixed8, nonce uint32, vub *uint32, method string, args ...any) error ContractAddress() util.Uint160 - EpochDuration() (uint64, error) + EpochDuration(ctx context.Context) (uint64, error) MorphTxHeight(h util.Uint256) (res uint32, err error) - NetMap() (*netmap.NetMap, error) + NetMap(ctx context.Context) (*netmap.NetMap, error) NewEpoch(ctx context.Context, epoch uint64) error MorphIsValidScript(script []byte, signers []transaction.Signer) (valid bool, err error) MorphNotarySignAndInvokeTX(mainTx *transaction.Transaction) error diff --git a/pkg/innerring/processors/netmap/wrappers.go b/pkg/innerring/processors/netmap/wrappers.go index 9cd71ae487..310f12248d 100644 --- a/pkg/innerring/processors/netmap/wrappers.go +++ b/pkg/innerring/processors/netmap/wrappers.go @@ -34,16 +34,16 @@ func (w *netmapClientWrapper) ContractAddress() util.Uint160 { return w.netmapClient.ContractAddress() } -func (w *netmapClientWrapper) EpochDuration() (uint64, error) { - return w.netmapClient.EpochDuration() +func (w *netmapClientWrapper) EpochDuration(ctx context.Context) (uint64, error) { + return w.netmapClient.EpochDuration(ctx) } func (w *netmapClientWrapper) MorphTxHeight(h util.Uint256) (res uint32, err error) { return w.netmapClient.Morph().TxHeight(h) } -func (w *netmapClientWrapper) NetMap() (*netmap.NetMap, error) { - return w.netmapClient.NetMap() +func (w *netmapClientWrapper) NetMap(ctx context.Context) (*netmap.NetMap, error) { + return w.netmapClient.NetMap(ctx) } func (w *netmapClientWrapper) NewEpoch(ctx context.Context, epoch uint64) error { diff --git a/pkg/innerring/state.go b/pkg/innerring/state.go index 3e9880e70c..0ef771359b 100644 --- a/pkg/innerring/state.go +++ b/pkg/innerring/state.go @@ -60,7 +60,7 @@ func (s *Server) IsAlphabet(ctx context.Context) bool { // InnerRingIndex is a getter for a global index of node in inner ring list. Negative // index means that node is not in the inner ring list. func (s *Server) InnerRingIndex(ctx context.Context) int { - index, err := s.statusIndex.InnerRingIndex() + index, err := s.statusIndex.InnerRingIndex(ctx) if err != nil { s.log.Error(ctx, logs.InnerringCantGetInnerRingIndex, zap.Error(err)) return -1 @@ -72,7 +72,7 @@ func (s *Server) InnerRingIndex(ctx context.Context) int { // InnerRingSize is a getter for a global size of inner ring list. This value // paired with inner ring index. func (s *Server) InnerRingSize(ctx context.Context) int { - size, err := s.statusIndex.InnerRingSize() + size, err := s.statusIndex.InnerRingSize(ctx) if err != nil { s.log.Error(ctx, logs.InnerringCantGetInnerRingSize, zap.Error(err)) return 0 @@ -84,7 +84,7 @@ func (s *Server) InnerRingSize(ctx context.Context) int { // AlphabetIndex is a getter for a global index of node in alphabet list. // Negative index means that node is not in the alphabet list. func (s *Server) AlphabetIndex(ctx context.Context) int { - index, err := s.statusIndex.AlphabetIndex() + index, err := s.statusIndex.AlphabetIndex(ctx) if err != nil { s.log.Error(ctx, logs.InnerringCantGetAlphabetIndex, zap.Error(err)) return -1 diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index f82268d1d9..85652b3ae3 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -279,7 +279,7 @@ func (s *containerSource) IsContainerAvailable(ctx context.Context, id cid.ID) ( return true, nil } - wasRemoved, err := container.WasRemoved(s.cs, id) + wasRemoved, err := container.WasRemoved(ctx, s.cs, id) if err != nil { return false, err } diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index fd1530f536..27eaea7683 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -425,7 +425,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context } egContainer.Go(func() error { var skip bool - c, err := e.containerSource.Load().cs.Get(cnt) + c, err := e.containerSource.Load().cs.Get(ctx, cnt) if err != nil { if client.IsErrContainerNotFound(err) { skip = true diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 248c391556..b9d7888e7c 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -37,7 +37,7 @@ type containerStorage struct { latency time.Duration } -func (cs *containerStorage) Get(id cid.ID) (*coreContainer.Container, error) { +func (cs *containerStorage) Get(ctx context.Context, id cid.ID) (*coreContainer.Container, error) { time.Sleep(cs.latency) v, ok := cs.cntmap[id] if !ok { @@ -49,7 +49,7 @@ func (cs *containerStorage) Get(id cid.ID) (*coreContainer.Container, error) { return &coreCnt, nil } -func (cs *containerStorage) DeletionInfo(cid.ID) (*coreContainer.DelInfo, error) { +func (cs *containerStorage) DeletionInfo(context.Context, cid.ID) (*coreContainer.DelInfo, error) { return nil, nil } diff --git a/pkg/local_object_storage/metabase/upgrade.go b/pkg/local_object_storage/metabase/upgrade.go index 6eba58c69f..4948f34241 100644 --- a/pkg/local_object_storage/metabase/upgrade.go +++ b/pkg/local_object_storage/metabase/upgrade.go @@ -360,7 +360,7 @@ func dropUserAttributes(ctx context.Context, db *bbolt.DB, cs container.InfoProv return nil } last = keys[len(keys)-1] - cnt, err := dropNonIndexedUserAttributeBuckets(db, cs, keys) + cnt, err := dropNonIndexedUserAttributeBuckets(ctx, db, cs, keys) if err != nil { log("deleting user attribute buckets completed with an error:", err) return err @@ -376,8 +376,8 @@ func dropUserAttributes(ctx context.Context, db *bbolt.DB, cs container.InfoProv } } -func dropNonIndexedUserAttributeBuckets(db *bbolt.DB, cs container.InfoProvider, keys [][]byte) (uint64, error) { - keysToDrop, err := selectUserAttributeKeysToDrop(keys, cs) +func dropNonIndexedUserAttributeBuckets(ctx context.Context, db *bbolt.DB, cs container.InfoProvider, keys [][]byte) (uint64, error) { + keysToDrop, err := selectUserAttributeKeysToDrop(ctx, keys, cs) if err != nil { return 0, fmt.Errorf("select non indexed user attributes: %w", err) } @@ -394,7 +394,7 @@ func dropNonIndexedUserAttributeBuckets(db *bbolt.DB, cs container.InfoProvider, return uint64(len(keysToDrop)), nil } -func selectUserAttributeKeysToDrop(keys [][]byte, cs container.InfoProvider) ([][]byte, error) { +func selectUserAttributeKeysToDrop(ctx context.Context, keys [][]byte, cs container.InfoProvider) ([][]byte, error) { var keysToDrop [][]byte for _, key := range keys { attr, ok := attributeFromAttributeBucket(key) @@ -409,7 +409,7 @@ func selectUserAttributeKeysToDrop(keys [][]byte, cs container.InfoProvider) ([] if !ok { return nil, fmt.Errorf("parse container ID from user attribute bucket key %s", hex.EncodeToString(key)) } - info, err := cs.Info(contID) + info, err := cs.Info(ctx, contID) if err != nil { return nil, err } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 3136ddfcc8..fedde22062 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -280,7 +280,7 @@ func (s *Shard) refillObject(ctx context.Context, data []byte, addr oid.Address, var isIndexedContainer bool if hasIndexedAttribute { - info, err := s.containerInfo.Info(addr.Container()) + info, err := s.containerInfo.Info(ctx, addr.Container()) if err != nil { return err } diff --git a/pkg/morph/client/balance/balanceOf.go b/pkg/morph/client/balance/balanceOf.go index 449d49e5a3..4462daab4a 100644 --- a/pkg/morph/client/balance/balanceOf.go +++ b/pkg/morph/client/balance/balanceOf.go @@ -1,6 +1,7 @@ package balance import ( + "context" "fmt" "math/big" @@ -10,14 +11,14 @@ import ( // BalanceOf receives the amount of funds in the client's account // through the Balance contract call, and returns it. -func (c *Client) BalanceOf(id user.ID) (*big.Int, error) { +func (c *Client) BalanceOf(ctx context.Context, id user.ID) (*big.Int, error) { h := id.ScriptHash() invokePrm := client.TestInvokePrm{} invokePrm.SetMethod(balanceOfMethod) invokePrm.SetArgs(h) - prms, err := c.client.TestInvoke(invokePrm) + prms, err := c.client.TestInvoke(ctx, invokePrm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", balanceOfMethod, err) } else if ln := len(prms); ln != 1 { diff --git a/pkg/morph/client/balance/decimals.go b/pkg/morph/client/balance/decimals.go index c2a66ddedd..57e61d62be 100644 --- a/pkg/morph/client/balance/decimals.go +++ b/pkg/morph/client/balance/decimals.go @@ -1,6 +1,7 @@ package balance import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -8,11 +9,11 @@ import ( // Decimals decimal precision of currency transactions // through the Balance contract call, and returns it. -func (c *Client) Decimals() (uint32, error) { +func (c *Client) Decimals(ctx context.Context) (uint32, error) { invokePrm := client.TestInvokePrm{} invokePrm.SetMethod(decimalsMethod) - prms, err := c.client.TestInvoke(invokePrm) + prms, err := c.client.TestInvoke(ctx, invokePrm) if err != nil { return 0, fmt.Errorf("test invoke (%s): %w", decimalsMethod, err) } else if ln := len(prms); ln != 1 { diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 01fcc98e58..10ded5142a 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -499,7 +499,7 @@ func (c *Client) TxHeight(h util.Uint256) (res uint32, err error) { // NeoFSAlphabetList returns keys that stored in NeoFS Alphabet role. Main chain // stores alphabet node keys of inner ring there, however the sidechain stores both // alphabet and non alphabet node keys of inner ring. -func (c *Client) NeoFSAlphabetList() (res keys.PublicKeys, err error) { +func (c *Client) NeoFSAlphabetList(_ context.Context) (res keys.PublicKeys, err error) { c.switchLock.RLock() defer c.switchLock.RUnlock() diff --git a/pkg/morph/client/container/containers_of.go b/pkg/morph/client/container/containers_of.go index 074a586beb..60fb8ad7c4 100644 --- a/pkg/morph/client/container/containers_of.go +++ b/pkg/morph/client/container/containers_of.go @@ -1,6 +1,7 @@ package container import ( + "context" "errors" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -13,7 +14,7 @@ import ( // to the specified user of FrostFS system. If idUser is nil, returns the list of all containers. // // If remote RPC does not support neo-go session API, fallback to List() method. -func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { +func (c *Client) ContainersOf(ctx context.Context, idUser *user.ID) ([]cid.ID, error) { var cidList []cid.ID var err error @@ -21,7 +22,7 @@ func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { cidList = append(cidList, id) return nil } - if err = c.IterateContainersOf(idUser, cb); err != nil { + if err = c.IterateContainersOf(ctx, idUser, cb); err != nil { return nil, err } return cidList, nil @@ -30,7 +31,7 @@ func (c *Client) ContainersOf(idUser *user.ID) ([]cid.ID, error) { // iterateContainers iterates over a list of container identifiers // belonging to the specified user of FrostFS system and executes // `cb` on each element. If idUser is nil, calls it on the list of all containers. -func (c *Client) IterateContainersOf(idUser *user.ID, cb func(item cid.ID) error) error { +func (c *Client) IterateContainersOf(ctx context.Context, idUser *user.ID, cb func(item cid.ID) error) error { var rawID []byte if idUser != nil { rawID = idUser.WalletBytes() @@ -59,7 +60,7 @@ func (c *Client) IterateContainersOf(idUser *user.ID, cb func(item cid.ID) error cnrHash := c.client.ContractAddress() err := c.client.Morph().TestInvokeIterator(itemCb, batchSize, cnrHash, containersOfMethod, rawID) if err != nil && errors.Is(err, unwrap.ErrNoSessionID) { - return c.iterate(idUser, cb) + return c.iterate(ctx, idUser, cb) } return err diff --git a/pkg/morph/client/container/deletion_info.go b/pkg/morph/client/container/deletion_info.go index b86e0ce9c0..90bcdd7d5c 100644 --- a/pkg/morph/client/container/deletion_info.go +++ b/pkg/morph/client/container/deletion_info.go @@ -1,6 +1,7 @@ package container import ( + "context" "crypto/sha256" "fmt" "strings" @@ -14,27 +15,27 @@ import ( "github.com/mr-tron/base58" ) -func (x *containerSource) DeletionInfo(cnr cid.ID) (*containercore.DelInfo, error) { - return DeletionInfo((*Client)(x), cnr) +func (x *containerSource) DeletionInfo(ctx context.Context, cnr cid.ID) (*containercore.DelInfo, error) { + return DeletionInfo(ctx, (*Client)(x), cnr) } type deletionInfo interface { - DeletionInfo(cid []byte) (*containercore.DelInfo, error) + DeletionInfo(ctx context.Context, cid []byte) (*containercore.DelInfo, error) } -func DeletionInfo(c deletionInfo, cnr cid.ID) (*containercore.DelInfo, error) { +func DeletionInfo(ctx context.Context, c deletionInfo, cnr cid.ID) (*containercore.DelInfo, error) { binCnr := make([]byte, sha256.Size) cnr.Encode(binCnr) - return c.DeletionInfo(binCnr) + return c.DeletionInfo(ctx, binCnr) } -func (c *Client) DeletionInfo(cid []byte) (*containercore.DelInfo, error) { +func (c *Client) DeletionInfo(ctx context.Context, cid []byte) (*containercore.DelInfo, error) { prm := client.TestInvokePrm{} prm.SetMethod(deletionInfoMethod) prm.SetArgs(cid) - res, err := c.client.TestInvoke(prm) + res, err := c.client.TestInvoke(ctx, prm) if err != nil { if strings.Contains(err.Error(), containerContract.NotFoundError) { return nil, new(apistatus.ContainerNotFound) diff --git a/pkg/morph/client/container/get.go b/pkg/morph/client/container/get.go index 2ab58bf017..8622d2cdd7 100644 --- a/pkg/morph/client/container/get.go +++ b/pkg/morph/client/container/get.go @@ -1,6 +1,7 @@ package container import ( + "context" "crypto/sha256" "fmt" "strings" @@ -16,8 +17,8 @@ import ( type containerSource Client -func (x *containerSource) Get(cnr cid.ID) (*containercore.Container, error) { - return Get((*Client)(x), cnr) +func (x *containerSource) Get(ctx context.Context, cnr cid.ID) (*containercore.Container, error) { + return Get(ctx, (*Client)(x), cnr) } // AsContainerSource provides container Source interface @@ -27,15 +28,15 @@ func AsContainerSource(w *Client) containercore.Source { } type getContainer interface { - Get(cid []byte) (*containercore.Container, error) + Get(ctx context.Context, cid []byte) (*containercore.Container, error) } // Get marshals container ID, and passes it to Wrapper's Get method. -func Get(c getContainer, cnr cid.ID) (*containercore.Container, error) { +func Get(ctx context.Context, c getContainer, cnr cid.ID) (*containercore.Container, error) { binCnr := make([]byte, sha256.Size) cnr.Encode(binCnr) - return c.Get(binCnr) + return c.Get(ctx, binCnr) } // Get reads the container from FrostFS system by binary identifier @@ -43,12 +44,12 @@ func Get(c getContainer, cnr cid.ID) (*containercore.Container, error) { // // If an empty slice is returned for the requested identifier, // storage.ErrNotFound error is returned. -func (c *Client) Get(cid []byte) (*containercore.Container, error) { +func (c *Client) Get(ctx context.Context, cid []byte) (*containercore.Container, error) { prm := client.TestInvokePrm{} prm.SetMethod(getMethod) prm.SetArgs(cid) - res, err := c.client.TestInvoke(prm) + res, err := c.client.TestInvoke(ctx, prm) if err != nil { if strings.Contains(err.Error(), containerContract.NotFoundError) { return nil, new(apistatus.ContainerNotFound) diff --git a/pkg/morph/client/container/list.go b/pkg/morph/client/container/list.go index 78ea8278f5..fc63d1beb2 100644 --- a/pkg/morph/client/container/list.go +++ b/pkg/morph/client/container/list.go @@ -1,6 +1,7 @@ package container import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -15,7 +16,7 @@ import ( // // Iterates through the identifiers of all FrostFS containers if pointer // to user identifier is nil. -func (c *Client) iterate(idUser *user.ID, cb func(cid.ID) error) error { +func (c *Client) iterate(ctx context.Context, idUser *user.ID, cb func(cid.ID) error) error { var rawID []byte if idUser != nil { @@ -26,7 +27,7 @@ func (c *Client) iterate(idUser *user.ID, cb func(cid.ID) error) error { prm.SetMethod(listMethod) prm.SetArgs(rawID) - res, err := c.client.TestInvoke(prm) + res, err := c.client.TestInvoke(ctx, prm) if err != nil { return fmt.Errorf("test invoke (%s): %w", listMethod, err) } else if ln := len(res); ln != 1 { diff --git a/pkg/morph/client/frostfsid/subject.go b/pkg/morph/client/frostfsid/subject.go index 305f3ce098..3a789672a3 100644 --- a/pkg/morph/client/frostfsid/subject.go +++ b/pkg/morph/client/frostfsid/subject.go @@ -1,6 +1,7 @@ package frostfsid import ( + "context" "fmt" frostfsidclient "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" @@ -14,12 +15,12 @@ const ( methodGetSubjectExtended = "getSubjectExtended" ) -func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) { +func (c *Client) GetSubject(ctx context.Context, addr util.Uint160) (*frostfsidclient.Subject, error) { prm := client.TestInvokePrm{} prm.SetMethod(methodGetSubject) prm.SetArgs(addr) - res, err := c.client.TestInvoke(prm) + res, err := c.client.TestInvoke(ctx, prm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", methodGetSubject, err) } @@ -37,12 +38,12 @@ func (c *Client) GetSubject(addr util.Uint160) (*frostfsidclient.Subject, error) return subj, nil } -func (c *Client) GetSubjectExtended(addr util.Uint160) (*frostfsidclient.SubjectExtended, error) { +func (c *Client) GetSubjectExtended(ctx context.Context, addr util.Uint160) (*frostfsidclient.SubjectExtended, error) { prm := client.TestInvokePrm{} prm.SetMethod(methodGetSubjectExtended) prm.SetArgs(addr) - res, err := c.client.TestInvoke(prm) + res, err := c.client.TestInvoke(ctx, prm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", methodGetSubjectExtended, err) } diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index 2b87df6f78..fcdb70e3f6 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -25,8 +25,8 @@ const ( // MaxObjectSize receives max object size configuration // value through the Netmap contract call. -func (c *Client) MaxObjectSize() (uint64, error) { - objectSize, err := c.readUInt64Config(MaxObjectSizeConfig) +func (c *Client) MaxObjectSize(ctx context.Context) (uint64, error) { + objectSize, err := c.readUInt64Config(ctx, MaxObjectSizeConfig) if err != nil { return 0, err } @@ -35,8 +35,8 @@ func (c *Client) MaxObjectSize() (uint64, error) { } // EpochDuration returns number of sidechain blocks per one FrostFS epoch. -func (c *Client) EpochDuration() (uint64, error) { - epochDuration, err := c.readUInt64Config(EpochDurationConfig) +func (c *Client) EpochDuration(ctx context.Context) (uint64, error) { + epochDuration, err := c.readUInt64Config(ctx, EpochDurationConfig) if err != nil { return 0, err } @@ -46,8 +46,8 @@ func (c *Client) EpochDuration() (uint64, error) { // ContainerFee returns fee paid by container owner to each alphabet node // for container registration. -func (c *Client) ContainerFee() (uint64, error) { - fee, err := c.readUInt64Config(ContainerFeeConfig) +func (c *Client) ContainerFee(ctx context.Context) (uint64, error) { + fee, err := c.readUInt64Config(ctx, ContainerFeeConfig) if err != nil { return 0, err } @@ -57,8 +57,8 @@ func (c *Client) ContainerFee() (uint64, error) { // ContainerAliasFee returns additional fee paid by container owner to each // alphabet node for container nice name registration. -func (c *Client) ContainerAliasFee() (uint64, error) { - fee, err := c.readUInt64Config(ContainerAliasFeeConfig) +func (c *Client) ContainerAliasFee(ctx context.Context) (uint64, error) { + fee, err := c.readUInt64Config(ctx, ContainerAliasFeeConfig) if err != nil { return 0, err } @@ -70,14 +70,14 @@ func (c *Client) ContainerAliasFee() (uint64, error) { // settings. // // Returns (false, nil) if config key is not found in the contract. -func (c *Client) HomomorphicHashDisabled() (bool, error) { - return c.readBoolConfig(HomomorphicHashingDisabledKey) +func (c *Client) HomomorphicHashDisabled(ctx context.Context) (bool, error) { + return c.readBoolConfig(ctx, HomomorphicHashingDisabledKey) } // InnerRingCandidateFee returns global configuration value of fee paid by // node to be in inner ring candidates list. -func (c *Client) InnerRingCandidateFee() (uint64, error) { - fee, err := c.readUInt64Config(IrCandidateFeeConfig) +func (c *Client) InnerRingCandidateFee(ctx context.Context) (uint64, error) { + fee, err := c.readUInt64Config(ctx, IrCandidateFeeConfig) if err != nil { return 0, err } @@ -87,8 +87,8 @@ func (c *Client) InnerRingCandidateFee() (uint64, error) { // WithdrawFee returns global configuration value of fee paid by user to // withdraw assets from FrostFS contract. -func (c *Client) WithdrawFee() (uint64, error) { - fee, err := c.readUInt64Config(WithdrawFeeConfig) +func (c *Client) WithdrawFee(ctx context.Context) (uint64, error) { + fee, err := c.readUInt64Config(ctx, WithdrawFeeConfig) if err != nil { return 0, err } @@ -101,12 +101,12 @@ func (c *Client) WithdrawFee() (uint64, error) { // that storage nodes are allowed to switch their state to "maintenance". // // By default, maintenance state is disallowed. -func (c *Client) MaintenanceModeAllowed() (bool, error) { - return c.readBoolConfig(MaintenanceModeAllowedConfig) +func (c *Client) MaintenanceModeAllowed(ctx context.Context) (bool, error) { + return c.readBoolConfig(ctx, MaintenanceModeAllowedConfig) } -func (c *Client) readUInt64Config(key string) (uint64, error) { - v, err := c.config([]byte(key), IntegerAssert) +func (c *Client) readUInt64Config(ctx context.Context, key string) (uint64, error) { + v, err := c.config(ctx, []byte(key), IntegerAssert) if err != nil { return 0, fmt.Errorf("read netconfig value '%s': %w", key, err) } @@ -117,8 +117,8 @@ func (c *Client) readUInt64Config(key string) (uint64, error) { // reads boolean value by the given key from the FrostFS network configuration // stored in the Sidechain. Returns false if key is not presented. -func (c *Client) readBoolConfig(key string) (bool, error) { - v, err := c.config([]byte(key), BoolAssert) +func (c *Client) readBoolConfig(ctx context.Context, key string) (bool, error) { + v, err := c.config(ctx, []byte(key), BoolAssert) if err != nil { if errors.Is(err, ErrConfigNotFound) { return false, nil @@ -199,12 +199,12 @@ type NetworkConfiguration struct { } // ReadNetworkConfiguration reads NetworkConfiguration from the FrostFS Sidechain. -func (c *Client) ReadNetworkConfiguration() (NetworkConfiguration, error) { +func (c *Client) ReadNetworkConfiguration(ctx context.Context) (NetworkConfiguration, error) { var res NetworkConfiguration prm := client.TestInvokePrm{} prm.SetMethod(configListMethod) - items, err := c.client.TestInvoke(prm) + items, err := c.client.TestInvoke(ctx, prm) if err != nil { return res, fmt.Errorf("test invoke (%s): %w", configListMethod, err) @@ -285,12 +285,12 @@ var ErrConfigNotFound = errors.New("config value not found") // method of FrostFS Netmap contract. // // Returns ErrConfigNotFound if config key is not found in the contract. -func (c *Client) config(key []byte, assert func(stackitem.Item) (any, error)) (any, error) { +func (c *Client) config(ctx context.Context, key []byte, assert func(stackitem.Item) (any, error)) (any, error) { prm := client.TestInvokePrm{} prm.SetMethod(configMethod) prm.SetArgs(key) - items, err := c.client.TestInvoke(prm) + items, err := c.client.TestInvoke(ctx, prm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", configMethod, err) diff --git a/pkg/morph/client/netmap/epoch.go b/pkg/morph/client/netmap/epoch.go index 6d73949984..8561329ecf 100644 --- a/pkg/morph/client/netmap/epoch.go +++ b/pkg/morph/client/netmap/epoch.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -8,11 +9,11 @@ import ( // Epoch receives number of current FrostFS epoch // through the Netmap contract call. -func (c *Client) Epoch() (uint64, error) { +func (c *Client) Epoch(ctx context.Context) (uint64, error) { prm := client.TestInvokePrm{} prm.SetMethod(epochMethod) - items, err := c.client.TestInvoke(prm) + items, err := c.client.TestInvoke(ctx, prm) if err != nil { return 0, fmt.Errorf("test invoke (%s): %w", epochMethod, err) @@ -32,11 +33,11 @@ func (c *Client) Epoch() (uint64, error) { // LastEpochBlock receives block number of current FrostFS epoch // through the Netmap contract call. -func (c *Client) LastEpochBlock() (uint32, error) { +func (c *Client) LastEpochBlock(ctx context.Context) (uint32, error) { prm := client.TestInvokePrm{} prm.SetMethod(lastEpochBlockMethod) - items, err := c.client.TestInvoke(prm) + items, err := c.client.TestInvoke(ctx, prm) if err != nil { return 0, fmt.Errorf("test invoke (%s): %w", lastEpochBlockMethod, err) diff --git a/pkg/morph/client/netmap/innerring.go b/pkg/morph/client/netmap/innerring.go index 0cfad4c82c..0e1f9186ba 100644 --- a/pkg/morph/client/netmap/innerring.go +++ b/pkg/morph/client/netmap/innerring.go @@ -40,11 +40,11 @@ func (c *Client) UpdateInnerRing(ctx context.Context, p UpdateIRPrm) error { } // GetInnerRingList return current IR list. -func (c *Client) GetInnerRingList() (keys.PublicKeys, error) { +func (c *Client) GetInnerRingList(ctx context.Context) (keys.PublicKeys, error) { invokePrm := client.TestInvokePrm{} invokePrm.SetMethod(innerRingListMethod) - prms, err := c.client.TestInvoke(invokePrm) + prms, err := c.client.TestInvoke(ctx, invokePrm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", innerRingListMethod, err) } diff --git a/pkg/morph/client/netmap/netmap.go b/pkg/morph/client/netmap/netmap.go index a0009ea734..97782fc251 100644 --- a/pkg/morph/client/netmap/netmap.go +++ b/pkg/morph/client/netmap/netmap.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "fmt" netmapcontract "git.frostfs.info/TrueCloudLab/frostfs-contract/netmap" @@ -11,12 +12,12 @@ import ( // GetNetMapByEpoch calls "snapshotByEpoch" method with the given epoch and // decodes netmap.NetMap from the response. -func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { +func (c *Client) GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmap.NetMap, error) { invokePrm := client.TestInvokePrm{} invokePrm.SetMethod(epochSnapshotMethod) invokePrm.SetArgs(epoch) - res, err := c.client.TestInvoke(invokePrm) + res, err := c.client.TestInvoke(ctx, invokePrm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", epochSnapshotMethod, err) @@ -34,11 +35,11 @@ func (c *Client) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { // GetCandidates calls "netmapCandidates" method and decodes []netmap.NodeInfo // from the response. -func (c *Client) GetCandidates() ([]netmap.NodeInfo, error) { +func (c *Client) GetCandidates(ctx context.Context) ([]netmap.NodeInfo, error) { invokePrm := client.TestInvokePrm{} invokePrm.SetMethod(netMapCandidatesMethod) - res, err := c.client.TestInvoke(invokePrm) + res, err := c.client.TestInvoke(ctx, invokePrm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", netMapCandidatesMethod, err) } @@ -51,11 +52,11 @@ func (c *Client) GetCandidates() ([]netmap.NodeInfo, error) { } // NetMap calls "netmap" method and decode netmap.NetMap from the response. -func (c *Client) NetMap() (*netmap.NetMap, error) { +func (c *Client) NetMap(ctx context.Context) (*netmap.NetMap, error) { invokePrm := client.TestInvokePrm{} invokePrm.SetMethod(netMapMethod) - res, err := c.client.TestInvoke(invokePrm) + res, err := c.client.TestInvoke(ctx, invokePrm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", netMapMethod, err) diff --git a/pkg/morph/client/netmap/snapshot.go b/pkg/morph/client/netmap/snapshot.go index a5134bcef7..9dbec1a90f 100644 --- a/pkg/morph/client/netmap/snapshot.go +++ b/pkg/morph/client/netmap/snapshot.go @@ -1,6 +1,7 @@ package netmap import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -8,12 +9,12 @@ import ( ) // GetNetMap calls "snapshot" method and decodes netmap.NetMap from the response. -func (c *Client) GetNetMap(diff uint64) (*netmap.NetMap, error) { +func (c *Client) GetNetMap(ctx context.Context, diff uint64) (*netmap.NetMap, error) { prm := client.TestInvokePrm{} prm.SetMethod(snapshotMethod) prm.SetArgs(diff) - res, err := c.client.TestInvoke(prm) + res, err := c.client.TestInvoke(ctx, prm) if err != nil { return nil, fmt.Errorf("test invoke (%s): %w", snapshotMethod, err) } diff --git a/pkg/morph/client/static.go b/pkg/morph/client/static.go index 21adebd9e2..c4eb120d26 100644 --- a/pkg/morph/client/static.go +++ b/pkg/morph/client/static.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" @@ -205,7 +206,9 @@ func (ti *TestInvokePrm) SetArgs(args ...any) { } // TestInvoke calls TestInvoke method of Client with static internal script hash. -func (s StaticClient) TestInvoke(prm TestInvokePrm) ([]stackitem.Item, error) { +func (s StaticClient) TestInvoke(ctx context.Context, prm TestInvokePrm) ([]stackitem.Item, error) { + _, span := tracing.StartSpanFromContext(ctx, "Morph.TestInvoke."+prm.method) + defer span.End() return s.client.TestInvoke( s.scScriptHash, prm.method, diff --git a/pkg/services/accounting/morph/executor.go b/pkg/services/accounting/morph/executor.go index b77d3e3e6c..6c2df84282 100644 --- a/pkg/services/accounting/morph/executor.go +++ b/pkg/services/accounting/morph/executor.go @@ -21,7 +21,7 @@ func NewExecutor(client *balance.Client) accountingSvc.ServiceExecutor { } } -func (s *morphExecutor) Balance(_ context.Context, body *accounting.BalanceRequestBody) (*accounting.BalanceResponseBody, error) { +func (s *morphExecutor) Balance(ctx context.Context, body *accounting.BalanceRequestBody) (*accounting.BalanceResponseBody, error) { idV2 := body.GetOwnerID() if idV2 == nil { return nil, errors.New("missing account") @@ -34,12 +34,12 @@ func (s *morphExecutor) Balance(_ context.Context, body *accounting.BalanceReque return nil, fmt.Errorf("invalid account: %w", err) } - amount, err := s.client.BalanceOf(id) + amount, err := s.client.BalanceOf(ctx, id) if err != nil { return nil, err } - balancePrecision, err := s.client.Decimals() + balancePrecision, err := s.client.Decimals(ctx) if err != nil { return nil, err } diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go index 9d8f665afd..58922fede2 100644 --- a/pkg/services/apemanager/executor.go +++ b/pkg/services/apemanager/executor.go @@ -78,12 +78,12 @@ var _ Server = (*Service)(nil) // validateContainerTargetRequest validates request for the container target. // It checks if request actor is the owner of the container, otherwise it denies the request. -func (s *Service) validateContainerTargetRequest(cid string, pubKey *keys.PublicKey) error { +func (s *Service) validateContainerTargetRequest(ctx context.Context, cid string, pubKey *keys.PublicKey) error { var cidSDK cidSDK.ID if err := cidSDK.DecodeString(cid); err != nil { return fmt.Errorf("invalid CID format: %w", err) } - isOwner, err := s.isActorContainerOwner(cidSDK, pubKey) + isOwner, err := s.isActorContainerOwner(ctx, cidSDK, pubKey) if err != nil { return fmt.Errorf("failed to check owner: %w", err) } @@ -117,7 +117,7 @@ func (s *Service) AddChain(ctx context.Context, req *apemanagerV2.AddChainReques switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { case apeV2.TargetTypeContainer: reqCID := req.GetBody().GetTarget().GetName() - if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { + if err = s.validateContainerTargetRequest(ctx, reqCID, pub); err != nil { return nil, err } target = policy_engine.ContainerTarget(reqCID) @@ -153,7 +153,7 @@ func (s *Service) RemoveChain(ctx context.Context, req *apemanagerV2.RemoveChain switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { case apeV2.TargetTypeContainer: reqCID := req.GetBody().GetTarget().GetName() - if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { + if err = s.validateContainerTargetRequest(ctx, reqCID, pub); err != nil { return nil, err } target = policy_engine.ContainerTarget(reqCID) @@ -177,7 +177,7 @@ func (s *Service) RemoveChain(ctx context.Context, req *apemanagerV2.RemoveChain return resp, nil } -func (s *Service) ListChains(_ context.Context, req *apemanagerV2.ListChainsRequest) (*apemanagerV2.ListChainsResponse, error) { +func (s *Service) ListChains(ctx context.Context, req *apemanagerV2.ListChainsRequest) (*apemanagerV2.ListChainsResponse, error) { pub, err := getSignaturePublicKey(req.GetVerificationHeader()) if err != nil { return nil, err @@ -188,7 +188,7 @@ func (s *Service) ListChains(_ context.Context, req *apemanagerV2.ListChainsRequ switch targetType := req.GetBody().GetTarget().GetTargetType(); targetType { case apeV2.TargetTypeContainer: reqCID := req.GetBody().GetTarget().GetName() - if err = s.validateContainerTargetRequest(reqCID, pub); err != nil { + if err = s.validateContainerTargetRequest(ctx, reqCID, pub); err != nil { return nil, err } target = policy_engine.ContainerTarget(reqCID) @@ -237,13 +237,13 @@ func getSignaturePublicKey(vh *session.RequestVerificationHeader) (*keys.PublicK return key, nil } -func (s *Service) isActorContainerOwner(cid cidSDK.ID, pk *keys.PublicKey) (bool, error) { +func (s *Service) isActorContainerOwner(ctx context.Context, cid cidSDK.ID, pk *keys.PublicKey) (bool, error) { var actor user.ID user.IDFromKey(&actor, (ecdsa.PublicKey)(*pk)) actorOwnerID := new(refs.OwnerID) actor.WriteToV2(actorOwnerID) - cnr, err := s.cnrSrc.Get(cid) + cnr, err := s.cnrSrc.Get(ctx, cid) if err != nil { return false, fmt.Errorf("get container error: %w", err) } diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index 86021c3db6..c9b0b7363a 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -1,6 +1,7 @@ package ape import ( + "context" "crypto/ecdsa" "errors" "fmt" @@ -48,7 +49,7 @@ type CheckPrm struct { // CheckCore provides methods to perform the common logic of APE check. type CheckCore interface { // CheckAPE performs the common policy-engine check logic on a prepared request. - CheckAPE(prm CheckPrm) error + CheckAPE(ctx context.Context, prm CheckPrm) error } type checkerCoreImpl struct { @@ -70,7 +71,7 @@ func New(localOverrideStorage policyengine.LocalOverrideStorage, morphChainStora } // CheckAPE performs the common policy-engine check logic on a prepared request. -func (c *checkerCoreImpl) CheckAPE(prm CheckPrm) error { +func (c *checkerCoreImpl) CheckAPE(ctx context.Context, prm CheckPrm) error { var cr policyengine.ChainRouter if prm.BearerToken != nil && !prm.BearerToken.Impersonate() { var err error @@ -85,7 +86,7 @@ func (c *checkerCoreImpl) CheckAPE(prm CheckPrm) error { cr = policyengine.NewDefaultChainRouterWithLocalOverrides(c.MorphChainStorage, c.LocalOverrideStorage) } - groups, err := aperequest.Groups(c.FrostFSSubjectProvider, prm.PublicKey) + groups, err := aperequest.Groups(ctx, c.FrostFSSubjectProvider, prm.PublicKey) if err != nil { return fmt.Errorf("failed to get group ids: %w", err) } diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 2c240412b8..e1fbe3960a 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -49,11 +49,11 @@ var ( ) type ir interface { - InnerRingKeys() ([][]byte, error) + InnerRingKeys(ctx context.Context) ([][]byte, error) } type containers interface { - Get(cid.ID) (*containercore.Container, error) + Get(context.Context, cid.ID) (*containercore.Container, error) } type apeChecker struct { @@ -106,7 +106,7 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.List") defer span.End() - role, pk, err := ac.getRoleWithoutContainerID(req.GetBody().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) + role, pk, err := ac.getRoleWithoutContainerID(ctx, req.GetBody().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) if err != nil { return nil, err } @@ -116,7 +116,7 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co nativeschema.PropertyKeyActorRole: role, } - reqProps, err = ac.fillWithUserClaimTags(reqProps, pk) + reqProps, err = ac.fillWithUserClaimTags(ctx, reqProps, pk) if err != nil { return nil, err } @@ -126,11 +126,11 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co } } - namespace, err := ac.namespaceByOwner(req.GetBody().GetOwnerID()) + namespace, err := ac.namespaceByOwner(ctx, req.GetBody().GetOwnerID()) if err != nil { return nil, fmt.Errorf("could not get owner namespace: %w", err) } - if err := ac.validateNamespaceByPublicKey(pk, namespace); err != nil { + if err := ac.validateNamespaceByPublicKey(ctx, pk, namespace); err != nil { return nil, err } @@ -143,7 +143,7 @@ func (ac *apeChecker) List(ctx context.Context, req *container.ListRequest) (*co reqProps, ) - groups, err := aperequest.Groups(ac.frostFSIDClient, pk) + groups, err := aperequest.Groups(ctx, ac.frostFSIDClient, pk) if err != nil { return nil, fmt.Errorf("failed to get group ids: %w", err) } @@ -179,7 +179,7 @@ func (ac *apeChecker) ListStream(req *container.ListStreamRequest, stream ListSt ctx, span := tracing.StartSpanFromContext(stream.Context(), "apeChecker.ListStream") defer span.End() - role, pk, err := ac.getRoleWithoutContainerID(req.GetBody().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) + role, pk, err := ac.getRoleWithoutContainerID(stream.Context(), req.GetBody().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) if err != nil { return err } @@ -189,7 +189,7 @@ func (ac *apeChecker) ListStream(req *container.ListStreamRequest, stream ListSt nativeschema.PropertyKeyActorRole: role, } - reqProps, err = ac.fillWithUserClaimTags(reqProps, pk) + reqProps, err = ac.fillWithUserClaimTags(ctx, reqProps, pk) if err != nil { return err } @@ -199,11 +199,11 @@ func (ac *apeChecker) ListStream(req *container.ListStreamRequest, stream ListSt } } - namespace, err := ac.namespaceByOwner(req.GetBody().GetOwnerID()) + namespace, err := ac.namespaceByOwner(ctx, req.GetBody().GetOwnerID()) if err != nil { return fmt.Errorf("could not get owner namespace: %w", err) } - if err := ac.validateNamespaceByPublicKey(pk, namespace); err != nil { + if err := ac.validateNamespaceByPublicKey(ctx, pk, namespace); err != nil { return err } @@ -216,7 +216,7 @@ func (ac *apeChecker) ListStream(req *container.ListStreamRequest, stream ListSt reqProps, ) - groups, err := aperequest.Groups(ac.frostFSIDClient, pk) + groups, err := aperequest.Groups(ctx, ac.frostFSIDClient, pk) if err != nil { return fmt.Errorf("failed to get group ids: %w", err) } @@ -252,7 +252,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont ctx, span := tracing.StartSpanFromContext(ctx, "apeChecker.Put") defer span.End() - role, pk, err := ac.getRoleWithoutContainerID(req.GetBody().GetContainer().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) + role, pk, err := ac.getRoleWithoutContainerID(ctx, req.GetBody().GetContainer().GetOwnerID(), req.GetMetaHeader(), req.GetVerificationHeader()) if err != nil { return nil, err } @@ -262,7 +262,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont nativeschema.PropertyKeyActorRole: role, } - reqProps, err = ac.fillWithUserClaimTags(reqProps, pk) + reqProps, err = ac.fillWithUserClaimTags(ctx, reqProps, pk) if err != nil { return nil, err } @@ -272,7 +272,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont } } - namespace, err := ac.namespaceByKnownOwner(req.GetBody().GetContainer().GetOwnerID()) + namespace, err := ac.namespaceByKnownOwner(ctx, req.GetBody().GetContainer().GetOwnerID()) if err != nil { return nil, fmt.Errorf("get namespace error: %w", err) } @@ -289,7 +289,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont reqProps, ) - groups, err := aperequest.Groups(ac.frostFSIDClient, pk) + groups, err := aperequest.Groups(ctx, ac.frostFSIDClient, pk) if err != nil { return nil, fmt.Errorf("failed to get group ids: %w", err) } @@ -321,7 +321,7 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont return nil, apeErr(nativeschema.MethodPutContainer, s) } -func (ac *apeChecker) getRoleWithoutContainerID(oID *refs.OwnerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader) (string, *keys.PublicKey, error) { +func (ac *apeChecker) getRoleWithoutContainerID(ctx context.Context, oID *refs.OwnerID, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader) (string, *keys.PublicKey, error) { if vh == nil { return "", nil, errMissingVerificationHeader } @@ -344,7 +344,7 @@ func (ac *apeChecker) getRoleWithoutContainerID(oID *refs.OwnerID, mh *session.R } pkBytes := pk.Bytes() - isIR, err := ac.isInnerRingKey(pkBytes) + isIR, err := ac.isInnerRingKey(ctx, pkBytes) if err != nil { return "", nil, err } @@ -365,7 +365,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, con return err } - cont, err := ac.reader.Get(id) + cont, err := ac.reader.Get(ctx, id) if err != nil { return err } @@ -381,7 +381,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, con namespace = cntNamespace } - groups, err := aperequest.Groups(ac.frostFSIDClient, pk) + groups, err := aperequest.Groups(ctx, ac.frostFSIDClient, pk) if err != nil { return fmt.Errorf("failed to get group ids: %w", err) } @@ -458,7 +458,7 @@ func (ac *apeChecker) getRequestProps(ctx context.Context, mh *session.RequestMe if err != nil { return nil, nil, err } - role, err := ac.getRole(actor, pk, cont, cnrID) + role, err := ac.getRole(ctx, actor, pk, cont, cnrID) if err != nil { return nil, nil, err } @@ -466,7 +466,7 @@ func (ac *apeChecker) getRequestProps(ctx context.Context, mh *session.RequestMe nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(pk.Bytes()), nativeschema.PropertyKeyActorRole: role, } - reqProps, err = ac.fillWithUserClaimTags(reqProps, pk) + reqProps, err = ac.fillWithUserClaimTags(ctx, reqProps, pk) if err != nil { return nil, nil, err } @@ -478,13 +478,13 @@ func (ac *apeChecker) getRequestProps(ctx context.Context, mh *session.RequestMe return reqProps, pk, nil } -func (ac *apeChecker) getRole(actor *user.ID, pk *keys.PublicKey, cont *containercore.Container, cnrID cid.ID) (string, error) { +func (ac *apeChecker) getRole(ctx context.Context, actor *user.ID, pk *keys.PublicKey, cont *containercore.Container, cnrID cid.ID) (string, error) { if cont.Value.Owner().Equals(*actor) { return nativeschema.PropertyValueContainerRoleOwner, nil } pkBytes := pk.Bytes() - isIR, err := ac.isInnerRingKey(pkBytes) + isIR, err := ac.isInnerRingKey(ctx, pkBytes) if err != nil { return "", err } @@ -492,7 +492,7 @@ func (ac *apeChecker) getRole(actor *user.ID, pk *keys.PublicKey, cont *containe return nativeschema.PropertyValueContainerRoleIR, nil } - isContainer, err := ac.isContainerKey(pkBytes, cnrID, cont) + isContainer, err := ac.isContainerKey(ctx, pkBytes, cnrID, cont) if err != nil { return "", err } @@ -586,8 +586,8 @@ func isOwnerFromKey(id user.ID, key *keys.PublicKey) bool { return id2.Equals(id) } -func (ac *apeChecker) isInnerRingKey(pk []byte) (bool, error) { - innerRingKeys, err := ac.ir.InnerRingKeys() +func (ac *apeChecker) isInnerRingKey(ctx context.Context, pk []byte) (bool, error) { + innerRingKeys, err := ac.ir.InnerRingKeys(ctx) if err != nil { return false, err } @@ -601,11 +601,11 @@ func (ac *apeChecker) isInnerRingKey(pk []byte) (bool, error) { return false, nil } -func (ac *apeChecker) isContainerKey(pk []byte, cnrID cid.ID, cont *containercore.Container) (bool, error) { +func (ac *apeChecker) isContainerKey(ctx context.Context, pk []byte, cnrID cid.ID, cont *containercore.Container) (bool, error) { binCnrID := make([]byte, sha256.Size) cnrID.Encode(binCnrID) - nm, err := netmap.GetLatestNetworkMap(ac.nm) + nm, err := netmap.GetLatestNetworkMap(ctx, ac.nm) if err != nil { return false, err } @@ -616,7 +616,7 @@ func (ac *apeChecker) isContainerKey(pk []byte, cnrID cid.ID, cont *containercor // then check previous netmap, this can happen in-between epoch change // when node migrates data from last epoch container - nm, err = netmap.GetPreviousNetworkMap(ac.nm) + nm, err = netmap.GetPreviousNetworkMap(ctx, ac.nm) if err != nil { return false, err } @@ -641,7 +641,7 @@ func isContainerNode(nm *netmapSDK.NetMap, pk, binCnrID []byte, cont *containerc return false } -func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { +func (ac *apeChecker) namespaceByOwner(ctx context.Context, owner *refs.OwnerID) (string, error) { var ownerSDK user.ID if owner == nil { return "", errOwnerIDIsNotSet @@ -652,7 +652,7 @@ func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { addr := ownerSDK.ScriptHash() namespace := "" - subject, err := ac.frostFSIDClient.GetSubject(addr) + subject, err := ac.frostFSIDClient.GetSubject(ctx, addr) if err == nil { namespace = subject.Namespace } else { @@ -663,7 +663,7 @@ func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { return namespace, nil } -func (ac *apeChecker) namespaceByKnownOwner(owner *refs.OwnerID) (string, error) { +func (ac *apeChecker) namespaceByKnownOwner(ctx context.Context, owner *refs.OwnerID) (string, error) { var ownerSDK user.ID if owner == nil { return "", errOwnerIDIsNotSet @@ -672,7 +672,7 @@ func (ac *apeChecker) namespaceByKnownOwner(owner *refs.OwnerID) (string, error) return "", err } addr := ownerSDK.ScriptHash() - subject, err := ac.frostFSIDClient.GetSubject(addr) + subject, err := ac.frostFSIDClient.GetSubject(ctx, addr) if err != nil { return "", fmt.Errorf("get subject error: %w", err) } @@ -706,12 +706,12 @@ func validateNamespace(cnrV2 *container.Container, ownerIDNamespace string) erro // validateNamespace validates if a namespace of a request actor equals to owner's namespace. // An actor's namespace is calculated by a public key. -func (ac *apeChecker) validateNamespaceByPublicKey(pk *keys.PublicKey, ownerIDNamespace string) error { +func (ac *apeChecker) validateNamespaceByPublicKey(ctx context.Context, pk *keys.PublicKey, ownerIDNamespace string) error { var actor user.ID user.IDFromKey(&actor, (ecdsa.PublicKey)(*pk)) actorOwnerID := new(refs.OwnerID) actor.WriteToV2(actorOwnerID) - actorNamespace, err := ac.namespaceByOwner(actorOwnerID) + actorNamespace, err := ac.namespaceByOwner(ctx, actorOwnerID) if err != nil { return fmt.Errorf("could not get actor namespace: %w", err) } @@ -722,11 +722,11 @@ func (ac *apeChecker) validateNamespaceByPublicKey(pk *keys.PublicKey, ownerIDNa } // fillWithUserClaimTags fills ape request properties with user claim tags getting them from frostfsid contract by actor public key. -func (ac *apeChecker) fillWithUserClaimTags(reqProps map[string]string, pk *keys.PublicKey) (map[string]string, error) { +func (ac *apeChecker) fillWithUserClaimTags(ctx context.Context, reqProps map[string]string, pk *keys.PublicKey) (map[string]string, error) { if reqProps == nil { reqProps = make(map[string]string) } - props, err := aperequest.FormFrostfsIDRequestProperties(ac.frostFSIDClient, pk) + props, err := aperequest.FormFrostfsIDRequestProperties(ctx, ac.frostFSIDClient, pk) if err != nil { return reqProps, err } diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 38b240d944..77a981d1ab 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -1092,7 +1092,7 @@ type irStub struct { keys [][]byte } -func (s *irStub) InnerRingKeys() ([][]byte, error) { +func (s *irStub) InnerRingKeys(_ context.Context) ([][]byte, error) { return s.keys, nil } @@ -1100,7 +1100,7 @@ type containerStub struct { c map[cid.ID]*containercore.Container } -func (s *containerStub) Get(id cid.ID) (*containercore.Container, error) { +func (s *containerStub) Get(_ context.Context, id cid.ID) (*containercore.Container, error) { if v, ok := s.c[id]; ok { return v, nil } @@ -1112,21 +1112,21 @@ type netmapStub struct { currentEpoch uint64 } -func (s *netmapStub) GetNetMap(diff uint64) (*netmap.NetMap, error) { +func (s *netmapStub) GetNetMap(ctx context.Context, diff uint64) (*netmap.NetMap, error) { if diff >= s.currentEpoch { return nil, errors.New("invalid diff") } - return s.GetNetMapByEpoch(s.currentEpoch - diff) + return s.GetNetMapByEpoch(ctx, s.currentEpoch-diff) } -func (s *netmapStub) GetNetMapByEpoch(epoch uint64) (*netmap.NetMap, error) { +func (s *netmapStub) GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmap.NetMap, error) { if nm, found := s.netmaps[epoch]; found { return nm, nil } return nil, errors.New("netmap not found") } -func (s *netmapStub) Epoch() (uint64, error) { +func (s *netmapStub) Epoch(ctx context.Context) (uint64, error) { return s.currentEpoch, nil } @@ -1135,7 +1135,7 @@ type frostfsidStub struct { subjectsExt map[util.Uint160]*client.SubjectExtended } -func (f *frostfsidStub) GetSubject(owner util.Uint160) (*client.Subject, error) { +func (f *frostfsidStub) GetSubject(ctx context.Context, owner util.Uint160) (*client.Subject, error) { s, ok := f.subjects[owner] if !ok { return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) @@ -1143,7 +1143,7 @@ func (f *frostfsidStub) GetSubject(owner util.Uint160) (*client.Subject, error) return s, nil } -func (f *frostfsidStub) GetSubjectExtended(owner util.Uint160) (*client.SubjectExtended, error) { +func (f *frostfsidStub) GetSubjectExtended(ctx context.Context, owner util.Uint160) (*client.SubjectExtended, error) { s, ok := f.subjectsExt[owner] if !ok { return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index cadf92e193..eaa608eba1 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -29,8 +29,8 @@ type Reader interface { // ContainersOf returns a list of container identifiers belonging // to the specified user of FrostFS system. Returns the identifiers // of all FrostFS containers if pointer to owner identifier is nil. - ContainersOf(*user.ID) ([]cid.ID, error) - IterateContainersOf(*user.ID, func(cid.ID) error) error + ContainersOf(context.Context, *user.ID) ([]cid.ID, error) + IterateContainersOf(context.Context, *user.ID, func(cid.ID) error) error } // Writer is an interface of container storage updater. @@ -133,7 +133,7 @@ func (s *morphExecutor) Delete(ctx context.Context, tokV2 *sessionV2.Token, body return new(container.DeleteResponseBody), nil } -func (s *morphExecutor) Get(_ context.Context, body *container.GetRequestBody) (*container.GetResponseBody, error) { +func (s *morphExecutor) Get(ctx context.Context, body *container.GetRequestBody) (*container.GetResponseBody, error) { idV2 := body.GetContainerID() if idV2 == nil { return nil, errors.New("missing container ID") @@ -146,7 +146,7 @@ func (s *morphExecutor) Get(_ context.Context, body *container.GetRequestBody) ( return nil, fmt.Errorf("invalid container ID: %w", err) } - cnr, err := s.rdr.Get(id) + cnr, err := s.rdr.Get(ctx, id) if err != nil { return nil, err } @@ -173,7 +173,7 @@ func (s *morphExecutor) Get(_ context.Context, body *container.GetRequestBody) ( return res, nil } -func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) (*container.ListResponseBody, error) { +func (s *morphExecutor) List(ctx context.Context, body *container.ListRequestBody) (*container.ListResponseBody, error) { idV2 := body.GetOwnerID() if idV2 == nil { return nil, errMissingUserID @@ -186,7 +186,7 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody) return nil, fmt.Errorf("invalid user ID: %w", err) } - cnrs, err := s.rdr.ContainersOf(&id) + cnrs, err := s.rdr.ContainersOf(ctx, &id) if err != nil { return nil, err } @@ -243,7 +243,7 @@ func (s *morphExecutor) ListStream(ctx context.Context, req *container.ListStrea return nil } - if err = s.rdr.IterateContainersOf(&id, processCID); err != nil { + if err = s.rdr.IterateContainersOf(ctx, &id, processCID); err != nil { return err } diff --git a/pkg/services/control/ir/server/calls.go b/pkg/services/control/ir/server/calls.go index e2c385c6ad..0509d2646c 100644 --- a/pkg/services/control/ir/server/calls.go +++ b/pkg/services/control/ir/server/calls.go @@ -48,7 +48,7 @@ func (s *Server) TickEpoch(ctx context.Context, req *control.TickEpochRequest) ( resp := new(control.TickEpochResponse) resp.SetBody(new(control.TickEpochResponse_Body)) - epoch, err := s.netmapClient.Epoch() + epoch, err := s.netmapClient.Epoch(ctx) if err != nil { return nil, fmt.Errorf("getting current epoch: %w", err) } @@ -77,7 +77,7 @@ func (s *Server) RemoveNode(ctx context.Context, req *control.RemoveNodeRequest) resp := new(control.RemoveNodeResponse) resp.SetBody(new(control.RemoveNodeResponse_Body)) - nm, err := s.netmapClient.NetMap() + nm, err := s.netmapClient.NetMap(ctx) if err != nil { return nil, fmt.Errorf("getting netmap: %w", err) } @@ -138,7 +138,7 @@ func (s *Server) RemoveContainer(ctx context.Context, req *control.RemoveContain return nil, status.Error(codes.InvalidArgument, "failed to read owner: "+err.Error()) } - cids, err := s.containerClient.ContainersOf(&owner) + cids, err := s.containerClient.ContainersOf(ctx, &owner) if err != nil { return nil, fmt.Errorf("failed to get owner's containers: %w", err) } diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 6982d780db..bbf2cf0cc7 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -1,6 +1,8 @@ package control import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/common" ) @@ -73,6 +75,7 @@ func SetNetmapStatus( // GetNetmapStatus executes ControlService.GetNetmapStatus RPC. func GetNetmapStatus( + _ context.Context, cli *client.Client, req *GetNetmapStatusRequest, opts ...client.CallOption, diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index da54015157..7469ea74ec 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -157,7 +157,7 @@ func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *obj return false, nil } - nodes, err := s.getContainerNodes(cid) + nodes, err := s.getContainerNodes(ctx, cid) if err != nil { return false, err } @@ -182,7 +182,7 @@ func (s *Server) replicateObject(ctx context.Context, addr oid.Address, obj *obj } func (s *Server) replicateTree(ctx context.Context, contID cid.ID, treeID string, forest pilorama.Forest) (bool, string, error) { - nodes, err := s.getContainerNodes(contID) + nodes, err := s.getContainerNodes(ctx, contID) if err != nil { return false, "", err } @@ -240,13 +240,13 @@ func (s *Server) replicateTreeToNode(ctx context.Context, forest pilorama.Forest } } -func (s *Server) getContainerNodes(contID cid.ID) ([]netmap.NodeInfo, error) { - nm, err := s.netMapSrc.GetNetMap(0) +func (s *Server) getContainerNodes(ctx context.Context, contID cid.ID) ([]netmap.NodeInfo, error) { + nm, err := s.netMapSrc.GetNetMap(ctx, 0) if err != nil { return nil, err } - c, err := s.cnrSrc.Get(contID) + c, err := s.cnrSrc.Get(ctx, contID) if err != nil { return nil, err } diff --git a/pkg/services/control/server/get_netmap_status.go b/pkg/services/control/server/get_netmap_status.go index 1c038253aa..5e04969100 100644 --- a/pkg/services/control/server/get_netmap_status.go +++ b/pkg/services/control/server/get_netmap_status.go @@ -10,12 +10,12 @@ import ( ) // GetNetmapStatus gets node status in FrostFS network. -func (s *Server) GetNetmapStatus(_ context.Context, req *control.GetNetmapStatusRequest) (*control.GetNetmapStatusResponse, error) { +func (s *Server) GetNetmapStatus(ctx context.Context, req *control.GetNetmapStatusRequest) (*control.GetNetmapStatusResponse, error) { if err := s.isValidRequest(req); err != nil { return nil, status.Error(codes.PermissionDenied, err.Error()) } - st, epoch, err := s.nodeState.GetNetmapStatus() + st, epoch, err := s.nodeState.GetNetmapStatus(ctx) if err != nil { return nil, err } diff --git a/pkg/services/control/server/server.go b/pkg/services/control/server/server.go index 94aa1ff5b0..59d701bc63 100644 --- a/pkg/services/control/server/server.go +++ b/pkg/services/control/server/server.go @@ -52,7 +52,7 @@ type NodeState interface { // but starts local maintenance regardless of the network settings. ForceMaintenance(ctx context.Context) error - GetNetmapStatus() (control.NetmapStatus, uint64, error) + GetNetmapStatus(ctx context.Context) (control.NetmapStatus, uint64, error) } // LocalOverrideStorageDecorator interface provides methods to decorate LocalOverrideEngine diff --git a/pkg/services/netmap/executor.go b/pkg/services/netmap/executor.go index 5223047dfb..44101a1530 100644 --- a/pkg/services/netmap/executor.go +++ b/pkg/services/netmap/executor.go @@ -42,7 +42,7 @@ type NetworkInfo interface { // Dump must return recent network information in FrostFS API v2 NetworkInfo structure. // // If protocol version is <=2.9, MillisecondsPerBlock and network config should be unset. - Dump(versionsdk.Version) (*netmapSDK.NetworkInfo, error) + Dump(context.Context, versionsdk.Version) (*netmapSDK.NetworkInfo, error) } func NewExecutionService(s NodeState, v versionsdk.Version, netInfo NetworkInfo, respSvc *response.Service) Server { @@ -82,7 +82,7 @@ func (s *executorSvc) LocalNodeInfo( } func (s *executorSvc) NetworkInfo( - _ context.Context, + ctx context.Context, req *netmap.NetworkInfoRequest, ) (*netmap.NetworkInfoResponse, error) { verV2 := req.GetMetaHeader().GetVersion() @@ -95,7 +95,7 @@ func (s *executorSvc) NetworkInfo( return nil, fmt.Errorf("can't read version: %w", err) } - ni, err := s.netInfo.Dump(ver) + ni, err := s.netInfo.Dump(ctx, ver) if err != nil { return nil, err } diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index db0f13ee73..86daec6cc9 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -669,13 +669,13 @@ func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.Pa } func (b Service) findRequestInfo(ctx context.Context, req MetaWithToken, idCnr cid.ID, op acl.Op) (info RequestInfo, err error) { - cnr, err := b.containers.Get(idCnr) // fetch actual container + cnr, err := b.containers.Get(ctx, idCnr) // fetch actual container if err != nil { return info, err } if req.token != nil { - currentEpoch, err := b.nm.Epoch() + currentEpoch, err := b.nm.Epoch(ctx) if err != nil { return info, errors.New("can't fetch current epoch") } @@ -727,13 +727,13 @@ func (b Service) findRequestInfo(ctx context.Context, req MetaWithToken, idCnr c // findRequestInfoWithoutACLOperationAssert is findRequestInfo without session token verb assert. func (b Service) findRequestInfoWithoutACLOperationAssert(ctx context.Context, req MetaWithToken, idCnr cid.ID) (info RequestInfo, err error) { - cnr, err := b.containers.Get(idCnr) // fetch actual container + cnr, err := b.containers.Get(ctx, idCnr) // fetch actual container if err != nil { return info, err } if req.token != nil { - currentEpoch, err := b.nm.Epoch() + currentEpoch, err := b.nm.Epoch(ctx) if err != nil { return info, errors.New("can't fetch current epoch") } diff --git a/pkg/services/object/acl/v2/types.go b/pkg/services/object/acl/v2/types.go index b03261b90f..3cf10eb562 100644 --- a/pkg/services/object/acl/v2/types.go +++ b/pkg/services/object/acl/v2/types.go @@ -1,9 +1,11 @@ package v2 +import "context" + // InnerRingFetcher is an interface that must provide // Inner Ring information. type InnerRingFetcher interface { // InnerRingKeys must return list of public keys of // the actual inner ring. - InnerRingKeys() ([][]byte, error) + InnerRingKeys(ctx context.Context) ([][]byte, error) } diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 4a3b5ba5ee..ee46a6fe46 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -99,7 +99,7 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { return err } - return c.checkerCore.CheckAPE(checkercore.CheckPrm{ + return c.checkerCore.CheckAPE(ctx, checkercore.CheckPrm{ Request: r, PublicKey: pub, Namespace: prm.Namespace, diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index e03b5750c2..97eb2b2d78 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -219,7 +219,7 @@ func scriptHashFromSenderKey(t *testing.T, senderKey string) util.Uint160 { return pk.GetScriptHash() } -func (f *frostfsIDProviderMock) GetSubject(key util.Uint160) (*client.Subject, error) { +func (f *frostfsIDProviderMock) GetSubject(ctx context.Context, key util.Uint160) (*client.Subject, error) { v, ok := f.subjects[key] if !ok { return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) @@ -227,7 +227,7 @@ func (f *frostfsIDProviderMock) GetSubject(key util.Uint160) (*client.Subject, e return v, nil } -func (f *frostfsIDProviderMock) GetSubjectExtended(key util.Uint160) (*client.SubjectExtended, error) { +func (f *frostfsIDProviderMock) GetSubjectExtended(ctx context.Context, key util.Uint160) (*client.SubjectExtended, error) { v, ok := f.subjectsExtended[key] if !ok { return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) @@ -619,21 +619,21 @@ type netmapStub struct { currentEpoch uint64 } -func (s *netmapStub) GetNetMap(diff uint64) (*netmapSDK.NetMap, error) { +func (s *netmapStub) GetNetMap(ctx context.Context, diff uint64) (*netmapSDK.NetMap, error) { if diff >= s.currentEpoch { return nil, errors.New("invalid diff") } - return s.GetNetMapByEpoch(s.currentEpoch - diff) + return s.GetNetMapByEpoch(ctx, s.currentEpoch-diff) } -func (s *netmapStub) GetNetMapByEpoch(epoch uint64) (*netmapSDK.NetMap, error) { +func (s *netmapStub) GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmapSDK.NetMap, error) { if nm, found := s.netmaps[epoch]; found { return nm, nil } return nil, errors.New("netmap not found") } -func (s *netmapStub) Epoch() (uint64, error) { +func (s *netmapStub) Epoch(ctx context.Context) (uint64, error) { return s.currentEpoch, nil } @@ -641,14 +641,14 @@ type testContainerSource struct { containers map[cid.ID]*container.Container } -func (s *testContainerSource) Get(cnrID cid.ID) (*container.Container, error) { +func (s *testContainerSource) Get(ctx context.Context, cnrID cid.ID) (*container.Container, error) { if cnr, found := s.containers[cnrID]; found { return cnr, nil } return nil, fmt.Errorf("container not found") } -func (s *testContainerSource) DeletionInfo(cid.ID) (*container.DelInfo, error) { +func (s *testContainerSource) DeletionInfo(context.Context, cid.ID) (*container.DelInfo, error) { return nil, nil } diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index cb9bbf1b8a..001a5f71e6 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -140,7 +140,7 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re reqProps[xheadKey] = xhead.GetValue() } - reqProps, err = c.fillWithUserClaimTags(reqProps, prm) + reqProps, err = c.fillWithUserClaimTags(ctx, reqProps, prm) if err != nil { return defaultRequest, err } @@ -177,7 +177,7 @@ func (c *checkerImpl) fillHeaderWithECParent(ctx context.Context, prm Prm, heade return nil, fmt.Errorf("EC parent object ID format error: %w", err) } // only container node have access to collect parent object - contNode, err := c.currentNodeIsContainerNode(prm.Container) + contNode, err := c.currentNodeIsContainerNode(ctx, prm.Container) if err != nil { return nil, fmt.Errorf("check container node status: %w", err) } @@ -200,13 +200,13 @@ func isLogicalError(err error) bool { return errors.As(err, &errObjRemoved) || errors.As(err, &errObjNotFound) } -func (c *checkerImpl) currentNodeIsContainerNode(cnrID cid.ID) (bool, error) { - cnr, err := c.cnrSource.Get(cnrID) +func (c *checkerImpl) currentNodeIsContainerNode(ctx context.Context, cnrID cid.ID) (bool, error) { + cnr, err := c.cnrSource.Get(ctx, cnrID) if err != nil { return false, err } - nm, err := netmap.GetLatestNetworkMap(c.nm) + nm, err := netmap.GetLatestNetworkMap(ctx, c.nm) if err != nil { return false, err } @@ -220,7 +220,7 @@ func (c *checkerImpl) currentNodeIsContainerNode(cnrID cid.ID) (bool, error) { return true, nil } - nm, err = netmap.GetPreviousNetworkMap(c.nm) + nm, err = netmap.GetPreviousNetworkMap(ctx, c.nm) if err != nil { return false, err } @@ -229,7 +229,7 @@ func (c *checkerImpl) currentNodeIsContainerNode(cnrID cid.ID) (bool, error) { } // fillWithUserClaimTags fills ape request properties with user claim tags getting them from frostfsid contract by actor public key. -func (c *checkerImpl) fillWithUserClaimTags(reqProps map[string]string, prm Prm) (map[string]string, error) { +func (c *checkerImpl) fillWithUserClaimTags(ctx context.Context, reqProps map[string]string, prm Prm) (map[string]string, error) { if reqProps == nil { reqProps = make(map[string]string) } @@ -237,7 +237,7 @@ func (c *checkerImpl) fillWithUserClaimTags(reqProps map[string]string, prm Prm) if err != nil { return nil, err } - props, err := aperequest.FormFrostfsIDRequestProperties(c.frostFSIDClient, pk) + props, err := aperequest.FormFrostfsIDRequestProperties(ctx, c.frostFSIDClient, pk) if err != nil { return reqProps, err } diff --git a/pkg/services/object/common/target/target.go b/pkg/services/object/common/target/target.go index 9e0f492972..b2ae79dbc9 100644 --- a/pkg/services/object/common/target/target.go +++ b/pkg/services/object/common/target/target.go @@ -1,6 +1,7 @@ package target import ( + "context" "errors" "fmt" @@ -13,20 +14,20 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" ) -func New(prm objectwriter.Params) (transformer.ChunkedObjectWriter, error) { +func New(ctx context.Context, prm objectwriter.Params) (transformer.ChunkedObjectWriter, error) { // prepare needed put parameters - if err := preparePrm(&prm); err != nil { + if err := preparePrm(ctx, &prm); err != nil { return nil, fmt.Errorf("could not prepare put parameters: %w", err) } if prm.Header.Signature() != nil { - return newUntrustedTarget(&prm) + return newUntrustedTarget(ctx, &prm) } - return newTrustedTarget(&prm) + return newTrustedTarget(ctx, &prm) } -func newUntrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { - maxPayloadSz := prm.Config.MaxSizeSrc.MaxObjectSize() +func newUntrustedTarget(ctx context.Context, prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { + maxPayloadSz := prm.Config.MaxSizeSrc.MaxObjectSize(ctx) if maxPayloadSz == 0 { return nil, errors.New("could not obtain max object size parameter") } @@ -48,9 +49,9 @@ func newUntrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWrit }, nil } -func newTrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { +func newTrustedTarget(ctx context.Context, prm *objectwriter.Params) (transformer.ChunkedObjectWriter, error) { prm.Relay = nil // do not relay request without signature - maxPayloadSz := prm.Config.MaxSizeSrc.MaxObjectSize() + maxPayloadSz := prm.Config.MaxSizeSrc.MaxObjectSize(ctx) if maxPayloadSz == 0 { return nil, errors.New("could not obtain max object size parameter") } @@ -111,11 +112,11 @@ func newTrustedTarget(prm *objectwriter.Params) (transformer.ChunkedObjectWriter }, nil } -func preparePrm(prm *objectwriter.Params) error { +func preparePrm(ctx context.Context, prm *objectwriter.Params) error { var err error // get latest network map - nm, err := netmap.GetLatestNetworkMap(prm.Config.NetmapSource) + nm, err := netmap.GetLatestNetworkMap(ctx, prm.Config.NetmapSource) if err != nil { return fmt.Errorf("could not get latest network map: %w", err) } @@ -126,7 +127,7 @@ func preparePrm(prm *objectwriter.Params) error { } // get container to store the object - cnrInfo, err := prm.Config.ContainerSource.Get(idCnr) + cnrInfo, err := prm.Config.ContainerSource.Get(ctx, idCnr) if err != nil { return fmt.Errorf("could not get container by ID: %w", err) } diff --git a/pkg/services/object/common/writer/common.go b/pkg/services/object/common/writer/common.go index 3b68efab41..dae168baff 100644 --- a/pkg/services/object/common/writer/common.go +++ b/pkg/services/object/common/writer/common.go @@ -29,7 +29,7 @@ func (c *Config) NewNodeIterator(opts []placement.Option) *NodeIterator { } func (n *NodeIterator) ForEachNode(ctx context.Context, f func(context.Context, NodeDescriptor) error) error { - traverser, err := placement.NewTraverser(n.Traversal.Opts...) + traverser, err := placement.NewTraverser(ctx, n.Traversal.Opts...) if err != nil { return fmt.Errorf("could not create object placement traverser: %w", err) } diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index 94bcf6a32c..8f269ec217 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -85,7 +85,7 @@ func (e *ECWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error } func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.Object) (bool, bool, error) { - currentNodeIsContainerNode, err := e.currentNodeIsContainerNode() + currentNodeIsContainerNode, err := e.currentNodeIsContainerNode(ctx) if err != nil { return false, false, err } @@ -108,8 +108,8 @@ func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.O return true, currentNodeIsContainerNode, nil } -func (e *ECWriter) currentNodeIsContainerNode() (bool, error) { - t, err := placement.NewTraverser(e.PlacementOpts...) +func (e *ECWriter) currentNodeIsContainerNode(ctx context.Context) (bool, error) { + t, err := placement.NewTraverser(ctx, e.PlacementOpts...) if err != nil { return false, err } @@ -128,7 +128,7 @@ func (e *ECWriter) currentNodeIsContainerNode() (bool, error) { } func (e *ECWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index uint32) error { - t, err := placement.NewTraverser(append(e.PlacementOpts, placement.ForObject(objID))...) + t, err := placement.NewTraverser(ctx, append(e.PlacementOpts, placement.ForObject(objID))...) if err != nil { return err } @@ -180,7 +180,7 @@ func (e *ECWriter) writeECPart(ctx context.Context, obj *objectSDK.Object) error return e.writePartLocal(ctx, obj) } - t, err := placement.NewTraverser(append(e.PlacementOpts, placement.ForObject(obj.ECHeader().Parent()))...) + t, err := placement.NewTraverser(ctx, append(e.PlacementOpts, placement.ForObject(obj.ECHeader().Parent()))...) if err != nil { return err } @@ -217,7 +217,7 @@ func (e *ECWriter) writeRawObject(ctx context.Context, obj *objectSDK.Object) er } partsProcessed := make([]atomic.Bool, len(parts)) objID, _ := obj.ID() - t, err := placement.NewTraverser(append(e.PlacementOpts, placement.ForObject(objID))...) + t, err := placement.NewTraverser(ctx, append(e.PlacementOpts, placement.ForObject(objID))...) if err != nil { return err } diff --git a/pkg/services/object/common/writer/ec_test.go b/pkg/services/object/common/writer/ec_test.go index 8ad7e641a5..b7764661f7 100644 --- a/pkg/services/object/common/writer/ec_test.go +++ b/pkg/services/object/common/writer/ec_test.go @@ -39,7 +39,7 @@ type testPlacementBuilder struct { vectors [][]netmap.NodeInfo } -func (p *testPlacementBuilder) BuildPlacement(_ cid.ID, _ *oid.ID, _ netmap.PlacementPolicy) ( +func (p *testPlacementBuilder) BuildPlacement(ctx context.Context, _ cid.ID, _ *oid.ID, _ netmap.PlacementPolicy) ( [][]netmap.NodeInfo, error, ) { arr := slices.Clone(p.vectors[0]) diff --git a/pkg/services/object/common/writer/writer.go b/pkg/services/object/common/writer/writer.go index 0e4c4d9c62..adaf1945b9 100644 --- a/pkg/services/object/common/writer/writer.go +++ b/pkg/services/object/common/writer/writer.go @@ -24,7 +24,7 @@ type MaxSizeSource interface { // of physically stored object in system. // // Must return 0 if value can not be obtained. - MaxObjectSize() uint64 + MaxObjectSize(context.Context) uint64 } type ClientConstructor interface { @@ -32,7 +32,7 @@ type ClientConstructor interface { } type InnerRing interface { - InnerRingKeys() ([][]byte, error) + InnerRingKeys(ctx context.Context) ([][]byte, error) } type FormatValidatorConfig interface { diff --git a/pkg/services/object/get/assemblerec.go b/pkg/services/object/get/assemblerec.go index a53299480e..e0a7e1da6f 100644 --- a/pkg/services/object/get/assemblerec.go +++ b/pkg/services/object/get/assemblerec.go @@ -125,7 +125,7 @@ func (a *assemblerec) reconstructObject(ctx context.Context, writer ObjectWriter func (a *assemblerec) reconstructObjectFromParts(ctx context.Context, headers bool) (*objectSDK.Object, error) { objID := a.addr.Object() - trav, cnr, err := a.traverserGenerator.GenerateTraverser(a.addr.Container(), &objID, a.epoch) + trav, cnr, err := a.traverserGenerator.GenerateTraverser(ctx, a.addr.Container(), &objID, a.epoch) if err != nil { return nil, err } diff --git a/pkg/services/object/get/get_test.go b/pkg/services/object/get/get_test.go index 6827018dcf..3efc72065a 100644 --- a/pkg/services/object/get/get_test.go +++ b/pkg/services/object/get/get_test.go @@ -63,7 +63,7 @@ type testClient struct { type testEpochReceiver uint64 -func (e testEpochReceiver) Epoch() (uint64, error) { +func (e testEpochReceiver) Epoch(ctx context.Context) (uint64, error) { return uint64(e), nil } @@ -79,7 +79,7 @@ func newTestStorage() *testStorage { } } -func (g *testTraverserGenerator) GenerateTraverser(cnr cid.ID, obj *oid.ID, e uint64) (*placement.Traverser, *containerCore.Container, error) { +func (g *testTraverserGenerator) GenerateTraverser(ctx context.Context, cnr cid.ID, obj *oid.ID, e uint64) (*placement.Traverser, *containerCore.Container, error) { opts := make([]placement.Option, 0, 4) opts = append(opts, placement.ForContainer(g.c), @@ -91,13 +91,13 @@ func (g *testTraverserGenerator) GenerateTraverser(cnr cid.ID, obj *oid.ID, e ui opts = append(opts, placement.ForObject(*obj)) } - t, err := placement.NewTraverser(opts...) + t, err := placement.NewTraverser(context.Background(), opts...) return t, &containerCore.Container{ Value: g.c, }, err } -func (p *testPlacementBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, _ netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { +func (p *testPlacementBuilder) BuildPlacement(ctx context.Context, cnr cid.ID, obj *oid.ID, _ netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { var addr oid.Address addr.SetContainer(cnr) diff --git a/pkg/services/object/get/getrangeec_test.go b/pkg/services/object/get/getrangeec_test.go index 599a6f176f..83ef547449 100644 --- a/pkg/services/object/get/getrangeec_test.go +++ b/pkg/services/object/get/getrangeec_test.go @@ -28,14 +28,14 @@ type containerStorage struct { cnt *container.Container } -func (cs *containerStorage) Get(cid.ID) (*coreContainer.Container, error) { +func (cs *containerStorage) Get(context.Context, cid.ID) (*coreContainer.Container, error) { coreCnt := coreContainer.Container{ Value: *cs.cnt, } return &coreCnt, nil } -func (cs *containerStorage) DeletionInfo(cid.ID) (*coreContainer.DelInfo, error) { +func (cs *containerStorage) DeletionInfo(context.Context, cid.ID) (*coreContainer.DelInfo, error) { return nil, nil } diff --git a/pkg/services/object/get/remote_getter.go b/pkg/services/object/get/remote_getter.go index 0df67dec9c..2c64244cf5 100644 --- a/pkg/services/object/get/remote_getter.go +++ b/pkg/services/object/get/remote_getter.go @@ -30,7 +30,7 @@ func (g *RemoteGetter) Get(ctx context.Context, prm RemoteGetPrm) (*objectSDK.Ob if err != nil { return nil, err } - epoch, err := g.es.Epoch() + epoch, err := g.es.Epoch(ctx) if err != nil { return nil, err } diff --git a/pkg/services/object/get/request.go b/pkg/services/object/get/request.go index be0950c60a..268080486a 100644 --- a/pkg/services/object/get/request.go +++ b/pkg/services/object/get/request.go @@ -122,7 +122,7 @@ func (r *request) initEpoch(ctx context.Context) bool { return true } - e, err := r.epochSource.Epoch() + e, err := r.epochSource.Epoch(ctx) switch { default: @@ -141,7 +141,7 @@ func (r *request) initEpoch(ctx context.Context) bool { func (r *request) generateTraverser(ctx context.Context, addr oid.Address) (*placement.Traverser, bool) { obj := addr.Object() - t, _, err := r.traverserGenerator.GenerateTraverser(addr.Container(), &obj, r.curProcEpoch) + t, _, err := r.traverserGenerator.GenerateTraverser(ctx, addr.Container(), &obj, r.curProcEpoch) switch { default: diff --git a/pkg/services/object/get/types.go b/pkg/services/object/get/types.go index 9669afdba1..664366d1b4 100644 --- a/pkg/services/object/get/types.go +++ b/pkg/services/object/get/types.go @@ -20,11 +20,11 @@ import ( ) type epochSource interface { - Epoch() (uint64, error) + Epoch(ctx context.Context) (uint64, error) } type traverserGenerator interface { - GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, *container.Container, error) + GenerateTraverser(context.Context, cid.ID, *oid.ID, uint64) (*placement.Traverser, *container.Container, error) } type keyStorage interface { diff --git a/pkg/services/object/get/v2/get_range_hash.go b/pkg/services/object/get/v2/get_range_hash.go index 7d26a38c32..308ccd5129 100644 --- a/pkg/services/object/get/v2/get_range_hash.go +++ b/pkg/services/object/get/v2/get_range_hash.go @@ -22,7 +22,7 @@ import ( // GetRangeHash calls internal service and returns v2 response. func (s *Service) GetRangeHash(ctx context.Context, req *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) { - forward, err := s.needToForwardGetRangeHashRequest(req) + forward, err := s.needToForwardGetRangeHashRequest(ctx, req) if err != nil { return nil, err } @@ -48,7 +48,7 @@ type getRangeForwardParams struct { address oid.Address } -func (s *Service) needToForwardGetRangeHashRequest(req *objectV2.GetRangeHashRequest) (getRangeForwardParams, error) { +func (s *Service) needToForwardGetRangeHashRequest(ctx context.Context, req *objectV2.GetRangeHashRequest) (getRangeForwardParams, error) { if req.GetMetaHeader().GetTTL() <= 1 { return getRangeForwardParams{}, nil } @@ -66,17 +66,17 @@ func (s *Service) needToForwardGetRangeHashRequest(req *objectV2.GetRangeHashReq } result.address = addr - cont, err := s.contSource.Get(addr.Container()) + cont, err := s.contSource.Get(ctx, addr.Container()) if err != nil { return result, fmt.Errorf("(%T) could not get container: %w", s, err) } - epoch, err := s.netmapSource.Epoch() + epoch, err := s.netmapSource.Epoch(ctx) if err != nil { return result, fmt.Errorf("(%T) could not get epoch: %w", s, err) } - nm, err := s.netmapSource.GetNetMapByEpoch(epoch) + nm, err := s.netmapSource.GetNetMapByEpoch(ctx, epoch) if err != nil { return result, fmt.Errorf("(%T) could not get netmap: %w", s, err) } @@ -84,7 +84,7 @@ func (s *Service) needToForwardGetRangeHashRequest(req *objectV2.GetRangeHashReq builder := placement.NewNetworkMapBuilder(nm) objectID := addr.Object() - nodesVector, err := builder.BuildPlacement(addr.Container(), &objectID, cont.Value.PlacementPolicy()) + nodesVector, err := builder.BuildPlacement(ctx, addr.Container(), &objectID, cont.Value.PlacementPolicy()) if err != nil { return result, fmt.Errorf("(%T) could not build object placement: %w", s, err) } diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index 91b4efdc10..5aba13f66c 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -112,7 +112,7 @@ func (s *Streamer) init(ctx context.Context, req *objectV2.PatchRequest) error { } oV2.GetHeader().SetOwnerID(ownerID) - target, err := target.New(objectwriter.Params{ + target, err := target.New(ctx, objectwriter.Params{ Config: s.Config, Common: commonPrm, Header: objectSDK.NewFromV2(oV2), diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index fec50b1d95..f3c2dca1a3 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -86,7 +86,7 @@ func (s *Service) PutSingle(ctx context.Context, req *objectAPI.PutSingleRequest } func (s *Service) validatePutSingle(ctx context.Context, obj *objectSDK.Object) (object.ContentMeta, error) { - if err := s.validarePutSingleSize(obj); err != nil { + if err := s.validarePutSingleSize(ctx, obj); err != nil { return object.ContentMeta{}, err } @@ -97,12 +97,12 @@ func (s *Service) validatePutSingle(ctx context.Context, obj *objectSDK.Object) return s.validatePutSingleObject(ctx, obj) } -func (s *Service) validarePutSingleSize(obj *objectSDK.Object) error { +func (s *Service) validarePutSingleSize(ctx context.Context, obj *objectSDK.Object) error { if uint64(len(obj.Payload())) != obj.PayloadSize() { return target.ErrWrongPayloadSize } - maxAllowedSize := s.Config.MaxSizeSrc.MaxObjectSize() + maxAllowedSize := s.Config.MaxSizeSrc.MaxObjectSize(ctx) if obj.PayloadSize() > maxAllowedSize { return target.ErrExceedingMaxSize } @@ -153,7 +153,7 @@ func (s *Service) validatePutSingleObject(ctx context.Context, obj *objectSDK.Ob func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *objectAPI.PutSingleRequest, meta object.ContentMeta) error { localOnly := req.GetMetaHeader().GetTTL() <= 1 - placement, err := s.getPutSinglePlacementOptions(obj, req.GetBody().GetCopiesNumber(), localOnly) + placement, err := s.getPutSinglePlacementOptions(ctx, obj, req.GetBody().GetCopiesNumber(), localOnly) if err != nil { return err } @@ -218,14 +218,14 @@ type putSinglePlacement struct { resetSuccessAfterOnBroadcast bool } -func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumber []uint32, localOnly bool) (putSinglePlacement, error) { +func (s *Service) getPutSinglePlacementOptions(ctx context.Context, obj *objectSDK.Object, copiesNumber []uint32, localOnly bool) (putSinglePlacement, error) { var result putSinglePlacement cnrID, ok := obj.ContainerID() if !ok { return result, errors.New("missing container ID") } - cnrInfo, err := s.Config.ContainerSource.Get(cnrID) + cnrInfo, err := s.Config.ContainerSource.Get(ctx, cnrID) if err != nil { return result, fmt.Errorf("could not get container by ID: %w", err) } @@ -249,7 +249,7 @@ func (s *Service) getPutSinglePlacementOptions(obj *objectSDK.Object, copiesNumb } result.placementOptions = append(result.placementOptions, placement.ForObject(objID)) - latestNetmap, err := netmap.GetLatestNetworkMap(s.Config.NetmapSource) + latestNetmap, err := netmap.GetLatestNetworkMap(ctx, s.Config.NetmapSource) if err != nil { return result, fmt.Errorf("could not get latest network map: %w", err) } diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index f71309d31f..19768b7fae 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -36,7 +36,7 @@ func (p *Streamer) Init(ctx context.Context, prm *PutInitPrm) error { } var err error - p.target, err = target.New(prmTarget) + p.target, err = target.New(ctx, prmTarget) if err != nil { return fmt.Errorf("(%T) could not initialize object target: %w", p, err) } diff --git a/pkg/services/object/put/v2/streamer.go b/pkg/services/object/put/v2/streamer.go index 1cd10cd7f6..f0c6481878 100644 --- a/pkg/services/object/put/v2/streamer.go +++ b/pkg/services/object/put/v2/streamer.go @@ -56,7 +56,7 @@ func (s *streamer) Send(ctx context.Context, req *object.PutRequest) (err error) s.saveChunks = v.GetSignature() != nil if s.saveChunks { - maxSz := s.stream.MaxSizeSrc.MaxObjectSize() + maxSz := s.stream.MaxSizeSrc.MaxObjectSize(ctx) s.sizes = &sizes{ payloadSz: v.GetHeader().GetPayloadLength(), diff --git a/pkg/services/object/search/container.go b/pkg/services/object/search/container.go index e82f999cf1..60d469b11d 100644 --- a/pkg/services/object/search/container.go +++ b/pkg/services/object/search/container.go @@ -20,7 +20,7 @@ func (exec *execCtx) executeOnContainer(ctx context.Context) error { ) // initialize epoch number - if err := exec.initEpoch(); err != nil { + if err := exec.initEpoch(ctx); err != nil { return fmt.Errorf("%s: %w", logs.CouldNotGetCurrentEpochNumber, err) } @@ -48,7 +48,7 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { zap.Uint64("number", exec.curProcEpoch), ) - traverser, _, err := exec.svc.traverserGenerator.GenerateTraverser(exec.containerID(), nil, exec.curProcEpoch) + traverser, _, err := exec.svc.traverserGenerator.GenerateTraverser(ctx, exec.containerID(), nil, exec.curProcEpoch) if err != nil { return fmt.Errorf("%s: %w", logs.SearchCouldNotGenerateContainerTraverser, err) } @@ -114,9 +114,9 @@ func (exec *execCtx) processCurrentEpoch(ctx context.Context) error { return nil } -func (exec *execCtx) getContainer() (containerSDK.Container, error) { +func (exec *execCtx) getContainer(ctx context.Context) (containerSDK.Container, error) { cnrID := exec.containerID() - cnr, err := exec.svc.containerSource.Get(cnrID) + cnr, err := exec.svc.containerSource.Get(ctx, cnrID) if err != nil { return containerSDK.Container{}, err } diff --git a/pkg/services/object/search/exec.go b/pkg/services/object/search/exec.go index eb9635f147..ced51ecce2 100644 --- a/pkg/services/object/search/exec.go +++ b/pkg/services/object/search/exec.go @@ -1,6 +1,8 @@ package searchsvc import ( + "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -48,13 +50,13 @@ func (exec *execCtx) netmapLookupDepth() uint64 { return exec.prm.common.NetmapLookupDepth() } -func (exec *execCtx) initEpoch() error { +func (exec *execCtx) initEpoch(ctx context.Context) error { exec.curProcEpoch = exec.netmapEpoch() if exec.curProcEpoch > 0 { return nil } - e, err := exec.svc.currentEpochReceiver.Epoch() + e, err := exec.svc.currentEpochReceiver.Epoch(ctx) if err != nil { return err } diff --git a/pkg/services/object/search/search_test.go b/pkg/services/object/search/search_test.go index 05643eb2b3..918ad421f8 100644 --- a/pkg/services/object/search/search_test.go +++ b/pkg/services/object/search/search_test.go @@ -59,7 +59,7 @@ type simpleIDWriter struct { type testEpochReceiver uint64 -func (e testEpochReceiver) Epoch() (uint64, error) { +func (e testEpochReceiver) Epoch(ctx context.Context) (uint64, error) { return uint64(e), nil } @@ -82,8 +82,8 @@ func newTestStorage() *testStorage { } } -func (g *testTraverserGenerator) GenerateTraverser(_ cid.ID, _ *oid.ID, epoch uint64) (*placement.Traverser, *containerCore.Container, error) { - t, err := placement.NewTraverser( +func (g *testTraverserGenerator) GenerateTraverser(ctx context.Context, _ cid.ID, _ *oid.ID, epoch uint64) (*placement.Traverser, *containerCore.Container, error) { + t, err := placement.NewTraverser(context.Background(), placement.ForContainer(g.c), placement.UseBuilder(g.b[epoch]), placement.WithoutSuccessTracking(), @@ -91,7 +91,7 @@ func (g *testTraverserGenerator) GenerateTraverser(_ cid.ID, _ *oid.ID, epoch ui return t, &containerCore.Container{Value: g.c}, err } -func (p *testPlacementBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, _ netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { +func (p *testPlacementBuilder) BuildPlacement(ctx context.Context, cnr cid.ID, obj *oid.ID, _ netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { var addr oid.Address addr.SetContainer(cnr) diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index 77d25357a5..e1aeca9576 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -46,11 +46,11 @@ type cfg struct { } traverserGenerator interface { - GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, *container.Container, error) + GenerateTraverser(context.Context, cid.ID, *oid.ID, uint64) (*placement.Traverser, *container.Container, error) } currentEpochReceiver interface { - Epoch() (uint64, error) + Epoch(ctx context.Context) (uint64, error) } keyStore *util.KeyStorage diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index 910384a0bc..fed168187a 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -113,7 +113,7 @@ func (c *clientWrapper) searchObjects(ctx context.Context, exec *execCtx, info c } func (e *storageEngineWrapper) search(ctx context.Context, exec *execCtx) ([]oid.ID, error) { - cnr, err := exec.getContainer() + cnr, err := exec.getContainer(ctx) if err != nil { return nil, err } diff --git a/pkg/services/object/util/placement.go b/pkg/services/object/util/placement.go index 1bd39f9ead..195944f92a 100644 --- a/pkg/services/object/util/placement.go +++ b/pkg/services/object/util/placement.go @@ -1,6 +1,7 @@ package util import ( + "context" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" @@ -43,8 +44,8 @@ func NewLocalPlacement(b placement.Builder, s netmap.AnnouncedKeys) placement.Bu } } -func (p *localPlacement) BuildPlacement(cnr cid.ID, obj *oid.ID, policy netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { - vs, err := p.builder.BuildPlacement(cnr, obj, policy) +func (p *localPlacement) BuildPlacement(ctx context.Context, cnr cid.ID, obj *oid.ID, policy netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { + vs, err := p.builder.BuildPlacement(ctx, cnr, obj, policy) if err != nil { return nil, fmt.Errorf("(%T) could not build object placement: %w", p, err) } @@ -76,8 +77,8 @@ func NewRemotePlacementBuilder(b placement.Builder, s netmap.AnnouncedKeys) plac } } -func (p *remotePlacement) BuildPlacement(cnr cid.ID, obj *oid.ID, policy netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { - vs, err := p.builder.BuildPlacement(cnr, obj, policy) +func (p *remotePlacement) BuildPlacement(ctx context.Context, cnr cid.ID, obj *oid.ID, policy netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { + vs, err := p.builder.BuildPlacement(ctx, cnr, obj, policy) if err != nil { return nil, fmt.Errorf("(%T) could not build object placement: %w", p, err) } @@ -122,15 +123,15 @@ func (g *TraverserGenerator) WithTraverseOptions(opts ...placement.Option) *Trav // GenerateTraverser generates placement Traverser for provided object address // using epoch-th network map. -func (g *TraverserGenerator) GenerateTraverser(idCnr cid.ID, idObj *oid.ID, epoch uint64) (*placement.Traverser, *container.Container, error) { +func (g *TraverserGenerator) GenerateTraverser(ctx context.Context, idCnr cid.ID, idObj *oid.ID, epoch uint64) (*placement.Traverser, *container.Container, error) { // get network map by epoch - nm, err := g.netMapSrc.GetNetMapByEpoch(epoch) + nm, err := g.netMapSrc.GetNetMapByEpoch(ctx, epoch) if err != nil { return nil, nil, fmt.Errorf("could not get network map #%d: %w", epoch, err) } // get container related container - cnr, err := g.cnrSrc.Get(idCnr) + cnr, err := g.cnrSrc.Get(ctx, idCnr) if err != nil { return nil, nil, fmt.Errorf("could not get container: %w", err) } @@ -160,7 +161,7 @@ func (g *TraverserGenerator) GenerateTraverser(idCnr cid.ID, idObj *oid.ID, epoc ) } - t, err := placement.NewTraverser(traverseOpts...) + t, err := placement.NewTraverser(ctx, traverseOpts...) if err != nil { return nil, nil, err } diff --git a/pkg/services/object_manager/placement/netmap.go b/pkg/services/object_manager/placement/netmap.go index 1782e27ea3..b3f8d9c03f 100644 --- a/pkg/services/object_manager/placement/netmap.go +++ b/pkg/services/object_manager/placement/netmap.go @@ -1,6 +1,7 @@ package placement import ( + "context" "crypto/sha256" "fmt" @@ -35,12 +36,12 @@ func NewNetworkMapSourceBuilder(nmSrc netmap.Source) Builder { } } -func (s *netMapSrc) GetNetMap(_ uint64) (*netmapSDK.NetMap, error) { +func (s *netMapSrc) GetNetMap(_ context.Context, _ uint64) (*netmapSDK.NetMap, error) { return s.nm, nil } -func (b *netMapBuilder) BuildPlacement(cnr cid.ID, obj *oid.ID, p netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { - nm, err := netmap.GetLatestNetworkMap(b.nmSrc) +func (b *netMapBuilder) BuildPlacement(ctx context.Context, cnr cid.ID, obj *oid.ID, p netmapSDK.PlacementPolicy) ([][]netmapSDK.NodeInfo, error) { + nm, err := netmap.GetLatestNetworkMap(ctx, b.nmSrc) if err != nil { return nil, fmt.Errorf("could not get network map: %w", err) } diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index 8daf382174..efa4a5b06e 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -1,6 +1,7 @@ package placement import ( + "context" "errors" "fmt" "slices" @@ -21,7 +22,7 @@ type Builder interface { // // Must return all container nodes if object identifier // is nil. - BuildPlacement(cid.ID, *oid.ID, netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) + BuildPlacement(context.Context, cid.ID, *oid.ID, netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) } type NodeState interface { @@ -78,7 +79,7 @@ func defaultCfg() *cfg { } // NewTraverser creates, initializes with options and returns Traverser instance. -func NewTraverser(opts ...Option) (*Traverser, error) { +func NewTraverser(ctx context.Context, opts ...Option) (*Traverser, error) { cfg := defaultCfg() for i := range opts { @@ -98,7 +99,7 @@ func NewTraverser(opts ...Option) (*Traverser, error) { return nil, fmt.Errorf("%s: %w", invalidOptsMsg, errNilPolicy) } - ns, err := cfg.builder.BuildPlacement(cfg.cnr, cfg.obj, cfg.policy) + ns, err := cfg.builder.BuildPlacement(ctx, cfg.cnr, cfg.obj, cfg.policy) if err != nil { return nil, fmt.Errorf("could not build placement: %w", err) } diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index 624efb007a..9c825bf193 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -1,6 +1,7 @@ package placement import ( + "context" "slices" "strconv" "testing" @@ -18,7 +19,7 @@ type testBuilder struct { vectors [][]netmap.NodeInfo } -func (b testBuilder) BuildPlacement(cid.ID, *oid.ID, netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { +func (b testBuilder) BuildPlacement(context.Context, cid.ID, *oid.ID, netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { return b.vectors, nil } @@ -102,7 +103,7 @@ func TestTraverserObjectScenarios(t *testing.T) { nodesCopy := copyVectors(nodes) - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{vectors: nodesCopy}), WithoutSuccessTracking(), @@ -131,7 +132,7 @@ func TestTraverserObjectScenarios(t *testing.T) { nodesCopy := copyVectors(nodes) - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{ vectors: nodesCopy, @@ -160,7 +161,7 @@ func TestTraverserObjectScenarios(t *testing.T) { nodesCopy := copyVectors(nodes) - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{vectors: nodesCopy}), ) @@ -201,7 +202,7 @@ func TestTraverserObjectScenarios(t *testing.T) { nodes, cnr := testPlacement(selectors, replicas) - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{ vectors: [][]netmap.NodeInfo{{nodes[1][1]}}, // single node (local) @@ -276,7 +277,7 @@ func TestTraverserRemValues(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{vectors: nodesCopy}), WithCopyNumbers(testCase.copyNumbers), @@ -322,7 +323,7 @@ func TestTraverserPriorityMetrics(t *testing.T) { m := []Metric{NewAttributeMetric("ClusterName")} - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{ vectors: nodesCopy, @@ -374,7 +375,7 @@ func TestTraverserPriorityMetrics(t *testing.T) { m := []Metric{NewAttributeMetric("ClusterName")} - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{ vectors: nodesCopy, @@ -445,7 +446,7 @@ func TestTraverserPriorityMetrics(t *testing.T) { NewAttributeMetric("UN-LOCODE"), } - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{ vectors: nodesCopy, @@ -483,7 +484,7 @@ func TestTraverserPriorityMetrics(t *testing.T) { nodesCopy = copyVectors(nodes) - tr, err = NewTraverser( + tr, err = NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{ vectors: nodesCopy, @@ -516,7 +517,7 @@ func TestTraverserPriorityMetrics(t *testing.T) { nodesCopy = copyVectors(nodes) - tr, err = NewTraverser( + tr, err = NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{ vectors: nodesCopy, @@ -567,7 +568,7 @@ func TestTraverserPriorityMetrics(t *testing.T) { m := []Metric{NewAttributeMetric("ClusterName")} - tr, err := NewTraverser( + tr, err := NewTraverser(context.Background(), ForContainer(cnr), UseBuilder(&testBuilder{ vectors: nodesCopy, diff --git a/pkg/services/policer/check.go b/pkg/services/policer/check.go index 7df3724764..dcaaec0b44 100644 --- a/pkg/services/policer/check.go +++ b/pkg/services/policer/check.go @@ -28,10 +28,10 @@ func (p *Policer) processObject(ctx context.Context, objInfo objectcore.Info) er )) defer span.End() - cnr, err := p.cnrSrc.Get(objInfo.Address.Container()) + cnr, err := p.cnrSrc.Get(ctx, objInfo.Address.Container()) if err != nil { if client.IsErrContainerNotFound(err) { - existed, errWasRemoved := containercore.WasRemoved(p.cnrSrc, objInfo.Address.Container()) + existed, errWasRemoved := containercore.WasRemoved(ctx, p.cnrSrc, objInfo.Address.Container()) if errWasRemoved != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotConfirmContainerRemoval, errWasRemoved) } else if existed { @@ -56,7 +56,7 @@ func (p *Policer) processObject(ctx context.Context, objInfo objectcore.Info) er func (p *Policer) processRepContainerObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { idObj := objInfo.Address.Object() idCnr := objInfo.Address.Container() - nn, err := p.placementBuilder.BuildPlacement(idCnr, &idObj, policy) + nn, err := p.placementBuilder.BuildPlacement(ctx, idCnr, &idObj, policy) if err != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) } diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index f6d3b9ea14..1ee31d480b 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -39,7 +39,7 @@ func (p *Policer) processECContainerObject(ctx context.Context, objInfo objectco // All of them must be stored on all of the container nodes. func (p *Policer) processECContainerRepObject(ctx context.Context, objInfo objectcore.Info, policy netmap.PlacementPolicy) error { objID := objInfo.Address.Object() - nn, err := p.placementBuilder.BuildPlacement(objInfo.Address.Container(), &objID, policy) + nn, err := p.placementBuilder.BuildPlacement(ctx, objInfo.Address.Container(), &objID, policy) if err != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) } @@ -69,7 +69,7 @@ func (p *Policer) processECContainerRepObject(ctx context.Context, objInfo objec } func (p *Policer) processECContainerECObject(ctx context.Context, objInfo objectcore.Info, cnr containerSDK.Container) error { - nn, err := p.placementBuilder.BuildPlacement(objInfo.Address.Container(), &objInfo.ECInfo.ParentID, cnr.PlacementPolicy()) + nn, err := p.placementBuilder.BuildPlacement(ctx, objInfo.Address.Container(), &objInfo.ECInfo.ParentID, cnr.PlacementPolicy()) if err != nil { return fmt.Errorf("%s: %w", logs.PolicerCouldNotBuildPlacementVectorForObject, err) } diff --git a/pkg/services/policer/ec_test.go b/pkg/services/policer/ec_test.go index e230153f93..c6980536b7 100644 --- a/pkg/services/policer/ec_test.go +++ b/pkg/services/policer/ec_test.go @@ -36,7 +36,7 @@ func TestECChunkHasValidPlacement(t *testing.T) { cnr.Value.Init() cnr.Value.SetPlacementPolicy(policy) containerSrc := containerSrc{ - get: func(id cid.ID) (*container.Container, error) { + get: func(ctx context.Context, id cid.ID) (*container.Container, error) { if id.Equals(chunkAddress.Container()) { return cnr, nil } @@ -123,7 +123,7 @@ func TestECChunkHasInvalidPlacement(t *testing.T) { cnr.Value.Init() cnr.Value.SetPlacementPolicy(policy) containerSrc := containerSrc{ - get: func(id cid.ID) (*container.Container, error) { + get: func(ctx context.Context, id cid.ID) (*container.Container, error) { if id.Equals(chunkAddress.Container()) { return cnr, nil } @@ -448,7 +448,7 @@ func TestECChunkRestore(t *testing.T) { cnr.Value.Init() cnr.Value.SetPlacementPolicy(policy) containerSrc := containerSrc{ - get: func(id cid.ID) (*container.Container, error) { + get: func(ctx context.Context, id cid.ID) (*container.Container, error) { if id.Equals(parentAddress.Container()) { return cnr, nil } @@ -599,7 +599,7 @@ func TestECChunkRestoreNodeOff(t *testing.T) { cnr.Value.Init() cnr.Value.SetPlacementPolicy(policy) containerSrc := containerSrc{ - get: func(id cid.ID) (*container.Container, error) { + get: func(ctx context.Context, id cid.ID) (*container.Container, error) { if id.Equals(parentAddress.Container()) { return cnr, nil } diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index 9b9ab99ace..cef4c36d94 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -36,10 +36,10 @@ func TestBuryObjectWithoutContainer(t *testing.T) { // Container source and bury function buryCh := make(chan oid.Address) containerSrc := containerSrc{ - get: func(id cid.ID) (*container.Container, error) { + get: func(ctx context.Context, id cid.ID) (*container.Container, error) { return nil, new(apistatus.ContainerNotFound) }, - deletionInfo: func(id cid.ID) (*container.DelInfo, error) { + deletionInfo: func(ctx context.Context, id cid.ID) (*container.DelInfo, error) { return &container.DelInfo{}, nil }, } @@ -239,14 +239,14 @@ func TestProcessObject(t *testing.T) { cnr.Value.Init() cnr.Value.SetPlacementPolicy(policy) containerSrc := containerSrc{ - get: func(id cid.ID) (*container.Container, error) { + get: func(ctx context.Context, id cid.ID) (*container.Container, error) { if id.Equals(addr.Container()) { return cnr, nil } t.Errorf("unexpected container requested: got=%v, want=%v", id, addr.Container()) return nil, new(apistatus.ContainerNotFound) }, - deletionInfo: func(id cid.ID) (*container.DelInfo, error) { + deletionInfo: func(ctx context.Context, id cid.ID) (*container.DelInfo, error) { return &container.DelInfo{}, nil }, } @@ -304,10 +304,10 @@ func TestProcessObjectError(t *testing.T) { cnr := &container.Container{} cnr.Value.Init() source := containerSrc{ - get: func(id cid.ID) (*container.Container, error) { + get: func(ctx context.Context, id cid.ID) (*container.Container, error) { return nil, new(apistatus.ContainerNotFound) }, - deletionInfo: func(id cid.ID) (*container.DelInfo, error) { + deletionInfo: func(ctx context.Context, id cid.ID) (*container.DelInfo, error) { return nil, new(apistatus.ContainerNotFound) }, } @@ -352,10 +352,10 @@ func TestIteratorContract(t *testing.T) { } containerSrc := containerSrc{ - get: func(id cid.ID) (*container.Container, error) { + get: func(ctx context.Context, id cid.ID) (*container.Container, error) { return nil, new(apistatus.ContainerNotFound) }, - deletionInfo: func(id cid.ID) (*container.DelInfo, error) { + deletionInfo: func(ctx context.Context, id cid.ID) (*container.DelInfo, error) { return &container.DelInfo{}, nil }, } @@ -444,18 +444,22 @@ func (it *sliceKeySpaceIterator) Rewind() { } type containerSrc struct { - get func(id cid.ID) (*container.Container, error) - deletionInfo func(id cid.ID) (*container.DelInfo, error) + get func(ctx context.Context, id cid.ID) (*container.Container, error) + deletionInfo func(ctx context.Context, id cid.ID) (*container.DelInfo, error) } -func (f containerSrc) Get(id cid.ID) (*container.Container, error) { return f.get(id) } +func (f containerSrc) Get(ctx context.Context, id cid.ID) (*container.Container, error) { + return f.get(ctx, id) +} -func (f containerSrc) DeletionInfo(id cid.ID) (*container.DelInfo, error) { return f.deletionInfo(id) } +func (f containerSrc) DeletionInfo(ctx context.Context, id cid.ID) (*container.DelInfo, error) { + return f.deletionInfo(ctx, id) +} // placementBuilderFunc is a placement.Builder backed by a function type placementBuilderFunc func(cid.ID, *oid.ID, netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) -func (f placementBuilderFunc) BuildPlacement(c cid.ID, o *oid.ID, p netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { +func (f placementBuilderFunc) BuildPlacement(ctx context.Context, c cid.ID, o *oid.ID, p netmap.PlacementPolicy) ([][]netmap.NodeInfo, error) { return f(c, o, p) } diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 606044f8ed..c4b03cbe6b 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -36,7 +36,7 @@ func (s *Service) newAPERequest(ctx context.Context, namespace string, nativeschema.PropertyKeyActorPublicKey: hex.EncodeToString(publicKey.Bytes()), nativeschema.PropertyKeyActorRole: schemaRole, } - reqProps, err = s.fillWithUserClaimTags(reqProps, publicKey) + reqProps, err = s.fillWithUserClaimTags(ctx, reqProps, publicKey) if err != nil { return aperequest.Request{}, err } @@ -74,7 +74,7 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, return fmt.Errorf("failed to create ape request: %w", err) } - return s.apeChecker.CheckAPE(checkercore.CheckPrm{ + return s.apeChecker.CheckAPE(ctx, checkercore.CheckPrm{ Request: request, Namespace: namespace, Container: cid, @@ -85,11 +85,11 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, } // fillWithUserClaimTags fills ape request properties with user claim tags getting them from frostfsid contract by actor public key. -func (s *Service) fillWithUserClaimTags(reqProps map[string]string, publicKey *keys.PublicKey) (map[string]string, error) { +func (s *Service) fillWithUserClaimTags(ctx context.Context, reqProps map[string]string, publicKey *keys.PublicKey) (map[string]string, error) { if reqProps == nil { reqProps = make(map[string]string) } - props, err := aperequest.FormFrostfsIDRequestProperties(s.frostfsidSubjectProvider, publicKey) + props, err := aperequest.FormFrostfsIDRequestProperties(ctx, s.frostfsidSubjectProvider, publicKey) if err != nil { return reqProps, err } diff --git a/pkg/services/tree/ape_test.go b/pkg/services/tree/ape_test.go index 3f94925b57..0afc7660a5 100644 --- a/pkg/services/tree/ape_test.go +++ b/pkg/services/tree/ape_test.go @@ -37,7 +37,7 @@ type frostfsIDProviderMock struct { subjectsExtended map[util.Uint160]*client.SubjectExtended } -func (f *frostfsIDProviderMock) GetSubject(key util.Uint160) (*client.Subject, error) { +func (f *frostfsIDProviderMock) GetSubject(ctx context.Context, key util.Uint160) (*client.Subject, error) { v, ok := f.subjects[key] if !ok { return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) @@ -45,7 +45,7 @@ func (f *frostfsIDProviderMock) GetSubject(key util.Uint160) (*client.Subject, e return v, nil } -func (f *frostfsIDProviderMock) GetSubjectExtended(key util.Uint160) (*client.SubjectExtended, error) { +func (f *frostfsIDProviderMock) GetSubjectExtended(ctx context.Context, key util.Uint160) (*client.SubjectExtended, error) { v, ok := f.subjectsExtended[key] if !ok { return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) diff --git a/pkg/services/tree/container.go b/pkg/services/tree/container.go index 4352575500..c641a21a2c 100644 --- a/pkg/services/tree/container.go +++ b/pkg/services/tree/container.go @@ -2,6 +2,7 @@ package tree import ( "bytes" + "context" "crypto/sha256" "fmt" "sync" @@ -32,13 +33,13 @@ type containerCacheItem struct { const defaultContainerCacheSize = 10 // getContainerNodes returns nodes in the container and a position of local key in the list. -func (s *Service) getContainerNodes(cid cidSDK.ID) ([]netmapSDK.NodeInfo, int, error) { - nm, err := s.nmSource.GetNetMap(0) +func (s *Service) getContainerNodes(ctx context.Context, cid cidSDK.ID) ([]netmapSDK.NodeInfo, int, error) { + nm, err := s.nmSource.GetNetMap(ctx, 0) if err != nil { return nil, -1, fmt.Errorf("can't get netmap: %w", err) } - cnr, err := s.cnrSource.Get(cid) + cnr, err := s.cnrSource.Get(ctx, cid) if err != nil { return nil, -1, fmt.Errorf("can't get container: %w", err) } diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index a3f4880098..4ad760846f 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -1,6 +1,7 @@ package tree import ( + "context" "crypto/ecdsa" "time" @@ -18,12 +19,12 @@ import ( type ContainerSource interface { container.Source - DeletionInfo(cid.ID) (*container.DelInfo, error) + DeletionInfo(ctx context.Context, cid cid.ID) (*container.DelInfo, error) // List must return list of all the containers in the FrostFS network // at the moment of a call and any error that does not allow fetching // container information. - List() ([]cid.ID, error) + List(ctx context.Context) ([]cid.ID, error) } type cfg struct { diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index bcbb73589e..164815c760 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -149,7 +149,7 @@ func (s *Service) replicateLoop(ctx context.Context) { return case op := <-s.replicateCh: start := time.Now() - err := s.replicate(op) + err := s.replicate(ctx, op) if err != nil { s.log.Error(ctx, logs.TreeErrorDuringReplication, zap.Error(err), @@ -161,14 +161,14 @@ func (s *Service) replicateLoop(ctx context.Context) { } } -func (s *Service) replicate(op movePair) error { +func (s *Service) replicate(ctx context.Context, op movePair) error { req := newApplyRequest(&op) err := SignMessage(req, s.key) if err != nil { return fmt.Errorf("can't sign data: %w", err) } - nodes, localIndex, err := s.getContainerNodes(op.cid) + nodes, localIndex, err := s.getContainerNodes(ctx, op.cid) if err != nil { return fmt.Errorf("can't get container nodes: %w", err) } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 2df3c08e65..3c0214a98a 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -118,7 +118,7 @@ func (s *Service) Add(ctx context.Context, req *AddRequest) (*AddResponse, error return nil, err } - ns, pos, err := s.getContainerNodes(cid) + ns, pos, err := s.getContainerNodes(ctx, cid) if err != nil { return nil, err } @@ -161,7 +161,7 @@ func (s *Service) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByP return nil, err } - ns, pos, err := s.getContainerNodes(cid) + ns, pos, err := s.getContainerNodes(ctx, cid) if err != nil { return nil, err } @@ -216,7 +216,7 @@ func (s *Service) Remove(ctx context.Context, req *RemoveRequest) (*RemoveRespon return nil, err } - ns, pos, err := s.getContainerNodes(cid) + ns, pos, err := s.getContainerNodes(ctx, cid) if err != nil { return nil, err } @@ -260,7 +260,7 @@ func (s *Service) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, er return nil, err } - ns, pos, err := s.getContainerNodes(cid) + ns, pos, err := s.getContainerNodes(ctx, cid) if err != nil { return nil, err } @@ -303,7 +303,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) return nil, err } - ns, pos, err := s.getContainerNodes(cid) + ns, pos, err := s.getContainerNodes(ctx, cid) if err != nil { return nil, err } @@ -376,7 +376,7 @@ func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeS return err } - ns, pos, err := s.getContainerNodes(cid) + ns, pos, err := s.getContainerNodes(srv.Context(), cid) if err != nil { return err } @@ -586,7 +586,7 @@ func sortByFilename(nodes []pilorama.NodeInfo, d GetSubTreeRequest_Body_Order_Di } // Apply locally applies operation from the remote node to the tree. -func (s *Service) Apply(_ context.Context, req *ApplyRequest) (*ApplyResponse, error) { +func (s *Service) Apply(ctx context.Context, req *ApplyRequest) (*ApplyResponse, error) { err := verifyMessage(req) if err != nil { return nil, err @@ -599,7 +599,7 @@ func (s *Service) Apply(_ context.Context, req *ApplyRequest) (*ApplyResponse, e key := req.GetSignature().GetKey() - _, pos, _, err := s.getContainerInfo(cid, key) + _, pos, _, err := s.getContainerInfo(ctx, cid, key) if err != nil { return nil, err } @@ -641,7 +641,7 @@ func (s *Service) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) return err } - ns, pos, err := s.getContainerNodes(cid) + ns, pos, err := s.getContainerNodes(srv.Context(), cid) if err != nil { return err } @@ -713,7 +713,7 @@ func (s *Service) TreeList(ctx context.Context, req *TreeListRequest) (*TreeList return nil, err } - ns, pos, err := s.getContainerNodes(cid) + ns, pos, err := s.getContainerNodes(ctx, cid) if err != nil { return nil, err } @@ -755,8 +755,8 @@ func metaToProto(arr []pilorama.KeyValue) []KeyValue { // getContainerInfo returns the list of container nodes, position in the container for the node // with pub key and total amount of nodes in all replicas. -func (s *Service) getContainerInfo(cid cidSDK.ID, pub []byte) ([]netmapSDK.NodeInfo, int, int, error) { - cntNodes, _, err := s.getContainerNodes(cid) +func (s *Service) getContainerInfo(ctx context.Context, cid cidSDK.ID, pub []byte) ([]netmapSDK.NodeInfo, int, int, error) { + cntNodes, _, err := s.getContainerNodes(ctx, cid) if err != nil { return nil, 0, 0, err } diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index b0f00615ae..d15438e81b 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -49,7 +49,7 @@ func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, return err } - cnr, err := s.cnrSource.Get(cid) + cnr, err := s.cnrSource.Get(ctx, cid) if err != nil { return fmt.Errorf("can't get container %s: %w", cid, err) } diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 7bc5002dc8..97f8a727a6 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -39,7 +39,7 @@ type dummySubjectProvider struct { subjects map[util.Uint160]client.SubjectExtended } -func (s dummySubjectProvider) GetSubject(addr util.Uint160) (*client.Subject, error) { +func (s dummySubjectProvider) GetSubject(ctx context.Context, addr util.Uint160) (*client.Subject, error) { res := s.subjects[addr] return &client.Subject{ PrimaryKey: res.PrimaryKey, @@ -50,7 +50,7 @@ func (s dummySubjectProvider) GetSubject(addr util.Uint160) (*client.Subject, er }, nil } -func (s dummySubjectProvider) GetSubjectExtended(addr util.Uint160) (*client.SubjectExtended, error) { +func (s dummySubjectProvider) GetSubjectExtended(ctx context.Context, addr util.Uint160) (*client.SubjectExtended, error) { res := s.subjects[addr] return &res, nil } @@ -65,7 +65,7 @@ func (s dummyEpochSource) CurrentEpoch() uint64 { type dummyContainerSource map[string]*containercore.Container -func (s dummyContainerSource) List() ([]cid.ID, error) { +func (s dummyContainerSource) List(context.Context) ([]cid.ID, error) { res := make([]cid.ID, 0, len(s)) var cnr cid.ID @@ -81,7 +81,7 @@ func (s dummyContainerSource) List() ([]cid.ID, error) { return res, nil } -func (s dummyContainerSource) Get(id cid.ID) (*containercore.Container, error) { +func (s dummyContainerSource) Get(ctx context.Context, id cid.ID) (*containercore.Container, error) { cnt, ok := s[id.String()] if !ok { return nil, errors.New("container not found") @@ -89,7 +89,7 @@ func (s dummyContainerSource) Get(id cid.ID) (*containercore.Container, error) { return cnt, nil } -func (s dummyContainerSource) DeletionInfo(id cid.ID) (*containercore.DelInfo, error) { +func (s dummyContainerSource) DeletionInfo(ctx context.Context, id cid.ID) (*containercore.DelInfo, error) { return &containercore.DelInfo{}, nil } diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 1a455def97..9b177d6b6e 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -39,7 +39,7 @@ const defaultSyncWorkerCount = 20 // tree IDs from the other container nodes. Returns ErrNotInContainer if the node // is not included in the container. func (s *Service) synchronizeAllTrees(ctx context.Context, cid cid.ID) error { - nodes, pos, err := s.getContainerNodes(cid) + nodes, pos, err := s.getContainerNodes(ctx, cid) if err != nil { return fmt.Errorf("can't get container nodes: %w", err) } @@ -112,7 +112,7 @@ func (s *Service) synchronizeAllTrees(ctx context.Context, cid cid.ID) error { // SynchronizeTree tries to synchronize log starting from the last stored height. func (s *Service) SynchronizeTree(ctx context.Context, cid cid.ID, treeID string) error { - nodes, pos, err := s.getContainerNodes(cid) + nodes, pos, err := s.getContainerNodes(ctx, cid) if err != nil { return fmt.Errorf("can't get container nodes: %w", err) } @@ -393,7 +393,7 @@ func (s *Service) syncLoop(ctx context.Context) { start := time.Now() - cnrs, err := s.cfg.cnrSource.List() + cnrs, err := s.cfg.cnrSource.List(ctx) if err != nil { s.log.Error(ctx, logs.TreeCouldNotFetchContainers, zap.Error(err)) s.metrics.AddSyncDuration(time.Since(start), false) @@ -463,7 +463,7 @@ func (s *Service) removeContainers(ctx context.Context, newContainers map[cid.ID continue } - existed, err := containerCore.WasRemoved(s.cnrSource, cnr) + existed, err := containerCore.WasRemoved(ctx, s.cnrSource, cnr) if err != nil { s.log.Error(ctx, logs.TreeCouldNotCheckIfContainerExisted, zap.Stringer("cid", cnr), @@ -493,7 +493,7 @@ func (s *Service) containersToSync(ctx context.Context, cnrs []cid.ID) (map[cid. cnrsToSync := make([]cid.ID, 0, len(cnrs)) for _, cnr := range cnrs { - _, pos, err := s.getContainerNodes(cnr) + _, pos, err := s.getContainerNodes(ctx, cnr) if err != nil { s.log.Error(ctx, logs.TreeCouldNotCalculateContainerNodes, zap.Stringer("cid", cnr), From 69c35b1d61fad2d08edf008f709f19ad45fdf250 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 6 Feb 2025 21:19:24 +0300 Subject: [PATCH 1174/1413] [#1637] govulncheck: Use patch release with security fixes Signed-off-by: Alexander Chuprov --- .forgejo/workflows/vulncheck.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index 8a5a818aa0..7c89a35555 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.23.5' + go-version: '1.23.6' - name: Install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest From 155f9eecb0159ac98ea85de0fefe04bbe24148c7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 21 Jan 2025 14:15:59 +0300 Subject: [PATCH 1175/1413] [#1608] config: Add QoS section and config Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 + cmd/frostfs-node/config/qos/config.go | 46 ++++++++++++++++++++++ cmd/frostfs-node/config/qos/config_test.go | 40 +++++++++++++++++++ cmd/frostfs-node/qos.go | 20 ++++++++++ config/example/node.env | 3 ++ config/example/node.json | 14 +++++++ config/example/node.yaml | 10 +++++ docs/storage-node-configuration.md | 20 +++++++++- 8 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 cmd/frostfs-node/config/qos/config.go create mode 100644 cmd/frostfs-node/config/qos/config_test.go create mode 100644 cmd/frostfs-node/qos.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 75d6f6dec0..5117775666 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -493,6 +493,7 @@ type cfg struct { cfgNetmap cfgNetmap cfgControlService cfgControlService cfgObject cfgObject + cfgQoSService cfgQoSService } // ReadCurrentNetMap reads network map which has been cached at the diff --git a/cmd/frostfs-node/config/qos/config.go b/cmd/frostfs-node/config/qos/config.go new file mode 100644 index 0000000000..85f8180ed7 --- /dev/null +++ b/cmd/frostfs-node/config/qos/config.go @@ -0,0 +1,46 @@ +package qos + +import ( + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +const ( + subsection = "qos" + criticalSubSection = "critical" + internalSubSection = "internal" +) + +// CriticalAuthorizedKeys parses and returns an array of "critical.authorized_keys" config +// parameter from "qos" section. +// +// Returns an empty list if not set. +func CriticalAuthorizedKeys(c *config.Config) keys.PublicKeys { + return authorizedKeys(c, criticalSubSection) +} + +// InternalAuthorizedKeys parses and returns an array of "internal.authorized_keys" config +// parameter from "qos" section. +// +// Returns an empty list if not set. +func InternalAuthorizedKeys(c *config.Config) keys.PublicKeys { + return authorizedKeys(c, internalSubSection) +} + +func authorizedKeys(c *config.Config, sub string) keys.PublicKeys { + strKeys := config.StringSliceSafe(c.Sub(subsection).Sub(sub), "authorized_keys") + pubs := make(keys.PublicKeys, 0, len(strKeys)) + + for i := range strKeys { + pub, err := keys.NewPublicKeyFromString(strKeys[i]) + if err != nil { + panic(fmt.Errorf("invalid authorized key %s for qos.%s: %w", strKeys[i], sub, err)) + } + + pubs = append(pubs, pub) + } + + return pubs +} diff --git a/cmd/frostfs-node/config/qos/config_test.go b/cmd/frostfs-node/config/qos/config_test.go new file mode 100644 index 0000000000..b3b6019ccd --- /dev/null +++ b/cmd/frostfs-node/config/qos/config_test.go @@ -0,0 +1,40 @@ +package qos + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestQoSSection(t *testing.T) { + t.Run("defaults", func(t *testing.T) { + empty := configtest.EmptyConfig() + + require.Empty(t, CriticalAuthorizedKeys(empty)) + require.Empty(t, InternalAuthorizedKeys(empty)) + }) + + const path = "../../../../config/example/node" + + criticalPubs := make(keys.PublicKeys, 2) + criticalPubs[0], _ = keys.NewPublicKeyFromString("035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11") + criticalPubs[1], _ = keys.NewPublicKeyFromString("028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6") + + internalPubs := make(keys.PublicKeys, 2) + internalPubs[0], _ = keys.NewPublicKeyFromString("02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2") + internalPubs[1], _ = keys.NewPublicKeyFromString("031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a") + + fileConfigTest := func(c *config.Config) { + require.Equal(t, criticalPubs, CriticalAuthorizedKeys(c)) + require.Equal(t, internalPubs, InternalAuthorizedKeys(c)) + } + + configtest.ForEachFileType(path, fileConfigTest) + + t.Run("ENV", func(t *testing.T) { + configtest.ForEnvFileType(t, path, fileConfigTest) + }) +} diff --git a/cmd/frostfs-node/qos.go b/cmd/frostfs-node/qos.go new file mode 100644 index 0000000000..20ef432309 --- /dev/null +++ b/cmd/frostfs-node/qos.go @@ -0,0 +1,20 @@ +package main + +import qosconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/qos" + +type cfgQoSService struct{} + +func initQoSService(c *cfg) { + criticalPubs := qosconfig.CriticalAuthorizedKeys(c.appCfg) + internalPubs := qosconfig.InternalAuthorizedKeys(c.appCfg) + rawCriticalPubs := make([][]byte, 0, len(criticalPubs)) + rawInternalPubs := make([][]byte, 0, len(internalPubs)) + for i := range criticalPubs { + rawCriticalPubs = append(rawCriticalPubs, criticalPubs[i].Bytes()) + } + for i := range internalPubs { + rawInternalPubs = append(rawInternalPubs, internalPubs[i].Bytes()) + } + + c.cfgQoSService = cfgQoSService{} +} diff --git a/config/example/node.env b/config/example/node.env index b2a0633a98..2ba432b1b2 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -225,3 +225,6 @@ FROSTFS_MULTINET_SUBNETS_1_SOURCE_IPS="10.78.70.185 10.78.71.185" FROSTFS_MULTINET_BALANCER=roundrobin FROSTFS_MULTINET_RESTRICT=false FROSTFS_MULTINET_FALLBACK_DELAY=350ms + +FROSTFS_QOS_CRITICAL_AUTHORIZED_KEYS="035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6" +FROSTFS_QOS_INTERNAL_AUTHORIZED_KEYS="02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a" diff --git a/config/example/node.json b/config/example/node.json index f3192ac2f0..cfde8bcc75 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -305,5 +305,19 @@ "balancer": "roundrobin", "restrict": false, "fallback_delay": "350ms" + }, + "qos": { + "critical": { + "authorized_keys": [ + "035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11", + "028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6" + ] + }, + "internal": { + "authorized_keys": [ + "02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2", + "031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a" + ] + } } } diff --git a/config/example/node.yaml b/config/example/node.yaml index c5acf53860..1f8ec843df 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -270,3 +270,13 @@ multinet: balancer: roundrobin restrict: false fallback_delay: 350ms + +qos: + critical: + authorized_keys: # list of hex-encoded public keys that have rights to use `critical` IO tag + - 035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11 + - 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6 + internal: + authorized_keys: # list of hex-encoded public keys that have rights to use `internal` IO tag + - 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2 + - 031a6c6fbbdf02ca351745fa86b9ba5a9452d785ac4f7fc2b7548ca2a46c4fcf4a diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 98d72cb692..de2729c68e 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -26,7 +26,8 @@ There are some custom types used for brevity: | `storage` | [Storage engine configuration](#storage-section) | | `runtime` | [Runtime configuration](#runtime-section) | | `audit` | [Audit configuration](#audit-section) | -| `multinet` | [Multinet configuration](#multinet-section) | +| `multinet` | [Multinet configuration](#multinet-section) | +| `qos` | [QoS configuration](#qos-section) | # `control` section ```yaml @@ -471,3 +472,20 @@ multinet: | `balancer` | `string` | "" | Balancer to select network interfaces, allowed values are "" (no balancing, use first suitable interface) or "roundrobin". | | `restrict` | `bool` | false | If `true` then any requests that do not match `subnets` will fail. | | `fallback_delay` | `duration` | 350ms | Delay before fallback to secondary IP addresses in case of hostname resolve. | + +# `qos` section +```yaml +qos: + critical: + authorized_keys: + - 035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11 + - 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6 + internal: + authorized_keys: + - 035839e45d472a3b7769a2a1bd7d54c4ccd4943c3b40f547870e83a8fcbfb3ce11 + - 028f42cfcb74499d7b15b35d9bff260a1c8d27de4f446a627406a382d8961486d6 +``` +| Parameter | Type | Default value | Description | +| -------------------------- | -------------- | ------------- | --------------------------------------------------------------------------- | +| `critical.authorized_keys` | `[]public key` | empty | List of public keys for which requests with the tag `critical` are allowed. | +| `internal.authorized_keys` | `[]public key` | empty | List of public keys for which requests with the tag `internal` are allowed. | From 9729f31e5c96028a434a175cb4c2ce51b74875a9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 11:26:09 +0300 Subject: [PATCH 1176/1413] [#1608] grpc: Add QoS interceptors for server and clients Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/internal/client/sdk.go | 5 +++-- cmd/frostfs-cli/modules/tree/client.go | 3 +++ cmd/frostfs-node/grpc.go | 3 +++ go.mod | 1 + go.sum | 2 ++ pkg/network/cache/multi.go | 3 +++ pkg/services/tree/cache.go | 3 +++ pkg/services/tree/sync.go | 3 +++ 8 files changed, 21 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/sdk.go b/cmd/frostfs-cli/internal/client/sdk.go index 2d9c45cbd9..71c35bd2cb 100644 --- a/cmd/frostfs-cli/internal/client/sdk.go +++ b/cmd/frostfs-cli/internal/client/sdk.go @@ -13,6 +13,7 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -56,8 +57,8 @@ func GetSDKClient(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey prmDial := client.PrmDial{ Endpoint: addr.URIAddr(), GRPCDialOptions: []grpc.DialOption{ - grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor()), - grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor()), + grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor(), qos.NewUnaryClientInteceptor()), + grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor(), qos.NewStreamClientInterceptor()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), }, } diff --git a/cmd/frostfs-cli/modules/tree/client.go b/cmd/frostfs-cli/modules/tree/client.go index a70624ac8d..421f115325 100644 --- a/cmd/frostfs-cli/modules/tree/client.go +++ b/cmd/frostfs-cli/modules/tree/client.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "github.com/spf13/cobra" "github.com/spf13/viper" "google.golang.org/grpc" @@ -36,10 +37,12 @@ func _client() (tree.TreeServiceClient, error) { grpc.WithChainUnaryInterceptor( metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInteceptor(), + qos.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( metrics.NewStreamClientInterceptor(), tracing.NewStreamClientInterceptor(), + qos.NewStreamClientInterceptor(), ), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), } diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index 6105be8611..4d679e4cc5 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -12,6 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -130,10 +131,12 @@ func getGrpcServerOpts(ctx context.Context, c *cfg, sc *grpcconfig.Config) ([]gr serverOpts := []grpc.ServerOption{ grpc.MaxRecvMsgSize(maxRecvMsgSize), grpc.ChainUnaryInterceptor( + qos.NewUnaryServerInterceptor(), metrics.NewUnaryServerInterceptor(), tracing.NewUnaryServerInterceptor(), ), grpc.ChainStreamInterceptor( + qos.NewStreamServerInterceptor(), metrics.NewStreamServerInterceptor(), tracing.NewStreamServerInterceptor(), ), diff --git a/go.mod b/go.mod index cc6b0a2028..8f2e7bc51d 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 + git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 diff --git a/go.sum b/go.sum index eae467b310..e92b648860 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe h1:81gDNdWNLP24oMQukRiCE9R1wGSh0l0dRq3F1W+Oesc= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421 h1:pP19IawSdsLCKFv7HMNfWAeH6E3uSnntKZkwka+/2+4= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 1bcb832590..5c3beb553c 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -64,10 +65,12 @@ func (x *multiClient) createForAddress(ctx context.Context, addr network.Address grpc.WithChainUnaryInterceptor( metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInteceptor(), + qos.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( metrics.NewStreamClientInterceptor(), tracing.NewStreamClientInterceptor(), + qos.NewStreamClientInterceptor(), ), grpc.WithContextDialer(x.opts.DialerSource.GrpcContextDialer()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index ac80d0e4c4..7f1dcf07cf 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -12,6 +12,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "github.com/hashicorp/golang-lru/v2/simplelru" "google.golang.org/grpc" "google.golang.org/grpc/connectivity" @@ -97,10 +98,12 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* grpc.WithChainUnaryInterceptor( metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInteceptor(), + qos.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( metrics.NewStreamClientInterceptor(), tracing.NewStreamClientInterceptor(), + qos.NewStreamClientInterceptor(), ), grpc.WithContextDialer(c.ds.GrpcContextDialer()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 9b177d6b6e..a0485d9d89 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -20,6 +20,7 @@ import ( metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" tracing_grpc "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/panjf2000/ants/v2" @@ -342,10 +343,12 @@ func (*Service) createConnection(a network.Address) (*grpc.ClientConn, error) { grpc.WithChainUnaryInterceptor( metrics.NewUnaryClientInterceptor(), tracing_grpc.NewUnaryClientInteceptor(), + qos.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( metrics.NewStreamClientInterceptor(), tracing_grpc.NewStreamClientInterceptor(), + qos.NewStreamClientInterceptor(), ), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), From f6b3f79e8916f826f55bb28aff799699d1465be0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 11:28:52 +0300 Subject: [PATCH 1177/1413] [#1608] qos: Add qos service to adjust incoming IO tags Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/main.go | 1 + cmd/frostfs-node/qos.go | 81 ++++++++++++++++++- internal/logs/logs.go | 3 + .../metabase/upgrade_test.go | 2 +- 4 files changed, 83 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index 3c15dc4396..b53bd88232 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -101,6 +101,7 @@ func initApp(ctx context.Context, c *cfg) { initAndLog(ctx, c, "gRPC", func(c *cfg) { initGRPC(ctx, c) }) initAndLog(ctx, c, "netmap", func(c *cfg) { initNetmapService(ctx, c) }) + initAndLog(ctx, c, "qos", func(c *cfg) { initQoSService(c) }) initAccessPolicyEngine(ctx, c) initAndLog(ctx, c, "access policy engine", func(c *cfg) { diff --git a/cmd/frostfs-node/qos.go b/cmd/frostfs-node/qos.go index 20ef432309..bfc2783331 100644 --- a/cmd/frostfs-node/qos.go +++ b/cmd/frostfs-node/qos.go @@ -1,8 +1,24 @@ package main -import qosconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/qos" +import ( + "bytes" + "context" -type cfgQoSService struct{} + qosconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/qos" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + qosTagging "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + "go.uber.org/zap" +) + +type cfgQoSService struct { + netmapSource netmap.Source + logger *logger.Logger + allowedCriticalPubs [][]byte + allowedInternalPubs [][]byte +} func initQoSService(c *cfg) { criticalPubs := qosconfig.CriticalAuthorizedKeys(c.appCfg) @@ -16,5 +32,64 @@ func initQoSService(c *cfg) { rawInternalPubs = append(rawInternalPubs, internalPubs[i].Bytes()) } - c.cfgQoSService = cfgQoSService{} + c.cfgQoSService = cfgQoSService{ + netmapSource: c.netMapSource, + logger: c.log, + allowedCriticalPubs: rawCriticalPubs, + allowedInternalPubs: rawInternalPubs, + } +} + +func (s *cfgQoSService) AdjustIncomingTag(ctx context.Context, requestSignPublicKey []byte) context.Context { + rawTag, defined := qosTagging.IOTagFromContext(ctx) + if !defined { + return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) + } + ioTag, err := qos.FromRawString(rawTag) + if err != nil { + s.logger.Warn(ctx, logs.FailedToParseIncomingIOTag, zap.Error(err)) + return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) + } + + switch ioTag { + case qos.IOTagClient: + return ctx + case qos.IOTagCritical: + for _, pk := range s.allowedCriticalPubs { + if bytes.Equal(pk, requestSignPublicKey) { + return ctx + } + } + nm, err := s.netmapSource.GetNetMap(ctx, 0) + if err != nil { + s.logger.Debug(ctx, logs.FailedToGetNetmapToAdjustIOTag, zap.Error(err)) + return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) + } + for _, node := range nm.Nodes() { + if bytes.Equal(node.PublicKey(), requestSignPublicKey) { + return ctx + } + } + return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) + case qos.IOTagInternal: + for _, pk := range s.allowedInternalPubs { + if bytes.Equal(pk, requestSignPublicKey) { + return ctx + } + } + nm, err := s.netmapSource.GetNetMap(ctx, 0) + if err != nil { + s.logger.Debug(ctx, logs.FailedToGetNetmapToAdjustIOTag, zap.Error(err)) + return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) + } + for _, node := range nm.Nodes() { + if bytes.Equal(node.PublicKey(), requestSignPublicKey) { + return ctx + } + } + return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) + default: + s.logger.Warn(ctx, logs.NotSupportedIncomingIOTagReplacedWithClient, zap.Stringer("io_tag", ioTag)) + return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) + } } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 0610dc1751..6a72644e5d 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -510,4 +510,7 @@ const ( BlobovniczatreeFailedToRemoveRebuildTempFile = "failed to remove rebuild temp file" WritecacheCantGetObject = "can't get an object from fstree" FailedToUpdateMultinetConfiguration = "failed to update multinet configuration" + FailedToParseIncomingIOTag = "failed to parse incoming IO tag" + NotSupportedIncomingIOTagReplacedWithClient = "incoming IO tag is not supported, replaced with `client`" + FailedToGetNetmapToAdjustIOTag = "failed to get netmap to adjust IO tag, replaced with `client`" ) diff --git a/pkg/local_object_storage/metabase/upgrade_test.go b/pkg/local_object_storage/metabase/upgrade_test.go index 5444264be4..c90de4dd6e 100644 --- a/pkg/local_object_storage/metabase/upgrade_test.go +++ b/pkg/local_object_storage/metabase/upgrade_test.go @@ -45,7 +45,7 @@ func TestUpgradeV2ToV3(t *testing.T) { type testContainerInfoProvider struct{} -func (p *testContainerInfoProvider) Info(id cid.ID) (container.Info, error) { +func (p *testContainerInfoProvider) Info(ctx context.Context, id cid.ID) (container.Info, error) { return container.Info{}, nil } From 12da2f826278762e8879994c2788e88b9084afe4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 11:29:22 +0300 Subject: [PATCH 1178/1413] [#1608] object: Add IO tag adjustment layer Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/object.go | 5 +- internal/qos/tags.go | 39 +++++++++++ pkg/services/object/qos.go | 132 +++++++++++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 internal/qos/tags.go create mode 100644 pkg/services/object/qos.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 77446b81ce..40d3cc1cdc 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -168,7 +168,7 @@ func initObjectService(c *cfg) { sPatch := createPatchSvc(sGet, sPut) // build service pipeline - // grpc | audit | | signature | response | acl | ape | split + // grpc | audit | qos | | signature | response | acl | ape | split splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2, sPatch) @@ -191,7 +191,8 @@ func initObjectService(c *cfg) { c.shared.metricsSvc = objectService.NewMetricCollector( signSvc, c.metricsCollector.ObjectService(), metricsconfig.Enabled(c.appCfg)) - auditSvc := objectService.NewAuditService(c.shared.metricsSvc, c.log, c.audit) + qosService := objectService.NewQoSObjectService(c.shared.metricsSvc, &c.cfgQoSService) + auditSvc := objectService.NewAuditService(qosService, c.log, c.audit) server := objectTransportGRPC.New(auditSvc) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { diff --git a/internal/qos/tags.go b/internal/qos/tags.go new file mode 100644 index 0000000000..6a9a7f7a41 --- /dev/null +++ b/internal/qos/tags.go @@ -0,0 +1,39 @@ +package qos + +import "fmt" + +type IOTag string + +const ( + IOTagClient IOTag = "client" + IOTagInternal IOTag = "internal" + IOTagBackground IOTag = "background" + IOTagWritecache IOTag = "writecache" + IOTagPolicer IOTag = "policer" + IOTagCritical IOTag = "critical" + + ioTagUnknown IOTag = "" +) + +func FromRawString(s string) (IOTag, error) { + switch s { + case string(IOTagCritical): + return IOTagCritical, nil + case string(IOTagClient): + return IOTagClient, nil + case string(IOTagInternal): + return IOTagInternal, nil + case string(IOTagBackground): + return IOTagBackground, nil + case string(IOTagWritecache): + return IOTagWritecache, nil + case string(IOTagPolicer): + return IOTagPolicer, nil + default: + return ioTagUnknown, fmt.Errorf("unknown tag %s", s) + } +} + +func (t IOTag) String() string { + return string(t) +} diff --git a/pkg/services/object/qos.go b/pkg/services/object/qos.go new file mode 100644 index 0000000000..145a316e24 --- /dev/null +++ b/pkg/services/object/qos.go @@ -0,0 +1,132 @@ +package object + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" +) + +var _ ServiceServer = (*qosObjectService)(nil) + +type AdjustIOTag interface { + AdjustIncomingTag(ctx context.Context, requestSignPublicKey []byte) context.Context +} + +type qosObjectService struct { + next ServiceServer + adj AdjustIOTag +} + +func NewQoSObjectService(next ServiceServer, adjIOTag AdjustIOTag) ServiceServer { + return &qosObjectService{ + next: next, + adj: adjIOTag, + } +} + +func (q *qosObjectService) Delete(ctx context.Context, req *object.DeleteRequest) (*object.DeleteResponse, error) { + ctx = q.adj.AdjustIncomingTag(ctx, req.GetVerificationHeader().GetBodySignature().GetKey()) + return q.next.Delete(ctx, req) +} + +func (q *qosObjectService) Get(req *object.GetRequest, s GetObjectStream) error { + ctx := q.adj.AdjustIncomingTag(s.Context(), req.GetVerificationHeader().GetBodySignature().GetKey()) + return q.next.Get(req, &qosReadStream[*object.GetResponse]{ + ctxF: func() context.Context { return ctx }, + sender: s, + }) +} + +func (q *qosObjectService) GetRange(req *object.GetRangeRequest, s GetObjectRangeStream) error { + ctx := q.adj.AdjustIncomingTag(s.Context(), req.GetVerificationHeader().GetBodySignature().GetKey()) + return q.next.GetRange(req, &qosReadStream[*object.GetRangeResponse]{ + ctxF: func() context.Context { return ctx }, + sender: s, + }) +} + +func (q *qosObjectService) GetRangeHash(ctx context.Context, req *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) { + ctx = q.adj.AdjustIncomingTag(ctx, req.GetVerificationHeader().GetBodySignature().GetKey()) + return q.next.GetRangeHash(ctx, req) +} + +func (q *qosObjectService) Head(ctx context.Context, req *object.HeadRequest) (*object.HeadResponse, error) { + ctx = q.adj.AdjustIncomingTag(ctx, req.GetVerificationHeader().GetBodySignature().GetKey()) + return q.next.Head(ctx, req) +} + +func (q *qosObjectService) Patch(ctx context.Context) (PatchObjectStream, error) { + s, err := q.next.Patch(ctx) + if err != nil { + return nil, err + } + return &qosWriteStream[*object.PatchRequest, *object.PatchResponse]{ + s: s, + adj: q.adj, + }, nil +} + +func (q *qosObjectService) Put(ctx context.Context) (PutObjectStream, error) { + s, err := q.next.Put(ctx) + if err != nil { + return nil, err + } + return &qosWriteStream[*object.PutRequest, *object.PutResponse]{ + s: s, + adj: q.adj, + }, nil +} + +func (q *qosObjectService) PutSingle(ctx context.Context, req *object.PutSingleRequest) (*object.PutSingleResponse, error) { + ctx = q.adj.AdjustIncomingTag(ctx, req.GetVerificationHeader().GetBodySignature().GetKey()) + return q.next.PutSingle(ctx, req) +} + +func (q *qosObjectService) Search(req *object.SearchRequest, s SearchStream) error { + ctx := q.adj.AdjustIncomingTag(s.Context(), req.GetVerificationHeader().GetBodySignature().GetKey()) + return q.next.Search(req, &qosReadStream[*object.SearchResponse]{ + ctxF: func() context.Context { return ctx }, + sender: s, + }) +} + +type qosSend[T any] interface { + Send(T) error +} + +type qosReadStream[T any] struct { + sender qosSend[T] + ctxF func() context.Context +} + +func (g *qosReadStream[T]) Context() context.Context { + return g.ctxF() +} + +func (g *qosReadStream[T]) Send(resp T) error { + return g.sender.Send(resp) +} + +type qosVerificationHeader interface { + GetVerificationHeader() *session.RequestVerificationHeader +} + +type qosSendRecv[TReq qosVerificationHeader, TResp any] interface { + Send(context.Context, TReq) error + CloseAndRecv(context.Context) (TResp, error) +} + +type qosWriteStream[TReq qosVerificationHeader, TResp any] struct { + s qosSendRecv[TReq, TResp] + adj AdjustIOTag +} + +func (q *qosWriteStream[TReq, TResp]) CloseAndRecv(ctx context.Context) (TResp, error) { + return q.s.CloseAndRecv(ctx) +} + +func (q *qosWriteStream[TReq, TResp]) Send(ctx context.Context, req TReq) error { + ctx = q.adj.AdjustIncomingTag(ctx, req.GetVerificationHeader().GetBodySignature().GetKey()) + return q.s.Send(ctx, req) +} From 170860c14a7778ff141a136899e52ba20ee6607b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 11:44:20 +0300 Subject: [PATCH 1179/1413] [#1608] logger: Add IO tag logging Signed-off-by: Dmitrii Stepanov --- pkg/util/logger/log.go | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/pkg/util/logger/log.go b/pkg/util/logger/log.go index 269e07d906..413b1d9aaf 100644 --- a/pkg/util/logger/log.go +++ b/pkg/util/logger/log.go @@ -4,37 +4,32 @@ import ( "context" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/tracing" + qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "go.uber.org/zap" ) func (l *Logger) Debug(ctx context.Context, msg string, fields ...zap.Field) { - if traceID := tracing.GetTraceID(ctx); traceID != "" { - l.z.Debug(msg, append(fields, zap.String("trace_id", traceID))...) - return - } - l.z.Debug(msg, fields...) + l.z.Debug(msg, appendContext(ctx, fields...)...) } func (l *Logger) Info(ctx context.Context, msg string, fields ...zap.Field) { - if traceID := tracing.GetTraceID(ctx); traceID != "" { - l.z.Info(msg, append(fields, zap.String("trace_id", traceID))...) - return - } - l.z.Info(msg, fields...) + l.z.Info(msg, appendContext(ctx, fields...)...) } func (l *Logger) Warn(ctx context.Context, msg string, fields ...zap.Field) { - if traceID := tracing.GetTraceID(ctx); traceID != "" { - l.z.Warn(msg, append(fields, zap.String("trace_id", traceID))...) - return - } - l.z.Warn(msg, fields...) + l.z.Warn(msg, appendContext(ctx, fields...)...) } func (l *Logger) Error(ctx context.Context, msg string, fields ...zap.Field) { - if traceID := tracing.GetTraceID(ctx); traceID != "" { - l.z.Error(msg, append(fields, zap.String("trace_id", traceID))...) - return - } - l.z.Error(msg, fields...) + l.z.Error(msg, appendContext(ctx, fields...)...) +} + +func appendContext(ctx context.Context, fields ...zap.Field) []zap.Field { + if traceID := tracing.GetTraceID(ctx); traceID != "" { + fields = append(fields, zap.String("trace_id", traceID)) + } + if ioTag, ioTagDefined := qos.IOTagFromContext(ctx); ioTagDefined { + fields = append(fields, zap.String("io_tag", ioTag)) + } + return fields } From dc6aea7b7956bfca222288fa057eecdaca35ca4d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 15:56:31 +0300 Subject: [PATCH 1180/1413] [#1608] control: Use IO tag `critical` Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/control.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index ecd82bba51..1d9ac3df0d 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -7,9 +7,13 @@ import ( controlconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/control" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" controlSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" + metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" + tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "go.uber.org/zap" "google.golang.org/grpc" ) @@ -50,7 +54,17 @@ func initControlService(ctx context.Context, c *cfg) { return } - c.cfgControlService.server = grpc.NewServer() + c.cfgControlService.server = grpc.NewServer( + grpc.ChainUnaryInterceptor( + func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { + ctx = tagging.ContextWithIOTag(ctx, qos.IOTagCritical.String()) + return handler(ctx, req) + }, + metrics.NewUnaryServerInterceptor(), + tracing.NewUnaryServerInterceptor(), + ), + // control service has no stream methods, so no stream interceptors added + ) c.onShutdown(func() { stopGRPC(ctx, "FrostFS Control API", c.cfgControlService.server, c.log) From acec938b2df8705c008efa2f47b4b2ecd9767245 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 17:43:53 +0300 Subject: [PATCH 1181/1413] [#1608] qos: Add client grpc interceptors `qos` client interceptors replace internal IO tags `writecache`, `policer` and `background` with `internal` IO tag for outcomming RPC. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/control.go | 6 +---- internal/qos/grpc.go | 51 +++++++++++++++++++++++++++++++++++++ pkg/network/cache/multi.go | 9 ++++--- pkg/services/tree/cache.go | 9 ++++--- pkg/services/tree/sync.go | 9 ++++--- 5 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 internal/qos/grpc.go diff --git a/cmd/frostfs-node/control.go b/cmd/frostfs-node/control.go index 1d9ac3df0d..1825013c7d 100644 --- a/cmd/frostfs-node/control.go +++ b/cmd/frostfs-node/control.go @@ -13,7 +13,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sdnotify" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "go.uber.org/zap" "google.golang.org/grpc" ) @@ -56,10 +55,7 @@ func initControlService(ctx context.Context, c *cfg) { c.cfgControlService.server = grpc.NewServer( grpc.ChainUnaryInterceptor( - func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { - ctx = tagging.ContextWithIOTag(ctx, qos.IOTagCritical.String()) - return handler(ctx, req) - }, + qos.NewSetCriticalIOTagUnaryServerInterceptor(), metrics.NewUnaryServerInterceptor(), tracing.NewUnaryServerInterceptor(), ), diff --git a/internal/qos/grpc.go b/internal/qos/grpc.go new file mode 100644 index 0000000000..c253f1e9da --- /dev/null +++ b/internal/qos/grpc.go @@ -0,0 +1,51 @@ +package qos + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + "google.golang.org/grpc" +) + +func NewSetCriticalIOTagUnaryServerInterceptor() grpc.UnaryServerInterceptor { + return func(ctx context.Context, req any, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { + ctx = tagging.ContextWithIOTag(ctx, IOTagCritical.String()) + return handler(ctx, req) + } +} + +func NewAdjustOutgoingIOTagUnaryClientInterceptor() grpc.UnaryClientInterceptor { + return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + rawTag, ok := tagging.IOTagFromContext(ctx) + if !ok { + return invoker(ctx, method, req, reply, cc, opts...) + } + tag, err := FromRawString(rawTag) + if err != nil { + tag = IOTagClient + } + if tag == IOTagBackground || tag == IOTagPolicer || tag == IOTagWritecache { + tag = IOTagInternal + } + ctx = tagging.ContextWithIOTag(ctx, tag.String()) + return invoker(ctx, method, req, reply, cc, opts...) + } +} + +func NewAdjustOutgoingIOTagStreamClientInterceptor() grpc.StreamClientInterceptor { + return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { + rawTag, ok := tagging.IOTagFromContext(ctx) + if !ok { + return streamer(ctx, desc, cc, method, opts...) + } + tag, err := FromRawString(rawTag) + if err != nil { + tag = IOTagClient + } + if tag == IOTagBackground || tag == IOTagPolicer || tag == IOTagWritecache { + tag = IOTagInternal + } + ctx = tagging.ContextWithIOTag(ctx, tag.String()) + return streamer(ctx, desc, cc, method, opts...) + } +} diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 5c3beb553c..e94fa580a6 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -7,11 +7,12 @@ import ( "sync" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" clientcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -63,14 +64,16 @@ func (x *multiClient) createForAddress(ctx context.Context, addr network.Address grpcOpts := []grpc.DialOption{ grpc.WithChainUnaryInterceptor( + qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInteceptor(), - qos.NewUnaryClientInteceptor(), + tagging.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( + qos.NewAdjustOutgoingIOTagStreamClientInterceptor(), metrics.NewStreamClientInterceptor(), tracing.NewStreamClientInterceptor(), - qos.NewStreamClientInterceptor(), + tagging.NewStreamClientInterceptor(), ), grpc.WithContextDialer(x.opts.DialerSource.GrpcContextDialer()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index 7f1dcf07cf..125871fc45 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -9,10 +9,11 @@ import ( "time" internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "github.com/hashicorp/golang-lru/v2/simplelru" "google.golang.org/grpc" "google.golang.org/grpc/connectivity" @@ -96,14 +97,16 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* opts := []grpc.DialOption{ grpc.WithChainUnaryInterceptor( + qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInteceptor(), - qos.NewUnaryClientInteceptor(), + tagging.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( + qos.NewAdjustOutgoingIOTagStreamClientInterceptor(), metrics.NewStreamClientInterceptor(), tracing.NewStreamClientInterceptor(), - qos.NewStreamClientInterceptor(), + tagging.NewStreamClientInterceptor(), ), grpc.WithContextDialer(c.ds.GrpcContextDialer()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index a0485d9d89..3e0a453853 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -13,6 +13,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" @@ -20,7 +21,7 @@ import ( metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" tracing_grpc "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/panjf2000/ants/v2" @@ -341,14 +342,16 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, func (*Service) createConnection(a network.Address) (*grpc.ClientConn, error) { return grpc.NewClient(a.URIAddr(), grpc.WithChainUnaryInterceptor( + qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), tracing_grpc.NewUnaryClientInteceptor(), - qos.NewUnaryClientInteceptor(), + tagging.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( + qos.NewAdjustOutgoingIOTagStreamClientInterceptor(), metrics.NewStreamClientInterceptor(), tracing_grpc.NewStreamClientInterceptor(), - qos.NewStreamClientInterceptor(), + tagging.NewStreamClientInterceptor(), ), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), From bfe325e61d79cd297b8c7a3a153dd59a67238f18 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 17:45:40 +0300 Subject: [PATCH 1182/1413] [#1608] policer: Add IO tag to context Signed-off-by: Dmitrii Stepanov --- pkg/services/policer/process.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/services/policer/process.go b/pkg/services/policer/process.go index bd830d04ee..635a5683b2 100644 --- a/pkg/services/policer/process.go +++ b/pkg/services/policer/process.go @@ -7,7 +7,9 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" ) @@ -18,6 +20,7 @@ func (p *Policer) Run(ctx context.Context) { } func (p *Policer) shardPolicyWorker(ctx context.Context) { + ctx = tagging.ContextWithIOTag(ctx, qos.IOTagPolicer.String()) for { select { case <-ctx.Done(): From fd0c6c461dd83daacd9e5d7e4427366ac2982f15 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 29 Jan 2025 17:47:10 +0300 Subject: [PATCH 1183/1413] [#1608] cli: Drop redundant interceptors There is no metrics or IO tags in cli. Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/internal/client/sdk.go | 5 ++--- cmd/frostfs-cli/modules/tree/client.go | 6 ------ 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/sdk.go b/cmd/frostfs-cli/internal/client/sdk.go index 71c35bd2cb..2d9c45cbd9 100644 --- a/cmd/frostfs-cli/internal/client/sdk.go +++ b/cmd/frostfs-cli/internal/client/sdk.go @@ -13,7 +13,6 @@ import ( commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -57,8 +56,8 @@ func GetSDKClient(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey prmDial := client.PrmDial{ Endpoint: addr.URIAddr(), GRPCDialOptions: []grpc.DialOption{ - grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor(), qos.NewUnaryClientInteceptor()), - grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor(), qos.NewStreamClientInterceptor()), + grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor()), + grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), }, } diff --git a/cmd/frostfs-cli/modules/tree/client.go b/cmd/frostfs-cli/modules/tree/client.go index 421f115325..c6953f126e 100644 --- a/cmd/frostfs-cli/modules/tree/client.go +++ b/cmd/frostfs-cli/modules/tree/client.go @@ -9,9 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" - metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "github.com/spf13/cobra" "github.com/spf13/viper" "google.golang.org/grpc" @@ -35,14 +33,10 @@ func _client() (tree.TreeServiceClient, error) { opts := []grpc.DialOption{ grpc.WithChainUnaryInterceptor( - metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInteceptor(), - qos.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( - metrics.NewStreamClientInterceptor(), tracing.NewStreamClientInterceptor(), - qos.NewStreamClientInterceptor(), ), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), } From abba5b20890d157305ab8581b8ae3c9dadf0da47 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 31 Jan 2025 10:12:46 +0300 Subject: [PATCH 1184/1413] [#1608] writecache: Add IO tag to flush worker Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/writecache/flush.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index d9e34ceab2..3f9b36f9de 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -6,6 +6,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" @@ -14,6 +15,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "go.opentelemetry.io/otel/attribute" @@ -35,6 +37,7 @@ func (c *cache) runFlushLoop(ctx context.Context) { if c.disableBackgroundFlush { return } + ctx = tagging.ContextWithIOTag(ctx, qos.IOTagWritecache.String()) fl := newFlushLimiter(c.flushSizeLimit) c.wg.Add(1) go func() { From 92450a76ba11cb5c75eeffa1fe2513e49f09a4df Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 31 Jan 2025 11:00:28 +0300 Subject: [PATCH 1185/1413] [#1608] shard: Add IO tag to GC Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/gc.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 1b218a372d..4a5ec7a71b 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -6,11 +6,13 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.uber.org/zap" @@ -149,7 +151,7 @@ func (gc *gc) init(ctx context.Context) { if sz > 0 { gc.workerPool = gc.workerPoolInit(sz) } - + ctx = tagging.ContextWithIOTag(ctx, qos.IOTagBackground.String()) gc.wg.Add(2) go gc.tickRemover(ctx) go gc.listenEvents(ctx) From 0671c277db2837fab94fdef2249b05f64caf2b73 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 31 Jan 2025 12:14:51 +0300 Subject: [PATCH 1186/1413] [#1608] tree: Add IO tag for tree sync requests Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/tree.go | 2 +- pkg/services/tree/qos.go | 101 +++++++++++++++++++++++++++++++++++ pkg/services/tree/service.go | 3 ++ 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 pkg/services/tree/qos.go diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index f8330a25ea..65414f0ca1 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -72,7 +72,7 @@ func initTreeService(c *cfg) { ) c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) { - tree.RegisterTreeServiceServer(s, c.treeService) + tree.RegisterTreeServiceServer(s, tree.NewIOTagAdjustServer(c.treeService, &c.cfgQoSService)) }) c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) { diff --git a/pkg/services/tree/qos.go b/pkg/services/tree/qos.go new file mode 100644 index 0000000000..8f21686df8 --- /dev/null +++ b/pkg/services/tree/qos.go @@ -0,0 +1,101 @@ +package tree + +import ( + "context" + + "google.golang.org/grpc" +) + +var _ TreeServiceServer = (*ioTagAdjust)(nil) + +type AdjustIOTag interface { + AdjustIncomingTag(ctx context.Context, requestSignPublicKey []byte) context.Context +} + +type ioTagAdjust struct { + s TreeServiceServer + a AdjustIOTag +} + +func NewIOTagAdjustServer(s TreeServiceServer, a AdjustIOTag) TreeServiceServer { + return &ioTagAdjust{ + s: s, + a: a, + } +} + +func (i *ioTagAdjust) Add(ctx context.Context, req *AddRequest) (*AddResponse, error) { + ctx = i.a.AdjustIncomingTag(ctx, req.GetSignature().GetKey()) + return i.s.Add(ctx, req) +} + +func (i *ioTagAdjust) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByPathResponse, error) { + ctx = i.a.AdjustIncomingTag(ctx, req.GetSignature().GetKey()) + return i.s.AddByPath(ctx, req) +} + +func (i *ioTagAdjust) Apply(ctx context.Context, req *ApplyRequest) (*ApplyResponse, error) { + ctx = i.a.AdjustIncomingTag(ctx, req.GetSignature().GetKey()) + return i.s.Apply(ctx, req) +} + +func (i *ioTagAdjust) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) (*GetNodeByPathResponse, error) { + ctx = i.a.AdjustIncomingTag(ctx, req.GetSignature().GetKey()) + return i.s.GetNodeByPath(ctx, req) +} + +func (i *ioTagAdjust) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) error { + ctx := i.a.AdjustIncomingTag(srv.Context(), req.GetSignature().GetKey()) + return i.s.GetOpLog(req, &qosServerWrapper[*GetOpLogResponse]{ + sender: srv, + ServerStream: srv, + ctxF: func() context.Context { return ctx }, + }) +} + +func (i *ioTagAdjust) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeServer) error { + ctx := i.a.AdjustIncomingTag(srv.Context(), req.GetSignature().GetKey()) + return i.s.GetSubTree(req, &qosServerWrapper[*GetSubTreeResponse]{ + sender: srv, + ServerStream: srv, + ctxF: func() context.Context { return ctx }, + }) +} + +func (i *ioTagAdjust) Healthcheck(ctx context.Context, req *HealthcheckRequest) (*HealthcheckResponse, error) { + ctx = i.a.AdjustIncomingTag(ctx, req.GetSignature().GetKey()) + return i.s.Healthcheck(ctx, req) +} + +func (i *ioTagAdjust) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, error) { + ctx = i.a.AdjustIncomingTag(ctx, req.GetSignature().GetKey()) + return i.s.Move(ctx, req) +} + +func (i *ioTagAdjust) Remove(ctx context.Context, req *RemoveRequest) (*RemoveResponse, error) { + ctx = i.a.AdjustIncomingTag(ctx, req.GetSignature().GetKey()) + return i.s.Remove(ctx, req) +} + +func (i *ioTagAdjust) TreeList(ctx context.Context, req *TreeListRequest) (*TreeListResponse, error) { + ctx = i.a.AdjustIncomingTag(ctx, req.GetSignature().GetKey()) + return i.s.TreeList(ctx, req) +} + +type qosSend[T any] interface { + Send(T) error +} + +type qosServerWrapper[T any] struct { + grpc.ServerStream + sender qosSend[T] + ctxF func() context.Context +} + +func (w *qosServerWrapper[T]) Send(resp T) error { + return w.sender.Send(resp) +} + +func (w *qosServerWrapper[T]) Context() context.Context { + return w.ctxF() +} diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 3c0214a98a..2e9722e791 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -9,9 +9,11 @@ import ( "sync" "sync/atomic" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" checkercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/common/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -83,6 +85,7 @@ func New(opts ...Option) *Service { // Start starts the service. func (s *Service) Start(ctx context.Context) { + ctx = tagging.ContextWithIOTag(ctx, qos.IOTagBackground.String()) go s.replicateLoop(ctx) go s.syncLoop(ctx) From 5d79abe523b0254fe0484220d6d2c57a172090e1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 5 Feb 2025 15:32:20 +0300 Subject: [PATCH 1187/1413] [#1608] shard: Add IO tag for rebuild Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/rebuild.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index 10eb51a283..0593f58942 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -6,10 +6,12 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" @@ -103,6 +105,7 @@ func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *lo default: } log.Info(ctx, logs.BlobstoreRebuildStarted) + ctx = tagging.ContextWithIOTag(ctx, qos.IOTagBackground.String()) if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, limiter, fillPercent); err != nil { log.Warn(ctx, logs.FailedToRebuildBlobstore, zap.Error(err)) } else { From a7145ca9bff4ef15abf3f7f170e420f806ebc310 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 10 Feb 2025 15:26:12 +0300 Subject: [PATCH 1188/1413] [#1614] adm/frostfsid: Add 'set-kv' Signed-off-by: Alexander Chuprov --- .../modules/morph/frostfsid/frostfsid.go | 43 +++++++++++++++++++ .../internal/modules/morph/frostfsid/root.go | 1 + 2 files changed, 44 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index b229d04368..9742991546 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -1,6 +1,7 @@ package frostfsid import ( + "errors" "fmt" "math/big" "sort" @@ -38,6 +39,11 @@ const ( groupIDFlag = "group-id" rootNamespacePlaceholder = "" + + keyFlag = "key" + keyDescFlag = "Key for storing a value in the subject's KV storage" + valueFlag = "value" + valueDescFlag = "Value to be stored in the subject's KV storage" ) var ( @@ -151,6 +157,15 @@ var ( }, Run: frostfsidListGroupSubjects, } + + frostfsidSetKVCmd = &cobra.Command{ + Use: "set-kv", + Short: "Store a key-value pair in the subject's KV storage", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + }, + Run: frostfsidSetKV, + } ) func initFrostfsIDCreateNamespaceCmd() { @@ -236,6 +251,14 @@ func initFrostfsIDListGroupSubjectsCmd() { frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") } +func initFrostfsIDSetKVCmd() { + Cmd.AddCommand(frostfsidSetKVCmd) + frostfsidSetKVCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + frostfsidSetKVCmd.Flags().String(subjectAddressFlag, "", "Subject address") + frostfsidSetKVCmd.Flags().String(keyFlag, "", keyDescFlag) + frostfsidSetKVCmd.Flags().String(valueFlag, "", valueDescFlag) +} + func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { ns := getFrostfsIDNamespace(cmd) @@ -403,6 +426,26 @@ func frostfsidRemoveSubjectFromGroup(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "remove subject from group error: %w", err) } +func frostfsidSetKV(cmd *cobra.Command, _ []string) { + subjectAddress := getFrostfsIDSubjectAddress(cmd) + key, _ := cmd.Flags().GetString(keyFlag) + value, _ := cmd.Flags().GetString(valueFlag) + + if key == "" { + commonCmd.ExitOnErr(cmd, "", errors.New("key can't be empty")) + } + + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + method, args := ffsid.roCli.SetSubjectKVCall(subjectAddress, key, value) + + ffsid.addCall(method, args) + + err = ffsid.sendWait() + commonCmd.ExitOnErr(cmd, "set KV: %w", err) +} + func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { ns := getFrostfsIDNamespace(cmd) groupID := getFrostfsIDGroupID(cmd) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go index 6ffcaa4871..930865f81b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go @@ -12,6 +12,7 @@ func init() { initFrostfsIDAddSubjectToGroupCmd() initFrostfsIDRemoveSubjectFromGroupCmd() initFrostfsIDListGroupSubjectsCmd() + initFrostfsIDSetKVCmd() initFrostfsIDAddSubjectKeyCmd() initFrostfsIDRemoveSubjectKeyCmd() } From 076952f4c73a8a2d7388f658344d8090a91f64a9 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 10 Feb 2025 15:28:29 +0300 Subject: [PATCH 1189/1413] [#1614] adm/frostfsid: Add 'delete-kv' Signed-off-by: Alexander Chuprov --- .../modules/morph/frostfsid/frostfsid.go | 34 +++++++++++++++++++ .../internal/modules/morph/frostfsid/root.go | 1 + 2 files changed, 35 insertions(+) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 9742991546..4fbd0bfe17 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -166,6 +166,14 @@ var ( }, Run: frostfsidSetKV, } + frostfsidDeleteKVCmd = &cobra.Command{ + Use: "delete-kv", + Short: "Delete a value from the subject's KV storage", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + }, + Run: frostfsidDeleteKV, + } ) func initFrostfsIDCreateNamespaceCmd() { @@ -259,6 +267,13 @@ func initFrostfsIDSetKVCmd() { frostfsidSetKVCmd.Flags().String(valueFlag, "", valueDescFlag) } +func initFrostfsIDDeleteKVCmd() { + Cmd.AddCommand(frostfsidDeleteKVCmd) + frostfsidDeleteKVCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + frostfsidDeleteKVCmd.Flags().String(subjectAddressFlag, "", "Subject address") + frostfsidDeleteKVCmd.Flags().String(keyFlag, "", keyDescFlag) +} + func frostfsidCreateNamespace(cmd *cobra.Command, _ []string) { ns := getFrostfsIDNamespace(cmd) @@ -446,6 +461,25 @@ func frostfsidSetKV(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "set KV: %w", err) } +func frostfsidDeleteKV(cmd *cobra.Command, _ []string) { + subjectAddress := getFrostfsIDSubjectAddress(cmd) + key, _ := cmd.Flags().GetString(keyFlag) + + if key == "" { + commonCmd.ExitOnErr(cmd, "", errors.New("key can't be empty")) + } + + ffsid, err := newFrostfsIDClient(cmd) + commonCmd.ExitOnErr(cmd, "init contract client: %w", err) + + method, args := ffsid.roCli.DeleteSubjectKVCall(subjectAddress, key) + + ffsid.addCall(method, args) + + err = ffsid.sendWait() + commonCmd.ExitOnErr(cmd, "delete KV: %w", err) +} + func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { ns := getFrostfsIDNamespace(cmd) groupID := getFrostfsIDGroupID(cmd) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go index 930865f81b..8aad5c5c1e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/root.go @@ -13,6 +13,7 @@ func init() { initFrostfsIDRemoveSubjectFromGroupCmd() initFrostfsIDListGroupSubjectsCmd() initFrostfsIDSetKVCmd() + initFrostfsIDDeleteKVCmd() initFrostfsIDAddSubjectKeyCmd() initFrostfsIDRemoveSubjectKeyCmd() } From b2163ff44c584f1f00bfc78272492b6e33fa3132 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 11 Feb 2025 12:00:25 +0300 Subject: [PATCH 1190/1413] [#1614] adm: Allow use any wallets Signed-off-by: Alexander Chuprov --- cmd/frostfs-adm/internal/commonflags/flags.go | 4 + .../internal/modules/morph/ape/ape_util.go | 5 +- .../internal/modules/morph/helper/actor.go | 88 +++++++++++++++---- .../internal/modules/morph/helper/util.go | 24 ++++- .../internal/modules/morph/nns/domains.go | 2 + .../internal/modules/morph/nns/helper.go | 26 +++++- .../internal/modules/morph/nns/record.go | 3 + .../internal/modules/morph/nns/root.go | 5 ++ 8 files changed, 135 insertions(+), 22 deletions(-) diff --git a/cmd/frostfs-adm/internal/commonflags/flags.go b/cmd/frostfs-adm/internal/commonflags/flags.go index 87692d0136..c25d902c24 100644 --- a/cmd/frostfs-adm/internal/commonflags/flags.go +++ b/cmd/frostfs-adm/internal/commonflags/flags.go @@ -16,6 +16,10 @@ const ( EndpointFlagDesc = "N3 RPC node endpoint" EndpointFlagShort = "r" + WalletPath = "wallet" + WalletPathShorthand = "w" + WalletPathUsage = "Path to the wallet" + AlphabetWalletsFlag = "alphabet-wallets" AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" diff --git a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go index 9146826476..3c332c3f00 100644 --- a/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go +++ b/cmd/frostfs-adm/internal/modules/morph/ape/ape_util.go @@ -3,6 +3,8 @@ package ape import ( "errors" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" @@ -76,7 +78,8 @@ func newPolicyContractInterface(cmd *cobra.Command) (*morph.ContractStorage, *he c, err := helper.NewRemoteClient(viper.GetViper()) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - ac, err := helper.NewLocalActor(cmd, c, constants.ConsensusAccountName) + walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) + ac, err := helper.NewLocalActor(c, &helper.AlphabetWallets{Path: walletDir, Label: constants.ConsensusAccountName}) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) var ch util.Uint160 diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go index eb04444089..6499ace5f9 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/actor.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/actor.go @@ -3,9 +3,6 @@ package helper import ( "fmt" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" - commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -16,7 +13,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/wallet" - "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -28,32 +24,86 @@ type LocalActor struct { rpcInvoker invoker.RPCInvoke } +type AlphabetWallets struct { + Label string + Path string +} + +func (a *AlphabetWallets) GetAccount(v *viper.Viper) ([]*wallet.Account, error) { + w, err := GetAlphabetWallets(v, a.Path) + if err != nil { + return nil, err + } + + var accounts []*wallet.Account + for _, wall := range w { + acc, err := GetWalletAccount(wall, a.Label) + if err != nil { + return nil, err + } + accounts = append(accounts, acc) + } + return accounts, nil +} + +type RegularWallets struct{ Path string } + +func (r *RegularWallets) GetAccount() ([]*wallet.Account, error) { + w, err := getRegularWallet(r.Path) + if err != nil { + return nil, err + } + + return []*wallet.Account{w.GetAccount(w.GetChangeAddress())}, nil +} + // NewLocalActor create LocalActor with accounts form provided wallets. // In case of empty wallets provided created actor with dummy account only for read operation. // // If wallets are provided, the contract client will use accounts with accName name from these wallets. // To determine which account name should be used in a contract client, refer to how the contract // verifies the transaction signature. -func NewLocalActor(cmd *cobra.Command, c actor.RPCActor, accName string) (*LocalActor, error) { - walletDir := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) +func NewLocalActor(c actor.RPCActor, alphabet *AlphabetWallets, regularWallets ...*RegularWallets) (*LocalActor, error) { var act *actor.Actor var accounts []*wallet.Account + var signers []actor.SignerAccount - wallets, err := GetAlphabetWallets(viper.GetViper(), walletDir) - commonCmd.ExitOnErr(cmd, "unable to get alphabet wallets: %w", err) + if alphabet != nil { + account, err := alphabet.GetAccount(viper.GetViper()) + if err != nil { + return nil, err + } - for _, w := range wallets { - acc, err := GetWalletAccount(w, accName) - commonCmd.ExitOnErr(cmd, fmt.Sprintf("can't find %s account: %%w", accName), err) - accounts = append(accounts, acc) + accounts = append(accounts, account...) + signers = append(signers, actor.SignerAccount{ + Signer: transaction.Signer{ + Account: account[0].Contract.ScriptHash(), + Scopes: transaction.Global, + }, + Account: account[0], + }) } - act, err = actor.New(c, []actor.SignerAccount{{ - Signer: transaction.Signer{ - Account: accounts[0].Contract.ScriptHash(), - Scopes: transaction.Global, - }, - Account: accounts[0], - }}) + + for _, w := range regularWallets { + if w == nil { + continue + } + account, err := w.GetAccount() + if err != nil { + return nil, err + } + + accounts = append(accounts, account...) + signers = append(signers, actor.SignerAccount{ + Signer: transaction.Signer{ + Account: account[0].Contract.ScriptHash(), + Scopes: transaction.Global, + }, + Account: account[0], + }) + } + + act, err := actor.New(c, signers) if err != nil { return nil, err } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/util.go b/cmd/frostfs-adm/internal/modules/morph/helper/util.go index c26aa447b3..be6b2c6dd0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/util.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/util.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" + "github.com/nspcc-dev/neo-go/cli/input" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" @@ -22,6 +23,27 @@ import ( "github.com/spf13/viper" ) +func getRegularWallet(walletPath string) (*wallet.Wallet, error) { + w, err := wallet.NewWalletFromFile(walletPath) + if err != nil { + return nil, err + } + + password, err := input.ReadPassword("Enter password for wallet:") + if err != nil { + return nil, fmt.Errorf("can't fetch password: %w", err) + } + + for i := range w.Accounts { + if err = w.Accounts[i].Decrypt(password, keys.NEP2ScryptParams()); err != nil { + err = fmt.Errorf("can't unlock wallet: %w", err) + break + } + } + + return w, err +} + func GetAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, error) { wallets, err := openAlphabetWallets(v, walletDir) if err != nil { @@ -51,7 +73,7 @@ func openAlphabetWallets(v *viper.Viper, walletDir string) ([]*wallet.Wallet, er if errors.Is(err, os.ErrNotExist) { err = nil } else { - err = fmt.Errorf("can't open wallet: %w", err) + err = fmt.Errorf("can't open alphabet wallet: %w", err) } break } diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/domains.go b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go index 1668bb327a..e25d0db498 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/domains.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go @@ -19,6 +19,7 @@ func initRegisterCmd() { registerCmd.Flags().Int64(nnsRetryFlag, constants.NNSRetryDefVal, "SOA record RETRY parameter") registerCmd.Flags().Int64(nnsExpireFlag, int64(constants.DefaultExpirationTime), "SOA record EXPIRE parameter") registerCmd.Flags().Int64(nnsTTLFlag, constants.NNSTtlDefVal, "SOA record TTL parameter") + registerCmd.Flags().StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, "", commonflags.WalletPathUsage) _ = cobra.MarkFlagRequired(registerCmd.Flags(), nnsNameFlag) } @@ -48,6 +49,7 @@ func initDeleteCmd() { deleteCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) deleteCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) deleteCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + deleteCmd.Flags().StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, "", commonflags.WalletPathUsage) _ = cobra.MarkFlagRequired(deleteCmd.Flags(), nnsNameFlag) } diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index b13cbc8a15..5cf02e8667 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -1,7 +1,11 @@ package nns import ( + "errors" + client "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" @@ -16,7 +20,27 @@ func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { c, err := helper.NewRemoteClient(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - ac, err := helper.NewLocalActor(cmd, c, constants.CommitteeAccountName) + alphabetWalletPath := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) + walletPath := config.ResolveHomePath(viper.GetString(commonflags.WalletPath)) + + var ( + alphabet *helper.AlphabetWallets + regularWallets []*helper.RegularWallets + ) + + if alphabetWalletPath != "" { + alphabet = &helper.AlphabetWallets{Path: alphabetWalletPath, Label: constants.ConsensusAccountName} + } + + if walletPath != "" { + regularWallets = append(regularWallets, &helper.RegularWallets{Path: walletPath}) + } + + if alphabet == nil && regularWallets == nil { + commonCmd.ExitOnErr(cmd, "", errors.New("no wallets provided")) + } + + ac, err := helper.NewLocalActor(c, alphabet, regularWallets...) commonCmd.ExitOnErr(cmd, "can't create actor: %w", err) r := management.NewReader(ac.Invoker) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/record.go b/cmd/frostfs-adm/internal/modules/morph/nns/record.go index 09ed92ab35..9cb47356f4 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/record.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/record.go @@ -19,6 +19,7 @@ func initAddRecordCmd() { addRecordCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) addRecordCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) addRecordCmd.Flags().String(nnsRecordDataFlag, "", nnsRecordDataFlagDesc) + addRecordCmd.Flags().StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, "", commonflags.WalletPathUsage) _ = cobra.MarkFlagRequired(addRecordCmd.Flags(), nnsNameFlag) _ = cobra.MarkFlagRequired(addRecordCmd.Flags(), nnsRecordTypeFlag) @@ -40,6 +41,7 @@ func initDelRecordsCmd() { delRecordsCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) delRecordsCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) delRecordsCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) + delRecordsCmd.Flags().StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, "", commonflags.WalletPathUsage) _ = cobra.MarkFlagRequired(delRecordsCmd.Flags(), nnsNameFlag) _ = cobra.MarkFlagRequired(delRecordsCmd.Flags(), nnsRecordTypeFlag) @@ -52,6 +54,7 @@ func initDelRecordCmd() { delRecordCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) delRecordCmd.Flags().String(nnsRecordTypeFlag, "", nnsRecordTypeFlagDesc) delRecordCmd.Flags().String(nnsRecordDataFlag, "", nnsRecordDataFlagDesc) + delRecordCmd.Flags().StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, "", commonflags.WalletPathUsage) _ = cobra.MarkFlagRequired(delRecordCmd.Flags(), nnsNameFlag) _ = cobra.MarkFlagRequired(delRecordCmd.Flags(), nnsRecordTypeFlag) diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/root.go b/cmd/frostfs-adm/internal/modules/morph/nns/root.go index 9bdeaccd90..64a279288f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/root.go @@ -39,6 +39,7 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) }, Run: registerDomain, } @@ -48,6 +49,7 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) }, Run: deleteDomain, } @@ -75,6 +77,7 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) }, Run: addRecord, } @@ -92,6 +95,7 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) }, Run: delRecords, } @@ -101,6 +105,7 @@ var ( PreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) }, Run: delRecord, } From 304bee938ba7fbd1ebbbef2b9996a0ae87950be6 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 11 Feb 2025 12:00:51 +0300 Subject: [PATCH 1191/1413] [#1614] adm/nns: Add 'set-admin' Signed-off-by: Alexander Chuprov --- cmd/frostfs-adm/internal/commonflags/flags.go | 3 +++ .../internal/modules/morph/nns/domains.go | 27 +++++++++++++++++++ .../internal/modules/morph/nns/helper.go | 9 +++++-- .../internal/modules/morph/nns/root.go | 12 +++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/commonflags/flags.go b/cmd/frostfs-adm/internal/commonflags/flags.go index c25d902c24..f194e97f5b 100644 --- a/cmd/frostfs-adm/internal/commonflags/flags.go +++ b/cmd/frostfs-adm/internal/commonflags/flags.go @@ -23,6 +23,9 @@ const ( AlphabetWalletsFlag = "alphabet-wallets" AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" + AdminWalletPath = "wallet-admin" + AdminWalletUsage = "Path to the admin wallet" + LocalDumpFlag = "local-dump" ProtoConfigPath = "protocol" ContractsInitFlag = "contracts" diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/domains.go b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go index e25d0db498..14f6eb390f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/domains.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/domains.go @@ -6,7 +6,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func initRegisterCmd() { @@ -64,3 +66,28 @@ func deleteDomain(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "delete domain error: %w", err) cmd.Println("Domain deleted successfully") } + +func initSetAdminCmd() { + Cmd.AddCommand(setAdminCmd) + setAdminCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + setAdminCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc) + setAdminCmd.Flags().String(nnsNameFlag, "", nnsNameFlagDesc) + setAdminCmd.Flags().StringP(commonflags.WalletPath, commonflags.WalletPathShorthand, "", commonflags.WalletPathUsage) + setAdminCmd.Flags().String(commonflags.AdminWalletPath, "", commonflags.AdminWalletUsage) + _ = setAdminCmd.MarkFlagRequired(commonflags.AdminWalletPath) + + _ = cobra.MarkFlagRequired(setAdminCmd.Flags(), nnsNameFlag) +} + +func setAdmin(cmd *cobra.Command, _ []string) { + c, actor := nnsWriter(cmd) + + name, _ := cmd.Flags().GetString(nnsNameFlag) + w, err := wallet.NewWalletFromFile(viper.GetString(commonflags.AdminWalletPath)) + commonCmd.ExitOnErr(cmd, "can't get admin wallet: %w", err) + h, vub, err := c.SetAdmin(name, w.GetAccount(w.GetChangeAddress()).ScriptHash()) + + _, err = actor.Wait(h, vub, err) + commonCmd.ExitOnErr(cmd, "Set admin error: %w", err) + cmd.Println("Set admin successfully") +} diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go index 5cf02e8667..e49f62256e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/helper.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/helper.go @@ -20,8 +20,9 @@ func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { c, err := helper.NewRemoteClient(v) commonCmd.ExitOnErr(cmd, "unable to create NEO rpc client: %w", err) - alphabetWalletPath := config.ResolveHomePath(viper.GetString(commonflags.AlphabetWalletsFlag)) - walletPath := config.ResolveHomePath(viper.GetString(commonflags.WalletPath)) + alphabetWalletPath := config.ResolveHomePath(v.GetString(commonflags.AlphabetWalletsFlag)) + walletPath := config.ResolveHomePath(v.GetString(commonflags.WalletPath)) + adminWalletPath := config.ResolveHomePath(v.GetString(commonflags.AdminWalletPath)) var ( alphabet *helper.AlphabetWallets @@ -36,6 +37,10 @@ func nnsWriter(cmd *cobra.Command) (*client.Contract, *helper.LocalActor) { regularWallets = append(regularWallets, &helper.RegularWallets{Path: walletPath}) } + if adminWalletPath != "" { + regularWallets = append(regularWallets, &helper.RegularWallets{Path: adminWalletPath}) + } + if alphabet == nil && regularWallets == nil { commonCmd.ExitOnErr(cmd, "", errors.New("no wallets provided")) } diff --git a/cmd/frostfs-adm/internal/modules/morph/nns/root.go b/cmd/frostfs-adm/internal/modules/morph/nns/root.go index 64a279288f..bb84933c6e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/nns/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/nns/root.go @@ -109,6 +109,17 @@ var ( }, Run: delRecord, } + setAdminCmd = &cobra.Command{ + Use: "set-admin", + Short: "Sets admin for domain", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.AlphabetWalletsFlag, cmd.Flags().Lookup(commonflags.AlphabetWalletsFlag)) + _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) + _ = viper.BindPFlag(commonflags.AdminWalletPath, cmd.Flags().Lookup(commonflags.AdminWalletPath)) + }, + Run: setAdmin, + } ) func init() { @@ -121,4 +132,5 @@ func init() { initGetRecordsCmd() initDelRecordsCmd() initDelRecordCmd() + initSetAdminCmd() } From 1bcaa1af1f4ff32b7a7f7bdfbef1ca62954361a2 Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Mon, 10 Feb 2025 18:30:18 +0300 Subject: [PATCH 1192/1413] [#1641] govulncheck: Fix minor toolchain updates for good Signed-off-by: Vitaliy Potyarkin --- .forgejo/workflows/vulncheck.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index 7c89a35555..140434dfc1 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -18,7 +18,8 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.23.6' + go-version: '1.23' + check-latest: true - name: Install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest From fe0cf86dc681e221706d9dcb4b25413bfdf065e9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 12 Feb 2025 15:37:38 +0300 Subject: [PATCH 1193/1413] [#1643] go.mod: Bump frostfs-observability version To add `grpc_client_msg_send_handling_seconds` metric. Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 8f2e7bc51d..5df7a5cc10 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1-0.20241205083807-762d7f9f9f08 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d - git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 + git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421 git.frostfs.info/TrueCloudLab/hrw v1.2.1 diff --git a/go.sum b/go.sum index e92b648860..39a6a98e64 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88 h1:9bvBDLApbbO5sXBKdODpE9tzy3HV99nXxkDWNn22rdI= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20241112082307-f17779933e88/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 h1:Mxw1c/8t96vFIUOffl28lFaHKi413oCBfLMGJmF9cFA= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe h1:81gDNdWNLP24oMQukRiCE9R1wGSh0l0dRq3F1W+Oesc= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421 h1:pP19IawSdsLCKFv7HMNfWAeH6E3uSnntKZkwka+/2+4= From 9b29e7392fb960f7d3c923f17ce29d5475ef9562 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 18 Feb 2025 09:38:00 +0300 Subject: [PATCH 1194/1413] [#1647] go.mod: Bump frostfs-sdk-go version Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 5df7a5cc10..23ddad2764 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 diff --git a/go.sum b/go.sum index 39a6a98e64..ecd2ab525c 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e13 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe h1:81gDNdWNLP24oMQukRiCE9R1wGSh0l0dRq3F1W+Oesc= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421 h1:pP19IawSdsLCKFv7HMNfWAeH6E3uSnntKZkwka+/2+4= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250202151421-8389887a3421/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4 h1:dOZHuOywvH1ms8U38lDCWpysgkCCeJ02RLI7zDhPcyw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= From 02f3a7f65c0d649f29db04f5c49703e48621b95b Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 18 Feb 2025 10:51:43 +0300 Subject: [PATCH 1195/1413] [#1648] writecache: Fix race condition when reporting cache size metrics There is a race condition when multiple cache operation try to report the cache size metrics simultaneously. Consider the following example: - the initial total size of objects stored in the cache size is 2 - worker X deletes an object and reads the cache size, which is 1 - worker Y deletes an object and reads the cache size, which is 0 - worker Y reports the cache size it learnt, which is 0 - worker X reports the cache size it learnt, which is 1 As a result, the observed cache size is 1 (i. e. one object remains in the cache), which is incorrect because the actual cache size is 0. To fix this, let's report the metrics periodically in the flush loop. Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/writecache/flush.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 3f9b36f9de..2d07d8b327 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -87,6 +87,9 @@ func (c *cache) pushToFlushQueue(ctx context.Context, fl *flushLimiter) { } c.modeMtx.RUnlock() + + // counter changed by fstree + c.estimateCacheSize() case <-ctx.Done(): return } From b2adf1109e380c364b8132ee7fa1947094c65c86 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 20 Feb 2025 12:27:07 +0300 Subject: [PATCH 1196/1413] [#1646] cli: Use Cmp() functions for ID-like structs Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/internal/client/client.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index ceae36ae7d..3f235f070b 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -9,7 +9,6 @@ import ( "io" "os" "slices" - "strings" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/accounting" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" @@ -77,9 +76,7 @@ func ListContainers(ctx context.Context, prm ListContainersPrm) (res ListContain // SortedIDList returns sorted list of identifiers of user's containers. func (x ListContainersRes) SortedIDList() []cid.ID { list := x.cliRes.Containers() - slices.SortFunc(list, func(lhs, rhs cid.ID) int { - return strings.Compare(lhs.EncodeToString(), rhs.EncodeToString()) - }) + slices.SortFunc(list, cid.ID.Cmp) return list } @@ -687,9 +684,7 @@ func SearchObjects(ctx context.Context, prm SearchObjectsPrm) (*SearchObjectsRes return nil, fmt.Errorf("read object list: %w", err) } - slices.SortFunc(list, func(a, b oid.ID) int { - return strings.Compare(a.EncodeToString(), b.EncodeToString()) - }) + slices.SortFunc(list, oid.ID.Cmp) return &SearchObjectsRes{ ids: list, From 003d568ae2361e7b675091b2a0dff36b490a6013 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 30 Jan 2025 16:27:48 +0300 Subject: [PATCH 1197/1413] [#1628] innerring: Relax container homomorphic hashing check Our initial desire was to prohibit using homomorphic hashing on the network level because of the resource consumption. However, the ability to use it, doesn't mean that we must. So only fail validation if container wants to have homomorphic hashing, but the network prohibits it. Signed-off-by: Evgenii Stratonikov --- pkg/innerring/processors/container/process_container.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/innerring/processors/container/process_container.go b/pkg/innerring/processors/container/process_container.go index 854e2c7792..8e4ab2623b 100644 --- a/pkg/innerring/processors/container/process_container.go +++ b/pkg/innerring/processors/container/process_container.go @@ -209,7 +209,7 @@ func checkHomomorphicHashing(ctx context.Context, ns NetworkState, cnr container return fmt.Errorf("could not get setting in contract: %w", err) } - if cnrSetting := containerSDK.IsHomomorphicHashingDisabled(cnr); netSetting != cnrSetting { + if cnrSetting := containerSDK.IsHomomorphicHashingDisabled(cnr); netSetting && !cnrSetting { return fmt.Errorf("network setting: %t, container setting: %t", netSetting, cnrSetting) } From 37972a91c19c6aa1b44c322bb5e485d553f031a9 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 24 Feb 2025 12:47:09 +0300 Subject: [PATCH 1198/1413] [#1654] adm: Make 'morph-init' idempotent Signed-off-by: Alexander Chuprov --- .../modules/morph/initialize/initialize_transfer.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go index 7f1bfee2b0..d379204a60 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go @@ -83,11 +83,14 @@ func transferFunds(c *helper.InitializeContext) error { // transferFundsFinished checks balances of accounts we transfer GAS to. // The stage is considered finished if the balance is greater than the half of what we need to transfer. func transferFundsFinished(c *helper.InitializeContext) (bool, error) { - acc := c.Accounts[0] - r := nep17.NewReader(c.ReadOnlyInvoker, gas.Hash) - res, err := r.BalanceOf(acc.Contract.ScriptHash()) - if err != nil || res.Cmp(big.NewInt(initialAlphabetGASAmount/2)) != 1 { + res, err := r.BalanceOf(c.ConsensusAcc.ScriptHash()) + if err != nil { + return false, err + } + + version, err := c.Client.GetVersion() + if err != nil || res.Cmp(big.NewInt(int64(version.Protocol.InitialGasDistribution))) != -1 { return false, err } From 2ff032db90de1c1c2af24a9231eeafaabbe5d643 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 24 Feb 2025 13:22:23 +0300 Subject: [PATCH 1199/1413] [#1654] adm: Get 'gasInitialTotalSupply' from network Signed-off-by: Alexander Chuprov --- .../morph/initialize/initialize_transfer.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go index d379204a60..bb684b3a9f 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_transfer.go @@ -22,15 +22,14 @@ import ( ) const ( - gasInitialTotalSupply = 30000000 * native.GASFactor // initialAlphabetGASAmount represents the amount of GAS given to each alphabet node. initialAlphabetGASAmount = 10_000 * native.GASFactor // initialProxyGASAmount represents the amount of GAS given to a proxy contract. initialProxyGASAmount = 50_000 * native.GASFactor ) -func initialCommitteeGASAmount(c *helper.InitializeContext) int64 { - return (gasInitialTotalSupply - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2 +func initialCommitteeGASAmount(c *helper.InitializeContext, initialGasDistribution int64) int64 { + return (initialGasDistribution - initialAlphabetGASAmount*int64(len(c.Wallets))) / 2 } func transferFunds(c *helper.InitializeContext) error { @@ -42,6 +41,11 @@ func transferFunds(c *helper.InitializeContext) error { return err } + version, err := c.Client.GetVersion() + if err != nil { + return err + } + var transfers []transferTarget for _, acc := range c.Accounts { to := acc.Contract.ScriptHash() @@ -59,7 +63,7 @@ func transferFunds(c *helper.InitializeContext) error { transferTarget{ Token: gas.Hash, Address: c.CommitteeAcc.Contract.ScriptHash(), - Amount: initialCommitteeGASAmount(c), + Amount: initialCommitteeGASAmount(c, int64(version.Protocol.InitialGasDistribution)), }, transferTarget{ Token: neo.Hash, @@ -95,7 +99,11 @@ func transferFundsFinished(c *helper.InitializeContext) (bool, error) { } res, err = r.BalanceOf(c.CommitteeAcc.ScriptHash()) - return res != nil && res.Cmp(big.NewInt(initialCommitteeGASAmount(c)/2)) == 1, err + if err != nil { + return false, err + } + + return res != nil && res.Cmp(big.NewInt(initialCommitteeGASAmount(c, int64(version.Protocol.InitialGasDistribution)))) == 1, err } func transferGASToProxy(c *helper.InitializeContext) error { From 9a0507704ae0b5069ab6555730fb758f71d04618 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 20 Feb 2025 17:47:28 +0300 Subject: [PATCH 1200/1413] [#1651] apemanager: Wrap some errors with `InvalidArgument` status Signed-off-by: Airat Arifullin --- pkg/services/apemanager/errors/errors.go | 6 ++++++ pkg/services/apemanager/executor.go | 14 +++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/pkg/services/apemanager/errors/errors.go b/pkg/services/apemanager/errors/errors.go index e64f9a8d13..1d485321c2 100644 --- a/pkg/services/apemanager/errors/errors.go +++ b/pkg/services/apemanager/errors/errors.go @@ -9,3 +9,9 @@ func ErrAPEManagerAccessDenied(reason string) error { err.WriteReason(reason) return err } + +func ErrAPEManagerInvalidArgument(msg string) error { + err := new(apistatus.InvalidArgument) + err.SetMessage(msg) + return err +} diff --git a/pkg/services/apemanager/executor.go b/pkg/services/apemanager/executor.go index 58922fede2..fc08fe569a 100644 --- a/pkg/services/apemanager/executor.go +++ b/pkg/services/apemanager/executor.go @@ -81,7 +81,7 @@ var _ Server = (*Service)(nil) func (s *Service) validateContainerTargetRequest(ctx context.Context, cid string, pubKey *keys.PublicKey) error { var cidSDK cidSDK.ID if err := cidSDK.DecodeString(cid); err != nil { - return fmt.Errorf("invalid CID format: %w", err) + return apemanager_errors.ErrAPEManagerInvalidArgument(fmt.Sprintf("invalid CID format: %v", err)) } isOwner, err := s.isActorContainerOwner(ctx, cidSDK, pubKey) if err != nil { @@ -101,7 +101,7 @@ func (s *Service) AddChain(ctx context.Context, req *apemanagerV2.AddChainReques chain, err := decodeAndValidateChain(req.GetBody().GetChain().GetKind().(*apeV2.ChainRaw).GetRaw()) if err != nil { - return nil, err + return nil, apemanager_errors.ErrAPEManagerInvalidArgument(err.Error()) } if len(chain.ID) == 0 { const randomIDLength = 10 @@ -122,7 +122,7 @@ func (s *Service) AddChain(ctx context.Context, req *apemanagerV2.AddChainReques } target = policy_engine.ContainerTarget(reqCID) default: - return nil, fmt.Errorf("unsupported target type: %s", targetType) + return nil, apemanager_errors.ErrAPEManagerInvalidArgument(fmt.Sprintf("unsupported target type: %s", targetType)) } txHash, vub, err := s.contractStorage.AddMorphRuleChain(apechain.Ingress, target, &chain) @@ -158,7 +158,7 @@ func (s *Service) RemoveChain(ctx context.Context, req *apemanagerV2.RemoveChain } target = policy_engine.ContainerTarget(reqCID) default: - return nil, fmt.Errorf("unsupported target type: %s", targetType) + return nil, apemanager_errors.ErrAPEManagerInvalidArgument(fmt.Sprintf("unsupported target type: %s", targetType)) } txHash, vub, err := s.contractStorage.RemoveMorphRuleChain(apechain.Ingress, target, req.GetBody().GetChainID()) @@ -193,7 +193,7 @@ func (s *Service) ListChains(ctx context.Context, req *apemanagerV2.ListChainsRe } target = policy_engine.ContainerTarget(reqCID) default: - return nil, fmt.Errorf("unsupported target type: %s", targetType) + return nil, apemanager_errors.ErrAPEManagerInvalidArgument(fmt.Sprintf("unsupported target type: %s", targetType)) } chs, err := s.contractStorage.ListMorphRuleChains(apechain.Ingress, target) @@ -227,11 +227,11 @@ func getSignaturePublicKey(vh *session.RequestVerificationHeader) (*keys.PublicK } sig := vh.GetBodySignature() if sig == nil { - return nil, errEmptyBodySignature + return nil, apemanager_errors.ErrAPEManagerInvalidArgument(errEmptyBodySignature.Error()) } key, err := keys.NewPublicKeyFromBytes(sig.GetKey(), elliptic.P256()) if err != nil { - return nil, fmt.Errorf("invalid signature key: %w", err) + return nil, apemanager_errors.ErrAPEManagerInvalidArgument(fmt.Sprintf("invalid signature key: %v", err)) } return key, nil From a97bded440c345c5212f7aaa9c9a89785b22cd32 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 6 Feb 2025 11:09:33 +0300 Subject: [PATCH 1201/1413] [#1639] config: Separate `replicator.pool_size` from other settings Separated `replicator.pool_size` and `object.put.remote_pool_size` settings. Signed-off-by: Aleksey Savchuk --- cmd/frostfs-node/config.go | 4 ---- cmd/frostfs-node/config/replicator/config.go | 11 ++++++++++- cmd/frostfs-node/config/replicator/config_test.go | 2 +- docs/storage-node-configuration.md | 8 ++++---- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 5117775666..d575c7228b 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1177,10 +1177,6 @@ func initObjectPool(cfg *config.Config) (pool cfgObjectRoutines) { fatalOnErr(err) replicatorPoolSize := replicatorconfig.PoolSize(cfg) - if replicatorPoolSize <= 0 { - replicatorPoolSize = putRemoteCapacity - } - pool.replication, err = ants.NewPool(replicatorPoolSize) fatalOnErr(err) diff --git a/cmd/frostfs-node/config/replicator/config.go b/cmd/frostfs-node/config/replicator/config.go index 0fbac935c6..e954bf19df 100644 --- a/cmd/frostfs-node/config/replicator/config.go +++ b/cmd/frostfs-node/config/replicator/config.go @@ -11,6 +11,8 @@ const ( // PutTimeoutDefault is a default timeout of object put request in replicator. PutTimeoutDefault = 5 * time.Second + // PoolSizeDefault is a default pool size for put request in replicator. + PoolSizeDefault = 10 ) // PutTimeout returns the value of "put_timeout" config parameter @@ -28,6 +30,13 @@ func PutTimeout(c *config.Config) time.Duration { // PoolSize returns the value of "pool_size" config parameter // from "replicator" section. +// +// Returns PoolSizeDefault if the value is non-positive integer. func PoolSize(c *config.Config) int { - return int(config.IntSafe(c.Sub(subsection), "pool_size")) + v := int(config.IntSafe(c.Sub(subsection), "pool_size")) + if v > 0 { + return v + } + + return PoolSizeDefault } diff --git a/cmd/frostfs-node/config/replicator/config_test.go b/cmd/frostfs-node/config/replicator/config_test.go index 2129c01b45..2aa4909469 100644 --- a/cmd/frostfs-node/config/replicator/config_test.go +++ b/cmd/frostfs-node/config/replicator/config_test.go @@ -15,7 +15,7 @@ func TestReplicatorSection(t *testing.T) { empty := configtest.EmptyConfig() require.Equal(t, replicatorconfig.PutTimeoutDefault, replicatorconfig.PutTimeout(empty)) - require.Equal(t, 0, replicatorconfig.PoolSize(empty)) + require.Equal(t, replicatorconfig.PoolSizeDefault, replicatorconfig.PoolSize(empty)) }) const path = "../../../../config/example/node" diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index de2729c68e..aef05d5893 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -396,10 +396,10 @@ replicator: pool_size: 10 ``` -| Parameter | Type | Default value | Description | -|---------------|------------|----------------------------------------|---------------------------------------------| -| `put_timeout` | `duration` | `5s` | Timeout for performing the `PUT` operation. | -| `pool_size` | `int` | Equal to `object.put.remote_pool_size` | Maximum amount of concurrent replications. | +| Parameter | Type | Default value | Description | +|---------------|------------|---------------|---------------------------------------------| +| `put_timeout` | `duration` | `5s` | Timeout for performing the `PUT` operation. | +| `pool_size` | `int` | `10` | Maximum amount of concurrent replications. | # `object` section Contains object-service related parameters. From dce269c62e555a08eb6e768b8fb25d7307564991 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 6 Feb 2025 11:50:12 +0300 Subject: [PATCH 1202/1413] [#1639] services/object: Remove limiting pools for Put operation Signed-off-by: Aleksey Savchuk --- cmd/frostfs-node/config.go | 22 +----------- cmd/frostfs-node/config/object/config.go | 28 --------------- cmd/frostfs-node/config/object/config_test.go | 4 --- cmd/frostfs-node/object.go | 1 - config/example/node.env | 2 -- config/example/node.json | 2 -- config/example/node.yaml | 2 -- docs/storage-node-configuration.md | 4 --- internal/logs/logs.go | 1 - pkg/services/object/common/writer/common.go | 10 ++---- pkg/services/object/common/writer/ec.go | 36 ++----------------- pkg/services/object/common/writer/ec_test.go | 5 --- pkg/services/object/common/writer/writer.go | 16 --------- pkg/services/object/put/service.go | 3 -- pkg/services/object/util/log.go | 8 ----- 15 files changed, 7 insertions(+), 137 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index d575c7228b..43ec40d1d4 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -664,10 +664,6 @@ type cfgAccessPolicyEngine struct { } type cfgObjectRoutines struct { - putRemote *ants.Pool - - putLocal *ants.Pool - replication *ants.Pool } @@ -1166,16 +1162,6 @@ func initAccessPolicyEngine(ctx context.Context, c *cfg) { func initObjectPool(cfg *config.Config) (pool cfgObjectRoutines) { var err error - optNonBlocking := ants.WithNonblocking(true) - - putRemoteCapacity := objectconfig.Put(cfg).PoolSizeRemote() - pool.putRemote, err = ants.NewPool(putRemoteCapacity, optNonBlocking) - fatalOnErr(err) - - putLocalCapacity := objectconfig.Put(cfg).PoolSizeLocal() - pool.putLocal, err = ants.NewPool(putLocalCapacity, optNonBlocking) - fatalOnErr(err) - replicatorPoolSize := replicatorconfig.PoolSize(cfg) pool.replication, err = ants.NewPool(replicatorPoolSize) fatalOnErr(err) @@ -1410,13 +1396,7 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { } func (c *cfg) reloadPools() error { - newSize := objectconfig.Put(c.appCfg).PoolSizeLocal() - c.reloadPool(c.cfgObject.pool.putLocal, newSize, "object.put.local_pool_size") - - newSize = objectconfig.Put(c.appCfg).PoolSizeRemote() - c.reloadPool(c.cfgObject.pool.putRemote, newSize, "object.put.remote_pool_size") - - newSize = replicatorconfig.PoolSize(c.appCfg) + newSize := replicatorconfig.PoolSize(c.appCfg) c.reloadPool(c.cfgObject.pool.replication, newSize, "replicator.pool_size") return nil diff --git a/cmd/frostfs-node/config/object/config.go b/cmd/frostfs-node/config/object/config.go index 6ff1fe2aba..c8c967d30a 100644 --- a/cmd/frostfs-node/config/object/config.go +++ b/cmd/frostfs-node/config/object/config.go @@ -21,10 +21,6 @@ const ( putSubsection = "put" getSubsection = "get" - - // PutPoolSizeDefault is a default value of routine pool size to - // process object.Put requests in object service. - PutPoolSizeDefault = 10 ) // Put returns structure that provides access to "put" subsection of @@ -35,30 +31,6 @@ func Put(c *config.Config) PutConfig { } } -// PoolSizeRemote returns the value of "remote_pool_size" config parameter. -// -// Returns PutPoolSizeDefault if the value is not a positive number. -func (g PutConfig) PoolSizeRemote() int { - v := config.Int(g.cfg, "remote_pool_size") - if v > 0 { - return int(v) - } - - return PutPoolSizeDefault -} - -// PoolSizeLocal returns the value of "local_pool_size" config parameter. -// -// Returns PutPoolSizeDefault if the value is not a positive number. -func (g PutConfig) PoolSizeLocal() int { - v := config.Int(g.cfg, "local_pool_size") - if v > 0 { - return int(v) - } - - return PutPoolSizeDefault -} - // SkipSessionTokenIssuerVerification returns the value of "skip_session_token_issuer_verification" config parameter or `false“ if is not defined. func (g PutConfig) SkipSessionTokenIssuerVerification() bool { return config.BoolSafe(g.cfg, "skip_session_token_issuer_verification") diff --git a/cmd/frostfs-node/config/object/config_test.go b/cmd/frostfs-node/config/object/config_test.go index e2bb105d9f..1c525ef554 100644 --- a/cmd/frostfs-node/config/object/config_test.go +++ b/cmd/frostfs-node/config/object/config_test.go @@ -13,8 +13,6 @@ func TestObjectSection(t *testing.T) { t.Run("defaults", func(t *testing.T) { empty := configtest.EmptyConfig() - require.Equal(t, objectconfig.PutPoolSizeDefault, objectconfig.Put(empty).PoolSizeRemote()) - require.Equal(t, objectconfig.PutPoolSizeDefault, objectconfig.Put(empty).PoolSizeLocal()) require.EqualValues(t, objectconfig.DefaultTombstoneLifetime, objectconfig.TombstoneLifetime(empty)) require.False(t, objectconfig.Put(empty).SkipSessionTokenIssuerVerification()) }) @@ -22,8 +20,6 @@ func TestObjectSection(t *testing.T) { const path = "../../../../config/example/node" fileConfigTest := func(c *config.Config) { - require.Equal(t, 100, objectconfig.Put(c).PoolSizeRemote()) - require.Equal(t, 200, objectconfig.Put(c).PoolSizeLocal()) require.EqualValues(t, 10, objectconfig.TombstoneLifetime(c)) require.True(t, objectconfig.Put(c).SkipSessionTokenIssuerVerification()) } diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 40d3cc1cdc..ad6f4140aa 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -326,7 +326,6 @@ func createPutSvc(c *cfg, keyStorage *util.KeyStorage, irFetcher *cachedIRFetche c, c.cfgNetmap.state, irFetcher, - objectwriter.WithWorkerPools(c.cfgObject.pool.putRemote, c.cfgObject.pool.putLocal), objectwriter.WithLogger(c.log), objectwriter.WithVerifySessionTokenIssuer(!c.cfgObject.skipSessionTokenIssuerVerification), ) diff --git a/config/example/node.env b/config/example/node.env index 2ba432b1b2..aa3c72a91b 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -87,8 +87,6 @@ FROSTFS_REPLICATOR_POOL_SIZE=10 FROSTFS_CONTAINER_LIST_STREAM_BATCH_SIZE=500 # Object service section -FROSTFS_OBJECT_PUT_REMOTE_POOL_SIZE=100 -FROSTFS_OBJECT_PUT_LOCAL_POOL_SIZE=200 FROSTFS_OBJECT_PUT_SKIP_SESSION_TOKEN_ISSUER_VERIFICATION=true FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME=10 FROSTFS_OBJECT_GET_PRIORITY="$attribute:ClusterName $attribute:UN-LOCODE" diff --git a/config/example/node.json b/config/example/node.json index cfde8bcc75..afa815bc3d 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -134,8 +134,6 @@ "tombstone_lifetime": 10 }, "put": { - "remote_pool_size": 100, - "local_pool_size": 200, "skip_session_token_issuer_verification": true }, "get": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 1f8ec843df..f63cc514ba 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -117,8 +117,6 @@ object: delete: tombstone_lifetime: 10 # tombstone "local" lifetime in epochs put: - remote_pool_size: 100 # number of async workers for remote PUT operations - local_pool_size: 200 # number of async workers for local PUT operations skip_session_token_issuer_verification: true # session token issuer verification will be skipped if true get: priority: # list of metrics of nodes for prioritization diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index aef05d5893..b2ab75b7eb 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -406,8 +406,6 @@ Contains object-service related parameters. ```yaml object: - put: - remote_pool_size: 100 get: priority: - $attribute:ClusterName @@ -416,8 +414,6 @@ object: | Parameter | Type | Default value | Description | |-----------------------------|------------|---------------|------------------------------------------------------------------------------------------------| | `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. | -| `put.remote_pool_size` | `int` | `10` | Max pool size for performing remote `PUT` operations. Used by Policer and Replicator services. | -| `put.local_pool_size` | `int` | `10` | Max pool size for performing local `PUT` operations. Used by Policer and Replicator services. | | `get.priority` | `[]string` | | List of metrics of nodes for prioritization. Used for computing response on GET requests. | # `runtime` section diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 6a72644e5d..d48a4da9b7 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -125,7 +125,6 @@ const ( SearchCouldNotWriteObjectIdentifiers = "could not write object identifiers" SearchLocalOperationFailed = "local operation failed" UtilObjectServiceError = "object service error" - UtilCouldNotPushTaskToWorkerPool = "could not push task to worker pool" V2CantCheckIfRequestFromInnerRing = "can't check if request from inner ring" V2CantCheckIfRequestFromContainerNode = "can't check if request from container node" ClientCouldNotRestoreBlockSubscriptionAfterRPCSwitch = "could not restore block subscription after RPC switch" diff --git a/pkg/services/object/common/writer/common.go b/pkg/services/object/common/writer/common.go index dae168baff..1998e96383 100644 --- a/pkg/services/object/common/writer/common.go +++ b/pkg/services/object/common/writer/common.go @@ -79,11 +79,11 @@ func (n *NodeIterator) forEachAddress(ctx context.Context, traverser *placement. continue } - workerPool, isLocal := n.cfg.getWorkerPool(addr.PublicKey()) + isLocal := n.cfg.NetmapKeys.IsLocalKey(addr.PublicKey()) item := new(bool) wg.Add(1) - if err := workerPool.Submit(func() { + go func() { defer wg.Done() err := f(ctx, NodeDescriptor{Local: isLocal, Info: addr}) @@ -95,11 +95,7 @@ func (n *NodeIterator) forEachAddress(ctx context.Context, traverser *placement. traverser.SubmitSuccess() *item = true - }); err != nil { - wg.Done() - svcutil.LogWorkerPoolError(ctx, n.cfg.Logger, "PUT", err) - return true - } + }() // Mark the container node as processed in order to exclude it // in subsequent container broadcast. Note that we don't diff --git a/pkg/services/object/common/writer/ec.go b/pkg/services/object/common/writer/ec.go index 8f269ec217..26a53e3156 100644 --- a/pkg/services/object/common/writer/ec.go +++ b/pkg/services/object/common/writer/ec.go @@ -149,17 +149,7 @@ func (e *ECWriter) relayToContainerNode(ctx context.Context, objID oid.ID, index return fmt.Errorf("could not create SDK client %s: %w", info.AddressGroup(), err) } - completed := make(chan interface{}) - if poolErr := e.Config.RemotePool.Submit(func() { - defer close(completed) - err = e.Relay(ctx, info, c) - }); poolErr != nil { - close(completed) - svcutil.LogWorkerPoolError(ctx, e.Config.Logger, "PUT", poolErr) - return poolErr - } - <-completed - + err = e.Relay(ctx, info, c) if err == nil { return nil } @@ -343,21 +333,11 @@ func (e *ECWriter) putECPartToNode(ctx context.Context, obj *objectSDK.Object, n } func (e *ECWriter) writePartLocal(ctx context.Context, obj *objectSDK.Object) error { - var err error localTarget := LocalTarget{ Storage: e.Config.LocalStore, Container: e.Container, } - completed := make(chan interface{}) - if poolErr := e.Config.LocalPool.Submit(func() { - defer close(completed) - err = localTarget.WriteObject(ctx, obj, e.ObjectMeta) - }); poolErr != nil { - close(completed) - return poolErr - } - <-completed - return err + return localTarget.WriteObject(ctx, obj, e.ObjectMeta) } func (e *ECWriter) writePartRemote(ctx context.Context, obj *objectSDK.Object, node placement.Node) error { @@ -371,15 +351,5 @@ func (e *ECWriter) writePartRemote(ctx context.Context, obj *objectSDK.Object, n nodeInfo: clientNodeInfo, } - var err error - completed := make(chan interface{}) - if poolErr := e.Config.RemotePool.Submit(func() { - defer close(completed) - err = remoteTaget.WriteObject(ctx, obj, e.ObjectMeta) - }); poolErr != nil { - close(completed) - return poolErr - } - <-completed - return err + return remoteTaget.WriteObject(ctx, obj, e.ObjectMeta) } diff --git a/pkg/services/object/common/writer/ec_test.go b/pkg/services/object/common/writer/ec_test.go index b7764661f7..2458e352f2 100644 --- a/pkg/services/object/common/writer/ec_test.go +++ b/pkg/services/object/common/writer/ec_test.go @@ -31,7 +31,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "git.frostfs.info/TrueCloudLab/tzhash/tz" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/panjf2000/ants/v2" "github.com/stretchr/testify/require" ) @@ -131,9 +130,6 @@ func TestECWriter(t *testing.T) { nodeKey, err := keys.NewPrivateKey() require.NoError(t, err) - pool, err := ants.NewPool(4, ants.WithNonblocking(true)) - require.NoError(t, err) - log, err := logger.NewLogger(nil) require.NoError(t, err) @@ -141,7 +137,6 @@ func TestECWriter(t *testing.T) { ecw := ECWriter{ Config: &Config{ NetmapKeys: n, - RemotePool: pool, Logger: log, ClientConstructor: clientConstructor{vectors: ns}, KeyStorage: util.NewKeyStorage(&nodeKey.PrivateKey, nil, nil), diff --git a/pkg/services/object/common/writer/writer.go b/pkg/services/object/common/writer/writer.go index adaf1945b9..d3d2b41b43 100644 --- a/pkg/services/object/common/writer/writer.go +++ b/pkg/services/object/common/writer/writer.go @@ -12,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/policy" objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -52,8 +51,6 @@ type Config struct { NetmapSource netmap.Source - RemotePool, LocalPool util.WorkerPool - NetmapKeys netmap.AnnouncedKeys FormatValidator *object.FormatValidator @@ -69,12 +66,6 @@ type Config struct { type Option func(*Config) -func WithWorkerPools(remote, local util.WorkerPool) Option { - return func(c *Config) { - c.RemotePool, c.LocalPool = remote, local - } -} - func WithLogger(l *logger.Logger) Option { return func(c *Config) { c.Logger = l @@ -87,13 +78,6 @@ func WithVerifySessionTokenIssuer(v bool) Option { } } -func (c *Config) getWorkerPool(pub []byte) (util.WorkerPool, bool) { - if c.NetmapKeys.IsLocalKey(pub) { - return c.LocalPool, true - } - return c.RemotePool, false -} - type Params struct { Config *Config diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index 5cc0a57225..099486b3fd 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -6,7 +6,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" objutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) @@ -27,8 +26,6 @@ func NewService(ks *objutil.KeyStorage, opts ...objectwriter.Option, ) *Service { c := &objectwriter.Config{ - RemotePool: util.NewPseudoWorkerPool(), - LocalPool: util.NewPseudoWorkerPool(), Logger: logger.NewLoggerWrapper(zap.L()), KeyStorage: ks, ClientConstructor: cc, diff --git a/pkg/services/object/util/log.go b/pkg/services/object/util/log.go index 2c1e053ac2..b108262261 100644 --- a/pkg/services/object/util/log.go +++ b/pkg/services/object/util/log.go @@ -17,11 +17,3 @@ func LogServiceError(ctx context.Context, l *logger.Logger, req string, node net zap.Error(err), ) } - -// LogWorkerPoolError writes debug error message of object worker pool to provided logger. -func LogWorkerPoolError(ctx context.Context, l *logger.Logger, req string, err error) { - l.Error(ctx, logs.UtilCouldNotPushTaskToWorkerPool, - zap.String("request", req), - zap.Error(err), - ) -} From f0b2017057841693612ef0e8239443afd230ce47 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Thu, 20 Feb 2025 11:18:02 +0300 Subject: [PATCH 1203/1413] [#1639] go.mod: Update sdk-go and qos Signed-off-by: Aleksey Savchuk --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 23ddad2764..2bfc3abfe7 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 - git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe + git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250213125059-356851eed3bf git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 diff --git a/go.sum b/go.sum index ecd2ab525c..4a7dfd4dc4 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 h1:Mxw1c/8t96vFIUOffl28lFaHKi413oCBfLMGJmF9cFA= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe h1:81gDNdWNLP24oMQukRiCE9R1wGSh0l0dRq3F1W+Oesc= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250128150313-cfbca7fa1dfe/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250213125059-356851eed3bf h1:ik2aMBpTJJpoZe2ffcGShXRkrvny65NEPLVt67KmH/A= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250213125059-356851eed3bf/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4 h1:dOZHuOywvH1ms8U38lDCWpysgkCCeJ02RLI7zDhPcyw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= From 55908865996def33858ca6e7274d0e0e892a9bf1 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 7 Feb 2025 17:23:10 +0300 Subject: [PATCH 1204/1413] [#1639] qos: Add interceptors for limiting active RPCs Signed-off-by: Aleksey Savchuk --- internal/qos/grpc.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/internal/qos/grpc.go b/internal/qos/grpc.go index c253f1e9da..534a1f74b1 100644 --- a/internal/qos/grpc.go +++ b/internal/qos/grpc.go @@ -3,7 +3,9 @@ package qos import ( "context" + "git.frostfs.info/TrueCloudLab/frostfs-qos/limiting" "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" "google.golang.org/grpc" ) @@ -49,3 +51,36 @@ func NewAdjustOutgoingIOTagStreamClientInterceptor() grpc.StreamClientIntercepto return streamer(ctx, desc, cc, method, opts...) } } + +func NewMaxActiveRPCLimiterUnaryServerInterceptor(getLimiter func() limiting.Limiter) grpc.UnaryServerInterceptor { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { + if tag, ok := tagging.IOTagFromContext(ctx); ok && tag == IOTagCritical.String() { + return handler(ctx, req) + } + + release, ok := getLimiter().Acquire(info.FullMethod) + if !ok { + return nil, new(apistatus.ResourceExhausted) + } + defer release() + + return handler(ctx, req) + } +} + +//nolint:contextcheck (grpc.ServerStream manages the context itself) +func NewMaxActiveRPCLimiterStreamServerInterceptor(getLimiter func() limiting.Limiter) grpc.StreamServerInterceptor { + return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + if tag, ok := tagging.IOTagFromContext(ss.Context()); ok && tag == IOTagCritical.String() { + return handler(srv, ss) + } + + release, ok := getLimiter().Acquire(info.FullMethod) + if !ok { + return new(apistatus.ResourceExhausted) + } + defer release() + + return handler(srv, ss) + } +} From dae0949f6eb8af3677f6552f52a00c2fdaa6bf79 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 7 Feb 2025 15:17:37 +0300 Subject: [PATCH 1205/1413] [#1639] node: Support active RPC limiting - Allow configuration of active RPC limits for method groups - Apply RPC limiting for all services except the control service Signed-off-by: Aleksey Savchuk --- cmd/frostfs-node/config.go | 40 ++++++++++++-- cmd/frostfs-node/config/rpc/config.go | 43 +++++++++++++++ cmd/frostfs-node/config/rpc/config_test.go | 53 +++++++++++++++++++ cmd/frostfs-node/config/rpc/testdata/node.env | 3 ++ .../config/rpc/testdata/node.json | 18 +++++++ .../config/rpc/testdata/node.yaml | 8 +++ cmd/frostfs-node/grpc.go | 4 ++ config/example/node.env | 5 ++ config/example/node.json | 17 ++++++ config/example/node.yaml | 10 ++++ docs/storage-node-configuration.md | 21 ++++++++ 11 files changed, 217 insertions(+), 5 deletions(-) create mode 100644 cmd/frostfs-node/config/rpc/config.go create mode 100644 cmd/frostfs-node/config/rpc/config_test.go create mode 100644 cmd/frostfs-node/config/rpc/testdata/node.env create mode 100644 cmd/frostfs-node/config/rpc/testdata/node.json create mode 100644 cmd/frostfs-node/config/rpc/testdata/node.yaml diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 43ec40d1d4..a7aeedc214 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -29,6 +29,7 @@ import ( nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" objectconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/object" replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" + rpcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/rpc" tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" @@ -69,6 +70,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/state" "git.frostfs.info/TrueCloudLab/frostfs-observability/logging/lokicore" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" + "git.frostfs.info/TrueCloudLab/frostfs-qos/limiting" netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -528,6 +530,8 @@ type cfgGRPC struct { maxChunkSize uint64 maxAddrAmount uint64 reconnectTimeout time.Duration + + limiter atomic.Pointer[limiting.SemaphoreLimiter] } func (c *cfgGRPC) append(e string, l net.Listener, s *grpc.Server) { @@ -717,7 +721,7 @@ func initCfg(appCfg *config.Config) *cfg { c.cfgNetmap = initNetmap(appCfg, netState, relayOnly) - c.cfgGRPC = initCfgGRPC() + c.cfgGRPC = initCfgGRPC(appCfg) c.cfgMorph = cfgMorph{ proxyScriptHash: contractsconfig.Proxy(appCfg), @@ -848,14 +852,23 @@ func initFrostfsID(appCfg *config.Config) cfgFrostfsID { } } -func initCfgGRPC() cfgGRPC { +func initCfgGRPC(appCfg *config.Config) (cfg cfgGRPC) { maxChunkSize := uint64(maxMsgSize) * 3 / 4 // 25% to meta, 75% to payload maxAddrAmount := maxChunkSize / addressSize // each address is about 72 bytes - return cfgGRPC{ - maxChunkSize: maxChunkSize, - maxAddrAmount: maxAddrAmount, + var limits []limiting.KeyLimit + for _, l := range rpcconfig.Limits(appCfg) { + limits = append(limits, limiting.KeyLimit{Keys: l.Methods, Limit: l.MaxOps}) } + + limiter, err := limiting.NewSemaphoreLimiter(limits) + fatalOnErr(err) + + cfg.maxChunkSize = maxChunkSize + cfg.maxAddrAmount = maxAddrAmount + cfg.limiter.Store(limiter) + + return } func initCfgObject(appCfg *config.Config) cfgObject { @@ -1392,9 +1405,26 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { components = append(components, dCmp{cmp.name, func() error { return cmp.reload(ctx) }}) } + components = append(components, dCmp{"rpc_limiter", c.reloadLimits}) + return components } +func (c *cfg) reloadLimits() error { + var limits []limiting.KeyLimit + for _, l := range rpcconfig.Limits(c.appCfg) { + limits = append(limits, limiting.KeyLimit{Keys: l.Methods, Limit: l.MaxOps}) + } + + limiter, err := limiting.NewSemaphoreLimiter(limits) + if err != nil { + return err + } + + c.cfgGRPC.limiter.Store(limiter) + return nil +} + func (c *cfg) reloadPools() error { newSize := replicatorconfig.PoolSize(c.appCfg) c.reloadPool(c.cfgObject.pool.replication, newSize, "replicator.pool_size") diff --git a/cmd/frostfs-node/config/rpc/config.go b/cmd/frostfs-node/config/rpc/config.go new file mode 100644 index 0000000000..197990d07b --- /dev/null +++ b/cmd/frostfs-node/config/rpc/config.go @@ -0,0 +1,43 @@ +package rpcconfig + +import ( + "strconv" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" +) + +const ( + subsection = "rpc" + limitsSubsection = "limits" +) + +type LimitConfig struct { + Methods []string + MaxOps int64 +} + +// Limits returns the "limits" config from "rpc" section. +func Limits(c *config.Config) []LimitConfig { + c = c.Sub(subsection).Sub(limitsSubsection) + + var limits []LimitConfig + + for i := uint64(0); ; i++ { + si := strconv.FormatUint(i, 10) + sc := c.Sub(si) + + methods := config.StringSliceSafe(sc, "methods") + if len(methods) == 0 { + break + } + + maxOps := config.IntSafe(sc, "max_ops") + if maxOps == 0 { + panic("no max operations for method group") + } + + limits = append(limits, LimitConfig{methods, maxOps}) + } + + return limits +} diff --git a/cmd/frostfs-node/config/rpc/config_test.go b/cmd/frostfs-node/config/rpc/config_test.go new file mode 100644 index 0000000000..31a837cee2 --- /dev/null +++ b/cmd/frostfs-node/config/rpc/config_test.go @@ -0,0 +1,53 @@ +package rpcconfig + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" + "github.com/stretchr/testify/require" +) + +func TestRPCSection(t *testing.T) { + t.Run("defaults", func(t *testing.T) { + require.Empty(t, Limits(configtest.EmptyConfig())) + }) + + t.Run("correct config", func(t *testing.T) { + const path = "../../../../config/example/node" + + fileConfigTest := func(c *config.Config) { + limits := Limits(c) + require.Len(t, limits, 2) + + limit0 := limits[0] + limit1 := limits[1] + + require.ElementsMatch(t, limit0.Methods, []string{"/neo.fs.v2.object.ObjectService/PutSingle", "/neo.fs.v2.object.ObjectService/Put"}) + require.Equal(t, limit0.MaxOps, int64(1000)) + + require.ElementsMatch(t, limit1.Methods, []string{"/neo.fs.v2.object.ObjectService/Get"}) + require.Equal(t, limit1.MaxOps, int64(10000)) + } + + configtest.ForEachFileType(path, fileConfigTest) + + t.Run("ENV", func(t *testing.T) { + configtest.ForEnvFileType(t, path, fileConfigTest) + }) + }) + + t.Run("no max operations", func(t *testing.T) { + const path = "testdata/node" + + fileConfigTest := func(c *config.Config) { + require.Panics(t, func() { _ = Limits(c) }) + } + + configtest.ForEachFileType(path, fileConfigTest) + + t.Run("ENV", func(t *testing.T) { + configtest.ForEnvFileType(t, path, fileConfigTest) + }) + }) +} diff --git a/cmd/frostfs-node/config/rpc/testdata/node.env b/cmd/frostfs-node/config/rpc/testdata/node.env new file mode 100644 index 0000000000..2fed4c5bcb --- /dev/null +++ b/cmd/frostfs-node/config/rpc/testdata/node.env @@ -0,0 +1,3 @@ +FROSTFS_RPC_LIMITS_0_METHODS="/neo.fs.v2.object.ObjectService/PutSingle /neo.fs.v2.object.ObjectService/Put" +FROSTFS_RPC_LIMITS_1_METHODS="/neo.fs.v2.object.ObjectService/Get" +FROSTFS_RPC_LIMITS_1_MAX_OPS=10000 diff --git a/cmd/frostfs-node/config/rpc/testdata/node.json b/cmd/frostfs-node/config/rpc/testdata/node.json new file mode 100644 index 0000000000..6156aa71d0 --- /dev/null +++ b/cmd/frostfs-node/config/rpc/testdata/node.json @@ -0,0 +1,18 @@ +{ + "rpc": { + "limits": [ + { + "methods": [ + "/neo.fs.v2.object.ObjectService/PutSingle", + "/neo.fs.v2.object.ObjectService/Put" + ] + }, + { + "methods": [ + "/neo.fs.v2.object.ObjectService/Get" + ], + "max_ops": 10000 + } + ] + } +} diff --git a/cmd/frostfs-node/config/rpc/testdata/node.yaml b/cmd/frostfs-node/config/rpc/testdata/node.yaml new file mode 100644 index 0000000000..e50b7ae935 --- /dev/null +++ b/cmd/frostfs-node/config/rpc/testdata/node.yaml @@ -0,0 +1,8 @@ +rpc: + limits: + - methods: + - /neo.fs.v2.object.ObjectService/PutSingle + - /neo.fs.v2.object.ObjectService/Put + - methods: + - /neo.fs.v2.object.ObjectService/Get + max_ops: 10000 diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index 4d679e4cc5..e1a273ce48 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -9,9 +9,11 @@ import ( grpcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/grpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + qosInternal "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-qos/limiting" qos "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "go.uber.org/zap" "google.golang.org/grpc" @@ -134,11 +136,13 @@ func getGrpcServerOpts(ctx context.Context, c *cfg, sc *grpcconfig.Config) ([]gr qos.NewUnaryServerInterceptor(), metrics.NewUnaryServerInterceptor(), tracing.NewUnaryServerInterceptor(), + qosInternal.NewMaxActiveRPCLimiterUnaryServerInterceptor(func() limiting.Limiter { return c.cfgGRPC.limiter.Load() }), ), grpc.ChainStreamInterceptor( qos.NewStreamServerInterceptor(), metrics.NewStreamServerInterceptor(), tracing.NewStreamServerInterceptor(), + qosInternal.NewMaxActiveRPCLimiterStreamServerInterceptor(func() limiting.Limiter { return c.cfgGRPC.limiter.Load() }), ), } diff --git a/config/example/node.env b/config/example/node.env index aa3c72a91b..2ebef181a5 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -91,6 +91,11 @@ FROSTFS_OBJECT_PUT_SKIP_SESSION_TOKEN_ISSUER_VERIFICATION=true FROSTFS_OBJECT_DELETE_TOMBSTONE_LIFETIME=10 FROSTFS_OBJECT_GET_PRIORITY="$attribute:ClusterName $attribute:UN-LOCODE" +FROSTFS_RPC_LIMITS_0_METHODS="/neo.fs.v2.object.ObjectService/PutSingle /neo.fs.v2.object.ObjectService/Put" +FROSTFS_RPC_LIMITS_0_MAX_OPS=1000 +FROSTFS_RPC_LIMITS_1_METHODS="/neo.fs.v2.object.ObjectService/Get" +FROSTFS_RPC_LIMITS_1_MAX_OPS=10000 + # Storage engine section FROSTFS_STORAGE_SHARD_POOL_SIZE=15 FROSTFS_STORAGE_SHARD_RO_ERROR_THRESHOLD=100 diff --git a/config/example/node.json b/config/example/node.json index afa815bc3d..0ed72effce 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -140,6 +140,23 @@ "priority": ["$attribute:ClusterName", "$attribute:UN-LOCODE"] } }, + "rpc": { + "limits": [ + { + "methods": [ + "/neo.fs.v2.object.ObjectService/PutSingle", + "/neo.fs.v2.object.ObjectService/Put" + ], + "max_ops": 1000 + }, + { + "methods": [ + "/neo.fs.v2.object.ObjectService/Get" + ], + "max_ops": 10000 + } + ] + }, "storage": { "shard_pool_size": 15, "shard_ro_error_threshold": 100, diff --git a/config/example/node.yaml b/config/example/node.yaml index f63cc514ba..6b810653e5 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -123,6 +123,16 @@ object: - $attribute:ClusterName - $attribute:UN-LOCODE +rpc: + limits: + - methods: + - /neo.fs.v2.object.ObjectService/PutSingle + - /neo.fs.v2.object.ObjectService/Put + max_ops: 1000 + - methods: + - /neo.fs.v2.object.ObjectService/Get + max_ops: 10000 + storage: # note: shard configuration can be omitted for relay node (see `node.relay`) shard_pool_size: 15 # size of per-shard worker pools used for PUT operations diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index b2ab75b7eb..1eb5437ba8 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -416,6 +416,27 @@ object: | `delete.tombstone_lifetime` | `int` | `5` | Tombstone lifetime for removed objects in epochs. | | `get.priority` | `[]string` | | List of metrics of nodes for prioritization. Used for computing response on GET requests. | + +# `rpc` section +Contains limits on the number of active RPC for specified method(s). + +```yaml +rpc: + limits: + - methods: + - /neo.fs.v2.object.ObjectService/PutSingle + - /neo.fs.v2.object.ObjectService/Put + max_ops: 1000 + - methods: + - /neo.fs.v2.object.ObjectService/Get + max_ops: 10000 +``` + +| Parameter | Type | Default value | Description | +|------------------|------------|---------------|--------------------------------------------------------------| +| `limits.max_ops` | `int` | | Maximum number of active RPC allowed for the given method(s) | +| `limits.methods` | `[]string` | | List of RPC methods sharing the given limit | + # `runtime` section Contains runtime parameters. From 92ab58984b6bbe7722ef8306ca9718e9543d5d9c Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 28 Feb 2025 15:07:24 +0300 Subject: [PATCH 1206/1413] [#1658] node: Simplify RPC limiter initialization - Move all initialization logic to one place - Initialize the limiter after all RPC services are registered to be able to validate that configured limits match the methods registered earlier Signed-off-by: Aleksey Savchuk --- cmd/frostfs-node/config.go | 31 +++---------------------------- cmd/frostfs-node/grpc.go | 17 +++++++++++++++++ cmd/frostfs-node/main.go | 2 ++ 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index a7aeedc214..3e1bfb4f22 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -29,7 +29,6 @@ import ( nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" objectconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/object" replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" - rpcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/rpc" tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" @@ -721,7 +720,7 @@ func initCfg(appCfg *config.Config) *cfg { c.cfgNetmap = initNetmap(appCfg, netState, relayOnly) - c.cfgGRPC = initCfgGRPC(appCfg) + c.cfgGRPC = initCfgGRPC() c.cfgMorph = cfgMorph{ proxyScriptHash: contractsconfig.Proxy(appCfg), @@ -852,21 +851,12 @@ func initFrostfsID(appCfg *config.Config) cfgFrostfsID { } } -func initCfgGRPC(appCfg *config.Config) (cfg cfgGRPC) { +func initCfgGRPC() (cfg cfgGRPC) { maxChunkSize := uint64(maxMsgSize) * 3 / 4 // 25% to meta, 75% to payload maxAddrAmount := maxChunkSize / addressSize // each address is about 72 bytes - var limits []limiting.KeyLimit - for _, l := range rpcconfig.Limits(appCfg) { - limits = append(limits, limiting.KeyLimit{Keys: l.Methods, Limit: l.MaxOps}) - } - - limiter, err := limiting.NewSemaphoreLimiter(limits) - fatalOnErr(err) - cfg.maxChunkSize = maxChunkSize cfg.maxAddrAmount = maxAddrAmount - cfg.limiter.Store(limiter) return } @@ -1405,26 +1395,11 @@ func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { components = append(components, dCmp{cmp.name, func() error { return cmp.reload(ctx) }}) } - components = append(components, dCmp{"rpc_limiter", c.reloadLimits}) + components = append(components, dCmp{"rpc_limiter", func() error { return initRPCLimiter(c) }}) return components } -func (c *cfg) reloadLimits() error { - var limits []limiting.KeyLimit - for _, l := range rpcconfig.Limits(c.appCfg) { - limits = append(limits, limiting.KeyLimit{Keys: l.Methods, Limit: l.MaxOps}) - } - - limiter, err := limiting.NewSemaphoreLimiter(limits) - if err != nil { - return err - } - - c.cfgGRPC.limiter.Store(limiter) - return nil -} - func (c *cfg) reloadPools() error { newSize := replicatorconfig.PoolSize(c.appCfg) c.reloadPool(c.cfgObject.pool.replication, newSize, "replicator.pool_size") diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index e1a273ce48..9ea3dd8a2b 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -4,10 +4,12 @@ import ( "context" "crypto/tls" "errors" + "fmt" "net" "time" grpcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/grpc" + rpcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/rpc" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" qosInternal "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" @@ -231,3 +233,18 @@ func stopGRPC(ctx context.Context, name string, s *grpc.Server, l *logger.Logger l.Info(ctx, logs.FrostFSNodeGRPCServerStoppedSuccessfully) } + +func initRPCLimiter(c *cfg) error { + var limits []limiting.KeyLimit + for _, l := range rpcconfig.Limits(c.appCfg) { + limits = append(limits, limiting.KeyLimit{Keys: l.Methods, Limit: l.MaxOps}) + } + + limiter, err := limiting.NewSemaphoreLimiter(limits) + if err != nil { + return fmt.Errorf("create RPC limiter: %w", err) + } + + c.cfgGRPC.limiter.Store(limiter) + return nil +} diff --git a/cmd/frostfs-node/main.go b/cmd/frostfs-node/main.go index b53bd88232..0228d2a10e 100644 --- a/cmd/frostfs-node/main.go +++ b/cmd/frostfs-node/main.go @@ -117,6 +117,8 @@ func initApp(ctx context.Context, c *cfg) { initAndLog(ctx, c, "apemanager", initAPEManagerService) initAndLog(ctx, c, "control", func(c *cfg) { initControlService(ctx, c) }) + initAndLog(ctx, c, "RPC limiter", func(c *cfg) { fatalOnErr(initRPCLimiter(c)) }) + initAndLog(ctx, c, "morph notifications", func(c *cfg) { listenMorphNotifications(ctx, c) }) } From c66027103910ab413a51dede50f64f767ef582ae Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 28 Feb 2025 15:14:15 +0300 Subject: [PATCH 1207/1413] [#1658] node: Validate RPC limiter configuration Validate that configured limits match the methods registered earlier. Signed-off-by: Aleksey Savchuk --- cmd/frostfs-node/grpc.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/cmd/frostfs-node/grpc.go b/cmd/frostfs-node/grpc.go index 9ea3dd8a2b..6b6d447501 100644 --- a/cmd/frostfs-node/grpc.go +++ b/cmd/frostfs-node/grpc.go @@ -240,6 +240,10 @@ func initRPCLimiter(c *cfg) error { limits = append(limits, limiting.KeyLimit{Keys: l.Methods, Limit: l.MaxOps}) } + if err := validateRPCLimits(c, limits); err != nil { + return fmt.Errorf("validate RPC limits: %w", err) + } + limiter, err := limiting.NewSemaphoreLimiter(limits) if err != nil { return fmt.Errorf("create RPC limiter: %w", err) @@ -248,3 +252,35 @@ func initRPCLimiter(c *cfg) error { c.cfgGRPC.limiter.Store(limiter) return nil } + +func validateRPCLimits(c *cfg, limits []limiting.KeyLimit) error { + availableMethods := getAvailableMethods(c.cfgGRPC.servers) + for _, limit := range limits { + for _, method := range limit.Keys { + if _, ok := availableMethods[method]; !ok { + return fmt.Errorf("set limit on an unknown method %q", method) + } + } + } + return nil +} + +func getAvailableMethods(servers []grpcServer) map[string]struct{} { + res := make(map[string]struct{}) + for _, server := range servers { + for _, method := range getMethodsForServer(server.Server) { + res[method] = struct{}{} + } + } + return res +} + +func getMethodsForServer(server *grpc.Server) []string { + var res []string + for service, info := range server.GetServiceInfo() { + for _, method := range info.Methods { + res = append(res, fmt.Sprintf("/%s/%s", service, method.Name)) + } + } + return res +} From 0991077cb364c94e40f6838035acab4754b4d8af Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Feb 2025 14:51:35 +0300 Subject: [PATCH 1208/1413] [#1657] engine: Fix data race in evacuation tests Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/evacuate_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index b9d7888e7c..45c4b696b8 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -475,7 +475,7 @@ func TestEvacuateObjectsAsync(t *testing.T) { eg, egCtx := errgroup.WithContext(context.Background()) eg.Go(func() error { require.NoError(t, e.Evacuate(egCtx, prm), "first evacuation failed") - st = testWaitForEvacuationCompleted(t, e) + st := testWaitForEvacuationCompleted(t, e) require.Equal(t, uint64(3), st.ObjectsEvacuated(), "invalid final count") return nil }) From 98d61250292bf3304043da4fe4007dc7bff9c99f Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 4 Feb 2025 18:20:48 +0300 Subject: [PATCH 1209/1413] [#1636] config: Add `shard.limits` config Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 12 ++ cmd/frostfs-node/config/engine/config_test.go | 86 ++++++++++++ .../config/engine/shard/config.go | 9 ++ .../config/engine/shard/limits/config.go | 130 ++++++++++++++++++ config/example/node.env | 41 ++++++ config/example/node.json | 70 ++++++++++ config/example/node.yaml | 46 +++++++ docs/storage-node-configuration.md | 59 ++++++++ internal/qos/validate.go | 92 +++++++++++++ 9 files changed, 545 insertions(+) create mode 100644 cmd/frostfs-node/config/engine/shard/limits/config.go create mode 100644 internal/qos/validate.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 3e1bfb4f22..004c8f128b 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -33,6 +33,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/chainbase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" @@ -277,6 +278,9 @@ func (a *applicationConfiguration) updateShardConfig(c *config.Config, oldConfig a.setMetabaseConfig(&newConfig, oldConfig) a.setGCConfig(&newConfig, oldConfig) + if err := a.setLimits(&newConfig, oldConfig); err != nil { + return err + } a.EngineCfg.shards = append(a.EngineCfg.shards, newConfig) @@ -370,6 +374,14 @@ func (a *applicationConfiguration) setGCConfig(newConfig *shardCfg, oldConfig *s newConfig.gcCfg.expiredCollectorWorkerCount = gcCfg.ExpiredCollectorWorkerCount() } +func (a *applicationConfiguration) setLimits(newConfig *shardCfg, oldConfig *shardconfig.Config) error { + limitsConfig := oldConfig.Limits() + if err := qos.ValidateConfig(limitsConfig); err != nil { + return err + } + return nil +} + // internals contains application-specific internals that are created // on application startup and are shared b/w the components during // the application life cycle. diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index ef6380a620..b912b5d7df 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -11,6 +11,7 @@ import ( blobovniczaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza" fstreeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/fstree" gcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/gc" + limitsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" piloramaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/pilorama" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/writecache" configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" @@ -76,6 +77,7 @@ func TestEngineSection(t *testing.T) { ss := blob.Storages() pl := sc.Pilorama() gc := sc.GC() + limits := sc.Limits() switch num { case 0: @@ -134,6 +136,75 @@ func TestEngineSection(t *testing.T) { require.Equal(t, false, sc.RefillMetabase()) require.Equal(t, mode.ReadOnly, sc.Mode()) require.Equal(t, 100, sc.RefillMetabaseWorkersCount()) + + readLimits := limits.Read() + writeLimits := limits.Write() + require.Equal(t, 30*time.Second, readLimits.IdleTimeout) + require.Equal(t, int64(10_000), readLimits.MaxRunningOps) + require.Equal(t, int64(1_000), readLimits.MaxWaitingOps) + require.Equal(t, 45*time.Second, writeLimits.IdleTimeout) + require.Equal(t, int64(1_000), writeLimits.MaxRunningOps) + require.Equal(t, int64(100), writeLimits.MaxWaitingOps) + require.ElementsMatch(t, readLimits.Tags, + []limitsconfig.IOTagConfig{ + { + Tag: "internal", + Weight: toPtr(20), + ReservedOps: toPtr(1000), + LimitOps: toPtr(0), + }, + { + Tag: "client", + Weight: toPtr(70), + ReservedOps: toPtr(10000), + }, + { + Tag: "background", + Weight: toPtr(5), + LimitOps: toPtr(10000), + ReservedOps: toPtr(0), + }, + { + Tag: "writecache", + Weight: toPtr(5), + LimitOps: toPtr(25000), + }, + { + Tag: "policer", + Weight: toPtr(5), + LimitOps: toPtr(25000), + }, + }) + require.ElementsMatch(t, writeLimits.Tags, + []limitsconfig.IOTagConfig{ + { + Tag: "internal", + Weight: toPtr(200), + ReservedOps: toPtr(100), + LimitOps: toPtr(0), + }, + { + Tag: "client", + Weight: toPtr(700), + ReservedOps: toPtr(1000), + }, + { + Tag: "background", + Weight: toPtr(50), + LimitOps: toPtr(1000), + ReservedOps: toPtr(0), + }, + { + Tag: "writecache", + Weight: toPtr(50), + LimitOps: toPtr(2500), + }, + { + Tag: "policer", + Weight: toPtr(50), + LimitOps: toPtr(2500), + }, + }) case 1: require.Equal(t, "tmp/1/blob/pilorama.db", pl.Path()) require.Equal(t, fs.FileMode(0o644), pl.Perm()) @@ -188,6 +259,17 @@ func TestEngineSection(t *testing.T) { require.Equal(t, true, sc.RefillMetabase()) require.Equal(t, mode.ReadWrite, sc.Mode()) require.Equal(t, shardconfig.RefillMetabaseWorkersCountDefault, sc.RefillMetabaseWorkersCount()) + + readLimits := limits.Read() + writeLimits := limits.Write() + require.Equal(t, limitsconfig.DefaultIdleTimeout, readLimits.IdleTimeout) + require.Equal(t, limitsconfig.NoLimit, readLimits.MaxRunningOps) + require.Equal(t, limitsconfig.NoLimit, readLimits.MaxWaitingOps) + require.Equal(t, limitsconfig.DefaultIdleTimeout, writeLimits.IdleTimeout) + require.Equal(t, limitsconfig.NoLimit, writeLimits.MaxRunningOps) + require.Equal(t, limitsconfig.NoLimit, writeLimits.MaxWaitingOps) + require.Equal(t, 0, len(readLimits.Tags)) + require.Equal(t, 0, len(writeLimits.Tags)) } return nil }) @@ -201,3 +283,7 @@ func TestEngineSection(t *testing.T) { configtest.ForEnvFileType(t, path, fileConfigTest) }) } + +func toPtr(v float64) *float64 { + return &v +} diff --git a/cmd/frostfs-node/config/engine/shard/config.go b/cmd/frostfs-node/config/engine/shard/config.go index 0620c9f630..e50d56b955 100644 --- a/cmd/frostfs-node/config/engine/shard/config.go +++ b/cmd/frostfs-node/config/engine/shard/config.go @@ -4,6 +4,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" blobstorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor" gcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/gc" + limitsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" metabaseconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/metabase" piloramaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/pilorama" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/writecache" @@ -125,6 +126,14 @@ func (x *Config) GC() *gcconfig.Config { ) } +// Limits returns "limits" subsection as a limitsconfig.Config. +func (x *Config) Limits() *limitsconfig.Config { + return limitsconfig.From( + (*config.Config)(x). + Sub("limits"), + ) +} + // RefillMetabase returns the value of "resync_metabase" config parameter. // // Returns false if the value is not a valid bool. diff --git a/cmd/frostfs-node/config/engine/shard/limits/config.go b/cmd/frostfs-node/config/engine/shard/limits/config.go new file mode 100644 index 0000000000..b9b5c43824 --- /dev/null +++ b/cmd/frostfs-node/config/engine/shard/limits/config.go @@ -0,0 +1,130 @@ +package limits + +import ( + "math" + "strconv" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + "github.com/spf13/cast" +) + +const ( + NoLimit int64 = math.MaxInt64 + DefaultIdleTimeout = 5 * time.Minute +) + +// From wraps config section into Config. +func From(c *config.Config) *Config { + return (*Config)(c) +} + +// Config is a wrapper over the config section +// which provides access to Shard's limits configurations. +type Config config.Config + +// Read returns the value of "read" limits config section. +func (x *Config) Read() OpConfig { + return x.parse("read") +} + +// Write returns the value of "write" limits config section. +func (x *Config) Write() OpConfig { + return x.parse("write") +} + +func (x *Config) parse(sub string) OpConfig { + c := (*config.Config)(x).Sub(sub) + var result OpConfig + + if s := config.Int(c, "max_waiting_ops"); s > 0 { + result.MaxWaitingOps = s + } else { + result.MaxWaitingOps = NoLimit + } + + if s := config.Int(c, "max_running_ops"); s > 0 { + result.MaxRunningOps = s + } else { + result.MaxRunningOps = NoLimit + } + + if s := config.DurationSafe(c, "idle_timeout"); s > 0 { + result.IdleTimeout = s + } else { + result.IdleTimeout = DefaultIdleTimeout + } + + result.Tags = tags(c) + + return result +} + +type OpConfig struct { + // MaxWaitingOps returns the value of "max_waiting_ops" config parameter. + // + // Equals NoLimit if the value is not a positive number. + MaxWaitingOps int64 + // MaxRunningOps returns the value of "max_running_ops" config parameter. + // + // Equals NoLimit if the value is not a positive number. + MaxRunningOps int64 + // IdleTimeout returns the value of "idle_timeout" config parameter. + // + // Equals DefaultIdleTimeout if the value is not a valid duration. + IdleTimeout time.Duration + // Tags returns the value of "tags" config parameter. + // + // Equals nil if the value is not a valid tags config slice. + Tags []IOTagConfig +} + +type IOTagConfig struct { + Tag string + Weight *float64 + LimitOps *float64 + ReservedOps *float64 +} + +func tags(c *config.Config) []IOTagConfig { + c = c.Sub("tags") + var result []IOTagConfig + for i := 0; ; i++ { + tag := config.String(c, strconv.Itoa(i)+".tag") + if tag == "" { + return result + } + + var tagConfig IOTagConfig + tagConfig.Tag = tag + + v := c.Value(strconv.Itoa(i) + ".weight") + if v != nil { + w, err := cast.ToFloat64E(v) + panicOnErr(err) + tagConfig.Weight = &w + } + + v = c.Value(strconv.Itoa(i) + ".limit_ops") + if v != nil { + l, err := cast.ToFloat64E(v) + panicOnErr(err) + tagConfig.LimitOps = &l + } + + v = c.Value(strconv.Itoa(i) + ".reserved_ops") + if v != nil { + r, err := cast.ToFloat64E(v) + panicOnErr(err) + tagConfig.ReservedOps = &r + } + + result = append(result, tagConfig) + } +} + +func panicOnErr(err error) { + if err != nil { + panic(err) + } +} diff --git a/config/example/node.env b/config/example/node.env index 2ebef181a5..9bd6453447 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -157,6 +157,47 @@ FROSTFS_STORAGE_SHARD_0_GC_REMOVER_SLEEP_INTERVAL=2m FROSTFS_STORAGE_SHARD_0_GC_EXPIRED_COLLECTOR_BATCH_SIZE=1500 #### Limit of concurrent workers collecting expired objects by the garbage collector FROSTFS_STORAGE_SHARD_0_GC_EXPIRED_COLLECTOR_WORKER_COUNT=15 +#### Limits config +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_MAX_RUNNING_OPS=10000 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_MAX_WAITING_OPS=1000 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_MAX_RUNNING_OPS=1000 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_MAX_WAITING_OPS=100 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_IDLE_TIMEOUT=45s +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_IDLE_TIMEOUT=30s +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_0_TAG=internal +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_0_WEIGHT=20 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_0_LIMIT_OPS=0 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_0_RESERVED_OPS=1000 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_1_TAG=client +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_1_WEIGHT=70 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_1_RESERVED_OPS=10000 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_2_TAG=background +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_2_WEIGHT=5 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_2_LIMIT_OPS=10000 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_2_RESERVED_OPS=0 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_3_TAG=writecache +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_3_WEIGHT=5 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_3_LIMIT_OPS=25000 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_TAG=policer +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_WEIGHT=5 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_LIMIT_OPS=25000 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_TAG=internal +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_WEIGHT=200 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_LIMIT_OPS=0 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_RESERVED_OPS=100 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_1_TAG=client +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_1_WEIGHT=700 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_1_RESERVED_OPS=1000 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_2_TAG=background +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_2_WEIGHT=50 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_2_LIMIT_OPS=1000 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_2_RESERVED_OPS=0 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_3_TAG=writecache +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_3_WEIGHT=50 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_3_LIMIT_OPS=2500 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_4_TAG=policer +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_4_WEIGHT=50 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_4_LIMIT_OPS=2500 ## 1 shard ### Flag to refill Metabase from BlobStor diff --git a/config/example/node.json b/config/example/node.json index 0ed72effce..6b799b3189 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -221,6 +221,76 @@ "remover_sleep_interval": "2m", "expired_collector_batch_size": 1500, "expired_collector_worker_count": 15 + }, + "limits": { + "read": { + "max_running_ops": 10000, + "max_waiting_ops": 1000, + "idle_timeout": "30s", + "tags": [ + { + "tag": "internal", + "weight": 20, + "limit_ops": 0, + "reserved_ops": 1000 + }, + { + "tag": "client", + "weight": 70, + "reserved_ops": 10000 + }, + { + "tag": "background", + "weight": 5, + "limit_ops": 10000, + "reserved_ops": 0 + }, + { + "tag": "writecache", + "weight": 5, + "limit_ops": 25000 + }, + { + "tag": "policer", + "weight": 5, + "limit_ops": 25000 + } + ] + }, + "write": { + "max_running_ops": 1000, + "max_waiting_ops": 100, + "idle_timeout": "45s", + "tags": [ + { + "tag": "internal", + "weight": 200, + "limit_ops": 0, + "reserved_ops": 100 + }, + { + "tag": "client", + "weight": 700, + "reserved_ops": 1000 + }, + { + "tag": "background", + "weight": 50, + "limit_ops": 1000, + "reserved_ops": 0 + }, + { + "tag": "writecache", + "weight": 50, + "limit_ops": 2500 + }, + { + "tag": "policer", + "weight": 50, + "limit_ops": 2500 + } + ] + } } }, "1": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 6b810653e5..2552a419ca 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -227,6 +227,52 @@ storage: expired_collector_batch_size: 1500 # number of objects to be marked expired by the garbage collector expired_collector_worker_count: 15 # number of concurrent workers collecting expired objects by the garbage collector + limits: + read: + max_running_ops: 10000 + max_waiting_ops: 1000 + idle_timeout: 30s + tags: + - tag: internal + weight: 20 + limit_ops: 0 + reserved_ops: 1000 + - tag: client + weight: 70 + reserved_ops: 10000 + - tag: background + weight: 5 + limit_ops: 10000 + reserved_ops: 0 + - tag: writecache + weight: 5 + limit_ops: 25000 + - tag: policer + weight: 5 + limit_ops: 25000 + write: + max_running_ops: 1000 + max_waiting_ops: 100 + idle_timeout: 45s + tags: + - tag: internal + weight: 200 + limit_ops: 0 + reserved_ops: 100 + - tag: client + weight: 700 + reserved_ops: 1000 + - tag: background + weight: 50 + limit_ops: 1000 + reserved_ops: 0 + - tag: writecache + weight: 50 + limit_ops: 2500 + - tag: policer + weight: 50 + limit_ops: 2500 + 1: writecache: path: tmp/1/cache # write-cache root directory diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 1eb5437ba8..271cc6532c 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -195,6 +195,7 @@ The following table describes configuration for each shard. | `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | | `small_object_size` | `size` | `1M` | Maximum size of an object stored in blobovnicza tree. | | `gc` | [GC config](#gc-subsection) | | GC configuration. | +| `limits` | [Shard limits config](#limits-subsection) | | Shard limits configuration. | ### `blobstor` subsection @@ -301,6 +302,64 @@ writecache: | `flush_worker_count` | `int` | `20` | Amount of background workers that move data from the writecache to the blobstor. | | `max_flushing_objects_size` | `size` | `512M` | Max total size of background flushing objects. | +### `limits` subsection + +```yaml +limits: + max_read_running_ops: 10000 + max_read_waiting_ops: 1000 + max_write_running_ops: 1000 + max_write_waiting_ops: 100 + read: + - tag: internal + weight: 20 + limit_ops: 0 + reserved_ops: 1000 + - tag: client + weight: 70 + reserved_ops: 10000 + - tag: background + weight: 5 + limit_ops: 10000 + reserved_ops: 0 + - tag: writecache + weight: 5 + limit_ops: 25000 + - tag: policer + weight: 5 + limit_ops: 25000 + write: + - tag: internal + weight: 200 + limit_ops: 0 + reserved_ops: 100 + - tag: client + weight: 700 + reserved_ops: 1000 + - tag: background + weight: 50 + limit_ops: 1000 + reserved_ops: 0 + - tag: writecache + weight: 50 + limit_ops: 2500 + - tag: policer + weight: 50 + limit_ops: 2500 +``` + +| Parameter | Type | Default value | Description | +| ----------------------- | -------- | -------------- | --------------------------------------------------------------------------------------------------------------- | +| `max_read_running_ops` | `int` | 0 (no limit) | The maximum number of runnig read operations. | +| `max_read_waiting_ops` | `int` | 0 (no limit) | The maximum number of waiting read operations. | +| `max_write_running_ops` | `int` | 0 (no limit) | The maximum number of running write operations. | +| `max_write_waiting_ops` | `int` | 0 (no limit) | The maximum number of running write operations. | +| `read` | `[]tag` | empty | Array of shard read settings for tags. | +| `write` | `[]tag` | empty | Array of shard write settings for tags. | +| `tag.tag` | `string` | empty | Tag name. Allowed values: `client`, `internal`, `background`, `writecache`, `policer`. | +| `tag.weight` | `float` | 0 (no weight) | Weight for queries with the specified tag. Weights must be specified for all tags or not specified for any one. | +| `tag.limit_ops` | `float` | 0 (no limit) | Operations per second rate limit for queries with the specified tag. | +| `tag.reserved_ops` | `float` | 0 (no reserve) | Reserved operations per second rate for queries with the specified tag. | # `node` section diff --git a/internal/qos/validate.go b/internal/qos/validate.go new file mode 100644 index 0000000000..afced345b2 --- /dev/null +++ b/internal/qos/validate.go @@ -0,0 +1,92 @@ +package qos + +import ( + "errors" + "fmt" + "math" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" +) + +var errWeightsMustBeSpecified = errors.New("invalid weights: weights must be specified for all tags or not specified for any") + +type tagConfig struct { + Shares, Limit, Reserved *float64 +} + +func ValidateConfig(c *limits.Config) error { + if err := validateOpConfig(c.Read()); err != nil { + return fmt.Errorf("limits 'read' section validation error: %w", err) + } + if err := validateOpConfig(c.Write()); err != nil { + return fmt.Errorf("limits 'write' section validation error: %w", err) + } + return nil +} + +func validateOpConfig(c limits.OpConfig) error { + if c.MaxRunningOps <= 0 { + return fmt.Errorf("invalid 'max_running_ops = %d': must be greater than zero", c.MaxRunningOps) + } + if c.MaxWaitingOps <= 0 { + return fmt.Errorf("invalid 'max_waiting_ops = %d': must be greater than zero", c.MaxWaitingOps) + } + if c.IdleTimeout <= 0 { + return fmt.Errorf("invalid 'idle_timeout = %s': must be greater than zero", c.IdleTimeout.String()) + } + if err := validateTags(c.Tags); err != nil { + return fmt.Errorf("'tags' config section validation error: %w", err) + } + return nil +} + +func validateTags(configTags []limits.IOTagConfig) error { + tags := map[IOTag]tagConfig{ + IOTagClient: {}, + IOTagInternal: {}, + IOTagBackground: {}, + IOTagWritecache: {}, + IOTagPolicer: {}, + } + for _, t := range configTags { + tag, err := FromRawString(t.Tag) + if err != nil { + return fmt.Errorf("invalid tag %s: %w", t.Tag, err) + } + if _, ok := tags[tag]; !ok { + return fmt.Errorf("tag %s is not configurable", t.Tag) + } + tags[tag] = tagConfig{ + Shares: t.Weight, + Limit: t.LimitOps, + Reserved: t.ReservedOps, + } + } + idx := 0 + var shares float64 + for t, v := range tags { + if idx == 0 { + idx++ + shares = float64Value(v.Shares) + } else if (shares != 0 && float64Value(v.Shares) == 0) || (shares == 0 && float64Value(v.Shares) != 0) { + return errWeightsMustBeSpecified + } + if float64Value(v.Shares) < 0 || math.IsNaN(float64Value(v.Shares)) { + return fmt.Errorf("invalid weight for tag %s: must be positive value", t.String()) + } + if float64Value(v.Limit) < 0 || math.IsNaN(float64Value(v.Limit)) { + return fmt.Errorf("invalid limit_ops for tag %s: must be positive value", t.String()) + } + if float64Value(v.Reserved) < 0 || math.IsNaN(float64Value(v.Reserved)) { + return fmt.Errorf("invalid reserved_ops for tag %s: must be positive value", t.String()) + } + } + return nil +} + +func float64Value(f *float64) float64 { + if f == nil { + return 0.0 + } + return *f +} From 92a67a6716723f81dabb4f809ff040ef7014903a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 5 Feb 2025 12:31:01 +0300 Subject: [PATCH 1210/1413] [#1636] qos: Add Limiter Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 12 +++- internal/assert/cond.go | 9 +++ internal/qos/limiter.go | 132 +++++++++++++++++++++++++++++++++++++ internal/qos/validate.go | 11 +++- 4 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 internal/assert/cond.go create mode 100644 internal/qos/limiter.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 004c8f128b..c625a041f7 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -136,6 +136,7 @@ type shardCfg struct { refillMetabase bool refillMetabaseWorkersCount int mode shardmode.Mode + limiter qos.Limiter metaCfg struct { path string @@ -278,7 +279,7 @@ func (a *applicationConfiguration) updateShardConfig(c *config.Config, oldConfig a.setMetabaseConfig(&newConfig, oldConfig) a.setGCConfig(&newConfig, oldConfig) - if err := a.setLimits(&newConfig, oldConfig); err != nil { + if err := a.setLimiter(&newConfig, oldConfig); err != nil { return err } @@ -374,11 +375,16 @@ func (a *applicationConfiguration) setGCConfig(newConfig *shardCfg, oldConfig *s newConfig.gcCfg.expiredCollectorWorkerCount = gcCfg.ExpiredCollectorWorkerCount() } -func (a *applicationConfiguration) setLimits(newConfig *shardCfg, oldConfig *shardconfig.Config) error { +func (a *applicationConfiguration) setLimiter(newConfig *shardCfg, oldConfig *shardconfig.Config) error { limitsConfig := oldConfig.Limits() - if err := qos.ValidateConfig(limitsConfig); err != nil { + limiter, err := qos.NewLimiter(limitsConfig) + if err != nil { return err } + if newConfig.limiter != nil { + newConfig.limiter.Close() + } + newConfig.limiter = limiter return nil } diff --git a/internal/assert/cond.go b/internal/assert/cond.go new file mode 100644 index 0000000000..701036fa87 --- /dev/null +++ b/internal/assert/cond.go @@ -0,0 +1,9 @@ +package assert + +import "strings" + +func True(cond bool, details ...string) { + if !cond { + panic(strings.Join(details, " ")) + } +} diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go new file mode 100644 index 0000000000..d2a1919f1c --- /dev/null +++ b/internal/qos/limiter.go @@ -0,0 +1,132 @@ +package qos + +import ( + "context" + "fmt" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" + "git.frostfs.info/TrueCloudLab/frostfs-qos/scheduling" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" +) + +const ( + defaultIdleTimeout time.Duration = 0 + defaultShare float64 = 1.0 +) + +type ReleaseFunc scheduling.ReleaseFunc + +type Limiter interface { + ReadRequest(context.Context) (ReleaseFunc, error) + WriteRequest(context.Context) (ReleaseFunc, error) + Close() +} + +func NewLimiter(c *limits.Config) (Limiter, error) { + if err := validateConfig(c); err != nil { + return nil, err + } + read, write := c.Read(), c.Write() + if isNoop(read, write) { + return noopLimiterInstance, nil + } + readScheduler, err := scheduling.NewMClock( + uint64(read.MaxRunningOps), uint64(read.MaxWaitingOps), + converToSchedulingTags(read.Tags), read.IdleTimeout) + if err != nil { + return nil, fmt.Errorf("create read scheduler: %w", err) + } + writeScheduler, err := scheduling.NewMClock( + uint64(write.MaxRunningOps), uint64(write.MaxWaitingOps), + converToSchedulingTags(write.Tags), write.IdleTimeout) + if err != nil { + return nil, fmt.Errorf("create write scheduler: %w", err) + } + return &mClockLimiter{ + readScheduler: readScheduler, + writeScheduler: writeScheduler, + }, nil +} + +func converToSchedulingTags(limits []limits.IOTagConfig) map[string]scheduling.TagInfo { + result := make(map[string]scheduling.TagInfo) + for _, tag := range []IOTag{IOTagClient, IOTagBackground, IOTagInternal, IOTagPolicer, IOTagWritecache} { + result[tag.String()] = scheduling.TagInfo{ + Share: defaultShare, + } + } + for _, l := range limits { + v := result[l.Tag] + if l.Weight != nil && *l.Weight != 0 { + v.Share = *l.Weight + } + if l.LimitOps != nil && *l.LimitOps != 0 { + v.LimitIOPS = l.LimitOps + } + if l.ReservedOps != nil && *l.ReservedOps != 0 { + v.ReservedIOPS = l.ReservedOps + } + result[l.Tag] = v + } + return result +} + +var ( + _ Limiter = (*noopLimiter)(nil) + releaseStub ReleaseFunc = func() {} + noopLimiterInstance = &noopLimiter{} +) + +type noopLimiter struct{} + +func (n *noopLimiter) ReadRequest(context.Context) (ReleaseFunc, error) { + return releaseStub, nil +} + +func (n *noopLimiter) WriteRequest(context.Context) (ReleaseFunc, error) { + return releaseStub, nil +} + +func (n *noopLimiter) Close() {} + +var _ Limiter = (*mClockLimiter)(nil) + +type mClockLimiter struct { + readScheduler *scheduling.MClock + writeScheduler *scheduling.MClock +} + +func (n *mClockLimiter) ReadRequest(ctx context.Context) (ReleaseFunc, error) { + tag, ok := tagging.IOTagFromContext(ctx) + assert.True(ok, "request has no tag") + if tag == IOTagCritical.String() { + return releaseStub, nil + } + rel, err := n.readScheduler.RequestArrival(ctx, tag) + if err != nil { + return nil, err + } + return ReleaseFunc(rel), nil +} + +func (n *mClockLimiter) WriteRequest(ctx context.Context) (ReleaseFunc, error) { + tag, ok := tagging.IOTagFromContext(ctx) + if !ok { + tag = IOTagClient.String() + } + if tag == IOTagCritical.String() { + return releaseStub, nil + } + rel, err := n.writeScheduler.RequestArrival(ctx, tag) + if err != nil { + return nil, err + } + return ReleaseFunc(rel), nil +} + +func (n *mClockLimiter) Close() { + n.readScheduler.Close() + n.writeScheduler.Close() +} diff --git a/internal/qos/validate.go b/internal/qos/validate.go index afced345b2..43aa749423 100644 --- a/internal/qos/validate.go +++ b/internal/qos/validate.go @@ -14,7 +14,7 @@ type tagConfig struct { Shares, Limit, Reserved *float64 } -func ValidateConfig(c *limits.Config) error { +func validateConfig(c *limits.Config) error { if err := validateOpConfig(c.Read()); err != nil { return fmt.Errorf("limits 'read' section validation error: %w", err) } @@ -90,3 +90,12 @@ func float64Value(f *float64) float64 { } return *f } + +func isNoop(read, write limits.OpConfig) bool { + return read.MaxRunningOps == limits.NoLimit && + read.MaxWaitingOps == limits.NoLimit && + write.MaxRunningOps == limits.NoLimit && + write.MaxWaitingOps == limits.NoLimit && + len(read.Tags) == 0 && + len(write.Tags) == 0 +} From e0dc3c3d0c4b948152cd054bda5545c64f413153 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 5 Feb 2025 15:57:27 +0300 Subject: [PATCH 1211/1413] [#1636] shard: Add limiter usage Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 + internal/qos/limiter.go | 4 + pkg/local_object_storage/engine/container.go | 2 +- pkg/local_object_storage/engine/inhume.go | 2 +- pkg/local_object_storage/shard/container.go | 26 ++- pkg/local_object_storage/shard/control.go | 4 + pkg/local_object_storage/shard/count.go | 6 + pkg/local_object_storage/shard/delete.go | 6 + pkg/local_object_storage/shard/exists.go | 17 +- pkg/local_object_storage/shard/gc.go | 177 +++++++++++++------ pkg/local_object_storage/shard/get.go | 6 + pkg/local_object_storage/shard/head.go | 6 + pkg/local_object_storage/shard/inhume.go | 6 + pkg/local_object_storage/shard/list.go | 40 ++++- pkg/local_object_storage/shard/lock.go | 21 ++- pkg/local_object_storage/shard/put.go | 6 + pkg/local_object_storage/shard/range.go | 6 + pkg/local_object_storage/shard/rebuild.go | 1 + pkg/local_object_storage/shard/select.go | 6 + pkg/local_object_storage/shard/shard.go | 10 ++ pkg/local_object_storage/shard/tree.go | 85 +++++++++ pkg/local_object_storage/shard/writecache.go | 19 ++ 22 files changed, 390 insertions(+), 67 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index c625a041f7..b422755382 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1072,6 +1072,7 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID return pool }), + shard.WithLimiter(shCfg.limiter), } return sh } diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index d2a1919f1c..996cebea1a 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -79,6 +79,10 @@ var ( noopLimiterInstance = &noopLimiter{} ) +func NewNoopLimiter() Limiter { + return &noopLimiter{} +} + type noopLimiter struct{} func (n *noopLimiter) ReadRequest(context.Context) (ReleaseFunc, error) { diff --git a/pkg/local_object_storage/engine/container.go b/pkg/local_object_storage/engine/container.go index b2d7a1037a..3160d7f835 100644 --- a/pkg/local_object_storage/engine/container.go +++ b/pkg/local_object_storage/engine/container.go @@ -74,7 +74,7 @@ func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) var csPrm shard.ContainerSizePrm csPrm.SetContainerID(prm.cnr) - csRes, err := sh.Shard.ContainerSize(csPrm) + csRes, err := sh.Shard.ContainerSize(ctx, csPrm) if err != nil { e.reportShardError(ctx, sh, "can't get container size", err, zap.Stringer("container_id", prm.cnr)) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index fb802ef2ab..c8ee33b534 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -339,7 +339,7 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid var drop []cid.ID for id := range idMap { prm.SetContainerID(id) - s, err := sh.ContainerSize(prm) + s, err := sh.ContainerSize(ctx, prm) if err != nil { e.log.Warn(ctx, logs.EngineFailedToGetContainerSize, zap.Stringer("container_id", id), zap.Error(err)) failed = true diff --git a/pkg/local_object_storage/shard/container.go b/pkg/local_object_storage/shard/container.go index 0309f0c81b..b4015ae8d2 100644 --- a/pkg/local_object_storage/shard/container.go +++ b/pkg/local_object_storage/shard/container.go @@ -26,7 +26,7 @@ func (r ContainerSizeRes) Size() uint64 { return r.size } -func (s *Shard) ContainerSize(prm ContainerSizePrm) (ContainerSizeRes, error) { +func (s *Shard) ContainerSize(ctx context.Context, prm ContainerSizePrm) (ContainerSizeRes, error) { s.m.RLock() defer s.m.RUnlock() @@ -34,6 +34,12 @@ func (s *Shard) ContainerSize(prm ContainerSizePrm) (ContainerSizeRes, error) { return ContainerSizeRes{}, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return ContainerSizeRes{}, err + } + defer release() + size, err := s.metaBase.ContainerSize(prm.cnr) if err != nil { return ContainerSizeRes{}, fmt.Errorf("get container size: %w", err) @@ -69,6 +75,12 @@ func (s *Shard) ContainerCount(ctx context.Context, prm ContainerCountPrm) (Cont return ContainerCountRes{}, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return ContainerCountRes{}, err + } + defer release() + counters, err := s.metaBase.ContainerCount(ctx, prm.ContainerID) if err != nil { return ContainerCountRes{}, fmt.Errorf("get container counters: %w", err) @@ -100,6 +112,12 @@ func (s *Shard) DeleteContainerSize(ctx context.Context, id cid.ID) error { return ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() + return s.metaBase.DeleteContainerSize(ctx, id) } @@ -122,5 +140,11 @@ func (s *Shard) DeleteContainerCount(ctx context.Context, id cid.ID) error { return ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() + return s.metaBase.DeleteContainerCount(ctx, id) } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index fedde22062..3520277c02 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -395,6 +395,10 @@ func (s *Shard) Close(ctx context.Context) error { s.gc.stop(ctx) } + if s.opsLimiter != nil { + s.opsLimiter.Close() + } + return lastErr } diff --git a/pkg/local_object_storage/shard/count.go b/pkg/local_object_storage/shard/count.go index b3bc6a30b5..8dc1f05225 100644 --- a/pkg/local_object_storage/shard/count.go +++ b/pkg/local_object_storage/shard/count.go @@ -23,6 +23,12 @@ func (s *Shard) LogicalObjectsCount(ctx context.Context) (uint64, error) { return 0, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return 0, err + } + defer release() + cc, err := s.metaBase.ObjectCounters() if err != nil { return 0, err diff --git a/pkg/local_object_storage/shard/delete.go b/pkg/local_object_storage/shard/delete.go index 55231b0322..0101817a81 100644 --- a/pkg/local_object_storage/shard/delete.go +++ b/pkg/local_object_storage/shard/delete.go @@ -54,6 +54,12 @@ func (s *Shard) delete(ctx context.Context, prm DeletePrm, skipFailed bool) (Del return DeleteRes{}, ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return DeleteRes{}, err + } + defer release() + result := DeleteRes{} for _, addr := range prm.addr { select { diff --git a/pkg/local_object_storage/shard/exists.go b/pkg/local_object_storage/shard/exists.go index 82ce48dde7..2c11b6b016 100644 --- a/pkg/local_object_storage/shard/exists.go +++ b/pkg/local_object_storage/shard/exists.go @@ -53,10 +53,6 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { )) defer span.End() - var exists bool - var locked bool - var err error - s.m.RLock() defer s.m.RUnlock() @@ -64,7 +60,18 @@ func (s *Shard) Exists(ctx context.Context, prm ExistsPrm) (ExistsRes, error) { return ExistsRes{}, ErrShardDisabled } else if s.info.EvacuationInProgress { return ExistsRes{}, logicerr.Wrap(new(apistatus.ObjectNotFound)) - } else if s.info.Mode.NoMetabase() { + } + + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return ExistsRes{}, err + } + defer release() + + var exists bool + var locked bool + + if s.info.Mode.NoMetabase() { var p common.ExistsPrm p.Address = prm.Address diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 4a5ec7a71b..32a377cd5a 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -291,28 +291,7 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { s.log.Debug(ctx, logs.ShardGCRemoveGarbageStarted) defer s.log.Debug(ctx, logs.ShardGCRemoveGarbageCompleted) - buf := make([]oid.Address, 0, s.rmBatchSize) - - var iterPrm meta.GarbageIterationPrm - iterPrm.SetHandler(func(g meta.GarbageObject) error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - buf = append(buf, g.Address()) - - if len(buf) == s.rmBatchSize { - return meta.ErrInterruptIterator - } - - return nil - }) - - // iterate over metabase's objects with GC mark - // (no more than s.rmBatchSize objects) - err := s.metaBase.IterateOverGarbage(ctx, iterPrm) + buf, err := s.getGarbage(ctx) if err != nil { s.log.Warn(ctx, logs.ShardIteratorOverMetabaseGraveyardFailed, zap.Error(err), @@ -344,6 +323,39 @@ func (s *Shard) removeGarbage(pctx context.Context) (result gcRunResult) { return } +func (s *Shard) getGarbage(ctx context.Context) ([]oid.Address, error) { + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, err + } + defer release() + + buf := make([]oid.Address, 0, s.rmBatchSize) + + var iterPrm meta.GarbageIterationPrm + iterPrm.SetHandler(func(g meta.GarbageObject) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + buf = append(buf, g.Address()) + + if len(buf) == s.rmBatchSize { + return meta.ErrInterruptIterator + } + + return nil + }) + + if err := s.metaBase.IterateOverGarbage(ctx, iterPrm); err != nil { + return nil, err + } + + return buf, nil +} + func (s *Shard) getExpiredObjectsParameters() (workerCount, batchSize int) { workerCount = max(minExpiredWorkers, s.gc.gcCfg.expiredCollectorWorkerCount) batchSize = max(minExpiredBatchSize, s.gc.gcCfg.expiredCollectorBatchSize) @@ -422,18 +434,9 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) return } - var inhumePrm meta.InhumePrm - - inhumePrm.SetAddresses(expired...) - inhumePrm.SetGCMark() - - // inhume the collected objects - res, err := s.metaBase.Inhume(ctx, inhumePrm) + res, err := s.inhumeGC(ctx, expired) if err != nil { - s.log.Warn(ctx, logs.ShardCouldNotInhumeTheObjects, - zap.Error(err), - ) - + s.log.Warn(ctx, logs.ShardCouldNotInhumeTheObjects, zap.Error(err)) return } @@ -451,6 +454,12 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) } func (s *Shard) getExpiredWithLinked(ctx context.Context, source []oid.Address) ([]oid.Address, error) { + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, err + } + defer release() + result := make([]oid.Address, 0, len(source)) parentToChildren, err := s.metaBase.GetChildren(ctx, source) if err != nil { @@ -464,6 +473,19 @@ func (s *Shard) getExpiredWithLinked(ctx context.Context, source []oid.Address) return result, nil } +func (s *Shard) inhumeGC(ctx context.Context, addrs []oid.Address) (meta.InhumeRes, error) { + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return meta.InhumeRes{}, err + } + defer release() + + var inhumePrm meta.InhumePrm + inhumePrm.SetAddresses(addrs...) + inhumePrm.SetGCMark() + return s.metaBase.Inhume(ctx, inhumePrm) +} + func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { var err error startedAt := time.Now() @@ -505,11 +527,17 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { return } - err = s.metaBase.IterateOverGraveyard(ctx, iterPrm) + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + log.Error(ctx, logs.ShardIteratorOverGraveyardFailed, zap.Error(err)) + s.m.RUnlock() + return + } + err = s.metaBase.IterateOverGraveyard(ctx, iterPrm) + release() if err != nil { log.Error(ctx, logs.ShardIteratorOverGraveyardFailed, zap.Error(err)) s.m.RUnlock() - return } @@ -598,7 +626,13 @@ func (s *Shard) getExpiredObjects(ctx context.Context, epoch uint64, onExpiredFo return ErrDegradedMode } - err := s.metaBase.IterateExpired(ctx, epoch, func(expiredObject *meta.ExpiredObject) error { + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return err + } + defer release() + + err = s.metaBase.IterateExpired(ctx, epoch, func(expiredObject *meta.ExpiredObject) error { select { case <-ctx.Done(): return meta.ErrInterruptIterator @@ -621,6 +655,12 @@ func (s *Shard) selectExpired(ctx context.Context, epoch uint64, addresses []oid return nil, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, err + } + defer release() + return s.metaBase.FilterExpired(ctx, epoch, addresses) } @@ -636,12 +676,15 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston return } - res, err := s.metaBase.InhumeTombstones(ctx, tss) + release, err := s.opsLimiter.WriteRequest(ctx) if err != nil { - s.log.Warn(ctx, logs.ShardCouldNotMarkTombstonesAsGarbage, - zap.Error(err), - ) - + s.log.Warn(ctx, logs.ShardCouldNotMarkTombstonesAsGarbage, zap.Error(err)) + return + } + res, err := s.metaBase.InhumeTombstones(ctx, tss) + release() + if err != nil { + s.log.Warn(ctx, logs.ShardCouldNotMarkTombstonesAsGarbage, zap.Error(err)) return } @@ -664,11 +707,16 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] if s.GetMode().NoMetabase() { return } - unlocked, err := s.metaBase.FreeLockedBy(lockers) + + release, err := s.opsLimiter.WriteRequest(ctx) if err != nil { - s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, - zap.Error(err), - ) + s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, zap.Error(err)) + return + } + unlocked, err := s.metaBase.FreeLockedBy(lockers) + release() + if err != nil { + s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, zap.Error(err)) return } @@ -676,13 +724,15 @@ func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers [] var pInhume meta.InhumePrm pInhume.SetAddresses(lockers...) pInhume.SetForceGCMark() - - res, err := s.metaBase.Inhume(ctx, pInhume) + release, err = s.opsLimiter.WriteRequest(ctx) if err != nil { - s.log.Warn(ctx, logs.ShardFailureToMarkLockersAsGarbage, - zap.Error(err), - ) - + s.log.Warn(ctx, logs.ShardFailureToMarkLockersAsGarbage, zap.Error(err)) + return + } + res, err := s.metaBase.Inhume(ctx, pInhume) + release() + if err != nil { + s.log.Warn(ctx, logs.ShardFailureToMarkLockersAsGarbage, zap.Error(err)) return } @@ -721,12 +771,15 @@ func (s *Shard) HandleDeletedLocks(ctx context.Context, lockers []oid.Address) { return } - _, err := s.metaBase.FreeLockedBy(lockers) + release, err := s.opsLimiter.WriteRequest(ctx) if err != nil { - s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, - zap.Error(err), - ) - + s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, zap.Error(err)) + return + } + _, err = s.metaBase.FreeLockedBy(lockers) + release() + if err != nil { + s.log.Warn(ctx, logs.ShardFailureToUnlockObjects, zap.Error(err)) return } } @@ -750,7 +803,13 @@ func (s *Shard) collectExpiredMetrics(ctx context.Context, e Event) { } func (s *Shard) collectExpiredContainerSizeMetrics(ctx context.Context, epoch uint64) { + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + s.log.Warn(ctx, logs.ShardGCFailedToCollectZeroSizeContainers, zap.Uint64("epoch", epoch), zap.Error(err)) + return + } ids, err := s.metaBase.ZeroSizeContainers(ctx) + release() if err != nil { s.log.Warn(ctx, logs.ShardGCFailedToCollectZeroSizeContainers, zap.Uint64("epoch", epoch), zap.Error(err)) return @@ -762,7 +821,13 @@ func (s *Shard) collectExpiredContainerSizeMetrics(ctx context.Context, epoch ui } func (s *Shard) collectExpiredContainerCountMetrics(ctx context.Context, epoch uint64) { + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + s.log.Warn(ctx, logs.ShardGCFailedToCollectZeroCountContainers, zap.Uint64("epoch", epoch), zap.Error(err)) + return + } ids, err := s.metaBase.ZeroCountContainers(ctx) + release() if err != nil { s.log.Warn(ctx, logs.ShardGCFailedToCollectZeroCountContainers, zap.Uint64("epoch", epoch), zap.Error(err)) return diff --git a/pkg/local_object_storage/shard/get.go b/pkg/local_object_storage/shard/get.go index 05823c62bd..28f8912be7 100644 --- a/pkg/local_object_storage/shard/get.go +++ b/pkg/local_object_storage/shard/get.go @@ -111,6 +111,12 @@ func (s *Shard) Get(ctx context.Context, prm GetPrm) (GetRes, error) { return c.Get(ctx, prm.addr) } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return GetRes{}, err + } + defer release() + skipMeta := prm.skipMeta || s.info.Mode.NoMetabase() obj, hasMeta, err := s.fetchObjectData(ctx, prm.addr, skipMeta, cb, wc) diff --git a/pkg/local_object_storage/shard/head.go b/pkg/local_object_storage/shard/head.go index ff57e3bf95..34b8290d64 100644 --- a/pkg/local_object_storage/shard/head.go +++ b/pkg/local_object_storage/shard/head.go @@ -81,6 +81,12 @@ func (s *Shard) Head(ctx context.Context, prm HeadPrm) (HeadRes, error) { headParams.SetAddress(prm.addr) headParams.SetRaw(prm.raw) + release, limitErr := s.opsLimiter.ReadRequest(ctx) + if limitErr != nil { + return HeadRes{}, limitErr + } + defer release() + var res meta.GetRes res, err = s.metaBase.Get(ctx, headParams) obj = res.Header() diff --git a/pkg/local_object_storage/shard/inhume.go b/pkg/local_object_storage/shard/inhume.go index 9d5f660637..c0fd65f4b6 100644 --- a/pkg/local_object_storage/shard/inhume.go +++ b/pkg/local_object_storage/shard/inhume.go @@ -81,6 +81,12 @@ func (s *Shard) Inhume(ctx context.Context, prm InhumePrm) (InhumeRes, error) { return InhumeRes{}, ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return InhumeRes{}, err + } + defer release() + if s.hasWriteCache() { for i := range prm.target { _ = s.writeCache.Delete(ctx, prm.target[i]) diff --git a/pkg/local_object_storage/shard/list.go b/pkg/local_object_storage/shard/list.go index 7bc5ead1d7..af87981cad 100644 --- a/pkg/local_object_storage/shard/list.go +++ b/pkg/local_object_storage/shard/list.go @@ -106,6 +106,12 @@ func (s *Shard) List(ctx context.Context) (res SelectRes, err error) { return SelectRes{}, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return SelectRes{}, err + } + defer release() + lst, err := s.metaBase.Containers(ctx) if err != nil { return res, fmt.Errorf("list stored containers: %w", err) @@ -145,6 +151,12 @@ func (s *Shard) ListContainers(ctx context.Context, _ ListContainersPrm) (ListCo return ListContainersRes{}, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return ListContainersRes{}, err + } + defer release() + containers, err := s.metaBase.Containers(ctx) if err != nil { return ListContainersRes{}, fmt.Errorf("get list of containers: %w", err) @@ -173,6 +185,12 @@ func (s *Shard) ListWithCursor(ctx context.Context, prm ListWithCursorPrm) (List return ListWithCursorRes{}, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return ListWithCursorRes{}, err + } + defer release() + var metaPrm meta.ListPrm metaPrm.SetCount(prm.count) metaPrm.SetCursor(prm.cursor) @@ -202,9 +220,15 @@ func (s *Shard) IterateOverContainers(ctx context.Context, prm IterateOverContai return ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return err + } + defer release() + var metaPrm meta.IterateOverContainersPrm metaPrm.Handler = prm.Handler - err := s.metaBase.IterateOverContainers(ctx, metaPrm) + err = s.metaBase.IterateOverContainers(ctx, metaPrm) if err != nil { return fmt.Errorf("iterate over containers: %w", err) } @@ -227,11 +251,17 @@ func (s *Shard) IterateOverObjectsInContainer(ctx context.Context, prm IterateOv return ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return err + } + defer release() + var metaPrm meta.IterateOverObjectsInContainerPrm metaPrm.ContainerID = prm.ContainerID metaPrm.ObjectType = prm.ObjectType metaPrm.Handler = prm.Handler - err := s.metaBase.IterateOverObjectsInContainer(ctx, metaPrm) + err = s.metaBase.IterateOverObjectsInContainer(ctx, metaPrm) if err != nil { return fmt.Errorf("iterate over objects: %w", err) } @@ -251,6 +281,12 @@ func (s *Shard) CountAliveObjectsInContainer(ctx context.Context, prm CountAlive return 0, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return 0, err + } + defer release() + var metaPrm meta.CountAliveObjectsInContainerPrm metaPrm.ObjectType = prm.ObjectType metaPrm.ContainerID = prm.ContainerID diff --git a/pkg/local_object_storage/shard/lock.go b/pkg/local_object_storage/shard/lock.go index 31ca16aa17..9c392fdacf 100644 --- a/pkg/local_object_storage/shard/lock.go +++ b/pkg/local_object_storage/shard/lock.go @@ -38,7 +38,13 @@ func (s *Shard) Lock(ctx context.Context, idCnr cid.ID, locker oid.ID, locked [] return ErrDegradedMode } - err := s.metaBase.Lock(ctx, idCnr, locker, locked) + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() + + err = s.metaBase.Lock(ctx, idCnr, locker, locked) if err != nil { return fmt.Errorf("metabase lock: %w", err) } @@ -61,6 +67,12 @@ func (s *Shard) IsLocked(ctx context.Context, addr oid.Address) (bool, error) { return false, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return false, err + } + defer release() + var prm meta.IsLockedPrm prm.SetAddress(addr) @@ -86,5 +98,12 @@ func (s *Shard) GetLocks(ctx context.Context, addr oid.Address) ([]oid.ID, error if m.NoMetabase() { return nil, ErrDegradedMode } + + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, err + } + defer release() + return s.metaBase.GetLocks(ctx, addr) } diff --git a/pkg/local_object_storage/shard/put.go b/pkg/local_object_storage/shard/put.go index 3f23111aff..f8cb00a31e 100644 --- a/pkg/local_object_storage/shard/put.go +++ b/pkg/local_object_storage/shard/put.go @@ -67,6 +67,12 @@ func (s *Shard) Put(ctx context.Context, prm PutPrm) (PutRes, error) { var res common.PutRes + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return PutRes{}, err + } + defer release() + // exist check are not performed there, these checks should be executed // ahead of `Put` by storage engine tryCache := s.hasWriteCache() && !m.NoMetabase() diff --git a/pkg/local_object_storage/shard/range.go b/pkg/local_object_storage/shard/range.go index 701268820d..4436891048 100644 --- a/pkg/local_object_storage/shard/range.go +++ b/pkg/local_object_storage/shard/range.go @@ -131,6 +131,12 @@ func (s *Shard) GetRange(ctx context.Context, prm RngPrm) (RngRes, error) { return obj, nil } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return RngRes{}, err + } + defer release() + skipMeta := prm.skipMeta || s.info.Mode.NoMetabase() obj, hasMeta, err := s.fetchObjectData(ctx, prm.addr, skipMeta, cb, wc) diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index 0593f58942..9fe1bbe8c8 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -106,6 +106,7 @@ func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *lo } log.Info(ctx, logs.BlobstoreRebuildStarted) ctx = tagging.ContextWithIOTag(ctx, qos.IOTagBackground.String()) + // TODO use shard limiter if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, limiter, fillPercent); err != nil { log.Warn(ctx, logs.FailedToRebuildBlobstore, zap.Error(err)) } else { diff --git a/pkg/local_object_storage/shard/select.go b/pkg/local_object_storage/shard/select.go index c7c7e11c2e..fbc751e267 100644 --- a/pkg/local_object_storage/shard/select.go +++ b/pkg/local_object_storage/shard/select.go @@ -60,6 +60,12 @@ func (s *Shard) Select(ctx context.Context, prm SelectPrm) (SelectRes, error) { return SelectRes{}, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return SelectRes{}, nil + } + defer release() + var selectPrm meta.SelectPrm selectPrm.SetFilters(prm.filters) selectPrm.SetContainerID(prm.cnr) diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 1eb7f14d02..b9ec05f013 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -7,6 +7,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" @@ -98,6 +99,8 @@ type cfg struct { reportErrorFunc func(ctx context.Context, selfID string, message string, err error) containerInfo container.InfoProvider + + opsLimiter qos.Limiter } func defaultCfg() *cfg { @@ -109,6 +112,7 @@ func defaultCfg() *cfg { zeroSizeContainersCallback: func(context.Context, []cid.ID) {}, zeroCountContainersCallback: func(context.Context, []cid.ID) {}, metricsWriter: noopMetrics{}, + opsLimiter: qos.NewNoopLimiter(), } } @@ -368,6 +372,12 @@ func WithContainerInfoProvider(containerInfo container.InfoProvider) Option { } } +func WithLimiter(l qos.Limiter) Option { + return func(c *cfg) { + c.opsLimiter = l + } +} + func (s *Shard) fillInfo() { s.cfg.info.MetaBaseInfo = s.metaBase.DumpInfo() s.cfg.info.BlobStorInfo = s.blobStor.DumpInfo() diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index 01a014cecc..e9cd5f8c1f 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -43,6 +43,11 @@ func (s *Shard) TreeMove(ctx context.Context, d pilorama.CIDDescriptor, treeID s if s.info.Mode.NoMetabase() { return nil, ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return nil, err + } + defer release() return s.pilorama.TreeMove(ctx, d, treeID, m) } @@ -75,6 +80,11 @@ func (s *Shard) TreeAddByPath(ctx context.Context, d pilorama.CIDDescriptor, tre if s.info.Mode.NoMetabase() { return nil, ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return nil, err + } + defer release() return s.pilorama.TreeAddByPath(ctx, d, treeID, attr, path, meta) } @@ -103,6 +113,11 @@ func (s *Shard) TreeApply(ctx context.Context, cnr cidSDK.ID, treeID string, m * if s.info.Mode.NoMetabase() { return ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() return s.pilorama.TreeApply(ctx, cnr, treeID, m, backgroundSync) } @@ -130,6 +145,11 @@ func (s *Shard) TreeApplyBatch(ctx context.Context, cnr cidSDK.ID, treeID string if s.info.Mode.NoMetabase() { return ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() return s.pilorama.TreeApplyBatch(ctx, cnr, treeID, m) } @@ -157,6 +177,11 @@ func (s *Shard) TreeGetByPath(ctx context.Context, cid cidSDK.ID, treeID string, if s.info.Mode.NoMetabase() { return nil, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, err + } + defer release() return s.pilorama.TreeGetByPath(ctx, cid, treeID, attr, path, latest) } @@ -182,6 +207,11 @@ func (s *Shard) TreeGetMeta(ctx context.Context, cid cidSDK.ID, treeID string, n if s.info.Mode.NoMetabase() { return pilorama.Meta{}, 0, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return pilorama.Meta{}, 0, err + } + defer release() return s.pilorama.TreeGetMeta(ctx, cid, treeID, nodeID) } @@ -207,6 +237,11 @@ func (s *Shard) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID strin if s.info.Mode.NoMetabase() { return nil, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, err + } + defer release() return s.pilorama.TreeGetChildren(ctx, cid, treeID, nodeID) } @@ -231,6 +266,11 @@ func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID if s.info.Mode.NoMetabase() { return nil, last, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, last, err + } + defer release() return s.pilorama.TreeSortedByFilename(ctx, cid, treeID, nodeID, last, count) } @@ -256,6 +296,11 @@ func (s *Shard) TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID string, if s.info.Mode.NoMetabase() { return pilorama.Move{}, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return pilorama.Move{}, err + } + defer release() return s.pilorama.TreeGetOpLog(ctx, cid, treeID, height) } @@ -280,6 +325,11 @@ func (s *Shard) TreeDrop(ctx context.Context, cid cidSDK.ID, treeID string) erro if s.info.Mode.NoMetabase() { return ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() return s.pilorama.TreeDrop(ctx, cid, treeID) } @@ -303,6 +353,11 @@ func (s *Shard) TreeList(ctx context.Context, cid cidSDK.ID) ([]string, error) { if s.info.Mode.NoMetabase() { return nil, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, err + } + defer release() return s.pilorama.TreeList(ctx, cid) } @@ -326,6 +381,11 @@ func (s *Shard) TreeHeight(ctx context.Context, cid cidSDK.ID, treeID string) (u if s.pilorama == nil { return 0, ErrPiloramaDisabled } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return 0, err + } + defer release() return s.pilorama.TreeHeight(ctx, cid, treeID) } @@ -350,6 +410,11 @@ func (s *Shard) TreeExists(ctx context.Context, cid cidSDK.ID, treeID string) (b if s.info.Mode.NoMetabase() { return false, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return false, err + } + defer release() return s.pilorama.TreeExists(ctx, cid, treeID) } @@ -378,6 +443,11 @@ func (s *Shard) TreeUpdateLastSyncHeight(ctx context.Context, cid cidSDK.ID, tre if s.info.Mode.NoMetabase() { return ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() return s.pilorama.TreeUpdateLastSyncHeight(ctx, cid, treeID, height) } @@ -402,6 +472,11 @@ func (s *Shard) TreeLastSyncHeight(ctx context.Context, cid cidSDK.ID, treeID st if s.info.Mode.NoMetabase() { return 0, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return 0, err + } + defer release() return s.pilorama.TreeLastSyncHeight(ctx, cid, treeID) } @@ -423,6 +498,11 @@ func (s *Shard) TreeListTrees(ctx context.Context, prm pilorama.TreeListTreesPrm if s.info.Mode.NoMetabase() { return nil, ErrDegradedMode } + release, err := s.opsLimiter.ReadRequest(ctx) + if err != nil { + return nil, err + } + defer release() return s.pilorama.TreeListTrees(ctx, prm) } @@ -452,5 +532,10 @@ func (s *Shard) TreeApplyStream(ctx context.Context, cnr cidSDK.ID, treeID strin if s.info.Mode.NoMetabase() { return ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() return s.pilorama.TreeApplyStream(ctx, cnr, treeID, source) } diff --git a/pkg/local_object_storage/shard/writecache.go b/pkg/local_object_storage/shard/writecache.go index f655e477a9..9edb89df8c 100644 --- a/pkg/local_object_storage/shard/writecache.go +++ b/pkg/local_object_storage/shard/writecache.go @@ -67,6 +67,12 @@ func (s *Shard) FlushWriteCache(ctx context.Context, p FlushWriteCachePrm) error return ErrDegradedMode } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() + return s.writeCache.Flush(ctx, p.ignoreErrors, p.seal) } @@ -124,6 +130,13 @@ func (s *Shard) SealWriteCache(ctx context.Context, p SealWriteCachePrm) error { close(started) defer cleanup() + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + s.log.Warn(ctx, logs.FailedToSealWritecacheAsync, zap.Error(err)) + return + } + defer release() + s.log.Info(ctx, logs.StartedWritecacheSealAsync) if err := s.writeCache.Seal(ctx, prm); err != nil { s.log.Warn(ctx, logs.FailedToSealWritecacheAsync, zap.Error(err)) @@ -138,5 +151,11 @@ func (s *Shard) SealWriteCache(ctx context.Context, p SealWriteCachePrm) error { return nil } } + release, err := s.opsLimiter.WriteRequest(ctx) + if err != nil { + return err + } + defer release() + return s.writeCache.Seal(ctx, prm) } From ceff5e1f6a08c12d84a04fcfa2e23f097bfa97fa Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 6 Feb 2025 17:24:23 +0300 Subject: [PATCH 1212/1413] [#1636] storage: Refactor shard rebuild Drop redundant interfaces. Rename fields. Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/rebuild.go | 13 ++--- .../blobovniczatree/rebuild_failover_test.go | 6 +-- .../blobstor/blobovniczatree/rebuild_test.go | 33 ++++++------- .../blobstor/common/rebuild.go | 17 ++++--- pkg/local_object_storage/blobstor/rebuild.go | 13 ++--- pkg/local_object_storage/engine/rebuild.go | 22 ++++++++- pkg/local_object_storage/shard/rebuild.go | 47 ++++--------------- 7 files changed, 72 insertions(+), 79 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 16ef2b1805..cbd45c3b4d 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -79,7 +79,7 @@ func (b *Blobovniczas) migrateDBs(ctx context.Context, dbs []string, prm common. var completedDBCount uint32 for _, db := range dbs { b.log.Debug(ctx, logs.BlobovniczaTreeRebuildingBlobovnicza, zap.String("path", db)) - movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage, prm.WorkerLimiter) + movedObjects, err := b.rebuildDB(ctx, db, prm.MetaStorage, prm.Limiter) res.ObjectsMoved += movedObjects if err != nil { b.log.Warn(ctx, logs.BlobovniczaTreeRebuildingBlobovniczaFailed, zap.String("path", db), zap.Uint64("moved_objects_count", movedObjects), zap.Error(err)) @@ -195,7 +195,7 @@ func (b *Blobovniczas) rebuildBySize(ctx context.Context, path string, targetFil return fp < targetFillPercent || fp > 100+(100-targetFillPercent), nil } -func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) { +func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.MetaStorage, concLimiter common.RebuildLimiter) (uint64, error) { shDB := b.getBlobovnicza(ctx, path) blz, err := shDB.Open(ctx) if err != nil { @@ -212,7 +212,7 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M if err != nil { return 0, err } - migratedObjects, err := b.moveObjects(ctx, blz, shDB.SystemPath(), meta, limiter) + migratedObjects, err := b.moveObjects(ctx, blz, shDB.SystemPath(), meta, concLimiter) if err != nil { return migratedObjects, err } @@ -238,7 +238,7 @@ func (b *Blobovniczas) addRebuildTempFile(ctx context.Context, path string) (fun }, nil } -func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, blzPath string, meta common.MetaStorage, limiter common.ConcurrentWorkersLimiter) (uint64, error) { +func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, blzPath string, meta common.MetaStorage, concLimiter common.RebuildLimiter) (uint64, error) { var result atomic.Uint64 batch := make(map[oid.Address][]byte) @@ -265,12 +265,13 @@ func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovn eg, egCtx := errgroup.WithContext(ctx) for addr, data := range batch { - if err := limiter.AcquireWorkSlot(egCtx); err != nil { + release, err := concLimiter.AcquireWorkSlot(egCtx) + if err != nil { _ = eg.Wait() return result.Load(), err } eg.Go(func() error { - defer limiter.ReleaseWorkSlot() + defer release() err := b.moveObject(egCtx, blz, blzPath, addr, data, meta) if err == nil { result.Add(1) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index 2f58624aae..91578d5e86 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -162,9 +162,9 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object guard: &sync.Mutex{}, } rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ - MetaStorage: metaStub, - WorkerLimiter: &rebuildLimiterStub{}, - FillPercent: 1, + MetaStorage: metaStub, + Limiter: &rebuildLimiterStub{}, + FillPercent: 1, }) require.NoError(t, err) require.Equal(t, uint64(1), rRes.ObjectsMoved) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index aae72b5fff..e26c485ba4 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -77,9 +77,9 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { guard: &sync.Mutex{}, } rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ - MetaStorage: metaStub, - WorkerLimiter: &rebuildLimiterStub{}, - FillPercent: 60, + MetaStorage: metaStub, + Limiter: &rebuildLimiterStub{}, + FillPercent: 60, }) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 @@ -129,9 +129,9 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { guard: &sync.Mutex{}, } rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ - MetaStorage: metaStub, - WorkerLimiter: &rebuildLimiterStub{}, - FillPercent: 90, // 64KB / 100KB = 64% + MetaStorage: metaStub, + Limiter: &rebuildLimiterStub{}, + FillPercent: 90, // 64KB / 100KB = 64% }) require.NoError(t, err) dataMigrated := rRes.ObjectsMoved > 0 || rRes.FilesRemoved > 0 || metaStub.updatedCount > 0 @@ -194,9 +194,9 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { guard: &sync.Mutex{}, } rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ - MetaStorage: metaStub, - WorkerLimiter: &rebuildLimiterStub{}, - FillPercent: 80, + MetaStorage: metaStub, + Limiter: &rebuildLimiterStub{}, + FillPercent: 80, }) require.NoError(t, err) require.Equal(t, uint64(49), rRes.FilesRemoved) @@ -267,9 +267,9 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, b.Init()) rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ - MetaStorage: metaStub, - WorkerLimiter: &rebuildLimiterStub{}, - FillPercent: 80, + MetaStorage: metaStub, + Limiter: &rebuildLimiterStub{}, + FillPercent: 80, }) require.NoError(t, err) require.Equal(t, uint64(49), rRes.FilesRemoved) @@ -340,7 +340,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { } var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub - rPrm.WorkerLimiter = &rebuildLimiterStub{} + rPrm.Limiter = &rebuildLimiterStub{} rPrm.FillPercent = 1 rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) @@ -429,7 +429,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta } var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub - rPrm.WorkerLimiter = &rebuildLimiterStub{} + rPrm.Limiter = &rebuildLimiterStub{} rPrm.FillPercent = 1 rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) @@ -464,5 +464,6 @@ func (s *storageIDUpdateStub) UpdateStorageID(ctx context.Context, addr oid.Addr type rebuildLimiterStub struct{} -func (s *rebuildLimiterStub) AcquireWorkSlot(context.Context) error { return nil } -func (s *rebuildLimiterStub) ReleaseWorkSlot() {} +func (s *rebuildLimiterStub) AcquireWorkSlot(context.Context) (common.ReleaseFunc, error) { + return func() {}, nil +} diff --git a/pkg/local_object_storage/blobstor/common/rebuild.go b/pkg/local_object_storage/blobstor/common/rebuild.go index 19e181ee70..4615190f78 100644 --- a/pkg/local_object_storage/blobstor/common/rebuild.go +++ b/pkg/local_object_storage/blobstor/common/rebuild.go @@ -12,16 +12,21 @@ type RebuildRes struct { } type RebuildPrm struct { - MetaStorage MetaStorage - WorkerLimiter ConcurrentWorkersLimiter - FillPercent int + MetaStorage MetaStorage + Limiter RebuildLimiter + FillPercent int } type MetaStorage interface { UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error } -type ConcurrentWorkersLimiter interface { - AcquireWorkSlot(ctx context.Context) error - ReleaseWorkSlot() +type ReleaseFunc func() + +type ConcurrencyLimiter interface { + AcquireWorkSlot(ctx context.Context) (ReleaseFunc, error) +} + +type RebuildLimiter interface { + ConcurrencyLimiter } diff --git a/pkg/local_object_storage/blobstor/rebuild.go b/pkg/local_object_storage/blobstor/rebuild.go index 2a6b947895..f288165556 100644 --- a/pkg/local_object_storage/blobstor/rebuild.go +++ b/pkg/local_object_storage/blobstor/rebuild.go @@ -13,19 +13,14 @@ type StorageIDUpdate interface { UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error } -type ConcurrentWorkersLimiter interface { - AcquireWorkSlot(ctx context.Context) error - ReleaseWorkSlot() -} - -func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter ConcurrentWorkersLimiter, fillPercent int) error { +func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, concLimiter common.RebuildLimiter, fillPercent int) error { var summary common.RebuildRes var rErr error for _, storage := range b.storage { res, err := storage.Storage.Rebuild(ctx, common.RebuildPrm{ - MetaStorage: upd, - WorkerLimiter: limiter, - FillPercent: fillPercent, + MetaStorage: upd, + Limiter: concLimiter, + FillPercent: fillPercent, }) summary.FilesRemoved += res.FilesRemoved summary.ObjectsMoved += res.ObjectsMoved diff --git a/pkg/local_object_storage/engine/rebuild.go b/pkg/local_object_storage/engine/rebuild.go index 83c6a54ede..a29dd7ed90 100644 --- a/pkg/local_object_storage/engine/rebuild.go +++ b/pkg/local_object_storage/engine/rebuild.go @@ -4,6 +4,7 @@ import ( "context" "sync" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "go.opentelemetry.io/otel/attribute" @@ -41,7 +42,7 @@ func (e *StorageEngine) Rebuild(ctx context.Context, prm RebuildPrm) (RebuildRes } resGuard := &sync.Mutex{} - limiter := shard.NewRebuildLimiter(prm.ConcurrencyLimit) + concLimiter := &concurrencyLimiter{semaphore: make(chan struct{}, prm.ConcurrencyLimit)} eg, egCtx := errgroup.WithContext(ctx) for _, shardID := range prm.ShardIDs { @@ -61,7 +62,7 @@ func (e *StorageEngine) Rebuild(ctx context.Context, prm RebuildPrm) (RebuildRes } err := sh.ScheduleRebuild(egCtx, shard.RebuildPrm{ - ConcurrencyLimiter: limiter, + ConcurrencyLimiter: concLimiter, TargetFillPercent: prm.TargetFillPercent, }) @@ -88,3 +89,20 @@ func (e *StorageEngine) Rebuild(ctx context.Context, prm RebuildPrm) (RebuildRes } return res, nil } + +type concurrencyLimiter struct { + semaphore chan struct{} +} + +func (l *concurrencyLimiter) AcquireWorkSlot(ctx context.Context) (common.ReleaseFunc, error) { + select { + case l.semaphore <- struct{}{}: + return l.releaseWorkSlot, nil + case <-ctx.Done(): + return nil, ctx.Err() + } +} + +func (l *concurrencyLimiter) releaseWorkSlot() { + <-l.semaphore +} diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index 9fe1bbe8c8..3aa94d5a3d 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -20,37 +21,9 @@ import ( var ErrRebuildInProgress = errors.New("shard rebuild in progress") -type RebuildWorkerLimiter interface { - AcquireWorkSlot(ctx context.Context) error - ReleaseWorkSlot() -} - -type rebuildLimiter struct { - semaphore chan struct{} -} - -func NewRebuildLimiter(workersCount uint32) RebuildWorkerLimiter { - return &rebuildLimiter{ - semaphore: make(chan struct{}, workersCount), - } -} - -func (l *rebuildLimiter) AcquireWorkSlot(ctx context.Context) error { - select { - case l.semaphore <- struct{}{}: - return nil - case <-ctx.Done(): - return ctx.Err() - } -} - -func (l *rebuildLimiter) ReleaseWorkSlot() { - <-l.semaphore -} - type rebuildTask struct { - limiter RebuildWorkerLimiter - fillPercent int + concurrencyLimiter common.RebuildLimiter + fillPercent int } type rebuilder struct { @@ -90,14 +63,14 @@ func (r *rebuilder) Start(ctx context.Context, bs *blobstor.BlobStor, mb *meta.D if !ok { continue } - runRebuild(ctx, bs, mb, log, t.fillPercent, t.limiter) + runRebuild(ctx, bs, mb, log, t.fillPercent, t.concurrencyLimiter) } } }() } func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *logger.Logger, - fillPercent int, limiter RebuildWorkerLimiter, + fillPercent int, concLimiter common.RebuildLimiter, ) { select { case <-ctx.Done(): @@ -107,21 +80,21 @@ func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *lo log.Info(ctx, logs.BlobstoreRebuildStarted) ctx = tagging.ContextWithIOTag(ctx, qos.IOTagBackground.String()) // TODO use shard limiter - if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, limiter, fillPercent); err != nil { + if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, concLimiter, fillPercent); err != nil { log.Warn(ctx, logs.FailedToRebuildBlobstore, zap.Error(err)) } else { log.Info(ctx, logs.BlobstoreRebuildCompletedSuccessfully) } } -func (r *rebuilder) ScheduleRebuild(ctx context.Context, limiter RebuildWorkerLimiter, fillPercent int, +func (r *rebuilder) ScheduleRebuild(ctx context.Context, limiter common.RebuildLimiter, fillPercent int, ) error { select { case <-ctx.Done(): return ctx.Err() case r.tasks <- rebuildTask{ - limiter: limiter, - fillPercent: fillPercent, + concurrencyLimiter: limiter, + fillPercent: fillPercent, }: return nil default: @@ -170,7 +143,7 @@ func (u *mbStorageIDUpdate) UpdateStorageID(ctx context.Context, addr oid.Addres } type RebuildPrm struct { - ConcurrencyLimiter RebuildWorkerLimiter + ConcurrencyLimiter common.ConcurrencyLimiter TargetFillPercent uint32 } From b9360be1dcd8b08ab20e2a73a150ceadeeeea966 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 7 Feb 2025 17:25:47 +0300 Subject: [PATCH 1213/1413] [#1636] blobovniczatree: Use RebuildLimiter Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/rebuild.go | 40 +++++++++++++++---- .../blobstor/blobovniczatree/rebuild_test.go | 8 ++++ .../blobstor/common/rebuild.go | 6 +++ pkg/local_object_storage/shard/rebuild.go | 28 ++++++++++++- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index cbd45c3b4d..7ef3317fd3 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -50,7 +50,7 @@ func (b *Blobovniczas) Rebuild(ctx context.Context, prm common.RebuildPrm) (comm var res common.RebuildRes b.log.Debug(ctx, logs.BlobovniczaTreeCompletingPreviousRebuild) - completedPreviosMoves, err := b.completeIncompletedMove(ctx, prm.MetaStorage) + completedPreviosMoves, err := b.completeIncompletedMove(ctx, prm.MetaStorage, prm.Limiter) res.ObjectsMoved += completedPreviosMoves if err != nil { b.log.Warn(ctx, logs.BlobovniczaTreeCompletedPreviousRebuildFailed, zap.Error(err)) @@ -238,7 +238,7 @@ func (b *Blobovniczas) addRebuildTempFile(ctx context.Context, path string) (fun }, nil } -func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, blzPath string, meta common.MetaStorage, concLimiter common.RebuildLimiter) (uint64, error) { +func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovnicza, blzPath string, meta common.MetaStorage, limiter common.RebuildLimiter) (uint64, error) { var result atomic.Uint64 batch := make(map[oid.Address][]byte) @@ -253,7 +253,12 @@ func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovn }) for { - _, err := blz.Iterate(ctx, prm) + release, err := limiter.ReadRequest(ctx) + if err != nil { + return result.Load(), err + } + _, err = blz.Iterate(ctx, prm) + release() if err != nil && !errors.Is(err, errBatchFull) { return result.Load(), err } @@ -265,14 +270,19 @@ func (b *Blobovniczas) moveObjects(ctx context.Context, blz *blobovnicza.Blobovn eg, egCtx := errgroup.WithContext(ctx) for addr, data := range batch { - release, err := concLimiter.AcquireWorkSlot(egCtx) + release, err := limiter.AcquireWorkSlot(egCtx) if err != nil { _ = eg.Wait() return result.Load(), err } eg.Go(func() error { defer release() - err := b.moveObject(egCtx, blz, blzPath, addr, data, meta) + moveRelease, err := limiter.WriteRequest(ctx) + if err != nil { + return err + } + err = b.moveObject(egCtx, blz, blzPath, addr, data, meta) + moveRelease() if err == nil { result.Add(1) } @@ -360,7 +370,7 @@ func (b *Blobovniczas) dropDirectoryIfEmpty(path string) error { return b.dropDirectoryIfEmpty(filepath.Dir(path)) } -func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore common.MetaStorage) (uint64, error) { +func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore common.MetaStorage, rateLimiter common.RateLimiter) (uint64, error) { var count uint64 var rebuildTempFilesToRemove []string err := b.iterateIncompletedRebuildDBPaths(ctx, func(s string) (bool, error) { @@ -373,13 +383,24 @@ func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore co } defer shDB.Close(ctx) + release, err := rateLimiter.ReadRequest(ctx) + if err != nil { + return false, err + } incompletedMoves, err := blz.ListMoveInfo(ctx) + release() if err != nil { return true, err } for _, move := range incompletedMoves { - if err := b.performMove(ctx, blz, shDB.SystemPath(), move, metaStore); err != nil { + release, err := rateLimiter.WriteRequest(ctx) + if err != nil { + return false, err + } + err = b.performMove(ctx, blz, shDB.SystemPath(), move, metaStore) + release() + if err != nil { return true, err } count++ @@ -389,9 +410,14 @@ func (b *Blobovniczas) completeIncompletedMove(ctx context.Context, metaStore co return false, nil }) for _, tmp := range rebuildTempFilesToRemove { + release, err := rateLimiter.WriteRequest(ctx) + if err != nil { + return count, err + } if err := os.Remove(filepath.Join(b.rootPath, tmp)); err != nil { b.log.Warn(ctx, logs.BlobovniczatreeFailedToRemoveRebuildTempFile, zap.Error(err)) } + release() } return count, err } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index e26c485ba4..865d04a8f0 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -467,3 +467,11 @@ type rebuildLimiterStub struct{} func (s *rebuildLimiterStub) AcquireWorkSlot(context.Context) (common.ReleaseFunc, error) { return func() {}, nil } + +func (s *rebuildLimiterStub) ReadRequest(context.Context) (common.ReleaseFunc, error) { + return func() {}, nil +} + +func (s *rebuildLimiterStub) WriteRequest(context.Context) (common.ReleaseFunc, error) { + return func() {}, nil +} diff --git a/pkg/local_object_storage/blobstor/common/rebuild.go b/pkg/local_object_storage/blobstor/common/rebuild.go index 4615190f78..788fe66f25 100644 --- a/pkg/local_object_storage/blobstor/common/rebuild.go +++ b/pkg/local_object_storage/blobstor/common/rebuild.go @@ -27,6 +27,12 @@ type ConcurrencyLimiter interface { AcquireWorkSlot(ctx context.Context) (ReleaseFunc, error) } +type RateLimiter interface { + ReadRequest(context.Context) (ReleaseFunc, error) + WriteRequest(context.Context) (ReleaseFunc, error) +} + type RebuildLimiter interface { ConcurrencyLimiter + RateLimiter } diff --git a/pkg/local_object_storage/shard/rebuild.go b/pkg/local_object_storage/shard/rebuild.go index 3aa94d5a3d..20f1f2b6f8 100644 --- a/pkg/local_object_storage/shard/rebuild.go +++ b/pkg/local_object_storage/shard/rebuild.go @@ -79,7 +79,6 @@ func runRebuild(ctx context.Context, bs *blobstor.BlobStor, mb *meta.DB, log *lo } log.Info(ctx, logs.BlobstoreRebuildStarted) ctx = tagging.ContextWithIOTag(ctx, qos.IOTagBackground.String()) - // TODO use shard limiter if err := bs.Rebuild(ctx, &mbStorageIDUpdate{mb: mb}, concLimiter, fillPercent); err != nil { log.Warn(ctx, logs.FailedToRebuildBlobstore, zap.Error(err)) } else { @@ -165,5 +164,30 @@ func (s *Shard) ScheduleRebuild(ctx context.Context, p RebuildPrm) error { return ErrDegradedMode } - return s.rb.ScheduleRebuild(ctx, p.ConcurrencyLimiter, int(p.TargetFillPercent)) + limiter := &rebuildLimiter{ + concurrencyLimiter: p.ConcurrencyLimiter, + rateLimiter: s.opsLimiter, + } + return s.rb.ScheduleRebuild(ctx, limiter, int(p.TargetFillPercent)) +} + +var _ common.RebuildLimiter = (*rebuildLimiter)(nil) + +type rebuildLimiter struct { + concurrencyLimiter common.ConcurrencyLimiter + rateLimiter qos.Limiter +} + +func (r *rebuildLimiter) AcquireWorkSlot(ctx context.Context) (common.ReleaseFunc, error) { + return r.concurrencyLimiter.AcquireWorkSlot(ctx) +} + +func (r *rebuildLimiter) ReadRequest(ctx context.Context) (common.ReleaseFunc, error) { + release, err := r.rateLimiter.ReadRequest(ctx) + return common.ReleaseFunc(release), err +} + +func (r *rebuildLimiter) WriteRequest(ctx context.Context) (common.ReleaseFunc, error) { + release, err := r.rateLimiter.WriteRequest(ctx) + return common.ReleaseFunc(release), err } From 2162f8e189a318550f55825755862a4e2a6a3e7b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 10 Feb 2025 17:55:34 +0300 Subject: [PATCH 1214/1413] [#1636] object: Fix IO tag adjustment for Put/Patch There was no tag adjustment for CloseAndRecv. Signed-off-by: Dmitrii Stepanov --- pkg/services/object/qos.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/pkg/services/object/qos.go b/pkg/services/object/qos.go index 145a316e24..01eb1ea8da 100644 --- a/pkg/services/object/qos.go +++ b/pkg/services/object/qos.go @@ -3,6 +3,8 @@ package object import ( "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" ) @@ -120,13 +122,24 @@ type qosSendRecv[TReq qosVerificationHeader, TResp any] interface { type qosWriteStream[TReq qosVerificationHeader, TResp any] struct { s qosSendRecv[TReq, TResp] adj AdjustIOTag + + ioTag string + ioTagDefined bool } func (q *qosWriteStream[TReq, TResp]) CloseAndRecv(ctx context.Context) (TResp, error) { + if q.ioTagDefined { + ctx = tagging.ContextWithIOTag(ctx, q.ioTag) + } return q.s.CloseAndRecv(ctx) } func (q *qosWriteStream[TReq, TResp]) Send(ctx context.Context, req TReq) error { - ctx = q.adj.AdjustIncomingTag(ctx, req.GetVerificationHeader().GetBodySignature().GetKey()) + if !q.ioTagDefined { + ctx = q.adj.AdjustIncomingTag(ctx, req.GetVerificationHeader().GetBodySignature().GetKey()) + q.ioTag, q.ioTagDefined = tagging.IOTagFromContext(ctx) + } + assert.True(q.ioTagDefined, "io tag undefined after incoming tag adjustment") + ctx = tagging.ContextWithIOTag(ctx, q.ioTag) return q.s.Send(ctx, req) } From c2d855aedd11258c37126c5920e7e0ffde42425d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 12 Feb 2025 16:45:39 +0300 Subject: [PATCH 1215/1413] [#1636] qos: Return Resource Exhausted error Signed-off-by: Dmitrii Stepanov --- internal/qos/limiter.go | 8 ++++++++ pkg/local_object_storage/engine/engine.go | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index 996cebea1a..3b6c6547c9 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -2,6 +2,7 @@ package qos import ( "context" + "errors" "fmt" "time" @@ -9,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-qos/scheduling" "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) const ( @@ -110,6 +112,9 @@ func (n *mClockLimiter) ReadRequest(ctx context.Context) (ReleaseFunc, error) { } rel, err := n.readScheduler.RequestArrival(ctx, tag) if err != nil { + if errors.Is(err, scheduling.ErrMClockSchedulerRequestLimitExceeded) { + return nil, &apistatus.ResourceExhausted{} + } return nil, err } return ReleaseFunc(rel), nil @@ -125,6 +130,9 @@ func (n *mClockLimiter) WriteRequest(ctx context.Context) (ReleaseFunc, error) { } rel, err := n.writeScheduler.RequestArrival(ctx, tag) if err != nil { + if errors.Is(err, scheduling.ErrMClockSchedulerRequestLimitExceeded) { + return nil, &apistatus.ResourceExhausted{} + } return nil, err } return ReleaseFunc(rel), nil diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 85652b3ae3..e13252b824 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" ) @@ -176,7 +177,10 @@ func (e *StorageEngine) reportShardError( } func isLogical(err error) bool { - return errors.As(err, &logicerr.Logical{}) || errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) + return errors.As(err, &logicerr.Logical{}) || + errors.Is(err, context.Canceled) || + errors.Is(err, context.DeadlineExceeded) || + errors.As(err, new(*apistatus.ResourceExhausted)) } // Option represents StorageEngine's constructor option. From 8ed71a969e256ee2410a1f089c8e41103ac63143 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 14 Feb 2025 10:05:06 +0300 Subject: [PATCH 1216/1413] [#1636] qos: Add semaphore limiter If no tags specified, then limiter could be optimized to use atomic semaphore. Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- internal/qos/limiter.go | 50 ++++++++++++++++++++------------------- internal/qos/semaphore.go | 39 ++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 27 deletions(-) create mode 100644 internal/qos/semaphore.go diff --git a/go.mod b/go.mod index 2bfc3abfe7..bbb8179577 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 - git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250213125059-356851eed3bf + git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 diff --git a/go.sum b/go.sum index 4a7dfd4dc4..0c66f45553 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 h1:Mxw1c/8t96vFIUOffl28lFaHKi413oCBfLMGJmF9cFA= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250213125059-356851eed3bf h1:ik2aMBpTJJpoZe2ffcGShXRkrvny65NEPLVt67KmH/A= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250213125059-356851eed3bf/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3 h1:QnAt5b2R6+hQthMOIn5ECfLAlVD8IAE5JRm1NCCOmuE= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4 h1:dOZHuOywvH1ms8U38lDCWpysgkCCeJ02RLI7zDhPcyw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index 3b6c6547c9..b1406a7f37 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -7,7 +7,6 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-qos/scheduling" "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -26,6 +25,11 @@ type Limiter interface { Close() } +type scheduler interface { + RequestArrival(ctx context.Context, tag string) (scheduling.ReleaseFunc, error) + Close() +} + func NewLimiter(c *limits.Config) (Limiter, error) { if err := validateConfig(c); err != nil { return nil, err @@ -34,15 +38,11 @@ func NewLimiter(c *limits.Config) (Limiter, error) { if isNoop(read, write) { return noopLimiterInstance, nil } - readScheduler, err := scheduling.NewMClock( - uint64(read.MaxRunningOps), uint64(read.MaxWaitingOps), - converToSchedulingTags(read.Tags), read.IdleTimeout) + readScheduler, err := createScheduler(c.Read()) if err != nil { return nil, fmt.Errorf("create read scheduler: %w", err) } - writeScheduler, err := scheduling.NewMClock( - uint64(write.MaxRunningOps), uint64(write.MaxWaitingOps), - converToSchedulingTags(write.Tags), write.IdleTimeout) + writeScheduler, err := createScheduler(c.Write()) if err != nil { return nil, fmt.Errorf("create write scheduler: %w", err) } @@ -52,6 +52,15 @@ func NewLimiter(c *limits.Config) (Limiter, error) { }, nil } +func createScheduler(config limits.OpConfig) (scheduler, error) { + if len(config.Tags) == 0 && config.MaxWaitingOps == limits.NoLimit { + return newSemaphoreScheduler(config.MaxRunningOps), nil + } + return scheduling.NewMClock( + uint64(config.MaxRunningOps), uint64(config.MaxWaitingOps), + converToSchedulingTags(config.Tags), config.IdleTimeout) +} + func converToSchedulingTags(limits []limits.IOTagConfig) map[string]scheduling.TagInfo { result := make(map[string]scheduling.TagInfo) for _, tag := range []IOTag{IOTagClient, IOTagBackground, IOTagInternal, IOTagPolicer, IOTagWritecache} { @@ -100,27 +109,19 @@ func (n *noopLimiter) Close() {} var _ Limiter = (*mClockLimiter)(nil) type mClockLimiter struct { - readScheduler *scheduling.MClock - writeScheduler *scheduling.MClock + readScheduler scheduler + writeScheduler scheduler } func (n *mClockLimiter) ReadRequest(ctx context.Context) (ReleaseFunc, error) { - tag, ok := tagging.IOTagFromContext(ctx) - assert.True(ok, "request has no tag") - if tag == IOTagCritical.String() { - return releaseStub, nil - } - rel, err := n.readScheduler.RequestArrival(ctx, tag) - if err != nil { - if errors.Is(err, scheduling.ErrMClockSchedulerRequestLimitExceeded) { - return nil, &apistatus.ResourceExhausted{} - } - return nil, err - } - return ReleaseFunc(rel), nil + return requestArrival(ctx, n.readScheduler) } func (n *mClockLimiter) WriteRequest(ctx context.Context) (ReleaseFunc, error) { + return requestArrival(ctx, n.writeScheduler) +} + +func requestArrival(ctx context.Context, s scheduler) (ReleaseFunc, error) { tag, ok := tagging.IOTagFromContext(ctx) if !ok { tag = IOTagClient.String() @@ -128,9 +129,10 @@ func (n *mClockLimiter) WriteRequest(ctx context.Context) (ReleaseFunc, error) { if tag == IOTagCritical.String() { return releaseStub, nil } - rel, err := n.writeScheduler.RequestArrival(ctx, tag) + rel, err := s.RequestArrival(ctx, tag) if err != nil { - if errors.Is(err, scheduling.ErrMClockSchedulerRequestLimitExceeded) { + if errors.Is(err, scheduling.ErrMClockSchedulerRequestLimitExceeded) || + errors.Is(err, errSemaphoreLimitExceeded) { return nil, &apistatus.ResourceExhausted{} } return nil, err diff --git a/internal/qos/semaphore.go b/internal/qos/semaphore.go new file mode 100644 index 0000000000..74e6928f32 --- /dev/null +++ b/internal/qos/semaphore.go @@ -0,0 +1,39 @@ +package qos + +import ( + "context" + "errors" + + qosSemaphore "git.frostfs.info/TrueCloudLab/frostfs-qos/limiting/semaphore" + "git.frostfs.info/TrueCloudLab/frostfs-qos/scheduling" +) + +var ( + _ scheduler = (*semaphore)(nil) + errSemaphoreLimitExceeded = errors.New("semaphore limit exceeded") +) + +type semaphore struct { + s *qosSemaphore.Semaphore +} + +func newSemaphoreScheduler(size int64) *semaphore { + return &semaphore{ + s: qosSemaphore.NewSemaphore(size), + } +} + +func (s *semaphore) Close() {} + +func (s *semaphore) RequestArrival(ctx context.Context, _ string) (scheduling.ReleaseFunc, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + + if s.s.Acquire() { + return s.s.Release, nil + } + return nil, errSemaphoreLimitExceeded +} From 401d96a89e179026b210729d261399b7d5874905 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 21 Feb 2025 16:37:00 +0300 Subject: [PATCH 1217/1413] [#1636] config: Refactor newConfig and oldConfig `newConfig` is actually target config to set config values from source (which is called `oldConfig`). Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 80 +++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index b422755382..afde0bbc0c 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -256,42 +256,42 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { return engineconfig.IterateShards(c, false, func(sc *shardconfig.Config) error { return a.updateShardConfig(c, sc) }) } -func (a *applicationConfiguration) updateShardConfig(c *config.Config, oldConfig *shardconfig.Config) error { - var newConfig shardCfg +func (a *applicationConfiguration) updateShardConfig(c *config.Config, source *shardconfig.Config) error { + var target shardCfg - newConfig.refillMetabase = oldConfig.RefillMetabase() - newConfig.refillMetabaseWorkersCount = oldConfig.RefillMetabaseWorkersCount() - newConfig.mode = oldConfig.Mode() - newConfig.compress = oldConfig.Compress() - newConfig.estimateCompressibility = oldConfig.EstimateCompressibility() - newConfig.estimateCompressibilityThreshold = oldConfig.EstimateCompressibilityThreshold() - newConfig.uncompressableContentType = oldConfig.UncompressableContentTypes() - newConfig.smallSizeObjectLimit = oldConfig.SmallSizeLimit() + target.refillMetabase = source.RefillMetabase() + target.refillMetabaseWorkersCount = source.RefillMetabaseWorkersCount() + target.mode = source.Mode() + target.compress = source.Compress() + target.estimateCompressibility = source.EstimateCompressibility() + target.estimateCompressibilityThreshold = source.EstimateCompressibilityThreshold() + target.uncompressableContentType = source.UncompressableContentTypes() + target.smallSizeObjectLimit = source.SmallSizeLimit() - a.setShardWriteCacheConfig(&newConfig, oldConfig) + a.setShardWriteCacheConfig(&target, source) - a.setShardPiloramaConfig(c, &newConfig, oldConfig) + a.setShardPiloramaConfig(c, &target, source) - if err := a.setShardStorageConfig(&newConfig, oldConfig); err != nil { + if err := a.setShardStorageConfig(&target, source); err != nil { return err } - a.setMetabaseConfig(&newConfig, oldConfig) + a.setMetabaseConfig(&target, source) - a.setGCConfig(&newConfig, oldConfig) - if err := a.setLimiter(&newConfig, oldConfig); err != nil { + a.setGCConfig(&target, source) + if err := a.setLimiter(&target, source); err != nil { return err } - a.EngineCfg.shards = append(a.EngineCfg.shards, newConfig) + a.EngineCfg.shards = append(a.EngineCfg.shards, target) return nil } -func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, oldConfig *shardconfig.Config) { - writeCacheCfg := oldConfig.WriteCache() +func (a *applicationConfiguration) setShardWriteCacheConfig(target *shardCfg, source *shardconfig.Config) { + writeCacheCfg := source.WriteCache() if writeCacheCfg.Enabled() { - wc := &newConfig.writecacheCfg + wc := &target.writecacheCfg wc.enabled = true wc.path = writeCacheCfg.Path() @@ -304,10 +304,10 @@ func (a *applicationConfiguration) setShardWriteCacheConfig(newConfig *shardCfg, } } -func (a *applicationConfiguration) setShardPiloramaConfig(c *config.Config, newConfig *shardCfg, oldConfig *shardconfig.Config) { +func (a *applicationConfiguration) setShardPiloramaConfig(c *config.Config, target *shardCfg, source *shardconfig.Config) { if config.BoolSafe(c.Sub("tree"), "enabled") { - piloramaCfg := oldConfig.Pilorama() - pr := &newConfig.piloramaCfg + piloramaCfg := source.Pilorama() + pr := &target.piloramaCfg pr.enabled = true pr.path = piloramaCfg.Path() @@ -318,8 +318,8 @@ func (a *applicationConfiguration) setShardPiloramaConfig(c *config.Config, newC } } -func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, oldConfig *shardconfig.Config) error { - blobStorCfg := oldConfig.BlobStor() +func (a *applicationConfiguration) setShardStorageConfig(target *shardCfg, source *shardconfig.Config) error { + blobStorCfg := source.BlobStor() storagesCfg := blobStorCfg.Storages() ss := make([]subStorageCfg, 0, len(storagesCfg)) @@ -353,13 +353,13 @@ func (a *applicationConfiguration) setShardStorageConfig(newConfig *shardCfg, ol ss = append(ss, sCfg) } - newConfig.subStorages = ss + target.subStorages = ss return nil } -func (a *applicationConfiguration) setMetabaseConfig(newConfig *shardCfg, oldConfig *shardconfig.Config) { - metabaseCfg := oldConfig.Metabase() - m := &newConfig.metaCfg +func (a *applicationConfiguration) setMetabaseConfig(target *shardCfg, source *shardconfig.Config) { + metabaseCfg := source.Metabase() + m := &target.metaCfg m.path = metabaseCfg.Path() m.perm = metabaseCfg.BoltDB().Perm() @@ -367,24 +367,24 @@ func (a *applicationConfiguration) setMetabaseConfig(newConfig *shardCfg, oldCon m.maxBatchSize = metabaseCfg.BoltDB().MaxBatchSize() } -func (a *applicationConfiguration) setGCConfig(newConfig *shardCfg, oldConfig *shardconfig.Config) { - gcCfg := oldConfig.GC() - newConfig.gcCfg.removerBatchSize = gcCfg.RemoverBatchSize() - newConfig.gcCfg.removerSleepInterval = gcCfg.RemoverSleepInterval() - newConfig.gcCfg.expiredCollectorBatchSize = gcCfg.ExpiredCollectorBatchSize() - newConfig.gcCfg.expiredCollectorWorkerCount = gcCfg.ExpiredCollectorWorkerCount() +func (a *applicationConfiguration) setGCConfig(target *shardCfg, source *shardconfig.Config) { + gcCfg := source.GC() + target.gcCfg.removerBatchSize = gcCfg.RemoverBatchSize() + target.gcCfg.removerSleepInterval = gcCfg.RemoverSleepInterval() + target.gcCfg.expiredCollectorBatchSize = gcCfg.ExpiredCollectorBatchSize() + target.gcCfg.expiredCollectorWorkerCount = gcCfg.ExpiredCollectorWorkerCount() } -func (a *applicationConfiguration) setLimiter(newConfig *shardCfg, oldConfig *shardconfig.Config) error { - limitsConfig := oldConfig.Limits() +func (a *applicationConfiguration) setLimiter(target *shardCfg, source *shardconfig.Config) error { + limitsConfig := source.Limits() limiter, err := qos.NewLimiter(limitsConfig) if err != nil { return err } - if newConfig.limiter != nil { - newConfig.limiter.Close() + if target.limiter != nil { + target.limiter.Close() } - newConfig.limiter = limiter + target.limiter = limiter return nil } From 6c6e463b73d0d7afbdd7f7142d0c9f20a59f871c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 24 Feb 2025 16:06:07 +0300 Subject: [PATCH 1218/1413] [#1636] shard: Change ops limiter on shard reload Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/control.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 3520277c02..6dee2da3f6 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -449,6 +449,10 @@ func (s *Shard) Reload(ctx context.Context, opts ...Option) error { return err } } + if c.opsLimiter != nil { + s.opsLimiter.Close() + s.opsLimiter = c.opsLimiter + } return s.setMode(ctx, c.info.Mode) } From eb8b9b2b3bd933e4fa7bfc7ffc8ea80beb49d522 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Feb 2025 10:04:24 +0300 Subject: [PATCH 1219/1413] [#1636] blobovniczatree: Validate limiter release in rebuild unit tests Signed-off-by: Dmitrii Stepanov --- .../blobovniczatree/rebuild_failover_test.go | 4 +- .../blobstor/blobovniczatree/rebuild_test.go | 54 +++++++++++++++---- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index 91578d5e86..8832603c44 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -161,9 +161,10 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object storageIDs: make(map[oid.Address][]byte), guard: &sync.Mutex{}, } + limiter := &rebuildLimiterStub{} rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, - Limiter: &rebuildLimiterStub{}, + Limiter: limiter, FillPercent: 1, }) require.NoError(t, err) @@ -171,6 +172,7 @@ func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object require.Equal(t, uint64(0), rRes.FilesRemoved) require.NoError(t, b.Close(context.Background())) + require.NoError(t, limiter.ValidateReleased()) blz := blobovnicza.New(blobovnicza.WithPath(filepath.Join(dir, "0", "0", "1.db"))) require.NoError(t, blz.Open(context.Background())) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 865d04a8f0..9c971bfb62 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -2,7 +2,9 @@ package blobovniczatree import ( "context" + "fmt" "sync" + "sync/atomic" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" @@ -76,9 +78,10 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { storageIDs: storageIDs, guard: &sync.Mutex{}, } + limiter := &rebuildLimiterStub{} rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, - Limiter: &rebuildLimiterStub{}, + Limiter: limiter, FillPercent: 60, }) require.NoError(t, err) @@ -94,6 +97,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { } require.NoError(t, b.Close(context.Background())) + require.NoError(t, limiter.ValidateReleased()) }) t.Run("no rebuild single db", func(t *testing.T) { @@ -128,9 +132,10 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { storageIDs: storageIDs, guard: &sync.Mutex{}, } + limiter := &rebuildLimiterStub{} rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, - Limiter: &rebuildLimiterStub{}, + Limiter: limiter, FillPercent: 90, // 64KB / 100KB = 64% }) require.NoError(t, err) @@ -146,6 +151,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { } require.NoError(t, b.Close(context.Background())) + require.NoError(t, limiter.ValidateReleased()) }) t.Run("rebuild by fill percent", func(t *testing.T) { @@ -193,9 +199,10 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { storageIDs: storageIDs, guard: &sync.Mutex{}, } + limiter := &rebuildLimiterStub{} rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, - Limiter: &rebuildLimiterStub{}, + Limiter: limiter, FillPercent: 80, }) require.NoError(t, err) @@ -215,6 +222,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { } require.NoError(t, b.Close(context.Background())) + require.NoError(t, limiter.ValidateReleased()) }) t.Run("rebuild by overflow", func(t *testing.T) { @@ -266,9 +274,10 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, b.Open(mode.ComponentReadWrite)) require.NoError(t, b.Init()) + limiter := &rebuildLimiterStub{} rRes, err := b.Rebuild(context.Background(), common.RebuildPrm{ MetaStorage: metaStub, - Limiter: &rebuildLimiterStub{}, + Limiter: limiter, FillPercent: 80, }) require.NoError(t, err) @@ -285,6 +294,7 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { } require.NoError(t, b.Close(context.Background())) + require.NoError(t, limiter.ValidateReleased()) }) } @@ -338,9 +348,10 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { storageIDs: storageIDs, guard: &sync.Mutex{}, } + limiter := &rebuildLimiterStub{} var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub - rPrm.Limiter = &rebuildLimiterStub{} + rPrm.Limiter = limiter rPrm.FillPercent = 1 rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) @@ -356,6 +367,7 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { } require.NoError(t, b.Close(context.Background())) + require.NoError(t, limiter.ValidateReleased()) } func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, targetDepth, targetWidth uint64, shouldMigrate bool) { @@ -427,9 +439,10 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta storageIDs: storageIDs, guard: &sync.Mutex{}, } + limiter := &rebuildLimiterStub{} var rPrm common.RebuildPrm rPrm.MetaStorage = metaStub - rPrm.Limiter = &rebuildLimiterStub{} + rPrm.Limiter = limiter rPrm.FillPercent = 1 rRes, err := b.Rebuild(context.Background(), rPrm) require.NoError(t, err) @@ -445,6 +458,7 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta } require.NoError(t, b.Close(context.Background())) + require.NoError(t, limiter.ValidateReleased()) } type storageIDUpdateStub struct { @@ -462,16 +476,36 @@ func (s *storageIDUpdateStub) UpdateStorageID(ctx context.Context, addr oid.Addr return nil } -type rebuildLimiterStub struct{} +type rebuildLimiterStub struct { + slots atomic.Int64 + readRequests atomic.Int64 + writeRequests atomic.Int64 +} func (s *rebuildLimiterStub) AcquireWorkSlot(context.Context) (common.ReleaseFunc, error) { - return func() {}, nil + s.slots.Add(1) + return func() { s.slots.Add(-1) }, nil } func (s *rebuildLimiterStub) ReadRequest(context.Context) (common.ReleaseFunc, error) { - return func() {}, nil + s.readRequests.Add(1) + return func() { s.readRequests.Add(-1) }, nil } func (s *rebuildLimiterStub) WriteRequest(context.Context) (common.ReleaseFunc, error) { - return func() {}, nil + s.writeRequests.Add(1) + return func() { s.writeRequests.Add(-1) }, nil +} + +func (s *rebuildLimiterStub) ValidateReleased() error { + if v := s.slots.Load(); v != 0 { + return fmt.Errorf("invalid slots value %d", v) + } + if v := s.readRequests.Load(); v != 0 { + return fmt.Errorf("invalid read requests value %d", v) + } + if v := s.writeRequests.Load(); v != 0 { + return fmt.Errorf("invalid write requests value %d", v) + } + return nil } From 4685afb1dc5737a70833231031582fda29476835 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Feb 2025 10:21:30 +0300 Subject: [PATCH 1220/1413] [#1636] engine: Validate limiter release in unit tests Signed-off-by: Dmitrii Stepanov --- .../engine/engine_test.go | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 926ff43f3c..7ddde1f024 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -3,8 +3,10 @@ package engine import ( "context" "path/filepath" + "sync/atomic" "testing" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" @@ -90,6 +92,7 @@ func testGetDefaultShardOptions(t testing.TB) []shard.Option { ), shard.WithPiloramaOptions(pilorama.WithPath(filepath.Join(t.TempDir(), "pilorama"))), shard.WithMetaBaseOptions(testGetDefaultMetabaseOptions(t)...), + shard.WithLimiter(&testQoSLimiter{t: t}), } } @@ -151,3 +154,26 @@ func newTestStorages(root string, smallSize uint64) ([]blobstor.SubStorage, *tes }, }, smallFileStorage, largeFileStorage } + +var _ qos.Limiter = (*testQoSLimiter)(nil) + +type testQoSLimiter struct { + t testing.TB + read atomic.Int64 + write atomic.Int64 +} + +func (t *testQoSLimiter) Close() { + require.Equal(t.t, int64(0), t.read.Load(), "read requests count after limiter close must be 0") + require.Equal(t.t, int64(0), t.write.Load(), "write requests count after limiter close must be 0") +} + +func (t *testQoSLimiter) ReadRequest(context.Context) (qos.ReleaseFunc, error) { + t.read.Add(1) + return func() { t.read.Add(-1) }, nil +} + +func (t *testQoSLimiter) WriteRequest(context.Context) (qos.ReleaseFunc, error) { + t.write.Add(1) + return func() { t.write.Add(-1) }, nil +} From 5ba0e2918e60146fe64d9e5c159629f279fe079d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 4 Mar 2025 10:16:20 +0300 Subject: [PATCH 1221/1413] [#1661] cli: Clarify `--rpc-endpoint` values `multiaddr` is not something an average user knows. Personally, I have never used it in CLI. On the other hand, we need to connect with TLS quite often, so it needs to be mentioned in help. Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/internal/commonflags/flags.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/internal/commonflags/flags.go b/cmd/frostfs-cli/internal/commonflags/flags.go index cd46d63eb5..fad1f6183e 100644 --- a/cmd/frostfs-cli/internal/commonflags/flags.go +++ b/cmd/frostfs-cli/internal/commonflags/flags.go @@ -28,7 +28,7 @@ const ( RPC = "rpc-endpoint" RPCShorthand = "r" RPCDefault = "" - RPCUsage = "Remote node address (as 'multiaddr' or ':')" + RPCUsage = "Remote node address (':' or 'grpcs://:')" Timeout = "timeout" TimeoutShorthand = "t" From bf8914fedc401fc7a8d17e7a8dc23f6776102a66 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 11 Nov 2024 12:33:31 +0300 Subject: [PATCH 1222/1413] [#1416] lens/explorer: Support metabase schema v3 Signed-off-by: Aleksey Savchuk --- cmd/frostfs-lens/internal/meta/tui.go | 49 ++++++++++++++++++- .../schema/metabase/buckets/parsers.go | 17 ++++++- .../schema/metabase/buckets/prefix.go | 40 ++++++++------- .../schema/metabase/buckets/string.go | 6 +-- .../internal/schema/metabase/buckets/types.go | 19 +++++-- .../internal/schema/metabase/parser.go | 27 +++++++++- .../schema/metabase/records/detailed.go | 8 +++ .../schema/metabase/records/filter.go | 23 +++++++++ .../schema/metabase/records/parsers.go | 42 ++++++++++++++++ .../schema/metabase/records/string.go | 20 ++++++++ .../internal/schema/metabase/records/types.go | 11 +++++ 11 files changed, 233 insertions(+), 29 deletions(-) diff --git a/cmd/frostfs-lens/internal/meta/tui.go b/cmd/frostfs-lens/internal/meta/tui.go index 5a41f945c0..7b0e25f3d2 100644 --- a/cmd/frostfs-lens/internal/meta/tui.go +++ b/cmd/frostfs-lens/internal/meta/tui.go @@ -2,13 +2,17 @@ package meta import ( "context" + "encoding/binary" + "errors" "fmt" common "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal" + schemaCommon "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" schema "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/tui" "github.com/rivo/tview" "github.com/spf13/cobra" + "go.etcd.io/bbolt" ) var tuiCMD = &cobra.Command{ @@ -27,6 +31,11 @@ Available search filters: var initialPrompt string +var parserPerSchemaVersion = map[uint64]schemaCommon.Parser{ + 2: schema.MetabaseParserV2, + 3: schema.MetabaseParserV3, +} + func init() { common.AddComponentPathFlag(tuiCMD, &vPath) @@ -49,12 +58,22 @@ func runTUI(cmd *cobra.Command) error { } defer db.Close() + schemaVersion, hasVersion := lookupSchemaVersion(cmd, db) + if !hasVersion { + return errors.New("couldn't detect schema version") + } + + metabaseParser, ok := parserPerSchemaVersion[schemaVersion] + if !ok { + return fmt.Errorf("unknown schema version %d", schemaVersion) + } + // Need if app was stopped with Ctrl-C. ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() app := tview.NewApplication() - ui := tui.NewUI(ctx, app, db, schema.MetabaseParser, nil) + ui := tui.NewUI(ctx, app, db, metabaseParser, nil) _ = ui.AddFilter("cid", tui.CIDParser, "CID") _ = ui.AddFilter("oid", tui.OIDParser, "OID") @@ -69,3 +88,31 @@ func runTUI(cmd *cobra.Command) error { app.SetRoot(ui, true).SetFocus(ui) return app.Run() } + +var ( + shardInfoBucket = []byte{5} + versionRecord = []byte("version") +) + +func lookupSchemaVersion(cmd *cobra.Command, db *bbolt.DB) (version uint64, ok bool) { + err := db.View(func(tx *bbolt.Tx) error { + bkt := tx.Bucket(shardInfoBucket) + if bkt == nil { + return nil + } + rec := bkt.Get(versionRecord) + if rec == nil { + return nil + } + + version = binary.LittleEndian.Uint64(rec) + ok = true + + return nil + }) + if err != nil { + common.ExitOnErr(cmd, fmt.Errorf("couldn't lookup version: %w", err)) + } + + return +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/parsers.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/parsers.go index 24cc0e52d1..4e6bbf08ac 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/buckets/parsers.go +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/parsers.go @@ -80,10 +80,15 @@ var ( }, ) - UserAttributeParser = NewUserAttributeKeyBucketParser( + UserAttributeParserV2 = NewUserAttributeKeyBucketParser( NewUserAttributeValueBucketParser(records.UserAttributeRecordParser), ) + UserAttributeParserV3 = NewUserAttributeKeyBucketParserWithSpecificKeys( + NewUserAttributeValueBucketParser(records.UserAttributeRecordParser), + []string{"FilePath", "S3-Access-Box-CRDT-Name"}, + ) + PayloadHashParser = NewPrefixContainerBucketParser(PayloadHash, records.PayloadHashRecordParser, Resolvers{ cidResolver: StrictResolver, oidResolver: StrictResolver, @@ -108,4 +113,14 @@ var ( cidResolver: StrictResolver, oidResolver: LenientResolver, }) + + ExpirationEpochToObjectParser = NewPrefixBucketParser(ExpirationEpochToObject, records.ExpirationEpochToObjectRecordParser, Resolvers{ + cidResolver: LenientResolver, + oidResolver: LenientResolver, + }) + + ObjectToExpirationEpochParser = NewPrefixContainerBucketParser(ObjectToExpirationEpoch, records.ObjectToExpirationEpochRecordParser, Resolvers{ + cidResolver: StrictResolver, + oidResolver: LenientResolver, + }) ) diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/prefix.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/prefix.go index 2fb122940d..42a24c594c 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/buckets/prefix.go +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/prefix.go @@ -22,27 +22,31 @@ const ( Split ContainerCounters ECInfo + ExpirationEpochToObject + ObjectToExpirationEpoch ) var x = map[Prefix]string{ - Graveyard: "Graveyard", - Garbage: "Garbage", - ToMoveIt: "To Move It", - ContainerVolume: "Container Volume", - Locked: "Locked", - ShardInfo: "Shard Info", - Primary: "Primary", - Lockers: "Lockers", - Tombstone: "Tombstone", - Small: "Small", - Root: "Root", - Owner: "Owner", - UserAttribute: "User Attribute", - PayloadHash: "Payload Hash", - Parent: "Parent", - Split: "Split", - ContainerCounters: "Container Counters", - ECInfo: "EC Info", + Graveyard: "Graveyard", + Garbage: "Garbage", + ToMoveIt: "To Move It", + ContainerVolume: "Container Volume", + Locked: "Locked", + ShardInfo: "Shard Info", + Primary: "Primary", + Lockers: "Lockers", + Tombstone: "Tombstone", + Small: "Small", + Root: "Root", + Owner: "Owner", + UserAttribute: "User Attribute", + PayloadHash: "Payload Hash", + Parent: "Parent", + Split: "Split", + ContainerCounters: "Container Counters", + ECInfo: "EC Info", + ExpirationEpochToObject: "Exp. Epoch to Object", + ObjectToExpirationEpoch: "Object to Exp. Epoch", } func (p Prefix) String() string { diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/string.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/string.go index db90bddbd9..62d126f884 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/buckets/string.go +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/string.go @@ -9,7 +9,7 @@ import ( func (b *PrefixBucket) String() string { return common.FormatSimple( - fmt.Sprintf("(%2d %-18s)", b.prefix, b.prefix), tcell.ColorLime, + fmt.Sprintf("(%2d %-20s)", b.prefix, b.prefix), tcell.ColorLime, ) } @@ -17,7 +17,7 @@ func (b *PrefixContainerBucket) String() string { return fmt.Sprintf( "%s CID %s", common.FormatSimple( - fmt.Sprintf("(%2d %-18s)", b.prefix, b.prefix), tcell.ColorLime, + fmt.Sprintf("(%2d %-20s)", b.prefix, b.prefix), tcell.ColorLime, ), common.FormatSimple(b.id.String(), tcell.ColorAqua), ) @@ -34,7 +34,7 @@ func (b *ContainerBucket) String() string { func (b *UserAttributeKeyBucket) String() string { return fmt.Sprintf("%s CID %s ATTR-KEY %s", common.FormatSimple( - fmt.Sprintf("(%2d %-18s)", b.prefix, b.prefix), tcell.ColorLime, + fmt.Sprintf("(%2d %-20s)", b.prefix, b.prefix), tcell.ColorLime, ), common.FormatSimple( fmt.Sprintf("%-44s", b.id), tcell.ColorAqua, diff --git a/cmd/frostfs-lens/internal/schema/metabase/buckets/types.go b/cmd/frostfs-lens/internal/schema/metabase/buckets/types.go index 82b47dd855..7355c3d9e4 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/buckets/types.go +++ b/cmd/frostfs-lens/internal/schema/metabase/buckets/types.go @@ -2,6 +2,7 @@ package buckets import ( "errors" + "slices" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -57,10 +58,11 @@ var ( ) var ( - ErrNotBucket = errors.New("not a bucket") - ErrInvalidKeyLength = errors.New("invalid key length") - ErrInvalidValueLength = errors.New("invalid value length") - ErrInvalidPrefix = errors.New("invalid prefix") + ErrNotBucket = errors.New("not a bucket") + ErrInvalidKeyLength = errors.New("invalid key length") + ErrInvalidValueLength = errors.New("invalid value length") + ErrInvalidPrefix = errors.New("invalid prefix") + ErrUnexpectedAttributeKey = errors.New("unexpected attribute key") ) func NewPrefixBucketParser(prefix Prefix, next common.Parser, resolvers Resolvers) common.Parser { @@ -132,6 +134,10 @@ func NewContainerBucketParser(next common.Parser, resolvers Resolvers) common.Pa } func NewUserAttributeKeyBucketParser(next common.Parser) common.Parser { + return NewUserAttributeKeyBucketParserWithSpecificKeys(next, nil) +} + +func NewUserAttributeKeyBucketParserWithSpecificKeys(next common.Parser, keys []string) common.Parser { return func(key, value []byte) (common.SchemaEntry, common.Parser, error) { if value != nil { return nil, nil, ErrNotBucket @@ -147,6 +153,11 @@ func NewUserAttributeKeyBucketParser(next common.Parser) common.Parser { return nil, nil, err } b.key = string(key[33:]) + + if len(keys) != 0 && !slices.Contains(keys, b.key) { + return nil, nil, ErrUnexpectedAttributeKey + } + return &b, next, nil } } diff --git a/cmd/frostfs-lens/internal/schema/metabase/parser.go b/cmd/frostfs-lens/internal/schema/metabase/parser.go index ea095e2071..4cc9e8765c 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/parser.go +++ b/cmd/frostfs-lens/internal/schema/metabase/parser.go @@ -5,7 +5,30 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/metabase/buckets" ) -var MetabaseParser = common.WithFallback( +var MetabaseParserV3 = common.WithFallback( + common.Any( + buckets.GraveyardParser, + buckets.GarbageParser, + buckets.ContainerVolumeParser, + buckets.LockedParser, + buckets.ShardInfoParser, + buckets.PrimaryParser, + buckets.LockersParser, + buckets.TombstoneParser, + buckets.SmallParser, + buckets.RootParser, + buckets.UserAttributeParserV3, + buckets.ParentParser, + buckets.SplitParser, + buckets.ContainerCountersParser, + buckets.ECInfoParser, + buckets.ExpirationEpochToObjectParser, + buckets.ObjectToExpirationEpochParser, + ), + common.RawParser.ToFallbackParser(), +) + +var MetabaseParserV2 = common.WithFallback( common.Any( buckets.GraveyardParser, buckets.GarbageParser, @@ -18,7 +41,7 @@ var MetabaseParser = common.WithFallback( buckets.SmallParser, buckets.RootParser, buckets.OwnerParser, - buckets.UserAttributeParser, + buckets.UserAttributeParserV2, buckets.PayloadHashParser, buckets.ParentParser, buckets.SplitParser, diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/detailed.go b/cmd/frostfs-lens/internal/schema/metabase/records/detailed.go index 2dda15b4f1..477c4fc9d4 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/records/detailed.go +++ b/cmd/frostfs-lens/internal/schema/metabase/records/detailed.go @@ -63,3 +63,11 @@ func (r *ContainerCountersRecord) DetailedString() string { func (r *ECInfoRecord) DetailedString() string { return spew.Sdump(*r) } + +func (r *ExpirationEpochToObjectRecord) DetailedString() string { + return spew.Sdump(*r) +} + +func (r *ObjectToExpirationEpochRecord) DetailedString() string { + return spew.Sdump(*r) +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/filter.go b/cmd/frostfs-lens/internal/schema/metabase/records/filter.go index 880a7a8ff2..e038911d72 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/records/filter.go +++ b/cmd/frostfs-lens/internal/schema/metabase/records/filter.go @@ -143,3 +143,26 @@ func (r *ECInfoRecord) Filter(typ string, val any) common.FilterResult { return common.No } } + +func (r *ExpirationEpochToObjectRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "cid": + id := val.(cid.ID) + return common.IfThenElse(r.cnt.Equals(id), common.Yes, common.No) + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.obj.Equals(id), common.Yes, common.No) + default: + return common.No + } +} + +func (r *ObjectToExpirationEpochRecord) Filter(typ string, val any) common.FilterResult { + switch typ { + case "oid": + id := val.(oid.ID) + return common.IfThenElse(r.obj.Equals(id), common.Yes, common.No) + default: + return common.No + } +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/parsers.go b/cmd/frostfs-lens/internal/schema/metabase/records/parsers.go index 1b070e2a02..5d846cb754 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/records/parsers.go +++ b/cmd/frostfs-lens/internal/schema/metabase/records/parsers.go @@ -249,3 +249,45 @@ func ECInfoRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, e } return &r, nil, nil } + +func ExpirationEpochToObjectRecordParser(key, _ []byte) (common.SchemaEntry, common.Parser, error) { + if len(key) != 72 { + return nil, nil, ErrInvalidKeyLength + } + + var ( + r ExpirationEpochToObjectRecord + err error + ) + + r.epoch = binary.BigEndian.Uint64(key[:8]) + if err = r.cnt.Decode(key[8:40]); err != nil { + return nil, nil, err + } + if err = r.obj.Decode(key[40:]); err != nil { + return nil, nil, err + } + + return &r, nil, nil +} + +func ObjectToExpirationEpochRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, error) { + if len(key) != 32 { + return nil, nil, ErrInvalidKeyLength + } + if len(value) != 8 { + return nil, nil, ErrInvalidValueLength + } + + var ( + r ObjectToExpirationEpochRecord + err error + ) + + if err = r.obj.Decode(key); err != nil { + return nil, nil, err + } + r.epoch = binary.LittleEndian.Uint64(value) + + return &r, nil, nil +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/string.go b/cmd/frostfs-lens/internal/schema/metabase/records/string.go index ec0ab8e1a4..f71244625e 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/records/string.go +++ b/cmd/frostfs-lens/internal/schema/metabase/records/string.go @@ -2,6 +2,7 @@ package records import ( "fmt" + "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" "github.com/gdamore/tcell/v2" @@ -133,3 +134,22 @@ func (r *ECInfoRecord) String() string { len(r.ids), ) } + +func (r *ExpirationEpochToObjectRecord) String() string { + return fmt.Sprintf( + "exp. epoch %s %c CID %s OID %s", + common.FormatSimple(fmt.Sprintf("%-20d", r.epoch), tcell.ColorAqua), + tview.Borders.Vertical, + common.FormatSimple(fmt.Sprintf("%-44s", r.cnt), tcell.ColorAqua), + common.FormatSimple(fmt.Sprintf("%-44s", r.obj), tcell.ColorAqua), + ) +} + +func (r *ObjectToExpirationEpochRecord) String() string { + return fmt.Sprintf( + "OID %s %c exp. epoch %s", + common.FormatSimple(fmt.Sprintf("%-44s", r.obj), tcell.ColorAqua), + tview.Borders.Vertical, + common.FormatSimple(strconv.FormatUint(r.epoch, 10), tcell.ColorAqua), + ) +} diff --git a/cmd/frostfs-lens/internal/schema/metabase/records/types.go b/cmd/frostfs-lens/internal/schema/metabase/records/types.go index 34c1c29fdf..0809cad1a7 100644 --- a/cmd/frostfs-lens/internal/schema/metabase/records/types.go +++ b/cmd/frostfs-lens/internal/schema/metabase/records/types.go @@ -79,4 +79,15 @@ type ( id oid.ID ids []oid.ID } + + ExpirationEpochToObjectRecord struct { + epoch uint64 + cnt cid.ID + obj oid.ID + } + + ObjectToExpirationEpochRecord struct { + obj oid.ID + epoch uint64 + } ) From 4c8f9580a16eb5d30320d670849585fe25c1d04d Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 5 Mar 2025 17:09:02 +0300 Subject: [PATCH 1223/1413] [#1662] object: Fix `CloseAndRecv` for patch streamer * A client may open stream to server, not send anything and close the open stream immediatly. This shouldn't cause a panic; * Return the error if `s.patcher` is uninitialized. Uninitialized patcher cannot be closed, this causes a panic. Signed-off-by: Airat Arifullin --- pkg/services/object/patch/streamer.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index 5aba13f66c..642b9f9fa1 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -214,6 +214,9 @@ func (s *Streamer) Send(ctx context.Context, req *objectV2.PatchRequest) error { } func (s *Streamer) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { + if s.patcher == nil { + return nil, errors.New("uninitialized patch streamer") + } patcherResp, err := s.patcher.Close(ctx) if err != nil { return nil, err From 471aeeaff3bdb8df231416bd69e659ca38e1e0c2 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 3 Mar 2025 04:21:53 +0300 Subject: [PATCH 1224/1413] [#1659] audit: Fix duplicated request logs When we do `object put` with audit enabled we get several entries in logs: with and without object id. `object put` request is logged in 2 places: 1. `(*auditPutStream) CloseAndRecv()` - when the client closes the request stream or when stream gets aborted. 2. `(*auditPutStream) Send()` - when stream was NOT aborted. `Send()` does error check for `ErrAbortStream` because if there is any other error - CloseAndRecv will not be called and there won't be any audit log about failed request. It led to logging on every object chunck put, even if `err == nil`. Added check for `err != nil` in `Send()` to fix it. Signed-off-by: Ekaterina Lebedeva --- pkg/services/object/audit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/audit.go b/pkg/services/object/audit.go index dde9f8fc05..367be0c0cd 100644 --- a/pkg/services/object/audit.go +++ b/pkg/services/object/audit.go @@ -163,7 +163,7 @@ func (a *auditPutStream) Send(ctx context.Context, req *object.PutRequest) error if err != nil { a.failed = true } - if !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here + if err != nil && !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here audit.LogRequestWithKey(ctx, a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key, audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), !a.failed) From a17c3356fa762c3d558ed9d6fcd76f44db2f1e40 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 6 Mar 2025 15:07:37 +0300 Subject: [PATCH 1225/1413] [#1665] go.mod: Update sdk-go Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bbb8179577..18378466eb 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 diff --git a/go.sum b/go.sum index 0c66f45553..5205dddeff 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e13 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3 h1:QnAt5b2R6+hQthMOIn5ECfLAlVD8IAE5JRm1NCCOmuE= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4 h1:dOZHuOywvH1ms8U38lDCWpysgkCCeJ02RLI7zDhPcyw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250217152255-c3f7378887a4/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 h1:svCl6NDAPZ/KuQPjdVKo74RkCIANesxUPM45zQZDhSw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= From 6260d703ce02a12a812d5071b601a3c925eb8860 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 6 Mar 2025 15:13:38 +0300 Subject: [PATCH 1226/1413] [#1665] treesvc: Disable service config query By default, gRPC fetches TXT report while resolving a domain. https://github.com/grpc/grpc-go/blob/0914bba6c5c5a545d34bd11e5dee0bbb8eaadd3f/internal/resolver/dns/dns_resolver.go#L336 This leads to a hanging dial if DNS is unavailable, even though the host may be specified in `/etc/hosts` (hello, localhost!). SDK client for the main API uses these options by default. Refs TrueCloudLab/frostfs-sdk-go#342 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/tree/client.go | 1 + pkg/services/tree/cache.go | 1 + pkg/services/tree/sync.go | 1 + 3 files changed, 3 insertions(+) diff --git a/cmd/frostfs-cli/modules/tree/client.go b/cmd/frostfs-cli/modules/tree/client.go index c6953f126e..933378df6b 100644 --- a/cmd/frostfs-cli/modules/tree/client.go +++ b/cmd/frostfs-cli/modules/tree/client.go @@ -39,6 +39,7 @@ func _client() (tree.TreeServiceClient, error) { tracing.NewStreamClientInterceptor(), ), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), + grpc.WithDisableServiceConfig(), } if !strings.HasPrefix(netAddr.URIAddr(), "grpcs:") { diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index 125871fc45..70f4a843ba 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -110,6 +110,7 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* ), grpc.WithContextDialer(c.ds.GrpcContextDialer()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), + grpc.WithDisableServiceConfig(), } if !netAddr.IsTLSEnabled() { diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 3e0a453853..89450b7397 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -355,6 +355,7 @@ func (*Service) createConnection(a network.Address) (*grpc.ClientConn, error) { ), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), + grpc.WithDisableServiceConfig(), ) } From 9e31cb249f10c06cd0908db1269f600f4bd51cda Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 4 Feb 2025 21:21:31 +0300 Subject: [PATCH 1227/1413] [#1635] control: Add method to search shards by object Added method `ListShardsForObject` to ControlService and to StorageEngine. It returns information about shards storing object on the node. Signed-off-by: Ekaterina Lebedeva --- internal/logs/logs.go | 1 + pkg/local_object_storage/engine/shards.go | 46 ++ pkg/services/control/rpc.go | 20 + .../control/server/list_shards_for_object.go | 66 ++ pkg/services/control/service.proto | 23 + pkg/services/control/service_frostfs.pb.go | 724 ++++++++++++++++++ pkg/services/control/service_grpc.pb.go | 39 + 7 files changed, 919 insertions(+) create mode 100644 pkg/services/control/server/list_shards_for_object.go diff --git a/internal/logs/logs.go b/internal/logs/logs.go index d48a4da9b7..d07f47fbf5 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -252,6 +252,7 @@ const ( ShardFailureToMarkLockersAsGarbage = "failure to mark lockers as garbage" ShardFailureToGetExpiredUnlockedObjects = "failure to get expired unlocked objects" ShardCouldNotMarkObjectToDeleteInMetabase = "could not mark object to delete in metabase" + ShardCouldNotFindObject = "could not find object" WritecacheWaitingForChannelsToFlush = "waiting for channels to flush" WritecacheCantRemoveObjectFromWritecache = "can't remove object from write-cache" BlobovniczatreeCouldNotGetObjectFromLevel = "could not get object from level" diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 8e191f72c4..28f0287bc0 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -11,6 +11,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/hrw" "github.com/google/uuid" @@ -442,3 +445,46 @@ func (e *StorageEngine) deleteShards(ctx context.Context, ids []*shard.ID) ([]ha func (s hashedShard) Hash() uint64 { return s.hash } + +func (e *StorageEngine) ListShardsForObject(ctx context.Context, obj oid.Address) ([]shard.Info, error) { + var err error + var info []shard.Info + prm := shard.ExistsPrm{ + Address: obj, + } + var siErr *objectSDK.SplitInfoError + var ecErr *objectSDK.ECInfoError + + e.iterateOverUnsortedShards(func(hs hashedShard) (stop bool) { + res, exErr := hs.Exists(ctx, prm) + if exErr != nil { + if client.IsErrObjectAlreadyRemoved(exErr) { + err = new(apistatus.ObjectAlreadyRemoved) + return true + } + + // Check if error is either SplitInfoError or ECInfoError. + // True means the object is virtual. + if errors.As(exErr, &siErr) || errors.As(exErr, &ecErr) { + info = append(info, hs.DumpInfo()) + return false + } + + if shard.IsErrObjectExpired(exErr) { + err = exErr + return true + } + + if !client.IsErrObjectNotFound(exErr) { + e.reportShardError(ctx, hs, "could not check existence of object in shard", exErr, zap.Stringer("address", prm.Address)) + } + + return false + } + if res.Exists() { + info = append(info, hs.DumpInfo()) + } + return false + }) + return info, err +} diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index bbf2cf0cc7..0c4236d0ee 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -32,6 +32,7 @@ const ( rpcListTargetsLocalOverrides = "ListTargetsLocalOverrides" rpcDetachShards = "DetachShards" rpcStartShardRebuild = "StartShardRebuild" + rpcListShardsForObject = "ListShardsForObject" ) // HealthCheck executes ControlService.HealthCheck RPC. @@ -364,3 +365,22 @@ func StartShardRebuild(cli *client.Client, req *StartShardRebuildRequest, opts . return wResp.message, nil } + +// ListShardsForObject executes ControlService.ListShardsForObject RPC. +func ListShardsForObject( + cli *client.Client, + req *ListShardsForObjectRequest, + opts ...client.CallOption, +) (*ListShardsForObjectResponse, error) { + wResp := newResponseWrapper[ListShardsForObjectResponse]() + + wReq := &requestWrapper{ + m: req, + } + err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcListShardsForObject), wReq, wResp, opts...) + if err != nil { + return nil, err + } + + return wResp.message, nil +} diff --git a/pkg/services/control/server/list_shards_for_object.go b/pkg/services/control/server/list_shards_for_object.go new file mode 100644 index 0000000000..84469772f8 --- /dev/null +++ b/pkg/services/control/server/list_shards_for_object.go @@ -0,0 +1,66 @@ +package control + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" + + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func (s *Server) ListShardsForObject(ctx context.Context, req *control.ListShardsForObjectRequest) (*control.ListShardsForObjectResponse, error) { + err := s.isValidRequest(req) + if err != nil { + return nil, status.Error(codes.PermissionDenied, err.Error()) + } + + var obj oid.ID + err = obj.DecodeString(req.GetBody().GetObjectId()) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + var cnr cid.ID + err = cnr.DecodeString(req.GetBody().GetContainerId()) + if err != nil { + return nil, status.Error(codes.InvalidArgument, err.Error()) + } + + resp := new(control.ListShardsForObjectResponse) + body := new(control.ListShardsForObjectResponse_Body) + resp.SetBody(body) + + var objAddr oid.Address + objAddr.SetContainer(cnr) + objAddr.SetObject(obj) + info, err := s.s.ListShardsForObject(ctx, objAddr) + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + if len(info) == 0 { + return nil, status.Error(codes.NotFound, logs.ShardCouldNotFindObject) + } + + body.SetShard_ID(shardInfoToProto(info)) + + // Sign the response + if err := ctrlmessage.Sign(s.key, resp); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + return resp, nil +} + +func shardInfoToProto(infos []shard.Info) [][]byte { + shardInfos := make([][]byte, 0, len(infos)) + for _, info := range infos { + shardInfos = append(shardInfos, *info.ID) + } + + return shardInfos +} diff --git a/pkg/services/control/service.proto b/pkg/services/control/service.proto index 97ecf9a8cd..4c539acfc2 100644 --- a/pkg/services/control/service.proto +++ b/pkg/services/control/service.proto @@ -89,6 +89,9 @@ service ControlService { // StartShardRebuild starts shard rebuild process. rpc StartShardRebuild(StartShardRebuildRequest) returns (StartShardRebuildResponse); + + // ListShardsForObject returns shard info where object is stored. + rpc ListShardsForObject(ListShardsForObjectRequest) returns (ListShardsForObjectResponse); } // Health check request. @@ -729,3 +732,23 @@ message StartShardRebuildResponse { Signature signature = 2; } + +message ListShardsForObjectRequest { + message Body { + string object_id = 1; + string container_id = 2; + } + + Body body = 1; + Signature signature = 2; +} + +message ListShardsForObjectResponse { + message Body { + // List of the node's shards storing object. + repeated bytes shard_ID = 1; + } + + Body body = 1; + Signature signature = 2; +} diff --git a/pkg/services/control/service_frostfs.pb.go b/pkg/services/control/service_frostfs.pb.go index 0b4e3cf32a..44849d591a 100644 --- a/pkg/services/control/service_frostfs.pb.go +++ b/pkg/services/control/service_frostfs.pb.go @@ -17303,3 +17303,727 @@ func (x *StartShardRebuildResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { in.Consumed() } } + +type ListShardsForObjectRequest_Body struct { + ObjectId string `json:"objectId"` + ContainerId string `json:"containerId"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListShardsForObjectRequest_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListShardsForObjectRequest_Body)(nil) + _ json.Marshaler = (*ListShardsForObjectRequest_Body)(nil) + _ json.Unmarshaler = (*ListShardsForObjectRequest_Body)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListShardsForObjectRequest_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.StringSize(1, x.ObjectId) + size += proto.StringSize(2, x.ContainerId) + return size +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListShardsForObjectRequest_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ListShardsForObjectRequest_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if len(x.ObjectId) != 0 { + mm.AppendString(1, x.ObjectId) + } + if len(x.ContainerId) != 0 { + mm.AppendString(2, x.ContainerId) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListShardsForObjectRequest_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListShardsForObjectRequest_Body") + } + switch fc.FieldNum { + case 1: // ObjectId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ObjectId") + } + x.ObjectId = data + case 2: // ContainerId + data, ok := fc.String() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "ContainerId") + } + x.ContainerId = data + } + } + return nil +} +func (x *ListShardsForObjectRequest_Body) GetObjectId() string { + if x != nil { + return x.ObjectId + } + return "" +} +func (x *ListShardsForObjectRequest_Body) SetObjectId(v string) { + x.ObjectId = v +} +func (x *ListShardsForObjectRequest_Body) GetContainerId() string { + if x != nil { + return x.ContainerId + } + return "" +} +func (x *ListShardsForObjectRequest_Body) SetContainerId(v string) { + x.ContainerId = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListShardsForObjectRequest_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListShardsForObjectRequest_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + first := true + out.RawByte('{') + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"objectId\":" + out.RawString(prefix) + out.String(x.ObjectId) + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"containerId\":" + out.RawString(prefix) + out.String(x.ContainerId) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListShardsForObjectRequest_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListShardsForObjectRequest_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "objectId": + { + var f string + f = in.String() + x.ObjectId = f + } + case "containerId": + { + var f string + f = in.String() + x.ContainerId = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListShardsForObjectRequest struct { + Body *ListShardsForObjectRequest_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListShardsForObjectRequest)(nil) + _ encoding.ProtoUnmarshaler = (*ListShardsForObjectRequest)(nil) + _ json.Marshaler = (*ListShardsForObjectRequest)(nil) + _ json.Unmarshaler = (*ListShardsForObjectRequest)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListShardsForObjectRequest) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ListShardsForObjectRequest) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ListShardsForObjectRequest) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().MarshalProtobuf(buf), nil +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListShardsForObjectRequest) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ListShardsForObjectRequest) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListShardsForObjectRequest) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListShardsForObjectRequest") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListShardsForObjectRequest_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListShardsForObjectRequest) GetBody() *ListShardsForObjectRequest_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListShardsForObjectRequest) SetBody(v *ListShardsForObjectRequest_Body) { + x.Body = v +} +func (x *ListShardsForObjectRequest) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ListShardsForObjectRequest) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListShardsForObjectRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListShardsForObjectRequest) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + first := true + out.RawByte('{') + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) + x.Body.MarshalEasyJSON(out) + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListShardsForObjectRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListShardsForObjectRequest) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListShardsForObjectRequest_Body + f = new(ListShardsForObjectRequest_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListShardsForObjectResponse_Body struct { + Shard_ID [][]byte `json:"shardID"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListShardsForObjectResponse_Body)(nil) + _ encoding.ProtoUnmarshaler = (*ListShardsForObjectResponse_Body)(nil) + _ json.Marshaler = (*ListShardsForObjectResponse_Body)(nil) + _ json.Unmarshaler = (*ListShardsForObjectResponse_Body)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListShardsForObjectResponse_Body) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.RepeatedBytesSize(1, x.Shard_ID) + return size +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListShardsForObjectResponse_Body) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ListShardsForObjectResponse_Body) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + for j := range x.Shard_ID { + mm.AppendBytes(1, x.Shard_ID[j]) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListShardsForObjectResponse_Body) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListShardsForObjectResponse_Body") + } + switch fc.FieldNum { + case 1: // Shard_ID + data, ok := fc.Bytes() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Shard_ID") + } + x.Shard_ID = append(x.Shard_ID, data) + } + } + return nil +} +func (x *ListShardsForObjectResponse_Body) GetShard_ID() [][]byte { + if x != nil { + return x.Shard_ID + } + return nil +} +func (x *ListShardsForObjectResponse_Body) SetShard_ID(v [][]byte) { + x.Shard_ID = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListShardsForObjectResponse_Body) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListShardsForObjectResponse_Body) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + first := true + out.RawByte('{') + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"shardID\":" + out.RawString(prefix) + out.RawByte('[') + for i := range x.Shard_ID { + if i != 0 { + out.RawByte(',') + } + if x.Shard_ID[i] != nil { + out.Base64Bytes(x.Shard_ID[i]) + } else { + out.String("") + } + } + out.RawByte(']') + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListShardsForObjectResponse_Body) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListShardsForObjectResponse_Body) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "shardID": + { + var f []byte + var list [][]byte + in.Delim('[') + for !in.IsDelim(']') { + { + tmp := in.Bytes() + if len(tmp) == 0 { + tmp = nil + } + f = tmp + } + list = append(list, f) + in.WantComma() + } + x.Shard_ID = list + in.Delim(']') + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} + +type ListShardsForObjectResponse struct { + Body *ListShardsForObjectResponse_Body `json:"body"` + Signature *Signature `json:"signature"` +} + +var ( + _ encoding.ProtoMarshaler = (*ListShardsForObjectResponse)(nil) + _ encoding.ProtoUnmarshaler = (*ListShardsForObjectResponse)(nil) + _ json.Marshaler = (*ListShardsForObjectResponse)(nil) + _ json.Unmarshaler = (*ListShardsForObjectResponse)(nil) +) + +// StableSize returns the size of x in protobuf format. +// +// Structures with the same field values have the same binary size. +func (x *ListShardsForObjectResponse) StableSize() (size int) { + if x == nil { + return 0 + } + size += proto.NestedStructureSize(1, x.Body) + size += proto.NestedStructureSize(2, x.Signature) + return size +} + +// ReadSignedData fills buf with signed data of x. +// If buffer length is less than x.SignedDataSize(), new buffer is allocated. +// +// Returns any error encountered which did not allow writing the data completely. +// Otherwise, returns the buffer in which the data is written. +// +// Structures with the same field values have the same signed data. +func (x *ListShardsForObjectResponse) SignedDataSize() int { + return x.GetBody().StableSize() +} + +// SignedDataSize returns size of the request signed data in bytes. +// +// Structures with the same field values have the same signed data size. +func (x *ListShardsForObjectResponse) ReadSignedData(buf []byte) ([]byte, error) { + return x.GetBody().MarshalProtobuf(buf), nil +} + +// MarshalProtobuf implements the encoding.ProtoMarshaler interface. +func (x *ListShardsForObjectResponse) MarshalProtobuf(dst []byte) []byte { + m := pool.MarshalerPool.Get() + defer pool.MarshalerPool.Put(m) + x.EmitProtobuf(m.MessageMarshaler()) + dst = m.Marshal(dst) + return dst +} + +func (x *ListShardsForObjectResponse) EmitProtobuf(mm *easyproto.MessageMarshaler) { + if x == nil { + return + } + if x.Body != nil { + x.Body.EmitProtobuf(mm.AppendMessage(1)) + } + if x.Signature != nil { + x.Signature.EmitProtobuf(mm.AppendMessage(2)) + } +} + +// UnmarshalProtobuf implements the encoding.ProtoUnmarshaler interface. +func (x *ListShardsForObjectResponse) UnmarshalProtobuf(src []byte) (err error) { + var fc easyproto.FieldContext + for len(src) > 0 { + src, err = fc.NextField(src) + if err != nil { + return fmt.Errorf("cannot read next field in %s", "ListShardsForObjectResponse") + } + switch fc.FieldNum { + case 1: // Body + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Body") + } + x.Body = new(ListShardsForObjectResponse_Body) + if err := x.Body.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + case 2: // Signature + data, ok := fc.MessageData() + if !ok { + return fmt.Errorf("cannot unmarshal field %s", "Signature") + } + x.Signature = new(Signature) + if err := x.Signature.UnmarshalProtobuf(data); err != nil { + return fmt.Errorf("unmarshal: %w", err) + } + } + } + return nil +} +func (x *ListShardsForObjectResponse) GetBody() *ListShardsForObjectResponse_Body { + if x != nil { + return x.Body + } + return nil +} +func (x *ListShardsForObjectResponse) SetBody(v *ListShardsForObjectResponse_Body) { + x.Body = v +} +func (x *ListShardsForObjectResponse) GetSignature() *Signature { + if x != nil { + return x.Signature + } + return nil +} +func (x *ListShardsForObjectResponse) SetSignature(v *Signature) { + x.Signature = v +} + +// MarshalJSON implements the json.Marshaler interface. +func (x *ListShardsForObjectResponse) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + x.MarshalEasyJSON(&w) + return w.Buffer.BuildBytes(), w.Error +} +func (x *ListShardsForObjectResponse) MarshalEasyJSON(out *jwriter.Writer) { + if x == nil { + out.RawString("null") + return + } + first := true + out.RawByte('{') + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"body\":" + out.RawString(prefix) + x.Body.MarshalEasyJSON(out) + } + { + if !first { + out.RawByte(',') + } else { + first = false + } + const prefix string = "\"signature\":" + out.RawString(prefix) + x.Signature.MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (x *ListShardsForObjectResponse) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + x.UnmarshalEasyJSON(&r) + return r.Error() +} +func (x *ListShardsForObjectResponse) UnmarshalEasyJSON(in *jlexer.Lexer) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeFieldName(false) + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "body": + { + var f *ListShardsForObjectResponse_Body + f = new(ListShardsForObjectResponse_Body) + f.UnmarshalEasyJSON(in) + x.Body = f + } + case "signature": + { + var f *Signature + f = new(Signature) + f.UnmarshalEasyJSON(in) + x.Signature = f + } + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} diff --git a/pkg/services/control/service_grpc.pb.go b/pkg/services/control/service_grpc.pb.go index 987e08c59e..045662ccfa 100644 --- a/pkg/services/control/service_grpc.pb.go +++ b/pkg/services/control/service_grpc.pb.go @@ -41,6 +41,7 @@ const ( ControlService_SealWriteCache_FullMethodName = "/control.ControlService/SealWriteCache" ControlService_DetachShards_FullMethodName = "/control.ControlService/DetachShards" ControlService_StartShardRebuild_FullMethodName = "/control.ControlService/StartShardRebuild" + ControlService_ListShardsForObject_FullMethodName = "/control.ControlService/ListShardsForObject" ) // ControlServiceClient is the client API for ControlService service. @@ -95,6 +96,8 @@ type ControlServiceClient interface { DetachShards(ctx context.Context, in *DetachShardsRequest, opts ...grpc.CallOption) (*DetachShardsResponse, error) // StartShardRebuild starts shard rebuild process. StartShardRebuild(ctx context.Context, in *StartShardRebuildRequest, opts ...grpc.CallOption) (*StartShardRebuildResponse, error) + // ListShardsForObject returns shard info where object is stored. + ListShardsForObject(ctx context.Context, in *ListShardsForObjectRequest, opts ...grpc.CallOption) (*ListShardsForObjectResponse, error) } type controlServiceClient struct { @@ -303,6 +306,15 @@ func (c *controlServiceClient) StartShardRebuild(ctx context.Context, in *StartS return out, nil } +func (c *controlServiceClient) ListShardsForObject(ctx context.Context, in *ListShardsForObjectRequest, opts ...grpc.CallOption) (*ListShardsForObjectResponse, error) { + out := new(ListShardsForObjectResponse) + err := c.cc.Invoke(ctx, ControlService_ListShardsForObject_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // ControlServiceServer is the server API for ControlService service. // All implementations should embed UnimplementedControlServiceServer // for forward compatibility @@ -355,6 +367,8 @@ type ControlServiceServer interface { DetachShards(context.Context, *DetachShardsRequest) (*DetachShardsResponse, error) // StartShardRebuild starts shard rebuild process. StartShardRebuild(context.Context, *StartShardRebuildRequest) (*StartShardRebuildResponse, error) + // ListShardsForObject returns shard info where object is stored. + ListShardsForObject(context.Context, *ListShardsForObjectRequest) (*ListShardsForObjectResponse, error) } // UnimplementedControlServiceServer should be embedded to have forward compatible implementations. @@ -427,6 +441,9 @@ func (UnimplementedControlServiceServer) DetachShards(context.Context, *DetachSh func (UnimplementedControlServiceServer) StartShardRebuild(context.Context, *StartShardRebuildRequest) (*StartShardRebuildResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method StartShardRebuild not implemented") } +func (UnimplementedControlServiceServer) ListShardsForObject(context.Context, *ListShardsForObjectRequest) (*ListShardsForObjectResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListShardsForObject not implemented") +} // UnsafeControlServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ControlServiceServer will @@ -835,6 +852,24 @@ func _ControlService_StartShardRebuild_Handler(srv interface{}, ctx context.Cont return interceptor(ctx, in, info, handler) } +func _ControlService_ListShardsForObject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListShardsForObjectRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ControlServiceServer).ListShardsForObject(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ControlService_ListShardsForObject_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ControlServiceServer).ListShardsForObject(ctx, req.(*ListShardsForObjectRequest)) + } + return interceptor(ctx, in, info, handler) +} + // ControlService_ServiceDesc is the grpc.ServiceDesc for ControlService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -930,6 +965,10 @@ var ControlService_ServiceDesc = grpc.ServiceDesc{ MethodName: "StartShardRebuild", Handler: _ControlService_StartShardRebuild_Handler, }, + { + MethodName: "ListShardsForObject", + Handler: _ControlService_ListShardsForObject_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "pkg/services/control/service.proto", From aab8addae006ea7667d0851170b278c65f2643e8 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 18 Feb 2025 13:04:48 +0300 Subject: [PATCH 1228/1413] [#1635] cli: Make `object.readObjectAddress()` public This method will be useful for upcoming control command. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/modules/object/delete.go | 2 +- cmd/frostfs-cli/modules/object/get.go | 2 +- cmd/frostfs-cli/modules/object/hash.go | 2 +- cmd/frostfs-cli/modules/object/head.go | 2 +- cmd/frostfs-cli/modules/object/nodes.go | 2 +- cmd/frostfs-cli/modules/object/patch.go | 2 +- cmd/frostfs-cli/modules/object/range.go | 2 +- cmd/frostfs-cli/modules/object/util.go | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/delete.go b/cmd/frostfs-cli/modules/object/delete.go index e4e9cddb80..08a9ac4c85 100644 --- a/cmd/frostfs-cli/modules/object/delete.go +++ b/cmd/frostfs-cli/modules/object/delete.go @@ -55,7 +55,7 @@ func deleteObject(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.OIDFlag)) } - objAddr = readObjectAddress(cmd, &cnr, &obj) + objAddr = ReadObjectAddress(cmd, &cnr, &obj) } pk := key.GetOrGenerate(cmd) diff --git a/cmd/frostfs-cli/modules/object/get.go b/cmd/frostfs-cli/modules/object/get.go index f1edccba2f..7312f53848 100644 --- a/cmd/frostfs-cli/modules/object/get.go +++ b/cmd/frostfs-cli/modules/object/get.go @@ -46,7 +46,7 @@ func getObject(cmd *cobra.Command, _ []string) { var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr := ReadObjectAddress(cmd, &cnr, &obj) filename := cmd.Flag(fileFlag).Value.String() out, closer := createOutWriter(cmd, filename) diff --git a/cmd/frostfs-cli/modules/object/hash.go b/cmd/frostfs-cli/modules/object/hash.go index d8ea449eb1..25df375d4d 100644 --- a/cmd/frostfs-cli/modules/object/hash.go +++ b/cmd/frostfs-cli/modules/object/hash.go @@ -52,7 +52,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) { var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr := ReadObjectAddress(cmd, &cnr, &obj) ranges, err := getRangeList(cmd) commonCmd.ExitOnErr(cmd, "", err) diff --git a/cmd/frostfs-cli/modules/object/head.go b/cmd/frostfs-cli/modules/object/head.go index 70c2734433..97e996cad2 100644 --- a/cmd/frostfs-cli/modules/object/head.go +++ b/cmd/frostfs-cli/modules/object/head.go @@ -47,7 +47,7 @@ func getObjectHeader(cmd *cobra.Command, _ []string) { var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr := ReadObjectAddress(cmd, &cnr, &obj) pk := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 1500830a2e..bc34b370df 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -101,7 +101,7 @@ func initObjectNodesCmd() { func objectNodes(cmd *cobra.Command, _ []string) { var cnrID cid.ID var objID oid.ID - readObjectAddress(cmd, &cnrID, &objID) + ReadObjectAddress(cmd, &cnrID, &objID) pk := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) diff --git a/cmd/frostfs-cli/modules/object/patch.go b/cmd/frostfs-cli/modules/object/patch.go index ebc415b2f5..d981826793 100644 --- a/cmd/frostfs-cli/modules/object/patch.go +++ b/cmd/frostfs-cli/modules/object/patch.go @@ -56,7 +56,7 @@ func patch(cmd *cobra.Command, _ []string) { var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr := ReadObjectAddress(cmd, &cnr, &obj) ranges, err := getRangeSlice(cmd) commonCmd.ExitOnErr(cmd, "", err) diff --git a/cmd/frostfs-cli/modules/object/range.go b/cmd/frostfs-cli/modules/object/range.go index 8f59906ca7..be4fee4cf5 100644 --- a/cmd/frostfs-cli/modules/object/range.go +++ b/cmd/frostfs-cli/modules/object/range.go @@ -47,7 +47,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) { var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr := ReadObjectAddress(cmd, &cnr, &obj) ranges, err := getRangeList(cmd) commonCmd.ExitOnErr(cmd, "", err) diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index b090c9f8c4..3955f8ee13 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -74,7 +74,7 @@ func parseXHeaders(cmd *cobra.Command) []string { return xs } -func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address { +func ReadObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address { readCID(cmd, cnr) readOID(cmd, obj) From df6d9da82aa965dbbf45114149b8279655276127 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 4 Feb 2025 21:23:00 +0300 Subject: [PATCH 1229/1413] [#1635] cli: Add command to get object's shard info Added `frostfs-cli object locate` subcommand. It lists info about shards storing an object. Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/modules/control/locate.go | 118 ++++++++++++++++++++++ cmd/frostfs-cli/modules/control/root.go | 2 + go.mod | 4 +- go.sum | 8 +- 4 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 cmd/frostfs-cli/modules/control/locate.go diff --git a/cmd/frostfs-cli/modules/control/locate.go b/cmd/frostfs-cli/modules/control/locate.go new file mode 100644 index 0000000000..d10e2a8964 --- /dev/null +++ b/cmd/frostfs-cli/modules/control/locate.go @@ -0,0 +1,118 @@ +package control + +import ( + "bytes" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" + object "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/modules/object" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" + rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + + "github.com/mr-tron/base58" + "github.com/spf13/cobra" +) + +const ( + FullInfoFlag = "full" + FullInfoFlagUsage = "Print full ShardInfo." +) + +var locateObjectCmd = &cobra.Command{ + Use: "locate-object", + Short: "List shards storing the object", + Long: "List shards storing the object", + Run: locateObject, +} + +func initControlLocateObjectCmd() { + initControlFlags(locateObjectCmd) + + flags := locateObjectCmd.Flags() + + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = locateObjectCmd.MarkFlagRequired(commonflags.CIDFlag) + + flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) + _ = locateObjectCmd.MarkFlagRequired(commonflags.OIDFlag) + + flags.Bool(commonflags.JSON, false, "Print shard info as a JSON array. Requires --full flag.") + flags.Bool(FullInfoFlag, false, FullInfoFlagUsage) +} + +func locateObject(cmd *cobra.Command, _ []string) { + var cnr cid.ID + var obj oid.ID + + _ = object.ReadObjectAddress(cmd, &cnr, &obj) + + pk := key.Get(cmd) + + body := new(control.ListShardsForObjectRequest_Body) + body.SetContainerId(cnr.EncodeToString()) + body.SetObjectId(obj.EncodeToString()) + req := new(control.ListShardsForObjectRequest) + req.SetBody(body) + signRequest(cmd, pk, req) + + cli := getClient(cmd, pk) + + var err error + var resp *control.ListShardsForObjectResponse + err = cli.ExecRaw(func(client *rawclient.Client) error { + resp, err = control.ListShardsForObject(client, req) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + + shardIDs := resp.GetBody().GetShard_ID() + + isFull, _ := cmd.Flags().GetBool(FullInfoFlag) + if !isFull { + for _, id := range shardIDs { + cmd.Println(base58.Encode(id)) + } + return + } + + // get full shard info + listShardsReq := new(control.ListShardsRequest) + listShardsReq.SetBody(new(control.ListShardsRequest_Body)) + signRequest(cmd, pk, listShardsReq) + var listShardsResp *control.ListShardsResponse + err = cli.ExecRaw(func(client *rawclient.Client) error { + listShardsResp, err = control.ListShards(client, listShardsReq) + return err + }) + commonCmd.ExitOnErr(cmd, "rpc error: %w", err) + + verifyResponse(cmd, listShardsResp.GetSignature(), listShardsResp.GetBody()) + + shards := listShardsResp.GetBody().GetShards() + sortShardsByID(shards) + shards = filterShards(shards, shardIDs) + + isJSON, _ := cmd.Flags().GetBool(commonflags.JSON) + if isJSON { + prettyPrintShardsJSON(cmd, shards) + } else { + prettyPrintShards(cmd, shards) + } +} + +func filterShards(info []control.ShardInfo, ids [][]byte) []control.ShardInfo { + var res []control.ShardInfo + for _, id := range ids { + for _, inf := range info { + if bytes.Equal(inf.Shard_ID, id) { + res = append(res, inf) + } + } + } + return res +} diff --git a/cmd/frostfs-cli/modules/control/root.go b/cmd/frostfs-cli/modules/control/root.go index b20d3618eb..3abfe80cbe 100644 --- a/cmd/frostfs-cli/modules/control/root.go +++ b/cmd/frostfs-cli/modules/control/root.go @@ -39,6 +39,7 @@ func init() { listRulesCmd, getRuleCmd, listTargetsCmd, + locateObjectCmd, ) initControlHealthCheckCmd() @@ -52,4 +53,5 @@ func init() { initControlListRulesCmd() initControGetRuleCmd() initControlListTargetsCmd() + initControlLocateObjectCmd() } diff --git a/go.mod b/go.mod index 18378466eb..9d0988bcd4 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( code.gitea.io/sdk/gitea v0.17.1 - git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1-0.20241205083807-762d7f9f9f08 + git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 @@ -12,7 +12,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/VictoriaMetrics/easyproto v0.1.4 diff --git a/go.sum b/go.sum index 5205dddeff..3ec679ee70 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8= code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1-0.20241205083807-762d7f9f9f08 h1:tl1TT+zNk1lF/J5EaD3syDrTaYbQwvJKVOVENM4oQ+k= -git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1-0.20241205083807-762d7f9f9f08/go.mod h1:5fSm/l5xSjGWqsPUffSdboiGFUHa7y/1S0fvxzQowN8= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1 h1:k1Qw8dWUQczfo0eVXlhrq9eXEbUMyDLW8jEMzY+gxMc= +git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1/go.mod h1:5fSm/l5xSjGWqsPUffSdboiGFUHa7y/1S0fvxzQowN8= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= @@ -18,8 +18,8 @@ git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/96 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972/go.mod h1:2hM42MBrlhvN6XToaW6OWNk5ZLcu1FhaukGgxtfpDDI= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07 h1:gPaqGsk6gSWQyNVjaStydfUz6Z/loHc9XyvGrJ5qSPY= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88 h1:vgbfkcnIexZUm3vREBBSa/Gv1Whjd1SFCUd0A+IaGPQ= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240814080254-96225afacb88/go.mod h1:SgioiGhQNWqiV5qpFAXRDJF81SEFRBhtwGEiU0FViyA= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b h1:M50kdfrf/h8c3cz0bJ2AEUcbXvAlPFVC1Wp1WkfZ/8E= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b/go.mod h1:GZTk55RI4dKzsK6BCn5h2xxE28UHNfgoq/NJxW/LQ6A= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= From bd61f7bf0a8e5a102175da73d0b79e9218de69f8 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Fri, 7 Mar 2025 12:29:28 +0300 Subject: [PATCH 1230/1413] [#1666] audit: Fix duplicated log in `Patch` method When we do `object patch` with audit enabled we get several duplicated entries in logs. `object patch` request is logged in 2 places: 1. `(*auditPatchStream) CloseAndRecv()` - when the client closes the request stream or when stream gets aborted. 2. `(*auditPatchStream) Send()` - when stream was NOT aborted. `Send()` doesn't check if `err != nil` before logging. It led to to logging on every `Send()` call. Signed-off-by: Ekaterina Lebedeva --- pkg/services/object/audit.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/object/audit.go b/pkg/services/object/audit.go index 367be0c0cd..f8ee089fe2 100644 --- a/pkg/services/object/audit.go +++ b/pkg/services/object/audit.go @@ -224,7 +224,7 @@ func (a *auditPatchStream) Send(ctx context.Context, req *object.PatchRequest) e if err != nil { a.failed = true } - if !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here + if err != nil && !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here audit.LogRequestWithKey(ctx, a.log, objectGRPC.ObjectService_Patch_FullMethodName, a.key, audit.TargetFromContainerIDObjectID(a.containerID, a.objectID), !a.failed) From 8643e0abc569f9f540abac5b9d0fba9e05ae5640 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 10 Mar 2025 17:51:06 +0300 Subject: [PATCH 1231/1413] [#1668] writecache: Use object size to check free space Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/writecache/put.go | 11 ++++++++++- pkg/local_object_storage/writecache/state.go | 4 ---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/writecache/put.go b/pkg/local_object_storage/writecache/put.go index 7da5c4d3a0..2fbf509137 100644 --- a/pkg/local_object_storage/writecache/put.go +++ b/pkg/local_object_storage/writecache/put.go @@ -2,6 +2,7 @@ package writecache import ( "context" + "fmt" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" @@ -59,7 +60,15 @@ func (c *cache) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, erro // putBig writes object to FSTree and pushes it to the flush workers queue. func (c *cache) putBig(ctx context.Context, prm common.PutPrm) error { - if !c.hasEnoughSpaceFS() { + if prm.RawData == nil { // foolproof: RawData should be marshalled by shard. + data, err := prm.Object.Marshal() + if err != nil { + return fmt.Errorf("cannot marshal object: %w", err) + } + prm.RawData = data + } + size := uint64(len(prm.RawData)) + if !c.hasEnoughSpace(size) { return ErrOutOfSpace } diff --git a/pkg/local_object_storage/writecache/state.go b/pkg/local_object_storage/writecache/state.go index 44caa26033..7a52d36728 100644 --- a/pkg/local_object_storage/writecache/state.go +++ b/pkg/local_object_storage/writecache/state.go @@ -7,10 +7,6 @@ func (c *cache) estimateCacheSize() (uint64, uint64) { return count, size } -func (c *cache) hasEnoughSpaceFS() bool { - return c.hasEnoughSpace(c.maxObjectSize) -} - func (c *cache) hasEnoughSpace(objectSize uint64) bool { count, size := c.estimateCacheSize() if c.maxCacheCount > 0 && count+1 > c.maxCacheCount { From d36afa31c7b4d0a878ecbe8e41657f6f955fbdc9 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 18 Feb 2025 10:57:17 +0300 Subject: [PATCH 1232/1413] [#1653] qos: Fix logging Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/qos.go | 6 ++++-- internal/logs/logs.go | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-node/qos.go b/cmd/frostfs-node/qos.go index bfc2783331..9663fc6aec 100644 --- a/cmd/frostfs-node/qos.go +++ b/cmd/frostfs-node/qos.go @@ -47,7 +47,7 @@ func (s *cfgQoSService) AdjustIncomingTag(ctx context.Context, requestSignPublic } ioTag, err := qos.FromRawString(rawTag) if err != nil { - s.logger.Warn(ctx, logs.FailedToParseIncomingIOTag, zap.Error(err)) + s.logger.Debug(ctx, logs.FailedToParseIncomingIOTag, zap.Error(err)) return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) } @@ -70,6 +70,7 @@ func (s *cfgQoSService) AdjustIncomingTag(ctx context.Context, requestSignPublic return ctx } } + s.logger.Debug(ctx, logs.FailedToValidateIncomingIOTag) return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) case qos.IOTagInternal: for _, pk := range s.allowedInternalPubs { @@ -87,9 +88,10 @@ func (s *cfgQoSService) AdjustIncomingTag(ctx context.Context, requestSignPublic return ctx } } + s.logger.Debug(ctx, logs.FailedToValidateIncomingIOTag) return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) default: - s.logger.Warn(ctx, logs.NotSupportedIncomingIOTagReplacedWithClient, zap.Stringer("io_tag", ioTag)) + s.logger.Debug(ctx, logs.NotSupportedIncomingIOTagReplacedWithClient, zap.Stringer("io_tag", ioTag)) return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) } } diff --git a/internal/logs/logs.go b/internal/logs/logs.go index d07f47fbf5..6115cdf90d 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -513,4 +513,5 @@ const ( FailedToParseIncomingIOTag = "failed to parse incoming IO tag" NotSupportedIncomingIOTagReplacedWithClient = "incoming IO tag is not supported, replaced with `client`" FailedToGetNetmapToAdjustIOTag = "failed to get netmap to adjust IO tag, replaced with `client`" + FailedToValidateIncomingIOTag = "failed to validate incoming IO tag, replaced with `client`" ) From 3727d60331d3d410087a146da1df2dfbef7fa7cd Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 5 Mar 2025 13:53:32 +0300 Subject: [PATCH 1233/1413] [#1653] qos: Add metrics Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 + internal/metrics/consts.go | 2 + internal/metrics/node.go | 6 ++ internal/metrics/qos.go | 52 +++++++++ internal/qos/limiter.go | 101 +++++++++++++++--- internal/qos/metrics.go | 31 ++++++ internal/qos/stats.go | 28 +++++ internal/qos/validate.go | 9 -- .../engine/engine_test.go | 4 + pkg/local_object_storage/shard/id.go | 1 + 10 files changed, 214 insertions(+), 21 deletions(-) create mode 100644 internal/metrics/qos.go create mode 100644 internal/qos/metrics.go create mode 100644 internal/qos/stats.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index afde0bbc0c..92aa827f24 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -1048,6 +1048,7 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID } if c.metricsCollector != nil { mbOptions = append(mbOptions, meta.WithMetrics(lsmetrics.NewMetabaseMetrics(shCfg.metaCfg.path, c.metricsCollector.MetabaseMetrics()))) + shCfg.limiter.SetMetrics(c.metricsCollector.QoSMetrics()) } var sh shardOptsWithID diff --git a/internal/metrics/consts.go b/internal/metrics/consts.go index cb165de69c..9123541ff5 100644 --- a/internal/metrics/consts.go +++ b/internal/metrics/consts.go @@ -23,6 +23,7 @@ const ( policerSubsystem = "policer" commonCacheSubsystem = "common_cache" multinetSubsystem = "multinet" + qosSubsystem = "qos" successLabel = "success" shardIDLabel = "shard_id" @@ -43,6 +44,7 @@ const ( hitLabel = "hit" cacheLabel = "cache" sourceIPLabel = "source_ip" + ioTagLabel = "io_tag" readWriteMode = "READ_WRITE" readOnlyMode = "READ_ONLY" diff --git a/internal/metrics/node.go b/internal/metrics/node.go index 4ea3c7c24d..8ade19eb27 100644 --- a/internal/metrics/node.go +++ b/internal/metrics/node.go @@ -26,6 +26,7 @@ type NodeMetrics struct { morphCache *morphCacheMetrics log logger.LogMetrics multinet *multinetMetrics + qos *QoSMetrics // nolint: unused appInfo *ApplicationInfo } @@ -55,6 +56,7 @@ func NewNodeMetrics() *NodeMetrics { log: logger.NewLogMetrics(namespace), appInfo: NewApplicationInfo(misc.Version), multinet: newMultinetMetrics(namespace), + qos: newQoSMetrics(), } } @@ -126,3 +128,7 @@ func (m *NodeMetrics) LogMetrics() logger.LogMetrics { func (m *NodeMetrics) MultinetMetrics() MultinetMetrics { return m.multinet } + +func (m *NodeMetrics) QoSMetrics() *QoSMetrics { + return m.qos +} diff --git a/internal/metrics/qos.go b/internal/metrics/qos.go new file mode 100644 index 0000000000..17fb67a27a --- /dev/null +++ b/internal/metrics/qos.go @@ -0,0 +1,52 @@ +package metrics + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics" + "github.com/prometheus/client_golang/prometheus" +) + +type QoSMetrics struct { + opsCounter *prometheus.GaugeVec +} + +func newQoSMetrics() *QoSMetrics { + return &QoSMetrics{ + opsCounter: metrics.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: namespace, + Subsystem: qosSubsystem, + Name: "operations_total", + Help: "Count of pending, in progree, completed and failed due of resource exhausted error operations for each shard", + }, []string{shardIDLabel, operationLabel, ioTagLabel, typeLabel}), + } +} + +func (m *QoSMetrics) SetOperationTagCounters(shardID, operation, tag string, pending, inProgress, completed, resourceExhausted uint64) { + m.opsCounter.With(prometheus.Labels{ + shardIDLabel: shardID, + operationLabel: operation, + ioTagLabel: tag, + typeLabel: "pending", + }).Set(float64(pending)) + m.opsCounter.With(prometheus.Labels{ + shardIDLabel: shardID, + operationLabel: operation, + ioTagLabel: tag, + typeLabel: "in_progress", + }).Set(float64(inProgress)) + m.opsCounter.With(prometheus.Labels{ + shardIDLabel: shardID, + operationLabel: operation, + ioTagLabel: tag, + typeLabel: "completed", + }).Set(float64(completed)) + m.opsCounter.With(prometheus.Labels{ + shardIDLabel: shardID, + operationLabel: operation, + ioTagLabel: tag, + typeLabel: "resource_exhausted", + }).Set(float64(resourceExhausted)) +} + +func (m *QoSMetrics) Close(shardID string) { + m.opsCounter.DeletePartialMatch(prometheus.Labels{shardIDLabel: shardID}) +} diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index b1406a7f37..8f00791c50 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "sync" + "sync/atomic" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" @@ -15,6 +17,9 @@ import ( const ( defaultIdleTimeout time.Duration = 0 defaultShare float64 = 1.0 + minusOne = ^uint64(0) + + defaultMetricsCollectTimeout = 5 * time.Second ) type ReleaseFunc scheduling.ReleaseFunc @@ -22,6 +27,8 @@ type ReleaseFunc scheduling.ReleaseFunc type Limiter interface { ReadRequest(context.Context) (ReleaseFunc, error) WriteRequest(context.Context) (ReleaseFunc, error) + SetParentID(string) + SetMetrics(Metrics) Close() } @@ -34,10 +41,6 @@ func NewLimiter(c *limits.Config) (Limiter, error) { if err := validateConfig(c); err != nil { return nil, err } - read, write := c.Read(), c.Write() - if isNoop(read, write) { - return noopLimiterInstance, nil - } readScheduler, err := createScheduler(c.Read()) if err != nil { return nil, fmt.Errorf("create read scheduler: %w", err) @@ -46,10 +49,18 @@ func NewLimiter(c *limits.Config) (Limiter, error) { if err != nil { return nil, fmt.Errorf("create write scheduler: %w", err) } - return &mClockLimiter{ + l := &mClockLimiter{ readScheduler: readScheduler, writeScheduler: writeScheduler, - }, nil + closeCh: make(chan struct{}), + wg: &sync.WaitGroup{}, + readStats: createStats(), + writeStats: createStats(), + } + l.shardID.Store(&shardID{}) + l.metrics.Store(&metricsHolder{metrics: &noopMetrics{}}) + l.startMetricsCollect() + return l, nil } func createScheduler(config limits.OpConfig) (scheduler, error) { @@ -91,7 +102,7 @@ var ( ) func NewNoopLimiter() Limiter { - return &noopLimiter{} + return noopLimiterInstance } type noopLimiter struct{} @@ -104,43 +115,109 @@ func (n *noopLimiter) WriteRequest(context.Context) (ReleaseFunc, error) { return releaseStub, nil } +func (n *noopLimiter) SetParentID(string) {} + func (n *noopLimiter) Close() {} +func (n *noopLimiter) SetMetrics(Metrics) {} + var _ Limiter = (*mClockLimiter)(nil) +type shardID struct { + id string +} + type mClockLimiter struct { readScheduler scheduler writeScheduler scheduler + + readStats map[string]*stat + writeStats map[string]*stat + + shardID atomic.Pointer[shardID] + metrics atomic.Pointer[metricsHolder] + closeCh chan struct{} + wg *sync.WaitGroup } func (n *mClockLimiter) ReadRequest(ctx context.Context) (ReleaseFunc, error) { - return requestArrival(ctx, n.readScheduler) + return requestArrival(ctx, n.readScheduler, n.readStats) } func (n *mClockLimiter) WriteRequest(ctx context.Context) (ReleaseFunc, error) { - return requestArrival(ctx, n.writeScheduler) + return requestArrival(ctx, n.writeScheduler, n.writeStats) } -func requestArrival(ctx context.Context, s scheduler) (ReleaseFunc, error) { +func requestArrival(ctx context.Context, s scheduler, stats map[string]*stat) (ReleaseFunc, error) { tag, ok := tagging.IOTagFromContext(ctx) if !ok { tag = IOTagClient.String() } + stat := getStat(tag, stats) + stat.pending.Add(1) if tag == IOTagCritical.String() { - return releaseStub, nil + stat.inProgress.Add(1) + return func() { + stat.completed.Add(1) + }, nil } rel, err := s.RequestArrival(ctx, tag) + stat.inProgress.Add(1) if err != nil { if errors.Is(err, scheduling.ErrMClockSchedulerRequestLimitExceeded) || errors.Is(err, errSemaphoreLimitExceeded) { + stat.resourceExhausted.Add(1) return nil, &apistatus.ResourceExhausted{} } + stat.completed.Add(1) return nil, err } - return ReleaseFunc(rel), nil + return func() { + rel() + stat.completed.Add(1) + }, nil } func (n *mClockLimiter) Close() { n.readScheduler.Close() n.writeScheduler.Close() + close(n.closeCh) + n.wg.Wait() + n.metrics.Load().metrics.Close(n.shardID.Load().id) +} + +func (n *mClockLimiter) SetParentID(parentID string) { + n.shardID.Store(&shardID{id: parentID}) +} + +func (n *mClockLimiter) SetMetrics(m Metrics) { + n.metrics.Store(&metricsHolder{metrics: m}) +} + +func (n *mClockLimiter) startMetricsCollect() { + n.wg.Add(1) + go func() { + defer n.wg.Done() + + ticker := time.NewTicker(defaultMetricsCollectTimeout) + defer ticker.Stop() + for { + select { + case <-n.closeCh: + return + case <-ticker.C: + shardID := n.shardID.Load().id + if shardID == "" { + continue + } + metrics := n.metrics.Load().metrics + for tag, s := range n.readStats { + metrics.SetOperationTagCounters(shardID, "read", tag, s.pending.Load(), s.inProgress.Load(), s.completed.Load(), s.resourceExhausted.Load()) + } + for tag, s := range n.writeStats { + metrics.SetOperationTagCounters(shardID, "write", tag, s.pending.Load(), s.inProgress.Load(), s.completed.Load(), s.resourceExhausted.Load()) + } + } + } + }() } diff --git a/internal/qos/metrics.go b/internal/qos/metrics.go new file mode 100644 index 0000000000..c00da51b71 --- /dev/null +++ b/internal/qos/metrics.go @@ -0,0 +1,31 @@ +package qos + +import "sync/atomic" + +type Metrics interface { + SetOperationTagCounters(shardID, operation, tag string, pending, inProgress, completed, resourceExhausted uint64) + Close(shardID string) +} + +var _ Metrics = (*noopMetrics)(nil) + +type noopMetrics struct{} + +func (n *noopMetrics) SetOperationTagCounters(string, string, string, uint64, uint64, uint64, uint64) { +} + +func (n *noopMetrics) Close(string) {} + +// stat presents limiter statistics cumulative counters. +// +// Each operation changes its status as follows: `pending` -> `in_progress` -> `completed` or `resource_exhausted`. +type stat struct { + completed atomic.Uint64 + pending atomic.Uint64 + resourceExhausted atomic.Uint64 + inProgress atomic.Uint64 +} + +type metricsHolder struct { + metrics Metrics +} diff --git a/internal/qos/stats.go b/internal/qos/stats.go new file mode 100644 index 0000000000..f077f552ba --- /dev/null +++ b/internal/qos/stats.go @@ -0,0 +1,28 @@ +package qos + +const unknownStatsTag = "unknown" + +var statTags = map[string]struct{}{ + IOTagClient.String(): {}, + IOTagBackground.String(): {}, + IOTagInternal.String(): {}, + IOTagPolicer.String(): {}, + IOTagWritecache.String(): {}, + IOTagCritical.String(): {}, + unknownStatsTag: {}, +} + +func createStats() map[string]*stat { + result := make(map[string]*stat) + for tag := range statTags { + result[tag] = &stat{} + } + return result +} + +func getStat(tag string, stats map[string]*stat) *stat { + if v, ok := stats[tag]; ok { + return v + } + return stats[unknownStatsTag] +} diff --git a/internal/qos/validate.go b/internal/qos/validate.go index 43aa749423..3fa4ebbd17 100644 --- a/internal/qos/validate.go +++ b/internal/qos/validate.go @@ -90,12 +90,3 @@ func float64Value(f *float64) float64 { } return *f } - -func isNoop(read, write limits.OpConfig) bool { - return read.MaxRunningOps == limits.NoLimit && - read.MaxWaitingOps == limits.NoLimit && - write.MaxRunningOps == limits.NoLimit && - write.MaxWaitingOps == limits.NoLimit && - len(read.Tags) == 0 && - len(write.Tags) == 0 -} diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 7ddde1f024..3f9196128c 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -163,6 +163,8 @@ type testQoSLimiter struct { write atomic.Int64 } +func (t *testQoSLimiter) SetMetrics(qos.Metrics) {} + func (t *testQoSLimiter) Close() { require.Equal(t.t, int64(0), t.read.Load(), "read requests count after limiter close must be 0") require.Equal(t.t, int64(0), t.write.Load(), "write requests count after limiter close must be 0") @@ -177,3 +179,5 @@ func (t *testQoSLimiter) WriteRequest(context.Context) (qos.ReleaseFunc, error) t.write.Add(1) return func() { t.write.Add(-1) }, nil } + +func (t *testQoSLimiter) SetParentID(string) {} diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index 26492cf01e..b233b705c9 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -61,6 +61,7 @@ func (s *Shard) UpdateID(ctx context.Context) (err error) { if s.pilorama != nil { s.pilorama.SetParentID(s.info.ID.String()) } + s.opsLimiter.SetParentID(s.info.ID.String()) if len(idFromMetabase) == 0 && !modeDegraded { if setErr := s.metaBase.SetShardID(ctx, *s.info.ID, s.GetMode()); setErr != nil { From 4ed2bbdb0f72589e59b5127ce237b65151f13b57 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 5 Mar 2025 15:25:35 +0300 Subject: [PATCH 1234/1413] [#1653] objectSvc: Add operations by IO tag metric Signed-off-by: Dmitrii Stepanov --- internal/metrics/object.go | 19 +++++++++++++++---- internal/qos/tags.go | 15 ++++++++++++++- pkg/services/object/metrics.go | 21 +++++++++++---------- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/internal/metrics/object.go b/internal/metrics/object.go index 0ba994ed34..e4f6dfde16 100644 --- a/internal/metrics/object.go +++ b/internal/metrics/object.go @@ -9,13 +9,14 @@ import ( ) type ObjectServiceMetrics interface { - AddRequestDuration(method string, d time.Duration, success bool) + AddRequestDuration(method string, d time.Duration, success bool, ioTag string) AddPayloadSize(method string, size int) } type objectServiceMetrics struct { - methodDuration *prometheus.HistogramVec - payloadCounter *prometheus.CounterVec + methodDuration *prometheus.HistogramVec + payloadCounter *prometheus.CounterVec + ioTagOpsCounter *prometheus.CounterVec } func newObjectServiceMetrics() *objectServiceMetrics { @@ -32,14 +33,24 @@ func newObjectServiceMetrics() *objectServiceMetrics { Name: "request_payload_bytes", Help: "Object Service request payload", }, []string{methodLabel}), + ioTagOpsCounter: metrics.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: objectSubsystem, + Name: "requests_total", + Help: "Count of requests for each IO tag", + }, []string{methodLabel, ioTagLabel}), } } -func (m *objectServiceMetrics) AddRequestDuration(method string, d time.Duration, success bool) { +func (m *objectServiceMetrics) AddRequestDuration(method string, d time.Duration, success bool, ioTag string) { m.methodDuration.With(prometheus.Labels{ methodLabel: method, successLabel: strconv.FormatBool(success), }).Observe(d.Seconds()) + m.ioTagOpsCounter.With(prometheus.Labels{ + ioTagLabel: ioTag, + methodLabel: method, + }).Inc() } func (m *objectServiceMetrics) AddPayloadSize(method string, size int) { diff --git a/internal/qos/tags.go b/internal/qos/tags.go index 6a9a7f7a41..9db45f190e 100644 --- a/internal/qos/tags.go +++ b/internal/qos/tags.go @@ -1,6 +1,11 @@ package qos -import "fmt" +import ( + "context" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" +) type IOTag string @@ -37,3 +42,11 @@ func FromRawString(s string) (IOTag, error) { func (t IOTag) String() string { return string(t) } + +func IOTagFromContext(ctx context.Context) string { + tag, ok := tagging.IOTagFromContext(ctx) + if !ok { + tag = "undefined" + } + return tag +} diff --git a/pkg/services/object/metrics.go b/pkg/services/object/metrics.go index 19748e9383..6a6ee0f0f3 100644 --- a/pkg/services/object/metrics.go +++ b/pkg/services/object/metrics.go @@ -4,6 +4,7 @@ import ( "context" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" ) @@ -34,7 +35,7 @@ type ( } MetricRegister interface { - AddRequestDuration(string, time.Duration, bool) + AddRequestDuration(string, time.Duration, bool, string) AddPayloadSize(string, int) } ) @@ -51,7 +52,7 @@ func (m MetricCollector) Get(req *object.GetRequest, stream GetObjectStream) (er if m.enabled { t := time.Now() defer func() { - m.metrics.AddRequestDuration("Get", time.Since(t), err == nil) + m.metrics.AddRequestDuration("Get", time.Since(t), err == nil, qos.IOTagFromContext(stream.Context())) }() err = m.next.Get(req, &getStreamMetric{ ServerStream: stream, @@ -106,7 +107,7 @@ func (m MetricCollector) PutSingle(ctx context.Context, request *object.PutSingl res, err := m.next.PutSingle(ctx, request) - m.metrics.AddRequestDuration("PutSingle", time.Since(t), err == nil) + m.metrics.AddRequestDuration("PutSingle", time.Since(t), err == nil, qos.IOTagFromContext(ctx)) if err == nil { m.metrics.AddPayloadSize("PutSingle", len(request.GetBody().GetObject().GetPayload())) } @@ -122,7 +123,7 @@ func (m MetricCollector) Head(ctx context.Context, request *object.HeadRequest) res, err := m.next.Head(ctx, request) - m.metrics.AddRequestDuration("Head", time.Since(t), err == nil) + m.metrics.AddRequestDuration("Head", time.Since(t), err == nil, qos.IOTagFromContext(ctx)) return res, err } @@ -135,7 +136,7 @@ func (m MetricCollector) Search(req *object.SearchRequest, stream SearchStream) err := m.next.Search(req, stream) - m.metrics.AddRequestDuration("Search", time.Since(t), err == nil) + m.metrics.AddRequestDuration("Search", time.Since(t), err == nil, qos.IOTagFromContext(stream.Context())) return err } @@ -148,7 +149,7 @@ func (m MetricCollector) Delete(ctx context.Context, request *object.DeleteReque res, err := m.next.Delete(ctx, request) - m.metrics.AddRequestDuration("Delete", time.Since(t), err == nil) + m.metrics.AddRequestDuration("Delete", time.Since(t), err == nil, qos.IOTagFromContext(ctx)) return res, err } return m.next.Delete(ctx, request) @@ -160,7 +161,7 @@ func (m MetricCollector) GetRange(req *object.GetRangeRequest, stream GetObjectR err := m.next.GetRange(req, stream) - m.metrics.AddRequestDuration("GetRange", time.Since(t), err == nil) + m.metrics.AddRequestDuration("GetRange", time.Since(t), err == nil, qos.IOTagFromContext(stream.Context())) return err } @@ -173,7 +174,7 @@ func (m MetricCollector) GetRangeHash(ctx context.Context, request *object.GetRa res, err := m.next.GetRangeHash(ctx, request) - m.metrics.AddRequestDuration("GetRangeHash", time.Since(t), err == nil) + m.metrics.AddRequestDuration("GetRangeHash", time.Since(t), err == nil, qos.IOTagFromContext(ctx)) return res, err } @@ -209,7 +210,7 @@ func (s putStreamMetric) Send(ctx context.Context, req *object.PutRequest) error func (s putStreamMetric) CloseAndRecv(ctx context.Context) (*object.PutResponse, error) { res, err := s.stream.CloseAndRecv(ctx) - s.metrics.AddRequestDuration("Put", time.Since(s.start), err == nil) + s.metrics.AddRequestDuration("Put", time.Since(s.start), err == nil, qos.IOTagFromContext(ctx)) return res, err } @@ -223,7 +224,7 @@ func (s patchStreamMetric) Send(ctx context.Context, req *object.PatchRequest) e func (s patchStreamMetric) CloseAndRecv(ctx context.Context) (*object.PatchResponse, error) { res, err := s.stream.CloseAndRecv(ctx) - s.metrics.AddRequestDuration("Patch", time.Since(s.start), err == nil) + s.metrics.AddRequestDuration("Patch", time.Since(s.start), err == nil, qos.IOTagFromContext(ctx)) return res, err } From 597bce7a879f2c5258b819014ca80b5815f6a168 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 5 Mar 2025 15:44:15 +0300 Subject: [PATCH 1235/1413] [#1653] treeSvc: Add operations by IO tag metric Signed-off-by: Dmitrii Stepanov --- internal/metrics/treeservice.go | 15 +++++++++++++++ pkg/services/tree/metrics.go | 2 ++ pkg/services/tree/service.go | 9 +++++++++ 3 files changed, 26 insertions(+) diff --git a/internal/metrics/treeservice.go b/internal/metrics/treeservice.go index 6702aa83c3..e192c4398e 100644 --- a/internal/metrics/treeservice.go +++ b/internal/metrics/treeservice.go @@ -12,12 +12,14 @@ type TreeMetricsRegister interface { AddReplicateTaskDuration(time.Duration, bool) AddReplicateWaitDuration(time.Duration, bool) AddSyncDuration(time.Duration, bool) + AddOperation(string, string) } type treeServiceMetrics struct { replicateTaskDuration *prometheus.HistogramVec replicateWaitDuration *prometheus.HistogramVec syncOpDuration *prometheus.HistogramVec + ioTagOpsCounter *prometheus.CounterVec } var _ TreeMetricsRegister = (*treeServiceMetrics)(nil) @@ -42,6 +44,12 @@ func newTreeServiceMetrics() *treeServiceMetrics { Name: "sync_duration_seconds", Help: "Duration of synchronization operations", }, []string{successLabel}), + ioTagOpsCounter: metrics.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Subsystem: treeServiceSubsystem, + Name: "requests_total", + Help: "Count of requests for each IO tag", + }, []string{methodLabel, ioTagLabel}), } } @@ -62,3 +70,10 @@ func (m *treeServiceMetrics) AddSyncDuration(d time.Duration, success bool) { successLabel: strconv.FormatBool(success), }).Observe(d.Seconds()) } + +func (m *treeServiceMetrics) AddOperation(op string, ioTag string) { + m.ioTagOpsCounter.With(prometheus.Labels{ + ioTagLabel: ioTag, + methodLabel: op, + }).Inc() +} diff --git a/pkg/services/tree/metrics.go b/pkg/services/tree/metrics.go index 0f0e4ee575..07503f8c3c 100644 --- a/pkg/services/tree/metrics.go +++ b/pkg/services/tree/metrics.go @@ -6,6 +6,7 @@ type MetricsRegister interface { AddReplicateTaskDuration(time.Duration, bool) AddReplicateWaitDuration(time.Duration, bool) AddSyncDuration(time.Duration, bool) + AddOperation(string, string) } type defaultMetricsRegister struct{} @@ -13,3 +14,4 @@ type defaultMetricsRegister struct{} func (defaultMetricsRegister) AddReplicateTaskDuration(time.Duration, bool) {} func (defaultMetricsRegister) AddReplicateWaitDuration(time.Duration, bool) {} func (defaultMetricsRegister) AddSyncDuration(time.Duration, bool) {} +func (defaultMetricsRegister) AddOperation(string, string) {} diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 2e9722e791..f9b7395e70 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -105,6 +105,7 @@ func (s *Service) Shutdown() { } func (s *Service) Add(ctx context.Context, req *AddRequest) (*AddResponse, error) { + defer s.metrics.AddOperation("Add", qos.IOTagFromContext(ctx)) if !s.initialSyncDone.Load() { return nil, ErrAlreadySyncing } @@ -148,6 +149,7 @@ func (s *Service) Add(ctx context.Context, req *AddRequest) (*AddResponse, error } func (s *Service) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByPathResponse, error) { + defer s.metrics.AddOperation("AddByPath", qos.IOTagFromContext(ctx)) if !s.initialSyncDone.Load() { return nil, ErrAlreadySyncing } @@ -203,6 +205,7 @@ func (s *Service) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByP } func (s *Service) Remove(ctx context.Context, req *RemoveRequest) (*RemoveResponse, error) { + defer s.metrics.AddOperation("Remove", qos.IOTagFromContext(ctx)) if !s.initialSyncDone.Load() { return nil, ErrAlreadySyncing } @@ -247,6 +250,7 @@ func (s *Service) Remove(ctx context.Context, req *RemoveRequest) (*RemoveRespon // Move applies client operation to the specified tree and pushes in queue // for replication on other nodes. func (s *Service) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, error) { + defer s.metrics.AddOperation("Move", qos.IOTagFromContext(ctx)) if !s.initialSyncDone.Load() { return nil, ErrAlreadySyncing } @@ -290,6 +294,7 @@ func (s *Service) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, er } func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) (*GetNodeByPathResponse, error) { + defer s.metrics.AddOperation("GetNodeByPath", qos.IOTagFromContext(ctx)) if !s.initialSyncDone.Load() { return nil, ErrAlreadySyncing } @@ -363,6 +368,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) } func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeServer) error { + defer s.metrics.AddOperation("GetSubTree", qos.IOTagFromContext(srv.Context())) if !s.initialSyncDone.Load() { return ErrAlreadySyncing } @@ -590,6 +596,7 @@ func sortByFilename(nodes []pilorama.NodeInfo, d GetSubTreeRequest_Body_Order_Di // Apply locally applies operation from the remote node to the tree. func (s *Service) Apply(ctx context.Context, req *ApplyRequest) (*ApplyResponse, error) { + defer s.metrics.AddOperation("Apply", qos.IOTagFromContext(ctx)) err := verifyMessage(req) if err != nil { return nil, err @@ -633,6 +640,7 @@ func (s *Service) Apply(ctx context.Context, req *ApplyRequest) (*ApplyResponse, } func (s *Service) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) error { + defer s.metrics.AddOperation("GetOpLog", qos.IOTagFromContext(srv.Context())) if !s.initialSyncDone.Load() { return ErrAlreadySyncing } @@ -697,6 +705,7 @@ func (s *Service) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) } func (s *Service) TreeList(ctx context.Context, req *TreeListRequest) (*TreeListResponse, error) { + defer s.metrics.AddOperation("TreeList", qos.IOTagFromContext(ctx)) if !s.initialSyncDone.Load() { return nil, ErrAlreadySyncing } From 2005fdda0982f7aa23d5938dfe7a40dd2a72fdb4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 10 Mar 2025 13:04:39 +0300 Subject: [PATCH 1236/1413] [#1667] shard: Drop shard pool After adding an ops limiter, shard's `put` pool is redundant. Signed-off-by: Dmitrii Stepanov --- .../internal/modules/storagecfg/config.go | 2 - cmd/frostfs-node/config.go | 3 - cmd/frostfs-node/config/configdir_test.go | 7 +- cmd/frostfs-node/config/engine/config.go | 16 --- cmd/frostfs-node/config/engine/config_test.go | 2 - config/example/node.env | 1 - config/example/node.json | 1 - config/example/node.yaml | 1 - docs/storage-node-configuration.md | 1 - pkg/local_object_storage/engine/control.go | 10 +- .../engine/control_test.go | 4 - pkg/local_object_storage/engine/engine.go | 18 +-- .../engine/engine_test.go | 1 - pkg/local_object_storage/engine/error_test.go | 1 - pkg/local_object_storage/engine/evacuate.go | 43 +++---- .../engine/evacuate_test.go | 1 - .../engine/inhume_test.go | 2 +- pkg/local_object_storage/engine/put.go | 106 ++++++++---------- pkg/local_object_storage/engine/shards.go | 20 ---- .../engine/shards_test.go | 2 - 20 files changed, 71 insertions(+), 171 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/config.go b/cmd/frostfs-adm/internal/modules/storagecfg/config.go index 77183fb497..67e3414c25 100644 --- a/cmd/frostfs-adm/internal/modules/storagecfg/config.go +++ b/cmd/frostfs-adm/internal/modules/storagecfg/config.go @@ -40,8 +40,6 @@ morph: - address: wss://{{.}}/ws{{end}} {{if not .Relay }} storage: - shard_pool_size: 15 # size of per-shard worker pools used for PUT operations - shard: default: # section with the default shard parameters metabase: diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 92aa827f24..e2fe231358 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -117,7 +117,6 @@ type applicationConfiguration struct { EngineCfg struct { errorThreshold uint32 - shardPoolSize uint32 shards []shardCfg lowMem bool } @@ -250,7 +249,6 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { // Storage Engine a.EngineCfg.errorThreshold = engineconfig.ShardErrorThreshold(c) - a.EngineCfg.shardPoolSize = engineconfig.ShardPoolSize(c) a.EngineCfg.lowMem = engineconfig.EngineLowMemoryConsumption(c) return engineconfig.IterateShards(c, false, func(sc *shardconfig.Config) error { return a.updateShardConfig(c, sc) }) @@ -893,7 +891,6 @@ func (c *cfg) engineOpts() []engine.Option { var opts []engine.Option opts = append(opts, - engine.WithShardPoolSize(c.EngineCfg.shardPoolSize), engine.WithErrorThreshold(c.EngineCfg.errorThreshold), engine.WithLogger(c.log), engine.WithLowMemoryConsumption(c.EngineCfg.lowMem), diff --git a/cmd/frostfs-node/config/configdir_test.go b/cmd/frostfs-node/config/configdir_test.go index 35dae97d9e..ee9d4268be 100644 --- a/cmd/frostfs-node/config/configdir_test.go +++ b/cmd/frostfs-node/config/configdir_test.go @@ -12,13 +12,10 @@ import ( func TestConfigDir(t *testing.T) { dir := t.TempDir() - cfgFileName0 := path.Join(dir, "cfg_00.json") - cfgFileName1 := path.Join(dir, "cfg_01.yml") + cfgFileName := path.Join(dir, "cfg_01.yml") - require.NoError(t, os.WriteFile(cfgFileName0, []byte(`{"storage":{"shard_pool_size":15}}`), 0o777)) - require.NoError(t, os.WriteFile(cfgFileName1, []byte("logger:\n level: debug"), 0o777)) + require.NoError(t, os.WriteFile(cfgFileName, []byte("logger:\n level: debug"), 0o777)) c := New("", dir, "") require.Equal(t, "debug", cast.ToString(c.Sub("logger").Value("level"))) - require.EqualValues(t, 15, cast.ToUint32(c.Sub("storage").Value("shard_pool_size"))) } diff --git a/cmd/frostfs-node/config/engine/config.go b/cmd/frostfs-node/config/engine/config.go index e5735e88be..7994e78095 100644 --- a/cmd/frostfs-node/config/engine/config.go +++ b/cmd/frostfs-node/config/engine/config.go @@ -11,10 +11,6 @@ import ( const ( subsection = "storage" - - // ShardPoolSizeDefault is a default value of routine pool size per-shard to - // process object PUT operations in a storage engine. - ShardPoolSizeDefault = 20 ) // ErrNoShardConfigured is returned when at least 1 shard is required but none are found. @@ -65,18 +61,6 @@ func IterateShards(c *config.Config, required bool, f func(*shardconfig.Config) return nil } -// ShardPoolSize returns the value of "shard_pool_size" config parameter from "storage" section. -// -// Returns ShardPoolSizeDefault if the value is not a positive number. -func ShardPoolSize(c *config.Config) uint32 { - v := config.Uint32Safe(c.Sub(subsection), "shard_pool_size") - if v > 0 { - return v - } - - return ShardPoolSizeDefault -} - // ShardErrorThreshold returns the value of "shard_ro_error_threshold" config parameter from "storage" section. // // Returns 0 if the the value is missing. diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index b912b5d7df..eaf2a294e1 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -54,7 +54,6 @@ func TestEngineSection(t *testing.T) { require.False(t, handlerCalled) require.EqualValues(t, 0, engineconfig.ShardErrorThreshold(empty)) - require.EqualValues(t, engineconfig.ShardPoolSizeDefault, engineconfig.ShardPoolSize(empty)) require.EqualValues(t, mode.ReadWrite, shardconfig.From(empty).Mode()) }) @@ -64,7 +63,6 @@ func TestEngineSection(t *testing.T) { num := 0 require.EqualValues(t, 100, engineconfig.ShardErrorThreshold(c)) - require.EqualValues(t, 15, engineconfig.ShardPoolSize(c)) err := engineconfig.IterateShards(c, true, func(sc *shardconfig.Config) error { defer func() { diff --git a/config/example/node.env b/config/example/node.env index 9bd6453447..010b6840cb 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -97,7 +97,6 @@ FROSTFS_RPC_LIMITS_1_METHODS="/neo.fs.v2.object.ObjectService/Get" FROSTFS_RPC_LIMITS_1_MAX_OPS=10000 # Storage engine section -FROSTFS_STORAGE_SHARD_POOL_SIZE=15 FROSTFS_STORAGE_SHARD_RO_ERROR_THRESHOLD=100 ## 0 shard ### Flag to refill Metabase from BlobStor diff --git a/config/example/node.json b/config/example/node.json index 6b799b3189..b26c35d2cb 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -158,7 +158,6 @@ ] }, "storage": { - "shard_pool_size": 15, "shard_ro_error_threshold": 100, "shard": { "0": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 2552a419ca..58b687d5cc 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -135,7 +135,6 @@ rpc: storage: # note: shard configuration can be omitted for relay node (see `node.relay`) - shard_pool_size: 15 # size of per-shard worker pools used for PUT operations shard_ro_error_threshold: 100 # amount of errors to occur before shard is made read-only (default: 0, ignore errors) shard: diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 271cc6532c..51f0a9669f 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -170,7 +170,6 @@ Local storage engine configuration. | Parameter | Type | Default value | Description | |----------------------------|-----------------------------------|---------------|------------------------------------------------------------------------------------------------------------------| -| `shard_pool_size` | `int` | `20` | Pool size for shard workers. Limits the amount of concurrent `PUT` operations on each shard. | | `shard_ro_error_threshold` | `int` | `0` | Maximum amount of storage errors to encounter before shard automatically moves to `Degraded` or `ReadOnly` mode. | | `low_mem` | `bool` | `false` | Reduce memory consumption by reducing performance. | | `shard` | [Shard config](#shard-subsection) | | Configuration for separate shards. | diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index 6a416cfd94..7caa515d4b 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -153,16 +153,10 @@ func (e *StorageEngine) Close(ctx context.Context) error { } // closes all shards. Never returns an error, shard errors are logged. -func (e *StorageEngine) close(ctx context.Context, releasePools bool) error { +func (e *StorageEngine) close(ctx context.Context) error { e.mtx.RLock() defer e.mtx.RUnlock() - if releasePools { - for _, p := range e.shardPools { - p.Release() - } - } - for id, sh := range e.shards { if err := sh.Close(ctx); err != nil { e.log.Debug(ctx, logs.EngineCouldNotCloseShard, @@ -213,7 +207,7 @@ func (e *StorageEngine) setBlockExecErr(ctx context.Context, err error) error { return e.open(ctx) } } else if prevErr == nil { // ok -> block - return e.close(ctx, errors.Is(err, errClosed)) + return e.close(ctx) } // otherwise do nothing diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index c9efc312ca..a0e658aebb 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -245,7 +245,6 @@ func TestReload(t *testing.T) { // no new paths => no new shards require.Equal(t, shardNum, len(e.shards)) - require.Equal(t, shardNum, len(e.shardPools)) newMeta := filepath.Join(addPath, fmt.Sprintf("%d.metabase", shardNum)) @@ -257,7 +256,6 @@ func TestReload(t *testing.T) { require.NoError(t, e.Reload(context.Background(), rcfg)) require.Equal(t, shardNum+1, len(e.shards)) - require.Equal(t, shardNum+1, len(e.shardPools)) require.NoError(t, e.Close(context.Background())) }) @@ -277,7 +275,6 @@ func TestReload(t *testing.T) { // removed one require.Equal(t, shardNum-1, len(e.shards)) - require.Equal(t, shardNum-1, len(e.shardPools)) require.NoError(t, e.Close(context.Background())) }) @@ -311,7 +308,6 @@ func engineWithShards(t *testing.T, path string, num int) (*StorageEngine, []str } require.Equal(t, num, len(e.shards)) - require.Equal(t, num, len(e.shardPools)) return e, currShards } diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index e13252b824..a915c9bd6c 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -12,7 +12,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -29,8 +28,6 @@ type StorageEngine struct { shards map[string]hashedShard - shardPools map[string]util.WorkerPool - closeCh chan struct{} setModeCh chan setModeRequest wg sync.WaitGroup @@ -193,8 +190,6 @@ type cfg struct { metrics MetricRegister - shardPoolSize uint32 - lowMem bool containerSource atomic.Pointer[containerSource] @@ -202,9 +197,8 @@ type cfg struct { func defaultCfg() *cfg { res := &cfg{ - log: logger.NewLoggerWrapper(zap.L()), - shardPoolSize: 20, - metrics: noopMetrics{}, + log: logger.NewLoggerWrapper(zap.L()), + metrics: noopMetrics{}, } res.containerSource.Store(&containerSource{}) return res @@ -221,7 +215,6 @@ func New(opts ...Option) *StorageEngine { return &StorageEngine{ cfg: c, shards: make(map[string]hashedShard), - shardPools: make(map[string]util.WorkerPool), closeCh: make(chan struct{}), setModeCh: make(chan setModeRequest), evacuateLimiter: &evacuationLimiter{}, @@ -241,13 +234,6 @@ func WithMetrics(v MetricRegister) Option { } } -// WithShardPoolSize returns option to specify size of worker pool for each shard. -func WithShardPoolSize(sz uint32) Option { - return func(c *cfg) { - c.shardPoolSize = sz - } -} - // WithErrorThreshold returns an option to specify size amount of errors after which // shard is moved to read-only mode. func WithErrorThreshold(sz uint32) Option { diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 3f9196128c..6ef3846ee6 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -57,7 +57,6 @@ func (te *testEngineWrapper) setShardsNumOpts( te.shardIDs[i] = shard.ID() } require.Len(t, te.engine.shards, num) - require.Len(t, te.engine.shardPools, num) return te } diff --git a/pkg/local_object_storage/engine/error_test.go b/pkg/local_object_storage/engine/error_test.go index d68a7e826b..57029dd5fc 100644 --- a/pkg/local_object_storage/engine/error_test.go +++ b/pkg/local_object_storage/engine/error_test.go @@ -46,7 +46,6 @@ func newEngineWithErrorThreshold(t testing.TB, dir string, errThreshold uint32) var testShards [2]*testShard te := testNewEngine(t, - WithShardPoolSize(1), WithErrorThreshold(errThreshold), ). setShardsNumOpts(t, 2, func(id int) []shard.Option { diff --git a/pkg/local_object_storage/engine/evacuate.go b/pkg/local_object_storage/engine/evacuate.go index 27eaea7683..c08dfbf03d 100644 --- a/pkg/local_object_storage/engine/evacuate.go +++ b/pkg/local_object_storage/engine/evacuate.go @@ -15,7 +15,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" @@ -201,11 +200,6 @@ func (p *EvacuateShardRes) DeepCopy() *EvacuateShardRes { return res } -type pooledShard struct { - hashedShard - pool util.WorkerPool -} - var errMustHaveTwoShards = errors.New("must have at least 1 spare shard") // Evacuate moves data from one shard to the others. @@ -252,7 +246,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) erro } var mtx sync.RWMutex - copyShards := func() []pooledShard { + copyShards := func() []hashedShard { mtx.RLock() defer mtx.RUnlock() t := slices.Clone(shards) @@ -266,7 +260,7 @@ func (e *StorageEngine) Evacuate(ctx context.Context, prm EvacuateShardPrm) erro } func (e *StorageEngine) evacuateShards(ctx context.Context, shardIDs []string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, + shards func() []hashedShard, shardsToEvacuate map[string]*shard.Shard, ) error { var err error ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShards", @@ -388,7 +382,7 @@ func (e *StorageEngine) getTotals(ctx context.Context, prm EvacuateShardPrm, sha } func (e *StorageEngine) evacuateShard(ctx context.Context, cancel context.CancelCauseFunc, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, + shards func() []hashedShard, shardsToEvacuate map[string]*shard.Shard, egContainer *errgroup.Group, egObject *errgroup.Group, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateShard", @@ -412,7 +406,7 @@ func (e *StorageEngine) evacuateShard(ctx context.Context, cancel context.Cancel } func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context.CancelCauseFunc, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - shards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, + shards func() []hashedShard, shardsToEvacuate map[string]*shard.Shard, egContainer *errgroup.Group, egObject *errgroup.Group, ) error { sh := shardsToEvacuate[shardID] @@ -485,7 +479,7 @@ func (e *StorageEngine) evacuateShardObjects(ctx context.Context, cancel context } func (e *StorageEngine) evacuateShardTrees(ctx context.Context, shardID string, prm EvacuateShardPrm, res *EvacuateShardRes, - getShards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, + getShards func() []hashedShard, shardsToEvacuate map[string]*shard.Shard, ) error { sh := shardsToEvacuate[shardID] shards := getShards() @@ -515,7 +509,7 @@ func (e *StorageEngine) evacuateShardTrees(ctx context.Context, shardID string, } func (e *StorageEngine) evacuateTrees(ctx context.Context, sh *shard.Shard, trees []pilorama.ContainerIDTreeID, - prm EvacuateShardPrm, res *EvacuateShardRes, shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, + prm EvacuateShardPrm, res *EvacuateShardRes, shards []hashedShard, shardsToEvacuate map[string]*shard.Shard, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateTrees", trace.WithAttributes( @@ -583,7 +577,7 @@ func (e *StorageEngine) evacuateTreeToOtherNode(ctx context.Context, sh *shard.S } func (e *StorageEngine) tryEvacuateTreeLocal(ctx context.Context, sh *shard.Shard, tree pilorama.ContainerIDTreeID, - prm EvacuateShardPrm, shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, + prm EvacuateShardPrm, shards []hashedShard, shardsToEvacuate map[string]*shard.Shard, ) (bool, string, error) { target, found, err := e.findShardToEvacuateTree(ctx, tree, shards, shardsToEvacuate) if err != nil { @@ -653,15 +647,15 @@ func (e *StorageEngine) tryEvacuateTreeLocal(ctx context.Context, sh *shard.Shar // findShardToEvacuateTree returns first shard according HRW or first shard with tree exists. func (e *StorageEngine) findShardToEvacuateTree(ctx context.Context, tree pilorama.ContainerIDTreeID, - shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, -) (pooledShard, bool, error) { + shards []hashedShard, shardsToEvacuate map[string]*shard.Shard, +) (hashedShard, bool, error) { hrw.SortHasherSliceByValue(shards, hrw.StringHash(tree.CID.EncodeToString())) - var result pooledShard + var result hashedShard var found bool for _, target := range shards { select { case <-ctx.Done(): - return pooledShard{}, false, ctx.Err() + return hashedShard{}, false, ctx.Err() default: } @@ -689,7 +683,7 @@ func (e *StorageEngine) findShardToEvacuateTree(ctx context.Context, tree pilora return result, found, nil } -func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) ([]pooledShard, error) { +func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) ([]hashedShard, error) { e.mtx.RLock() defer e.mtx.RUnlock() @@ -719,18 +713,15 @@ func (e *StorageEngine) getActualShards(shardIDs []string, prm EvacuateShardPrm) // We must have all shards, to have correct information about their // indexes in a sorted slice and set appropriate marks in the metabase. // Evacuated shard is skipped during put. - shards := make([]pooledShard, 0, len(e.shards)) + shards := make([]hashedShard, 0, len(e.shards)) for id := range e.shards { - shards = append(shards, pooledShard{ - hashedShard: e.shards[id], - pool: e.shardPools[id], - }) + shards = append(shards, e.shards[id]) } return shards, nil } func (e *StorageEngine) evacuateObject(ctx context.Context, shardID string, objInfo *object.Info, prm EvacuateShardPrm, res *EvacuateShardRes, - getShards func() []pooledShard, shardsToEvacuate map[string]*shard.Shard, cnr containerSDK.Container, + getShards func() []hashedShard, shardsToEvacuate map[string]*shard.Shard, cnr containerSDK.Container, ) error { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.evacuateObjects") defer span.End() @@ -800,7 +791,7 @@ func (e *StorageEngine) isNotRepOne(c *container.Container) bool { } func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Address, object *objectSDK.Object, sh *shard.Shard, - shards []pooledShard, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes, cnr containerSDK.Container, + shards []hashedShard, shardsToEvacuate map[string]*shard.Shard, res *EvacuateShardRes, cnr containerSDK.Container, ) (bool, error) { hrw.SortHasherSliceByValue(shards, hrw.StringHash(addr.EncodeToString())) for j := range shards { @@ -813,7 +804,7 @@ func (e *StorageEngine) tryEvacuateObjectLocal(ctx context.Context, addr oid.Add if _, ok := shardsToEvacuate[shards[j].ID().String()]; ok { continue } - switch e.putToShard(ctx, shards[j].hashedShard, shards[j].pool, addr, object, container.IsIndexedContainer(cnr)).status { + switch e.putToShard(ctx, shards[j], addr, object, container.IsIndexedContainer(cnr)).status { case putToShardSuccess: res.objEvacuated.Add(1) e.log.Debug(ctx, logs.EngineObjectIsMovedToAnotherShard, diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 45c4b696b8..ec79232973 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -196,7 +196,6 @@ func TestEvacuateShardObjects(t *testing.T) { e.mtx.Lock() delete(e.shards, evacuateShardID) - delete(e.shardPools, evacuateShardID) e.mtx.Unlock() checkHasObjects(t) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 8c5d28b154..10cebfb52b 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -205,7 +205,7 @@ func BenchmarkInhumeMultipart(b *testing.B) { func benchmarkInhumeMultipart(b *testing.B, numShards, numObjects int) { b.StopTimer() - engine := testNewEngine(b, WithShardPoolSize(uint32(numObjects))). + engine := testNewEngine(b). setShardsNum(b, numShards).prepare(b).engine defer func() { require.NoError(b, engine.Close(context.Background())) }() diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index 64288a5118..b348d13a23 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -9,7 +9,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -99,13 +98,13 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { var shRes putToShardRes e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { e.mtx.RLock() - pool, ok := e.shardPools[sh.ID().String()] + _, ok := e.shards[sh.ID().String()] e.mtx.RUnlock() if !ok { // Shard was concurrently removed, skip. return false } - shRes = e.putToShard(ctx, sh, pool, addr, prm.Object, prm.IsIndexedContainer) + shRes = e.putToShard(ctx, sh, addr, prm.Object, prm.IsIndexedContainer) return shRes.status != putToShardUnknown }) switch shRes.status { @@ -122,70 +121,59 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { // putToShard puts object to sh. // Return putToShardStatus and error if it is necessary to propagate an error upper. -func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, pool util.WorkerPool, +func (e *StorageEngine) putToShard(ctx context.Context, sh hashedShard, addr oid.Address, obj *objectSDK.Object, isIndexedContainer bool, ) (res putToShardRes) { - exitCh := make(chan struct{}) + var existPrm shard.ExistsPrm + existPrm.Address = addr - if err := pool.Submit(func() { - defer close(exitCh) - - var existPrm shard.ExistsPrm - existPrm.Address = addr - - exists, err := sh.Exists(ctx, existPrm) - if err != nil { - if shard.IsErrObjectExpired(err) { - // object is already found but - // expired => do nothing with it - res.status = putToShardExists - } else { - e.log.Warn(ctx, logs.EngineCouldNotCheckObjectExistence, - zap.Stringer("shard_id", sh.ID()), - zap.Error(err)) - } - - return // this is not ErrAlreadyRemoved error so we can go to the next shard - } - - if exists.Exists() { + exists, err := sh.Exists(ctx, existPrm) + if err != nil { + if shard.IsErrObjectExpired(err) { + // object is already found but + // expired => do nothing with it res.status = putToShardExists - return + } else { + e.log.Warn(ctx, logs.EngineCouldNotCheckObjectExistence, + zap.Stringer("shard_id", sh.ID()), + zap.Error(err)) } - var putPrm shard.PutPrm - putPrm.SetObject(obj) - putPrm.SetIndexAttributes(isIndexedContainer) - - _, err = sh.Put(ctx, putPrm) - if err != nil { - if errors.Is(err, shard.ErrReadOnlyMode) || errors.Is(err, blobstor.ErrNoPlaceFound) || - errors.Is(err, common.ErrReadOnly) || errors.Is(err, common.ErrNoSpace) { - e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, - zap.Stringer("shard_id", sh.ID()), - zap.Error(err)) - return - } - if client.IsErrObjectAlreadyRemoved(err) { - e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, - zap.Stringer("shard_id", sh.ID()), - zap.Error(err)) - res.status = putToShardRemoved - res.err = err - return - } - - e.reportShardError(ctx, sh, "could not put object to shard", err, zap.Stringer("address", addr)) - return - } - - res.status = putToShardSuccess - }); err != nil { - e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, zap.Error(err)) - close(exitCh) + return // this is not ErrAlreadyRemoved error so we can go to the next shard } - <-exitCh + if exists.Exists() { + res.status = putToShardExists + return + } + + var putPrm shard.PutPrm + putPrm.SetObject(obj) + putPrm.SetIndexAttributes(isIndexedContainer) + + _, err = sh.Put(ctx, putPrm) + if err != nil { + if errors.Is(err, shard.ErrReadOnlyMode) || errors.Is(err, blobstor.ErrNoPlaceFound) || + errors.Is(err, common.ErrReadOnly) || errors.Is(err, common.ErrNoSpace) { + e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, + zap.Stringer("shard_id", sh.ID()), + zap.Error(err)) + return + } + if client.IsErrObjectAlreadyRemoved(err) { + e.log.Warn(ctx, logs.EngineCouldNotPutObjectToShard, + zap.Stringer("shard_id", sh.ID()), + zap.Error(err)) + res.status = putToShardRemoved + res.err = err + return + } + + e.reportShardError(ctx, sh, "could not put object to shard", err, zap.Stringer("address", addr)) + return + } + + res.status = putToShardSuccess return } diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 28f0287bc0..a38c851511 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -17,7 +17,6 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/hrw" "github.com/google/uuid" - "github.com/panjf2000/ants/v2" "go.uber.org/zap" "golang.org/x/sync/errgroup" ) @@ -181,11 +180,6 @@ func (e *StorageEngine) addShard(sh *shard.Shard) error { e.mtx.Lock() defer e.mtx.Unlock() - pool, err := ants.NewPool(int(e.shardPoolSize), ants.WithNonblocking(true)) - if err != nil { - return fmt.Errorf("create pool: %w", err) - } - strID := sh.ID().String() if _, ok := e.shards[strID]; ok { return fmt.Errorf("shard with id %s was already added", strID) @@ -199,8 +193,6 @@ func (e *StorageEngine) addShard(sh *shard.Shard) error { hash: hrw.StringHash(strID), } - e.shardPools[strID] = pool - return nil } @@ -225,12 +217,6 @@ func (e *StorageEngine) removeShards(ctx context.Context, ids ...string) { ss = append(ss, sh) delete(e.shards, id) - pool, ok := e.shardPools[id] - if ok { - pool.Release() - delete(e.shardPools, id) - } - e.log.Info(ctx, logs.EngineShardHasBeenRemoved, zap.String("id", id)) } @@ -429,12 +415,6 @@ func (e *StorageEngine) deleteShards(ctx context.Context, ids []*shard.ID) ([]ha delete(e.shards, idStr) - pool, ok := e.shardPools[idStr] - if ok { - pool.Release() - delete(e.shardPools, idStr) - } - e.log.Info(ctx, logs.EngineShardHasBeenRemoved, zap.String("id", idStr)) } diff --git a/pkg/local_object_storage/engine/shards_test.go b/pkg/local_object_storage/engine/shards_test.go index 0bbc7563c3..3aa9629b05 100644 --- a/pkg/local_object_storage/engine/shards_test.go +++ b/pkg/local_object_storage/engine/shards_test.go @@ -17,7 +17,6 @@ func TestRemoveShard(t *testing.T) { e, ids := te.engine, te.shardIDs defer func() { require.NoError(t, e.Close(context.Background())) }() - require.Equal(t, numOfShards, len(e.shardPools)) require.Equal(t, numOfShards, len(e.shards)) removedNum := numOfShards / 2 @@ -37,7 +36,6 @@ func TestRemoveShard(t *testing.T) { } } - require.Equal(t, numOfShards-removedNum, len(e.shardPools)) require.Equal(t, numOfShards-removedNum, len(e.shards)) for id, removed := range mSh { From 737788b35f173fb9cd2838fb53858d8c8b22ec25 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 12 Mar 2025 09:21:15 +0300 Subject: [PATCH 1237/1413] [#1669] go.mod: Bump frostfs-qos version Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9d0988bcd4..69273fda24 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 - git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3 + git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 diff --git a/go.sum b/go.sum index 3ec679ee70..a8f7216a54 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 h1:Mxw1c/8t96vFIUOffl28lFaHKi413oCBfLMGJmF9cFA= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3 h1:QnAt5b2R6+hQthMOIn5ECfLAlVD8IAE5JRm1NCCOmuE= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250227072915-25102d1e1aa3/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529 h1:CBreXSxGoYJAdZ1QdJPsDs1UCXGF5psinII0lxtohsc= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 h1:svCl6NDAPZ/KuQPjdVKo74RkCIANesxUPM45zQZDhSw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= From bcc84c85a0bdc9095f511ba2d03094723b48c7dd Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 13 Mar 2025 08:57:35 +0300 Subject: [PATCH 1238/1413] [#1671] Replace `interface{}` with `any` gopatch: ``` @@ @@ -interface{} +any ``` Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/engine/evacuate_test.go | 8 ++++---- pkg/morph/client/client.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index ec79232973..bd5222b788 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -404,8 +404,8 @@ func TestEvacuateSingleProcess(t *testing.T) { require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) require.NoError(t, e.shards[ids[1].String()].SetMode(context.Background(), mode.ReadOnly)) - blocker := make(chan interface{}) - running := make(chan interface{}) + blocker := make(chan any) + running := make(chan any) var prm EvacuateShardPrm prm.ShardID = ids[1:2] @@ -446,8 +446,8 @@ func TestEvacuateObjectsAsync(t *testing.T) { require.NoError(t, e.shards[ids[0].String()].SetMode(context.Background(), mode.ReadOnly)) require.NoError(t, e.shards[ids[1].String()].SetMode(context.Background(), mode.ReadOnly)) - blocker := make(chan interface{}) - running := make(chan interface{}) + blocker := make(chan any) + running := make(chan any) var prm EvacuateShardPrm prm.ShardID = ids[1:2] diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 10ded5142a..19349ccd52 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -213,7 +213,7 @@ func (c *Client) Invoke(ctx context.Context, contract util.Uint160, fee fixedn.F // If the remote neo-go node does not support sessions, `unwrap.ErrNoSessionID` is returned. // batchSize is the number of items to prefetch: if the number of items in the iterator is less than batchSize, no session will be created. // The default batchSize is 100, the default limit from neo-go. -func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int, contract util.Uint160, method string, args ...interface{}) error { +func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int, contract util.Uint160, method string, args ...any) error { start := time.Now() success := false defer func() { From d66bffb1919c8b6caa253b84b1f95f38afd639a0 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 13 Mar 2025 09:01:42 +0300 Subject: [PATCH 1239/1413] [#1671] Use max builtin where possible gopatcH: ``` @@ var d, a expression @@ -if d < a { - d = a -} -return d +return max(d, a) @@ var d, a expression @@ -if d <= a { - d = a -} -return d +return max(d, a) ``` Signed-off-by: Evgenii Stratonikov --- .../config/engine/shard/boltdb/boltdb.go | 15 +++------------ .../config/engine/shard/pilorama/config.go | 10 ++-------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go b/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go index a51308b5ba..b564d36f8d 100644 --- a/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go +++ b/cmd/frostfs-node/config/engine/shard/boltdb/boltdb.go @@ -37,10 +37,7 @@ func (x *Config) Perm() fs.FileMode { // Returns 0 if the value is not a positive number. func (x *Config) MaxBatchDelay() time.Duration { d := config.DurationSafe((*config.Config)(x), "max_batch_delay") - if d < 0 { - d = 0 - } - return d + return max(d, 0) } // MaxBatchSize returns the value of "max_batch_size" config parameter. @@ -48,10 +45,7 @@ func (x *Config) MaxBatchDelay() time.Duration { // Returns 0 if the value is not a positive number. func (x *Config) MaxBatchSize() int { s := int(config.IntSafe((*config.Config)(x), "max_batch_size")) - if s < 0 { - s = 0 - } - return s + return max(s, 0) } // NoSync returns the value of "no_sync" config parameter. @@ -66,8 +60,5 @@ func (x *Config) NoSync() bool { // Returns 0 if the value is not a positive number. func (x *Config) PageSize() int { s := int(config.SizeInBytesSafe((*config.Config)(x), "page_size")) - if s < 0 { - s = 0 - } - return s + return max(s, 0) } diff --git a/cmd/frostfs-node/config/engine/shard/pilorama/config.go b/cmd/frostfs-node/config/engine/shard/pilorama/config.go index 28671ca55a..5d4e8f4089 100644 --- a/cmd/frostfs-node/config/engine/shard/pilorama/config.go +++ b/cmd/frostfs-node/config/engine/shard/pilorama/config.go @@ -52,10 +52,7 @@ func (x *Config) NoSync() bool { // Returns 0 if the value is not a positive number. func (x *Config) MaxBatchDelay() time.Duration { d := config.DurationSafe((*config.Config)(x), "max_batch_delay") - if d <= 0 { - d = 0 - } - return d + return max(d, 0) } // MaxBatchSize returns the value of "max_batch_size" config parameter. @@ -63,8 +60,5 @@ func (x *Config) MaxBatchDelay() time.Duration { // Returns 0 if the value is not a positive number. func (x *Config) MaxBatchSize() int { s := int(config.IntSafe((*config.Config)(x), "max_batch_size")) - if s <= 0 { - s = 0 - } - return s + return max(s, 0) } From 40536d8a0658bf374120007b13bce712422f7ba1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 13 Mar 2025 09:09:14 +0300 Subject: [PATCH 1240/1413] [#1671] Use `fmt.Appendf` where warranted Fix gopls warnings: ``` cmd/frostfs-adm/internal/modules/morph/config/config.go:68:20-64: Replace []byte(fmt.Sprintf...) with fmt.Appendf ```` gopatch: ``` @@ var f expression @@ -[]byte(fmt.Sprintf(f, ...)) +fmt.Appendf(nil, f, ...) ``` Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/config/config.go | 6 +++--- .../internal/modules/morph/contract/dump_hashes.go | 4 ++-- cmd/frostfs-adm/internal/modules/morph/policy/policy.go | 6 +++--- cmd/frostfs-cli/modules/control/list_targets.go | 2 +- pkg/local_object_storage/metabase/reset_test.go | 2 +- scripts/populate-metabase/internal/populate.go | 7 ++----- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index 65ccc9f9f9..f64cb4817b 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -65,14 +65,14 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { nbuf := make([]byte, 8) copy(nbuf[:], v) n := binary.LittleEndian.Uint64(nbuf) - _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%d (int)\n", k, n))) + _, _ = tw.Write(fmt.Appendf(nil, "%s:\t%d (int)\n", k, n)) case netmap.HomomorphicHashingDisabledKey, netmap.MaintenanceModeAllowedConfig: if len(v) == 0 || len(v) > 1 { return helper.InvalidConfigValueErr(k) } - _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%t (bool)\n", k, v[0] == 1))) + _, _ = tw.Write(fmt.Appendf(nil, "%s:\t%t (bool)\n", k, v[0] == 1)) default: - _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%s (hex)\n", k, hex.EncodeToString(v)))) + _, _ = tw.Write(fmt.Appendf(nil, "%s:\t%s (hex)\n", k, hex.EncodeToString(v))) } } diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index 437e2480dd..fb7e4ff624 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -219,8 +219,8 @@ func printContractInfo(cmd *cobra.Command, infos []contractDumpInfo) { if info.version == "" { info.version = "unknown" } - _, _ = tw.Write([]byte(fmt.Sprintf("%s\t(%s):\t%s\n", - info.name, info.version, info.hash.StringLE()))) + _, _ = tw.Write(fmt.Appendf(nil, "%s\t(%s):\t%s\n", + info.name, info.version, info.hash.StringLE())) } _ = tw.Flush() diff --git a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go index 686a244f0e..f2932e87cb 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy/policy.go @@ -80,9 +80,9 @@ func dumpPolicyCmd(cmd *cobra.Command, _ []string) error { buf := bytes.NewBuffer(nil) tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) - _, _ = tw.Write([]byte(fmt.Sprintf("Execution Fee Factor:\t%d (int)\n", execFee))) - _, _ = tw.Write([]byte(fmt.Sprintf("Fee Per Byte:\t%d (int)\n", feePerByte))) - _, _ = tw.Write([]byte(fmt.Sprintf("Storage Price:\t%d (int)\n", storagePrice))) + _, _ = tw.Write(fmt.Appendf(nil, "Execution Fee Factor:\t%d (int)\n", execFee)) + _, _ = tw.Write(fmt.Appendf(nil, "Fee Per Byte:\t%d (int)\n", feePerByte)) + _, _ = tw.Write(fmt.Appendf(nil, "Storage Price:\t%d (int)\n", storagePrice)) _ = tw.Flush() cmd.Print(buf.String()) diff --git a/cmd/frostfs-cli/modules/control/list_targets.go b/cmd/frostfs-cli/modules/control/list_targets.go index 8bd2dc9cde..3142d02e7b 100644 --- a/cmd/frostfs-cli/modules/control/list_targets.go +++ b/cmd/frostfs-cli/modules/control/list_targets.go @@ -62,7 +62,7 @@ func listTargets(cmd *cobra.Command, _ []string) { tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) _, _ = tw.Write([]byte("#\tName\tType\n")) for i, t := range targets { - _, _ = tw.Write([]byte(fmt.Sprintf("%s\t%s\t%s\n", strconv.Itoa(i), t.GetName(), t.GetType()))) + _, _ = tw.Write(fmt.Appendf(nil, "%s\t%s\t%s\n", strconv.Itoa(i), t.GetName(), t.GetType())) } _ = tw.Flush() cmd.Print(buf.String()) diff --git a/pkg/local_object_storage/metabase/reset_test.go b/pkg/local_object_storage/metabase/reset_test.go index 45faecc13f..5f0956f0bd 100644 --- a/pkg/local_object_storage/metabase/reset_test.go +++ b/pkg/local_object_storage/metabase/reset_test.go @@ -37,7 +37,7 @@ func TestResetDropsContainerBuckets(t *testing.T) { for idx := range 100 { var putPrm PutPrm putPrm.SetObject(testutil.GenerateObject()) - putPrm.SetStorageID([]byte(fmt.Sprintf("0/%d", idx))) + putPrm.SetStorageID(fmt.Appendf(nil, "0/%d", idx)) _, err := db.Put(context.Background(), putPrm) require.NoError(t, err) } diff --git a/scripts/populate-metabase/internal/populate.go b/scripts/populate-metabase/internal/populate.go index 4da23a295d..fafe61eaa7 100644 --- a/scripts/populate-metabase/internal/populate.go +++ b/scripts/populate-metabase/internal/populate.go @@ -31,13 +31,10 @@ func PopulateWithObjects( for range count { obj := factory() - - id := []byte(fmt.Sprintf( - "%c/%c/%c", + id := fmt.Appendf(nil, "%c/%c/%c", digits[rand.Int()%len(digits)], digits[rand.Int()%len(digits)], - digits[rand.Int()%len(digits)], - )) + digits[rand.Int()%len(digits)]) prm := meta.PutPrm{} prm.SetObject(obj) From 155d3ddb6e9d8400bdfc43cd2606ac577b6b8945 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 13 Mar 2025 09:14:14 +0300 Subject: [PATCH 1241/1413] [#1671] Use `min` builtin where possible Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/pilorama/forest.go | 5 +---- pkg/morph/client/client.go | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index 92183716c3..ef284a7272 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -205,10 +205,7 @@ func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeI r := mergeNodeInfos(res) for i := range r { if start == nil || string(findAttr(r[i].Meta, AttributeFilename)) > *start { - finish := i + count - if len(res) < finish { - finish = len(res) - } + finish := min(len(res), i+count) last := string(findAttr(r[finish-1].Meta, AttributeFilename)) return r[i:finish], &last, nil } diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 19349ccd52..e63d926e0d 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -262,10 +262,7 @@ func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int }() // Batch size for TraverseIterator() can restricted on the server-side. - traverseBatchSize := batchSize - if invoker.DefaultIteratorResultItems < traverseBatchSize { - traverseBatchSize = invoker.DefaultIteratorResultItems - } + traverseBatchSize := min(batchSize, invoker.DefaultIteratorResultItems) for { items, err := c.rpcActor.TraverseIterator(sid, &r, traverseBatchSize) if err != nil { From 460e5cbccf8fa62134ff8bbc73f886ee5ceaeb87 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 13 Mar 2025 09:24:44 +0300 Subject: [PATCH 1242/1413] [#1671] Use `slices.Delete()` where possible gopatch is missing for this one, because https://github.com/uber-go/gopatch/issues/179 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-lens/internal/tui/input.go | 4 +++- .../blobstor/internal/blobstortest/iterate.go | 3 ++- pkg/local_object_storage/metabase/lock.go | 3 ++- pkg/services/object/delete/exec.go | 3 ++- pkg/services/object/search/util.go | 3 ++- pkg/services/object/util/placement.go | 3 ++- pkg/services/object_manager/placement/traverser.go | 4 ++-- 7 files changed, 15 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-lens/internal/tui/input.go b/cmd/frostfs-lens/internal/tui/input.go index 4fdf97119c..90729c1190 100644 --- a/cmd/frostfs-lens/internal/tui/input.go +++ b/cmd/frostfs-lens/internal/tui/input.go @@ -1,6 +1,8 @@ package tui import ( + "slices" + "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) @@ -26,7 +28,7 @@ func (f *InputFieldWithHistory) AddToHistory(s string) { // Used history data for search prompt, so just make that data recent. if f.historyPointer != len(f.history) && s == f.history[f.historyPointer] { - f.history = append(f.history[:f.historyPointer], f.history[f.historyPointer+1:]...) + f.history = slices.Delete(f.history, f.historyPointer, f.historyPointer+1) f.history = append(f.history, s) } diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index 36b2c33f88..c11d0888b5 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -3,6 +3,7 @@ package blobstortest import ( "context" "errors" + "slices" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" @@ -26,7 +27,7 @@ func TestIterate(t *testing.T, cons Constructor, minSize, maxSize uint64) { _, err := s.Delete(context.Background(), delPrm) require.NoError(t, err) - objects = append(objects[:delID], objects[delID+1:]...) + objects = slices.Delete(objects, delID, delID+1) runTestNormalHandler(t, s, objects) diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index b930a01413..aa14784231 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "fmt" + "slices" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" @@ -250,7 +251,7 @@ func freePotentialLocks(tx *bbolt.Tx, idCnr cid.ID, locker oid.ID) ([]oid.Addres unlockedObjects = append(unlockedObjects, addr) } else { // exclude locker - keyLockers = append(keyLockers[:i], keyLockers[i+1:]...) + keyLockers = slices.Delete(keyLockers, i, i+1) v, err = encodeList(keyLockers) if err != nil { diff --git a/pkg/services/object/delete/exec.go b/pkg/services/object/delete/exec.go index 36a17bde2c..a99ba3586d 100644 --- a/pkg/services/object/delete/exec.go +++ b/pkg/services/object/delete/exec.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "slices" "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" @@ -182,7 +183,7 @@ func (exec *execCtx) addMembers(incoming []oid.ID) { for i := range members { for j := 0; j < len(incoming); j++ { // don't use range, slice mutates in body if members[i].Equals(incoming[j]) { - incoming = append(incoming[:j], incoming[j+1:]...) + incoming = slices.Delete(incoming, j, j+1) j-- } } diff --git a/pkg/services/object/search/util.go b/pkg/services/object/search/util.go index fed168187a..0be5345b9a 100644 --- a/pkg/services/object/search/util.go +++ b/pkg/services/object/search/util.go @@ -2,6 +2,7 @@ package searchsvc import ( "context" + "slices" "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" @@ -53,7 +54,7 @@ func (w *uniqueIDWriter) WriteIDs(list []oid.ID) error { } // exclude processed address - list = append(list[:i], list[i+1:]...) + list = slices.Delete(list, i, i+1) i-- } diff --git a/pkg/services/object/util/placement.go b/pkg/services/object/util/placement.go index 195944f92a..f74b0aab9a 100644 --- a/pkg/services/object/util/placement.go +++ b/pkg/services/object/util/placement.go @@ -3,6 +3,7 @@ package util import ( "context" "fmt" + "slices" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" @@ -93,7 +94,7 @@ func (p *remotePlacement) BuildPlacement(ctx context.Context, cnr cid.ID, obj *o } if p.netmapKeys.IsLocalKey(vs[i][j].PublicKey()) { - vs[i] = append(vs[i][:j], vs[i][j+1:]...) + vs[i] = slices.Delete(vs[i], j, j+1) j-- } } diff --git a/pkg/services/object_manager/placement/traverser.go b/pkg/services/object_manager/placement/traverser.go index efa4a5b06e..a3f9af959b 100644 --- a/pkg/services/object_manager/placement/traverser.go +++ b/pkg/services/object_manager/placement/traverser.go @@ -288,8 +288,8 @@ func (t *Traverser) Next() []Node { func (t *Traverser) skipEmptyVectors() { for i := 0; i < len(t.vectors); i++ { // don't use range, slice changes in body if len(t.vectors[i]) == 0 && t.rem[i] <= 0 || t.rem[0] == 0 { - t.vectors = append(t.vectors[:i], t.vectors[i+1:]...) - t.rem = append(t.rem[:i], t.rem[i+1:]...) + t.vectors = slices.Delete(t.vectors, i, i+1) + t.rem = slices.Delete(t.rem, i, i+1) i-- } else { break From ecb6b0793c877ae9a6d1b399a3c364323f77254d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 13 Mar 2025 09:34:59 +0300 Subject: [PATCH 1243/1413] [#1671] Use `slices.ContainsFunc()` where possible Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/netmap.go | 8 +++----- pkg/network/group.go | 7 +++---- pkg/services/object/acl/v2/util_test.go | 9 ++------- pkg/services/policer/policer_test.go | 7 +++---- pkg/services/tree/service.go | 13 +++++-------- 5 files changed, 16 insertions(+), 28 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go index fb8f037838..20abaff0a5 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/netmap.go @@ -3,6 +3,7 @@ package helper import ( "errors" "fmt" + "slices" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" @@ -118,11 +119,8 @@ func MergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error { return err } for k, v := range m { - for _, key := range NetmapConfigKeys { - if k == key { - md[k] = v - break - } + if slices.Contains(NetmapConfigKeys, k) { + md[k] = v } } return nil diff --git a/pkg/network/group.go b/pkg/network/group.go index 9843b14d4d..5a71e530ed 100644 --- a/pkg/network/group.go +++ b/pkg/network/group.go @@ -3,6 +3,7 @@ package network import ( "errors" "fmt" + "slices" "sort" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -164,10 +165,8 @@ func WriteToNodeInfo(g AddressGroup, ni *netmap.NodeInfo) { // at least one common address. func (x AddressGroup) Intersects(x2 AddressGroup) bool { for i := range x { - for j := range x2 { - if x[i].equal(x2[j]) { - return true - } + if slices.ContainsFunc(x2, x[i].equal) { + return true } } diff --git a/pkg/services/object/acl/v2/util_test.go b/pkg/services/object/acl/v2/util_test.go index 4b19cecfef..40fce88772 100644 --- a/pkg/services/object/acl/v2/util_test.go +++ b/pkg/services/object/acl/v2/util_test.go @@ -4,6 +4,7 @@ import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" + "slices" "testing" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" @@ -91,13 +92,7 @@ func TestIsVerbCompatible(t *testing.T) { for op, list := range table { for _, verb := range verbs { - var contains bool - for _, v := range list { - if v == verb { - contains = true - break - } - } + contains := slices.Contains(list, verb) tok.ForVerb(verb) diff --git a/pkg/services/policer/policer_test.go b/pkg/services/policer/policer_test.go index cef4c36d94..049c337531 100644 --- a/pkg/services/policer/policer_test.go +++ b/pkg/services/policer/policer_test.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "errors" + "slices" "sort" "testing" "time" @@ -226,10 +227,8 @@ func TestProcessObject(t *testing.T) { return nil, err } } - for _, i := range ti.objHolders { - if index == i { - return nil, nil - } + if slices.Contains(ti.objHolders, index) { + return nil, nil } return nil, new(apistatus.ObjectNotFound) } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index f9b7395e70..cd89d6a286 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -345,14 +345,11 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) } else { var metaValue []KeyValue for _, kv := range m.Items { - for _, attr := range b.GetAttributes() { - if kv.Key == attr { - metaValue = append(metaValue, KeyValue{ - Key: kv.Key, - Value: kv.Value, - }) - break - } + if slices.Contains(b.GetAttributes(), kv.Key) { + metaValue = append(metaValue, KeyValue{ + Key: kv.Key, + Value: kv.Value, + }) } } x.Meta = metaValue From 997759994a55cc943804d6a16f29a4703f8435a3 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 13 Mar 2025 12:01:57 +0300 Subject: [PATCH 1244/1413] [#1676] golangci: Enable gci linter Signed-off-by: Alexander Chuprov --- .golangci.yml | 6 ++++++ cmd/frostfs-adm/internal/modules/storagecfg/root.go | 1 - cmd/frostfs-cli/modules/control/locate.go | 1 - pkg/services/control/server/list_shards_for_object.go | 1 - 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index d83f36de8c..f21a46248e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -22,6 +22,11 @@ linters-settings: # 'default' case is present, even if all enum members aren't listed in the # switch default-signifies-exhaustive: true + gci: + sections: + - standard + - default + custom-order: true govet: # report about shadowed variables check-shadowing: false @@ -72,6 +77,7 @@ linters: - durationcheck - exhaustive - copyloopvar + - gci - gofmt - goimports - misspell diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/root.go b/cmd/frostfs-adm/internal/modules/storagecfg/root.go index 8acbc45795..a5adea0da7 100644 --- a/cmd/frostfs-adm/internal/modules/storagecfg/root.go +++ b/cmd/frostfs-adm/internal/modules/storagecfg/root.go @@ -31,7 +31,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/wallet" - "github.com/spf13/cobra" ) diff --git a/cmd/frostfs-cli/modules/control/locate.go b/cmd/frostfs-cli/modules/control/locate.go index d10e2a8964..4cb4be539f 100644 --- a/cmd/frostfs-cli/modules/control/locate.go +++ b/cmd/frostfs-cli/modules/control/locate.go @@ -11,7 +11,6 @@ import ( rawclient "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "github.com/mr-tron/base58" "github.com/spf13/cobra" ) diff --git a/pkg/services/control/server/list_shards_for_object.go b/pkg/services/control/server/list_shards_for_object.go index 84469772f8..39565ed50a 100644 --- a/pkg/services/control/server/list_shards_for_object.go +++ b/pkg/services/control/server/list_shards_for_object.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/server/ctrlmessage" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "google.golang.org/grpc/codes" From ff4e9b6ae119ca234cf035c00d5c23fc4d494c5a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 13 Mar 2025 10:18:26 +0300 Subject: [PATCH 1245/1413] [#1673] logger: Drop unused fields Signed-off-by: Dmitrii Stepanov --- pkg/util/logger/logger.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index 19d3f1ed10..a0b2728c97 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -147,8 +147,6 @@ func newJournaldLogger(prm *Prm) (*Logger, error) { lvl := zap.NewAtomicLevelAt(prm.level) c := zap.NewProductionConfig() - c.Level = lvl - c.Encoding = "console" if prm.SamplingHook != nil { c.Sampling.Hook = prm.SamplingHook } From 7893d763d1b1d5eeeb62d8a4beb2175acaa13b65 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 13 Mar 2025 10:37:29 +0300 Subject: [PATCH 1246/1413] [#1673] logger: Add sampling for journald logger Signed-off-by: Dmitrii Stepanov --- pkg/util/logger/logger.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index a0b2728c97..2eb5e55389 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -2,6 +2,7 @@ package logger import ( "fmt" + "time" "git.frostfs.info/TrueCloudLab/zapjournald" "github.com/ssgreg/journald" @@ -166,7 +167,18 @@ func newJournaldLogger(prm *Prm) (*Logger, error) { zapjournald.SyslogPid(), }) - lZap := zap.New(coreWithContext, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), zap.AddCallerSkip(1)) + var samplerOpts []zapcore.SamplerOption + if c.Sampling.Hook != nil { + samplerOpts = append(samplerOpts, zapcore.SamplerHook(c.Sampling.Hook)) + } + samplingCore := zapcore.NewSamplerWithOptions( + coreWithContext, + time.Second, + c.Sampling.Initial, + c.Sampling.Thereafter, + samplerOpts..., + ) + lZap := zap.New(samplingCore, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), zap.AddCallerSkip(1)) l := &Logger{z: lZap, lvl: lvl} prm._log = l From 07a660fbc440dbd3974250608506e39c093bf6cc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 13 Mar 2025 18:01:27 +0300 Subject: [PATCH 1247/1413] [#1677] writecache: Add QoS limiter usage Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 1 + internal/logs/logs.go | 1 + pkg/local_object_storage/writecache/cache.go | 2 ++ pkg/local_object_storage/writecache/flush.go | 15 ++++++++++++++- pkg/local_object_storage/writecache/options.go | 9 +++++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index e2fe231358..2531e91739 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -930,6 +930,7 @@ func (c *cfg) getWriteCacheOpts(shCfg shardCfg) []writecache.Option { writecache.WithMaxCacheCount(wcRead.countLimit), writecache.WithNoSync(wcRead.noSync), writecache.WithLogger(c.log), + writecache.WithQoSLimiter(shCfg.limiter), ) } return writeCacheOpts diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 6115cdf90d..3503c922e1 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -514,4 +514,5 @@ const ( NotSupportedIncomingIOTagReplacedWithClient = "incoming IO tag is not supported, replaced with `client`" FailedToGetNetmapToAdjustIOTag = "failed to get netmap to adjust IO tag, replaced with `client`" FailedToValidateIncomingIOTag = "failed to validate incoming IO tag, replaced with `client`" + WriteCacheFailedToAcquireRPSQuota = "writecache failed to acquire RPS quota to flush object" ) diff --git a/pkg/local_object_storage/writecache/cache.go b/pkg/local_object_storage/writecache/cache.go index b99d73d3a8..ee709ea732 100644 --- a/pkg/local_object_storage/writecache/cache.go +++ b/pkg/local_object_storage/writecache/cache.go @@ -6,6 +6,7 @@ import ( "sync" "sync/atomic" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -61,6 +62,7 @@ func New(opts ...Option) Cache { maxCacheSize: defaultMaxCacheSize, metrics: DefaultMetrics(), flushSizeLimit: defaultFlushWorkersCount * defaultMaxObjectSize, + qosLimiter: qos.NewNoopLimiter(), }, } diff --git a/pkg/local_object_storage/writecache/flush.go b/pkg/local_object_storage/writecache/flush.go index 2d07d8b327..893d27ba29 100644 --- a/pkg/local_object_storage/writecache/flush.go +++ b/pkg/local_object_storage/writecache/flush.go @@ -67,7 +67,13 @@ func (c *cache) pushToFlushQueue(ctx context.Context, fl *flushLimiter) { continue } - err := c.fsTree.IterateInfo(ctx, func(oi fstree.ObjectInfo) error { + release, err := c.qosLimiter.ReadRequest(ctx) + if err != nil { + c.log.Warn(ctx, logs.WriteCacheFailedToAcquireRPSQuota, zap.String("operation", "fstree.IterateInfo"), zap.Error(err)) + c.modeMtx.RUnlock() + continue + } + err = c.fsTree.IterateInfo(ctx, func(oi fstree.ObjectInfo) error { if err := fl.acquire(oi.DataSize); err != nil { return err } @@ -82,6 +88,7 @@ func (c *cache) pushToFlushQueue(ctx context.Context, fl *flushLimiter) { return ctx.Err() } }) + release() if err != nil { c.log.Warn(ctx, logs.BlobstorErrorOccurredDuringTheIteration, zap.Error(err)) } @@ -113,6 +120,12 @@ func (c *cache) workerFlush(ctx context.Context, fl *flushLimiter) { func (c *cache) flushIfAnObjectExistsWorker(ctx context.Context, objInfo objectInfo, fl *flushLimiter) { defer fl.release(objInfo.size) + release, err := c.qosLimiter.WriteRequest(ctx) + if err != nil { + c.log.Warn(ctx, logs.WriteCacheFailedToAcquireRPSQuota, zap.String("operation", "fstree.Get"), zap.Error(err)) + return + } + defer release() res, err := c.fsTree.Get(ctx, common.GetPrm{ Address: objInfo.addr, }) diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index f2957fe980..dbbe66c19e 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -3,6 +3,7 @@ package writecache import ( "context" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "go.uber.org/zap" ) @@ -38,6 +39,8 @@ type options struct { disableBackgroundFlush bool // flushSizeLimit is total size of flushing objects. flushSizeLimit uint64 + // qosLimiter used to limit flush RPS. + qosLimiter qos.Limiter } // WithLogger sets logger. @@ -136,3 +139,9 @@ func WithFlushSizeLimit(v uint64) Option { o.flushSizeLimit = v } } + +func WithQoSLimiter(l qos.Limiter) Option { + return func(o *options) { + o.qosLimiter = l + } +} From fde2649e60ff27c4e5aa66cbd163a14bf585398e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 14 Mar 2025 12:03:42 +0300 Subject: [PATCH 1248/1413] [#1678] adm: Fix frostfs-adm morph list-subjects & list-group-subjects `include-names` for `list-subjects` returns error `invalid response subject struct` because `ListSubjects` returns only subject addresses (see frostfs-contract). Replace `include-names` with `extended` as now all subject info printed. Signed-off-by: Dmitrii Stepanov --- .../modules/morph/frostfsid/frostfsid.go | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 4fbd0bfe17..8ae606f1a3 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -34,7 +34,7 @@ const ( subjectNameFlag = "subject-name" subjectKeyFlag = "subject-key" subjectAddressFlag = "subject-address" - includeNamesFlag = "include-names" + extendedFlag = "extended" groupNameFlag = "group-name" groupIDFlag = "group-id" @@ -209,7 +209,7 @@ func initFrostfsIDListSubjectsCmd() { Cmd.AddCommand(frostfsidListSubjectsCmd) frostfsidListSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace to list subjects") - frostfsidListSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") + frostfsidListSubjectsCmd.Flags().Bool(extendedFlag, false, "Whether include subject info (require additional requests)") } func initFrostfsIDCreateGroupCmd() { @@ -256,7 +256,7 @@ func initFrostfsIDListGroupSubjectsCmd() { frostfsidListGroupSubjectsCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) frostfsidListGroupSubjectsCmd.Flags().String(namespaceFlag, "", "Namespace name") frostfsidListGroupSubjectsCmd.Flags().Int64(groupIDFlag, 0, "Group id") - frostfsidListGroupSubjectsCmd.Flags().Bool(includeNamesFlag, false, "Whether include subject name (require additional requests)") + frostfsidListGroupSubjectsCmd.Flags().Bool(extendedFlag, false, "Whether include subject info (require additional requests)") } func initFrostfsIDSetKVCmd() { @@ -336,7 +336,7 @@ func frostfsidDeleteSubject(cmd *cobra.Command, _ []string) { } func frostfsidListSubjects(cmd *cobra.Command, _ []string) { - includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) + extended, _ := cmd.Flags().GetBool(extendedFlag) ns := getFrostfsIDNamespace(cmd) inv, _, hash := initInvoker(cmd) reader := frostfsidrpclient.NewReader(inv, hash) @@ -349,21 +349,19 @@ func frostfsidListSubjects(cmd *cobra.Command, _ []string) { sort.Slice(subAddresses, func(i, j int) bool { return subAddresses[i].Less(subAddresses[j]) }) for _, addr := range subAddresses { - if !includeNames { + if !extended { cmd.Println(address.Uint160ToString(addr)) continue } - sessionID, it, err := reader.ListSubjects() + items, err := reader.GetSubject(addr) commonCmd.ExitOnErr(cmd, "can't get subject: %w", err) - items, err := readIterator(inv, &it, sessionID) - commonCmd.ExitOnErr(cmd, "can't read iterator: %w", err) - subj, err := frostfsidclient.ParseSubject(items) commonCmd.ExitOnErr(cmd, "can't parse subject: %w", err) - cmd.Printf("%s (%s)\n", address.Uint160ToString(addr), subj.Name) + printSubjectInfo(cmd, addr, subj) + cmd.Println() } } @@ -483,7 +481,7 @@ func frostfsidDeleteKV(cmd *cobra.Command, _ []string) { func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { ns := getFrostfsIDNamespace(cmd) groupID := getFrostfsIDGroupID(cmd) - includeNames, _ := cmd.Flags().GetBool(includeNamesFlag) + extended, _ := cmd.Flags().GetBool(extendedFlag) inv, cs, hash := initInvoker(cmd) _, err := helper.NNSResolveHash(inv, cs.Hash, helper.DomainOf(constants.FrostfsIDContract)) commonCmd.ExitOnErr(cmd, "can't get netmap contract hash: %w", err) @@ -501,7 +499,7 @@ func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { sort.Slice(subjects, func(i, j int) bool { return subjects[i].Less(subjects[j]) }) for _, subjAddr := range subjects { - if !includeNames { + if !extended { cmd.Println(address.Uint160ToString(subjAddr)) continue } @@ -510,7 +508,8 @@ func frostfsidListGroupSubjects(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "can't get subject: %w", err) subj, err := frostfsidclient.ParseSubject(items) commonCmd.ExitOnErr(cmd, "can't parse subject: %w", err) - cmd.Printf("%s (%s)\n", address.Uint160ToString(subjAddr), subj.Name) + printSubjectInfo(cmd, subjAddr, subj) + cmd.Println() } } @@ -600,3 +599,30 @@ func initInvoker(cmd *cobra.Command) (*invoker.Invoker, *state.Contract, util.Ui return inv, cs, nmHash } + +func printSubjectInfo(cmd *cobra.Command, addr util.Uint160, subj *frostfsidclient.Subject) { + cmd.Printf("Address: %s\n", address.Uint160ToString(addr)) + pk := "" + if subj.PrimaryKey != nil { + pk = subj.PrimaryKey.String() + } + cmd.Printf("Primary key: %s\n", pk) + cmd.Printf("Name: %s\n", subj.Name) + cmd.Printf("Namespace: %s\n", subj.Namespace) + if len(subj.AdditionalKeys) > 0 { + cmd.Printf("Additional keys:\n") + for _, key := range subj.AdditionalKeys { + k := "" + if key != nil { + k = key.String() + } + cmd.Printf("- %s\n", k) + } + } + if len(subj.KV) > 0 { + cmd.Printf("KV:\n") + for k, v := range subj.KV { + cmd.Printf("- %s: %s\n", k, v) + } + } +} From ef6ac751dfa849e3c32171890229b5fbbf979b7a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 14 Mar 2025 16:32:30 +0300 Subject: [PATCH 1249/1413] [#1671] Update gopls to v0.17.1 Signed-off-by: Evgenii Stratonikov --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 497dce1156..538912cc12 100755 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ GOFUMPT_VERSION ?= v0.7.0 GOFUMPT_DIR ?= $(abspath $(BIN))/gofumpt GOFUMPT_VERSION_DIR ?= $(GOFUMPT_DIR)/$(GOFUMPT_VERSION) -GOPLS_VERSION ?= v0.15.1 +GOPLS_VERSION ?= v0.17.1 GOPLS_DIR ?= $(abspath $(BIN))/gopls GOPLS_VERSION_DIR ?= $(GOPLS_DIR)/$(GOPLS_VERSION) GOPLS_TEMP_FILE := $(shell mktemp) From 91c7b39232fb23ad5e46975b7a04da57214f4de0 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 14 Mar 2025 16:34:34 +0300 Subject: [PATCH 1250/1413] [#1680] go.mod: Bump go version to 1.23 Change-Id: I77f908924f675e676f0db6a57204d7c1e0df219a Signed-off-by: Evgenii Stratonikov --- .forgejo/workflows/build.yml | 2 +- .forgejo/workflows/dco.yml | 2 +- .forgejo/workflows/pre-commit.yml | 2 +- .forgejo/workflows/tests.yml | 10 +++++----- .forgejo/workflows/vulncheck.yml | 2 +- Makefile | 2 +- go.mod | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 9129d136ed..d568b96076 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.22', '1.23' ] + go_versions: [ '1.23', '1.24' ] steps: - uses: actions/checkout@v3 diff --git a/.forgejo/workflows/dco.yml b/.forgejo/workflows/dco.yml index 7c5af8410b..190d7764a8 100644 --- a/.forgejo/workflows/dco.yml +++ b/.forgejo/workflows/dco.yml @@ -13,7 +13,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.24' - name: Run commit format checker uses: https://git.frostfs.info/TrueCloudLab/dco-go@v3 diff --git a/.forgejo/workflows/pre-commit.yml b/.forgejo/workflows/pre-commit.yml index b27e7a39a8..c2e293175e 100644 --- a/.forgejo/workflows/pre-commit.yml +++ b/.forgejo/workflows/pre-commit.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.23 + go-version: 1.24 - name: Set up Python run: | apt update diff --git a/.forgejo/workflows/tests.yml b/.forgejo/workflows/tests.yml index 4f1bebe61f..f3f5432cee 100644 --- a/.forgejo/workflows/tests.yml +++ b/.forgejo/workflows/tests.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Install linters @@ -30,7 +30,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go_versions: [ '1.22', '1.23' ] + go_versions: [ '1.23', '1.24' ] fail-fast: false steps: - uses: actions/checkout@v3 @@ -53,7 +53,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.22' + go-version: '1.24' cache: true - name: Run tests @@ -68,7 +68,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Install staticcheck @@ -104,7 +104,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '1.23' + go-version: '1.24' cache: true - name: Install gofumpt diff --git a/.forgejo/workflows/vulncheck.yml b/.forgejo/workflows/vulncheck.yml index 140434dfc1..bc94792d81 100644 --- a/.forgejo/workflows/vulncheck.yml +++ b/.forgejo/workflows/vulncheck.yml @@ -18,7 +18,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: '1.23' + go-version: '1.24' check-latest: true - name: Install govulncheck diff --git a/Makefile b/Makefile index 538912cc12..fd2ee3b6fd 100755 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" -GO_VERSION ?= 1.22 +GO_VERSION ?= 1.23 LINT_VERSION ?= 1.62.2 TRUECLOUDLAB_LINT_VERSION ?= 0.0.8 PROTOC_VERSION ?= 25.0 diff --git a/go.mod b/go.mod index 69273fda24..eeaca1645b 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.frostfs.info/TrueCloudLab/frostfs-node -go 1.22 +go 1.23 require ( code.gitea.io/sdk/gitea v0.17.1 From 54ef71a92ffdcdaebe3fb1685d548170c4a11006 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 14 Mar 2025 16:39:19 +0300 Subject: [PATCH 1251/1413] [#1680] Update staticcheck to 2025.1.1 Change-Id: Ie851e714afebf171c4d42d4c49b42379c2665113 Signed-off-by: Evgenii Stratonikov --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fd2ee3b6fd..cd80fc72ef 100755 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ PROTOC_OS_VERSION=osx-x86_64 ifeq ($(shell uname), Linux) PROTOC_OS_VERSION=linux-x86_64 endif -STATICCHECK_VERSION ?= 2024.1.1 +STATICCHECK_VERSION ?= 2025.1.1 ARCH = amd64 BIN = bin From fc743cc5373c7ccce331c2c84fb53d7dd41e4d29 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 18 Mar 2025 10:56:30 +0300 Subject: [PATCH 1252/1413] [#1684] cli: Correct description of control shards writecache seal Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/modules/control/writecache.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/modules/control/writecache.go b/cmd/frostfs-cli/modules/control/writecache.go index 80e4a0c87c..d0c9a641b6 100644 --- a/cmd/frostfs-cli/modules/control/writecache.go +++ b/cmd/frostfs-cli/modules/control/writecache.go @@ -24,7 +24,7 @@ var writecacheShardCmd = &cobra.Command{ var sealWritecacheShardCmd = &cobra.Command{ Use: "seal", Short: "Flush objects from write-cache and move write-cache to degraded read only mode.", - Long: "Flush all the objects from the write-cache to the main storage and move the write-cache to the degraded read only mode: write-cache will be empty and no objects will be put in it.", + Long: "Flush all the objects from the write-cache to the main storage and move the write-cache to the 'CLOSED' mode: write-cache will be empty and no objects will be put in it.", Run: sealWritecache, } From a7319bc979669dde3a67762220fdbd96077a3f94 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 18 Mar 2025 09:26:34 +0300 Subject: [PATCH 1253/1413] [#1683] metabase/test: Report allocs in benchmarkSelect() Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/select_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/local_object_storage/metabase/select_test.go b/pkg/local_object_storage/metabase/select_test.go index 5cc9983117..ce2156d2e7 100644 --- a/pkg/local_object_storage/metabase/select_test.go +++ b/pkg/local_object_storage/metabase/select_test.go @@ -1216,6 +1216,8 @@ func TestExpiredObjects(t *testing.T) { } func benchmarkSelect(b *testing.B, db *meta.DB, cid cidSDK.ID, fs objectSDK.SearchFilters, expected int) { + b.ReportAllocs() + var prm meta.SelectPrm prm.SetContainerID(cid) prm.SetFilters(fs) From a405fb1f39d616e37fd6d0de35c2e68d6cd3b6b8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 18 Mar 2025 09:34:47 +0300 Subject: [PATCH 1254/1413] [#1683] metabase: Check object status once in Select() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit objectStatus() is called twice for the same object: First, in selectObject() to filter removed objects. Then, again, in getObjectForSlowFilters() via db.get(). The second call will return the same result, so remove useless branch. ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ old │ status │ │ sec/op │ sec/op vs base │ Select/string_equal-8 5.022m ± 7% 3.968m ± 8% -20.98% (p=0.000 n=10) Select/string_not_equal-8 4.953m ± 9% 3.990m ± 10% -19.44% (p=0.000 n=10) Select/common_prefix-8 4.962m ± 8% 3.971m ± 9% -19.98% (p=0.000 n=10) Select/unknown-8 5.246m ± 9% 3.548m ± 5% -32.37% (p=0.000 n=10) geomean 5.045m 3.865m -23.39% │ old │ status │ │ B/op │ B/op vs base │ Select/string_equal-8 2.685Mi ± 0% 2.250Mi ± 0% -16.20% (p=0.000 n=10) Select/string_not_equal-8 2.685Mi ± 0% 2.250Mi ± 0% -16.20% (p=0.000 n=10) Select/common_prefix-8 2.685Mi ± 0% 2.250Mi ± 0% -16.20% (p=0.000 n=10) Select/unknown-8 2.677Mi ± 0% 2.243Mi ± 0% -16.24% (p=0.000 n=10) geomean 2.683Mi 2.248Mi -16.21% │ old │ status │ │ allocs/op │ allocs/op vs base │ Select/string_equal-8 69.03k ± 0% 56.02k ± 0% -18.84% (p=0.000 n=10) Select/string_not_equal-8 69.03k ± 0% 56.02k ± 0% -18.84% (p=0.000 n=10) Select/common_prefix-8 69.03k ± 0% 56.02k ± 0% -18.84% (p=0.000 n=10) Select/unknown-8 68.03k ± 0% 55.03k ± 0% -19.11% (p=0.000 n=10) geomean 68.78k 55.77k -18.90% ``` Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/select.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 9f1b8b0601..4a3b22b553 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -517,7 +517,7 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc func (db *DB) getObjectForSlowFilters(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (*objectSDK.Object, bool, error) { buf := make([]byte, addressKeySize) - obj, err := db.get(tx, addr, buf, true, false, currEpoch) + obj, err := db.get(tx, addr, buf, false, false, currEpoch) if err != nil { var ecInfoError *objectSDK.ECInfoError if errors.As(err, &ecInfoError) { From a11b2d27e4011cf366e889f79cac198abdbcaa51 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 20 Feb 2025 11:05:11 +0300 Subject: [PATCH 1255/1413] [#1642] tree: Introduce `Cursor` type * Use `Cursor` as parameter for `TreeSortedByFilename` Signed-off-by: Airat Arifullin --- pkg/local_object_storage/engine/tree.go | 4 ++-- pkg/local_object_storage/pilorama/boltdb.go | 9 ++++---- pkg/local_object_storage/pilorama/forest.go | 8 +++---- .../pilorama/forest_test.go | 4 ++-- pkg/local_object_storage/pilorama/heap.go | 6 ++--- .../pilorama/interface.go | 23 ++++++++++++++++++- .../pilorama/split_test.go | 2 +- pkg/local_object_storage/shard/tree.go | 2 +- pkg/services/tree/service.go | 2 +- 9 files changed, 40 insertions(+), 20 deletions(-) diff --git a/pkg/local_object_storage/engine/tree.go b/pkg/local_object_storage/engine/tree.go index 7f70d36f74..cfd15b4d4f 100644 --- a/pkg/local_object_storage/engine/tree.go +++ b/pkg/local_object_storage/engine/tree.go @@ -230,7 +230,7 @@ func (e *StorageEngine) TreeGetChildren(ctx context.Context, cid cidSDK.ID, tree } // TreeSortedByFilename implements the pilorama.Forest interface. -func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.MultiNode, last *string, count int) ([]pilorama.MultiNodeInfo, *string, error) { +func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.MultiNode, last *pilorama.Cursor, count int) ([]pilorama.MultiNodeInfo, *pilorama.Cursor, error) { ctx, span := tracing.StartSpanFromContext(ctx, "StorageEngine.TreeSortedByFilename", trace.WithAttributes( attribute.String("container_id", cid.EncodeToString()), @@ -241,7 +241,7 @@ func (e *StorageEngine) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, var err error var nodes []pilorama.MultiNodeInfo - var cursor *string + var cursor *pilorama.Cursor for _, sh := range e.sortShards(cid) { nodes, cursor, err = sh.TreeSortedByFilename(ctx, cid, treeID, nodeID, last, count) if err != nil { diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 9d71d9fdae..0eea60ad82 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1077,7 +1077,7 @@ func (t *boltForest) hasFewChildren(b *bbolt.Bucket, nodeIDs MultiNode, threshol } // TreeSortedByFilename implements the Forest interface. -func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeIDs MultiNode, last *string, count int) ([]MultiNodeInfo, *string, error) { +func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeIDs MultiNode, last *Cursor, count int) ([]MultiNodeInfo, *Cursor, error) { var ( startedAt = time.Now() success = false @@ -1128,7 +1128,6 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr } t.fillSortedChildren(b, nodeIDs, h) - for info, ok := h.pop(); ok; info, ok = h.pop() { for _, id := range info.id { childInfo, err := t.getChildInfo(b, key, id) @@ -1155,7 +1154,7 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr } if len(res) != 0 { s := string(findAttr(res[len(res)-1].Meta, AttributeFilename)) - last = &s + last = NewCursor(s) } return res, last, metaerr.Wrap(err) } @@ -1166,10 +1165,10 @@ func sortByFilename(nodes []NodeInfo) { }) } -func sortAndCut(result []NodeInfo, last *string) []NodeInfo { +func sortAndCut(result []NodeInfo, last *Cursor) []NodeInfo { var lastBytes []byte if last != nil { - lastBytes = []byte(*last) + lastBytes = []byte(last.GetFilename()) } sortByFilename(result) diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index ef284a7272..ce8528a814 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -164,7 +164,7 @@ func (f *memoryForest) TreeGetMeta(_ context.Context, cid cid.ID, treeID string, } // TreeSortedByFilename implements the Forest interface. -func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeID string, nodeIDs MultiNode, start *string, count int) ([]MultiNodeInfo, *string, error) { +func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeID string, nodeIDs MultiNode, start *Cursor, count int) ([]MultiNodeInfo, *Cursor, error) { fullID := cid.String() + "/" + treeID s, ok := f.treeMap[fullID] if !ok { @@ -204,14 +204,14 @@ func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeI r := mergeNodeInfos(res) for i := range r { - if start == nil || string(findAttr(r[i].Meta, AttributeFilename)) > *start { + if start == nil || string(findAttr(r[i].Meta, AttributeFilename)) > start.GetFilename() { finish := min(len(res), i+count) last := string(findAttr(r[finish-1].Meta, AttributeFilename)) - return r[i:finish], &last, nil + return r[i:finish], NewCursor(last), nil } } last := string(res[len(res)-1].Meta.GetAttr(AttributeFilename)) - return nil, &last, nil + return nil, NewCursor(last), nil } // TreeGetChildren implements the Forest interface. diff --git a/pkg/local_object_storage/pilorama/forest_test.go b/pkg/local_object_storage/pilorama/forest_test.go index de56fc82be..844084c552 100644 --- a/pkg/local_object_storage/pilorama/forest_test.go +++ b/pkg/local_object_storage/pilorama/forest_test.go @@ -273,7 +273,7 @@ func testForestTreeSortedIterationBugWithSkip(t *testing.T, s ForestStorage) { } var result []MultiNodeInfo - treeAppend := func(t *testing.T, last *string, count int) *string { + treeAppend := func(t *testing.T, last *Cursor, count int) *Cursor { res, cursor, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, MultiNode{RootID}, last, count) require.NoError(t, err) result = append(result, res...) @@ -328,7 +328,7 @@ func testForestTreeSortedIteration(t *testing.T, s ForestStorage) { } var result []MultiNodeInfo - treeAppend := func(t *testing.T, last *string, count int) *string { + treeAppend := func(t *testing.T, last *Cursor, count int) *Cursor { res, cursor, err := s.TreeSortedByFilename(context.Background(), d.CID, treeID, MultiNode{RootID}, last, count) require.NoError(t, err) result = append(result, res...) diff --git a/pkg/local_object_storage/pilorama/heap.go b/pkg/local_object_storage/pilorama/heap.go index 5a00bcf7a3..70afc148a1 100644 --- a/pkg/local_object_storage/pilorama/heap.go +++ b/pkg/local_object_storage/pilorama/heap.go @@ -30,13 +30,13 @@ func (h *filenameHeap) Pop() any { // fixedHeap maintains a fixed number of smallest elements started at some point. type fixedHeap struct { - start *string + start *Cursor sorted bool count int h *filenameHeap } -func newHeap(start *string, count int) *fixedHeap { +func newHeap(start *Cursor, count int) *fixedHeap { h := new(filenameHeap) heap.Init(h) @@ -50,7 +50,7 @@ func newHeap(start *string, count int) *fixedHeap { const amortizationMultiplier = 5 func (h *fixedHeap) push(id MultiNode, filename string) bool { - if h.start != nil && filename <= *h.start { + if h.start != nil && filename <= (*h.start).GetFilename() { return false } diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index 1f7e742a21..e364b008b2 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -37,7 +37,7 @@ type Forest interface { TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID string, nodeID Node) ([]NodeInfo, error) // TreeSortedByFilename returns children of the node with the specified ID. The nodes are sorted by the filename attribute.. // Should return ErrTreeNotFound if the tree is not found, and empty result if the node is not in the tree. - TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID MultiNode, last *string, count int) ([]MultiNodeInfo, *string, error) + TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID MultiNode, last *Cursor, count int) ([]MultiNodeInfo, *Cursor, error) // TreeGetOpLog returns first log operation stored at or above the height. // In case no such operation is found, empty Move and nil error should be returned. TreeGetOpLog(ctx context.Context, cid cidSDK.ID, treeID string, height uint64) (Move, error) @@ -79,6 +79,27 @@ const ( AttributeVersion = "Version" ) +// Cursor keeps state between function calls for traversing nodes. +// It stores the attributes associated with a previous call, allowing subsequent operations +// to resume traversal from this point rather than starting from the beginning. +type Cursor struct { + // Last traversed filename. + filename string +} + +func NewCursor(filename string) *Cursor { + return &Cursor{ + filename: filename, + } +} + +func (c *Cursor) GetFilename() string { + if c == nil { + return "" + } + return c.filename +} + // CIDDescriptor contains container ID and information about the node position // in the list of container nodes. type CIDDescriptor struct { diff --git a/pkg/local_object_storage/pilorama/split_test.go b/pkg/local_object_storage/pilorama/split_test.go index 54c2b90a65..eecee1527b 100644 --- a/pkg/local_object_storage/pilorama/split_test.go +++ b/pkg/local_object_storage/pilorama/split_test.go @@ -96,7 +96,7 @@ func testDuplicateDirectory(t *testing.T, f Forest) { require.Equal(t, []byte{8}, testGetByPath(t, "dir1/dir3/value4")) require.Equal(t, []byte{10}, testGetByPath(t, "value0")) - testSortedByFilename := func(t *testing.T, root MultiNode, last *string, batchSize int) ([]MultiNodeInfo, *string) { + testSortedByFilename := func(t *testing.T, root MultiNode, last *Cursor, batchSize int) ([]MultiNodeInfo, *Cursor) { res, last, err := f.TreeSortedByFilename(context.Background(), d.CID, treeID, root, last, batchSize) require.NoError(t, err) return res, last diff --git a/pkg/local_object_storage/shard/tree.go b/pkg/local_object_storage/shard/tree.go index e9cd5f8c1f..db361a8bd2 100644 --- a/pkg/local_object_storage/shard/tree.go +++ b/pkg/local_object_storage/shard/tree.go @@ -246,7 +246,7 @@ func (s *Shard) TreeGetChildren(ctx context.Context, cid cidSDK.ID, treeID strin } // TreeSortedByFilename implements the pilorama.Forest interface. -func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.MultiNode, last *string, count int) ([]pilorama.MultiNodeInfo, *string, error) { +func (s *Shard) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, treeID string, nodeID pilorama.MultiNode, last *pilorama.Cursor, count int) ([]pilorama.MultiNodeInfo, *pilorama.Cursor, error) { ctx, span := tracing.StartSpanFromContext(ctx, "Shard.TreeSortedByFilename", trace.WithAttributes( attribute.String("shard_id", s.ID().String()), diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index cd89d6a286..98c5626bd4 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -412,7 +412,7 @@ func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeS type stackItem struct { values []pilorama.MultiNodeInfo parent pilorama.MultiNode - last *string + last *pilorama.Cursor } func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid cidSDK.ID, b *GetSubTreeRequest_Body, forest pilorama.Forest) error { From 760b6a44ea0557489a1f16fbdbbdfb81efcc0d58 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Fri, 28 Feb 2025 15:47:29 +0300 Subject: [PATCH 1256/1413] [#1642] tree: Fix sorted getSubtree for multiversion filenames Signed-off-by: Airat Arifullin --- pkg/local_object_storage/pilorama/boltdb.go | 3 ++- pkg/local_object_storage/pilorama/forest.go | 4 ++-- pkg/local_object_storage/pilorama/heap.go | 15 +++++++++++++-- pkg/local_object_storage/pilorama/interface.go | 13 ++++++++++++- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 0eea60ad82..2ca6fdefa5 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1128,6 +1128,7 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr } t.fillSortedChildren(b, nodeIDs, h) + for info, ok := h.pop(); ok; info, ok = h.pop() { for _, id := range info.id { childInfo, err := t.getChildInfo(b, key, id) @@ -1154,7 +1155,7 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr } if len(res) != 0 { s := string(findAttr(res[len(res)-1].Meta, AttributeFilename)) - last = NewCursor(s) + last = NewCursor(s, res[len(res)-1].Children[len(res[len(res)-1].Children)-1]) } return res, last, metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index ce8528a814..b5320e42dd 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -207,11 +207,11 @@ func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeI if start == nil || string(findAttr(r[i].Meta, AttributeFilename)) > start.GetFilename() { finish := min(len(res), i+count) last := string(findAttr(r[finish-1].Meta, AttributeFilename)) - return r[i:finish], NewCursor(last), nil + return r[i:finish], NewCursor(last, 0), nil } } last := string(res[len(res)-1].Meta.GetAttr(AttributeFilename)) - return nil, NewCursor(last), nil + return nil, NewCursor(last, 0), nil } // TreeGetChildren implements the Forest interface. diff --git a/pkg/local_object_storage/pilorama/heap.go b/pkg/local_object_storage/pilorama/heap.go index 70afc148a1..b035be1e15 100644 --- a/pkg/local_object_storage/pilorama/heap.go +++ b/pkg/local_object_storage/pilorama/heap.go @@ -50,8 +50,19 @@ func newHeap(start *Cursor, count int) *fixedHeap { const amortizationMultiplier = 5 func (h *fixedHeap) push(id MultiNode, filename string) bool { - if h.start != nil && filename <= (*h.start).GetFilename() { - return false + if h.start != nil { + if filename < h.start.GetFilename() { + return false + } else if filename == h.start.GetFilename() { + // A tree may have a lot of nodes with the same filename but different versions so that + // len(nodes) > batch_size. The cut nodes should be pushed into the result on repeated call + // with the same filename. + pos := slices.Index(id, h.start.GetNode()) + if pos == -1 || pos+1 >= len(id) { + return false + } + id = id[pos+1:] + } } *h.h = append(*h.h, heapInfo{id: id, filename: filename}) diff --git a/pkg/local_object_storage/pilorama/interface.go b/pkg/local_object_storage/pilorama/interface.go index e364b008b2..e1f6cd8e7f 100644 --- a/pkg/local_object_storage/pilorama/interface.go +++ b/pkg/local_object_storage/pilorama/interface.go @@ -85,11 +85,15 @@ const ( type Cursor struct { // Last traversed filename. filename string + + // Last traversed node. + node Node } -func NewCursor(filename string) *Cursor { +func NewCursor(filename string, node Node) *Cursor { return &Cursor{ filename: filename, + node: node, } } @@ -100,6 +104,13 @@ func (c *Cursor) GetFilename() string { return c.filename } +func (c *Cursor) GetNode() Node { + if c == nil { + return Node(0) + } + return c.node +} + // CIDDescriptor contains container ID and information about the node position // in the list of container nodes. type CIDDescriptor struct { From 39f549a7ab011c25b81f4bafa7c21f8a46cd5b26 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 10 Mar 2025 13:17:24 +0300 Subject: [PATCH 1257/1413] [#1642] tree: Intoduce a helper `LastChild` Signed-off-by: Airat Arifullin --- pkg/local_object_storage/pilorama/boltdb.go | 2 +- pkg/local_object_storage/pilorama/multinode.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index 2ca6fdefa5..fc7cdaabc0 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1155,7 +1155,7 @@ func (t *boltForest) TreeSortedByFilename(ctx context.Context, cid cidSDK.ID, tr } if len(res) != 0 { s := string(findAttr(res[len(res)-1].Meta, AttributeFilename)) - last = NewCursor(s, res[len(res)-1].Children[len(res[len(res)-1].Children)-1]) + last = NewCursor(s, res[len(res)-1].LastChild()) } return res, last, metaerr.Wrap(err) } diff --git a/pkg/local_object_storage/pilorama/multinode.go b/pkg/local_object_storage/pilorama/multinode.go index 106ba6ae9c..36d347f100 100644 --- a/pkg/local_object_storage/pilorama/multinode.go +++ b/pkg/local_object_storage/pilorama/multinode.go @@ -25,6 +25,10 @@ func (r *MultiNodeInfo) Add(info NodeInfo) bool { return true } +func (r *MultiNodeInfo) LastChild() Node { + return r.Children[len(r.Children)-1] +} + func (n NodeInfo) ToMultiNode() MultiNodeInfo { return MultiNodeInfo{ Children: MultiNode{n.ID}, From a7ac30da9c47abe0e2fffa49de287e8849d570ed Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 12 Mar 2025 17:01:56 +0300 Subject: [PATCH 1258/1413] [#1642] tree: Refactor `getSortedSubTree` * Reuse `item` as result for `forest.TreeSortedByFilename` invocation. Signed-off-by: Airat Arifullin --- pkg/services/tree/service.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 98c5626bd4..eeffec08b1 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -463,14 +463,13 @@ func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid break } - nodes, last, err := forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), item.parent, item.last, batchSize) + var err error + item.values, item.last, err = forest.TreeSortedByFilename(ctx, cid, b.GetTreeId(), item.parent, item.last, batchSize) if err != nil { return err } - item.values = nodes - item.last = last - if len(nodes) == 0 { + if len(item.values) == 0 { stack = stack[:len(stack)-1] continue } From a49f0717b3fbba0ecf51ce55f49221474a8f8fb8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 19 Mar 2025 09:22:29 +0300 Subject: [PATCH 1259/1413] [#1685] metabase: Cache frequently accessed singleton buckets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some buckets we access almost always, to check whether an object is alive. In search we also iterate over lots of objects, and `tx.Bucket()` shows itself a lot in pprof. ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ 1 │ 2 │ │ sec/op │ sec/op vs base │ Select/string_equal-8 4.753m ± 6% 3.969m ± 14% -16.50% (p=0.000 n=10) Select/string_not_equal-8 4.247m ± 9% 3.486m ± 11% -17.93% (p=0.000 n=10) Select/common_prefix-8 4.163m ± 5% 3.323m ± 5% -20.18% (p=0.000 n=10) Select/unknown-8 3.557m ± 3% 3.064m ± 8% -13.85% (p=0.001 n=10) geomean 4.158m 3.445m -17.15% │ 1 │ 2 │ │ B/op │ B/op vs base │ Select/string_equal-8 2.250Mi ± 0% 1.907Mi ± 0% -15.24% (p=0.000 n=10) Select/string_not_equal-8 2.250Mi ± 0% 1.907Mi ± 0% -15.24% (p=0.000 n=10) Select/common_prefix-8 2.250Mi ± 0% 1.907Mi ± 0% -15.24% (p=0.000 n=10) Select/unknown-8 2.243Mi ± 0% 1.900Mi ± 0% -15.29% (p=0.000 n=10) geomean 2.248Mi 1.905Mi -15.26% │ 1 │ 2 │ │ allocs/op │ allocs/op vs base │ Select/string_equal-8 56.02k ± 0% 47.03k ± 0% -16.05% (p=0.000 n=10) Select/string_not_equal-8 56.02k ± 0% 47.03k ± 0% -16.05% (p=0.000 n=10) Select/common_prefix-8 56.02k ± 0% 47.03k ± 0% -16.05% (p=0.000 n=10) Select/unknown-8 55.03k ± 0% 46.04k ± 0% -16.34% (p=0.000 n=10) geomean 55.78k 46.78k -16.12% ``` Signed-off-by: Evgenii Stratonikov --- .../metabase/bucket_cache.go | 45 +++++++++++++++++++ pkg/local_object_storage/metabase/exists.go | 10 +++-- pkg/local_object_storage/metabase/lock.go | 6 ++- pkg/local_object_storage/metabase/select.go | 3 +- 4 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 pkg/local_object_storage/metabase/bucket_cache.go diff --git a/pkg/local_object_storage/metabase/bucket_cache.go b/pkg/local_object_storage/metabase/bucket_cache.go new file mode 100644 index 0000000000..b425450af8 --- /dev/null +++ b/pkg/local_object_storage/metabase/bucket_cache.go @@ -0,0 +1,45 @@ +package meta + +import ( + "go.etcd.io/bbolt" +) + +type bucketCache struct { + locked *bbolt.Bucket + graveyard *bbolt.Bucket + garbage *bbolt.Bucket +} + +func newBucketCache() *bucketCache { + return &bucketCache{} +} + +func getLockedBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket { + if bc == nil { + return tx.Bucket(bucketNameLocked) + } + return getBucket(&bc.locked, tx, bucketNameLocked) +} + +func getGraveyardBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket { + if bc == nil { + return tx.Bucket(graveyardBucketName) + } + return getBucket(&bc.graveyard, tx, graveyardBucketName) +} + +func getGarbageBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket { + if bc == nil { + return tx.Bucket(garbageBucketName) + } + return getBucket(&bc.garbage, tx, garbageBucketName) +} + +func getBucket(cache **bbolt.Bucket, tx *bbolt.Tx, name []byte) *bbolt.Bucket { + if *cache != nil { + return *cache + } + + *cache = tx.Bucket(name) + return *cache +} diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index 962108a761..0b28da5c9e 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -153,8 +153,12 @@ func (db *DB) exists(tx *bbolt.Tx, addr oid.Address, ecParent oid.Address, currE // - 2 if object is covered with tombstone; // - 3 if object is expired. func objectStatus(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (uint8, error) { + return objectStatusWithCache(nil, tx, addr, currEpoch) +} + +func objectStatusWithCache(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (uint8, error) { // locked object could not be removed/marked with GC/expired - if objectLocked(tx, addr.Container(), addr.Object()) { + if objectLockedWithCache(bc, tx, addr.Container(), addr.Object()) { return 0, nil } @@ -167,8 +171,8 @@ func objectStatus(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (uint8, erro return 3, nil } - graveyardBkt := tx.Bucket(graveyardBucketName) - garbageBkt := tx.Bucket(garbageBucketName) + graveyardBkt := getGraveyardBucket(bc, tx) + garbageBkt := getGarbageBucket(bc, tx) addrKey := addressKey(addr, make([]byte, addressKeySize)) return inGraveyardWithKey(addrKey, graveyardBkt, garbageBkt), nil } diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index aa14784231..f73c2b4f68 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -163,7 +163,11 @@ func (db *DB) FreeLockedBy(lockers []oid.Address) ([]oid.Address, error) { // checks if specified object is locked in the specified container. func objectLocked(tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) bool { - bucketLocked := tx.Bucket(bucketNameLocked) + return objectLockedWithCache(nil, tx, idCnr, idObj) +} + +func objectLockedWithCache(bc *bucketCache, tx *bbolt.Tx, idCnr cid.ID, idObj oid.ID) bool { + bucketLocked := getLockedBucket(bc, tx) if bucketLocked != nil { key := make([]byte, cidSize) idCnr.Encode(key) diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index 4a3b22b553..a953847539 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -131,6 +131,7 @@ func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters res := make([]oid.Address, 0, len(mAddr)) + bc := newBucketCache() for a, ind := range mAddr { if ind != expLen { continue // ignore objects with unmatched fast filters @@ -145,7 +146,7 @@ func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters var addr oid.Address addr.SetContainer(cnr) addr.SetObject(id) - st, err := objectStatus(tx, addr, currEpoch) + st, err := objectStatusWithCache(bc, tx, addr, currEpoch) if err != nil { return nil, err } From af5b3575d0a2a63f6ec87fb58feb28b30419110a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 20 Mar 2025 14:41:13 +0300 Subject: [PATCH 1260/1413] [#1690] qos: Do not export zero metrics counters Signed-off-by: Dmitrii Stepanov --- internal/qos/limiter.go | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index 8f00791c50..e92cef652a 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -211,13 +211,26 @@ func (n *mClockLimiter) startMetricsCollect() { continue } metrics := n.metrics.Load().metrics - for tag, s := range n.readStats { - metrics.SetOperationTagCounters(shardID, "read", tag, s.pending.Load(), s.inProgress.Load(), s.completed.Load(), s.resourceExhausted.Load()) - } - for tag, s := range n.writeStats { - metrics.SetOperationTagCounters(shardID, "write", tag, s.pending.Load(), s.inProgress.Load(), s.completed.Load(), s.resourceExhausted.Load()) - } + exportMetrics(metrics, n.readStats, shardID, "read") + exportMetrics(metrics, n.writeStats, shardID, "write") } } }() } + +func exportMetrics(metrics Metrics, stats map[string]*stat, shardID, operation string) { + var pending uint64 + var inProgress uint64 + var completed uint64 + var resExh uint64 + for tag, s := range stats { + pending = s.pending.Load() + inProgress = s.inProgress.Load() + completed = s.completed.Load() + resExh = s.resourceExhausted.Load() + if pending == 0 && inProgress == 0 && completed == 0 && resExh == 0 { + continue + } + metrics.SetOperationTagCounters(shardID, operation, tag, pending, inProgress, completed, resExh) + } +} From 21bed3362c03730160b5f98fa3dc06c3d4d78cf2 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Mar 2025 10:14:22 +0300 Subject: [PATCH 1261/1413] [#1685] metabase: Cache expired bucket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ master │ expired │ │ sec/op │ sec/op vs base │ Select/string_equal-8 4.007m ± 10% 3.529m ± 11% -11.94% (p=0.000 n=10) Select/string_not_equal-8 3.834m ± 12% 3.440m ± 7% -10.29% (p=0.029 n=10) Select/common_prefix-8 3.470m ± 9% 3.240m ± 6% ~ (p=0.105 n=10) Select/unknown-8 3.156m ± 3% 3.198m ± 6% ~ (p=0.631 n=10) geomean 3.602m 3.349m -7.03% │ master │ expired │ │ B/op │ B/op vs base │ Select/string_equal-8 1.907Mi ± 0% 1.885Mi ± 0% -1.18% (p=0.000 n=10) Select/string_not_equal-8 1.907Mi ± 0% 1.885Mi ± 0% -1.18% (p=0.000 n=10) Select/common_prefix-8 1.907Mi ± 0% 1.885Mi ± 0% -1.18% (p=0.000 n=10) Select/unknown-8 1.900Mi ± 0% 1.877Mi ± 0% -1.18% (p=0.000 n=10) geomean 1.905Mi 1.883Mi -1.18% │ master │ expired │ │ allocs/op │ allocs/op vs base │ Select/string_equal-8 47.03k ± 0% 46.04k ± 0% -2.12% (p=0.000 n=10) Select/string_not_equal-8 47.03k ± 0% 46.04k ± 0% -2.12% (p=0.000 n=10) Select/common_prefix-8 47.03k ± 0% 46.04k ± 0% -2.12% (p=0.000 n=10) Select/unknown-8 46.04k ± 0% 45.05k ± 0% -2.16% (p=0.000 n=10) geomean 46.78k 45.79k -2.13% ``` Change-Id: I9c7a5e1f5c8b9eb3f25a563fd74c6ad2a9d1b92e Signed-off-by: Evgenii Stratonikov --- .../metabase/bucket_cache.go | 25 ++++++++++++++++++- pkg/local_object_storage/metabase/exists.go | 2 +- pkg/local_object_storage/metabase/expired.go | 8 +++--- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/pkg/local_object_storage/metabase/bucket_cache.go b/pkg/local_object_storage/metabase/bucket_cache.go index b425450af8..14c164afcc 100644 --- a/pkg/local_object_storage/metabase/bucket_cache.go +++ b/pkg/local_object_storage/metabase/bucket_cache.go @@ -1,6 +1,7 @@ package meta import ( + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.etcd.io/bbolt" ) @@ -8,10 +9,11 @@ type bucketCache struct { locked *bbolt.Bucket graveyard *bbolt.Bucket garbage *bbolt.Bucket + expired map[cid.ID]*bbolt.Bucket } func newBucketCache() *bucketCache { - return &bucketCache{} + return &bucketCache{expired: make(map[cid.ID]*bbolt.Bucket)} } func getLockedBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket { @@ -43,3 +45,24 @@ func getBucket(cache **bbolt.Bucket, tx *bbolt.Tx, name []byte) *bbolt.Bucket { *cache = tx.Bucket(name) return *cache } + +func getExpiredBucket(bc *bucketCache, tx *bbolt.Tx, cnr cid.ID) *bbolt.Bucket { + if bc == nil { + bucketName := make([]byte, bucketKeySize) + bucketName = objectToExpirationEpochBucketName(cnr, bucketName) + return tx.Bucket(bucketName) + } + return getMappedBucket(bc.expired, tx, objectToExpirationEpochBucketName, cnr) +} + +func getMappedBucket(m map[cid.ID]*bbolt.Bucket, tx *bbolt.Tx, nameFunc func(cid.ID, []byte) []byte, cnr cid.ID) *bbolt.Bucket { + value, ok := m[cnr] + if ok { + return value + } + + bucketName := make([]byte, bucketKeySize) + bucketName = nameFunc(cnr, bucketName) + m[cnr] = getBucket(&value, tx, bucketName) + return value +} diff --git a/pkg/local_object_storage/metabase/exists.go b/pkg/local_object_storage/metabase/exists.go index 0b28da5c9e..7bd6f90a67 100644 --- a/pkg/local_object_storage/metabase/exists.go +++ b/pkg/local_object_storage/metabase/exists.go @@ -162,7 +162,7 @@ func objectStatusWithCache(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, curr return 0, nil } - expired, err := isExpired(tx, addr, currEpoch) + expired, err := isExpiredWithCache(bc, tx, addr, currEpoch) if err != nil { return 0, err } diff --git a/pkg/local_object_storage/metabase/expired.go b/pkg/local_object_storage/metabase/expired.go index 68144d8b18..a1351cb6f5 100644 --- a/pkg/local_object_storage/metabase/expired.go +++ b/pkg/local_object_storage/metabase/expired.go @@ -74,9 +74,11 @@ func (db *DB) FilterExpired(ctx context.Context, epoch uint64, addresses []oid.A } func isExpired(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (bool, error) { - bucketName := make([]byte, bucketKeySize) - bucketName = objectToExpirationEpochBucketName(addr.Container(), bucketName) - b := tx.Bucket(bucketName) + return isExpiredWithCache(nil, tx, addr, currEpoch) +} + +func isExpiredWithCache(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (bool, error) { + b := getExpiredBucket(bc, tx, addr.Container()) if b == nil { return false, nil } From eb9df85b989f861f50891fc21732ce56e56dabc3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Mar 2025 10:23:26 +0300 Subject: [PATCH 1262/1413] [#1685] metabase: Cache primary bucket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ expired │ primary │ │ sec/op │ sec/op vs base │ Select/string_equal-8 3.529m ± 11% 3.689m ± 7% +4.55% (p=0.023 n=10) Select/string_not_equal-8 3.440m ± 7% 3.543m ± 13% ~ (p=0.190 n=10) Select/common_prefix-8 3.240m ± 6% 3.050m ± 5% -5.85% (p=0.005 n=10) Select/unknown-8 3.198m ± 6% 2.928m ± 8% -8.44% (p=0.003 n=10) geomean 3.349m 3.287m -1.84% │ expired │ primary │ │ B/op │ B/op vs base │ Select/string_equal-8 1.885Mi ± 0% 1.786Mi ± 0% -5.23% (p=0.000 n=10) Select/string_not_equal-8 1.885Mi ± 0% 1.786Mi ± 0% -5.23% (p=0.000 n=10) Select/common_prefix-8 1.885Mi ± 0% 1.786Mi ± 0% -5.23% (p=0.000 n=10) Select/unknown-8 1.877Mi ± 0% 1.779Mi ± 0% -5.26% (p=0.000 n=10) geomean 1.883Mi 1.784Mi -5.24% │ expired │ primary │ │ allocs/op │ allocs/op vs base │ Select/string_equal-8 46.04k ± 0% 43.04k ± 0% -6.50% (p=0.000 n=10) Select/string_not_equal-8 46.04k ± 0% 43.04k ± 0% -6.50% (p=0.000 n=10) Select/common_prefix-8 46.04k ± 0% 43.04k ± 0% -6.50% (p=0.000 n=10) Select/unknown-8 45.05k ± 0% 42.05k ± 0% -6.65% (p=0.000 n=10) geomean 45.79k 42.79k -6.54% ``` Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/bucket_cache.go | 15 ++++++++++++++- pkg/local_object_storage/metabase/get.go | 15 ++++++++++----- pkg/local_object_storage/metabase/select.go | 12 ++++++------ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/pkg/local_object_storage/metabase/bucket_cache.go b/pkg/local_object_storage/metabase/bucket_cache.go index 14c164afcc..69553d55c3 100644 --- a/pkg/local_object_storage/metabase/bucket_cache.go +++ b/pkg/local_object_storage/metabase/bucket_cache.go @@ -10,10 +10,14 @@ type bucketCache struct { graveyard *bbolt.Bucket garbage *bbolt.Bucket expired map[cid.ID]*bbolt.Bucket + primary map[cid.ID]*bbolt.Bucket } func newBucketCache() *bucketCache { - return &bucketCache{expired: make(map[cid.ID]*bbolt.Bucket)} + return &bucketCache{ + expired: make(map[cid.ID]*bbolt.Bucket), + primary: make(map[cid.ID]*bbolt.Bucket), + } } func getLockedBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket { @@ -55,6 +59,15 @@ func getExpiredBucket(bc *bucketCache, tx *bbolt.Tx, cnr cid.ID) *bbolt.Bucket { return getMappedBucket(bc.expired, tx, objectToExpirationEpochBucketName, cnr) } +func getPrimaryBucket(bc *bucketCache, tx *bbolt.Tx, cnr cid.ID) *bbolt.Bucket { + if bc == nil { + bucketName := make([]byte, bucketKeySize) + bucketName = primaryBucketName(cnr, bucketName) + return tx.Bucket(bucketName) + } + return getMappedBucket(bc.primary, tx, primaryBucketName, cnr) +} + func getMappedBucket(m map[cid.ID]*bbolt.Bucket, tx *bbolt.Tx, nameFunc func(cid.ID, []byte) []byte, cnr cid.ID) *bbolt.Bucket { value, ok := m[cnr] if ok { diff --git a/pkg/local_object_storage/metabase/get.go b/pkg/local_object_storage/metabase/get.go index 615add1af1..821810c090 100644 --- a/pkg/local_object_storage/metabase/get.go +++ b/pkg/local_object_storage/metabase/get.go @@ -88,8 +88,12 @@ func (db *DB) Get(ctx context.Context, prm GetPrm) (res GetRes, err error) { } func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw bool, currEpoch uint64) (*objectSDK.Object, error) { + return db.getWithCache(nil, tx, addr, key, checkStatus, raw, currEpoch) +} + +func (db *DB) getWithCache(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw bool, currEpoch uint64) (*objectSDK.Object, error) { if checkStatus { - st, err := objectStatus(tx, addr, currEpoch) + st, err := objectStatusWithCache(bc, tx, addr, currEpoch) if err != nil { return nil, err } @@ -109,12 +113,13 @@ func (db *DB) get(tx *bbolt.Tx, addr oid.Address, key []byte, checkStatus, raw b bucketName := make([]byte, bucketKeySize) // check in primary index - data := getFromBucket(tx, primaryBucketName(cnr, bucketName), key) - if len(data) != 0 { - return obj, obj.Unmarshal(data) + if b := getPrimaryBucket(bc, tx, cnr); b != nil { + if data := b.Get(key); len(data) != 0 { + return obj, obj.Unmarshal(data) + } } - data = getFromBucket(tx, ecInfoBucketName(cnr, bucketName), key) + data := getFromBucket(tx, ecInfoBucketName(cnr, bucketName), key) if len(data) != 0 { return nil, getECInfoError(tx, cnr, data) } diff --git a/pkg/local_object_storage/metabase/select.go b/pkg/local_object_storage/metabase/select.go index a953847539..60da506717 100644 --- a/pkg/local_object_storage/metabase/select.go +++ b/pkg/local_object_storage/metabase/select.go @@ -154,7 +154,7 @@ func (db *DB) selectObjects(tx *bbolt.Tx, cnr cid.ID, fs objectSDK.SearchFilters continue // ignore removed objects } - addr, match := db.matchSlowFilters(tx, addr, group.slowFilters, currEpoch) + addr, match := db.matchSlowFilters(bc, tx, addr, group.slowFilters, currEpoch) if !match { continue // ignore objects with unmatched slow filters } @@ -452,13 +452,13 @@ func (db *DB) selectObjectID( } // matchSlowFilters return true if object header is matched by all slow filters. -func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.SearchFilters, currEpoch uint64) (oid.Address, bool) { +func (db *DB) matchSlowFilters(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, f objectSDK.SearchFilters, currEpoch uint64) (oid.Address, bool) { result := addr if len(f) == 0 { return result, true } - obj, isECChunk, err := db.getObjectForSlowFilters(tx, addr, currEpoch) + obj, isECChunk, err := db.getObjectForSlowFilters(bc, tx, addr, currEpoch) if err != nil { return result, false } @@ -516,9 +516,9 @@ func (db *DB) matchSlowFilters(tx *bbolt.Tx, addr oid.Address, f objectSDK.Searc return result, true } -func (db *DB) getObjectForSlowFilters(tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (*objectSDK.Object, bool, error) { +func (db *DB) getObjectForSlowFilters(bc *bucketCache, tx *bbolt.Tx, addr oid.Address, currEpoch uint64) (*objectSDK.Object, bool, error) { buf := make([]byte, addressKeySize) - obj, err := db.get(tx, addr, buf, false, false, currEpoch) + obj, err := db.getWithCache(bc, tx, addr, buf, false, false, currEpoch) if err != nil { var ecInfoError *objectSDK.ECInfoError if errors.As(err, &ecInfoError) { @@ -528,7 +528,7 @@ func (db *DB) getObjectForSlowFilters(tx *bbolt.Tx, addr oid.Address, currEpoch continue } addr.SetObject(objID) - obj, err = db.get(tx, addr, buf, true, false, currEpoch) + obj, err = db.getWithCache(bc, tx, addr, buf, true, false, currEpoch) if err == nil { return obj, true, nil } From e8801dbf49c2407bb7cbd25d003d7a9b95fc7c3b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Mar 2025 15:28:14 +0300 Subject: [PATCH 1263/1413] [#1691] metabase: Move cheaper conditions to the front in ListWithCursor() `objectLocked` call is expensive, it does IO. We may omit it if object is not expired. Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index eaef3b9ba7..0b6cdf702e 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -251,7 +251,7 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket } expEpoch, hasExpEpoch := hasExpirationEpoch(&o) - if !objectLocked(bkt.Tx(), cnt, obj) && hasExpEpoch && expEpoch < currEpoch { + if hasExpEpoch && expEpoch < currEpoch && !objectLocked(bkt.Tx(), cnt, obj) { continue } From 45b779615104ed790f65f4776fb59cc6c163d0f6 Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Tue, 11 Mar 2025 16:57:07 +0300 Subject: [PATCH 1264/1413] [#1689] ci: Reimplement CI tasks in Jenkinsfile This commit introduces Jenkins pipeline that duplicates the features of existing Forgejo Actions workflows. Change-Id: I657a6c27373a1ed4736ae27b4fb660e0ac86012d Signed-off-by: Vitaliy Potyarkin --- .ci/Jenkinsfile | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .ci/Jenkinsfile diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile new file mode 100644 index 0000000000..e21ce61c54 --- /dev/null +++ b/.ci/Jenkinsfile @@ -0,0 +1,81 @@ +def golang = ['1.23', '1.24'] +def golangDefault = "golang:${golang.last()}" + +async { + + for (version in golang) { + def go = version + + task("test/go${go}") { + container("golang:${go}") { + sh 'make test' + } + } + + task("build/go${go}") { + container("golang:${go}") { + for (app in ['cli', 'node', 'ir', 'adm', 'lens']) { + sh """ + make bin/frostfs-${app} + bin/frostfs-${app} --version + """ + } + } + } + } + + task('test/race') { + container(golangDefault) { + sh 'make test GOFLAGS="-count=1 -race"' + } + } + + task('lint') { + container(golangDefault) { + sh 'make lint-install lint' + } + } + + task('staticcheck') { + container(golangDefault) { + sh 'make staticcheck-install staticcheck-run' + } + } + + task('gopls') { + container(golangDefault) { + sh 'make gopls-install gopls-run' + } + } + + task('gofumpt') { + container(golangDefault) { + sh ''' + make fumpt-install + make fumpt + git diff --exit-code --quiet + ''' + } + } + + task('vulncheck') { + container(golangDefault) { + sh ''' + go install golang.org/x/vuln/cmd/govulncheck@latest + govulncheck ./... + ''' + } + } + + task('pre-commit') { + sh ''' + apt update + apt install -y --no-install-recommends pre-commit + ''' // TODO: Make an OCI image for pre-commit + golang? Unpack golang tarball with a library function? + withEnv(['SKIP=make-lint,go-staticcheck-repo-mod,go-unit-tests,gofumpt']) { + sh 'pre-commit run --color=always --hook-stage=manual --all-files' + } + } +} + +// TODO: dco check From affab255120dd54fc581a26fbdcac2cf9a82346a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 13 Mar 2025 10:26:08 +0300 Subject: [PATCH 1265/1413] Makefile: Add Gerrit-related targets This commit adds helper targets to easily setup an existing repo for work with Gerrit. Change-Id: I0696eb8ea84cc16a9482be6a2fb0382fe624bb96 Signed-off-by: Evgenii Stratonikov --- Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Makefile b/Makefile index cd80fc72ef..46168719d9 100755 --- a/Makefile +++ b/Makefile @@ -186,6 +186,20 @@ test: @echo "⇒ Running go test" @GOFLAGS="$(GOFLAGS)" go test ./... +# Install Gerrit commit-msg hook +review-install: GIT_HOOK_DIR := $(shell git rev-parse --git-dir)/hooks +review-install: + @git config remote.review.url \ + || git remote add review ssh://review.frostfs.info:2222/TrueCloudLab/frostfs-node + @mkdir -p $(GIT_HOOK_DIR)/ + @curl -Lo $(GIT_HOOK_DIR)/commit-msg https://review.frostfs.info/tools/hooks/commit-msg + @chmod +x $(GIT_HOOK_DIR)/commit-msg + +# Create a PR in Gerrit +review: BRANCH ?= master +review: + @git push review HEAD:refs/for/$(BRANCH) + # Run pre-commit pre-commit-run: @pre-commit run -a --hook-stage manual From 7df2912a83f8c4b02e89d6311a10f0bdb0a6eddc Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Mar 2025 17:26:35 +0300 Subject: [PATCH 1266/1413] [#1689] Makefile: Create prepare-commit-msg hook too `commit-msg` is ignored when `--no-verify` option is used, so there is no way to ignore `pre-commit` while retaining `commit-msg` hook. Ignoring pre-commit is useful, though, so we might add Change-Id in `prepare-commit-msg` hook instead. It accepts more parameters, but the first one is a file with the commit message, so we may reuse `commit-msg` hook. Change-Id: I4edb79810bbe38a5dcf7f4f07535f34c6bda0da3 Signed-off-by: Evgenii Stratonikov --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 46168719d9..210ea1dc1f 100755 --- a/Makefile +++ b/Makefile @@ -194,6 +194,8 @@ review-install: @mkdir -p $(GIT_HOOK_DIR)/ @curl -Lo $(GIT_HOOK_DIR)/commit-msg https://review.frostfs.info/tools/hooks/commit-msg @chmod +x $(GIT_HOOK_DIR)/commit-msg + @echo -e '#!/bin/sh\n"$$(git rev-parse --git-path hooks)"/commit-msg "$$1"' >$(GIT_HOOK_DIR)/prepare-commit-msg + @chmod +x $(GIT_HOOK_DIR)/prepare-commit-msg # Create a PR in Gerrit review: BRANCH ?= master From 60cea8c714fcbad23d86143c9c1949b09d5444e6 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Mar 2025 16:22:22 +0300 Subject: [PATCH 1267/1413] [#1692] metabase/test: Fix end of iteration error check This is not good: ``` BenchmarkListWithCursor/1_item-8 --- FAIL: BenchmarkListWithCursor/1_item-8 list_test.go:63: error: end of object listing ``` Change-Id: I61b70937ce30fefaf16ebeb0cdb51bdd39096061 Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/list_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/metabase/list_test.go b/pkg/local_object_storage/metabase/list_test.go index 817b220105..02985991cb 100644 --- a/pkg/local_object_storage/metabase/list_test.go +++ b/pkg/local_object_storage/metabase/list_test.go @@ -59,7 +59,7 @@ func benchmarkListWithCursor(b *testing.B, db *meta.DB, batchSize int) { for range b.N { res, err := db.ListWithCursor(context.Background(), prm) if err != nil { - if errors.Is(err, meta.ErrEndOfListing) { + if !errors.Is(err, meta.ErrEndOfListing) { b.Fatalf("error: %v", err) } prm.SetCursor(nil) From 3f4717a37fbb27ba59cc63065a83bfc18eac7a8b Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Mar 2025 16:35:01 +0300 Subject: [PATCH 1268/1413] [#1692] metabase: Do not allocate map in cache unless needed Change-Id: I8b1015a8c7c3df4153a08fdb788117d9f0d6c333 Signed-off-by: Evgenii Stratonikov --- .../metabase/bucket_cache.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/pkg/local_object_storage/metabase/bucket_cache.go b/pkg/local_object_storage/metabase/bucket_cache.go index 69553d55c3..de1479e6fa 100644 --- a/pkg/local_object_storage/metabase/bucket_cache.go +++ b/pkg/local_object_storage/metabase/bucket_cache.go @@ -14,10 +14,7 @@ type bucketCache struct { } func newBucketCache() *bucketCache { - return &bucketCache{ - expired: make(map[cid.ID]*bbolt.Bucket), - primary: make(map[cid.ID]*bbolt.Bucket), - } + return &bucketCache{} } func getLockedBucket(bc *bucketCache, tx *bbolt.Tx) *bbolt.Bucket { @@ -56,7 +53,7 @@ func getExpiredBucket(bc *bucketCache, tx *bbolt.Tx, cnr cid.ID) *bbolt.Bucket { bucketName = objectToExpirationEpochBucketName(cnr, bucketName) return tx.Bucket(bucketName) } - return getMappedBucket(bc.expired, tx, objectToExpirationEpochBucketName, cnr) + return getMappedBucket(&bc.expired, tx, objectToExpirationEpochBucketName, cnr) } func getPrimaryBucket(bc *bucketCache, tx *bbolt.Tx, cnr cid.ID) *bbolt.Bucket { @@ -65,17 +62,21 @@ func getPrimaryBucket(bc *bucketCache, tx *bbolt.Tx, cnr cid.ID) *bbolt.Bucket { bucketName = primaryBucketName(cnr, bucketName) return tx.Bucket(bucketName) } - return getMappedBucket(bc.primary, tx, primaryBucketName, cnr) + return getMappedBucket(&bc.primary, tx, primaryBucketName, cnr) } -func getMappedBucket(m map[cid.ID]*bbolt.Bucket, tx *bbolt.Tx, nameFunc func(cid.ID, []byte) []byte, cnr cid.ID) *bbolt.Bucket { - value, ok := m[cnr] +func getMappedBucket(m *map[cid.ID]*bbolt.Bucket, tx *bbolt.Tx, nameFunc func(cid.ID, []byte) []byte, cnr cid.ID) *bbolt.Bucket { + value, ok := (*m)[cnr] if ok { return value } + if *m == nil { + *m = make(map[cid.ID]*bbolt.Bucket, 1) + } + bucketName := make([]byte, bucketKeySize) bucketName = nameFunc(cnr, bucketName) - m[cnr] = getBucket(&value, tx, bucketName) + (*m)[cnr] = getBucket(&value, tx, bucketName) return value } From 049a650b89554a1f4f879048edb3555be6b387ec Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 28 Jan 2025 13:29:10 +0300 Subject: [PATCH 1269/1413] [#1619] logger: Simplify `logger` config reloading Change-Id: Ide892b250304b8cdb6c279f5f728c3b35f05df54 Signed-off-by: Anton Nikiforov --- cmd/frostfs-ir/config.go | 6 ++- cmd/frostfs-ir/main.go | 2 +- cmd/frostfs-node/config.go | 41 ++++++++++---------- pkg/services/object/common/writer/ec_test.go | 2 +- pkg/util/logger/logger.go | 40 +++---------------- 5 files changed, 31 insertions(+), 60 deletions(-) diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index 09af085254..19b7f05d67 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -9,6 +9,7 @@ import ( configViper "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/config" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "github.com/spf13/viper" "go.uber.org/zap" ) @@ -38,13 +39,14 @@ func reloadConfig() error { } cmode.Store(cfg.GetBool("node.kludge_compatibility_mode")) audit.Store(cfg.GetBool("audit.enabled")) + var logPrm logger.Prm err = logPrm.SetLevelString(cfg.GetString("logger.level")) if err != nil { return err } - logPrm.PrependTimestamp = cfg.GetBool("logger.timestamp") + log.Reload(logPrm) - return logPrm.Reload() + return nil } func watchForSignal(ctx context.Context, cancel func()) { diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index ade64ba84e..114d8e4de1 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -31,7 +31,6 @@ const ( var ( wg = new(sync.WaitGroup) intErr = make(chan error) // internal inner ring errors - logPrm = new(logger.Prm) innerRing *innerring.Server pprofCmp *pprofComponent metricsCmp *httpComponent @@ -70,6 +69,7 @@ func main() { metrics := irMetrics.NewInnerRingMetrics() + var logPrm logger.Prm err = logPrm.SetLevelString( cfg.GetString("logger.level"), ) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 2531e91739..c3c6877635 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -473,7 +473,6 @@ type shared struct { // dynamicConfiguration stores parameters of the // components that supports runtime reconfigurations. type dynamicConfiguration struct { - logger *logger.Prm pprof *httpComponent metrics *httpComponent } @@ -714,7 +713,8 @@ func initCfg(appCfg *config.Config) *cfg { netState.metrics = c.metricsCollector - logPrm := c.loggerPrm() + logPrm, err := c.loggerPrm() + fatalOnErr(err) logPrm.SamplingHook = c.metricsCollector.LogMetrics().GetSamplingHook() log, err := logger.NewLogger(logPrm) fatalOnErr(err) @@ -1076,26 +1076,22 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID return sh } -func (c *cfg) loggerPrm() *logger.Prm { - // check if it has been inited before - if c.dynamicConfiguration.logger == nil { - c.dynamicConfiguration.logger = new(logger.Prm) - } - +func (c *cfg) loggerPrm() (logger.Prm, error) { + var prm logger.Prm // (re)init read configuration - err := c.dynamicConfiguration.logger.SetLevelString(c.LoggerCfg.level) + err := prm.SetLevelString(c.LoggerCfg.level) if err != nil { // not expected since validation should be performed before - panic("incorrect log level format: " + c.LoggerCfg.level) + return logger.Prm{}, errors.New("incorrect log level format: " + c.LoggerCfg.level) } - err = c.dynamicConfiguration.logger.SetDestination(c.LoggerCfg.destination) + err = prm.SetDestination(c.LoggerCfg.destination) if err != nil { // not expected since validation should be performed before - panic("incorrect log destination format: " + c.LoggerCfg.destination) + return logger.Prm{}, errors.New("incorrect log destination format: " + c.LoggerCfg.destination) } - c.dynamicConfiguration.logger.PrependTimestamp = c.LoggerCfg.timestamp + prm.PrependTimestamp = c.LoggerCfg.timestamp - return c.dynamicConfiguration.logger + return prm, nil } func (c *cfg) LocalAddress() network.AddressGroup { @@ -1335,11 +1331,7 @@ func (c *cfg) reloadConfig(ctx context.Context) { // all the components are expected to support // Logger's dynamic reconfiguration approach - // Logger - - logPrm := c.loggerPrm() - - components := c.getComponents(ctx, logPrm) + components := c.getComponents(ctx) // Object c.cfgObject.tombstoneLifetime.Store(c.ObjectCfg.tombstoneLifetime) @@ -1377,10 +1369,17 @@ func (c *cfg) reloadConfig(ctx context.Context) { c.log.Info(ctx, logs.FrostFSNodeConfigurationHasBeenReloadedSuccessfully) } -func (c *cfg) getComponents(ctx context.Context, logPrm *logger.Prm) []dCmp { +func (c *cfg) getComponents(ctx context.Context) []dCmp { var components []dCmp - components = append(components, dCmp{"logger", logPrm.Reload}) + components = append(components, dCmp{"logger", func() error { + prm, err := c.loggerPrm() + if err != nil { + return err + } + c.log.Reload(prm) + return nil + }}) components = append(components, dCmp{"runtime", func() error { setRuntimeParameters(ctx, c) return nil diff --git a/pkg/services/object/common/writer/ec_test.go b/pkg/services/object/common/writer/ec_test.go index 2458e352f2..d5eeddf21a 100644 --- a/pkg/services/object/common/writer/ec_test.go +++ b/pkg/services/object/common/writer/ec_test.go @@ -130,7 +130,7 @@ func TestECWriter(t *testing.T) { nodeKey, err := keys.NewPrivateKey() require.NoError(t, err) - log, err := logger.NewLogger(nil) + log, err := logger.NewLogger(logger.Prm{}) require.NoError(t, err) var n nmKeys diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index 2eb5e55389..952a6f2dc3 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -23,16 +23,8 @@ type Logger struct { // Parameters that have been connected to the Logger support its // configuration changing. // -// Passing Prm after a successful connection via the NewLogger, connects -// the Prm to a new instance of the Logger. -// -// See also Reload, SetLevelString. +// See also Logger.Reload, SetLevelString. type Prm struct { - // link to the created Logger - // instance; used for a runtime - // reconfiguration - _log *Logger - // support runtime rereading level zapcore.Level @@ -73,22 +65,6 @@ func (p *Prm) SetDestination(d string) error { return nil } -// Reload reloads configuration of a connected instance of the Logger. -// Returns ErrLoggerNotConnected if no connection has been performed. -// Returns any reconfiguration error from the Logger directly. -func (p Prm) Reload() error { - if p._log == nil { - // incorrect logger usage - panic("parameters are not connected to any Logger") - } - - return p._log.reload(p) -} - -func defaultPrm() *Prm { - return new(Prm) -} - // NewLogger constructs a new zap logger instance. Constructing with nil // parameters is safe: default values will be used then. // Passing non-nil parameters after a successful creation (non-error) allows @@ -100,10 +76,7 @@ func defaultPrm() *Prm { // - ISO8601 time encoding. // // Logger records a stack trace for all messages at or above fatal level. -func NewLogger(prm *Prm) (*Logger, error) { - if prm == nil { - prm = defaultPrm() - } +func NewLogger(prm Prm) (*Logger, error) { switch prm.dest { case DestinationUndefined, DestinationStdout: return newConsoleLogger(prm) @@ -114,7 +87,7 @@ func NewLogger(prm *Prm) (*Logger, error) { } } -func newConsoleLogger(prm *Prm) (*Logger, error) { +func newConsoleLogger(prm Prm) (*Logger, error) { lvl := zap.NewAtomicLevelAt(prm.level) c := zap.NewProductionConfig() @@ -139,12 +112,11 @@ func newConsoleLogger(prm *Prm) (*Logger, error) { } l := &Logger{z: lZap, lvl: lvl} - prm._log = l return l, nil } -func newJournaldLogger(prm *Prm) (*Logger, error) { +func newJournaldLogger(prm Prm) (*Logger, error) { lvl := zap.NewAtomicLevelAt(prm.level) c := zap.NewProductionConfig() @@ -181,14 +153,12 @@ func newJournaldLogger(prm *Prm) (*Logger, error) { lZap := zap.New(samplingCore, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), zap.AddCallerSkip(1)) l := &Logger{z: lZap, lvl: lvl} - prm._log = l return l, nil } -func (l *Logger) reload(prm Prm) error { +func (l *Logger) Reload(prm Prm) { l.lvl.SetLevel(prm.level) - return nil } func (l *Logger) WithOptions(options ...zap.Option) { From eea46a599d5e8c07d354900152ba62584b9c8d44 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 21 Mar 2025 11:20:53 +0300 Subject: [PATCH 1270/1413] [#1695] qos: Add treesync tag Tree sync is too much different from GC and rebuild to use the same tag for GC and tree sync. Change-Id: Ib44d5fa9a88daff507d759d0b0410cc9272e236f Signed-off-by: Dmitrii Stepanov --- internal/qos/grpc.go | 4 ++-- internal/qos/limiter.go | 2 +- internal/qos/stats.go | 1 + internal/qos/tags.go | 7 +++++++ internal/qos/validate.go | 1 + pkg/services/tree/service.go | 2 +- 6 files changed, 13 insertions(+), 4 deletions(-) diff --git a/internal/qos/grpc.go b/internal/qos/grpc.go index 534a1f74b1..58cd9e52cd 100644 --- a/internal/qos/grpc.go +++ b/internal/qos/grpc.go @@ -26,7 +26,7 @@ func NewAdjustOutgoingIOTagUnaryClientInterceptor() grpc.UnaryClientInterceptor if err != nil { tag = IOTagClient } - if tag == IOTagBackground || tag == IOTagPolicer || tag == IOTagWritecache { + if tag.IsLocal() { tag = IOTagInternal } ctx = tagging.ContextWithIOTag(ctx, tag.String()) @@ -44,7 +44,7 @@ func NewAdjustOutgoingIOTagStreamClientInterceptor() grpc.StreamClientIntercepto if err != nil { tag = IOTagClient } - if tag == IOTagBackground || tag == IOTagPolicer || tag == IOTagWritecache { + if tag.IsLocal() { tag = IOTagInternal } ctx = tagging.ContextWithIOTag(ctx, tag.String()) diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index e92cef652a..82f9917a5f 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -74,7 +74,7 @@ func createScheduler(config limits.OpConfig) (scheduler, error) { func converToSchedulingTags(limits []limits.IOTagConfig) map[string]scheduling.TagInfo { result := make(map[string]scheduling.TagInfo) - for _, tag := range []IOTag{IOTagClient, IOTagBackground, IOTagInternal, IOTagPolicer, IOTagWritecache} { + for _, tag := range []IOTag{IOTagClient, IOTagBackground, IOTagInternal, IOTagPolicer, IOTagWritecache, IOTagTreeSync} { result[tag.String()] = scheduling.TagInfo{ Share: defaultShare, } diff --git a/internal/qos/stats.go b/internal/qos/stats.go index f077f552ba..aa4d4caf9c 100644 --- a/internal/qos/stats.go +++ b/internal/qos/stats.go @@ -9,6 +9,7 @@ var statTags = map[string]struct{}{ IOTagPolicer.String(): {}, IOTagWritecache.String(): {}, IOTagCritical.String(): {}, + IOTagTreeSync.String(): {}, unknownStatsTag: {}, } diff --git a/internal/qos/tags.go b/internal/qos/tags.go index 9db45f190e..2781dec765 100644 --- a/internal/qos/tags.go +++ b/internal/qos/tags.go @@ -13,6 +13,7 @@ const ( IOTagClient IOTag = "client" IOTagInternal IOTag = "internal" IOTagBackground IOTag = "background" + IOTagTreeSync IOTag = "treesync" IOTagWritecache IOTag = "writecache" IOTagPolicer IOTag = "policer" IOTagCritical IOTag = "critical" @@ -34,6 +35,8 @@ func FromRawString(s string) (IOTag, error) { return IOTagWritecache, nil case string(IOTagPolicer): return IOTagPolicer, nil + case string(IOTagTreeSync): + return IOTagTreeSync, nil default: return ioTagUnknown, fmt.Errorf("unknown tag %s", s) } @@ -50,3 +53,7 @@ func IOTagFromContext(ctx context.Context) string { } return tag } + +func (t IOTag) IsLocal() bool { + return t == IOTagBackground || t == IOTagPolicer || t == IOTagWritecache || t == IOTagTreeSync +} diff --git a/internal/qos/validate.go b/internal/qos/validate.go index 3fa4ebbd17..75bf4f4b9f 100644 --- a/internal/qos/validate.go +++ b/internal/qos/validate.go @@ -47,6 +47,7 @@ func validateTags(configTags []limits.IOTagConfig) error { IOTagBackground: {}, IOTagWritecache: {}, IOTagPolicer: {}, + IOTagTreeSync: {}, } for _, t := range configTags { tag, err := FromRawString(t.Tag) diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index eeffec08b1..b9bb96bab9 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -85,7 +85,7 @@ func New(opts ...Option) *Service { // Start starts the service. func (s *Service) Start(ctx context.Context) { - ctx = tagging.ContextWithIOTag(ctx, qos.IOTagBackground.String()) + ctx = tagging.ContextWithIOTag(ctx, qos.IOTagTreeSync.String()) go s.replicateLoop(ctx) go s.syncLoop(ctx) From 5385f9994fd4decefbbdd82a85aecedb55671872 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 21 Mar 2025 11:59:25 +0300 Subject: [PATCH 1271/1413] [#1695] mod: Bump frostfs-observability version Change-Id: Id362b71f743ff70c8cd374030c9fa67e2566022f Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/internal/client/sdk.go | 2 +- cmd/frostfs-cli/modules/tree/client.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- pkg/network/cache/multi.go | 2 +- pkg/services/tree/cache.go | 2 +- pkg/services/tree/sync.go | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-cli/internal/client/sdk.go b/cmd/frostfs-cli/internal/client/sdk.go index 2d9c45cbd9..1eadfa2e15 100644 --- a/cmd/frostfs-cli/internal/client/sdk.go +++ b/cmd/frostfs-cli/internal/client/sdk.go @@ -56,7 +56,7 @@ func GetSDKClient(ctx context.Context, cmd *cobra.Command, key *ecdsa.PrivateKey prmDial := client.PrmDial{ Endpoint: addr.URIAddr(), GRPCDialOptions: []grpc.DialOption{ - grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInteceptor()), + grpc.WithChainUnaryInterceptor(tracing.NewUnaryClientInterceptor()), grpc.WithChainStreamInterceptor(tracing.NewStreamClientInterceptor()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), }, diff --git a/cmd/frostfs-cli/modules/tree/client.go b/cmd/frostfs-cli/modules/tree/client.go index 933378df6b..421b96ccdd 100644 --- a/cmd/frostfs-cli/modules/tree/client.go +++ b/cmd/frostfs-cli/modules/tree/client.go @@ -33,7 +33,7 @@ func _client() (tree.TreeServiceClient, error) { opts := []grpc.DialOption{ grpc.WithChainUnaryInterceptor( - tracing.NewUnaryClientInteceptor(), + tracing.NewUnaryClientInterceptor(), ), grpc.WithChainStreamInterceptor( tracing.NewStreamClientInterceptor(), diff --git a/go.mod b/go.mod index eeaca1645b..fafb4f8280 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d - git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 + git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 git.frostfs.info/TrueCloudLab/hrw v1.2.1 diff --git a/go.sum b/go.sum index a8f7216a54..7818583d4f 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSV git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824 h1:Mxw1c/8t96vFIUOffl28lFaHKi413oCBfLMGJmF9cFA= -git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250212111929-d34e1329c824/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 h1:fluzML8BIIabd07LyPSjc0JAV2qymWkPiFaLrXdALLA= +git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529 h1:CBreXSxGoYJAdZ1QdJPsDs1UCXGF5psinII0lxtohsc= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 h1:svCl6NDAPZ/KuQPjdVKo74RkCIANesxUPM45zQZDhSw= diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index e94fa580a6..77420865a4 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -66,7 +66,7 @@ func (x *multiClient) createForAddress(ctx context.Context, addr network.Address grpc.WithChainUnaryInterceptor( qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), - tracing.NewUnaryClientInteceptor(), + tracing.NewUnaryClientInterceptor(), tagging.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index 70f4a843ba..3359af2c55 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -99,7 +99,7 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* grpc.WithChainUnaryInterceptor( qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), - tracing.NewUnaryClientInteceptor(), + tracing.NewUnaryClientInterceptor(), tagging.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 89450b7397..103e2a6132 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -344,7 +344,7 @@ func (*Service) createConnection(a network.Address) (*grpc.ClientConn, error) { grpc.WithChainUnaryInterceptor( qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), - tracing_grpc.NewUnaryClientInteceptor(), + tracing_grpc.NewUnaryClientInterceptor(), tagging.NewUnaryClientInteceptor(), ), grpc.WithChainStreamInterceptor( From 3fa5c22ddfc036a414e66fb0e89c816e44a677dc Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 13:18:18 +0300 Subject: [PATCH 1272/1413] [#1689] Makefile: Add default reviewers via --push-option Gerrit doesn't provide an easy way to have default reviewers assigned to new change requests. However, we can use `--push-option` and mention all people from storage-core-developers group. Change-Id: Ia01f8a3c5c8eb8a1dca6efb66fbe07018f6a42c9 Signed-off-by: Evgenii Stratonikov --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 210ea1dc1f..c9147f5119 100755 --- a/Makefile +++ b/Makefile @@ -200,7 +200,14 @@ review-install: # Create a PR in Gerrit review: BRANCH ?= master review: - @git push review HEAD:refs/for/$(BRANCH) + @git push review HEAD:refs/for/$(BRANCH) \ + --push-option r=e.stratonikov@yadro.com \ + --push-option r=d.stepanov@yadro.com \ + --push-option r=an.nikiforov@yadro.com \ + --push-option r=a.arifullin@yadro.com \ + --push-option r=ekaterina.lebedeva@yadro.com \ + --push-option r=a.savchuk@yadro.com \ + --push-option r=a.chuprov@yadro.com # Run pre-commit pre-commit-run: From af76350bfb2eaabb22ad19fccf1412d26a226004 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 21 Mar 2025 13:19:28 +0300 Subject: [PATCH 1273/1413] [#1695] qos: Sort tags by asc Change-Id: Ia23e392bb49d2536096de2ba07fc6f8fb7ac0489 Signed-off-by: Dmitrii Stepanov --- internal/qos/limiter.go | 2 +- internal/qos/stats.go | 6 +++--- internal/qos/tags.go | 24 ++++++++++++------------ internal/qos/validate.go | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index 82f9917a5f..98d254fd0f 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -74,7 +74,7 @@ func createScheduler(config limits.OpConfig) (scheduler, error) { func converToSchedulingTags(limits []limits.IOTagConfig) map[string]scheduling.TagInfo { result := make(map[string]scheduling.TagInfo) - for _, tag := range []IOTag{IOTagClient, IOTagBackground, IOTagInternal, IOTagPolicer, IOTagWritecache, IOTagTreeSync} { + for _, tag := range []IOTag{IOTagBackground, IOTagClient, IOTagInternal, IOTagPolicer, IOTagTreeSync, IOTagWritecache} { result[tag.String()] = scheduling.TagInfo{ Share: defaultShare, } diff --git a/internal/qos/stats.go b/internal/qos/stats.go index aa4d4caf9c..3ecfad9f92 100644 --- a/internal/qos/stats.go +++ b/internal/qos/stats.go @@ -3,13 +3,13 @@ package qos const unknownStatsTag = "unknown" var statTags = map[string]struct{}{ - IOTagClient.String(): {}, IOTagBackground.String(): {}, + IOTagClient.String(): {}, + IOTagCritical.String(): {}, IOTagInternal.String(): {}, IOTagPolicer.String(): {}, - IOTagWritecache.String(): {}, - IOTagCritical.String(): {}, IOTagTreeSync.String(): {}, + IOTagWritecache.String(): {}, unknownStatsTag: {}, } diff --git a/internal/qos/tags.go b/internal/qos/tags.go index 2781dec765..e3f7cafd6f 100644 --- a/internal/qos/tags.go +++ b/internal/qos/tags.go @@ -10,33 +10,33 @@ import ( type IOTag string const ( - IOTagClient IOTag = "client" - IOTagInternal IOTag = "internal" IOTagBackground IOTag = "background" + IOTagClient IOTag = "client" + IOTagCritical IOTag = "critical" + IOTagInternal IOTag = "internal" + IOTagPolicer IOTag = "policer" IOTagTreeSync IOTag = "treesync" IOTagWritecache IOTag = "writecache" - IOTagPolicer IOTag = "policer" - IOTagCritical IOTag = "critical" ioTagUnknown IOTag = "" ) func FromRawString(s string) (IOTag, error) { switch s { - case string(IOTagCritical): - return IOTagCritical, nil - case string(IOTagClient): - return IOTagClient, nil - case string(IOTagInternal): - return IOTagInternal, nil case string(IOTagBackground): return IOTagBackground, nil - case string(IOTagWritecache): - return IOTagWritecache, nil + case string(IOTagClient): + return IOTagClient, nil + case string(IOTagCritical): + return IOTagCritical, nil + case string(IOTagInternal): + return IOTagInternal, nil case string(IOTagPolicer): return IOTagPolicer, nil case string(IOTagTreeSync): return IOTagTreeSync, nil + case string(IOTagWritecache): + return IOTagWritecache, nil default: return ioTagUnknown, fmt.Errorf("unknown tag %s", s) } diff --git a/internal/qos/validate.go b/internal/qos/validate.go index 75bf4f4b9f..d4475e38ba 100644 --- a/internal/qos/validate.go +++ b/internal/qos/validate.go @@ -42,12 +42,12 @@ func validateOpConfig(c limits.OpConfig) error { func validateTags(configTags []limits.IOTagConfig) error { tags := map[IOTag]tagConfig{ + IOTagBackground: {}, IOTagClient: {}, IOTagInternal: {}, - IOTagBackground: {}, - IOTagWritecache: {}, IOTagPolicer: {}, IOTagTreeSync: {}, + IOTagWritecache: {}, } for _, t := range configTags { tag, err := FromRawString(t.Tag) From 9aa486c9d814d3feed94a99d24aa1914a57b17fa Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 14:10:46 +0300 Subject: [PATCH 1274/1413] [#1689] Makefile: Create dirs with -p flag On CI there is no `bin` directory initially, so an error occurs ``` mkdir: cannot create directory '/var/cache/jenkins-agent/workspace/gerrit/frostfs-node#55-488b12-8ac3c/bin/gofumpt': No such file or directory ``` Change-Id: I43895c8f5ed7cc5c71c8025228710279f9e75e9c Signed-off-by: Evgenii Stratonikov --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c9147f5119..2c1cf89f77 100755 --- a/Makefile +++ b/Makefile @@ -115,7 +115,7 @@ protoc: # Install protoc protoc-install: @rm -rf $(PROTOBUF_DIR) - @mkdir $(PROTOBUF_DIR) + @mkdir -p $(PROTOBUF_DIR) @echo "⇒ Installing protoc... " @wget -q -O $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip 'https://github.com/protocolbuffers/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-$(PROTOC_OS_VERSION).zip' @unzip -q -o $(PROTOBUF_DIR)/protoc-$(PROTOC_VERSION).zip -d $(PROTOC_DIR) @@ -169,7 +169,7 @@ imports: # Install gofumpt fumpt-install: @rm -rf $(GOFUMPT_DIR) - @mkdir $(GOFUMPT_DIR) + @mkdir -p $(GOFUMPT_DIR) @GOBIN=$(GOFUMPT_VERSION_DIR) go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION) # Run gofumpt @@ -214,9 +214,9 @@ pre-commit-run: @pre-commit run -a --hook-stage manual # Install linters -lint-install: +lint-install: $(BIN) @rm -rf $(OUTPUT_LINT_DIR) - @mkdir $(OUTPUT_LINT_DIR) + @mkdir -p $(OUTPUT_LINT_DIR) @mkdir -p $(TMP_DIR) @rm -rf $(TMP_DIR)/linters @git -c advice.detachedHead=false clone --branch v$(TRUECLOUDLAB_LINT_VERSION) https://git.frostfs.info/TrueCloudLab/linters.git $(TMP_DIR)/linters @@ -235,7 +235,7 @@ lint: # Install staticcheck staticcheck-install: @rm -rf $(STATICCHECK_DIR) - @mkdir $(STATICCHECK_DIR) + @mkdir -p $(STATICCHECK_DIR) @GOBIN=$(STATICCHECK_VERSION_DIR) go install honnef.co/go/tools/cmd/staticcheck@$(STATICCHECK_VERSION) # Run staticcheck @@ -248,7 +248,7 @@ staticcheck-run: # Install gopls gopls-install: @rm -rf $(GOPLS_DIR) - @mkdir $(GOPLS_DIR) + @mkdir -p $(GOPLS_DIR) @GOBIN=$(GOPLS_VERSION_DIR) go install golang.org/x/tools/gopls@$(GOPLS_VERSION) # Run gopls From 016f2e11e371b8cbb5b6459aed33b2e3c962fc3e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 14:38:18 +0300 Subject: [PATCH 1275/1413] [#1689] Makefile: Add more restricted .SHELLFLAGS Catch more errors immediately. Change-Id: I576f1b394a2b167c78c693a794ab8cca3ac1013b Signed-off-by: Evgenii Stratonikov --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 2c1cf89f77..321365f0d4 100755 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ #!/usr/bin/make -f SHELL = bash +.SHELLFLAGS = -euo pipefail -c REPO ?= $(shell go list -m) VERSION ?= $(shell git describe --tags --dirty --match "v*" --always --abbrev=8 2>/dev/null || cat VERSION 2>/dev/null || echo "develop") From d95128913123f7c3c1fbc31c79ade0d54594b2e5 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 4 Mar 2025 19:41:53 +0300 Subject: [PATCH 1276/1413] [#1294] docs: Fix description of shard switching mode Signed-off-by: Alexander Chuprov --- docs/shard-modes.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/shard-modes.md b/docs/shard-modes.md index 3b459335b8..6cc4ab13c8 100644 --- a/docs/shard-modes.md +++ b/docs/shard-modes.md @@ -51,10 +51,7 @@ However, all mode changing operations are idempotent. ## Automatic mode changes -Shard can automatically switch to a `degraded-read-only` mode in 3 cases: -1. If the metabase was not available or couldn't be opened/initialized during shard startup. -2. If shard error counter exceeds threshold. -3. If the metabase couldn't be reopened during SIGHUP handling. +A shard can automatically switch to `read-only` mode if its error counter exceeds the threshold. # Detach shard From 4919b6a206ad9f448fcb36ae7d574a8f7dd3ad59 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 21 Mar 2025 15:51:22 +0300 Subject: [PATCH 1277/1413] [#1689] node/config: Allow zero `max_ops` in RPC limits config The limiter allows zeros for limits, meaning "this operation is disabled". However, the config didn't allow zero due to the lack of distinction between "no value" and "zero" - cast functions read both `nil` and zero as zero. Now, the config allows a zero limit. Added tests. Managing such cases should be easier after #1610. Change-Id: Ifc840732390b2feb975f230573b34bf479406e05 Signed-off-by: Aleksey Savchuk --- cmd/frostfs-node/config/rpc/config.go | 5 ++-- cmd/frostfs-node/config/rpc/config_test.go | 26 ++++++++++++++++++- .../rpc/testdata/{node.env => no_max_ops.env} | 0 .../testdata/{node.json => no_max_ops.json} | 0 .../testdata/{node.yaml => no_max_ops.yaml} | 0 .../config/rpc/testdata/zero_max_ops.env | 4 +++ .../config/rpc/testdata/zero_max_ops.json | 19 ++++++++++++++ .../config/rpc/testdata/zero_max_ops.yaml | 9 +++++++ 8 files changed, 59 insertions(+), 4 deletions(-) rename cmd/frostfs-node/config/rpc/testdata/{node.env => no_max_ops.env} (100%) rename cmd/frostfs-node/config/rpc/testdata/{node.json => no_max_ops.json} (100%) rename cmd/frostfs-node/config/rpc/testdata/{node.yaml => no_max_ops.yaml} (100%) create mode 100644 cmd/frostfs-node/config/rpc/testdata/zero_max_ops.env create mode 100644 cmd/frostfs-node/config/rpc/testdata/zero_max_ops.json create mode 100644 cmd/frostfs-node/config/rpc/testdata/zero_max_ops.yaml diff --git a/cmd/frostfs-node/config/rpc/config.go b/cmd/frostfs-node/config/rpc/config.go index 197990d07b..e0efdfde23 100644 --- a/cmd/frostfs-node/config/rpc/config.go +++ b/cmd/frostfs-node/config/rpc/config.go @@ -31,12 +31,11 @@ func Limits(c *config.Config) []LimitConfig { break } - maxOps := config.IntSafe(sc, "max_ops") - if maxOps == 0 { + if sc.Value("max_ops") == nil { panic("no max operations for method group") } - limits = append(limits, LimitConfig{methods, maxOps}) + limits = append(limits, LimitConfig{methods, config.IntSafe(sc, "max_ops")}) } return limits diff --git a/cmd/frostfs-node/config/rpc/config_test.go b/cmd/frostfs-node/config/rpc/config_test.go index 31a837cee2..a6365e19f9 100644 --- a/cmd/frostfs-node/config/rpc/config_test.go +++ b/cmd/frostfs-node/config/rpc/config_test.go @@ -38,7 +38,7 @@ func TestRPCSection(t *testing.T) { }) t.Run("no max operations", func(t *testing.T) { - const path = "testdata/node" + const path = "testdata/no_max_ops" fileConfigTest := func(c *config.Config) { require.Panics(t, func() { _ = Limits(c) }) @@ -50,4 +50,28 @@ func TestRPCSection(t *testing.T) { configtest.ForEnvFileType(t, path, fileConfigTest) }) }) + + t.Run("zero max operations", func(t *testing.T) { + const path = "testdata/zero_max_ops" + + fileConfigTest := func(c *config.Config) { + limits := Limits(c) + require.Len(t, limits, 2) + + limit0 := limits[0] + limit1 := limits[1] + + require.ElementsMatch(t, limit0.Methods, []string{"/neo.fs.v2.object.ObjectService/PutSingle", "/neo.fs.v2.object.ObjectService/Put"}) + require.Equal(t, limit0.MaxOps, int64(0)) + + require.ElementsMatch(t, limit1.Methods, []string{"/neo.fs.v2.object.ObjectService/Get"}) + require.Equal(t, limit1.MaxOps, int64(10000)) + } + + configtest.ForEachFileType(path, fileConfigTest) + + t.Run("ENV", func(t *testing.T) { + configtest.ForEnvFileType(t, path, fileConfigTest) + }) + }) } diff --git a/cmd/frostfs-node/config/rpc/testdata/node.env b/cmd/frostfs-node/config/rpc/testdata/no_max_ops.env similarity index 100% rename from cmd/frostfs-node/config/rpc/testdata/node.env rename to cmd/frostfs-node/config/rpc/testdata/no_max_ops.env diff --git a/cmd/frostfs-node/config/rpc/testdata/node.json b/cmd/frostfs-node/config/rpc/testdata/no_max_ops.json similarity index 100% rename from cmd/frostfs-node/config/rpc/testdata/node.json rename to cmd/frostfs-node/config/rpc/testdata/no_max_ops.json diff --git a/cmd/frostfs-node/config/rpc/testdata/node.yaml b/cmd/frostfs-node/config/rpc/testdata/no_max_ops.yaml similarity index 100% rename from cmd/frostfs-node/config/rpc/testdata/node.yaml rename to cmd/frostfs-node/config/rpc/testdata/no_max_ops.yaml diff --git a/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.env b/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.env new file mode 100644 index 0000000000..ce7302b0b9 --- /dev/null +++ b/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.env @@ -0,0 +1,4 @@ +FROSTFS_RPC_LIMITS_0_METHODS="/neo.fs.v2.object.ObjectService/PutSingle /neo.fs.v2.object.ObjectService/Put" +FROSTFS_RPC_LIMITS_0_MAX_OPS=0 +FROSTFS_RPC_LIMITS_1_METHODS="/neo.fs.v2.object.ObjectService/Get" +FROSTFS_RPC_LIMITS_1_MAX_OPS=10000 diff --git a/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.json b/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.json new file mode 100644 index 0000000000..16a1c173f5 --- /dev/null +++ b/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.json @@ -0,0 +1,19 @@ +{ + "rpc": { + "limits": [ + { + "methods": [ + "/neo.fs.v2.object.ObjectService/PutSingle", + "/neo.fs.v2.object.ObjectService/Put" + ], + "max_ops": 0 + }, + { + "methods": [ + "/neo.fs.v2.object.ObjectService/Get" + ], + "max_ops": 10000 + } + ] + } +} diff --git a/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.yaml b/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.yaml new file mode 100644 index 0000000000..525d768d48 --- /dev/null +++ b/cmd/frostfs-node/config/rpc/testdata/zero_max_ops.yaml @@ -0,0 +1,9 @@ +rpc: + limits: + - methods: + - /neo.fs.v2.object.ObjectService/PutSingle + - /neo.fs.v2.object.ObjectService/Put + max_ops: 0 + - methods: + - /neo.fs.v2.object.ObjectService/Get + max_ops: 10000 From e7e91ef63407d4946f70ffa746e33d79cfea1999 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 16:31:20 +0300 Subject: [PATCH 1278/1413] [#1689] adm: Remove storagecfg subcommand It is unused and unsupported for a long time. Change-Id: I570567db4e8cb202e41286064406ad85cd0e7a39 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/root.go | 2 - .../internal/modules/storagecfg/config.go | 135 ------ .../internal/modules/storagecfg/root.go | 432 ------------------ 3 files changed, 569 deletions(-) delete mode 100644 cmd/frostfs-adm/internal/modules/storagecfg/config.go delete mode 100644 cmd/frostfs-adm/internal/modules/storagecfg/root.go diff --git a/cmd/frostfs-adm/internal/modules/root.go b/cmd/frostfs-adm/internal/modules/root.go index defd898c8d..e42204b7a3 100644 --- a/cmd/frostfs-adm/internal/modules/root.go +++ b/cmd/frostfs-adm/internal/modules/root.go @@ -7,7 +7,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/storagecfg" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/autocomplete" utilConfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config" @@ -41,7 +40,6 @@ func init() { rootCmd.AddCommand(config.RootCmd) rootCmd.AddCommand(morph.RootCmd) - rootCmd.AddCommand(storagecfg.RootCmd) rootCmd.AddCommand(metabase.RootCmd) rootCmd.AddCommand(autocomplete.Command("frostfs-adm")) diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/config.go b/cmd/frostfs-adm/internal/modules/storagecfg/config.go deleted file mode 100644 index 67e3414c25..0000000000 --- a/cmd/frostfs-adm/internal/modules/storagecfg/config.go +++ /dev/null @@ -1,135 +0,0 @@ -package storagecfg - -const configTemplate = `logger: - level: info # logger level: one of "debug", "info" (default), "warn", "error", "dpanic", "panic", "fatal" - -node: - wallet: - path: {{ .Wallet.Path }} # path to a NEO wallet; ignored if key is presented - address: {{ .Wallet.Account }} # address of a NEO account in the wallet; ignored if key is presented - password: {{ .Wallet.Password }} # password for a NEO account in the wallet; ignored if key is presented - addresses: # list of addresses announced by Storage node in the Network map - - {{ .AnnouncedAddress }} - attribute_0: UN-LOCODE:{{ .Attribute.Locode }} - relay: {{ .Relay }} # start Storage node in relay mode without bootstrapping into the Network map - -grpc: - num: 1 # total number of listener endpoints - 0: - endpoint: {{ .Endpoint }} # endpoint for gRPC server - tls:{{if .TLSCert}} - enabled: true # enable TLS for a gRPC connection (min version is TLS 1.2) - certificate: {{ .TLSCert }} # path to TLS certificate - key: {{ .TLSKey }} # path to TLS key - {{- else }} - enabled: false # disable TLS for a gRPC connection - {{- end}} - -control: - authorized_keys: # list of hex-encoded public keys that have rights to use the Control Service - {{- range .AuthorizedKeys }} - - {{.}}{{end}} - grpc: - endpoint: {{.ControlEndpoint}} # endpoint that is listened by the Control Service - -morph: - dial_timeout: 20s # timeout for side chain NEO RPC client connection - cache_ttl: 15s # use TTL cache for side chain GET operations - rpc_endpoint: # side chain N3 RPC endpoints - {{- range .MorphRPC }} - - address: wss://{{.}}/ws{{end}} -{{if not .Relay }} -storage: - shard: - default: # section with the default shard parameters - metabase: - perm: 0644 # permissions for metabase files(directories: +x for current user and group) - - blobstor: - perm: 0644 # permissions for blobstor files(directories: +x for current user and group) - depth: 2 # max depth of object tree storage in FS - small_object_size: 102400 # 100KiB, size threshold for "small" objects which are stored in key-value DB, not in FS, bytes - compress: true # turn on/off Zstandard compression (level 3) of stored objects - compression_exclude_content_types: - - audio/* - - video/* - - blobovnicza: - size: 1073741824 # approximate size limit of single blobovnicza instance, total size will be: size*width^(depth+1), bytes - depth: 1 # max depth of object tree storage in key-value DB - width: 4 # max width of object tree storage in key-value DB - opened_cache_capacity: 50 # maximum number of opened database files - opened_cache_ttl: 5m # ttl for opened database file - opened_cache_exp_interval: 15s # cache cleanup interval for expired blobovnicza's - - gc: - remover_batch_size: 200 # number of objects to be removed by the garbage collector - remover_sleep_interval: 5m # frequency of the garbage collector invocation - 0: - mode: "read-write" # mode of the shard, must be one of the: "read-write" (default), "read-only" - - metabase: - path: {{ .MetabasePath }} # path to the metabase - - blobstor: - path: {{ .BlobstorPath }} # path to the blobstor -{{end}}` - -const ( - neofsMainnetAddress = "2cafa46838e8b564468ebd868dcafdd99dce6221" - balanceMainnetAddress = "dc1ec98d9d0c5f9dfade16144defe08cffc5ca55" - neofsTestnetAddress = "b65d8243ac63983206d17e5221af0653a7266fa1" - balanceTestnetAddress = "e0420c216003747626670d1424569c17c79015bf" -) - -var n3config = map[string]struct { - MorphRPC []string - RPC []string - NeoFSContract string - BalanceContract string -}{ - "testnet": { - MorphRPC: []string{ - "rpc01.morph.testnet.fs.neo.org:51331", - "rpc02.morph.testnet.fs.neo.org:51331", - "rpc03.morph.testnet.fs.neo.org:51331", - "rpc04.morph.testnet.fs.neo.org:51331", - "rpc05.morph.testnet.fs.neo.org:51331", - "rpc06.morph.testnet.fs.neo.org:51331", - "rpc07.morph.testnet.fs.neo.org:51331", - }, - RPC: []string{ - "rpc01.testnet.n3.nspcc.ru:21331", - "rpc02.testnet.n3.nspcc.ru:21331", - "rpc03.testnet.n3.nspcc.ru:21331", - "rpc04.testnet.n3.nspcc.ru:21331", - "rpc05.testnet.n3.nspcc.ru:21331", - "rpc06.testnet.n3.nspcc.ru:21331", - "rpc07.testnet.n3.nspcc.ru:21331", - }, - NeoFSContract: neofsTestnetAddress, - BalanceContract: balanceTestnetAddress, - }, - "mainnet": { - MorphRPC: []string{ - "rpc1.morph.fs.neo.org:40341", - "rpc2.morph.fs.neo.org:40341", - "rpc3.morph.fs.neo.org:40341", - "rpc4.morph.fs.neo.org:40341", - "rpc5.morph.fs.neo.org:40341", - "rpc6.morph.fs.neo.org:40341", - "rpc7.morph.fs.neo.org:40341", - }, - RPC: []string{ - "rpc1.n3.nspcc.ru:10331", - "rpc2.n3.nspcc.ru:10331", - "rpc3.n3.nspcc.ru:10331", - "rpc4.n3.nspcc.ru:10331", - "rpc5.n3.nspcc.ru:10331", - "rpc6.n3.nspcc.ru:10331", - "rpc7.n3.nspcc.ru:10331", - }, - NeoFSContract: neofsMainnetAddress, - BalanceContract: balanceMainnetAddress, - }, -} diff --git a/cmd/frostfs-adm/internal/modules/storagecfg/root.go b/cmd/frostfs-adm/internal/modules/storagecfg/root.go deleted file mode 100644 index a5adea0da7..0000000000 --- a/cmd/frostfs-adm/internal/modules/storagecfg/root.go +++ /dev/null @@ -1,432 +0,0 @@ -package storagecfg - -import ( - "bytes" - "context" - "encoding/hex" - "errors" - "fmt" - "math/rand" - "net" - "net/url" - "os" - "path/filepath" - "slices" - "strconv" - "strings" - "text/template" - "time" - - netutil "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - "github.com/chzyer/readline" - "github.com/nspcc-dev/neo-go/cli/flags" - "github.com/nspcc-dev/neo-go/cli/input" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/gas" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" - "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/wallet" - "github.com/spf13/cobra" -) - -const ( - walletFlag = "wallet" - accountFlag = "account" -) - -const ( - defaultControlEndpoint = "localhost:8090" - defaultDataEndpoint = "localhost" -) - -// RootCmd is a root command of config section. -var RootCmd = &cobra.Command{ - Use: "storage-config [-w wallet] [-a acccount] []", - Short: "Section for storage node configuration commands", - Run: storageConfig, -} - -func init() { - fs := RootCmd.Flags() - - fs.StringP(walletFlag, "w", "", "Path to wallet") - fs.StringP(accountFlag, "a", "", "Wallet account") -} - -type config struct { - AnnouncedAddress string - AuthorizedKeys []string - ControlEndpoint string - Endpoint string - TLSCert string - TLSKey string - MorphRPC []string - Attribute struct { - Locode string - } - Wallet struct { - Path string - Account string - Password string - } - Relay bool - BlobstorPath string - MetabasePath string -} - -func storageConfig(cmd *cobra.Command, args []string) { - outPath := getOutputPath(args) - - historyPath := filepath.Join(os.TempDir(), "frostfs-adm.history") - readline.SetHistoryPath(historyPath) - - var c config - - c.Wallet.Path, _ = cmd.Flags().GetString(walletFlag) - if c.Wallet.Path == "" { - c.Wallet.Path = getPath("Path to the storage node wallet: ") - } - - w, err := wallet.NewWalletFromFile(c.Wallet.Path) - fatalOnErr(err) - - fillWalletAccount(cmd, &c, w) - - accH, err := flags.ParseAddress(c.Wallet.Account) - fatalOnErr(err) - - acc := w.GetAccount(accH) - if acc == nil { - fatalOnErr(errors.New("can't find account in wallet")) - } - - c.Wallet.Password, err = input.ReadPassword(fmt.Sprintf("Enter password for %s > ", c.Wallet.Account)) - fatalOnErr(err) - - err = acc.Decrypt(c.Wallet.Password, keys.NEP2ScryptParams()) - fatalOnErr(err) - - c.AuthorizedKeys = append(c.AuthorizedKeys, hex.EncodeToString(acc.PrivateKey().PublicKey().Bytes())) - - network := readNetwork(cmd) - - c.MorphRPC = n3config[network].MorphRPC - - depositGas(cmd, acc, network) - - c.Attribute.Locode = getString("UN-LOCODE attribute in [XX YYY] format: ") - - endpoint := getDefaultEndpoint(cmd, &c) - c.Endpoint = getString(fmt.Sprintf("Listening address [%s]: ", endpoint)) - if c.Endpoint == "" { - c.Endpoint = endpoint - } - - c.ControlEndpoint = getString(fmt.Sprintf("Listening address (control endpoint) [%s]: ", defaultControlEndpoint)) - if c.ControlEndpoint == "" { - c.ControlEndpoint = defaultControlEndpoint - } - - c.TLSCert = getPath("TLS Certificate (optional): ") - if c.TLSCert != "" { - c.TLSKey = getPath("TLS Key: ") - } - - c.Relay = getConfirmation(false, "Use node as a relay? yes/[no]: ") - if !c.Relay { - p := getPath("Path to the storage directory (all available storage will be used): ") - c.BlobstorPath = filepath.Join(p, "blob") - c.MetabasePath = filepath.Join(p, "meta") - } - - out := applyTemplate(c) - fatalOnErr(os.WriteFile(outPath, out, 0o644)) - - cmd.Println("Node is ready for work! Run `frostfs-node -config " + outPath + "`") -} - -func getDefaultEndpoint(cmd *cobra.Command, c *config) string { - var addr, port string - for { - c.AnnouncedAddress = getString("Publicly announced address: ") - validator := netutil.Address{} - err := validator.FromString(c.AnnouncedAddress) - if err != nil { - cmd.Println("Incorrect address format. See https://git.frostfs.info/TrueCloudLab/frostfs-node/src/branch/master/pkg/network/address.go for details.") - continue - } - uriAddr, err := url.Parse(validator.URIAddr()) - if err != nil { - panic(fmt.Errorf("unexpected error: %w", err)) - } - addr = uriAddr.Hostname() - port = uriAddr.Port() - ip, err := net.ResolveIPAddr("ip", addr) - if err != nil { - cmd.Printf("Can't resolve IP address %s: %v\n", addr, err) - continue - } - - if !ip.IP.IsGlobalUnicast() { - cmd.Println("IP must be global unicast.") - continue - } - cmd.Printf("Resolved IP address: %s\n", ip.String()) - - _, err = strconv.ParseUint(port, 10, 16) - if err != nil { - cmd.Println("Port must be an integer.") - continue - } - - break - } - return net.JoinHostPort(defaultDataEndpoint, port) -} - -func fillWalletAccount(cmd *cobra.Command, c *config, w *wallet.Wallet) { - c.Wallet.Account, _ = cmd.Flags().GetString(accountFlag) - if c.Wallet.Account == "" { - addr := address.Uint160ToString(w.GetChangeAddress()) - c.Wallet.Account = getWalletAccount(w, fmt.Sprintf("Wallet account [%s]: ", addr)) - if c.Wallet.Account == "" { - c.Wallet.Account = addr - } - } -} - -func readNetwork(cmd *cobra.Command) string { - var network string - for { - network = getString("Choose network [mainnet]/testnet: ") - switch network { - case "": - network = "mainnet" - case "testnet", "mainnet": - default: - cmd.Println(`Network must be either "mainnet" or "testnet"`) - continue - } - break - } - return network -} - -func getOutputPath(args []string) string { - if len(args) != 0 { - return args[0] - } - outPath := getPath("File to write config at [./config.yml]: ") - if outPath == "" { - outPath = "./config.yml" - } - return outPath -} - -func getWalletAccount(w *wallet.Wallet, prompt string) string { - addrs := make([]readline.PrefixCompleterInterface, len(w.Accounts)) - for i := range w.Accounts { - addrs[i] = readline.PcItem(w.Accounts[i].Address) - } - - readline.SetAutoComplete(readline.NewPrefixCompleter(addrs...)) - defer readline.SetAutoComplete(nil) - - s, err := readline.Line(prompt) - fatalOnErr(err) - return strings.TrimSpace(s) // autocompleter can return a string with a trailing space -} - -func getString(prompt string) string { - s, err := readline.Line(prompt) - fatalOnErr(err) - if s != "" { - _ = readline.AddHistory(s) - } - return s -} - -type filenameCompleter struct{} - -func (filenameCompleter) Do(line []rune, pos int) (newLine [][]rune, length int) { - prefix := string(line[:pos]) - dir := filepath.Dir(prefix) - de, err := os.ReadDir(dir) - if err != nil { - return nil, 0 - } - - for i := range de { - name := filepath.Join(dir, de[i].Name()) - if strings.HasPrefix(name, prefix) { - tail := []rune(strings.TrimPrefix(name, prefix)) - if de[i].IsDir() { - tail = append(tail, filepath.Separator) - } - newLine = append(newLine, tail) - } - } - if pos != 0 { - return newLine, pos - len([]rune(dir)) - } - return newLine, 0 -} - -func getPath(prompt string) string { - readline.SetAutoComplete(filenameCompleter{}) - defer readline.SetAutoComplete(nil) - - p, err := readline.Line(prompt) - fatalOnErr(err) - - if p == "" { - return p - } - - _ = readline.AddHistory(p) - - abs, err := filepath.Abs(p) - if err != nil { - fatalOnErr(fmt.Errorf("can't create an absolute path: %w", err)) - } - - return abs -} - -func getConfirmation(def bool, prompt string) bool { - for { - s, err := readline.Line(prompt) - fatalOnErr(err) - - switch strings.ToLower(s) { - case "y", "yes": - return true - case "n", "no": - return false - default: - if len(s) == 0 { - return def - } - } - } -} - -func applyTemplate(c config) []byte { - tmpl, err := template.New("config").Parse(configTemplate) - fatalOnErr(err) - - b := bytes.NewBuffer(nil) - fatalOnErr(tmpl.Execute(b, c)) - - return b.Bytes() -} - -func fatalOnErr(err error) { - if err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } -} - -func depositGas(cmd *cobra.Command, acc *wallet.Account, network string) { - sideClient := initClient(n3config[network].MorphRPC) - balanceHash, _ := util.Uint160DecodeStringLE(n3config[network].BalanceContract) - - sideActor, err := actor.NewSimple(sideClient, acc) - if err != nil { - fatalOnErr(fmt.Errorf("creating actor over side chain client: %w", err)) - } - - sideGas := nep17.NewReader(sideActor, balanceHash) - accSH := acc.Contract.ScriptHash() - - balance, err := sideGas.BalanceOf(accSH) - if err != nil { - fatalOnErr(fmt.Errorf("side chain balance: %w", err)) - } - - ok := getConfirmation(false, fmt.Sprintf("Current NeoFS balance is %s, make a deposit? y/[n]: ", - fixedn.ToString(balance, 12))) - if !ok { - return - } - - amountStr := getString("Enter amount in GAS: ") - amount, err := fixedn.FromString(amountStr, 8) - if err != nil { - fatalOnErr(fmt.Errorf("invalid amount: %w", err)) - } - - mainClient := initClient(n3config[network].RPC) - neofsHash, _ := util.Uint160DecodeStringLE(n3config[network].NeoFSContract) - - mainActor, err := actor.NewSimple(mainClient, acc) - if err != nil { - fatalOnErr(fmt.Errorf("creating actor over main chain client: %w", err)) - } - - mainGas := nep17.New(mainActor, gas.Hash) - - txHash, _, err := mainGas.Transfer(accSH, neofsHash, amount, nil) - if err != nil { - fatalOnErr(fmt.Errorf("sending TX to the NeoFS contract: %w", err)) - } - - cmd.Print("Waiting for transactions to persist.") - tick := time.NewTicker(time.Second / 2) - defer tick.Stop() - - timer := time.NewTimer(time.Second * 20) - defer timer.Stop() - - at := trigger.Application - -loop: - for { - select { - case <-tick.C: - _, err := mainClient.GetApplicationLog(txHash, &at) - if err == nil { - cmd.Print("\n") - break loop - } - cmd.Print(".") - case <-timer.C: - cmd.Printf("\nTimeout while waiting for transaction to persist.\n") - if getConfirmation(false, "Continue configuration? yes/[no]: ") { - return - } - os.Exit(1) - } - } -} - -func initClient(rpc []string) *rpcclient.Client { - var c *rpcclient.Client - var err error - - shuffled := slices.Clone(rpc) - rand.Shuffle(len(shuffled), func(i, j int) { shuffled[i], shuffled[j] = shuffled[j], shuffled[i] }) - - for _, endpoint := range shuffled { - c, err = rpcclient.New(context.Background(), "https://"+endpoint, rpcclient.Options{ - DialTimeout: time.Second * 2, - RequestTimeout: time.Second * 5, - }) - if err != nil { - continue - } - if err = c.Init(); err != nil { - continue - } - return c - } - - fatalOnErr(fmt.Errorf("can't create N3 client: %w", err)) - panic("unreachable") -} From 30099194ba8f64b5340c3c2ff3153d31ab549223 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 15:18:28 +0300 Subject: [PATCH 1279/1413] [#1689] config: Remove testnet and mainnet configs They are invalid and unsupported. There is neither mainnet nor testnet currently. Change-Id: I520363e2de0c22a584238accc253248be3eefea5 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/validate_test.go | 14 ---- config/mainnet/README.md | 28 ------- config/mainnet/config.yml | 70 ---------------- config/testnet/README.md | 129 ------------------------------ config/testnet/config.yml | 52 ------------ 5 files changed, 293 deletions(-) delete mode 100644 config/mainnet/README.md delete mode 100644 config/mainnet/config.yml delete mode 100644 config/testnet/README.md delete mode 100644 config/testnet/config.yml diff --git a/cmd/frostfs-node/validate_test.go b/cmd/frostfs-node/validate_test.go index d9c0f167fb..495365cf0e 100644 --- a/cmd/frostfs-node/validate_test.go +++ b/cmd/frostfs-node/validate_test.go @@ -1,7 +1,6 @@ package main import ( - "os" "path/filepath" "testing" @@ -22,17 +21,4 @@ func TestValidate(t *testing.T) { require.NoError(t, err) }) }) - - t.Run("mainnet", func(t *testing.T) { - os.Clearenv() // ENVs have priority over config files, so we do this in tests - p := filepath.Join(exampleConfigPrefix, "mainnet/config.yml") - c := config.New(p, "", config.EnvPrefix) - require.NoError(t, validateConfig(c)) - }) - t.Run("testnet", func(t *testing.T) { - os.Clearenv() // ENVs have priority over config files, so we do this in tests - p := filepath.Join(exampleConfigPrefix, "testnet/config.yml") - c := config.New(p, "", config.EnvPrefix) - require.NoError(t, validateConfig(c)) - }) } diff --git a/config/mainnet/README.md b/config/mainnet/README.md deleted file mode 100644 index 717a9b0ff5..0000000000 --- a/config/mainnet/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# N3 Mainnet Storage node configuration - -Here is a template for simple storage node configuration in N3 Mainnet. -Make sure to specify correct values instead of `<...>` placeholders. -Do not change `contracts` section. Run the latest frostfs-node release with -the fixed config `frostfs-node -c config.yml` - -To use NeoFS in the Mainnet, you need to deposit assets to NeoFS contract. -The contract sript hash is `2cafa46838e8b564468ebd868dcafdd99dce6221` -(N3 address `NNxVrKjLsRkWsmGgmuNXLcMswtxTGaNQLk`) - -## Tips - -Use `grpcs://` scheme in the announced address if you enable TLS in grpc server. -```yaml -node: - addresses: - - grpcs://frostfs.my.org:8080 - -grpc: - num: 1 - 0: - endpoint: frostfs.my.org:8080 - tls: - enabled: true - certificate: /path/to/cert - key: /path/to/key -``` diff --git a/config/mainnet/config.yml b/config/mainnet/config.yml deleted file mode 100644 index d86ea451fe..0000000000 --- a/config/mainnet/config.yml +++ /dev/null @@ -1,70 +0,0 @@ -node: - wallet: - path: - address: - password: - addresses: - - - attribute_0: UN-LOCODE: - attribute_1: Price:100000 - attribute_2: User-Agent:FrostFS\/0.9999 - -grpc: - num: 1 - 0: - endpoint: - tls: - enabled: false - -storage: - shard_num: 1 - shard: - 0: - metabase: - path: /storage/path/metabase - perm: 0600 - blobstor: - - path: /storage/path/blobovnicza - type: blobovnicza - perm: 0600 - opened_cache_capacity: 32 - depth: 1 - width: 1 - - path: /storage/path/fstree - type: fstree - perm: 0600 - depth: 4 - writecache: - enabled: false - gc: - remover_batch_size: 100 - remover_sleep_interval: 1m - -logger: - level: info - -prometheus: - enabled: true - address: localhost:9090 - shutdown_timeout: 15s - -object: - put: - remote_pool_size: 100 - local_pool_size: 100 - -morph: - rpc_endpoint: - - wss://rpc1.morph.frostfs.info:40341/ws - - wss://rpc2.morph.frostfs.info:40341/ws - - wss://rpc3.morph.frostfs.info:40341/ws - - wss://rpc4.morph.frostfs.info:40341/ws - - wss://rpc5.morph.frostfs.info:40341/ws - - wss://rpc6.morph.frostfs.info:40341/ws - - wss://rpc7.morph.frostfs.info:40341/ws - dial_timeout: 20s - -contracts: - balance: dc1ec98d9d0c5f9dfade16144defe08cffc5ca55 - container: 1b6e68d299b570e1cb7e86eadfdc06aa2e8e0cc5 - netmap: 7c5bdb23e36cc7cce95bf42f3ab9e452c2501df1 diff --git a/config/testnet/README.md b/config/testnet/README.md deleted file mode 100644 index e2cda33eca..0000000000 --- a/config/testnet/README.md +++ /dev/null @@ -1,129 +0,0 @@ -# N3 Testnet Storage node configuration - -There is a prepared configuration for NeoFS Storage Node deployment in -N3 Testnet. The easiest way to deploy a Storage Node is to use the prepared -docker image and run it with docker-compose. - -## Build image - -Prepared **frostfs-storage-testnet** image is available at Docker Hub. -However, if you need to rebuild it for some reason, run -`make image-storage-testnet` command. - -``` -$ make image-storage-testnet -... -Successfully built ab0557117b02 -Successfully tagged nspccdev/neofs-storage-testnet:0.25.1 -``` - -## Deploy node - -To run a storage node in N3 Testnet environment, you should deposit GAS assets, -update docker-compose file and start the node. - -### Deposit - -The Storage Node owner should deposit GAS to NeoFS smart contract. It generates a -bit of sidechain GAS in the node's wallet. Sidechain GAS is used to send bootstrap tx. - -First, obtain GAS in N3 Testnet chain. You can do that with -[faucet](https://neowish.ngd.network) service. - -Then, make a deposit by transferring GAS to NeoFS contract in N3 Testnet. -You can provide scripthash in the `data` argument of transfer tx to make a -deposit to a specified account. Otherwise, deposit is made to the tx sender. - -NeoFS contract scripthash in N3 Testnet is `b65d8243ac63983206d17e5221af0653a7266fa1`, -so the address is `NadZ8YfvkddivcFFkztZgfwxZyKf1acpRF`. - -See a deposit example with `neo-go`. - -``` -neo-go wallet nep17 transfer -w wallet.json -r https://rpc01.testnet.n3.nspcc.ru:21331 \ ---from NXxRAFPqPstaPByndKMHuC8iGcaHgtRY3m \ ---to NadZ8YfvkddivcFFkztZgfwxZyKf1acpRF \ ---token GAS \ ---amount 1 -``` - -### Configure - -Next, configure `node_config.env` file. Change endpoints values. Both -should contain your **public** IP. - -``` -NEOFS_GRPC_0_ENDPOINT=65.52.183.157:36512 -NEOFS_NODE_ADDRESSES=65.52.183.157:36512 -``` - -Set up your [UN/LOCODE](https://unece.org/trade/cefact/unlocode-code-list-country-and-territory) -attribute. - -``` -NEOFS_GRPC_0_ENDPOINT=65.52.183.157:36512 -NEOFS_NODE_ADDRESSES=65.52.183.157:36512 -NEOFS_NODE_ATTRIBUTE_2=UN-LOCODE:RU LED -``` - -You can validate UN/LOCODE attribute in -[NeoFS LOCODE database](https://git.frostfs.info/TrueCloudLab/frostfs-locode-db/releases/tag/v0.4.0) -with frostfs-cli. - -``` -$ frostfs-cli util locode info --db ./locode_db --locode 'RU LED' -Country: Russia -Location: Saint Petersburg (ex Leningrad) -Continent: Europe -Subdivision: [SPE] Sankt-Peterburg -Coordinates: 59.53, 30.15 -``` - -It is recommended to pass the node's key as a file. To do so, convert your wallet -WIF to 32-byte hex (via `frostfs-cli` for example) and save it to a file. - -``` -// Print WIF in a 32-byte hex format -$ frostfs-cli util keyer Kwp4Q933QujZLUCcn39tzY94itNQJS4EjTp28oAMzuxMwabm3p1s -PrivateKey 11ab917cd99170cb8d0d48e78fca317564e6b3aaff7f7058952d6175cdca0f56 -PublicKey 02be8b2e837cab232168f5c3303f1b985818b7583682fb49026b8d2f43df7c1059 -WIF Kwp4Q933QujZLUCcn39tzY94itNQJS4EjTp28oAMzuxMwabm3p1s -Wallet3.0 Nfzmk7FAZmEHDhLePdgysQL2FgkJbaEMpQ -ScriptHash3.0 dffe39998f50d42f2e06807866161cd0440b4bdc -ScriptHash3.0BE dc4b0b44d01c16667880062e2fd4508f9939fedf - -// Save 32-byte hex into a file -$ echo '11ab917cd99170cb8d0d48e78fca317564e6b3aaff7f7058952d6175cdca0f56' | xxd -r -p > my_wallet.key -``` - -Then, specify the path to this file in `docker-compose.yml` -```yaml - volumes: - - frostfs_storage:/storage - - ./my_wallet.key:/node.key -``` - - -NeoFS objects will be stored on your machine. By default, docker-compose -is configured to store objects in named docker volume `frostfs_storage`. You can -specify a directory on the filesystem to store objects there. - -```yaml - volumes: - - /home/username/frostfs/rc3/storage:/storage - - ./my_wallet.key:/node.key -``` - -### Start - -Run the node with `docker-compose up` command and stop it with `docker-compose down`. - -### Debug - -To print node logs, use `docker logs frostfs-testnet`. To print debug messages in -log, set up log level to debug with this env: - -```yaml - environment: - - NEOFS_LOGGER_LEVEL=debug -``` diff --git a/config/testnet/config.yml b/config/testnet/config.yml deleted file mode 100644 index 76b36cdf6a..0000000000 --- a/config/testnet/config.yml +++ /dev/null @@ -1,52 +0,0 @@ -logger: - level: info - -morph: - rpc_endpoint: - - wss://rpc01.morph.testnet.frostfs.info:51331/ws - - wss://rpc02.morph.testnet.frostfs.info:51331/ws - - wss://rpc03.morph.testnet.frostfs.info:51331/ws - - wss://rpc04.morph.testnet.frostfs.info:51331/ws - - wss://rpc05.morph.testnet.frostfs.info:51331/ws - - wss://rpc06.morph.testnet.frostfs.info:51331/ws - - wss://rpc07.morph.testnet.frostfs.info:51331/ws - dial_timeout: 20s - -contracts: - balance: e0420c216003747626670d1424569c17c79015bf - container: 9dbd2b5e67568ed285c3d6f96bac4edf5e1efba0 - netmap: d4b331639799e2958d4bc5b711b469d79de94e01 - -node: - key: /node.key - attribute_0: Deployed:SelfHosted - attribute_1: User-Agent:FrostFS\/0.9999 - -prometheus: - enabled: true - address: localhost:9090 - shutdown_timeout: 15s - -storage: - shard_num: 1 - shard: - 0: - metabase: - path: /storage/metabase - perm: 0777 - blobstor: - - path: /storage/path/blobovnicza - type: blobovnicza - perm: 0600 - opened_cache_capacity: 32 - depth: 1 - width: 1 - - path: /storage/path/fstree - type: fstree - perm: 0600 - depth: 4 - writecache: - enabled: false - gc: - remover_batch_size: 100 - remover_sleep_interval: 1m From a4da1da7670b32b73e03f240d0cfcca45f33afda Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 15:40:40 +0300 Subject: [PATCH 1280/1413] [#905] morph/client: Fetch NNS hash once on init NNS contract hash is taken from the contract with ID=1. Because morph client is expected to work with the same chain, and because contract hash doesn't change on update, there is no need to fetch it from each new endpoint. Change-Id: Ic6dc18283789da076d6a0b3701139b97037714cc Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/client.go | 17 +------------ pkg/morph/client/constructor.go | 5 ++++ pkg/morph/client/nns.go | 42 ++++----------------------------- 3 files changed, 10 insertions(+), 54 deletions(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index e63d926e0d..a7c3c6d8d6 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -60,6 +60,7 @@ type Client struct { rpcActor *actor.Actor // neo-go RPC actor gasToken *nep17.Token // neo-go GAS token wrapper rolemgmt *rolemgmt.Contract // neo-go Designation contract wrapper + nnsHash util.Uint160 // NNS contract hash acc *wallet.Account // neo account accAddr util.Uint160 // account's address @@ -94,27 +95,12 @@ type Client struct { type cache struct { m sync.RWMutex - nnsHash *util.Uint160 gKey *keys.PublicKey txHeights *lru.Cache[util.Uint256, uint32] metrics metrics.MorphCacheMetrics } -func (c *cache) nns() *util.Uint160 { - c.m.RLock() - defer c.m.RUnlock() - - return c.nnsHash -} - -func (c *cache) setNNSHash(nnsHash util.Uint160) { - c.m.Lock() - defer c.m.Unlock() - - c.nnsHash = &nnsHash -} - func (c *cache) groupKey() *keys.PublicKey { c.m.RLock() defer c.m.RUnlock() @@ -133,7 +119,6 @@ func (c *cache) invalidate() { c.m.Lock() defer c.m.Unlock() - c.nnsHash = nil c.gKey = nil c.txHeights.Purge() } diff --git a/pkg/morph/client/constructor.go b/pkg/morph/client/constructor.go index d061747bb5..e4dcd0db71 100644 --- a/pkg/morph/client/constructor.go +++ b/pkg/morph/client/constructor.go @@ -145,6 +145,11 @@ func New(ctx context.Context, key *keys.PrivateKey, opts ...Option) (*Client, er if cli.client == nil { return nil, ErrNoHealthyEndpoint } + cs, err := cli.client.GetContractStateByID(nnsContractID) + if err != nil { + return nil, fmt.Errorf("resolve nns hash: %w", err) + } + cli.nnsHash = cs.Hash cli.setActor(act) go cli.closeWaiter(ctx) diff --git a/pkg/morph/client/nns.go b/pkg/morph/client/nns.go index f292dccf1a..b03967fdd9 100644 --- a/pkg/morph/client/nns.go +++ b/pkg/morph/client/nns.go @@ -61,11 +61,7 @@ func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) { return util.Uint160{}, ErrConnectionLost } - nnsHash, err := c.NNSHash() - if err != nil { - return util.Uint160{}, err - } - + nnsHash := c.NNSHash() sh, err = nnsResolve(c.client, nnsHash, name) if err != nil { return sh, fmt.Errorf("NNS.resolve: %w", err) @@ -74,34 +70,8 @@ func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) { } // NNSHash returns NNS contract hash. -func (c *Client) NNSHash() (util.Uint160, error) { - c.switchLock.RLock() - defer c.switchLock.RUnlock() - - if c.inactive { - return util.Uint160{}, ErrConnectionLost - } - - success := false - startedAt := time.Now() - - defer func() { - c.cache.metrics.AddMethodDuration("NNSContractHash", success, time.Since(startedAt)) - }() - - nnsHash := c.cache.nns() - - if nnsHash == nil { - cs, err := c.client.GetContractStateByID(nnsContractID) - if err != nil { - return util.Uint160{}, fmt.Errorf("NNS contract state: %w", err) - } - - c.cache.setNNSHash(cs.Hash) - nnsHash = &cs.Hash - } - success = true - return *nnsHash, nil +func (c *Client) NNSHash() util.Uint160 { + return c.nnsHash } func nnsResolveItem(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (stackitem.Item, error) { @@ -241,11 +211,7 @@ func (c *Client) contractGroupKey() (*keys.PublicKey, error) { return gKey, nil } - nnsHash, err := c.NNSHash() - if err != nil { - return nil, err - } - + nnsHash := c.NNSHash() item, err := nnsResolveItem(c.client, nnsHash, NNSGroupKeyName) if err != nil { return nil, err From eed082459081628eef495d13b5053c07fb67ae84 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 21 Mar 2025 18:03:03 +0300 Subject: [PATCH 1281/1413] go.mod: Bump frostfs-qos version Change-Id: I8bc045b509ee1259cfad288477a0b7d045683f10 Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- pkg/network/cache/multi.go | 2 +- pkg/services/tree/cache.go | 2 +- pkg/services/tree/sync.go | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index fafb4f8280..753bfbd29d 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 - git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529 + git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 diff --git a/go.sum b/go.sum index 7818583d4f..7f94179548 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 h1:fluzML8BIIabd07LyPSjc0JAV2qymWkPiFaLrXdALLA= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529 h1:CBreXSxGoYJAdZ1QdJPsDs1UCXGF5psinII0lxtohsc= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250310135838-3e7ca9403529/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275 h1:WqWxCnCl2ekfjWja/CpGeF2rf4h0x199xhdnsm/j+E8= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 h1:svCl6NDAPZ/KuQPjdVKo74RkCIANesxUPM45zQZDhSw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= diff --git a/pkg/network/cache/multi.go b/pkg/network/cache/multi.go index 77420865a4..54c1e18fb7 100644 --- a/pkg/network/cache/multi.go +++ b/pkg/network/cache/multi.go @@ -67,7 +67,7 @@ func (x *multiClient) createForAddress(ctx context.Context, addr network.Address qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInterceptor(), - tagging.NewUnaryClientInteceptor(), + tagging.NewUnaryClientInterceptor(), ), grpc.WithChainStreamInterceptor( qos.NewAdjustOutgoingIOTagStreamClientInterceptor(), diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index 3359af2c55..e2be2f4a2b 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -100,7 +100,7 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), tracing.NewUnaryClientInterceptor(), - tagging.NewUnaryClientInteceptor(), + tagging.NewUnaryClientInterceptor(), ), grpc.WithChainStreamInterceptor( qos.NewAdjustOutgoingIOTagStreamClientInterceptor(), diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 103e2a6132..1c35213445 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -345,7 +345,7 @@ func (*Service) createConnection(a network.Address) (*grpc.ClientConn, error) { qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), tracing_grpc.NewUnaryClientInterceptor(), - tagging.NewUnaryClientInteceptor(), + tagging.NewUnaryClientInterceptor(), ), grpc.WithChainStreamInterceptor( qos.NewAdjustOutgoingIOTagStreamClientInterceptor(), From 73e35bc88554954371555bd0e9bdf6ce99d20de7 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 19 Mar 2025 13:57:44 +0300 Subject: [PATCH 1282/1413] [#1052] object: Make `ape` middleware form request info * Move some helpers from `acl/v2` package to `ape`. Also move errors; * Introduce `Metadata`, `RequestInfo` types; * Introduce `RequestInfoExtractor` interface and its implementation. The extractor's purpose is to extract request info based on request metadata. It also validates session token; * Refactor ape service - each handler forms request info and pass necessary fields to checker. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/object.go | 5 +- pkg/services/object/ape/errors.go | 15 + pkg/services/object/ape/metadata.go | 172 ++++++++++++ pkg/services/object/ape/metadata_test.go | 164 +++++++++++ pkg/services/object/ape/service.go | 335 ++++++++++------------- pkg/services/object/ape/types.go | 8 + pkg/services/object/ape/util.go | 169 ++++++++++++ pkg/services/object/ape/util_test.go | 84 ++++++ 8 files changed, 759 insertions(+), 193 deletions(-) create mode 100644 pkg/services/object/ape/metadata.go create mode 100644 pkg/services/object/ape/metadata_test.go create mode 100644 pkg/services/object/ape/util.go create mode 100644 pkg/services/object/ape/util_test.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index ad6f4140aa..652d3ad04c 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -172,7 +172,7 @@ func initObjectService(c *cfg) { splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2, sPatch) - apeSvc := createAPEService(c, splitSvc) + apeSvc := createAPEService(c, &irFetcher, splitSvc) aclSvc := createACLServiceV2(c, apeSvc, &irFetcher) @@ -439,7 +439,7 @@ func createACLServiceV2(c *cfg, apeSvc *objectAPE.Service, irFetcher *cachedIRFe ) } -func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *objectAPE.Service { +func createAPEService(c *cfg, irFetcher *cachedIRFetcher, splitSvc *objectService.TransportSplitter) *objectAPE.Service { return objectAPE.NewService( objectAPE.NewChecker( c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage(), @@ -451,6 +451,7 @@ func createAPEService(c *cfg, splitSvc *objectService.TransportSplitter) *object c.cfgObject.cnrSource, c.binPublicKey, ), + objectAPE.NewRequestInfoExtractor(c.log, c.cfgObject.cnrSource, irFetcher, c.netMapSource), splitSvc, ) } diff --git a/pkg/services/object/ape/errors.go b/pkg/services/object/ape/errors.go index 6e458b3849..82e660a7f2 100644 --- a/pkg/services/object/ape/errors.go +++ b/pkg/services/object/ape/errors.go @@ -7,6 +7,21 @@ import ( apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" ) +var ( + errMissingContainerID = malformedRequestError("missing container ID") + errEmptyVerificationHeader = malformedRequestError("empty verification header") + errEmptyBodySig = malformedRequestError("empty at body signature") + errInvalidSessionSig = malformedRequestError("invalid session token signature") + errInvalidSessionOwner = malformedRequestError("invalid session token owner") + errInvalidVerb = malformedRequestError("session token verb is invalid") +) + +func malformedRequestError(reason string) error { + invalidArgErr := &apistatus.InvalidArgument{} + invalidArgErr.SetMessage(reason) + return invalidArgErr +} + func toStatusErr(err error) error { var chRouterErr *checkercore.ChainRouterError if !errors.As(err, &chRouterErr) { diff --git a/pkg/services/object/ape/metadata.go b/pkg/services/object/ape/metadata.go new file mode 100644 index 0000000000..b37c3b6f8b --- /dev/null +++ b/pkg/services/object/ape/metadata.go @@ -0,0 +1,172 @@ +package ape + +import ( + "context" + "encoding/hex" + "errors" + "fmt" + "strings" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +type Metadata struct { + Container cid.ID + Object *oid.ID + MetaHeader *session.RequestMetaHeader + VerificationHeader *session.RequestVerificationHeader + SessionToken *sessionSDK.Object + BearerToken *bearer.Token +} + +func (m Metadata) RequestOwner() (*user.ID, *keys.PublicKey, error) { + if m.VerificationHeader == nil { + return nil, nil, errEmptyVerificationHeader + } + + if m.BearerToken != nil && m.BearerToken.Impersonate() { + return unmarshalPublicKeyWithOwner(m.BearerToken.SigningKeyBytes()) + } + + // if session token is presented, use it as truth source + if m.SessionToken != nil { + // verify signature of session token + return ownerFromToken(m.SessionToken) + } + + // otherwise get original body signature + bodySignature := originalBodySignature(m.VerificationHeader) + if bodySignature == nil { + return nil, nil, errEmptyBodySig + } + + return unmarshalPublicKeyWithOwner(bodySignature.GetKey()) +} + +// RequestInfo contains request information extracted by request metadata. +type RequestInfo struct { + // Role defines under which role this request is executed. + // It must be represented only as a constant represented in native schema. + Role string + + ContainerOwner user.ID + + // Namespace defines to which namespace a container is belonged. + Namespace string + + // HEX-encoded sender key. + SenderKey string +} + +type RequestInfoExtractor interface { + GetRequestInfo(context.Context, Metadata, string) (RequestInfo, error) +} + +type extractor struct { + containers container.Source + + nm netmap.Source + + classifier objectCore.SenderClassifier +} + +func NewRequestInfoExtractor(log *logger.Logger, containers container.Source, irFetcher InnerRingFetcher, nm netmap.Source) RequestInfoExtractor { + return &extractor{ + containers: containers, + nm: nm, + classifier: objectCore.NewSenderClassifier(irFetcher, nm, log), + } +} + +func (e *extractor) verifySessionToken(ctx context.Context, sessionToken *sessionSDK.Object, method string) error { + currentEpoch, err := e.nm.Epoch(ctx) + if err != nil { + return errors.New("can't fetch current epoch") + } + if sessionToken.ExpiredAt(currentEpoch) { + return new(apistatus.SessionTokenExpired) + } + if sessionToken.InvalidAt(currentEpoch) { + return fmt.Errorf("malformed request: token is invalid at %d epoch)", currentEpoch) + } + if !assertVerb(*sessionToken, method) { + return errInvalidVerb + } + return nil +} + +func (e *extractor) GetRequestInfo(ctx context.Context, m Metadata, method string) (ri RequestInfo, err error) { + cnr, err := e.containers.Get(ctx, m.Container) + if err != nil { + return ri, err + } + + if m.SessionToken != nil { + if err = e.verifySessionToken(ctx, m.SessionToken, method); err != nil { + return ri, err + } + } + + ownerID, ownerKey, err := m.RequestOwner() + if err != nil { + return ri, err + } + res, err := e.classifier.Classify(ctx, ownerID, ownerKey, m.Container, cnr.Value) + if err != nil { + return ri, err + } + + ri.Role = nativeSchemaRole(res.Role) + ri.ContainerOwner = cnr.Value.Owner() + + cnrNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cnr.Value).Zone(), ".ns") + if hasNamespace { + ri.Namespace = cnrNamespace + } + + // it is assumed that at the moment the key will be valid, + // otherwise the request would not pass validation + ri.SenderKey = hex.EncodeToString(res.Key) + + return ri, nil +} + +func readSessionToken(cnr cid.ID, obj *oid.ID, tokV2 *session.Token) (*sessionSDK.Object, error) { + var sTok *sessionSDK.Object + + if tokV2 != nil { + sTok = new(sessionSDK.Object) + + err := sTok.ReadFromV2(*tokV2) + if err != nil { + return nil, fmt.Errorf("invalid session token: %w", err) + } + + if sTok.AssertVerb(sessionSDK.VerbObjectDelete) { + // if session relates to object's removal, we don't check + // relation of the tombstone to the session here since user + // can't predict tomb's ID. + err = assertSessionRelation(*sTok, cnr, nil) + } else { + err = assertSessionRelation(*sTok, cnr, obj) + } + + if err != nil { + return nil, err + } + } + + return sTok, nil +} diff --git a/pkg/services/object/ape/metadata_test.go b/pkg/services/object/ape/metadata_test.go new file mode 100644 index 0000000000..fd919008f2 --- /dev/null +++ b/pkg/services/object/ape/metadata_test.go @@ -0,0 +1,164 @@ +package ape + +import ( + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + sigutilV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/signature" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + "github.com/google/uuid" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestRequestOwner(t *testing.T) { + containerOwner, err := keys.NewPrivateKey() + require.NoError(t, err) + + userPk, err := keys.NewPrivateKey() + require.NoError(t, err) + + var userID user.ID + user.IDFromKey(&userID, userPk.PrivateKey.PublicKey) + + var userSignature refs.Signature + userSignature.SetKey(userPk.PublicKey().Bytes()) + + vh := new(sessionV2.RequestVerificationHeader) + vh.SetBodySignature(&userSignature) + + t.Run("empty verification header", func(t *testing.T) { + req := Metadata{} + checkOwner(t, req, nil, errEmptyVerificationHeader) + }) + t.Run("empty verification header signature", func(t *testing.T) { + req := Metadata{ + VerificationHeader: new(sessionV2.RequestVerificationHeader), + } + checkOwner(t, req, nil, errEmptyBodySig) + }) + t.Run("no tokens", func(t *testing.T) { + req := Metadata{ + VerificationHeader: vh, + } + checkOwner(t, req, userPk.PublicKey(), nil) + }) + + t.Run("bearer without impersonate, no session", func(t *testing.T) { + req := Metadata{ + VerificationHeader: vh, + BearerToken: newBearer(t, containerOwner, userID, false), + } + checkOwner(t, req, userPk.PublicKey(), nil) + }) + t.Run("bearer with impersonate, no session", func(t *testing.T) { + req := Metadata{ + VerificationHeader: vh, + BearerToken: newBearer(t, containerOwner, userID, true), + } + checkOwner(t, req, containerOwner.PublicKey(), nil) + }) + t.Run("bearer with impersonate, with session", func(t *testing.T) { + // To check that bearer token takes priority, use different key to sign session token. + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + req := Metadata{ + VerificationHeader: vh, + BearerToken: newBearer(t, containerOwner, userID, true), + SessionToken: newSession(t, pk), + } + checkOwner(t, req, containerOwner.PublicKey(), nil) + }) + t.Run("with session", func(t *testing.T) { + req := Metadata{ + VerificationHeader: vh, + SessionToken: newSession(t, containerOwner), + } + checkOwner(t, req, containerOwner.PublicKey(), nil) + }) + t.Run("malformed session token", func(t *testing.T) { + // This test is tricky: session token has issuer field and signature, which must correspond to each other. + // SDK prevents constructing such token in the first place, but it is still possible via API. + // Thus, construct v2 token, convert it to SDK one and pass to our function. + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + var user1 user.ID + user.IDFromKey(&user1, pk.PrivateKey.PublicKey) + + var id refs.OwnerID + id.SetValue(user1.WalletBytes()) + + raw, err := uuid.New().MarshalBinary() + require.NoError(t, err) + + var cidV2 refs.ContainerID + cidtest.ID().WriteToV2(&cidV2) + + sessionCtx := new(sessionV2.ObjectSessionContext) + sessionCtx.SetTarget(&cidV2) + + var body sessionV2.TokenBody + body.SetOwnerID(&id) + body.SetID(raw) + body.SetLifetime(new(sessionV2.TokenLifetime)) + body.SetSessionKey(pk.PublicKey().Bytes()) + body.SetContext(sessionCtx) + + var tokV2 sessionV2.Token + tokV2.SetBody(&body) + require.NoError(t, sigutilV2.SignData(&containerOwner.PrivateKey, smWrapper{Token: &tokV2})) + require.NoError(t, sigutilV2.VerifyData(smWrapper{Token: &tokV2})) + + var tok sessionSDK.Object + require.NoError(t, tok.ReadFromV2(tokV2)) + + req := Metadata{ + VerificationHeader: vh, + SessionToken: &tok, + } + checkOwner(t, req, nil, errInvalidSessionOwner) + }) +} + +type smWrapper struct { + *sessionV2.Token +} + +func (s smWrapper) ReadSignedData(data []byte) ([]byte, error) { + return s.Token.GetBody().StableMarshal(data), nil +} + +func (s smWrapper) SignedDataSize() int { + return s.Token.GetBody().StableSize() +} + +func newSession(t *testing.T, pk *keys.PrivateKey) *sessionSDK.Object { + var tok sessionSDK.Object + require.NoError(t, tok.Sign(pk.PrivateKey)) + return &tok +} + +func newBearer(t *testing.T, pk *keys.PrivateKey, user user.ID, impersonate bool) *bearer.Token { + var tok bearer.Token + tok.SetImpersonate(impersonate) + tok.ForUser(user) + require.NoError(t, tok.Sign(pk.PrivateKey)) + return &tok +} + +func checkOwner(t *testing.T, req Metadata, expected *keys.PublicKey, expectedErr error) { + _, actual, err := req.RequestOwner() + if expectedErr != nil { + require.ErrorIs(t, err, expectedErr) + return + } + + require.NoError(t, err) + require.Equal(t, expected, actual) +} diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index d9594a3fc8..e199e26384 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -2,9 +2,6 @@ package ape import ( "context" - "encoding/hex" - "errors" - "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" objectSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" @@ -12,19 +9,18 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" ) -var errFailedToCastToRequestContext = errors.New("failed cast to RequestContext") - type Service struct { apeChecker Checker + extractor RequestInfoExtractor + next objectSvc.ServiceServer } @@ -64,9 +60,10 @@ func NewStorageEngineHeaderProvider(e *engine.StorageEngine, s *getsvc.Service) } } -func NewService(apeChecker Checker, next objectSvc.ServiceServer) *Service { +func NewService(apeChecker Checker, extractor RequestInfoExtractor, next objectSvc.ServiceServer) *Service { return &Service{ apeChecker: apeChecker, + extractor: extractor, next: next, } } @@ -76,15 +73,9 @@ type getStreamBasicChecker struct { apeChecker Checker - namespace string + metadata Metadata - senderKey []byte - - containerOwner user.ID - - role string - - bearerToken *bearer.Token + reqInfo RequestInfo } func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { @@ -95,15 +86,15 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { } prm := Prm{ - Namespace: g.namespace, + Namespace: g.reqInfo.Namespace, Container: cnrID, Object: objID, Header: partInit.GetHeader(), Method: nativeschema.MethodGetObject, - SenderKey: hex.EncodeToString(g.senderKey), - ContainerOwner: g.containerOwner, - Role: g.role, - BearerToken: g.bearerToken, + SenderKey: g.reqInfo.SenderKey, + ContainerOwner: g.reqInfo.ContainerOwner, + Role: g.reqInfo.Role, + BearerToken: g.metadata.BearerToken, XHeaders: resp.GetMetaHeader().GetXHeaders(), } @@ -114,69 +105,53 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { return g.GetObjectStream.Send(resp) } -func requestContext(ctx context.Context) (*objectSvc.RequestContext, error) { - untyped := ctx.Value(objectSvc.RequestContextKey) - if untyped == nil { - return nil, fmt.Errorf("no key %s in context", objectSvc.RequestContextKey) - } - rc, ok := untyped.(*objectSvc.RequestContext) - if !ok { - return nil, errFailedToCastToRequestContext - } - return rc, nil -} - func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectStream) error { - reqCtx, err := requestContext(stream.Context()) + md, err := newMetadata(request, request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { - return toStatusErr(err) + return err + } + reqInfo, err := c.extractor.GetRequestInfo(stream.Context(), md, nativeschema.MethodGetObject) + if err != nil { + return err } - return c.next.Get(request, &getStreamBasicChecker{ GetObjectStream: stream, apeChecker: c.apeChecker, - namespace: reqCtx.Namespace, - senderKey: reqCtx.SenderKey, - containerOwner: reqCtx.ContainerOwner, - role: nativeSchemaRole(reqCtx.Role), - bearerToken: reqCtx.BearerToken, + metadata: md, + reqInfo: reqInfo, }) } type putStreamBasicChecker struct { apeChecker Checker + extractor RequestInfoExtractor + next objectSvc.PutObjectStream } func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRequest) error { - meta := request.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - if partInit, ok := request.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok { - reqCtx, err := requestContext(ctx) + md, err := newMetadata(request, partInit.GetHeader().GetContainerID(), partInit.GetObjectID()) if err != nil { - return toStatusErr(err) + return err } - - cnrID, objID, err := getAddressParamsSDK(partInit.GetHeader().GetContainerID(), partInit.GetObjectID()) + reqInfo, err := p.extractor.GetRequestInfo(ctx, md, nativeschema.MethodPutObject) if err != nil { - return toStatusErr(err) + return err } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, Header: partInit.GetHeader(), Method: nativeschema.MethodPutObject, - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - Role: nativeSchemaRole(reqCtx.Role), - BearerToken: reqCtx.BearerToken, - XHeaders: meta.GetXHeaders(), + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + Role: reqInfo.Role, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -196,6 +171,7 @@ func (c *Service) Put(ctx context.Context) (objectSvc.PutObjectStream, error) { return &putStreamBasicChecker{ apeChecker: c.apeChecker, + extractor: c.extractor, next: streamer, }, err } @@ -203,40 +179,36 @@ func (c *Service) Put(ctx context.Context) (objectSvc.PutObjectStream, error) { type patchStreamBasicChecker struct { apeChecker Checker + extractor RequestInfoExtractor + next objectSvc.PatchObjectStream nonFirstSend bool } func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { - meta := request.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - if !p.nonFirstSend { p.nonFirstSend = true - reqCtx, err := requestContext(ctx) + md, err := newMetadata(request, request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { - return toStatusErr(err) + return err } - - cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + reqInfo, err := p.extractor.GetRequestInfo(ctx, md, nativeschema.MethodPatchObject) if err != nil { - return toStatusErr(err) + return err } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, Method: nativeschema.MethodPatchObject, - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - Role: nativeSchemaRole(reqCtx.Role), - BearerToken: reqCtx.BearerToken, - XHeaders: meta.GetXHeaders(), + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + Role: reqInfo.Role, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -256,22 +228,17 @@ func (c *Service) Patch(ctx context.Context) (objectSvc.PatchObjectStream, error return &patchStreamBasicChecker{ apeChecker: c.apeChecker, + extractor: c.extractor, next: streamer, }, err } func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*objectV2.HeadResponse, error) { - meta := request.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - - cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + md, err := newMetadata(request, request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { return nil, err } - - reqCtx, err := requestContext(ctx) + reqInfo, err := c.extractor.GetRequestInfo(ctx, md, nativeschema.MethodHeadObject) if err != nil { return nil, err } @@ -285,7 +252,7 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj switch headerPart := resp.GetBody().GetHeaderPart().(type) { case *objectV2.ShortHeader: cidV2 := new(refs.ContainerID) - cnrID.WriteToV2(cidV2) + md.Container.WriteToV2(cidV2) header.SetContainerID(cidV2) header.SetVersion(headerPart.GetVersion()) header.SetCreationEpoch(headerPart.GetCreationEpoch()) @@ -301,16 +268,16 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, Header: header, Method: nativeschema.MethodHeadObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - BearerToken: reqCtx.BearerToken, - XHeaders: meta.GetXHeaders(), + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -319,32 +286,24 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.SearchStream) error { - meta := request.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - - var cnrID cid.ID - if cnrV2 := request.GetBody().GetContainerID(); cnrV2 != nil { - if err := cnrID.ReadFromV2(*cnrV2); err != nil { - return toStatusErr(err) - } - } - - reqCtx, err := requestContext(stream.Context()) + md, err := newMetadata(request, request.GetBody().GetContainerID(), nil) if err != nil { - return toStatusErr(err) + return err + } + reqInfo, err := c.extractor.GetRequestInfo(stream.Context(), md, nativeschema.MethodSearchObject) + if err != nil { + return err } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, + Namespace: reqInfo.Namespace, + Container: md.Container, Method: nativeschema.MethodSearchObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - BearerToken: reqCtx.BearerToken, - XHeaders: meta.GetXHeaders(), + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -354,31 +313,25 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc } func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) (*objectV2.DeleteResponse, error) { - meta := request.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - - cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + md, err := newMetadata(request, request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { return nil, err } - - reqCtx, err := requestContext(ctx) + reqInfo, err := c.extractor.GetRequestInfo(ctx, md, nativeschema.MethodDeleteObject) if err != nil { return nil, err } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, Method: nativeschema.MethodDeleteObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - BearerToken: reqCtx.BearerToken, - XHeaders: meta.GetXHeaders(), + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -393,31 +346,25 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( } func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.GetObjectRangeStream) error { - meta := request.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - - cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + md, err := newMetadata(request, request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { - return toStatusErr(err) + return err } - - reqCtx, err := requestContext(stream.Context()) + reqInfo, err := c.extractor.GetRequestInfo(stream.Context(), md, nativeschema.MethodRangeObject) if err != nil { - return toStatusErr(err) + return err } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, Method: nativeschema.MethodRangeObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - BearerToken: reqCtx.BearerToken, - XHeaders: meta.GetXHeaders(), + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -427,31 +374,25 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G } func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHashRequest) (*objectV2.GetRangeHashResponse, error) { - meta := request.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - - cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) + md, err := newMetadata(request, request.GetBody().GetAddress().GetContainerID(), request.GetBody().GetAddress().GetObjectID()) if err != nil { return nil, err } - - reqCtx, err := requestContext(ctx) + reqInfo, err := c.extractor.GetRequestInfo(ctx, md, nativeschema.MethodHashObject) if err != nil { return nil, err } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, Method: nativeschema.MethodHashObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - BearerToken: reqCtx.BearerToken, - XHeaders: meta.GetXHeaders(), + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), } resp, err := c.next.GetRangeHash(ctx, request) @@ -466,32 +407,26 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa } func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequest) (*objectV2.PutSingleResponse, error) { - meta := request.GetMetaHeader() - for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { - meta = origin - } - - cnrID, objID, err := getAddressParamsSDK(request.GetBody().GetObject().GetHeader().GetContainerID(), request.GetBody().GetObject().GetObjectID()) + md, err := newMetadata(request, request.GetBody().GetObject().GetHeader().GetContainerID(), request.GetBody().GetObject().GetObjectID()) if err != nil { return nil, err } - - reqCtx, err := requestContext(ctx) + reqInfo, err := c.extractor.GetRequestInfo(ctx, md, nativeschema.MethodPutObject) if err != nil { return nil, err } prm := Prm{ - Namespace: reqCtx.Namespace, - Container: cnrID, - Object: objID, + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, Header: request.GetBody().GetObject().GetHeader(), Method: nativeschema.MethodPutObject, - Role: nativeSchemaRole(reqCtx.Role), - SenderKey: hex.EncodeToString(reqCtx.SenderKey), - ContainerOwner: reqCtx.ContainerOwner, - BearerToken: reqCtx.BearerToken, - XHeaders: meta.GetXHeaders(), + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -501,18 +436,36 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ return c.next.PutSingle(ctx, request) } -func getAddressParamsSDK(cidV2 *refs.ContainerID, objV2 *refs.ObjectID) (cnrID cid.ID, objID *oid.ID, err error) { - if cidV2 != nil { - if err = cnrID.ReadFromV2(*cidV2); err != nil { - return - } +type request interface { + GetMetaHeader() *session.RequestMetaHeader + GetVerificationHeader() *session.RequestVerificationHeader +} + +func newMetadata(request request, cnrV2 *refs.ContainerID, objV2 *refs.ObjectID) (md Metadata, err error) { + meta := request.GetMetaHeader() + for origin := meta.GetOrigin(); origin != nil; origin = meta.GetOrigin() { + meta = origin } - if objV2 != nil { - objID = new(oid.ID) - if err = objID.ReadFromV2(*objV2); err != nil { - return - } + cnrID, objID, err := getAddressParamsSDK(cnrV2, objV2) + if err != nil { + return + } + session, err := readSessionToken(cnrID, objID, meta.GetSessionToken()) + if err != nil { + return + } + bearer, err := originalBearerToken(request.GetMetaHeader()) + if err != nil { + return + } + + md = Metadata{ + Container: cnrID, + Object: objID, + VerificationHeader: request.GetVerificationHeader(), + SessionToken: session, + BearerToken: bearer, } return } diff --git a/pkg/services/object/ape/types.go b/pkg/services/object/ape/types.go index 46e55360d6..97dbfa658a 100644 --- a/pkg/services/object/ape/types.go +++ b/pkg/services/object/ape/types.go @@ -7,3 +7,11 @@ import "context" type Checker interface { CheckAPE(context.Context, Prm) error } + +// InnerRingFetcher is an interface that must provide +// Inner Ring information. +type InnerRingFetcher interface { + // InnerRingKeys must return list of public keys of + // the actual inner ring. + InnerRingKeys(ctx context.Context) ([][]byte, error) +} diff --git a/pkg/services/object/ape/util.go b/pkg/services/object/ape/util.go new file mode 100644 index 0000000000..5cd2caa503 --- /dev/null +++ b/pkg/services/object/ape/util.go @@ -0,0 +1,169 @@ +package ape + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "errors" + "fmt" + + refsV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" + sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" +) + +func getAddressParamsSDK(cidV2 *refsV2.ContainerID, objV2 *refsV2.ObjectID) (cnrID cid.ID, objID *oid.ID, err error) { + if cidV2 != nil { + if err = cnrID.ReadFromV2(*cidV2); err != nil { + return + } + } else { + err = errMissingContainerID + return + } + + if objV2 != nil { + objID = new(oid.ID) + if err = objID.ReadFromV2(*objV2); err != nil { + return + } + } + return +} + +// originalBearerToken goes down to original request meta header and fetches +// bearer token from there. +func originalBearerToken(header *sessionV2.RequestMetaHeader) (*bearer.Token, error) { + for header.GetOrigin() != nil { + header = header.GetOrigin() + } + + tokV2 := header.GetBearerToken() + if tokV2 == nil { + return nil, nil + } + + var tok bearer.Token + return &tok, tok.ReadFromV2(*tokV2) +} + +func ownerFromToken(token *sessionSDK.Object) (*user.ID, *keys.PublicKey, error) { + // 1. First check signature of session token. + if !token.VerifySignature() { + return nil, nil, errInvalidSessionSig + } + + // 2. Then check if session token owner issued the session token + // TODO(@cthulhu-rider): #468 implement and use another approach to avoid conversion + var tokV2 sessionV2.Token + token.WriteToV2(&tokV2) + + tokenIssuerKey, err := unmarshalPublicKey(tokV2.GetSignature().GetKey()) + if err != nil { + return nil, nil, fmt.Errorf("invalid key in session token signature: %w", err) + } + + tokenIssuer := token.Issuer() + + if !isOwnerFromKey(tokenIssuer, tokenIssuerKey) { + // TODO: #767 in this case we can issue all owner keys from frostfs.id and check once again + return nil, nil, errInvalidSessionOwner + } + + return &tokenIssuer, tokenIssuerKey, nil +} + +func originalBodySignature(v *sessionV2.RequestVerificationHeader) *refsV2.Signature { + if v == nil { + return nil + } + + for v.GetOrigin() != nil { + v = v.GetOrigin() + } + + return v.GetBodySignature() +} + +func unmarshalPublicKey(bs []byte) (*keys.PublicKey, error) { + return keys.NewPublicKeyFromBytes(bs, elliptic.P256()) +} + +func isOwnerFromKey(id user.ID, key *keys.PublicKey) bool { + if key == nil { + return false + } + + var id2 user.ID + user.IDFromKey(&id2, (ecdsa.PublicKey)(*key)) + + return id2.Equals(id) +} + +// assertVerb checks that token verb corresponds to the method. +func assertVerb(tok sessionSDK.Object, method string) bool { + switch method { + case nativeschema.MethodPutObject: + return tok.AssertVerb(sessionSDK.VerbObjectPut, sessionSDK.VerbObjectDelete, sessionSDK.VerbObjectPatch) + case nativeschema.MethodDeleteObject: + return tok.AssertVerb(sessionSDK.VerbObjectDelete) + case nativeschema.MethodGetObject: + return tok.AssertVerb(sessionSDK.VerbObjectGet) + case nativeschema.MethodHeadObject: + return tok.AssertVerb( + sessionSDK.VerbObjectHead, + sessionSDK.VerbObjectGet, + sessionSDK.VerbObjectDelete, + sessionSDK.VerbObjectRange, + sessionSDK.VerbObjectRangeHash, + sessionSDK.VerbObjectPatch, + ) + case nativeschema.MethodSearchObject: + return tok.AssertVerb(sessionSDK.VerbObjectSearch, sessionSDK.VerbObjectDelete) + case nativeschema.MethodRangeObject: + return tok.AssertVerb(sessionSDK.VerbObjectRange, sessionSDK.VerbObjectRangeHash, sessionSDK.VerbObjectPatch) + case nativeschema.MethodHashObject: + return tok.AssertVerb(sessionSDK.VerbObjectRangeHash) + case nativeschema.MethodPatchObject: + return tok.AssertVerb(sessionSDK.VerbObjectPatch) + } + return false +} + +// assertSessionRelation checks if given token describing the FrostFS session +// relates to the given container and optional object. Missing object +// means that the context isn't bound to any FrostFS object in the container. +// Returns no error iff relation is correct. Criteria: +// +// session is bound to the given container +// object is not specified or session is bound to this object +// +// Session MUST be bound to the particular container, otherwise behavior is undefined. +func assertSessionRelation(tok sessionSDK.Object, cnr cid.ID, obj *oid.ID) error { + if !tok.AssertContainer(cnr) { + return errors.New("requested container is not related to the session") + } + + if obj != nil && !tok.AssertObject(*obj) { + return errors.New("requested object is not related to the session") + } + + return nil +} + +func unmarshalPublicKeyWithOwner(rawKey []byte) (*user.ID, *keys.PublicKey, error) { + key, err := unmarshalPublicKey(rawKey) + if err != nil { + return nil, nil, fmt.Errorf("invalid signature key: %w", err) + } + + var idSender user.ID + user.IDFromKey(&idSender, (ecdsa.PublicKey)(*key)) + + return &idSender, key, nil +} diff --git a/pkg/services/object/ape/util_test.go b/pkg/services/object/ape/util_test.go new file mode 100644 index 0000000000..916bce4271 --- /dev/null +++ b/pkg/services/object/ape/util_test.go @@ -0,0 +1,84 @@ +package ape + +import ( + "slices" + "testing" + + cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" + oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" + sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" + nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" + "github.com/stretchr/testify/require" +) + +func TestIsVerbCompatible(t *testing.T) { + table := map[string][]sessionSDK.ObjectVerb{ + nativeschema.MethodPutObject: {sessionSDK.VerbObjectPut, sessionSDK.VerbObjectDelete, sessionSDK.VerbObjectPatch}, + nativeschema.MethodDeleteObject: {sessionSDK.VerbObjectDelete}, + nativeschema.MethodGetObject: {sessionSDK.VerbObjectGet}, + nativeschema.MethodHeadObject: { + sessionSDK.VerbObjectHead, + sessionSDK.VerbObjectGet, + sessionSDK.VerbObjectDelete, + sessionSDK.VerbObjectRange, + sessionSDK.VerbObjectRangeHash, + sessionSDK.VerbObjectPatch, + }, + nativeschema.MethodRangeObject: {sessionSDK.VerbObjectRange, sessionSDK.VerbObjectRangeHash, sessionSDK.VerbObjectPatch}, + nativeschema.MethodHashObject: {sessionSDK.VerbObjectRangeHash}, + nativeschema.MethodSearchObject: {sessionSDK.VerbObjectSearch, sessionSDK.VerbObjectDelete}, + nativeschema.MethodPatchObject: {sessionSDK.VerbObjectPatch}, + } + + verbs := []sessionSDK.ObjectVerb{ + sessionSDK.VerbObjectPut, + sessionSDK.VerbObjectDelete, + sessionSDK.VerbObjectHead, + sessionSDK.VerbObjectRange, + sessionSDK.VerbObjectRangeHash, + sessionSDK.VerbObjectGet, + sessionSDK.VerbObjectSearch, + sessionSDK.VerbObjectPatch, + } + + var tok sessionSDK.Object + + for op, list := range table { + for _, verb := range verbs { + contains := slices.Contains(list, verb) + + tok.ForVerb(verb) + + require.Equal(t, contains, assertVerb(tok, op), + "%v in token, %s executing", verb, op) + } + } +} + +func TestAssertSessionRelation(t *testing.T) { + var tok sessionSDK.Object + cnr := cidtest.ID() + cnrOther := cidtest.ID() + obj := oidtest.ID() + objOther := oidtest.ID() + + // make sure ids differ, otherwise test won't work correctly + require.False(t, cnrOther.Equals(cnr)) + require.False(t, objOther.Equals(obj)) + + // bind session to the container (required) + tok.BindContainer(cnr) + + // test container-global session + require.NoError(t, assertSessionRelation(tok, cnr, nil)) + require.NoError(t, assertSessionRelation(tok, cnr, &obj)) + require.Error(t, assertSessionRelation(tok, cnrOther, nil)) + require.Error(t, assertSessionRelation(tok, cnrOther, &obj)) + + // limit the session to the particular object + tok.LimitByObjects(obj) + + // test fixed object session (here obj arg must be non-nil everywhere) + require.NoError(t, assertSessionRelation(tok, cnr, &obj)) + require.Error(t, assertSessionRelation(tok, cnr, &objOther)) +} From ccdd6cb767d728ce85e6da62b6b0fc9c760f69d8 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 19 Mar 2025 14:46:33 +0300 Subject: [PATCH 1283/1413] [#1052] object: Nuke out `acl` middleware * Remove `acl` package as it's no longer used; * Remove `RequestContext`; * Fix `cmd/frostfs-node`. Signed-off-by: Airat Arifullin --- cmd/frostfs-node/object.go | 17 +- pkg/services/object/acl/eacl/v2/eacl_test.go | 166 ---- pkg/services/object/acl/eacl/v2/headers.go | 246 ------ pkg/services/object/acl/eacl/v2/object.go | 92 --- pkg/services/object/acl/eacl/v2/opts.go | 11 - pkg/services/object/acl/eacl/v2/xheader.go | 69 -- pkg/services/object/acl/v2/errors.go | 20 - pkg/services/object/acl/v2/opts.go | 12 - pkg/services/object/acl/v2/request.go | 152 ---- pkg/services/object/acl/v2/request_test.go | 164 ---- pkg/services/object/acl/v2/service.go | 779 ------------------- pkg/services/object/acl/v2/types.go | 11 - pkg/services/object/acl/v2/util.go | 223 ------ pkg/services/object/acl/v2/util_test.go | 131 ---- pkg/services/object/request_context.go | 24 - 15 files changed, 2 insertions(+), 2115 deletions(-) delete mode 100644 pkg/services/object/acl/eacl/v2/eacl_test.go delete mode 100644 pkg/services/object/acl/eacl/v2/headers.go delete mode 100644 pkg/services/object/acl/eacl/v2/object.go delete mode 100644 pkg/services/object/acl/eacl/v2/opts.go delete mode 100644 pkg/services/object/acl/eacl/v2/xheader.go delete mode 100644 pkg/services/object/acl/v2/errors.go delete mode 100644 pkg/services/object/acl/v2/opts.go delete mode 100644 pkg/services/object/acl/v2/request.go delete mode 100644 pkg/services/object/acl/v2/request_test.go delete mode 100644 pkg/services/object/acl/v2/service.go delete mode 100644 pkg/services/object/acl/v2/types.go delete mode 100644 pkg/services/object/acl/v2/util.go delete mode 100644 pkg/services/object/acl/v2/util_test.go delete mode 100644 pkg/services/object/request_context.go diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 652d3ad04c..2674be8c7b 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -16,7 +16,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache" objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc" objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" - v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2" objectAPE "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/ape" objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" deletesvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/delete" @@ -174,10 +173,8 @@ func initObjectService(c *cfg) { apeSvc := createAPEService(c, &irFetcher, splitSvc) - aclSvc := createACLServiceV2(c, apeSvc, &irFetcher) - var commonSvc objectService.Common - commonSvc.Init(&c.internals, aclSvc) + commonSvc.Init(&c.internals, apeSvc) respSvc := objectService.NewResponseService( &commonSvc, @@ -284,7 +281,7 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl }) } -func createInnerRingFetcher(c *cfg) v2.InnerRingFetcher { +func createInnerRingFetcher(c *cfg) objectAPE.InnerRingFetcher { return &innerRingFetcherWithNotary{ sidechain: c.cfgMorph.client, } @@ -429,16 +426,6 @@ func createSplitService(c *cfg, sPutV2 *putsvcV2.Service, sGetV2 *getsvcV2.Servi ) } -func createACLServiceV2(c *cfg, apeSvc *objectAPE.Service, irFetcher *cachedIRFetcher) v2.Service { - return v2.New( - apeSvc, - c.netMapSource, - irFetcher, - c.cfgObject.cnrSource, - v2.WithLogger(c.log), - ) -} - func createAPEService(c *cfg, irFetcher *cachedIRFetcher, splitSvc *objectService.TransportSplitter) *objectAPE.Service { return objectAPE.NewService( objectAPE.NewChecker( diff --git a/pkg/services/object/acl/eacl/v2/eacl_test.go b/pkg/services/object/acl/eacl/v2/eacl_test.go deleted file mode 100644 index 94e015abec..0000000000 --- a/pkg/services/object/acl/eacl/v2/eacl_test.go +++ /dev/null @@ -1,166 +0,0 @@ -package v2 - -import ( - "context" - "crypto/ecdsa" - "errors" - "testing" - - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/stretchr/testify/require" -) - -type testLocalStorage struct { - t *testing.T - - expAddr oid.Address - - obj *objectSDK.Object - - err error -} - -func (s *testLocalStorage) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) { - require.True(s.t, addr.Container().Equals(s.expAddr.Container())) - require.True(s.t, addr.Object().Equals(s.expAddr.Object())) - - return s.obj, s.err -} - -func testXHeaders(strs ...string) []session.XHeader { - res := make([]session.XHeader, len(strs)/2) - - for i := 0; i < len(strs); i += 2 { - res[i/2].SetKey(strs[i]) - res[i/2].SetValue(strs[i+1]) - } - - return res -} - -func TestHeadRequest(t *testing.T) { - req := new(objectV2.HeadRequest) - - meta := new(session.RequestMetaHeader) - req.SetMetaHeader(meta) - - body := new(objectV2.HeadRequestBody) - req.SetBody(body) - - addr := oidtest.Address() - - var addrV2 refs.Address - addr.WriteToV2(&addrV2) - - body.SetAddress(&addrV2) - - xKey := "x-key" - xVal := "x-val" - xHdrs := testXHeaders( - xKey, xVal, - ) - - meta.SetXHeaders(xHdrs) - - obj := objectSDK.New() - - attrKey := "attr_key" - attrVal := "attr_val" - var attr objectSDK.Attribute - attr.SetKey(attrKey) - attr.SetValue(attrVal) - obj.SetAttributes(attr) - - table := new(eaclSDK.Table) - - priv, err := keys.NewPrivateKey() - require.NoError(t, err) - senderKey := priv.PublicKey() - - r := eaclSDK.NewRecord() - r.SetOperation(eaclSDK.OperationHead) - r.SetAction(eaclSDK.ActionDeny) - r.AddFilter(eaclSDK.HeaderFromObject, eaclSDK.MatchStringEqual, attrKey, attrVal) - r.AddFilter(eaclSDK.HeaderFromRequest, eaclSDK.MatchStringEqual, xKey, xVal) - eaclSDK.AddFormedTarget(r, eaclSDK.RoleUnknown, (ecdsa.PublicKey)(*senderKey)) - - table.AddRecord(r) - - lStorage := &testLocalStorage{ - t: t, - expAddr: addr, - obj: obj, - } - - id := addr.Object() - - newSource := func(t *testing.T) eaclSDK.TypedHeaderSource { - hdrSrc, err := NewMessageHeaderSource( - lStorage, - NewRequestXHeaderSource(req), - addr.Container(), - WithOID(&id)) - require.NoError(t, err) - return hdrSrc - } - - cnr := addr.Container() - - unit := new(eaclSDK.ValidationUnit). - WithContainerID(&cnr). - WithOperation(eaclSDK.OperationHead). - WithSenderKey(senderKey.Bytes()). - WithEACLTable(table) - - validator := eaclSDK.NewValidator() - - checkAction(t, eaclSDK.ActionDeny, validator, unit.WithHeaderSource(newSource(t))) - - meta.SetXHeaders(nil) - - checkDefaultAction(t, validator, unit.WithHeaderSource(newSource(t))) - - meta.SetXHeaders(xHdrs) - - obj.SetAttributes() - - checkDefaultAction(t, validator, unit.WithHeaderSource(newSource(t))) - - lStorage.err = errors.New("any error") - - checkDefaultAction(t, validator, unit.WithHeaderSource(newSource(t))) - - r.SetAction(eaclSDK.ActionAllow) - - rID := eaclSDK.NewRecord() - rID.SetOperation(eaclSDK.OperationHead) - rID.SetAction(eaclSDK.ActionDeny) - rID.AddObjectIDFilter(eaclSDK.MatchStringEqual, addr.Object()) - eaclSDK.AddFormedTarget(rID, eaclSDK.RoleUnknown, (ecdsa.PublicKey)(*senderKey)) - - table = eaclSDK.NewTable() - table.AddRecord(r) - table.AddRecord(rID) - - unit.WithEACLTable(table) - checkDefaultAction(t, validator, unit.WithHeaderSource(newSource(t))) -} - -func checkAction(t *testing.T, expected eaclSDK.Action, v *eaclSDK.Validator, u *eaclSDK.ValidationUnit) { - actual, fromRule := v.CalculateAction(u) - require.True(t, fromRule) - require.Equal(t, expected, actual) -} - -func checkDefaultAction(t *testing.T, v *eaclSDK.Validator, u *eaclSDK.ValidationUnit) { - actual, fromRule := v.CalculateAction(u) - require.False(t, fromRule) - require.Equal(t, eaclSDK.ActionAllow, actual) -} diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go deleted file mode 100644 index ecb793df82..0000000000 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ /dev/null @@ -1,246 +0,0 @@ -package v2 - -import ( - "context" - "errors" - "fmt" - - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" -) - -type Option func(*cfg) - -type cfg struct { - storage ObjectStorage - - msg XHeaderSource - - cnr cid.ID - obj *oid.ID -} - -type ObjectStorage interface { - Head(context.Context, oid.Address) (*objectSDK.Object, error) -} - -type Request interface { - GetMetaHeader() *session.RequestMetaHeader -} - -type Response interface { - GetMetaHeader() *session.ResponseMetaHeader -} - -type headerSource struct { - requestHeaders []eaclSDK.Header - objectHeaders []eaclSDK.Header - - incompleteObjectHeaders bool -} - -func NewMessageHeaderSource(os ObjectStorage, xhs XHeaderSource, cnrID cid.ID, opts ...Option) (eaclSDK.TypedHeaderSource, error) { - cfg := &cfg{ - storage: os, - cnr: cnrID, - msg: xhs, - } - - for i := range opts { - opts[i](cfg) - } - - if cfg.msg == nil { - return nil, errors.New("message is not provided") - } - - var res headerSource - - err := cfg.readObjectHeaders(&res) - if err != nil { - return nil, err - } - - res.requestHeaders = cfg.msg.GetXHeaders() - - return res, nil -} - -func (h headerSource) HeadersOfType(typ eaclSDK.FilterHeaderType) ([]eaclSDK.Header, bool) { - switch typ { - default: - return nil, true - case eaclSDK.HeaderFromRequest: - return h.requestHeaders, true - case eaclSDK.HeaderFromObject: - return h.objectHeaders, !h.incompleteObjectHeaders - } -} - -type xHeader session.XHeader - -func (x xHeader) Key() string { - return (*session.XHeader)(&x).GetKey() -} - -func (x xHeader) Value() string { - return (*session.XHeader)(&x).GetValue() -} - -var errMissingOID = errors.New("object ID is missing") - -func (h *cfg) readObjectHeaders(dst *headerSource) error { - switch m := h.msg.(type) { - default: - panic(fmt.Sprintf("unexpected message type %T", h.msg)) - case requestXHeaderSource: - return h.readObjectHeadersFromRequestXHeaderSource(m, dst) - case responseXHeaderSource: - return h.readObjectHeadersResponseXHeaderSource(m, dst) - } -} - -func (h *cfg) readObjectHeadersFromRequestXHeaderSource(m requestXHeaderSource, dst *headerSource) error { - switch req := m.req.(type) { - case - *objectV2.GetRequest, - *objectV2.HeadRequest: - if h.obj == nil { - return errMissingOID - } - - objHeaders, completed := h.localObjectHeaders(h.cnr, h.obj) - - dst.objectHeaders = objHeaders - dst.incompleteObjectHeaders = !completed - case - *objectV2.GetRangeRequest, - *objectV2.GetRangeHashRequest, - *objectV2.DeleteRequest: - if h.obj == nil { - return errMissingOID - } - - dst.objectHeaders = addressHeaders(h.cnr, h.obj) - case *objectV2.PutRequest: - if v, ok := req.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit); ok { - oV2 := new(objectV2.Object) - oV2.SetObjectID(v.GetObjectID()) - oV2.SetHeader(v.GetHeader()) - - dst.objectHeaders = headersFromObject(objectSDK.NewFromV2(oV2), h.cnr, h.obj) - } - case *objectV2.PutSingleRequest: - dst.objectHeaders = headersFromObject(objectSDK.NewFromV2(req.GetBody().GetObject()), h.cnr, h.obj) - case *objectV2.SearchRequest: - cnrV2 := req.GetBody().GetContainerID() - var cnr cid.ID - - if cnrV2 != nil { - if err := cnr.ReadFromV2(*cnrV2); err != nil { - return fmt.Errorf("can't parse container ID: %w", err) - } - } - - dst.objectHeaders = []eaclSDK.Header{cidHeader(cnr)} - } - return nil -} - -func (h *cfg) readObjectHeadersResponseXHeaderSource(m responseXHeaderSource, dst *headerSource) error { - switch resp := m.resp.(type) { - default: - objectHeaders, completed := h.localObjectHeaders(h.cnr, h.obj) - - dst.objectHeaders = objectHeaders - dst.incompleteObjectHeaders = !completed - case *objectV2.GetResponse: - if v, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok { - oV2 := new(objectV2.Object) - oV2.SetObjectID(v.GetObjectID()) - oV2.SetHeader(v.GetHeader()) - - dst.objectHeaders = headersFromObject(objectSDK.NewFromV2(oV2), h.cnr, h.obj) - } - case *objectV2.HeadResponse: - oV2 := new(objectV2.Object) - - var hdr *objectV2.Header - - switch v := resp.GetBody().GetHeaderPart().(type) { - case *objectV2.ShortHeader: - hdr = new(objectV2.Header) - - var idV2 refsV2.ContainerID - h.cnr.WriteToV2(&idV2) - - hdr.SetContainerID(&idV2) - hdr.SetVersion(v.GetVersion()) - hdr.SetCreationEpoch(v.GetCreationEpoch()) - hdr.SetOwnerID(v.GetOwnerID()) - hdr.SetObjectType(v.GetObjectType()) - hdr.SetPayloadLength(v.GetPayloadLength()) - case *objectV2.HeaderWithSignature: - hdr = v.GetHeader() - } - - oV2.SetHeader(hdr) - - dst.objectHeaders = headersFromObject(objectSDK.NewFromV2(oV2), h.cnr, h.obj) - } - return nil -} - -func (h *cfg) localObjectHeaders(cnr cid.ID, idObj *oid.ID) ([]eaclSDK.Header, bool) { - if idObj != nil { - var addr oid.Address - addr.SetContainer(cnr) - addr.SetObject(*idObj) - - obj, err := h.storage.Head(context.TODO(), addr) - if err == nil { - return headersFromObject(obj, cnr, idObj), true - } - } - - return addressHeaders(cnr, idObj), false -} - -func cidHeader(idCnr cid.ID) sysObjHdr { - return sysObjHdr{ - k: acl.FilterObjectContainerID, - v: idCnr.EncodeToString(), - } -} - -func oidHeader(obj oid.ID) sysObjHdr { - return sysObjHdr{ - k: acl.FilterObjectID, - v: obj.EncodeToString(), - } -} - -func ownerIDHeader(ownerID user.ID) sysObjHdr { - return sysObjHdr{ - k: acl.FilterObjectOwnerID, - v: ownerID.EncodeToString(), - } -} - -func addressHeaders(cnr cid.ID, oid *oid.ID) []eaclSDK.Header { - hh := make([]eaclSDK.Header, 0, 2) - hh = append(hh, cidHeader(cnr)) - - if oid != nil { - hh = append(hh, oidHeader(*oid)) - } - - return hh -} diff --git a/pkg/services/object/acl/eacl/v2/object.go b/pkg/services/object/acl/eacl/v2/object.go deleted file mode 100644 index 92570a3c58..0000000000 --- a/pkg/services/object/acl/eacl/v2/object.go +++ /dev/null @@ -1,92 +0,0 @@ -package v2 - -import ( - "strconv" - - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" - objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" -) - -type sysObjHdr struct { - k, v string -} - -func (s sysObjHdr) Key() string { - return s.k -} - -func (s sysObjHdr) Value() string { - return s.v -} - -func u64Value(v uint64) string { - return strconv.FormatUint(v, 10) -} - -func headersFromObject(obj *objectSDK.Object, cnr cid.ID, oid *oid.ID) []eaclSDK.Header { - var count int - for obj := obj; obj != nil; obj = obj.Parent() { - count += 9 + len(obj.Attributes()) - } - - res := make([]eaclSDK.Header, 0, count) - for ; obj != nil; obj = obj.Parent() { - res = append(res, - cidHeader(cnr), - // creation epoch - sysObjHdr{ - k: acl.FilterObjectCreationEpoch, - v: u64Value(obj.CreationEpoch()), - }, - // payload size - sysObjHdr{ - k: acl.FilterObjectPayloadLength, - v: u64Value(obj.PayloadSize()), - }, - // object version - sysObjHdr{ - k: acl.FilterObjectVersion, - v: obj.Version().String(), - }, - // object type - sysObjHdr{ - k: acl.FilterObjectType, - v: obj.Type().String(), - }, - ) - - if oid != nil { - res = append(res, oidHeader(*oid)) - } - - if idOwner := obj.OwnerID(); !idOwner.IsEmpty() { - res = append(res, ownerIDHeader(idOwner)) - } - - cs, ok := obj.PayloadChecksum() - if ok { - res = append(res, sysObjHdr{ - k: acl.FilterObjectPayloadHash, - v: cs.String(), - }) - } - - cs, ok = obj.PayloadHomomorphicHash() - if ok { - res = append(res, sysObjHdr{ - k: acl.FilterObjectHomomorphicHash, - v: cs.String(), - }) - } - - attrs := obj.Attributes() - for i := range attrs { - res = append(res, &attrs[i]) // only pointer attrs can implement eaclSDK.Header interface - } - } - - return res -} diff --git a/pkg/services/object/acl/eacl/v2/opts.go b/pkg/services/object/acl/eacl/v2/opts.go deleted file mode 100644 index d91a21c752..0000000000 --- a/pkg/services/object/acl/eacl/v2/opts.go +++ /dev/null @@ -1,11 +0,0 @@ -package v2 - -import ( - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" -) - -func WithOID(v *oid.ID) Option { - return func(c *cfg) { - c.obj = v - } -} diff --git a/pkg/services/object/acl/eacl/v2/xheader.go b/pkg/services/object/acl/eacl/v2/xheader.go deleted file mode 100644 index ce380c117a..0000000000 --- a/pkg/services/object/acl/eacl/v2/xheader.go +++ /dev/null @@ -1,69 +0,0 @@ -package v2 - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" - eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl" -) - -type XHeaderSource interface { - GetXHeaders() []eaclSDK.Header -} - -type requestXHeaderSource struct { - req Request -} - -func NewRequestXHeaderSource(req Request) XHeaderSource { - return requestXHeaderSource{req: req} -} - -type responseXHeaderSource struct { - resp Response - - req Request -} - -func NewResponseXHeaderSource(resp Response, req Request) XHeaderSource { - return responseXHeaderSource{resp: resp, req: req} -} - -func (s requestXHeaderSource) GetXHeaders() []eaclSDK.Header { - ln := 0 - - for meta := s.req.GetMetaHeader(); meta != nil; meta = meta.GetOrigin() { - ln += len(meta.GetXHeaders()) - } - - res := make([]eaclSDK.Header, 0, ln) - for meta := s.req.GetMetaHeader(); meta != nil; meta = meta.GetOrigin() { - x := meta.GetXHeaders() - for i := range x { - res = append(res, (xHeader)(x[i])) - } - } - - return res -} - -func (s responseXHeaderSource) GetXHeaders() []eaclSDK.Header { - ln := 0 - xHdrs := make([][]session.XHeader, 0) - - for meta := s.req.GetMetaHeader(); meta != nil; meta = meta.GetOrigin() { - x := meta.GetXHeaders() - - ln += len(x) - - xHdrs = append(xHdrs, x) - } - - res := make([]eaclSDK.Header, 0, ln) - - for i := range xHdrs { - for j := range xHdrs[i] { - res = append(res, xHeader(xHdrs[i][j])) - } - } - - return res -} diff --git a/pkg/services/object/acl/v2/errors.go b/pkg/services/object/acl/v2/errors.go deleted file mode 100644 index cd2de174ae..0000000000 --- a/pkg/services/object/acl/v2/errors.go +++ /dev/null @@ -1,20 +0,0 @@ -package v2 - -import ( - "fmt" -) - -const invalidRequestMessage = "malformed request" - -func malformedRequestError(reason string) error { - return fmt.Errorf("%s: %s", invalidRequestMessage, reason) -} - -var ( - errEmptyBody = malformedRequestError("empty body") - errEmptyVerificationHeader = malformedRequestError("empty verification header") - errEmptyBodySig = malformedRequestError("empty at body signature") - errInvalidSessionSig = malformedRequestError("invalid session token signature") - errInvalidSessionOwner = malformedRequestError("invalid session token owner") - errInvalidVerb = malformedRequestError("session token verb is invalid") -) diff --git a/pkg/services/object/acl/v2/opts.go b/pkg/services/object/acl/v2/opts.go deleted file mode 100644 index 15fcce884e..0000000000 --- a/pkg/services/object/acl/v2/opts.go +++ /dev/null @@ -1,12 +0,0 @@ -package v2 - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" -) - -// WithLogger returns option to set logger. -func WithLogger(v *logger.Logger) Option { - return func(c *cfg) { - c.log = v - } -} diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go deleted file mode 100644 index 8bd34ccb36..0000000000 --- a/pkg/services/object/acl/v2/request.go +++ /dev/null @@ -1,152 +0,0 @@ -package v2 - -import ( - "crypto/ecdsa" - "fmt" - - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" -) - -// RequestInfo groups parsed version-independent (from SDK library) -// request information and raw API request. -type RequestInfo struct { - basicACL acl.Basic - requestRole acl.Role - operation acl.Op // put, get, head, etc. - cnrOwner user.ID // container owner - - // cnrNamespace defined to which namespace a container is belonged. - cnrNamespace string - - idCnr cid.ID - - // optional for some request - // e.g. Put, Search - obj *oid.ID - - senderKey []byte - - bearer *bearer.Token // bearer token of request - - srcRequest any -} - -func (r *RequestInfo) SetBasicACL(basicACL acl.Basic) { - r.basicACL = basicACL -} - -func (r *RequestInfo) SetRequestRole(requestRole acl.Role) { - r.requestRole = requestRole -} - -func (r *RequestInfo) SetSenderKey(senderKey []byte) { - r.senderKey = senderKey -} - -// Request returns raw API request. -func (r RequestInfo) Request() any { - return r.srcRequest -} - -// ContainerOwner returns owner if the container. -func (r RequestInfo) ContainerOwner() user.ID { - return r.cnrOwner -} - -func (r RequestInfo) ContainerNamespace() string { - return r.cnrNamespace -} - -// ObjectID return object ID. -func (r RequestInfo) ObjectID() *oid.ID { - return r.obj -} - -// ContainerID return container ID. -func (r RequestInfo) ContainerID() cid.ID { - return r.idCnr -} - -// CleanBearer forces cleaning bearer token information. -func (r *RequestInfo) CleanBearer() { - r.bearer = nil -} - -// Bearer returns bearer token of the request. -func (r RequestInfo) Bearer() *bearer.Token { - return r.bearer -} - -// BasicACL returns basic ACL of the container. -func (r RequestInfo) BasicACL() acl.Basic { - return r.basicACL -} - -// SenderKey returns public key of the request's sender. -func (r RequestInfo) SenderKey() []byte { - return r.senderKey -} - -// Operation returns request's operation. -func (r RequestInfo) Operation() acl.Op { - return r.operation -} - -// RequestRole returns request sender's role. -func (r RequestInfo) RequestRole() acl.Role { - return r.requestRole -} - -// MetaWithToken groups session and bearer tokens, -// verification header and raw API request. -type MetaWithToken struct { - vheader *sessionV2.RequestVerificationHeader - token *sessionSDK.Object - bearer *bearer.Token - src any -} - -// RequestOwner returns ownerID and its public key -// according to internal meta information. -func (r MetaWithToken) RequestOwner() (*user.ID, *keys.PublicKey, error) { - if r.vheader == nil { - return nil, nil, errEmptyVerificationHeader - } - - if r.bearer != nil && r.bearer.Impersonate() { - return unmarshalPublicKeyWithOwner(r.bearer.SigningKeyBytes()) - } - - // if session token is presented, use it as truth source - if r.token != nil { - // verify signature of session token - return ownerFromToken(r.token) - } - - // otherwise get original body signature - bodySignature := originalBodySignature(r.vheader) - if bodySignature == nil { - return nil, nil, errEmptyBodySig - } - - return unmarshalPublicKeyWithOwner(bodySignature.GetKey()) -} - -func unmarshalPublicKeyWithOwner(rawKey []byte) (*user.ID, *keys.PublicKey, error) { - key, err := unmarshalPublicKey(rawKey) - if err != nil { - return nil, nil, fmt.Errorf("invalid signature key: %w", err) - } - - var idSender user.ID - user.IDFromKey(&idSender, (ecdsa.PublicKey)(*key)) - - return &idSender, key, nil -} diff --git a/pkg/services/object/acl/v2/request_test.go b/pkg/services/object/acl/v2/request_test.go deleted file mode 100644 index 618af3469b..0000000000 --- a/pkg/services/object/acl/v2/request_test.go +++ /dev/null @@ -1,164 +0,0 @@ -package v2 - -import ( - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" - sigutilV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/util/signature" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/google/uuid" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/stretchr/testify/require" -) - -func TestRequestOwner(t *testing.T) { - containerOwner, err := keys.NewPrivateKey() - require.NoError(t, err) - - userPk, err := keys.NewPrivateKey() - require.NoError(t, err) - - var userID user.ID - user.IDFromKey(&userID, userPk.PrivateKey.PublicKey) - - var userSignature refs.Signature - userSignature.SetKey(userPk.PublicKey().Bytes()) - - vh := new(sessionV2.RequestVerificationHeader) - vh.SetBodySignature(&userSignature) - - t.Run("empty verification header", func(t *testing.T) { - req := MetaWithToken{} - checkOwner(t, req, nil, errEmptyVerificationHeader) - }) - t.Run("empty verification header signature", func(t *testing.T) { - req := MetaWithToken{ - vheader: new(sessionV2.RequestVerificationHeader), - } - checkOwner(t, req, nil, errEmptyBodySig) - }) - t.Run("no tokens", func(t *testing.T) { - req := MetaWithToken{ - vheader: vh, - } - checkOwner(t, req, userPk.PublicKey(), nil) - }) - - t.Run("bearer without impersonate, no session", func(t *testing.T) { - req := MetaWithToken{ - vheader: vh, - bearer: newBearer(t, containerOwner, userID, false), - } - checkOwner(t, req, userPk.PublicKey(), nil) - }) - t.Run("bearer with impersonate, no session", func(t *testing.T) { - req := MetaWithToken{ - vheader: vh, - bearer: newBearer(t, containerOwner, userID, true), - } - checkOwner(t, req, containerOwner.PublicKey(), nil) - }) - t.Run("bearer with impersonate, with session", func(t *testing.T) { - // To check that bearer token takes priority, use different key to sign session token. - pk, err := keys.NewPrivateKey() - require.NoError(t, err) - - req := MetaWithToken{ - vheader: vh, - bearer: newBearer(t, containerOwner, userID, true), - token: newSession(t, pk), - } - checkOwner(t, req, containerOwner.PublicKey(), nil) - }) - t.Run("with session", func(t *testing.T) { - req := MetaWithToken{ - vheader: vh, - token: newSession(t, containerOwner), - } - checkOwner(t, req, containerOwner.PublicKey(), nil) - }) - t.Run("malformed session token", func(t *testing.T) { - // This test is tricky: session token has issuer field and signature, which must correspond to each other. - // SDK prevents constructing such token in the first place, but it is still possible via API. - // Thus, construct v2 token, convert it to SDK one and pass to our function. - pk, err := keys.NewPrivateKey() - require.NoError(t, err) - - var user1 user.ID - user.IDFromKey(&user1, pk.PrivateKey.PublicKey) - - var id refs.OwnerID - id.SetValue(user1.WalletBytes()) - - raw, err := uuid.New().MarshalBinary() - require.NoError(t, err) - - var cidV2 refs.ContainerID - cidtest.ID().WriteToV2(&cidV2) - - sessionCtx := new(sessionV2.ObjectSessionContext) - sessionCtx.SetTarget(&cidV2) - - var body sessionV2.TokenBody - body.SetOwnerID(&id) - body.SetID(raw) - body.SetLifetime(new(sessionV2.TokenLifetime)) - body.SetSessionKey(pk.PublicKey().Bytes()) - body.SetContext(sessionCtx) - - var tokV2 sessionV2.Token - tokV2.SetBody(&body) - require.NoError(t, sigutilV2.SignData(&containerOwner.PrivateKey, smWrapper{Token: &tokV2})) - require.NoError(t, sigutilV2.VerifyData(smWrapper{Token: &tokV2})) - - var tok sessionSDK.Object - require.NoError(t, tok.ReadFromV2(tokV2)) - - req := MetaWithToken{ - vheader: vh, - token: &tok, - } - checkOwner(t, req, nil, errInvalidSessionOwner) - }) -} - -type smWrapper struct { - *sessionV2.Token -} - -func (s smWrapper) ReadSignedData(data []byte) ([]byte, error) { - return s.Token.GetBody().StableMarshal(data), nil -} - -func (s smWrapper) SignedDataSize() int { - return s.Token.GetBody().StableSize() -} - -func newSession(t *testing.T, pk *keys.PrivateKey) *sessionSDK.Object { - var tok sessionSDK.Object - require.NoError(t, tok.Sign(pk.PrivateKey)) - return &tok -} - -func newBearer(t *testing.T, pk *keys.PrivateKey, user user.ID, impersonate bool) *bearer.Token { - var tok bearer.Token - tok.SetImpersonate(impersonate) - tok.ForUser(user) - require.NoError(t, tok.Sign(pk.PrivateKey)) - return &tok -} - -func checkOwner(t *testing.T, req MetaWithToken, expected *keys.PublicKey, expectedErr error) { - _, actual, err := req.RequestOwner() - if expectedErr != nil { - require.ErrorIs(t, err, expectedErr) - return - } - - require.NoError(t, err) - require.Equal(t, expected, actual) -} diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go deleted file mode 100644 index 86daec6cc9..0000000000 --- a/pkg/services/object/acl/v2/service.go +++ /dev/null @@ -1,779 +0,0 @@ -package v2 - -import ( - "context" - "errors" - "fmt" - "strings" - - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" - objectCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" - apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" - cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "go.uber.org/zap" -) - -// Service checks basic ACL rules. -type Service struct { - *cfg - - c objectCore.SenderClassifier -} - -type putStreamBasicChecker struct { - source *Service - next object.PutObjectStream -} - -type patchStreamBasicChecker struct { - source *Service - next object.PatchObjectStream - nonFirstSend bool -} - -// Option represents Service constructor option. -type Option func(*cfg) - -type cfg struct { - log *logger.Logger - - containers container.Source - - irFetcher InnerRingFetcher - - nm netmap.Source - - next object.ServiceServer -} - -// New is a constructor for object ACL checking service. -func New(next object.ServiceServer, - nm netmap.Source, - irf InnerRingFetcher, - cs container.Source, - opts ...Option, -) Service { - cfg := &cfg{ - log: logger.NewLoggerWrapper(zap.L()), - next: next, - nm: nm, - irFetcher: irf, - containers: cs, - } - - for i := range opts { - opts[i](cfg) - } - - return Service{ - cfg: cfg, - c: objectCore.NewSenderClassifier(cfg.irFetcher, cfg.nm, cfg.log), - } -} - -// wrappedGetObjectStream propagates RequestContext into GetObjectStream's context. -// This allows to retrieve already calculated immutable request-specific values in next handler invocation. -type wrappedGetObjectStream struct { - object.GetObjectStream - - requestInfo RequestInfo -} - -func (w *wrappedGetObjectStream) Context() context.Context { - return context.WithValue(w.GetObjectStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - ContainerOwner: w.requestInfo.ContainerOwner(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - BearerToken: w.requestInfo.Bearer(), - }) -} - -func newWrappedGetObjectStreamStream(getObjectStream object.GetObjectStream, reqInfo RequestInfo) object.GetObjectStream { - return &wrappedGetObjectStream{ - GetObjectStream: getObjectStream, - requestInfo: reqInfo, - } -} - -// wrappedRangeStream propagates RequestContext into GetObjectRangeStream's context. -// This allows to retrieve already calculated immutable request-specific values in next handler invocation. -type wrappedRangeStream struct { - object.GetObjectRangeStream - - requestInfo RequestInfo -} - -func (w *wrappedRangeStream) Context() context.Context { - return context.WithValue(w.GetObjectRangeStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - ContainerOwner: w.requestInfo.ContainerOwner(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - BearerToken: w.requestInfo.Bearer(), - }) -} - -func newWrappedRangeStream(rangeStream object.GetObjectRangeStream, reqInfo RequestInfo) object.GetObjectRangeStream { - return &wrappedRangeStream{ - GetObjectRangeStream: rangeStream, - requestInfo: reqInfo, - } -} - -// wrappedSearchStream propagates RequestContext into SearchStream's context. -// This allows to retrieve already calculated immutable request-specific values in next handler invocation. -type wrappedSearchStream struct { - object.SearchStream - - requestInfo RequestInfo -} - -func (w *wrappedSearchStream) Context() context.Context { - return context.WithValue(w.SearchStream.Context(), object.RequestContextKey, &object.RequestContext{ - Namespace: w.requestInfo.ContainerNamespace(), - ContainerOwner: w.requestInfo.ContainerOwner(), - SenderKey: w.requestInfo.SenderKey(), - Role: w.requestInfo.RequestRole(), - BearerToken: w.requestInfo.Bearer(), - }) -} - -func newWrappedSearchStream(searchStream object.SearchStream, reqInfo RequestInfo) object.SearchStream { - return &wrappedSearchStream{ - SearchStream: searchStream, - requestInfo: reqInfo, - } -} - -// Get implements ServiceServer interface, makes ACL checks and calls -// next Get method in the ServiceServer pipeline. -func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream) error { - cnr, err := getContainerIDFromRequest(request) - if err != nil { - return err - } - - obj, err := getObjectIDFromRequestBody(request.GetBody()) - if err != nil { - return err - } - - sTok, err := originalSessionToken(request.GetMetaHeader()) - if err != nil { - return err - } - - if sTok != nil { - err = assertSessionRelation(*sTok, cnr, obj) - if err != nil { - return err - } - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := b.findRequestInfo(stream.Context(), req, cnr, acl.OpObjectGet) - if err != nil { - return err - } - - reqInfo.obj = obj - - return b.next.Get(request, newWrappedGetObjectStreamStream(stream, reqInfo)) -} - -func (b Service) Put(ctx context.Context) (object.PutObjectStream, error) { - streamer, err := b.next.Put(ctx) - - return putStreamBasicChecker{ - source: &b, - next: streamer, - }, err -} - -func (b Service) Patch(ctx context.Context) (object.PatchObjectStream, error) { - streamer, err := b.next.Patch(ctx) - - return &patchStreamBasicChecker{ - source: &b, - next: streamer, - }, err -} - -func (b Service) Head( - ctx context.Context, - request *objectV2.HeadRequest, -) (*objectV2.HeadResponse, error) { - cnr, err := getContainerIDFromRequest(request) - if err != nil { - return nil, err - } - - obj, err := getObjectIDFromRequestBody(request.GetBody()) - if err != nil { - return nil, err - } - - sTok, err := originalSessionToken(request.GetMetaHeader()) - if err != nil { - return nil, err - } - - if sTok != nil { - err = assertSessionRelation(*sTok, cnr, obj) - if err != nil { - return nil, err - } - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return nil, err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := b.findRequestInfo(ctx, req, cnr, acl.OpObjectHead) - if err != nil { - return nil, err - } - - reqInfo.obj = obj - - return b.next.Head(requestContext(ctx, reqInfo), request) -} - -func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStream) error { - id, err := getContainerIDFromRequest(request) - if err != nil { - return err - } - - sTok, err := originalSessionToken(request.GetMetaHeader()) - if err != nil { - return err - } - - if sTok != nil { - err = assertSessionRelation(*sTok, id, nil) - if err != nil { - return err - } - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := b.findRequestInfo(stream.Context(), req, id, acl.OpObjectSearch) - if err != nil { - return err - } - - return b.next.Search(request, newWrappedSearchStream(stream, reqInfo)) -} - -func (b Service) Delete( - ctx context.Context, - request *objectV2.DeleteRequest, -) (*objectV2.DeleteResponse, error) { - cnr, err := getContainerIDFromRequest(request) - if err != nil { - return nil, err - } - - obj, err := getObjectIDFromRequestBody(request.GetBody()) - if err != nil { - return nil, err - } - - sTok, err := originalSessionToken(request.GetMetaHeader()) - if err != nil { - return nil, err - } - - if sTok != nil { - err = assertSessionRelation(*sTok, cnr, obj) - if err != nil { - return nil, err - } - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return nil, err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := b.findRequestInfo(ctx, req, cnr, acl.OpObjectDelete) - if err != nil { - return nil, err - } - - reqInfo.obj = obj - - return b.next.Delete(requestContext(ctx, reqInfo), request) -} - -func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetObjectRangeStream) error { - cnr, err := getContainerIDFromRequest(request) - if err != nil { - return err - } - - obj, err := getObjectIDFromRequestBody(request.GetBody()) - if err != nil { - return err - } - - sTok, err := originalSessionToken(request.GetMetaHeader()) - if err != nil { - return err - } - - if sTok != nil { - err = assertSessionRelation(*sTok, cnr, obj) - if err != nil { - return err - } - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := b.findRequestInfo(stream.Context(), req, cnr, acl.OpObjectRange) - if err != nil { - return err - } - - reqInfo.obj = obj - - return b.next.GetRange(request, newWrappedRangeStream(stream, reqInfo)) -} - -func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context { - return context.WithValue(ctx, object.RequestContextKey, &object.RequestContext{ - Namespace: reqInfo.ContainerNamespace(), - ContainerOwner: reqInfo.ContainerOwner(), - SenderKey: reqInfo.SenderKey(), - Role: reqInfo.RequestRole(), - BearerToken: reqInfo.Bearer(), - }) -} - -func (b Service) GetRangeHash( - ctx context.Context, - request *objectV2.GetRangeHashRequest, -) (*objectV2.GetRangeHashResponse, error) { - cnr, err := getContainerIDFromRequest(request) - if err != nil { - return nil, err - } - - obj, err := getObjectIDFromRequestBody(request.GetBody()) - if err != nil { - return nil, err - } - - sTok, err := originalSessionToken(request.GetMetaHeader()) - if err != nil { - return nil, err - } - - if sTok != nil { - err = assertSessionRelation(*sTok, cnr, obj) - if err != nil { - return nil, err - } - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return nil, err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := b.findRequestInfo(ctx, req, cnr, acl.OpObjectHash) - if err != nil { - return nil, err - } - - reqInfo.obj = obj - - return b.next.GetRangeHash(requestContext(ctx, reqInfo), request) -} - -func (b Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequest) (*objectV2.PutSingleResponse, error) { - cnr, err := getContainerIDFromRequest(request) - if err != nil { - return nil, err - } - - idV2 := request.GetBody().GetObject().GetHeader().GetOwnerID() - if idV2 == nil { - return nil, errors.New("missing object owner") - } - - var idOwner user.ID - - err = idOwner.ReadFromV2(*idV2) - if err != nil { - return nil, fmt.Errorf("invalid object owner: %w", err) - } - - obj, err := getObjectIDFromRefObjectID(request.GetBody().GetObject().GetObjectID()) - if err != nil { - return nil, err - } - - var sTok *sessionSDK.Object - sTok, err = readSessionToken(cnr, obj, request.GetMetaHeader().GetSessionToken()) - if err != nil { - return nil, err - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return nil, err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := b.findRequestInfo(ctx, req, cnr, acl.OpObjectPut) - if err != nil { - return nil, err - } - - reqInfo.obj = obj - - return b.next.PutSingle(requestContext(ctx, reqInfo), request) -} - -func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRequest) error { - body := request.GetBody() - if body == nil { - return errEmptyBody - } - - part := body.GetObjectPart() - if part, ok := part.(*objectV2.PutObjectPartInit); ok { - cnr, err := getContainerIDFromRequest(request) - if err != nil { - return err - } - - idV2 := part.GetHeader().GetOwnerID() - if idV2 == nil { - return errors.New("missing object owner") - } - - var idOwner user.ID - - err = idOwner.ReadFromV2(*idV2) - if err != nil { - return fmt.Errorf("invalid object owner: %w", err) - } - - objV2 := part.GetObjectID() - var obj *oid.ID - - if objV2 != nil { - obj = new(oid.ID) - - err = obj.ReadFromV2(*objV2) - if err != nil { - return err - } - } - - var sTok *sessionSDK.Object - sTok, err = readSessionToken(cnr, obj, request.GetMetaHeader().GetSessionToken()) - if err != nil { - return err - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := p.source.findRequestInfo(ctx, req, cnr, acl.OpObjectPut) - if err != nil { - return err - } - - reqInfo.obj = obj - - ctx = requestContext(ctx, reqInfo) - } - - return p.next.Send(ctx, request) -} - -func readSessionToken(cnr cid.ID, obj *oid.ID, tokV2 *session.Token) (*sessionSDK.Object, error) { - var sTok *sessionSDK.Object - - if tokV2 != nil { - sTok = new(sessionSDK.Object) - - err := sTok.ReadFromV2(*tokV2) - if err != nil { - return nil, fmt.Errorf("invalid session token: %w", err) - } - - if sTok.AssertVerb(sessionSDK.VerbObjectDelete) { - // if session relates to object's removal, we don't check - // relation of the tombstone to the session here since user - // can't predict tomb's ID. - err = assertSessionRelation(*sTok, cnr, nil) - } else { - err = assertSessionRelation(*sTok, cnr, obj) - } - - if err != nil { - return nil, err - } - } - - return sTok, nil -} - -func (p putStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PutResponse, error) { - return p.next.CloseAndRecv(ctx) -} - -func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error { - body := request.GetBody() - if body == nil { - return errEmptyBody - } - - if !p.nonFirstSend { - p.nonFirstSend = true - - cnr, err := getContainerIDFromRequest(request) - if err != nil { - return err - } - - objV2 := request.GetBody().GetAddress().GetObjectID() - if objV2 == nil { - return errors.New("missing oid") - } - obj := new(oid.ID) - err = obj.ReadFromV2(*objV2) - if err != nil { - return err - } - - var sTok *sessionSDK.Object - sTok, err = readSessionToken(cnr, obj, request.GetMetaHeader().GetSessionToken()) - if err != nil { - return err - } - - bTok, err := originalBearerToken(request.GetMetaHeader()) - if err != nil { - return err - } - - req := MetaWithToken{ - vheader: request.GetVerificationHeader(), - token: sTok, - bearer: bTok, - src: request, - } - - reqInfo, err := p.source.findRequestInfoWithoutACLOperationAssert(ctx, req, cnr) - if err != nil { - return err - } - - reqInfo.obj = obj - - ctx = requestContext(ctx, reqInfo) - } - - return p.next.Send(ctx, request) -} - -func (p patchStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PatchResponse, error) { - return p.next.CloseAndRecv(ctx) -} - -func (b Service) findRequestInfo(ctx context.Context, req MetaWithToken, idCnr cid.ID, op acl.Op) (info RequestInfo, err error) { - cnr, err := b.containers.Get(ctx, idCnr) // fetch actual container - if err != nil { - return info, err - } - - if req.token != nil { - currentEpoch, err := b.nm.Epoch(ctx) - if err != nil { - return info, errors.New("can't fetch current epoch") - } - if req.token.ExpiredAt(currentEpoch) { - return info, new(apistatus.SessionTokenExpired) - } - if req.token.InvalidAt(currentEpoch) { - return info, fmt.Errorf("%s: token is invalid at %d epoch)", - invalidRequestMessage, currentEpoch) - } - - if !assertVerb(*req.token, op) { - return info, errInvalidVerb - } - } - - // find request role and key - ownerID, ownerKey, err := req.RequestOwner() - if err != nil { - return info, err - } - res, err := b.c.Classify(ctx, ownerID, ownerKey, idCnr, cnr.Value) - if err != nil { - return info, err - } - - info.basicACL = cnr.Value.BasicACL() - info.requestRole = res.Role - info.operation = op - info.cnrOwner = cnr.Value.Owner() - info.idCnr = idCnr - - cnrNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cnr.Value).Zone(), ".ns") - if hasNamespace { - info.cnrNamespace = cnrNamespace - } - - // it is assumed that at the moment the key will be valid, - // otherwise the request would not pass validation - info.senderKey = res.Key - - // add bearer token if it is present in request - info.bearer = req.bearer - - info.srcRequest = req.src - - return info, nil -} - -// findRequestInfoWithoutACLOperationAssert is findRequestInfo without session token verb assert. -func (b Service) findRequestInfoWithoutACLOperationAssert(ctx context.Context, req MetaWithToken, idCnr cid.ID) (info RequestInfo, err error) { - cnr, err := b.containers.Get(ctx, idCnr) // fetch actual container - if err != nil { - return info, err - } - - if req.token != nil { - currentEpoch, err := b.nm.Epoch(ctx) - if err != nil { - return info, errors.New("can't fetch current epoch") - } - if req.token.ExpiredAt(currentEpoch) { - return info, new(apistatus.SessionTokenExpired) - } - if req.token.InvalidAt(currentEpoch) { - return info, fmt.Errorf("%s: token is invalid at %d epoch)", - invalidRequestMessage, currentEpoch) - } - } - - // find request role and key - ownerID, ownerKey, err := req.RequestOwner() - if err != nil { - return info, err - } - res, err := b.c.Classify(ctx, ownerID, ownerKey, idCnr, cnr.Value) - if err != nil { - return info, err - } - - info.basicACL = cnr.Value.BasicACL() - info.requestRole = res.Role - info.cnrOwner = cnr.Value.Owner() - info.idCnr = idCnr - - cnrNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cnr.Value).Zone(), ".ns") - if hasNamespace { - info.cnrNamespace = cnrNamespace - } - - // it is assumed that at the moment the key will be valid, - // otherwise the request would not pass validation - info.senderKey = res.Key - - // add bearer token if it is present in request - info.bearer = req.bearer - - info.srcRequest = req.src - - return info, nil -} diff --git a/pkg/services/object/acl/v2/types.go b/pkg/services/object/acl/v2/types.go deleted file mode 100644 index 3cf10eb562..0000000000 --- a/pkg/services/object/acl/v2/types.go +++ /dev/null @@ -1,11 +0,0 @@ -package v2 - -import "context" - -// InnerRingFetcher is an interface that must provide -// Inner Ring information. -type InnerRingFetcher interface { - // InnerRingKeys must return list of public keys of - // the actual inner ring. - InnerRingKeys(ctx context.Context) ([][]byte, error) -} diff --git a/pkg/services/object/acl/v2/util.go b/pkg/services/object/acl/v2/util.go deleted file mode 100644 index e02f707716..0000000000 --- a/pkg/services/object/acl/v2/util.go +++ /dev/null @@ -1,223 +0,0 @@ -package v2 - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "errors" - "fmt" - - objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" - refsV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/refs" - sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" - oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" -) - -var errMissingContainerID = errors.New("missing container ID") - -func getContainerIDFromRequest(req any) (cid.ID, error) { - var idV2 *refsV2.ContainerID - var id cid.ID - - switch v := req.(type) { - case *objectV2.GetRequest: - idV2 = v.GetBody().GetAddress().GetContainerID() - case *objectV2.PutRequest: - part, ok := v.GetBody().GetObjectPart().(*objectV2.PutObjectPartInit) - if !ok { - return cid.ID{}, errors.New("can't get container ID in chunk") - } - - idV2 = part.GetHeader().GetContainerID() - case *objectV2.HeadRequest: - idV2 = v.GetBody().GetAddress().GetContainerID() - case *objectV2.SearchRequest: - idV2 = v.GetBody().GetContainerID() - case *objectV2.DeleteRequest: - idV2 = v.GetBody().GetAddress().GetContainerID() - case *objectV2.GetRangeRequest: - idV2 = v.GetBody().GetAddress().GetContainerID() - case *objectV2.GetRangeHashRequest: - idV2 = v.GetBody().GetAddress().GetContainerID() - case *objectV2.PutSingleRequest: - idV2 = v.GetBody().GetObject().GetHeader().GetContainerID() - case *objectV2.PatchRequest: - idV2 = v.GetBody().GetAddress().GetContainerID() - default: - return cid.ID{}, errors.New("unknown request type") - } - - if idV2 == nil { - return cid.ID{}, errMissingContainerID - } - - return id, id.ReadFromV2(*idV2) -} - -// originalBearerToken goes down to original request meta header and fetches -// bearer token from there. -func originalBearerToken(header *sessionV2.RequestMetaHeader) (*bearer.Token, error) { - for header.GetOrigin() != nil { - header = header.GetOrigin() - } - - tokV2 := header.GetBearerToken() - if tokV2 == nil { - return nil, nil - } - - var tok bearer.Token - return &tok, tok.ReadFromV2(*tokV2) -} - -// originalSessionToken goes down to original request meta header and fetches -// session token from there. -func originalSessionToken(header *sessionV2.RequestMetaHeader) (*sessionSDK.Object, error) { - for header.GetOrigin() != nil { - header = header.GetOrigin() - } - - tokV2 := header.GetSessionToken() - if tokV2 == nil { - return nil, nil - } - - var tok sessionSDK.Object - - err := tok.ReadFromV2(*tokV2) - if err != nil { - return nil, fmt.Errorf("invalid session token: %w", err) - } - - return &tok, nil -} - -// getObjectIDFromRequestBody decodes oid.ID from the common interface of the -// object reference's holders. Returns an error if object ID is missing in the request. -func getObjectIDFromRequestBody(body interface{ GetAddress() *refsV2.Address }) (*oid.ID, error) { - idV2 := body.GetAddress().GetObjectID() - return getObjectIDFromRefObjectID(idV2) -} - -func getObjectIDFromRefObjectID(idV2 *refsV2.ObjectID) (*oid.ID, error) { - if idV2 == nil { - return nil, errors.New("missing object ID") - } - - var id oid.ID - - err := id.ReadFromV2(*idV2) - if err != nil { - return nil, err - } - - return &id, nil -} - -func ownerFromToken(token *sessionSDK.Object) (*user.ID, *keys.PublicKey, error) { - // 1. First check signature of session token. - if !token.VerifySignature() { - return nil, nil, errInvalidSessionSig - } - - // 2. Then check if session token owner issued the session token - // TODO(@cthulhu-rider): #468 implement and use another approach to avoid conversion - var tokV2 sessionV2.Token - token.WriteToV2(&tokV2) - - tokenIssuerKey, err := unmarshalPublicKey(tokV2.GetSignature().GetKey()) - if err != nil { - return nil, nil, fmt.Errorf("invalid key in session token signature: %w", err) - } - - tokenIssuer := token.Issuer() - - if !isOwnerFromKey(tokenIssuer, tokenIssuerKey) { - // TODO: #767 in this case we can issue all owner keys from frostfs.id and check once again - return nil, nil, errInvalidSessionOwner - } - - return &tokenIssuer, tokenIssuerKey, nil -} - -func originalBodySignature(v *sessionV2.RequestVerificationHeader) *refsV2.Signature { - if v == nil { - return nil - } - - for v.GetOrigin() != nil { - v = v.GetOrigin() - } - - return v.GetBodySignature() -} - -func unmarshalPublicKey(bs []byte) (*keys.PublicKey, error) { - return keys.NewPublicKeyFromBytes(bs, elliptic.P256()) -} - -func isOwnerFromKey(id user.ID, key *keys.PublicKey) bool { - if key == nil { - return false - } - - var id2 user.ID - user.IDFromKey(&id2, (ecdsa.PublicKey)(*key)) - - return id2.Equals(id) -} - -// assertVerb checks that token verb corresponds to op. -func assertVerb(tok sessionSDK.Object, op acl.Op) bool { - switch op { - case acl.OpObjectPut: - return tok.AssertVerb(sessionSDK.VerbObjectPut, sessionSDK.VerbObjectDelete, sessionSDK.VerbObjectPatch) - case acl.OpObjectDelete: - return tok.AssertVerb(sessionSDK.VerbObjectDelete) - case acl.OpObjectGet: - return tok.AssertVerb(sessionSDK.VerbObjectGet) - case acl.OpObjectHead: - return tok.AssertVerb( - sessionSDK.VerbObjectHead, - sessionSDK.VerbObjectGet, - sessionSDK.VerbObjectDelete, - sessionSDK.VerbObjectRange, - sessionSDK.VerbObjectRangeHash, - sessionSDK.VerbObjectPatch, - ) - case acl.OpObjectSearch: - return tok.AssertVerb(sessionSDK.VerbObjectSearch, sessionSDK.VerbObjectDelete) - case acl.OpObjectRange: - return tok.AssertVerb(sessionSDK.VerbObjectRange, sessionSDK.VerbObjectRangeHash, sessionSDK.VerbObjectPatch) - case acl.OpObjectHash: - return tok.AssertVerb(sessionSDK.VerbObjectRangeHash) - } - - return false -} - -// assertSessionRelation checks if given token describing the FrostFS session -// relates to the given container and optional object. Missing object -// means that the context isn't bound to any FrostFS object in the container. -// Returns no error iff relation is correct. Criteria: -// -// session is bound to the given container -// object is not specified or session is bound to this object -// -// Session MUST be bound to the particular container, otherwise behavior is undefined. -func assertSessionRelation(tok sessionSDK.Object, cnr cid.ID, obj *oid.ID) error { - if !tok.AssertContainer(cnr) { - return errors.New("requested container is not related to the session") - } - - if obj != nil && !tok.AssertObject(*obj) { - return errors.New("requested object is not related to the session") - } - - return nil -} diff --git a/pkg/services/object/acl/v2/util_test.go b/pkg/services/object/acl/v2/util_test.go deleted file mode 100644 index 40fce88772..0000000000 --- a/pkg/services/object/acl/v2/util_test.go +++ /dev/null @@ -1,131 +0,0 @@ -package v2 - -import ( - "crypto/ecdsa" - "crypto/elliptic" - "crypto/rand" - "slices" - "testing" - - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/acl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" - bearertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer/test" - aclsdk "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" - oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test" - sessionSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" - sessiontest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session/test" - "github.com/stretchr/testify/require" -) - -func TestOriginalTokens(t *testing.T) { - sToken := sessiontest.ObjectSigned() - bToken := bearertest.Token() - - pk, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - require.NoError(t, bToken.Sign(*pk)) - - var bTokenV2 acl.BearerToken - bToken.WriteToV2(&bTokenV2) - // This line is needed because SDK uses some custom format for - // reserved filters, so `cid.ID` is not converted to string immediately. - require.NoError(t, bToken.ReadFromV2(bTokenV2)) - - var sTokenV2 session.Token - sToken.WriteToV2(&sTokenV2) - - for i := range 10 { - metaHeaders := testGenerateMetaHeader(uint32(i), &bTokenV2, &sTokenV2) - res, err := originalSessionToken(metaHeaders) - require.NoError(t, err) - require.Equal(t, sToken, res, i) - - bTok, err := originalBearerToken(metaHeaders) - require.NoError(t, err) - require.Equal(t, &bToken, bTok, i) - } -} - -func testGenerateMetaHeader(depth uint32, b *acl.BearerToken, s *session.Token) *session.RequestMetaHeader { - metaHeader := new(session.RequestMetaHeader) - metaHeader.SetBearerToken(b) - metaHeader.SetSessionToken(s) - - for range depth { - link := metaHeader - metaHeader = new(session.RequestMetaHeader) - metaHeader.SetOrigin(link) - } - - return metaHeader -} - -func TestIsVerbCompatible(t *testing.T) { - // Source: https://nspcc.ru/upload/frostfs-spec-latest.pdf#page=28 - table := map[aclsdk.Op][]sessionSDK.ObjectVerb{ - aclsdk.OpObjectPut: {sessionSDK.VerbObjectPut, sessionSDK.VerbObjectDelete}, - aclsdk.OpObjectDelete: {sessionSDK.VerbObjectDelete}, - aclsdk.OpObjectGet: {sessionSDK.VerbObjectGet}, - aclsdk.OpObjectHead: { - sessionSDK.VerbObjectHead, - sessionSDK.VerbObjectGet, - sessionSDK.VerbObjectDelete, - sessionSDK.VerbObjectRange, - sessionSDK.VerbObjectRangeHash, - }, - aclsdk.OpObjectRange: {sessionSDK.VerbObjectRange, sessionSDK.VerbObjectRangeHash}, - aclsdk.OpObjectHash: {sessionSDK.VerbObjectRangeHash}, - aclsdk.OpObjectSearch: {sessionSDK.VerbObjectSearch, sessionSDK.VerbObjectDelete}, - } - - verbs := []sessionSDK.ObjectVerb{ - sessionSDK.VerbObjectPut, - sessionSDK.VerbObjectDelete, - sessionSDK.VerbObjectHead, - sessionSDK.VerbObjectRange, - sessionSDK.VerbObjectRangeHash, - sessionSDK.VerbObjectGet, - sessionSDK.VerbObjectSearch, - } - - var tok sessionSDK.Object - - for op, list := range table { - for _, verb := range verbs { - contains := slices.Contains(list, verb) - - tok.ForVerb(verb) - - require.Equal(t, contains, assertVerb(tok, op), - "%v in token, %s executing", verb, op) - } - } -} - -func TestAssertSessionRelation(t *testing.T) { - var tok sessionSDK.Object - cnr := cidtest.ID() - cnrOther := cidtest.ID() - obj := oidtest.ID() - objOther := oidtest.ID() - - // make sure ids differ, otherwise test won't work correctly - require.False(t, cnrOther.Equals(cnr)) - require.False(t, objOther.Equals(obj)) - - // bind session to the container (required) - tok.BindContainer(cnr) - - // test container-global session - require.NoError(t, assertSessionRelation(tok, cnr, nil)) - require.NoError(t, assertSessionRelation(tok, cnr, &obj)) - require.Error(t, assertSessionRelation(tok, cnrOther, nil)) - require.Error(t, assertSessionRelation(tok, cnrOther, &obj)) - - // limit the session to the particular object - tok.LimitByObjects(obj) - - // test fixed object session (here obj arg must be non-nil everywhere) - require.NoError(t, assertSessionRelation(tok, cnr, &obj)) - require.Error(t, assertSessionRelation(tok, cnr, &objOther)) -} diff --git a/pkg/services/object/request_context.go b/pkg/services/object/request_context.go deleted file mode 100644 index eb4041f808..0000000000 --- a/pkg/services/object/request_context.go +++ /dev/null @@ -1,24 +0,0 @@ -package object - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" - "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" -) - -type RequestContextKeyT struct{} - -var RequestContextKey = RequestContextKeyT{} - -// RequestContext is a context passed between middleware handlers. -type RequestContext struct { - Namespace string - - SenderKey []byte - - ContainerOwner user.ID - - Role acl.Role - - BearerToken *bearer.Token -} From 3bb1fb744a6b09e796b6e33c80910e90ab69f67f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 15:56:11 +0300 Subject: [PATCH 1284/1413] [#1689] morph/client: Reuse auto-generated wrappers for NNS Make code simpler, remove unused methods. Change-Id: I18807f2c14b5a96e533e5e3fc153e23c742c66c1 Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/client.go | 4 ++ pkg/morph/client/nns.go | 96 ++++++-------------------------------- 2 files changed, 19 insertions(+), 81 deletions(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index a7c3c6d8d6..1c12130b74 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -9,6 +9,7 @@ import ( "sync/atomic" "time" + nnsClient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" morphmetrics "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/metrics" @@ -62,6 +63,8 @@ type Client struct { rolemgmt *rolemgmt.Contract // neo-go Designation contract wrapper nnsHash util.Uint160 // NNS contract hash + nnsReader *nnsClient.ContractReader // NNS contract wrapper + acc *wallet.Account // neo account accAddr util.Uint160 // account's address @@ -576,6 +579,7 @@ func (c *Client) setActor(act *actor.Actor) { c.rpcActor = act c.gasToken = nep17.New(act, gas.Hash) c.rolemgmt = rolemgmt.New(act) + c.nnsReader = nnsClient.NewReader(act, c.nnsHash) } func (c *Client) GetActor() *actor.Actor { diff --git a/pkg/morph/client/nns.go b/pkg/morph/client/nns.go index b03967fdd9..bc00eb8890 100644 --- a/pkg/morph/client/nns.go +++ b/pkg/morph/client/nns.go @@ -8,14 +8,12 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + nnsClient "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" - "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" ) const ( @@ -37,12 +35,8 @@ const ( NNSPolicyContractName = "policy.frostfs" ) -var ( - // ErrNNSRecordNotFound means that there is no such record in NNS contract. - ErrNNSRecordNotFound = errors.New("record has not been found in NNS contract") - - errEmptyResultStack = errors.New("returned result stack is empty") -) +// ErrNNSRecordNotFound means that there is no such record in NNS contract. +var ErrNNSRecordNotFound = errors.New("record has not been found in NNS contract") // NNSAlphabetContractName returns contract name of the alphabet contract in NNS // based on alphabet index. @@ -61,67 +55,36 @@ func (c *Client) NNSContractAddress(name string) (sh util.Uint160, err error) { return util.Uint160{}, ErrConnectionLost } - nnsHash := c.NNSHash() - sh, err = nnsResolve(c.client, nnsHash, name) + sh, err = nnsResolve(c.nnsReader, name) if err != nil { return sh, fmt.Errorf("NNS.resolve: %w", err) } return sh, nil } -// NNSHash returns NNS contract hash. -func (c *Client) NNSHash() util.Uint160 { - return c.nnsHash -} - -func nnsResolveItem(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (stackitem.Item, error) { - found, err := exists(c, nnsHash, domain) +func nnsResolveItem(r *nnsClient.ContractReader, domain string) ([]stackitem.Item, error) { + available, err := r.IsAvailable(domain) if err != nil { return nil, fmt.Errorf("check presence in NNS contract for %s: %w", domain, err) } - if !found { + if available { return nil, ErrNNSRecordNotFound } - result, err := c.InvokeFunction(nnsHash, "resolve", []smartcontract.Parameter{ - { - Type: smartcontract.StringType, - Value: domain, - }, - { - Type: smartcontract.IntegerType, - Value: big.NewInt(int64(nns.TXT)), - }, - }, nil) - if err != nil { - return nil, err - } - if result.State != vmstate.Halt.String() { - return nil, fmt.Errorf("invocation failed: %s", result.FaultException) - } - if len(result.Stack) == 0 { - return nil, errEmptyResultStack - } - return result.Stack[0], nil + return r.Resolve(domain, big.NewInt(int64(nns.TXT))) } -func nnsResolve(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (util.Uint160, error) { - res, err := nnsResolveItem(c, nnsHash, domain) +func nnsResolve(r *nnsClient.ContractReader, domain string) (util.Uint160, error) { + arr, err := nnsResolveItem(r, domain) if err != nil { return util.Uint160{}, err } - // Parse the result of resolving NNS record. - // It works with multiple formats (corresponding to multiple NNS versions). - // If array of hashes is provided, it returns only the first one. - if arr, ok := res.Value().([]stackitem.Item); ok { - if len(arr) == 0 { - return util.Uint160{}, errors.New("NNS record is missing") - } - res = arr[0] + if len(arr) == 0 { + return util.Uint160{}, errors.New("NNS record is missing") } - bs, err := res.TryBytes() + bs, err := arr[0].TryBytes() if err != nil { return util.Uint160{}, fmt.Errorf("malformed response: %w", err) } @@ -141,33 +104,6 @@ func nnsResolve(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (uti return util.Uint160{}, errors.New("no valid hashes are found") } -func exists(c *rpcclient.WSClient, nnsHash util.Uint160, domain string) (bool, error) { - result, err := c.InvokeFunction(nnsHash, "isAvailable", []smartcontract.Parameter{ - { - Type: smartcontract.StringType, - Value: domain, - }, - }, nil) - if err != nil { - return false, err - } - - if len(result.Stack) == 0 { - return false, errEmptyResultStack - } - - res := result.Stack[0] - - available, err := res.TryBool() - if err != nil { - return false, fmt.Errorf("malformed response: %w", err) - } - - // not available means that it is taken - // and, therefore, exists - return !available, nil -} - // SetGroupSignerScope makes the default signer scope include all FrostFS contracts. // Should be called for side-chain client only. func (c *Client) SetGroupSignerScope() error { @@ -211,14 +147,12 @@ func (c *Client) contractGroupKey() (*keys.PublicKey, error) { return gKey, nil } - nnsHash := c.NNSHash() - item, err := nnsResolveItem(c.client, nnsHash, NNSGroupKeyName) + arr, err := nnsResolveItem(c.nnsReader, NNSGroupKeyName) if err != nil { return nil, err } - arr, ok := item.Value().([]stackitem.Item) - if !ok || len(arr) == 0 { + if len(arr) == 0 { return nil, errors.New("NNS record is missing") } From 0a9d139e20fed1d6386f5913f2da9dc749d85d4e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 16:03:10 +0300 Subject: [PATCH 1285/1413] [#1689] morph/client: Remove notary hash field from `notaryInfo` Notary contract hash is constant. Change-Id: I7935580acbced5c9d567875ea75daa57cc259a3c Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/notary.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index dbd58a53ac..4e20a3639b 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -38,8 +38,7 @@ type ( alphabetSource AlphabetKeys // source of alphabet node keys to prepare witness - notary util.Uint160 - proxy util.Uint160 + proxy util.Uint160 } notaryCfg struct { @@ -102,7 +101,6 @@ func (c *Client) EnableNotarySupport(opts ...NotaryOption) error { txValidTime: cfg.txValidTime, roundTime: cfg.roundTime, alphabetSource: cfg.alphabetSource, - notary: notary.Hash, } c.notary = notaryCfg @@ -188,7 +186,7 @@ func (c *Client) DepositEndlessNotary(ctx context.Context, amount fixedn.Fixed8) func (c *Client) depositNotary(ctx context.Context, amount fixedn.Fixed8, till int64) (util.Uint256, uint32, error) { txHash, vub, err := c.gasToken.Transfer( c.accAddr, - c.notary.notary, + notary.Hash, big.NewInt(int64(amount)), []any{c.acc.PrivateKey().GetScriptHash(), till}) if err != nil { From 0c664fa804bbecab361fdec2287fa42b051c82d4 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 24 Mar 2025 11:52:39 +0300 Subject: [PATCH 1286/1413] [#1689] qos: Fix metric description Change-Id: I460fdd3713e765d57ef3ff2945b9b3776f46c164 Signed-off-by: Dmitrii Stepanov --- internal/metrics/qos.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/metrics/qos.go b/internal/metrics/qos.go index 17fb67a27a..be68781422 100644 --- a/internal/metrics/qos.go +++ b/internal/metrics/qos.go @@ -15,7 +15,7 @@ func newQoSMetrics() *QoSMetrics { Namespace: namespace, Subsystem: qosSubsystem, Name: "operations_total", - Help: "Count of pending, in progree, completed and failed due of resource exhausted error operations for each shard", + Help: "Count of pending, in progress, completed and failed due of resource exhausted error operations for each shard", }, []string{shardIDLabel, operationLabel, ioTagLabel, typeLabel}), } } From 163e2e9f83a79def2d7bfda6b2b6609cfa02c1b2 Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Mon, 24 Mar 2025 17:04:24 +0300 Subject: [PATCH 1287/1413] ci: Cache pre-commit installations on Jenkins Agent This change introduces a custom helper from our shared library [0] that defines ad-hoc container environment to execute CI steps in. Pre-commit installation will now be cached on Jenkins Agent: builds will tolerate network hiccups better and we will also save some run time (although on non-critical path of a parallel process). [0]: https://git.frostfs.info/TrueCloudLab/jenkins/pulls/8 Change-Id: I93b01f169c457aa35f4d8bc5b90f31b31e2bd8b2 Signed-off-by: Vitaliy Potyarkin --- .ci/Jenkinsfile | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index e21ce61c54..166fb92861 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -68,12 +68,14 @@ async { } task('pre-commit') { - sh ''' - apt update - apt install -y --no-install-recommends pre-commit - ''' // TODO: Make an OCI image for pre-commit + golang? Unpack golang tarball with a library function? - withEnv(['SKIP=make-lint,go-staticcheck-repo-mod,go-unit-tests,gofumpt']) { - sh 'pre-commit run --color=always --hook-stage=manual --all-files' + dockerfile(""" + FROM ${golangDefault} + RUN apt update && \ + apt install -y --no-install-recommends pre-commit + """) { + withEnv(['SKIP=make-lint,go-staticcheck-repo-mod,go-unit-tests,gofumpt']) { + sh 'pre-commit run --color=always --hook-stage=manual --all-files' + } } } } From 5470b205fd461d95c968c55ed122334c7e7f32cd Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 25 Mar 2025 10:15:51 +0300 Subject: [PATCH 1288/1413] [#1619] gc: Fix metric `frostfs_node.garbage_collector.marking_duration_seconds` Change-Id: I957f930d1babf179d0fb6de624a90f4fe9977862 Signed-off-by: Anton Nikiforov --- pkg/local_object_storage/shard/gc.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 32a377cd5a..84fb6039ee 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -527,7 +527,8 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { return } - release, err := s.opsLimiter.ReadRequest(ctx) + var release qos.ReleaseFunc + release, err = s.opsLimiter.ReadRequest(ctx) if err != nil { log.Error(ctx, logs.ShardIteratorOverGraveyardFailed, zap.Error(err)) s.m.RUnlock() From 9358938222bc44bd4f4638a78b74cd331cdba808 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 10 Mar 2025 11:42:55 +0300 Subject: [PATCH 1289/1413] [#1633] go.mod: Bump frostfs-sdk-go Change-Id: I50c1a0d5b88e307402a5b1b2883bb9b9a357a2c7 Signed-off-by: Anton Nikiforov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 753bfbd29d..887f8bb2b2 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b diff --git a/go.sum b/go.sum index 7f94179548..982fddf236 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275 h1:WqWxCnCl2ekfjWja/CpGeF2rf4h0x199xhdnsm/j+E8= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9 h1:svCl6NDAPZ/KuQPjdVKo74RkCIANesxUPM45zQZDhSw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250306092416-69b0711d12d9/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592 h1:n7Pl8V7O1yS07J/fqdbzZjVe/mQW42a7eS0QHfgrzJw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= From 3bbee1b554a1407e1b8c30ef0244cd4599c4299f Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 24 Mar 2025 12:32:41 +0300 Subject: [PATCH 1290/1413] [#1619] logger: Allow to set options for `zap.Logger` via `logger.Prm` Change-Id: I8eed951c25d1ecf18b0aea62c6825be65a450085 Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/config.go | 16 ++++++++++------ pkg/util/logger/logger.go | 20 +++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index c3c6877635..4313162580 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -108,6 +108,7 @@ type applicationConfiguration struct { level string destination string timestamp bool + options []zap.Option } ObjectCfg struct { @@ -232,6 +233,14 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { a.LoggerCfg.level = loggerconfig.Level(c) a.LoggerCfg.destination = loggerconfig.Destination(c) a.LoggerCfg.timestamp = loggerconfig.Timestamp(c) + var opts []zap.Option + if loggerconfig.ToLokiConfig(c).Enabled { + opts = []zap.Option{zap.WrapCore(func(core zapcore.Core) zapcore.Core { + lokiCore := lokicore.New(core, loggerconfig.ToLokiConfig(c)) + return lokiCore + })} + } + a.LoggerCfg.options = opts // Object @@ -718,12 +727,6 @@ func initCfg(appCfg *config.Config) *cfg { logPrm.SamplingHook = c.metricsCollector.LogMetrics().GetSamplingHook() log, err := logger.NewLogger(logPrm) fatalOnErr(err) - if loggerconfig.ToLokiConfig(appCfg).Enabled { - log.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core { - lokiCore := lokicore.New(core, loggerconfig.ToLokiConfig(appCfg)) - return lokiCore - })) - } c.internals = initInternals(appCfg, log) @@ -1090,6 +1093,7 @@ func (c *cfg) loggerPrm() (logger.Prm, error) { return logger.Prm{}, errors.New("incorrect log destination format: " + c.LoggerCfg.destination) } prm.PrependTimestamp = c.LoggerCfg.timestamp + prm.Options = c.LoggerCfg.options return prm, nil } diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index 952a6f2dc3..10c7e8dc90 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -36,6 +36,9 @@ type Prm struct { // PrependTimestamp specifies whether to prepend a timestamp in the log PrependTimestamp bool + + // Options for zap.Logger + Options []zap.Option } const ( @@ -103,10 +106,12 @@ func newConsoleLogger(prm Prm) (*Logger, error) { c.EncoderConfig.TimeKey = "" } - lZap, err := c.Build( + opts := []zap.Option{ zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), zap.AddCallerSkip(1), - ) + } + opts = append(opts, prm.Options...) + lZap, err := c.Build(opts...) if err != nil { return nil, err } @@ -150,7 +155,12 @@ func newJournaldLogger(prm Prm) (*Logger, error) { c.Sampling.Thereafter, samplerOpts..., ) - lZap := zap.New(samplingCore, zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), zap.AddCallerSkip(1)) + opts := []zap.Option{ + zap.AddStacktrace(zap.NewAtomicLevelAt(zap.FatalLevel)), + zap.AddCallerSkip(1), + } + opts = append(opts, prm.Options...) + lZap := zap.New(samplingCore, opts...) l := &Logger{z: lZap, lvl: lvl} @@ -161,10 +171,6 @@ func (l *Logger) Reload(prm Prm) { l.lvl.SetLevel(prm.level) } -func (l *Logger) WithOptions(options ...zap.Option) { - l.z = l.z.WithOptions(options...) -} - func (l *Logger) With(fields ...zap.Field) *Logger { return &Logger{z: l.z.With(fields...)} } From 632bd8e38dd34e2438dd39c53111605dd94ef8b1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 25 Mar 2025 12:15:46 +0300 Subject: [PATCH 1291/1413] [#1696] qos: Fix internal tag adjust If request has no tag, but request's public key is netmap node's key or one of allowed internal tag keys from config, then request must use internal IO tag. Change-Id: Iff93b626941a81b088d8999b3f2947f9501dcdf8 Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/qos.go | 39 ++++-- cmd/frostfs-node/qos_test.go | 226 ++++++++++++++++++++++++++++++ internal/logs/logs.go | 2 +- pkg/core/object/fmt_test.go | 42 ++---- pkg/util/testing/netmap_source.go | 36 +++++ 5 files changed, 298 insertions(+), 47 deletions(-) create mode 100644 cmd/frostfs-node/qos_test.go create mode 100644 pkg/util/testing/netmap_source.go diff --git a/cmd/frostfs-node/qos.go b/cmd/frostfs-node/qos.go index 9663fc6aec..6394b668b6 100644 --- a/cmd/frostfs-node/qos.go +++ b/cmd/frostfs-node/qos.go @@ -43,6 +43,9 @@ func initQoSService(c *cfg) { func (s *cfgQoSService) AdjustIncomingTag(ctx context.Context, requestSignPublicKey []byte) context.Context { rawTag, defined := qosTagging.IOTagFromContext(ctx) if !defined { + if s.isInternalIOTagPublicKey(ctx, requestSignPublicKey) { + return qosTagging.ContextWithIOTag(ctx, qos.IOTagInternal.String()) + } return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) } ioTag, err := qos.FromRawString(rawTag) @@ -73,20 +76,8 @@ func (s *cfgQoSService) AdjustIncomingTag(ctx context.Context, requestSignPublic s.logger.Debug(ctx, logs.FailedToValidateIncomingIOTag) return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) case qos.IOTagInternal: - for _, pk := range s.allowedInternalPubs { - if bytes.Equal(pk, requestSignPublicKey) { - return ctx - } - } - nm, err := s.netmapSource.GetNetMap(ctx, 0) - if err != nil { - s.logger.Debug(ctx, logs.FailedToGetNetmapToAdjustIOTag, zap.Error(err)) - return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) - } - for _, node := range nm.Nodes() { - if bytes.Equal(node.PublicKey(), requestSignPublicKey) { - return ctx - } + if s.isInternalIOTagPublicKey(ctx, requestSignPublicKey) { + return ctx } s.logger.Debug(ctx, logs.FailedToValidateIncomingIOTag) return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) @@ -95,3 +86,23 @@ func (s *cfgQoSService) AdjustIncomingTag(ctx context.Context, requestSignPublic return qosTagging.ContextWithIOTag(ctx, qos.IOTagClient.String()) } } + +func (s *cfgQoSService) isInternalIOTagPublicKey(ctx context.Context, publicKey []byte) bool { + for _, pk := range s.allowedInternalPubs { + if bytes.Equal(pk, publicKey) { + return true + } + } + nm, err := s.netmapSource.GetNetMap(ctx, 0) + if err != nil { + s.logger.Debug(ctx, logs.FailedToGetNetmapToAdjustIOTag, zap.Error(err)) + return false + } + for _, node := range nm.Nodes() { + if bytes.Equal(node.PublicKey(), publicKey) { + return true + } + } + + return false +} diff --git a/cmd/frostfs-node/qos_test.go b/cmd/frostfs-node/qos_test.go new file mode 100644 index 0000000000..971f9eebf3 --- /dev/null +++ b/cmd/frostfs-node/qos_test.go @@ -0,0 +1,226 @@ +package main + +import ( + "context" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" + utilTesting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/testing" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/stretchr/testify/require" +) + +func TestQoSService_Client(t *testing.T) { + t.Parallel() + s, pk := testQoSServicePrepare(t) + t.Run("IO tag client defined", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagClient.String()) + ctx = s.AdjustIncomingTag(ctx, pk.Request) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("no IO tag defined, signed with unknown key", func(t *testing.T) { + ctx := s.AdjustIncomingTag(context.Background(), pk.Request) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("no IO tag defined, signed with allowed critical key", func(t *testing.T) { + ctx := s.AdjustIncomingTag(context.Background(), pk.Critical) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("unknown IO tag, signed with unknown key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), "some IO tag we don't know") + ctx = s.AdjustIncomingTag(ctx, pk.Request) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("unknown IO tag, signed with netmap key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), "some IO tag we don't know") + ctx = s.AdjustIncomingTag(ctx, pk.NetmapNode) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("unknown IO tag, signed with allowed internal key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), "some IO tag we don't know") + ctx = s.AdjustIncomingTag(ctx, pk.Internal) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("unknown IO tag, signed with allowed critical key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), "some IO tag we don't know") + ctx = s.AdjustIncomingTag(ctx, pk.Critical) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("IO tag internal defined, signed with unknown key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagInternal.String()) + ctx = s.AdjustIncomingTag(ctx, pk.Request) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("IO tag internal defined, signed with allowed critical key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagInternal.String()) + ctx = s.AdjustIncomingTag(ctx, pk.Critical) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("IO tag critical defined, signed with unknown key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagCritical.String()) + ctx = s.AdjustIncomingTag(ctx, pk.Request) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("IO tag critical defined, signed with allowed internal key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagCritical.String()) + ctx = s.AdjustIncomingTag(ctx, pk.Internal) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) +} + +func TestQoSService_Internal(t *testing.T) { + t.Parallel() + s, pk := testQoSServicePrepare(t) + t.Run("IO tag internal defined, signed with netmap key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagInternal.String()) + ctx = s.AdjustIncomingTag(ctx, pk.NetmapNode) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagInternal.String(), tag) + }) + t.Run("IO tag internal defined, signed with allowed internal key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagInternal.String()) + ctx = s.AdjustIncomingTag(ctx, pk.Internal) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagInternal.String(), tag) + }) + t.Run("no IO tag defined, signed with netmap key", func(t *testing.T) { + ctx := s.AdjustIncomingTag(context.Background(), pk.NetmapNode) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagInternal.String(), tag) + }) + t.Run("no IO tag defined, signed with allowed internal key", func(t *testing.T) { + ctx := s.AdjustIncomingTag(context.Background(), pk.Internal) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagInternal.String(), tag) + }) +} + +func TestQoSService_Critical(t *testing.T) { + t.Parallel() + s, pk := testQoSServicePrepare(t) + t.Run("IO tag critical defined, signed with netmap key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagCritical.String()) + ctx = s.AdjustIncomingTag(ctx, pk.NetmapNode) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagCritical.String(), tag) + }) + t.Run("IO tag critical defined, signed with allowed critical key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagCritical.String()) + ctx = s.AdjustIncomingTag(ctx, pk.Critical) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagCritical.String(), tag) + }) +} + +func TestQoSService_NetmapGetError(t *testing.T) { + t.Parallel() + s, pk := testQoSServicePrepare(t) + s.netmapSource = &utilTesting.TestNetmapSource{} + t.Run("IO tag internal defined, signed with netmap key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagInternal.String()) + ctx = s.AdjustIncomingTag(ctx, pk.NetmapNode) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("IO tag critical defined, signed with netmap key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagCritical.String()) + ctx = s.AdjustIncomingTag(ctx, pk.NetmapNode) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("no IO tag defined, signed with netmap key", func(t *testing.T) { + ctx := s.AdjustIncomingTag(context.Background(), pk.NetmapNode) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) + t.Run("unknown IO tag, signed with netmap key", func(t *testing.T) { + ctx := tagging.ContextWithIOTag(context.Background(), "some IO tag we don't know") + ctx = s.AdjustIncomingTag(ctx, pk.NetmapNode) + tag, ok := tagging.IOTagFromContext(ctx) + require.True(t, ok) + require.Equal(t, qos.IOTagClient.String(), tag) + }) +} + +func testQoSServicePrepare(t *testing.T) (*cfgQoSService, *testQoSServicePublicKeys) { + nmSigner, err := keys.NewPrivateKey() + require.NoError(t, err) + + reqSigner, err := keys.NewPrivateKey() + require.NoError(t, err) + + allowedCritSigner, err := keys.NewPrivateKey() + require.NoError(t, err) + + allowedIntSigner, err := keys.NewPrivateKey() + require.NoError(t, err) + + var node netmap.NodeInfo + node.SetPublicKey(nmSigner.PublicKey().Bytes()) + nm := &netmap.NetMap{} + nm.SetEpoch(100) + nm.SetNodes([]netmap.NodeInfo{node}) + + return &cfgQoSService{ + logger: test.NewLogger(t), + netmapSource: &utilTesting.TestNetmapSource{ + Netmaps: map[uint64]*netmap.NetMap{ + 100: nm, + }, + CurrentEpoch: 100, + }, + allowedCriticalPubs: [][]byte{ + allowedCritSigner.PublicKey().Bytes(), + }, + allowedInternalPubs: [][]byte{ + allowedIntSigner.PublicKey().Bytes(), + }, + }, + &testQoSServicePublicKeys{ + NetmapNode: nmSigner.PublicKey().Bytes(), + Request: reqSigner.PublicKey().Bytes(), + Internal: allowedIntSigner.PublicKey().Bytes(), + Critical: allowedCritSigner.PublicKey().Bytes(), + } +} + +type testQoSServicePublicKeys struct { + NetmapNode []byte + Request []byte + Internal []byte + Critical []byte +} diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 3503c922e1..5b42b25bab 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -512,7 +512,7 @@ const ( FailedToUpdateMultinetConfiguration = "failed to update multinet configuration" FailedToParseIncomingIOTag = "failed to parse incoming IO tag" NotSupportedIncomingIOTagReplacedWithClient = "incoming IO tag is not supported, replaced with `client`" - FailedToGetNetmapToAdjustIOTag = "failed to get netmap to adjust IO tag, replaced with `client`" + FailedToGetNetmapToAdjustIOTag = "failed to get netmap to adjust IO tag" FailedToValidateIncomingIOTag = "failed to validate incoming IO tag, replaced with `client`" WriteCacheFailedToAcquireRPSQuota = "writecache failed to acquire RPS quota to flush object" ) diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index 239a9f389d..dc336eb345 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + utilTesting "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/testing" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" containerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -410,11 +411,11 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { }, ), WithNetmapSource( - &testNetmapSource{ - netmaps: map[uint64]*netmap.NetMap{ + &utilTesting.TestNetmapSource{ + Netmaps: map[uint64]*netmap.NetMap{ curEpoch: currentEpochNM, }, - currentEpoch: curEpoch, + CurrentEpoch: curEpoch, }, ), WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), @@ -483,12 +484,12 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { }, ), WithNetmapSource( - &testNetmapSource{ - netmaps: map[uint64]*netmap.NetMap{ + &utilTesting.TestNetmapSource{ + Netmaps: map[uint64]*netmap.NetMap{ curEpoch: currentEpochNM, curEpoch - 1: previousEpochNM, }, - currentEpoch: curEpoch, + CurrentEpoch: curEpoch, }, ), WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), @@ -559,12 +560,12 @@ func TestFormatValidator_ValidateTokenIssuer(t *testing.T) { }, ), WithNetmapSource( - &testNetmapSource{ - netmaps: map[uint64]*netmap.NetMap{ + &utilTesting.TestNetmapSource{ + Netmaps: map[uint64]*netmap.NetMap{ curEpoch: currentEpochNM, curEpoch - 1: previousEpochNM, }, - currentEpoch: curEpoch, + CurrentEpoch: curEpoch, }, ), WithLogger(logger.NewLoggerWrapper(zaptest.NewLogger(t))), @@ -596,26 +597,3 @@ func (s *testContainerSource) Get(ctx context.Context, cnrID cid.ID) (*container func (s *testContainerSource) DeletionInfo(context.Context, cid.ID) (*container.DelInfo, error) { return nil, nil } - -type testNetmapSource struct { - netmaps map[uint64]*netmap.NetMap - currentEpoch uint64 -} - -func (s *testNetmapSource) GetNetMap(ctx context.Context, diff uint64) (*netmap.NetMap, error) { - if diff >= s.currentEpoch { - return nil, fmt.Errorf("invalid diff") - } - return s.GetNetMapByEpoch(ctx, s.currentEpoch-diff) -} - -func (s *testNetmapSource) GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmap.NetMap, error) { - if nm, found := s.netmaps[epoch]; found { - return nm, nil - } - return nil, fmt.Errorf("netmap not found") -} - -func (s *testNetmapSource) Epoch(ctx context.Context) (uint64, error) { - return s.currentEpoch, nil -} diff --git a/pkg/util/testing/netmap_source.go b/pkg/util/testing/netmap_source.go new file mode 100644 index 0000000000..7373e538fb --- /dev/null +++ b/pkg/util/testing/netmap_source.go @@ -0,0 +1,36 @@ +package testing + +import ( + "context" + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" +) + +var ( + errInvalidDiff = errors.New("invalid diff") + errNetmapNotFound = errors.New("netmap not found") +) + +type TestNetmapSource struct { + Netmaps map[uint64]*netmap.NetMap + CurrentEpoch uint64 +} + +func (s *TestNetmapSource) GetNetMap(ctx context.Context, diff uint64) (*netmap.NetMap, error) { + if diff >= s.CurrentEpoch { + return nil, errInvalidDiff + } + return s.GetNetMapByEpoch(ctx, s.CurrentEpoch-diff) +} + +func (s *TestNetmapSource) GetNetMapByEpoch(_ context.Context, epoch uint64) (*netmap.NetMap, error) { + if nm, found := s.Netmaps[epoch]; found { + return nm, nil + } + return nil, errNetmapNotFound +} + +func (s *TestNetmapSource) Epoch(context.Context) (uint64, error) { + return s.CurrentEpoch, nil +} From 0a38571a10df69da4200db8ea6c952f587c10c4d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 08:20:40 +0300 Subject: [PATCH 1292/1413] [#1689] adm: Simplify getCandidateRegisterPrice() After all the refactoring, there is no more need to have custom branch for the local client. Change-Id: I274305b0c390578fb4583759135d3e7ce58873dc Signed-off-by: Evgenii Stratonikov --- .../morph/initialize/initialize_register.go | 31 ++----------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index 4c6607f9a7..841acdc831 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -1,7 +1,6 @@ package initialize import ( - "errors" "fmt" "math/big" @@ -11,7 +10,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" @@ -30,7 +28,9 @@ const ( ) func registerCandidateRange(c *helper.InitializeContext, start, end int) error { - regPrice, err := getCandidateRegisterPrice(c) + inv := invoker.New(c.Client, nil) + reader := neo.NewReader(inv) + regPrice, err := reader.GetRegisterPrice() if err != nil { return fmt.Errorf("can't fetch registration price: %w", err) } @@ -144,28 +144,3 @@ func transferNEOFinished(c *helper.InitializeContext, neoHash util.Uint160) (boo bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash()) return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err } - -var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response") - -func getCandidateRegisterPrice(c *helper.InitializeContext) (int64, error) { - switch c.Client.(type) { - case *rpcclient.Client: - inv := invoker.New(c.Client, nil) - reader := neo.NewReader(inv) - return reader.GetRegisterPrice() - default: - neoHash := neo.Hash - res, err := helper.InvokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil) - if err != nil { - return 0, err - } - if len(res.Stack) == 0 { - return 0, errGetPriceInvalid - } - bi, err := res.Stack[0].TryInteger() - if err != nil || !bi.IsInt64() { - return 0, errGetPriceInvalid - } - return bi.Int64(), nil - } -} From c2c05e222863945fdf1fb954135043cc98c5acef Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 08:21:50 +0300 Subject: [PATCH 1293/1413] [#1689] adm: Reuse ReadOnlyInvoker in registerCandidateRange() Change-Id: I544d10340825494b45a62700fa247404c18f746a Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/initialize/initialize_register.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index 841acdc831..3efa40c508 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -11,7 +11,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" @@ -28,8 +27,7 @@ const ( ) func registerCandidateRange(c *helper.InitializeContext, start, end int) error { - inv := invoker.New(c.Client, nil) - reader := neo.NewReader(inv) + reader := neo.NewReader(c.ReadOnlyInvoker) regPrice, err := reader.GetRegisterPrice() if err != nil { return fmt.Errorf("can't fetch registration price: %w", err) From bce2f7bef0c31f251daeaec377b6900ec9c01c9d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 08:24:33 +0300 Subject: [PATCH 1294/1413] [#1689] adm: Reuse `neo.NewReader` helper in transferNEOFinished() Change-Id: I27980ed87436958cb4d27278e30e05da021d1506 Signed-off-by: Evgenii Stratonikov --- .../modules/morph/initialize/initialize_register.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index 3efa40c508..46e6621d2e 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -12,7 +12,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/neo" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/nep17" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/util" @@ -114,7 +113,7 @@ func registerCandidates(c *helper.InitializeContext) error { func transferNEOToAlphabetContracts(c *helper.InitializeContext) error { neoHash := neo.Hash - ok, err := transferNEOFinished(c, neoHash) + ok, err := transferNEOFinished(c) if ok || err != nil { return err } @@ -137,8 +136,8 @@ func transferNEOToAlphabetContracts(c *helper.InitializeContext) error { return c.AwaitTx() } -func transferNEOFinished(c *helper.InitializeContext, neoHash util.Uint160) (bool, error) { - r := nep17.NewReader(c.ReadOnlyInvoker, neoHash) +func transferNEOFinished(c *helper.InitializeContext) (bool, error) { + r := neo.NewReader(c.ReadOnlyInvoker) bal, err := r.BalanceOf(c.CommitteeAcc.Contract.ScriptHash()) return bal.Cmp(big.NewInt(native.NEOTotalSupply)) == -1, err } From bd8ab2d84a59a1c251820a71e63d5e741fd9450e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 08:27:49 +0300 Subject: [PATCH 1295/1413] [#1689] adm: Remove useless switch in NNSIsAvailable() After all the refactorings, there is no need to have custom behaviour for local client. Change-Id: I99e297cdeffff979524b3f89d3580ab5780e7681 Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/initialize.go | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go index 961ceba536..48f7a62a43 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go @@ -13,7 +13,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" - "github.com/nspcc-dev/neo-go/pkg/rpcclient" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" nns2 "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" @@ -187,19 +186,9 @@ func NNSResolveKey(inv *invoker.Invoker, nnsHash util.Uint160, domain string) (* } func NNSIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) { - switch c.(type) { - case *rpcclient.Client: - inv := invoker.New(c, nil) - reader := nns2.NewReader(inv, nnsHash) - return reader.IsAvailable(name) - default: - b, err := unwrap.Bool(InvokeFunction(c, nnsHash, "isAvailable", []any{name}, nil)) - if err != nil { - return false, fmt.Errorf("`isAvailable`: invalid response: %w", err) - } - - return b, nil - } + inv := invoker.New(c, nil) + reader := nns2.NewReader(inv, nnsHash) + return reader.IsAvailable(name) } func CheckNotaryEnabled(c Client) error { From 60446bb66816e5d92bccf3a61022b708b6506297 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 08:31:10 +0300 Subject: [PATCH 1296/1413] [#1689] adm/helper: Use proper nns bindings import The one in `neo-go` is for another contract. Change-Id: Ia1ac2da5e419b48801afdb26df72892d77344e0d Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/helper/initialize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go index 48f7a62a43..50b5c1ec76 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize.go @@ -6,6 +6,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" + nns2 "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" @@ -14,7 +15,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" - nns2 "github.com/nspcc-dev/neo-go/pkg/rpcclient/nns" "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" From d00c606feed8ad776fe6df65b601b81790e7dfbe Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 21 Mar 2025 08:12:20 +0300 Subject: [PATCH 1297/1413] [#652] adm: Group independent stages in batches Each stage waits until transaction persists. This is needed to ensure the next stage will see the result of the previous one. However, some of the stages do not depend one on another, so we may execute them in parallel. `AwaitDisabled` flag is used to localize this batching on the code level. We could've removed `AwaitTx()` from respective stages, but it seems more error prone. Close #652. Change-Id: Ib9c6f6cd5e0db0f31aa1cda8e127b1fad5166336 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/helper/n3client.go | 4 +++- .../internal/modules/morph/initialize/initialize.go | 8 +++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index 3f3a66cb68..d6ca012ced 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -40,6 +40,8 @@ type ClientContext struct { CommitteeAct *actor.Actor // committee actor with the Global witness scope ReadOnlyInvoker *invoker.Invoker // R/O contract invoker, does not contain any signer SentTxs []HashVUBPair + + AwaitDisabled bool } func NewRemoteClient(v *viper.Viper) (Client, error) { @@ -120,7 +122,7 @@ func (c *ClientContext) SendTx(tx *transaction.Transaction, cmd *cobra.Command, } func (c *ClientContext) AwaitTx(cmd *cobra.Command) error { - if len(c.SentTxs) == 0 { + if len(c.SentTxs) == 0 || c.AwaitDisabled { return nil } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go index cdaf7d3bca..4d39dc6622 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go @@ -39,6 +39,7 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { return err } + initCtx.AwaitDisabled = true cmd.Println("Stage 4.1: Transfer GAS to proxy contract.") if err := transferGASToProxy(initCtx); err != nil { return err @@ -55,5 +56,10 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { } cmd.Println("Stage 7: set addresses in NNS.") - return setNNS(initCtx) + if err := setNNS(initCtx); err != nil { + return err + } + + initCtx.AwaitDisabled = false + return initCtx.AwaitTx() } From a2053870e23b9d58529cd3cebb7898bff2abae15 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Mar 2025 16:36:29 +0300 Subject: [PATCH 1298/1413] [#1692] metabase: Use bucket cache in ListWithCursor() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No changes in speed, but unified approach: ``` goos: linux goarch: amd64 pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz │ master │ new │ │ sec/op │ sec/op vs base │ ListWithCursor/1_item-8 6.067µ ± 8% 5.731µ ± 10% ~ (p=0.052 n=10) ListWithCursor/10_items-8 25.40µ ± 11% 26.12µ ± 13% ~ (p=0.971 n=10) ListWithCursor/100_items-8 210.7µ ± 9% 203.2µ ± 6% ~ (p=0.280 n=10) geomean 31.90µ 31.22µ -2.16% │ master │ new │ │ B/op │ B/op vs base │ ListWithCursor/1_item-8 3.287Ki ± 0% 3.287Ki ± 0% ~ (p=1.000 n=10) ¹ ListWithCursor/10_items-8 15.63Ki ± 0% 15.62Ki ± 0% ~ (p=0.328 n=10) ListWithCursor/100_items-8 138.1Ki ± 0% 138.1Ki ± 0% ~ (p=0.340 n=10) geomean 19.21Ki 19.21Ki -0.00% ¹ all samples are equal │ master │ new │ │ allocs/op │ allocs/op vs base │ ListWithCursor/1_item-8 109.0 ± 0% 109.0 ± 0% ~ (p=1.000 n=10) ¹ ListWithCursor/10_items-8 380.0 ± 0% 380.0 ± 0% ~ (p=1.000 n=10) ¹ ListWithCursor/100_items-8 3.082k ± 0% 3.082k ± 0% ~ (p=1.000 n=10) ¹ geomean 503.5 503.5 +0.00% ¹ all samples are equal ``` Change-Id: Ic11673427615053656b2a60068a6d4dbd27af2cb Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/list.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index 0b6cdf702e..a1b3f4e2dd 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -139,8 +139,7 @@ func (db *DB) listWithCursor(tx *bbolt.Tx, result []objectcore.Info, count int, var containerID cid.ID var offset []byte - graveyardBkt := tx.Bucket(graveyardBucketName) - garbageBkt := tx.Bucket(garbageBucketName) + bc := newBucketCache() rawAddr := make([]byte, cidSize, addressKeySize) @@ -169,7 +168,7 @@ loop: bkt := tx.Bucket(name) if bkt != nil { copy(rawAddr, cidRaw) - result, offset, cursor, err = selectNFromBucket(bkt, objType, graveyardBkt, garbageBkt, rawAddr, containerID, + result, offset, cursor, err = selectNFromBucket(bc, bkt, objType, rawAddr, containerID, result, count, cursor, threshold, currEpoch) if err != nil { return nil, nil, err @@ -204,9 +203,10 @@ loop: // selectNFromBucket similar to selectAllFromBucket but uses cursor to find // object to start selecting from. Ignores inhumed objects. -func selectNFromBucket(bkt *bbolt.Bucket, // main bucket +func selectNFromBucket( + bc *bucketCache, + bkt *bbolt.Bucket, // main bucket objType objectSDK.Type, // type of the objects stored in the main bucket - graveyardBkt, garbageBkt *bbolt.Bucket, // cached graveyard buckets cidRaw []byte, // container ID prefix, optimization cnt cid.ID, // container ID to []objectcore.Info, // listing result @@ -241,6 +241,8 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket } offset = k + graveyardBkt := getGraveyardBucket(bc, bkt.Tx()) + garbageBkt := getGarbageBucket(bc, bkt.Tx()) if inGraveyardWithKey(append(cidRaw, k...), graveyardBkt, garbageBkt) > 0 { continue } @@ -251,7 +253,7 @@ func selectNFromBucket(bkt *bbolt.Bucket, // main bucket } expEpoch, hasExpEpoch := hasExpirationEpoch(&o) - if hasExpEpoch && expEpoch < currEpoch && !objectLocked(bkt.Tx(), cnt, obj) { + if hasExpEpoch && expEpoch < currEpoch && !objectLockedWithCache(bc, bkt.Tx(), cnt, obj) { continue } From d144abc9771fdc8780435e09e6abba50fca81620 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 20 Mar 2025 17:55:31 +0300 Subject: [PATCH 1299/1413] [#1692] metabase: Remove useless `count` variable It is always equal to `len(to)`. Change-Id: Id7a4c26e9711216b78f96e6b2511efa0773e3471 Signed-off-by: Evgenii Stratonikov --- pkg/local_object_storage/metabase/list.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/local_object_storage/metabase/list.go b/pkg/local_object_storage/metabase/list.go index a1b3f4e2dd..2a0bd7f6a1 100644 --- a/pkg/local_object_storage/metabase/list.go +++ b/pkg/local_object_storage/metabase/list.go @@ -219,7 +219,6 @@ func selectNFromBucket( cursor = new(Cursor) } - count := len(to) c := bkt.Cursor() k, v := c.First() @@ -231,7 +230,7 @@ func selectNFromBucket( } for ; k != nil; k, v = c.Next() { - if count >= limit { + if len(to) >= limit { break } @@ -275,7 +274,6 @@ func selectNFromBucket( a.SetContainer(cnt) a.SetObject(obj) to = append(to, objectcore.Info{Address: a, Type: objType, IsLinkingObject: isLinkingObj, ECInfo: ecInfo}) - count++ } return to, offset, cursor, nil From d432bebef45be28487db419c7a005f455a08a0ac Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 28 Mar 2025 13:16:35 +0300 Subject: [PATCH 1300/1413] [#1689] go.mod: Bump frostfs-qos version Change-Id: Iaa28da1a1e7b2f4ab7fd8ed661939eb38f4c7782 Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 887f8bb2b2..2dbd1e231f 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 - git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275 + git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 diff --git a/go.sum b/go.sum index 982fddf236..6969fdc534 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 h1:fluzML8BIIabd07LyPSjc0JAV2qymWkPiFaLrXdALLA= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275 h1:WqWxCnCl2ekfjWja/CpGeF2rf4h0x199xhdnsm/j+E8= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250320142439-32079ad7c275/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167 h1:NhqfqNcATndYwx413BaaYXxVJbkeu2vQOtVyxXw5xCQ= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592 h1:n7Pl8V7O1yS07J/fqdbzZjVe/mQW42a7eS0QHfgrzJw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= From 2254c8aff5716a0de0c4367c268223ab2b0390a0 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 31 Mar 2025 10:53:25 +0300 Subject: [PATCH 1301/1413] [#1689] go.mod: Bump SDK version Change-Id: Ic946aa68c3d6da9e7d54363f8e9141c6547707d6 Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2dbd1e231f..9ae49a90cb 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b diff --git a/go.sum b/go.sum index 6969fdc534..63925fef2f 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167 h1:NhqfqNcATndYwx413BaaYXxVJbkeu2vQOtVyxXw5xCQ= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592 h1:n7Pl8V7O1yS07J/fqdbzZjVe/mQW42a7eS0QHfgrzJw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250307150202-749b4e9ab592/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945 h1:zM2l316J55h9p30snl6vHBI/h0xmnuqZjnxIjRDtJZw= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= From 30d4692c3eab07bba7cc472c06f8cb48b0d52263 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 28 Mar 2025 19:32:26 +0300 Subject: [PATCH 1302/1413] [#1640] go.mod: Bump version for `frostfs-locode-db` Change-Id: Ic45ae77d6209c0097575fc8f89b076b22d50d149 Signed-off-by: Anton Nikiforov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9ae49a90cb..76662ff5ea 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( code.gitea.io/sdk/gitea v0.17.1 git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1 git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 - git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d + git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.5.2 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945 diff --git a/go.sum b/go.sum index 63925fef2f..42078073b0 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1 h1:k1Qw8dWUQczfo0eVXlhrq9 git.frostfs.info/TrueCloudLab/frostfs-contract v0.21.1/go.mod h1:5fSm/l5xSjGWqsPUffSdboiGFUHa7y/1S0fvxzQowN8= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 h1:FxqFDhQYYgpe41qsIHVOcdzSVCB8JNSfPG7Uk4r2oSk= git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0/go.mod h1:RUIKZATQLJ+TaYQa60X2fTDwfuhMfm8Ar60bQ5fr+vU= -git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d h1:uJ/wvuMdepbkaV8XMS5uN9B0FQWMep0CttSuDZiDhq0= -git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.4.1-0.20240710074952-65761deb5c0d/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= +git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.5.2 h1:AovQs7bea0fLnYfldCZB88FkUgRj0QaHkJEbcWfgzvY= +git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.5.2/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 h1:fluzML8BIIabd07LyPSjc0JAV2qymWkPiFaLrXdALLA= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167 h1:NhqfqNcATndYwx413BaaYXxVJbkeu2vQOtVyxXw5xCQ= From 12a0537a7a9f5af0b4c2bd20f1d5b9f1891897d4 Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Tue, 25 Mar 2025 17:15:21 +0300 Subject: [PATCH 1303/1413] [#1689] ci: Add commit checker to Jenkinsfile - Commit checker image is built from dco-go: https://git.frostfs.info/TrueCloudLab/dco-go/pulls/14 - 'pull_request_target' branch is defined in Jenkins job: https://git.frostfs.info/TrueCloudLab/jenkins/pulls/10 https://git.frostfs.info/TrueCloudLab/jenkins/pulls/11 Change-Id: Ib86c5749f9e084d736b868240c4b47014b02ba8d Signed-off-by: Vitaliy Potyarkin --- .ci/Jenkinsfile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index 166fb92861..4ddd36406f 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -78,6 +78,10 @@ async { } } } -} -// TODO: dco check + task('dco') { + container('git.frostfs.info/truecloudlab/commit-check:master') { + sh 'FROM=pull_request_target commit-check' + } + } +} From 115aae7c34bd85f11a866d62ebe453c393f55c70 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Sat, 22 Mar 2025 01:54:06 +0300 Subject: [PATCH 1304/1413] [#1656] qos: Add tests for MaxActiveRPCLimiter Interceptors Change-Id: Ib65890ae5aec34c34e15d4ec1f05952f74f1ad26 Signed-off-by: Ekaterina Lebedeva --- internal/qos/grpc_test.go | 121 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 internal/qos/grpc_test.go diff --git a/internal/qos/grpc_test.go b/internal/qos/grpc_test.go new file mode 100644 index 0000000000..d6e2a689c4 --- /dev/null +++ b/internal/qos/grpc_test.go @@ -0,0 +1,121 @@ +package qos_test + +import ( + "context" + "errors" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" + "git.frostfs.info/TrueCloudLab/frostfs-qos/limiting" + "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" +) + +const ( + okKey = "ok" +) + +var ( + errTest = errors.New("mock") + errResExhausted *apistatus.ResourceExhausted +) + +type mockGRPCServerStream struct { + grpc.ServerStream + + ctx context.Context +} + +func (m *mockGRPCServerStream) Context() context.Context { + return m.ctx +} + +type limiter struct { + acquired bool + released bool +} + +func (l *limiter) Acquire(key string) (limiting.ReleaseFunc, bool) { + l.acquired = true + if key != okKey { + return nil, false + } + return func() { l.released = true }, true +} + +func unaryMaxActiveRPCLimiter(ctx context.Context, lim *limiter, methodName string) error { + interceptor := qos.NewMaxActiveRPCLimiterUnaryServerInterceptor(func() limiting.Limiter { return lim }) + handler := func(ctx context.Context, req any) (any, error) { + return nil, errTest + } + _, err := interceptor(ctx, nil, &grpc.UnaryServerInfo{FullMethod: methodName}, handler) + return err +} + +func streamMaxActiveRPCLimiter(ctx context.Context, lim *limiter, methodName string) error { + interceptor := qos.NewMaxActiveRPCLimiterStreamServerInterceptor(func() limiting.Limiter { return lim }) + handler := func(srv any, stream grpc.ServerStream) error { + return errTest + } + err := interceptor(nil, &mockGRPCServerStream{ctx: ctx}, &grpc.StreamServerInfo{ + FullMethod: methodName, + }, handler) + return err +} + +func Test_MaxActiveRPCLimiter(t *testing.T) { + // UnaryServerInterceptor + t.Run("unary fail", func(t *testing.T) { + var lim limiter + + err := unaryMaxActiveRPCLimiter(context.Background(), &lim, "") + require.ErrorAs(t, err, &errResExhausted) + require.True(t, lim.acquired) + require.False(t, lim.released) + }) + t.Run("unary pass critical", func(t *testing.T) { + var lim limiter + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagCritical.String()) + + err := unaryMaxActiveRPCLimiter(ctx, &lim, "") + require.ErrorIs(t, err, errTest) + require.False(t, lim.acquired) + require.False(t, lim.released) + }) + t.Run("unary pass", func(t *testing.T) { + var lim limiter + + err := unaryMaxActiveRPCLimiter(context.Background(), &lim, okKey) + require.ErrorIs(t, err, errTest) + require.True(t, lim.acquired) + require.True(t, lim.released) + }) + // StreamServerInterceptor + t.Run("stream fail", func(t *testing.T) { + var lim limiter + + err := streamMaxActiveRPCLimiter(context.Background(), &lim, "") + require.ErrorAs(t, err, &errResExhausted) + require.True(t, lim.acquired) + require.False(t, lim.released) + }) + t.Run("stream pass critical", func(t *testing.T) { + var lim limiter + ctx := tagging.ContextWithIOTag(context.Background(), qos.IOTagCritical.String()) + + err := streamMaxActiveRPCLimiter(ctx, &lim, "") + require.ErrorIs(t, err, errTest) + require.False(t, lim.acquired) + require.False(t, lim.released) + }) + t.Run("stream pass", func(t *testing.T) { + var lim limiter + + err := streamMaxActiveRPCLimiter(context.Background(), &lim, okKey) + require.ErrorIs(t, err, errTest) + require.True(t, lim.acquired) + require.True(t, lim.released) + }) +} From dcb2b23a7d863d2e07c11fc22ebd7ceb83467486 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Sat, 22 Mar 2025 16:36:55 +0300 Subject: [PATCH 1305/1413] [#1656] qos: Add test for `SetCriticalIOTag` Interceptor Change-Id: I4a55fcb84e6f65408a1c0120ac917e49e23354a1 Signed-off-by: Ekaterina Lebedeva --- internal/qos/grpc_test.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/qos/grpc_test.go b/internal/qos/grpc_test.go index d6e2a689c4..d4030c39ea 100644 --- a/internal/qos/grpc_test.go +++ b/internal/qos/grpc_test.go @@ -19,6 +19,7 @@ const ( var ( errTest = errors.New("mock") + errWrongTag = errors.New("wrong tag") errResExhausted *apistatus.ResourceExhausted ) @@ -119,3 +120,18 @@ func Test_MaxActiveRPCLimiter(t *testing.T) { require.True(t, lim.released) }) } + +func TestSetCriticalIOTagUnaryServerInterceptor_Pass(t *testing.T) { + interceptor := qos.NewSetCriticalIOTagUnaryServerInterceptor() + called := false + handler := func(ctx context.Context, req any) (any, error) { + called = true + if tag, ok := tagging.IOTagFromContext(ctx); ok && tag == qos.IOTagCritical.String() { + return nil, nil + } + return nil, errWrongTag + } + _, err := interceptor(context.Background(), nil, nil, handler) + require.NoError(t, err) + require.True(t, called) +} From 5a13830a94ab866b8425c3a97115a29a60007650 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 31 Mar 2025 14:14:30 +0300 Subject: [PATCH 1306/1413] [#1699] mod: Bump frostfs-qos version Change-Id: Ie5e708c0ca653596c6e3346aa286618868a5aee8 Signed-off-by: Dmitrii Stepanov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 76662ff5ea..23be9c8224 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.5.2 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 - git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167 + git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47 git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 diff --git a/go.sum b/go.sum index 42078073b0..e5d476ffeb 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.5.2 h1:AovQs7bea0fLnYfldCZB88 git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.5.2/go.mod h1:7ZZq8iguY7qFsXajdHGmZd2AW4QbucyrJwhbsRfOfek= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 h1:fluzML8BIIabd07LyPSjc0JAV2qymWkPiFaLrXdALLA= git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167 h1:NhqfqNcATndYwx413BaaYXxVJbkeu2vQOtVyxXw5xCQ= -git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250324133647-57d895c32167/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47 h1:O2c3VOlaGZ862hf2ZPLBMdTG6vGJzhIgDvFEFGfntzU= +git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945 h1:zM2l316J55h9p30snl6vHBI/h0xmnuqZjnxIjRDtJZw= git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= From a5bae6c5af6252a6d340a957742c4095daeb22be Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 31 Mar 2025 14:14:58 +0300 Subject: [PATCH 1307/1413] [#1699] qos: Allow to prohibit operations for IO tag Change-Id: I2bee26885244e241d224860978b6de3526527e96 Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config/engine/config_test.go | 7 ++++--- cmd/frostfs-node/config/engine/shard/limits/config.go | 8 ++++++++ config/example/node.env | 1 + config/example/node.json | 3 ++- config/example/node.yaml | 1 + docs/storage-node-configuration.md | 1 + internal/qos/limiter.go | 10 ++++++++-- 7 files changed, 25 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index eaf2a294e1..22f26268d0 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -168,9 +168,10 @@ func TestEngineSection(t *testing.T) { LimitOps: toPtr(25000), }, { - Tag: "policer", - Weight: toPtr(5), - LimitOps: toPtr(25000), + Tag: "policer", + Weight: toPtr(5), + LimitOps: toPtr(25000), + Prohibited: true, }, }) require.ElementsMatch(t, writeLimits.Tags, diff --git a/cmd/frostfs-node/config/engine/shard/limits/config.go b/cmd/frostfs-node/config/engine/shard/limits/config.go index b9b5c43824..8444d6aa83 100644 --- a/cmd/frostfs-node/config/engine/shard/limits/config.go +++ b/cmd/frostfs-node/config/engine/shard/limits/config.go @@ -84,6 +84,7 @@ type IOTagConfig struct { Weight *float64 LimitOps *float64 ReservedOps *float64 + Prohibited bool } func tags(c *config.Config) []IOTagConfig { @@ -119,6 +120,13 @@ func tags(c *config.Config) []IOTagConfig { tagConfig.ReservedOps = &r } + v = c.Value(strconv.Itoa(i) + ".prohibited") + if v != nil { + r, err := cast.ToBoolE(v) + panicOnErr(err) + tagConfig.Prohibited = r + } + result = append(result, tagConfig) } } diff --git a/config/example/node.env b/config/example/node.env index 010b6840cb..b7c798ad8c 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -180,6 +180,7 @@ FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_3_LIMIT_OPS=25000 FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_TAG=policer FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_WEIGHT=5 FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_LIMIT_OPS=25000 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_PROHIBITED=true FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_TAG=internal FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_WEIGHT=200 FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_LIMIT_OPS=0 diff --git a/config/example/node.json b/config/example/node.json index b26c35d2cb..2f4413e4d0 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -252,7 +252,8 @@ { "tag": "policer", "weight": 5, - "limit_ops": 25000 + "limit_ops": 25000, + "prohibited": true } ] }, diff --git a/config/example/node.yaml b/config/example/node.yaml index 58b687d5cc..a07795da53 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -249,6 +249,7 @@ storage: - tag: policer weight: 5 limit_ops: 25000 + prohibited: true write: max_running_ops: 1000 max_waiting_ops: 100 diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 51f0a9669f..3944f663f3 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -359,6 +359,7 @@ limits: | `tag.weight` | `float` | 0 (no weight) | Weight for queries with the specified tag. Weights must be specified for all tags or not specified for any one. | | `tag.limit_ops` | `float` | 0 (no limit) | Operations per second rate limit for queries with the specified tag. | | `tag.reserved_ops` | `float` | 0 (no reserve) | Reserved operations per second rate for queries with the specified tag. | +| `tag.prohibited` | `bool` | false | If true, operations with this specified tag will be prohibited. | # `node` section diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index 98d254fd0f..c73481c2c3 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -90,6 +90,7 @@ func converToSchedulingTags(limits []limits.IOTagConfig) map[string]scheduling.T if l.ReservedOps != nil && *l.ReservedOps != 0 { v.ReservedIOPS = l.ReservedOps } + v.Prohibited = l.Prohibited result[l.Tag] = v } return result @@ -164,8 +165,7 @@ func requestArrival(ctx context.Context, s scheduler, stats map[string]*stat) (R rel, err := s.RequestArrival(ctx, tag) stat.inProgress.Add(1) if err != nil { - if errors.Is(err, scheduling.ErrMClockSchedulerRequestLimitExceeded) || - errors.Is(err, errSemaphoreLimitExceeded) { + if isResourceExhaustedErr(err) { stat.resourceExhausted.Add(1) return nil, &apistatus.ResourceExhausted{} } @@ -234,3 +234,9 @@ func exportMetrics(metrics Metrics, stats map[string]*stat, shardID, operation s metrics.SetOperationTagCounters(shardID, operation, tag, pending, inProgress, completed, resExh) } } + +func isResourceExhaustedErr(err error) bool { + return errors.Is(err, scheduling.ErrMClockSchedulerRequestLimitExceeded) || + errors.Is(err, errSemaphoreLimitExceeded) || + errors.Is(err, scheduling.ErrTagRequestsProhibited) +} From 6e1576cfdb02883a6bbc4f2800ce98f9cd06c71a Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Sat, 22 Mar 2025 16:40:31 +0300 Subject: [PATCH 1308/1413] [#1656] qos: Add tests for `AdjustOutgoingIOTag` Interceptors Change-Id: If534e756b26cf7f202039d48ecdf554b4283728b Signed-off-by: Ekaterina Lebedeva --- internal/qos/grpc_test.go | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/internal/qos/grpc_test.go b/internal/qos/grpc_test.go index d4030c39ea..7d0826754d 100644 --- a/internal/qos/grpc_test.go +++ b/internal/qos/grpc_test.go @@ -3,6 +3,7 @@ package qos_test import ( "context" "errors" + "fmt" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" @@ -20,7 +21,9 @@ const ( var ( errTest = errors.New("mock") errWrongTag = errors.New("wrong tag") + errNoTag = errors.New("failed to get tag from context") errResExhausted *apistatus.ResourceExhausted + tags = []qos.IOTag{qos.IOTagBackground, qos.IOTagWritecache, qos.IOTagPolicer, qos.IOTagTreeSync} ) type mockGRPCServerStream struct { @@ -135,3 +138,82 @@ func TestSetCriticalIOTagUnaryServerInterceptor_Pass(t *testing.T) { require.NoError(t, err) require.True(t, called) } + +func TestAdjustOutgoingIOTagUnaryClientInterceptor(t *testing.T) { + interceptor := qos.NewAdjustOutgoingIOTagUnaryClientInterceptor() + + // check context with no value + called := false + invoker := func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, opts ...grpc.CallOption) error { + called = true + if _, ok := tagging.IOTagFromContext(ctx); ok { + return fmt.Errorf("%v: expected no IO tags", errWrongTag) + } + return nil + } + require.NoError(t, interceptor(context.Background(), "", nil, nil, nil, invoker, nil)) + require.True(t, called) + + // check context for internal tag + targetTag := qos.IOTagInternal.String() + invoker = func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, opts ...grpc.CallOption) error { + raw, ok := tagging.IOTagFromContext(ctx) + if !ok { + return errNoTag + } + if raw != targetTag { + return errWrongTag + } + return nil + } + for _, tag := range tags { + ctx := tagging.ContextWithIOTag(context.Background(), tag.String()) + require.NoError(t, interceptor(ctx, "", nil, nil, nil, invoker, nil)) + } + + // check context for client tag + ctx := tagging.ContextWithIOTag(context.Background(), "") + targetTag = qos.IOTagClient.String() + require.NoError(t, interceptor(ctx, "", nil, nil, nil, invoker, nil)) +} + +func TestAdjustOutgoingIOTagStreamClientInterceptor(t *testing.T) { + interceptor := qos.NewAdjustOutgoingIOTagStreamClientInterceptor() + + // check context with no value + called := false + streamer := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) { + called = true + if _, ok := tagging.IOTagFromContext(ctx); ok { + return nil, fmt.Errorf("%v: expected no IO tags", errWrongTag) + } + return nil, nil + } + _, err := interceptor(context.Background(), nil, nil, "", streamer, nil) + require.True(t, called) + require.NoError(t, err) + + // check context for internal tag + targetTag := qos.IOTagInternal.String() + streamer = func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) { + raw, ok := tagging.IOTagFromContext(ctx) + if !ok { + return nil, errNoTag + } + if raw != targetTag { + return nil, errWrongTag + } + return nil, nil + } + for _, tag := range tags { + ctx := tagging.ContextWithIOTag(context.Background(), tag.String()) + _, err := interceptor(ctx, nil, nil, "", streamer, nil) + require.NoError(t, err) + } + + // check context for client tag + ctx := tagging.ContextWithIOTag(context.Background(), "") + targetTag = qos.IOTagClient.String() + _, err = interceptor(ctx, nil, nil, "", streamer, nil) + require.NoError(t, err) +} From bc6cc9ae2a2631b8a10d27d588c67d88e7b7041c Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 1 Apr 2025 10:55:33 +0300 Subject: [PATCH 1309/1413] [#1700] engine: Print stacks on test request limiter Change-Id: I4952769ca431d1049955823b41b99b0984b385fc Signed-off-by: Dmitrii Stepanov --- .../engine/engine_test.go | 71 ++++++++++++++++--- 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 6ef3846ee6..711a76100d 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -2,8 +2,11 @@ package engine import ( "context" + "fmt" "path/filepath" - "sync/atomic" + "runtime/debug" + "strings" + "sync" "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" @@ -157,26 +160,74 @@ func newTestStorages(root string, smallSize uint64) ([]blobstor.SubStorage, *tes var _ qos.Limiter = (*testQoSLimiter)(nil) type testQoSLimiter struct { - t testing.TB - read atomic.Int64 - write atomic.Int64 + t testing.TB + quard sync.Mutex + id int64 + readStacks map[int64][]byte + writeStacks map[int64][]byte } func (t *testQoSLimiter) SetMetrics(qos.Metrics) {} func (t *testQoSLimiter) Close() { - require.Equal(t.t, int64(0), t.read.Load(), "read requests count after limiter close must be 0") - require.Equal(t.t, int64(0), t.write.Load(), "write requests count after limiter close must be 0") + t.quard.Lock() + defer t.quard.Unlock() + + var sb strings.Builder + var seqN int + for _, stack := range t.readStacks { + seqN++ + sb.WriteString(fmt.Sprintf("%d\n read request stack after limiter close: %s\n", seqN, string(stack))) + } + for _, stack := range t.writeStacks { + seqN++ + sb.WriteString(fmt.Sprintf("%d\n write request stack after limiter close: %s\n", seqN, string(stack))) + } + require.True(t.t, seqN == 0, sb.String()) } func (t *testQoSLimiter) ReadRequest(context.Context) (qos.ReleaseFunc, error) { - t.read.Add(1) - return func() { t.read.Add(-1) }, nil + t.quard.Lock() + defer t.quard.Unlock() + + stack := debug.Stack() + + t.id++ + id := t.id + + if t.readStacks == nil { + t.readStacks = make(map[int64][]byte) + } + t.readStacks[id] = stack + + return func() { + t.quard.Lock() + defer t.quard.Unlock() + + delete(t.readStacks, id) + }, nil } func (t *testQoSLimiter) WriteRequest(context.Context) (qos.ReleaseFunc, error) { - t.write.Add(1) - return func() { t.write.Add(-1) }, nil + t.quard.Lock() + defer t.quard.Unlock() + + stack := debug.Stack() + + t.id++ + id := t.id + + if t.writeStacks == nil { + t.writeStacks = make(map[int64][]byte) + } + t.writeStacks[id] = stack + + return func() { + t.quard.Lock() + defer t.quard.Unlock() + + delete(t.writeStacks, id) + }, nil } func (t *testQoSLimiter) SetParentID(string) {} From 27899598dc2617b859bdcd99d28fc7810329632a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 1 Apr 2025 12:37:35 +0300 Subject: [PATCH 1310/1413] [#1700] gc: Drop Event interface There is only one event: new epoch. Change-Id: I982f3650f7bc753ff2782393625452f0f8cdcc35 Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/shards.go | 4 +- pkg/local_object_storage/shard/control.go | 24 +++-- pkg/local_object_storage/shard/gc.go | 109 +++++++--------------- pkg/local_object_storage/shard/gc_test.go | 4 +- 4 files changed, 47 insertions(+), 94 deletions(-) diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index a38c851511..dfc3b1a352 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -318,8 +318,6 @@ func (e *StorageEngine) SetShardMode(ctx context.Context, id *shard.ID, m mode.M // HandleNewEpoch notifies every shard about NewEpoch event. func (e *StorageEngine) HandleNewEpoch(ctx context.Context, epoch uint64) { - ev := shard.EventNewEpoch(epoch) - e.mtx.RLock() defer e.mtx.RUnlock() @@ -327,7 +325,7 @@ func (e *StorageEngine) HandleNewEpoch(ctx context.Context, epoch uint64) { select { case <-ctx.Done(): return - case sh.NotificationChannel() <- ev: + case sh.NotificationChannel() <- epoch: default: e.log.Debug(ctx, logs.ShardEventProcessingInProgress, zap.Uint64("epoch", epoch), zap.Stringer("shard", sh.ID())) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 6dee2da3f6..19b13a8abe 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -108,19 +108,17 @@ func (s *Shard) Init(ctx context.Context) error { s.updateMetrics(ctx) s.gc = &gc{ - gcCfg: &s.gcCfg, - remover: s.removeGarbage, - stopChannel: make(chan struct{}), - eventChan: make(chan Event), - mEventHandler: map[eventType]*eventHandlers{ - eventNewEpoch: { - cancelFunc: func() {}, - handlers: []eventHandler{ - s.collectExpiredLocks, - s.collectExpiredObjects, - s.collectExpiredTombstones, - s.collectExpiredMetrics, - }, + gcCfg: &s.gcCfg, + remover: s.removeGarbage, + stopChannel: make(chan struct{}), + newEpochChan: make(chan uint64), + newEpochHandlers: &newEpochHandlers{ + cancelFunc: func() {}, + handlers: []newEpochHandler{ + s.collectExpiredLocks, + s.collectExpiredObjects, + s.collectExpiredTombstones, + s.collectExpiredMetrics, }, }, } diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 84fb6039ee..82e76f1a76 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -33,41 +33,14 @@ type TombstoneSource interface { IsTombstoneAvailable(ctx context.Context, addr oid.Address, epoch uint64) bool } -// Event represents class of external events. -type Event interface { - typ() eventType -} +type newEpochHandler func(context.Context, uint64) -type eventType int - -const ( - _ eventType = iota - eventNewEpoch -) - -type newEpoch struct { - epoch uint64 -} - -func (e newEpoch) typ() eventType { - return eventNewEpoch -} - -// EventNewEpoch returns new epoch event. -func EventNewEpoch(e uint64) Event { - return newEpoch{ - epoch: e, - } -} - -type eventHandler func(context.Context, Event) - -type eventHandlers struct { +type newEpochHandlers struct { prevGroup sync.WaitGroup cancelFunc context.CancelFunc - handlers []eventHandler + handlers []newEpochHandler } type gcRunResult struct { @@ -109,10 +82,10 @@ type gc struct { remover func(context.Context) gcRunResult - // eventChan is used only for listening for the new epoch event. + // newEpochChan is used only for listening for the new epoch event. // It is ok to keep opened, we are listening for context done when writing in it. - eventChan chan Event - mEventHandler map[eventType]*eventHandlers + newEpochChan chan uint64 + newEpochHandlers *newEpochHandlers } type gcCfg struct { @@ -142,15 +115,7 @@ func defaultGCCfg() gcCfg { } func (gc *gc) init(ctx context.Context) { - sz := 0 - - for _, v := range gc.mEventHandler { - sz += len(v.handlers) - } - - if sz > 0 { - gc.workerPool = gc.workerPoolInit(sz) - } + gc.workerPool = gc.workerPoolInit(len(gc.newEpochHandlers.handlers)) ctx = tagging.ContextWithIOTag(ctx, qos.IOTagBackground.String()) gc.wg.Add(2) go gc.tickRemover(ctx) @@ -168,7 +133,7 @@ func (gc *gc) listenEvents(ctx context.Context) { case <-ctx.Done(): gc.log.Warn(ctx, logs.ShardStopEventListenerByContext) return - case event, ok := <-gc.eventChan: + case event, ok := <-gc.newEpochChan: if !ok { gc.log.Warn(ctx, logs.ShardStopEventListenerByClosedEventChannel) return @@ -179,38 +144,33 @@ func (gc *gc) listenEvents(ctx context.Context) { } } -func (gc *gc) handleEvent(ctx context.Context, event Event) { - v, ok := gc.mEventHandler[event.typ()] - if !ok { - return - } - - v.cancelFunc() - v.prevGroup.Wait() +func (gc *gc) handleEvent(ctx context.Context, epoch uint64) { + gc.newEpochHandlers.cancelFunc() + gc.newEpochHandlers.prevGroup.Wait() var runCtx context.Context - runCtx, v.cancelFunc = context.WithCancel(ctx) + runCtx, gc.newEpochHandlers.cancelFunc = context.WithCancel(ctx) - v.prevGroup.Add(len(v.handlers)) + gc.newEpochHandlers.prevGroup.Add(len(gc.newEpochHandlers.handlers)) - for i := range v.handlers { + for i := range gc.newEpochHandlers.handlers { select { case <-ctx.Done(): return default: } - h := v.handlers[i] + h := gc.newEpochHandlers.handlers[i] err := gc.workerPool.Submit(func() { - defer v.prevGroup.Done() - h(runCtx, event) + defer gc.newEpochHandlers.prevGroup.Done() + h(runCtx, epoch) }) if err != nil { gc.log.Warn(ctx, logs.ShardCouldNotSubmitGCJobToWorkerPool, zap.Error(err), ) - v.prevGroup.Done() + gc.newEpochHandlers.prevGroup.Done() } } } @@ -362,7 +322,7 @@ func (s *Shard) getExpiredObjectsParameters() (workerCount, batchSize int) { return } -func (s *Shard) collectExpiredObjects(ctx context.Context, e Event) { +func (s *Shard) collectExpiredObjects(ctx context.Context, epoch uint64) { var err error startedAt := time.Now() @@ -370,8 +330,8 @@ func (s *Shard) collectExpiredObjects(ctx context.Context, e Event) { s.gc.metrics.AddExpiredObjectCollectionDuration(time.Since(startedAt), err == nil, objectTypeRegular) }() - s.log.Debug(ctx, logs.ShardGCCollectingExpiredObjectsStarted, zap.Uint64("epoch", e.(newEpoch).epoch)) - defer s.log.Debug(ctx, logs.ShardGCCollectingExpiredObjectsCompleted, zap.Uint64("epoch", e.(newEpoch).epoch)) + s.log.Debug(ctx, logs.ShardGCCollectingExpiredObjectsStarted, zap.Uint64("epoch", epoch)) + defer s.log.Debug(ctx, logs.ShardGCCollectingExpiredObjectsCompleted, zap.Uint64("epoch", epoch)) workersCount, batchSize := s.getExpiredObjectsParameters() @@ -380,7 +340,7 @@ func (s *Shard) collectExpiredObjects(ctx context.Context, e Event) { errGroup.Go(func() error { batch := make([]oid.Address, 0, batchSize) - expErr := s.getExpiredObjects(egCtx, e.(newEpoch).epoch, func(o *meta.ExpiredObject) { + expErr := s.getExpiredObjects(egCtx, epoch, func(o *meta.ExpiredObject) { if o.Type() != objectSDK.TypeTombstone && o.Type() != objectSDK.TypeLock { batch = append(batch, o.Address()) @@ -486,7 +446,7 @@ func (s *Shard) inhumeGC(ctx context.Context, addrs []oid.Address) (meta.InhumeR return s.metaBase.Inhume(ctx, inhumePrm) } -func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { +func (s *Shard) collectExpiredTombstones(ctx context.Context, epoch uint64) { var err error startedAt := time.Now() @@ -494,7 +454,6 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { s.gc.metrics.AddExpiredObjectCollectionDuration(time.Since(startedAt), err == nil, objectTypeTombstone) }() - epoch := e.(newEpoch).epoch log := s.log.With(zap.Uint64("epoch", epoch)) log.Debug(ctx, logs.ShardStartedExpiredTombstonesHandling) @@ -566,7 +525,7 @@ func (s *Shard) collectExpiredTombstones(ctx context.Context, e Event) { } } -func (s *Shard) collectExpiredLocks(ctx context.Context, e Event) { +func (s *Shard) collectExpiredLocks(ctx context.Context, epoch uint64) { var err error startedAt := time.Now() @@ -574,8 +533,8 @@ func (s *Shard) collectExpiredLocks(ctx context.Context, e Event) { s.gc.metrics.AddExpiredObjectCollectionDuration(time.Since(startedAt), err == nil, objectTypeLock) }() - s.log.Debug(ctx, logs.ShardGCCollectingExpiredLocksStarted, zap.Uint64("epoch", e.(newEpoch).epoch)) - defer s.log.Debug(ctx, logs.ShardGCCollectingExpiredLocksCompleted, zap.Uint64("epoch", e.(newEpoch).epoch)) + s.log.Debug(ctx, logs.ShardGCCollectingExpiredLocksStarted, zap.Uint64("epoch", epoch)) + defer s.log.Debug(ctx, logs.ShardGCCollectingExpiredLocksCompleted, zap.Uint64("epoch", epoch)) workersCount, batchSize := s.getExpiredObjectsParameters() @@ -585,14 +544,14 @@ func (s *Shard) collectExpiredLocks(ctx context.Context, e Event) { errGroup.Go(func() error { batch := make([]oid.Address, 0, batchSize) - expErr := s.getExpiredObjects(egCtx, e.(newEpoch).epoch, func(o *meta.ExpiredObject) { + expErr := s.getExpiredObjects(egCtx, epoch, func(o *meta.ExpiredObject) { if o.Type() == objectSDK.TypeLock { batch = append(batch, o.Address()) if len(batch) == batchSize { expired := batch errGroup.Go(func() error { - s.expiredLocksCallback(egCtx, e.(newEpoch).epoch, expired) + s.expiredLocksCallback(egCtx, epoch, expired) return egCtx.Err() }) batch = make([]oid.Address, 0, batchSize) @@ -606,7 +565,7 @@ func (s *Shard) collectExpiredLocks(ctx context.Context, e Event) { if len(batch) > 0 { expired := batch errGroup.Go(func() error { - s.expiredLocksCallback(egCtx, e.(newEpoch).epoch, expired) + s.expiredLocksCallback(egCtx, epoch, expired) return egCtx.Err() }) } @@ -785,17 +744,15 @@ func (s *Shard) HandleDeletedLocks(ctx context.Context, lockers []oid.Address) { } } -// NotificationChannel returns channel for shard events. -func (s *Shard) NotificationChannel() chan<- Event { - return s.gc.eventChan +// NotificationChannel returns channel for new epoch events. +func (s *Shard) NotificationChannel() chan<- uint64 { + return s.gc.newEpochChan } -func (s *Shard) collectExpiredMetrics(ctx context.Context, e Event) { +func (s *Shard) collectExpiredMetrics(ctx context.Context, epoch uint64) { ctx, span := tracing.StartSpanFromContext(ctx, "shard.collectExpiredMetrics") defer span.End() - epoch := e.(newEpoch).epoch - s.log.Debug(ctx, logs.ShardGCCollectingExpiredMetricsStarted, zap.Uint64("epoch", epoch)) defer s.log.Debug(ctx, logs.ShardGCCollectingExpiredMetricsCompleted, zap.Uint64("epoch", epoch)) diff --git a/pkg/local_object_storage/shard/gc_test.go b/pkg/local_object_storage/shard/gc_test.go index e3670b441b..f512a488ad 100644 --- a/pkg/local_object_storage/shard/gc_test.go +++ b/pkg/local_object_storage/shard/gc_test.go @@ -69,7 +69,7 @@ func Test_GCDropsLockedExpiredSimpleObject(t *testing.T) { require.NoError(t, err) epoch.Value = 105 - sh.gc.handleEvent(context.Background(), EventNewEpoch(epoch.Value)) + sh.gc.handleEvent(context.Background(), epoch.Value) var getPrm GetPrm getPrm.SetAddress(objectCore.AddressOf(obj)) @@ -165,7 +165,7 @@ func Test_GCDropsLockedExpiredComplexObject(t *testing.T) { require.True(t, errors.As(err, &splitInfoError), "split info must be provided") epoch.Value = 105 - sh.gc.handleEvent(context.Background(), EventNewEpoch(epoch.Value)) + sh.gc.handleEvent(context.Background(), epoch.Value) _, err = sh.Get(context.Background(), getPrm) require.True(t, client.IsErrObjectNotFound(err) || IsErrObjectExpired(err), "expired complex object must be deleted on epoch after lock expires") From f62d81e26a6b4ca44fbb15fd7dd4e1343bdbed71 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 1 Apr 2025 12:50:21 +0300 Subject: [PATCH 1311/1413] [#1700] gc: Take mode mutex in locks handlers Change-Id: I4408eae3aed936f85427b6246dcf727bd6813a0d Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/gc.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 82e76f1a76..3b9ad690b1 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -664,7 +664,10 @@ func (s *Shard) HandleExpiredTombstones(ctx context.Context, tss []meta.Tombston // HandleExpiredLocks unlocks all objects which were locked by lockers. // If successful, marks lockers themselves as garbage. func (s *Shard) HandleExpiredLocks(ctx context.Context, epoch uint64, lockers []oid.Address) { - if s.GetMode().NoMetabase() { + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { return } @@ -727,7 +730,10 @@ func (s *Shard) inhumeUnlockedIfExpired(ctx context.Context, epoch uint64, unloc // HandleDeletedLocks unlocks all objects which were locked by lockers. func (s *Shard) HandleDeletedLocks(ctx context.Context, lockers []oid.Address) { - if s.GetMode().NoMetabase() { + s.m.RLock() + defer s.m.RUnlock() + + if s.info.Mode.NoMetabase() { return } From 19ca9072237254f1b32b18c19e75586d8bb1c88a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 1 Apr 2025 13:16:11 +0300 Subject: [PATCH 1312/1413] [#1689] treesvc: Untie `createConnection()` from `Service` struct Change-Id: I6212de4b81afe8c2516981a7bb2fea099c7df773 Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/sync.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 1c35213445..92ff97c1c4 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -301,7 +301,7 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return false } - cc, err := s.createConnection(a) + cc, err := createConnection(a) if err != nil { s.log.Warn(ctx, logs.TreeFailedToConnectForTreeSynchronization, zap.Error(err), zap.String("address", addr)) return false @@ -339,7 +339,7 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return from } -func (*Service) createConnection(a network.Address) (*grpc.ClientConn, error) { +func createConnection(a network.Address) (*grpc.ClientConn, error) { return grpc.NewClient(a.URIAddr(), grpc.WithChainUnaryInterceptor( qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), From b112a92408fac6a2da5509d5c5c9a86b044ea908 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 1 Apr 2025 13:20:20 +0300 Subject: [PATCH 1313/1413] [#1689] treesvc: Create request after client is initialized Make it easier to follow. Change-Id: I40c4db77f015bb45cb25f16ce24e68188fc14380 Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/cache.go | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index e2be2f4a2b..a74fdc5ddf 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -117,13 +117,6 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } - req := &HealthcheckRequest{ - Body: &HealthcheckRequest_Body{}, - } - if err := SignMessage(req, c.key); err != nil { - return nil, err - } - cc, err := grpc.NewClient(netAddr.URIAddr(), opts...) if err != nil { return nil, err @@ -131,6 +124,14 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* ctx, cancel := context.WithTimeout(ctx, defaultClientConnectTimeout) defer cancel() + + req := &HealthcheckRequest{ + Body: &HealthcheckRequest_Body{}, + } + if err := SignMessage(req, c.key); err != nil { + return nil, err + } + // perform some request to check connection if _, err := NewTreeServiceClient(cc).Healthcheck(ctx, req); err != nil { _ = cc.Close() From a11b54ca150a9ae8900698c95fb3fc26eed44bb3 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 1 Apr 2025 13:31:48 +0300 Subject: [PATCH 1314/1413] [#1689] treesvc: Unify gRPC client creation for cache and sync They connect to the same endpoints, the only difference is that connection for synchronization is limited in lifetime and is closed after the sync is finished. This is probably not intentional, as synchronization was implemented before cache was introduced. However, reusing dialTreeService() in sync.go has possible perfomance implications, so is avoided for now. Change-Id: I2e37befd783b4d873ff833969f932deded1195be Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/cache.go | 29 +---------------------------- pkg/services/tree/sync.go | 8 +++++--- 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index a74fdc5ddf..d250f577ac 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -9,15 +9,10 @@ import ( "time" internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" - "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" - metrics "git.frostfs.info/TrueCloudLab/frostfs-observability/metrics/grpc" - tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" - "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" "github.com/hashicorp/golang-lru/v2/simplelru" "google.golang.org/grpc" "google.golang.org/grpc/connectivity" - "google.golang.org/grpc/credentials/insecure" ) type clientCache struct { @@ -95,29 +90,7 @@ func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (* return nil, err } - opts := []grpc.DialOption{ - grpc.WithChainUnaryInterceptor( - qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), - metrics.NewUnaryClientInterceptor(), - tracing.NewUnaryClientInterceptor(), - tagging.NewUnaryClientInterceptor(), - ), - grpc.WithChainStreamInterceptor( - qos.NewAdjustOutgoingIOTagStreamClientInterceptor(), - metrics.NewStreamClientInterceptor(), - tracing.NewStreamClientInterceptor(), - tagging.NewStreamClientInterceptor(), - ), - grpc.WithContextDialer(c.ds.GrpcContextDialer()), - grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), - grpc.WithDisableServiceConfig(), - } - - if !netAddr.IsTLSEnabled() { - opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) - } - - cc, err := grpc.NewClient(netAddr.URIAddr(), opts...) + cc, err := createConnection(netAddr, grpc.WithContextDialer(c.ds.GrpcContextDialer())) if err != nil { return nil, err } diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 92ff97c1c4..7107b2bada 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -339,8 +339,8 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return from } -func createConnection(a network.Address) (*grpc.ClientConn, error) { - return grpc.NewClient(a.URIAddr(), +func createConnection(a network.Address, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + defaultOpts := []grpc.DialOption{ grpc.WithChainUnaryInterceptor( qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), metrics.NewUnaryClientInterceptor(), @@ -356,7 +356,9 @@ func createConnection(a network.Address) (*grpc.ClientConn, error) { grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), grpc.WithDisableServiceConfig(), - ) + } + + return grpc.NewClient(a.URIAddr(), append(defaultOpts, opts...)...) } // ErrAlreadySyncing is returned when a service synchronization has already From 3cd808023285c226a086d7756db837f5b0559339 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 1 Apr 2025 13:35:41 +0300 Subject: [PATCH 1315/1413] [#1689] treesvc: Fix dial options for TLS connections There are two problems with the current approach: 1. For TLS connections we need different transport credentials. 2. grpc.NewClient() considers scheme from `URIAddr()` as a scheme for a resolver. `grpcs://` scheme doesn't exist, though, so the default one is picked. The default resolver (`dns://`) is in turn unable to parse the https://github.com/grpc/grpc-go/blob/5edab9e55414068e74320716117a2659c5d2174e/internal/resolver/dns/dns_resolver.go#L405 The error is `grpcs://192.168.198.248:8081:443: too many colons in address`. Both problems don't exist in the SDK code, take it from there. Change-Id: Ia1212050f539162a560796685efdc3f9cfbf80a0 Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/sync.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 7107b2bada..1a084a47fe 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -3,6 +3,7 @@ package tree import ( "context" "crypto/sha256" + "crypto/tls" "errors" "fmt" "io" @@ -22,12 +23,14 @@ import ( tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" tracing_grpc "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/panjf2000/ants/v2" "go.uber.org/zap" "golang.org/x/sync/errgroup" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" ) @@ -340,6 +343,16 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, } func createConnection(a network.Address, opts ...grpc.DialOption) (*grpc.ClientConn, error) { + host, isTLS, err := client.ParseURI(a.URIAddr()) + if err != nil { + return nil, err + } + + creds := insecure.NewCredentials() + if isTLS { + creds = credentials.NewTLS(&tls.Config{}) + } + defaultOpts := []grpc.DialOption{ grpc.WithChainUnaryInterceptor( qos.NewAdjustOutgoingIOTagUnaryClientInterceptor(), @@ -353,12 +366,12 @@ func createConnection(a network.Address, opts ...grpc.DialOption) (*grpc.ClientC tracing_grpc.NewStreamClientInterceptor(), tagging.NewStreamClientInterceptor(), ), - grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithTransportCredentials(creds), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), grpc.WithDisableServiceConfig(), } - return grpc.NewClient(a.URIAddr(), append(defaultOpts, opts...)...) + return grpc.NewClient(host, append(defaultOpts, opts...)...) } // ErrAlreadySyncing is returned when a service synchronization has already From b27f7d1d175b7d132497087497270b4bf8ecff64 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 1 Apr 2025 13:43:20 +0300 Subject: [PATCH 1316/1413] [#1689] treesvc: Use context dialer in synchronizeTree() This dialer supports source-based routing and is already used in cache. Change-Id: Ic7852edd2faea4e5d8667221e6f681cc82bb143a Signed-off-by: Evgenii Stratonikov --- pkg/services/tree/sync.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 1a084a47fe..8abdafaa73 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -304,7 +304,7 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return false } - cc, err := createConnection(a) + cc, err := createConnection(a, grpc.WithContextDialer(s.ds.GrpcContextDialer())) if err != nil { s.log.Warn(ctx, logs.TreeFailedToConnectForTreeSynchronization, zap.Error(err), zap.String("address", addr)) return false From bd1c18e117f7a4eb7d23e1f173fbd802252374d4 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 1 Apr 2025 13:51:53 +0300 Subject: [PATCH 1317/1413] [#1689] cli/tree: Copy dial options from the service code There should be no `grpcs://` prefix in address and credentials should be picked. Change-Id: I58cdc98b079eac2c7db7dc088f4f131794a91b9f Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/tree/client.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/tree/client.go b/cmd/frostfs-cli/modules/tree/client.go index 421b96ccdd..d71a94b983 100644 --- a/cmd/frostfs-cli/modules/tree/client.go +++ b/cmd/frostfs-cli/modules/tree/client.go @@ -2,17 +2,19 @@ package tree import ( "context" + "crypto/tls" "fmt" - "strings" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" tracing "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/spf13/cobra" "github.com/spf13/viper" "google.golang.org/grpc" + "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" ) @@ -31,6 +33,16 @@ func _client() (tree.TreeServiceClient, error) { return nil, err } + host, isTLS, err := client.ParseURI(netAddr.URIAddr()) + if err != nil { + return nil, err + } + + creds := insecure.NewCredentials() + if isTLS { + creds = credentials.NewTLS(&tls.Config{}) + } + opts := []grpc.DialOption{ grpc.WithChainUnaryInterceptor( tracing.NewUnaryClientInterceptor(), @@ -40,13 +52,10 @@ func _client() (tree.TreeServiceClient, error) { ), grpc.WithDefaultCallOptions(grpc.WaitForReady(true)), grpc.WithDisableServiceConfig(), + grpc.WithTransportCredentials(creds), } - if !strings.HasPrefix(netAddr.URIAddr(), "grpcs:") { - opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) - } - - cc, err := grpc.NewClient(netAddr.URIAddr(), opts...) + cc, err := grpc.NewClient(host, opts...) return tree.NewTreeServiceClient(cc), err } From e142d25fac6c5a3377e598639f36d7286a779a80 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 1 Apr 2025 12:56:55 +0300 Subject: [PATCH 1318/1413] [#1700] gc: Wait for handlers on GC stopping First wait for goroutine handles epoch events to not to get data race on `gc.newEpochHandlers.cancelFunc`. Then cancel handlers and wait for them. Change-Id: I71f11f8526961f8356f582a95b10eb8340c0aedd Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/gc.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 3b9ad690b1..9b327f6f12 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -227,6 +227,9 @@ func (gc *gc) stop(ctx context.Context) { gc.log.Info(ctx, logs.ShardWaitingForGCWorkersToStop) gc.wg.Wait() + + gc.newEpochHandlers.cancelFunc() + gc.newEpochHandlers.prevGroup.Wait() } // iterates over metabase and deletes objects From b924ecb850d7812395e1ff9427857403e1e1f663 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 31 Mar 2025 10:53:40 +0300 Subject: [PATCH 1319/1413] [#1689] object: Make patch streamer use `ApplyHeaderPatch` Change-Id: I4fb94936621544f70ef4e08815c42efaa5ba846f Signed-off-by: Airat Arifullin --- pkg/services/object/patch/streamer.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/services/object/patch/streamer.go b/pkg/services/object/patch/streamer.go index 642b9f9fa1..ff13b1d3ed 100644 --- a/pkg/services/object/patch/streamer.go +++ b/pkg/services/object/patch/streamer.go @@ -195,7 +195,12 @@ func (s *Streamer) Send(ctx context.Context, req *objectV2.PatchRequest) error { patch.FromV2(req.GetBody()) if !s.nonFirstSend { - err := s.patcher.ApplyAttributesPatch(ctx, patch.NewAttributes, patch.ReplaceAttributes) + err := s.patcher.ApplyHeaderPatch(ctx, + patcher.ApplyHeaderPatchPrm{ + NewSplitHeader: patch.NewSplitHeader, + NewAttributes: patch.NewAttributes, + ReplaceAttributes: patch.ReplaceAttributes, + }) if err != nil { return fmt.Errorf("patch attributes: %w", err) } From 11493d587bd31de7e8d0c52eb671a7abe934294e Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 2 Apr 2025 11:07:15 +0300 Subject: [PATCH 1320/1413] [#579] config: Change config example to be compatible with YAML 1.2 standard In accordance with the YAML 1.2 specification, octal numbers must begin with the 0o prefix. Change-Id: Icb2e83a4aa75c1eb91decd0b7c9b146aaa9fb3e2 Signed-off-by: Alexander Chuprov --- config/example/node.yaml | 8 ++++---- docs/storage-node-configuration.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/config/example/node.yaml b/config/example/node.yaml index a07795da53..a448ba7ce6 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -148,7 +148,7 @@ storage: flush_worker_count: 30 # number of write-cache flusher threads metabase: - perm: 0644 # permissions for metabase files(directories: +x for current user and group) + perm: 0o644 # permissions for metabase files(directories: +x for current user and group) max_batch_size: 200 max_batch_delay: 20ms @@ -161,13 +161,13 @@ storage: blobstor: - size: 4m # approximate size limit of single blobovnicza instance, total size will be: size*width^(depth+1), bytes - perm: 0644 # permissions for blobstor files(directories: +x for current user and group) + perm: 0o644 # permissions for blobstor files(directories: +x for current user and group) depth: 1 # max depth of object tree storage in key-value DB width: 4 # max width of object tree storage in key-value DB opened_cache_capacity: 50 # maximum number of opened database files opened_cache_ttl: 5m # ttl for opened database file opened_cache_exp_interval: 15s # cache cleanup interval for expired blobovnicza's - - perm: 0644 # permissions for blobstor files(directories: +x for current user and group) + - perm: 0o644 # permissions for blobstor files(directories: +x for current user and group) depth: 5 # max depth of object tree storage in FS gc: @@ -291,7 +291,7 @@ storage: pilorama: path: tmp/1/blob/pilorama.db no_sync: true # USE WITH CAUTION. Return to user before pages have been persisted. - perm: 0644 # permission to use for the database file and intermediate directories + perm: 0o644 # permission to use for the database file and intermediate directories tracing: enabled: true diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 3944f663f3..b5c8aadfed 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -209,7 +209,7 @@ blobstor: width: 4 - type: fstree path: /path/to/blobstor/blobovnicza - perm: 0644 + perm: 0o644 size: 4194304 depth: 1 width: 4 @@ -269,7 +269,7 @@ gc: ```yaml metabase: path: /path/to/meta.db - perm: 0644 + perm: 0o644 max_batch_size: 200 max_batch_delay: 20ms ``` From 2a6cdbdb72a3acb07948bf1e0124df98fc964925 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 31 Mar 2025 10:53:56 +0300 Subject: [PATCH 1321/1413] [#1689] cli: Add `split-header` option for object patch command * Make `split-header` option read binary- or JSON-encoded split-header; * Use `PatchHeader` instead of `PatchAttributes`. Change-Id: I50ae1bd93d4695657249dacbea981199a39e1a35 Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/internal/client/client.go | 8 +++++++- cmd/frostfs-cli/modules/object/patch.go | 25 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/internal/client/client.go b/cmd/frostfs-cli/internal/client/client.go index 3f235f070b..299d0a830c 100644 --- a/cmd/frostfs-cli/internal/client/client.go +++ b/cmd/frostfs-cli/internal/client/client.go @@ -858,6 +858,8 @@ type PatchObjectPrm struct { ReplaceAttribute bool + NewSplitHeader *objectSDK.SplitHeader + PayloadPatches []PayloadPatch } @@ -888,7 +890,11 @@ func Patch(ctx context.Context, prm PatchObjectPrm) (*PatchRes, error) { return nil, fmt.Errorf("init payload reading: %w", err) } - if patcher.PatchAttributes(ctx, prm.NewAttributes, prm.ReplaceAttribute) { + if patcher.PatchHeader(ctx, client.PatchHeaderPrm{ + NewSplitHeader: prm.NewSplitHeader, + NewAttributes: prm.NewAttributes, + ReplaceAttributes: prm.ReplaceAttribute, + }) { for _, pp := range prm.PayloadPatches { payloadFile, err := os.OpenFile(pp.PayloadPath, os.O_RDONLY, os.ModePerm) if err != nil { diff --git a/cmd/frostfs-cli/modules/object/patch.go b/cmd/frostfs-cli/modules/object/patch.go index d981826793..ebbde76a25 100644 --- a/cmd/frostfs-cli/modules/object/patch.go +++ b/cmd/frostfs-cli/modules/object/patch.go @@ -2,6 +2,7 @@ package object import ( "fmt" + "os" "strconv" "strings" @@ -9,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key" commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -20,6 +22,7 @@ const ( replaceAttrsFlagName = "replace-attrs" rangeFlagName = "range" payloadFlagName = "payload" + splitHeaderFlagName = "split-header" ) var objectPatchCmd = &cobra.Command{ @@ -50,6 +53,7 @@ func initObjectPatchCmd() { flags.Bool(replaceAttrsFlagName, false, "Replace object attributes by new ones.") flags.StringSlice(rangeFlagName, []string{}, "Range to which patch payload is applied. Format: offset:length") flags.StringSlice(payloadFlagName, []string{}, "Path to file with patch payload.") + flags.String(splitHeaderFlagName, "", "Path to binary or JSON-encoded split header") } func patch(cmd *cobra.Command, _ []string) { @@ -84,6 +88,8 @@ func patch(cmd *cobra.Command, _ []string) { prm.NewAttributes = newAttrs prm.ReplaceAttribute = replaceAttrs + prm.NewSplitHeader = parseSplitHeaderBinaryOrJSON(cmd) + for i := range ranges { prm.PayloadPatches = append(prm.PayloadPatches, internalclient.PayloadPatch{ Range: ranges[i], @@ -147,3 +153,22 @@ func patchPayloadPaths(cmd *cobra.Command) []string { v, _ := cmd.Flags().GetStringSlice(payloadFlagName) return v } + +func parseSplitHeaderBinaryOrJSON(cmd *cobra.Command) *objectSDK.SplitHeader { + path, _ := cmd.Flags().GetString(splitHeaderFlagName) + if path == "" { + return nil + } + + data, err := os.ReadFile(path) + commonCmd.ExitOnErr(cmd, "read file error: %w", err) + + splitHdrV2 := new(objectV2.SplitHeader) + err = splitHdrV2.Unmarshal(data) + if err != nil { + err = splitHdrV2.UnmarshalJSON(data) + commonCmd.ExitOnErr(cmd, "unmarshal error: %w", err) + } + + return objectSDK.NewSplitHeaderFromV2(splitHdrV2) +} From 634de975094b8f83b5b9eeff15b7fd2bfdd6f1fc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 3 Apr 2025 10:09:05 +0300 Subject: [PATCH 1322/1413] [#1704] metabase: Do not ignore errors by Delete Change-Id: Ie7b89071a007f53f55879ff9e7e0c25d24ad5dbf Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/metabase/delete.go | 59 ++++++++++++--------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index d338e228ff..cf1d563e9b 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -376,11 +376,12 @@ func parentLength(tx *bbolt.Tx, addr oid.Address) int { return len(lst) } -func delUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) { +func delUniqueIndexItem(tx *bbolt.Tx, item namedBucketItem) error { bkt := tx.Bucket(item.name) if bkt != nil { - _ = bkt.Delete(item.key) // ignore error, best effort there + return bkt.Delete(item.key) } + return nil } func delListIndexItem(tx *bbolt.Tx, item namedBucketItem) error { @@ -405,19 +406,16 @@ func delListIndexItem(tx *bbolt.Tx, item namedBucketItem) error { // if list empty, remove the key from bucket if len(lst) == 0 { - _ = bkt.Delete(item.key) // ignore error, best effort there - - return nil + return bkt.Delete(item.key) } // if list is not empty, then update it encodedLst, err := encodeList(lst) if err != nil { - return nil // ignore error, best effort there + return err } - _ = bkt.Put(item.key, encodedLst) // ignore error, best effort there - return nil + return bkt.Put(item.key, encodedLst) } func delFKBTIndexItem(tx *bbolt.Tx, item namedBucketItem) error { @@ -480,35 +478,47 @@ func delUniqueIndexes(tx *bbolt.Tx, obj *objectSDK.Object, isParent bool) error return ErrUnknownObjectType } - delUniqueIndexItem(tx, namedBucketItem{ + if err := delUniqueIndexItem(tx, namedBucketItem{ name: bucketName, key: objKey, - }) + }); err != nil { + return err + } } else { - delUniqueIndexItem(tx, namedBucketItem{ + if err := delUniqueIndexItem(tx, namedBucketItem{ name: parentBucketName(cnr, bucketName), key: objKey, - }) + }); err != nil { + return err + } } - delUniqueIndexItem(tx, namedBucketItem{ // remove from storage id index + if err := delUniqueIndexItem(tx, namedBucketItem{ // remove from storage id index name: smallBucketName(cnr, bucketName), key: objKey, - }) - delUniqueIndexItem(tx, namedBucketItem{ // remove from root index + }); err != nil { + return err + } + if err := delUniqueIndexItem(tx, namedBucketItem{ // remove from root index name: rootBucketName(cnr, bucketName), key: objKey, - }) + }); err != nil { + return err + } if expEpoch, ok := hasExpirationEpoch(obj); ok { - delUniqueIndexItem(tx, namedBucketItem{ + if err := delUniqueIndexItem(tx, namedBucketItem{ name: expEpochToObjectBucketName, key: expirationEpochKey(expEpoch, cnr, addr.Object()), - }) - delUniqueIndexItem(tx, namedBucketItem{ + }); err != nil { + return err + } + if err := delUniqueIndexItem(tx, namedBucketItem{ name: objectToExpirationEpochBucketName(cnr, make([]byte, bucketKeySize)), key: objKey, - }) + }); err != nil { + return err + } } return nil @@ -535,10 +545,12 @@ func deleteECRelatedInfo(tx *bbolt.Tx, garbageBKT *bbolt.Bucket, obj *objectSDK. // also drop EC parent root info if current EC chunk is the last one if !hasAnyChunks { - delUniqueIndexItem(tx, namedBucketItem{ + if err := delUniqueIndexItem(tx, namedBucketItem{ name: rootBucketName(cnr, make([]byte, bucketKeySize)), key: objectKey(ech.Parent(), make([]byte, objectKeySize)), - }) + }); err != nil { + return err + } } if ech.ParentSplitParentID() == nil { @@ -572,11 +584,10 @@ func deleteECRelatedInfo(tx *bbolt.Tx, garbageBKT *bbolt.Bucket, obj *objectSDK. } // drop split info - delUniqueIndexItem(tx, namedBucketItem{ + return delUniqueIndexItem(tx, namedBucketItem{ name: rootBucketName(cnr, make([]byte, bucketKeySize)), key: objectKey(*ech.ParentSplitParentID(), make([]byte, objectKeySize)), }) - return nil } func hasAnyECChunks(tx *bbolt.Tx, ech *objectSDK.ECHeader, cnr cid.ID) bool { From 50dccff7c1e16eb242bfe192ddc3b93d91c03427 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 10 Mar 2025 11:43:40 +0300 Subject: [PATCH 1323/1413] [#1633] morph/netmap: Merge node info in netmap with candidates list Applicable for both cases: when node uses local cache for netmap and when it disabled. Change-Id: I3050f537e20312a4b39e944aca763b77bd1e74c4 Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/cache.go | 292 +++++++++++++++++++----- cmd/frostfs-node/cache_test.go | 74 ++++++ cmd/frostfs-node/config/morph/config.go | 17 ++ cmd/frostfs-node/morph.go | 5 +- cmd/frostfs-node/netmap_source.go | 55 +++++ config/example/node.yaml | 3 + docs/storage-node-configuration.md | 18 +- internal/logs/logs.go | 1 + 8 files changed, 397 insertions(+), 68 deletions(-) create mode 100644 cmd/frostfs-node/netmap_source.go diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index 0fe56d2b08..38cee5837b 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -1,20 +1,27 @@ package main import ( + "bytes" + "cmp" "context" + "slices" "sync" + "sync/atomic" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" - lru "github.com/hashicorp/golang-lru/v2" "github.com/hashicorp/golang-lru/v2/expirable" + "github.com/hashicorp/golang-lru/v2/simplelru" + "go.uber.org/zap" ) type netValueReader[K any, V any] func(ctx context.Context, cid K) (V, error) @@ -110,55 +117,6 @@ func (c *ttlNetCache[K, V]) remove(key K) { hit = c.cache.Remove(key) } -// entity that provides LRU cache interface. -type lruNetCache struct { - cache *lru.Cache[uint64, *netmapSDK.NetMap] - - netRdr netValueReader[uint64, *netmapSDK.NetMap] - - metrics cacheMetrics -} - -// newNetworkLRUCache returns wrapper over netValueReader with LRU cache. -func newNetworkLRUCache(sz int, netRdr netValueReader[uint64, *netmapSDK.NetMap], metrics cacheMetrics) *lruNetCache { - cache, err := lru.New[uint64, *netmapSDK.NetMap](sz) - fatalOnErr(err) - - return &lruNetCache{ - cache: cache, - netRdr: netRdr, - metrics: metrics, - } -} - -// reads value by the key. -// -// updates the value from the network on cache miss. -// -// returned value should not be modified. -func (c *lruNetCache) get(ctx context.Context, key uint64) (*netmapSDK.NetMap, error) { - hit := false - startedAt := time.Now() - defer func() { - c.metrics.AddMethodDuration("Get", time.Since(startedAt), hit) - }() - - val, ok := c.cache.Get(key) - if ok { - hit = true - return val, nil - } - - val, err := c.netRdr(ctx, key) - if err != nil { - return nil, err - } - - c.cache.Add(key, val) - - return val, nil -} - // wrapper over TTL cache of values read from the network // that implements container storage. type ttlContainerStorage struct { @@ -200,20 +158,236 @@ func (s ttlContainerStorage) DeletionInfo(ctx context.Context, cnr cid.ID) (*con type lruNetmapSource struct { netState netmap.State - cache *lruNetCache + client rawSource + cache *simplelru.LRU[uint64, *atomic.Pointer[netmapSDK.NetMap]] + mtx sync.RWMutex + metrics cacheMetrics + log *logger.Logger + candidates atomic.Pointer[[]netmapSDK.NodeInfo] } -func newCachedNetmapStorage(s netmap.State, v netmap.Source) netmap.Source { +type rawSource interface { + GetCandidates(ctx context.Context) ([]netmapSDK.NodeInfo, error) + GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmapSDK.NetMap, error) +} + +func newCachedNetmapStorage(ctx context.Context, log *logger.Logger, + netState netmap.State, client rawSource, wg *sync.WaitGroup, d time.Duration, +) netmap.Source { const netmapCacheSize = 10 - lruNetmapCache := newNetworkLRUCache(netmapCacheSize, func(ctx context.Context, key uint64) (*netmapSDK.NetMap, error) { - return v.GetNetMapByEpoch(ctx, key) - }, metrics.NewCacheMetrics("netmap")) + cache, err := simplelru.NewLRU[uint64, *atomic.Pointer[netmapSDK.NetMap]](netmapCacheSize, nil) + fatalOnErr(err) - return &lruNetmapSource{ - netState: s, - cache: lruNetmapCache, + src := &lruNetmapSource{ + netState: netState, + client: client, + cache: cache, + log: log, + metrics: metrics.NewCacheMetrics("netmap"), } + + wg.Add(1) + go func() { + defer wg.Done() + src.updateCandidates(ctx, d) + }() + + return src +} + +// updateCandidates routine to merge netmap in cache with candidates list. +func (s *lruNetmapSource) updateCandidates(ctx context.Context, d time.Duration) { + timer := time.NewTimer(d) + defer timer.Stop() + + for { + select { + case <-ctx.Done(): + return + case <-timer.C: + newCandidates, err := s.client.GetCandidates(ctx) + if err != nil { + s.log.Debug(ctx, logs.FailedToUpdateNetmapCandidates, zap.Error(err)) + timer.Reset(d) + break + } + if len(newCandidates) == 0 { + s.candidates.Store(&newCandidates) + timer.Reset(d) + break + } + slices.SortFunc(newCandidates, func(n1 netmapSDK.NodeInfo, n2 netmapSDK.NodeInfo) int { + return cmp.Compare(n1.Hash(), n2.Hash()) + }) + + // Check once state changed + v := s.candidates.Load() + if v == nil { + s.candidates.Store(&newCandidates) + s.mergeCacheWithCandidates(newCandidates) + timer.Reset(d) + break + } + ret := slices.CompareFunc(*v, newCandidates, func(n1 netmapSDK.NodeInfo, n2 netmapSDK.NodeInfo) int { + if !bytes.Equal(n1.PublicKey(), n2.PublicKey()) || + uint32(n1.Status()) != uint32(n2.Status()) || + slices.Compare(n1.ExternalAddresses(), n2.ExternalAddresses()) != 0 { + return 1 + } + var ne1 []string + n1.IterateNetworkEndpoints(func(s string) bool { + ne1 = append(ne1, s) + return false + }) + var ne2 []string + n2.IterateNetworkEndpoints(func(s string) bool { + ne2 = append(ne2, s) + return false + }) + return slices.Compare(ne1, ne2) + }) + if ret != 0 { + s.candidates.Store(&newCandidates) + s.mergeCacheWithCandidates(newCandidates) + } + timer.Reset(d) + } + } +} + +func (s *lruNetmapSource) mergeCacheWithCandidates(candidates []netmapSDK.NodeInfo) { + s.mtx.Lock() + tmp := s.cache.Values() + s.mtx.Unlock() + for _, pointer := range tmp { + nm := pointer.Load() + updates := getNetMapNodesToUpdate(nm, candidates) + if len(updates) > 0 { + nm = nm.Clone() + mergeNetmapWithCandidates(updates, nm) + pointer.Store(nm) + } + } +} + +// reads value by the key. +// +// updates the value from the network on cache miss. +// +// returned value should not be modified. +func (s *lruNetmapSource) get(ctx context.Context, key uint64) (*netmapSDK.NetMap, error) { + hit := false + startedAt := time.Now() + defer func() { + s.metrics.AddMethodDuration("Get", time.Since(startedAt), hit) + }() + + s.mtx.RLock() + val, ok := s.cache.Get(key) + s.mtx.RUnlock() + if ok { + hit = true + return val.Load(), nil + } + + s.mtx.Lock() + defer s.mtx.Unlock() + + val, ok = s.cache.Get(key) + if ok { + hit = true + return val.Load(), nil + } + + nm, err := s.client.GetNetMapByEpoch(ctx, key) + if err != nil { + return nil, err + } + v := s.candidates.Load() + if v != nil { + updates := getNetMapNodesToUpdate(nm, *v) + if len(updates) > 0 { + mergeNetmapWithCandidates(updates, nm) + } + } + + p := atomic.Pointer[netmapSDK.NetMap]{} + p.Store(nm) + s.cache.Add(key, &p) + + return nm, nil +} + +// mergeNetmapWithCandidates updates nodes state in the provided netmap with state in the list of candidates. +func mergeNetmapWithCandidates(updates []nodeToUpdate, nm *netmapSDK.NetMap) { + for _, v := range updates { + if v.status != netmapSDK.UnspecifiedState { + nm.Nodes()[v.netmapIndex].SetStatus(v.status) + } + if v.externalAddresses != nil { + nm.Nodes()[v.netmapIndex].SetExternalAddresses(v.externalAddresses...) + } + if v.endpoints != nil { + nm.Nodes()[v.netmapIndex].SetNetworkEndpoints(v.endpoints...) + } + } +} + +type nodeToUpdate struct { + netmapIndex int + status netmapSDK.NodeState + externalAddresses []string + endpoints []string +} + +// getNetMapNodesToUpdate checks for the changes between provided netmap and the list of candidates. +func getNetMapNodesToUpdate(nm *netmapSDK.NetMap, candidates []netmapSDK.NodeInfo) []nodeToUpdate { + var res []nodeToUpdate + for i := range nm.Nodes() { + for _, cnd := range candidates { + if bytes.Equal(nm.Nodes()[i].PublicKey(), cnd.PublicKey()) { + var tmp nodeToUpdate + var update bool + + if cnd.Status() != nm.Nodes()[i].Status() && + (cnd.Status() == netmapSDK.Online || cnd.Status() == netmapSDK.Maintenance) { + update = true + tmp.status = cnd.Status() + } + + externalAddresses := cnd.ExternalAddresses() + if externalAddresses != nil && + slices.Compare(externalAddresses, nm.Nodes()[i].ExternalAddresses()) != 0 { + update = true + tmp.externalAddresses = externalAddresses + } + + nodeEndpoints := make([]string, 0, nm.Nodes()[i].NumberOfNetworkEndpoints()) + nm.Nodes()[i].IterateNetworkEndpoints(func(s string) bool { + nodeEndpoints = append(nodeEndpoints, s) + return false + }) + candidateEndpoints := make([]string, 0, cnd.NumberOfNetworkEndpoints()) + cnd.IterateNetworkEndpoints(func(s string) bool { + candidateEndpoints = append(candidateEndpoints, s) + return false + }) + if slices.Compare(nodeEndpoints, candidateEndpoints) != 0 { + update = true + tmp.endpoints = candidateEndpoints + } + + if update { + tmp.netmapIndex = i + res = append(res, tmp) + } + + break + } + } + } + return res } func (s *lruNetmapSource) GetNetMap(ctx context.Context, diff uint64) (*netmapSDK.NetMap, error) { @@ -225,7 +399,7 @@ func (s *lruNetmapSource) GetNetMapByEpoch(ctx context.Context, epoch uint64) (* } func (s *lruNetmapSource) getNetMapByEpoch(ctx context.Context, epoch uint64) (*netmapSDK.NetMap, error) { - val, err := s.cache.get(ctx, epoch) + val, err := s.get(ctx, epoch) if err != nil { return nil, err } diff --git a/cmd/frostfs-node/cache_test.go b/cmd/frostfs-node/cache_test.go index b1601aa677..24286826f1 100644 --- a/cmd/frostfs-node/cache_test.go +++ b/cmd/frostfs-node/cache_test.go @@ -3,9 +3,11 @@ package main import ( "context" "errors" + "sync" "testing" "time" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/stretchr/testify/require" ) @@ -59,3 +61,75 @@ func testNetValueReader(_ context.Context, key string) (time.Time, error) { type noopCacheMetricts struct{} func (m *noopCacheMetricts) AddMethodDuration(method string, d time.Duration, hit bool) {} + +type rawSrc struct{} + +func (r *rawSrc) GetCandidates(_ context.Context) ([]netmapSDK.NodeInfo, error) { + node0 := netmapSDK.NodeInfo{} + node0.SetPublicKey([]byte{byte(1)}) + node0.SetStatus(netmapSDK.Online) + node0.SetExternalAddresses("1", "0") + node0.SetNetworkEndpoints("1", "0") + + node1 := netmapSDK.NodeInfo{} + node1.SetPublicKey([]byte{byte(1)}) + node1.SetStatus(netmapSDK.Online) + node1.SetExternalAddresses("1", "0") + node1.SetNetworkEndpoints("1", "0") + + return []netmapSDK.NodeInfo{node0, node1}, nil +} + +func (r *rawSrc) GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmapSDK.NetMap, error) { + nm := netmapSDK.NetMap{} + nm.SetEpoch(1) + + node0 := netmapSDK.NodeInfo{} + node0.SetPublicKey([]byte{byte(1)}) + node0.SetStatus(netmapSDK.Maintenance) + node0.SetExternalAddresses("0") + node0.SetNetworkEndpoints("0") + + node1 := netmapSDK.NodeInfo{} + node1.SetPublicKey([]byte{byte(1)}) + node1.SetStatus(netmapSDK.Maintenance) + node1.SetExternalAddresses("0") + node1.SetNetworkEndpoints("0") + + nm.SetNodes([]netmapSDK.NodeInfo{node0, node1}) + + return &nm, nil +} + +type st struct{} + +func (s *st) CurrentEpoch() uint64 { + return 1 +} + +func TestNetmapStorage(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + wg := sync.WaitGroup{} + cache := newCachedNetmapStorage(ctx, nil, &st{}, &rawSrc{}, &wg, time.Millisecond*50) + + nm, err := cache.GetNetMapByEpoch(ctx, 1) + require.NoError(t, err) + require.True(t, nm.Nodes()[0].Status() == netmapSDK.Maintenance) + require.True(t, len(nm.Nodes()[0].ExternalAddresses()) == 1) + require.True(t, nm.Nodes()[0].NumberOfNetworkEndpoints() == 1) + + require.Eventually(t, func() bool { + nm, err := cache.GetNetMapByEpoch(ctx, 1) + require.NoError(t, err) + for _, node := range nm.Nodes() { + if !(node.Status() == netmapSDK.Online && len(node.ExternalAddresses()) == 2 && + node.NumberOfNetworkEndpoints() == 2) { + return false + } + } + return true + }, time.Second*5, time.Millisecond*10) + + cancel() + wg.Wait() +} diff --git a/cmd/frostfs-node/config/morph/config.go b/cmd/frostfs-node/config/morph/config.go index d089870eae..a9f774d18a 100644 --- a/cmd/frostfs-node/config/morph/config.go +++ b/cmd/frostfs-node/config/morph/config.go @@ -33,6 +33,9 @@ const ( // ContainerCacheSizeDefault represents the default size for the container cache. ContainerCacheSizeDefault = 100 + + // PollCandidatesTimeoutDefault is a default poll timeout for netmap candidates. + PollCandidatesTimeoutDefault = 20 * time.Second ) var errNoMorphEndpoints = errors.New("no morph chain RPC endpoints, see `morph.rpc_endpoint` section") @@ -154,3 +157,17 @@ func FrostfsIDCacheSize(c *config.Config) uint32 { } return config.Uint32Safe(c.Sub(subsection), "frostfsid_cache_size") } + +// NetmapCandidatesPollInterval returns the value of "netmap.candidates.poll_interval" config parameter +// from "morph" section. +// +// Returns PollCandidatesTimeoutDefault if the value is not positive duration. +func NetmapCandidatesPollInterval(c *config.Config) time.Duration { + v := config.DurationSafe(c.Sub(subsection). + Sub("netmap").Sub("candidates"), "poll_interval") + if v > 0 { + return v + } + + return PollCandidatesTimeoutDefault +} diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index 657e22389c..d3c0f7b81c 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -60,10 +60,11 @@ func (c *cfg) initMorphComponents(ctx context.Context) { } if c.cfgMorph.cacheTTL < 0 { - netmapSource = wrap + netmapSource = newRawNetmapStorage(wrap) } else { // use RPC node as source of netmap (with caching) - netmapSource = newCachedNetmapStorage(c.cfgNetmap.state, wrap) + netmapSource = newCachedNetmapStorage(ctx, c.log, c.cfgNetmap.state, wrap, &c.wg, + morphconfig.NetmapCandidatesPollInterval(c.appCfg)) } c.netMapSource = netmapSource diff --git a/cmd/frostfs-node/netmap_source.go b/cmd/frostfs-node/netmap_source.go new file mode 100644 index 0000000000..e6be9cdf51 --- /dev/null +++ b/cmd/frostfs-node/netmap_source.go @@ -0,0 +1,55 @@ +package main + +import ( + "context" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + netmapClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" +) + +type rawNetmapSource struct { + client *netmapClient.Client +} + +func newRawNetmapStorage(client *netmapClient.Client) netmap.Source { + return &rawNetmapSource{ + client: client, + } +} + +func (s *rawNetmapSource) GetNetMap(ctx context.Context, diff uint64) (*netmapSDK.NetMap, error) { + nm, err := s.client.GetNetMap(ctx, diff) + if err != nil { + return nil, err + } + candidates, err := s.client.GetCandidates(ctx) + if err != nil { + return nil, err + } + updates := getNetMapNodesToUpdate(nm, candidates) + if len(updates) > 0 { + mergeNetmapWithCandidates(updates, nm) + } + return nm, nil +} + +func (s *rawNetmapSource) GetNetMapByEpoch(ctx context.Context, epoch uint64) (*netmapSDK.NetMap, error) { + nm, err := s.client.GetNetMapByEpoch(ctx, epoch) + if err != nil { + return nil, err + } + candidates, err := s.client.GetCandidates(ctx) + if err != nil { + return nil, err + } + updates := getNetMapNodesToUpdate(nm, candidates) + if len(updates) > 0 { + mergeNetmapWithCandidates(updates, nm) + } + return nm, nil +} + +func (s *rawNetmapSource) Epoch(ctx context.Context) (uint64, error) { + return s.client.Epoch(ctx) +} diff --git a/config/example/node.yaml b/config/example/node.yaml index a448ba7ce6..0b6c7b12c0 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -95,6 +95,9 @@ morph: - address: wss://rpc2.morph.frostfs.info:40341/ws priority: 2 ape_chain_cache_size: 100000 + netmap: + candidates: + poll_interval: 20s apiclient: dial_timeout: 15s # timeout for FrostFS API client connection diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index b5c8aadfed..5fe011ece2 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -148,15 +148,19 @@ morph: - address: wss://rpc2.morph.frostfs.info:40341/ws priority: 2 switch_interval: 2m + netmap: + candidates: + poll_interval: 20s ``` -| Parameter | Type | Default value | Description | -| ---------------------- | --------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `dial_timeout` | `duration` | `5s` | Timeout for dialing connections to N3 RPCs. | -| `cache_ttl` | `duration` | Morph block time | Sidechain cache TTL value (min interval between similar calls).
Negative value disables caching.
Cached entities: containers, container lists, eACL tables. | -| `rpc_endpoint` | list of [endpoint descriptions](#rpc_endpoint-subsection) | | Array of endpoint descriptions. | -| `switch_interval` | `duration` | `2m` | Time interval between the attempts to connect to the highest priority RPC node if the connection is not established yet. | -| `ape_chain_cache_size` | `int` | `10000` | Size of the morph cache for APE chains. | +| Parameter | Type | Default value | Description | +|-----------------------------------|-----------------------------------------------------------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `dial_timeout` | `duration` | `5s` | Timeout for dialing connections to N3 RPCs. | +| `cache_ttl` | `duration` | Morph block time | Sidechain cache TTL value (min interval between similar calls).
Negative value disables caching.
Cached entities: containers, container lists, eACL tables. | +| `rpc_endpoint` | list of [endpoint descriptions](#rpc_endpoint-subsection) | | Array of endpoint descriptions. | +| `switch_interval` | `duration` | `2m` | Time interval between the attempts to connect to the highest priority RPC node if the connection is not established yet. | +| `ape_chain_cache_size` | `int` | `10000` | Size of the morph cache for APE chains. | +| `netmap.candidates.poll_interval` | `duration` | `20s` | Timeout to set up frequency of merge candidates to netmap with netmap in local cache. | ## `rpc_endpoint` subsection | Parameter | Type | Default value | Description | diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 5b42b25bab..3a3ceb1501 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -515,4 +515,5 @@ const ( FailedToGetNetmapToAdjustIOTag = "failed to get netmap to adjust IO tag" FailedToValidateIncomingIOTag = "failed to validate incoming IO tag, replaced with `client`" WriteCacheFailedToAcquireRPSQuota = "writecache failed to acquire RPS quota to flush object" + FailedToUpdateNetmapCandidates = "update netmap candidates failed" ) From 272128e61fd20c53aa0a3b02da8bdc77f7779e26 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 4 Apr 2025 13:32:11 +0300 Subject: [PATCH 1324/1413] Revert "[#652] adm: Group independent stages in batches" This reverts commit d00c606feed8ad776fe6df65b601b81790e7dfbe. There are internal dependencies inside the last stage: first, we register NNS root, only then register add records. Revert for now, will revert back after more testing. Change-Id: I760632b5628caf04849d4a64c714cf286051f357 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-adm/internal/modules/morph/helper/n3client.go | 4 +--- .../internal/modules/morph/initialize/initialize.go | 8 +------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go index d6ca012ced..3f3a66cb68 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/n3client.go @@ -40,8 +40,6 @@ type ClientContext struct { CommitteeAct *actor.Actor // committee actor with the Global witness scope ReadOnlyInvoker *invoker.Invoker // R/O contract invoker, does not contain any signer SentTxs []HashVUBPair - - AwaitDisabled bool } func NewRemoteClient(v *viper.Viper) (Client, error) { @@ -122,7 +120,7 @@ func (c *ClientContext) SendTx(tx *transaction.Transaction, cmd *cobra.Command, } func (c *ClientContext) AwaitTx(cmd *cobra.Command) error { - if len(c.SentTxs) == 0 || c.AwaitDisabled { + if len(c.SentTxs) == 0 { return nil } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go index 4d39dc6622..cdaf7d3bca 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize.go @@ -39,7 +39,6 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { return err } - initCtx.AwaitDisabled = true cmd.Println("Stage 4.1: Transfer GAS to proxy contract.") if err := transferGASToProxy(initCtx); err != nil { return err @@ -56,10 +55,5 @@ func initializeSideChainCmd(cmd *cobra.Command, _ []string) error { } cmd.Println("Stage 7: set addresses in NNS.") - if err := setNNS(initCtx); err != nil { - return err - } - - initCtx.AwaitDisabled = false - return initCtx.AwaitTx() + return setNNS(initCtx) } From 2938498b52369bc3abaac3ab1f8e790bba414e8e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 4 Apr 2025 15:23:41 +0300 Subject: [PATCH 1325/1413] [#1689] adm: Fix NNS root availability check After https://git.frostfs.info/TrueCloudLab/frostfs-contract/pulls/117 we allow checking for root domain availability directly. Before this commit, NNSRootRegistered() has always returned true, so the actual root registration happened as a side-effect of the following code, because NNS registers all parent domains, if they are missing. Change-Id: Icf98f130e77d31b4af7b69697989183c1c8f6a56 Signed-off-by: Evgenii Stratonikov --- .../internal/modules/morph/helper/initialize_ctx.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go index 8e5615baa6..27052697f1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go @@ -21,6 +21,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/actor" "github.com/nspcc-dev/neo-go/pkg/rpcclient/management" + "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/context" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" @@ -28,7 +29,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" - "github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -524,12 +524,8 @@ func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.U } func (c *InitializeContext) NNSRootRegistered(nnsHash util.Uint160, zone string) (bool, error) { - res, err := c.CommitteeAct.Call(nnsHash, "isAvailable", "name."+zone) - if err != nil { - return false, err - } - - return res.State == vmstate.Halt.String(), nil + avail, err := unwrap.Bool(c.CommitteeAct.Call(nnsHash, "isAvailable", zone)) + return !avail, err } func (c *InitializeContext) IsUpdated(ctrHash util.Uint160, cs *ContractState) bool { From 5350632e01f2b01f8068dbfec2b9829ae8721519 Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Fri, 4 Apr 2025 12:48:22 +0300 Subject: [PATCH 1326/1413] [#1705] engine/test: Increase evacuation timeout This test was flaky in CI probably because of runner load fluctuations. Let's increase the timeout and see if the flakiness goes away. (close #1705) Change-Id: I76f96e3d6f4adb3d5de0e27b8ee6b47685236277 Signed-off-by: Vitaliy Potyarkin --- pkg/local_object_storage/engine/evacuate_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index bd5222b788..359e49481c 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -208,7 +208,7 @@ func testWaitForEvacuationCompleted(t *testing.T, e *StorageEngine) *EvacuationS st, err = e.GetEvacuationState(context.Background()) require.NoError(t, err) return st.ProcessingStatus() == EvacuateProcessStateCompleted - }, 3*time.Second, 10*time.Millisecond) + }, 6*time.Second, 10*time.Millisecond) return st } From fbc623f34e5d50d3ca16f1b63ba0ac5fbf011a0b Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 2 Apr 2025 10:47:42 +0300 Subject: [PATCH 1327/1413] [#1701] go.mod: Bump `policy-engine` version Change-Id: I7aa359bf235034d6459275d366a276d9930fa227 Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 23be9c8224..9ed5e41876 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945 git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250402100642-acd94d200f88 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/VictoriaMetrics/easyproto v0.1.4 diff --git a/go.sum b/go.sum index e5d476ffeb..9727d8786d 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/96 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972/go.mod h1:2hM42MBrlhvN6XToaW6OWNk5ZLcu1FhaukGgxtfpDDI= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07 h1:gPaqGsk6gSWQyNVjaStydfUz6Z/loHc9XyvGrJ5qSPY= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b h1:M50kdfrf/h8c3cz0bJ2AEUcbXvAlPFVC1Wp1WkfZ/8E= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20240822104152-a3bc3099bd5b/go.mod h1:GZTk55RI4dKzsK6BCn5h2xxE28UHNfgoq/NJxW/LQ6A= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250402100642-acd94d200f88 h1:V0a7ia84ZpSM2YxpJq1SKLQfeYmsqFWqcxwweBHJIzc= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250402100642-acd94d200f88/go.mod h1:GZTk55RI4dKzsK6BCn5h2xxE28UHNfgoq/NJxW/LQ6A= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= From 979d4bb2aec9ce74a45b83f00defa532e5d764db Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Wed, 2 Apr 2025 11:15:40 +0300 Subject: [PATCH 1328/1413] [#1701] tree: Form `$Tree:ID` resource property for APE * Make `verifyClient`, `checkAPE` receive `treeID` from request body; * Make `newAPERequest` set `$Tree:ID` property * Add unit-test to check if a rule for `$Tree:ID` works Close #1701 Change-Id: I834fed366e8adfd4b5c07bf50aac09af6239991b Signed-off-by: Airat Arifullin --- pkg/services/tree/ape.go | 12 +++++--- pkg/services/tree/ape_test.go | 43 +++++++++++++++++++++++++++-- pkg/services/tree/service.go | 12 ++++---- pkg/services/tree/signature.go | 4 +-- pkg/services/tree/signature_test.go | 36 ++++++++++++------------ 5 files changed, 76 insertions(+), 31 deletions(-) diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index c4b03cbe6b..58757ff6d8 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -22,7 +22,7 @@ import ( ) func (s *Service) newAPERequest(ctx context.Context, namespace string, - cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey, + cid cid.ID, treeID string, operation acl.Op, role acl.Role, publicKey *keys.PublicKey, ) (aperequest.Request, error) { schemaMethod, err := converter.SchemaMethodFromACLOperation(operation) if err != nil { @@ -53,15 +53,19 @@ func (s *Service) newAPERequest(ctx context.Context, namespace string, resourceName = fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainerObjects, namespace, cid.EncodeToString()) } + resProps := map[string]string{ + nativeschema.ProperyKeyTreeID: treeID, + } + return aperequest.NewRequest( schemaMethod, - aperequest.NewResource(resourceName, make(map[string]string)), + aperequest.NewResource(resourceName, resProps), reqProps, ), nil } func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, - container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey, + container *core.Container, cid cid.ID, treeID string, operation acl.Op, role acl.Role, publicKey *keys.PublicKey, ) error { namespace := "" cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns") @@ -69,7 +73,7 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token, namespace = cntNamespace } - request, err := s.newAPERequest(ctx, namespace, cid, operation, role, publicKey) + request, err := s.newAPERequest(ctx, namespace, cid, treeID, operation, role, publicKey) if err != nil { return fmt.Errorf("failed to create ape request: %w", err) } diff --git a/pkg/services/tree/ape_test.go b/pkg/services/tree/ape_test.go index 0afc7660a5..7b209fd47d 100644 --- a/pkg/services/tree/ape_test.go +++ b/pkg/services/tree/ape_test.go @@ -107,6 +107,45 @@ func TestCheckAPE(t *testing.T) { cid := cid.ID{} _ = cid.DecodeString(containerID) + t.Run("treeID rule", func(t *testing.T) { + los := inmemory.NewInmemoryLocalStorage() + mcs := inmemory.NewInmemoryMorphRuleChainStorage() + fid := newFrostfsIDProviderMock(t) + s := Service{ + cfg: cfg{ + frostfsidSubjectProvider: fid, + }, + apeChecker: checkercore.New(los, mcs, fid, &stMock{}), + } + + mcs.AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(containerID), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.QuotaLimitReached, + Actions: chain.Actions{Names: []string{nativeschema.MethodGetObject}}, + Resources: chain.Resources{ + Names: []string{fmt.Sprintf(nativeschema.ResourceFormatRootContainerObjects, containerID)}, + }, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Kind: chain.KindResource, + Key: nativeschema.ProperyKeyTreeID, + Value: versionTreeID, + }, + }, + }, + }, + MatchType: chain.MatchTypeFirstMatch, + }) + + err := s.checkAPE(context.Background(), nil, rootCnr, cid, versionTreeID, acl.OpObjectGet, acl.RoleOwner, senderPrivateKey.PublicKey()) + + var chErr *checkercore.ChainRouterError + require.ErrorAs(t, err, &chErr) + require.Equal(t, chain.QuotaLimitReached, chErr.Status()) + }) + t.Run("put non-tombstone rule won't affect tree remove", func(t *testing.T) { los := inmemory.NewInmemoryLocalStorage() mcs := inmemory.NewInmemoryMorphRuleChainStorage() @@ -152,7 +191,7 @@ func TestCheckAPE(t *testing.T) { MatchType: chain.MatchTypeFirstMatch, }) - err := s.checkAPE(context.Background(), nil, rootCnr, cid, acl.OpObjectDelete, acl.RoleOwner, senderPrivateKey.PublicKey()) + err := s.checkAPE(context.Background(), nil, rootCnr, cid, versionTreeID, acl.OpObjectDelete, acl.RoleOwner, senderPrivateKey.PublicKey()) require.NoError(t, err) }) @@ -201,7 +240,7 @@ func TestCheckAPE(t *testing.T) { MatchType: chain.MatchTypeFirstMatch, }) - err := s.checkAPE(context.Background(), nil, rootCnr, cid, acl.OpObjectPut, acl.RoleOwner, senderPrivateKey.PublicKey()) + err := s.checkAPE(context.Background(), nil, rootCnr, cid, versionTreeID, acl.OpObjectPut, acl.RoleOwner, senderPrivateKey.PublicKey()) require.NoError(t, err) }) } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index b9bb96bab9..85bb03a28f 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -117,7 +117,7 @@ func (s *Service) Add(ctx context.Context, req *AddRequest) (*AddResponse, error return nil, err } - err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut) + err := s.verifyClient(ctx, req, cid, req.GetBody().GetTreeId(), b.GetBearerToken(), acl.OpObjectPut) if err != nil { return nil, err } @@ -161,7 +161,7 @@ func (s *Service) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByP return nil, err } - err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut) + err := s.verifyClient(ctx, req, cid, req.GetBody().GetTreeId(), b.GetBearerToken(), acl.OpObjectPut) if err != nil { return nil, err } @@ -217,7 +217,7 @@ func (s *Service) Remove(ctx context.Context, req *RemoveRequest) (*RemoveRespon return nil, err } - err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectDelete) + err := s.verifyClient(ctx, req, cid, req.GetBody().GetTreeId(), b.GetBearerToken(), acl.OpObjectDelete) if err != nil { return nil, err } @@ -262,7 +262,7 @@ func (s *Service) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, er return nil, err } - err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut) + err := s.verifyClient(ctx, req, cid, req.GetBody().GetTreeId(), b.GetBearerToken(), acl.OpObjectPut) if err != nil { return nil, err } @@ -306,7 +306,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) return nil, err } - err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectGet) + err := s.verifyClient(ctx, req, cid, req.GetBody().GetTreeId(), b.GetBearerToken(), acl.OpObjectGet) if err != nil { return nil, err } @@ -377,7 +377,7 @@ func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeS return err } - err := s.verifyClient(srv.Context(), req, cid, b.GetBearerToken(), acl.OpObjectGet) + err := s.verifyClient(srv.Context(), req, cid, req.GetBody().GetTreeId(), b.GetBearerToken(), acl.OpObjectGet) if err != nil { return err } diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index d15438e81b..89056056de 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -38,7 +38,7 @@ var ( // Operation must be one of: // - 1. ObjectPut; // - 2. ObjectGet. -func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, rawBearer []byte, op acl.Op) error { +func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, treeID string, rawBearer []byte, op acl.Op) error { err := verifyMessage(req) if err != nil { return err @@ -64,7 +64,7 @@ func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, return fmt.Errorf("can't get request role: %w", err) } - if err = s.checkAPE(ctx, bt, cnr, cid, op, role, pubKey); err != nil { + if err = s.checkAPE(ctx, bt, cnr, cid, treeID, op, role, pubKey); err != nil { return apeErr(err) } return nil diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 97f8a727a6..947de8e589 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -31,6 +31,8 @@ import ( "github.com/stretchr/testify/require" ) +const versionTreeID = "version" + type dummyNetmapSource struct { netmap.Source } @@ -168,26 +170,26 @@ func TestMessageSign(t *testing.T) { cnr.Value.SetBasicACL(acl.PublicRW) t.Run("missing signature, no panic", func(t *testing.T) { - require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op)) + require.Error(t, s.verifyClient(context.Background(), req, cid2, versionTreeID, nil, op)) }) require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) - require.NoError(t, s.verifyClient(context.Background(), req, cid1, nil, op)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, nil, op)) t.Run("invalid CID", func(t *testing.T) { - require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op)) + require.Error(t, s.verifyClient(context.Background(), req, cid2, versionTreeID, nil, op)) }) cnr.Value.SetBasicACL(acl.Private) t.Run("extension disabled", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op)) + require.Error(t, s.verifyClient(context.Background(), req, cid2, versionTreeID, nil, op)) }) t.Run("invalid key", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, nil, op)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, nil, op)) }) t.Run("bearer", func(t *testing.T) { @@ -200,7 +202,7 @@ func TestMessageSign(t *testing.T) { t.Run("invalid bearer", func(t *testing.T) { req.Body.BearerToken = []byte{0xFF} require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) t.Run("invalid bearer CID", func(t *testing.T) { @@ -209,7 +211,7 @@ func TestMessageSign(t *testing.T) { req.Body.BearerToken = bt.Marshal() require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) t.Run("invalid bearer owner", func(t *testing.T) { bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey()) @@ -217,7 +219,7 @@ func TestMessageSign(t *testing.T) { req.Body.BearerToken = bt.Marshal() require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) t.Run("invalid bearer signature", func(t *testing.T) { bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey()) @@ -229,7 +231,7 @@ func TestMessageSign(t *testing.T) { req.Body.BearerToken = bv2.StableMarshal(nil) require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) t.Run("impersonate", func(t *testing.T) { @@ -241,8 +243,8 @@ func TestMessageSign(t *testing.T) { req.Body.BearerToken = bt.Marshal() require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey()) @@ -252,18 +254,18 @@ func TestMessageSign(t *testing.T) { t.Run("put and get", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) - require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) t.Run("only get", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[2].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) t.Run("none", func(t *testing.T) { require.NoError(t, SignMessage(req, &privs[3].PrivateKey)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) }) } From 52367dc9b259b6044f0fc7fda09e4339b7170f3d Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 4 Apr 2025 20:07:23 +0300 Subject: [PATCH 1329/1413] [#1689] go.mod: Update sdk-go Change-Id: I72052fe11e66e4c77f4aef6cb2c0f038aa7b0d1f Signed-off-by: Evgenii Stratonikov --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9ed5e41876..5ed4a90be3 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.5.2 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945 + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250404152210-6458c11e833d git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250402100642-acd94d200f88 diff --git a/go.sum b/go.sum index 9727d8786d..38aba9bdee 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47 h1:O2c3VOlaGZ862hf2ZPLBMdTG6vGJzhIgDvFEFGfntzU= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945 h1:zM2l316J55h9p30snl6vHBI/h0xmnuqZjnxIjRDtJZw= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250326101739-4d36a49d3945/go.mod h1:aQpPWfG8oyfJ2X+FenPTJpSRWZjwcP5/RAtkW+/VEX8= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250404152210-6458c11e833d h1:ZLKDupw362Ciing7kdIZhDYGMyo2QZyJ6sS/8X9QWJ0= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250404152210-6458c11e833d/go.mod h1:2PWt5GwJTnhjHp+mankcfCeAJBMn7puxPm+RS+lliVk= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= From 3d771aa21c8fb961c53816566db77b3b0274dc40 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 5 Apr 2025 08:56:22 +0300 Subject: [PATCH 1330/1413] [#1689] morph: Remove `frostfsError` type It has no custom methods defined, only adds `frostfs error: ` prefix to the error message. The utility of this prefix is debatable, failed invocations already have `invocation failed` prefix. Change-Id: If25ebb3679497f3f10acde43b596c81d52351907 Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/client.go | 18 ++---------------- pkg/morph/client/notary.go | 8 +++----- pkg/morph/client/util.go | 2 +- pkg/morph/client/waiter.go | 2 +- 4 files changed, 7 insertions(+), 23 deletions(-) diff --git a/pkg/morph/client/client.go b/pkg/morph/client/client.go index 1c12130b74..aab058d277 100644 --- a/pkg/morph/client/client.go +++ b/pkg/morph/client/client.go @@ -151,20 +151,6 @@ func (e *notHaltStateError) Error() string { ) } -// implementation of error interface for FrostFS-specific errors. -type frostfsError struct { - err error -} - -func (e frostfsError) Error() string { - return fmt.Sprintf("frostfs error: %v", e.err) -} - -// wraps FrostFS-specific error into frostfsError. Arg must not be nil. -func wrapFrostFSError(err error) error { - return frostfsError{err} -} - // Invoke invokes contract method by sending transaction into blockchain. // Returns valid until block value. // Supported args types: int64, string, util.Uint160, []byte and bool. @@ -228,7 +214,7 @@ func (c *Client) TestInvokeIterator(cb func(stackitem.Item) error, batchSize int if err != nil { return err } else if val.State != HaltState { - return wrapFrostFSError(¬HaltStateError{state: val.State, exception: val.FaultException}) + return ¬HaltStateError{state: val.State, exception: val.FaultException} } arr, sid, r, err := unwrap.ArrayAndSessionIterator(val, err) @@ -292,7 +278,7 @@ func (c *Client) TestInvoke(contract util.Uint160, method string, args ...any) ( } if val.State != HaltState { - return nil, wrapFrostFSError(¬HaltStateError{state: val.State, exception: val.FaultException}) + return nil, ¬HaltStateError{state: val.State, exception: val.FaultException} } success = true diff --git a/pkg/morph/client/notary.go b/pkg/morph/client/notary.go index 4e20a3639b..4487026132 100644 --- a/pkg/morph/client/notary.go +++ b/pkg/morph/client/notary.go @@ -461,7 +461,7 @@ func (c *Client) notaryInvoke(ctx context.Context, committee, invokedByAlpha boo mainH, fbH, untilActual, err := nAct.Notarize(nAct.MakeTunedCall(contract, method, nil, func(r *result.Invoke, t *transaction.Transaction) error { if r.State != vmstate.Halt.String() { - return wrapFrostFSError(¬HaltStateError{state: r.State, exception: r.FaultException}) + return ¬HaltStateError{state: r.State, exception: r.FaultException} } t.ValidUntilBlock = until @@ -608,8 +608,7 @@ func (c *Client) notaryMultisigAccount(ir []*keys.PublicKey, committee, invokedB multisigAccount = wallet.NewAccountFromPrivateKey(c.acc.PrivateKey()) err := multisigAccount.ConvertMultisig(m, ir) if err != nil { - // wrap error as FrostFS-specific since the call is not related to any client - return nil, wrapFrostFSError(fmt.Errorf("convert account to inner ring multisig wallet: %w", err)) + return nil, fmt.Errorf("convert account to inner ring multisig wallet: %w", err) } } else { // alphabet multisig redeem script is @@ -617,8 +616,7 @@ func (c *Client) notaryMultisigAccount(ir []*keys.PublicKey, committee, invokedB // inner ring multiaddress witness multisigAccount, err = notary.FakeMultisigAccount(m, ir) if err != nil { - // wrap error as FrostFS-specific since the call is not related to any client - return nil, wrapFrostFSError(fmt.Errorf("make inner ring multisig wallet: %w", err)) + return nil, fmt.Errorf("make inner ring multisig wallet: %w", err) } } diff --git a/pkg/morph/client/util.go b/pkg/morph/client/util.go index f68d39beba..f7b6705a8c 100644 --- a/pkg/morph/client/util.go +++ b/pkg/morph/client/util.go @@ -98,7 +98,7 @@ func StringFromStackItem(param stackitem.Item) (string, error) { func addFeeCheckerModifier(add int64) func(r *result.Invoke, t *transaction.Transaction) error { return func(r *result.Invoke, t *transaction.Transaction) error { if r.State != HaltState { - return wrapFrostFSError(¬HaltStateError{state: r.State, exception: r.FaultException}) + return ¬HaltStateError{state: r.State, exception: r.FaultException} } t.SystemFee += add diff --git a/pkg/morph/client/waiter.go b/pkg/morph/client/waiter.go index 5b9d2cbe0f..87fcf84b88 100644 --- a/pkg/morph/client/waiter.go +++ b/pkg/morph/client/waiter.go @@ -47,5 +47,5 @@ func (c *Client) WaitTxHalt(ctx context.Context, vub uint32, h util.Uint256) err if res.VMState.HasFlag(vmstate.Halt) { return nil } - return wrapFrostFSError(¬HaltStateError{state: res.VMState.String(), exception: res.FaultException}) + return ¬HaltStateError{state: res.VMState.String(), exception: res.FaultException} } From d933609084a23595e36bf48e5c226664d315bc23 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 5 Apr 2025 09:07:03 +0300 Subject: [PATCH 1331/1413] [#1689] client/netmap: Refactor Client.config() There are problems with that code: - explicit casts, - `ErrConfigNotFound` which is not a part of a public API, - hand-rolled assertions, even though neo-go already has everything we need. So, remove the error, use `stackitem/Item.Try*()` methods for conversions. Note, that readUint64Config() returns an error if the parameter is missing. This is likely an error, but this behaviour is preserved in this PR: `TryInteger()` returns error when applied to `Null`. By contract, `TryBool()` returns false for `Null`, so this PR introduces no functional changes. Refs https://github.com/nspcc-dev/neo-go/blob/82c7a50b8a308698e1440a716d34232094f9f55f/pkg/vm/stackitem/item.go#L418 Change-Id: I445d28a7c6b5abb9a2bb97b57c0cc42d617e16f7 Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/netmap/config.go | 46 +++++++------------------------ 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index fcdb70e3f6..78063b8578 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -2,7 +2,6 @@ package netmap import ( "context" - "errors" "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" @@ -106,29 +105,27 @@ func (c *Client) MaintenanceModeAllowed(ctx context.Context) (bool, error) { } func (c *Client) readUInt64Config(ctx context.Context, key string) (uint64, error) { - v, err := c.config(ctx, []byte(key), IntegerAssert) + v, err := c.config(ctx, []byte(key)) if err != nil { return 0, fmt.Errorf("read netconfig value '%s': %w", key, err) } - // IntegerAssert is guaranteed to return int64 if the error is nil. - return uint64(v.(int64)), nil + bi, err := v.TryInteger() + if err != nil { + return 0, err + } + return bi.Uint64(), nil } // reads boolean value by the given key from the FrostFS network configuration // stored in the Sidechain. Returns false if key is not presented. func (c *Client) readBoolConfig(ctx context.Context, key string) (bool, error) { - v, err := c.config(ctx, []byte(key), BoolAssert) + v, err := c.config(ctx, []byte(key)) if err != nil { - if errors.Is(err, ErrConfigNotFound) { - return false, nil - } - return false, fmt.Errorf("read netconfig value '%s': %w", key, err) } - // BoolAssert is guaranteed to return bool if the error is nil. - return v.(bool), nil + return v.TryBool() } // SetConfigPrm groups parameters of SetConfig operation. @@ -277,15 +274,11 @@ func bytesToBool(val []byte) bool { return false } -// ErrConfigNotFound is returned when the requested key was not found -// in the network config (returned value is `Null`). -var ErrConfigNotFound = errors.New("config value not found") - // config performs the test invoke of get config value // method of FrostFS Netmap contract. // // Returns ErrConfigNotFound if config key is not found in the contract. -func (c *Client) config(ctx context.Context, key []byte, assert func(stackitem.Item) (any, error)) (any, error) { +func (c *Client) config(ctx context.Context, key []byte) (stackitem.Item, error) { prm := client.TestInvokePrm{} prm.SetMethod(configMethod) prm.SetArgs(key) @@ -301,26 +294,7 @@ func (c *Client) config(ctx context.Context, key []byte, assert func(stackitem.I configMethod, ln) } - if _, ok := items[0].(stackitem.Null); ok { - return nil, ErrConfigNotFound - } - - return assert(items[0]) -} - -// IntegerAssert converts stack item to int64. -func IntegerAssert(item stackitem.Item) (any, error) { - return client.IntFromStackItem(item) -} - -// StringAssert converts stack item to string. -func StringAssert(item stackitem.Item) (any, error) { - return client.StringFromStackItem(item) -} - -// BoolAssert converts stack item to bool. -func BoolAssert(item stackitem.Item) (any, error) { - return client.BoolFromStackItem(item) + return items[0], nil } // iterateRecords iterates over all config records and passes them to f. From c4f941a5f5217024ed8ba3cebda22d3518bd18f7 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Sat, 5 Apr 2025 09:16:25 +0300 Subject: [PATCH 1332/1413] [#1689] client/netmap: Remove useless error-handling No functional changes. Change-Id: I3a53c992c3ce5e8c6db252abb09aa40626142a97 Signed-off-by: Evgenii Stratonikov --- pkg/morph/client/netmap/config.go | 42 +++++-------------------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/pkg/morph/client/netmap/config.go b/pkg/morph/client/netmap/config.go index 78063b8578..3f6aed506d 100644 --- a/pkg/morph/client/netmap/config.go +++ b/pkg/morph/client/netmap/config.go @@ -25,44 +25,24 @@ const ( // MaxObjectSize receives max object size configuration // value through the Netmap contract call. func (c *Client) MaxObjectSize(ctx context.Context) (uint64, error) { - objectSize, err := c.readUInt64Config(ctx, MaxObjectSizeConfig) - if err != nil { - return 0, err - } - - return objectSize, nil + return c.readUInt64Config(ctx, MaxObjectSizeConfig) } // EpochDuration returns number of sidechain blocks per one FrostFS epoch. func (c *Client) EpochDuration(ctx context.Context) (uint64, error) { - epochDuration, err := c.readUInt64Config(ctx, EpochDurationConfig) - if err != nil { - return 0, err - } - - return epochDuration, nil + return c.readUInt64Config(ctx, EpochDurationConfig) } // ContainerFee returns fee paid by container owner to each alphabet node // for container registration. func (c *Client) ContainerFee(ctx context.Context) (uint64, error) { - fee, err := c.readUInt64Config(ctx, ContainerFeeConfig) - if err != nil { - return 0, err - } - - return fee, nil + return c.readUInt64Config(ctx, ContainerFeeConfig) } // ContainerAliasFee returns additional fee paid by container owner to each // alphabet node for container nice name registration. func (c *Client) ContainerAliasFee(ctx context.Context) (uint64, error) { - fee, err := c.readUInt64Config(ctx, ContainerAliasFeeConfig) - if err != nil { - return 0, err - } - - return fee, nil + return c.readUInt64Config(ctx, ContainerAliasFeeConfig) } // HomomorphicHashDisabled returns global configuration value of homomorphic hashing @@ -76,23 +56,13 @@ func (c *Client) HomomorphicHashDisabled(ctx context.Context) (bool, error) { // InnerRingCandidateFee returns global configuration value of fee paid by // node to be in inner ring candidates list. func (c *Client) InnerRingCandidateFee(ctx context.Context) (uint64, error) { - fee, err := c.readUInt64Config(ctx, IrCandidateFeeConfig) - if err != nil { - return 0, err - } - - return fee, nil + return c.readUInt64Config(ctx, IrCandidateFeeConfig) } // WithdrawFee returns global configuration value of fee paid by user to // withdraw assets from FrostFS contract. func (c *Client) WithdrawFee(ctx context.Context) (uint64, error) { - fee, err := c.readUInt64Config(ctx, WithdrawFeeConfig) - if err != nil { - return 0, err - } - - return fee, nil + return c.readUInt64Config(ctx, WithdrawFeeConfig) } // MaintenanceModeAllowed reads admission of "maintenance" state from the From 0c5d74729c62d535959965952fd88fe3fbdeffb2 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 13:43:30 +0300 Subject: [PATCH 1333/1413] [#1679] node: Fix 'revive' warning Change-Id: I74ff6332b10f17a329c5d108d01d43002e92aafd Signed-off-by: Alexander Chuprov --- pkg/util/ape/parser.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/util/ape/parser.go b/pkg/util/ape/parser.go index a34a17f6f9..6f114d45b9 100644 --- a/pkg/util/ape/parser.go +++ b/pkg/util/ape/parser.go @@ -174,11 +174,11 @@ func parseStatus(lexeme string) (apechain.Status, error) { case "deny": if !found { return apechain.AccessDenied, nil - } else if strings.EqualFold(expression, "QuotaLimitReached") { - return apechain.QuotaLimitReached, nil - } else { - return 0, fmt.Errorf("%w: %s", errUnknownStatusDetail, expression) } + if strings.EqualFold(expression, "QuotaLimitReached") { + return apechain.QuotaLimitReached, nil + } + return 0, fmt.Errorf("%w: %s", errUnknownStatusDetail, expression) case "allow": if found { return 0, errUnknownStatusDetail From b4b053cecd4c85361eee345b4b628e98412d270e Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 13:46:49 +0300 Subject: [PATCH 1334/1413] [#1679] node: Fix 'gocognit' warning Change-Id: I6e2a278af51869c05c306c2910ba85130e39532e Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/engine/lock.go | 29 ++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index 5d43e59df1..18fff9cad8 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -84,17 +84,11 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo var siErr *objectSDK.SplitInfoError var eiErr *objectSDK.ECInfoError if errors.As(err, &eiErr) { - eclocked := []oid.ID{locked} - for _, chunk := range eiErr.ECInfo().Chunks { - var objID oid.ID - err = objID.ReadFromV2(chunk.ID) - if err != nil { - e.reportShardError(ctx, sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), - zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) - return false - } - eclocked = append(eclocked, objID) + eclocked, ok := e.checkECLocked(ctx, sh, idCnr, locker, locked, eiErr) + if !ok { + return false } + err = sh.Lock(ctx, idCnr, locker, eclocked) if err != nil { e.reportShardError(ctx, sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), @@ -137,3 +131,18 @@ func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, lo }) return } + +func (e *StorageEngine) checkECLocked(ctx context.Context, sh hashedShard, idCnr cid.ID, locker, locked oid.ID, eiErr *objectSDK.ECInfoError) ([]oid.ID, bool) { + eclocked := []oid.ID{locked} + for _, chunk := range eiErr.ECInfo().Chunks { + var objID oid.ID + err := objID.ReadFromV2(chunk.ID) + if err != nil { + e.reportShardError(ctx, sh, "could not lock object in shard", err, zap.Stringer("container_id", idCnr), + zap.Stringer("locker_id", locker), zap.Stringer("locked_id", locked)) + return nil, false + } + eclocked = append(eclocked, objID) + } + return eclocked, true +} From 9b5c1da40f2eac063ce38ca05d9211deba541234 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 14:21:44 +0300 Subject: [PATCH 1335/1413] [#1679] linter: Bump 'golangci-lint' to v1.64.8 - Removed deprecated config option 'linters.govet.check-shadowing', replaced with enabling the 'shadow' linter. - Removed usage of deprecated 'tenv' linter, replaced by 'usetesting'. Change-Id: Ib1bd1ec83b0fd55a47e405b290bc2bc967b9389c Signed-off-by: Alexander Chuprov --- .golangci.yml | 7 ++----- Makefile | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index f21a46248e..18de494254 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -27,9 +27,6 @@ linters-settings: - standard - default custom-order: true - govet: - # report about shadowed variables - check-shadowing: false staticcheck: checks: ["all", "-SA1019"] # TODO Enable SA1019 after deprecated warning are fixed. funlen: @@ -60,8 +57,8 @@ linters-settings: linters: enable: # mandatory linters - - govet - revive + - predeclared # some default golangci-lint linters - errcheck @@ -94,8 +91,8 @@ linters: - testifylint - protogetter - intrange - - tenv - unconvert - unparam + - usetesting disable-all: true fast: false diff --git a/Makefile b/Makefile index 321365f0d4..5b55c9eec6 100755 --- a/Makefile +++ b/Makefile @@ -9,8 +9,8 @@ HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.23 -LINT_VERSION ?= 1.62.2 -TRUECLOUDLAB_LINT_VERSION ?= 0.0.8 +LINT_VERSION ?= 1.64.8 +TRUECLOUDLAB_LINT_VERSION ?= 0.0.10 PROTOC_VERSION ?= 25.0 PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go) PROTOC_OS_VERSION=osx-x86_64 From 923f0acf8f03a485c665f9b610bd5f96b5c0200d Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 31 Mar 2025 05:12:22 +0300 Subject: [PATCH 1336/1413] [#1564] cli: Fix output of `object nodes` command The object nodes command misleadingly reported the number of "found data objects" as if it matched the actual expected amount, which could be incorrect for EC objects. Updated the output wording to explicitly distinguish between currently available data objects and total objects per the EC schema. Change-Id: Ib36b89db58ae66d8978baf5a16b59435db9a068d Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-cli/modules/object/nodes.go | 59 ++++++++++++++++++------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index bc34b370df..734b557a43 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -48,6 +48,12 @@ type ecHeader struct { parent oid.ID } +type objectCounter struct { + sync.Mutex + total uint32 + isECcounted bool +} + type objectPlacement struct { requiredNodes []netmapSDK.NodeInfo confirmedNodes []netmapSDK.NodeInfo @@ -56,6 +62,7 @@ type objectPlacement struct { type objectNodesResult struct { errors []error placements map[oid.ID]objectPlacement + total uint32 } type ObjNodesDataObject struct { @@ -106,18 +113,18 @@ func objectNodes(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) cli := internalclient.GetSDKClientByFlag(cmd, pk, commonflags.RPC) - objects := getPhyObjects(cmd, cnrID, objID, cli, pk) + objects, count := getPhyObjects(cmd, cnrID, objID, cli, pk) placementPolicy, netmap := getPlacementPolicyAndNetmap(cmd, cnrID, cli) result := getRequiredPlacement(cmd, objects, placementPolicy, netmap) - getActualPlacement(cmd, netmap, pk, objects, result) + getActualPlacement(cmd, netmap, pk, objects, count, result) printPlacement(cmd, objID, objects, result) } -func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey) []phyObject { +func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey) ([]phyObject, int) { var addrObj oid.Address addrObj.SetContainer(cnrID) addrObj.SetObject(objID) @@ -145,7 +152,7 @@ func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.C parent: res.Header().ECHeader().Parent(), } } - return []phyObject{obj} + return []phyObject{obj}, 1 } var errSplitInfo *objectSDK.SplitInfoError @@ -155,29 +162,34 @@ func getPhyObjects(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.C var ecInfoError *objectSDK.ECInfoError if errors.As(err, &ecInfoError) { - return getECObjectChunks(cmd, cnrID, objID, ecInfoError) + return getECObjectChunks(cmd, cnrID, objID, ecInfoError), 1 } commonCmd.ExitOnErr(cmd, "failed to get object info: %w", err) - return nil + return nil, 0 } -func getComplexObjectParts(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, prmHead internalclient.HeadObjectPrm, errSplitInfo *objectSDK.SplitInfoError) []phyObject { - members := getCompexObjectMembers(cmd, cnrID, objID, cli, prmHead, errSplitInfo) - return flattenComplexMembersIfECContainer(cmd, cnrID, members, prmHead) +func getComplexObjectParts(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, prmHead internalclient.HeadObjectPrm, errSplitInfo *objectSDK.SplitInfoError) ([]phyObject, int) { + members, total := getCompexObjectMembers(cmd, cnrID, objID, cli, prmHead, errSplitInfo) + return flattenComplexMembersIfECContainer(cmd, cnrID, members, prmHead), total } -func getCompexObjectMembers(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, prmHead internalclient.HeadObjectPrm, errSplitInfo *objectSDK.SplitInfoError) []oid.ID { +func getCompexObjectMembers(cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, prmHead internalclient.HeadObjectPrm, errSplitInfo *objectSDK.SplitInfoError) ([]oid.ID, int) { + var total int splitInfo := errSplitInfo.SplitInfo() if members, ok := tryGetSplitMembersByLinkingObject(cmd, splitInfo, prmHead, cnrID); ok { - return members + if total = len(members); total > 0 { + total-- // linking object is not data object + } + return members, total } if members, ok := tryGetSplitMembersBySplitID(cmd, splitInfo, cli, cnrID); ok { - return members + return members, len(members) } - return tryRestoreChainInReverse(cmd, splitInfo, prmHead, cli, cnrID, objID) + members := tryRestoreChainInReverse(cmd, splitInfo, prmHead, cli, cnrID, objID) + return members, len(members) } func flattenComplexMembersIfECContainer(cmd *cobra.Command, cnrID cid.ID, members []oid.ID, prmHead internalclient.HeadObjectPrm) []phyObject { @@ -383,8 +395,11 @@ func getECRequiredPlacementInternal(cmd *cobra.Command, object phyObject, placem } } -func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, pk *ecdsa.PrivateKey, objects []phyObject, result *objectNodesResult) { +func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, pk *ecdsa.PrivateKey, objects []phyObject, count int, result *objectNodesResult) { resultMtx := &sync.Mutex{} + counter := &objectCounter{ + total: uint32(count), + } candidates := getNodesToCheckObjectExistance(cmd, netmap, result) @@ -401,7 +416,7 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, pk *ecdsa. for _, object := range objects { eg.Go(func() error { - stored, err := isObjectStoredOnNode(egCtx, cmd, object.containerID, object.objectID, cli, pk) + stored, err := isObjectStoredOnNode(egCtx, cmd, object.containerID, object.objectID, cli, pk, counter) resultMtx.Lock() defer resultMtx.Unlock() if err == nil && stored { @@ -420,6 +435,7 @@ func getActualPlacement(cmd *cobra.Command, netmap *netmapSDK.NetMap, pk *ecdsa. } commonCmd.ExitOnErr(cmd, "failed to get actual placement: %w", eg.Wait()) + result.total = counter.total } func getNodesToCheckObjectExistance(cmd *cobra.Command, netmap *netmapSDK.NetMap, result *objectNodesResult) []netmapSDK.NodeInfo { @@ -478,7 +494,7 @@ func createClient(ctx context.Context, cmd *cobra.Command, candidate netmapSDK.N return cli, nil } -func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey) (bool, error) { +func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID, objID oid.ID, cli *client.Client, pk *ecdsa.PrivateKey, counter *objectCounter) (bool, error) { var addrObj oid.Address addrObj.SetContainer(cnrID) addrObj.SetObject(objID) @@ -493,6 +509,14 @@ func isObjectStoredOnNode(ctx context.Context, cmd *cobra.Command, cnrID cid.ID, res, err := internalclient.HeadObject(ctx, prmHead) if err == nil && res != nil { + if res.Header().ECHeader() != nil { + counter.Lock() + defer counter.Unlock() + if !counter.isECcounted { + counter.total *= res.Header().ECHeader().Total() + } + counter.isECcounted = true + } return true, nil } var notFound *apistatus.ObjectNotFound @@ -512,7 +536,8 @@ func printPlacement(cmd *cobra.Command, objID oid.ID, objects []phyObject, resul } func printObjectNodesAsText(cmd *cobra.Command, objID oid.ID, objects []phyObject, result *objectNodesResult) { - fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects:\n", objID.EncodeToString(), len(objects)) + fmt.Fprintf(cmd.OutOrStdout(), "Object %s stores payload in %d data objects\n", objID.EncodeToString(), result.total) + fmt.Fprintf(cmd.OutOrStdout(), "Found %d:\n", len(objects)) for _, object := range objects { fmt.Fprintf(cmd.OutOrStdout(), "- %s\n", object.objectID) From 6f7b6b65f3b8cc3f372d900ee41242f0624b5b67 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 16:54:58 +0300 Subject: [PATCH 1337/1413] [#1689] linter: Fix staticcheck warning: 'embedded field can be simplified' Change-Id: I8f454f7d09973cdea096495c3949b88cdd01102e Signed-off-by: Alexander Chuprov --- .../modules/morph/contract/dump_hashes.go | 2 +- cmd/frostfs-lens/internal/tui/input.go | 8 ++-- cmd/frostfs-lens/internal/tui/ui.go | 2 +- cmd/frostfs-node/apemanager.go | 2 +- cmd/frostfs-node/container.go | 6 +-- cmd/frostfs-node/metrics.go | 28 ++++++------- cmd/frostfs-node/object.go | 6 +-- cmd/frostfs-node/pprof.go | 26 ++++++------ cmd/frostfs-node/tree.go | 4 +- pkg/local_object_storage/blobstor/blobstor.go | 2 +- pkg/local_object_storage/engine/container.go | 4 +- pkg/local_object_storage/engine/control.go | 2 +- pkg/local_object_storage/engine/inhume.go | 4 +- pkg/local_object_storage/engine/shards.go | 2 +- pkg/local_object_storage/pilorama/boltdb.go | 6 +-- pkg/local_object_storage/pilorama/forest.go | 4 +- pkg/local_object_storage/pilorama/inmemory.go | 10 ++--- pkg/local_object_storage/shard/control.go | 4 +- pkg/local_object_storage/shard/gc.go | 4 +- pkg/local_object_storage/shard/id.go | 2 +- pkg/local_object_storage/shard/shard.go | 42 +++++++++---------- pkg/services/control/server/evacuate_async.go | 2 +- pkg/services/object/common/writer/common.go | 6 +-- pkg/services/object/get/assemble.go | 2 +- pkg/services/object/get/get.go | 2 +- pkg/services/object/get/v2/streamer.go | 6 +-- pkg/services/object/patch/service.go | 2 +- pkg/services/object/put/single.go | 22 +++++----- pkg/services/policer/ec.go | 14 +++---- .../session/storage/persistent/storage.go | 2 +- pkg/services/tree/cache.go | 6 +-- pkg/services/tree/replicator.go | 2 +- pkg/services/tree/service.go | 2 +- pkg/services/tree/sync.go | 4 +- 34 files changed, 121 insertions(+), 121 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index fb7e4ff624..7630a226e0 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -242,7 +242,7 @@ func fillContractVersion(cmd *cobra.Command, c helper.Client, infos []contractDu script := sub.Bytes() emit.Instruction(bw.BinWriter, opcode.TRY, []byte{byte(3 + len(script) + 2), 0}) - bw.BinWriter.WriteBytes(script) + bw.WriteBytes(script) emit.Instruction(bw.BinWriter, opcode.ENDTRY, []byte{2 + 1}) emit.Opcodes(bw.BinWriter, opcode.PUSH0) } diff --git a/cmd/frostfs-lens/internal/tui/input.go b/cmd/frostfs-lens/internal/tui/input.go index 90729c1190..471514e5d7 100644 --- a/cmd/frostfs-lens/internal/tui/input.go +++ b/cmd/frostfs-lens/internal/tui/input.go @@ -53,17 +53,17 @@ func (f *InputFieldWithHistory) InputHandler() func(event *tcell.EventKey, setFo f.historyPointer++ // Stop iterating over history. if f.historyPointer == len(f.history) { - f.InputField.SetText(f.currentContent) + f.SetText(f.currentContent) return } - f.InputField.SetText(f.history[f.historyPointer]) + f.SetText(f.history[f.historyPointer]) case tcell.KeyUp: if len(f.history) == 0 { return } // Start iterating over history. if f.historyPointer == len(f.history) { - f.currentContent = f.InputField.GetText() + f.currentContent = f.GetText() } // End of history. if f.historyPointer == 0 { @@ -71,7 +71,7 @@ func (f *InputFieldWithHistory) InputHandler() func(event *tcell.EventKey, setFo } // Iterate to least recent prompts. f.historyPointer-- - f.InputField.SetText(f.history[f.historyPointer]) + f.SetText(f.history[f.historyPointer]) default: f.InputField.InputHandler()(event, func(tview.Primitive) {}) } diff --git a/cmd/frostfs-lens/internal/tui/ui.go b/cmd/frostfs-lens/internal/tui/ui.go index bcc082821c..bd7540b01c 100644 --- a/cmd/frostfs-lens/internal/tui/ui.go +++ b/cmd/frostfs-lens/internal/tui/ui.go @@ -482,7 +482,7 @@ func (ui *UI) handleInputOnSearching(event *tcell.EventKey) { ui.searchBar.InputHandler()(event, func(tview.Primitive) {}) } - ui.Box.MouseHandler() + ui.MouseHandler() } func (ui *UI) WithPrompt(prompt string) error { diff --git a/cmd/frostfs-node/apemanager.go b/cmd/frostfs-node/apemanager.go index e761a1b14c..513314712a 100644 --- a/cmd/frostfs-node/apemanager.go +++ b/cmd/frostfs-node/apemanager.go @@ -14,7 +14,7 @@ import ( func initAPEManagerService(c *cfg) { contractStorage := ape_contract.NewProxyVerificationContractStorage( morph.NewSwitchRPCGuardedActor(c.cfgMorph.client), - c.shared.key, + c.key, c.cfgMorph.proxyScriptHash, c.cfgObject.cfgAccessPolicyEngine.policyContractHash) diff --git a/cmd/frostfs-node/container.go b/cmd/frostfs-node/container.go index 0120122972..bdb280d87b 100644 --- a/cmd/frostfs-node/container.go +++ b/cmd/frostfs-node/container.go @@ -32,7 +32,7 @@ func initContainerService(_ context.Context, c *cfg) { wrap, err := cntClient.NewFromMorph(c.cfgMorph.client, c.cfgContainer.scriptHash, 0) fatalOnErr(err) - c.shared.cnrClient = wrap + c.cnrClient = wrap cnrSrc := cntClient.AsContainerSource(wrap) @@ -47,7 +47,7 @@ func initContainerService(_ context.Context, c *cfg) { frostfsIDSubjectProvider = newMorphFrostfsIDCache(frostfsIDSubjectProvider, int(cacheSize), c.cfgMorph.cacheTTL, metrics.NewCacheMetrics("frostfs_id")) } - c.shared.frostfsidClient = frostfsIDSubjectProvider + c.frostfsidClient = frostfsIDSubjectProvider c.cfgContainer.containerBatchSize = containerconfig.ContainerBatchSize(c.appCfg) defaultChainRouter := engine.NewDefaultChainRouterWithLocalOverrides( @@ -57,7 +57,7 @@ func initContainerService(_ context.Context, c *cfg) { service := containerService.NewSignService( &c.key.PrivateKey, containerService.NewAPEServer(defaultChainRouter, cnrRdr, - newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient, + newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.frostfsidClient, containerService.NewSplitterService( c.cfgContainer.containerBatchSize, c.respSvc, containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc)), diff --git a/cmd/frostfs-node/metrics.go b/cmd/frostfs-node/metrics.go index 19b4af51f1..d9ca01e704 100644 --- a/cmd/frostfs-node/metrics.go +++ b/cmd/frostfs-node/metrics.go @@ -8,38 +8,38 @@ import ( func metricsComponent(c *cfg) (*httpComponent, bool) { var updated bool // check if it has been inited before - if c.dynamicConfiguration.metrics == nil { - c.dynamicConfiguration.metrics = new(httpComponent) - c.dynamicConfiguration.metrics.cfg = c - c.dynamicConfiguration.metrics.name = "metrics" - c.dynamicConfiguration.metrics.handler = metrics.Handler() + if c.metrics == nil { + c.metrics = new(httpComponent) + c.metrics.cfg = c + c.metrics.name = "metrics" + c.metrics.handler = metrics.Handler() updated = true } // (re)init read configuration enabled := metricsconfig.Enabled(c.appCfg) - if enabled != c.dynamicConfiguration.metrics.enabled { - c.dynamicConfiguration.metrics.enabled = enabled + if enabled != c.metrics.enabled { + c.metrics.enabled = enabled updated = true } address := metricsconfig.Address(c.appCfg) - if address != c.dynamicConfiguration.metrics.address { - c.dynamicConfiguration.metrics.address = address + if address != c.metrics.address { + c.metrics.address = address updated = true } dur := metricsconfig.ShutdownTimeout(c.appCfg) - if dur != c.dynamicConfiguration.metrics.shutdownDur { - c.dynamicConfiguration.metrics.shutdownDur = dur + if dur != c.metrics.shutdownDur { + c.metrics.shutdownDur = dur updated = true } - return c.dynamicConfiguration.metrics, updated + return c.metrics, updated } func enableMetricsSvc(c *cfg) { - c.shared.metricsSvc.Enable() + c.metricsSvc.Enable() } func disableMetricsSvc(c *cfg) { - c.shared.metricsSvc.Disable() + c.metricsSvc.Disable() } diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 2674be8c7b..527746d260 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -186,9 +186,9 @@ func initObjectService(c *cfg) { respSvc, ) - c.shared.metricsSvc = objectService.NewMetricCollector( + c.metricsSvc = objectService.NewMetricCollector( signSvc, c.metricsCollector.ObjectService(), metricsconfig.Enabled(c.appCfg)) - qosService := objectService.NewQoSObjectService(c.shared.metricsSvc, &c.cfgQoSService) + qosService := objectService.NewQoSObjectService(c.metricsSvc, &c.cfgQoSService) auditSvc := objectService.NewAuditService(qosService, c.log, c.audit) server := objectTransportGRPC.New(auditSvc) @@ -432,7 +432,7 @@ func createAPEService(c *cfg, irFetcher *cachedIRFetcher, splitSvc *objectServic c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.LocalStorage(), c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine.MorphRuleChainStorage(), objectAPE.NewStorageEngineHeaderProvider(c.cfgObject.cfgLocalStorage.localStorage, c.cfgObject.getSvc), - c.shared.frostfsidClient, + c.frostfsidClient, c.netMapSource, c.cfgNetmap.state, c.cfgObject.cnrSource, diff --git a/cmd/frostfs-node/pprof.go b/cmd/frostfs-node/pprof.go index 5b40c8a88a..e4da8119ff 100644 --- a/cmd/frostfs-node/pprof.go +++ b/cmd/frostfs-node/pprof.go @@ -18,33 +18,33 @@ func initProfilerService(ctx context.Context, c *cfg) { func pprofComponent(c *cfg) (*httpComponent, bool) { var updated bool // check if it has been inited before - if c.dynamicConfiguration.pprof == nil { - c.dynamicConfiguration.pprof = new(httpComponent) - c.dynamicConfiguration.pprof.cfg = c - c.dynamicConfiguration.pprof.name = "pprof" - c.dynamicConfiguration.pprof.handler = httputil.Handler() - c.dynamicConfiguration.pprof.preReload = tuneProfilers + if c.pprof == nil { + c.pprof = new(httpComponent) + c.pprof.cfg = c + c.pprof.name = "pprof" + c.pprof.handler = httputil.Handler() + c.pprof.preReload = tuneProfilers updated = true } // (re)init read configuration enabled := profilerconfig.Enabled(c.appCfg) - if enabled != c.dynamicConfiguration.pprof.enabled { - c.dynamicConfiguration.pprof.enabled = enabled + if enabled != c.pprof.enabled { + c.pprof.enabled = enabled updated = true } address := profilerconfig.Address(c.appCfg) - if address != c.dynamicConfiguration.pprof.address { - c.dynamicConfiguration.pprof.address = address + if address != c.pprof.address { + c.pprof.address = address updated = true } dur := profilerconfig.ShutdownTimeout(c.appCfg) - if dur != c.dynamicConfiguration.pprof.shutdownDur { - c.dynamicConfiguration.pprof.shutdownDur = dur + if dur != c.pprof.shutdownDur { + c.pprof.shutdownDur = dur updated = true } - return c.dynamicConfiguration.pprof, updated + return c.pprof, updated } func tuneProfilers(c *cfg) { diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index 65414f0ca1..67d9c9df02 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -51,9 +51,9 @@ func initTreeService(c *cfg) { c.treeService = tree.New( tree.WithContainerSource(cnrSource{ src: c.cfgObject.cnrSource, - cli: c.shared.cnrClient, + cli: c.cnrClient, }), - tree.WithFrostfsidSubjectProvider(c.shared.frostfsidClient), + tree.WithFrostfsidSubjectProvider(c.frostfsidClient), tree.WithNetmapSource(c.netMapSource), tree.WithPrivateKey(&c.key.PrivateKey), tree.WithLogger(c.log), diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index f850f48b40..d7c3333496 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -153,5 +153,5 @@ func WithMetrics(m Metrics) Option { } func (b *BlobStor) Compressor() *compression.Config { - return &b.cfg.compression + return &b.compression } diff --git a/pkg/local_object_storage/engine/container.go b/pkg/local_object_storage/engine/container.go index 3160d7f835..03a299b93b 100644 --- a/pkg/local_object_storage/engine/container.go +++ b/pkg/local_object_storage/engine/container.go @@ -74,7 +74,7 @@ func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) var csPrm shard.ContainerSizePrm csPrm.SetContainerID(prm.cnr) - csRes, err := sh.Shard.ContainerSize(ctx, csPrm) + csRes, err := sh.ContainerSize(ctx, csPrm) if err != nil { e.reportShardError(ctx, sh, "can't get container size", err, zap.Stringer("container_id", prm.cnr)) @@ -119,7 +119,7 @@ func (e *StorageEngine) listContainers(ctx context.Context) ListContainersRes { uniqueIDs := make(map[string]cid.ID) e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { - res, err := sh.Shard.ListContainers(ctx, shard.ListContainersPrm{}) + res, err := sh.ListContainers(ctx, shard.ListContainersPrm{}) if err != nil { e.reportShardError(ctx, sh, "can't get list of containers", err) return false diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index 7caa515d4b..96b53581e7 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -77,7 +77,7 @@ func (e *StorageEngine) Init(ctx context.Context) error { errCh := make(chan shardInitError, len(e.shards)) var eg errgroup.Group - if e.cfg.lowMem && e.anyShardRequiresRefill() { + if e.lowMem && e.anyShardRequiresRefill() { eg.SetLimit(1) } diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index c8ee33b534..6ec9a4ef0e 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -227,7 +227,7 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e var outErr error e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { - locked, err = h.Shard.IsLocked(ctx, addr) + locked, err = h.IsLocked(ctx, addr) if err != nil { e.reportShardError(ctx, h, "can't check object's lockers", err, zap.Stringer("address", addr)) outErr = err @@ -256,7 +256,7 @@ func (e *StorageEngine) GetLocks(ctx context.Context, addr oid.Address) ([]oid.I var outErr error e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { - locks, err := h.Shard.GetLocks(ctx, addr) + locks, err := h.GetLocks(ctx, addr) if err != nil { e.reportShardError(ctx, h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr)) outErr = err diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index dfc3b1a352..6e6c08bb55 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -118,7 +118,7 @@ func (e *StorageEngine) AddShard(ctx context.Context, opts ...shard.Option) (*sh return nil, fmt.Errorf("add %s shard: %w", sh.ID().String(), err) } - e.cfg.metrics.SetMode(sh.ID().String(), sh.GetMode()) + e.metrics.SetMode(sh.ID().String(), sh.GetMode()) return sh.ID(), nil } diff --git a/pkg/local_object_storage/pilorama/boltdb.go b/pkg/local_object_storage/pilorama/boltdb.go index fc7cdaabc0..897b37ea0e 100644 --- a/pkg/local_object_storage/pilorama/boltdb.go +++ b/pkg/local_object_storage/pilorama/boltdb.go @@ -1582,12 +1582,12 @@ func (t *boltForest) moveFromBytes(m *Move, data []byte) error { func (t *boltForest) logFromBytes(lm *Move, data []byte) error { lm.Child = binary.LittleEndian.Uint64(data) lm.Parent = binary.LittleEndian.Uint64(data[8:]) - return lm.Meta.FromBytes(data[16:]) + return lm.FromBytes(data[16:]) } func (t *boltForest) logToBytes(lm *Move) []byte { w := io.NewBufBinWriter() - size := 8 + 8 + lm.Meta.Size() + 1 + size := 8 + 8 + lm.Size() + 1 // if lm.HasOld { // size += 8 + lm.Old.Meta.Size() // } @@ -1595,7 +1595,7 @@ func (t *boltForest) logToBytes(lm *Move) []byte { w.Grow(size) w.WriteU64LE(lm.Child) w.WriteU64LE(lm.Parent) - lm.Meta.EncodeBinary(w.BinWriter) + lm.EncodeBinary(w.BinWriter) // w.WriteBool(lm.HasOld) // if lm.HasOld { // w.WriteU64LE(lm.Old.Parent) diff --git a/pkg/local_object_storage/pilorama/forest.go b/pkg/local_object_storage/pilorama/forest.go index b5320e42dd..ebfd0bcc08 100644 --- a/pkg/local_object_storage/pilorama/forest.go +++ b/pkg/local_object_storage/pilorama/forest.go @@ -177,7 +177,7 @@ func (f *memoryForest) TreeSortedByFilename(_ context.Context, cid cid.ID, treeI var res []NodeInfo for _, nodeID := range nodeIDs { - children := s.tree.getChildren(nodeID) + children := s.getChildren(nodeID) for _, childID := range children { var found bool for _, kv := range s.infoMap[childID].Meta.Items { @@ -222,7 +222,7 @@ func (f *memoryForest) TreeGetChildren(_ context.Context, cid cid.ID, treeID str return nil, ErrTreeNotFound } - children := s.tree.getChildren(nodeID) + children := s.getChildren(nodeID) res := make([]NodeInfo, 0, len(children)) for _, childID := range children { res = append(res, NodeInfo{ diff --git a/pkg/local_object_storage/pilorama/inmemory.go b/pkg/local_object_storage/pilorama/inmemory.go index ce7b3db1e9..f74d12a1b6 100644 --- a/pkg/local_object_storage/pilorama/inmemory.go +++ b/pkg/local_object_storage/pilorama/inmemory.go @@ -35,9 +35,9 @@ func newMemoryTree() *memoryTree { // undo un-does op and changes s in-place. func (s *memoryTree) undo(op *move) { if op.HasOld { - s.tree.infoMap[op.Child] = op.Old + s.infoMap[op.Child] = op.Old } else { - delete(s.tree.infoMap, op.Child) + delete(s.infoMap, op.Child) } } @@ -83,8 +83,8 @@ func (s *memoryTree) do(op *Move) move { }, } - shouldPut := !s.tree.isAncestor(op.Child, op.Parent) - p, ok := s.tree.infoMap[op.Child] + shouldPut := !s.isAncestor(op.Child, op.Parent) + p, ok := s.infoMap[op.Child] if ok { lm.HasOld = true lm.Old = p @@ -100,7 +100,7 @@ func (s *memoryTree) do(op *Move) move { p.Meta = m p.Parent = op.Parent - s.tree.infoMap[op.Child] = p + s.infoMap[op.Child] = p return lm } diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 19b13a8abe..72e650c5e8 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -214,8 +214,8 @@ func (s *Shard) refillMetabase(ctx context.Context) error { } eg, egCtx := errgroup.WithContext(ctx) - if s.cfg.refillMetabaseWorkersCount > 0 { - eg.SetLimit(s.cfg.refillMetabaseWorkersCount) + if s.refillMetabaseWorkersCount > 0 { + eg.SetLimit(s.refillMetabaseWorkersCount) } var completedCount uint64 diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 9b327f6f12..19b6e2d12f 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -320,8 +320,8 @@ func (s *Shard) getGarbage(ctx context.Context) ([]oid.Address, error) { } func (s *Shard) getExpiredObjectsParameters() (workerCount, batchSize int) { - workerCount = max(minExpiredWorkers, s.gc.gcCfg.expiredCollectorWorkerCount) - batchSize = max(minExpiredBatchSize, s.gc.gcCfg.expiredCollectorBatchSize) + workerCount = max(minExpiredWorkers, s.gc.expiredCollectorWorkerCount) + batchSize = max(minExpiredBatchSize, s.gc.expiredCollectorBatchSize) return } diff --git a/pkg/local_object_storage/shard/id.go b/pkg/local_object_storage/shard/id.go index b233b705c9..7391adef2e 100644 --- a/pkg/local_object_storage/shard/id.go +++ b/pkg/local_object_storage/shard/id.go @@ -45,7 +45,7 @@ func (s *Shard) UpdateID(ctx context.Context) (err error) { } shardID := s.info.ID.String() - s.cfg.metricsWriter.SetShardID(shardID) + s.metricsWriter.SetShardID(shardID) if s.writeCache != nil && s.writeCache.GetMetrics() != nil { s.writeCache.GetMetrics().SetShardID(shardID) } diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index b9ec05f013..304a6bf9df 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -218,7 +218,7 @@ func WithWriteCache(use bool) Option { // hasWriteCache returns bool if write cache exists on shards. func (s *Shard) hasWriteCache() bool { - return s.cfg.useWriteCache + return s.useWriteCache } // NeedRefillMetabase returns true if metabase is needed to be refilled. @@ -379,15 +379,15 @@ func WithLimiter(l qos.Limiter) Option { } func (s *Shard) fillInfo() { - s.cfg.info.MetaBaseInfo = s.metaBase.DumpInfo() - s.cfg.info.BlobStorInfo = s.blobStor.DumpInfo() - s.cfg.info.Mode = s.GetMode() + s.info.MetaBaseInfo = s.metaBase.DumpInfo() + s.info.BlobStorInfo = s.blobStor.DumpInfo() + s.info.Mode = s.GetMode() - if s.cfg.useWriteCache { - s.cfg.info.WriteCacheInfo = s.writeCache.DumpInfo() + if s.useWriteCache { + s.info.WriteCacheInfo = s.writeCache.DumpInfo() } if s.pilorama != nil { - s.cfg.info.PiloramaInfo = s.pilorama.DumpInfo() + s.info.PiloramaInfo = s.pilorama.DumpInfo() } } @@ -454,57 +454,57 @@ func (s *Shard) updateMetrics(ctx context.Context) { s.setContainerObjectsCount(contID.EncodeToString(), logical, count.Logic) s.setContainerObjectsCount(contID.EncodeToString(), user, count.User) } - s.cfg.metricsWriter.SetMode(s.info.Mode) + s.metricsWriter.SetMode(s.info.Mode) } // incObjectCounter increment both physical and logical object // counters. func (s *Shard) incObjectCounter(cnrID cid.ID, isUser bool) { - s.cfg.metricsWriter.IncObjectCounter(physical) - s.cfg.metricsWriter.IncObjectCounter(logical) - s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), physical) - s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), logical) + s.metricsWriter.IncObjectCounter(physical) + s.metricsWriter.IncObjectCounter(logical) + s.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), physical) + s.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), logical) if isUser { - s.cfg.metricsWriter.IncObjectCounter(user) - s.cfg.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), user) + s.metricsWriter.IncObjectCounter(user) + s.metricsWriter.IncContainerObjectsCount(cnrID.EncodeToString(), user) } } func (s *Shard) decObjectCounterBy(typ string, v uint64) { if v > 0 { - s.cfg.metricsWriter.AddToObjectCounter(typ, -int(v)) + s.metricsWriter.AddToObjectCounter(typ, -int(v)) } } func (s *Shard) setObjectCounterBy(typ string, v uint64) { if v > 0 { - s.cfg.metricsWriter.SetObjectCounter(typ, v) + s.metricsWriter.SetObjectCounter(typ, v) } } func (s *Shard) decContainerObjectCounter(byCnr map[cid.ID]meta.ObjectCounters) { for cnrID, count := range byCnr { if count.Phy > 0 { - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy) + s.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), physical, count.Phy) } if count.Logic > 0 { - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic) + s.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), logical, count.Logic) } if count.User > 0 { - s.cfg.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), user, count.User) + s.metricsWriter.SubContainerObjectsCount(cnrID.EncodeToString(), user, count.User) } } } func (s *Shard) addToContainerSize(cnr string, size int64) { if size != 0 { - s.cfg.metricsWriter.AddToContainerSize(cnr, size) + s.metricsWriter.AddToContainerSize(cnr, size) } } func (s *Shard) addToPayloadSize(size int64) { if size != 0 { - s.cfg.metricsWriter.AddToPayloadSize(size) + s.metricsWriter.AddToPayloadSize(size) } } diff --git a/pkg/services/control/server/evacuate_async.go b/pkg/services/control/server/evacuate_async.go index 7469ea74ec..f3ba9015ed 100644 --- a/pkg/services/control/server/evacuate_async.go +++ b/pkg/services/control/server/evacuate_async.go @@ -220,7 +220,7 @@ func (s *Server) replicateTreeToNode(ctx context.Context, forest pilorama.Forest TreeId: treeID, Operation: &tree.LogMove{ ParentId: op.Parent, - Meta: op.Meta.Bytes(), + Meta: op.Bytes(), ChildId: op.Child, }, }, diff --git a/pkg/services/object/common/writer/common.go b/pkg/services/object/common/writer/common.go index 1998e96383..6593d3ca08 100644 --- a/pkg/services/object/common/writer/common.go +++ b/pkg/services/object/common/writer/common.go @@ -29,7 +29,7 @@ func (c *Config) NewNodeIterator(opts []placement.Option) *NodeIterator { } func (n *NodeIterator) ForEachNode(ctx context.Context, f func(context.Context, NodeDescriptor) error) error { - traverser, err := placement.NewTraverser(ctx, n.Traversal.Opts...) + traverser, err := placement.NewTraverser(ctx, n.Opts...) if err != nil { return fmt.Errorf("could not create object placement traverser: %w", err) } @@ -56,7 +56,7 @@ func (n *NodeIterator) ForEachNode(ctx context.Context, f func(context.Context, } // perform additional container broadcast if needed - if n.Traversal.submitPrimaryPlacementFinish() { + if n.submitPrimaryPlacementFinish() { err := n.ForEachNode(ctx, f) if err != nil { n.cfg.Logger.Error(ctx, logs.PutAdditionalContainerBroadcastFailure, zap.Error(err)) @@ -101,7 +101,7 @@ func (n *NodeIterator) forEachAddress(ctx context.Context, traverser *placement. // in subsequent container broadcast. Note that we don't // process this node during broadcast if primary placement // on it failed. - n.Traversal.submitProcessed(addr, item) + n.submitProcessed(addr, item) } wg.Wait() diff --git a/pkg/services/object/get/assemble.go b/pkg/services/object/get/assemble.go index e164627d2b..e801324896 100644 --- a/pkg/services/object/get/assemble.go +++ b/pkg/services/object/get/assemble.go @@ -146,5 +146,5 @@ func (r *request) getObjectWithIndependentRequest(ctx context.Context, prm Reque detachedExecutor.execute(ctx) - return detachedExecutor.statusError.err + return detachedExecutor.err } diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 557e9a0285..9676fd9144 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -87,7 +87,7 @@ func (s *Service) get(ctx context.Context, prm RequestParameters) error { exec.execute(ctx) - return exec.statusError.err + return exec.err } func (exec *request) execute(ctx context.Context) { diff --git a/pkg/services/object/get/v2/streamer.go b/pkg/services/object/get/v2/streamer.go index 98207336c4..0d73bcd4d4 100644 --- a/pkg/services/object/get/v2/streamer.go +++ b/pkg/services/object/get/v2/streamer.go @@ -24,14 +24,14 @@ func (s *streamObjectWriter) WriteHeader(_ context.Context, obj *objectSDK.Objec p.SetHeader(objV2.GetHeader()) p.SetSignature(objV2.GetSignature()) - return s.GetObjectStream.Send(newResponse(p)) + return s.Send(newResponse(p)) } func (s *streamObjectWriter) WriteChunk(_ context.Context, chunk []byte) error { p := new(objectV2.GetObjectPartChunk) p.SetChunk(chunk) - return s.GetObjectStream.Send(newResponse(p)) + return s.Send(newResponse(p)) } func newResponse(p objectV2.GetObjectPart) *objectV2.GetResponse { @@ -46,7 +46,7 @@ func newResponse(p objectV2.GetObjectPart) *objectV2.GetResponse { } func (s *streamObjectRangeWriter) WriteChunk(_ context.Context, chunk []byte) error { - return s.GetObjectRangeStream.Send(newRangeResponse(chunk)) + return s.Send(newRangeResponse(chunk)) } func newRangeResponse(p []byte) *objectV2.GetRangeResponse { diff --git a/pkg/services/object/patch/service.go b/pkg/services/object/patch/service.go index 953f82b483..5d298bfed0 100644 --- a/pkg/services/object/patch/service.go +++ b/pkg/services/object/patch/service.go @@ -28,7 +28,7 @@ func NewService(cfg *objectwriter.Config, // Patch calls internal service and returns v2 object streamer. func (s *Service) Patch() (object.PatchObjectStream, error) { - nodeKey, err := s.Config.KeyStorage.GetKey(nil) + nodeKey, err := s.KeyStorage.GetKey(nil) if err != nil { return nil, err } diff --git a/pkg/services/object/put/single.go b/pkg/services/object/put/single.go index f3c2dca1a3..90f4732542 100644 --- a/pkg/services/object/put/single.go +++ b/pkg/services/object/put/single.go @@ -102,7 +102,7 @@ func (s *Service) validarePutSingleSize(ctx context.Context, obj *objectSDK.Obje return target.ErrWrongPayloadSize } - maxAllowedSize := s.Config.MaxSizeSrc.MaxObjectSize(ctx) + maxAllowedSize := s.MaxSizeSrc.MaxObjectSize(ctx) if obj.PayloadSize() > maxAllowedSize { return target.ErrExceedingMaxSize } @@ -166,13 +166,13 @@ func (s *Service) saveToNodes(ctx context.Context, obj *objectSDK.Object, req *o } func (s *Service) saveToREPReplicas(ctx context.Context, placement putSinglePlacement, obj *objectSDK.Object, localOnly bool, req *objectAPI.PutSingleRequest, meta object.ContentMeta) error { - iter := s.Config.NewNodeIterator(placement.placementOptions) + iter := s.NewNodeIterator(placement.placementOptions) iter.ExtraBroadcastEnabled = objectwriter.NeedAdditionalBroadcast(obj, localOnly) iter.ResetSuccessAfterOnBroadcast = placement.resetSuccessAfterOnBroadcast signer := &putSingleRequestSigner{ req: req, - keyStorage: s.Config.KeyStorage, + keyStorage: s.KeyStorage, signer: &sync.Once{}, } @@ -186,13 +186,13 @@ func (s *Service) saveToECReplicas(ctx context.Context, placement putSinglePlace if err != nil { return err } - key, err := s.Config.KeyStorage.GetKey(nil) + key, err := s.KeyStorage.GetKey(nil) if err != nil { return err } signer := &putSingleRequestSigner{ req: req, - keyStorage: s.Config.KeyStorage, + keyStorage: s.KeyStorage, signer: &sync.Once{}, } @@ -225,7 +225,7 @@ func (s *Service) getPutSinglePlacementOptions(ctx context.Context, obj *objectS if !ok { return result, errors.New("missing container ID") } - cnrInfo, err := s.Config.ContainerSource.Get(ctx, cnrID) + cnrInfo, err := s.ContainerSource.Get(ctx, cnrID) if err != nil { return result, fmt.Errorf("could not get container by ID: %w", err) } @@ -249,14 +249,14 @@ func (s *Service) getPutSinglePlacementOptions(ctx context.Context, obj *objectS } result.placementOptions = append(result.placementOptions, placement.ForObject(objID)) - latestNetmap, err := netmap.GetLatestNetworkMap(ctx, s.Config.NetmapSource) + latestNetmap, err := netmap.GetLatestNetworkMap(ctx, s.NetmapSource) if err != nil { return result, fmt.Errorf("could not get latest network map: %w", err) } builder := placement.NewNetworkMapBuilder(latestNetmap) if localOnly { result.placementOptions = append(result.placementOptions, placement.SuccessAfter(1)) - builder = svcutil.NewLocalPlacement(builder, s.Config.NetmapKeys) + builder = svcutil.NewLocalPlacement(builder, s.NetmapKeys) } result.placementOptions = append(result.placementOptions, placement.UseBuilder(builder)) return result, nil @@ -273,7 +273,7 @@ func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *objectwrite client.NodeInfoFromNetmapElement(&info, nodeDesc.Info) - c, err := s.Config.ClientConstructor.Get(info) + c, err := s.ClientConstructor.Get(info) if err != nil { return fmt.Errorf("could not create SDK client %s: %w", info.AddressGroup(), err) } @@ -283,7 +283,7 @@ func (s *Service) saveToPlacementNode(ctx context.Context, nodeDesc *objectwrite func (s *Service) saveLocal(ctx context.Context, obj *objectSDK.Object, meta object.ContentMeta, container containerSDK.Container) error { localTarget := &objectwriter.LocalTarget{ - Storage: s.Config.LocalStore, + Storage: s.LocalStore, Container: container, } return localTarget.WriteObject(ctx, obj, meta) @@ -317,7 +317,7 @@ func (s *Service) redirectPutSingleRequest(ctx context.Context, if err != nil { objID, _ := obj.ID() cnrID, _ := obj.ContainerID() - s.Config.Logger.Warn(ctx, logs.PutSingleRedirectFailure, + s.Logger.Warn(ctx, logs.PutSingleRedirectFailure, zap.Error(err), zap.Stringer("address", addr), zap.Stringer("object_id", objID), diff --git a/pkg/services/policer/ec.go b/pkg/services/policer/ec.go index 1ee31d480b..fbdeb31485 100644 --- a/pkg/services/policer/ec.go +++ b/pkg/services/policer/ec.go @@ -101,7 +101,7 @@ func (p *Policer) processECContainerECObject(ctx context.Context, objInfo object func (p *Policer) processECChunk(ctx context.Context, objInfo objectcore.Info, nodes []netmap.NodeInfo) ecChunkProcessResult { var removeLocalChunk bool requiredNode := nodes[int(objInfo.ECInfo.Index)%(len(nodes))] - if p.cfg.netmapKeys.IsLocalKey(requiredNode.PublicKey()) { + if p.netmapKeys.IsLocalKey(requiredNode.PublicKey()) { // current node is required node, we are happy return ecChunkProcessResult{ validPlacement: true, @@ -185,7 +185,7 @@ func (p *Policer) collectRequiredECChunks(nodes []netmap.NodeInfo, objInfo objec if uint32(i) == objInfo.ECInfo.Total { break } - if p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) { + if p.netmapKeys.IsLocalKey(n.PublicKey()) { requiredChunkIndexes[uint32(i)] = []netmap.NodeInfo{} } } @@ -210,7 +210,7 @@ func (p *Policer) resolveLocalECChunks(ctx context.Context, parentAddress oid.Ad func (p *Policer) resolveRemoteECChunks(ctx context.Context, parentAddress oid.Address, nodes []netmap.NodeInfo, required map[uint32][]netmap.NodeInfo, indexToObjectID map[uint32]oid.ID) bool { var eiErr *objectSDK.ECInfoError for _, n := range nodes { - if p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) { + if p.netmapKeys.IsLocalKey(n.PublicKey()) { continue } _, err := p.remoteHeader(ctx, n, parentAddress, true) @@ -260,7 +260,7 @@ func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info return } var err error - if p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) { + if p.netmapKeys.IsLocalKey(n.PublicKey()) { _, err = p.localHeader(ctx, parentAddress) } else { _, err = p.remoteHeader(ctx, n, parentAddress, true) @@ -283,7 +283,7 @@ func (p *Policer) adjustECPlacement(ctx context.Context, objInfo objectcore.Info } } else if client.IsErrObjectAlreadyRemoved(err) { restore = false - } else if !p.cfg.netmapKeys.IsLocalKey(n.PublicKey()) && uint32(idx) < objInfo.ECInfo.Total { + } else if !p.netmapKeys.IsLocalKey(n.PublicKey()) && uint32(idx) < objInfo.ECInfo.Total { p.log.Warn(ctx, logs.PolicerCouldNotGetObjectFromNodeMoving, zap.String("node", hex.EncodeToString(n.PublicKey())), zap.Stringer("object", parentAddress), zap.Error(err)) p.replicator.HandleReplicationTask(ctx, replicator.Task{ NumCopies: 1, @@ -343,7 +343,7 @@ func (p *Policer) restoreECObject(ctx context.Context, objInfo objectcore.Info, pID, _ := part.ID() addr.SetObject(pID) targetNode := nodes[idx%len(nodes)] - if p.cfg.netmapKeys.IsLocalKey(targetNode.PublicKey()) { + if p.netmapKeys.IsLocalKey(targetNode.PublicKey()) { p.replicator.HandleLocalPutTask(ctx, replicator.Task{ Addr: addr, Obj: part, @@ -371,7 +371,7 @@ func (p *Policer) collectExistedChunks(ctx context.Context, objInfo objectcore.I var obj *objectSDK.Object var err error for _, node := range nodes { - if p.cfg.netmapKeys.IsLocalKey(node.PublicKey()) { + if p.netmapKeys.IsLocalKey(node.PublicKey()) { obj, err = p.localObject(egCtx, objID) } else { obj, err = p.remoteObject(egCtx, node, objID) diff --git a/pkg/services/session/storage/persistent/storage.go b/pkg/services/session/storage/persistent/storage.go index d312ea0ea7..132d624459 100644 --- a/pkg/services/session/storage/persistent/storage.go +++ b/pkg/services/session/storage/persistent/storage.go @@ -64,7 +64,7 @@ func NewTokenStore(path string, opts ...Option) (*TokenStore, error) { // enable encryption if it // was configured so if cfg.privateKey != nil { - rawKey := make([]byte, (cfg.privateKey.Curve.Params().N.BitLen()+7)/8) + rawKey := make([]byte, (cfg.privateKey.Params().N.BitLen()+7)/8) cfg.privateKey.D.FillBytes(rawKey) c, err := aes.NewCipher(rawKey) diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index d250f577ac..462c8554f8 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -48,7 +48,7 @@ func (c *clientCache) init(pk *ecdsa.PrivateKey, ds *internalNet.DialerSource) { func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceClient, error) { c.Lock() - ccInt, ok := c.LRU.Get(netmapAddr) + ccInt, ok := c.Get(netmapAddr) c.Unlock() if ok { @@ -71,9 +71,9 @@ func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceCl c.Lock() if err != nil { - c.LRU.Add(netmapAddr, cacheItem{cc: nil, lastTry: lastTry}) + c.Add(netmapAddr, cacheItem{cc: nil, lastTry: lastTry}) } else { - c.LRU.Add(netmapAddr, cacheItem{cc: cc, lastTry: lastTry}) + c.Add(netmapAddr, cacheItem{cc: cc, lastTry: lastTry}) } c.Unlock() diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 164815c760..01a4ffde03 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -202,7 +202,7 @@ func newApplyRequest(op *movePair) *ApplyRequest { TreeId: op.treeID, Operation: &LogMove{ ParentId: op.op.Parent, - Meta: op.op.Meta.Bytes(), + Meta: op.op.Bytes(), ChildId: op.op.Child, }, }, diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 85bb03a28f..a00c8c1cde 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -687,7 +687,7 @@ func (s *Service) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) Body: &GetOpLogResponse_Body{ Operation: &LogMove{ ParentId: lm.Parent, - Meta: lm.Meta.Bytes(), + Meta: lm.Bytes(), ChildId: lm.Child, }, }, diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 8abdafaa73..c3796fbd40 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -245,7 +245,7 @@ func (s *Service) startStream(ctx context.Context, cid cid.ID, treeID string, Parent: lm.GetParentId(), Child: lm.GetChildId(), } - if err := m.Meta.FromBytes(lm.GetMeta()); err != nil { + if err := m.FromBytes(lm.GetMeta()); err != nil { return err } select { @@ -415,7 +415,7 @@ func (s *Service) syncLoop(ctx context.Context) { start := time.Now() - cnrs, err := s.cfg.cnrSource.List(ctx) + cnrs, err := s.cnrSource.List(ctx) if err != nil { s.log.Error(ctx, logs.TreeCouldNotFetchContainers, zap.Error(err)) s.metrics.AddSyncDuration(time.Since(start), false) From b0ef737a74d9e0b789be24db0830fa927e7078e0 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 16:58:21 +0300 Subject: [PATCH 1338/1413] [#1689] linter: Fix testifylint warning: 'len: use require.Len' Change-Id: I7a08f09c169ac237647dcb20b0737f1c51c441ad Signed-off-by: Alexander Chuprov --- .../blobstor/internal/blobstortest/iterate.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go index c11d0888b5..d54c54f59d 100644 --- a/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go +++ b/pkg/local_object_storage/blobstor/internal/blobstortest/iterate.go @@ -50,7 +50,7 @@ func runTestNormalHandler(t *testing.T, s common.Storage, objects []objectDesc) _, err := s.Iterate(context.Background(), iterPrm) require.NoError(t, err) - require.Equal(t, len(objects), len(seen)) + require.Len(t, objects, len(seen)) for i := range objects { d, ok := seen[objects[i].addr.String()] require.True(t, ok) From f4696e8964786dd5489fdce1456eccab010d02b8 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 17:03:19 +0300 Subject: [PATCH 1339/1413] [#1689] linter: Fix staticcheck warning: 'Use fmt.Fprintf(...) instead of WriteString(fmt.Sprintf(...))' Change-Id: I253ab717885cb01b4a2e471147e883ee351be277 Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/modules/control/evacuation.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-cli/modules/control/evacuation.go b/cmd/frostfs-cli/modules/control/evacuation.go index 8032bf09a9..b8d7eb046c 100644 --- a/cmd/frostfs-cli/modules/control/evacuation.go +++ b/cmd/frostfs-cli/modules/control/evacuation.go @@ -296,7 +296,7 @@ func appendEstimation(sb *strings.Builder, resp *control.GetShardEvacuationStatu leftSeconds := avgObjEvacuationTimeSeconds * objectsLeft leftMinutes := int(leftSeconds / 60) - sb.WriteString(fmt.Sprintf(" Estimated time left: %d minutes.", leftMinutes)) + fmt.Fprintf(sb, " Estimated time left: %d minutes.", leftMinutes) } func appendDuration(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { @@ -305,20 +305,20 @@ func appendDuration(sb *strings.Builder, resp *control.GetShardEvacuationStatusR hour := int(duration.Seconds() / 3600) minute := int(duration.Seconds()/60) % 60 second := int(duration.Seconds()) % 60 - sb.WriteString(fmt.Sprintf(" Duration: %02d:%02d:%02d.", hour, minute, second)) + fmt.Fprintf(sb, " Duration: %02d:%02d:%02d.", hour, minute, second) } } func appendStartedAt(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { if resp.GetBody().GetStartedAt() != nil { startedAt := time.Unix(resp.GetBody().GetStartedAt().GetValue(), 0).UTC() - sb.WriteString(fmt.Sprintf(" Started at: %s UTC.", startedAt.Format(time.RFC3339))) + fmt.Fprintf(sb, " Started at: %s UTC.", startedAt.Format(time.RFC3339)) } } func appendError(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { if len(resp.GetBody().GetErrorMessage()) > 0 { - sb.WriteString(fmt.Sprintf(" Error: %s.", resp.GetBody().GetErrorMessage())) + fmt.Fprintf(sb, " Error: %s.", resp.GetBody().GetErrorMessage()) } } @@ -332,7 +332,7 @@ func appendStatus(sb *strings.Builder, resp *control.GetShardEvacuationStatusRes default: status = "undefined" } - sb.WriteString(fmt.Sprintf(" Status: %s.", status)) + fmt.Fprintf(sb, " Status: %s.", status) } func appendShardIDs(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { @@ -350,14 +350,14 @@ func appendShardIDs(sb *strings.Builder, resp *control.GetShardEvacuationStatusR } func appendCounts(sb *strings.Builder, resp *control.GetShardEvacuationStatusResponse) { - sb.WriteString(fmt.Sprintf(" Evacuated %d objects out of %d, failed to evacuate: %d, skipped: %d; evacuated %d trees out of %d, failed to evacuate: %d.", + fmt.Fprintf(sb, " Evacuated %d objects out of %d, failed to evacuate: %d, skipped: %d; evacuated %d trees out of %d, failed to evacuate: %d.", resp.GetBody().GetEvacuatedObjects(), resp.GetBody().GetTotalObjects(), resp.GetBody().GetFailedObjects(), resp.GetBody().GetSkippedObjects(), resp.GetBody().GetEvacuatedTrees(), resp.GetBody().GetTotalTrees(), - resp.GetBody().GetFailedTrees())) + resp.GetBody().GetFailedTrees()) } func initControlEvacuationShardCmd() { From 4c03561aa20c2bbc2e311c9438fd7979ff1d96db Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 7 Apr 2025 18:48:36 +0300 Subject: [PATCH 1340/1413] [#1693] internal/assert: Add `False` and `NoError` checks Change-Id: Ib3ab1671eeff8e8917673513477f158cadbb4287 Signed-off-by: Ekaterina Lebedeva --- internal/assert/cond.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/internal/assert/cond.go b/internal/assert/cond.go index 701036fa87..c6a034f94f 100644 --- a/internal/assert/cond.go +++ b/internal/assert/cond.go @@ -1,9 +1,25 @@ package assert -import "strings" +import ( + "fmt" + "strings" +) func True(cond bool, details ...string) { if !cond { panic(strings.Join(details, " ")) } } + +func False(cond bool, details ...string) { + if cond { + panic(strings.Join(details, " ")) + } +} + +func NoError(err error, details ...string) { + if err != nil { + content := fmt.Sprintf("BUG: %v: %s", err, strings.Join(details, " ")) + panic(content) + } +} From 0e1b01b15ff21c07d809dbed00f23c6b2377bf4e Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Wed, 2 Apr 2025 19:06:10 +0300 Subject: [PATCH 1341/1413] [#1693] cli/adm: Replace conditional panics with asserts Change-Id: I3a46f7ac6d9e4ff51bb490e6fcfc07957418f1a7 Signed-off-by: Ekaterina Lebedeva --- .../internal/modules/morph/balance/balance.go | 9 +++----- .../modules/morph/container/container.go | 5 ++-- .../internal/modules/morph/contract/deploy.go | 10 ++++---- .../modules/morph/contract/dump_hashes.go | 9 +++----- .../modules/morph/helper/initialize_ctx.go | 23 ++++++++----------- .../modules/morph/helper/local_client.go | 9 +++----- .../morph/initialize/initialize_nns.go | 5 ++-- .../morph/initialize/initialize_register.go | 5 ++-- 8 files changed, 28 insertions(+), 47 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go index be42f2aa5f..23dba14f49 100644 --- a/cmd/frostfs-adm/internal/modules/morph/balance/balance.go +++ b/cmd/frostfs-adm/internal/modules/morph/balance/balance.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" "github.com/nspcc-dev/neo-go/pkg/core/native/noderoles" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -161,9 +162,7 @@ func printAlphabetContractBalances(cmd *cobra.Command, c helper.Client, inv *inv helper.GetAlphabetNNSDomain(i), int64(nns.TXT)) } - if w.Err != nil { - panic(w.Err) - } + assert.NoError(w.Err) alphaRes, err := c.InvokeScript(w.Bytes(), nil) if err != nil { @@ -226,9 +225,7 @@ func fetchBalances(c *invoker.Invoker, gasHash util.Uint160, accounts []accBalan for i := range accounts { emit.AppCall(w.BinWriter, gasHash, "balanceOf", callflag.ReadStates, accounts[i].scriptHash) } - if w.Err != nil { - panic(w.Err) - } + assert.NoError(w.Err) res, err := c.Run(w.Bytes()) if err != nil || res.State != vmstate.Halt.String() || len(res.Stack) != len(accounts) { diff --git a/cmd/frostfs-adm/internal/modules/morph/container/container.go b/cmd/frostfs-adm/internal/modules/morph/container/container.go index e72dc15e9c..79685f1119 100644 --- a/cmd/frostfs-adm/internal/modules/morph/container/container.go +++ b/cmd/frostfs-adm/internal/modules/morph/container/container.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/io" @@ -235,9 +236,7 @@ func restoreOrPutContainers(containers []Container, isOK func([]byte) bool, cmd putContainer(bw, ch, cnt) - if bw.Err != nil { - panic(bw.Err) - } + assert.NoError(bw.Err) if err := wCtx.SendConsensusTx(bw.Bytes()); err != nil { return err diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go index 5adb480da9..543b5fcb34 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/deploy.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "github.com/nspcc-dev/neo-go/cli/cmdargs" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/encoding/address" @@ -120,9 +121,7 @@ func deployContractCmd(cmd *cobra.Command, args []string) error { } } - if writer.Err != nil { - panic(fmt.Errorf("BUG: can't create deployment script: %w", writer.Err)) - } + assert.NoError(writer.Err, "can't create deployment script") if err := c.SendCommitteeTx(writer.Bytes(), false); err != nil { return err @@ -173,9 +172,8 @@ func registerNNS(nnsCs *state.Contract, c *helper.InitializeContext, zone string domain, int64(nns.TXT), address.Uint160ToString(cs.Hash)) } - if bw.Err != nil { - panic(fmt.Errorf("BUG: can't create deployment script: %w", writer.Err)) - } else if bw.Len() != start { + assert.NoError(bw.Err, "can't create deployment script") + if bw.Len() != start { writer.WriteBytes(bw.Bytes()) emit.Opcodes(writer.BinWriter, opcode.LDSFLD0, opcode.PUSH1, opcode.PACK) emit.AppCallNoArgs(writer.BinWriter, nnsCs.Hash, "setPrice", callflag.All) diff --git a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go index 7630a226e0..fde58fd2ba 100644 --- a/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go +++ b/cmd/frostfs-adm/internal/modules/morph/contract/dump_hashes.go @@ -11,6 +11,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker" @@ -236,9 +237,7 @@ func fillContractVersion(cmd *cobra.Command, c helper.Client, infos []contractDu } else { sub.Reset() emit.AppCall(sub.BinWriter, infos[i].hash, "version", callflag.NoneFlag) - if sub.Err != nil { - panic(fmt.Errorf("BUG: can't create version script: %w", bw.Err)) - } + assert.NoError(sub.Err, "can't create version script") script := sub.Bytes() emit.Instruction(bw.BinWriter, opcode.TRY, []byte{byte(3 + len(script) + 2), 0}) @@ -248,9 +247,7 @@ func fillContractVersion(cmd *cobra.Command, c helper.Client, infos []contractDu } } emit.Opcodes(bw.BinWriter, opcode.NOP) // for the last ENDTRY target - if bw.Err != nil { - panic(fmt.Errorf("BUG: can't create version script: %w", bw.Err)) - } + assert.NoError(bw.Err, "can't create version script") res, err := c.InvokeScript(bw.Bytes(), nil) if err != nil { diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go index 27052697f1..da5ffedae1 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/initialize_ctx.go @@ -13,6 +13,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -375,9 +376,7 @@ func (c *InitializeContext) sendMultiTx(script []byte, tryGroup bool, withConsen } act, err = actor.New(c.Client, signers) } else { - if withConsensus { - panic("BUG: should never happen") - } + assert.False(withConsensus, "BUG: should never happen") act, err = c.CommitteeAct, nil } if err != nil { @@ -411,11 +410,9 @@ func (c *InitializeContext) MultiSignAndSend(tx *transaction.Transaction, accTyp func (c *InitializeContext) MultiSign(tx *transaction.Transaction, accType string) error { version, err := c.Client.GetVersion() - if err != nil { - // error appears only if client - // has not been initialized - panic(err) - } + // error appears only if client + // has not been initialized + assert.NoError(err) network := version.Protocol.Network // Use parameter context to avoid dealing with signature order. @@ -447,12 +444,12 @@ func (c *InitializeContext) MultiSign(tx *transaction.Transaction, accType strin for i := range tx.Signers { if tx.Signers[i].Account == h { + assert.True(i <= len(tx.Scripts), "BUG: invalid signing order") if i < len(tx.Scripts) { tx.Scripts[i] = *w - } else if i == len(tx.Scripts) { + } + if i == len(tx.Scripts) { tx.Scripts = append(tx.Scripts, *w) - } else { - panic("BUG: invalid signing order") } return nil } @@ -510,9 +507,7 @@ func (c *InitializeContext) NNSRegisterDomainScript(nnsHash, expectedHash util.U int64(constants.DefaultExpirationTime), constants.NNSTtlDefVal) emit.Opcodes(bw.BinWriter, opcode.ASSERT) - if bw.Err != nil { - panic(bw.Err) - } + assert.NoError(bw.Err) return bw.Bytes(), false, nil } diff --git a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go index d0a05d5c74..46611c1779 100644 --- a/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go +++ b/cmd/frostfs-adm/internal/modules/morph/helper/local_client.go @@ -10,6 +10,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/core" @@ -316,9 +317,7 @@ func (l *LocalClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint func (l *LocalClient) putTransactions() error { // 1. Prepare new block. lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash()) - if err != nil { - panic(err) - } + assert.NoError(err) defer func() { l.transactions = l.transactions[:0] }() b := &block.Block{ @@ -359,9 +358,7 @@ func InvokeFunction(c Client, h util.Uint160, method string, parameters []any, s w := io.NewBufBinWriter() emit.Array(w.BinWriter, parameters...) emit.AppCallNoArgs(w.BinWriter, h, method, callflag.All) - if w.Err != nil { - panic(fmt.Sprintf("BUG: invalid parameters for '%s': %v", method, w.Err)) - } + assert.True(w.Err == nil, fmt.Sprintf("BUG: invalid parameters for '%s': %v", method, w.Err)) return c.InvokeScript(w.Bytes(), signers) } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go index e127ca5453..176356378d 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_nns.go @@ -7,6 +7,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-contract/nns" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" morphClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -111,9 +112,7 @@ func wrapRegisterScriptWithPrice(w *io.BufBinWriter, nnsHash util.Uint160, s []b emit.Opcodes(w.BinWriter, opcode.LDSFLD0, opcode.PUSH1, opcode.PACK) emit.AppCallNoArgs(w.BinWriter, nnsHash, "setPrice", callflag.All) - if w.Err != nil { - panic(fmt.Errorf("BUG: can't wrap register script: %w", w.Err)) - } + assert.NoError(w.Err, "can't wrap register script") } func nnsRegisterDomain(c *helper.InitializeContext, nnsHash, expectedHash util.Uint160, domain string) error { diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go index 46e6621d2e..7b7597d911 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize/initialize_register.go @@ -6,6 +6,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/constants" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/helper" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -39,9 +40,7 @@ func registerCandidateRange(c *helper.InitializeContext, start, end int) error { emit.Opcodes(w.BinWriter, opcode.ASSERT) } emit.AppCall(w.BinWriter, neo.Hash, "setRegisterPrice", callflag.States, regPrice) - if w.Err != nil { - panic(fmt.Sprintf("BUG: %v", w.Err)) - } + assert.NoError(w.Err) signers := []actor.SignerAccount{{ Signer: c.GetSigner(false, c.CommitteeAcc), From 766d9ec46b7b7da10dbbd4bf257db6f5f799a968 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 7 Apr 2025 19:25:57 +0300 Subject: [PATCH 1342/1413] [#1693] cli/lens: Replace conditional panics with asserts Change-Id: Id827da0cd9eef66efd806be6c9bc61044175a971 Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-lens/internal/schema/common/schema.go | 8 +++----- cmd/frostfs-lens/internal/tui/records.go | 5 ++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-lens/internal/schema/common/schema.go b/cmd/frostfs-lens/internal/schema/common/schema.go index 9bad190320..077a687850 100644 --- a/cmd/frostfs-lens/internal/schema/common/schema.go +++ b/cmd/frostfs-lens/internal/schema/common/schema.go @@ -3,6 +3,8 @@ package common import ( "errors" "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" ) type FilterResult byte @@ -71,11 +73,7 @@ func (fp FallbackParser) ToParser() Parser { func (p Parser) ToFallbackParser() FallbackParser { return func(key, value []byte) (SchemaEntry, Parser) { entry, next, err := p(key, value) - if err != nil { - panic(fmt.Errorf( - "couldn't use that parser as a fallback parser, it returned an error: %w", err, - )) - } + assert.NoError(err, "couldn't use that parser as a fallback parser") return entry, next } } diff --git a/cmd/frostfs-lens/internal/tui/records.go b/cmd/frostfs-lens/internal/tui/records.go index 5f61df8841..a4d392ab31 100644 --- a/cmd/frostfs-lens/internal/tui/records.go +++ b/cmd/frostfs-lens/internal/tui/records.go @@ -8,6 +8,7 @@ import ( "sync" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-lens/internal/schema/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) @@ -94,9 +95,7 @@ func (v *RecordsView) Mount(ctx context.Context) error { } func (v *RecordsView) Unmount() { - if v.onUnmount == nil { - panic("try to unmount not mounted component") - } + assert.False(v.onUnmount == nil, "try to unmount not mounted component") v.onUnmount() v.onUnmount = nil } From 17cba3387e926c50ae47a224af47f3f6668134f4 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 8 Apr 2025 19:57:43 +0300 Subject: [PATCH 1343/1413] [#1332] cli/playground: Prevent prompt artifacts by writing to 'readline' stdout Change-Id: I1c3cbb0b762f29c0995d3f6fc79bae5246ee7bc3 Signed-off-by: Alexander Chuprov --- .../modules/container/policy_playground.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index dcd755510d..825e1d222e 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -19,8 +19,9 @@ import ( ) type policyPlaygroundREPL struct { - cmd *cobra.Command - nodes map[string]netmap.NodeInfo + cmd *cobra.Command + nodes map[string]netmap.NodeInfo + console *readline.Instance } func newPolicyPlaygroundREPL(cmd *cobra.Command) *policyPlaygroundREPL { @@ -40,7 +41,7 @@ func (repl *policyPlaygroundREPL) handleLs(args []string) error { node.IterateAttributes(func(k, v string) { attrs = append(attrs, fmt.Sprintf("%s:%q", k, v)) }) - fmt.Printf("\t%2d: id=%s attrs={%v}\n", i, id, strings.Join(attrs, " ")) + fmt.Fprintf(repl.console, "\t%2d: id=%s attrs={%v}\n", i, id, strings.Join(attrs, " ")) i++ } return nil @@ -147,7 +148,7 @@ func (repl *policyPlaygroundREPL) handleEval(args []string) error { for _, node := range ns { ids = append(ids, hex.EncodeToString(node.PublicKey())) } - fmt.Printf("\t%2d: %v\n", i+1, ids) + fmt.Fprintf(repl.console, "\t%2d: %v\n", i+1, ids) } return nil @@ -208,6 +209,7 @@ func (repl *policyPlaygroundREPL) run() error { if err != nil { return fmt.Errorf("error initializing readline: %w", err) } + repl.console = rl defer rl.Close() var exit bool @@ -232,10 +234,10 @@ func (repl *policyPlaygroundREPL) run() error { cmd := parts[0] if handler, exists := cmdHandlers[cmd]; exists { if err := handler(parts[1:]); err != nil { - fmt.Printf("error: %v\n", err) + fmt.Fprintf(repl.console, "error: %v\n", err) } } else { - fmt.Printf("error: unknown command %q\n", cmd) + fmt.Fprintf(repl.console, "error: unknown command %q\n", cmd) } } } From 46fd5e17b2366c22dba259d1349c6e3fa8662cb6 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 8 Apr 2025 20:23:22 +0300 Subject: [PATCH 1344/1413] [#1332] cli/playground: Add help Change-Id: I6160cfddf427b161619e4b96ceec8396b75c4d08 Signed-off-by: Alexander Chuprov --- .../modules/container/policy_playground.go | 119 ++++++++++++++++-- 1 file changed, 109 insertions(+), 10 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 825e1d222e..f747b3252b 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -5,7 +5,9 @@ import ( "encoding/json" "errors" "fmt" + "maps" "os" + "slices" "strings" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" @@ -154,6 +156,23 @@ func (repl *policyPlaygroundREPL) handleEval(args []string) error { return nil } +func (repl *policyPlaygroundREPL) handleHelp(args []string) error { + if len(args) != 0 { + if _, ok := commands[args[0]]; !ok { + return fmt.Errorf("unknown command: %q", args[0]) + } + fmt.Fprintln(repl.console, commands[args[0]].usage) + return nil + } + + commandList := slices.Collect(maps.Keys(commands)) + slices.Sort(commandList) + for _, command := range commandList { + fmt.Fprintf(repl.console, "%s: %s\n", command, commands[command].descriprion) + } + return nil +} + func (repl *policyPlaygroundREPL) netMap() netmap.NetMap { var nm netmap.NetMap var nodes []netmap.NodeInfo @@ -164,15 +183,82 @@ func (repl *policyPlaygroundREPL) netMap() netmap.NetMap { return nm } -var policyPlaygroundCompleter = readline.NewPrefixCompleter( - readline.PcItem("list"), - readline.PcItem("ls"), - readline.PcItem("add"), - readline.PcItem("load"), - readline.PcItem("remove"), - readline.PcItem("rm"), - readline.PcItem("eval"), -) +type commandDescription struct { + descriprion string + usage string +} + +var commands = map[string]commandDescription{ + "list": { + descriprion: "Display all nodes in the netmap", + usage: `Display all nodes in the netmap +Example of usage: + list + 1: id=03ff65b6ae79134a4dce9d0d39d3851e9bab4ee97abf86e81e1c5bbc50cd2826ae attrs={Continent:"Europe" Country:"Poland"} + 2: id=02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3 attrs={Continent:"Antarctica" Country:"Heard Island"} +`, + }, + + "ls": { + descriprion: "Display all nodes in the netmap", + usage: `Display all nodes in the netmap +Example of usage: + ls + 1: id=03ff65b6ae79134a4dce9d0d39d3851e9bab4ee97abf86e81e1c5bbc50cd2826ae attrs={Continent:"Europe" Country:"Poland"} + 2: id=02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3 attrs={Continent:"Antarctica" Country:"Heard Island"} +`, + }, + + "add": { + descriprion: "Add a new node: add attr=value", + usage: `Add a new node +Example of usage: + add 03ff65b6ae79134a4dce9d0d39d3851e9bab4ee97abf86e81e1c5bbc50cd2826ae continent:Europe country:Poland`, + }, + + "load": { + descriprion: "Load netmap from file: load ", + usage: `Load netmap from file +Example of usage: + load "netmap.json" +File format (netmap.json): +{ + "03ff65b6ae79134a4dce9d0d39d3851e9bab4ee97abf86e81e1c5bbc50cd2826ae": { + "continent": "Europe", + "country": "Poland" + }, + "02ac920cd7df0b61b289072e6b946e2da4e1a31b9ab1c621bb475e30fa4ab102c3": { + "continent": "Antarctica", + "country": "Heard Island" + } +}`, + }, + + "remove": { + descriprion: "Remove a node: remove ", + usage: `Remove a node +Example of usage: + remove 03ff65b6ae79134a4dce9d0d39d3851e9bab4ee97abf86e81e1c5bbc50cd2826ae`, + }, + + "rm": { + descriprion: "Remove a node: rm ", + usage: `Remove a node +Example of usage: + rm 03ff65b6ae79134a4dce9d0d39d3851e9bab4ee97abf86e81e1c5bbc50cd2826ae`, + }, + + "eval": { + descriprion: "Evaluate a policy: eval ", + usage: `Evaluate a policy +Example of usage: + eval REP 2`, + }, + + "help": { + descriprion: "Show available commands", + }, +} func (repl *policyPlaygroundREPL) run() error { if len(viper.GetString(commonflags.RPC)) > 0 { @@ -199,12 +285,25 @@ func (repl *policyPlaygroundREPL) run() error { "remove": repl.handleRemove, "rm": repl.handleRemove, "eval": repl.handleEval, + "help": repl.handleHelp, } + var cfgCompleter []readline.PrefixCompleterInterface + var helpSubItems []readline.PrefixCompleterInterface + + for name := range commands { + if name != "help" { + cfgCompleter = append(cfgCompleter, readline.PcItem(name)) + helpSubItems = append(helpSubItems, readline.PcItem(name)) + } + } + + cfgCompleter = append(cfgCompleter, readline.PcItem("help", helpSubItems...)) + completer := readline.NewPrefixCompleter(cfgCompleter...) rl, err := readline.NewEx(&readline.Config{ Prompt: "> ", InterruptPrompt: "^C", - AutoComplete: policyPlaygroundCompleter, + AutoComplete: completer, }) if err != nil { return fmt.Errorf("error initializing readline: %w", err) From faec499b38a8ff06bc5c38fa31b4e75139d09d7d Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 17:19:34 +0300 Subject: [PATCH 1345/1413] [#1689] linter: Fix staticcheck warning: 'variable naming format' Change-Id: I8f8b63a6a5f9b6feb7c91f70fe8ac092575b145c Signed-off-by: Alexander Chuprov --- .../blobstor/blobovniczatree/manager.go | 26 +++++++++---------- .../blobstor/blobovniczatree/rebuild.go | 4 +-- pkg/local_object_storage/pilorama/inmemory.go | 4 +-- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go index f2f9509adb..6438f715b9 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/manager.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/manager.go @@ -141,8 +141,8 @@ func (b *sharedDB) SystemPath() string { return b.path } -// levelDbManager stores pointers of the sharedDB's for the leaf directory of the blobovnicza tree. -type levelDbManager struct { +// levelDBManager stores pointers of the sharedDB's for the leaf directory of the blobovnicza tree. +type levelDBManager struct { dbMtx *sync.RWMutex databases map[uint64]*sharedDB @@ -157,8 +157,8 @@ type levelDbManager struct { func newLevelDBManager(options []blobovnicza.Option, rootPath string, lvlPath string, readOnly bool, metrics blobovnicza.Metrics, openDBCounter *openDBCounter, closedFlag *atomic.Bool, log *logger.Logger, -) *levelDbManager { - result := &levelDbManager{ +) *levelDBManager { + result := &levelDBManager{ databases: make(map[uint64]*sharedDB), dbMtx: &sync.RWMutex{}, @@ -173,7 +173,7 @@ func newLevelDBManager(options []blobovnicza.Option, rootPath string, lvlPath st return result } -func (m *levelDbManager) GetByIndex(idx uint64) *sharedDB { +func (m *levelDBManager) GetByIndex(idx uint64) *sharedDB { res := m.getDBIfExists(idx) if res != nil { return res @@ -181,14 +181,14 @@ func (m *levelDbManager) GetByIndex(idx uint64) *sharedDB { return m.getOrCreateDB(idx) } -func (m *levelDbManager) getDBIfExists(idx uint64) *sharedDB { +func (m *levelDBManager) getDBIfExists(idx uint64) *sharedDB { m.dbMtx.RLock() defer m.dbMtx.RUnlock() return m.databases[idx] } -func (m *levelDbManager) getOrCreateDB(idx uint64) *sharedDB { +func (m *levelDBManager) getOrCreateDB(idx uint64) *sharedDB { m.dbMtx.Lock() defer m.dbMtx.Unlock() @@ -202,7 +202,7 @@ func (m *levelDbManager) getOrCreateDB(idx uint64) *sharedDB { return db } -func (m *levelDbManager) hasAnyDB() bool { +func (m *levelDBManager) hasAnyDB() bool { m.dbMtx.RLock() defer m.dbMtx.RUnlock() @@ -213,7 +213,7 @@ func (m *levelDbManager) hasAnyDB() bool { // // The blobovnicza opens at the first request, closes after the last request. type dbManager struct { - levelToManager map[string]*levelDbManager + levelToManager map[string]*levelDBManager levelToManagerGuard *sync.RWMutex closedFlag *atomic.Bool dbCounter *openDBCounter @@ -231,7 +231,7 @@ func newDBManager(rootPath string, options []blobovnicza.Option, readOnly bool, options: options, readOnly: readOnly, metrics: metrics, - levelToManager: make(map[string]*levelDbManager), + levelToManager: make(map[string]*levelDBManager), levelToManagerGuard: &sync.RWMutex{}, log: log, closedFlag: &atomic.Bool{}, @@ -266,7 +266,7 @@ func (m *dbManager) Close() { m.dbCounter.WaitUntilAllClosed() } -func (m *dbManager) getLevelManager(lvlPath string) *levelDbManager { +func (m *dbManager) getLevelManager(lvlPath string) *levelDBManager { result := m.getLevelManagerIfExists(lvlPath) if result != nil { return result @@ -274,14 +274,14 @@ func (m *dbManager) getLevelManager(lvlPath string) *levelDbManager { return m.getOrCreateLevelManager(lvlPath) } -func (m *dbManager) getLevelManagerIfExists(lvlPath string) *levelDbManager { +func (m *dbManager) getLevelManagerIfExists(lvlPath string) *levelDBManager { m.levelToManagerGuard.RLock() defer m.levelToManagerGuard.RUnlock() return m.levelToManager[lvlPath] } -func (m *dbManager) getOrCreateLevelManager(lvlPath string) *levelDbManager { +func (m *dbManager) getOrCreateLevelManager(lvlPath string) *levelDBManager { m.levelToManagerGuard.Lock() defer m.levelToManagerGuard.Unlock() diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index 7ef3317fd3..d2eef20744 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -328,7 +328,7 @@ func (b *Blobovniczas) moveObject(ctx context.Context, source *blobovnicza.Blobo return nil } -func (b *Blobovniczas) dropDB(ctx context.Context, path string, shDb *sharedDB) (bool, error) { +func (b *Blobovniczas) dropDB(ctx context.Context, path string, shDB *sharedDB) (bool, error) { select { case <-ctx.Done(): return false, ctx.Err() @@ -341,7 +341,7 @@ func (b *Blobovniczas) dropDB(ctx context.Context, path string, shDb *sharedDB) b.dbFilesGuard.Lock() defer b.dbFilesGuard.Unlock() - if err := shDb.CloseAndRemoveFile(ctx); err != nil { + if err := shDB.CloseAndRemoveFile(ctx); err != nil { return false, err } b.commondbManager.CleanResources(path) diff --git a/pkg/local_object_storage/pilorama/inmemory.go b/pkg/local_object_storage/pilorama/inmemory.go index f74d12a1b6..28b7faec8c 100644 --- a/pkg/local_object_storage/pilorama/inmemory.go +++ b/pkg/local_object_storage/pilorama/inmemory.go @@ -192,7 +192,7 @@ func (t tree) getByPath(attr string, path []string, latest bool) []Node { } var nodes []Node - var lastTs Timestamp + var lastTS Timestamp children := t.getChildren(curNode) for i := range children { @@ -200,7 +200,7 @@ func (t tree) getByPath(attr string, path []string, latest bool) []Node { fileName := string(info.Meta.GetAttr(attr)) if fileName == path[len(path)-1] { if latest { - if info.Meta.Time >= lastTs { + if info.Meta.Time >= lastTS { nodes = append(nodes[:0], children[i]) } } else { From c274bbeb7c0b6957ccc5d3f507b5b5432f91ffd6 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 17:25:59 +0300 Subject: [PATCH 1346/1413] [#1689] linter: Fix staticcheck warning: 'methods on the same type should have the same receiver name' Change-Id: I25e9432987f73061c1506a184a82065e37885861 Signed-off-by: Alexander Chuprov --- pkg/services/object/get/get.go | 42 +++++++++++++++--------------- pkg/services/object/put/service.go | 4 +-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pkg/services/object/get/get.go b/pkg/services/object/get/get.go index 9676fd9144..3a50308c22 100644 --- a/pkg/services/object/get/get.go +++ b/pkg/services/object/get/get.go @@ -90,48 +90,48 @@ func (s *Service) get(ctx context.Context, prm RequestParameters) error { return exec.err } -func (exec *request) execute(ctx context.Context) { - exec.log.Debug(ctx, logs.ServingRequest) +func (r *request) execute(ctx context.Context) { + r.log.Debug(ctx, logs.ServingRequest) // perform local operation - exec.executeLocal(ctx) + r.executeLocal(ctx) - exec.analyzeStatus(ctx, true) + r.analyzeStatus(ctx, true) } -func (exec *request) analyzeStatus(ctx context.Context, execCnr bool) { +func (r *request) analyzeStatus(ctx context.Context, execCnr bool) { // analyze local result - switch exec.status { + switch r.status { case statusOK: - exec.log.Debug(ctx, logs.OperationFinishedSuccessfully) + r.log.Debug(ctx, logs.OperationFinishedSuccessfully) case statusINHUMED: - exec.log.Debug(ctx, logs.GetRequestedObjectWasMarkedAsRemoved) + r.log.Debug(ctx, logs.GetRequestedObjectWasMarkedAsRemoved) case statusVIRTUAL: - exec.log.Debug(ctx, logs.GetRequestedObjectIsVirtual) - exec.assemble(ctx) + r.log.Debug(ctx, logs.GetRequestedObjectIsVirtual) + r.assemble(ctx) case statusOutOfRange: - exec.log.Debug(ctx, logs.GetRequestedRangeIsOutOfObjectBounds) + r.log.Debug(ctx, logs.GetRequestedRangeIsOutOfObjectBounds) case statusEC: - exec.log.Debug(ctx, logs.GetRequestedObjectIsEC) - if exec.isRaw() && execCnr { - exec.executeOnContainer(ctx) - exec.analyzeStatus(ctx, false) + r.log.Debug(ctx, logs.GetRequestedObjectIsEC) + if r.isRaw() && execCnr { + r.executeOnContainer(ctx) + r.analyzeStatus(ctx, false) } - exec.assembleEC(ctx) + r.assembleEC(ctx) default: - exec.log.Debug(ctx, logs.OperationFinishedWithError, - zap.Error(exec.err), + r.log.Debug(ctx, logs.OperationFinishedWithError, + zap.Error(r.err), ) var errAccessDenied *apistatus.ObjectAccessDenied - if execCnr && errors.As(exec.err, &errAccessDenied) { + if execCnr && errors.As(r.err, &errAccessDenied) { // Local get can't return access denied error, so this error was returned by // write to the output stream. So there is no need to try to find object on other nodes. return } if execCnr { - exec.executeOnContainer(ctx) - exec.analyzeStatus(ctx, false) + r.executeOnContainer(ctx) + r.analyzeStatus(ctx, false) } } } diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index 099486b3fd..7aeb5857df 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -56,8 +56,8 @@ func NewService(ks *objutil.KeyStorage, } } -func (p *Service) Put() (*Streamer, error) { +func (s *Service) Put() (*Streamer, error) { return &Streamer{ - Config: p.Config, + Config: s.Config, }, nil } From 2394ae6ce006acf85e3914fc29c3dd284be9ce3c Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 17:28:27 +0300 Subject: [PATCH 1347/1413] [#1689] linter: Fix staticcheck warning: 'could lift into loop condition' Change-Id: I4ff3cda54861d857740203d6994872998a22d5d5 Signed-off-by: Alexander Chuprov --- pkg/services/object/get/container.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/pkg/services/object/get/container.go b/pkg/services/object/get/container.go index 0ee8aed537..dfb31133c4 100644 --- a/pkg/services/object/get/container.go +++ b/pkg/services/object/get/container.go @@ -28,16 +28,7 @@ func (r *request) executeOnContainer(ctx context.Context) { localStatus := r.status - for { - if r.processCurrentEpoch(ctx, localStatus) { - break - } - - // check the maximum depth has been reached - if lookupDepth == 0 { - break - } - + for !r.processCurrentEpoch(ctx, localStatus) && lookupDepth != 0 { lookupDepth-- // go to the previous epoch From dfdeedfc6fe2b557fe71d58960f954f30be2c339 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 17:32:23 +0300 Subject: [PATCH 1348/1413] [#1689] linter: Fix staticcheck warning: 'could apply De Morgan's law' Change-Id: Ife03172bad7d517dc99771250c3308a9fc0916b3 Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/modules/object/range.go | 2 +- pkg/morph/event/notary_preparator.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/range.go b/cmd/frostfs-cli/modules/object/range.go index be4fee4cf5..6ec508ae27 100644 --- a/cmd/frostfs-cli/modules/object/range.go +++ b/cmd/frostfs-cli/modules/object/range.go @@ -154,7 +154,7 @@ func printECInfoErr(cmd *cobra.Command, err error) bool { if ok { toJSON, _ := cmd.Flags().GetBool(commonflags.JSON) toProto, _ := cmd.Flags().GetBool("proto") - if !(toJSON || toProto) { + if !toJSON && !toProto { cmd.PrintErrln("Object is erasure-encoded, ec information received.") } printECInfo(cmd, errECInfo.ECInfo()) diff --git a/pkg/morph/event/notary_preparator.go b/pkg/morph/event/notary_preparator.go index 40f5984a97..b119736465 100644 --- a/pkg/morph/event/notary_preparator.go +++ b/pkg/morph/event/notary_preparator.go @@ -199,8 +199,8 @@ func (p Preparator) validateNotaryRequest(nr *payload.P2PNotaryRequest) error { // neo-go API) // // this check prevents notary flow recursion - if !(len(nr.MainTransaction.Scripts[1].InvocationScript) == 0 || - bytes.Equal(nr.MainTransaction.Scripts[1].InvocationScript, p.dummyInvocationScript)) { // compatibility with old version + if len(nr.MainTransaction.Scripts[1].InvocationScript) != 0 && + !bytes.Equal(nr.MainTransaction.Scripts[1].InvocationScript, p.dummyInvocationScript) { // compatibility with old version return ErrTXAlreadyHandled } @@ -364,8 +364,8 @@ func (p Preparator) validateWitnesses(w []transaction.Witness, alphaKeys keys.Pu // the last one must be a placeholder for notary contract witness last := len(w) - 1 - if !(len(w[last].InvocationScript) == 0 || // https://github.com/nspcc-dev/neo-go/pull/2981 - bytes.Equal(w[last].InvocationScript, p.dummyInvocationScript)) || // compatibility with old version + if (len(w[last].InvocationScript) != 0 && // https://github.com/nspcc-dev/neo-go/pull/2981 + !bytes.Equal(w[last].InvocationScript, p.dummyInvocationScript)) || // compatibility with old version len(w[last].VerificationScript) != 0 { return errIncorrectNotaryPlaceholder } From 4f9d237042233c8ae155ae3d2de4ea3911f8ce49 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Mon, 7 Apr 2025 17:36:54 +0300 Subject: [PATCH 1349/1413] [#1689] linter: Fix staticcheck warning: 'probably want to use time.Time.Equal instead' Change-Id: Idb119d3f4f167c9e42ed48633d301185589553ed Signed-off-by: Alexander Chuprov --- pkg/local_object_storage/engine/evacuate_limiter.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/local_object_storage/engine/evacuate_limiter.go b/pkg/local_object_storage/engine/evacuate_limiter.go index c74134500f..3dd7494be4 100644 --- a/pkg/local_object_storage/engine/evacuate_limiter.go +++ b/pkg/local_object_storage/engine/evacuate_limiter.go @@ -95,8 +95,7 @@ func (s *EvacuationState) StartedAt() *time.Time { if s == nil { return nil } - defaultTime := time.Time{} - if s.startedAt == defaultTime { + if s.startedAt.IsZero() { return nil } return &s.startedAt @@ -106,8 +105,7 @@ func (s *EvacuationState) FinishedAt() *time.Time { if s == nil { return nil } - defaultTime := time.Time{} - if s.finishedAt == defaultTime { + if s.finishedAt.IsZero() { return nil } return &s.finishedAt From fe29ed043a7d5e6e27256cf52490e1ec7ceedb40 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 8 Apr 2025 15:22:00 +0300 Subject: [PATCH 1350/1413] [#1689] linter: Fix staticcheck warning: 'could use tagged switch on *' Change-Id: Ia340ce1ccdd223eb87f7aefabfba62b7055f344d Signed-off-by: Alexander Chuprov --- pkg/services/object/ape/checker.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index ee46a6fe46..b96757def3 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -76,9 +76,10 @@ var errMissingOID = errors.New("object ID is not set") // CheckAPE prepares an APE-request and checks if it is permitted by policies. func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error { // APE check is ignored for some inter-node requests. - if prm.Role == nativeschema.PropertyValueContainerRoleContainer { + switch prm.Role { + case nativeschema.PropertyValueContainerRoleContainer: return nil - } else if prm.Role == nativeschema.PropertyValueContainerRoleIR { + case nativeschema.PropertyValueContainerRoleIR: switch prm.Method { case nativeschema.MethodGetObject, nativeschema.MethodHeadObject, From aed84b567caac5b2825888621ca170ee9dae0974 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Tue, 8 Apr 2025 15:23:51 +0300 Subject: [PATCH 1351/1413] [#1689] linter: Bump 'golangci-lint' to v2.0.2 Change-Id: Ib546af43845014785f0debce429a37d62e616539 Signed-off-by: Alexander Chuprov --- .golangci.yml | 179 ++++++++++++++++++++++++++------------------------ Makefile | 4 +- 2 files changed, 94 insertions(+), 89 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 18de494254..3ac4eb651b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,98 +1,103 @@ -# This file contains all available configuration options -# with their default values. - -# options for analysis running +version: "2" run: - # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 20m - - # include test files or not, default is true tests: false - -# output configuration options output: - # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" formats: - - format: tab - -# all available settings of specific linters -linters-settings: - exhaustive: - # indicates that switch statements are to be considered exhaustive if a - # 'default' case is present, even if all enum members aren't listed in the - # switch - default-signifies-exhaustive: true - gci: - sections: - - standard - - default - custom-order: true - staticcheck: - checks: ["all", "-SA1019"] # TODO Enable SA1019 after deprecated warning are fixed. - funlen: - lines: 80 # default 60 - statements: 60 # default 40 - gocognit: - min-complexity: 40 # default 30 - importas: - no-unaliased: true - no-extra-aliases: false - alias: - pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object - alias: objectSDK - unused: - field-writes-are-uses: false - exported-fields-are-used: false - local-variables-are-used: false - custom: - truecloudlab-linters: - path: bin/linters/external_linters.so - original-url: git.frostfs.info/TrueCloudLab/linters.git - settings: - noliteral: - target-methods : ["reportFlushError", "reportError"] - disable-packages: ["codes", "err", "res","exec"] - constants-package: "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" - + tab: + path: stdout + colors: false linters: + default: none enable: - # mandatory linters - - revive - - predeclared - - # some default golangci-lint linters - - errcheck - - gosimple - - godot - - ineffassign - - staticcheck - - typecheck - - unused - - # extra linters - bidichk - - durationcheck - - exhaustive + - containedctx + - contextcheck - copyloopvar + - durationcheck + - errcheck + - exhaustive + - funlen + - gocognit + - godot + - importas + - ineffassign + - intrange + - misspell + - perfsprint + - predeclared + - protogetter + - reassign + - revive + - staticcheck + - testifylint + - truecloudlab-linters + - unconvert + - unparam + - unused + - usetesting + - whitespace + settings: + exhaustive: + default-signifies-exhaustive: true + funlen: + lines: 80 + statements: 60 + gocognit: + min-complexity: 40 + importas: + alias: + - pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object + alias: objectSDK + no-unaliased: true + no-extra-aliases: false + staticcheck: + checks: + - all + - -QF1002 + unused: + field-writes-are-uses: false + exported-fields-are-used: false + local-variables-are-used: false + custom: + truecloudlab-linters: + path: bin/linters/external_linters.so + original-url: git.frostfs.info/TrueCloudLab/linters.git + settings: + noliteral: + constants-package: git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs + disable-packages: + - codes + - err + - res + - exec + target-methods: + - reportFlushError + - reportError + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: - gci - gofmt - goimports - - misspell - - predeclared - - reassign - - whitespace - - containedctx - - funlen - - gocognit - - contextcheck - - importas - - truecloudlab-linters - - perfsprint - - testifylint - - protogetter - - intrange - - unconvert - - unparam - - usetesting - disable-all: true - fast: false + settings: + gci: + sections: + - standard + - default + custom-order: true + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/Makefile b/Makefile index 5b55c9eec6..575eaae6fb 100755 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ HUB_IMAGE ?= git.frostfs.info/truecloudlab/frostfs HUB_TAG ?= "$(shell echo ${VERSION} | sed 's/^v//')" GO_VERSION ?= 1.23 -LINT_VERSION ?= 1.64.8 +LINT_VERSION ?= 2.0.2 TRUECLOUDLAB_LINT_VERSION ?= 0.0.10 PROTOC_VERSION ?= 25.0 PROTOGEN_FROSTFS_VERSION ?= $(shell go list -f '{{.Version}}' -m git.frostfs.info/TrueCloudLab/frostfs-sdk-go) @@ -224,7 +224,7 @@ lint-install: $(BIN) @@make -C $(TMP_DIR)/linters lib CGO_ENABLED=1 OUT_DIR=$(OUTPUT_LINT_DIR) @rm -rf $(TMP_DIR)/linters @rmdir $(TMP_DIR) 2>/dev/null || true - @CGO_ENABLED=1 GOBIN=$(LINT_DIR) go install -trimpath github.com/golangci/golangci-lint/cmd/golangci-lint@v$(LINT_VERSION) + @CGO_ENABLED=1 GOBIN=$(LINT_DIR) go install -trimpath github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v$(LINT_VERSION) # Run linters lint: From f93b96c60114440128782ca9d0a228a80a501ae1 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Apr 2025 12:35:34 +0300 Subject: [PATCH 1352/1413] [#1712] adm: Add `maintenance zombie` commands Change-Id: I1b73e561a8daad67d0a8ffc0d293cbdd09aaab6b Signed-off-by: Dmitrii Stepanov --- .../internal/modules/maintenance/root.go | 15 + .../modules/maintenance/zombie/key.go | 70 +++++ .../modules/maintenance/zombie/list.go | 31 ++ .../modules/maintenance/zombie/morph.go | 46 +++ .../modules/maintenance/zombie/quarantine.go | 154 ++++++++++ .../modules/maintenance/zombie/remove.go | 55 ++++ .../modules/maintenance/zombie/restore.go | 69 +++++ .../modules/maintenance/zombie/root.go | 125 ++++++++ .../modules/maintenance/zombie/scan.go | 281 ++++++++++++++++++ .../maintenance/zombie/storage_engine.go | 203 +++++++++++++ cmd/frostfs-adm/internal/modules/root.go | 2 + 11 files changed, 1051 insertions(+) create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/root.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/key.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/list.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/morph.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/quarantine.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/remove.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/restore.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/scan.go create mode 100644 cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go diff --git a/cmd/frostfs-adm/internal/modules/maintenance/root.go b/cmd/frostfs-adm/internal/modules/maintenance/root.go new file mode 100644 index 0000000000..d67b70d2a4 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/root.go @@ -0,0 +1,15 @@ +package maintenance + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/maintenance/zombie" + "github.com/spf13/cobra" +) + +var RootCmd = &cobra.Command{ + Use: "maintenance", + Short: "Section for maintenance commands", +} + +func init() { + RootCmd.AddCommand(zombie.Cmd) +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/key.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/key.go new file mode 100644 index 0000000000..1b66889aaf --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/key.go @@ -0,0 +1,70 @@ +package zombie + +import ( + "crypto/ecdsa" + "fmt" + "os" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "github.com/nspcc-dev/neo-go/cli/flags" + "github.com/nspcc-dev/neo-go/cli/input" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/wallet" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +func getPrivateKey(cmd *cobra.Command, appCfg *config.Config) *ecdsa.PrivateKey { + keyDesc := viper.GetString(walletFlag) + if keyDesc == "" { + return &nodeconfig.Key(appCfg).PrivateKey + } + data, err := os.ReadFile(keyDesc) + commonCmd.ExitOnErr(cmd, "open wallet file: %w", err) + + priv, err := keys.NewPrivateKeyFromBytes(data) + if err != nil { + w, err := wallet.NewWalletFromFile(keyDesc) + commonCmd.ExitOnErr(cmd, "provided key is incorrect, only wallet or binary key supported: %w", err) + return fromWallet(cmd, w, viper.GetString(addressFlag)) + } + return &priv.PrivateKey +} + +func fromWallet(cmd *cobra.Command, w *wallet.Wallet, addrStr string) *ecdsa.PrivateKey { + var ( + addr util.Uint160 + err error + ) + + if addrStr == "" { + addr = w.GetChangeAddress() + } else { + addr, err = flags.ParseAddress(addrStr) + commonCmd.ExitOnErr(cmd, "--address option must be specified and valid: %w", err) + } + + acc := w.GetAccount(addr) + if acc == nil { + commonCmd.ExitOnErr(cmd, "--address option must be specified and valid: %w", fmt.Errorf("can't find wallet account for %s", addrStr)) + } + + pass, err := getPassword() + commonCmd.ExitOnErr(cmd, "invalid password for the encrypted key: %w", err) + + commonCmd.ExitOnErr(cmd, "can't decrypt account: %w", acc.Decrypt(pass, keys.NEP2ScryptParams())) + + return &acc.PrivateKey().PrivateKey +} + +func getPassword() (string, error) { + // this check allows empty passwords + if viper.IsSet("password") { + return viper.GetString("password"), nil + } + + return input.ReadPassword("Enter password > ") +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/list.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/list.go new file mode 100644 index 0000000000..f73f33db97 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/list.go @@ -0,0 +1,31 @@ +package zombie + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/spf13/cobra" +) + +func list(cmd *cobra.Command, _ []string) { + configFile, _ := cmd.Flags().GetString(commonflags.ConfigFlag) + configDir, _ := cmd.Flags().GetString(commonflags.ConfigDirFlag) + appCfg := config.New(configFile, configDir, config.EnvPrefix) + storageEngine := newEngine(cmd, appCfg) + q := createQuarantine(cmd, storageEngine.DumpInfo()) + var containerID *cid.ID + if cidStr, _ := cmd.Flags().GetString(cidFlag); cidStr != "" { + containerID = &cid.ID{} + commonCmd.ExitOnErr(cmd, "decode container ID string: %w", containerID.DecodeString(cidStr)) + } + + commonCmd.ExitOnErr(cmd, "iterate over quarantine: %w", q.Iterate(cmd.Context(), func(a oid.Address) error { + if containerID != nil && a.Container() != *containerID { + return nil + } + cmd.Println(a.EncodeToString()) + return nil + })) +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/morph.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/morph.go new file mode 100644 index 0000000000..cd3a644997 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/morph.go @@ -0,0 +1,46 @@ +package zombie + +import ( + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + morphconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/morph" + nodeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/node" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" + cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" + netmapClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + "github.com/spf13/cobra" +) + +func createMorphClient(cmd *cobra.Command, appCfg *config.Config) *client.Client { + addresses := morphconfig.RPCEndpoint(appCfg) + if len(addresses) == 0 { + commonCmd.ExitOnErr(cmd, "create morph client: %w", errors.New("no morph endpoints found")) + } + key := nodeconfig.Key(appCfg) + cli, err := client.New(cmd.Context(), + key, + client.WithDialTimeout(morphconfig.DialTimeout(appCfg)), + client.WithEndpoints(addresses...), + client.WithSwitchInterval(morphconfig.SwitchInterval(appCfg)), + ) + commonCmd.ExitOnErr(cmd, "create morph client: %w", err) + return cli +} + +func createContainerClient(cmd *cobra.Command, morph *client.Client) *cntClient.Client { + hs, err := morph.NNSContractAddress(client.NNSContainerContractName) + commonCmd.ExitOnErr(cmd, "resolve container contract hash: %w", err) + cc, err := cntClient.NewFromMorph(morph, hs, 0) + commonCmd.ExitOnErr(cmd, "create morph container client: %w", err) + return cc +} + +func createNetmapClient(cmd *cobra.Command, morph *client.Client) *netmapClient.Client { + hs, err := morph.NNSContractAddress(client.NNSNetmapContractName) + commonCmd.ExitOnErr(cmd, "resolve netmap contract hash: %w", err) + cli, err := netmapClient.NewFromMorph(morph, hs, 0) + commonCmd.ExitOnErr(cmd, "create morph netmap client: %w", err) + return cli +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/quarantine.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/quarantine.go new file mode 100644 index 0000000000..27f83aec76 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/quarantine.go @@ -0,0 +1,154 @@ +package zombie + +import ( + "context" + "fmt" + "math" + "os" + "path/filepath" + "strings" + "sync" + + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + objectcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/spf13/cobra" +) + +type quarantine struct { + // mtx protects current field. + mtx sync.Mutex + current int + trees []*fstree.FSTree +} + +func createQuarantine(cmd *cobra.Command, engineInfo engine.Info) *quarantine { + var paths []string + for _, sh := range engineInfo.Shards { + var storagePaths []string + for _, st := range sh.BlobStorInfo.SubStorages { + storagePaths = append(storagePaths, st.Path) + } + if len(storagePaths) == 0 { + continue + } + paths = append(paths, filepath.Join(commonPath(storagePaths), "quarantine")) + } + q, err := newQuarantine(paths) + commonCmd.ExitOnErr(cmd, "create quarantine: %w", err) + return q +} + +func commonPath(paths []string) string { + if len(paths) == 0 { + return "" + } + if len(paths) == 1 { + return paths[0] + } + minLen := math.MaxInt + for _, p := range paths { + if len(p) < minLen { + minLen = len(p) + } + } + + var sb strings.Builder + for i := range minLen { + for _, path := range paths[1:] { + if paths[0][i] != path[i] { + return sb.String() + } + } + sb.WriteByte(paths[0][i]) + } + return sb.String() +} + +func newQuarantine(paths []string) (*quarantine, error) { + var q quarantine + for i := range paths { + f := fstree.New( + fstree.WithDepth(1), + fstree.WithDirNameLen(1), + fstree.WithPath(paths[i]), + fstree.WithPerm(os.ModePerm), + ) + if err := f.Open(mode.ComponentReadWrite); err != nil { + return nil, fmt.Errorf("open fstree %s: %w", paths[i], err) + } + if err := f.Init(); err != nil { + return nil, fmt.Errorf("init fstree %s: %w", paths[i], err) + } + q.trees = append(q.trees, f) + } + return &q, nil +} + +func (q *quarantine) Get(ctx context.Context, a oid.Address) (*objectSDK.Object, error) { + for i := range q.trees { + res, err := q.trees[i].Get(ctx, common.GetPrm{Address: a}) + if err != nil { + continue + } + return res.Object, nil + } + return nil, &apistatus.ObjectNotFound{} +} + +func (q *quarantine) Delete(ctx context.Context, a oid.Address) error { + for i := range q.trees { + _, err := q.trees[i].Delete(ctx, common.DeletePrm{Address: a}) + if err != nil { + continue + } + return nil + } + return &apistatus.ObjectNotFound{} +} + +func (q *quarantine) Put(ctx context.Context, obj *objectSDK.Object) error { + data, err := obj.Marshal() + if err != nil { + return err + } + + var prm common.PutPrm + prm.Address = objectcore.AddressOf(obj) + prm.Object = obj + prm.RawData = data + + q.mtx.Lock() + current := q.current + q.current = (q.current + 1) % len(q.trees) + q.mtx.Unlock() + + _, err = q.trees[current].Put(ctx, prm) + return err +} + +func (q *quarantine) Iterate(ctx context.Context, f func(oid.Address) error) error { + var prm common.IteratePrm + prm.Handler = func(elem common.IterationElement) error { + return f(elem.Address) + } + for i := range q.trees { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + _, err := q.trees[i].Iterate(ctx, prm) + if err != nil { + return err + } + } + return nil +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/remove.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/remove.go new file mode 100644 index 0000000000..0b8f2f1728 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/remove.go @@ -0,0 +1,55 @@ +package zombie + +import ( + "errors" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/spf13/cobra" +) + +func remove(cmd *cobra.Command, _ []string) { + configFile, _ := cmd.Flags().GetString(commonflags.ConfigFlag) + configDir, _ := cmd.Flags().GetString(commonflags.ConfigDirFlag) + appCfg := config.New(configFile, configDir, config.EnvPrefix) + storageEngine := newEngine(cmd, appCfg) + q := createQuarantine(cmd, storageEngine.DumpInfo()) + + var containerID cid.ID + cidStr, _ := cmd.Flags().GetString(cidFlag) + commonCmd.ExitOnErr(cmd, "decode container ID string: %w", containerID.DecodeString(cidStr)) + + var objectID *oid.ID + oidStr, _ := cmd.Flags().GetString(oidFlag) + if oidStr != "" { + objectID = &oid.ID{} + commonCmd.ExitOnErr(cmd, "decode object ID string: %w", objectID.DecodeString(oidStr)) + } + + if objectID != nil { + var addr oid.Address + addr.SetContainer(containerID) + addr.SetObject(*objectID) + removeObject(cmd, q, addr) + } else { + commonCmd.ExitOnErr(cmd, "iterate over quarantine: %w", q.Iterate(cmd.Context(), func(addr oid.Address) error { + if addr.Container() != containerID { + return nil + } + removeObject(cmd, q, addr) + return nil + })) + } +} + +func removeObject(cmd *cobra.Command, q *quarantine, addr oid.Address) { + err := q.Delete(cmd.Context(), addr) + if errors.Is(err, new(apistatus.ObjectNotFound)) { + return + } + commonCmd.ExitOnErr(cmd, "remove object from quarantine: %w", err) +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/restore.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/restore.go new file mode 100644 index 0000000000..f179c7c2df --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/restore.go @@ -0,0 +1,69 @@ +package zombie + +import ( + "crypto/sha256" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" + cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/spf13/cobra" +) + +func restore(cmd *cobra.Command, _ []string) { + configFile, _ := cmd.Flags().GetString(commonflags.ConfigFlag) + configDir, _ := cmd.Flags().GetString(commonflags.ConfigDirFlag) + appCfg := config.New(configFile, configDir, config.EnvPrefix) + storageEngine := newEngine(cmd, appCfg) + q := createQuarantine(cmd, storageEngine.DumpInfo()) + morphClient := createMorphClient(cmd, appCfg) + cnrCli := createContainerClient(cmd, morphClient) + + var containerID cid.ID + cidStr, _ := cmd.Flags().GetString(cidFlag) + commonCmd.ExitOnErr(cmd, "decode container ID string: %w", containerID.DecodeString(cidStr)) + + var objectID *oid.ID + oidStr, _ := cmd.Flags().GetString(oidFlag) + if oidStr != "" { + objectID = &oid.ID{} + commonCmd.ExitOnErr(cmd, "decode object ID string: %w", objectID.DecodeString(oidStr)) + } + + if objectID != nil { + var addr oid.Address + addr.SetContainer(containerID) + addr.SetObject(*objectID) + restoreObject(cmd, storageEngine, q, addr, cnrCli) + } else { + commonCmd.ExitOnErr(cmd, "iterate over quarantine: %w", q.Iterate(cmd.Context(), func(addr oid.Address) error { + if addr.Container() != containerID { + return nil + } + restoreObject(cmd, storageEngine, q, addr, cnrCli) + return nil + })) + } +} + +func restoreObject(cmd *cobra.Command, storageEngine *engine.StorageEngine, q *quarantine, addr oid.Address, cnrCli *cntClient.Client) { + obj, err := q.Get(cmd.Context(), addr) + commonCmd.ExitOnErr(cmd, "get object from quarantine: %w", err) + rawCID := make([]byte, sha256.Size) + + cid := addr.Container() + cid.Encode(rawCID) + cnr, err := cnrCli.Get(cmd.Context(), rawCID) + commonCmd.ExitOnErr(cmd, "get container: %w", err) + + putPrm := engine.PutPrm{ + Object: obj, + IsIndexedContainer: containerCore.IsIndexedContainer(cnr.Value), + } + commonCmd.ExitOnErr(cmd, "put object to storage engine: %w", storageEngine.Put(cmd.Context(), putPrm)) + commonCmd.ExitOnErr(cmd, "remove object from quarantine: %w", q.Delete(cmd.Context(), addr)) +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go new file mode 100644 index 0000000000..9ef18f7f82 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go @@ -0,0 +1,125 @@ +package zombie + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const ( + flagBatchSize = "batch-size" + flagBatchSizeUsage = "Objects iteration batch size" + cidFlag = "cid" + cidFlagUsage = "Container ID" + oidFlag = "oid" + oidFlagUsage = "Object ID" + walletFlag = "wallet" + walletFlagShorthand = "w" + walletFlagUsage = "Path to the wallet or binary key" + addressFlag = "address" + addressFlagUsage = "Address of wallet account" + moveFlag = "move" + moveFlagUsage = "Move objects from storage engine to quarantine" +) + +var ( + Cmd = &cobra.Command{ + Use: "zombie", + Short: "Zombie objects related commands", + } + scanCmd = &cobra.Command{ + Use: "scan", + Short: "Scan storage engine for zombie objects and move them to quarantine", + Long: "", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) + _ = viper.BindPFlag(commonflags.ConfigFlag, cmd.Flags().Lookup(commonflags.ConfigFlag)) + _ = viper.BindPFlag(commonflags.ConfigDirFlag, cmd.Flags().Lookup(commonflags.ConfigDirFlag)) + _ = viper.BindPFlag(walletFlag, cmd.Flags().Lookup(walletFlag)) + _ = viper.BindPFlag(addressFlag, cmd.Flags().Lookup(addressFlag)) + _ = viper.BindPFlag(flagBatchSize, cmd.Flags().Lookup(flagBatchSize)) + _ = viper.BindPFlag(moveFlag, cmd.Flags().Lookup(moveFlag)) + }, + Run: scan, + } + listCmd = &cobra.Command{ + Use: "list", + Short: "List zombie objects from quarantine", + Long: "", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.ConfigFlag, cmd.Flags().Lookup(commonflags.ConfigFlag)) + _ = viper.BindPFlag(commonflags.ConfigDirFlag, cmd.Flags().Lookup(commonflags.ConfigDirFlag)) + _ = viper.BindPFlag(cidFlag, cmd.Flags().Lookup(cidFlag)) + }, + Run: list, + } + restoreCmd = &cobra.Command{ + Use: "restore", + Short: "Restore zombie objects from quarantine", + Long: "", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.ConfigFlag, cmd.Flags().Lookup(commonflags.ConfigFlag)) + _ = viper.BindPFlag(commonflags.ConfigDirFlag, cmd.Flags().Lookup(commonflags.ConfigDirFlag)) + _ = viper.BindPFlag(cidFlag, cmd.Flags().Lookup(cidFlag)) + _ = viper.BindPFlag(oidFlag, cmd.Flags().Lookup(oidFlag)) + }, + Run: restore, + } + removeCmd = &cobra.Command{ + Use: "remove", + Short: "Remove zombie objects from quarantine", + Long: "", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(commonflags.ConfigFlag, cmd.Flags().Lookup(commonflags.ConfigFlag)) + _ = viper.BindPFlag(commonflags.ConfigDirFlag, cmd.Flags().Lookup(commonflags.ConfigDirFlag)) + _ = viper.BindPFlag(cidFlag, cmd.Flags().Lookup(cidFlag)) + _ = viper.BindPFlag(oidFlag, cmd.Flags().Lookup(oidFlag)) + }, + Run: remove, + } +) + +func init() { + initScanCmd() + initListCmd() + initRestoreCmd() + initRemoveCmd() +} + +func initScanCmd() { + Cmd.AddCommand(scanCmd) + + scanCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) + scanCmd.Flags().StringP(commonflags.ConfigFlag, commonflags.ConfigFlagShorthand, "", commonflags.ConfigFlagUsage) + scanCmd.Flags().String(commonflags.ConfigDirFlag, "", commonflags.ConfigDirFlagUsage) + scanCmd.Flags().Uint32(flagBatchSize, 1000, flagBatchSizeUsage) + scanCmd.Flags().StringP(walletFlag, walletFlagShorthand, "", walletFlagUsage) + scanCmd.Flags().String(addressFlag, "", addressFlagUsage) + scanCmd.Flags().Bool(moveFlag, false, moveFlagUsage) +} + +func initListCmd() { + Cmd.AddCommand(listCmd) + + listCmd.Flags().StringP(commonflags.ConfigFlag, commonflags.ConfigFlagShorthand, "", commonflags.ConfigFlagUsage) + listCmd.Flags().String(commonflags.ConfigDirFlag, "", commonflags.ConfigDirFlagUsage) + listCmd.Flags().String(cidFlag, "", cidFlagUsage) +} + +func initRestoreCmd() { + Cmd.AddCommand(restoreCmd) + + restoreCmd.Flags().StringP(commonflags.ConfigFlag, commonflags.ConfigFlagShorthand, "", commonflags.ConfigFlagUsage) + restoreCmd.Flags().String(commonflags.ConfigDirFlag, "", commonflags.ConfigDirFlagUsage) + restoreCmd.Flags().String(cidFlag, "", cidFlagUsage) + restoreCmd.Flags().String(oidFlag, "", oidFlagUsage) +} + +func initRemoveCmd() { + Cmd.AddCommand(removeCmd) + + removeCmd.Flags().StringP(commonflags.ConfigFlag, commonflags.ConfigFlagShorthand, "", commonflags.ConfigFlagUsage) + removeCmd.Flags().String(commonflags.ConfigDirFlag, "", commonflags.ConfigDirFlagUsage) + removeCmd.Flags().String(cidFlag, "", cidFlagUsage) + removeCmd.Flags().String(oidFlag, "", oidFlagUsage) +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/scan.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/scan.go new file mode 100644 index 0000000000..268ec49111 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/scan.go @@ -0,0 +1,281 @@ +package zombie + +import ( + "context" + "crypto/ecdsa" + "crypto/sha256" + "errors" + "fmt" + "sync" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + apiclientconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/apiclient" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + clientCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" + netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache" + clientSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" + apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" +) + +func scan(cmd *cobra.Command, _ []string) { + configFile, _ := cmd.Flags().GetString(commonflags.ConfigFlag) + configDir, _ := cmd.Flags().GetString(commonflags.ConfigDirFlag) + appCfg := config.New(configFile, configDir, config.EnvPrefix) + batchSize, _ := cmd.Flags().GetUint32(flagBatchSize) + if batchSize == 0 { + commonCmd.ExitOnErr(cmd, "invalid batch size: %w", errors.New("batch size must be positive value")) + } + move, _ := cmd.Flags().GetBool(moveFlag) + + storageEngine := newEngine(cmd, appCfg) + morphClient := createMorphClient(cmd, appCfg) + cnrCli := createContainerClient(cmd, morphClient) + nmCli := createNetmapClient(cmd, morphClient) + q := createQuarantine(cmd, storageEngine.DumpInfo()) + pk := getPrivateKey(cmd, appCfg) + + epoch, err := nmCli.Epoch(cmd.Context()) + commonCmd.ExitOnErr(cmd, "read epoch from morph: %w", err) + + nm, err := nmCli.GetNetMapByEpoch(cmd.Context(), epoch) + commonCmd.ExitOnErr(cmd, "read netmap from morph: %w", err) + + cmd.Printf("Epoch: %d\n", nm.Epoch()) + cmd.Printf("Nodes in the netmap: %d\n", len(nm.Nodes())) + + ps := &processStatus{ + statusCount: make(map[status]uint64), + } + + stopCh := make(chan struct{}) + start := time.Now() + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + tick := time.NewTicker(time.Second) + defer tick.Stop() + for { + select { + case <-cmd.Context().Done(): + return + case <-stopCh: + return + case <-tick.C: + fmt.Printf("Objects processed: %d; Time elapsed: %s\n", ps.total(), time.Since(start)) + } + } + }() + go func() { + defer wg.Done() + err = scanStorageEngine(cmd, batchSize, storageEngine, ps, appCfg, cnrCli, nmCli, q, pk, move) + close(stopCh) + }() + wg.Wait() + commonCmd.ExitOnErr(cmd, "scan storage engine for zombie objects: %w", err) + + cmd.Println() + cmd.Println("Status description:") + cmd.Println("undefined -- nothing is clear") + cmd.Println("found -- object is found in cluster") + cmd.Println("quarantine -- object is not found in cluster") + cmd.Println() + for status, count := range ps.statusCount { + cmd.Printf("Status: %s, Count: %d\n", status, count) + } +} + +type status string + +const ( + statusUndefined status = "undefined" + statusFound status = "found" + statusQuarantine status = "quarantine" +) + +func checkAddr(ctx context.Context, cnrCli *cntClient.Client, nmCli *netmap.Client, cc *cache.ClientCache, obj object.Info) (status, error) { + rawCID := make([]byte, sha256.Size) + cid := obj.Address.Container() + cid.Encode(rawCID) + + cnr, err := cnrCli.Get(ctx, rawCID) + if err != nil { + var errContainerNotFound *apistatus.ContainerNotFound + if errors.As(err, &errContainerNotFound) { + // Policer will deal with this object. + return statusFound, nil + } + return statusUndefined, fmt.Errorf("read container %s from morph: %w", cid, err) + } + nm, err := nmCli.NetMap(ctx) + if err != nil { + return statusUndefined, fmt.Errorf("read netmap from morph: %w", err) + } + + nodes, err := nm.ContainerNodes(cnr.Value.PlacementPolicy(), rawCID) + if err != nil { + // Not enough nodes, check all netmap nodes. + nodes = append([][]netmap.NodeInfo{}, nm.Nodes()) + } + + objID := obj.Address.Object() + cnrID := obj.Address.Container() + local := true + raw := false + if obj.ECInfo != nil { + objID = obj.ECInfo.ParentID + local = false + raw = true + } + prm := clientSDK.PrmObjectHead{ + ObjectID: &objID, + ContainerID: &cnrID, + Local: local, + Raw: raw, + } + + var ni clientCore.NodeInfo + for i := range nodes { + for j := range nodes[i] { + if err := clientCore.NodeInfoFromRawNetmapElement(&ni, netmapCore.Node(nodes[i][j])); err != nil { + return statusUndefined, fmt.Errorf("parse node info: %w", err) + } + c, err := cc.Get(ni) + if err != nil { + continue + } + res, err := c.ObjectHead(ctx, prm) + if err != nil { + var errECInfo *objectSDK.ECInfoError + if raw && errors.As(err, &errECInfo) { + return statusFound, nil + } + continue + } + if err := apistatus.ErrFromStatus(res.Status()); err != nil { + continue + } + return statusFound, nil + } + } + + if cnr.Value.PlacementPolicy().NumberOfReplicas() == 1 && cnr.Value.PlacementPolicy().ReplicaDescriptor(0).NumberOfObjects() == 1 { + return statusFound, nil + } + return statusQuarantine, nil +} + +func scanStorageEngine(cmd *cobra.Command, batchSize uint32, storageEngine *engine.StorageEngine, ps *processStatus, + appCfg *config.Config, cnrCli *cntClient.Client, nmCli *netmap.Client, q *quarantine, pk *ecdsa.PrivateKey, move bool, +) error { + cc := cache.NewSDKClientCache(cache.ClientCacheOpts{ + DialTimeout: apiclientconfig.DialTimeout(appCfg), + StreamTimeout: apiclientconfig.StreamTimeout(appCfg), + ReconnectTimeout: apiclientconfig.ReconnectTimeout(appCfg), + Key: pk, + AllowExternal: apiclientconfig.AllowExternal(appCfg), + }) + ctx := cmd.Context() + + var cursor *engine.Cursor + for { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + var prm engine.ListWithCursorPrm + prm.WithCursor(cursor) + prm.WithCount(batchSize) + + res, err := storageEngine.ListWithCursor(ctx, prm) + if err != nil { + if errors.Is(err, engine.ErrEndOfListing) { + return nil + } + return fmt.Errorf("list with cursor: %w", err) + } + + cursor = res.Cursor() + addrList := res.AddressList() + eg, egCtx := errgroup.WithContext(ctx) + eg.SetLimit(int(batchSize)) + + for i := range addrList { + addr := addrList[i] + eg.Go(func() error { + result, err := checkAddr(egCtx, cnrCli, nmCli, cc, addr) + if err != nil { + return fmt.Errorf("check object %s status: %w", addr.Address, err) + } + ps.add(result) + + if !move && result == statusQuarantine { + cmd.Println(addr) + return nil + } + + if result == statusQuarantine { + return moveToQuarantine(egCtx, storageEngine, q, addr.Address) + } + return nil + }) + } + if err := eg.Wait(); err != nil { + return fmt.Errorf("process objects batch: %w", err) + } + } +} + +func moveToQuarantine(ctx context.Context, storageEngine *engine.StorageEngine, q *quarantine, addr oid.Address) error { + var getPrm engine.GetPrm + getPrm.WithAddress(addr) + res, err := storageEngine.Get(ctx, getPrm) + if err != nil { + return fmt.Errorf("get object %s from storage engine: %w", addr, err) + } + + if err := q.Put(ctx, res.Object()); err != nil { + return fmt.Errorf("put object %s to quarantine: %w", addr, err) + } + + var delPrm engine.DeletePrm + delPrm.WithForceRemoval() + delPrm.WithAddress(addr) + + if err = storageEngine.Delete(ctx, delPrm); err != nil { + return fmt.Errorf("delete object %s from storage engine: %w", addr, err) + } + return nil +} + +type processStatus struct { + guard sync.RWMutex + statusCount map[status]uint64 + count uint64 +} + +func (s *processStatus) add(st status) { + s.guard.Lock() + defer s.guard.Unlock() + s.statusCount[st]++ + s.count++ +} + +func (s *processStatus) total() uint64 { + s.guard.RLock() + defer s.guard.RUnlock() + return s.count +} diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go new file mode 100644 index 0000000000..5851e049ce --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go @@ -0,0 +1,203 @@ +package zombie + +import ( + "context" + "time" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + engineconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine" + shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard" + blobovniczaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza" + fstreeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/fstree" + commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" + meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" + "github.com/panjf2000/ants/v2" + "github.com/spf13/cobra" + "go.etcd.io/bbolt" + "go.uber.org/zap" +) + +func newEngine(cmd *cobra.Command, c *config.Config) *engine.StorageEngine { + ngOpts := storageEngineOptions(c) + shardOpts := shardOptions(cmd, c) + e := engine.New(ngOpts...) + for _, opts := range shardOpts { + _, err := e.AddShard(cmd.Context(), opts...) + commonCmd.ExitOnErr(cmd, "iterate shards from config: %w", err) + } + commonCmd.ExitOnErr(cmd, "open storage engine: %w", e.Open(cmd.Context())) + commonCmd.ExitOnErr(cmd, "init storage engine: %w", e.Init(cmd.Context())) + return e +} + +func storageEngineOptions(c *config.Config) []engine.Option { + return []engine.Option{ + engine.WithErrorThreshold(engineconfig.ShardErrorThreshold(c)), + engine.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + engine.WithLowMemoryConsumption(engineconfig.EngineLowMemoryConsumption(c)), + } +} + +func shardOptions(cmd *cobra.Command, c *config.Config) [][]shard.Option { + var result [][]shard.Option + err := engineconfig.IterateShards(c, false, func(sh *shardconfig.Config) error { + result = append(result, getShardOpts(cmd, c, sh)) + return nil + }) + commonCmd.ExitOnErr(cmd, "iterate shards from config: %w", err) + return result +} + +func getShardOpts(cmd *cobra.Command, c *config.Config, sh *shardconfig.Config) []shard.Option { + wc, wcEnabled := getWriteCacheOpts(sh) + return []shard.Option{ + shard.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + shard.WithRefillMetabase(sh.RefillMetabase()), + shard.WithRefillMetabaseWorkersCount(sh.RefillMetabaseWorkersCount()), + shard.WithMode(sh.Mode()), + shard.WithBlobStorOptions(getBlobstorOpts(cmd.Context(), sh)...), + shard.WithMetaBaseOptions(getMetabaseOpts(sh)...), + shard.WithPiloramaOptions(getPiloramaOpts(c, sh)...), + shard.WithWriteCache(wcEnabled), + shard.WithWriteCacheOptions(wc), + shard.WithRemoverBatchSize(sh.GC().RemoverBatchSize()), + shard.WithGCRemoverSleepInterval(sh.GC().RemoverSleepInterval()), + shard.WithExpiredCollectorBatchSize(sh.GC().ExpiredCollectorBatchSize()), + shard.WithExpiredCollectorWorkerCount(sh.GC().ExpiredCollectorWorkerCount()), + shard.WithGCWorkerPoolInitializer(func(sz int) util.WorkerPool { + pool, err := ants.NewPool(sz) + commonCmd.ExitOnErr(cmd, "init GC pool: %w", err) + return pool + }), + shard.WithLimiter(qos.NewNoopLimiter()), + } +} + +func getWriteCacheOpts(sh *shardconfig.Config) ([]writecache.Option, bool) { + if wc := sh.WriteCache(); wc != nil && wc.Enabled() { + var result []writecache.Option + result = append(result, + writecache.WithPath(wc.Path()), + writecache.WithFlushSizeLimit(wc.MaxFlushingObjectsSize()), + writecache.WithMaxObjectSize(wc.MaxObjectSize()), + writecache.WithFlushWorkersCount(wc.WorkerCount()), + writecache.WithMaxCacheSize(wc.SizeLimit()), + writecache.WithMaxCacheCount(wc.CountLimit()), + writecache.WithNoSync(wc.NoSync()), + writecache.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + writecache.WithQoSLimiter(qos.NewNoopLimiter()), + ) + return result, true + } + return nil, false +} + +func getPiloramaOpts(c *config.Config, sh *shardconfig.Config) []pilorama.Option { + var piloramaOpts []pilorama.Option + if config.BoolSafe(c.Sub("tree"), "enabled") { + pr := sh.Pilorama() + piloramaOpts = append(piloramaOpts, + pilorama.WithPath(pr.Path()), + pilorama.WithPerm(pr.Perm()), + pilorama.WithNoSync(pr.NoSync()), + pilorama.WithMaxBatchSize(pr.MaxBatchSize()), + pilorama.WithMaxBatchDelay(pr.MaxBatchDelay()), + ) + } + return piloramaOpts +} + +func getMetabaseOpts(sh *shardconfig.Config) []meta.Option { + return []meta.Option{ + meta.WithPath(sh.Metabase().Path()), + meta.WithPermissions(sh.Metabase().BoltDB().Perm()), + meta.WithMaxBatchSize(sh.Metabase().BoltDB().MaxBatchSize()), + meta.WithMaxBatchDelay(sh.Metabase().BoltDB().MaxBatchDelay()), + meta.WithBoltDBOptions(&bbolt.Options{ + Timeout: 100 * time.Millisecond, + }), + meta.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + meta.WithEpochState(&epochState{}), + } +} + +func getBlobstorOpts(ctx context.Context, sh *shardconfig.Config) []blobstor.Option { + result := []blobstor.Option{ + blobstor.WithCompressObjects(sh.Compress()), + blobstor.WithUncompressableContentTypes(sh.UncompressableContentTypes()), + blobstor.WithCompressibilityEstimate(sh.EstimateCompressibility()), + blobstor.WithCompressibilityEstimateThreshold(sh.EstimateCompressibilityThreshold()), + blobstor.WithStorages(getSubStorages(ctx, sh)), + blobstor.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + } + + return result +} + +func getSubStorages(ctx context.Context, sh *shardconfig.Config) []blobstor.SubStorage { + var ss []blobstor.SubStorage + for _, storage := range sh.BlobStor().Storages() { + switch storage.Type() { + case blobovniczatree.Type: + sub := blobovniczaconfig.From((*config.Config)(storage)) + blobTreeOpts := []blobovniczatree.Option{ + blobovniczatree.WithRootPath(storage.Path()), + blobovniczatree.WithPermissions(storage.Perm()), + blobovniczatree.WithBlobovniczaSize(sub.Size()), + blobovniczatree.WithBlobovniczaShallowDepth(sub.ShallowDepth()), + blobovniczatree.WithBlobovniczaShallowWidth(sub.ShallowWidth()), + blobovniczatree.WithOpenedCacheSize(sub.OpenedCacheSize()), + blobovniczatree.WithOpenedCacheTTL(sub.OpenedCacheTTL()), + blobovniczatree.WithOpenedCacheExpInterval(sub.OpenedCacheExpInterval()), + blobovniczatree.WithInitWorkerCount(sub.InitWorkerCount()), + blobovniczatree.WithWaitBeforeDropDB(sub.RebuildDropTimeout()), + blobovniczatree.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + blobovniczatree.WithObjectSizeLimit(sh.SmallSizeLimit()), + } + + ss = append(ss, blobstor.SubStorage{ + Storage: blobovniczatree.NewBlobovniczaTree(ctx, blobTreeOpts...), + Policy: func(_ *objectSDK.Object, data []byte) bool { + return uint64(len(data)) < sh.SmallSizeLimit() + }, + }) + case fstree.Type: + sub := fstreeconfig.From((*config.Config)(storage)) + fstreeOpts := []fstree.Option{ + fstree.WithPath(storage.Path()), + fstree.WithPerm(storage.Perm()), + fstree.WithDepth(sub.Depth()), + fstree.WithNoSync(sub.NoSync()), + fstree.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + } + + ss = append(ss, blobstor.SubStorage{ + Storage: fstree.New(fstreeOpts...), + Policy: func(_ *objectSDK.Object, _ []byte) bool { + return true + }, + }) + default: + // should never happen, that has already + // been handled: when the config was read + } + } + return ss +} + +type epochState struct{} + +func (epochState) CurrentEpoch() uint64 { + return 0 +} diff --git a/cmd/frostfs-adm/internal/modules/root.go b/cmd/frostfs-adm/internal/modules/root.go index e42204b7a3..cc8225c7aa 100644 --- a/cmd/frostfs-adm/internal/modules/root.go +++ b/cmd/frostfs-adm/internal/modules/root.go @@ -5,6 +5,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/maintenance" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph" "git.frostfs.info/TrueCloudLab/frostfs-node/misc" @@ -41,6 +42,7 @@ func init() { rootCmd.AddCommand(config.RootCmd) rootCmd.AddCommand(morph.RootCmd) rootCmd.AddCommand(metabase.RootCmd) + rootCmd.AddCommand(maintenance.RootCmd) rootCmd.AddCommand(autocomplete.Command("frostfs-adm")) rootCmd.AddCommand(gendoc.Command(rootCmd, gendoc.Options{})) From f7779adf71babe6c06a91172e3ef95c947c1f1a7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Apr 2025 15:32:23 +0300 Subject: [PATCH 1353/1413] [#1712] core: Extend object info string with EC header Closes #1712 Change-Id: Ief4a960f7dece3359763113270d1ff5155f3f19e Signed-off-by: Dmitrii Stepanov --- pkg/core/object/info.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/core/object/info.go b/pkg/core/object/info.go index 67c9a31882..aab12ebf93 100644 --- a/pkg/core/object/info.go +++ b/pkg/core/object/info.go @@ -13,6 +13,13 @@ type ECInfo struct { Total uint32 } +func (v *ECInfo) String() string { + if v == nil { + return "" + } + return fmt.Sprintf("parent ID: %s, index: %d, total %d", v.ParentID, v.Index, v.Total) +} + // Info groups object address with its FrostFS // object info. type Info struct { @@ -23,5 +30,5 @@ type Info struct { } func (v Info) String() string { - return fmt.Sprintf("address: %s, type: %s, is linking: %t", v.Address, v.Type, v.IsLinkingObject) + return fmt.Sprintf("address: %s, type: %s, is linking: %t, EC header: %s", v.Address, v.Type, v.IsLinkingObject, v.ECInfo) } From 6730e27ae71a97af5ca33392ce6ab5e9e3257173 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 9 Apr 2025 16:29:48 +0300 Subject: [PATCH 1354/1413] [#1712] adm: Drop rpc-endpoint flag from `zombie scan` Morph addresses from config are used. Change-Id: Id99f91defbbff442c308f30d219b9824b4c871de Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go index 9ef18f7f82..c8fd9e5e55 100644 --- a/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/root.go @@ -32,7 +32,6 @@ var ( Short: "Scan storage engine for zombie objects and move them to quarantine", Long: "", PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(commonflags.EndpointFlag, cmd.Flags().Lookup(commonflags.EndpointFlag)) _ = viper.BindPFlag(commonflags.ConfigFlag, cmd.Flags().Lookup(commonflags.ConfigFlag)) _ = viper.BindPFlag(commonflags.ConfigDirFlag, cmd.Flags().Lookup(commonflags.ConfigDirFlag)) _ = viper.BindPFlag(walletFlag, cmd.Flags().Lookup(walletFlag)) @@ -89,7 +88,6 @@ func init() { func initScanCmd() { Cmd.AddCommand(scanCmd) - scanCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc) scanCmd.Flags().StringP(commonflags.ConfigFlag, commonflags.ConfigFlagShorthand, "", commonflags.ConfigFlagUsage) scanCmd.Flags().String(commonflags.ConfigDirFlag, "", commonflags.ConfigDirFlagUsage) scanCmd.Flags().Uint32(flagBatchSize, 1000, flagBatchSizeUsage) From dcfd89544925719560343521ceb9a792d195cb51 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 8 Apr 2025 10:21:14 +0300 Subject: [PATCH 1355/1413] [#1710] object: Implement `Unwrap()` for `errIncompletePut` * When sign service calls `SignResponse`, it tries to set v2 status to response by unwrapping an error to the possible depth. This wasn't applicable for `errIncompletePut` so far as it didn't implement `Unwrap()`. Thus, it wasn't able to find a correct status set in error. Change-Id: I280c1806a008176854c55f13bf8688e5736ef941 Signed-off-by: Airat Arifullin --- pkg/services/object/common/writer/distributed.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/services/object/common/writer/distributed.go b/pkg/services/object/common/writer/distributed.go index f7486eae72..fff58aca71 100644 --- a/pkg/services/object/common/writer/distributed.go +++ b/pkg/services/object/common/writer/distributed.go @@ -95,6 +95,10 @@ func (x errIncompletePut) Error() string { return commonMsg } +func (x errIncompletePut) Unwrap() error { + return x.singleErr +} + // WriteObject implements the transformer.ObjectWriter interface. func (t *distributedWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error { t.obj = obj From 64c1392513f43b95bbe3f2afb6bab0a8edd03f89 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 8 Apr 2025 10:45:46 +0300 Subject: [PATCH 1356/1413] [#1710] object: Sign response even if `CloseAndRecv` returns error * Sign service wraps an error with status and sign a response even if error occurs from `CloseAndRecv` in `Put` and `Patch` methods. Close #1710 Change-Id: I7e1d8fe00db53607fa6e04ebec9a29b87349f8a1 Signed-off-by: Airat Arifullin --- pkg/services/object/sign.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/services/object/sign.go b/pkg/services/object/sign.go index 2b44227a52..fd8e926ddc 100644 --- a/pkg/services/object/sign.go +++ b/pkg/services/object/sign.go @@ -96,7 +96,8 @@ func (s *putStreamSigner) CloseAndRecv(ctx context.Context) (resp *object.PutRes } else { resp, err = s.stream.CloseAndRecv(ctx) if err != nil { - return nil, fmt.Errorf("could not close stream and receive response: %w", err) + err = fmt.Errorf("could not close stream and receive response: %w", err) + resp = new(object.PutResponse) } } @@ -132,7 +133,8 @@ func (s *patchStreamSigner) CloseAndRecv(ctx context.Context) (resp *object.Patc } else { resp, err = s.stream.CloseAndRecv(ctx) if err != nil { - return nil, fmt.Errorf("could not close stream and receive response: %w", err) + err = fmt.Errorf("could not close stream and receive response: %w", err) + resp = new(object.PatchResponse) } } From e06ecacf57e14630f1cd783af0c88854c26f41cc Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 10 Apr 2025 16:04:04 +0300 Subject: [PATCH 1357/1413] [#1705] engine: Use condition var for evacuation unit tests To know exactly when the evacuation was completed, a conditional variable was added. Closes #1705 Change-Id: I86f6d7d2ad2b9759905b6b5e9341008cb74f5dfd Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/engine.go | 16 +++++++++++----- .../engine/evacuate_limiter.go | 6 +++++- .../engine/evacuate_test.go | 18 +++++++++++++----- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index a915c9bd6c..1d33c0592c 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -212,12 +212,18 @@ func New(opts ...Option) *StorageEngine { opts[i](c) } + evLimMtx := &sync.RWMutex{} + evLimCond := sync.NewCond(evLimMtx) + return &StorageEngine{ - cfg: c, - shards: make(map[string]hashedShard), - closeCh: make(chan struct{}), - setModeCh: make(chan setModeRequest), - evacuateLimiter: &evacuationLimiter{}, + cfg: c, + shards: make(map[string]hashedShard), + closeCh: make(chan struct{}), + setModeCh: make(chan setModeRequest), + evacuateLimiter: &evacuationLimiter{ + guard: evLimMtx, + statusCond: evLimCond, + }, } } diff --git a/pkg/local_object_storage/engine/evacuate_limiter.go b/pkg/local_object_storage/engine/evacuate_limiter.go index 3dd7494be4..b75e8686d8 100644 --- a/pkg/local_object_storage/engine/evacuate_limiter.go +++ b/pkg/local_object_storage/engine/evacuate_limiter.go @@ -139,7 +139,8 @@ type evacuationLimiter struct { eg *errgroup.Group cancel context.CancelFunc - guard sync.RWMutex + guard *sync.RWMutex + statusCond *sync.Cond // used in unit tests } func (l *evacuationLimiter) TryStart(ctx context.Context, shardIDs []string, result *EvacuateShardRes) (*errgroup.Group, context.Context, error) { @@ -165,6 +166,7 @@ func (l *evacuationLimiter) TryStart(ctx context.Context, shardIDs []string, res startedAt: time.Now().UTC(), result: result, } + l.statusCond.Broadcast() return l.eg, egCtx, nil } @@ -180,6 +182,7 @@ func (l *evacuationLimiter) Complete(err error) { l.state.processState = EvacuateProcessStateCompleted l.state.errMessage = errMsq l.state.finishedAt = time.Now().UTC() + l.statusCond.Broadcast() l.eg = nil } @@ -214,6 +217,7 @@ func (l *evacuationLimiter) ResetEvacuationStatus() error { l.state = EvacuationState{} l.eg = nil l.cancel = nil + l.statusCond.Broadcast() return nil } diff --git a/pkg/local_object_storage/engine/evacuate_test.go b/pkg/local_object_storage/engine/evacuate_test.go index 359e49481c..f2ba7d994a 100644 --- a/pkg/local_object_storage/engine/evacuate_test.go +++ b/pkg/local_object_storage/engine/evacuate_test.go @@ -204,11 +204,10 @@ func TestEvacuateShardObjects(t *testing.T) { func testWaitForEvacuationCompleted(t *testing.T, e *StorageEngine) *EvacuationState { var st *EvacuationState var err error - require.Eventually(t, func() bool { - st, err = e.GetEvacuationState(context.Background()) - require.NoError(t, err) - return st.ProcessingStatus() == EvacuateProcessStateCompleted - }, 6*time.Second, 10*time.Millisecond) + e.evacuateLimiter.waitForCompleted() + st, err = e.GetEvacuationState(context.Background()) + require.NoError(t, err) + require.Equal(t, EvacuateProcessStateCompleted, st.ProcessingStatus()) return st } @@ -817,3 +816,12 @@ func TestEvacuateShardObjectsRepOneOnlyBench(t *testing.T) { t.Logf("evacuate took %v\n", time.Since(start)) require.NoError(t, err) } + +func (l *evacuationLimiter) waitForCompleted() { + l.guard.Lock() + defer l.guard.Unlock() + + for l.state.processState != EvacuateProcessStateCompleted { + l.statusCond.Wait() + } +} From dfe2f9956a82c6bee62e443e9e5178d6584ade64 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 24 Mar 2025 15:32:25 +0300 Subject: [PATCH 1358/1413] [#1619] logger: Filter entries by tags provided in config Change-Id: Ia2a79d6cb2a5eb263fb2e6db3f9cf9f2a7d57118 Signed-off-by: Anton Nikiforov --- cmd/frostfs-ir/config.go | 23 +++++- cmd/frostfs-ir/main.go | 4 ++ cmd/frostfs-node/config.go | 10 ++- cmd/frostfs-node/config/logger/config.go | 16 +++++ cmd/frostfs-node/validate.go | 5 ++ pkg/util/logger/logger.go | 92 +++++++++++++++++++----- pkg/util/logger/tag_string.go | 24 +++++++ pkg/util/logger/tags.go | 75 +++++++++++++++++++ 8 files changed, 231 insertions(+), 18 deletions(-) create mode 100644 pkg/util/logger/tag_string.go create mode 100644 pkg/util/logger/tags.go diff --git a/cmd/frostfs-ir/config.go b/cmd/frostfs-ir/config.go index 19b7f05d67..13a747ba6f 100644 --- a/cmd/frostfs-ir/config.go +++ b/cmd/frostfs-ir/config.go @@ -4,12 +4,14 @@ import ( "context" "os" "os/signal" + "strconv" "syscall" configViper "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/config" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" + "github.com/spf13/cast" "github.com/spf13/viper" "go.uber.org/zap" ) @@ -44,11 +46,30 @@ func reloadConfig() error { if err != nil { return err } - log.Reload(logPrm) + err = logPrm.SetTags(loggerTags()) + if err != nil { + return err + } + logger.UpdateLevelForTags(logPrm) return nil } +func loggerTags() [][]string { + var res [][]string + for i := 0; ; i++ { + var item []string + index := strconv.FormatInt(int64(i), 10) + names := cast.ToString(cfg.Get("logger.tags." + index + ".names")) + if names == "" { + break + } + item = append(item, names, cast.ToString(cfg.Get("logger.tags."+index+".level"))) + res = append(res, item) + } + return res +} + func watchForSignal(ctx context.Context, cancel func()) { ch := make(chan os.Signal, 1) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) diff --git a/cmd/frostfs-ir/main.go b/cmd/frostfs-ir/main.go index 114d8e4de1..799feb784e 100644 --- a/cmd/frostfs-ir/main.go +++ b/cmd/frostfs-ir/main.go @@ -80,10 +80,14 @@ func main() { exitErr(err) logPrm.SamplingHook = metrics.LogMetrics().GetSamplingHook() logPrm.PrependTimestamp = cfg.GetBool("logger.timestamp") + err = logPrm.SetTags(loggerTags()) + exitErr(err) log, err = logger.NewLogger(logPrm) exitErr(err) + logger.UpdateLevelForTags(logPrm) + ctx, cancel := context.WithCancel(context.Background()) pprofCmp = newPprofComponent() diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 4313162580..88e45d848b 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -109,6 +109,7 @@ type applicationConfiguration struct { destination string timestamp bool options []zap.Option + tags [][]string } ObjectCfg struct { @@ -241,6 +242,7 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { })} } a.LoggerCfg.options = opts + a.LoggerCfg.tags = loggerconfig.Tags(c) // Object @@ -727,6 +729,7 @@ func initCfg(appCfg *config.Config) *cfg { logPrm.SamplingHook = c.metricsCollector.LogMetrics().GetSamplingHook() log, err := logger.NewLogger(logPrm) fatalOnErr(err) + logger.UpdateLevelForTags(logPrm) c.internals = initInternals(appCfg, log) @@ -1094,6 +1097,11 @@ func (c *cfg) loggerPrm() (logger.Prm, error) { } prm.PrependTimestamp = c.LoggerCfg.timestamp prm.Options = c.LoggerCfg.options + err = prm.SetTags(c.LoggerCfg.tags) + if err != nil { + // not expected since validation should be performed before + return logger.Prm{}, errors.New("incorrect allowed tags format: " + c.LoggerCfg.destination) + } return prm, nil } @@ -1381,7 +1389,7 @@ func (c *cfg) getComponents(ctx context.Context) []dCmp { if err != nil { return err } - c.log.Reload(prm) + logger.UpdateLevelForTags(prm) return nil }}) components = append(components, dCmp{"runtime", func() error { diff --git a/cmd/frostfs-node/config/logger/config.go b/cmd/frostfs-node/config/logger/config.go index ba9eeea2b3..20f373184d 100644 --- a/cmd/frostfs-node/config/logger/config.go +++ b/cmd/frostfs-node/config/logger/config.go @@ -2,6 +2,7 @@ package loggerconfig import ( "os" + "strconv" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" @@ -60,6 +61,21 @@ func Timestamp(c *config.Config) bool { return config.BoolSafe(c.Sub(subsection), "timestamp") } +// Tags returns the value of "tags" config parameter from "logger" section. +func Tags(c *config.Config) [][]string { + var res [][]string + sub := c.Sub(subsection).Sub("tags") + for i := 0; ; i++ { + s := sub.Sub(strconv.FormatInt(int64(i), 10)) + names := config.StringSafe(s, "names") + if names == "" { + break + } + res = append(res, []string{names, config.StringSafe(s, "level")}) + } + return res +} + // ToLokiConfig extracts loki config. func ToLokiConfig(c *config.Config) loki.Config { hostname, _ := os.Hostname() diff --git a/cmd/frostfs-node/validate.go b/cmd/frostfs-node/validate.go index ae52b9e4ab..22d2e0aa93 100644 --- a/cmd/frostfs-node/validate.go +++ b/cmd/frostfs-node/validate.go @@ -30,6 +30,11 @@ func validateConfig(c *config.Config) error { return fmt.Errorf("invalid logger destination: %w", err) } + err = loggerPrm.SetTags(loggerconfig.Tags(c)) + if err != nil { + return fmt.Errorf("invalid list of allowed tags: %w", err) + } + // shard configuration validation shardNum := 0 diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index 10c7e8dc90..276847be13 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -13,8 +13,10 @@ import ( // Logger represents a component // for writing messages to log. type Logger struct { - z *zap.Logger - lvl zap.AtomicLevel + z *zap.Logger + c zapcore.Core + t Tag + w bool } // Prm groups Logger's parameters. @@ -39,6 +41,9 @@ type Prm struct { // Options for zap.Logger Options []zap.Option + + // map of tag's bit masks to log level, overrides lvl + tl map[Tag]zapcore.Level } const ( @@ -68,6 +73,12 @@ func (p *Prm) SetDestination(d string) error { return nil } +// SetTags parses list of tags with log level. +func (p *Prm) SetTags(tags [][]string) (err error) { + p.tl, err = parseTags(tags) + return err +} + // NewLogger constructs a new zap logger instance. Constructing with nil // parameters is safe: default values will be used then. // Passing non-nil parameters after a successful creation (non-error) allows @@ -91,10 +102,8 @@ func NewLogger(prm Prm) (*Logger, error) { } func newConsoleLogger(prm Prm) (*Logger, error) { - lvl := zap.NewAtomicLevelAt(prm.level) - c := zap.NewProductionConfig() - c.Level = lvl + c.Level = zap.NewAtomicLevelAt(zap.DebugLevel) c.Encoding = "console" if prm.SamplingHook != nil { c.Sampling.Hook = prm.SamplingHook @@ -115,15 +124,13 @@ func newConsoleLogger(prm Prm) (*Logger, error) { if err != nil { return nil, err } - - l := &Logger{z: lZap, lvl: lvl} + l := &Logger{z: lZap, c: lZap.Core()} + l = l.WithTag(TagMain) return l, nil } func newJournaldLogger(prm Prm) (*Logger, error) { - lvl := zap.NewAtomicLevelAt(prm.level) - c := zap.NewProductionConfig() if prm.SamplingHook != nil { c.Sampling.Hook = prm.SamplingHook @@ -137,7 +144,7 @@ func newJournaldLogger(prm Prm) (*Logger, error) { encoder := zapjournald.NewPartialEncoder(zapcore.NewConsoleEncoder(c.EncoderConfig), zapjournald.SyslogFields) - core := zapjournald.NewCore(lvl, encoder, &journald.Journal{}, zapjournald.SyslogFields) + core := zapjournald.NewCore(zap.NewAtomicLevelAt(zap.DebugLevel), encoder, &journald.Journal{}, zapjournald.SyslogFields) coreWithContext := core.With([]zapcore.Field{ zapjournald.SyslogFacility(zapjournald.LogDaemon), zapjournald.SyslogIdentifier(), @@ -161,22 +168,75 @@ func newJournaldLogger(prm Prm) (*Logger, error) { } opts = append(opts, prm.Options...) lZap := zap.New(samplingCore, opts...) - - l := &Logger{z: lZap, lvl: lvl} + l := &Logger{z: lZap, c: lZap.Core()} + l = l.WithTag(TagMain) return l, nil } -func (l *Logger) Reload(prm Prm) { - l.lvl.SetLevel(prm.level) +// With create a child logger with new fields, don't affect the parent. +// Throws panic if tag is unset. +func (l *Logger) With(fields ...zap.Field) *Logger { + if l.t == 0 { + panic("tag is unset") + } + c := *l + c.z = l.z.With(fields...) + // With called under the logger + c.w = true + return &c } -func (l *Logger) With(fields ...zap.Field) *Logger { - return &Logger{z: l.z.With(fields...)} +type core struct { + c zapcore.Core + l zap.AtomicLevel +} + +func (c *core) Enabled(lvl zapcore.Level) bool { + return c.l.Enabled(lvl) +} + +func (c *core) With(fields []zapcore.Field) zapcore.Core { + clone := *c + clone.c = clone.c.With(fields) + return &clone +} + +func (c *core) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry { + return c.c.Check(e, ce) +} + +func (c *core) Write(e zapcore.Entry, fields []zapcore.Field) error { + return c.c.Write(e, fields) +} + +func (c *core) Sync() error { + return c.c.Sync() +} + +// WithTag is an equivalent of calling [NewLogger] with the same parameters for the current logger. +// Throws panic if provided unsupported tag. +func (l *Logger) WithTag(tag Tag) *Logger { + if tag == 0 || tag > Tag(len(_Tag_index)-1) { + panic("unsupported tag " + tag.String()) + } + if l.w { + panic("unsupported operation for the logger's state") + } + c := *l + c.t = tag + c.z = l.z.WithOptions(zap.WrapCore(func(zapcore.Core) zapcore.Core { + return &core{ + c: l.c.With([]zap.Field{zap.String("tag", tag.String())}), + l: tagToLogLevel[tag], + } + })) + return &c } func NewLoggerWrapper(z *zap.Logger) *Logger { return &Logger{ z: z.WithOptions(zap.AddCallerSkip(1)), + t: TagMain, } } diff --git a/pkg/util/logger/tag_string.go b/pkg/util/logger/tag_string.go new file mode 100644 index 0000000000..80cb712ebd --- /dev/null +++ b/pkg/util/logger/tag_string.go @@ -0,0 +1,24 @@ +// Code generated by "stringer -type Tag -linecomment"; DO NOT EDIT. + +package logger + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[TagMain-1] +} + +const _Tag_name = "main" + +var _Tag_index = [...]uint8{0, 4} + +func (i Tag) String() string { + i -= 1 + if i >= Tag(len(_Tag_index)-1) { + return "Tag(" + strconv.FormatInt(int64(i+1), 10) + ")" + } + return _Tag_name[_Tag_index[i]:_Tag_index[i+1]] +} diff --git a/pkg/util/logger/tags.go b/pkg/util/logger/tags.go new file mode 100644 index 0000000000..06abcabe5d --- /dev/null +++ b/pkg/util/logger/tags.go @@ -0,0 +1,75 @@ +package logger + +import ( + "fmt" + "strings" + + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +//go:generate stringer -type Tag -linecomment + +type Tag uint8 + +const ( + _ Tag = iota // + TagMain // main + + defaultLevel = zapcore.InfoLevel +) + +var ( + tagToLogLevel = map[Tag]zap.AtomicLevel{} + stringToTag = map[string]Tag{} +) + +func init() { + for i := TagMain; i <= Tag(len(_Tag_index)-1); i++ { + tagToLogLevel[i] = zap.NewAtomicLevelAt(defaultLevel) + stringToTag[i.String()] = i + } +} + +// parseTags returns: +// - map(always instantiated) of tag to custom log level for that tag; +// - error if it occurred(map is empty). +func parseTags(raw [][]string) (map[Tag]zapcore.Level, error) { + m := make(map[Tag]zapcore.Level) + if len(raw) == 0 { + return m, nil + } + for _, item := range raw { + str, level := item[0], item[1] + if len(level) == 0 { + // It is not necessary to parse tags without level, + // because default log level will be used. + continue + } + var l zapcore.Level + err := l.UnmarshalText([]byte(level)) + if err != nil { + return nil, err + } + tmp := strings.Split(str, ",") + for _, tagStr := range tmp { + tag, ok := stringToTag[strings.TrimSpace(tagStr)] + if !ok { + return nil, fmt.Errorf("unsupported tag %s", str) + } + m[tag] = l + } + } + return m, nil +} + +func UpdateLevelForTags(prm Prm) { + for k, v := range tagToLogLevel { + nk, ok := prm.tl[k] + if ok { + v.SetLevel(nk) + } else { + v.SetLevel(prm.level) + } + } +} From 12fc7850dd78d6ea0818f90d90388de8e42d190c Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 29 Jan 2025 14:37:17 +0300 Subject: [PATCH 1359/1413] [#1619] logger: Set tags for `ir` components Change-Id: Ifab575bc2a3cd83c9001cd68fffaf94c91494043 Signed-off-by: Anton Nikiforov --- config/example/ir.env | 2 ++ config/example/ir.yaml | 3 +++ pkg/innerring/initialization.go | 16 ++++++++-------- pkg/innerring/innerring.go | 2 +- pkg/util/logger/tag_string.go | 8 ++++++-- pkg/util/logger/tags.go | 8 ++++++-- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/config/example/ir.env b/config/example/ir.env index ebd91c243e..c13044a6ed 100644 --- a/config/example/ir.env +++ b/config/example/ir.env @@ -1,5 +1,7 @@ FROSTFS_IR_LOGGER_LEVEL=info FROSTFS_IR_LOGGER_TIMESTAMP=true +FROSTFS_IR_LOGGER_TAGS_0_NAMES="main, morph" +FROSTFS_IR_LOGGER_TAGS_0_LEVEL="debug" FROSTFS_IR_WALLET_PATH=/path/to/wallet.json FROSTFS_IR_WALLET_ADDRESS=NUHtW3eM6a4mmFCgyyr4rj4wygsTKB88XX diff --git a/config/example/ir.yaml b/config/example/ir.yaml index 49f9fd324c..a4a0065507 100644 --- a/config/example/ir.yaml +++ b/config/example/ir.yaml @@ -3,6 +3,9 @@ logger: level: info # Logger level: one of "debug", "info" (default), "warn", "error", "dpanic", "panic", "fatal" timestamp: true + tags: + - names: "main, morph" # Possible values: `main`, `morph`, `grpc_svc`, `ir`, `processor`. + level: debug wallet: path: /path/to/wallet.json # Path to NEP-6 NEO wallet file diff --git a/pkg/innerring/initialization.go b/pkg/innerring/initialization.go index f7b71dbe6f..3d236641e4 100644 --- a/pkg/innerring/initialization.go +++ b/pkg/innerring/initialization.go @@ -50,7 +50,7 @@ func (s *Server) initNetmapProcessor(ctx context.Context, cfg *viper.Viper, var err error s.netmapProcessor, err = netmap.New(&netmap.Params{ - Log: s.log, + Log: s.log.WithTag(logger.TagProcessor), Metrics: s.irMetrics, PoolSize: poolSize, NetmapClient: netmap.NewNetmapClient(s.netmapClient), @@ -159,7 +159,7 @@ func (s *Server) createAlphaSync(cfg *viper.Viper, frostfsCli *frostfsClient.Cli } else { // create governance processor governanceProcessor, err := governance.New(&governance.Params{ - Log: s.log, + Log: s.log.WithTag(logger.TagProcessor), Metrics: s.irMetrics, FrostFSClient: frostfsCli, AlphabetState: s, @@ -225,7 +225,7 @@ func (s *Server) initAlphabetProcessor(ctx context.Context, cfg *viper.Viper) er // create alphabet processor s.alphabetProcessor, err = alphabet.New(&alphabet.Params{ ParsedWallets: parsedWallets, - Log: s.log, + Log: s.log.WithTag(logger.TagProcessor), Metrics: s.irMetrics, PoolSize: poolSize, AlphabetContracts: s.contracts.alphabet, @@ -247,7 +247,7 @@ func (s *Server) initContainerProcessor(ctx context.Context, cfg *viper.Viper, c s.log.Debug(ctx, logs.ContainerContainerWorkerPool, zap.Int("size", poolSize)) // container processor containerProcessor, err := cont.New(&cont.Params{ - Log: s.log, + Log: s.log.WithTag(logger.TagProcessor), Metrics: s.irMetrics, PoolSize: poolSize, AlphabetState: s, @@ -268,7 +268,7 @@ func (s *Server) initBalanceProcessor(ctx context.Context, cfg *viper.Viper, fro s.log.Debug(ctx, logs.BalanceBalanceWorkerPool, zap.Int("size", poolSize)) // create balance processor balanceProcessor, err := balance.New(&balance.Params{ - Log: s.log, + Log: s.log.WithTag(logger.TagProcessor), Metrics: s.irMetrics, PoolSize: poolSize, FrostFSClient: frostfsCli, @@ -291,7 +291,7 @@ func (s *Server) initFrostFSMainnetProcessor(ctx context.Context, cfg *viper.Vip s.log.Debug(ctx, logs.FrostFSFrostfsWorkerPool, zap.Int("size", poolSize)) frostfsProcessor, err := frostfs.New(&frostfs.Params{ - Log: s.log, + Log: s.log.WithTag(logger.TagProcessor), Metrics: s.irMetrics, PoolSize: poolSize, FrostFSContract: s.contracts.frostfs, @@ -342,7 +342,7 @@ func (s *Server) initGRPCServer(ctx context.Context, cfg *viper.Viper, log *logg controlSvc := controlsrv.NewAuditService(controlsrv.New(p, s.netmapClient, s.containerClient, controlsrv.WithAllowedKeys(authKeys), - ), log, audit) + ), log.WithTag(logger.TagGrpcSvc), audit) grpcControlSrv := grpc.NewServer() control.RegisterControlServiceServer(grpcControlSrv, controlSvc) @@ -458,7 +458,7 @@ func (s *Server) initMorph(ctx context.Context, cfg *viper.Viper, errChan chan<- } morphChain := &chainParams{ - log: s.log, + log: s.log.WithTag(logger.TagMorph), cfg: cfg, key: s.key, name: morphPrefix, diff --git a/pkg/innerring/innerring.go b/pkg/innerring/innerring.go index ae5661905c..3a51372618 100644 --- a/pkg/innerring/innerring.go +++ b/pkg/innerring/innerring.go @@ -339,7 +339,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan ) (*Server, error) { var err error server := &Server{ - log: log, + log: log.WithTag(logger.TagIr), irMetrics: metrics, cmode: cmode, } diff --git a/pkg/util/logger/tag_string.go b/pkg/util/logger/tag_string.go index 80cb712ebd..a25b3c4454 100644 --- a/pkg/util/logger/tag_string.go +++ b/pkg/util/logger/tag_string.go @@ -9,11 +9,15 @@ func _() { // Re-run the stringer command to generate them again. var x [1]struct{} _ = x[TagMain-1] + _ = x[TagMorph-2] + _ = x[TagGrpcSvc-3] + _ = x[TagIr-4] + _ = x[TagProcessor-5] } -const _Tag_name = "main" +const _Tag_name = "mainmorphgrpc_svcirprocessor" -var _Tag_index = [...]uint8{0, 4} +var _Tag_index = [...]uint8{0, 4, 9, 17, 19, 28} func (i Tag) String() string { i -= 1 diff --git a/pkg/util/logger/tags.go b/pkg/util/logger/tags.go index 06abcabe5d..51a6f62da4 100644 --- a/pkg/util/logger/tags.go +++ b/pkg/util/logger/tags.go @@ -13,8 +13,12 @@ import ( type Tag uint8 const ( - _ Tag = iota // - TagMain // main + _ Tag = iota // + TagMain // main + TagMorph // morph + TagGrpcSvc // grpc_svc + TagIr // ir + TagProcessor // processor defaultLevel = zapcore.InfoLevel ) From 8e87cbee17d3374c55a536bc14f02acb752f9d5f Mon Sep 17 00:00:00 2001 From: Vitaliy Potyarkin Date: Fri, 11 Apr 2025 14:44:19 +0300 Subject: [PATCH 1360/1413] [#1689] ci: Move commit checker out of Jenkinsfile Commit checker is now configured globally for all Gerrit repositories: https://git.frostfs.info/TrueCloudLab/jenkins/pulls/16 This allows us to execute commit-checker independently from the rest of CI suite and re-check commit message format without rerunning other tests. Change-Id: Ib8f899b856482a5dc5d03861171585415ff6b452 Signed-off-by: Vitaliy Potyarkin --- .ci/Jenkinsfile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index 4ddd36406f..4234de160b 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -78,10 +78,4 @@ async { } } } - - task('dco') { - container('git.frostfs.info/truecloudlab/commit-check:master') { - sh 'FROM=pull_request_target commit-check' - } - } } From 0d36e93169495b82e0cd23ff0c681c67c020c5e6 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 9 Apr 2025 16:27:03 +0300 Subject: [PATCH 1361/1413] [#1332] cli/playground: Move command handler selection to separate function Change-Id: I2dcbd85e61960c3cf141b815edab174e308ef858 Signed-off-by: Alexander Chuprov --- .../modules/container/policy_playground.go | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index f747b3252b..a9dea13b17 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -260,6 +260,28 @@ Example of usage: }, } +func (repl *policyPlaygroundREPL) handleCommand(args []string) error { + if len(args) == 0 { + return nil + } + + switch args[0] { + case "list", "ls": + return repl.handleLs(args[1:]) + case "add": + return repl.handleAdd(args[1:]) + case "load": + return repl.handleLoad(args[1:]) + case "remove", "rm": + return repl.handleRemove(args[1:]) + case "eval": + return repl.handleEval(args[1:]) + case "help": + return repl.handleHelp(args[1:]) + } + return fmt.Errorf("unknown command %q", args[0]) +} + func (repl *policyPlaygroundREPL) run() error { if len(viper.GetString(commonflags.RPC)) > 0 { key := key.GetOrGenerate(repl.cmd) @@ -277,17 +299,6 @@ func (repl *policyPlaygroundREPL) run() error { } } - cmdHandlers := map[string]func([]string) error{ - "list": repl.handleLs, - "ls": repl.handleLs, - "add": repl.handleAdd, - "load": repl.handleLoad, - "remove": repl.handleRemove, - "rm": repl.handleRemove, - "eval": repl.handleEval, - "help": repl.handleHelp, - } - var cfgCompleter []readline.PrefixCompleterInterface var helpSubItems []readline.PrefixCompleterInterface @@ -326,17 +337,8 @@ func (repl *policyPlaygroundREPL) run() error { } exit = false - parts := strings.Fields(line) - if len(parts) == 0 { - continue - } - cmd := parts[0] - if handler, exists := cmdHandlers[cmd]; exists { - if err := handler(parts[1:]); err != nil { - fmt.Fprintf(repl.console, "error: %v\n", err) - } - } else { - fmt.Fprintf(repl.console, "error: unknown command %q\n", cmd) + if err := repl.handleCommand(strings.Fields(line)); err != nil { + fmt.Fprintf(repl.console, "error: %v\n", err) } } } From 29b4fbe451bb695724e529e757e339f235dd8759 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 9 Apr 2025 16:31:48 +0300 Subject: [PATCH 1362/1413] [#1332] cli/playground: Add 'netmap-config' flag Change-Id: I4342fb9a6da2a05c18ae4e0ad9f0c71550efc5ef Signed-off-by: Alexander Chuprov --- .../modules/container/policy_playground.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index a9dea13b17..377cf43c6f 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -299,6 +299,11 @@ func (repl *policyPlaygroundREPL) run() error { } } + if len(viper.GetString(netmapConfigPath)) > 0 { + err := repl.handleLoad([]string{viper.GetString(netmapConfigPath)}) + commonCmd.ExitOnErr(repl.cmd, "load netmap config error: %w", err) + } + var cfgCompleter []readline.PrefixCompleterInterface var helpSubItems []readline.PrefixCompleterInterface @@ -354,6 +359,14 @@ If a wallet and endpoint is provided, the initial netmap data will be loaded fro }, } +const ( + netmapConfigPath = "netmap-config" + netmapConfigUsage = "Path to the netmap configuration file" +) + func initContainerPolicyPlaygroundCmd() { commonflags.Init(policyPlaygroundCmd) + policyPlaygroundCmd.Flags().String(netmapConfigPath, "", netmapConfigUsage) + + _ = viper.BindPFlag(netmapConfigPath, policyPlaygroundCmd.Flags().Lookup(netmapConfigPath)) } From 3be33b7117900ba1dc715e330545ca6ff5d44dc4 Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Wed, 9 Apr 2025 16:34:16 +0300 Subject: [PATCH 1363/1413] [#1706] cli/playground: Mention 'help' in error message for invalid commands Change-Id: Ica1112b907919a6d19fa1bf683f2a952c4c638e4 Signed-off-by: Alexander Chuprov --- cmd/frostfs-cli/modules/container/policy_playground.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 377cf43c6f..2cc1107ef2 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -279,7 +279,7 @@ func (repl *policyPlaygroundREPL) handleCommand(args []string) error { case "help": return repl.handleHelp(args[1:]) } - return fmt.Errorf("unknown command %q", args[0]) + return fmt.Errorf("unknown command %q. See 'help' for assistance", args[0]) } func (repl *policyPlaygroundREPL) run() error { From 5aaa3df533c02763db0dfef0ad5fd63cb0bebc46 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 11 Apr 2025 14:56:07 +0300 Subject: [PATCH 1364/1413] [#1700] config: Move config struct to qos package Change-Id: Ie642fff5cd1702cda00425628e11f3fd8c514798 Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 2 +- cmd/frostfs-node/config/engine/config_test.go | 36 ++++++---- .../config/engine/shard/limits/config.go | 66 ++++++------------- config/example/node.env | 6 ++ config/example/node.json | 10 +++ config/example/node.yaml | 6 ++ internal/qos/config.go | 31 +++++++++ internal/qos/limiter.go | 15 ++--- internal/qos/validate.go | 12 ++-- 9 files changed, 109 insertions(+), 75 deletions(-) create mode 100644 internal/qos/config.go diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 88e45d848b..2980491585 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -385,7 +385,7 @@ func (a *applicationConfiguration) setGCConfig(target *shardCfg, source *shardco } func (a *applicationConfiguration) setLimiter(target *shardCfg, source *shardconfig.Config) error { - limitsConfig := source.Limits() + limitsConfig := source.Limits().ToConfig() limiter, err := qos.NewLimiter(limitsConfig) if err != nil { return err diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 22f26268d0..34613ad9e5 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -11,10 +11,10 @@ import ( blobovniczaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/blobovnicza" fstreeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/blobstor/fstree" gcconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/gc" - limitsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" piloramaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/pilorama" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/writecache" configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" ) @@ -135,8 +135,8 @@ func TestEngineSection(t *testing.T) { require.Equal(t, mode.ReadOnly, sc.Mode()) require.Equal(t, 100, sc.RefillMetabaseWorkersCount()) - readLimits := limits.Read() - writeLimits := limits.Write() + readLimits := limits.ToConfig().Read + writeLimits := limits.ToConfig().Write require.Equal(t, 30*time.Second, readLimits.IdleTimeout) require.Equal(t, int64(10_000), readLimits.MaxRunningOps) require.Equal(t, int64(1_000), readLimits.MaxWaitingOps) @@ -144,7 +144,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, int64(1_000), writeLimits.MaxRunningOps) require.Equal(t, int64(100), writeLimits.MaxWaitingOps) require.ElementsMatch(t, readLimits.Tags, - []limitsconfig.IOTagConfig{ + []qos.IOTagConfig{ { Tag: "internal", Weight: toPtr(20), @@ -173,9 +173,14 @@ func TestEngineSection(t *testing.T) { LimitOps: toPtr(25000), Prohibited: true, }, + { + Tag: "treesync", + Weight: toPtr(5), + LimitOps: toPtr(25), + }, }) require.ElementsMatch(t, writeLimits.Tags, - []limitsconfig.IOTagConfig{ + []qos.IOTagConfig{ { Tag: "internal", Weight: toPtr(200), @@ -203,6 +208,11 @@ func TestEngineSection(t *testing.T) { Weight: toPtr(50), LimitOps: toPtr(2500), }, + { + Tag: "treesync", + Weight: toPtr(50), + LimitOps: toPtr(100), + }, }) case 1: require.Equal(t, "tmp/1/blob/pilorama.db", pl.Path()) @@ -259,14 +269,14 @@ func TestEngineSection(t *testing.T) { require.Equal(t, mode.ReadWrite, sc.Mode()) require.Equal(t, shardconfig.RefillMetabaseWorkersCountDefault, sc.RefillMetabaseWorkersCount()) - readLimits := limits.Read() - writeLimits := limits.Write() - require.Equal(t, limitsconfig.DefaultIdleTimeout, readLimits.IdleTimeout) - require.Equal(t, limitsconfig.NoLimit, readLimits.MaxRunningOps) - require.Equal(t, limitsconfig.NoLimit, readLimits.MaxWaitingOps) - require.Equal(t, limitsconfig.DefaultIdleTimeout, writeLimits.IdleTimeout) - require.Equal(t, limitsconfig.NoLimit, writeLimits.MaxRunningOps) - require.Equal(t, limitsconfig.NoLimit, writeLimits.MaxWaitingOps) + readLimits := limits.ToConfig().Read + writeLimits := limits.ToConfig().Write + require.Equal(t, qos.DefaultIdleTimeout, readLimits.IdleTimeout) + require.Equal(t, qos.NoLimit, readLimits.MaxRunningOps) + require.Equal(t, qos.NoLimit, readLimits.MaxWaitingOps) + require.Equal(t, qos.DefaultIdleTimeout, writeLimits.IdleTimeout) + require.Equal(t, qos.NoLimit, writeLimits.MaxRunningOps) + require.Equal(t, qos.NoLimit, writeLimits.MaxWaitingOps) require.Equal(t, 0, len(readLimits.Tags)) require.Equal(t, 0, len(writeLimits.Tags)) } diff --git a/cmd/frostfs-node/config/engine/shard/limits/config.go b/cmd/frostfs-node/config/engine/shard/limits/config.go index 8444d6aa83..ccd1e0000d 100644 --- a/cmd/frostfs-node/config/engine/shard/limits/config.go +++ b/cmd/frostfs-node/config/engine/shard/limits/config.go @@ -1,19 +1,13 @@ package limits import ( - "math" "strconv" - "time" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "github.com/spf13/cast" ) -const ( - NoLimit int64 = math.MaxInt64 - DefaultIdleTimeout = 5 * time.Minute -) - // From wraps config section into Config. func From(c *config.Config) *Config { return (*Config)(c) @@ -23,36 +17,43 @@ func From(c *config.Config) *Config { // which provides access to Shard's limits configurations. type Config config.Config -// Read returns the value of "read" limits config section. -func (x *Config) Read() OpConfig { +func (x *Config) ToConfig() qos.LimiterConfig { + result := qos.LimiterConfig{ + Read: x.read(), + Write: x.write(), + } + panicOnErr(result.Validate()) + return result +} + +func (x *Config) read() qos.OpConfig { return x.parse("read") } -// Write returns the value of "write" limits config section. -func (x *Config) Write() OpConfig { +func (x *Config) write() qos.OpConfig { return x.parse("write") } -func (x *Config) parse(sub string) OpConfig { +func (x *Config) parse(sub string) qos.OpConfig { c := (*config.Config)(x).Sub(sub) - var result OpConfig + var result qos.OpConfig if s := config.Int(c, "max_waiting_ops"); s > 0 { result.MaxWaitingOps = s } else { - result.MaxWaitingOps = NoLimit + result.MaxWaitingOps = qos.NoLimit } if s := config.Int(c, "max_running_ops"); s > 0 { result.MaxRunningOps = s } else { - result.MaxRunningOps = NoLimit + result.MaxRunningOps = qos.NoLimit } if s := config.DurationSafe(c, "idle_timeout"); s > 0 { result.IdleTimeout = s } else { - result.IdleTimeout = DefaultIdleTimeout + result.IdleTimeout = qos.DefaultIdleTimeout } result.Tags = tags(c) @@ -60,43 +61,16 @@ func (x *Config) parse(sub string) OpConfig { return result } -type OpConfig struct { - // MaxWaitingOps returns the value of "max_waiting_ops" config parameter. - // - // Equals NoLimit if the value is not a positive number. - MaxWaitingOps int64 - // MaxRunningOps returns the value of "max_running_ops" config parameter. - // - // Equals NoLimit if the value is not a positive number. - MaxRunningOps int64 - // IdleTimeout returns the value of "idle_timeout" config parameter. - // - // Equals DefaultIdleTimeout if the value is not a valid duration. - IdleTimeout time.Duration - // Tags returns the value of "tags" config parameter. - // - // Equals nil if the value is not a valid tags config slice. - Tags []IOTagConfig -} - -type IOTagConfig struct { - Tag string - Weight *float64 - LimitOps *float64 - ReservedOps *float64 - Prohibited bool -} - -func tags(c *config.Config) []IOTagConfig { +func tags(c *config.Config) []qos.IOTagConfig { c = c.Sub("tags") - var result []IOTagConfig + var result []qos.IOTagConfig for i := 0; ; i++ { tag := config.String(c, strconv.Itoa(i)+".tag") if tag == "" { return result } - var tagConfig IOTagConfig + var tagConfig qos.IOTagConfig tagConfig.Tag = tag v := c.Value(strconv.Itoa(i) + ".weight") diff --git a/config/example/node.env b/config/example/node.env index b7c798ad8c..dfb250341f 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -181,6 +181,9 @@ FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_TAG=policer FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_WEIGHT=5 FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_LIMIT_OPS=25000 FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_4_PROHIBITED=true +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_5_TAG=treesync +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_5_WEIGHT=5 +FROSTFS_STORAGE_SHARD_0_LIMITS_READ_TAGS_5_LIMIT_OPS=25 FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_TAG=internal FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_WEIGHT=200 FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_0_LIMIT_OPS=0 @@ -198,6 +201,9 @@ FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_3_LIMIT_OPS=2500 FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_4_TAG=policer FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_4_WEIGHT=50 FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_4_LIMIT_OPS=2500 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_5_TAG=treesync +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_5_WEIGHT=50 +FROSTFS_STORAGE_SHARD_0_LIMITS_WRITE_TAGS_5_LIMIT_OPS=100 ## 1 shard ### Flag to refill Metabase from BlobStor diff --git a/config/example/node.json b/config/example/node.json index 2f4413e4d0..0b061a3d45 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -254,6 +254,11 @@ "weight": 5, "limit_ops": 25000, "prohibited": true + }, + { + "tag": "treesync", + "weight": 5, + "limit_ops": 25 } ] }, @@ -288,6 +293,11 @@ "tag": "policer", "weight": 50, "limit_ops": 2500 + }, + { + "tag": "treesync", + "weight": 50, + "limit_ops": 100 } ] } diff --git a/config/example/node.yaml b/config/example/node.yaml index 0b6c7b12c0..46e4ebdbea 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -253,6 +253,9 @@ storage: weight: 5 limit_ops: 25000 prohibited: true + - tag: treesync + weight: 5 + limit_ops: 25 write: max_running_ops: 1000 max_waiting_ops: 100 @@ -275,6 +278,9 @@ storage: - tag: policer weight: 50 limit_ops: 2500 + - tag: treesync + weight: 50 + limit_ops: 100 1: writecache: diff --git a/internal/qos/config.go b/internal/qos/config.go new file mode 100644 index 0000000000..d90b403b56 --- /dev/null +++ b/internal/qos/config.go @@ -0,0 +1,31 @@ +package qos + +import ( + "math" + "time" +) + +const ( + NoLimit int64 = math.MaxInt64 + DefaultIdleTimeout = 5 * time.Minute +) + +type LimiterConfig struct { + Read OpConfig + Write OpConfig +} + +type OpConfig struct { + MaxWaitingOps int64 + MaxRunningOps int64 + IdleTimeout time.Duration + Tags []IOTagConfig +} + +type IOTagConfig struct { + Tag string + Weight *float64 + LimitOps *float64 + ReservedOps *float64 + Prohibited bool +} diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index c73481c2c3..5851d76267 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -8,7 +8,6 @@ import ( "sync/atomic" "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" "git.frostfs.info/TrueCloudLab/frostfs-qos/scheduling" "git.frostfs.info/TrueCloudLab/frostfs-qos/tagging" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -37,15 +36,15 @@ type scheduler interface { Close() } -func NewLimiter(c *limits.Config) (Limiter, error) { - if err := validateConfig(c); err != nil { +func NewLimiter(c LimiterConfig) (Limiter, error) { + if err := c.Validate(); err != nil { return nil, err } - readScheduler, err := createScheduler(c.Read()) + readScheduler, err := createScheduler(c.Read) if err != nil { return nil, fmt.Errorf("create read scheduler: %w", err) } - writeScheduler, err := createScheduler(c.Write()) + writeScheduler, err := createScheduler(c.Write) if err != nil { return nil, fmt.Errorf("create write scheduler: %w", err) } @@ -63,8 +62,8 @@ func NewLimiter(c *limits.Config) (Limiter, error) { return l, nil } -func createScheduler(config limits.OpConfig) (scheduler, error) { - if len(config.Tags) == 0 && config.MaxWaitingOps == limits.NoLimit { +func createScheduler(config OpConfig) (scheduler, error) { + if len(config.Tags) == 0 && config.MaxWaitingOps == NoLimit { return newSemaphoreScheduler(config.MaxRunningOps), nil } return scheduling.NewMClock( @@ -72,7 +71,7 @@ func createScheduler(config limits.OpConfig) (scheduler, error) { converToSchedulingTags(config.Tags), config.IdleTimeout) } -func converToSchedulingTags(limits []limits.IOTagConfig) map[string]scheduling.TagInfo { +func converToSchedulingTags(limits []IOTagConfig) map[string]scheduling.TagInfo { result := make(map[string]scheduling.TagInfo) for _, tag := range []IOTag{IOTagBackground, IOTagClient, IOTagInternal, IOTagPolicer, IOTagTreeSync, IOTagWritecache} { result[tag.String()] = scheduling.TagInfo{ diff --git a/internal/qos/validate.go b/internal/qos/validate.go index d4475e38ba..70f1f24e8e 100644 --- a/internal/qos/validate.go +++ b/internal/qos/validate.go @@ -4,8 +4,6 @@ import ( "errors" "fmt" "math" - - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/limits" ) var errWeightsMustBeSpecified = errors.New("invalid weights: weights must be specified for all tags or not specified for any") @@ -14,17 +12,17 @@ type tagConfig struct { Shares, Limit, Reserved *float64 } -func validateConfig(c *limits.Config) error { - if err := validateOpConfig(c.Read()); err != nil { +func (c *LimiterConfig) Validate() error { + if err := validateOpConfig(c.Read); err != nil { return fmt.Errorf("limits 'read' section validation error: %w", err) } - if err := validateOpConfig(c.Write()); err != nil { + if err := validateOpConfig(c.Write); err != nil { return fmt.Errorf("limits 'write' section validation error: %w", err) } return nil } -func validateOpConfig(c limits.OpConfig) error { +func validateOpConfig(c OpConfig) error { if c.MaxRunningOps <= 0 { return fmt.Errorf("invalid 'max_running_ops = %d': must be greater than zero", c.MaxRunningOps) } @@ -40,7 +38,7 @@ func validateOpConfig(c limits.OpConfig) error { return nil } -func validateTags(configTags []limits.IOTagConfig) error { +func validateTags(configTags []IOTagConfig) error { tags := map[IOTag]tagConfig{ IOTagBackground: {}, IOTagClient: {}, From e80632884a2a89c6a5edfcb46cc1a939c9413028 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 11 Apr 2025 16:21:27 +0300 Subject: [PATCH 1365/1413] [#1700] config: Drop redundant check Target config created on level above, so limiter is always nil. Change-Id: I1896baae5b9ddeed339a7d2b022a9a886589d362 Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/config.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 2980491585..b167439e05 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -390,9 +390,6 @@ func (a *applicationConfiguration) setLimiter(target *shardCfg, source *shardcon if err != nil { return err } - if target.limiter != nil { - target.limiter.Close() - } target.limiter = limiter return nil } From fd37cea443df4aad4b3a61db0e31fbfa0ae94c33 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 11 Apr 2025 17:08:44 +0300 Subject: [PATCH 1366/1413] [#1700] engine: Drop unused block execution methods `BlockExecution` and `ResumeExecution` were used only by unit test. So drop them and simplify code. Change-Id: Ib3de324617e8a27fc1f015542ac5e94df5c60a6e Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/engine/control.go | 67 +++---------------- .../engine/control_test.go | 40 ----------- pkg/local_object_storage/engine/engine.go | 5 +- 3 files changed, 10 insertions(+), 102 deletions(-) diff --git a/pkg/local_object_storage/engine/control.go b/pkg/local_object_storage/engine/control.go index 96b53581e7..bf1649f6ea 100644 --- a/pkg/local_object_storage/engine/control.go +++ b/pkg/local_object_storage/engine/control.go @@ -22,10 +22,6 @@ type shardInitError struct { // Open opens all StorageEngine's components. func (e *StorageEngine) Open(ctx context.Context) error { - return e.open(ctx) -} - -func (e *StorageEngine) open(ctx context.Context) error { e.mtx.Lock() defer e.mtx.Unlock() @@ -149,11 +145,11 @@ var errClosed = errors.New("storage engine is closed") func (e *StorageEngine) Close(ctx context.Context) error { close(e.closeCh) defer e.wg.Wait() - return e.setBlockExecErr(ctx, errClosed) + return e.closeEngine(ctx) } // closes all shards. Never returns an error, shard errors are logged. -func (e *StorageEngine) close(ctx context.Context) error { +func (e *StorageEngine) closeAllShards(ctx context.Context) error { e.mtx.RLock() defer e.mtx.RUnlock() @@ -176,70 +172,23 @@ func (e *StorageEngine) execIfNotBlocked(op func() error) error { e.blockExec.mtx.RLock() defer e.blockExec.mtx.RUnlock() - if e.blockExec.err != nil { - return e.blockExec.err + if e.blockExec.closed { + return errClosed } return op() } -// sets the flag of blocking execution of all data operations according to err: -// - err != nil, then blocks the execution. If exec wasn't blocked, calls close method -// (if err == errClosed => additionally releases pools and does not allow to resume executions). -// - otherwise, resumes execution. If exec was blocked, calls open method. -// -// Can be called concurrently with exec. In this case it waits for all executions to complete. -func (e *StorageEngine) setBlockExecErr(ctx context.Context, err error) error { +func (e *StorageEngine) closeEngine(ctx context.Context) error { e.blockExec.mtx.Lock() defer e.blockExec.mtx.Unlock() - prevErr := e.blockExec.err - - wasClosed := errors.Is(prevErr, errClosed) - if wasClosed { + if e.blockExec.closed { return errClosed } - e.blockExec.err = err - - if err == nil { - if prevErr != nil { // block -> ok - return e.open(ctx) - } - } else if prevErr == nil { // ok -> block - return e.close(ctx) - } - - // otherwise do nothing - - return nil -} - -// BlockExecution blocks the execution of any data-related operation. All blocked ops will return err. -// To resume the execution, use ResumeExecution method. -// -// Сan be called regardless of the fact of the previous blocking. If execution wasn't blocked, releases all resources -// similar to Close. Can be called concurrently with Close and any data related method (waits for all executions -// to complete). Returns error if any Close has been called before. -// -// Must not be called concurrently with either Open or Init. -// -// Note: technically passing nil error will resume the execution, otherwise, it is recommended to call ResumeExecution -// for this. -func (e *StorageEngine) BlockExecution(err error) error { - return e.setBlockExecErr(context.Background(), err) -} - -// ResumeExecution resumes the execution of any data-related operation. -// To block the execution, use BlockExecution method. -// -// Сan be called regardless of the fact of the previous blocking. If execution was blocked, prepares all resources -// similar to Open. Can be called concurrently with Close and any data related method (waits for all executions -// to complete). Returns error if any Close has been called before. -// -// Must not be called concurrently with either Open or Init. -func (e *StorageEngine) ResumeExecution() error { - return e.setBlockExecErr(context.Background(), nil) + e.blockExec.closed = true + return e.closeAllShards(ctx) } type ReConfiguration struct { diff --git a/pkg/local_object_storage/engine/control_test.go b/pkg/local_object_storage/engine/control_test.go index a0e658aebb..4ff0ed5ec6 100644 --- a/pkg/local_object_storage/engine/control_test.go +++ b/pkg/local_object_storage/engine/control_test.go @@ -2,7 +2,6 @@ package engine import ( "context" - "errors" "fmt" "io/fs" "os" @@ -12,17 +11,14 @@ import ( "testing" "time" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/testutil" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/writecache" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger/test" - cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" "github.com/stretchr/testify/require" "go.etcd.io/bbolt" ) @@ -163,42 +159,6 @@ func testEngineFailInitAndReload(t *testing.T, degradedMode bool, opts []shard.O require.Equal(t, 1, shardCount) } -func TestExecBlocks(t *testing.T) { - e := testNewEngine(t).setShardsNum(t, 2).prepare(t).engine // number doesn't matter in this test, 2 is several but not many - - // put some object - obj := testutil.GenerateObjectWithCID(cidtest.ID()) - - addr := object.AddressOf(obj) - - require.NoError(t, Put(context.Background(), e, obj, false)) - - // block executions - errBlock := errors.New("block exec err") - - require.NoError(t, e.BlockExecution(errBlock)) - - // try to exec some op - _, err := Head(context.Background(), e, addr) - require.ErrorIs(t, err, errBlock) - - // resume executions - require.NoError(t, e.ResumeExecution()) - - _, err = Head(context.Background(), e, addr) // can be any data-related op - require.NoError(t, err) - - // close - require.NoError(t, e.Close(context.Background())) - - // try exec after close - _, err = Head(context.Background(), e, addr) - require.Error(t, err) - - // try to resume - require.Error(t, e.ResumeExecution()) -} - func TestPersistentShardID(t *testing.T) { dir := t.TempDir() diff --git a/pkg/local_object_storage/engine/engine.go b/pkg/local_object_storage/engine/engine.go index 1d33c0592c..376d545d38 100644 --- a/pkg/local_object_storage/engine/engine.go +++ b/pkg/local_object_storage/engine/engine.go @@ -33,9 +33,8 @@ type StorageEngine struct { wg sync.WaitGroup blockExec struct { - mtx sync.RWMutex - - err error + mtx sync.RWMutex + closed bool } evacuateLimiter *evacuationLimiter } From f37babdc5482334a3c573f09c7b43f43943d7dfa Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 14 Apr 2025 09:51:50 +0300 Subject: [PATCH 1367/1413] [#1700] shard: Lock shard's mode mutex on close To prevent race between GC handlers and close. Change-Id: I06219230964f000f666a56158d3563c760518c3b Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/control.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/local_object_storage/shard/control.go b/pkg/local_object_storage/shard/control.go index 72e650c5e8..d489b8b0dc 100644 --- a/pkg/local_object_storage/shard/control.go +++ b/pkg/local_object_storage/shard/control.go @@ -363,6 +363,7 @@ func (s *Shard) refillTombstoneObject(ctx context.Context, obj *objectSDK.Object // Close releases all Shard's components. func (s *Shard) Close(ctx context.Context) error { + unlock := s.lockExclusive() if s.rb != nil { s.rb.Stop(ctx, s.log) } @@ -388,15 +389,19 @@ func (s *Shard) Close(ctx context.Context) error { } } + if s.opsLimiter != nil { + s.opsLimiter.Close() + } + + unlock() + + // GC waits for handlers and remover to complete. Handlers may try to lock shard's lock. + // So to prevent deadlock GC stopping is outside of exclusive lock. // If Init/Open was unsuccessful gc can be nil. if s.gc != nil { s.gc.stop(ctx) } - if s.opsLimiter != nil { - s.opsLimiter.Close() - } - return lastErr } From 48930ec452bc957a1919ee66f91606937cd08261 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Fri, 4 Apr 2025 16:59:22 +0300 Subject: [PATCH 1368/1413] [#1703] cli: Allow reading RPC endpoint from config file Allowed reading an RPC endpoint from a configuration file when getting current epoch in the `object lock` and `bearer create` commands. Close #1703 Change-Id: Iea8509dff2893a02cb63f695d7f532eecd743ed8 Signed-off-by: Aleksey Savchuk --- cmd/frostfs-cli/modules/bearer/create.go | 3 ++- cmd/frostfs-cli/modules/object/lock.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-cli/modules/bearer/create.go b/cmd/frostfs-cli/modules/bearer/create.go index a86506c375..0927788baf 100644 --- a/cmd/frostfs-cli/modules/bearer/create.go +++ b/cmd/frostfs-cli/modules/bearer/create.go @@ -44,6 +44,7 @@ is set to current epoch + n. _ = viper.BindPFlag(commonflags.WalletPath, ff.Lookup(commonflags.WalletPath)) _ = viper.BindPFlag(commonflags.Account, ff.Lookup(commonflags.Account)) + _ = viper.BindPFlag(commonflags.RPC, ff.Lookup(commonflags.RPC)) }, } @@ -81,7 +82,7 @@ func createToken(cmd *cobra.Command, _ []string) { commonCmd.ExitOnErr(cmd, "can't parse --"+notValidBeforeFlag+" flag: %w", err) if iatRelative || expRelative || nvbRelative { - endpoint, _ := cmd.Flags().GetString(commonflags.RPC) + endpoint := viper.GetString(commonflags.RPC) if len(endpoint) == 0 { commonCmd.ExitOnErr(cmd, "can't fetch current epoch: %w", fmt.Errorf("'%s' flag value must be specified", commonflags.RPC)) } diff --git a/cmd/frostfs-cli/modules/object/lock.go b/cmd/frostfs-cli/modules/object/lock.go index 53dd01868a..d67db9f0d7 100644 --- a/cmd/frostfs-cli/modules/object/lock.go +++ b/cmd/frostfs-cli/modules/object/lock.go @@ -18,6 +18,7 @@ import ( oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" "github.com/spf13/cobra" + "github.com/spf13/viper" ) // object lock command. @@ -78,7 +79,7 @@ var objectLockCmd = &cobra.Command{ ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) defer cancel() - endpoint, _ := cmd.Flags().GetString(commonflags.RPC) + endpoint := viper.GetString(commonflags.RPC) currEpoch, err := internalclient.GetCurrentEpoch(ctx, cmd, endpoint) commonCmd.ExitOnErr(cmd, "Request current epoch: %w", err) From 0712c113dee45c81dfacb882f688c18ea39c1ee3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Tue, 15 Apr 2025 10:06:05 +0300 Subject: [PATCH 1369/1413] [#1700] gc: Fix deadlock `HandleExpiredLocks` gets read lock, then `shard.Close` tries to acquire write lock, but `HandleExpiredLocks` calls `inhumeUnlockedIfExpired` or `selectExpired`, that try to acquire read lock again. Change-Id: Ib2ed015e859328045b5a542a4f569e5e0ff8b05b Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/shard/gc.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/pkg/local_object_storage/shard/gc.go b/pkg/local_object_storage/shard/gc.go index 19b6e2d12f..a262a52cbd 100644 --- a/pkg/local_object_storage/shard/gc.go +++ b/pkg/local_object_storage/shard/gc.go @@ -391,6 +391,16 @@ func (s *Shard) handleExpiredObjects(ctx context.Context, expired []oid.Address) return } + s.handleExpiredObjectsUnsafe(ctx, expired) +} + +func (s *Shard) handleExpiredObjectsUnsafe(ctx context.Context, expired []oid.Address) { + select { + case <-ctx.Done(): + return + default: + } + expired, err := s.getExpiredWithLinked(ctx, expired) if err != nil { s.log.Warn(ctx, logs.ShardGCFailedToGetExpiredWithLinked, zap.Error(err)) @@ -611,13 +621,6 @@ func (s *Shard) getExpiredObjects(ctx context.Context, epoch uint64, onExpiredFo } func (s *Shard) selectExpired(ctx context.Context, epoch uint64, addresses []oid.Address) ([]oid.Address, error) { - s.m.RLock() - defer s.m.RUnlock() - - if s.info.Mode.NoMetabase() { - return nil, ErrDegradedMode - } - release, err := s.opsLimiter.ReadRequest(ctx) if err != nil { return nil, err @@ -728,7 +731,7 @@ func (s *Shard) inhumeUnlockedIfExpired(ctx context.Context, epoch uint64, unloc return } - s.handleExpiredObjects(ctx, expiredUnlocked) + s.handleExpiredObjectsUnsafe(ctx, expiredUnlocked) } // HandleDeletedLocks unlocks all objects which were locked by lockers. From 56d09a99579a59b41f194f4c90a1dd582a9c88bb Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Fri, 7 Feb 2025 17:09:08 +0300 Subject: [PATCH 1370/1413] [#1640] object: Add priority metric based on geo distance Change-Id: I3a7ea4fc4807392bf50e6ff1389c61367c953074 Signed-off-by: Anton Nikiforov --- cmd/frostfs-node/config.go | 17 +- cmd/frostfs-node/config/node/config.go | 5 + config/example/node.env | 1 + config/example/node.json | 3 +- config/example/node.yaml | 1 + docs/storage-node-configuration.md | 53 ++++--- .../object_manager/placement/metrics.go | 150 +++++++++++++++++- .../placement/traverser_test.go | 49 ++++++ 8 files changed, 241 insertions(+), 38 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index b167439e05..8ceef2c314 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -247,15 +247,16 @@ func (a *applicationConfiguration) readConfig(c *config.Config) error { // Object a.ObjectCfg.tombstoneLifetime = objectconfig.TombstoneLifetime(c) - var pm []placement.Metric - for _, raw := range objectconfig.Get(c).Priority() { - m, err := placement.ParseMetric(raw) - if err != nil { - return err - } - pm = append(pm, m) + locodeDBPath := nodeconfig.LocodeDBPath(c) + parser, err := placement.NewMetricsParser(locodeDBPath) + if err != nil { + return fmt.Errorf("metrics parser creation: %w", err) } - a.ObjectCfg.priorityMetrics = pm + m, err := parser.ParseMetrics(objectconfig.Get(c).Priority()) + if err != nil { + return fmt.Errorf("parse metrics: %w", err) + } + a.ObjectCfg.priorityMetrics = m // Storage Engine diff --git a/cmd/frostfs-node/config/node/config.go b/cmd/frostfs-node/config/node/config.go index 969d773964..18aa254f1c 100644 --- a/cmd/frostfs-node/config/node/config.go +++ b/cmd/frostfs-node/config/node/config.go @@ -217,3 +217,8 @@ func (l PersistentPolicyRulesConfig) NoSync() bool { func CompatibilityMode(c *config.Config) bool { return config.BoolSafe(c.Sub(subsection), "kludge_compatibility_mode") } + +// LocodeDBPath returns path to LOCODE database. +func LocodeDBPath(c *config.Config) string { + return config.String(c.Sub(subsection), "locode_db_path") +} diff --git a/config/example/node.env b/config/example/node.env index dfb250341f..b501d38360 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -23,6 +23,7 @@ FROSTFS_NODE_ATTRIBUTE_1="UN-LOCODE:RU MSK" FROSTFS_NODE_RELAY=true FROSTFS_NODE_PERSISTENT_SESSIONS_PATH=/sessions FROSTFS_NODE_PERSISTENT_STATE_PATH=/state +FROSTFS_NODE_LOCODE_DB_PATH=/path/to/locode/db # Tree service section FROSTFS_TREE_ENABLED=true diff --git a/config/example/node.json b/config/example/node.json index 0b061a3d45..b02f43f600 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -37,7 +37,8 @@ }, "persistent_state": { "path": "/state" - } + }, + "locode_db_path": "/path/to/locode/db" }, "grpc": { "0": { diff --git a/config/example/node.yaml b/config/example/node.yaml index 46e4ebdbea..ba32adb82f 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -36,6 +36,7 @@ node: path: /sessions # path to persistent session tokens file of Storage node (default: in-memory sessions) persistent_state: path: /state # path to persistent state file of Storage node + "locode_db_path": "/path/to/locode/db" grpc: - endpoint: s01.frostfs.devenv:8080 # endpoint for gRPC server diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 5fe011ece2..248b54ea4c 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -12,22 +12,23 @@ There are some custom types used for brevity: # Structure -| Section | Description | -|------------------------|---------------------------------------------------------------------| -| `logger` | [Logging parameters](#logger-section) | -| `pprof` | [PProf configuration](#pprof-section) | -| `prometheus` | [Prometheus metrics configuration](#prometheus-section) | -| `control` | [Control service configuration](#control-section) | -| `contracts` | [Override FrostFS contracts hashes](#contracts-section) | -| `morph` | [N3 blockchain client configuration](#morph-section) | -| `apiclient` | [FrostFS API client configuration](#apiclient-section) | -| `policer` | [Policer service configuration](#policer-section) | -| `replicator` | [Replicator service configuration](#replicator-section) | -| `storage` | [Storage engine configuration](#storage-section) | -| `runtime` | [Runtime configuration](#runtime-section) | -| `audit` | [Audit configuration](#audit-section) | -| `multinet` | [Multinet configuration](#multinet-section) | -| `qos` | [QoS configuration](#qos-section) | +| Section | Description | +|--------------|---------------------------------------------------------| +| `node` | [Node parameters](#node-section) | +| `logger` | [Logging parameters](#logger-section) | +| `pprof` | [PProf configuration](#pprof-section) | +| `prometheus` | [Prometheus metrics configuration](#prometheus-section) | +| `control` | [Control service configuration](#control-section) | +| `contracts` | [Override FrostFS contracts hashes](#contracts-section) | +| `morph` | [N3 blockchain client configuration](#morph-section) | +| `apiclient` | [FrostFS API client configuration](#apiclient-section) | +| `policer` | [Policer service configuration](#policer-section) | +| `replicator` | [Replicator service configuration](#replicator-section) | +| `storage` | [Storage engine configuration](#storage-section) | +| `runtime` | [Runtime configuration](#runtime-section) | +| `audit` | [Audit configuration](#audit-section) | +| `multinet` | [Multinet configuration](#multinet-section) | +| `qos` | [QoS configuration](#qos-section) | # `control` section ```yaml @@ -384,17 +385,19 @@ node: path: /sessions persistent_state: path: /state + locode_db_path: "/path/to/locode/db" ``` -| Parameter | Type | Default value | Description | -|-----------------------|---------------------------------------------------------------|---------------|-------------------------------------------------------------------------| -| `key` | `string` | | Path to the binary-encoded private key. | -| `wallet` | [Wallet config](#wallet-subsection) | | Wallet configuration. Has no effect if `key` is provided. | -| `addresses` | `[]string` | | Addresses advertised in the netmap. | -| `attribute` | `[]string` | | Node attributes as a list of key-value pairs in `:` format. | -| `relay` | `bool` | | Enable relay mode. | -| `persistent_sessions` | [Persistent sessions config](#persistent_sessions-subsection) | | Persistent session token store configuration. | -| `persistent_state` | [Persistent state config](#persistent_state-subsection) | | Persistent state configuration. | +| Parameter | Type | Default value | Description | +|-----------------------|---------------------------------------------------------------|---------------|-----------------------------------------------------------------------------------------------------| +| `key` | `string` | | Path to the binary-encoded private key. | +| `wallet` | [Wallet config](#wallet-subsection) | | Wallet configuration. Has no effect if `key` is provided. | +| `addresses` | `[]string` | | Addresses advertised in the netmap. | +| `attribute` | `[]string` | | Node attributes as a list of key-value pairs in `:` format. | +| `relay` | `bool` | | Enable relay mode. | +| `persistent_sessions` | [Persistent sessions config](#persistent_sessions-subsection) | | Persistent session token store configuration. | +| `persistent_state` | [Persistent state config](#persistent_state-subsection) | | Persistent state configuration. | +| `locode_db_path` | `string` | empty | Path to UN/LOCODE [database](https://git.frostfs.info/TrueCloudLab/frostfs-locode-db/) for FrostFS. | ## `wallet` subsection N3 wallet configuration. diff --git a/pkg/services/object_manager/placement/metrics.go b/pkg/services/object_manager/placement/metrics.go index 45e6df3397..0f24a9d96c 100644 --- a/pkg/services/object_manager/placement/metrics.go +++ b/pkg/services/object_manager/placement/metrics.go @@ -2,24 +2,90 @@ package placement import ( "errors" + "fmt" + "maps" + "math" "strings" + "sync" + "sync/atomic" + locodedb "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode/db" + locodebolt "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode/db/boltdb" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" ) const ( attrPrefix = "$attribute:" + + geoDistance = "$geoDistance" ) type Metric interface { CalculateValue(*netmap.NodeInfo, *netmap.NodeInfo) int } -func ParseMetric(raw string) (Metric, error) { - if attr, found := strings.CutPrefix(raw, attrPrefix); found { - return NewAttributeMetric(attr), nil +type metricsParser struct { + locodeDBPath string + locodes map[string]locodedb.Point +} + +type MetricParser interface { + ParseMetrics([]string) ([]Metric, error) +} + +func NewMetricsParser(locodeDBPath string) (MetricParser, error) { + return &metricsParser{ + locodeDBPath: locodeDBPath, + }, nil +} + +func (p *metricsParser) initLocodes() error { + if len(p.locodes) != 0 { + return nil } - return nil, errors.New("unsupported priority metric") + if len(p.locodeDBPath) > 0 { + p.locodes = make(map[string]locodedb.Point) + locodeDB := locodebolt.New(locodebolt.Prm{ + Path: p.locodeDBPath, + }, + locodebolt.ReadOnly(), + ) + err := locodeDB.Open() + if err != nil { + return err + } + defer locodeDB.Close() + err = locodeDB.IterateOverLocodes(func(k string, v locodedb.Point) { + p.locodes[k] = v + }) + if err != nil { + return err + } + return nil + } + return errors.New("set path to locode database") +} + +func (p *metricsParser) ParseMetrics(priority []string) ([]Metric, error) { + var metrics []Metric + for _, raw := range priority { + if attr, found := strings.CutPrefix(raw, attrPrefix); found { + metrics = append(metrics, NewAttributeMetric(attr)) + } else if raw == geoDistance { + err := p.initLocodes() + if err != nil { + return nil, err + } + if len(p.locodes) == 0 { + return nil, fmt.Errorf("provide locodes database for metric %s", raw) + } + m := NewGeoDistanceMetric(p.locodes) + metrics = append(metrics, m) + } else { + return nil, fmt.Errorf("unsupported priority metric %s", raw) + } + } + return metrics, nil } // attributeMetric describes priority metric based on attribute. @@ -41,3 +107,79 @@ func (am *attributeMetric) CalculateValue(from *netmap.NodeInfo, to *netmap.Node func NewAttributeMetric(attr string) Metric { return &attributeMetric{attribute: attr} } + +// geoDistanceMetric describes priority metric based on attribute. +type geoDistanceMetric struct { + locodes map[string]locodedb.Point + distance *atomic.Pointer[map[string]int] + mtx sync.Mutex +} + +func NewGeoDistanceMetric(locodes map[string]locodedb.Point) Metric { + d := atomic.Pointer[map[string]int]{} + m := make(map[string]int) + d.Store(&m) + gm := &geoDistanceMetric{ + locodes: locodes, + distance: &d, + } + return gm +} + +// CalculateValue return distance in kilometers between current node and provided, +// if coordinates for provided node found. In other case return math.MaxInt. +func (gm *geoDistanceMetric) CalculateValue(from *netmap.NodeInfo, to *netmap.NodeInfo) int { + fl := from.LOCODE() + tl := to.LOCODE() + if fl == tl { + return 0 + } + m := gm.distance.Load() + if v, ok := (*m)[fl+tl]; ok { + return v + } + return gm.calculateDistance(fl, tl) +} + +func (gm *geoDistanceMetric) calculateDistance(from, to string) int { + gm.mtx.Lock() + defer gm.mtx.Unlock() + od := gm.distance.Load() + if v, ok := (*od)[from+to]; ok { + return v + } + nd := maps.Clone(*od) + var dist int + pointFrom, okFrom := gm.locodes[from] + pointTo, okTo := gm.locodes[to] + if okFrom && okTo { + dist = int(distance(pointFrom.Latitude(), pointFrom.Longitude(), pointTo.Latitude(), pointTo.Longitude())) + } else { + dist = math.MaxInt + } + nd[from+to] = dist + gm.distance.Store(&nd) + + return dist +} + +// distance return amount of KM between two points. +// Parameters are latitude and longitude of point 1 and 2 in decimal degrees. +// Original implementation can be found here https://www.geodatasource.com/developers/go. +func distance(lt1 float64, ln1 float64, lt2 float64, ln2 float64) float64 { + radLat1 := math.Pi * lt1 / 180 + radLat2 := math.Pi * lt2 / 180 + radTheta := math.Pi * (ln1 - ln2) / 180 + + dist := math.Sin(radLat1)*math.Sin(radLat2) + math.Cos(radLat1)*math.Cos(radLat2)*math.Cos(radTheta) + + if dist > 1 { + dist = 1 + } + + dist = math.Acos(dist) + dist = dist * 180 / math.Pi + dist = dist * 60 * 1.1515 * 1.609344 + + return dist +} diff --git a/pkg/services/object_manager/placement/traverser_test.go b/pkg/services/object_manager/placement/traverser_test.go index 9c825bf193..d1370f21e2 100644 --- a/pkg/services/object_manager/placement/traverser_test.go +++ b/pkg/services/object_manager/placement/traverser_test.go @@ -601,4 +601,53 @@ func TestTraverserPriorityMetrics(t *testing.T) { next = tr.Next() require.Nil(t, next) }) + + t.Run("one rep one geo metric", func(t *testing.T) { + t.Skip() + selectors := []int{2} + replicas := []int{2} + + nodes, cnr := testPlacement(selectors, replicas) + + // Node_0, PK - ip4/0.0.0.0/tcp/0 + nodes[0][0].SetAttribute("UN-LOCODE", "RU MOW") + // Node_1, PK - ip4/0.0.0.0/tcp/1 + nodes[0][1].SetAttribute("UN-LOCODE", "RU LED") + + sdkNode := testNode(2) + sdkNode.SetAttribute("UN-LOCODE", "FI HEL") + + nodesCopy := copyVectors(nodes) + + parser, err := NewMetricsParser("/path/to/locode_db") + require.NoError(t, err) + m, err := parser.ParseMetrics([]string{geoDistance}) + require.NoError(t, err) + + tr, err := NewTraverser(context.Background(), + ForContainer(cnr), + UseBuilder(&testBuilder{ + vectors: nodesCopy, + }), + WithoutSuccessTracking(), + WithPriorityMetrics(m), + WithNodeState(&nodeState{ + node: &sdkNode, + }), + ) + require.NoError(t, err) + + // Without priority metric `$geoDistance` the order will be: + // [ {Node_0 RU MOW}, {Node_1 RU LED}] + // With priority metric `$geoDistance` the order should be: + // [ {Node_1 RU LED}, {Node_0 RU MOW}] + next := tr.Next() + require.NotNil(t, next) + require.Equal(t, 2, len(next)) + require.Equal(t, "/ip4/0.0.0.0/tcp/1", string(next[0].PublicKey())) + require.Equal(t, "/ip4/0.0.0.0/tcp/0", string(next[1].PublicKey())) + + next = tr.Next() + require.Nil(t, next) + }) } From bf06c4fb4b935410a4ea9b610f4e12f2fe28cb2a Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 4 Apr 2025 20:22:05 +0300 Subject: [PATCH 1371/1413] [#1689] Remove deprecated NodeInfo.IterateNetworkEndpoints() Change-Id: Ic78f18aed11fab34ee3147ceea657296b89fe60c Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/netmap/nodeinfo.go | 4 +- cmd/frostfs-cli/modules/object/nodes.go | 11 ++---- cmd/frostfs-node/cache.go | 22 ++--------- cmd/frostfs-node/netmap.go | 6 ++- cmd/internal/common/netmap.go | 4 +- pkg/core/netmap/nodes.go | 6 ++- pkg/network/validation.go | 6 ++- pkg/services/replicator/pull.go | 7 +--- pkg/services/tree/redirect.go | 41 +++++++++++-------- pkg/services/tree/replicator.go | 46 ++++++++++++---------- pkg/services/tree/sync.go | 12 +++--- 11 files changed, 83 insertions(+), 82 deletions(-) diff --git a/cmd/frostfs-cli/modules/netmap/nodeinfo.go b/cmd/frostfs-cli/modules/netmap/nodeinfo.go index ae4bb329a0..316d18d2b7 100644 --- a/cmd/frostfs-cli/modules/netmap/nodeinfo.go +++ b/cmd/frostfs-cli/modules/netmap/nodeinfo.go @@ -62,9 +62,9 @@ func prettyPrintNodeInfo(cmd *cobra.Command, i netmap.NodeInfo) { cmd.Println("state:", stateWord) - netmap.IterateNetworkEndpoints(i, func(s string) { + for s := range i.NetworkEndpoints() { cmd.Println("address:", s) - }) + } i.IterateAttributes(func(key, value string) { cmd.Printf("attribute: %s=%s\n", key, value) diff --git a/cmd/frostfs-cli/modules/object/nodes.go b/cmd/frostfs-cli/modules/object/nodes.go index 734b557a43..4762386519 100644 --- a/cmd/frostfs-cli/modules/object/nodes.go +++ b/cmd/frostfs-cli/modules/object/nodes.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "fmt" + "slices" "sync" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/client" @@ -460,17 +461,11 @@ func createClient(ctx context.Context, cmd *cobra.Command, candidate netmapSDK.N var cli *client.Client var addresses []string if preferInternal, _ := cmd.Flags().GetBool(preferInternalAddressesFlag); preferInternal { - candidate.IterateNetworkEndpoints(func(s string) bool { - addresses = append(addresses, s) - return false - }) + addresses = slices.AppendSeq(addresses, candidate.NetworkEndpoints()) addresses = append(addresses, candidate.ExternalAddresses()...) } else { addresses = append(addresses, candidate.ExternalAddresses()...) - candidate.IterateNetworkEndpoints(func(s string) bool { - addresses = append(addresses, s) - return false - }) + addresses = slices.AppendSeq(addresses, candidate.NetworkEndpoints()) } var lastErr error diff --git a/cmd/frostfs-node/cache.go b/cmd/frostfs-node/cache.go index 38cee5837b..e5df0a22d0 100644 --- a/cmd/frostfs-node/cache.go +++ b/cmd/frostfs-node/cache.go @@ -235,16 +235,8 @@ func (s *lruNetmapSource) updateCandidates(ctx context.Context, d time.Duration) slices.Compare(n1.ExternalAddresses(), n2.ExternalAddresses()) != 0 { return 1 } - var ne1 []string - n1.IterateNetworkEndpoints(func(s string) bool { - ne1 = append(ne1, s) - return false - }) - var ne2 []string - n2.IterateNetworkEndpoints(func(s string) bool { - ne2 = append(ne2, s) - return false - }) + ne1 := slices.Collect(n1.NetworkEndpoints()) + ne2 := slices.Collect(n2.NetworkEndpoints()) return slices.Compare(ne1, ne2) }) if ret != 0 { @@ -364,15 +356,9 @@ func getNetMapNodesToUpdate(nm *netmapSDK.NetMap, candidates []netmapSDK.NodeInf } nodeEndpoints := make([]string, 0, nm.Nodes()[i].NumberOfNetworkEndpoints()) - nm.Nodes()[i].IterateNetworkEndpoints(func(s string) bool { - nodeEndpoints = append(nodeEndpoints, s) - return false - }) + nodeEndpoints = slices.AppendSeq(nodeEndpoints, nm.Nodes()[i].NetworkEndpoints()) candidateEndpoints := make([]string, 0, cnd.NumberOfNetworkEndpoints()) - cnd.IterateNetworkEndpoints(func(s string) bool { - candidateEndpoints = append(candidateEndpoints, s) - return false - }) + candidateEndpoints = slices.AppendSeq(candidateEndpoints, cnd.NetworkEndpoints()) if slices.Compare(nodeEndpoints, candidateEndpoints) != 0 { update = true tmp.endpoints = candidateEndpoints diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 0e90e77075..6d57edcce5 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -124,7 +124,11 @@ func nodeKeyFromNetmap(c *cfg) []byte { func (c *cfg) iterateNetworkAddresses(f func(string) bool) { ni, ok := c.cfgNetmap.state.getNodeInfo() if ok { - ni.IterateNetworkEndpoints(f) + for s := range ni.NetworkEndpoints() { + if f(s) { + return + } + } } } diff --git a/cmd/internal/common/netmap.go b/cmd/internal/common/netmap.go index f550552d21..334b662f82 100644 --- a/cmd/internal/common/netmap.go +++ b/cmd/internal/common/netmap.go @@ -27,9 +27,9 @@ func PrettyPrintNodeInfo(cmd *cobra.Command, node netmap.NodeInfo, cmd.Printf("%sNode %d: %s %s ", indent, index+1, hex.EncodeToString(node.PublicKey()), strState) - netmap.IterateNetworkEndpoints(node, func(endpoint string) { + for endpoint := range node.NetworkEndpoints() { cmd.Printf("%s ", endpoint) - }) + } cmd.Println() if !short { diff --git a/pkg/core/netmap/nodes.go b/pkg/core/netmap/nodes.go index b0c9e1f9e1..f01c07b194 100644 --- a/pkg/core/netmap/nodes.go +++ b/pkg/core/netmap/nodes.go @@ -17,7 +17,11 @@ func (x Node) PublicKey() []byte { // IterateAddresses iterates over all announced network addresses // and passes them into f. Handler MUST NOT be nil. func (x Node) IterateAddresses(f func(string) bool) { - (netmap.NodeInfo)(x).IterateNetworkEndpoints(f) + for s := range (netmap.NodeInfo)(x).NetworkEndpoints() { + if f(s) { + return + } + } } // NumberOfAddresses returns number of announced network addresses. diff --git a/pkg/network/validation.go b/pkg/network/validation.go index 92f6501193..73a3ef8d71 100644 --- a/pkg/network/validation.go +++ b/pkg/network/validation.go @@ -35,7 +35,11 @@ var ( type NodeEndpointsIterator netmap.NodeInfo func (x NodeEndpointsIterator) IterateAddresses(f func(string) bool) { - (netmap.NodeInfo)(x).IterateNetworkEndpoints(f) + for s := range (netmap.NodeInfo)(x).NetworkEndpoints() { + if f(s) { + return + } + } } func (x NodeEndpointsIterator) NumberOfAddresses() int { diff --git a/pkg/services/replicator/pull.go b/pkg/services/replicator/pull.go index bb38c72ad6..216fe4919c 100644 --- a/pkg/services/replicator/pull.go +++ b/pkg/services/replicator/pull.go @@ -3,6 +3,7 @@ package replicator import ( "context" "errors" + "slices" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" @@ -42,11 +43,7 @@ func (p *Replicator) HandlePullTask(ctx context.Context, task Task) { if err == nil { break } - var endpoints []string - node.IterateNetworkEndpoints(func(s string) bool { - endpoints = append(endpoints, s) - return false - }) + endpoints := slices.Collect(node.NetworkEndpoints()) p.log.Error(ctx, logs.ReplicatorCouldNotGetObjectFromRemoteStorage, zap.Stringer("object", task.Addr), zap.Error(err), diff --git a/pkg/services/tree/redirect.go b/pkg/services/tree/redirect.go index d92c749a82..3dcdc4fc79 100644 --- a/pkg/services/tree/redirect.go +++ b/pkg/services/tree/redirect.go @@ -41,24 +41,15 @@ func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo var called bool for _, n := range cntNodes { var stop bool - n.IterateNetworkEndpoints(func(endpoint string) bool { - ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.IterateNetworkEndpoints", - trace.WithAttributes( - attribute.String("endpoint", endpoint), - )) - defer span.End() - - c, err := s.cache.get(ctx, endpoint) - if err != nil { - return false + for endpoint := range n.NetworkEndpoints() { + stop = s.execOnClient(ctx, endpoint, func(c TreeServiceClient) bool { + called = true + return f(c) + }) + if called { + break } - - s.log.Debug(ctx, logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint)) - - called = true - stop = f(c) - return true - }) + } if stop { return nil } @@ -68,3 +59,19 @@ func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo } return nil } + +func (s *Service) execOnClient(ctx context.Context, endpoint string, f func(TreeServiceClient) bool) bool { + ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.IterateNetworkEndpoints", + trace.WithAttributes( + attribute.String("endpoint", endpoint), + )) + defer span.End() + + c, err := s.cache.get(ctx, endpoint) + if err != nil { + return false + } + + s.log.Debug(ctx, logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint)) + return f(c) +} diff --git a/pkg/services/tree/replicator.go b/pkg/services/tree/replicator.go index 01a4ffde03..ee40884ebc 100644 --- a/pkg/services/tree/replicator.go +++ b/pkg/services/tree/replicator.go @@ -89,29 +89,13 @@ func (s *Service) ReplicateTreeOp(ctx context.Context, n netmapSDK.NodeInfo, req var lastErr error var lastAddr string - n.IterateNetworkEndpoints(func(addr string) bool { - ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.HandleReplicationTaskOnEndpoint", - trace.WithAttributes( - attribute.String("public_key", hex.EncodeToString(n.PublicKey())), - attribute.String("address", addr), - ), - ) - defer span.End() - + for addr := range n.NetworkEndpoints() { lastAddr = addr - - c, err := s.cache.get(ctx, addr) - if err != nil { - lastErr = fmt.Errorf("can't create client: %w", err) - return false + lastErr = s.apply(ctx, n, addr, req) + if lastErr == nil { + break } - - ctx, cancel := context.WithTimeout(ctx, s.replicatorTimeout) - _, lastErr = c.Apply(ctx, req) - cancel() - - return lastErr == nil - }) + } if lastErr != nil { if errors.Is(lastErr, errRecentlyFailed) { @@ -130,6 +114,26 @@ func (s *Service) ReplicateTreeOp(ctx context.Context, n netmapSDK.NodeInfo, req return nil } +func (s *Service) apply(ctx context.Context, n netmapSDK.NodeInfo, addr string, req *ApplyRequest) error { + ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.HandleReplicationTaskOnEndpoint", + trace.WithAttributes( + attribute.String("public_key", hex.EncodeToString(n.PublicKey())), + attribute.String("address", addr), + ), + ) + defer span.End() + + c, err := s.cache.get(ctx, addr) + if err != nil { + return fmt.Errorf("can't create client: %w", err) + } + + ctx, cancel := context.WithTimeout(ctx, s.replicatorTimeout) + _, err = c.Apply(ctx, req) + cancel() + return err +} + func (s *Service) replicateLoop(ctx context.Context) { for range s.replicatorWorkerCount { go s.replicationWorker(ctx) diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index c3796fbd40..32297f9d70 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -297,27 +297,27 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, for i, n := range nodes { errGroup.Go(func() error { var nodeSynced bool - n.IterateNetworkEndpoints(func(addr string) bool { + for addr := range n.NetworkEndpoints() { var a network.Address if err := a.FromString(addr); err != nil { s.log.Warn(ctx, logs.TreeFailedToParseAddressForTreeSynchronization, zap.Error(err), zap.String("address", addr)) - return false + continue } cc, err := createConnection(a, grpc.WithContextDialer(s.ds.GrpcContextDialer())) if err != nil { s.log.Warn(ctx, logs.TreeFailedToConnectForTreeSynchronization, zap.Error(err), zap.String("address", addr)) - return false + continue } - defer cc.Close() err = s.startStream(egCtx, cid, treeID, from, cc, nodeOperationStreams[i]) if err != nil { s.log.Warn(ctx, logs.TreeFailedToRunTreeSynchronizationForSpecificNode, zap.Error(err), zap.String("address", addr)) } nodeSynced = err == nil - return true - }) + _ = cc.Close() + break + } close(nodeOperationStreams[i]) if !nodeSynced { allNodesSynced.Store(false) From e65d578ba93f18c5d4276300fe660f01941f630c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 4 Apr 2025 20:24:46 +0300 Subject: [PATCH 1372/1413] [#1689] Remove deprecated NodeInfo.IterateAttributes() Change-Id: Ibd07302079efe148903aa6177759232a28616736 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-cli/modules/container/policy_playground.go | 4 ++-- cmd/frostfs-cli/modules/netmap/nodeinfo.go | 4 ++-- cmd/internal/common/netmap.go | 4 ++-- pkg/util/attributes/parser_test.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/policy_playground.go b/cmd/frostfs-cli/modules/container/policy_playground.go index 2cc1107ef2..cf4862b4a6 100644 --- a/cmd/frostfs-cli/modules/container/policy_playground.go +++ b/cmd/frostfs-cli/modules/container/policy_playground.go @@ -40,9 +40,9 @@ func (repl *policyPlaygroundREPL) handleLs(args []string) error { i := 1 for id, node := range repl.nodes { var attrs []string - node.IterateAttributes(func(k, v string) { + for k, v := range node.Attributes() { attrs = append(attrs, fmt.Sprintf("%s:%q", k, v)) - }) + } fmt.Fprintf(repl.console, "\t%2d: id=%s attrs={%v}\n", i, id, strings.Join(attrs, " ")) i++ } diff --git a/cmd/frostfs-cli/modules/netmap/nodeinfo.go b/cmd/frostfs-cli/modules/netmap/nodeinfo.go index 316d18d2b7..5da66dcd9c 100644 --- a/cmd/frostfs-cli/modules/netmap/nodeinfo.go +++ b/cmd/frostfs-cli/modules/netmap/nodeinfo.go @@ -66,7 +66,7 @@ func prettyPrintNodeInfo(cmd *cobra.Command, i netmap.NodeInfo) { cmd.Println("address:", s) } - i.IterateAttributes(func(key, value string) { + for key, value := range i.Attributes() { cmd.Printf("attribute: %s=%s\n", key, value) - }) + } } diff --git a/cmd/internal/common/netmap.go b/cmd/internal/common/netmap.go index 334b662f82..5dd1a060e5 100644 --- a/cmd/internal/common/netmap.go +++ b/cmd/internal/common/netmap.go @@ -33,9 +33,9 @@ func PrettyPrintNodeInfo(cmd *cobra.Command, node netmap.NodeInfo, cmd.Println() if !short { - node.IterateAttributes(func(key, value string) { + for key, value := range node.Attributes() { cmd.Printf("%s\t%s: %s\n", indent, key, value) - }) + } } } diff --git a/pkg/util/attributes/parser_test.go b/pkg/util/attributes/parser_test.go index 547c8d50b4..66581878a5 100644 --- a/pkg/util/attributes/parser_test.go +++ b/pkg/util/attributes/parser_test.go @@ -23,12 +23,12 @@ func testAttributeMap(t *testing.T, mSrc, mExp map[string]string) { mExp = mSrc } - node.IterateAttributes(func(key, value string) { + for key, value := range node.Attributes() { v, ok := mExp[key] require.True(t, ok) require.Equal(t, value, v) delete(mExp, key) - }) + } require.Empty(t, mExp) } From 2d1232ce6de2f9291528c1c3e325bb8a0683de10 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Fri, 4 Apr 2025 20:31:35 +0300 Subject: [PATCH 1373/1413] [#1689] network,core/netmap: Replace Iterate*() functions with iterators Change-Id: I4842a3160d74c56d99ea9465d4be2f0662080605 Signed-off-by: Evgenii Stratonikov --- cmd/frostfs-node/config/node/config.go | 10 ++++------ pkg/core/client/util.go | 3 ++- pkg/core/netmap/nodes.go | 12 +++++++++++- pkg/network/group.go | 18 +++++++++--------- pkg/network/group_test.go | 8 ++++---- pkg/network/validation.go | 9 +++------ 6 files changed, 33 insertions(+), 27 deletions(-) diff --git a/cmd/frostfs-node/config/node/config.go b/cmd/frostfs-node/config/node/config.go index 18aa254f1c..81b191e966 100644 --- a/cmd/frostfs-node/config/node/config.go +++ b/cmd/frostfs-node/config/node/config.go @@ -3,7 +3,9 @@ package nodeconfig import ( "fmt" "io/fs" + "iter" "os" + "slices" "strconv" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config" @@ -88,12 +90,8 @@ func Wallet(c *config.Config) *keys.PrivateKey { type stringAddressGroup []string -func (x stringAddressGroup) IterateAddresses(f func(string) bool) { - for i := range x { - if f(x[i]) { - break - } - } +func (x stringAddressGroup) Addresses() iter.Seq[string] { + return slices.Values(x) } func (x stringAddressGroup) NumberOfAddresses() int { diff --git a/pkg/core/client/util.go b/pkg/core/client/util.go index d4bc0cf68a..91ee5c6c3c 100644 --- a/pkg/core/client/util.go +++ b/pkg/core/client/util.go @@ -3,6 +3,7 @@ package client import ( "bytes" "fmt" + "iter" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" @@ -19,7 +20,7 @@ func nodeInfoFromKeyAddr(dst *NodeInfo, k []byte, a, external network.AddressGro // Args must not be nil. func NodeInfoFromRawNetmapElement(dst *NodeInfo, info interface { PublicKey() []byte - IterateAddresses(func(string) bool) + Addresses() iter.Seq[string] NumberOfAddresses() int ExternalAddresses() []string }, diff --git a/pkg/core/netmap/nodes.go b/pkg/core/netmap/nodes.go index f01c07b194..e58e426343 100644 --- a/pkg/core/netmap/nodes.go +++ b/pkg/core/netmap/nodes.go @@ -1,6 +1,10 @@ package netmap -import "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" +import ( + "iter" + + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" +) // Node is a named type of netmap.NodeInfo which provides interface needed // in the current repository. Node is expected to be used everywhere instead @@ -14,8 +18,14 @@ func (x Node) PublicKey() []byte { return (netmap.NodeInfo)(x).PublicKey() } +// Addresses returns an iterator over all announced network addresses. +func (x Node) Addresses() iter.Seq[string] { + return (netmap.NodeInfo)(x).NetworkEndpoints() +} + // IterateAddresses iterates over all announced network addresses // and passes them into f. Handler MUST NOT be nil. +// Deprecated: use [Node.Addresses] instead. func (x Node) IterateAddresses(f func(string) bool) { for s := range (netmap.NodeInfo)(x).NetworkEndpoints() { if f(s) { diff --git a/pkg/network/group.go b/pkg/network/group.go index 5a71e530ed..0044fb2d4e 100644 --- a/pkg/network/group.go +++ b/pkg/network/group.go @@ -3,6 +3,7 @@ package network import ( "errors" "fmt" + "iter" "slices" "sort" @@ -68,9 +69,8 @@ func (x AddressGroup) Swap(i, j int) { // MultiAddressIterator is an interface of network address group. type MultiAddressIterator interface { - // IterateAddresses must iterate over network addresses and pass each one - // to the handler until it returns true. - IterateAddresses(func(string) bool) + // Addresses must return an iterator over network addresses. + Addresses() iter.Seq[string] // NumberOfAddresses must return number of addresses in group. NumberOfAddresses() int @@ -131,19 +131,19 @@ func (x *AddressGroup) FromIterator(iter MultiAddressIterator) error { // iterateParsedAddresses parses each address from MultiAddressIterator and passes it to f // until 1st parsing failure or f's error. func iterateParsedAddresses(iter MultiAddressIterator, f func(s Address) error) (err error) { - iter.IterateAddresses(func(s string) bool { + for s := range iter.Addresses() { var a Address err = a.FromString(s) if err != nil { - err = fmt.Errorf("could not parse address from string: %w", err) - return true + return fmt.Errorf("could not parse address from string: %w", err) } err = f(a) - - return err != nil - }) + if err != nil { + return err + } + } return } diff --git a/pkg/network/group_test.go b/pkg/network/group_test.go index 5b335fa526..d082645336 100644 --- a/pkg/network/group_test.go +++ b/pkg/network/group_test.go @@ -1,6 +1,8 @@ package network import ( + "iter" + "slices" "sort" "testing" @@ -58,10 +60,8 @@ func TestAddressGroup_FromIterator(t *testing.T) { type testIterator []string -func (t testIterator) IterateAddresses(f func(string) bool) { - for i := range t { - f(t[i]) - } +func (t testIterator) Addresses() iter.Seq[string] { + return slices.Values(t) } func (t testIterator) NumberOfAddresses() int { diff --git a/pkg/network/validation.go b/pkg/network/validation.go index 73a3ef8d71..b5157f28f6 100644 --- a/pkg/network/validation.go +++ b/pkg/network/validation.go @@ -2,6 +2,7 @@ package network import ( "errors" + "iter" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" ) @@ -34,12 +35,8 @@ var ( // MultiAddressIterator. type NodeEndpointsIterator netmap.NodeInfo -func (x NodeEndpointsIterator) IterateAddresses(f func(string) bool) { - for s := range (netmap.NodeInfo)(x).NetworkEndpoints() { - if f(s) { - return - } - } +func (x NodeEndpointsIterator) Addresses() iter.Seq[string] { + return (netmap.NodeInfo)(x).NetworkEndpoints() } func (x NodeEndpointsIterator) NumberOfAddresses() int { From 98308d0cad312c34f2575d05651405de58c5b2f3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 14 Apr 2025 15:39:56 +0300 Subject: [PATCH 1374/1413] [#1715] blobstor: Allow to specify custom compression level Change-Id: I140c39b9dceaaeb58767061b131777af22242b19 Signed-off-by: Dmitrii Stepanov --- .../maintenance/zombie/storage_engine.go | 2 ++ cmd/frostfs-node/config.go | 4 +++ cmd/frostfs-node/config/engine/config_test.go | 2 ++ .../config/engine/shard/config.go | 10 ++++++ config/example/node.env | 1 + config/example/node.json | 1 + config/example/node.yaml | 5 +-- docs/storage-node-configuration.md | 3 +- internal/assert/cond.go | 4 +++ internal/logs/logs.go | 1 + pkg/local_object_storage/blobstor/blobstor.go | 6 ++++ .../blobstor/compression/compress.go | 34 ++++++++++++++++++- pkg/local_object_storage/blobstor/control.go | 5 +++ 13 files changed, 74 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go index 5851e049ce..fe75a6f6f3 100644 --- a/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go @@ -13,6 +13,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" @@ -135,6 +136,7 @@ func getMetabaseOpts(sh *shardconfig.Config) []meta.Option { func getBlobstorOpts(ctx context.Context, sh *shardconfig.Config) []blobstor.Option { result := []blobstor.Option{ blobstor.WithCompressObjects(sh.Compress()), + blobstor.WithCompressionLevel(compression.Level(sh.CompressionLevel())), blobstor.WithUncompressableContentTypes(sh.UncompressableContentTypes()), blobstor.WithCompressibilityEstimate(sh.EstimateCompressibility()), blobstor.WithCompressibilityEstimateThreshold(sh.EstimateCompressibilityThreshold()), diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index 8ceef2c314..f32953c584 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -40,6 +40,7 @@ import ( netmapCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" @@ -129,6 +130,7 @@ type applicationConfiguration struct { type shardCfg struct { compress bool + compressionLevel compression.Level estimateCompressibility bool estimateCompressibilityThreshold float64 @@ -273,6 +275,7 @@ func (a *applicationConfiguration) updateShardConfig(c *config.Config, source *s target.refillMetabaseWorkersCount = source.RefillMetabaseWorkersCount() target.mode = source.Mode() target.compress = source.Compress() + target.compressionLevel = compression.Level(source.CompressionLevel()) target.estimateCompressibility = source.EstimateCompressibility() target.estimateCompressibilityThreshold = source.EstimateCompressibilityThreshold() target.uncompressableContentType = source.UncompressableContentTypes() @@ -1027,6 +1030,7 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID blobstoreOpts := []blobstor.Option{ blobstor.WithCompressObjects(shCfg.compress), + blobstor.WithCompressionLevel(shCfg.compressionLevel), blobstor.WithUncompressableContentTypes(shCfg.uncompressableContentType), blobstor.WithCompressibilityEstimate(shCfg.estimateCompressibility), blobstor.WithCompressibilityEstimateThreshold(shCfg.estimateCompressibilityThreshold), diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index 34613ad9e5..afadb4c995 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -101,6 +101,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, 10*time.Millisecond, meta.BoltDB().MaxBatchDelay()) require.Equal(t, true, sc.Compress()) + require.Equal(t, "fastest", sc.CompressionLevel()) require.Equal(t, []string{"audio/*", "video/*"}, sc.UncompressableContentTypes()) require.Equal(t, true, sc.EstimateCompressibility()) require.Equal(t, float64(0.7), sc.EstimateCompressibilityThreshold()) @@ -237,6 +238,7 @@ func TestEngineSection(t *testing.T) { require.Equal(t, 20*time.Millisecond, meta.BoltDB().MaxBatchDelay()) require.Equal(t, false, sc.Compress()) + require.Equal(t, "", sc.CompressionLevel()) require.Equal(t, []string(nil), sc.UncompressableContentTypes()) require.EqualValues(t, 102400, sc.SmallSizeLimit()) diff --git a/cmd/frostfs-node/config/engine/shard/config.go b/cmd/frostfs-node/config/engine/shard/config.go index e50d56b955..14e91f01ff 100644 --- a/cmd/frostfs-node/config/engine/shard/config.go +++ b/cmd/frostfs-node/config/engine/shard/config.go @@ -37,6 +37,16 @@ func (x *Config) Compress() bool { ) } +// CompressionLevel returns the value of "compression_level" config parameter. +// +// Returns empty string if the value is not a valid string. +func (x *Config) CompressionLevel() string { + return config.StringSafe( + (*config.Config)(x), + "compression_level", + ) +} + // UncompressableContentTypes returns the value of "compress_skip_content_types" config parameter. // // Returns nil if a the value is missing or is invalid. diff --git a/config/example/node.env b/config/example/node.env index b501d38360..fb4fc69dd7 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -123,6 +123,7 @@ FROSTFS_STORAGE_SHARD_0_METABASE_MAX_BATCH_SIZE=100 FROSTFS_STORAGE_SHARD_0_METABASE_MAX_BATCH_DELAY=10ms ### Blobstor config FROSTFS_STORAGE_SHARD_0_COMPRESS=true +FROSTFS_STORAGE_SHARD_0_COMPRESSION_LEVEL=fastest FROSTFS_STORAGE_SHARD_0_COMPRESSION_EXCLUDE_CONTENT_TYPES="audio/* video/*" FROSTFS_STORAGE_SHARD_0_COMPRESSION_ESTIMATE_COMPRESSIBILITY=true FROSTFS_STORAGE_SHARD_0_COMPRESSION_ESTIMATE_COMPRESSIBILITY_THRESHOLD=0.7 diff --git a/config/example/node.json b/config/example/node.json index b02f43f600..1e9dd7835b 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -184,6 +184,7 @@ "max_batch_delay": "10ms" }, "compress": true, + "compression_level": "fastest", "compression_exclude_content_types": [ "audio/*", "video/*" ], diff --git a/config/example/node.yaml b/config/example/node.yaml index ba32adb82f..26c6e248c8 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -160,7 +160,7 @@ storage: max_batch_delay: 5ms # maximum delay for a batch of operations to be executed max_batch_size: 100 # maximum amount of operations in a single batch - compress: false # turn on/off zstd(level 3) compression of stored objects + compress: false # turn on/off zstd compression of stored objects small_object_size: 100 kb # size threshold for "small" objects which are cached in key-value DB, not in FS, bytes blobstor: @@ -202,7 +202,8 @@ storage: max_batch_size: 100 max_batch_delay: 10ms - compress: true # turn on/off zstd(level 3) compression of stored objects + compress: true # turn on/off zstd compression of stored objects + compression_level: fastest compression_exclude_content_types: - audio/* - video/* diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 248b54ea4c..19f6ee66d0 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -188,6 +188,7 @@ The following table describes configuration for each shard. | Parameter | Type | Default value | Description | | ------------------------------------------------ | ------------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `compress` | `bool` | `false` | Flag to enable compression. | +| `compression_level` | `string` | `optimal` | Compression level. Available values are `optimal`, `fastest`, `smallest_size`. | | `compression_exclude_content_types` | `[]string` | | List of content-types to disable compression for. Content-type is taken from `Content-Type` object attribute. Each element can contain a star `*` as a first (last) character, which matches any prefix (suffix). | | `compression_estimate_compressibility` | `bool` | `false` | If `true`, then noramalized compressibility estimation is used to decide compress data or not. | | `compression_estimate_compressibility_threshold` | `float` | `0.1` | Normilized compressibility estimate threshold: data will compress if estimation if greater than this value. | @@ -199,7 +200,7 @@ The following table describes configuration for each shard. | `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | | `small_object_size` | `size` | `1M` | Maximum size of an object stored in blobovnicza tree. | | `gc` | [GC config](#gc-subsection) | | GC configuration. | -| `limits` | [Shard limits config](#limits-subsection) | | Shard limits configuration. | +| `limits` | [Shard limits config](#limits-subsection) | | Shard limits configuration. | ### `blobstor` subsection diff --git a/internal/assert/cond.go b/internal/assert/cond.go index c6a034f94f..113d2eba90 100644 --- a/internal/assert/cond.go +++ b/internal/assert/cond.go @@ -23,3 +23,7 @@ func NoError(err error, details ...string) { panic(content) } } + +func Fail(details ...string) { + panic(strings.Join(details, " ")) +} diff --git a/internal/logs/logs.go b/internal/logs/logs.go index 3a3ceb1501..dedc7e12cc 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -516,4 +516,5 @@ const ( FailedToValidateIncomingIOTag = "failed to validate incoming IO tag, replaced with `client`" WriteCacheFailedToAcquireRPSQuota = "writecache failed to acquire RPS quota to flush object" FailedToUpdateNetmapCandidates = "update netmap candidates failed" + UnknownCompressionLevelDefaultWillBeUsed = "unknown compression level, 'optimal' will be used" ) diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index d7c3333496..7a9568aff9 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -109,6 +109,12 @@ func WithCompressObjects(comp bool) Option { } } +func WithCompressionLevel(level compression.Level) Option { + return func(c *cfg) { + c.compression.Level = level + } +} + // WithCompressibilityEstimate returns an option to use // normilized compressibility estimate to decide compress // data or not. diff --git a/pkg/local_object_storage/blobstor/compression/compress.go b/pkg/local_object_storage/blobstor/compression/compress.go index 85ab476926..8a86b69826 100644 --- a/pkg/local_object_storage/blobstor/compression/compress.go +++ b/pkg/local_object_storage/blobstor/compression/compress.go @@ -4,15 +4,26 @@ import ( "bytes" "strings" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" "github.com/klauspost/compress" "github.com/klauspost/compress/zstd" ) +type Level string + +const ( + LevelDefault Level = "" + LevelOptimal Level = "optimal" + LevelFastest Level = "fastest" + LevelSmallestSize Level = "smallest_size" +) + // Config represents common compression-related configuration. type Config struct { Enabled bool UncompressableContentTypes []string + Level Level UseCompressEstimation bool CompressEstimationThreshold float64 @@ -30,7 +41,7 @@ func (c *Config) Init() error { var err error if c.Enabled { - c.encoder, err = zstd.NewWriter(nil) + c.encoder, err = zstd.NewWriter(nil, zstd.WithEncoderLevel(c.compressionLevel())) if err != nil { return err } @@ -116,3 +127,24 @@ func (c *Config) Close() error { } return err } + +func (c *Config) HasValidCompressionLevel() bool { + return c.Level == LevelDefault || + c.Level == LevelOptimal || + c.Level == LevelFastest || + c.Level == LevelSmallestSize +} + +func (c *Config) compressionLevel() zstd.EncoderLevel { + switch c.Level { + case LevelDefault, LevelOptimal: + return zstd.SpeedDefault + case LevelFastest: + return zstd.SpeedFastest + case LevelSmallestSize: + return zstd.SpeedBestCompression + default: + assert.Fail("unknown compression level", string(c.Level)) + return zstd.SpeedDefault + } +} diff --git a/pkg/local_object_storage/blobstor/control.go b/pkg/local_object_storage/blobstor/control.go index 93316be026..0418eedd05 100644 --- a/pkg/local_object_storage/blobstor/control.go +++ b/pkg/local_object_storage/blobstor/control.go @@ -6,6 +6,7 @@ import ( "fmt" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "go.uber.org/zap" ) @@ -53,6 +54,10 @@ var ErrInitBlobovniczas = errors.New("failure on blobovnicza initialization stag func (b *BlobStor) Init(ctx context.Context) error { b.log.Debug(ctx, logs.BlobstorInitializing) + if !b.compression.HasValidCompressionLevel() { + b.log.Warn(ctx, logs.UnknownCompressionLevelDefaultWillBeUsed, zap.String("level", string(b.compression.Level))) + b.compression.Level = compression.LevelDefault + } if err := b.compression.Init(); err != nil { return err } From 8c746a914ac917a16b0ab3098e70fda7e15dcbb0 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 14 Apr 2025 16:18:08 +0300 Subject: [PATCH 1375/1413] [#1715] compression: Decouple Config and Compressor Refactoring. Change-Id: Ide2e1378f30c39045d4bacd13a902331bd4f764f Signed-off-by: Dmitrii Stepanov --- .../blobstor/blobovniczatree/blobovnicza.go | 4 ++-- .../blobstor/blobovniczatree/option.go | 2 +- pkg/local_object_storage/blobstor/blobstor.go | 4 ++-- .../blobstor/common/storage.go | 4 ++-- .../blobstor/compression/bench_test.go | 16 +++++++++----- .../blobstor/compression/compress.go | 22 +++++++++++-------- .../blobstor/fstree/fstree.go | 18 +++++++-------- .../blobstor/memstore/control.go | 4 ++-- .../blobstor/memstore/option.go | 2 +- .../blobstor/teststore/option.go | 8 +++---- .../blobstor/teststore/teststore.go | 4 ++-- .../writecache/writecache.go | 2 +- 12 files changed, 49 insertions(+), 41 deletions(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go index d9e99d0d13..3e8b9f07b6 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/blobovnicza.go @@ -158,11 +158,11 @@ func (b *Blobovniczas) Path() string { } // SetCompressor implements common.Storage. -func (b *Blobovniczas) SetCompressor(cc *compression.Config) { +func (b *Blobovniczas) SetCompressor(cc *compression.Compressor) { b.compression = cc } -func (b *Blobovniczas) Compressor() *compression.Config { +func (b *Blobovniczas) Compressor() *compression.Compressor { return b.compression } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index 0e1b2022e9..2f6d31b4ea 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -19,7 +19,7 @@ type cfg struct { openedCacheSize int blzShallowDepth uint64 blzShallowWidth uint64 - compression *compression.Config + compression *compression.Compressor blzOpts []blobovnicza.Option reportError func(context.Context, string, error) // reportError is the function called when encountering disk errors. metrics Metrics diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index 7a9568aff9..cf67c6fe94 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -41,7 +41,7 @@ type SubStorageInfo struct { type Option func(*cfg) type cfg struct { - compression compression.Config + compression compression.Compressor log *logger.Logger storage []SubStorage metrics Metrics @@ -158,6 +158,6 @@ func WithMetrics(m Metrics) Option { } } -func (b *BlobStor) Compressor() *compression.Config { +func (b *BlobStor) Compressor() *compression.Compressor { return &b.compression } diff --git a/pkg/local_object_storage/blobstor/common/storage.go b/pkg/local_object_storage/blobstor/common/storage.go index 6ecef48cdc..e35c35e602 100644 --- a/pkg/local_object_storage/blobstor/common/storage.go +++ b/pkg/local_object_storage/blobstor/common/storage.go @@ -18,8 +18,8 @@ type Storage interface { Path() string ObjectsCount(ctx context.Context) (uint64, error) - SetCompressor(cc *compression.Config) - Compressor() *compression.Config + SetCompressor(cc *compression.Compressor) + Compressor() *compression.Compressor // SetReportErrorFunc allows to provide a function to be called on disk errors. // This function MUST be called before Open. diff --git a/pkg/local_object_storage/blobstor/compression/bench_test.go b/pkg/local_object_storage/blobstor/compression/bench_test.go index 9f70f8ec2a..445a0494bc 100644 --- a/pkg/local_object_storage/blobstor/compression/bench_test.go +++ b/pkg/local_object_storage/blobstor/compression/bench_test.go @@ -11,7 +11,7 @@ import ( ) func BenchmarkCompression(b *testing.B) { - c := Config{Enabled: true} + c := Compressor{Config: Config{Enabled: true}} require.NoError(b, c.Init()) for _, size := range []int{128, 1024, 32 * 1024, 32 * 1024 * 1024} { @@ -33,7 +33,7 @@ func BenchmarkCompression(b *testing.B) { } } -func benchWith(b *testing.B, c Config, data []byte) { +func benchWith(b *testing.B, c Compressor, data []byte) { b.ResetTimer() b.ReportAllocs() for range b.N { @@ -56,8 +56,10 @@ func BenchmarkCompressionRealVSEstimate(b *testing.B) { b.Run("estimate", func(b *testing.B) { b.ResetTimer() - c := &Config{ - Enabled: true, + c := &Compressor{ + Config: Config{ + Enabled: true, + }, } require.NoError(b, c.Init()) @@ -76,8 +78,10 @@ func BenchmarkCompressionRealVSEstimate(b *testing.B) { b.Run("compress", func(b *testing.B) { b.ResetTimer() - c := &Config{ - Enabled: true, + c := &Compressor{ + Config: Config{ + Enabled: true, + }, } require.NoError(b, c.Init()) diff --git a/pkg/local_object_storage/blobstor/compression/compress.go b/pkg/local_object_storage/blobstor/compression/compress.go index 8a86b69826..efe84ea2a3 100644 --- a/pkg/local_object_storage/blobstor/compression/compress.go +++ b/pkg/local_object_storage/blobstor/compression/compress.go @@ -19,6 +19,13 @@ const ( LevelSmallestSize Level = "smallest_size" ) +type Compressor struct { + Config + + encoder *zstd.Encoder + decoder *zstd.Decoder +} + // Config represents common compression-related configuration. type Config struct { Enabled bool @@ -27,9 +34,6 @@ type Config struct { UseCompressEstimation bool CompressEstimationThreshold float64 - - encoder *zstd.Encoder - decoder *zstd.Decoder } // zstdFrameMagic contains first 4 bytes of any compressed object @@ -37,7 +41,7 @@ type Config struct { var zstdFrameMagic = []byte{0x28, 0xb5, 0x2f, 0xfd} // Init initializes compression routines. -func (c *Config) Init() error { +func (c *Compressor) Init() error { var err error if c.Enabled { @@ -84,7 +88,7 @@ func (c *Config) NeedsCompression(obj *objectSDK.Object) bool { // Decompress decompresses data if it starts with the magic // and returns data untouched otherwise. -func (c *Config) Decompress(data []byte) ([]byte, error) { +func (c *Compressor) Decompress(data []byte) ([]byte, error) { if len(data) < 4 || !bytes.Equal(data[:4], zstdFrameMagic) { return data, nil } @@ -93,7 +97,7 @@ func (c *Config) Decompress(data []byte) ([]byte, error) { // Compress compresses data if compression is enabled // and returns data untouched otherwise. -func (c *Config) Compress(data []byte) []byte { +func (c *Compressor) Compress(data []byte) []byte { if c == nil || !c.Enabled { return data } @@ -107,7 +111,7 @@ func (c *Config) Compress(data []byte) []byte { return c.compress(data) } -func (c *Config) compress(data []byte) []byte { +func (c *Compressor) compress(data []byte) []byte { maxSize := c.encoder.MaxEncodedSize(len(data)) compressed := c.encoder.EncodeAll(data, make([]byte, 0, maxSize)) if len(data) < len(compressed) { @@ -117,7 +121,7 @@ func (c *Config) compress(data []byte) []byte { } // Close closes encoder and decoder, returns any error occurred. -func (c *Config) Close() error { +func (c *Compressor) Close() error { var err error if c.encoder != nil { err = c.encoder.Close() @@ -135,7 +139,7 @@ func (c *Config) HasValidCompressionLevel() bool { c.Level == LevelSmallestSize } -func (c *Config) compressionLevel() zstd.EncoderLevel { +func (c *Compressor) compressionLevel() zstd.EncoderLevel { switch c.Level { case LevelDefault, LevelOptimal: return zstd.SpeedDefault diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 031b385b2d..112741ab41 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -45,7 +45,7 @@ type FSTree struct { log *logger.Logger - *compression.Config + compressor *compression.Compressor Depth uint64 DirNameLen int @@ -82,7 +82,7 @@ func New(opts ...Option) *FSTree { Permissions: 0o700, RootPath: "./", }, - Config: nil, + compressor: nil, Depth: 4, DirNameLen: DirNameLen, metrics: &noopMetrics{}, @@ -196,7 +196,7 @@ func (t *FSTree) iterate(ctx context.Context, depth uint64, curPath []string, pr } if err == nil { - data, err = t.Decompress(data) + data, err = t.compressor.Decompress(data) } if err != nil { if prm.IgnoreErrors { @@ -405,7 +405,7 @@ func (t *FSTree) Put(ctx context.Context, prm common.PutPrm) (common.PutRes, err return common.PutRes{}, err } if !prm.DontCompress { - prm.RawData = t.Compress(prm.RawData) + prm.RawData = t.compressor.Compress(prm.RawData) } size = len(prm.RawData) @@ -448,7 +448,7 @@ func (t *FSTree) Get(ctx context.Context, prm common.GetPrm) (common.GetRes, err } } - data, err = t.Decompress(data) + data, err = t.compressor.Decompress(data) if err != nil { return common.GetRes{}, err } @@ -597,12 +597,12 @@ func (t *FSTree) Path() string { } // SetCompressor implements common.Storage. -func (t *FSTree) SetCompressor(cc *compression.Config) { - t.Config = cc +func (t *FSTree) SetCompressor(cc *compression.Compressor) { + t.compressor = cc } -func (t *FSTree) Compressor() *compression.Config { - return t.Config +func (t *FSTree) Compressor() *compression.Compressor { + return t.compressor } // SetReportErrorFunc implements common.Storage. diff --git a/pkg/local_object_storage/blobstor/memstore/control.go b/pkg/local_object_storage/blobstor/memstore/control.go index 95a916662d..3df96a1c36 100644 --- a/pkg/local_object_storage/blobstor/memstore/control.go +++ b/pkg/local_object_storage/blobstor/memstore/control.go @@ -16,7 +16,7 @@ func (s *memstoreImpl) Init() error func (s *memstoreImpl) Close(context.Context) error { return nil } func (s *memstoreImpl) Type() string { return Type } func (s *memstoreImpl) Path() string { return s.rootPath } -func (s *memstoreImpl) SetCompressor(cc *compression.Config) { s.compression = cc } -func (s *memstoreImpl) Compressor() *compression.Config { return s.compression } +func (s *memstoreImpl) SetCompressor(cc *compression.Compressor) { s.compression = cc } +func (s *memstoreImpl) Compressor() *compression.Compressor { return s.compression } func (s *memstoreImpl) SetReportErrorFunc(func(context.Context, string, error)) {} func (s *memstoreImpl) SetParentID(string) {} diff --git a/pkg/local_object_storage/blobstor/memstore/option.go b/pkg/local_object_storage/blobstor/memstore/option.go index 97a03993d5..7605af4e59 100644 --- a/pkg/local_object_storage/blobstor/memstore/option.go +++ b/pkg/local_object_storage/blobstor/memstore/option.go @@ -7,7 +7,7 @@ import ( type cfg struct { rootPath string readOnly bool - compression *compression.Config + compression *compression.Compressor } func defaultConfig() *cfg { diff --git a/pkg/local_object_storage/blobstor/teststore/option.go b/pkg/local_object_storage/blobstor/teststore/option.go index fb11887517..3a38ecf82f 100644 --- a/pkg/local_object_storage/blobstor/teststore/option.go +++ b/pkg/local_object_storage/blobstor/teststore/option.go @@ -17,8 +17,8 @@ type cfg struct { Type func() string Path func() string - SetCompressor func(cc *compression.Config) - Compressor func() *compression.Config + SetCompressor func(cc *compression.Compressor) + Compressor func() *compression.Compressor SetReportErrorFunc func(f func(context.Context, string, error)) Get func(common.GetPrm) (common.GetRes, error) @@ -45,11 +45,11 @@ func WithClose(f func() error) Option { return func(c *cfg) { c func WithType(f func() string) Option { return func(c *cfg) { c.overrides.Type = f } } func WithPath(f func() string) Option { return func(c *cfg) { c.overrides.Path = f } } -func WithSetCompressor(f func(*compression.Config)) Option { +func WithSetCompressor(f func(*compression.Compressor)) Option { return func(c *cfg) { c.overrides.SetCompressor = f } } -func WithCompressor(f func() *compression.Config) Option { +func WithCompressor(f func() *compression.Compressor) Option { return func(c *cfg) { c.overrides.Compressor = f } } diff --git a/pkg/local_object_storage/blobstor/teststore/teststore.go b/pkg/local_object_storage/blobstor/teststore/teststore.go index 626ba00231..190b6a8760 100644 --- a/pkg/local_object_storage/blobstor/teststore/teststore.go +++ b/pkg/local_object_storage/blobstor/teststore/teststore.go @@ -116,7 +116,7 @@ func (s *TestStore) Path() string { } } -func (s *TestStore) SetCompressor(cc *compression.Config) { +func (s *TestStore) SetCompressor(cc *compression.Compressor) { s.mu.RLock() defer s.mu.RUnlock() switch { @@ -129,7 +129,7 @@ func (s *TestStore) SetCompressor(cc *compression.Config) { } } -func (s *TestStore) Compressor() *compression.Config { +func (s *TestStore) Compressor() *compression.Compressor { s.mu.RLock() defer s.mu.RUnlock() switch { diff --git a/pkg/local_object_storage/writecache/writecache.go b/pkg/local_object_storage/writecache/writecache.go index 70b17eb8e6..7ed5113189 100644 --- a/pkg/local_object_storage/writecache/writecache.go +++ b/pkg/local_object_storage/writecache/writecache.go @@ -52,7 +52,7 @@ type Cache interface { // MainStorage is the interface of the underlying storage of Cache implementations. type MainStorage interface { - Compressor() *compression.Config + Compressor() *compression.Compressor Exists(context.Context, common.ExistsPrm) (common.ExistsRes, error) Put(context.Context, common.PutPrm) (common.PutRes, error) } From 0ee7467da5c9cda8c398a011fa00c86657b7cbc3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 14 Apr 2025 17:36:51 +0300 Subject: [PATCH 1376/1413] [#1715] config: Add `compression` config section To group all `compression_*` parameters together. Change-Id: I11ad9600f731903753fef1adfbc0328ef75bbf87 Signed-off-by: Dmitrii Stepanov --- .../maintenance/zombie/storage_engine.go | 7 +-- cmd/frostfs-node/config.go | 18 +----- cmd/frostfs-node/config/engine/config_test.go | 17 +++--- .../config/engine/shard/config.go | 56 ++++++------------- config/example/node.env | 2 +- config/example/node.json | 20 ++++--- config/example/node.yaml | 18 +++--- docs/storage-node-configuration.md | 51 +++++++++++------ pkg/local_object_storage/blobstor/blobstor.go | 47 +--------------- .../blobstor/blobstor_test.go | 11 +++- .../blobstor/compression/compress.go | 8 +-- .../blobstor/iterate_test.go | 5 +- 12 files changed, 105 insertions(+), 155 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go index fe75a6f6f3..c54b331f33 100644 --- a/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go @@ -13,7 +13,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" @@ -135,11 +134,7 @@ func getMetabaseOpts(sh *shardconfig.Config) []meta.Option { func getBlobstorOpts(ctx context.Context, sh *shardconfig.Config) []blobstor.Option { result := []blobstor.Option{ - blobstor.WithCompressObjects(sh.Compress()), - blobstor.WithCompressionLevel(compression.Level(sh.CompressionLevel())), - blobstor.WithUncompressableContentTypes(sh.UncompressableContentTypes()), - blobstor.WithCompressibilityEstimate(sh.EstimateCompressibility()), - blobstor.WithCompressibilityEstimateThreshold(sh.EstimateCompressibilityThreshold()), + blobstor.WithCompression(sh.Compression()), blobstor.WithStorages(getSubStorages(ctx, sh)), blobstor.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index f32953c584..f80401b5ba 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -129,13 +129,9 @@ type applicationConfiguration struct { } type shardCfg struct { - compress bool - compressionLevel compression.Level - estimateCompressibility bool - estimateCompressibilityThreshold float64 + compression compression.Config smallSizeObjectLimit uint64 - uncompressableContentType []string refillMetabase bool refillMetabaseWorkersCount int mode shardmode.Mode @@ -274,11 +270,7 @@ func (a *applicationConfiguration) updateShardConfig(c *config.Config, source *s target.refillMetabase = source.RefillMetabase() target.refillMetabaseWorkersCount = source.RefillMetabaseWorkersCount() target.mode = source.Mode() - target.compress = source.Compress() - target.compressionLevel = compression.Level(source.CompressionLevel()) - target.estimateCompressibility = source.EstimateCompressibility() - target.estimateCompressibilityThreshold = source.EstimateCompressibilityThreshold() - target.uncompressableContentType = source.UncompressableContentTypes() + target.compression = source.Compression() target.smallSizeObjectLimit = source.SmallSizeLimit() a.setShardWriteCacheConfig(&target, source) @@ -1029,11 +1021,7 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID ss := c.getSubstorageOpts(ctx, shCfg) blobstoreOpts := []blobstor.Option{ - blobstor.WithCompressObjects(shCfg.compress), - blobstor.WithCompressionLevel(shCfg.compressionLevel), - blobstor.WithUncompressableContentTypes(shCfg.uncompressableContentType), - blobstor.WithCompressibilityEstimate(shCfg.estimateCompressibility), - blobstor.WithCompressibilityEstimateThreshold(shCfg.estimateCompressibilityThreshold), + blobstor.WithCompression(shCfg.compression), blobstor.WithStorages(ss), blobstor.WithLogger(c.log), } diff --git a/cmd/frostfs-node/config/engine/config_test.go b/cmd/frostfs-node/config/engine/config_test.go index afadb4c995..401c54edcd 100644 --- a/cmd/frostfs-node/config/engine/config_test.go +++ b/cmd/frostfs-node/config/engine/config_test.go @@ -15,6 +15,7 @@ import ( writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/writecache" configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" "github.com/stretchr/testify/require" ) @@ -100,11 +101,11 @@ func TestEngineSection(t *testing.T) { require.Equal(t, 100, meta.BoltDB().MaxBatchSize()) require.Equal(t, 10*time.Millisecond, meta.BoltDB().MaxBatchDelay()) - require.Equal(t, true, sc.Compress()) - require.Equal(t, "fastest", sc.CompressionLevel()) - require.Equal(t, []string{"audio/*", "video/*"}, sc.UncompressableContentTypes()) - require.Equal(t, true, sc.EstimateCompressibility()) - require.Equal(t, float64(0.7), sc.EstimateCompressibilityThreshold()) + require.Equal(t, true, sc.Compression().Enabled) + require.Equal(t, compression.LevelFastest, sc.Compression().Level) + require.Equal(t, []string{"audio/*", "video/*"}, sc.Compression().UncompressableContentTypes) + require.Equal(t, true, sc.Compression().EstimateCompressibility) + require.Equal(t, float64(0.7), sc.Compression().EstimateCompressibilityThreshold) require.EqualValues(t, 102400, sc.SmallSizeLimit()) require.Equal(t, 2, len(ss)) @@ -237,9 +238,9 @@ func TestEngineSection(t *testing.T) { require.Equal(t, 200, meta.BoltDB().MaxBatchSize()) require.Equal(t, 20*time.Millisecond, meta.BoltDB().MaxBatchDelay()) - require.Equal(t, false, sc.Compress()) - require.Equal(t, "", sc.CompressionLevel()) - require.Equal(t, []string(nil), sc.UncompressableContentTypes()) + require.Equal(t, false, sc.Compression().Enabled) + require.Equal(t, compression.LevelDefault, sc.Compression().Level) + require.Equal(t, []string(nil), sc.Compression().UncompressableContentTypes) require.EqualValues(t, 102400, sc.SmallSizeLimit()) require.Equal(t, 2, len(ss)) diff --git a/cmd/frostfs-node/config/engine/shard/config.go b/cmd/frostfs-node/config/engine/shard/config.go index 14e91f01ff..d42646da7a 100644 --- a/cmd/frostfs-node/config/engine/shard/config.go +++ b/cmd/frostfs-node/config/engine/shard/config.go @@ -8,6 +8,7 @@ import ( metabaseconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/metabase" piloramaconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/pilorama" writecacheconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard/writecache" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" ) @@ -27,52 +28,27 @@ func From(c *config.Config) *Config { return (*Config)(c) } -// Compress returns the value of "compress" config parameter. -// -// Returns false if the value is not a valid bool. -func (x *Config) Compress() bool { - return config.BoolSafe( - (*config.Config)(x), - "compress", - ) -} - -// CompressionLevel returns the value of "compression_level" config parameter. -// -// Returns empty string if the value is not a valid string. -func (x *Config) CompressionLevel() string { - return config.StringSafe( - (*config.Config)(x), - "compression_level", - ) -} - -// UncompressableContentTypes returns the value of "compress_skip_content_types" config parameter. -// -// Returns nil if a the value is missing or is invalid. -func (x *Config) UncompressableContentTypes() []string { - return config.StringSliceSafe( - (*config.Config)(x), - "compression_exclude_content_types") -} - -// EstimateCompressibility returns the value of "estimate_compressibility" config parameter. -// -// Returns false if the value is not a valid bool. -func (x *Config) EstimateCompressibility() bool { - return config.BoolSafe( - (*config.Config)(x), - "compression_estimate_compressibility", - ) +func (x *Config) Compression() compression.Config { + cc := (*config.Config)(x).Sub("compression") + if cc == nil { + return compression.Config{} + } + return compression.Config{ + Enabled: config.BoolSafe(cc, "enabled"), + UncompressableContentTypes: config.StringSliceSafe(cc, "exclude_content_types"), + Level: compression.Level(config.StringSafe(cc, "level")), + EstimateCompressibility: config.BoolSafe(cc, "estimate_compressibility"), + EstimateCompressibilityThreshold: estimateCompressibilityThreshold(cc), + } } // EstimateCompressibilityThreshold returns the value of "estimate_compressibility_threshold" config parameter. // // Returns EstimateCompressibilityThresholdDefault if the value is not defined, not valid float or not in range [0.0; 1.0]. -func (x *Config) EstimateCompressibilityThreshold() float64 { +func estimateCompressibilityThreshold(c *config.Config) float64 { v := config.FloatOrDefault( - (*config.Config)(x), - "compression_estimate_compressibility_threshold", + c, + "estimate_compressibility_threshold", EstimateCompressibilityThresholdDefault) if v < 0.0 || v > 1.0 { return EstimateCompressibilityThresholdDefault diff --git a/config/example/node.env b/config/example/node.env index fb4fc69dd7..9d054fe78f 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -122,7 +122,7 @@ FROSTFS_STORAGE_SHARD_0_METABASE_PERM=0644 FROSTFS_STORAGE_SHARD_0_METABASE_MAX_BATCH_SIZE=100 FROSTFS_STORAGE_SHARD_0_METABASE_MAX_BATCH_DELAY=10ms ### Blobstor config -FROSTFS_STORAGE_SHARD_0_COMPRESS=true +FROSTFS_STORAGE_SHARD_0_COMPRESSION_ENABLED=true FROSTFS_STORAGE_SHARD_0_COMPRESSION_LEVEL=fastest FROSTFS_STORAGE_SHARD_0_COMPRESSION_EXCLUDE_CONTENT_TYPES="audio/* video/*" FROSTFS_STORAGE_SHARD_0_COMPRESSION_ESTIMATE_COMPRESSIBILITY=true diff --git a/config/example/node.json b/config/example/node.json index 1e9dd7835b..110e99ee88 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -183,13 +183,15 @@ "max_batch_size": 100, "max_batch_delay": "10ms" }, - "compress": true, - "compression_level": "fastest", - "compression_exclude_content_types": [ - "audio/*", "video/*" - ], - "compression_estimate_compressibility": true, - "compression_estimate_compressibility_threshold": 0.7, + "compression": { + "enabled": true, + "level": "fastest", + "exclude_content_types": [ + "audio/*", "video/*" + ], + "estimate_compressibility": true, + "estimate_compressibility_threshold": 0.7 + }, "small_object_size": 102400, "blobstor": [ { @@ -323,7 +325,9 @@ "max_batch_size": 200, "max_batch_delay": "20ms" }, - "compress": false, + "compression": { + "enabled": false + }, "small_object_size": 102400, "blobstor": [ { diff --git a/config/example/node.yaml b/config/example/node.yaml index 26c6e248c8..de5eaa1331 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -160,7 +160,8 @@ storage: max_batch_delay: 5ms # maximum delay for a batch of operations to be executed max_batch_size: 100 # maximum amount of operations in a single batch - compress: false # turn on/off zstd compression of stored objects + compression: + enabled: false # turn on/off zstd compression of stored objects small_object_size: 100 kb # size threshold for "small" objects which are cached in key-value DB, not in FS, bytes blobstor: @@ -202,13 +203,14 @@ storage: max_batch_size: 100 max_batch_delay: 10ms - compress: true # turn on/off zstd compression of stored objects - compression_level: fastest - compression_exclude_content_types: - - audio/* - - video/* - compression_estimate_compressibility: true - compression_estimate_compressibility_threshold: 0.7 + compression: + enabled: true # turn on/off zstd compression of stored objects + level: fastest + exclude_content_types: + - audio/* + - video/* + estimate_compressibility: true + estimate_compressibility_threshold: 0.7 blobstor: - type: blobovnicza diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 19f6ee66d0..1494d2fca2 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -185,22 +185,41 @@ Contains configuration for each shard. Keys must be consecutive numbers starting `default` subsection has the same format and specifies defaults for missing values. The following table describes configuration for each shard. -| Parameter | Type | Default value | Description | -| ------------------------------------------------ | ------------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `compress` | `bool` | `false` | Flag to enable compression. | -| `compression_level` | `string` | `optimal` | Compression level. Available values are `optimal`, `fastest`, `smallest_size`. | -| `compression_exclude_content_types` | `[]string` | | List of content-types to disable compression for. Content-type is taken from `Content-Type` object attribute. Each element can contain a star `*` as a first (last) character, which matches any prefix (suffix). | -| `compression_estimate_compressibility` | `bool` | `false` | If `true`, then noramalized compressibility estimation is used to decide compress data or not. | -| `compression_estimate_compressibility_threshold` | `float` | `0.1` | Normilized compressibility estimate threshold: data will compress if estimation if greater than this value. | -| `mode` | `string` | `read-write` | Shard Mode.
Possible values: `read-write`, `read-only`, `degraded`, `degraded-read-only`, `disabled` | -| `resync_metabase` | `bool` | `false` | Flag to enable metabase resync on start. | -| `resync_metabase_worker_count` | `int` | `1000` | Count of concurrent workers to resync metabase. | -| `writecache` | [Writecache config](#writecache-subsection) | | Write-cache configuration. | -| `metabase` | [Metabase config](#metabase-subsection) | | Metabase configuration. | -| `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | -| `small_object_size` | `size` | `1M` | Maximum size of an object stored in blobovnicza tree. | -| `gc` | [GC config](#gc-subsection) | | GC configuration. | -| `limits` | [Shard limits config](#limits-subsection) | | Shard limits configuration. | +| Parameter | Type | Default value | Description | +| ------------------------------ | --------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------- | +| `compression` | [Compression config](#compression-subsection) | | Compression config. | +| `mode` | `string` | `read-write` | Shard Mode.
Possible values: `read-write`, `read-only`, `degraded`, `degraded-read-only`, `disabled` | +| `resync_metabase` | `bool` | `false` | Flag to enable metabase resync on start. | +| `resync_metabase_worker_count` | `int` | `1000` | Count of concurrent workers to resync metabase. | +| `writecache` | [Writecache config](#writecache-subsection) | | Write-cache configuration. | +| `metabase` | [Metabase config](#metabase-subsection) | | Metabase configuration. | +| `blobstor` | [Blobstor config](#blobstor-subsection) | | Blobstor configuration. | +| `small_object_size` | `size` | `1M` | Maximum size of an object stored in blobovnicza tree. | +| `gc` | [GC config](#gc-subsection) | | GC configuration. | +| `limits` | [Shard limits config](#limits-subsection) | | Shard limits configuration. | + +### `compression` subsection + +Contains compression config. + +```yaml +compression: + enabled: true + level: smallest_size + exclude_content_types: + - audio/* + - video/* + estimate_compressibility: true + estimate_compressibility_threshold: 0.7 +``` + +| Parameter | Type | Default value | Description | +| ------------------------------------ | ---------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `enabled` | `bool` | `false` | Flag to enable compression. | +| `level` | `string` | `optimal` | Compression level. Available values are `optimal`, `fastest`, `smallest_size`. | +| `exclude_content_types` | `[]string` | | List of content-types to disable compression for. Content-type is taken from `Content-Type` object attribute. Each element can contain a star `*` as a first (last) character, which matches any prefix (suffix). | +| `estimate_compressibility` | `bool` | `false` | If `true`, then noramalized compressibility estimation is used to decide compress data or not. | +| `estimate_compressibility_threshold` | `float` | `0.1` | Normilized compressibility estimate threshold: data will compress if estimation if greater than this value. | ### `blobstor` subsection diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index cf67c6fe94..edb2c19461 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -95,52 +95,9 @@ func WithLogger(l *logger.Logger) Option { } } -// WithCompressObjects returns option to toggle -// compression of the stored objects. -// -// If true, Zstandard algorithm is used for data compression. -// -// If compressor (decompressor) creation failed, -// the uncompressed option will be used, and the error -// is recorded in the provided log. -func WithCompressObjects(comp bool) Option { +func WithCompression(comp compression.Config) Option { return func(c *cfg) { - c.compression.Enabled = comp - } -} - -func WithCompressionLevel(level compression.Level) Option { - return func(c *cfg) { - c.compression.Level = level - } -} - -// WithCompressibilityEstimate returns an option to use -// normilized compressibility estimate to decide compress -// data or not. -// -// See https://github.com/klauspost/compress/blob/v1.17.2/compressible.go#L5 -func WithCompressibilityEstimate(v bool) Option { - return func(c *cfg) { - c.compression.UseCompressEstimation = v - } -} - -// WithCompressibilityEstimateThreshold returns an option to set -// normilized compressibility estimate threshold. -// -// See https://github.com/klauspost/compress/blob/v1.17.2/compressible.go#L5 -func WithCompressibilityEstimateThreshold(threshold float64) Option { - return func(c *cfg) { - c.compression.CompressEstimationThreshold = threshold - } -} - -// WithUncompressableContentTypes returns option to disable decompression -// for specific content types as seen by object.AttributeContentType attribute. -func WithUncompressableContentTypes(values []string) Option { - return func(c *cfg) { - c.compression.UncompressableContentTypes = values + c.compression.Config = comp } } diff --git a/pkg/local_object_storage/blobstor/blobstor_test.go b/pkg/local_object_storage/blobstor/blobstor_test.go index 6cc56fa3b2..6ddeb6f008 100644 --- a/pkg/local_object_storage/blobstor/blobstor_test.go +++ b/pkg/local_object_storage/blobstor/blobstor_test.go @@ -9,6 +9,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/object" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/blobovniczatree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/fstree" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -51,7 +52,9 @@ func TestCompression(t *testing.T) { newBlobStor := func(t *testing.T, compress bool) *BlobStor { bs := New( - WithCompressObjects(compress), + WithCompression(compression.Config{ + Enabled: compress, + }), WithStorages(defaultStorages(dir, smallSizeLimit))) require.NoError(t, bs.Open(context.Background(), mode.ReadWrite)) require.NoError(t, bs.Init(context.Background())) @@ -113,8 +116,10 @@ func TestBlobstor_needsCompression(t *testing.T) { dir := t.TempDir() bs := New( - WithCompressObjects(compress), - WithUncompressableContentTypes(ct), + WithCompression(compression.Config{ + Enabled: compress, + UncompressableContentTypes: ct, + }), WithStorages([]SubStorage{ { Storage: blobovniczatree.NewBlobovniczaTree( diff --git a/pkg/local_object_storage/blobstor/compression/compress.go b/pkg/local_object_storage/blobstor/compression/compress.go index efe84ea2a3..c76cec9a10 100644 --- a/pkg/local_object_storage/blobstor/compression/compress.go +++ b/pkg/local_object_storage/blobstor/compression/compress.go @@ -32,8 +32,8 @@ type Config struct { UncompressableContentTypes []string Level Level - UseCompressEstimation bool - CompressEstimationThreshold float64 + EstimateCompressibility bool + EstimateCompressibilityThreshold float64 } // zstdFrameMagic contains first 4 bytes of any compressed object @@ -101,9 +101,9 @@ func (c *Compressor) Compress(data []byte) []byte { if c == nil || !c.Enabled { return data } - if c.UseCompressEstimation { + if c.EstimateCompressibility { estimated := compress.Estimate(data) - if estimated >= c.CompressEstimationThreshold { + if estimated >= c.EstimateCompressibilityThreshold { return c.compress(data) } return data diff --git a/pkg/local_object_storage/blobstor/iterate_test.go b/pkg/local_object_storage/blobstor/iterate_test.go index ccfa510fe4..2786321a82 100644 --- a/pkg/local_object_storage/blobstor/iterate_test.go +++ b/pkg/local_object_storage/blobstor/iterate_test.go @@ -8,6 +8,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/compression" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/memstore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/teststore" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard/mode" @@ -24,7 +25,9 @@ func TestIterateObjects(t *testing.T) { // create BlobStor instance blobStor := New( WithStorages(defaultStorages(p, smalSz)), - WithCompressObjects(true), + WithCompression(compression.Config{ + Enabled: true, + }), ) defer os.RemoveAll(p) From 410b6f70bae0e44da29d328ec3ba532042617c8b Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 15 Apr 2025 17:56:47 +0300 Subject: [PATCH 1377/1413] [#1716] cli: Return trace ID on operation failure Close #1716 Change-Id: I293d0cc6b7331517e8cde42eae07d65384976da5 Signed-off-by: Aleksey Savchuk --- cmd/internal/common/exit.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/internal/common/exit.go b/cmd/internal/common/exit.go index b8acf0143a..13f447af4b 100644 --- a/cmd/internal/common/exit.go +++ b/cmd/internal/common/exit.go @@ -51,8 +51,13 @@ func ExitOnErr(cmd *cobra.Command, errFmt string, err error) { } cmd.PrintErrln(err) - if cmd.PersistentPostRun != nil { - cmd.PersistentPostRun(cmd, nil) + for p := cmd; p != nil; p = p.Parent() { + if p.PersistentPostRun != nil { + p.PersistentPostRun(cmd, nil) + if !cobra.EnableTraverseRunHooks { + break + } + } } os.Exit(code) } From a285d8924f87da6af50ad3fc28b5ac5726fc92e8 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Mon, 14 Apr 2025 12:38:52 +0300 Subject: [PATCH 1378/1413] [#1693] node: Replace conditional panics with asserts Change-Id: I5024705fd1693d00cb9241235030a73984c2a7e1 Signed-off-by: Ekaterina Lebedeva --- cmd/frostfs-node/netmap.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 6d57edcce5..82b799e4c8 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -8,6 +8,7 @@ import ( "net" "sync/atomic" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" @@ -104,9 +105,7 @@ func (s *networkState) getNodeInfo() (res netmapSDK.NodeInfo, ok bool) { v := s.nodeInfo.Load() if v != nil { res, ok = v.(netmapSDK.NodeInfo) - if !ok { - panic(fmt.Sprintf("unexpected value in atomic node info state: %T", v)) - } + assert.True(ok, fmt.Sprintf("unexpected value in atomic node info state: %T", v)) } return From fc6abe30b892491fce0053492220e2ec91e11236 Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 8 Apr 2025 16:47:52 +0300 Subject: [PATCH 1379/1413] [#1693] storage: Replace conditional panics with asserts Change-Id: I9d8ccde3c71fca716856c7bfc53da20ee0542f20 Signed-off-by: Ekaterina Lebedeva --- .../blobstor/fstree/counter.go | 17 +++++++---------- pkg/local_object_storage/metabase/lock.go | 5 ++--- pkg/local_object_storage/metabase/util.go | 5 ++--- pkg/local_object_storage/writecache/limiter.go | 16 ++++++---------- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/pkg/local_object_storage/blobstor/fstree/counter.go b/pkg/local_object_storage/blobstor/fstree/counter.go index b5dbc9e409..3caee7ee16 100644 --- a/pkg/local_object_storage/blobstor/fstree/counter.go +++ b/pkg/local_object_storage/blobstor/fstree/counter.go @@ -2,6 +2,8 @@ package fstree import ( "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" ) // FileCounter used to count files in FSTree. The implementation must be thread-safe. @@ -52,16 +54,11 @@ func (c *SimpleCounter) Dec(size uint64) { c.mtx.Lock() defer c.mtx.Unlock() - if c.count > 0 { - c.count-- - } else { - panic("fstree.SimpleCounter: invalid count") - } - if c.size >= size { - c.size -= size - } else { - panic("fstree.SimpleCounter: invalid size") - } + assert.True(c.count > 0, "fstree.SimpleCounter: invalid count") + c.count-- + + assert.True(c.size >= size, "fstree.SimpleCounter: invalid size") + c.size -= size } func (c *SimpleCounter) CountSize() (uint64, uint64) { diff --git a/pkg/local_object_storage/metabase/lock.go b/pkg/local_object_storage/metabase/lock.go index f73c2b4f68..f4cb9e53bc 100644 --- a/pkg/local_object_storage/metabase/lock.go +++ b/pkg/local_object_storage/metabase/lock.go @@ -7,6 +7,7 @@ import ( "slices" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/internal/metaerr" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/util/logicerr" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" @@ -63,9 +64,7 @@ func (db *DB) Lock(ctx context.Context, cnr cid.ID, locker oid.ID, locked []oid. return ErrReadOnlyMode } - if len(locked) == 0 { - panic("empty locked list") - } + assert.False(len(locked) == 0, "empty locked list") err := db.lockInternal(locked, cnr, locker) success = err == nil diff --git a/pkg/local_object_storage/metabase/util.go b/pkg/local_object_storage/metabase/util.go index 80851f1c43..4ad83332bf 100644 --- a/pkg/local_object_storage/metabase/util.go +++ b/pkg/local_object_storage/metabase/util.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" @@ -278,9 +279,7 @@ func objectKey(obj oid.ID, key []byte) []byte { // // firstIrregularObjectType(tx, cnr, obj) usage allows getting object type. func firstIrregularObjectType(tx *bbolt.Tx, idCnr cid.ID, objs ...[]byte) objectSDK.Type { - if len(objs) == 0 { - panic("empty object list in firstIrregularObjectType") - } + assert.False(len(objs) == 0, "empty object list in firstIrregularObjectType") var keys [2][1 + cidSize]byte diff --git a/pkg/local_object_storage/writecache/limiter.go b/pkg/local_object_storage/writecache/limiter.go index ddc4101be1..0e020b36eb 100644 --- a/pkg/local_object_storage/writecache/limiter.go +++ b/pkg/local_object_storage/writecache/limiter.go @@ -3,6 +3,8 @@ package writecache import ( "errors" "sync" + + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" ) var errLimiterClosed = errors.New("acquire failed: limiter closed") @@ -45,17 +47,11 @@ func (l *flushLimiter) release(size uint64) { l.cond.L.Lock() defer l.cond.L.Unlock() - if l.size >= size { - l.size -= size - } else { - panic("flushLimiter: invalid size") - } + assert.True(l.size >= size, "flushLimiter: invalid size") + l.size -= size - if l.count > 0 { - l.count-- - } else { - panic("flushLimiter: invalid count") - } + assert.True(l.count > 0, "flushLimiter: invalid count") + l.count-- l.cond.Broadcast() } From bc045b29e21b458c9d3f244f05a16bce9869059e Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 8 Apr 2025 16:54:05 +0300 Subject: [PATCH 1380/1413] [#1693] services: Replace conditional panics with asserts Change-Id: Ic79609e6ad867caa88ad245b3014aa7fc32e05a8 Signed-off-by: Ekaterina Lebedeva --- pkg/services/netmap/executor.go | 11 +++++++---- pkg/services/object_manager/tombstone/constructor.go | 5 ++--- .../object_manager/tombstone/source/source.go | 5 ++--- pkg/services/policer/policer.go | 6 +++--- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/pkg/services/netmap/executor.go b/pkg/services/netmap/executor.go index 44101a1530..1b92fdaade 100644 --- a/pkg/services/netmap/executor.go +++ b/pkg/services/netmap/executor.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/version" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util/response" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/netmap" @@ -46,10 +47,12 @@ type NetworkInfo interface { } func NewExecutionService(s NodeState, v versionsdk.Version, netInfo NetworkInfo, respSvc *response.Service) Server { - if s == nil || netInfo == nil || !version.IsValid(v) || respSvc == nil { - // this should never happen, otherwise it programmers bug - panic("can't create netmap execution service") - } + // this should never happen, otherwise it's a programmer's bug + msg := "BUG: can't create netmap execution service" + assert.False(s == nil, msg, "node state is nil") + assert.False(netInfo == nil, msg, "network info is nil") + assert.False(respSvc == nil, msg, "response service is nil") + assert.True(version.IsValid(v), msg, "invalid version") res := &executorSvc{ state: s, diff --git a/pkg/services/object_manager/tombstone/constructor.go b/pkg/services/object_manager/tombstone/constructor.go index 67ddf316f2..2147a32fe8 100644 --- a/pkg/services/object_manager/tombstone/constructor.go +++ b/pkg/services/object_manager/tombstone/constructor.go @@ -3,6 +3,7 @@ package tombstone import ( "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" lru "github.com/hashicorp/golang-lru/v2" "go.uber.org/zap" @@ -49,9 +50,7 @@ func NewChecker(oo ...Option) *ExpirationChecker { panicOnNil(cfg.tsSource, "Tombstone source") cache, err := lru.New[string, uint64](cfg.cacheSize) - if err != nil { - panic(fmt.Errorf("could not create LRU cache with %d size: %w", cfg.cacheSize, err)) - } + assert.NoError(err, fmt.Sprintf("could not create LRU cache with %d size", cfg.cacheSize)) return &ExpirationChecker{ cache: cache, diff --git a/pkg/services/object_manager/tombstone/source/source.go b/pkg/services/object_manager/tombstone/source/source.go index 1ff07b05a0..9759418471 100644 --- a/pkg/services/object_manager/tombstone/source/source.go +++ b/pkg/services/object_manager/tombstone/source/source.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" @@ -38,9 +39,7 @@ func (s *TombstoneSourcePrm) SetGetService(v *getsvc.Service) { // Panics if any of the provided options does not allow // constructing a valid tombstone local Source. func NewSource(p TombstoneSourcePrm) Source { - if p.s == nil { - panic("Tombstone source: nil object service") - } + assert.False(p.s == nil, "Tombstone source: nil object service") return Source(p) } diff --git a/pkg/services/policer/policer.go b/pkg/services/policer/policer.go index 4e8bacfec1..d18b71a238 100644 --- a/pkg/services/policer/policer.go +++ b/pkg/services/policer/policer.go @@ -1,9 +1,11 @@ package policer import ( + "fmt" "sync" "time" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" lru "github.com/hashicorp/golang-lru/v2" "go.uber.org/zap" @@ -57,9 +59,7 @@ func New(opts ...Option) *Policer { c.log = c.log.With(zap.String("component", "Object Policer")) cache, err := lru.New[oid.Address, time.Time](int(c.cacheSize)) - if err != nil { - panic(err) - } + assert.NoError(err, fmt.Sprintf("could not create LRU cache with %d size", c.cacheSize)) return &Policer{ cfg: c, From 5dd8d7e87ab20ff3d7e1c4c2d93982a1ae79381a Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 8 Apr 2025 16:54:51 +0300 Subject: [PATCH 1381/1413] [#1693] network: Replace conditional panics with asserts Change-Id: Icba39aa2ed0048d63c6efed398273627e1e4fbbe Signed-off-by: Ekaterina Lebedeva --- pkg/network/address.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/network/address.go b/pkg/network/address.go index cb83a813d6..4643eef15b 100644 --- a/pkg/network/address.go +++ b/pkg/network/address.go @@ -2,11 +2,11 @@ package network import ( "errors" - "fmt" "net" "net/url" "strings" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/rpc/client" "github.com/multiformats/go-multiaddr" manet "github.com/multiformats/go-multiaddr/net" @@ -44,11 +44,9 @@ func (a Address) equal(addr Address) bool { // See also FromString. func (a Address) URIAddr() string { _, host, err := manet.DialArgs(a.ma) - if err != nil { - // the only correct way to construct Address is AddressFromString - // which makes this error appear unexpected - panic(fmt.Errorf("could not get host addr: %w", err)) - } + // the only correct way to construct Address is AddressFromString + // which makes this error appear unexpected + assert.NoError(err, "could not get host addr") if !a.IsTLSEnabled() { return host From e45382b0c18ef6f5b116df4cd89f7813d271d54d Mon Sep 17 00:00:00 2001 From: Ekaterina Lebedeva Date: Tue, 8 Apr 2025 16:55:56 +0300 Subject: [PATCH 1382/1413] [#1693] util: Replace conditional panics with asserts Change-Id: I13b566cde3e6d43d8a75aa2e9b28e63b597adff9 Signed-off-by: Ekaterina Lebedeva --- pkg/util/keyer/dashboard.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/util/keyer/dashboard.go b/pkg/util/keyer/dashboard.go index b2942b52a6..6337039a9b 100644 --- a/pkg/util/keyer/dashboard.go +++ b/pkg/util/keyer/dashboard.go @@ -6,6 +6,7 @@ import ( "os" "text/tabwriter" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" "github.com/mr-tron/base58" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" @@ -104,9 +105,7 @@ func (d Dashboard) PrettyPrint(uncompressed, useHex bool) { func base58ToHex(data string) string { val, err := base58.Decode(data) - if err != nil { - panic("produced incorrect base58 value") - } + assert.NoError(err, "produced incorrect base58 value") return hex.EncodeToString(val) } From 36fb15b9a4b1b7771b2011c745222326ee6e9299 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Wed, 16 Apr 2025 11:55:00 +0300 Subject: [PATCH 1383/1413] [#1689] engine: Return error if object is locked during inhume Return `object is locked` error if object doesn't exists but is locked, since the locked index may be populated even when the object itself doesn't exist. Change-Id: If1a145c6efead9873acd33bb4fd22cf6175cbabd Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/inhume.go | 11 ++-- .../engine/inhume_test.go | 55 +++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index 6ec9a4ef0e..e5a2396e1c 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -186,10 +186,6 @@ func (e *StorageEngine) findShards(ctx context.Context, addr oid.Address, checkL default: } - if !objectExists { - return - } - if checkLocked { if isLocked, err := sh.IsLocked(ctx, addr); err != nil { e.log.Warn(ctx, logs.EngineRemovingAnObjectWithoutFullLockingCheck, @@ -202,6 +198,13 @@ func (e *StorageEngine) findShards(ctx context.Context, addr oid.Address, checkL } } + // This exit point must come after checking if the object is locked, + // since the locked index may be populated even if the object doesn't + // exist. + if !objectExists { + return + } + ids = append(ids, sh.ID().String()) // Continue if it's a root object. diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 10cebfb52b..0601a43f2d 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -242,3 +242,58 @@ func benchmarkInhumeMultipart(b *testing.B, numShards, numObjects int) { b.StopTimer() } } + +func TestInhumeIfObjectDoesntExist(t *testing.T) { + t.Run("object is locked", func(t *testing.T) { + t.Run("inhume without tombstone", func(t *testing.T) { + testInhumeLockedIfObjectDoesntExist(t, false, false) + }) + t.Run("inhume with tombstone", func(t *testing.T) { + testInhumeLockedIfObjectDoesntExist(t, true, false) + }) + t.Run("force inhume without tombstone", func(t *testing.T) { + testInhumeLockedIfObjectDoesntExist(t, false, true) + }) + t.Run("force inhume with tombstone", func(t *testing.T) { + testInhumeLockedIfObjectDoesntExist(t, true, true) + }) + }) +} + +func testInhumeLockedIfObjectDoesntExist(t *testing.T, withTombstone, withForce bool) { + t.Parallel() + + var ( + errLocked *apistatus.ObjectLocked + inhumePrm InhumePrm + ctx = context.Background() + container = cidtest.ID() + object = oidtest.Address() + lock = oidtest.ID() + tombstone = oidtest.Address() + ) + object.SetContainer(container) + tombstone.SetContainer(container) + + engine := testNewEngine(t).setShardsNum(t, 4).prepare(t).engine + defer func() { require.NoError(t, engine.Close(ctx)) }() + + err := engine.Lock(ctx, container, lock, []oid.ID{object.Object()}) + require.NoError(t, err) + + if withTombstone { + inhumePrm.WithTarget(tombstone, object) + } else { + inhumePrm.MarkAsGarbage(object) + } + if withForce { + inhumePrm.WithForceRemoval() + } + + err = engine.Inhume(ctx, inhumePrm) + if withForce { + require.NoError(t, err) + } else { + require.ErrorAs(t, err, &errLocked) + } +} From 100eb8b654b55286caa5bf4aa18c358eab12fd26 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Wed, 29 Jan 2025 15:39:28 +0300 Subject: [PATCH 1384/1413] [#1619] logger: Set tags for `node` components Change-Id: I55ffcce9d2a74fdd47621674739b07f2e20199e3 Signed-off-by: Anton Nikiforov --- .../maintenance/zombie/storage_engine.go | 3 ++- cmd/frostfs-node/config.go | 13 ++++----- cmd/frostfs-node/config/logger/config_test.go | 3 +++ cmd/frostfs-node/morph.go | 14 +++++----- cmd/frostfs-node/object.go | 14 +++++----- cmd/frostfs-node/session.go | 3 ++- cmd/frostfs-node/tree.go | 3 ++- config/example/node.env | 2 ++ config/example/node.json | 8 +++++- config/example/node.yaml | 3 +++ docs/storage-node-configuration.md | 16 ++++++++--- .../blobovnicza/blobovnicza.go | 2 +- .../blobovniczatree/concurrency_test.go | 3 ++- .../blobstor/blobovniczatree/exists_test.go | 3 ++- .../blobstor/blobovniczatree/generic_test.go | 6 +++-- .../blobstor/blobovniczatree/option.go | 11 +++++--- .../blobovniczatree/rebuild_failover_test.go | 3 ++- .../blobstor/blobovniczatree/rebuild_test.go | 27 ++++++++++++------- pkg/local_object_storage/blobstor/blobstor.go | 2 +- .../blobstor/fstree/option.go | 3 +-- .../engine/engine_test.go | 3 ++- .../shard/gc_internal_test.go | 3 ++- pkg/local_object_storage/shard/lock_test.go | 3 ++- pkg/local_object_storage/shard/range_test.go | 3 ++- pkg/local_object_storage/shard/shard.go | 2 +- pkg/local_object_storage/shard/shard_test.go | 3 ++- .../writecache/options.go | 3 +-- pkg/services/object/delete/service.go | 2 +- pkg/services/object/get/service.go | 2 +- pkg/services/object/get/v2/service.go | 2 +- pkg/services/object/search/service.go | 2 +- pkg/services/policer/policer.go | 3 --- pkg/services/replicator/replicator.go | 3 --- pkg/services/session/executor.go | 5 +--- pkg/util/logger/logger.go | 1 + pkg/util/logger/tag_string.go | 19 +++++++++++-- pkg/util/logger/tags.go | 27 ++++++++++++++----- 37 files changed, 151 insertions(+), 77 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go b/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go index c54b331f33..5be34d502c 100644 --- a/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go +++ b/cmd/frostfs-adm/internal/modules/maintenance/zombie/storage_engine.go @@ -159,7 +159,8 @@ func getSubStorages(ctx context.Context, sh *shardconfig.Config) []blobstor.SubS blobovniczatree.WithOpenedCacheExpInterval(sub.OpenedCacheExpInterval()), blobovniczatree.WithInitWorkerCount(sub.InitWorkerCount()), blobovniczatree.WithWaitBeforeDropDB(sub.RebuildDropTimeout()), - blobovniczatree.WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + blobovniczatree.WithBlobovniczaLogger(logger.NewLoggerWrapper(zap.NewNop())), + blobovniczatree.WithBlobovniczaTreeLogger(logger.NewLoggerWrapper(zap.NewNop())), blobovniczatree.WithObjectSizeLimit(sh.SmallSizeLimit()), } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index f80401b5ba..fae1ca1ca7 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -891,7 +891,7 @@ func (c *cfg) engineOpts() []engine.Option { opts = append(opts, engine.WithErrorThreshold(c.EngineCfg.errorThreshold), - engine.WithLogger(c.log), + engine.WithLogger(c.log.WithTag(logger.TagEngine)), engine.WithLowMemoryConsumption(c.EngineCfg.lowMem), ) @@ -928,7 +928,7 @@ func (c *cfg) getWriteCacheOpts(shCfg shardCfg) []writecache.Option { writecache.WithMaxCacheSize(wcRead.sizeLimit), writecache.WithMaxCacheCount(wcRead.countLimit), writecache.WithNoSync(wcRead.noSync), - writecache.WithLogger(c.log), + writecache.WithLogger(c.log.WithTag(logger.TagWriteCache)), writecache.WithQoSLimiter(shCfg.limiter), ) } @@ -968,7 +968,8 @@ func (c *cfg) getSubstorageOpts(ctx context.Context, shCfg shardCfg) []blobstor. blobovniczatree.WithOpenedCacheExpInterval(sRead.openedCacheExpInterval), blobovniczatree.WithInitWorkerCount(sRead.initWorkerCount), blobovniczatree.WithWaitBeforeDropDB(sRead.rebuildDropTimeout), - blobovniczatree.WithLogger(c.log), + blobovniczatree.WithBlobovniczaLogger(c.log.WithTag(logger.TagBlobovnicza)), + blobovniczatree.WithBlobovniczaTreeLogger(c.log.WithTag(logger.TagBlobovniczaTree)), blobovniczatree.WithObjectSizeLimit(shCfg.smallSizeObjectLimit), } @@ -991,7 +992,7 @@ func (c *cfg) getSubstorageOpts(ctx context.Context, shCfg shardCfg) []blobstor. fstree.WithPerm(sRead.perm), fstree.WithDepth(sRead.depth), fstree.WithNoSync(sRead.noSync), - fstree.WithLogger(c.log), + fstree.WithLogger(c.log.WithTag(logger.TagFSTree)), } if c.metricsCollector != nil { fstreeOpts = append(fstreeOpts, @@ -1023,7 +1024,7 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID blobstoreOpts := []blobstor.Option{ blobstor.WithCompression(shCfg.compression), blobstor.WithStorages(ss), - blobstor.WithLogger(c.log), + blobstor.WithLogger(c.log.WithTag(logger.TagBlobstor)), } if c.metricsCollector != nil { blobstoreOpts = append(blobstoreOpts, blobstor.WithMetrics(lsmetrics.NewBlobstoreMetrics(c.metricsCollector.Blobstore()))) @@ -1048,7 +1049,7 @@ func (c *cfg) getShardOpts(ctx context.Context, shCfg shardCfg) shardOptsWithID var sh shardOptsWithID sh.configID = shCfg.id() sh.shOpts = []shard.Option{ - shard.WithLogger(c.log), + shard.WithLogger(c.log.WithTag(logger.TagShard)), shard.WithRefillMetabase(shCfg.refillMetabase), shard.WithRefillMetabaseWorkersCount(shCfg.refillMetabaseWorkersCount), shard.WithMode(shCfg.mode), diff --git a/cmd/frostfs-node/config/logger/config_test.go b/cmd/frostfs-node/config/logger/config_test.go index ffe8ac6932..796ad529ee 100644 --- a/cmd/frostfs-node/config/logger/config_test.go +++ b/cmd/frostfs-node/config/logger/config_test.go @@ -22,6 +22,9 @@ func TestLoggerSection_Level(t *testing.T) { require.Equal(t, "debug", loggerconfig.Level(c)) require.Equal(t, "journald", loggerconfig.Destination(c)) require.Equal(t, true, loggerconfig.Timestamp(c)) + tags := loggerconfig.Tags(c) + require.Equal(t, "main, morph", tags[0][0]) + require.Equal(t, "debug", tags[0][1]) } configtest.ForEachFileType(path, fileConfigTest) diff --git a/cmd/frostfs-node/morph.go b/cmd/frostfs-node/morph.go index d3c0f7b81c..917cf6fc02 100644 --- a/cmd/frostfs-node/morph.go +++ b/cmd/frostfs-node/morph.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" netmapEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/subscriber" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/rand" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/state" @@ -84,7 +85,7 @@ func initMorphClient(ctx context.Context, c *cfg) { cli, err := client.New(ctx, c.key, client.WithDialTimeout(morphconfig.DialTimeout(c.appCfg)), - client.WithLogger(c.log), + client.WithLogger(c.log.WithTag(logger.TagMorph)), client.WithMetrics(c.metricsCollector.MorphClientMetrics()), client.WithEndpoints(addresses...), client.WithConnLostCallback(func() { @@ -165,6 +166,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { err error subs subscriber.Subscriber ) + log := c.log.WithTag(logger.TagMorph) fromSideChainBlock, err := c.persistate.UInt32(persistateSideChainLastBlockKey) if err != nil { @@ -173,14 +175,14 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { } subs, err = subscriber.New(ctx, &subscriber.Params{ - Log: c.log, + Log: log, StartFromBlock: fromSideChainBlock, Client: c.cfgMorph.client, }) fatalOnErr(err) lis, err := event.NewListener(event.ListenerParams{ - Logger: c.log, + Logger: log, Subscriber: subs, }) fatalOnErr(err) @@ -198,7 +200,7 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { setNetmapNotificationParser(c, newEpochNotification, func(src *state.ContainedNotificationEvent) (event.Event, error) { res, err := netmapEvent.ParseNewEpoch(src) if err == nil { - c.log.Info(ctx, logs.FrostFSNodeNewEpochEventFromSidechain, + log.Info(ctx, logs.FrostFSNodeNewEpochEventFromSidechain, zap.Uint64("number", res.(netmapEvent.NewEpoch).EpochNumber()), ) } @@ -209,11 +211,11 @@ func listenMorphNotifications(ctx context.Context, c *cfg) { registerNotificationHandlers(c.cfgContainer.scriptHash, lis, c.cfgContainer.parsers, c.cfgContainer.subscribers) registerBlockHandler(lis, func(ctx context.Context, block *block.Block) { - c.log.Debug(ctx, logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index)) + log.Debug(ctx, logs.FrostFSNodeNewBlock, zap.Uint32("index", block.Index)) err = c.persistate.SetUInt32(persistateSideChainLastBlockKey, block.Index) if err != nil { - c.log.Warn(ctx, logs.FrostFSNodeCantUpdatePersistentState, + log.Warn(ctx, logs.FrostFSNodeCantUpdatePersistentState, zap.String("chain", "side"), zap.Uint32("block_index", block.Index)) } diff --git a/cmd/frostfs-node/object.go b/cmd/frostfs-node/object.go index 527746d260..c33c02b3f5 100644 --- a/cmd/frostfs-node/object.go +++ b/cmd/frostfs-node/object.go @@ -31,6 +31,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/policer" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object/grpc" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" @@ -217,9 +218,8 @@ func addPolicer(c *cfg, keyStorage *util.KeyStorage, clientConstructor *cache.Cl } remoteReader := objectService.NewRemoteReader(keyStorage, clientConstructor) - pol := policer.New( - policer.WithLogger(c.log), + policer.WithLogger(c.log.WithTag(logger.TagPolicer)), policer.WithKeySpaceIterator(&keySpaceIterator{ng: ls}), policer.WithBuryFunc(buryFn), policer.WithContainerSource(c.cfgObject.cnrSource), @@ -291,7 +291,7 @@ func createReplicator(c *cfg, keyStorage *util.KeyStorage, cache *cache.ClientCa ls := c.cfgObject.cfgLocalStorage.localStorage return replicator.New( - replicator.WithLogger(c.log), + replicator.WithLogger(c.log.WithTag(logger.TagReplicator)), replicator.WithPutTimeout( replicatorconfig.PutTimeout(c.appCfg), ), @@ -348,7 +348,7 @@ func createSearchSvc(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.Trav c.netMapSource, keyStorage, containerSource, - searchsvc.WithLogger(c.log), + searchsvc.WithLogger(c.log.WithTag(logger.TagSearchSvc)), ) } @@ -374,7 +374,7 @@ func createGetService(c *cfg, keyStorage *util.KeyStorage, traverseGen *util.Tra ), coreConstructor, containerSource, - getsvc.WithLogger(c.log)) + getsvc.WithLogger(c.log.WithTag(logger.TagGetSvc))) } func createGetServiceV2(c *cfg, sGet *getsvc.Service, keyStorage *util.KeyStorage) *getsvcV2.Service { @@ -385,7 +385,7 @@ func createGetServiceV2(c *cfg, sGet *getsvc.Service, keyStorage *util.KeyStorag c.netMapSource, c, c.cfgObject.cnrSource, - getsvcV2.WithLogger(c.log), + getsvcV2.WithLogger(c.log.WithTag(logger.TagGetSvc)), ) } @@ -402,7 +402,7 @@ func createDeleteService(c *cfg, keyStorage *util.KeyStorage, sGet *getsvc.Servi cfg: c, }, keyStorage, - deletesvc.WithLogger(c.log), + deletesvc.WithLogger(c.log.WithTag(logger.TagDeleteSvc)), ) } diff --git a/cmd/frostfs-node/session.go b/cmd/frostfs-node/session.go index 2f3c9cbfea..fbfe3f5e65 100644 --- a/cmd/frostfs-node/session.go +++ b/cmd/frostfs-node/session.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/persistent" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/session/storage/temporary" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session" sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session/grpc" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -55,7 +56,7 @@ func initSessionService(c *cfg) { server := sessionTransportGRPC.New( sessionSvc.NewSignService( &c.key.PrivateKey, - sessionSvc.NewExecutionService(c.privateTokenStore, c.respSvc, c.log), + sessionSvc.NewExecutionService(c.privateTokenStore, c.respSvc, c.log.WithTag(logger.TagSessionSvc)), ), ) diff --git a/cmd/frostfs-node/tree.go b/cmd/frostfs-node/tree.go index 67d9c9df02..62af453895 100644 --- a/cmd/frostfs-node/tree.go +++ b/cmd/frostfs-node/tree.go @@ -14,6 +14,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event" containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/tree" + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "go.uber.org/zap" "google.golang.org/grpc" @@ -56,7 +57,7 @@ func initTreeService(c *cfg) { tree.WithFrostfsidSubjectProvider(c.frostfsidClient), tree.WithNetmapSource(c.netMapSource), tree.WithPrivateKey(&c.key.PrivateKey), - tree.WithLogger(c.log), + tree.WithLogger(c.log.WithTag(logger.TagTreeSvc)), tree.WithStorage(c.cfgObject.cfgLocalStorage.localStorage), tree.WithContainerCacheSize(treeConfig.CacheSize()), tree.WithReplicationTimeout(treeConfig.ReplicationTimeout()), diff --git a/config/example/node.env b/config/example/node.env index 9d054fe78f..e7d7a6cc86 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -1,6 +1,8 @@ FROSTFS_LOGGER_LEVEL=debug FROSTFS_LOGGER_DESTINATION=journald FROSTFS_LOGGER_TIMESTAMP=true +FROSTFS_LOGGER_TAGS_0_NAMES="main, morph" +FROSTFS_LOGGER_TAGS_0_LEVEL="debug" FROSTFS_PPROF_ENABLED=true FROSTFS_PPROF_ADDRESS=localhost:6060 diff --git a/config/example/node.json b/config/example/node.json index 110e99ee88..3f7854d98d 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -2,7 +2,13 @@ "logger": { "level": "debug", "destination": "journald", - "timestamp": true + "timestamp": true, + "tags": [ + { + "names": "main, morph", + "level": "debug" + } + ] }, "pprof": { "enabled": true, diff --git a/config/example/node.yaml b/config/example/node.yaml index de5eaa1331..32f0cba675 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -2,6 +2,9 @@ logger: level: debug # logger level: one of "debug", "info" (default), "warn", "error", "dpanic", "panic", "fatal" destination: journald # logger destination: one of "stdout" (default), "journald" timestamp: true + tags: + - names: "main, morph" + level: debug systemdnotify: enabled: true diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 1494d2fca2..3e770457ba 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -112,11 +112,21 @@ Contains logger parameters. ```yaml logger: level: info + tags: + - names: "main, morph" + level: debug ``` -| Parameter | Type | Default value | Description | -|-----------|----------|---------------|---------------------------------------------------------------------------------------------------| -| `level` | `string` | `info` | Logging level.
Possible values: `debug`, `info`, `warn`, `error`, `dpanic`, `panic`, `fatal` | +| Parameter | Type | Default value | Description | +|-----------|-----------------------------------------------|---------------|---------------------------------------------------------------------------------------------------| +| `level` | `string` | `info` | Logging level.
Possible values: `debug`, `info`, `warn`, `error`, `dpanic`, `panic`, `fatal` | +| `tags` | list of [tags descriptions](#tags-subsection) | | Array of tags description. | + +## `tags` subsection +| Parameter | Type | Default value | Description | +|-----------|----------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `names` | `string` | | List of components divided by `,`.
Possible values: `main`, `morph`, `grpcsvc`, `ir`, `processor`, `engine`, `blobovnicza`, `blobstor`, `fstree`, `gc`, `shard`, `writecache`, `deletesvc`, `getsvc`, `searchsvc`, `sessionsvc`, `treesvc`, `policer`, `replicator`. | +| `level` | `string` | | Logging level for the components from `names`, overrides default logging level. | # `contracts` section Contains override values for FrostFS side-chain contract hashes. Most of the time contract diff --git a/pkg/local_object_storage/blobovnicza/blobovnicza.go b/pkg/local_object_storage/blobovnicza/blobovnicza.go index 08ef8b86cd..a6c40f9fa7 100644 --- a/pkg/local_object_storage/blobovnicza/blobovnicza.go +++ b/pkg/local_object_storage/blobovnicza/blobovnicza.go @@ -110,7 +110,7 @@ func WithFullSizeLimit(lim uint64) Option { // WithLogger returns an option to specify Blobovnicza's logger. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = l.With(zap.String("component", "Blobovnicza")) + c.log = l } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go index ec9743b57b..f87f4a1449 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/concurrency_test.go @@ -19,7 +19,8 @@ func TestBlobovniczaTree_Concurrency(t *testing.T) { st := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(1024), WithBlobovniczaShallowWidth(10), WithBlobovniczaShallowDepth(1), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go index 5414140f05..df2b4ffe53 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/exists_test.go @@ -19,7 +19,8 @@ func TestExistsInvalidStorageID(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(1024), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go index d390ecf1d1..9244d765cc 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/generic_test.go @@ -15,7 +15,8 @@ func TestGeneric(t *testing.T) { helper := func(t *testing.T, dir string) common.Storage { return NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), @@ -43,7 +44,8 @@ func TestControl(t *testing.T) { newTree := func(t *testing.T) common.Storage { return NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(maxObjectSize), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/option.go b/pkg/local_object_storage/blobstor/blobovniczatree/option.go index 2f6d31b4ea..5f268b0f28 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/option.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/option.go @@ -63,10 +63,15 @@ func initConfig(c *cfg) { } } -func WithLogger(l *logger.Logger) Option { +func WithBlobovniczaTreeLogger(log *logger.Logger) Option { return func(c *cfg) { - c.log = l - c.blzOpts = append(c.blzOpts, blobovnicza.WithLogger(l)) + c.log = log + } +} + +func WithBlobovniczaLogger(log *logger.Logger) Option { + return func(c *cfg) { + c.blzOpts = append(c.blzOpts, blobovnicza.WithLogger(log)) } } diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go index 8832603c44..4146ef2606 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_failover_test.go @@ -140,7 +140,8 @@ func testRebuildFailoverObjectDeletedFromSource(t *testing.T) { func testRebuildFailoverValidate(t *testing.T, dir string, obj *objectSDK.Object, mustUpdateStorageID bool) { b := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(2), WithBlobovniczaShallowDepth(2), diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go index 9c971bfb62..a7a99fec36 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild_test.go @@ -50,7 +50,8 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(64*1024), WithBlobovniczaShallowWidth(1), // single directory WithBlobovniczaShallowDepth(1), @@ -106,7 +107,8 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(64*1024), WithBlobovniczaShallowWidth(1), // single directory WithBlobovniczaShallowDepth(1), @@ -160,7 +162,8 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(64*1024), WithBlobovniczaShallowWidth(1), // single directory WithBlobovniczaShallowDepth(1), @@ -231,7 +234,8 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(64*1024), WithBlobovniczaShallowWidth(1), // single directory WithBlobovniczaShallowDepth(1), @@ -262,7 +266,8 @@ func TestBlobovniczaTreeFillPercentRebuild(t *testing.T) { require.NoError(t, b.Close(context.Background())) b = NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(64*1024), WithBlobovniczaShallowWidth(1), WithBlobovniczaShallowDepth(1), @@ -304,7 +309,8 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { dir := t.TempDir() b := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(64*1024), // 64KB object size limit WithBlobovniczaShallowWidth(5), WithBlobovniczaShallowDepth(2), // depth = 2 @@ -332,7 +338,8 @@ func TestBlobovniczaTreeRebuildLargeObject(t *testing.T) { b = NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(32*1024), // 32KB object size limit WithBlobovniczaShallowWidth(5), WithBlobovniczaShallowDepth(3), // depth = 3 @@ -374,7 +381,8 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta dir := t.TempDir() b := NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(sourceWidth), WithBlobovniczaShallowDepth(sourceDepth), @@ -415,7 +423,8 @@ func testBlobovniczaTreeRebuildHelper(t *testing.T, sourceDepth, sourceWidth, ta b = NewBlobovniczaTree( context.Background(), - WithLogger(test.NewLogger(t)), + WithBlobovniczaLogger(test.NewLogger(t)), + WithBlobovniczaTreeLogger(test.NewLogger(t)), WithObjectSizeLimit(2048), WithBlobovniczaShallowWidth(targetWidth), WithBlobovniczaShallowDepth(targetDepth), diff --git a/pkg/local_object_storage/blobstor/blobstor.go b/pkg/local_object_storage/blobstor/blobstor.go index edb2c19461..ceaf2538a4 100644 --- a/pkg/local_object_storage/blobstor/blobstor.go +++ b/pkg/local_object_storage/blobstor/blobstor.go @@ -91,7 +91,7 @@ func WithStorages(st []SubStorage) Option { // WithLogger returns option to specify BlobStor's logger. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = l.With(zap.String("component", "BlobStor")) + c.log = l } } diff --git a/pkg/local_object_storage/blobstor/fstree/option.go b/pkg/local_object_storage/blobstor/fstree/option.go index 7155ddcbb6..6f2ac87e1d 100644 --- a/pkg/local_object_storage/blobstor/fstree/option.go +++ b/pkg/local_object_storage/blobstor/fstree/option.go @@ -4,7 +4,6 @@ import ( "io/fs" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" ) type Option func(*FSTree) @@ -53,6 +52,6 @@ func WithFileCounter(c FileCounter) Option { func WithLogger(l *logger.Logger) Option { return func(f *FSTree) { - f.log = l.With(zap.String("component", "FSTree")) + f.log = l } } diff --git a/pkg/local_object_storage/engine/engine_test.go b/pkg/local_object_storage/engine/engine_test.go index 711a76100d..fc6d9ee9c7 100644 --- a/pkg/local_object_storage/engine/engine_test.go +++ b/pkg/local_object_storage/engine/engine_test.go @@ -116,7 +116,8 @@ func newStorages(t testing.TB, root string, smallSize uint64) []blobstor.SubStor blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1), blobovniczatree.WithPermissions(0o700), - blobovniczatree.WithLogger(test.NewLogger(t))), + blobovniczatree.WithBlobovniczaLogger(test.NewLogger(t)), + blobovniczatree.WithBlobovniczaTreeLogger(test.NewLogger(t))), Policy: func(_ *objectSDK.Object, data []byte) bool { return uint64(len(data)) < smallSize }, diff --git a/pkg/local_object_storage/shard/gc_internal_test.go b/pkg/local_object_storage/shard/gc_internal_test.go index 9998bbae2d..54d2f1510d 100644 --- a/pkg/local_object_storage/shard/gc_internal_test.go +++ b/pkg/local_object_storage/shard/gc_internal_test.go @@ -37,7 +37,8 @@ func Test_ObjectNotFoundIfNotDeletedFromMetabase(t *testing.T) { { Storage: blobovniczatree.NewBlobovniczaTree( context.Background(), - blobovniczatree.WithLogger(test.NewLogger(t)), + blobovniczatree.WithBlobovniczaLogger(test.NewLogger(t)), + blobovniczatree.WithBlobovniczaTreeLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/shard/lock_test.go b/pkg/local_object_storage/shard/lock_test.go index 5caf3641ff..3878a65cd6 100644 --- a/pkg/local_object_storage/shard/lock_test.go +++ b/pkg/local_object_storage/shard/lock_test.go @@ -28,9 +28,10 @@ func TestShard_Lock(t *testing.T) { var sh *Shard rootPath := t.TempDir() + l := logger.NewLoggerWrapper(zap.NewNop()) opts := []Option{ WithID(NewIDFromBytes([]byte{})), - WithLogger(logger.NewLoggerWrapper(zap.NewNop())), + WithLogger(l), WithBlobStorOptions( blobstor.WithStorages([]blobstor.SubStorage{ { diff --git a/pkg/local_object_storage/shard/range_test.go b/pkg/local_object_storage/shard/range_test.go index 146e834cc1..06fe9f5110 100644 --- a/pkg/local_object_storage/shard/range_test.go +++ b/pkg/local_object_storage/shard/range_test.go @@ -79,7 +79,8 @@ func testShardGetRange(t *testing.T, hasWriteCache bool) { { Storage: blobovniczatree.NewBlobovniczaTree( context.Background(), - blobovniczatree.WithLogger(test.NewLogger(t)), + blobovniczatree.WithBlobovniczaLogger(test.NewLogger(t)), + blobovniczatree.WithBlobovniczaTreeLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(t.TempDir(), "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/shard/shard.go b/pkg/local_object_storage/shard/shard.go index 304a6bf9df..d89b562662 100644 --- a/pkg/local_object_storage/shard/shard.go +++ b/pkg/local_object_storage/shard/shard.go @@ -205,7 +205,7 @@ func WithPiloramaOptions(opts ...pilorama.Option) Option { func WithLogger(l *logger.Logger) Option { return func(c *cfg) { c.log = l - c.gcCfg.log = l + c.gcCfg.log = l.WithTag(logger.TagGC) } } diff --git a/pkg/local_object_storage/shard/shard_test.go b/pkg/local_object_storage/shard/shard_test.go index f9ee34488b..84be71c4db 100644 --- a/pkg/local_object_storage/shard/shard_test.go +++ b/pkg/local_object_storage/shard/shard_test.go @@ -60,7 +60,8 @@ func newCustomShard(t testing.TB, enableWriteCache bool, o shardOptions) *Shard { Storage: blobovniczatree.NewBlobovniczaTree( context.Background(), - blobovniczatree.WithLogger(test.NewLogger(t)), + blobovniczatree.WithBlobovniczaLogger(test.NewLogger(t)), + blobovniczatree.WithBlobovniczaTreeLogger(test.NewLogger(t)), blobovniczatree.WithRootPath(filepath.Join(o.rootPath, "blob", "blobovnicza")), blobovniczatree.WithBlobovniczaShallowDepth(1), blobovniczatree.WithBlobovniczaShallowWidth(1)), diff --git a/pkg/local_object_storage/writecache/options.go b/pkg/local_object_storage/writecache/options.go index dbbe66c19e..a4f98ad064 100644 --- a/pkg/local_object_storage/writecache/options.go +++ b/pkg/local_object_storage/writecache/options.go @@ -5,7 +5,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" ) // Option represents write-cache configuration option. @@ -46,7 +45,7 @@ type options struct { // WithLogger sets logger. func WithLogger(log *logger.Logger) Option { return func(o *options) { - o.log = log.With(zap.String("component", "WriteCache")) + o.log = log } } diff --git a/pkg/services/object/delete/service.go b/pkg/services/object/delete/service.go index 867d3f4ef3..1c4d7d5853 100644 --- a/pkg/services/object/delete/service.go +++ b/pkg/services/object/delete/service.go @@ -92,6 +92,6 @@ func New(gs *getsvc.Service, // WithLogger returns option to specify Delete service's logger. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = l.With(zap.String("component", "objectSDK.Delete service")) + c.log = l } } diff --git a/pkg/services/object/get/service.go b/pkg/services/object/get/service.go index 9ec10b5f27..a103f5a7fa 100644 --- a/pkg/services/object/get/service.go +++ b/pkg/services/object/get/service.go @@ -53,6 +53,6 @@ func New( // WithLogger returns option to specify Get service's logger. func WithLogger(l *logger.Logger) Option { return func(s *Service) { - s.log = l.With(zap.String("component", "Object.Get service")) + s.log = l } } diff --git a/pkg/services/object/get/v2/service.go b/pkg/services/object/get/v2/service.go index fc483b74b9..0ec8912fd5 100644 --- a/pkg/services/object/get/v2/service.go +++ b/pkg/services/object/get/v2/service.go @@ -145,6 +145,6 @@ func (s *Service) Head(ctx context.Context, req *objectV2.HeadRequest) (*objectV func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = l.With(zap.String("component", "Object.Get V2 service")) + c.log = l } } diff --git a/pkg/services/object/search/service.go b/pkg/services/object/search/service.go index e1aeca9576..56fe56468f 100644 --- a/pkg/services/object/search/service.go +++ b/pkg/services/object/search/service.go @@ -94,6 +94,6 @@ func New(e *engine.StorageEngine, // WithLogger returns option to specify Get service's logger. func WithLogger(l *logger.Logger) Option { return func(c *cfg) { - c.log = l.With(zap.String("component", "Object.Search service")) + c.log = l } } diff --git a/pkg/services/policer/policer.go b/pkg/services/policer/policer.go index d18b71a238..c91e7cc7c1 100644 --- a/pkg/services/policer/policer.go +++ b/pkg/services/policer/policer.go @@ -8,7 +8,6 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/internal/assert" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" lru "github.com/hashicorp/golang-lru/v2" - "go.uber.org/zap" ) type objectsInWork struct { @@ -56,8 +55,6 @@ func New(opts ...Option) *Policer { opts[i](c) } - c.log = c.log.With(zap.String("component", "Object Policer")) - cache, err := lru.New[oid.Address, time.Time](int(c.cacheSize)) assert.NoError(err, fmt.Sprintf("could not create LRU cache with %d size", c.cacheSize)) diff --git a/pkg/services/replicator/replicator.go b/pkg/services/replicator/replicator.go index 6910fa5af5..a940cef377 100644 --- a/pkg/services/replicator/replicator.go +++ b/pkg/services/replicator/replicator.go @@ -7,7 +7,6 @@ import ( objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer" getsvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/get" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" - "go.uber.org/zap" ) // Replicator represents the utility that replicates @@ -45,8 +44,6 @@ func New(opts ...Option) *Replicator { opts[i](c) } - c.log = c.log.With(zap.String("component", "Object Replicator")) - return &Replicator{ cfg: c, } diff --git a/pkg/services/session/executor.go b/pkg/services/session/executor.go index 12b2216132..f0591de71c 100644 --- a/pkg/services/session/executor.go +++ b/pkg/services/session/executor.go @@ -33,10 +33,7 @@ func NewExecutionService(exec ServiceExecutor, respSvc *response.Service, l *log } func (s *executorSvc) Create(ctx context.Context, req *session.CreateRequest) (*session.CreateResponse, error) { - s.log.Debug(ctx, logs.ServingRequest, - zap.String("component", "SessionService"), - zap.String("request", "Create"), - ) + s.log.Debug(ctx, logs.ServingRequest, zap.String("request", "Create")) respBody, err := s.exec.Create(ctx, req.GetBody()) if err != nil { diff --git a/pkg/util/logger/logger.go b/pkg/util/logger/logger.go index 276847be13..a1998cb1a5 100644 --- a/pkg/util/logger/logger.go +++ b/pkg/util/logger/logger.go @@ -238,5 +238,6 @@ func NewLoggerWrapper(z *zap.Logger) *Logger { return &Logger{ z: z.WithOptions(zap.AddCallerSkip(1)), t: TagMain, + c: z.Core(), } } diff --git a/pkg/util/logger/tag_string.go b/pkg/util/logger/tag_string.go index a25b3c4454..1b98f2e62c 100644 --- a/pkg/util/logger/tag_string.go +++ b/pkg/util/logger/tag_string.go @@ -13,11 +13,26 @@ func _() { _ = x[TagGrpcSvc-3] _ = x[TagIr-4] _ = x[TagProcessor-5] + _ = x[TagEngine-6] + _ = x[TagBlobovnicza-7] + _ = x[TagBlobovniczaTree-8] + _ = x[TagBlobstor-9] + _ = x[TagFSTree-10] + _ = x[TagGC-11] + _ = x[TagShard-12] + _ = x[TagWriteCache-13] + _ = x[TagDeleteSvc-14] + _ = x[TagGetSvc-15] + _ = x[TagSearchSvc-16] + _ = x[TagSessionSvc-17] + _ = x[TagTreeSvc-18] + _ = x[TagPolicer-19] + _ = x[TagReplicator-20] } -const _Tag_name = "mainmorphgrpc_svcirprocessor" +const _Tag_name = "mainmorphgrpcsvcirprocessorengineblobovniczablobovniczatreeblobstorfstreegcshardwritecachedeletesvcgetsvcsearchsvcsessionsvctreesvcpolicerreplicator" -var _Tag_index = [...]uint8{0, 4, 9, 17, 19, 28} +var _Tag_index = [...]uint8{0, 4, 9, 16, 18, 27, 33, 44, 59, 67, 73, 75, 80, 90, 99, 105, 114, 124, 131, 138, 148} func (i Tag) String() string { i -= 1 diff --git a/pkg/util/logger/tags.go b/pkg/util/logger/tags.go index 51a6f62da4..a5386707e1 100644 --- a/pkg/util/logger/tags.go +++ b/pkg/util/logger/tags.go @@ -13,12 +13,27 @@ import ( type Tag uint8 const ( - _ Tag = iota // - TagMain // main - TagMorph // morph - TagGrpcSvc // grpc_svc - TagIr // ir - TagProcessor // processor + _ Tag = iota // + TagMain // main + TagMorph // morph + TagGrpcSvc // grpcsvc + TagIr // ir + TagProcessor // processor + TagEngine // engine + TagBlobovnicza // blobovnicza + TagBlobovniczaTree // blobovniczatree + TagBlobstor // blobstor + TagFSTree // fstree + TagGC // gc + TagShard // shard + TagWriteCache // writecache + TagDeleteSvc // deletesvc + TagGetSvc // getsvc + TagSearchSvc // searchsvc + TagSessionSvc // sessionsvc + TagTreeSvc // treesvc + TagPolicer // policer + TagReplicator // replicator defaultLevel = zapcore.InfoLevel ) From 86264e4e20af3eb9f90ae65487a5b5e91eb8a28d Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 4 Feb 2025 09:11:36 +0300 Subject: [PATCH 1385/1413] [#1619] logger: Add benchmark Change-Id: I49e90e8a3689a755755afd0638b327a6b1884795 Signed-off-by: Anton Nikiforov --- pkg/util/logger/logger_test.go | 118 +++++++++++++++++++++++++++++ pkg/util/logger/logger_test.result | 46 +++++++++++ 2 files changed, 164 insertions(+) create mode 100644 pkg/util/logger/logger_test.go create mode 100644 pkg/util/logger/logger_test.result diff --git a/pkg/util/logger/logger_test.go b/pkg/util/logger/logger_test.go new file mode 100644 index 0000000000..b867ee6cc2 --- /dev/null +++ b/pkg/util/logger/logger_test.go @@ -0,0 +1,118 @@ +package logger + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest/observer" +) + +func BenchmarkLogger(b *testing.B) { + ctx := context.Background() + m := map[string]Prm{} + + prm := Prm{} + require.NoError(b, prm.SetLevelString("debug")) + m["logging enabled"] = prm + + prm = Prm{} + require.NoError(b, prm.SetLevelString("error")) + m["logging disabled"] = prm + + prm = Prm{} + require.NoError(b, prm.SetLevelString("error")) + require.NoError(b, prm.SetTags([][]string{{"main", "debug"}, {"morph", "debug"}})) + m["logging enabled via tags"] = prm + + prm = Prm{} + require.NoError(b, prm.SetLevelString("debug")) + require.NoError(b, prm.SetTags([][]string{{"main", "error"}, {"morph", "debug"}})) + m["logging disabled via tags"] = prm + + for k, v := range m { + b.Run(k, func(b *testing.B) { + logger, err := createLogger(v) + require.NoError(b, err) + UpdateLevelForTags(v) + b.ResetTimer() + b.ReportAllocs() + for range b.N { + logger.Info(ctx, "test info") + } + }) + } +} + +type testCore struct { + core zapcore.Core +} + +func (c *testCore) Enabled(lvl zapcore.Level) bool { + return c.core.Enabled(lvl) +} + +func (c *testCore) With(fields []zapcore.Field) zapcore.Core { + c.core = c.core.With(fields) + return c +} + +func (c *testCore) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry { + return ce.AddCore(e, c) +} + +func (c *testCore) Write(zapcore.Entry, []zapcore.Field) error { + return nil +} + +func (c *testCore) Sync() error { + return c.core.Sync() +} + +func createLogger(prm Prm) (*Logger, error) { + prm.Options = []zap.Option{zap.WrapCore(func(core zapcore.Core) zapcore.Core { + tc := testCore{core: core} + return &tc + })} + return NewLogger(prm) +} + +func TestLoggerOutput(t *testing.T) { + obs, logs := observer.New(zap.NewAtomicLevelAt(zap.DebugLevel)) + + prm := Prm{} + require.NoError(t, prm.SetLevelString("debug")) + prm.Options = []zap.Option{zap.WrapCore(func(zapcore.Core) zapcore.Core { + return obs + })} + loggerMain, err := NewLogger(prm) + require.NoError(t, err) + UpdateLevelForTags(prm) + + loggerMainWith := loggerMain.With(zap.String("key", "value")) + + require.Panics(t, func() { + loggerMainWith.WithTag(TagShard) + }) + loggerShard := loggerMain.WithTag(TagShard) + loggerShard = loggerShard.With(zap.String("key1", "value1")) + + loggerMorph := loggerMain.WithTag(TagMorph) + loggerMorph = loggerMorph.With(zap.String("key2", "value2")) + + ctx := context.Background() + loggerMain.Debug(ctx, "main") + loggerMainWith.Debug(ctx, "main with") + loggerShard.Debug(ctx, "shard") + loggerMorph.Debug(ctx, "morph") + + require.Len(t, logs.All(), 4) + require.Len(t, logs.FilterFieldKey("key").All(), 1) + require.Len(t, logs.FilterFieldKey("key1").All(), 1) + require.Len(t, logs.FilterFieldKey("key2").All(), 1) + require.Len(t, logs.FilterField(zap.String("tag", TagMain.String())).All(), 2) + require.Len(t, logs.FilterField(zap.String("tag", TagShard.String())).All(), 1) + require.Len(t, logs.FilterField(zap.String("tag", TagMorph.String())).All(), 1) +} diff --git a/pkg/util/logger/logger_test.result b/pkg/util/logger/logger_test.result new file mode 100644 index 0000000000..612fa29678 --- /dev/null +++ b/pkg/util/logger/logger_test.result @@ -0,0 +1,46 @@ +goos: linux +goarch: amd64 +pkg: git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger +cpu: 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz +BenchmarkLogger/logging_enabled-8 10000 1156 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1124 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1106 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1096 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1071 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1081 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1074 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1134 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1123 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled-8 10000 1144 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_disabled-8 10000 16.15 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 16.54 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 16.22 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 16.22 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 17.01 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 16.31 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 16.61 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 16.17 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 16.26 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled-8 10000 21.02 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1146 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1086 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1113 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1157 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1069 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1073 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1096 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1092 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1060 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_enabled_via_tags-8 10000 1153 ns/op 240 B/op 1 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.23 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.39 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.47 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.62 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.53 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.53 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.74 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.20 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 17.06 ns/op 0 B/op 0 allocs/op +BenchmarkLogger/logging_disabled_via_tags-8 10000 16.60 ns/op 0 B/op 0 allocs/op +PASS +ok git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger 0.260s From cf48069fd8a12df6c0013d60cc0ce0a89420241b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 14:26:20 +0300 Subject: [PATCH 1386/1413] [#1718] linter: Resolve gocritic's appendAssign linter See https://go-critic.com/overview#appendassign for details. Change-Id: I991979ea680af25e2cec9097fa12b1c4eebc6c1d Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/modules/object/util.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index 3955f8ee13..8e4e8b2874 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -262,13 +262,8 @@ func OpenSessionViaClient(cmd *cobra.Command, dst SessionPrm, cli *client.Client if _, ok := dst.(*internal.DeleteObjectPrm); ok { common.PrintVerbose(cmd, "Collecting relatives of the removal object...") - rels := collectObjectRelatives(cmd, cli, cnr, *obj) - - if len(rels) == 0 { - objs = []oid.ID{*obj} - } else { - objs = append(rels, *obj) - } + objs = collectObjectRelatives(cmd, cli, cnr, *obj) + objs = append(objs, *obj) } } From 2075e09cedad3150a91216524c014846edb3cb71 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 14:28:21 +0300 Subject: [PATCH 1387/1413] [#1718] linter: Resolve gocritic's unslice linter See https://go-critic.com/overview#unslice for details. Change-Id: I6d21e8ce1c9bae56099dc203f5080b0e3ea0c1ef Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-adm/internal/modules/morph/config/config.go | 2 +- cmd/frostfs-lens/internal/schema/writecache/parsers.go | 2 +- pkg/local_object_storage/metabase/delete.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/config/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go index f64cb4817b..c17fb62fff 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -63,7 +63,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { netmap.MaxObjectSizeConfig, netmap.WithdrawFeeConfig, netmap.MaxECDataCountConfig, netmap.MaxECParityCountConfig: nbuf := make([]byte, 8) - copy(nbuf[:], v) + copy(nbuf, v) n := binary.LittleEndian.Uint64(nbuf) _, _ = tw.Write(fmt.Appendf(nil, "%s:\t%d (int)\n", k, n)) case netmap.HomomorphicHashingDisabledKey, netmap.MaintenanceModeAllowedConfig: diff --git a/cmd/frostfs-lens/internal/schema/writecache/parsers.go b/cmd/frostfs-lens/internal/schema/writecache/parsers.go index 7d70b27b2a..3bfe2608b6 100644 --- a/cmd/frostfs-lens/internal/schema/writecache/parsers.go +++ b/cmd/frostfs-lens/internal/schema/writecache/parsers.go @@ -57,7 +57,7 @@ func DefaultRecordParser(key, value []byte) (common.SchemaEntry, common.Parser, r.addr.SetContainer(cnr) r.addr.SetObject(obj) - r.data = value[:] + r.data = value return &r, nil, nil } diff --git a/pkg/local_object_storage/metabase/delete.go b/pkg/local_object_storage/metabase/delete.go index cf1d563e9b..9a5a6e5746 100644 --- a/pkg/local_object_storage/metabase/delete.go +++ b/pkg/local_object_storage/metabase/delete.go @@ -363,12 +363,12 @@ func (db *DB) deleteObject( func parentLength(tx *bbolt.Tx, addr oid.Address) int { bucketName := make([]byte, bucketKeySize) - bkt := tx.Bucket(parentBucketName(addr.Container(), bucketName[:])) + bkt := tx.Bucket(parentBucketName(addr.Container(), bucketName)) if bkt == nil { return 0 } - lst, err := decodeList(bkt.Get(objectKey(addr.Object(), bucketName[:]))) + lst, err := decodeList(bkt.Get(objectKey(addr.Object(), bucketName))) if err != nil { return 0 } From d2114759aaaf4e99aa83c1185c0a5d184a83b97a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 14:38:06 +0300 Subject: [PATCH 1388/1413] [#1718] linter: Resolve gocritic's typeSwitchVar linter See https://go-critic.com/overview#typeswitchvar for details Change-Id: Ic29db32c9b080576ab51dd484b4376114e9e775c Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-lens/internal/tui/ui.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-lens/internal/tui/ui.go b/cmd/frostfs-lens/internal/tui/ui.go index bd7540b01c..cc6b7859e7 100644 --- a/cmd/frostfs-lens/internal/tui/ui.go +++ b/cmd/frostfs-lens/internal/tui/ui.go @@ -460,11 +460,11 @@ func (ui *UI) handleInputOnSearching(event *tcell.EventKey) { return } - switch ui.mountedPage.(type) { + switch v := ui.mountedPage.(type) { case *BucketsView: ui.moveNextPage(NewBucketsView(ui, res)) case *RecordsView: - bucket := ui.mountedPage.(*RecordsView).bucket + bucket := v.bucket ui.moveNextPage(NewRecordsView(ui, bucket, res)) } From 8d499f03fee98825d183d18a7ef492a6a019b25a Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 14:40:31 +0300 Subject: [PATCH 1389/1413] [#1718] linter: Resolve gocritic's elseif linter See https://go-critic.com/overview#elseif for details. Change-Id: I8fd3edfacaeea2b0a83917575d545af7e7ab4d13 Signed-off-by: Dmitrii Stepanov --- pkg/services/container/ape.go | 6 ++---- pkg/services/object/common/target/target.go | 6 ++---- pkg/services/object_manager/tombstone/checker.go | 6 ++---- pkg/services/tree/service.go | 6 ++---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index e1fbe3960a..01bd825d73 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -655,10 +655,8 @@ func (ac *apeChecker) namespaceByOwner(ctx context.Context, owner *refs.OwnerID) subject, err := ac.frostFSIDClient.GetSubject(ctx, addr) if err == nil { namespace = subject.Namespace - } else { - if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { - return "", fmt.Errorf("get subject error: %w", err) - } + } else if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { + return "", fmt.Errorf("get subject error: %w", err) } return namespace, nil } diff --git a/pkg/services/object/common/target/target.go b/pkg/services/object/common/target/target.go index b2ae79dbc9..f2bd907dbe 100644 --- a/pkg/services/object/common/target/target.go +++ b/pkg/services/object/common/target/target.go @@ -89,10 +89,8 @@ func newTrustedTarget(ctx context.Context, prm *objectwriter.Params) (transforme if !ownerObj.Equals(ownerSession) { return nil, fmt.Errorf("session token is missing but object owner id (%s) is different from the default key (%s)", ownerObj, ownerSession) } - } else { - if !ownerObj.Equals(sessionInfo.Owner) { - return nil, fmt.Errorf("different token issuer and object owner identifiers %s/%s", sessionInfo.Owner, ownerObj) - } + } else if !ownerObj.Equals(sessionInfo.Owner) { + return nil, fmt.Errorf("different token issuer and object owner identifiers %s/%s", sessionInfo.Owner, ownerObj) } if prm.SignRequestPrivateKey == nil { diff --git a/pkg/services/object_manager/tombstone/checker.go b/pkg/services/object_manager/tombstone/checker.go index a4e36c2dc6..e5f001d5a2 100644 --- a/pkg/services/object_manager/tombstone/checker.go +++ b/pkg/services/object_manager/tombstone/checker.go @@ -61,10 +61,8 @@ func (g *ExpirationChecker) IsTombstoneAvailable(ctx context.Context, a oid.Addr logs.TombstoneCouldNotGetTheTombstoneTheSource, zap.Error(err), ) - } else { - if ts != nil { - return g.handleTS(ctx, addrStr, ts, epoch) - } + } else if ts != nil { + return g.handleTS(ctx, addrStr, ts, epoch) } // requested tombstone not diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index a00c8c1cde..5349dd13eb 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -436,10 +436,8 @@ func getSortedSubTree(ctx context.Context, srv TreeService_GetSubTreeServer, cid } if ms == nil { ms = m.Items - } else { - if len(m.Items) != 1 { - return status.Error(codes.InvalidArgument, "multiple non-internal nodes provided") - } + } else if len(m.Items) != 1 { + return status.Error(codes.InvalidArgument, "multiple non-internal nodes provided") } ts = append(ts, m.Time) ps = append(ps, p) From 64900f87e1872dea2794b02ddbc888f171a24a77 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 14:44:00 +0300 Subject: [PATCH 1390/1413] [#1718] linter: Resolve gocritic's singleCaseSwitch linter See https://go-critic.com/overview#singlecaseswitch for details. Change-Id: Ied7885f83b4116969771de6f91bc5e1e3b2a4f1e Signed-off-by: Dmitrii Stepanov --- .../blobstor/fstree/fstree_write_generic.go | 9 +++------ pkg/services/control/ir/server/server.go | 3 +-- pkg/util/http/server.go | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go index 07a618b0ac..6d633dad66 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree_write_generic.go @@ -67,12 +67,9 @@ func (w *genericWriter) writeAndRename(tmpPath, p string, data []byte) error { err := w.writeFile(tmpPath, data) if err != nil { var pe *fs.PathError - if errors.As(err, &pe) { - switch pe.Err { - case syscall.ENOSPC: - err = common.ErrNoSpace - _ = os.RemoveAll(tmpPath) - } + if errors.As(err, &pe) && errors.Is(pe.Err, syscall.ENOSPC) { + err = common.ErrNoSpace + _ = os.RemoveAll(tmpPath) } return err } diff --git a/pkg/services/control/ir/server/server.go b/pkg/services/control/ir/server/server.go index c2a4f88a69..0cfca71c15 100644 --- a/pkg/services/control/ir/server/server.go +++ b/pkg/services/control/ir/server/server.go @@ -35,8 +35,7 @@ func panicOnPrmValue(n string, v any) { // the parameterized private key. func New(prm Prm, netmapClient *netmap.Client, containerClient *container.Client, opts ...Option) *Server { // verify required parameters - switch { - case prm.healthChecker == nil: + if prm.healthChecker == nil { panicOnPrmValue("health checker", prm.healthChecker) } diff --git a/pkg/util/http/server.go b/pkg/util/http/server.go index 923412a7f2..2589ab786c 100644 --- a/pkg/util/http/server.go +++ b/pkg/util/http/server.go @@ -76,8 +76,7 @@ func New(prm HTTPSrvPrm, opts ...Option) *Server { o(c) } - switch { - case c.shutdownTimeout <= 0: + if c.shutdownTimeout <= 0 { panicOnOptValue("shutdown timeout", c.shutdownTimeout) } From b88fe8c4a7f842c65d98a1edf6b83e54a7f2c3b3 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 14:45:04 +0300 Subject: [PATCH 1391/1413] [#1718] linter: Resolve gocritic's assignOp linter See https://go-critic.com/overview#assignop for details. Change-Id: I839446846437c8c74c119d8b5669f5b866c247dc Signed-off-by: Dmitrii Stepanov --- pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go index d2eef20744..a840275b8c 100644 --- a/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go +++ b/pkg/local_object_storage/blobstor/blobovniczatree/rebuild.go @@ -226,7 +226,7 @@ func (b *Blobovniczas) rebuildDB(ctx context.Context, path string, meta common.M func (b *Blobovniczas) addRebuildTempFile(ctx context.Context, path string) (func(), error) { sysPath := filepath.Join(b.rootPath, path) - sysPath = sysPath + rebuildSuffix + sysPath += rebuildSuffix _, err := os.OpenFile(sysPath, os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, b.perm) if err != nil { return nil, err From ca8b01667fac7107a8451843a4b21c656dfc7527 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 14:46:31 +0300 Subject: [PATCH 1392/1413] [#1718] linter: Resolve gocritic's unlambda linter See https://go-critic.com/overview#unlambda for details. Change-Id: Iccb2d293ce31a302fcbb2c3f9c55c9b3fa554db5 Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/v2/util.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index bfa7fd619f..4b7dcc530b 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -182,9 +182,7 @@ func (s *Service) toHashRangePrm(req *objectV2.GetRangeHashRequest) (*getsvc.Ran default: return nil, errUnknownChechsumType(t) case refs.SHA256: - p.SetHashGenerator(func() hash.Hash { - return sha256.New() - }) + p.SetHashGenerator(sha256.New) case refs.TillichZemor: p.SetHashGenerator(func() hash.Hash { return tz.New() From 3cbff575351a9a8ffff384e920d06da56a6c9703 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 14:47:32 +0300 Subject: [PATCH 1393/1413] [#1718] linter: Enable gocritic linter See https://go-critic.com/overview#checkers-from-the-diagnostic-group for list of default enabled checkers. `ifElseChain` disabled as it generates doubtful issues. Change-Id: I5937b116d9af8b3cdf8b06451c4904d0b3f67f68 Signed-off-by: Dmitrii Stepanov --- .golangci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.golangci.yml b/.golangci.yml index 3ac4eb651b..e3ec09f60d 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -18,6 +18,7 @@ linters: - exhaustive - funlen - gocognit + - gocritic - godot - importas - ineffassign @@ -44,6 +45,9 @@ linters: statements: 60 gocognit: min-complexity: 40 + gocritic: + disabled-checks: + - ifElseChain importas: alias: - pkg: git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object From c84013a85408a5403c2cc8f6f9cf98fb7bf79a7b Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Wed, 16 Apr 2025 15:09:43 +0300 Subject: [PATCH 1394/1413] [#1719] cli: Fix TTL description Change-Id: I051a27af57a74304713c1f832dc31dbaeb10cbc6 Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-cli/internal/commonflags/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/frostfs-cli/internal/commonflags/api.go b/cmd/frostfs-cli/internal/commonflags/api.go index 88321176f8..6ed21e107c 100644 --- a/cmd/frostfs-cli/internal/commonflags/api.go +++ b/cmd/frostfs-cli/internal/commonflags/api.go @@ -9,7 +9,7 @@ const ( TTL = "ttl" TTLShorthand = "" TTLDefault = 2 - TTLUsage = "TTL value in request meta header" + TTLUsage = "The maximum number of intermediate nodes in the request route" XHeadersKey = "xhdr" XHeadersShorthand = "x" From 1a738792c00518eff82b8643135c4bd4a40e0710 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Thu, 17 Apr 2025 16:15:12 +0300 Subject: [PATCH 1395/1413] [#1722] node, ir: Fix documentation for logger tags Close #1722. Change-Id: Iee9b3d96a31353622e1680d2d596ca6a9ee104b4 Signed-off-by: Anton Nikiforov --- config/example/ir.yaml | 2 +- docs/storage-node-configuration.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/example/ir.yaml b/config/example/ir.yaml index a4a0065507..ed53f014bf 100644 --- a/config/example/ir.yaml +++ b/config/example/ir.yaml @@ -4,7 +4,7 @@ logger: level: info # Logger level: one of "debug", "info" (default), "warn", "error", "dpanic", "panic", "fatal" timestamp: true tags: - - names: "main, morph" # Possible values: `main`, `morph`, `grpc_svc`, `ir`, `processor`. + - names: "main, morph" # Possible values: `main`, `morph`, `grpcsvc`, `ir`, `processor`. level: debug wallet: diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 3e770457ba..14ebb53b3d 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -123,10 +123,10 @@ logger: | `tags` | list of [tags descriptions](#tags-subsection) | | Array of tags description. | ## `tags` subsection -| Parameter | Type | Default value | Description | -|-----------|----------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `names` | `string` | | List of components divided by `,`.
Possible values: `main`, `morph`, `grpcsvc`, `ir`, `processor`, `engine`, `blobovnicza`, `blobstor`, `fstree`, `gc`, `shard`, `writecache`, `deletesvc`, `getsvc`, `searchsvc`, `sessionsvc`, `treesvc`, `policer`, `replicator`. | -| `level` | `string` | | Logging level for the components from `names`, overrides default logging level. | +| Parameter | Type | Default value | Description | +|-----------|----------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `names` | `string` | | List of components divided by `,`.
Possible values: `main`, `engine`, `blobovnicza`, `blobovniczatree`, `blobstor`, `fstree`, `gc`, `shard`, `writecache`, `deletesvc`, `getsvc`, `searchsvc`, `sessionsvc`, `treesvc`, `policer`, `replicator`. | +| `level` | `string` | | Logging level for the components from `names`, overrides default logging level. | # `contracts` section Contains override values for FrostFS side-chain contract hashes. Most of the time contract From 6567ceaf132c3295b8f011920d3718c989168b2f Mon Sep 17 00:00:00 2001 From: Alexander Chuprov Date: Thu, 17 Apr 2025 13:20:18 +0300 Subject: [PATCH 1396/1413] [#1702] tree: Support reloading 'tree.authorized_keys' on SIGHUP Allows updating the list of public keys authorized to invoke 'Tree service' operations without restarting the node. Change-Id: I01b6e05875b7ae3f3218062eb12bf9755e87f2a3 Signed-off-by: Alexander Chuprov --- cmd/frostfs-node/config.go | 7 +++++++ pkg/services/tree/options.go | 8 +++----- pkg/services/tree/service.go | 14 ++++++++++++++ pkg/services/tree/signature.go | 4 ++-- pkg/services/tree/signature_test.go | 1 + 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index fae1ca1ca7..b688acfde0 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -30,6 +30,7 @@ import ( objectconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/object" replicatorconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/replicator" tracingconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tracing" + treeconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/tree" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/metrics" internalNet "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" @@ -1403,6 +1404,12 @@ func (c *cfg) getComponents(ctx context.Context) []dCmp { } return err }}) + if c.treeService != nil { + components = append(components, dCmp{"tree", func() error { + c.treeService.ReloadAuthorizedKeys(treeconfig.Tree(c.appCfg).AuthorizedKeys()) + return nil + }}) + } if cmp, updated := metricsComponent(c); updated { if cmp.enabled { cmp.preReload = enableMetricsSvc diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index 4ad760846f..56cbcc0814 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -3,6 +3,7 @@ package tree import ( "context" "crypto/ecdsa" + "sync/atomic" "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" @@ -41,7 +42,7 @@ type cfg struct { replicatorWorkerCount int replicatorTimeout time.Duration containerCacheSize int - authorizedKeys [][]byte + authorizedKeys atomic.Pointer[[][]byte] syncBatchSize int localOverrideStorage policyengine.LocalOverrideStorage @@ -147,10 +148,7 @@ func WithMetrics(v MetricsRegister) Option { // keys that have rights to use Tree service. func WithAuthorizedKeys(keys keys.PublicKeys) Option { return func(c *cfg) { - c.authorizedKeys = nil - for _, key := range keys { - c.authorizedKeys = append(c.authorizedKeys, key.Bytes()) - } + c.authorizedKeys.Store(fromPublicKeys(keys)) } } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index 5349dd13eb..a4bc0c97c2 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -17,6 +17,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cidSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/panjf2000/ants/v2" "go.uber.org/zap" "google.golang.org/grpc/codes" @@ -59,6 +60,7 @@ func New(opts ...Option) *Service { s.replicatorTimeout = defaultReplicatorSendTimeout s.syncBatchSize = defaultSyncBatchSize s.metrics = defaultMetricsRegister{} + s.authorizedKeys.Store(&[][]byte{}) for i := range opts { opts[i](&s.cfg) @@ -782,3 +784,15 @@ func (s *Service) Healthcheck(context.Context, *HealthcheckRequest) (*Healthchec return new(HealthcheckResponse), nil } + +func (s *Service) ReloadAuthorizedKeys(newKeys keys.PublicKeys) { + s.authorizedKeys.Store(fromPublicKeys(newKeys)) +} + +func fromPublicKeys(keys keys.PublicKeys) *[][]byte { + buff := make([][]byte, len(keys)) + for i, k := range keys { + buff[i] = k.Bytes() + } + return &buff +} diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 89056056de..8221a4546f 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -95,8 +95,8 @@ func (s *Service) isAuthorized(req message, op acl.Op) (bool, error) { } key := sign.GetKey() - for i := range s.authorizedKeys { - if bytes.Equal(s.authorizedKeys[i], key) { + for _, currentKey := range *s.authorizedKeys.Load() { + if bytes.Equal(currentKey, key) { return true, nil } } diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 947de8e589..f5659d5e2d 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -152,6 +152,7 @@ func TestMessageSign(t *testing.T) { apeChecker: checkercore.New(e.LocalStorage(), e.MorphRuleChainStorage(), frostfsidProvider, dummyEpochSource{}), } + s.cfg.authorizedKeys.Store(&[][]byte{}) rawCID1 := make([]byte, sha256.Size) cid1.Encode(rawCID1) From 4bcb67263076baebb2192c49c4d9c6e8d46627cb Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 18 Apr 2025 18:28:36 +0300 Subject: [PATCH 1397/1413] [#1707] tree: Pass tracing context in `forEachNode` Change-Id: I884dcd215bd3934f9b4ea43dcc77e38f9dadcf10 Signed-off-by: Dmitrii Stepanov --- pkg/services/tree/redirect.go | 14 +++++++------- pkg/services/tree/service.go | 8 ++++---- pkg/services/tree/sync.go | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pkg/services/tree/redirect.go b/pkg/services/tree/redirect.go index 3dcdc4fc79..647f8cb301 100644 --- a/pkg/services/tree/redirect.go +++ b/pkg/services/tree/redirect.go @@ -19,8 +19,8 @@ var errNoSuitableNode = errors.New("no node was found to execute the request") func relayUnary[Req any, Resp any](ctx context.Context, s *Service, ns []netmapSDK.NodeInfo, req *Req, callback func(TreeServiceClient, context.Context, *Req, ...grpc.CallOption) (*Resp, error)) (*Resp, error) { var resp *Resp var outErr error - err := s.forEachNode(ctx, ns, func(c TreeServiceClient) bool { - resp, outErr = callback(c, ctx, req) + err := s.forEachNode(ctx, ns, func(fCtx context.Context, c TreeServiceClient) bool { + resp, outErr = callback(c, fCtx, req) return true }) if err != nil { @@ -31,7 +31,7 @@ func relayUnary[Req any, Resp any](ctx context.Context, s *Service, ns []netmapS // forEachNode executes callback for each node in the container until true is returned. // Returns errNoSuitableNode if there was no successful attempt to dial any node. -func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo, f func(c TreeServiceClient) bool) error { +func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo, f func(context.Context, TreeServiceClient) bool) error { for _, n := range cntNodes { if bytes.Equal(n.PublicKey(), s.rawPub) { return nil @@ -42,9 +42,9 @@ func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo for _, n := range cntNodes { var stop bool for endpoint := range n.NetworkEndpoints() { - stop = s.execOnClient(ctx, endpoint, func(c TreeServiceClient) bool { + stop = s.execOnClient(ctx, endpoint, func(fCtx context.Context, c TreeServiceClient) bool { called = true - return f(c) + return f(fCtx, c) }) if called { break @@ -60,7 +60,7 @@ func (s *Service) forEachNode(ctx context.Context, cntNodes []netmapSDK.NodeInfo return nil } -func (s *Service) execOnClient(ctx context.Context, endpoint string, f func(TreeServiceClient) bool) bool { +func (s *Service) execOnClient(ctx context.Context, endpoint string, f func(context.Context, TreeServiceClient) bool) bool { ctx, span := tracing.StartSpanFromContext(ctx, "TreeService.IterateNetworkEndpoints", trace.WithAttributes( attribute.String("endpoint", endpoint), @@ -73,5 +73,5 @@ func (s *Service) execOnClient(ctx context.Context, endpoint string, f func(Tree } s.log.Debug(ctx, logs.TreeRedirectingTreeServiceQuery, zap.String("endpoint", endpoint)) - return f(c) + return f(ctx, c) } diff --git a/pkg/services/tree/service.go b/pkg/services/tree/service.go index a4bc0c97c2..3994d69737 100644 --- a/pkg/services/tree/service.go +++ b/pkg/services/tree/service.go @@ -391,8 +391,8 @@ func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeS if pos < 0 { var cli TreeService_GetSubTreeClient var outErr error - err = s.forEachNode(srv.Context(), ns, func(c TreeServiceClient) bool { - cli, outErr = c.GetSubTree(srv.Context(), req) + err = s.forEachNode(srv.Context(), ns, func(fCtx context.Context, c TreeServiceClient) bool { + cli, outErr = c.GetSubTree(fCtx, req) return true }) if err != nil { @@ -655,8 +655,8 @@ func (s *Service) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) if pos < 0 { var cli TreeService_GetOpLogClient var outErr error - err := s.forEachNode(srv.Context(), ns, func(c TreeServiceClient) bool { - cli, outErr = c.GetOpLog(srv.Context(), req) + err := s.forEachNode(srv.Context(), ns, func(fCtx context.Context, c TreeServiceClient) bool { + cli, outErr = c.GetOpLog(fCtx, req) return true }) if err != nil { diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index 32297f9d70..d4040337d7 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -76,8 +76,8 @@ func (s *Service) synchronizeAllTrees(ctx context.Context, cid cid.ID) error { var treesToSync []string var outErr error - err = s.forEachNode(ctx, nodes, func(c TreeServiceClient) bool { - resp, outErr = c.TreeList(ctx, req) + err = s.forEachNode(ctx, nodes, func(fCtx context.Context, c TreeServiceClient) bool { + resp, outErr = c.TreeList(fCtx, req) if outErr != nil { return false } From a27e0035083b8e66ee446c949f98405c1ac2791d Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 21 Apr 2025 10:53:51 +0300 Subject: [PATCH 1398/1413] [#1709] qos: Add context.Done check before schedule request Do not push request to schedule queue, if context is already cancelled. Change-Id: Ieef837a7d423158e3dbb0c3b4efecaa20744c845 Signed-off-by: Dmitrii Stepanov --- internal/qos/limiter.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/internal/qos/limiter.go b/internal/qos/limiter.go index 5851d76267..2d7de32fc9 100644 --- a/internal/qos/limiter.go +++ b/internal/qos/limiter.go @@ -149,6 +149,11 @@ func (n *mClockLimiter) WriteRequest(ctx context.Context) (ReleaseFunc, error) { } func requestArrival(ctx context.Context, s scheduler, stats map[string]*stat) (ReleaseFunc, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } tag, ok := tagging.IOTagFromContext(ctx) if !ok { tag = IOTagClient.String() From 3a441f072ffb955c6513eb7dd7733da311590ad7 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 21 Apr 2025 12:13:32 +0300 Subject: [PATCH 1399/1413] [#1709] shard: Check if context canceled for shard iteration If context has already been canceled, then there is no need to check other shards. At the same time, it is necessary to avoid handling context cancellation in each handler. Therefore, the context check has been moved to the shard iteration method, which now returns an error. Change-Id: I70030ace36593ce7d2b8376bee39fe82e9dbf88f Signed-off-by: Dmitrii Stepanov --- internal/logs/logs.go | 1 + pkg/local_object_storage/engine/container.go | 27 ++++--- pkg/local_object_storage/engine/delete.go | 12 +-- pkg/local_object_storage/engine/exists.go | 6 +- pkg/local_object_storage/engine/get.go | 16 ++-- pkg/local_object_storage/engine/head.go | 6 +- pkg/local_object_storage/engine/inhume.go | 77 ++++++++++++-------- pkg/local_object_storage/engine/lock.go | 16 +++- pkg/local_object_storage/engine/put.go | 6 +- pkg/local_object_storage/engine/range.go | 16 ++-- pkg/local_object_storage/engine/select.go | 30 +++++--- pkg/local_object_storage/engine/shards.go | 22 +++++- 12 files changed, 149 insertions(+), 86 deletions(-) diff --git a/internal/logs/logs.go b/internal/logs/logs.go index dedc7e12cc..626372f435 100644 --- a/internal/logs/logs.go +++ b/internal/logs/logs.go @@ -198,6 +198,7 @@ const ( EngineInterruptProcessingTheExpiredLocks = "interrupt processing the expired locks" EngineInterruptGettingLockers = "can't get object's lockers" EngineInterruptProcessingTheDeletedLocks = "interrupt processing the deleted locks" + EngineInterruptProcessingTheExpiredTombstones = "interrupt processing the expired tombstones" EngineFailedToMoveShardInDegradedreadonlyModeMovingToReadonly = "failed to move shard in degraded-read-only mode, moving to read-only" EngineFailedToMoveShardInReadonlyMode = "failed to move shard in read-only mode" EngineShardIsMovedInReadonlyModeDueToErrorThreshold = "shard is moved in read-only mode due to error threshold" diff --git a/pkg/local_object_storage/engine/container.go b/pkg/local_object_storage/engine/container.go index 03a299b93b..e0617a8326 100644 --- a/pkg/local_object_storage/engine/container.go +++ b/pkg/local_object_storage/engine/container.go @@ -48,8 +48,9 @@ func (e *StorageEngine) ContainerSize(ctx context.Context, prm ContainerSizePrm) defer elapsed("ContainerSize", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res = e.containerSize(ctx, prm) - return nil + var csErr error + res, csErr = e.containerSize(ctx, prm) + return csErr }) return @@ -69,8 +70,9 @@ func ContainerSize(ctx context.Context, e *StorageEngine, id cid.ID) (uint64, er return res.Size(), nil } -func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) (res ContainerSizeRes) { - e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { +func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) (ContainerSizeRes, error) { + var res ContainerSizeRes + err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) { var csPrm shard.ContainerSizePrm csPrm.SetContainerID(prm.cnr) @@ -86,7 +88,7 @@ func (e *StorageEngine) containerSize(ctx context.Context, prm ContainerSizePrm) return false }) - return + return res, err } // ListContainers returns a unique container IDs presented in the engine objects. @@ -96,8 +98,9 @@ func (e *StorageEngine) ListContainers(ctx context.Context, _ ListContainersPrm) defer elapsed("ListContainers", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res = e.listContainers(ctx) - return nil + var lcErr error + res, lcErr = e.listContainers(ctx) + return lcErr }) return @@ -115,10 +118,10 @@ func ListContainers(ctx context.Context, e *StorageEngine) ([]cid.ID, error) { return res.Containers(), nil } -func (e *StorageEngine) listContainers(ctx context.Context) ListContainersRes { +func (e *StorageEngine) listContainers(ctx context.Context) (ListContainersRes, error) { uniqueIDs := make(map[string]cid.ID) - e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) { res, err := sh.ListContainers(ctx, shard.ListContainersPrm{}) if err != nil { e.reportShardError(ctx, sh, "can't get list of containers", err) @@ -133,7 +136,9 @@ func (e *StorageEngine) listContainers(ctx context.Context) ListContainersRes { } return false - }) + }); err != nil { + return ListContainersRes{}, err + } result := make([]cid.ID, 0, len(uniqueIDs)) for _, v := range uniqueIDs { @@ -142,5 +147,5 @@ func (e *StorageEngine) listContainers(ctx context.Context) ListContainersRes { return ListContainersRes{ containers: result, - } + }, nil } diff --git a/pkg/local_object_storage/engine/delete.go b/pkg/local_object_storage/engine/delete.go index 5e5f65fa2f..223cdbc488 100644 --- a/pkg/local_object_storage/engine/delete.go +++ b/pkg/local_object_storage/engine/delete.go @@ -71,7 +71,7 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) error { // Removal of a big object is done in multiple stages: // 1. Remove the parent object. If it is locked or already removed, return immediately. // 2. Otherwise, search for all objects with a particular SplitID and delete them too. - e.iterateOverSortedShards(prm.addr, func(_ int, sh hashedShard) (stop bool) { + if err := e.iterateOverSortedShards(ctx, prm.addr, func(_ int, sh hashedShard) (stop bool) { var existsPrm shard.ExistsPrm existsPrm.Address = prm.addr @@ -116,20 +116,22 @@ func (e *StorageEngine) delete(ctx context.Context, prm DeletePrm) error { // If a parent object is removed we should set GC mark on each shard. return splitInfo == nil - }) + }); err != nil { + return err + } if locked.is { return new(apistatus.ObjectLocked) } if splitInfo != nil { - e.deleteChildren(ctx, prm.addr, prm.forceRemoval, splitInfo.SplitID()) + return e.deleteChildren(ctx, prm.addr, prm.forceRemoval, splitInfo.SplitID()) } return nil } -func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, force bool, splitID *objectSDK.SplitID) { +func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, force bool, splitID *objectSDK.SplitID) error { var fs objectSDK.SearchFilters fs.AddSplitIDFilter(objectSDK.MatchStringEqual, splitID) @@ -142,7 +144,7 @@ func (e *StorageEngine) deleteChildren(ctx context.Context, addr oid.Address, fo inhumePrm.ForceRemoval() } - e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { + return e.iterateOverSortedShards(ctx, addr, func(_ int, sh hashedShard) (stop bool) { res, err := sh.Select(ctx, selectPrm) if err != nil { e.log.Warn(ctx, logs.EngineErrorDuringSearchingForObjectChildren, diff --git a/pkg/local_object_storage/engine/exists.go b/pkg/local_object_storage/engine/exists.go index 9d2b1c1b78..7dac9eb97f 100644 --- a/pkg/local_object_storage/engine/exists.go +++ b/pkg/local_object_storage/engine/exists.go @@ -18,7 +18,7 @@ func (e *StorageEngine) exists(ctx context.Context, shPrm shard.ExistsPrm) (bool exists := false locked := false - e.iterateOverSortedShards(shPrm.Address, func(_ int, sh hashedShard) (stop bool) { + if err := e.iterateOverSortedShards(ctx, shPrm.Address, func(_ int, sh hashedShard) (stop bool) { res, err := sh.Exists(ctx, shPrm) if err != nil { if client.IsErrObjectAlreadyRemoved(err) { @@ -50,7 +50,9 @@ func (e *StorageEngine) exists(ctx context.Context, shPrm shard.ExistsPrm) (bool } return false - }) + }); err != nil { + return false, false, err + } if alreadyRemoved { return false, false, new(apistatus.ObjectAlreadyRemoved) diff --git a/pkg/local_object_storage/engine/get.go b/pkg/local_object_storage/engine/get.go index 74c64bbb60..0694c53f35 100644 --- a/pkg/local_object_storage/engine/get.go +++ b/pkg/local_object_storage/engine/get.go @@ -78,7 +78,9 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { Engine: e, } - it.tryGetWithMeta(ctx) + if err := it.tryGetWithMeta(ctx); err != nil { + return GetRes{}, err + } if it.SplitInfo != nil { return GetRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo)) @@ -97,7 +99,9 @@ func (e *StorageEngine) get(ctx context.Context, prm GetPrm) (GetRes, error) { return GetRes{}, it.OutError } - it.tryGetFromBlobstore(ctx) + if err := it.tryGetFromBlobstore(ctx); err != nil { + return GetRes{}, err + } if it.Object == nil { return GetRes{}, it.OutError @@ -133,8 +137,8 @@ type getShardIterator struct { ecInfoErr *objectSDK.ECInfoError } -func (i *getShardIterator) tryGetWithMeta(ctx context.Context) { - i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) { +func (i *getShardIterator) tryGetWithMeta(ctx context.Context) error { + return i.Engine.iterateOverSortedShards(ctx, i.Address, func(_ int, sh hashedShard) (stop bool) { noMeta := sh.GetMode().NoMetabase() i.ShardPrm.SetIgnoreMeta(noMeta) @@ -187,13 +191,13 @@ func (i *getShardIterator) tryGetWithMeta(ctx context.Context) { }) } -func (i *getShardIterator) tryGetFromBlobstore(ctx context.Context) { +func (i *getShardIterator) tryGetFromBlobstore(ctx context.Context) error { // If the object is not found but is present in metabase, // try to fetch it from blobstor directly. If it is found in any // blobstor, increase the error counter for the shard which contains the meta. i.ShardPrm.SetIgnoreMeta(true) - i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) { + return i.Engine.iterateOverSortedShards(ctx, i.Address, func(_ int, sh hashedShard) (stop bool) { if sh.GetMode().NoMetabase() { // Already visited. return false diff --git a/pkg/local_object_storage/engine/head.go b/pkg/local_object_storage/engine/head.go index d6892f1291..d436dd4113 100644 --- a/pkg/local_object_storage/engine/head.go +++ b/pkg/local_object_storage/engine/head.go @@ -82,7 +82,7 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) shPrm.SetAddress(prm.addr) shPrm.SetRaw(prm.raw) - e.iterateOverSortedShards(prm.addr, func(_ int, sh hashedShard) (stop bool) { + if err := e.iterateOverSortedShards(ctx, prm.addr, func(_ int, sh hashedShard) (stop bool) { shPrm.ShardLooksBad = sh.errorCount.Load() >= e.errorsThreshold res, err := sh.Head(ctx, shPrm) if err != nil { @@ -123,7 +123,9 @@ func (e *StorageEngine) head(ctx context.Context, prm HeadPrm) (HeadRes, error) } head = res.Object() return true - }) + }); err != nil { + return HeadRes{}, err + } if head != nil { return HeadRes{head: head}, nil diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index e5a2396e1c..e13f04927d 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -158,7 +158,7 @@ func (e *StorageEngine) findShards(ctx context.Context, addr oid.Address, checkL objectExists bool ) - e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { + if err := e.iterateOverSortedShards(ctx, addr, func(_ int, sh hashedShard) (stop bool) { objectExists = false prm.Address = addr @@ -209,7 +209,9 @@ func (e *StorageEngine) findShards(ctx context.Context, addr oid.Address, checkL // Continue if it's a root object. return !isRootObject - }) + }); err != nil { + return nil, err + } if retErr != nil { return nil, retErr @@ -229,7 +231,7 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e var err error var outErr error - e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { + if err := e.iterateOverUnsortedShards(ctx, func(h hashedShard) (stop bool) { locked, err = h.IsLocked(ctx, addr) if err != nil { e.reportShardError(ctx, h, "can't check object's lockers", err, zap.Stringer("address", addr)) @@ -238,7 +240,9 @@ func (e *StorageEngine) IsLocked(ctx context.Context, addr oid.Address) (bool, e } return locked - }) + }); err != nil { + return false, err + } if locked { return locked, nil @@ -258,7 +262,7 @@ func (e *StorageEngine) GetLocks(ctx context.Context, addr oid.Address) ([]oid.I var allLocks []oid.ID var outErr error - e.iterateOverUnsortedShards(func(h hashedShard) (stop bool) { + if err := e.iterateOverUnsortedShards(ctx, func(h hashedShard) (stop bool) { locks, err := h.GetLocks(ctx, addr) if err != nil { e.reportShardError(ctx, h, logs.EngineInterruptGettingLockers, err, zap.Stringer("address", addr)) @@ -266,7 +270,9 @@ func (e *StorageEngine) GetLocks(ctx context.Context, addr oid.Address) ([]oid.I } allLocks = append(allLocks, locks...) return false - }) + }); err != nil { + return nil, err + } if len(allLocks) > 0 { return allLocks, nil } @@ -274,20 +280,23 @@ func (e *StorageEngine) GetLocks(ctx context.Context, addr oid.Address) ([]oid.I } func (e *StorageEngine) processExpiredTombstones(ctx context.Context, addrs []meta.TombstonedObject) { - e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) { sh.HandleExpiredTombstones(ctx, addrs) select { case <-ctx.Done(): + e.log.Info(ctx, logs.EngineInterruptProcessingTheExpiredTombstones, zap.Error(ctx.Err())) return true default: return false } - }) + }); err != nil { + e.log.Info(ctx, logs.EngineInterruptProcessingTheExpiredTombstones, zap.Error(err)) + } } func (e *StorageEngine) processExpiredLocks(ctx context.Context, epoch uint64, lockers []oid.Address) { - e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) { sh.HandleExpiredLocks(ctx, epoch, lockers) select { @@ -297,11 +306,13 @@ func (e *StorageEngine) processExpiredLocks(ctx context.Context, epoch uint64, l default: return false } - }) + }); err != nil { + e.log.Info(ctx, logs.EngineInterruptProcessingTheExpiredLocks, zap.Error(err)) + } } func (e *StorageEngine) processDeletedLocks(ctx context.Context, lockers []oid.Address) { - e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) { sh.HandleDeletedLocks(ctx, lockers) select { @@ -311,26 +322,25 @@ func (e *StorageEngine) processDeletedLocks(ctx context.Context, lockers []oid.A default: return false } - }) + }); err != nil { + e.log.Info(ctx, logs.EngineInterruptProcessingTheDeletedLocks, zap.Error(err)) + } } func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid.ID) { if len(ids) == 0 { return } - idMap, err := e.selectNonExistentIDs(ctx, ids) if err != nil { return } - if len(idMap) == 0 { return } - var failed bool var prm shard.ContainerSizePrm - e.iterateOverUnsortedShards(func(sh hashedShard) bool { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) bool { select { case <-ctx.Done(): e.log.Info(ctx, logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(ctx.Err())) @@ -357,13 +367,15 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid } return len(idMap) == 0 - }) - + }); err != nil { + e.log.Info(ctx, logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(err)) + return + } if failed || len(idMap) == 0 { return } - e.iterateOverUnsortedShards(func(sh hashedShard) bool { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) bool { select { case <-ctx.Done(): e.log.Info(ctx, logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(ctx.Err())) @@ -381,12 +393,13 @@ func (e *StorageEngine) processZeroSizeContainers(ctx context.Context, ids []cid } return false - }) - + }); err != nil { + e.log.Info(ctx, logs.EngineInterruptProcessingZeroSizeContainers, zap.Error(err)) + return + } if failed { return } - for id := range idMap { e.metrics.DeleteContainerSize(id.EncodeToString()) } @@ -396,19 +409,16 @@ func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []ci if len(ids) == 0 { return } - idMap, err := e.selectNonExistentIDs(ctx, ids) if err != nil { return } - if len(idMap) == 0 { return } - var failed bool var prm shard.ContainerCountPrm - e.iterateOverUnsortedShards(func(sh hashedShard) bool { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) bool { select { case <-ctx.Done(): e.log.Info(ctx, logs.EngineInterruptProcessingZeroCountContainers, zap.Error(ctx.Err())) @@ -435,13 +445,15 @@ func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []ci } return len(idMap) == 0 - }) - + }); err != nil { + e.log.Info(ctx, logs.EngineInterruptProcessingZeroCountContainers, zap.Error(err)) + return + } if failed || len(idMap) == 0 { return } - e.iterateOverUnsortedShards(func(sh hashedShard) bool { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) bool { select { case <-ctx.Done(): e.log.Info(ctx, logs.EngineInterruptProcessingZeroCountContainers, zap.Error(ctx.Err())) @@ -459,12 +471,13 @@ func (e *StorageEngine) processZeroCountContainers(ctx context.Context, ids []ci } return false - }) - + }); err != nil { + e.log.Info(ctx, logs.EngineInterruptProcessingZeroCountContainers, zap.Error(err)) + return + } if failed { return } - for id := range idMap { e.metrics.DeleteContainerCount(id.EncodeToString()) } diff --git a/pkg/local_object_storage/engine/lock.go b/pkg/local_object_storage/engine/lock.go index 18fff9cad8..3b0cf74f99 100644 --- a/pkg/local_object_storage/engine/lock.go +++ b/pkg/local_object_storage/engine/lock.go @@ -41,11 +41,19 @@ func (e *StorageEngine) Lock(ctx context.Context, idCnr cid.ID, locker oid.ID, l func (e *StorageEngine) lock(ctx context.Context, idCnr cid.ID, locker oid.ID, locked []oid.ID) error { for i := range locked { - switch e.lockSingle(ctx, idCnr, locker, locked[i], true) { + st, err := e.lockSingle(ctx, idCnr, locker, locked[i], true) + if err != nil { + return err + } + switch st { case 1: return logicerr.Wrap(new(apistatus.LockNonRegularObject)) case 0: - switch e.lockSingle(ctx, idCnr, locker, locked[i], false) { + st, err = e.lockSingle(ctx, idCnr, locker, locked[i], false) + if err != nil { + return err + } + switch st { case 1: return logicerr.Wrap(new(apistatus.LockNonRegularObject)) case 0: @@ -61,13 +69,13 @@ func (e *StorageEngine) lock(ctx context.Context, idCnr cid.ID, locker oid.ID, l // - 0: fail // - 1: locking irregular object // - 2: ok -func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, locked oid.ID, checkExists bool) (status uint8) { +func (e *StorageEngine) lockSingle(ctx context.Context, idCnr cid.ID, locker, locked oid.ID, checkExists bool) (status uint8, retErr error) { // code is pretty similar to inhumeAddr, maybe unify? root := false var addrLocked oid.Address addrLocked.SetContainer(idCnr) addrLocked.SetObject(locked) - e.iterateOverSortedShards(addrLocked, func(_ int, sh hashedShard) (stop bool) { + retErr = e.iterateOverSortedShards(ctx, addrLocked, func(_ int, sh hashedShard) (stop bool) { defer func() { // if object is root we continue since information about it // can be presented in other shards diff --git a/pkg/local_object_storage/engine/put.go b/pkg/local_object_storage/engine/put.go index b348d13a23..10cf5ffd5d 100644 --- a/pkg/local_object_storage/engine/put.go +++ b/pkg/local_object_storage/engine/put.go @@ -96,7 +96,7 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { } var shRes putToShardRes - e.iterateOverSortedShards(addr, func(_ int, sh hashedShard) (stop bool) { + if err := e.iterateOverSortedShards(ctx, addr, func(_ int, sh hashedShard) (stop bool) { e.mtx.RLock() _, ok := e.shards[sh.ID().String()] e.mtx.RUnlock() @@ -106,7 +106,9 @@ func (e *StorageEngine) put(ctx context.Context, prm PutPrm) error { } shRes = e.putToShard(ctx, sh, addr, prm.Object, prm.IsIndexedContainer) return shRes.status != putToShardUnknown - }) + }); err != nil { + return err + } switch shRes.status { case putToShardUnknown: return errPutShard diff --git a/pkg/local_object_storage/engine/range.go b/pkg/local_object_storage/engine/range.go index a468cf5944..7ec4742d8c 100644 --- a/pkg/local_object_storage/engine/range.go +++ b/pkg/local_object_storage/engine/range.go @@ -93,7 +93,9 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error Engine: e, } - it.tryGetWithMeta(ctx) + if err := it.tryGetWithMeta(ctx); err != nil { + return RngRes{}, err + } if it.SplitInfo != nil { return RngRes{}, logicerr.Wrap(objectSDK.NewSplitInfoError(it.SplitInfo)) @@ -109,7 +111,9 @@ func (e *StorageEngine) getRange(ctx context.Context, prm RngPrm) (RngRes, error return RngRes{}, it.OutError } - it.tryGetFromBlobstor(ctx) + if err := it.tryGetFromBlobstor(ctx); err != nil { + return RngRes{}, err + } if it.Object == nil { return RngRes{}, it.OutError @@ -157,8 +161,8 @@ type getRangeShardIterator struct { Engine *StorageEngine } -func (i *getRangeShardIterator) tryGetWithMeta(ctx context.Context) { - i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) { +func (i *getRangeShardIterator) tryGetWithMeta(ctx context.Context) error { + return i.Engine.iterateOverSortedShards(ctx, i.Address, func(_ int, sh hashedShard) (stop bool) { noMeta := sh.GetMode().NoMetabase() i.HasDegraded = i.HasDegraded || noMeta i.ShardPrm.SetIgnoreMeta(noMeta) @@ -209,13 +213,13 @@ func (i *getRangeShardIterator) tryGetWithMeta(ctx context.Context) { }) } -func (i *getRangeShardIterator) tryGetFromBlobstor(ctx context.Context) { +func (i *getRangeShardIterator) tryGetFromBlobstor(ctx context.Context) error { // If the object is not found but is present in metabase, // try to fetch it from blobstor directly. If it is found in any // blobstor, increase the error counter for the shard which contains the meta. i.ShardPrm.SetIgnoreMeta(true) - i.Engine.iterateOverSortedShards(i.Address, func(_ int, sh hashedShard) (stop bool) { + return i.Engine.iterateOverSortedShards(ctx, i.Address, func(_ int, sh hashedShard) (stop bool) { if sh.GetMode().NoMetabase() { // Already processed it without a metabase. return false diff --git a/pkg/local_object_storage/engine/select.go b/pkg/local_object_storage/engine/select.go index fc8b4a9a72..4243a54819 100644 --- a/pkg/local_object_storage/engine/select.go +++ b/pkg/local_object_storage/engine/select.go @@ -54,14 +54,15 @@ func (e *StorageEngine) Select(ctx context.Context, prm SelectPrm) (res SelectRe defer elapsed("Select", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res = e._select(ctx, prm) - return nil + var sErr error + res, sErr = e._select(ctx, prm) + return sErr }) return } -func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) SelectRes { +func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) (SelectRes, error) { addrList := make([]oid.Address, 0) uniqueMap := make(map[string]struct{}) @@ -69,7 +70,7 @@ func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) SelectRes { shPrm.SetContainerID(prm.cnr, prm.indexedContainer) shPrm.SetFilters(prm.filters) - e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) { res, err := sh.Select(ctx, shPrm) if err != nil { e.reportShardError(ctx, sh, "could not select objects from shard", err) @@ -84,11 +85,13 @@ func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) SelectRes { } return false - }) + }); err != nil { + return SelectRes{}, err + } return SelectRes{ addrList: addrList, - } + }, nil } // List returns `limit` available physically storage object addresses in engine. @@ -98,20 +101,21 @@ func (e *StorageEngine) _select(ctx context.Context, prm SelectPrm) SelectRes { func (e *StorageEngine) List(ctx context.Context, limit uint64) (res SelectRes, err error) { defer elapsed("List", e.metrics.AddMethodDuration)() err = e.execIfNotBlocked(func() error { - res = e.list(ctx, limit) - return nil + var lErr error + res, lErr = e.list(ctx, limit) + return lErr }) return } -func (e *StorageEngine) list(ctx context.Context, limit uint64) SelectRes { +func (e *StorageEngine) list(ctx context.Context, limit uint64) (SelectRes, error) { addrList := make([]oid.Address, 0, limit) uniqueMap := make(map[string]struct{}) ln := uint64(0) // consider iterating over shuffled shards - e.iterateOverUnsortedShards(func(sh hashedShard) (stop bool) { + if err := e.iterateOverUnsortedShards(ctx, func(sh hashedShard) (stop bool) { res, err := sh.List(ctx) // consider limit result of shard iterator if err != nil { e.reportShardError(ctx, sh, "could not select objects from shard", err) @@ -130,11 +134,13 @@ func (e *StorageEngine) list(ctx context.Context, limit uint64) SelectRes { } return false - }) + }); err != nil { + return SelectRes{}, err + } return SelectRes{ addrList: addrList, - } + }, nil } // Select selects objects from local storage using provided filters. diff --git a/pkg/local_object_storage/engine/shards.go b/pkg/local_object_storage/engine/shards.go index 6e6c08bb55..69067c500b 100644 --- a/pkg/local_object_storage/engine/shards.go +++ b/pkg/local_object_storage/engine/shards.go @@ -280,20 +280,32 @@ func (e *StorageEngine) unsortedShards() []hashedShard { return shards } -func (e *StorageEngine) iterateOverSortedShards(addr oid.Address, handler func(int, hashedShard) (stop bool)) { +func (e *StorageEngine) iterateOverSortedShards(ctx context.Context, addr oid.Address, handler func(int, hashedShard) (stop bool)) error { for i, sh := range e.sortShards(addr) { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } if handler(i, sh) { break } } + return nil } -func (e *StorageEngine) iterateOverUnsortedShards(handler func(hashedShard) (stop bool)) { +func (e *StorageEngine) iterateOverUnsortedShards(ctx context.Context, handler func(hashedShard) (stop bool)) error { for _, sh := range e.unsortedShards() { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } if handler(sh) { break } } + return nil } // SetShardMode sets mode of the shard with provided identifier. @@ -433,7 +445,7 @@ func (e *StorageEngine) ListShardsForObject(ctx context.Context, obj oid.Address var siErr *objectSDK.SplitInfoError var ecErr *objectSDK.ECInfoError - e.iterateOverUnsortedShards(func(hs hashedShard) (stop bool) { + if itErr := e.iterateOverUnsortedShards(ctx, func(hs hashedShard) (stop bool) { res, exErr := hs.Exists(ctx, prm) if exErr != nil { if client.IsErrObjectAlreadyRemoved(exErr) { @@ -463,6 +475,8 @@ func (e *StorageEngine) ListShardsForObject(ctx context.Context, obj oid.Address info = append(info, hs.DumpInfo()) } return false - }) + }); itErr != nil { + return nil, itErr + } return info, err } From 908b08108d7781bad2054d449c427389f2dfe9f3 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 21 Apr 2025 11:59:21 +0300 Subject: [PATCH 1400/1413] [#1689] engine/test: Fix `TestInhumeIfObjectDoesntExist` test Removed an invalid test case which used exclusive options, added object status check after removal. Change-Id: I4551c0e4532fb669ee6c72871dc4bd34707d8469 Signed-off-by: Aleksey Savchuk --- .../engine/inhume_test.go | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 0601a43f2d..fa73dcad50 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -11,6 +11,7 @@ import ( meta "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/metabase" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" + "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -251,21 +252,23 @@ func TestInhumeIfObjectDoesntExist(t *testing.T) { t.Run("inhume with tombstone", func(t *testing.T) { testInhumeLockedIfObjectDoesntExist(t, true, false) }) - t.Run("force inhume without tombstone", func(t *testing.T) { + t.Run("force inhume", func(t *testing.T) { testInhumeLockedIfObjectDoesntExist(t, false, true) }) - t.Run("force inhume with tombstone", func(t *testing.T) { - testInhumeLockedIfObjectDoesntExist(t, true, true) - }) }) } func testInhumeLockedIfObjectDoesntExist(t *testing.T, withTombstone, withForce bool) { t.Parallel() + // Due to the tests design it is possible to set both the options, + // however removal with tombstone and force removal are exclusive. + require.False(t, withTombstone && withForce) + var ( errLocked *apistatus.ObjectLocked inhumePrm InhumePrm + headPrm HeadPrm ctx = context.Background() container = cidtest.ID() object = oidtest.Address() @@ -291,9 +294,17 @@ func testInhumeLockedIfObjectDoesntExist(t *testing.T, withTombstone, withForce } err = engine.Inhume(ctx, inhumePrm) - if withForce { - require.NoError(t, err) - } else { + if !withForce { require.ErrorAs(t, err, &errLocked) + return + } + require.NoError(t, err) + + headPrm.WithAddress(object) + _, err = engine.Head(ctx, headPrm) + if withTombstone { + require.True(t, client.IsErrObjectAlreadyRemoved(err)) + } else { + require.True(t, client.IsErrObjectNotFound(err)) } } From 487cb34c5dcf21bf385d8ddf8a397652260101a8 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 21 Apr 2025 13:26:32 +0300 Subject: [PATCH 1401/1413] [#1689] engine/test: Refactor `TestInhumeIfObjectDoesntExist` test - Use the same storage engine in multiple parallel tests - Move `Lock`, `Inhume`, `Head` calls to separate functions Change-Id: I00849c1f068f0ab8d92061719d67d6fe786200db Signed-off-by: Aleksey Savchuk --- .../engine/inhume_test.go | 84 ++++++++++--------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index fa73dcad50..813c329f29 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -245,66 +245,74 @@ func benchmarkInhumeMultipart(b *testing.B, numShards, numObjects int) { } func TestInhumeIfObjectDoesntExist(t *testing.T) { + const numShards = 4 + + engine := testNewEngine(t).setShardsNum(t, numShards).prepare(t).engine + t.Cleanup(func() { require.NoError(t, engine.Close(context.Background())) }) + t.Run("object is locked", func(t *testing.T) { t.Run("inhume without tombstone", func(t *testing.T) { - testInhumeLockedIfObjectDoesntExist(t, false, false) + testInhumeLockedIfObjectDoesntExist(t, engine, false, false) }) t.Run("inhume with tombstone", func(t *testing.T) { - testInhumeLockedIfObjectDoesntExist(t, true, false) + testInhumeLockedIfObjectDoesntExist(t, engine, true, false) }) t.Run("force inhume", func(t *testing.T) { - testInhumeLockedIfObjectDoesntExist(t, false, true) + testInhumeLockedIfObjectDoesntExist(t, engine, false, true) }) }) } -func testInhumeLockedIfObjectDoesntExist(t *testing.T, withTombstone, withForce bool) { +func testInhumeLockedIfObjectDoesntExist(t *testing.T, e *StorageEngine, withTombstone, withForce bool) { t.Parallel() - // Due to the tests design it is possible to set both the options, - // however removal with tombstone and force removal are exclusive. - require.False(t, withTombstone && withForce) + object := oidtest.Address() + require.NoError(t, testLockObject(e, object)) - var ( - errLocked *apistatus.ObjectLocked - inhumePrm InhumePrm - headPrm HeadPrm - ctx = context.Background() - container = cidtest.ID() - object = oidtest.Address() - lock = oidtest.ID() - tombstone = oidtest.Address() - ) - object.SetContainer(container) - tombstone.SetContainer(container) - - engine := testNewEngine(t).setShardsNum(t, 4).prepare(t).engine - defer func() { require.NoError(t, engine.Close(ctx)) }() - - err := engine.Lock(ctx, container, lock, []oid.ID{object.Object()}) - require.NoError(t, err) - - if withTombstone { - inhumePrm.WithTarget(tombstone, object) - } else { - inhumePrm.MarkAsGarbage(object) - } - if withForce { - inhumePrm.WithForceRemoval() - } - - err = engine.Inhume(ctx, inhumePrm) + err := testInhumeObject(t, e, object, withTombstone, withForce) if !withForce { + var errLocked *apistatus.ObjectLocked require.ErrorAs(t, err, &errLocked) return } require.NoError(t, err) - headPrm.WithAddress(object) - _, err = engine.Head(ctx, headPrm) + err = testHeadObject(e, object) if withTombstone { require.True(t, client.IsErrObjectAlreadyRemoved(err)) } else { require.True(t, client.IsErrObjectNotFound(err)) } } + +func testLockObject(e *StorageEngine, obj oid.Address) error { + return e.Lock(context.Background(), obj.Container(), oidtest.ID(), []oid.ID{obj.Object()}) +} + +func testInhumeObject(t testing.TB, e *StorageEngine, obj oid.Address, withTombstone, withForce bool) error { + tombstone := oidtest.Address() + tombstone.SetContainer(obj.Container()) + + // Due to the tests design it is possible to set both the options, + // however removal with tombstone and force removal are exclusive. + require.False(t, withTombstone && withForce) + + var inhumePrm InhumePrm + if withTombstone { + inhumePrm.WithTarget(tombstone, obj) + } else { + inhumePrm.MarkAsGarbage(obj) + } + if withForce { + inhumePrm.WithForceRemoval() + } + return e.Inhume(context.Background(), inhumePrm) +} + +func testHeadObject(e *StorageEngine, obj oid.Address) error { + var headPrm HeadPrm + headPrm.WithAddress(obj) + + _, err := e.Head(context.Background(), headPrm) + return err +} From 77b8545601f13ba4e596542be58b7e6f9c8e36d1 Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Mon, 21 Apr 2025 13:31:54 +0300 Subject: [PATCH 1402/1413] [#1689] engine: Fix removal of objects not found on node Ensured correct object status if the object is not found on a node. Fixed regression introduced in #1450. Besides an object not being found on any shard, it also important to remove it anyway in order to populate the metabase indexes because they are responsible for the correct object status, i.e., the status will be `object not found` without the indexes, the status will be `object is already removed` with the indexes. Change-Id: I6237fbc0f8bb0c4f2a51ada3a68f52950050e660 Signed-off-by: Aleksey Savchuk --- pkg/local_object_storage/engine/inhume.go | 100 +++++++++++++++--- .../engine/inhume_test.go | 24 +++++ 2 files changed, 107 insertions(+), 17 deletions(-) diff --git a/pkg/local_object_storage/engine/inhume.go b/pkg/local_object_storage/engine/inhume.go index e13f04927d..e5f7072e28 100644 --- a/pkg/local_object_storage/engine/inhume.go +++ b/pkg/local_object_storage/engine/inhume.go @@ -74,7 +74,7 @@ func (e *StorageEngine) Inhume(ctx context.Context, prm InhumePrm) error { } func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) error { - addrsPerShard, err := e.groupObjectsByShard(ctx, prm.addrs, !prm.forceRemoval) + addrsPerShard, notFoundObjects, err := e.groupObjectsByShard(ctx, prm.addrs, !prm.forceRemoval) if err != nil { return err } @@ -84,8 +84,6 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) error { shPrm.ForceRemoval() } - var errLocked *apistatus.ObjectLocked - for shardID, addrs := range addrsPerShard { if prm.tombstone != nil { shPrm.SetTarget(*prm.tombstone, addrs...) @@ -103,39 +101,107 @@ func (e *StorageEngine) inhume(ctx context.Context, prm InhumePrm) error { } if _, err := sh.Inhume(ctx, shPrm); err != nil { - switch { - case errors.As(err, &errLocked): - case errors.Is(err, shard.ErrLockObjectRemoval): - case errors.Is(err, shard.ErrReadOnlyMode): - case errors.Is(err, shard.ErrDegradedMode): - default: - e.reportShardError(ctx, sh, "couldn't inhume object in shard", err) - } + e.reportInhumeError(ctx, err, sh) return err } } - return nil + return e.inhumeNotFoundObjects(ctx, notFoundObjects, prm) +} + +func (e *StorageEngine) reportInhumeError(ctx context.Context, err error, hs hashedShard) { + if err == nil { + return + } + + var errLocked *apistatus.ObjectLocked + switch { + case errors.As(err, &errLocked): + case errors.Is(err, shard.ErrLockObjectRemoval): + case errors.Is(err, shard.ErrReadOnlyMode): + case errors.Is(err, shard.ErrDegradedMode): + default: + e.reportShardError(ctx, hs, "couldn't inhume object in shard", err) + } +} + +// inhumeNotFoundObjects removes object which are not found on any shard. +// +// Besides an object not being found on any shard, it is also important to +// remove it anyway in order to populate the metabase indexes because they are +// responsible for the correct object status, i.e., the status will be `object +// not found` without the indexes, the status will be `object is already +// removed` with the indexes. +// +// It is suggested to evenly remove those objects on each shard with the batch +// size equal to 1 + floor(number of objects / number of shards). +func (e *StorageEngine) inhumeNotFoundObjects(ctx context.Context, addrs []oid.Address, prm InhumePrm) error { + if len(addrs) == 0 { + return nil + } + + var shPrm shard.InhumePrm + if prm.forceRemoval { + shPrm.ForceRemoval() + } + + numObjectsPerShard := 1 + len(addrs)/len(e.shards) + + var inhumeErr error + itErr := e.iterateOverUnsortedShards(ctx, func(hs hashedShard) (stop bool) { + numObjects := min(numObjectsPerShard, len(addrs)) + + if numObjects == 0 { + return true + } + + if prm.tombstone != nil { + shPrm.SetTarget(*prm.tombstone, addrs[:numObjects]...) + } else { + shPrm.MarkAsGarbage(addrs[:numObjects]...) + } + addrs = addrs[numObjects:] + + _, inhumeErr = hs.Inhume(ctx, shPrm) + e.reportInhumeError(ctx, inhumeErr, hs) + return inhumeErr != nil + }) + if inhumeErr != nil { + return inhumeErr + } + return itErr } // groupObjectsByShard groups objects based on the shard(s) they are stored on. // // If checkLocked is set, [apistatus.ObjectLocked] will be returned if any of // the objects are locked. -func (e *StorageEngine) groupObjectsByShard(ctx context.Context, addrs []oid.Address, checkLocked bool) (map[string][]oid.Address, error) { - groups := make(map[string][]oid.Address) +// +// Returns two sets of objects: found objects which are grouped per shard and +// not found object. Not found objects are objects which are not found on any +// shard. This can happen if a node is a container node but doesn't participate +// in a replica group of the object. +func (e *StorageEngine) groupObjectsByShard(ctx context.Context, addrs []oid.Address, checkLocked bool) (groups map[string][]oid.Address, notFoundObjects []oid.Address, err error) { + groups = make(map[string][]oid.Address) + var ids []string for _, addr := range addrs { - ids, err := e.findShards(ctx, addr, checkLocked) + ids, err = e.findShards(ctx, addr, checkLocked) if err != nil { - return nil, err + return } + + if len(ids) == 0 { + notFoundObjects = append(notFoundObjects, addr) + continue + } + for _, id := range ids { groups[id] = append(groups[id], addr) } } - return groups, nil + return } // findShards determines the shard(s) where the object is stored. diff --git a/pkg/local_object_storage/engine/inhume_test.go b/pkg/local_object_storage/engine/inhume_test.go index 813c329f29..0e268cd231 100644 --- a/pkg/local_object_storage/engine/inhume_test.go +++ b/pkg/local_object_storage/engine/inhume_test.go @@ -250,6 +250,16 @@ func TestInhumeIfObjectDoesntExist(t *testing.T) { engine := testNewEngine(t).setShardsNum(t, numShards).prepare(t).engine t.Cleanup(func() { require.NoError(t, engine.Close(context.Background())) }) + t.Run("inhume without tombstone", func(t *testing.T) { + testInhumeIfObjectDoesntExist(t, engine, false, false) + }) + t.Run("inhume with tombstone", func(t *testing.T) { + testInhumeIfObjectDoesntExist(t, engine, true, false) + }) + t.Run("force inhume", func(t *testing.T) { + testInhumeIfObjectDoesntExist(t, engine, false, true) + }) + t.Run("object is locked", func(t *testing.T) { t.Run("inhume without tombstone", func(t *testing.T) { testInhumeLockedIfObjectDoesntExist(t, engine, false, false) @@ -263,6 +273,20 @@ func TestInhumeIfObjectDoesntExist(t *testing.T) { }) } +func testInhumeIfObjectDoesntExist(t *testing.T, e *StorageEngine, withTombstone, withForce bool) { + t.Parallel() + + object := oidtest.Address() + require.NoError(t, testInhumeObject(t, e, object, withTombstone, withForce)) + + err := testHeadObject(e, object) + if withTombstone { + require.True(t, client.IsErrObjectAlreadyRemoved(err)) + } else { + require.True(t, client.IsErrObjectNotFound(err)) + } +} + func testInhumeLockedIfObjectDoesntExist(t *testing.T, e *StorageEngine, withTombstone, withForce bool) { t.Parallel() From 6bdbe6a18b2fc666af67837a3b5ce6434ddbea96 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 22 Apr 2025 17:37:29 +0300 Subject: [PATCH 1403/1413] [#1689] adm: Fix `printSubjectInfo` method * Fix print format for primary and additional subject keys from frostfsid contract. Since the format corresponds to `neo-go wallet dump-keys` output format. Change-Id: I9ae9fd43bfb378970786b97bd3d9d7f739466ae6 Signed-off-by: Airat Arifullin --- .../internal/modules/morph/frostfsid/frostfsid.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go index 8ae606f1a3..7f777db983 100644 --- a/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go +++ b/cmd/frostfs-adm/internal/modules/morph/frostfsid/frostfsid.go @@ -1,6 +1,7 @@ package frostfsid import ( + "encoding/hex" "errors" "fmt" "math/big" @@ -604,7 +605,7 @@ func printSubjectInfo(cmd *cobra.Command, addr util.Uint160, subj *frostfsidclie cmd.Printf("Address: %s\n", address.Uint160ToString(addr)) pk := "" if subj.PrimaryKey != nil { - pk = subj.PrimaryKey.String() + pk = hex.EncodeToString(subj.PrimaryKey.Bytes()) } cmd.Printf("Primary key: %s\n", pk) cmd.Printf("Name: %s\n", subj.Name) @@ -614,7 +615,7 @@ func printSubjectInfo(cmd *cobra.Command, addr util.Uint160, subj *frostfsidclie for _, key := range subj.AdditionalKeys { k := "" if key != nil { - k = key.String() + k = hex.EncodeToString(key.Bytes()) } cmd.Printf("- %s\n", k) } From b0f39dca16c9564c6a68da874ceab705288dde9a Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Tue, 22 Apr 2025 18:14:00 +0300 Subject: [PATCH 1404/1413] [#1721] object: Make `CheckAPE` always validate bearer token * The bearer token must always be validated, regardless of whether it has been impersonated; * Fix unit-tests for tree service which check verification with bearer token. Close #1721 Change-Id: I5f715c498ae10b2e758244e60b8f21849328a04f Signed-off-by: Airat Arifullin --- pkg/services/common/ape/checker.go | 12 ++++++++---- pkg/services/tree/signature_test.go | 28 +++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index c9b0b7363a..a2e6281444 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -73,14 +73,18 @@ func New(localOverrideStorage policyengine.LocalOverrideStorage, morphChainStora // CheckAPE performs the common policy-engine check logic on a prepared request. func (c *checkerCoreImpl) CheckAPE(ctx context.Context, prm CheckPrm) error { var cr policyengine.ChainRouter - if prm.BearerToken != nil && !prm.BearerToken.Impersonate() { + if prm.BearerToken != nil { var err error if err = isValidBearer(prm.BearerToken, prm.ContainerOwner, prm.Container, prm.PublicKey, c.State); err != nil { return fmt.Errorf("bearer validation error: %w", err) } - cr, err = router.BearerChainFeedRouter(c.LocalOverrideStorage, c.MorphChainStorage, prm.BearerToken.APEOverride()) - if err != nil { - return fmt.Errorf("create chain router error: %w", err) + if prm.BearerToken.Impersonate() { + cr = policyengine.NewDefaultChainRouterWithLocalOverrides(c.MorphChainStorage, c.LocalOverrideStorage) + } else { + cr, err = router.BearerChainFeedRouter(c.LocalOverrideStorage, c.MorphChainStorage, prm.BearerToken.APEOverride()) + if err != nil { + return fmt.Errorf("create chain router error: %w", err) + } } } else { cr = policyengine.NewDefaultChainRouterWithLocalOverrides(c.MorphChainStorage, c.LocalOverrideStorage) diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index f5659d5e2d..dd37b41910 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -238,14 +238,40 @@ func TestMessageSign(t *testing.T) { t.Run("impersonate", func(t *testing.T) { cnr.Value.SetBasicACL(acl.PublicRWExtended) var bt bearer.Token + bt.SetExp(10) bt.SetImpersonate(true) + bt.SetAPEOverride(bearer.APEOverride{ + Target: ape.ChainTarget{ + TargetType: ape.TargetTypeContainer, + Name: cid1.EncodeToString(), + }, + Chains: []ape.Chain{}, + }) + require.NoError(t, bt.Sign(privs[0].PrivateKey)) + req.Body.BearerToken = bt.Marshal() + require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + }) + + t.Run("impersonate but invalid signer", func(t *testing.T) { + var bt bearer.Token + bt.SetExp(10) + bt.SetImpersonate(true) + bt.SetAPEOverride(bearer.APEOverride{ + Target: ape.ChainTarget{ + TargetType: ape.TargetTypeContainer, + Name: cid1.EncodeToString(), + }, + Chains: []ape.Chain{}, + }) require.NoError(t, bt.Sign(privs[1].PrivateKey)) req.Body.BearerToken = bt.Marshal() require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) - require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey()) From 5b6cba04cb5c3fb0589caa6e26bdc67c8ef183e2 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Fri, 18 Apr 2025 18:17:00 +0300 Subject: [PATCH 1405/1413] [#1689] node: Drop `node.relay` config It is not used and not tested properly, so drop it. Change-Id: I7c90c7391ecb4be17459415d209811ba1a693f7a Signed-off-by: Dmitrii Stepanov --- cmd/frostfs-node/attributes.go | 4 --- cmd/frostfs-node/config.go | 27 +++++---------------- cmd/frostfs-node/config/node/config.go | 8 ------ cmd/frostfs-node/config/node/config_test.go | 5 ---- cmd/frostfs-node/netmap.go | 20 +++++---------- config/example/node.env | 1 - config/example/node.json | 1 - config/example/node.yaml | 2 -- docs/storage-node-configuration.md | 2 -- 9 files changed, 12 insertions(+), 58 deletions(-) diff --git a/cmd/frostfs-node/attributes.go b/cmd/frostfs-node/attributes.go index 64c3beba72..ce8ae9662b 100644 --- a/cmd/frostfs-node/attributes.go +++ b/cmd/frostfs-node/attributes.go @@ -6,9 +6,5 @@ import ( ) func parseAttributes(c *cfg) { - if nodeconfig.Relay(c.appCfg) { - return - } - fatalOnErr(attributes.ReadNodeAttributes(&c.cfgNodeInfo.localInfo, nodeconfig.Attributes(c.appCfg))) } diff --git a/cmd/frostfs-node/config.go b/cmd/frostfs-node/config.go index b688acfde0..96274e6253 100644 --- a/cmd/frostfs-node/config.go +++ b/cmd/frostfs-node/config.go @@ -651,7 +651,6 @@ type cfgNetmap struct { state *networkState - needBootstrap bool reBoostrapTurnedOff *atomic.Bool // managed by control service in runtime } @@ -710,11 +709,9 @@ func initCfg(appCfg *config.Config) *cfg { key := nodeconfig.Key(appCfg) - relayOnly := nodeconfig.Relay(appCfg) - netState := newNetworkState() - c.shared = initShared(appCfg, key, netState, relayOnly) + c.shared = initShared(appCfg, key, netState) netState.metrics = c.metricsCollector @@ -734,7 +731,7 @@ func initCfg(appCfg *config.Config) *cfg { c.cfgFrostfsID = initFrostfsID(appCfg) - c.cfgNetmap = initNetmap(appCfg, netState, relayOnly) + c.cfgNetmap = initNetmap(appCfg, netState) c.cfgGRPC = initCfgGRPC() @@ -780,12 +777,8 @@ func initSdNotify(appCfg *config.Config) bool { return false } -func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkState, relayOnly bool) shared { - var netAddr network.AddressGroup - - if !relayOnly { - netAddr = nodeconfig.BootstrapAddresses(appCfg) - } +func initShared(appCfg *config.Config, key *keys.PrivateKey, netState *networkState) shared { + netAddr := nodeconfig.BootstrapAddresses(appCfg) persistate, err := state.NewPersistentStorage(nodeconfig.PersistentState(appCfg).Path()) fatalOnErr(err) @@ -836,18 +829,15 @@ func internalNetConfig(appCfg *config.Config, m metrics.MultinetMetrics) interna return result } -func initNetmap(appCfg *config.Config, netState *networkState, relayOnly bool) cfgNetmap { +func initNetmap(appCfg *config.Config, netState *networkState) cfgNetmap { netmapWorkerPool, err := ants.NewPool(notificationHandlerPoolSize) fatalOnErr(err) - var reBootstrapTurnedOff atomic.Bool - reBootstrapTurnedOff.Store(relayOnly) return cfgNetmap{ scriptHash: contractsconfig.Netmap(appCfg), state: netState, workerPool: netmapWorkerPool, - needBootstrap: !relayOnly, - reBoostrapTurnedOff: &reBootstrapTurnedOff, + reBoostrapTurnedOff: &atomic.Bool{}, } } @@ -1256,11 +1246,6 @@ func (c *cfg) bootstrap(ctx context.Context) error { return bootstrapOnline(ctx, c) } -// needBootstrap checks if local node should be registered in network on bootup. -func (c *cfg) needBootstrap() bool { - return c.cfgNetmap.needBootstrap -} - type dCmp struct { name string reloadFunc func() error diff --git a/cmd/frostfs-node/config/node/config.go b/cmd/frostfs-node/config/node/config.go index 81b191e966..c50718c5f5 100644 --- a/cmd/frostfs-node/config/node/config.go +++ b/cmd/frostfs-node/config/node/config.go @@ -131,14 +131,6 @@ func Attributes(c *config.Config) (attrs []string) { return } -// Relay returns the value of "relay" config parameter -// from "node" section. -// -// Returns false if the value is not set. -func Relay(c *config.Config) bool { - return config.BoolSafe(c.Sub(subsection), "relay") -} - // PersistentSessions returns structure that provides access to "persistent_sessions" // subsection of "node" section. func PersistentSessions(c *config.Config) PersistentSessionsConfig { diff --git a/cmd/frostfs-node/config/node/config_test.go b/cmd/frostfs-node/config/node/config_test.go index 7b9adecf4d..9af1dc0387 100644 --- a/cmd/frostfs-node/config/node/config_test.go +++ b/cmd/frostfs-node/config/node/config_test.go @@ -29,12 +29,10 @@ func TestNodeSection(t *testing.T) { ) attribute := Attributes(empty) - relay := Relay(empty) persisessionsPath := PersistentSessions(empty).Path() persistatePath := PersistentState(empty).Path() require.Empty(t, attribute) - require.Equal(t, false, relay) require.Equal(t, "", persisessionsPath) require.Equal(t, PersistentStatePathDefault, persistatePath) }) @@ -45,7 +43,6 @@ func TestNodeSection(t *testing.T) { key := Key(c) addrs := BootstrapAddresses(c) attributes := Attributes(c) - relay := Relay(c) wKey := Wallet(c) persisessionsPath := PersistentSessions(c).Path() persistatePath := PersistentState(c).Path() @@ -87,8 +84,6 @@ func TestNodeSection(t *testing.T) { return false }) - require.Equal(t, true, relay) - require.Len(t, attributes, 2) require.Equal(t, "Price:11", attributes[0]) require.Equal(t, "UN-LOCODE:RU MSK", attributes[1]) diff --git a/cmd/frostfs-node/netmap.go b/cmd/frostfs-node/netmap.go index 82b799e4c8..7dfb4fe12d 100644 --- a/cmd/frostfs-node/netmap.go +++ b/cmd/frostfs-node/netmap.go @@ -187,7 +187,7 @@ func addNewEpochNotificationHandlers(c *cfg) { c.updateContractNodeInfo(ctx, e) - if !c.needBootstrap() || c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470 + if c.cfgNetmap.reBoostrapTurnedOff.Load() { // fixes #470 return } @@ -209,14 +209,12 @@ func addNewEpochNotificationHandlers(c *cfg) { // bootstrapNode adds current node to the Network map. // Must be called after initNetmapService. func bootstrapNode(ctx context.Context, c *cfg) { - if c.needBootstrap() { - if c.IsMaintenance() { - c.log.Info(ctx, logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) - return - } - err := c.bootstrap(ctx) - fatalOnErrDetails("bootstrap error", err) + if c.IsMaintenance() { + c.log.Info(ctx, logs.FrostFSNodeNodeIsUnderMaintenanceSkipInitialBootstrap) + return } + err := c.bootstrap(ctx) + fatalOnErrDetails("bootstrap error", err) } func addNetmapNotificationHandler(c *cfg, sTyp string, h event.Handler) { @@ -352,8 +350,6 @@ func addNewEpochAsyncNotificationHandler(c *cfg, h event.Handler) { ) } -var errRelayBootstrap = errors.New("setting netmap status is forbidden in relay mode") - func (c *cfg) SetNetmapStatus(ctx context.Context, st control.NetmapStatus) error { switch st { default: @@ -365,10 +361,6 @@ func (c *cfg) SetNetmapStatus(ctx context.Context, st control.NetmapStatus) erro c.stopMaintenance(ctx) - if !c.needBootstrap() { - return errRelayBootstrap - } - if st == control.NetmapStatus_ONLINE { c.cfgNetmap.reBoostrapTurnedOff.Store(false) return bootstrapOnline(ctx, c) diff --git a/config/example/node.env b/config/example/node.env index e7d7a6cc86..9a24263585 100644 --- a/config/example/node.env +++ b/config/example/node.env @@ -22,7 +22,6 @@ FROSTFS_NODE_WALLET_PASSWORD=password FROSTFS_NODE_ADDRESSES="s01.frostfs.devenv:8080 /dns4/s02.frostfs.devenv/tcp/8081 grpc://127.0.0.1:8082 grpcs://localhost:8083" FROSTFS_NODE_ATTRIBUTE_0=Price:11 FROSTFS_NODE_ATTRIBUTE_1="UN-LOCODE:RU MSK" -FROSTFS_NODE_RELAY=true FROSTFS_NODE_PERSISTENT_SESSIONS_PATH=/sessions FROSTFS_NODE_PERSISTENT_STATE_PATH=/state FROSTFS_NODE_LOCODE_DB_PATH=/path/to/locode/db diff --git a/config/example/node.json b/config/example/node.json index 3f7854d98d..6b7a9c2c68 100644 --- a/config/example/node.json +++ b/config/example/node.json @@ -37,7 +37,6 @@ ], "attribute_0": "Price:11", "attribute_1": "UN-LOCODE:RU MSK", - "relay": true, "persistent_sessions": { "path": "/sessions" }, diff --git a/config/example/node.yaml b/config/example/node.yaml index 32f0cba675..2d4bc90fbf 100644 --- a/config/example/node.yaml +++ b/config/example/node.yaml @@ -34,7 +34,6 @@ node: - grpcs://localhost:8083 attribute_0: "Price:11" attribute_1: UN-LOCODE:RU MSK - relay: true # start Storage node in relay mode without bootstrapping into the Network map persistent_sessions: path: /sessions # path to persistent session tokens file of Storage node (default: in-memory sessions) persistent_state: @@ -141,7 +140,6 @@ rpc: max_ops: 10000 storage: - # note: shard configuration can be omitted for relay node (see `node.relay`) shard_ro_error_threshold: 100 # amount of errors to occur before shard is made read-only (default: 0, ignore errors) shard: diff --git a/docs/storage-node-configuration.md b/docs/storage-node-configuration.md index 14ebb53b3d..da9fdfed05 100644 --- a/docs/storage-node-configuration.md +++ b/docs/storage-node-configuration.md @@ -410,7 +410,6 @@ node: - "Price:11" - "UN-LOCODE:RU MSK" - "key:value" - relay: false persistent_sessions: path: /sessions persistent_state: @@ -424,7 +423,6 @@ node: | `wallet` | [Wallet config](#wallet-subsection) | | Wallet configuration. Has no effect if `key` is provided. | | `addresses` | `[]string` | | Addresses advertised in the netmap. | | `attribute` | `[]string` | | Node attributes as a list of key-value pairs in `:` format. | -| `relay` | `bool` | | Enable relay mode. | | `persistent_sessions` | [Persistent sessions config](#persistent_sessions-subsection) | | Persistent session token store configuration. | | `persistent_state` | [Persistent state config](#persistent_state-subsection) | | Persistent state configuration. | | `locode_db_path` | `string` | empty | Path to UN/LOCODE [database](https://git.frostfs.info/TrueCloudLab/frostfs-locode-db/) for FrostFS. | From 652237500fb9e1618eb66310d3f2a51c599a033e Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Thu, 24 Apr 2025 16:54:47 +0300 Subject: [PATCH 1406/1413] [#1689] tree: Dial tree service after create connection on sync Background trees sync creates grpc connection with `grpc.WithDefaultCallOptions(grpc.WaitForReady(true))` option. When grpc connection created with this option, client will wait until a connection becomes available or the RPC's deadline is reached. As background sync has no timeout in context, so in case of client is in TRANSIENT_FAILURE RPC call will hang forever. Change-Id: I17c8c1d2779bb81c541f47dd0e558e0b8ed2e7c1 Signed-off-by: Dmitrii Stepanov --- pkg/services/tree/cache.go | 36 ++++++------------------------------ pkg/services/tree/sync.go | 28 +++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/pkg/services/tree/cache.go b/pkg/services/tree/cache.go index 462c8554f8..a117007719 100644 --- a/pkg/services/tree/cache.go +++ b/pkg/services/tree/cache.go @@ -66,7 +66,12 @@ func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceCl } } - cc, err := c.dialTreeService(ctx, netmapAddr) + var netAddr network.Address + if err := netAddr.FromString(netmapAddr); err != nil { + return nil, err + } + + cc, err := dialTreeService(ctx, netAddr, c.key, c.ds) lastTry := time.Now() c.Lock() @@ -83,32 +88,3 @@ func (c *clientCache) get(ctx context.Context, netmapAddr string) (TreeServiceCl return NewTreeServiceClient(cc), nil } - -func (c *clientCache) dialTreeService(ctx context.Context, netmapAddr string) (*grpc.ClientConn, error) { - var netAddr network.Address - if err := netAddr.FromString(netmapAddr); err != nil { - return nil, err - } - - cc, err := createConnection(netAddr, grpc.WithContextDialer(c.ds.GrpcContextDialer())) - if err != nil { - return nil, err - } - - ctx, cancel := context.WithTimeout(ctx, defaultClientConnectTimeout) - defer cancel() - - req := &HealthcheckRequest{ - Body: &HealthcheckRequest_Body{}, - } - if err := SignMessage(req, c.key); err != nil { - return nil, err - } - - // perform some request to check connection - if _, err := NewTreeServiceClient(cc).Healthcheck(ctx, req); err != nil { - _ = cc.Close() - return nil, err - } - return cc, nil -} diff --git a/pkg/services/tree/sync.go b/pkg/services/tree/sync.go index d4040337d7..af355639f2 100644 --- a/pkg/services/tree/sync.go +++ b/pkg/services/tree/sync.go @@ -2,6 +2,7 @@ package tree import ( "context" + "crypto/ecdsa" "crypto/sha256" "crypto/tls" "errors" @@ -14,6 +15,7 @@ import ( "time" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs" + "git.frostfs.info/TrueCloudLab/frostfs-node/internal/net" "git.frostfs.info/TrueCloudLab/frostfs-node/internal/qos" containerCore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" @@ -304,7 +306,7 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, continue } - cc, err := createConnection(a, grpc.WithContextDialer(s.ds.GrpcContextDialer())) + cc, err := dialTreeService(ctx, a, s.key, s.ds) if err != nil { s.log.Warn(ctx, logs.TreeFailedToConnectForTreeSynchronization, zap.Error(err), zap.String("address", addr)) continue @@ -342,6 +344,30 @@ func (s *Service) synchronizeTree(ctx context.Context, cid cid.ID, from uint64, return from } +func dialTreeService(ctx context.Context, netAddr network.Address, key *ecdsa.PrivateKey, ds *net.DialerSource) (*grpc.ClientConn, error) { + cc, err := createConnection(netAddr, grpc.WithContextDialer(ds.GrpcContextDialer())) + if err != nil { + return nil, err + } + + ctx, cancel := context.WithTimeout(ctx, defaultClientConnectTimeout) + defer cancel() + + req := &HealthcheckRequest{ + Body: &HealthcheckRequest_Body{}, + } + if err := SignMessage(req, key); err != nil { + return nil, err + } + + // perform some request to check connection + if _, err := NewTreeServiceClient(cc).Healthcheck(ctx, req); err != nil { + _ = cc.Close() + return nil, err + } + return cc, nil +} + func createConnection(a network.Address, opts ...grpc.DialOption) (*grpc.ClientConn, error) { host, isTLS, err := client.ParseURI(a.URIAddr()) if err != nil { From 8e2f919df0fe4525bf25fcbe1fa11f6af642637e Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 28 Apr 2025 20:07:56 +0300 Subject: [PATCH 1407/1413] [#1689] go.mod: Bump SDK version * Fix `APEOverride` method usage in ape checker. * Fix linter errors: factor out deprecated methods and packages. Change-Id: I8c939f4c58c2a4e3c4e795c7224d935d40ce6f24 Signed-off-by: Airat Arifullin --- cmd/frostfs-cli/modules/container/get.go | 4 +- cmd/frostfs-cli/modules/container/list.go | 4 +- go.mod | 24 ++++----- go.sum | 52 +++++++++---------- pkg/core/container/util.go | 4 +- .../internal/testutil/generators.go | 7 +-- .../internal/testutil/object.go | 2 +- pkg/services/common/ape/checker.go | 5 +- .../populate-metabase/internal/generate.go | 5 +- 9 files changed, 55 insertions(+), 52 deletions(-) diff --git a/cmd/frostfs-cli/modules/container/get.go b/cmd/frostfs-cli/modules/container/get.go index 8c4ab14f82..fac6eb2cdf 100644 --- a/cmd/frostfs-cli/modules/container/get.go +++ b/cmd/frostfs-cli/modules/container/get.go @@ -93,9 +93,9 @@ func prettyPrintContainer(cmd *cobra.Command, cnr container.Container, jsonEncod cmd.Println("created:", container.CreatedAt(cnr)) cmd.Println("attributes:") - cnr.IterateAttributes(func(key, val string) { + for key, val := range cnr.Attributes() { cmd.Printf("\t%s=%s\n", key, val) - }) + } cmd.Println("placement policy:") commonCmd.ExitOnErr(cmd, "write policy: %w", cnr.PlacementPolicy().WriteStringTo((*stringWriter)(cmd))) diff --git a/cmd/frostfs-cli/modules/container/list.go b/cmd/frostfs-cli/modules/container/list.go index bbb8da8401..e4a023d91e 100644 --- a/cmd/frostfs-cli/modules/container/list.go +++ b/cmd/frostfs-cli/modules/container/list.go @@ -102,9 +102,9 @@ func printContainer(cmd *cobra.Command, prmGet internalclient.GetContainerPrm, i cmd.Println(id.String()) if flagVarListPrintAttr { - cnr.IterateUserAttributes(func(key, val string) { + for key, val := range cnr.Attributes() { cmd.Printf(" %s: %s\n", key, val) - }) + } } } diff --git a/go.mod b/go.mod index 5ed4a90be3..fb45c38742 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.frostfs.info/TrueCloudLab/frostfs-node -go 1.23 +go 1.23.0 require ( code.gitea.io/sdk/gitea v0.17.1 @@ -9,7 +9,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-locode-db v0.5.2 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248 git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47 - git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250404152210-6458c11e833d + git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250428134706-8822aedbbbaa git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250402100642-acd94d200f88 @@ -28,7 +28,7 @@ require ( github.com/klauspost/compress v1.17.4 github.com/mailru/easyjson v0.7.7 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.3 github.com/olekukonko/tablewriter v0.0.5 github.com/panjf2000/ants/v2 v2.9.0 @@ -44,10 +44,9 @@ require ( go.opentelemetry.io/otel v1.31.0 go.opentelemetry.io/otel/trace v1.31.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/sync v0.10.0 - golang.org/x/sys v0.28.0 - golang.org/x/term v0.27.0 + golang.org/x/sync v0.12.0 + golang.org/x/sys v0.31.0 + golang.org/x/term v0.30.0 google.golang.org/grpc v1.69.2 google.golang.org/protobuf v1.36.1 gopkg.in/yaml.v3 v3.0.1 @@ -86,9 +85,9 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/holiman/uint256 v1.2.4 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/ipfs/go-cid v0.4.1 // indirect + github.com/ipfs/go-cid v0.5.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/klauspost/reedsolomon v1.12.1 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -124,13 +123,14 @@ require ( go.opentelemetry.io/otel/sdk v1.31.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // 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-20250305212735-054e65f0b394 // indirect golang.org/x/net v0.30.0 // indirect - golang.org/x/text v0.21.0 // indirect + golang.org/x/text v0.23.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 // indirect gopkg.in/ini.v1 v1.67.0 // indirect - lukechampine.com/blake3 v1.2.1 // indirect + lukechampine.com/blake3 v1.4.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 38aba9bdee..acc26af36b 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20250321063246-93b681a20248/go.mod h1:kbwB4v2o6RyOfCo9kEFeUDZIX3LKhmS0yXPrtvzkQ1g= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47 h1:O2c3VOlaGZ862hf2ZPLBMdTG6vGJzhIgDvFEFGfntzU= git.frostfs.info/TrueCloudLab/frostfs-qos v0.0.0-20250331080422-b5ed0b6eff47/go.mod h1:PCijYq4oa8vKtIEcUX6jRiszI6XAW+nBwU+T1kB4d1U= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250404152210-6458c11e833d h1:ZLKDupw362Ciing7kdIZhDYGMyo2QZyJ6sS/8X9QWJ0= -git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250404152210-6458c11e833d/go.mod h1:2PWt5GwJTnhjHp+mankcfCeAJBMn7puxPm+RS+lliVk= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250428134706-8822aedbbbaa h1:ttJxiw5+Wti3outhaPFaLGwCinmUTQgyVQfD/sIU5sg= +git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250428134706-8822aedbbbaa/go.mod h1:mimnb6yQUBLLQ8PboNc5ZP8iz4VMhFRKrfZcjfR9CVs= git.frostfs.info/TrueCloudLab/hrw v1.2.1 h1:ccBRK21rFvY5R1WotI6LNoPlizk7qSvdfD8lNIRudVc= git.frostfs.info/TrueCloudLab/hrw v1.2.1/go.mod h1:C1Ygde2n843yTZEQ0FP69jYiuaYV0kriLvP4zm8JuvM= git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/960fWeyn2AFHwQUwDsWB3sbP6lTEnFnMzLMM6tx6N8= @@ -145,14 +145,14 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= -github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/ipfs/go-cid v0.5.0 h1:goEKKhaGm0ul11IHA7I6p1GmKz8kEYniqFopaB5Otwg= +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/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= +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/go.mod h1:nEi5Kjb6QqtbofI6s+cbG/j1da11c96IBYBSnVGtuBs= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -192,8 +192,8 @@ github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aG github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= 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-multiaddr v0.14.0 h1:bfrHrJhrRuh/NXH5mCnemjpbGjzRw/b+tJFOD41g2tU= -github.com/multiformats/go-multiaddr v0.14.0/go.mod h1:6EkVAxtznq2yC3QT5CM1UTAwG0GTP3EWAIcjHuzQ+r4= +github.com/multiformats/go-multiaddr v0.15.0 h1:zB/HeaI/apcZiTDwhY5YqMvNVl/oQYvs3XySU+qeAVo= +github.com/multiformats/go-multiaddr v0.15.0/go.mod h1:JSVUmXDjsVFiW7RjIFMP7+Ev+h1DTbiJgVeTV/tcmP0= 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-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= @@ -324,15 +324,15 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= +golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= +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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -353,8 +353,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -381,16 +381,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -398,15 +398,15 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= +golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -445,7 +445,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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 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.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w= +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/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/pkg/core/container/util.go b/pkg/core/container/util.go index a24b369449..61c568052e 100644 --- a/pkg/core/container/util.go +++ b/pkg/core/container/util.go @@ -26,10 +26,10 @@ func WasRemoved(ctx context.Context, s Source, cid cid.ID) (bool, error) { // IsIndexedContainer returns True if container attributes should be indexed. func IsIndexedContainer(cnr containerSDK.Container) bool { var isS3Container bool - cnr.IterateAttributes(func(key, _ string) { + for key := range cnr.Attributes() { if key == ".s3-location-constraint" { isS3Container = true } - }) + } return !isS3Container } diff --git a/pkg/local_object_storage/internal/testutil/generators.go b/pkg/local_object_storage/internal/testutil/generators.go index 383c596af3..52b199b0b5 100644 --- a/pkg/local_object_storage/internal/testutil/generators.go +++ b/pkg/local_object_storage/internal/testutil/generators.go @@ -1,7 +1,9 @@ package testutil import ( + cryptorand "crypto/rand" "encoding/binary" + "math/rand" "sync/atomic" "testing" @@ -9,7 +11,6 @@ import ( objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "github.com/stretchr/testify/require" - "golang.org/x/exp/rand" ) // AddressGenerator is the interface of types that generate object addresses. @@ -61,7 +62,7 @@ var _ ObjectGenerator = &SeqObjGenerator{} func generateObjectWithOIDWithCIDWithSize(oid oid.ID, cid cid.ID, sz uint64) *objectSDK.Object { data := make([]byte, sz) - _, _ = rand.Read(data) + _, _ = cryptorand.Read(data) obj := GenerateObjectWithCIDWithPayload(cid, data) obj.SetID(oid) return obj @@ -82,7 +83,7 @@ var _ ObjectGenerator = &RandObjGenerator{} func (g *RandObjGenerator) Next() *objectSDK.Object { var id oid.ID - _, _ = rand.Read(id[:]) + _, _ = cryptorand.Read(id[:]) return generateObjectWithOIDWithCIDWithSize(id, cid.ID{}, g.ObjSize) } diff --git a/pkg/local_object_storage/internal/testutil/object.go b/pkg/local_object_storage/internal/testutil/object.go index 60e9211d5d..1087e40be5 100644 --- a/pkg/local_object_storage/internal/testutil/object.go +++ b/pkg/local_object_storage/internal/testutil/object.go @@ -1,6 +1,7 @@ package testutil import ( + "crypto/rand" "crypto/sha256" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" @@ -11,7 +12,6 @@ import ( usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "git.frostfs.info/TrueCloudLab/tzhash/tz" - "golang.org/x/exp/rand" ) const defaultDataSize = 32 diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index a2e6281444..02c1e2ee12 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -81,7 +81,8 @@ func (c *checkerCoreImpl) CheckAPE(ctx context.Context, prm CheckPrm) error { if prm.BearerToken.Impersonate() { cr = policyengine.NewDefaultChainRouterWithLocalOverrides(c.MorphChainStorage, c.LocalOverrideStorage) } else { - cr, err = router.BearerChainFeedRouter(c.LocalOverrideStorage, c.MorphChainStorage, prm.BearerToken.APEOverride()) + override, _ := prm.BearerToken.APEOverride() + cr, err = router.BearerChainFeedRouter(c.LocalOverrideStorage, c.MorphChainStorage, override) if err != nil { return fmt.Errorf("create chain router error: %w", err) } @@ -130,7 +131,7 @@ func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKe } // Check for ape overrides defined in the bearer token. - apeOverride := token.APEOverride() + apeOverride, _ := token.APEOverride() if len(apeOverride.Chains) > 0 && apeOverride.Target.TargetType != ape.TargetTypeContainer { return fmt.Errorf("%w: %s", errInvalidTargetType, apeOverride.Target.TargetType.ToV2().String()) } diff --git a/scripts/populate-metabase/internal/generate.go b/scripts/populate-metabase/internal/generate.go index f2f8881cfd..39a420358e 100644 --- a/scripts/populate-metabase/internal/generate.go +++ b/scripts/populate-metabase/internal/generate.go @@ -1,8 +1,10 @@ package internal import ( + cryptorand "crypto/rand" "crypto/sha256" "fmt" + "math/rand" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -14,14 +16,13 @@ import ( usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version" "git.frostfs.info/TrueCloudLab/tzhash/tz" - "golang.org/x/exp/rand" ) func GeneratePayloadPool(count uint, size uint) [][]byte { var pool [][]byte for range count { payload := make([]byte, size) - _, _ = rand.Read(payload) + _, _ = cryptorand.Read(payload) pool = append(pool, payload) } From 64b46746e409a40a93a41c030a646d69fbf45282 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 28 Apr 2025 20:10:09 +0300 Subject: [PATCH 1408/1413] [#1689] ape: Fix validation for overrides in bearer * APE-overrides are optional for bearer. So, it should validate only set override; * Bearer can set overrides for containers, not only the one container - validation expects for any target type for set override. Basically, APE-overrides for all container must be set for namespace target; * Add unit-test cases to check bearer token validation. Change-Id: I6b8e19eb73d24f8cd8799bf99b6c551287da67d9 Signed-off-by: Airat Arifullin --- pkg/services/common/ape/checker.go | 32 ++++++++------- pkg/services/tree/signature_test.go | 61 +++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 15 deletions(-) diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index 02c1e2ee12..fcd3efa444 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -20,7 +20,6 @@ import ( ) var ( - errInvalidTargetType = errors.New("bearer token defines non-container target override") errBearerExpired = errors.New("bearer token has expired") errBearerInvalidSignature = errors.New("bearer token has invalid signature") errBearerInvalidContainerID = errors.New("bearer token was created for another container") @@ -81,7 +80,10 @@ func (c *checkerCoreImpl) CheckAPE(ctx context.Context, prm CheckPrm) error { if prm.BearerToken.Impersonate() { cr = policyengine.NewDefaultChainRouterWithLocalOverrides(c.MorphChainStorage, c.LocalOverrideStorage) } else { - override, _ := prm.BearerToken.APEOverride() + override, isSet := prm.BearerToken.APEOverride() + if !isSet { + return errors.New("expected for override within bearer") + } cr, err = router.BearerChainFeedRouter(c.LocalOverrideStorage, c.MorphChainStorage, override) if err != nil { return fmt.Errorf("create chain router error: %w", err) @@ -131,19 +133,19 @@ func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKe } // Check for ape overrides defined in the bearer token. - apeOverride, _ := token.APEOverride() - if len(apeOverride.Chains) > 0 && apeOverride.Target.TargetType != ape.TargetTypeContainer { - return fmt.Errorf("%w: %s", errInvalidTargetType, apeOverride.Target.TargetType.ToV2().String()) - } - - // Then check if container is either empty or equal to the container in the request. - var targetCnr cid.ID - err := targetCnr.DecodeString(apeOverride.Target.Name) - if err != nil { - return fmt.Errorf("invalid cid format: %s", apeOverride.Target.Name) - } - if !cntID.Equals(targetCnr) { - return errBearerInvalidContainerID + if apeOverride, isSet := token.APEOverride(); isSet { + switch apeOverride.Target.TargetType { + case ape.TargetTypeContainer: + var targetCnr cid.ID + err := targetCnr.DecodeString(apeOverride.Target.Name) + if err != nil { + return fmt.Errorf("invalid cid format: %s", apeOverride.Target.Name) + } + if !cntID.Equals(targetCnr) { + return errBearerInvalidContainerID + } + default: + } } // Then check if container owner signed this token. diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index dd37b41910..13a5c13954 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -235,6 +235,48 @@ func TestMessageSign(t *testing.T) { require.Error(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) }) + t.Run("omit override within bt", func(t *testing.T) { + t.Run("personated", func(t *testing.T) { + bt := testBearerTokenNoOverride() + require.NoError(t, bt.Sign(privs[0].PrivateKey)) + req.Body.BearerToken = bt.Marshal() + + require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) + require.ErrorContains(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut), "expected for override") + }) + + t.Run("impersonated", func(t *testing.T) { + bt := testBearerTokenNoOverride() + bt.SetImpersonate(true) + require.NoError(t, bt.Sign(privs[0].PrivateKey)) + req.Body.BearerToken = bt.Marshal() + + require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + }) + }) + + t.Run("invalid override within bearer token", func(t *testing.T) { + t.Run("personated", func(t *testing.T) { + bt := testBearerTokenCorruptOverride(privs[1].PublicKey(), privs[2].PublicKey()) + require.NoError(t, bt.Sign(privs[0].PrivateKey)) + req.Body.BearerToken = bt.Marshal() + + require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) + require.ErrorContains(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut), "invalid cid") + }) + + t.Run("impersonated", func(t *testing.T) { + bt := testBearerTokenCorruptOverride(privs[1].PublicKey(), privs[2].PublicKey()) + bt.SetImpersonate(true) + require.NoError(t, bt.Sign(privs[0].PrivateKey)) + req.Body.BearerToken = bt.Marshal() + + require.NoError(t, SignMessage(req, &privs[0].PrivateKey)) + require.ErrorContains(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut), "invalid cid") + }) + }) + t.Run("impersonate", func(t *testing.T) { cnr.Value.SetBasicACL(acl.PublicRWExtended) var bt bearer.Token @@ -311,6 +353,25 @@ func testBearerToken(cid cid.ID, forPutGet, forGet *keys.PublicKey) bearer.Token return b } +func testBearerTokenCorruptOverride(forPutGet, forGet *keys.PublicKey) bearer.Token { + var b bearer.Token + b.SetExp(currentEpoch + 1) + b.SetAPEOverride(bearer.APEOverride{ + Target: ape.ChainTarget{ + TargetType: ape.TargetTypeContainer, + }, + Chains: []ape.Chain{{Raw: testChain(forPutGet, forGet).Bytes()}}, + }) + + return b +} + +func testBearerTokenNoOverride() bearer.Token { + var b bearer.Token + b.SetExp(currentEpoch + 1) + return b +} + func testChain(forPutGet, forGet *keys.PublicKey) *chain.Chain { ruleGet := chain.Rule{ Status: chain.Allow, From e0a4835ea3eb1e2dfda921319c86f4de69b686fe Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 24 Apr 2025 18:48:24 +0300 Subject: [PATCH 1409/1413] [#1689] go.mod: Bump `policy-engine` package version * The bumped version of `policy-engine` package introduces new native schema properties for resource. Change-Id: If392c51415cff66c46798a788a2f0944f15900d3 Signed-off-by: Airat Arifullin --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fb45c38742..6f19509369 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,7 @@ require ( git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20250428134706-8822aedbbbaa git.frostfs.info/TrueCloudLab/hrw v1.2.1 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 - git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250402100642-acd94d200f88 + git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250425083815-09ff3bf14991 git.frostfs.info/TrueCloudLab/tzhash v1.8.0 git.frostfs.info/TrueCloudLab/zapjournald v0.0.0-20240124114243-cb2e66427d02 github.com/VictoriaMetrics/easyproto v0.1.4 diff --git a/go.sum b/go.sum index acc26af36b..5b075f60a5 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972 h1:/96 git.frostfs.info/TrueCloudLab/multinet v0.0.0-20241015075604-6cb0d80e0972/go.mod h1:2hM42MBrlhvN6XToaW6OWNk5ZLcu1FhaukGgxtfpDDI= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07 h1:gPaqGsk6gSWQyNVjaStydfUz6Z/loHc9XyvGrJ5qSPY= git.frostfs.info/TrueCloudLab/neoneo-go v0.106.1-0.20241015133823-8aee80dbdc07/go.mod h1:bZyJexBlrja4ngxiBgo8by5pVHuAbhg9l09/8yVGDyg= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250402100642-acd94d200f88 h1:V0a7ia84ZpSM2YxpJq1SKLQfeYmsqFWqcxwweBHJIzc= -git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250402100642-acd94d200f88/go.mod h1:GZTk55RI4dKzsK6BCn5h2xxE28UHNfgoq/NJxW/LQ6A= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250425083815-09ff3bf14991 h1:eTefR8y2y9cg7X5kybIcXDdmABfk/3A2awdmFD3zOsA= +git.frostfs.info/TrueCloudLab/policy-engine v0.0.0-20250425083815-09ff3bf14991/go.mod h1:GZTk55RI4dKzsK6BCn5h2xxE28UHNfgoq/NJxW/LQ6A= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 h1:M2KR3iBj7WpY3hP10IevfIB9MURr4O9mwVfJ+SjT3HA= git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0/go.mod h1:okpbKfVYf/BpejtfFTfhZqFP+sZ8rsHrP8Rr/jYPNRc= git.frostfs.info/TrueCloudLab/tzhash v1.8.0 h1:UFMnUIk0Zh17m8rjGHJMqku2hCgaXDqjqZzS4gsb4UA= From 6cedfbc17a871f6d96110b63071760488dbccb19 Mon Sep 17 00:00:00 2001 From: Dmitrii Stepanov Date: Mon, 5 May 2025 16:20:13 +0300 Subject: [PATCH 1410/1413] [#1689] getSvc: Stop node addresses iteratation on logical errors Before this fix: If first node address returns non-logical error (context deadline exceeded, context canceled, etc), then this error will override logical error from second node address. Change-Id: Ib30d0209828fdc83b55308ca2e33a361aa4caee6 Signed-off-by: Dmitrii Stepanov --- pkg/services/object/get/v2/util.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/pkg/services/object/get/v2/util.go b/pkg/services/object/get/v2/util.go index 4b7dcc530b..e699a3779a 100644 --- a/pkg/services/object/get/v2/util.go +++ b/pkg/services/object/get/v2/util.go @@ -3,6 +3,7 @@ package getsvc import ( "context" "crypto/sha256" + "errors" "hash" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" @@ -358,19 +359,20 @@ func groupAddressRequestForwarder(f func(context.Context, network.Address, clien info.AddressGroup().IterateAddresses(func(addr network.Address) (stop bool) { var err error - - defer func() { - stop = err == nil - - if stop || firstErr == nil { - firstErr = err - } - - // would be nice to log otherwise - }() - res, err = f(ctx, addr, c, key) + // non-status logic error that could be returned + // from the SDK client; should not be considered + // as a connection error + var siErr *objectSDK.SplitInfoError + var eiErr *objectSDK.ECInfoError + + stop = err == nil || errors.As(err, &siErr) || errors.As(err, &eiErr) + + if stop || firstErr == nil { + firstErr = err + } + return }) From a5f76a609deb8a414685015fb7a39d5c99ad085c Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Mon, 5 May 2025 16:33:07 +0300 Subject: [PATCH 1411/1413] [#1689] ape: Fix bearer token validation * Request's sender is set to the token's issuer's public key if it's impersonated. Thus, token's user assertion must be fixed; * Add unit-test: check impersonated token but set user with `ForUser`. Change-Id: I5e299947761e237b1b4b339cf2d1278ef518239d Signed-off-by: Airat Arifullin --- pkg/services/common/ape/checker.go | 12 ++++++++++-- pkg/services/tree/signature_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/pkg/services/common/ape/checker.go b/pkg/services/common/ape/checker.go index fcd3efa444..eb62633206 100644 --- a/pkg/services/common/ape/checker.go +++ b/pkg/services/common/ape/checker.go @@ -157,8 +157,16 @@ func isValidBearer(token *bearer.Token, ownerCnr user.ID, cntID cid.ID, publicKe var usrSender user.ID user.IDFromKey(&usrSender, (ecdsa.PublicKey)(*publicKey)) - if !token.AssertUser(usrSender) { - return errBearerInvalidOwner + // Then check if sender is valid. If it is an impersonated token, the sender is set to the token's issuer's + // public key, but not the actual sender. + if !token.Impersonate() { + if !token.AssertUser(usrSender) { + return errBearerInvalidOwner + } + } else { + if !bearer.ResolveIssuer(*token).Equals(usrSender) { + return errBearerInvalidOwner + } } return nil diff --git a/pkg/services/tree/signature_test.go b/pkg/services/tree/signature_test.go index 13a5c13954..8815c227f3 100644 --- a/pkg/services/tree/signature_test.go +++ b/pkg/services/tree/signature_test.go @@ -297,6 +297,30 @@ func TestMessageSign(t *testing.T) { require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) }) + t.Run("impersonate, but target user is still set", func(t *testing.T) { + var bt bearer.Token + bt.SetExp(10) + bt.SetImpersonate(true) + + var reqSigner user.ID + user.IDFromKey(&reqSigner, (ecdsa.PublicKey)(*privs[1].PublicKey())) + + bt.ForUser(reqSigner) + bt.SetAPEOverride(bearer.APEOverride{ + Target: ape.ChainTarget{ + TargetType: ape.TargetTypeContainer, + Name: cid1.EncodeToString(), + }, + Chains: []ape.Chain{}, + }) + require.NoError(t, bt.Sign(privs[0].PrivateKey)) + req.Body.BearerToken = bt.Marshal() + + require.NoError(t, SignMessage(req, &privs[1].PrivateKey)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectPut)) + require.NoError(t, s.verifyClient(context.Background(), req, cid1, versionTreeID, req.GetBody().GetBearerToken(), acl.OpObjectGet)) + }) + t.Run("impersonate but invalid signer", func(t *testing.T) { var bt bearer.Token bt.SetExp(10) From c2a495814f32b9ccfe3efedff76937ba03a61858 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 24 Apr 2025 18:57:23 +0300 Subject: [PATCH 1412/1413] [#1689] object: Make APE middleware form container system attributes * Extract container system attributes into request info; * Form APE-resource proprties from the extracted attributes; * Fix unit-test. Change-Id: I8fbd9a167ad05af0e75df350ac882b866da7bdcb Signed-off-by: Airat Arifullin --- pkg/services/object/ape/checker.go | 3 + pkg/services/object/ape/metadata.go | 7 + pkg/services/object/ape/request.go | 9 +- pkg/services/object/ape/request_test.go | 20 ++- pkg/services/object/ape/service.go | 177 +++++++++++++----------- 5 files changed, 128 insertions(+), 88 deletions(-) diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index b96757def3..bb6067a373 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -64,6 +64,9 @@ type Prm struct { // An encoded container's owner user ID. ContainerOwner user.ID + // Attributes defined for the container. + ContainerAttributes map[string]string + // The request's bearer token. It is used in order to check APE overrides with the token. BearerToken *bearer.Token diff --git a/pkg/services/object/ape/metadata.go b/pkg/services/object/ape/metadata.go index b37c3b6f8b..102985aa68 100644 --- a/pkg/services/object/ape/metadata.go +++ b/pkg/services/object/ape/metadata.go @@ -63,6 +63,8 @@ type RequestInfo struct { ContainerOwner user.ID + ContainerAttributes map[string]string + // Namespace defines to which namespace a container is belonged. Namespace string @@ -131,6 +133,11 @@ func (e *extractor) GetRequestInfo(ctx context.Context, m Metadata, method strin ri.Role = nativeSchemaRole(res.Role) ri.ContainerOwner = cnr.Value.Owner() + ri.ContainerAttributes = map[string]string{} + for key, val := range cnr.Value.Attributes() { + ri.ContainerAttributes[key] = val + } + cnrNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(cnr.Value).Zone(), ".ns") if hasNamespace { ri.Namespace = cnrNamespace diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 001a5f71e6..39dd7f4763 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -57,11 +57,16 @@ func resourceName(cid cid.ID, oid *oid.ID, namespace string) string { } // objectProperties collects object properties from address parameters and a header if it is passed. -func objectProperties(cnr cid.ID, oid *oid.ID, cnrOwner user.ID, header *objectV2.Header) map[string]string { +func objectProperties(cnr cid.ID, oid *oid.ID, cnrOwner user.ID, cnrAttrs map[string]string, header *objectV2.Header) map[string]string { objectProps := map[string]string{ nativeschema.PropertyKeyObjectContainerID: cnr.EncodeToString(), } + for attrName, attrValue := range cnrAttrs { + prop := fmt.Sprintf(nativeschema.PropertyKeyFormatObjectContainerAttribute, attrName) + objectProps[prop] = attrValue + } + objectProps[nativeschema.PropertyKeyContainerOwnerID] = cnrOwner.EncodeToString() if oid != nil { @@ -155,7 +160,7 @@ func (c *checkerImpl) newAPERequest(ctx context.Context, prm Prm) (aperequest.Re prm.Method, aperequest.NewResource( resourceName(prm.Container, prm.Object, prm.Namespace), - objectProperties(prm.Container, prm.Object, prm.ContainerOwner, header), + objectProperties(prm.Container, prm.Object, prm.ContainerOwner, prm.ContainerAttributes, header), ), reqProps, ), nil diff --git a/pkg/services/object/ape/request_test.go b/pkg/services/object/ape/request_test.go index f270bf97db..fcf7c4c40f 100644 --- a/pkg/services/object/ape/request_test.go +++ b/pkg/services/object/ape/request_test.go @@ -7,6 +7,7 @@ import ( "testing" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" + cnrV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/container" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/object" checksumtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum/test" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -22,8 +23,17 @@ const ( testOwnerID = "NURFM8PWbLA2aLt2vrD8q4FyfAdgESwM8y" incomingIP = "192.92.33.1" + + testSysAttrName = "unittest" + + testSysAttrZone = "eggplant" ) +var containerAttrs = map[string]string{ + cnrV2.SysAttributeName: testSysAttrName, + cnrV2.SysAttributeZone: testSysAttrZone, +} + func ctxWithPeerInfo() context.Context { return peer.NewContext(context.Background(), &peer.Peer{ Addr: &net.TCPAddr{ @@ -105,7 +115,7 @@ func TestObjectProperties(t *testing.T) { var testCnrOwner user.ID require.NoError(t, testCnrOwner.DecodeString(testOwnerID)) - props := objectProperties(cnr, obj, testCnrOwner, header.ToV2().GetHeader()) + props := objectProperties(cnr, obj, testCnrOwner, containerAttrs, header.ToV2().GetHeader()) require.Equal(t, test.container, props[nativeschema.PropertyKeyObjectContainerID]) require.Equal(t, testOwnerID, props[nativeschema.PropertyKeyContainerOwnerID]) @@ -124,6 +134,8 @@ func TestObjectProperties(t *testing.T) { require.Equal(t, test.header.typ.String(), props[nativeschema.PropertyKeyObjectType]) require.Equal(t, test.header.payloadChecksum.String(), props[nativeschema.PropertyKeyObjectPayloadHash]) require.Equal(t, test.header.payloadHomomorphicHash.String(), props[nativeschema.PropertyKeyObjectHomomorphicHash]) + require.Equal(t, containerAttrs[cnrV2.SysAttributeName], props[fmt.Sprintf(nativeschema.PropertyKeyFormatObjectContainerAttribute, cnrV2.SysAttributeName)]) + require.Equal(t, containerAttrs[cnrV2.SysAttributeZone], props[fmt.Sprintf(nativeschema.PropertyKeyFormatObjectContainerAttribute, cnrV2.SysAttributeZone)]) for _, attr := range test.header.attributes { require.Equal(t, attr.val, props[attr.key]) @@ -245,6 +257,10 @@ func TestNewAPERequest(t *testing.T) { Role: role, SenderKey: senderKey, ContainerOwner: testCnrOwner, + ContainerAttributes: map[string]string{ + cnrV2.SysAttributeZone: testSysAttrZone, + cnrV2.SysAttributeName: testSysAttrName, + }, } headerSource := newHeaderProviderMock() @@ -277,7 +293,7 @@ func TestNewAPERequest(t *testing.T) { method, aperequest.NewResource( resourceName(cnr, obj, prm.Namespace), - objectProperties(cnr, obj, testCnrOwner, func() *objectV2.Header { + objectProperties(cnr, obj, testCnrOwner, containerAttrs, func() *objectV2.Header { if headerObjSDK != nil { return headerObjSDK.ToV2().GetHeader() } diff --git a/pkg/services/object/ape/service.go b/pkg/services/object/ape/service.go index e199e26384..5e04843f37 100644 --- a/pkg/services/object/ape/service.go +++ b/pkg/services/object/ape/service.go @@ -86,16 +86,17 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error { } prm := Prm{ - Namespace: g.reqInfo.Namespace, - Container: cnrID, - Object: objID, - Header: partInit.GetHeader(), - Method: nativeschema.MethodGetObject, - SenderKey: g.reqInfo.SenderKey, - ContainerOwner: g.reqInfo.ContainerOwner, - Role: g.reqInfo.Role, - BearerToken: g.metadata.BearerToken, - XHeaders: resp.GetMetaHeader().GetXHeaders(), + Namespace: g.reqInfo.Namespace, + Container: cnrID, + Object: objID, + Header: partInit.GetHeader(), + Method: nativeschema.MethodGetObject, + SenderKey: g.reqInfo.SenderKey, + ContainerOwner: g.reqInfo.ContainerOwner, + ContainerAttributes: g.reqInfo.ContainerAttributes, + Role: g.reqInfo.Role, + BearerToken: g.metadata.BearerToken, + XHeaders: resp.GetMetaHeader().GetXHeaders(), } if err := g.apeChecker.CheckAPE(g.Context(), prm); err != nil { @@ -142,16 +143,17 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR } prm := Prm{ - Namespace: reqInfo.Namespace, - Container: md.Container, - Object: md.Object, - Header: partInit.GetHeader(), - Method: nativeschema.MethodPutObject, - SenderKey: reqInfo.SenderKey, - ContainerOwner: reqInfo.ContainerOwner, - Role: reqInfo.Role, - BearerToken: md.BearerToken, - XHeaders: md.MetaHeader.GetXHeaders(), + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, + Header: partInit.GetHeader(), + Method: nativeschema.MethodPutObject, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + ContainerAttributes: reqInfo.ContainerAttributes, + Role: reqInfo.Role, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -200,15 +202,16 @@ func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.Pa } prm := Prm{ - Namespace: reqInfo.Namespace, - Container: md.Container, - Object: md.Object, - Method: nativeschema.MethodPatchObject, - SenderKey: reqInfo.SenderKey, - ContainerOwner: reqInfo.ContainerOwner, - Role: reqInfo.Role, - BearerToken: md.BearerToken, - XHeaders: md.MetaHeader.GetXHeaders(), + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, + Method: nativeschema.MethodPatchObject, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + ContainerAttributes: reqInfo.ContainerAttributes, + Role: reqInfo.Role, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), } if err := p.apeChecker.CheckAPE(ctx, prm); err != nil { @@ -268,16 +271,17 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqInfo.Namespace, - Container: md.Container, - Object: md.Object, - Header: header, - Method: nativeschema.MethodHeadObject, - Role: reqInfo.Role, - SenderKey: reqInfo.SenderKey, - ContainerOwner: reqInfo.ContainerOwner, - BearerToken: md.BearerToken, - XHeaders: md.MetaHeader.GetXHeaders(), + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, + Header: header, + Method: nativeschema.MethodHeadObject, + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + ContainerAttributes: reqInfo.ContainerAttributes, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -296,14 +300,15 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqInfo.Namespace, - Container: md.Container, - Method: nativeschema.MethodSearchObject, - Role: reqInfo.Role, - SenderKey: reqInfo.SenderKey, - ContainerOwner: reqInfo.ContainerOwner, - BearerToken: md.BearerToken, - XHeaders: md.MetaHeader.GetXHeaders(), + Namespace: reqInfo.Namespace, + Container: md.Container, + Method: nativeschema.MethodSearchObject, + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + ContainerAttributes: reqInfo.ContainerAttributes, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -323,15 +328,16 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) ( } err = c.apeChecker.CheckAPE(ctx, Prm{ - Namespace: reqInfo.Namespace, - Container: md.Container, - Object: md.Object, - Method: nativeschema.MethodDeleteObject, - Role: reqInfo.Role, - SenderKey: reqInfo.SenderKey, - ContainerOwner: reqInfo.ContainerOwner, - BearerToken: md.BearerToken, - XHeaders: md.MetaHeader.GetXHeaders(), + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, + Method: nativeschema.MethodDeleteObject, + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + ContainerAttributes: reqInfo.ContainerAttributes, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), }) if err != nil { return nil, toStatusErr(err) @@ -356,15 +362,16 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G } err = c.apeChecker.CheckAPE(stream.Context(), Prm{ - Namespace: reqInfo.Namespace, - Container: md.Container, - Object: md.Object, - Method: nativeschema.MethodRangeObject, - Role: reqInfo.Role, - SenderKey: reqInfo.SenderKey, - ContainerOwner: reqInfo.ContainerOwner, - BearerToken: md.BearerToken, - XHeaders: md.MetaHeader.GetXHeaders(), + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, + Method: nativeschema.MethodRangeObject, + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + ContainerAttributes: reqInfo.ContainerAttributes, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), }) if err != nil { return toStatusErr(err) @@ -384,15 +391,16 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa } prm := Prm{ - Namespace: reqInfo.Namespace, - Container: md.Container, - Object: md.Object, - Method: nativeschema.MethodHashObject, - Role: reqInfo.Role, - SenderKey: reqInfo.SenderKey, - ContainerOwner: reqInfo.ContainerOwner, - BearerToken: md.BearerToken, - XHeaders: md.MetaHeader.GetXHeaders(), + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, + Method: nativeschema.MethodHashObject, + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + ContainerAttributes: reqInfo.ContainerAttributes, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), } resp, err := c.next.GetRangeHash(ctx, request) @@ -417,16 +425,17 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ } prm := Prm{ - Namespace: reqInfo.Namespace, - Container: md.Container, - Object: md.Object, - Header: request.GetBody().GetObject().GetHeader(), - Method: nativeschema.MethodPutObject, - Role: reqInfo.Role, - SenderKey: reqInfo.SenderKey, - ContainerOwner: reqInfo.ContainerOwner, - BearerToken: md.BearerToken, - XHeaders: md.MetaHeader.GetXHeaders(), + Namespace: reqInfo.Namespace, + Container: md.Container, + Object: md.Object, + Header: request.GetBody().GetObject().GetHeader(), + Method: nativeschema.MethodPutObject, + Role: reqInfo.Role, + SenderKey: reqInfo.SenderKey, + ContainerOwner: reqInfo.ContainerOwner, + ContainerAttributes: reqInfo.ContainerAttributes, + BearerToken: md.BearerToken, + XHeaders: md.MetaHeader.GetXHeaders(), } if err = c.apeChecker.CheckAPE(ctx, prm); err != nil { From 86aec1ad6dfd2404a385349d1937fa6af4488780 Mon Sep 17 00:00:00 2001 From: Airat Arifullin Date: Thu, 24 Apr 2025 19:08:30 +0300 Subject: [PATCH 1413/1413] [#1689] container: Make APE middleware form container system attributes * Make `Put` handler extract container attributes from request body and form APE-resource properties; * Make `validateContainerBoundedOperation` used by `Get` and `Delete` handlers extracts attributes from read container. Change-Id: I005345575c3d25b505bae4108f60cd320a7489ba Signed-off-by: Airat Arifullin --- pkg/services/container/ape.go | 29 ++++- pkg/services/container/ape_test.go | 181 +++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 4 deletions(-) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 01bd825d73..3b5dab9aa7 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -280,11 +280,16 @@ func (ac *apeChecker) Put(ctx context.Context, req *container.PutRequest) (*cont return nil, err } + cnrProps, err := getContainerPropsFromV2(req.GetBody().GetContainer()) + if err != nil { + return nil, fmt.Errorf("get container properties: %w", err) + } + request := aperequest.NewRequest( nativeschema.MethodPutContainer, aperequest.NewResource( resourceName(namespace, ""), - make(map[string]string), + cnrProps, ), reqProps, ) @@ -395,7 +400,7 @@ func (ac *apeChecker) validateContainerBoundedOperation(ctx context.Context, con op, aperequest.NewResource( resourceName(namespace, id.EncodeToString()), - ac.getContainerProps(cont), + getContainerProps(cont), ), reqProps, ) @@ -445,10 +450,26 @@ func resourceName(namespace string, container string) string { return fmt.Sprintf(nativeschema.ResourceFormatNamespaceContainer, namespace, container) } -func (ac *apeChecker) getContainerProps(c *containercore.Container) map[string]string { - return map[string]string{ +func getContainerProps(c *containercore.Container) map[string]string { + props := map[string]string{ nativeschema.PropertyKeyContainerOwnerID: c.Value.Owner().EncodeToString(), } + for attrName, attrVal := range c.Value.Attributes() { + name := fmt.Sprintf(nativeschema.PropertyKeyFormatContainerAttribute, attrName) + props[name] = attrVal + } + return props +} + +func getContainerPropsFromV2(cnrV2 *container.Container) (map[string]string, error) { + if cnrV2 == nil { + return nil, errors.New("container is not set") + } + c := cnrSDK.Container{} + if err := c.ReadFromV2(*cnrV2); err != nil { + return nil, err + } + return getContainerProps(&containercore.Container{Value: c}), nil } func (ac *apeChecker) getRequestProps(ctx context.Context, mh *session.RequestMetaHeader, vh *session.RequestVerificationHeader, diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index 77a981d1ab..6438c34ca9 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -54,6 +54,8 @@ func TestAPE(t *testing.T) { t.Run("deny put container with invlaid namespace", testDenyPutContainerInvalidNamespace) t.Run("deny list containers for owner with PK", testDenyListContainersForPK) t.Run("deny list containers by namespace invalidation", testDenyListContainersValidationNamespaceError) + t.Run("deny get by container attribute rules", testDenyGetContainerSysZoneAttr) + t.Run("deny put by container attribute rules", testDenyPutContainerSysZoneAttr) } const ( @@ -564,6 +566,185 @@ func testDenyGetContainerByIP(t *testing.T) { require.Contains(t, errAccessDenied.Reason(), chain.AccessDenied.String()) } +func testDenyGetContainerSysZoneAttr(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + pk, err := keys.NewPrivateKey() + require.NoError(t, err) + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + }, + }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + pk.PublicKey().GetScriptHash(): { + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 19888, + }, + }, + }, + }, + } + + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + testContainer.SetAttribute(container.SysAttributeZone, "eggplant") + contRdr.c[contID] = &containercore.Container{Value: testContainer} + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + _, _, err = router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.ContainerTarget(contID.EncodeToString()), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodGetContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + fmt.Sprintf(nativeschema.ResourceFormatRootContainer, contID.EncodeToString()), + }, + }, + Condition: []chain.Condition{ + { + Kind: chain.KindResource, + Key: fmt.Sprintf(nativeschema.PropertyKeyFormatContainerAttribute, container.SysAttributeZone), + Value: "eggplant", + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := &container.GetRequest{} + req.SetBody(&container.GetRequestBody{}) + var refContID refs.ContainerID + contID.WriteToV2(&refContID) + req.GetBody().SetContainerID(&refContID) + + require.NoError(t, signature.SignServiceMessage(&pk.PrivateKey, req)) + + resp, err := apeSrv.Get(ctxWithPeerInfo(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) + require.Contains(t, errAccessDenied.Reason(), chain.AccessDenied.String()) +} + +func testDenyPutContainerSysZoneAttr(t *testing.T) { + t.Parallel() + srv := &srvStub{ + calls: map[string]int{}, + } + router := inmemory.NewInMemory() + contRdr := &containerStub{ + c: map[cid.ID]*containercore.Container{}, + } + ir := &irStub{ + keys: [][]byte{}, + } + nm := &netmapStub{} + + contID := cidtest.ID() + testContainer := containertest.Container() + pp := netmap.PlacementPolicy{} + require.NoError(t, pp.DecodeString("REP 1")) + testContainer.SetPlacementPolicy(pp) + testContainer.SetAttribute(container.SysAttributeZone, "eggplant") + contRdr.c[contID] = &containercore.Container{Value: testContainer} + owner := testContainer.Owner() + ownerAddr := owner.ScriptHash() + + frostfsIDSubjectReader := &frostfsidStub{ + subjects: map[util.Uint160]*client.Subject{ + ownerAddr: {}, + }, + subjectsExt: map[util.Uint160]*client.SubjectExtended{ + ownerAddr: {}, + }, + } + + apeSrv := NewAPEServer(router, contRdr, ir, nm, frostfsIDSubjectReader, srv) + + nm.currentEpoch = 100 + nm.netmaps = map[uint64]*netmap.NetMap{} + var testNetmap netmap.NetMap + testNetmap.SetEpoch(nm.currentEpoch) + testNetmap.SetNodes([]netmap.NodeInfo{{}}) + nm.netmaps[nm.currentEpoch] = &testNetmap + nm.netmaps[nm.currentEpoch-1] = &testNetmap + + _, _, err := router.MorphRuleChainStorage().AddMorphRuleChain(chain.Ingress, engine.NamespaceTarget(""), &chain.Chain{ + Rules: []chain.Rule{ + { + Status: chain.AccessDenied, + Actions: chain.Actions{ + Names: []string{ + nativeschema.MethodPutContainer, + }, + }, + Resources: chain.Resources{ + Names: []string{ + nativeschema.ResourceFormatRootContainers, + }, + }, + Condition: []chain.Condition{ + { + Kind: chain.KindResource, + Key: fmt.Sprintf(nativeschema.PropertyKeyFormatContainerAttribute, container.SysAttributeZone), + Value: "eggplant", + Op: chain.CondStringEquals, + }, + }, + }, + }, + }) + require.NoError(t, err) + + req := initPutRequest(t, testContainer) + + resp, err := apeSrv.Put(ctxWithPeerInfo(), req) + require.Nil(t, resp) + var errAccessDenied *apistatus.ObjectAccessDenied + require.ErrorAs(t, err, &errAccessDenied) + require.Contains(t, errAccessDenied.Reason(), chain.AccessDenied.String()) +} + func testDenyGetContainerByGroupID(t *testing.T) { t.Parallel() srv := &srvStub{